From f7a01900acbf057d408de7323b1eda93c3789cd3 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnier Date: Sat, 28 Mar 2026 08:44:19 +0100 Subject: [PATCH] =?UTF-8?q?Import=20initial=20du=20syst=C3=A8me?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + CHANGELOG.md | 18 + css/cde-theme.css | 1634 ++++++++++++++++- css/cde-theme.less | 1614 +++++++++++++++- dist/system.js | 1024 ++++++++++- dist/system.js.map | 8 +- fonts/Averia-Regular.ttf | Bin 0 -> 78448 bytes lang/en-cde.json | 37 +- lang/es-cde.json | 4 +- lang/fr-cde.json | 626 ++++--- package.json | 3 + .../{000035.log => 000051.log} | 0 packs/aide-pour-fxmaster/CURRENT | 2 +- packs/aide-pour-fxmaster/LOG | 6 +- packs/aide-pour-fxmaster/LOG.old | 14 +- .../{MANIFEST-000034 => MANIFEST-000050} | Bin 205 -> 205 bytes .../{000151.log => 000167.log} | 0 packs/aide-pour-la-lumiere/CURRENT | 2 +- packs/aide-pour-la-lumiere/LOG | 6 +- packs/aide-pour-la-lumiere/LOG.old | 16 +- .../{MANIFEST-000150 => MANIFEST-000166} | Bin 209 -> 209 bytes .../{000723.log => 000739.log} | 0 packs/aide-pour-linitiative/CURRENT | 2 +- packs/aide-pour-linitiative/LOG | 6 +- packs/aide-pour-linitiative/LOG.old | 16 +- .../{MANIFEST-000722 => MANIFEST-000738} | Bin 209 -> 209 bytes .../{004344.log => 004360.log} | 0 packs/aides-pour-les-joueuses/CURRENT | 2 +- packs/aides-pour-les-joueuses/LOG | 6 +- packs/aides-pour-les-joueuses/LOG.old | 14 +- .../{MANIFEST-004343 => MANIFEST-004359} | Bin 210 -> 210 bytes .../{000064.log => 000080.log} | 0 packs/cantonese-name-generators/CURRENT | 2 +- packs/cantonese-name-generators/LOG | 6 +- packs/cantonese-name-generators/LOG.old | 16 +- .../{MANIFEST-000063 => MANIFEST-000079} | Bin 208 -> 208 bytes packs/fxmastercde/{000045.log => 000061.log} | 0 packs/fxmastercde/CURRENT | 2 +- packs/fxmastercde/LOG | 6 +- packs/fxmastercde/LOG.old | 16 +- .../{MANIFEST-000044 => MANIFEST-000060} | Bin 156 -> 156 bytes packs/macros/{000223.log => 000239.log} | 0 packs/macros/CURRENT | 2 +- packs/macros/LOG | 6 +- packs/macros/LOG.old | 16 +- .../{MANIFEST-000222 => MANIFEST-000238} | Bin 195 -> 195 bytes .../{000965.log => 000981.log} | 0 packs/telecharger-compendiums/CURRENT | 2 +- packs/telecharger-compendiums/LOG | 6 +- packs/telecharger-compendiums/LOG.old | 16 +- .../{MANIFEST-000964 => MANIFEST-000980} | Bin 208 -> 208 bytes src/config/constants.js | 4 + src/data/actors/character.js | 6 +- src/data/actors/npc.js | 4 +- src/data/items/armor.js | 19 + src/data/items/index.js | 4 + src/data/items/ingredient.js | 18 + src/data/items/item.js | 4 - src/data/items/kungfu.js | 8 +- src/data/items/sanhei.js | 27 + src/data/items/spell.js | 6 +- src/data/items/supernatural.js | 4 + src/data/items/weapon.js | 22 + src/migration.js | 22 +- src/system.js | 52 +- src/ui/initiative.js | 173 ++ src/ui/rolling.js | 621 +++++++ src/ui/sheets/actors/base.js | 22 +- src/ui/sheets/actors/character.js | 40 +- src/ui/sheets/actors/npc.js | 19 +- src/ui/sheets/items/armor.js | 12 + src/ui/sheets/items/base.js | 16 +- src/ui/sheets/items/index.js | 4 + src/ui/sheets/items/ingredient.js | 12 + src/ui/sheets/items/item.js | 13 +- src/ui/sheets/items/sanhei.js | 23 + src/ui/sheets/items/supernatural.js | 7 + src/ui/sheets/items/weapon.js | 12 + system.json | 104 +- templates/actor/cde-character-sheet.html | 59 +- templates/actor/cde-loksyu-sheet.html | 154 +- templates/actor/cde-npc-sheet.html | 250 ++- templates/actor/cde-tinji-sheet.html | 40 +- .../actor/parts/cde-character-items.html | 92 + .../actor/parts/cde-character-kungfus.html | 1 + .../actor/parts/cde-character-magics.html | 57 +- .../actor/parts/cde-character-nghang.html | 164 +- .../actor/parts/cde-character-skills.html | 56 +- .../actor/parts/cde-character-treasures.html | 156 +- templates/form/cde-dice-result.html | 556 ++---- templates/form/cde-initiative-prompt-npc.html | 33 + templates/form/cde-initiative-prompt.html | 33 + templates/form/cde-initiative-result.html | 41 + templates/form/cde-magic-dice-prompt.html | 223 +-- templates/form/cde-skill-dice-prompt.html | 141 +- .../form/cde-skill-special-dice-prompt.html | 141 +- templates/form/cde-weapon-dice-prompt.html | 80 + templates/item/cde-armor-sheet.html | 65 + templates/item/cde-ingredient-sheet.html | 68 + templates/item/cde-item-sheet.html | 72 +- templates/item/cde-kungfu-sheet.html | 126 +- templates/item/cde-sanhei-sheet.html | 135 ++ templates/item/cde-spell-sheet.html | 124 +- templates/item/cde-supernatural-sheet.html | 56 +- templates/item/cde-weapon-sheet.html | 94 + 105 files changed, 7362 insertions(+), 2090 deletions(-) create mode 100644 fonts/Averia-Regular.ttf rename packs/aide-pour-fxmaster/{000035.log => 000051.log} (100%) rename packs/aide-pour-fxmaster/{MANIFEST-000034 => MANIFEST-000050} (62%) rename packs/aide-pour-la-lumiere/{000151.log => 000167.log} (100%) rename packs/aide-pour-la-lumiere/{MANIFEST-000150 => MANIFEST-000166} (61%) rename packs/aide-pour-linitiative/{000723.log => 000739.log} (100%) rename packs/aide-pour-linitiative/{MANIFEST-000722 => MANIFEST-000738} (61%) rename packs/aides-pour-les-joueuses/{004344.log => 004360.log} (100%) rename packs/aides-pour-les-joueuses/{MANIFEST-004343 => MANIFEST-004359} (91%) rename packs/cantonese-name-generators/{000064.log => 000080.log} (100%) rename packs/cantonese-name-generators/{MANIFEST-000063 => MANIFEST-000079} (92%) rename packs/fxmastercde/{000045.log => 000061.log} (100%) rename packs/fxmastercde/{MANIFEST-000044 => MANIFEST-000060} (65%) rename packs/macros/{000223.log => 000239.log} (100%) rename packs/macros/{MANIFEST-000222 => MANIFEST-000238} (65%) rename packs/telecharger-compendiums/{000965.log => 000981.log} (100%) rename packs/telecharger-compendiums/{MANIFEST-000964 => MANIFEST-000980} (61%) create mode 100644 src/data/items/armor.js create mode 100644 src/data/items/ingredient.js create mode 100644 src/data/items/sanhei.js create mode 100644 src/data/items/weapon.js create mode 100644 src/ui/initiative.js create mode 100644 src/ui/rolling.js create mode 100644 src/ui/sheets/items/armor.js create mode 100644 src/ui/sheets/items/ingredient.js create mode 100644 src/ui/sheets/items/sanhei.js create mode 100644 src/ui/sheets/items/weapon.js create mode 100644 templates/form/cde-initiative-prompt-npc.html create mode 100644 templates/form/cde-initiative-prompt.html create mode 100644 templates/form/cde-initiative-result.html create mode 100644 templates/form/cde-weapon-dice-prompt.html create mode 100644 templates/item/cde-armor-sheet.html create mode 100644 templates/item/cde-ingredient-sheet.html create mode 100644 templates/item/cde-sanhei-sheet.html create mode 100644 templates/item/cde-weapon-sheet.html diff --git a/.gitignore b/.gitignore index 35228fe..2e4006a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ node_modules/ package-lock.json chroniquesdeletrange.lock +*.pdf diff --git a/CHANGELOG.md b/CHANGELOG.md index 0245760..43bb37e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +3.0.0 +- Refonte complète vers DataModels (FoundryVTT V13) et Application V2 +- Suppression du code legacy (module/) — réécriture totale en src/ +- Pipeline LESS (cde-theme.less → cde-theme.css) via lessc/esbuild +- DataModels pour acteurs : character, npc, tinji, loksyu +- DataModels pour items : item, kungfu, spell, supernatural +- Fiches acteurs et items en ApplicationV2 avec tabs gérés via changeTab +- Suppression de template.json (inutile avec DataModels) +- Déclaration documentTypes dans system.json +- Design Neo-Tokyo Neon Noir sur les fiches items : + * Nouvelle palette : fond #080c14, accents néon par type + * .cde-neon-header avec bande colorée + clip-path angulaire + * .cde-stat-grid style terminal (labels mono uppercase) + * .cde-badge parallélogramme clip-path (par type) + * .cde-neon-tabs avec underline néon animé +- Corrections AppV2 : DEFAULT_OPTIONS sans mergeObject, fix tabs display +- ID système : fvtt-chroniques-de-l-etrange + 2.3.3 - Image monastère titre sans accentuations diff --git a/css/cde-theme.css b/css/cde-theme.css index 4b0a060..33803da 100644 --- a/css/cde-theme.css +++ b/css/cde-theme.css @@ -2,19 +2,15 @@ Fonts ---------------------------------------------*/ @font-face { - font-family: "DeliusUnicaseBold"; - src: url(../fonts/DeliusUnicase-Bold.ttf); -} -@font-face { - font-family: "DeliusUnicase"; - src: url(../fonts/DeliusUnicase-Regular.ttf); + font-family: "Averia"; + src: url(../fonts/Averia-Regular.ttf); } .fvtt-chroniques-de-l-etrange { --cde-bg: #080c14; --cde-surface: #101622; --cde-border: #1a2436; --cde-text: #e2e8f4; - --cde-muted: #5b6b88; + --cde-muted: #7d94b8; --cde-item: #00d4d4; --cde-kungfu: #ff3d5a; --cde-spell: #4a9eff; @@ -25,7 +21,7 @@ .cde-sheet { background: #080c14; color: #e2e8f4; - font-family: "DeliusUnicase", sans-serif; + font-family: "Averia", sans-serif; display: flex; flex-direction: column; width: 100%; @@ -81,6 +77,22 @@ background: #cc44ff; box-shadow: 0 0 10px rgba(204, 68, 255, 0.5); } +.cde-neon-header.weapon::before { + background: #ff6b35; + box-shadow: 0 0 10px rgba(255, 107, 53, 0.5); +} +.cde-neon-header.armor::before { + background: #4ecdc4; + box-shadow: 0 0 10px rgba(78, 205, 196, 0.5); +} +.cde-neon-header.sanhei::before { + background: #cc44ff; + box-shadow: 0 0 10px rgba(204, 68, 255, 0.5); +} +.cde-neon-header.ingredient::before { + background: #98c379; + box-shadow: 0 0 10px rgba(152, 195, 121, 0.5); +} .cde-avatar { width: 90px; height: 90px; @@ -110,7 +122,7 @@ background: transparent; color: #e2e8f4; font-size: 18px; - font-family: "DeliusUnicase", sans-serif; + font-family: "Averia", sans-serif; font-weight: 700; padding: 4px 0 6px; letter-spacing: 0.04em; @@ -130,6 +142,18 @@ .cde-neon-header.supernatural .cde-item-name input:focus { border-bottom-color: #cc44ff; } +.cde-neon-header.weapon .cde-item-name input:focus { + border-bottom-color: #ff6b35; +} +.cde-neon-header.armor .cde-item-name input:focus { + border-bottom-color: #4ecdc4; +} +.cde-neon-header.sanhei .cde-item-name input:focus { + border-bottom-color: #cc44ff; +} +.cde-neon-header.ingredient .cde-item-name input:focus { + border-bottom-color: #98c379; +} .cde-stat-grid { display: flex; flex-wrap: wrap; @@ -146,10 +170,10 @@ } .cde-stat-label { font-size: 10px; - font-family: monospace; + font-family: "Averia", sans-serif; text-transform: uppercase; letter-spacing: 0.1em; - color: #5b6b88; + color: #7d94b8; white-space: nowrap; } .cde-stat-value { @@ -186,6 +210,22 @@ .cde-neon-header.supernatural .cde-stat-cell select:focus { border-bottom-color: #cc44ff; } +.cde-neon-header.weapon .cde-stat-cell input:focus, +.cde-neon-header.weapon .cde-stat-cell select:focus { + border-bottom-color: #ff6b35; +} +.cde-neon-header.armor .cde-stat-cell input:focus, +.cde-neon-header.armor .cde-stat-cell select:focus { + border-bottom-color: #4ecdc4; +} +.cde-neon-header.sanhei .cde-stat-cell input:focus, +.cde-neon-header.sanhei .cde-stat-cell select:focus { + border-bottom-color: #cc44ff; +} +.cde-neon-header.ingredient .cde-stat-cell input:focus, +.cde-neon-header.ingredient .cde-stat-cell select:focus { + border-bottom-color: #98c379; +} .cde-badge { display: inline-flex; align-items: center; @@ -218,6 +258,18 @@ .cde-badge.npc { background: #cc44ff; } +.cde-badge.weapon { + background: #ff6b35; +} +.cde-badge.armor { + background: #4ecdc4; +} +.cde-badge.sanhei { + background: #cc44ff; +} +.cde-badge.ingredient { + background: #98c379; +} .cde-neon-tabs { display: flex; gap: 0; @@ -229,10 +281,10 @@ .cde-neon-tabs .item { padding: 8px 14px; font-size: 11px; - font-family: monospace; + font-family: "Averia", sans-serif; text-transform: uppercase; letter-spacing: 0.1em; - color: #5b6b88; + color: #7d94b8; border-bottom: 2px solid transparent; white-space: nowrap; transition: color 0.15s, border-color 0.15s; @@ -244,19 +296,61 @@ .cde-neon-tabs .item.active { color: #00d4d4; border-bottom-color: #00d4d4; + font-weight: 700; + background: rgba(0, 212, 212, 0.08); } .item.kungfu .cde-neon-tabs .item.active, -form.kungfu .cde-neon-tabs .item.active { +form.kungfu .cde-neon-tabs .item.active, +section.kungfu .cde-neon-tabs .item.active { color: #ff3d5a; border-bottom-color: #ff3d5a; + background: rgba(255, 61, 90, 0.08); } -form.spell .cde-neon-tabs .item.active { +form.spell .cde-neon-tabs .item.active, +section.spell .cde-neon-tabs .item.active { color: #4a9eff; border-bottom-color: #4a9eff; + background: rgba(74, 158, 255, 0.08); } -form.supernatural .cde-neon-tabs .item.active { +form.supernatural .cde-neon-tabs .item.active, +section.supernatural .cde-neon-tabs .item.active { color: #cc44ff; border-bottom-color: #cc44ff; + background: rgba(204, 68, 255, 0.08); +} +form.weapon .cde-neon-tabs .item.active, +section.weapon .cde-neon-tabs .item.active { + color: #ff6b35; + border-bottom-color: #ff6b35; + background: rgba(255, 107, 53, 0.08); +} +form.armor .cde-neon-tabs .item.active, +section.armor .cde-neon-tabs .item.active { + color: #4ecdc4; + border-bottom-color: #4ecdc4; + background: rgba(78, 205, 196, 0.08); +} +form.sanhei .cde-neon-tabs .item.active, +section.sanhei .cde-neon-tabs .item.active { + color: #cc44ff; + border-bottom-color: #cc44ff; + background: rgba(204, 68, 255, 0.08); +} +form.ingredient .cde-neon-tabs .item.active, +section.ingredient .cde-neon-tabs .item.active { + color: #98c379; + border-bottom-color: #98c379; + background: rgba(152, 195, 121, 0.08); +} +section.character .cde-neon-tabs .item.active { + color: #00d4d4; + border-bottom-color: #00d4d4; + background: rgba(0, 212, 212, 0.08); +} +section.npc .cde-neon-tabs .item.active { + color: #cc44ff; + border-bottom-color: #cc44ff; + background: rgba(204, 68, 255, 0.08); } .cde-tab-body { flex: 1 1 0; @@ -272,11 +366,23 @@ form.supernatural .cde-neon-tabs .item.active { display: none; flex-direction: column; gap: 12px; - height: 100%; + min-height: 100%; } .cde-tab-body .tab.active { display: flex; } +.cde-tab-label { + font-family: "Averia", sans-serif; + font-size: 0.65rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.15em; + color: #7d94b8; + padding: 2px 6px; + border-left: 2px solid #263853; + margin-bottom: 2px; + flex-shrink: 0; +} .cde-card { background: #101622; border: 1px solid #1a2436; @@ -285,11 +391,11 @@ form.supernatural .cde-neon-tabs .item.active { box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4); } .cde-card .tab-sous-titre { - font-family: monospace; + font-family: "Averia", sans-serif; font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; - color: #5b6b88; + color: #7d94b8; margin-bottom: 6px; border-bottom: 1px solid #1a2436; padding-bottom: 4px; @@ -357,10 +463,10 @@ form.supernatural .cde-neon-tabs .item.active { } .cde-check-cell label { font-size: 10px; - font-family: monospace; + font-family: "Averia", sans-serif; text-transform: uppercase; letter-spacing: 0.08em; - color: #5b6b88; + color: #7d94b8; } .cde-check-cell input[type="checkbox"] { width: 18px; @@ -380,10 +486,10 @@ form.supernatural .cde-neon-tabs .item.active { } .cde-chip label { font-size: 10px; - font-family: monospace; + font-family: "Averia", sans-serif; letter-spacing: 0.08em; text-transform: uppercase; - color: #5b6b88; + color: #7d94b8; margin: 0; } .cde-chip input, @@ -447,6 +553,18 @@ form.supernatural .cde-neon-tabs .item.active { .cde-pill.npc { background: #cc44ff; } +.cde-pill.weapon { + background: #ff6b35; +} +.cde-pill.armor { + background: #4ecdc4; +} +.cde-pill.sanhei { + background: #cc44ff; +} +.cde-pill.ingredient { + background: #98c379; +} .cde-header { background: #101622; border: 1px solid #1a2436; @@ -471,7 +589,7 @@ form.supernatural .cde-neon-tabs .item.active { background: transparent; color: #e2e8f4; font-size: 20px; - font-family: "DeliusUnicase", sans-serif; + font-family: "Averia", sans-serif; padding: 4px 0 8px; outline: none; } @@ -508,35 +626,97 @@ form.supernatural .cde-neon-tabs .item.active { } .cde-initiative-card { border: 1px solid #1a2436; + border-left: 3px solid #4a9eff; border-radius: 8px; - padding: 10px; + padding: 8px 12px; background: rgba(16, 22, 34, 0.7); box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4); display: inline-flex; flex-direction: column; + gap: 4px; + min-width: 130px; +} +.cde-initiative-header { + display: flex; + align-items: center; gap: 6px; } +.cde-initiative-title { + font-size: 10px; + font-family: "Averia", sans-serif; + text-transform: uppercase; + letter-spacing: 0.08em; + color: #7d94b8; +} +.cde-initiative-icon { + font-size: 11px; + color: #4a9eff; + text-shadow: 0 0 6px rgba(74, 158, 255, 0.7); +} .cde-initiative-controls { display: inline-flex; align-items: center; - gap: 8px; + gap: 6px; } -.cde-initiative-controls img { - width: 30px; - height: 30px; +.cde-initiative-controls .cde-init-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 26px; + height: 26px; + padding: 0; border: 1px solid #1a2436; border-radius: 5px; - background: rgba(8, 12, 20, 0.9); + background: rgba(8, 12, 20, 0.8); + color: #7d94b8; + font-size: 11px; cursor: pointer; + flex-shrink: 0; + transition: border-color 0.15s, box-shadow 0.15s, color 0.15s; } -.cde-initiative-controls img:hover { +.cde-initiative-controls .cde-init-btn:hover { border-color: #4a9eff; + color: #4a9eff; box-shadow: 0 0 0 2px rgba(74, 158, 255, 0.25); } +.cde-initiative-controls .cde-init-btn--roll { + width: 30px; + height: 30px; + font-size: 14px; + border-color: rgba(74, 158, 255, 0.4); + color: #4a9eff; + background: rgba(74, 158, 255, 0.1); + box-shadow: 0 0 6px rgba(74, 158, 255, 0.2); +} +.cde-initiative-controls .cde-init-btn--roll:hover { + background: rgba(74, 158, 255, 0.2); + box-shadow: 0 0 10px rgba(74, 158, 255, 0.4); +} +.cde-initiative-values { + display: flex; + flex-direction: column; + align-items: center; + gap: 2px; + min-width: 50px; +} .cde-initiative-value { - min-width: 28px; - text-align: center; + font-size: 20px; font-weight: 800; + text-align: center; + color: #4a9eff; + text-shadow: 0 0 8px rgba(74, 158, 255, 0.6); + line-height: 1; +} +.cde-anti-initiative-value { + font-size: 9px; + font-family: "Averia", sans-serif; + color: #7d94b8; + text-align: center; + white-space: nowrap; +} +.cde-anti-initiative-value i { + font-size: 8px; + opacity: 0.7; } .cde-grid { display: grid; @@ -552,10 +732,10 @@ form.supernatural .cde-neon-tabs .item.active { display: block; margin-bottom: 4px; font-size: 10px; - font-family: monospace; + font-family: "Averia", sans-serif; text-transform: uppercase; letter-spacing: 0.08em; - color: #5b6b88; + color: #7d94b8; } .cde-field input, .cde-field select, @@ -574,12 +754,12 @@ form.supernatural .cde-neon-tabs .item.active { border-bottom-color: #00d4d4; } .cde-section-title { - font-family: monospace; + font-family: "Averia", sans-serif; font-size: 10px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; - color: #5b6b88; + color: #7d94b8; margin-bottom: 8px; border-bottom: 1px solid #1a2436; padding-bottom: 4px; @@ -595,7 +775,7 @@ form.supernatural .cde-neon-tabs .item.active { text-transform: uppercase; letter-spacing: 0.04em; background: rgba(26, 36, 54, 0.8); - color: #5b6b88; + color: #7d94b8; border: 1px solid #1a2436; } .cde-data-table table { @@ -636,28 +816,421 @@ form.supernatural .cde-neon-tabs .item.active { border: 1px solid #1a2436; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6); } -.loksyu_wrap .schema, -.tinji_wrap .schema { - display: grid; - gap: 12px; - align-items: center; +.cde-aptitudes-table .cde-spec-cell { + flex: 1 1 0; } -.loksyu-visual, -.tinji-visual { +.cde-npc-tracks { + margin-top: 12px; +} +.cde-npc-tracks .cde-track-row { + display: flex; + align-items: center; + gap: 10px; + padding: 8px 0; + border-bottom: 1px solid #1a2436; +} +.cde-npc-tracks .cde-track-row:last-child { + border-bottom: none; +} +.cde-npc-tracks .cde-track-label { + display: flex; + align-items: center; + gap: 6px; + width: 120px; + flex-shrink: 0; + font-size: 11px; + font-family: "Averia", sans-serif; + text-transform: uppercase; + letter-spacing: 0.08em; + color: #7d94b8; +} +.cde-npc-tracks .cde-track-label i { + font-size: 12px; +} +.cde-npc-tracks .cde-track-value { + display: flex; + align-items: center; + gap: 6px; +} +.cde-npc-tracks .cde-track-value input.cde-circle-input { + width: 48px; +} +.cde-npc-tracks .cde-track-sep { + font-size: 14px; + color: #7d94b8; + font-weight: 700; +} +.cde-npc-tracks .cde-track-max { + font-size: 15px; + font-weight: 700; + color: #4a9eff; + text-shadow: 0 0 6px rgba(74, 158, 255, 0.4); + min-width: 28px; + text-align: center; +} +.cde-npc-tracks .cde-track-note { + flex: 1; +} +.cde-npc-tracks .cde-track-note input { + width: 100%; +} +.cde-loksyu-grid { + display: grid; + grid-template-columns: repeat(5, minmax(0, 1fr)); + gap: 12px; + padding: 12px 0; +} +.cde-element-card { + background: #101622; + border: 1px solid #1a2436; + border-radius: 8px; + padding: 10px 8px; + display: flex; + flex-direction: column; + gap: 8px; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4); + transition: border-color 0.15s, box-shadow 0.15s; +} +.cde-element-card:hover { + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6); +} +.cde-element--wood { + border-top: 3px solid #41a436; +} +.cde-element--wood .cde-element-name { + color: #41a436; + text-shadow: 0 0 6px rgba(65, 164, 54, 0.5); +} +.cde-element--wood .cde-element-img { + filter: drop-shadow(0 0 4px #41a436); +} +.cde-element--wood .cde-element-polarity--yang { + border-left: 2px solid rgba(65, 164, 54, 0.7); +} +.cde-element--fire { + border-top: 3px solid #cd171a; +} +.cde-element--fire .cde-element-name { + color: #cd171a; + text-shadow: 0 0 6px rgba(205, 23, 26, 0.5); +} +.cde-element--fire .cde-element-img { + filter: drop-shadow(0 0 4px #cd171a); +} +.cde-element--fire .cde-element-polarity--yang { + border-left: 2px solid rgba(205, 23, 26, 0.7); +} +.cde-element--earth { + border-top: 3px solid #a85747; +} +.cde-element--earth .cde-element-name { + color: #a85747; + text-shadow: 0 0 6px rgba(168, 87, 71, 0.5); +} +.cde-element--earth .cde-element-img { + filter: drop-shadow(0 0 4px #a85747); +} +.cde-element--earth .cde-element-polarity--yang { + border-left: 2px solid rgba(168, 87, 71, 0.7); +} +.cde-element--metal { + border-top: 3px solid #70706e; +} +.cde-element--metal .cde-element-name { + color: #70706e; + text-shadow: 0 0 6px rgba(112, 112, 110, 0.5); +} +.cde-element--metal .cde-element-img { + filter: drop-shadow(0 0 4px #70706e); +} +.cde-element--metal .cde-element-polarity--yang { + border-left: 2px solid rgba(112, 112, 110, 0.7); +} +.cde-element--water { + border-top: 3px solid #009fe2; +} +.cde-element--water .cde-element-name { + color: #009fe2; + text-shadow: 0 0 6px rgba(0, 159, 226, 0.5); +} +.cde-element--water .cde-element-img { + filter: drop-shadow(0 0 4px #009fe2); +} +.cde-element--water .cde-element-polarity--yang { + border-left: 2px solid rgba(0, 159, 226, 0.7); +} +.cde-element--wood .cde-element-polarity input:focus { + border-bottom-color: #41a436; + box-shadow: 0 1px 0 0 #41a436; +} +.cde-element--fire .cde-element-polarity input:focus { + border-bottom-color: #cd171a; + box-shadow: 0 1px 0 0 #cd171a; +} +.cde-element--earth .cde-element-polarity input:focus { + border-bottom-color: #a85747; + box-shadow: 0 1px 0 0 #a85747; +} +.cde-element--metal .cde-element-polarity input:focus { + border-bottom-color: #70706e; + box-shadow: 0 1px 0 0 #70706e; +} +.cde-element--water .cde-element-polarity input:focus { + border-bottom-color: #009fe2; + box-shadow: 0 1px 0 0 #009fe2; +} +.cde-element-header { + display: flex; + flex-direction: column; + align-items: center; + gap: 6px; + text-align: center; +} +.cde-element-img { + width: 36px; + height: 36px; + object-fit: contain; + filter: drop-shadow(0 0 4px var(--el-color)); +} +.cde-element-titles { + display: flex; + flex-direction: column; + gap: 2px; +} +.cde-element-name { + font-family: "Averia", sans-serif; + font-size: 11px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.08em; + color: #7d94b8; + white-space: nowrap; +} +.cde-element-qualities { + font-size: 9px; + color: #7d94b8; + font-style: italic; + line-height: 1.3; + text-align: center; + display: none; +} +.cde-element-values { + display: flex; + flex-direction: column; + gap: 4px; +} +.cde-element-polarity { + display: flex; + align-items: center; + gap: 6px; + padding: 3px 6px; + border-radius: 4px; + background: rgba(8, 12, 20, 0.6); +} +.cde-element-polarity--yin { + border-left: 2px solid rgba(125, 148, 184, 0.4); +} +.cde-polarity-label { + font-size: 9px; + font-family: "Averia", sans-serif; + text-transform: uppercase; + letter-spacing: 0.06em; + color: #7d94b8; + white-space: nowrap; + min-width: 32px; +} +.cde-element-polarity input { + width: 40px; + border: none; + border-bottom: 1px solid #1a2436; + background: transparent; + color: #e2e8f4; + font-size: 14px; + font-weight: 700; + text-align: center; + padding: 2px 0; + outline: none; +} +.cde-loksyu-visual-row { + display: flex; + justify-content: center; + padding-top: 12px; +} +.cde-loksyu-visual-row .loksyu-visual { max-width: 100%; + height: auto; + opacity: 0.7; + border-radius: 8px; + border: 1px solid #1a2436; +} +.cde-tinji-layout { + display: flex; + align-items: center; + justify-content: space-between; + gap: 24px; + padding: 12px; + flex-wrap: wrap; +} +.cde-tinji-main { + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + flex: 1; +} +.cde-tinji-chinese { + font-size: 48px; + color: #cc44ff; + text-shadow: 0 0 20px rgba(204, 68, 255, 0.6); + line-height: 1; + letter-spacing: 0.1em; +} +.cde-tinji-subtitle { + font-family: "Averia", sans-serif; + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.2em; + color: #7d94b8; +} +.cde-tinji-value-wrapper { + display: flex; + align-items: center; + justify-content: center; +} +.cde-tinji-value-wrapper .cde-tinji-input { + width: 80px; + text-align: center; + font-size: 36px; + font-weight: 700; + color: #cc44ff; + text-shadow: 0 0 12px rgba(204, 68, 255, 0.5); + border: none; + border-bottom: 2px solid #cc44ff; + background: transparent; + outline: none; + padding: 4px 0; +} +.cde-tinji-value-wrapper .cde-tinji-input:focus { + border-bottom-color: #e191ff; + box-shadow: 0 2px 0 0 rgba(204, 68, 255, 0.6); +} +.cde-tinji-hint { + font-size: 10px; + font-family: "Averia", sans-serif; + color: #7d94b8; + text-transform: uppercase; + letter-spacing: 0.12em; + text-align: center; +} +.tinji-visual { + max-height: 280px; + max-width: 200px; border-radius: 8px; border: 1px solid #1a2436; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6); } +.cde-weapon-roll-btn { + color: #ff6b35 !important; +} +.cde-weapon-roll-btn:hover { + text-shadow: 0 0 6px rgba(255, 107, 53, 0.6); +} +.cde-item-damage { + color: #ff6b35; + font-weight: 700; +} +.cde-weapon-prompt .cde-weapon-info-bar { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + background: rgba(255, 107, 53, 0.08); + border: 1px solid rgba(255, 107, 53, 0.3); + border-radius: 8px; + margin-bottom: 12px; +} +.cde-weapon-prompt .cde-weapon-info-bar .cde-weapon-aspect-icon { + width: 36px; + height: 36px; + object-fit: contain; +} +.cde-weapon-prompt .cde-weapon-info-bar .cde-weapon-info-text { + flex: 1; + display: flex; + flex-direction: column; + gap: 2px; +} +.cde-weapon-prompt .cde-weapon-info-bar .cde-weapon-info-name { + font-size: 14px; + font-weight: 700; + font-family: "Averia", sans-serif; + color: #e2e8f4; +} +.cde-weapon-prompt .cde-weapon-info-bar .cde-weapon-info-meta { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: #7d94b8; + font-family: "Averia", sans-serif; +} +.cde-weapon-prompt .cde-weapon-info-bar .cde-weapon-info-badge { + font-size: 20px; + color: rgba(255, 107, 53, 0.5); +} +.cde-rr-weapon-damage { + display: flex; + align-items: center; + gap: 10px; + padding: 8px 12px; + background: rgba(255, 107, 53, 0.1); + border-top: 1px solid rgba(255, 107, 53, 0.3); + border-bottom: 1px solid rgba(255, 107, 53, 0.3); + margin: 4px 0; +} +.cde-rr-weapon-damage .cde-rr-weapon-icon { + font-size: 16px; + color: #ff6b35; + text-shadow: 0 0 6px rgba(255, 107, 53, 0.5); + flex-shrink: 0; +} +.cde-rr-weapon-damage .cde-rr-weapon-text { + display: flex; + flex-direction: column; + gap: 2px; +} +.cde-rr-weapon-damage .cde-rr-weapon-name { + font-size: 11px; + font-family: "Averia", sans-serif; + text-transform: uppercase; + letter-spacing: 0.08em; + color: #7d94b8; +} +.cde-rr-weapon-damage .cde-rr-weapon-calc { + font-size: 12px; + color: #e2e8f4; +} +.cde-rr-weapon-damage .cde-rr-weapon-total { + font-size: 16px; + font-weight: 900; + color: #ff6b35; + text-shadow: 0 0 8px rgba(255, 107, 53, 0.6); + margin: 0 2px; +} +.cde-rr-weapon-damage .cde-rr-weapon-unit { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.06em; + color: #7d94b8; +} .cde-tabs { margin-top: 12px; border-bottom: 1px solid #1a2436; } .cde-tabs .item { - color: #5b6b88; + color: #7d94b8; padding: 8px 12px; font-size: 11px; - font-family: monospace; + font-family: "Averia", sans-serif; text-transform: uppercase; letter-spacing: 0.08em; } @@ -694,21 +1267,21 @@ form.supernatural .cde-neon-tabs .item.active { a.compendium-name, a.entry-name, strong.ellipsis { - font-family: "DeliusUnicase"; + font-family: "Averia"; } /* concerne les pages de journaux */ .journal-header input { - font-family: "DeliusUnicase"; + font-family: "Averia"; } .journal-entry-page h1 { - font-family: "DeliusUnicaseBold"; + font-family: "Averia"; text-align: center; color: hsla(249, 66%, 58%, 0.874); border-bottom: 1px solid orange; border-top: 1px solid orange; } .journal-entry-page h2 { - font-family: "DeliusUnicaseBold"; + font-family: "Averia"; color: orange; border-bottom: 0px; border-top: 1px solid orange; @@ -717,7 +1290,7 @@ strong.ellipsis { .journal-entry-page h4, .journal-entry-page h5, .journal-entry-page h6 { - font-family: "DeliusUnicaseBold"; + font-family: "Averia"; color: hsla(249, 66%, 58%, 0.874); border-bottom: 0px; } @@ -733,3 +1306,960 @@ strong.ellipsis { #interface .chat-message .message-header .message-sender { width: 100px; } +.cde-flex-center-text { + display: flex; + justify-content: center; + align-items: center; + text-align: center; +} +.cde-flex-center { + display: flex; + justify-content: center; + align-items: center; +} +.cde-circle-input { + width: 44px !important; + height: 44px !important; + border-radius: 50%; + border: 2px solid #263853; + background: #101622; + color: #e2e8f4; + text-align: center; + font-size: 1.1rem; + font-weight: 700; + padding: 0; + flex-shrink: 0; + display: inline-block !important; + line-height: 40px; + vertical-align: middle; + box-sizing: border-box; +} +.cde-circle-input:focus { + outline: none; + border-color: #00d4d4; + box-shadow: 0 0 8px rgba(0, 212, 212, 0.4); +} +.cde-circle-input.cde-circle-sm { + width: 32px !important; + height: 32px !important; + font-size: 0.85rem; + line-height: 28px; +} +.cde-skills-table { + width: 100%; + border-collapse: collapse; +} +.cde-skills-table tr { + border-bottom: 1px solid #1a2436; +} +.cde-skills-table tr:last-child { + border-bottom: none; +} +.cde-skills-table td { + padding: 3px 4px; + vertical-align: middle; +} +.cde-skills-table td.click, +.cde-skills-table td.noclick { + width: 30px; + min-width: 30px; + text-align: center; + cursor: pointer; +} +.cde-skills-table td.click:hover img, +.cde-skills-table td.noclick:hover img { + filter: drop-shadow(0 0 5px #00d4d4); +} +.cde-skills-table td.noclick { + cursor: default; + opacity: 0.4; +} +.cde-skills-table .cde-skill-label { + white-space: nowrap; + font-size: 0.8rem; + padding-right: 8px; +} +.cde-skills-table .cde-val-cell { + width: 52px; + min-width: 52px; + text-align: center; + padding: 4px; +} +.cde-skills-table .cde-spec-cell { + width: 100%; +} +.cde-skills-table .cde-spec-cell input[type="text"] { + width: 100%; +} +.cde-skills-table .cde-bonus-cell { + white-space: nowrap; + font-family: monospace; + font-size: 0.65rem; + color: #7d94b8; + padding: 0 6px; +} +.cde-skills-table .cde-check-cell { + width: 22px; + text-align: center; +} +.cde-tt-block { + margin-bottom: 12px; +} +.cde-tt-block .cde-tt-row { + display: flex; + align-items: center; + justify-content: center; + gap: 10px; +} +.cde-tt-block .cde-tt-labels { + margin-bottom: 4px; +} +.cde-tt-block .cde-tt-labels span { + width: 52px; + text-align: center; + font-family: "Averia", sans-serif; + font-size: 0.6rem; + text-transform: uppercase; + color: #7d94b8; +} +.cde-tt-block .cde-tt-labels .cde-tt-center { + width: 44px; +} +.cde-tt-block .cde-tt-yinyang { + width: 44px; + height: 44px; + opacity: 0.8; +} +.cde-tt-sanzing { + margin-bottom: 12px; +} +.cde-tt-sanzing .cde-tt-sz-header, +.cde-tt-sanzing .cde-tt-sz-row { + display: grid; + grid-template-columns: 36px 48px 1fr 48px 36px; + align-items: center; + gap: 6px; + padding: 4px 8px; +} +.cde-tt-sanzing .cde-tt-sz-header { + font-family: "Averia", sans-serif; + font-size: 0.6rem; + text-transform: uppercase; + color: #7d94b8; + text-align: center; +} +.cde-tt-sanzing .cde-tt-sz-row { + border-top: 1px solid #1a2436; +} +.cde-tt-sanzing .cde-tt-sz-row .cde-circle-input { + justify-self: center; +} +.cde-tt-sanzing .cde-tt-level { + text-align: center; + font-family: monospace; + font-size: 0.75rem; + font-weight: 700; + color: #7d94b8; +} +.cde-aspects-header { + display: flex; + justify-content: center; + margin-bottom: 10px; +} +.cde-aspects-header .cde-aspects-logo { + max-height: 48px; + opacity: 0.7; +} +.cde-aspects-grid { + display: flex; + flex-wrap: wrap; + gap: 8px; + justify-content: center; + margin-bottom: 12px; +} +.cde-aspect-card { + display: flex; + flex-direction: column; + align-items: center; + gap: 6px; + padding: 10px 8px; + border-radius: 4px; + background: #101622; + border: 1px solid #1a2436; + min-width: 88px; + flex: 1 1 88px; + max-width: 120px; +} +.cde-aspect-card .cde-aspect-top { + display: flex; + flex-direction: column; + align-items: center; + gap: 3px; +} +.cde-aspect-card .cde-aspect-gif { + width: 36px; + height: 36px; +} +.cde-aspect-card .cde-aspect-name { + font-family: "Averia"; + font-size: 0.8rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.08em; +} +.cde-aspect-card .cde-aspect-roll { + display: flex; + align-items: center; + gap: 6px; +} +.cde-aspect-card .cde-aspect-roll .cde-roll-trigger { + cursor: pointer; + display: flex; + align-items: center; +} +.cde-aspect-card .cde-aspect-roll .cde-roll-trigger:hover img { + filter: drop-shadow(0 0 5px currentColor); +} +.cde-aspect-card .cde-aspect-qual { + font-size: 0.6rem; + color: #7d94b8; + text-align: center; + line-height: 1.3; +} +.cde-aspect-card.cde-aspect--fire { + border-color: #ff3d5a; +} +.cde-aspect-card.cde-aspect--fire .cde-aspect-name { + color: #ff3d5a; +} +.cde-aspect-card.cde-aspect--fire .cde-circle-input:focus { + border-color: #ff3d5a; + box-shadow: 0 0 6px #ff3d5a; +} +.cde-aspect-card.cde-aspect--wood { + border-color: #44bb44; +} +.cde-aspect-card.cde-aspect--wood .cde-aspect-name { + color: #55cc55; +} +.cde-aspect-card.cde-aspect--wood .cde-circle-input:focus { + border-color: #55cc55; + box-shadow: 0 0 6px #55cc55; +} +.cde-aspect-card.cde-aspect--earth { + border-color: #aa7722; +} +.cde-aspect-card.cde-aspect--earth .cde-aspect-name { + color: #cc9933; +} +.cde-aspect-card.cde-aspect--earth .cde-circle-input:focus { + border-color: #cc9933; + box-shadow: 0 0 6px #cc9933; +} +.cde-aspect-card.cde-aspect--water { + border-color: #4a9eff; +} +.cde-aspect-card.cde-aspect--water .cde-aspect-name { + color: #4a9eff; +} +.cde-aspect-card.cde-aspect--water .cde-circle-input:focus { + border-color: #4a9eff; + box-shadow: 0 0 6px #4a9eff; +} +.cde-aspect-card.cde-aspect--metal { + border-color: #7d94b8; +} +.cde-aspect-card.cde-aspect--metal .cde-aspect-name { + color: #e2e8f4; +} +.cde-aspect-card.cde-aspect--metal .cde-circle-input:focus { + border-color: #00d4d4; + box-shadow: 0 0 6px #00d4d4; +} +.cde-nghang-diagram { + display: flex; + justify-content: center; + margin-top: 8px; +} +.cde-nghang-diagram img { + max-width: 100%; + max-height: 180px; + opacity: 0.45; + border-radius: 4px; +} +.img-die-sm { + width: 27px !important; + height: 27px !important; + flex-shrink: 0; +} +.cde-magics-table td.image { + width: 2.2%; +} +.cde-magics-table td.image.td-die { + width: 2%; +} +.cde-magics-table td.value { + width: 25%; +} +.cde-magics-table td.td-spacer { + width: 2.2%; +} +.chancethrow { + display: flex; + justify-content: center; + align-items: center; +} +.cde-item-group-label { + font-family: "Averia", sans-serif; + font-size: 0.65rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.15em; + color: #7d94b8; + padding: 2px 6px; + border-left: 2px solid #263853; + margin: 8px 0 2px; + flex-shrink: 0; +} +ol.item-list { + list-style: none; + margin: 0 0 4px; + padding: 0; +} +ol.item-list li.item { + display: flex; + align-items: center; + gap: 8px; + padding: 3px 6px; + border-radius: 4px; + background: #101622; + border: 1px solid #1a2436; + margin-bottom: 2px; +} +ol.item-list li.item img { + border: none; + border-radius: 3px; + flex-shrink: 0; +} +ol.item-list li.item h4.item-name { + flex: 1 1 0; + margin: 0; + font-size: 13px; + color: #e2e8f4; +} +ol.item-list li.item .cde-item-stat { + font-family: monospace; + font-size: 11px; + color: #7d94b8; +} +ol.item-list li.item .item-controls { + display: flex; + gap: 4px; + flex-shrink: 0; +} +ol.item-list li.item .item-controls a.item-control { + color: #7d94b8; +} +ol.item-list li.item .item-controls a.item-control:hover { + color: #e2e8f4; +} +.cde-roll-prompt { + background: #080c14; + color: #e2e8f4; + font-family: "Averia", sans-serif; + padding: 12px 14px; +} +.cde-roll-prompt.cde-roll-prompt--magic { + min-width: 340px; +} +.cde-roll-prompt .cde-roll-header { + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: 8px; + margin-bottom: 10px; + border-bottom: 1px solid #1a2436; +} +.cde-roll-prompt .cde-roll-title { + font-size: 13px; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + color: #e2e8f4; +} +.cde-roll-prompt .cde-roll-dice-count { + font-size: 36px; + font-weight: 900; + color: #00d4d4; + line-height: 1; + text-align: center; + margin: 4px 0 8px; + text-shadow: 0 0 12px rgba(0, 212, 212, 0.6); +} +.cde-roll-prompt .cde-roll-dice-count .cde-roll-dice-label { + font-size: 14px; + font-weight: 600; + color: #7d94b8; + margin-left: 4px; +} +.cde-roll-prompt .cde-roll-section { + margin-bottom: 8px; +} +.cde-roll-prompt .cde-roll-section.cde-roll-section--separator { + padding-bottom: 10px; + margin-bottom: 10px; + border-bottom: 1px dashed #1a2436; +} +.cde-roll-prompt .cde-roll-section-title { + font-size: 11px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.1em; + color: #7d94b8; + margin: 0 0 6px; +} +.cde-roll-prompt .cde-roll-fields { + display: flex; + flex-direction: column; + gap: 5px; +} +.cde-roll-prompt .cde-roll-field { + display: flex; + align-items: center; + gap: 8px; +} +.cde-roll-prompt .cde-roll-field label { + flex: 0 0 160px; + font-size: 11px; + color: #7d94b8; + text-transform: uppercase; + letter-spacing: 0.05em; +} +.cde-roll-prompt .cde-roll-field select, +.cde-roll-prompt .cde-roll-field .cde-roll-input { + flex: 1; + background: #101622; + border: none; + border-bottom: 1px solid #1a2436; + color: #e2e8f4; + font-family: monospace; + font-size: 13px; + padding: 3px 6px; + border-radius: 2px; +} +.cde-roll-prompt .cde-roll-field select:focus, +.cde-roll-prompt .cde-roll-field .cde-roll-input:focus { + outline: none; + border-bottom-color: #00d4d4; + box-shadow: 0 1px 0 0 #00d4d4; +} +.cde-roll-prompt .cde-roll-field select option { + background: #101622; + color: #e2e8f4; +} +.cde-roll-prompt .cde-roll-hint { + font-size: 10px; + color: #7d94b8; + margin: 4px 0 0; + font-style: italic; +} +[data-aspect="wood"] { + --rr-accent: #41a436; + --rr-accent-bg: rgba(65, 164, 54, 0.12); +} +[data-aspect="wood"] .cde-rr-row--auspicious { + --rr-color: #cd171a; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png); +} +[data-aspect="wood"] .cde-rr-row--noxious { + --rr-color: #009fe2; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png); +} +[data-aspect="wood"] .cde-rr-row--loksyu { + --rr-color: #a85747; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png); +} +[data-aspect="wood"] .cde-rr-row--tinji { + --rr-color: #70706e; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png); +} +[data-aspect="fire"] { + --rr-accent: #cd171a; + --rr-accent-bg: rgba(205, 23, 26, 0.12); +} +[data-aspect="fire"] .cde-rr-row--auspicious { + --rr-color: #a85747; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png); +} +[data-aspect="fire"] .cde-rr-row--noxious { + --rr-color: #41a436; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png); +} +[data-aspect="fire"] .cde-rr-row--loksyu { + --rr-color: #70706e; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png); +} +[data-aspect="fire"] .cde-rr-row--tinji { + --rr-color: #009fe2; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png); +} +[data-aspect="earth"] { + --rr-accent: #a85747; + --rr-accent-bg: rgba(168, 87, 71, 0.12); +} +[data-aspect="earth"] .cde-rr-row--auspicious { + --rr-color: #70706e; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png); +} +[data-aspect="earth"] .cde-rr-row--noxious { + --rr-color: #cd171a; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png); +} +[data-aspect="earth"] .cde-rr-row--loksyu { + --rr-color: #009fe2; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png); +} +[data-aspect="earth"] .cde-rr-row--tinji { + --rr-color: #41a436; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png); +} +[data-aspect="metal"] { + --rr-accent: #70706e; + --rr-accent-bg: rgba(112, 112, 110, 0.16); +} +[data-aspect="metal"] .cde-rr-row--auspicious { + --rr-color: #009fe2; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png); +} +[data-aspect="metal"] .cde-rr-row--noxious { + --rr-color: #a85747; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png); +} +[data-aspect="metal"] .cde-rr-row--loksyu { + --rr-color: #41a436; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png); +} +[data-aspect="metal"] .cde-rr-row--tinji { + --rr-color: #cd171a; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png); +} +[data-aspect="water"] { + --rr-accent: #009fe2; + --rr-accent-bg: rgba(0, 159, 226, 0.12); +} +[data-aspect="water"] .cde-rr-row--auspicious { + --rr-color: #41a436; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png); +} +[data-aspect="water"] .cde-rr-row--noxious { + --rr-color: #70706e; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png); +} +[data-aspect="water"] .cde-rr-row--loksyu { + --rr-color: #cd171a; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png); +} +[data-aspect="water"] .cde-rr-row--tinji { + --rr-color: #a85747; + --rr-icon: url(/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png); +} +.cde-roll-result { + background: #080c14; + color: #e2e8f4; + font-family: 'Share Tech Mono', monospace; + border-radius: 4px; + border: 1px solid #1a2436; + overflow: hidden; +} +.cde-roll-result .cde-rr-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 12px; + background: var(--rr-accent-bg, rgba(16, 22, 34, 0.8)); + border-left: 4px solid var(--rr-accent, #1a2436); + border-bottom: 1px solid #1a2436; + gap: 8px; +} +.cde-roll-result .cde-rr-header .cde-rr-header-left { + display: flex; + align-items: center; + gap: 10px; + flex: 1; +} +.cde-roll-result .cde-rr-header .cde-rr-aspect-icon { + width: 32px; + height: 32px; + object-fit: contain; + filter: drop-shadow(0 0 4px var(--rr-accent, #1a2436)); + border: none; +} +.cde-roll-result .cde-rr-header .cde-rr-header-text { + display: flex; + flex-direction: column; +} +.cde-roll-result .cde-rr-header .cde-rr-aspect-label { + font-size: 11px; + font-weight: 900; + text-transform: uppercase; + letter-spacing: 0.12em; + color: var(--rr-accent, #e2e8f4); + text-shadow: 0 0 6px var(--rr-accent, transparent); +} +.cde-roll-result .cde-rr-header .cde-rr-roll-label { + font-size: 13px; + font-weight: 600; + color: #e2e8f4; +} +.cde-roll-result .cde-rr-header .cde-rr-header-right { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 2px; +} +.cde-roll-result .cde-rr-header .cde-rr-actor-avatar { + width: 28px; + height: 28px; + border-radius: 50%; + border: 1px solid var(--rr-accent, #1a2436); + object-fit: cover; +} +.cde-roll-result .cde-rr-header .cde-rr-actor-name { + font-size: 9px; + color: #7d94b8; + text-transform: uppercase; + letter-spacing: 0.05em; +} +.cde-roll-result .cde-rr-hero { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 16px; + background: rgba(16, 22, 34, 0.4); +} +.cde-roll-result .cde-rr-hero .cde-rr-hero-count { + font-size: 48px; + font-weight: 900; + line-height: 1; + color: var(--rr-accent, #e2e8f4); + text-shadow: 0 0 16px var(--rr-accent, transparent), 0 0 32px var(--rr-accent, transparent); +} +.cde-roll-result .cde-rr-hero .cde-rr-hero-right { + display: flex; + flex-direction: column; +} +.cde-roll-result .cde-rr-hero .cde-rr-hero-label { + font-size: 11px; + font-weight: 900; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--rr-accent, #e2e8f4); +} +.cde-roll-result .cde-rr-hero .cde-rr-hero-dice { + font-size: 13px; + color: #7d94b8; + margin-top: 2px; +} +.cde-roll-result .cde-rr-hero .cde-rr-hero-dice-label { + font-size: 10px; +} +.cde-roll-result .cde-rr-hero .cde-rr-spell-power { + margin-left: auto; + display: flex; + flex-direction: column; + align-items: flex-end; + border-left: 2px solid var(--rr-accent, #1a2436); + padding-left: 10px; +} +.cde-roll-result .cde-rr-hero .cde-rr-spell-power .cde-rr-spell-power-count { + font-size: 32px; + font-weight: 900; + line-height: 1; + 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-label { + font-size: 9px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.1em; + color: #7d94b8; +} +.cde-roll-result .cde-rr-details { + display: flex; + flex-direction: column; + gap: 2px; + padding: 6px 10px; +} +.cde-roll-result .cde-rr-row { + display: flex; + align-items: center; + gap: 8px; + padding: 3px 6px; + border-radius: 3px; + background: rgba(16, 22, 34, 0.6); + color: var(--rr-color, #7d94b8); +} +.cde-roll-result .cde-rr-row .cde-rr-count { + font-size: 18px; + font-weight: 900; + line-height: 1; + min-width: 26px; + text-align: center; + text-shadow: 0 0 6px currentColor; +} +.cde-roll-result .cde-rr-row .cde-rr-icon { + width: 22px; + height: 22px; + background-image: var(--rr-icon); + background-size: contain; + background-repeat: no-repeat; + background-position: center; + flex-shrink: 0; + opacity: 0.85; +} +.cde-roll-result .cde-rr-row .cde-rr-label { + font-size: 10px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.07em; + flex: 1; +} +.cde-roll-result .cde-rr-row .cde-rr-partition { + font-size: 9px; + color: #7d94b8; + margin-left: 4px; +} +.cde-roll-result .cde-rr-footer { + padding: 5px 12px; + border-top: 1px solid #1a2436; + background: rgba(16, 22, 34, 0.3); + display: flex; + align-items: baseline; + gap: 6px; +} +.cde-roll-result .cde-rr-footer .cde-rr-footer-label { + font-size: 9px; + font-weight: 700; + text-transform: uppercase; + color: #7d94b8; + letter-spacing: 0.08em; +} +.cde-roll-result .cde-rr-footer .cde-rr-footer-text { + font-size: 10px; + color: #7d94b8; + font-family: "Averia", sans-serif; +} +.cde-roll-result .cde-dice-grid { + display: grid; + grid-template-columns: repeat(10, 1fr); + gap: 3px; + padding: 8px 8px 6px; + border-top: 1px solid #1a2436; +} +.cde-roll-result .cde-dice-grid .cde-dice-cell { + display: flex; + flex-direction: column; + align-items: center; + gap: 1px; +} +.cde-roll-result .cde-dice-grid .cde-dice-cell .cde-dice-count { + font-size: 12px; + font-weight: 700; + color: #e2e8f4; + line-height: 1; +} +.cde-roll-result .cde-dice-grid .cde-dice-cell .cde-dice-plate { + width: 100%; + border: none; + opacity: 0.65; +} +.cde-initiative-prompt .cde-roll-field { + flex-direction: column; + align-items: stretch; + gap: 4px; +} +.cde-initiative-prompt .cde-roll-field label { + flex: none; + font-size: 10px; + color: #7d94b8; + text-transform: uppercase; + letter-spacing: 0.05em; +} +.cde-initiative-prompt .cde-roll-field select, +.cde-initiative-prompt .cde-roll-field .cde-roll-input { + flex: none; + width: 100%; +} +.cde-initiative-prompt .cde-initiative-base-row { + display: flex; + align-items: flex-end; + gap: 10px; + flex-wrap: nowrap; +} +.cde-initiative-prompt .cde-initiative-base-field { + flex-shrink: 0; + min-width: 70px; +} +.cde-initiative-prompt .cde-initiative-base-value { + display: block; + font-size: 22px; + font-weight: 800; + color: #4a9eff; + text-shadow: 0 0 8px rgba(74, 158, 255, 0.5); + text-align: center; + line-height: 1; + padding: 4px 0; +} +.cde-initiative-prompt .cde-initiative-op { + font-size: 18px; + font-weight: 700; + color: #7d94b8; + padding-bottom: 6px; + flex-shrink: 0; + align-self: flex-end; +} +.cde-initiative-prompt .cde-initiative-action-field { + flex: 1; + min-width: 0; +} +.cde-initiative-prompt .cde-initiative-select { + width: 100%; +} +.cde-initiative-prompt .cde-initiative-hint { + font-size: 10px; + font-family: "Averia", sans-serif; + color: #7d94b8; + text-align: center; + letter-spacing: 0.05em; + padding: 4px 0 0; + border-top: 1px solid #1a2436; + margin-top: 4px; +} +.cde-initiative-prompt .cde-initiative-icon { + font-size: 20px; + color: #4a9eff; +} +.cde-initiative-result { + background: #101622; + border: 1px solid #1a2436; + border-left: 4px solid #4a9eff; + border-radius: 8px; + overflow: hidden; + color: #e2e8f4; +} +.cde-initiative-result .cde-ir-header { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + background: rgba(74, 158, 255, 0.08); + border-bottom: 1px solid #1a2436; +} +.cde-initiative-result .cde-ir-avatar { + width: 36px; + height: 36px; + border-radius: 50%; + border: 2px solid #1a2436; + object-fit: cover; + flex-shrink: 0; +} +.cde-initiative-result .cde-ir-actor-info { + display: flex; + flex-direction: column; + gap: 2px; +} +.cde-initiative-result .cde-ir-actor-name { + font-size: 13px; + font-weight: 700; + color: #e2e8f4; +} +.cde-initiative-result .cde-ir-roll-label { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: #7d94b8; + font-family: "Averia", sans-serif; +} +.cde-initiative-result .cde-ir-formula { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + gap: 5px; + padding: 8px 12px; + background: rgba(8, 12, 20, 0.6); + border-bottom: 1px solid #1a2436; + font-family: monospace; + font-size: 12px; +} +.cde-initiative-result .cde-ir-formula-base { + color: #7d94b8; + font-size: 11px; +} +.cde-initiative-result .cde-ir-formula-val { + font-weight: 700; + color: #e2e8f4; + font-size: 13px; +} +.cde-initiative-result .cde-ir-formula-mod { + color: #ff3d5a; +} +.cde-initiative-result .cde-ir-formula-sep { + color: #7d94b8; +} +.cde-initiative-result .cde-ir-formula-eq { + color: #7d94b8; + font-size: 14px; +} +.cde-initiative-result .cde-ir-formula-total { + font-size: 16px; + font-weight: 800; + color: #4a9eff; + text-shadow: 0 0 6px rgba(74, 158, 255, 0.5); +} +.cde-initiative-result .cde-ir-hero { + display: flex; + align-items: center; + justify-content: center; + gap: 14px; + padding: 14px 12px; +} +.cde-initiative-result .cde-ir-init-value { + font-size: 48px; + font-weight: 900; + color: #4a9eff; + text-shadow: 0 0 12px rgba(74, 158, 255, 0.7), 0 0 24px rgba(74, 158, 255, 0.35); + line-height: 1; + font-family: 'Averia Regular', sans-serif; +} +.cde-initiative-result .cde-ir-hero-right { + display: flex; + flex-direction: column; + gap: 4px; +} +.cde-initiative-result .cde-ir-init-label { + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: #7d94b8; + font-family: "Averia", sans-serif; +} +.cde-initiative-result .cde-ir-anti { + display: flex; + gap: 5px; + align-items: baseline; +} +.cde-initiative-result .cde-ir-anti-label { + font-size: 10px; + color: #7d94b8; + font-family: "Averia", sans-serif; + text-transform: uppercase; + letter-spacing: 0.05em; +} +.cde-initiative-result .cde-ir-anti-value { + font-size: 14px; + font-weight: 700; + color: #ff3d5a; + text-shadow: 0 0 5px rgba(255, 61, 90, 0.4); +} diff --git a/css/cde-theme.less b/css/cde-theme.less index c184f63..a7cc157 100644 --- a/css/cde-theme.less +++ b/css/cde-theme.less @@ -4,13 +4,8 @@ ---------------------------------------------*/ @font-face { - font-family: "DeliusUnicaseBold"; - src: url(../fonts/DeliusUnicase-Bold.ttf); -} - -@font-face { - font-family: "DeliusUnicase"; - src: url(../fonts/DeliusUnicase-Regular.ttf); + font-family: "Averia"; + src: url(../fonts/Averia-Regular.ttf); } // ============================================================ @@ -22,13 +17,17 @@ @cde-border: #1a2436; @cde-border-hi: #263853; @cde-text: #e2e8f4; -@cde-muted: #5b6b88; +@cde-muted: #7d94b8; // Accents néon par type @cde-item: #00d4d4; @cde-kungfu: #ff3d5a; @cde-spell: #4a9eff; @cde-supernatural: #cc44ff; +@cde-weapon: #ff6b35; +@cde-armor: #4ecdc4; +@cde-sanhei: #cc44ff; +@cde-ingredient: #98c379; @cde-shadow: 0 8px 32px rgba(0, 0, 0, 0.6); @cde-shadow-sm: 0 2px 12px rgba(0, 0, 0, 0.4); @@ -63,7 +62,7 @@ .cde-sheet { background: @cde-bg; color: @cde-text; - font-family: "DeliusUnicase", sans-serif; + font-family: "Averia", sans-serif; display: flex; flex-direction: column; width: 100%; @@ -116,6 +115,10 @@ &.kungfu { &::before { background: @cde-kungfu; box-shadow: 0 0 10px fade(@cde-kungfu, 50%); } } &.spell { &::before { background: @cde-spell; box-shadow: 0 0 10px fade(@cde-spell, 50%); } } &.supernatural { &::before { background: @cde-supernatural; box-shadow: 0 0 10px fade(@cde-supernatural, 50%); } } + &.weapon { &::before { background: @cde-weapon; box-shadow: 0 0 10px fade(@cde-weapon, 50%); } } + &.armor { &::before { background: @cde-armor; box-shadow: 0 0 10px fade(@cde-armor, 50%); } } + &.sanhei { &::before { background: @cde-sanhei; box-shadow: 0 0 10px fade(@cde-sanhei, 50%); } } + &.ingredient { &::before { background: @cde-ingredient; box-shadow: 0 0 10px fade(@cde-ingredient, 50%); } } } // Avatar inside neon header — angular clip @@ -152,7 +155,7 @@ background: transparent; color: @cde-text; font-size: 18px; - font-family: "DeliusUnicase", sans-serif; + font-family: "Averia", sans-serif; font-weight: 700; padding: 4px 0 6px; letter-spacing: 0.04em; @@ -170,6 +173,10 @@ .cde-neon-header.kungfu .cde-item-name input:focus { border-bottom-color: @cde-kungfu; } .cde-neon-header.spell .cde-item-name input:focus { border-bottom-color: @cde-spell; } .cde-neon-header.supernatural .cde-item-name input:focus { border-bottom-color: @cde-supernatural; } +.cde-neon-header.weapon .cde-item-name input:focus { border-bottom-color: @cde-weapon; } +.cde-neon-header.armor .cde-item-name input:focus { border-bottom-color: @cde-armor; } +.cde-neon-header.sanhei .cde-item-name input:focus { border-bottom-color: @cde-sanhei; } +.cde-neon-header.ingredient .cde-item-name input:focus { border-bottom-color: @cde-ingredient; } // ============================================================ // Stat Grid (terminal style) @@ -192,7 +199,7 @@ .cde-stat-label { font-size: 10px; - font-family: monospace; + font-family: "Averia", sans-serif; text-transform: uppercase; letter-spacing: 0.1em; color: @cde-muted; @@ -229,6 +236,14 @@ .cde-neon-header.spell .cde-stat-cell select:focus { border-bottom-color: @cde-spell; } .cde-neon-header.supernatural .cde-stat-cell input:focus, .cde-neon-header.supernatural .cde-stat-cell select:focus { border-bottom-color: @cde-supernatural; } +.cde-neon-header.weapon .cde-stat-cell input:focus, +.cde-neon-header.weapon .cde-stat-cell select:focus { border-bottom-color: @cde-weapon; } +.cde-neon-header.armor .cde-stat-cell input:focus, +.cde-neon-header.armor .cde-stat-cell select:focus { border-bottom-color: @cde-armor; } +.cde-neon-header.sanhei .cde-stat-cell input:focus, +.cde-neon-header.sanhei .cde-stat-cell select:focus { border-bottom-color: @cde-sanhei; } +.cde-neon-header.ingredient .cde-stat-cell input:focus, +.cde-neon-header.ingredient .cde-stat-cell select:focus { border-bottom-color: @cde-ingredient; } // ============================================================ // Type Badge — angular clip-path parallelogram @@ -253,6 +268,10 @@ &.supernatural { background: @cde-supernatural; } &.character { background: @cde-item; } &.npc { background: @cde-supernatural; } + &.weapon { background: @cde-weapon; } + &.armor { background: @cde-armor; } + &.sanhei { background: @cde-sanhei; } + &.ingredient { background: @cde-ingredient; } } // ============================================================ @@ -269,7 +288,7 @@ .item { padding: 8px 14px; font-size: 11px; - font-family: monospace; + font-family: "Averia", sans-serif; text-transform: uppercase; letter-spacing: 0.1em; color: @cde-muted; @@ -285,15 +304,31 @@ &.active { color: @cde-item; border-bottom-color: @cde-item; + font-weight: 700; + background: fade(@cde-item, 8%); } } } // Per-type active tab color .item.kungfu .cde-neon-tabs .item.active, -form.kungfu .cde-neon-tabs .item.active { color: @cde-kungfu; border-bottom-color: @cde-kungfu; } -form.spell .cde-neon-tabs .item.active { color: @cde-spell; border-bottom-color: @cde-spell; } -form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; border-bottom-color: @cde-supernatural; } +form.kungfu .cde-neon-tabs .item.active, +section.kungfu .cde-neon-tabs .item.active { color: @cde-kungfu; border-bottom-color: @cde-kungfu; background: fade(@cde-kungfu, 8%); } +form.spell .cde-neon-tabs .item.active, +section.spell .cde-neon-tabs .item.active { color: @cde-spell; border-bottom-color: @cde-spell; background: fade(@cde-spell, 8%); } +form.supernatural .cde-neon-tabs .item.active, +section.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; border-bottom-color: @cde-supernatural; background: fade(@cde-supernatural, 8%); } +form.weapon .cde-neon-tabs .item.active, +section.weapon .cde-neon-tabs .item.active { color: @cde-weapon; border-bottom-color: @cde-weapon; background: fade(@cde-weapon, 8%); } +form.armor .cde-neon-tabs .item.active, +section.armor .cde-neon-tabs .item.active { color: @cde-armor; border-bottom-color: @cde-armor; background: fade(@cde-armor, 8%); } +form.sanhei .cde-neon-tabs .item.active, +section.sanhei .cde-neon-tabs .item.active { color: @cde-sanhei; border-bottom-color: @cde-sanhei; background: fade(@cde-sanhei, 8%); } +form.ingredient .cde-neon-tabs .item.active, +section.ingredient .cde-neon-tabs .item.active { color: @cde-ingredient; border-bottom-color: @cde-ingredient; background: fade(@cde-ingredient, 8%); } +// Actor type accent colors +section.character .cde-neon-tabs .item.active { color: @cde-item; border-bottom-color: @cde-item; background: fade(@cde-item, 8%); } +section.npc .cde-neon-tabs .item.active { color: @cde-supernatural; border-bottom-color: @cde-supernatural; background: fade(@cde-supernatural, 8%); } // ============================================================ // Tab body @@ -312,7 +347,7 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde display: none; flex-direction: column; gap: @cde-gap; - height: 100%; + min-height: 100%; } .tab.active { @@ -320,6 +355,20 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde } } +// Tab section label — visible inside each tab body +.cde-tab-label { + font-family: "Averia", sans-serif; + font-size: 0.65rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.15em; + color: @cde-muted; + padding: 2px 6px; + border-left: 2px solid @cde-border-hi; + margin-bottom: 2px; + flex-shrink: 0; +} + // ============================================================ // Card // ============================================================ @@ -332,7 +381,7 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde } .cde-card .tab-sous-titre { - font-family: monospace; + font-family: "Averia", sans-serif; font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; @@ -419,7 +468,7 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde label { font-size: 10px; - font-family: monospace; + font-family: "Averia", sans-serif; text-transform: uppercase; letter-spacing: 0.08em; color: @cde-muted; @@ -448,7 +497,7 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde label { font-size: 10px; - font-family: monospace; + font-family: "Averia", sans-serif; letter-spacing: 0.08em; text-transform: uppercase; color: @cde-muted; @@ -503,6 +552,10 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde &.supernatural { background: @cde-supernatural; } &.character { background: @cde-item; } &.npc { background: @cde-supernatural; } + &.weapon { background: @cde-weapon; } + &.armor { background: @cde-armor; } + &.sanhei { background: @cde-sanhei; } + &.ingredient { background: @cde-ingredient; } } // ============================================================ @@ -533,7 +586,7 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde background: transparent; color: @cde-text; font-size: 20px; - font-family: "DeliusUnicase", sans-serif; + font-family: "Averia", sans-serif; padding: 4px 0 8px; outline: none; @@ -574,39 +627,109 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde .cde-initiative-card { border: 1px solid @cde-border; + border-left: 3px solid @cde-spell; border-radius: @cde-radius; - padding: 10px; + padding: 8px 12px; background: fade(@cde-surface, 70%); box-shadow: @cde-shadow-sm; display: inline-flex; flex-direction: column; + gap: 4px; + min-width: 130px; +} + +.cde-initiative-header { + display: flex; + align-items: center; gap: 6px; } +.cde-initiative-title { + font-size: 10px; + font-family: "Averia", sans-serif; + text-transform: uppercase; + letter-spacing: 0.08em; + color: @cde-muted; +} + +.cde-initiative-icon { + font-size: 11px; + color: @cde-spell; + text-shadow: 0 0 6px fade(@cde-spell, 70%); +} + .cde-initiative-controls { display: inline-flex; align-items: center; - gap: 8px; + gap: 6px; - img { - width: 30px; - height: 30px; + .cde-init-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 26px; + height: 26px; + padding: 0; border: 1px solid @cde-border; border-radius: 5px; - background: fade(@cde-bg, 90%); + background: fade(@cde-bg, 80%); + color: @cde-muted; + font-size: 11px; cursor: pointer; + flex-shrink: 0; + transition: border-color 0.15s, box-shadow 0.15s, color 0.15s; &:hover { border-color: @cde-spell; + color: @cde-spell; box-shadow: 0 0 0 2px fade(@cde-spell, 25%); } } + + .cde-init-btn--roll { + width: 30px; + height: 30px; + font-size: 14px; + border-color: fade(@cde-spell, 40%); + color: @cde-spell; + background: fade(@cde-spell, 10%); + box-shadow: 0 0 6px fade(@cde-spell, 20%); + + &:hover { + background: fade(@cde-spell, 20%); + box-shadow: 0 0 10px fade(@cde-spell, 40%); + } + } +} + +.cde-initiative-values { + display: flex; + flex-direction: column; + align-items: center; + gap: 2px; + min-width: 50px; } .cde-initiative-value { - min-width: 28px; - text-align: center; + font-size: 20px; font-weight: 800; + text-align: center; + color: @cde-spell; + text-shadow: 0 0 8px fade(@cde-spell, 60%); + line-height: 1; +} + +.cde-anti-initiative-value { + font-size: 9px; + font-family: "Averia", sans-serif; + color: @cde-muted; + text-align: center; + white-space: nowrap; + + i { + font-size: 8px; + opacity: 0.7; + } } // ============================================================ @@ -625,7 +748,7 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde display: block; margin-bottom: 4px; font-size: 10px; - font-family: monospace; + font-family: "Averia", sans-serif; text-transform: uppercase; letter-spacing: 0.08em; color: @cde-muted; @@ -645,7 +768,7 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde } .cde-section-title { - font-family: monospace; + font-family: "Averia", sans-serif; font-size: 10px; font-weight: 800; letter-spacing: 0.1em; @@ -712,21 +835,398 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde } } -.loksyu_wrap .schema, -.tinji_wrap .schema { - display: grid; - gap: @cde-gap; - align-items: center; +// ============================================================ +// NPC Aptitudes table — modern cde-skills-table layout +// ============================================================ +.cde-aptitudes-table { + // Inherits .cde-skills-table styles; just ensure consistent width + .cde-spec-cell { flex: 1 1 0; } +} + +// NPC vitality / hei tracker +.cde-npc-tracks { + margin-top: @cde-gap; + + .cde-track-row { + display: flex; + align-items: center; + gap: 10px; + padding: 8px 0; + border-bottom: 1px solid @cde-border; + + &:last-child { border-bottom: none; } + } + + .cde-track-label { + display: flex; + align-items: center; + gap: 6px; + width: 120px; + flex-shrink: 0; + font-size: 11px; + font-family: "Averia", sans-serif; + text-transform: uppercase; + letter-spacing: 0.08em; + color: @cde-muted; + + i { font-size: 12px; } + } + + .cde-track-value { + display: flex; + align-items: center; + gap: 6px; + + input.cde-circle-input { + width: 48px; + } + } + + .cde-track-sep { + font-size: 14px; + color: @cde-muted; + font-weight: 700; + } + + .cde-track-max { + font-size: 15px; + font-weight: 700; + color: @cde-spell; + text-shadow: 0 0 6px fade(@cde-spell, 40%); + min-width: 28px; + text-align: center; + } + + .cde-track-note { + flex: 1; + input { width: 100%; } + } +} + +// ============================================================ +// Loksyu — 5 elemental cards grid +// ============================================================ +.cde-loksyu-grid { + display: grid; + grid-template-columns: repeat(5, minmax(0, 1fr)); + gap: @cde-gap; + padding: @cde-gap 0; +} + +.cde-element-card { + background: @cde-surface; + border: 1px solid @cde-border; + border-radius: @cde-radius; + padding: 10px 8px; + display: flex; + flex-direction: column; + gap: 8px; + box-shadow: @cde-shadow-sm; + transition: border-color 0.15s, box-shadow 0.15s; + + &:hover { box-shadow: @cde-shadow; } +} + +// Per-element color theming using LESS variables +.cde-element--wood { border-top: 3px solid @wu-green; .cde-element-name { color: @wu-green; text-shadow: 0 0 6px fade(@wu-green, 50%); } .cde-element-img { filter: drop-shadow(0 0 4px @wu-green); } .cde-element-polarity--yang { border-left: 2px solid fade(@wu-green, 70%); } } +.cde-element--fire { border-top: 3px solid @wu-red; .cde-element-name { color: @wu-red; text-shadow: 0 0 6px fade(@wu-red, 50%); } .cde-element-img { filter: drop-shadow(0 0 4px @wu-red); } .cde-element-polarity--yang { border-left: 2px solid fade(@wu-red, 70%); } } +.cde-element--earth { border-top: 3px solid @wu-brown; .cde-element-name { color: @wu-brown; text-shadow: 0 0 6px fade(@wu-brown, 50%); } .cde-element-img { filter: drop-shadow(0 0 4px @wu-brown); } .cde-element-polarity--yang { border-left: 2px solid fade(@wu-brown, 70%); } } +.cde-element--metal { border-top: 3px solid @wu-gray; .cde-element-name { color: @wu-gray; text-shadow: 0 0 6px fade(@wu-gray, 50%); } .cde-element-img { filter: drop-shadow(0 0 4px @wu-gray); } .cde-element-polarity--yang { border-left: 2px solid fade(@wu-gray, 70%); } } +.cde-element--water { border-top: 3px solid @wu-blue; .cde-element-name { color: @wu-blue; text-shadow: 0 0 6px fade(@wu-blue, 50%); } .cde-element-img { filter: drop-shadow(0 0 4px @wu-blue); } .cde-element-polarity--yang { border-left: 2px solid fade(@wu-blue, 70%); } } + +// Input focus per element +.cde-element--wood .cde-element-polarity input:focus { border-bottom-color: @wu-green; box-shadow: 0 1px 0 0 @wu-green; } +.cde-element--fire .cde-element-polarity input:focus { border-bottom-color: @wu-red; box-shadow: 0 1px 0 0 @wu-red; } +.cde-element--earth .cde-element-polarity input:focus { border-bottom-color: @wu-brown; box-shadow: 0 1px 0 0 @wu-brown; } +.cde-element--metal .cde-element-polarity input:focus { border-bottom-color: @wu-gray; box-shadow: 0 1px 0 0 @wu-gray; } +.cde-element--water .cde-element-polarity input:focus { border-bottom-color: @wu-blue; box-shadow: 0 1px 0 0 @wu-blue; } + +.cde-element-header { + display: flex; + flex-direction: column; + align-items: center; + gap: 6px; + text-align: center; +} + +.cde-element-img { + width: 36px; + height: 36px; + object-fit: contain; + filter: drop-shadow(0 0 4px var(--el-color)); +} + +.cde-element-titles { + display: flex; + flex-direction: column; + gap: 2px; +} + +.cde-element-name { + font-family: "Averia", sans-serif; + font-size: 11px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.08em; + color: @cde-muted; // overridden per-element below + white-space: nowrap; +} + +.cde-element-qualities { + font-size: 9px; + color: @cde-muted; + font-style: italic; + line-height: 1.3; + text-align: center; + display: none; // hidden on small width, shown via media query if needed +} + +.cde-element-values { + display: flex; + flex-direction: column; + gap: 4px; +} + +.cde-element-polarity { + display: flex; + align-items: center; + gap: 6px; + padding: 3px 6px; + border-radius: 4px; + background: fade(@cde-bg, 60%); + + &--yin { border-left: 2px solid fade(@cde-muted, 40%); } +} + +.cde-polarity-label { + font-size: 9px; + font-family: "Averia", sans-serif; + text-transform: uppercase; + letter-spacing: 0.06em; + color: @cde-muted; + white-space: nowrap; + min-width: 32px; +} + +.cde-element-polarity input { + width: 40px; + border: none; + border-bottom: 1px solid @cde-border; + background: transparent; + color: @cde-text; + font-size: 14px; + font-weight: 700; + text-align: center; + padding: 2px 0; + outline: none; +} + +.cde-loksyu-visual-row { + display: flex; + justify-content: center; + padding-top: @cde-gap; + + .loksyu-visual { + max-width: 100%; + height: auto; + opacity: 0.7; + border-radius: @cde-radius; + border: 1px solid @cde-border; + } +} + +// ============================================================ +// Tin Ji — enhanced display +// ============================================================ +.cde-tinji-layout { + display: flex; + align-items: center; + justify-content: space-between; + gap: @cde-gap * 2; + padding: @cde-gap; + flex-wrap: wrap; +} + +.cde-tinji-main { + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + flex: 1; +} + +.cde-tinji-chinese { + font-size: 48px; + color: @cde-supernatural; + text-shadow: 0 0 20px fade(@cde-supernatural, 60%); + line-height: 1; + letter-spacing: 0.1em; +} + +.cde-tinji-subtitle { + font-family: "Averia", sans-serif; + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.2em; + color: @cde-muted; +} + +.cde-tinji-value-wrapper { + display: flex; + align-items: center; + justify-content: center; + + .cde-tinji-input { + width: 80px; + text-align: center; + font-size: 36px; + font-weight: 700; + color: @cde-supernatural; + text-shadow: 0 0 12px fade(@cde-supernatural, 50%); + border: none; + border-bottom: 2px solid @cde-supernatural; + background: transparent; + outline: none; + padding: 4px 0; + + &:focus { + border-bottom-color: lighten(@cde-supernatural, 15%); + box-shadow: 0 2px 0 0 fade(@cde-supernatural, 60%); + } + } +} + +.cde-tinji-hint { + font-size: 10px; + font-family: "Averia", sans-serif; + color: @cde-muted; + text-transform: uppercase; + letter-spacing: 0.12em; + text-align: center; } -.loksyu-visual, .tinji-visual { - max-width: 100%; + max-height: 280px; + max-width: 200px; border-radius: @cde-radius; border: 1px solid @cde-border; box-shadow: @cde-shadow; } +// ============================================================ +// Weapon roll button + dialog +// ============================================================ + +.cde-weapon-roll-btn { + color: @cde-weapon !important; + &:hover { text-shadow: 0 0 6px fade(@cde-weapon, 60%); } +} + +.cde-item-damage { + color: @cde-weapon; + font-weight: 700; +} + +.cde-weapon-prompt { + // Weapon info bar at top of dialog + .cde-weapon-info-bar { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + background: fade(@cde-weapon, 8%); + border: 1px solid fade(@cde-weapon, 30%); + border-radius: @cde-radius; + margin-bottom: @cde-gap; + + .cde-weapon-aspect-icon { + width: 36px; + height: 36px; + object-fit: contain; + } + + .cde-weapon-info-text { + flex: 1; + display: flex; + flex-direction: column; + gap: 2px; + } + + .cde-weapon-info-name { + font-size: 14px; + font-weight: 700; + font-family: "Averia", sans-serif; + color: @cde-text; + } + + .cde-weapon-info-meta { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: @cde-muted; + font-family: "Averia", sans-serif; + } + + .cde-weapon-info-badge { + font-size: 20px; + color: fade(@cde-weapon, 50%); + } + } +} + +// Weapon damage result in chat card +.cde-rr-weapon-damage { + display: flex; + align-items: center; + gap: 10px; + padding: 8px 12px; + background: fade(@cde-weapon, 10%); + border-top: 1px solid fade(@cde-weapon, 30%); + border-bottom: 1px solid fade(@cde-weapon, 30%); + margin: 4px 0; + + .cde-rr-weapon-icon { + font-size: 16px; + color: @cde-weapon; + text-shadow: 0 0 6px fade(@cde-weapon, 50%); + flex-shrink: 0; + } + + .cde-rr-weapon-text { + display: flex; + flex-direction: column; + gap: 2px; + } + + .cde-rr-weapon-name { + font-size: 11px; + font-family: "Averia", sans-serif; + text-transform: uppercase; + letter-spacing: 0.08em; + color: @cde-muted; + } + + .cde-rr-weapon-calc { + font-size: 12px; + color: @cde-text; + } + + .cde-rr-weapon-total { + font-size: 16px; + font-weight: 900; + color: @cde-weapon; + text-shadow: 0 0 8px fade(@cde-weapon, 60%); + margin: 0 2px; + } + + .cde-rr-weapon-unit { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.06em; + color: @cde-muted; + } +} + // Legacy tabs (actor sheets still use cde-tabs) .cde-tabs { margin-top: @cde-gap; @@ -736,7 +1236,7 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde color: @cde-muted; padding: 8px 12px; font-size: 11px; - font-family: monospace; + font-family: "Averia", sans-serif; text-transform: uppercase; letter-spacing: 0.08em; @@ -780,7 +1280,7 @@ form.supernatural .cde-neon-tabs .item.active { color: @cde-supernatural; borde a.compendium-name, a.entry-name, strong.ellipsis { - font-family: "DeliusUnicase"; + font-family: "Averia"; } @@ -788,11 +1288,11 @@ strong.ellipsis { /* concerne les pages de journaux */ .journal-header input { - font-family: "DeliusUnicase"; + font-family: "Averia"; } .journal-entry-page h1 { - font-family: "DeliusUnicaseBold"; + font-family: "Averia"; text-align: center; color:hsla(249, 66%, 58%, 0.874); border-bottom: 1px solid orange; @@ -802,7 +1302,7 @@ strong.ellipsis { } .journal-entry-page h2 { - font-family: "DeliusUnicaseBold"; + font-family: "Averia"; color:orange; border-bottom: 0px; border-top: 1px solid orange; @@ -812,7 +1312,7 @@ strong.ellipsis { .journal-entry-page h4, .journal-entry-page h5, .journal-entry-page h6 { - font-family: "DeliusUnicaseBold"; + font-family: "Averia"; color:hsla(249, 66%, 58%, 0.874); border-bottom: 0px; } @@ -831,3 +1331,1031 @@ strong.ellipsis { #interface .chat-message .message-header .message-sender { width: 100px; } + +// ============================================================ +// Three Treasures partial layout +// ============================================================ +.cde-flex-center-text { + display: flex; + justify-content: center; + align-items: center; + text-align: center; +} + +.cde-flex-center { + display: flex; + justify-content: center; + align-items: center; +} + +// ============================================================ +// Circle input — replaces cercle.png overlay approach +// ============================================================ +.cde-circle-input { + width: 44px !important; + height: 44px !important; + border-radius: 50%; + border: 2px solid @cde-border-hi; + background: @cde-surface; + color: @cde-text; + text-align: center; + font-size: 1.1rem; + font-weight: 700; + padding: 0; + flex-shrink: 0; + display: inline-block !important; + line-height: 40px; + vertical-align: middle; + box-sizing: border-box; + + &:focus { + outline: none; + border-color: @cde-item; + box-shadow: 0 0 8px fade(@cde-item, 40%); + } + + &.cde-circle-sm { + width: 32px !important; + height: 32px !important; + font-size: 0.85rem; + line-height: 28px; + } +} + +// ============================================================ +// Skills table +// ============================================================ +.cde-skills-table { + width: 100%; + border-collapse: collapse; + + tr { border-bottom: 1px solid @cde-border; } + tr:last-child { border-bottom: none; } + + td { + padding: 3px 4px; + vertical-align: middle; + } + + td.click, td.noclick { + width: 30px; + min-width: 30px; + text-align: center; + cursor: pointer; + + &:hover img { filter: drop-shadow(0 0 5px @cde-item); } + } + + td.noclick { cursor: default; opacity: 0.4; } + + .cde-skill-label { + white-space: nowrap; + font-size: 0.8rem; + padding-right: 8px; + } + + .cde-val-cell { + width: 52px; + min-width: 52px; + text-align: center; + padding: 4px; + } + + .cde-spec-cell { + width: 100%; + input[type="text"] { width: 100%; } + } + + .cde-bonus-cell { + white-space: nowrap; + font-family: monospace; + font-size: 0.65rem; + color: @cde-muted; + padding: 0 6px; + } + + .cde-check-cell { width: 22px; text-align: center; } +} + +// ============================================================ +// Three Treasures layout (HEI / SAN-ZING / PTAO) +// ============================================================ +.cde-tt-block { + margin-bottom: 12px; + + .cde-tt-row { + display: flex; + align-items: center; + justify-content: center; + gap: 10px; + } + + .cde-tt-labels { + margin-bottom: 4px; + span { + width: 52px; + text-align: center; + font-family: "Averia", sans-serif; + font-size: 0.6rem; + text-transform: uppercase; + color: @cde-muted; + } + .cde-tt-center { width: 44px; } + } + + .cde-tt-yinyang { + width: 44px; + height: 44px; + opacity: 0.8; + } +} + +.cde-tt-sanzing { + margin-bottom: 12px; + + .cde-tt-sz-header, + .cde-tt-sz-row { + display: grid; + grid-template-columns: 36px 48px 1fr 48px 36px; + align-items: center; + gap: 6px; + padding: 4px 8px; + } + + .cde-tt-sz-header { + font-family: "Averia", sans-serif; + font-size: 0.6rem; + text-transform: uppercase; + color: @cde-muted; + text-align: center; + } + + .cde-tt-sz-row { + border-top: 1px solid @cde-border; + + .cde-circle-input { justify-self: center; } + } + + .cde-tt-level { + text-align: center; + font-family: monospace; + font-size: 0.75rem; + font-weight: 700; + color: @cde-muted; + } +} + +// ============================================================ +// Ng Hang — Aspects grid +// ============================================================ +.cde-aspects-header { + display: flex; + justify-content: center; + margin-bottom: 10px; + + .cde-aspects-logo { + max-height: 48px; + opacity: 0.7; + } +} + +.cde-aspects-grid { + display: flex; + flex-wrap: wrap; + gap: 8px; + justify-content: center; + margin-bottom: 12px; +} + +.cde-aspect-card { + display: flex; + flex-direction: column; + align-items: center; + gap: 6px; + padding: 10px 8px; + border-radius: 4px; + background: @cde-surface; + border: 1px solid @cde-border; + min-width: 88px; + flex: 1 1 88px; + max-width: 120px; + + .cde-aspect-top { + display: flex; + flex-direction: column; + align-items: center; + gap: 3px; + } + + .cde-aspect-gif { width: 36px; height: 36px; } + + .cde-aspect-name { + font-family: "Averia"; + font-size: 0.8rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.08em; + } + + .cde-aspect-roll { + display: flex; + align-items: center; + gap: 6px; + + .cde-roll-trigger { + cursor: pointer; + display: flex; + align-items: center; + + &:hover img { filter: drop-shadow(0 0 5px currentColor); } + } + } + + .cde-aspect-qual { + font-size: 0.6rem; + color: @cde-muted; + text-align: center; + line-height: 1.3; + } + + &.cde-aspect--fire { + border-color: @cde-kungfu; + .cde-aspect-name { color: @cde-kungfu; } + .cde-circle-input:focus { border-color: @cde-kungfu; box-shadow: 0 0 6px @cde-kungfu; } + } + + &.cde-aspect--wood { + border-color: #44bb44; + .cde-aspect-name { color: #55cc55; } + .cde-circle-input:focus { border-color: #55cc55; box-shadow: 0 0 6px #55cc55; } + } + + &.cde-aspect--earth { + border-color: #aa7722; + .cde-aspect-name { color: #cc9933; } + .cde-circle-input:focus { border-color: #cc9933; box-shadow: 0 0 6px #cc9933; } + } + + &.cde-aspect--water { + border-color: @cde-spell; + .cde-aspect-name { color: @cde-spell; } + .cde-circle-input:focus { border-color: @cde-spell; box-shadow: 0 0 6px @cde-spell; } + } + + &.cde-aspect--metal { + border-color: @cde-muted; + .cde-aspect-name { color: @cde-text; } + .cde-circle-input:focus { border-color: @cde-item; box-shadow: 0 0 6px @cde-item; } + } +} + +.cde-nghang-diagram { + display: flex; + justify-content: center; + margin-top: 8px; + + img { + max-width: 100%; + max-height: 180px; + opacity: 0.45; + border-radius: 4px; + } +} + +.img-die-sm { + width: 27px !important; + height: 27px !important; + flex-shrink: 0; +} + +// ============================================================ +// Magics partial layout +// ============================================================ +.cde-magics-table { + td.image { + width: 2.2%; + &.td-die { width: 2%; } + } + td.value { width: 25%; } + td.td-spacer { width: 2.2%; } +} + +.chancethrow { + display: flex; + justify-content: center; + align-items: center; +} + +// ============================================================ +// Actor sheet item lists +// ============================================================ +.cde-item-group-label { + font-family: "Averia", sans-serif; + font-size: 0.65rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.15em; + color: @cde-muted; + padding: 2px 6px; + border-left: 2px solid @cde-border-hi; + margin: 8px 0 2px; + flex-shrink: 0; +} + +ol.item-list { + list-style: none; + margin: 0 0 4px; + padding: 0; + + li.item { + display: flex; + align-items: center; + gap: 8px; + padding: 3px 6px; + border-radius: 4px; + background: @cde-surface; + border: 1px solid @cde-border; + margin-bottom: 2px; + + img { border: none; border-radius: 3px; flex-shrink: 0; } + + h4.item-name { flex: 1 1 0; margin: 0; font-size: 13px; color: @cde-text; } + + .cde-item-stat { + font-family: monospace; + font-size: 11px; + color: @cde-muted; + } + + .item-controls { + display: flex; + gap: 4px; + flex-shrink: 0; + + a.item-control { + color: @cde-muted; + &:hover { color: @cde-text; } + } + } + } +} + +// ============================================================ +// Roll Prompt Dialogs (.cde-roll-prompt) +// ============================================================ + +.cde-roll-prompt { + background: @cde-bg; + color: @cde-text; + font-family: "Averia", sans-serif; + padding: 12px 14px; + + &.cde-roll-prompt--magic { + min-width: 340px; + } + + .cde-roll-header { + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: 8px; + margin-bottom: 10px; + border-bottom: 1px solid @cde-border; + } + + .cde-roll-title { + font-size: 13px; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + color: @cde-text; + } + + .cde-roll-dice-count { + font-size: 36px; + font-weight: 900; + color: @cde-item; + line-height: 1; + text-align: center; + margin: 4px 0 8px; + text-shadow: 0 0 12px fade(@cde-item, 60%); + + .cde-roll-dice-label { + font-size: 14px; + font-weight: 600; + color: @cde-muted; + margin-left: 4px; + } + } + + .cde-roll-section { + margin-bottom: 8px; + + &.cde-roll-section--separator { + padding-bottom: 10px; + margin-bottom: 10px; + border-bottom: 1px dashed @cde-border; + } + } + + .cde-roll-section-title { + font-size: 11px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.1em; + color: @cde-muted; + margin: 0 0 6px; + } + + .cde-roll-fields { + display: flex; + flex-direction: column; + gap: 5px; + } + + .cde-roll-field { + display: flex; + align-items: center; + gap: 8px; + + label { + flex: 0 0 160px; + font-size: 11px; + color: @cde-muted; + text-transform: uppercase; + letter-spacing: 0.05em; + } + + select, + .cde-roll-input { + flex: 1; + background: @cde-surface; + border: none; + border-bottom: 1px solid @cde-border; + color: @cde-text; + font-family: monospace; + font-size: 13px; + padding: 3px 6px; + border-radius: 2px; + + &:focus { + outline: none; + border-bottom-color: @cde-item; + box-shadow: 0 1px 0 0 @cde-item; + } + } + + select option { + background: @cde-surface; + color: @cde-text; + } + } + + .cde-roll-hint { + font-size: 10px; + color: @cde-muted; + margin: 4px 0 0; + font-style: italic; + } +} + +// ============================================================ +// Dice Roll Result in Chat (.cde-roll-result) +// ============================================================ + +// Wu Xing aspect color + icon custom properties +// Row order: [successes, auspicious, noxious, loksyu, tinji] +// Colors: wood=#41a436 fire=#cd171a earth=#a85747 metal=#70706e water=#009fe2 + +@wu-green: #41a436; +@wu-red: #cd171a; +@wu-brown: #a85747; +@wu-gray: #70706e; +@wu-blue: #009fe2; + +@wu-img-bois: ~"url(/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png)"; +@wu-img-feu: ~"url(/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png)"; +@wu-img-terre: ~"url(/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png)"; +@wu-img-metal: ~"url(/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png)"; +@wu-img-eau: ~"url(/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png)"; + +// Wu Xing aspect custom properties (accent color + icon per aspect) +// Sets --rr-accent on the card root, plus per-row --rr-color/--rr-icon +[data-aspect="wood"] { + --rr-accent: @wu-green; + --rr-accent-bg: fade(@wu-green, 12%); + .cde-rr-row--auspicious { --rr-color: @wu-red; --rr-icon: @wu-img-feu; } + .cde-rr-row--noxious { --rr-color: @wu-blue; --rr-icon: @wu-img-eau; } + .cde-rr-row--loksyu { --rr-color: @wu-brown; --rr-icon: @wu-img-terre; } + .cde-rr-row--tinji { --rr-color: @wu-gray; --rr-icon: @wu-img-metal; } +} +[data-aspect="fire"] { + --rr-accent: @wu-red; + --rr-accent-bg: fade(@wu-red, 12%); + .cde-rr-row--auspicious { --rr-color: @wu-brown; --rr-icon: @wu-img-terre; } + .cde-rr-row--noxious { --rr-color: @wu-green; --rr-icon: @wu-img-bois; } + .cde-rr-row--loksyu { --rr-color: @wu-gray; --rr-icon: @wu-img-metal; } + .cde-rr-row--tinji { --rr-color: @wu-blue; --rr-icon: @wu-img-eau; } +} +[data-aspect="earth"] { + --rr-accent: @wu-brown; + --rr-accent-bg: fade(@wu-brown, 12%); + .cde-rr-row--auspicious { --rr-color: @wu-gray; --rr-icon: @wu-img-metal; } + .cde-rr-row--noxious { --rr-color: @wu-red; --rr-icon: @wu-img-feu; } + .cde-rr-row--loksyu { --rr-color: @wu-blue; --rr-icon: @wu-img-eau; } + .cde-rr-row--tinji { --rr-color: @wu-green; --rr-icon: @wu-img-bois; } +} +[data-aspect="metal"] { + --rr-accent: @wu-gray; + --rr-accent-bg: fade(@wu-gray, 16%); + .cde-rr-row--auspicious { --rr-color: @wu-blue; --rr-icon: @wu-img-eau; } + .cde-rr-row--noxious { --rr-color: @wu-brown; --rr-icon: @wu-img-terre; } + .cde-rr-row--loksyu { --rr-color: @wu-green; --rr-icon: @wu-img-bois; } + .cde-rr-row--tinji { --rr-color: @wu-red; --rr-icon: @wu-img-feu; } +} +[data-aspect="water"] { + --rr-accent: @wu-blue; + --rr-accent-bg: fade(@wu-blue, 12%); + .cde-rr-row--auspicious { --rr-color: @wu-green; --rr-icon: @wu-img-bois; } + .cde-rr-row--noxious { --rr-color: @wu-gray; --rr-icon: @wu-img-metal; } + .cde-rr-row--loksyu { --rr-color: @wu-red; --rr-icon: @wu-img-feu; } + .cde-rr-row--tinji { --rr-color: @wu-brown; --rr-icon: @wu-img-terre; } +} + +.cde-roll-result { + background: @cde-bg; + color: @cde-text; + font-family: 'Share Tech Mono', monospace; + border-radius: 4px; + border: 1px solid @cde-border; + overflow: hidden; + + // ---- Header ---- + .cde-rr-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 12px; + background: var(--rr-accent-bg, fade(@cde-surface, 80%)); + border-left: 4px solid var(--rr-accent, @cde-border); + border-bottom: 1px solid @cde-border; + gap: 8px; + + .cde-rr-header-left { + display: flex; + align-items: center; + gap: 10px; + flex: 1; + } + + .cde-rr-aspect-icon { + width: 32px; + height: 32px; + object-fit: contain; + filter: drop-shadow(0 0 4px var(--rr-accent, @cde-border)); + border: none; + } + + .cde-rr-header-text { + display: flex; + flex-direction: column; + } + + .cde-rr-aspect-label { + font-size: 11px; + font-weight: 900; + text-transform: uppercase; + letter-spacing: 0.12em; + color: var(--rr-accent, @cde-text); + text-shadow: 0 0 6px var(--rr-accent, transparent); + } + + .cde-rr-roll-label { + font-size: 13px; + font-weight: 600; + color: @cde-text; + } + + .cde-rr-header-right { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 2px; + } + + .cde-rr-actor-avatar { + width: 28px; + height: 28px; + border-radius: 50%; + border: 1px solid var(--rr-accent, @cde-border); + object-fit: cover; + } + + .cde-rr-actor-name { + font-size: 9px; + color: @cde-muted; + text-transform: uppercase; + letter-spacing: 0.05em; + } + } + + // ---- Hero: successes count ---- + .cde-rr-hero { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 16px; + background: fade(@cde-surface, 40%); + + .cde-rr-hero-count { + font-size: 48px; + font-weight: 900; + line-height: 1; + color: var(--rr-accent, @cde-text); + text-shadow: 0 0 16px var(--rr-accent, transparent), 0 0 32px var(--rr-accent, transparent); + } + + .cde-rr-hero-right { + display: flex; + flex-direction: column; + } + + .cde-rr-hero-label { + font-size: 11px; + font-weight: 900; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--rr-accent, @cde-text); + } + + .cde-rr-hero-dice { + font-size: 13px; + color: @cde-muted; + margin-top: 2px; + } + + .cde-rr-hero-dice-label { + font-size: 10px; + } + + .cde-rr-spell-power { + margin-left: auto; + display: flex; + flex-direction: column; + align-items: flex-end; + border-left: 2px solid var(--rr-accent, @cde-border); + padding-left: 10px; + + .cde-rr-spell-power-count { + font-size: 32px; + font-weight: 900; + line-height: 1; + color: var(--rr-accent, @cde-text); + text-shadow: 0 0 12px var(--rr-accent, transparent); + } + + .cde-rr-spell-power-label { + font-size: 9px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.1em; + color: @cde-muted; + } + } + } + + // ---- Detail rows ---- + .cde-rr-details { + display: flex; + flex-direction: column; + gap: 2px; + padding: 6px 10px; + } + + .cde-rr-row { + display: flex; + align-items: center; + gap: 8px; + padding: 3px 6px; + border-radius: 3px; + background: fade(@cde-surface, 60%); + color: var(--rr-color, @cde-muted); + + .cde-rr-count { + font-size: 18px; + font-weight: 900; + line-height: 1; + min-width: 26px; + text-align: center; + text-shadow: 0 0 6px currentColor; + } + + .cde-rr-icon { + width: 22px; + height: 22px; + background-image: var(--rr-icon); + background-size: contain; + background-repeat: no-repeat; + background-position: center; + flex-shrink: 0; + opacity: 0.85; + } + + .cde-rr-label { + font-size: 10px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.07em; + flex: 1; + } + + .cde-rr-partition { + font-size: 9px; + color: @cde-muted; + margin-left: 4px; + } + } + + // ---- Footer modifiers ---- + .cde-rr-footer { + padding: 5px 12px; + border-top: 1px solid @cde-border; + background: fade(@cde-surface, 30%); + display: flex; + align-items: baseline; + gap: 6px; + + .cde-rr-footer-label { + font-size: 9px; + font-weight: 700; + text-transform: uppercase; + color: @cde-muted; + letter-spacing: 0.08em; + } + + .cde-rr-footer-text { + font-size: 10px; + color: @cde-muted; + font-family: "Averia", sans-serif; + } + } + + // ---- Dice face grid ---- + .cde-dice-grid { + display: grid; + grid-template-columns: repeat(10, 1fr); + gap: 3px; + padding: 8px 8px 6px; + border-top: 1px solid @cde-border; + + .cde-dice-cell { + display: flex; + flex-direction: column; + align-items: center; + gap: 1px; + + .cde-dice-count { + font-size: 12px; + font-weight: 700; + color: @cde-text; + line-height: 1; + } + + .cde-dice-plate { + width: 100%; + border: none; + opacity: 0.65; + } + } + } +} + + +// ============================================================ +// Initiative prompt dialog +// ============================================================ +.cde-initiative-prompt { + // Override: fields use vertical layout (label on top, control below) + // to avoid the fixed 160px label squeezing the select to 12px. + .cde-roll-field { + flex-direction: column; + align-items: stretch; + gap: 4px; + + label { + flex: none; + font-size: 10px; + color: @cde-muted; + text-transform: uppercase; + letter-spacing: 0.05em; + } + + select, .cde-roll-input { + flex: none; + width: 100%; + } + } + + .cde-initiative-base-row { + display: flex; + align-items: flex-end; + gap: 10px; + flex-wrap: nowrap; + } + + .cde-initiative-base-field { + flex-shrink: 0; + min-width: 70px; + } + + .cde-initiative-base-value { + display: block; + font-size: 22px; + font-weight: 800; + color: @cde-spell; + text-shadow: 0 0 8px fade(@cde-spell, 50%); + text-align: center; + line-height: 1; + padding: 4px 0; + } + + .cde-initiative-op { + font-size: 18px; + font-weight: 700; + color: @cde-muted; + padding-bottom: 6px; + flex-shrink: 0; + align-self: flex-end; + } + + .cde-initiative-action-field { + flex: 1; + min-width: 0; + } + + .cde-initiative-select { + width: 100%; + } + + .cde-initiative-hint { + font-size: 10px; + font-family: "Averia", sans-serif; + color: @cde-muted; + text-align: center; + letter-spacing: 0.05em; + padding: 4px 0 0; + border-top: 1px solid @cde-border; + margin-top: 4px; + } + + .cde-initiative-icon { + font-size: 20px; + color: @cde-spell; + } +} + +// ============================================================ +// Initiative chat result card +// ============================================================ +.cde-initiative-result { + background: @cde-surface; + border: 1px solid @cde-border; + border-left: 4px solid @cde-spell; + border-radius: @cde-radius; + overflow: hidden; + color: @cde-text; + + .cde-ir-header { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + background: fade(@cde-spell, 8%); + border-bottom: 1px solid @cde-border; + } + + .cde-ir-avatar { + width: 36px; + height: 36px; + border-radius: 50%; + border: 2px solid @cde-border; + object-fit: cover; + flex-shrink: 0; + } + + .cde-ir-actor-info { + display: flex; + flex-direction: column; + gap: 2px; + } + + .cde-ir-actor-name { + font-size: 13px; + font-weight: 700; + color: @cde-text; + } + + .cde-ir-roll-label { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: @cde-muted; + font-family: "Averia", sans-serif; + } + + .cde-ir-formula { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + gap: 5px; + padding: 8px 12px; + background: fade(@cde-bg, 60%); + border-bottom: 1px solid @cde-border; + font-family: monospace; + font-size: 12px; + } + + .cde-ir-formula-base { + color: @cde-muted; + font-size: 11px; + } + + .cde-ir-formula-val { + font-weight: 700; + color: @cde-text; + font-size: 13px; + } + + .cde-ir-formula-mod { + color: @cde-kungfu; + } + + .cde-ir-formula-sep { + color: @cde-muted; + } + + .cde-ir-formula-eq { + color: @cde-muted; + font-size: 14px; + } + + .cde-ir-formula-total { + font-size: 16px; + font-weight: 800; + color: @cde-spell; + text-shadow: 0 0 6px fade(@cde-spell, 50%); + } + + .cde-ir-hero { + display: flex; + align-items: center; + justify-content: center; + gap: 14px; + padding: 14px 12px; + } + + .cde-ir-init-value { + font-size: 48px; + font-weight: 900; + color: @cde-spell; + text-shadow: 0 0 12px fade(@cde-spell, 70%), 0 0 24px fade(@cde-spell, 35%); + line-height: 1; + font-family: 'Averia Regular', sans-serif; + } + + .cde-ir-hero-right { + display: flex; + flex-direction: column; + gap: 4px; + } + + .cde-ir-init-label { + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: @cde-muted; + font-family: "Averia", sans-serif; + } + + .cde-ir-anti { + display: flex; + gap: 5px; + align-items: baseline; + } + + .cde-ir-anti-label { + font-size: 10px; + color: @cde-muted; + font-family: "Averia", sans-serif; + text-transform: uppercase; + letter-spacing: 0.05em; + } + + .cde-ir-anti-value { + font-size: 14px; + font-weight: 700; + color: @cde-kungfu; + text-shadow: 0 0 5px fade(@cde-kungfu, 40%); + } +} diff --git a/dist/system.js b/dist/system.js index 3482c12..25f4403 100644 --- a/dist/system.js +++ b/dist/system.js @@ -10,7 +10,11 @@ var ITEM_TYPES = { item: "item", kungfu: "kungfu", spell: "spell", - supernatural: "supernatural" + supernatural: "supernatural", + weapon: "weapon", + armor: "armor", + sanhei: "sanhei", + ingredient: "ingredient" }; var SUBTYPES = { weapon: { id: "weapon", label: "CDE.Weapon" }, @@ -204,7 +208,7 @@ var CharacterDataModel = class extends foundry.abstract.TypeDataModel { }); const schema = { concept: stringField(""), - guardian: stringField("0"), + guardian: numberField(0, { min: 0, max: 5 }), initiative: numberField(1, { min: 0 }), anti_initiative: numberField(24, { min: 0 }), description: htmlField(""), @@ -276,8 +280,8 @@ var CharacterDataModel = class extends foundry.abstract.TypeDataModel { geomancy: magicField() }), threetreasures: new fields.SchemaField({ - heiyang: new fields.SchemaField({ value: numberField(0, { min: 0 }) }), - heiyin: new fields.SchemaField({ value: numberField(0, { min: 0 }) }), + heiyang: new fields.SchemaField({ value: numberField(0, { min: 0 }), max: numberField(0, { min: 0 }) }), + heiyin: new fields.SchemaField({ value: numberField(0, { min: 0 }), max: numberField(0, { min: 0 }) }), dicelevel: new fields.SchemaField({ level0d: treasureLevel(), level1d: treasureLevel(), @@ -313,8 +317,10 @@ var NpcDataModel = class extends foundry.abstract.TypeDataModel { }); return { type: stringField(""), - levelofthreat: numberField(0, { min: 0 }), - powerofnuisance: numberField(0, { min: 0 }), + threat: numberField(0, { min: 0, max: 4 }), + // profane(0) | apprentice(1) | initiate(2) | accomplished(3) | renowned(4) + nuisance: numberField(0, { min: 0, max: 5 }), + // figurant(0) | minion(1) | adversary(2) | ally(3) | boss(4) | divinity(5) initiative: numberField(1, { min: 0 }), anti_initiative: numberField(24, { min: 0 }), aptitudes: new fields.SchemaField({ @@ -379,14 +385,10 @@ var EquipmentDataModel = class extends foundry.abstract.TypeDataModel { const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial }); const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true }); return { - subtype: stringField(""), reference: stringField(""), description: htmlField(""), quantity: numberField(1, { min: 0 }), weight: numberField(0, { min: 0 }), - protection: stringField(""), - damage: stringField(""), - range: stringField(""), notes: htmlField("") }; } @@ -402,15 +404,19 @@ var KungfuDataModel = class extends foundry.abstract.TypeDataModel { const techniqueField = () => new fields.SchemaField({ check: boolField(false), name: stringField(""), - activation: stringField(""), + activation: stringField("action-attack"), + // action-attack | action-defense | action-aid | action-attack-defense | reaction | dice | damage-inflicted | damage-received technique: htmlField("") }); return { reference: stringField(""), description: htmlField(""), - orientation: stringField(""), - aspect: stringField(""), - skill: stringField(""), + orientation: stringField("yin"), + // yin | yang | yinyang + aspect: stringField("metal"), + // metal | eau | terre | feu | bois + skill: stringField("kungfu"), + // kungfu | rangedcombat speciality: stringField(""), style: stringField(""), techniques: new fields.SchemaField({ @@ -433,7 +439,8 @@ var SpellDataModel = class extends foundry.abstract.TypeDataModel { reference: stringField(""), description: htmlField(""), specialityname: stringField(""), - associatedelement: stringField(""), + associatedelement: stringField("metal"), + // metal | eau | terre | feu | bois hei: stringField(""), realizationtimeritual: stringField(""), realizationtimeaccelerated: stringField(""), @@ -441,7 +448,11 @@ var SpellDataModel = class extends foundry.abstract.TypeDataModel { components: htmlField(""), effects: htmlField(""), examples: htmlField(""), - notes: htmlField("") + notes: htmlField(""), + discipline: stringField("cinabre"), + heiType: stringField("yin"), + heiCost: new fields.NumberField({ required: true, nullable: false, integer: true, min: 0, initial: 1 }), + difficulty: new fields.NumberField({ required: true, nullable: false, integer: true, min: 0, initial: 1 }) }; } }; @@ -455,6 +466,100 @@ var SupernaturalDataModel = class extends foundry.abstract.TypeDataModel { return { reference: stringField(""), description: htmlField(""), + notes: htmlField(""), + heiType: stringField("yin"), + heiCost: new fields.NumberField({ required: true, nullable: false, integer: true, min: 0, initial: 0 }), + trigger: stringField(""), + effects: htmlField("") + }; + } +}; + +// src/data/items/weapon.js +var WeaponDataModel = class extends foundry.abstract.TypeDataModel { + static defineSchema() { + const { fields } = foundry.data; + const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial }); + const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true }); + const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts }); + return { + reference: stringField(""), + description: htmlField(""), + weaponType: stringField("melee"), + material: stringField(""), + damageAspect: stringField("metal"), + damageBase: intField(1), + 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), + notes: htmlField("") + }; + } +}; + +// src/data/items/armor.js +var ArmorDataModel = class extends foundry.abstract.TypeDataModel { + static defineSchema() { + const { fields } = foundry.data; + const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial }); + const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true }); + const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts }); + return { + reference: stringField(""), + description: htmlField(""), + protectionValue: intField(0), + domain: stringField(""), + obtainLevel: intField(0, { min: 0, max: 5 }), + obtainDifficulty: intField(0, { min: 0, max: 3 }), + quantity: intField(1), + notes: htmlField("") + }; + } +}; + +// src/data/items/sanhei.js +var SanheiDataModel = class extends foundry.abstract.TypeDataModel { + static defineSchema() { + const { fields } = foundry.data; + const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial }); + const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true }); + const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts }); + const propertySchema = () => new fields.SchemaField({ + name: stringField(""), + heiCost: intField(0), + heiType: stringField("yin"), + description: htmlField("") + }); + return { + reference: stringField(""), + description: htmlField(""), + heiType: stringField("yin"), + properties: new fields.SchemaField({ + prop1: propertySchema(), + prop2: propertySchema(), + prop3: propertySchema() + }), + notes: htmlField("") + }; + } +}; + +// src/data/items/ingredient.js +var IngredientDataModel = class extends foundry.abstract.TypeDataModel { + static defineSchema() { + const { fields } = foundry.data; + const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial }); + const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true }); + const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts }); + return { + reference: stringField(""), + description: htmlField(""), + school: stringField("all"), + obtainLevel: intField(0, { min: 0, max: 5 }), + obtainDifficulty: intField(0, { min: 0, max: 3 }), + quantity: intField(1), notes: htmlField("") }; } @@ -629,12 +734,671 @@ async function preloadPartials() { return loadTemplates(TEMPLATE_PARTIALS); } +// src/ui/initiative.js +var PC_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-prompt.html"; +var NPC_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-prompt-npc.html"; +var RESULT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-result.html"; +function buildPCOptions(sys) { + const sk = sys.skills ?? {}; + const rs = sys.resources ?? {}; + const mg = sys.magics ?? {}; + return [ + { key: "art", label: game.i18n.localize("CDE.Art"), value: sk.art?.value ?? 0 }, + { key: "investigation", label: game.i18n.localize("CDE.Investigation"), value: sk.investigation?.value ?? 0 }, + { key: "erudition", label: game.i18n.localize("CDE.Erudition"), value: sk.erudition?.value ?? 0 }, + { key: "knavery", label: game.i18n.localize("CDE.Knavery"), value: sk.knavery?.value ?? 0 }, + { key: "wordliness", label: game.i18n.localize("CDE.Wordliness"), value: sk.wordliness?.value ?? 0 }, + { key: "prowess", label: game.i18n.localize("CDE.Prowess"), value: sk.prowess?.value ?? 0 }, + { key: "sciences", label: game.i18n.localize("CDE.Sciences"), value: sk.sciences?.value ?? 0 }, + { key: "technologies", label: game.i18n.localize("CDE.Technologies"), value: sk.technologies?.value ?? 0 }, + { key: "kungfu", label: game.i18n.localize("CDE.KungFu"), value: sk.kungfu?.value ?? 0 }, + { key: "rangedcombat", label: game.i18n.localize("CDE.RangedCombat"), value: sk.rangedcombat?.value ?? 0 }, + { key: "supply", label: game.i18n.localize("CDE.Supply"), value: rs.supply?.value ?? 0 }, + { key: "inquiry", label: game.i18n.localize("CDE.Inquiry"), value: rs.inquiry?.value ?? 0 }, + { key: "influence", label: game.i18n.localize("CDE.Influence"), value: rs.influence?.value ?? 0 }, + { key: "internalcinnabar", label: game.i18n.localize("CDE.InternalCinnabar"), value: mg.internalcinnabar?.value ?? 0 }, + { key: "alchemy", label: game.i18n.localize("CDE.Alchemy"), value: mg.alchemy?.value ?? 0 }, + { key: "masteryoftheway", label: game.i18n.localize("CDE.MasteryOfTheWay"), value: mg.masteryoftheway?.value ?? 0 }, + { key: "exorcism", label: game.i18n.localize("CDE.Exorcism"), value: mg.exorcism?.value ?? 0 }, + { key: "geomancy", label: game.i18n.localize("CDE.Geomancy"), value: mg.geomancy?.value ?? 0 } + ]; +} +function buildNPCOptions(sys) { + const ap = sys.aptitudes ?? {}; + return [ + { key: "physical", label: game.i18n.localize("CDE.Physical"), value: ap.physical?.value ?? 0 }, + { key: "martial", label: game.i18n.localize("CDE.Martial"), value: ap.martial?.value ?? 0 }, + { key: "mental", label: game.i18n.localize("CDE.Mental"), value: ap.mental?.value ?? 0 }, + { key: "social", label: game.i18n.localize("CDE.Social"), value: ap.social?.value ?? 0 }, + { key: "spiritual", label: game.i18n.localize("CDE.Spiritual"), value: ap.spiritual?.value ?? 0 } + ]; +} +function readInitFields(dialog) { + const root = dialog.element ?? dialog; + const selectedKey = root.querySelector("select[name='firstaction']")?.value ?? ""; + const modifier = parseInt(root.querySelector("input[name='modifier']")?.value ?? 0) || 0; + return { selectedKey, modifier }; +} +async function sendInitChatMessage({ actor, baseName, baseValue, actionName, actionValue, modifier, initiative, antiInitiative }) { + const html = await foundry.applications.handlebars.renderTemplate(RESULT_TEMPLATE, { + actorName: actor.name, + actorImg: actor.img, + baseName, + baseValue, + actionName, + actionValue, + modifier, + hasModifier: modifier !== 0, + initiative, + antiInitiative + }); + await ChatMessage.create({ + user: game.user.id, + speaker: ChatMessage.getSpeaker({ actor }), + content: html + }); +} +async function rollInitiativePC(actor) { + const sys = actor.system; + const prowess = sys.skills?.prowess?.value ?? 0; + const options = buildPCOptions(sys); + const baseName = game.i18n.localize("CDE.Prowess"); + const content = await foundry.applications.handlebars.renderTemplate(PC_PROMPT_TEMPLATE, { + prowessValue: prowess, + options, + modifier: 0 + }); + const result = await foundry.applications.api.DialogV2.prompt({ + window: { title: game.i18n.localize("CDE.InitiativeRoll") }, + content, + rejectClose: false, + ok: { + label: game.i18n.localize("CDE.Validate"), + callback: (_ev, _btn, dialog) => readInitFields(dialog) + } + }); + if (!result) return; + const { selectedKey, modifier } = result; + const selected = options.find((o) => o.key === selectedKey) ?? options[0]; + const rawValue = prowess + selected.value + modifier; + const initiative = Math.max(1, Math.min(24, rawValue)); + const antiInit = 25 - initiative; + await actor.update({ "system.initiative": initiative }); + await sendInitChatMessage({ + actor, + baseName, + baseValue: prowess, + actionName: selected.label, + actionValue: selected.value, + modifier, + initiative, + antiInitiative: antiInit + }); +} +async function rollInitiativeNPC(actor) { + const sys = actor.system; + const physical = sys.aptitudes?.physical?.value ?? 0; + const options = buildNPCOptions(sys); + const baseName = game.i18n.localize("CDE.Physical"); + const content = await foundry.applications.handlebars.renderTemplate(NPC_PROMPT_TEMPLATE, { + physicalValue: physical, + options, + modifier: 0 + }); + const result = await foundry.applications.api.DialogV2.prompt({ + window: { title: game.i18n.localize("CDE.InitiativeRoll") }, + content, + rejectClose: false, + ok: { + label: game.i18n.localize("CDE.Validate"), + callback: (_ev, _btn, dialog) => readInitFields(dialog) + } + }); + if (!result) return; + const { selectedKey, modifier } = result; + const selected = options.find((o) => o.key === selectedKey) ?? options[0]; + const rawValue = physical + selected.value + modifier; + const initiative = Math.max(1, Math.min(24, rawValue)); + const antiInit = 25 - initiative; + await actor.update({ "system.initiative": initiative }); + await sendInitChatMessage({ + actor, + baseName, + baseValue: physical, + actionName: selected.label, + actionValue: selected.value, + modifier, + initiative, + antiInitiative: antiInit + }); +} + +// src/ui/rolling.js +var RESULT_TEMPLATE2 = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-dice-result.html"; +var SKILL_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-skill-dice-prompt.html"; +var SKILL_SPECIAL_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-skill-special-dice-prompt.html"; +var MAGIC_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-magic-dice-prompt.html"; +var WEAPON_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-weapon-dice-prompt.html"; +var LABELELEMENT_TO_ASPECT = { + "CDE.Metal": "metal", + "CDE.Water": "water", + "CDE.Earth": "earth", + "CDE.Fire": "fire", + "CDE.Wood": "wood" +}; +var ASPECT_NAMES = ["metal", "water", "earth", "fire", "wood"]; +var ASPECT_LABELS = { + metal: "CDE.Metal", + water: "CDE.Water", + earth: "CDE.Earth", + fire: "CDE.Fire", + wood: "CDE.Wood" +}; +var ASPECT_ICONS = { + metal: "systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png", + water: "systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png", + earth: "systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png", + fire: "systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png", + wood: "systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png" +}; +var ASPECT_FACES = { + metal: [3, 8], + water: [1, 6], + earth: [0, 5], + // 0 = face "10" + fire: [2, 7], + wood: [4, 9] +}; +var WU_XING_CYCLE = { + wood: ["wood", "fire", "water", "earth", "metal"], + fire: ["fire", "earth", "wood", "metal", "water"], + earth: ["earth", "metal", "fire", "water", "wood"], + metal: ["metal", "water", "earth", "wood", "fire"], + water: ["water", "wood", "metal", "fire", "earth"] +}; +var RANGE_MALUS = { + contact: 0, + courte: 0, + mediane: -1, + longue: -2, + extreme: -3 +}; +var WEAPON_TYPE_SKILL = { + melee: "kungfu", + thrown: "rangedcombat", + ranged: "rangedcombat", + firearm: "rangedcombat" +}; +var WEAPON_ASPECT_INDEX = { metal: 0, eau: 1, water: 1, terre: 2, earth: 2, feu: 3, fire: 3, bois: 4, wood: 4 }; +function countFaces(rollResults) { + const counts = { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 0: 0 }; + for (const die of rollResults) { + const face = die.result === 10 ? 0 : die.result; + counts[face]++; + } + return counts; +} +function computeWuXingResults(faces, aspectName, bonusAuspicious = 0) { + const cycle = WU_XING_CYCLE[aspectName]; + if (!cycle) return null; + const [succAspect, ausAspect, noxAspect, lokAspect, tinAspect] = cycle; + const [succYin, succYang] = ASPECT_FACES[succAspect]; + const [ausYin, ausYang] = ASPECT_FACES[ausAspect]; + const [noxYin, noxYang] = ASPECT_FACES[noxAspect]; + const [lokYin, lokYang] = ASPECT_FACES[lokAspect]; + const [tinYin, tinYang] = ASPECT_FACES[tinAspect]; + const yin = game.i18n.localize("CDE.Yin"); + const yang = game.i18n.localize("CDE.Yang"); + return { + successesdice: faces[succYin] + faces[succYang], + auspiciousdice: faces[ausYin] + faces[ausYang] + bonusAuspicious, + noxiousdice: faces[noxYin] + faces[noxYang], + loksyudice: faces[lokYin] + faces[lokYang], + loksyurepartition: `[${yin}(${faces[lokYin]}) ${yang}(${faces[lokYang]})]`, + tinjidice: faces[tinYin] + faces[tinYang] + }; +} +function readField(dlg, name) { + const el = dlg.querySelector(`[name="${name}"]`); + if (!el) return null; + return el.type === "checkbox" ? el.checked : el.value; +} +async function showRollPrompt({ title, template, data, fields }) { + const content = await foundry.applications.handlebars.renderTemplate(template, data); + return foundry.applications.api.DialogV2.prompt({ + window: { title }, + content, + rejectClose: false, + ok: { + label: game.i18n.localize("CDE.Validate"), + callback: (event, button, dialog) => { + const root = dialog.element ?? dialog; + const result = {}; + for (const field of fields) { + result[field] = readField(root, field); + } + return result; + } + } + }); +} +async function showSkillPrompt(params) { + return showRollPrompt({ + title: params.title, + template: params.isSpecial ? SKILL_SPECIAL_PROMPT_TEMPLATE : SKILL_PROMPT_TEMPLATE, + data: { + numberofdice: params.numberofdice, + aspect: Number(params.aspect ?? 0), + bonusmalus: params.bonusmalus ?? 0, + woundmalus: params.woundmalus ?? 0, + bonusauspiciousdice: params.bonusauspiciousdice ?? 0, + typeofthrow: Number(params.typeofthrow ?? 0) + }, + fields: ["aspect", "bonusmalus", "woundmalus", "bonusauspiciousdice", "typeofthrow"] + }); +} +async function showMagicPrompt(params) { + return showRollPrompt({ + title: params.title, + template: MAGIC_PROMPT_TEMPLATE, + data: { + 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) + }, + fields: [ + "aspectskill", + "bonusmalusskill", + "bonusauspiciousdice", + "aspectspeciality", + "rolldifficulty", + "bonusmalusspeciality", + "heispend", + "typeofthrow" + ] + }); +} +async function showWeaponPrompt(params) { + return showRollPrompt({ + title: params.title, + template: WEAPON_PROMPT_TEMPLATE, + data: { + numberofdice: params.numberofdice ?? 0, + weaponName: params.weaponName ?? "", + weaponTypeLabel: params.weaponTypeLabel ?? "CDE.Weapon", + weaponAspectIcon: params.weaponAspectIcon ?? "", + weaponAspectLabel: params.weaponAspectLabel ?? "", + damageBase: params.damageBase ?? 1, + weaponskill: params.weaponskill ?? "kungfu", + aspect: Number(params.aspect ?? 0), + effectiverange: params.effectiverange ?? "contact", + bonusmalus: params.bonusmalus ?? 0, + woundmalus: params.woundmalus ?? 0, + bonusauspiciousdice: params.bonusauspiciousdice ?? 0, + typeofthrow: Number(params.typeofthrow ?? 0) + }, + fields: [ + "weaponskill", + "aspect", + "effectiverange", + "bonusmalus", + "woundmalus", + "bonusauspiciousdice", + "typeofthrow" + ] + }); +} +async function sendResultMessage(actor, resultData, roll, rollMode) { + const html = await foundry.applications.handlebars.renderTemplate(RESULT_TEMPLATE2, resultData); + return ChatMessage.create({ + user: game.user.id, + speaker: ChatMessage.getSpeaker({ actor }), + content: html, + rolls: [roll], + rollMode + }); +} +var ROLL_MODES = ["roll", "gmroll", "blindroll", "selfroll"]; +async function rollForActor(actor, rollKey) { + const parts = rollKey.split("-"); + const skillLibel = parts[0]; + const typeLibel = parts[1]; + const specialLibel = parts[2] ?? null; + const sys = actor.system; + const typeOfThrow = Number(sys.prefs?.typeofthrow?.choice ?? 0); + let numberofdice = 0; + let title = ""; + let isSpecial = false; + let isMagic = false; + let isMagicSpecial = false; + let kfDefaultAspect = -1; + const MAGIC_I18N_KEYS = { + internalcinnabar: "CDE.InternalCinnabar", + alchemy: "CDE.Alchemy", + masteryoftheway: "CDE.MasteryOfTheWay", + exorcism: "CDE.Exorcism", + geomancy: "CDE.Geomancy" + }; + switch (typeLibel) { + case "aspect": + numberofdice = sys.aspect[skillLibel]?.value ?? 0; + title = game.i18n.localize(sys.aspect[skillLibel]?.label ?? "CDE.Roll"); + break; + case "skill": + numberofdice = sys.skills[skillLibel]?.value ?? 0; + title = game.i18n.localize(sys.skills[skillLibel]?.label ?? "CDE.Roll"); + break; + case "special": + numberofdice = sys.skills[skillLibel]?.value ?? 0; + title = game.i18n.localize(sys.skills[skillLibel]?.label ?? "CDE.Roll"); + title += ` [${game.i18n.localize("CDE.Speciality")}]`; + isSpecial = true; + if (!sys.skills[skillLibel]?.specialities) { + ui.notifications.warn(game.i18n.localize("CDE.Error2")); + return; + } + break; + case "resource": + numberofdice = sys.resources[skillLibel]?.value ?? 0; + title = game.i18n.localize(sys.resources[skillLibel]?.label ?? "CDE.Roll"); + break; + case "field": + numberofdice = sys.resources[skillLibel]?.value ?? 0; + title = game.i18n.localize(sys.resources[skillLibel]?.label ?? "CDE.Roll"); + title += ` [${game.i18n.localize("CDE.Field")}]`; + isSpecial = true; + if (!sys.resources[skillLibel]?.specialities) { + ui.notifications.warn(game.i18n.localize("CDE.Error4")); + return; + } + break; + case "magic": + numberofdice = sys.magics[skillLibel]?.value ?? 0; + isMagic = true; + title = game.i18n.localize(MAGIC_I18N_KEYS[skillLibel] ?? "CDE.Magics"); + break; + case "magicspecial": + numberofdice = sys.magics[skillLibel]?.value ?? 0; + isMagicSpecial = true; + isMagic = true; + if (!sys.magics[skillLibel]?.speciality?.[specialLibel]?.check) { + ui.notifications.warn(game.i18n.localize("CDE.Error6")); + return; + } + title = `${game.i18n.localize(MAGIC_I18N_KEYS[skillLibel] ?? "CDE.Magics")} [${game.i18n.localize(game.system.CONST?.MAGICS?.[skillLibel]?.speciality?.[specialLibel]?.label ?? "")}]`; + break; + case "itemkungfu": { + const kfItem = actor.items.get(skillLibel); + if (!kfItem) { + ui.notifications.warn(game.i18n.localize("CDE.Error0")); + return; + } + 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"); + if (kfDefaultAspect < 0) kfDefaultAspect = 0; + break; + } + case "itemweapon": { + const wpItem = actor.items.get(skillLibel); + if (!wpItem) { + ui.notifications.warn(game.i18n.localize("CDE.Error0")); + return; + } + const wpType = wpItem.system.weaponType ?? "melee"; + const wpSkill = WEAPON_TYPE_SKILL[wpType] ?? "kungfu"; + numberofdice = sys.skills[wpSkill]?.value ?? 0; + const wpAspectRaw = wpItem.system.damageAspect ?? "metal"; + const wpAspectIdx = WEAPON_ASPECT_INDEX[wpAspectRaw] ?? 0; + const wpRange = wpItem.system.range ?? "contact"; + const WEAPON_TYPE_LABELS = { + melee: "CDE.WeaponMelee", + thrown: "CDE.WeaponThrown", + ranged: "CDE.WeaponRanged", + firearm: "CDE.WeaponFirearm" + }; + const wParams = await showWeaponPrompt({ + title: `${wpItem.name} [${game.i18n.localize(sys.skills[wpSkill]?.label ?? "CDE.WeaponRoll")}]`, + numberofdice, + weaponName: wpItem.name, + weaponTypeLabel: WEAPON_TYPE_LABELS[wpType] ?? "CDE.Weapon", + weaponAspectIcon: ASPECT_ICONS[ASPECT_NAMES[wpAspectIdx]] ?? "", + weaponAspectLabel: game.i18n.localize(ASPECT_LABELS[ASPECT_NAMES[wpAspectIdx]] ?? ""), + damageBase: wpItem.system.damageBase ?? 1, + weaponskill: wpSkill, + aspect: wpAspectIdx, + effectiverange: wpRange, + bonusmalus: 0, + woundmalus: 0, + bonusauspiciousdice: 0, + typeofthrow: typeOfThrow + }); + if (!wParams) return; + const wpChosenSkill = wParams.weaponskill ?? wpSkill; + const wpSkillDice = sys.skills[wpChosenSkill]?.value ?? 0; + const wpAspFinal = Number(wParams.aspect ?? wpAspectIdx); + const wpAspectDice = sys.aspect[ASPECT_NAMES[wpAspFinal]]?.value ?? 0; + const wpRangeMalus = RANGE_MALUS[wParams.effectiverange ?? "contact"] ?? 0; + const wpBonusMalus = Number(wParams.bonusmalus ?? 0); + const wpWoundMalus = Number(wParams.woundmalus ?? 0); + const wpBonusAusp = Number(wParams.bonusauspiciousdice ?? 0); + const wpThrowMode = Number(wParams.typeofthrow ?? 0); + const wpDamageBase = wpItem.system.damageBase ?? 1; + const wpTotalDice = wpSkillDice + wpAspectDice + wpRangeMalus + wpBonusMalus - wpWoundMalus; + if (wpTotalDice <= 0) { + ui.notifications.warn(game.i18n.localize("CDE.Error0")); + return; + } + const wpRoll = new Roll(`${wpTotalDice}d10`); + await wpRoll.evaluate(); + const wpAspectName = ASPECT_NAMES[wpAspFinal] ?? "metal"; + const wpFaces = countFaces(wpRoll.dice[0]?.results ?? []); + const wpResults = computeWuXingResults(wpFaces, wpAspectName, wpBonusAusp); + if (!wpResults) return; + const wpModParts = []; + if (wpRangeMalus !== 0) wpModParts.push(`${wpRangeMalus} ${game.i18n.localize("CDE.RangePenalty")}`); + if (wpBonusMalus !== 0) wpModParts.push(`${wpBonusMalus > 0 ? "+" : ""}${wpBonusMalus} ${game.i18n.localize("CDE.BonusMalus")}`); + if (wpWoundMalus !== 0) wpModParts.push(`-${wpWoundMalus} ${game.i18n.localize("CDE.WoundMalus")}`); + if (wpBonusAusp !== 0) wpModParts.push(`+${wpBonusAusp} ${game.i18n.localize("CDE.BonusAuspiciousDice")}`); + const wpMsg = await sendResultMessage(actor, { + rollLabel: `${wpItem.name}`, + aspectName: wpAspectName, + aspectLabel: game.i18n.localize(ASPECT_LABELS[wpAspectName] ?? ""), + aspectIcon: ASPECT_ICONS[wpAspectName] ?? "", + totalDice: wpTotalDice, + modifiersText: wpModParts.length ? wpModParts.join(" \xB7 ") : "", + spellPower: null, + rollDifficulty: null, + actorName: actor.name ?? "", + actorImg: actor.img ?? "", + // weapon-specific + weaponName: wpItem.name, + damageBase: wpDamageBase, + totalDamage: wpResults.successesdice * wpDamageBase, + ...wpResults, + aspect: wpAspectName, + d1: wpFaces[1], + d2: wpFaces[2], + d3: wpFaces[3], + d4: wpFaces[4], + d5: wpFaces[5], + d6: wpFaces[6], + d7: wpFaces[7], + d8: wpFaces[8], + d9: wpFaces[9], + d0: wpFaces[0] + }, wpRoll, ROLL_MODES[wpThrowMode] ?? "roll"); + if (game.modules.get("dice-so-nice")?.active && wpMsg?.id) { + await game.dice3d.waitFor3DAnimationByMessageID(wpMsg.id); + } + return; + } + default: + ui.notifications.warn(`Unknown roll type: ${typeLibel}`); + return; + } + if (numberofdice <= 0 && typeLibel !== "aspect" && typeLibel !== "itemkungfu" && !isMagic) { + ui.notifications.warn(game.i18n.localize("CDE.Error0")); + return; + } + const MAGIC_ASPECTS = { + internalcinnabar: 0, + // metal + alchemy: 1, + // water + masteryoftheway: 2, + // earth + exorcism: 3, + // fire + geomancy: 4 + // wood + }; + let defaultAspect = typeLibel === "aspect" ? ["metal", "water", "earth", "fire", "wood"].indexOf(skillLibel) : 0; + if (isMagic && MAGIC_ASPECTS[skillLibel] !== void 0) { + defaultAspect = MAGIC_ASPECTS[skillLibel]; + } + if (kfDefaultAspect >= 0) { + defaultAspect = kfDefaultAspect; + } + let defaultSpecialAspect = 0; + if (isMagicSpecial && specialLibel) { + const specialCfg = game.system.CONST?.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({ + title, + numberofdice, + aspectskill: defaultAspect, + bonusmalusskill: 0, + bonusauspiciousdice: 0, + aspectspeciality: defaultSpecialAspect, + rolldifficulty: 1, + bonusmalusspeciality: 0, + heispend: 0, + typeofthrow: typeOfThrow + }); + } else { + params = await showSkillPrompt({ + title, + numberofdice, + aspect: defaultAspect, + bonusmalus: 0, + woundmalus: 0, + bonusauspiciousdice: 0, + typeofthrow: typeOfThrow, + isSpecial + }); + } + 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; + } else { + aspectIndex = Number(params.aspect ?? 0); + bonusMalus = Number(params.bonusmalus ?? 0); + const woundMalus = Number(params.woundmalus ?? 0); + bonusAuspicious = Number(params.bonusauspiciousdice ?? 0); + throwMode = Number(params.typeofthrow ?? 0); + const aspectDice = typeLibel !== "aspect" ? sys.aspect[ASPECT_NAMES[aspectIndex]]?.value ?? 0 : 0; + numberofdice = numberofdice + aspectDice + bonusMalus - woundMalus; + if (isSpecial) numberofdice += 1; + } + if (numberofdice <= 0) { + ui.notifications.warn(game.i18n.localize("CDE.Error0")); + return; + } + 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]; + 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); + 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 (rollDifficulty !== 1) modParts.push(`\xD7${rollDifficulty} ${game.i18n.localize("CDE.RollDifficulty")}`); + } else { + const bm = Number(params.bonusmalus ?? 0); + const wm = Number(params.woundmalus ?? 0); + const ba = Number(params.bonusauspiciousdice ?? 0); + if (bm !== 0) modParts.push(`${bm > 0 ? "+" : ""}${bm} ${game.i18n.localize("CDE.BonusMalus")}`); + if (wm !== 0) modParts.push(`-${wm} ${game.i18n.localize("CDE.WoundMalus")}`); + if (ba !== 0) modParts.push(`+${ba} ${game.i18n.localize("CDE.BonusAuspiciousDice")}`); + } + const msg = await sendResultMessage(actor, { + // Roll identity + rollLabel: title, + aspectName: wuXingAspectName, + aspectLabel: game.i18n.localize(ASPECT_LABELS[wuXingAspectName] ?? ""), + aspectIcon: ASPECT_ICONS[wuXingAspectName] ?? "", + totalDice: numberofdice, + modifiersText: modParts.length ? modParts.join(" \xB7 ") : "", + // Spell power (magic only) + spellPower, + rollDifficulty: isMagic ? rollDifficulty : null, + // Actor info + actorName: actor.name ?? "", + actorImg: actor.img ?? "", + // Wu Xing results + aspect: wuXingAspectName, + ...results, + // Die face counts + d1: faces[1], + d2: faces[2], + d3: faces[3], + d4: faces[4], + d5: faces[5], + d6: faces[6], + d7: faces[7], + d8: faces[8], + d9: faces[9], + d0: faces[0] + }, roll, rollModeKey); + if (game.modules.get("dice-so-nice")?.active && msg?.id) { + await game.dice3d.waitFor3DAnimationByMessageID(msg.id); + } +} + // src/ui/sheets/actors/base.js var { HandlebarsApplicationMixin } = foundry.applications.api; var CDEBaseActorSheet = class _CDEBaseActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) { static DEFAULT_OPTIONS = { classes: ["fvtt-chroniques-de-l-etrange", "actor"], - position: { width: 920, height: "auto" }, + position: { width: 920, height: 800 }, window: { resizable: true }, form: { submitOnChange: true }, dragDrop: [{ dragSelector: ".item, [data-drag='true']", dropSelector: null }], @@ -645,6 +1409,9 @@ var CDEBaseActorSheet = class _CDEBaseActorSheet extends HandlebarsApplicationMi } }; tabGroups = { primary: "description" }; + get title() { + return this.document.name; + } async _prepareContext() { const descriptionHTML = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description ?? "", { async: true }); const cssClass = this.options.classes?.join(" ") ?? ""; @@ -652,19 +1419,18 @@ var CDEBaseActorSheet = class _CDEBaseActorSheet extends HandlebarsApplicationMi actor: this.document, system: this.document.system, systemData: this.document.system, + systemFields: this.document.system.schema.fields, items: this.document.items.contents, descriptionHTML, editable: this.isEditable, cssClass }; } - async _onFirstRender(context, options) { - await super._onFirstRender(context, options); - for (const [group, tab] of Object.entries(this.tabGroups)) { - this.changeTab(tab, group, { force: true }); - } - } + // Restore the active tab after every render (including re-renders from submitOnChange). + // AppV2 does NOT preserve tab state natively — we must re-apply it from this.tabGroups, + // which is dynamically updated by changeTab() when the user clicks a tab. _onRender(context, options) { + super._onRender?.(context, options); for (const [group, tab] of Object.entries(this.tabGroups)) { this.changeTab(tab, group, { force: true }); } @@ -674,6 +1440,10 @@ var CDEBaseActorSheet = class _CDEBaseActorSheet extends HandlebarsApplicationMi const cls = getDocumentClass("Item"); const labels = { item: "CDE.ItemNew", + weapon: "CDE.WeaponNew", + armor: "CDE.ArmorNew", + sanhei: "CDE.SanheiNew", + ingredient: "CDE.IngredientNew", kungfu: "CDE.KFNew", spell: "CDE.SpellNew", supernatural: "CDE.SupernaturalNew" @@ -705,6 +1475,10 @@ var CDECharacterSheet = class extends CDEBaseActorSheet { async _prepareContext() { const context = await super._prepareContext(); context.equipments = context.items.filter((item) => item.type === "item"); + context.weapons = context.items.filter((item) => item.type === "weapon"); + context.armors = context.items.filter((item) => item.type === "armor"); + context.sanheis = context.items.filter((item) => item.type === "sanhei"); + context.ingredients = context.items.filter((item) => item.type === "ingredient"); context.spells = context.items.filter((item) => item.type === "spell"); context.kungfus = context.items.filter((item) => item.type === "kungfu"); context.CDE = { MAGICS, SUBTYPES }; @@ -714,6 +1488,7 @@ var CDECharacterSheet = class extends CDEBaseActorSheet { super._onRender?.(context, options); this.#bindInitiativeControls(); this.#bindPrefs(); + this.#bindRollButtons(); } #bindInitiativeControls() { const buttons = this.element?.querySelectorAll(".click-initiative"); @@ -733,26 +1508,7 @@ var CDECharacterSheet = class extends CDEBaseActorSheet { return; } if (action === "create") { - const html = ` -
-
- - -
-
`; - const value = await Dialog.prompt({ - title: game.i18n.localize("CDE.TurnOrder"), - content: html, - label: game.i18n.localize("CDE.Validate"), - callback: (dlg) => { - const input = dlg.querySelector("input[name='initiative']"); - return Number(input?.value ?? initiative); - } - }); - if (Number.isFinite(value)) { - const sanitized = foundry.utils.clamp(Number(value), 1, 24); - await this.document.update({ "system.initiative": sanitized }); - } + await rollInitiativePC(this.document); } }); }); @@ -796,6 +1552,17 @@ var CDECharacterSheet = class extends CDEBaseActorSheet { } }); } + #bindRollButtons() { + const cells = this.element?.querySelectorAll("td.click[data-libel-id], td.click2[data-libel-id], .cde-roll-trigger[data-libel-id]"); + if (!cells?.length) return; + cells.forEach((cell) => { + cell.addEventListener("click", (event) => { + event.preventDefault(); + const rollKey = cell.dataset.libelId; + if (rollKey) rollForActor(this.document, rollKey); + }); + }); + } }; // src/ui/sheets/actors/npc.js @@ -837,23 +1604,7 @@ var CDENpcSheet = class extends CDEBaseActorSheet { return; } if (action === "create") { - const html = ` -
-
- - -
-
`; - const value = await Dialog.prompt({ - title: game.i18n.localize("CDE.TurnOrder"), - content: html, - label: game.i18n.localize("CDE.Validate"), - callback: (dlg) => Number(dlg.querySelector("input[name='initiative']")?.value ?? initiative) - }); - if (Number.isFinite(value)) { - const sanitized = foundry.utils.clamp(Number(value), 1, 24); - await this.document.update({ "system.initiative": sanitized }); - } + await rollInitiativeNPC(this.document); } }); }); @@ -892,7 +1643,10 @@ var CDEBaseItemSheet = class extends HandlebarsApplicationMixin2(foundry.applica form: { submitOnChange: true }, actions: {} }; - tabGroups = { primary: "description" }; + tabGroups = { primary: "details" }; + get title() { + return this.document.name; + } async _prepareContext() { const cssClass = this.options.classes?.join(" ") ?? ""; const enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description ?? "", { async: true }); @@ -901,6 +1655,7 @@ var CDEBaseItemSheet = class extends HandlebarsApplicationMixin2(foundry.applica item: this.document, system: this.document.system, systemData: this.document.system, + systemFields: this.document.system.schema.fields, editable: this.isEditable, cssClass, enrichedDescription, @@ -909,13 +1664,9 @@ var CDEBaseItemSheet = class extends HandlebarsApplicationMixin2(foundry.applica notesHTML: enrichedNotes }; } - async _onFirstRender(context, options) { - await super._onFirstRender(context, options); - for (const [group, tab] of Object.entries(this.tabGroups)) { - this.changeTab(tab, group, { force: true }); - } - } + // Restore the active tab after every render (including re-renders from submitOnChange). _onRender(context, options) { + super._onRender?.(context, options); for (const [group, tab] of Object.entries(this.tabGroups)) { this.changeTab(tab, group, { force: true }); } @@ -926,20 +1677,11 @@ var CDEBaseItemSheet = class extends HandlebarsApplicationMixin2(foundry.applica var CDEItemSheet = class extends CDEBaseItemSheet { static DEFAULT_OPTIONS = { classes: ["equipment"], - position: { width: 620, height: 580 } + position: { width: 560, height: 460 } }; static PARTS = { main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/item/cde-item-sheet.html" } }; - async _prepareContext() { - const context = await super._prepareContext(); - context.subtypes = SUBTYPES; - context.isWeapon = this.document.isWeapon; - context.isArmor = this.document.isArmor; - context.isSanhei = this.document.isSanhei; - context.isOther = this.document.isOther; - return context; - } }; // src/ui/sheets/items/kungfu.js @@ -991,6 +1733,66 @@ var CDESupernaturalSheet = class extends CDEBaseItemSheet { static PARTS = { main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/item/cde-supernatural-sheet.html" } }; + async _prepareContext() { + const context = await super._prepareContext(); + const enrich = (content) => foundry.applications.ux.TextEditor.implementation.enrichHTML(content ?? "", { async: true }); + context.effectsHTML = await enrich(this.document.system.effects); + return context; + } +}; + +// src/ui/sheets/items/weapon.js +var CDEWeaponSheet = class extends CDEBaseItemSheet { + static DEFAULT_OPTIONS = { + classes: ["weapon"], + position: { width: 580, height: 520 } + }; + static PARTS = { + main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/item/cde-weapon-sheet.html" } + }; +}; + +// src/ui/sheets/items/armor.js +var CDEArmorSheet = class extends CDEBaseItemSheet { + static DEFAULT_OPTIONS = { + classes: ["armor"], + position: { width: 520, height: 460 } + }; + static PARTS = { + main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/item/cde-armor-sheet.html" } + }; +}; + +// src/ui/sheets/items/sanhei.js +var CDESanheiSheet = class extends CDEBaseItemSheet { + static DEFAULT_OPTIONS = { + classes: ["sanhei"], + position: { width: 580, height: 620 } + }; + static PARTS = { + main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/item/cde-sanhei-sheet.html" } + }; + 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; + return context; + } +}; + +// src/ui/sheets/items/ingredient.js +var CDEIngredientSheet = class extends CDEBaseItemSheet { + static DEFAULT_OPTIONS = { + classes: ["ingredient"], + position: { width: 520, height: 460 } + }; + static PARTS = { + main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/item/cde-ingredient-sheet.html" } + }; }; // src/migration.js @@ -1007,7 +1809,7 @@ function registerSettings() { async function migrateIfNeeded() { const current = game.system.version ?? MIGRATION_VERSION; const stored = game.settings.get(SYSTEM_ID, "migrationVersion") ?? "0.0.0"; - if (!isNewerVersion(current, stored)) return; + if (!foundry.utils.isNewerVersion(current, stored)) return; ui.notifications.info(`CHRONIQUESDELETRANGE | Migration vers ${current} en cours...`, { permanent: true }); await migrateActors(); await migrateItems(); @@ -1073,6 +1875,22 @@ function migrateActorData(actor) { const defaultCheck = actorType === "character"; updateData["system.prefs.typeofthrow"] = { check: defaultCheck, choice: "0" }; } + if (actorType === "npc") { + if (system.levelofthreat !== void 0 && system.threat === void 0) { + updateData["system.threat"] = system.levelofthreat; + updateData["system.-=levelofthreat"] = null; + } + if (system.powerofnuisance !== void 0 && system.nuisance === void 0) { + updateData["system.nuisance"] = system.powerofnuisance; + updateData["system.-=powerofnuisance"] = null; + } + } + if (actorType === "character" && typeof system.guardian === "string") { + const guardianNum = parseInt(system.guardian, 10); + if (!isNaN(guardianNum)) { + updateData["system.guardian"] = guardianNum; + } + } return updateData; } function migrateItemData(item) { @@ -1087,64 +1905,88 @@ Hooks.once("init", async () => { console.info(`CHRONIQUESDELETRANGE | Initializing ${SYSTEM_ID}`); registerSettings(); game.system.CONST = { MAGICS, SUBTYPES }; - CONFIG.Actor.systemDataModels = { + CONFIG.Actor.dataModels = { [ACTOR_TYPES.character]: CharacterDataModel, [ACTOR_TYPES.npc]: NpcDataModel, [ACTOR_TYPES.tinji]: TinjiDataModel, [ACTOR_TYPES.loksyu]: LoksyuDataModel }; - CONFIG.Item.systemDataModels = { + CONFIG.Item.dataModels = { [ITEM_TYPES.item]: EquipmentDataModel, [ITEM_TYPES.kungfu]: KungfuDataModel, [ITEM_TYPES.spell]: SpellDataModel, - [ITEM_TYPES.supernatural]: SupernaturalDataModel + [ITEM_TYPES.supernatural]: SupernaturalDataModel, + [ITEM_TYPES.weapon]: WeaponDataModel, + [ITEM_TYPES.armor]: ArmorDataModel, + [ITEM_TYPES.sanhei]: SanheiDataModel, + [ITEM_TYPES.ingredient]: IngredientDataModel }; CONFIG.Actor.documentClass = CDEActor; CONFIG.Item.documentClass = CDEItem; CONFIG.ChatMessage.documentClass = CDEMessage; configureRuntime(); - DocumentSheetConfig.unregisterSheet(Actor, "core", ActorSheet); - DocumentSheetConfig.unregisterSheet(Item, "core", ItemSheet); - DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDECharacterSheet, { + foundry.applications.apps.DocumentSheetConfig.unregisterSheet(Actor, "core", ActorSheet); + foundry.applications.apps.DocumentSheetConfig.unregisterSheet(Item, "core", ItemSheet); + foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDECharacterSheet, { types: [ACTOR_TYPES.character], makeDefault: true, label: "CDE Character Sheet (V2)" }); - DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDENpcSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDENpcSheet, { types: [ACTOR_TYPES.npc], makeDefault: true, label: "CDE NPC Sheet (V2)" }); - DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDETinjiSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDETinjiSheet, { types: [ACTOR_TYPES.tinji], makeDefault: true, label: "CDE Tinji Sheet (V2)" }); - DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDELoksyuSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDELoksyuSheet, { types: [ACTOR_TYPES.loksyu], makeDefault: true, label: "CDE Loksyu Sheet (V2)" }); - DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEItemSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEItemSheet, { types: [ITEM_TYPES.item], makeDefault: true, label: "CDE Item Sheet (V2)" }); - DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEKungfuSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEKungfuSheet, { types: [ITEM_TYPES.kungfu], makeDefault: true, label: "CDE KungFu Sheet (V2)" }); - DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESpellSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESpellSheet, { types: [ITEM_TYPES.spell], makeDefault: true, label: "CDE Spell Sheet (V2)" }); - DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESupernaturalSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESupernaturalSheet, { types: [ITEM_TYPES.supernatural], makeDefault: true, label: "CDE Supernatural Sheet (V2)" }); + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEWeaponSheet, { + types: [ITEM_TYPES.weapon], + makeDefault: true, + label: "CDE Weapon Sheet (V2)" + }); + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEArmorSheet, { + types: [ITEM_TYPES.armor], + makeDefault: true, + label: "CDE Armor Sheet (V2)" + }); + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESanheiSheet, { + types: [ITEM_TYPES.sanhei], + makeDefault: true, + label: "CDE Sanhei Sheet (V2)" + }); + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEIngredientSheet, { + types: [ITEM_TYPES.ingredient], + makeDefault: true, + label: "CDE Ingredient Sheet (V2)" + }); await preloadPartials(); registerHandlebarsHelpers(); registerDice(); diff --git a/dist/system.js.map b/dist/system.js.map index c1607ea..f5bf70a 100644 --- a/dist/system.js.map +++ b/dist/system.js.map @@ -1,7 +1,7 @@ { "version": 3, - "sources": ["../src/config/constants.js", "../src/config/localize.js", "../src/config/runtime.js", "../src/data/actors/character.js", "../src/data/actors/npc.js", "../src/data/actors/tinji.js", "../src/data/actors/loksyu.js", "../src/data/items/item.js", "../src/data/items/kungfu.js", "../src/data/items/spell.js", "../src/data/items/supernatural.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/sheets/actors/base.js", "../src/ui/sheets/actors/character.js", "../src/ui/sheets/actors/npc.js", "../src/ui/sheets/actors/tinji.js", "../src/ui/sheets/actors/loksyu.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/migration.js", "../src/system.js"], - "sourcesContent": ["export const SYSTEM_ID = \"fvtt-chroniques-de-l-etrange\"\n\nexport const ACTOR_TYPES = {\n character: \"character\",\n npc: \"npc\",\n tinji: \"tinji\",\n loksyu: \"loksyu\",\n}\n\nexport const ITEM_TYPES = {\n item: \"item\",\n kungfu: \"kungfu\",\n spell: \"spell\",\n supernatural: \"supernatural\",\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.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n mind: { label: \"CDE.Mind\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n purification: { label: \"CDE.Purification\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n manipulation: { label: \"CDE.Manipulation\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n aura: { label: \"CDE.Aura\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png\", 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.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n elixirs: { label: \"CDE.Elixirs\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n poisons: { label: \"CDE.Poisons\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n arsenal: { label: \"CDE.Arsenal\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n potions: { label: \"CDE.Potions\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png\", 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.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n transfiguration: { label: \"CDE.Transfiguration\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n necromancy: { label: \"CDE.Necromancy\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n climatecontrol: { label: \"CDE.ClimateControl\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n goldenmagic: { label: \"CDE.GoldenMagic\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png\", 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.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n tracking: { label: \"CDE.Tracking\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n protection: { label: \"CDE.Protection\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n punishment: { label: \"CDE.Punishment\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n domination: { label: \"CDE.Domination\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png\", 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.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n divination: { label: \"CDE.Divination\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n earthlyprayer: { label: \"CDE.EarthlyPrayer\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n heavenlyprayer: { label: \"CDE.HeavenlyPrayer\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n fungseoi: { label: \"CDE.Fungseoi\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png\", labelicon: \"Yang\", labelelement: \"CDE.Wood\" },\n },\n },\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-character-spells.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]\n", "import { 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", "export 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", "export 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: stringField(\"0\"),\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 }) }),\n heiyin: new fields.SchemaField({ value: 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", "export 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 levelofthreat: numberField(0, { min: 0 }),\n powerofnuisance: numberField(0, { min: 0 }),\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", "export default class TinjiDataModel 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 htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n return {\n value: numberField(0, { min: 0 }),\n description: htmlField(\"\"),\n }\n }\n}\n", "export default class LoksyuDataModel 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 htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n const polarity = () =>\n new fields.SchemaField({\n yin: new fields.SchemaField({ value: numberField(0, { min: 0 }) }),\n yang: new fields.SchemaField({ value: numberField(0, { min: 0 }) }),\n })\n\n return {\n fire: polarity(),\n earth: polarity(),\n metal: polarity(),\n water: polarity(),\n wood: polarity(),\n description: htmlField(\"\"),\n }\n }\n}\n", "export 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 subtype: stringField(\"\"),\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n quantity: numberField(1, { min: 0 }),\n weight: numberField(0, { min: 0 }),\n protection: stringField(\"\"),\n damage: stringField(\"\"),\n range: stringField(\"\"),\n notes: htmlField(\"\"),\n }\n }\n}\n", "export 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(\"\"),\n technique: htmlField(\"\"),\n })\n\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n orientation: stringField(\"\"),\n aspect: stringField(\"\"),\n skill: stringField(\"\"),\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", "export 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(\"\"),\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 }\n }\n}\n", "export 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 }\n }\n}\n", "export 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 getAssociatedActor() {\n if (this.speaker.scene && this.speaker.token) {\n const scene = game.scenes.get(this.speaker.scene)\n const token = scene?.tokens.get(this.speaker.token)\n if (token) return token.actor\n }\n return game.actors.get(this.speaker.actor)\n }\n\n #enrichChatCard(html) {\n const actor = this.getAssociatedActor()\n\n let img\n let nameText\n if (this.isContentVisible) {\n img = actor?.img ?? this.author.avatar\n nameText = this.alias\n } else {\n img = this.author.avatar\n nameText = this.author.name\n }\n\n const avatar = document.createElement(\"a\")\n avatar.classList.add(\"avatar\")\n if (actor) avatar.dataset.uuid = actor.uuid\n const avatarImg = document.createElement(\"img\")\n Object.assign(avatarImg, { src: img, alt: nameText })\n avatar.append(avatarImg)\n\n const name = document.createElement(\"span\")\n name.classList.add(\"name-stacked\")\n const title = document.createElement(\"span\")\n title.classList.add(\"title\")\n title.append(nameText)\n name.append(title)\n\n const sender = html.querySelector(\".message-sender\")\n sender?.replaceChildren(avatar, name)\n }\n}\n", "import { ACTOR_TYPES } from \"../config/constants.js\"\n\nexport class CDEActor extends Actor {\n getRollData() {\n const data = this.toObject(false).system\n return data\n }\n\n prepareBaseData() {\n super.prepareBaseData()\n\n if (this.type === ACTOR_TYPES.character) {\n this.system.anti_initiative = 25 - (this.system.initiative ?? 0)\n }\n\n if (this.type === ACTOR_TYPES.npc) {\n this.system.vitality.calcul = (this.system.aptitudes.physical.value ?? 0) * 4\n this.system.hei.calcul = (this.system.aptitudes.spiritual.value ?? 0) * 4\n this.system.anti_initiative = 25 - (this.system.initiative ?? 0)\n }\n }\n}\n", "export class CDEItem extends Item {\n get isWeapon() {\n return this.system.subtype === \"weapon\"\n }\n\n get isArmor() {\n return this.system.subtype === \"armor\"\n }\n\n get isSanhei() {\n return this.system.subtype === \"sanhei\"\n }\n\n get isOther() {\n return this.system.subtype === \"other\"\n }\n}\n", "const 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", "import { MAGICS } from \"../config/constants.js\"\n\nexport function registerHandlebarsHelpers() {\n const { Handlebars } = globalThis\n if (!Handlebars) return\n\n Handlebars.registerHelper(\"select\", function (selected, options) {\n const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected))\n const rgx = new RegExp(` value=[\"']${escapedValue}[\"']`)\n const html = options.fn(this)\n return html.replace(rgx, \"$& selected\")\n })\n\n Handlebars.registerHelper(\"getMagicBackground\", function (magic) {\n return game.i18n.localize(MAGICS[magic]?.background ?? \"\")\n })\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(\"getMagicSpecialityIcon\", function (magic, speciality) {\n return MAGICS[magic]?.speciality?.[speciality]?.icon ?? \"\"\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", "import { TEMPLATE_PARTIALS } from \"../config/constants.js\"\n\nexport async function preloadPartials() {\n return loadTemplates(TEMPLATE_PARTIALS)\n}\n", "const { 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: \"auto\" },\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 },\n }\n\n tabGroups = { primary: \"description\" }\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 items: this.document.items.contents,\n descriptionHTML,\n editable: this.isEditable,\n cssClass,\n }\n }\n\n async _onFirstRender(context, options) {\n await super._onFirstRender(context, options)\n for (const [group, tab] of Object.entries(this.tabGroups)) {\n this.changeTab(tab, group, { force: true })\n }\n }\n\n _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 kungfu: \"CDE.KFNew\",\n spell: \"CDE.SpellNew\",\n supernatural: \"CDE.SupernaturalNew\",\n }\n const name = game.i18n.localize(labels[type] ?? \"CDE.ItemNew\")\n return cls.create({ name, type }, { parent: this.document })\n }\n\n static #onItemEdit(event, target) {\n const itemId = target.closest(\".item\")?.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.closest(\".item\")?.dataset.itemId\n const item = this.document.items.get(itemId)\n if (item) item.delete()\n }\n}\n", "import { MAGICS, SUBTYPES } from \"../../../config/constants.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.spells = context.items.filter((item) => item.type === \"spell\")\n context.kungfus = context.items.filter((item) => item.type === \"kungfu\")\n context.CDE = { MAGICS, SUBTYPES }\n return context\n }\n\n _onRender(context, options) {\n super._onRender?.(context, options)\n this.#bindInitiativeControls()\n this.#bindPrefs()\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 const html = `\n
\n
\n \n \n
\n
`\n const value = await Dialog.prompt({\n title: game.i18n.localize(\"CDE.TurnOrder\"),\n content: html,\n label: game.i18n.localize(\"CDE.Validate\"),\n callback: (dlg) => {\n const input = dlg.querySelector(\"input[name='initiative']\")\n return Number(input?.value ?? initiative)\n },\n })\n if (Number.isFinite(value)) {\n const sanitized = foundry.utils.clamp(Number(value), 1, 24)\n await this.document.update({ \"system.initiative\": sanitized })\n }\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 Dialog.prompt({\n title: game.i18n.localize(\"CDE.Preferences\"),\n content: html,\n label: game.i18n.localize(\"CDE.Validate\"),\n callback: (dlg) => {\n const choice = dlg.querySelector(\"select[name='choice']\")?.value ?? \"0\"\n const check = dlg.querySelector(\"input[name='check']\")?.checked ?? false\n return { choice, check }\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", "import { 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.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 }\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 const html = `\n
\n
\n \n \n
\n
`\n const value = await Dialog.prompt({\n title: game.i18n.localize(\"CDE.TurnOrder\"),\n content: html,\n label: game.i18n.localize(\"CDE.Validate\"),\n callback: (dlg) => Number(dlg.querySelector(\"input[name='initiative']\")?.value ?? initiative),\n })\n if (Number.isFinite(value)) {\n const sanitized = foundry.utils.clamp(Number(value), 1, 24)\n await this.document.update({ \"system.initiative\": sanitized })\n }\n }\n })\n })\n }\n}\n", "import { CDEBaseActorSheet } from \"./base.js\"\n\nexport class CDETinjiSheet extends CDEBaseActorSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"tinji\"],\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/actor/cde-tinji-sheet.html\" },\n }\n\n tabGroups = { primary: \"tinji\" }\n}\n", "import { CDEBaseActorSheet } from \"./base.js\"\n\nexport class CDELoksyuSheet extends CDEBaseActorSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"loksyu\"],\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/actor/cde-loksyu-sheet.html\" },\n }\n\n tabGroups = { primary: \"loksyu\" }\n}\n", "const { 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 }\n\n tabGroups = { primary: \"description\" }\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 editable: this.isEditable,\n cssClass,\n enrichedDescription,\n enrichedNotes,\n descriptionHTML: enrichedDescription,\n notesHTML: enrichedNotes,\n }\n }\n\n async _onFirstRender(context, options) {\n await super._onFirstRender(context, options)\n for (const [group, tab] of Object.entries(this.tabGroups)) {\n this.changeTab(tab, group, { force: true })\n }\n }\n\n _onRender(context, options) {\n for (const [group, tab] of Object.entries(this.tabGroups)) {\n this.changeTab(tab, group, { force: true })\n }\n }\n}\n", "import { SUBTYPES } from \"../../../config/constants.js\"\nimport { CDEBaseItemSheet } from \"./base.js\"\n\nexport class CDEItemSheet extends CDEBaseItemSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"equipment\"],\n position: { width: 620, height: 580 },\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/item/cde-item-sheet.html\" },\n }\n\n async _prepareContext() {\n const context = await super._prepareContext()\n context.subtypes = SUBTYPES\n context.isWeapon = this.document.isWeapon\n context.isArmor = this.document.isArmor\n context.isSanhei = this.document.isSanhei\n context.isOther = this.document.isOther\n return context\n }\n}\n", "import { 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", "import { 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", "import { 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", "import { SYSTEM_ID } from \"./config/constants.js\"\n\nconst MIGRATION_VERSION = \"3.0.0\"\n\nexport function registerSettings() {\n game.settings.register(SYSTEM_ID, \"migrationVersion\", {\n name: \"Migration version\",\n scope: \"world\",\n config: false,\n type: String,\n default: \"0.0.0\",\n })\n}\n\nexport async function migrateIfNeeded() {\n const current = game.system.version ?? MIGRATION_VERSION\n const stored = game.settings.get(SYSTEM_ID, \"migrationVersion\") ?? \"0.0.0\"\n if (!isNewerVersion(current, stored)) return\n\n ui.notifications.info(`CHRONIQUESDELETRANGE | Migration vers ${current} en cours...`, { permanent: true })\n await migrateActors()\n await migrateItems()\n await migrateCompendiumActors()\n await migrateCompendiumItems()\n await game.settings.set(SYSTEM_ID, \"migrationVersion\", current)\n ui.notifications.info(`CHRONIQUESDELETRANGE | Migration vers ${current} termin\u00E9e.`)\n}\n\nasync function migrateActors() {\n const updates = []\n for (const actor of game.actors.contents) {\n const updateData = migrateActorData(actor)\n if (Object.keys(updateData).length > 0) {\n updates.push(actor.update(updateData, { enforceTypes: false }))\n }\n }\n await Promise.all(updates)\n}\n\nasync function migrateCompendiumActors() {\n const packs = game.packs.filter((p) => p.documentName === \"Actor\" && p.metadata.system === SYSTEM_ID)\n for (const pack of packs) {\n const content = await pack.getDocuments()\n for (const actor of content) {\n const updateData = migrateActorData(actor)\n if (Object.keys(updateData).length > 0) {\n await actor.update(updateData, { pack: pack.collection, enforceTypes: false })\n }\n }\n }\n}\n\nasync function migrateItems() {\n const updates = []\n for (const item of game.items.contents) {\n const updateData = migrateItemData(item)\n if (Object.keys(updateData).length > 0) {\n updates.push(item.update(updateData, { enforceTypes: false }))\n }\n }\n await Promise.all(updates)\n}\n\nasync function migrateCompendiumItems() {\n const packs = game.packs.filter((p) => p.documentName === \"Item\" && p.metadata.system === SYSTEM_ID)\n for (const pack of packs) {\n const content = await pack.getDocuments()\n for (const item of content) {\n const updateData = migrateItemData(item)\n if (Object.keys(updateData).length > 0) {\n await item.update(updateData, { pack: pack.collection, enforceTypes: false })\n }\n }\n }\n}\n\nfunction migrateActorData(actor) {\n const updateData = {}\n const system = actor.system ?? {}\n const actorType = actor.type\n\n // Fix legacy typo: masteryofthway -> masteryoftheway\n const legacyMagic = system.magics?.masteryofthway\n if (legacyMagic && !system.magics?.masteryoftheway) {\n updateData[\"system.magics.masteryoftheway\"] = legacyMagic\n updateData[\"system.magics.-=masteryofthway\"] = null\n }\n\n // Ensure prefs.typeofthrow exists on relevant actor types\n if ((actorType === \"character\" || actorType === \"npc\") && !system.prefs?.typeofthrow) {\n const defaultCheck = actorType === \"character\"\n updateData[\"system.prefs.typeofthrow\"] = { check: defaultCheck, choice: \"0\" }\n }\n\n return updateData\n}\n\nfunction migrateItemData(item) {\n const updateData = {}\n const system = item.system ?? {}\n\n // Add item-specific migrations here as needed\n\n return updateData\n}\n", "import { ACTOR_TYPES, ITEM_TYPES, MAGICS, SUBTYPES, SYSTEM_ID } from \"./config/constants.js\"\nimport { preLocalizeConfig } from \"./config/localize.js\"\nimport { configureRuntime } from \"./config/runtime.js\"\nimport { CharacterDataModel, LoksyuDataModel, NpcDataModel, TinjiDataModel } from \"./data/actors/index.js\"\nimport { EquipmentDataModel, KungfuDataModel, SpellDataModel, SupernaturalDataModel } 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 { CDELoksyuSheet, CDECharacterSheet, CDENpcSheet, CDETinjiSheet } from \"./ui/sheets/actors/index.js\"\nimport { CDEItemSheet, CDEKungfuSheet, CDESpellSheet, CDESupernaturalSheet } from \"./ui/sheets/items/index.js\"\nimport { migrateIfNeeded, registerSettings } from \"./migration.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 CONFIG.Actor.systemDataModels = {\n [ACTOR_TYPES.character]: CharacterDataModel,\n [ACTOR_TYPES.npc]: NpcDataModel,\n [ACTOR_TYPES.tinji]: TinjiDataModel,\n [ACTOR_TYPES.loksyu]: LoksyuDataModel,\n }\n CONFIG.Item.systemDataModels = {\n [ITEM_TYPES.item]: EquipmentDataModel,\n [ITEM_TYPES.kungfu]: KungfuDataModel,\n [ITEM_TYPES.spell]: SpellDataModel,\n [ITEM_TYPES.supernatural]: SupernaturalDataModel,\n }\n\n CONFIG.Actor.documentClass = CDEActor\n CONFIG.Item.documentClass = CDEItem\n CONFIG.ChatMessage.documentClass = CDEMessage\n\n configureRuntime()\n\n DocumentSheetConfig.unregisterSheet(Actor, \"core\", ActorSheet)\n DocumentSheetConfig.unregisterSheet(Item, \"core\", ItemSheet)\n\n DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDECharacterSheet, {\n types: [ACTOR_TYPES.character],\n makeDefault: true,\n label: \"CDE Character Sheet (V2)\",\n })\n DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDENpcSheet, {\n types: [ACTOR_TYPES.npc],\n makeDefault: true,\n label: \"CDE NPC Sheet (V2)\",\n })\n DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDETinjiSheet, {\n types: [ACTOR_TYPES.tinji],\n makeDefault: true,\n label: \"CDE Tinji Sheet (V2)\",\n })\n DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDELoksyuSheet, {\n types: [ACTOR_TYPES.loksyu],\n makeDefault: true,\n label: \"CDE Loksyu Sheet (V2)\",\n })\n\n DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEItemSheet, {\n types: [ITEM_TYPES.item],\n makeDefault: true,\n label: \"CDE Item Sheet (V2)\",\n })\n DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEKungfuSheet, {\n types: [ITEM_TYPES.kungfu],\n makeDefault: true,\n label: \"CDE KungFu Sheet (V2)\",\n })\n DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESpellSheet, {\n types: [ITEM_TYPES.spell],\n makeDefault: true,\n label: \"CDE Spell Sheet (V2)\",\n })\n DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESupernaturalSheet, {\n types: [ITEM_TYPES.supernatural],\n makeDefault: true,\n label: \"CDE Supernatural Sheet (V2)\",\n })\n\n await preloadPartials()\n registerHandlebarsHelpers()\n registerDice()\n Hooks.on(\"renderSettings\", (_app, html) => injectCompendiumLink(html))\n\n console.info(`CHRONIQUESDELETRANGE | Initialized`)\n})\n\nHooks.once(\"ready\", async () => {\n if (!game.modules.get(\"lib-wrapper\")?.active && game.user.isGM) {\n ui.notifications.error(\"System fvtt-chroniques-de-l-etrange requires the 'libWrapper' module. Please install and activate it.\")\n }\n await migrateIfNeeded()\n})\n\nfunction injectCompendiumLink(html) {\n const header = html[0]?.querySelector?.(\"h4.divider\")\n if (!header) return\n\n const section = document.createElement(\"section\")\n section.classList.add(\"settings\", \"flexcol\")\n section.innerHTML = `\n \n
\n \n
\n Guide d'installation\n \n

Rendez-vous sur le site de l'\u00E9diteur, t\u00E9l\u00E9chargez les PDF contenant les liens vers les compendia, puis ajoutez leurs manifestes dans Foundry.

\n
\n
\n
\n `\n section.querySelector(\"button[data-action='open-cde-link']\")?.addEventListener(\"click\", () => {\n window.open(\"https://antre-monde.com/les-chroniques-de-letrengae/\", \"_blank\")\n })\n\n header.parentNode.insertBefore(section, header)\n}\n"], - "mappings": "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", - "names": ["HandlebarsApplicationMixin"] + "sources": ["../src/config/constants.js", "../src/config/localize.js", "../src/config/runtime.js", "../src/data/actors/character.js", "../src/data/actors/npc.js", "../src/data/actors/tinji.js", "../src/data/actors/loksyu.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/rolling.js", "../src/ui/sheets/actors/base.js", "../src/ui/sheets/actors/character.js", "../src/ui/sheets/actors/npc.js", "../src/ui/sheets/actors/tinji.js", "../src/ui/sheets/actors/loksyu.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/migration.js", "../src/system.js"], + "sourcesContent": ["export const SYSTEM_ID = \"fvtt-chroniques-de-l-etrange\"\n\nexport const ACTOR_TYPES = {\n character: \"character\",\n npc: \"npc\",\n tinji: \"tinji\",\n loksyu: \"loksyu\",\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.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n mind: { label: \"CDE.Mind\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n purification: { label: \"CDE.Purification\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n manipulation: { label: \"CDE.Manipulation\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n aura: { label: \"CDE.Aura\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png\", 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.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n elixirs: { label: \"CDE.Elixirs\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n poisons: { label: \"CDE.Poisons\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n arsenal: { label: \"CDE.Arsenal\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n potions: { label: \"CDE.Potions\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png\", 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.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n transfiguration: { label: \"CDE.Transfiguration\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n necromancy: { label: \"CDE.Necromancy\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n climatecontrol: { label: \"CDE.ClimateControl\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n goldenmagic: { label: \"CDE.GoldenMagic\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png\", 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.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n tracking: { label: \"CDE.Tracking\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n protection: { label: \"CDE.Protection\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n punishment: { label: \"CDE.Punishment\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n domination: { label: \"CDE.Domination\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png\", 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.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png\", labelicon: \"Yin\", labelelement: \"CDE.Metal\" },\n divination: { label: \"CDE.Divination\", classicon: \"icon-yin\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png\", labelicon: \"Yin\", labelelement: \"CDE.Water\" },\n earthlyprayer: { label: \"CDE.EarthlyPrayer\", classicon: \"icon-yinyang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png\", labelicon: \"Yin/Yang\", labelelement: \"CDE.Earth\" },\n heavenlyprayer: { label: \"CDE.HeavenlyPrayer\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png\", labelicon: \"Yang\", labelelement: \"CDE.Fire\" },\n fungseoi: { label: \"CDE.Fungseoi\", classicon: \"icon-yang\", icon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.png\", elementicon: \"/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png\", labelicon: \"Yang\", labelelement: \"CDE.Wood\" },\n },\n },\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-character-spells.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]\n", "import { 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", "export 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", "export 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", "export 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", "export default class TinjiDataModel 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 htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n return {\n value: numberField(0, { min: 0 }),\n description: htmlField(\"\"),\n }\n }\n}\n", "export default class LoksyuDataModel 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 htmlField = (initial = \"\") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true })\n\n const polarity = () =>\n new fields.SchemaField({\n yin: new fields.SchemaField({ value: numberField(0, { min: 0 }) }),\n yang: new fields.SchemaField({ value: numberField(0, { min: 0 }) }),\n })\n\n return {\n fire: polarity(),\n earth: polarity(),\n metal: polarity(),\n water: polarity(),\n wood: polarity(),\n description: htmlField(\"\"),\n }\n }\n}\n", "export 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", "export 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", "export 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(\"cinabre\"),\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", "export 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", "export 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\n return {\n reference: stringField(\"\"),\n description: htmlField(\"\"),\n weaponType: stringField(\"melee\"),\n material: stringField(\"\"),\n damageAspect: stringField(\"metal\"),\n damageBase: intField(1),\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", "export 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", "export 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", "export 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", "export 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 getAssociatedActor() {\n if (this.speaker.scene && this.speaker.token) {\n const scene = game.scenes.get(this.speaker.scene)\n const token = scene?.tokens.get(this.speaker.token)\n if (token) return token.actor\n }\n return game.actors.get(this.speaker.actor)\n }\n\n #enrichChatCard(html) {\n const actor = this.getAssociatedActor()\n\n let img\n let nameText\n if (this.isContentVisible) {\n img = actor?.img ?? this.author.avatar\n nameText = this.alias\n } else {\n img = this.author.avatar\n nameText = this.author.name\n }\n\n const avatar = document.createElement(\"a\")\n avatar.classList.add(\"avatar\")\n if (actor) avatar.dataset.uuid = actor.uuid\n const avatarImg = document.createElement(\"img\")\n Object.assign(avatarImg, { src: img, alt: nameText })\n avatar.append(avatarImg)\n\n const name = document.createElement(\"span\")\n name.classList.add(\"name-stacked\")\n const title = document.createElement(\"span\")\n title.classList.add(\"title\")\n title.append(nameText)\n name.append(title)\n\n const sender = html.querySelector(\".message-sender\")\n sender?.replaceChildren(avatar, name)\n }\n}\n", "import { ACTOR_TYPES } from \"../config/constants.js\"\n\nexport class CDEActor extends Actor {\n getRollData() {\n const data = this.toObject(false).system\n return data\n }\n\n prepareBaseData() {\n super.prepareBaseData()\n\n if (this.type === ACTOR_TYPES.character) {\n this.system.anti_initiative = 25 - (this.system.initiative ?? 0)\n }\n\n if (this.type === ACTOR_TYPES.npc) {\n this.system.vitality.calcul = (this.system.aptitudes.physical.value ?? 0) * 4\n this.system.hei.calcul = (this.system.aptitudes.spiritual.value ?? 0) * 4\n this.system.anti_initiative = 25 - (this.system.initiative ?? 0)\n }\n }\n}\n", "export class CDEItem extends Item {\n get isWeapon() {\n return this.system.subtype === \"weapon\"\n }\n\n get isArmor() {\n return this.system.subtype === \"armor\"\n }\n\n get isSanhei() {\n return this.system.subtype === \"sanhei\"\n }\n\n get isOther() {\n return this.system.subtype === \"other\"\n }\n}\n", "const 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", "import { MAGICS } from \"../config/constants.js\"\n\nexport function registerHandlebarsHelpers() {\n const { Handlebars } = globalThis\n if (!Handlebars) return\n\n Handlebars.registerHelper(\"select\", function (selected, options) {\n const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected))\n const rgx = new RegExp(` value=[\"']${escapedValue}[\"']`)\n const html = options.fn(this)\n return html.replace(rgx, \"$& selected\")\n })\n\n Handlebars.registerHelper(\"getMagicBackground\", function (magic) {\n return game.i18n.localize(MAGICS[magic]?.background ?? \"\")\n })\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(\"getMagicSpecialityIcon\", function (magic, speciality) {\n return MAGICS[magic]?.speciality?.[speciality]?.icon ?? \"\"\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", "import { TEMPLATE_PARTIALS } from \"../config/constants.js\"\n\nexport async function preloadPartials() {\n return loadTemplates(TEMPLATE_PARTIALS)\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) || 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 * 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\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/** Map aspect index \u2192 string name used in result template */\nconst ASPECT_NAMES = [\"metal\", \"water\", \"earth\", \"fire\", \"wood\"]\n\n/** Map aspect name \u2192 i18n label key */\nconst 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 */\nconst ASPECT_ICONS = {\n metal: \"systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png\",\n water: \"systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png\",\n earth: \"systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png\",\n fire: \"systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png\",\n wood: \"systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png\",\n}\n\n/** Map aspect index \u2192 die face pair [yin, yang] (face=10 stored as 0) */\nconst 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/**\n * Wu Xing generating/overcoming cycle:\n * wood \u2192 fire \u2192 earth \u2192 metal \u2192 water \u2192 wood (generating)\n * For each active aspect, the five categories in order:\n * [successes, auspicious, noxious, loksyu, tinji]\n */\nconst 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\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 */\nexport async 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 */\nexport async 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 */\nexport async 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 ?? 1,\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 })\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 \"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(game.system.CONST?.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 ?? 1,\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 ?? 1\n\n const wpTotalDice = wpSkillDice + wpAspectDice + wpRangeMalus + wpBonusMalus - wpWoundMalus\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 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 totalDamage: wpResults.successesdice * wpDamageBase,\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 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 = game.system.CONST?.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", "const { 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 },\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 return cls.create({ name, type }, { parent: this.document })\n }\n\n static #onItemEdit(event, target) {\n const itemId = target.closest(\".item\")?.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.closest(\".item\")?.dataset.itemId\n const item = this.document.items.get(itemId)\n if (item) item.delete()\n }\n}\n", "import { 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 return context\n }\n\n _onRender(context, options) {\n super._onRender?.(context, options)\n this.#bindInitiativeControls()\n this.#bindPrefs()\n this.#bindRollButtons()\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 Dialog.prompt({\n title: game.i18n.localize(\"CDE.Preferences\"),\n content: html,\n label: game.i18n.localize(\"CDE.Validate\"),\n callback: (dlg) => {\n const choice = dlg.querySelector(\"select[name='choice']\")?.value ?? \"0\"\n const check = dlg.querySelector(\"input[name='check']\")?.checked ?? false\n return { choice, check }\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", "import { rollInitiativeNPC } from \"../../initiative.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.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 }\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", "import { CDEBaseActorSheet } from \"./base.js\"\n\nexport class CDETinjiSheet extends CDEBaseActorSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"tinji\"],\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/actor/cde-tinji-sheet.html\" },\n }\n\n tabGroups = { primary: \"tinji\" }\n}\n", "import { CDEBaseActorSheet } from \"./base.js\"\n\nexport class CDELoksyuSheet extends CDEBaseActorSheet {\n static DEFAULT_OPTIONS = {\n classes: [\"loksyu\"],\n }\n\n static PARTS = {\n main: { template: \"systems/fvtt-chroniques-de-l-etrange/templates/actor/cde-loksyu-sheet.html\" },\n }\n\n tabGroups = { primary: \"loksyu\" }\n}\n", "const { 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 }\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", "import { 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", "import { 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", "import { 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", "import { 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", "import { 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", "import { 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", "import { 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", "import { 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", "import { SYSTEM_ID } from \"./config/constants.js\"\n\nconst MIGRATION_VERSION = \"3.0.0\"\n\nexport function registerSettings() {\n game.settings.register(SYSTEM_ID, \"migrationVersion\", {\n name: \"Migration version\",\n scope: \"world\",\n config: false,\n type: String,\n default: \"0.0.0\",\n })\n}\n\nexport async function migrateIfNeeded() {\n const current = game.system.version ?? MIGRATION_VERSION\n const stored = game.settings.get(SYSTEM_ID, \"migrationVersion\") ?? \"0.0.0\"\n if (!foundry.utils.isNewerVersion(current, stored)) return\n\n ui.notifications.info(`CHRONIQUESDELETRANGE | Migration vers ${current} en cours...`, { permanent: true })\n await migrateActors()\n await migrateItems()\n await migrateCompendiumActors()\n await migrateCompendiumItems()\n await game.settings.set(SYSTEM_ID, \"migrationVersion\", current)\n ui.notifications.info(`CHRONIQUESDELETRANGE | Migration vers ${current} termin\u00E9e.`)\n}\n\nasync function migrateActors() {\n const updates = []\n for (const actor of game.actors.contents) {\n const updateData = migrateActorData(actor)\n if (Object.keys(updateData).length > 0) {\n updates.push(actor.update(updateData, { enforceTypes: false }))\n }\n }\n await Promise.all(updates)\n}\n\nasync function migrateCompendiumActors() {\n const packs = game.packs.filter((p) => p.documentName === \"Actor\" && p.metadata.system === SYSTEM_ID)\n for (const pack of packs) {\n const content = await pack.getDocuments()\n for (const actor of content) {\n const updateData = migrateActorData(actor)\n if (Object.keys(updateData).length > 0) {\n await actor.update(updateData, { pack: pack.collection, enforceTypes: false })\n }\n }\n }\n}\n\nasync function migrateItems() {\n const updates = []\n for (const item of game.items.contents) {\n const updateData = migrateItemData(item)\n if (Object.keys(updateData).length > 0) {\n updates.push(item.update(updateData, { enforceTypes: false }))\n }\n }\n await Promise.all(updates)\n}\n\nasync function migrateCompendiumItems() {\n const packs = game.packs.filter((p) => p.documentName === \"Item\" && p.metadata.system === SYSTEM_ID)\n for (const pack of packs) {\n const content = await pack.getDocuments()\n for (const item of content) {\n const updateData = migrateItemData(item)\n if (Object.keys(updateData).length > 0) {\n await item.update(updateData, { pack: pack.collection, enforceTypes: false })\n }\n }\n }\n}\n\nfunction migrateActorData(actor) {\n const updateData = {}\n const system = actor.system ?? {}\n const actorType = actor.type\n\n // Fix legacy typo: masteryofthway -> masteryoftheway\n const legacyMagic = system.magics?.masteryofthway\n if (legacyMagic && !system.magics?.masteryoftheway) {\n updateData[\"system.magics.masteryoftheway\"] = legacyMagic\n updateData[\"system.magics.-=masteryofthway\"] = null\n }\n\n // Ensure prefs.typeofthrow exists on relevant actor types\n if ((actorType === \"character\" || actorType === \"npc\") && !system.prefs?.typeofthrow) {\n const defaultCheck = actorType === \"character\"\n updateData[\"system.prefs.typeofthrow\"] = { check: defaultCheck, choice: \"0\" }\n }\n\n // Migrate NPC field renames: levelofthreat \u2192 threat, powerofnuisance \u2192 nuisance\n if (actorType === \"npc\") {\n if (system.levelofthreat !== undefined && system.threat === undefined) {\n updateData[\"system.threat\"] = system.levelofthreat\n updateData[\"system.-=levelofthreat\"] = null\n }\n if (system.powerofnuisance !== undefined && system.nuisance === undefined) {\n updateData[\"system.nuisance\"] = system.powerofnuisance\n updateData[\"system.-=powerofnuisance\"] = null\n }\n }\n\n // Migrate character guardian from string to number\n if (actorType === \"character\" && typeof system.guardian === \"string\") {\n const guardianNum = parseInt(system.guardian, 10)\n if (!isNaN(guardianNum)) {\n updateData[\"system.guardian\"] = guardianNum\n }\n }\n\n return updateData\n}\n\nfunction migrateItemData(item) {\n const updateData = {}\n const system = item.system ?? {}\n\n // Add item-specific migrations here as needed\n\n return updateData\n}\n", "import { ACTOR_TYPES, ITEM_TYPES, MAGICS, SUBTYPES, SYSTEM_ID } from \"./config/constants.js\"\nimport { preLocalizeConfig } from \"./config/localize.js\"\nimport { configureRuntime } from \"./config/runtime.js\"\nimport { CharacterDataModel, LoksyuDataModel, NpcDataModel, TinjiDataModel } 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 { CDELoksyuSheet, CDECharacterSheet, CDENpcSheet, CDETinjiSheet } from \"./ui/sheets/actors/index.js\"\nimport { CDEItemSheet, CDEKungfuSheet, CDESpellSheet, CDESupernaturalSheet, CDEWeaponSheet, CDEArmorSheet, CDESanheiSheet, CDEIngredientSheet } from \"./ui/sheets/items/index.js\"\nimport { migrateIfNeeded, registerSettings } from \"./migration.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 CONFIG.Actor.dataModels = {\n [ACTOR_TYPES.character]: CharacterDataModel,\n [ACTOR_TYPES.npc]: NpcDataModel,\n [ACTOR_TYPES.tinji]: TinjiDataModel,\n [ACTOR_TYPES.loksyu]: LoksyuDataModel,\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\", ActorSheet)\n foundry.applications.apps.DocumentSheetConfig.unregisterSheet(Item, \"core\", 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 foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDETinjiSheet, {\n types: [ACTOR_TYPES.tinji],\n makeDefault: true,\n label: \"CDE Tinji Sheet (V2)\",\n })\n foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDELoksyuSheet, {\n types: [ACTOR_TYPES.loksyu],\n makeDefault: true,\n label: \"CDE Loksyu 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 Hooks.on(\"renderSettings\", (_app, html) => injectCompendiumLink(html))\n\n console.info(`CHRONIQUESDELETRANGE | Initialized`)\n})\n\nHooks.once(\"ready\", async () => {\n if (!game.modules.get(\"lib-wrapper\")?.active && game.user.isGM) {\n ui.notifications.error(\"System fvtt-chroniques-de-l-etrange requires the 'libWrapper' module. Please install and activate it.\")\n }\n await migrateIfNeeded()\n})\n\nfunction injectCompendiumLink(html) {\n const header = html[0]?.querySelector?.(\"h4.divider\")\n if (!header) return\n\n const section = document.createElement(\"section\")\n section.classList.add(\"settings\", \"flexcol\")\n section.innerHTML = `\n \n
\n \n
\n Guide d'installation\n \n

Rendez-vous sur le site de l'\u00E9diteur, t\u00E9l\u00E9chargez les PDF contenant les liens vers les compendia, puis ajoutez leurs manifestes dans Foundry.

\n
\n
\n
\n `\n section.querySelector(\"button[data-action='open-cde-link']\")?.addEventListener(\"click\", () => {\n window.open(\"https://antre-monde.com/les-chroniques-de-letrengae/\", \"_blank\")\n })\n\n header.parentNode.insertBefore(section, header)\n}\n"], + "mappings": "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", + "names": ["RESULT_TEMPLATE", "HandlebarsApplicationMixin"] } diff --git a/fonts/Averia-Regular.ttf b/fonts/Averia-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f5e06c11a286f54c7cdd2c0a40e4cfff60db5d73 GIT binary patch literal 78448 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 Ao&W#< literal 0 HcmV?d00001 diff --git a/lang/en-cde.json b/lang/en-cde.json index d3285d6..6d11719 100644 --- a/lang/en-cde.json +++ b/lang/en-cde.json @@ -172,11 +172,16 @@ "CDE.SpellDelete": "Delete Spell", "CDE.SpellNew": "New Spell", - "CDE.SkillPromptName": "", + "CDE.SkillPromptName": "Skill Roll", + "CDE.Modifiers": "Modifiers", "CDE.BonusMalus": "Bonus/Malus D", + "CDE.WoundMalus": "Wound Malus", + "CDE.HeiSpend": "HEI Spend", + "CDE.SpellBonus": "Spell Bonus", + "CDE.SpellPower": "Spell Power", "CDE.BonusAuspiciousDice": "Bonus/Auspicious-Dice", - "CDE.MagicPromptName": "", + "CDE.MagicPromptName": "Magic Roll", "CDE.OneMagicRoll": "1. Magic Roll", "CDE.DoNotModify": "Do not Modify this Aspect", "CDE.AspectSkill": "Aspect/Skill", @@ -203,7 +208,7 @@ "CDE.Apprentice": "Apprentice", "CDE.Initiate": "Initiate", "CDE.Accomplished": "Accomplished", - "CDE.Reknowned": "Reknowned", + "CDE.Renowned": "Renowned", "CDE.Nuisance": "Level of Nuisance", "CDE.Figurant": "Figurant", @@ -211,7 +216,7 @@ "CDE.Adversary": "Adversary", "CDE.Ally": "Ally", "CDE.Boss": "Boss", - "CDE.Dininity": "Divinity", + "CDE.Divinity": "Divinity", "CDE.Aptitudes": "Aptitudes", "CDE.SuperNatural": "Supernatural Abilities", @@ -336,5 +341,27 @@ "spell": "Spell", "supernatural": "Supernatural Ability" } - } + }, + "CDE.WeaponCreate": "Create Weapon", + "CDE.ArmorCreate": "Create Armor", + "CDE.SanheiCreate": "Create San Hei", + "CDE.IngredientCreate": "Create Ingredient", + "CDE.WeaponNew": "New Weapon", + "CDE.ArmorNew": "New Armor", + "CDE.SanheiNew": "New San Hei", + "CDE.IngredientNew": "New Ingredient", + "CDE.ArmorType": "Armor", + "CDE.SanheiType": "San Hei", + "CDE.IngredientType": "Ingredient", + "CDE.ItemType": "Item", + "CDE.Weapons": "Weapons", + "CDE.Armors": "Armors", + "CDE.Sanheis": "San Hei", + "CDE.CreatureMortel": "Mortal", + "CDE.CreatureDemon": "Demon", + "CDE.CreatureEsprit": "Spirit", + "CDE.CreatureEspritAnimal": "Animal Spirit", + "CDE.CreatureFantome": "Ghost", + "CDE.CreatureJiugwaai": "Jiugwaai", + "CDE.CreatureDieu": "God / Divinity" } diff --git a/lang/es-cde.json b/lang/es-cde.json index f9208a3..3b919ed 100644 --- a/lang/es-cde.json +++ b/lang/es-cde.json @@ -203,7 +203,7 @@ "CDE.Apprentice": "Aprendiz", "CDE.Initiate": "Iniciado", "CDE.Accomplished": "Consumado", - "CDE.Reknowned": "Renombrado", + "CDE.Renowned": "Renombrado", "CDE.Nuisance": "Capacitad de Molesta", "CDE.Figurant": "Extra", @@ -211,7 +211,7 @@ "CDE.Adversary": "Adversario", "CDE.Ally": "Aliado", "CDE.Boss": "Jefe", - "CDE.Dininity": "Deidad", + "CDE.Divinity": "Deidad", "CDE.Aptitudes": "Aptitudes", "CDE.SuperNatural": "Habilidades Sobrenaturales", diff --git a/lang/fr-cde.json b/lang/fr-cde.json index 8f949b1..724d53a 100644 --- a/lang/fr-cde.json +++ b/lang/fr-cde.json @@ -1,340 +1,370 @@ { - "CDE.ItemCreate": "Créer un Équipement", - "CDE.ItemEdit": "Éditer l′Équipement", - "CDE.ItemDelete": "Supprimer l′Équipement", - "CDE.ItemNew": "Nouvel Équipement", - - "CDE.TypeOfItem": "Type d′Équipement", - "CDE.Weapon": "Arme", + "CDE.Accomplished": "Accompli", + "CDE.Activation": "Activation", + "CDE.ActivationAid": "Action d'Aide", + "CDE.ActivationAttack": "Action d'attaque", + "CDE.ActivationAttackOrDefense": "Action d'attaque ou de défense", + "CDE.ActivationDamageInflicted": "Dégâts infligés", + "CDE.ActivationDamageReceived": "Dégâts reçus", + "CDE.ActivationDefense": "Action de défense", + "CDE.ActivationDice": "Dés-fastes", + "CDE.ActivationReaction": "Réaction", + "CDE.Acupuncture": "Acupuncture", + "CDE.Adversary": "Adversaire", + "CDE.Alchemy": "Alchimie", + "CDE.Ally": "Allié", + "CDE.AntiInitiative": "Anti-Initiative", + "CDE.Apprentice": "Apprenti", + "CDE.Aptitudes": "Aptitudes", "CDE.Armor": "Protection", - "CDE.Sanhei": "Sanhei", - "CDE.Other": "Autre", - - - "CDE.ResourceMin": "Min", - "CDE.ResourceValue": "Valeur", - "CDE.ResourceMax": "Max", - - "CDE.DefineTemplate": "Définir comme Modèle", - "CDE.UnsetTemplate": "Désactiver le Modèle", - "CDE.NoTemplate": "Aucun Modèle", - - "CDE.Quantity": "Quantité", - "CDE.Weight": "Poids", - "CDE.Damage": "Dégâts", - "CDE.Range": "Portée", - - "CDE.Masterized": "Vous maîtrisez cette Technique", - - "CDE.Create": "Créer", - "CDE.New": "Nouveau", - - "CDE.Name": "Nom", - "CDE.PCName": "Nom du Personnage", - "CDE.Concept": "Concept", + "CDE.Arsenal": "Arsenal", + "CDE.Art": "Art", + "CDE.Aspect": "Aspect", + "CDE.AspectSkill": "Aspect/Compétence", + "CDE.AspectSpeciality": "Aspect/Spécialité", + "CDE.AssociatedElement": "Élément Associé", + "CDE.Attributes": "Attributs", + "CDE.Aura": "Aura", + "CDE.AuspiciousDice": "Dés-fastes", + "CDE.AuspiciousDie": "Dé-faste", + "CDE.Beneficial": "Dés-Fastes", + "CDE.BonusAuspiciousDice": "Bonus/Dés-fastes", + "CDE.Modifiers": "Modificateurs", + "CDE.WoundMalus": "Malus blessures", + "CDE.HeiSpend": "Dépense HEI", + "CDE.SpellBonus": "Bonus Sort", + "CDE.SpellPower": "Puissance du Sort", + "CDE.Boss": "Boss", + "CDE.Cancel": "Annuler", + "CDE.CancelChanges": "Annuler les modifications", "CDE.CelestialGuardian": "Gardien Céleste", "CDE.CelestialGuardian1": "Tigre Blanc (Métal)", "CDE.CelestialGuardian2": "Tortue Noire (Eau)", "CDE.CelestialGuardian3": "Kirin Jaune (Terre)", "CDE.CelestialGuardian4": "Oiseau Écarlate (Feu)", "CDE.CelestialGuardian5": "Dragon d′Azur (Bois)", - - "CDE.Description": "Description", - "CDE.Description2" : "Descript.", - "CDE.Attributes": "Attributs", - "CDE.Skills": "Compétences", - "CDE.Magics": "Magies", - "CDE.Resources": "Ressources", - "CDE.Treasures": "Trois Trésors", - "CDE.NgHang": "Ng Hang", - "CDE.Items": "Équipement", - "CDE.KungFu": "Kung Fu", - "CDE.Spells": "Sortilèges", - "CDE.ModernJapan": "Japon contemporain", - - "CDE.Die": "Cliquez ici pour jeter les dés pour ", - "CDE.DieSP": "Cliquez ici pour jeter les dés pour la spécialité ", - "CDE.DieDM": "Cliquez ici pour jeter les dés pour un de ces domaines", - "CDE.Debt": "Cochez si vous avec contracté une dette en ", - - "CDE.Specialities": "Spécialités", - "CDE.Fields": "Domaines", - "CDE.Art": "Art", - "CDE.Investigation": "Enquête", - "CDE.Erudition": "Érudition", - "CDE.Knavery": "Filouterie", - "CDE.Wordliness": "Mondanités", - "CDE.Prowess": "Prouesse", - "CDE.Sciences": "Sciences", - "CDE.Technologies": "Technologies", - "CDE.RangedCombat": "Combat à Distance", - - "CDE.Supply": "Matériel", - "CDE.Inquiry": "Renseignement", - "CDE.Influence": "Influence", - - "CDE.Components2": "Composants & Ingrédients", - "CDE.Component": "Composant n° ", "CDE.ChanceThrow": "Choisir un composant au hasard dans l′urgence", - "CDE.TypesOfMagic": "Types de Magie", - - "CDE.InternalCinnabar": "Cinabre Interne", - "CDE.Alchemy": "Alchimie", - "CDE.MasteryOfTheWay": "Maîtrise de la Voie", - "CDE.Exorcism": "Exorcisme", - "CDE.Geomancy": "Géomancie", - "CDE.WoodYin": "㊍ Bois Yin (4)", - - "CDE.Metal": "㊎ Métal ", - "CDE.MetalQualities": "– agressif, passionné, combatif, enthousiate…", - "CDE.Water": "㊌ Eau ", - "CDE.WaterQualities": "– souple, appliqué, adaptable, discipliné…", + "CDE.ClimateControl": "Maîtrise Climatique", + "CDE.Component": "Composant n° ", + "CDE.Components": "Composantes", + "CDE.Components2": "Composants & Ingrédients", + "CDE.Concept": "Concept", + "CDE.Create": "Créer", + "CDE.Curse": "Malédiction", + "CDE.DMOnly": "Le MJ uniquement", + "CDE.Damage": "Dégâts", + "CDE.DamageAspect": "Aspect des dégâts", + "CDE.DamageBase": "Dégâts de base", + "CDE.Data": "Données", + "CDE.Debt": "Cochez si vous avec contracté une dette en ", + "CDE.DefineTemplate": "Définir comme Modèle", + "CDE.Description": "Description", + "CDE.Description2": "Descript.", + "CDE.Details": "Détails", + "CDE.DeterminateInitiative": "Déterminer l'initiative : Prouesse + première action", + "CDE.DeterminateNPCInitiative": "Déterminer l'initiative : Aptitude physique + première action", + "CDE.Die": "Cliquez ici pour jeter les dés pour ", + "CDE.DieDM": "Cliquez ici pour jeter les dés pour un de ces domaines", + "CDE.DieSP": "Cliquez ici pour jeter les dés pour la spécialité ", + "CDE.Difficulty": "Difficulté", + "CDE.Divinity": "Divinité", + "CDE.Discipline": "Discipline", + "CDE.Divination": "Divination", + "CDE.DoNotModify": "Ne modifiez pas cet Aspect", + "CDE.Domain": "Domaine d'accès", + "CDE.Domination": "Domination", "CDE.Earth": "㊏ Terre ", "CDE.EarthQualities": "– obstiné, résilient, endurant, patient…", - "CDE.Fire": "㊋ Feu ", - "CDE.FireQualities": "– chaleureux, créatif, empathique, inspiré…", - "CDE.Wood": "㊍ Bois ", - "CDE.WoodQualities": "– intuitif, observateur, ouvert, instinctif…", - - "CDE.PracticeSpecialty": "Cochez si vous pratiquez la spécialité ", - - "CDE.Essence": "Essence", - "CDE.Mind": "Esprit", - "CDE.Purification": "Purification", - "CDE.Manipulation": "Manipulation", - "CDE.Aura": "Aura", - - "CDE.Acupuncture": "Acupuncture", - "CDE.Elixirs": "Élixirs", - "CDE.Poisons": "Poisons", - "CDE.Arsenal": "Arsenal", - "CDE.Potions": "Philtres", - - "CDE.Curse": "Malédiction", - "CDE.Transfiguration": "Transfiguration", - "CDE.Necromancy": "Nécromancie", - "CDE.ClimateControl": "Maîtrise Climatique", - "CDE.GoldenMagic": "Magie d′Or", - - "CDE.Invocation": "Invocation", - "CDE.Tracking": "Traque", - "CDE.Protection": "Protection", - "CDE.Punishment": "Punition", - "CDE.Domination": "Domination", - - "CDE.Neutralization": "Neutralisation", - "CDE.Divination": "Divination", - "CDE.EarthlyPrayer": "Prière Terrestre", - "CDE.HeavenlyPrayer": "Prière Céleste", - "CDE.Fungseoi": "Fungseoi", - - "CDE.HEI": "HEI", - "CDE.Essence2": "(Essence)", - "CDE.YANG-YIN": "YANG ● YIN", - "CDE.Max-Present-Present-Max": "Max ● Actuel ● Actuel ● Max", - "CDE.SAN-ZING": "SAN ● ZING", - "CDE.MentalHealth-PhysicalHealth": "(Santé Mentale ● Santé Physique)", - "CDE.Max-Present-Malus-Present-Max": "Max ● Actuel ● Malus ● Actuel ● Max", - "CDE.PTAO": "PTAO", - "CDE.Experience": "(Expérience)", - "CDE.Total-Present": "Total ● Actuel", - - "CDE.Present": "Actuel", - "CDE.Total": "Total", - "CDE.Max": "Max", - - "CDE.Orientation": "Orientation", - "CDE.Aspect": "Aspect", - "CDE.Skill": "Compétence", - "CDE.Speciality": "Spécialité", - "CDE.Field": "Domaine", - "CDE.Style": "Style", - "CDE.Technique": "Technique", - "CDE.Activation": "Activation", - - "CDE.KFCreate": "Créer un Art Martial", - "CDE.KFEdit": "Éditer l′Art Martial", - "CDE.KFDelete": "Supprimer l′Art Martial", - "CDE.KFNew": "Nouvel Art Martial", - - "CDE.SpecialityName": "Nom Spécialité", - "CDE.AssociatedElement": "Élément Associé", - "CDE.HEI2": "Hei", - "CDE.RealizationTimeRitual": "Temps de Réalisation (Rituel)", - "CDE.RealizationTimeAccelerated": "Temps de Réalisation (Accéléré)", - "CDE.Flashback": "Flash-back", - "CDE.Data": "Données", - "CDE.Components": "Composantes", - "CDE.Effects": "Effets", - "CDE.Examples": "Exemples", - - "CDE.SpellCreate": "Créer un Sortilège", - "CDE.SpellEdit": "Éditer le Sortilège", - "CDE.SpellDelete": "Supprimer le Sortilège", - "CDE.SpellNew": "Nouveau Sortilège", - - "CDE.SkillPromptName": "", - "CDE.BonusMalus": "D Bonus/Malus", - "CDE.BonusAuspiciousDice": "Bonus/Dés-fastes", - - "CDE.MagicPromptName": "", - "CDE.OneMagicRoll": "1. Jet de Magie", - "CDE.DoNotModify": "Ne modifiez pas cet Aspect", - "CDE.AspectSkill": "Aspect/Compétence", - "CDE.TwoPowerOfSpell": "2. Puissance du Sort", - "CDE.AspectSpeciality": "Aspect/Spécialité", - "CDE.RollDifficulty": "Difficulté du Jet", - - "CDE.TypeOfThrow": "Type de jet : visible pour…", - "CDE.Everybody": "Tout le monde", - "CDE.JustDMAndMe": "Juste le MJ et moi", - "CDE.DMOnly": "Le MJ uniquement", - "CDE.MeOnly": "Moi uniquement", - "CDE.AuspiciousDice": "Dés-fastes", - "CDE.AuspiciousDie": "Dé-faste", - - "CDE.Validate": "Valider", - "CDE.Cancel": "Annuler", - - "CDE.NPCName": "Nom du PNJ", - "CDE.TypeOfCreature": "Type de Créature", - - "CDE.Threat": "Niveau de Menace", - "CDE.Profane": "Profane", - "CDE.Apprentice": "Apprenti", - "CDE.Initiate": "Initié", - "CDE.Accomplished": "Accompli", - "CDE.Reknowned": "Renommé", - - "CDE.Nuisance": "Capacité de Nuisance", - "CDE.Figurant": "Figurant", - "CDE.Minion": "Sbire", - "CDE.Adversary": "Adversaire", - "CDE.Ally": "Allié", - "CDE.Boss": "Boss", - "CDE.Dininity": "Divinité", - - "CDE.Aptitudes": "Aptitudes", - "CDE.SuperNatural": "Capacités Surnaturelles", - - "CDE.Physical": "● Physique", - "CDE.Martial": "● Martiale", - "CDE.Mental": "● Mentale", - "CDE.Social": "● Sociale", - "CDE.Spiritual": "● Spirituelle", - - "CDE.Vitality": "Vitalité", - "CDE.Hei": "Hei", - - "CDE.Notes": "Notes", - - "CDE.SupernaturalCreate": "Créer une Capacité Surnaturelle", - "CDE.SupernaturalEdit": "Éditer la Capacité Surnaturelle", - "CDE.SupernaturalDelete": "Supprimer la Capacité Surnaturelle", - "CDE.SupernaturalNew": "Nouvelle Capacité Surnaturelle", - - "CDE.LoksyuName": "Nom du Loksyu", - "CDE.Loksyu": "Loksyu", - "CDE.MetalYang": "㊎ Métal Yang (3)", - "CDE.MetalYin": "㊎ Métal Yin (8)", - "CDE.WaterYang": "㊌ Eau Yang (1)", - "CDE.WaterYin": "㊌ Eau Yin (6)", "CDE.EarthYang": "㊏ Terre Yang (5)", "CDE.EarthYin": "㊏ Terre Yin (0)", - "CDE.FireYang": "㊋ Feu Yang (7)", - "CDE.FireYin": "㊋ Feu Yin (2)", - "CDE.WoodYang": "㊍ Bois Yang (9)", - - "CDE.Yin": "● Yin", - "CDE.Yang": "○ Yang", - "CDE.Successes": "Succès", - "CDE.Beneficial": "Dés-Fastes", - "CDE.Noxious": "Dés-Néfastes", - "CDE.TinJi": "Tin Ji :", - "CDE.Loksyu2": "Loksyu :", - "CDE.Results": "Résultats :", - "CDE.SpecialAspect": "Aspect Spécialité", - - "CDE.Randomize": "Tirage aléatoire", - "CDE.RandomizeSentence": "n° du composant choisi au hasard dans l'urgence", - - "CDE.Reference": "Référence", - + "CDE.EarthlyPrayer": "Prière Terrestre", + "CDE.Effects": "Effets", + "CDE.Elixirs": "Élixirs", "CDE.Error0": "Impossible de poursuivre : le nombre total de vos dés à lancer est inférieur à 1.", "CDE.Error1": "Impossible de poursuivre : vous ne possédez pas cette Compétence.", + "CDE.Error10": "Impossible de poursuivre : vous avez 0 ou moins dans cet Aspect.", + "CDE.Error12": "Impossible de poursuivre : vous ne pouvez pas posséder de Spécialité dans cette Compétence dont le score est inférieur à 1.", + "CDE.Error14": "Impossible de poursuivre : vous ne pouvez pas posséder de Domaine dans cette Ressource dont le score est inférieur à 1.", + "CDE.Error16": "Impossible de poursuivre : vous ne pouvez pas posséder de Spécialité dans cette Compétence de Magie dont le score est inférieur à 1.", "CDE.Error2": "Impossible de poursuivre : vous ne possédez pas de Spécialité dans cette Compétence.", "CDE.Error3": "Impossible de poursuivre : vous ne possédez pas cette Ressource.", "CDE.Error4": "Impossible de poursuivre : vous ne possédez pas de Domaine dans cette Ressource.", "CDE.Error5": "Impossible de poursuivre : vous ne possédez pas cette Compétence de Magie.", "CDE.Error6": "Impossible de poursuivre : vous ne possédez pas cette Spécialité dans cette Compétence de Magie.", - "CDE.Error10": "Impossible de poursuivre : vous avez 0 ou moins dans cet Aspect.", - "CDE.Error12": "Impossible de poursuivre : vous ne pouvez pas posséder de Spécialité dans cette Compétence dont le score est inférieur à 1.", - "CDE.Error14": "Impossible de poursuivre : vous ne pouvez pas posséder de Domaine dans cette Ressource dont le score est inférieur à 1.", - "CDE.Error16": "Impossible de poursuivre : vous ne pouvez pas posséder de Spécialité dans cette Compétence de Magie dont le score est inférieur à 1.", - - "CDE.Preferences": "Préférences pour cet acteur", - "CDE.TypeOfThrowCheck": "Toujours demander avant d'effectuer un lancer", - - "CDE.TypeOfThrow4ThisTime": "Type de jet pour cette fois : visible pour…", - "CDE.TypeOfThrowTitle": "Modifier le type de jet ?", - "CDE.CancelChanges": "Annuler les modifications", - - "CDE.NextTimeGoToTheSettings": "Tout ceci est paramétrable dans les Préférences", - - - "CDE.OneDie": "dé", - "CDE.ManyDice": "dés", - + "CDE.Erudition": "Érudition", + "CDE.Essence": "Essence", + "CDE.Essence2": "(Essence)", + "CDE.Everybody": "Tout le monde", + "CDE.Examples": "Exemples", + "CDE.Exorcism": "Exorcisme", + "CDE.Experience": "(Expérience)", + "CDE.Field": "Domaine", + "CDE.Fields": "Domaines", + "CDE.Figurant": "Figurant", + "CDE.Fire": "㊋ Feu ", + "CDE.FirstAction": "Première action", + "CDE.FireQualities": "– chaleureux, créatif, empathique, inspiré…", + "CDE.FireYang": "㊋ Feu Yang (7)", + "CDE.FireYin": "㊋ Feu Yin (2)", + "CDE.Flashback": "Flash-back", + "CDE.Fungseoi": "Fungseoi", + "CDE.Geomancy": "Géomancie", + "CDE.GoldenMagic": "Magie d′Or", + "CDE.HEI": "HEI", + "CDE.HEI2": "Hei", "CDE.HasCastASpell": "a lancé un sortilège ", + "CDE.HeavenlyPrayer": "Prière Céleste", + "CDE.Hei": "Hei", + "CDE.HeiCost": "Coût en Hei", + "CDE.HeiType": "Type de Hei", + "CDE.HeiYang": "Yang", + "CDE.HeiYin": "Yin", + "CDE.Influence": "Influence", + "CDE.Ingredient": "Ingrédient", + "CDE.Ingredients": "Ingrédients", + "CDE.Initiate": "Initié", + "CDE.Initiative": "Initiative", + "CDE.InitiativeBonus": "Modificateur", + "CDE.InitiativeFormula": "Prouesse + Première action choisie", + "CDE.InitiativeFormulaNPC": "Aptitude physique + Première action choisie", + "CDE.InitiativeNPCSpeciality": "Première action (Aptitude) que vous escomptez effectuer", + "CDE.InitiativeRoll": "Jet d'initiative", + "CDE.InitiativeSpeciality": "Première action (Compétence) que vous escomptez effectuer", + "CDE.Inquiry": "Renseignement", + "CDE.InternalCinnabar": "Cinabre Interne", + "CDE.Investigation": "Enquête", + "CDE.Invocation": "Invocation", + "CDE.ItemCreate": "Créer un Équipement", + "CDE.ItemDelete": "Supprimer l′Équipement", + "CDE.ItemEdit": "Éditer l′Équipement", + "CDE.ItemNew": "Nouvel Équipement", + "CDE.Items": "Équipement", + "CDE.JustDMAndMe": "Juste le MJ et moi", + "CDE.KFCreate": "Créer un Art Martial", + "CDE.KFDelete": "Supprimer l′Art Martial", + "CDE.KFEdit": "Éditer l′Art Martial", + "CDE.KFNew": "Nouvel Art Martial", + "CDE.Knavery": "Filouterie", + "CDE.KungFu": "Kung Fu", + "CDE.Loksyu": "Loksyu", + "CDE.Loksyu2": "Loksyu :", + "CDE.LoksyuName": "Nom du Loksyu", + "CDE.MagicPromptName": "Jet de Magie", + "CDE.Magics": "Magies", + "CDE.Manipulation": "Manipulation", + "CDE.ManyDice": "dés", + "CDE.Martial": "● Martiale", + "CDE.MartialArts": "Arts Martiaux", + "CDE.Masterized": "Vous maîtrisez cette Technique", + "CDE.MasteryOfTheWay": "Maîtrise de la Voie", + "CDE.Max": "Max", + "CDE.Max-Present-Malus-Present-Max": "Max ● Actuel ● Malus ● Actuel ● Max", + "CDE.Max-Present-Present-Max": "Max ● Actuel ● Actuel ● Max", + "CDE.MeOnly": "Moi uniquement", + "CDE.Mental": "● Mentale", + "CDE.MentalHealth-PhysicalHealth": "(Santé Mentale ● Santé Physique)", + "CDE.Metal": "㊎ Métal ", + "CDE.MetalQualities": "– agressif, passionné, combatif, enthousiate…", + "CDE.MetalYang": "㊎ Métal Yang (3)", + "CDE.MetalYin": "㊎ Métal Yin (8)", + "CDE.Mind": "Esprit", + "CDE.Minion": "Sbire", + "CDE.MinusInitiative": "Moins Initiative", + "CDE.ModernJapan": "Japon contemporain", "CDE.MsgMagic1": "Le nombre de points de Hei dépensés pour le sort de spécialité ", "CDE.MsgMagic2": "s'élève à ", "CDE.MsgMagic3": ". La puissance à invoquer est de ", "CDE.MsgMagic4": ", si toutefois le sort est lancé avec succès.", - - - "CDE.TinJiName": "Nom de la Tin Ji", + "CDE.NPCName": "Nom du PNJ", + "CDE.Name": "Nom", + "CDE.Necromancy": "Nécromancie", + "CDE.Neutralization": "Neutralisation", + "CDE.New": "Nouveau", + "CDE.NextTimeGoToTheSettings": "Tout ceci est paramétrable dans les Préférences", + "CDE.NgHang": "Ng Hang", + "CDE.NoTemplate": "Aucun Modèle", + "CDE.Notes": "Notes", + "CDE.Noxious": "Dés-Néfastes", + "CDE.Nuisance": "Capacité de Nuisance", + "CDE.ObtainDifficulty": "Diff. d'obtention", + "CDE.ObtainLevel": "Niv. d'obtention", + "CDE.OneDie": "dé", + "CDE.OneMagicRoll": "1. Jet de Magie", + "CDE.Orientation": "Orientation", + "CDE.OrientationYang": "Yang (offensif)", + "CDE.OrientationYin": "Yin (défensif)", + "CDE.OrientationYinYang": "Yin ou Yang", + "CDE.Other": "Autre", + "CDE.PCName": "Nom du Personnage", + "CDE.PTAO": "PTAO", + "CDE.Physical": "● Physique", + "CDE.PlusInitiative": "Plus Initiative", + "CDE.Poisons": "Poisons", + "CDE.Potions": "Philtres", + "CDE.PracticeSpecialty": "Cochez si vous pratiquez la spécialité ", + "CDE.Preferences": "Préférences pour cet acteur", + "CDE.Present": "Actuel", + "CDE.Profane": "Profane", + "CDE.Property": "Propriété", + "CDE.Protection": "Protection", + "CDE.ProtectionValue": "Valeur de protection", + "CDE.Prowess": "Prouesse", + "CDE.Punishment": "Punition", + "CDE.Purification": "Purification", + "CDE.Quantity": "Quantité", + "CDE.Randomize": "Tirage aléatoire", + "CDE.RandomizeSentence": "n° du composant choisi au hasard dans l'urgence", + "CDE.Range": "Portée", + "CDE.RangeContact": "Au contact", + "CDE.RangeCourte": "Distance courte", + "CDE.RangeExtreme": "Distance extrême", + "CDE.RangeLongue": "Distance longue", + "CDE.RangeMediane": "Distance médiane", + "CDE.RangedCombat": "Combat à Distance", + "CDE.RealizationTimeAccelerated": "Temps de Réalisation (Accéléré)", + "CDE.RealizationTimeRitual": "Temps de Réalisation (Rituel)", + "CDE.Reference": "Référence", + "CDE.Renowned": "Renommé", + "CDE.ResourceMax": "Max", + "CDE.ResourceMin": "Min", + "CDE.ResourceValue": "Valeur", + "CDE.Resources": "Ressources", + "CDE.Results": "Résultats :", + "CDE.RollDifficulty": "Difficulté du Jet", + "CDE.SAN-ZING": "SAN ● ZING", + "CDE.Sanhei": "Sanhei", + "CDE.SanheiProperties": "Propriétés du sanhei", + "CDE.School": "École", + "CDE.SchoolAlchemy": "Alchimie", + "CDE.SchoolAll": "Toutes disciplines", + "CDE.SchoolCinabre": "Cinabre interne", + "CDE.SchoolExorcisme": "Exorcisme", + "CDE.SchoolGeomancy": "Géomancie", + "CDE.SchoolVoie": "Maîtrise de la Voie", + "CDE.Sciences": "Sciences", + "CDE.Skill": "Compétence", + "CDE.SkillCombatDistance": "Combat à distance", + "CDE.SkillKungfu": "Kung-fu", + "CDE.SkillPromptName": "Jet de Compétence", + "CDE.Skills": "Compétences", + "CDE.Social": "● Sociale", + "CDE.SpecialAspect": "Aspect Spécialité", + "CDE.Specialities": "Spécialités", + "CDE.Speciality": "Spécialité", + "CDE.SpecialityName": "Nom Spécialité", + "CDE.SpellCreate": "Créer un Sortilège", + "CDE.SpellDelete": "Supprimer le Sortilège", + "CDE.SpellEdit": "Éditer le Sortilège", + "CDE.SpellNew": "Nouveau Sortilège", + "CDE.Spells": "Sortilèges", + "CDE.Spiritual": "● Spirituelle", + "CDE.Style": "Style", + "CDE.Successes": "Succès", + "CDE.SuperNatural": "Capacités Surnaturelles", + "CDE.SupernaturalCreate": "Créer une Capacité Surnaturelle", + "CDE.SupernaturalDelete": "Supprimer la Capacité Surnaturelle", + "CDE.SupernaturalEdit": "Éditer la Capacité Surnaturelle", + "CDE.SupernaturalNew": "Nouvelle Capacité Surnaturelle", + "CDE.Supply": "Matériel", + "CDE.Technique": "Technique", + "CDE.Technologies": "Technologies", + "CDE.Threat": "Niveau de Menace", + "CDE.TinJi": "Tin Ji :", "CDE.TinJi2": "Tin Ji", - - "CDE.UpperCaseSuccesses": "SUCCÈS", + "CDE.TinJiName": "Nom de la Tin Ji", + "CDE.Total": "Total", + "CDE.Total-Present": "Total ● Actuel", + "CDE.Tracking": "Traque", + "CDE.Transfiguration": "Transfiguration", + "CDE.Treasures": "Trois Trésors", + "CDE.Trigger": "Déclenchement", + "CDE.TurnOrder": "Détermination de votre initiative", + "CDE.TwoPowerOfSpell": "2. Puissance du Sort", + "CDE.TypeOfCreature": "Type de Créature", + "CDE.TypeOfItem": "Type d′Équipement", + "CDE.TypeOfThrow": "Type de jet : visible pour…", + "CDE.TypeOfThrow4ThisTime": "Type de jet pour cette fois : visible pour…", + "CDE.TypeOfThrowCheck": "Toujours demander avant d'effectuer un lancer", + "CDE.TypeOfThrowTitle": "Modifier le type de jet ?", + "CDE.TypesOfMagic": "Types de Magie", + "CDE.UnsetTemplate": "Désactiver le Modèle", "CDE.UpperCaseAuspiciousDice": "DÉS-FASTES", - "CDE.UpperCaseNoxiousDice": "DÉS-NÉFASTES", - "CDE.UpperCaseLoksyu": "LOKSYU", - "CDE.UpperCaseTinJi": "TIN JI", - - "CDE.UpperCaseMetal": "METAL", - "CDE.UpperCaseWater": "EAU", "CDE.UpperCaseEarth": "TERRE", "CDE.UpperCaseFire": "FEU", + "CDE.UpperCaseLoksyu": "LOKSYU", + "CDE.UpperCaseMetal": "METAL", + "CDE.UpperCaseNoxiousDice": "DÉS-NÉFASTES", + "CDE.UpperCaseSuccesses": "SUCCÈS", + "CDE.UpperCaseTinJi": "TIN JI", + "CDE.UpperCaseWater": "EAU", "CDE.UpperCaseWood": "BOIS", - - + "CDE.Validate": "Valider", "CDE.Visible": "Spécialités visibles", - - "CDE.MartialArts": "Arts Martiaux", - - "CDE.Initiative": "Initiative", - "CDE.TurnOrder": "Détermination de votre initiative", - "CDE.InitiativeSpeciality": "Première action (Compétence) que vous escomptez effectuer", - "CDE.InitiativeNPCSpeciality": "Première action (Aptitude) que vous escomptez effectuer", - - "CDE.DeterminateInitiative": "Déterminer l'initiative : Prouesse + première action", - "CDE.DeterminateNPCInitiative": "Déterminer l'initiative : Aptitude physique + première action", - "CDE.PlusInitiative": "Plus Initiative", - "CDE.MinusInitiative": "Moins Initiative", - - + "CDE.Vitality": "Vitalité", + "CDE.Water": "㊌ Eau ", + "CDE.WaterQualities": "– souple, appliqué, adaptable, discipliné…", + "CDE.WaterYang": "㊌ Eau Yang (1)", + "CDE.WaterYin": "㊌ Eau Yin (6)", + "CDE.Weapon": "Arme", + "CDE.WeaponFirearm": "Arme à feu", + "CDE.WeaponMelee": "Arme blanche", + "CDE.WeaponRanged": "Arme à distance", + "CDE.WeaponThrown": "Arme de jet", + "CDE.WeaponType": "Type d'arme", + "CDE.Weight": "Poids", + "CDE.Wood": "㊍ Bois ", + "CDE.WoodQualities": "– intuitif, observateur, ouvert, instinctif…", + "CDE.WoodYang": "㊍ Bois Yang (9)", + "CDE.WoodYin": "㊍ Bois Yin (4)", + "CDE.Wordliness": "Mondanités", + "CDE.YANG-YIN": "YANG ● YIN", + "CDE.Yang": "○ Yang", + "CDE.Yin": "● Yin", "TYPES": { "Actor": { "character": "Fat si", + "loksyu": "Loksyu", "npc": "Créature", - "tinji": "Tin Ji", - "loksyu": "Loksyu" + "tinji": "Tin Ji" }, "Item": { + "armor": "Protection", + "ingredient": "Ingrédient", "item": "Équipement", "kungfu": "Art martial", + "sanhei": "Sanhei", "spell": "Sortilège", - "supernatural": "Capacité surnaturelle" + "supernatural": "Capacité surnaturelle", + "weapon": "Arme" } - } + }, + "CDE.WeaponCreate": "Créer une arme", + "CDE.ArmorCreate": "Créer une protection", + "CDE.SanheiCreate": "Créer un San Hei", + "CDE.IngredientCreate": "Créer un ingrédient", + "CDE.WeaponNew": "Nouvelle arme", + "CDE.ArmorNew": "Nouvelle protection", + "CDE.SanheiNew": "Nouveau San Hei", + "CDE.IngredientNew": "Nouvel ingrédient", + "CDE.ArmorType": "Protection", + "CDE.SanheiType": "San Hei", + "CDE.IngredientType": "Ingrédient", + "CDE.ItemType": "Objet", + "CDE.Weapons": "Armes", + "CDE.Armors": "Protections", + "CDE.Sanheis": "San Hei", + "CDE.CreatureMortel": "Mortel", + "CDE.CreatureDemon": "Démon", + "CDE.CreatureEsprit": "Esprit", + "CDE.CreatureEspritAnimal": "Esprit animal", + "CDE.CreatureFantome": "Fantôme", + "CDE.CreatureJiugwaai": "Jiugwaai", + "CDE.CreatureDieu": "Dieu / Divinité", + + "CDE.WeaponRollTitle": "Jet d'attaque", + "CDE.EffectiveRange": "Portée effective", + "CDE.TotalDamage": "Dommages", + "CDE.WeaponRoll": "Jet d'arme", + "CDE.RangePenalty": "Pénalité de portée", + "CDE.SuccessTimesDamage": "succès × dégâts de base" } diff --git a/package.json b/package.json index 366b140..6e316c3 100644 --- a/package.json +++ b/package.json @@ -22,5 +22,8 @@ "devDependencies": { "esbuild": "^0.27.4", "less": "^4.2.0" + }, + "dependencies": { + "puppeteer-core": "^24.40.0" } } diff --git a/packs/aide-pour-fxmaster/000035.log b/packs/aide-pour-fxmaster/000051.log similarity index 100% rename from packs/aide-pour-fxmaster/000035.log rename to packs/aide-pour-fxmaster/000051.log diff --git a/packs/aide-pour-fxmaster/CURRENT b/packs/aide-pour-fxmaster/CURRENT index eea9b0f..7570f19 100644 --- a/packs/aide-pour-fxmaster/CURRENT +++ b/packs/aide-pour-fxmaster/CURRENT @@ -1 +1 @@ -MANIFEST-000034 +MANIFEST-000050 diff --git a/packs/aide-pour-fxmaster/LOG b/packs/aide-pour-fxmaster/LOG index 0584037..06a4743 100644 --- a/packs/aide-pour-fxmaster/LOG +++ b/packs/aide-pour-fxmaster/LOG @@ -1,3 +1,3 @@ -2026/03/25-23:20:54.993495 7f90f7fff6c0 Recovering log #32 -2026/03/25-23:20:55.003177 7f90f7fff6c0 Delete type=3 #30 -2026/03/25-23:20:55.003228 7f90f7fff6c0 Delete type=0 #32 +2026/03/26-23:22:41.148674 7f90f77fe6c0 Recovering log #48 +2026/03/26-23:22:41.202546 7f90f77fe6c0 Delete type=3 #46 +2026/03/26-23:22:41.202617 7f90f77fe6c0 Delete type=0 #48 diff --git a/packs/aide-pour-fxmaster/LOG.old b/packs/aide-pour-fxmaster/LOG.old index ea2e5c7..982f1d0 100644 --- a/packs/aide-pour-fxmaster/LOG.old +++ b/packs/aide-pour-fxmaster/LOG.old @@ -1,7 +1,7 @@ -2026/03/25-23:09:24.686953 7f90f67fc6c0 Recovering log #27 -2026/03/25-23:09:24.697512 7f90f67fc6c0 Delete type=3 #25 -2026/03/25-23:09:24.697571 7f90f67fc6c0 Delete type=0 #27 -2026/03/25-23:20:49.874535 7f90f5ffb6c0 Level-0 table #33: started -2026/03/25-23:20:49.874573 7f90f5ffb6c0 Level-0 table #33: 0 bytes OK -2026/03/25-23:20:49.881637 7f90f5ffb6c0 Delete type=0 #31 -2026/03/25-23:20:49.894392 7f90f5ffb6c0 Manual compaction at level-0 from '!journal!ZWBHiWW5QlUeseAX' @ 72057594037927935 : 1 .. '!journal.pages!ZWBHiWW5QlUeseAX.jtQXIqLfyet8Nlte' @ 0 : 0; will stop at (end) +2026/03/26-22:00:22.685636 7f90f7fff6c0 Recovering log #44 +2026/03/26-22:00:22.746783 7f90f7fff6c0 Delete type=3 #42 +2026/03/26-22:00:22.746837 7f90f7fff6c0 Delete type=0 #44 +2026/03/26-23:22:30.433416 7f90f5ffb6c0 Level-0 table #49: started +2026/03/26-23:22:30.433442 7f90f5ffb6c0 Level-0 table #49: 0 bytes OK +2026/03/26-23:22:30.471510 7f90f5ffb6c0 Delete type=0 #47 +2026/03/26-23:22:30.471678 7f90f5ffb6c0 Manual compaction at level-0 from '!journal!ZWBHiWW5QlUeseAX' @ 72057594037927935 : 1 .. '!journal.pages!ZWBHiWW5QlUeseAX.jtQXIqLfyet8Nlte' @ 0 : 0; will stop at (end) diff --git a/packs/aide-pour-fxmaster/MANIFEST-000034 b/packs/aide-pour-fxmaster/MANIFEST-000050 similarity index 62% rename from packs/aide-pour-fxmaster/MANIFEST-000034 rename to packs/aide-pour-fxmaster/MANIFEST-000050 index f2dd8dae08813c2b4265778cd30638816dd74ab7..01c2e93df6c3ddbbd259b1d37b7416c515028891 100644 GIT binary patch delta 22 ecmX@hc$RU(KK}1sD_?UkFfti)GBBI4XaWFYkp_AI delta 22 ecmX@hc$RU(KK>(1m|k%(Ffu7~GBB&KXaWFRSq0eu diff --git a/packs/aide-pour-la-lumiere/000151.log b/packs/aide-pour-la-lumiere/000167.log similarity index 100% rename from packs/aide-pour-la-lumiere/000151.log rename to packs/aide-pour-la-lumiere/000167.log diff --git a/packs/aide-pour-la-lumiere/CURRENT b/packs/aide-pour-la-lumiere/CURRENT index 939d9b8..830373b 100644 --- a/packs/aide-pour-la-lumiere/CURRENT +++ b/packs/aide-pour-la-lumiere/CURRENT @@ -1 +1 @@ -MANIFEST-000150 +MANIFEST-000166 diff --git a/packs/aide-pour-la-lumiere/LOG b/packs/aide-pour-la-lumiere/LOG index 55c10ed..f27573e 100644 --- a/packs/aide-pour-la-lumiere/LOG +++ b/packs/aide-pour-la-lumiere/LOG @@ -1,3 +1,3 @@ -2026/03/25-23:20:54.979842 7f90f67fc6c0 Recovering log #148 -2026/03/25-23:20:54.991234 7f90f67fc6c0 Delete type=3 #146 -2026/03/25-23:20:54.991298 7f90f67fc6c0 Delete type=0 #148 +2026/03/26-23:22:41.093289 7f90f67fc6c0 Recovering log #164 +2026/03/26-23:22:41.146507 7f90f67fc6c0 Delete type=3 #162 +2026/03/26-23:22:41.146560 7f90f67fc6c0 Delete type=0 #164 diff --git a/packs/aide-pour-la-lumiere/LOG.old b/packs/aide-pour-la-lumiere/LOG.old index 7206f05..13525dd 100644 --- a/packs/aide-pour-la-lumiere/LOG.old +++ b/packs/aide-pour-la-lumiere/LOG.old @@ -1,8 +1,8 @@ -2026/03/25-23:09:24.673117 7f90f7fff6c0 Recovering log #143 -2026/03/25-23:09:24.683104 7f90f7fff6c0 Delete type=3 #141 -2026/03/25-23:09:24.683202 7f90f7fff6c0 Delete type=0 #143 -2026/03/25-23:20:49.854866 7f90f5ffb6c0 Level-0 table #149: started -2026/03/25-23:20:49.854893 7f90f5ffb6c0 Level-0 table #149: 0 bytes OK -2026/03/25-23:20:49.861669 7f90f5ffb6c0 Delete type=0 #147 -2026/03/25-23:20:49.874373 7f90f5ffb6c0 Manual compaction at level-0 from '!journal!TniC3ok9W0hDYxJS' @ 72057594037927935 : 1 .. '!journal.pages!yZsG9QaBHT3cUfNd.AHcfBcO96nUCELxv' @ 0 : 0; will stop at (end) -2026/03/25-23:20:49.874418 7f90f5ffb6c0 Manual compaction at level-1 from '!journal!TniC3ok9W0hDYxJS' @ 72057594037927935 : 1 .. '!journal.pages!yZsG9QaBHT3cUfNd.AHcfBcO96nUCELxv' @ 0 : 0; will stop at (end) +2026/03/26-22:00:22.608830 7f90f67fc6c0 Recovering log #160 +2026/03/26-22:00:22.665730 7f90f67fc6c0 Delete type=3 #158 +2026/03/26-22:00:22.665947 7f90f67fc6c0 Delete type=0 #160 +2026/03/26-23:22:30.583548 7f90f5ffb6c0 Level-0 table #165: started +2026/03/26-23:22:30.583573 7f90f5ffb6c0 Level-0 table #165: 0 bytes OK +2026/03/26-23:22:30.620608 7f90f5ffb6c0 Delete type=0 #163 +2026/03/26-23:22:30.620784 7f90f5ffb6c0 Manual compaction at level-0 from '!journal!TniC3ok9W0hDYxJS' @ 72057594037927935 : 1 .. '!journal.pages!yZsG9QaBHT3cUfNd.AHcfBcO96nUCELxv' @ 0 : 0; will stop at (end) +2026/03/26-23:22:30.620826 7f90f5ffb6c0 Manual compaction at level-1 from '!journal!TniC3ok9W0hDYxJS' @ 72057594037927935 : 1 .. '!journal.pages!yZsG9QaBHT3cUfNd.AHcfBcO96nUCELxv' @ 0 : 0; will stop at (end) diff --git a/packs/aide-pour-la-lumiere/MANIFEST-000150 b/packs/aide-pour-la-lumiere/MANIFEST-000166 similarity index 61% rename from packs/aide-pour-la-lumiere/MANIFEST-000150 rename to packs/aide-pour-la-lumiere/MANIFEST-000166 index 68a39ca452e6b8955124a286f2591bd092c30d7d..7c765e8410b7c3ff0576a1aa616b7d06165f20de 100644 GIT binary patch delta 25 hcmcb}c#(0!ej)E?b@#a$7@3wcaxyTlU}Rar2mpCh2dn@9 delta 25 hcmcb}c#(0!exY0U?&xtdFfvVN^Q(2p#|c delta 25 hcmcb}c#(0!excSY`@Far7@01!axySqVP!eZ1OR%92m=5B diff --git a/packs/aides-pour-les-joueuses/004344.log b/packs/aides-pour-les-joueuses/004360.log similarity index 100% rename from packs/aides-pour-les-joueuses/004344.log rename to packs/aides-pour-les-joueuses/004360.log diff --git a/packs/aides-pour-les-joueuses/CURRENT b/packs/aides-pour-les-joueuses/CURRENT index f955117..da36800 100644 --- a/packs/aides-pour-les-joueuses/CURRENT +++ b/packs/aides-pour-les-joueuses/CURRENT @@ -1 +1 @@ -MANIFEST-004343 +MANIFEST-004359 diff --git a/packs/aides-pour-les-joueuses/LOG b/packs/aides-pour-les-joueuses/LOG index b0eb014..4551611 100644 --- a/packs/aides-pour-les-joueuses/LOG +++ b/packs/aides-pour-les-joueuses/LOG @@ -1,3 +1,3 @@ -2026/03/25-23:20:54.941740 7f90f67fc6c0 Recovering log #4341 -2026/03/25-23:20:54.952935 7f90f67fc6c0 Delete type=3 #4339 -2026/03/25-23:20:54.952993 7f90f67fc6c0 Delete type=0 #4341 +2026/03/26-23:22:40.912790 7f90f67fc6c0 Recovering log #4357 +2026/03/26-23:22:40.970516 7f90f67fc6c0 Delete type=3 #4355 +2026/03/26-23:22:40.970566 7f90f67fc6c0 Delete type=0 #4357 diff --git a/packs/aides-pour-les-joueuses/LOG.old b/packs/aides-pour-les-joueuses/LOG.old index 4c750a2..44b9c8d 100644 --- a/packs/aides-pour-les-joueuses/LOG.old +++ b/packs/aides-pour-les-joueuses/LOG.old @@ -1,7 +1,7 @@ -2026/03/25-23:09:24.632404 7f90f7fff6c0 Recovering log #4337 -2026/03/25-23:09:24.642953 7f90f7fff6c0 Delete type=3 #4335 -2026/03/25-23:09:24.643019 7f90f7fff6c0 Delete type=0 #4337 -2026/03/25-23:20:49.861772 7f90f5ffb6c0 Level-0 table #4342: started -2026/03/25-23:20:49.861806 7f90f5ffb6c0 Level-0 table #4342: 0 bytes OK -2026/03/25-23:20:49.867856 7f90f5ffb6c0 Delete type=0 #4340 -2026/03/25-23:20:49.874387 7f90f5ffb6c0 Manual compaction at level-0 from '!journal!0lxwWrzKsdTBQhH0' @ 72057594037927935 : 1 .. '!journal.pages!wgSyae4GTJDkmBOm.6Ql0lgquUCTrMyTZ' @ 0 : 0; will stop at (end) +2026/03/26-22:00:22.375122 7f90f67fc6c0 Recovering log #4353 +2026/03/26-22:00:22.431093 7f90f67fc6c0 Delete type=3 #4351 +2026/03/26-22:00:22.431156 7f90f67fc6c0 Delete type=0 #4353 +2026/03/26-23:22:30.322515 7f90f5ffb6c0 Level-0 table #4358: started +2026/03/26-23:22:30.322564 7f90f5ffb6c0 Level-0 table #4358: 0 bytes OK +2026/03/26-23:22:30.358054 7f90f5ffb6c0 Delete type=0 #4356 +2026/03/26-23:22:30.471641 7f90f5ffb6c0 Manual compaction at level-0 from '!journal!0lxwWrzKsdTBQhH0' @ 72057594037927935 : 1 .. '!journal.pages!wgSyae4GTJDkmBOm.6Ql0lgquUCTrMyTZ' @ 0 : 0; will stop at (end) diff --git a/packs/aides-pour-les-joueuses/MANIFEST-004343 b/packs/aides-pour-les-joueuses/MANIFEST-004359 similarity index 91% rename from packs/aides-pour-les-joueuses/MANIFEST-004343 rename to packs/aides-pour-les-joueuses/MANIFEST-004359 index 62e403b95184839b3ea662f6f1078e28498dc38f..bfa151c855ad0e446196136c41acd1a101f436db 100644 GIT binary patch delta 25 hcmcb_c!_bs0ioxa*8;g27@0bhI2o8bl~^va004QS2gm>b delta 25 hcmcb_c!_bs0ig|bI)2;?j7&ciIT@ILDzaQ;0RVE}2iE`q diff --git a/packs/cantonese-name-generators/000064.log b/packs/cantonese-name-generators/000080.log similarity index 100% rename from packs/cantonese-name-generators/000064.log rename to packs/cantonese-name-generators/000080.log diff --git a/packs/cantonese-name-generators/CURRENT b/packs/cantonese-name-generators/CURRENT index e8c0266..dad8bc0 100644 --- a/packs/cantonese-name-generators/CURRENT +++ b/packs/cantonese-name-generators/CURRENT @@ -1 +1 @@ -MANIFEST-000063 +MANIFEST-000079 diff --git a/packs/cantonese-name-generators/LOG b/packs/cantonese-name-generators/LOG index fd7a27e..f6bd268 100644 --- a/packs/cantonese-name-generators/LOG +++ b/packs/cantonese-name-generators/LOG @@ -1,3 +1,3 @@ -2026/03/25-23:20:55.028995 7f90f6ffd6c0 Recovering log #61 -2026/03/25-23:20:55.038606 7f90f6ffd6c0 Delete type=3 #59 -2026/03/25-23:20:55.038658 7f90f6ffd6c0 Delete type=0 #61 +2026/03/26-23:22:41.320339 7f90f6ffd6c0 Recovering log #77 +2026/03/26-23:22:41.378833 7f90f6ffd6c0 Delete type=3 #75 +2026/03/26-23:22:41.378896 7f90f6ffd6c0 Delete type=0 #77 diff --git a/packs/cantonese-name-generators/LOG.old b/packs/cantonese-name-generators/LOG.old index 4645c7e..3c214b5 100644 --- a/packs/cantonese-name-generators/LOG.old +++ b/packs/cantonese-name-generators/LOG.old @@ -1,8 +1,8 @@ -2026/03/25-23:09:24.728225 7f90f7fff6c0 Recovering log #56 -2026/03/25-23:09:24.738919 7f90f7fff6c0 Delete type=3 #54 -2026/03/25-23:09:24.738983 7f90f7fff6c0 Delete type=0 #56 -2026/03/25-23:20:49.894409 7f90f5ffb6c0 Level-0 table #62: started -2026/03/25-23:20:49.894444 7f90f5ffb6c0 Level-0 table #62: 0 bytes OK -2026/03/25-23:20:49.900567 7f90f5ffb6c0 Delete type=0 #60 -2026/03/25-23:20:49.907833 7f90f5ffb6c0 Manual compaction at level-0 from '!tables!J9VdvrwkbyKxMAT7' @ 72057594037927935 : 1 .. '!tables.results!jGKjfCyk4ROSy9fU.zRzADzATtijaBdNX' @ 0 : 0; will stop at (end) -2026/03/25-23:20:49.907898 7f90f5ffb6c0 Manual compaction at level-1 from '!tables!J9VdvrwkbyKxMAT7' @ 72057594037927935 : 1 .. '!tables.results!jGKjfCyk4ROSy9fU.zRzADzATtijaBdNX' @ 0 : 0; will stop at (end) +2026/03/26-22:00:22.875118 7f90f77fe6c0 Recovering log #73 +2026/03/26-22:00:22.937050 7f90f77fe6c0 Delete type=3 #71 +2026/03/26-22:00:22.937152 7f90f77fe6c0 Delete type=0 #73 +2026/03/26-23:22:30.545930 7f90f5ffb6c0 Level-0 table #78: started +2026/03/26-23:22:30.545959 7f90f5ffb6c0 Level-0 table #78: 0 bytes OK +2026/03/26-23:22:30.583434 7f90f5ffb6c0 Delete type=0 #76 +2026/03/26-23:22:30.620775 7f90f5ffb6c0 Manual compaction at level-0 from '!tables!J9VdvrwkbyKxMAT7' @ 72057594037927935 : 1 .. '!tables.results!jGKjfCyk4ROSy9fU.zRzADzATtijaBdNX' @ 0 : 0; will stop at (end) +2026/03/26-23:22:30.620818 7f90f5ffb6c0 Manual compaction at level-1 from '!tables!J9VdvrwkbyKxMAT7' @ 72057594037927935 : 1 .. '!tables.results!jGKjfCyk4ROSy9fU.zRzADzATtijaBdNX' @ 0 : 0; will stop at (end) diff --git a/packs/cantonese-name-generators/MANIFEST-000063 b/packs/cantonese-name-generators/MANIFEST-000079 similarity index 92% rename from packs/cantonese-name-generators/MANIFEST-000063 rename to packs/cantonese-name-generators/MANIFEST-000079 index 50d70e636c893dba0f4f05278bba9385f17d07fb..59f57371fb6e77cfddaa521fa789f0f131b116cb 100644 GIT binary patch delta 23 ecmcb>c!6=k0RaJxiffzc!6=k0fDacyZ}Ry1Xch5 delta 22 dcmbQkIEQgUFTcXg(}Elfj7++m49t2gyZ}k51it_P diff --git a/packs/macros/000223.log b/packs/macros/000239.log similarity index 100% rename from packs/macros/000223.log rename to packs/macros/000239.log diff --git a/packs/macros/CURRENT b/packs/macros/CURRENT index a8d01b2..4846f49 100644 --- a/packs/macros/CURRENT +++ b/packs/macros/CURRENT @@ -1 +1 @@ -MANIFEST-000222 +MANIFEST-000238 diff --git a/packs/macros/LOG b/packs/macros/LOG index 4fa850d..977ea00 100644 --- a/packs/macros/LOG +++ b/packs/macros/LOG @@ -1,3 +1,3 @@ -2026/03/25-23:20:55.005125 7f90f77fe6c0 Recovering log #220 -2026/03/25-23:20:55.015600 7f90f77fe6c0 Delete type=3 #218 -2026/03/25-23:20:55.015651 7f90f77fe6c0 Delete type=0 #220 +2026/03/26-23:22:41.206104 7f90f6ffd6c0 Recovering log #236 +2026/03/26-23:22:41.262267 7f90f6ffd6c0 Delete type=3 #234 +2026/03/26-23:22:41.262335 7f90f6ffd6c0 Delete type=0 #236 diff --git a/packs/macros/LOG.old b/packs/macros/LOG.old index b62e667..b821612 100644 --- a/packs/macros/LOG.old +++ b/packs/macros/LOG.old @@ -1,8 +1,8 @@ -2026/03/25-23:09:24.701586 7f90f6ffd6c0 Recovering log #216 -2026/03/25-23:09:24.712861 7f90f6ffd6c0 Delete type=3 #214 -2026/03/25-23:09:24.712933 7f90f6ffd6c0 Delete type=0 #216 -2026/03/25-23:20:49.881844 7f90f5ffb6c0 Level-0 table #221: started -2026/03/25-23:20:49.881867 7f90f5ffb6c0 Level-0 table #221: 0 bytes OK -2026/03/25-23:20:49.888032 7f90f5ffb6c0 Delete type=0 #219 -2026/03/25-23:20:49.900708 7f90f5ffb6c0 Manual compaction at level-0 from '!macros!Admg6zBHid4mfbJY' @ 72057594037927935 : 1 .. '!macros!wY3tga12higX7soz' @ 0 : 0; will stop at (end) -2026/03/25-23:20:49.907859 7f90f5ffb6c0 Manual compaction at level-1 from '!macros!Admg6zBHid4mfbJY' @ 72057594037927935 : 1 .. '!macros!wY3tga12higX7soz' @ 0 : 0; will stop at (end) +2026/03/26-22:00:22.749196 7f90f6ffd6c0 Recovering log #232 +2026/03/26-22:00:22.804213 7f90f6ffd6c0 Delete type=3 #230 +2026/03/26-22:00:22.804283 7f90f6ffd6c0 Delete type=0 #232 +2026/03/26-23:22:30.471790 7f90f5ffb6c0 Level-0 table #237: started +2026/03/26-23:22:30.471814 7f90f5ffb6c0 Level-0 table #237: 0 bytes OK +2026/03/26-23:22:30.508477 7f90f5ffb6c0 Delete type=0 #235 +2026/03/26-23:22:30.620742 7f90f5ffb6c0 Manual compaction at level-0 from '!macros!Admg6zBHid4mfbJY' @ 72057594037927935 : 1 .. '!macros!wY3tga12higX7soz' @ 0 : 0; will stop at (end) +2026/03/26-23:22:30.620792 7f90f5ffb6c0 Manual compaction at level-1 from '!macros!Admg6zBHid4mfbJY' @ 72057594037927935 : 1 .. '!macros!wY3tga12higX7soz' @ 0 : 0; will stop at (end) diff --git a/packs/macros/MANIFEST-000222 b/packs/macros/MANIFEST-000238 similarity index 65% rename from packs/macros/MANIFEST-000222 rename to packs/macros/MANIFEST-000238 index 0543dc36f575f7a924f0e1f1fc63dfe00b124b8a..6df7fca99087eedb7a0f27ac4cd1ae21855deeff 100644 GIT binary patch delta 25 hcmX@ic$jg*Mxo_$ACtKm7@6KPaxyS~U}R}v1ORfN2Xz1d delta 25 hcmX@ic$jg*Mxo>1p6umjU}U<_$jQL`fRUwv5den12$}!@ diff --git a/packs/telecharger-compendiums/000965.log b/packs/telecharger-compendiums/000981.log similarity index 100% rename from packs/telecharger-compendiums/000965.log rename to packs/telecharger-compendiums/000981.log diff --git a/packs/telecharger-compendiums/CURRENT b/packs/telecharger-compendiums/CURRENT index 6169e01..2f512cb 100644 --- a/packs/telecharger-compendiums/CURRENT +++ b/packs/telecharger-compendiums/CURRENT @@ -1 +1 @@ -MANIFEST-000964 +MANIFEST-000980 diff --git a/packs/telecharger-compendiums/LOG b/packs/telecharger-compendiums/LOG index 7932ff6..0f53b1d 100644 --- a/packs/telecharger-compendiums/LOG +++ b/packs/telecharger-compendiums/LOG @@ -1,3 +1,3 @@ -2026/03/25-23:20:54.955460 7f90f6ffd6c0 Recovering log #962 -2026/03/25-23:20:54.965054 7f90f6ffd6c0 Delete type=3 #960 -2026/03/25-23:20:54.965130 7f90f6ffd6c0 Delete type=0 #962 +2026/03/26-23:22:40.972919 7f90f77fe6c0 Recovering log #978 +2026/03/26-23:22:41.035302 7f90f77fe6c0 Delete type=3 #976 +2026/03/26-23:22:41.035379 7f90f77fe6c0 Delete type=0 #978 diff --git a/packs/telecharger-compendiums/LOG.old b/packs/telecharger-compendiums/LOG.old index 7157ba0..2430f0a 100644 --- a/packs/telecharger-compendiums/LOG.old +++ b/packs/telecharger-compendiums/LOG.old @@ -1,8 +1,8 @@ -2026/03/25-23:09:24.646478 7f90f67fc6c0 Recovering log #957 -2026/03/25-23:09:24.656447 7f90f67fc6c0 Delete type=3 #955 -2026/03/25-23:09:24.656519 7f90f67fc6c0 Delete type=0 #957 -2026/03/25-23:20:49.848491 7f90f5ffb6c0 Level-0 table #963: started -2026/03/25-23:20:49.848532 7f90f5ffb6c0 Level-0 table #963: 0 bytes OK -2026/03/25-23:20:49.854765 7f90f5ffb6c0 Delete type=0 #961 -2026/03/25-23:20:49.874351 7f90f5ffb6c0 Manual compaction at level-0 from '!journal!OgzOugwIXfHtijaY' @ 72057594037927935 : 1 .. '!journal.pages!OgzOugwIXfHtijaY.OOev7kj2KoMOGoMD' @ 0 : 0; will stop at (end) -2026/03/25-23:20:49.874410 7f90f5ffb6c0 Manual compaction at level-1 from '!journal!OgzOugwIXfHtijaY' @ 72057594037927935 : 1 .. '!journal.pages!OgzOugwIXfHtijaY.OOev7kj2KoMOGoMD' @ 0 : 0; will stop at (end) +2026/03/26-22:00:22.455743 7f90f6ffd6c0 Recovering log #974 +2026/03/26-22:00:22.523057 7f90f6ffd6c0 Delete type=3 #972 +2026/03/26-22:00:22.523122 7f90f6ffd6c0 Delete type=0 #974 +2026/03/26-23:22:30.395975 7f90f5ffb6c0 Level-0 table #979: started +2026/03/26-23:22:30.395996 7f90f5ffb6c0 Level-0 table #979: 0 bytes OK +2026/03/26-23:22:30.433284 7f90f5ffb6c0 Delete type=0 #977 +2026/03/26-23:22:30.471668 7f90f5ffb6c0 Manual compaction at level-0 from '!journal!OgzOugwIXfHtijaY' @ 72057594037927935 : 1 .. '!journal.pages!OgzOugwIXfHtijaY.OOev7kj2KoMOGoMD' @ 0 : 0; will stop at (end) +2026/03/26-23:22:30.471709 7f90f5ffb6c0 Manual compaction at level-1 from '!journal!OgzOugwIXfHtijaY' @ 72057594037927935 : 1 .. '!journal.pages!OgzOugwIXfHtijaY.OOev7kj2KoMOGoMD' @ 0 : 0; will stop at (end) diff --git a/packs/telecharger-compendiums/MANIFEST-000964 b/packs/telecharger-compendiums/MANIFEST-000980 similarity index 61% rename from packs/telecharger-compendiums/MANIFEST-000964 rename to packs/telecharger-compendiums/MANIFEST-000980 index 47118693d5cbf9902dc13c3110154cdf6a87676a..7412b008798719bd649a31a9aa8e6721fb528cca 100644 GIT binary patch delta 24 gcmcb>c!6=kenG~?M$fny7@4lJb22brV`otS0A@c1wEzGB delta 24 gcmcb>c!6=ke!=tEZ&z?JFftuw=VV|$#?GPu0Cz42r~m)} diff --git a/src/config/constants.js b/src/config/constants.js index ea07c0e..f02ee03 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -12,6 +12,10 @@ export const ITEM_TYPES = { kungfu: "kungfu", spell: "spell", supernatural: "supernatural", + weapon: "weapon", + armor: "armor", + sanhei: "sanhei", + ingredient: "ingredient", } export const SUBTYPES = { diff --git a/src/data/actors/character.js b/src/data/actors/character.js index 09ff3f9..d226caa 100644 --- a/src/data/actors/character.js +++ b/src/data/actors/character.js @@ -86,7 +86,7 @@ export default class CharacterDataModel extends foundry.abstract.TypeDataModel { const schema = { concept: stringField(""), - guardian: stringField("0"), + guardian: numberField(0, { min: 0, max: 5 }), initiative: numberField(1, { min: 0 }), anti_initiative: numberField(24, { min: 0 }), description: htmlField(""), @@ -158,8 +158,8 @@ export default class CharacterDataModel extends foundry.abstract.TypeDataModel { geomancy: magicField(), }), threetreasures: new fields.SchemaField({ - heiyang: new fields.SchemaField({ value: numberField(0, { min: 0 }) }), - heiyin: new fields.SchemaField({ value: numberField(0, { min: 0 }) }), + heiyang: new fields.SchemaField({ value: numberField(0, { min: 0 }), max: numberField(0, { min: 0 }) }), + heiyin: new fields.SchemaField({ value: numberField(0, { min: 0 }), max: numberField(0, { min: 0 }) }), dicelevel: new fields.SchemaField({ level0d: treasureLevel(), level1d: treasureLevel(), diff --git a/src/data/actors/npc.js b/src/data/actors/npc.js index c7a8b0d..8953ed2 100644 --- a/src/data/actors/npc.js +++ b/src/data/actors/npc.js @@ -21,8 +21,8 @@ export default class NpcDataModel extends foundry.abstract.TypeDataModel { return { type: stringField(""), - levelofthreat: numberField(0, { min: 0 }), - powerofnuisance: numberField(0, { min: 0 }), + threat: numberField(0, { min: 0, max: 4 }), // profane(0) | apprentice(1) | initiate(2) | accomplished(3) | renowned(4) + nuisance: numberField(0, { min: 0, max: 5 }), // figurant(0) | minion(1) | adversary(2) | ally(3) | boss(4) | divinity(5) initiative: numberField(1, { min: 0 }), anti_initiative: numberField(24, { min: 0 }), aptitudes: new fields.SchemaField({ diff --git a/src/data/items/armor.js b/src/data/items/armor.js new file mode 100644 index 0000000..2e7f72d --- /dev/null +++ b/src/data/items/armor.js @@ -0,0 +1,19 @@ +export default class ArmorDataModel extends foundry.abstract.TypeDataModel { + static defineSchema() { + const { fields } = foundry.data + const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial }) + const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true }) + const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts }) + + return { + reference: stringField(""), + description: htmlField(""), + protectionValue: intField(0), + domain: stringField(""), + obtainLevel: intField(0, { min: 0, max: 5 }), + obtainDifficulty: intField(0, { min: 0, max: 3 }), + quantity: intField(1), + notes: htmlField(""), + } + } +} diff --git a/src/data/items/index.js b/src/data/items/index.js index 834b368..69363a4 100644 --- a/src/data/items/index.js +++ b/src/data/items/index.js @@ -2,3 +2,7 @@ export { default as EquipmentDataModel } from "./item.js" export { default as KungfuDataModel } from "./kungfu.js" export { default as SpellDataModel } from "./spell.js" export { default as SupernaturalDataModel } from "./supernatural.js" +export { default as WeaponDataModel } from "./weapon.js" +export { default as ArmorDataModel } from "./armor.js" +export { default as SanheiDataModel } from "./sanhei.js" +export { default as IngredientDataModel } from "./ingredient.js" diff --git a/src/data/items/ingredient.js b/src/data/items/ingredient.js new file mode 100644 index 0000000..e2d7bc8 --- /dev/null +++ b/src/data/items/ingredient.js @@ -0,0 +1,18 @@ +export default class IngredientDataModel extends foundry.abstract.TypeDataModel { + static defineSchema() { + const { fields } = foundry.data + const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial }) + const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true }) + const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts }) + + return { + reference: stringField(""), + description: htmlField(""), + school: stringField("all"), + obtainLevel: intField(0, { min: 0, max: 5 }), + obtainDifficulty: intField(0, { min: 0, max: 3 }), + quantity: intField(1), + notes: htmlField(""), + } + } +} diff --git a/src/data/items/item.js b/src/data/items/item.js index 1ea0db2..d55c94f 100644 --- a/src/data/items/item.js +++ b/src/data/items/item.js @@ -6,14 +6,10 @@ export default class EquipmentDataModel extends foundry.abstract.TypeDataModel { const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true }) return { - subtype: stringField(""), reference: stringField(""), description: htmlField(""), quantity: numberField(1, { min: 0 }), weight: numberField(0, { min: 0 }), - protection: stringField(""), - damage: stringField(""), - range: stringField(""), notes: htmlField(""), } } diff --git a/src/data/items/kungfu.js b/src/data/items/kungfu.js index 106f34e..9c82d99 100644 --- a/src/data/items/kungfu.js +++ b/src/data/items/kungfu.js @@ -9,16 +9,16 @@ export default class KungfuDataModel extends foundry.abstract.TypeDataModel { new fields.SchemaField({ check: boolField(false), name: stringField(""), - activation: stringField(""), + activation: stringField("action-attack"), // action-attack | action-defense | action-aid | action-attack-defense | reaction | dice | damage-inflicted | damage-received technique: htmlField(""), }) return { reference: stringField(""), description: htmlField(""), - orientation: stringField(""), - aspect: stringField(""), - skill: stringField(""), + orientation: stringField("yin"), // yin | yang | yinyang + aspect: stringField("metal"), // metal | eau | terre | feu | bois + skill: stringField("kungfu"), // kungfu | rangedcombat speciality: stringField(""), style: stringField(""), techniques: new fields.SchemaField({ diff --git a/src/data/items/sanhei.js b/src/data/items/sanhei.js new file mode 100644 index 0000000..81b6fe2 --- /dev/null +++ b/src/data/items/sanhei.js @@ -0,0 +1,27 @@ +export default class SanheiDataModel extends foundry.abstract.TypeDataModel { + static defineSchema() { + const { fields } = foundry.data + const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial }) + const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true }) + const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts }) + + const propertySchema = () => new fields.SchemaField({ + name: stringField(""), + heiCost: intField(0), + heiType: stringField("yin"), + description: htmlField(""), + }) + + return { + reference: stringField(""), + description: htmlField(""), + heiType: stringField("yin"), + properties: new fields.SchemaField({ + prop1: propertySchema(), + prop2: propertySchema(), + prop3: propertySchema(), + }), + notes: htmlField(""), + } + } +} diff --git a/src/data/items/spell.js b/src/data/items/spell.js index 3829a85..7ccad14 100644 --- a/src/data/items/spell.js +++ b/src/data/items/spell.js @@ -8,7 +8,7 @@ export default class SpellDataModel extends foundry.abstract.TypeDataModel { reference: stringField(""), description: htmlField(""), specialityname: stringField(""), - associatedelement: stringField(""), + associatedelement: stringField("metal"), // metal | eau | terre | feu | bois hei: stringField(""), realizationtimeritual: stringField(""), realizationtimeaccelerated: stringField(""), @@ -17,6 +17,10 @@ export default class SpellDataModel extends foundry.abstract.TypeDataModel { effects: htmlField(""), examples: htmlField(""), notes: htmlField(""), + discipline: stringField("cinabre"), + heiType: stringField("yin"), + heiCost: new fields.NumberField({ required: true, nullable: false, integer: true, min: 0, initial: 1 }), + difficulty: new fields.NumberField({ required: true, nullable: false, integer: true, min: 0, initial: 1 }), } } } diff --git a/src/data/items/supernatural.js b/src/data/items/supernatural.js index 34a4cfc..19809b3 100644 --- a/src/data/items/supernatural.js +++ b/src/data/items/supernatural.js @@ -8,6 +8,10 @@ export default class SupernaturalDataModel extends foundry.abstract.TypeDataMode reference: stringField(""), description: htmlField(""), notes: htmlField(""), + heiType: stringField("yin"), + heiCost: new fields.NumberField({ required: true, nullable: false, integer: true, min: 0, initial: 0 }), + trigger: stringField(""), + effects: htmlField(""), } } } diff --git a/src/data/items/weapon.js b/src/data/items/weapon.js new file mode 100644 index 0000000..1750467 --- /dev/null +++ b/src/data/items/weapon.js @@ -0,0 +1,22 @@ +export default class WeaponDataModel extends foundry.abstract.TypeDataModel { + static defineSchema() { + const { fields } = foundry.data + const stringField = (initial = "") => new fields.StringField({ required: true, nullable: false, initial }) + const htmlField = (initial = "") => new fields.HTMLField({ required: true, nullable: false, initial, textSearch: true }) + const intField = (initial = 0, opts = {}) => new fields.NumberField({ required: true, nullable: false, integer: true, initial, ...opts }) + + return { + reference: stringField(""), + description: htmlField(""), + weaponType: stringField("melee"), + material: stringField(""), + damageAspect: stringField("metal"), + damageBase: intField(1), + 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), + notes: htmlField(""), + } + } +} diff --git a/src/migration.js b/src/migration.js index a081f1a..8be00a5 100644 --- a/src/migration.js +++ b/src/migration.js @@ -15,7 +15,7 @@ export function registerSettings() { export async function migrateIfNeeded() { const current = game.system.version ?? MIGRATION_VERSION const stored = game.settings.get(SYSTEM_ID, "migrationVersion") ?? "0.0.0" - if (!isNewerVersion(current, stored)) return + if (!foundry.utils.isNewerVersion(current, stored)) return ui.notifications.info(`CHRONIQUESDELETRANGE | Migration vers ${current} en cours...`, { permanent: true }) await migrateActors() @@ -92,6 +92,26 @@ function migrateActorData(actor) { updateData["system.prefs.typeofthrow"] = { check: defaultCheck, choice: "0" } } + // Migrate NPC field renames: levelofthreat → threat, powerofnuisance → nuisance + if (actorType === "npc") { + if (system.levelofthreat !== undefined && system.threat === undefined) { + updateData["system.threat"] = system.levelofthreat + updateData["system.-=levelofthreat"] = null + } + if (system.powerofnuisance !== undefined && system.nuisance === undefined) { + updateData["system.nuisance"] = system.powerofnuisance + updateData["system.-=powerofnuisance"] = null + } + } + + // Migrate character guardian from string to number + if (actorType === "character" && typeof system.guardian === "string") { + const guardianNum = parseInt(system.guardian, 10) + if (!isNaN(guardianNum)) { + updateData["system.guardian"] = guardianNum + } + } + return updateData } diff --git a/src/system.js b/src/system.js index 66db97c..59e3cd0 100644 --- a/src/system.js +++ b/src/system.js @@ -2,7 +2,7 @@ import { ACTOR_TYPES, ITEM_TYPES, MAGICS, SUBTYPES, SYSTEM_ID } from "./config/c import { preLocalizeConfig } from "./config/localize.js" import { configureRuntime } from "./config/runtime.js" import { CharacterDataModel, LoksyuDataModel, NpcDataModel, TinjiDataModel } from "./data/actors/index.js" -import { EquipmentDataModel, KungfuDataModel, SpellDataModel, SupernaturalDataModel } from "./data/items/index.js" +import { EquipmentDataModel, KungfuDataModel, SpellDataModel, SupernaturalDataModel, WeaponDataModel, ArmorDataModel, SanheiDataModel, IngredientDataModel } from "./data/items/index.js" import { CDEMessage } from "./documents/chat-message.js" import { CDEActor } from "./documents/actor.js" import { CDEItem } from "./documents/item.js" @@ -10,7 +10,7 @@ import { registerDice } from "./ui/dice.js" import { registerHandlebarsHelpers } from "./ui/helpers.js" import { preloadPartials } from "./ui/templates.js" import { CDELoksyuSheet, CDECharacterSheet, CDENpcSheet, CDETinjiSheet } from "./ui/sheets/actors/index.js" -import { CDEItemSheet, CDEKungfuSheet, CDESpellSheet, CDESupernaturalSheet } from "./ui/sheets/items/index.js" +import { CDEItemSheet, CDEKungfuSheet, CDESpellSheet, CDESupernaturalSheet, CDEWeaponSheet, CDEArmorSheet, CDESanheiSheet, CDEIngredientSheet } from "./ui/sheets/items/index.js" import { migrateIfNeeded, registerSettings } from "./migration.js" Hooks.once("i18nInit", preLocalizeConfig) @@ -22,17 +22,21 @@ Hooks.once("init", async () => { game.system.CONST = { MAGICS, SUBTYPES } - CONFIG.Actor.systemDataModels = { + CONFIG.Actor.dataModels = { [ACTOR_TYPES.character]: CharacterDataModel, [ACTOR_TYPES.npc]: NpcDataModel, [ACTOR_TYPES.tinji]: TinjiDataModel, [ACTOR_TYPES.loksyu]: LoksyuDataModel, } - CONFIG.Item.systemDataModels = { + CONFIG.Item.dataModels = { [ITEM_TYPES.item]: EquipmentDataModel, [ITEM_TYPES.kungfu]: KungfuDataModel, [ITEM_TYPES.spell]: SpellDataModel, [ITEM_TYPES.supernatural]: SupernaturalDataModel, + [ITEM_TYPES.weapon]: WeaponDataModel, + [ITEM_TYPES.armor]: ArmorDataModel, + [ITEM_TYPES.sanhei]: SanheiDataModel, + [ITEM_TYPES.ingredient]: IngredientDataModel, } CONFIG.Actor.documentClass = CDEActor @@ -41,50 +45,70 @@ Hooks.once("init", async () => { configureRuntime() - DocumentSheetConfig.unregisterSheet(Actor, "core", ActorSheet) - DocumentSheetConfig.unregisterSheet(Item, "core", ItemSheet) + foundry.applications.apps.DocumentSheetConfig.unregisterSheet(Actor, "core", ActorSheet) + foundry.applications.apps.DocumentSheetConfig.unregisterSheet(Item, "core", ItemSheet) - DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDECharacterSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDECharacterSheet, { types: [ACTOR_TYPES.character], makeDefault: true, label: "CDE Character Sheet (V2)", }) - DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDENpcSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDENpcSheet, { types: [ACTOR_TYPES.npc], makeDefault: true, label: "CDE NPC Sheet (V2)", }) - DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDETinjiSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDETinjiSheet, { types: [ACTOR_TYPES.tinji], makeDefault: true, label: "CDE Tinji Sheet (V2)", }) - DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDELoksyuSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Actor, SYSTEM_ID, CDELoksyuSheet, { types: [ACTOR_TYPES.loksyu], makeDefault: true, label: "CDE Loksyu Sheet (V2)", }) - DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEItemSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEItemSheet, { types: [ITEM_TYPES.item], makeDefault: true, label: "CDE Item Sheet (V2)", }) - DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEKungfuSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEKungfuSheet, { types: [ITEM_TYPES.kungfu], makeDefault: true, label: "CDE KungFu Sheet (V2)", }) - DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESpellSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESpellSheet, { types: [ITEM_TYPES.spell], makeDefault: true, label: "CDE Spell Sheet (V2)", }) - DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESupernaturalSheet, { + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESupernaturalSheet, { types: [ITEM_TYPES.supernatural], makeDefault: true, label: "CDE Supernatural Sheet (V2)", }) + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEWeaponSheet, { + types: [ITEM_TYPES.weapon], + makeDefault: true, + label: "CDE Weapon Sheet (V2)", + }) + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEArmorSheet, { + types: [ITEM_TYPES.armor], + makeDefault: true, + label: "CDE Armor Sheet (V2)", + }) + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDESanheiSheet, { + types: [ITEM_TYPES.sanhei], + makeDefault: true, + label: "CDE Sanhei Sheet (V2)", + }) + foundry.applications.apps.DocumentSheetConfig.registerSheet(Item, SYSTEM_ID, CDEIngredientSheet, { + types: [ITEM_TYPES.ingredient], + makeDefault: true, + label: "CDE Ingredient Sheet (V2)", + }) await preloadPartials() registerHandlebarsHelpers() diff --git a/src/ui/initiative.js b/src/ui/initiative.js new file mode 100644 index 0000000..fdb2621 --- /dev/null +++ b/src/ui/initiative.js @@ -0,0 +1,173 @@ +/** + * Initiative determination system for Chroniques de l'Étrange. + * + * PJ formula: Initiative = Prouesse + Première action (compétence/ressource/magie) + * PNJ formula: Initiative = Aptitude physique + Première action (aptitude) + * + * Range 1-24 ; anti-initiative = 25 − initiative. + * Combat order is ascending (low initiative acts first). + */ + +const PC_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-prompt.html" +const NPC_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-prompt-npc.html" +const RESULT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-result.html" + +/** Skills, resources and magics available as "première action" for a PC. */ +function buildPCOptions(sys) { + const sk = sys.skills ?? {} + const rs = sys.resources ?? {} + const mg = sys.magics ?? {} + return [ + { key: "art", label: game.i18n.localize("CDE.Art"), value: sk.art?.value ?? 0 }, + { key: "investigation", label: game.i18n.localize("CDE.Investigation"), value: sk.investigation?.value ?? 0 }, + { key: "erudition", label: game.i18n.localize("CDE.Erudition"), value: sk.erudition?.value ?? 0 }, + { key: "knavery", label: game.i18n.localize("CDE.Knavery"), value: sk.knavery?.value ?? 0 }, + { key: "wordliness", label: game.i18n.localize("CDE.Wordliness"), value: sk.wordliness?.value ?? 0 }, + { key: "prowess", label: game.i18n.localize("CDE.Prowess"), value: sk.prowess?.value ?? 0 }, + { key: "sciences", label: game.i18n.localize("CDE.Sciences"), value: sk.sciences?.value ?? 0 }, + { key: "technologies", label: game.i18n.localize("CDE.Technologies"), value: sk.technologies?.value ?? 0 }, + { key: "kungfu", label: game.i18n.localize("CDE.KungFu"), value: sk.kungfu?.value ?? 0 }, + { key: "rangedcombat", label: game.i18n.localize("CDE.RangedCombat"), value: sk.rangedcombat?.value ?? 0 }, + { key: "supply", label: game.i18n.localize("CDE.Supply"), value: rs.supply?.value ?? 0 }, + { key: "inquiry", label: game.i18n.localize("CDE.Inquiry"), value: rs.inquiry?.value ?? 0 }, + { key: "influence", label: game.i18n.localize("CDE.Influence"), value: rs.influence?.value ?? 0 }, + { key: "internalcinnabar", label: game.i18n.localize("CDE.InternalCinnabar"), value: mg.internalcinnabar?.value ?? 0 }, + { key: "alchemy", label: game.i18n.localize("CDE.Alchemy"), value: mg.alchemy?.value ?? 0 }, + { key: "masteryoftheway", label: game.i18n.localize("CDE.MasteryOfTheWay"), value: mg.masteryoftheway?.value ?? 0 }, + { key: "exorcism", label: game.i18n.localize("CDE.Exorcism"), value: mg.exorcism?.value ?? 0 }, + { key: "geomancy", label: game.i18n.localize("CDE.Geomancy"), value: mg.geomancy?.value ?? 0 }, + ] +} + +/** Aptitudes available as "première action" for an NPC. */ +function buildNPCOptions(sys) { + const ap = sys.aptitudes ?? {} + return [ + { key: "physical", label: game.i18n.localize("CDE.Physical"), value: ap.physical?.value ?? 0 }, + { key: "martial", label: game.i18n.localize("CDE.Martial"), value: ap.martial?.value ?? 0 }, + { key: "mental", label: game.i18n.localize("CDE.Mental"), value: ap.mental?.value ?? 0 }, + { key: "social", label: game.i18n.localize("CDE.Social"), value: ap.social?.value ?? 0 }, + { key: "spiritual", label: game.i18n.localize("CDE.Spiritual"), value: ap.spiritual?.value ?? 0 }, + ] +} + +/** Parse the dialog element and extract firstaction + modifier. */ +function readInitFields(dialog) { + const root = dialog.element ?? dialog + const selectedKey = root.querySelector("select[name='firstaction']")?.value ?? "" + const modifier = parseInt(root.querySelector("input[name='modifier']")?.value ?? 0) || 0 + return { selectedKey, modifier } +} + +/** Post a styled initiative chat message. */ +async function sendInitChatMessage({ actor, baseName, baseValue, actionName, actionValue, modifier, initiative, antiInitiative }) { + const html = await foundry.applications.handlebars.renderTemplate(RESULT_TEMPLATE, { + actorName: actor.name, + actorImg: actor.img, + baseName, + baseValue, + actionName, + actionValue, + modifier, + hasModifier: modifier !== 0, + initiative, + antiInitiative, + }) + await ChatMessage.create({ + user: game.user.id, + speaker: ChatMessage.getSpeaker({ actor }), + content: html, + }) +} + +/** + * Open the PC initiative dialog, compute initiative (Prouesse + Première action + modificateur) + * and update the actor, then post a chat card. + */ +export async function rollInitiativePC(actor) { + const sys = actor.system + const prowess = sys.skills?.prowess?.value ?? 0 + const options = buildPCOptions(sys) + const baseName = game.i18n.localize("CDE.Prowess") + + const content = await foundry.applications.handlebars.renderTemplate(PC_PROMPT_TEMPLATE, { + prowessValue: prowess, + options, + modifier: 0, + }) + + const result = await foundry.applications.api.DialogV2.prompt({ + window: { title: game.i18n.localize("CDE.InitiativeRoll") }, + content, + rejectClose: false, + ok: { + label: game.i18n.localize("CDE.Validate"), + callback: (_ev, _btn, dialog) => readInitFields(dialog), + }, + }) + if (!result) return + + const { selectedKey, modifier } = result + const selected = options.find((o) => o.key === selectedKey) ?? options[0] + const rawValue = prowess + selected.value + modifier + const initiative = Math.max(1, Math.min(24, rawValue)) + const antiInit = 25 - initiative + + await actor.update({ "system.initiative": initiative }) + await sendInitChatMessage({ + actor, + baseName, + baseValue: prowess, + actionName: selected.label, + actionValue: selected.value, + modifier, + initiative, + antiInitiative: antiInit, + }) +} + +/** + * Open the NPC initiative dialog, compute initiative (Aptitude physique + Première action + modificateur) + * and update the actor, then post a chat card. + */ +export async function rollInitiativeNPC(actor) { + const sys = actor.system + const physical = sys.aptitudes?.physical?.value ?? 0 + const options = buildNPCOptions(sys) + const baseName = game.i18n.localize("CDE.Physical") + + const content = await foundry.applications.handlebars.renderTemplate(NPC_PROMPT_TEMPLATE, { + physicalValue: physical, + options, + modifier: 0, + }) + + const result = await foundry.applications.api.DialogV2.prompt({ + window: { title: game.i18n.localize("CDE.InitiativeRoll") }, + content, + rejectClose: false, + ok: { + label: game.i18n.localize("CDE.Validate"), + callback: (_ev, _btn, dialog) => readInitFields(dialog), + }, + }) + if (!result) return + + const { selectedKey, modifier } = result + const selected = options.find((o) => o.key === selectedKey) ?? options[0] + const rawValue = physical + selected.value + modifier + const initiative = Math.max(1, Math.min(24, rawValue)) + const antiInit = 25 - initiative + + await actor.update({ "system.initiative": initiative }) + await sendInitChatMessage({ + actor, + baseName, + baseValue: physical, + actionName: selected.label, + actionValue: selected.value, + modifier, + initiative, + antiInitiative: antiInit, + }) +} diff --git a/src/ui/rolling.js b/src/ui/rolling.js new file mode 100644 index 0000000..71ed562 --- /dev/null +++ b/src/ui/rolling.js @@ -0,0 +1,621 @@ +/** + * Wu Xing rolling system for Chroniques de l'Étrange. + * + * The Wu Xing cycle maps each aspect (by index 0-4) to die face groups: + * - metal=0 : faces 3,8 + * - water=1 : faces 1,6 + * - earth=2 : faces 0/10,5 + * - fire=3 : faces 2,7 + * - wood=4 : faces 4,9 + * + * For a given active aspect the five result categories are: + * successes / auspicious / noxious / loksyu (yin face, yang face) / tinji + * Each category is associated with one of the five aspects in Wu Xing cycle order. + */ + +const RESULT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-dice-result.html" +const SKILL_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-skill-dice-prompt.html" +const SKILL_SPECIAL_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-skill-special-dice-prompt.html" +const MAGIC_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-magic-dice-prompt.html" +const WEAPON_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-weapon-dice-prompt.html" + +/** Maps i18n element label → aspect name (for speciality default aspect lookup) */ +const LABELELEMENT_TO_ASPECT = { + "CDE.Metal": "metal", + "CDE.Water": "water", + "CDE.Earth": "earth", + "CDE.Fire": "fire", + "CDE.Wood": "wood", +} + +/** Map aspect index → string name used in result template */ +const ASPECT_NAMES = ["metal", "water", "earth", "fire", "wood"] + +/** Map aspect name → i18n label key */ +const ASPECT_LABELS = { + metal: "CDE.Metal", + water: "CDE.Water", + earth: "CDE.Earth", + fire: "CDE.Fire", + wood: "CDE.Wood", +} + +/** Map aspect name → image path */ +const ASPECT_ICONS = { + metal: "systems/fvtt-chroniques-de-l-etrange/images/cde_metal.png", + water: "systems/fvtt-chroniques-de-l-etrange/images/cde_eau.png", + earth: "systems/fvtt-chroniques-de-l-etrange/images/cde_terre.png", + fire: "systems/fvtt-chroniques-de-l-etrange/images/cde_feu.png", + wood: "systems/fvtt-chroniques-de-l-etrange/images/cde_bois.png", +} + +/** Map aspect index → die face pair [yin, yang] (face=10 stored as 0) */ +const ASPECT_FACES = { + metal: [3, 8], + water: [1, 6], + earth: [0, 5], // 0 = face "10" + fire: [2, 7], + wood: [4, 9], +} + +/** + * Wu Xing generating/overcoming cycle: + * wood → fire → earth → metal → water → wood (generating) + * For each active aspect, the five categories in order: + * [successes, auspicious, noxious, loksyu, tinji] + */ +const WU_XING_CYCLE = { + wood: ["wood", "fire", "water", "earth", "metal"], + fire: ["fire", "earth", "wood", "metal", "water"], + earth: ["earth", "metal", "fire", "water", "wood"], + metal: ["metal", "water", "earth", "wood", "fire"], + water: ["water", "wood", "metal", "fire", "earth"], +} + +/** Maps weapon range string → dice malus applied to the attack pool */ +const RANGE_MALUS = { + contact: 0, + courte: 0, + mediane: -1, + longue: -2, + extreme: -3, +} + +/** Maps weapon type string → default skill key */ +const WEAPON_TYPE_SKILL = { + melee: "kungfu", + thrown: "rangedcombat", + ranged: "rangedcombat", + firearm: "rangedcombat", +} + +/** Maps weapon damageAspect name → ASPECT_NAMES index */ +const WEAPON_ASPECT_INDEX = { metal: 0, eau: 1, water: 1, terre: 2, earth: 2, feu: 3, fire: 3, bois: 4, wood: 4 } + +/** Count how many times each die face appeared in the roll results */ +function countFaces(rollResults) { + const counts = { 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 0:0 } + for (const die of rollResults) { + const face = die.result === 10 ? 0 : die.result + counts[face]++ + } + return counts +} + +/** + * Compute Wu Xing result categories from face counts and active aspect. + * Returns { successesdice, auspiciousdice, noxiousdice, loksyudice, tinjidice, loksyurepartition } + */ +function computeWuXingResults(faces, aspectName, bonusAuspicious = 0) { + const cycle = WU_XING_CYCLE[aspectName] + if (!cycle) return null + + const [succAspect, ausAspect, noxAspect, lokAspect, tinAspect] = cycle + const [succYin, succYang] = ASPECT_FACES[succAspect] + const [ausYin, ausYang] = ASPECT_FACES[ausAspect] + const [noxYin, noxYang] = ASPECT_FACES[noxAspect] + const [lokYin, lokYang] = ASPECT_FACES[lokAspect] + const [tinYin, tinYang] = ASPECT_FACES[tinAspect] + + const yin = game.i18n.localize("CDE.Yin") + const yang = game.i18n.localize("CDE.Yang") + + return { + successesdice: faces[succYin] + faces[succYang], + auspiciousdice: faces[ausYin] + faces[ausYang] + bonusAuspicious, + noxiousdice: faces[noxYin] + faces[noxYang], + loksyudice: faces[lokYin] + faces[lokYang], + loksyurepartition: `[${yin}(${faces[lokYin]}) ${yang}(${faces[lokYang]})]`, + tinjidice: faces[tinYin] + faces[tinYang], + } +} + +/** Read a named field from a dialog DOM element */ +function readField(dlg, name) { + const el = dlg.querySelector(`[name="${name}"]`) + if (!el) return null + return el.type === "checkbox" ? el.checked : el.value +} + +/** + * Open a DialogV2.prompt with the given template + data and return the resolved form values. + * The callback receives the DialogV2 application instance; fields are read from its .element. + * @returns {Promise|null>} + */ +async function showRollPrompt({ title, template, data, fields }) { + const content = await foundry.applications.handlebars.renderTemplate(template, data) + return foundry.applications.api.DialogV2.prompt({ + window: { title }, + content, + rejectClose: false, + ok: { + label: game.i18n.localize("CDE.Validate"), + callback: (event, button, dialog) => { + // In AppV2, dialog is the application instance; .element is the root HTMLElement + const root = dialog.element ?? dialog + const result = {} + for (const field of fields) { + result[field] = readField(root, field) + } + return result + }, + }, + }) +} + +/** + * Open the skill roll prompt and return the user-confirmed parameters. + * @param {object} params - Initial values + * @returns {Promise} + */ +export async function showSkillPrompt(params) { + return showRollPrompt({ + title: params.title, + template: params.isSpecial ? SKILL_SPECIAL_PROMPT_TEMPLATE : SKILL_PROMPT_TEMPLATE, + data: { + numberofdice: params.numberofdice, + aspect: Number(params.aspect ?? 0), + bonusmalus: params.bonusmalus ?? 0, + woundmalus: params.woundmalus ?? 0, + bonusauspiciousdice: params.bonusauspiciousdice ?? 0, + typeofthrow: Number(params.typeofthrow ?? 0), + }, + fields: ["aspect", "bonusmalus", "woundmalus", "bonusauspiciousdice", "typeofthrow"], + }) +} + +/** + * Open the magic roll prompt and return the user-confirmed parameters. + */ +export async function showMagicPrompt(params) { + return showRollPrompt({ + title: params.title, + template: MAGIC_PROMPT_TEMPLATE, + data: { + 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), + }, + fields: ["aspectskill", "bonusmalusskill", "bonusauspiciousdice", + "aspectspeciality", "rolldifficulty", "bonusmalusspeciality", + "heispend", "typeofthrow"], + }) +} + +/** + * Open the weapon attack roll prompt and return user-confirmed parameters. + */ +export async function showWeaponPrompt(params) { + return showRollPrompt({ + title: params.title, + template: WEAPON_PROMPT_TEMPLATE, + data: { + numberofdice: params.numberofdice ?? 0, + weaponName: params.weaponName ?? "", + weaponTypeLabel: params.weaponTypeLabel ?? "CDE.Weapon", + weaponAspectIcon: params.weaponAspectIcon ?? "", + weaponAspectLabel: params.weaponAspectLabel ?? "", + damageBase: params.damageBase ?? 1, + weaponskill: params.weaponskill ?? "kungfu", + aspect: Number(params.aspect ?? 0), + effectiverange: params.effectiverange ?? "contact", + bonusmalus: params.bonusmalus ?? 0, + woundmalus: params.woundmalus ?? 0, + bonusauspiciousdice: params.bonusauspiciousdice ?? 0, + typeofthrow: Number(params.typeofthrow ?? 0), + }, + fields: ["weaponskill", "aspect", "effectiverange", "bonusmalus", "woundmalus", + "bonusauspiciousdice", "typeofthrow"], + }) +} + +/** + * Build and send a single enriched ChatMessage containing both the roll + * (for Dice So Nice) and the Wu Xing result card. + */ +async function sendResultMessage(actor, resultData, roll, rollMode) { + const html = await foundry.applications.handlebars.renderTemplate(RESULT_TEMPLATE, resultData) + return ChatMessage.create({ + user: game.user.id, + speaker: ChatMessage.getSpeaker({ actor }), + content: html, + rolls: [roll], + rollMode, + }) +} + +const ROLL_MODES = ["roll", "gmroll", "blindroll", "selfroll"] + +/** + * Main entry point: roll dice for a given actor. + * + * @param {Actor} actor + * @param {string} rollKey - e.g. "prowess-skill", "fire-aspect", "alchemy-magic-elixirs" + */ +export async function rollForActor(actor, rollKey) { + const parts = rollKey.split("-") + const skillLibel = parts[0] + const typeLibel = parts[1] + const specialLibel = parts[2] ?? null + + const sys = actor.system + const typeOfThrow = Number(sys.prefs?.typeofthrow?.choice ?? 0) + + let numberofdice = 0 + let title = "" + let isSpecial = false + let isMagic = false + let isMagicSpecial = false + let kfDefaultAspect = -1 // set in "itemkungfu" case, used when computing defaultAspect + + // ---- Determine dice count + title ---- + const MAGIC_I18N_KEYS = { + internalcinnabar: "CDE.InternalCinnabar", + alchemy: "CDE.Alchemy", + masteryoftheway: "CDE.MasteryOfTheWay", + exorcism: "CDE.Exorcism", + geomancy: "CDE.Geomancy", + } + + switch (typeLibel) { + case "aspect": + numberofdice = sys.aspect[skillLibel]?.value ?? 0 + title = game.i18n.localize(sys.aspect[skillLibel]?.label ?? "CDE.Roll") + break + case "skill": + numberofdice = sys.skills[skillLibel]?.value ?? 0 + title = game.i18n.localize(sys.skills[skillLibel]?.label ?? "CDE.Roll") + break + case "special": + numberofdice = sys.skills[skillLibel]?.value ?? 0 + title = game.i18n.localize(sys.skills[skillLibel]?.label ?? "CDE.Roll") + title += ` [${game.i18n.localize("CDE.Speciality")}]` + isSpecial = true + if (!sys.skills[skillLibel]?.specialities) { + ui.notifications.warn(game.i18n.localize("CDE.Error2")) + return + } + break + case "resource": + numberofdice = sys.resources[skillLibel]?.value ?? 0 + title = game.i18n.localize(sys.resources[skillLibel]?.label ?? "CDE.Roll") + break + case "field": + numberofdice = sys.resources[skillLibel]?.value ?? 0 + title = game.i18n.localize(sys.resources[skillLibel]?.label ?? "CDE.Roll") + title += ` [${game.i18n.localize("CDE.Field")}]` + isSpecial = true + if (!sys.resources[skillLibel]?.specialities) { + ui.notifications.warn(game.i18n.localize("CDE.Error4")) + return + } + break + case "magic": + numberofdice = sys.magics[skillLibel]?.value ?? 0 + isMagic = true + title = game.i18n.localize(MAGIC_I18N_KEYS[skillLibel] ?? "CDE.Magics") + break + case "magicspecial": + numberofdice = sys.magics[skillLibel]?.value ?? 0 + isMagicSpecial = true + isMagic = true + if (!sys.magics[skillLibel]?.speciality?.[specialLibel]?.check) { + ui.notifications.warn(game.i18n.localize("CDE.Error6")) + return + } + title = `${game.i18n.localize(MAGIC_I18N_KEYS[skillLibel] ?? "CDE.Magics")} [${game.i18n.localize(game.system.CONST?.MAGICS?.[skillLibel]?.speciality?.[specialLibel]?.label ?? "")}]` + break + case "itemkungfu": { + // skillLibel = item._id — look up the kungfu item to find which skill + aspect to use + const kfItem = actor.items.get(skillLibel) + if (!kfItem) { ui.notifications.warn(game.i18n.localize("CDE.Error0")); return } + 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") + if (kfDefaultAspect < 0) kfDefaultAspect = 0 + break + } + case "itemweapon": { + // skillLibel = item._id — look up the weapon item to find type + aspect + damage + const wpItem = actor.items.get(skillLibel) + if (!wpItem) { ui.notifications.warn(game.i18n.localize("CDE.Error0")); return } + + const wpType = wpItem.system.weaponType ?? "melee" + const wpSkill = WEAPON_TYPE_SKILL[wpType] ?? "kungfu" + numberofdice = sys.skills[wpSkill]?.value ?? 0 + + const wpAspectRaw = wpItem.system.damageAspect ?? "metal" + const wpAspectIdx = WEAPON_ASPECT_INDEX[wpAspectRaw] ?? 0 + const wpRange = wpItem.system.range ?? "contact" + + const WEAPON_TYPE_LABELS = { + melee: "CDE.WeaponMelee", + thrown: "CDE.WeaponThrown", + ranged: "CDE.WeaponRanged", + firearm: "CDE.WeaponFirearm", + } + + // Show weapon-specific prompt + const wParams = await showWeaponPrompt({ + title: `${wpItem.name} [${game.i18n.localize(sys.skills[wpSkill]?.label ?? "CDE.WeaponRoll")}]`, + numberofdice, + weaponName: wpItem.name, + weaponTypeLabel: WEAPON_TYPE_LABELS[wpType] ?? "CDE.Weapon", + weaponAspectIcon: ASPECT_ICONS[ASPECT_NAMES[wpAspectIdx]] ?? "", + weaponAspectLabel: game.i18n.localize(ASPECT_LABELS[ASPECT_NAMES[wpAspectIdx]] ?? ""), + damageBase: wpItem.system.damageBase ?? 1, + weaponskill: wpSkill, + aspect: wpAspectIdx, + effectiverange: wpRange, + bonusmalus: 0, + woundmalus: 0, + bonusauspiciousdice: 0, + typeofthrow: typeOfThrow, + }) + + if (!wParams) return // cancelled + + // Resolve final pool from weapon prompt values + const wpChosenSkill = wParams.weaponskill ?? wpSkill + const wpSkillDice = sys.skills[wpChosenSkill]?.value ?? 0 + const wpAspFinal = Number(wParams.aspect ?? wpAspectIdx) + const wpAspectDice = sys.aspect[ASPECT_NAMES[wpAspFinal]]?.value ?? 0 + const wpRangeMalus = RANGE_MALUS[wParams.effectiverange ?? "contact"] ?? 0 + const wpBonusMalus = Number(wParams.bonusmalus ?? 0) + const wpWoundMalus = Number(wParams.woundmalus ?? 0) + const wpBonusAusp = Number(wParams.bonusauspiciousdice ?? 0) + const wpThrowMode = Number(wParams.typeofthrow ?? 0) + const wpDamageBase = wpItem.system.damageBase ?? 1 + + const wpTotalDice = wpSkillDice + wpAspectDice + wpRangeMalus + wpBonusMalus - wpWoundMalus + if (wpTotalDice <= 0) { + ui.notifications.warn(game.i18n.localize("CDE.Error0")) + return + } + + const wpRoll = new Roll(`${wpTotalDice}d10`) + await wpRoll.evaluate() + + const wpAspectName = ASPECT_NAMES[wpAspFinal] ?? "metal" + const wpFaces = countFaces(wpRoll.dice[0]?.results ?? []) + const wpResults = computeWuXingResults(wpFaces, wpAspectName, wpBonusAusp) + if (!wpResults) return + + const wpModParts = [] + if (wpRangeMalus !== 0) wpModParts.push(`${wpRangeMalus} ${game.i18n.localize("CDE.RangePenalty")}`) + if (wpBonusMalus !== 0) wpModParts.push(`${wpBonusMalus > 0 ? "+" : ""}${wpBonusMalus} ${game.i18n.localize("CDE.BonusMalus")}`) + if (wpWoundMalus !== 0) wpModParts.push(`-${wpWoundMalus} ${game.i18n.localize("CDE.WoundMalus")}`) + if (wpBonusAusp !== 0) wpModParts.push(`+${wpBonusAusp} ${game.i18n.localize("CDE.BonusAuspiciousDice")}`) + + const wpMsg = await sendResultMessage(actor, { + rollLabel: `${wpItem.name}`, + aspectName: wpAspectName, + aspectLabel: game.i18n.localize(ASPECT_LABELS[wpAspectName] ?? ""), + aspectIcon: ASPECT_ICONS[wpAspectName] ?? "", + totalDice: wpTotalDice, + modifiersText: wpModParts.length ? wpModParts.join(" · ") : "", + spellPower: null, + rollDifficulty: null, + actorName: actor.name ?? "", + actorImg: actor.img ?? "", + // weapon-specific + weaponName: wpItem.name, + damageBase: wpDamageBase, + totalDamage: wpResults.successesdice * wpDamageBase, + ...wpResults, + aspect: wpAspectName, + d1: wpFaces[1], d2: wpFaces[2], d3: wpFaces[3], d4: wpFaces[4], d5: wpFaces[5], + d6: wpFaces[6], d7: wpFaces[7], d8: wpFaces[8], d9: wpFaces[9], d0: wpFaces[0], + }, wpRoll, ROLL_MODES[wpThrowMode] ?? "roll") + + if (game.modules.get("dice-so-nice")?.active && wpMsg?.id) { + await game.dice3d.waitFor3DAnimationByMessageID(wpMsg.id) + } + return + } + default: + ui.notifications.warn(`Unknown roll type: ${typeLibel}`) + 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). + if (numberofdice <= 0 && typeLibel !== "aspect" && typeLibel !== "itemkungfu" && !isMagic) { + ui.notifications.warn(game.i18n.localize("CDE.Error0")) + return + } + + // ---- Pre-compute default aspect for magic based on skill ---- + const MAGIC_ASPECTS = { + internalcinnabar: 0, // metal + alchemy: 1, // water + masteryoftheway: 2, // earth + exorcism: 3, // fire + geomancy: 4, // wood + } + + let defaultAspect = typeLibel === "aspect" + ? ["metal","water","earth","fire","wood"].indexOf(skillLibel) + : 0 + if (isMagic && MAGIC_ASPECTS[skillLibel] !== undefined) { + defaultAspect = MAGIC_ASPECTS[skillLibel] + } + if (kfDefaultAspect >= 0) { + defaultAspect = kfDefaultAspect + } + + let defaultSpecialAspect = 0 + if (isMagicSpecial && specialLibel) { + // Look up the speciality's element from the MAGICS config constant + const specialCfg = game.system.CONST?.MAGICS?.[skillLibel]?.speciality?.[specialLibel] + const aspectName = LABELELEMENT_TO_ASPECT[specialCfg?.labelelement] + if (aspectName) { + defaultSpecialAspect = ASPECT_NAMES.indexOf(aspectName) + } + } + + // ---- Show roll prompt ---- + let params + + if (isMagic) { + params = await showMagicPrompt({ + title, + numberofdice, + aspectskill: defaultAspect, + bonusmalusskill: 0, + bonusauspiciousdice: 0, + aspectspeciality: defaultSpecialAspect, + rolldifficulty: 1, + bonusmalusspeciality: 0, + heispend: 0, + typeofthrow: typeOfThrow, + }) + } else { + params = await showSkillPrompt({ + title, + numberofdice, + aspect: defaultAspect, + bonusmalus: 0, + woundmalus: 0, + bonusauspiciousdice: 0, + typeofthrow: typeOfThrow, + isSpecial, + }) + } + + if (!params) return // cancelled + + // ---- 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 + + if (isMagic) { + const skillAspectIndex = Number(params.aspectskill ?? 0) + spellAspectIndex = Number(params.aspectspeciality ?? skillAspectIndex) + aspectIndex = skillAspectIndex // used only for skill dice pool + 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 + } else { + aspectIndex = Number(params.aspect ?? 0) + bonusMalus = Number(params.bonusmalus ?? 0) + const woundMalus = Number(params.woundmalus ?? 0) + bonusAuspicious = Number(params.bonusauspiciousdice ?? 0) + throwMode = Number(params.typeofthrow ?? 0) + + const aspectDice = (typeLibel !== "aspect") + ? (sys.aspect[ASPECT_NAMES[aspectIndex]]?.value ?? 0) + : 0 + + numberofdice = numberofdice + aspectDice + bonusMalus - woundMalus + if (isSpecial) numberofdice += 1 // +1d for speciality + } + + if (numberofdice <= 0) { + ui.notifications.warn(game.i18n.localize("CDE.Error0")) + return + } + + // ---- Roll ---- + const roll = new Roll(`${numberofdice}d10`) + await roll.evaluate() + + const rollModeKey = ROLL_MODES[throwMode] ?? "roll" + + // ---- 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] + 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) + 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 (rollDifficulty !== 1) modParts.push(`×${rollDifficulty} ${game.i18n.localize("CDE.RollDifficulty")}`) + } else { + const bm = Number(params.bonusmalus ?? 0) + const wm = Number(params.woundmalus ?? 0) + const ba = Number(params.bonusauspiciousdice ?? 0) + if (bm !== 0) modParts.push(`${bm > 0 ? "+" : ""}${bm} ${game.i18n.localize("CDE.BonusMalus")}`) + if (wm !== 0) modParts.push(`-${wm} ${game.i18n.localize("CDE.WoundMalus")}`) + if (ba !== 0) modParts.push(`+${ba} ${game.i18n.localize("CDE.BonusAuspiciousDice")}`) + } + + // ---- Send single enriched ChatMessage (roll + result card) ---- + const msg = await sendResultMessage(actor, { + // Roll identity + rollLabel: title, + aspectName: wuXingAspectName, + aspectLabel: game.i18n.localize(ASPECT_LABELS[wuXingAspectName] ?? ""), + aspectIcon: ASPECT_ICONS[wuXingAspectName] ?? "", + totalDice: numberofdice, + modifiersText: modParts.length ? modParts.join(" · ") : "", + // Spell power (magic only) + spellPower, + rollDifficulty: isMagic ? rollDifficulty : null, + // Actor info + actorName: actor.name ?? "", + actorImg: actor.img ?? "", + // Wu Xing results + aspect: wuXingAspectName, + ...results, + // Die face counts + d1: faces[1], d2: faces[2], d3: faces[3], d4: faces[4], d5: faces[5], + d6: faces[6], d7: faces[7], d8: faces[8], d9: faces[9], d0: faces[0], + }, roll, rollModeKey) + + // ---- Wait for Dice So Nice animation ---- + if (game.modules.get("dice-so-nice")?.active && msg?.id) { + await game.dice3d.waitFor3DAnimationByMessageID(msg.id) + } +} diff --git a/src/ui/sheets/actors/base.js b/src/ui/sheets/actors/base.js index 4023e2c..4798f01 100644 --- a/src/ui/sheets/actors/base.js +++ b/src/ui/sheets/actors/base.js @@ -3,7 +3,7 @@ const { HandlebarsApplicationMixin } = foundry.applications.api export class CDEBaseActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) { static DEFAULT_OPTIONS = { classes: ["fvtt-chroniques-de-l-etrange", "actor"], - position: { width: 920, height: "auto" }, + position: { width: 920, height: 800 }, window: { resizable: true }, form: { submitOnChange: true }, dragDrop: [{ dragSelector: ".item, [data-drag='true']", dropSelector: null }], @@ -16,6 +16,10 @@ export class CDEBaseActorSheet extends HandlebarsApplicationMixin(foundry.applic tabGroups = { primary: "description" } + get title() { + return this.document.name + } + async _prepareContext() { const descriptionHTML = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description ?? "", { async: true }) const cssClass = this.options.classes?.join(" ") ?? "" @@ -23,6 +27,7 @@ export class CDEBaseActorSheet extends HandlebarsApplicationMixin(foundry.applic actor: this.document, system: this.document.system, systemData: this.document.system, + systemFields: this.document.system.schema.fields, items: this.document.items.contents, descriptionHTML, editable: this.isEditable, @@ -30,14 +35,11 @@ export class CDEBaseActorSheet extends HandlebarsApplicationMixin(foundry.applic } } - async _onFirstRender(context, options) { - await super._onFirstRender(context, options) - for (const [group, tab] of Object.entries(this.tabGroups)) { - this.changeTab(tab, group, { force: true }) - } - } - + // Restore the active tab after every render (including re-renders from submitOnChange). + // AppV2 does NOT preserve tab state natively — we must re-apply it from this.tabGroups, + // which is dynamically updated by changeTab() when the user clicks a tab. _onRender(context, options) { + super._onRender?.(context, options) for (const [group, tab] of Object.entries(this.tabGroups)) { this.changeTab(tab, group, { force: true }) } @@ -48,6 +50,10 @@ export class CDEBaseActorSheet extends HandlebarsApplicationMixin(foundry.applic const cls = getDocumentClass("Item") const labels = { item: "CDE.ItemNew", + weapon: "CDE.WeaponNew", + armor: "CDE.ArmorNew", + sanhei: "CDE.SanheiNew", + ingredient: "CDE.IngredientNew", kungfu: "CDE.KFNew", spell: "CDE.SpellNew", supernatural: "CDE.SupernaturalNew", diff --git a/src/ui/sheets/actors/character.js b/src/ui/sheets/actors/character.js index 9c772f8..1f49520 100644 --- a/src/ui/sheets/actors/character.js +++ b/src/ui/sheets/actors/character.js @@ -1,4 +1,6 @@ import { MAGICS, SUBTYPES } from "../../../config/constants.js" +import { rollInitiativePC } from "../../initiative.js" +import { rollForActor } from "../../rolling.js" import { CDEBaseActorSheet } from "./base.js" export class CDECharacterSheet extends CDEBaseActorSheet { @@ -15,6 +17,10 @@ export class CDECharacterSheet extends CDEBaseActorSheet { async _prepareContext() { const context = await super._prepareContext() context.equipments = context.items.filter((item) => item.type === "item") + context.weapons = context.items.filter((item) => item.type === "weapon") + context.armors = context.items.filter((item) => item.type === "armor") + context.sanheis = context.items.filter((item) => item.type === "sanhei") + context.ingredients = context.items.filter((item) => item.type === "ingredient") context.spells = context.items.filter((item) => item.type === "spell") context.kungfus = context.items.filter((item) => item.type === "kungfu") context.CDE = { MAGICS, SUBTYPES } @@ -25,6 +31,7 @@ export class CDECharacterSheet extends CDEBaseActorSheet { super._onRender?.(context, options) this.#bindInitiativeControls() this.#bindPrefs() + this.#bindRollButtons() } #bindInitiativeControls() { @@ -45,26 +52,7 @@ export class CDECharacterSheet extends CDEBaseActorSheet { return } if (action === "create") { - const html = ` -
-
- - -
-
` - const value = await Dialog.prompt({ - title: game.i18n.localize("CDE.TurnOrder"), - content: html, - label: game.i18n.localize("CDE.Validate"), - callback: (dlg) => { - const input = dlg.querySelector("input[name='initiative']") - return Number(input?.value ?? initiative) - }, - }) - if (Number.isFinite(value)) { - const sanitized = foundry.utils.clamp(Number(value), 1, 24) - await this.document.update({ "system.initiative": sanitized }) - } + await rollInitiativePC(this.document) } }) }) @@ -109,4 +97,16 @@ export class CDECharacterSheet extends CDEBaseActorSheet { } }) } + + #bindRollButtons() { + const cells = this.element?.querySelectorAll("td.click[data-libel-id], td.click2[data-libel-id], .cde-roll-trigger[data-libel-id]") + if (!cells?.length) return + cells.forEach((cell) => { + cell.addEventListener("click", (event) => { + event.preventDefault() + const rollKey = cell.dataset.libelId + if (rollKey) rollForActor(this.document, rollKey) + }) + }) + } } diff --git a/src/ui/sheets/actors/npc.js b/src/ui/sheets/actors/npc.js index 54201bc..48c8d68 100644 --- a/src/ui/sheets/actors/npc.js +++ b/src/ui/sheets/actors/npc.js @@ -1,3 +1,4 @@ +import { rollInitiativeNPC } from "../../initiative.js" import { CDEBaseActorSheet } from "./base.js" export class CDENpcSheet extends CDEBaseActorSheet { @@ -43,23 +44,7 @@ export class CDENpcSheet extends CDEBaseActorSheet { return } if (action === "create") { - const html = ` -
-
- - -
-
` - const value = await Dialog.prompt({ - title: game.i18n.localize("CDE.TurnOrder"), - content: html, - label: game.i18n.localize("CDE.Validate"), - callback: (dlg) => Number(dlg.querySelector("input[name='initiative']")?.value ?? initiative), - }) - if (Number.isFinite(value)) { - const sanitized = foundry.utils.clamp(Number(value), 1, 24) - await this.document.update({ "system.initiative": sanitized }) - } + await rollInitiativeNPC(this.document) } }) }) diff --git a/src/ui/sheets/items/armor.js b/src/ui/sheets/items/armor.js new file mode 100644 index 0000000..d10f69e --- /dev/null +++ b/src/ui/sheets/items/armor.js @@ -0,0 +1,12 @@ +import { CDEBaseItemSheet } from "./base.js" + +export class CDEArmorSheet extends CDEBaseItemSheet { + static DEFAULT_OPTIONS = { + classes: ["armor"], + position: { width: 520, height: 460 }, + } + + static PARTS = { + main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/item/cde-armor-sheet.html" }, + } +} diff --git a/src/ui/sheets/items/base.js b/src/ui/sheets/items/base.js index ca64a8f..9f553a8 100644 --- a/src/ui/sheets/items/base.js +++ b/src/ui/sheets/items/base.js @@ -9,7 +9,11 @@ export class CDEBaseItemSheet extends HandlebarsApplicationMixin(foundry.applica actions: {}, } - tabGroups = { primary: "description" } + tabGroups = { primary: "details" } + + get title() { + return this.document.name + } async _prepareContext() { const cssClass = this.options.classes?.join(" ") ?? "" @@ -19,6 +23,7 @@ export class CDEBaseItemSheet extends HandlebarsApplicationMixin(foundry.applica item: this.document, system: this.document.system, systemData: this.document.system, + systemFields: this.document.system.schema.fields, editable: this.isEditable, cssClass, enrichedDescription, @@ -28,14 +33,9 @@ export class CDEBaseItemSheet extends HandlebarsApplicationMixin(foundry.applica } } - async _onFirstRender(context, options) { - await super._onFirstRender(context, options) - for (const [group, tab] of Object.entries(this.tabGroups)) { - this.changeTab(tab, group, { force: true }) - } - } - + // Restore the active tab after every render (including re-renders from submitOnChange). _onRender(context, options) { + super._onRender?.(context, options) for (const [group, tab] of Object.entries(this.tabGroups)) { this.changeTab(tab, group, { force: true }) } diff --git a/src/ui/sheets/items/index.js b/src/ui/sheets/items/index.js index 200a90e..d9749cf 100644 --- a/src/ui/sheets/items/index.js +++ b/src/ui/sheets/items/index.js @@ -3,3 +3,7 @@ export { CDEItemSheet } from "./item.js" export { CDEKungfuSheet } from "./kungfu.js" export { CDESpellSheet } from "./spell.js" export { CDESupernaturalSheet } from "./supernatural.js" +export { CDEWeaponSheet } from "./weapon.js" +export { CDEArmorSheet } from "./armor.js" +export { CDESanheiSheet } from "./sanhei.js" +export { CDEIngredientSheet } from "./ingredient.js" diff --git a/src/ui/sheets/items/ingredient.js b/src/ui/sheets/items/ingredient.js new file mode 100644 index 0000000..46eb91c --- /dev/null +++ b/src/ui/sheets/items/ingredient.js @@ -0,0 +1,12 @@ +import { CDEBaseItemSheet } from "./base.js" + +export class CDEIngredientSheet extends CDEBaseItemSheet { + static DEFAULT_OPTIONS = { + classes: ["ingredient"], + position: { width: 520, height: 460 }, + } + + static PARTS = { + main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/item/cde-ingredient-sheet.html" }, + } +} diff --git a/src/ui/sheets/items/item.js b/src/ui/sheets/items/item.js index ac22371..e5cbb86 100644 --- a/src/ui/sheets/items/item.js +++ b/src/ui/sheets/items/item.js @@ -1,23 +1,12 @@ -import { SUBTYPES } from "../../../config/constants.js" import { CDEBaseItemSheet } from "./base.js" export class CDEItemSheet extends CDEBaseItemSheet { static DEFAULT_OPTIONS = { classes: ["equipment"], - position: { width: 620, height: 580 }, + position: { width: 560, height: 460 }, } static PARTS = { main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/item/cde-item-sheet.html" }, } - - async _prepareContext() { - const context = await super._prepareContext() - context.subtypes = SUBTYPES - context.isWeapon = this.document.isWeapon - context.isArmor = this.document.isArmor - context.isSanhei = this.document.isSanhei - context.isOther = this.document.isOther - return context - } } diff --git a/src/ui/sheets/items/sanhei.js b/src/ui/sheets/items/sanhei.js new file mode 100644 index 0000000..687c539 --- /dev/null +++ b/src/ui/sheets/items/sanhei.js @@ -0,0 +1,23 @@ +import { CDEBaseItemSheet } from "./base.js" + +export class CDESanheiSheet extends CDEBaseItemSheet { + static DEFAULT_OPTIONS = { + classes: ["sanhei"], + position: { width: 580, height: 620 }, + } + + static PARTS = { + main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/item/cde-sanhei-sheet.html" }, + } + + 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 + return context + } +} diff --git a/src/ui/sheets/items/supernatural.js b/src/ui/sheets/items/supernatural.js index 06e1289..c1bf30d 100644 --- a/src/ui/sheets/items/supernatural.js +++ b/src/ui/sheets/items/supernatural.js @@ -9,4 +9,11 @@ export class CDESupernaturalSheet extends CDEBaseItemSheet { static PARTS = { main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/item/cde-supernatural-sheet.html" }, } + + async _prepareContext() { + const context = await super._prepareContext() + const enrich = (content) => foundry.applications.ux.TextEditor.implementation.enrichHTML(content ?? "", { async: true }) + context.effectsHTML = await enrich(this.document.system.effects) + return context + } } diff --git a/src/ui/sheets/items/weapon.js b/src/ui/sheets/items/weapon.js new file mode 100644 index 0000000..e5b5df4 --- /dev/null +++ b/src/ui/sheets/items/weapon.js @@ -0,0 +1,12 @@ +import { CDEBaseItemSheet } from "./base.js" + +export class CDEWeaponSheet extends CDEBaseItemSheet { + static DEFAULT_OPTIONS = { + classes: ["weapon"], + position: { width: 580, height: 520 }, + } + + static PARTS = { + main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/item/cde-weapon-sheet.html" }, + } +} diff --git a/system.json b/system.json index 818b470..0b56dcf 100644 --- a/system.json +++ b/system.json @@ -10,8 +10,12 @@ "name": "LeRatierBretonnien" } ], - "esmodules": ["dist/system.js"], - "styles": ["css/cde-theme.css"], + "esmodules": [ + "dist/system.js" + ], + "styles": [ + "css/cde-theme.css" + ], "packFolders": [ { "name": "FR - Aides", @@ -142,7 +146,7 @@ "name": "English", "path": "lang/en-cde.json" }, - { + { "lang": "fr", "name": "Français", "path": "lang/fr-cde.json" @@ -155,13 +159,34 @@ ], "documentTypes": { "Actor": { - "character": { "htmlFields": ["description"] }, - "npc": { "htmlFields": ["description"] }, - "tinji": { "htmlFields": ["description"] }, - "loksyu": { "htmlFields": ["description"] } + "character": { + "htmlFields": [ + "description" + ] + }, + "npc": { + "htmlFields": [ + "description" + ] + }, + "tinji": { + "htmlFields": [ + "description" + ] + }, + "loksyu": { + "htmlFields": [ + "description" + ] + } }, "Item": { - "item": { "htmlFields": ["description", "notes"] }, + "item": { + "htmlFields": [ + "description", + "notes" + ] + }, "kungfu": { "htmlFields": [ "description", @@ -171,8 +196,49 @@ "notes" ] }, - "spell": { "htmlFields": ["description", "components", "effects", "examples", "notes"] }, - "supernatural": { "htmlFields": ["description", "notes"] } + "spell": { + "htmlFields": [ + "description", + "components", + "effects", + "examples", + "notes" + ] + }, + "supernatural": { + "htmlFields": [ + "description", + "notes", + "effects" + ] + }, + "weapon": { + "htmlFields": [ + "description", + "notes" + ] + }, + "armor": { + "htmlFields": [ + "description", + "notes" + ] + }, + "sanhei": { + "htmlFields": [ + "description", + "properties.prop1.description", + "properties.prop2.description", + "properties.prop3.description", + "notes" + ] + }, + "ingredient": { + "htmlFields": [ + "description", + "notes" + ] + } } }, "compatibility": { @@ -180,14 +246,16 @@ "verified": "13" }, "relationships": { - "requires": [{ - "id": "lib-wrapper", - "type": "module", - "manifest": "https://github.com/ruipin/fvtt-lib-wrapper/releases/download/v1.12.13.1/module.json", - "compatibility": { - "minimum": "1.12.13.1" + "requires": [ + { + "id": "lib-wrapper", + "type": "module", + "manifest": "https://github.com/ruipin/fvtt-lib-wrapper/releases/download/v1.12.13.1/module.json", + "compatibility": { + "minimum": "1.12.13.1" + } } - }] + ] }, "background": "/systems/fvtt-chroniques-de-l-etrange/images/background/accueil.jpg", "grid": { @@ -199,4 +267,4 @@ "secondaryTokenAttribute": "threetreasures.heiyin", "manifest": "https://chroniques-etrange-no.fr/download/foundry/system.json", "download": "https://chroniques-etrange-no.fr/download/foundry/release-233.zip" -} +} \ No newline at end of file diff --git a/templates/actor/cde-character-sheet.html b/templates/actor/cde-character-sheet.html index 5e26bfc..a867070 100644 --- a/templates/actor/cde-character-sheet.html +++ b/templates/actor/cde-character-sheet.html @@ -1,4 +1,4 @@ -
diff --git a/templates/actor/cde-loksyu-sheet.html b/templates/actor/cde-loksyu-sheet.html index 23222b8..878ad89 100644 --- a/templates/actor/cde-loksyu-sheet.html +++ b/templates/actor/cde-loksyu-sheet.html @@ -1,5 +1,4 @@ -
- {{log 'loksyu-sheet' this}} +
@@ -7,67 +6,132 @@
- {{ localize "CDE.Loksyu" }} - {{ localize "CDE.ModernJapan" }} + {{ localize "CDE.UpperCaseLoksyu" }} + Chroniques de l'Étrange
-
diff --git a/templates/actor/cde-npc-sheet.html b/templates/actor/cde-npc-sheet.html index b6c19b5..75a5c10 100644 --- a/templates/actor/cde-npc-sheet.html +++ b/templates/actor/cde-npc-sheet.html @@ -1,6 +1,4 @@ -
- {{log 'npc-sheet' this}} - +
@@ -12,19 +10,26 @@
- +
@@ -32,40 +37,41 @@
- +
+ + {{ localize "CDE.Initiative" }} +
- Init - - {{systemData.initiative}} - +
+ {{systemData.initiative}} + {{systemData.anti_initiative}} +
+ +
@@ -76,7 +82,7 @@
-
diff --git a/templates/actor/cde-tinji-sheet.html b/templates/actor/cde-tinji-sheet.html index b4552a2..c2551c7 100644 --- a/templates/actor/cde-tinji-sheet.html +++ b/templates/actor/cde-tinji-sheet.html @@ -1,5 +1,4 @@ -
- {{log 'tinji-sheet' this}} +
@@ -7,40 +6,43 @@
- {{ localize "CDE.TinJi2" }} - {{ localize "CDE.ModernJapan" }} + {{ localize "CDE.UpperCaseTinJi" }} + Chroniques de l'Étrange
-
diff --git a/templates/actor/parts/cde-character-items.html b/templates/actor/parts/cde-character-items.html index 33006a3..bdc1572 100644 --- a/templates/actor/parts/cde-character-items.html +++ b/templates/actor/parts/cde-character-items.html @@ -1,8 +1,100 @@ +{{! Weapons }} +{{#if weapons.length}} +

{{ localize "CDE.Weapons" }}

+{{/if}} +
    + {{#each weapons as |item id|}} +
  1. + +

    {{item.name}}

    + {{ localize "CDE.WeaponType" }} + {{item.system.damageBase}} +
    + + + +
    +
  2. + {{/each}} +
+

+ {{ localize "CDE.WeaponCreate" }} +

+ +{{! Armors }} +{{#if armors.length}} +

{{ localize "CDE.Armors" }}

+{{/if}} +
    + {{#each armors as |item id|}} +
  1. + +

    {{item.name}}

    + {{ localize "CDE.ArmorType" }} + {{#if item.system.protection}}{{item.system.protection}}{{/if}} +
    + + +
    +
  2. + {{/each}} +
+

+ {{ localize "CDE.ArmorCreate" }} +

+ +{{! Sanhei }} +{{#if sanheis.length}} +

{{ localize "CDE.Sanheis" }}

+{{/if}} +
    + {{#each sanheis as |item id|}} +
  1. + +

    {{item.name}}

    + {{ localize "CDE.SanheiType" }} +
    + + +
    +
  2. + {{/each}} +
+

+ {{ localize "CDE.SanheiCreate" }} +

+ +{{! Ingredients }} +{{#if ingredients.length}} +

{{ localize "CDE.Ingredients" }}

+{{/if}} +
    + {{#each ingredients as |item id|}} +
  1. + +

    {{item.name}}

    + {{ localize "CDE.IngredientType" }} +
    + + +
    +
  2. + {{/each}} +
+

+ {{ localize "CDE.IngredientCreate" }} +

+ +{{! Generic items }} +{{#if equipments.length}} +

{{ localize "CDE.Items" }}

+{{/if}}
    {{#each equipments as |item id|}}
  1. {{item.name}}

    + {{ localize "CDE.ItemType" }}
    diff --git a/templates/actor/parts/cde-character-kungfus.html b/templates/actor/parts/cde-character-kungfus.html index c340bbc..6f78f07 100644 --- a/templates/actor/parts/cde-character-kungfus.html +++ b/templates/actor/parts/cde-character-kungfus.html @@ -4,6 +4,7 @@

    {{item.name}}

    +
    diff --git a/templates/actor/parts/cde-character-magics.html b/templates/actor/parts/cde-character-magics.html index 18d19dd..1dae885 100644 --- a/templates/actor/parts/cde-character-magics.html +++ b/templates/actor/parts/cde-character-magics.html @@ -1,66 +1,65 @@
    {{ localize "CDE.Components2" }}
    - +
    - - + - - - + + - - + - - - + + - - + - - - + + - - + - - - + + - - + - - - + +
    Die + Die  Die +  Die
    Die + Die  Die +  Die
    Die + Die  Die +  Die
    Die + Die  Die +  Die
    Die + Die  Die +  Die
    -
    +
    - - -
    -
    - Die -
    - -
    -
    -
    - Die -
    - -
    -
    -
    -
    - Die -
    - -
    -
    -
    - Die -
    - -
    -
    -
    -
    - Die -
    - -
    +
    + +
    +
    + +
    +
    + Feu + {{ localize "CDE.Fire" }} +
    +
    + + Die + + +
    +
    {{ localize "CDE.FireQualities" }}
    +
    + +
    +
    + Bois + {{ localize "CDE.Wood" }} +
    +
    + + Die + + +
    +
    {{ localize "CDE.WoodQualities" }}
    +
    + +
    +
    + Terre + {{ localize "CDE.Earth" }} +
    +
    + + Die + + +
    +
    {{ localize "CDE.EarthQualities" }}
    +
    + +
    +
    + Eau + {{ localize "CDE.Water" }} +
    +
    + + Die + + +
    +
    {{ localize "CDE.WaterQualities" }}
    +
    + +
    +
    + Metal + {{ localize "CDE.Metal" }} +
    +
    + + Die + + +
    +
    {{ localize "CDE.MetalQualities" }}
    +
    + +
    +
    + Ng Hang
    -Ng Hang diff --git a/templates/actor/parts/cde-character-skills.html b/templates/actor/parts/cde-character-skills.html index 045390e..f031793 100644 --- a/templates/actor/parts/cde-character-skills.html +++ b/templates/actor/parts/cde-character-skills.html @@ -1,42 +1,46 @@
    {{ localize "CDE.Skills" }}
    - +
    {{#each systemData.skills as |skill key|}} - - + - - + - + + - - {{/each}}
    - Die +
    + Die  {{ localize skill.label }} - Cercle -
     
    - +
    {{ localize skill.label }} + - + + + +1D + Die +1 DDie
    {{ localize "CDE.Resources" }}
    - +
    {{#each systemData.resources as |resource key|}} - - - - + - + + + + + - - - {{/each}}
    NoDie {{ localize resource.label }} - Cercle -
     
    - +
    + NoDie - + {{ localize resource.label }} + + + + +1D + Die + + +1 DDie
    diff --git a/templates/actor/parts/cde-character-treasures.html b/templates/actor/parts/cde-character-treasures.html index f1713a3..303e288 100644 --- a/templates/actor/parts/cde-character-treasures.html +++ b/templates/actor/parts/cde-character-treasures.html @@ -1,98 +1,64 @@ -
    - {{ localize "CDE.HEI" }} +{{!-- HEI — Essence --}} +
    {{ localize "CDE.HEI" }} — {{ localize "CDE.Essence2" }}
    +
    +
    + Yang max + Yang + + Yin + Yin max +
    +
    + + + Yin Yang + + +
    -
    - {{ localize "CDE.Essence2" }} + +{{!-- SAN-ZING — Santé --}} +
    {{ localize "CDE.SAN-ZING" }} — {{ localize "CDE.MentalHealth-PhysicalHealth" }}
    +
    +
    + San max + San + Malus + Zing + Zing max +
    +
    + + + 0 dé + + +
    +
    + + + - 1 dé + + +
    +
    + + + - 2 dés + + +
    -
    - {{ localize "CDE.YANG-YIN" }} + +{{!-- PTAO — Expérience --}} +
    {{ localize "CDE.PTAO" }} — {{ localize "CDE.Experience" }}
    +
    +
    + {{ localize "CDE.Total" }} + {{ localize "CDE.Present" }} +
    +
    + + +
    -
    - {{ localize "CDE.Max-Present-Present-Max" }} -
    -
    - Cercle - Cercle - Yin Yang - Cercle - Cercle -
    -
    - - - - -

      - 
      -
    - {{ localize "CDE.SAN-ZING" }} -
    -
    - {{ localize "CDE.MentalHealth-PhysicalHealth" }} -
    -
    -{{ localize "CDE.Max-Present-Malus-Present-Max" }} -
    -
    - Cercle - Cercle - -- - Cercle - Cercle -
    -
    - - - - -

      - 
      -
    - Cercle - Cercle - - 1 D - Cercle - Cercle -
    -
    - - - - -

      - 
      -
    - Cercle - Cercle - - 2 D - Cercle - Cercle -
    -
    - - - - -

      - 
      -
    - {{ localize "CDE.PTAO" }} -
    -
    - {{ localize "CDE.Experience" }} -
    -
    - {{ localize "CDE.Total-Present" }} -
    -
    - Cercle - Cercle -
    -
    - - -
    \ No newline at end of file diff --git a/templates/form/cde-dice-result.html b/templates/form/cde-dice-result.html index b311001..f773606 100644 --- a/templates/form/cde-dice-result.html +++ b/templates/form/cde-dice-result.html @@ -1,437 +1,133 @@ -
    -
    +
    -
    - - {{!-- Sheet Body --}} -
    + {{!-- Header: aspect identity + roll label --}} +
    +
    + {{aspectLabel}} +
    + {{aspectLabel}} + {{rollLabel}} +
    +
    + {{#if actorImg}} +
    + {{actorName}} + {{actorName}} +
    + {{/if}} +
    - {{!-- Frame --}} -
    + {{!-- Hero: successes count (+ spell power for magic rolls) --}} +
    + {{successesdice}} +
    + {{ localize "CDE.UpperCaseSuccesses" }} + {{totalDice}} d10 +
    + {{#if spellPower}} +
    + {{spellPower}} + {{ localize "CDE.SpellPower" }} +
    + {{/if}} +
    - {{#if (eq aspect 'wood')}} - - - - - - - - - - - - - - - - -
    -
    - {{ successesdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseSuccesses" }} -
    -
    -
    - {{ auspiciousdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseAuspiciousDice" }} -
    -
    -
    - {{ noxiousdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseNoxiousDice" }} -
    -
    -
    - {{ loksyudice }} {{ loksyurepartition }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseLoksyu" }} -
    -
    -
    - {{ tinjidice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseTinJi" }} -
    -
    - {{/if}} + {{!-- Detail rows: auspicious / noxious / loksyu / tinji --}} +
    - {{#if (eq aspect 'fire')}} - - - - - - - - - - - - - - - - -
    -
    - {{ successesdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseSuccesses" }} -
    -
    -
    - {{ auspiciousdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseAuspiciousDice" }} -
    -
    -
    - {{ noxiousdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseNoxiousDice" }} -
    -
    -
    - {{ loksyudice }} {{ loksyurepartition }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseLoksyu" }} -
    -
    -
    - {{ tinjidice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseTinJi" }} -
    -
    - {{/if}} +
    + {{auspiciousdice}} +
    + {{ localize "CDE.UpperCaseAuspiciousDice" }} +
    - {{#if (eq aspect 'earth')}} - - - - - - - - - - - - - - - - -
    -
    - {{ successesdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseSuccesses" }} -
    -
    -
    - {{ auspiciousdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseAuspiciousDice" }} -
    -
    -
    - {{ noxiousdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseNoxiousDice" }} -
    -
    -
    - {{ loksyudice }} {{ loksyurepartition }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseLoksyu" }} -
    -
    -
    - {{ tinjidice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseTinJi" }} -
    -
    - {{/if}} +
    + {{noxiousdice}} +
    + {{ localize "CDE.UpperCaseNoxiousDice" }} +
    - {{#if (eq aspect 'metal')}} - - - - - - - - - - - - - - - - -
    -
    - {{ successesdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseSuccesses" }} -
    -
    -
    - {{ auspiciousdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseAuspiciousDice" }} -
    -
    -
    - {{ noxiousdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseNoxiousDice" }} -
    -
    -
    - {{ loksyudice }} {{ loksyurepartition }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseLoksyu" }} -
    -
    -
    - {{ tinjidice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseTinJi" }} -
    -
    - {{/if}} +
    + {{loksyudice}} +
    + {{ localize "CDE.UpperCaseLoksyu" }} + {{loksyurepartition}} + +
    - {{#if (eq aspect 'water')}} - - - - - - - - - - - - - - - - -
    -
    - {{ successesdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseSuccesses" }} -
    -
    -
    - {{ auspiciousdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseAuspiciousDice" }} -
    -
    -
    - {{ noxiousdice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseNoxiousDice" }} -
    -
    -
    - {{ loksyudice }} {{ loksyurepartition }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseLoksyu" }} -
    -
    -
    - {{ tinjidice }} -
    -
    - -
    -
    - {{ localize "CDE.UpperCaseTinJi" }} -
    -
    - {{/if}} -
    - - - - - - - - - - - - - - - -
    - {{ d1 }} - - {{ d2 }} - - {{ d3 }} - - {{ d4 }} - - {{ d5 }} -
    - - - - - - - - - -
    - - - - - - - - - - - - - - - -
    - {{ d6 }} - - {{ d7 }} - - {{ d8 }} - - {{ d9 }} - - {{ d0 }} -
    - - - - - - - - - -
    -
    -
    -
    -
    \ No newline at end of file +
    + {{tinjidice}} +
    + {{ localize "CDE.UpperCaseTinJi" }} +
    + +
    + + {{!-- Weapon damage (only for weapon rolls) --}} + {{#if weaponName}} +
    + +
    + {{weaponName}} + + {{successesdice}} × {{damageBase}} = + {{totalDamage}} + {{ localize "CDE.TotalDamage" }} + +
    +
    + {{/if}} + + {{!-- Modifiers footer (only if non-empty) --}} + {{#if modifiersText}} + + {{/if}} + + {{!-- Die face counts grid (d1–d9, d0=10) --}} +
    +
    + {{d1}} + 1 +
    +
    + {{d2}} + 2 +
    +
    + {{d3}} + 3 +
    +
    + {{d4}} + 4 +
    +
    + {{d5}} + 5 +
    +
    + {{d6}} + 6 +
    +
    + {{d7}} + 7 +
    +
    + {{d8}} + 8 +
    +
    + {{d9}} + 9 +
    +
    + {{d0}} + 10 +
    +
    + +
    diff --git a/templates/form/cde-initiative-prompt-npc.html b/templates/form/cde-initiative-prompt-npc.html new file mode 100644 index 0000000..a898b62 --- /dev/null +++ b/templates/form/cde-initiative-prompt-npc.html @@ -0,0 +1,33 @@ +
    + +
    + {{ localize "CDE.InitiativeRoll" }} + +
    + +
    +
    + + {{physicalValue}} +
    + + +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    {{ localize "CDE.InitiativeFormulaNPC" }}
    + +
    diff --git a/templates/form/cde-initiative-prompt.html b/templates/form/cde-initiative-prompt.html new file mode 100644 index 0000000..b97a5be --- /dev/null +++ b/templates/form/cde-initiative-prompt.html @@ -0,0 +1,33 @@ +
    + +
    + {{ localize "CDE.InitiativeRoll" }} + +
    + +
    +
    + + {{prowessValue}} +
    + + +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    {{ localize "CDE.InitiativeFormula" }}
    + +
    diff --git a/templates/form/cde-initiative-result.html b/templates/form/cde-initiative-result.html new file mode 100644 index 0000000..02b1002 --- /dev/null +++ b/templates/form/cde-initiative-result.html @@ -0,0 +1,41 @@ +
    + + {{!-- Header: actor identity --}} +
    + {{#if actorImg}} + {{actorName}} + {{/if}} +
    + {{actorName}} + {{ localize "CDE.InitiativeRoll" }} +
    +
    + + {{!-- Formula display --}} +
    + {{baseName}} + {{baseValue}} + + + {{actionName}} + {{actionValue}} + {{#if hasModifier}} + {{#if (gt modifier 0)}}+{{else}}{{/if}} + {{modifier}} + {{/if}} + = + {{initiative}} +
    + + {{!-- Hero: big neon initiative number --}} +
    + {{initiative}} +
    + {{ localize "CDE.Initiative" }} + + {{ localize "CDE.AntiInitiative" }} + {{antiInitiative}} + +
    +
    + +
    diff --git a/templates/form/cde-magic-dice-prompt.html b/templates/form/cde-magic-dice-prompt.html index 505e937..1d13df8 100644 --- a/templates/form/cde-magic-dice-prompt.html +++ b/templates/form/cde-magic-dice-prompt.html @@ -1,152 +1,77 @@ -
    -
    -
    - -
    -
    - - {{!-- Sheet Body --}} -
    - {{!-- Frame --}} -
    +
    + {{ localize "CDE.MagicPromptName" }} +
    - - - - -
    - {{ localize "CDE.OneMagicRoll" }} -
    - - - - - - - - -
      - -
    - -
    -
    - {{ numberofdice }} -
    -
      + 1 + 
    - - - - - - - - - - - - - - - -
    {{ localize "CDE.AspectSkill" }} {{ localize "CDE.BonusMalus" }} {{ localize "CDE.BonusAuspiciousDice" }}
    - - +  - -
    - - - - -
    -  {{ localize "CDE.DoNotModify" }} -
    -
    - - - - -
    - {{ localize "CDE.TwoPowerOfSpell" }} -
    - - - - - - - - - - - - - - - -
    {{ localize "CDE.AspectSpeciality" }} {{ localize "CDE.RollDifficulty" }} {{ localize "CDE.BonusMalus" }}
    - - +
    - - - - -
    -  {{ localize "CDE.DoNotModify" }} -
    -
     
    - - - {{ localize "CDE.TypeOfThrow" }} - - -
    - -
    + {{!-- Part 1: Magic Skill Roll --}} +
    +

    ① {{ localize "CDE.OneMagicRoll" }}

    +
    {{ numberofdice }}d10 +1
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +

    {{ localize "CDE.DoNotModify" }}

    +
    -
    -
    -
    \ No newline at end of file + {{!-- Part 2: Spell Power Roll --}} +
    +

    ② {{ localize "CDE.TwoPowerOfSpell" }}

    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +

    {{ localize "CDE.DoNotModify" }}

    +
    + + {{!-- Visibility --}} +
    +
    + + +
    +
    + +
    \ No newline at end of file diff --git a/templates/form/cde-skill-dice-prompt.html b/templates/form/cde-skill-dice-prompt.html index 521dd2a..808fc1b 100644 --- a/templates/form/cde-skill-dice-prompt.html +++ b/templates/form/cde-skill-dice-prompt.html @@ -1,102 +1,45 @@ -
    -
    -
    - -
    -
    - - {{!-- Sheet Body --}} -
    +
    - {{!-- Frame --}} -
    +
    + {{ localize "CDE.SkillPromptName" }} + {{ numberofdice }}d10 +
    - - - - - - - - -
      - -
    - -
    -
    - {{ numberofdice }} -
    -
      +  
    - - - - - - - - - - - -
    {{ localize "CDE.Aspect" }} {{ localize "CDE.BonusMalus" }}
    - -  + 
    - - - - - - - -
    {{ localize "CDE.BonusAuspiciousDice" }}
    - -
    -
    - - - {{ localize "CDE.TypeOfThrow" }} - - -
    - -
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    -
    -
    -
    \ No newline at end of file +
    +
    + + +
    +
    + + +
    +
    + +
    \ No newline at end of file diff --git a/templates/form/cde-skill-special-dice-prompt.html b/templates/form/cde-skill-special-dice-prompt.html index 2c7dbbd..f4b5317 100644 --- a/templates/form/cde-skill-special-dice-prompt.html +++ b/templates/form/cde-skill-special-dice-prompt.html @@ -1,102 +1,45 @@ -
    -
    -
    - -
    -
    - - {{!-- Sheet Body --}} -
    +
    - {{!-- Frame --}} -
    +
    + {{ localize "CDE.SkillPromptName" }} + {{ numberofdice }}d10 +1 +
    - - - - - - - - -
      - -
    - -
    -
    - {{ numberofdice }} -
    -
      + 1 + 
    - - - - - - - - - - - -
    {{ localize "CDE.Aspect" }} {{ localize "CDE.BonusMalus" }}
    - -  + 
    - - - - - - - -
    {{ localize "CDE.BonusAuspiciousDice" }}
    - -
    -
    - - - {{ localize "CDE.TypeOfThrow" }} - - -
    - -
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    -
    -
    -
    \ No newline at end of file +
    +
    + + +
    +
    + + +
    +
    + +
    \ No newline at end of file diff --git a/templates/form/cde-weapon-dice-prompt.html b/templates/form/cde-weapon-dice-prompt.html new file mode 100644 index 0000000..c906804 --- /dev/null +++ b/templates/form/cde-weapon-dice-prompt.html @@ -0,0 +1,80 @@ +
    + + {{!-- Weapon identity bar --}} +
    + {{weaponAspectLabel}} +
    + {{weaponName}} + {{ localize weaponTypeLabel }} · {{ localize "CDE.DamageBase" }}: {{damageBase}} +
    +
    + +
    +
    + +
    + {{ localize "CDE.WeaponRollTitle" }} + {{numberofdice}}d10 +
    + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    diff --git a/templates/item/cde-armor-sheet.html b/templates/item/cde-armor-sheet.html new file mode 100644 index 0000000..7e7bcd6 --- /dev/null +++ b/templates/item/cde-armor-sheet.html @@ -0,0 +1,65 @@ +
    +
    + +
    +

    + +

    +
    +
    + + + +
    +
    +
    {{ localize "CDE.Details" }}
    +
    +
    +
    + {{ localize "CDE.ProtectionValue" }} + +
    +
    + {{ localize "CDE.Domain" }} + +
    +
    + {{ localize "CDE.ObtainLevel" }} + +
    +
    + {{ localize "CDE.ObtainDifficulty" }} + +
    +
    + {{ localize "CDE.Quantity" }} + +
    +
    + {{ localize "CDE.Reference" }} + +
    +
    +
    + {{ localize "CDE.Protection" }} +
    +
    +
    +
    +
    {{ localize "CDE.Description" }}
    +
    + {{formInput systemFields.description enriched=descriptionHTML value=system.description name="system.description" toggled=true}} +
    +
    +
    +
    {{ localize "CDE.Notes" }}
    +
    + {{formInput systemFields.notes enriched=notesHTML value=system.notes name="system.notes" toggled=true}} +
    +
    +
    +
    diff --git a/templates/item/cde-ingredient-sheet.html b/templates/item/cde-ingredient-sheet.html new file mode 100644 index 0000000..95ebf2d --- /dev/null +++ b/templates/item/cde-ingredient-sheet.html @@ -0,0 +1,68 @@ +
    +
    + +
    +

    + +

    +
    +
    + + + +
    +
    +
    {{ localize "CDE.Details" }}
    +
    +
    +
    + {{ localize "CDE.School" }} + +
    +
    + {{ localize "CDE.ObtainLevel" }} + +
    +
    + {{ localize "CDE.ObtainDifficulty" }} + +
    +
    + {{ localize "CDE.Quantity" }} + +
    +
    + {{ localize "CDE.Reference" }} + +
    +
    +
    + {{ localize "CDE.Ingredient" }} +
    +
    +
    +
    +
    {{ localize "CDE.Description" }}
    +
    + {{formInput systemFields.description enriched=descriptionHTML value=system.description name="system.description" toggled=true}} +
    +
    +
    +
    {{ localize "CDE.Notes" }}
    +
    + {{formInput systemFields.notes enriched=notesHTML value=system.notes name="system.notes" toggled=true}} +
    +
    +
    +
    diff --git a/templates/item/cde-item-sheet.html b/templates/item/cde-item-sheet.html index 3e9295b..42a769a 100644 --- a/templates/item/cde-item-sheet.html +++ b/templates/item/cde-item-sheet.html @@ -1,67 +1,53 @@ -
    +

    -
    -
    - {{ localize "CDE.TypeOfItem" }} - -
    -
    - {{ localize "CDE.Reference" }} - -
    -
    - {{ localize "CDE.Quantity" }} - -
    -
    - {{ localize "CDE.Weight" }} - -
    - {{#if isWeapon}} -
    - {{ localize "CDE.Damage" }} - -
    -
    - {{ localize "CDE.Range" }} - -
    - {{/if}} - {{#if isArmor}} -
    - {{ localize "CDE.Protection" }} - -
    - {{/if}} -
    -
    - {{ localize "CDE.Items" }} -
    +
    +
    {{ localize "CDE.Details" }}
    +
    +
    +
    + {{ localize "CDE.Reference" }} + +
    +
    + {{ localize "CDE.Quantity" }} + +
    +
    + {{ localize "CDE.Weight" }} + +
    +
    +
    + {{ localize "CDE.Items" }} +
    +
    +
    +
    {{ localize "CDE.Description" }}
    - {{editor descriptionHTML target="system.description" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.description enriched=descriptionHTML value=system.description name="system.description" toggled=true}}
    +
    {{ localize "CDE.Notes" }}
    - {{editor notesHTML target="system.notes" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.notes enriched=notesHTML value=system.notes name="system.notes" toggled=true}}
    - +
    diff --git a/templates/item/cde-kungfu-sheet.html b/templates/item/cde-kungfu-sheet.html index 6841a4b..a4ce548 100644 --- a/templates/item/cde-kungfu-sheet.html +++ b/templates/item/cde-kungfu-sheet.html @@ -1,39 +1,15 @@ -
    +

    -
    -
    - {{ localize "CDE.Orientation" }} - -
    -
    - {{ localize "CDE.Aspect" }} - -
    -
    - {{ localize "CDE.Skill" }} - -
    -
    - {{ localize "CDE.Speciality" }} - -
    -
    - {{ localize "CDE.Reference" }} - -
    -
    -
    - {{ localize "CDE.KungFu" }} -
    +
    +
    {{ localize "CDE.Details" }}
    +
    +
    +
    + {{ localize "CDE.Orientation" }} + +
    +
    + {{ localize "CDE.Aspect" }} + +
    +
    + {{ localize "CDE.Skill" }} + +
    +
    + {{ localize "CDE.Speciality" }} + +
    +
    + {{ localize "CDE.Style" }} + +
    +
    + {{ localize "CDE.Reference" }} + +
    +
    +
    + {{ localize "CDE.KungFu" }} +
    +
    +
    +
    +
    {{ localize "CDE.Description" }}
    - {{editor descriptionHTML target="system.description" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.description enriched=descriptionHTML value=system.description name="system.description" toggled=true}}
    @@ -65,13 +90,21 @@
    {{ localize "CDE.Activation" }} - +
    - {{editor descriptionTechnique1HTML target="system.techniques.technique1.technique" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.techniques.fields.technique1.fields.technique enriched=descriptionTechnique1HTML value=system.techniques.technique1.technique name="system.techniques.technique1.technique" toggled=true}}
    @@ -93,13 +126,21 @@
    {{ localize "CDE.Activation" }} - +
    - {{editor descriptionTechnique2HTML target="system.techniques.technique2.technique" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.techniques.fields.technique2.fields.technique enriched=descriptionTechnique2HTML value=system.techniques.technique2.technique name="system.techniques.technique2.technique" toggled=true}}
    @@ -121,21 +162,30 @@
    {{ localize "CDE.Activation" }} - +
    - {{editor descriptionTechnique3HTML target="system.techniques.technique3.technique" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.techniques.fields.technique3.fields.technique enriched=descriptionTechnique3HTML value=system.techniques.technique3.technique name="system.techniques.technique3.technique" toggled=true}}
    +
    {{ localize "CDE.Notes" }}
    - {{editor notesHTML target="system.notes" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.notes enriched=notesHTML value=system.notes name="system.notes" toggled=true}}
    - + diff --git a/templates/item/cde-sanhei-sheet.html b/templates/item/cde-sanhei-sheet.html new file mode 100644 index 0000000..89a2a11 --- /dev/null +++ b/templates/item/cde-sanhei-sheet.html @@ -0,0 +1,135 @@ +
    +
    + +
    +

    + +

    +
    +
    + + + +
    +
    +
    {{ localize "CDE.Details" }}
    +
    +
    +
    + {{ localize "CDE.HeiType" }} + +
    +
    + {{ localize "CDE.Reference" }} + +
    +
    +
    + {{ localize "CDE.Sanhei" }} +
    +
    +
    + +
    +
    {{ localize "CDE.Description" }}
    +
    + {{formInput systemFields.description enriched=descriptionHTML value=system.description name="system.description" toggled=true}} +
    +
    + +
    +
    {{ localize "CDE.Property" }} 1
    +
    +
    +
    + {{ localize "CDE.Property" }} + +
    +
    + {{ localize "CDE.HeiCost" }} + +
    +
    + {{ localize "CDE.HeiType" }} + +
    +
    +
    +
    + {{formInput propFields.prop1.fields.description enriched=prop1DescriptionHTML value=system.properties.prop1.description name="system.properties.prop1.description" toggled=true}} +
    +
    + +
    +
    {{ localize "CDE.Property" }} 2
    +
    +
    +
    + {{ localize "CDE.Property" }} + +
    +
    + {{ localize "CDE.HeiCost" }} + +
    +
    + {{ localize "CDE.HeiType" }} + +
    +
    +
    +
    + {{formInput propFields.prop2.fields.description enriched=prop2DescriptionHTML value=system.properties.prop2.description name="system.properties.prop2.description" toggled=true}} +
    +
    + +
    +
    {{ localize "CDE.Property" }} 3
    +
    +
    +
    + {{ localize "CDE.Property" }} + +
    +
    + {{ localize "CDE.HeiCost" }} + +
    +
    + {{ localize "CDE.HeiType" }} + +
    +
    +
    +
    + {{formInput propFields.prop3.fields.description enriched=prop3DescriptionHTML value=system.properties.prop3.description name="system.properties.prop3.description" toggled=true}} +
    +
    + +
    +
    {{ localize "CDE.Notes" }}
    +
    + {{formInput systemFields.notes enriched=notesHTML value=system.notes name="system.notes" toggled=true}} +
    +
    +
    +
    diff --git a/templates/item/cde-spell-sheet.html b/templates/item/cde-spell-sheet.html index 177d10d..a3797e7 100644 --- a/templates/item/cde-spell-sheet.html +++ b/templates/item/cde-spell-sheet.html @@ -1,49 +1,15 @@ -
    +

    -
    -
    - {{ localize "CDE.SpecialityName" }} - -
    -
    - {{ localize "CDE.AssociatedElement" }} - -
    -
    - {{ localize "CDE.Hei" }} - -
    -
    - {{ localize "CDE.Reference" }} - -
    -
    -
    -
    - {{ localize "CDE.RealizationTimeRitual" }} - -
    -
    - {{ localize "CDE.RealizationTimeAccelerated" }} - -
    -
    - {{ localize "CDE.Flashback" }} - -
    -
    -
    - {{ localize "CDE.Spells" }} -
    +
    +
    {{ localize "CDE.Details" }}
    +
    +
    +
    + {{ localize "CDE.Discipline" }} + +
    +
    + {{ localize "CDE.SpecialityName" }} + +
    +
    + {{ localize "CDE.AssociatedElement" }} + +
    +
    + {{ localize "CDE.HeiType" }} + +
    +
    + {{ localize "CDE.Hei" }} + +
    +
    + {{ localize "CDE.HeiCost" }} + +
    +
    + {{ localize "CDE.Difficulty" }} + +
    +
    + {{ localize "CDE.RealizationTimeRitual" }} + +
    +
    + {{ localize "CDE.RealizationTimeAccelerated" }} + +
    +
    + {{ localize "CDE.Flashback" }} + +
    +
    + {{ localize "CDE.Reference" }} + +
    +
    +
    + {{ localize "CDE.Spells" }} +
    +
    +
    +
    {{ localize "CDE.Description" }}
    - {{editor spellDescriptionHTML target="system.description" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.description enriched=spellDescriptionHTML value=system.description name="system.description" toggled=true}}
    +
    {{ localize "CDE.Components" }}
    - {{editor componentsDescriptionHTML target="system.components" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.components enriched=componentsDescriptionHTML value=system.components name="system.components" toggled=true}}
    +
    {{ localize "CDE.Effects" }}
    - {{editor effectsDescriptionHTML target="system.effects" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.effects enriched=effectsDescriptionHTML value=system.effects name="system.effects" toggled=true}}
    +
    {{ localize "CDE.Examples" }}
    - {{editor examplesDescriptionHTML target="system.examples" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.examples enriched=examplesDescriptionHTML value=system.examples name="system.examples" toggled=true}}
    +
    {{ localize "CDE.Notes" }}
    - {{editor notesHTML target="system.notes" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.notes enriched=notesHTML value=system.notes name="system.notes" toggled=true}}
    - +
    diff --git a/templates/item/cde-supernatural-sheet.html b/templates/item/cde-supernatural-sheet.html index 355d406..3b2d4eb 100644 --- a/templates/item/cde-supernatural-sheet.html +++ b/templates/item/cde-supernatural-sheet.html @@ -1,37 +1,67 @@ -
    +

    -
    -
    - {{ localize "CDE.Reference" }} - -
    -
    -
    - {{ localize "CDE.Supernatural" }} -
    +
    +
    {{ localize "CDE.Details" }}
    +
    +
    +
    + {{ localize "CDE.Reference" }} + +
    +
    + {{ localize "CDE.HeiType" }} + +
    +
    + {{ localize "CDE.HeiCost" }} + +
    +
    + {{ localize "CDE.Trigger" }} + +
    +
    +
    + {{ localize "CDE.SuperNatural" }} +
    +
    +
    +
    {{ localize "CDE.Description" }}
    - {{editor descriptionHTML target="system.description" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.description enriched=descriptionHTML value=system.description name="system.description" toggled=true}} +
    +
    +
    +
    {{ localize "CDE.Effects" }}
    +
    + {{formInput systemFields.effects enriched=effectsHTML value=system.effects name="system.effects" toggled=true}}
    +
    {{ localize "CDE.Notes" }}
    - {{editor notesHTML target="system.notes" button=true editable=editable engine="prosemirror"}} + {{formInput systemFields.notes enriched=notesHTML value=system.notes name="system.notes" toggled=true}}
    - +
    diff --git a/templates/item/cde-weapon-sheet.html b/templates/item/cde-weapon-sheet.html new file mode 100644 index 0000000..a57cb23 --- /dev/null +++ b/templates/item/cde-weapon-sheet.html @@ -0,0 +1,94 @@ +
    +
    + +
    +

    + +

    +
    +
    + + + +
    +
    +
    {{ localize "CDE.Details" }}
    +
    +
    +
    + {{ localize "CDE.WeaponType" }} + +
    +
    + {{ localize "CDE.Material" }} + +
    +
    + {{ localize "CDE.DamageBase" }} + +
    +
    + {{ localize "CDE.DamageAspect" }} + +
    +
    + {{ localize "CDE.Range" }} + +
    +
    + {{ localize "CDE.ObtainLevel" }} + +
    +
    + {{ localize "CDE.ObtainDifficulty" }} + +
    +
    + {{ localize "CDE.Quantity" }} + +
    +
    + {{ localize "CDE.Reference" }} + +
    +
    +
    + {{ localize "CDE.Weapon" }} +
    +
    +
    +
    +
    {{ localize "CDE.Description" }}
    +
    + {{formInput systemFields.description enriched=descriptionHTML value=system.description name="system.description" toggled=true}} +
    +
    +
    +
    {{ localize "CDE.Notes" }}
    +
    + {{formInput systemFields.notes enriched=notesHTML value=system.notes name="system.notes" toggled=true}} +
    +
    +
    +
+
{{log 'actor-sheet' this}}
@@ -20,14 +20,12 @@
@@ -37,37 +35,40 @@ Chroniques de l'Étrange
- +
+ + {{ localize "CDE.Initiative" }} +
- Init - - {{systemData.initiative}} - +
+ {{systemData.initiative}} + {{systemData.anti_initiative}} +
+ +
-