From 3dc4daffc3119aa44b4052219f471fe08da6fdb0 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Thu, 31 Jul 2025 18:03:33 +0200 Subject: [PATCH] Fixed relinking of Features from items created on Character --- lang/en.json | 1 + .../dialogs/multiclassChoiceDialog.mjs | 2 +- module/data/actor/character.mjs | 13 ++-- module/data/item/base.mjs | 36 +++++++--- module/data/item/subclass.mjs | 25 ++++++- templates/dialogs/multiclassChoice.hbs | 2 +- templates/sheets/items/class/features.hbs | 68 ++++++++++--------- 7 files changed, 96 insertions(+), 51 deletions(-) diff --git a/lang/en.json b/lang/en.json index 3f1bdcf3..e863ed90 100755 --- a/lang/en.json +++ b/lang/en.json @@ -2221,6 +2221,7 @@ "tooHighLevel": "You cannot raise the character level past the maximum", "tooLowLevel": "You cannot lower the character level below starting level", "subclassNotInClass": "This subclass does not belong to your selected class.", + "subclassNotInMulticlass": "This subclass does not belong to your selected multiclass.", "missingClass": "You don't have a class selected yet.", "missingMulticlass": "Missing multiclass", "wrongDomain": "The card isn't from one of your class domains.", diff --git a/module/applications/dialogs/multiclassChoiceDialog.mjs b/module/applications/dialogs/multiclassChoiceDialog.mjs index 9e9f90ab..12f2629b 100644 --- a/module/applications/dialogs/multiclassChoiceDialog.mjs +++ b/module/applications/dialogs/multiclassChoiceDialog.mjs @@ -41,7 +41,7 @@ export default class MulticlassChoiceDialog extends HandlebarsApplicationMixin(A description: game.i18n.localize(domain.description), src: domain.src, selected: value === this.selectedDomain, - disabled: this.actor.system.domains.includes(domain) + disabled: this.actor.system.domains.includes(value) }; }); context.multiclassDisabled = !this.selectedDomain; diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 6a3d1019..e0bbcc03 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -407,11 +407,16 @@ export default class DhCharacter extends BaseDataActor { } else if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.subclass.id) { if (this.class.subclass) { const subclassState = this.class.subclass.system.featureState; - const subType = item.system.subType; + const subclass = + item.system.identifier === 'multiclass' ? this.multiclass.subclass : this.class.subclass; + const featureType = subclass + ? (subclass.system.features.find(x => x.item?.uuid === item.uuid)?.type ?? null) + : null; + if ( - subType === CONFIG.DH.ITEM.featureSubTypes.foundation || - (subType === CONFIG.DH.ITEM.featureSubTypes.specialization && subclassState >= 2) || - (subType === CONFIG.DH.ITEM.featureSubTypes.mastery && subclassState >= 3) + featureType === CONFIG.DH.ITEM.featureSubTypes.foundation || + (featureType === CONFIG.DH.ITEM.featureSubTypes.specialization && subclassState >= 2) || + (featureType === CONFIG.DH.ITEM.featureSubTypes.mastery && subclassState >= 3) ) { subclassFeatures.push(item); } diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs index 1839a983..1f1c06fd 100644 --- a/module/data/item/base.mjs +++ b/module/data/item/base.mjs @@ -125,18 +125,36 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { } if (this.actor && this.actor.type === 'character' && this.features) { + const featureUpdates = {}; for (let f of this.features) { const feature = f.item ?? f; - const createData = foundry.utils.mergeObject(feature.toObject(), { - system: { - originItemType: this.parent.type, - originId: data._id, - identifier: feature.identifier, - subType: feature.item ? feature.type : undefined - } - }, { inplace: false }); - await this.actor.createEmbeddedDocuments('Item', [createData]); + const createData = foundry.utils.mergeObject( + feature.toObject(), + { + system: { + originItemType: this.parent.type, + originId: data._id, + identifier: this.isMulticlass ? 'multiclass' : null, + subType: feature.item ? feature.type : undefined + } + }, + { inplace: false } + ); + const [doc] = await this.actor.createEmbeddedDocuments('Item', [createData]); + + if (!featureUpdates.features) + featureUpdates.features = this.features.map(x => (x.item ? { ...x, item: x.item.uuid } : x.uuid)); + + if (f.item) { + const existingFeature = featureUpdates.features.find(x => x.item === f.item.uuid); + existingFeature.item = doc.uuid; + } else { + const replaceIndex = featureUpdates.features.findIndex(x => x === f.uuid); + featureUpdates.features.splice(replaceIndex, 1, doc.uuid); + } } + + await this.updateSource(featureUpdates); } } diff --git a/module/data/item/subclass.mjs b/module/data/item/subclass.mjs index 2a58fd8a..11d42e86 100644 --- a/module/data/item/subclass.mjs +++ b/module/data/item/subclass.mjs @@ -41,9 +41,6 @@ export default class DHSubclass extends BaseDataItem { } async _preCreate(data, options, user) { - const allowed = await super._preCreate(data, options, user); - if (allowed === false) return; - if (this.actor?.type === 'character') { if (this.actor.system.class.subclass) { if (this.actor.system.multiclass.subclass) { @@ -55,6 +52,17 @@ export default class DHSubclass extends BaseDataItem { return false; } + if ( + this.actor.system.multiclass.value.system.subclasses.every( + x => x.uuid !== (data.uuid ?? `Item.${data._id}`) + ) + ) { + ui.notifications.error( + game.i18n.localize('DAGGERHEART.UI.Notifications.subclassNotInMulticlass') + ); + return false; + } + await this.updateSource({ isMulticlass: true }); } } else { @@ -62,8 +70,19 @@ export default class DHSubclass extends BaseDataItem { ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.missingClass')); return false; } + if ( + this.actor.system.class.value.system.subclasses.every( + x => x.uuid !== (data.uuid ?? `Item.${data._id}`) + ) + ) { + ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.subclassNotInClass')); + return false; + } } } + + const allowed = await super._preCreate(data, options, user); + if (allowed === false) return; } _onCreate(data, options, userId) { diff --git a/templates/dialogs/multiclassChoice.hbs b/templates/dialogs/multiclassChoice.hbs index 2e37544a..3c89ff1a 100644 --- a/templates/dialogs/multiclassChoice.hbs +++ b/templates/dialogs/multiclassChoice.hbs @@ -6,7 +6,7 @@
{{#each domainChoices as | choice |}}
- diff --git a/templates/sheets/items/class/features.hbs b/templates/sheets/items/class/features.hbs index 368047c9..4e6a7e6f 100644 --- a/templates/sheets/items/class/features.hbs +++ b/templates/sheets/items/class/features.hbs @@ -23,38 +23,40 @@
-
- {{localize "TYPES.Item.subclass"}} -
- {{#each source.system.subclasses as |subclass index|}} -
  • -
    - -

    - {{subclass.name}} -

    -
    - - - - - - + {{#unless (eq document.parent.type 'character')}} +
    + {{localize "TYPES.Item.subclass"}} +
    + {{#each source.system.subclasses as |subclass index|}} +
  • +
    + +

    + {{subclass.name}} +

    +
    -
  • -
  • - {{/each}} -
    -
    + + {{/each}} +
    + + {{/unless}} \ No newline at end of file