Completed ability editor
This commit is contained in:
parent
308c2974f1
commit
1de2439a8a
BIN
db.sqlite-shm
BIN
db.sqlite-shm
Binary file not shown.
BIN
db.sqlite-wal
BIN
db.sqlite-wal
Binary file not shown.
|
|
@ -26,6 +26,18 @@ const mainStatTexts: Record<MainStat, string> = {
|
|||
"charisma": "Charisme",
|
||||
"psyche": "Psyché",
|
||||
}
|
||||
|
||||
function abilitySpecialFeatures(type: "points" | "max", curiosity: DoubleIndex<TrainingLevel>[], value: number): number
|
||||
{
|
||||
if(type === 'points')
|
||||
{
|
||||
if(curiosity.find(e => e[0] == 7 && e[1] === 0))
|
||||
return Math.max(6, value);
|
||||
if(curiosity.find(e => e[0] == 7 && e[1] === 2))
|
||||
return value + 1;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
</script>
|
||||
<script setup lang="ts">
|
||||
import { Icon } from '@iconify/vue/dist/iconify.js';
|
||||
|
|
@ -71,11 +83,11 @@ const trainingPoints = computed(() => {
|
|||
});
|
||||
const training = computed(() => Object.entries(characterConfig.training).map(e => [e[0], getFeaturesOf(e[0] as MainStat, data.value.progress.training[e[0] as MainStat])]) as [MainStat, TrainingOption[]][])
|
||||
const maxTraining = computed(() => Object.entries(data.value.progress.training).reduce((p, v) => { p[v[0]] = v[1].reduce((_p, _v) => Math.max(_p, _v[0]) , 0); return p; }, {} as Record<MainStat, number>));
|
||||
const trainingSpent = computed(() => Object.values(maxTraining.value).reduce((p, v) => p + v));
|
||||
const modifiers = computed(() => Object.entries(maxTraining.value).reduce((p, v) => { p[v[0]] = Math.floor(v[1] / 3) + (data.value.progress.modifiers ? data.value.progress.modifiers[v[0]] : 0); return p; }, {} as Record<MainStat, number>))
|
||||
const trainingSpent = computed(() => Object.values(maxTraining.value).reduce((p, v) => p + v, 0));
|
||||
const modifiers = computed(() => Object.entries(maxTraining.value).reduce((p, v) => { p[v[0]] = Math.floor(v[1] / 3) + (data.value.progress.modifiers ? (data.value.progress.modifiers[v[0] as MainStat] ?? 0) : 0); return p; }, {} as Record<MainStat, number>))
|
||||
const abilityPoints = computed(() => training.value.flatMap(e => e[1].filter(_e => _e.ability !== undefined)).reduce((p, v) => p + v.ability!, 0));
|
||||
const abilityMax = computed(() => Object.entries(characterConfig.ability).reduce((p, v) => { p[v[0]] = Math.floor(maxTraining.value[v[1].max[0]] / 3) + Math.floor(maxTraining.value[v[1].max[1]] / 3); return p; }, {} as Record<Ability, number>));
|
||||
const abilitySpent = computed(() => Object.values(data.value.progress.abilities ?? {}).reduce((p, v) => p + v[1], 0));
|
||||
const abilityMax = computed(() => Object.entries(characterConfig.ability).reduce((p, v) => { p[v[0]] = abilitySpecialFeatures("max", data.value.progress.training.curiosity, Math.floor(maxTraining.value[v[1].max[0]] / 3) + Math.floor(maxTraining.value[v[1].max[1]] / 3)); return p; }, {} as Record<Ability, number>));
|
||||
const abilitySpent = computed(() => Object.values(data.value.progress.abilities ?? {}).reduce((p, v) => p + v[0], 0));
|
||||
|
||||
if(id !== 'new')
|
||||
{
|
||||
|
|
@ -167,6 +179,11 @@ function updateLevel()
|
|||
}
|
||||
async function save(leave: boolean)
|
||||
{
|
||||
if(data.value.name === '' || data.value.progress.race.index === undefined || data.value.progress.race.index === -1)
|
||||
{
|
||||
add({ title: 'Données manquantes', content: "Merci de saisir un nom et une race avant de pouvoir enregistrer votre personnage", type: 'error', duration: 25000, timer: true });
|
||||
return;
|
||||
}
|
||||
if(id === 'new')
|
||||
{
|
||||
id = await useRequestFetch()(`/api/character`, {
|
||||
|
|
@ -263,46 +280,10 @@ useShortcuts({
|
|||
<Icon icon="radix-icons:caret-right" class="w-6 h-6 border border-light-30 dark:border-dark-30 cursor-pointer" @click="() => trainingTab = clamp(trainingTab + 1, 0, 6)" />
|
||||
</div>
|
||||
<div class="flex gap-4 relative" :style="`left: calc(calc(-100% - 1em) * ${trainingTab}); transition: left .5s ease;`">
|
||||
<div class="flex w-full flex-shrink-0 flex-col gap-2 relative">
|
||||
<div class="sticky top-1 left-16 py-1 px-3 bg-light-0 dark:bg-dark-0 z-10 text-xl font-bold self-start border border-light-30 dark:border-dark-30">Force<span v-if="maxTraining.strength >= 0">: Niveau {{ maxTraining.strength }} (+{{ modifiers.strength }})</span></div>
|
||||
<div class="flex flex-row gap-4 justify-center" v-for="(level, index) of characterConfig.training.strength" :class="{ 'opacity-30': index > maxTraining.strength + 1 }">
|
||||
<div class="border border-light-40 dark:border-dark-40 cursor-pointer px-2 py-1 w-1/3" v-for="(option, i) of level" @click="switchTrainingOption('strength', index as TrainingLevel, i)" :class="{ 'hover:border-light-60 dark:hover:border-dark-60': index <= maxTraining.strength + 1, '!border-accent-blue bg-accent-blue bg-opacity-20': index == 0 || (data.progress.training.strength?.some(e => e[0] == index && e[1] === i) ?? false) }"><MarkdownRenderer :proses="{ 'a': PreviewA }" :content="option.description.map(e => e.text).join('\n')" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex w-full flex-shrink-0 flex-col gap-2 relative">
|
||||
<div class="sticky top-1 left-16 py-1 px-3 bg-light-0 dark:bg-dark-0 z-10 text-xl font-bold self-start border border-light-30 dark:border-dark-30">Dextérité<span v-if="maxTraining.dexterity >= 0">: Niveau {{ maxTraining.dexterity }} (+{{ modifiers.dexterity }})</span></div>
|
||||
<div class="flex flex-row gap-4 justify-center" v-for="(level, index) of characterConfig.training.dexterity" :class="{ 'opacity-30': index > maxTraining.dexterity + 1 }">
|
||||
<div class="border border-light-40 dark:border-dark-40 cursor-pointer px-2 py-1 w-1/3" v-for="(option, i) of level" @click="switchTrainingOption('dexterity', index as TrainingLevel, i)" :class="{ 'hover:border-light-60 dark:hover:border-dark-60': index <= maxTraining.dexterity + 1, '!border-accent-blue bg-accent-blue bg-opacity-20': index == 0 || (data.progress.training.dexterity?.some(e => e[0] == index && e[1] === i) ?? false) }"><MarkdownRenderer :proses="{ 'a': PreviewA }" :content="option.description.map(e => e.text).join('\n')" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex w-full flex-shrink-0 flex-col gap-2 relative">
|
||||
<div class="sticky top-1 left-16 py-1 px-3 bg-light-0 dark:bg-dark-0 z-10 text-xl font-bold self-start border border-light-30 dark:border-dark-30">Constitution<span v-if="maxTraining.constitution >= 0">: Niveau {{ maxTraining.constitution }} (+{{ modifiers.constitution }})</span></div>
|
||||
<div class="flex flex-row gap-4 justify-center" v-for="(level, index) of characterConfig.training.constitution" :class="{ 'opacity-30': index > maxTraining.constitution + 1 }">
|
||||
<div class="border border-light-40 dark:border-dark-40 cursor-pointer px-2 py-1 w-1/3" v-for="(option, i) of level" @click="switchTrainingOption('constitution', index as TrainingLevel, i)" :class="{ 'hover:border-light-60 dark:hover:border-dark-60': index <= maxTraining.constitution + 1, '!border-accent-blue bg-accent-blue bg-opacity-20': index == 0 || (data.progress.training.constitution?.some(e => e[0] == index && e[1] === i) ?? false) }"><MarkdownRenderer :proses="{ 'a': PreviewA }" :content="option.description.map(e => e.text).join('\n')" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex w-full flex-shrink-0 flex-col gap-2 relative">
|
||||
<div class="sticky top-1 left-16 py-1 px-3 bg-light-0 dark:bg-dark-0 z-10 text-xl font-bold self-start border border-light-30 dark:border-dark-30">Intelligence<span v-if="maxTraining.intelligence >= 0">: Niveau {{ maxTraining.intelligence }} (+{{ modifiers.intelligence }})</span></div>
|
||||
<div class="flex flex-row gap-4 justify-center" v-for="(level, index) of characterConfig.training.intelligence" :class="{ 'opacity-30': index > maxTraining.intelligence + 1 }">
|
||||
<div class="border border-light-40 dark:border-dark-40 cursor-pointer px-2 py-1 w-1/3" v-for="(option, i) of level" @click="switchTrainingOption('intelligence', index as TrainingLevel, i)" :class="{ 'hover:border-light-60 dark:hover:border-dark-60': index <= maxTraining.intelligence + 1, '!border-accent-blue bg-accent-blue bg-opacity-20': index == 0 || (data.progress.training.intelligence?.some(e => e[0] == index && e[1] === i) ?? false) }"><MarkdownRenderer :proses="{ 'a': PreviewA }" :content="option.description.map(e => e.text).join('\n')" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex w-full flex-shrink-0 flex-col gap-2 relative">
|
||||
<div class="sticky top-1 left-16 py-1 px-3 bg-light-0 dark:bg-dark-0 z-10 text-xl font-bold self-start border border-light-30 dark:border-dark-30">Curiosité<span v-if="maxTraining.curiosity >= 0">: Niveau {{ maxTraining.curiosity }} (+{{ modifiers.curiosity }})</span></div>
|
||||
<div class="flex flex-row gap-4 justify-center" v-for="(level, index) of characterConfig.training.curiosity" :class="{ 'opacity-30': index > maxTraining.curiosity + 1 }">
|
||||
<div class="border border-light-40 dark:border-dark-40 cursor-pointer px-2 py-1 w-1/3" v-for="(option, i) of level" @click="switchTrainingOption('curiosity', index as TrainingLevel, i)" :class="{ 'hover:border-light-60 dark:hover:border-dark-60': index <= maxTraining.curiosity + 1, '!border-accent-blue bg-accent-blue bg-opacity-20': index == 0 || (data.progress.training.curiosity?.some(e => e[0] == index && e[1] === i) ?? false) }"><MarkdownRenderer :proses="{ 'a': PreviewA }" :content="option.description.map(e => e.text).join('\n')" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex w-full flex-shrink-0 flex-col gap-2 relative">
|
||||
<div class="sticky top-1 left-16 py-1 px-3 bg-light-0 dark:bg-dark-0 z-10 text-xl font-bold self-start border border-light-30 dark:border-dark-30">Charisme<span v-if="maxTraining.charisma >= 0">: Niveau {{ maxTraining.charisma }} (+{{ modifiers.charisma }})</span></div>
|
||||
<div class="flex flex-row gap-4 justify-center" v-for="(level, index) of characterConfig.training.charisma" :class="{ 'opacity-30': index > maxTraining.charisma + 1 }">
|
||||
<div class="border border-light-40 dark:border-dark-40 cursor-pointer px-2 py-1 w-1/3" v-for="(option, i) of level" @click="switchTrainingOption('charisma', index as TrainingLevel, i)" :class="{ 'hover:border-light-60 dark:hover:border-dark-60': index <= maxTraining.charisma + 1, '!border-accent-blue bg-accent-blue bg-opacity-20': index == 0 || (data.progress.training.charisma?.some(e => e[0] == index && e[1] === i) ?? false) }"><MarkdownRenderer :proses="{ 'a': PreviewA }" :content="option.description.map(e => e.text).join('\n')" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex w-full flex-shrink-0 flex-col gap-2 relative">
|
||||
<div class="sticky top-1 left-16 py-1 px-3 bg-light-0 dark:bg-dark-0 z-10 text-xl font-bold self-start border border-light-30 dark:border-dark-30">Psyché<span v-if="maxTraining.psyche >= 0">: Niveau {{ maxTraining.psyche }} (+{{ modifiers.psyche }})</span></div>
|
||||
<div class="flex flex-row gap-4 justify-center" v-for="(level, index) of characterConfig.training.psyche" :class="{ 'opacity-30': index > maxTraining.psyche + 1 }">
|
||||
<div class="border border-light-40 dark:border-dark-40 cursor-pointer px-2 py-1 w-1/3" v-for="(option, i) of level" @click="switchTrainingOption('psyche', index as TrainingLevel, i)" :class="{ 'hover:border-light-60 dark:hover:border-dark-60': index <= maxTraining.psyche + 1, '!border-accent-blue bg-accent-blue bg-opacity-20': index == 0 || (data.progress.training.psyche?.some(e => e[0] == index && e[1] === i) ?? false) }"><MarkdownRenderer :proses="{ 'a': PreviewA }" :content="option.description.map(e => e.text).join('\n')" /></div>
|
||||
<div class="flex w-full flex-shrink-0 flex-col gap-2 relative" v-for="(text, stat) of mainStatTexts">
|
||||
<div class="sticky top-1 left-16 py-1 px-3 bg-light-0 dark:bg-dark-0 z-10 text-xl font-bold self-start border border-light-30 dark:border-dark-30">{{ text }}<span v-if="maxTraining[stat] >= 0">: Niveau {{ maxTraining[stat] }} (+{{ modifiers[stat] }})</span></div>
|
||||
<div class="flex flex-row gap-4 justify-center" v-for="(level, index) of characterConfig.training[stat]" :class="{ 'opacity-30': index > maxTraining[stat] + 1 }">
|
||||
<div class="border border-light-40 dark:border-dark-40 cursor-pointer px-2 py-1 w-1/3" v-for="(option, i) of level" @click="switchTrainingOption(stat, index as TrainingLevel, i)" :class="{ 'hover:border-light-60 dark:hover:border-dark-60': index <= maxTraining[stat] + 1, '!border-accent-blue bg-accent-blue bg-opacity-20': index == 0 || (data.progress.training[stat]?.some(e => e[0] == index && e[1] === i) ?? false) }"><MarkdownRenderer :proses="{ 'a': PreviewA }" :content="option.description.map(e => e.text).join('\n')" /></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -314,12 +295,14 @@ useShortcuts({
|
|||
<span class="font-bold text-xl">Compétences</span>
|
||||
</template>
|
||||
<template #default>
|
||||
<div class="flex flex-col gap-2 px-4">
|
||||
<div class="flex flex-col gap-2 max-h-[50vh] px-4 relative overflow-y-auto">
|
||||
<div class="sticky top-0 py-2 bg-light-0 dark:bg-dark-0 z-10 flex justify-between">
|
||||
<span class="text-xl -mx-2" :class="{ 'text-light-red dark:text-dark-red': (abilityPoints ?? 0) < abilitySpent }">Points d'entrainement restants: {{ (abilityPoints ?? 0) - abilitySpent }}</span>
|
||||
</div>
|
||||
<div v-for="(ability, index) of characterConfig.ability" class="grid grid-cols-10 gap-4 items-center">
|
||||
<span class="text-lg col-span-2">{{ ability.name }}</span>
|
||||
<span class="text-sm text-light-70 dark:text-dark-70 col-span-2">({{ mainStatTexts[ability.max[0]] }} + {{ mainStatTexts[ability.max[1]] }})</span>
|
||||
<NumberFieldRoot :min="0" :max="20" :default-value="data.progress.abilities[index] ? data.progress.abilities[index][0] : 0" @update:model-value="(value) => { data.progress.abilities[index] = [value, data.progress.abilities[index] ? data.progress.abilities[index][1] : 0]; console.log(abilitySpent) }" class="flex justify-center border border-light-35 dark:border-dark-35 bg-light-20 dark:bg-dark-20 data-[disabled]:border-light-20 dark:data-[disabled]:border-dark-20 data-[disabled]:bg-light-20 dark:data-[disabled]:bg-dark-20
|
||||
<NumberFieldRoot :min="0" :max="abilityMax[index]" :default-value="data.progress.abilities[index] ? data.progress.abilities[index][0] : 0" @update:model-value="(value) => { data.progress.abilities[index] = [value, data.progress.abilities[index] ? data.progress.abilities[index][1] : 0]; console.log(abilitySpent) }" class="flex justify-center border border-light-35 dark:border-dark-35 bg-light-20 dark:bg-dark-20 data-[disabled]:border-light-20 dark:data-[disabled]:border-dark-20 data-[disabled]:bg-light-20 dark:data-[disabled]:bg-dark-20
|
||||
data-[disabled]:text-light-70 dark:data-[disabled]:text-dark-70 hover:border-light-50 dark:hover:border-dark-50 has-[:focus]:shadow-raw transition-[box-shadow] has-[:focus]:shadow-light-40 dark:has-[:focus]:shadow-dark-40">
|
||||
<NumberFieldInput class="tabular-nums w-20 bg-transparent px-3 py-1 outline-none caret-light-50 dark:caret-dark-50" />
|
||||
</NumberFieldRoot>
|
||||
|
|
@ -328,7 +311,6 @@ useShortcuts({
|
|||
</div>
|
||||
</template>
|
||||
</Collapsible>
|
||||
<div class="h-[50vh]"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -96,6 +96,12 @@ const { data: character, status, error } = await useAsyncData(() => useRequestFe
|
|||
<span>Sorts de savoir: <span class="font-bold">{{ character.spellranks.knowledge }}</span></span>
|
||||
<span>Sorts d'instinct: <span class="font-bold">{{ character.spellranks.instinct }}</span></span>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<span class="text-lg font-semibold border-b border-light-30 dark:border-dark-30 mb-2">Compétences</span>
|
||||
<div class="grid grid-cols-3 gap-1">
|
||||
<div class="flex flex-col px-2 items-center" v-for="(value, ability) of character.abilities"><span class="font-bold">+{{ value }}</span><span>{{ config.ability[ability].name }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-1 flex-col border-l border-light-30 dark:border-dark-30 ps-8 gap-4 py-8 max-w-[80rem]">
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
|
|
|
|||
|
|
@ -135,23 +135,23 @@ function compileCharacter(character: Character & { username?: string }): Compile
|
|||
misc: [],
|
||||
},
|
||||
abilities: {
|
||||
athletics: [0, 0],
|
||||
acrobatics: [0, 0],
|
||||
intimidation: [0, 0],
|
||||
sleightofhand: [0, 0],
|
||||
stealth: [0, 0],
|
||||
survival: [0, 0],
|
||||
investigation: [0, 0],
|
||||
history: [0, 0],
|
||||
religion: [0, 0],
|
||||
arcana: [0, 0],
|
||||
understanding: [0, 0],
|
||||
perception: [0, 0],
|
||||
performance: [0, 0],
|
||||
medecine: [0, 0],
|
||||
persuasion: [0, 0],
|
||||
animalhandling: [0, 0],
|
||||
deception: [0, 0]
|
||||
athletics: 0,
|
||||
acrobatics: 0,
|
||||
intimidation: 0,
|
||||
sleightofhand: 0,
|
||||
stealth: 0,
|
||||
survival: 0,
|
||||
investigation: 0,
|
||||
history: 0,
|
||||
religion: 0,
|
||||
arcana: 0,
|
||||
understanding: 0,
|
||||
perception: 0,
|
||||
performance: 0,
|
||||
medecine: 0,
|
||||
persuasion: 0,
|
||||
animalhandling: 0,
|
||||
deception: 0
|
||||
},
|
||||
spellslots: 0,
|
||||
spellranks: {
|
||||
|
|
@ -195,14 +195,15 @@ function compileCharacter(character: Character & { username?: string }): Compile
|
|||
|
||||
features.forEach(e => e[1].forEach((_e, i) => applyTrainingOption(e[0], _e, compiled, i === e[1].length - 1)));
|
||||
specialFeatures(compiled, character.progress.training);
|
||||
|
||||
Object.entries(character.progress.abilities).forEach(e => compiled.abilities[e[0]] += e[1][0]);
|
||||
|
||||
return compiled;
|
||||
}
|
||||
function applyTrainingOption(stat: MainStat, option: TrainingOption, character: CompiledCharacter, last: boolean)
|
||||
{
|
||||
if(option.health) character.health += option.health;
|
||||
if(option.mana) character.mana += option.mana;
|
||||
if(option.modifier) option.modifier.forEach(e => character.modifier[e[0]] += e[1]);
|
||||
if(option.ability) option.ability.forEach(e => character.abilities[e[0]]![0] += e[1]);
|
||||
if(option.mastery) character.mastery[option.mastery]++;
|
||||
if(option.speed) character.speed = option.speed;
|
||||
if(option.initiative) character.initiative += option.initiative;
|
||||
|
|
|
|||
|
|
@ -1720,7 +1720,8 @@
|
|||
"disposable": false,
|
||||
"replaced": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 6
|
||||
}
|
||||
],
|
||||
"1": [
|
||||
|
|
@ -1735,7 +1736,8 @@
|
|||
"disposable": false,
|
||||
"replaced": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 3
|
||||
}
|
||||
],
|
||||
"2": [
|
||||
|
|
@ -1745,7 +1747,8 @@
|
|||
"text": "+5 points de compétence.",
|
||||
"disposable": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 5
|
||||
}
|
||||
],
|
||||
"3": [
|
||||
|
|
@ -1755,7 +1758,8 @@
|
|||
"text": "+3 points de compétence.",
|
||||
"disposable": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 3
|
||||
}
|
||||
],
|
||||
"4": [
|
||||
|
|
@ -1765,7 +1769,8 @@
|
|||
"text": "+4 points de compétence.",
|
||||
"disposable": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 4
|
||||
}
|
||||
],
|
||||
"5": [
|
||||
|
|
@ -1799,7 +1804,8 @@
|
|||
"text": "+3 points de compétence.",
|
||||
"disposable": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 3
|
||||
}
|
||||
],
|
||||
"6": [
|
||||
|
|
@ -1822,7 +1828,8 @@
|
|||
"text": "+1 point de compétence.",
|
||||
"disposable": false
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 1
|
||||
},
|
||||
{
|
||||
"description": [
|
||||
|
|
@ -1830,7 +1837,8 @@
|
|||
"text": "+3 points de compétence.",
|
||||
"disposable": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 3
|
||||
}
|
||||
],
|
||||
"7": [
|
||||
|
|
@ -1838,13 +1846,14 @@
|
|||
"description": [
|
||||
{
|
||||
"text": "Le maximum de toutes les compétences est de 6 points, sauf s'il est déjà supérieur.",
|
||||
"disposable": false
|
||||
"disposable": true
|
||||
},
|
||||
{
|
||||
"text": "+2 points de compétence.",
|
||||
"disposable": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 2
|
||||
},
|
||||
{
|
||||
"description": [
|
||||
|
|
@ -1858,13 +1867,14 @@
|
|||
"description": [
|
||||
{
|
||||
"text": "Le maximum de toutes les compétences augmente de 1 point.",
|
||||
"disposable": false
|
||||
"disposable": true
|
||||
},
|
||||
{
|
||||
"text": "+2 points de compétence.",
|
||||
"disposable": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 2
|
||||
}
|
||||
],
|
||||
"8": [
|
||||
|
|
@ -1890,7 +1900,8 @@
|
|||
"text": "+4 points de compétence.",
|
||||
"disposable": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 4
|
||||
}
|
||||
],
|
||||
"9": [
|
||||
|
|
@ -1942,7 +1953,8 @@
|
|||
"text": "+4 points de compétence.",
|
||||
"disposable": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 4
|
||||
}
|
||||
],
|
||||
"11": [
|
||||
|
|
@ -1968,7 +1980,8 @@
|
|||
"text": "+4 points de compétence.",
|
||||
"disposable": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 4
|
||||
}
|
||||
],
|
||||
"12": [
|
||||
|
|
@ -2020,7 +2033,8 @@
|
|||
"text": "+5 points de compétence.",
|
||||
"disposable": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"ability": 5
|
||||
}
|
||||
],
|
||||
"14": [
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ export type CompiledCharacter = {
|
|||
};
|
||||
|
||||
modifier: Record<MainStat, number>;
|
||||
abilities: Partial<Record<Ability, [number, number]>>;
|
||||
abilities: Partial<Record<Ability, number>>;
|
||||
level: number;
|
||||
features: Record<Category, string[]>; //Currently: List of training option as text. TODO: Update to a more complex structure later
|
||||
};
|
||||
Loading…
Reference in New Issue