diff --git a/Architecture_Projet.md b/Architecture_Projet.md index c21649ca..e69abefa 100644 --- a/Architecture_Projet.md +++ b/Architecture_Projet.md @@ -425,21 +425,21 @@ Content/Systems/ │ └── BP_Projectile_Arrow.uasset → Hérite de BP_Projectile_Base. Override du mesh `ArrowMesh` (mesh Fab `cc0_wooden_arrow`, collision `BlockAllDynamic`) via override de composant hérité (PAS le template du parent — voir piège §9). Override `HandleImpact` : au lieu de se détruire, se fige (désactive la simulation + la collision) et s'attache (KeepWorld) au composant touché pour rester planté visuellement dans le décor/la cible. │ ├── Wildlife/ (2026-09-05) → Premiers animaux sauvages (cerf mâle + biche). Architecture générique : toute la logique commune vit dans `BP_AnimalBase` + un unique StateTree partagé ; une espèce (Content/Systems/Wildlife/BP_Deer_Stag, BP_Deer_Doe) ne fait qu'assigner mesh/anims/tunables — ajouter un sanglier ou un loup plus tard consiste à créer UN NOUVEAU Character enfant de `BP_AnimalBase`, sans toucher au StateTree ni aux tâches. Réutilise tel quel `AC_Stats` (vie/dégâts/mort) et `BP_ScentPoint` (odeurs) — voir §1.3. Nécessite le plugin **GameplayStateTree** (ajouté à `ProjectFv1.uproject` cette session, `StateTreeAIComponentSchema`/`StateTreeComponentSchema` indisponibles sans lui — seul le plugin `StateTree` de base était actif auparavant) ; premier usage de StateTree dans ce projet (aucune Behavior Tree/Blackboard/AIController n'existait avant). -│ ├── E_AnimalState.uasset → Enum (UserDefinedEnum, créé via `unreal.EnumStructService`) : Idle/Wander/Graze/Rest/Alert/Flee/Dead. Sert d'étiquette de debug + de sélecteur d'anim (voir `BP_AnimalBase::PlayStateAnimation`) ; le StateTree stocke en interne l'état courant sous forme de `byte` (les outils Blueprint disponibles ne permettent pas d'ajouter une variable membre ou un paramètre de fonction/dispatcher directement typé sur un enum utilisateur — limitation déjà documentée §9 pour AC_Stats, confirmée à nouveau ici). -│ ├── AC_AnimalSenses.uasset → ActorComponent générique (vue + odorat), ajouté à `BP_AnimalBase`. Vue : ne fait AUCUNE détection elle-même — se contente de variables (`bCanSeePlayer`, `DistanceToPlayer`, `LastKnownPlayerLocation`) mises à jour par `BP_AnimalAIController` via `ReportPlayerSighted`/`ReportPlayerLostSight`. Odorat : self-contained, `CheckScent` tourne sur un timer (`ScentCheckInterval`, 0.5s par défaut) démarré au `BeginPlay`, interroge `GetAllActorsOfClass(BP_ScentPoint)` et retient le plus proche (`bScentDetected`/`ScentSourceLocation` si distance ≤ `ScentDetectionRadius`, 800 par défaut). `DistanceToPlayer` est recalculée à CHAQUE tick de `CheckScent` (pas seulement quand le joueur est vu) — nécessaire pour que le StateTree puisse détecter le retour au calme (`DistanceToPlayer >= SafeDistance`) même après que l'animal ait fui hors de vue (bug rencontré et corrigé en test PIE, voir §9). -│ ├── BP_AnimalAIController.uasset → AIController, `AIPerceptionComponent` natif configuré en Python (`AISenseConfig_Sight`, rayon 2500/3000, FOV 90°). `OnTargetPerceptionUpdated` relaie vers `AC_AnimalSenses` du pion possédé (`ReportPlayerSighted`/`ReportPlayerLostSight` selon `Stimulus.WasSuccessfullySensed()`) — ne fonctionne QUE parce que le joueur porte un `AIPerceptionStimuliSourceComponent` (voir §1.3). -│ ├── BP_AnimalBase.uasset → Character générique, base de TOUTE la faune. Composants : `Stats` (AC_Stats), `AnimalSenses` (AC_AnimalSenses), `StateTree` (StateTreeComponent, schema `StateTreeComponentSchema`, contexte = l'acteur lui-même — PAS `StateTreeAIComponentSchema`, pour rester détaché de l'AIController et garder le StateTree simple). `AIControllerClass` = `BP_AnimalAIController`, `AutoPossessAI` = Placed in World or Spawned. Tunables instance-editable : WalkSpeed/RunSpeed, WanderRadius, IdleTime/GrazeTime/RestTime(Min/Max), AlertTime, FleeDistance (400-600 : distance de panique immédiate si vu de près), SafeDistance (doit être largement > FleeDistance : distance à atteindre pour se recalmer), HerdID (Name — animaux partageant le même HerdID se relaient une alerte), DebugEnabled, Anim_Idle/Wander/Graze/Rest/Alert/Flee/Dead/Hit (AnimSequence, un jeu à fournir par espèce). Fonctions clés : `MoveTo`/`StopMovementAnimal` (wrappers autour de l'AIController caché, utilisés par les tâches StateTree), `SetCurrentState` (met à jour l'enum de debug ET déclenche `PlayStateAnimation` — lecture d'anim en **Single Node** via `SkeletalMeshComponent::PlayAnimation`, PAS d'AnimBlueprint/State Machine : suffisant pour un premier jet crédible sans blending, cf. §9), `GetThreatLocation` (position du joueur si vu, sinon source d'odeur, sinon position de l'animal), `BroadcastAlertToHerd`/`ReceiveHerdAlert` (alerte les autres membres du même HerdID sans jamais lire une variable d'une AUTRE instance directement — le HerdID appelant est passé en paramètre de fonction, voir piège §9), `HandleDeath` (ragdoll `SetAllBodiesSimulatePhysics`, lié à `AC_Stats::OnDeath` via un Custom Event `OnAnimalDeathEvt` — PAS un binding direct sur une fonction classique, voir piège §9), `CheckHealthChanged` (polling toutes les 0.2s de `AC_Stats::GetHealth` : une baisse de vie hors mort → `bWasHitRecently=true` ; préféré à un binding direct sur le dispatcher `AC_Stats::OnDamaged`, qui provoque une erreur interne du compilateur Blueprint dans ce projet, voir piège §9). -│ ├── ST_AnimalBase.uasset → StateTree partagé par toute la faune (schema `StateTreeComponentSchema`, contexte = `BP_AnimalBase`). États : `Normal` (groupe) {Idle→Wander→Graze→Rest→Idle, cycle via transitions `OnStateCompleted`/`NextState`}, `Alert` (hésite `AlertTime` secondes puis retourne à Idle si la menace n'est pas confirmée — deny-timeout), `Flee` (fuite), `Dead` (terminal). Transitions clés, TOUTES en conditions liées par binding direct au contexte (`bind_transition_condition_property_to_context`, propriétés imbriquées type `AnimalSenses.bCanSeePlayer` — inclure le préfixe `b` des booléens, voir piège §9), aucune n'exige de Blueprint condition custom : `Normal→Alert` (vue OU odorat OU alerte de horde, combinées en OR via `set_transition_condition_operand`), `Normal→Flee` et `Alert→Flee` (priorité High : vu ET distance ≤ FleeDistance — "trop près, panique immédiate"), `Flee→Normal/Idle` (distance ≥ SafeDistance ET plus vu), transitions globales posées sur `Root` (s'appliquent depuis N'IMPORTE quel état actif) : `→Flee` (priorité High, `bWasHitRecently` ET pas mort — coup reçu non-létal) et `→Dead` (priorité Critical, `bIsDead`). +│ ├── E_AnimalState.uasset → Enum (UserDefinedEnum, créé via `unreal.EnumStructService`) : Idle/Wander/Graze/Rest/Alert/Flee/Dead. Sert d'étiquette de debug + de sélecteur d'anim d'arrêt (voir `BP_AnimalBase::ApplyIdleForState`) ; le StateTree stocke en interne l'état courant sous forme de `byte` (les outils Blueprint disponibles ne permettent pas d'ajouter une variable membre ou un paramètre de fonction/dispatcher directement typé sur un enum utilisateur — limitation déjà documentée §9 pour AC_Stats, confirmée à nouveau ici). +│ ├── AC_AnimalSenses.uasset → ActorComponent générique (vue + odorat), ajouté à `BP_AnimalBase`. Vue : ne fait AUCUNE détection elle-même — se contente de variables (`bCanSeePlayer`, `DistanceToPlayer`, `LastKnownPlayerLocation`) mises à jour par `BP_AnimalAIController` via `ReportPlayerSighted`/`ReportPlayerLostSight`. Odorat : self-contained, `CheckScent` tourne sur un timer (`ScentCheckInterval`, 0.5s par défaut) démarré au `BeginPlay`, interroge `GetAllActorsOfClass(BP_ScentPoint)` et retient le plus proche (`bScentDetected`/`ScentSourceLocation` si distance ≤ `ScentDetectionRadius`, 800 par défaut). `DistanceToPlayer` est recalculée à CHAQUE tick de `CheckScent` (pas seulement quand le joueur est vu) — nécessaire pour que le StateTree puisse détecter le retour au calme (`DistanceToPlayer >= SafeDistance`) même après que l'animal ait fui hors de vue (bug rencontré et corrigé en test PIE, voir §9). (2026-09-14) `CheckScent` réécrit : distance calculée par point d'odeur dans la boucle (l'ancienne version comparait une valeur hors boucle), pawn joueur relu à chaque passe via `GetPlayerPawn(0)` (le cache du `BeginPlay` devenait invalide après mort/respawn → fuite infinie), `LastKnownPlayerLocation` rafraîchie tant que le joueur est vu (la perception ne notifie qu'au gain/perte de vue), et `bCanSeePlayer=false` si aucun pawn. +│ ├── BP_AnimalAIController.uasset → AIController, `AIPerceptionComponent` natif configuré en Python (`AISenseConfig_Sight`, rayon 2500/3000, FOV 90°). `OnTargetPerceptionUpdated` relaie vers `AC_AnimalSenses` du pion possédé (`ReportPlayerSighted`/`ReportPlayerLostSight` selon `Stimulus.WasSuccessfullySensed()`) — ne fonctionne QUE parce que le joueur porte un `AIPerceptionStimuliSourceComponent` (voir §1.3). (2026-09-14) Filtre ajouté : l'événement ne relaie QUE si `Actor == GetPlayerPawn(0)` — sans lui, les autres animaux (pawns) perçus faisaient passer `bCanSeePlayer` à vrai/faux et déclenchaient alertes/fuites entre cerfs. (2026-09-14) Le template `AIPerception` avait perdu son `AISenseConfig_Sight` (`SensesConfig = [None]` → aucune détection) : recréé par Python (`unreal.new_object(AISenseConfig_Sight, outer=