Add support for Hp grow bonus and Leaning bonus.
This commit is contained in:
parent
3419afbe59
commit
ca20078ffa
18 changed files with 526 additions and 402 deletions
|
|
@ -42,6 +42,8 @@
|
|||
<string name="character_sheet_edit__sub_characteristics__power_point">Points de pouvoir</string>
|
||||
<string name="character_sheet_edit__sub_characteristics__damage_bonus">Bonus aux dégats</string>
|
||||
<string name="character_sheet_edit__sub_characteristics__armor">Armure</string>
|
||||
<string name="character_sheet_edit__sub_characteristics__learning">Bonus d'apprentissage</string>
|
||||
<string name="character_sheet_edit__sub_characteristics__hp_grow">Bonus de PV</string>
|
||||
<string name="character_sheet_edit__skills__common_title">Compétences communes</string>
|
||||
<string name="character_sheet_edit__skills__special_title">Compétences spéciales</string>
|
||||
<string name="character_sheet_edit__skills__special_action">Ajouter une compétence spéciale</string>
|
||||
|
|
@ -94,6 +96,8 @@
|
|||
<string name="character_sheet__sub_characteristics__power_point">Points de pouvoir</string>
|
||||
<string name="character_sheet__sub_characteristics__damage_bonus">Bonus aux dégats</string>
|
||||
<string name="character_sheet__sub_characteristics__armor">Armure</string>
|
||||
<string name="character_sheet__sub_characteristics__learning">Bonus d'apprentissage</string>
|
||||
<string name="character_sheet__sub_characteristics__hp_grow">Bonus de PV</string>
|
||||
<string name="character_sheet__skills__common_title">Compétences communes</string>
|
||||
<string name="character_sheet__skills__special_title">Compétences spéciales</string>
|
||||
<string name="character_sheet__skills__magic_title">Compétences magiques</string>
|
||||
|
|
@ -113,7 +117,8 @@
|
|||
<string name="tooltip__sub_characteristics__power_point">les points de pouvoir sont égaux au POU et sont dépensés pour utiliser la magie ou d’autres pouvoirs. Tous les points de pouvoir régénèrent naturellement après une nuit de repos.</string>
|
||||
<string name="tooltip__sub_characteristics__bonus_damage">Les personnages plus massifs ou plus forts infligent plus de dégâts quand ils frappent leurs ennemis en combat au corps à corps. Le modificateur s’applique aux dégâts infligés par toute attaque portée par les personnages avec des armes de mêlée (BDC). La moitié de ce bonus s'applique aux attaques de lancer (BDD).</string>
|
||||
<string name="tooltip__sub_characteristics__armor">Une armure protège son porteur des blessures. Lorsqu’un personnage est touché en combat par une attaque non magique, soustrayez les points d’armure aux points de dégâts infligés. Les dommages au-delà de la protection de l’armure surpassent celle-ci et sont infligés au personnage, réduisant ses points de vie actuels.</string>
|
||||
|
||||
<string name="tooltip__sub_characteristics__learning">Plus un personnage est intelligent, plus il assimile rapidement les connaissances et plus il digère son expérience efficacement. Ce modificateur s'applique au score des compétences nouvellement acquises et aux jets d'expériences. Il est égal à (INT - 10) x 2 avec une valeur minimale de zéro.</string>
|
||||
<string name="tooltip__sub_characteristics__hp_grow">Plus un personnage est de bonne constitution, plus son corps se renforce rapidement. Ce modificateur indique le nombre de "PV" maximum que le personnage gagne à chaque progression. Il est égal à CON / 3, arrondi à l'inférieur.</string>
|
||||
<string name="tooltip__skills__combat">Attaque en combat à mains nues. Une attaque réussie inflige 1D3 + BDGT.</string>
|
||||
<string name="tooltip__skills__dodge">Éviter une attaque, un projectile, etc.</string>
|
||||
<string name="tooltip__skills__grab">Maitriser/immobiliser un adversaire.</string>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
package com.pixelized.desktop.lwa
|
||||
|
||||
import com.pixelized.desktop.lwa.business.DamageBonusUseCase
|
||||
import com.pixelized.desktop.lwa.business.CharacterSheetUseCase
|
||||
import com.pixelized.desktop.lwa.business.RollUseCase
|
||||
import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase
|
||||
import com.pixelized.desktop.lwa.business.SkillStepUseCase
|
||||
import com.pixelized.desktop.lwa.business.SkillValueComputationUseCase
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
|
||||
|
|
@ -71,9 +70,8 @@ val parserDependencies
|
|||
|
||||
val useCaseDependencies
|
||||
get() = module {
|
||||
factoryOf(::DamageBonusUseCase)
|
||||
factoryOf(::SkillStepUseCase)
|
||||
factoryOf(::SkillNormalizerUseCase)
|
||||
factoryOf(::RollUseCase)
|
||||
factoryOf(::SkillValueComputationUseCase)
|
||||
factoryOf(::CharacterSheetUseCase)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
package com.pixelized.desktop.lwa.business
|
||||
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.max
|
||||
|
||||
class CharacterSheetUseCase {
|
||||
|
||||
fun normalize(value: Int): Int {
|
||||
return value - value % 5 // (truncate(value.toFloat() / 5f) * 5f).toInt()
|
||||
}
|
||||
|
||||
fun defaultMovement(): Int = 10
|
||||
|
||||
fun defaultMaxHp(
|
||||
constitution: Int,
|
||||
height: Int,
|
||||
): Int {
|
||||
return (ceil((constitution + height) / 2f).toInt())
|
||||
}
|
||||
|
||||
fun defaultMaxPower(
|
||||
power: Int,
|
||||
): Int {
|
||||
return power
|
||||
}
|
||||
|
||||
fun defaultDamageBonus(
|
||||
strength: Int,
|
||||
height: Int,
|
||||
): String {
|
||||
return defaultDamageBonus(sum = strength + height)
|
||||
}
|
||||
|
||||
fun defaultDamageBonus(
|
||||
sum: Int,
|
||||
): String {
|
||||
return when {
|
||||
sum < 12 -> "-1d6"
|
||||
sum in 12..17 -> "-1d4"
|
||||
sum in 18..22 -> "+0"
|
||||
sum in 23..29 -> "+1d4"
|
||||
sum in 30..39 -> "+1d6"
|
||||
else -> "+2d6"
|
||||
}
|
||||
}
|
||||
|
||||
fun defaultArmor(): Int = 0
|
||||
|
||||
fun defaultLearning(intelligence: Int): Int {
|
||||
return max(0, (intelligence - 10) * 2)
|
||||
}
|
||||
|
||||
fun defaultHpGrow(constitution: Int): Int {
|
||||
return (constitution / 3)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
package com.pixelized.desktop.lwa.business
|
||||
|
||||
class DamageBonusUseCase {
|
||||
|
||||
fun bonusDamage(strength: Int, height: Int): String {
|
||||
return bonusDamage(stat = strength + height)
|
||||
}
|
||||
|
||||
fun bonusDamage(stat: Int): String {
|
||||
return when {
|
||||
stat < 12 -> "-1d6"
|
||||
stat in 12..17 -> "-1d4"
|
||||
stat in 18..22 -> "+0"
|
||||
stat in 23..29 -> "+1d4"
|
||||
stat in 30..39 -> "+1d6"
|
||||
else -> "+2d6"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,10 +7,6 @@ import kotlin.math.min
|
|||
|
||||
class RollUseCase {
|
||||
|
||||
fun rollD100(): Int {
|
||||
return roll(modifier = null, quantity = 1, faces = 100)
|
||||
}
|
||||
|
||||
fun roll(dice: Instruction.Dice): Int {
|
||||
return roll(
|
||||
modifier = dice.modifier,
|
||||
|
|
@ -19,9 +15,13 @@ class RollUseCase {
|
|||
)
|
||||
}
|
||||
|
||||
fun roll(modifier: Instruction.Dice.Modifier?, quantity: Int, faces: Int): Int {
|
||||
fun roll(
|
||||
modifier: Instruction.Dice.Modifier? = null,
|
||||
quantity: Int = 1,
|
||||
faces: Int,
|
||||
): Int {
|
||||
print("{")
|
||||
return sum(count = quantity) {
|
||||
return sum(count = quantity) { left ->
|
||||
when (modifier) {
|
||||
Instruction.Dice.Modifier.ADVANTAGE -> {
|
||||
val roll1 = roll(faces = faces)
|
||||
|
|
@ -54,6 +54,8 @@ class RollUseCase {
|
|||
null -> {
|
||||
roll(faces = faces).also { print("$it") }
|
||||
}
|
||||
}.also {
|
||||
if (quantity > 1 && left != 1) print(",")
|
||||
}
|
||||
}.also {
|
||||
print("}:")
|
||||
|
|
@ -61,14 +63,14 @@ class RollUseCase {
|
|||
}
|
||||
|
||||
private fun roll(faces: Int): Int {
|
||||
return (Math.random() * faces.toDouble() + 1).toInt()
|
||||
return (Math.random() * faces.toDouble() + 1.0).toInt()
|
||||
}
|
||||
|
||||
private fun sum(count: Int, block: () -> Int): Int {
|
||||
private fun sum(count: Int, block: (Int) -> Int): Int {
|
||||
return if (count > 1) {
|
||||
block() + sum(count - 1, block)
|
||||
block(count) + sum(count - 1, block)
|
||||
} else {
|
||||
block()
|
||||
block(count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
package com.pixelized.desktop.lwa.business
|
||||
|
||||
import kotlin.math.truncate
|
||||
|
||||
class SkillNormalizerUseCase {
|
||||
fun normalize(value: Int): Int {
|
||||
return (truncate(value.toFloat() / 5f) * 5f).toInt()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
package com.pixelized.desktop.lwa.parser.arithmetic
|
||||
|
||||
sealed class Instruction(
|
||||
val sign: Int,
|
||||
) {
|
||||
class Dice(
|
||||
sign: Int,
|
||||
sealed class Instruction {
|
||||
abstract val sign: Int
|
||||
|
||||
data class Dice(
|
||||
override val sign: Int,
|
||||
val modifier: Modifier?,
|
||||
val quantity: Int,
|
||||
val faces: Int,
|
||||
) : Instruction(
|
||||
sign = sign,
|
||||
) {
|
||||
) : Instruction() {
|
||||
|
||||
enum class Modifier {
|
||||
ADVANTAGE,
|
||||
DISADVANTAGE,
|
||||
|
|
@ -29,23 +28,20 @@ sealed class Instruction(
|
|||
}
|
||||
}
|
||||
|
||||
class Flat(
|
||||
sign: Int,
|
||||
data class Flat(
|
||||
override val sign: Int,
|
||||
val value: Int,
|
||||
) : Instruction(
|
||||
sign = sign,
|
||||
) {
|
||||
) : Instruction() {
|
||||
override fun toString(): String {
|
||||
return "${sign.sign}${value}"
|
||||
}
|
||||
}
|
||||
|
||||
class Word(
|
||||
sign: Int,
|
||||
data class Word(
|
||||
override val sign: Int,
|
||||
val type: Type,
|
||||
) : Instruction(
|
||||
sign = sign
|
||||
) {
|
||||
) : Instruction() {
|
||||
|
||||
enum class Type {
|
||||
BDC, // Damages bonus for melee
|
||||
BDD, // Damages bonus for range
|
||||
|
|
|
|||
|
|
@ -1,34 +1,13 @@
|
|||
package com.pixelized.desktop.lwa.repository.characterSheet
|
||||
|
||||
import com.pixelized.desktop.lwa.business.DamageBonusUseCase
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
|
||||
import com.pixelized.desktop.lwa.business.CharacterSheetUseCase
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJson
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJsonV1
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__acrobatics
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__aid
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__athletics
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__bargain
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__combat
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__discretion
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__dodge
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__empathy
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__grab
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__intimidation
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__perception
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__persuasion
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__search
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__sleight_of_hand
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__spiel
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__throw
|
||||
import org.jetbrains.compose.resources.getString
|
||||
import kotlin.math.ceil
|
||||
|
||||
class CharacterSheetJsonFactory(
|
||||
private val bonusDamageUseCase: DamageBonusUseCase,
|
||||
private val skillDescriptionFactory: SkillDescriptionFactory,
|
||||
private val characterSheetUseCase: CharacterSheetUseCase,
|
||||
) {
|
||||
|
||||
fun convertToJson(
|
||||
|
|
@ -51,6 +30,8 @@ class CharacterSheetJsonFactory(
|
|||
maxPP = if (sheet.overrideMaxPP) sheet.maxPp else null,
|
||||
damageBonus = if (sheet.overrideDamageBonus) sheet.damageBonus else null,
|
||||
armor = if (sheet.overrideArmor) sheet.armor else null,
|
||||
learning = if (sheet.overrideLearning) sheet.learning else null,
|
||||
hpGrowf = if (sheet.overrideHpGrow) sheet.hpGrow else null,
|
||||
skills = sheet.commonSkills.map {
|
||||
CharacterSheetJsonV1.Skill(
|
||||
id = it.id,
|
||||
|
|
@ -108,8 +89,8 @@ class CharacterSheetJsonFactory(
|
|||
|
||||
private suspend fun convertFromV1(
|
||||
json: CharacterSheetJsonV1,
|
||||
): CharacterSheet {
|
||||
val sheet = CharacterSheet(
|
||||
): CharacterSheet = characterSheetUseCase.run {
|
||||
CharacterSheet(
|
||||
id = json.id,
|
||||
name = json.name,
|
||||
strength = json.strength,
|
||||
|
|
@ -120,21 +101,27 @@ class CharacterSheetJsonFactory(
|
|||
power = json.power,
|
||||
charisma = json.charisma,
|
||||
overrideMovement = json.movement != null,
|
||||
movement = json.movement ?: 10,
|
||||
movement = json.movement ?: defaultMovement(),
|
||||
currentHp = json.currentHp,
|
||||
overrideMaxHp = json.maxHp != null,
|
||||
maxHp = json.maxHp ?: (ceil((json.constitution + json.height) / 2f).toInt()),
|
||||
maxHp = json.maxHp ?: defaultMaxHp(
|
||||
constitution = json.constitution,
|
||||
height = json.height,
|
||||
),
|
||||
currentPp = json.currentPP,
|
||||
overrideMaxPP = json.maxPP != null,
|
||||
maxPp = json.maxPP ?: json.power,
|
||||
maxPp = json.maxPP ?: defaultMaxPower(power = json.power),
|
||||
overrideDamageBonus = json.damageBonus != null,
|
||||
damageBonus = json.damageBonus
|
||||
?: bonusDamageUseCase.bonusDamage(
|
||||
strength = json.strength,
|
||||
height = json.height
|
||||
),
|
||||
damageBonus = json.damageBonus ?: defaultDamageBonus(
|
||||
strength = json.strength,
|
||||
height = json.height,
|
||||
),
|
||||
overrideArmor = json.armor != null,
|
||||
armor = json.armor ?: 0,
|
||||
armor = json.armor ?: defaultArmor(),
|
||||
overrideLearning = json.learning != null,
|
||||
learning = json.learning ?: defaultLearning(intelligence = json.intelligence),
|
||||
overrideHpGrow = json.hpGrowf != null,
|
||||
hpGrow = json.hpGrowf ?: defaultHpGrow(constitution = json.constitution),
|
||||
commonSkills = json.skills.map {
|
||||
CharacterSheet.Skill(
|
||||
id = it.id,
|
||||
|
|
@ -179,6 +166,5 @@ class CharacterSheetJsonFactory(
|
|||
)
|
||||
},
|
||||
)
|
||||
return sheet
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,10 @@ data class CharacterSheet(
|
|||
val damageBonus: String,
|
||||
val overrideArmor: Boolean,
|
||||
val armor: Int,
|
||||
val overrideLearning: Boolean,
|
||||
val learning: Int,
|
||||
val overrideHpGrow: Boolean,
|
||||
val hpGrow: Int,
|
||||
// skills
|
||||
val commonSkills: List<Skill>,
|
||||
val specialSkills: List<Skill>,
|
||||
|
|
@ -80,5 +84,7 @@ data class CharacterSheet(
|
|||
const val PP = "PP"
|
||||
const val DMG = "DMG"
|
||||
const val ARMOR = "ARMOR"
|
||||
const val LB = "LEARNING"
|
||||
const val GHP = "HP_GROW"
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,8 @@ data class CharacterSheetJsonV1(
|
|||
val maxPP: Int?,
|
||||
val damageBonus: String?,
|
||||
val armor: Int?,
|
||||
val learning: Int?,
|
||||
val hpGrowf: Int?,
|
||||
// skills
|
||||
val skills: List<Skill>,
|
||||
// occupations
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ import lwacharactersheet.composeapp.generated.resources.character_sheet__charact
|
|||
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__armor
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__damage_bonus
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__hit_point
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__hp_grow
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__learning
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__movement
|
||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__power_point
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__charisma
|
||||
|
|
@ -30,6 +32,8 @@ import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics
|
|||
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__armor
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__bonus_damage
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__hit_point
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__hp_grow
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__learning
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__movement
|
||||
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__power_point
|
||||
import org.jetbrains.compose.resources.getString
|
||||
|
|
@ -171,6 +175,26 @@ class CharacterSheetFactory(
|
|||
),
|
||||
editable = false,
|
||||
),
|
||||
Characteristic(
|
||||
id = CharacteristicId.LB,
|
||||
label = getString(Res.string.character_sheet__sub_characteristics__learning),
|
||||
value = "${sheet.learning}",
|
||||
tooltips = TooltipUio(
|
||||
title = getString(Res.string.character_sheet__sub_characteristics__learning),
|
||||
description = getString(Res.string.tooltip__sub_characteristics__learning),
|
||||
),
|
||||
editable = false,
|
||||
),
|
||||
Characteristic(
|
||||
id = CharacteristicId.GHP,
|
||||
label = getString(Res.string.character_sheet__sub_characteristics__hp_grow),
|
||||
value = "${sheet.hpGrow}",
|
||||
tooltips = TooltipUio(
|
||||
title = getString(Res.string.character_sheet__sub_characteristics__hp_grow),
|
||||
description = getString(Res.string.tooltip__sub_characteristics__hp_grow),
|
||||
),
|
||||
editable = false,
|
||||
),
|
||||
),
|
||||
commonSkills = sheet.commonSkills.map { skill ->
|
||||
Node(
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ package com.pixelized.desktop.lwa.screen.characterSheet.edit
|
|||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import com.pixelized.desktop.lwa.business.DamageBonusUseCase
|
||||
import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase
|
||||
import com.pixelized.desktop.lwa.business.CharacterSheetUseCase
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.SkillDescriptionFactory
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.edit.common.SkillFieldFactory
|
||||
|
|
@ -45,27 +44,26 @@ import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sk
|
|||
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__hit_point
|
||||
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 lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__power_point
|
||||
import org.jetbrains.compose.resources.getString
|
||||
import java.util.UUID
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class CharacterSheetEditFactory(
|
||||
private val bonusDamageUseCase: DamageBonusUseCase,
|
||||
private val characterSheetUseCase: CharacterSheetUseCase,
|
||||
private val skillFieldFactory: SkillFieldFactory,
|
||||
private val skillDescriptionFactory: SkillDescriptionFactory,
|
||||
private val normalizer: SkillNormalizerUseCase,
|
||||
) {
|
||||
suspend fun updateCharacterSheet(
|
||||
currentSheet: CharacterSheet?,
|
||||
editedSheet: CharacterSheetEditPageUio,
|
||||
): CharacterSheet {
|
||||
val editedMaxHp = editedSheet.maxHp.unpack()?.toIntOrNull() ?: currentSheet?.maxHp ?: 0
|
||||
val editedMaxPp = editedSheet.maxPp.unpack()?.toIntOrNull() ?: currentSheet?.maxPp ?: 0
|
||||
return CharacterSheet(
|
||||
id = editedSheet.id,
|
||||
name = editedSheet.name.value.value,
|
||||
|
|
@ -95,19 +93,11 @@ class CharacterSheetEditFactory(
|
|||
?: currentSheet?.movement
|
||||
?: 10,
|
||||
overrideMaxHp = editedSheet.maxHp.value.value.value.isNotBlank(),
|
||||
maxHp = editedSheet.maxHp.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.maxHp
|
||||
?: 0,
|
||||
currentHp = editedSheet.currentHp.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.currentHp
|
||||
?: 0,
|
||||
maxHp = editedMaxHp,
|
||||
currentHp = currentSheet?.currentHp?.coerceAtMost(editedMaxHp) ?: editedMaxHp,
|
||||
overrideMaxPP = editedSheet.maxPp.value.value.value.isNotBlank(),
|
||||
maxPp = editedSheet.maxPp.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.maxPp
|
||||
?: 0,
|
||||
currentPp = editedSheet.currentPp.unpack()?.toIntOrNull()
|
||||
?: currentSheet?.currentPp
|
||||
?: 0,
|
||||
maxPp = editedMaxPp,
|
||||
currentPp = currentSheet?.currentPp?.coerceAtMost(editedMaxPp) ?: editedMaxPp,
|
||||
overrideDamageBonus = editedSheet.damageBonus.value.value.value.isNotBlank(),
|
||||
damageBonus = editedSheet.damageBonus.unpack()
|
||||
?: currentSheet?.damageBonus
|
||||
|
|
@ -116,6 +106,10 @@ class CharacterSheetEditFactory(
|
|||
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,
|
||||
commonSkills = editedSheet.commonSkills.map { editedSkill ->
|
||||
val currentSkill = currentSheet?.commonSkills?.firstOrNull {
|
||||
it.id == editedSkill.id
|
||||
|
|
@ -236,239 +230,243 @@ class CharacterSheetEditFactory(
|
|||
val specialSkillsLabel = getString(Res.string.character_sheet_edit__skills__special_title)
|
||||
val magicSkillsLabel = getString(Res.string.character_sheet_edit__skills__magic_title)
|
||||
|
||||
val maxHitPoint = 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 { "${ceil((con() + hei()) / 2f).toInt()}" },
|
||||
)
|
||||
)
|
||||
val maxPowerPoint = 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 { "${pow()}" },
|
||||
)
|
||||
)
|
||||
|
||||
return CharacterSheetEditPageUio(
|
||||
id = sheet?.id ?: UUID.randomUUID().toString(),
|
||||
name = skillFieldFactory.createWrapper(
|
||||
label = mutableStateOf(getString(Res.string.character_sheet_edit__name_label)),
|
||||
value = sheet?.name ?: ""
|
||||
),
|
||||
strength = str,
|
||||
dexterity = dex,
|
||||
constitution = con,
|
||||
height = hei,
|
||||
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 = mutableStateOf("10"),
|
||||
)
|
||||
),
|
||||
maxHp = maxHitPoint,
|
||||
currentHp = SimpleFieldUio(
|
||||
label = getString(Res.string.character_sheet_edit__sub_characteristics__hit_point),
|
||||
value = skillFieldFactory.createWrapper(
|
||||
enable = false,
|
||||
placeholder = derivedStateOf {
|
||||
val min = min(
|
||||
sheet?.currentHp ?: Int.MAX_VALUE,
|
||||
maxHitPoint.unpack()?.toIntOrNull() ?: Int.MAX_VALUE,
|
||||
)
|
||||
if (min != Int.MAX_VALUE) "$min" else ""
|
||||
},
|
||||
)
|
||||
),
|
||||
maxPp = maxPowerPoint,
|
||||
currentPp = SimpleFieldUio(
|
||||
label = getString(Res.string.character_sheet_edit__sub_characteristics__power_point),
|
||||
value = skillFieldFactory.createWrapper(
|
||||
enable = false,
|
||||
placeholder = derivedStateOf {
|
||||
val min = min(
|
||||
sheet?.currentPp ?: Int.MAX_VALUE,
|
||||
maxPowerPoint.unpack()?.toIntOrNull() ?: Int.MAX_VALUE,
|
||||
)
|
||||
if (min != Int.MAX_VALUE) "$min" else ""
|
||||
},
|
||||
)
|
||||
),
|
||||
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 {
|
||||
bonusDamageUseCase.bonusDamage(
|
||||
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 = mutableStateOf("0"),
|
||||
)
|
||||
),
|
||||
commonSkills = listOf(
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.COMBAT_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__combat),
|
||||
base = derivedStateOf { normalizer.normalize(dex() * 2) },
|
||||
return with(characterSheetUseCase) {
|
||||
CharacterSheetEditPageUio(
|
||||
id = sheet?.id ?: UUID.randomUUID().toString(),
|
||||
name = skillFieldFactory.createWrapper(
|
||||
label = mutableStateOf(getString(Res.string.character_sheet_edit__name_label)),
|
||||
value = sheet?.name ?: ""
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.DODGE_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__dodge),
|
||||
base = derivedStateOf { normalizer.normalize(dex() * 2) },
|
||||
strength = str,
|
||||
dexterity = dex,
|
||||
constitution = con,
|
||||
height = hei,
|
||||
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()}"
|
||||
},
|
||||
)
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.GRAB_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__grab),
|
||||
base = derivedStateOf { normalizer.normalize(str() + hei()) },
|
||||
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()
|
||||
)
|
||||
}"
|
||||
},
|
||||
)
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.THROW_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__throw),
|
||||
base = derivedStateOf { normalizer.normalize(str() + dex()) },
|
||||
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())}"
|
||||
},
|
||||
)
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.ATHLETICS_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__athletics),
|
||||
base = derivedStateOf { normalizer.normalize(str() + con() * 2) },
|
||||
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()
|
||||
)
|
||||
},
|
||||
)
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.ACROBATICS_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__acrobatics),
|
||||
base = derivedStateOf { normalizer.normalize(dex() + con() * 2) },
|
||||
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()}"
|
||||
},
|
||||
)
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.PERCEPTION_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__perception),
|
||||
base = derivedStateOf { normalizer.normalize(10 + int() * 2) },
|
||||
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())}"
|
||||
},
|
||||
)
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.SEARCH_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__search),
|
||||
base = derivedStateOf { normalizer.normalize(10 + int() * 2) },
|
||||
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())}"
|
||||
},
|
||||
)
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.EMPATHY_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__empathy),
|
||||
base = derivedStateOf { normalizer.normalize(cha() + int()) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.PERSUASION_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__persuasion),
|
||||
base = derivedStateOf { normalizer.normalize(cha() * 3) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.INTIMIDATION_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__intimidation),
|
||||
base = derivedStateOf { normalizer.normalize(cha() + max(pow(), hei()) * 2) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.SPIEL_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__spiel),
|
||||
base = derivedStateOf { normalizer.normalize(cha() * 2 + int()) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.BARGAIN_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__bargain),
|
||||
base = derivedStateOf { normalizer.normalize(cha() * 2) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.DISCRETION_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__discretion),
|
||||
base = derivedStateOf { normalizer.normalize(cha() + dex() * 2 - hei()) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.SLEIGHT_OF_HAND_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__sleight_of_hand),
|
||||
base = derivedStateOf { normalizer.normalize(dex() * 2) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.AID_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__aid),
|
||||
base = derivedStateOf { normalizer.normalize(int() + dex()) },
|
||||
),
|
||||
),
|
||||
specialSkills = sheet?.specialSkills?.map { skill ->
|
||||
skillFieldFactory.createSkill(
|
||||
id = skill.id,
|
||||
label = specialSkillsLabel,
|
||||
descriptionValue = skill.description ?: "",
|
||||
labelValue = skill.label,
|
||||
baseValue = skill.base,
|
||||
bonusValue = skill.bonus ?: "",
|
||||
levelValue = skill.level ?: "",
|
||||
options = run {
|
||||
val current = sheet.specialSkills.firstOrNull { it.id == skill.id }
|
||||
listOf(
|
||||
skillFieldFactory.occupationOption(checked = current?.occupation ?: false),
|
||||
skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
|
||||
)
|
||||
},
|
||||
)
|
||||
} ?: emptyList(),
|
||||
magicSkills = sheet?.magicSkills?.map { skill ->
|
||||
skillFieldFactory.createSkill(
|
||||
id = skill.id,
|
||||
label = magicSkillsLabel,
|
||||
descriptionValue = skill.description ?: "",
|
||||
labelValue = skill.label,
|
||||
baseValue = skill.base,
|
||||
bonusValue = skill.bonus ?: "",
|
||||
levelValue = skill.level ?: "",
|
||||
options = run {
|
||||
val current = sheet.magicSkills.firstOrNull { it.id == skill.id }
|
||||
listOf(
|
||||
skillFieldFactory.occupationOption(
|
||||
checked = current?.occupation ?: false
|
||||
),
|
||||
skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
|
||||
)
|
||||
},
|
||||
)
|
||||
} ?: emptyList(),
|
||||
actions = sheet?.actions?.map { action ->
|
||||
ActionFieldUio(
|
||||
id = action.id,
|
||||
label = skillFieldFactory.createWrapper(
|
||||
label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__name_label)),
|
||||
value = action.label,
|
||||
commonSkills = listOf(
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.COMBAT_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__combat),
|
||||
base = derivedStateOf { normalize(dex() * 2) },
|
||||
),
|
||||
action = skillFieldFactory.createWrapper(
|
||||
label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__action_label)),
|
||||
value = action.roll,
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.DODGE_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__dodge),
|
||||
base = derivedStateOf { normalize(dex() * 2) },
|
||||
),
|
||||
option = skillFieldFactory.deleteOption { onDeleteSkill(action.id) },
|
||||
)
|
||||
} ?: emptyList(),
|
||||
)
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.GRAB_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__grab),
|
||||
base = derivedStateOf { normalize(str() + hei()) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.THROW_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__throw),
|
||||
base = derivedStateOf { normalize(str() + dex()) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.ATHLETICS_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__athletics),
|
||||
base = derivedStateOf { normalize(str() + con() * 2) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.ACROBATICS_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__acrobatics),
|
||||
base = derivedStateOf { normalize(dex() + con() * 2) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.PERCEPTION_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__perception),
|
||||
base = derivedStateOf { normalize(10 + int() * 2) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.SEARCH_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__search),
|
||||
base = derivedStateOf { normalize(10 + int() * 2) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.EMPATHY_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__empathy),
|
||||
base = derivedStateOf { normalize(cha() + int()) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.PERSUASION_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__persuasion),
|
||||
base = derivedStateOf { normalize(cha() * 3) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.INTIMIDATION_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__intimidation),
|
||||
base = derivedStateOf { normalize(cha() + max(pow(), hei()) * 2) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.SPIEL_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__spiel),
|
||||
base = derivedStateOf { normalize(cha() * 2 + int()) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.BARGAIN_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__bargain),
|
||||
base = derivedStateOf { normalize(cha() * 2) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.DISCRETION_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__discretion),
|
||||
base = derivedStateOf { normalize(cha() + dex() * 2 - hei()) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.SLEIGHT_OF_HAND_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__sleight_of_hand),
|
||||
base = derivedStateOf { normalize(dex() * 2) },
|
||||
),
|
||||
createBaseSkill(
|
||||
sheet = sheet,
|
||||
id = CharacterSheet.CommonSkillId.AID_ID,
|
||||
label = getString(Res.string.character_sheet_edit__skills__aid),
|
||||
base = derivedStateOf { normalize(int() + dex()) },
|
||||
),
|
||||
),
|
||||
specialSkills = sheet?.specialSkills?.map { skill ->
|
||||
skillFieldFactory.createSkill(
|
||||
id = skill.id,
|
||||
label = specialSkillsLabel,
|
||||
descriptionValue = skill.description ?: "",
|
||||
labelValue = skill.label,
|
||||
baseValue = skill.base,
|
||||
bonusValue = skill.bonus ?: "",
|
||||
levelValue = skill.level ?: "",
|
||||
options = run {
|
||||
val current = sheet.specialSkills.firstOrNull { it.id == skill.id }
|
||||
listOf(
|
||||
skillFieldFactory.occupationOption(current?.occupation ?: false),
|
||||
skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
|
||||
)
|
||||
},
|
||||
)
|
||||
} ?: emptyList(),
|
||||
magicSkills = sheet?.magicSkills?.map { skill ->
|
||||
skillFieldFactory.createSkill(
|
||||
id = skill.id,
|
||||
label = magicSkillsLabel,
|
||||
descriptionValue = skill.description ?: "",
|
||||
labelValue = skill.label,
|
||||
baseValue = skill.base,
|
||||
bonusValue = skill.bonus ?: "",
|
||||
levelValue = skill.level ?: "",
|
||||
options = run {
|
||||
val current = sheet.magicSkills.firstOrNull { it.id == skill.id }
|
||||
listOf(
|
||||
skillFieldFactory.occupationOption(
|
||||
checked = current?.occupation ?: false
|
||||
),
|
||||
skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
|
||||
)
|
||||
},
|
||||
)
|
||||
} ?: emptyList(),
|
||||
actions = sheet?.actions?.map { action ->
|
||||
ActionFieldUio(
|
||||
id = action.id,
|
||||
label = skillFieldFactory.createWrapper(
|
||||
label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__name_label)),
|
||||
value = action.label,
|
||||
),
|
||||
action = skillFieldFactory.createWrapper(
|
||||
label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__action_label)),
|
||||
value = action.roll,
|
||||
),
|
||||
option = skillFieldFactory.deleteOption { onDeleteSkill(action.id) },
|
||||
)
|
||||
} ?: emptyList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun createBaseSkill(
|
||||
|
|
|
|||
|
|
@ -70,10 +70,10 @@ data class CharacterSheetEditPageUio(
|
|||
val movement: SimpleFieldUio,
|
||||
val maxHp: SimpleFieldUio,
|
||||
val maxPp: SimpleFieldUio,
|
||||
val currentHp: SimpleFieldUio,
|
||||
val currentPp: 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>,
|
||||
|
|
@ -94,11 +94,11 @@ data class CharacterSheetEditPageUio(
|
|||
get() = listOf(
|
||||
movement,
|
||||
maxHp,
|
||||
currentHp,
|
||||
maxPp,
|
||||
currentPp,
|
||||
damageBonus,
|
||||
armor,
|
||||
learning,
|
||||
hpGrow,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,43 +6,45 @@ class DamageBonusUseCaseTest {
|
|||
|
||||
@Test
|
||||
fun testBonusDamage() {
|
||||
val userCase = CharacterSheetUseCase()
|
||||
|
||||
(0 until 12).forEach {
|
||||
val result = DamageBonusUseCase.bonusDamage(stat = it)
|
||||
val result = userCase.defaultDamageBonus(sum = it)
|
||||
val expected = "-1d6"
|
||||
assert(result == expected) {
|
||||
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
||||
}
|
||||
}
|
||||
(12 until 18).forEach {
|
||||
val result = DamageBonusUseCase.bonusDamage(stat = it)
|
||||
val result = userCase.defaultDamageBonus(sum = it)
|
||||
val expected = "-1d4"
|
||||
assert(result == expected) {
|
||||
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
||||
}
|
||||
}
|
||||
(18 until 23).forEach {
|
||||
val result = DamageBonusUseCase.bonusDamage(stat = it)
|
||||
val result = userCase.defaultDamageBonus(sum = it)
|
||||
val expected = "+0"
|
||||
assert(result == expected) {
|
||||
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
||||
}
|
||||
}
|
||||
(23 until 30).forEach {
|
||||
val result = DamageBonusUseCase.bonusDamage(stat = it)
|
||||
val result = userCase.defaultDamageBonus(sum = it)
|
||||
val expected = "+1d4"
|
||||
assert(result == expected) {
|
||||
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
||||
}
|
||||
}
|
||||
(30 until 40).forEach {
|
||||
val result = DamageBonusUseCase.bonusDamage(stat = it)
|
||||
val result = userCase.defaultDamageBonus(sum = it)
|
||||
val expected = "+1d6"
|
||||
assert(result == expected) {
|
||||
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
||||
}
|
||||
}
|
||||
(40 until 100).forEach {
|
||||
val result = DamageBonusUseCase.bonusDamage(stat = it)
|
||||
val result = userCase.defaultDamageBonus(sum = it)
|
||||
val expected = "+2d6"
|
||||
assert(result == expected) {
|
||||
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import org.junit.Test
|
|||
class RollUseCaseTest {
|
||||
|
||||
companion object {
|
||||
private const val ROLL_COUNT = 1000000000
|
||||
private const val ROLL_COUNT = 100000000 // 100*10^6
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -20,16 +20,18 @@ class RollUseCaseTest {
|
|||
|
||||
@Test
|
||||
fun testRoll1D100_() {
|
||||
val result = build1D100ResultSet()
|
||||
val results = build1D100ResultSet()
|
||||
|
||||
val delta = 0.001f
|
||||
val delta = 0.005f
|
||||
val median = (ROLL_COUNT / 100).let {
|
||||
(it * (1f - delta)).toInt()..(it * (1f + delta)).toInt()
|
||||
}
|
||||
|
||||
println("Testing if with $ROLL_COUNT rolls we have at least all results in $median.")
|
||||
assert(result.all { it in median }) {
|
||||
"Maybe a false negative, we expected that all values should be in $median a result.\nroll amount: $ROLL_COUNT - result:$result"
|
||||
results.map { it in median }.forEachIndexed { index, result ->
|
||||
assert(result) {
|
||||
"Maybe a false negative, we expected that all values should be in $median a result.\nroll amount: $ROLL_COUNT - index:$index result:${results[index]}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -37,7 +39,7 @@ class RollUseCaseTest {
|
|||
val useCase = RollUseCase()
|
||||
val result = MutableList(100) { 0 }
|
||||
repeat(count) {
|
||||
val roll = useCase.rollD100()
|
||||
val roll = useCase.roll(faces = 100)
|
||||
result[roll - 1] += 1
|
||||
}
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ class SkillNormalizerUseCaseText {
|
|||
|
||||
@Test
|
||||
fun testNormalization() {
|
||||
val useCase = SkillNormalizerUseCase()
|
||||
val useCase = CharacterSheetUseCase()
|
||||
|
||||
val samples = listOf(
|
||||
0 to 0,
|
||||
1 to 0,
|
||||
|
|
@ -19,6 +20,96 @@ class SkillNormalizerUseCaseText {
|
|||
8 to 5,
|
||||
9 to 5,
|
||||
10 to 10,
|
||||
11 to 10,
|
||||
12 to 10,
|
||||
13 to 10,
|
||||
14 to 10,
|
||||
15 to 15,
|
||||
16 to 15,
|
||||
17 to 15,
|
||||
18 to 15,
|
||||
19 to 15,
|
||||
20 to 20,
|
||||
21 to 20,
|
||||
22 to 20,
|
||||
23 to 20,
|
||||
24 to 20,
|
||||
25 to 25,
|
||||
26 to 25,
|
||||
27 to 25,
|
||||
28 to 25,
|
||||
29 to 25,
|
||||
30 to 30,
|
||||
31 to 30,
|
||||
32 to 30,
|
||||
33 to 30,
|
||||
34 to 30,
|
||||
35 to 35,
|
||||
36 to 35,
|
||||
37 to 35,
|
||||
38 to 35,
|
||||
39 to 35,
|
||||
40 to 40,
|
||||
41 to 40,
|
||||
42 to 40,
|
||||
43 to 40,
|
||||
44 to 40,
|
||||
45 to 45,
|
||||
46 to 45,
|
||||
47 to 45,
|
||||
48 to 45,
|
||||
49 to 45,
|
||||
50 to 50,
|
||||
51 to 50,
|
||||
52 to 50,
|
||||
53 to 50,
|
||||
54 to 50,
|
||||
55 to 55,
|
||||
56 to 55,
|
||||
57 to 55,
|
||||
58 to 55,
|
||||
59 to 55,
|
||||
60 to 60,
|
||||
61 to 60,
|
||||
62 to 60,
|
||||
63 to 60,
|
||||
64 to 60,
|
||||
65 to 65,
|
||||
66 to 65,
|
||||
67 to 65,
|
||||
68 to 65,
|
||||
69 to 65,
|
||||
70 to 70,
|
||||
71 to 70,
|
||||
72 to 70,
|
||||
73 to 70,
|
||||
74 to 70,
|
||||
75 to 75,
|
||||
76 to 75,
|
||||
77 to 75,
|
||||
78 to 75,
|
||||
79 to 75,
|
||||
80 to 80,
|
||||
81 to 80,
|
||||
82 to 80,
|
||||
83 to 80,
|
||||
84 to 80,
|
||||
85 to 85,
|
||||
86 to 85,
|
||||
87 to 85,
|
||||
88 to 85,
|
||||
89 to 85,
|
||||
90 to 90,
|
||||
91 to 90,
|
||||
92 to 90,
|
||||
93 to 90,
|
||||
94 to 90,
|
||||
95 to 95,
|
||||
96 to 95,
|
||||
97 to 95,
|
||||
98 to 95,
|
||||
99 to 95,
|
||||
100 to 100,
|
||||
)
|
||||
samples.forEach { (value, expected) ->
|
||||
assert(useCase.normalize(value) == expected) {
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@ class SkillStepUseCaseTest {
|
|||
|
||||
@Test
|
||||
fun testStepForSkill() {
|
||||
val useCase = SkillStepUseCase()
|
||||
(1..500).forEach { skill ->
|
||||
val step = SkillStepUseCase.computeSkillStep(
|
||||
val step = useCase.computeSkillStep(
|
||||
skill = skill,
|
||||
)
|
||||
val expected = expected[skill] ?: error(
|
||||
|
|
|
|||
|
|
@ -13,16 +13,16 @@ class InstructionParserTest {
|
|||
|
||||
fun test(
|
||||
instruction: String,
|
||||
expectedModifier: Instruction.Dice.Modifier.Dice.Modifier?,
|
||||
expectedModifier: Instruction.Dice.Modifier?,
|
||||
expectedQuantity: Int,
|
||||
expectedFaces: Int,
|
||||
) {
|
||||
val dice = parser.parseInstruction(instruction = instruction)
|
||||
val dice = parser.parse(value = instruction).first()
|
||||
|
||||
assert(dice is Instruction.Dice.Dice) {
|
||||
assert(dice is Instruction.Dice) {
|
||||
"Instruction should be ArithmeticInstruction.Dice but was: ${dice::class.java.simpleName}"
|
||||
}
|
||||
(dice as? Instruction.Dice.Dice)?.let {
|
||||
(dice as? Instruction.Dice)?.let {
|
||||
assert(dice.modifier == expectedModifier) {
|
||||
"$instruction modifier should be:\"$expectedModifier\", but was: ${dice.modifier}"
|
||||
}
|
||||
|
|
@ -66,14 +66,14 @@ class InstructionParserTest {
|
|||
val parser = ArithmeticParser()
|
||||
|
||||
ArithmeticParser.words.map { instruction ->
|
||||
val word = parser.parseInstruction(instruction = instruction)
|
||||
val word = parser.parse(value = instruction).first()
|
||||
|
||||
assert(word is Instruction.Word.Word) {
|
||||
assert(word is Instruction.Word) {
|
||||
"Instruction should be ArithmeticInstruction.Word but was: ${word::class.java.simpleName}"
|
||||
}
|
||||
(word as? Instruction.Word.Word)?.let {
|
||||
assert(it.name == instruction) {
|
||||
"Instruction should be $instruction, but was ${it.name}"
|
||||
(word as? Instruction.Word)?.let {
|
||||
assert(it.type.name == instruction) {
|
||||
"Instruction should be $instruction, but was ${it.type.name}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -84,12 +84,12 @@ class InstructionParserTest {
|
|||
val parser = ArithmeticParser()
|
||||
|
||||
"100".let { instruction ->
|
||||
val flat = parser.parseInstruction(instruction = instruction)
|
||||
val flat = parser.parse(value = instruction).first()
|
||||
|
||||
assert(flat is Instruction.Flat.Flat) {
|
||||
assert(flat is Instruction.Flat) {
|
||||
"Instruction should be ArithmeticInstruction.Flat but was: ${flat::class.java.simpleName}"
|
||||
}
|
||||
(flat as? Instruction.Flat.Flat)?.let {
|
||||
(flat as? Instruction.Flat)?.let {
|
||||
assert("${it.value}" == instruction) {
|
||||
"Instruction should be $instruction, but was ${it.value}"
|
||||
}
|
||||
|
|
@ -97,59 +97,42 @@ class InstructionParserTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFailedInstructionParse() {
|
||||
val parser = ArithmeticParser()
|
||||
assertFails(
|
||||
message = "Instruction parse should failed with UnknownInstruction",
|
||||
) {
|
||||
parser.parseInstruction(instruction = "a110")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRollParse() {
|
||||
val parser = ArithmeticParser()
|
||||
|
||||
fun test(
|
||||
arithmetics: Instruction,
|
||||
expectedSign: Int,
|
||||
instruction: Instruction,
|
||||
expectedInstruction: Instruction,
|
||||
) {
|
||||
assert(arithmetics.sign == expectedSign) {
|
||||
"Arithmetic sign should be $expectedSign but was: ${arithmetics.sign}"
|
||||
}
|
||||
assert(arithmetics.instruction == expectedInstruction) {
|
||||
"Arithmetic instruction should be $expectedInstruction but was: ${arithmetics.instruction}"
|
||||
assert(instruction == expectedInstruction) {
|
||||
"Arithmetic instruction should be $expectedInstruction but was: $instruction"
|
||||
}
|
||||
}
|
||||
|
||||
val instructions = parser.parse(value = "1+1d6+2-BDC+BDD")
|
||||
val instructions = parser.parse(
|
||||
value = "1+1d6+2-BDC+BDD",
|
||||
)
|
||||
|
||||
test(
|
||||
arithmetics = instructions[0],
|
||||
expectedSign = 1,
|
||||
expectedInstruction = Instruction.Flat(value = 1),
|
||||
instruction = instructions[0],
|
||||
expectedInstruction = Instruction.Flat(sign = 1, value = 1),
|
||||
)
|
||||
test(
|
||||
arithmetics = instructions[1],
|
||||
expectedSign = 1,
|
||||
expectedInstruction = Instruction.Dice(quantity = 1, faces = 6, modifier = null),
|
||||
instruction = instructions[1],
|
||||
expectedInstruction = Instruction.Dice(sign = 1, modifier = null, quantity = 1, faces = 6),
|
||||
)
|
||||
test(
|
||||
arithmetics = instructions[2],
|
||||
expectedSign = 1,
|
||||
expectedInstruction = Instruction.Flat(value = 2),
|
||||
instruction = instructions[2],
|
||||
expectedInstruction = Instruction.Flat(sign = 1, value = 2),
|
||||
)
|
||||
test(
|
||||
arithmetics = instructions[3],
|
||||
expectedSign = -1,
|
||||
expectedInstruction = Instruction.Word.BDC,
|
||||
instruction = instructions[3],
|
||||
expectedInstruction = Instruction.Word(sign = -1, type = Instruction.Word.Type.BDC),
|
||||
)
|
||||
test(
|
||||
arithmetics = instructions[4],
|
||||
expectedSign = 1,
|
||||
expectedInstruction = Instruction.Word.BDD,
|
||||
instruction = instructions[4],
|
||||
expectedInstruction = Instruction.Word(sign = 1, type = Instruction.Word.Type.BDD),
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue