From 746e0f239a90d6be324594aea7b419041ea8d89e Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Sat, 7 Jun 2025 20:30:12 +0200 Subject: [PATCH] 110 - Class Data Model (#111) * Added PreCreate/Create/Delete logic for Class/Subclass and set it as foreignUUID fields in PC * Moved methods into TypedModelData * Simplified Subclass --- lang/en.json | 8 ++ module/applications/levelup.mjs | 6 +- .../applications/sheets/daggerheart-sheet.mjs | 2 +- module/applications/sheets/items/class.mjs | 30 +++---- module/applications/sheets/pc.mjs | 86 ++++--------------- .../data/fields/foreignDocumentUUIDField.mjs | 65 +++++++------- module/data/item/class.mjs | 70 +++++++++++---- module/data/item/subclass.mjs | 85 +++++++++--------- module/data/pc.mjs | 17 ++-- module/documents/item.mjs | 11 +-- .../global/partials/feature-section-item.hbs | 4 +- templates/sheets/items/subclass/features.hbs | 12 +-- templates/sheets/parts/features.hbs | 6 +- templates/sheets/pc/pc.hbs | 12 +-- 14 files changed, 190 insertions(+), 224 deletions(-) diff --git a/lang/en.json b/lang/en.json index 39d5225c..eb5ecd62 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1178,6 +1178,14 @@ "Description": "Description" } }, + "Item": { + "Errors": { + "MissingClass": "The character is missing a class", + "SubclassNotInClass": "The subclass does not belong to the character's class", + "ClassAlreadySelected": "The character already has a class", + "SubclassAlreadySelected": "The character already has a subclass for that class." + } + }, "Effects": { "Types": { "health": { diff --git a/module/applications/levelup.mjs b/module/applications/levelup.mjs index 7e69a6a1..22c6d33e 100644 --- a/module/applications/levelup.mjs +++ b/module/applications/levelup.mjs @@ -230,7 +230,7 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2) domains: multiclass?.system?.domains.map(key => { const domain = domains[key]; - const alreadySelected = this.actor.system.class.system.domains.includes(key); + const alreadySelected = this.actor.system.class.value.system.domains.includes(key); return { ...domain, @@ -480,7 +480,7 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2) const target = event.target.closest('.card-preview-container'); if (item.type === 'domainCard') { if ( - !this.actor.system.class.system.domains.includes(item.system.domain) && + !this.actor.system.class.value.system.domains.includes(item.system.domain) && this.levelup.classUpgradeChoices?.multiclass?.domain !== item.system.domain ) { ui.notifications.error( @@ -522,7 +522,7 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2) } else if (event.target.closest('.multiclass-cards')) { const target = event.target.closest('.multiclass-cards'); if (item.type === 'class') { - if (item.name === this.actor.system.class.name) { + if (item.name === this.actor.system.class.value.name) { ui.notifications.error( game.i18n.localize('DAGGERHEART.Application.LevelUp.notifications.error.alreadySelectedClass') ); diff --git a/module/applications/sheets/daggerheart-sheet.mjs b/module/applications/sheets/daggerheart-sheet.mjs index 635d2434..4810b0a7 100644 --- a/module/applications/sheets/daggerheart-sheet.mjs +++ b/module/applications/sheets/daggerheart-sheet.mjs @@ -27,7 +27,7 @@ export default function DhpApplicationMixin(Base) { async _prepareContext(_options, objectPath = 'document') { const context = await super._prepareContext(_options); - context.source = this[objectPath].toObject(); + context.source = this[objectPath]; context.fields = this[objectPath].schema.fields; context.systemFields = this[objectPath].system ? this[objectPath].system.schema.fields : {}; diff --git a/module/applications/sheets/items/class.mjs b/module/applications/sheets/items/class.mjs index 978a3f9a..b0d8bd1d 100644 --- a/module/applications/sheets/items/class.mjs +++ b/module/applications/sheets/items/class.mjs @@ -11,8 +11,8 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) { actions: { removeSubclass: this.removeSubclass, viewSubclass: this.viewSubclass, - removeFeature: this.removeFeature, - viewFeature: this.viewFeature, + deleteFeature: this.deleteFeature, + editFeature: this.editFeature, removeItem: this.removeItem, viewItem: this.viewItem, removePrimaryWeapon: this.removePrimaryWeapon, @@ -153,13 +153,13 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) { subclass.sheet.render(true); } - static async removeFeature(_, button) { + static async deleteFeature(_, button) { await this.document.update({ - 'system.features': this.document.system.features.filter(x => x.uuid !== button.dataset.feature) + 'system.features': this.document.system.features.map(x => x.uuid).filter(x => x !== button.dataset.feature) }); } - static async viewFeature(_, button) { + static async editFeature(_, button) { const feature = await fromUuid(button.dataset.feature); feature.sheet.render(true); } @@ -198,15 +198,11 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) { const item = await fromUuid(data.uuid); if (item.type === 'subclass') { await this.document.update({ - 'system.subclasses': [ - ...this.document.system.subclasses, item.uuid - ] + 'system.subclasses': [...this.document.system.subclasses.map(x => x.uuid), item.uuid] }); } else if (item.type === 'feature') { await this.document.update({ - 'system.features': [ - ...this.document.system.features, item.uuid - ] + 'system.features': [...this.document.system.features.map(x => x.uuid), item.uuid] }); } else if (item.type === 'weapon') { if (event.currentTarget.classList.contains('primary-weapon-section')) { @@ -231,25 +227,19 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) { if (item.type === 'miscellaneous' || item.type === 'consumable') { if (this.document.system.inventory.choiceA.length < 2) await this.document.update({ - 'system.inventory.choiceA': [ - ...this.document.system.inventory.choiceA, item.uuid - ] + 'system.inventory.choiceA': [...this.document.system.inventory.choiceA, item.uuid] }); } } else if (item.type === 'miscellaneous') { if (event.currentTarget.classList.contains('take-section')) { if (this.document.system.inventory.take.length < 3) await this.document.update({ - 'system.inventory.take': [ - ...this.document.system.inventory.take, item.uuid - ] + 'system.inventory.take': [...this.document.system.inventory.take, item.uuid] }); } else if (event.currentTarget.classList.contains('choice-b-section')) { if (this.document.system.inventory.choiceB.length < 2) await this.document.update({ - 'system.inventory.choiceB': [ - ...this.document.system.inventory.choiceB, item.uuid - ] + 'system.inventory.choiceB': [...this.document.system.inventory.choiceB, item.uuid] }); } } diff --git a/module/applications/sheets/pc.mjs b/module/applications/sheets/pc.mjs index b38195d5..7433e3f3 100644 --- a/module/applications/sheets/pc.mjs +++ b/module/applications/sheets/pc.mjs @@ -215,13 +215,13 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { context.abilityScoresFinished = context.abilityScoreArray.every(x => x.value === 0); //FIXME: - context.domains = this.document.system.class + context.domains = this.document.system.class.value ? { - first: this.document.system.class.system.domains[0] - ? SYSTEM.DOMAIN.domains[this.document.system.class.system.domains[0]].src + first: this.document.system.class.value.system.domains[0] + ? SYSTEM.DOMAIN.domains[this.document.system.class.value.system.domains[0]].src : null, - second: this.document.system.class.system.domains[1] - ? SYSTEM.DOMAIN.domains[this.document.system.class.system.domains[1]].src + second: this.document.system.class.value.system.domains[1] + ? SYSTEM.DOMAIN.domains[this.document.system.class.value.system.domains[1]].src : null } : {}; @@ -361,7 +361,7 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { } mapAdvancementFeatures(actor, config) { - if (!actor.system.subclass) return { foundation: null, advancements: [] }; + if (!actor.system.class.value || !actor.system.class.subclass) return { foundation: null, advancements: [] }; const { subclass, multiclassSubclass } = actor.system.subclassFeatures; @@ -370,8 +370,8 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { multiclass: false, img: actor.system.subclass.img, subtitle: game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.FoundationTitle'), - domains: actor.system.class.system.domains.map(x => config.DOMAIN.domains[x].src), - className: actor.system.class.name, + domains: actor.system.class.value.system.domains.map(x => config.DOMAIN.domains[x].src), + className: actor.system.class.value.name, subclassUuid: actor.system.subclass.uuid, subclassName: actor.system.subclass.name, spellcast: config.ACTOR.abilities[actor.system.subclass.system.spellcastingTrait]?.name ?? null, @@ -402,9 +402,9 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { : game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.FoundationTitle'), domains: firstKey === 'sub' - ? actor.system.class.system.domains.map(x => config.DOMAIN.domains[x].src) + ? actor.system.class.value.system.domains.map(x => config.DOMAIN.domains[x].src) : actor.system.multiclass.system.domains.map(x => config.DOMAIN.domains[x].src), - className: firstKey === 'sub' ? actor.system.class.name : actor.system.multiclass.name, + className: firstKey === 'sub' ? actor.system.class.value.name : actor.system.multiclass.name, subclassUuid: firstBase.uuid, subclassName: firstBase.name, spellcast: @@ -456,9 +456,9 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { : game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.FoundationTitle'), domains: secondKey === 'sub' - ? actor.system.class.system.domains.map(x => config.DOMAIN.domains[x].src) + ? actor.system.class.value.system.domains.map(x => config.DOMAIN.domains[x].src) : actor.system.multiclass.system.domains.map(x => config.DOMAIN.domains[x].src), - className: secondKey === 'sub' ? actor.system.class.name : actor.system.multiclass.name, + className: secondKey === 'sub' ? actor.system.class.value.name : actor.system.multiclass.name, subclassUuid: secondBase.uuid, subclassName: secondBase.name, spellcast: @@ -644,7 +644,7 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { } openLevelUp() { - if (!this.document.system.class || !this.document.system.subclass) { + if (!this.document.system.class.value || !this.document.system.subclass) { ui.notifications.error(game.i18n.localize('DAGGERHEART.Sheets.PC.Errors.missingClassOrSubclass')); return; } @@ -1144,7 +1144,7 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { const createdItems = []; if (item.type === 'domainCard') { - if (!this.document.system.class) { + if (!this.document.system.class.value) { ui.notifications.error(game.i18n.localize('DAGGERHEART.Notification.Error.NoClassSelected')); return; } @@ -1173,63 +1173,7 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { return createdItem; } else { - if (!item.system.multiclass && ['class', 'subclass', 'ancestry', 'community'].includes(item.type)) { - const existing = this.document.items.find(x => x.type === item.type); - await existing?.delete(); - } - - if (item.type === 'subclass') { - if (!item.system.multiclass) { - if (!this.document.system.class) { - ui.notifications.info( - game.i18n.localize('DAGGERHEART.Notification.Info.SelectClassBeforeSubclass') - ); - return; - } else if (!this.document.system.class.system.subclasses.some(x => x.uuid === item.uuid)) { - ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.SubclassNotOfClass')); - return; - } - - for (var feature of this.document.items.filter( - x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.subclass.id - )) { - await feature.delete(); - } - } - - const features = [ - itemData.system.foundationFeature, - itemData.system.specializationFeature, - itemData.system.masteryFeature - ]; - for (var i = 0; i < features.length; i++) { - const feature = features[i]; - for (var ability of feature.abilities) { - const data = (await fromUuid(ability.uuid)).toObject(); - if (i > 0) data.system.disabled = true; - data.uuid = itemData.uuid; - - const abilityData = await this._onDropItemCreate(data); - ability.uuid = abilityData[0].uuid; - - createdItems.push(abilityData); - } - } - } else if (item.type === 'class') { - if (!item.system.multiclass) { - for (var feature of this.document.items.filter( - x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.class.id - )) { - await feature.delete(); - } - } - - for (var feature of item.system.features) { - const data = (await fromUuid(feature.uuid)).toObject(); - const itemData = await this._onDropItemCreate(data); - createdItems.push(itemData); - } - } else if (item.type === 'ancestry') { + if (item.type === 'ancestry') { for (var feature of this.document.items.filter( x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.ancestry.id )) { diff --git a/module/data/fields/foreignDocumentUUIDField.mjs b/module/data/fields/foreignDocumentUUIDField.mjs index 13bbc80d..29cfaff3 100644 --- a/module/data/fields/foreignDocumentUUIDField.mjs +++ b/module/data/fields/foreignDocumentUUIDField.mjs @@ -3,40 +3,39 @@ * that resolves to either the document, the index(for items in compenidums) or the UUID string. */ export default class ForeignDocumentUUIDField extends foundry.data.fields.DocumentUUIDField { + /** + * @param {foundry.data.types.DocumentUUIDFieldOptions} [options] Options which configure the behavior of the field + * @param {foundry.data.types.DataFieldContext} [context] Additional context which describes the field + */ + constructor(options, context) { + super(options, context); + } -/** - * @param {foundry.data.types.DocumentUUIDFieldOptions} [options] Options which configure the behavior of the field - * @param {foundry.data.types.DataFieldContext} [context] Additional context which describes the field - */ - constructor(options, context) { - super(options, context); - } + /** @inheritdoc */ + static get _defaults() { + return foundry.utils.mergeObject(super._defaults, { + nullable: true, + readonly: false, + idOnly: false + }); + } - /** @inheritdoc */ - static get _defaults() { - return foundry.utils.mergeObject(super._defaults, { - nullable: true, - readonly: false, - idOnly: false, - }); - } + /**@override */ + initialize(value, _model, _options = {}) { + if (this.idOnly) return value; + return (() => { + try { + const doc = fromUuidSync(value); + return doc; + } catch (error) { + console.error(error); + return value ?? null; + } + })(); + } - /**@override */ - initialize(value, _model, _options = {}) { - if (this.idOnly) return value; - return () => { - try { - const doc = fromUuidSync(value); - return doc; - } catch (error) { - console.error(error); - return value ?? null; - } - }; - } - - /**@override */ - toObject(value) { - return value?.uuid ?? value; - } + /**@override */ + toObject(value) { + return value?.uuid ?? value; + } } diff --git a/module/data/item/class.mjs b/module/data/item/class.mjs index 8d9d62e9..423ad8a5 100644 --- a/module/data/item/class.mjs +++ b/module/data/item/class.mjs @@ -1,4 +1,3 @@ -import { getTier } from '../../helpers/utils.mjs'; import BaseDataItem from './base.mjs'; import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs'; @@ -6,9 +5,9 @@ export default class DHClass extends BaseDataItem { /** @inheritDoc */ static get metadata() { return foundry.utils.mergeObject(super.metadata, { - label: "TYPES.Item.class", - type: "class", - hasDescription: true, + label: 'TYPES.Item.class', + type: 'class', + hasDescription: true }); } @@ -19,15 +18,22 @@ export default class DHClass extends BaseDataItem { ...super.defineSchema(), domains: new fields.ArrayField(new fields.StringField(), { max: 2 }), - classItems: new fields.ArrayField(new ForeignDocumentUUIDField({ type: "Item" })), + classItems: new fields.ArrayField(new ForeignDocumentUUIDField({ type: 'Item' })), evasion: new fields.NumberField({ initial: 0, integer: true }), - features: new fields.ArrayField(new ForeignDocumentUUIDField({ type: "Item" })), - - subclasses: new fields.ArrayField(new ForeignDocumentUUIDField({ type: "Item", required: false, nullable: true, initial: undefined })), + features: new fields.ArrayField(new ForeignDocumentUUIDField({ type: 'Item' })), + subclasses: new fields.ArrayField( + new ForeignDocumentUUIDField({ type: 'Item', required: false, nullable: true, initial: undefined }) + ), inventory: new fields.SchemaField({ - take: new fields.ArrayField(new ForeignDocumentUUIDField({ type: "Item", required: false, nullable: true, initial: undefined })), - choiceA: new fields.ArrayField(new ForeignDocumentUUIDField({ type: "Item", required: false, nullable: true, initial: undefined })), - choiceB: new fields.ArrayField(new ForeignDocumentUUIDField({ type: "Item", required: false, nullable: true, initial: undefined })), + take: new fields.ArrayField( + new ForeignDocumentUUIDField({ type: 'Item', required: false, nullable: true, initial: undefined }) + ), + choiceA: new fields.ArrayField( + new ForeignDocumentUUIDField({ type: 'Item', required: false, nullable: true, initial: undefined }) + ), + choiceB: new fields.ArrayField( + new ForeignDocumentUUIDField({ type: 'Item', required: false, nullable: true, initial: undefined }) + ) }), characterGuide: new fields.SchemaField({ suggestedTraits: new fields.SchemaField({ @@ -38,15 +44,45 @@ export default class DHClass extends BaseDataItem { presence: new fields.NumberField({ initial: 0, integer: true }), knowledge: new fields.NumberField({ initial: 0, integer: true }) }), - suggestedPrimaryWeapon: new ForeignDocumentUUIDField({ type: "Item" }), - suggestedSecondaryWeapon: new ForeignDocumentUUIDField({ type: "Item" }), - suggestedArmor: new ForeignDocumentUUIDField({ type: "Item" }), + suggestedPrimaryWeapon: new ForeignDocumentUUIDField({ type: 'Item' }), + suggestedSecondaryWeapon: new ForeignDocumentUUIDField({ type: 'Item' }), + suggestedArmor: new ForeignDocumentUUIDField({ type: 'Item' }) }), - multiclass: new fields.NumberField({ initial: null, nullable: true, integer: true }), + isMulticlass: new fields.BooleanField({ initial: false }) }; } - get multiclassTier() { - return getTier(this.multiclass, true); + async _preCreate(data, options, user) { + const allowed = await super._preCreate(data, options, user); + if (allowed === false) return; + + if (this.actor?.type === 'pc') { + const path = data.system.isMulticlass ? 'system.multiclass.value' : 'system.class.value'; + if (foundry.utils.getProperty(this.actor, path)) { + ui.notifications.error(game.i18n.localize('DAGGERHEART.Item.Errors.ClassAlreadySelected')); + return false; + } + } + } + + _onCreate(data, options, userId) { + super._onCreate(data, options, userId); + if (options.parent?.type === 'pc') { + const path = `system.${data.system.isMulticlass ? 'multiclass.value' : 'class.value'}`; + options.parent.update({ [path]: `${options.parent.uuid}.Item.${data._id}` }); + } + } + + _onDelete(options, userId) { + super._onDelete(options, userId); + + if (options.parent?.type === 'pc') { + const path = `system.${this.isMulticlass ? 'multiclass' : 'class'}`; + options.parent.update({ + [`${path}.value`]: null + }); + + foundry.utils.getProperty(options.parent, `${path}.subclass`)?.delete(); + } } } diff --git a/module/data/item/subclass.mjs b/module/data/item/subclass.mjs index ff92db53..883df064 100644 --- a/module/data/item/subclass.mjs +++ b/module/data/item/subclass.mjs @@ -1,13 +1,13 @@ -import { getTier } from '../../helpers/utils.mjs'; +import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs'; import BaseDataItem from './base.mjs'; export default class DHSubclass extends BaseDataItem { /** @inheritDoc */ static get metadata() { return foundry.utils.mergeObject(super.metadata, { - label: "TYPES.Item.subclass", - type: "subclass", - hasDescription: true, + label: 'TYPES.Item.subclass', + type: 'subclass', + hasDescription: true }); } @@ -22,45 +22,48 @@ export default class DHSubclass extends BaseDataItem { nullable: true, initial: null }), - foundationFeature: new fields.SchemaField({ - description: new fields.HTMLField({}), - abilities: new fields.ArrayField( - new fields.SchemaField({ - name: new fields.StringField({}), - img: new fields.StringField({}), - uuid: new fields.StringField({}) - }) - ) - }), - specializationFeature: new fields.SchemaField({ - unlocked: new fields.BooleanField({ initial: false }), - tier: new fields.NumberField({ initial: null, nullable: true, integer: true }), - description: new fields.HTMLField({}), - abilities: new fields.ArrayField( - new fields.SchemaField({ - name: new fields.StringField({}), - img: new fields.StringField({}), - uuid: new fields.StringField({}) - }) - ) - }), - masteryFeature: new fields.SchemaField({ - unlocked: new fields.BooleanField({ initial: false }), - tier: new fields.NumberField({ initial: null, nullable: true, integer: true }), - description: new fields.HTMLField({}), - abilities: new fields.ArrayField( - new fields.SchemaField({ - name: new fields.StringField({}), - img: new fields.StringField({}), - uuid: new fields.StringField({}) - }) - ) - }), - multiclass: new fields.NumberField({ initial: null, nullable: true, integer: true }) + foundationFeature: new ForeignDocumentUUIDField({ type: 'Item' }), + specializationFeature: new ForeignDocumentUUIDField({ type: 'Item' }), + masteryFeature: new ForeignDocumentUUIDField({ type: 'Item' }), + isMulticlass: new fields.BooleanField({ initial: false }) }; } - get multiclassTier() { - return getTier(this.multiclass); + async _preCreate(data, options, user) { + const allowed = await super._preCreate(data, options, user); + if (allowed === false) return; + + if (this.actor?.type === 'pc') { + const path = data.system.isMulticlass ? 'system.multiclass' : 'system.class'; + const classData = foundry.utils.getProperty(this.actor, path); + if (!classData.value) { + ui.notifications.error(game.i18n.localize('DAGGERHEART.Item.Errors.MissingClass')); + return false; + } else if (classData.subclass) { + ui.notifications.error(game.i18n.localize('DAGGERHEART.Item.Errors.SubclassAlreadySelected')); + return false; + } else if (classData.value.system.subclasses.every(x => x.uuid !== `Item.${data._id}`)) { + ui.notifications.error(game.i18n.localize('DAGGERHEART.Item.Errors.SubclassNotInClass')); + return false; + } + } + } + + _onCreate(data, options, userId) { + super._onCreate(data, options, userId); + + if (options.parent?.type === 'pc') { + const path = `system.${data.system.isMulticlass ? 'multiclass.subclass' : 'class.subclass'}`; + options.parent.update({ [path]: `${options.parent.uuid}.Item.${data._id}` }); + } + } + + _onDelete(options, userId) { + super._onDelete(options, userId); + + if (options.parent?.type === 'pc') { + const path = `system.${this.isMulticlass ? 'multiclass.subclass' : 'class.subclass'}`; + options.parent.update({ [path]: null }); + } } } diff --git a/module/data/pc.mjs b/module/data/pc.mjs index 7589321a..740b51eb 100644 --- a/module/data/pc.mjs +++ b/module/data/pc.mjs @@ -1,4 +1,5 @@ import { getPathValue } from '../helpers/utils.mjs'; +import ForeignDocumentUUIDField from './fields/foreignDocumentUUIDField.mjs'; import { LevelOptionType } from './levelTier.mjs'; const fields = foundry.data.fields; @@ -96,6 +97,14 @@ export default class DhpPC extends foundry.abstract.TypeDataModel { max: new fields.NumberField({ initial: 6, integer: true }), value: new fields.NumberField({ initial: 0, integer: true }) }), + class: new fields.SchemaField({ + value: new ForeignDocumentUUIDField({ type: 'Item', nullable: true }), + subclass: new ForeignDocumentUUIDField({ type: 'Item', nullable: true }) + }), + multiclass: new fields.SchemaField({ + value: new ForeignDocumentUUIDField({ type: 'Item', nullable: true }), + subclass: new ForeignDocumentUUIDField({ type: 'Item', nullable: true }) + }), levelData: new fields.EmbeddedDataField(DhPCLevelData) }; } @@ -108,14 +117,6 @@ export default class DhpPC extends foundry.abstract.TypeDataModel { return this.parent.items.find(x => x.type === 'ancestry') ?? null; } - get class() { - return this.parent.items.find(x => x.type === 'class' && !x.system.multiclass) ?? null; - } - - get multiclass() { - return this.parent.items.find(x => x.type === 'class' && x.system.multiclass) ?? null; - } - get multiclassSubclass() { return this.parent.items.find(x => x.type === 'subclass' && x.system.multiclass) ?? null; } diff --git a/module/documents/item.mjs b/module/documents/item.mjs index 955c2c27..65dafc51 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -1,21 +1,12 @@ export default class DhpItem extends Item { - _preCreate(data, changes, user) { - super._preCreate(data, changes, user); - } - prepareData() { super.prepareData(); - - if (this.type === 'class') { - // Bad. Make this better. - // this.system.domains = CONFIG.daggerheart.DOMAIN.classDomainMap[Object.keys(CONFIG.daggerheart.DOMAIN.classDomainMap).find(x => x === this.name.toLowerCase())]; - } } /** * @inheritdoc * @param {object} options - Options which modify the getRollData method. - * @returns + * @returns */ getRollData(options = {}) { let data; diff --git a/templates/sheets/global/partials/feature-section-item.hbs b/templates/sheets/global/partials/feature-section-item.hbs index adc029e9..ebaabefe 100644 --- a/templates/sheets/global/partials/feature-section-item.hbs +++ b/templates/sheets/global/partials/feature-section-item.hbs @@ -9,7 +9,7 @@ @@ -17,7 +17,7 @@ diff --git a/templates/sheets/items/subclass/features.hbs b/templates/sheets/items/subclass/features.hbs index eb2010c4..d9ebb3c1 100644 --- a/templates/sheets/items/subclass/features.hbs +++ b/templates/sheets/items/subclass/features.hbs @@ -5,22 +5,16 @@ >
\ No newline at end of file diff --git a/templates/sheets/parts/features.hbs b/templates/sheets/parts/features.hbs index ac9f8195..4fb37890 100644 --- a/templates/sheets/parts/features.hbs +++ b/templates/sheets/parts/features.hbs @@ -1,12 +1,12 @@