diff --git a/lang/en.json b/lang/en.json index afd1785..7a97d5b 100644 --- a/lang/en.json +++ b/lang/en.json @@ -250,7 +250,7 @@ "Oaths": "Oaths", "Weapons": "Weapons", "Attacks": "Attacks", - "Armor": "Armor & Shields", + "Armor": "Armor", "Ammunition": "Ammunition", "ItemSlots": "Item Slots", "Spells": "Spells", @@ -444,7 +444,7 @@ "ExplodeOn5": "Explode on 5+", "ExplodeOn5Hint": "trait bonus — 5s & 6s explode", "DiceColor": "Dice Color", - "DiceColorHint": "equipment traits can upgrade dice", + "DiceColorHint": "White (4+), Red (3+), or Black (2+) thresholds", "AttackTitle": "Attack: {weapon}", "DamageTitle": "Damage: {weapon}", "Attack": "Attack", diff --git a/module/applications/miracle-dialog.mjs b/module/applications/miracle-dialog.mjs index b49088e..e230ead 100644 --- a/module/applications/miracle-dialog.mjs +++ b/module/applications/miracle-dialog.mjs @@ -6,9 +6,10 @@ export default class OathHammerMiracleDialog { const sys = miracle.system const actorSys = actor.system - const wpRank = actorSys.attributes.willpower.rank - const magicRank = actorSys.skills.magic.rank - const basePool = wpRank + magicRank + const wpRank = actorSys.attributes.willpower.rank + const magicRank = actorSys.skills.magic.rank + const magicColor = actorSys.skills.magic.colorDiceType ?? "white" + const basePool = wpRank + magicRank const isRitual = sys.isRitual const dv = isRitual ? (sys.difficultyValue || 1) : null @@ -18,6 +19,12 @@ export default class OathHammerMiracleDialog { return key ? game.i18n.localize(key) : sys.divineTradition })() + const colorOptions = [ + { value: "white", label: game.i18n.localize("OATHHAMMER.ColorDice.White"), selected: magicColor === "white" }, + { value: "red", label: game.i18n.localize("OATHHAMMER.ColorDice.Red"), selected: magicColor === "red" }, + { value: "black", label: game.i18n.localize("OATHHAMMER.ColorDice.Black"), selected: magicColor === "black" }, + ] + // Miracle count options — DV = miracle number today const miracleCountOptions = Array.from({ length: 10 }, (_, i) => ({ value: i + 1, @@ -55,6 +62,7 @@ export default class OathHammerMiracleDialog { magicRank, basePool, miracleCountOptions, + colorOptions, bonusOptions, availableLuck, isHuman, @@ -93,6 +101,7 @@ export default class OathHammerMiracleDialog { return { dv: computedDV, isRitual, + colorOverride: result.colorOverride ?? magicColor, bonus: parseInt(result.bonus) || 0, visibility: result.visibility ?? game.settings.get("core", "rollMode"), explodeOn5: result.explodeOn5 === "true", diff --git a/module/applications/spell-dialog.mjs b/module/applications/spell-dialog.mjs index dd3241d..6d4f510 100644 --- a/module/applications/spell-dialog.mjs +++ b/module/applications/spell-dialog.mjs @@ -25,9 +25,10 @@ export default class OathHammerSpellDialog { const sys = spell.system const actorSys = actor.system - const intRank = actorSys.attributes.intelligence.rank - const magicRank = actorSys.skills.magic.rank - const basePool = intRank + magicRank + const intRank = actorSys.attributes.intelligence.rank + const magicRank = actorSys.skills.magic.rank + const magicColor = actorSys.skills.magic.colorDiceType ?? "white" + const basePool = intRank + magicRank const currentStress = actorSys.arcaneStress.value const stressThreshold = actorSys.arcaneStress.threshold @@ -41,6 +42,12 @@ export default class OathHammerSpellDialog { return entry ? game.i18n.localize(entry.label) : (sys.tradition ?? "") })() + const colorOptions = [ + { value: "white", label: game.i18n.localize("OATHHAMMER.ColorDice.White"), selected: magicColor === "white" }, + { value: "red", label: game.i18n.localize("OATHHAMMER.ColorDice.Red"), selected: magicColor === "red" }, + { value: "black", label: game.i18n.localize("OATHHAMMER.ColorDice.Black"), selected: magicColor === "black" }, + ] + const enhancementOptions = Object.entries(SPELL_ENHANCEMENTS).map(([key, def]) => ({ value: key, label: game.i18n.localize(def.label), @@ -87,6 +94,7 @@ export default class OathHammerSpellDialog { magicRank, basePool, poolSizeOptions, + colorOptions, currentStress, stressThreshold, isOverThreshold, @@ -134,6 +142,7 @@ export default class OathHammerSpellDialog { poolPenalty: enh.penalty, redDice: enh.redDice, noStress: enh.noStress, + colorOverride: result.colorOverride ?? magicColor, elementalBonus: parseInt(result.elementalBonus) || 0, bonus: parseInt(result.bonus) || 0, poolSize: Math.min(Math.max(1, parseInt(result.poolSize) || basePool), basePool), diff --git a/module/rolls.mjs b/module/rolls.mjs index 5f2e903..40b619f 100644 --- a/module/rolls.mjs +++ b/module/rolls.mjs @@ -468,6 +468,7 @@ export async function rollSpellCast(actor, spell, options = {}) { poolPenalty = 0, redDice = false, noStress = false, + colorOverride = "white", elementalBonus = 0, bonus = 0, poolSize = null, @@ -489,8 +490,8 @@ export async function rollSpellCast(actor, spell, options = {}) { const totalDice = poolSize !== null ? Math.max(1, Math.min(poolSize + bonus + poolPenalty + elementalBonus + grimPenalty + (luckSpend * luckDicePerPoint), baseDice)) : Math.max(baseDice, 1) - const threshold = redDice ? 3 : 4 - const colorEmoji = redDice ? "🔴" : "⬜" + const threshold = colorOverride === "black" ? 2 : colorOverride === "red" ? 3 : 4 + const colorEmoji = colorOverride === "black" ? "⬛" : colorOverride === "red" ? "🔴" : "⬜" const { roll, rolls, successes, diceResults } = await _rollPool(totalDice, threshold, explodeOn5) const diceHtml = _diceHtml(diceResults, threshold) @@ -560,13 +561,12 @@ export async function rollSpellCast(actor, spell, options = {}) { ` const rollMode = visibility ?? game.settings.get("core", "rollMode") - const spellColorType = redDice ? "red" : "white" const msgData = { speaker: ChatMessage.getSpeaker({ actor }), content, rolls: rolls, sound: CONFIG.sounds.dice, - flags: { "fvtt-oath-hammer": { luckRoll: _luckFlagData(actor, threshold, spellColorType, dv, false, explodeOn5) } }, + flags: { "fvtt-oath-hammer": { luckRoll: _luckFlagData(actor, threshold, colorOverride, dv, false, explodeOn5) } }, } ChatMessage.applyRollMode(msgData, rollMode) await ChatMessage.create(msgData) @@ -590,6 +590,7 @@ export async function rollMiracleCast(actor, miracle, options = {}) { const { dv = 1, isRitual = false, + colorOverride = "white", bonus = 0, visibility, explodeOn5 = false, @@ -604,8 +605,8 @@ export async function rollMiracleCast(actor, miracle, options = {}) { const magicRank = actorSys.skills.magic.rank const luckDicePerPoint = luckIsHuman ? 3 : 2 const totalDice = Math.max(wpRank + magicRank + bonus + (luckSpend * luckDicePerPoint), 1) - const threshold = 4 - const colorEmoji = "⬜" + const threshold = colorOverride === "black" ? 2 : colorOverride === "red" ? 3 : 4 + const colorEmoji = colorOverride === "black" ? "⬛" : colorOverride === "red" ? "🔴" : "⬜" const { roll, rolls, successes, diceResults } = await _rollPool(totalDice, threshold, explodeOn5) const diceHtml = _diceHtml(diceResults, threshold) @@ -664,7 +665,7 @@ export async function rollMiracleCast(actor, miracle, options = {}) { content, rolls: rolls, sound: CONFIG.sounds.dice, - flags: { "fvtt-oath-hammer": { luckRoll: _luckFlagData(actor, threshold, "white", dv, false, explodeOn5) } }, + flags: { "fvtt-oath-hammer": { luckRoll: _luckFlagData(actor, threshold, colorOverride, dv, false, explodeOn5) } }, } ChatMessage.applyRollMode(msgData, rollMode) await ChatMessage.create(msgData) diff --git a/templates/miracle-cast-dialog.hbs b/templates/miracle-cast-dialog.hbs index 345b032..0df992c 100644 --- a/templates/miracle-cast-dialog.hbs +++ b/templates/miracle-cast-dialog.hbs @@ -45,6 +45,14 @@ {{/unless}} +