fix: empêcher le réengagement immédiat après rechargement d'une fuite (#42) #45

Merged
Reliodas merged 1 commit from fix/42-flee-reload-reengage into develop 2026-06-20 11:29:35 +00:00
Owner

Closes #42

Le verrou de désengagement _disengaged ajouté par #26 ne vit que dans l'instance de World. Or une fuite écrit immédiatement une autosave avec le héros et l'ennemi encore en perception mutuelle. Au chargement, _disengaged est vide et l'appel différé à evaluate_perception relance directement le combat (reproduit en headless).

Changements

  • scenes/exploration/world.gd : dans _ready, lors de la restauration des états persistants (GameState.entity_states_for(map_id)), amorcer _disengaged[ent.entity_id] = true pour toute entité dont l'état est restauré. entity_state_by_map ne contient que des entités ayant fui/divergé et survit déjà au save/load (deep-duplicate dans to_save/apply_save) : le verrou est donc reconstitué au chargement, avant l'appel différé à evaluate_perception. Politique équivalente à un verrou persistant, sans nouveau champ.
  • La levée du verrou (rupture de perception) reste celle de #26 : quand la perception est déjà rompue au chargement, le verrou tombe à la première évaluation ; une nouvelle acquisition réengage. Le contact (Player._try_move) réengage toujours.
  • tests/unit/test_world_encounter.gd : isolation renforcée (entity_state_by_map nettoyé en before_each/after_each), car cet état alimente désormais le verrou.

Critères d'acceptation

  • charger une sauvegarde prise après une fuite laisse le joueur en exploration ;
  • l'hostile fui ne réengage pas tant que sa perception du héros n'a pas été rompue ;
  • le verrou survit au save/load (politique équivalente : reconstitué depuis l'état persistant des fuyards) ;
  • le contact direct reste capable de réengager ;
  • après rupture puis nouvelle acquisition de perception, l'hostile peut réengager ;
  • un test de régression couvre fuite, save/load, absence de réengagement immédiat, rupture et réacquisition.

Tests

  • tests/unit/test_world_encounter.gd::test_flee_save_load_does_not_reengage_until_perception_breaks : fuite → to_save/apply_save → nouvelle instance World → verrou reconstitué, pas de réengagement immédiat ; rupture (mur) → verrou levé ; réacquisition → FIGHTING.
  • Suite GUT complète verte : 163 tests, 519 assertions.
Closes #42 Le verrou de désengagement `_disengaged` ajouté par #26 ne vit que dans l'instance de `World`. Or une fuite écrit immédiatement une autosave avec le héros et l'ennemi encore en perception mutuelle. Au chargement, `_disengaged` est vide et l'appel différé à `evaluate_perception` relance directement le combat (reproduit en headless). ## Changements - `scenes/exploration/world.gd` : dans `_ready`, lors de la restauration des états persistants (`GameState.entity_states_for(map_id)`), **amorcer `_disengaged[ent.entity_id] = true`** pour toute entité dont l'état est restauré. `entity_state_by_map` ne contient **que** des entités ayant fui/divergé et survit déjà au save/load (deep-duplicate dans `to_save`/`apply_save`) : le verrou est donc reconstitué au chargement, **avant** l'appel différé à `evaluate_perception`. Politique équivalente à un verrou persistant, sans nouveau champ. - La levée du verrou (rupture de perception) reste celle de #26 : quand la perception est déjà rompue au chargement, le verrou tombe à la première évaluation ; une nouvelle acquisition réengage. Le contact (`Player._try_move`) réengage toujours. - `tests/unit/test_world_encounter.gd` : isolation renforcée (`entity_state_by_map` nettoyé en `before_each`/`after_each`), car cet état alimente désormais le verrou. ## Critères d'acceptation - [x] charger une sauvegarde prise après une fuite laisse le joueur en exploration ; - [x] l'hostile fui ne réengage pas tant que sa perception du héros n'a pas été rompue ; - [x] le verrou survit au save/load (politique équivalente : reconstitué depuis l'état persistant des fuyards) ; - [x] le contact direct reste capable de réengager ; - [x] après rupture puis nouvelle acquisition de perception, l'hostile peut réengager ; - [x] un test de régression couvre fuite, save/load, absence de réengagement immédiat, rupture et réacquisition. ## Tests - `tests/unit/test_world_encounter.gd::test_flee_save_load_does_not_reengage_until_perception_breaks` : fuite → `to_save`/`apply_save` → nouvelle instance `World` → verrou reconstitué, pas de réengagement immédiat ; rupture (mur) → verrou levé ; réacquisition → `FIGHTING`. - Suite GUT complète verte : **163 tests, 519 assertions**.
fix: empêcher le réengagement immédiat après rechargement d'une fuite (#42)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
ci/woodpecker/pull_request_closed/woodpecker Pipeline was successful
b945d4db40
Le verrou de désengagement de #26 (World._disengaged) ne vivait qu'en mémoire ;
une fuite autosauve aussitôt avec héros et hostile en perception mutuelle, donc
au rechargement l'appel différé à evaluate_perception relançait le combat.
entity_state_by_map (qui survit au save/load) ne contient que des fuyards :
World._ready reverrouille toute entité dont l'état est restauré, avant l'appel
différé. Le verrou tombe à la rupture de perception, le contact réengage
toujours, et une réacquisition réengage. Isolation des tests World renforcée
(nettoyage de entity_state_by_map).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reliodas merged commit 629231c219 into develop 2026-06-20 11:29:35 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: jeux/beaulieu-sur-brume#45
No description provided.