import { VermineExperience } from "../experience.mjs"; const { HandlebarsApplicationMixin } = foundry.applications.api; /** * Dialogue d'achat d'une Adaptation/Mutation avec les Dés d'Évolution * accumulés. Vérifie le coût (niveau 1-4), la limite du Mode de jeu et les * restrictions sur les Mutations ; en cas de succès, crée l'item et consomme * un nombre de Dés d'Évolution égal au niveau choisi. */ export default class BuyEvolutionDialog extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) { #actor; static DEFAULT_OPTIONS = { classes: ["vermine-roll", "buy-evolution"], tag: "form", window: { icon: "fas fa-cart-shopping", resizable: false }, position: { width: 480, height: 460 }, actions: { buy: BuyEvolutionDialog.#onBuy, cancel: BuyEvolutionDialog.#onCancel } }; static PARTS = { main: { template: "systems/vermine2047/templates/dialogs/buy-evolution-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 BuyEvolutionDialog({ actor }); } constructor(options = {}) { super(options); this.#actor = options.actor; } get title() { return game.i18n.localize("VERMINE.buy_evolution"); } async _prepareContext() { const actor = this.#actor; const mode = VermineExperience.gameMode(); const modeLabels = { 1: game.i18n.localize("VERMINE.mode_survie"), 2: game.i18n.localize("VERMINE.mode_cauchemar"), 3: game.i18n.localize("VERMINE.mode_apocalypse") }; const levels = []; for (let value = 1; value <= 4; value++) { levels.push({ value }); } return { evolutionDice: actor.system?.experience?.evolution || 0, defaultName: game.i18n.localize("ITEMS.new_evolution"), levels, totalLevels: VermineExperience.evolutionTotalLevels(actor), modeMax: VermineExperience.evolutionMaxForMode(mode), modeLabel: modeLabels[mode] || "" }; } async _onRender() { this.element.querySelectorAll("[data-roll]").forEach(inp => inp.addEventListener("change", () => this.#updateUI())); this.#updateUI(); } /** Met à jour le total des niveaux « après achat » selon le niveau sélectionné. */ #updateUI() { const cost = parseInt(this.element.querySelector("#evolution-level")?.value, 10) || 0; const el = this.element.querySelector("#evolution-total-value"); if (el) el.textContent = `${VermineExperience.evolutionTotalLevels(this.#actor) + cost}D`; } static async #onCancel(event, target) { this.close(); } static async #onBuy(event, target) { const actor = this.#actor; const name = this.element.querySelector("#evolution-name")?.value?.trim() || ""; const cost = parseInt(this.element.querySelector("#evolution-level")?.value, 10) || 0; const mutation = this.element.querySelector("#evolution-mutation")?.checked || false; if (!name) { ui.notifications.warn(game.i18n.localize("VERMINE.error_evolution_no_name")); return; } const error = VermineExperience.validateEvolutionPurchase(actor, cost, mutation); if (error) { ui.notifications.warn(game.i18n.localize(error)); return; } const created = await actor.createEmbeddedDocuments("Item", [{ name, type: "evolution", system: { level: { value: cost }, mutation } }]); // Ne consomme que le coût du niveau choisi (Règles p. 116-117 : coût = niveau). if (!created || created.length === 0) { ui.notifications.warn(game.i18n.localize("VERMINE.error_evolution_create")); return; } await actor.update({ "system.experience.evolution": Math.max(0, (actor.system?.experience?.evolution || 0) - cost) }); ui.notifications.info(game.i18n.localize("VERMINE.buy_evolution_done")); this.close(); } }