From f95e511a4d3d7b358201422c95e9e1ab501f8235 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Tue, 19 May 2026 23:36:28 -0400 Subject: [PATCH 1/2] Fix removal when de-leveling --- module/documents/actor.mjs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index c1c9aca9..0a4e5e32 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -233,16 +233,14 @@ export default class DhpActor extends Actor { if (multiclass) { const multiclassItem = this.items.find(x => x.uuid === multiclass.itemUuid); - const multiclassFeatures = this.items.filter( - x => x.system.originItemType === 'class' && x.system.multiclassOrigin - ); - const subclassFeatures = this.items.filter( - x => x.system.originItemType === 'subclass' && x.system.multiclassOrigin + const multiclassRelatedFeatures = this.items.filter( + x => ['class', 'subclass'].includes(x.system.originItemType) && x.system.multiclassOrigin ); + if (!multiclassItem) console.error('Unexpected missing multiclass item to remove'); this.deleteEmbeddedDocuments( 'Item', - [multiclassItem, ...multiclassFeatures, ...subclassFeatures].map(x => x.id) + [multiclassItem, ...multiclassRelatedFeatures].filter(i => !!i).map(x => x.id) ); this.update({ @@ -394,6 +392,7 @@ export default class DhpActor extends Actor { const embeddedItem = await this.createEmbeddedDocuments('Item', [ { ...multiclassData, + uuid: multiclassItem.uuid, // todo: replace with setting an id and using keepId _stats: getStatsWithSource(multiclassItem), system: { ...multiclassData.system, @@ -407,6 +406,7 @@ export default class DhpActor extends Actor { await this.createEmbeddedDocuments('Item', [ { ...subclassData, + uuid: subclassItem.uuid, // todo: replace with setting an id and using keepId _stats: getStatsWithSource(subclassItem), system: { ...subclassData.system, @@ -427,6 +427,7 @@ export default class DhpActor extends Actor { const embeddedItem = await this.createEmbeddedDocuments('Item', [ { ...cardData, + uuid: cardItem.uuid, // todo: replace with setting an id and using keepId _stats: getStatsWithSource(cardItem), system: { ...cardData.system, From ac010482fe352942d2fc439228bd2e0e9a7b5d21 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Wed, 20 May 2026 00:12:00 -0400 Subject: [PATCH 2/2] Also delete multiclass related stuff if reducing below the minimum multiclass level --- module/documents/actor.mjs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 0a4e5e32..e4c11a5c 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -153,10 +153,13 @@ export default class DhpActor extends Actor { async updateLevel(newLevel) { if (!['character', 'companion'].includes(this.type) || newLevel === this.system.levelData.level.changed) return; + const tiers = Object.values(game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers); + const maxLevel = tiers.reduce((acc, tier) => Math.max(acc, tier.levels.end), 0); + const multiclassMinLevel = Math.min( + maxLevel, + ...tiers.filter(t => t.options.multiclass).map(t => t.levels.start) + ); if (newLevel > this.system.levelData.level.current) { - const maxLevel = Object.values( - game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers - ).reduce((acc, tier) => Math.max(acc, tier.levels.end), 0); if (newLevel > maxLevel) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.tooHighLevel')); } @@ -231,16 +234,19 @@ export default class DhpActor extends Actor { this.system.multiclass.subclass.update({ 'system.featureState': subclassFeatureState.multiclass }); } - if (multiclass) { - const multiclassItem = this.items.find(x => x.uuid === multiclass.itemUuid); - const multiclassRelatedFeatures = this.items.filter( - x => ['class', 'subclass'].includes(x.system.originItemType) && x.system.multiclassOrigin + // Remove multiclass if we're removing a multiclass feature or if we're below the multiclass minimum level + // Multclasses cannot be manually removed on the sheet, so this allows recovering in the case of errors + if (multiclass || newLevel < multiclassMinLevel) { + const multiclassItems = this.items.filter( + x => + x.uuid === multiclass?.itemUuid || + x.system.isMulticlass || + (['class', 'subclass'].includes(x.system.originItemType) && x.system.multiclassOrigin) ); - if (!multiclassItem) console.error('Unexpected missing multiclass item to remove'); this.deleteEmbeddedDocuments( 'Item', - [multiclassItem, ...multiclassRelatedFeatures].filter(i => !!i).map(x => x.id) + multiclassItems.map(x => x.id) ); this.update({