Corrected actor.takeDamage and actor.takeHealing

This commit is contained in:
WBHarry 2026-07-18 13:54:16 +02:00
parent b2bf102443
commit 21daa7f3c0
4 changed files with 52 additions and 45 deletions

View file

@ -77,7 +77,10 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application
static updateRollConfiguration(_event, _, formData) {
const data = foundry.utils.expandObject(formData.object);
if (this.config.damageFormula)
foundry.utils.mergeObject(this.config.damageFormula, data.damageFormula);
foundry.utils.mergeObject(this.config.resourceFormulas, data.resourceFormulas);
foundry.utils.mergeObject(this.config.modifiers, data.modifiers);
this.config.selectedMessageMode = data.selectedMessageMode;

View file

@ -99,7 +99,7 @@ export default class DamageField extends fields.SchemaField {
: actor.prototypeToken;
if (config.hasHealing)
damagePromises.push(
actor.takeHealing(config.damage.types).then(updates => targetDamage.push({ token, updates }))
actor.takeHealing(config.damage).then(updates => targetDamage.push({ token, updates }))
);
else {
const configDamage = config.damage.clone();

View file

@ -27,10 +27,14 @@ export default class DamageRoll extends DHRoll {
return roll.roll;
}
if (!config.damage) config.damage = { main: null, resources: {} };
if (config.damageFormula) {
config.damage.main = await evaluateRoll(config.damageFormula);
config.damage.main.options = { damageTypes:
config.damageFormula.damageTypes ? [...config.damageFormula.damageTypes] : []
};
}
for (const roll of config.resourceFormulas) {
config.damage.resources[roll.applyTo] = await evaluateRoll(roll);

View file

@ -662,23 +662,16 @@ export default class DhpActor extends Actor {
if (Hooks.call(`${CONFIG.DH.id}.postCalculateDamage`, this, damages) === false) return null;
// Convert deducted resources and damage to a record of updates, merging damage to hp with hp marked
// Convert deducted resources to a record of updates. Return if nothing to do.
const updates = Object.entries(damages.resources).map(([key, damage]) => ({ key, value: damage.total }));
if (damages.main) {
const existing = updates.find(u => u.key === CONFIG.DH.GENERAL.healingTypes.hitPoints.id);
const value = this.convertDamageToThreshold(damages.main.total);
const damageTypes = new Set(damages.main.options.damageTypes);
if (existing) {
existing.value += value;
existing.damageTypes = damageTypes;
} else {
updates.push({ value, damageTypes, key: CONFIG.DH.GENERAL.healingTypes.hitPoints.id });
}
}
if (!updates.some(u => u.value)) return; // early return if nothing to do
if (!updates.some(u => u.value) && !damages.main) return;
const hpDamage = updates.find(u => u.key === CONFIG.DH.GENERAL.healingTypes.hitPoints.id);
if (hpDamage?.value) {
if (damages.main) {
const hpDamage = {
value: this.convertDamageToThreshold(damages.main.total),
damageTypes: new Set(damages.main.options.damageTypes),
key: CONFIG.DH.GENERAL.healingTypes.hitPoints.id
};
if (this.type === 'character' && !isDirect && this.#canReduceDamage(hpDamage.total, hpDamage.damageTypes)) {
const armorSlotResult = await this.owner.query(
'armorSlot',
@ -712,6 +705,15 @@ export default class DhpActor extends Actor {
hpDamage.value = Math.max(0, hpDamage.value - 1);
}
}
// Merge existing hitPoint deduction with finalised damage deduction
const existing = updates.find(u => u.key === CONFIG.DH.GENERAL.healingTypes.hitPoints.id);
if (existing) {
existing.value += hpDamage.value;
existing.damageTypes = hpDamage.damageTypes;
} else {
updates.push(hpDamage);
}
}
const results = await game.system.registeredTriggers.runTrigger(
@ -738,6 +740,28 @@ export default class DhpActor extends Actor {
return updates;
}
async takeHealing(healings) {
if (Hooks.call(`${CONFIG.DH.id}.preTakeHealing`, this, healings) === false) return null;
const updates = Object.entries(healings.resources).map(([key, damage]) => ({
key,
value: damage.total
}));
updates.forEach(
u =>
(u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false)
? u.value * -1
: u.value)
);
await this.modifyResource(updates);
if (Hooks.call(`${CONFIG.DH.id}.postTakeHealing`, this, updates) === false) return null;
return updates;
}
calculateDamage(baseDamage, type) {
if (this.canResist(type, 'immunity')) return 0;
if (this.canResist(type, 'resistance')) baseDamage = Math.ceil(baseDamage / 2);
@ -762,30 +786,6 @@ export default class DhpActor extends Actor {
return reduction === Infinity ? 0 : reduction;
}
async takeHealing(healings) {
if (Hooks.call(`${CONFIG.DH.id}.preTakeHealing`, this, healings) === false) return null;
const updates = [];
Object.entries(healings).forEach(([key, healing]) => {
const update = updates.find(u => u.key === key);
if (update) update.value += healing.roll.total;
else updates.push({ value: healing.roll.total, key });
});
updates.forEach(
u =>
(u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false)
? u.value * -1
: u.value)
);
await this.modifyResource(updates);
if (Hooks.call(`${CONFIG.DH.id}.postTakeHealing`, this, updates) === false) return null;
return updates;
}
/**
* Resources are modified asynchronously, so be careful not to update the same resource in
* quick succession.