diff --git a/module/applications/hud/tokenHUD.mjs b/module/applications/hud/tokenHUD.mjs index 572b03f9..5c29260b 100644 --- a/module/applications/hud/tokenHUD.mjs +++ b/module/applications/hud/tokenHUD.mjs @@ -66,12 +66,9 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { if (!status) continue; if (status._id) { if (status._id !== effect.id) continue; - } else { - if (effect.statuses.size !== 1) continue; } status.isActive = true; if (effect.getFlag('core', 'overlay')) status.isOverlay = true; - break; } } diff --git a/module/applications/sheets-configs/activeEffectConfig.mjs b/module/applications/sheets-configs/activeEffectConfig.mjs index 087b5b08..88edf9d6 100644 --- a/module/applications/sheets-configs/activeEffectConfig.mjs +++ b/module/applications/sheets-configs/activeEffectConfig.mjs @@ -99,7 +99,17 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac async _preparePartContext(partId, context) { const partContext = await super._preparePartContext(partId, context); switch (partId) { - case 'changes': + case 'details': + const useGeneric = game.settings.get( + CONFIG.DH.id, + CONFIG.DH.SETTINGS.gameSettings.appearance + ).showGenericStatusEffects; + if (!useGeneric) { + partContext.statuses = Object.values(CONFIG.DH.GENERAL.conditions).map(status => ({ + value: status.id, + label: game.i18n.localize(status.name) + })); + } break; } diff --git a/module/canvas/placeables/token.mjs b/module/canvas/placeables/token.mjs index 967df0f8..dd6f089e 100644 --- a/module/canvas/placeables/token.mjs +++ b/module/canvas/placeables/token.mjs @@ -10,8 +10,28 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token { this.effects.overlay = null; // Categorize effects - const activeEffects = this.actor ? Array.from(this.actor.effects).filter(x => !x.disabled) : []; - const overlayEffect = activeEffects.findLast(e => e.img && e.getFlag('core', 'overlay')); + const statusMap = new Map(foundry.CONFIG.statusEffects.map(status => [status.id, status])); + const activeEffects = (this.actor ? this.actor.effects.filter(x => !x.disabled) : []).reduce((acc, effect) => { + acc.push(effect); + + const currentStatusActiveEffects = acc.filter( + x => x.statuses.size === 1 && x.name === game.i18n.localize(statusMap.get(x.statuses.first()).name) + ); + for (var status of effect.statuses) { + if (!currentStatusActiveEffects.find(x => x.statuses.includes(status))) { + const statusData = statusMap.get(status); + acc.push({ + name: game.i18n.localize(statusData.name), + statuses: [status], + img: statusData.icon, + tint: effect.tint + }); + } + } + + return acc; + }, []); + const overlayEffect = activeEffects.findLast(e => e.img && e.getFlag?.('core', 'overlay')); // Draw effects const promises = []; diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs index 3c45929b..5d45e2e1 100644 --- a/module/documents/activeEffect.mjs +++ b/module/documents/activeEffect.mjs @@ -41,6 +41,14 @@ export default class DhActiveEffect extends ActiveEffect { }); } + get localizedStatuses() { + const statusMap = new Map(foundry.CONFIG.statusEffects.map(status => [status.id, status.name])); + return this.statuses.map(x => ({ + key: x, + name: game.i18n.localize(statusMap.get(x)) + })); + } + async _preCreate(data, options, user) { const update = {}; if (!data.img) { diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index fc62e870..c60a0b90 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -389,6 +389,41 @@ export default class DhpActor extends Actor { return this.system.difficulty ?? 10; } + /** @inheritDoc */ + async toggleStatusEffect(statusId, { active, overlay = false } = {}) { + const status = CONFIG.statusEffects.find(e => e.id === statusId); + if (!status) throw new Error(`Invalid status ID "${statusId}" provided to Actor#toggleStatusEffect`); + const existing = []; + + // Find the effect with the static _id of the status effect + if (status._id) { + const effect = this.effects.get(status._id); + if (effect) existing.push(effect.id); + } + + // If no static _id, find all effects that have this status + else { + for (const effect of this.effects) { + if (effect.statuses.has(status.id)) existing.push(effect.id); + } + } + + // Remove the existing effects unless the status effect is forced active + if (existing.length) { + if (active) return true; + await this.deleteEmbeddedDocuments('ActiveEffect', existing); + return false; + } + + // Create a new effect unless the status effect is forced inactive + if (!active && active !== undefined) return; + + const ActiveEffect = getDocumentClass('ActiveEffect'); + const effect = await ActiveEffect.fromStatusEffect(statusId); + if (overlay) effect.updateSource({ 'flags.core.overlay': true }); + return ActiveEffect.implementation.create(effect, { parent: this, keepId: true }); + } + getRollData() { const rollData = super.getRollData(); rollData.system = this.system.getRollData(); @@ -505,16 +540,16 @@ export default class DhpActor extends Actor { Object.entries(healings).forEach(([key, healing]) => { healing.parts.forEach(part => { const update = updates.find(u => u.key === key); - if (update) - update.value += part.total; + if (update) update.value += part.total; else updates.push({ value: part.total, key }); }); }); updates.forEach( u => - (u.value = - !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false) ? u.value * -1 : u.value) + (u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false) + ? u.value * -1 + : u.value) ); await this.modifyResource(updates); @@ -561,7 +596,7 @@ export default class DhpActor extends Actor { } } }); - + Object.keys(updates).forEach(async key => { const u = updates[key]; if (key === 'items') { diff --git a/templates/sheets/global/partials/inventory-item-V2.hbs b/templates/sheets/global/partials/inventory-item-V2.hbs index 90e1c543..46d63861 100644 --- a/templates/sheets/global/partials/inventory-item-V2.hbs +++ b/templates/sheets/global/partials/inventory-item-V2.hbs @@ -156,8 +156,8 @@ Parameters: {{localize 'DAGGERHEART.EFFECTS.Duration.passive'}} {{/if}} - {{#each item.statuses as |status|}} -
{{localize (concat 'DAGGERHEART.CONFIG.Condition.' status '.name')}}
+ {{#each item.localizedStatuses as |status|}} +
{{status.name}}
{{/each}} {{else if (not hideLabels)}}