Borders: Don't rely on .inCombat to check combat status

When changing scenes, *a lot* of data is either empty or points to
the previous scene, preventing us from knowing whether a token is in
combat or not directly from the token.

To work around that, go through the list of combats directly and try
to match them with the scene and token we are drawing instead of using
`.inCombat`.
We cannot rely on `game.combats.active` either as it points to the
active combat in the previous scene.

This is far more work, but it is the only working solution I found.
It depends quite a bit on Fabula Ultima's system combat type which
lists combatants.

This leaves a more minor issue that the borders are not updated when
switching between encounters on the same scene, but this is a rarer
scenario.

Remove the issue from the README and mention the encounter switch issue.
This commit is contained in:
trotFunky 2025-06-01 23:42:22 +01:00
parent 73d2a08b88
commit 77ae01a7b3
2 changed files with 42 additions and 15 deletions

View file

@ -38,12 +38,11 @@ The module supports going back and forth in the combat rounds, as well as going
### Limitations
There are currently one main issue that need to be fixed :
1. The token borders will be incorrect when switching to a new scene
- It is unclear why, but apparently switching to another scene is very different from loading a new scene,
and the combat encounter of the scene is not available when tokens are created. This means that the combat status,
and thus the border type, cannot be properly determined on scene switch.
- This can be fixed by receiving a combat update, either from the players or the GM, on the scene.
There are currently one minor issue that might be fixed :
1. The token borders will be incorrect when switching between different encounters in the same scene
- Producing a combat event or switching away and back to the scene will fix it.
- It doesn't appear that there is an event on combat switch that could be hooked into, which makes fixing the
issue uncertain.
## Token UI adjustments

View file

@ -1,6 +1,7 @@
import * as MillsFabula from "./mills_fabula.mjs";
import { FUHooks } from "/systems/projectfu/module/hooks.mjs"
import { FU } from "/systems/projectfu/module/helpers/config.mjs"
import { FUCombat } from '/systems/projectfu/module/ui/combat.mjs';
// NOTES
// Tokens are working PIXI.js objects, can .addChild() a sprite
@ -120,6 +121,7 @@ function token_remote_set_border_visibility(scene_id, token_id, played) {
/**
* Check if a token has played in a specific round, or the current combat round if it exists for the token.
* The function does not rely on the token's internal data, as it is not properly set when changing scenes.
* @param {Token} token The actual token object to check combat status
* @param {number} [round] The round to check the token's status in, will check the token's combat current turn otherwise
* @returns {boolean} If the token has played in the current or requested round
@ -127,15 +129,42 @@ function token_remote_set_border_visibility(scene_id, token_id, played) {
function token_has_played(token, round = -1) {
// console.debug("↓↓↓ token_has_played ↓↓↓");
// console.debug(token.inCombat)
if (!token.inCombat) {
/**
* When we change scene, the token might not be updated with the combat
* data, so we might need to go check ourselves if they are not set.
* @type {FUCombat}
*/
let combat = token.combatant?.combat;
/** @type {Combatant} */
let combatant = token.combatant;
// We might be changing scene, so let's check if that's true.
if (!combatant) {
/*
* There should only be one active combat per scene.
* If there isn't one, we're sure that the token is not in combat.
*/
let active_scene_combat = game.combats.contents.filter(
(combat) => combat.active && combat.scene.id === token.scene.id)
if (active_scene_combat.length === 0) {
return false;
}
/**
* As we check beforehand, combat should always exist.
* @type {Combat}
*/
let combat = token.combatant.combat;
combat = active_scene_combat[0];
// Now search among the combatants
for (let active_combatant of combat.combatants) {
if (active_combatant.tokenId === token.id) {
combatant = active_combatant;
break;
}
}
// We have not found our token in the active combat, assume it isn't in combat.
if (!combatant) {
return false;
}
}
let round_turns_taken = combat?.flags.projectfu.CombatantsTurnTaken[round < 0 ? combat?.round : round]
// console.debug(`Testing played for round : ${combat?.round}`)
console.debug(round_turns_taken)
@ -147,7 +176,7 @@ function token_has_played(token, round = -1) {
// console.debug("↑↑↑ token_has_played ↑↑↑");
// Token might have played, let's search now.
return round_turns_taken.includes(token.combatant.id)
return round_turns_taken.includes(combatant.id)
}
/**
@ -240,7 +269,6 @@ function combat_border_main() {
})
// Create the borders from defined textures and add them to the tokens when they are first created on canvas.
// FIXME: Does not work on scene change !
Hooks.on("drawToken", (drawn_token) => {
// FIXME: Handle deactivation properly
if (!game.settings.get(MillsFabula.id, BorderSettings.BorderEnabled)) {