Maybe simplify API

This commit is contained in:
Carlos Fernandez 2026-07-18 20:12:42 -04:00
parent 47847b5b8d
commit 32abcfb0c4

View file

@ -622,6 +622,11 @@ export default class DhpActor extends Actor {
return rollData; return rollData;
} }
/**
* Checks to see if damage can be reduced in one way or another.
* @param {number} hpDamage the amount of marked hp that will be marked
* @param {Set<string>} types a list of damage types
*/
#canReduceDamage(hpDamage, types) { #canReduceDamage(hpDamage, types) {
const { stressDamageReduction, disabledArmor, reduceSeverity, thresholdImmunities } = const { stressDamageReduction, disabledArmor, reduceSeverity, thresholdImmunities } =
this.system.rules.damageReduction; this.system.rules.damageReduction;
@ -648,31 +653,33 @@ export default class DhpActor extends Actor {
return canUseArmor || canUseStress || hasReduceSeverity || hasThresholdImmunity; return canUseArmor || canUseStress || hasReduceSeverity || hasThresholdImmunity;
} }
async takeDamage(damages, isDirect = false) { async takeDamage(args, isDirect = false) {
if (Hooks.call(`${CONFIG.DH.id}.preTakeDamage`, this, damages) === false) return null; args = this.#parseDamageArgs(args);
if (Hooks.call(`${CONFIG.DH.id}.preTakeDamage`, this, args) === false) return null;
if (this.type === 'companion') { if (this.type === 'companion') {
await this.modifyResource([{ value: 1, key: 'stress' }]); await this.modifyResource([{ value: 1, key: 'stress' }]);
return; return;
} }
if (damages.main) { const updates = args.resourceUpdates;
damages.main.total = this.calculateDamage(damages.main.total, damages.main.damageTypes); if (args.main) {
// todo: avoid side effects, but hook currently requires it
args.main.value = this.calculateDamage(args.main.value, args.main.damageTypes);
} }
if (Hooks.call(`${CONFIG.DH.id}.postCalculateDamage`, this, damages) === false) return null; if (Hooks.call(`${CONFIG.DH.id}.postCalculateDamage`, this, args) === false) return null;
// Convert deducted resources to a record of updates. Return if nothing to do. // 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 (!updates.some(u => u.value) && !args.main) return;
if (!updates.some(u => u.value) && !damages.main) return;
if (damages.main) { if (args.main) {
const hpDamage = { const hpDamage = {
value: this.convertDamageToThreshold(damages.main.total), value: this.convertDamageToThreshold(args.main.value),
damageTypes: new Set(damages.main.options.damageTypes), damageTypes: new Set(args.main.damageTypes),
key: CONFIG.DH.GENERAL.healingTypes.hitPoints.id key: CONFIG.DH.GENERAL.healingTypes.hitPoints.id
}; };
if (this.type === 'character' && !isDirect && this.#canReduceDamage(hpDamage.total, hpDamage.damageTypes)) { if (this.type === 'character' && !isDirect && this.#canReduceDamage(hpDamage.value, hpDamage.damageTypes)) {
const armorSlotResult = await this.owner.query( const armorSlotResult = await this.owner.query(
'armorSlot', 'armorSlot',
{ {
@ -743,18 +750,12 @@ export default class DhpActor extends Actor {
async takeHealing(healings) { async takeHealing(healings) {
if (Hooks.call(`${CONFIG.DH.id}.preTakeHealing`, this, healings) === false) return null; if (Hooks.call(`${CONFIG.DH.id}.preTakeHealing`, this, healings) === false) return null;
const updates = Object.entries(healings.resources).map(([key, damage]) => ({ const resources = 'resources' in healings ? healings.resources : healings;
key, const updates = this.#parseDamageArgs({ resources }).resourceUpdates;
value: damage.total for (const u of updates) {
})); const shouldFlip = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false);
u.value = shouldFlip ? u.value * -1 : u.value;
updates.forEach( }
u =>
(u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false)
? u.value * -1
: u.value)
);
await this.modifyResource(updates); await this.modifyResource(updates);
if (Hooks.call(`${CONFIG.DH.id}.postTakeHealing`, this, updates) === false) return null; if (Hooks.call(`${CONFIG.DH.id}.postTakeHealing`, this, updates) === false) return null;
@ -762,6 +763,20 @@ export default class DhpActor extends Actor {
return updates; return updates;
} }
/** Parse damage args that may be coming from takeHealing or takeDamage. Used to simplify macro usage and roll vs non-roll usage */
#parseDamageArgs(args = {}) {
const damageRoll = 'total' in args ? args : (args.main ?? args.damage);
const damageValue = typeof damageRoll === 'number' ? damageRoll : damageRoll?.total;
const damageTypes = Array.from(damageRoll?.options?.damageTypes ?? damageRoll?.damageTypes ?? []);
const main = typeof damageValue === 'number' ? { key: 'damage', value: damageValue, damageTypes } : null;
const resourceUpdates = Object.entries(args.resources ?? {}).map(([key, damage]) => ({
key,
value: typeof damage === 'number' ? damage : damage?.total ?? 0
}));
return { main, resourceUpdates };
}
calculateDamage(baseDamage, type) { calculateDamage(baseDamage, type) {
if (this.canResist(type, 'immunity')) return 0; if (this.canResist(type, 'immunity')) return 0;
if (this.canResist(type, 'resistance')) baseDamage = Math.ceil(baseDamage / 2); if (this.canResist(type, 'resistance')) baseDamage = Math.ceil(baseDamage / 2);