A token having a turnmarker is now determined by a global setting, and not wether its a combatants turn

This commit is contained in:
WBHarry 2026-03-28 01:34:21 +01:00
parent 2a294684d4
commit 1fe1ec3dcb
8 changed files with 105 additions and 21 deletions

View file

@ -2555,8 +2555,7 @@
"MACROS": {
"Spotlight": {
"errors": {
"noActiveCombat": "There is no active encounter",
"noCombatantSelected": "A combatant token must be either selected or hovered to spotlight it"
"noTokenSelected": "A token on the canvas must either be selected or hovered to spotlight it"
}
}
},

View file

@ -1,5 +1,6 @@
import { AdversaryBPPerEncounter } from '../../config/encounterConfig.mjs';
import { expireActiveEffects } from '../../helpers/utils.mjs';
import { spotlightToken } from '../../macros/spotlightCombatant.mjs';
export default class DhCombatTracker extends foundry.applications.sidebar.tabs.CombatTracker {
static DEFAULT_OPTIONS = {
@ -150,13 +151,13 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C
}
async setCombatantSpotlight(combatantId) {
const combatant = this.viewed.combatants.get(combatantId);
const update = {
system: {
'spotlight.requesting': false,
'spotlight.requestOrderIndex': 0
}
};
const combatant = this.viewed.combatants.get(combatantId);
const toggleTurn = this.viewed.combatants.contents
.sort(this.viewed._sortCombatants)
@ -187,6 +188,16 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C
round: this.viewed.round + 1
});
await combatant.update(update);
if (!combatant.token) return;
spotlightToken(combatant.token);
}
async clearTurn() {
await this.viewed.update({
turn: null,
round: this.viewed.round + 1
});
}
static async requestSpotlight(_, target) {

View file

@ -10,6 +10,34 @@ 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 spotlighted = game.settings
.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker)
.spotlightedTokens.has(this.document.uuid);
const markerActive = markersEnabled && 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;

View file

@ -39,7 +39,8 @@ export const gameSettings = {
Countdowns: 'Countdowns',
LastMigrationVersion: 'LastMigrationVersion',
SpotlightRequestQueue: 'SpotlightRequestQueue',
CompendiumBrowserSettings: 'CompendiumBrowserSettings'
CompendiumBrowserSettings: 'CompendiumBrowserSettings',
SpotlightTracker: 'SpotlightTracker'
};
export const actionAutomationChoices = {

View file

@ -4,6 +4,7 @@ export { default as DhRollTable } from './rollTable.mjs';
export { default as RegisteredTriggers } from './registeredTriggers.mjs';
export { default as CompendiumBrowserSettings } from './compendiumBrowserSettings.mjs';
export { default as TagTeamData } from './tagTeamData.mjs';
export { default as SpotlightTracker } from './spotlightTracker.mjs';
export * as countdowns from './countdowns.mjs';
export * as actions from './action/_module.mjs';

View file

@ -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())
};
}
}

View file

@ -1,21 +1,44 @@
/**
* Spotlights a combatant.
* The combatant can be selected in a number of ways. If many are applied at the same time, the following order is used:
* 1) SelectedCombatant
* 2) HoveredCombatant
* Spotlight a token on the canvas. If it is a combatant, run it through combatTracker's spotlight logic.
* @param {TokenDocument} token - The token to spotlight
* @returns {void}
*/
const spotlightCombatant = () => {
if (!game.combat)
return ui.notifications.error(game.i18n.localize('DAGGERHEART.MACROS.Spotlight.errors.noActiveCombat'));
const spotlightCombatantMacro = token => {
if (!token)
return ui.notifications.error(game.i18n.localize('DAGGERHEART.MACROS.Spotlight.errors.noTokenSelected'));
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)
return ui.notifications.error(game.i18n.localize('DAGGERHEART.MACROS.Spotlight.errors.noCombatantSelected'));
ui.combat.setCombatantSpotlight(combatant.id);
if (game.combat && token.combatant) {
ui.combat.setCombatantSpotlight(token.combatant.id);
} else {
if (game.combat) ui.combat.clearTurn();
spotlightToken(token.document);
}
};
export default spotlightCombatant;
/**
* Spotlight a token on the canvas.
* @param {TokenDocument} token - The token to spotlight
* @returns {void}
*/
export const spotlightToken = async token => {
const spotlightTracker = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker);
let previouslySpotlightedUuid = null;
const isSpotlighted = spotlightTracker.spotlightedTokens.has(token.uuid);
if (!isSpotlighted && spotlightTracker.spotlightedTokens.size > 0) {
previouslySpotlightedUuid = spotlightTracker.spotlightedTokens.first();
}
spotlightTracker.updateSource({
spotlightedTokens: isSpotlighted ? [] : [token.uuid]
});
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker, spotlightTracker);
token.object.renderFlags.set({ refreshTurnMarker: true });
if (previouslySpotlightedUuid) {
const previousToken = await foundry.utils.fromUuid(previouslySpotlightedUuid);
previousToken.object.renderFlags.set({ refreshTurnMarker: true });
}
};
export default spotlightCombatantMacro;

View file

@ -16,6 +16,7 @@ import {
DhVariantRuleSettings
} from '../applications/settings/_module.mjs';
import { CompendiumBrowserSettings } from '../data/_module.mjs';
import SpotlightTracker from '../data/spotlightTracker.mjs';
export const registerDHSettings = () => {
registerKeyBindings();
@ -40,7 +41,12 @@ export const registerKeyBindings = () => {
hint: game.i18n.localize('DAGGERHEART.SETTINGS.Keybindings.spotlight.hint'),
uneditable: [],
editable: [],
onDown: game.system.api.macros.spotlightCombatant,
onDown: () => {
const selectedTokens = canvas.tokens.controlled.length > 0 ? canvas.tokens.controlled[0] : null;
const hoveredTokens = game.canvas.tokens.hover ? game.canvas.tokens.hover : null;
const tokens = selectedTokens ?? hoveredTokens;
game.system.api.macros.spotlightCombatant(tokens);
},
onUp: () => {},
restricted: true,
reservedModifiers: [],
@ -177,4 +183,10 @@ const registerNonConfigSettings = () => {
config: false,
type: CompendiumBrowserSettings
});
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker, {
scope: 'world',
config: false,
type: SpotlightTracker
});
};