import { getAllEffectMappings } from '../hooks/effectMappingHooks.js'; import { FEATURE_CONTROL, TVA_CONFIG } from '../settings.js'; import { registerWrapper, unregisterWrapper } from './wrappers.js'; const feature_id = 'EffectIcons'; export function registerEffectIconWrappers() { unregisterWrapper(feature_id, 'Token.prototype.drawEffects'); unregisterWrapper(feature_id, 'CombatTracker.prototype.getData'); if (!FEATURE_CONTROL[feature_id]) return; if ( !TVA_CONFIG.disableEffectIcons && TVA_CONFIG.filterEffectIcons && !['pf1e', 'pf2e'].includes(game.system.id) ) { registerWrapper(feature_id, 'Token.prototype.drawEffects', _drawEffects, 'OVERRIDE'); } else if (TVA_CONFIG.disableEffectIcons) { registerWrapper( feature_id, 'Token.prototype.drawEffects', _drawEffects_fullReplace, 'OVERRIDE' ); } else if (TVA_CONFIG.displayEffectIconsOnHover) { registerWrapper(feature_id, 'Token.prototype.drawEffects', _drawEffects_hoverOnly, 'WRAPPER'); } if (TVA_CONFIG.disableEffectIcons || TVA_CONFIG.filterCustomEffectIcons) { registerWrapper( feature_id, 'CombatTracker.prototype.getData', _combatTrackerGetData, 'WRAPPER' ); } } async function _drawEffects_hoverOnly(wrapped, ...args) { let result = await wrapped(...args); this.effects.visible = this.hover; return result; } async function _drawEffects_fullReplace(...args) { this.effects.removeChildren().forEach((c) => c.destroy()); this.effects.bg = this.effects.addChild(new PIXI.Graphics()); this.effects.overlay = null; } async function _combatTrackerGetData(wrapped, ...args) { let data = await wrapped(...args); if (data && data.combat && data.turns) { const combat = data.combat; for (const turn of data.turns) { const combatant = combat.combatants.find((c) => c.id === turn.id); if (combatant) { if (TVA_CONFIG.disableEffectIcons) { turn.effects = new Set(); } else if (TVA_CONFIG.filterEffectIcons) { const restrictedEffects = _getRestrictedEffects(combatant.token); // Copied from CombatTracker.getData(...) turn.effects = new Set(); if (combatant.token) { combatant.token.effects.forEach((e) => turn.effects.add(e)); if (combatant.token.overlayEffect) turn.effects.add(combatant.token.overlayEffect); } // modified to filter restricted effects if (combatant.actor) { for (const effect of combatant.actor.temporaryEffects) { if (effect.statuses.has(CONFIG.specialStatusEffects.DEFEATED)) { } else if (effect.icon && !restrictedEffects.includes(effect.name ?? effect.label)) turn.effects.add(effect.icon); } } // end of copy } } } } return data; } async function _drawEffects(...args) { this.effects.renderable = false; this.effects.removeChildren().forEach((c) => c.destroy()); this.effects.bg = this.effects.addChild(new PIXI.Graphics()); this.effects.overlay = null; // Categorize new effects let tokenEffects = this.document.effects; let actorEffects = this.actor?.temporaryEffects || []; let overlay = { src: this.document.overlayEffect, tint: null, }; // Modified from the original token.drawEffects if (TVA_CONFIG.displayEffectIconsOnHover) this.effects.visible = this.hover; if (tokenEffects.length || actorEffects.length) { const restrictedEffects = _getRestrictedEffects(this.document); actorEffects = actorEffects.filter((ef) => !restrictedEffects.includes(ef.name ?? ef.label)); tokenEffects = tokenEffects.filter( // check if it's a string here // for tokens without representing actors effects are just stored as paths to icons (ef) => typeof ef === 'string' || !restrictedEffects.includes(ef.name ?? ef.label) ); } // End of modifications // Draw status effects if (tokenEffects.length || actorEffects.length) { const promises = []; // Draw actor effects first for (let f of actorEffects) { if (!f.icon) continue; const tint = Color.from(f.tint ?? null); if (f.getFlag('core', 'overlay')) { overlay = { src: f.icon, tint }; continue; } promises.push(this._drawEffect(f.icon, tint)); } // Next draw token effects for (let f of tokenEffects) promises.push(this._drawEffect(f, null)); await Promise.all(promises); } // Draw overlay effect this.effects.overlay = await this._drawOverlay(overlay.src, overlay.tint); this._refreshEffects(); this.effects.renderable = true; } function _getRestrictedEffects(tokenDoc) { let restrictedEffects = TVA_CONFIG.filterIconList; if (TVA_CONFIG.filterCustomEffectIcons) { const mappings = getAllEffectMappings(tokenDoc); if (mappings) restrictedEffects = restrictedEffects.concat(mappings.map((m) => m.expression)); } return restrictedEffects; }