diff --git a/module/applications/advancement/advancement-config.mjs b/module/applications/advancement/advancement-config.mjs index d432cf84fa..bb98f8a3f7 100644 --- a/module/applications/advancement/advancement-config.mjs +++ b/module/applications/advancement/advancement-config.mjs @@ -87,7 +87,7 @@ export default class AdvancementConfig extends FormApplication { * @param {object} configuration Configuration object. * @returns {object} Modified configuration. */ - prepareConfigurationUpdate(configuration) { + async prepareConfigurationUpdate(configuration) { return configuration; } @@ -116,7 +116,7 @@ export default class AdvancementConfig extends FormApplication { delete updates.data; updates = { ...updates, ...data }; } - if ( updates.configuration ) updates.configuration = this.prepareConfigurationUpdate(updates.configuration); + if ( updates.configuration ) updates.configuration = await this.prepareConfigurationUpdate(updates.configuration); await this.advancement.update(updates); this.render(); } diff --git a/module/applications/advancement/item-choice-config.mjs b/module/applications/advancement/item-choice-config.mjs index a50d4a7d24..1572836365 100644 --- a/module/applications/advancement/item-choice-config.mjs +++ b/module/applications/advancement/item-choice-config.mjs @@ -30,8 +30,19 @@ export default class ItemChoiceConfig extends AdvancementConfig { /* -------------------------------------------- */ /** @inheritdoc */ - prepareConfigurationUpdate(configuration) { + async prepareConfigurationUpdate(configuration) { if ( configuration.choices ) configuration.choices = this.constructor._cleanedObject(configuration.choices); + + // Ensure items are still valid if type restriction or spell restriction are changed + configuration.pool ??= this.advancement.data.configuration.pool; + configuration.pool = await configuration.pool.reduce(async (pool, uuid) => { + const item = await fromUuid(uuid); + if ( this.advancement._verifyItemType(item, { + restriction: configuration.type, spellLevel: configuration.spell?.level ?? false, error: false + }) ) return [...await pool, uuid]; + return pool; + }, []); + return configuration; } diff --git a/module/documents/advancement/item-choice.mjs b/module/documents/advancement/item-choice.mjs index 35e27d3b3f..986bdc925b 100644 --- a/module/documents/advancement/item-choice.mjs +++ b/module/documents/advancement/item-choice.mjs @@ -143,28 +143,40 @@ export default class ItemChoiceAdvancement extends Advancement { /** * Verify that the provided item can be used with this advancement based on the configuration. - * @param {Item5e} item Item that needs to be tested. - * @throws An error if the item is invalid. + * @param {Item5e} item Item that needs to be tested. + * @param {object} config + * @param {string} config.restriction Type restriction on this advancement. + * @param {string} config.spellLevel Spell level limitation. + * @param {boolean} [config.error=true] Should an error be thrown when an invalid type is encountered? + * @returns {boolean} Is this type valid? + * @throws An error if the item is invalid and warn is `true`. */ - _verifyItemType(item) { + _verifyItemType(item, { restriction, spellLevel, error=true }={}) { + restriction ??= this.data.configuration.type; + spellLevel ??= this.data.configuration.spell?.level; + // Type restriction is set and the item type does not match the selected type - const restriction = this.data.configuration.type; if ( restriction && (restriction !== item.type) ) { const type = game.i18n.localize(`ITEM.Type${restriction.capitalize()}`); - throw new Error(game.i18n.format("DND5E.AdvancementItemChoiceTypeWarning", { type })); + if ( error ) throw new Error(game.i18n.format("DND5E.AdvancementItemChoiceTypeWarning", { type })); + return false; } // Item is not one of the valid types if ( !this.constructor.VALID_TYPES.has(item.type) ) { const type = game.i18n.localize(`ITEM.Type${item.type.capitalize()}`); - throw new Error(game.i18n.format("DND5E.AdvancementItemTypeInvalidWarning", { type })); + if ( error ) throw new Error(game.i18n.format("DND5E.AdvancementItemTypeInvalidWarning", { type })); + return false; } // If spell level is restricted, ensure the spell is of the appropriate level - const l = parseInt(this.data.configuration.spell?.level); + const l = parseInt(spellLevel); if ( (restriction === "spell") && Number.isNumeric(l) && (item.system.level !== l) ) { const level = CONFIG.DND5E.spellLevels[l]; - throw new Error(game.i18n.format("DND5E.AdvancementItemChoiceSpellLevelSpecificWarning", { level })); + if ( error ) throw new Error(game.i18n.format("DND5E.AdvancementItemChoiceSpellLevelSpecificWarning", { level })); + return false; } + + return true; } }