Support wild shape transformation (hp wise)
This commit is contained in:
parent
483a8cf556
commit
1b97560dce
7 changed files with 138 additions and 55 deletions
|
|
@ -0,0 +1,13 @@
|
|||
package com.pixelized.rplexicon.business
|
||||
|
||||
import com.pixelized.rplexicon.data.model.alteration.Alteration
|
||||
|
||||
private const val WILD_SHAPE = "Forme sauvage"
|
||||
|
||||
fun isWildShape(alteration: Alteration): Boolean {
|
||||
return isWildShape(alterationId = alteration.name)
|
||||
}
|
||||
|
||||
fun isWildShape(alterationId: String): Boolean {
|
||||
return alterationId.contains(WILD_SHAPE)
|
||||
}
|
||||
|
|
@ -37,6 +37,10 @@ data class CharacterSheetFire(
|
|||
@get:PropertyName("value")
|
||||
@set:PropertyName("value")
|
||||
var value: Int? = null,
|
||||
|
||||
@get:PropertyName("wild_shape")
|
||||
@set:PropertyName("wild_shape")
|
||||
var wildShape: Int? = null,
|
||||
)
|
||||
|
||||
@Keep
|
||||
|
|
|
|||
|
|
@ -142,7 +142,12 @@ class FirebaseRepository @Inject constructor(
|
|||
fun getAlterationStatusSnapshot(key: AlterationStatus.Key): AlterationStatus.Value =
|
||||
alterationStatus.value[key] ?: AlterationStatus.Value(false)
|
||||
|
||||
fun setCharacterHitPoint(character: String, value: Int, extra: Int) {
|
||||
fun setCharacterHitPoint(
|
||||
character: String,
|
||||
value: Int? = characterFireSheet.value[character]?.hitPoint?.value,
|
||||
extra: Int? = characterFireSheet.value[character]?.hitPoint?.additional,
|
||||
wildShape: Int? = characterFireSheet.value[character]?.hitPoint?.wildShape,
|
||||
) {
|
||||
val reference = database.getReference(
|
||||
"$PATH_CHARACTERS/$character/${CharacterSheetFire.HIT_POINT}"
|
||||
)
|
||||
|
|
@ -150,6 +155,7 @@ class FirebaseRepository @Inject constructor(
|
|||
CharacterSheetFire.HitPoint(
|
||||
additional = extra,
|
||||
value = value,
|
||||
wildShape = wildShape,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,13 @@ class ActiveAlterationRepository @Inject constructor(
|
|||
fun getActiveAssignedAlterations(character: String?): Flow<List<Alteration>> =
|
||||
activeAlterations.map { it[character] ?: emptyList() }
|
||||
|
||||
/**
|
||||
* Returns the first element matching the given predicate, or null if element was not found.
|
||||
*/
|
||||
fun firstOrNull(character: String?, predicate: (Alteration) -> Boolean): Alteration? {
|
||||
return activeAlterations.value[character]?.firstOrNull { predicate(it) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ACTIVE = AlterationStatus.Value(value = true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,10 @@ class CharacterSheetHeaderUioFactory @Inject constructor(
|
|||
),
|
||||
hitPoint = LabelPointUio(
|
||||
label = R.string.character_sheet_title_hp,
|
||||
value = convertToHitPointLabel(hitPoint = fireHeaderData),
|
||||
value = convertToHitPointLabel(
|
||||
fireHeaderData = fireHeaderData,
|
||||
sheetHeaderData = sheetHeaderData,
|
||||
),
|
||||
max = sheetHeaderData?.hpMax?.let { "/ $it" } ?: " ",
|
||||
),
|
||||
dC = sheetHeaderData?.dc?.let {
|
||||
|
|
@ -65,11 +68,22 @@ class CharacterSheetHeaderUioFactory @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun convertToHitPointLabel(hitPoint: HeaderViewModel.FireHeaderData?): String {
|
||||
return when {
|
||||
hitPoint?.hp == null -> "?"
|
||||
hitPoint.extra == 0 -> "${hitPoint.hp}"
|
||||
else -> "${hitPoint.hp}+${hitPoint.extra}"
|
||||
private fun convertToHitPointLabel(
|
||||
fireHeaderData: HeaderViewModel.FireHeaderData?,
|
||||
sheetHeaderData: HeaderViewModel.SheetHeaderData?,
|
||||
): String {
|
||||
return when (fireHeaderData?.wildShapeAlteration) {
|
||||
null -> when {
|
||||
fireHeaderData?.hp == null -> "?"
|
||||
fireHeaderData.extraHp == 0 -> "${fireHeaderData.hp}"
|
||||
else -> "${fireHeaderData.hp}+${fireHeaderData.extraHp}"
|
||||
}
|
||||
|
||||
else -> when {
|
||||
fireHeaderData?.wildShapeHp == null -> sheetHeaderData?.hpMax?.let { "$it" } ?: "?"
|
||||
fireHeaderData.extraHp == 0 -> "${fireHeaderData.wildShapeHp}"
|
||||
else -> "${fireHeaderData.wildShapeHp}+${fireHeaderData.extraHp}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,14 +7,15 @@ import androidx.compose.runtime.mutableStateOf
|
|||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.pixelized.rplexicon.business.isWildShape
|
||||
import com.pixelized.rplexicon.data.model.CharacterSheet
|
||||
import com.pixelized.rplexicon.data.model.DiceThrow
|
||||
import com.pixelized.rplexicon.data.model.Property
|
||||
import com.pixelized.rplexicon.data.model.alteration.Alteration
|
||||
import com.pixelized.rplexicon.data.model.alteration.AlterationStatus
|
||||
import com.pixelized.rplexicon.data.network.CharacterSheetFire
|
||||
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
|
||||
import com.pixelized.rplexicon.data.repository.character.ActiveAlterationRepository
|
||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
|
||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
|
||||
import com.pixelized.rplexicon.ui.composable.edit.HpPointDialogUio
|
||||
import com.pixelized.rplexicon.ui.composable.edit.SkillEditDialogUio
|
||||
|
|
@ -36,8 +37,8 @@ import javax.inject.Inject
|
|||
class HeaderViewModel @Inject constructor(
|
||||
private val headerFactory: CharacterSheetHeaderUioFactory,
|
||||
private val firebaseRepository: FirebaseRepository,
|
||||
private val activeAlterationRepository: ActiveAlterationRepository,
|
||||
characterRepository: CharacterSheetRepository,
|
||||
activeAlterationRepository: ActiveAlterationRepository,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel() {
|
||||
val character = savedStateHandle.characterSheetArgument.name
|
||||
|
|
@ -67,10 +68,13 @@ class HeaderViewModel @Inject constructor(
|
|||
struct.sheet = sheets[character]
|
||||
struct.alterationsStatus = alterations.toStatus()
|
||||
}
|
||||
.combine(firebaseRepository.getCharacter(character = character)) { _, fire ->
|
||||
struct.fire = fire
|
||||
}
|
||||
.collect {
|
||||
val (sheet, status) = struct
|
||||
val (sheet, status, fire) = struct
|
||||
if (sheet != null) {
|
||||
val data = SheetHeaderData(
|
||||
val headerCategories = SheetHeaderData(
|
||||
hpMax = sheet.hitPoint + status[Property.HIT_POINT].sum,
|
||||
characterClass = sheet.characterClass,
|
||||
initiative = (sheet.dexterity + status[Property.DEXTERITY].sum).modifier + status[Property.INITIATIVE].sum,
|
||||
|
|
@ -78,35 +82,27 @@ class HeaderViewModel @Inject constructor(
|
|||
dc = sheet.dC,
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
sheetData.value = data
|
||||
sheetData.value = headerCategories
|
||||
}
|
||||
val headerValues = FireHeaderData(
|
||||
hp = fire.hitPoint?.value ?: 1,
|
||||
extraHp = fire.hitPoint?.additional ?: 0,
|
||||
wildShapeHp = fire.hitPoint?.wildShape ?: headerCategories.hpMax,
|
||||
resource = fire.skills[sheet.resource],
|
||||
deathSuccess = fire.death?.success ?: 0,
|
||||
deathFailure = fire.death?.failure ?: 0,
|
||||
wildShapeAlteration = activeAlterationRepository.firstOrNull(
|
||||
character = character
|
||||
) { isWildShape(it) },
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
fireData.value = headerValues
|
||||
}
|
||||
} else {
|
||||
launch { characterRepository.fetchCharacterSheet() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
launch(context = Dispatchers.Default) {
|
||||
val struct = HeaderValueStruct()
|
||||
characterRepository.data
|
||||
.combine(firebaseRepository.getCharacter(character = character)) { sheets, fire ->
|
||||
struct.sheet = sheets[character]
|
||||
struct.fire = fire
|
||||
}
|
||||
.collect {
|
||||
val (sheet, fire) = struct
|
||||
val data = FireHeaderData(
|
||||
hp = fire.hitPoint?.value ?: 1,
|
||||
resource = fire.skills[sheet?.resource],
|
||||
extra = fire.hitPoint?.additional ?: 0,
|
||||
deathSuccess = fire.death?.success ?: 0,
|
||||
deathFailure = fire.death?.failure ?: 0,
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
fireData.value = data
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -133,8 +129,11 @@ class HeaderViewModel @Inject constructor(
|
|||
fun toggleHitPointDialog() {
|
||||
_hitPointDialog.value = if (_hitPointDialog.value == null) {
|
||||
HpPointDialogUio(
|
||||
value = fireData.value?.hp ?: 10,
|
||||
extra = fireData.value?.extra ?: 0,
|
||||
value = when (fireData.value?.wildShapeAlteration) {
|
||||
null -> fireData.value?.hp ?: 10
|
||||
else -> fireData.value?.wildShapeHp ?: 1
|
||||
},
|
||||
extra = fireData.value?.extraHp ?: 0,
|
||||
max = sheetData.value?.hpMax ?: 10,
|
||||
)
|
||||
} else {
|
||||
|
|
@ -143,20 +142,53 @@ class HeaderViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun applyHitPointChange(hp: Int, extra: Int) {
|
||||
val hpDownToZero = (fireData.value?.hp ?: 0) > 0 && hp == 0
|
||||
val hpUpFromZero = (fireData.value?.hp ?: 0) == 0 && hp > 0
|
||||
if (hpDownToZero || hpUpFromZero) {
|
||||
firebaseRepository.setCharacterDeathCounter(
|
||||
val wildShapeAlteration = fireData.value?.wildShapeAlteration
|
||||
// check if we have a wild shape alteration activated.
|
||||
if (wildShapeAlteration != null) {
|
||||
// character is in wild shape form.
|
||||
// check if we are down to 0 hp.
|
||||
val hpDownToZero = (fireData.value?.wildShapeHp ?: 0) > 0 && hp == 0
|
||||
if (hpDownToZero) {
|
||||
// deactivate the wild shape alteration
|
||||
firebaseRepository.setAlterationStatus(
|
||||
key = AlterationStatus.Key(character, wildShapeAlteration.name),
|
||||
value = AlterationStatus.Value(false),
|
||||
)
|
||||
// remove the wild shape hit point
|
||||
firebaseRepository.setCharacterHitPoint(
|
||||
character = character,
|
||||
wildShape = null,
|
||||
extra = extra,
|
||||
)
|
||||
} else {
|
||||
// change the current wild shape hit point.
|
||||
firebaseRepository.setCharacterHitPoint(
|
||||
character = character,
|
||||
wildShape = hp,
|
||||
extra = extra,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// character is NOT in wild shape
|
||||
// check if we are down to 0 hp or up from 0.
|
||||
val hpDownToZero = (fireData.value?.hp ?: 0) > 0 && hp == 0
|
||||
val hpUpFromZero = (fireData.value?.hp ?: 0) == 0 && hp > 0
|
||||
if (hpDownToZero || hpUpFromZero) {
|
||||
// set the death counter to 0
|
||||
firebaseRepository.setCharacterDeathCounter(
|
||||
character = character,
|
||||
success = 0,
|
||||
failure = 0,
|
||||
)
|
||||
}
|
||||
// change the current hp of the character
|
||||
firebaseRepository.setCharacterHitPoint(
|
||||
character = character,
|
||||
success = 0,
|
||||
failure = 0,
|
||||
value = hp,
|
||||
extra = extra,
|
||||
wildShape = null,
|
||||
)
|
||||
}
|
||||
firebaseRepository.setCharacterHitPoint(
|
||||
character = character,
|
||||
value = hp,
|
||||
extra = extra,
|
||||
)
|
||||
_hitPointDialog.value = null
|
||||
}
|
||||
|
||||
|
|
@ -182,15 +214,10 @@ class HeaderViewModel @Inject constructor(
|
|||
data class HeaderStruct(
|
||||
var sheet: CharacterSheet? = null,
|
||||
var alterationsStatus: Map<Property, List<Alteration.Status>> = emptyMap(),
|
||||
)
|
||||
|
||||
class HeaderValueStruct(
|
||||
var sheet: CharacterSheet? = null
|
||||
) {
|
||||
lateinit var fire: CharacterSheetFire
|
||||
|
||||
operator fun component1() = sheet
|
||||
operator fun component2() = fire
|
||||
operator fun component3() = fire
|
||||
}
|
||||
|
||||
@Stable
|
||||
|
|
@ -205,9 +232,11 @@ class HeaderViewModel @Inject constructor(
|
|||
@Stable
|
||||
data class FireHeaderData(
|
||||
val hp: Int,
|
||||
val extraHp: Int,
|
||||
val wildShapeHp: Int?,
|
||||
val resource: Int?,
|
||||
val extra: Int,
|
||||
val deathSuccess: Int,
|
||||
val deathFailure: Int,
|
||||
val wildShapeAlteration: Alteration?,
|
||||
)
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import androidx.lifecycle.SavedStateHandle
|
|||
import androidx.lifecycle.viewModelScope
|
||||
import com.pixelized.rplexicon.R
|
||||
import com.pixelized.rplexicon.business.AlterationSortUseCase
|
||||
import com.pixelized.rplexicon.business.isWildShape
|
||||
import com.pixelized.rplexicon.data.model.CharacterSheet
|
||||
import com.pixelized.rplexicon.data.model.Description
|
||||
import com.pixelized.rplexicon.data.model.alteration.Alteration
|
||||
|
|
@ -88,9 +89,18 @@ class AlterationViewModel @Inject constructor(
|
|||
|
||||
fun toggleAlteration(alteration: String) {
|
||||
val key = AlterationStatus.Key(character = character, alteration = alteration)
|
||||
val value = firebaseRepository.getAlterationStatusSnapshot(key = key)
|
||||
// check if this is a wild shape alteration, if it is clear the hit point before activating it.
|
||||
if (isWildShape(alteration) && !value.value) {
|
||||
firebaseRepository.setCharacterHitPoint(
|
||||
character = character,
|
||||
wildShape = null,
|
||||
)
|
||||
}
|
||||
// switch the alteration status
|
||||
firebaseRepository.setAlterationStatus(
|
||||
key = key,
|
||||
value = firebaseRepository.getAlterationStatusSnapshot(key = key).switch(),
|
||||
value = value.switch(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue