Add Skill passive in the proficiency page
This commit is contained in:
parent
755caf1194
commit
a009e6c831
8 changed files with 265 additions and 85 deletions
|
|
@ -6,4 +6,5 @@ data class Skill(
|
||||||
val rest: String?,
|
val rest: String?,
|
||||||
val cost: String?,
|
val cost: String?,
|
||||||
val effect: Throw?,
|
val effect: Throw?,
|
||||||
|
val passive: Boolean,
|
||||||
)
|
)
|
||||||
|
|
@ -31,6 +31,7 @@ class SkillParser @Inject constructor(
|
||||||
rest = row.parse(column = REST),
|
rest = row.parse(column = REST),
|
||||||
cost = row.parse(column = COST),
|
cost = row.parse(column = COST),
|
||||||
effect = throwParser.parse(row.parse(column = EFFECT)),
|
effect = throwParser.parse(row.parse(column = EFFECT)),
|
||||||
|
passive = row.parseBool(column = PASSIVE) ?: false
|
||||||
)
|
)
|
||||||
skills.getOrPut(characterSheet.name) { mutableListOf() }.add(skill)
|
skills.getOrPut(characterSheet.name) { mutableListOf() }.add(skill)
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +49,8 @@ class SkillParser @Inject constructor(
|
||||||
private val REST = column("Récupération")
|
private val REST = column("Récupération")
|
||||||
private val COST = column("Coût")
|
private val COST = column("Coût")
|
||||||
private val EFFECT = column("Effect")
|
private val EFFECT = column("Effect")
|
||||||
|
private val PASSIVE = column("Passif")
|
||||||
|
|
||||||
private val COLUMNS get() = listOf(CHARACTER, NAME, AMOUNT, REST, COST, EFFECT)
|
private val COLUMNS get() = listOf(CHARACTER, NAME, AMOUNT, REST, COST, EFFECT, PASSIVE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.heightIn
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.minimumInteractiveComponentSize
|
import androidx.compose.material.minimumInteractiveComponentSize
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
|
@ -64,7 +63,6 @@ fun SkillItem(
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable { onInfo(skill) }
|
.clickable { onInfo(skill) }
|
||||||
.minimumInteractiveComponentSize()
|
|
||||||
.padding(paddingValues = padding)
|
.padding(paddingValues = padding)
|
||||||
.then(other = modifier),
|
.then(other = modifier),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
|
|
@ -160,7 +158,7 @@ private fun CounterItemPreview(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Stable
|
@Stable
|
||||||
fun rememberTokenListStatePreview(): State<List<SkillItemUio>> = remember {
|
fun rememberSkillsListStatePreview(): State<List<SkillItemUio>> = remember {
|
||||||
val provider = CounterItemPreviewProvider()
|
val provider = CounterItemPreviewProvider()
|
||||||
mutableStateOf(provider.values.toList())
|
mutableStateOf(provider.values.toList())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.pixelized.rplexicon.ui.screens.character.factory
|
||||||
|
|
||||||
|
import com.pixelized.rplexicon.data.model.CharacterSheet
|
||||||
|
import com.pixelized.rplexicon.data.model.Property
|
||||||
|
import com.pixelized.rplexicon.data.model.Skill
|
||||||
|
import com.pixelized.rplexicon.data.network.CharacterSheetFire
|
||||||
|
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
|
||||||
|
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SkillItemUio
|
||||||
|
import com.pixelized.rplexicon.utilitary.extentions.icon
|
||||||
|
import com.pixelized.rplexicon.utilitary.extentions.modifier
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class SkillFactoryUioFactory @Inject constructor(
|
||||||
|
private val descriptionRepository: DescriptionRepository,
|
||||||
|
) {
|
||||||
|
fun convert(
|
||||||
|
character: CharacterSheet?,
|
||||||
|
fire: CharacterSheetFire?,
|
||||||
|
skills: List<Skill>,
|
||||||
|
): List<SkillItemUio> {
|
||||||
|
// Filter out passive skills, theses are display in the Proficiency Page.
|
||||||
|
return skills.map { skill ->
|
||||||
|
val description = descriptionRepository.find(name = skill.name)
|
||||||
|
val modifier = skill.effect?.modifier?.sumOf {
|
||||||
|
when (it) {
|
||||||
|
Property.LEVEL -> character?.level ?: 0
|
||||||
|
Property.PROFICIENCY -> character?.proficiency ?: 0
|
||||||
|
Property.STRENGTH -> character?.strength?.modifier ?: 0
|
||||||
|
Property.DEXTERITY -> character?.dexterity?.modifier ?: 0
|
||||||
|
Property.CONSTITUTION -> character?.constitution?.modifier ?: 0
|
||||||
|
Property.INTELLIGENCE -> character?.intelligence?.modifier ?: 0
|
||||||
|
Property.WISDOM -> character?.wisdom?.modifier ?: 0
|
||||||
|
Property.CHARISMA -> character?.charisma?.modifier ?: 0
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
} ?: 0
|
||||||
|
SkillItemUio(
|
||||||
|
label = skill.name,
|
||||||
|
translate = description?.original,
|
||||||
|
rest = skill.rest,
|
||||||
|
cost = skill.cost,
|
||||||
|
effect = skill.effect?.let {
|
||||||
|
SkillItemUio.Dice(
|
||||||
|
icon = it.faces.icon,
|
||||||
|
label = "${skill.effect.amount}d${skill.effect.faces}${if (modifier > 0) "+$modifier" else ""}",
|
||||||
|
)
|
||||||
|
},
|
||||||
|
value = fire?.skills?.get(skill.name) ?: 0,
|
||||||
|
max = skill.amount,
|
||||||
|
haveDetail = description?.description != null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,7 @@ import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
import androidx.compose.material.ModalBottomSheetState
|
import androidx.compose.material.ModalBottomSheetState
|
||||||
|
import androidx.compose.material.minimumInteractiveComponentSize
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
|
|
@ -39,7 +40,7 @@ import com.pixelized.rplexicon.ui.screens.character.composable.actions.Spell
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeader
|
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeader
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeaderUio
|
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeaderUio
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio
|
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.rememberTokenListStatePreview
|
import com.pixelized.rplexicon.ui.screens.character.composable.actions.rememberSkillsListStatePreview
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberAttackListStatePreview
|
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberAttackListStatePreview
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberObjectListStatePreview
|
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberObjectListStatePreview
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberSpellListStatePreview
|
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberSpellListStatePreview
|
||||||
|
|
@ -63,7 +64,7 @@ fun ActionPage(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
attacks = attacksViewModel.attacks,
|
attacks = attacksViewModel.attacks,
|
||||||
objects = objectsViewModel.objects,
|
objects = objectsViewModel.objects,
|
||||||
tokens = skillViewModel.skills,
|
skills = skillViewModel.skills,
|
||||||
spells = spellsViewModel.spells,
|
spells = spellsViewModel.spells,
|
||||||
onAttackHit = { id ->
|
onAttackHit = { id ->
|
||||||
attacksViewModel.onHitRoll(id)?.let {
|
attacksViewModel.onHitRoll(id)?.let {
|
||||||
|
|
@ -146,7 +147,7 @@ fun ActionsPageContent(
|
||||||
lazyListState: LazyListState = rememberLazyListState(),
|
lazyListState: LazyListState = rememberLazyListState(),
|
||||||
attacks: State<List<AttackUio>>,
|
attacks: State<List<AttackUio>>,
|
||||||
objects: State<List<ObjectItemUio>>,
|
objects: State<List<ObjectItemUio>>,
|
||||||
tokens: State<List<SkillItemUio>>,
|
skills: State<List<SkillItemUio>>,
|
||||||
spells: State<List<Pair<SpellHeaderUio, List<SpellUio>>>>,
|
spells: State<List<Pair<SpellHeaderUio, List<SpellUio>>>>,
|
||||||
onAttackHit: (id: String) -> Unit,
|
onAttackHit: (id: String) -> Unit,
|
||||||
onAttackDamage: (id: String) -> Unit,
|
onAttackDamage: (id: String) -> Unit,
|
||||||
|
|
@ -204,14 +205,15 @@ fun ActionsPageContent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokens.value.isNotEmpty()) {
|
if (skills.value.isNotEmpty()) {
|
||||||
stickyHeader {
|
stickyHeader {
|
||||||
GenericHeader(
|
GenericHeader(
|
||||||
label = R.string.character_sheet_title_skills,
|
label = R.string.character_sheet_title_skills,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
items(items = tokens.value) {
|
items(items = skills.value) {
|
||||||
SkillItem(
|
SkillItem(
|
||||||
|
modifier = Modifier.minimumInteractiveComponentSize(),
|
||||||
skill = it,
|
skill = it,
|
||||||
onInfo = onSkillInfo,
|
onInfo = onSkillInfo,
|
||||||
onThrow = onSkillThrow,
|
onThrow = onSkillThrow,
|
||||||
|
|
@ -259,7 +261,7 @@ fun ActionPagePreview() {
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
attacks = rememberAttackListStatePreview(),
|
attacks = rememberAttackListStatePreview(),
|
||||||
objects = rememberObjectListStatePreview(),
|
objects = rememberObjectListStatePreview(),
|
||||||
tokens = rememberTokenListStatePreview(),
|
skills = rememberSkillsListStatePreview(),
|
||||||
spells = rememberSpellListStatePreview(),
|
spells = rememberSpellListStatePreview(),
|
||||||
onAttackHit = { },
|
onAttackHit = { },
|
||||||
onAttackDamage = { },
|
onAttackDamage = { },
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,9 @@ import androidx.lifecycle.AndroidViewModel
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.pixelized.rplexicon.data.model.CharacterSheet
|
import com.pixelized.rplexicon.data.model.CharacterSheet
|
||||||
import com.pixelized.rplexicon.data.network.CharacterSheetFire
|
|
||||||
import com.pixelized.rplexicon.data.model.DiceThrow
|
import com.pixelized.rplexicon.data.model.DiceThrow
|
||||||
import com.pixelized.rplexicon.data.model.Property
|
|
||||||
import com.pixelized.rplexicon.data.model.Skill
|
import com.pixelized.rplexicon.data.model.Skill
|
||||||
|
import com.pixelized.rplexicon.data.network.CharacterSheetFire
|
||||||
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
|
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
|
||||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
|
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
|
||||||
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
|
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
|
||||||
|
|
@ -18,8 +17,7 @@ import com.pixelized.rplexicon.data.repository.character.SkillRepository
|
||||||
import com.pixelized.rplexicon.ui.composable.edit.SkillEditDialogUio
|
import com.pixelized.rplexicon.ui.composable.edit.SkillEditDialogUio
|
||||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
|
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SkillItemUio
|
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SkillItemUio
|
||||||
import com.pixelized.rplexicon.utilitary.extentions.icon
|
import com.pixelized.rplexicon.ui.screens.character.factory.SkillFactoryUioFactory
|
||||||
import com.pixelized.rplexicon.utilitary.extentions.modifier
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
|
@ -30,9 +28,10 @@ import javax.inject.Inject
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class SkillsViewModel @Inject constructor(
|
class SkillsViewModel @Inject constructor(
|
||||||
private val sheetRepository: CharacterSheetRepository,
|
private val sheetRepository: CharacterSheetRepository,
|
||||||
private val skillRepository: SkillRepository,
|
|
||||||
private val firebaseRepository: FirebaseRepository,
|
private val firebaseRepository: FirebaseRepository,
|
||||||
|
private val skillRepository: SkillRepository,
|
||||||
private val descriptionRepository: DescriptionRepository,
|
private val descriptionRepository: DescriptionRepository,
|
||||||
|
private val skillFactory: SkillFactoryUioFactory,
|
||||||
application: Application,
|
application: Application,
|
||||||
savedStateHandle: SavedStateHandle,
|
savedStateHandle: SavedStateHandle,
|
||||||
) : AndroidViewModel(application) {
|
) : AndroidViewModel(application) {
|
||||||
|
|
@ -50,48 +49,23 @@ class SkillsViewModel @Inject constructor(
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
|
val data = SkillStruct()
|
||||||
sheetRepository.data
|
sheetRepository.data
|
||||||
.combine(skillRepository.skills) { sheets, skills ->
|
.combine(skillRepository.skills) { sheets, skills ->
|
||||||
Struct(sheet = sheets[character], skill = skills[character] ?: emptyList())
|
data.sheet = sheets[character]
|
||||||
|
data.skill = skills[character] ?: emptyList()
|
||||||
}
|
}
|
||||||
.combine(firebaseRepository.getCharacter(character = character)) { data, fire ->
|
.combine(firebaseRepository.getCharacter(character = character)) { _, fire ->
|
||||||
data.apply { this.fire = fire }
|
data.fire = fire
|
||||||
}
|
}
|
||||||
.collect { data ->
|
.collect {
|
||||||
val (character, values, fire) = data
|
val (character, fire, values) = data
|
||||||
|
// Filter out passive skills, theses are display in the Proficiency Page.
|
||||||
val skills = values.map { skill ->
|
val skills = skillFactory.convert(
|
||||||
val description = descriptionRepository.find(name = skill.name)
|
character = character,
|
||||||
val modifier = skill.effect?.modifier?.sumOf {
|
fire = fire,
|
||||||
when (it) {
|
skills = values.filter { it.passive.not() }
|
||||||
Property.LEVEL -> character?.level ?: 0
|
)
|
||||||
Property.PROFICIENCY -> character?.proficiency ?: 0
|
|
||||||
Property.STRENGTH -> character?.strength?.modifier ?: 0
|
|
||||||
Property.DEXTERITY -> character?.dexterity?.modifier ?: 0
|
|
||||||
Property.CONSTITUTION -> character?.constitution?.modifier ?: 0
|
|
||||||
Property.INTELLIGENCE -> character?.intelligence?.modifier ?: 0
|
|
||||||
Property.WISDOM -> character?.wisdom?.modifier ?: 0
|
|
||||||
Property.CHARISMA -> character?.charisma?.modifier ?: 0
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
} ?: 0
|
|
||||||
SkillItemUio(
|
|
||||||
label = skill.name,
|
|
||||||
translate = description?.original,
|
|
||||||
rest = skill.rest,
|
|
||||||
cost = skill.cost,
|
|
||||||
effect = skill.effect?.let {
|
|
||||||
SkillItemUio.Dice(
|
|
||||||
icon = it.faces.icon,
|
|
||||||
label = "${skill.effect.amount}d${skill.effect.faces}${if (modifier > 0) "+$modifier" else ""}",
|
|
||||||
)
|
|
||||||
},
|
|
||||||
value = fire?.skills?.get(skill.name) ?: 0,
|
|
||||||
max = skill.amount,
|
|
||||||
haveDetail = description?.description != null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
_skills.value = skills
|
_skills.value = skills
|
||||||
}
|
}
|
||||||
|
|
@ -140,9 +114,9 @@ class SkillsViewModel @Inject constructor(
|
||||||
hideSkillEditDialog()
|
hideSkillEditDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Struct(
|
private data class SkillStruct(
|
||||||
val sheet: CharacterSheet?,
|
var sheet: CharacterSheet? = null,
|
||||||
val skill: List<Skill>,
|
var fire: CharacterSheetFire? = null,
|
||||||
var fire: CharacterSheetFire? = null
|
var skill: List<Skill> = emptyList(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -7,8 +7,10 @@ import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.IntrinsicSize
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.sizeIn
|
import androidx.compose.foundation.layout.sizeIn
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
|
@ -20,6 +22,7 @@ import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
|
@ -38,6 +41,10 @@ import androidx.compose.ui.unit.dp
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import com.pixelized.rplexicon.LocalRollOverlay
|
import com.pixelized.rplexicon.LocalRollOverlay
|
||||||
import com.pixelized.rplexicon.R
|
import com.pixelized.rplexicon.R
|
||||||
|
import com.pixelized.rplexicon.ui.composable.edit.HandleSkillEditDialog
|
||||||
|
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SkillItem
|
||||||
|
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SkillItemUio
|
||||||
|
import com.pixelized.rplexicon.ui.screens.character.composable.actions.rememberSkillsListStatePreview
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.LabelPointUio
|
import com.pixelized.rplexicon.ui.screens.character.composable.character.LabelPointUio
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.Masteries
|
import com.pixelized.rplexicon.ui.screens.character.composable.character.Masteries
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.MasteriesUio
|
import com.pixelized.rplexicon.ui.screens.character.composable.character.MasteriesUio
|
||||||
|
|
@ -48,6 +55,7 @@ import com.pixelized.rplexicon.ui.screens.character.composable.character.Profici
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.Stat
|
import com.pixelized.rplexicon.ui.screens.character.composable.character.Stat
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.StatUio
|
import com.pixelized.rplexicon.ui.screens.character.composable.character.StatUio
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberCharacterSheetStatePreview
|
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberCharacterSheetStatePreview
|
||||||
|
import com.pixelized.rplexicon.ui.screens.character.pages.actions.HandleSkillDetailDialog
|
||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||||
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
|
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
|
||||||
|
|
||||||
|
|
@ -72,6 +80,7 @@ fun ProficiencyPage(
|
||||||
ProficiencyPageContent(
|
ProficiencyPageContent(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
sheet = sheet,
|
sheet = sheet,
|
||||||
|
passives = viewModel.skills,
|
||||||
onStats = { stat ->
|
onStats = { stat ->
|
||||||
overlay.prepareRoll(diceThrow = viewModel.statRoll(stat.id))
|
overlay.prepareRoll(diceThrow = viewModel.statRoll(stat.id))
|
||||||
overlay.showOverlay()
|
overlay.showOverlay()
|
||||||
|
|
@ -80,6 +89,27 @@ fun ProficiencyPage(
|
||||||
overlay.prepareRoll(diceThrow = viewModel.proficiencyRoll(proficiency.id))
|
overlay.prepareRoll(diceThrow = viewModel.proficiencyRoll(proficiency.id))
|
||||||
overlay.showOverlay()
|
overlay.showOverlay()
|
||||||
},
|
},
|
||||||
|
onSkillCount = {
|
||||||
|
viewModel.showSkillEditDialog(item = it)
|
||||||
|
},
|
||||||
|
onSkillThrow = {
|
||||||
|
overlay.prepareRoll(diceThrow = viewModel.onSkillRoll(it.label))
|
||||||
|
overlay.showOverlay()
|
||||||
|
},
|
||||||
|
onSkillInfo = {
|
||||||
|
viewModel.showSkillDetailDialog(item = it.label)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
HandleSkillEditDialog(
|
||||||
|
dialog = viewModel.skillEditDialog,
|
||||||
|
onDismissRequest = viewModel::hideSkillEditDialog,
|
||||||
|
onConfirm = viewModel::applySkillChange
|
||||||
|
)
|
||||||
|
|
||||||
|
HandleSkillDetailDialog(
|
||||||
|
dialog = viewModel.skillDetailDialog,
|
||||||
|
onDismissRequest = viewModel::hideSkillDetailDialog
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -91,13 +121,17 @@ fun ProficiencyPageContent(
|
||||||
inner: Shape = remember { RoundedCornerShape(size = 8.dp) },
|
inner: Shape = remember { RoundedCornerShape(size = 8.dp) },
|
||||||
outline: Shape = remember { CutCornerShape(size = 16.dp) },
|
outline: Shape = remember { CutCornerShape(size = 16.dp) },
|
||||||
sheet: CharacterSheetUio,
|
sheet: CharacterSheetUio,
|
||||||
|
passives: State<List<SkillItemUio>>,
|
||||||
onStats: (StatUio) -> Unit,
|
onStats: (StatUio) -> Unit,
|
||||||
onProficiencies: (ProficiencyUio) -> Unit,
|
onProficiencies: (ProficiencyUio) -> Unit,
|
||||||
|
onSkillThrow: (SkillItemUio) -> Unit,
|
||||||
|
onSkillCount: (SkillItemUio) -> Unit,
|
||||||
|
onSkillInfo: (SkillItemUio) -> Unit,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.verticalScroll(state = state)
|
.verticalScroll(state = state)
|
||||||
.padding(all = 16.dp),
|
.padding(vertical = 16.dp),
|
||||||
) {
|
) {
|
||||||
ProficiencyLayout(
|
ProficiencyLayout(
|
||||||
inner = inner,
|
inner = inner,
|
||||||
|
|
@ -181,8 +215,22 @@ fun ProficiencyPageContent(
|
||||||
},
|
},
|
||||||
masteries = {
|
masteries = {
|
||||||
Masteries(
|
Masteries(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
masteries = sheet.masteries,
|
masteries = sheet.masteries,
|
||||||
)
|
)
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(top = 8.dp),
|
||||||
|
) {
|
||||||
|
passives.value.forEach {
|
||||||
|
SkillItem(
|
||||||
|
modifier = Modifier.padding(vertical = 4.dp),
|
||||||
|
skill = it,
|
||||||
|
onInfo = onSkillInfo,
|
||||||
|
onThrow = onSkillThrow,
|
||||||
|
onSkill = onSkillCount,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -247,8 +295,9 @@ private fun ProficiencyLayout(
|
||||||
measurePolicy = { measurables, constraints ->
|
measurePolicy = { measurables, constraints ->
|
||||||
val spacingPx = with(density) { spacing.toPx().toInt() }
|
val spacingPx = with(density) { spacing.toPx().toInt() }
|
||||||
val statsWidth = with(density) { 100.dp.toPx().toInt() }
|
val statsWidth = with(density) { 100.dp.toPx().toInt() }
|
||||||
|
val horizontal = with(density) { 16.dp.toPx().toInt() }
|
||||||
|
|
||||||
val proficienciesWidth = constraints.maxWidth - statsWidth - spacingPx
|
val proficienciesWidth = constraints.maxWidth - statsWidth - spacingPx - horizontal * 2
|
||||||
val passivesMeasure = measurables.passives.measure(
|
val passivesMeasure = measurables.passives.measure(
|
||||||
constraints = constraints.copy(
|
constraints = constraints.copy(
|
||||||
minWidth = proficienciesWidth,
|
minWidth = proficienciesWidth,
|
||||||
|
|
@ -291,23 +340,23 @@ private fun ProficiencyLayout(
|
||||||
height = statsMeasure.height + masteriesMeasure.height + passivesMeasure.height + spacingPx * 2,
|
height = statsMeasure.height + masteriesMeasure.height + passivesMeasure.height + spacingPx * 2,
|
||||||
) {
|
) {
|
||||||
statsMeasure.place(
|
statsMeasure.place(
|
||||||
x = 0,
|
x = horizontal,
|
||||||
y = 0,
|
y = 0,
|
||||||
)
|
)
|
||||||
savingThrowsMeasure.place(
|
savingThrowsMeasure.place(
|
||||||
x = statsWidth + spacingPx,
|
x = horizontal + statsWidth + spacingPx,
|
||||||
y = 0,
|
y = 0,
|
||||||
)
|
)
|
||||||
proficienciesMeasure.place(
|
proficienciesMeasure.place(
|
||||||
x = statsWidth + spacingPx,
|
x = horizontal + statsWidth + spacingPx,
|
||||||
y = savingThrowsMeasure.height + spacingPx,
|
y = savingThrowsMeasure.height + spacingPx,
|
||||||
)
|
)
|
||||||
speedMeasure.place(
|
speedMeasure.place(
|
||||||
x = 0,
|
x = horizontal,
|
||||||
y = statsHeight + spacingPx,
|
y = statsHeight + spacingPx,
|
||||||
)
|
)
|
||||||
passivesMeasure.place(
|
passivesMeasure.place(
|
||||||
x = statsWidth + spacingPx,
|
x = horizontal + statsWidth + spacingPx,
|
||||||
y = savingThrowsMeasure.height + proficienciesMeasure.height + spacingPx * 2,
|
y = savingThrowsMeasure.height + proficienciesMeasure.height + spacingPx * 2,
|
||||||
)
|
)
|
||||||
masteriesMeasure.place(
|
masteriesMeasure.place(
|
||||||
|
|
@ -327,16 +376,20 @@ val List<Measurable>.passives get() = first { it.layoutId == "PassivesId" }
|
||||||
val List<Measurable>.masteries get() = first { it.layoutId == "MasteriesId" }
|
val List<Measurable>.masteries get() = first { it.layoutId == "MasteriesId" }
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Preview(uiMode = UI_MODE_NIGHT_NO, heightDp = 1300)
|
@Preview(uiMode = UI_MODE_NIGHT_NO, heightDp = 1500)
|
||||||
@Preview(uiMode = UI_MODE_NIGHT_YES, heightDp = 1300)
|
@Preview(uiMode = UI_MODE_NIGHT_YES, heightDp = 1500)
|
||||||
fun ProficiencyPreview() {
|
fun ProficiencyPreview() {
|
||||||
LexiconTheme {
|
LexiconTheme {
|
||||||
Surface {
|
Surface {
|
||||||
val sheet by rememberCharacterSheetStatePreview()
|
val sheet by rememberCharacterSheetStatePreview()
|
||||||
ProficiencyPageContent(
|
ProficiencyPageContent(
|
||||||
sheet = sheet,
|
sheet = sheet,
|
||||||
|
passives = rememberSkillsListStatePreview(),
|
||||||
onStats = { },
|
onStats = { },
|
||||||
onProficiencies = { },
|
onProficiencies = { },
|
||||||
|
onSkillThrow = { },
|
||||||
|
onSkillCount = { },
|
||||||
|
onSkillInfo = { },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,23 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.lifecycle.AndroidViewModel
|
import androidx.lifecycle.AndroidViewModel
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.pixelized.rplexicon.data.model.CharacterSheet
|
||||||
import com.pixelized.rplexicon.data.model.DiceThrow
|
import com.pixelized.rplexicon.data.model.DiceThrow
|
||||||
|
import com.pixelized.rplexicon.data.model.Skill
|
||||||
|
import com.pixelized.rplexicon.data.network.CharacterSheetFire
|
||||||
|
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
|
||||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
|
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
|
||||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
|
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
|
||||||
|
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
|
||||||
|
import com.pixelized.rplexicon.data.repository.character.SkillRepository
|
||||||
|
import com.pixelized.rplexicon.ui.composable.edit.SkillEditDialogUio
|
||||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
|
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
|
||||||
|
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SkillItemUio
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.ProficiencyUio
|
import com.pixelized.rplexicon.ui.screens.character.composable.character.ProficiencyUio
|
||||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.StatUio
|
import com.pixelized.rplexicon.ui.screens.character.composable.character.StatUio
|
||||||
import com.pixelized.rplexicon.ui.screens.character.factory.CharacterSheetUioFactory
|
import com.pixelized.rplexicon.ui.screens.character.factory.CharacterSheetUioFactory
|
||||||
|
import com.pixelized.rplexicon.ui.screens.character.factory.SkillFactoryUioFactory
|
||||||
|
import com.pixelized.rplexicon.ui.screens.character.pages.actions.SkillDetailUio
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
|
@ -23,8 +33,12 @@ import javax.inject.Inject
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class ProficiencyViewModel @Inject constructor(
|
class ProficiencyViewModel @Inject constructor(
|
||||||
private val characterRepository: CharacterSheetRepository,
|
private val characterRepository: CharacterSheetRepository,
|
||||||
|
private val firebaseRepository: FirebaseRepository,
|
||||||
private val alterationRepository: AlterationRepository,
|
private val alterationRepository: AlterationRepository,
|
||||||
private val characterSheetFactory: CharacterSheetUioFactory,
|
private val characterSheetFactory: CharacterSheetUioFactory,
|
||||||
|
private val skillRepository: SkillRepository,
|
||||||
|
private val descriptionRepository: DescriptionRepository,
|
||||||
|
private val skillFactory: SkillFactoryUioFactory,
|
||||||
savedStateHandle: SavedStateHandle,
|
savedStateHandle: SavedStateHandle,
|
||||||
application: Application,
|
application: Application,
|
||||||
) : AndroidViewModel(application) {
|
) : AndroidViewModel(application) {
|
||||||
|
|
@ -33,27 +47,63 @@ class ProficiencyViewModel @Inject constructor(
|
||||||
private val _sheet = mutableStateOf<CharacterSheetUio?>(null)
|
private val _sheet = mutableStateOf<CharacterSheetUio?>(null)
|
||||||
val sheet: State<CharacterSheetUio?> get() = _sheet
|
val sheet: State<CharacterSheetUio?> get() = _sheet
|
||||||
|
|
||||||
|
private val _skillEditDialog = mutableStateOf<SkillEditDialogUio?>(null)
|
||||||
|
val skillEditDialog: State<SkillEditDialogUio?> get() = _skillEditDialog
|
||||||
|
|
||||||
|
private val _skillDetailDialog = mutableStateOf<SkillDetailUio?>(null)
|
||||||
|
val skillDetailDialog: State<SkillDetailUio?> get() = _skillDetailDialog
|
||||||
|
|
||||||
|
private val _skills = mutableStateOf<List<SkillItemUio>>(emptyList())
|
||||||
|
val skills: State<List<SkillItemUio>> get() = _skills
|
||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch {
|
||||||
characterRepository.data
|
launch(Dispatchers.IO) {
|
||||||
.combine(alterationRepository.assignedAlterations) { sheets, _ -> sheets }
|
characterRepository.data
|
||||||
.collect {
|
.combine(alterationRepository.assignedAlterations) { sheets, _ -> sheets }
|
||||||
val characterSheet = it[character]
|
.collect {
|
||||||
if (characterSheet != null) {
|
val characterSheet = it[character]
|
||||||
val alterations = alterationRepository.getActiveAlterationsStatus(character)
|
if (characterSheet != null) {
|
||||||
val sheet = characterSheetFactory.convert(
|
val alterations =
|
||||||
sheet = characterSheet,
|
alterationRepository.getActiveAlterationsStatus(character)
|
||||||
status = alterations,
|
val sheet = characterSheetFactory.convert(
|
||||||
)
|
sheet = characterSheet,
|
||||||
withContext(Dispatchers.Main) {
|
status = alterations,
|
||||||
_sheet.value = sheet
|
)
|
||||||
}
|
withContext(Dispatchers.Main) {
|
||||||
} else {
|
_sheet.value = sheet
|
||||||
launch {
|
}
|
||||||
characterRepository.fetchCharacterSheet()
|
} else {
|
||||||
|
launch {
|
||||||
|
characterRepository.fetchCharacterSheet()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
|
val data = SkillStruct()
|
||||||
|
characterRepository.data
|
||||||
|
.combine(skillRepository.skills) { sheets, skills ->
|
||||||
|
data.sheet = sheets[character]
|
||||||
|
data.skill = skills[character] ?: emptyList()
|
||||||
|
}
|
||||||
|
.combine(firebaseRepository.getCharacter(character = character)) { _, fire ->
|
||||||
|
data.fire = fire
|
||||||
|
}
|
||||||
|
.collect {
|
||||||
|
val (character, fire, values) = data
|
||||||
|
// Filter out non passive skills.
|
||||||
|
val skills = skillFactory.convert(
|
||||||
|
character = character,
|
||||||
|
fire = fire,
|
||||||
|
skills = values.filter { it.passive }
|
||||||
|
)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
_skills.value = skills
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,4 +142,50 @@ class ProficiencyViewModel @Inject constructor(
|
||||||
ProficiencyUio.ID.STEALTH -> DiceThrow.Stealth(character)
|
ProficiencyUio.ID.STEALTH -> DiceThrow.Stealth(character)
|
||||||
ProficiencyUio.ID.SURVIVAL -> DiceThrow.Survival(character)
|
ProficiencyUio.ID.SURVIVAL -> DiceThrow.Survival(character)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onSkillRoll(name: String): DiceThrow = DiceThrow.Skill(
|
||||||
|
character = character,
|
||||||
|
skill = name,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun showSkillDetailDialog(item: String) {
|
||||||
|
_skillDetailDialog.value = descriptionRepository
|
||||||
|
.find(name = item)
|
||||||
|
?.let { description ->
|
||||||
|
SkillDetailUio(
|
||||||
|
name = item,
|
||||||
|
original = description.original,
|
||||||
|
description = description.description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideSkillDetailDialog() {
|
||||||
|
_skillDetailDialog.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showSkillEditDialog(item: SkillItemUio) {
|
||||||
|
if (item.max != null) {
|
||||||
|
_skillEditDialog.value = SkillEditDialogUio(
|
||||||
|
label = item.label,
|
||||||
|
value = item.value ?: 0,
|
||||||
|
max = item.max,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideSkillEditDialog() {
|
||||||
|
_skillEditDialog.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun applySkillChange(id: String, value: Int) {
|
||||||
|
firebaseRepository.setSkill(character = character, name = id, value = value)
|
||||||
|
hideSkillEditDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class SkillStruct(
|
||||||
|
var sheet: CharacterSheet? = null,
|
||||||
|
var fire: CharacterSheetFire? = null,
|
||||||
|
var skill: List<Skill> = emptyList(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue