diff --git a/module/utils/combat.mjs b/module/utils/combat.mjs index 19e4125..48104b2 100644 --- a/module/utils/combat.mjs +++ b/module/utils/combat.mjs @@ -105,8 +105,24 @@ export async function handleAttackBoosted(msg) { } = msg const defender = game.actors.get(defenderId) + const attacker = game.actors.get(attackerId) if (!defender) return + // When the attacker is GM-owned (not a PC on another client), the createChatMessage + // hook on the defender's client already handles everything: D30 bonus dice, defense + // reaction dialog (grit/luck/shield/mulligan), and the comparison message. Running + // handleAttackBoosted too would double-roll all dice and show duplicate dialogs. + // Only proceed when the hook is suppressed (attacker is a PC on another client). + const attackerHasNonGMOwner = attacker && game.users.some(u => u.active && !u.isGM && attacker.testUserPermission(u, "OWNER")) + const _isPrimaryController = actor => { + if (!actor) return false + const activePlayerOwners = game.users.filter(u => u.active && !u.isGM && actor.testUserPermission(u, "OWNER")) + if (activePlayerOwners.length > 0) return activePlayerOwners[0].id === game.user.id + return game.user.isGM + } + const attackerIsCrossClient = attackerHasNonGMOwner && !_isPrimaryController(attacker) + if (!attackerIsCrossClient) return + let updatedDefenseRoll = defenseRoll let shieldBlocked = false let shieldReaction = null