feat: New features (research, invest, gambling, new game+, trophies)

This commit is contained in:
gauvainboiche
2026-10-08 14:03:00 +02:00
parent 1caa4d92b9
commit fc0d5e3ba4
56 changed files with 4332 additions and 249 deletions
+52
View File
@@ -0,0 +1,52 @@
// Legacy (prestige): restart the run for permanent points. Points are spent on
// repeatable perks, and every point ever earned also gives a small passive bonus.
// What survives a restart: see META_KEYS in state.js.
import { modifiersFor } from './modifiers.js';
import { createState, META_KEYS } from './state.js';
/** Points a restart would grant right now (0 until the run is big enough). */
export function legacyGain(state, ctx, mods) {
const { threshold } = ctx.rules.legacy;
if (state.totalProduced < threshold) return 0;
return Math.floor(Math.sqrt(state.totalProduced / threshold) * mods.legacyGain);
}
export function perkLevel(state, perk) {
return state.legacy.perks[perk.id] ?? 0;
}
export function perkCost(perk, level) {
return Math.ceil(perk.baseCost * perk.costGrowth ** level);
}
export function buyPerk(state, ctx, id) {
const perk = ctx.perksById.get(id);
if (!perk) return false;
const level = perkLevel(state, perk);
const cost = perkCost(perk, level);
if (level >= perk.maxLevel || state.legacy.points < cost) return false;
state.legacy.points -= cost;
state.legacy.perks[id] = level + 1;
return true;
}
/** Restart the run in place. Returns the points gained, or 0 if not allowed. */
export function prestige(state, ctx, now = Date.now()) {
const gain = legacyGain(state, ctx, modifiersFor(state, ctx));
if (gain < 1) return 0;
const fresh = createState(ctx, now);
const kept = Object.fromEntries(META_KEYS.map((key) => [key, state[key]]));
kept.legacy = {
...state.legacy,
points: state.legacy.points + gain,
earned: state.legacy.earned + gain,
prestiges: state.legacy.prestiges + 1,
};
Object.assign(state, fresh, kept);
// Perks like "head start" shape the new run.
state.funds += modifiersFor(state, ctx).startFunds;
return gain;
}