From 5afd7ae6861db9949279246784506d7a7ee3cfe9 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Mon, 28 Jul 2025 03:49:10 +0200 Subject: [PATCH] Effects with statuses on them will now add them as full additional effects so they show up on the token. --- module/documents/activeEffect.mjs | 89 ++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs index 5d45e2e1..0e49ff27 100644 --- a/module/documents/activeEffect.mjs +++ b/module/documents/activeEffect.mjs @@ -42,13 +42,22 @@ export default class DhActiveEffect extends ActiveEffect { } get localizedStatuses() { - const statusMap = new Map(foundry.CONFIG.statusEffects.map(status => [status.id, status.name])); + const { statusMap, isStatusActiveEffect } = this.isStatusActiveEffect; + if (!isStatusActiveEffect) return []; + return this.statuses.map(x => ({ key: x, - name: game.i18n.localize(statusMap.get(x)) + name: game.i18n.localize(statusMap.get(x).name) })); } + get isStatusActiveEffect() { + const statusMap = new Map(foundry.CONFIG.statusEffects.map(status => [status.id, status])); + const isStatusActiveEffect = + this.statuses.size === 1 && this.name === game.i18n.localize(statusMap.get(this.statuses.first()).name); + return { statusMap, isStatusActiveEffect }; + } + async _preCreate(data, options, user) { const update = {}; if (!data.img) { @@ -62,6 +71,34 @@ export default class DhActiveEffect extends ActiveEffect { await super._preCreate(data, options, user); } + _onCreate(data, options, userId) { + super._onCreate(data, options, userId); + + if (game.user.id === userId) { + this.addStatusActiveEffects(data.statuses); + } + } + + _onUpdate(changed, options, userId) { + super._onUpdate(changed, options, userId); + + if ('disabled' in changed) { + if (changed.disabled) { + this.removeStatusActiveEffects(this.statuses); + } else { + this.addStatusActiveEffects(this.statuses); + } + } + } + + _onDelete(data, userId) { + super._onDelete(data, userId); + + if (game.user.id === userId) { + this.removeStatusActiveEffects(this.statuses); + } + } + static applyField(model, change, field) { const evalValue = this.effectSafeEval(itemAbleRollParse(change.value, model, change.effect.parent)); change.value = evalValue ?? change.value; @@ -82,6 +119,54 @@ export default class DhActiveEffect extends ActiveEffect { return result; } + async addStatusActiveEffects(statuses) { + if (this.parent.type !== 'character') return; + + const { statusMap, isStatusActiveEffect } = this.isStatusActiveEffect; + if (isStatusActiveEffect) return; + + const statusesToAdd = statuses.reduce((acc, status) => { + const statusData = statusMap.get(status); + const statusName = game.i18n.localize(statusData.name); + const alreadyExists = this.parent.effects.find( + effect => effect.statuses.size === 1 && effect.statuses.first() === status && effect.name === statusName + ); + if (!alreadyExists) { + acc.push({ + name: statusName, + description: game.i18n.localize(statusData.description), + img: statusData.icon, + statuses: [status] + }); + } + + return acc; + }, []); + + await this.parent.createEmbeddedDocuments('ActiveEffect', statusesToAdd); + } + + async removeStatusActiveEffects(statuses) { + if (this.parent.type !== 'character') return; + + const { statusMap, isStatusActiveEffect } = this.isStatusActiveEffect; + if (isStatusActiveEffect) return; + + const statusesToRemove = statuses.reduce((acc, status) => { + const statusName = game.i18n.localize(statusMap.get(status).name); + const existingEffect = this.parent.effects.find( + effect => effect.statuses.size === 1 && effect.statuses.first() === status && effect.name === statusName + ); + if (existingEffect) { + acc.push(existingEffect.id); + } + + return acc; + }, []); + + await this.parent.deleteEmbeddedDocuments('ActiveEffect', statusesToRemove); + } + async toChat(origin) { const cls = getDocumentClass('ChatMessage'); const systemData = {