Merged with v14-Dev

This commit is contained in:
WBHarry 2026-03-22 11:21:51 +01:00
commit 08f3dd04e1
99 changed files with 1989 additions and 545 deletions

View file

@ -1,5 +1,5 @@
import { itemAbleRollParse } from '../helpers/utils.mjs';
import { RefreshType, socketEvent } from '../systemRegistration/socket.mjs';
import { RefreshType } from '../systemRegistration/socket.mjs';
export default class DhActiveEffect extends foundry.documents.ActiveEffect {
/* -------------------------------------------- */
@ -11,6 +11,8 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
const conditionalSuspended = game.system.api.data.activeEffects.EffectConditionals.isConditionalSuspended(this);
if (conditionalSuspended) return true;
if (this.system.isSuppressed === true) return true;
// If this is a copied effect from an attachment, never suppress it
// (These effects have attachmentSource metadata)
if (this.flags?.daggerheart?.attachmentSource) {
@ -18,7 +20,7 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
}
// Then apply the standard suppression rules
if (['weapon', 'armor'].includes(this.parent?.type)) {
if (['weapon', 'armor'].includes(this.parent?.type) && this.transfer) {
return !this.parent.system.equipped;
}
@ -79,7 +81,7 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
throw new Error('The array of sub-types to restrict to must not be empty.');
}
const creatableEffects = ['base'];
const creatableEffects = types || ['base'];
const documentTypes = this.TYPES.filter(type => creatableEffects.includes(type)).map(type => {
const labelKey = `TYPES.ActiveEffect.${type}`;
const label = game.i18n.has(labelKey) ? game.i18n.localize(labelKey) : type;
@ -164,9 +166,9 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
super.applyChangeField(model, change, field);
}
_applyLegacy(actor, change, changes) {
static _applyChangeUnguided(actor, change, changes, options) {
change.value = DhActiveEffect.getChangeValue(actor, change, change.effect);
super._applyLegacy(actor, change, changes);
super._applyChangeUnguided(actor, change, changes, options);
}
static getChangeValue(model, change, effect) {

View file

@ -598,8 +598,7 @@ export default class DhpActor extends Actor {
const availableStress = this.system.resources.stress.max - this.system.resources.stress.value;
const canUseArmor =
this.system.armor &&
this.system.armor.system.marks.value < this.system.armorScore &&
this.system.armorScore.value < this.system.armorScore.max &&
type.every(t => this.system.armorApplicableDamageTypes[t] === true);
const canUseStress = Object.keys(stressDamageReduction).reduce((acc, x) => {
const rule = stressDamageReduction[x];
@ -639,12 +638,7 @@ export default class DhpActor extends Actor {
const hpDamage = updates.find(u => u.key === CONFIG.DH.GENERAL.healingTypes.hitPoints.id);
if (hpDamage?.value) {
hpDamage.value = this.convertDamageToThreshold(hpDamage.value);
if (
this.type === 'character' &&
!isDirect &&
this.system.armor &&
this.#canReduceDamage(hpDamage.value, hpDamage.damageTypes)
) {
if (this.type === 'character' && !isDirect && this.#canReduceDamage(hpDamage.value, hpDamage.damageTypes)) {
const armorSlotResult = await this.owner.query(
'armorSlot',
{
@ -657,12 +651,10 @@ export default class DhpActor extends Actor {
}
);
if (armorSlotResult) {
const { modifiedDamage, armorSpent, stressSpent } = armorSlotResult;
const { modifiedDamage, armorChanges, stressSpent } = armorSlotResult;
updates.find(u => u.key === 'hitPoints').value = modifiedDamage;
if (armorSpent) {
const armorUpdate = updates.find(u => u.key === 'armor');
if (armorUpdate) armorUpdate.value += armorSpent;
else updates.push({ value: armorSpent, key: 'armor' });
for (const armorChange of armorChanges) {
updates.push({ value: armorChange.amount, key: 'armor', uuid: armorChange.uuid });
}
if (stressSpent) {
const stressUpdate = updates.find(u => u.key === 'stress');
@ -809,12 +801,8 @@ export default class DhpActor extends Actor {
);
break;
case 'armor':
if (this.system.armor?.system?.marks) {
updates.armor.resources['system.marks.value'] = Math.max(
Math.min(valueFunc(this.system.armor.system.marks, r), this.system.armorScore),
0
);
}
if (!r.uuid) this.system.updateArmorValue(r);
else this.system.updateArmorEffectValue(r);
break;
default:
if (this.system.resources?.[r.key]) {
@ -1030,4 +1018,20 @@ export default class DhpActor extends Actor {
return allTokens;
}
/**@inheritdoc */
*allApplicableEffects({ noSelfArmor, noTransferArmor } = {}) {
for (const effect of this.effects) {
if (!noSelfArmor || effect.type !== 'armor') yield effect;
}
for (const item of this.items) {
for (const effect of item.effects) {
if (effect.transfer && (!noTransferArmor || effect.type !== 'armor')) yield effect;
}
}
}
applyActiveEffects(phase) {
super.applyActiveEffects(phase);
}
}

View file

@ -230,4 +230,14 @@ export default class DHItem extends foundry.documents.Item {
async _preDelete() {
this.deleteTriggers();
}
/** @inheritDoc */
static migrateData(source) {
const documentClass = game.system.api.data.items[`DH${source.type?.capitalize()}`];
if (documentClass?.migrateDocumentData) {
documentClass.migrateDocumentData(source);
}
return super.migrateData(source);
}
}