/** * Armor roll dialog. * * Pool = Armor Value (AV) − AP penalty + manual bonus (can go to 0, unlike other pools) * Reinforced trait on the armor → red dice (3+) by default * Each success on the roll reduces incoming damage by 1. */ export default class OathHammerArmorDialog { static async prompt(actor, armor) { const sys = armor.system const av = sys.armorValue ?? 0 const isReinforced = [...(sys.traits ?? [])].includes("reinforced") const defaultColor = isReinforced ? "red" : "white" // Luck const actorSys = actor.system const availableLuck = actorSys.luck?.value ?? 0 const isHuman = (actorSys.lineage?.name ?? "").toLowerCase() === "human" const luckDicePerPoint = isHuman ? 3 : 2 const luckOptions = Array.from({ length: availableLuck + 1 }, (_, i) => ({ value: i, label: i === 0 ? "0" : `${i} (+${i * luckDicePerPoint}d)`, selected: i === 0, })) // AP options — entered by the user based on the attacker's weapon const apOptions = Array.from({ length: 9 }, (_, i) => ({ value: -i, label: i === 0 ? "0" : `−${i}`, selected: i === 0, })) const bonusOptions = Array.from({ length: 7 }, (_, i) => { const v = i - 3 return { value: v, label: v > 0 ? `+${v}` : String(v), selected: v === 0 } }) const colorOptions = [ { value: "white", label: "⬜ White (4+)", selected: defaultColor === "white" }, { value: "red", label: "🔴 Red (3+)", selected: defaultColor === "red" }, { value: "black", label: "⬛ Black (2+)", selected: defaultColor === "black" }, ] const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes) const context = { actorName: actor.name, armorName: armor.name, armorImg: armor.img, av, isReinforced, apOptions, bonusOptions, colorOptions, rollModes, visibility: game.settings.get("core", "rollMode"), availableLuck, isHuman, luckOptions, } const content = await foundry.applications.handlebars.renderTemplate( "systems/fvtt-oath-hammer/templates/armor-roll-dialog.hbs", context ) const result = await foundry.applications.api.DialogV2.wait({ window: { title: game.i18n.format("OATHHAMMER.Dialog.ArmorRollTitle", { armor: armor.name }) }, classes: ["fvtt-oath-hammer"], position: { width: 420 }, content, rejectClose: false, buttons: [{ label: game.i18n.localize("OATHHAMMER.Dialog.RollArmor"), callback: (_ev, btn) => { const out = {} for (const el of btn.form.elements) { if (!el.name) continue out[el.name] = el.type === "checkbox" ? String(el.checked) : el.value } return out }, }], }) if (!result) return null return { av, isReinforced, colorOverride: result.colorOverride || defaultColor, apPenalty: parseInt(result.ap) || 0, bonus: parseInt(result.bonus) || 0, visibility: result.visibility ?? game.settings.get("core", "rollMode"), explodeOn5: result.explodeOn5 === "true", luckSpend: Math.min(Math.max(0, parseInt(result.luckSpend) || 0), availableLuck), luckIsHuman: result.luckIsHuman === "true", } } }