// Achievements: permanent small bonuses for milestones. Each one reads a // single statistic, so adding one is a line in data/achievements.json (plus // its title in the core locale files). export function statValue(state, stat) { switch (stat) { case 'lifetimeProduced': return state.lifetimeProduced; case 'generatorsOwned': return Object.values(state.generators).reduce((sum, n) => sum + n, 0); case 'upgradesOwned': return state.upgrades.length; case 'researchOwned': return state.research.length; case 'prestiges': return state.legacy.prestiges; case 'chips': return state.chips; default: return state.stats[stat] ?? 0; // investProfit, gambleWins, contractsDone, eventsClaimed... } } /** Grant every achievement whose condition is now met. Returns the new ids. */ export function checkAchievements(state, ctx) { const granted = []; for (const a of ctx.achievements) { if (state.achievements.includes(a.id)) continue; if (statValue(state, a.condition.stat) >= a.condition.min) { state.achievements.push(a.id); granted.push(a.id); } } return granted; }