From 1c288b654a69109faf556b7d34f2ab7055ba34d5 Mon Sep 17 00:00:00 2001 From: fabres Date: Wed, 22 Jul 2026 00:25:20 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20migration=20V14=20-=20rollMode=E2=86=92m?= =?UTF-8?q?essageMode,=20Token=20HUD,=20data-message-id?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - remplace core.rollMode → core.messageMode (setting V14) - migre toutes les cles (gmroll→gm, selfroll→self, blindroll→blind) - corrige le hook renderTokenHUD pour recuperer le tokenId via app.document - ajoute un bouton combat personnalise si absent du HUD V14 - corrige le toggle combat : isCombat manquant et guard si hors combat - chat-utility : data-document-id→data-message-id pour les messages V14 - rdd-utility : idem pour findChatMessage/getChatMessageId - roll-part-possession : getBestDraconic peut retourner undefined - distance.mjs : Token→foundry.canvas.placeables.Token --- module/actor.js | 8 ++-- module/actor/base-actor-reve.js | 2 +- .../actor/random/app-personnage-aleatoire.js | 2 +- module/chat-utility.js | 21 +++++----- module/combat/distance.mjs | 2 +- module/item/maladie.js | 2 +- module/misc.js | 4 +- module/rdd-combat.js | 2 +- module/rdd-resolution-table.js | 2 +- module/rdd-roll-result.js | 2 +- module/rdd-rolltables.js | 20 +++++----- module/rdd-token-hud.js | 39 +++++++++++-------- module/rdd-utility.js | 8 ++-- module/roll/roll-dialog.mjs | 2 +- module/roll/roll-part-possession.mjs | 2 +- module/roll/roll-part-rollmode.mjs | 6 +-- module/time/rdd-calendrier.js | 6 +-- module/tmr-rencontres.js | 4 +- 18 files changed, 72 insertions(+), 62 deletions(-) diff --git a/module/actor.js b/module/actor.js index eb02cda5..76e7c8ff 100644 --- a/module/actor.js +++ b/module/actor.js @@ -1646,10 +1646,10 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async ajoutExperience(rollData, hideChatMessage = 'show') { - const rollMode = rollData.current?.rollmode?.key ?? game.settings.get("core", "rollMode") + const rollMode = rollData.current?.rollmode?.key ?? game.settings.get("core", "messageMode") if (!rollData.rolled.isPart || rollData.finalLevel >= 0 || - rollMode == 'selfroll' || + rollMode == 'self' || !Misc.hasConnectedGM()) { return } @@ -1675,7 +1675,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async appliquerAppelMoral(rollData) { - if (!rollData.use.moral || game.settings.get("core", "rollMode") == 'selfroll') { + if (!rollData.use.moral || game.settings.get("core", "messageMode") == 'self') { return } if (rollData.rolled.isEchec || @@ -3057,7 +3057,7 @@ export class RdDActor extends RdDBaseActorSang { incarnation.name = 'Réincarnation de ' + incarnation.name incarnation.system = { carac: foundry.utils.deepClone(this.system.carac), - heure: RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "selfroll", showDice: SHOW_DICE })).key, + heure: RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "self", showDice: SHOW_DICE })).key, age: 18, biographie: '', notes: '', diff --git a/module/actor/base-actor-reve.js b/module/actor/base-actor-reve.js index e56b984a..230a0030 100644 --- a/module/actor/base-actor-reve.js +++ b/module/actor/base-actor-reve.js @@ -362,7 +362,7 @@ export class RdDBaseActorReve extends RdDBaseActor { selectedCarac: carac, competence: competence, diffLibre: diff ?? 0, - current: { rollmode: { key: game.settings.get("core", "rollMode") } }, + current: { rollmode: { key: game.settings.get("core", "messageMode") } }, show: { title: options?.title ?? '' } } RollDataAjustements.calcul(rollData, this); diff --git a/module/actor/random/app-personnage-aleatoire.js b/module/actor/random/app-personnage-aleatoire.js index 0db74c6f..5e40dfb4 100644 --- a/module/actor/random/app-personnage-aleatoire.js +++ b/module/actor/random/app-personnage-aleatoire.js @@ -38,7 +38,7 @@ async function randomPoidsKg(taille) { } async function randomHeure() { - return RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "selfroll", showDice: SHOW_DICE })).key + return RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "self", showDice: SHOW_DICE })).key } const CONTROL_UNKNOWN = { name: 'unknown', path: '', getter: (act) => { undefined }, random: async act => undefined } diff --git a/module/chat-utility.js b/module/chat-utility.js index 2dd40507..c6d826b2 100644 --- a/module/chat-utility.js +++ b/module/chat-utility.js @@ -93,9 +93,9 @@ export class ChatUtility { /* -------------------------------------------- */ static adaptVisibility( messageData, options = { actor: undefined, rollMode: undefined }) { - foundry.utils.mergeObject(options, { rollMode: game.settings.get("core", "rollMode") }, { overwrite: false }); + foundry.utils.mergeObject(options, { rollMode: game.settings.get("core", "messageMode") }, { overwrite: false }); switch (options.rollMode) { - case "blindroll": // GM only + case "blind": // GM only if (!game.user.isGM) { ChatUtility.blindMessageToGM(messageData) messageData.whisper = [game.user] @@ -105,10 +105,10 @@ export class ChatUtility { messageData.whisper = ChatUtility.getGMs() } break; - case "gmroll": + case "gm": messageData.whisper = options.actor ? ChatUtility.getOwners(options.actor) : ChatUtility.getUserAndGMs() break; - case "selfroll": + case "self": messageData.whisper = [game.user] break } @@ -158,21 +158,21 @@ export class ChatUtility { return game.users.filter(user => user.isGM) } - static applyRollMode(chatMessageData = {}, rollMode = game.settings.get("core", "rollMode")) { + static applyRollMode(chatMessageData = {}, rollMode = game.settings.get("core", "messageMode")) { switch (rollMode) { - case "blindroll": + case "blind": chatMessageData.blind = true chatMessageData.whisper = ChatUtility.getGMs() break - case "gmroll": + case "gm": chatMessageData.whisper = ChatUtility.getGMs() chatMessageData.blind = false break - case "roll": + case "public": chatMessageData.whisper = ChatUtility.getUsers(user => user.active) chatMessageData.blind = false break - case "selfroll": + case "self": chatMessageData.whisper = [game.user] chatMessageData.blind = false break @@ -211,7 +211,8 @@ export class ChatUtility { } static getChatMessage(event) { - const chatMessageId = $(event.currentTarget).closest('.chat-message').attr('data-document-id'); + const chatMessageEl = $(event.currentTarget).closest('.chat-message'); + const chatMessageId = chatMessageEl.attr('data-document-id') ?? chatMessageEl.attr('data-message-id'); return game.messages.get(chatMessageId); } diff --git a/module/combat/distance.mjs b/module/combat/distance.mjs index 3f54d693..6fa7077e 100644 --- a/module/combat/distance.mjs +++ b/module/combat/distance.mjs @@ -116,7 +116,7 @@ export class Distance { } static $isToken(token) { - return token instanceof Token || token instanceof TokenDocument + return token instanceof foundry.canvas.placeables.Token || token instanceof TokenDocument } } \ No newline at end of file diff --git a/module/item/maladie.js b/module/item/maladie.js index 0a86a42f..94c4b794 100644 --- a/module/item/maladie.js +++ b/module/item/maladie.js @@ -26,7 +26,7 @@ export class RdDItemMaladie extends RdDItem { whisper: ChatUtility.getOwners(mal.actor), content: `${mal.actor.name} souffre ${souffrance} (${Misc.typeName('Item', mal.type)}): vérifiez que les effets ne se sont pas aggravés !` }) - mal.postItemToChat('gmroll') + mal.postItemToChat('gm') await RdDItemMaladie.prolongerPeriode(mal, oldTimestamp, newTimestamp) } } diff --git a/module/misc.js b/module/misc.js index ca507f2b..372d7ef4 100644 --- a/module/misc.js +++ b/module/misc.js @@ -201,8 +201,8 @@ export class Misc { } static isRollModeHiddenToPlayer() { - const mode = game.settings.get("core", "rollMode"); - return mode === "blindroll" || mode === "gmroll" || mode === "selfroll"; + const mode = game.settings.get("core", "messageMode"); + return mode === "blind" || mode === "gm" || mode === "self"; } static getActiveUser(id) { diff --git a/module/rdd-combat.js b/module/rdd-combat.js index c4d4a75c..b8eaa831 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -150,7 +150,7 @@ export class RdDCombatManager extends Combat { }]) // Send a chat message - let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode"); + let rollMode = messageOptions.rollMode || game.settings.get("core", "messageMode"); let messageData = foundry.utils.mergeObject({ speaker: { scene: canvas?.scene?.id, diff --git a/module/rdd-resolution-table.js b/module/rdd-resolution-table.js index 0e03d5ab..1df8fed9 100644 --- a/module/rdd-resolution-table.js +++ b/module/rdd-resolution-table.js @@ -107,7 +107,7 @@ export class RdDResolutionTable { this._updateChancesWithBonus(chances, rollData.bonus, finalLevel); this._updateChancesFactor(chances, rollData.diviseurSignificative); chances.showDice = rollData.showDice; - chances.rollMode = rollData.current?.rollmode?.key ?? game.settings.get("core", "rollMode") + chances.rollMode = rollData.current?.rollmode?.key ?? game.settings.get("core", "messageMode") let rolled = await this.rollChances(chances, rollData.diviseurSignificative, rollData.forceDiceResult); rolled.caracValue = caracValue; diff --git a/module/rdd-roll-result.js b/module/rdd-roll-result.js index 9c842888..23775018 100644 --- a/module/rdd-roll-result.js +++ b/module/rdd-roll-result.js @@ -6,7 +6,7 @@ export class RdDRollResult { static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.hbs') { return await ChatMessage.create(ChatUtility.adaptVisibility( { content: await RdDRollResult.buildRollDataHtml(rollData, template) }, - { actor: actor, rollMode: rollData.current?.rollmode?.key ?? game.settings.get("core", "rollMode") } + { actor: actor, rollMode: rollData.current?.rollmode?.key ?? game.settings.get("core", "messageMode") } )) } diff --git a/module/rdd-rolltables.js b/module/rdd-rolltables.js index e3413932..037dffab 100644 --- a/module/rdd-rolltables.js +++ b/module/rdd-rolltables.js @@ -5,7 +5,7 @@ export class RdDRollTables { /* -------------------------------------------- */ static async genericGetTableResult(tableName, toChat) { let table = RdDRollTables.getWorldTable(tableName) ?? (await RdDRollTables.getSystemTable(tableName)); - const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll" }); + const draw = await table.draw({ displayChat: toChat, rollMode: "gm" }); return draw.results.length > 0 ? draw.results[0] : undefined; } @@ -34,7 +34,7 @@ export class RdDRollTables { } /* -------------------------------------------- */ - static async getCompetence(toChat = false, rollMode = "gmroll") { + static async getCompetence(toChat = false, rollMode = "gm") { if (toChat == 'liste') { return await RdDRollTables.listOrRoll('competences', 'Item', ['competence'], toChat, rollMode, it => 1); } @@ -44,44 +44,44 @@ export class RdDRollTables { } /* -------------------------------------------- */ - static async getSouffle(toChat = false, rollMode = "gmroll") { + static async getSouffle(toChat = false, rollMode = "gm") { return await RdDRollTables.listOrRoll('souffles-de-dragon', 'Item', ['souffle'], toChat, rollMode); } /* -------------------------------------------- */ - static async getQueue(toChat = false, rollMode = "gmroll") { + static async getQueue(toChat = false, rollMode = "gm") { return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat, rollMode); } - static async getDesirLancinant(toChat = false, rollMode = "gmroll") { + static async getDesirLancinant(toChat = false, rollMode = "gm") { return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat, rollMode, it => it.system.frequence, it => it.system.categorie == 'lancinant'); } - static async getIdeeFixe(toChat = false, rollMode = "gmroll") { + static async getIdeeFixe(toChat = false, rollMode = "gm") { return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat, rollMode, it => it.system.frequence, it => it.system.categorie == 'ideefixe'); } /* -------------------------------------------- */ - static async getTeteHR(toChat = false, rollMode = "gmroll") { + static async getTeteHR(toChat = false, rollMode = "gm") { return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-haut-revants', 'Item', ['tete'], toChat, rollMode); } /* -------------------------------------------- */ - static async getTete(toChat = false, rollMode = "gmroll") { + static async getTete(toChat = false, rollMode = "gm") { return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-tous-personnages', 'Item', ['tete'], toChat, rollMode); } /* -------------------------------------------- */ - static async getOmbre(toChat = false, rollMode = "gmroll") { + static async getOmbre(toChat = false, rollMode = "gm") { return await RdDRollTables.listOrRoll('ombres-de-thanatos', 'Item', ['ombre'], toChat, rollMode); } /* -------------------------------------------- */ - static async getTarot(toChat = true, rollMode = "gmroll") { + static async getTarot(toChat = true, rollMode = "gm") { return await RdDRollTables.listOrRoll('tarot-draconique', 'Item', ['tarot'], toChat, rollMode); } diff --git a/module/rdd-token-hud.js b/module/rdd-token-hud.js index 7cd39990..63f230a9 100644 --- a/module/rdd-token-hud.js +++ b/module/rdd-token-hud.js @@ -11,7 +11,7 @@ export class RdDTokenHud { static init() { // Integration du TokenHUD - Hooks.on('renderTokenHUD', (app, html, token) => { RdDTokenHud.addTokenHudExtensions(app, html, token.id) }); + Hooks.on('renderTokenHUD', (app, html) => { RdDTokenHud.addTokenHudExtensions(app, html, app.document?.id) }); } /* -------------------------------------------- */ @@ -24,14 +24,14 @@ export class RdDTokenHud { static async addExtensionHud(app, html, tokenId, isCombat) { let token = canvas?.tokens?.get(tokenId); - if (!token) return; - let actor = token.actor; + let actor = token?.actor ?? app.actor; app.hasExtension = true; // soins await RdDTokenHud.addExtensionHudSoins(html, actor); if (isCombat) { - const combatant = game.combat.combatants.find(c => c.tokenId == tokenId) + const combatant = game.combat?.combatants?.find(c => c.tokenId == tokenId) + if (!combatant) return; const actor = RdDCombatManager.getActorCombatant(combatant, { warning: false }) if (actor) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { @@ -165,19 +165,26 @@ export class RdDTokenHud { /* -------------------------------------------- */ static async addTokenHudExtensions(app, html, tokenId) { console.log(`Adding token HUD extensions for token ${tokenId}`); - const controlIconCombat = $(html).find('.control-icon[data-action=combat]'); - if (controlIconCombat.length > 0) { - controlIconCombat.click(event => { - if (event.currentTarget.className.includes('active')) { - RdDTokenHud.removeExtensionHud(app, html, tokenId); - } else { - setTimeout(() => RdDTokenHud.addExtensionHud(app, html, tokenId), 200); - } - }); - - const isCombat = controlIconCombat[0].className.includes('active'); - RdDTokenHud.addExtensionHud(app, html, tokenId, isCombat); + let controlIconCombat = $(html).find('.control-icon[data-action=combat]'); + if (!controlIconCombat.length) { + const colLeft = $(html).find('div.col.left'); + if (!colLeft.length) return; + controlIconCombat = $(``); + colLeft.append(controlIconCombat); } + controlIconCombat.click(event => { + const btn = event.currentTarget; + if (btn.className.includes('active')) { + btn.classList.remove('active'); + RdDTokenHud.removeExtensionHud(app, html, tokenId); + } else { + btn.classList.add('active'); + setTimeout(() => RdDTokenHud.addExtensionHud(app, html, tokenId, true), 200); + } + }); + + const isCombat = controlIconCombat[0].className.includes('active'); + RdDTokenHud.addExtensionHud(app, html, tokenId, isCombat); } /* -------------------------------------------- */ diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 13ad8648..1011d50e 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -892,11 +892,13 @@ export class RdDUtility { } static getChatMessageId(node) { - return node?.attributes.getNamedItem('data-document-id')?.value; + return node?.attributes.getNamedItem('data-document-id')?.value + ?? node?.attributes.getNamedItem('data-message-id')?.value; } static findChatMessage(current) { - return RdDUtility.findNodeMatching(current, it => it.classList.contains('chat-message') && it.attributes.getNamedItem('data-document-id')); + return RdDUtility.findNodeMatching(current, it => it.classList.contains('chat-message') + && (it.attributes.getNamedItem('data-document-id') || it.attributes.getNamedItem('data-message-id'))); } static findNodeMatching(current, predicate) { @@ -1000,7 +1002,7 @@ export class RdDUtility { static chatDataSetup(content, modeOverride, isRoll = false, forceWhisper) { let chatData = { user: game.user.id, - rollMode: modeOverride || game.settings.get("core", "rollMode"), + rollMode: modeOverride || game.settings.get("core", "messageMode"), content: content } ChatUtility.applyRollMode(chatData) diff --git a/module/roll/roll-dialog.mjs b/module/roll/roll-dialog.mjs index 6e8b824c..d4132cc4 100644 --- a/module/roll/roll-dialog.mjs +++ b/module/roll/roll-dialog.mjs @@ -314,7 +314,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 ALL_ROLL_TYPES.find(m => m.code == rollType).setRollDataType(rollData) rollData.refs = foundry.utils.mergeObject(rollData.refs ?? {}, Object.fromEntries(allowedRollParts.map(p => [p.code, {}]))); - rollData.options = rollData.options ?? { rollMode: game.settings.get("core", "rollMode") } + rollData.options = rollData.options ?? { rollMode: game.settings.get("core", "messageMode") } allowedRollParts.forEach(p => RollDialog.$initializeRollPart(rollData, p.code)) allowedRollParts diff --git a/module/roll/roll-part-possession.mjs b/module/roll/roll-part-possession.mjs index 412e0752..e4934824 100644 --- a/module/roll/roll-part-possession.mjs +++ b/module/roll/roll-part-possession.mjs @@ -31,7 +31,7 @@ export class RollPartPossession extends RollPartSelect { $getActorConjurations(rollData) { const competences = rollData.active.actor.getBestDraconic({possession: true}) - return competences.map(RollPartPossession.extractPossession) + return (competences ? [competences] : []).map(RollPartPossession.extractPossession) } static extractPossession(comp) { diff --git a/module/roll/roll-part-rollmode.mjs b/module/roll/roll-part-rollmode.mjs index 2df68935..eff4a26c 100644 --- a/module/roll/roll-part-rollmode.mjs +++ b/module/roll/roll-part-rollmode.mjs @@ -13,7 +13,7 @@ export class RollPartRollMode extends RollPart { } restore(rollData) { - this.setCurrent(rollData, { key: this.getSaved(rollData)?.key ?? game.settings.get("core", "rollMode") }) + this.setCurrent(rollData, { key: this.getSaved(rollData)?.key ?? game.settings.get("core", "messageMode") }) } store(rollData, targetData) { @@ -37,8 +37,8 @@ export class RollPartRollMode extends RollPart { } async onUpdateSetting(rollDialog, setting, update, options, id) { - if (setting == 'core.rollMode') { - this.setCurrent(rollDialog.rollData, { key: game.settings.get("core", "rollMode") }) + if (setting == 'core.messageMode') { + this.setCurrent(rollDialog.rollData, { key: game.settings.get("core", "messageMode") }) rollDialog.render() } } diff --git a/module/time/rdd-calendrier.js b/module/time/rdd-calendrier.js index 226da643..984f3469 100644 --- a/module/time/rdd-calendrier.js +++ b/module/time/rdd-calendrier.js @@ -236,7 +236,7 @@ export class RdDCalendrier extends HandlebarsApplicationMixin(foundry.applicatio /* -------------------------------------------- */ async ajouterNombreAstral(indexDate) { - const nombreAstral = await RdDDice.rollHeure( { showDice: HIDE_DICE, rollMode: "selfroll" }); + const nombreAstral = await RdDDice.rollHeure( { showDice: HIDE_DICE, rollMode: "self" }); return { nombreAstral: nombreAstral, lectures: [], @@ -348,7 +348,7 @@ export class RdDCalendrier extends HandlebarsApplicationMixin(foundry.applicatio caracValue: request.carac_vue, finalLevel: niveau, showDice: HIDE_DICE, - rollMode: "blindroll" + rollMode: "blind" }; await RdDResolutionTable.rollData(rollData); request.rolled = rollData.rolled; @@ -364,7 +364,7 @@ export class RdDCalendrier extends HandlebarsApplicationMixin(foundry.applicatio } else { request.nbAstral = await RdDDice.rollTotal("1dhr" + request.nbAstral, { - rollMode: "selfroll", showDice: HIDE_DICE + rollMode: "self", showDice: HIDE_DICE }); } await this.addNbAstralJoueur(actor, request.date, request.nbAstral, request.isValid) diff --git a/module/tmr-rencontres.js b/module/tmr-rencontres.js index 394ac29a..cc26802b 100644 --- a/module/tmr-rencontres.js +++ b/module/tmr-rencontres.js @@ -38,7 +38,7 @@ export class TMRRencontres { const frequence = it => it.system.frequence[tmrType]; const row = await this.table.getRandom(frequence, filtreMauvaise, forcedRoll); if (row) { - await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item', { showSource: false, rollMode: "gmroll" }); + await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item', { showSource: false, rollMode: "gm" }); } return row?.document; @@ -118,6 +118,6 @@ export class TMRRencontres { sound: CONFIG.sounds.dice, content: flavorContent }; - ChatMessage.create(messageData, { rollMode: "gmroll" }); + ChatMessage.create(messageData, { rollMode: "gm" }); } }