diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs index 2a18ad95..0603ae9d 100644 --- a/module/applications/sheets/actors/adversary.mjs +++ b/module/applications/sheets/actors/adversary.mjs @@ -1,19 +1,15 @@ import DHBaseActorSheet from '../api/base-actor.mjs'; -import DHActionConfig from '../../sheets-configs/action-config.mjs'; -import DHAdversarySettings from '../../sheets-configs/adversary-settings.mjs'; + +/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ export default class AdversarySheet extends DHBaseActorSheet { static DEFAULT_OPTIONS = { classes: ['adversary'], position: { width: 660, height: 766 }, actions: { - reactionRoll: this.reactionRoll, + reactionRoll: AdversarySheet.#reactionRoll, useItem: this.useItem, toChat: this.toChat, - attackConfigure: this.attackConfigure, - addExperience: this.addExperience, - removeExperience: this.removeExperience, - openSettings: this.openSettings }, window: { resizable: true @@ -51,7 +47,15 @@ export default class AdversarySheet extends DHBaseActorSheet { return item; } - static async reactionRoll(event) { + /* -------------------------------------------- */ + /* Application Clicks Actions */ + /* -------------------------------------------- */ + + /** + * Performs a reaction roll for an Adversary. + * @type {ApplicationClickAction} + */ + static #reactionRoll(event) { const config = { event: event, title: `Reaction Roll: ${this.actor.name}`, @@ -65,18 +69,23 @@ export default class AdversarySheet extends DHBaseActorSheet { mute: true } }; + this.actor.diceRoll(config); } - static async openSettings() { - await new DHAdversarySettings(this.document).render(true); - } - + /** + * + * @type {ApplicationClickAction} + */ static async useItem(event) { const action = this.getItem(event) ?? this.actor.system.attack; action.use(event); } + /** + * + * @type {ApplicationClickAction} + */ static async toChat(event, button) { if (button?.dataset?.type === 'experience') { const experience = this.document.system.experiences[button.dataset.uuid]; @@ -103,21 +112,4 @@ export default class AdversarySheet extends DHBaseActorSheet { } } - static async attackConfigure(event) { - await new DHActionConfig(this.document.system.attack).render(true); - } - - static async addExperience() { - const experienceId = foundry.utils.randomID(); - await this.document.update({ - [`system.experiences.${experienceId}`]: { id: experienceId, name: 'Experience', value: 1 } - }); - } - - static async removeExperience(_, button) { - await this.document.update({ - [`system.experiences.-=${button.dataset.experience}`]: null - }); - } - } diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index 06cc985e..6dc13fff 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -172,7 +172,8 @@ export default class CharacterSheet extends DHBaseActorSheet { /** * Get the set of ContextMenu options. - * @returns {import('@client/applications/ux/context-menu.mjs').ContextMenuEntry[]} The Array of context options passed to the ContextMenu instance + * @returns {import('@client/applications/ux/context-menu.mjs').ContextMenuEntry[]} - The Array of context options passed to the ContextMenu instance + * @this {CharacterSheet} * @protected */ static _getContextMenuOptions() { @@ -199,7 +200,7 @@ export default class CharacterSheet extends DHBaseActorSheet { const item = getItem(el); return ['weapon', 'armor'].includes(item.type) && !item.system.equipped; }, - callback: CharacterSheet.toggleEquipItem.bind(this) + callback: CharacterSheet.#toggleEquipItem.bind(this) }, { name: 'DAGGERHEART.Sheets.PC.ContextMenu.Unequip', icon: '', @@ -207,7 +208,7 @@ export default class CharacterSheet extends DHBaseActorSheet { const item = getItem(el); return ['weapon', 'armor'].includes(item.type) && item.system.equipped; }, - callback: CharacterSheet.toggleEquipItem.bind(this) + callback: CharacterSheet.#toggleEquipItem.bind(this) }, { name: 'DAGGERHEART.Sheets.PC.ContextMenu.ToLoadout', icon: '', diff --git a/module/applications/sheets/actors/companion.mjs b/module/applications/sheets/actors/companion.mjs index f064bb2a..ccf49b86 100644 --- a/module/applications/sheets/actors/companion.mjs +++ b/module/applications/sheets/actors/companion.mjs @@ -1,5 +1,7 @@ import DHBaseActorSheet from '../api/base-actor.mjs'; -import DHCompanionSettings from '../../sheets-configs/companion-settings.mjs'; + +/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ + export default class DhCompanionSheet extends DHBaseActorSheet { static DEFAULT_OPTIONS = { @@ -7,9 +9,8 @@ export default class DhCompanionSheet extends DHBaseActorSheet { position: { width: 300 }, actions: { viewActor: this.viewActor, - openSettings: this.openSettings, useItem: this.useItem, - toChat: this.toChat + toChat: this.toChat, }, }; @@ -30,6 +31,10 @@ export default class DhCompanionSheet extends DHBaseActorSheet { } }; + /* -------------------------------------------- */ + /* Application Clicks Actions */ + /* -------------------------------------------- */ + static async viewActor(_, button) { const target = button.closest('[data-item-uuid]'); const actor = await foundry.utils.fromUuid(target.dataset.itemUuid); @@ -73,8 +78,4 @@ export default class DhCompanionSheet extends DHBaseActorSheet { item.toChat(this.document.id); } } - - static async openSettings() { - await new DHCompanionSettings(this.document).render(true); - } } diff --git a/module/applications/sheets/actors/environment.mjs b/module/applications/sheets/actors/environment.mjs index 46fa382d..a66145d5 100644 --- a/module/applications/sheets/actors/environment.mjs +++ b/module/applications/sheets/actors/environment.mjs @@ -1,22 +1,22 @@ import DHBaseActorSheet from '../api/base-actor.mjs'; -import DHEnvironmentSettings from '../../sheets-configs/environment-settings.mjs'; + +/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ export default class DhpEnvironment extends DHBaseActorSheet { + /**@inheritdoc */ static DEFAULT_OPTIONS = { classes: ['environment'], position: { width: 500 }, actions: { - addAdversary: this.addAdversary, - deleteProperty: this.deleteProperty, - openSettings: this.openSettings, useItem: this.useItem, toChat: this.toChat }, dragDrop: [{ dragSelector: '.action-section .inventory-item', dropSelector: null }] }; + /**@override */ static PARTS = { header: { template: 'systems/daggerheart/templates/sheets/actors/environment/header.hbs' }, features: { template: 'systems/daggerheart/templates/sheets/actors/environment/features.hbs' }, @@ -35,30 +35,22 @@ export default class DhpEnvironment extends DHBaseActorSheet { } }; + /* -------------------------------------------- */ + getItem(element) { const itemId = (element.target ?? element).closest('[data-item-id]').dataset.itemId, item = this.document.items.get(itemId); return item; } - static async openSettings() { - await new DHEnvironmentSettings(this.document).render(true); - } - - static async addAdversary() { - await this.document.update({ - [`system.potentialAdversaries.${foundry.utils.randomID()}.label`]: game.i18n.localize( - 'DAGGERHEART.ACTORS.Environment.newAdversary' - ) - }); - this.render(); - } - - static async deleteProperty(_, target) { - await this.document.update({ [`${target.dataset.path}.-=${target.id}`]: null }); - this.render(); - } + /* -------------------------------------------- */ + /* Application Clicks Actions */ + /* -------------------------------------------- */ + /** + * + * @type {ApplicationClickAction} + */ async viewAdversary(_, button) { const target = button.closest('[data-item-uuid]'); const adversary = await foundry.utils.fromUuid(target.dataset.itemUuid); @@ -67,7 +59,7 @@ export default class DhpEnvironment extends DHBaseActorSheet { return; } - adversary.sheet.render(true); + adversary.sheet.render({ force: true }); } static async useItem(event, button) { diff --git a/module/applications/sheets/api/base-actor.mjs b/module/applications/sheets/api/base-actor.mjs index 3a2187d7..0647857f 100644 --- a/module/applications/sheets/api/base-actor.mjs +++ b/module/applications/sheets/api/base-actor.mjs @@ -2,6 +2,8 @@ import DHApplicationMixin from './application-mixin.mjs'; const { ActorSheetV2 } = foundry.applications.sheets; +/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ + /** * A base actor sheet extending {@link ActorSheetV2} via {@link DHApplicationMixin} * @extends ActorSheetV2 @@ -17,14 +19,36 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { form: { submitOnChange: true }, - actions: {}, - dragDrop: [] + actions: { + openSettings: DHBaseActorSheet.#openSettings + }, + dragDrop: [], }; + /** + * + */ + #settingSheet; + + get settingSheet() { + const SheetClass = this.document.system.metadata.settingSheet; + return this.#settingSheet ??= SheetClass ? new SheetClass(this.document): null; + } + + /**@inheritdoc */ async _prepareContext(_options) { const context = await super._prepareContext(_options); context.isNPC = this.document.isNPC; - return context; } + + /** + * + * @type {ApplicationClickAction} + */ + static async #openSettings() { + await this.settingSheet.render({ force: true }); + } + + } \ No newline at end of file diff --git a/module/data/actor/adversary.mjs b/module/data/actor/adversary.mjs index db7d2ca1..4dcea784 100644 --- a/module/data/actor/adversary.mjs +++ b/module/data/actor/adversary.mjs @@ -1,3 +1,4 @@ +import DHAdversarySettings from '../../applications/sheets-configs/adversary-settings.mjs'; import ActionField from '../fields/actionField.mjs'; import BaseDataActor from './base.mjs'; @@ -13,7 +14,8 @@ export default class DhpAdversary extends BaseDataActor { static get metadata() { return foundry.utils.mergeObject(super.metadata, { label: 'TYPES.Actor.adversary', - type: 'adversary' + type: 'adversary', + settingSheet: DHAdversarySettings, }); } diff --git a/module/data/actor/base.mjs b/module/data/actor/base.mjs index a04138ff..d4afa51f 100644 --- a/module/data/actor/base.mjs +++ b/module/data/actor/base.mjs @@ -4,6 +4,7 @@ * @property {string} label - A localizable label used on application. * @property {string} type - The system type that this data model represents. * @property {Boolean} isNPC - This data model represents a NPC? + * @property {typeof foundry.applications.api.DocumentSheetV2} settingSheet - The sheet class used to render the settings UI for this actor type. */ export default class BaseDataActor extends foundry.abstract.TypeDataModel { /** @returns {ActorDataModelMetadata}*/ @@ -12,9 +13,15 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel { label: 'Base Actor', type: 'base', isNPC: true, + settingSheet: null, }; } + /**@returns {ActorDataModelMetadata}*/ + get metadata() { + return this.constructor.metadata; + } + /** @inheritDoc */ static defineSchema() { const fields = foundry.data.fields; diff --git a/module/data/actor/companion.mjs b/module/data/actor/companion.mjs index 8745473f..1203cc96 100644 --- a/module/data/actor/companion.mjs +++ b/module/data/actor/companion.mjs @@ -3,6 +3,7 @@ import DhLevelData from '../levelData.mjs'; import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs'; import ActionField from '../fields/actionField.mjs'; import { adjustDice, adjustRange } from '../../helpers/utils.mjs'; +import DHCompanionSettings from '../../applications/sheets-configs/companion-settings.mjs'; export default class DhCompanion extends BaseDataActor { static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Companion']; @@ -10,7 +11,8 @@ export default class DhCompanion extends BaseDataActor { static get metadata() { return foundry.utils.mergeObject(super.metadata, { label: 'TYPES.Actor.companion', - type: 'companion' + type: 'companion', + settingSheet: DHCompanionSettings }); } diff --git a/module/data/actor/environment.mjs b/module/data/actor/environment.mjs index 2cd3338f..76990e88 100644 --- a/module/data/actor/environment.mjs +++ b/module/data/actor/environment.mjs @@ -1,5 +1,6 @@ import BaseDataActor from './base.mjs'; import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; +import DHEnvironmentSettings from '../../applications/sheets-configs/environment-settings.mjs'; export default class DhEnvironment extends BaseDataActor { static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Environment']; @@ -7,7 +8,8 @@ export default class DhEnvironment extends BaseDataActor { static get metadata() { return foundry.utils.mergeObject(super.metadata, { label: 'TYPES.Actor.environment', - type: 'environment' + type: 'environment', + settingSheet: DHEnvironmentSettings }); } diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs index 1a250327..bddfb106 100644 --- a/module/data/item/base.mjs +++ b/module/data/item/base.mjs @@ -22,6 +22,11 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { }; } + /**@returns {ItemDataModelMetadata}*/ + get metadata() { + return this.constructor.metadata; + } + /** @inheritDoc */ static defineSchema() { const schema = {}; @@ -56,9 +61,9 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { /**@inheritdoc */ async _preCreate(data, options, user) { // Skip if no initial action is required or actions already exist - if (!this.constructor.metadata.hasInitialAction || !foundry.utils.isEmpty(this.actions)) return; + if (!this.metadata.hasInitialAction || !foundry.utils.isEmpty(this.actions)) return; - const metadataType = this.constructor.metadata.type; + const metadataType = this.metadata.type; const actionType = { weapon: 'attack' }[metadataType]; const ActionClass = game.system.api.models.actions.actionsTypes[actionType]; diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index c2c3a545..b48d8c26 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -11,7 +11,7 @@ export default class DhpActor extends foundry.documents.Actor { * @returns {boolean} */ get isNPC() { - return this.system.constructor.metadata.isNPC; + return this.system.metadata.isNPC; } async _preCreate(data, options, user) { diff --git a/module/documents/item.mjs b/module/documents/item.mjs index 21674009..3a9b705a 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -34,7 +34,7 @@ export default class DHItem extends foundry.documents.Item { * @returns {boolean} Returns `true` if the item is an inventory item. */ get isInventoryItem() { - return this.system.constructor.metadata.isInventoryItem ?? false; + return this.system.metadata.isInventoryItem ?? false; } /** @inheritdoc */ @@ -53,17 +53,17 @@ export default class DHItem extends foundry.documents.Item { const isInventoryItem = CONFIG.Item.dataModels[type]?.metadata?.isInventoryItem; const group = isInventoryItem === true - ? 'Inventory Items' + ? 'Inventory Items' //TODO localize : isInventoryItem === false - ? 'Character Items' - : 'Other'; + ? 'Character Items' //TODO localize + : 'Other'; //TODO localize return { value: type, label, group }; } ); if (!documentTypes.length) { - throw new Error('No document types were permitted to be created.'); + throw new Error('No document types were permitted to be created.'); //TODO localize } const sortedTypes = documentTypes.sort((a, b) => a.label.localeCompare(b.label, game.i18n.lang));