Add characterSheet and Campaing to the server.
This commit is contained in:
parent
1e5f0d88ae
commit
495768e5fe
53 changed files with 879 additions and 513 deletions
|
|
@ -9,6 +9,8 @@ import com.pixelized.desktop.lwa.parser.expression.ExpressionParser
|
|||
import com.pixelized.desktop.lwa.parser.word.WordParser
|
||||
import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository
|
||||
import com.pixelized.desktop.lwa.repository.alteration.AlterationStore
|
||||
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
|
||||
import com.pixelized.desktop.lwa.repository.campaign.CampaignStore
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetStore
|
||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
||||
|
|
@ -29,8 +31,7 @@ import com.pixelized.desktop.lwa.ui.screen.network.NetworkFactory
|
|||
import com.pixelized.desktop.lwa.ui.screen.network.NetworkViewModel
|
||||
import com.pixelized.desktop.lwa.ui.screen.roll.RollViewModel
|
||||
import com.pixelized.desktop.lwa.ui.screen.rollhistory.RollHistoryViewModel
|
||||
import com.pixelized.shared.lwa.model.campaign.CampaignRepository
|
||||
import com.pixelized.shared.lwa.model.campaign.model.CampaignFactory
|
||||
import com.pixelized.shared.lwa.model.campaign.CampaignJsonFactory
|
||||
import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.HttpClientEngine
|
||||
|
|
@ -78,6 +79,7 @@ val storeDependencies
|
|||
singleOf(::CharacterSheetStore)
|
||||
singleOf(::SettingsStore)
|
||||
singleOf(::AlterationStore)
|
||||
singleOf(::CampaignStore)
|
||||
}
|
||||
|
||||
val repositoryDependencies
|
||||
|
|
@ -97,7 +99,7 @@ val factoryDependencies
|
|||
factoryOf(::NetworkFactory)
|
||||
factoryOf(::SkillFieldFactory)
|
||||
factoryOf(::SettingsFactory)
|
||||
factoryOf(::CampaignFactory)
|
||||
factoryOf(::CampaignJsonFactory)
|
||||
}
|
||||
|
||||
val viewModelDependencies
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ package com.pixelized.desktop.lwa.business
|
|||
import com.pixelized.desktop.lwa.parser.expression.Expression
|
||||
import com.pixelized.desktop.lwa.parser.expression.ExpressionParser
|
||||
import com.pixelized.desktop.lwa.parser.word.Word
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
|
|
@ -32,9 +32,7 @@ class ExpressionUseCase(
|
|||
val bonus = context.evaluate(
|
||||
expression = skill.bonus?.let(expressionParser::parse),
|
||||
)
|
||||
val level = context.evaluate(
|
||||
expression = skill.level?.let(expressionParser::parse),
|
||||
)
|
||||
val level = max((skill.level - 1) * 5, 0)
|
||||
|
||||
return max(base + bonus + level + alterations, 0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,24 +4,24 @@ import com.pixelized.desktop.lwa.parser.expression.Expression
|
|||
import com.pixelized.desktop.lwa.parser.expression.ExpressionParser
|
||||
import com.pixelized.desktop.lwa.repository.alteration.model.Alteration
|
||||
import com.pixelized.desktop.lwa.repository.alteration.model.AlterationMetadata
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CharacteristicId
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CharacteristicId.ARMOR
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CharacteristicId.DEX
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CharacteristicId.HEI
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CharacteristicId.MOV
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CharacteristicId.STR
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CommonSkillId.ACROBATICS_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CommonSkillId.AID_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CommonSkillId.ATHLETICS_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CommonSkillId.BARGAIN_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CommonSkillId.COMBAT_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CommonSkillId.DISCRETION_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CommonSkillId.INTIMIDATION_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CommonSkillId.PERCEPTION_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CommonSkillId.PERSUASION_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CommonSkillId.SLEIGHT_OF_HAND_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CommonSkillId.SPIEL_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CommonSkillId.THROW_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.ARMOR
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.DEX
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.HEI
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.MOV
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.STR
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CommonSkillId.ACROBATICS_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CommonSkillId.AID_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CommonSkillId.ATHLETICS_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CommonSkillId.BARGAIN_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CommonSkillId.COMBAT_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CommonSkillId.DISCRETION_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CommonSkillId.INTIMIDATION_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CommonSkillId.PERCEPTION_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CommonSkillId.PERSUASION_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CommonSkillId.SLEIGHT_OF_HAND_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CommonSkillId.SPIEL_ID
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CommonSkillId.THROW_ID
|
||||
|
||||
class AlterationStore(
|
||||
private val expressionParser: ExpressionParser,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package com.pixelized.desktop.lwa.repository.campaign
|
||||
|
||||
import com.pixelized.shared.lwa.model.campaign.Campaign
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class CampaignRepository(
|
||||
store: CampaignStore,
|
||||
) {
|
||||
private val scope = CoroutineScope(Dispatchers.IO + Job())
|
||||
|
||||
private val campaign = store.campaignFlow()
|
||||
.stateIn(
|
||||
scope = scope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = Campaign.EMPTY,
|
||||
)
|
||||
|
||||
fun campaignFlow(): StateFlow<Campaign> = campaign
|
||||
|
||||
fun characterInstance(id: String): StateFlow<Campaign.CharacterInstance> {
|
||||
return campaign
|
||||
.mapNotNull {
|
||||
it.characters[id]
|
||||
}
|
||||
.stateIn(
|
||||
scope = scope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = campaign.value.characters[id] ?: Campaign.CharacterInstance(
|
||||
characteristic = emptyMap(),
|
||||
usedSkill = emptyList(),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package com.pixelized.desktop.lwa.repository.campaign
|
||||
|
||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
||||
import com.pixelized.shared.lwa.model.campaign.Campaign
|
||||
import com.pixelized.shared.lwa.model.campaign.CampaignJson
|
||||
import com.pixelized.shared.lwa.model.campaign.CampaignJsonFactory
|
||||
import com.pixelized.shared.lwa.protocol.MessageType
|
||||
import com.pixelized.shared.lwa.protocol.payload.UpdatePlayerCharacteristicMessage
|
||||
import com.pixelized.shared.lwa.usecase.CampaignUseCase
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
class CampaignStore(
|
||||
private val network: NetworkRepository,
|
||||
private val factory: CampaignJsonFactory,
|
||||
private val useCase: CampaignUseCase,
|
||||
private val client: HttpClient,
|
||||
private val json: Json,
|
||||
) {
|
||||
private val flow = MutableStateFlow(value = Campaign.EMPTY)
|
||||
|
||||
init {
|
||||
val scope = CoroutineScope(Dispatchers.IO + Job())
|
||||
scope.launch {
|
||||
flow.value = load()
|
||||
}
|
||||
scope.launch {
|
||||
network.data
|
||||
.mapNotNull { it.takeIf { it.type == MessageType.UpdatePlayerCharacteristic } }
|
||||
.map { json.decodeFromString<UpdatePlayerCharacteristicMessage>(it.value) }
|
||||
.collect {
|
||||
updateCharacteristic(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun campaignFlow(): StateFlow<Campaign> = flow
|
||||
|
||||
private suspend fun load(): Campaign {
|
||||
val request: CampaignJson = client
|
||||
.get("http://pixelized.freeboxos.fr:16030/campaign") // TODO
|
||||
.body()
|
||||
val data = factory.convertFromJson(json = request)
|
||||
return data
|
||||
}
|
||||
|
||||
private fun updateCharacteristic(
|
||||
message: UpdatePlayerCharacteristicMessage,
|
||||
) {
|
||||
val characters = flow.value.characters.toMutableMap()
|
||||
val character = characters[message.characterId] ?: Campaign.CharacterInstance(
|
||||
characteristic = emptyMap(),
|
||||
usedSkill = emptyList(),
|
||||
)
|
||||
characters[message.characterId] = useCase.updateCharacteristic(
|
||||
character = character,
|
||||
characteristic = message.characteristic,
|
||||
value = message.value
|
||||
)
|
||||
flow.value = flow.value.copy(characters = characters)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.pixelized.desktop.lwa.repository.characterSheet
|
||||
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
|
|
|
|||
|
|
@ -1,24 +1,31 @@
|
|||
package com.pixelized.desktop.lwa.repository.characterSheet
|
||||
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheetJson
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheetJsonFactory
|
||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJson
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJsonFactory
|
||||
import com.pixelized.shared.lwa.protocol.MessageType
|
||||
import com.pixelized.shared.lwa.protocol.payload.UpdateSkillUsageMessage
|
||||
import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
class CharacterSheetStore(
|
||||
private val network: NetworkRepository,
|
||||
private val factory: CharacterSheetJsonFactory,
|
||||
private val useCase: CharacterSheetUseCase,
|
||||
private val client: HttpClient,
|
||||
private val json: Json,
|
||||
) {
|
||||
private val flow = MutableStateFlow<List<CharacterSheet>>(value = emptyList())
|
||||
|
||||
|
|
@ -27,21 +34,24 @@ class CharacterSheetStore(
|
|||
scope.launch {
|
||||
flow.value = load()
|
||||
}
|
||||
scope.launch {
|
||||
network.data
|
||||
.mapNotNull { it.takeIf { it.type == MessageType.UpdateSkillUsage } }
|
||||
.map { json.decodeFromString<UpdateSkillUsageMessage>(it.value) }
|
||||
.collect {
|
||||
updateCharacterSkillChange(
|
||||
characterId = it.characterId,
|
||||
skillId = it.skillId,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun characterSheetFlow(): StateFlow<List<CharacterSheet>> = flow
|
||||
|
||||
fun save(sheet: CharacterSheet) {
|
||||
|
||||
}
|
||||
|
||||
fun delete(id: String): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
suspend fun load(): List<CharacterSheet> {
|
||||
val request: List<CharacterSheetJson> = client
|
||||
.get("http://pixelized.freeboxos.fr:16030/characters")
|
||||
.get("http://pixelized.freeboxos.fr:16030/characters") // TODO
|
||||
.body()
|
||||
val data = request.map {
|
||||
factory.convertFromJson(json = it)
|
||||
|
|
@ -49,8 +59,19 @@ class CharacterSheetStore(
|
|||
return data
|
||||
}
|
||||
|
||||
sealed class CharacterSheetStoreException(root: Exception) : Exception(root)
|
||||
class JsonConversionException(root: Exception) : CharacterSheetStoreException(root)
|
||||
class FileWriteException(root: Exception) : CharacterSheetStoreException(root)
|
||||
class FileReadException(root: Exception) : CharacterSheetStoreException(root)
|
||||
private fun updateCharacterSkillChange(
|
||||
characterId: String,
|
||||
skillId: String,
|
||||
) {
|
||||
val characters = flow.value.toMutableList()
|
||||
val index = characters.indexOfFirst { it.id == characterId }
|
||||
|
||||
if (index > -1) {
|
||||
characters[index] = useCase.updateSkillUsage(
|
||||
character = characters[index],
|
||||
skillId = skillId,
|
||||
)
|
||||
flow.value = characters
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,10 @@ import com.pixelized.desktop.lwa.utils.extention.encodeToFrame
|
|||
import com.pixelized.shared.lwa.SERVER_PORT
|
||||
import com.pixelized.shared.lwa.protocol.Message
|
||||
import com.pixelized.shared.lwa.protocol.MessageType
|
||||
import com.pixelized.shared.lwa.protocol.payload.MessagePayload
|
||||
import com.pixelized.shared.lwa.protocol.payload.RollMessage
|
||||
import com.pixelized.shared.lwa.protocol.payload.UpdatePlayerCharacteristicMessage
|
||||
import com.pixelized.shared.lwa.protocol.payload.UpdateSkillUsageMessage
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.websocket.Frame
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -19,11 +23,13 @@ import kotlinx.coroutines.flow.SharedFlow
|
|||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
class NetworkRepository(
|
||||
private val settingsRepository: SettingsRepository,
|
||||
private val client: HttpClient,
|
||||
private val json: Json,
|
||||
) {
|
||||
companion object {
|
||||
const val DEFAULT_PORT = SERVER_PORT
|
||||
|
|
@ -88,6 +94,33 @@ class NetworkRepository(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun share(
|
||||
playerName: String = settingsRepository.settings().playerName,
|
||||
payload: MessagePayload,
|
||||
) {
|
||||
if (status.value == Status.CONNECTED) {
|
||||
when (payload) {
|
||||
is RollMessage -> share(
|
||||
playerName = playerName,
|
||||
type = MessageType.Roll,
|
||||
content = json.encodeToString(payload),
|
||||
)
|
||||
|
||||
is UpdateSkillUsageMessage -> share(
|
||||
playerName = playerName,
|
||||
type = MessageType.UpdateSkillUsage,
|
||||
content = json.encodeToString(payload),
|
||||
)
|
||||
|
||||
is UpdatePlayerCharacteristicMessage -> share(
|
||||
playerName = playerName,
|
||||
type = MessageType.UpdatePlayerCharacteristic,
|
||||
content = json.encodeToString(payload),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun share(
|
||||
playerName: String = settingsRepository.settings().playerName,
|
||||
type: MessageType,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.pixelized.desktop.lwa.repository.roll_history
|
|||
|
||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
||||
import com.pixelized.shared.lwa.protocol.MessageType
|
||||
import com.pixelized.shared.lwa.protocol.roll.RollMessage
|
||||
import com.pixelized.shared.lwa.protocol.payload.RollMessage
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
|
|
@ -28,14 +28,6 @@ class RollHistoryRepository(
|
|||
started = SharingStarted.Eagerly,
|
||||
)
|
||||
|
||||
init {
|
||||
scope.launch {
|
||||
network.data.collect {
|
||||
println(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun share(
|
||||
characterId: String,
|
||||
skillLabel: String,
|
||||
|
|
|
|||
|
|
@ -51,13 +51,13 @@ data class CharacterDetailUio(
|
|||
val name: String,
|
||||
val hp: String,
|
||||
val pp: String,
|
||||
val mov: String,
|
||||
)
|
||||
|
||||
@Stable
|
||||
data class CharacterDynDetailUio(
|
||||
val hp: String,
|
||||
val pp: String,
|
||||
val mov: String,
|
||||
)
|
||||
|
||||
@Composable
|
||||
|
|
@ -265,7 +265,7 @@ private fun CharacterHeader(
|
|||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = MaterialTheme.typography.h6,
|
||||
text = dynDetail.value.mov,
|
||||
text = character.mov,
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ import androidx.compose.runtime.remember
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository
|
||||
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||
import com.pixelized.shared.lwa.model.campaign.Campaign.CharacterInstance.Characteristic.Damage
|
||||
import com.pixelized.shared.lwa.model.campaign.Campaign.CharacterInstance.Characteristic.Power
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
|
@ -17,24 +20,27 @@ import kotlinx.coroutines.flow.mapNotNull
|
|||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class CharacterDetailViewModel(
|
||||
private val repository: CharacterSheetRepository,
|
||||
private val alteration: AlterationRepository,
|
||||
private val characterRepository: CharacterSheetRepository,
|
||||
private val campaignRepository: CampaignRepository,
|
||||
private val alterationRepository: AlterationRepository,
|
||||
) : ViewModel() {
|
||||
|
||||
private val displayedCharacterId = MutableStateFlow<String?>(null)
|
||||
|
||||
val detail: StateFlow<CharacterDetailUio?> = combine(
|
||||
displayedCharacterId,
|
||||
repository.characterSheetFlow(),
|
||||
) { id, sheets ->
|
||||
characterRepository.characterSheetFlow(),
|
||||
campaignRepository.campaignFlow(),
|
||||
) { id, sheets, campaign ->
|
||||
val sheet = sheets.firstOrNull { it.id == id }
|
||||
if (sheet == null) return@combine null
|
||||
CharacterDetailUio(
|
||||
id = sheet.id,
|
||||
portrait = sheet.portrait,
|
||||
name = sheet.name,
|
||||
hp = "${sheet.maxHp}",
|
||||
pp = "${sheet.maxPp}",
|
||||
hp = "${sheet.hp - (campaign.characters[id]?.characteristic?.get(Damage) ?: 0)}",
|
||||
pp = "${sheet.pp - (campaign.characters[id]?.characteristic?.get(Power) ?: 0)}",
|
||||
mov = "${sheet.movement}"
|
||||
)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
|
|
@ -46,22 +52,19 @@ class CharacterDetailViewModel(
|
|||
@Stable
|
||||
fun collectDynamicDetailAsState(id: String): State<CharacterDynDetailUio> {
|
||||
val flow = remember(id) {
|
||||
repository.characterSheetFlow(id = id)
|
||||
campaignRepository.characterInstance(id = id)
|
||||
}
|
||||
return remember(id) {
|
||||
flow.mapNotNull { sheet ->
|
||||
if (sheet == null) return@mapNotNull null
|
||||
CharacterDynDetailUio(
|
||||
hp = sheet.currentHp.toString(),
|
||||
pp = sheet.currentPp.toString(),
|
||||
mov = sheet.movement.toString(),
|
||||
hp = sheet.characteristic[Damage].toString(),
|
||||
pp = sheet.characteristic[Power].toString(),
|
||||
)
|
||||
}
|
||||
}.collectAsState(
|
||||
initial = CharacterDynDetailUio(
|
||||
hp = flow.value?.maxHp?.toString() ?: "",
|
||||
pp = flow.value?.maxPp?.toString() ?: "",
|
||||
mov = flow.value?.movement?.toString() ?: "",
|
||||
CharacterDynDetailUio(
|
||||
hp = flow.value.characteristic[Damage].toString(),
|
||||
pp = flow.value.characteristic[Power].toString(),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ import org.jetbrains.compose.resources.painterResource
|
|||
data class PlayerPortraitUio(
|
||||
val id: String,
|
||||
val portrait: String?,
|
||||
val hp: Int,
|
||||
val damage: Int,
|
||||
val maxHp: Int,
|
||||
val pp: Int,
|
||||
val usedPp: Int,
|
||||
val maxPp: Int,
|
||||
)
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ fun PlayerPortrait(
|
|||
Text(
|
||||
modifier = Modifier.padding(bottom = 2.dp),
|
||||
style = MaterialTheme.typography.caption,
|
||||
text = "${character.hp}/${character.maxHp}",
|
||||
text = "${character.maxHp - character.damage}/${character.maxHp}",
|
||||
)
|
||||
}
|
||||
Row(
|
||||
|
|
@ -111,7 +111,7 @@ fun PlayerPortrait(
|
|||
Text(
|
||||
modifier = Modifier.padding(bottom = 2.dp),
|
||||
style = MaterialTheme.typography.caption,
|
||||
text = "${character.pp}/${character.maxPp}",
|
||||
text = "${character.maxPp - character.usedPp}/${character.maxPp}",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,34 +8,42 @@ import androidx.compose.runtime.State
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||
import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
|
||||
import com.pixelized.shared.lwa.model.campaign.character
|
||||
import com.pixelized.shared.lwa.model.campaign.damage
|
||||
import com.pixelized.shared.lwa.model.campaign.power
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class PlayerRibbonViewModel(
|
||||
private val rollHistoryRepository: RollHistoryRepository,
|
||||
characterRepository: CharacterSheetRepository,
|
||||
campaignRepository: CampaignRepository,
|
||||
) : ViewModel() {
|
||||
val characters: StateFlow<List<PlayerPortraitUio>> = characterRepository.characterSheetFlow()
|
||||
.map { sheets ->
|
||||
sheets.map { sheet ->
|
||||
PlayerPortraitUio(
|
||||
id = sheet.id,
|
||||
portrait = sheet.thumbnail,
|
||||
hp = sheet.currentHp,
|
||||
maxHp = sheet.maxHp,
|
||||
pp = sheet.currentPp,
|
||||
maxPp = sheet.maxPp,
|
||||
)
|
||||
}
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = emptyList()
|
||||
)
|
||||
val characters: StateFlow<List<PlayerPortraitUio>> = combine(
|
||||
characterRepository.characterSheetFlow(),
|
||||
campaignRepository.campaignFlow(),
|
||||
) { sheets, campaign ->
|
||||
sheets.map { sheet ->
|
||||
val instance = campaign.character(id = sheet.id)
|
||||
PlayerPortraitUio(
|
||||
id = sheet.id,
|
||||
portrait = sheet.thumbnail,
|
||||
damage = instance.damage,
|
||||
maxHp = sheet.hp,
|
||||
usedPp = instance.power,
|
||||
maxPp = sheet.pp,
|
||||
)
|
||||
}
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = emptyList()
|
||||
)
|
||||
|
||||
private val rolls = hashMapOf<String, MutableState<PlayerPortraitRollUio?>>()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
package com.pixelized.desktop.lwa.ui.screen.characterSheet.detail
|
||||
|
||||
import com.pixelized.desktop.lwa.business.ExpressionUseCase
|
||||
import com.pixelized.desktop.lwa.ui.composable.tooltip.TooltipUio
|
||||
import com.pixelized.desktop.lwa.repository.alteration.model.FieldAlteration
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CharacteristicId
|
||||
import com.pixelized.desktop.lwa.ui.composable.tooltip.TooltipUio
|
||||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic
|
||||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.CharacterSheetPageUio.Node
|
||||
import com.pixelized.shared.lwa.model.campaign.Campaign
|
||||
import com.pixelized.shared.lwa.model.campaign.character
|
||||
import com.pixelized.shared.lwa.model.campaign.damage
|
||||
import com.pixelized.shared.lwa.model.campaign.power
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__cha
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__con
|
||||
|
|
@ -45,7 +49,7 @@ class CharacterSheetFactory(
|
|||
|
||||
suspend fun convertToUio(
|
||||
sheet: CharacterSheet?,
|
||||
diminished: Int,
|
||||
campaign: Campaign,
|
||||
alterations: Map<String, List<FieldAlteration>>,
|
||||
): CharacterSheetPageUio? {
|
||||
if (sheet == null) return null
|
||||
|
|
@ -56,6 +60,10 @@ class CharacterSheetFactory(
|
|||
} ?: 0
|
||||
}
|
||||
|
||||
val maxHp = sheet.hp + alterations[CharacteristicId.HP].sum()
|
||||
val maxPp = sheet.pp + alterations[CharacteristicId.PP].sum()
|
||||
val instance = campaign.character(sheet.id)
|
||||
|
||||
return CharacterSheetPageUio(
|
||||
id = sheet.id,
|
||||
name = sheet.name,
|
||||
|
|
@ -145,7 +153,7 @@ class CharacterSheetFactory(
|
|||
Characteristic(
|
||||
id = CharacteristicId.HP,
|
||||
label = getString(Res.string.character_sheet__sub_characteristics__hit_point),
|
||||
value = "${sheet.currentHp}/${sheet.maxHp + alterations[CharacteristicId.HP].sum()}",
|
||||
value = "${maxHp - instance.damage}/${maxHp}",
|
||||
tooltips = TooltipUio(
|
||||
title = getString(Res.string.character_sheet__sub_characteristics__hit_point),
|
||||
description = getString(Res.string.tooltip__sub_characteristics__hit_point),
|
||||
|
|
@ -155,7 +163,7 @@ class CharacterSheetFactory(
|
|||
Characteristic(
|
||||
id = CharacteristicId.PP,
|
||||
label = getString(Res.string.character_sheet__sub_characteristics__power_point),
|
||||
value = "${sheet.currentPp}/${sheet.maxPp + alterations[CharacteristicId.PP].sum()}",
|
||||
value = "${maxPp - instance.power}/${maxPp}",
|
||||
tooltips = TooltipUio(
|
||||
title = getString(Res.string.character_sheet__sub_characteristics__power_point),
|
||||
description = getString(Res.string.tooltip__sub_characteristics__power_point),
|
||||
|
|
@ -205,6 +213,7 @@ class CharacterSheetFactory(
|
|||
),
|
||||
commonSkills = sheet.commonSkills.map { skill ->
|
||||
Node(
|
||||
id = skill.id,
|
||||
label = skill.label,
|
||||
value = skillUseCase.computeSkillValue(
|
||||
sheet = sheet,
|
||||
|
|
@ -222,6 +231,7 @@ class CharacterSheetFactory(
|
|||
},
|
||||
specialSKills = sheet.specialSkills.map { skill ->
|
||||
Node(
|
||||
id = skill.id,
|
||||
label = skill.label,
|
||||
tooltips = skill.description?.takeIf { it.isNotBlank() }?.let { description ->
|
||||
TooltipUio(
|
||||
|
|
@ -239,6 +249,7 @@ class CharacterSheetFactory(
|
|||
},
|
||||
magicsSkills = sheet.magicSkills.map { skill ->
|
||||
Node(
|
||||
id = skill.id,
|
||||
label = skill.label,
|
||||
tooltips = skill.description?.takeIf { it.isNotBlank() }?.let { description ->
|
||||
TooltipUio(
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ data class CharacterSheetPageUio(
|
|||
|
||||
@Stable
|
||||
data class Node(
|
||||
val id: String,
|
||||
val label: String,
|
||||
val value: Int,
|
||||
val tooltips: TooltipUio? = null,
|
||||
|
|
|
|||
|
|
@ -9,27 +9,40 @@ import androidx.compose.ui.text.input.TextFieldValue
|
|||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.CharacterSheetDestination
|
||||
import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository
|
||||
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
||||
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.CharacterSheetDestination
|
||||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.CharacterSheetDeleteConfirmationDialogUio
|
||||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.DiminishedStatDialogUio
|
||||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.StatChangeDialogUio
|
||||
import com.pixelized.desktop.lwa.utils.extention.collectAsState
|
||||
import com.pixelized.shared.lwa.model.campaign.Campaign.CharacterInstance.Characteristic
|
||||
import com.pixelized.shared.lwa.model.campaign.damage
|
||||
import com.pixelized.shared.lwa.model.campaign.power
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
|
||||
import com.pixelized.shared.lwa.protocol.payload.UpdatePlayerCharacteristicMessage
|
||||
|
||||
import com.pixelized.shared.lwa.protocol.payload.UpdateSkillUsageMessage
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.json.Json
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__diminished__label
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__hit_point
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__power_point
|
||||
import org.jetbrains.compose.resources.getString
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
private typealias CSDCDialogUio = CharacterSheetDeleteConfirmationDialogUio
|
||||
|
||||
class CharacterSheetViewModel(
|
||||
private val repository: CharacterSheetRepository,
|
||||
private val characterRepository: CharacterSheetRepository,
|
||||
private val campaignRepository: CampaignRepository,
|
||||
private val network: NetworkRepository,
|
||||
private val json: Json,
|
||||
private val alteration: AlterationRepository,
|
||||
private val factory: CharacterSheetFactory,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
|
|
@ -49,7 +62,7 @@ class CharacterSheetViewModel(
|
|||
private val _diminishedDialog = mutableStateOf<DiminishedStatDialogUio?>(null)
|
||||
val diminishedDialog: State<DiminishedStatDialogUio?> get() = _diminishedDialog
|
||||
|
||||
private val diminishedValueFlow = repository.characterDiminishedFlow(id = argument.id)
|
||||
private val diminishedValueFlow = characterRepository.characterDiminishedFlow(id = argument.id)
|
||||
val diminishedValue: State<Int?>
|
||||
@Composable
|
||||
get() = diminishedValueFlow.collectAsState { it ->
|
||||
|
|
@ -57,53 +70,46 @@ class CharacterSheetViewModel(
|
|||
}
|
||||
|
||||
private val sheetFlow = combine(
|
||||
repository.characterSheetFlow(id = argument.id),
|
||||
repository.characterDiminishedFlow(id = argument.id),
|
||||
characterRepository.characterSheetFlow(id = argument.id),
|
||||
campaignRepository.campaignFlow(),
|
||||
alteration.alterations(characterId = argument.id),
|
||||
transform = { sheet, diminished, alterations ->
|
||||
factory.convertToUio(sheet = sheet, diminished = diminished, alterations = alterations)
|
||||
transform = { sheet, campaign, alterations ->
|
||||
factory.convertToUio(
|
||||
sheet = sheet,
|
||||
campaign = campaign,
|
||||
alterations = alterations
|
||||
)
|
||||
},
|
||||
).stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = null,
|
||||
)
|
||||
val sheet: State<CharacterSheetPageUio?>
|
||||
@Composable
|
||||
get() = sheetFlow.collectAsState(
|
||||
initial = null,
|
||||
context = viewModelScope.coroutineContext,
|
||||
)
|
||||
get() = sheetFlow.collectAsState()
|
||||
|
||||
fun toggleWolf() {
|
||||
alteration.toggle(argument.id, "65e37d32-3031-4bf8-9369-d2c45d2efac0")
|
||||
}
|
||||
|
||||
fun deleteCharacter(id: String) {
|
||||
repository.delete(id = id)
|
||||
characterRepository.delete(id = id)
|
||||
}
|
||||
|
||||
fun onUseSkill(skill: CharacterSheetPageUio.Node) {
|
||||
repository.characterSheetFlow(id = argument.id).value?.let { sheet ->
|
||||
|
||||
val skills = sheet.commonSkills.map {
|
||||
if (it.label == skill.label) it.copy(used = it.used.not()) else it
|
||||
}
|
||||
val occupations = sheet.specialSkills.map {
|
||||
if (it.label == skill.label) it.copy(used = it.used.not()) else it
|
||||
}
|
||||
val magics = sheet.magicSkills.map {
|
||||
if (it.label == skill.label) it.copy(used = it.used.not()) else it
|
||||
}
|
||||
|
||||
repository.save(
|
||||
characterSheet = sheet.copy(
|
||||
commonSkills = skills,
|
||||
specialSkills = occupations,
|
||||
magicSkills = magics,
|
||||
viewModelScope.launch {
|
||||
network.share(
|
||||
payload = UpdateSkillUsageMessage(
|
||||
characterId = argument.id,
|
||||
skillId = skill.id,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun showConfirmCharacterDeletionDialog() {
|
||||
repository.characterSheetFlow(id = argument.id).value?.let { sheet ->
|
||||
characterRepository.characterSheetFlow(id = argument.id).value?.let { sheet ->
|
||||
_displayDeleteConfirmationDialog.value = CharacterSheetDeleteConfirmationDialogUio(
|
||||
id = sheet.id,
|
||||
name = sheet.name,
|
||||
|
|
@ -116,35 +122,36 @@ class CharacterSheetViewModel(
|
|||
}
|
||||
|
||||
suspend fun showSubCharacteristicDialog(id: String) {
|
||||
repository.characterSheetFlow(id = argument.id).value?.let { sheet ->
|
||||
characterRepository.characterSheetFlow(id = argument.id).value?.let { sheet ->
|
||||
val instance = campaignRepository.characterInstance(id = argument.id).value
|
||||
_statChangeDialog.value = when (id) {
|
||||
CharacterSheet.CharacteristicId.HP -> {
|
||||
val value = mutableStateOf(
|
||||
"${sheet.currentHp}".let {
|
||||
"${sheet.hp - instance.damage}".let {
|
||||
TextFieldValue(text = it, selection = TextRange(it.length))
|
||||
}
|
||||
)
|
||||
StatChangeDialogUio(
|
||||
id = CharacterSheet.CharacteristicId.HP,
|
||||
id = Characteristic.Damage,
|
||||
label = getString(resource = Res.string.character_sheet_edit__sub_characteristics__hit_point),
|
||||
value = { value.value },
|
||||
onValueChange = { value.value = it },
|
||||
maxValue = "${sheet.maxHp}",
|
||||
maxValue = "${sheet.hp}",
|
||||
)
|
||||
}
|
||||
|
||||
CharacterSheet.CharacteristicId.PP -> {
|
||||
val value = mutableStateOf(
|
||||
"${sheet.currentPp}".let {
|
||||
"${sheet.power - instance.power}".let {
|
||||
TextFieldValue(text = it, selection = TextRange(it.length))
|
||||
}
|
||||
)
|
||||
StatChangeDialogUio(
|
||||
id = CharacterSheet.CharacteristicId.PP,
|
||||
id = Characteristic.Power,
|
||||
label = getString(resource = Res.string.character_sheet_edit__sub_characteristics__power_point),
|
||||
value = { value.value },
|
||||
onValueChange = { value.value = it },
|
||||
maxValue = "${sheet.maxPp}",
|
||||
maxValue = "${sheet.power}",
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -158,29 +165,24 @@ class CharacterSheetViewModel(
|
|||
}
|
||||
|
||||
fun changeSubCharacteristic(
|
||||
characteristicId: String,
|
||||
characteristicId: Characteristic,
|
||||
value: Int,
|
||||
) {
|
||||
val sheet = repository.characterSheetFlow(id = argument.id).value
|
||||
val updated = when (characteristicId) {
|
||||
CharacterSheet.CharacteristicId.HP -> sheet?.copy(
|
||||
currentHp = max(
|
||||
0,
|
||||
min(sheet.maxHp, value)
|
||||
viewModelScope.launch {
|
||||
val sheet = characterRepository.characterSheetFlow(id = argument.id).value
|
||||
if (sheet != null) {
|
||||
network.share(
|
||||
payload = UpdatePlayerCharacteristicMessage(
|
||||
characterId = argument.id,
|
||||
characteristic = characteristicId,
|
||||
value = when (characteristicId) {
|
||||
Characteristic.Damage -> sheet.hp - value
|
||||
Characteristic.Power -> sheet.pp - value
|
||||
else -> sheet.movement - value
|
||||
},
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
CharacterSheet.CharacteristicId.PP -> sheet?.copy(
|
||||
currentPp = max(
|
||||
0,
|
||||
min(sheet.maxPp, value)
|
||||
)
|
||||
)
|
||||
|
||||
else -> null
|
||||
}
|
||||
updated?.let {
|
||||
repository.save(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +195,7 @@ class CharacterSheetViewModel(
|
|||
}
|
||||
|
||||
suspend fun showDiminishedDialog() {
|
||||
val diminished = repository.characterDiminishedFlow(id = argument.id).value
|
||||
val diminished = characterRepository.characterDiminishedFlow(id = argument.id).value
|
||||
val textFieldValue =
|
||||
mutableStateOf(TextFieldValue("$diminished", selection = TextRange(index = 0)))
|
||||
_diminishedDialog.value = DiminishedStatDialogUio(
|
||||
|
|
@ -215,7 +217,7 @@ class CharacterSheetViewModel(
|
|||
|
||||
fun changeDiminished(dialog: DiminishedStatDialogUio) {
|
||||
val value = dialog.value().text.toIntOrNull() ?: 0
|
||||
repository.setDiminishedForCharacter(
|
||||
characterRepository.setDiminishedForCharacter(
|
||||
id = dialog.id,
|
||||
diminished = value,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import androidx.compose.ui.text.input.TextFieldValue
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.desktop.lwa.ui.composable.decoratedBox.DecoratedBox
|
||||
import com.pixelized.shared.lwa.model.campaign.Campaign
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.dialog__cancel_action
|
||||
import lwacharactersheet.composeapp.generated.resources.dialog__confirm_action
|
||||
|
|
@ -49,7 +50,7 @@ import org.jetbrains.compose.resources.stringResource
|
|||
|
||||
@Stable
|
||||
data class StatChangeDialogUio(
|
||||
val id: String,
|
||||
val id: Campaign.CharacterInstance.Characteristic,
|
||||
val label: String,
|
||||
val value: () -> TextFieldValue,
|
||||
val onValueChange: (TextFieldValue) -> Unit,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.preview
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.remember
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet.CharacteristicId
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId
|
||||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.CharacterSheetPageUio
|
||||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import com.pixelized.desktop.lwa.ui.screen.characterSheet.edit.common.occupation
|
|||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.edit.composable.ActionFieldUio
|
||||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.edit.composable.BaseSkillFieldUio
|
||||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.edit.composable.SimpleFieldUio
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
|
||||
import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__actions__action_label
|
||||
|
|
@ -41,13 +41,6 @@ import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sk
|
|||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__special_title
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__spiel
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__throw
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__armor
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__damage_bonus
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__hp_grow
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__learning
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__max_hit_point
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__max_power_point
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__movement
|
||||
import org.jetbrains.compose.resources.getString
|
||||
import java.util.UUID
|
||||
import kotlin.math.max
|
||||
|
|
@ -60,56 +53,57 @@ class CharacterSheetEditFactory(
|
|||
currentSheet: CharacterSheet?,
|
||||
editedSheet: CharacterSheetEditPageUio,
|
||||
): CharacterSheet {
|
||||
val editedMaxHp = editedSheet.maxHp.unpack()?.toIntOrNull() ?: currentSheet?.maxHp ?: 0
|
||||
val editedMaxPp = editedSheet.maxPp.unpack()?.toIntOrNull() ?: currentSheet?.maxPp ?: 0
|
||||
|
||||
val level = currentSheet?.level ?: 1
|
||||
val strength = editedSheet.strength.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.strength
|
||||
?: 0
|
||||
val dexterity = editedSheet.dexterity.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.dexterity
|
||||
?: 0
|
||||
val constitution = editedSheet.constitution.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.constitution
|
||||
?: 0
|
||||
val height = editedSheet.height.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.height
|
||||
?: 0
|
||||
val intelligence = editedSheet.intelligence.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.intelligence
|
||||
?: 0
|
||||
val power = editedSheet.power.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.power
|
||||
?: 0
|
||||
val charisma = editedSheet.charisma.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.charisma
|
||||
?: 0
|
||||
|
||||
return CharacterSheet(
|
||||
id = editedSheet.id,
|
||||
name = editedSheet.name.value.value,
|
||||
portrait = currentSheet?.portrait,
|
||||
thumbnail = currentSheet?.thumbnail,
|
||||
strength = editedSheet.strength.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.strength
|
||||
?: 0,
|
||||
dexterity = editedSheet.dexterity.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.dexterity
|
||||
?: 0,
|
||||
constitution = editedSheet.constitution.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.constitution
|
||||
?: 0,
|
||||
height = editedSheet.height.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.height
|
||||
?: 0,
|
||||
intelligence = editedSheet.intelligence.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.intelligence
|
||||
?: 0,
|
||||
power = editedSheet.power.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.power
|
||||
?: 0,
|
||||
charisma = editedSheet.charisma.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.charisma
|
||||
?: 0,
|
||||
overrideMovement = editedSheet.movement.value.value.value.isNotBlank(),
|
||||
movement = editedSheet.movement.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.movement
|
||||
?: 10,
|
||||
overrideMaxHp = editedSheet.maxHp.value.value.value.isNotBlank(),
|
||||
maxHp = editedMaxHp,
|
||||
currentHp = currentSheet?.currentHp?.coerceAtMost(editedMaxHp) ?: editedMaxHp,
|
||||
overrideMaxPP = editedSheet.maxPp.value.value.value.isNotBlank(),
|
||||
maxPp = editedMaxPp,
|
||||
currentPp = currentSheet?.currentPp?.coerceAtMost(editedMaxPp) ?: editedMaxPp,
|
||||
overrideDamageBonus = editedSheet.damageBonus.value.value.value.isNotBlank(),
|
||||
damageBonus = editedSheet.damageBonus.unpack()
|
||||
?: currentSheet?.damageBonus
|
||||
?: "",
|
||||
overrideArmor = editedSheet.armor.value.value.value.isNotBlank(),
|
||||
armor = editedSheet.armor.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.armor
|
||||
?: 0,
|
||||
overrideLearning = editedSheet.learning.value.value.value.isNotBlank(),
|
||||
learning = editedSheet.learning.unpack()?.toIntOrNull() ?: 0,
|
||||
overrideHpGrow = editedSheet.hpGrow.value.value.value.isNotBlank(),
|
||||
hpGrow = editedSheet.hpGrow.unpack()?.toIntOrNull() ?: 0,
|
||||
level = level,
|
||||
strength = strength,
|
||||
dexterity = dexterity,
|
||||
constitution = constitution,
|
||||
height = height,
|
||||
intelligence = intelligence,
|
||||
power = power,
|
||||
charisma = charisma,
|
||||
hp = characterSheetUseCase.defaultMaxHp(
|
||||
constitution = constitution,
|
||||
height = height,
|
||||
level = level
|
||||
),
|
||||
pp = characterSheetUseCase.defaultMaxPower(power = power),
|
||||
movement = characterSheetUseCase.defaultMovement(),
|
||||
damageBonus = characterSheetUseCase.defaultDamageBonus(
|
||||
strength = strength,
|
||||
height = height
|
||||
),
|
||||
armor = characterSheetUseCase.defaultArmor(),
|
||||
learning = characterSheetUseCase.defaultLearning(intelligence = intelligence),
|
||||
hpGrow = characterSheetUseCase.defaultHpGrow(constitution = constitution),
|
||||
commonSkills = editedSheet.commonSkills.map { editedSkill ->
|
||||
val currentSkill = currentSheet?.commonSkills?.firstOrNull {
|
||||
it.id == editedSkill.id
|
||||
|
|
@ -120,7 +114,7 @@ class CharacterSheetEditFactory(
|
|||
description = currentSkill?.description,
|
||||
base = "${editedSkill.base.value}",
|
||||
bonus = editedSkill.bonus.value.value.takeIf { it.isNotBlank() },
|
||||
level = editedSkill.level.value.value.takeIf { it.isNotBlank() },
|
||||
level = editedSkill.level.value.value.toIntOrNull() ?: 0,
|
||||
occupation = editedSkill.option.checked.value,
|
||||
used = currentSkill?.used ?: false,
|
||||
)
|
||||
|
|
@ -135,7 +129,7 @@ class CharacterSheetEditFactory(
|
|||
description = editedSkill.description.value.value,
|
||||
base = editedSkill.base.value.value,
|
||||
bonus = editedSkill.bonus.value.value.takeIf { it.isNotBlank() },
|
||||
level = editedSkill.level.value.value.takeIf { it.isNotBlank() },
|
||||
level = editedSkill.level.value.value.toIntOrNull() ?: 0,
|
||||
occupation = editedSkill.options.occupation,
|
||||
used = currentSkill?.used ?: false,
|
||||
)
|
||||
|
|
@ -150,7 +144,7 @@ class CharacterSheetEditFactory(
|
|||
description = editedSkill.description.value.value,
|
||||
base = editedSkill.base.value.value,
|
||||
bonus = editedSkill.bonus.value.value.takeIf { it.isNotBlank() },
|
||||
level = editedSkill.level.value.value.takeIf { it.isNotBlank() },
|
||||
level = editedSkill.level.value.value.toIntOrNull() ?: 0,
|
||||
occupation = editedSkill.options.occupation,
|
||||
used = currentSkill?.used ?: false,
|
||||
)
|
||||
|
|
@ -159,6 +153,8 @@ class CharacterSheetEditFactory(
|
|||
CharacterSheet.Roll(
|
||||
id = it.id,
|
||||
label = it.label.value.value,
|
||||
description = null, // TODO
|
||||
canBeCritical = false, // TODO
|
||||
roll = it.action.value.value,
|
||||
)
|
||||
},
|
||||
|
|
@ -244,77 +240,6 @@ class CharacterSheetEditFactory(
|
|||
intelligence = int,
|
||||
power = pow,
|
||||
charisma = cha,
|
||||
movement = SimpleFieldUio(
|
||||
label = getString(Res.string.character_sheet_edit__sub_characteristics__movement),
|
||||
value = skillFieldFactory.createWrapper(
|
||||
value = if (sheet?.overrideMovement == true) "${sheet.movement}" else "",
|
||||
placeholder = derivedStateOf {
|
||||
"${characterSheetUseCase.defaultMovement()}"
|
||||
},
|
||||
)
|
||||
),
|
||||
maxHp = SimpleFieldUio(
|
||||
label = getString(Res.string.character_sheet_edit__sub_characteristics__max_hit_point),
|
||||
value = skillFieldFactory.createWrapper(
|
||||
value = if (sheet?.overrideMaxHp == true) "${sheet.maxHp}" else "",
|
||||
placeholder = derivedStateOf {
|
||||
"${
|
||||
characterSheetUseCase.defaultMaxHp(
|
||||
constitution = con(),
|
||||
height = hei()
|
||||
)
|
||||
}"
|
||||
},
|
||||
)
|
||||
),
|
||||
maxPp = SimpleFieldUio(
|
||||
label = getString(Res.string.character_sheet_edit__sub_characteristics__max_power_point),
|
||||
value = skillFieldFactory.createWrapper(
|
||||
value = if (sheet?.overrideMaxPP == true) "${sheet.maxPp}" else "",
|
||||
placeholder = derivedStateOf {
|
||||
"${characterSheetUseCase.defaultMaxPower(power = pow())}"
|
||||
},
|
||||
)
|
||||
),
|
||||
damageBonus = SimpleFieldUio(
|
||||
label = getString(Res.string.character_sheet_edit__sub_characteristics__damage_bonus),
|
||||
value = skillFieldFactory.createWrapper(
|
||||
value = if (sheet?.overrideDamageBonus == true) sheet.damageBonus else "",
|
||||
placeholder = derivedStateOf {
|
||||
characterSheetUseCase.defaultDamageBonus(
|
||||
strength = str(),
|
||||
height = hei()
|
||||
)
|
||||
},
|
||||
)
|
||||
),
|
||||
armor = SimpleFieldUio(
|
||||
label = getString(Res.string.character_sheet_edit__sub_characteristics__armor),
|
||||
value = skillFieldFactory.createWrapper(
|
||||
value = if (sheet?.overrideArmor == true) "${sheet.armor}" else "",
|
||||
placeholder = derivedStateOf {
|
||||
"${characterSheetUseCase.defaultArmor()}"
|
||||
},
|
||||
)
|
||||
),
|
||||
learning = SimpleFieldUio(
|
||||
label = getString(Res.string.character_sheet_edit__sub_characteristics__learning),
|
||||
value = skillFieldFactory.createWrapper(
|
||||
value = if (sheet?.overrideLearning == true) "${sheet.learning}" else "",
|
||||
placeholder = derivedStateOf {
|
||||
"${characterSheetUseCase.defaultLearning(intelligence = int())}"
|
||||
},
|
||||
)
|
||||
),
|
||||
hpGrow = SimpleFieldUio(
|
||||
label = getString(Res.string.character_sheet_edit__sub_characteristics__hp_grow),
|
||||
value = skillFieldFactory.createWrapper(
|
||||
value = if (sheet?.overrideHpGrow == true) "${sheet.hpGrow}" else "",
|
||||
placeholder = derivedStateOf {
|
||||
"${characterSheetUseCase.defaultHpGrow(constitution = con())}"
|
||||
},
|
||||
)
|
||||
),
|
||||
commonSkills = listOf(
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
|
|
@ -421,7 +346,7 @@ class CharacterSheetEditFactory(
|
|||
labelValue = skill.label,
|
||||
baseValue = skill.base,
|
||||
bonusValue = skill.bonus ?: "",
|
||||
levelValue = skill.level ?: "",
|
||||
levelValue = skill.level.takeIf { it > 0 }?.toString() ?: "",
|
||||
options = run {
|
||||
val current = sheet.specialSkills.firstOrNull { it.id == skill.id }
|
||||
listOf(
|
||||
|
|
@ -439,7 +364,7 @@ class CharacterSheetEditFactory(
|
|||
labelValue = skill.label,
|
||||
baseValue = skill.base,
|
||||
bonusValue = skill.bonus ?: "",
|
||||
levelValue = skill.level ?: "",
|
||||
levelValue = skill.level.takeIf { it > 0 }?.toString() ?: "",
|
||||
options = run {
|
||||
val current = sheet.magicSkills.firstOrNull { it.id == skill.id }
|
||||
listOf(
|
||||
|
|
@ -487,7 +412,7 @@ class CharacterSheetEditFactory(
|
|||
),
|
||||
level = skillFieldFactory.createWrapper(
|
||||
label = mutableStateOf(getString(Res.string.character_sheet_edit__skills__level_label)),
|
||||
value = skill?.level ?: "",
|
||||
value = skill?.level?.takeIf { it > 0 }?.toString() ?: "",
|
||||
),
|
||||
option = skillFieldFactory.occupationOption(skill?.occupation ?: false),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -67,13 +67,6 @@ data class CharacterSheetEditPageUio(
|
|||
val intelligence: SimpleFieldUio,
|
||||
val power: SimpleFieldUio,
|
||||
val charisma: SimpleFieldUio,
|
||||
val movement: SimpleFieldUio,
|
||||
val maxHp: SimpleFieldUio,
|
||||
val maxPp: SimpleFieldUio,
|
||||
val damageBonus: SimpleFieldUio,
|
||||
val armor: SimpleFieldUio,
|
||||
val learning: SimpleFieldUio,
|
||||
val hpGrow: SimpleFieldUio,
|
||||
val commonSkills: List<BaseSkillFieldUio>,
|
||||
val specialSkills: List<SkillFieldUio>,
|
||||
val magicSkills: List<SkillFieldUio>,
|
||||
|
|
@ -89,17 +82,6 @@ data class CharacterSheetEditPageUio(
|
|||
power,
|
||||
charisma,
|
||||
)
|
||||
|
||||
val subCharacteristics
|
||||
get() = listOf(
|
||||
movement,
|
||||
maxHp,
|
||||
maxPp,
|
||||
damageBonus,
|
||||
armor,
|
||||
learning,
|
||||
hpGrow,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -215,27 +197,6 @@ fun CharacterSheetEdit(
|
|||
}
|
||||
}
|
||||
}
|
||||
DecoratedBox(
|
||||
modifier = Modifier.weight(weight = 1f),
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(vertical = 8.dp),
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
style = MaterialTheme.typography.caption,
|
||||
text = stringResource(Res.string.character_sheet_edit__sub_characteristics__title),
|
||||
)
|
||||
form.subCharacteristics.forEach {
|
||||
SimpleField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
field = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DecoratedBox(
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetReposit
|
|||
import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
|
||||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.CharacterSheetPageUio
|
||||
import com.pixelized.desktop.lwa.ui.screen.roll.DifficultyUio.Difficulty
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import androidx.lifecycle.ViewModel
|
|||
import androidx.lifecycle.viewModelScope
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||
import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
|
||||
import com.pixelized.shared.lwa.model.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue