**Motivations:** - Initialisation du versionning git pour le projet **Root causes:** - N/A (Nouveau projet) **Correctifs:** - N/A **Evolutions:** - Structure initiale du projet - Ajout du .gitignore **Pages affectées:** - Tous les fichiers
51 lines
4.3 KiB
Markdown
51 lines
4.3 KiB
Markdown
# Phase 8 – Attractivité et visiteurs (billeterie, cap, score)
|
||
|
||
**Objectif :** Plafonner les visiteurs par la capacité billeterie, calculer un score d’attractivité (valeur, espèces, rareté, remplissage, pénalités morts, bonus naissances) et l’afficher sur la carte du monde.
|
||
|
||
**Référence :** `docs/plan-implementation-rappel-grandes-regles.md` phase 8.
|
||
|
||
## Impacts
|
||
|
||
- Les visiteurs sont plafonnés par la capacité billeterie (20 × niveau total billeterie). Sans billeterie, le plafond n’est pas appliqué (comportement inchangé).
|
||
- Nouveau score d’attractivité exposé dans `state.attractivityScore` et affiché sous le nom du zoo (joueur) sur la carte du monde.
|
||
- La formule d’attractivité pourra servir plus tard à l’allocation des visiteurs depuis les villes (phase 11).
|
||
|
||
## Modifications
|
||
|
||
- **income.js** : suppression des imports dupliqués ; `getBilleterieCapacity(state)` ; dans `getVisitorParams`, plafonnement de `visitorCount` par `getBilleterieCapacity(state)` ; `getAttractivityScore(state)` (valeur cumulée, nombre d’espèces, rareté moyenne, taux de remplissage, pénalité morts, bonus naissances).
|
||
- **config.js** : `Visitor.AttractivityDeathPenalty`, `Visitor.AttractivityBirthBonus`.
|
||
- **types.js** : `GameState.attractivityScore?`.
|
||
- **game-loop.js** : import `getAttractivityScore` ; après `tickResearch`, `state.attractivityScore = getAttractivityScore(state)`.
|
||
- **ui.js** : pour le zoo joueur, ligne « Score attractivité: X.X » sous le score de reproduction (classe `world-map-zoo-attractivity-score`).
|
||
- **main.css** : style `.world-map-zoo-attractivity-score`.
|
||
|
||
## Disparition des animaux non visités (§2)
|
||
|
||
- **Config** : `Visitor.MaxSecondsWithoutVisit` (300 s par défaut). Un animal dont aucune visite n’a été enregistrée sur sa case depuis plus de cette durée est retiré (case vidée, `deathCountRecent` incrémenté).
|
||
- **animal-visits.js** : `tickAnimalVisits(state, nowUnix, nowMs)` met à jour `lastVisitedAt` des cases animales sous la position actuelle des visiteurs (orbites autour du centre d’attraction).
|
||
- **food.js** : `checkDeathCauses(state, nowUnix)` utilise `MaxSecondsWithoutVisit` ; si `nowUnix - lastVisitedAt >= maxVisit`, le bloc animal est supprimé.
|
||
- **game-loop.js** : `tickAnimalVisits` est appelé avant `tickFeeding` et `checkDeathCauses`.
|
||
|
||
## Stagnation (§3)
|
||
|
||
- **Config** : `Visitor.StagnationDecayAfterSeconds` (60 s), `Visitor.StagnationDecayPerMinute` (0.05). Après ce délai sans action d’évolution, le multiplicateur de demande visiteurs décroît (plancher 10 %).
|
||
- **income.js** : `getStagnationMultiplier(state, nowUnix)` utilise `state.lastEvolutionAt` ; appliqué dans `getVisitorDemand(state, nowUnix)`.
|
||
- **lastEvolutionAt** est mis à jour sur : upgrade (plot, conveyor, truck, world map, school, nursery, shop, research, billeterie, food, reception, biome), place (egg, baby, reception animal), vente (sellAnimalToNpc, addMatureBabyToSale, addReceptionAnimalToSale), prestige, moveCell.
|
||
|
||
## Implémenté ultérieurement (modèle visiteurs par entité)
|
||
|
||
- **Durée max 1 journée par visiteur** : `state.visitorArrivals[]` avec `{ arrivedAt }` ; base = `Time.DayLengthSeconds` (1 jour) ; sortie quand `now > arrivedAt + getStayDurationSeconds(state)`.
|
||
- **Prolongation par boutiques et diversité** : `getStayMultiplier(state)` = 1 + (niveaux boutique × `Visitor.StayMultiplierPerShopLevel`) + (espèces distinctes × `Visitor.StayMultiplierPerSpecies`) ; `getStayDurationSeconds(state) = base × getStayMultiplier(state)`.
|
||
- **Config** : `Visitor.StayMultiplierPerShopLevel`, `Visitor.StayMultiplierPerSpecies` (base jour = `Time.DayLengthSeconds`).
|
||
- **Game loop** : `tickVisitorArrivals(state, nowUnix)` appelé avant `incomeTick` ; `getVisitorParams(state)` utilise `state.visitorArrivals.length` ; sans billeterie, fallback sur l’ancienne formule pour rétrocompatibilité.
|
||
|
||
## Modalités de déploiement
|
||
|
||
- Aucun déploiement serveur. Rechargement client suffit.
|
||
|
||
## Modalités d’analyse
|
||
|
||
- Sans billeterie : le nombre de visiteurs reste calculé comme avant (sans plafond).
|
||
- Avec au moins une case billeterie : le nombre de visiteurs affiché et utilisé pour les revenus ne dépasse pas (niveau total billeterie × 20).
|
||
- Carte du monde, zoo joueur : affichage « Score attractivité: X.X » mis à jour à chaque tick.
|