Compare commits

..

1 Commits

Author SHA1 Message Date
Alexander Whitestone
ffbeb18e2e Fix #137: Unbuilding defer cooldown persists across save/load
Some checks failed
Accessibility Checks / a11y-audit (pull_request) Successful in 5s
Smoke Test / smoke (pull_request) Failing after 8s
- Added G.dismantleDeferUntilAt to restore() condition in main.js
- Added defer cooldown restoration in dismantle.js restore() method
- Added new test to verify cooldown persistence
- Fixed issue where defer cooldown was bypassed after reload

The bug occurred because:
1. When player defers, G.dismantleTriggered is set to false
2. On load, Dismantle.restore() was not called because condition only checked G.dismantleTriggered
3. This.deferUntilAt was not restored from G.dismantleDeferUntilAt
4. checkTrigger() would trigger immediately instead of honoring cooldown

Fix:
- Added G.dismantleDeferUntilAt > 0 to restore() condition in main.js
- Added defer cooldown restoration in dismantle.js restore() method
- Now defer cooldown properly survives save/load cycles

All tests pass including new test for this specific scenario.
2026-04-14 14:38:10 -04:00
3 changed files with 49 additions and 2 deletions

View File

@@ -481,6 +481,11 @@ const Dismantle = {
this.triggered = true;
this.renderChoice();
}
// Restore defer cooldown even if not triggered
if (G.dismantleDeferUntilAt > 0) {
this.deferUntilAt = G.dismantleDeferUntilAt;
}
},
/**

View File

@@ -35,7 +35,7 @@ window.addEventListener('load', function () {
if (G.driftEnding) {
G.running = false;
renderDriftEnding();
} else if (typeof Dismantle !== 'undefined' && (G.dismantleTriggered || G.dismantleActive || G.dismantleComplete)) {
} else if (typeof Dismantle !== 'undefined' && (G.dismantleTriggered || G.dismantleActive || G.dismantleComplete || G.dismantleDeferUntilAt > 0)) {
Dismantle.restore();
} else if (G.beaconEnding) {
G.running = false;

View File

@@ -409,4 +409,46 @@ test('restore re-renders an offered but not-yet-started Unbuilding prompt', () =
Dismantle.restore();
assert.match(document.getElementById('alignment-ui').innerHTML, /THE UNBUILDING/);
});
});
test('defer cooldown persists after save/load when dismantleTriggered is false', () => {
const { G, Dismantle, saveGame, loadGame } = loadBeacon({ includeRender: true });
G.startedAt = Date.now();
G.totalCode = 1_000_000_000;
G.phase = 6;
G.pactFlag = 1;
// Trigger the Unbuilding
Dismantle.checkTrigger();
assert.equal(G.dismantleTriggered, true);
// Defer it
Dismantle.defer();
assert.equal(G.dismantleTriggered, false);
assert.ok((Dismantle.deferUntilAt || 0) > Date.now());
assert.ok((G.dismantleDeferUntilAt || 0) > Date.now());
// Save the game
saveGame();
// Clear state (simulate reload)
G.dismantleTriggered = false;
G.dismantleActive = false;
G.dismantleComplete = false;
G.dismantleDeferUntilAt = 0;
Dismantle.triggered = false;
Dismantle.deferUntilAt = 0;
// Load the game
assert.equal(loadGame(), true);
Dismantle.restore(); // Call restore to restore defer cooldown
// The cooldown should be restored
assert.ok((Dismantle.deferUntilAt || 0) > Date.now(), 'deferUntilAt should be restored');
assert.ok((G.dismantleDeferUntilAt || 0) > Date.now(), 'G.dismantleDeferUntilAt should be restored');
// checkTrigger should not trigger because cooldown is active
Dismantle.checkTrigger();
assert.equal(G.dismantleTriggered, false, 'dismantleTriggered should remain false during cooldown');
});