diff --git a/lang/en.json b/lang/en.json index a4aa7c2f..d908a091 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1189,6 +1189,7 @@ "LevelUp": "You can level up", "Features": "Features", "CompanionFeatures": "Companion Features", + "beastformFeatures": "Beastform Features", "Tabs": { "Features": "Features", "Inventory": "Inventory", diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index d82ac900..cbe8edb5 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -307,7 +307,7 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { const itemId = listElement.dataset.itemId; if (listElement.dataset.type === 'effect') { return this.document.effects.get(itemId); - } else if (listElement.dataset.type === 'features') { + } else if (['armor', 'weapon', 'feature', 'consumable', 'miscellaneous'].includes(listElement.dataset.type)) { return this.document.items.get(itemId); } else { return this.document.system[listElement.dataset.type].system.actions.find(x => x.id === itemId); @@ -618,7 +618,9 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { if (!item) return; // Should dandle its actions. Or maybe they'll be separate buttons as per an Issue on the board - if (item.type === 'feature' || item instanceof ActiveEffect) { + if (item.type === 'feature') { + item.use(event); + } else if (item instanceof ActiveEffect) { item.toChat(this); } else { const wasUsed = await item.use(event); diff --git a/module/applications/sheets/items/beastform.mjs b/module/applications/sheets/items/beastform.mjs index 12134558..ab01b9d5 100644 --- a/module/applications/sheets/items/beastform.mjs +++ b/module/applications/sheets/items/beastform.mjs @@ -19,12 +19,16 @@ export default class BeastformSheet extends DHBaseItemSheet { features: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-features.hbs', scrollable: ['.features'] + }, + effects: { + template: 'systems/daggerheart/templates/sheets/global/tabs/tab-effects.hbs', + scrollable: ['.effects'] } }; static TABS = { primary: { - tabs: [{ id: 'settings' }, { id: 'features' }], + tabs: [{ id: 'settings' }, { id: 'features' }, { id: 'effects' }], initial: 'settings', labelPrefix: 'DAGGERHEART.Sheets.TABS' } diff --git a/module/data/action/action.mjs b/module/data/action/action.mjs index f6c56bf7..ea1d17f4 100644 --- a/module/data/action/action.mjs +++ b/module/data/action/action.mjs @@ -786,14 +786,12 @@ export class DhBeastformAction extends DHBaseAction { } async handleActiveTransformations() { - const activeBeastforms = this.actor.items.filter(x => x.type === 'beastform'); - if (activeBeastforms.length > 0) { - for (let form of activeBeastforms) { - await form.delete(); + const beastformEffects = this.actor.effects.filter(x => x.type === 'beastform'); + if (beastformEffects.length > 0) { + for (let effect of beastformEffects) { + await effect.delete(); } - this.actor.effects.filter(x => x.type === 'beastform').forEach(x => x.delete()); - return true; } diff --git a/module/data/activeEffect/beastformEffect.mjs b/module/data/activeEffect/beastformEffect.mjs index 19ed9efa..5cb19b7d 100644 --- a/module/data/activeEffect/beastformEffect.mjs +++ b/module/data/activeEffect/beastformEffect.mjs @@ -1,17 +1,45 @@ +import { updateActorTokens } from '../../helpers/utils.mjs'; + export default class BeastformEffect extends foundry.abstract.TypeDataModel { static defineSchema() { const fields = foundry.data.fields; return { - isBeastform: new fields.BooleanField({ initial: false }) + isBeastform: new fields.BooleanField({ initial: false }), + characterTokenData: new fields.SchemaField({ + tokenImg: new fields.FilePathField({ + categories: ['IMAGE'], + base64: false, + nullable: true + }), + tokenSize: new fields.SchemaField({ + height: new fields.NumberField({ integer: true, nullable: true }), + width: new fields.NumberField({ integer: true, nullable: true }) + }) + }), + advantageOn: new fields.ArrayField(new fields.StringField()), + featureIds: new fields.ArrayField(new fields.StringField()), + effectIds: new fields.ArrayField(new fields.StringField()) }; } async _preDelete() { if (this.parent.parent.type === 'character') { - for (let item of this.parent.parent.items) { - if (item.type === 'beastform') { - await item.delete(); + const update = { + height: this.characterTokenData.tokenSize.height, + width: this.characterTokenData.tokenSize.width, + texture: { + src: this.characterTokenData.tokenImg } + }; + + await updateActorTokens(this.parent.parent, update); + + for (var feature of this.parent.parent.items.filter(x => this.featureIds.includes(x.id))) { + await feature.delete(); + } + + for (var effect of this.parent.parent.effects.filter(x => this.effectIds.includes(x.id))) { + await effect.delete(); } } } diff --git a/module/data/item/beastform.mjs b/module/data/item/beastform.mjs index 22b8e30a..899d4355 100644 --- a/module/data/item/beastform.mjs +++ b/module/data/item/beastform.mjs @@ -33,18 +33,6 @@ export default class DHBeastform extends BaseDataItem { height: new fields.NumberField({ integer: true, min: 1, initial: null, nullable: true }), width: new fields.NumberField({ integer: true, min: 1, initial: null, nullable: true }) }), - characterTokenData: new fields.SchemaField({ - tokenImg: new fields.FilePathField({ - categories: ['IMAGE'], - base64: false, - nullable: true, - initial: null - }), - tokenSize: new fields.SchemaField({ - height: new fields.NumberField({ integer: true, initial: null, nullable: true }), - width: new fields.NumberField({ integer: true, initial: null, nullable: true }) - }) - }), examples: new fields.StringField(), advantageOn: new fields.ArrayField(new fields.StringField()), features: new ForeignDocumentUUIDArrayField({ type: 'Item' }) @@ -65,49 +53,44 @@ export default class DHBeastform extends BaseDataItem { return; } - await this.updateSource({ - characterTokenData: { - tokenImg: this.parent.parent.prototypeToken.texture.src, - tokenSize: { - height: this.parent.parent.prototypeToken.height, - width: this.parent.parent.prototypeToken.width - } - } - }); - } + const features = await this.parent.parent.createEmbeddedDocuments( + 'Item', + this.features.map(x => x.toObject()) + ); + const effects = await this.parent.parent.createEmbeddedDocuments( + 'ActiveEffect', + this.parent.effects.map(x => x.toObject()) + ); - _onCreate(data, options, userId) { - super._onCreate(data, options, userId); - - const update = { - height: this.tokenSize.height, - width: this.tokenSize.width, - texture: { - src: this.tokenImg - } - }; - updateActorTokens(this.parent.parent, update); - - this.parent.parent.createEmbeddedDocuments('ActiveEffect', [ + await this.parent.parent.createEmbeddedDocuments('ActiveEffect', [ { type: 'beastform', name: game.i18n.localize('DAGGERHEART.Sheets.Beastform.beastformEffect'), img: 'icons/creatures/abilities/paw-print-pair-purple.webp', system: { - isBeastform: true + isBeastform: true, + characterTokenData: { + tokenImg: this.parent.parent.prototypeToken.texture.src, + tokenSize: { + height: this.parent.parent.prototypeToken.height, + width: this.parent.parent.prototypeToken.width + } + }, + advantageOn: this.advantageOn, + featureIds: features.map(x => x.id), + effectIds: effects.map(x => x.id) } } ]); - } - async _preDelete() { - const update = { - height: this.characterTokenData.tokenSize.height, - width: this.characterTokenData.tokenSize.width, + await updateActorTokens(this.parent.parent, { + height: this.tokenSize.height, + width: this.tokenSize.width, texture: { - src: this.characterTokenData.tokenImg + src: this.tokenImg } - }; - await updateActorTokens(this.parent.parent, update); + }); + + return false; } } diff --git a/module/documents/item.mjs b/module/documents/item.mjs index 0671e7e3..79e065fd 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -97,16 +97,16 @@ export default class DHItem extends foundry.documents.Item { async use(event) { const actions = this.system.actions; - let response; if (actions?.length) { let action = actions[0]; if (actions.length > 1 && !event?.shiftKey) { // Actions Choice Dialog action = await this.selectActionDialog(); } - if (action) response = action.use(event); + if (action) return action.use(event); } - return response; + + return this.toChat(); } async toChat(origin) {