Files
fvtt-chroniques-de-l-etrange/src/ui/helpers.js
T
2026-05-12 00:34:47 +02:00

132 lines
5.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Chroniques de l'Étrange — Système FoundryVTT
*
* Chroniques de l'Étrange est un jeu de rôle édité par Antre-Monde Éditions.
* Ce système FoundryVTT est une implémentation indépendante et n'est pas
* affilié à Antre-Monde Éditions,
* mais a été réalisé avec l'autorisation d'Antre-Monde Éditions.
*
* @author LeRatierBretonnien
* @copyright 20242026 LeRatierBretonnien
* @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
*/
import { MAGICS } from "../config/constants.js"
export function registerHandlebarsHelpers() {
const { Handlebars } = globalThis
if (!Handlebars) return
Handlebars.registerHelper("getMagicLabel", function (magic) {
return game.i18n.localize(MAGICS[magic]?.label ?? "")
})
Handlebars.registerHelper("getMagicAspectLabel", function (magic) {
return game.i18n.localize(MAGICS[magic]?.aspectlabel ?? "")
})
Handlebars.registerHelper("getMagicSpecialityLabel", function (magic, speciality) {
return game.i18n.localize(MAGICS[magic]?.speciality?.[speciality]?.label ?? "")
})
Handlebars.registerHelper("getMagicSpecialityClassIcon", function (magic, speciality) {
return MAGICS[magic]?.speciality?.[speciality]?.classicon ?? ""
})
Handlebars.registerHelper("getMagicSpecialityElementIcon", function (magic, speciality) {
return MAGICS[magic]?.speciality?.[speciality]?.elementicon ?? ""
})
Handlebars.registerHelper("getMagicSpecialityLabelIcon", function (magic, speciality) {
return MAGICS[magic]?.speciality?.[speciality]?.labelicon ?? ""
})
Handlebars.registerHelper("getMagicSpecialityLabelElement", function (magic, speciality) {
return game.i18n.localize(MAGICS[magic]?.speciality?.[speciality]?.labelelement ?? "")
})
Handlebars.registerHelper("getMagicAspectIcon", function (magic) {
const icons = {
internalcinnabar: "/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp",
alchemy: "/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp",
masteryoftheway: "/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp",
exorcism: "/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp",
geomancy: "/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp",
}
return icons[magic] ?? ""
})
Handlebars.registerHelper("getElementIcon", function (aspect) {
const icons = {
metal: "/systems/fvtt-chroniques-de-l-etrange/images/cde_metal.webp",
water: "/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp",
earth: "/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp",
fire: "/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp",
wood: "/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp",
// legacy French keys
eau: "/systems/fvtt-chroniques-de-l-etrange/images/cde_eau.webp",
terre: "/systems/fvtt-chroniques-de-l-etrange/images/cde_terre.webp",
feu: "/systems/fvtt-chroniques-de-l-etrange/images/cde_feu.webp",
bois: "/systems/fvtt-chroniques-de-l-etrange/images/cde_bois.webp",
}
return icons[aspect] ?? ""
})
Handlebars.registerHelper("getOrientationIcon", function (orientation) {
const icons = {
yin: "/systems/fvtt-chroniques-de-l-etrange/images/cde_yin.webp",
yang: "/systems/fvtt-chroniques-de-l-etrange/images/cde_yang.webp",
yinyang: "/systems/fvtt-chroniques-de-l-etrange/images/yin_yang.webp",
}
return icons[orientation] ?? ""
})
Handlebars.registerHelper("getOrientationLabel", function (orientation) {
const keys = {
yin: "CDE.OrientationYin",
yang: "CDE.OrientationYang",
yinyang: "CDE.OrientationYinYang",
}
return game.i18n.localize(keys[orientation] ?? "CDE.Orientation")
})
Handlebars.registerHelper("getActivationLabel", function (activation) {
const keys = {
"action-attack": "CDE.ActivationAttack",
"action-defense": "CDE.ActivationDefense",
"action-aid": "CDE.ActivationAid",
"action-attack-defense": "CDE.ActivationAttackOrDefense",
reaction: "CDE.ActivationReaction",
dice: "CDE.ActivationDice",
"damage-inflicted": "CDE.ActivationDamageInflicted",
"damage-received": "CDE.ActivationDamageReceived",
}
return game.i18n.localize(keys[activation] ?? "CDE.Activation")
})
/**
* Compute the SVG x,y coordinates for a cran on the initiative wheel.
* Cran 124 are arranged counter-clockwise from the bottom (reference at 6 o'clock).
* angle = 90° + cran * 15° (counter-clockwise = positive in standard math, negative in SVG).
* In SVG coords: x = cx + r*cos(a), y = cy - r*sin(a) [y-axis is flipped in SVG].
*/
Handlebars.registerHelper("cranPosition", function (cran, cx, cy, r) {
const angleDeg = 90 + cran * 15 // counter-clockwise from bottom
const angleRad = (angleDeg * Math.PI) / 180
const x = Math.round(cx + r * Math.cos(angleRad))
const y = Math.round(cy - r * Math.sin(angleRad))
return { x, y }
})
/** X offset for overlapping fighters on the same cran. Centres a 30px image on the cran cx. */
Handlebars.registerHelper("fighterX", function (cx, index, total) {
const offset = total > 1 ? (index - (total - 1) / 2) * 34 : 0
return Math.round(cx - 15 + offset)
})
/** Y offset for fighters — positions image just above the cran circle. */
Handlebars.registerHelper("fighterY", function (cy, index, total) {
return Math.round(cy - 50)
})
}