import { VermineTotemDice } from "../totem-dice.mjs"; const { HandlebarsApplicationMixin } = foundry.applications.api; /** * Dialogue de gestion des Dés de Totems (Humain / Adapté). * Permet d'appliquer les gains et pertes liés aux Instincts et Interdits * (1D ou 2D selon la gravité de l'acte), en respectant les limites * (3 Dés du même Totem, 5 Dés au maximum) et les règles d'échange. */ export default class TotemDiceDialog extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) { #actor; #serious = false; static DEFAULT_OPTIONS = { classes: ["vermine-roll", "totem-dice"], tag: "form", window: { icon: "fas fa-dice-d10", resizable: false }, position: { width: 480, height: 420 }, actions: { gainHuman: TotemDiceDialog.#onGainHuman, gainAdapted: TotemDiceDialog.#onGainAdapted, loseHuman: TotemDiceDialog.#onLoseHuman, close: TotemDiceDialog.#onClose } }; static PARTS = { main: { template: "systems/vermine2047/templates/dialogs/totem-dice-dialog.hbs", scrollable: [""] } }; static async create({ actorId }) { const actor = await game.actors.get(actorId); if (!actor) { ui.notifications.warn(game.i18n.localize("VERMINE.error_no_actor_selected")); return null; } return new TotemDiceDialog({ actor }); } constructor(options = {}) { super(options); this.#actor = options.actor; } get title() { return game.i18n.localize("VERMINE.totem_dice"); } async _prepareContext() { const actor = this.#actor; const influence = VermineTotemDice.getInfluence(actor); const influenceLabels = { human: game.i18n.localize("TOTEMS.human.name"), adapted: game.i18n.localize("TOTEMS.adapted.name"), neutral: game.i18n.localize("VERMINE.totem_neutral") }; return { humanValue: actor.system?.adaptation?.totems?.human?.value ?? 0, humanMax: actor.system?.adaptation?.totems?.human?.max ?? 3, adaptedValue: actor.system?.adaptation?.totems?.adapted?.value ?? 0, adaptedMax: actor.system?.adaptation?.totems?.adapted?.max ?? 3, influenceLabel: influenceLabels[influence] || "", serious: this.#serious }; } _onRender(context, options) { super._onRender(context, options); const checkbox = this.element.querySelector("#totem-serious"); if (checkbox) { checkbox.checked = this.#serious; checkbox.addEventListener("change", () => { this.#serious = checkbox.checked; }); } } #getCount() { return this.element.querySelector("#totem-serious")?.checked ? 2 : 1; } #notify(result) { const key = result.totem === "human" ? "TOTEMS.human.name" : "TOTEMS.adapted.name"; const totemName = game.i18n.localize(key); const parts = []; if (result.gained) parts.push(game.i18n.localize("VERMINE.totem_gained").replace("{totem}", totemName)); if (result.exchanged) parts.push(game.i18n.localize("VERMINE.totem_exchanged").replace("{totem}", totemName)); if (result.replaced) parts.push(game.i18n.localize("VERMINE.totem_replaced").replace("{totem}", totemName)); if (result.lost) parts.push(game.i18n.localize("VERMINE.totem_lost")); if (result.gainedAdapted) parts.push(game.i18n.localize("VERMINE.totem_gained_adapted")); if (result.refused) parts.push(game.i18n.localize("VERMINE.totem_limit_reached")); const text = parts.join(" "); if (result.refused && !result.gained && !result.lost && !result.exchanged && !result.replaced) { ui.notifications.warn(text || game.i18n.localize("VERMINE.totem_limit_reached")); } else if (text) { ui.notifications.info(text); } this.render(); } static async #onGainHuman() { const result = await VermineTotemDice.gainDie(this.#actor, "human", this.#getCount()); this.#notify(result); } static async #onGainAdapted() { const result = await VermineTotemDice.gainDie(this.#actor, "adapted", this.#getCount()); this.#notify(result); } static async #onLoseHuman() { const result = await VermineTotemDice.loseDie(this.#actor, "human", this.#getCount()); this.#notify(result); } static #onClose() { this.close(); } }