BIG EGG · Refonte terminée · Les 7 phases sont livrées

Refonte des variables globales

Les sept phases sont livrées et validées. Ce document reste le registre de référence : décisions, raisonnement archivé et état final.

Registre

Décisions arrêtées

DécisionRetenu
D1PortéeLes 7 phases d'affilée, sans interruption, mais suite de tests validée à chaque frontière de phase. Copie de sauvegarde datée avant chaque phase.
D2Couche overrideDès le départ — quatre couches complètes.
D3EmpilementClé par effet. Une instance par application, groupées par stack_key ; stack = expiration par pile, stack_refresh = expiration commune.
D4ChampsListe validée. Les champs d'auteur déjà définis dans l'outil deviennent adressables en plus, automatiquement.
D5RéactivitéRecalcul global via state_changed.
D6AdressesPréfixe element. supprimé. Les collections sont racines directes.
D7ÉquipementPrévu : arme, armure, objet, consommables, 1 à 3 skills, sets distincts resto/donjon. Les 7 phases livrent le substrat, pas l'équipement lui-même.
D8Fusion compteursfact_values fait foi.

Conséquence de D6 sur les adresses

fact.boss_defeated
player.attack_damage
enemies.fungling.total_killed
recipes.fried_egg.total_cooked
upgrade_nodes.hot_pan.purchased

Les racines forment un vocabulaire fermé : les noms de collections du fichier maître, plus fact, player, run et meta. Le premier segment se valide par simple appartenance à cet ensemble.

Conséquence de D7 sur l'architecture

Des sets distincts resto/donjon rendent player.attack_damage dépendant de la scène active. Le fournisseur d'équipement est donc conçu dès le départ autour d'emplacements et d'un contexte courant, même si aucun équipement n'existe encore.

Ce qui est acquis

Issu des échanges précédents, et inchangé.

La formule, en une ligne

final = (base + Σflat) × (coef_base + Σscaling) × (1 + Σglobal) × Πoverride
        → minimum → maximum → arrondi

Archive

Le raisonnement derrière chaque décision

Conservé pour mémoire : ces choix sont tranchés (voir le registre plus haut). Les options non retenues restent documentées afin qu'on sache, dans six mois, pourquoi elles ont été écartées — et ce qu'il faudrait rouvrir pour changer d'avis.

Deux écarts par rapport à mes recommandations : D1 (les 7 phases plutôt que 1-3) et D2 (override tout de suite). Les deux sont assumés et encadrés — D1 par la validation à chaque frontière de phase et les sauvegardes datées.

D1Structurante · la plus lourde

Quelle portée pour le premier chantier ?

Le plan complet fait sept phases. Rien n'oblige à tout faire d'un coup.

A · Phases 1 à 3 Recommandé

Adressage, compteurs automatiques, sélecteur dans l'outil. Le calcul des statistiques n'est pas touché.

Ce que tu obtiens à la fin :

// éditable dans l'outil, sans une ligne de GDScript
{ "path": "element.enemies.fungling.total_killed",
  "op": ">=", "value": 100 }

Et dungeon.gd:68 disparaît.

B · Phases 1 à 5

Ajoute les quatre couches, les sources nommées et les modificateurs temporaires. Débloque équipement et nourriture.

Impose la migration du schéma et de la sauvegarde dans le même chantier.

C · Les sept phases

Ajoute les effets temporaires avec cibles multiples. C'est quatre à six fois la surface de A, et le moment où une régression devient difficile à isoler.

Pourquoi A. Tu valides l'ergonomie de l'adressage — celle que tu utiliseras tous les jours dans l'outil — avant d'engager le calcul des stats, qui est la partie où une erreur se voit le moins et coûte le plus. Les phases suivantes restent ouvertes et ne redemandent aucun travail jeté.

D2Structurante

La couche override tout de suite, ou trois couches pour commencer ?

override est le seul vrai facteur multiplicatif : il s'applique isolément au lieu de se cumuler avec les autres.

A · Trois couches Recommandé

« Dégâts doublés » se fait avec global +1.0.

1 effet  : (1 + 1)     = ×2  ✓
2 effets : (1 + 1 + 1) = ×3

Correct tant qu'un seul effet de ce type peut être actif.

B · Quatre couches

Chaque override multiplie séparément.

1 effet  : ×2       = ×2
2 effets : ×2 × ×2  = ×4  ✓

Nécessaire si deux « doublements » doivent se composer.

Pourquoi A. Aucun effet de ton jeu n'en a besoin aujourd'hui, et ajouter la couche plus tard ne casse rien : c'est un champ supplémentaire, les données existantes restent valides sans migration. C'est une décision réversible à bas coût — autant ne pas la payer maintenant.

D3Structurante · visible en jeu

Quel empilement par défaut pour un effet réappliqué ?

Trois fungling empoisonnent le joueur. Poison : 3 dégâts/seconde par pile, maximum 3 piles.

A · Clé par effet Recommandé
stack_key = "poison"

Un poison à 3 piles → 9 dégâts/s. Une seule icône. Expire d'un bloc.

Le plafond de piles tient sa promesse : impossible de dépasser 9 dégâts/s quel que soit le nombre d'ennemis.

B · Clé par effet + source
stack_key = "poison@enemy:1234"

