const { HandlebarsApplicationMixin } = foundry.applications.api; /** * Dialogue du meneur pour ouvrir une phase d'Expérience. * Permet d'attribuer les Dés d'Expérience collectifs (Danger, Découvertes, * Durée) au Groupe et aux personnages, ainsi que les Dés individuels * (Implication, Influence, Interprétation), les récompenses d'Objectifs et * la récompense de Traumatisme choisi. */ export default class ExperiencePhaseDialog extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) { static DEFAULT_OPTIONS = { classes: ["vermine-roll"], tag: "form", window: { icon: "fas fa-star", resizable: true }, position: { width: 620, height: 700 }, actions: { apply: ExperiencePhaseDialog.#onApply, cancel: ExperiencePhaseDialog.#onCancel } }; static PARTS = { main: { template: "systems/vermine2047/templates/dialogs/experience-phase-dialog.hbs", scrollable: [""] } }; static async create() { return new ExperiencePhaseDialog(); } get title() { return game.i18n.localize("VERMINE.experience_phase"); } async _prepareContext() { const characters = game.actors.filter(a => a.type === "character"); const groups = game.actors.filter(a => a.type === "group"); return { characters: characters.map(a => ({ id: a.id, name: a.name, dice: a.system?.experience?.dice || 0 })), groups: groups.map(a => ({ id: a.id, name: a.name, dice: a.system?.experience?.dice || 0 })), rewards: [ { value: 0, label: game.i18n.localize("VERMINE.reward_anecdotic") }, { value: 1, label: game.i18n.localize("VERMINE.reward_minor") }, { value: 2, label: game.i18n.localize("VERMINE.reward_major") }, { value: 3, label: game.i18n.localize("VERMINE.reward_exceptionnal") } ] }; } async _onRender(context, options) { this.element.querySelectorAll("[data-roll]").forEach(inp => inp.addEventListener("change", () => this.#updateUI())); this.#updateUI(); } #updateUI() { const danger = parseInt(this.element.querySelector("#collective-danger")?.value, 10) || 0; const discoveries = parseInt(this.element.querySelector("#collective-discoveries")?.value, 10) || 0; const duration = parseInt(this.element.querySelector("#collective-duration")?.value, 10) || 0; const el = this.element.querySelector("#collective-total"); if (el) el.textContent = `${danger + discoveries + duration}D`; } static async #onCancel(event, target) { this.close(); } static async #onApply(event, target) { const collective = (parseInt(this.element.querySelector("#collective-danger")?.value, 10) || 0) + (parseInt(this.element.querySelector("#collective-discoveries")?.value, 10) || 0) + (parseInt(this.element.querySelector("#collective-duration")?.value, 10) || 0); const groupId = this.element.querySelector("#group-select")?.value || null; if (groupId) { const group = game.actors.get(groupId); if (group && collective > 0) { const current = group.system?.experience?.dice || 0; await group.update({ "system.experience.dice": current + collective }); } } const results = []; for (const row of this.element.querySelectorAll("[data-character-id]")) { const id = row.dataset.characterId; const actor = game.actors.get(id); if (!actor) continue; const implication = parseInt(row.querySelector(`[name="implication-${id}"]`)?.value, 10) || 0; const influence = parseInt(row.querySelector(`[name="influence-${id}"]`)?.value, 10) || 0; const interpretation = parseInt(row.querySelector(`[name="interpretation-${id}"]`)?.value, 10) || 0; const objectiveMinor = row.querySelector(`[name="objective-minor-${id}"]`)?.checked ? 3 : 0; const objectiveMajor = row.querySelector(`[name="objective-major-${id}"]`)?.checked ? 5 : 0; const trauma = row.querySelector(`[name="trauma-${id}"]`)?.checked ? 5 : 0; const individual = implication + influence + interpretation; const bonus = objectiveMinor + objectiveMajor + trauma; const gained = collective + individual + bonus; const ex = actor.system?.experience; const nextPhase = (ex?.phase || 0) + 1; const update = { "system.experience.phase": nextPhase, "system.experience.dice": (ex?.dice || 0) + gained, "system.experience.collective.danger": parseInt(this.element.querySelector("#collective-danger")?.value, 10) || 0, "system.experience.collective.discoveries": parseInt(this.element.querySelector("#collective-discoveries")?.value, 10) || 0, "system.experience.collective.duration": parseInt(this.element.querySelector("#collective-duration")?.value, 10) || 0, "system.experience.individual.implication": implication, "system.experience.individual.influence": influence, "system.experience.individual.interpretation": interpretation, "system.experience.traumaReward": trauma > 0, "system.experience.learned.phase": nextPhase, "system.experience.learned.skill": false, "system.experience.learned.specialty": false, "system.experience.learned.reserve": false, "system.experience.learned.characteristic": false, "system.experience.learned.evolution": false }; await actor.update(update); results.push({ name: actor.name, gained }); } const lines = [`${game.i18n.localize("VERMINE.experience_phase")} +1`]; if (groupId) { const group = game.actors.get(groupId); lines.push(`${group?.name ?? ""} (${game.i18n.localize("VERMINE.collective")}): +${collective}D`); } for (const r of results) { lines.push(`${r.name}: +${r.gained}D`); } await ChatMessage.create({ user: game.user?._id, speaker: ChatMessage.getSpeaker(), content: `

${game.i18n.localize("VERMINE.experience_rewards")}

${lines.map(l => `${l}`).join("")}
` }); this.close(); } }