1 Commits
Author SHA1 Message Date
tevansandClaude Fable 5 7d684ffdb2 Robust pause overlay + PNG NPC tokens — v2.0.3
The radar-scope pause overlay only applied via the renderGamePause hook,
which does not fire on every pause toggle path — pressing Space after an
unpause could show Foundry's default GAME PAUSED. The overlay injector is
now idempotent and wired to renderGamePause AND pauseGame (plus a ready
check), so the scope applies on every toggle; verified across repeated
unpause/pause cycles.

Also rasterize the three FALSE ALARM NPC tokens (Rostova, Changed Vance,
the Tear) to 1024px PNGs, matching the map fix in v2.0.1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 22:16:11 +01:00
9 changed files with 43 additions and 22 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

+3 -3
View File
@@ -95,7 +95,7 @@ function npcActor({ key, name, type, img, token, stats, health, skills, notes, s
const aRostova = npcActor({
key: "rostova", name: "Dr. Elena Rostova", type: "npc",
img: `${A}/token-rostova.svg`, token: `${A}/token-rostova.svg`,
img: `${A}/token-rostova.png`, token: `${A}/token-rostova.png`,
stats: { str: 10, con: 10, dex: 11, int: 15, pow: 12, cha: 11 }, health: 10, san: 0,
skills: { computer_science: 70, science: 0, sigint: 40, first_aid: 30, alertness: 40 },
shortDescription: "FAA facility technician — deceased, flash-frozen.",
@@ -104,7 +104,7 @@ const aRostova = npcActor({
const aVance = npcActor({
key: "vance", name: "Deputy Marcus Vance (Changed)", type: "unnatural",
img: `${A}/token-vance.svg`, token: `${A}/token-vance.svg`,
img: `${A}/token-vance.png`, token: `${A}/token-vance.png`,
stats: { str: 17, con: 16, dex: 16, int: 6, pow: 15, cha: 3 }, health: 16,
san: { failed: "1D6", success: "1" },
skills: { alertness: 60, athletics: 70, dodge: 50, melee_weapons: 65, unarmed_combat: 55 },
@@ -115,7 +115,7 @@ const aVance = npcActor({
const aTear = npcActor({
key: "tear", name: "The Tear (Static Between Stations)", type: "unnatural",
img: `${A}/token-entity.svg`, token: `${A}/token-entity.svg`,
img: `${A}/token-entity.png`, token: `${A}/token-entity.png`,
stats: { str: 20, con: 30, dex: 20, int: 20, pow: 25, cha: 1 }, health: 30,
san: { failed: "1D20", success: "1D6" },
skills: { alertness: 90, dodge: 80 },
+31 -10
View File
@@ -221,16 +221,25 @@ Hooks.once("diceSoNiceReady", (dice3d) => {
}
});
Hooks.on("renderGamePause", function (_, html, options) {
if (options.cssClass !== "paused") return;
/**
* Replace the stock pause spinner with the DG2 radar-scope animation.
* Idempotent: safe to call on every render/toggle; skips if already applied.
* Wired to BOTH renderGamePause and pauseGame so the scope appears no matter
* which path Foundry takes when the pause state changes.
*/
function applyDG2PauseOverlay(element) {
try {
const caption = game.i18n.translations.DG?.MissionPaused ?? "Mission Paused";
const sub = game.i18n.translations.DG2?.PausedSub ?? "ALL STATIONS HOLD // AWAITING HANDLER";
const el = element ?? document.getElementById("pause");
if (!el || !game.paused) return;
if (el.querySelector(".dg2-pause-scope")) return; // already applied
// Replace the default spinner with a DG2 radar-scope pause animation.
html.classList.add("dg2-pause");
html.innerHTML = `
const caption = game.i18n.translations.DG?.MissionPaused ?? "Mission Paused";
const sub =
game.i18n.translations.DG2?.PausedSub ??
"All stations hold // awaiting Handler";
el.classList.add("dg2-pause");
el.innerHTML = `
<div class="dg2-pause-scope" aria-hidden="true">
<span class="dg2-pause-ring r1"></span>
<span class="dg2-pause-ring r2"></span>
@@ -246,11 +255,23 @@ Hooks.on("renderGamePause", function (_, html, options) {
<span class="dg2-pause-title">${caption}</span>
<span class="dg2-pause-sub">${sub}</span>
</figcaption>`;
} catch {
// noop
} catch (ex) {
console.warn("Delta Green 2 | pause overlay failed", ex);
}
}
Hooks.on("renderGamePause", (_app, html) => {
const el = html instanceof HTMLElement ? html : html?.[0];
applyDG2PauseOverlay(el);
});
Hooks.on("pauseGame", () => {
// Run after Foundry finishes its own pause render/toggle.
setTimeout(() => applyDG2PauseOverlay(), 60);
});
Hooks.once("ready", () => applyDG2PauseOverlay());
function addEventListenerToChatMessage(element) {
element.addEventListener("click", (event) => {
const btnWithAction = event.target.closest("button[data-action]");
Binary file not shown.
+3 -3
View File
@@ -1,3 +1,3 @@
2026/07/16-15:09:13.184913 170e2b000 Recovering log #4
2026/07/16-15:09:13.186094 170e2b000 Delete type=0 #4
2026/07/16-15:09:13.186131 170e2b000 Delete type=3 #2
2026/07/16-22:12:46.376475 17235f000 Recovering log #4
2026/07/16-22:12:46.380006 17235f000 Delete type=0 #4
2026/07/16-22:12:46.380058 17235f000 Delete type=3 #2
+5 -5
View File
@@ -1,5 +1,5 @@
2026/07/16-15:09:13.093478 16f10f000 Delete type=3 #1
2026/07/16-15:09:13.095837 16f9a7000 Level-0 table #5: started
2026/07/16-15:09:13.096279 16f9a7000 Level-0 table #5: 19548 bytes OK
2026/07/16-15:09:13.096401 16f9a7000 Delete type=0 #3
2026/07/16-15:09:13.096523 16f9a7000 Manual compaction at level-0 from '!adventures!5zf355zpx5s1ux56' @ 72057594037927935 : 1 .. '!adventures!5zf355zpx5s1ux56' @ 0 : 0; will stop at (end)
2026/07/16-22:12:46.303554 1737b7000 Delete type=3 #1
2026/07/16-22:12:46.305623 17404f000 Level-0 table #5: started
2026/07/16-22:12:46.305975 17404f000 Level-0 table #5: 19548 bytes OK
2026/07/16-22:12:46.306072 17404f000 Delete type=0 #3
2026/07/16-22:12:46.306136 17404f000 Manual compaction at level-0 from '!adventures!5zf355zpx5s1ux56' @ 72057594037927935 : 1 .. '!adventures!5zf355zpx5s1ux56' @ 0 : 0; will stop at (end)
+1 -1
View File
@@ -15,7 +15,7 @@
"discord": "jalensailin"
}
],
"version": "2.0.2",
"version": "2.0.3",
"compatibility": {
"minimum": "13",
"verified": "14",