diff --git a/dnd5e.mjs b/dnd5e.mjs index f71c992b61..c5f1e74f7e 100644 --- a/dnd5e.mjs +++ b/dnd5e.mjs @@ -154,6 +154,7 @@ Hooks.once("init", function() { // Hook up system data types Object.assign(CONFIG.ActiveEffect.changeTypes, DND5E.activeEffectChangeTypes); Object.assign(CONFIG.ActiveEffect.dataModels, dataModels.activeEffect.config); + Object.assign(CONFIG.ActiveEffect.phases, dataModels.activeEffect.phases); CONFIG.Actor.dataModels = dataModels.actor.config; CONFIG.ChatMessage.dataModels = dataModels.chatMessage.config; CONFIG.Item.dataModels = dataModels.item.config; diff --git a/lang/en.json b/lang/en.json index 73f685c079..cf5b48b3c1 100644 --- a/lang/en.json +++ b/lang/en.json @@ -2755,6 +2755,12 @@ }, "Label": "Available Effects", "New": "New Effect", + "PHASES": { + "postAbilities": { + "label": "Post Abilities", + "hint": "Immediately after ability data has been prepared" + } + }, "Replacement": { "NoChange": "No Change", "Origin": "Origin", diff --git a/module/data/active-effect/_module.mjs b/module/data/active-effect/_module.mjs index 74414cf586..f85547190a 100644 --- a/module/data/active-effect/_module.mjs +++ b/module/data/active-effect/_module.mjs @@ -13,3 +13,10 @@ export const config = { condition: ConditionData, enchantment: EnchantmentData }; + +export const phases = { + postAbilities: { + label: "DND5E.EFFECT.PHASES.postAbilities.label", + hint: "DND5E.EFFECT.PHASES.postAbilities.hint" + } +}; diff --git a/module/data/active-effect/base.mjs b/module/data/active-effect/base.mjs index 17425cc802..e2cb340775 100644 --- a/module/data/active-effect/base.mjs +++ b/module/data/active-effect/base.mjs @@ -34,6 +34,18 @@ export default class BaseEffectData extends ActiveEffectDataModel { }; } + /* -------------------------------------------- */ + /* Data Preparation */ + /* -------------------------------------------- */ + + /** @inheritDoc */ + prepareBaseData() { + super.prepareBaseData(); + for ( const change of this.changes ) { + if ( change.value.includes?.("@item.uses.value") ) change.phase = "postAbilities"; + } + } + /* -------------------------------------------- */ /* Properties */ /* -------------------------------------------- */ diff --git a/module/data/actor/templates/common.mjs b/module/data/actor/templates/common.mjs index 531c9e7cd0..8e254b20df 100644 --- a/module/data/actor/templates/common.mjs +++ b/module/data/actor/templates/common.mjs @@ -385,6 +385,8 @@ export default class CommonTemplate extends ActorDataModel.mixin(CurrencyTemplat CommonTemplate.shimAbilityData(abl, id); } + + this.parent.applyActiveEffects("postAbilities"); } /* -------------------------------------------- */ diff --git a/module/data/item/consumable.mjs b/module/data/item/consumable.mjs index 6e8cca3cff..fb39a93bbf 100644 --- a/module/data/item/consumable.mjs +++ b/module/data/item/consumable.mjs @@ -244,7 +244,7 @@ export default class ConsumableData extends ItemDataModel.mixin( /** @inheritDoc */ prepareFinalData() { - this.prepareFinalActivityData(this.parent.getRollData({ deterministic: true })); + this.prepareFinalActivityData(); this.prepareFinalEquippableData(); } diff --git a/module/data/item/equipment.mjs b/module/data/item/equipment.mjs index 1b1cab0fd5..268cff4491 100644 --- a/module/data/item/equipment.mjs +++ b/module/data/item/equipment.mjs @@ -300,7 +300,7 @@ export default class EquipmentData extends ItemDataModel.mixin( /** @inheritDoc */ prepareFinalData() { - this.prepareFinalActivityData(this.parent.getRollData({ deterministic: true })); + this.prepareFinalActivityData(); this.prepareFinalEquippableData(); } diff --git a/module/data/item/facility.mjs b/module/data/item/facility.mjs index 15590cfb85..6b10885ef0 100644 --- a/module/data/item/facility.mjs +++ b/module/data/item/facility.mjs @@ -191,7 +191,7 @@ export default class FacilityData extends ItemDataModel.mixin(ActivitiesTemplate /** @inheritDoc */ prepareFinalData() { - this.prepareFinalActivityData(this.parent.getRollData({ deterministic: true })); + this.prepareFinalActivityData(); } /* -------------------------------------------- */ diff --git a/module/data/item/feat.mjs b/module/data/item/feat.mjs index 37fd782e82..227705a4db 100644 --- a/module/data/item/feat.mjs +++ b/module/data/item/feat.mjs @@ -283,7 +283,7 @@ export default class FeatData extends ItemDataModel.mixin( /** @inheritDoc */ prepareFinalData() { - this.prepareFinalActivityData(this.parent.getRollData({ deterministic: true })); + this.prepareFinalActivityData(); } /* -------------------------------------------- */ diff --git a/module/data/item/spell.mjs b/module/data/item/spell.mjs index 757cf7e15b..23be86b47a 100644 --- a/module/data/item/spell.mjs +++ b/module/data/item/spell.mjs @@ -496,7 +496,7 @@ export default class SpellData extends ItemDataModel.mixin(ActivitiesTemplate, I prepareFinalData() { const rollData = this.parent.getRollData({ deterministic: true }); const labels = this.parent.labels ??= {}; - this.prepareFinalActivityData(rollData); + this.prepareFinalActivityData(); ActivationField.prepareData.call(this, rollData, labels); DurationField.prepareData.call(this, rollData, labels); RangeField.prepareData.call(this, rollData, labels); diff --git a/module/data/item/templates/activities.mjs b/module/data/item/templates/activities.mjs index f7f9d3c507..e767fae423 100644 --- a/module/data/item/templates/activities.mjs +++ b/module/data/item/templates/activities.mjs @@ -304,12 +304,20 @@ export default class ActivitiesTemplate extends SystemDataModel { /* -------------------------------------------- */ /** - * Prepare final data for the activities & uses. + * Prepare final uses data. * @param {ItemRollData} rollData */ - prepareFinalActivityData(rollData) { + prepareUsesData(rollData=this.parent.getRollData({ deterministic: true })) { const labels = this.parent.labels; UsesField.prepareData.call(this, rollData, labels); + } + + /* -------------------------------------------- */ + + /** + * Prepare final data for the activities. + */ + prepareFinalActivityData() { for ( const activity of this.activities ) activity.prepareFinalData(); } diff --git a/module/data/item/tool.mjs b/module/data/item/tool.mjs index d9bf85da48..d3b1bf4a52 100644 --- a/module/data/item/tool.mjs +++ b/module/data/item/tool.mjs @@ -206,7 +206,7 @@ export default class ToolData extends ItemDataModel.mixin( /** @inheritDoc */ prepareFinalData() { - this.prepareFinalActivityData(this.parent.getRollData({ deterministic: true })); + this.prepareFinalActivityData(); this.prepareFinalEquippableData(); } diff --git a/module/data/item/weapon.mjs b/module/data/item/weapon.mjs index 299a626d95..f1fde080e2 100644 --- a/module/data/item/weapon.mjs +++ b/module/data/item/weapon.mjs @@ -494,7 +494,7 @@ export default class WeaponData extends ItemDataModel.mixin( /** @inheritDoc */ prepareFinalData() { - this.prepareFinalActivityData(this.parent.getRollData({ deterministic: true })); + this.prepareFinalActivityData(); this.prepareFinalEquippableData(); const labels = this.parent.labels ??= {}; diff --git a/module/documents/actor/actor.mjs b/module/documents/actor/actor.mjs index dbde177af4..b8d42dbdd9 100644 --- a/module/documents/actor/actor.mjs +++ b/module/documents/actor/actor.mjs @@ -392,6 +392,11 @@ export default class Actor5e extends SystemDocumentMixin(Actor) { } } + // Prepare item uses, if present + if ( phase === "postAbilities" ) { + this.items.forEach(item => item.system?.prepareUsesData?.()) + } + // Prepare final attributes & spellcasting so that they can be used/modified in "final" phase if ( phase === "final" ) { this.items.forEach(item => item.prepareFinalAttributes());