feat: click upgrades — buy click power with tadpoles, tied to generators
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 21s

5 click upgrades, each linked to a generator type:
- Nid Douillet (+1/clic, 50 base) — requires owning a Nid
- Eau Fertile (+3/clic, 500 base) — requires a Mare
- Spores Actives (+8/clic, 5k base) — requires a Marecage
- Courant Vital (+20/clic, 50k base) — requires an Etang
- Source Ancestrale (+50/clic, 500k base) — requires a Lac

Cost scales x1.2 per level. Reset at prestige (like generators).
Click gain = (base + upgradePower) × prestige × tree × infraBonus.
ClickPanel shows upgrade shop with level badges and gen requirements.
Adds tadpole sink for active play — strategic choice vs buying generators.
This commit is contained in:
2026-03-28 21:19:01 +01:00
parent f9dd4c3ca4
commit 7a8f4f325c
4 changed files with 155 additions and 53 deletions

View File

@@ -3,8 +3,8 @@
// Chaque sprint ajoute un step (v2→v3, etc.)
import { CURRENT_SAVE_VERSION } from "./balance";
import type { GameState } from "./economy";
import { DEFAULT_EVOLUTION_TREE, DEFAULT_GENERATORS } from "./economy";
import type { GameState, ClickUpgrade } from "./economy";
import { DEFAULT_EVOLUTION_TREE, DEFAULT_GENERATORS, DEFAULT_CLICK_UPGRADES } from "./economy";
/**
* Détecte la version d'une save et applique les migrations nécessaires.
@@ -32,6 +32,11 @@ export function migrateSave(raw: Record<string, unknown>): GameState {
state.generators as Array<Record<string, unknown>> | undefined
);
// Click upgrades — merge with defaults (preserves levels, adds new upgrades)
state.clickUpgrades = mergeClickUpgrades(
state.clickUpgrades as Array<Record<string, unknown>> | undefined
);
return state as unknown as GameState;
}
@@ -149,3 +154,25 @@ function mergeGenerators(
return { ...defaultGen };
});
}
/**
* Merge les click upgrades sauvegardés avec DEFAULT_CLICK_UPGRADES.
* Conserve le level, met à jour les stats de base.
*/
function mergeClickUpgrades(
saved: Array<Record<string, unknown>> | undefined
): ClickUpgrade[] {
if (!saved || !Array.isArray(saved)) {
return DEFAULT_CLICK_UPGRADES.map((u) => ({ ...u }));
}
const savedById = new Map(saved.map((u) => [u.id as string, u]));
return DEFAULT_CLICK_UPGRADES.map((def) => {
const s = savedById.get(def.id);
if (s) {
return { ...def, level: typeof s.level === "number" ? s.level : 0 };
}
return { ...def };
});
}