update 19/09/26

This commit is contained in:
Dodo committed 2026-09-19 17:31:31 +02:00
1 parent ef85534eea
commit b2fe07180b
216 files changed
+686 -28

No files matched your search

+58 -6
View File
@@ -85,6 +85,11 @@ Character (Pawn, géré par le framework "Sandbox Character")
│ PAS l'enum directement — UserDefinedEnum non utilisable comme type de variable membre via les outils,
│ voir §9) configurée par arme sur le composant (1=Bow sur `BP_Item_Bow`, 4=Riffle sur
│ `BP_Item_AdvancedRifle`), convertie via `Utilities|Enum|BytetoEnumWeapon_Equip` avant d'être assignée.
│ **Support du personnage Mover (2026-09-19)** : `Equip`/`Unequip` ne faisaient qu'un `Cast To
│ SandboxCharacter_CMC`. Sur `SandboxCharacter_Mover` (parent `Pawn`, aucune classe commune avec le CMC)
│ le cast échouait silencieusement → `Weapon`/`isArmed` jamais écrits, donc arme en main mais locomotion
│ toujours désarmée. Les deux fonctions ont désormais une branche `Cast Failed` → `Cast To
│ SandboxCharacter_Mover` → `SetEquippedWeapon(WeaponTypeByte)` (nouvelle fonction du pion Mover, voir §4.2.3).
│ **Bras armé qui reste bloqué en pose par défaut à l'équipement (2026-09-06, CORRIGÉ)** : deux causes
│ distinctes cumulées, toutes deux dans `SandboxCharacter_CMC_ABP` :
│ (1) `Get_MMInterruptMode` (utilisée par `Update_MotionMatching` pour choisir le `PoseSearchInterruptMode`
@@ -230,6 +235,7 @@ Quelques fichiers importants vivent directement sous `Content/`, hors de toute o
```text
Content/
├── Core/Character/SandboxCharacter_CMC.uasset → (déplacé depuis la racine le 2026-09-13) ⭐ Le Blueprint du PERSONNAGE JOUEUR lui-même (Character/Pawn). Référencé par GM_Dev, GM_Sandbox, PC_Sandbox, Gamemode_AGIS, WB_InventoryScreen, WBP_PauseMenu, BP_Moveble_Object, BP_Simply_Door, AC_PreCMCTick, AC_ClimbingComponent et son propre Anim BP (Systems/Blueprints/SandboxCharacter_CMC_ABP). C'est le point d'entrée central de tout le gameplay. Son EventGraph contient aussi : la détection de mort par chute (suivi tick de `IsFalling`/`FallStartZ`, calcul de hauteur à `OnLanded`, dégâts scalés via `AC_Stats.TakeDamage` au-delà de 300 unités, létal au-delà de 800) et une touche de debug K (InputDebugKey) qui force la mort via ce même `TakeDamage` — ajoutés le 2026-09-04.
├── Core/Character/SandboxCharacter_Mover.uasset + _Mover_Ragdoll.uasset → Personnage alternatif basé sur le plugin **Mover** (pion par défaut de `GM_Dev` ; en PIE c'est la variante `_Ragdoll` qui est possédée). Décrits avec le reste du framework Mover en §4.2.1, et leurs systèmes cover/prone/nage en §4.2.2.
├── Core/BP_GameInstance.uasset → (déplacé depuis la racine le 2026-09-13 ; `Config/DefaultEngine.ini` → `GameInstanceClass=/Game/Core/BP_GameInstance.BP_GameInstance_C`) GameInstance réellement utilisé par le projet (à ne pas confondre avec `Core/Coreinventory/GameInstance_AGIS`, la base du plugin — vérifier lequel des deux est configuré comme GameInstance par défaut avant de supposer que c'est l'un ou l'autre).
└── Data/DT_DemoTags.uasset → (déplacé depuis la racine le 2026-09-13 ; l'export texte `DT_DemoTags.T3D` a été supprimé) ⚠️ **À NE PAS SUPPRIMER** : DataTable de gameplay tags du socle AGIS, déclarée dans `Config/DefaultGameplayTags.ini` (`+GameplayTagTableList=/Game/Data/DT_DemoTags`). Elle définit `General Inventory Slot` (indispensable à l'inventaire), `Human.*`, `Attachment.*` (singulier), `Flashlight.Battery`, `Other.*`, `Vehicle.*`. (Corrigé le 2026-09-13 : l'ancienne mention « aucune référence trouvée » était fausse — la référence passe par la config, invisible pour l'Asset Registry.) Dette connue : `DT_Items`, `Inventory_Player` et `AttachmentData_AdvancedRifle` utilisent `Attachments.*` (pluriel, tags inexistants → avertissements « Invalid GameplayTag »), antérieur au commit du 2026-09-04.
```
@@ -390,9 +396,10 @@ Copie du framework "Sandbox Character" du sample Epic **Game Animation Sample**,
```text
Content/Systems/Mover/
├── SandboxCharacter_Mover.uasset → Personnage basé sur le plugin Mover. (Vérifié le 2026-09-15) `GM_Dev` (GameMode de `MapDev1`) a `DefaultPawnClass = SandboxCharacter_Mover` ; en PIE sur `MapDev1` le pion obtenu est `SandboxCharacter_Mover_Ragdoll`. `SetupInput` ajoute `Core/PlayerController/Input/IMC_Sandbox` (même IMC que le CMC, inputs AGIS/inventaire compris) ; il porte aussi `Inventory_Player`, dont la propriété `Input Mapping Context` DOIT valoir ce même `IMC_Sandbox` (corrigé le 2026-09-15, elle valait `IMC_AGIS_Character`) : à la fermeture de l'inventaire, `WB_InventoryScreen.SwitchInput` fait `ClearAllMappings` puis ne ré-ajoute QUE cette variable — une mauvaise valeur coupe tous les contrôles (ZQSD, caméra) après fermeture. Même piège pour tout futur pion équipé d'`Inventory_Player`. Implémente `BPI_Interactable` depuis le 2026-09-17 (`GetTracePoint` = position/forward du composant `Camera`, comme `SandboxCharacter_CMC`) : sans cette interface, le trace d'interaction d'`Inventory_Player` (`Client Trace`, `Verify Trace`) part de (0,0,0) avec une direction nulle et aucun objet ne peut être ramassé. Tout futur pion équipé d'`Inventory_Player` doit aussi implémenter `BPI_Interactable::GetTracePoint`
├── SandboxCharacter_Mover_Ragdoll.uasset → Variante ragdoll du personnage Mover
├── SandboxCharacter_Mover_ABP.uasset → Anim Blueprint du Mover (utilise `Systems/Aiming/ABP_AimingMaster`)
⚠️ (2026-09-18) `SandboxCharacter_Mover`, `_Ragdoll` (et l'ABP du CMC) vivent en réalité dans `Content/Core/Character/` — les deux lignes ci-dessous y correspondent, elles restent décrites ici pour garder le framework Mover d'un seul tenant.
├── SandboxCharacter_Mover.uasset → (dans `Content/Core/Character/`) Personnage basé sur le plugin Mover. (Vérifié le 2026-09-15) `GM_Dev` (GameMode de `MapDev1`) a `DefaultPawnClass = SandboxCharacter_Mover` ; en PIE sur `MapDev1` le pion obtenu est `SandboxCharacter_Mover_Ragdoll`. `SetupInput` ajoute `Core/PlayerController/Input/IMC_Sandbox` (même IMC que le CMC, inputs AGIS/inventaire compris) ; il porte aussi `Inventory_Player`, dont la propriété `Input Mapping Context` DOIT valoir ce même `IMC_Sandbox` (corrigé le 2026-09-15, elle valait `IMC_AGIS_Character`) : à la fermeture de l'inventaire, `WB_InventoryScreen.SwitchInput` fait `ClearAllMappings` puis ne ré-ajoute QUE cette variable — une mauvaise valeur coupe tous les contrôles (ZQSD, caméra) après fermeture. Même piège pour tout futur pion équipé d'`Inventory_Player`. Implémente `BPI_Interactable` depuis le 2026-09-17 (`GetTracePoint` = position/forward du composant `Camera`, comme `SandboxCharacter_CMC`) : sans cette interface, le trace d'interaction d'`Inventory_Player` (`Client Trace`, `Verify Trace`) part de (0,0,0) avec une direction nulle et aucun objet ne peut être ramassé. Tout futur pion équipé d'`Inventory_Player` doit aussi implémenter `BPI_Interactable::GetTracePoint`
├── SandboxCharacter_Mover_Ragdoll.uasset → Variante ragdoll du personnage Mover. ⚠️ C'est LUI le pion réellement possédé en PIE ; il surcharge le composant `CharacterMover` (ses propres `MovementModes`, dont `Ragdoll`) et `ProduceInput`/`On_MovementModeChanged_PostFinalize`. Toute modification du parent qui touche à ces éléments doit être vérifiée ici.
├── SandboxCharacter_Mover_ABP.uasset → Anim Blueprint du Mover (utilise `Systems/Aiming/ABP_AimingMaster`). (2026-09-18) Deux corrections majeures : (1) les nœuds `Evaluate Chooser` de `Update_MotionMatching` n'avaient AUCUN objet de contexte branché (au CMC il est relié à `self`) → le chooser ne pouvait résoudre aucune de ses colonnes, `ValidDatabases` restait vide et la branche Motion Matching de l'`AnimGraph` était morte ; `self` est désormais branché sur les deux nœuds. (2) Nouvelle variable `AnimBranchIndex` (affectée en fin d'`Update_Logic`) branchée sur l'`ActiveChildIndex` du *Blend Poses by int* de l'`AnimGraph`. Elle a d'abord piloté un hybride (Motion Matching en prone/nage, state machine GASP sinon) ; **depuis le 2026-09-18 elle vaut la constante `0`** : l'ABP du Mover est **100 % Motion Matching** (chooser `CHT_PoseSearchDatabases_Mover`), la state machine « State Controller » n'est plus jamais évaluée. Le nœud `Set AnimBranchIndex` et la variable sont conservés pour pouvoir rebasculer sur la voie 1 en changeant une seule valeur. Variables `Is Armed` et `IS Moving Object` ajoutées pour les colonnes du chooser copié.
├── GM_Sandbox.uasset / PC_Sandbox.uasset → GameMode (pawn = SandboxCharacter_Mover) et PlayerController du Mover ; création du widget de démo retirée le 2026-09-14
├── AC_TraversalLogic.uasset → Traversal du personnage Mover (vault/mantle/hurdle/climb). (2026-09-15) La détection de rebords du sample (limitée aux blocs de démo `LevelBlock_Traversable`, retirée le 2026-09-14) est remplacée par celle de `Systems/Blueprints/AC_TraversalLogic` (CMC), portée à l'identique : variables `Min Ledge Width`, `Min Front Ledge Depth`, `Max Ledge Sideways Depth`, `Trace Complex`, `Show Trace`, `Persistent Show Trace`, `RespectPlayersFacingDir`, `Banned Tags` (mêmes valeurs par défaut) et fonctions `ComputeLedgeData`, `TraceAlongHitPlane`, `TraceCorners`, `TraceWidth`, `NudgeTraceTowardsObjectOrigin`, `Set Trace Hit Point`, `Tag Compare`. Dans `TryTraversalAction` : capsule trace sur `TraceTypeQuery1` (Visibility, au lieu du canal `Traversable`), `Hit` → tags acteur+composant → `ComputeLedgeData` → rebords avant/arrière écrits dans `TraversalCheckResult` (équivalent inliné de `TryAndCalculateLedges`, non recopiée car elle prend le struct Systems par référence), puis `Tag Compare` (tags bannis) avant le chooser `CHT_TraversalMontages_Mover`. Le déclenchement (`IA_Jump` → `CanDoTraversal` → `TryTraversalAction`) et l'exécution Mover (`PerformTraversalAction_Mover`, mode `Traversing`) sont inchangés. Les deux composants restent des doublons divergents (structs/BPI `Systems/Mover/` vs `Systems/Blueprints/`).
├── AC_PreCMCTick, AC_PostABPTick, AC_VisualOverrideManager → Composants du sample (versions GASP, divergentes de celles de `Systems/Blueprints/`)
@@ -402,7 +409,7 @@ Content/Systems/Mover/
├── Cameras/ → `CameraAsset_SandboxCharacter`, `CameraDirector_SandboxCharacter`, `CHT_CameraRig`, `CameraShake_Basic`, `Rigs/CameraRig_*` (16)
├── ControlRigs/CR_Biped_FootPlacement.uasset
├── Data/ → Structs GASP (`S_CharacterPropertiesFor*`, `S_Traversal*`, `S_CHT_*` des choosers Mover/GetUp/Interaction, `S_Ragdoll*`, `S_MoverCustomInputs*`…), `Curve_RotationOffset_*`, `CHT_RotationOffsetCurve`, `BFL_HelpfulFunctions`, `BPI_InteractionTransform`
├── MovementModes/ → `BP_MovementMode_Walking/Falling/Slide/Ragdoll`, `B_MovementMode_Flying`, `BP_MovementTransition_To/FromSlide`
├── MovementModes/ → `BP_MovementMode_Walking/Falling/Slide/Ragdoll`, `B_MovementMode_Flying`, `BP_MovementTransition_To/FromSlide`, **`BP_MovementMode_Swimming`** (2026-09-18). `BP_MovementMode_Walking` : la `Select` d'allure n'alimentait QUE Walk/Run/Sprint — les allures ajoutées (Prone, Swinning, SwinningSprint) donnaient vitesse ET accélération = 0 (personnage figé) ; ajout de la variable `ProneSpeed` (125) et câblage des entrées manquantes (prone → `ProneSpeed`/`WalkAcceleration`, nage → Walk/Run). `BP_MovementMode_Swimming` : enfant de `SimpleFlyingMode` (comme le mode vol), tag `Mover.IsSwimming`, `MaxSpeedOverride = 1` (l'entrée devient un pur vecteur d'intention) ; sa fonction `ComputeSwimTarget` lit le personnage propriétaire (cast `SandboxCharacter_Mover`) et produit la vitesse cible : en surface, Z = flottaison vers `WaterSurfaceZ - SurfaceOffset` (60) bornée par `MaxBobSpeed`, en plongée Z = intention caméra + `SwimVerticalInput` × `VerticalSpeed`, horizontal = intention × `SwimSpeed` (250) ou `SwimSprintSpeed` (450). ⚠️ Le `SwimmingMode` natif du plugin Mover (UE 5.8) n'est PAS utilisable : son `SimulationTick` est vide et rien n'alimente ses données d'eau (`CommonBlackboard::LastWaterResult`).
└── SmartObjects/ → `AC_SmartObjectAnimation` (version GASP, aussi utilisée par des STT de `Systems/Blueprints/`), `CHPA_SmartObject`, `PSS_SmartObject`, `Bench/`, `TasksAndConditions/STT_*`
Content/Systems/Aiming/ → Système de visée développé dans Project_F : `ABP_AimingMaster`, `ABP_AimingMaster_UEFN` (aim offset), choosers `CH_AO`, `CH_Base_AO_Animechooser` (enum `Data/Enums/E_WaponType`)
@@ -410,6 +417,45 @@ Content/Systems/Aiming/ → Système de visée développé da
Content/Blueprints/AnimNotifies/ → SEUL reste de `Content/Blueprints/` : 23 notifies du sample (`BP_AnimNotify_FoleyEvent*`, `BP_NotifyState_EarlyTransition`, `_MontageBlendOut`, `_MMI_*`, `BP_AnimNotify_TriggerRagdoll`, `_OverrideMovementMode`…) liés à 1278 animations de `Characters/UEFN_Mannequin`. Laissés en place volontairement : les déplacer réenregistrerait 1,78 Go d'animations. Pour la plupart doublons de `Systems/Blueprints/AnimNotifies/`.
```
#### 4.2.2 Cover / prone / nage portés du CMC vers le personnage Mover (2026-09-18)
Ces trois fonctionnalités n'existaient que sur `SandboxCharacter_CMC` (via le `CharacterMovementComponent`). Elles ont été reportées sur `Core/Character/SandboxCharacter_Mover`, en passant par les mécanismes du plugin Mover et non par des écritures directes sur la capsule.
- **Composants ajoutés au Mover** : `Systems/Movement/Cover/AC_Cover` (le composant du CMC, générique : il travaille via `GetOwner`) et `Arrow1` (ArrowComponent, `(0,0,90)` / yaw 90). ⚠️ `Arrow1` DOIT être attaché au **SkeletalMesh** (comme au CMC) et non à la capsule : le mesh porte un yaw −90, donc l'arrow attaché au mesh se retrouve aligné sur l'acteur (avant = avant de l'acteur, droite = droite de l'acteur), ce qu'attend le sphere trace de `MoveAlongWall` (il part de 55 uu sur le côté puis trace 60 uu vers l'avant, dans le mur). Attaché à la capsule, ses axes sont tournés de 90° : le trace part dans le vide, `MoveAlongWall` ne produit aucun `AddMovementInput` et on ne peut pas se déplacer en couverture (bug corrigé le 2026-09-18).
- **Variables ajoutées au Mover** — catégorie `Cover` : `In Cover`, `Cover` (`E_CoverD`), `Edge L`, `Edge R` ; catégorie `Prone` : `IsProne`, `ProneHalfHeight` (40), `CrouchHalfHeight` (55) ; catégorie `Swimming` : `CurrentWaterBodyComp`, `IsSwimming`, `IsUnderwater`, `SwimSprint`, `WaterSurfaceZ`, `WaterDepth`, `SwimVerticalInput`, `SwimStartDepth` (95), `SwimStopDepth` (80), `SwimmingModeClass`.
- **Prone** : `IA_Prone` → `ToggleProne` (bascule `IsProne` + `WantsToCrouch`/`WantsToStrafe` dans `PlayerInputState`), refusé en nage ou en cover. La hauteur de capsule N'est PAS écrite directement (contrairement au CMC qui fait `SetCapsuleSize`) : `Apply_CrouchOrProne`, appelée depuis `On_PreSimulateTick`, règle `StanceSettings.CrouchHalfHeight` (40 en prone, 55 accroupi) et force un cycle `UnCrouch`→`Crouch` quand la capsule courante ne correspond pas — c'est le `FStanceModifier` du plugin qui redimensionne la capsule, replace l'acteur et décale le mesh. `IA_Crouch` en prone appelle `ExitProneToCrouch` (retour accroupi).
- **Nage** : les overlaps de la capsule (`OnComponentBegin/EndOverlap` → cast `WaterBody`) renseignent `CurrentWaterBodyComp` ; `Update_Swimming` (appelée depuis `On_PreSimulateTick`, voir l'encadré « tick » plus bas) lit `GetWaterSurfaceInfoAtLocation` (surface + profondeur), met à jour `SwimSprint` (depuis `PlayerInputState.WantsToSprint`) et `SwimVerticalInput` (valeurs brutes de `IA_Jump` − `IA_Crouch`), puis `StartSwimming` (profondeur ≥ `SwimStartDepth` → `QueueNextMovementMode("Swimming")`) / `StopSwimming` (< `SwimStopDepth` → `Falling`). `IA_SwimmingDeep` bascule `IsUnderwater` (plongée). Le mode « Swimming » est enregistré **au BeginPlay** par `AddMovementModeFromClass` (variable `SwimmingModeClass`) et non dans la map `MovementModes` du composant : une instance créée par script dans le template du parent est privée et empêchait la sauvegarde de `SandboxCharacter_Mover_Ragdoll` (« Illegal reference to private object »).
- **Cover** : l'événement `OnEntreredCover` d'`AC_Cover` recopie `InCover`/`cover`/`EdgeL`/`EdgeR` sur le personnage puis `ApplyCoverCrouch` (accroupi **et `WantsToStrafe` = en couverture** tant qu'on y est) ; `IA_Move` appelle `AC_Cover.MoveAlongWall` quand `In Cover`. Comme le Mover ignore `AddMovementInput`, `Get_MoveInput` renvoie, en cover, `ConsumeMovementInputVector` (le vecteur accumulé par le composant). `Update_Cover` (`On_PreSimulateTick`) met `CharacterMover.bAcceptExternalMovement` à la valeur d'`AC_Cover.InCover`, sinon le `MoveComponentTo` de collage au mur serait annulé par la simulation Mover. ⚠️ Le mode **strafe est indispensable** en couverture : sans lui le Mover réoriente le personnage dans la direction du glissement dès le premier pas, l'`Arrow1` tourne avec, le trace de `MoveAlongWall` rate le mur et le déplacement se bloque après quelques centimètres (bug corrigé le 2026-09-18). L'entrée en couverture reste sur la touche **P** : depuis le 2026-09-18 le corps de cet `InputKey` est déporté dans l'événement `ToggleCover` d'`AC_Cover` (la touche P l'appelle), ce qui permet de déclencher la couverture par script/test ou de la remapper plus tard sur une Input Action.
- **Alimentation de l'animation** : `Get_PropertiesForAnimation` renvoie désormais `Stance` = Swinning / SwinningDeep / Prone / Crouch / Stand, et `Get_Gait` renvoie Prone en prone, Swinning/SwinningSprint en nage. `Get_MoveInput` utilise la rotation caméra complète (input 3D) en plongée comme en vol. Le chooser `Characters/UEFN_Mannequin/Animations/MotionMatchingData/CHT_PoseSearchDatabases_Mover` est une copie du `_Dense` du CMC dont le `ContextData` pointe sur `SandboxCharacter_Mover_ABP` ; ses deux colonnes booléennes (`Is Armed`, `IS Moving Object`) sont désactivées et la ligne « push » restreinte à `Stance = Stand`.
- **Les deux moteurs d'animation de l'ABP (Motion Matching vs state machine)** : l'`AnimGraph` (CMC comme Mover) contient un `Blend Poses by int` dont l'entrée **0 est le nœud Motion Matching** et l'entrée **1 la state machine « State Controller » + Blend Stack** (la voie « expérimentale » du sample GASP). Voie 0 : `Update_MotionMatching` (fonction de nœud) évalue un chooser qui renvoie une LISTE de `PoseSearchDatabase`, `SetDatabasesToSearch` les donne au nœud, qui recherche chaque frame la meilleure pose d'après la trajectoire (`Update_Trajectory`) — variables `ValidDatabases`, `CurrentSelectedDatabase/Anim`, `MM Search Cost`, réglages `Get_MMBlendTime`/`Get_MMInterruptMode`. Voie 1 : à chaque entrée d'état, `SetBlendStackAnimFromChooser` évalue `CHT_MoverCharacterAnimations_PoseMatch` (chooser **par clip**, une ligne = une animation) qui renvoie UNE anim + ses réglages de blend, poussée dans le `Blend Stack` — variables `StateName`, `BlendStackInputs`, `Search Cost`, `NoValidAnim`. Dans les deux ABP l'index valait la constante `0` (Motion Matching en permanence) ; sur le Mover il passe par la variable `AnimBranchIndex`, qui vaut elle aussi `0` en permanence depuis le 2026-09-18 (l'hybride state machine / Motion Matching a été abandonné à la demande de l'utilisateur, voir §4.2.1). Les CVars GASP `DDCvar.UseExperimentalStateMachine` / `DDCvar.ExperimentalStateMachine` n'existent pas dans ce projet (avertissement « Failed to find console variable » en PIE) : elles ne commandent rien.
- **Correction de `MovementModeMap`** : « Ragdoll » pointait sur *Climbing* et « Flying » sur *SwimmingOnSurface* (décalage laissé par la fusion des enums GASP → projet, §8.2). Remis sur `Ragdoll`/`Flying` + ajout de `Swimming` → `SwimmingOnSurface`. Effet de bord bénéfique : le ragdoll du pion refonctionne (son Tick et `EnteredRagdollSuccessfullyCheck` comparent le mode courant à `Ragdoll`).
- **⚠️ Tick du personnage Mover (corrigé le 2026-09-18)** : `SandboxCharacter_Mover` et `_Ragdoll` avaient `PrimaryActorTick.TickInterval = 30 s` (le CMC est à 0). Tout leur `Event Tick` — `CacheInputsFromMover`, `Update_FloorValues`, `Update_ControlRotationRate`, `Update_SlidingAudio`, `Update_TargetedActor`, `Update_TwinStickMode`, `Update_SmoothedAnalogInputAmount`, `DebugDraws` — ne tournait donc qu'une fois toutes les 30 secondes (c'est ce qui empêchait la nage de se déclencher : `Update_Swimming` y était branchée). Intervalle remis à **0** sur les deux pions, et par sécurité `Update_Swimming` + `Update_Cover` ont été déplacées du `Event Tick` vers `On_PreSimulateTick` (délégué du `CharacterMover`, exécuté à chaque pas de simulation). Si un jour le tick de ces pions est de nouveau throttlé (politique `BP_TickManager`), la nage et la couverture continueront de fonctionner, mais les `Update_*` du framework GASP, eux, en souffriront.
- **⚠️ Bases Pose Search de nage vides → T-pose (contourné le 2026-09-18)** : sur les 6 bases de nage, **une seule est réellement remplie**, `Animations/humain/SwimmingAnimation/Swimming_animation/Breastok/surface/PSD_SwimmingMoving` (5 clips de brasse en surface). `PSD_SwimmingIdle`, `PSD_SwimmingMovingSprint`, `PSD_SwimmingDeepIdle`, `PSD_SwimmingDeepMoving`, `PSD_SwimmingDeepMovingSprint` ont des lignes dont l'`AnimAsset` est **None** (log : `OnGetComplete - Database None entry N has no associated animation asset`), et la table imbriquée `SwimmingInDeepIdle` du chooser n'a **aucun résultat**. L'ABP étant désormais 100 % Motion Matching, une base vide = aucune pose = **T-pose**, exactement le bug remonté. Contournement appliqué dans `CHT_PoseSearchDatabases_Mover` : les lignes qui pointent sur une base vide (12, 14, 15, 17) sont rendues inatteignables (`Stance = Prone` alors que `Movement Mode = Swimming`, combinaison impossible par construction) et les deux lignes qui pointent sur `PSD_SwimmingMoving` (13 pour Swinning, 16 pour SwinningDeep) passent `Movement State` et `Gait` en **MatchAny** pour couvrir tous les cas de nage. Vérifié en PIE : nage de surface immobile, nage de surface en mouvement et nage profonde sélectionnent bien `RM_Breastroke_overwater_01_*`.
- **Vraie correction à faire à la main** (impossible par script : la propriété `DatabaseAnimationAssets` d'un `PoseSearchDatabase` et le `ResultsStructs` d'un `ChooserTable` ne sont exposés ni au Python d'UE ni à `ObjectTools.set_properties` — seules `columnsStructs`/`contextData` le sont) : ouvrir chaque base vide et y glisser les clips qui existent déjà sous `Animations/humain/SwimmingAnimation/` — `IDLE/IP_idle_underwater_01_Retargeted` + `IDLE/RM_Idle_turn_*` pour `PSD_SwimmingIdle`, `Swimming_animation/Crawl/RM_Crawl_*` pour `PSD_SwimmingMovingSprint`, `Swimming_animation/Breastok/RM_Breastroke_underwater_*` pour `PSD_SwimmingDeepIdle/Moving/MovingSprint` — puis remettre les lignes 12/14/15/17 du chooser sur leur `Stance` d'origine (3, 3, 4, 4) et donner un résultat à la table imbriquée `SwimmingInDeepIdle`.
- **Restes connus** : le cover du Mover joue les anims accroupies GASP, pas les bases de couverture du CMC (`PSD_Dense_Crouch_Idles_CoverLeft/Right`) ni le nœud `Mirror` de l'AnimGraph du CMC ; en couverture le personnage conserve un écart d'orientation d'une dizaine de degrés par rapport au mur (orientation strafe qui converge lentement).
#### 4.2.3 Système d'armes porté sur le personnage Mover (2026-09-19)
Ce qui marchait déjà sur le Mover avant cette session (vérifié en PIE) : le ramassage (`IA_InteractAGIS`), le rangement au dos (socket `SpineRifle`), le passage en main par la roue V/B (`IA_QuickSelectAGIS` / `IA_QuickEquipAGIS` → socket `Rifle`), l'appel de `AC_Weapon::Equip`/`Unequip` via `HandleHeldStateChanged`, et le tir (`IA_UseItemPrimaryAGIS` → `Inventory_Player::UseHeldPrimarySERVER` → `BP_Item_AdvancedRifle::EventPrimaryUse`). `Inventory_Equipper` est générique : son `OwnerMesh` se résout bien sur le composant `SkeletalMesh` du Mover.
Ce qui ne marchait PAS et a été corrigé :
- **`AC_Weapon` ne parlait qu'au CMC** : `Equip`/`Unequip` faisaient un `Cast To SandboxCharacter_CMC`, qui échoue sur le Mover (`Pawn` vs `Character`, aucune classe commune). Résultat : arme bien en main, mais `Weapon` et `isArmed` jamais écrits → locomotion désarmée en permanence. Une branche `Cast Failed` → `Cast To SandboxCharacter_Mover` a été ajoutée dans les deux fonctions ; le CMC est inchangé.
- **Nouvelle fonction `SandboxCharacter_Mover::SetEquippedWeapon(WeaponTypeByte)`** (appelée par `AC_Weapon`, `0` = déséquipement) : écrit `Weapon_Equip` (nouvelle variable, enum `Weapon_Equip`), `isArmed` (= byte ≠ 0), `WantToshot` (remis à false au déséquipement) et `Weapon`. ⚠️ **Trois enums d'arme coexistent dans le projet** : `Weapon_Equip` (None/Bow/OneArmPistol/TwoArmPistol/Riffle/Bat — c'est l'espace de `AC_Weapon::WeaponTypeByte` et des colonnes du chooser de locomotion), `E_WaponType` (None/Riffle/Pistoll/Bow — c'est le type de `SandboxCharacter_Mover::Weapon` et du champ `S_CharacterPropertiesForAnimation.Weapon_Type`, lu par les choosers d'aim offset de `Systems/Aiming/`) et `E_WeaponType` (inutilisé ici). `SetEquippedWeapon` fait donc la conversion 1(Bow)→3, 2/3(Pistol)→2, 4(Riffle)→1, reste→0.
- **IA_Aim renseigne `WantToshot`** (nouvelle variable du pion) : `WantToshot = ActionValue AND isArmed` sur `Triggered`, remis à `false` sur `Completed`. C'est ce bool que lit la colonne « Want Toshot » du sous-chooser `Stand Idles Bow` pour passer de l'idle arc à l'idle arc en visée.
- **`SandboxCharacter_Mover_ABP` reçoit l'état d'arme** : nouvelles variables `Weapon_Equip`, `Weapon_Equip Last Frame`, `Want Toshot` (+ `Is Armed` et `IS Moving Object` déjà présentes), toutes alimentées en fin de `Update_PropertiesFromCharacter` (**thread principal**, comme le CMC le fait dans son `EventBlueprintUpdateAnimation` — surtout pas dans `Update_Logic`, qui peut tourner en thread-safe update).
- **`Is Armed` de l'ABP = `isArmed` ET `Weapon_Equip == Bow`** — *stopgap assumé* : l'arc est la SEULE arme qui possède des bases Motion Matching armées (`PSD_Dense_Stand_Bow_Idles`, `_Bow_Aim_Idles`, `PSD_Walk_Bow`). Sans cette condition, un fusil mettait `Is Armed = true`, les lignes 0/2 du chooser (`MatchFalse`) étaient rejetées, les lignes arc 1/3 échouaient sur leur colonne `Weapon_Equip`, et on retombait sur la ligne 18 « Push » (ou sur rien du tout). Avec la condition, fusil/pistolet jouent proprement la locomotion désarmée, arme en main. À retirer le jour où des bases fusil existeront.
- **`Update_MotionMatching`** : le chooser `CHT_PoseSearchDatabases_Mover` n'était consulté que si `Stance` ∉ {Stand, Crouch} (prone/nage). La condition devient `(Stance ≠ Stand ET ≠ Crouch) OU Is Armed`, sinon les lignes arc — qui sont des lignes *debout* — n'étaient jamais atteintes. La sortie `False` du Branch est en plus reliée à `SetDatabasesToSearch` pour que les deux chemins poussent bien leur liste dans le nœud MM.
- **`Get_MMInterruptMode`** : ajout du terme `Weapon_Equip ≠ Weapon_Equip Last Frame` sur le `OR` racine. Sans lui, changer d'arme ne forcçait aucune interruption : Motion Matching gardait la pose continue (anim désarmée) et ne basculait jamais sur la base arc, même une fois celle-ci dans la liste (coût de continuité toujours plus bas). C'est le même piège que celui décrit en §1.3 pour le CMC.
- **`CHT_PoseSearchDatabases_Mover`** : colonne `Is Armed` **réactivée** (elle avait été désactivée le 2026-09-18 faute de propriété correspondante sur l'ABP Mover), colonne `IS Moving Object` réactivée aussi (sinon la ligne 18 « Push » devient un attrape-tout qui remporte tous les cas debout non couverts), et **ligne 1 (« Stand Idles Bow ») : colonne `Gait` passée de `MatchEqual Walk` à `MatchAny`**. C'était le dernier blocage : l'allure par défaut du personnage est `Run`, donc la ligne arc ne pouvait jamais matcher à l'arrêt. (Le même défaut existe dans `CHT_PoseSearchDatabases_Dense` côté CMC, non corrigé ici.)
Vérifié en PIE, dans cet ordre : ramassage du fusil → dos ; V+B → main + `Weapon = Riffle`, `Weapon_Equip = Riffle`, `isArmed = true` côté pion ET côté ABP ; locomotion désarmée propre avec le fusil en main (pas de T-pose) ; arc → `PSD_Dense_Stand_Bow_Idles` → `StandingIdle01_UE_Anim3` ; arc + clic droit → `Want Toshot = true` → `PSD_Dense_Stand_Bow_Aim_Idles` ; arc en course → repli propre sur `PSD_Dense_Stand_Run_Loops` ; clic gauche → `EventPrimaryUse` du fusil (qui refuse de tirer faute de chargeur équipé — comportement normal, non lié au Mover) ; non-régression prone (`PSD_Dense_Prone_Idles`) et nage (`PSD_SwimmingMoving`).
Restant à faire :
- Aucune base Motion Matching armée pour le fusil / le pistolet (seul l'arc en a) ; `PSD_Crouch_Bow` existe mais n'est référencée par aucune ligne de chooser.
- `SandboxCharacter_Mover` n'a **pas** de composant `AC_Stats` (le CMC en a un) : `BFL_WeaponDamage::ApplyPointDamage` résout `AC_Stats` sur la cible, donc le pion Mover ne peut pas encaisser de dégâts. Il lui manque aussi les capsules de hitbox et le `PerceptionStimuliSource` du CMC.
- La visée n'a pas d'équivalent de `SandboxCharacter_CMC::ISaiming` sur le Mover (seuls `PlayerInputState.WantsToAim` et `WantToshot` existent).
### 4.3 Autres systèmes de gameplay (ajouts spécifiques au projet)
```text
@@ -451,7 +497,7 @@ Content/Systems/
│
├── Movement/
│ ├── Climbing/AC_ClimbingComponent.uasset, CR_ClimbingGraphV2.uasset (Control Rig), CR_Mannequin_BasicFootIK.uasset, ClimbingMaterial.uasset
│ └── Cover/AC_Cover.uasset → ActorComponent : système de couverture (cover system)
│ └── Cover/AC_Cover.uasset → ActorComponent : système de couverture (cover system). Générique (tout passe par `GetOwner`) : porté par `SandboxCharacter_CMC` ET, depuis le 2026-09-18, par `SandboxCharacter_Mover` (voir §4.2.2). Entrée/sortie de couverture sur la touche **P** gérée dans le composant lui-même ; `MoveAlongWall` fait un sphere trace le long du mur, `AddMovementInput` sur le pion et diffuse `OnEntreredCover` (InCover, direction `E_CoverD`, EdgeL/EdgeR).
│
├── Scent/BP_ScentPoint.uasset → Point émetteur d'odeur, spawné par `SandboxCharacter_CMC::ScentFunct` (toutes les 2s pendant que le joueur se déplace) et consommé par `AC_AnimalSenses::CheckScent` (Systems/Wildlife/, §4.4). (2026-09-05) Deux bugs corrigés à la réutilisation par la faune : (a) `ScentFunct` ne créait le point QUE via `SpawnActorFromClass`, sans jamais appeler son événement `Custom|Create(life)` — la durée de vie (`TimeToLife`) restait donc à 0 ; ajout d'un appel explicite `Create(life=20.0)` juste après le spawn. (b) Le décompte de durée de vie (`Custom|CustomEvent(DeltaTime)`) existait déjà mais n'était appelé par PERSONNE (`BeginPlay` enregistrait l'acteur auprès de `BP_TickManager` mais rien n'invoquait réellement l'event) — le point ne s'auto-détruisait donc jamais ; ajout d'un `EventTick` natif qui appelle directement ce Custom Event (évite de toucher au brancher `BP_TickManager` partagé, hors-scope). Comparaison de fin de vie durcie de `== 0` à `<= 0` (float exact-equality fragile). Aucune nouvelle logique d'odeur créée — uniquement réparation du mécanisme existant.
├── Movable_Object/BP_Moveble_Object.uasset → Objet physique déplaçable par le joueur
@@ -699,6 +745,10 @@ Contenu du framework du sample conservé volontairement (déplacé le 2026-09-14
Ce projet est modifié via le plugin **VibeUE** (service MCP `unreal-mcp`, voir `.mcp.json`), qui expose des services Python (`unreal.BlueprintService`, `unreal.WidgetService`, `unreal.InputService`, `unreal.EnumStructService`, etc.) pour piloter l'éditeur Unreal sans l'ouvrir manuellement. Quelques pièges rencontrés et leurs solutions :
- **PIÈGE — un nœud `Evaluate Chooser` sans objet de contexte branché renvoie TOUJOURS une liste vide (2026-09-18)** : constaté sur `SandboxCharacter_Mover_ABP::Update_MotionMatching`, dont les deux nœuds avaient leur pin de contexte (`SandboxCharacter_Mover_ABP_C`) laissé vide — aucune colonne du chooser ne pouvait être résolue, `ValidDatabases` restait vide en permanence et toute la branche Motion Matching de l'`AnimGraph` était inerte (`MM Search Cost` = FLT_MAX, `CurrentSelectedAnim` = None) sans qu'aucune erreur ne soit loguée. Toujours brancher `self` (type id créable : `Variables|Getareferencetoself`). Symptôme jumeau à surveiller : un chooser dupliqué dont on a changé le `ContextData` fonctionne, les liaisons se résolvant par NOM de variable sur la nouvelle classe de contexte.
- **PIÈGE — créer par script un sous-objet instancié dans un template de composant casse la sauvegarde des Blueprints ENFANTS (2026-09-17)** : `unreal.new_object(cls, outer=<template du composant>)` (ici un mode de mouvement ajouté à `CharacterMover.MovementModes`) produit un objet **privé** ; l'enfant (`SandboxCharacter_Mover_Ragdoll`, qui surcharge le composant via son `InheritableComponentHandler`) le prend comme archétype et sa sauvegarde échoue avec `Illegal reference to private object`. Préférer un enregistrement à l'exécution (`MoverComponent::AddMovementModeFromClass` au BeginPlay) ou l'édition manuelle dans l'éditeur.
- **PIÈGE — `SubobjectDataSubsystem.rename_subobject` juste après `BlueprintService.remove_component` provoque une assertion fatale (2026-09-17)** : `Renaming an object (…Arrow_GEN_VARIABLE) on top of an existing object (…Arrow1_GEN_VARIABLE) is not allowed` — l'ancien template n'est pas encore collecté. L'interpréteur Python est ensuite corrompu (`0xC0000005` au premier accès au Blueprint) et **le MCP sauvegarde les packages modifiés à chaque appel**, donc l'état intermédiaire peut se retrouver sur disque : redémarrer l'éditeur et vérifier le Blueprint (composants, liaisons) après ce type d'erreur. Corollaire : un composant ajouté par `BlueprintService.add_component(..., parent_name="Capsule")` reçoit un `ParentComponentOrVariableName` explicite qui déclenche l'avertissement `Reparenting the 'X' component … possible cyclic linkage` à chaque compilation ; l'ajouter sans parent (comme les autres composants racine du SCS) évite l'avertissement.
- **Lire l'état de jeu en PIE depuis Python est décalé d'une frame ou deux** (surtout pour les variables d'Anim Blueprint écrites dans l'update thread-safe) : une même valeur peut sembler « fausse » (allure restée à Run, `ValidDatabases` vide) puis correcte à l'appel suivant. Toujours relire dans un second appel avant de conclure à un bug. De plus, `BlueprintService.list_graphs`/`list_variables` renvoient **0 élément pendant une session PIE** : arrêter le PIE avant d'inspecter un graphe.
- **`build_graph`** attend un champ **`"ref"`** pour identifier chaque nœud dans la liste `nodes` (pas `"id"`). Un mauvais nom de champ échoue silencieusement (retourne `None` sans erreur explicite).
- Les **variables locales à une fonction** (paramètres, locals créés via `add_object_variable` avec `graph=...`) ne sont pas fiables avec `build_graph`'s `variable_get`/`variable_set` : préférer des **variables membres** du Blueprint.
- Un `K2Node_VariableSet`/`Get` créé via un spawner_key générique (`discover_nodes` + `create_node_by_key`) peut se résoudre sur la **mauvaise classe** si plusieurs Blueprints chargés ont une variable de même nom affiché (ex. "Owner Inventory" existe à la fois sur `WB_Container` et sur un widget créé cette session) — toujours vérifier les pins du nœud créé (`get_node_pins`) avant de câbler, ou utiliser `build_graph` avec `type: "variable_set"` + `params.variable` en contexte "self" qui est fiable.
@@ -795,4 +845,6 @@ Ce document **doit toujours refléter l'état réel du projet**. Un skill dédi
- *2026-09-14 (météo) : corrections du système météo projet (`WB_WeatherControl`/`WB_WeatherZone`, voir §4 Weather). Bugs corrigés : `setWeatherbetweenZone` lisait deux fois Zone2 ; `GetNearZone` ne trouvait jamais de zone (distances locales à 0, poids 0/0 et inversés) ; `SetNuage`/`MakeTemp` retournaient 0 sans zone voisine (return dans la boucle) et clampaient la température à 0–10 ; `makestate` renvoyait un état vide (branche froide nuages ≥ 8) et ne calculait ni vent/brouillard/poussière ni humidité ; `MakeForcast` avait des pas de 0–1 s ; `UpdateWeatherstate` n'avançait jamais le temps (+0) ; rayon d'influence ≈ 900 uu et tri `Trie zone` pouvant boucler à l'infini ; overlaps déclenchés par n'importe quel acteur ; saison en secondes. Nouveaux : fonctions `StepForecast`, `ApplyToUDW`, `GetZoneState` ; variables `ForecastStepMin/Max`, `InfluenceRadius`, `LastUpdateTime` (zone), `SeasonDurationScale` (contrôleur). `[CoreRedirects]` UDS + 10 systèmes Niagara re-sauvegardés. PIE OK (zones prêtes, 16 prévisions, poids 0.52/0.48, UDW alimenté, aucune erreur météo). Restant : `WeatherData` des 2 zones de MapDev1 vide (0 °C / 0 %), `BP_TickManager` transmet un `DeltaTime` ~10× trop petit au contrôleur (saison lente), avertissement d'attache des ChildActor UDS/UDW (mobilité). Sauvegarde des assets avant modification : `E:\projet\ProjectFv1_backup_migration_2026-09-13\weather_before_fixes_2026-09-14\`.*
*`Content/Data/DT_DemoTags.uasset` (anciennement à la racine) : longtemps considéré comme un reste de test sans référence — FAUX (vérifié le 2026-09-13) : c'est la table de tags AGIS déclarée dans `Config/DefaultGameplayTags.ini`, à conserver (voir §2.1).*
- *2026-09-18 (migration cover / prone / nage du CMC vers le Mover, voir §4.2.2) : `SandboxCharacter_Mover` reçoit `AC_Cover` + `Arrow1`, les variables et fonctions de cover/prone/nage, l'enregistrement du mode « Swimming » au BeginPlay, et ses fonctions `Get_Gait`/`Get_MoveInput`/`Get_PropertiesForAnimation`/`On_PreSimulateTick` étendues. Nouveaux assets : `Systems/Mover/MovementModes/BP_MovementMode_Swimming`, `Characters/UEFN_Mannequin/Animations/MotionMatchingData/CHT_PoseSearchDatabases_Mover`. Corrections annexes : `BP_MovementMode_Walking` (vitesse/accélération nulles pour les allures prone et nage), `MovementModeMap` (Ragdoll→Climbing et Flying→SwimmingOnSurface, séquelles de la fusion des enums — le ragdoll du pion refonctionne), `SandboxCharacter_Mover_ABP` (contexte `self` absent des `Evaluate Chooser` → branche Motion Matching inerte ; nouvelle bascule `AnimBranchIndex`). Testé en PIE : prone (capsule 40 ↔ 86 via le `StanceModifier`, base `PSD_Dense_Prone_Idles` sélectionnée), nage dans `WaterBodyLake_0` (entrée/flottaison à la profondeur cible/plongée/sortie, `PSD_SwimmingIdle` sélectionnée), accroupi de couverture. NON testé : entrée en couverture par la touche P et déplacement le long d'un vrai mur. Sauvegarde des assets avant modification : `E:\projet\ProjectFv1_backup_mover_migration_2026-09-17\`.*
- *2026-09-18 (suite) : à la demande de l'utilisateur, `SandboxCharacter_Mover_ABP` passe **entièrement en Motion Matching** — `Update_Logic` ne calcule plus la bascule, `AnimBranchIndex` est fixé à `0` (nœuds `Select` / `Not Equal (Enum)` / `AND` / `Get Stance` supprimés, valeur par défaut de la variable mise à 0). Diagnostic de la **T-pose en nage** : ce n'était pas l'ABP mais le contenu — 5 des 6 bases Pose Search de nage n'ont que des lignes à `AnimAsset = None` et la table `SwimmingInDeepIdle` du chooser est vide ; seul `PSD_SwimmingMoving` est rempli. Contournement dans `CHT_PoseSearchDatabases_Mover` (lignes vers bases vides neutralisées, lignes 13/16 élargies en MatchAny), détail et procédure de correction définitive en §4.2.2. Vérifié en PIE avec MM permanent : idle debout (`PSD_Relaxed_Stand_Idles`), course avant (`PSD_Relaxed_Stand_Run_F_Starts/Loops`), prone (`PSD_Dense_Prone_Idles` → `anim_Prone_Idle`), nage surface immobile / en mouvement et nage profonde (`PSD_SwimmingMoving` → `RM_Breastroke_overwater_01_right_turn_Retargeted`).*
- *2026-09-19 (système d'armes sur le Mover, voir §4.2.3) : `AC_Weapon::Equip/Unequip` reçoivent une branche `Cast Failed` → `SandboxCharacter_Mover` (leur `Cast To SandboxCharacter_CMC` échouait en silence sur le Mover, d'où `Weapon`/`isArmed` jamais renseignés). Nouvelle fonction `SandboxCharacter_Mover::SetEquippedWeapon` + variables `Weapon_Equip`/`WantToshot` sur le pion, `Weapon_Equip`/`Weapon_Equip Last Frame`/`Want Toshot` sur `SandboxCharacter_Mover_ABP` (alimentées dans `Update_PropertiesFromCharacter`, thread principal). `IA_Aim` renseigne `WantToshot`. `Update_MotionMatching` consulte aussi `CHT_PoseSearchDatabases_Mover` quand `Is Armed`, et `Get_MMInterruptMode` force l'interruption au changement d'arme. Dans `CHT_PoseSearchDatabases_Mover` : colonnes `Is Armed` et `IS Moving Object` réactivées, ligne 1 (« Stand Idles Bow ») passée en `Gait = MatchAny`. Testé en PIE de bout en bout (ramassage → main → anims arc → visée → tir) avec non-régression prone/nage. `Inventory_Equipper.uasset` apparaît modifié sans changement de contenu (resauvegarde automatique du MCP, mêmes références `/Game/`).*