From cbeaaeec99720d1765b28b2d812d559eb9825064 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnier Date: Fri, 12 Jun 2026 08:19:42 +0200 Subject: [PATCH] Final fixes and code review checks --- lethal-fantasy.mjs | 68 +++++++------------ module/applications/combat.mjs | 54 ++++----------- .../applications/sheets/base-actor-sheet.mjs | 13 ++-- .../applications/sheets/base-item-sheet.mjs | 6 +- .../applications/sheets/character-sheet.mjs | 33 +++++---- module/applications/sheets/monster-sheet.mjs | 2 +- module/documents/actor.mjs | 4 +- module/documents/d30-roll.mjs | 4 +- module/documents/roll.mjs | 44 ++++++------ module/macros.mjs | 10 +-- module/models/monster.mjs | 6 +- module/models/weapon.mjs | 5 +- module/utils.mjs | 68 ++++++++++--------- 13 files changed, 137 insertions(+), 180 deletions(-) diff --git a/lethal-fantasy.mjs b/lethal-fantasy.mjs index 43a907f..9f277fa 100644 --- a/lethal-fantasy.mjs +++ b/lethal-fantasy.mjs @@ -4,7 +4,6 @@ */ import { SYSTEM } from "./module/config/system.mjs" -globalThis.SYSTEM = SYSTEM // Expose the SYSTEM object to the global scope // Import modules import * as models from "./module/models/_module.mjs" @@ -14,15 +13,24 @@ import * as applications from "./module/applications/_module.mjs" import { LethalFantasyCombatTracker, LethalFantasyCombat } from "./module/applications/combat.mjs" import { Macros } from "./module/macros.mjs" import { setupTextEnrichers } from "./module/enrichers.mjs" -import { default as LethalFantasyUtils } from "./module/utils.mjs" - -export class ClassCounter { static printHello() { console.log("Hello") } static sendJsonPostRequest(e, s) { const t = { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify(s) }; return fetch(e, t).then((e => { if (!e.ok) throw new Error("La requête a échoué avec le statut " + e.status); return e.json() })).catch((e => { throw console.error("Erreur envoi de la requête:", e), e })) } static registerUsageCount(e = game.system.id, s = {}) { if (game.user.isGM) { game.settings.register(e, "world-key", { name: "Unique world key", scope: "world", config: !1, default: "", type: String }); let t = game.settings.get(e, "world-key"); null != t && "" != t && "NONE" != t && "none" != t.toLowerCase() || (t = foundry.utils.randomID(32), game.settings.set(e, "world-key", t)); let a = { name: e, system: game.system.id, worldKey: t, version: game.system.version, language: game.settings.get("core", "language"), remoteAddr: game.data.addresses.remote, nbInstalledModules: game.modules.size, nbActiveModules: game.modules.filter((e => e.active)).length, nbPacks: game.world.packs.size, nbUsers: game.users.size, nbScenes: game.scenes.size, nbActors: game.actors.size, nbPlaylist: game.playlists.size, nbTables: game.tables.size, nbCards: game.cards.size, optionsData: s, foundryVersion: `${game.release.generation}.${game.release.build}` }; this.sendJsonPostRequest("https://www.uberwald.me/fvtt_appcount/count_post.php", a) } } } +import LethalFantasyUtils, { log } from "./module/utils.mjs" Hooks.once("init", function () { + globalThis.SYSTEM = SYSTEM + globalThis.pendingDefenses = new Map() console.info("Lethal Fantasy RPG | Initializing System") console.info(SYSTEM.ASCII) + game.settings.register(game.system.id, "debug", { + name: "Debug logging", + scope: "client", + config: true, + default: false, + type: Boolean, + }) + globalThis.lethalFantasy = game.system + globalThis.log = log game.system.CONST = SYSTEM // Expose the system API @@ -54,12 +62,10 @@ Hooks.once("init", function () { miracle: models.LethalFantasyMiracle } - // Register sheet application classes - foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet) + // Register sheet application classes (V2) foundry.documents.collections.Actors.registerSheet("lethalFantasy", applications.LethalFantasyCharacterSheet, { types: ["character"], makeDefault: true }) foundry.documents.collections.Actors.registerSheet("lethalFantasy", applications.LethalFantasyMonsterSheet, { types: ["monster"], makeDefault: true }) - foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ActorSheet) foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasySkillSheet, { types: ["skill"], makeDefault: true }) foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyGiftSheet, { types: ["gift"], makeDefault: true }) foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyVulnerabilitySheet, { types: ["vulnerability"], makeDefault: true }) @@ -76,14 +82,6 @@ Hooks.once("init", function () { // Dice system configuration CONFIG.Dice.rolls.push(documents.LethalFantasyRoll) - game.settings.register("lethalFantasy", "worldKey", { - name: "Unique world key", - scope: "world", - config: false, - type: String, - default: "", - }) - // Activate socket handler game.socket.on(`system.${SYSTEM.id}`, LethalFantasyUtils.handleSocketEvent) @@ -113,10 +111,6 @@ Hooks.once("ready", function () { // Initialiser la table des résultats D30 documents.D30Roll.initialize() - if (!SYSTEM.DEV_MODE) { - registerWorldCount("lethalFantasy") - } - // Saignement piloté par le combat tracker _registerBleedingHooks() @@ -333,7 +327,7 @@ Hooks.on("renderChatMessageHTML", (message, html, data) => { ? (rollTargetData?._id || rollTargetData?.id) : (rollTargetData?.weapon?.id || rollTargetData?.weapon?._id) const attackRollKey = rollTargetData?.rollKey - console.log(`[LF] request-defense-btn | attackRollType=${attackRollType} defender=${defenderName} defenderType=${combatant.actor?.type}`) + log(`[LF] request-defense-btn | attackRollType=${attackRollType} defender=${defenderName} defenderType=${combatant.actor?.type}`) const attackD30result = message.rolls[0]?.options?.D30result || null const attackD30message = message.rolls[0]?.options?.D30message || null const attackDiceResults = message.rolls[0]?.options?.diceResults || null @@ -552,7 +546,7 @@ Hooks.on("preCreateChatMessage", (message) => { [`flags.${SYSTEM.id}.attackData`]: game.lethalFantasy.nextDefenseData }) - console.log("Added attack data to defense message:", game.lethalFantasy.nextDefenseData) + log("Added attack data to defense message:", game.lethalFantasy.nextDefenseData) // Nettoyer delete game.lethalFantasy.nextDefenseData @@ -563,7 +557,7 @@ Hooks.on("preCreateChatMessage", (message) => { Hooks.on("createChatMessage", async (message) => { const rollType = message.rolls[0]?.options?.rollType - console.log("Defense hook checking message, rollType:", rollType) + log("Defense hook checking message, rollType:", rollType) // Vérifier si c'est un message de défense if (rollType !== "weapon-defense" && rollType !== "monster-defense" && rollType !== "save") return @@ -571,10 +565,10 @@ Hooks.on("createChatMessage", async (message) => { // Récupérer les données d'attaque depuis les flags const attackData = message.flags?.[SYSTEM.id]?.attackData - console.log("Defense message confirmed, attackData:", attackData) + log("Defense message confirmed, attackData:", attackData) if (!attackData) { - console.log("No attack data found in message flags") + log("No attack data found in message flags") return } @@ -596,7 +590,7 @@ Hooks.on("createChatMessage", async (message) => { let defenseRoll = message.rolls[0]?.options?.rollTotal || message.rolls[0]?.total || 0 const defenseD30message = message.rolls[0]?.options?.D30message || null - console.log("Processing defense:", { attackRoll, defenseRoll, attackerId, defenderId }) + log("Processing defense:", { attackRoll, defenseRoll, attackerId, defenderId }) // Attendre l'animation 3D if (game?.dice3d) { @@ -1058,7 +1052,7 @@ Hooks.on("createChatMessage", async (message) => { )) if (shouldCreateMessage) { - console.log("Creating comparison message", { attackerHandledBonus, defenderHandledBonus, isDefenderOwner: defender.isOwner }) + log("Creating comparison message", { attackerHandledBonus, defenderHandledBonus, isDefenderOwner: defender.isOwner }) await LethalFantasyUtils.compareAttackDefense({ attackerName, @@ -1080,7 +1074,7 @@ Hooks.on("createChatMessage", async (message) => { attackD30message }) } else { - console.log("Skipping message creation", { attackerHandledBonus, defenderHandledBonus }) + log("Skipping message creation", { attackerHandledBonus, defenderHandledBonus }) } }) @@ -1161,7 +1155,7 @@ Hooks.on("createChatMessage", async (message) => { const defenderId = message.rolls[0]?.options?.defenderId const isDamage = message.rolls[0]?.options?.rollData?.isDamage - console.log("Auto-damage hook:", { defenderId, isDamage, rollType: message.rolls[0]?.options?.rollType }) + log("Auto-damage hook:", { defenderId, isDamage, rollType: message.rolls[0]?.options?.rollType }) if (!defenderId || !isDamage) return @@ -1186,11 +1180,11 @@ Hooks.on("createChatMessage", async (message) => { } if (!shouldApplyDamage) { - console.log("Auto-damage hook: Not responsible for applying damage, skipping") + log("Auto-damage hook: Not responsible for applying damage, skipping") return } - console.log("Auto-damage hook: Applying damage as responsible user") + log("Auto-damage hook: Applying damage as responsible user") // Attendre l'animation 3D avant d'appliquer les dégâts if (game?.dice3d) { @@ -1401,16 +1395,4 @@ Hooks.on("hotbarDrop", (bar, data, slot) => { */ Hooks.on("renderChatLog", (_chatLog, html) => applications.injectDiceTray(_chatLog, html)) -/** - * Register world usage statistics - * @param {string} registerKey - */ -async function registerWorldCount(registerKey) { - if (game.user.isGM) { - try { - ClassCounter.registerUsageCount(game.system.id, {}) - } catch { - console.log("No usage log ") - } - } -} + diff --git a/module/applications/combat.mjs b/module/applications/combat.mjs index 632088f..ea8aa3a 100644 --- a/module/applications/combat.mjs +++ b/module/applications/combat.mjs @@ -24,30 +24,29 @@ export class LethalFantasyCombatTracker extends foundry.applications.sidebar.tab async _prepareContext(options) { let data = await super._prepareContext(options); - console?.log("Combat Tracker Data", data); + log("Combat Tracker Data", data); /*for (let u of data.turns) { let c = game.combat.combatants.get(u.id); u.progressionCount = c.system.progressionCount u.isMonster = c.actor.type === "monster" } - console.log("Combat Data", data);*/ + log("Combat Data", data);*/ return data; } - static #initiativePlus(ev) { + static async #initiativePlus(ev) { ev.preventDefault(); let cId = ev.target.closest(".combatant").dataset.combatantId; let c = game.combat.combatants.get(cId); - c.update({ 'initiative': c.initiative + 1 }); - console.log("Initiative Plus"); + await c.update({ 'initiative': c.initiative + 1 }); } - static #initiativeMinus(ev) { + static async #initiativeMinus(ev) { ev.preventDefault(); let cId = ev.target.closest(".combatant").dataset.combatantId; let c = game.combat.combatants.get(cId); let newInit = Math.max(c.initiative - 1, 0); - c.update({ 'initiative': newInit }); + await c.update({ 'initiative': newInit }); } /** @@ -58,33 +57,6 @@ export class LethalFantasyCombatTracker extends foundry.applications.sidebar.tab ev.preventDefault(); await game.combat.rollMonsterProgression(); } - - activateListeners(html) { - super.activateListeners(html); - // Display Combat settings - html.find(".initiative-plus").click(ev => { - ev.preventDefault(); - let cId = ev.currentTarget.closest(".combatant").dataset.combatantId; - let c = game.combat.combatants.get(cId); - c.update({ 'initiative': c.initiative + 1 }); - }); - - html.find(".initiative-minus").click(ev => { - ev.preventDefault(); - let cId = ev.currentTarget.closest(".combatant").dataset.combatantId; - let c = game.combat.combatants.get(cId); - c.update({ 'initiative': c.initiative - 1 }); - console.log("Initiative Minus"); - }); - } - - /* -------------------------------------------- */ - static get defaultOptions() { - let path = "systems/fvtt-lethal-fantasy/templates/combat-tracker.hbs"; - return foundry.utils.mergeObject(super.defaultOptions, { - template: path, - }); - } } export class LethalFantasyCombat extends Combat { @@ -94,7 +66,7 @@ export class LethalFantasyCombat extends Combat { * @returns {Combatant[]} */ setupTurns() { - console?.log("Setup Turns...."); + log("Setup Turns...."); this.turns ||= []; // Determine the turn order and the current turn @@ -164,19 +136,19 @@ export class LethalFantasyCombat extends Combat { } } - resetProgression(cId) { + async resetProgression(cId) { let c = this.combatants.get(cId); - c.update({ 'system.progressionCount': 0 }); + await c.update({ 'system.progressionCount': 0 }); } - setCasting(cId) { + async setCasting(cId) { let c = this.combatants.get(cId); - c.setFlag(SYSTEM.id, "casting", true); + await c.setFlag(SYSTEM.id, "casting", true); } - resetCasting(cId) { + async resetCasting(cId) { let c = this.combatants.get(cId); - c.setFlag(SYSTEM.id, "casting", false); + await c.setFlag(SYSTEM.id, "casting", false); } isCasting(cId) { diff --git a/module/applications/sheets/base-actor-sheet.mjs b/module/applications/sheets/base-actor-sheet.mjs index e1f073d..63233f8 100644 --- a/module/applications/sheets/base-actor-sheet.mjs +++ b/module/applications/sheets/base-actor-sheet.mjs @@ -78,7 +78,6 @@ export default class LethalFantasyActorSheet extends HandlebarsApplicationMixin( /** @override */ _onRender(context, options) { this.#dragDrop.forEach((d) => d.bind(this.element)) - // Add listeners to rollable elements const rollables = this.element.querySelectorAll(".rollable") rollables.forEach((d) => d.addEventListener("click", this._onRoll.bind(this))) } @@ -234,12 +233,12 @@ export default class LethalFantasyActorSheet extends HandlebarsApplicationMixin( const attr = target.dataset.edit const current = foundry.utils.getProperty(this.document, attr) const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {} - const fp = new FilePicker({ + const fp = new foundry.applications.ux.FilePicker.implementation({ current, type: "image", redirectToRoot: img ? [img] : [], - callback: (path) => { - this.document.update({ [attr]: path }) + callback: async (path) => { + await this.document.update({ [attr]: path }) }, top: this.position.top + 40, left: this.position.left + 10, @@ -261,7 +260,7 @@ export default class LethalFantasyActorSheet extends HandlebarsApplicationMixin( item = await fromUuid(uuid) if (!item) item = this.document.items.get(id) if (!item) return - item.sheet.render(true) + item.sheet.render({ force: true }) } /** @@ -284,8 +283,8 @@ export default class LethalFantasyActorSheet extends HandlebarsApplicationMixin( * @private * @static */ - static #onCreateSpell(event, target) { - const item = this.document.createEmbeddedDocuments("Item", [{ name: "Nouveau sortilège", type: "spell" }]) + static async #onCreateSpell(event, target) { + await this.document.createEmbeddedDocuments("Item", [{ name: "Nouveau sortilège", type: "spell" }]) } // #endregion diff --git a/module/applications/sheets/base-item-sheet.mjs b/module/applications/sheets/base-item-sheet.mjs index 45bbb20..5db57bc 100644 --- a/module/applications/sheets/base-item-sheet.mjs +++ b/module/applications/sheets/base-item-sheet.mjs @@ -177,12 +177,12 @@ export default class LethalFantasyItemSheet extends HandlebarsApplicationMixin(f const attr = target.dataset.edit const current = foundry.utils.getProperty(this.document, attr) const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {} - const fp = new FilePicker({ + const fp = new foundry.applications.ux.FilePicker.implementation({ current, type: "image", redirectToRoot: img ? [img] : [], - callback: (path) => { - this.document.update({ [attr]: path }) + callback: async (path) => { + await this.document.update({ [attr]: path }) }, top: this.position.top + 40, left: this.position.left + 10, diff --git a/module/applications/sheets/character-sheet.mjs b/module/applications/sheets/character-sheet.mjs index e6dfad9..c9e84a3 100644 --- a/module/applications/sheets/character-sheet.mjs +++ b/module/applications/sheets/character-sheet.mjs @@ -180,44 +180,44 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet await this.document.system.rollInitiative() } - static #onArmorHitPointsPlus(event, target) { + static async #onArmorHitPointsPlus(event, target) { let armorHP = this.actor.system.combat.armorHitPoints armorHP += 1 - this.actor.update({ "system.combat.armorHitPoints": armorHP }) + await this.actor.update({ "system.combat.armorHitPoints": armorHP }) } - static #onArmorHitPointsMinus(event, target) { + static async #onArmorHitPointsMinus(event, target) { let armorHP = this.actor.system.combat.armorHitPoints armorHP -= 1 - this.actor.update({ "system.combat.armorHitPoints": Math.max(armorHP, 0) }) + await this.actor.update({ "system.combat.armorHitPoints": Math.max(armorHP, 0) }) } - static #onDivinityPointsPlus(event, target) { + static async #onDivinityPointsPlus(event, target) { let points = this.actor.system.divinityPoints.value points += 1 points = Math.min(points, this.actor.system.divinityPoints.max) - this.actor.update({ "system.divinityPoints.value": points }) + await this.actor.update({ "system.divinityPoints.value": points }) } - static #onDivinityPointsMinus(event, target) { + static async #onDivinityPointsMinus(event, target) { let points = this.actor.system.divinityPoints.value points -= 1 points = Math.max(points, 0) - this.actor.update({ "system.divinityPoints.value": points }) + await this.actor.update({ "system.divinityPoints.value": points }) } - static #onAetherPointsPlus(event, target) { + static async #onAetherPointsPlus(event, target) { let points = this.actor.system.aetherPoints.value points += 1 points = Math.min(points, this.actor.system.aetherPoints.max) - this.actor.update({ "system.aetherPoints.value": points }) + await this.actor.update({ "system.aetherPoints.value": points }) } - static #onAetherPointsMinus(event, target) { + static async #onAetherPointsMinus(event, target) { let points = this.actor.system.aetherPoints.value points -= 1 points = Math.max(points, 0) - this.actor.update({ "system.aetherPoints.value": points }) + await this.actor.update({ "system.aetherPoints.value": points }) } /** @@ -293,10 +293,9 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet } _onRender(context, options) { - // Inputs with class `item-quantity` const woundDescription = this.element.querySelectorAll('.wound-data') for (const input of woundDescription) { - input.addEventListener("change", (e) => { + input.addEventListener("change", async (e) => { e.preventDefault(); e.stopImmediatePropagation(); const newValue = e.currentTarget.value @@ -304,11 +303,11 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet const fieldName = e.currentTarget.dataset.name let tab = foundry.utils.duplicate(this.actor.system.hp.wounds) tab[index][fieldName] = newValue - console.log(tab, index, fieldName, newValue) - this.actor.update({ "system.hp.wounds": tab }); + log(tab, index, fieldName, newValue) + await this.actor.update({ "system.hp.wounds": tab }); }) } - super._onRender(); + super._onRender(context, options); } diff --git a/module/applications/sheets/monster-sheet.mjs b/module/applications/sheets/monster-sheet.mjs index 5cce484..9fac97e 100644 --- a/module/applications/sheets/monster-sheet.mjs +++ b/module/applications/sheets/monster-sheet.mjs @@ -91,7 +91,7 @@ export default class LethalFantasyMonsterSheet extends LethalFantasyActorSheet { */ async _onDrop(event) { if (!this.isEditable || !this.isEditMode) return - const data = TextEditor.getDragEventData(event) + const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event) // Handle different data types switch (data.type) { diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 6891427..877c9c0 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -72,7 +72,7 @@ export default class LethalFantasyActor extends Actor { /* *************************************************/ async applyDamage(hpLoss) { let hp = this.system.hp.value + hpLoss - this.update({ "system.hp.value": hp }) + await this.update({ "system.hp.value": hp }) } /* *************************************************/ @@ -163,7 +163,7 @@ export default class LethalFantasyActor extends Actor { /* *************************************************/ async prepareRoll(rollType, rollKey, rollDice, defenderId, defenderTokenId, extraShieldDr = 0, d30Effects = {}) { - console.log("Preparing roll", rollType, rollKey, rollDice, defenderId) + log("Preparing roll", rollType, rollKey, rollDice, defenderId) let rollTarget switch (rollType) { case "granted": diff --git a/module/documents/d30-roll.mjs b/module/documents/d30-roll.mjs index 66dff5a..ab3d08f 100644 --- a/module/documents/d30-roll.mjs +++ b/module/documents/d30-roll.mjs @@ -1,3 +1,5 @@ +import { log } from "../utils.mjs" + /** * Classe pour gérer les résultats du D30 dans Lethal Fantasy */ @@ -41,7 +43,7 @@ export default class D30Roll { this.resultsTable = data.d30_dice_results this.definitions = data.definitions - console.log("D30Roll | D30 results table loaded successfully") + log("D30Roll | D30 results table loaded successfully") } catch (error) { console.error("D30Roll | Error loading D30 table:", error) ui.notifications.error("Unable to load D30 results table") diff --git a/module/documents/roll.mjs b/module/documents/roll.mjs index e1056e3..bd5d8dc 100644 --- a/module/documents/roll.mjs +++ b/module/documents/roll.mjs @@ -392,7 +392,7 @@ export default class LethalFantasyRoll extends Roll { { label: label, callback: (event, button, dialog) => { - console.log("Roll context", event, button, dialog) + log("Roll context", event, button, dialog) let position = dialog?.position game.user.setFlag(SYSTEM.id, "roll-dialog-pos", foundry.utils.duplicate(position)) const output = Array.from(button.form.elements).reduce((obj, input) => { @@ -435,7 +435,7 @@ export default class LethalFantasyRoll extends Roll { // If the user cancels the dialog, exit if (rollContext === null) return - console.log("rollContext", rollContext, hasGrantedDice) + log("rollContext", rollContext, hasGrantedDice) rollContext.saveSpell = saveSpell // Update fucking flag let fullModifier = 0 @@ -552,7 +552,7 @@ export default class LethalFantasyRoll extends Roll { if (rollContext.favor === "favor") { rollFavor = new this(baseFormula, options.data, rollData) await rollFavor.evaluate() - console.log("Rolling with favor", rollFavor) + log("Rolling with favor", rollFavor) if (game?.dice3d) { game.dice3d.showForRoll(rollFavor, game.user, true) } @@ -861,12 +861,12 @@ export default class LethalFantasyRoll extends Roll { rejectClose: false // Click on Close button will not launch an error }) - console.log("RollContext", dialogContext, rollContext) + log("RollContext", dialogContext, rollContext) // If action is cancelled, exit if (rollContext === null || rollContext === "cancel") { await combatant.setFlag(SYSTEM.id, "currentAction", "") let message = `${combatant.name} : Other action, progression reset` - ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) + await ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) return } @@ -924,7 +924,7 @@ export default class LethalFantasyRoll extends Roll { // Set the flag on the combatant await combatant.setFlag(SYSTEM.id, "currentAction", actionItem) let message = `${combatant.name} action : ${selectedItem.name}, start rolling progression dice or casting time` - ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) + await ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) rollContext = (actionItem.type === "weapon") ? "rollProgressionDice" : "rollLethargyDice" // Set the roll context to rollProgressionDice currentAction = actionItem } @@ -935,14 +935,14 @@ export default class LethalFantasyRoll extends Roll { let time = currentAction.type === "spell" ? currentAction.system.castingTime : currentAction.system.prayerTime if (currentAction.castingTime < time) { let message = `Casting time : ${currentAction.name}, count : ${currentAction.castingTime}/${time}` - ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) + await ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) currentAction.castingTime += 1 await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction)) return } else { // Last counting second — announce ready and transition immediately (no extra second consumed) let message = `Casting time : ${currentAction.name}, count : ${time}/${time} — ready to cast next second !` - ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) + await ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) currentAction.castingTime = 1 currentAction.spellStatus = "toBeCasted" await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction)) @@ -982,7 +982,7 @@ export default class LethalFantasyRoll extends Roll { isLethargy: true } ) - ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) + await ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) // Update the combatant progression count await combatant.setFlag(SYSTEM.id, "currentAction", "") // Display the action selection window again @@ -1002,7 +1002,7 @@ export default class LethalFantasyRoll extends Roll { isLethargy: true } ) - ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) + await ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) } } } @@ -1014,18 +1014,18 @@ export default class LethalFantasyRoll extends Roll { let split = toSplit.split("+") currentAction.rangedLoad = Number(split[0]) || 0 formula = split[1] - console.log("Ranged Mode", currentAction.rangedMode, currentAction.rangedLoad, formula) + log("Ranged Mode", currentAction.rangedMode, currentAction.rangedLoad, formula) } // Range weapon loading if (!currentAction.weaponLoaded && currentAction.rangedLoad) { if (currentAction.progressionCount < currentAction.rangedLoad) { let message = `Ranged weapon ${currentAction.name} is loading, loading count : ${currentAction.progressionCount}/${currentAction.rangedLoad}` - ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) + await ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) currentAction.progressionCount += 1 await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction)) } else { let message = `Ranged weapon ${currentAction.name} is loaded !` - ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) + await ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) currentAction.weaponLoaded = true currentAction.progressionCount = 1 await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction)) @@ -1057,13 +1057,13 @@ export default class LethalFantasyRoll extends Roll { rollResult: roll.total } ) - ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) + await ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) await combatant.setFlag(SYSTEM.id, "currentAction", "") combatant.actor.prepareRoll(currentAction.type === "weapon" ? "weapon-attack" : "spell-attack", currentAction._id) } else { // Notify that the player cannot act now with a chat message currentAction.progressionCount += 1 - combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction)) + await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction)) const messageContent = await foundry.applications.handlebars.renderTemplate( "systems/fvtt-lethal-fantasy/templates/progression-message.hbs", { @@ -1074,7 +1074,7 @@ export default class LethalFantasyRoll extends Roll { progressionCount: currentAction.progressionCount } ) - ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) + await ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) }) } } } @@ -1130,7 +1130,7 @@ export default class LethalFantasyRoll extends Roll { // If the user cancels the dialog, exit if (rollContext === null) return - console.log("RollContext", rollContext) + log("RollContext", rollContext) // Add disfavor/favor option if point blank range if (rollContext.range === "pointblank") { rollContext.movement = rollContext.movement.replace("kh", "") @@ -1426,7 +1426,7 @@ export default class LethalFantasyRoll extends Roll { /** @override */ async render(chatOptions = {}) { let chatData = await this._getChatCardData(chatOptions.isPrivate) - console.log("ChatData", chatData) + log("ChatData", chatData) return await foundry.applications.handlebars.renderTemplate(this.constructor.CHAT_TEMPLATE, chatData) } @@ -1464,15 +1464,15 @@ export default class LethalFantasyRoll extends Roll { // Récupérer les informations de l'arme pour les attaques réussies let weaponDamageOptions = null - console.log("Roll type:", this.type, "rollTarget:", this.rollTarget, "Has weapon:", !!this.rollTarget?.weapon) + log("Roll type:", this.type, "rollTarget:", this.rollTarget, "Has weapon:", !!this.rollTarget?.weapon) if (this.type === "weapon-attack" && this.rollTarget?.weapon) { const weapon = this.rollTarget.weapon weaponDamageOptions = { - weaponId: weapon._id || weapon.id, + weaponId: weapon.id, weaponName: weapon.name, damageM: weapon.system?.damage?.damageM } - console.log("Weapon damage options:", weaponDamageOptions) + log("Weapon damage options:", weaponDamageOptions) } else if (this.type === "monster-attack" && this.rollTarget) { weaponDamageOptions = { weaponId: this.rollTarget.rollKey, @@ -1481,7 +1481,7 @@ export default class LethalFantasyRoll extends Roll { damageModifier: this.rollTarget.damageModifier, isMonster: true } - console.log("Monster damage options:", weaponDamageOptions) + log("Monster damage options:", weaponDamageOptions) } const cardData = { diff --git a/module/macros.mjs b/module/macros.mjs index 1e8f9dc..8e6b145 100644 --- a/module/macros.mjs +++ b/module/macros.mjs @@ -32,20 +32,20 @@ export class Macros { dropData.rollType === "save" ? `game.actors.get('${dropData.actorId}').system.roll('${dropData.rollType}', '${dropData.rollTarget}', '=');` : `game.actors.get('${dropData.actorId}').system.roll('${dropData.rollType}', '${dropData.rollTarget}');` - const rollName = `${game.i18n.localize("TENEBRIS.Label.jet")} ${game.i18n.localize(`TENEBRIS.Manager.${dropData.rollTarget}`)}` + const rollName = `${game.i18n.localize("LETHALFANTASY.Label.jet")} ${game.i18n.localize(`LETHALFANTASY.Label.${dropData.rollTarget}`)}` this.createMacro(slot, rollName, rollCommand, "icons/svg/d20-grey.svg") break case "rollDamage": const weapon = game.actors.get(dropData.actorId).items.get(dropData.rollTarget) const rollDamageCommand = `game.actors.get('${dropData.actorId}').system.roll('${dropData.rollType}', '${dropData.rollTarget}');` - const rollDamageName = `${game.i18n.localize("TENEBRIS.Label.jet")} ${weapon.name}` + const rollDamageName = `${game.i18n.localize("LETHALFANTASY.Label.jet")} ${weapon.name}` this.createMacro(slot, rollDamageName, rollDamageCommand, weapon.img) break case "rollAttack": const rollAttackCommand = `game.actors.get('${dropData.actorId}').system.roll('${dropData.rollValue}', '${dropData.rollTarget}');` - const rollAttackName = `${game.i18n.localize("TENEBRIS.Label.jet")} ${dropData.rollTarget}` + const rollAttackName = `${game.i18n.localize("LETHALFANTASY.Label.jet")} ${dropData.rollTarget}` this.createMacro(slot, rollAttackName, rollAttackCommand, "icons/svg/d20-grey.svg") break @@ -57,7 +57,7 @@ export class Macros { /** * Create a macro - * All macros are flaged with a tenebris.macro flag at true + * All macros are flaged with a lethalFantasy.macro flag at true * @param {*} slot * @param {*} name * @param {*} command @@ -72,7 +72,7 @@ export class Macros { type: "script", img: img, command: command, - flags: { "tenebris.macro": true }, + flags: { "lethalFantasy.macro": true }, }, { displaySheet: false }, ) diff --git a/module/models/monster.mjs b/module/models/monster.mjs index 3103acc..5b1de81 100644 --- a/module/models/monster.mjs +++ b/module/models/monster.mjs @@ -383,7 +383,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel rollResult: roll.total } ) - ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: this.parent }) }) + await ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: this.parent }) }) let token = combatant?.token this.prepareMonsterRoll("monster-attack", key, undefined, token?.id) if (token?.object) { @@ -407,7 +407,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel rollResult: roll.total } ) - ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: this.parent }) }) + await ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: this.parent }) }) let token = combatant?.token this.prepareMonsterRoll("monster-attack-hth", key, undefined, token?.id) if (token?.object) { @@ -426,7 +426,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel rollResult: roll.total } ) - ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: this.parent }) }) + await ChatMessage.create({ content: messageContent, speaker: ChatMessage.getSpeaker({ actor: this.parent }) }) } } diff --git a/module/models/weapon.mjs b/module/models/weapon.mjs index a7cff9e..2ec2ca5 100644 --- a/module/models/weapon.mjs +++ b/module/models/weapon.mjs @@ -1,6 +1,7 @@ import { SYSTEM } from "../config/system.mjs" +import { WEAPON_TYPE } from "../config/weapon.mjs" -export default class LethalFantasySkill extends foundry.abstract.TypeDataModel { +export default class LethalFantasyWeapon extends foundry.abstract.TypeDataModel { static defineSchema() { const fields = foundry.data.fields const schema = {} @@ -62,7 +63,7 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel { static LOCALIZATION_PREFIXES = ["LETHALFANTASY.Weapon"] get weaponCategory() { - return game.i18n.localize(CATEGORY[this.weaponType].label) + return game.i18n.localize(WEAPON_TYPE[this.weaponType] || this.weaponType) } } diff --git a/module/utils.mjs b/module/utils.mjs index e05e9f6..2d6e60f 100644 --- a/module/utils.mjs +++ b/module/utils.mjs @@ -1,8 +1,9 @@ import { SYSTEM } from "./config/system.mjs" -// Map temporaire pour stocker les données d'attaque en attente de défense -if (!globalThis.pendingDefenses) { - globalThis.pendingDefenses = new Map() +export function log(...args) { + if (game?.settings?.get(game.system.id, "debug")) { + console.log(...args) + } } export default class LethalFantasyUtils { @@ -28,6 +29,7 @@ export default class LethalFantasyUtils { static setHookListeners() { Hooks.on('renderTokenHUD', async (hud, html, token) => { + if (html.querySelector(".lethal-hp-loss-hud")) return // HP Loss Button (existing) const lossHPButton = await foundry.applications.handlebars.renderTemplate('systems/fvtt-lethal-fantasy/templates/loss-hp-hud.hbs', {}) $(html).find('div.left').append(lossHPButton); @@ -50,14 +52,14 @@ export default class LethalFantasyUtils { $(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-disabled'); } }) - $(html).find('.loss-hp-hud-click').click((event) => { + $(html).find('.loss-hp-hud-click').click(async (event) => { event.preventDefault(); let hpLoss = event.currentTarget.dataset.hpValue; if (token) { - let tokenFull = canvas.tokens.placeables.find(t => t.id === token._id); - console.log(tokenFull, token) + let tokenFull = canvas.tokens.placeables.find(t => t.id === token.id); + log(tokenFull, token) let actor = tokenFull.actor; - actor.applyDamage(Number(hpLoss)); + await actor.applyDamage(Number(hpLoss)); $(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-active'); $(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-disabled'); $(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-active'); @@ -89,14 +91,14 @@ export default class LethalFantasyUtils { $(html).find('.hp-gain-wrap')[2].classList.add('hp-gain-hud-disabled'); } }) - $(html).find('.gain-hp-hud-click').click((event) => { + $(html).find('.gain-hp-hud-click').click(async (event) => { event.preventDefault(); let hpGain = event.currentTarget.dataset.hpValue; if (token) { - let tokenFull = canvas.tokens.placeables.find(t => t.id === token._id); - console.log(tokenFull, token) + let tokenFull = canvas.tokens.placeables.find(t => t.id === token.id); + log(tokenFull, token) let actor = tokenFull.actor; - actor.applyDamage(Number(hpGain)); // Positive value to add HP + await actor.applyDamage(Number(hpGain)); // Positive value to add HP $(html).find('.hp-gain-wrap')[0].classList.remove('hp-gain-hud-active'); $(html).find('.hp-gain-wrap')[0].classList.add('hp-gain-hud-disabled'); $(html).find('.hp-gain-wrap')[1].classList.remove('hp-gain-hud-active'); @@ -120,16 +122,16 @@ export default class LethalFantasyUtils { wrap.classList.add('luck-grit-hud-disabled'); } }) - $(html).find('.luck-grit-btn').click((event) => { + $(html).find('.luck-grit-btn').click(async (event) => { event.preventDefault(); if (token) { - let tokenFull = canvas.tokens.placeables.find(t => t.id === token._id); + let tokenFull = canvas.tokens.placeables.find(t => t.id === token.id); let actor = tokenFull.actor; const resource = event.currentTarget.dataset.resource; const amount = Number(event.currentTarget.dataset.amount); const current = Number(foundry.utils.getProperty(actor.system, `${resource}.current`)) || 0; const newValue = Math.max(0, current + amount); - actor.update({ [`system.${resource}.current`]: newValue }); + await actor.update({ [`system.${resource}.current`]: newValue }); $(html).find('.luck-grit-wrap')[0].classList.remove('luck-grit-hud-active'); $(html).find('.luck-grit-wrap')[0].classList.add('luck-grit-hud-disabled'); } @@ -138,8 +140,8 @@ export default class LethalFantasyUtils { } /* -------------------------------------------- */ - static handleSocketEvent(msg = {}) { - console.log(`handleSocketEvent !`, msg) + static async handleSocketEvent(msg = {}) { + log(`handleSocketEvent !`, msg) let actor switch (msg.type) { case "applyDamage": @@ -149,18 +151,18 @@ export default class LethalFantasyUtils { ? canvas.tokens?.placeables?.find(t => t.id === msg.tokenId)?.actor : (game.combat?.combatants?.find(c => c.actorId === msg.actorId)?.actor ?? game.actors.get(msg.actorId)) - if (actor) actor.applyDamage(msg.damage) + if (actor) await actor.applyDamage(msg.damage) } break case "rollInitiative": if (msg.userId && msg.userId !== game.user.id) break actor = game.actors.get(msg.actorId) - actor.system.rollInitiative(msg.combatId, msg.combatantId) + await actor.system.rollInitiative(msg.combatId, msg.combatantId) break case "rollProgressionDice": if (msg.userId && msg.userId !== game.user.id) break actor = game.actors.get(msg.actorId) - actor.system.rollProgressionDice(msg.combatId, msg.combatantId, msg.rollProgressionCount) + await actor.system.rollProgressionDice(msg.combatId, msg.combatantId, msg.rollProgressionCount) break case "requestDefense": // Vérifier si le message est destiné à cet utilisateur @@ -184,7 +186,7 @@ export default class LethalFantasyUtils { const slot = wounds.findIndex(w => !w.value && !w.duration) if (slot !== -1) { wounds[slot] = { value: msg.damage, duration: msg.damage, description: "Bleeding" } - actor.update({ "system.hp.wounds": wounds }) + await actor.update({ "system.hp.wounds": wounds }) } } } @@ -497,7 +499,7 @@ export default class LethalFantasyUtils { const isMonster = defender.type === "monster" - console.log(`[LF] showDefenseRequest | attackRollType=${attackRollType} isMonster=${isMonster} defender=${defender?.name}`) + log(`[LF] showDefenseRequest | attackRollType=${attackRollType} isMonster=${isMonster} defender=${defender?.name}`) // Spell/miracle attacks use saving throws instead of weapon defense const isSpellAttack = attackRollType === "spell-attack" || attackRollType === "miracle-attack" @@ -559,9 +561,9 @@ export default class LethalFantasyUtils { defenderTokenId } if (isMonster) { - defender.system.prepareMonsterRoll("save", result) + await defender.system.prepareMonsterRoll("save", result) } else { - defender.prepareRoll("save", result) + await defender.prepareRoll("save", result) } } return @@ -637,7 +639,7 @@ export default class LethalFantasyUtils { isRanged: msg.isRanged } - defender.system.prepareMonsterRoll("monster-defense", result) + await defender.system.prepareMonsterRoll("monster-defense", result) } return } @@ -744,9 +746,9 @@ export default class LethalFantasyUtils { isRanged: msg.isRanged } - console.log("Storing defense data for character:", defender.id) + log("Storing defense data for character:", defender.id) - defender.prepareRoll("weapon-defense", result) + await defender.prepareRoll("weapon-defense", result) } } @@ -1285,7 +1287,7 @@ export default class LethalFantasyUtils { /* -------------------------------------------- */ static async compareAttackDefense(data) { - console.log("compareAttackDefense called with:", data) + log("compareAttackDefense called with:", data) // Compute D30 effects from the attack D30 message directly. // This is more reliable than depending on the caller-provided values, which are @@ -1300,11 +1302,11 @@ export default class LethalFantasyUtils { const outcome = data.outcome || (data.attackRoll > data.defenseRoll ? "hit" : "miss") const isAttackWin = outcome !== "miss" - console.log("isAttackWin:", isAttackWin, "attackRoll:", data.attackRoll, "defenseRoll:", data.defenseRoll) + log("isAttackWin:", isAttackWin, "attackRoll:", data.attackRoll, "defenseRoll:", data.defenseRoll) let damageButton = "" if (isAttackWin && (data.attackWeaponId || data.attackRollKey)) { - console.log("Creating damage button. defenderId:", data.defenderId) + log("Creating damage button. defenderId:", data.defenderId) // Déterminer le type de dégâts à lancer if (data.attackRollType === "weapon-attack") { damageButton = ` @@ -1385,12 +1387,12 @@ export default class LethalFantasyUtils { ` - console.log("Creating combat result message...") + log("Creating combat result message...") await ChatMessage.create({ content: resultMessage, speaker: { alias: "Combat System" } }) - console.log("Combat result message created!") + log("Combat result message created!") } static registerHandlebarsHelpers() { @@ -1527,7 +1529,7 @@ export default class LethalFantasyUtils { return eval(expr); }) Handlebars.registerHelper('isOwnerOrGM', function (actor) { - console.log("Testing actor", actor.isOwner, game.userId) + log("Testing actor", actor.isOwner, game.userId) return actor.isOwner || game.isGM; }) Handlebars.registerHelper('upperCase', function (text) { @@ -1665,7 +1667,7 @@ export default class LethalFantasyUtils { } ) - ChatMessage.create({ + await ChatMessage.create({ user: game.user.id, speaker: { alias: targetActor.name }, mode: "gm",