From 75f79c1c088238920599b14b07b3e5cc881bf242 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnier Date: Wed, 10 Jun 2026 15:54:31 +0200 Subject: [PATCH] feat(magic): reorder schools, fix Wu Xing aspect & power formula MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `magicOrder` ArrayField + ▲/▼ buttons for manual reordering - Magic rolls use school's aspect for Wu Xing, not speciality's element - Spell power: `difficulty × (aspectValue + freePowerLevels)` (not `successes × diff`) - Prompt replaces `aspectspeciality`/`bonusmalusspeciality`/`heispend` with `freepowerlevels` fix: code review issues - combat.js: guard undefined `ids` in rollInitiative - rolling.js: catch Dice So Nice promise, normalize French→English kungfu aspects - weapon/armor/ingredient: `{ min: 0 }` on quantity - character.js/npc.js: catch rollForActor fire-and-forget promises - roll-actions.js/tinji-app.js: await ChatMessage.create - sanhei.js: null guard on properties - spell.js/kungfu.js: fix aspect name comments (French→English) --- css/cde-theme.css | 25 +++ css/cde-theme.less | 24 +++ dist/system.js | 181 +++++++++++------- dist/system.js.map | 4 +- lang/fr-cde.json | 3 + src/data/actors/character.js | 7 +- src/data/items/armor.js | 2 +- src/data/items/ingredient.js | 2 +- src/data/items/kungfu.js | 2 +- src/data/items/spell.js | 2 +- src/data/items/weapon.js | 2 +- src/documents/combat.js | 4 +- src/ui/apps/tinji-app.js | 2 +- src/ui/roll-actions.js | 4 +- src/ui/rolling.js | 91 +++++---- src/ui/sheets/actors/character.js | 74 +++++-- src/ui/sheets/actors/npc.js | 2 +- src/ui/sheets/items/sanhei.js | 10 +- .../actor/parts/cde-character-magics.html | 8 + templates/form/cde-dice-result.html | 1 + templates/form/cde-magic-dice-prompt.html | 43 +---- 21 files changed, 304 insertions(+), 189 deletions(-) diff --git a/css/cde-theme.css b/css/cde-theme.css index 0b9a214..2c810a2 100644 --- a/css/cde-theme.css +++ b/css/cde-theme.css @@ -2179,6 +2179,25 @@ section.npc .cde-neon-tabs .item.active { .cde-magic-toggle:hover i { color: #e2e8f4; } +.cde-magic-order-btn { + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + color: #7d94b8; + border-radius: 3px; + flex-shrink: 0; + transition: color 0.12s, background 0.12s; +} +.cde-magic-order-btn i { + font-size: 9px; +} +.cde-magic-order-btn:hover { + color: #e2e8f4; + background: rgba(38, 56, 83, 0.25); +} .cde-magic-specialities { border-top: 1px solid #1a2436; padding: 4px 0; @@ -3523,6 +3542,12 @@ ol.item-list li.item .item-controls a.item-control:hover { color: var(--rr-accent, #e2e8f4); text-shadow: 0 0 12px var(--rr-accent, transparent); } +.cde-roll-result .cde-rr-hero .cde-rr-spell-power .cde-rr-spell-power-formula { + font-size: 10px; + color: #7d94b8; + margin: 2px 0; + white-space: nowrap; +} .cde-roll-result .cde-rr-hero .cde-rr-spell-power .cde-rr-spell-power-label { font-size: 9px; font-weight: 700; diff --git a/css/cde-theme.less b/css/cde-theme.less index b2a1e9f..df6cb48 100644 --- a/css/cde-theme.less +++ b/css/cde-theme.less @@ -2253,6 +2253,23 @@ section.npc .cde-neon-tabs .item.active { color: @cde-supernatural; borde &:hover i { color: @cde-text; } } +.cde-magic-order-btn { + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + color: @cde-muted; + border-radius: 3px; + flex-shrink: 0; + transition: color 0.12s, background 0.12s; + + i { font-size: 9px; } + + &:hover { color: @cde-text; background: fade(@cde-border-hi, 25%); } +} + // Specialities list .cde-magic-specialities { border-top: 1px solid @cde-border; @@ -3582,6 +3599,13 @@ ol.item-list { text-shadow: 0 0 12px var(--rr-accent, transparent); } + .cde-rr-spell-power-formula { + font-size: 10px; + color: @cde-muted; + margin: 2px 0; + white-space: nowrap; + } + .cde-rr-spell-power-label { font-size: 9px; font-weight: 700; diff --git a/dist/system.js b/dist/system.js index 495f54d..f1cf426 100644 --- a/dist/system.js +++ b/dist/system.js @@ -774,9 +774,8 @@ var CharacterDataModel = class extends foundry.abstract.TypeDataModel { typeofthrow: numberField(0), aspectskill: numberField(0), bonusmalusskill: numberField(0), - aspectspeciality: numberField(0), rolldifficulty: numberField(0), - bonusmalusspeciality: numberField(0) + freepowerlevels: numberField(0) }) }), aspect: new fields.SchemaField({ @@ -815,6 +814,10 @@ var CharacterDataModel = class extends foundry.abstract.TypeDataModel { nine: componentField(), zero: componentField() }), + magicOrder: new fields.ArrayField( + new fields.StringField({ required: true, nullable: false, initial: "" }), + { required: true, initial: [] } + ), magics: new fields.SchemaField({ internalcinnabar: magicField(), alchemy: magicField(), @@ -931,7 +934,7 @@ var KungfuDataModel = class extends foundry.abstract.TypeDataModel { orientation: stringField("yin"), // yin | yang | yinyang aspect: stringField("metal"), - // metal | eau | terre | feu | bois + // metal | water | earth | fire | wood skill: stringField("kungfu"), // kungfu | rangedcombat speciality: stringField(""), @@ -957,7 +960,7 @@ var SpellDataModel = class extends foundry.abstract.TypeDataModel { description: htmlField(""), specialityname: stringField(""), associatedelement: stringField("metal"), - // metal | eau | terre | feu | bois + // metal | water | earth | fire | wood hei: stringField(""), realizationtimeritual: stringField(""), realizationtimeaccelerated: stringField(""), @@ -1012,7 +1015,7 @@ var WeaponDataModel = class extends foundry.abstract.TypeDataModel { // contact | courte | mediane | longue | extreme obtainLevel: intField(0, { min: 0, max: 5 }), obtainDifficulty: intField(0, { min: 0, max: 3 }), - quantity: intField(1), + quantity: intField(1, { min: 0 }), notes: htmlField("") }; } @@ -1032,7 +1035,7 @@ var ArmorDataModel = class extends foundry.abstract.TypeDataModel { domain: stringField(""), obtainLevel: intField(0, { min: 0, max: 5 }), obtainDifficulty: intField(0, { min: 0, max: 3 }), - quantity: intField(1), + quantity: intField(1, { min: 0 }), notes: htmlField("") }; } @@ -1078,7 +1081,7 @@ var IngredientDataModel = class extends foundry.abstract.TypeDataModel { school: stringField("all"), obtainLevel: intField(0, { min: 0, max: 5 }), obtainDifficulty: intField(0, { min: 0, max: 3 }), - quantity: intField(1), + quantity: intField(1, { min: 0 }), notes: htmlField("") }; } @@ -1568,20 +1571,16 @@ async function showMagicPrompt(params) { aspectskill: Number(params.aspectskill ?? 0), bonusmalusskill: params.bonusmalusskill ?? 0, bonusauspiciousdice: params.bonusauspiciousdice ?? 0, - aspectspeciality: Number(params.aspectspeciality ?? 0), rolldifficulty: params.rolldifficulty ?? 1, - bonusmalusspeciality: params.bonusmalusspeciality ?? 0, - heispend: params.heispend ?? 0, + freepowerlevels: params.freepowerlevels ?? 0, typeofthrow: Number(params.typeofthrow ?? 0) }, fields: [ "aspectskill", "bonusmalusskill", "bonusauspiciousdice", - "aspectspeciality", "rolldifficulty", - "bonusmalusspeciality", - "heispend", + "freepowerlevels", "typeofthrow" ] }); @@ -1711,7 +1710,9 @@ async function rollForActor(actor, rollKey) { const kfSkill = kfItem.system.skill ?? "kungfu"; numberofdice = sys.skills?.[kfSkill]?.value ?? 0; title = `${kfItem.name} [${game.i18n.localize(sys.skills?.[kfSkill]?.label ?? "CDE.KungFu")}]`; - kfDefaultAspect = ASPECT_NAMES.indexOf(kfItem.system.aspect ?? "metal"); + const kfAspect = kfItem.system.aspect?.toLowerCase() ?? "metal"; + const ASPECT_NORMALIZE = { eau: "water", terre: "earth", feu: "fire", bois: "wood" }; + kfDefaultAspect = ASPECT_NAMES.indexOf(ASPECT_NORMALIZE[kfAspect] ?? kfAspect); if (kfDefaultAspect < 0) kfDefaultAspect = 0; break; } @@ -1813,7 +1814,10 @@ async function rollForActor(actor, rollKey) { d0: wpFaces[0] }, wpRoll, ROLL_MODES[wpThrowMode] ?? "roll"); if (game.modules.get("dice-so-nice")?.active && wpMsg?.id) { - await game.dice3d.waitFor3DAnimationByMessageID(wpMsg.id); + try { + await game.dice3d.waitFor3DAnimationByMessageID(wpMsg.id); + } catch (_e) { + } } if ((wpResults.loksyudice ?? 0) > 0) await updateLoksyuFromRoll(wpAspectName, wpFaces); if ((wpResults.tinjidice ?? 0) > 0) await updateTinjiFromRoll(wpResults.tinjidice); @@ -1846,14 +1850,6 @@ async function rollForActor(actor, rollKey) { if (kfDefaultAspect >= 0) { defaultAspect = kfDefaultAspect; } - let defaultSpecialAspect = 0; - if (isMagicSpecial && specialLibel) { - const specialCfg = MAGICS?.[skillLibel]?.speciality?.[specialLibel]; - const aspectName = LABELELEMENT_TO_ASPECT[specialCfg?.labelelement]; - if (aspectName) { - defaultSpecialAspect = ASPECT_NAMES.indexOf(aspectName); - } - } let params; if (isMagic) { params = await showMagicPrompt({ @@ -1862,10 +1858,8 @@ async function rollForActor(actor, rollKey) { aspectskill: defaultAspect, bonusmalusskill: 0, bonusauspiciousdice: 0, - aspectspeciality: defaultSpecialAspect, rolldifficulty: 1, - bonusmalusspeciality: 0, - heispend: 0, + freepowerlevels: 0, typeofthrow: typeOfThrow }); } else { @@ -1882,20 +1876,16 @@ async function rollForActor(actor, rollKey) { } if (!params) return; let aspectIndex, bonusMalus, bonusAuspicious, throwMode; - let spellAspectIndex = null; let rollDifficulty = 1; if (isMagic) { const skillAspectIndex = Number(params.aspectskill ?? 0); - spellAspectIndex = Number(params.aspectspeciality ?? skillAspectIndex); aspectIndex = skillAspectIndex; bonusMalus = Number(params.bonusmalusskill ?? 0); bonusAuspicious = Number(params.bonusauspiciousdice ?? 0); rollDifficulty = Math.max(1, Number(params.rolldifficulty ?? 1)); throwMode = Number(params.typeofthrow ?? 0); const aspectDice = sys.aspect?.[ASPECT_NAMES[aspectIndex]]?.value ?? 0; - const bonusSpec = Number(params.bonusmalusspeciality ?? 0); - const heiDice = Number(params.heispend ?? 0); - numberofdice = numberofdice + aspectDice + bonusMalus + 1 + bonusSpec + heiDice; + numberofdice = numberofdice + aspectDice + bonusMalus + 1; } else { aspectIndex = Number(params.aspect ?? 0); bonusMalus = Number(params.bonusmalus ?? 0); @@ -1913,22 +1903,33 @@ async function rollForActor(actor, rollKey) { const roll = new Roll(`${numberofdice}d10`); await roll.evaluate(); const rollModeKey = ROLL_MODES[throwMode] ?? "roll"; - const wuXingAspectName = spellAspectIndex !== null ? ASPECT_NAMES[spellAspectIndex] : ASPECT_NAMES[aspectIndex]; + let spellPower = null; + let spellPowerAspectName = null; + let spellPowerAspectValue = null; + if (isMagic) { + if (isMagicSpecial && specialLibel) { + const specialCfg = MAGICS?.[skillLibel]?.speciality?.[specialLibel]; + const elemName = LABELELEMENT_TO_ASPECT[specialCfg?.labelelement]; + if (elemName) spellPowerAspectName = elemName; + } + if (!spellPowerAspectName) spellPowerAspectName = ASPECT_NAMES[aspectIndex]; + spellPowerAspectValue = sys.aspect?.[spellPowerAspectName]?.value ?? 0; + const freePowerLevels = Number(params.freepowerlevels ?? 0); + spellPower = rollDifficulty * (spellPowerAspectValue + freePowerLevels); + } + const wuXingAspectName = ASPECT_NAMES[aspectIndex]; const allResults = roll.dice[0]?.results ?? []; const faces = countFaces(allResults); const results = computeWuXingResults(faces, wuXingAspectName, bonusAuspicious); if (!results) return; - const spellPower = isMagic ? results.successesdice * rollDifficulty : null; const modParts = []; if (isMagic) { const bm = Number(params.bonusmalusskill ?? 0); - const bs = Number(params.bonusmalusspeciality ?? 0); - const hs = Number(params.heispend ?? 0); const ba = Number(params.bonusauspiciousdice ?? 0); + const fp = Number(params.freepowerlevels ?? 0); if (bm !== 0) modParts.push(`${bm > 0 ? "+" : ""}${bm} ${game.i18n.localize("CDE.BonusMalus")}`); - if (bs !== 0) modParts.push(`${bs > 0 ? "+" : ""}${bs} ${game.i18n.localize("CDE.SpellBonus")}`); if (ba !== 0) modParts.push(`+${ba} ${game.i18n.localize("CDE.BonusAuspiciousDice")}`); - if (hs !== 0) modParts.push(`${hs} ${game.i18n.localize("CDE.HeiSpend")}`); + if (fp !== 0) modParts.push(`+${fp} ${game.i18n.localize("CDE.FreePowerLevels")}`); if (rollDifficulty !== 1) modParts.push(`\xD7${rollDifficulty} ${game.i18n.localize("CDE.RollDifficulty")}`); } else { const bm = Number(params.bonusmalus ?? 0); @@ -1948,6 +1949,9 @@ async function rollForActor(actor, rollKey) { modifiersText: modParts.length ? modParts.join(" \xB7 ") : "", // Spell power (magic only) spellPower, + spellPowerAspectLabel: spellPowerAspectName ? game.i18n.localize(ASPECT_LABELS[spellPowerAspectName] ?? "") : "", + spellPowerAspectValue, + spellPowerFreeLevels: isMagic ? Number(params.freepowerlevels ?? 0) : 0, rollDifficulty: isMagic ? rollDifficulty : null, // Actor info actorName: actor.name ?? "", @@ -1968,7 +1972,10 @@ async function rollForActor(actor, rollKey) { d0: faces[0] }, roll, rollModeKey); if (game.modules.get("dice-so-nice")?.active && msg?.id) { - await game.dice3d.waitFor3DAnimationByMessageID(msg.id); + try { + await game.dice3d.waitFor3DAnimationByMessageID(msg.id); + } catch (_e) { + } } if ((results.loksyudice ?? 0) > 0) await updateLoksyuFromRoll(wuXingAspectName, faces); if ((results.tinjidice ?? 0) > 0) await updateTinjiFromRoll(results.tinjidice); @@ -2064,9 +2071,13 @@ var CDEBaseActorSheet = class _CDEBaseActorSheet extends HandlebarsApplicationMi }; // src/ui/sheets/actors/character.js -var CDECharacterSheet = class extends CDEBaseActorSheet { +var CDECharacterSheet = class _CDECharacterSheet extends CDEBaseActorSheet { static DEFAULT_OPTIONS = { - classes: ["character"] + classes: ["character"], + actions: { + moveMagicUp: _CDECharacterSheet.#onMoveMagicUp, + moveMagicDown: _CDECharacterSheet.#onMoveMagicDown + } }; static PARTS = { main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/actor/cde-character-sheet.html" } @@ -2089,25 +2100,35 @@ var CDECharacterSheet = class extends CDEBaseActorSheet { spellsByDiscipline[disc].push(spell); } const systemMagics = context.systemData.magics ?? {}; - context.magicsDisplay = Object.fromEntries( - Object.entries(MAGICS).map(([magicKey, magicDef]) => { - const magicData = systemMagics[magicKey] ?? {}; - return [ - magicKey, - { - value: magicData.value ?? 0, - visible: magicData.visible ?? false, - speciality: Object.fromEntries( - Object.keys(magicDef.speciality).map((specKey) => [ - specKey, - { check: magicData.speciality?.[specKey]?.check ?? false } - ]) - ), - grimoire: spellsByDiscipline[magicKey] ?? [] - } - ]; - }) - ); + const magicEntries = Object.entries(MAGICS).map(([magicKey, magicDef]) => { + const magicData = systemMagics[magicKey] ?? {}; + return [ + magicKey, + { + value: magicData.value ?? 0, + visible: magicData.visible ?? false, + speciality: Object.fromEntries( + Object.keys(magicDef.speciality).map((specKey) => [ + specKey, + { check: magicData.speciality?.[specKey]?.check ?? false } + ]) + ), + grimoire: spellsByDiscipline[magicKey] ?? [] + } + ]; + }); + const order = context.systemData.magicOrder ?? []; + if (order.length > 0) { + magicEntries.sort((a, b) => { + const ia = order.indexOf(a[0]); + const ib = order.indexOf(b[0]); + if (ia === -1 && ib === -1) return 0; + if (ia === -1) return 1; + if (ib === -1) return -1; + return ia - ib; + }); + } + context.magicsDisplay = Object.fromEntries(magicEntries); return context; } _onRender(context, options) { @@ -2191,7 +2212,7 @@ var CDECharacterSheet = class extends CDEBaseActorSheet { cell.addEventListener("click", (event) => { event.preventDefault(); const rollKey = cell.dataset.libelId; - if (rollKey) rollForActor(this.document, rollKey); + if (rollKey) rollForActor(this.document, rollKey)?.catch((err) => console.error("Roll failed:", err)); }); }); } @@ -2205,6 +2226,26 @@ var CDECharacterSheet = class extends CDEBaseActorSheet { }).render(true); }); } + static async #onMoveMagicUp(event, target) { + const key = target.dataset.magicKey; + let order = this.document.system.magicOrder ?? []; + if (!order.length) order = [...Object.keys(MAGICS)]; + else order = [...order]; + const idx = order.indexOf(key); + if (idx <= 0) return; + [order[idx - 1], order[idx]] = [order[idx], order[idx - 1]]; + await this.document.update({ "system.magicOrder": order }); + } + static async #onMoveMagicDown(event, target) { + const key = target.dataset.magicKey; + let order = this.document.system.magicOrder ?? []; + if (!order.length) order = [...Object.keys(MAGICS)]; + else order = [...order]; + const idx = order.indexOf(key); + if (idx === -1 || idx >= order.length - 1) return; + [order[idx], order[idx + 1]] = [order[idx + 1], order[idx]]; + await this.document.update({ "system.magicOrder": order }); + } #bindComponentRandomize() { const btn = this.element?.querySelector("[data-action='randomize-component']"); if (!btn) return; @@ -2274,7 +2315,7 @@ var CDENpcSheet = class extends CDEBaseActorSheet { cell.addEventListener("click", (event) => { event.preventDefault(); const rollKey = cell.dataset.libelId; - if (rollKey) rollForActor(this.document, rollKey); + if (rollKey) rollForActor(this.document, rollKey)?.catch((err) => console.error("Roll failed:", err)); }); }); } @@ -2461,11 +2502,11 @@ var CDESanheiSheet = class extends CDEBaseItemSheet { async _prepareContext() { const context = await super._prepareContext(); const enrich = (content) => foundry.applications.ux.TextEditor.implementation.enrichHTML(content ?? "", { async: true }); - const props = this.document.system.properties; - context.prop1DescriptionHTML = await enrich(props.prop1.description); - context.prop2DescriptionHTML = await enrich(props.prop2.description); - context.prop3DescriptionHTML = await enrich(props.prop3.description); - context.propFields = this.document.system.schema.fields.properties.fields; + const props = this.document.system.properties ?? {}; + context.prop1DescriptionHTML = await enrich(props.prop1?.description); + context.prop2DescriptionHTML = await enrich(props.prop2?.description); + context.prop3DescriptionHTML = await enrich(props.prop3?.description); + context.propFields = this.document.system.schema.fields.properties?.fields; return context; } }; @@ -2673,7 +2714,7 @@ var CDETinjiApp = class _CDETinjiApp extends foundry.applications.api.Handlebars return; } await setTinjiValue(current - 1); - ChatMessage.create({ + await ChatMessage.create({ user: game.user.id, content: `
@@ -2692,7 +2733,7 @@ var CDECombat = class extends Combat { * for each selected combatant, then sync the result to the Combatant document. */ async rollInitiative(ids, options = {}) { - const combatantIds = typeof ids === "string" ? [ids] : ids; + const combatantIds = ids ? typeof ids === "string" ? [ids] : ids : this.combatants.map((c) => c.id); for (const id of combatantIds) { const combatant = this.combatants.get(id); if (!combatant) continue; @@ -2994,7 +3035,7 @@ async function _drawFromLoksyu(message, aspect, type, aspectLabel) { } const remain = entry.yin + entry.yang; const typeLabel = type === "success" ? game.i18n.localize("CDE.Successes") : game.i18n.localize("CDE.AuspiciousDie"); - ChatMessage.create({ + await ChatMessage.create({ user: game.user.id, content: `
@@ -3020,7 +3061,7 @@ async function _spendTinjiPostRoll() { return; } await setTinjiValue(current - 1); - ChatMessage.create({ + await ChatMessage.create({ user: game.user.id, content: `
\u5929 diff --git a/dist/system.js.map b/dist/system.js.map index bfbf541..322bd4f 100644 --- a/dist/system.js.map +++ b/dist/system.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/config/constants.js", "../src/migration/migrator.js", "../src/ui/apps/migration-app.js", "../src/config/settings.js", "../src/config/localize.js", "../src/config/runtime.js", "../src/data/actors/character.js", "../src/data/actors/npc.js", "../src/data/items/item.js", "../src/data/items/kungfu.js", "../src/data/items/spell.js", "../src/data/items/supernatural.js", "../src/data/items/weapon.js", "../src/data/items/armor.js", "../src/data/items/sanhei.js", "../src/data/items/ingredient.js", "../src/documents/chat-message.js", "../src/documents/actor.js", "../src/documents/item.js", "../src/ui/dice.js", "../src/ui/helpers.js", "../src/ui/templates.js", "../src/ui/initiative.js", "../src/ui/apps/singletons.js", "../src/ui/rolling.js", "../src/ui/sheets/actors/base.js", "../src/ui/sheets/actors/character.js", "../src/ui/sheets/actors/npc.js", "../src/ui/sheets/items/base.js", "../src/ui/sheets/items/item.js", "../src/ui/sheets/items/kungfu.js", "../src/ui/sheets/items/spell.js", "../src/ui/sheets/items/supernatural.js", "../src/ui/sheets/items/weapon.js", "../src/ui/sheets/items/armor.js", "../src/ui/sheets/items/sanhei.js", "../src/ui/sheets/items/ingredient.js", "../src/ui/apps/loksyu-app.js", "../src/ui/apps/tinji-app.js", "../src/documents/combat.js", "../src/ui/apps/wheel-app.js", "../src/ui/roll-actions.js", "../src/ui/apps/welcome.js", "../src/system.js"], - "sourcesContent": ["/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport const SYSTEM_ID = \"fvtt-chroniques-de-l-etrange\"\n\nexport const ACTOR_TYPES = {\n character: \"character\",\n npc: \"npc\",\n}\n\nexport const ITEM_TYPES = {\n item: \"item\",\n kungfu: \"kungfu\",\n spell: \"spell\",\n supernatural: \"supernatural\",\n weapon: \"weapon\",\n armor: \"armor\",\n sanhei: \"sanhei\",\n ingredient: \"ingredient\",\n}\n\nexport const SUBTYPES = {\n weapon: { id: \"weapon\", label: \"CDE.Weapon\" },\n armor: { id: \"armor\", label: \"CDE.Armor\" },\n sanhei: { id: \"sanhei\", label: \"CDE.Sanhei\" },\n other: { id: \"other\", label: \"CDE.Other\" },\n}\n\nexport const MAGICS = {\n internalcinnabar: {\n id: \"internalcinnabar\",\n background: \"linear-grey\",\n label: \"CDE.InternalCinnabar\",\n aspectlabel: \"CDE.Metal\",\n speciality: {\n essence: { label: \"CDE.Essence\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n mind: { label: \"CDE.Mind\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n purification: { label: \"CDE.Purification\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n manipulation: { label: \"CDE.Manipulation\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n aura: { label: \"CDE.Aura\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\", labelicon: \"Yang\", labelelement: \"CDE.Wood\" },\n },\n },\n alchemy: {\n id: \"alchemy\",\n background: \"linear-blue\",\n label: \"CDE.Alchemy\",\n aspectlabel: \"CDE.Water\",\n speciality: {\n acupuncture: { label: \"CDE.Acupuncture\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n elixirs: { label: \"CDE.Elixirs\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n poisons: { label: \"CDE.Poisons\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n arsenal: { label: \"CDE.Arsenal\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n potions: { label: \"CDE.Potions\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\", labelicon: \"Yang\", labelelement: \"CDE.Wood\" },\n },\n },\n masteryoftheway: {\n id: \"masteryoftheway\",\n background: \"linear-brown\",\n label: \"CDE.MasteryOfTheWay\",\n aspectlabel: \"CDE.Earth\",\n speciality: {\n curse: { label: \"CDE.Curse\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n transfiguration: { label: \"CDE.Transfiguration\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n necromancy: { label: \"CDE.Necromancy\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n climatecontrol: { label: \"CDE.ClimateControl\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n goldenmagic: { label: \"CDE.GoldenMagic\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\", labelicon: \"Yang\", labelelement: \"CDE.Wood\" },\n },\n },\n exorcism: {\n id: \"exorcism\",\n background: \"linear-red\",\n label: \"CDE.Exorcism\",\n aspectlabel: \"CDE.Fire\",\n speciality: {\n invocation: { label: \"CDE.Invocation\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n tracking: { label: \"CDE.Tracking\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n protection: { label: \"CDE.Protection\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n punishment: { label: \"CDE.Punishment\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n domination: { label: \"CDE.Domination\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\", labelicon: \"Yang\", labelelement: \"CDE.Wood\" },\n },\n },\n geomancy: {\n id: \"geomancy\",\n background: \"linear-green\",\n label: \"CDE.Geomancy\",\n aspectlabel: \"CDE.Wood\",\n speciality: {\n neutralization: { label: \"CDE.Neutralization\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n divination: { label: \"CDE.Divination\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n earthlyprayer: { label: \"CDE.EarthlyPrayer\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n heavenlyprayer: { label: \"CDE.HeavenlyPrayer\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n fungseoi: { label: \"CDE.Fungseoi\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\", labelicon: \"Yang\", labelelement: \"CDE.Wood\" },\n },\n },\n}\n\n/** Map aspect name \u2192 i18n label key */\nexport const ASPECT_LABELS = {\n metal: \"CDE.Metal\",\n water: \"CDE.Water\",\n earth: \"CDE.Earth\",\n fire: \"CDE.Fire\",\n wood: \"CDE.Wood\",\n}\n\n/** Map aspect name \u2192 image path */\nexport const ASPECT_ICONS = {\n metal: \"systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\",\n water: \"systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\",\n earth: \"systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\",\n fire: \"systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\",\n wood: \"systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\",\n}\n\n/** Map aspect name \u2192 die face pair [yin, yang] (face=10 stored as 0) */\nexport const ASPECT_FACES = {\n metal: [3, 8],\n water: [1, 6],\n earth: [0, 5], // 0 = face \"10\"\n fire: [2, 7],\n wood: [4, 9],\n}\n\n/** Ordered aspect names by index (metal=0, water=1, earth=2, fire=3, wood=4) */\nexport const ASPECT_NAMES = [\"metal\", \"water\", \"earth\", \"fire\", \"wood\"]\n\n/**\n * Wu Xing generating/overcoming cycle.\n * For each active aspect, the five result categories in order:\n * [successes, auspicious, noxious, loksyu, tinji]\n */\nexport const WU_XING_CYCLE = {\n wood: [\"wood\", \"fire\", \"water\", \"earth\", \"metal\"],\n fire: [\"fire\", \"earth\", \"wood\", \"metal\", \"water\"],\n earth: [\"earth\", \"metal\", \"fire\", \"water\", \"wood\"],\n metal: [\"metal\", \"water\", \"earth\", \"wood\", \"fire\"],\n water: [\"water\", \"wood\", \"metal\", \"fire\", \"earth\"],\n}\n\nexport const TEMPLATE_PARTIALS = [\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-character-skills.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-character-magics.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-character-nghang.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-character-treasures.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-character-items.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-character-kungfus.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-npc-supernaturals.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-npc-spells.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-npc-kungfus.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-npc-items.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-loksyu-app.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-tinji-app.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-wheel-app.html\",\n]\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\n/**\n * Migrates actor JSON from the legacy CDE system to the current system format.\n *\n * This module is pure logic \u2014 it does not interact with Foundry APIs directly.\n * All transformation is done in-memory; the caller is responsible for creating\n * Foundry documents from the returned data.\n */\n\n// \u2500\u2500 Element label \u2192 key \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst ELEMENT_LABEL_TO_KEY = {\n \"m\u00E9tal\": \"metal\",\n \"metal\": \"metal\",\n \"eau\": \"eau\",\n \"terre\": \"terre\",\n \"feu\": \"feu\",\n \"bois\": \"bois\",\n}\n\n/** Normalise a French element label to its system key (e.g. \"M\u00E9tal\" \u2192 \"metal\"). */\nfunction elementKey(label = \"\") {\n return ELEMENT_LABEL_TO_KEY[label.toLowerCase().trim()] ?? \"metal\"\n}\n\n// \u2500\u2500 Hei polarity label \u2192 key \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction heiKey(label = \"\") {\n const l = label.toLowerCase().trim()\n if (l === \"yin/yang\" || l === \"yinyang\") return \"yinyang\"\n if (l === \"yang\") return \"yang\"\n return \"yin\"\n}\n\n// \u2500\u2500 Spell discipline inference from speciality name \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Maps French speciality labels (lowercase, accents stripped) \u2192 school key. */\nconst SPECIALITY_TO_DISCIPLINE = {\n // internalcinnabar\n \"essence\": \"internalcinnabar\",\n \"esprit\": \"internalcinnabar\",\n \"mind\": \"internalcinnabar\",\n \"purification\": \"internalcinnabar\",\n \"manipulation\": \"internalcinnabar\",\n \"aura\": \"internalcinnabar\",\n // alchemy\n \"acupuncture\": \"alchemy\",\n \"\u00E9lixirs\": \"alchemy\",\n \"elixirs\": \"alchemy\",\n \"poisons\": \"alchemy\",\n \"arsenal\": \"alchemy\",\n \"potions\": \"alchemy\",\n // masteryoftheway\n \"mal\u00E9diction\": \"masteryoftheway\",\n \"malediction\": \"masteryoftheway\",\n \"transfiguration\": \"masteryoftheway\",\n \"n\u00E9cromancie\": \"masteryoftheway\",\n \"necromancie\": \"masteryoftheway\",\n \"contr\u00F4le climatique\": \"masteryoftheway\",\n \"controle climatique\": \"masteryoftheway\",\n \"magie d'or\": \"masteryoftheway\",\n \"magie dor\": \"masteryoftheway\",\n // exorcism\n \"invocation\": \"exorcism\",\n \"pistage\": \"exorcism\",\n \"tra\u00E7age\": \"exorcism\",\n \"tracage\": \"exorcism\",\n \"protection\": \"exorcism\",\n \"ch\u00E2timent\": \"exorcism\",\n \"chatiment\": \"exorcism\",\n \"domination\": \"exorcism\",\n // geomancy\n \"neutralisation\": \"geomancy\",\n \"divination\": \"geomancy\",\n \"pri\u00E8re terrestre\": \"geomancy\",\n \"priere terrestre\": \"geomancy\",\n \"pri\u00E8re c\u00E9leste\": \"geomancy\",\n \"priere celeste\": \"geomancy\",\n \"g\u00E9omancie\": \"geomancy\",\n \"geomancie\": \"geomancy\",\n \"feng shui\": \"geomancy\",\n \"fungseoi\": \"geomancy\",\n}\n\n/**\n * Attempt to infer the magic school (discipline) from a spell's speciality name.\n * Falls back to scanning the item name for school keywords if needed.\n */\nfunction inferDiscipline(specialityName = \"\", itemName = \"\") {\n const key = specialityName.toLowerCase().trim()\n if (SPECIALITY_TO_DISCIPLINE[key]) return SPECIALITY_TO_DISCIPLINE[key]\n\n // Fuzzy fallback: check item name for school markers\n const name = itemName.toLowerCase()\n if (name.includes(\"exorcis\")) return \"exorcism\"\n if (name.includes(\"g\u00E9omanci\") || name.includes(\"geomanci\")) return \"geomancy\"\n if (name.includes(\"alchimi\")) return \"alchemy\"\n if (name.includes(\"cinnabre\") || name.includes(\"interne\")) return \"internalcinnabar\"\n if (name.includes(\"ma\u00EEtrise\") || name.includes(\"maitrise\") || name.includes(\"tao\")) return \"masteryoftheway\"\n\n return \"internalcinnabar\"\n}\n\n// \u2500\u2500 KungFu activation mapping \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction mapActivation(oldActivation = \"\") {\n const s = oldActivation.toLowerCase()\n if (s.includes(\"inflig\u00E9s\") || s.includes(\"infliges\")) return \"damage-inflicted\"\n if (s.includes(\"re\u00E7us\") || s.includes(\"recus\")) return \"damage-received\"\n if (s.includes(\"r\u00E9action\") || s.includes(\"reaction\")) return \"reaction\"\n if (s.includes(\"d\u00E9s-fastes\") || s.includes(\"des-fastes\") || s.includes(\"fastes\")) return \"dice\"\n if (s.includes(\"aide\")) return \"action-aid\"\n if (s.includes(\"attaque\") && s.includes(\"d\u00E9fense\")) return \"action-attack-defense\"\n if (s.includes(\"attaque\") && s.includes(\"defense\")) return \"action-attack-defense\"\n if (s.includes(\"attaque\")) return \"action-attack\"\n if (s.includes(\"d\u00E9fense\") || s.includes(\"defense\")) return \"action-defense\"\n return \"action-attack\"\n}\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst DEFAULT_ACTOR_IMG = \"icons/svg/mystery-man.svg\"\nconst DEFAULT_ITEM_IMG = \"icons/svg/item-bag.svg\"\n\n// \u2500\u2500 Item migration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction migrateEquipmentItem(oldItem) {\n const s = oldItem.system ?? {}\n return {\n name: oldItem.name,\n type: \"item\",\n img: oldItem.img || DEFAULT_ITEM_IMG,\n system: {\n reference: s.reference ?? \"\",\n description: s.description ?? \"\",\n quantity: Number(s.quantity ?? 1),\n weight: Number(s.weight ?? 0),\n notes: s.notes ?? \"\",\n },\n }\n}\n\nfunction migrateKungfuItem(oldItem) {\n const s = oldItem.system ?? {}\n const techs = s.techniques ?? {}\n\n const migratedTechs = {}\n for (const key of [\"technique1\", \"technique2\", \"technique3\"]) {\n const t = techs[key] ?? {}\n migratedTechs[key] = {\n check: Boolean(t.check),\n name: t.name ?? \"\",\n activation: mapActivation(t.activation ?? \"\"),\n technique: t.technique ?? \"\",\n }\n }\n\n return {\n name: oldItem.name,\n type: \"kungfu\",\n img: oldItem.img || DEFAULT_ITEM_IMG,\n system: {\n reference: s.reference ?? \"\",\n description: s.description ?? \"\",\n orientation: s.orientation || \"yin\",\n aspect: s.aspect || \"metal\",\n skill: s.skill || \"kungfu\",\n speciality: s.speciality ?? \"\",\n style: s.style ?? \"\",\n techniques: migratedTechs,\n notes: s.notes ?? \"\",\n },\n }\n}\n\nfunction migrateSpellItem(oldItem) {\n const s = oldItem.system ?? {}\n return {\n name: oldItem.name,\n type: \"spell\",\n img: oldItem.img || DEFAULT_ITEM_IMG,\n system: {\n reference: s.reference ?? \"\",\n description: s.description ?? \"\",\n specialityname: s.specialityname ?? \"\",\n associatedelement: elementKey(s.associatedelement ?? \"\"),\n heiType: heiKey(s.hei ?? \"\"),\n heiCost: Number(s.heiCost ?? 0),\n difficulty: Number(s.difficulty ?? 0),\n realizationtimeritual: s.realizationtimeritual ?? \"\",\n realizationtimeaccelerated: s.realizationtimeaccelerated ?? \"\",\n flashback: s.flashback ?? \"\",\n components: s.components ?? \"\",\n effects: s.effects ?? \"\",\n examples: s.examples ?? \"\",\n notes: s.notes ?? \"\",\n discipline: inferDiscipline(s.specialityname ?? \"\", oldItem.name ?? \"\"),\n },\n }\n}\n\nfunction migrateSupernaturalItem(oldItem) {\n const s = oldItem.system ?? {}\n // Old system stored a nested `supernatural: { reference }` \u2014 prefer that reference if top-level is empty\n const nestedRef = s.supernatural?.reference ?? \"\"\n return {\n name: oldItem.name,\n type: \"supernatural\",\n img: oldItem.img || DEFAULT_ITEM_IMG,\n system: {\n reference: s.reference || nestedRef,\n description: s.description ?? \"\",\n notes: s.notes ?? \"\",\n heiType: \"yin\",\n heiCost: 0,\n trigger: \"\",\n effects: \"\",\n },\n }\n}\n\nfunction migrateItem(oldItem) {\n switch (oldItem.type) {\n case \"item\": return migrateEquipmentItem(oldItem)\n case \"kungfu\": return migrateKungfuItem(oldItem)\n case \"spell\": return migrateSpellItem(oldItem)\n case \"supernatural\": return migrateSupernaturalItem(oldItem)\n default:\n // Unknown item type: keep as generic equipment\n return migrateEquipmentItem({ ...oldItem, type: \"item\" })\n }\n}\n\n// \u2500\u2500 Actor migration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction migrateCharacter(old) {\n const s = old.system ?? {}\n\n // aspects: keep only { chinese, label, value }\n const aspect = {}\n for (const [k, v] of Object.entries(s.aspect ?? {})) {\n aspect[k] = { chinese: v.chinese ?? \"\", label: v.label ?? \"\", value: Number(v.value ?? 0) }\n }\n\n // skills: keep { label, specialities, value }\n const skills = {}\n for (const [k, v] of Object.entries(s.skills ?? {})) {\n skills[k] = { label: v.label ?? \"\", specialities: v.specialities ?? \"\", value: Number(v.value ?? 0) }\n }\n\n // resources: keep { label, specialities, value, debt }\n const resources = {}\n for (const [k, v] of Object.entries(s.resources ?? {})) {\n resources[k] = { label: v.label ?? \"\", specialities: v.specialities ?? \"\", value: Number(v.value ?? 0), debt: Boolean(v.debt) }\n }\n\n // components: keep { value }\n const component = {}\n for (const [k, v] of Object.entries(s.component ?? {})) {\n component[k] = { value: v.value ?? \"\" }\n }\n\n // magics: keep { visible, value, speciality: { [key]: { check } } }\n const MAGIC_SPECIALITIES = {\n internalcinnabar: [\"essence\", \"mind\", \"purification\", \"manipulation\", \"aura\"],\n alchemy: [\"acupuncture\", \"elixirs\", \"poisons\", \"arsenal\", \"potions\"],\n masteryoftheway: [\"curse\", \"transfiguration\", \"necromancy\", \"climatecontrol\", \"goldenmagic\"],\n exorcism: [\"invocation\", \"tracking\", \"protection\", \"punishment\", \"domination\"],\n geomancy: [\"neutralization\", \"divination\", \"earthlyprayer\", \"heavenlyprayer\", \"fungseoi\"],\n }\n const magics = {}\n for (const [school, specs] of Object.entries(MAGIC_SPECIALITIES)) {\n const om = s.magics?.[school] ?? {}\n const speciality = {}\n for (const spec of specs) {\n speciality[spec] = { check: Boolean(om.speciality?.[spec]?.check) }\n }\n magics[school] = { visible: Boolean(om.visible), value: Number(om.value ?? 0), speciality }\n }\n\n // threetreasures: strip `min` from heiyang/heiyin; keep dicelevel as-is\n const tt = s.threetreasures ?? {}\n const threetreasures = {\n heiyang: { value: Number(tt.heiyang?.value ?? 0), max: Number(tt.heiyang?.max ?? 0) },\n heiyin: { value: Number(tt.heiyin?.value ?? 0), max: Number(tt.heiyin?.max ?? 0) },\n dicelevel: {\n level0d: {\n san: { value: Number(tt.dicelevel?.level0d?.san?.value ?? 0), max: Number(tt.dicelevel?.level0d?.san?.max ?? 0) },\n zing: { value: Number(tt.dicelevel?.level0d?.zing?.value ?? 0), max: Number(tt.dicelevel?.level0d?.zing?.max ?? 0) },\n },\n level1d: {\n san: { value: Number(tt.dicelevel?.level1d?.san?.value ?? 0), max: Number(tt.dicelevel?.level1d?.san?.max ?? 0) },\n zing: { value: Number(tt.dicelevel?.level1d?.zing?.value ?? 0), max: Number(tt.dicelevel?.level1d?.zing?.max ?? 0) },\n },\n level2d: {\n san: { value: Number(tt.dicelevel?.level2d?.san?.value ?? 0), max: Number(tt.dicelevel?.level2d?.san?.max ?? 0) },\n zing: { value: Number(tt.dicelevel?.level2d?.zing?.value ?? 0), max: Number(tt.dicelevel?.level2d?.zing?.max ?? 0) },\n },\n },\n }\n\n // biography (old separate field) merged into description\n const description = s.description || s.biography || \"\"\n\n return {\n name: old.name,\n type: \"character\",\n img: old.img || DEFAULT_ACTOR_IMG,\n system: {\n concept: s.concept ?? \"\",\n guardian: parseInt(s.guardian ?? \"0\") || 0,\n initiative: Number(s.initiative ?? 1),\n anti_initiative: Number(s.anti_initiative ?? 24),\n description,\n aspect,\n skills,\n resources,\n component,\n magics,\n threetreasures,\n experience: {\n value: Number(s.experience?.value ?? 0),\n max: Number(s.experience?.max ?? 0),\n min: Number(s.experience?.min ?? 0),\n },\n },\n items: (old.items ?? []).map(migrateItem),\n }\n}\n\nfunction migrateNpc(old) {\n const s = old.system ?? {}\n\n const aptitudes = {}\n for (const [k, v] of Object.entries(s.aptitudes ?? {})) {\n aptitudes[k] = { value: Number(v.value ?? 0), speciality: v.speciality ?? \"\" }\n }\n\n return {\n name: old.name,\n type: \"npc\",\n img: old.img || DEFAULT_ACTOR_IMG,\n system: {\n type: s.type ?? \"\",\n // Old system had separate `levelofthreat`/`powerofnuisance` as numbers\n // and string copies `threat`/`nuisance` \u2014 use the numeric fields\n threat: Number(s.levelofthreat ?? s.threat ?? 0),\n nuisance: Number(s.powerofnuisance ?? s.nuisance ?? 0),\n initiative: Number(s.initiative ?? 1),\n anti_initiative: Number(s.anti_initiative ?? 24),\n aptitudes,\n vitality: {\n value: Number(s.vitality?.value ?? 0),\n calcul: Number(s.vitality?.calcul ?? 0),\n note: s.vitality?.note ?? \"\",\n },\n hei: {\n value: Number(s.hei?.value ?? 0),\n calcul: Number(s.hei?.calcul ?? 0),\n note: s.hei?.note ?? \"\",\n },\n description: s.description ?? \"\",\n },\n items: (old.items ?? []).map(migrateItem),\n }\n}\n\n// \u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Migrate a single legacy actor JSON to the current system format.\n *\n * @param {object} oldJson Parsed JSON from the old system export\n * @returns {{ name: string, type: string, img: string, system: object, items: object[] }}\n * @throws {Error} if the actor type is unrecognised\n */\nexport function migrateActor(oldJson) {\n switch (oldJson.type) {\n case \"character\": return migrateCharacter(oldJson)\n case \"npc\": return migrateNpc(oldJson)\n default:\n throw new Error(`Unknown actor type \"${oldJson.type}\" in \"${oldJson.name}\"`)\n }\n}\n\n/**\n * Parse one or more legacy JSON strings and return migrated actor data.\n * Accepts a single actor object or an array of actor objects in one file.\n *\n * @param {string} jsonText Raw JSON text from a file\n * @returns {Array<{ name, type, img, system, items }>}\n */\nexport function parseLegacyJson(jsonText) {\n const parsed = JSON.parse(jsonText)\n if (typeof parsed !== \"object\" || parsed === null) {\n throw new Error(\"Le fichier JSON doit contenir un objet acteur ou un tableau d'acteurs\")\n }\n const actors = Array.isArray(parsed) ? parsed : [parsed]\n return actors.map(migrateActor)\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { parseLegacyJson } from \"../../migration/migrator.js\"\n\nconst MIGRATION_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-migration-app.html\"\n\n/**\n * Dialog for importing legacy CDE actor JSON files into the current system.\n *\n * Accessible via the System Settings menu (registerMenu).\n * Supports multi-file selection and shows a preview table before importing.\n */\nexport class CDEMigrationApp extends foundry.applications.api.HandlebarsApplicationMixin(\n foundry.applications.api.ApplicationV2\n) {\n static DEFAULT_OPTIONS = {\n id: \"cde-migration-app\",\n classes: [\"cde-migration-app\"],\n tag: \"div\",\n window: {\n title: \"CDE.MigrationTitle\",\n icon: \"fas fa-file-import\",\n resizable: false,\n },\n position: { width: 560, height: \"auto\" },\n actions: {\n clearFiles: CDEMigrationApp.#clearFiles,\n doImport: CDEMigrationApp.#doImport,\n },\n }\n\n static PARTS = {\n form: { template: MIGRATION_TEMPLATE },\n }\n\n /** @type {Array<{name: string, type: string, img: string, system: object, items: object[], _srcFile: string}>} */\n #pending = []\n\n /** @type {string[]} - error messages per file */\n #errors = []\n\n async _prepareContext(options) {\n return {\n pending: this.#pending,\n errors: this.#errors,\n hasPending: this.#pending.length > 0,\n hasErrors: this.#errors.length > 0,\n count: this.#pending.length,\n }\n }\n\n /** After render, wire up the file input. */\n _onRender(context, options) {\n super._onRender(context, options)\n const input = this.element.querySelector(\".cde-migration-file-input\")\n input?.addEventListener(\"change\", this.#onFileChange.bind(this))\n\n const dropZone = this.element.querySelector(\".cde-migration-drop-zone\")\n if (dropZone) {\n dropZone.addEventListener(\"dragover\", (e) => { e.preventDefault(); dropZone.classList.add(\"is-dragover\") })\n dropZone.addEventListener(\"dragleave\", () => dropZone.classList.remove(\"is-dragover\"))\n dropZone.addEventListener(\"drop\", (e) => {\n e.preventDefault()\n dropZone.classList.remove(\"is-dragover\")\n this.#processFiles(Array.from(e.dataTransfer.files))\n })\n }\n }\n\n async #onFileChange(event) {\n const files = Array.from(event.target.files ?? [])\n event.target.value = \"\"\n await this.#processFiles(files)\n }\n\n async #processFiles(files) {\n for (const file of files) {\n if (!file.name.endsWith(\".json\")) {\n this.#errors.push(game.i18n.format(\"CDE.MigrationErrorNotJson\", { file: file.name }))\n continue\n }\n try {\n const text = await file.text()\n const actors = parseLegacyJson(text)\n for (const actor of actors) {\n actor._srcFile = file.name\n // Avoid duplicates by name\n if (!this.#pending.some(p => p.name === actor.name)) {\n this.#pending.push(actor)\n }\n }\n } catch (err) {\n this.#errors.push(game.i18n.format(\"CDE.MigrationErrorParse\", { file: file.name, error: err.message }))\n }\n }\n this.render()\n }\n\n static async #clearFiles() {\n this.#pending = []\n this.#errors = []\n this.render()\n }\n\n static async #doImport() {\n if (!this.#pending.length) return\n\n const created = []\n const failed = []\n\n for (const data of this.#pending) {\n try {\n const { _srcFile, ...actorData } = data\n const actor = await Actor.create(actorData)\n created.push(actor.name)\n } catch (err) {\n failed.push(`${data.name}: ${err.message}`)\n console.error(`CHRONIQUESDELETRANGE | Migration failed for \"${data.name}\":`, err)\n }\n }\n\n this.#pending = []\n this.#errors = failed\n this.render()\n\n if (created.length) {\n ui.notifications.info(\n game.i18n.format(\"CDE.MigrationSuccess\", { count: created.length, names: created.join(\", \") })\n )\n }\n if (failed.length) {\n ui.notifications.warn(\n game.i18n.format(\"CDE.MigrationPartialError\", { count: failed.length })\n )\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { SYSTEM_ID } from \"./constants.js\"\nimport { CDEMigrationApp } from \"../ui/apps/migration-app.js\"\n\n/**\n * Register all world/client settings for the system.\n * Called during the \"init\" hook before sheets and data-models are set up.\n */\nexport function registerSettings() {\n game.settings.registerMenu(SYSTEM_ID, \"migrationTool\", {\n name: \"CDE.MigrationTitle\",\n label: \"CDE.MigrationMenuLabel\",\n hint: \"CDE.MigrationMenuHint\",\n icon: \"fas fa-file-import\",\n type: CDEMigrationApp,\n restricted: true,\n })\n\n game.settings.register(SYSTEM_ID, \"loksyuData\", {\n scope: \"world\",\n config: false,\n type: Object,\n default: {\n wood: { yin: 0, yang: 0 },\n fire: { yin: 0, yang: 0 },\n earth: { yin: 0, yang: 0 },\n metal: { yin: 0, yang: 0 },\n water: { yin: 0, yang: 0 },\n },\n })\n\n game.settings.register(SYSTEM_ID, \"loksyuConsumptionOrder\", {\n name: \"CDE.Settings.LoksyuConsumptionOrder\",\n hint: \"CDE.Settings.LoksyuConsumptionOrderHint\",\n scope: \"world\",\n config: true,\n type: String,\n choices: {\n \"yang-first\": \"CDE.Settings.LoksyuOrderYangFirst\",\n \"yin-first\": \"CDE.Settings.LoksyuOrderYinFirst\",\n \"balanced\": \"CDE.Settings.LoksyuOrderBalanced\",\n },\n default: \"yang-first\",\n onChange: () => Hooks.callAll(\"cde:loksyuUpdated\"),\n })\n\n game.settings.register(SYSTEM_ID, \"tinjiData\", {\n scope: \"world\",\n config: false,\n type: Number,\n default: 0,\n })\n\n game.settings.register(SYSTEM_ID, \"welcomeSceneLoaded\", {\n scope: \"world\",\n config: false,\n type: Boolean,\n default: false,\n })\n}\n\n/**\n * Run any pending data migrations on the \"ready\" hook.\n * Reserved for future schema migrations.\n */\nexport async function migrateIfNeeded() {\n // No migrations required yet.\n}\n\n/**\n * On first startup, import the \"Accueil\" scene from the cde-scenes compendium\n * into the world and activate it. Only runs once (tracked via the\n * `welcomeSceneLoaded` setting). GM-only.\n */\nexport async function loadWelcomeSceneIfNeeded() {\n if (!game.user.isGM) return\n if (game.settings.get(SYSTEM_ID, \"welcomeSceneLoaded\")) return\n\n try {\n const pack = game.packs.get(`${SYSTEM_ID}.cde-scenes`)\n if (!pack) return\n\n const index = await pack.getIndex()\n const entry = index.find(e => e.name === \"Accueil\")\n if (!entry) return\n\n // Check if the scene already exists in the world (e.g. manually imported)\n const existing = game.scenes.find(s => s.name === \"Accueil\")\n let scene = existing\n\n if (!scene) {\n const doc = await pack.getDocument(entry._id)\n ;[scene] = await Scene.createDocuments([doc.toObject()])\n }\n\n await game.settings.set(SYSTEM_ID, \"welcomeSceneLoaded\", true)\n await scene.activate()\n } catch (err) {\n console.error(\"CHRONIQUESDELETRANGE | loadWelcomeSceneIfNeeded failed:\", err)\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { MAGICS, SUBTYPES } from \"./constants.js\"\n\nexport function preLocalizeConfig() {\n const localizeConfigObject = (obj, keys) => {\n for (const o of Object.values(obj)) {\n for (const key of keys) {\n o[key] = game.i18n.localize(o[key])\n }\n }\n }\n\n localizeConfigObject(SUBTYPES, [\"label\"])\n Object.values(MAGICS).forEach((magic) => {\n magic.label = game.i18n.localize(magic.label)\n magic.aspectlabel = game.i18n.localize(magic.aspectlabel)\n Object.values(magic.speciality).forEach((spec) => {\n spec.label = game.i18n.localize(spec.label)\n spec.labelelement = game.i18n.localize(spec.labelelement)\n })\n })\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport function configureRuntime() {\n CONFIG.Actor.compendiumBanner = \"/systems/fvtt-chroniques-de-l-etrange/images/banners/actor-banner.webp\"\n CONFIG.Adventure.compendiumBanner = \"/systems/fvtt-chroniques-de-l-etrange/images/banners/adventure-banner.webp\"\n CONFIG.Cards.compendiumBanner = \"ui/banners/cards-banner.webp\"\n CONFIG.Item.compendiumBanner = \"/systems/fvtt-chroniques-de-l-etrange/images/banners/item-banner.webp\"\n CONFIG.JournalEntry.compendiumBanner = \"/systems/fvtt-chroniques-de-l-etrange/images/banners/journalentry-banner.webp\"\n CONFIG.Macro.compendiumBanner = \"ui/banners/macro-banner.webp\"\n CONFIG.Playlist.compendiumBanner = \"ui/banners/playlist-banner.webp\"\n CONFIG.RollTable.compendiumBanner = \"ui/banners/rolltable-banner.webp\"\n CONFIG.Scene.compendiumBanner = \"/systems/fvtt-chroniques-de-l-etrange/images/banners/scene-banner.webp\"\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class CharacterDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const numberField = (initial = 0, extra = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...extra })\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const boolField = (initial = false) => new fields.BooleanField({ required: true, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n const aspectField = (label, chinese) =>\n new fields.SchemaField({\n chinese: stringField(chinese),\n label: stringField(label),\n value: numberField(15, { min: 0 }),\n })\n\n const skillField = (label) =>\n new fields.SchemaField({\n label: stringField(label),\n specialities: stringField(\"\"),\n value: numberField(0, { min: 0 }),\n })\n\n const resourceField = (label) =>\n new fields.SchemaField({\n label: stringField(label),\n specialities: stringField(\"\"),\n value: numberField(0, { min: 0 }),\n debt: boolField(false),\n })\n\n const componentField = () =>\n new fields.SchemaField({\n value: stringField(\"\"),\n })\n\n const magicSpecialityField = () =>\n new fields.SchemaField({\n check: boolField(false),\n })\n\n const magicField = () =>\n new fields.SchemaField({\n visible: boolField(true),\n value: numberField(0, { min: 0 }),\n speciality: new fields.SchemaField({\n essence: magicSpecialityField(),\n mind: magicSpecialityField(),\n purification: magicSpecialityField(),\n manipulation: magicSpecialityField(),\n aura: magicSpecialityField(),\n acupuncture: magicSpecialityField(),\n elixirs: magicSpecialityField(),\n poisons: magicSpecialityField(),\n arsenal: magicSpecialityField(),\n potions: magicSpecialityField(),\n curse: magicSpecialityField(),\n transfiguration: magicSpecialityField(),\n necromancy: magicSpecialityField(),\n climatecontrol: magicSpecialityField(),\n goldenmagic: magicSpecialityField(),\n invocation: magicSpecialityField(),\n tracking: magicSpecialityField(),\n protection: magicSpecialityField(),\n punishment: magicSpecialityField(),\n domination: magicSpecialityField(),\n neutralization: magicSpecialityField(),\n divination: magicSpecialityField(),\n earthlyprayer: magicSpecialityField(),\n heavenlyprayer: magicSpecialityField(),\n fungseoi: magicSpecialityField(),\n }),\n })\n\n const treasureBranch = () =>\n new fields.SchemaField({\n value: numberField(0, { min: 0 }),\n max: numberField(0, { min: 0 }),\n min: numberField(0, { min: 0 }),\n })\n\n const treasureLevel = () =>\n new fields.SchemaField({\n san: treasureBranch(),\n zing: treasureBranch(),\n })\n\n const schema = {\n concept: stringField(\"\"),\n guardian: numberField(0, { min: 0, max: 5 }),\n initiative: numberField(1, { min: 0 }),\n anti_initiative: numberField(24, { min: 0 }),\n description: htmlField(\"\"),\n prefs: new fields.SchemaField({\n typeofthrow: new fields.SchemaField({\n check: boolField(true),\n choice: stringField(\"0\"),\n }),\n }),\n prompt: new fields.SchemaField({\n typeofthrow: new fields.SchemaField({\n check: boolField(true),\n choice: stringField(\"0\"),\n }),\n configure: new fields.SchemaField({\n numberofdice: numberField(0),\n aspect: numberField(0),\n bonus: numberField(0),\n bonusauspiciousdice: numberField(0),\n typeofthrow: numberField(0),\n aspectskill: numberField(0),\n bonusmalusskill: numberField(0),\n aspectspeciality: numberField(0),\n rolldifficulty: numberField(0),\n bonusmalusspeciality: numberField(0),\n }),\n }),\n aspect: new fields.SchemaField({\n fire: aspectField(\"CDE.Fire\", \"\u328B\"),\n earth: aspectField(\"CDE.Earth\", \"\u328F\"),\n metal: aspectField(\"CDE.Metal\", \"\u328E\"),\n water: aspectField(\"CDE.Water\", \"\u328C\"),\n wood: aspectField(\"CDE.Wood\", \"\u328D\"),\n }),\n skills: new fields.SchemaField({\n art: skillField(\"CDE.Art\"),\n investigation: skillField(\"CDE.Investigation\"),\n erudition: skillField(\"CDE.Erudition\"),\n knavery: skillField(\"CDE.Knavery\"),\n wordliness: skillField(\"CDE.Wordliness\"),\n prowess: skillField(\"CDE.Prowess\"),\n sciences: skillField(\"CDE.Sciences\"),\n technologies: skillField(\"CDE.Technologies\"),\n kungfu: skillField(\"CDE.KungFu\"),\n rangedcombat: skillField(\"CDE.RangedCombat\"),\n }),\n resources: new fields.SchemaField({\n supply: resourceField(\"CDE.Supply\"),\n inquiry: resourceField(\"CDE.Inquiry\"),\n influence: resourceField(\"CDE.Influence\"),\n }),\n component: new fields.SchemaField({\n one: componentField(),\n two: componentField(),\n three: componentField(),\n four: componentField(),\n five: componentField(),\n six: componentField(),\n seven: componentField(),\n eight: componentField(),\n nine: componentField(),\n zero: componentField(),\n }),\n magics: new fields.SchemaField({\n internalcinnabar: magicField(),\n alchemy: magicField(),\n masteryoftheway: magicField(),\n exorcism: magicField(),\n geomancy: magicField(),\n }),\n threetreasures: new fields.SchemaField({\n heiyang: new fields.SchemaField({ value: numberField(0, { min: 0 }), max: numberField(0, { min: 0 }) }),\n heiyin: new fields.SchemaField({ value: numberField(0, { min: 0 }), max: numberField(0, { min: 0 }) }),\n dicelevel: new fields.SchemaField({\n level0d: treasureLevel(),\n level1d: treasureLevel(),\n level2d: treasureLevel(),\n }),\n }),\n experience: new fields.SchemaField({\n value: numberField(0, { min: 0 }),\n max: numberField(0, { min: 0 }),\n min: numberField(0, { min: 0 }),\n }),\n }\n\n return schema\n }\n\n prepareDerivedData() {\n this.anti_initiative = 25 - (this.initiative ?? 0)\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class NpcDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const numberField = (initial = 0, extra = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...extra })\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const boolField = (initial = false) => new fields.BooleanField({ required: true, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n const aptitudeField = () =>\n new fields.SchemaField({\n value: numberField(0, { min: 0 }),\n speciality: stringField(\"\"),\n })\n\n const trackedField = () =>\n new fields.SchemaField({\n value: numberField(0, { min: 0 }),\n calcul: numberField(0, { min: 0 }),\n note: stringField(\"\"),\n })\n\n return {\n type: stringField(\"\"),\n threat: numberField(0, { min: 0, max: 4 }), // profane(0) | apprentice(1) | initiate(2) | accomplished(3) | renowned(4)\n nuisance: numberField(0, { min: 0, max: 5 }), // figurant(0) | minion(1) | adversary(2) | ally(3) | boss(4) | divinity(5)\n initiative: numberField(1, { min: 0 }),\n anti_initiative: numberField(24, { min: 0 }),\n aptitudes: new fields.SchemaField({\n physical: aptitudeField(),\n martial: aptitudeField(),\n mental: aptitudeField(),\n social: aptitudeField(),\n spiritual: aptitudeField(),\n }),\n vitality: trackedField(),\n hei: trackedField(),\n description: htmlField(\"\"),\n prefs: new fields.SchemaField({\n typeofthrow: new fields.SchemaField({\n check: boolField(false),\n choice: stringField(\"0\"),\n }),\n }),\n }\n }\n\n prepareDerivedData() {\n this.anti_initiative = 25 - (this.initiative ?? 0)\n this.vitality.calcul = (this.aptitudes.physical.value ?? 0) * 4\n this.hei.calcul = (this.aptitudes.spiritual.value ?? 0) * 4\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class EquipmentDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const numberField = (initial = 0, extra = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...extra })\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n quantity: numberField(1, { min: 0 }),\n weight: numberField(0, { min: 0 }),\n notes: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class KungfuDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n const boolField = (initial = false) => new fields.BooleanField({ required: true, initial })\n\n const techniqueField = () =>\n new fields.SchemaField({\n check: boolField(false),\n name: stringField(\"\"),\n activation: stringField(\"action-attack\"), // action-attack | action-defense | action-aid | action-attack-defense | reaction | dice | damage-inflicted | damage-received\n technique: htmlField(\"\"),\n })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n orientation: stringField(\"yin\"), // yin | yang | yinyang\n aspect: stringField(\"metal\"), // metal | eau | terre | feu | bois\n skill: stringField(\"kungfu\"), // kungfu | rangedcombat\n speciality: stringField(\"\"),\n style: stringField(\"\"),\n techniques: new fields.SchemaField({\n technique1: techniqueField(),\n technique2: techniqueField(),\n technique3: techniqueField(),\n }),\n notes: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class SpellDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n specialityname: stringField(\"\"),\n associatedelement: stringField(\"metal\"), // metal | eau | terre | feu | bois\n hei: stringField(\"\"),\n realizationtimeritual: stringField(\"\"),\n realizationtimeaccelerated: stringField(\"\"),\n flashback: stringField(\"\"),\n components: htmlField(\"\"),\n effects: htmlField(\"\"),\n examples: htmlField(\"\"),\n notes: htmlField(\"\"),\n discipline: stringField(\"internalcinnabar\"),\n heiType: stringField(\"yin\"),\n heiCost: new fields.NumberField({ required: true, nullable: false, integer: true, min: 0, initial: 1 }),\n difficulty: new fields.NumberField({ required: true, nullable: false, integer: true, min: 0, initial: 1 }),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class SupernaturalDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n notes: htmlField(\"\"),\n heiType: stringField(\"yin\"),\n heiCost: new fields.NumberField({ required: true, nullable: false, integer: true, min: 0, initial: 0 }),\n trigger: stringField(\"\"),\n effects: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class WeaponDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts })\n const boolField = (initial = false) => new fields.BooleanField({ required: true, initial })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n hasSpeciality: boolField(false),\n weaponType: stringField(\"melee\"),\n material: stringField(\"\"),\n damageAspect: stringField(\"metal\"),\n damageBase: intField(0),\n range: stringField(\"contact\"), // contact | courte | mediane | longue | extreme\n obtainLevel: intField(0, { min: 0, max: 5 }),\n obtainDifficulty: intField(0, { min: 0, max: 3 }),\n quantity: intField(1),\n notes: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class ArmorDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n protectionValue: intField(0),\n domain: stringField(\"\"),\n obtainLevel: intField(0, { min: 0, max: 5 }),\n obtainDifficulty: intField(0, { min: 0, max: 3 }),\n quantity: intField(1),\n notes: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class SanheiDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts })\n\n const propertySchema = () => new fields.SchemaField({\n name: stringField(\"\"),\n heiCost: intField(0),\n heiType: stringField(\"yin\"),\n description: htmlField(\"\"),\n })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n heiType: stringField(\"yin\"),\n properties: new fields.SchemaField({\n prop1: propertySchema(),\n prop2: propertySchema(),\n prop3: propertySchema(),\n }),\n notes: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class IngredientDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n school: stringField(\"all\"),\n obtainLevel: intField(0, { min: 0, max: 5 }),\n obtainDifficulty: intField(0, { min: 0, max: 3 }),\n quantity: intField(1),\n notes: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport class CDEMessage extends ChatMessage {\n async renderHTML({ canDelete, canClose = false, ...rest } = {}) {\n const html = await super.renderHTML({ canDelete, canClose, ...rest })\n this.#enrichChatCard(html)\n return html\n }\n\n #enrichChatCard(html) {\n const tokenDoc = (this.speaker.scene && this.speaker.token)\n ? game.scenes.get(this.speaker.scene)?.tokens.get(this.speaker.token)\n : null\n const actor = tokenDoc?.actor ?? game.actors.get(this.speaker.actor) ?? null\n\n const [img, nameText] = this.isContentVisible\n ? [actor?.img ?? this.author.avatar, this.alias]\n : [this.author.avatar, this.author.name]\n\n const avatarImg = Object.assign(document.createElement(\"img\"), { src: img, alt: nameText })\n const avatar = Object.assign(document.createElement(\"a\"), { className: \"avatar\" })\n if (actor) avatar.dataset.uuid = actor.uuid\n avatar.append(avatarImg)\n\n const title = Object.assign(document.createElement(\"span\"), { className: \"title\", textContent: nameText })\n const name = Object.assign(document.createElement(\"span\"), { className: \"name-stacked\" })\n name.append(title)\n\n html.querySelector(\".message-sender\")?.replaceChildren(avatar, name)\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport class CDEActor extends Actor {\n getRollData() {\n return this.toObject(false).system\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\n/** Default icons per item type. */\nconst DEFAULT_ICONS = {\n kungfu: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-kungfu.svg\",\n spell: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-spell.svg\",\n supernatural: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-supernatural.svg\",\n weapon: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-weapon.svg\",\n armor: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-armor.svg\",\n sanhei: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-sanhei.svg\",\n ingredient: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-ingredient.svg\",\n item: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-item.svg\",\n};\n\nexport class CDEItem extends Item {\n\n /** @override */\n async _preCreate(data, options, userId) {\n await super._preCreate(data, options, userId);\n const defaultIcon = DEFAULT_ICONS[this.type];\n if (defaultIcon && (!data.img || data.img === Item.DEFAULT_ICON)) {\n this.updateSource({ img: defaultIcon });\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nconst DIGIT_LABELS = [\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-1.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-2.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-3.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-4.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-5.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-6.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-7.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-8.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-9.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-10.webp\",\n]\n\nconst CLASSIC_LABELS = [\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-1.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-2.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-3.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-4.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-5.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-6.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-7.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-8.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-9.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-10.webp\",\n]\n\nexport function registerDice() {\n Hooks.once(\"diceSoNiceReady\", (dice3d) => {\n dice3d.addColorset(\n {\n name: \"cde\",\n description: \"CdE\",\n foreground: \"#000000\",\n background: \"#ffffff\",\n edge: \"#ffffff\",\n font: \"DeliusUnicase\",\n texture: \"ice\",\n material: \"plastic\",\n },\n \"preferred\",\n )\n\n dice3d.addSystem({ id: \"fvtt-chroniques-de-l-etrangedigit\", name: \"Chroniques de l'\u00E9trange digits\" }, \"preferred\")\n dice3d.addDicePreset({ type: \"d10\", labels: DIGIT_LABELS, system: \"fvtt-chroniques-de-l-etrangedigit\" })\n\n dice3d.addSystem({ id: \"fvtt-chroniques-de-l-etrange\", name: \"Chroniques de l'\u00E9trange\" }, \"preferred\")\n dice3d.addDicePreset({ type: \"d10\", labels: CLASSIC_LABELS, system: \"fvtt-chroniques-de-l-etrange\" })\n })\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { MAGICS } from \"../config/constants.js\"\n\nexport function registerHandlebarsHelpers() {\n const { Handlebars } = globalThis\n if (!Handlebars) return\n\n Handlebars.registerHelper(\"getMagicLabel\", function (magic) {\n return game.i18n.localize(MAGICS[magic]?.label ?? \"\")\n })\n\n Handlebars.registerHelper(\"getMagicAspectLabel\", function (magic) {\n return game.i18n.localize(MAGICS[magic]?.aspectlabel ?? \"\")\n })\n\n Handlebars.registerHelper(\"getMagicSpecialityLabel\", function (magic, speciality) {\n return game.i18n.localize(MAGICS[magic]?.speciality?.[speciality]?.label ?? \"\")\n })\n\n Handlebars.registerHelper(\"getMagicSpecialityClassIcon\", function (magic, speciality) {\n return MAGICS[magic]?.speciality?.[speciality]?.classicon ?? \"\"\n })\n\n Handlebars.registerHelper(\"getMagicSpecialityElementIcon\", function (magic, speciality) {\n return MAGICS[magic]?.speciality?.[speciality]?.elementicon ?? \"\"\n })\n\n Handlebars.registerHelper(\"getMagicSpecialityLabelIcon\", function (magic, speciality) {\n return MAGICS[magic]?.speciality?.[speciality]?.labelicon ?? \"\"\n })\n\n Handlebars.registerHelper(\"getMagicSpecialityLabelElement\", function (magic, speciality) {\n return game.i18n.localize(MAGICS[magic]?.speciality?.[speciality]?.labelelement ?? \"\")\n })\n\n Handlebars.registerHelper(\"getMagicAspectIcon\", function (magic) {\n const icons = {\n internalcinnabar: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\",\n alchemy: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\",\n masteryoftheway: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\",\n exorcism: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\",\n geomancy: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\",\n }\n return icons[magic] ?? \"\"\n })\n\n Handlebars.registerHelper(\"getElementIcon\", function (aspect) {\n const icons = {\n metal: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\",\n water: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\",\n earth: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\",\n fire: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\",\n wood: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\",\n // legacy French keys\n eau: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\",\n terre: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\",\n feu: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\",\n bois: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\",\n }\n return icons[aspect] ?? \"\"\n })\n\n Handlebars.registerHelper(\"getOrientationIcon\", function (orientation) {\n const icons = {\n yin: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\",\n yang: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\",\n yinyang: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp\",\n }\n return icons[orientation] ?? \"\"\n })\n\n Handlebars.registerHelper(\"getOrientationLabel\", function (orientation) {\n const keys = {\n yin: \"CDE.OrientationYin\",\n yang: \"CDE.OrientationYang\",\n yinyang: \"CDE.OrientationYinYang\",\n }\n return game.i18n.localize(keys[orientation] ?? \"CDE.Orientation\")\n })\n\n Handlebars.registerHelper(\"getActivationLabel\", function (activation) {\n const keys = {\n \"action-attack\": \"CDE.ActivationAttack\",\n \"action-defense\": \"CDE.ActivationDefense\",\n \"action-aid\": \"CDE.ActivationAid\",\n \"action-attack-defense\": \"CDE.ActivationAttackOrDefense\",\n reaction: \"CDE.ActivationReaction\",\n dice: \"CDE.ActivationDice\",\n \"damage-inflicted\": \"CDE.ActivationDamageInflicted\",\n \"damage-received\": \"CDE.ActivationDamageReceived\",\n }\n return game.i18n.localize(keys[activation] ?? \"CDE.Activation\")\n })\n\n /**\n * Compute the SVG x,y coordinates for a cran on the initiative wheel.\n * Cran 1\u201324 are arranged counter-clockwise from the bottom (reference at 6 o'clock).\n * angle = 90\u00B0 + cran * 15\u00B0 (counter-clockwise = positive in standard math, negative in SVG).\n * In SVG coords: x = cx + r*cos(a), y = cy - r*sin(a) [y-axis is flipped in SVG].\n */\n Handlebars.registerHelper(\"cranPosition\", function (cran, cx, cy, r) {\n const angleDeg = 90 + cran * 15 // counter-clockwise from bottom\n const angleRad = (angleDeg * Math.PI) / 180\n const x = Math.round(cx + r * Math.cos(angleRad))\n const y = Math.round(cy - r * Math.sin(angleRad))\n return { x, y }\n })\n\n /** X offset for overlapping fighters on the same cran. Centres a 30px image on the cran cx. */\n Handlebars.registerHelper(\"fighterX\", function (cx, index, total) {\n const offset = total > 1 ? (index - (total - 1) / 2) * 34 : 0\n return Math.round(cx - 15 + offset)\n })\n\n /** Y offset for fighters \u2014 positions image just above the cran circle. */\n Handlebars.registerHelper(\"fighterY\", function (cy, index, total) {\n return Math.round(cy - 50)\n })\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { TEMPLATE_PARTIALS } from \"../config/constants.js\"\n\nexport async function preloadPartials() {\n return foundry.applications.handlebars.loadTemplates(TEMPLATE_PARTIALS)\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\n/**\n * Initiative determination system for Chroniques de l'\u00C9trange.\n *\n * PJ formula: Initiative = Prouesse + Premi\u00E8re action (comp\u00E9tence/ressource/magie)\n * PNJ formula: Initiative = Aptitude physique + Premi\u00E8re action (aptitude)\n *\n * Range 1-24 ; anti-initiative = 25 \u2212 initiative.\n * Combat order is ascending (low initiative acts first).\n */\n\nconst PC_PROMPT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-prompt.html\"\nconst NPC_PROMPT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-prompt-npc.html\"\nconst RESULT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-result.html\"\n\n/** Skills, resources and magics available as \"premi\u00E8re action\" for a PC. */\nfunction buildPCOptions(sys) {\n const sk = sys.skills ?? {}\n const rs = sys.resources ?? {}\n const mg = sys.magics ?? {}\n return [\n { key: \"art\", label: game.i18n.localize(\"CDE.Art\"), value: sk.art?.value ?? 0 },\n { key: \"investigation\", label: game.i18n.localize(\"CDE.Investigation\"), value: sk.investigation?.value ?? 0 },\n { key: \"erudition\", label: game.i18n.localize(\"CDE.Erudition\"), value: sk.erudition?.value ?? 0 },\n { key: \"knavery\", label: game.i18n.localize(\"CDE.Knavery\"), value: sk.knavery?.value ?? 0 },\n { key: \"wordliness\", label: game.i18n.localize(\"CDE.Wordliness\"), value: sk.wordliness?.value ?? 0 },\n { key: \"prowess\", label: game.i18n.localize(\"CDE.Prowess\"), value: sk.prowess?.value ?? 0 },\n { key: \"sciences\", label: game.i18n.localize(\"CDE.Sciences\"), value: sk.sciences?.value ?? 0 },\n { key: \"technologies\", label: game.i18n.localize(\"CDE.Technologies\"), value: sk.technologies?.value ?? 0 },\n { key: \"kungfu\", label: game.i18n.localize(\"CDE.KungFu\"), value: sk.kungfu?.value ?? 0 },\n { key: \"rangedcombat\", label: game.i18n.localize(\"CDE.RangedCombat\"), value: sk.rangedcombat?.value ?? 0 },\n { key: \"supply\", label: game.i18n.localize(\"CDE.Supply\"), value: rs.supply?.value ?? 0 },\n { key: \"inquiry\", label: game.i18n.localize(\"CDE.Inquiry\"), value: rs.inquiry?.value ?? 0 },\n { key: \"influence\", label: game.i18n.localize(\"CDE.Influence\"), value: rs.influence?.value ?? 0 },\n { key: \"internalcinnabar\", label: game.i18n.localize(\"CDE.InternalCinnabar\"), value: mg.internalcinnabar?.value ?? 0 },\n { key: \"alchemy\", label: game.i18n.localize(\"CDE.Alchemy\"), value: mg.alchemy?.value ?? 0 },\n { key: \"masteryoftheway\", label: game.i18n.localize(\"CDE.MasteryOfTheWay\"), value: mg.masteryoftheway?.value ?? 0 },\n { key: \"exorcism\", label: game.i18n.localize(\"CDE.Exorcism\"), value: mg.exorcism?.value ?? 0 },\n { key: \"geomancy\", label: game.i18n.localize(\"CDE.Geomancy\"), value: mg.geomancy?.value ?? 0 },\n ]\n}\n\n/** Aptitudes available as \"premi\u00E8re action\" for an NPC. */\nfunction buildNPCOptions(sys) {\n const ap = sys.aptitudes ?? {}\n return [\n { key: \"physical\", label: game.i18n.localize(\"CDE.Physical\"), value: ap.physical?.value ?? 0 },\n { key: \"martial\", label: game.i18n.localize(\"CDE.Martial\"), value: ap.martial?.value ?? 0 },\n { key: \"mental\", label: game.i18n.localize(\"CDE.Mental\"), value: ap.mental?.value ?? 0 },\n { key: \"social\", label: game.i18n.localize(\"CDE.Social\"), value: ap.social?.value ?? 0 },\n { key: \"spiritual\", label: game.i18n.localize(\"CDE.Spiritual\"), value: ap.spiritual?.value ?? 0 },\n ]\n}\n\n/** Parse the dialog element and extract firstaction + modifier. */\nfunction readInitFields(dialog) {\n const root = dialog.element ?? dialog\n const selectedKey = root.querySelector(\"select[name='firstaction']\")?.value ?? \"\"\n const modifier = parseInt(root.querySelector(\"input[name='modifier']\")?.value ?? \"0\", 10) || 0\n return { selectedKey, modifier }\n}\n\n/** Post a styled initiative chat message. */\nasync function sendInitChatMessage({ actor, baseName, baseValue, actionName, actionValue, modifier, initiative, antiInitiative }) {\n const html = await foundry.applications.handlebars.renderTemplate(RESULT_TEMPLATE, {\n actorName: actor.name,\n actorImg: actor.img,\n baseName,\n baseValue,\n actionName,\n actionValue,\n modifier,\n hasModifier: modifier !== 0,\n initiative,\n antiInitiative,\n })\n await ChatMessage.create({\n user: game.user.id,\n speaker: ChatMessage.getSpeaker({ actor }),\n content: html,\n })\n}\n\n/**\n * Open the PC initiative dialog, compute initiative (Prouesse + Premi\u00E8re action + modificateur)\n * and update the actor, then post a chat card.\n */\nexport async function rollInitiativePC(actor) {\n const sys = actor.system\n const prowess = sys.skills?.prowess?.value ?? 0\n const options = buildPCOptions(sys)\n const baseName = game.i18n.localize(\"CDE.Prowess\")\n\n const content = await foundry.applications.handlebars.renderTemplate(PC_PROMPT_TEMPLATE, {\n prowessValue: prowess,\n options,\n modifier: 0,\n })\n\n const result = await foundry.applications.api.DialogV2.prompt({\n window: { title: game.i18n.localize(\"CDE.InitiativeRoll\") },\n content,\n rejectClose: false,\n ok: {\n label: game.i18n.localize(\"CDE.Validate\"),\n callback: (_ev, _btn, dialog) => readInitFields(dialog),\n },\n })\n if (!result) return\n\n const { selectedKey, modifier } = result\n const selected = options.find((o) => o.key === selectedKey) ?? options[0]\n const rawValue = prowess + selected.value + modifier\n const initiative = Math.max(1, Math.min(24, rawValue))\n const antiInit = 25 - initiative\n\n await actor.update({ \"system.initiative\": initiative })\n await sendInitChatMessage({\n actor,\n baseName,\n baseValue: prowess,\n actionName: selected.label,\n actionValue: selected.value,\n modifier,\n initiative,\n antiInitiative: antiInit,\n })\n}\n\n/**\n * Open the NPC initiative dialog, compute initiative (Aptitude physique + Premi\u00E8re action + modificateur)\n * and update the actor, then post a chat card.\n */\nexport async function rollInitiativeNPC(actor) {\n const sys = actor.system\n const physical = sys.aptitudes?.physical?.value ?? 0\n const options = buildNPCOptions(sys)\n const baseName = game.i18n.localize(\"CDE.Physical\")\n\n const content = await foundry.applications.handlebars.renderTemplate(NPC_PROMPT_TEMPLATE, {\n physicalValue: physical,\n options,\n modifier: 0,\n })\n\n const result = await foundry.applications.api.DialogV2.prompt({\n window: { title: game.i18n.localize(\"CDE.InitiativeRoll\") },\n content,\n rejectClose: false,\n ok: {\n label: game.i18n.localize(\"CDE.Validate\"),\n callback: (_ev, _btn, dialog) => readInitFields(dialog),\n },\n })\n if (!result) return\n\n const { selectedKey, modifier } = result\n const selected = options.find((o) => o.key === selectedKey) ?? options[0]\n const rawValue = physical + selected.value + modifier\n const initiative = Math.max(1, Math.min(24, rawValue))\n const antiInit = 25 - initiative\n\n await actor.update({ \"system.initiative\": initiative })\n await sendInitChatMessage({\n actor,\n baseName,\n baseValue: physical,\n actionName: selected.label,\n actionValue: selected.value,\n modifier,\n initiative,\n antiInitiative: antiInit,\n })\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\n/**\n * Loksyu / TinJi settings-based helpers.\n *\n * Data is stored as world settings instead of singleton Actor documents.\n */\n\nimport { SYSTEM_ID, WU_XING_CYCLE, ASPECT_FACES } from \"../../config/constants.js\"\n\n/** Read the current loksyu data object from world settings */\nexport function getLoksyuData() {\n return game.settings.get(SYSTEM_ID, \"loksyuData\") ?? {\n wood: {yin:0,yang:0}, fire: {yin:0,yang:0}, earth: {yin:0,yang:0}, metal: {yin:0,yang:0}, water: {yin:0,yang:0},\n }\n}\n\n/** Write the loksyu data object to world settings */\nexport async function setLoksyuData(data) {\n await game.settings.set(SYSTEM_ID, \"loksyuData\", data)\n Hooks.callAll(\"cde:loksyuUpdated\", data)\n}\n\n/** Read current TinJi value from world settings */\nexport function getTinjiValue() {\n return game.settings.get(SYSTEM_ID, \"tinjiData\") ?? 0\n}\n\n/** Write TinJi value to world settings */\nexport async function setTinjiValue(value) {\n await game.settings.set(SYSTEM_ID, \"tinjiData\", Math.max(0, value))\n Hooks.callAll(\"cde:tinjiUpdated\", Math.max(0, value))\n}\n\n/**\n * After a WuXing roll, add the loksyu faces (yin + yang) of the relevant\n * aspect to the loksyu settings data.\n *\n * @param {string} activeAspect - e.g. \"fire\"\n * @param {Object} faces - Die face counts { 0: n, 1: n, \u2026, 9: n }\n */\nexport async function updateLoksyuFromRoll(activeAspect, faces) {\n const cycle = WU_XING_CYCLE[activeAspect]\n if (!cycle) return\n\n const lokAspect = cycle[3]\n const [yinFace, yangFace] = ASPECT_FACES[lokAspect] ?? []\n if (yinFace === undefined) return\n\n const yinCount = faces[yinFace] ?? 0\n const yangCount = faces[yangFace] ?? 0\n if (yinCount === 0 && yangCount === 0) return\n\n const data = getLoksyuData()\n const current = data[lokAspect] ?? { yin: 0, yang: 0 }\n data[lokAspect] = {\n yin: (current.yin ?? 0) + yinCount,\n yang: (current.yang ?? 0) + yangCount,\n }\n await setLoksyuData(data)\n}\n\n/**\n * After a WuXing roll, add tinji faces to the TinJi settings.\n *\n * @param {number} count - Number of tinji faces rolled\n */\nexport async function updateTinjiFromRoll(count) {\n if (!count || count <= 0) return\n const current = getTinjiValue()\n await setTinjiValue(current + count)\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\n/**\n * Wu Xing rolling system for Chroniques de l'\u00C9trange.\n *\n * The Wu Xing cycle maps each aspect (by index 0-4) to die face groups:\n * - metal=0 : faces 3,8\n * - water=1 : faces 1,6\n * - earth=2 : faces 0/10,5\n * - fire=3 : faces 2,7\n * - wood=4 : faces 4,9\n *\n * For a given active aspect the five result categories are:\n * successes / auspicious / noxious / loksyu (yin face, yang face) / tinji\n * Each category is associated with one of the five aspects in Wu Xing cycle order.\n */\n\nimport { MAGICS, ASPECT_LABELS, ASPECT_ICONS, ASPECT_FACES, ASPECT_NAMES, WU_XING_CYCLE } from \"../config/constants.js\"\nimport { updateLoksyuFromRoll, updateTinjiFromRoll } from \"./apps/singletons.js\"\n\nconst RESULT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-dice-result.html\"\nconst SKILL_PROMPT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-skill-dice-prompt.html\"\nconst SKILL_SPECIAL_PROMPT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-skill-special-dice-prompt.html\"\nconst MAGIC_PROMPT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-magic-dice-prompt.html\"\nconst WEAPON_PROMPT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-weapon-dice-prompt.html\"\n\n/** Maps i18n element label \u2192 aspect name (for speciality default aspect lookup) */\nconst LABELELEMENT_TO_ASPECT = {\n \"CDE.Metal\": \"metal\",\n \"CDE.Water\": \"water\",\n \"CDE.Earth\": \"earth\",\n \"CDE.Fire\": \"fire\",\n \"CDE.Wood\": \"wood\",\n}\n\n/** Maps weapon range string \u2192 dice malus applied to the attack pool */\nconst RANGE_MALUS = {\n contact: 0,\n courte: 0,\n mediane: -1,\n longue: -2,\n extreme: -3,\n}\n\n/** Maps weapon type string \u2192 default skill key */\nconst WEAPON_TYPE_SKILL = {\n melee: \"kungfu\",\n thrown: \"rangedcombat\",\n ranged: \"rangedcombat\",\n firearm: \"rangedcombat\",\n}\n\n/** Maps weapon damageAspect name \u2192 ASPECT_NAMES index */\nconst WEAPON_ASPECT_INDEX = { metal: 0, eau: 1, water: 1, terre: 2, earth: 2, feu: 3, fire: 3, bois: 4, wood: 4 }\n\n/** Count how many times each die face appeared in the roll results */\nfunction countFaces(rollResults) {\n const counts = { 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 0:0 }\n for (const die of rollResults) {\n const face = die.result === 10 ? 0 : die.result\n counts[face]++\n }\n return counts\n}\n\n/**\n * Compute Wu Xing result categories from face counts and active aspect.\n * Returns { successesdice, auspiciousdice, noxiousdice, loksyudice, tinjidice, loksyurepartition }\n */\nfunction computeWuXingResults(faces, aspectName, bonusAuspicious = 0) {\n const cycle = WU_XING_CYCLE[aspectName]\n if (!cycle) return null\n\n const [succAspect, ausAspect, noxAspect, lokAspect, tinAspect] = cycle\n const [succYin, succYang] = ASPECT_FACES[succAspect]\n const [ausYin, ausYang] = ASPECT_FACES[ausAspect]\n const [noxYin, noxYang] = ASPECT_FACES[noxAspect]\n const [lokYin, lokYang] = ASPECT_FACES[lokAspect]\n const [tinYin, tinYang] = ASPECT_FACES[tinAspect]\n\n const yin = game.i18n.localize(\"CDE.Yin\")\n const yang = game.i18n.localize(\"CDE.Yang\")\n\n return {\n successesdice: faces[succYin] + faces[succYang],\n auspiciousdice: faces[ausYin] + faces[ausYang] + bonusAuspicious,\n noxiousdice: faces[noxYin] + faces[noxYang],\n loksyudice: faces[lokYin] + faces[lokYang],\n loksyurepartition: `[${yin}(${faces[lokYin]}) ${yang}(${faces[lokYang]})]`,\n tinjidice: faces[tinYin] + faces[tinYang],\n }\n}\n\n/** Read a named field from a dialog DOM element */\nfunction readField(dlg, name) {\n const el = dlg.querySelector(`[name=\"${name}\"]`)\n if (!el) return null\n return el.type === \"checkbox\" ? el.checked : el.value\n}\n\n/**\n * Open a DialogV2.prompt with the given template + data and return the resolved form values.\n * The callback receives the DialogV2 application instance; fields are read from its .element.\n * @returns {Promise|null>}\n */\nasync function showRollPrompt({ title, template, data, fields }) {\n const content = await foundry.applications.handlebars.renderTemplate(template, data)\n return foundry.applications.api.DialogV2.prompt({\n window: { title },\n content,\n rejectClose: false,\n ok: {\n label: game.i18n.localize(\"CDE.Validate\"),\n callback: (event, button, dialog) => {\n // In AppV2, dialog is the application instance; .element is the root HTMLElement\n const root = dialog.element ?? dialog\n const result = {}\n for (const field of fields) {\n result[field] = readField(root, field)\n }\n return result\n },\n },\n })\n}\n\n/**\n * Open the skill roll prompt and return the user-confirmed parameters.\n * @param {object} params - Initial values\n * @returns {Promise}\n */\nasync function showSkillPrompt(params) {\n return showRollPrompt({\n title: params.title,\n template: params.isSpecial ? SKILL_SPECIAL_PROMPT_TEMPLATE : SKILL_PROMPT_TEMPLATE,\n data: {\n numberofdice: params.numberofdice,\n aspect: Number(params.aspect ?? 0),\n bonusmalus: params.bonusmalus ?? 0,\n woundmalus: params.woundmalus ?? 0,\n bonusauspiciousdice: params.bonusauspiciousdice ?? 0,\n typeofthrow: Number(params.typeofthrow ?? 0),\n },\n fields: [\"aspect\", \"bonusmalus\", \"woundmalus\", \"bonusauspiciousdice\", \"typeofthrow\"],\n })\n}\n\n/**\n * Open the magic roll prompt and return the user-confirmed parameters.\n */\nasync function showMagicPrompt(params) {\n return showRollPrompt({\n title: params.title,\n template: MAGIC_PROMPT_TEMPLATE,\n data: {\n numberofdice: params.numberofdice ?? 0,\n aspectskill: Number(params.aspectskill ?? 0),\n bonusmalusskill: params.bonusmalusskill ?? 0,\n bonusauspiciousdice: params.bonusauspiciousdice ?? 0,\n aspectspeciality: Number(params.aspectspeciality ?? 0),\n rolldifficulty: params.rolldifficulty ?? 1,\n bonusmalusspeciality: params.bonusmalusspeciality ?? 0,\n heispend: params.heispend ?? 0,\n typeofthrow: Number(params.typeofthrow ?? 0),\n },\n fields: [\"aspectskill\", \"bonusmalusskill\", \"bonusauspiciousdice\",\n \"aspectspeciality\", \"rolldifficulty\", \"bonusmalusspeciality\",\n \"heispend\", \"typeofthrow\"],\n })\n}\n\n/**\n * Open the weapon attack roll prompt and return user-confirmed parameters.\n */\nasync function showWeaponPrompt(params) {\n return showRollPrompt({\n title: params.title,\n template: WEAPON_PROMPT_TEMPLATE,\n data: {\n numberofdice: params.numberofdice ?? 0,\n weaponName: params.weaponName ?? \"\",\n weaponTypeLabel: params.weaponTypeLabel ?? \"CDE.Weapon\",\n weaponAspectIcon: params.weaponAspectIcon ?? \"\",\n weaponAspectLabel: params.weaponAspectLabel ?? \"\",\n damageBase: params.damageBase ?? 0,\n weaponskill: params.weaponskill ?? \"kungfu\",\n aspect: Number(params.aspect ?? 0),\n effectiverange: params.effectiverange ?? \"contact\",\n bonusmalus: params.bonusmalus ?? 0,\n woundmalus: params.woundmalus ?? 0,\n bonusauspiciousdice: params.bonusauspiciousdice ?? 0,\n typeofthrow: Number(params.typeofthrow ?? 0),\n },\n fields: [\"weaponskill\", \"aspect\", \"effectiverange\", \"bonusmalus\", \"woundmalus\",\n \"bonusauspiciousdice\", \"typeofthrow\"],\n })\n}\n\n/**\n * Build and send a single enriched ChatMessage containing both the roll\n * (for Dice So Nice) and the Wu Xing result card.\n */\nasync function sendResultMessage(actor, resultData, roll, rollMode) {\n const html = await foundry.applications.handlebars.renderTemplate(RESULT_TEMPLATE, resultData)\n return ChatMessage.create({\n user: game.user.id,\n speaker: ChatMessage.getSpeaker({ actor }),\n content: html,\n rolls: [roll],\n rollMode,\n flags: {\n \"fvtt-chroniques-de-l-etrange\": { rollResult: { ...resultData } },\n },\n })\n}\n\nconst ROLL_MODES = [\"roll\", \"gmroll\", \"blindroll\", \"selfroll\"]\n\n/**\n * Main entry point: roll dice for a given actor.\n *\n * @param {Actor} actor\n * @param {string} rollKey - e.g. \"prowess-skill\", \"fire-aspect\", \"alchemy-magic-elixirs\"\n */\nexport async function rollForActor(actor, rollKey) {\n const parts = rollKey.split(\"-\")\n const skillLibel = parts[0]\n const typeLibel = parts[1]\n const specialLibel = parts[2] ?? null\n\n const sys = actor.system\n const typeOfThrow = Number(sys.prefs?.typeofthrow?.choice ?? 0)\n\n let numberofdice = 0\n let title = \"\"\n let isSpecial = false\n let isMagic = false\n let isMagicSpecial = false\n let kfDefaultAspect = -1 // set in \"itemkungfu\" case, used when computing defaultAspect\n\n // ---- Determine dice count + title ----\n const MAGIC_I18N_KEYS = {\n internalcinnabar: \"CDE.InternalCinnabar\",\n alchemy: \"CDE.Alchemy\",\n masteryoftheway: \"CDE.MasteryOfTheWay\",\n exorcism: \"CDE.Exorcism\",\n geomancy: \"CDE.Geomancy\",\n }\n\n switch (typeLibel) {\n case \"aspect\":\n numberofdice = sys.aspect[skillLibel]?.value ?? 0\n title = game.i18n.localize(sys.aspect[skillLibel]?.label ?? \"CDE.Roll\")\n break\n case \"aptitude\":\n // NPC aptitude roll \u2014 flat pool with WuXing prompt\n numberofdice = sys.aptitudes?.[skillLibel]?.value ?? 0\n title = game.i18n.localize(`CDE.${skillLibel.charAt(0).toUpperCase() + skillLibel.slice(1)}`)\n break\n case \"skill\":\n numberofdice = sys.skills?.[skillLibel]?.value ?? 0\n title = game.i18n.localize(sys.skills?.[skillLibel]?.label ?? \"CDE.Roll\")\n break\n case \"special\":\n numberofdice = sys.skills?.[skillLibel]?.value ?? 0\n title = game.i18n.localize(sys.skills?.[skillLibel]?.label ?? \"CDE.Roll\")\n title += ` [${game.i18n.localize(\"CDE.Speciality\")}]`\n isSpecial = true\n if (!sys.skills?.[skillLibel]?.specialities) {\n ui.notifications.warn(game.i18n.localize(\"CDE.Error2\"))\n return\n }\n break\n case \"resource\":\n numberofdice = sys.resources?.[skillLibel]?.value ?? 0\n title = game.i18n.localize(sys.resources?.[skillLibel]?.label ?? \"CDE.Roll\")\n break\n case \"field\":\n numberofdice = sys.resources?.[skillLibel]?.value ?? 0\n title = game.i18n.localize(sys.resources?.[skillLibel]?.label ?? \"CDE.Roll\")\n title += ` [${game.i18n.localize(\"CDE.Field\")}]`\n isSpecial = true\n if (!sys.resources?.[skillLibel]?.specialities) {\n ui.notifications.warn(game.i18n.localize(\"CDE.Error4\"))\n return\n }\n break\n case \"magic\":\n numberofdice = sys.magics?.[skillLibel]?.value ?? 0\n isMagic = true\n title = game.i18n.localize(MAGIC_I18N_KEYS[skillLibel] ?? \"CDE.Magics\")\n break\n case \"magicspecial\":\n numberofdice = sys.magics?.[skillLibel]?.value ?? 0\n isMagicSpecial = true\n isMagic = true\n if (!sys.magics?.[skillLibel]?.speciality?.[specialLibel]?.check) {\n ui.notifications.warn(game.i18n.localize(\"CDE.Error6\"))\n return\n }\n title = `${game.i18n.localize(MAGIC_I18N_KEYS[skillLibel] ?? \"CDE.Magics\")} [${game.i18n.localize(MAGICS?.[skillLibel]?.speciality?.[specialLibel]?.label ?? \"\")}]`\n break\n case \"itemkungfu\": {\n // skillLibel = item._id \u2014 look up the kungfu item to find which skill + aspect to use\n const kfItem = actor.items.get(skillLibel)\n if (!kfItem) { ui.notifications.warn(game.i18n.localize(\"CDE.Error0\")); return }\n const kfSkill = kfItem.system.skill ?? \"kungfu\"\n numberofdice = sys.skills?.[kfSkill]?.value ?? 0\n title = `${kfItem.name} [${game.i18n.localize(sys.skills?.[kfSkill]?.label ?? \"CDE.KungFu\")}]`\n kfDefaultAspect = ASPECT_NAMES.indexOf(kfItem.system.aspect ?? \"metal\")\n if (kfDefaultAspect < 0) kfDefaultAspect = 0\n break\n }\n case \"itemweapon\": {\n // skillLibel = item._id \u2014 look up the weapon item to find type + aspect + damage\n const wpItem = actor.items.get(skillLibel)\n if (!wpItem) { ui.notifications.warn(game.i18n.localize(\"CDE.Error0\")); return }\n\n const wpType = wpItem.system.weaponType ?? \"melee\"\n const wpSkill = WEAPON_TYPE_SKILL[wpType] ?? \"kungfu\"\n numberofdice = sys.skills?.[wpSkill]?.value ?? 0\n\n const wpAspectRaw = wpItem.system.damageAspect ?? \"metal\"\n const wpAspectIdx = WEAPON_ASPECT_INDEX[wpAspectRaw] ?? 0\n const wpRange = wpItem.system.range ?? \"contact\"\n\n const WEAPON_TYPE_LABELS = {\n melee: \"CDE.WeaponMelee\",\n thrown: \"CDE.WeaponThrown\",\n ranged: \"CDE.WeaponRanged\",\n firearm: \"CDE.WeaponFirearm\",\n }\n\n // Show weapon-specific prompt\n const wParams = await showWeaponPrompt({\n title: `${wpItem.name} [${game.i18n.localize(sys.skills?.[wpSkill]?.label ?? \"CDE.WeaponRoll\")}]`,\n numberofdice,\n weaponName: wpItem.name,\n weaponTypeLabel: WEAPON_TYPE_LABELS[wpType] ?? \"CDE.Weapon\",\n weaponAspectIcon: ASPECT_ICONS[ASPECT_NAMES[wpAspectIdx]] ?? \"\",\n weaponAspectLabel: game.i18n.localize(ASPECT_LABELS[ASPECT_NAMES[wpAspectIdx]] ?? \"\"),\n damageBase: wpItem.system.damageBase ?? 0,\n weaponskill: wpSkill,\n aspect: wpAspectIdx,\n effectiverange: wpRange,\n bonusmalus: 0,\n woundmalus: 0,\n bonusauspiciousdice: 0,\n typeofthrow: typeOfThrow,\n })\n\n if (!wParams) return // cancelled\n\n // Resolve final pool from weapon prompt values\n const wpChosenSkill = wParams.weaponskill ?? wpSkill\n const wpSkillDice = sys.skills?.[wpChosenSkill]?.value ?? 0\n const wpAspFinal = Number(wParams.aspect ?? wpAspectIdx)\n const wpAspectDice = sys.aspect[ASPECT_NAMES[wpAspFinal]]?.value ?? 0\n const wpRangeMalus = RANGE_MALUS[wParams.effectiverange ?? \"contact\"] ?? 0\n const wpBonusMalus = Number(wParams.bonusmalus ?? 0)\n const wpWoundMalus = Number(wParams.woundmalus ?? 0)\n const wpBonusAusp = Number(wParams.bonusauspiciousdice ?? 0)\n const wpThrowMode = Number(wParams.typeofthrow ?? 0)\n const wpDamageBase = wpItem.system.damageBase ?? 0\n\n const wpSpecialtyBonus = wpItem.system.hasSpeciality ? 1 : 0\n\n const wpTotalDice = wpSkillDice + wpAspectDice + wpRangeMalus + wpBonusMalus - wpWoundMalus + wpSpecialtyBonus\n if (wpTotalDice <= 0) {\n ui.notifications.warn(game.i18n.localize(\"CDE.Error0\"))\n return\n }\n\n const wpRoll = new Roll(`${wpTotalDice}d10`)\n await wpRoll.evaluate()\n\n const wpAspectName = ASPECT_NAMES[wpAspFinal] ?? \"metal\"\n const wpFaces = countFaces(wpRoll.dice[0]?.results ?? [])\n const wpResults = computeWuXingResults(wpFaces, wpAspectName, wpBonusAusp)\n if (!wpResults) return\n\n const wpModParts = []\n if (wpRangeMalus !== 0) wpModParts.push(`${wpRangeMalus} ${game.i18n.localize(\"CDE.RangePenalty\")}`)\n if (wpBonusMalus !== 0) wpModParts.push(`${wpBonusMalus > 0 ? \"+\" : \"\"}${wpBonusMalus} ${game.i18n.localize(\"CDE.BonusMalus\")}`)\n if (wpWoundMalus !== 0) wpModParts.push(`-${wpWoundMalus} ${game.i18n.localize(\"CDE.WoundMalus\")}`)\n if (wpBonusAusp !== 0) wpModParts.push(`+${wpBonusAusp} ${game.i18n.localize(\"CDE.BonusAuspiciousDice\")}`)\n\n // Damage = character's aspect value (from weapon's damageAspect) + weapon base damage\n const wpDamageAspectRaw = wpItem.system.damageAspect ?? \"metal\"\n const wpDamageAspectIdx = WEAPON_ASPECT_INDEX[wpDamageAspectRaw] ?? 0\n const wpDamageAspectName = ASPECT_NAMES[wpDamageAspectIdx]\n const wpDamageAspectValue = sys.aspect?.[wpDamageAspectName]?.value ?? 0\n const wpDamageAspectLabel = game.i18n.localize(ASPECT_LABELS[wpDamageAspectName] ?? \"\")\n\n const wpMsg = await sendResultMessage(actor, {\n rollLabel: `${wpItem.name}`,\n aspectName: wpAspectName,\n aspectLabel: game.i18n.localize(ASPECT_LABELS[wpAspectName] ?? \"\"),\n aspectIcon: ASPECT_ICONS[wpAspectName] ?? \"\",\n totalDice: wpTotalDice,\n modifiersText: wpModParts.length ? wpModParts.join(\" \u00B7 \") : \"\",\n spellPower: null,\n rollDifficulty: null,\n actorName: actor.name ?? \"\",\n actorImg: actor.img ?? \"\",\n // weapon-specific\n weaponName: wpItem.name,\n damageBase: wpDamageBase,\n damageAspectValue: wpDamageAspectValue,\n damageAspectLabel: wpDamageAspectLabel,\n totalDamage: wpDamageBase + wpDamageAspectValue,\n ...wpResults,\n aspect: wpAspectName,\n d1: wpFaces[1], d2: wpFaces[2], d3: wpFaces[3], d4: wpFaces[4], d5: wpFaces[5],\n d6: wpFaces[6], d7: wpFaces[7], d8: wpFaces[8], d9: wpFaces[9], d0: wpFaces[0],\n }, wpRoll, ROLL_MODES[wpThrowMode] ?? \"roll\")\n\n if (game.modules.get(\"dice-so-nice\")?.active && wpMsg?.id) {\n await game.dice3d.waitFor3DAnimationByMessageID(wpMsg.id)\n }\n // Auto-update Loksyu/TinJi singletons from weapon roll faces\n if ((wpResults.loksyudice ?? 0) > 0) await updateLoksyuFromRoll(wpAspectName, wpFaces)\n if ((wpResults.tinjidice ?? 0) > 0) await updateTinjiFromRoll(wpResults.tinjidice)\n return\n }\n default:\n ui.notifications.warn(`Unknown roll type: ${typeLibel}`)\n return\n }\n\n // For magic rolls the prompt allows adding HEI dice, so don't block early.\n // For itemkungfu, allow 0 base dice (user can add bonus dice in the prompt).\n if (numberofdice <= 0 && typeLibel !== \"aspect\" && typeLibel !== \"itemkungfu\" && !isMagic) {\n ui.notifications.warn(game.i18n.localize(\"CDE.Error0\"))\n return\n }\n\n // ---- Pre-compute default aspect for magic based on skill ----\n const MAGIC_ASPECTS = {\n internalcinnabar: 0, // metal\n alchemy: 1, // water\n masteryoftheway: 2, // earth\n exorcism: 3, // fire\n geomancy: 4, // wood\n }\n\n let defaultAspect = typeLibel === \"aspect\"\n ? [\"metal\",\"water\",\"earth\",\"fire\",\"wood\"].indexOf(skillLibel)\n : 0\n if (isMagic && MAGIC_ASPECTS[skillLibel] !== undefined) {\n defaultAspect = MAGIC_ASPECTS[skillLibel]\n }\n if (kfDefaultAspect >= 0) {\n defaultAspect = kfDefaultAspect\n }\n\n let defaultSpecialAspect = 0\n if (isMagicSpecial && specialLibel) {\n // Look up the speciality's element from the MAGICS config constant\n const specialCfg = MAGICS?.[skillLibel]?.speciality?.[specialLibel]\n const aspectName = LABELELEMENT_TO_ASPECT[specialCfg?.labelelement]\n if (aspectName) {\n defaultSpecialAspect = ASPECT_NAMES.indexOf(aspectName)\n }\n }\n\n // ---- Show roll prompt ----\n let params\n\n if (isMagic) {\n params = await showMagicPrompt({\n title,\n numberofdice,\n aspectskill: defaultAspect,\n bonusmalusskill: 0,\n bonusauspiciousdice: 0,\n aspectspeciality: defaultSpecialAspect,\n rolldifficulty: 1,\n bonusmalusspeciality: 0,\n heispend: 0,\n typeofthrow: typeOfThrow,\n })\n } else {\n params = await showSkillPrompt({\n title,\n numberofdice,\n aspect: defaultAspect,\n bonusmalus: 0,\n woundmalus: 0,\n bonusauspiciousdice: 0,\n typeofthrow: typeOfThrow,\n isSpecial,\n })\n }\n\n if (!params) return // cancelled\n\n // ---- Compute total dice and roll ----\n let aspectIndex, bonusMalus, bonusAuspicious, throwMode\n let spellAspectIndex = null // magic only: aspect of the speciality for Wu Xing\n let rollDifficulty = 1 // magic only: multiplier applied to successes\n\n if (isMagic) {\n const skillAspectIndex = Number(params.aspectskill ?? 0)\n spellAspectIndex = Number(params.aspectspeciality ?? skillAspectIndex)\n aspectIndex = skillAspectIndex // used only for skill dice pool\n bonusMalus = Number(params.bonusmalusskill ?? 0)\n bonusAuspicious = Number(params.bonusauspiciousdice ?? 0)\n rollDifficulty = Math.max(1, Number(params.rolldifficulty ?? 1))\n throwMode = Number(params.typeofthrow ?? 0)\n // magic: magic skill + aspect + bonuses + 1 (speciality base) + HEI spent\n const aspectDice = sys.aspect?.[ASPECT_NAMES[aspectIndex]]?.value ?? 0\n const bonusSpec = Number(params.bonusmalusspeciality ?? 0)\n const heiDice = Number(params.heispend ?? 0)\n numberofdice = numberofdice + aspectDice + bonusMalus + 1 + bonusSpec + heiDice\n } else {\n aspectIndex = Number(params.aspect ?? 0)\n bonusMalus = Number(params.bonusmalus ?? 0)\n const woundMalus = Number(params.woundmalus ?? 0)\n bonusAuspicious = Number(params.bonusauspiciousdice ?? 0)\n throwMode = Number(params.typeofthrow ?? 0)\n\n const aspectDice = (typeLibel !== \"aspect\")\n ? (sys.aspect?.[ASPECT_NAMES[aspectIndex]]?.value ?? 0)\n : 0\n\n numberofdice = numberofdice + aspectDice + bonusMalus - woundMalus\n if (isSpecial) numberofdice += 1 // +1d for speciality\n }\n\n if (numberofdice <= 0) {\n ui.notifications.warn(game.i18n.localize(\"CDE.Error0\"))\n return\n }\n\n // ---- Roll ----\n const roll = new Roll(`${numberofdice}d10`)\n await roll.evaluate()\n\n const rollModeKey = ROLL_MODES[throwMode] ?? \"roll\"\n\n // ---- Compute Wu Xing results ----\n // For magic rolls, the spell's aspect (aspectspeciality) governs the Wu Xing\n // cycle (which faces count as successes/auspicious/etc.), not the skill aspect.\n const wuXingAspectName = spellAspectIndex !== null\n ? ASPECT_NAMES[spellAspectIndex]\n : ASPECT_NAMES[aspectIndex]\n const allResults = roll.dice[0]?.results ?? []\n const faces = countFaces(allResults)\n const results = computeWuXingResults(faces, wuXingAspectName, bonusAuspicious)\n if (!results) return\n\n // For magic, successesdice \u00D7 rollDifficulty = spell power\n const spellPower = isMagic ? results.successesdice * rollDifficulty : null\n\n // ---- Build modifier summary text ----\n const modParts = []\n if (isMagic) {\n const bm = Number(params.bonusmalusskill ?? 0)\n const bs = Number(params.bonusmalusspeciality ?? 0)\n const hs = Number(params.heispend ?? 0)\n const ba = Number(params.bonusauspiciousdice ?? 0)\n if (bm !== 0) modParts.push(`${bm > 0 ? \"+\" : \"\"}${bm} ${game.i18n.localize(\"CDE.BonusMalus\")}`)\n if (bs !== 0) modParts.push(`${bs > 0 ? \"+\" : \"\"}${bs} ${game.i18n.localize(\"CDE.SpellBonus\")}`)\n if (ba !== 0) modParts.push(`+${ba} ${game.i18n.localize(\"CDE.BonusAuspiciousDice\")}`)\n if (hs !== 0) modParts.push(`${hs} ${game.i18n.localize(\"CDE.HeiSpend\")}`)\n if (rollDifficulty !== 1) modParts.push(`\u00D7${rollDifficulty} ${game.i18n.localize(\"CDE.RollDifficulty\")}`)\n } else {\n const bm = Number(params.bonusmalus ?? 0)\n const wm = Number(params.woundmalus ?? 0)\n const ba = Number(params.bonusauspiciousdice ?? 0)\n if (bm !== 0) modParts.push(`${bm > 0 ? \"+\" : \"\"}${bm} ${game.i18n.localize(\"CDE.BonusMalus\")}`)\n if (wm !== 0) modParts.push(`-${wm} ${game.i18n.localize(\"CDE.WoundMalus\")}`)\n if (ba !== 0) modParts.push(`+${ba} ${game.i18n.localize(\"CDE.BonusAuspiciousDice\")}`)\n }\n\n // ---- Send single enriched ChatMessage (roll + result card) ----\n const msg = await sendResultMessage(actor, {\n // Roll identity\n rollLabel: title,\n aspectName: wuXingAspectName,\n aspectLabel: game.i18n.localize(ASPECT_LABELS[wuXingAspectName] ?? \"\"),\n aspectIcon: ASPECT_ICONS[wuXingAspectName] ?? \"\",\n totalDice: numberofdice,\n modifiersText: modParts.length ? modParts.join(\" \u00B7 \") : \"\",\n // Spell power (magic only)\n spellPower,\n rollDifficulty: isMagic ? rollDifficulty : null,\n // Actor info\n actorName: actor.name ?? \"\",\n actorImg: actor.img ?? \"\",\n // Wu Xing results\n aspect: wuXingAspectName,\n ...results,\n // Die face counts\n d1: faces[1], d2: faces[2], d3: faces[3], d4: faces[4], d5: faces[5],\n d6: faces[6], d7: faces[7], d8: faces[8], d9: faces[9], d0: faces[0],\n }, roll, rollModeKey)\n\n // ---- Wait for Dice So Nice animation ----\n if (game.modules.get(\"dice-so-nice\")?.active && msg?.id) {\n await game.dice3d.waitFor3DAnimationByMessageID(msg.id)\n }\n\n // ---- Auto-update Loksyu / TinJi singletons ----\n if ((results.loksyudice ?? 0) > 0) await updateLoksyuFromRoll(wuXingAspectName, faces)\n if ((results.tinjidice ?? 0) > 0) await updateTinjiFromRoll(results.tinjidice)\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nconst { HandlebarsApplicationMixin } = foundry.applications.api\n\nexport class CDEBaseActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {\n static DEFAULT_OPTIONS = {\n classes: [\"fvtt-chroniques-de-l-etrange\", \"actor\"],\n position: { width: 920, height: 800 },\n window: { resizable: true },\n form: { submitOnChange: true },\n dragDrop: [{ dragSelector: \".item, [data-drag='true']\", dropSelector: null }],\n actions: {\n create: CDEBaseActorSheet.#onItemCreate,\n edit: CDEBaseActorSheet.#onItemEdit,\n delete: CDEBaseActorSheet.#onItemDelete,\n editImage: CDEBaseActorSheet.#onEditImage,\n },\n }\n\n tabGroups = { primary: \"description\" }\n\n get title() {\n return this.document.name\n }\n\n async _prepareContext() {\n const descriptionHTML = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description ?? \"\", { async: true })\n const cssClass = this.options.classes?.join(\" \") ?? \"\"\n return {\n actor: this.document,\n system: this.document.system,\n systemData: this.document.system,\n systemFields: this.document.system.schema.fields,\n items: this.document.items.contents,\n descriptionHTML,\n editable: this.isEditable,\n cssClass,\n }\n }\n\n // Restore the active tab after every render (including re-renders from submitOnChange).\n // AppV2 does NOT preserve tab state natively \u2014 we must re-apply it from this.tabGroups,\n // which is dynamically updated by changeTab() when the user clicks a tab.\n _onRender(context, options) {\n super._onRender?.(context, options)\n for (const [group, tab] of Object.entries(this.tabGroups)) {\n this.changeTab(tab, group, { force: true })\n }\n }\n\n static async #onItemCreate(event, target) {\n const type = target.dataset.type ?? \"item\"\n const cls = getDocumentClass(\"Item\")\n const labels = {\n item: \"CDE.ItemNew\",\n weapon: \"CDE.WeaponNew\",\n armor: \"CDE.ArmorNew\",\n sanhei: \"CDE.SanheiNew\",\n ingredient: \"CDE.IngredientNew\",\n kungfu: \"CDE.KFNew\",\n spell: \"CDE.SpellNew\",\n supernatural: \"CDE.SupernaturalNew\",\n }\n const name = game.i18n.localize(labels[type] ?? \"CDE.ItemNew\")\n const systemData = {}\n if (type === \"spell\" && target.dataset.discipline) {\n systemData.discipline = target.dataset.discipline\n }\n return cls.create({ name, type, system: systemData }, { parent: this.document })\n }\n\n static #onItemEdit(event, target) {\n const itemId = target.dataset.itemId ?? target.closest(\"[data-item-id]\")?.dataset.itemId\n const item = this.document.items.get(itemId)\n if (item) item.sheet.render(true)\n }\n\n static #onItemDelete(event, target) {\n const itemId = target.dataset.itemId ?? target.closest(\"[data-item-id]\")?.dataset.itemId\n const item = this.document.items.get(itemId)\n if (item) item.delete()\n }\n\n static async #onEditImage(event, target) {\n const attr = target.dataset.edit\n const current = foundry.utils.getProperty(this.document, attr)\n const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}\n const fp = new FilePicker({\n current,\n type: \"image\",\n redirectToRoot: img ? [img] : [],\n callback: (path) => this.document.update({ [attr]: path }),\n top: this.position.top + 40,\n left: this.position.left + 10,\n })\n return fp.browse()\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { MAGICS, SUBTYPES } from \"../../../config/constants.js\"\nimport { rollInitiativePC } from \"../../initiative.js\"\nimport { rollForActor } from \"../../rolling.js\"\nimport { CDEBaseActorSheet } from \"./base.js\"\n\nexport class CDECharacterSheet extends CDEBaseActorSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"character\"],\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/actor/cde-character-sheet.html\" },\n }\n\n tabGroups = { primary: \"description\" }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n context.equipments = context.items.filter((item) => item.type === \"item\")\n context.weapons = context.items.filter((item) => item.type === \"weapon\")\n context.armors = context.items.filter((item) => item.type === \"armor\")\n context.sanheis = context.items.filter((item) => item.type === \"sanhei\")\n context.ingredients = context.items.filter((item) => item.type === \"ingredient\")\n context.spells = context.items.filter((item) => item.type === \"spell\")\n context.kungfus = context.items.filter((item) => item.type === \"kungfu\")\n context.CDE = { MAGICS, SUBTYPES }\n\n // Group spells by discipline key (matches MAGICS keys)\n const spellsByDiscipline = {}\n for (const spell of context.spells) {\n const disc = spell.system?.discipline ?? \"internalcinnabar\"\n if (!spellsByDiscipline[disc]) spellsByDiscipline[disc] = []\n spellsByDiscipline[disc].push(spell)\n }\n\n // Build magicsDisplay: only include the 5 relevant specialities per magic type + grimoire\n const systemMagics = context.systemData.magics ?? {}\n context.magicsDisplay = Object.fromEntries(\n Object.entries(MAGICS).map(([magicKey, magicDef]) => {\n const magicData = systemMagics[magicKey] ?? {}\n return [\n magicKey,\n {\n value: magicData.value ?? 0,\n visible: magicData.visible ?? false,\n speciality: Object.fromEntries(\n Object.keys(magicDef.speciality).map((specKey) => [\n specKey,\n { check: magicData.speciality?.[specKey]?.check ?? false },\n ])\n ),\n grimoire: spellsByDiscipline[magicKey] ?? [],\n },\n ]\n })\n )\n\n return context\n }\n\n _onRender(context, options) {\n super._onRender(context, options)\n this.#bindInitiativeControls()\n this.#bindPrefs()\n this.#bindRollButtons()\n this.#bindComponentRandomize()\n this.#bindDiagramZoom()\n }\n\n #bindInitiativeControls() {\n const buttons = this.element?.querySelectorAll(\".click-initiative\")\n if (!buttons?.length) return\n buttons.forEach((button) => {\n button.addEventListener(\"click\", async () => {\n const action = button.dataset.libelId\n let initiative = this.document.system.initiative ?? 1\n if (action === \"plus\") {\n initiative = initiative >= 24 ? 1 : initiative + 1\n await this.document.update({ \"system.initiative\": initiative })\n return\n }\n if (action === \"minus\") {\n initiative = initiative <= 1 ? 24 : initiative - 1\n await this.document.update({ \"system.initiative\": initiative })\n return\n }\n if (action === \"create\") {\n await rollInitiativePC(this.document)\n }\n })\n })\n }\n\n #bindPrefs() {\n const button = this.element?.querySelector(\".click-prefs\")\n if (!button) return\n button.addEventListener(\"click\", async () => {\n const current = this.document.system.prefs?.typeofthrow ?? { choice: \"0\", check: true }\n const html = `\n
\n
\n \n \n
\n
\n \n \n
\n
`\n const prefs = await foundry.applications.api.DialogV2.prompt({\n window: { title: game.i18n.localize(\"CDE.Preferences\") },\n content: html,\n rejectClose: false,\n ok: {\n label: game.i18n.localize(\"CDE.Validate\"),\n callback: (_ev, _btn, dialog) => {\n const root = dialog.element ?? dialog\n const choice = root.querySelector(\"select[name='choice']\")?.value ?? \"0\"\n const check = root.querySelector(\"input[name='check']\")?.checked ?? false\n return { choice, check }\n },\n },\n })\n if (prefs) {\n await this.document.update({\n \"system.prefs.typeofthrow.choice\": String(prefs.choice),\n \"system.prefs.typeofthrow.check\": !!prefs.check,\n })\n }\n })\n }\n\n #bindRollButtons() {\n const cells = this.element?.querySelectorAll(\"td.click[data-libel-id], td.click2[data-libel-id], .cde-roll-trigger[data-libel-id]\")\n if (!cells?.length) return\n cells.forEach((cell) => {\n cell.addEventListener(\"click\", (event) => {\n event.preventDefault()\n const rollKey = cell.dataset.libelId\n if (rollKey) rollForActor(this.document, rollKey)\n })\n })\n }\n\n #bindDiagramZoom() {\n const img = this.element?.querySelector(\"[data-action='zoom-diagram']\")\n if (!img) return\n img.addEventListener(\"click\", () => {\n new ImagePopout(img.src, {\n title: game.i18n.localize(\"CDE.NghangDiagramTitle\"),\n shareable: false,\n }).render(true)\n })\n }\n\n #bindComponentRandomize() {\n const btn = this.element?.querySelector(\"[data-action='randomize-component']\")\n if (!btn) return\n btn.addEventListener(\"click\", async () => {\n const roll = new Roll(\"1d10\")\n await roll.evaluate()\n const face = roll.total === 10 ? 0 : roll.total\n const COMPONENT_KEYS = { 1:\"one\", 2:\"two\", 3:\"three\", 4:\"four\", 5:\"five\",\n 6:\"six\", 7:\"seven\", 8:\"eight\", 9:\"nine\", 0:\"zero\" }\n const componentKey = COMPONENT_KEYS[face]\n const componentValue = this.document.system.component?.[componentKey]?.value ?? \"\"\n const label = componentValue\n ? `${componentValue}`\n : `${game.i18n.localize(\"CDE.Component\")}${face}`\n const content = `\n
\n ${game.i18n.localize(\"CDE.ChanceThrowResult\")}\n ${label}\n
`\n await ChatMessage.create({\n user: game.user.id,\n speaker: ChatMessage.getSpeaker({ actor: this.document }),\n content,\n rolls: [roll],\n rollMode: game.settings.get(\"core\", \"rollMode\") ?? \"roll\",\n })\n })\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { rollInitiativeNPC } from \"../../initiative.js\"\nimport { rollForActor } from \"../../rolling.js\"\nimport { CDEBaseActorSheet } from \"./base.js\"\n\nexport class CDENpcSheet extends CDEBaseActorSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"npc\"],\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/actor/cde-npc-sheet.html\" },\n }\n\n tabGroups = { primary: \"description\" }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n context.supernaturals = context.items.filter((item) => item.type === \"supernatural\")\n context.spells = context.items.filter((item) => item.type === \"spell\")\n context.kungfus = context.items.filter((item) => item.type === \"kungfu\")\n context.weapons = context.items.filter((item) => item.type === \"weapon\")\n context.armors = context.items.filter((item) => item.type === \"armor\")\n context.equipments = context.items.filter((item) => item.type === \"item\")\n return context\n }\n\n _onRender(context, options) {\n super._onRender(context, options)\n this.#bindInitiativeControls()\n this.#bindRollButtons()\n }\n\n #bindRollButtons() {\n const cells = this.element?.querySelectorAll(\".cde-roll-trigger[data-libel-id]\")\n if (!cells?.length) return\n cells.forEach((cell) => {\n cell.addEventListener(\"click\", (event) => {\n event.preventDefault()\n const rollKey = cell.dataset.libelId\n if (rollKey) rollForActor(this.document, rollKey)\n })\n })\n }\n\n #bindInitiativeControls() {\n const buttons = this.element?.querySelectorAll(\".click-initiative-npc\")\n if (!buttons?.length) return\n buttons.forEach((button) => {\n button.addEventListener(\"click\", async () => {\n const action = button.dataset.libelId\n let initiative = this.document.system.initiative ?? 1\n if (action === \"plus\") {\n initiative = initiative >= 24 ? 1 : initiative + 1\n await this.document.update({ \"system.initiative\": initiative })\n return\n }\n if (action === \"minus\") {\n initiative = initiative <= 1 ? 24 : initiative - 1\n await this.document.update({ \"system.initiative\": initiative })\n return\n }\n if (action === \"create\") {\n await rollInitiativeNPC(this.document)\n }\n })\n })\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nconst { HandlebarsApplicationMixin } = foundry.applications.api\n\nexport class CDEBaseItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {\n static DEFAULT_OPTIONS = {\n classes: [\"fvtt-chroniques-de-l-etrange\", \"item\"],\n position: { width: 520, height: \"auto\" },\n window: { resizable: true },\n form: { submitOnChange: true },\n actions: {\n editImage: CDEBaseItemSheet.#onEditImage,\n },\n }\n\n tabGroups = { primary: \"details\" }\n\n get title() {\n return this.document.name\n }\n\n async _prepareContext() {\n const cssClass = this.options.classes?.join(\" \") ?? \"\"\n const enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description ?? \"\", { async: true })\n const enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.notes ?? \"\", { async: true })\n return {\n item: this.document,\n system: this.document.system,\n systemData: this.document.system,\n systemFields: this.document.system.schema.fields,\n editable: this.isEditable,\n cssClass,\n enrichedDescription,\n enrichedNotes,\n descriptionHTML: enrichedDescription,\n notesHTML: enrichedNotes,\n }\n }\n\n // Restore the active tab after every render (including re-renders from submitOnChange).\n _onRender(context, options) {\n super._onRender?.(context, options)\n for (const [group, tab] of Object.entries(this.tabGroups)) {\n this.changeTab(tab, group, { force: true })\n }\n }\n\n static async #onEditImage(event, target) {\n const attr = target.dataset.edit\n const current = foundry.utils.getProperty(this.document, attr)\n const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}\n const fp = new FilePicker({\n current,\n type: \"image\",\n redirectToRoot: img ? [img] : [],\n callback: (path) => this.document.update({ [attr]: path }),\n top: this.position.top + 40,\n left: this.position.left + 10,\n })\n return fp.browse()\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDEItemSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"equipment\"],\n position: { width: 560, height: 460 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-item-sheet.html\" },\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDEKungfuSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"kungfu\"],\n position: { width: 720, height: 680 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-kungfu-sheet.html\" },\n }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n const techniques = this.document.system.techniques ?? {}\n const enrich = (value) => foundry.applications.ux.TextEditor.implementation.enrichHTML(value ?? \"\", { async: true })\n context.descriptionTechnique1HTML = await enrich(techniques.technique1?.technique)\n context.descriptionTechnique2HTML = await enrich(techniques.technique2?.technique)\n context.descriptionTechnique3HTML = await enrich(techniques.technique3?.technique)\n return context\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDESpellSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"spell\"],\n position: { width: 660, height: 680 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-spell-sheet.html\" },\n }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n const enrich = (content) => foundry.applications.ux.TextEditor.implementation.enrichHTML(content ?? \"\", { async: true })\n context.spellDescriptionHTML = await enrich(this.document.system.description)\n context.componentsDescriptionHTML = await enrich(this.document.system.components)\n context.effectsDescriptionHTML = await enrich(this.document.system.effects)\n context.examplesDescriptionHTML = await enrich(this.document.system.examples)\n return context\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDESupernaturalSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"supernatural\"],\n position: { width: 560, height: 520 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-supernatural-sheet.html\" },\n }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n const enrich = (content) => foundry.applications.ux.TextEditor.implementation.enrichHTML(content ?? \"\", { async: true })\n context.effectsHTML = await enrich(this.document.system.effects)\n return context\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDEWeaponSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"weapon\"],\n position: { width: 580, height: 520 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-weapon-sheet.html\" },\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDEArmorSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"armor\"],\n position: { width: 520, height: 460 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-armor-sheet.html\" },\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDESanheiSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"sanhei\"],\n position: { width: 580, height: 620 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-sanhei-sheet.html\" },\n }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n const enrich = (content) => foundry.applications.ux.TextEditor.implementation.enrichHTML(content ?? \"\", { async: true })\n const props = this.document.system.properties\n context.prop1DescriptionHTML = await enrich(props.prop1.description)\n context.prop2DescriptionHTML = await enrich(props.prop2.description)\n context.prop3DescriptionHTML = await enrich(props.prop3.description)\n context.propFields = this.document.system.schema.fields.properties.fields\n return context\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDEIngredientSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"ingredient\"],\n position: { width: 520, height: 460 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-ingredient-sheet.html\" },\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { getLoksyuData, setLoksyuData } from \"./singletons.js\"\nimport { SYSTEM_ID } from \"../../config/constants.js\"\n\nexport class CDELoksyuApp extends foundry.applications.api.HandlebarsApplicationMixin(\n foundry.applications.api.ApplicationV2\n) {\n static DEFAULT_OPTIONS = {\n id: \"cde-loksyu-app\",\n tag: \"div\",\n window: {\n title: \"CDE.Loksyu\",\n icon: \"fas fa-yin-yang\",\n resizable: false,\n },\n classes: [\"cde-app\", \"cde-loksyu-standalone\"],\n position: { width: 520, height: \"auto\" },\n actions: {\n resetElement: CDELoksyuApp.#onResetElement,\n resetAll: CDELoksyuApp.#onResetAll,\n zoomVisual: CDELoksyuApp.#onZoomVisual,\n },\n }\n\n static PARTS = {\n main: {\n template: `systems/${SYSTEM_ID}/templates/apps/cde-loksyu-app.html`,\n },\n }\n\n /** @type {Function|null} bound hook handler */\n _updateHook = null\n\n /** Singleton accessor \u2014 open or bring to front */\n static open() {\n const existing = Array.from(foundry.applications.instances.values()).find(\n (app) => app instanceof CDELoksyuApp\n )\n if (existing) { existing.bringToFront(); return existing }\n const app = new CDELoksyuApp()\n app.render(true)\n return app\n }\n\n async _prepareContext() {\n const sys = getLoksyuData()\n const ELEMENTS = [\n { key: \"wood\", nameKey: \"CDE.Wood\", qualKey: \"CDE.WoodQualities\", img: `systems/${SYSTEM_ID}/images/cde_bois.webp` },\n { key: \"fire\", nameKey: \"CDE.Fire\", qualKey: \"CDE.FireQualities\", img: `systems/${SYSTEM_ID}/images/cde_feu.webp` },\n { key: \"earth\", nameKey: \"CDE.Earth\", qualKey: \"CDE.EarthQualities\", img: `systems/${SYSTEM_ID}/images/cde_terre.webp` },\n { key: \"metal\", nameKey: \"CDE.Metal\", qualKey: \"CDE.MetalQualities\", img: `systems/${SYSTEM_ID}/images/cde_metal.webp` },\n { key: \"water\", nameKey: \"CDE.Water\", qualKey: \"CDE.WaterQualities\", img: `systems/${SYSTEM_ID}/images/cde_eau.webp` },\n ]\n\n return {\n canEdit: game.user.isGM,\n elements: ELEMENTS.map((el) => ({\n ...el,\n yang: sys[el.key]?.yang ?? 0,\n yin: sys[el.key]?.yin ?? 0,\n })),\n }\n }\n\n _onRender(context, options) {\n super._onRender(context, options)\n this.#bindInputs()\n\n this._updateHook = Hooks.on(\"cde:loksyuUpdated\", () => this.render())\n }\n\n _onClose(options) {\n if (this._updateHook !== null) {\n Hooks.off(\"cde:loksyuUpdated\", this._updateHook)\n this._updateHook = null\n }\n super._onClose(options)\n }\n\n #bindInputs() {\n const inputs = this.element?.querySelectorAll(\"input[data-field]\")\n if (!inputs?.length) return\n inputs.forEach((input) => {\n input.addEventListener(\"change\", async (ev) => {\n const field = ev.currentTarget.dataset.field\n const val = parseInt(ev.currentTarget.value, 10)\n if (!field || isNaN(val)) return\n // field is like \"wood.yin\" or \"fire.yang\"\n const [aspect, dim] = field.split(\".\")\n if (!aspect || !dim) return\n const data = getLoksyuData()\n if (!data[aspect]) data[aspect] = { yin: 0, yang: 0 }\n data[aspect][dim] = Math.max(0, val)\n await setLoksyuData(data)\n })\n })\n }\n\n static async #onResetElement(event, target) {\n const key = target.dataset.element\n if (!key) return\n const data = getLoksyuData()\n data[key] = { yin: 0, yang: 0 }\n await setLoksyuData(data)\n }\n\n static async #onResetAll(_event, _target) {\n const KEYS = [\"wood\", \"fire\", \"earth\", \"metal\", \"water\"]\n const data = getLoksyuData()\n for (const k of KEYS) data[k] = { yin: 0, yang: 0 }\n await setLoksyuData(data)\n }\n\n static #onZoomVisual(_event, target) {\n new ImagePopout(target.src, {\n title: game.i18n.localize(\"CDE.LoksyuDiagramTitle\"),\n shareable: false,\n }).render(true)\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { getTinjiValue, setTinjiValue } from \"./singletons.js\"\nimport { SYSTEM_ID } from \"../../config/constants.js\"\n\nexport class CDETinjiApp extends foundry.applications.api.HandlebarsApplicationMixin(\n foundry.applications.api.ApplicationV2\n) {\n static DEFAULT_OPTIONS = {\n id: \"cde-tinji-app\",\n tag: \"div\",\n window: {\n title: \"CDE.TinJi2\",\n icon: \"fas fa-star\",\n resizable: false,\n },\n classes: [\"cde-app\", \"cde-tinji-standalone\"],\n position: { width: 380, height: \"auto\" },\n actions: {\n increment: CDETinjiApp.#onIncrement,\n decrement: CDETinjiApp.#onDecrement,\n reset: CDETinjiApp.#onReset,\n spend: CDETinjiApp.#onSpend,\n },\n }\n\n static PARTS = {\n main: {\n template: `systems/${SYSTEM_ID}/templates/apps/cde-tinji-app.html`,\n },\n }\n\n /** @type {Function|null} */\n _updateHook = null\n\n static open() {\n const existing = Array.from(foundry.applications.instances.values()).find(\n (app) => app instanceof CDETinjiApp\n )\n if (existing) { existing.bringToFront(); return existing }\n const app = new CDETinjiApp()\n app.render(true)\n return app\n }\n\n async _prepareContext() {\n return {\n canEdit: game.user.isGM,\n value: getTinjiValue(),\n }\n }\n\n _onRender(context, options) {\n super._onRender(context, options)\n this.#bindDirectInput()\n this._updateHook = Hooks.on(\"cde:tinjiUpdated\", () => this.render())\n }\n\n _onClose(options) {\n if (this._updateHook !== null) {\n Hooks.off(\"cde:tinjiUpdated\", this._updateHook)\n this._updateHook = null\n }\n super._onClose(options)\n }\n\n #bindDirectInput() {\n const input = this.element?.querySelector(\"input.cde-tinji-direct\")\n if (!input) return\n input.addEventListener(\"change\", async (ev) => {\n const val = parseInt(ev.currentTarget.value, 10)\n if (!isNaN(val)) await setTinjiValue(val)\n })\n }\n\n static async #onIncrement() {\n await setTinjiValue(getTinjiValue() + 1)\n }\n\n static async #onDecrement() {\n const current = getTinjiValue()\n if (current <= 0) return\n await setTinjiValue(current - 1)\n }\n\n static async #onReset() {\n await setTinjiValue(0)\n }\n\n static async #onSpend() {\n const current = getTinjiValue()\n if (current <= 0) {\n ui.notifications.warn(game.i18n.localize(\"CDE.TinjiEmpty\"))\n return\n }\n await setTinjiValue(current - 1)\n ChatMessage.create({\n user: game.user.id,\n content: `
\n \n ${game.i18n.localize(\"CDE.TinJi2\")}\n ${game.i18n.format(\"CDE.TinjiSpent\", { name: game.user.name })}\n (${current - 1} ${game.i18n.localize(\"CDE.TinjiRemaining\")})\n
`,\n })\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { rollInitiativePC, rollInitiativeNPC } from \"../ui/initiative.js\"\nimport { ACTOR_TYPES } from \"../config/constants.js\"\n\n/**\n * Custom Combat document for Chroniques de l'\u00C9trange.\n *\n * The initiative wheel has 24 crans (positions). The character with the\n * highest initiative acts first (furthest counter-clockwise from reference).\n * After each action, their position advances clockwise by the action's cran cost\n * (initiative decreases, wrapping from 1 \u2192 24).\n *\n * Sort order: descending by initiative (highest acts first).\n */\nexport class CDECombat extends Combat {\n\n /**\n * Override rollInitiative to open the PC or NPC initiative dialog\n * for each selected combatant, then sync the result to the Combatant document.\n */\n async rollInitiative(ids, options = {}) {\n const combatantIds = typeof ids === \"string\" ? [ids] : ids\n for (const id of combatantIds) {\n const combatant = this.combatants.get(id)\n if (!combatant) continue\n const actor = combatant.actor\n if (!actor) continue\n\n if (actor.type === ACTOR_TYPES.character) {\n await rollInitiativePC(actor)\n } else {\n await rollInitiativeNPC(actor)\n }\n // combatant.initiative is synced by the updateActor hook in system.js\n // (triggered by actor.update inside rollInitiativePC/NPC)\n }\n return this\n }\n\n /**\n * Sort combatants: highest initiative first (furthest counter-clockwise = acts first).\n * Ties: PCs before NPCs; among PCs, by name; among NPCs, by name.\n * Calls super.setupTurns() first to ensure this.current is properly initialized.\n */\n setupTurns() {\n super.setupTurns()\n this.turns = this.turns.slice().sort((a, b) => {\n const ia = a.initiative ?? 0\n const ib = b.initiative ?? 0\n if (ia !== ib) return ib - ia // descending \u2014 highest acts first\n\n // Tie-break: PCs before NPCs\n const aIsPC = a.actor?.type === ACTOR_TYPES.character ? 1 : 0\n const bIsPC = b.actor?.type === ACTOR_TYPES.character ? 1 : 0\n if (aIsPC !== bIsPC) return bIsPC - aIsPC\n\n return (a.name ?? \"\").localeCompare(b.name ?? \"\")\n })\n return this.turns\n }\n}\n\n/**\n * Advance a combatant's wheel position by the given action cran cost.\n * Position wraps: after reaching 1, it continues from 24.\n *\n * @param {Combatant} combatant\n * @param {number} cranCost\n */\nexport async function advanceCombatantPosition(combatant, cranCost) {\n const current = combatant.initiative ?? combatant.actor?.system?.initiative ?? 1\n const newValue = ((current - cranCost - 1 + 48) % 24) + 1\n // Update combatant only; the updateCombatant hook in system.js syncs actor.initiative.\n await combatant.update({ initiative: newValue })\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { advanceCombatantPosition } from \"../../documents/combat.js\"\n\nconst WHEEL_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-wheel-app.html\"\n\n/**\n * Action costs for common combat actions (in crans).\n * Listed in order from cheapest to most expensive.\n */\nexport const ACTION_COSTS = [\n { key: \"draw\", label: \"CDE.ActionCostDraw\", cost: 1 },\n { key: \"changestyle\", label: \"CDE.ActionCostChangeStyle\", cost: 1 },\n { key: \"defense\", label: \"CDE.ActionCostDefense\", cost: 1 },\n { key: \"aim\", label: \"CDE.ActionCostAim\", cost: 2 },\n { key: \"help\", label: \"CDE.ActionCostHelp\", cost: 2 },\n { key: \"defally\", label: \"CDE.ActionCostDefendAlly\", cost: 2 },\n { key: \"move\", label: \"CDE.ActionCostMove\", cost: 2 },\n { key: \"attack\", label: \"CDE.ActionCostAttack\", cost: 3 },\n { key: \"delay\", label: \"CDE.ActionCostDelay\", cost: 6 },\n]\n\n/**\n * Wu Xing color segments for the 24-cran wheel.\n * 6 colors \u00D7 4 crans = 24. Each colour covers crans [start..start+3].\n * An effect lasting 6 crans returns to the same colour.\n */\nconst WHEEL_SEGMENTS = [\n { label: \"M\u00E9tal\", color: \"#b8c4cc\", textColor: \"#1a1a1a\", crans: [1, 2, 3, 4] },\n { label: \"Eau\", color: \"#3a7bd5\", textColor: \"#ffffff\", crans: [5, 6, 7, 8] },\n { label: \"Terre\", color: \"#c8a84b\", textColor: \"#1a1a1a\", crans: [9, 10, 11, 12] },\n { label: \"Feu\", color: \"#d94f3d\", textColor: \"#ffffff\", crans: [13, 14, 15, 16] },\n { label: \"Bois\", color: \"#4a9b5a\", textColor: \"#ffffff\", crans: [17, 18, 19, 20] },\n { label: \"Rep\u00E8re\", color: \"#1a1a2e\", textColor: \"#aaaaaa\", crans: [21, 22, 23, 24] },\n]\n\n/** Return the segment data for a given cran (1\u201324). */\nfunction segmentForCran(cran) {\n return WHEEL_SEGMENTS.find(s => s.crans.includes(cran)) ?? WHEEL_SEGMENTS[0]\n}\n\n/**\n * Roue d'Initiative \u2014 visual initiative wheel for CDE combat.\n *\n * Shows all combatants in the current combat scene on a 24-cran wheel.\n * Provides action-cost buttons to advance a combatant's position.\n *\n * Singleton: open via CDEWheelApp.open().\n */\nexport class CDEWheelApp extends foundry.applications.api.ApplicationV2 {\n static DEFAULT_OPTIONS = {\n id: \"cde-wheel-app\",\n classes: [\"cde-wheel-app\"],\n tag: \"div\",\n window: {\n title: \"CDE.InitiativeWheel\",\n icon: \"fas fa-circle-notch\",\n resizable: true,\n },\n position: { width: 820, height: 620 },\n actions: {\n advanceCran: CDEWheelApp.#advanceCran,\n setSurprised: CDEWheelApp.#setSurprised,\n rollInitiative: CDEWheelApp.#rollInitiative,\n },\n }\n\n /** @type {CDEWheelApp|null} */\n static #instance = null\n\n /** Open (or bring to front) the singleton instance. */\n static open() {\n if (!CDEWheelApp.#instance || CDEWheelApp.#instance.rendered === false) {\n CDEWheelApp.#instance = new CDEWheelApp()\n CDEWheelApp.#instance.render(true)\n } else {\n CDEWheelApp.#instance.bringToFront()\n }\n return CDEWheelApp.#instance\n }\n\n /** Currently selected combatant id (for action panel). */\n #selectedId = null\n\n async _prepareContext(options) {\n const combat = game.combat\n const combatants = combat ? [...combat.combatants.values()] : []\n const sorted = [...combatants].sort((a, b) => (b.initiative ?? 0) - (a.initiative ?? 0))\n const cranData = this.#buildCranData(combatants)\n const selected = this.#selectedId\n ? combatants.find(c => c.id === this.#selectedId)\n : null\n const actionCosts = ACTION_COSTS.map(a => ({\n ...a,\n label: game.i18n.localize(a.label),\n }))\n\n return {\n hasCombat: !!combat,\n combatants: sorted.map(c => ({\n id: c.id,\n name: c.name,\n img: c.token?.texture?.src ?? c.actor?.img ?? \"icons/svg/mystery-man.svg\",\n initiative: c.initiative ?? \"\u2014\",\n segment: segmentForCran(c.initiative ?? 1),\n isActive: combat?.current?.combatantId === c.id,\n isSelected: c.id === this.#selectedId,\n hasInitiative: c.initiative != null,\n })),\n cranData,\n selected,\n selectedName: selected?.name ?? null,\n actionCosts,\n }\n }\n\n async _renderHTML(context, options) {\n return foundry.applications.handlebars.renderTemplate(WHEEL_TEMPLATE, context)\n }\n\n _replaceHTML(result, content, options) {\n content.innerHTML = result\n this.#bindEvents(content)\n }\n\n /** Build per-cran data for the SVG wheel. */\n #buildCranData(combatants) {\n const data = []\n for (let cran = 1; cran <= 24; cran++) {\n const segment = segmentForCran(cran)\n const fighters = combatants.filter(c => Math.round(c.initiative) === cran)\n data.push({ cran, segment, fighters })\n }\n return data\n }\n\n /** Bind click events for combatant selection. */\n #bindEvents(content) {\n content.querySelectorAll(\"[data-select-combatant]\").forEach(el => {\n el.addEventListener(\"click\", () => {\n this.#selectedId = el.dataset.selectCombatant\n this.render()\n })\n })\n }\n\n /** Action: advance selected combatant by given cran cost. */\n static async #advanceCran(event, element) {\n const app = CDEWheelApp.#instance\n if (!app?.#selectedId) return\n const cost = parseInt(element.dataset.cost, 10)\n if (!cost || isNaN(cost)) return\n const combatant = game.combat?.combatants.get(app.#selectedId)\n if (!combatant) return\n await advanceCombatantPosition(combatant, cost)\n }\n\n /** Action: set selected combatant to surprised (position 1 = reference). */\n static async #setSurprised(event, element) {\n const app = CDEWheelApp.#instance\n if (!app?.#selectedId) return\n const combatant = game.combat?.combatants.get(app.#selectedId)\n if (!combatant) return\n // Update combatant only \u2014 updateCombatant hook in system.js syncs actor\n await combatant.update({ initiative: 1 })\n }\n\n /** Action: open the initiative dialog for the selected combatant. */\n static async #rollInitiative(event, element) {\n const app = CDEWheelApp.#instance\n if (!app?.#selectedId) return\n const combatant = game.combat?.combatants.get(app.#selectedId)\n if (!combatant) return\n await game.combat.rollInitiative([app.#selectedId])\n }\n\n /** Re-render when combat state changes. */\n static registerHooks() {\n const refresh = () => {\n if (CDEWheelApp.#instance?.rendered) CDEWheelApp.#instance.render()\n }\n Hooks.on(\"updateCombat\", refresh)\n Hooks.on(\"updateCombatant\", refresh)\n Hooks.on(\"createCombatant\", refresh)\n Hooks.on(\"deleteCombatant\", refresh)\n Hooks.on(\"updateActor\", (_actor, diff) => {\n if (foundry.utils.hasProperty(diff, \"system.initiative\")) refresh()\n })\n Hooks.on(\"deleteCombat\", () => {\n if (CDEWheelApp.#instance?.rendered) CDEWheelApp.#instance.render()\n })\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\n/**\n * Post-roll interactive action buttons injected into dice result chat messages.\n * Allows players to pull dice from the Loksyu (as Successes or d\u00E9s-fastes)\n * and allows the GM to spend Tin Ji to intervene.\n *\n * After a draw, the originating roll result message is updated in-place\n * with the new counts, without creating noise.\n */\n\nimport { getLoksyuData, setLoksyuData, getTinjiValue, setTinjiValue } from \"./apps/singletons.js\"\nimport { SYSTEM_ID, WU_XING_CYCLE, ASPECT_LABELS, ASPECT_ICONS } from \"../config/constants.js\"\n\nconst RESULT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-dice-result.html\"\n\n/**\n * Inject or refresh post-roll action buttons in the given chat message HTML element.\n * Called from renderChatMessageHTML hook.\n * @param {ChatMessage} message\n * @param {HTMLElement} html - the chat message HTML element (li.chat-message)\n */\nexport function injectRollActions(message, html) {\n const rollCard = html.querySelector(\".cde-roll-result\")\n if (!rollCard) return\n const aspect = rollCard.dataset.aspect\n if (!aspect || !WU_XING_CYCLE[aspect]) return\n refreshRollActions(rollCard, aspect, message)\n}\n\n/**\n * Re-render the action buttons section based on current Loksyu / TinJi state.\n */\nfunction refreshRollActions(rollCard, aspect, message) {\n rollCard.querySelector(\".cde-roll-actions\")?.remove()\n\n const cycle = WU_XING_CYCLE[aspect]\n const fasteAspect = cycle[1]\n\n const loksyu = getLoksyuData()\n const tinji = getTinjiValue()\n\n const successAvail = (loksyu[aspect]?.yin ?? 0) + (loksyu[aspect]?.yang ?? 0)\n const fasteAvail = (loksyu[fasteAspect]?.yin ?? 0) + (loksyu[fasteAspect]?.yang ?? 0)\n const isGM = game.user.isGM\n\n const hasSomething = successAvail > 0 || fasteAvail > 0 || (isGM && tinji > 0)\n if (!hasSomething) return\n\n const aspLabel = game.i18n.localize(ASPECT_LABELS[aspect])\n const fasteLabel = game.i18n.localize(ASPECT_LABELS[fasteAspect])\n\n let btns = \"\"\n\n if (successAvail > 0) {\n btns += ``\n }\n\n if (fasteAvail > 0) {\n btns += ``\n }\n\n if (isGM && tinji > 0) {\n btns += ``\n }\n\n const wrapper = document.createElement(\"div\")\n wrapper.className = \"cde-roll-actions\"\n wrapper.innerHTML = `\n
\n \n ${game.i18n.localize(\"CDE.PostRollActions\")}\n
\n
${btns}
\n `\n rollCard.appendChild(wrapper)\n\n wrapper.addEventListener(\"click\", async ev => {\n const btn = ev.target.closest(\"[data-action]\")\n if (!btn || btn.disabled) return\n const action = btn.dataset.action\n if (action === \"loksyu-success\") {\n await _drawFromLoksyu(message, aspect, \"success\", aspLabel)\n } else if (action === \"loksyu-faste\") {\n await _drawFromLoksyu(message, fasteAspect, \"faste\", fasteLabel)\n } else if (action === \"tinji\") {\n await _spendTinjiPostRoll()\n }\n // Buttons will be re-injected automatically via renderChatMessageHTML\n // after message.update(). For tinji (no message update), refresh manually.\n if (action === \"tinji\") refreshRollActions(rollCard, aspect, message)\n })\n}\n\n/**\n * Pull one die from a given Loksyu aspect slot, update Loksyu settings,\n * and update the originating roll-result message in-place.\n *\n * @param {ChatMessage} message - the roll result chat message to update\n * @param {string} aspect - which Loksyu aspect slot to draw from\n * @param {\"success\"|\"faste\"} type\n * @param {string} aspectLabel - localised aspect name for the notification\n */\nasync function _drawFromLoksyu(message, aspect, type, aspectLabel) {\n const data = getLoksyuData()\n const entry = data[aspect] ?? { yin: 0, yang: 0 }\n const total = entry.yin + entry.yang\n if (total <= 0) {\n ui.notifications.warn(game.i18n.localize(\"CDE.LoksyuEmpty\"))\n return\n }\n\n // Remove 1 die according to the consumption order setting\n const order = game.settings.get(SYSTEM_ID, \"loksyuConsumptionOrder\")\n if (order === \"yin-first\") {\n if (entry.yin > 0) entry.yin--\n else entry.yang--\n } else if (order === \"balanced\") {\n if (entry.yin > entry.yang) entry.yin--\n else if (entry.yang > entry.yin) entry.yang--\n else if (entry.yang > 0) entry.yang--\n else entry.yin--\n } else {\n // yang-first (default)\n if (entry.yang > 0) entry.yang--\n else entry.yin--\n }\n data[aspect] = entry\n await setLoksyuData(data)\n\n // Update the roll-result message in-place if it has stored flags\n const flags = message?.flags?.[SYSTEM_ID]\n if (flags?.rollResult && message.isOwner) {\n const updated = foundry.utils.deepClone(flags.rollResult)\n if (type === \"success\") {\n updated.successesdice = (updated.successesdice ?? 0) + 1\n updated.loksyuBonusSuc = (updated.loksyuBonusSuc ?? 0) + 1\n // Recalculate weapon damage if applicable\n if (updated.damageBase != null) updated.totalDamage = updated.damageBase + (updated.damageAspectValue ?? 0)\n } else {\n updated.auspiciousdice = (updated.auspiciousdice ?? 0) + 1\n updated.loksyuBonusFaste = (updated.loksyuBonusFaste ?? 0) + 1\n }\n const newHtml = await foundry.applications.handlebars.renderTemplate(RESULT_TEMPLATE, updated)\n await message.update({\n content: newHtml,\n [`flags.${SYSTEM_ID}.rollResult`]: updated,\n })\n // renderChatMessageHTML hook fires automatically \u2192 buttons re-injected\n }\n\n const remain = entry.yin + entry.yang\n const typeLabel = type === \"success\"\n ? game.i18n.localize(\"CDE.Successes\")\n : game.i18n.localize(\"CDE.AuspiciousDie\")\n\n ChatMessage.create({\n user: game.user.id,\n content: `
\n
\n \"${aspectLabel}\"/\n ${game.user.name}\n ${game.i18n.localize(\"CDE.LoksyuDrawsA\")}\n ${typeLabel}\n ${game.i18n.localize(\"CDE.LoksyuFromAspect\")} ${aspectLabel}\n
\n
\n \n ${game.i18n.localize(\"CDE.Loksyu\")} ${aspectLabel} : \n ${remain} ${game.i18n.localize(\"CDE.LoksyuRemaining\")}\n
\n
`,\n })\n}\n\n/**\n * Spend 1 Tin Ji point (GM only) and post a notification.\n */\nasync function _spendTinjiPostRoll() {\n if (!game.user.isGM) return\n const current = getTinjiValue()\n if (current <= 0) {\n ui.notifications.warn(game.i18n.localize(\"CDE.TinjiEmpty\"))\n return\n }\n await setTinjiValue(current - 1)\n ChatMessage.create({\n user: game.user.id,\n content: `
\n \u5929\n \n ${game.user.name} ${game.i18n.localize(\"CDE.TinjiSpent\").replace(\"{name}\", game.user.name)}\n \n (${current - 1} ${game.i18n.localize(\"CDE.TinjiRemaining\")})\n
`,\n })\n}\n\n/**\n * Refresh all visible roll-result buttons when Loksyu or TinJi settings change.\n * Wired up via Hooks.on(\"updateSetting\", ...) in system.js.\n */\nexport function refreshAllRollActions() {\n document.querySelectorAll(\".chat-message .cde-roll-result[data-aspect]\").forEach(card => {\n const aspect = card.dataset.aspect\n if (!aspect || !WU_XING_CYCLE[aspect]) return\n // Find the ChatMessage document from the ancestor element's data-message-id\n const msgEl = card.closest(\"[data-message-id]\")\n const msgId = msgEl?.dataset?.messageId\n const message = msgId ? game.messages.get(msgId) : null\n refreshRollActions(card, aspect, message)\n })\n}\n\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { SYSTEM_ID } from \"../../config/constants.js\"\n\nconst HELP_JOURNAL_UUID = `Compendium.${SYSTEM_ID}.cde-help.JournalEntry.CDEGuideMain0001`\n\n/** Post a styled welcome chat message. Called once per session by the GM. */\nexport async function showWelcomeMessage() {\n const logo = `systems/${SYSTEM_ID}/images/logo_jeu.webp`\n const content = `\n
\n \"Les\n

Les Chroniques de l'\u00C9trange

\n

\n Un jeu de r\u00F4le \u00E9dit\u00E9 par\n Antre-Monde \u00C9ditions\n

\n

\n Syst\u00E8me FoundryVTT r\u00E9alis\u00E9 par\n LeRatierBretonnien\n

\n \n
`\n\n await ChatMessage.create({\n content,\n speaker: { alias: \"Les Chroniques de l'\u00C9trange\" },\n flags: { [SYSTEM_ID]: { welcome: true } },\n })\n}\n\n/** Attach the help-open click handler to a welcome chat message HTML node. */\nexport function injectWelcomeActions(_message, html) {\n const el = html instanceof HTMLElement ? html : (html[0] ?? html)\n const btn = el?.querySelector?.(\"[data-action='open-cde-help']\")\n if (!btn) return\n\n btn.addEventListener(\"click\", async () => {\n try {\n const doc = await fromUuid(HELP_JOURNAL_UUID)\n doc?.sheet?.render(true)\n } catch {\n // Pack not yet loaded \u2014 open the compendium browser as fallback\n game.packs.get(`${SYSTEM_ID}.cde-help`)?.render(true)\n }\n })\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { ACTOR_TYPES, ITEM_TYPES, MAGICS, SUBTYPES, SYSTEM_ID } from \"./config/constants.js\"\nimport { registerSettings, migrateIfNeeded, loadWelcomeSceneIfNeeded } from \"./config/settings.js\"\nimport { preLocalizeConfig } from \"./config/localize.js\"\nimport { configureRuntime } from \"./config/runtime.js\"\nimport { CharacterDataModel, NpcDataModel } from \"./data/actors/index.js\"\nimport { EquipmentDataModel, KungfuDataModel, SpellDataModel, SupernaturalDataModel, WeaponDataModel, ArmorDataModel, SanheiDataModel, IngredientDataModel } from \"./data/items/index.js\"\nimport { CDEMessage } from \"./documents/chat-message.js\"\nimport { CDEActor } from \"./documents/actor.js\"\nimport { CDEItem } from \"./documents/item.js\"\nimport { registerDice } from \"./ui/dice.js\"\nimport { registerHandlebarsHelpers } from \"./ui/helpers.js\"\nimport { preloadPartials } from \"./ui/templates.js\"\nimport { CDECharacterSheet, CDENpcSheet } from \"./ui/sheets/actors/index.js\"\nimport { CDEItemSheet, CDEKungfuSheet, CDESpellSheet, CDESupernaturalSheet, CDEWeaponSheet, CDEArmorSheet, CDESanheiSheet, CDEIngredientSheet } from \"./ui/sheets/items/index.js\"\nimport { CDELoksyuApp } from \"./ui/apps/loksyu-app.js\"\nimport { CDETinjiApp } from \"./ui/apps/tinji-app.js\"\nimport { CDEWheelApp } from \"./ui/apps/wheel-app.js\"\nimport { injectRollActions, refreshAllRollActions } from \"./ui/roll-actions.js\"\nimport { CDECombat } from \"./documents/combat.js\"\nimport { showWelcomeMessage, injectWelcomeActions } from \"./ui/apps/welcome.js\"\n\nHooks.once(\"i18nInit\", preLocalizeConfig)\n\nHooks.once(\"init\", async () => {\n console.info(`CHRONIQUESDELETRANGE | Initializing ${SYSTEM_ID}`)\n\n registerSettings()\n\n game.system.CONST = { MAGICS, SUBTYPES }\n\n // Expose standalone apps globally for macros\n game.cde = { CDELoksyuApp, CDETinjiApp, CDEWheelApp }\n\n CONFIG.Combat.documentClass = CDECombat\n\n CONFIG.Actor.dataModels = {\n [ACTOR_TYPES.character]: CharacterDataModel,\n [ACTOR_TYPES.npc]: NpcDataModel,\n }\n CONFIG.Item.dataModels = {\n [ITEM_TYPES.item]: EquipmentDataModel,\n [ITEM_TYPES.kungfu]: KungfuDataModel,\n [ITEM_TYPES.spell]: SpellDataModel,\n [ITEM_TYPES.supernatural]: SupernaturalDataModel,\n [ITEM_TYPES.weapon]: WeaponDataModel,\n [ITEM_TYPES.armor]: ArmorDataModel,\n [ITEM_TYPES.sanhei]: SanheiDataModel,\n [ITEM_TYPES.ingredient]: IngredientDataModel,\n }\n\n CONFIG.Actor.documentClass = CDEActor\n CONFIG.Item.documentClass = CDEItem\n CONFIG.ChatMessage.documentClass = CDEMessage\n\n configureRuntime()\n\n foundry.applications.apps.DocumentSheetConfig.unregisterSheet(Actor, \"core\", foundry.appv1.sheets.ActorSheet)\n foundry.applications.apps.DocumentSheetConfig.unregisterSheet(Item, \"core\", foundry.appv1.sheets.ItemSheet)\n\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDECharacterSheet, {\n types: [ACTOR_TYPES.character],\n makeDefault: true,\n label: \"CDE Character Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDENpcSheet, {\n types: [ACTOR_TYPES.npc],\n makeDefault: true,\n label: \"CDE NPC Sheet (V2)\",\n })\n\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEItemSheet, {\n types: [ITEM_TYPES.item],\n makeDefault: true,\n label: \"CDE Item Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEKungfuSheet, {\n types: [ITEM_TYPES.kungfu],\n makeDefault: true,\n label: \"CDE KungFu Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESpellSheet, {\n types: [ITEM_TYPES.spell],\n makeDefault: true,\n label: \"CDE Spell Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESupernaturalSheet, {\n types: [ITEM_TYPES.supernatural],\n makeDefault: true,\n label: \"CDE Supernatural Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEWeaponSheet, {\n types: [ITEM_TYPES.weapon],\n makeDefault: true,\n label: \"CDE Weapon Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEArmorSheet, {\n types: [ITEM_TYPES.armor],\n makeDefault: true,\n label: \"CDE Armor Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESanheiSheet, {\n types: [ITEM_TYPES.sanhei],\n makeDefault: true,\n label: \"CDE Sanhei Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEIngredientSheet, {\n types: [ITEM_TYPES.ingredient],\n makeDefault: true,\n label: \"CDE Ingredient Sheet (V2)\",\n })\n\n await preloadPartials()\n registerHandlebarsHelpers()\n registerDice()\n\n console.info(`CHRONIQUESDELETRANGE | Initialized`)\n})\n\nHooks.once(\"ready\", async () => {\n await migrateIfNeeded()\n await loadWelcomeSceneIfNeeded()\n CDEWheelApp.registerHooks()\n if (game.user.isGM) showWelcomeMessage()\n})\n\n/** Add Loksyu + Tin Ji quick-access buttons to the chat panel (FoundryVTT v13) */\nHooks.on(\"renderChatLog\", (_app, html) => {\n const el = html instanceof HTMLElement ? html : (html[0] ?? html)\n if (!el?.querySelector) return\n\n // Avoid double-injection on re-renders\n if (el.querySelector(\".cde-chat-app-buttons\")) return\n\n const wrapper = document.createElement(\"div\")\n wrapper.classList.add(\"cde-chat-app-buttons\")\n wrapper.innerHTML = `\n \n \n \n `\n\n // Use event delegation to avoid being swallowed by Foundry's own handlers\n wrapper.addEventListener(\"click\", (ev) => {\n if (ev.target.closest(\".cde-chat-btn--loksyu\")) CDELoksyuApp.open()\n if (ev.target.closest(\".cde-chat-btn--tinji\")) CDETinjiApp.open()\n if (ev.target.closest(\".cde-chat-btn--wheel\")) CDEWheelApp.open()\n })\n\n // Insert before the chat form \u2014 works on v12 and v13\n const anchor = el.querySelector(\".chat-form\")\n ?? el.querySelector(\".chat-message-form\")\n ?? el.querySelector(\"form\")\n if (anchor) anchor.parentElement.insertBefore(wrapper, anchor)\n else el.appendChild(wrapper)\n})\n\n/** Inject Loksyu / TinJi action buttons into roll-result chat messages */\nHooks.on(\"renderChatMessageHTML\", (message, html) => {\n injectRollActions(message, html)\n if (message.flags?.[SYSTEM_ID]?.welcome) injectWelcomeActions(message, html)\n})\n\n/** Refresh all visible roll-result buttons whenever Loksyu or TinJi settings change */\nHooks.on(\"updateSetting\", setting => {\n if (!setting.key) return\n if (setting.key.includes(\"loksyuData\") || setting.key.includes(\"tinjiData\")) {\n refreshAllRollActions()\n }\n})\n\n/**\n * When an actor's initiative changes (via +/- buttons on the sheet),\n * sync the corresponding combatant in the active combat.\n */\nHooks.on(\"updateActor\", (actor, diff) => {\n if (!foundry.utils.hasProperty(diff, \"system.initiative\")) return\n if (!game.combat) return\n const initiative = actor.system.initiative\n const combatant = game.combat.combatants.find(c => c.actor?.id === actor.id)\n if (combatant && combatant.initiative !== initiative) {\n combatant.update({ initiative }).catch(() => {})\n }\n})\n\n/**\n * When a combatant's initiative changes (via wheel action buttons),\n * sync the actor's system.initiative to match.\n * Uses setTimeout to defer until after Foundry's update chain resolves,\n * avoiding concurrent #recordPreviousState errors on the combat document.\n */\nHooks.on(\"updateCombatant\", (combatant, diff) => {\n if (!(\"initiative\" in diff)) return\n const initiative = combatant.initiative\n if (initiative == null) return\n setTimeout(() => {\n const actor = combatant.actor\n if (actor && actor.system?.initiative !== initiative) {\n actor.update({ \"system.initiative\": initiative }).catch(() => {})\n }\n }, 0)\n})\n"], - "mappings": "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", + "sourcesContent": ["/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport const SYSTEM_ID = \"fvtt-chroniques-de-l-etrange\"\n\nexport const ACTOR_TYPES = {\n character: \"character\",\n npc: \"npc\",\n}\n\nexport const ITEM_TYPES = {\n item: \"item\",\n kungfu: \"kungfu\",\n spell: \"spell\",\n supernatural: \"supernatural\",\n weapon: \"weapon\",\n armor: \"armor\",\n sanhei: \"sanhei\",\n ingredient: \"ingredient\",\n}\n\nexport const SUBTYPES = {\n weapon: { id: \"weapon\", label: \"CDE.Weapon\" },\n armor: { id: \"armor\", label: \"CDE.Armor\" },\n sanhei: { id: \"sanhei\", label: \"CDE.Sanhei\" },\n other: { id: \"other\", label: \"CDE.Other\" },\n}\n\nexport const MAGICS = {\n internalcinnabar: {\n id: \"internalcinnabar\",\n background: \"linear-grey\",\n label: \"CDE.InternalCinnabar\",\n aspectlabel: \"CDE.Metal\",\n speciality: {\n essence: { label: \"CDE.Essence\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n mind: { label: \"CDE.Mind\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n purification: { label: \"CDE.Purification\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n manipulation: { label: \"CDE.Manipulation\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n aura: { label: \"CDE.Aura\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\", labelicon: \"Yang\", labelelement: \"CDE.Wood\" },\n },\n },\n alchemy: {\n id: \"alchemy\",\n background: \"linear-blue\",\n label: \"CDE.Alchemy\",\n aspectlabel: \"CDE.Water\",\n speciality: {\n acupuncture: { label: \"CDE.Acupuncture\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n elixirs: { label: \"CDE.Elixirs\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n poisons: { label: \"CDE.Poisons\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n arsenal: { label: \"CDE.Arsenal\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n potions: { label: \"CDE.Potions\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\", labelicon: \"Yang\", labelelement: \"CDE.Wood\" },\n },\n },\n masteryoftheway: {\n id: \"masteryoftheway\",\n background: \"linear-brown\",\n label: \"CDE.MasteryOfTheWay\",\n aspectlabel: \"CDE.Earth\",\n speciality: {\n curse: { label: \"CDE.Curse\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n transfiguration: { label: \"CDE.Transfiguration\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n necromancy: { label: \"CDE.Necromancy\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n climatecontrol: { label: \"CDE.ClimateControl\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n goldenmagic: { label: \"CDE.GoldenMagic\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\", labelicon: \"Yang\", labelelement: \"CDE.Wood\" },\n },\n },\n exorcism: {\n id: \"exorcism\",\n background: \"linear-red\",\n label: \"CDE.Exorcism\",\n aspectlabel: \"CDE.Fire\",\n speciality: {\n invocation: { label: \"CDE.Invocation\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n tracking: { label: \"CDE.Tracking\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n protection: { label: \"CDE.Protection\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n punishment: { label: \"CDE.Punishment\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n domination: { label: \"CDE.Domination\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\", labelicon: \"Yang\", labelelement: \"CDE.Wood\" },\n },\n },\n geomancy: {\n id: \"geomancy\",\n background: \"linear-green\",\n label: \"CDE.Geomancy\",\n aspectlabel: \"CDE.Wood\",\n speciality: {\n neutralization: { label: \"CDE.Neutralization\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n divination: { label: \"CDE.Divination\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n earthlyprayer: { label: \"CDE.EarthlyPrayer\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n heavenlyprayer: { label: \"CDE.HeavenlyPrayer\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n fungseoi: { label: \"CDE.Fungseoi\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\", labelicon: \"Yang\", labelelement: \"CDE.Wood\" },\n },\n },\n}\n\n/** Map aspect name \u2192 i18n label key */\nexport const ASPECT_LABELS = {\n metal: \"CDE.Metal\",\n water: \"CDE.Water\",\n earth: \"CDE.Earth\",\n fire: \"CDE.Fire\",\n wood: \"CDE.Wood\",\n}\n\n/** Map aspect name \u2192 image path */\nexport const ASPECT_ICONS = {\n metal: \"systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\",\n water: \"systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\",\n earth: \"systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\",\n fire: \"systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\",\n wood: \"systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\",\n}\n\n/** Map aspect name \u2192 die face pair [yin, yang] (face=10 stored as 0) */\nexport const ASPECT_FACES = {\n metal: [3, 8],\n water: [1, 6],\n earth: [0, 5], // 0 = face \"10\"\n fire: [2, 7],\n wood: [4, 9],\n}\n\n/** Ordered aspect names by index (metal=0, water=1, earth=2, fire=3, wood=4) */\nexport const ASPECT_NAMES = [\"metal\", \"water\", \"earth\", \"fire\", \"wood\"]\n\n/**\n * Wu Xing generating/overcoming cycle.\n * For each active aspect, the five result categories in order:\n * [successes, auspicious, noxious, loksyu, tinji]\n */\nexport const WU_XING_CYCLE = {\n wood: [\"wood\", \"fire\", \"water\", \"earth\", \"metal\"],\n fire: [\"fire\", \"earth\", \"wood\", \"metal\", \"water\"],\n earth: [\"earth\", \"metal\", \"fire\", \"water\", \"wood\"],\n metal: [\"metal\", \"water\", \"earth\", \"wood\", \"fire\"],\n water: [\"water\", \"wood\", \"metal\", \"fire\", \"earth\"],\n}\n\nexport const TEMPLATE_PARTIALS = [\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-character-skills.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-character-magics.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-character-nghang.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-character-treasures.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-character-items.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-character-kungfus.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-npc-supernaturals.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-npc-spells.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-npc-kungfus.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/actor/parts/cde-npc-items.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-loksyu-app.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-tinji-app.html\",\n \"systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-wheel-app.html\",\n]\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\n/**\n * Migrates actor JSON from the legacy CDE system to the current system format.\n *\n * This module is pure logic \u2014 it does not interact with Foundry APIs directly.\n * All transformation is done in-memory; the caller is responsible for creating\n * Foundry documents from the returned data.\n */\n\n// \u2500\u2500 Element label \u2192 key \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst ELEMENT_LABEL_TO_KEY = {\n \"m\u00E9tal\": \"metal\",\n \"metal\": \"metal\",\n \"eau\": \"eau\",\n \"terre\": \"terre\",\n \"feu\": \"feu\",\n \"bois\": \"bois\",\n}\n\n/** Normalise a French element label to its system key (e.g. \"M\u00E9tal\" \u2192 \"metal\"). */\nfunction elementKey(label = \"\") {\n return ELEMENT_LABEL_TO_KEY[label.toLowerCase().trim()] ?? \"metal\"\n}\n\n// \u2500\u2500 Hei polarity label \u2192 key \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction heiKey(label = \"\") {\n const l = label.toLowerCase().trim()\n if (l === \"yin/yang\" || l === \"yinyang\") return \"yinyang\"\n if (l === \"yang\") return \"yang\"\n return \"yin\"\n}\n\n// \u2500\u2500 Spell discipline inference from speciality name \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Maps French speciality labels (lowercase, accents stripped) \u2192 school key. */\nconst SPECIALITY_TO_DISCIPLINE = {\n // internalcinnabar\n \"essence\": \"internalcinnabar\",\n \"esprit\": \"internalcinnabar\",\n \"mind\": \"internalcinnabar\",\n \"purification\": \"internalcinnabar\",\n \"manipulation\": \"internalcinnabar\",\n \"aura\": \"internalcinnabar\",\n // alchemy\n \"acupuncture\": \"alchemy\",\n \"\u00E9lixirs\": \"alchemy\",\n \"elixirs\": \"alchemy\",\n \"poisons\": \"alchemy\",\n \"arsenal\": \"alchemy\",\n \"potions\": \"alchemy\",\n // masteryoftheway\n \"mal\u00E9diction\": \"masteryoftheway\",\n \"malediction\": \"masteryoftheway\",\n \"transfiguration\": \"masteryoftheway\",\n \"n\u00E9cromancie\": \"masteryoftheway\",\n \"necromancie\": \"masteryoftheway\",\n \"contr\u00F4le climatique\": \"masteryoftheway\",\n \"controle climatique\": \"masteryoftheway\",\n \"magie d'or\": \"masteryoftheway\",\n \"magie dor\": \"masteryoftheway\",\n // exorcism\n \"invocation\": \"exorcism\",\n \"pistage\": \"exorcism\",\n \"tra\u00E7age\": \"exorcism\",\n \"tracage\": \"exorcism\",\n \"protection\": \"exorcism\",\n \"ch\u00E2timent\": \"exorcism\",\n \"chatiment\": \"exorcism\",\n \"domination\": \"exorcism\",\n // geomancy\n \"neutralisation\": \"geomancy\",\n \"divination\": \"geomancy\",\n \"pri\u00E8re terrestre\": \"geomancy\",\n \"priere terrestre\": \"geomancy\",\n \"pri\u00E8re c\u00E9leste\": \"geomancy\",\n \"priere celeste\": \"geomancy\",\n \"g\u00E9omancie\": \"geomancy\",\n \"geomancie\": \"geomancy\",\n \"feng shui\": \"geomancy\",\n \"fungseoi\": \"geomancy\",\n}\n\n/**\n * Attempt to infer the magic school (discipline) from a spell's speciality name.\n * Falls back to scanning the item name for school keywords if needed.\n */\nfunction inferDiscipline(specialityName = \"\", itemName = \"\") {\n const key = specialityName.toLowerCase().trim()\n if (SPECIALITY_TO_DISCIPLINE[key]) return SPECIALITY_TO_DISCIPLINE[key]\n\n // Fuzzy fallback: check item name for school markers\n const name = itemName.toLowerCase()\n if (name.includes(\"exorcis\")) return \"exorcism\"\n if (name.includes(\"g\u00E9omanci\") || name.includes(\"geomanci\")) return \"geomancy\"\n if (name.includes(\"alchimi\")) return \"alchemy\"\n if (name.includes(\"cinnabre\") || name.includes(\"interne\")) return \"internalcinnabar\"\n if (name.includes(\"ma\u00EEtrise\") || name.includes(\"maitrise\") || name.includes(\"tao\")) return \"masteryoftheway\"\n\n return \"internalcinnabar\"\n}\n\n// \u2500\u2500 KungFu activation mapping \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction mapActivation(oldActivation = \"\") {\n const s = oldActivation.toLowerCase()\n if (s.includes(\"inflig\u00E9s\") || s.includes(\"infliges\")) return \"damage-inflicted\"\n if (s.includes(\"re\u00E7us\") || s.includes(\"recus\")) return \"damage-received\"\n if (s.includes(\"r\u00E9action\") || s.includes(\"reaction\")) return \"reaction\"\n if (s.includes(\"d\u00E9s-fastes\") || s.includes(\"des-fastes\") || s.includes(\"fastes\")) return \"dice\"\n if (s.includes(\"aide\")) return \"action-aid\"\n if (s.includes(\"attaque\") && s.includes(\"d\u00E9fense\")) return \"action-attack-defense\"\n if (s.includes(\"attaque\") && s.includes(\"defense\")) return \"action-attack-defense\"\n if (s.includes(\"attaque\")) return \"action-attack\"\n if (s.includes(\"d\u00E9fense\") || s.includes(\"defense\")) return \"action-defense\"\n return \"action-attack\"\n}\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst DEFAULT_ACTOR_IMG = \"icons/svg/mystery-man.svg\"\nconst DEFAULT_ITEM_IMG = \"icons/svg/item-bag.svg\"\n\n// \u2500\u2500 Item migration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction migrateEquipmentItem(oldItem) {\n const s = oldItem.system ?? {}\n return {\n name: oldItem.name,\n type: \"item\",\n img: oldItem.img || DEFAULT_ITEM_IMG,\n system: {\n reference: s.reference ?? \"\",\n description: s.description ?? \"\",\n quantity: Number(s.quantity ?? 1),\n weight: Number(s.weight ?? 0),\n notes: s.notes ?? \"\",\n },\n }\n}\n\nfunction migrateKungfuItem(oldItem) {\n const s = oldItem.system ?? {}\n const techs = s.techniques ?? {}\n\n const migratedTechs = {}\n for (const key of [\"technique1\", \"technique2\", \"technique3\"]) {\n const t = techs[key] ?? {}\n migratedTechs[key] = {\n check: Boolean(t.check),\n name: t.name ?? \"\",\n activation: mapActivation(t.activation ?? \"\"),\n technique: t.technique ?? \"\",\n }\n }\n\n return {\n name: oldItem.name,\n type: \"kungfu\",\n img: oldItem.img || DEFAULT_ITEM_IMG,\n system: {\n reference: s.reference ?? \"\",\n description: s.description ?? \"\",\n orientation: s.orientation || \"yin\",\n aspect: s.aspect || \"metal\",\n skill: s.skill || \"kungfu\",\n speciality: s.speciality ?? \"\",\n style: s.style ?? \"\",\n techniques: migratedTechs,\n notes: s.notes ?? \"\",\n },\n }\n}\n\nfunction migrateSpellItem(oldItem) {\n const s = oldItem.system ?? {}\n return {\n name: oldItem.name,\n type: \"spell\",\n img: oldItem.img || DEFAULT_ITEM_IMG,\n system: {\n reference: s.reference ?? \"\",\n description: s.description ?? \"\",\n specialityname: s.specialityname ?? \"\",\n associatedelement: elementKey(s.associatedelement ?? \"\"),\n heiType: heiKey(s.hei ?? \"\"),\n heiCost: Number(s.heiCost ?? 0),\n difficulty: Number(s.difficulty ?? 0),\n realizationtimeritual: s.realizationtimeritual ?? \"\",\n realizationtimeaccelerated: s.realizationtimeaccelerated ?? \"\",\n flashback: s.flashback ?? \"\",\n components: s.components ?? \"\",\n effects: s.effects ?? \"\",\n examples: s.examples ?? \"\",\n notes: s.notes ?? \"\",\n discipline: inferDiscipline(s.specialityname ?? \"\", oldItem.name ?? \"\"),\n },\n }\n}\n\nfunction migrateSupernaturalItem(oldItem) {\n const s = oldItem.system ?? {}\n // Old system stored a nested `supernatural: { reference }` \u2014 prefer that reference if top-level is empty\n const nestedRef = s.supernatural?.reference ?? \"\"\n return {\n name: oldItem.name,\n type: \"supernatural\",\n img: oldItem.img || DEFAULT_ITEM_IMG,\n system: {\n reference: s.reference || nestedRef,\n description: s.description ?? \"\",\n notes: s.notes ?? \"\",\n heiType: \"yin\",\n heiCost: 0,\n trigger: \"\",\n effects: \"\",\n },\n }\n}\n\nfunction migrateItem(oldItem) {\n switch (oldItem.type) {\n case \"item\": return migrateEquipmentItem(oldItem)\n case \"kungfu\": return migrateKungfuItem(oldItem)\n case \"spell\": return migrateSpellItem(oldItem)\n case \"supernatural\": return migrateSupernaturalItem(oldItem)\n default:\n // Unknown item type: keep as generic equipment\n return migrateEquipmentItem({ ...oldItem, type: \"item\" })\n }\n}\n\n// \u2500\u2500 Actor migration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction migrateCharacter(old) {\n const s = old.system ?? {}\n\n // aspects: keep only { chinese, label, value }\n const aspect = {}\n for (const [k, v] of Object.entries(s.aspect ?? {})) {\n aspect[k] = { chinese: v.chinese ?? \"\", label: v.label ?? \"\", value: Number(v.value ?? 0) }\n }\n\n // skills: keep { label, specialities, value }\n const skills = {}\n for (const [k, v] of Object.entries(s.skills ?? {})) {\n skills[k] = { label: v.label ?? \"\", specialities: v.specialities ?? \"\", value: Number(v.value ?? 0) }\n }\n\n // resources: keep { label, specialities, value, debt }\n const resources = {}\n for (const [k, v] of Object.entries(s.resources ?? {})) {\n resources[k] = { label: v.label ?? \"\", specialities: v.specialities ?? \"\", value: Number(v.value ?? 0), debt: Boolean(v.debt) }\n }\n\n // components: keep { value }\n const component = {}\n for (const [k, v] of Object.entries(s.component ?? {})) {\n component[k] = { value: v.value ?? \"\" }\n }\n\n // magics: keep { visible, value, speciality: { [key]: { check } } }\n const MAGIC_SPECIALITIES = {\n internalcinnabar: [\"essence\", \"mind\", \"purification\", \"manipulation\", \"aura\"],\n alchemy: [\"acupuncture\", \"elixirs\", \"poisons\", \"arsenal\", \"potions\"],\n masteryoftheway: [\"curse\", \"transfiguration\", \"necromancy\", \"climatecontrol\", \"goldenmagic\"],\n exorcism: [\"invocation\", \"tracking\", \"protection\", \"punishment\", \"domination\"],\n geomancy: [\"neutralization\", \"divination\", \"earthlyprayer\", \"heavenlyprayer\", \"fungseoi\"],\n }\n const magics = {}\n for (const [school, specs] of Object.entries(MAGIC_SPECIALITIES)) {\n const om = s.magics?.[school] ?? {}\n const speciality = {}\n for (const spec of specs) {\n speciality[spec] = { check: Boolean(om.speciality?.[spec]?.check) }\n }\n magics[school] = { visible: Boolean(om.visible), value: Number(om.value ?? 0), speciality }\n }\n\n // threetreasures: strip `min` from heiyang/heiyin; keep dicelevel as-is\n const tt = s.threetreasures ?? {}\n const threetreasures = {\n heiyang: { value: Number(tt.heiyang?.value ?? 0), max: Number(tt.heiyang?.max ?? 0) },\n heiyin: { value: Number(tt.heiyin?.value ?? 0), max: Number(tt.heiyin?.max ?? 0) },\n dicelevel: {\n level0d: {\n san: { value: Number(tt.dicelevel?.level0d?.san?.value ?? 0), max: Number(tt.dicelevel?.level0d?.san?.max ?? 0) },\n zing: { value: Number(tt.dicelevel?.level0d?.zing?.value ?? 0), max: Number(tt.dicelevel?.level0d?.zing?.max ?? 0) },\n },\n level1d: {\n san: { value: Number(tt.dicelevel?.level1d?.san?.value ?? 0), max: Number(tt.dicelevel?.level1d?.san?.max ?? 0) },\n zing: { value: Number(tt.dicelevel?.level1d?.zing?.value ?? 0), max: Number(tt.dicelevel?.level1d?.zing?.max ?? 0) },\n },\n level2d: {\n san: { value: Number(tt.dicelevel?.level2d?.san?.value ?? 0), max: Number(tt.dicelevel?.level2d?.san?.max ?? 0) },\n zing: { value: Number(tt.dicelevel?.level2d?.zing?.value ?? 0), max: Number(tt.dicelevel?.level2d?.zing?.max ?? 0) },\n },\n },\n }\n\n // biography (old separate field) merged into description\n const description = s.description || s.biography || \"\"\n\n return {\n name: old.name,\n type: \"character\",\n img: old.img || DEFAULT_ACTOR_IMG,\n system: {\n concept: s.concept ?? \"\",\n guardian: parseInt(s.guardian ?? \"0\") || 0,\n initiative: Number(s.initiative ?? 1),\n anti_initiative: Number(s.anti_initiative ?? 24),\n description,\n aspect,\n skills,\n resources,\n component,\n magics,\n threetreasures,\n experience: {\n value: Number(s.experience?.value ?? 0),\n max: Number(s.experience?.max ?? 0),\n min: Number(s.experience?.min ?? 0),\n },\n },\n items: (old.items ?? []).map(migrateItem),\n }\n}\n\nfunction migrateNpc(old) {\n const s = old.system ?? {}\n\n const aptitudes = {}\n for (const [k, v] of Object.entries(s.aptitudes ?? {})) {\n aptitudes[k] = { value: Number(v.value ?? 0), speciality: v.speciality ?? \"\" }\n }\n\n return {\n name: old.name,\n type: \"npc\",\n img: old.img || DEFAULT_ACTOR_IMG,\n system: {\n type: s.type ?? \"\",\n // Old system had separate `levelofthreat`/`powerofnuisance` as numbers\n // and string copies `threat`/`nuisance` \u2014 use the numeric fields\n threat: Number(s.levelofthreat ?? s.threat ?? 0),\n nuisance: Number(s.powerofnuisance ?? s.nuisance ?? 0),\n initiative: Number(s.initiative ?? 1),\n anti_initiative: Number(s.anti_initiative ?? 24),\n aptitudes,\n vitality: {\n value: Number(s.vitality?.value ?? 0),\n calcul: Number(s.vitality?.calcul ?? 0),\n note: s.vitality?.note ?? \"\",\n },\n hei: {\n value: Number(s.hei?.value ?? 0),\n calcul: Number(s.hei?.calcul ?? 0),\n note: s.hei?.note ?? \"\",\n },\n description: s.description ?? \"\",\n },\n items: (old.items ?? []).map(migrateItem),\n }\n}\n\n// \u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Migrate a single legacy actor JSON to the current system format.\n *\n * @param {object} oldJson Parsed JSON from the old system export\n * @returns {{ name: string, type: string, img: string, system: object, items: object[] }}\n * @throws {Error} if the actor type is unrecognised\n */\nexport function migrateActor(oldJson) {\n switch (oldJson.type) {\n case \"character\": return migrateCharacter(oldJson)\n case \"npc\": return migrateNpc(oldJson)\n default:\n throw new Error(`Unknown actor type \"${oldJson.type}\" in \"${oldJson.name}\"`)\n }\n}\n\n/**\n * Parse one or more legacy JSON strings and return migrated actor data.\n * Accepts a single actor object or an array of actor objects in one file.\n *\n * @param {string} jsonText Raw JSON text from a file\n * @returns {Array<{ name, type, img, system, items }>}\n */\nexport function parseLegacyJson(jsonText) {\n const parsed = JSON.parse(jsonText)\n if (typeof parsed !== \"object\" || parsed === null) {\n throw new Error(\"Le fichier JSON doit contenir un objet acteur ou un tableau d'acteurs\")\n }\n const actors = Array.isArray(parsed) ? parsed : [parsed]\n return actors.map(migrateActor)\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { parseLegacyJson } from \"../../migration/migrator.js\"\n\nconst MIGRATION_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-migration-app.html\"\n\n/**\n * Dialog for importing legacy CDE actor JSON files into the current system.\n *\n * Accessible via the System Settings menu (registerMenu).\n * Supports multi-file selection and shows a preview table before importing.\n */\nexport class CDEMigrationApp extends foundry.applications.api.HandlebarsApplicationMixin(\n foundry.applications.api.ApplicationV2\n) {\n static DEFAULT_OPTIONS = {\n id: \"cde-migration-app\",\n classes: [\"cde-migration-app\"],\n tag: \"div\",\n window: {\n title: \"CDE.MigrationTitle\",\n icon: \"fas fa-file-import\",\n resizable: false,\n },\n position: { width: 560, height: \"auto\" },\n actions: {\n clearFiles: CDEMigrationApp.#clearFiles,\n doImport: CDEMigrationApp.#doImport,\n },\n }\n\n static PARTS = {\n form: { template: MIGRATION_TEMPLATE },\n }\n\n /** @type {Array<{name: string, type: string, img: string, system: object, items: object[], _srcFile: string}>} */\n #pending = []\n\n /** @type {string[]} - error messages per file */\n #errors = []\n\n async _prepareContext(options) {\n return {\n pending: this.#pending,\n errors: this.#errors,\n hasPending: this.#pending.length > 0,\n hasErrors: this.#errors.length > 0,\n count: this.#pending.length,\n }\n }\n\n /** After render, wire up the file input. */\n _onRender(context, options) {\n super._onRender(context, options)\n const input = this.element.querySelector(\".cde-migration-file-input\")\n input?.addEventListener(\"change\", this.#onFileChange.bind(this))\n\n const dropZone = this.element.querySelector(\".cde-migration-drop-zone\")\n if (dropZone) {\n dropZone.addEventListener(\"dragover\", (e) => { e.preventDefault(); dropZone.classList.add(\"is-dragover\") })\n dropZone.addEventListener(\"dragleave\", () => dropZone.classList.remove(\"is-dragover\"))\n dropZone.addEventListener(\"drop\", (e) => {\n e.preventDefault()\n dropZone.classList.remove(\"is-dragover\")\n this.#processFiles(Array.from(e.dataTransfer.files))\n })\n }\n }\n\n async #onFileChange(event) {\n const files = Array.from(event.target.files ?? [])\n event.target.value = \"\"\n await this.#processFiles(files)\n }\n\n async #processFiles(files) {\n for (const file of files) {\n if (!file.name.endsWith(\".json\")) {\n this.#errors.push(game.i18n.format(\"CDE.MigrationErrorNotJson\", { file: file.name }))\n continue\n }\n try {\n const text = await file.text()\n const actors = parseLegacyJson(text)\n for (const actor of actors) {\n actor._srcFile = file.name\n // Avoid duplicates by name\n if (!this.#pending.some(p => p.name === actor.name)) {\n this.#pending.push(actor)\n }\n }\n } catch (err) {\n this.#errors.push(game.i18n.format(\"CDE.MigrationErrorParse\", { file: file.name, error: err.message }))\n }\n }\n this.render()\n }\n\n static async #clearFiles() {\n this.#pending = []\n this.#errors = []\n this.render()\n }\n\n static async #doImport() {\n if (!this.#pending.length) return\n\n const created = []\n const failed = []\n\n for (const data of this.#pending) {\n try {\n const { _srcFile, ...actorData } = data\n const actor = await Actor.create(actorData)\n created.push(actor.name)\n } catch (err) {\n failed.push(`${data.name}: ${err.message}`)\n console.error(`CHRONIQUESDELETRANGE | Migration failed for \"${data.name}\":`, err)\n }\n }\n\n this.#pending = []\n this.#errors = failed\n this.render()\n\n if (created.length) {\n ui.notifications.info(\n game.i18n.format(\"CDE.MigrationSuccess\", { count: created.length, names: created.join(\", \") })\n )\n }\n if (failed.length) {\n ui.notifications.warn(\n game.i18n.format(\"CDE.MigrationPartialError\", { count: failed.length })\n )\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { SYSTEM_ID } from \"./constants.js\"\nimport { CDEMigrationApp } from \"../ui/apps/migration-app.js\"\n\n/**\n * Register all world/client settings for the system.\n * Called during the \"init\" hook before sheets and data-models are set up.\n */\nexport function registerSettings() {\n game.settings.registerMenu(SYSTEM_ID, \"migrationTool\", {\n name: \"CDE.MigrationTitle\",\n label: \"CDE.MigrationMenuLabel\",\n hint: \"CDE.MigrationMenuHint\",\n icon: \"fas fa-file-import\",\n type: CDEMigrationApp,\n restricted: true,\n })\n\n game.settings.register(SYSTEM_ID, \"loksyuData\", {\n scope: \"world\",\n config: false,\n type: Object,\n default: {\n wood: { yin: 0, yang: 0 },\n fire: { yin: 0, yang: 0 },\n earth: { yin: 0, yang: 0 },\n metal: { yin: 0, yang: 0 },\n water: { yin: 0, yang: 0 },\n },\n })\n\n game.settings.register(SYSTEM_ID, \"loksyuConsumptionOrder\", {\n name: \"CDE.Settings.LoksyuConsumptionOrder\",\n hint: \"CDE.Settings.LoksyuConsumptionOrderHint\",\n scope: \"world\",\n config: true,\n type: String,\n choices: {\n \"yang-first\": \"CDE.Settings.LoksyuOrderYangFirst\",\n \"yin-first\": \"CDE.Settings.LoksyuOrderYinFirst\",\n \"balanced\": \"CDE.Settings.LoksyuOrderBalanced\",\n },\n default: \"yang-first\",\n onChange: () => Hooks.callAll(\"cde:loksyuUpdated\"),\n })\n\n game.settings.register(SYSTEM_ID, \"tinjiData\", {\n scope: \"world\",\n config: false,\n type: Number,\n default: 0,\n })\n\n game.settings.register(SYSTEM_ID, \"welcomeSceneLoaded\", {\n scope: \"world\",\n config: false,\n type: Boolean,\n default: false,\n })\n}\n\n/**\n * Run any pending data migrations on the \"ready\" hook.\n * Reserved for future schema migrations.\n */\nexport async function migrateIfNeeded() {\n // No migrations required yet.\n}\n\n/**\n * On first startup, import the \"Accueil\" scene from the cde-scenes compendium\n * into the world and activate it. Only runs once (tracked via the\n * `welcomeSceneLoaded` setting). GM-only.\n */\nexport async function loadWelcomeSceneIfNeeded() {\n if (!game.user.isGM) return\n if (game.settings.get(SYSTEM_ID, \"welcomeSceneLoaded\")) return\n\n try {\n const pack = game.packs.get(`${SYSTEM_ID}.cde-scenes`)\n if (!pack) return\n\n const index = await pack.getIndex()\n const entry = index.find(e => e.name === \"Accueil\")\n if (!entry) return\n\n // Check if the scene already exists in the world (e.g. manually imported)\n const existing = game.scenes.find(s => s.name === \"Accueil\")\n let scene = existing\n\n if (!scene) {\n const doc = await pack.getDocument(entry._id)\n ;[scene] = await Scene.createDocuments([doc.toObject()])\n }\n\n await game.settings.set(SYSTEM_ID, \"welcomeSceneLoaded\", true)\n await scene.activate()\n } catch (err) {\n console.error(\"CHRONIQUESDELETRANGE | loadWelcomeSceneIfNeeded failed:\", err)\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { MAGICS, SUBTYPES } from \"./constants.js\"\n\nexport function preLocalizeConfig() {\n const localizeConfigObject = (obj, keys) => {\n for (const o of Object.values(obj)) {\n for (const key of keys) {\n o[key] = game.i18n.localize(o[key])\n }\n }\n }\n\n localizeConfigObject(SUBTYPES, [\"label\"])\n Object.values(MAGICS).forEach((magic) => {\n magic.label = game.i18n.localize(magic.label)\n magic.aspectlabel = game.i18n.localize(magic.aspectlabel)\n Object.values(magic.speciality).forEach((spec) => {\n spec.label = game.i18n.localize(spec.label)\n spec.labelelement = game.i18n.localize(spec.labelelement)\n })\n })\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport function configureRuntime() {\n CONFIG.Actor.compendiumBanner = \"/systems/fvtt-chroniques-de-l-etrange/images/banners/actor-banner.webp\"\n CONFIG.Adventure.compendiumBanner = \"/systems/fvtt-chroniques-de-l-etrange/images/banners/adventure-banner.webp\"\n CONFIG.Cards.compendiumBanner = \"ui/banners/cards-banner.webp\"\n CONFIG.Item.compendiumBanner = \"/systems/fvtt-chroniques-de-l-etrange/images/banners/item-banner.webp\"\n CONFIG.JournalEntry.compendiumBanner = \"/systems/fvtt-chroniques-de-l-etrange/images/banners/journalentry-banner.webp\"\n CONFIG.Macro.compendiumBanner = \"ui/banners/macro-banner.webp\"\n CONFIG.Playlist.compendiumBanner = \"ui/banners/playlist-banner.webp\"\n CONFIG.RollTable.compendiumBanner = \"ui/banners/rolltable-banner.webp\"\n CONFIG.Scene.compendiumBanner = \"/systems/fvtt-chroniques-de-l-etrange/images/banners/scene-banner.webp\"\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class CharacterDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const numberField = (initial = 0, extra = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...extra })\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const boolField = (initial = false) => new fields.BooleanField({ required: true, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n const aspectField = (label, chinese) =>\n new fields.SchemaField({\n chinese: stringField(chinese),\n label: stringField(label),\n value: numberField(15, { min: 0 }),\n })\n\n const skillField = (label) =>\n new fields.SchemaField({\n label: stringField(label),\n specialities: stringField(\"\"),\n value: numberField(0, { min: 0 }),\n })\n\n const resourceField = (label) =>\n new fields.SchemaField({\n label: stringField(label),\n specialities: stringField(\"\"),\n value: numberField(0, { min: 0 }),\n debt: boolField(false),\n })\n\n const componentField = () =>\n new fields.SchemaField({\n value: stringField(\"\"),\n })\n\n const magicSpecialityField = () =>\n new fields.SchemaField({\n check: boolField(false),\n })\n\n const magicField = () =>\n new fields.SchemaField({\n visible: boolField(true),\n value: numberField(0, { min: 0 }),\n speciality: new fields.SchemaField({\n essence: magicSpecialityField(),\n mind: magicSpecialityField(),\n purification: magicSpecialityField(),\n manipulation: magicSpecialityField(),\n aura: magicSpecialityField(),\n acupuncture: magicSpecialityField(),\n elixirs: magicSpecialityField(),\n poisons: magicSpecialityField(),\n arsenal: magicSpecialityField(),\n potions: magicSpecialityField(),\n curse: magicSpecialityField(),\n transfiguration: magicSpecialityField(),\n necromancy: magicSpecialityField(),\n climatecontrol: magicSpecialityField(),\n goldenmagic: magicSpecialityField(),\n invocation: magicSpecialityField(),\n tracking: magicSpecialityField(),\n protection: magicSpecialityField(),\n punishment: magicSpecialityField(),\n domination: magicSpecialityField(),\n neutralization: magicSpecialityField(),\n divination: magicSpecialityField(),\n earthlyprayer: magicSpecialityField(),\n heavenlyprayer: magicSpecialityField(),\n fungseoi: magicSpecialityField(),\n }),\n })\n\n const treasureBranch = () =>\n new fields.SchemaField({\n value: numberField(0, { min: 0 }),\n max: numberField(0, { min: 0 }),\n min: numberField(0, { min: 0 }),\n })\n\n const treasureLevel = () =>\n new fields.SchemaField({\n san: treasureBranch(),\n zing: treasureBranch(),\n })\n\n const schema = {\n concept: stringField(\"\"),\n guardian: numberField(0, { min: 0, max: 5 }),\n initiative: numberField(1, { min: 0 }),\n anti_initiative: numberField(24, { min: 0 }),\n description: htmlField(\"\"),\n prefs: new fields.SchemaField({\n typeofthrow: new fields.SchemaField({\n check: boolField(true),\n choice: stringField(\"0\"),\n }),\n }),\n prompt: new fields.SchemaField({\n typeofthrow: new fields.SchemaField({\n check: boolField(true),\n choice: stringField(\"0\"),\n }),\n configure: new fields.SchemaField({\n numberofdice: numberField(0),\n aspect: numberField(0),\n bonus: numberField(0),\n bonusauspiciousdice: numberField(0),\n typeofthrow: numberField(0),\n aspectskill: numberField(0),\n bonusmalusskill: numberField(0),\n rolldifficulty: numberField(0),\n freepowerlevels: numberField(0),\n }),\n }),\n aspect: new fields.SchemaField({\n fire: aspectField(\"CDE.Fire\", \"\u328B\"),\n earth: aspectField(\"CDE.Earth\", \"\u328F\"),\n metal: aspectField(\"CDE.Metal\", \"\u328E\"),\n water: aspectField(\"CDE.Water\", \"\u328C\"),\n wood: aspectField(\"CDE.Wood\", \"\u328D\"),\n }),\n skills: new fields.SchemaField({\n art: skillField(\"CDE.Art\"),\n investigation: skillField(\"CDE.Investigation\"),\n erudition: skillField(\"CDE.Erudition\"),\n knavery: skillField(\"CDE.Knavery\"),\n wordliness: skillField(\"CDE.Wordliness\"),\n prowess: skillField(\"CDE.Prowess\"),\n sciences: skillField(\"CDE.Sciences\"),\n technologies: skillField(\"CDE.Technologies\"),\n kungfu: skillField(\"CDE.KungFu\"),\n rangedcombat: skillField(\"CDE.RangedCombat\"),\n }),\n resources: new fields.SchemaField({\n supply: resourceField(\"CDE.Supply\"),\n inquiry: resourceField(\"CDE.Inquiry\"),\n influence: resourceField(\"CDE.Influence\"),\n }),\n component: new fields.SchemaField({\n one: componentField(),\n two: componentField(),\n three: componentField(),\n four: componentField(),\n five: componentField(),\n six: componentField(),\n seven: componentField(),\n eight: componentField(),\n nine: componentField(),\n zero: componentField(),\n }),\n magicOrder: new fields.ArrayField(\n new fields.StringField({ required: true, nullable: false, initial: \"\" }),\n { required: true, initial: [] }\n ),\n magics: new fields.SchemaField({\n internalcinnabar: magicField(),\n alchemy: magicField(),\n masteryoftheway: magicField(),\n exorcism: magicField(),\n geomancy: magicField(),\n }),\n threetreasures: new fields.SchemaField({\n heiyang: new fields.SchemaField({ value: numberField(0, { min: 0 }), max: numberField(0, { min: 0 }) }),\n heiyin: new fields.SchemaField({ value: numberField(0, { min: 0 }), max: numberField(0, { min: 0 }) }),\n dicelevel: new fields.SchemaField({\n level0d: treasureLevel(),\n level1d: treasureLevel(),\n level2d: treasureLevel(),\n }),\n }),\n experience: new fields.SchemaField({\n value: numberField(0, { min: 0 }),\n max: numberField(0, { min: 0 }),\n min: numberField(0, { min: 0 }),\n }),\n }\n\n return schema\n }\n\n prepareDerivedData() {\n this.anti_initiative = 25 - (this.initiative ?? 0)\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class NpcDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const numberField = (initial = 0, extra = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...extra })\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const boolField = (initial = false) => new fields.BooleanField({ required: true, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n const aptitudeField = () =>\n new fields.SchemaField({\n value: numberField(0, { min: 0 }),\n speciality: stringField(\"\"),\n })\n\n const trackedField = () =>\n new fields.SchemaField({\n value: numberField(0, { min: 0 }),\n calcul: numberField(0, { min: 0 }),\n note: stringField(\"\"),\n })\n\n return {\n type: stringField(\"\"),\n threat: numberField(0, { min: 0, max: 4 }), // profane(0) | apprentice(1) | initiate(2) | accomplished(3) | renowned(4)\n nuisance: numberField(0, { min: 0, max: 5 }), // figurant(0) | minion(1) | adversary(2) | ally(3) | boss(4) | divinity(5)\n initiative: numberField(1, { min: 0 }),\n anti_initiative: numberField(24, { min: 0 }),\n aptitudes: new fields.SchemaField({\n physical: aptitudeField(),\n martial: aptitudeField(),\n mental: aptitudeField(),\n social: aptitudeField(),\n spiritual: aptitudeField(),\n }),\n vitality: trackedField(),\n hei: trackedField(),\n description: htmlField(\"\"),\n prefs: new fields.SchemaField({\n typeofthrow: new fields.SchemaField({\n check: boolField(false),\n choice: stringField(\"0\"),\n }),\n }),\n }\n }\n\n prepareDerivedData() {\n this.anti_initiative = 25 - (this.initiative ?? 0)\n this.vitality.calcul = (this.aptitudes.physical.value ?? 0) * 4\n this.hei.calcul = (this.aptitudes.spiritual.value ?? 0) * 4\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class EquipmentDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const numberField = (initial = 0, extra = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...extra })\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n quantity: numberField(1, { min: 0 }),\n weight: numberField(0, { min: 0 }),\n notes: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class KungfuDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n const boolField = (initial = false) => new fields.BooleanField({ required: true, initial })\n\n const techniqueField = () =>\n new fields.SchemaField({\n check: boolField(false),\n name: stringField(\"\"),\n activation: stringField(\"action-attack\"), // action-attack | action-defense | action-aid | action-attack-defense | reaction | dice | damage-inflicted | damage-received\n technique: htmlField(\"\"),\n })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n orientation: stringField(\"yin\"), // yin | yang | yinyang\n aspect: stringField(\"metal\"), // metal | water | earth | fire | wood\n skill: stringField(\"kungfu\"), // kungfu | rangedcombat\n speciality: stringField(\"\"),\n style: stringField(\"\"),\n techniques: new fields.SchemaField({\n technique1: techniqueField(),\n technique2: techniqueField(),\n technique3: techniqueField(),\n }),\n notes: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class SpellDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n specialityname: stringField(\"\"),\n associatedelement: stringField(\"metal\"), // metal | water | earth | fire | wood\n hei: stringField(\"\"),\n realizationtimeritual: stringField(\"\"),\n realizationtimeaccelerated: stringField(\"\"),\n flashback: stringField(\"\"),\n components: htmlField(\"\"),\n effects: htmlField(\"\"),\n examples: htmlField(\"\"),\n notes: htmlField(\"\"),\n discipline: stringField(\"internalcinnabar\"),\n heiType: stringField(\"yin\"),\n heiCost: new fields.NumberField({ required: true, nullable: false, integer: true, min: 0, initial: 1 }),\n difficulty: new fields.NumberField({ required: true, nullable: false, integer: true, min: 0, initial: 1 }),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class SupernaturalDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n notes: htmlField(\"\"),\n heiType: stringField(\"yin\"),\n heiCost: new fields.NumberField({ required: true, nullable: false, integer: true, min: 0, initial: 0 }),\n trigger: stringField(\"\"),\n effects: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class WeaponDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts })\n const boolField = (initial = false) => new fields.BooleanField({ required: true, initial })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n hasSpeciality: boolField(false),\n weaponType: stringField(\"melee\"),\n material: stringField(\"\"),\n damageAspect: stringField(\"metal\"),\n damageBase: intField(0),\n range: stringField(\"contact\"), // contact | courte | mediane | longue | extreme\n obtainLevel: intField(0, { min: 0, max: 5 }),\n obtainDifficulty: intField(0, { min: 0, max: 3 }),\n quantity: intField(1, { min: 0 }),\n notes: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class ArmorDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n protectionValue: intField(0),\n domain: stringField(\"\"),\n obtainLevel: intField(0, { min: 0, max: 5 }),\n obtainDifficulty: intField(0, { min: 0, max: 3 }),\n quantity: intField(1, { min: 0 }),\n notes: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class SanheiDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts })\n\n const propertySchema = () => new fields.SchemaField({\n name: stringField(\"\"),\n heiCost: intField(0),\n heiType: stringField(\"yin\"),\n description: htmlField(\"\"),\n })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n heiType: stringField(\"yin\"),\n properties: new fields.SchemaField({\n prop1: propertySchema(),\n prop2: propertySchema(),\n prop3: propertySchema(),\n }),\n notes: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport default class IngredientDataModel extends foundry.abstract.TypeDataModel {\n static defineSchema() {\n const { fields } = foundry.data\n const stringField = (initial = \"\") => new fields.StringField({ required: true, nullable: false, initial })\n const htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n school: stringField(\"all\"),\n obtainLevel: intField(0, { min: 0, max: 5 }),\n obtainDifficulty: intField(0, { min: 0, max: 3 }),\n quantity: intField(1, { min: 0 }),\n notes: htmlField(\"\"),\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport class CDEMessage extends ChatMessage {\n async renderHTML({ canDelete, canClose = false, ...rest } = {}) {\n const html = await super.renderHTML({ canDelete, canClose, ...rest })\n this.#enrichChatCard(html)\n return html\n }\n\n #enrichChatCard(html) {\n const tokenDoc = (this.speaker.scene && this.speaker.token)\n ? game.scenes.get(this.speaker.scene)?.tokens.get(this.speaker.token)\n : null\n const actor = tokenDoc?.actor ?? game.actors.get(this.speaker.actor) ?? null\n\n const [img, nameText] = this.isContentVisible\n ? [actor?.img ?? this.author.avatar, this.alias]\n : [this.author.avatar, this.author.name]\n\n const avatarImg = Object.assign(document.createElement(\"img\"), { src: img, alt: nameText })\n const avatar = Object.assign(document.createElement(\"a\"), { className: \"avatar\" })\n if (actor) avatar.dataset.uuid = actor.uuid\n avatar.append(avatarImg)\n\n const title = Object.assign(document.createElement(\"span\"), { className: \"title\", textContent: nameText })\n const name = Object.assign(document.createElement(\"span\"), { className: \"name-stacked\" })\n name.append(title)\n\n html.querySelector(\".message-sender\")?.replaceChildren(avatar, name)\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nexport class CDEActor extends Actor {\n getRollData() {\n return this.toObject(false).system\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\n/** Default icons per item type. */\nconst DEFAULT_ICONS = {\n kungfu: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-kungfu.svg\",\n spell: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-spell.svg\",\n supernatural: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-supernatural.svg\",\n weapon: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-weapon.svg\",\n armor: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-armor.svg\",\n sanhei: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-sanhei.svg\",\n ingredient: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-ingredient.svg\",\n item: \"systems/fvtt-chroniques-de-l-etrange/images/icons/icon-item.svg\",\n};\n\nexport class CDEItem extends Item {\n\n /** @override */\n async _preCreate(data, options, userId) {\n await super._preCreate(data, options, userId);\n const defaultIcon = DEFAULT_ICONS[this.type];\n if (defaultIcon && (!data.img || data.img === Item.DEFAULT_ICON)) {\n this.updateSource({ img: defaultIcon });\n }\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nconst DIGIT_LABELS = [\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-1.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-2.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-3.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-4.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-5.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-6.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-7.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-8.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-9.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/digit/d10-10.webp\",\n]\n\nconst CLASSIC_LABELS = [\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-1.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-2.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-3.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-4.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-5.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-6.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-7.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-8.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-9.webp\",\n \"systems/fvtt-chroniques-de-l-etrange/images/dice-so-nice/d10-10.webp\",\n]\n\nexport function registerDice() {\n Hooks.once(\"diceSoNiceReady\", (dice3d) => {\n dice3d.addColorset(\n {\n name: \"cde\",\n description: \"CdE\",\n foreground: \"#000000\",\n background: \"#ffffff\",\n edge: \"#ffffff\",\n font: \"DeliusUnicase\",\n texture: \"ice\",\n material: \"plastic\",\n },\n \"preferred\",\n )\n\n dice3d.addSystem({ id: \"fvtt-chroniques-de-l-etrangedigit\", name: \"Chroniques de l'\u00E9trange digits\" }, \"preferred\")\n dice3d.addDicePreset({ type: \"d10\", labels: DIGIT_LABELS, system: \"fvtt-chroniques-de-l-etrangedigit\" })\n\n dice3d.addSystem({ id: \"fvtt-chroniques-de-l-etrange\", name: \"Chroniques de l'\u00E9trange\" }, \"preferred\")\n dice3d.addDicePreset({ type: \"d10\", labels: CLASSIC_LABELS, system: \"fvtt-chroniques-de-l-etrange\" })\n })\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { MAGICS } from \"../config/constants.js\"\n\nexport function registerHandlebarsHelpers() {\n const { Handlebars } = globalThis\n if (!Handlebars) return\n\n Handlebars.registerHelper(\"getMagicLabel\", function (magic) {\n return game.i18n.localize(MAGICS[magic]?.label ?? \"\")\n })\n\n Handlebars.registerHelper(\"getMagicAspectLabel\", function (magic) {\n return game.i18n.localize(MAGICS[magic]?.aspectlabel ?? \"\")\n })\n\n Handlebars.registerHelper(\"getMagicSpecialityLabel\", function (magic, speciality) {\n return game.i18n.localize(MAGICS[magic]?.speciality?.[speciality]?.label ?? \"\")\n })\n\n Handlebars.registerHelper(\"getMagicSpecialityClassIcon\", function (magic, speciality) {\n return MAGICS[magic]?.speciality?.[speciality]?.classicon ?? \"\"\n })\n\n Handlebars.registerHelper(\"getMagicSpecialityElementIcon\", function (magic, speciality) {\n return MAGICS[magic]?.speciality?.[speciality]?.elementicon ?? \"\"\n })\n\n Handlebars.registerHelper(\"getMagicSpecialityLabelIcon\", function (magic, speciality) {\n return MAGICS[magic]?.speciality?.[speciality]?.labelicon ?? \"\"\n })\n\n Handlebars.registerHelper(\"getMagicSpecialityLabelElement\", function (magic, speciality) {\n return game.i18n.localize(MAGICS[magic]?.speciality?.[speciality]?.labelelement ?? \"\")\n })\n\n Handlebars.registerHelper(\"getMagicAspectIcon\", function (magic) {\n const icons = {\n internalcinnabar: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\",\n alchemy: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\",\n masteryoftheway: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\",\n exorcism: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\",\n geomancy: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\",\n }\n return icons[magic] ?? \"\"\n })\n\n Handlebars.registerHelper(\"getElementIcon\", function (aspect) {\n const icons = {\n metal: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp\",\n water: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\",\n earth: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\",\n fire: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\",\n wood: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\",\n // legacy French keys\n eau: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp\",\n terre: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp\",\n feu: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp\",\n bois: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp\",\n }\n return icons[aspect] ?? \"\"\n })\n\n Handlebars.registerHelper(\"getOrientationIcon\", function (orientation) {\n const icons = {\n yin: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp\",\n yang: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp\",\n yinyang: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp\",\n }\n return icons[orientation] ?? \"\"\n })\n\n Handlebars.registerHelper(\"getOrientationLabel\", function (orientation) {\n const keys = {\n yin: \"CDE.OrientationYin\",\n yang: \"CDE.OrientationYang\",\n yinyang: \"CDE.OrientationYinYang\",\n }\n return game.i18n.localize(keys[orientation] ?? \"CDE.Orientation\")\n })\n\n Handlebars.registerHelper(\"getActivationLabel\", function (activation) {\n const keys = {\n \"action-attack\": \"CDE.ActivationAttack\",\n \"action-defense\": \"CDE.ActivationDefense\",\n \"action-aid\": \"CDE.ActivationAid\",\n \"action-attack-defense\": \"CDE.ActivationAttackOrDefense\",\n reaction: \"CDE.ActivationReaction\",\n dice: \"CDE.ActivationDice\",\n \"damage-inflicted\": \"CDE.ActivationDamageInflicted\",\n \"damage-received\": \"CDE.ActivationDamageReceived\",\n }\n return game.i18n.localize(keys[activation] ?? \"CDE.Activation\")\n })\n\n /**\n * Compute the SVG x,y coordinates for a cran on the initiative wheel.\n * Cran 1\u201324 are arranged counter-clockwise from the bottom (reference at 6 o'clock).\n * angle = 90\u00B0 + cran * 15\u00B0 (counter-clockwise = positive in standard math, negative in SVG).\n * In SVG coords: x = cx + r*cos(a), y = cy - r*sin(a) [y-axis is flipped in SVG].\n */\n Handlebars.registerHelper(\"cranPosition\", function (cran, cx, cy, r) {\n const angleDeg = 90 + cran * 15 // counter-clockwise from bottom\n const angleRad = (angleDeg * Math.PI) / 180\n const x = Math.round(cx + r * Math.cos(angleRad))\n const y = Math.round(cy - r * Math.sin(angleRad))\n return { x, y }\n })\n\n /** X offset for overlapping fighters on the same cran. Centres a 30px image on the cran cx. */\n Handlebars.registerHelper(\"fighterX\", function (cx, index, total) {\n const offset = total > 1 ? (index - (total - 1) / 2) * 34 : 0\n return Math.round(cx - 15 + offset)\n })\n\n /** Y offset for fighters \u2014 positions image just above the cran circle. */\n Handlebars.registerHelper(\"fighterY\", function (cy, index, total) {\n return Math.round(cy - 50)\n })\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { TEMPLATE_PARTIALS } from \"../config/constants.js\"\n\nexport async function preloadPartials() {\n return foundry.applications.handlebars.loadTemplates(TEMPLATE_PARTIALS)\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\n/**\n * Initiative determination system for Chroniques de l'\u00C9trange.\n *\n * PJ formula: Initiative = Prouesse + Premi\u00E8re action (comp\u00E9tence/ressource/magie)\n * PNJ formula: Initiative = Aptitude physique + Premi\u00E8re action (aptitude)\n *\n * Range 1-24 ; anti-initiative = 25 \u2212 initiative.\n * Combat order is ascending (low initiative acts first).\n */\n\nconst PC_PROMPT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-prompt.html\"\nconst NPC_PROMPT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-prompt-npc.html\"\nconst RESULT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-result.html\"\n\n/** Skills, resources and magics available as \"premi\u00E8re action\" for a PC. */\nfunction buildPCOptions(sys) {\n const sk = sys.skills ?? {}\n const rs = sys.resources ?? {}\n const mg = sys.magics ?? {}\n return [\n { key: \"art\", label: game.i18n.localize(\"CDE.Art\"), value: sk.art?.value ?? 0 },\n { key: \"investigation\", label: game.i18n.localize(\"CDE.Investigation\"), value: sk.investigation?.value ?? 0 },\n { key: \"erudition\", label: game.i18n.localize(\"CDE.Erudition\"), value: sk.erudition?.value ?? 0 },\n { key: \"knavery\", label: game.i18n.localize(\"CDE.Knavery\"), value: sk.knavery?.value ?? 0 },\n { key: \"wordliness\", label: game.i18n.localize(\"CDE.Wordliness\"), value: sk.wordliness?.value ?? 0 },\n { key: \"prowess\", label: game.i18n.localize(\"CDE.Prowess\"), value: sk.prowess?.value ?? 0 },\n { key: \"sciences\", label: game.i18n.localize(\"CDE.Sciences\"), value: sk.sciences?.value ?? 0 },\n { key: \"technologies\", label: game.i18n.localize(\"CDE.Technologies\"), value: sk.technologies?.value ?? 0 },\n { key: \"kungfu\", label: game.i18n.localize(\"CDE.KungFu\"), value: sk.kungfu?.value ?? 0 },\n { key: \"rangedcombat\", label: game.i18n.localize(\"CDE.RangedCombat\"), value: sk.rangedcombat?.value ?? 0 },\n { key: \"supply\", label: game.i18n.localize(\"CDE.Supply\"), value: rs.supply?.value ?? 0 },\n { key: \"inquiry\", label: game.i18n.localize(\"CDE.Inquiry\"), value: rs.inquiry?.value ?? 0 },\n { key: \"influence\", label: game.i18n.localize(\"CDE.Influence\"), value: rs.influence?.value ?? 0 },\n { key: \"internalcinnabar\", label: game.i18n.localize(\"CDE.InternalCinnabar\"), value: mg.internalcinnabar?.value ?? 0 },\n { key: \"alchemy\", label: game.i18n.localize(\"CDE.Alchemy\"), value: mg.alchemy?.value ?? 0 },\n { key: \"masteryoftheway\", label: game.i18n.localize(\"CDE.MasteryOfTheWay\"), value: mg.masteryoftheway?.value ?? 0 },\n { key: \"exorcism\", label: game.i18n.localize(\"CDE.Exorcism\"), value: mg.exorcism?.value ?? 0 },\n { key: \"geomancy\", label: game.i18n.localize(\"CDE.Geomancy\"), value: mg.geomancy?.value ?? 0 },\n ]\n}\n\n/** Aptitudes available as \"premi\u00E8re action\" for an NPC. */\nfunction buildNPCOptions(sys) {\n const ap = sys.aptitudes ?? {}\n return [\n { key: \"physical\", label: game.i18n.localize(\"CDE.Physical\"), value: ap.physical?.value ?? 0 },\n { key: \"martial\", label: game.i18n.localize(\"CDE.Martial\"), value: ap.martial?.value ?? 0 },\n { key: \"mental\", label: game.i18n.localize(\"CDE.Mental\"), value: ap.mental?.value ?? 0 },\n { key: \"social\", label: game.i18n.localize(\"CDE.Social\"), value: ap.social?.value ?? 0 },\n { key: \"spiritual\", label: game.i18n.localize(\"CDE.Spiritual\"), value: ap.spiritual?.value ?? 0 },\n ]\n}\n\n/** Parse the dialog element and extract firstaction + modifier. */\nfunction readInitFields(dialog) {\n const root = dialog.element ?? dialog\n const selectedKey = root.querySelector(\"select[name='firstaction']\")?.value ?? \"\"\n const modifier = parseInt(root.querySelector(\"input[name='modifier']\")?.value ?? \"0\", 10) || 0\n return { selectedKey, modifier }\n}\n\n/** Post a styled initiative chat message. */\nasync function sendInitChatMessage({ actor, baseName, baseValue, actionName, actionValue, modifier, initiative, antiInitiative }) {\n const html = await foundry.applications.handlebars.renderTemplate(RESULT_TEMPLATE, {\n actorName: actor.name,\n actorImg: actor.img,\n baseName,\n baseValue,\n actionName,\n actionValue,\n modifier,\n hasModifier: modifier !== 0,\n initiative,\n antiInitiative,\n })\n await ChatMessage.create({\n user: game.user.id,\n speaker: ChatMessage.getSpeaker({ actor }),\n content: html,\n })\n}\n\n/**\n * Open the PC initiative dialog, compute initiative (Prouesse + Premi\u00E8re action + modificateur)\n * and update the actor, then post a chat card.\n */\nexport async function rollInitiativePC(actor) {\n const sys = actor.system\n const prowess = sys.skills?.prowess?.value ?? 0\n const options = buildPCOptions(sys)\n const baseName = game.i18n.localize(\"CDE.Prowess\")\n\n const content = await foundry.applications.handlebars.renderTemplate(PC_PROMPT_TEMPLATE, {\n prowessValue: prowess,\n options,\n modifier: 0,\n })\n\n const result = await foundry.applications.api.DialogV2.prompt({\n window: { title: game.i18n.localize(\"CDE.InitiativeRoll\") },\n content,\n rejectClose: false,\n ok: {\n label: game.i18n.localize(\"CDE.Validate\"),\n callback: (_ev, _btn, dialog) => readInitFields(dialog),\n },\n })\n if (!result) return\n\n const { selectedKey, modifier } = result\n const selected = options.find((o) => o.key === selectedKey) ?? options[0]\n const rawValue = prowess + selected.value + modifier\n const initiative = Math.max(1, Math.min(24, rawValue))\n const antiInit = 25 - initiative\n\n await actor.update({ \"system.initiative\": initiative })\n await sendInitChatMessage({\n actor,\n baseName,\n baseValue: prowess,\n actionName: selected.label,\n actionValue: selected.value,\n modifier,\n initiative,\n antiInitiative: antiInit,\n })\n}\n\n/**\n * Open the NPC initiative dialog, compute initiative (Aptitude physique + Premi\u00E8re action + modificateur)\n * and update the actor, then post a chat card.\n */\nexport async function rollInitiativeNPC(actor) {\n const sys = actor.system\n const physical = sys.aptitudes?.physical?.value ?? 0\n const options = buildNPCOptions(sys)\n const baseName = game.i18n.localize(\"CDE.Physical\")\n\n const content = await foundry.applications.handlebars.renderTemplate(NPC_PROMPT_TEMPLATE, {\n physicalValue: physical,\n options,\n modifier: 0,\n })\n\n const result = await foundry.applications.api.DialogV2.prompt({\n window: { title: game.i18n.localize(\"CDE.InitiativeRoll\") },\n content,\n rejectClose: false,\n ok: {\n label: game.i18n.localize(\"CDE.Validate\"),\n callback: (_ev, _btn, dialog) => readInitFields(dialog),\n },\n })\n if (!result) return\n\n const { selectedKey, modifier } = result\n const selected = options.find((o) => o.key === selectedKey) ?? options[0]\n const rawValue = physical + selected.value + modifier\n const initiative = Math.max(1, Math.min(24, rawValue))\n const antiInit = 25 - initiative\n\n await actor.update({ \"system.initiative\": initiative })\n await sendInitChatMessage({\n actor,\n baseName,\n baseValue: physical,\n actionName: selected.label,\n actionValue: selected.value,\n modifier,\n initiative,\n antiInitiative: antiInit,\n })\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\n/**\n * Loksyu / TinJi settings-based helpers.\n *\n * Data is stored as world settings instead of singleton Actor documents.\n */\n\nimport { SYSTEM_ID, WU_XING_CYCLE, ASPECT_FACES } from \"../../config/constants.js\"\n\n/** Read the current loksyu data object from world settings */\nexport function getLoksyuData() {\n return game.settings.get(SYSTEM_ID, \"loksyuData\") ?? {\n wood: {yin:0,yang:0}, fire: {yin:0,yang:0}, earth: {yin:0,yang:0}, metal: {yin:0,yang:0}, water: {yin:0,yang:0},\n }\n}\n\n/** Write the loksyu data object to world settings */\nexport async function setLoksyuData(data) {\n await game.settings.set(SYSTEM_ID, \"loksyuData\", data)\n Hooks.callAll(\"cde:loksyuUpdated\", data)\n}\n\n/** Read current TinJi value from world settings */\nexport function getTinjiValue() {\n return game.settings.get(SYSTEM_ID, \"tinjiData\") ?? 0\n}\n\n/** Write TinJi value to world settings */\nexport async function setTinjiValue(value) {\n await game.settings.set(SYSTEM_ID, \"tinjiData\", Math.max(0, value))\n Hooks.callAll(\"cde:tinjiUpdated\", Math.max(0, value))\n}\n\n/**\n * After a WuXing roll, add the loksyu faces (yin + yang) of the relevant\n * aspect to the loksyu settings data.\n *\n * @param {string} activeAspect - e.g. \"fire\"\n * @param {Object} faces - Die face counts { 0: n, 1: n, \u2026, 9: n }\n */\nexport async function updateLoksyuFromRoll(activeAspect, faces) {\n const cycle = WU_XING_CYCLE[activeAspect]\n if (!cycle) return\n\n const lokAspect = cycle[3]\n const [yinFace, yangFace] = ASPECT_FACES[lokAspect] ?? []\n if (yinFace === undefined) return\n\n const yinCount = faces[yinFace] ?? 0\n const yangCount = faces[yangFace] ?? 0\n if (yinCount === 0 && yangCount === 0) return\n\n const data = getLoksyuData()\n const current = data[lokAspect] ?? { yin: 0, yang: 0 }\n data[lokAspect] = {\n yin: (current.yin ?? 0) + yinCount,\n yang: (current.yang ?? 0) + yangCount,\n }\n await setLoksyuData(data)\n}\n\n/**\n * After a WuXing roll, add tinji faces to the TinJi settings.\n *\n * @param {number} count - Number of tinji faces rolled\n */\nexport async function updateTinjiFromRoll(count) {\n if (!count || count <= 0) return\n const current = getTinjiValue()\n await setTinjiValue(current + count)\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\n/**\n * Wu Xing rolling system for Chroniques de l'\u00C9trange.\n *\n * The Wu Xing cycle maps each aspect (by index 0-4) to die face groups:\n * - metal=0 : faces 3,8\n * - water=1 : faces 1,6\n * - earth=2 : faces 0/10,5\n * - fire=3 : faces 2,7\n * - wood=4 : faces 4,9\n *\n * For a given active aspect the five result categories are:\n * successes / auspicious / noxious / loksyu (yin face, yang face) / tinji\n * Each category is associated with one of the five aspects in Wu Xing cycle order.\n */\n\nimport { MAGICS, ASPECT_LABELS, ASPECT_ICONS, ASPECT_FACES, ASPECT_NAMES, WU_XING_CYCLE } from \"../config/constants.js\"\nimport { updateLoksyuFromRoll, updateTinjiFromRoll } from \"./apps/singletons.js\"\n\nconst RESULT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-dice-result.html\"\nconst SKILL_PROMPT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-skill-dice-prompt.html\"\nconst SKILL_SPECIAL_PROMPT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-skill-special-dice-prompt.html\"\nconst MAGIC_PROMPT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-magic-dice-prompt.html\"\nconst WEAPON_PROMPT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-weapon-dice-prompt.html\"\n\n/** Maps i18n element label \u2192 aspect name (for speciality default aspect lookup) */\nconst LABELELEMENT_TO_ASPECT = {\n \"CDE.Metal\": \"metal\",\n \"CDE.Water\": \"water\",\n \"CDE.Earth\": \"earth\",\n \"CDE.Fire\": \"fire\",\n \"CDE.Wood\": \"wood\",\n}\n\n/** Maps weapon range string \u2192 dice malus applied to the attack pool */\nconst RANGE_MALUS = {\n contact: 0,\n courte: 0,\n mediane: -1,\n longue: -2,\n extreme: -3,\n}\n\n/** Maps weapon type string \u2192 default skill key */\nconst WEAPON_TYPE_SKILL = {\n melee: \"kungfu\",\n thrown: \"rangedcombat\",\n ranged: \"rangedcombat\",\n firearm: \"rangedcombat\",\n}\n\n/** Maps weapon damageAspect name \u2192 ASPECT_NAMES index */\nconst WEAPON_ASPECT_INDEX = { metal: 0, eau: 1, water: 1, terre: 2, earth: 2, feu: 3, fire: 3, bois: 4, wood: 4 }\n\n/** Count how many times each die face appeared in the roll results */\nfunction countFaces(rollResults) {\n const counts = { 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 0:0 }\n for (const die of rollResults) {\n const face = die.result === 10 ? 0 : die.result\n counts[face]++\n }\n return counts\n}\n\n/**\n * Compute Wu Xing result categories from face counts and active aspect.\n * Returns { successesdice, auspiciousdice, noxiousdice, loksyudice, tinjidice, loksyurepartition }\n */\nfunction computeWuXingResults(faces, aspectName, bonusAuspicious = 0) {\n const cycle = WU_XING_CYCLE[aspectName]\n if (!cycle) return null\n\n const [succAspect, ausAspect, noxAspect, lokAspect, tinAspect] = cycle\n const [succYin, succYang] = ASPECT_FACES[succAspect]\n const [ausYin, ausYang] = ASPECT_FACES[ausAspect]\n const [noxYin, noxYang] = ASPECT_FACES[noxAspect]\n const [lokYin, lokYang] = ASPECT_FACES[lokAspect]\n const [tinYin, tinYang] = ASPECT_FACES[tinAspect]\n\n const yin = game.i18n.localize(\"CDE.Yin\")\n const yang = game.i18n.localize(\"CDE.Yang\")\n\n return {\n successesdice: faces[succYin] + faces[succYang],\n auspiciousdice: faces[ausYin] + faces[ausYang] + bonusAuspicious,\n noxiousdice: faces[noxYin] + faces[noxYang],\n loksyudice: faces[lokYin] + faces[lokYang],\n loksyurepartition: `[${yin}(${faces[lokYin]}) ${yang}(${faces[lokYang]})]`,\n tinjidice: faces[tinYin] + faces[tinYang],\n }\n}\n\n/** Read a named field from a dialog DOM element */\nfunction readField(dlg, name) {\n const el = dlg.querySelector(`[name=\"${name}\"]`)\n if (!el) return null\n return el.type === \"checkbox\" ? el.checked : el.value\n}\n\n/**\n * Open a DialogV2.prompt with the given template + data and return the resolved form values.\n * The callback receives the DialogV2 application instance; fields are read from its .element.\n * @returns {Promise|null>}\n */\nasync function showRollPrompt({ title, template, data, fields }) {\n const content = await foundry.applications.handlebars.renderTemplate(template, data)\n return foundry.applications.api.DialogV2.prompt({\n window: { title },\n content,\n rejectClose: false,\n ok: {\n label: game.i18n.localize(\"CDE.Validate\"),\n callback: (event, button, dialog) => {\n // In AppV2, dialog is the application instance; .element is the root HTMLElement\n const root = dialog.element ?? dialog\n const result = {}\n for (const field of fields) {\n result[field] = readField(root, field)\n }\n return result\n },\n },\n })\n}\n\n/**\n * Open the skill roll prompt and return the user-confirmed parameters.\n * @param {object} params - Initial values\n * @returns {Promise}\n */\nasync function showSkillPrompt(params) {\n return showRollPrompt({\n title: params.title,\n template: params.isSpecial ? SKILL_SPECIAL_PROMPT_TEMPLATE : SKILL_PROMPT_TEMPLATE,\n data: {\n numberofdice: params.numberofdice,\n aspect: Number(params.aspect ?? 0),\n bonusmalus: params.bonusmalus ?? 0,\n woundmalus: params.woundmalus ?? 0,\n bonusauspiciousdice: params.bonusauspiciousdice ?? 0,\n typeofthrow: Number(params.typeofthrow ?? 0),\n },\n fields: [\"aspect\", \"bonusmalus\", \"woundmalus\", \"bonusauspiciousdice\", \"typeofthrow\"],\n })\n}\n\n/**\n * Open the magic roll prompt and return the user-confirmed parameters.\n */\nasync function showMagicPrompt(params) {\n return showRollPrompt({\n title: params.title,\n template: MAGIC_PROMPT_TEMPLATE,\n data: {\n numberofdice: params.numberofdice ?? 0,\n aspectskill: Number(params.aspectskill ?? 0),\n bonusmalusskill: params.bonusmalusskill ?? 0,\n bonusauspiciousdice: params.bonusauspiciousdice ?? 0,\n rolldifficulty: params.rolldifficulty ?? 1,\n freepowerlevels: params.freepowerlevels ?? 0,\n typeofthrow: Number(params.typeofthrow ?? 0),\n },\n fields: [\"aspectskill\", \"bonusmalusskill\", \"bonusauspiciousdice\",\n \"rolldifficulty\", \"freepowerlevels\", \"typeofthrow\"],\n })\n}\n\n/**\n * Open the weapon attack roll prompt and return user-confirmed parameters.\n */\nasync function showWeaponPrompt(params) {\n return showRollPrompt({\n title: params.title,\n template: WEAPON_PROMPT_TEMPLATE,\n data: {\n numberofdice: params.numberofdice ?? 0,\n weaponName: params.weaponName ?? \"\",\n weaponTypeLabel: params.weaponTypeLabel ?? \"CDE.Weapon\",\n weaponAspectIcon: params.weaponAspectIcon ?? \"\",\n weaponAspectLabel: params.weaponAspectLabel ?? \"\",\n damageBase: params.damageBase ?? 0,\n weaponskill: params.weaponskill ?? \"kungfu\",\n aspect: Number(params.aspect ?? 0),\n effectiverange: params.effectiverange ?? \"contact\",\n bonusmalus: params.bonusmalus ?? 0,\n woundmalus: params.woundmalus ?? 0,\n bonusauspiciousdice: params.bonusauspiciousdice ?? 0,\n typeofthrow: Number(params.typeofthrow ?? 0),\n },\n fields: [\"weaponskill\", \"aspect\", \"effectiverange\", \"bonusmalus\", \"woundmalus\",\n \"bonusauspiciousdice\", \"typeofthrow\"],\n })\n}\n\n/**\n * Build and send a single enriched ChatMessage containing both the roll\n * (for Dice So Nice) and the Wu Xing result card.\n */\nasync function sendResultMessage(actor, resultData, roll, rollMode) {\n const html = await foundry.applications.handlebars.renderTemplate(RESULT_TEMPLATE, resultData)\n return ChatMessage.create({\n user: game.user.id,\n speaker: ChatMessage.getSpeaker({ actor }),\n content: html,\n rolls: [roll],\n rollMode,\n flags: {\n \"fvtt-chroniques-de-l-etrange\": { rollResult: { ...resultData } },\n },\n })\n}\n\nconst ROLL_MODES = [\"roll\", \"gmroll\", \"blindroll\", \"selfroll\"]\n\n/**\n * Main entry point: roll dice for a given actor.\n *\n * @param {Actor} actor\n * @param {string} rollKey - e.g. \"prowess-skill\", \"fire-aspect\", \"alchemy-magic-elixirs\"\n */\nexport async function rollForActor(actor, rollKey) {\n const parts = rollKey.split(\"-\")\n const skillLibel = parts[0]\n const typeLibel = parts[1]\n const specialLibel = parts[2] ?? null\n\n const sys = actor.system\n const typeOfThrow = Number(sys.prefs?.typeofthrow?.choice ?? 0)\n\n let numberofdice = 0\n let title = \"\"\n let isSpecial = false\n let isMagic = false\n let isMagicSpecial = false\n let kfDefaultAspect = -1 // set in \"itemkungfu\" case, used when computing defaultAspect\n\n // ---- Determine dice count + title ----\n const MAGIC_I18N_KEYS = {\n internalcinnabar: \"CDE.InternalCinnabar\",\n alchemy: \"CDE.Alchemy\",\n masteryoftheway: \"CDE.MasteryOfTheWay\",\n exorcism: \"CDE.Exorcism\",\n geomancy: \"CDE.Geomancy\",\n }\n\n switch (typeLibel) {\n case \"aspect\":\n numberofdice = sys.aspect[skillLibel]?.value ?? 0\n title = game.i18n.localize(sys.aspect[skillLibel]?.label ?? \"CDE.Roll\")\n break\n case \"aptitude\":\n // NPC aptitude roll \u2014 flat pool with WuXing prompt\n numberofdice = sys.aptitudes?.[skillLibel]?.value ?? 0\n title = game.i18n.localize(`CDE.${skillLibel.charAt(0).toUpperCase() + skillLibel.slice(1)}`)\n break\n case \"skill\":\n numberofdice = sys.skills?.[skillLibel]?.value ?? 0\n title = game.i18n.localize(sys.skills?.[skillLibel]?.label ?? \"CDE.Roll\")\n break\n case \"special\":\n numberofdice = sys.skills?.[skillLibel]?.value ?? 0\n title = game.i18n.localize(sys.skills?.[skillLibel]?.label ?? \"CDE.Roll\")\n title += ` [${game.i18n.localize(\"CDE.Speciality\")}]`\n isSpecial = true\n if (!sys.skills?.[skillLibel]?.specialities) {\n ui.notifications.warn(game.i18n.localize(\"CDE.Error2\"))\n return\n }\n break\n case \"resource\":\n numberofdice = sys.resources?.[skillLibel]?.value ?? 0\n title = game.i18n.localize(sys.resources?.[skillLibel]?.label ?? \"CDE.Roll\")\n break\n case \"field\":\n numberofdice = sys.resources?.[skillLibel]?.value ?? 0\n title = game.i18n.localize(sys.resources?.[skillLibel]?.label ?? \"CDE.Roll\")\n title += ` [${game.i18n.localize(\"CDE.Field\")}]`\n isSpecial = true\n if (!sys.resources?.[skillLibel]?.specialities) {\n ui.notifications.warn(game.i18n.localize(\"CDE.Error4\"))\n return\n }\n break\n case \"magic\":\n numberofdice = sys.magics?.[skillLibel]?.value ?? 0\n isMagic = true\n title = game.i18n.localize(MAGIC_I18N_KEYS[skillLibel] ?? \"CDE.Magics\")\n break\n case \"magicspecial\":\n numberofdice = sys.magics?.[skillLibel]?.value ?? 0\n isMagicSpecial = true\n isMagic = true\n if (!sys.magics?.[skillLibel]?.speciality?.[specialLibel]?.check) {\n ui.notifications.warn(game.i18n.localize(\"CDE.Error6\"))\n return\n }\n title = `${game.i18n.localize(MAGIC_I18N_KEYS[skillLibel] ?? \"CDE.Magics\")} [${game.i18n.localize(MAGICS?.[skillLibel]?.speciality?.[specialLibel]?.label ?? \"\")}]`\n break\n case \"itemkungfu\": {\n // skillLibel = item._id \u2014 look up the kungfu item to find which skill + aspect to use\n const kfItem = actor.items.get(skillLibel)\n if (!kfItem) { ui.notifications.warn(game.i18n.localize(\"CDE.Error0\")); return }\n const kfSkill = kfItem.system.skill ?? \"kungfu\"\n numberofdice = sys.skills?.[kfSkill]?.value ?? 0\n title = `${kfItem.name} [${game.i18n.localize(sys.skills?.[kfSkill]?.label ?? \"CDE.KungFu\")}]`\n const kfAspect = kfItem.system.aspect?.toLowerCase() ?? \"metal\"\n const ASPECT_NORMALIZE = { eau: \"water\", terre: \"earth\", feu: \"fire\", bois: \"wood\" }\n kfDefaultAspect = ASPECT_NAMES.indexOf(ASPECT_NORMALIZE[kfAspect] ?? kfAspect)\n if (kfDefaultAspect < 0) kfDefaultAspect = 0\n break\n }\n case \"itemweapon\": {\n // skillLibel = item._id \u2014 look up the weapon item to find type + aspect + damage\n const wpItem = actor.items.get(skillLibel)\n if (!wpItem) { ui.notifications.warn(game.i18n.localize(\"CDE.Error0\")); return }\n\n const wpType = wpItem.system.weaponType ?? \"melee\"\n const wpSkill = WEAPON_TYPE_SKILL[wpType] ?? \"kungfu\"\n numberofdice = sys.skills?.[wpSkill]?.value ?? 0\n\n const wpAspectRaw = wpItem.system.damageAspect ?? \"metal\"\n const wpAspectIdx = WEAPON_ASPECT_INDEX[wpAspectRaw] ?? 0\n const wpRange = wpItem.system.range ?? \"contact\"\n\n const WEAPON_TYPE_LABELS = {\n melee: \"CDE.WeaponMelee\",\n thrown: \"CDE.WeaponThrown\",\n ranged: \"CDE.WeaponRanged\",\n firearm: \"CDE.WeaponFirearm\",\n }\n\n // Show weapon-specific prompt\n const wParams = await showWeaponPrompt({\n title: `${wpItem.name} [${game.i18n.localize(sys.skills?.[wpSkill]?.label ?? \"CDE.WeaponRoll\")}]`,\n numberofdice,\n weaponName: wpItem.name,\n weaponTypeLabel: WEAPON_TYPE_LABELS[wpType] ?? \"CDE.Weapon\",\n weaponAspectIcon: ASPECT_ICONS[ASPECT_NAMES[wpAspectIdx]] ?? \"\",\n weaponAspectLabel: game.i18n.localize(ASPECT_LABELS[ASPECT_NAMES[wpAspectIdx]] ?? \"\"),\n damageBase: wpItem.system.damageBase ?? 0,\n weaponskill: wpSkill,\n aspect: wpAspectIdx,\n effectiverange: wpRange,\n bonusmalus: 0,\n woundmalus: 0,\n bonusauspiciousdice: 0,\n typeofthrow: typeOfThrow,\n })\n\n if (!wParams) return // cancelled\n\n // Resolve final pool from weapon prompt values\n const wpChosenSkill = wParams.weaponskill ?? wpSkill\n const wpSkillDice = sys.skills?.[wpChosenSkill]?.value ?? 0\n const wpAspFinal = Number(wParams.aspect ?? wpAspectIdx)\n const wpAspectDice = sys.aspect[ASPECT_NAMES[wpAspFinal]]?.value ?? 0\n const wpRangeMalus = RANGE_MALUS[wParams.effectiverange ?? \"contact\"] ?? 0\n const wpBonusMalus = Number(wParams.bonusmalus ?? 0)\n const wpWoundMalus = Number(wParams.woundmalus ?? 0)\n const wpBonusAusp = Number(wParams.bonusauspiciousdice ?? 0)\n const wpThrowMode = Number(wParams.typeofthrow ?? 0)\n const wpDamageBase = wpItem.system.damageBase ?? 0\n\n const wpSpecialtyBonus = wpItem.system.hasSpeciality ? 1 : 0\n\n const wpTotalDice = wpSkillDice + wpAspectDice + wpRangeMalus + wpBonusMalus - wpWoundMalus + wpSpecialtyBonus\n if (wpTotalDice <= 0) {\n ui.notifications.warn(game.i18n.localize(\"CDE.Error0\"))\n return\n }\n\n const wpRoll = new Roll(`${wpTotalDice}d10`)\n await wpRoll.evaluate()\n\n const wpAspectName = ASPECT_NAMES[wpAspFinal] ?? \"metal\"\n const wpFaces = countFaces(wpRoll.dice[0]?.results ?? [])\n const wpResults = computeWuXingResults(wpFaces, wpAspectName, wpBonusAusp)\n if (!wpResults) return\n\n const wpModParts = []\n if (wpRangeMalus !== 0) wpModParts.push(`${wpRangeMalus} ${game.i18n.localize(\"CDE.RangePenalty\")}`)\n if (wpBonusMalus !== 0) wpModParts.push(`${wpBonusMalus > 0 ? \"+\" : \"\"}${wpBonusMalus} ${game.i18n.localize(\"CDE.BonusMalus\")}`)\n if (wpWoundMalus !== 0) wpModParts.push(`-${wpWoundMalus} ${game.i18n.localize(\"CDE.WoundMalus\")}`)\n if (wpBonusAusp !== 0) wpModParts.push(`+${wpBonusAusp} ${game.i18n.localize(\"CDE.BonusAuspiciousDice\")}`)\n\n // Damage = character's aspect value (from weapon's damageAspect) + weapon base damage\n const wpDamageAspectRaw = wpItem.system.damageAspect ?? \"metal\"\n const wpDamageAspectIdx = WEAPON_ASPECT_INDEX[wpDamageAspectRaw] ?? 0\n const wpDamageAspectName = ASPECT_NAMES[wpDamageAspectIdx]\n const wpDamageAspectValue = sys.aspect?.[wpDamageAspectName]?.value ?? 0\n const wpDamageAspectLabel = game.i18n.localize(ASPECT_LABELS[wpDamageAspectName] ?? \"\")\n\n const wpMsg = await sendResultMessage(actor, {\n rollLabel: `${wpItem.name}`,\n aspectName: wpAspectName,\n aspectLabel: game.i18n.localize(ASPECT_LABELS[wpAspectName] ?? \"\"),\n aspectIcon: ASPECT_ICONS[wpAspectName] ?? \"\",\n totalDice: wpTotalDice,\n modifiersText: wpModParts.length ? wpModParts.join(\" \u00B7 \") : \"\",\n spellPower: null,\n rollDifficulty: null,\n actorName: actor.name ?? \"\",\n actorImg: actor.img ?? \"\",\n // weapon-specific\n weaponName: wpItem.name,\n damageBase: wpDamageBase,\n damageAspectValue: wpDamageAspectValue,\n damageAspectLabel: wpDamageAspectLabel,\n totalDamage: wpDamageBase + wpDamageAspectValue,\n ...wpResults,\n aspect: wpAspectName,\n d1: wpFaces[1], d2: wpFaces[2], d3: wpFaces[3], d4: wpFaces[4], d5: wpFaces[5],\n d6: wpFaces[6], d7: wpFaces[7], d8: wpFaces[8], d9: wpFaces[9], d0: wpFaces[0],\n }, wpRoll, ROLL_MODES[wpThrowMode] ?? \"roll\")\n\n if (game.modules.get(\"dice-so-nice\")?.active && wpMsg?.id) {\n try { await game.dice3d.waitFor3DAnimationByMessageID(wpMsg.id) } catch (_e) { /* DSN not available */ }\n }\n // Auto-update Loksyu/TinJi singletons from weapon roll faces\n if ((wpResults.loksyudice ?? 0) > 0) await updateLoksyuFromRoll(wpAspectName, wpFaces)\n if ((wpResults.tinjidice ?? 0) > 0) await updateTinjiFromRoll(wpResults.tinjidice)\n return\n }\n default:\n ui.notifications.warn(`Unknown roll type: ${typeLibel}`)\n return\n }\n\n // For magic rolls / itemkungfu, allow 0 base dice (user can add bonus dice in the prompt).\n if (numberofdice <= 0 && typeLibel !== \"aspect\" && typeLibel !== \"itemkungfu\" && !isMagic) {\n ui.notifications.warn(game.i18n.localize(\"CDE.Error0\"))\n return\n }\n\n // ---- Pre-compute default aspect for magic based on skill ----\n const MAGIC_ASPECTS = {\n internalcinnabar: 0, // metal\n alchemy: 1, // water\n masteryoftheway: 2, // earth\n exorcism: 3, // fire\n geomancy: 4, // wood\n }\n\n let defaultAspect = typeLibel === \"aspect\"\n ? [\"metal\",\"water\",\"earth\",\"fire\",\"wood\"].indexOf(skillLibel)\n : 0\n if (isMagic && MAGIC_ASPECTS[skillLibel] !== undefined) {\n defaultAspect = MAGIC_ASPECTS[skillLibel]\n }\n if (kfDefaultAspect >= 0) {\n defaultAspect = kfDefaultAspect\n }\n\n // ---- Show roll prompt ----\n let params\n\n if (isMagic) {\n params = await showMagicPrompt({\n title,\n numberofdice,\n aspectskill: defaultAspect,\n bonusmalusskill: 0,\n bonusauspiciousdice: 0,\n rolldifficulty: 1,\n freepowerlevels: 0,\n typeofthrow: typeOfThrow,\n })\n } else {\n params = await showSkillPrompt({\n title,\n numberofdice,\n aspect: defaultAspect,\n bonusmalus: 0,\n woundmalus: 0,\n bonusauspiciousdice: 0,\n typeofthrow: typeOfThrow,\n isSpecial,\n })\n }\n\n if (!params) return // cancelled\n\n // ---- Compute total dice and roll ----\n let aspectIndex, bonusMalus, bonusAuspicious, throwMode\n let rollDifficulty = 1 // magic only: multiplier applied to successes\n\n if (isMagic) {\n const skillAspectIndex = Number(params.aspectskill ?? 0)\n aspectIndex = skillAspectIndex // used for both dice pool and Wu Xing cycle\n bonusMalus = Number(params.bonusmalusskill ?? 0)\n bonusAuspicious = Number(params.bonusauspiciousdice ?? 0)\n rollDifficulty = Math.max(1, Number(params.rolldifficulty ?? 1))\n throwMode = Number(params.typeofthrow ?? 0)\n // magic: magic skill + aspect + bonuses + 1 (speciality base) + HEI spent\n const aspectDice = sys.aspect?.[ASPECT_NAMES[aspectIndex]]?.value ?? 0\n numberofdice = numberofdice + aspectDice + bonusMalus + 1\n } else {\n aspectIndex = Number(params.aspect ?? 0)\n bonusMalus = Number(params.bonusmalus ?? 0)\n const woundMalus = Number(params.woundmalus ?? 0)\n bonusAuspicious = Number(params.bonusauspiciousdice ?? 0)\n throwMode = Number(params.typeofthrow ?? 0)\n\n const aspectDice = (typeLibel !== \"aspect\")\n ? (sys.aspect?.[ASPECT_NAMES[aspectIndex]]?.value ?? 0)\n : 0\n\n numberofdice = numberofdice + aspectDice + bonusMalus - woundMalus\n if (isSpecial) numberofdice += 1 // +1d for speciality\n }\n\n if (numberofdice <= 0) {\n ui.notifications.warn(game.i18n.localize(\"CDE.Error0\"))\n return\n }\n\n // ---- Roll ----\n const roll = new Roll(`${numberofdice}d10`)\n await roll.evaluate()\n\n const rollModeKey = ROLL_MODES[throwMode] ?? \"roll\"\n\n // ---- Compute spell power (magic only) ----\n // Power = rollDifficulty \u00D7 character aspect value for the speciality's\n // associated element (or the school's aspect for base magic rolls).\n let spellPower = null\n let spellPowerAspectName = null\n let spellPowerAspectValue = null\n if (isMagic) {\n if (isMagicSpecial && specialLibel) {\n const specialCfg = MAGICS?.[skillLibel]?.speciality?.[specialLibel]\n const elemName = LABELELEMENT_TO_ASPECT[specialCfg?.labelelement]\n if (elemName) spellPowerAspectName = elemName\n }\n if (!spellPowerAspectName) spellPowerAspectName = ASPECT_NAMES[aspectIndex]\n spellPowerAspectValue = sys.aspect?.[spellPowerAspectName]?.value ?? 0\n const freePowerLevels = Number(params.freepowerlevels ?? 0)\n spellPower = rollDifficulty * (spellPowerAspectValue + freePowerLevels)\n }\n\n // ---- Compute Wu Xing results ----\n // The Wu Xing cycle always uses the roll's aspect (skill aspect for magic,\n // skill/resource aspect otherwise) to determine which faces count as\n // successes/auspicious/etc.\n const wuXingAspectName = ASPECT_NAMES[aspectIndex]\n const allResults = roll.dice[0]?.results ?? []\n const faces = countFaces(allResults)\n const results = computeWuXingResults(faces, wuXingAspectName, bonusAuspicious)\n if (!results) return\n\n // ---- Build modifier summary text ----\n const modParts = []\n if (isMagic) {\n const bm = Number(params.bonusmalusskill ?? 0)\n const ba = Number(params.bonusauspiciousdice ?? 0)\n const fp = Number(params.freepowerlevels ?? 0)\n if (bm !== 0) modParts.push(`${bm > 0 ? \"+\" : \"\"}${bm} ${game.i18n.localize(\"CDE.BonusMalus\")}`)\n if (ba !== 0) modParts.push(`+${ba} ${game.i18n.localize(\"CDE.BonusAuspiciousDice\")}`)\n if (fp !== 0) modParts.push(`+${fp} ${game.i18n.localize(\"CDE.FreePowerLevels\")}`)\n if (rollDifficulty !== 1) modParts.push(`\u00D7${rollDifficulty} ${game.i18n.localize(\"CDE.RollDifficulty\")}`)\n } else {\n const bm = Number(params.bonusmalus ?? 0)\n const wm = Number(params.woundmalus ?? 0)\n const ba = Number(params.bonusauspiciousdice ?? 0)\n if (bm !== 0) modParts.push(`${bm > 0 ? \"+\" : \"\"}${bm} ${game.i18n.localize(\"CDE.BonusMalus\")}`)\n if (wm !== 0) modParts.push(`-${wm} ${game.i18n.localize(\"CDE.WoundMalus\")}`)\n if (ba !== 0) modParts.push(`+${ba} ${game.i18n.localize(\"CDE.BonusAuspiciousDice\")}`)\n }\n\n // ---- Send single enriched ChatMessage (roll + result card) ----\n const msg = await sendResultMessage(actor, {\n // Roll identity\n rollLabel: title,\n aspectName: wuXingAspectName,\n aspectLabel: game.i18n.localize(ASPECT_LABELS[wuXingAspectName] ?? \"\"),\n aspectIcon: ASPECT_ICONS[wuXingAspectName] ?? \"\",\n totalDice: numberofdice,\n modifiersText: modParts.length ? modParts.join(\" \u00B7 \") : \"\",\n // Spell power (magic only)\n spellPower,\n spellPowerAspectLabel: spellPowerAspectName ? game.i18n.localize(ASPECT_LABELS[spellPowerAspectName] ?? \"\") : \"\",\n spellPowerAspectValue,\n spellPowerFreeLevels: isMagic ? Number(params.freepowerlevels ?? 0) : 0,\n rollDifficulty: isMagic ? rollDifficulty : null,\n // Actor info\n actorName: actor.name ?? \"\",\n actorImg: actor.img ?? \"\",\n // Wu Xing results\n aspect: wuXingAspectName,\n ...results,\n // Die face counts\n d1: faces[1], d2: faces[2], d3: faces[3], d4: faces[4], d5: faces[5],\n d6: faces[6], d7: faces[7], d8: faces[8], d9: faces[9], d0: faces[0],\n }, roll, rollModeKey)\n\n // ---- Wait for Dice So Nice animation ----\n if (game.modules.get(\"dice-so-nice\")?.active && msg?.id) {\n try { await game.dice3d.waitFor3DAnimationByMessageID(msg.id) } catch (_e) { /* DSN not available */ }\n }\n\n // ---- Auto-update Loksyu / TinJi singletons ----\n if ((results.loksyudice ?? 0) > 0) await updateLoksyuFromRoll(wuXingAspectName, faces)\n if ((results.tinjidice ?? 0) > 0) await updateTinjiFromRoll(results.tinjidice)\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nconst { HandlebarsApplicationMixin } = foundry.applications.api\n\nexport class CDEBaseActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {\n static DEFAULT_OPTIONS = {\n classes: [\"fvtt-chroniques-de-l-etrange\", \"actor\"],\n position: { width: 920, height: 800 },\n window: { resizable: true },\n form: { submitOnChange: true },\n dragDrop: [{ dragSelector: \".item, [data-drag='true']\", dropSelector: null }],\n actions: {\n create: CDEBaseActorSheet.#onItemCreate,\n edit: CDEBaseActorSheet.#onItemEdit,\n delete: CDEBaseActorSheet.#onItemDelete,\n editImage: CDEBaseActorSheet.#onEditImage,\n },\n }\n\n tabGroups = { primary: \"description\" }\n\n get title() {\n return this.document.name\n }\n\n async _prepareContext() {\n const descriptionHTML = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description ?? \"\", { async: true })\n const cssClass = this.options.classes?.join(\" \") ?? \"\"\n return {\n actor: this.document,\n system: this.document.system,\n systemData: this.document.system,\n systemFields: this.document.system.schema.fields,\n items: this.document.items.contents,\n descriptionHTML,\n editable: this.isEditable,\n cssClass,\n }\n }\n\n // Restore the active tab after every render (including re-renders from submitOnChange).\n // AppV2 does NOT preserve tab state natively \u2014 we must re-apply it from this.tabGroups,\n // which is dynamically updated by changeTab() when the user clicks a tab.\n _onRender(context, options) {\n super._onRender?.(context, options)\n for (const [group, tab] of Object.entries(this.tabGroups)) {\n this.changeTab(tab, group, { force: true })\n }\n }\n\n static async #onItemCreate(event, target) {\n const type = target.dataset.type ?? \"item\"\n const cls = getDocumentClass(\"Item\")\n const labels = {\n item: \"CDE.ItemNew\",\n weapon: \"CDE.WeaponNew\",\n armor: \"CDE.ArmorNew\",\n sanhei: \"CDE.SanheiNew\",\n ingredient: \"CDE.IngredientNew\",\n kungfu: \"CDE.KFNew\",\n spell: \"CDE.SpellNew\",\n supernatural: \"CDE.SupernaturalNew\",\n }\n const name = game.i18n.localize(labels[type] ?? \"CDE.ItemNew\")\n const systemData = {}\n if (type === \"spell\" && target.dataset.discipline) {\n systemData.discipline = target.dataset.discipline\n }\n return cls.create({ name, type, system: systemData }, { parent: this.document })\n }\n\n static #onItemEdit(event, target) {\n const itemId = target.dataset.itemId ?? target.closest(\"[data-item-id]\")?.dataset.itemId\n const item = this.document.items.get(itemId)\n if (item) item.sheet.render(true)\n }\n\n static #onItemDelete(event, target) {\n const itemId = target.dataset.itemId ?? target.closest(\"[data-item-id]\")?.dataset.itemId\n const item = this.document.items.get(itemId)\n if (item) item.delete()\n }\n\n static async #onEditImage(event, target) {\n const attr = target.dataset.edit\n const current = foundry.utils.getProperty(this.document, attr)\n const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}\n const fp = new FilePicker({\n current,\n type: \"image\",\n redirectToRoot: img ? [img] : [],\n callback: (path) => this.document.update({ [attr]: path }),\n top: this.position.top + 40,\n left: this.position.left + 10,\n })\n return fp.browse()\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { MAGICS, SUBTYPES } from \"../../../config/constants.js\"\nimport { rollInitiativePC } from \"../../initiative.js\"\nimport { rollForActor } from \"../../rolling.js\"\nimport { CDEBaseActorSheet } from \"./base.js\"\n\nexport class CDECharacterSheet extends CDEBaseActorSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"character\"],\n actions: {\n moveMagicUp: CDECharacterSheet.#onMoveMagicUp,\n moveMagicDown: CDECharacterSheet.#onMoveMagicDown,\n },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/actor/cde-character-sheet.html\" },\n }\n\n tabGroups = { primary: \"description\" }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n context.equipments = context.items.filter((item) => item.type === \"item\")\n context.weapons = context.items.filter((item) => item.type === \"weapon\")\n context.armors = context.items.filter((item) => item.type === \"armor\")\n context.sanheis = context.items.filter((item) => item.type === \"sanhei\")\n context.ingredients = context.items.filter((item) => item.type === \"ingredient\")\n context.spells = context.items.filter((item) => item.type === \"spell\")\n context.kungfus = context.items.filter((item) => item.type === \"kungfu\")\n context.CDE = { MAGICS, SUBTYPES }\n\n // Group spells by discipline key (matches MAGICS keys)\n const spellsByDiscipline = {}\n for (const spell of context.spells) {\n const disc = spell.system?.discipline ?? \"internalcinnabar\"\n if (!spellsByDiscipline[disc]) spellsByDiscipline[disc] = []\n spellsByDiscipline[disc].push(spell)\n }\n\n // Build magicsDisplay: only include the 5 relevant specialities per magic type + grimoire\n const systemMagics = context.systemData.magics ?? {}\n const magicEntries = Object.entries(MAGICS).map(([magicKey, magicDef]) => {\n const magicData = systemMagics[magicKey] ?? {}\n return [\n magicKey,\n {\n value: magicData.value ?? 0,\n visible: magicData.visible ?? false,\n speciality: Object.fromEntries(\n Object.keys(magicDef.speciality).map((specKey) => [\n specKey,\n { check: magicData.speciality?.[specKey]?.check ?? false },\n ])\n ),\n grimoire: spellsByDiscipline[magicKey] ?? [],\n },\n ]\n })\n const order = context.systemData.magicOrder ?? []\n if (order.length > 0) {\n magicEntries.sort((a, b) => {\n const ia = order.indexOf(a[0])\n const ib = order.indexOf(b[0])\n if (ia === -1 && ib === -1) return 0\n if (ia === -1) return 1\n if (ib === -1) return -1\n return ia - ib\n })\n }\n context.magicsDisplay = Object.fromEntries(magicEntries)\n\n return context\n }\n\n _onRender(context, options) {\n super._onRender(context, options)\n this.#bindInitiativeControls()\n this.#bindPrefs()\n this.#bindRollButtons()\n this.#bindComponentRandomize()\n this.#bindDiagramZoom()\n }\n\n #bindInitiativeControls() {\n const buttons = this.element?.querySelectorAll(\".click-initiative\")\n if (!buttons?.length) return\n buttons.forEach((button) => {\n button.addEventListener(\"click\", async () => {\n const action = button.dataset.libelId\n let initiative = this.document.system.initiative ?? 1\n if (action === \"plus\") {\n initiative = initiative >= 24 ? 1 : initiative + 1\n await this.document.update({ \"system.initiative\": initiative })\n return\n }\n if (action === \"minus\") {\n initiative = initiative <= 1 ? 24 : initiative - 1\n await this.document.update({ \"system.initiative\": initiative })\n return\n }\n if (action === \"create\") {\n await rollInitiativePC(this.document)\n }\n })\n })\n }\n\n #bindPrefs() {\n const button = this.element?.querySelector(\".click-prefs\")\n if (!button) return\n button.addEventListener(\"click\", async () => {\n const current = this.document.system.prefs?.typeofthrow ?? { choice: \"0\", check: true }\n const html = `\n
\n
\n \n \n
\n
\n \n \n
\n
`\n const prefs = await foundry.applications.api.DialogV2.prompt({\n window: { title: game.i18n.localize(\"CDE.Preferences\") },\n content: html,\n rejectClose: false,\n ok: {\n label: game.i18n.localize(\"CDE.Validate\"),\n callback: (_ev, _btn, dialog) => {\n const root = dialog.element ?? dialog\n const choice = root.querySelector(\"select[name='choice']\")?.value ?? \"0\"\n const check = root.querySelector(\"input[name='check']\")?.checked ?? false\n return { choice, check }\n },\n },\n })\n if (prefs) {\n await this.document.update({\n \"system.prefs.typeofthrow.choice\": String(prefs.choice),\n \"system.prefs.typeofthrow.check\": !!prefs.check,\n })\n }\n })\n }\n\n #bindRollButtons() {\n const cells = this.element?.querySelectorAll(\"td.click[data-libel-id], td.click2[data-libel-id], .cde-roll-trigger[data-libel-id]\")\n if (!cells?.length) return\n cells.forEach((cell) => {\n cell.addEventListener(\"click\", (event) => {\n event.preventDefault()\n const rollKey = cell.dataset.libelId\n if (rollKey) rollForActor(this.document, rollKey)?.catch(err => console.error(\"Roll failed:\", err))\n })\n })\n }\n\n #bindDiagramZoom() {\n const img = this.element?.querySelector(\"[data-action='zoom-diagram']\")\n if (!img) return\n img.addEventListener(\"click\", () => {\n new ImagePopout(img.src, {\n title: game.i18n.localize(\"CDE.NghangDiagramTitle\"),\n shareable: false,\n }).render(true)\n })\n }\n\n static async #onMoveMagicUp(event, target) {\n const key = target.dataset.magicKey\n let order = this.document.system.magicOrder ?? []\n if (!order.length) order = [...Object.keys(MAGICS)]\n else order = [...order]\n const idx = order.indexOf(key)\n if (idx <= 0) return\n [order[idx - 1], order[idx]] = [order[idx], order[idx - 1]]\n await this.document.update({ \"system.magicOrder\": order })\n }\n\n static async #onMoveMagicDown(event, target) {\n const key = target.dataset.magicKey\n let order = this.document.system.magicOrder ?? []\n if (!order.length) order = [...Object.keys(MAGICS)]\n else order = [...order]\n const idx = order.indexOf(key)\n if (idx === -1 || idx >= order.length - 1) return\n [order[idx], order[idx + 1]] = [order[idx + 1], order[idx]]\n await this.document.update({ \"system.magicOrder\": order })\n }\n\n #bindComponentRandomize() {\n const btn = this.element?.querySelector(\"[data-action='randomize-component']\")\n if (!btn) return\n btn.addEventListener(\"click\", async () => {\n const roll = new Roll(\"1d10\")\n await roll.evaluate()\n const face = roll.total === 10 ? 0 : roll.total\n const COMPONENT_KEYS = { 1:\"one\", 2:\"two\", 3:\"three\", 4:\"four\", 5:\"five\",\n 6:\"six\", 7:\"seven\", 8:\"eight\", 9:\"nine\", 0:\"zero\" }\n const componentKey = COMPONENT_KEYS[face]\n const componentValue = this.document.system.component?.[componentKey]?.value ?? \"\"\n const label = componentValue\n ? `${componentValue}`\n : `${game.i18n.localize(\"CDE.Component\")}${face}`\n const content = `\n
\n ${game.i18n.localize(\"CDE.ChanceThrowResult\")}\n ${label}\n
`\n await ChatMessage.create({\n user: game.user.id,\n speaker: ChatMessage.getSpeaker({ actor: this.document }),\n content,\n rolls: [roll],\n rollMode: game.settings.get(\"core\", \"rollMode\") ?? \"roll\",\n })\n })\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { rollInitiativeNPC } from \"../../initiative.js\"\nimport { rollForActor } from \"../../rolling.js\"\nimport { CDEBaseActorSheet } from \"./base.js\"\n\nexport class CDENpcSheet extends CDEBaseActorSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"npc\"],\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/actor/cde-npc-sheet.html\" },\n }\n\n tabGroups = { primary: \"description\" }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n context.supernaturals = context.items.filter((item) => item.type === \"supernatural\")\n context.spells = context.items.filter((item) => item.type === \"spell\")\n context.kungfus = context.items.filter((item) => item.type === \"kungfu\")\n context.weapons = context.items.filter((item) => item.type === \"weapon\")\n context.armors = context.items.filter((item) => item.type === \"armor\")\n context.equipments = context.items.filter((item) => item.type === \"item\")\n return context\n }\n\n _onRender(context, options) {\n super._onRender(context, options)\n this.#bindInitiativeControls()\n this.#bindRollButtons()\n }\n\n #bindRollButtons() {\n const cells = this.element?.querySelectorAll(\".cde-roll-trigger[data-libel-id]\")\n if (!cells?.length) return\n cells.forEach((cell) => {\n cell.addEventListener(\"click\", (event) => {\n event.preventDefault()\n const rollKey = cell.dataset.libelId\n if (rollKey) rollForActor(this.document, rollKey)?.catch(err => console.error(\"Roll failed:\", err))\n })\n })\n }\n\n #bindInitiativeControls() {\n const buttons = this.element?.querySelectorAll(\".click-initiative-npc\")\n if (!buttons?.length) return\n buttons.forEach((button) => {\n button.addEventListener(\"click\", async () => {\n const action = button.dataset.libelId\n let initiative = this.document.system.initiative ?? 1\n if (action === \"plus\") {\n initiative = initiative >= 24 ? 1 : initiative + 1\n await this.document.update({ \"system.initiative\": initiative })\n return\n }\n if (action === \"minus\") {\n initiative = initiative <= 1 ? 24 : initiative - 1\n await this.document.update({ \"system.initiative\": initiative })\n return\n }\n if (action === \"create\") {\n await rollInitiativeNPC(this.document)\n }\n })\n })\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nconst { HandlebarsApplicationMixin } = foundry.applications.api\n\nexport class CDEBaseItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {\n static DEFAULT_OPTIONS = {\n classes: [\"fvtt-chroniques-de-l-etrange\", \"item\"],\n position: { width: 520, height: \"auto\" },\n window: { resizable: true },\n form: { submitOnChange: true },\n actions: {\n editImage: CDEBaseItemSheet.#onEditImage,\n },\n }\n\n tabGroups = { primary: \"details\" }\n\n get title() {\n return this.document.name\n }\n\n async _prepareContext() {\n const cssClass = this.options.classes?.join(\" \") ?? \"\"\n const enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description ?? \"\", { async: true })\n const enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.notes ?? \"\", { async: true })\n return {\n item: this.document,\n system: this.document.system,\n systemData: this.document.system,\n systemFields: this.document.system.schema.fields,\n editable: this.isEditable,\n cssClass,\n enrichedDescription,\n enrichedNotes,\n descriptionHTML: enrichedDescription,\n notesHTML: enrichedNotes,\n }\n }\n\n // Restore the active tab after every render (including re-renders from submitOnChange).\n _onRender(context, options) {\n super._onRender?.(context, options)\n for (const [group, tab] of Object.entries(this.tabGroups)) {\n this.changeTab(tab, group, { force: true })\n }\n }\n\n static async #onEditImage(event, target) {\n const attr = target.dataset.edit\n const current = foundry.utils.getProperty(this.document, attr)\n const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}\n const fp = new FilePicker({\n current,\n type: \"image\",\n redirectToRoot: img ? [img] : [],\n callback: (path) => this.document.update({ [attr]: path }),\n top: this.position.top + 40,\n left: this.position.left + 10,\n })\n return fp.browse()\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDEItemSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"equipment\"],\n position: { width: 560, height: 460 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-item-sheet.html\" },\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDEKungfuSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"kungfu\"],\n position: { width: 720, height: 680 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-kungfu-sheet.html\" },\n }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n const techniques = this.document.system.techniques ?? {}\n const enrich = (value) => foundry.applications.ux.TextEditor.implementation.enrichHTML(value ?? \"\", { async: true })\n context.descriptionTechnique1HTML = await enrich(techniques.technique1?.technique)\n context.descriptionTechnique2HTML = await enrich(techniques.technique2?.technique)\n context.descriptionTechnique3HTML = await enrich(techniques.technique3?.technique)\n return context\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDESpellSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"spell\"],\n position: { width: 660, height: 680 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-spell-sheet.html\" },\n }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n const enrich = (content) => foundry.applications.ux.TextEditor.implementation.enrichHTML(content ?? \"\", { async: true })\n context.spellDescriptionHTML = await enrich(this.document.system.description)\n context.componentsDescriptionHTML = await enrich(this.document.system.components)\n context.effectsDescriptionHTML = await enrich(this.document.system.effects)\n context.examplesDescriptionHTML = await enrich(this.document.system.examples)\n return context\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDESupernaturalSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"supernatural\"],\n position: { width: 560, height: 520 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-supernatural-sheet.html\" },\n }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n const enrich = (content) => foundry.applications.ux.TextEditor.implementation.enrichHTML(content ?? \"\", { async: true })\n context.effectsHTML = await enrich(this.document.system.effects)\n return context\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDEWeaponSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"weapon\"],\n position: { width: 580, height: 520 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-weapon-sheet.html\" },\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDEArmorSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"armor\"],\n position: { width: 520, height: 460 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-armor-sheet.html\" },\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDESanheiSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"sanhei\"],\n position: { width: 580, height: 620 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-sanhei-sheet.html\" },\n }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n const enrich = (content) => foundry.applications.ux.TextEditor.implementation.enrichHTML(content ?? \"\", { async: true })\n const props = this.document.system.properties ?? {}\n context.prop1DescriptionHTML = await enrich(props.prop1?.description)\n context.prop2DescriptionHTML = await enrich(props.prop2?.description)\n context.prop3DescriptionHTML = await enrich(props.prop3?.description)\n context.propFields = this.document.system.schema.fields.properties?.fields\n return context\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDEIngredientSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"ingredient\"],\n position: { width: 520, height: 460 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-ingredient-sheet.html\" },\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { getLoksyuData, setLoksyuData } from \"./singletons.js\"\nimport { SYSTEM_ID } from \"../../config/constants.js\"\n\nexport class CDELoksyuApp extends foundry.applications.api.HandlebarsApplicationMixin(\n foundry.applications.api.ApplicationV2\n) {\n static DEFAULT_OPTIONS = {\n id: \"cde-loksyu-app\",\n tag: \"div\",\n window: {\n title: \"CDE.Loksyu\",\n icon: \"fas fa-yin-yang\",\n resizable: false,\n },\n classes: [\"cde-app\", \"cde-loksyu-standalone\"],\n position: { width: 520, height: \"auto\" },\n actions: {\n resetElement: CDELoksyuApp.#onResetElement,\n resetAll: CDELoksyuApp.#onResetAll,\n zoomVisual: CDELoksyuApp.#onZoomVisual,\n },\n }\n\n static PARTS = {\n main: {\n template: `systems/${SYSTEM_ID}/templates/apps/cde-loksyu-app.html`,\n },\n }\n\n /** @type {Function|null} bound hook handler */\n _updateHook = null\n\n /** Singleton accessor \u2014 open or bring to front */\n static open() {\n const existing = Array.from(foundry.applications.instances.values()).find(\n (app) => app instanceof CDELoksyuApp\n )\n if (existing) { existing.bringToFront(); return existing }\n const app = new CDELoksyuApp()\n app.render(true)\n return app\n }\n\n async _prepareContext() {\n const sys = getLoksyuData()\n const ELEMENTS = [\n { key: \"wood\", nameKey: \"CDE.Wood\", qualKey: \"CDE.WoodQualities\", img: `systems/${SYSTEM_ID}/images/cde_bois.webp` },\n { key: \"fire\", nameKey: \"CDE.Fire\", qualKey: \"CDE.FireQualities\", img: `systems/${SYSTEM_ID}/images/cde_feu.webp` },\n { key: \"earth\", nameKey: \"CDE.Earth\", qualKey: \"CDE.EarthQualities\", img: `systems/${SYSTEM_ID}/images/cde_terre.webp` },\n { key: \"metal\", nameKey: \"CDE.Metal\", qualKey: \"CDE.MetalQualities\", img: `systems/${SYSTEM_ID}/images/cde_metal.webp` },\n { key: \"water\", nameKey: \"CDE.Water\", qualKey: \"CDE.WaterQualities\", img: `systems/${SYSTEM_ID}/images/cde_eau.webp` },\n ]\n\n return {\n canEdit: game.user.isGM,\n elements: ELEMENTS.map((el) => ({\n ...el,\n yang: sys[el.key]?.yang ?? 0,\n yin: sys[el.key]?.yin ?? 0,\n })),\n }\n }\n\n _onRender(context, options) {\n super._onRender(context, options)\n this.#bindInputs()\n\n this._updateHook = Hooks.on(\"cde:loksyuUpdated\", () => this.render())\n }\n\n _onClose(options) {\n if (this._updateHook !== null) {\n Hooks.off(\"cde:loksyuUpdated\", this._updateHook)\n this._updateHook = null\n }\n super._onClose(options)\n }\n\n #bindInputs() {\n const inputs = this.element?.querySelectorAll(\"input[data-field]\")\n if (!inputs?.length) return\n inputs.forEach((input) => {\n input.addEventListener(\"change\", async (ev) => {\n const field = ev.currentTarget.dataset.field\n const val = parseInt(ev.currentTarget.value, 10)\n if (!field || isNaN(val)) return\n // field is like \"wood.yin\" or \"fire.yang\"\n const [aspect, dim] = field.split(\".\")\n if (!aspect || !dim) return\n const data = getLoksyuData()\n if (!data[aspect]) data[aspect] = { yin: 0, yang: 0 }\n data[aspect][dim] = Math.max(0, val)\n await setLoksyuData(data)\n })\n })\n }\n\n static async #onResetElement(event, target) {\n const key = target.dataset.element\n if (!key) return\n const data = getLoksyuData()\n data[key] = { yin: 0, yang: 0 }\n await setLoksyuData(data)\n }\n\n static async #onResetAll(_event, _target) {\n const KEYS = [\"wood\", \"fire\", \"earth\", \"metal\", \"water\"]\n const data = getLoksyuData()\n for (const k of KEYS) data[k] = { yin: 0, yang: 0 }\n await setLoksyuData(data)\n }\n\n static #onZoomVisual(_event, target) {\n new ImagePopout(target.src, {\n title: game.i18n.localize(\"CDE.LoksyuDiagramTitle\"),\n shareable: false,\n }).render(true)\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { getTinjiValue, setTinjiValue } from \"./singletons.js\"\nimport { SYSTEM_ID } from \"../../config/constants.js\"\n\nexport class CDETinjiApp extends foundry.applications.api.HandlebarsApplicationMixin(\n foundry.applications.api.ApplicationV2\n) {\n static DEFAULT_OPTIONS = {\n id: \"cde-tinji-app\",\n tag: \"div\",\n window: {\n title: \"CDE.TinJi2\",\n icon: \"fas fa-star\",\n resizable: false,\n },\n classes: [\"cde-app\", \"cde-tinji-standalone\"],\n position: { width: 380, height: \"auto\" },\n actions: {\n increment: CDETinjiApp.#onIncrement,\n decrement: CDETinjiApp.#onDecrement,\n reset: CDETinjiApp.#onReset,\n spend: CDETinjiApp.#onSpend,\n },\n }\n\n static PARTS = {\n main: {\n template: `systems/${SYSTEM_ID}/templates/apps/cde-tinji-app.html`,\n },\n }\n\n /** @type {Function|null} */\n _updateHook = null\n\n static open() {\n const existing = Array.from(foundry.applications.instances.values()).find(\n (app) => app instanceof CDETinjiApp\n )\n if (existing) { existing.bringToFront(); return existing }\n const app = new CDETinjiApp()\n app.render(true)\n return app\n }\n\n async _prepareContext() {\n return {\n canEdit: game.user.isGM,\n value: getTinjiValue(),\n }\n }\n\n _onRender(context, options) {\n super._onRender(context, options)\n this.#bindDirectInput()\n this._updateHook = Hooks.on(\"cde:tinjiUpdated\", () => this.render())\n }\n\n _onClose(options) {\n if (this._updateHook !== null) {\n Hooks.off(\"cde:tinjiUpdated\", this._updateHook)\n this._updateHook = null\n }\n super._onClose(options)\n }\n\n #bindDirectInput() {\n const input = this.element?.querySelector(\"input.cde-tinji-direct\")\n if (!input) return\n input.addEventListener(\"change\", async (ev) => {\n const val = parseInt(ev.currentTarget.value, 10)\n if (!isNaN(val)) await setTinjiValue(val)\n })\n }\n\n static async #onIncrement() {\n await setTinjiValue(getTinjiValue() + 1)\n }\n\n static async #onDecrement() {\n const current = getTinjiValue()\n if (current <= 0) return\n await setTinjiValue(current - 1)\n }\n\n static async #onReset() {\n await setTinjiValue(0)\n }\n\n static async #onSpend() {\n const current = getTinjiValue()\n if (current <= 0) {\n ui.notifications.warn(game.i18n.localize(\"CDE.TinjiEmpty\"))\n return\n }\n await setTinjiValue(current - 1)\n await ChatMessage.create({\n user: game.user.id,\n content: `
\n \n ${game.i18n.localize(\"CDE.TinJi2\")}\n ${game.i18n.format(\"CDE.TinjiSpent\", { name: game.user.name })}\n (${current - 1} ${game.i18n.localize(\"CDE.TinjiRemaining\")})\n
`,\n })\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { rollInitiativePC, rollInitiativeNPC } from \"../ui/initiative.js\"\nimport { ACTOR_TYPES } from \"../config/constants.js\"\n\n/**\n * Custom Combat document for Chroniques de l'\u00C9trange.\n *\n * The initiative wheel has 24 crans (positions). The character with the\n * highest initiative acts first (furthest counter-clockwise from reference).\n * After each action, their position advances clockwise by the action's cran cost\n * (initiative decreases, wrapping from 1 \u2192 24).\n *\n * Sort order: descending by initiative (highest acts first).\n */\nexport class CDECombat extends Combat {\n\n /**\n * Override rollInitiative to open the PC or NPC initiative dialog\n * for each selected combatant, then sync the result to the Combatant document.\n */\n async rollInitiative(ids, options = {}) {\n const combatantIds = ids\n ? (typeof ids === \"string\" ? [ids] : ids)\n : this.combatants.map(c => c.id)\n for (const id of combatantIds) {\n const combatant = this.combatants.get(id)\n if (!combatant) continue\n const actor = combatant.actor\n if (!actor) continue\n\n if (actor.type === ACTOR_TYPES.character) {\n await rollInitiativePC(actor)\n } else {\n await rollInitiativeNPC(actor)\n }\n // combatant.initiative is synced by the updateActor hook in system.js\n // (triggered by actor.update inside rollInitiativePC/NPC)\n }\n return this\n }\n\n /**\n * Sort combatants: highest initiative first (furthest counter-clockwise = acts first).\n * Ties: PCs before NPCs; among PCs, by name; among NPCs, by name.\n * Calls super.setupTurns() first to ensure this.current is properly initialized.\n */\n setupTurns() {\n super.setupTurns()\n this.turns = this.turns.slice().sort((a, b) => {\n const ia = a.initiative ?? 0\n const ib = b.initiative ?? 0\n if (ia !== ib) return ib - ia // descending \u2014 highest acts first\n\n // Tie-break: PCs before NPCs\n const aIsPC = a.actor?.type === ACTOR_TYPES.character ? 1 : 0\n const bIsPC = b.actor?.type === ACTOR_TYPES.character ? 1 : 0\n if (aIsPC !== bIsPC) return bIsPC - aIsPC\n\n return (a.name ?? \"\").localeCompare(b.name ?? \"\")\n })\n return this.turns\n }\n}\n\n/**\n * Advance a combatant's wheel position by the given action cran cost.\n * Position wraps: after reaching 1, it continues from 24.\n *\n * @param {Combatant} combatant\n * @param {number} cranCost\n */\nexport async function advanceCombatantPosition(combatant, cranCost) {\n const current = combatant.initiative ?? combatant.actor?.system?.initiative ?? 1\n const newValue = ((current - cranCost - 1 + 48) % 24) + 1\n // Update combatant only; the updateCombatant hook in system.js syncs actor.initiative.\n await combatant.update({ initiative: newValue })\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { advanceCombatantPosition } from \"../../documents/combat.js\"\n\nconst WHEEL_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-wheel-app.html\"\n\n/**\n * Action costs for common combat actions (in crans).\n * Listed in order from cheapest to most expensive.\n */\nexport const ACTION_COSTS = [\n { key: \"draw\", label: \"CDE.ActionCostDraw\", cost: 1 },\n { key: \"changestyle\", label: \"CDE.ActionCostChangeStyle\", cost: 1 },\n { key: \"defense\", label: \"CDE.ActionCostDefense\", cost: 1 },\n { key: \"aim\", label: \"CDE.ActionCostAim\", cost: 2 },\n { key: \"help\", label: \"CDE.ActionCostHelp\", cost: 2 },\n { key: \"defally\", label: \"CDE.ActionCostDefendAlly\", cost: 2 },\n { key: \"move\", label: \"CDE.ActionCostMove\", cost: 2 },\n { key: \"attack\", label: \"CDE.ActionCostAttack\", cost: 3 },\n { key: \"delay\", label: \"CDE.ActionCostDelay\", cost: 6 },\n]\n\n/**\n * Wu Xing color segments for the 24-cran wheel.\n * 6 colors \u00D7 4 crans = 24. Each colour covers crans [start..start+3].\n * An effect lasting 6 crans returns to the same colour.\n */\nconst WHEEL_SEGMENTS = [\n { label: \"M\u00E9tal\", color: \"#b8c4cc\", textColor: \"#1a1a1a\", crans: [1, 2, 3, 4] },\n { label: \"Eau\", color: \"#3a7bd5\", textColor: \"#ffffff\", crans: [5, 6, 7, 8] },\n { label: \"Terre\", color: \"#c8a84b\", textColor: \"#1a1a1a\", crans: [9, 10, 11, 12] },\n { label: \"Feu\", color: \"#d94f3d\", textColor: \"#ffffff\", crans: [13, 14, 15, 16] },\n { label: \"Bois\", color: \"#4a9b5a\", textColor: \"#ffffff\", crans: [17, 18, 19, 20] },\n { label: \"Rep\u00E8re\", color: \"#1a1a2e\", textColor: \"#aaaaaa\", crans: [21, 22, 23, 24] },\n]\n\n/** Return the segment data for a given cran (1\u201324). */\nfunction segmentForCran(cran) {\n return WHEEL_SEGMENTS.find(s => s.crans.includes(cran)) ?? WHEEL_SEGMENTS[0]\n}\n\n/**\n * Roue d'Initiative \u2014 visual initiative wheel for CDE combat.\n *\n * Shows all combatants in the current combat scene on a 24-cran wheel.\n * Provides action-cost buttons to advance a combatant's position.\n *\n * Singleton: open via CDEWheelApp.open().\n */\nexport class CDEWheelApp extends foundry.applications.api.ApplicationV2 {\n static DEFAULT_OPTIONS = {\n id: \"cde-wheel-app\",\n classes: [\"cde-wheel-app\"],\n tag: \"div\",\n window: {\n title: \"CDE.InitiativeWheel\",\n icon: \"fas fa-circle-notch\",\n resizable: true,\n },\n position: { width: 820, height: 620 },\n actions: {\n advanceCran: CDEWheelApp.#advanceCran,\n setSurprised: CDEWheelApp.#setSurprised,\n rollInitiative: CDEWheelApp.#rollInitiative,\n },\n }\n\n /** @type {CDEWheelApp|null} */\n static #instance = null\n\n /** Open (or bring to front) the singleton instance. */\n static open() {\n if (!CDEWheelApp.#instance || CDEWheelApp.#instance.rendered === false) {\n CDEWheelApp.#instance = new CDEWheelApp()\n CDEWheelApp.#instance.render(true)\n } else {\n CDEWheelApp.#instance.bringToFront()\n }\n return CDEWheelApp.#instance\n }\n\n /** Currently selected combatant id (for action panel). */\n #selectedId = null\n\n async _prepareContext(options) {\n const combat = game.combat\n const combatants = combat ? [...combat.combatants.values()] : []\n const sorted = [...combatants].sort((a, b) => (b.initiative ?? 0) - (a.initiative ?? 0))\n const cranData = this.#buildCranData(combatants)\n const selected = this.#selectedId\n ? combatants.find(c => c.id === this.#selectedId)\n : null\n const actionCosts = ACTION_COSTS.map(a => ({\n ...a,\n label: game.i18n.localize(a.label),\n }))\n\n return {\n hasCombat: !!combat,\n combatants: sorted.map(c => ({\n id: c.id,\n name: c.name,\n img: c.token?.texture?.src ?? c.actor?.img ?? \"icons/svg/mystery-man.svg\",\n initiative: c.initiative ?? \"\u2014\",\n segment: segmentForCran(c.initiative ?? 1),\n isActive: combat?.current?.combatantId === c.id,\n isSelected: c.id === this.#selectedId,\n hasInitiative: c.initiative != null,\n })),\n cranData,\n selected,\n selectedName: selected?.name ?? null,\n actionCosts,\n }\n }\n\n async _renderHTML(context, options) {\n return foundry.applications.handlebars.renderTemplate(WHEEL_TEMPLATE, context)\n }\n\n _replaceHTML(result, content, options) {\n content.innerHTML = result\n this.#bindEvents(content)\n }\n\n /** Build per-cran data for the SVG wheel. */\n #buildCranData(combatants) {\n const data = []\n for (let cran = 1; cran <= 24; cran++) {\n const segment = segmentForCran(cran)\n const fighters = combatants.filter(c => Math.round(c.initiative) === cran)\n data.push({ cran, segment, fighters })\n }\n return data\n }\n\n /** Bind click events for combatant selection. */\n #bindEvents(content) {\n content.querySelectorAll(\"[data-select-combatant]\").forEach(el => {\n el.addEventListener(\"click\", () => {\n this.#selectedId = el.dataset.selectCombatant\n this.render()\n })\n })\n }\n\n /** Action: advance selected combatant by given cran cost. */\n static async #advanceCran(event, element) {\n const app = CDEWheelApp.#instance\n if (!app?.#selectedId) return\n const cost = parseInt(element.dataset.cost, 10)\n if (!cost || isNaN(cost)) return\n const combatant = game.combat?.combatants.get(app.#selectedId)\n if (!combatant) return\n await advanceCombatantPosition(combatant, cost)\n }\n\n /** Action: set selected combatant to surprised (position 1 = reference). */\n static async #setSurprised(event, element) {\n const app = CDEWheelApp.#instance\n if (!app?.#selectedId) return\n const combatant = game.combat?.combatants.get(app.#selectedId)\n if (!combatant) return\n // Update combatant only \u2014 updateCombatant hook in system.js syncs actor\n await combatant.update({ initiative: 1 })\n }\n\n /** Action: open the initiative dialog for the selected combatant. */\n static async #rollInitiative(event, element) {\n const app = CDEWheelApp.#instance\n if (!app?.#selectedId) return\n const combatant = game.combat?.combatants.get(app.#selectedId)\n if (!combatant) return\n await game.combat.rollInitiative([app.#selectedId])\n }\n\n /** Re-render when combat state changes. */\n static registerHooks() {\n const refresh = () => {\n if (CDEWheelApp.#instance?.rendered) CDEWheelApp.#instance.render()\n }\n Hooks.on(\"updateCombat\", refresh)\n Hooks.on(\"updateCombatant\", refresh)\n Hooks.on(\"createCombatant\", refresh)\n Hooks.on(\"deleteCombatant\", refresh)\n Hooks.on(\"updateActor\", (_actor, diff) => {\n if (foundry.utils.hasProperty(diff, \"system.initiative\")) refresh()\n })\n Hooks.on(\"deleteCombat\", () => {\n if (CDEWheelApp.#instance?.rendered) CDEWheelApp.#instance.render()\n })\n }\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\n/**\n * Post-roll interactive action buttons injected into dice result chat messages.\n * Allows players to pull dice from the Loksyu (as Successes or d\u00E9s-fastes)\n * and allows the GM to spend Tin Ji to intervene.\n *\n * After a draw, the originating roll result message is updated in-place\n * with the new counts, without creating noise.\n */\n\nimport { getLoksyuData, setLoksyuData, getTinjiValue, setTinjiValue } from \"./apps/singletons.js\"\nimport { SYSTEM_ID, WU_XING_CYCLE, ASPECT_LABELS, ASPECT_ICONS } from \"../config/constants.js\"\n\nconst RESULT_TEMPLATE = \"systems/fvtt-chroniques-de-l-etrange/templates/form/cde-dice-result.html\"\n\n/**\n * Inject or refresh post-roll action buttons in the given chat message HTML element.\n * Called from renderChatMessageHTML hook.\n * @param {ChatMessage} message\n * @param {HTMLElement} html - the chat message HTML element (li.chat-message)\n */\nexport function injectRollActions(message, html) {\n const rollCard = html.querySelector(\".cde-roll-result\")\n if (!rollCard) return\n const aspect = rollCard.dataset.aspect\n if (!aspect || !WU_XING_CYCLE[aspect]) return\n refreshRollActions(rollCard, aspect, message)\n}\n\n/**\n * Re-render the action buttons section based on current Loksyu / TinJi state.\n */\nfunction refreshRollActions(rollCard, aspect, message) {\n rollCard.querySelector(\".cde-roll-actions\")?.remove()\n\n const cycle = WU_XING_CYCLE[aspect]\n const fasteAspect = cycle[1]\n\n const loksyu = getLoksyuData()\n const tinji = getTinjiValue()\n\n const successAvail = (loksyu[aspect]?.yin ?? 0) + (loksyu[aspect]?.yang ?? 0)\n const fasteAvail = (loksyu[fasteAspect]?.yin ?? 0) + (loksyu[fasteAspect]?.yang ?? 0)\n const isGM = game.user.isGM\n\n const hasSomething = successAvail > 0 || fasteAvail > 0 || (isGM && tinji > 0)\n if (!hasSomething) return\n\n const aspLabel = game.i18n.localize(ASPECT_LABELS[aspect])\n const fasteLabel = game.i18n.localize(ASPECT_LABELS[fasteAspect])\n\n let btns = \"\"\n\n if (successAvail > 0) {\n btns += ``\n }\n\n if (fasteAvail > 0) {\n btns += ``\n }\n\n if (isGM && tinji > 0) {\n btns += ``\n }\n\n const wrapper = document.createElement(\"div\")\n wrapper.className = \"cde-roll-actions\"\n wrapper.innerHTML = `\n
\n \n ${game.i18n.localize(\"CDE.PostRollActions\")}\n
\n
${btns}
\n `\n rollCard.appendChild(wrapper)\n\n wrapper.addEventListener(\"click\", async ev => {\n const btn = ev.target.closest(\"[data-action]\")\n if (!btn || btn.disabled) return\n const action = btn.dataset.action\n if (action === \"loksyu-success\") {\n await _drawFromLoksyu(message, aspect, \"success\", aspLabel)\n } else if (action === \"loksyu-faste\") {\n await _drawFromLoksyu(message, fasteAspect, \"faste\", fasteLabel)\n } else if (action === \"tinji\") {\n await _spendTinjiPostRoll()\n }\n // Buttons will be re-injected automatically via renderChatMessageHTML\n // after message.update(). For tinji (no message update), refresh manually.\n if (action === \"tinji\") refreshRollActions(rollCard, aspect, message)\n })\n}\n\n/**\n * Pull one die from a given Loksyu aspect slot, update Loksyu settings,\n * and update the originating roll-result message in-place.\n *\n * @param {ChatMessage} message - the roll result chat message to update\n * @param {string} aspect - which Loksyu aspect slot to draw from\n * @param {\"success\"|\"faste\"} type\n * @param {string} aspectLabel - localised aspect name for the notification\n */\nasync function _drawFromLoksyu(message, aspect, type, aspectLabel) {\n const data = getLoksyuData()\n const entry = data[aspect] ?? { yin: 0, yang: 0 }\n const total = entry.yin + entry.yang\n if (total <= 0) {\n ui.notifications.warn(game.i18n.localize(\"CDE.LoksyuEmpty\"))\n return\n }\n\n // Remove 1 die according to the consumption order setting\n const order = game.settings.get(SYSTEM_ID, \"loksyuConsumptionOrder\")\n if (order === \"yin-first\") {\n if (entry.yin > 0) entry.yin--\n else entry.yang--\n } else if (order === \"balanced\") {\n if (entry.yin > entry.yang) entry.yin--\n else if (entry.yang > entry.yin) entry.yang--\n else if (entry.yang > 0) entry.yang--\n else entry.yin--\n } else {\n // yang-first (default)\n if (entry.yang > 0) entry.yang--\n else entry.yin--\n }\n data[aspect] = entry\n await setLoksyuData(data)\n\n // Update the roll-result message in-place if it has stored flags\n const flags = message?.flags?.[SYSTEM_ID]\n if (flags?.rollResult && message.isOwner) {\n const updated = foundry.utils.deepClone(flags.rollResult)\n if (type === \"success\") {\n updated.successesdice = (updated.successesdice ?? 0) + 1\n updated.loksyuBonusSuc = (updated.loksyuBonusSuc ?? 0) + 1\n // Recalculate weapon damage if applicable\n if (updated.damageBase != null) updated.totalDamage = updated.damageBase + (updated.damageAspectValue ?? 0)\n } else {\n updated.auspiciousdice = (updated.auspiciousdice ?? 0) + 1\n updated.loksyuBonusFaste = (updated.loksyuBonusFaste ?? 0) + 1\n }\n const newHtml = await foundry.applications.handlebars.renderTemplate(RESULT_TEMPLATE, updated)\n await message.update({\n content: newHtml,\n [`flags.${SYSTEM_ID}.rollResult`]: updated,\n })\n // renderChatMessageHTML hook fires automatically \u2192 buttons re-injected\n }\n\n const remain = entry.yin + entry.yang\n const typeLabel = type === \"success\"\n ? game.i18n.localize(\"CDE.Successes\")\n : game.i18n.localize(\"CDE.AuspiciousDie\")\n\n await ChatMessage.create({\n user: game.user.id,\n content: `
\n
\n \"${aspectLabel}\"/\n ${game.user.name}\n ${game.i18n.localize(\"CDE.LoksyuDrawsA\")}\n ${typeLabel}\n ${game.i18n.localize(\"CDE.LoksyuFromAspect\")} ${aspectLabel}\n
\n
\n \n ${game.i18n.localize(\"CDE.Loksyu\")} ${aspectLabel} : \n ${remain} ${game.i18n.localize(\"CDE.LoksyuRemaining\")}\n
\n
`,\n })\n}\n\n/**\n * Spend 1 Tin Ji point (GM only) and post a notification.\n */\nasync function _spendTinjiPostRoll() {\n if (!game.user.isGM) return\n const current = getTinjiValue()\n if (current <= 0) {\n ui.notifications.warn(game.i18n.localize(\"CDE.TinjiEmpty\"))\n return\n }\n await setTinjiValue(current - 1)\n await ChatMessage.create({\n user: game.user.id,\n content: `
\n \u5929\n \n ${game.user.name} ${game.i18n.localize(\"CDE.TinjiSpent\").replace(\"{name}\", game.user.name)}\n \n (${current - 1} ${game.i18n.localize(\"CDE.TinjiRemaining\")})\n
`,\n })\n}\n\n/**\n * Refresh all visible roll-result buttons when Loksyu or TinJi settings change.\n * Wired up via Hooks.on(\"updateSetting\", ...) in system.js.\n */\nexport function refreshAllRollActions() {\n document.querySelectorAll(\".chat-message .cde-roll-result[data-aspect]\").forEach(card => {\n const aspect = card.dataset.aspect\n if (!aspect || !WU_XING_CYCLE[aspect]) return\n // Find the ChatMessage document from the ancestor element's data-message-id\n const msgEl = card.closest(\"[data-message-id]\")\n const msgId = msgEl?.dataset?.messageId\n const message = msgId ? game.messages.get(msgId) : null\n refreshRollActions(card, aspect, message)\n })\n}\n\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { SYSTEM_ID } from \"../../config/constants.js\"\n\nconst HELP_JOURNAL_UUID = `Compendium.${SYSTEM_ID}.cde-help.JournalEntry.CDEGuideMain0001`\n\n/** Post a styled welcome chat message. Called once per session by the GM. */\nexport async function showWelcomeMessage() {\n const logo = `systems/${SYSTEM_ID}/images/logo_jeu.webp`\n const content = `\n
\n \"Les\n

Les Chroniques de l'\u00C9trange

\n

\n Un jeu de r\u00F4le \u00E9dit\u00E9 par\n Antre-Monde \u00C9ditions\n

\n

\n Syst\u00E8me FoundryVTT r\u00E9alis\u00E9 par\n LeRatierBretonnien\n

\n \n
`\n\n await ChatMessage.create({\n content,\n speaker: { alias: \"Les Chroniques de l'\u00C9trange\" },\n flags: { [SYSTEM_ID]: { welcome: true } },\n })\n}\n\n/** Attach the help-open click handler to a welcome chat message HTML node. */\nexport function injectWelcomeActions(_message, html) {\n const el = html instanceof HTMLElement ? html : (html[0] ?? html)\n const btn = el?.querySelector?.(\"[data-action='open-cde-help']\")\n if (!btn) return\n\n btn.addEventListener(\"click\", async () => {\n try {\n const doc = await fromUuid(HELP_JOURNAL_UUID)\n doc?.sheet?.render(true)\n } catch {\n // Pack not yet loaded \u2014 open the compendium browser as fallback\n game.packs.get(`${SYSTEM_ID}.cde-help`)?.render(true)\n }\n })\n}\n", "/**\n * Chroniques de l'\u00C9trange \u2014 Syst\u00E8me FoundryVTT\n *\n * Chroniques de l'\u00C9trange est un jeu de r\u00F4le \u00E9dit\u00E9 par Antre-Monde \u00C9ditions.\n * Ce syst\u00E8me FoundryVTT est une impl\u00E9mentation ind\u00E9pendante et n'est pas\n * affili\u00E9 \u00E0 Antre-Monde \u00C9ditions,\n * mais a \u00E9t\u00E9 r\u00E9alis\u00E9 avec l'autorisation d'Antre-Monde \u00C9ditions.\n *\n * @author LeRatierBretonnien\n * @copyright 2024\u20132026 LeRatierBretonnien\n * @license CC BY-NC-SA 4.0 \u2013 https://creativecommons.org/licenses/by-nc-sa/4.0/\n */\n\nimport { ACTOR_TYPES, ITEM_TYPES, MAGICS, SUBTYPES, SYSTEM_ID } from \"./config/constants.js\"\nimport { registerSettings, migrateIfNeeded, loadWelcomeSceneIfNeeded } from \"./config/settings.js\"\nimport { preLocalizeConfig } from \"./config/localize.js\"\nimport { configureRuntime } from \"./config/runtime.js\"\nimport { CharacterDataModel, NpcDataModel } from \"./data/actors/index.js\"\nimport { EquipmentDataModel, KungfuDataModel, SpellDataModel, SupernaturalDataModel, WeaponDataModel, ArmorDataModel, SanheiDataModel, IngredientDataModel } from \"./data/items/index.js\"\nimport { CDEMessage } from \"./documents/chat-message.js\"\nimport { CDEActor } from \"./documents/actor.js\"\nimport { CDEItem } from \"./documents/item.js\"\nimport { registerDice } from \"./ui/dice.js\"\nimport { registerHandlebarsHelpers } from \"./ui/helpers.js\"\nimport { preloadPartials } from \"./ui/templates.js\"\nimport { CDECharacterSheet, CDENpcSheet } from \"./ui/sheets/actors/index.js\"\nimport { CDEItemSheet, CDEKungfuSheet, CDESpellSheet, CDESupernaturalSheet, CDEWeaponSheet, CDEArmorSheet, CDESanheiSheet, CDEIngredientSheet } from \"./ui/sheets/items/index.js\"\nimport { CDELoksyuApp } from \"./ui/apps/loksyu-app.js\"\nimport { CDETinjiApp } from \"./ui/apps/tinji-app.js\"\nimport { CDEWheelApp } from \"./ui/apps/wheel-app.js\"\nimport { injectRollActions, refreshAllRollActions } from \"./ui/roll-actions.js\"\nimport { CDECombat } from \"./documents/combat.js\"\nimport { showWelcomeMessage, injectWelcomeActions } from \"./ui/apps/welcome.js\"\n\nHooks.once(\"i18nInit\", preLocalizeConfig)\n\nHooks.once(\"init\", async () => {\n console.info(`CHRONIQUESDELETRANGE | Initializing ${SYSTEM_ID}`)\n\n registerSettings()\n\n game.system.CONST = { MAGICS, SUBTYPES }\n\n // Expose standalone apps globally for macros\n game.cde = { CDELoksyuApp, CDETinjiApp, CDEWheelApp }\n\n CONFIG.Combat.documentClass = CDECombat\n\n CONFIG.Actor.dataModels = {\n [ACTOR_TYPES.character]: CharacterDataModel,\n [ACTOR_TYPES.npc]: NpcDataModel,\n }\n CONFIG.Item.dataModels = {\n [ITEM_TYPES.item]: EquipmentDataModel,\n [ITEM_TYPES.kungfu]: KungfuDataModel,\n [ITEM_TYPES.spell]: SpellDataModel,\n [ITEM_TYPES.supernatural]: SupernaturalDataModel,\n [ITEM_TYPES.weapon]: WeaponDataModel,\n [ITEM_TYPES.armor]: ArmorDataModel,\n [ITEM_TYPES.sanhei]: SanheiDataModel,\n [ITEM_TYPES.ingredient]: IngredientDataModel,\n }\n\n CONFIG.Actor.documentClass = CDEActor\n CONFIG.Item.documentClass = CDEItem\n CONFIG.ChatMessage.documentClass = CDEMessage\n\n configureRuntime()\n\n foundry.applications.apps.DocumentSheetConfig.unregisterSheet(Actor, \"core\", foundry.appv1.sheets.ActorSheet)\n foundry.applications.apps.DocumentSheetConfig.unregisterSheet(Item, \"core\", foundry.appv1.sheets.ItemSheet)\n\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDECharacterSheet, {\n types: [ACTOR_TYPES.character],\n makeDefault: true,\n label: \"CDE Character Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDENpcSheet, {\n types: [ACTOR_TYPES.npc],\n makeDefault: true,\n label: \"CDE NPC Sheet (V2)\",\n })\n\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEItemSheet, {\n types: [ITEM_TYPES.item],\n makeDefault: true,\n label: \"CDE Item Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEKungfuSheet, {\n types: [ITEM_TYPES.kungfu],\n makeDefault: true,\n label: \"CDE KungFu Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESpellSheet, {\n types: [ITEM_TYPES.spell],\n makeDefault: true,\n label: \"CDE Spell Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESupernaturalSheet, {\n types: [ITEM_TYPES.supernatural],\n makeDefault: true,\n label: \"CDE Supernatural Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEWeaponSheet, {\n types: [ITEM_TYPES.weapon],\n makeDefault: true,\n label: \"CDE Weapon Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEArmorSheet, {\n types: [ITEM_TYPES.armor],\n makeDefault: true,\n label: \"CDE Armor Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESanheiSheet, {\n types: [ITEM_TYPES.sanhei],\n makeDefault: true,\n label: \"CDE Sanhei Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEIngredientSheet, {\n types: [ITEM_TYPES.ingredient],\n makeDefault: true,\n label: \"CDE Ingredient Sheet (V2)\",\n })\n\n await preloadPartials()\n registerHandlebarsHelpers()\n registerDice()\n\n console.info(`CHRONIQUESDELETRANGE | Initialized`)\n})\n\nHooks.once(\"ready\", async () => {\n await migrateIfNeeded()\n await loadWelcomeSceneIfNeeded()\n CDEWheelApp.registerHooks()\n if (game.user.isGM) showWelcomeMessage()\n})\n\n/** Add Loksyu + Tin Ji quick-access buttons to the chat panel (FoundryVTT v13) */\nHooks.on(\"renderChatLog\", (_app, html) => {\n const el = html instanceof HTMLElement ? html : (html[0] ?? html)\n if (!el?.querySelector) return\n\n // Avoid double-injection on re-renders\n if (el.querySelector(\".cde-chat-app-buttons\")) return\n\n const wrapper = document.createElement(\"div\")\n wrapper.classList.add(\"cde-chat-app-buttons\")\n wrapper.innerHTML = `\n \n \n \n `\n\n // Use event delegation to avoid being swallowed by Foundry's own handlers\n wrapper.addEventListener(\"click\", (ev) => {\n if (ev.target.closest(\".cde-chat-btn--loksyu\")) CDELoksyuApp.open()\n if (ev.target.closest(\".cde-chat-btn--tinji\")) CDETinjiApp.open()\n if (ev.target.closest(\".cde-chat-btn--wheel\")) CDEWheelApp.open()\n })\n\n // Insert before the chat form \u2014 works on v12 and v13\n const anchor = el.querySelector(\".chat-form\")\n ?? el.querySelector(\".chat-message-form\")\n ?? el.querySelector(\"form\")\n if (anchor) anchor.parentElement.insertBefore(wrapper, anchor)\n else el.appendChild(wrapper)\n})\n\n/** Inject Loksyu / TinJi action buttons into roll-result chat messages */\nHooks.on(\"renderChatMessageHTML\", (message, html) => {\n injectRollActions(message, html)\n if (message.flags?.[SYSTEM_ID]?.welcome) injectWelcomeActions(message, html)\n})\n\n/** Refresh all visible roll-result buttons whenever Loksyu or TinJi settings change */\nHooks.on(\"updateSetting\", setting => {\n if (!setting.key) return\n if (setting.key.includes(\"loksyuData\") || setting.key.includes(\"tinjiData\")) {\n refreshAllRollActions()\n }\n})\n\n/**\n * When an actor's initiative changes (via +/- buttons on the sheet),\n * sync the corresponding combatant in the active combat.\n */\nHooks.on(\"updateActor\", (actor, diff) => {\n if (!foundry.utils.hasProperty(diff, \"system.initiative\")) return\n if (!game.combat) return\n const initiative = actor.system.initiative\n const combatant = game.combat.combatants.find(c => c.actor?.id === actor.id)\n if (combatant && combatant.initiative !== initiative) {\n combatant.update({ initiative }).catch(() => {})\n }\n})\n\n/**\n * When a combatant's initiative changes (via wheel action buttons),\n * sync the actor's system.initiative to match.\n * Uses setTimeout to defer until after Foundry's update chain resolves,\n * avoiding concurrent #recordPreviousState errors on the combat document.\n */\nHooks.on(\"updateCombatant\", (combatant, diff) => {\n if (!(\"initiative\" in diff)) return\n const initiative = combatant.initiative\n if (initiative == null) return\n setTimeout(() => {\n const actor = combatant.actor\n if (actor && actor.system?.initiative !== initiative) {\n actor.update({ \"system.initiative\": initiative }).catch(() => {})\n }\n }, 0)\n})\n"], + "mappings": "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", "names": ["RESULT_TEMPLATE", "HandlebarsApplicationMixin", "app", "app", "RESULT_TEMPLATE"] } diff --git a/lang/fr-cde.json b/lang/fr-cde.json index 52341d6..f8549d1 100644 --- a/lang/fr-cde.json +++ b/lang/fr-cde.json @@ -217,8 +217,11 @@ "CDE.MsgMagic2": "s'élève à ", "CDE.MsgMagic3": ". La puissance à invoquer est de ", "CDE.MsgMagic4": ", si toutefois le sort est lancé avec succès.", + "CDE.MoveUp": "Monter", + "CDE.MoveDown": "Descendre", "CDE.NPCName": "Nom du PNJ", "CDE.FatSi": "Fat Si", + "CDE.FreePowerLevels": "Niveaux de puissance gratuits", "CDE.PNJ": "PNJ", "CDE.Name": "Nom", "CDE.Necromancy": "Nécromancie", diff --git a/src/data/actors/character.js b/src/data/actors/character.js index 834c625..18e540e 100644 --- a/src/data/actors/character.js +++ b/src/data/actors/character.js @@ -122,9 +122,8 @@ export default class CharacterDataModel extends foundry.abstract.TypeDataModel { typeofthrow: numberField(0), aspectskill: numberField(0), bonusmalusskill: numberField(0), - aspectspeciality: numberField(0), rolldifficulty: numberField(0), - bonusmalusspeciality: numberField(0), + freepowerlevels: numberField(0), }), }), aspect: new fields.SchemaField({ @@ -163,6 +162,10 @@ export default class CharacterDataModel extends foundry.abstract.TypeDataModel { nine: componentField(), zero: componentField(), }), + magicOrder: new fields.ArrayField( + new fields.StringField({ required: true, nullable: false, initial: "" }), + { required: true, initial: [] } + ), magics: new fields.SchemaField({ internalcinnabar: magicField(), alchemy: magicField(), diff --git a/src/data/items/armor.js b/src/data/items/armor.js index 6e8b002..a06730a 100644 --- a/src/data/items/armor.js +++ b/src/data/items/armor.js @@ -25,7 +25,7 @@ export default class ArmorDataModel extends foundry.abstract.TypeDataModel { domain: stringField(""), obtainLevel: intField(0, { min: 0, max: 5 }), obtainDifficulty: intField(0, { min: 0, max: 3 }), - quantity: intField(1), + quantity: intField(1, { min: 0 }), notes: htmlField(""), } } diff --git a/src/data/items/ingredient.js b/src/data/items/ingredient.js index 7ccb0a4..164b418 100644 --- a/src/data/items/ingredient.js +++ b/src/data/items/ingredient.js @@ -24,7 +24,7 @@ export default class IngredientDataModel extends foundry.abstract.TypeDataModel school: stringField("all"), obtainLevel: intField(0, { min: 0, max: 5 }), obtainDifficulty: intField(0, { min: 0, max: 3 }), - quantity: intField(1), + quantity: intField(1, { min: 0 }), notes: htmlField(""), } } diff --git a/src/data/items/kungfu.js b/src/data/items/kungfu.js index a654f39..7b8384d 100644 --- a/src/data/items/kungfu.js +++ b/src/data/items/kungfu.js @@ -30,7 +30,7 @@ export default class KungfuDataModel extends foundry.abstract.TypeDataModel { reference: stringField(""), description: htmlField(""), orientation: stringField("yin"), // yin | yang | yinyang - aspect: stringField("metal"), // metal | eau | terre | feu | bois + aspect: stringField("metal"), // metal | water | earth | fire | wood skill: stringField("kungfu"), // kungfu | rangedcombat speciality: stringField(""), style: stringField(""), diff --git a/src/data/items/spell.js b/src/data/items/spell.js index a35ee0c..4da28fc 100644 --- a/src/data/items/spell.js +++ b/src/data/items/spell.js @@ -21,7 +21,7 @@ export default class SpellDataModel extends foundry.abstract.TypeDataModel { reference: stringField(""), description: htmlField(""), specialityname: stringField(""), - associatedelement: stringField("metal"), // metal | eau | terre | feu | bois + associatedelement: stringField("metal"), // metal | water | earth | fire | wood hei: stringField(""), realizationtimeritual: stringField(""), realizationtimeaccelerated: stringField(""), diff --git a/src/data/items/weapon.js b/src/data/items/weapon.js index ea1edeb..f9af9d8 100644 --- a/src/data/items/weapon.js +++ b/src/data/items/weapon.js @@ -30,7 +30,7 @@ export default class WeaponDataModel extends foundry.abstract.TypeDataModel { range: stringField("contact"), // contact | courte | mediane | longue | extreme obtainLevel: intField(0, { min: 0, max: 5 }), obtainDifficulty: intField(0, { min: 0, max: 3 }), - quantity: intField(1), + quantity: intField(1, { min: 0 }), notes: htmlField(""), } } diff --git a/src/documents/combat.js b/src/documents/combat.js index 4b9d01c..eab9a4d 100644 --- a/src/documents/combat.js +++ b/src/documents/combat.js @@ -31,7 +31,9 @@ export class CDECombat extends Combat { * for each selected combatant, then sync the result to the Combatant document. */ async rollInitiative(ids, options = {}) { - const combatantIds = typeof ids === "string" ? [ids] : ids + const combatantIds = ids + ? (typeof ids === "string" ? [ids] : ids) + : this.combatants.map(c => c.id) for (const id of combatantIds) { const combatant = this.combatants.get(id) if (!combatant) continue diff --git a/src/ui/apps/tinji-app.js b/src/ui/apps/tinji-app.js index cb36e20..446fe5c 100644 --- a/src/ui/apps/tinji-app.js +++ b/src/ui/apps/tinji-app.js @@ -105,7 +105,7 @@ export class CDETinjiApp extends foundry.applications.api.HandlebarsApplicationM return } await setTinjiValue(current - 1) - ChatMessage.create({ + await ChatMessage.create({ user: game.user.id, content: `
diff --git a/src/ui/roll-actions.js b/src/ui/roll-actions.js index bf452ec..5fd0c5d 100644 --- a/src/ui/roll-actions.js +++ b/src/ui/roll-actions.js @@ -177,7 +177,7 @@ async function _drawFromLoksyu(message, aspect, type, aspectLabel) { ? game.i18n.localize("CDE.Successes") : game.i18n.localize("CDE.AuspiciousDie") - ChatMessage.create({ + await ChatMessage.create({ user: game.user.id, content: `
@@ -207,7 +207,7 @@ async function _spendTinjiPostRoll() { return } await setTinjiValue(current - 1) - ChatMessage.create({ + await ChatMessage.create({ user: game.user.id, content: `
diff --git a/src/ui/rolling.js b/src/ui/rolling.js index b201e9f..6ec8f18 100644 --- a/src/ui/rolling.js +++ b/src/ui/rolling.js @@ -164,19 +164,16 @@ async function showMagicPrompt(params) { title: params.title, template: MAGIC_PROMPT_TEMPLATE, data: { - numberofdice: params.numberofdice ?? 0, - aspectskill: Number(params.aspectskill ?? 0), - bonusmalusskill: params.bonusmalusskill ?? 0, + numberofdice: params.numberofdice ?? 0, + aspectskill: Number(params.aspectskill ?? 0), + bonusmalusskill: params.bonusmalusskill ?? 0, bonusauspiciousdice: params.bonusauspiciousdice ?? 0, - aspectspeciality: Number(params.aspectspeciality ?? 0), - rolldifficulty: params.rolldifficulty ?? 1, - bonusmalusspeciality: params.bonusmalusspeciality ?? 0, - heispend: params.heispend ?? 0, - typeofthrow: Number(params.typeofthrow ?? 0), + rolldifficulty: params.rolldifficulty ?? 1, + freepowerlevels: params.freepowerlevels ?? 0, + typeofthrow: Number(params.typeofthrow ?? 0), }, fields: ["aspectskill", "bonusmalusskill", "bonusauspiciousdice", - "aspectspeciality", "rolldifficulty", "bonusmalusspeciality", - "heispend", "typeofthrow"], + "rolldifficulty", "freepowerlevels", "typeofthrow"], }) } @@ -318,7 +315,9 @@ export async function rollForActor(actor, rollKey) { const kfSkill = kfItem.system.skill ?? "kungfu" numberofdice = sys.skills?.[kfSkill]?.value ?? 0 title = `${kfItem.name} [${game.i18n.localize(sys.skills?.[kfSkill]?.label ?? "CDE.KungFu")}]` - kfDefaultAspect = ASPECT_NAMES.indexOf(kfItem.system.aspect ?? "metal") + const kfAspect = kfItem.system.aspect?.toLowerCase() ?? "metal" + const ASPECT_NORMALIZE = { eau: "water", terre: "earth", feu: "fire", bois: "wood" } + kfDefaultAspect = ASPECT_NAMES.indexOf(ASPECT_NORMALIZE[kfAspect] ?? kfAspect) if (kfDefaultAspect < 0) kfDefaultAspect = 0 break } @@ -427,7 +426,7 @@ export async function rollForActor(actor, rollKey) { }, wpRoll, ROLL_MODES[wpThrowMode] ?? "roll") if (game.modules.get("dice-so-nice")?.active && wpMsg?.id) { - await game.dice3d.waitFor3DAnimationByMessageID(wpMsg.id) + try { await game.dice3d.waitFor3DAnimationByMessageID(wpMsg.id) } catch (_e) { /* DSN not available */ } } // Auto-update Loksyu/TinJi singletons from weapon roll faces if ((wpResults.loksyudice ?? 0) > 0) await updateLoksyuFromRoll(wpAspectName, wpFaces) @@ -439,8 +438,7 @@ export async function rollForActor(actor, rollKey) { return } - // For magic rolls the prompt allows adding HEI dice, so don't block early. - // For itemkungfu, allow 0 base dice (user can add bonus dice in the prompt). + // For magic rolls / itemkungfu, allow 0 base dice (user can add bonus dice in the prompt). if (numberofdice <= 0 && typeLibel !== "aspect" && typeLibel !== "itemkungfu" && !isMagic) { ui.notifications.warn(game.i18n.localize("CDE.Error0")) return @@ -465,16 +463,6 @@ export async function rollForActor(actor, rollKey) { defaultAspect = kfDefaultAspect } - let defaultSpecialAspect = 0 - if (isMagicSpecial && specialLibel) { - // Look up the speciality's element from the MAGICS config constant - const specialCfg = MAGICS?.[skillLibel]?.speciality?.[specialLibel] - const aspectName = LABELELEMENT_TO_ASPECT[specialCfg?.labelelement] - if (aspectName) { - defaultSpecialAspect = ASPECT_NAMES.indexOf(aspectName) - } - } - // ---- Show roll prompt ---- let params @@ -485,10 +473,8 @@ export async function rollForActor(actor, rollKey) { aspectskill: defaultAspect, bonusmalusskill: 0, bonusauspiciousdice: 0, - aspectspeciality: defaultSpecialAspect, rolldifficulty: 1, - bonusmalusspeciality: 0, - heispend: 0, + freepowerlevels: 0, typeofthrow: typeOfThrow, }) } else { @@ -508,22 +494,18 @@ export async function rollForActor(actor, rollKey) { // ---- Compute total dice and roll ---- let aspectIndex, bonusMalus, bonusAuspicious, throwMode - let spellAspectIndex = null // magic only: aspect of the speciality for Wu Xing - let rollDifficulty = 1 // magic only: multiplier applied to successes + let rollDifficulty = 1 // magic only: multiplier applied to successes if (isMagic) { const skillAspectIndex = Number(params.aspectskill ?? 0) - spellAspectIndex = Number(params.aspectspeciality ?? skillAspectIndex) - aspectIndex = skillAspectIndex // used only for skill dice pool + aspectIndex = skillAspectIndex // used for both dice pool and Wu Xing cycle bonusMalus = Number(params.bonusmalusskill ?? 0) bonusAuspicious = Number(params.bonusauspiciousdice ?? 0) rollDifficulty = Math.max(1, Number(params.rolldifficulty ?? 1)) throwMode = Number(params.typeofthrow ?? 0) // magic: magic skill + aspect + bonuses + 1 (speciality base) + HEI spent const aspectDice = sys.aspect?.[ASPECT_NAMES[aspectIndex]]?.value ?? 0 - const bonusSpec = Number(params.bonusmalusspeciality ?? 0) - const heiDice = Number(params.heispend ?? 0) - numberofdice = numberofdice + aspectDice + bonusMalus + 1 + bonusSpec + heiDice + numberofdice = numberofdice + aspectDice + bonusMalus + 1 } else { aspectIndex = Number(params.aspect ?? 0) bonusMalus = Number(params.bonusmalus ?? 0) @@ -550,31 +532,43 @@ export async function rollForActor(actor, rollKey) { const rollModeKey = ROLL_MODES[throwMode] ?? "roll" + // ---- Compute spell power (magic only) ---- + // Power = rollDifficulty × character aspect value for the speciality's + // associated element (or the school's aspect for base magic rolls). + let spellPower = null + let spellPowerAspectName = null + let spellPowerAspectValue = null + if (isMagic) { + if (isMagicSpecial && specialLibel) { + const specialCfg = MAGICS?.[skillLibel]?.speciality?.[specialLibel] + const elemName = LABELELEMENT_TO_ASPECT[specialCfg?.labelelement] + if (elemName) spellPowerAspectName = elemName + } + if (!spellPowerAspectName) spellPowerAspectName = ASPECT_NAMES[aspectIndex] + spellPowerAspectValue = sys.aspect?.[spellPowerAspectName]?.value ?? 0 + const freePowerLevels = Number(params.freepowerlevels ?? 0) + spellPower = rollDifficulty * (spellPowerAspectValue + freePowerLevels) + } + // ---- Compute Wu Xing results ---- - // For magic rolls, the spell's aspect (aspectspeciality) governs the Wu Xing - // cycle (which faces count as successes/auspicious/etc.), not the skill aspect. - const wuXingAspectName = spellAspectIndex !== null - ? ASPECT_NAMES[spellAspectIndex] - : ASPECT_NAMES[aspectIndex] + // The Wu Xing cycle always uses the roll's aspect (skill aspect for magic, + // skill/resource aspect otherwise) to determine which faces count as + // successes/auspicious/etc. + const wuXingAspectName = ASPECT_NAMES[aspectIndex] const allResults = roll.dice[0]?.results ?? [] const faces = countFaces(allResults) const results = computeWuXingResults(faces, wuXingAspectName, bonusAuspicious) if (!results) return - // For magic, successesdice × rollDifficulty = spell power - const spellPower = isMagic ? results.successesdice * rollDifficulty : null - // ---- Build modifier summary text ---- const modParts = [] if (isMagic) { const bm = Number(params.bonusmalusskill ?? 0) - const bs = Number(params.bonusmalusspeciality ?? 0) - const hs = Number(params.heispend ?? 0) const ba = Number(params.bonusauspiciousdice ?? 0) + const fp = Number(params.freepowerlevels ?? 0) if (bm !== 0) modParts.push(`${bm > 0 ? "+" : ""}${bm} ${game.i18n.localize("CDE.BonusMalus")}`) - if (bs !== 0) modParts.push(`${bs > 0 ? "+" : ""}${bs} ${game.i18n.localize("CDE.SpellBonus")}`) if (ba !== 0) modParts.push(`+${ba} ${game.i18n.localize("CDE.BonusAuspiciousDice")}`) - if (hs !== 0) modParts.push(`${hs} ${game.i18n.localize("CDE.HeiSpend")}`) + if (fp !== 0) modParts.push(`+${fp} ${game.i18n.localize("CDE.FreePowerLevels")}`) if (rollDifficulty !== 1) modParts.push(`×${rollDifficulty} ${game.i18n.localize("CDE.RollDifficulty")}`) } else { const bm = Number(params.bonusmalus ?? 0) @@ -596,6 +590,9 @@ export async function rollForActor(actor, rollKey) { modifiersText: modParts.length ? modParts.join(" · ") : "", // Spell power (magic only) spellPower, + spellPowerAspectLabel: spellPowerAspectName ? game.i18n.localize(ASPECT_LABELS[spellPowerAspectName] ?? "") : "", + spellPowerAspectValue, + spellPowerFreeLevels: isMagic ? Number(params.freepowerlevels ?? 0) : 0, rollDifficulty: isMagic ? rollDifficulty : null, // Actor info actorName: actor.name ?? "", @@ -610,7 +607,7 @@ export async function rollForActor(actor, rollKey) { // ---- Wait for Dice So Nice animation ---- if (game.modules.get("dice-so-nice")?.active && msg?.id) { - await game.dice3d.waitFor3DAnimationByMessageID(msg.id) + try { await game.dice3d.waitFor3DAnimationByMessageID(msg.id) } catch (_e) { /* DSN not available */ } } // ---- Auto-update Loksyu / TinJi singletons ---- diff --git a/src/ui/sheets/actors/character.js b/src/ui/sheets/actors/character.js index 43bb37e9..25a6e35 100644 --- a/src/ui/sheets/actors/character.js +++ b/src/ui/sheets/actors/character.js @@ -19,6 +19,10 @@ import { CDEBaseActorSheet } from "./base.js" export class CDECharacterSheet extends CDEBaseActorSheet { static DEFAULT_OPTIONS = { classes: ["character"], + actions: { + moveMagicUp: CDECharacterSheet.#onMoveMagicUp, + moveMagicDown: CDECharacterSheet.#onMoveMagicDown, + }, } static PARTS = { @@ -48,25 +52,35 @@ export class CDECharacterSheet extends CDEBaseActorSheet { // Build magicsDisplay: only include the 5 relevant specialities per magic type + grimoire const systemMagics = context.systemData.magics ?? {} - context.magicsDisplay = Object.fromEntries( - Object.entries(MAGICS).map(([magicKey, magicDef]) => { - const magicData = systemMagics[magicKey] ?? {} - return [ - magicKey, - { - value: magicData.value ?? 0, - visible: magicData.visible ?? false, - speciality: Object.fromEntries( - Object.keys(magicDef.speciality).map((specKey) => [ - specKey, - { check: magicData.speciality?.[specKey]?.check ?? false }, - ]) - ), - grimoire: spellsByDiscipline[magicKey] ?? [], - }, - ] + const magicEntries = Object.entries(MAGICS).map(([magicKey, magicDef]) => { + const magicData = systemMagics[magicKey] ?? {} + return [ + magicKey, + { + value: magicData.value ?? 0, + visible: magicData.visible ?? false, + speciality: Object.fromEntries( + Object.keys(magicDef.speciality).map((specKey) => [ + specKey, + { check: magicData.speciality?.[specKey]?.check ?? false }, + ]) + ), + grimoire: spellsByDiscipline[magicKey] ?? [], + }, + ] + }) + const order = context.systemData.magicOrder ?? [] + if (order.length > 0) { + magicEntries.sort((a, b) => { + const ia = order.indexOf(a[0]) + const ib = order.indexOf(b[0]) + if (ia === -1 && ib === -1) return 0 + if (ia === -1) return 1 + if (ib === -1) return -1 + return ia - ib }) - ) + } + context.magicsDisplay = Object.fromEntries(magicEntries) return context } @@ -155,7 +169,7 @@ export class CDECharacterSheet extends CDEBaseActorSheet { cell.addEventListener("click", (event) => { event.preventDefault() const rollKey = cell.dataset.libelId - if (rollKey) rollForActor(this.document, rollKey) + if (rollKey) rollForActor(this.document, rollKey)?.catch(err => console.error("Roll failed:", err)) }) }) } @@ -171,6 +185,28 @@ export class CDECharacterSheet extends CDEBaseActorSheet { }) } + static async #onMoveMagicUp(event, target) { + const key = target.dataset.magicKey + let order = this.document.system.magicOrder ?? [] + if (!order.length) order = [...Object.keys(MAGICS)] + else order = [...order] + const idx = order.indexOf(key) + if (idx <= 0) return + [order[idx - 1], order[idx]] = [order[idx], order[idx - 1]] + await this.document.update({ "system.magicOrder": order }) + } + + static async #onMoveMagicDown(event, target) { + const key = target.dataset.magicKey + let order = this.document.system.magicOrder ?? [] + if (!order.length) order = [...Object.keys(MAGICS)] + else order = [...order] + const idx = order.indexOf(key) + if (idx === -1 || idx >= order.length - 1) return + [order[idx], order[idx + 1]] = [order[idx + 1], order[idx]] + await this.document.update({ "system.magicOrder": order }) + } + #bindComponentRandomize() { const btn = this.element?.querySelector("[data-action='randomize-component']") if (!btn) return diff --git a/src/ui/sheets/actors/npc.js b/src/ui/sheets/actors/npc.js index 2c45227..bd287d0 100644 --- a/src/ui/sheets/actors/npc.js +++ b/src/ui/sheets/actors/npc.js @@ -50,7 +50,7 @@ export class CDENpcSheet extends CDEBaseActorSheet { cell.addEventListener("click", (event) => { event.preventDefault() const rollKey = cell.dataset.libelId - if (rollKey) rollForActor(this.document, rollKey) + if (rollKey) rollForActor(this.document, rollKey)?.catch(err => console.error("Roll failed:", err)) }) }) } diff --git a/src/ui/sheets/items/sanhei.js b/src/ui/sheets/items/sanhei.js index 9650b90..8d000de 100644 --- a/src/ui/sheets/items/sanhei.js +++ b/src/ui/sheets/items/sanhei.js @@ -26,11 +26,11 @@ export class CDESanheiSheet extends CDEBaseItemSheet { async _prepareContext() { const context = await super._prepareContext() const enrich = (content) => foundry.applications.ux.TextEditor.implementation.enrichHTML(content ?? "", { async: true }) - const props = this.document.system.properties - context.prop1DescriptionHTML = await enrich(props.prop1.description) - context.prop2DescriptionHTML = await enrich(props.prop2.description) - context.prop3DescriptionHTML = await enrich(props.prop3.description) - context.propFields = this.document.system.schema.fields.properties.fields + const props = this.document.system.properties ?? {} + context.prop1DescriptionHTML = await enrich(props.prop1?.description) + context.prop2DescriptionHTML = await enrich(props.prop2?.description) + context.prop3DescriptionHTML = await enrich(props.prop3?.description) + context.propFields = this.document.system.schema.fields.properties?.fields return context } } diff --git a/templates/actor/parts/cde-character-magics.html b/templates/actor/parts/cde-character-magics.html index 58f623f..4726ff0 100644 --- a/templates/actor/parts/cde-character-magics.html +++ b/templates/actor/parts/cde-character-magics.html @@ -81,6 +81,14 @@ title="{{ localize 'CDE.Roll' }} {{getMagicLabel key}}"> + + + + + +