diff --git a/db.sqlite b/db.sqlite index c15aae5..ba9eab2 100644 Binary files a/db.sqlite and b/db.sqlite differ diff --git a/db.sqlite-shm b/db.sqlite-shm index fe9ac28..da6eab5 100644 Binary files a/db.sqlite-shm and b/db.sqlite-shm differ diff --git a/db.sqlite-wal b/db.sqlite-wal index e69de29..0b84fef 100644 Binary files a/db.sqlite-wal and b/db.sqlite-wal differ diff --git a/shared/character-config.json b/shared/character-config.json index d87ff51..2fde7a5 100644 --- a/shared/character-config.json +++ b/shared/character-config.json @@ -186,248 +186,168 @@ "options": { "1": [ { - "training": 35, - "health": 14 + "description": "+35 points de statistiques.\n+14 PV max." } ], "2": [ { - "training": 1, - "health": 3, - "mana": 2 + "description": "+1 point de statistique.\n+3 PV max.\n+2 mana max." }, { - "health": 6, - "mana": 3, - "abilities": 1 + "description": "+1 point de compétence.\n+6 PV max.\n+3 mana max." } ], "3": [ { - "training": 2, - "health": 3, - "mana": 1, - "abilities": 1 + "description": "+2 points de statistiques.\n+1 point de compétence.\n+3 PV max.\n+1 mana max." } ], "4": [ { - "training": 1, - "health": 4, - "mana": 2, - "abilities": 2 + "description": "+1 point de statistique.\n+2 points de compétences.\n+4 PV max.\n+2 mana max." } ], "5": [ { - "training": 1, - "health": 4, - "mana": 2, - "abilities": 2 + "description": "+1 point de statistique.\n+2 points de compétences.\n+4 PV max.\n+2 mana max." }, { - "training": 1, - "shaping": 1, - "health": 8, - "mana": 4 + "description": "+1 point de statistique.\n+1 transformation par jour.\n+8 PV max.\n+4 mana max." }, { - "training": 2, - "health": 7, - "mana": 2 + "description": "+2 points de statistiques.\n+7 PV max.\n+2 mana max." } ], "6": [ { - "training": 1, - "health": 3, - "mana": 3 + "description": "+1 point de statistique.\n+3 PV max.\n+3 mana max." }, { - "training": 1, - "abilities": 3, - "spellslots": 1 + "description": "+1 point de statistique.\n+3 points de compétences.\n+1 sort maitrisé." } ], "7": [ { - "training": 2, - "health": 3, - "mana": 5 + "description": "+2 points de statistiques.\n+3 PV max.\n+5 mana max." }, { - "training": 2, - "health": 5, - "mana": 2 + "description": "+2 points de statistiques.\n+5 PV max.\n+2 mana max." } ], "8": [ { - "training": 3 + "description": "+3 points de statistiques." }, { - "training": 1, - "health": 6, - "mana": 6, - "spellslots": 1 + "description": "+1 point de statistique.\n+6 PV max.\n+6 mana max.\n+1 sort maitrisé." } ], "9": [ { - "training": 1, - "health": 3, - "mana": 5 + "description": "+1 point de statistique.\n+3 PV max.\n+5 mana max." }, { - "training": 1, - "health": 2, - "abilities": 2 + "description": "+1 point de statistique.\n+2 points de compétences.\n+2 PV max." } ], "10": [ { - "training": 2 + "description": "+2 points de statistiques." }, { - "training": 1, - "shaping": 1, - "abilities": 2 + "description": "+1 point de statistique.\n+1 transformation par jour.\n+2 points de compétences." }, { - "modifier": 1, - "abilities": 1 + "description": "+1 au modifieur de votre choix.\n+1 point de compétence." } ], "11": [ { - "training": 1, - "health": 7, - "mana": 1 + "description": "+1 point de statistique.\n+7 PV max.\n+1 mana max." }, { - "training": 1, - "health": 2, - "mana": 5 + "description": "+1 point de statistique.\n+2 PV max.\n+5 mana max." }, { - "training": 1, - "abilities": 2 + "description": "+1 point de statistique.\n+2 points de compétences." } ], "12": [ { - "training": 2, - "spellslots": 1 + "description": "+2 points de statistiques.\n+1 sort maitrisé." }, { - "training": 2, - "health": 8 + "description": "+2 points de statistiques.\n+8 PV max." }, { - "training": 2, - "mana": 7 + "description": "+2 points de statistiques.\n+7 mana max." } ], "13": [ { - "training": 1, - "health": 2, - "mana": 2, - "abilities": 1 + "description": "+1 point de statistique.\n+1 point de compétence.\n+2 PV max.\n+2 mana max." }, { - "training": 1, - "shaping": 1, - "health": 4, - "mana": 4 + "description": "+1 point de statistique.\n+1 transformation par jour.\n+4 PV max.\n+4 mana max." } ], "14": [ { - "training": 3, - "health": 3, - "mana": 5 + "description": "+3 points de statistiques.\n+3 PV max.\n+5 mana max." }, { - "training": 3, - "health": 6, - "mana": 1 + "description": "+3 points de statistiques.\n+6 PV max.\n+1 mana max." } ], "15": [ { - "training": 1 + "description": "+1 point de statistique." }, { - "health": 5, - "mana": 5, - "abilities": 1 + "description": "+1 point de compétence.\n+5 PV max.\n+5 mana max." } ], "16": [ { - "training": 1, - "health": 3, - "mana": 5 + "description": "+1 point de statistique.\n+3 PV max.\n+5 mana max." }, { - "training": 1, - "health": 5, - "mana": 2 + "description": "+1 point de statistique.\n+5 PV max.\n+2 mana max." } ], "17": [ { - "training": 2, - "abilities": 1, - "spellslots": 1 + "description": "+2 points de statistiques.\n+1 point de compétence.\n+1 sort maitrisé." }, { - "training": 1, - "shaping": 1, - "abilities": 2, - "spellslots": 1 + "description": "+1 point de statistique.\n+1 transformation par jour.\n+2 points de compétences.\n+1 sort maitrisé." }, { - "training": 1, - "health": 7, - "mana": 5, - "abilities": 1 + "description": "+1 point de statistique.\n+1 point de compétence.\n+7 PV max.\n+5 mana max." } ], "18": [ { - "training": 1, - "health": 6, - "mana": 1 + "description": "+1 point de statistique.\n+6 PV max.\n+1 mana max." }, { - "training": 1, - "health": 2, - "mana": 5 + "description": "+1 point de statistique.\n+2 PV max.\n+5 mana max." } ], "19": [ { - "training": 2, - "health": 6, - "mana": 3, - "abilities": 2 + "description": "+2 points de statistiques.\n+2 points de compétences.\n+6 PV max.\n+3 mana max." }, { - "training": 2, - "health": 2, - "mana": 5, - "spellslots": 1 + "description": "+2 points de statistiques.\n+2 PV max.\n+5 mana max.\n+1 sort maitrisé." } ], "20": [ { - "training": 2 + "description": "+2 points de statistiques." }, { - "modifier": 1, - "abilities": 1 + "description": "+1 au modifieur de votre choix.\n+1 point de compétence." } ] } diff --git a/shared/character.util.ts b/shared/character.util.ts index dd90652..adffc22 100644 --- a/shared/character.util.ts +++ b/shared/character.util.ts @@ -4,6 +4,7 @@ import characterConfig from './character-config.json'; import { button, loading } from "./proses"; import { div, dom, icon, text } from "./dom.util"; import { popper } from "./floating.util"; +import { clamp } from "./general.util"; const config = characterConfig as CharacterConfig; @@ -182,6 +183,7 @@ export class CharacterBuilder ]; this._stepsContent = [ new PeoplePicker(this), + new LevelPicker(this), ]; this._content = div('flex-1 outline-none max-w-full w-full overflow-y-auto'); this._container.appendChild(div('flex flex-1 flex-col justify-start items-center px-8 w-full h-full overflow-y-hidden', [ @@ -301,7 +303,7 @@ export class CharacterBuilder } }) } - private updateLevel(level: Level) + updateLevel(level: Level) { this._character.level = level; @@ -320,7 +322,7 @@ export class CharacterBuilder } } } - private toggleLevelOption(level: Level, choice: number) + toggleLevelOption(level: Level, choice: number) { if(level > this._character.level) //Cannot add more level options than the current level return; @@ -355,7 +357,7 @@ export class CharacterBuilder this.add(config.peoples[this._character.people!]!.options[level][choice]!); } } - private toggleTrainingOption(stat: MainStat, level: TrainingLevel, option: number) + toggleTrainingOption(stat: MainStat, level: TrainingLevel, option: number) { } @@ -422,17 +424,6 @@ class PeoplePicker implements BuilderTab constructor(builder: CharacterBuilder) { - /* -
-
- - {{ people.name }} - - {{ people.description }} -
-
- */ this._builder = builder; this._nameInput = dom("input", { class: `mx-4 caret-light-50 dark:caret-dark-50 text-light-100 dark:text-dark-100 placeholder:text-light-50 dark:placeholder:text-dark-50 @@ -495,4 +486,109 @@ class PeoplePicker implements BuilderTab { return this._content; } +} +class LevelPicker implements BuilderTab +{ + private _builder: CharacterBuilder; + private _content: Array; + + private _levelInput: HTMLInputElement; + private _pointsInput: HTMLInputElement; + private _healthText: Text; + private _manaText: Text; + private _options: HTMLDivElement[][]; + + constructor(builder: CharacterBuilder) + { + this._builder = builder; + + this._levelInput = dom("input", { class: `w-14 mx-4 caret-light-50 dark:caret-dark-50 text-light-100 dark:text-dark-100 placeholder:text-light-50 dark:placeholder:text-dark-50 bg-light-20 dark:bg-dark-20 appearance-none outline-none px-3 py-1 focus:shadow-raw transition-[box-shadow] focus:shadow-light-40 dark:focus:shadow-dark-40 border border-light-35 dark:border-dark-35 hover:border-light-50 dark:hover:border-dark-50 data-[disabled]:bg-light-20 dark:data-[disabled]:bg-dark-20 data-[disabled]:border-light-20 dark:data-[disabled]:border-dark-20`, listeners: { + input: (e: Event) => { + this._builder.character.level = parseInt(this._levelInput.value) ?? 1; + this.updateLevel(); + }, + keydown: (e: KeyboardEvent) => { + let value = this._levelInput.value; + switch(e.key) + { + case "ArrowUp": + value = clamp(parseInt(value) + 1, 1, 20).toString(); + break; + case "ArrowDown": + value = clamp(parseInt(value) - 1, 1, 20).toString(); + break; + default: + break; + } + + if(this._levelInput.value !== value) + { + this._levelInput.value = value; + this._builder.character.level = parseInt(value); + this.updateLevel(); + } + } + }}); + this._pointsInput = dom("input", { class: `w-14 mx-4 text-light-70 dark:text-dark-70 tabular-nums bg-light-10 dark:bg-dark-10 appearance-none outline-none px-3 py-1 focus:shadow-raw transition-[box-shadow] border bg-light-20 bg-dark-20 border-light-20 dark:border-dark-20`, attributes: { type: "number", disabled: true }}); + this._healthText = text("0"), this._manaText = text("0"); + + this._options = Object.entries(config.peoples[this._builder.character.people!]!.options).map( + (level) => [ div("w-full h-px", [div("border-t border-dashed border-light-50 dark:border-dark-50 w-full"), div("sticky top-0", [ text(level[0]) ])]), + div("flex flex-row gap-4 justify-center", level[1].map((option, j) => dom("div", { class: ["flex border border-light-50 dark:border-dark-50 px-4 py-2 w-[400px]", { 'hover:border-light-70 dark:hover:border-dark-70 cursor-pointer': (level[0] as any as Level) <= this._builder.character.level, '!border-accent-blue bg-accent-blue bg-opacity-20': this._builder.character.leveling?.some(e => e[0] == (level[0] as any as Level) && e[1] === j) ?? false }], listeners: { click: e => { + this._builder.toggleLevelOption(level[0] as any as Level, j); + }}}, [ dom('span', { class: "text-wrap whitespace-pre", text: option.description }) ]))) + ]); + + this._content = [ div("flex flex-1 gap-12 px-2 py-4 justify-center items-center", [ + dom("label", { class: "flex justify-center items-center my-2" }, [ + dom("span", { class: "pb-1 md:p-0", text: "Niveau" }), + this._levelInput, + ]), + dom("label", { class: "flex justify-center items-center my-2" }, [ + dom("span", { class: "md:text-base text-sm", text: "Points restantes" }), + this._pointsInput, + ]), + div("flex justify-center items-center gap-2 my-2 md:text-base text-sm", [ + dom("span", { text: "Vie" }), + this._healthText, + ]), + div("flex justify-center items-center gap-2 my-2 md:text-base text-sm", [ + dom("span", { text: "Mana" }), + this._manaText, + ]), + button(text('Suivant'), () => this._builder.display(1), 'h-[35px] px-[15px]'), + ]), div('flex flex-col flex-1 gap-4 mx-8 my-4', this._options.flatMap(e => [...e]))]; + } + update() + { + const values = this._builder.values; + + this._levelInput.value = this._builder.character.level.toString(); + this._pointsInput.value = (this._builder.character.level - this._builder.character.leveling.length).toString(); + this._healthText.textContent = values.health?.toString() ?? '0'; + this._manaText.textContent = values.mana?.toString() ?? '0'; + + this.updateLevel(); + } + private updateLevel() + { + this._builder.updateLevel(this._builder.character.level as Level); + + this._options.forEach((e, i) => { + e[0]?.classList.toggle("opacity-30", ((i + 1) as Level) > this._builder.character.level); + e[1]?.classList.toggle("opacity-30", ((i + 1) as Level) > this._builder.character.level); + e[1]?.childNodes.forEach((option, j) => { + 'hover:border-light-70 dark:hover:border-dark-70 cursor-pointer'.split(" ").forEach(_e => (option as HTMLDivElement).classList.toggle(_e, ((i + 1) as Level) <= this._builder.character.level)); + '!border-accent-blue bg-accent-blue bg-opacity-20'.split(" ").forEach(_e => (option as HTMLDivElement).classList.toggle(_e, this._builder.character.leveling?.some(e => e[0] == ((i + 1) as Level) && e[1] === j) ?? false)); + }) + }); + } + validate(): boolean + { + return this._builder.character.people !== undefined; + } + get dom() + { + return this._content; + } } \ No newline at end of file