From bfbce9557bf60d08a9cc554e2509fd217dd2e9d6 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnier Date: Sun, 5 Jul 2026 20:51:26 +0200 Subject: [PATCH] fix: wrap mulligan message creation in try/catch to prevent handler abort Even with the partial correctly registered, a template rendering failure should not abort the entire reroll handler. Without try/catch, the exception propagates out of the do-while loop and prevents combat result creation. The reroll value was applied but nothing else happened. --- module/hooks/chat-reaction.mjs | 48 ++++++++++++++++++++-------------- module/utils/combat.mjs | 26 ++++++++++-------- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/module/hooks/chat-reaction.mjs b/module/hooks/chat-reaction.mjs index 24117b0..ff10df5 100644 --- a/module/hooks/chat-reaction.mjs +++ b/module/hooks/chat-reaction.mjs @@ -551,16 +551,20 @@ Hooks.on("createChatMessage", async (message) => { canRerollDefense = false if (!reroll) continue defenseRoll = reroll.options?.rollTotal || reroll.total || oldDefenseRoll - await createReactionMessage(defender, { - type: "mulligan", - actorName: defenderName, - side: "defense", - oldRoll: oldDefenseRoll, - newRoll: defenseRoll, - diceResults: reroll.options?.diceResults || [], - D30result: reroll.options?.D30result, - D30message: reroll.options?.D30message - }) + try { + await createReactionMessage(defender, { + type: "mulligan", + actorName: defenderName, + side: "defense", + oldRoll: oldDefenseRoll, + newRoll: defenseRoll, + diceResults: reroll.options?.diceResults || [], + D30result: reroll.options?.D30result, + D30message: reroll.options?.D30message + }) + } catch(e) { + console.error("Mulligan message creation failed (non-fatal):", e) + } // Apply new D30 result on the restart if (reroll.options?.D30message) { defenseD30message = reroll.options.D30message @@ -753,16 +757,20 @@ Hooks.on("createChatMessage", async (message) => { canRerollAttack = false if (!reroll) continue attackRollFinal = reroll.options?.rollTotal || reroll.total || oldAttackRoll - await createReactionMessage(attacker, { - type: "mulligan", - actorName: attackerName, - side: "attack", - oldRoll: oldAttackRoll, - newRoll: attackRollFinal, - diceResults: reroll.options?.diceResults || [], - D30result: reroll.options?.D30result, - D30message: reroll.options?.D30message - }) + try { + await createReactionMessage(attacker, { + type: "mulligan", + actorName: attackerName, + side: "attack", + oldRoll: oldAttackRoll, + newRoll: attackRollFinal, + diceResults: reroll.options?.diceResults || [], + D30result: reroll.options?.D30result, + D30message: reroll.options?.D30message + }) + } catch(e) { + console.error("Mulligan message creation failed (non-fatal):", e) + } // Apply new D30 result on the restart if (reroll.options?.D30message) { attackD30message = reroll.options.D30message diff --git a/module/utils/combat.mjs b/module/utils/combat.mjs index d56d847..c1c3582 100644 --- a/module/utils/combat.mjs +++ b/module/utils/combat.mjs @@ -206,17 +206,21 @@ export async function handleAttackBoosted(msg) { if (!reroll) continue updatedDefenseRoll = reroll.options?.rollTotal || reroll.total || oldDefenseRoll let newD30message = reroll.options?.D30message || null - const mulliganContent = await foundry.applications.handlebars.renderTemplate("systems/fvtt-lethal-fantasy/templates/chat/reaction-message.hbs", { - type: "mulligan", - actorName: defenderName, - side: "defense", - oldRoll: oldDefenseRoll, - newRoll: updatedDefenseRoll, - diceResults: reroll.options?.diceResults || [], - D30result: reroll.options?.D30result, - D30message: newD30message - }) - await ChatMessage.create({content: mulliganContent, speaker: ChatMessage.getSpeaker({actor: defender})}) + try { + const mulliganContent = await foundry.applications.handlebars.renderTemplate("systems/fvtt-lethal-fantasy/templates/chat/reaction-message.hbs", { + type: "mulligan", + actorName: defenderName, + side: "defense", + oldRoll: oldDefenseRoll, + newRoll: updatedDefenseRoll, + diceResults: reroll.options?.diceResults || [], + D30result: reroll.options?.D30result, + D30message: newD30message + }) + await ChatMessage.create({content: mulliganContent, speaker: ChatMessage.getSpeaker({actor: defender})}) + } catch(e) { + console.error("Mulligan message creation failed (non-fatal):", e) + } // Process new D30 bonus dice from the reroll if (newD30message) { defenseD30message = newD30message