Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0381e8e024 |
@@ -565,16 +565,19 @@
|
|||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
font-size: calc(0.86rem * 0.9);
|
font-size: calc(0.86rem * 0.9);
|
||||||
}
|
}
|
||||||
.oathhammer .character-main .character-stats-band .character-resources .character-resource .grit-max-group {
|
.oathhammer .character-main .character-stats-band .character-resources .character-resource .grit-max-group,
|
||||||
|
.oathhammer .character-main .character-stats-band .character-resources .character-resource .luck-max-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
}
|
}
|
||||||
.oathhammer .character-main .character-stats-band .character-resources .character-resource .grit-max-group .res-bonus-label {
|
.oathhammer .character-main .character-stats-band .character-resources .character-resource .grit-max-group .res-bonus-label,
|
||||||
|
.oathhammer .character-main .character-stats-band .character-resources .character-resource .luck-max-group .res-bonus-label {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
font-size: calc(0.86rem * 0.9);
|
font-size: calc(0.86rem * 0.9);
|
||||||
}
|
}
|
||||||
.oathhammer .character-main .character-stats-band .character-resources .character-resource .grit-max-group .res-bonus-input {
|
.oathhammer .character-main .character-stats-band .character-resources .character-resource .grit-max-group .res-bonus-input,
|
||||||
|
.oathhammer .character-main .character-stats-band .character-resources .character-resource .luck-max-group .res-bonus-input {
|
||||||
width: 2.2rem;
|
width: 2.2rem;
|
||||||
opacity: 0.85;
|
opacity: 0.85;
|
||||||
border-left: 1px dashed #535128;
|
border-left: 1px dashed #535128;
|
||||||
@@ -1327,6 +1330,7 @@
|
|||||||
}
|
}
|
||||||
.slots-counter {
|
.slots-counter {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
padding: 2px 6px 4px;
|
padding: 2px 6px 4px;
|
||||||
}
|
}
|
||||||
@@ -1353,6 +1357,20 @@
|
|||||||
background: rgba(192, 57, 43, 0.1);
|
background: rgba(192, 57, 43, 0.1);
|
||||||
border-color: rgba(192, 57, 43, 0.4);
|
border-color: rgba(192, 57, 43, 0.4);
|
||||||
}
|
}
|
||||||
|
.slots-counter .slots-bonus-label {
|
||||||
|
font-size: calc(0.86rem * 0.9);
|
||||||
|
color: rgba(42, 26, 10, 0.6);
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
.slots-counter .slots-bonus-input {
|
||||||
|
width: 3rem;
|
||||||
|
font-size: calc(0.86rem * 0.9);
|
||||||
|
text-align: center;
|
||||||
|
padding: 1px 4px;
|
||||||
|
border: 1px solid rgba(200, 168, 75, 0.4);
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(200, 168, 75, 0.08);
|
||||||
|
}
|
||||||
.oathhammer .item-list--regiment .item-list-header,
|
.oathhammer .item-list--regiment .item-list-header,
|
||||||
.oathhammer .item-list--regiment .item-entry {
|
.oathhammer .item-list--regiment .item-entry {
|
||||||
grid-template-columns: 24px 1fr 4rem 5rem 4rem 4.5rem;
|
grid-template-columns: 24px 1fr 4rem 5rem 4rem 4.5rem;
|
||||||
@@ -2360,6 +2378,42 @@
|
|||||||
.oh-miracle-dialog select.enhancement-select {
|
.oh-miracle-dialog select.enhancement-select {
|
||||||
min-width: 220px;
|
min-width: 220px;
|
||||||
}
|
}
|
||||||
|
.oh-spell-dialog .roll-option-enhancements,
|
||||||
|
.oh-miracle-dialog .roll-option-enhancements {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.oh-spell-dialog .roll-option-enhancements .enhancements-header,
|
||||||
|
.oh-miracle-dialog .roll-option-enhancements .enhancements-header {
|
||||||
|
padding-top: 3px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.oh-spell-dialog .roll-option-enhancements .enhancements-list,
|
||||||
|
.oh-miracle-dialog .roll-option-enhancements .enhancements-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
.oh-spell-dialog .roll-option-enhancements .enhancement-item,
|
||||||
|
.oh-miracle-dialog .roll-option-enhancements .enhancement-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.oh-spell-dialog .roll-option-enhancements .enhancement-item input[type="checkbox"],
|
||||||
|
.oh-miracle-dialog .roll-option-enhancements .enhancement-item input[type="checkbox"] {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.oh-spell-dialog .roll-option-enhancements .enhancement-item .enh-name,
|
||||||
|
.oh-miracle-dialog .roll-option-enhancements .enhancement-item .enh-name {
|
||||||
|
font-size: calc(0.86rem * 0.85);
|
||||||
|
color: #2a1a0a;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
.oh-spell-card .oh-stress-line,
|
.oh-spell-card .oh-stress-line,
|
||||||
.oh-miracle-card .oh-stress-line {
|
.oh-miracle-card .oh-stress-line {
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
|
|||||||
@@ -253,6 +253,7 @@
|
|||||||
"Armor": "Armor",
|
"Armor": "Armor",
|
||||||
"Ammunition": "Ammunition",
|
"Ammunition": "Ammunition",
|
||||||
"ItemSlots": "Item Slots",
|
"ItemSlots": "Item Slots",
|
||||||
|
"SlotsBonus": "Bonus Slots",
|
||||||
"Spells": "Spells",
|
"Spells": "Spells",
|
||||||
"Miracles": "Miracles",
|
"Miracles": "Miracles",
|
||||||
"Equipment": "Equipment",
|
"Equipment": "Equipment",
|
||||||
|
|||||||
@@ -169,7 +169,8 @@
|
|||||||
|
|
||||||
.res-sep { opacity: 0.7; font-size: @font-size-xs; }
|
.res-sep { opacity: 0.7; font-size: @font-size-xs; }
|
||||||
|
|
||||||
.grit-max-group {
|
.grit-max-group,
|
||||||
|
.luck-max-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
|
|||||||
@@ -302,6 +302,7 @@
|
|||||||
// Slots counter on the Combat tab
|
// Slots counter on the Combat tab
|
||||||
.slots-counter {
|
.slots-counter {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
padding: 2px 6px 4px;
|
padding: 2px 6px 4px;
|
||||||
|
|
||||||
@@ -330,6 +331,22 @@
|
|||||||
border-color: fade(#c0392b, 40%);
|
border-color: fade(#c0392b, 40%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.slots-bonus-label {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: fade(@color-dark, 60%);
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slots-bonus-input {
|
||||||
|
width: 3rem;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
text-align: center;
|
||||||
|
padding: 1px 4px;
|
||||||
|
border: 1px solid fade(@color-gold, 40%);
|
||||||
|
border-radius: 4px;
|
||||||
|
background: fade(@color-gold, 8%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Regiment list (settlement garrison tab) ──────────────────────────────────
|
// ── Regiment list (settlement garrison tab) ──────────────────────────────────
|
||||||
|
|||||||
+38
-1
@@ -553,10 +553,47 @@
|
|||||||
i { flex-shrink: 0; }
|
i { flex-shrink: 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wide select for enhancement list
|
// Wide select for enhancement list (legacy, kept for miracle dialog)
|
||||||
select.enhancement-select {
|
select.enhancement-select {
|
||||||
min-width: 220px;
|
min-width: 220px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Multi-enhancement checkbox list
|
||||||
|
.roll-option-enhancements {
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
.enhancements-header {
|
||||||
|
padding-top: 3px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enhancements-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enhancement-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enh-name {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-dark;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chat card additions for spell/miracle
|
// Chat card additions for spell/miracle
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ export default class OathHammerMiracleDialog {
|
|||||||
|
|
||||||
const wpRank = actorSys.attributes.willpower.rank
|
const wpRank = actorSys.attributes.willpower.rank
|
||||||
const magicRank = actorSys.skills.magic.rank
|
const magicRank = actorSys.skills.magic.rank
|
||||||
|
const magicMod = actorSys.skills.magic.modifier ?? 0
|
||||||
const magicColor = actorSys.skills.magic.colorDiceType ?? "white"
|
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 isRitual = sys.isRitual
|
||||||
const dv = isRitual ? (sys.difficultyValue || 1) : null
|
const dv = isRitual ? (sys.difficultyValue || 1) : null
|
||||||
@@ -60,6 +62,8 @@ export default class OathHammerMiracleDialog {
|
|||||||
spellSave: sys.spellSave,
|
spellSave: sys.spellSave,
|
||||||
wpRank,
|
wpRank,
|
||||||
magicRank,
|
magicRank,
|
||||||
|
magicMod,
|
||||||
|
magicModDisplay,
|
||||||
basePool,
|
basePool,
|
||||||
miracleCountOptions,
|
miracleCountOptions,
|
||||||
colorOptions,
|
colorOptions,
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export default class OathHammerCharacterSheet extends OathHammerActorSheet {
|
|||||||
adjustCurrency: OathHammerCharacterSheet.#onAdjustCurrency,
|
adjustCurrency: OathHammerCharacterSheet.#onAdjustCurrency,
|
||||||
adjustLuck: OathHammerCharacterSheet.#onAdjustLuck,
|
adjustLuck: OathHammerCharacterSheet.#onAdjustLuck,
|
||||||
adjustGrit: OathHammerCharacterSheet.#onAdjustGrit,
|
adjustGrit: OathHammerCharacterSheet.#onAdjustGrit,
|
||||||
|
adjustStress: OathHammerCharacterSheet.#onAdjustStress,
|
||||||
clearStress: OathHammerCharacterSheet.#onClearStress,
|
clearStress: OathHammerCharacterSheet.#onClearStress,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -190,8 +191,8 @@ export default class OathHammerCharacterSheet extends OathHammerActorSheet {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
context.ammunition = doc.itemTypes.ammunition
|
context.ammunition = doc.itemTypes.ammunition
|
||||||
// Slot tracking: max = 10 + (Might rank × 2); used = sum of all items' slots × quantity
|
// Slot tracking: max = 10 + (Might rank × 2) + bonus; used = sum of all items' slots × quantity
|
||||||
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) => {
|
context.slotsUsed = doc.items.reduce((sum, item) => {
|
||||||
const qty = item.system.quantity ?? 1
|
const qty = item.system.quantity ?? 1
|
||||||
return sum + (item.system.slots ?? 0) * Math.max(qty, 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,
|
id: m.id, uuid: m.uuid, img: m.img, name: m.name, system: m.system,
|
||||||
_descTooltip: _stripHtml(m.system.description)
|
_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) => {
|
context.slotsUsed = doc.items.reduce((sum, item) => {
|
||||||
const qty = item.system.quantity ?? 1
|
const qty = item.system.quantity ?? 1
|
||||||
return sum + (item.system.slots ?? 0) * Math.max(qty, 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 intRank = actorSys.attributes.intelligence.rank
|
||||||
const magicRank = actorSys.skills.magic.rank
|
const magicRank = actorSys.skills.magic.rank
|
||||||
|
const magicMod = actorSys.skills.magic.modifier ?? 0
|
||||||
const magicColor = actorSys.skills.magic.colorDiceType ?? "white"
|
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 currentStress = actorSys.arcaneStress.value
|
||||||
const stressThreshold = actorSys.arcaneStress.threshold
|
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" },
|
{ value: "black", label: game.i18n.localize("OATHHAMMER.ColorDice.Black"), selected: magicColor === "black" },
|
||||||
]
|
]
|
||||||
|
|
||||||
const enhancementOptions = Object.entries(SPELL_ENHANCEMENTS).map(([key, def]) => ({
|
const enhancementOptions = Object.entries(SPELL_ENHANCEMENTS)
|
||||||
value: key,
|
.filter(([key]) => key !== "none")
|
||||||
label: game.i18n.localize(def.label),
|
.map(([key, def]) => ({
|
||||||
selected: key === "none",
|
value: key,
|
||||||
}))
|
label: game.i18n.localize(def.label),
|
||||||
|
}))
|
||||||
|
|
||||||
const bonusOptions = Array.from({ length: 13 }, (_, i) => {
|
const bonusOptions = Array.from({ length: 13 }, (_, i) => {
|
||||||
const v = i - 6
|
const v = i - 6
|
||||||
@@ -92,6 +95,8 @@ export default class OathHammerSpellDialog {
|
|||||||
element: sys.element,
|
element: sys.element,
|
||||||
intRank,
|
intRank,
|
||||||
magicRank,
|
magicRank,
|
||||||
|
magicMod,
|
||||||
|
magicModDisplay,
|
||||||
basePool,
|
basePool,
|
||||||
poolSizeOptions,
|
poolSizeOptions,
|
||||||
colorOptions,
|
colorOptions,
|
||||||
@@ -132,16 +137,25 @@ export default class OathHammerSpellDialog {
|
|||||||
|
|
||||||
if (!result) return null
|
if (!result) return null
|
||||||
|
|
||||||
const enhKey = result.enhancement ?? "none"
|
// Collect all checked enhancements and aggregate their effects
|
||||||
const enh = SPELL_ENHANCEMENTS[enhKey] ?? SPELL_ENHANCEMENTS.none
|
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 {
|
return {
|
||||||
dv,
|
dv,
|
||||||
enhancement: enhKey,
|
enhancements: selectedEnhs.length ? selectedEnhs : ["none"],
|
||||||
stressCost: enh.stress,
|
stressCost: aggregated.stress,
|
||||||
poolPenalty: enh.penalty,
|
poolPenalty: aggregated.penalty,
|
||||||
redDice: enh.redDice,
|
redDice: aggregated.redDice,
|
||||||
noStress: enh.noStress,
|
noStress: aggregated.noStress,
|
||||||
colorOverride: result.colorOverride ?? magicColor,
|
colorOverride: result.colorOverride ?? magicColor,
|
||||||
elementalBonus: parseInt(result.elementalBonus) || 0,
|
elementalBonus: parseInt(result.elementalBonus) || 0,
|
||||||
bonus: parseInt(result.bonus) || 0,
|
bonus: parseInt(result.bonus) || 0,
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ export default class OathHammerCharacter extends foundry.abstract.TypeDataModel
|
|||||||
// Luck.max is derived from fate.rank; resets at session start.
|
// Luck.max is derived from fate.rank; resets at session start.
|
||||||
schema.luck = new fields.SchemaField({
|
schema.luck = new fields.SchemaField({
|
||||||
value: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }),
|
value: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }),
|
||||||
max: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 })
|
max: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }),
|
||||||
|
bonus: new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||||
})
|
})
|
||||||
|
|
||||||
schema.arcaneStress = new fields.SchemaField({
|
schema.arcaneStress = new fields.SchemaField({
|
||||||
@@ -119,6 +120,10 @@ export default class OathHammerCharacter extends foundry.abstract.TypeDataModel
|
|||||||
copper: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
copper: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
schema.inventory = new fields.SchemaField({
|
||||||
|
slotsBonus: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
|
||||||
|
})
|
||||||
|
|
||||||
return schema
|
return schema
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,8 +133,8 @@ export default class OathHammerCharacter extends foundry.abstract.TypeDataModel
|
|||||||
super.prepareDerivedData()
|
super.prepareDerivedData()
|
||||||
// Grit max = Resilience skill rank + Toughness attribute rank + bonus (rulebook p.5)
|
// Grit max = Resilience skill rank + Toughness attribute rank + bonus (rulebook p.5)
|
||||||
this.grit.max = this.skills.resilience.rank + this.attributes.toughness.rank + (this.grit.bonus ?? 0)
|
this.grit.max = this.skills.resilience.rank + this.attributes.toughness.rank + (this.grit.bonus ?? 0)
|
||||||
// Luck max = Fate rank; restores at session start
|
// Luck max = Fate rank + bonus; restores at session start
|
||||||
this.luck.max = this.attributes.fate.rank
|
this.luck.max = this.attributes.fate.rank + (this.luck.bonus ?? 0)
|
||||||
// Defense score = 10 + Agility + Armor Rating + bonus
|
// Defense score = 10 + Agility + Armor Rating + bonus
|
||||||
this.defense.value = 10 + this.attributes.agility.rank + this.defense.armorRating + this.defense.bonus
|
this.defense.value = 10 + this.attributes.agility.rank + this.defense.armorRating + this.defense.bonus
|
||||||
// Stress Threshold = Willpower rank + Magic rank + bonus (rulebook p.101)
|
// Stress Threshold = Willpower rank + Magic rank + bonus (rulebook p.101)
|
||||||
|
|||||||
+11
-7
@@ -463,7 +463,7 @@ export async function rollWeaponDamage(actor, weapon, options = {}) {
|
|||||||
export async function rollSpellCast(actor, spell, options = {}) {
|
export async function rollSpellCast(actor, spell, options = {}) {
|
||||||
const {
|
const {
|
||||||
dv = spell.system.difficultyValue,
|
dv = spell.system.difficultyValue,
|
||||||
enhancement = "none",
|
enhancements = ["none"],
|
||||||
stressCost = 0,
|
stressCost = 0,
|
||||||
poolPenalty = 0,
|
poolPenalty = 0,
|
||||||
redDice = false,
|
redDice = false,
|
||||||
@@ -484,8 +484,9 @@ export async function rollSpellCast(actor, spell, options = {}) {
|
|||||||
|
|
||||||
const intRank = actorSys.attributes.intelligence.rank
|
const intRank = actorSys.attributes.intelligence.rank
|
||||||
const magicRank = actorSys.skills.magic.rank
|
const magicRank = actorSys.skills.magic.rank
|
||||||
|
const magicMod = actorSys.skills.magic.modifier ?? 0
|
||||||
const luckDicePerPoint = luckIsHuman ? 3 : 2
|
const luckDicePerPoint = luckIsHuman ? 3 : 2
|
||||||
const baseDice = intRank + magicRank + bonus + poolPenalty + elementalBonus + grimPenalty + (luckSpend * luckDicePerPoint)
|
const baseDice = intRank + magicRank + magicMod + bonus + poolPenalty + elementalBonus + grimPenalty + (luckSpend * luckDicePerPoint)
|
||||||
// poolSize: voluntary reduction (p.101) — clamped to [1, baseDice]
|
// poolSize: voluntary reduction (p.101) — clamped to [1, baseDice]
|
||||||
const totalDice = poolSize !== null
|
const totalDice = poolSize !== null
|
||||||
? Math.max(1, Math.min(poolSize + bonus + poolPenalty + elementalBonus + grimPenalty + (luckSpend * luckDicePerPoint), baseDice))
|
? Math.max(1, Math.min(poolSize + bonus + poolPenalty + elementalBonus + grimPenalty + (luckSpend * luckDicePerPoint), baseDice))
|
||||||
@@ -523,9 +524,11 @@ export async function rollSpellCast(actor, spell, options = {}) {
|
|||||||
: game.i18n.localize("OATHHAMMER.Roll.Failure")
|
: game.i18n.localize("OATHHAMMER.Roll.Failure")
|
||||||
|
|
||||||
const modParts = []
|
const modParts = []
|
||||||
if (poolSize !== null && poolSize < intRank + magicRank) modParts.push(`🎲 ${poolSize}d ${game.i18n.localize("OATHHAMMER.Dialog.PoolSizeReduced")}`)
|
if (poolSize !== null && poolSize < intRank + magicRank + magicMod) modParts.push(`🎲 ${poolSize}d ${game.i18n.localize("OATHHAMMER.Dialog.PoolSizeReduced")}`)
|
||||||
if (bonus !== 0) modParts.push(`${bonus > 0 ? "+" : ""}${bonus} ${game.i18n.localize("OATHHAMMER.Dialog.Modifier")}`)
|
if (bonus !== 0) modParts.push(`${bonus > 0 ? "+" : ""}${bonus} ${game.i18n.localize("OATHHAMMER.Dialog.Modifier")}`)
|
||||||
if (poolPenalty !== 0) modParts.push(`${poolPenalty} ${game.i18n.localize("OATHHAMMER.Enhancement." + _cap(enhancement))}`)
|
const activeEnhs = enhancements.filter(k => k !== "none")
|
||||||
|
if (poolPenalty !== 0 || (activeEnhs.length && !poolPenalty))
|
||||||
|
modParts.push(`${poolPenalty !== 0 ? poolPenalty + "d " : ""}[${activeEnhs.join(", ")}]`)
|
||||||
if (elementalBonus > 0) modParts.push(`+${elementalBonus} ${game.i18n.localize("OATHHAMMER.Dialog.ElementMet")}`)
|
if (elementalBonus > 0) modParts.push(`+${elementalBonus} ${game.i18n.localize("OATHHAMMER.Dialog.ElementMet")}`)
|
||||||
if (grimPenalty < 0) modParts.push(`${grimPenalty} ${game.i18n.localize("OATHHAMMER.Dialog.GrimoireNo")}`)
|
if (grimPenalty < 0) modParts.push(`${grimPenalty} ${game.i18n.localize("OATHHAMMER.Dialog.GrimoireNo")}`)
|
||||||
if (luckSpend > 0) modParts.push(`+${luckSpend * luckDicePerPoint} ${game.i18n.localize("OATHHAMMER.Dialog.LuckSpend")} (${luckSpend}LP${luckIsHuman ? " 👤" : ""})`)
|
if (luckSpend > 0) modParts.push(`+${luckSpend * luckDicePerPoint} ${game.i18n.localize("OATHHAMMER.Dialog.LuckSpend")} (${luckSpend}LP${luckIsHuman ? " 👤" : ""})`)
|
||||||
@@ -547,7 +550,7 @@ export async function rollSpellCast(actor, spell, options = {}) {
|
|||||||
<span>${spell.name} (DV ${dv})</span>
|
<span>${spell.name} (DV ${dv})</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="oh-roll-info">
|
<div class="oh-roll-info">
|
||||||
<span>${attrLabel} ${intRank} + ${skillLabel} ${magicRank}</span>
|
<span>${attrLabel} ${intRank} + ${skillLabel} ${magicRank}${magicMod !== 0 ? ` ${magicMod > 0 ? "+" : ""}${magicMod}` : ""}</span>
|
||||||
<span>${colorEmoji} ${totalDice}d6 (${threshold}+)</span>
|
<span>${colorEmoji} ${totalDice}d6 (${threshold}+)</span>
|
||||||
</div>
|
</div>
|
||||||
${modLine}
|
${modLine}
|
||||||
@@ -603,8 +606,9 @@ export async function rollMiracleCast(actor, miracle, options = {}) {
|
|||||||
|
|
||||||
const wpRank = actorSys.attributes.willpower.rank
|
const wpRank = actorSys.attributes.willpower.rank
|
||||||
const magicRank = actorSys.skills.magic.rank
|
const magicRank = actorSys.skills.magic.rank
|
||||||
|
const magicMod = actorSys.skills.magic.modifier ?? 0
|
||||||
const luckDicePerPoint = luckIsHuman ? 3 : 2
|
const luckDicePerPoint = luckIsHuman ? 3 : 2
|
||||||
const totalDice = Math.max(wpRank + magicRank + bonus + (luckSpend * luckDicePerPoint), 1)
|
const totalDice = Math.max(wpRank + magicRank + magicMod + bonus + (luckSpend * luckDicePerPoint), 1)
|
||||||
const threshold = colorOverride === "black" ? 2 : colorOverride === "red" ? 3 : 4
|
const threshold = colorOverride === "black" ? 2 : colorOverride === "red" ? 3 : 4
|
||||||
const colorEmoji = colorOverride === "black" ? "⬛" : colorOverride === "red" ? "🔴" : "⬜"
|
const colorEmoji = colorOverride === "black" ? "⬛" : colorOverride === "red" ? "🔴" : "⬜"
|
||||||
|
|
||||||
@@ -646,7 +650,7 @@ export async function rollMiracleCast(actor, miracle, options = {}) {
|
|||||||
<span>${miracle.name} (${dvNote})</span>
|
<span>${miracle.name} (${dvNote})</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="oh-roll-info">
|
<div class="oh-roll-info">
|
||||||
<span>${attrLabel} ${wpRank} + ${skillLabel} ${magicRank}</span>
|
<span>${attrLabel} ${wpRank} + ${skillLabel} ${magicRank}${magicMod !== 0 ? ` ${magicMod > 0 ? "+" : ""}${magicMod}` : ""}</span>
|
||||||
<span>${colorEmoji} ${totalDice}d6 (${threshold}+)</span>
|
<span>${colorEmoji} ${totalDice}d6 (${threshold}+)</span>
|
||||||
</div>
|
</div>
|
||||||
${modLine}
|
${modLine}
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000021
|
MANIFEST-000030
|
||||||
|
|||||||
Binary file not shown.
@@ -2,6 +2,8 @@
|
|||||||
<div class="slots-counter">
|
<div class="slots-counter">
|
||||||
<span class="slots-label">{{localize "OATHHAMMER.Label.ItemSlots"}}</span>
|
<span class="slots-label">{{localize "OATHHAMMER.Label.ItemSlots"}}</span>
|
||||||
<span class="slots-value {{#if slotsOver}}slots-over{{/if}}">{{slotsUsed}} / {{slotsMax}}</span>
|
<span class="slots-value {{#if slotsOver}}slots-over{{/if}}">{{slotsUsed}} / {{slotsMax}}</span>
|
||||||
|
<span class="slots-bonus-label">{{localize "OATHHAMMER.Label.SlotsBonus"}}</span>
|
||||||
|
<input type="number" name="system.inventory.slotsBonus" value="{{system.inventory.slotsBonus}}" class="slots-bonus-input">
|
||||||
</div>
|
</div>
|
||||||
<fieldset class="currency-bar">
|
<fieldset class="currency-bar">
|
||||||
<legend>{{localize "OATHHAMMER.Label.Currency"}}</legend>
|
<legend>{{localize "OATHHAMMER.Label.Currency"}}</legend>
|
||||||
|
|||||||
@@ -72,7 +72,13 @@
|
|||||||
<a data-action="adjustLuck" data-delta="1" class="luck-btn">+</a>
|
<a data-action="adjustLuck" data-delta="1" class="luck-btn">+</a>
|
||||||
</div>
|
</div>
|
||||||
<span class="res-sep">/</span>
|
<span class="res-sep">/</span>
|
||||||
{{formInput systemFields.luck.fields.max value=system.luck.max name="system.luck.max" disabled=isPlayMode}}
|
<span class="luck-max-group">
|
||||||
|
{{formInput systemFields.luck.fields.max value=system.luck.max name="system.luck.max" disabled=true}}
|
||||||
|
{{#unless isPlayMode}}
|
||||||
|
<span class="res-bonus-label">+</span>
|
||||||
|
{{formInput systemFields.luck.fields.bonus value=system.luck.bonus name="system.luck.bonus" class="res-bonus-input"}}
|
||||||
|
{{/unless}}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="character-resource">
|
<div class="character-resource">
|
||||||
<span class="resource-label">{{localize "OATHHAMMER.Label.Movement"}}</span>
|
<span class="resource-label">{{localize "OATHHAMMER.Label.Movement"}}</span>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
<div class="pool-info-line">
|
<div class="pool-info-line">
|
||||||
{{localize "OATHHAMMER.Skill.Magic"}} ({{localize "OATHHAMMER.Attribute.Willpower"}} {{wpRank}})
|
{{localize "OATHHAMMER.Skill.Magic"}} ({{localize "OATHHAMMER.Attribute.Willpower"}} {{wpRank}})
|
||||||
+ {{localize "OATHHAMMER.Label.SkillRank"}} {{magicRank}}
|
+ {{localize "OATHHAMMER.Label.SkillRank"}} {{magicRank}}
|
||||||
|
{{#if magicModDisplay}} {{localize "OATHHAMMER.Label.SkillModifier"}} {{magicModDisplay}}{{/if}}
|
||||||
= <strong>{{basePool}}d6</strong>
|
= <strong>{{basePool}}d6</strong>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
<div class="pool-info-line">
|
<div class="pool-info-line">
|
||||||
{{localize "OATHHAMMER.Skill.Magic"}} ({{localize "OATHHAMMER.Attribute.Intelligence"}} {{intRank}})
|
{{localize "OATHHAMMER.Skill.Magic"}} ({{localize "OATHHAMMER.Attribute.Intelligence"}} {{intRank}})
|
||||||
+ {{localize "OATHHAMMER.Label.SkillRank"}} {{magicRank}}
|
+ {{localize "OATHHAMMER.Label.SkillRank"}} {{magicRank}}
|
||||||
|
{{#if magicModDisplay}} {{localize "OATHHAMMER.Label.SkillModifier"}} {{magicModDisplay}}{{/if}}
|
||||||
= <strong>{{basePool}}d6</strong>
|
= <strong>{{basePool}}d6</strong>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -52,11 +53,16 @@
|
|||||||
<span class="roll-option-hint">{{localize "OATHHAMMER.Dialog.DiceColorHint"}}</span>
|
<span class="roll-option-hint">{{localize "OATHHAMMER.Dialog.DiceColorHint"}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="roll-option-row">
|
<div class="roll-option-row roll-option-enhancements">
|
||||||
<label>{{localize "OATHHAMMER.Dialog.Enhancement"}}</label>
|
<label class="enhancements-header">{{localize "OATHHAMMER.Dialog.Enhancement"}}</label>
|
||||||
<select name="enhancement" class="enhancement-select">
|
<div class="enhancements-list">
|
||||||
{{#each enhancementOptions}}<option value="{{value}}"{{#if selected}} selected{{/if}}>{{label}}</option>{{/each}}
|
{{#each enhancementOptions}}
|
||||||
</select>
|
<div class="enhancement-item">
|
||||||
|
<input type="checkbox" id="enh_{{value}}" name="enh_{{value}}" value="true">
|
||||||
|
<label for="enh_{{value}}" class="enh-name">{{label}}</label>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if isElemental}}
|
{{#if isElemental}}
|
||||||
|
|||||||
Reference in New Issue
Block a user