diff --git a/eslint.config.mjs b/eslint.config.mjs index f47a550..aabd56c 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -35,6 +35,7 @@ export default [ Combat: `readonly`, Combatant: `readonly`, canvas: `readonly`, + Token: `readonly`, }, }, }, diff --git a/module/Apps/sidebar/CombatTracker.mjs b/module/Apps/sidebar/CombatTracker.mjs index 483cdd6..bbef58f 100644 --- a/module/Apps/sidebar/CombatTracker.mjs +++ b/module/Apps/sidebar/CombatTracker.mjs @@ -10,9 +10,9 @@ export class RipCryptCombatTracker extends CombatTracker { turn.hasDecimals = true; turn.initiative = combatant.dynamicInitiative; - const groupKey = combatant.groupKey; + const groupKey = combatant?.groupKey; if (groupKey && combat.started) { - turn.active ||= combat.combatant.groupKey === groupKey; + turn.active ||= combat.combatant?.groupKey === groupKey; if (turn.active && !turn.css.includes(`active`)) { turn.css += `active`; }; diff --git a/module/documents/combat.mjs b/module/documents/combat.mjs index acfedbe..bca1afa 100644 --- a/module/documents/combat.mjs +++ b/module/documents/combat.mjs @@ -48,7 +48,7 @@ export class RipCryptCombat extends Combat { const turn = this.turn ?? -1; - const groupKey = this.combatant.groupKey; + const groupKey = this.turns[turn]?.groupKey; // Determine the next turn number let nextTurn = null; @@ -88,6 +88,14 @@ export class RipCryptCombat extends Combat { } } + if (previousTurn < 0) { + if (this.round === 1) { + this.round = 0; + return this; + }; + return this.previousRound() + } + const advanceTime = this.getTimeDelta(this.round, this.turn, this.round, previousTurn); // Update the document, passing data through a hook first @@ -104,8 +112,6 @@ export class RipCryptCombat extends Combat { * @internal */ _updateTurnMarkers() { - return super._updateTurnMarkers(); - /* eslint-disable no-unreachable */ if (!canvas.ready) { return }; const tokenGroup = this.combatant?.groupKey; @@ -118,15 +124,21 @@ export class RipCryptCombat extends Combat { if (!this.active) { return }; const currentToken = this.combatant?.token?._object; - console.log(this.combatant.token._object) if (!tokenGroup && currentToken) { currentToken.renderFlags.set({refreshTurnMarker: true}); } else { - for (const combatant of this.groups.get(tokenGroup)) { - console.log(combatant.token._object); - combatant.token._object.renderFlags.set({ refreshTurnMarker: true }); + const group = this.groups.get(tokenGroup) ?? []; + for (const combatant of group) { + combatant.token?._object?.renderFlags.set({ refreshTurnMarker: true }); } } - /* eslint-enable no-unreachable */ } + + async _manageTurnEvents() { + try { + await super._manageTurnEvents(); + } catch { + this._updateTurnMarkers(); + }; + }; }; diff --git a/module/documents/combatant.mjs b/module/documents/combatant.mjs index 648a7aa..21e1ba8 100644 --- a/module/documents/combatant.mjs +++ b/module/documents/combatant.mjs @@ -3,7 +3,7 @@ import { distanceBetweenFates } from "../utils/distanceBetweenFates.mjs"; export class RipCryptCombatant extends Combatant { get disposition() { - switch (this.token.disposition) { + switch (this.token?.disposition) { case CONST.TOKEN_DISPOSITIONS.HOSTILE: return `hostile`; case CONST.TOKEN_DISPOSITIONS.FRIENDLY: @@ -12,6 +12,10 @@ export class RipCryptCombatant extends Combatant { return `unknown`; }; + /** + * Used by the Combat tracker to order combatants according to their + * fate path and the coin flip. + */ get dynamicInitiative() { let total = 0; @@ -21,13 +25,11 @@ export class RipCryptCombatant extends Combatant { const whoFirst = game.settings.get(`ripcrypt`, `whoFirst`); const disposition = this.disposition; - if (whoFirst) { - if (disposition === `unknown`) { - total += 0.25; - } else if (whoFirst !== disposition) { - total += 0.5; - }; - } + if (disposition === `unknown`) { + total += 0.25; + } else if (whoFirst && whoFirst !== disposition) { + total += 0.5; + }; return total; }; @@ -39,16 +41,20 @@ export class RipCryptCombatant extends Combatant { if (!path) { return null }; // Token Disposition (group into: friendlies, unknown, hostiles) - let disposition = `unknown`; - switch (this.token.disposition) { - case CONST.TOKEN_DISPOSITIONS.HOSTILE: - disposition = `hostile`; - break; - case CONST.TOKEN_DISPOSITIONS.FRIENDLY: - disposition = `friendly`; - break; - }; + let disposition = this.disposition; return `${path}:${disposition}`; }; + + _onCreate() { + if (this.token) { + this.token._object._refreshTurnMarker(); + }; + }; + + _onDelete() { + if (this.token) { + this.token._object._refreshTurnMarker(); + }; + }; }; diff --git a/module/documents/token.mjs b/module/documents/token.mjs new file mode 100644 index 0000000..2b66aac --- /dev/null +++ b/module/documents/token.mjs @@ -0,0 +1,27 @@ +const { TokenTurnMarker } = foundry.canvas.placeables.tokens; + +export class RipCryptToken extends Token { + _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 combatant = game.combat?.active ? game.combat.combatant : null; + const isTurn = combatant && (combatant.groupKey === this.combatant?.groupKey); + const isDefeated = combatant && combatant.isDefeated; + const markerActive = markersEnabled && isTurn && !isDefeated; + + // Activate a Turn Marker + if ( markerActive ) { + if ( !this.turnMarker ) { + this.turnMarker = this.addChildAt(new TokenTurnMarker(this), 0); + }; + canvas.tokens.turnMarkers.add(this); + this.turnMarker.draw(); + } else if ( this.turnMarker ) { + canvas.tokens.turnMarkers.delete(this); + this.turnMarker.destroy(); + this.turnMarker = null; + } + } +}; diff --git a/module/hooks/init.mjs b/module/hooks/init.mjs index 2577eb2..212626a 100644 --- a/module/hooks/init.mjs +++ b/module/hooks/init.mjs @@ -31,11 +31,12 @@ import { registerWorldSettings } from "../settings/worldSettings.mjs"; import { RipCryptCombat } from "../documents/combat.mjs"; import { RipCryptCombatant } from "../documents/combatant.mjs"; import { RipCryptCombatTracker } from "../Apps/sidebar/CombatTracker.mjs"; +import { RipCryptToken } from "../documents/token.mjs"; Hooks.once(`init`, () => { Logger.log(`Initializing`); - CONFIG.Combat.initiative.decimals = 1; + CONFIG.Combat.initiative.decimals = 2; CONFIG.ui.crypt = DelveTourApp; // #region Settings @@ -60,6 +61,7 @@ Hooks.once(`init`, () => { CONFIG.ui.combat = RipCryptCombatTracker; CONFIG.Combat.documentClass = RipCryptCombat; CONFIG.Combatant.documentClass = RipCryptCombatant; + CONFIG.Token.objectClass = RipCryptToken; CONFIG.Item.documentClass = RipCryptItem; CONFIG.Dice.terms.d = CryptDie; // #endregion