diff --git a/lang/en.json b/lang/en.json index 75f2b886..fc6653c7 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1537,7 +1537,11 @@ "noAvailableArmorMarks": "You have no more available armor marks", "notEnoughStress": "You don't have enough stress", "damageIgnore": "{character} did not take damage", - "featureIsMissing": "Feature is missing" + "featureIsMissing": "Feature is missing", + "featureNotHope": "This feature is used as something else than a Hope feature and cannot be used here.", + "featureNotClass": "This feature is used as something else than a Class feature and cannot be used here.", + "featureNotPrimary": "This feature is used as something else than a Primary feature and cannot be used here.", + "featureNotSecondary": "This feature is used as something else than a Secondary feature and cannot be used here." }, "Tooltip": { "openItemWorld": "Open Item World", diff --git a/module/applications/sheets/items/ancestry.mjs b/module/applications/sheets/items/ancestry.mjs index bd9e3792..de55301d 100644 --- a/module/applications/sheets/items/ancestry.mjs +++ b/module/applications/sheets/items/ancestry.mjs @@ -63,22 +63,8 @@ export default class AncestrySheet extends DHHeritageSheet { event.stopPropagation(); const target = button.closest('.feature-item'); const feature = this.document.system[`${target.dataset.type}Feature`]; - const featureExists = feature && Object.keys(feature).length > 0; - if (featureExists) { - const confirmed = await foundry.applications.api.DialogV2.confirm({ - window: { - title: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.title', { - type: game.i18n.localize(`TYPES.Item.feature`), - name: feature.name - }) - }, - content: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.text', { name: feature.name }) - }); - if (!confirmed) return; - } - - if (featureExists && target.dataset.type === 'primary') await feature.update({ 'system.primary': null }); + if (feature) await feature.update({ 'system.subType': null }); await this.document.update({ 'system.features': this.document.system.features.filter(x => x && x.uuid !== feature.uuid).map(x => x.uuid) }); @@ -94,15 +80,18 @@ export default class AncestrySheet extends DHHeritageSheet { */ async _onDrop(event) { event.stopPropagation(); - event.preventDefault(); - const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); const item = await fromUuid(data.uuid); if (item?.type === 'feature') { const subType = event.target.closest('.primary-feature') ? 'primary' : 'secondary'; - await item.update({ 'system.subType': subType }); + if (item.system.subType && item.system.subType !== CONFIG.DH.ITEM.featureSubTypes[subType]) { + const error = subType === 'primary' ? 'featureNotPrimary' : 'featureNotSecondary'; + ui.notifications.warn(game.i18n.localize(`DAGGERHEART.UI.Notifications.${error}`)); + return; + } + await item.update({ 'system.subType': subType }); await this.document.update({ 'system.features': [...this.document.system.features.map(x => x.uuid), item.uuid] }); diff --git a/module/applications/sheets/items/class.mjs b/module/applications/sheets/items/class.mjs index b49105be..3a34bcec 100644 --- a/module/applications/sheets/items/class.mjs +++ b/module/applications/sheets/items/class.mjs @@ -78,6 +78,7 @@ export default class ClassSheet extends DHBaseItemSheet { /* -------------------------------------------- */ async _onDrop(event) { + event.stopPropagation(); const data = TextEditor.getDragEventData(event); const item = await fromUuid(data.uuid); const target = event.target.closest('fieldset.drop-section'); @@ -87,12 +88,24 @@ export default class ClassSheet extends DHBaseItemSheet { }); } else if (item.type === 'feature') { if (target.classList.contains('hope-feature')) { + if (item.system.subType && item.system.subType !== CONFIG.DH.ITEM.featureSubTypes.hope) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.featureNotHope')); + return; + } + + await item.update({ 'system.subType': CONFIG.DH.ITEM.featureSubTypes.hope }); await this.document.update({ - 'system.hopeFeatures': [...this.document.system.hopeFeatures.map(x => x.uuid), item.uuid] + 'system.features': [...this.document.system.features.map(x => x.uuid), item.uuid] }); } else if (target.classList.contains('class-feature')) { + if (item.system.subType && item.system.subType !== CONFIG.DH.ITEM.featureSubTypes.class) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.featureNotClass')); + return; + } + + await item.update({ 'system.subType': CONFIG.DH.ITEM.featureSubTypes.class }); await this.document.update({ - 'system.classFeatures': [...this.document.system.classFeatures.map(x => x.uuid), item.uuid] + 'system.features': [...this.document.system.features.map(x => x.uuid), item.uuid] }); } } else if (item.type === 'weapon') { @@ -177,28 +190,25 @@ export default class ClassSheet extends DHBaseItemSheet { doc.sheet.render({ force: true }); } - getActionPath(type) { - return type === 'hope' ? 'hopeFeatures' : 'classFeatures'; - } - static async addFeature(_, target) { - const actionPath = this.getActionPath(target.dataset.type); const feature = await game.items.documentClass.create({ type: 'feature', - name: game.i18n.format('DOCUMENT.New', { type: game.i18n.localize('TYPES.Item.feature') }) + name: game.i18n.format('DOCUMENT.New', { type: game.i18n.localize('TYPES.Item.feature') }), + system: { + subType: + target.dataset.type === 'hope' + ? CONFIG.DH.ITEM.featureSubTypes.hope + : CONFIG.DH.ITEM.featureSubTypes.class + } }); await this.document.update({ - [`system.${actionPath}`]: [ - ...this.document.system[actionPath].filter(x => x).map(x => x.uuid), - feature.uuid - ] + [`system.features`]: [...this.document.system.features.filter(x => x).map(x => x.uuid), feature.uuid] }); } static async editFeature(_, button) { const target = button.closest('.feature-item'); - const actionPath = this.getActionPath(button.dataset.type); - const feature = this.document.system[actionPath].find(x => x?.id === target.dataset.featureId); + const feature = this.document.system.features.find(x => x?.id === target.dataset.featureId); if (!feature) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.featureIsMissing')); return; @@ -210,10 +220,16 @@ export default class ClassSheet extends DHBaseItemSheet { static async deleteFeature(event, button) { event.stopPropagation(); const target = button.closest('.feature-item'); - const actionPath = this.getActionPath(button.dataset.type); + + const feature = this.document.system.features.find( + feature => feature && feature.id === target.dataset.featureId + ); + if (feature) { + await feature.update({ 'system.subType': null }); + } await this.document.update({ - [`system.${actionPath}`]: this.document.system[actionPath] + [`system.features`]: this.document.system.features .filter(feature => feature && feature.id !== target.dataset.featureId) .map(x => x.uuid) }); diff --git a/module/config/itemConfig.mjs b/module/config/itemConfig.mjs index ede5ef08..d8583b40 100644 --- a/module/config/itemConfig.mjs +++ b/module/config/itemConfig.mjs @@ -1322,7 +1322,9 @@ export const featureTypes = { export const featureSubTypes = { primary: 'primary', - secondary: 'secondary' + secondary: 'secondary', + hope: 'hope', + class: 'class' }; export const actionTypes = { diff --git a/module/data/item/class.mjs b/module/data/item/class.mjs index 281b0a48..b8a9ab81 100644 --- a/module/data/item/class.mjs +++ b/module/data/item/class.mjs @@ -27,8 +27,7 @@ export default class DHClass extends BaseDataItem { label: 'DAGGERHEART.GENERAL.hitPoints.plural' }), evasion: new fields.NumberField({ initial: 0, integer: true, label: 'DAGGERHEART.GENERAL.evasion' }), - hopeFeatures: new ForeignDocumentUUIDArrayField({ type: 'Item' }), - classFeatures: new ForeignDocumentUUIDArrayField({ type: 'Item' }), + features: new ForeignDocumentUUIDArrayField({ type: 'Item' }), subclasses: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }), inventory: new fields.SchemaField({ take: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }), @@ -52,12 +51,18 @@ export default class DHClass extends BaseDataItem { }; } - get hopeFeature() { - return this.hopeFeatures.length > 0 ? this.hopeFeatures[0] : null; + get hopeFeatures() { + return ( + this.features.filter(x => x?.system?.subType === CONFIG.DH.ITEM.featureSubTypes.hope) ?? + (this.features.filter(x => !x).length > 0 ? {} : null) + ); } - get features() { - return [...this.hopeFeatures.filter(x => x), ...this.classFeatures.filter(x => x)]; + get classFeatures() { + return ( + this.features.filter(x => x?.system?.subType === CONFIG.DH.ITEM.featureSubTypes.class) ?? + (this.features.filter(x => !x).length > 0 ? {} : null) + ); } async _preCreate(data, options, user) {