Initial release for FoundryVTT
This commit is contained in:
189
modules/donjon-et-cie-utility.mjs
Normal file
189
modules/donjon-et-cie-utility.mjs
Normal file
@@ -0,0 +1,189 @@
|
||||
import { DONJON_ET_CIE } from "./donjon-et-cie-config.mjs";
|
||||
|
||||
export class DonjonEtCieUtility {
|
||||
static defaultItemIcons = {
|
||||
arme: "systems/fvtt-donjon-et-cie/assets/icons/system/items/arme.svg",
|
||||
armure: "systems/fvtt-donjon-et-cie/assets/icons/system/items/armure.svg",
|
||||
trait: "systems/fvtt-donjon-et-cie/assets/icons/system/items/trait.svg",
|
||||
sortilege: "systems/fvtt-donjon-et-cie/assets/icons/system/items/sortilege.svg",
|
||||
equipement: "systems/fvtt-donjon-et-cie/assets/icons/system/items/equipement.svg",
|
||||
other: "systems/fvtt-donjon-et-cie/assets/icons/system/items/autre.svg"
|
||||
};
|
||||
|
||||
static async preloadHandlebarsTemplates() {
|
||||
return foundry.applications.handlebars.loadTemplates([
|
||||
"systems/fvtt-donjon-et-cie/templates/actors/employe-sheet.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/actors/pnj-sheet.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/items/item-sheet.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/dialogs/characteristic-roll.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/dialogs/initiative-roll.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/dialogs/weapon-roll.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/dialogs/damage-roll.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/dialogs/spell-roll.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/dialogs/usage-roll.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/chat/roll-card.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/chat/spell-card.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/chat/chaos-card.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/chat/hit-dice-card.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/chat/damage-card.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/chat/damage-application-card.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/chat/favor-card.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/chat/initiative-card.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/chat/usage-card.hbs",
|
||||
"systems/fvtt-donjon-et-cie/templates/chat/item-card.hbs"
|
||||
]);
|
||||
}
|
||||
|
||||
static getCharacteristicEntries(system) {
|
||||
return Object.entries(DONJON_ET_CIE.characteristics).map(([key, metadata]) => ({
|
||||
key,
|
||||
label: metadata.label,
|
||||
short: metadata.short,
|
||||
value: system.caracteristiques?.[key]?.value ?? 0
|
||||
}));
|
||||
}
|
||||
|
||||
static formatUsageDie(value) {
|
||||
return value ? `Δ${value}` : "—";
|
||||
}
|
||||
|
||||
static getDefaultItemIcon(type) {
|
||||
return this.defaultItemIcons[type] ?? this.defaultItemIcons.other;
|
||||
}
|
||||
|
||||
static getCurrentSceneId() {
|
||||
return canvas?.scene?.id ?? game.scenes?.current?.id ?? "global";
|
||||
}
|
||||
|
||||
static getSceneDamageTargets() {
|
||||
const scene = canvas?.scene ?? game.scenes?.current;
|
||||
const tokens = scene?.tokens?.contents ?? [];
|
||||
|
||||
return tokens
|
||||
.map((token) => {
|
||||
const actor = token.actor;
|
||||
if (!actor || !["employe", "pnj"].includes(actor.type)) return null;
|
||||
|
||||
const tokenName = token.name || actor.name;
|
||||
const actorName = actor.name || tokenName;
|
||||
const label = tokenName === actorName ? tokenName : `${tokenName} (${actorName})`;
|
||||
|
||||
return {
|
||||
tokenId: token.id,
|
||||
tokenUuid: token.uuid,
|
||||
actorUuid: actor.uuid,
|
||||
label
|
||||
};
|
||||
})
|
||||
.filter(Boolean)
|
||||
.sort((a, b) => a.label.localeCompare(b.label, "fr", { sensitivity: "base" }));
|
||||
}
|
||||
|
||||
static getMagicResourceContext(actor) {
|
||||
const rank = Number(actor.system.anciennete?.rang ?? actor.system.sante?.dv ?? 0);
|
||||
const focusDelta = Number(actor.system.magie?.focus?.delta ?? 0);
|
||||
const focusResult = Number(actor.system.magie?.focus?.resultat ?? 0);
|
||||
const focusSceneId = actor.system.magie?.focus?.sceneId ?? "";
|
||||
const activeFocus = focusSceneId === this.getCurrentSceneId() ? focusResult : 0;
|
||||
const chaosDelta = Number(actor.system.magie?.chaos?.delta ?? 12);
|
||||
|
||||
return {
|
||||
rank,
|
||||
focusDelta,
|
||||
focusLabel: this.formatUsageDie(focusDelta),
|
||||
focusSceneId,
|
||||
focusStoredResult: focusResult,
|
||||
focusActiveValue: activeFocus,
|
||||
focusIsActive: activeFocus > 0,
|
||||
focusDisplay: activeFocus > 0 ? `${activeFocus} (${this.formatUsageDie(focusDelta)})` : "—",
|
||||
chaosDelta,
|
||||
chaosLabel: this.formatUsageDie(chaosDelta),
|
||||
chaosAvailable: chaosDelta >= 4
|
||||
};
|
||||
}
|
||||
|
||||
static getFavorLabel(key) {
|
||||
return DONJON_ET_CIE.favorDepartments[key] ?? key;
|
||||
}
|
||||
|
||||
static getFavorEntries(system) {
|
||||
const favors = system.faveurs ?? {};
|
||||
return Object.entries(DONJON_ET_CIE.favorDepartments).map(([key, label]) => {
|
||||
const delta = Number(favors[key]?.delta ?? 0);
|
||||
return {
|
||||
key,
|
||||
label,
|
||||
delta,
|
||||
deltaLabel: this.formatUsageDie(delta),
|
||||
hasFavor: delta > 0
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
static getAvailableFavorOptions(actor) {
|
||||
return this.getFavorEntries(actor.system)
|
||||
.filter((entry) => entry.hasFavor)
|
||||
.map((entry) => ({ value: entry.key, label: `${entry.label} (${entry.deltaLabel})` }));
|
||||
}
|
||||
|
||||
static getChaosTableEntries() {
|
||||
return Object.entries(DONJON_ET_CIE.chaosTable)
|
||||
.map(([value, entry]) => ({ value: Number(value), ...entry }))
|
||||
.sort((a, b) => a.value - b.value);
|
||||
}
|
||||
|
||||
static degradeUsageDie(value) {
|
||||
const sequence = [12, 10, 8, 6, 4];
|
||||
const index = sequence.indexOf(Number(value));
|
||||
if (index === -1) return 0;
|
||||
return sequence[index + 1] ?? 0;
|
||||
}
|
||||
|
||||
static sortByName(documents) {
|
||||
return [...documents].sort((a, b) => a.name.localeCompare(b.name, "fr", { sensitivity: "base" }));
|
||||
}
|
||||
|
||||
static getWeaponCharacteristicKey(category) {
|
||||
return category === "distance" ? "dexterite" : "force";
|
||||
}
|
||||
|
||||
static getWeaponCharacteristicLabel(category) {
|
||||
const key = this.getWeaponCharacteristicKey(category);
|
||||
return DONJON_ET_CIE.characteristics[key]?.label ?? key;
|
||||
}
|
||||
|
||||
static enrichItemForSheet(item) {
|
||||
const system = item.system;
|
||||
const delta = Number(system.delta ?? 0);
|
||||
return {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
type: item.type,
|
||||
img: item.img,
|
||||
system,
|
||||
uuid: item.uuid,
|
||||
usageLabel: delta > 0 ? this.formatUsageDie(delta) : null,
|
||||
protectionLabel: item.type === "armure" && Number(system.resultatProtection ?? 0) > 0 ? `Protection ${system.resultatProtection}` : null,
|
||||
weaponCharacteristicLabel: item.type === "arme" ? this.getWeaponCharacteristicLabel(system.categorie) : null,
|
||||
canRoll: ["arme", "sortilege"].includes(item.type),
|
||||
canUse: delta > 0,
|
||||
canRollDamage: Boolean(system.degats),
|
||||
rollAction: item.type === "sortilege" ? "rollSpell" : "rollWeapon",
|
||||
damageAction: "rollDamage",
|
||||
isEquipped: Boolean(system.equipee)
|
||||
};
|
||||
}
|
||||
|
||||
static buildActorSections(actor) {
|
||||
return Object.entries(DONJON_ET_CIE.actorSections).map(([key, metadata]) => {
|
||||
const types = DONJON_ET_CIE.sectionTypes[key];
|
||||
const items = this.sortByName(actor.items.filter((item) => types.includes(item.type))).map((item) => this.enrichItemForSheet(item));
|
||||
return {
|
||||
key,
|
||||
label: metadata.label,
|
||||
createType: metadata.createType,
|
||||
items
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user