From 2827ddef7270a1013c4954082c04fe4a527f1366 Mon Sep 17 00:00:00 2001 From: Hikari Date: Tue, 31 Mar 2026 17:42:54 -0700 Subject: [PATCH] feat: add endgame prestige and gold milestone achievements (#183, #185) - Add prestige milestones at P50/P100/P150/P200 (10k/25k/50k/100k crystals) - Add gold milestones at 1e30/1e60/1e90 (Cosmic Wealthy, Infinite Hoarder, Omniversal Tycoon) --- apps/api/src/data/achievements.ts | 63 +++++++++++++++++++++++++++++++ apps/web/src/engine/tick.ts | 4 +- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/apps/api/src/data/achievements.ts b/apps/api/src/data/achievements.ts index 330a43c..1d70349 100644 --- a/apps/api/src/data/achievements.ts +++ b/apps/api/src/data/achievements.ts @@ -269,6 +269,33 @@ export const defaultAchievements: Array = [ reward: { crystals: 50_000 }, unlockedAt: null, }, + { + condition: { amount: 1e30, type: "totalGoldEarned" }, + description: "Earn 1 nonillion gold in total.", + icon: "🌌", + id: "cosmic_wealthy", + name: "Cosmic Wealthy", + reward: { crystals: 100_000 }, + unlockedAt: null, + }, + { + condition: { amount: 1e60, type: "totalGoldEarned" }, + description: "Earn a vigintillion gold in total.", + icon: "♾️", + id: "infinite_hoarder", + name: "Infinite Hoarder", + reward: { crystals: 250_000 }, + unlockedAt: null, + }, + { + condition: { amount: 1e90, type: "totalGoldEarned" }, + description: "Earn a trigintillion gold in total.", + icon: "🔮", + id: "omniversal_tycoon", + name: "Omniversal Tycoon", + reward: { crystals: 1_000_000 }, + unlockedAt: null, + }, // Higher quest milestones { condition: { amount: 30, type: "questsCompleted" }, @@ -363,4 +390,40 @@ export const defaultAchievements: Array = [ reward: { crystals: 25_000 }, unlockedAt: null, }, + { + condition: { amount: 50, type: "prestigeCount" }, + description: "Prestige 50 times.", + icon: "✨", + id: "prestige_transcendent", + name: "Transcendent", + reward: { crystals: 10_000 }, + unlockedAt: null, + }, + { + condition: { amount: 100, type: "prestigeCount" }, + description: "Prestige 100 times.", + icon: "💎", + id: "prestige_eternal", + name: "Eternal Looper", + reward: { crystals: 25_000 }, + unlockedAt: null, + }, + { + condition: { amount: 150, type: "prestigeCount" }, + description: "Prestige 150 times.", + icon: "🌟", + id: "prestige_immortal", + name: "Immortal Cycler", + reward: { crystals: 50_000 }, + unlockedAt: null, + }, + { + condition: { amount: 200, type: "prestigeCount" }, + description: "Prestige 200 times.", + icon: "👑", + id: "prestige_absolute", + name: "Absolute Champion", + reward: { crystals: 100_000 }, + unlockedAt: null, + }, ]; diff --git a/apps/web/src/engine/tick.ts b/apps/web/src/engine/tick.ts index 06ceaa7..db663ab 100644 --- a/apps/web/src/engine/tick.ts +++ b/apps/web/src/engine/tick.ts @@ -476,8 +476,8 @@ export const computeProjectedRunestones = (state: GameState): number => { ? 1.5 : 1; const runestoneMult = gain1Mult * gain2Mult; - /* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- optional chained game state field */ - const echoMult: number = state.transcendence?.echoPrestigeRunestoneMultiplier ?? 1; + const echoMult: number + = state.transcendence?.echoPrestigeRunestoneMultiplier ?? 1; return Math.floor(base * runestoneMult * echoMult); };