fix: aligner le JS avec l'API Foundry v14

- effects.mjs: remove e._getSourceName() (removed in v14, now a getter)
- fight.mjs: convert VermineCombatTracker from AppV1 (get template/getData)
  to AppV2 PARTS + _prepareContext/_prepareTurnContext
- fight.mjs: VermineCombat.rollInitiative v14 options-object signature
- hooks.mjs: renderPause -> renderGamePause; getSceneControlButtons now
  uses controls.tokens and tools record (v14 names/structure)
- roll.mjs: ChatMessage.create uses rolls array (v14 removed 'roll' key)
- item.mjs: getRollData returns system when no actor (v14 expects object)
- vermine2047.mjs: correct unregisterSheet API for ActorSheetV2
- base-item-sheet.mjs: call super._onRender
This commit is contained in:
2026-08-01 21:33:38 +02:00
parent 8916600bf6
commit df852f17d1
7 changed files with 72 additions and 24 deletions
@@ -76,6 +76,7 @@ export class VermineBaseItemSheet extends HandlebarsApplicationMixin(foundry.app
// ── Rendu ─────────────────────────────────────────────────────────── // ── Rendu ───────────────────────────────────────────────────────────
_onRender(context, options) { _onRender(context, options) {
super._onRender(context, options);
this.#dragDrop.forEach(d => d.bind(this.element)) this.#dragDrop.forEach(d => d.bind(this.element))
} }
+1 -1
View File
@@ -54,7 +54,7 @@ export default class VermineItem extends Item {
*/ */
getRollData() { getRollData() {
// If present, return the actor's roll data. // If present, return the actor's roll data.
if (!this.actor) return null; if (!this.actor) return this.system;
const rollData = this.actor.getRollData(); const rollData = this.actor.getRollData();
// Grab the item's system data as well. // Grab the item's system data as well.
rollData.item = foundry.utils.deepClone(this.system); rollData.item = foundry.utils.deepClone(this.system);
-1
View File
@@ -54,7 +54,6 @@ export function prepareActiveEffectCategories(effects) {
// Iterate over active effects, classifying them into categories // Iterate over active effects, classifying them into categories
for ( let e of effects ) { for ( let e of effects ) {
e._getSourceName(); // Trigger a lookup for the source name
if ( e.disabled ) categories.inactive.effects.push(e); if ( e.disabled ) categories.inactive.effects.push(e);
else if ( e.isTemporary ) categories.temporary.effects.push(e); else if ( e.isTemporary ) categories.temporary.effects.push(e);
else categories.passive.effects.push(e); else categories.passive.effects.push(e);
+63 -14
View File
@@ -184,10 +184,9 @@ export class VermineCombat extends Combat {
// encounter check // encounter check
} }
async rollInitiative(ids, formula = undefined, messageOptions = {}) { async rollInitiative(ids, {formula=null, updateTurn=true, messageMode, messageOptions={}}={}) {
// roll initiative // roll initiative
return super.rollInitiative(ids, formula, messageOptions) return super.rollInitiative(ids, {formula, updateTurn, messageMode, messageOptions});
} }
nextRound() { nextRound() {
@@ -224,19 +223,69 @@ export class VermineCombat extends Combat {
export class VermineCombatTracker extends foundry.applications.sidebar.tabs.CombatTracker { export class VermineCombatTracker extends foundry.applications.sidebar.tabs.CombatTracker {
get template() { /** @override */
return "systems/vermine2047/templates/combat-tracker.hbs"; static PARTS = {
main: {
template: "systems/vermine2047/templates/combat-tracker.hbs",
root: true
}
};
/** @override */
async _prepareContext(options) {
const context = await super._prepareContext(options);
context.user = game.user;
const combat = this.viewed;
const hasCombat = combat !== null;
const combats = this.combats;
const currentIdx = combats.indexOf(combat);
const isPlayerTurn = combat?.combatant?.players?.includes(game.user);
const canControl = combat?.turn && combat.turn.between(1, combat.turns.length - 2)
? combat.canUserModify(game.user, "update", { turn: 0 })
: combat?.canUserModify(game.user, "update", { round: 0 });
Object.assign(context, {
combat,
hasCombat,
combatCount: combats.length,
currentIndex: currentIdx + 1,
previousId: combats[currentIdx - 1]?.id,
nextId: combats[currentIdx + 1]?.id,
round: combat?.round,
control: isPlayerTurn && canControl,
linked: combat?.scene !== null,
cssClass: combats.length > 7 ? "cycle" : combats.length ? "tabbed" : "",
cssId: "combat",
tabName: "combat",
labels: {
scope: game.i18n.localize(`COMBAT.${combat?.scene ? "Linked" : "Unlinked"}`)
},
turns: []
});
if ( combat ) {
for ( const [i, combatant] of combat.turns.entries() ) {
if ( !combatant.visible ) continue;
context.turns.push(await this._prepareTurnContext(combat, combatant, i));
}
}
return context;
} }
async getData(options) { /** @override */
const context = await super.getData(options); async _prepareTurnContext(combat, combatant, index) {
const turn = await super._prepareTurnContext(combat, combatant, index);
if (!context.hasCombat) { const actor = combatant.actor;
return context; turn.attitude = combatant.getFlag("world", "attitude") || "active";
} turn.isPlayer = actor?.hasPlayerOwner ?? false;
turn.isNpc = !!actor && !actor.hasPlayerOwner;
turn.owner = combatant.isOwner;
return context; turn.defeated = combatant.isDefeated;
turn.hasRolled = combatant.initiative !== null;
turn.hasResource = combatant.resource !== null && combatant.resource !== undefined;
turn.effects = (turn.effects?.icons ?? []).map(e => e.img);
return turn;
} }
_onRender(context, options) { _onRender(context, options) {
+5 -5
View File
@@ -69,8 +69,8 @@ export const registerHooks = function () {
}); });
// changement de la pause // changement de la pause
Hooks.on("renderPause", async function () { Hooks.on("renderGamePause", async function (element) {
const pauseEl = document.getElementById("pause"); const pauseEl = element ?? document.getElementById("pause");
if (!pauseEl || pauseEl.className !== "paused") return; if (!pauseEl || pauseEl.className !== "paused") return;
pauseEl.querySelectorAll("img").forEach(img => { pauseEl.querySelectorAll("img").forEach(img => {
img.src = 'systems/vermine2047/assets/images/ui/vermine_pause.webp'; img.src = 'systems/vermine2047/assets/images/ui/vermine_pause.webp';
@@ -94,9 +94,9 @@ export const registerHooks = function () {
}); });
Hooks.on('getSceneControlButtons', async (controls) => { Hooks.on('getSceneControlButtons', async (controls) => {
const tokenControls = controls.token; const tokenControls = controls.tokens;
if (tokenControls && tokenControls.tools) { if (tokenControls && tokenControls.tools) {
tokenControls.tools.push({ tokenControls.tools['dice-roller'] = {
name: 'Dice Roller', name: 'Dice Roller',
title: game.i18n.localize("VERMINE.RollTool"), title: game.i18n.localize("VERMINE.RollTool"),
icon: 'fas fa-dice-d10', icon: 'fas fa-dice-d10',
@@ -104,7 +104,7 @@ export const registerHooks = function () {
onClick() { onClick() {
RollDialog.create().then(d => d.render(true)); RollDialog.create().then(d => d.render(true));
} }
}); };
} }
}); });
+1 -2
View File
@@ -472,10 +472,9 @@ export class VermineUtils {
user: game.user?._id, user: game.user?._id,
speaker: ChatMessage.getSpeaker(), speaker: ChatMessage.getSpeaker(),
content: content, content: content,
roll: roll rolls: [roll]
}; };
const msg = await ChatMessage.create(chatData); const msg = await ChatMessage.create(chatData);
await msg.setFlag('world', 'roll', roll);
return msg; return msg;
} }
+1 -1
View File
@@ -71,7 +71,7 @@ Hooks.once('init', async function () {
// Register sheet application classes (ApplicationV2) // Register sheet application classes (ApplicationV2)
// Unregister core sheets // Unregister core sheets
foundry.applications.sheets.ActorSheetV2?.unregisterSheet?.("core", "Actor", { foundry.documents.collections.Actors.unregisterSheet("core", foundry.applications.sheets.ActorSheetV2, {
types: ["character", "npc", "group", "creature"] types: ["character", "npc", "group", "creature"]
}) })
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1?.sheets?.ItemSheet) foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1?.sheets?.ItemSheet)