diff --git a/lang/en.json b/lang/en.json index 111f9f18d3..6916e4ba0d 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1790,7 +1790,7 @@ "hint": "Custom formula or flat value for defining the save DC." }, "CustomFormula": "Custom Formula", - "DefaultFormula": "8 + Ability + Proficiency" + "DefaultFormula": "8 + @mod + @prof" } } } diff --git a/module/applications/activity/activity-sheet.mjs b/module/applications/activity/activity-sheet.mjs index fa7fddc818..19acfdeaa6 100644 --- a/module/applications/activity/activity-sheet.mjs +++ b/module/applications/activity/activity-sheet.mjs @@ -333,7 +333,7 @@ export default class ActivitySheet extends Application5e { context.tab = context.tabs.effect; if ( context.activity.effects ) { - const appliedEffects = new Set(context.activity.effects?.map(e => e.id) ?? []); + const appliedEffects = new Set(context.activity.effects?.map(e => e._id) ?? []); context.allEffects = this.item.effects.map(effect => ({ value: effect.id, label: effect.name, selected: appliedEffects.has(effect.id) })); @@ -548,7 +548,7 @@ export default class ActivitySheet extends Application5e { transfer: false }; const [created] = await this.item.createEmbeddedDocuments("ActiveEffect", [effectData]); - this.activity.update({ effects: [...this.activity.toObject().effects, { id: created.id }] }); + this.activity.update({ effects: [...this.activity.toObject().effects, { _id: created.id }] }); } /* -------------------------------------------- */ @@ -614,7 +614,7 @@ export default class ActivitySheet extends Application5e { const effectId = target.closest("[data-effect-id]")?.dataset.effectId; const result = await this.item.effects.get(effectId)?.deleteDialog(); if ( result instanceof ActiveEffect ) { - const effects = this.activity.toObject().effects.filter(e => e.id !== effectId); + const effects = this.activity.toObject().effects.filter(e => e._id !== effectId); this.activity.update({ effects }); } } @@ -681,10 +681,10 @@ export default class ActivitySheet extends Application5e { } if ( foundry.utils.hasProperty(submitData, "appliedEffects") ) { const effects = submitData.effects ?? this.activity.toObject().effects; - submitData.effects = effects.filter(e => submitData.appliedEffects.includes(e.id)); - for ( const id of submitData.appliedEffects ) { - if ( submitData.effects.find(e => e.id === id) ) continue; - submitData.effects.push({ id }); + submitData.effects = effects.filter(e => submitData.appliedEffects.includes(e._id)); + for ( const _id of submitData.appliedEffects ) { + if ( submitData.effects.find(e => e._id === _id) ) continue; + submitData.effects.push({ _id }); } } return submitData; diff --git a/module/data/activity/_module.mjs b/module/data/activity/_module.mjs index 08e8eaeee2..f4a783cbfc 100644 --- a/module/data/activity/_module.mjs +++ b/module/data/activity/_module.mjs @@ -4,3 +4,5 @@ export {default as AttackActivityData} from "./attack-data.mjs"; export {default as SaveActivityData} from "./save-data.mjs"; export {default as SummonActivityData} from "./summon-data.mjs"; export {default as UtilityActivityData} from "./utility-data.mjs"; + +export {default as AppliedEffectField} from "./fields/applied-effect-field.mjs"; diff --git a/module/data/activity/base-activity.mjs b/module/data/activity/base-activity.mjs index 5d72213001..8fd9679123 100644 --- a/module/data/activity/base-activity.mjs +++ b/module/data/activity/base-activity.mjs @@ -1,6 +1,7 @@ import { formatNumber } from "../../utils.mjs"; import FormulaField from "../fields/formula-field.mjs"; import UsesField from "../shared/uses-field.mjs"; +import AppliedEffectField from "./fields/applied-effect-field.mjs"; const { ArrayField, BooleanField, DocumentIdField, FilePathField, NumberField, SchemaField, StringField @@ -23,7 +24,7 @@ const { * Data for effects that can be applied. * * @typedef {object} EffectApplicationData - * @property {string} effect ID of the effect to apply. + * @property {string} _id ID of the effect to apply. */ /** @@ -117,7 +118,7 @@ export default class BaseActivityData extends foundry.abstract.DataModel { units: new StringField({ initial: "inst" }), special: new StringField() }), - effects: new ArrayField(new SchemaField(this.defineEffectSchema())), + effects: new ArrayField(new AppliedEffectField()), range: new SchemaField({ value: new FormulaField({ deterministic: true }), units: new StringField(), @@ -145,18 +146,6 @@ export default class BaseActivityData extends foundry.abstract.DataModel { }; } - /* -------------------------------------------- */ - - /** - * Return the fields that will be included in the schema for applied effects. - * @returns {Record} - */ - static defineEffectSchema() { - return { - id: new DocumentIdField() - }; - } - /* -------------------------------------------- */ /* Data Preparation */ /* -------------------------------------------- */ @@ -169,7 +158,7 @@ export default class BaseActivityData extends foundry.abstract.DataModel { this.img = this.img || this.metadata?.img; const item = this.item; this.effects?.forEach(e => Object.defineProperty(e, "effect", { - get() { return item.effects.get(e.id); }, + get() { return item.effects.get(e._id); }, configurable: true })); UsesField.prepareData.call(this, this.getRollData({ deterministic: true })); diff --git a/module/data/activity/fields/applied-effect-field.mjs b/module/data/activity/fields/applied-effect-field.mjs new file mode 100644 index 0000000000..f20e9023c6 --- /dev/null +++ b/module/data/activity/fields/applied-effect-field.mjs @@ -0,0 +1,15 @@ +const { DocumentIdField, SchemaField } = foundry.data.fields; + +/** + * Field for storing an active effects applied by an activity. + * + * @property {string} _id ID of the effect to apply. + */ +export default class AppliedEffectField extends SchemaField { + constructor(fields={}, options={}) { + super({ + _id: new DocumentIdField(), + ...fields + }, options); + } +} diff --git a/module/data/activity/save-data.mjs b/module/data/activity/save-data.mjs index 338403e7f3..fe68e6902d 100644 --- a/module/data/activity/save-data.mjs +++ b/module/data/activity/save-data.mjs @@ -1,6 +1,7 @@ import FormulaField from "../fields/formula-field.mjs"; import DamageField from "../shared/damage-field.mjs"; import BaseActivityData from "./base-activity.mjs"; +import AppliedEffectField from "./fields/applied-effect-field.mjs"; const { ArrayField, BooleanField, SchemaField, StringField } = foundry.data.fields; @@ -12,7 +13,7 @@ const { ArrayField, BooleanField, SchemaField, StringField } = foundry.data.fiel /** * Data model for an save activity. * - * @property {string} ability Ability used to make the attack and determine damage. + * @property {string} ability Make the saving throw with this ability. * @property {object} damage * @property {string} damage.onSave How much damage is done on a successful save? * @property {DamageData[]} damage.parts Parts of damage to inflict. @@ -32,6 +33,9 @@ export default class SaveActivityData extends BaseActivityData { onSave: new StringField(), parts: new ArrayField(new DamageField()) }), + effects: new ArrayField(new AppliedEffectField({ + onSave: new BooleanField() + })), save: new SchemaField({ dc: new SchemaField({ calculation: new StringField(), @@ -41,19 +45,6 @@ export default class SaveActivityData extends BaseActivityData { }; } - /* -------------------------------------------- */ - - /** - * Return the fields that will be included in the schema for applied effects. - * @returns {Record} - */ - static defineEffectSchema() { - return { - ...super.defineEffectSchema(), - onSave: new BooleanField() - }; - } - /* -------------------------------------------- */ /* Data Preparation */ /* -------------------------------------------- */ diff --git a/templates/activity/parts/activity-effects.hbs b/templates/activity/parts/activity-effects.hbs index 653b0d3c31..389a712580 100644 --- a/templates/activity/parts/activity-effects.hbs +++ b/templates/activity/parts/activity-effects.hbs @@ -5,7 +5,7 @@