feat: CombatController multi-acteurs et équipes (#54) #64

Merged
Reliodas merged 1 commit from feature/54-multi-actor-combat into develop 2026-06-22 06:33:43 +00:00
Owner

Closes #54.

Retire du cœur du combat l'hypothèse selon laquelle le seul tour contrôlable est celui de hero. Sixième pierre du jalon 0.16.0 (dépend de #49 et #53). Le contrôleur raisonne désormais en acteur actif et en équipes, ouvrant la voie à la résolution par équipe (#55), aux acteurs automatiques (#56) et à l'UI dynamique (#57). Le cas solo 0.15.0 reste strictement inchangé.

Changements

  • Acteur actif & contrôle : active_actor() expose le combattant courant ; une table de contrôle Creature -> PartyMember.ControlMode distingue les acteurs pilotés par le joueur (héros + alliés PLAYER) des automatiques (ennemis, alliés AUTO_ALLY/SCRIPTED_GUEST). is_controllable() en découle. Le mode de contrôle n'est jamais l'équipe.
  • Actions sur l'acteur actif : player_attack / player_move / player_dodge / player_second_wind, le ciblage (select_target, _resolve_attack_target, _attackable_targets), Second Wind et les cases atteignables portent sur active_actor(). L'économie d'action vient de manager.get_economy(actor) (plus de _hero_economy unique) : chaque tour a sa propre Action, Action bonus et distance, et une action n'affecte que l'acteur actif.
  • Boucle de tours : _resume() rend la main à tout acteur contrôlable et enchaîne les tours automatiques jusqu'au prochain (ennemis joués par l'IA ; alliés automatiques encore inertes jusqu'à #56). L'IA ennemie cible un membre vivant de l'équipe du héros (_enemy_target()), plus hero codé en dur.
  • Fin de combat par équipe : _finish() calcule la victoire via _team_has_living(HERO_TEAM) — le contrôleur ne dépend plus de la seule survie de hero pour la victoire, le ciblage ou le tour joueur. (La distinction fine victoire/défaite/survivants reste #55.)
  • Façades : les API hero_* (ex. hero_reachable_cells) restent en place et délèguent aux versions génériques.

Critères d'acceptation

  • deux personnages joueur distincts peuvent agir dans la même initiative ;
  • chaque tour possède sa propre Action, Action bonus et distance restante ;
  • une action ne peut pas être exécutée pour le mauvais acteur ;
  • les tours automatiques s'enchaînent jusqu'au prochain acteur contrôlable ;
  • le contrôleur ne dépend plus de hero pour déterminer victoire, ciblage ou tour joueur ;
  • les tests solo existants restent verts et de nouveaux tests couvrent deux alliés.

Tests

Suite GUT complète verte : 255 tests / 824 assertions (depuis 249 / 801).

  • tests/unit/test_combat_multi_actor.gd : deux PJ agissent dans la même initiative ; l'acteur actif est toujours contrôlable quand la main revient ; économie propre à chaque tour ; une attaque ne consomme que l'Action de l'acteur actif (pas celle de l'autre PJ) ; les tours automatiques s'enchaînent jusqu'au prochain contrôlable ; un allié AUTO_ALLY n'est jamais piloté ni joué comme ennemi ; victoire calculée par survie d'équipe.
  • Tous les tests de combat solo (test_combat_controller, test_world_combat_*) restent verts.

Note d'intégration

Les API génériques cohabitent avec les façades hero_* (transition progressive demandée par le ticket). Côté World/overlay, le pilotage d'un allié PLAYER fonctionne déjà (les actions visent l'acteur actif), mais l'affichage « à qui le tour » et les descripteurs d'action dynamiques relèvent de #57 ; le ressenti UI sera validé manuellement au #58.

Closes #54. Retire du cœur du combat l'hypothèse selon laquelle le seul tour contrôlable est celui de `hero`. Sixième pierre du jalon 0.16.0 (dépend de #49 et #53). Le contrôleur raisonne désormais en **acteur actif** et en **équipes**, ouvrant la voie à la résolution par équipe (#55), aux acteurs automatiques (#56) et à l'UI dynamique (#57). Le cas solo 0.15.0 reste strictement inchangé. ## Changements - **Acteur actif & contrôle** : `active_actor()` expose le combattant courant ; une **table de contrôle** `Creature -> PartyMember.ControlMode` distingue les acteurs pilotés par le joueur (héros + alliés `PLAYER`) des automatiques (ennemis, alliés `AUTO_ALLY`/`SCRIPTED_GUEST`). `is_controllable()` en découle. **Le mode de contrôle n'est jamais l'équipe.** - **Actions sur l'acteur actif** : `player_attack` / `player_move` / `player_dodge` / `player_second_wind`, le ciblage (`select_target`, `_resolve_attack_target`, `_attackable_targets`), Second Wind et les cases atteignables portent sur `active_actor()`. L'économie d'action vient de `manager.get_economy(actor)` (plus de `_hero_economy` unique) : **chaque tour a sa propre Action, Action bonus et distance**, et une action n'affecte que l'acteur actif. - **Boucle de tours** : `_resume()` rend la main à tout acteur contrôlable et **enchaîne les tours automatiques jusqu'au prochain** (ennemis joués par l'IA ; alliés automatiques encore inertes jusqu'à #56). L'IA ennemie cible un **membre vivant de l'équipe du héros** (`_enemy_target()`), plus `hero` codé en dur. - **Fin de combat par équipe** : `_finish()` calcule la victoire via `_team_has_living(HERO_TEAM)` — le contrôleur ne dépend plus de la seule survie de `hero` pour la victoire, le ciblage ou le tour joueur. (La distinction fine victoire/défaite/survivants reste #55.) - **Façades** : les API `hero_*` (ex. `hero_reachable_cells`) restent en place et délèguent aux versions génériques. ## Critères d'acceptation - [x] deux personnages joueur distincts peuvent agir dans la même initiative ; - [x] chaque tour possède sa propre Action, Action bonus et distance restante ; - [x] une action ne peut pas être exécutée pour le mauvais acteur ; - [x] les tours automatiques s'enchaînent jusqu'au prochain acteur contrôlable ; - [x] le contrôleur ne dépend plus de hero pour déterminer victoire, ciblage ou tour joueur ; - [x] les tests solo existants restent verts et de nouveaux tests couvrent deux alliés. ## Tests Suite GUT complète verte : **255 tests / 824 assertions** (depuis 249 / 801). - `tests/unit/test_combat_multi_actor.gd` : deux PJ agissent dans la même initiative ; l'acteur actif est toujours contrôlable quand la main revient ; économie propre à chaque tour ; une attaque ne consomme que l'Action de l'acteur actif (pas celle de l'autre PJ) ; les tours automatiques s'enchaînent jusqu'au prochain contrôlable ; un allié `AUTO_ALLY` n'est jamais piloté ni joué comme ennemi ; victoire calculée par survie d'équipe. - Tous les tests de combat solo (`test_combat_controller`, `test_world_combat_*`) restent verts. ### Note d'intégration Les API génériques cohabitent avec les façades `hero_*` (transition progressive demandée par le ticket). Côté `World`/overlay, le pilotage d'un **allié `PLAYER`** fonctionne déjà (les actions visent l'acteur actif), mais l'affichage « à qui le tour » et les descripteurs d'action dynamiques relèvent de #57 ; le ressenti UI sera validé manuellement au #58.
feat: généraliser CombatController au combattant actif et aux équipes (#54)
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
2fda837536
Retire du cœur du combat l'hypothèse que le seul tour contrôlable est celui
de hero :

- active_actor() expose le combattant courant ; une table de contrôle
  Creature -> ControlMode (héros + alliés PLAYER contrôlables, ennemis et
  alliés AUTO_ALLY/SCRIPTED_GUEST automatiques) pilote is_controllable() ;
  le mode n'est jamais l'équipe ;
- toutes les actions joueur, le ciblage, Second Wind et les cases
  atteignables portent sur l'acteur actif ; l'économie d'action vient de
  manager.get_economy(actor) — Action, Action bonus et distance propres à
  chaque tour, et une action n'affecte que l'acteur actif ;
- les tours automatiques s'enchaînent jusqu'au prochain acteur contrôlable ;
  l'IA ennemie cible un membre vivant de l'équipe du héros (plus hero codé
  en dur) ; la victoire est calculée par survie d'équipe.

Les API hero_* restent des façades ; cas solo 0.15.0 inchangé.

Tests : test_combat_multi_actor.gd (deux PJ dans la même initiative,
économie propre à chaque tour, action sur le bon acteur seulement, tours
auto jusqu'au prochain contrôlable, allié auto ignoré, victoire par équipe).
Suite 255 tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reliodas merged commit 613e43cd99 into develop 2026-06-22 06:33:43 +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#64
No description provided.