Trois poisons à 1 pile → 9 dégâts/s. Trois icônes. Expirent séparément.

Le plafond ne borne plus rien : dix ennemis donnent dix poisons.

Pourquoi A. C'est le seul des deux où max_stacks garantit réellement un plafond de dégâts — donc le seul équilibrable. B reste disponible effet par effet quand tu le veux explicitement.

D4Rapide · faible enjeu

Cette liste de champs vivants te convient-elle ?

Fournis automatiquement pour toutes les entités d'une collection, sans rien déclarer.

CollectionChamps automatiques
enemiestotal_killed, total_spawned, times_damaged_player
ingredientsowned, total_collected, total_spent
recipestotal_cooked, total_served, can_cook
upgrade_nodespurchased, state
customer_profilestotal_served, total_left_angry

Faible enjeu. Ajouter un champ plus tard, c'est une ligne dans le catalogue. Ne bloque pas sur cette liste — dis-moi juste s'il en manque un que tu sais déjà vouloir.

D5Structurante

Recalcul global, ou invalidation fine par chemin ?

A · Recalcul global Recommandé

Le signal state_changed existant. Recalculer les 13 nœuds d'upgrade coûte quelques dizaines de microsecondes.

B · Invalidation par chemin

Chaque écriture notifie les abonnés du chemin touché. Mise à jour chirurgicale.

Pourquoi A. C'est le cas où la bonne pratique générale n'est pas la bonne application : à cette échelle, B n'apporte aucun gain mesurable et ajoute des abonnements fantômes et des ordres de mise à jour subtils. Et comme Registry.write() est le point de passage unique, B reste greffable plus tard sans rien réécrire.

D6Rapide · irréversible en pratique

Confirmes-tu la forme des adresses ?

Ton exemple disait element.monsters.id.variable. En gardant les noms du fichier maître, ça donne :

// ton exemple
element.monsters.turkey_clown.total_killed

// ce que ça devient réellement
element.enemies.turkey_clown.total_killed

Pourquoi confirmer. Ce préfixe sera tapé dans chaque condition et chaque effet, pour toujours. Si tu préfères entity. ou data. à element., c'est maintenant — après, c'est une migration de toutes les données.

D7Information · pas un choix de design

L'équipement est-il prévu, et à quelle échéance ?

Il n'existe aucun système d'arme ou d'équipement dans le jeu aujourd'hui. J'ai proposé que l'équipement soit une source dérivée — lue en direct depuis l'emplacement équipé, jamais stockée dans la table.

Aujourd'hui, la seule source dérivée est upgrade:. Je construis quand même l'interface de fournisseur — elle coûte presque rien — mais je ne construis pas d'équipement tant que tu ne le demandes pas.

Ce que ça change. Si l'équipement arrive bientôt, je dimensionne l'interface pour plusieurs emplacements dès la phase 5. Sinon, un fournisseur unique suffit.

D8Rapide · peut perdre des données

Comment fusionner statistics et fact_values ?

Aujourd'hui le même compteur est écrit dans deux dictionnaires, et load_game() contient de la logique de réconciliation. La phase 2 les fusionne. Si ta sauvegarde actuelle a divergé entre les deux, il faut une règle.

A · fact_values fait foi Recommandé

C'est celui que lisent les conditions d'upgrade — donc celui qui reflète ce que le joueur a réellement vu débloquer.

B · Le plus grand des deux

Ne perd jamais de progression, mais peut débloquer rétroactivement un nœud qui ne l'était pas.

Pourquoi A. Cohérence avec ce qui était affiché. En pratique les deux valeurs sont presque toujours identiques — c'est une règle de sûreté, pas un cas courant.

Suivi

Avancement des phases

Une copie de sauvegarde datée est prise avant chaque phase, dans _backups/. La suite complète — parse éditeur, smoke test, upgrade return, lint PHP et JS — doit être verte avant de passer à la suivante.

PhaseContenuÉtat
0Sauvegarde initialeCopie complète avant toute modificationfait
1Résolveur d'adressesAddressCatalog + Registry, catalogue de champs, traduction des conditions héritées. Aucune donnée modifiée.fait
2Compteurs unifiésstatistics supprimé, compteurs par entité alimentés par le jeu, dungeon.gd:68 supprimé. Sauvegarde 6 avec migration.fait
3Sélecteur dans l'outilListes en cascade, validation PHP miroir, schéma 8, 27 conditions migrées vers des adresses.fait
4Crochets d'événement9 points de jeu instrumentés, effets déclaratifs plats validés des deux côtés, éditeur de crochets pour 5 collections.fait
5Couches et sourcesQuatre couches, sources nommées, expirations, ordre set → add → multiply imposé. Bug de déterminisme corrigé.fait
6Effets temporairesCollection effects, porteurs d'effets, empilement avec expiration par pile, drapeaux de capacité, persistance des effets du joueur.fait
7Retrait du format héritéLe runtime ne connaît plus que les adresses et les couches. L'outil reste tolérant à l'import.fait

Ce que ces phases ne livrent pas

Le substrat, oui. L'équipement lui-même, non. Armes, armures, emplacements, skills activables et sets par contexte sont une fonctionnalité distincte, à construire une fois ce socle en place.