From 6f5d154e5a53734340d39b4f1ff15b71e68e60b8 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Fri, 27 Mar 2026 23:39:12 +0100 Subject: [PATCH] Initial idea --- module/canvas/placeables/token.mjs | 29 +++++++++++++++++++++++ module/config/settingsConfig.mjs | 3 ++- module/data/_module.mjs | 1 + module/data/spotlightTracker.mjs | 9 ++++++++ module/macros/spotlightCombatant.mjs | 32 +++++++++++++++++++------- module/systemRegistration/settings.mjs | 7 ++++++ 6 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 module/data/spotlightTracker.mjs diff --git a/module/canvas/placeables/token.mjs b/module/canvas/placeables/token.mjs index 148466c1..9ccd41de 100644 --- a/module/canvas/placeables/token.mjs +++ b/module/canvas/placeables/token.mjs @@ -9,6 +9,35 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token { this.previewHelp ||= this.addChild(this.#drawPreviewHelp()); } + /**@inheritdoc */ + _refreshTurnMarker() { + // Should a Turn Marker be active? + const { turnMarker } = this.document; + const markersEnabled = + CONFIG.Combat.settings.turnMarker.enabled && turnMarker.mode !== CONST.TOKEN_TURN_MARKER_MODES.DISABLED; + const isTurn = game.combat?.combatant?.tokenId === this.id; + const spotlighted = game.settings + .get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker) + .spotlightedTokens.has(this.document.uuid); + + const markerActive = markersEnabled && (isTurn || spotlighted); + + // Activate a Turn Marker + if (markerActive) { + if (!this.turnMarker) + this.turnMarker = this.addChildAt(new foundry.canvas.placeables.tokens.TokenTurnMarker(this), 0); + canvas.tokens.turnMarkers.add(this); + this.turnMarker.draw(); + } + + // Remove a Turn Marker + else if (this.turnMarker) { + canvas.tokens.turnMarkers.delete(this); + this.turnMarker.destroy(); + this.turnMarker = null; + } + } + /** @inheritDoc */ async _drawEffects() { this.effects.renderable = false; diff --git a/module/config/settingsConfig.mjs b/module/config/settingsConfig.mjs index c19e6e26..df639e43 100644 --- a/module/config/settingsConfig.mjs +++ b/module/config/settingsConfig.mjs @@ -40,7 +40,8 @@ export const gameSettings = { LastMigrationVersion: 'LastMigrationVersion', TagTeamRoll: 'TagTeamRoll', SpotlightRequestQueue: 'SpotlightRequestQueue', - CompendiumBrowserSettings: 'CompendiumBrowserSettings' + CompendiumBrowserSettings: 'CompendiumBrowserSettings', + SpotlightTracker: 'SpotlightTracker' }; export const actionAutomationChoices = { diff --git a/module/data/_module.mjs b/module/data/_module.mjs index 52fa689e..843ffb3e 100644 --- a/module/data/_module.mjs +++ b/module/data/_module.mjs @@ -4,6 +4,7 @@ export { default as DhTagTeamRoll } from './tagTeamRoll.mjs'; export { default as DhRollTable } from './rollTable.mjs'; export { default as RegisteredTriggers } from './registeredTriggers.mjs'; export { default as CompendiumBrowserSettings } from './compendiumBrowserSettings.mjs'; +export { default as SpotlighTracker } from './spotlightTracker.mjs'; export * as countdowns from './countdowns.mjs'; export * as actions from './action/_module.mjs'; diff --git a/module/data/spotlightTracker.mjs b/module/data/spotlightTracker.mjs new file mode 100644 index 00000000..57f54e16 --- /dev/null +++ b/module/data/spotlightTracker.mjs @@ -0,0 +1,9 @@ +export default class SpotlightTracker extends foundry.abstract.DataModel { + static defineSchema() { + const fields = foundry.data.fields; + + return { + spotlightedTokens: new fields.SetField(new fields.DocumentUUIDField()) + }; + } +} diff --git a/module/macros/spotlightCombatant.mjs b/module/macros/spotlightCombatant.mjs index 68a26ff9..7afdf66c 100644 --- a/module/macros/spotlightCombatant.mjs +++ b/module/macros/spotlightCombatant.mjs @@ -5,17 +5,33 @@ * 2) HoveredCombatant */ const spotlightCombatant = () => { - if (!game.combat) - return ui.notifications.error(game.i18n.localize('DAGGERHEART.MACROS.Spotlight.errors.noActiveCombat')); + const selectedTokens = canvas.tokens.controlled.length > 0 ? canvas.tokens.controlled : []; + const hoveredTokens = game.canvas.tokens.hover ? [game.canvas.tokens.hover] : []; - const selectedCombatant = canvas.tokens.controlled.length > 0 ? canvas.tokens.controlled[0].combatant : null; - const hoveredCombatant = game.canvas.tokens.hover?.combatant; - - const combatant = selectedCombatant ?? hoveredCombatant; - if (!combatant) + const tokens = selectedTokens.length ? selectedTokens : hoveredTokens; + if (!tokens.length) return ui.notifications.error(game.i18n.localize('DAGGERHEART.MACROS.Spotlight.errors.noCombatantSelected')); - ui.combat.setCombatantSpotlight(combatant.id); + const spotlightTracker = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker); + spotlightTracker.updateSource(); + + for (const token of tokens) { + if (game.combat && token.combatant) { + ui.combat.setCombatantSpotlight(token.combatant.id); + } else { + const isSpotlighted = spotlightTracker.spotlightedTokens.has(token.document.uuid); + spotlightTracker.updateSource({ + spotlightedTokens: isSpotlighted + ? [...spotlightTracker.spotlightedTokens].filter(x => x !== token.document.uuid) + : [...spotlightTracker.spotlightedTokens, token.document.uuid] + }); + } + } + + game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker, spotlightTracker); + for (const token of tokens) { + token.renderFlags.set({ refreshTurnMarker: true }); + } }; export default spotlightCombatant; diff --git a/module/systemRegistration/settings.mjs b/module/systemRegistration/settings.mjs index 17dab6f7..d2798ad1 100644 --- a/module/systemRegistration/settings.mjs +++ b/module/systemRegistration/settings.mjs @@ -16,6 +16,7 @@ import { DhVariantRuleSettings } from '../applications/settings/_module.mjs'; import { CompendiumBrowserSettings, DhTagTeamRoll } from '../data/_module.mjs'; +import SpotlightTracker from '../data/spotlightTracker.mjs'; export const registerDHSettings = () => { registerKeyBindings(); @@ -183,4 +184,10 @@ const registerNonConfigSettings = () => { config: false, type: CompendiumBrowserSettings }); + + game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker, { + scope: 'world', + config: false, + type: SpotlightTracker + }); };