mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-04-21 23:13:39 +02:00
[V14] [Feature] Spotlight Without Combat (#1755)
This commit is contained in:
parent
2a294684d4
commit
24d22dde59
8 changed files with 109 additions and 19 deletions
|
|
@ -2555,8 +2555,7 @@
|
||||||
"MACROS": {
|
"MACROS": {
|
||||||
"Spotlight": {
|
"Spotlight": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"noActiveCombat": "There is no active encounter",
|
"noTokenSelected": "A token on the canvas must either be selected or hovered to spotlight it"
|
||||||
"noCombatantSelected": "A combatant token must be either selected or hovered to spotlight it"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { AdversaryBPPerEncounter } from '../../config/encounterConfig.mjs';
|
import { AdversaryBPPerEncounter } from '../../config/encounterConfig.mjs';
|
||||||
import { expireActiveEffects } from '../../helpers/utils.mjs';
|
import { expireActiveEffects } from '../../helpers/utils.mjs';
|
||||||
|
import { clearPreviousSpotlight } from '../../macros/spotlightCombatant.mjs';
|
||||||
|
|
||||||
export default class DhCombatTracker extends foundry.applications.sidebar.tabs.CombatTracker {
|
export default class DhCombatTracker extends foundry.applications.sidebar.tabs.CombatTracker {
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
|
|
@ -150,13 +151,13 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C
|
||||||
}
|
}
|
||||||
|
|
||||||
async setCombatantSpotlight(combatantId) {
|
async setCombatantSpotlight(combatantId) {
|
||||||
|
const combatant = this.viewed.combatants.get(combatantId);
|
||||||
const update = {
|
const update = {
|
||||||
system: {
|
system: {
|
||||||
'spotlight.requesting': false,
|
'spotlight.requesting': false,
|
||||||
'spotlight.requestOrderIndex': 0
|
'spotlight.requestOrderIndex': 0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const combatant = this.viewed.combatants.get(combatantId);
|
|
||||||
|
|
||||||
const toggleTurn = this.viewed.combatants.contents
|
const toggleTurn = this.viewed.combatants.contents
|
||||||
.sort(this.viewed._sortCombatants)
|
.sort(this.viewed._sortCombatants)
|
||||||
|
|
@ -187,6 +188,14 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C
|
||||||
round: this.viewed.round + 1
|
round: this.viewed.round + 1
|
||||||
});
|
});
|
||||||
await combatant.update(update);
|
await combatant.update(update);
|
||||||
|
if (combatant.token) clearPreviousSpotlight();
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearTurn() {
|
||||||
|
await this.viewed.update({
|
||||||
|
turn: null,
|
||||||
|
round: this.viewed.round + 1
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static async requestSpotlight(_, target) {
|
static async requestSpotlight(_, target) {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,36 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
this.previewHelp ||= this.addChild(this.#drawPreviewHelp());
|
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 turnIsSet = game.combat?.turn !== null;
|
||||||
|
const isTurn = game.combat?.combatant?.tokenId === this.id;
|
||||||
|
const markerActive = markersEnabled && turnIsSet ? 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 */
|
/** @inheritDoc */
|
||||||
async _drawEffects() {
|
async _drawEffects() {
|
||||||
this.effects.renderable = false;
|
this.effects.renderable = false;
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,8 @@ export const gameSettings = {
|
||||||
Countdowns: 'Countdowns',
|
Countdowns: 'Countdowns',
|
||||||
LastMigrationVersion: 'LastMigrationVersion',
|
LastMigrationVersion: 'LastMigrationVersion',
|
||||||
SpotlightRequestQueue: 'SpotlightRequestQueue',
|
SpotlightRequestQueue: 'SpotlightRequestQueue',
|
||||||
CompendiumBrowserSettings: 'CompendiumBrowserSettings'
|
CompendiumBrowserSettings: 'CompendiumBrowserSettings',
|
||||||
|
SpotlightTracker: 'SpotlightTracker'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const actionAutomationChoices = {
|
export const actionAutomationChoices = {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ export { default as DhRollTable } from './rollTable.mjs';
|
||||||
export { default as RegisteredTriggers } from './registeredTriggers.mjs';
|
export { default as RegisteredTriggers } from './registeredTriggers.mjs';
|
||||||
export { default as CompendiumBrowserSettings } from './compendiumBrowserSettings.mjs';
|
export { default as CompendiumBrowserSettings } from './compendiumBrowserSettings.mjs';
|
||||||
export { default as TagTeamData } from './tagTeamData.mjs';
|
export { default as TagTeamData } from './tagTeamData.mjs';
|
||||||
|
export { default as SpotlightTracker } from './spotlightTracker.mjs';
|
||||||
|
|
||||||
export * as countdowns from './countdowns.mjs';
|
export * as countdowns from './countdowns.mjs';
|
||||||
export * as actions from './action/_module.mjs';
|
export * as actions from './action/_module.mjs';
|
||||||
|
|
|
||||||
9
module/data/spotlightTracker.mjs
Normal file
9
module/data/spotlightTracker.mjs
Normal 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())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,21 +1,50 @@
|
||||||
/**
|
/**
|
||||||
* Spotlights a combatant.
|
* Spotlight a token on the canvas. If it is a combatant, run it through combatTracker's spotlight logic.
|
||||||
* The combatant can be selected in a number of ways. If many are applied at the same time, the following order is used:
|
* @param {TokenDocument} token - The token to spotlight
|
||||||
* 1) SelectedCombatant
|
* @returns {void}
|
||||||
* 2) HoveredCombatant
|
|
||||||
*/
|
*/
|
||||||
const spotlightCombatant = () => {
|
const spotlightCombatantMacro = async token => {
|
||||||
if (!game.combat)
|
if (!token)
|
||||||
return ui.notifications.error(game.i18n.localize('DAGGERHEART.MACROS.Spotlight.errors.noActiveCombat'));
|
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 combatantCombat = token.combatant
|
||||||
const hoveredCombatant = game.canvas.tokens.hover?.combatant;
|
? game.combat
|
||||||
|
: game.combats.find(combat => combat.combatants.some(x => x.token && x.token.id === token.document.id));
|
||||||
|
if (combatantCombat) {
|
||||||
|
const combatant = combatantCombat.combatants.find(x => x.token.id === token.document.id);
|
||||||
|
if (!combatantCombat.active) {
|
||||||
|
await combatantCombat.activate();
|
||||||
|
if (combatantCombat.combatant?.id !== combatant.id) ui.combat.setCombatantSpotlight(combatant.id);
|
||||||
|
} else {
|
||||||
|
ui.combat.setCombatantSpotlight(combatant.id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (game.combat) await ui.combat.clearTurn();
|
||||||
|
|
||||||
const combatant = selectedCombatant ?? hoveredCombatant;
|
const spotlightTracker = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker);
|
||||||
if (!combatant)
|
const isSpotlighted = spotlightTracker.spotlightedTokens.has(token.document.uuid);
|
||||||
return ui.notifications.error(game.i18n.localize('DAGGERHEART.MACROS.Spotlight.errors.noCombatantSelected'));
|
if (!isSpotlighted) await clearPreviousSpotlight();
|
||||||
|
|
||||||
ui.combat.setCombatantSpotlight(combatant.id);
|
spotlightTracker.updateSource({
|
||||||
|
spotlightedTokens: isSpotlighted ? [] : [token.document.uuid]
|
||||||
|
});
|
||||||
|
|
||||||
|
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker, spotlightTracker);
|
||||||
|
token.renderFlags.set({ refreshTurnMarker: true });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default spotlightCombatant;
|
export const clearPreviousSpotlight = async () => {
|
||||||
|
const spotlightTracker = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker);
|
||||||
|
const previouslySpotlightedUuid =
|
||||||
|
spotlightTracker.spotlightedTokens.size > 0 ? spotlightTracker.spotlightedTokens.first() : null;
|
||||||
|
if (!previouslySpotlightedUuid) return;
|
||||||
|
|
||||||
|
spotlightTracker.updateSource({ spotlightedTokens: [] });
|
||||||
|
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker, spotlightTracker);
|
||||||
|
|
||||||
|
const previousToken = await foundry.utils.fromUuid(previouslySpotlightedUuid);
|
||||||
|
previousToken.object.renderFlags.set({ refreshTurnMarker: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
export default spotlightCombatantMacro;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import {
|
||||||
DhVariantRuleSettings
|
DhVariantRuleSettings
|
||||||
} from '../applications/settings/_module.mjs';
|
} from '../applications/settings/_module.mjs';
|
||||||
import { CompendiumBrowserSettings } from '../data/_module.mjs';
|
import { CompendiumBrowserSettings } from '../data/_module.mjs';
|
||||||
|
import SpotlightTracker from '../data/spotlightTracker.mjs';
|
||||||
|
|
||||||
export const registerDHSettings = () => {
|
export const registerDHSettings = () => {
|
||||||
registerKeyBindings();
|
registerKeyBindings();
|
||||||
|
|
@ -40,7 +41,12 @@ export const registerKeyBindings = () => {
|
||||||
hint: game.i18n.localize('DAGGERHEART.SETTINGS.Keybindings.spotlight.hint'),
|
hint: game.i18n.localize('DAGGERHEART.SETTINGS.Keybindings.spotlight.hint'),
|
||||||
uneditable: [],
|
uneditable: [],
|
||||||
editable: [],
|
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: () => {},
|
onUp: () => {},
|
||||||
restricted: true,
|
restricted: true,
|
||||||
reservedModifiers: [],
|
reservedModifiers: [],
|
||||||
|
|
@ -177,4 +183,10 @@ const registerNonConfigSettings = () => {
|
||||||
config: false,
|
config: false,
|
||||||
type: CompendiumBrowserSettings
|
type: CompendiumBrowserSettings
|
||||||
});
|
});
|
||||||
|
|
||||||
|
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.SpotlightTracker, {
|
||||||
|
scope: 'world',
|
||||||
|
config: false,
|
||||||
|
type: SpotlightTracker
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue