[V14] Effect Stacking (#1667)

* Added the ability for effects to have stacks

* Fixed effect stacking

* Improved token overlay spacing

* Compendium updaetes

* Simplify effect click event (#1748)

* Fixed a bunch of deprecations

* Corrected AgileScout Beastform json data

* Updated TokenHUD to the new v14

* Removed DestroyOnEmpty from consumables

* Fixed so that tooltips don't get stuck (#1745)

* [Feature] TagTeam Partial Rendering (#1735)

* I done did it, I think

* Think I fixed the partial rendering bug for gm->player

* [V14] 1743 - Damage Update Error (#1746)

* Fixed DamageParts causing errors on update

* Fixed ActionBaseConfig error when no damage present on the action

* Fix removal of damage field

* Removed unneccessary default value function for parts

---------

Co-authored-by: Carlos Fernandez <cfern1990@gmail.com>

* Simplify effect click event

---------

Co-authored-by: WBHarry <williambjrklund@gmail.com>
Co-authored-by: WBHarry <89362246+WBHarry@users.noreply.github.com>

* Fixed stacking-value pointer event

* Set the stacking value in EffectsDisplay to be tabular-nums for monospacing

* Made baseEffect.stacking nullable instead of having an enabled property

* .

* Fixed so that actor._onUpdateDescantDocuments re-renders the EffectDisplay if effects were updated

---------

Co-authored-by: Carlos Fernandez <CarlosFdez@users.noreply.github.com>
This commit is contained in:
WBHarry 2026-03-25 13:54:14 +01:00 committed by GitHub
parent 64ce615116
commit aa1d117c43
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 349 additions and 204 deletions

View file

@ -108,6 +108,18 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
update.img = 'icons/magic/life/heart-cross-blue.webp';
}
const existingEffect = this.actor.effects.find(x => x.origin === data.origin);
const stacks = Boolean(data.system?.stacking);
if (existingEffect && !stacks) return false;
if (existingEffect && stacks) {
const incrementedValue = existingEffect.system.stacking.value + 1;
await existingEffect.update({
'system.stacking.value': Math.min(incrementedValue, existingEffect.system.stacking.max ?? Infinity)
});
return false;
}
const statuses = Object.keys(data.statuses ?? {});
const immuneStatuses =
statuses.filter(
@ -184,7 +196,10 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
} catch (_) {}
}
const evalValue = this.effectSafeEval(itemAbleRollParse(key, parseModel, effect.parent));
const stackingParsedValue = effect.system.stacking
? Roll.replaceFormulaData(key, { stacks: effect.system.stacking.value })
: key;
const evalValue = itemAbleRollParse(stackingParsedValue, parseModel, effect.parent);
return evalValue ?? key;
}

View file

@ -122,6 +122,14 @@ export default class DhpActor extends Actor {
}
}
_onUpdateDescendantDocuments(parent, collection, documents, changes, options, userId) {
if (collection === 'effects') {
ui.effectsDisplay.render();
}
super._onUpdateDescendantDocuments(parent, collection, documents, changes, options, userId);
}
async updateLevel(newLevel) {
if (!['character', 'companion'].includes(this.type) || newLevel === this.system.levelData.level.changed) return;