Update D30 descriptions and add simple shield option for NPCs

This commit is contained in:
2026-04-16 23:42:24 +02:00
parent 8c9a13faf1
commit 81584ed5d6
4 changed files with 124 additions and 17 deletions

View File

@@ -524,6 +524,7 @@ Hooks.on("createChatMessage", async (message) => {
const shieldData = LethalFantasyUtils.getShieldReactionData(defender)
let canRerollDefense = LethalFantasyUtils.hasD30Reroll(defenseD30message)
let canShieldReact = !!shieldData
let canAdHocShield = !shieldData
while (defenseRoll < attackRoll) {
const currentGrit = Number(defender.system?.grit?.current) || 0
@@ -571,6 +572,14 @@ Hooks.on("createChatMessage", async (message) => {
icon: "fa-solid fa-shield",
callback: () => "shieldReact"
})
} else if (canAdHocShield) {
// No pre-configured shield — offer ad-hoc shield option (useful for monsters)
buttons.push({
action: "adHocShield",
label: "Roll ad-hoc shield (choose dice + DR)",
icon: "fa-solid fa-shield-halved",
callback: () => "adHocShield"
})
}
buttons.push({
@@ -640,7 +649,6 @@ Hooks.on("createChatMessage", async (message) => {
canShieldReact = false
if (newDefenseTotal >= attackRoll) {
// Shield roll tied or exceeded the attack — shield blocked
shieldBlocked = true
shieldReaction = {
damageReduction: shieldData.damageReduction,
@@ -652,7 +660,6 @@ Hooks.on("createChatMessage", async (message) => {
`<p><strong>${defenderName}</strong> rolls <strong>${shieldData.label}</strong> and adds <strong>${shieldBonus}</strong> to defense (${newDefenseTotal}${attackRoll}). <strong>Shield blocked the attack!</strong> Both armor DR and shield DR <strong>${shieldData.damageReduction}</strong> will apply to damage.</p>`
)
} else {
// Shield roll not enough — hit still lands, armor DR only
shieldReaction = null
await createReactionMessage(
defender,
@@ -660,6 +667,35 @@ Hooks.on("createChatMessage", async (message) => {
)
}
}
if (choice === "adHocShield") {
const adHoc = await LethalFantasyUtils.promptAdHocShield(defenderName, attackRoll, defenseRoll)
if (!adHoc) continue
const shieldBonus = await LethalFantasyUtils.rollBonusDie(adHoc.formula, defender)
const newDefenseTotal = defenseRoll + shieldBonus
defenseRoll = newDefenseTotal
canShieldReact = false
canAdHocShield = false
if (newDefenseTotal >= attackRoll) {
shieldBlocked = true
shieldReaction = {
damageReduction: adHoc.damageReduction,
label: `${adHoc.formula.toUpperCase()} shield`,
bonus: shieldBonus
}
await createReactionMessage(
defender,
`<p><strong>${defenderName}</strong> rolls <strong>${adHoc.formula.toUpperCase()}</strong> shield and adds <strong>${shieldBonus}</strong> to defense (${newDefenseTotal}${attackRoll}). <strong>Shield blocked the attack!</strong> Both armor DR and shield DR <strong>${adHoc.damageReduction}</strong> will apply to damage.</p>`
)
} else {
shieldReaction = null
await createReactionMessage(
defender,
`<p><strong>${defenderName}</strong> rolls <strong>${adHoc.formula.toUpperCase()}</strong> shield and adds <strong>${shieldBonus}</strong> to defense (${newDefenseTotal} < ${attackRoll}). Shield did not block — normal hit, armor DR only.</p>`
)
}
}
}
}