From f2d82d58fc68078be2ad5f4b2ab9d5efcf65c2c7 Mon Sep 17 00:00:00 2001 From: Hikari Date: Mon, 9 Mar 2026 21:31:06 -0700 Subject: [PATCH] fix: preserve achievements across prestige Fixes #38. buildPostPrestigeState was using structuredClone(defaultAchievements) via the freshState, which reset all achievements on every prestige. Achievements are now carried forward from currentState.achievements instead, ensuring unlocked achievements are never lost across prestige resets. --- apps/api/src/services/prestige.ts | 4 +++- apps/api/test/services/prestige.spec.ts | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/api/src/services/prestige.ts b/apps/api/src/services/prestige.ts index 0d9140b..d05de0b 100644 --- a/apps/api/src/services/prestige.ts +++ b/apps/api/src/services/prestige.ts @@ -225,7 +225,9 @@ const buildPostPrestigeState = ( const prestigeState: GameState = { ...freshState, - lastTickAt: Date.now(), + // Achievements are permanent — earned achievements survive all prestiges + achievements: currentState.achievements, + lastTickAt: Date.now(), /* * Fold current-run totals into lifetime stats so the GameState reflects diff --git a/apps/api/test/services/prestige.spec.ts b/apps/api/test/services/prestige.spec.ts index 6b09d2f..c913e74 100644 --- a/apps/api/test/services/prestige.spec.ts +++ b/apps/api/test/services/prestige.spec.ts @@ -320,6 +320,20 @@ describe("buildPostPrestigeState", () => { expect(prestigeState.player.lifetimeAdventurersRecruited).toBe(5); }); + it("preserves achievements from current state across prestige", () => { + const achievement = { + description: "Did a thing", + id: "ach_persisted", + name: "Achiever", + requirement: 1, + type: "totalClicks" as const, + unlockedAt: Date.now(), + }; + const state = makeMinimalState({ achievements: [ achievement ] as GameState["achievements"] }); + const { prestigeState } = buildPostPrestigeState(state, "Tester"); + expect(prestigeState.achievements).toEqual([ achievement ]); + }); + it("accumulates unlocked achievements into lifetime total", () => { const achievement = { description: "Did a thing",