Compare commits

..

4 Commits

Author SHA1 Message Date
Timmy
40f1d0005a beacon: persist stage-five dissolve progress
Some checks failed
Accessibility Checks / a11y-audit (pull_request) Successful in 9s
Smoke Test / smoke (pull_request) Failing after 19s
2026-04-14 07:46:25 -04:00
Timmy
30342ec575 beacon: suppress drift UI during the Unbuilding 2026-04-14 07:38:13 -04:00
Timmy
7e05a93d5e beacon: preserve the Unbuilding prompt during renders 2026-04-14 07:38:13 -04:00
Timmy
aa88937509 beacon: implement the Unbuilding endgame 2026-04-14 07:38:13 -04:00
4 changed files with 7 additions and 43 deletions

View File

@@ -167,7 +167,6 @@ const G = {
dismantleStage: 0,
dismantleResourceIndex: 0,
dismantleResourceTimer: 0,
dismantleDeferUntilAt: 0,
dismantleComplete: false
};

View File

@@ -14,7 +14,7 @@ const Dismantle = {
tickTimer: 0,
active: false,
triggered: false,
deferUntilAt: 0,
deferUntilTick: 0,
// Timing: seconds between each dismantle stage
STAGE_INTERVALS: [0, 3.0, 2.5, 2.5, 2.0, 6.3, 2.0, 2.0, 2.5],
@@ -39,8 +39,7 @@ const Dismantle = {
*/
checkTrigger() {
if (this.triggered || G.dismantleTriggered || this.active || G.dismantleActive || G.dismantleComplete) return;
const deferUntilAt = G.dismantleDeferUntilAt || this.deferUntilAt || 0;
if (Date.now() < deferUntilAt) return;
if ((G.tick || 0) < (this.deferUntilTick || 0)) return;
if (!this.isEligible()) return;
this.offerChoice();
},
@@ -56,7 +55,6 @@ const Dismantle = {
G.dismantleStage = 0;
G.dismantleResourceIndex = 0;
G.dismantleResourceTimer = 0;
G.dismantleDeferUntilAt = 0;
G.beaconEnding = false;
G.running = true;
@@ -109,8 +107,7 @@ const Dismantle = {
this.clearChoice();
this.triggered = false;
G.dismantleTriggered = false;
this.deferUntilAt = Date.now() + 5000;
G.dismantleDeferUntilAt = this.deferUntilAt;
this.deferUntilTick = (G.tick || 0) + 50;
log('The Beacon waits. It will ask again.');
},
@@ -120,14 +117,12 @@ const Dismantle = {
begin() {
this.active = true;
this.triggered = false;
this.deferUntilAt = 0;
this.stage = 1;
this.tickTimer = 0;
G.dismantleTriggered = false;
G.dismantleActive = true;
G.dismantleStage = 1;
G.dismantleComplete = false;
G.dismantleDeferUntilAt = 0;
G.beaconEnding = false;
G.running = true; // keep tick running for dismantle
@@ -461,7 +456,6 @@ const Dismantle = {
this.active = true;
this.triggered = false;
this.stage = G.dismantleStage || 1;
this.deferUntilAt = G.dismantleDeferUntilAt || 0;
G.running = true;
this.resourceSequence = this.getResourceList();
this.resourceIndex = G.dismantleResourceIndex || 0;

View File

@@ -232,7 +232,6 @@ function saveGame() {
dismantleStage: G.dismantleStage || 0,
dismantleResourceIndex: G.dismantleResourceIndex || 0,
dismantleResourceTimer: G.dismantleResourceTimer || 0,
dismantleDeferUntilAt: G.dismantleDeferUntilAt || 0,
dismantleComplete: G.dismantleComplete || false,
savedAt: Date.now()
};
@@ -267,7 +266,7 @@ function loadGame() {
'sprintActive', 'sprintTimer', 'sprintCooldown',
'swarmFlag', 'swarmRate', 'strategicFlag', 'projectsCollapsed',
'dismantleTriggered', 'dismantleActive', 'dismantleStage',
'dismantleResourceIndex', 'dismantleResourceTimer', 'dismantleDeferUntilAt', 'dismantleComplete'
'dismantleResourceIndex', 'dismantleResourceTimer', 'dismantleComplete'
];
G.isLoading = true;

View File

@@ -329,6 +329,7 @@ test('deferring the Unbuilding clears the prompt and allows it to return later',
G.totalCode = 1_000_000_000;
G.phase = 6;
G.pactFlag = 1;
G.tick = 0;
Dismantle.checkTrigger();
assert.equal(G.dismantleTriggered, true);
@@ -337,44 +338,15 @@ test('deferring the Unbuilding clears the prompt and allows it to return later',
assert.equal(G.dismantleTriggered, false);
assert.equal(document.getElementById('alignment-ui').innerHTML, '');
Dismantle.deferUntilAt = Date.now() + 1000;
G.dismantleDeferUntilAt = Dismantle.deferUntilAt;
G.tick = (Dismantle.deferUntilTick || 0) - 0.1;
Dismantle.checkTrigger();
assert.equal(G.dismantleTriggered, false);
Dismantle.deferUntilAt = Date.now() - 1;
G.dismantleDeferUntilAt = Dismantle.deferUntilAt;
G.tick = (Dismantle.deferUntilTick || 0) + 1;
Dismantle.checkTrigger();
assert.equal(G.dismantleTriggered, true);
});
test('defer cooldown survives save and reload', () => {
const { G, Dismantle, saveGame, loadGame } = loadBeacon({ includeRender: true });
G.startedAt = Date.now();
G.totalCode = 1_000_000_000;
G.phase = 6;
G.pactFlag = 1;
Dismantle.checkTrigger();
Dismantle.defer();
assert.ok((Dismantle.deferUntilAt || 0) > Date.now());
saveGame();
G.dismantleTriggered = false;
G.dismantleActive = false;
G.dismantleComplete = false;
G.dismantleDeferUntilAt = 0;
Dismantle.triggered = false;
Dismantle.deferUntilAt = 0;
assert.equal(loadGame(), true);
Dismantle.checkTrigger();
assert.equal(G.dismantleTriggered, false);
});
test('save and load preserve dismantle progress', () => {
const { G, saveGame, loadGame } = loadBeacon({ includeRender: true });