Add spacial resource into CharacterSheet header.
This commit is contained in:
parent
8c1d83402c
commit
75644aad91
14 changed files with 246 additions and 33 deletions
|
|
@ -1,11 +1,13 @@
|
|||
package com.pixelized.rplexicon.data.model
|
||||
|
||||
import com.pixelized.rplexicon.R
|
||||
|
||||
data class CharacterSheet(
|
||||
val name: String,
|
||||
val race: String?,
|
||||
val proficiency: Int, // Bonus de maîtrise
|
||||
val level: Int, // Niveau
|
||||
val characterClass: String, // Classe
|
||||
val characterClass: List<Class>, // Classe
|
||||
val hitPoint: Int, // Point de vie MAX
|
||||
val spell1: Int?, // level 1 spell slot
|
||||
val spell2: Int?, // level 2 spell slot
|
||||
|
|
@ -53,9 +55,36 @@ data class CharacterSheet(
|
|||
val languages: List<String>, // languages masteries
|
||||
val others: List<String>, // others masteries
|
||||
) {
|
||||
val isWarlock: Boolean get() = characterClass.contains(CLASS_WARLOCK)
|
||||
val isWarlock: Boolean get() = characterClass.contains(Class.WARLOCK)
|
||||
|
||||
companion object {
|
||||
const val CLASS_WARLOCK = "Occultiste"
|
||||
enum class Class(
|
||||
val value: String,
|
||||
val resource: String? = null,
|
||||
val label: Int? = null,
|
||||
) {
|
||||
BARBARIAN(
|
||||
value = "Barbare",
|
||||
resource = "Rage",
|
||||
label = R.string.character_sheet_title_rage
|
||||
),
|
||||
BARD(
|
||||
value = "Barde",
|
||||
resource = "Inspiration bardique",
|
||||
label = R.string.character_sheet_title_inspiration
|
||||
),
|
||||
CLERIC(
|
||||
value = "Clerc",
|
||||
resource = "Conduit divin",
|
||||
label = R.string.character_sheet_title_conduit
|
||||
),
|
||||
DRUID(value = "Druide"),
|
||||
FIGHTER(value = "Guerrier"),
|
||||
MONK(value = "Moine"),
|
||||
PALADIN(value = "Paladin"),
|
||||
RANGER(value = "Rodeur"),
|
||||
ROGUE(value = "Roublard"),
|
||||
SORCERER(value = "Ensorceleur"),
|
||||
WARLOCK(value = "Occultiste"),
|
||||
WIZARD(value = "Magicien"),
|
||||
}
|
||||
}
|
||||
|
|
@ -25,7 +25,9 @@ class AlterationParser @Inject constructor(
|
|||
|
||||
sheet.forEachRowIndexed { index, row ->
|
||||
when (index) {
|
||||
0 -> updateStructure(row = row, columns = COLUMNS + characterSheets.map { column(it.name) })
|
||||
0 -> updateStructure(
|
||||
row = row,
|
||||
columns = COLUMNS + characterSheets.map { column(it.name) })
|
||||
|
||||
else -> {
|
||||
// Assume that the name is the first column.
|
||||
|
|
@ -56,7 +58,7 @@ class AlterationParser @Inject constructor(
|
|||
characterSheets
|
||||
.filter { // check if the alteration is applicable to the character
|
||||
alteration.target.let { target ->
|
||||
target == ALL || target == it.characterClass || target == it.race || target == it.name
|
||||
target == ALL || it.characterClass.any { it.value == target } || target == it.race || target == it.name
|
||||
}
|
||||
}
|
||||
.forEach { // check the default alteration state for that character
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
package com.pixelized.rplexicon.data.parser.characterSheet
|
||||
|
||||
import com.pixelized.rplexicon.data.model.CharacterSheet
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class CharacterClassParser @Inject constructor() {
|
||||
|
||||
fun parse(value: String?): List<CharacterSheet.Class> {
|
||||
return value
|
||||
?.split(",")
|
||||
?.map { it.trim() }
|
||||
?.mapNotNull {
|
||||
when (it) {
|
||||
CharacterSheet.Class.BARBARIAN.value -> CharacterSheet.Class.BARBARIAN
|
||||
CharacterSheet.Class.BARD.value -> CharacterSheet.Class.BARD
|
||||
CharacterSheet.Class.CLERIC.value -> CharacterSheet.Class.CLERIC
|
||||
CharacterSheet.Class.DRUID.value -> CharacterSheet.Class.DRUID
|
||||
CharacterSheet.Class.FIGHTER.value -> CharacterSheet.Class.FIGHTER
|
||||
CharacterSheet.Class.MONK.value -> CharacterSheet.Class.MONK
|
||||
CharacterSheet.Class.PALADIN.value -> CharacterSheet.Class.PALADIN
|
||||
CharacterSheet.Class.RANGER.value -> CharacterSheet.Class.RANGER
|
||||
CharacterSheet.Class.ROGUE.value -> CharacterSheet.Class.ROGUE
|
||||
CharacterSheet.Class.SORCERER.value -> CharacterSheet.Class.SORCERER
|
||||
CharacterSheet.Class.WARLOCK.value -> CharacterSheet.Class.WARLOCK
|
||||
CharacterSheet.Class.WIZARD.value -> CharacterSheet.Class.WIZARD
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
?: emptyList()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,17 @@
|
|||
package com.pixelized.rplexicon.data.parser
|
||||
package com.pixelized.rplexicon.data.parser.characterSheet
|
||||
|
||||
import com.google.api.services.sheets.v4.model.ValueRange
|
||||
import com.pixelized.rplexicon.data.model.CharacterSheet
|
||||
import com.pixelized.rplexicon.data.parser.column
|
||||
import com.pixelized.rplexicon.data.parser.parserScope
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class CharacterSheetParser @Inject constructor() {
|
||||
|
||||
class CharacterSheetParser @Inject constructor(
|
||||
private val classParser: CharacterClassParser,
|
||||
) {
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun parse(value: ValueRange): Map<String, CharacterSheet> = parserScope {
|
||||
// fetch the character sheet
|
||||
|
|
@ -34,7 +37,7 @@ class CharacterSheetParser @Inject constructor() {
|
|||
race = item.parse(column = RACE),
|
||||
proficiency = item.parseInt(column = MASTERY) ?: 2,
|
||||
level = item.parseInt(column = LEVEL) ?: 2,
|
||||
characterClass = item.parse(column = CLASS) ?: "",
|
||||
characterClass = classParser.parse(value = item.parse(column = CLASS)),
|
||||
hitPoint = item.parseInt(column = MAX_HIT_POINT) ?: 1,
|
||||
spell1 = item.parseInt(column = SPELL_LEVEL_1),
|
||||
spell2 = item.parseInt(column = SPELL_LEVEL_2),
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package com.pixelized.rplexicon.data.repository.character
|
||||
|
||||
import com.pixelized.rplexicon.data.model.CharacterSheet
|
||||
import com.pixelized.rplexicon.data.parser.CharacterSheetParser
|
||||
import com.pixelized.rplexicon.data.parser.characterSheet.CharacterSheetParser
|
||||
import com.pixelized.rplexicon.data.repository.CharacterBinder
|
||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
|
||||
import com.pixelized.rplexicon.utilitary.Update
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class SkillRepository @Inject constructor(
|
|||
var lastSuccessFullUpdate: Update = Update.INITIAL
|
||||
private set
|
||||
|
||||
fun find(character: String, skill: String): Skill? {
|
||||
fun find(character: String, skill: String?): Skill? {
|
||||
return skills.value[character]?.firstOrNull { it.name == skill }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,8 +74,6 @@ import com.pixelized.rplexicon.ui.screens.character.CharacterTabUio.Inventory
|
|||
import com.pixelized.rplexicon.ui.screens.character.CharacterTabUio.Proficiency
|
||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeader
|
||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeaderUio
|
||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.ProficiencyUio.ID.*
|
||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.StatUio.ID.*
|
||||
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberCharacterHeaderStatePreview
|
||||
import com.pixelized.rplexicon.ui.screens.character.pages.actions.ActionPage
|
||||
import com.pixelized.rplexicon.ui.screens.character.pages.actions.ActionPagePreview
|
||||
|
|
@ -157,6 +155,9 @@ fun CharacterSheetScreen(
|
|||
scope.launch { pagerState.animateScrollToPage(it) }
|
||||
},
|
||||
onHitPoint = headerViewModel::toggleHitPointDialog,
|
||||
onResource = {
|
||||
// TODO()
|
||||
},
|
||||
onDeathRoll = {
|
||||
overlay.prepareRoll(diceThrow = headerViewModel.onDeathThrow())
|
||||
overlay.showOverlay()
|
||||
|
|
@ -260,6 +261,7 @@ private fun CharacterSheetContent(
|
|||
tabs: State<List<CharacterTabUio>>,
|
||||
header: State<CharacterSheetHeaderUio?>,
|
||||
onHitPoint: () -> Unit,
|
||||
onResource: () -> Unit,
|
||||
onDeathRoll: () -> Unit,
|
||||
onDeathSuccess: () -> Unit,
|
||||
onDeathFailure: () -> Unit,
|
||||
|
|
@ -360,6 +362,7 @@ private fun CharacterSheetContent(
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
header = header,
|
||||
onHitPoint = onHitPoint,
|
||||
onResource = onResource,
|
||||
onDeathRoll = onDeathRoll,
|
||||
onDeathSuccess = onDeathSuccess,
|
||||
onDeathFailure = onDeathFailure,
|
||||
|
|
@ -501,6 +504,7 @@ private fun CharacterScreenPreview(
|
|||
onFullRefresh = { },
|
||||
loader = { },
|
||||
onHitPoint = { },
|
||||
onResource = { },
|
||||
onDeathRoll = { },
|
||||
onDeathSuccess = { },
|
||||
onDeathFailure = { },
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ data class CharacterSheetHeaderUio(
|
|||
val hitPoint: LabelPointUio,
|
||||
val speed: LabelPointUio,
|
||||
val dC: LabelPointUio?,
|
||||
val resource: ResourcePointUio?,
|
||||
val death: DeathThrowUio? = null
|
||||
)
|
||||
|
||||
|
|
@ -36,6 +37,7 @@ fun CharacterSheetHeader(
|
|||
padding: PaddingValues = PaddingValues(start = 16.dp, end = 16.dp, bottom = 4.dp),
|
||||
header: State<CharacterSheetHeaderUio?>,
|
||||
onHitPoint: () -> Unit,
|
||||
onResource: () -> Unit,
|
||||
onDeathRoll: () -> Unit,
|
||||
onDeathSuccess: () -> Unit,
|
||||
onDeathFailure: () -> Unit,
|
||||
|
|
@ -55,6 +57,9 @@ fun CharacterSheetHeader(
|
|||
alignment = Alignment.CenterHorizontally
|
||||
),
|
||||
) {
|
||||
header.value?.resource?.let {
|
||||
ResourcePoint(label = it, onClick = onResource)
|
||||
}
|
||||
header.value?.armorClass?.let {
|
||||
LabelPoint(label = it)
|
||||
}
|
||||
|
|
@ -95,6 +100,7 @@ private fun CharacterSheetHeaderPreview() {
|
|||
death = rememberDeathThrowUio(),
|
||||
),
|
||||
onHitPoint = { },
|
||||
onResource = { },
|
||||
onDeathRoll = { },
|
||||
onDeathSuccess = { },
|
||||
onDeathFailure = { },
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
package com.pixelized.rplexicon.ui.screens.character.composable.character
|
||||
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.rplexicon.R
|
||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||
|
||||
@Stable
|
||||
data class ResourcePointUio(
|
||||
val label: Int?,
|
||||
val value: String?,
|
||||
val max: String? = null,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun ResourcePoint(
|
||||
modifier: Modifier = Modifier,
|
||||
labelStyle: TextStyle = MaterialTheme.typography.labelSmall,
|
||||
valueStyle: TextStyle = MaterialTheme.typography.headlineSmall,
|
||||
maxStyle: TextStyle = MaterialTheme.typography.titleSmall,
|
||||
label: ResourcePointUio,
|
||||
onClick: (() -> Unit)? = null,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(bounded = false),
|
||||
enabled = onClick != null, onClick = { onClick?.invoke() }
|
||||
)
|
||||
.then(other = modifier),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
label.label?.let {
|
||||
Text(
|
||||
style = labelStyle,
|
||||
fontWeight = FontWeight.Light,
|
||||
text = stringResource(id = it),
|
||||
)
|
||||
}
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = valueStyle,
|
||||
color = when (onClick) {
|
||||
null -> MaterialTheme.colorScheme.onSurface
|
||||
else -> MaterialTheme.colorScheme.primary
|
||||
},
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = label.value ?: "0"
|
||||
)
|
||||
label.max?.let {
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = maxStyle,
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = UI_MODE_NIGHT_NO)
|
||||
@Preview(uiMode = UI_MODE_NIGHT_YES)
|
||||
private fun LabelPointPreview() {
|
||||
LexiconTheme {
|
||||
Surface {
|
||||
ResourcePoint(
|
||||
label = ResourcePointUio(
|
||||
label = R.string.character_sheet_title_inspiration,
|
||||
value = "2",
|
||||
max = "/ 2",
|
||||
),
|
||||
onClick = { },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import com.pixelized.rplexicon.R
|
|||
import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeaderUio
|
||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.DeathThrowUio
|
||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.LabelPointUio
|
||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.ResourcePointUio
|
||||
|
||||
@Composable
|
||||
@Stable
|
||||
|
|
@ -34,6 +35,11 @@ fun rememberCharacterHeaderStatePreview(
|
|||
label = R.string.character_sheet_title_dc,
|
||||
value = "13",
|
||||
),
|
||||
resource = ResourcePointUio(
|
||||
label = R.string.character_sheet_title_rage,
|
||||
value = "2",
|
||||
max = "/ 2",
|
||||
),
|
||||
death = death,
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.pixelized.rplexicon.R
|
|||
import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeaderUio
|
||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.DeathThrowUio
|
||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.LabelPointUio
|
||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.ResourcePointUio
|
||||
import com.pixelized.rplexicon.ui.screens.character.pages.actions.HeaderViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -35,6 +36,15 @@ class CharacterSheetHeaderUioFactory @Inject constructor() {
|
|||
value = "$it",
|
||||
)
|
||||
},
|
||||
resource = if (sheetHeaderData?.resourceMax != null) {
|
||||
ResourcePointUio(
|
||||
label = sheetHeaderData.resourceLabel,
|
||||
value = "${fireHeaderData?.resource ?: 0}",
|
||||
max = "/ ${sheetHeaderData.resourceMax}"
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
death = if (fireHeaderData?.hp == 0) {
|
||||
DeathThrowUio(
|
||||
success = fireHeaderData.deathSuccess,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.pixelized.rplexicon.data.model.Property
|
|||
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
|
||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
|
||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
|
||||
import com.pixelized.rplexicon.data.repository.character.SkillRepository
|
||||
import com.pixelized.rplexicon.ui.composable.edit.HpPointDialogUio
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
|
||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeaderUio
|
||||
|
|
@ -30,6 +31,7 @@ class HeaderViewModel @Inject constructor(
|
|||
private val firebaseRepository: FirebaseRepository,
|
||||
characterRepository: CharacterSheetRepository,
|
||||
alterationRepository: AlterationRepository,
|
||||
skillRepository: SkillRepository,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel() {
|
||||
val character = savedStateHandle.characterSheetArgument.name
|
||||
|
|
@ -51,18 +53,24 @@ class HeaderViewModel @Inject constructor(
|
|||
viewModelScope.launch {
|
||||
launch(context = Dispatchers.IO) {
|
||||
characterRepository.data
|
||||
.combine(alterationRepository.assignedAlterations) { sheets, _ -> sheets }
|
||||
.collect { sheets ->
|
||||
val character = sheets[character]
|
||||
if (character != null) {
|
||||
.combine(skillRepository.skills) { sheets, _ -> sheets[character] }
|
||||
.combine(alterationRepository.assignedAlterations) { sheet, _ -> sheet }
|
||||
.collect { sheet ->
|
||||
if (sheet != null) {
|
||||
val alterations = alterationRepository.getActiveAlterationsStatus(
|
||||
character = character.name,
|
||||
character = sheet.name,
|
||||
)
|
||||
val resource = sheet.characterClass.firstOrNull()
|
||||
val data = SheetHeaderData(
|
||||
hpMax = character.hitPoint + alterations[Property.HIT_POINT].sum,
|
||||
speed = character.speed,
|
||||
ca = character.armorClass + alterations[Property.ARMOR_CLASS].sum,
|
||||
dc = character.dC,
|
||||
hpMax = sheet.hitPoint + alterations[Property.HIT_POINT].sum,
|
||||
resourceLabel = resource?.label,
|
||||
resourceMax = skillRepository.find(
|
||||
character = character,
|
||||
skill = resource?.resource,
|
||||
)?.amount,
|
||||
speed = sheet.speed,
|
||||
ca = sheet.armorClass + alterations[Property.ARMOR_CLASS].sum,
|
||||
dc = sheet.dC,
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
sheetData.value = data
|
||||
|
|
@ -73,17 +81,21 @@ class HeaderViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
launch(context = Dispatchers.IO) {
|
||||
firebaseRepository.getCharacter(character = character).collect { sheets ->
|
||||
val data = FireHeaderData(
|
||||
hp = sheets.hitPoint?.value ?: 1,
|
||||
extra = sheets.hitPoint?.additional ?: 0,
|
||||
deathSuccess = sheets.death?.success ?: 0,
|
||||
deathFailure = sheets.death?.failure ?: 0,
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
fireData.value = data
|
||||
characterRepository.data
|
||||
.combine(firebaseRepository.getCharacter(character = character)) { sheets, fire -> sheets[character] to fire }
|
||||
.collect {
|
||||
val (sheet, fire) = it
|
||||
val data = FireHeaderData(
|
||||
hp = fire.hitPoint?.value ?: 1,
|
||||
resource = fire.skills[sheet?.characterClass?.firstOrNull()?.resource],
|
||||
extra = fire.hitPoint?.additional ?: 0,
|
||||
deathSuccess = fire.death?.success ?: 0,
|
||||
deathFailure = fire.death?.failure ?: 0,
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
fireData.value = data
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -141,6 +153,8 @@ class HeaderViewModel @Inject constructor(
|
|||
@Stable
|
||||
data class SheetHeaderData(
|
||||
val hpMax: Int,
|
||||
val resourceLabel: Int?,
|
||||
val resourceMax: Int?,
|
||||
val speed: Int,
|
||||
val ca: Int,
|
||||
val dc: Int?,
|
||||
|
|
@ -149,6 +163,7 @@ class HeaderViewModel @Inject constructor(
|
|||
@Stable
|
||||
data class FireHeaderData(
|
||||
val hp: Int,
|
||||
val resource: Int?,
|
||||
val extra: Int,
|
||||
val deathSuccess: Int,
|
||||
val deathFailure: Int,
|
||||
|
|
|
|||
|
|
@ -88,6 +88,9 @@
|
|||
<string name="character_sheet_title_ca">CA</string>
|
||||
<string name="character_sheet_title_dc">DD</string>
|
||||
<string name="character_sheet_title_speed">Vitesse</string>
|
||||
<string name="character_sheet_title_rage">Rage</string>
|
||||
<string name="character_sheet_title_inspiration">Inspiration</string>
|
||||
<string name="character_sheet_title_conduit">Conduit Divin</string>
|
||||
<string name="character_sheet_title_initiative">Initiative</string>
|
||||
<string name="character_sheet_title_saving_throws">Jet de sauvegarde</string>
|
||||
<string name="character_sheet_title_proficiencies">Talents</string>
|
||||
|
|
|
|||
|
|
@ -96,6 +96,9 @@
|
|||
<string name="character_sheet_title_ca">CA</string>
|
||||
<string name="character_sheet_title_dc">DC</string>
|
||||
<string name="character_sheet_title_speed">Speed</string>
|
||||
<string name="character_sheet_title_rage">Rage</string>
|
||||
<string name="character_sheet_title_inspiration">Inspiration</string>
|
||||
<string name="character_sheet_title_conduit">Divine conduit</string>
|
||||
<string name="character_sheet_title_initiative">Initiative</string>
|
||||
<string name="character_sheet_title_saving_throws">Saving Throws</string>
|
||||
<string name="character_sheet_title_proficiencies">Proficiencies</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue