// cosmetics.ts — Système cosmétique (récompenses achievements + prestige) import type { GameState } from "./economy"; import { ACHIEVEMENTS } from "../data/achievements"; export type CosmeticSlot = "hat" | "eyes" | "body" | "tail" | "accessory"; export interface Cosmetic { id: string; name: string; slot: CosmeticSlot; svg: string; // chemin vers le SVG overlay (/svg/cosmetics/...) source: "achievement" | "prestige"; sourceId: string; // achievement id ou "prestige_N" description: string; } export interface CosmeticState { inventory: string[]; // ids des cosmétiques débloqués equipped: Partial>; // slot → cosmetic id } export const DEFAULT_COSMETIC_STATE: CosmeticState = { inventory: [], equipped: {}, }; // --- Catalogue des cosmétiques --- export const COSMETICS: Cosmetic[] = [ // Hat { id: "crown", name: "Couronne Ancestrale", slot: "hat", svg: "/svg/cosmetics/crown.svg", source: "prestige", sourceId: "prestige_10", description: "10 prestiges — la royauté du marais" }, { id: "cap_swamp", name: "Casquette du Marais", slot: "hat", svg: "/svg/cosmetics/cap-swamp.svg", source: "achievement", sourceId: "industriel", description: "10 générateurs au total" }, // Eyes { id: "glasses_savant", name: "Lunettes du Savant", slot: "eyes", svg: "/svg/cosmetics/glasses-savant.svg", source: "prestige", sourceId: "prestige_5", description: "5 prestiges — la sagesse" }, { id: "mask_frog", name: "Masque Grenouille", slot: "eyes", svg: "/svg/cosmetics/mask-frog.svg", source: "achievement", sourceId: "empire", description: "1M têtards — le regard de l'empire" }, // Body { id: "cape_algae", name: "Cape d'Algues", slot: "body", svg: "/svg/cosmetics/cape-algae.svg", source: "prestige", sourceId: "prestige_25", description: "25 prestiges — tissée par le marais" }, { id: "armor_scales", name: "Armure d'Écailles", slot: "body", svg: "/svg/cosmetics/armor-scales.svg", source: "achievement", sourceId: "tycoon", description: "100 générateurs — blindage total" }, // Tail { id: "flame_tail", name: "Queue Enflammée", slot: "tail", svg: "/svg/cosmetics/flame-tail.svg", source: "prestige", sourceId: "prestige_50", description: "50 prestiges — la traîne de feu" }, { id: "ribbon", name: "Ruban du Nouveau-Né", slot: "tail", svg: "/svg/cosmetics/ribbon.svg", source: "achievement", sourceId: "first_prestige", description: "Premier prestige — le début de tout" }, // Accessory { id: "aura_swamp", name: "Aura du Marais", slot: "accessory", svg: "/svg/aura-swamp.svg", source: "achievement", sourceId: "veteran", description: "5 prestiges — l'aura des anciens" }, { id: "particles_gold", name: "Particules Dorées", slot: "accessory", svg: "/svg/cosmetics/particles-gold.svg", source: "prestige", sourceId: "prestige_3", description: "3 prestiges — poussière d'étoiles" }, ]; // --- Fonctions cosmétiques --- // Vérifie si un cosmétique devrait être débloqué export function shouldUnlockCosmetic(cosmetic: Cosmetic, state: GameState): boolean { if (cosmetic.source === "prestige") { const tier = parseInt(cosmetic.sourceId.replace("prestige_", ""), 10); return state.prestigeCount >= tier; } if (cosmetic.source === "achievement") { const achievement = ACHIEVEMENTS.find((a) => a.id === cosmetic.sourceId); return achievement ? achievement.check(state) : false; } return false; } // Calcule les cosmétiques nouvellement débloqués (pas encore dans l'inventaire) export function computeNewUnlocks(state: GameState, cosmeticState: CosmeticState): string[] { return COSMETICS .filter((c) => !cosmeticState.inventory.includes(c.id) && shouldUnlockCosmetic(c, state)) .map((c) => c.id); } // Équiper un cosmétique (retourne le nouvel état) export function equipCosmetic(cosmeticState: CosmeticState, cosmeticId: string): CosmeticState { const cosmetic = COSMETICS.find((c) => c.id === cosmeticId); if (!cosmetic) return cosmeticState; if (!cosmeticState.inventory.includes(cosmeticId)) return cosmeticState; return { ...cosmeticState, equipped: { ...cosmeticState.equipped, [cosmetic.slot]: cosmeticId }, }; } // Déséquiper un slot export function unequipSlot(cosmeticState: CosmeticState, slot: CosmeticSlot): CosmeticState { const { [slot]: _, ...rest } = cosmeticState.equipped; return { ...cosmeticState, equipped: rest }; } // Ajouter des cosmétiques à l'inventaire export function addToInventory(cosmeticState: CosmeticState, ids: string[]): CosmeticState { const newIds = ids.filter((id) => !cosmeticState.inventory.includes(id)); if (newIds.length === 0) return cosmeticState; return { ...cosmeticState, inventory: [...cosmeticState.inventory, ...newIds] }; }