feat: luck bonus, inventory slots bonus, multi-enhancements, magic skill modifier
Release Creation / build (release) Successful in 1m25s
Release Creation / build (release) Successful in 1m25s
- Add luck.bonus field to character DataModel; included in prepareDerivedData (luck.max = fate.rank + bonus); shown as editable +bonus field next to luck max in edit mode (same UX as grit bonus) - Add inventory.slotsBonus field to character DataModel; Equipment tab now shows an editable "Bonus Slots" input that adds to the calculated max slots (10 + Might×2 + bonus) - Replace single Enhancement <select> in spell cast dialog with a checkbox list; multiple enhancements can now be selected simultaneously — stress costs, pool penalties, and boolean flags (redDice, noStress) are aggregated across all active enhancements - Include skills.magic.modifier in basePool for both spell and miracle dialogs and in baseDice in rollSpellCast / rollMiracleCast; modifier is shown in the dialog pool-info line and in the chat card when non-zero - Fix: pool-reduction indicator in rollSpellCast now compares against intRank + magicRank + magicMod (was missing magicMod)
This commit is contained in:
@@ -8,8 +8,10 @@ export default class OathHammerMiracleDialog {
|
||||
|
||||
const wpRank = actorSys.attributes.willpower.rank
|
||||
const magicRank = actorSys.skills.magic.rank
|
||||
const magicMod = actorSys.skills.magic.modifier ?? 0
|
||||
const magicColor = actorSys.skills.magic.colorDiceType ?? "white"
|
||||
const basePool = wpRank + magicRank
|
||||
const basePool = wpRank + magicRank + magicMod
|
||||
const magicModDisplay = magicMod > 0 ? `+${magicMod}` : magicMod < 0 ? `${magicMod}` : ""
|
||||
|
||||
const isRitual = sys.isRitual
|
||||
const dv = isRitual ? (sys.difficultyValue || 1) : null
|
||||
@@ -60,6 +62,8 @@ export default class OathHammerMiracleDialog {
|
||||
spellSave: sys.spellSave,
|
||||
wpRank,
|
||||
magicRank,
|
||||
magicMod,
|
||||
magicModDisplay,
|
||||
basePool,
|
||||
miracleCountOptions,
|
||||
colorOptions,
|
||||
|
||||
@@ -39,6 +39,7 @@ export default class OathHammerCharacterSheet extends OathHammerActorSheet {
|
||||
adjustCurrency: OathHammerCharacterSheet.#onAdjustCurrency,
|
||||
adjustLuck: OathHammerCharacterSheet.#onAdjustLuck,
|
||||
adjustGrit: OathHammerCharacterSheet.#onAdjustGrit,
|
||||
adjustStress: OathHammerCharacterSheet.#onAdjustStress,
|
||||
clearStress: OathHammerCharacterSheet.#onClearStress,
|
||||
},
|
||||
}
|
||||
@@ -190,8 +191,8 @@ export default class OathHammerCharacterSheet extends OathHammerActorSheet {
|
||||
}
|
||||
})
|
||||
context.ammunition = doc.itemTypes.ammunition
|
||||
// Slot tracking: max = 10 + (Might rank × 2); used = sum of all items' slots × quantity
|
||||
context.slotsMax = 10 + (doc.system.attributes.might.rank * 2)
|
||||
// Slot tracking: max = 10 + (Might rank × 2) + bonus; used = sum of all items' slots × quantity
|
||||
context.slotsMax = 10 + (doc.system.attributes.might.rank * 2) + (doc.system.inventory?.slotsBonus ?? 0)
|
||||
context.slotsUsed = doc.items.reduce((sum, item) => {
|
||||
const qty = item.system.quantity ?? 1
|
||||
return sum + (item.system.slots ?? 0) * Math.max(qty, 1)
|
||||
@@ -225,7 +226,7 @@ export default class OathHammerCharacterSheet extends OathHammerActorSheet {
|
||||
id: m.id, uuid: m.uuid, img: m.img, name: m.name, system: m.system,
|
||||
_descTooltip: _stripHtml(m.system.description)
|
||||
}))
|
||||
context.slotsMax = 10 + (doc.system.attributes.might.rank * 2)
|
||||
context.slotsMax = 10 + (doc.system.attributes.might.rank * 2) + (doc.system.inventory?.slotsBonus ?? 0)
|
||||
context.slotsUsed = doc.items.reduce((sum, item) => {
|
||||
const qty = item.system.quantity ?? 1
|
||||
return sum + (item.system.slots ?? 0) * Math.max(qty, 1)
|
||||
|
||||
@@ -27,8 +27,10 @@ export default class OathHammerSpellDialog {
|
||||
|
||||
const intRank = actorSys.attributes.intelligence.rank
|
||||
const magicRank = actorSys.skills.magic.rank
|
||||
const magicMod = actorSys.skills.magic.modifier ?? 0
|
||||
const magicColor = actorSys.skills.magic.colorDiceType ?? "white"
|
||||
const basePool = intRank + magicRank
|
||||
const basePool = intRank + magicRank + magicMod
|
||||
const magicModDisplay = magicMod > 0 ? `+${magicMod}` : magicMod < 0 ? `${magicMod}` : ""
|
||||
|
||||
const currentStress = actorSys.arcaneStress.value
|
||||
const stressThreshold = actorSys.arcaneStress.threshold
|
||||
@@ -48,11 +50,12 @@ export default class OathHammerSpellDialog {
|
||||
{ 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),
|
||||
selected: key === "none",
|
||||
}))
|
||||
const enhancementOptions = Object.entries(SPELL_ENHANCEMENTS)
|
||||
.filter(([key]) => key !== "none")
|
||||
.map(([key, def]) => ({
|
||||
value: key,
|
||||
label: game.i18n.localize(def.label),
|
||||
}))
|
||||
|
||||
const bonusOptions = Array.from({ length: 13 }, (_, i) => {
|
||||
const v = i - 6
|
||||
@@ -92,6 +95,8 @@ export default class OathHammerSpellDialog {
|
||||
element: sys.element,
|
||||
intRank,
|
||||
magicRank,
|
||||
magicMod,
|
||||
magicModDisplay,
|
||||
basePool,
|
||||
poolSizeOptions,
|
||||
colorOptions,
|
||||
@@ -132,16 +137,25 @@ export default class OathHammerSpellDialog {
|
||||
|
||||
if (!result) return null
|
||||
|
||||
const enhKey = result.enhancement ?? "none"
|
||||
const enh = SPELL_ENHANCEMENTS[enhKey] ?? SPELL_ENHANCEMENTS.none
|
||||
// Collect all checked enhancements and aggregate their effects
|
||||
const selectedEnhs = Object.keys(SPELL_ENHANCEMENTS)
|
||||
.filter(k => k !== "none" && result[`enh_${k}`] === "true")
|
||||
const aggregated = selectedEnhs.reduce((acc, key) => {
|
||||
const def = SPELL_ENHANCEMENTS[key]
|
||||
acc.stress += def.stress
|
||||
acc.penalty += def.penalty
|
||||
if (def.redDice) acc.redDice = true
|
||||
if (def.noStress) acc.noStress = true
|
||||
return acc
|
||||
}, { stress: 0, penalty: 0, redDice: false, noStress: false })
|
||||
|
||||
return {
|
||||
dv,
|
||||
enhancement: enhKey,
|
||||
stressCost: enh.stress,
|
||||
poolPenalty: enh.penalty,
|
||||
redDice: enh.redDice,
|
||||
noStress: enh.noStress,
|
||||
enhancements: selectedEnhs.length ? selectedEnhs : ["none"],
|
||||
stressCost: aggregated.stress,
|
||||
poolPenalty: aggregated.penalty,
|
||||
redDice: aggregated.redDice,
|
||||
noStress: aggregated.noStress,
|
||||
colorOverride: result.colorOverride ?? magicColor,
|
||||
elementalBonus: parseInt(result.elementalBonus) || 0,
|
||||
bonus: parseInt(result.bonus) || 0,
|
||||
|
||||
Reference in New Issue
Block a user