const { HandlebarsApplicationMixin } = foundry.applications.api export default class HamalronActionComplexe extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) { constructor(options = {}) { super(options) HamalronActionComplexe.#instance = this this.actions = [] this.#loadState() } static #instance static get instance() { if (!HamalronActionComplexe.#instance) { HamalronActionComplexe.#instance = new HamalronActionComplexe() } return HamalronActionComplexe.#instance } static DEFAULT_OPTIONS = { id: "action-complexe", classes: ["fvtt-hamalron", "action-complexe"], tag: "div", window: { title: "HAMALRON.ActionComplexe.Title", icon: "fas fa-tasks", resizable: true, }, position: { width: 500, height: "auto", }, actions: { createAction: HamalronActionComplexe.#onCreateAction, recordSuccess: HamalronActionComplexe.#onRecordSuccess, recordFailure: HamalronActionComplexe.#onRecordFailure, deleteAction: HamalronActionComplexe.#onDeleteAction, resetAction: HamalronActionComplexe.#onResetAction, }, } static PARTS = { main: { template: "systems/fvtt-hamalron/templates/dialog-action-complexe.hbs", }, } async _prepareContext(options) { const context = await super._prepareContext(options) context.actions = this.actions.map(a => ({ ...a, pct: a.resistance > 0 ? Math.round((a.currentSuccesses / a.resistance) * 100) : 0, isComplete: a.currentSuccesses >= a.resistance, symboleIcon: HamalronActionComplexe.#symboleIcon(a.symbole), })) context.hasActions = context.actions.length > 0 return context } static #symboleIcon(symbole) { const icons = { coupe: "fa-heart", epee: "fa-crossed-swords", denier: "fa-coins", baton: "fa-staff" } return icons[symbole] || "fa-circle" } #loadState() { const state = game.settings.get("fvtt-hamalron", "actionComplexeState") if (state?.actions?.length) { this.actions = state.actions } } async #saveState() { await game.settings.set("fvtt-hamalron", "actionComplexeState", { actions: this.actions }) } static #onCreateAction(event, target) { const self = this const content = `
` foundry.applications.api.DialogV2.wait({ window: { title: game.i18n.localize("HAMALRON.ActionComplexe.CreateTitle") }, content, rejectClose: false, buttons: [{ action: "create", label: game.i18n.localize("HAMALRON.ActionComplexe.Create"), default: true, callback: (event, button) => { const name = button.form.elements["ac-name"].value.trim() if (!name) return null return { name, symbole: button.form.elements["ac-symbole"].value, resistance: Number(button.form.elements["ac-resistance"].value) || 3, notes: button.form.elements["ac-notes"].value.trim(), } }, }, { action: "cancel", label: game.i18n.localize("Cancel"), }], }).then(result => { if (!result) return self.actions.push({ id: foundry.utils.randomID(8), name: result.name, symbole: result.symbole, resistance: result.resistance, currentSuccesses: 0, failures: 0, notes: result.notes, createdAt: Date.now(), }) self.#saveState() self.render() }) } static async #onRecordSuccess(event, target) { const id = target.dataset.actionId const action = this.actions.find(a => a.id === id) if (!action || action.isComplete) return action.currentSuccesses++ await this.#saveState() if (action.currentSuccesses >= action.resistance) { ui.notifications.info( game.i18n.format("HAMALRON.ActionComplexe.Completed", { name: action.name }) ) ChatMessage.create({ content: `

${game.i18n.format("HAMALRON.ActionComplexe.Completed", { name: action.name })}

${action.currentSuccesses}/${action.resistance} ${game.i18n.localize("HAMALRON.ActionComplexe.Successes")}

`, style: CONST.CHAT_MESSAGE_STYLES.OTHER, }) } this.render() } static async #onRecordFailure(event, target) { const id = target.dataset.actionId const action = this.actions.find(a => a.id === id) if (!action) return action.failures++ await this.#saveState() this.render() } static async #onDeleteAction(event, target) { const id = target.dataset.actionId const confirmed = await foundry.applications.api.DialogV2.confirm({ window: { title: game.i18n.localize("HAMALRON.ActionComplexe.DeleteTitle") }, content: `

${game.i18n.localize("HAMALRON.ActionComplexe.DeleteWarning")}

`, rejectClose: false, modal: true, }) if (!confirmed) return this.actions = this.actions.filter(a => a.id !== id) await this.#saveState() this.render() } static #onResetAction(event, target) { const id = target.dataset.actionId const action = this.actions.find(a => a.id === id) if (!action) return action.currentSuccesses = 0 action.failures = 0 this.#saveState() this.render() } static open() { if (!game.user.isGM) { ui.notifications.warn(game.i18n.localize("HAMALRON.Notifications.GMOnly")) return } HamalronActionComplexe.instance.render(true, { focus: true }) return HamalronActionComplexe.instance } }