diff --git a/lang/en.json b/lang/en.json index 332de6a0..72985551 100755 --- a/lang/en.json +++ b/lang/en.json @@ -25,7 +25,8 @@ "notifications": { "adversaryMissing": "The linked adversary doesn't exist in the world.", "beastformInapplicable": "A beastform can only be applied to a Character.", - "beastformAlreadyApplied": "The character already has a beastform applied!" + "beastformAlreadyApplied": "The character already has a beastform applied!", + "featureIsMissing": "The feature doesn't exist. You should remove it." } }, "Settings": { diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 6f04acb4..3ba471db 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -128,12 +128,20 @@ export default function DHApplicationMixin(Base) { _createDragDropHandlers() { return this.options.dragDrop.map(d => { d.callbacks = { + dragstart: this._onDragStart.bind(this), drop: this._onDrop.bind(this) }; return new foundry.applications.ux.DragDrop.implementation(d); }); } + /** + * Handle dragStart event. + * @param {DragEvent} event + * @protected + */ + _onDragStart(event) {} + /** * Handle drop event. * @param {DragEvent} event diff --git a/module/applications/sheets/api/base-item.mjs b/module/applications/sheets/api/base-item.mjs index 47ba5188..049f72e1 100644 --- a/module/applications/sheets/api/base-item.mjs +++ b/module/applications/sheets/api/base-item.mjs @@ -1,6 +1,4 @@ import DHApplicationMixin from './application-mixin.mjs'; -import DHActionConfig from '../../sheets-configs/action-config.mjs'; -import { actionsTypes } from '../../../data/action/_module.mjs'; const { ItemSheetV2 } = foundry.applications.sheets; @@ -18,10 +16,14 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) { submitOnChange: true }, actions: { - addAction: DHBaseItemSheet.#addAction, - editAction: DHBaseItemSheet.#editAction, - removeAction: DHBaseItemSheet.#removeAction - } + addFeature: DHBaseItemSheet.#addFeature, + editFeature: DHBaseItemSheet.#editFeature, + removeFeature: DHBaseItemSheet.#removeFeature + }, + dragDrop: [ + { dragSelector: null, dropSelector: '.tab.features .drop-section' }, + { dragSelector: '.feature-item', dropSelector: null } + ] }; /* -------------------------------------------- */ @@ -29,7 +31,7 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) { /** @inheritdoc */ static TABS = { primary: { - tabs: [{ id: 'description' }, { id: 'actions' }, { id: 'settings' }], + tabs: [{ id: 'description' }, { id: 'features' }, { id: 'settings' }], initial: 'description', labelPrefix: 'DAGGERHEART.Sheets.TABS' } @@ -63,77 +65,89 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) { /* -------------------------------------------- */ /** - * Render a dialog prompting the user to select an action type. - * - * @returns {Promise} An object containing the selected action type. + * Add a new feature to the item, prompting the user for its type. + * @param {PointerEvent} _event - The originating click event + * @param {HTMLElement} _button - The capturing HTML element which defines the [data-action="addFeature"] */ - static async selectActionType() { - const content = await foundry.applications.handlebars.renderTemplate( - 'systems/daggerheart/templates/actionTypes/actionType.hbs', - { types: CONFIG.DH.ACTIONS.actionTypes } - ), - title = 'Select Action Type'; - - return foundry.applications.api.DialogV2.prompt({ - window: { title }, - content, - ok: { - label: title, - callback: (event, button, dialog) => button.form.elements.type.value - } + static async #addFeature(_event, _button) { + const feature = await game.items.documentClass.create({ + id: foundry.utils.randomID(), + type: 'feature', + name: game.i18n.localize('DAGGERHEART.General.newFeature') + }); + await this.document.update({ + 'system.features': [...this.document.system.features.filter(x => x).map(x => x.uuid), feature.uuid] }); } /** - * Add a new action to the item, prompting the user for its type. + * Edit an existing feature on the item * @param {PointerEvent} _event - The originating click event - * @param {HTMLElement} _button - The capturing HTML element which defines the [data-action="addAction"] + * @param {HTMLElement} button - The capturing HTML element which defines the [data-action="editFeature"] */ - static async #addAction(_event, _button) { - const actionType = await DHBaseItemSheet.selectActionType(); - if (!actionType) return; - try { - const cls = actionsTypes[actionType] ?? actionsTypes.attack, - action = new cls( - { - _id: foundry.utils.randomID(), - type: actionType, - name: game.i18n.localize(CONFIG.DH.ACTIONS.actionTypes[actionType].name), - ...cls.getSourceConfig(this.document) - }, - { - parent: this.document - } - ); - await this.document.update({ 'system.actions': [...this.document.system.actions, action] }); - await new DHActionConfig(this.document.system.actions[this.document.system.actions.length - 1]).render({ - force: true - }); - } catch (error) { - console.log(error); + static async #editFeature(_event, button) { + const target = button.closest('.feature-item'); + const feature = this.document.system.features.find(x => x?.id === target.id); + if (!feature) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.notifications.featureIsMissing')); + return; + } + + feature.sheet.render(true); + } + + /** + * Remove a feature from the item. + * @param {PointerEvent} event - The originating click event + * @param {HTMLElement} button - The capturing HTML element which defines the [data-action="removeFeature"] + */ + static async #removeFeature(event, button) { + event.stopPropagation(); + const target = button.closest('.feature-item'); + + await this.document.update({ + 'system.features': this.document.system.features + .filter(feature => feature && feature.id !== target.id) + .map(x => x.uuid) + }); + } + + /* -------------------------------------------- */ + /* Application Drag/Drop */ + /* -------------------------------------------- */ + + /** + * On dragStart on the item. + * @param {DragEvent} event - The drag event + */ + async _onDragStart(event) { + const featureItem = event.currentTarget.closest('.feature-item'); + + if (featureItem) { + const feature = this.document.system.features.find(x => x?.id === featureItem.id); + if (!feature) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.notifications.featureIsMissing')); + return; + } + + const featureData = { type: 'Item', data: { ...feature.toObject(), _id: null }, fromInternal: true }; + event.dataTransfer.setData('text/plain', JSON.stringify(featureData)); + event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0); } } /** - * Edit an existing action on the item - * @param {PointerEvent} _event - The originating click event - * @param {HTMLElement} button - The capturing HTML element which defines the [data-action="editAction"] + * On drop on the item. + * @param {DragEvent} event - The drag event */ - static async #editAction(_event, button) { - const action = this.document.system.actions[button.dataset.index]; - await new DHActionConfig(action).render({ force: true }); - } + async _onDrop(event) { + const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); + if (data.fromInternal) return; - /** - * Remove an action from the item. - * @param {PointerEvent} event - The originating click event - * @param {HTMLElement} button - The capturing HTML element which defines the [data-action="removeAction"] - */ - static async #removeAction(event, button) { - event.stopPropagation(); - const actionIndex = button.closest('[data-index]').dataset.index; - await this.document.update({ - 'system.actions': this.document.system.actions.filter((_, index) => index !== Number.parseInt(actionIndex)) - }); + const item = await fromUuid(data.uuid); + if (item?.type === 'feature') { + const current = this.document.system.features.map(x => x.uuid); + await this.document.update({ 'system.features': [...current, item.uuid] }); + } } } diff --git a/module/applications/sheets/api/heritage-sheet.mjs b/module/applications/sheets/api/heritage-sheet.mjs index 4938f5b0..d9a63388 100644 --- a/module/applications/sheets/api/heritage-sheet.mjs +++ b/module/applications/sheets/api/heritage-sheet.mjs @@ -10,9 +10,9 @@ export default class DHHeritageSheet extends DHBaseItemSheet { static PARTS = { tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' }, - actions: { - template: 'systems/daggerheart/templates/sheets/global/tabs/tab-actions.hbs', - scrollable: ['.actions'] + feature: { + template: 'systems/daggerheart/templates/sheets/global/tabs/tab-features.hbs', + scrollable: ['.feature'] }, effects: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-effects.hbs', @@ -23,7 +23,7 @@ export default class DHHeritageSheet extends DHBaseItemSheet { /** @override*/ static TABS = { primary: { - tabs: [{ id: 'description' }, { id: 'actions' }, { id: 'effects' }], + tabs: [{ id: 'description' }, { id: 'features' }, { id: 'effects' }], initial: 'description', labelPrefix: 'DAGGERHEART.Sheets.TABS' } diff --git a/module/applications/sheets/items/armor.mjs b/module/applications/sheets/items/armor.mjs index bb98c8c3..6bf13ae6 100644 --- a/module/applications/sheets/items/armor.mjs +++ b/module/applications/sheets/items/armor.mjs @@ -9,7 +9,7 @@ export default class ArmorSheet extends DHBaseItemSheet { { selector: '.features-input', options: () => CONFIG.DH.ITEM.armorFeatures, - callback: ArmorSheet.#onFeatureSelect + callback: ArmorSheet.#onArmorFeatureSelect } ] }; @@ -19,9 +19,9 @@ export default class ArmorSheet extends DHBaseItemSheet { header: { template: 'systems/daggerheart/templates/sheets/items/armor/header.hbs' }, tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' }, - actions: { - template: 'systems/daggerheart/templates/sheets/global/tabs/tab-actions.hbs', - scrollable: ['.actions'] + features: { + template: 'systems/daggerheart/templates/sheets/global/tabs/tab-features.hbs', + scrollable: ['.features'] }, settings: { template: 'systems/daggerheart/templates/sheets/items/armor/settings.hbs', @@ -35,7 +35,7 @@ export default class ArmorSheet extends DHBaseItemSheet { switch (partId) { case 'settings': - context.features = this.document.system.features.map(x => x.value); + context.armorFeatures = this.document.system.armorFeatures.map(x => x.value); break; } @@ -46,7 +46,7 @@ export default class ArmorSheet extends DHBaseItemSheet { * Callback function used by `tagifyElement`. * @param {Array} selectedOptions - The currently selected tag objects. */ - static async #onFeatureSelect(selectedOptions) { - await this.document.update({ 'system.features': selectedOptions.map(x => ({ value: x.value })) }); + static async #onArmorFeatureSelect(selectedOptions) { + await this.document.update({ 'system.armorFeatures': selectedOptions.map(x => ({ value: x.value })) }); } } diff --git a/module/applications/sheets/items/beastform.mjs b/module/applications/sheets/items/beastform.mjs index 9ce9b739..f1be204a 100644 --- a/module/applications/sheets/items/beastform.mjs +++ b/module/applications/sheets/items/beastform.mjs @@ -3,12 +3,7 @@ import DHBaseItemSheet from '../api/base-item.mjs'; export default class BeastformSheet extends DHBaseItemSheet { /**@inheritdoc */ static DEFAULT_OPTIONS = { - classes: ['beastform'], - dragDrop: [{ dragSelector: null, dropSelector: '.drop-section' }], - actions: { - editFeature: this.editFeature, - removeFeature: this.removeFeature - } + classes: ['beastform'] }; /**@override */ @@ -40,26 +35,4 @@ export default class BeastformSheet extends DHBaseItemSheet { return context; } - - static editFeature(event) { - const target = event.target.closest('[data-action="editFeature"]'); - const feature = this.document.system.features[target.dataset.index]; - feature.sheet.render({ force: true }); - } - - static async removeFeature(_, target) { - const current = this.document.system.features.map(x => x.uuid); - await this.document.update({ - 'system.features': current.filter((_, index) => index !== Number(target.dataset.index)) - }); - } - - async _onDrop(event) { - const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); - const item = await fromUuid(data.uuid); - if (item.type === 'feature') { - const current = this.document.system.features.map(x => x.uuid); - await this.document.update({ 'system.features': [...current, item.uuid] }); - } - } } diff --git a/module/applications/sheets/items/consumable.mjs b/module/applications/sheets/items/consumable.mjs index f6fb1ba5..8db63582 100644 --- a/module/applications/sheets/items/consumable.mjs +++ b/module/applications/sheets/items/consumable.mjs @@ -12,9 +12,9 @@ export default class ConsumableSheet extends DHBaseItemSheet { header: { template: 'systems/daggerheart/templates/sheets/items/consumable/header.hbs' }, tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' }, - actions: { - template: 'systems/daggerheart/templates/sheets/global/tabs/tab-actions.hbs', - scrollable: ['.actions'] + features: { + template: 'systems/daggerheart/templates/sheets/global/tabs/tab-features.hbs', + scrollable: ['.features'] }, settings: { template: 'systems/daggerheart/templates/sheets/items/consumable/settings.hbs', diff --git a/module/applications/sheets/items/domainCard.mjs b/module/applications/sheets/items/domainCard.mjs index d7a70741..75420d38 100644 --- a/module/applications/sheets/items/domainCard.mjs +++ b/module/applications/sheets/items/domainCard.mjs @@ -10,7 +10,7 @@ export default class DomainCardSheet extends DHBaseItemSheet { /** @override */ static TABS = { primary: { - tabs: [{ id: 'description' }, { id: 'actions' }, { id: 'settings' }, { id: 'effects' }], + tabs: [{ id: 'description' }, { id: 'features' }, { id: 'settings' }, { id: 'effects' }], initial: 'description', labelPrefix: 'DAGGERHEART.Sheets.TABS' } @@ -21,9 +21,9 @@ export default class DomainCardSheet extends DHBaseItemSheet { header: { template: 'systems/daggerheart/templates/sheets/items/domainCard/header.hbs' }, tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' }, - actions: { - template: 'systems/daggerheart/templates/sheets/global/tabs/tab-actions.hbs', - scrollable: ['.actions'] + features: { + template: 'systems/daggerheart/templates/sheets/global/tabs/tab-features.hbs', + scrollable: ['.features'] }, settings: { template: 'systems/daggerheart/templates/sheets/items/domainCard/settings.hbs', diff --git a/module/applications/sheets/items/feature.mjs b/module/applications/sheets/items/feature.mjs index a5b8bd8f..4f3bb438 100644 --- a/module/applications/sheets/items/feature.mjs +++ b/module/applications/sheets/items/feature.mjs @@ -1,3 +1,5 @@ +import { actionsTypes } from '../../../data/action/_module.mjs'; +import DHActionConfig from '../../sheets-configs/action-config.mjs'; import DHBaseItemSheet from '../api/base-item.mjs'; export default class FeatureSheet extends DHBaseItemSheet { @@ -6,7 +8,12 @@ export default class FeatureSheet extends DHBaseItemSheet { id: 'daggerheart-feature', classes: ['feature'], position: { height: 600 }, - window: { resizable: true } + window: { resizable: true }, + actions: { + addAction: FeatureSheet.#addAction, + editAction: FeatureSheet.#editAction, + removeAction: FeatureSheet.#removeAction + } }; /**@override */ @@ -41,4 +48,83 @@ export default class FeatureSheet extends DHBaseItemSheet { return context; } + + /* -------------------------------------------- */ + /* Application Clicks Actions */ + /* -------------------------------------------- */ + + /** + * Render a dialog prompting the user to select an action type. + * + * @returns {Promise} An object containing the selected action type. + */ + static async selectActionType() { + const content = await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/actionTypes/actionType.hbs', + { types: CONFIG.DH.ACTIONS.actionTypes } + ), + title = 'Select Action Type'; + + return foundry.applications.api.DialogV2.prompt({ + window: { title }, + content, + ok: { + label: title, + callback: (event, button, dialog) => button.form.elements.type.value + } + }); + } + + /** + * Add a new action to the item, prompting the user for its type. + * @param {PointerEvent} _event - The originating click event + * @param {HTMLElement} _button - The capturing HTML element which defines the [data-action="addAction"] + */ + static async #addAction(_event, _button) { + const actionType = await FeatureSheet.selectActionType(); + if (!actionType) return; + try { + const cls = actionsTypes[actionType] ?? actionsTypes.attack, + action = new cls( + { + _id: foundry.utils.randomID(), + type: actionType, + name: game.i18n.localize(CONFIG.DH.ACTIONS.actionTypes[actionType].name), + ...cls.getSourceConfig(this.document) + }, + { + parent: this.document + } + ); + await this.document.update({ 'system.actions': [...this.document.system.actions, action] }); + await new DHActionConfig(this.document.system.actions[this.document.system.actions.length - 1]).render({ + force: true + }); + } catch (error) { + console.log(error); + } + } + + /** + * Edit an existing action on the item + * @param {PointerEvent} _event - The originating click event + * @param {HTMLElement} button - The capturing HTML element which defines the [data-action="editAction"] + */ + static async #editAction(_event, button) { + const action = this.document.system.actions[button.dataset.index]; + await new DHActionConfig(action).render({ force: true }); + } + + /** + * Remove an action from the item. + * @param {PointerEvent} event - The originating click event + * @param {HTMLElement} button - The capturing HTML element which defines the [data-action="removeAction"] + */ + static async #removeAction(event, button) { + event.stopPropagation(); + const actionIndex = button.closest('[data-index]').dataset.index; + await this.document.update({ + 'system.actions': this.document.system.actions.filter((_, index) => index !== Number.parseInt(actionIndex)) + }); + } } diff --git a/module/applications/sheets/items/miscellaneous.mjs b/module/applications/sheets/items/miscellaneous.mjs index 62df4e8c..fbd4f0c1 100644 --- a/module/applications/sheets/items/miscellaneous.mjs +++ b/module/applications/sheets/items/miscellaneous.mjs @@ -12,9 +12,9 @@ export default class MiscellaneousSheet extends DHBaseItemSheet { header: { template: 'systems/daggerheart/templates/sheets/items/miscellaneous/header.hbs' }, tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' }, - actions: { - template: 'systems/daggerheart/templates/sheets/global/tabs/tab-actions.hbs', - scrollable: ['.actions'] + features: { + template: 'systems/daggerheart/templates/sheets/global/tabs/tab-features.hbs', + scrollable: ['.features'] }, settings: { template: 'systems/daggerheart/templates/sheets/items/miscellaneous/settings.hbs', diff --git a/module/applications/sheets/items/weapon.mjs b/module/applications/sheets/items/weapon.mjs index fdce55fc..f3ea918c 100644 --- a/module/applications/sheets/items/weapon.mjs +++ b/module/applications/sheets/items/weapon.mjs @@ -8,7 +8,7 @@ export default class WeaponSheet extends DHBaseItemSheet { { selector: '.features-input', options: () => CONFIG.DH.ITEM.weaponFeatures, - callback: WeaponSheet.#onFeatureSelect + callback: WeaponSheet.#onWeaponFeatureSelect } ] }; @@ -18,9 +18,9 @@ export default class WeaponSheet extends DHBaseItemSheet { header: { template: 'systems/daggerheart/templates/sheets/items/weapon/header.hbs' }, tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' }, - actions: { - template: 'systems/daggerheart/templates/sheets/global/tabs/tab-actions.hbs', - scrollable: ['.actions'] + features: { + template: 'systems/daggerheart/templates/sheets/global/tabs/tab-features.hbs', + scrollable: ['.features'] }, settings: { template: 'systems/daggerheart/templates/sheets/items/weapon/settings.hbs', @@ -34,7 +34,7 @@ export default class WeaponSheet extends DHBaseItemSheet { switch (partId) { case 'settings': - context.features = this.document.system.features.map(x => x.value); + context.weaponFeatures = this.document.system.weaponFeatures.map(x => x.value); break; } @@ -45,7 +45,7 @@ export default class WeaponSheet extends DHBaseItemSheet { * Callback function used by `tagifyElement`. * @param {Array} selectedOptions - The currently selected tag objects. */ - static async #onFeatureSelect(selectedOptions) { - await this.document.update({ 'system.features': selectedOptions.map(x => ({ value: x.value })) }); + static async #onWeaponFeatureSelect(selectedOptions) { + await this.document.update({ 'system.weaponFeatures': selectedOptions.map(x => ({ value: x.value })) }); } } diff --git a/module/data/item/ancestry.mjs b/module/data/item/ancestry.mjs index 8af6e081..463fe6c1 100644 --- a/module/data/item/ancestry.mjs +++ b/module/data/item/ancestry.mjs @@ -1,4 +1,4 @@ -import ActionField from '../fields/actionField.mjs'; +import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; import BaseDataItem from './base.mjs'; export default class DHAncestry extends BaseDataItem { @@ -13,10 +13,9 @@ export default class DHAncestry extends BaseDataItem { /** @inheritDoc */ static defineSchema() { - const fields = foundry.data.fields; return { ...super.defineSchema(), - actions: new fields.ArrayField(new ActionField()) + features: new ForeignDocumentUUIDArrayField({ type: 'Item' }) }; } } diff --git a/module/data/item/armor.mjs b/module/data/item/armor.mjs index 4e5a26e6..b3eac15d 100644 --- a/module/data/item/armor.mjs +++ b/module/data/item/armor.mjs @@ -1,6 +1,6 @@ import BaseDataItem from './base.mjs'; -import ActionField from '../fields/actionField.mjs'; import { armorFeatures } from '../../config/itemConfig.mjs'; +import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; export default class DHArmor extends BaseDataItem { /** @inheritDoc */ @@ -22,7 +22,7 @@ export default class DHArmor extends BaseDataItem { tier: new fields.NumberField({ required: true, integer: true, initial: 1, min: 1 }), equipped: new fields.BooleanField({ initial: false }), baseScore: new fields.NumberField({ integer: true, initial: 0 }), - features: new fields.ArrayField( + armorFeatures: new fields.ArrayField( new fields.SchemaField({ value: new fields.StringField({ required: true, @@ -40,32 +40,28 @@ export default class DHArmor extends BaseDataItem { major: new fields.NumberField({ integer: true, initial: 0 }), severe: new fields.NumberField({ integer: true, initial: 0 }) }), - actions: new fields.ArrayField(new ActionField()) + features: new ForeignDocumentUUIDArrayField({ type: 'Item' }) }; } - get featureInfo() { - return this.feature ? CONFIG.DH.ITEM.armorFeatures[this.feature] : null; - } - async _preUpdate(changes, options, user) { const allowed = await super._preUpdate(changes, options, user); if (allowed === false) return false; - if (changes.system.features) { - const removed = this.features.filter(x => !changes.system.features.includes(x)); - const added = changes.system.features.filter(x => !this.features.includes(x)); + if (changes.system?.armorFeatures) { + const removed = this.armorFeatures.filter(x => !changes.system.armorFeatures.includes(x)); + const added = changes.system.armorFeatures.filter(x => !this.armorFeatures.includes(x)); - for (var feature of removed) { - for (var effectId of feature.effectIds) { + for (var armorFeature of removed) { + for (var effectId of armorFeature.effectIds) { await this.parent.effects.get(effectId).delete(); } - changes.system.actions = this.actions.filter(x => !feature.actionIds.includes(x._id)); + changes.system.actions = this.actions.filter(x => !armorFeature.actionIds.includes(x._id)); } - for (var feature of added) { - const featureData = armorFeatures[feature.value]; + for (var armorFeature of added) { + const featureData = armorFeatures[armorFeature.value]; if (featureData.effects?.length > 0) { const embeddedItems = await this.parent.createEmbeddedDocuments('ActiveEffect', [ { @@ -74,7 +70,7 @@ export default class DHArmor extends BaseDataItem { changes: featureData.effects.flatMap(x => x.changes) } ]); - feature.effectIds = embeddedItems.map(x => x.id); + armorFeature.effectIds = embeddedItems.map(x => x.id); } if (featureData.actions?.length > 0) { const newActions = featureData.actions.map(action => { @@ -85,7 +81,7 @@ export default class DHArmor extends BaseDataItem { ); }); changes.system.actions = [...this.actions, ...newActions]; - feature.actionIds = newActions.map(x => x._id); + armorFeature.actionIds = newActions.map(x => x._id); } } } diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs index c90202fb..5946dc15 100644 --- a/module/data/item/base.mjs +++ b/module/data/item/base.mjs @@ -1,4 +1,4 @@ -// import { actionsTypes } from '../action/_module.mjs'; +import { actionsTypes } from '../action/_module.mjs'; /** * Describes metadata about the item data model type @@ -60,8 +60,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { const actionType = { weapon: 'attack' }[this.constructor.metadata.type], - cls = game.system.api.models.actionsTypes[actionType], - // cls = actionsTypes.attack, + cls = actionsTypes[actionType], action = new cls( { _id: foundry.utils.randomID(), diff --git a/module/data/item/community.mjs b/module/data/item/community.mjs index d0ede69a..b2827242 100644 --- a/module/data/item/community.mjs +++ b/module/data/item/community.mjs @@ -1,4 +1,4 @@ -import ActionField from '../fields/actionField.mjs'; +import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; import BaseDataItem from './base.mjs'; export default class DHCommunity extends BaseDataItem { @@ -16,7 +16,7 @@ export default class DHCommunity extends BaseDataItem { const fields = foundry.data.fields; return { ...super.defineSchema(), - actions: new fields.ArrayField(new ActionField()) + features: new ForeignDocumentUUIDArrayField({ type: 'Item' }) }; } } diff --git a/module/data/item/consumable.mjs b/module/data/item/consumable.mjs index 3e70f97a..78c7584a 100644 --- a/module/data/item/consumable.mjs +++ b/module/data/item/consumable.mjs @@ -1,5 +1,5 @@ import BaseDataItem from './base.mjs'; -import ActionField from '../fields/actionField.mjs'; +import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; export default class DHConsumable extends BaseDataItem { /** @inheritDoc */ @@ -19,7 +19,7 @@ export default class DHConsumable extends BaseDataItem { return { ...super.defineSchema(), consumeOnUse: new fields.BooleanField({ initial: false }), - actions: new fields.ArrayField(new ActionField()) + features: new ForeignDocumentUUIDArrayField({ type: 'Item' }) }; } } diff --git a/module/data/item/domainCard.mjs b/module/data/item/domainCard.mjs index 3f64d74f..2f6a77ec 100644 --- a/module/data/item/domainCard.mjs +++ b/module/data/item/domainCard.mjs @@ -1,5 +1,5 @@ import BaseDataItem from './base.mjs'; -import ActionField from '../fields/actionField.mjs'; +import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; export default class DHDomainCard extends BaseDataItem { /** @inheritDoc */ @@ -30,7 +30,7 @@ export default class DHDomainCard extends BaseDataItem { }), foundation: new fields.BooleanField({ initial: false }), inVault: new fields.BooleanField({ initial: false }), - actions: new fields.ArrayField(new ActionField()) + features: new ForeignDocumentUUIDArrayField({ type: 'Item' }) }; } diff --git a/module/data/item/miscellaneous.mjs b/module/data/item/miscellaneous.mjs index cad07f48..87f2b242 100644 --- a/module/data/item/miscellaneous.mjs +++ b/module/data/item/miscellaneous.mjs @@ -1,5 +1,5 @@ import BaseDataItem from './base.mjs'; -import ActionField from '../fields/actionField.mjs'; +import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; export default class DHMiscellaneous extends BaseDataItem { /** @inheritDoc */ @@ -15,10 +15,9 @@ export default class DHMiscellaneous extends BaseDataItem { /** @inheritDoc */ static defineSchema() { - const fields = foundry.data.fields; return { ...super.defineSchema(), - actions: new fields.ArrayField(new ActionField()) + features: new ForeignDocumentUUIDArrayField({ type: 'Item' }) }; } } diff --git a/module/data/item/weapon.mjs b/module/data/item/weapon.mjs index 30bed1e0..a9104f5c 100644 --- a/module/data/item/weapon.mjs +++ b/module/data/item/weapon.mjs @@ -1,5 +1,6 @@ import BaseDataItem from './base.mjs'; -import ActionField from '../fields/actionField.mjs'; +import { actionsTypes } from '../action/_module.mjs'; +import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; export default class DHWeapon extends BaseDataItem { /** @inheritDoc */ @@ -37,7 +38,7 @@ export default class DHWeapon extends BaseDataItem { initial: 'physical' }) }), - features: new fields.ArrayField( + weaponFeatures: new fields.ArrayField( new fields.SchemaField({ value: new fields.StringField({ required: true, @@ -48,7 +49,7 @@ export default class DHWeapon extends BaseDataItem { actionIds: new fields.ArrayField(new fields.StringField({ required: true })) }) ), - actions: new fields.ArrayField(new ActionField()) + features: new ForeignDocumentUUIDArrayField({ type: 'Item' }) }; } @@ -56,20 +57,20 @@ export default class DHWeapon extends BaseDataItem { const allowed = await super._preUpdate(changes, options, user); if (allowed === false) return false; - if (changes.system.features) { - const removed = this.features.filter(x => !changes.system.features.includes(x)); - const added = changes.system.features.filter(x => !this.features.includes(x)); + if (changes.system?.weaponFeatures) { + const removed = this.weaponFeatures.filter(x => !changes.system.weaponFeatures.includes(x)); + const added = changes.system.weaponFeatures.filter(x => !this.weaponFeatures.includes(x)); - for (var feature of removed) { - for (var effectId of feature.effectIds) { + for (var weaponFeature of removed) { + for (var effectId of weaponFeature.effectIds) { await this.parent.effects.get(effectId).delete(); } - changes.system.actions = this.actions.filter(x => !feature.actionIds.includes(x._id)); + changes.system.actions = this.actions.filter(x => !weaponFeature.actionIds.includes(x._id)); } - for (var feature of added) { - const featureData = CONFIG.DH.ITEM.weaponFeatures[feature.value]; + for (var weaponFeature of added) { + const featureData = CONFIG.DH.ITEM.weaponFeatures[weaponFeature.value]; if (featureData.effects?.length > 0) { const embeddedItems = await this.parent.createEmbeddedDocuments('ActiveEffect', [ { @@ -78,18 +79,18 @@ export default class DHWeapon extends BaseDataItem { changes: featureData.effects.flatMap(x => x.changes) } ]); - feature.effectIds = embeddedItems.map(x => x.id); + weaponFeature.effectIds = embeddedItems.map(x => x.id); } if (featureData.actions?.length > 0) { const newActions = featureData.actions.map(action => { - const cls = CONFIG.DH.ACTIONS.actionsTypes[action.type]; + const cls = actionsTypes[action.type]; return new cls( { ...action, _id: foundry.utils.randomID(), name: game.i18n.localize(action.name) }, { parent: this } ); }); changes.system.actions = [...this.actions, ...newActions]; - feature.actionIds = newActions.map(x => x._id); + weaponFeature.actionIds = newActions.map(x => x._id); } } } diff --git a/templates/sheets/global/tabs/tab-features.hbs b/templates/sheets/global/tabs/tab-features.hbs index 59a43655..8ea1d534 100644 --- a/templates/sheets/global/tabs/tab-features.hbs +++ b/templates/sheets/global/tabs/tab-features.hbs @@ -4,17 +4,17 @@ data-group='{{tabs.features.group}}' >
- {{localize "DAGGERHEART.Sheets.Global.Features"}} + {{localize "DAGGERHEART.Sheets.Global.Features"}}
- {{#each document.system.features as |feature index|}} + {{#each document.system.features as |feature|}}
{{feature.name}}
- +
{{/each}}