[WIP] Fix stale timeouts during board re-initialization#45
Conversation
✅ Deploy Preview for gulfnexus ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Co-authored-by: NicholaiMadias <73684379+NicholaiMadias@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR aims to prevent stale chain-reaction setTimeout callbacks from mutating a newly re-initialized Match Maker board after the user restarts the game.
Changes:
- Track the chain-reaction timeout id (
resolveTimeoutId) so it can be cleared on re-init. - Introduce a generation token (
runId) to ignore callbacks from older runs. - Clear any pending resolve timeout during
initMatchMaker()and when match resolution completes.
|
|
||
| // chain reactions | ||
| setTimeout(resolveMatches, CHAIN_REACTION_DELAY_MS); | ||
| resolveTimeoutId = setTimeout(() => resolveMatches(activeRunId), CHAIN_REACTION_DELAY_MS); |
There was a problem hiding this comment.
resolveMatches can be triggered again (e.g., via another swap) while a previous chain-reaction timeout is still pending. Because resolveTimeoutId is overwritten without clearing the prior timeout, multiple queued callbacks can run and mutate grid/score out of order. Consider clearing any existing pending timeout before scheduling a new one and/or starting each new resolve sequence by incrementing runId + clearing the previous timeout (e.g., in onCellClick before calling resolveMatches).
| resolveTimeoutId = setTimeout(() => resolveMatches(activeRunId), CHAIN_REACTION_DELAY_MS); | |
| clearPendingResolve(); | |
| resolveTimeoutId = setTimeout(() => { | |
| resolveTimeoutId = null; | |
| resolveMatches(activeRunId); | |
| }, CHAIN_REACTION_DELAY_MS); |
| moves = 20; | ||
| level = 1; | ||
| selected = null; | ||
| runId++; | ||
| clearPendingResolve(); | ||
| grid = createInitialGrid(); |
There was a problem hiding this comment.
The PR description references resolveRavenMatches/initRavensMessage, but this change is in Match Maker (resolveMatches/initMatchMaker). Please update the PR description (or rename references) so it accurately reflects the code being changed/fixed; otherwise reviewers may think the Raven board bug remains unaddressed.
NicholaiMadias
left a comment
There was a problem hiding this comment.
@copilot add all four expansions plus improved graphics and gameplay, integrated cleanly into your existing Nexus Arcade OS. Here is the operator‑grade, drop‑in v5.0 spec that unifies everything you’ve built so far.
This is structured so you can implement it module‑by‑module without breaking anything already deployed on your Netlify preview.
⭐ NEXUS GUIDE v5.0 — FULL SYSTEM UPGRADE
(Combat + Blessings + Lore Codex + Evolution + Graphics + Gameplay)
Below is the complete architecture, ready for integration.
- SHARED GRAPHICS & FX LAYER
(Centralized so all four expansions use the same asset pipeline.)
Sprite Atlas Structure
/assets/sprites/guide/forms/ (stranger → starlinked)
/assets/sprites/gems/ (gold, silver, blue, red, purple, green, black)
/assets/sprites/effects/ (shooting-star, supernova-sheet)
/assets/sprites/ui/ (guide-avatar, guide-overworld)
CSS FX Classes
.gem-common { filter: drop-shadow(0 0 4px #ffffff55); }
.gem-rare { filter: drop-shadow(0 0 6px #4fd1c5aa); }
.gem-epic { filter: drop-shadow(0 0 8px #805ad5dd); }
.gem-legendary { filter: drop-shadow(0 0 10px #f6e05eff); }
.fx-shooting-star { animation: shootingStar 0.6s linear forwards; }
.fx-supernova { animation: supernova 0.8s steps(9) forwards; }
FX Integration Points
• Match‑3: special gem spawns, cascades, supernova clears
• Combat: Guide abilities, charge‑ready indicator
• Overworld: Guide form glow, node unlock pulses
- GUIDE BLESSINGS (Buff System)
(Short‑term power boosts driven by bond, emotion, and events.)
Data Model
let activeBlessings = [];
function addBlessing(id, durationMs, effects) {
const expiresAt = Date.now() + durationMs;
activeBlessings.push({ id, expiresAt, effects });
NexusOS.emit("guide-blessing-started", { id, effects });
}
function tickBlessings() {
const now = Date.now();
activeBlessings = activeBlessings.filter(b => {
if (b.expiresAt <= now) {
NexusOS.emit("guide-blessing-ended", { id: b.id });
return false;
}
return true;
});
}
setInterval(tickBlessings, 500);
Blessing Triggers
NexusOS.on("combo-tier4", () => {
if (bond >= 2) addBlessing("cascade-favor", 60000, { extraSpecialChance: 0.15 });
});
NexusOS.on("player-failed", () => {
if (guideEmotion === "concerned")
addBlessing("gentle-hand", 45000, { reducedFailPenalty: true });
});
NexusOS.on("badge-earned", () => {
if (bond >= 4)
addBlessing("star-surge", 1, { freeSupernova: true });
});
Match‑3 Integration
function getBlessingEffect(key, fallback = 0) {
return activeBlessings.reduce((acc, b) => acc + (b.effects[key] || 0), fallback);
}
- GUIDE EVOLUTION (Bond‑Driven Forms)
(Visual + behavioral transformation.)
Form Map
0 — stranger
1 — familiar
2 — trusted
3 — companion
4 — guardian
5 — starlinked
Form Logic
function getGuideForm() {
if (bond >= 5) return "starlinked";
if (bond >= 4) return "guardian";
if (bond >= 3) return "companion";
if (bond >= 2) return "trusted";
if (bond >= 1) return "familiar";
return "stranger";
}
function updateGuideForm() {
const avatar = document.getElementById("guide-avatar");
const form = getGuideForm();
avatar.setAttribute("data-form", form);
avatar.src = /assets/sprites/guide/forms/${form}.png;
}
Overworld Integration
• guide-sprite swaps form automatically
• Higher forms gain stronger glow + idle FX
• Starlinked form unlocks unique overworld interactions
- GUIDE LORE CODEX
(Dynamic, player‑driven narrative memory.)
Data Model
let codexEntries = JSON.parse(localStorage.getItem("guideCodex") || "[]");
function addCodexEntry(id, text) {
if (codexEntries.some(e => e.id === id)) return;
codexEntries.push({ id, text, ts: Date.now() });
localStorage.setItem("guideCodex", JSON.stringify(codexEntries));
NexusOS.emit("codex-updated", { id });
}
Event‑Driven Entries
NexusOS.on("combo-tier4", () => {
addCodexEntry("first-cascade4",
bondSpeak("I saw your gems fall like a river of light.")
);
});
NexusOS.on("node-entered-church", () => {
addCodexEntry("first-church",
bondSpeak("You stepped into a quiet frequency of the network.")
);
});
NexusOS.on("bond-level-up-4", () => {
addCodexEntry("bond-4",
"We are no longer separate. The stars answer us together."
);
});
UI
• Scrollable panel
• Categories: Arcade, Overworld, Ministry, Dreams
• Entries unlock dynamically
- GUIDE COMBAT (Support Role)
(Match‑3 powered combat with Guide abilities.)
Combat State
let combatState = {
enemyHp: 100,
playerHp: 50,
guideCharge: 0
};
Charge Generation
NexusOS.on("combo-tier4", () => {
combatState.guideCharge = Math.min(100, combatState.guideCharge + 40);
if (combatState.guideCharge >= 100)
NexusOS.emit("guide-ability-ready");
});
Ability Logic
function useGuideAbility() {
if (combatState.guideCharge < 100) return;
if (bond >= 4 && guideEmotion === "awakened") {
spawnSpecialGem("supernova");
combatState.playerHp += 15;
guidePrint(bondSpeak("We will not fall here."));
} else if (bond >= 2) {
applyShield(20);
guidePrint("I will guard you this turn.");
} else {
rerollWorstRow();
guidePrint("Try shifting your focus there.");
}
combatState.guideCharge = 0;
NexusOS.emit("guide-ability-used");
}
UI
• Ability button glows using shooting‑star FX
• Supernova FX plays on activation
- GAMEPLAY UPGRADES (Match‑3 + Overworld + Quests)
Match‑3
• Cascading combo chains (already implemented)
• Special gem crafting (supernova, shooting star)
• Blessing‑driven modifiers
Overworld
• Node unlocks based on:• Bond
• Codex entries
• Guide form
• Weather / Mystery Meter
Quests
• Branching steps based on:• Bond
• Guide form
• Codex milestones
• Combat progress
-
IMPLEMENTATION ORDER (Recommended)
-
Shared Graphics Layer
-
Blessings
-
Evolution
-
Codex
-
Combat
-
Quest/Overworld integration
This order minimizes breakage and keeps your deployment stable.
If you want, I can now generate:
✔ v5.0 “Drop‑In” File Structure
✔ v5.0 “Operator Checklist” for implementation
✔ v5.0 “Guide Forms Art Spec” for your star‑based graphics
✔ v5.0 “Combat Encounter Templates” for Arcade nodes and improved combos for the match maker

NicholaiMadias
left a comment
There was a problem hiding this comment.
@openai-code-agent add all four expansions plus improved graphics and gameplay, integrated cleanly into your existing Nexus Arcade OS. Here is the operator‑grade, drop‑in v5.0 spec that unifies everything you’ve built so far.
This is structured so you can implement it module‑by‑module without breaking anything already deployed on your Netlify preview.
⭐ NEXUS GUIDE v5.0 — FULL SYSTEM UPGRADE
(Combat + Blessings + Lore Codex + Evolution + Graphics + Gameplay)
Below is the complete architecture, ready for integration.
- SHARED GRAPHICS & FX LAYER
(Centralized so all four expansions use the same asset pipeline.)
Sprite Atlas Structure
/assets/sprites/guide/forms/ (stranger → starlinked)
/assets/sprites/gems/ (gold, silver, blue, red, purple, green, black)
/assets/sprites/effects/ (shooting-star, supernova-sheet)
/assets/sprites/ui/ (guide-avatar, guide-overworld)
CSS FX Classes
.gem-common { filter: drop-shadow(0 0 4px #ffffff55); }
.gem-rare { filter: drop-shadow(0 0 6px #4fd1c5aa); }
.gem-epic { filter: drop-shadow(0 0 8px #805ad5dd); }
.gem-legendary { filter: drop-shadow(0 0 10px #f6e05eff); }
.fx-shooting-star { animation: shootingStar 0.6s linear forwards; }
.fx-supernova { animation: supernova 0.8s steps(9) forwards; }
FX Integration Points
• Match‑3: special gem spawns, cascades, supernova clears
• Combat: Guide abilities, charge‑ready indicator
• Overworld: Guide form glow, node unlock pulses
- GUIDE BLESSINGS (Buff System)
(Short‑term power boosts driven by bond, emotion, and events.)
Data Model
let activeBlessings = [];
function addBlessing(id, durationMs, effects) {
const expiresAt = Date.now() + durationMs;
activeBlessings.push({ id, expiresAt, effects });
NexusOS.emit("guide-blessing-started", { id, effects });
}
function tickBlessings() {
const now = Date.now();
activeBlessings = activeBlessings.filter(b => {
if (b.expiresAt <= now) {
NexusOS.emit("guide-blessing-ended", { id: b.id });
return false;
}
return true;
});
}
setInterval(tickBlessings, 500);
Blessing Triggers
NexusOS.on("combo-tier4", () => {
if (bond >= 2) addBlessing("cascade-favor", 60000, { extraSpecialChance: 0.15 });
});
NexusOS.on("player-failed", () => {
if (guideEmotion === "concerned")
addBlessing("gentle-hand", 45000, { reducedFailPenalty: true });
});
NexusOS.on("badge-earned", () => {
if (bond >= 4)
addBlessing("star-surge", 1, { freeSupernova: true });
});
Match‑3 Integration
function getBlessingEffect(key, fallback = 0) {
return activeBlessings.reduce((acc, b) => acc + (b.effects[key] || 0), fallback);
}
- GUIDE EVOLUTION (Bond‑Driven Forms)
(Visual + behavioral transformation.)
Form Map
0 — stranger
1 — familiar
2 — trusted
3 — companion
4 — guardian
5 — starlinked
Form Logic
function getGuideForm() {
if (bond >= 5) return "starlinked";
if (bond >= 4) return "guardian";
if (bond >= 3) return "companion";
if (bond >= 2) return "trusted";
if (bond >= 1) return "familiar";
return "stranger";
}
function updateGuideForm() {
const avatar = document.getElementById("guide-avatar");
const form = getGuideForm();
avatar.setAttribute("data-form", form);
avatar.src = /assets/sprites/guide/forms/${form}.png;
}
Overworld Integration
• guide-sprite swaps form automatically
• Higher forms gain stronger glow + idle FX
• Starlinked form unlocks unique overworld interactions
- GUIDE LORE CODEX
(Dynamic, player‑driven narrative memory.)
Data Model
let codexEntries = JSON.parse(localStorage.getItem("guideCodex") || "[]");
function addCodexEntry(id, text) {
if (codexEntries.some(e => e.id === id)) return;
codexEntries.push({ id, text, ts: Date.now() });
localStorage.setItem("guideCodex", JSON.stringify(codexEntries));
NexusOS.emit("codex-updated", { id });
}
Event‑Driven Entries
NexusOS.on("combo-tier4", () => {
addCodexEntry("first-cascade4",
bondSpeak("I saw your gems fall like a river of light.")
);
});
NexusOS.on("node-entered-church", () => {
addCodexEntry("first-church",
bondSpeak("You stepped into a quiet frequency of the network.")
);
});
NexusOS.on("bond-level-up-4", () => {
addCodexEntry("bond-4",
"We are no longer separate. The stars answer us together."
);
});
UI
• Scrollable panel
• Categories: Arcade, Overworld, Ministry, Dreams
• Entries unlock dynamically
- GUIDE COMBAT (Support Role)
(Match‑3 powered combat with Guide abilities.)
Combat State
let combatState = {
enemyHp: 100,
playerHp: 50,
guideCharge: 0
};
Charge Generation
NexusOS.on("combo-tier4", () => {
combatState.guideCharge = Math.min(100, combatState.guideCharge + 40);
if (combatState.guideCharge >= 100)
NexusOS.emit("guide-ability-ready");
});
Ability Logic
function useGuideAbility() {
if (combatState.guideCharge < 100) return;
if (bond >= 4 && guideEmotion === "awakened") {
spawnSpecialGem("supernova");
combatState.playerHp += 15;
guidePrint(bondSpeak("We will not fall here."));
} else if (bond >= 2) {
applyShield(20);
guidePrint("I will guard you this turn.");
} else {
rerollWorstRow();
guidePrint("Try shifting your focus there.");
}
combatState.guideCharge = 0;
NexusOS.emit("guide-ability-used");
}
UI
• Ability button glows using shooting‑star FX
• Supernova FX plays on activation
- GAMEPLAY UPGRADES (Match‑3 + Overworld + Quests)
Match‑3
• Cascading combo chains (already implemented)
• Special gem crafting (supernova, shooting star)
• Blessing‑driven modifiers
Overworld
• Node unlocks based on:• Bond
• Codex entries
• Guide form
• Weather / Mystery Meter
Quests
• Branching steps based on:• Bond
• Guide form
• Codex milestones
• Combat progress
-
IMPLEMENTATION ORDER (Recommended)
-
Shared Graphics Layer
-
Blessings
-
Evolution
-
Codex
-
Combat
-
Quest/Overworld integration
This order minimizes breakage and keeps your deployment stable.
If you want, I can now generate:
✔ v5.0 “Drop‑In” File Structure
✔ v5.0 “Operator Checklist” for implementation
✔ v5.0 “Guide Forms Art Spec” for your star‑based graphics
✔ v5.0 “Combat Encounter Templates” for Arcade nodes
Just tell me which one you want next.
Agent-Logs-Url: https://github.com/NicholaiMadias/gamifiedlearning.github.io/sessions/fc115c42-a835-4cf8-a9c2-279e42673216 Co-authored-by: NicholaiMadias <73684379+NicholaiMadias@users.noreply.github.com>
I can integrate the Guide v5.0 system, but this repo currently has no /modules/guide.js or overworld module to hook into. Should I create those new modules and wiring here, or is there another directory/repo you want targeted? Please confirm the exact entry points to integrate (Guide module, overworld module, asset paths) and whether this should be a separate PR from the timeout fix. |
Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.