From 9e4d8d637a377b2ca6e8873452078858d5ad1aa1 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Tue, 14 Jul 2026 20:24:19 +0200 Subject: [PATCH] add reloading feature Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> --- lang/en.json | 11 +++++++ module/config/generalConfig.mjs | 5 +++ module/data/fields/action/costField.mjs | 22 +++++++++++-- module/data/fields/action/damageField.mjs | 10 ++++-- module/documents/actor.mjs | 38 +++++++++++++++++------ templates/actionTypes/damage.hbs | 5 +++ templates/ui/chat/damageSummary.hbs | 10 +++++- templates/ui/chat/parts/damage-part.hbs | 6 ++-- 8 files changed, 91 insertions(+), 16 deletions(-) diff --git a/lang/en.json b/lang/en.json index 41d2cabd..ef8ba2e3 100755 --- a/lang/en.json +++ b/lang/en.json @@ -144,6 +144,10 @@ "resultBased": { "label": "Formula based on Hope/Fear result." }, + "fullRestore": { + "label": "Fully restore the resource.", + "inChatRoll": "Full" + }, "applyTo": { "label": "Targeted Resource" }, @@ -1279,6 +1283,11 @@ "name": "Fear", "abbreviation": "FR", "inChatRoll": "Fear" + }, + "weaponResource": { + "name": "Weapon Resource", + "abbreviation": "WR", + "inChatRoll": "Reload" } }, "ItemResourceProgression": { @@ -3090,6 +3099,8 @@ "applyHealing": "Apply Healing" }, "markResource": "Mark {quantity} {resource}", + "reloadWeapon": "Reload {weapon}", + "restoreWeaponResource": "Restore {quantity} on {weapon}", "refreshMessage": { "title": "Feature Refresh", "header": "Refreshed" diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index 188efafb..c31313de 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -191,6 +191,11 @@ export const healingTypes = { id: 'fear', label: 'DAGGERHEART.CONFIG.HealingType.fear.name', abbreviation: 'DAGGERHEART.CONFIG.HealingType.fear.abbreviation' + }, + weaponResource: { + id: 'weaponResource', + label: 'DAGGERHEART.CONFIG.HealingType.weaponResource.name', + abbreviation: 'DAGGERHEART.CONFIG.HealingType.weaponResource.abbreviation' } }; diff --git a/module/data/fields/action/costField.mjs b/module/data/fields/action/costField.mjs index 82cfcd23..96032cb4 100644 --- a/module/data/fields/action/costField.mjs +++ b/module/data/fields/action/costField.mjs @@ -197,11 +197,29 @@ export default class CostField extends fields.ArrayField { static getItemIdCostUpdate(r) { switch (r.key) { - case CONFIG.DH.GENERAL.itemAbilityCosts.resource.id: + case CONFIG.DH.GENERAL.itemAbilityCosts.resource.id: { + const resource = r.target.system.resource; + let max = Number(resource.max); + if (!Number.isFinite(max) && resource.max) { + try { + max = Roll.safeEval(Roll.replaceFormulaData(resource.max, r.target.getRollData())); + } catch { + max = null; + } + } + const hasMax = Number.isFinite(max) && max > 0; + if (r.clear) { + return { + path: 'system.resource.value', + value: hasMax ? max : resource.value + }; + } + const newValue = resource.value + r.value; return { path: 'system.resource.value', - value: r.target.system.resource.value + r.value + value: Math.max(hasMax ? Math.min(newValue, max) : newValue, 0) }; + } case CONFIG.DH.GENERAL.itemAbilityCosts.quantity.id: return { path: 'system.quantity', diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index 9b21d3ba..be4ec9b2 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -45,9 +45,10 @@ export default class DamageField extends fields.SchemaField { return; let formulas = this.damage.parts.map(p => ({ - formula: DamageField.getFormulaValue.call(this, p, config).getFormula(this.actor), + formula: p.fullRestore ? '0' : DamageField.getFormulaValue.call(this, p, config).getFormula(this.actor), damageTypes: p.applyTo === 'hitPoints' && !p.type.size ? new Set(['physical']) : p.type, - applyTo: p.applyTo + applyTo: p.applyTo, + fullRestore: p.fullRestore })); if (!formulas.length) return false; @@ -67,6 +68,7 @@ export default class DamageField extends fields.SchemaField { if (DamageField.getAutomation() === CONFIG.DH.SETTINGS.actionAutomationChoices.always.id) damageConfig.dialog.configure = false; + if (formulas.every(f => f.fullRestore)) damageConfig.dialog.configure = false; if (config.hasSave) config.onSave = damageConfig.onSave = this.save.damageMod; damageConfig.source.message = messageId; @@ -297,6 +299,10 @@ export class DHResourceData extends foundry.abstract.DataModel { initial: false, label: 'DAGGERHEART.ACTIONS.Settings.resultBased.label' }), + fullRestore: new fields.BooleanField({ + initial: false, + label: 'DAGGERHEART.ACTIONS.Settings.fullRestore.label' + }), value: new fields.EmbeddedDataField(DHActionDiceData), valueAlt: new fields.EmbeddedDataField(DHActionDiceData) }; diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 30901374..def7d5cd 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -766,17 +766,21 @@ export default class DhpActor extends Actor { Object.entries(healings).forEach(([key, healing]) => { healing.parts.forEach(part => { const update = updates.find(u => u.key === key); - if (update) update.value += part.total; - else updates.push({ value: part.total, key }); + if (update) { + update.value += part.total; + update.clear ||= !!part.fullRestore; + } else updates.push({ value: part.total, key, clear: !!part.fullRestore }); }); }); - updates.forEach( - u => - (u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false) - ? u.value * -1 - : u.value) - ); + updates.forEach(u => { + if (u.key === CONFIG.DH.GENERAL.healingTypes.weaponResource.id) return; + u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false) + ? u.value * -1 + : u.value; + }); + + this.convertResourceHealingToReload(updates); await this.modifyResource(updates); @@ -802,7 +806,7 @@ export default class DhpActor extends Actor { resources.forEach(r => { if (r.itemId) { const { path, value } = game.system.api.fields.ActionFields.CostField.getItemIdCostUpdate(r); - updates.items[r.key] = { + updates.items[`${r.itemId}-${r.key}`] = { target: r.target, resources: { [path]: value } }; @@ -873,6 +877,22 @@ export default class DhpActor extends Actor { return damage >= this.system.damageThresholds.severe ? 3 : damage >= this.system.damageThresholds.major ? 2 : 1; } + convertResourceHealingToReload(updates) { + const resourceIndex = updates.findIndex(u => u.key === CONFIG.DH.GENERAL.healingTypes.weaponResource.id); + if (resourceIndex === -1) return; + const [reload] = updates.splice(resourceIndex, 1); + const weapons = this.items.filter(i => i.type === 'weapon' && i.system.equipped && i.system.resource); + for (const weapon of weapons) { + updates.push({ + key: CONFIG.DH.GENERAL.itemAbilityCosts.resource.id, + value: reload.value, + clear: reload.clear, + itemId: weapon.id, + target: weapon + }); + } + } + convertStressDamageToHP(resources) { const stressDamage = resources.find(r => r.key === 'stress'), newValue = this.system.resources.stress.value + stressDamage.value; diff --git a/templates/actionTypes/damage.hbs b/templates/actionTypes/damage.hbs index 03300840..cbdf2278 100644 --- a/templates/actionTypes/damage.hbs +++ b/templates/actionTypes/damage.hbs @@ -31,6 +31,10 @@ {{/unless}} + {{#if (eq dmg.applyTo 'weaponResource')}} + {{formField ../fields.fullRestore value=dmg.fullRestore name=(concat ../path "damage.parts." dmg.applyTo ".fullRestore") localize=true classes="checkbox"}} + {{/if}} + {{#unless dmg.fullRestore}} {{#if (and (not @root.isNPC) @root.hasRoll (not dmg.base))}} {{formField ../fields.resultBased value=dmg.resultBased name=(concat "damage.parts." dmg.applyTo ".resultBased") localize=true classes="checkbox"}} {{/if}} @@ -48,6 +52,7 @@ {{else}} {{> formula fields=../fields.value.fields type=../fields.type dmg=dmg source=dmg.value target="value" key=dmg.applyTo path=../path}} {{/if}} + {{/unless}} {{#if (and (eq dmg.applyTo 'hitPoints') (ne @root.source.type 'healing'))}} {{formField ../fields.type value=dmg.type name=(concat ../path "damage.parts." dmg.applyTo ".type") localize=true}} diff --git a/templates/ui/chat/damageSummary.hbs b/templates/ui/chat/damageSummary.hbs index 721f153f..a3458185 100644 --- a/templates/ui/chat/damageSummary.hbs +++ b/templates/ui/chat/damageSummary.hbs @@ -8,7 +8,15 @@