113 lines
3.5 KiB
JavaScript
113 lines
3.5 KiB
JavaScript
import { getLoksyuData, setLoksyuData } from "./singletons.js"
|
|
|
|
const SYSTEM_ID = "fvtt-chroniques-de-l-etrange"
|
|
|
|
export class CDELoksyuApp extends foundry.applications.api.HandlebarsApplicationMixin(
|
|
foundry.applications.api.ApplicationV2
|
|
) {
|
|
static DEFAULT_OPTIONS = {
|
|
id: "cde-loksyu-app",
|
|
tag: "div",
|
|
window: {
|
|
title: "CDE.Loksyu",
|
|
icon: "fas fa-yin-yang",
|
|
resizable: false,
|
|
},
|
|
classes: ["cde-app", "cde-loksyu-standalone"],
|
|
position: { width: 520, height: "auto" },
|
|
actions: {
|
|
resetElement: CDELoksyuApp.#onResetElement,
|
|
resetAll: CDELoksyuApp.#onResetAll,
|
|
},
|
|
}
|
|
|
|
static PARTS = {
|
|
main: {
|
|
template: `systems/${SYSTEM_ID}/templates/apps/cde-loksyu-app.html`,
|
|
},
|
|
}
|
|
|
|
/** @type {Function|null} bound hook handler */
|
|
_updateHook = null
|
|
|
|
/** Singleton accessor — open or bring to front */
|
|
static open() {
|
|
const existing = Array.from(foundry.applications.instances.values()).find(
|
|
(app) => app instanceof CDELoksyuApp
|
|
)
|
|
if (existing) { existing.bringToFront(); return existing }
|
|
const app = new CDELoksyuApp()
|
|
app.render(true)
|
|
return app
|
|
}
|
|
|
|
async _prepareContext() {
|
|
const sys = getLoksyuData()
|
|
const ELEMENTS = [
|
|
{ key: "wood", nameKey: "CDE.Wood", qualKey: "CDE.WoodQualities", img: `systems/${SYSTEM_ID}/images/cde_bois.webp` },
|
|
{ key: "fire", nameKey: "CDE.Fire", qualKey: "CDE.FireQualities", img: `systems/${SYSTEM_ID}/images/cde_feu.webp` },
|
|
{ key: "earth", nameKey: "CDE.Earth", qualKey: "CDE.EarthQualities", img: `systems/${SYSTEM_ID}/images/cde_terre.webp` },
|
|
{ key: "metal", nameKey: "CDE.Metal", qualKey: "CDE.MetalQualities", img: `systems/${SYSTEM_ID}/images/cde_metal.webp` },
|
|
{ key: "water", nameKey: "CDE.Water", qualKey: "CDE.WaterQualities", img: `systems/${SYSTEM_ID}/images/cde_eau.webp` },
|
|
]
|
|
|
|
return {
|
|
canEdit: game.user.isGM,
|
|
elements: ELEMENTS.map((el) => ({
|
|
...el,
|
|
yang: sys[el.key]?.yang ?? 0,
|
|
yin: sys[el.key]?.yin ?? 0,
|
|
})),
|
|
}
|
|
}
|
|
|
|
_onRender(context, options) {
|
|
super._onRender(context, options)
|
|
this.#bindInputs()
|
|
|
|
this._updateHook = Hooks.on("cde:loksyuUpdated", () => this.render())
|
|
}
|
|
|
|
_onClose(options) {
|
|
if (this._updateHook !== null) {
|
|
Hooks.off("cde:loksyuUpdated", this._updateHook)
|
|
this._updateHook = null
|
|
}
|
|
super._onClose(options)
|
|
}
|
|
|
|
#bindInputs() {
|
|
const inputs = this.element?.querySelectorAll("input[data-field]")
|
|
if (!inputs?.length) return
|
|
inputs.forEach((input) => {
|
|
input.addEventListener("change", async (ev) => {
|
|
const field = ev.currentTarget.dataset.field
|
|
const val = parseInt(ev.currentTarget.value, 10)
|
|
if (!field || isNaN(val)) return
|
|
// field is like "wood.yin" or "fire.yang"
|
|
const [aspect, dim] = field.split(".")
|
|
if (!aspect || !dim) return
|
|
const data = getLoksyuData()
|
|
if (!data[aspect]) data[aspect] = { yin: 0, yang: 0 }
|
|
data[aspect][dim] = Math.max(0, val)
|
|
await setLoksyuData(data)
|
|
})
|
|
})
|
|
}
|
|
|
|
static async #onResetElement(event, target) {
|
|
const key = target.dataset.element
|
|
if (!key) return
|
|
const data = getLoksyuData()
|
|
data[key] = { yin: 0, yang: 0 }
|
|
await setLoksyuData(data)
|
|
}
|
|
|
|
static async #onResetAll(_event, _target) {
|
|
const KEYS = ["wood", "fire", "earth", "metal", "water"]
|
|
const data = getLoksyuData()
|
|
for (const k of KEYS) data[k] = { yin: 0, yang: 0 }
|
|
await setLoksyuData(data)
|
|
}
|
|
}
|