From b567c8bbea0285e3956d2c74a18ae271b6e04ddc Mon Sep 17 00:00:00 2001 From: LeRatierBretonnier Date: Sat, 13 Jun 2026 23:15:22 +0200 Subject: [PATCH] Fix D30 management, again --- lethal-fantasy.mjs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lethal-fantasy.mjs b/lethal-fantasy.mjs index e56587c..b14e835 100644 --- a/lethal-fantasy.mjs +++ b/lethal-fantasy.mjs @@ -873,6 +873,7 @@ Hooks.on("createChatMessage", async (message) => { // ── D30 bonus dice (attack) — resolved before grit/luck ──────────────── if (attackD30message && !attackD30Processed) { + const preD30AttackRoll = attackRollFinal const canDialog = isPrimaryController(attacker) const d30Result = await LethalFantasyUtils.processD30BonusDice(attackD30message, "attack", attackNaturalRoll, attacker, canDialog) if (d30Result.modifier) { @@ -913,10 +914,17 @@ Hooks.on("createChatMessage", async (message) => { } } attackD30Processed = true + // If D30 boosted attack past defense, restart so defender can react. + // Only restart when D30 actually changed the outcome (pre-D30 defender was + // winning or tied, post-D30 defender is losing). + if (defender && preD30AttackRoll <= defenseRoll && defenseRoll < attackRollFinal) { + mulliganRestart = true + continue + } } // ── Attack reaction loop ─────────────────────────────────────────────── - if (!defenderHandledBonus && attacker && attackRollFinal <= defenseRoll && isPrimaryController(attacker)) { + if (attacker && attackRollFinal <= defenseRoll && isPrimaryController(attacker)) { while (attackRollFinal <= defenseRoll) { const currentGrit = Number(attacker.system?.grit?.current) || 0 const buttons = []