From 0508bf4188097294ffe960a1aa4feed5e1369b7c Mon Sep 17 00:00:00 2001 From: Nick Salyzyn Date: Sat, 20 Dec 2025 14:00:16 -0700 Subject: [PATCH] [PR] Removing refreshables the user doesn't have during rest actions (#1449) * Marking up the places that need changing for bug #1160 * Creating a shared method called isItemAvailable and using it in downtime * Explicitely adding the false value rather than relying on undefined returns. Oops * Removing spaces * Removing a needless return line * Adding missing semicolon --- module/applications/dialogs/downtime.mjs | 2 +- module/data/actor/base.mjs | 12 +++++++ module/data/actor/character.mjs | 45 ++++++++++++++++-------- module/documents/activeEffect.mjs | 25 +++---------- 4 files changed, 47 insertions(+), 37 deletions(-) diff --git a/module/applications/dialogs/downtime.mjs b/module/applications/dialogs/downtime.mjs index 96e06446..3d5b7f0f 100644 --- a/module/applications/dialogs/downtime.mjs +++ b/module/applications/dialogs/downtime.mjs @@ -93,7 +93,7 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV } getRefreshables() { - const actionItems = this.actor.items.reduce((acc, x) => { + const actionItems = this.actor.items.filter(x => this.actor.system.isItemAvailable(x)).reduce((acc, x) => { if (x.system.actions) { const recoverable = x.system.actions.reduce((acc, action) => { if (refreshIsAllowed([this.shortrest ? 'shortRest' : 'longRest'], action.uses.recovery)) { diff --git a/module/data/actor/base.mjs b/module/data/actor/base.mjs index c7f7ee75..f3662da2 100644 --- a/module/data/actor/base.mjs +++ b/module/data/actor/base.mjs @@ -1,4 +1,5 @@ import DHBaseActorSettings from '../../applications/sheets/api/actor-setting.mjs'; +import DHItem from '../../documents/item.mjs'; import { getScrollTextData } from '../../helpers/utils.mjs'; const resistanceField = (resistanceLabel, immunityLabel, reductionLabel) => @@ -106,6 +107,17 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel { return data; } + /** + * Checks if an item is available for use, such as multiclass features being disabled + * on a character. + * + * @param {DHItem} item The item being checked for availability + * @return {boolean} whether the item is available + */ + isItemAvailable(item) { + return true; + } + async _preDelete() { /* Clear all partyMembers from tagTeam setting.*/ /* Revisit this when tagTeam is improved for many parties */ diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index c5ab914c..5bce5c55 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -435,6 +435,34 @@ export default class DhCharacter extends BaseDataActor { return attack; } + /** @inheritDoc */ + isItemAvailable(item) { + if (!super.isItemAvailable(this)) return false; + /** + * Preventing subclass features from being available if the chacaracter does not + * have the right subclass advancement + */ + if (item.system.originItemType !== CONFIG.DH.ITEM.featureTypes.subclass.id) { + return true; + } + if (!this.class.subclass) return false; + + const prop = item.system.multiclassOrigin ? 'multiclass' : 'class'; + const subclassState = this[prop].subclass?.system?.featureState; + if (!subclassState) return false; + + if ( + item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.foundation || + (item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.specialization && + subclassState >= 2) || + (item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.mastery && subclassState >= 3) + ) { + return true; + } else { + return false; + } + } + get sheetLists() { const ancestryFeatures = [], communityFeatures = [], @@ -443,7 +471,7 @@ export default class DhCharacter extends BaseDataActor { companionFeatures = [], features = []; - for (let item of this.parent.items) { + for (let item of this.parent.items.filter(x => this.isItemAvailable(x))) { if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.ancestry.id) { ancestryFeatures.push(item); } else if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.community.id) { @@ -451,20 +479,7 @@ export default class DhCharacter extends BaseDataActor { } else if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.class.id) { classFeatures.push(item); } else if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.subclass.id) { - if (this.class.subclass) { - const prop = item.system.multiclassOrigin ? 'multiclass' : 'class'; - const subclassState = this[prop].subclass?.system?.featureState; - if (!subclassState) continue; - - if ( - item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.foundation || - (item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.specialization && - subclassState >= 2) || - (item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.mastery && subclassState >= 3) - ) { - subclassFeatures.push(item); - } - } + subclassFeatures.push(item); } else if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.companion.id) { companionFeatures.push(item); } else if (item.type === 'feature' && !item.system.type) { diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs index fcf1d590..2297ea27 100644 --- a/module/documents/activeEffect.mjs +++ b/module/documents/activeEffect.mjs @@ -194,27 +194,10 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect { } prepareDerivedData() { - /* Preventing subclass features from transferring to actor if they do not have the right subclass advancement */ - if (this.parent?.type === 'feature') { - const origSubclassParent = this.parent.system.originItemType === 'subclass'; - if (origSubclassParent) { - const subclass = this.parent.parent.items.find( - x => - x.type === 'subclass' && - x.system.isMulticlass === (this.parent.system.identifier === 'multiclass') - ); - - if (subclass) { - const featureState = subclass.system.featureState; - - if ( - (this.parent.system.identifier === CONFIG.DH.ITEM.featureSubTypes.specialization && - featureState < 2) || - (this.parent.system.identifier === CONFIG.DH.ITEM.featureSubTypes.mastery && featureState < 3) - ) { - this.transfer = false; - } - } + /* Check for item availability such as in the case of subclass advancement. */ + if (this.parent?.parent?.system?.isItemAvailable) { + if (!this.parent.parent.system.isItemAvailable(this.parent)) { + this.transfer = false; } } }