diff --git a/module/data/activeEffect/beastformEffect.mjs b/module/data/activeEffect/beastformEffect.mjs index b5cbdb28..769b8153 100644 --- a/module/data/activeEffect/beastformEffect.mjs +++ b/module/data/activeEffect/beastformEffect.mjs @@ -6,10 +6,12 @@ export default class BeastformEffect extends BaseEffect { const fields = foundry.data.fields; return { characterTokenData: new fields.SchemaField({ + usesDynamicToken: new fields.BooleanField({ initial: false }), tokenImg: new fields.FilePathField({ categories: ['IMAGE'], base64: false, - nullable: true + nullable: true, + wildcard: true }), tokenRingImg: new fields.FilePathField({ initial: 'icons/svg/mystery-man.svg', @@ -38,20 +40,38 @@ export default class BeastformEffect extends BaseEffect { async _preDelete() { if (this.parent.parent.type === 'character') { - const update = { + const baseUpdate = { height: this.characterTokenData.tokenSize.height, - width: this.characterTokenData.tokenSize.width, + width: this.characterTokenData.tokenSize.width + }; + const update = { + ...baseUpdate, texture: { src: this.characterTokenData.tokenImg }, ring: { + enabled: this.characterTokenData.usesDynamicToken, subject: { texture: this.characterTokenData.tokenRingImg } } }; - await updateActorTokens(this.parent.parent, update); + const updateToken = token => ({ + ...baseUpdate, + 'texture': { + enabled: this.characterTokenData.usesDynamicToken, + src: token.flags.daggerheart.beastformTokenImg + }, + 'ring': { + subject: { + texture: token.flags.daggerheart.beastformSubjectTexture + } + }, + 'flags.daggerheart': { '-=beastformTokenImg': null, '-=beastformSubjectTexture': null } + }); + + await updateActorTokens(this.parent.parent, update, updateToken); await this.parent.parent.deleteEmbeddedDocuments('Item', this.featureIds); await this.parent.parent.deleteEmbeddedDocuments('ActiveEffect', this.effectIds); diff --git a/module/data/item/beastform.mjs b/module/data/item/beastform.mjs index 8f5dffe6..51ca298d 100644 --- a/module/data/item/beastform.mjs +++ b/module/data/item/beastform.mjs @@ -160,7 +160,6 @@ export default class DHBeastform extends BaseDataItem { this.parent.effects.filter(x => x.type !== 'beastform').map(x => x.toObject()) ); - const tokenImages = await this.parent.parent.getTokenImages(); const beastformEffect = this.parent.effects.find(x => x.type === 'beastform'); await beastformEffect.updateSource({ changes: [ @@ -175,7 +174,8 @@ export default class DHBeastform extends BaseDataItem { ], system: { characterTokenData: { - tokenImg: tokenImages[0], + usesDynamicToken: this.parent.parent.prototypeToken.ring.enabled, + tokenImg: this.parent.parent.prototypeToken.texture.src, tokenRingImg: this.parent.parent.prototypeToken.ring.subject.texture, tokenSize: { height: this.parent.parent.prototypeToken.height, @@ -190,7 +190,7 @@ export default class DHBeastform extends BaseDataItem { await this.parent.parent.createEmbeddedDocuments('ActiveEffect', [beastformEffect.toObject()]); - await updateActorTokens(this.parent.parent, { + const prototypeTokenUpdate = { height: this.tokenSize.height, width: this.tokenSize.width, texture: { @@ -201,22 +201,20 @@ export default class DHBeastform extends BaseDataItem { texture: this.tokenRingImg } } + }; + + const tokenUpdate = token => ({ + ...prototypeTokenUpdate, + flags: { + daggerheart: { + beastformTokenImg: token.texture.src, + beastformSubjectTexture: token.ring.subject.texture + } + } }); + await updateActorTokens(this.parent.parent, prototypeTokenUpdate, tokenUpdate); + return false; } - - _onCreate(_data, _options, userId) { - if (userId !== game.user.id) return; - - if (!this.parent.effects.find(x => x.type === 'beastform')) { - this.parent.createEmbeddedDocuments('ActiveEffect', [ - { - type: 'beastform', - name: game.i18n.localize('DAGGERHEART.ITEMS.Beastform.beastformEffect'), - img: 'icons/creatures/abilities/paw-print-pair-purple.webp' - } - ]); - } - } } diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index d5a402f2..f1bec45c 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -251,7 +251,13 @@ export const adjustRange = (rangeVal, decrease) => { return range[rangeKeys[newIndex]]; }; -export const updateActorTokens = async (actor, update) => { +/** + * + * @param {DhActor} actor - The actor for which all tokens will run a data update. + * @param {string} update - The data update to be applied to all tokens. + * @param {func} updateToken - Optional, specific data update for the non-prototype tokens as a function using the token data. Useful to handle wildcard images where each token has a different image but the prototype has a wildcard path. + */ +export const updateActorTokens = async (actor, update, updateToken) => { await actor.prototypeToken.update({ ...update }); /* Update the tokens in all scenes belonging to Actor */ @@ -259,7 +265,7 @@ export const updateActorTokens = async (actor, update) => { const tokenActor = token.baseActor ?? token.actor; if (token.id && tokenActor?.id === actor.id) { await token.update({ - ...update, + ...(updateToken ? updateToken(token) : update), _id: token.id }); }