Release Creation / build (release) Failing after 1m32s
- VermineTotemDice : influence Humain/Adapté (+1D/-1D par domaine, règles p. 121), gains/pertes via Instincts/Interdits avec limites (3D/totem, 5D total) et règles d'échange. - roll.mjs applique l'influence selon le Totem dominant (au lieu de l'ancienne logique basée sur identity.totem). - Dialogue TotemDiceDialog (instinct Humain/autre totem, interdit Humain, acte grave ±2D) + bouton et ligne d'influence sur la fiche personnage. - Dés de Totem gagnés en cas d'échec à l'apprentissage Dé d'Évolution (dés dépensés, garde capacité vide). - Couleur de texte @color-text-light-2 assombrie (#c9e0c0 → #3f9b55) pour la lisibilité dans tous les dialogues. fix: robustesse et visibilité des évolutions - buyEvolutionDialog : n'efface les Dés d'Évolution que si l'item est créé. - Flag mutation éditable sur la fiche item evolution + badge Adaptation/Mutation dans la liste du personnage. - loseDie : applique aussi la limite totale de 5 dés au gain Adapté. - Case "acte grave" conservée entre les rendus du dialogue.
126 lines
4.1 KiB
JavaScript
126 lines
4.1 KiB
JavaScript
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();
|
|
}
|
|
}
|