# Plan d'implémentation – Specs Animaux, Morts, Saisons, Billeterie Références : `docs/plan-action-cahier-des-charges.md` (§7 Animaux/morts/saisons, §8 Billeterie), `docs/features/causes-mort-audit.md`, et tous les fichiers de `docs/specs/` concernés. --- ## Spécifications couvertes | Spec | Périmètre implémenté | |------|----------------------| | **animal_generique.md** | États faim/température/santé ; feedbacks visuels (froid=bleu/givre, chaud=rouge/vapeur, faim=icône, heureux=cœurs) ; pas de jauges. | | **mort_bebe.md** | Causes déjà en place ; conséquence mort adulte vente échouée (aligné). | | **inventaire_saisons.md** | Cycle 4 saisons ; modificateurs météo/température/reproduction/survie/visiteurs. | | **temperature.md** | Modificateur saison (+0 Printemps, +10 Été, -2 Automne, -15 Hiver) ; modificateur jour/nuit (+5 jour, -5 nuit) ; feedback critique (spec déjà partiellement en place via tolerance). | | **reproduction.md** | Impact saisons : Printemps +20% chance, Hiver -50% (sauf animaux froids). | | **billeterie.md** | Flux entrée/sortie ; capacité 20/unité ; ouverture 08h–20h ; 1 visiteur/s max entrée ; modificateurs saison (été +20% prix, hiver -10%). | | **visiteur.md** | Arrivée par billeterie ; durée max (1 journée / stayDuration) ; départ par billeterie ; affluence selon heure (08h–10h faible, 10h–16h fort, >18h nul) ; multiplicateur saison (été x1.5, hiver x0.6, etc.). | | **inventaire_heures.md** | Cycle jour/nuit (déjà timeOfDay) ; billeterie fermée la nuit. | | **centre_recherche.md** | Niveau recherche (skill level) : si rareté animal > niveau recherche → mort (cause « niveau de recherche trop inférieur »). | | **causes-mort-audit.md** | Seuls (animal seul meurt) ; recherche trop basse ; vente adulte échouée (deathCountRecent). | --- ## Phase 1 – Causes de mort manquantes **Objectif :** Compléter les causes de mort listées dans `docs/features/causes-mort-audit.md` (Non implémenté). ### 1.1 Vente adulte échouée - **Fichier :** `web/js/trade.js` - **Changement :** Dans `tickSaleListings`, lorsque `nowUnix >= listing.endAt` et `listing.isBaby === false`, incrémenter `state.deathCountRecent` (comme pour les bébés). - **Spec :** causes-mort-audit §9. ### 1.2 Niveau de recherche trop inférieur - **Fichier :** `web/js/food.js` (ou module commun appelé par `checkDeathCauses`) - **Logique :** Pour chaque bloc animal sur la grille, récupérer `LootTables.Animals[cell.id].rarityLevel` et le comparer à `getSkillLevel(state)` (depuis `conveyor.js`). Si `rarityLevel > getSkillLevel(state)`, retirer le bloc et incrémenter `deathCountRecent`. - **Config optionnelle :** `GameConfig.Research?.MaxRarityAllowed` ou utiliser directement skill level (1–8) vs rarityLevel (1–5) ; si le projet utilise skill level comme “niveau école” et que la spec centre_recherche parle de “rareté visible”, interpréter : animal de rareté > niveau compétence → mort. - **Fichiers :** `web/js/food.js`, `web/js/config.js` (si config ajoutée), `docs/features/causes-mort-audit.md` (mise à jour). ### 1.3 Animal seul (solitude) - **Spec :** animal_generique “Besoin de congénères (reproduction) ou de solitude (selon espèce)” ; causes-mort-audit §1 “Seuls”. - **Interprétation :** Au moins une règle “animal seul meurt” : si aucun autre animal de la même espèce (même `cell.id`) dans un rayon de N cases (ex. 5), après un délai configurable, retirer l’animal et incrémenter `deathCountRecent`. - **Fichiers :** `web/js/config.js` (`Animal.MinSameSpeciesInRadius`, `Animal.MaxSecondsAlone`), `web/js/food.js` dans `checkDeathCauses` (ou helper) : pour chaque origine animal, compter les autres blocs même `id` dans le rayon ; si 0 et `nowUnix - placedAt > MaxSecondsAlone`, retirer. - **État :** Optionnel si “selon espèce” complique (toutes espèces = besoin congénères par défaut). --- ## Phase 2 – Config et données saisons **Objectif :** Introduire le cycle de saisons et la config sans encore brancher tous les impacts. ### 2.1 Config saisons - **Fichier :** `web/js/config.js` - **Ajout :** `Season: { DayLengthSeconds: 120, DaysPerSeason: 7 }` (ou 30 jours in-game). `Season.TemperatureModifier: { spring: 0, summer: 10, autumn: -2, winter: -15 }`. `Season.VisitorMultiplier: { spring: 1, summer: 1.5, autumn: 0.8, winter: 0.6 }`. `Season.ReproductionBonus: { spring: 0.2, summer: 0, autumn: 0, winter: -0.5 }` (Hiver -50% sauf animaux froids à traiter dans reproduction). - **Référence :** `docs/specs/inventaire_saisons.md`, `temperature.md`, `visiteur.md`, `reproduction.md`. ### 2.2 State et temps de jeu “jour” - **Fichier :** `web/js/types.js` - **Ajout :** `gameDay?: number` (jour de jeu absolu, dérivé de `timeOfDay` et `DayLengthSeconds`) ou `season?: 'spring'|'summer'|'autumn'|'winter'`, `seasonDay?: number` (jour dans la saison). - **Fichier :** `web/js/time-weather.js` ou nouveau `web/js/seasons.js` - **Logique :** À partir de `state.timeOfDay` et `GameConfig.Time.DayLengthSeconds`, calculer un “game day” (entier). À partir de `gameDay` et `DaysPerSeason`, calculer `season` et `seasonDay`. Exporter `getCurrentSeason(state)`, `getSeasonTemperatureModifier(season)`, `getSeasonVisitorMultiplier(season)`, `getSeasonReproductionBonus(season)`. --- ## Phase 3 – Cycle saisons et impacts **Objectif :** Brancher la saison sur température, reproduction, visiteurs, billeterie. ### 3.1 Température affichée / calculée avec saison - **Fichiers :** `web/js/placement.js` ou module température existant (ex. `getDisplayTemperature` dans food.js / grid-utils) - **Changement :** `currentTemp = baseBiomeTemp + seasonMod + dayNightMod + caseRegulatorOffset`. Récupérer `seasonMod` depuis `getSeasonTemperatureModifier(getCurrentSeason(state))`. - **Spec :** `temperature.md` (Impact Saisons, Impact Heure / Jour-Nuit). ### 3.2 Reproduction et saison - **Fichier :** `web/js/reproduction.js` - **Changement :** Intégrer un bonus/malus de saison (Printemps +20%, Hiver -50% sauf animaux “froids” selon biome) dans le calcul de chance de reproduction. - **Spec :** `reproduction.md`, `inventaire_saisons.md`. ### 3.3 Visiteurs et saison - **Fichier :** `web/js/income.js` - **Changement :** Dans `getVisitorDemand`, multiplier par `getSeasonVisitorMultiplier(getCurrentSeason(state))`. - **Spec :** `visiteur.md` (Impact Saisons). ### 3.4 Billeterie – modificateur prix ticket par saison - **Fichier :** `web/js/income.js` (ou economy) - **Changement :** Prix ticket base ; si saison été : *1.2 ; si saison hiver : *0.9. Appliquer dans le calcul de `paymentPerVisitor` (entrée). - **Spec :** `billeterie.md` (Impact Saisons). ### 3.5 Notification changement de saison - **Fichier :** `web/js/ui.js` ou game-loop - **Changement :** Lors d’un changement de saison (comparer `getCurrentSeason(state)` à une valeur stockée), afficher un message type “C’est le [Saison] !” (toast ou texte temporaire). Stocker `lastSeason` dans le state si nécessaire. - **Spec :** `inventaire_saisons.md` (Messages SEASON_CHANGE). --- ## Phase 4 – Flux billeterie complet **Objectif :** Heures d’ouverture, départs explicites, limite 1 visiteur/s à l’entrée. ### 4.1 Heures d’ouverture (08h–20h) - **Fichier :** `web/js/config.js` - **Ajout :** `Billeterie.OpenHour: 8`, `Billeterie.CloseHour: 20` (ou 20h = fermeture, pas d’entrée après). - **Fichier :** `web/js/income.js` - **Changement :** Dans `tickVisitorArrivals`, ne pas ajouter de nouveaux visiteurs si `timeOfDay` est en dehors de [8, 20] (ou équivalent en phase “night”). Utiliser `getTimePhase(state.timeOfDay)` ; si phase “night” ou `timeOfDay < 8` ou `timeOfDay >= 20`, ne pas pousser de nouveaux `{ arrivedAt }`. - **Spec :** `billeterie.md`, `inventaire_heures.md`. ### 4.2 Départs par billeterie (durée max “1 journée”) - **Déjà en place :** `getStayDurationSeconds` et filtre `nowUnix < v.arrivedAt + stayDuration`. S’assurer que la durée est bien “1 journée” (DayLengthSeconds × facteur) selon spec. Optionnel : faire partir les visiteurs vers la “sortie” (billeterie) visuellement. - **Spec :** `visiteur.md` (Durée max, Départ). ### 4.3 Limite 1 visiteur / seconde à l’entrée - **Fichier :** `web/js/income.js` - **Changement :** Dans `tickVisitorArrivals`, au lieu d’ajouter `target - current` d’un coup, limiter le nombre d’entrées sur ce tick à au plus `ceil(dt)` ou 1 par tick si tick = 1s, ou stocker `lastVisitorSpawnAt` et n’ajouter qu’un visiteur par seconde réelle. Adapter selon `IncomeTickMs` (ex. si tick 5s, ajouter au plus 5 nouveaux visiteurs par tick, ou 1 par seconde en interpolant). - **Spec :** `billeterie.md` (“1 visiteur / seconde max”). ### 4.4 Affluence selon l’heure (optionnel) - **Fichier :** `web/js/income.js` - **Changement :** Dans `getVisitorDemand`, appliquer un coefficient selon `timeOfDay` : 08h–10h faible, 10h–16h fort, 16h–18h décroissant, >18h nul (ou très faible). Utiliser `state.timeOfDay` et `getTimePhase`. - **Spec :** `visiteur.md` (Impact Heure / Jour-Nuit). --- ## Phase 5 – Feedbacks visuels animaux **Objectif :** Pas de jauges ; états visuels dérivés des données existantes (température, nourriture, visite, reproduction). ### 5.1 Détection des états par cellule animal - **Fichier :** nouveau `web/js/animal-visual-state.js` ou dans `web/js/ui.js` / module rendu - **Logique :** Pour une cellule animal (origine) : `getDisplayTemperature`, `lastFedAt`, `lastVisitedAt`, état reproduction (paire proche). Exporter `getAnimalVisualState(cell, state, grid)` → `{ cold: boolean, hot: boolean, hungry: boolean, sick: boolean, happy: boolean }` (sick si proche mort / mal nourri ; happy si récemment visité et nourri et temp ok, ou en reproduction). - **Spec :** `animal_generique.md`, `temperature.md` (Feedback critique). ### 5.2 Rendu CSS / classes - **Fichier :** `web/js/ui.js` (rendu grille) - **Changement :** Pour chaque bloc animal rendu, ajouter des classes CSS selon `getAnimalVisualState` : ex. `animal-cold`, `animal-hot`, `animal-hungry`, `animal-sick`, `animal-happy`. Pas de jauges. - **Fichier :** `web/css/main.css` - **Changement :** Styles pour ces classes : teinte bleutée/givre (froid), rougeâtre/vapeur (chaud), icône faim (lent/maigre), ternes/mouches (malade), cœurs/couleurs vives (heureux). Utiliser filter, box-shadow ou pseudo-éléments pour icônes. - **Spec :** `animal_generique.md` (Vie Quotidienne), `temperature.md` (Feedback critique). --- ## Phase 6 – Documentation et clôture - Mettre à jour `docs/features/causes-mort-audit.md` (causes implémentées : seuls, recherche, vente adulte). - Créer ou mettre à jour `docs/features/saisons-phase.md` (cycle, config, impacts). - Créer ou mettre à jour `docs/features/billeterie-flux.md` (heures, 1/s, départs). - Créer `docs/features/feedbacks-visuels-animaux.md` (états, classes CSS, pas de jauges). - Vérifier lint, types, compilation. --- ## Ordre d’exécution recommandé 1. **Phase 1** – Causes de mort (trade.js adulte, food.js recherche, optionnel solitude). 2. **Phase 2** – Config et module saisons (config.js, seasons.js, types.js). 3. **Phase 3** – Impacts saisons (température, reproduction, visiteurs, billeterie, notification). 4. **Phase 4** – Flux billeterie (heures, 1/s, affluence heure). 5. **Phase 5** – Feedbacks visuels animaux (animal-visual-state.js, ui.js, main.css). 6. **Phase 6** – Documentation. --- ## Fichiers principaux impactés | Fichier | Phases | |---------|--------| | `web/js/trade.js` | 1.1 | | `web/js/food.js` | 1.2, 1.3 | | `web/js/config.js` | 1.2, 1.3, 2.1, 4.1 | | `web/js/types.js` | 2.2 | | `web/js/time-weather.js` ou `web/js/seasons.js` | 2.2, 3.1 | | `web/js/placement.js` ou module température | 3.1 | | `web/js/reproduction.js` | 3.2 | | `web/js/income.js` | 3.3, 3.4, 4.1, 4.3, 4.4 | | `web/js/ui.js` | 3.5, 5.2 | | `web/js/animal-visual-state.js` (nouveau) | 5.1 | | `web/css/main.css` | 5.2 | | `docs/features/*.md` | 6 |