# đŸ—ïž Architecture du Projet — ProjectF > **Ce document est la rĂ©fĂ©rence d'architecture du projet, destinĂ©e en prioritĂ© aux modĂšles d'IA (Claude, etc.) qui vont lire, modifier ou crĂ©er du contenu dans ce projet Unreal Engine.** > Il doit permettre de comprendre **oĂč se trouve chaque systĂšme, quel fichier est responsable de quoi, et oĂč ajouter du nouveau contenu** — sans avoir Ă  explorer tout le projet Ă  chaque session. > > ⚠ **Ce document doit rester Ă  jour.** Voir la section [10. Maintenir ce document Ă  jour](#10-maintenir-ce-document-Ă -jour) et le skill `maintain-architecture-doc`. --- ## 1. Vue d'ensemble du projet ### 1.1 Nature du projet - **Moteur** : Unreal Engine **5.8**. - **Aucun code C++** : il n'y a pas de dossier `Source/`. Tout le gameplay est Ă©crit en **Blueprint visuel**, dans `Content/`. - **Genre** : jeu de survie / extraction en vue 3e personne avec un **inventaire en grille façon "Escape from Tarkov"** (armure, sac Ă  dos, armes, munitions, craft sur feu de camp/fonderie, gĂ©nĂ©rateurs, lecteurs de carte magnĂ©tique, coffres, PNJ pillables, vĂ©hicules). - **Multijoueur** : le systĂšme d'inventaire est rĂ©pliquĂ© (RPC client/serveur visibles partout dans `Inventory_Player`, ex. `Request Switch Weapon SERVER`, `Disarm Request SERVER`). Le projet doit donc ĂȘtre pensĂ© serveur-autoritaire pour tout ce qui touche Ă  l'inventaire, aux stats et au combat. ### 1.2 Les grandes couches du projet Le projet est construit par empilement de **trois grands blocs** de contenu, plus une couche d'outillage IA : 1. **Framework de personnage / locomotion ("Sandbox Character")** — `Content/Systems/Blueprints/` BasĂ© sur le sample officiel Epic "Motion Matching" (plugins `Mover`, `MotionWarping`, `MotionTrajectory`, `Chooser`, `AnimationLocomotionLibrary`, `AnimationWarping`). GĂšre le mouvement, la camĂ©ra, le Motion Matching, le traversal (vault/mantle/climb), les modes de mouvement personnalisĂ©s. **Ce framework est en grande partie template/tiers** : n'y toucher qu'en connaissance de cause. 2. **SystĂšme d'inventaire AGIS** ("Advanced Grid Inventory System", asset marketplace) — `Content/Core/Coreinventory/`, `Content/Systems/Inventory/`, `Content/UI/Inventory_UI/`, `Content/Data/Inventory_Data/`. C'est le **cƓur du gameplay** : inventaire en grille, Ă©quipement, craft, loot, sauvegarde. La quasi-totalitĂ© des systĂšmes de jeu ajoutĂ©s par l'Ă©quipe (stats, mort, sĂ©lection rapide d'Ă©quipement, interactables) se branchent sur ce systĂšme. 3. **SystĂšmes de jeu spĂ©cifiques au projet**, ajoutĂ©s par-dessus AGIS — `Content/Systems/Stats/`, `Content/Systems/Scent/`, `Content/Systems/Movable_Object/`, `Content/Systems/Door/`, `Content/PCG/`, `Content/Items/`, `Content/UI/Widgets/` (HUD, pause menu). C'est ici que la majoritĂ© des Ă©volutions de gameplay futures doivent ĂȘtre ajoutĂ©es. 4. **Outillage IA** — plugins `VibeUE`, `EditorToolset`, `ModelContextProtocol`, `Terminal` (dĂ©clarĂ©s dans `ProjectFv1.uproject`) + `.mcp.json` Ă  la racine. Ils exposent l'Ă©diteur Unreal (Blueprints, Widgets, Input, PCG, Landscape, Niagara, etc.) Ă  un serveur MCP local (`http://127.0.0.1:8000/mcp`) pilotĂ© par des agents Claude. **C'est le mĂ©canisme par lequel un modĂšle d'IA lit/modifie ce projet** — voir la section [9. Notes pour les IA](#9-notes-pour-les-ia-piĂšges-connus-de-loutillage) pour les piĂšges connus. En plus de cela, deux couches d'assets tiers volumineuses sont prĂ©sentes mais **ne contiennent pas de logique de gameplay propre au projet** : le pack mĂ©tĂ©o **UltraDynamicSky** (`Content/Systems/Weather/UltraDynamicSky/`) et diverses bibliothĂšques d'assets 3D Fab/Megascans/Quixel (`Content/Fab/`, `Content/Megaplant_Library/`, une bonne partie de `Content/Animations/` et `Content/Characters/`). ### 1.3 DĂ©pendances principales entre systĂšmes ``` Character (Pawn, gĂ©rĂ© par le framework "Sandbox Character") │ ├─ Composant Inventory_Player (Content/Core/Coreinventory/Inventory_Player) │ └─ hĂ©rite de Inventory_Equipper (Ă©quipement d'armes/objets) │ └─ hĂ©rite de Inventory__Main (cƓur gĂ©nĂ©rique AGIS : slots, containers, rĂ©seau) │ │ ⚠ Pour un item (`_BP_ItemBase` et enfants) qui a besoin de chercher/consommer un item dans │ l'inventaire de son porteur (ex. l'arc qui cherche des flĂšches), utiliser sa propriĂ©tĂ© hĂ©ritĂ©e │ `Owner Inventory` (fonction `Variables|Runtime|GetOwnerInventory`, self implicite) plutĂŽt que de │ reconstruire `GetOwnerCharacter → Cast SandboxCharacter_CMC → GetInventoryPlayer → GetListeningInventory` : │ cette derniĂšre chaĂźne se rĂ©sout Ă  `None` tant que le joueur n'a pas ouvert son Ă©cran d'inventaire au │ moins une fois (`Listening Inventory` est un Ă©tat d'UI, pas l'inventaire persistant). `Owner Inventory` │ est typĂ©e `Inventory_Equipper` mais accepte directement les pins `Inventory__Main` (ex. `BOTH|FindItem`) │ grĂące Ă  cette hiĂ©rarchie d'hĂ©ritage — aucun cast nĂ©cessaire. DĂ©couvert et corrigĂ© dans │ `BP_Item_Bow::CountArrows/ConsumeArrow` (voir §7). │ │ Inventory_Player pilote/possĂšde : │ ├─ WB_InventoryScreen (UI d'inventaire complĂšte, créée Ă  la demande) │ │ └─ WB_InventoryPart1 / WB_InventoryPart2 │ │ └─ WB_EquipSlot → WB_Container → WB_InventorySlot → WB_Item │ ├─ WB_QuickSelect (roue de sĂ©lection rapide d'Ă©quipement, 4 slots) │ └─ Les Input Actions IA_*AGIS via l'IMC_AGIS_Character / IMC_AGIS_InventoryTab │ ├─ Composant AC_Stats (Content/Systems/Stats/AC_Stats) │ └─ Vie, mort (OnDeath), Revive → dĂ©clenche WB_YouDied et le respawn du Character. │ TakeDamage(BodyPart, DMGValue) est le point d'entrĂ©e UNIQUE de toute cause de mort : │ utilisĂ© Ă  la fois par la mort par chute et par la touche de debug K (SandboxCharacter_CMC/EventGraph). │ ├─ Armes (Content/Systems/Weapons/, voir §4.3) │ └─ AC_Weapon, ActorComponent ajoutĂ© Ă  chaque Blueprint d'arme (BP_Item_Bow, BP_Item_AdvancedRifle) : │ s'auto-abonne (EventBeginPlay, cast Owner → BP_Item_HoldableBase) au dispatcher │ `BP_Item_HoldableBase::OnHeldStateChanged(bIsHeld)` — PAS Ă  `_BP_ItemBase::OnOwnerChanged` │ (2026-09 : bug corrigĂ© — OnOwnerChanged se dĂ©clenche pour TOUT changement de propriĂ©taire, │ y compris le simple ramassage/rangement dans un slot d'inventaire non tenu en main, ce qui │ causait "2 armes Ă©quipĂ©es en mĂȘme temps" dĂšs que 2 armes Ă©taient prĂ©sentes dans l'inventaire. │ OnHeldStateChanged ne se dĂ©clenche que sur le VRAI changement d'Ă©tat main/pas-en-main, via │ `BPI_HoldableItem::On Item Attached(ShouldHold)` dĂ©jĂ  implĂ©mentĂ© par BP_Item_HoldableBase). │ HandleHeldStateChanged(bIsHeld) → Equip(Owner)/Unequip() selon bIsHeld, qui pilotent `bIsEquipped`. │ Expose CanUse()/TryUsePrimary()/StopPrimary() (cooldown gĂ©nĂ©rique) que chaque item interroge dans ses │ overrides `Custom|PrimaryUse`/`StopPrimaryUsing` existants (voir §7). BFL_WeaponDamage::ApplyPointDamage │ route les dĂ©gĂąts d'un projectile vers `AC_Stats::TakeDamage` (mapping nom d'os → E_BodyPart). │ **SĂ©lection d'animation (2026-09-06)** : `Equip`/`Unequip` pilotent aussi `SandboxCharacter_CMC::Weapon` │ (enum `Weapon_Equip` : None/Bow/OneArmPistol/TwoArmPistol/Riffle/Bat — lu par la Pose Search Database │ `CHT_PoseSearchDatabases_Dense` pour sĂ©lectionner le pool d'animations armĂ©es/dĂ©sarmĂ©es de Motion │ Matching) et `isArmed` (bool) — ces deux variables existaient dĂ©jĂ  sur le personnage mais n'Ă©taient │ JAMAIS renseignĂ©es avant ce fix (dette du template de base), donc la locomotion restait toujours │ "Ă  mains nues" quelle que soit l'arme tenue. `AC_Weapon` porte une variable `WeaponTypeByte` (byte, │ 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` │ passĂ© Ă  `MotionMatchingAnimNodeLibrary.SetDatabasesToSearch`) ne testait QUE MovementMode/MovementState/ │ Gait — jamais `Weapon_Equip` (variable ABP, distincte de `SandboxCharacter_CMC::Weapon`, alimentĂ©e depuis │ celle-ci via PropertyAccess dans `Update_States`, qui a bien SON PROPRE tracker `Weapon_Equip Last Frame` │ dĂ©jĂ  prĂ©sent mais jamais branchĂ©). RĂ©sultat : passer armĂ©/dĂ©sarmĂ© EN RESTANT IMMOBILE ne changeait ni │ MovementMode/State/Gait, donc `Get_MMInterruptMode` retournait toujours `DoNotInterrupt` et Motion │ Matching continuait indĂ©finiment l'ancienne pose (`bIsContinuingPoseSearch=True`) sans jamais essayer │ la nouvelle base de donnĂ©es pourtant correctement sĂ©lectionnĂ©e dans `ValidDatabases`/`DatabasesToSearch`. │ Fix : condition supplĂ©mentaire `Weapon_Equip != Weapon_Equip Last Frame` ajoutĂ©e au `OR` racine de │ `Get_MMInterruptMode` (3ᔉ pin ajoutĂ©e au nƓud `ORBoolean` existant via `add_node_pin`, PAS une réécriture │ DSL complĂšte — voir §9 pour le piĂšge du wildcard enum). (2) Une fois l'interruption forcĂ©e, la recherche │ Ă©chouait quand mĂȘme : `PSD_Dense_Stand_Bow_Idles`/`_Bow_Aim_Idles`/`PSD_Walk_Bow`/`PSD_Crouch_Bow` │ (toutes sous `/Game/Animations/humain/Armed_mov/Bow/`) avaient leur `PoseSearchMode` sur `PCAKD_TREE` │ et leur build d'index Ă©chouait dĂšs le chargement (`LogPoseSearch: Error: ... BuildIndex Failed because │ of 'No Convergence' while calculating PCA data`) — passĂ©es en `BRUTE_FORCE` (pas besoin de PCA, dataset │ de toute façon minuscule), ce qui a dĂ©bloquĂ© la recherche. (3) **Lignes armĂ©es manquantes dans le │ chooser (CORRIGÉ 2026-09-06)** : la colonne `Is Armed` de `CHT_PoseSearchDatabases_Dense` (seule des 4 │ tables LOD Ă  en avoir une) n'avait que DEUX lignes `MatchTrue` — "Stand Idles Bow" (ligne 1) et "Stand │ Walks Armed" (ligne 3). Toutes les autres (courses 4-5, sprint 6, InAir 7, accroupi 8-9, prone 10-11, │ nage 12-17) exigeaient `MatchFalse`, donc AUCUNE ligne ne correspondait dĂšs qu'on courait/sautait/ │ s'accroupissait armĂ© → chooser vide → Motion Matching gardait la derniĂšre pose (symptĂŽme : "mĂȘme │ animation en marchant, courant et accroupi"). Fix : ces lignes passĂ©es de `MatchFalse` Ă  `MatchAny` │ (repli propre sur l'animation non-armĂ©e au lieu du gel ; les lignes 0 et 2 DOIVENT rester `MatchFalse` │ sinon elles masqueraient les lignes arc 1 et 3, l'Ă©valuation Ă©tant descendante premier-match-gagne). │ Aucun sous-chooser concernĂ© n'a de colonne d'arme, le repli est donc sans effet de bord. │ ⚠ **RÉGRESSION 2026-09-13 (voir §8.2)** : `CHT_PoseSearchDatabases_Dense` a Ă©tĂ© ÉCRASÉ par la migration depuis │ `Project_F` — les lignes armĂ©es Bow (`PSD_Dense_Stand_Bow_Idles`, `_Bow_Aim_Idles`, `PSD_Walk_Bow`) et le passage │ `MatchFalse`→`MatchAny` dĂ©crits ci-dessus avaient disparu. **RESTAURÉ le 2026-09-14** : la version du commit `d29748b` │ a Ă©tĂ© remise (lignes Bow, Prone, nage, cover accroupi et Push revenues, contexte `Systems/Blueprints/SandboxCharacter_CMC_ABP`) │ puis le fix MatchAny a Ă©tĂ© refait par script : colonne `Is Armed` : lignes 0 et 2 en `MatchFalse`, 1 et 3 en `MatchTrue`, lignes 4 Ă  17 passĂ©es de `MatchFalse` Ă  `MatchAny` (la ligne 18 l'Ă©tait dĂ©jĂ ), vĂ©rifiĂ© aprĂšs rechargement. │ **Reste un problĂšme de contenu NON corrigĂ©** (voir §9) : `PSD_Dense_Stand_Bow_Idles` — et ELLE SEULE │ (`_Bow_Aim_Idles`/`PSD_Walk_Bow`/`PSD_Crouch_Bow` sont sains) — a ses 4 entrĂ©es │ `DatabaseAnimationAssets[i].SamplingRange` rĂ©glĂ©es sur `(longueur_du_clip, longueur_du_clip)`, une │ fenĂȘtre de largeur nulle placĂ©e Ă  la toute FIN du clip. Or Pose Search ne traite un asset comme │ bouclable que si sa plage vaut `(0,0)` (= « tout le clip ») : d'oĂč `bLoopAnimation=False` + fenĂȘtre de │ lecture nulle = une seule frame figĂ©e, alors mĂȘme que les AnimSequences sources sont bien `Loop=True`. │ Correction = remettre chaque `Sampling Range` Ă  `0 / 0` dans l'Ă©diteur Pose Search Database — Ă  faire Ă  │ la main : la propriĂ©tĂ© n'est exposĂ©e par AUCUNE API (absente de `ObjectTools.list_properties`, refusĂ©e │ par `get/set_editor_property` ET `ObjectTools`, et le `SET` console ne cible qu'une classe entiĂšre donc │ toutes les databases chargĂ©es). C'est aussi ce dataset dĂ©gĂ©nĂ©rĂ© (4 poses uniques) qui faisait Ă©chouer │ le PCA du point (2). │ `PSD_Crouch_Bow` existe mais n'est rĂ©fĂ©rencĂ©e par AUCUN chooser (contenu orphelin) : une fois les │ SamplingRange corrigĂ©es, on pourra lui dĂ©dier une vraie ligne armĂ©e accroupie plutĂŽt que le repli. │ ├─ Composants de mouvement (Content/Systems/Movement/, Systems/Blueprints/MovementModes/) │ └─ AC_ClimbingComponent, AC_Cover, AC_TraversalLogic, AC_PreCMCTick, AC_VisualOverrideManager
 │ ├─ Composant AIPerceptionStimuliSourceComponent (2026-09-05) │ └─ AjoutĂ© sur SandboxCharacter_CMC pour que le joueur soit dĂ©tectable par la vue de l'IA │ (AISense_Sight, auto_register_as_source=true). Sans lui, AUCUN AIPerceptionComponent │ ne peut jamais dĂ©tecter le joueur, quels que soient rayon/FOV/LOS configurĂ©s cĂŽtĂ© IA. │ └─ Autres composants gameplay (BP_ScentPoint, etc. — voir Systems/Scent/ §4.3 et Systems/Wildlife/ §4.4) Interactables (Content/Systems/Inventory/Interactables/*) └─ ImplĂ©mentent BPI_Interactable, exposent un inventaire via un composant Inventory_Storage / Inventory_Vendor / Inventory_Crafting (mĂȘmes bases AGIS que le joueur) → consultĂ©s par Inventory_Player lors d'une interaction (touche IA_InteractAGIS) DonnĂ©es d'items (Content/Data/Inventory_Data/, Content/Items/) └─ DT_Items (DataTable), ItemDefaults / ItemInfo (structs), DD_Item (DataAsset par item) alimentent Ă  la fois l'UI d'inventaire ET les Blueprints d'objets sous Content/Items/BP_Item_* Faune sauvage (Content/Systems/Wildlife/, voir §4.4) └─ BP_AnimalBase (Character) rĂ©utilise TEL QUEL AC_Stats (vie/dĂ©gĂąts/mort, §1.3 ci-dessus) et BP_ScentPoint (Systems/Scent/, §4.3) — aucun systĂšme de vie ni d'odeur parallĂšle n'a Ă©tĂ© créé. BFL_WeaponDamage::ApplyPointDamage fonctionne automatiquement sur un animal (rĂ©sout AC_Stats par GetComponentByClass) : aucune adaptation nĂ©cessaire cĂŽtĂ© systĂšme d'armes. ``` ### 1.4 Conventions de nommage des assets | PrĂ©fixe | Signification | Exemple | |---|---|---| | `BP_` | Blueprint d'acteur | `BP_Campfire`, `BP_Item_Helmet` | | `WB_` / `WBP_` | Widget Blueprint (UMG) | `WB_InventoryScreen`, `WBP_PauseMenu` | | `AC_` | ActorComponent | `AC_Stats`, `AC_ClimbingComponent` | | `IA_` | Input Action (Enhanced Input) | `IA_InteractAGIS`, `IA_QuickSelectAGIS` | | `IMC_` | Input Mapping Context | `IMC_AGIS_Character` | | `E_` / `EM_` | Enum | `E_MovementMode`, `EM_Road_Type` | | `S_` / `ST_` | Struct | `S_TraversalCheckInputs`, `ST_Weather_Zone_forecasts` | | `M_` | Material | `M_Road`, `M_Campfire` | | `MI_` | Material Instance | `MI_Black`, `MI_Bottle` | | `SM_` | Static Mesh | `SM_Campfire`, `SM_RifleAdvanced` | | `SKM_` | Skeletal Mesh | `SKM_BodyArmor` | | `PA_` | Physics Asset | `PA_BodyArmor` | | `T_` | Texture | `T_Helmet` | | `RT_` | Render Target | `RT_InspectRenderer` | | `DT_` | Data Table | `DT_Items` | | `DD_` | Data Definition (DataAsset) | `DD_Item` | | `ML_` | Macro Library (Blueprint) | `ML_InventoryMacros` | | `SG_` | SaveGame | `SG_AGIS_UID`, `SG_AGIS_World` | | `GM_` / `PC_` | GameMode / PlayerController | `GM_Sandbox`, `PC_Sandbox` | | `CR_` | Control Rig | `CR_ClimbingGraphV2` | | `ABP_` | Animation Blueprint | `ABP_GenericRetarget` | | `AM_` | Anim Modifier / Anim Montage | `AM_ReloadHip` | | `NS_` | Niagara System | `NS_Tornado` | | `BPI_` | Blueprint Interface | `BPI_Interactable` | Le suffixe `AGIS` sur beaucoup d'assets (`IA_InteractAGIS`, `WB_...AGIS`, fonctions "Target is Inventory Player") signale qu'ils appartiennent au **socle marketplace AGIS**, par opposition aux ajouts spĂ©cifiques au projet. ### 1.5 Conventions importantes Ă  respecter - **Ne jamais renommer/dĂ©placer** les assets du socle AGIS (`Content/Core/Coreinventory/`, une bonne partie de `Content/Systems/Inventory/`, `Content/UI/Inventory_UI/Widgets/WB_Container|WB_EquipSlot|WB_InventorySlot|WB_Item`) sans nĂ©cessitĂ© — de nombreuses rĂ©fĂ©rences internes au plugin marketplace en dĂ©pendent. - **Nouveau systĂšme de gameplay** → crĂ©er un dossier dĂ©diĂ© sous `Content/Systems//`, Ă  l'image de `Systems/Stats/`, `Systems/Scent/`, `Systems/Movable_Object/`. - **Nouvel objet d'inventaire (item)** → suivre le patron existant dans `Content/Items/` : un Blueprint `BP_Item_` (hĂ©ritant de `_BP_ItemBase` ou d'une base spĂ©cialisĂ©e dans `Items/BaseBlueprints/`), ses assets (mesh/matĂ©riau/texture) dans un sous-dossier `Content/Items//` ou `Content/Items/Resources//`, et une entrĂ©e dans `DT_Items` / les DataAssets sous `Content/Data/Inventory_Data/DataAssets/`. - **Nouvel Input Action liĂ© Ă  l'inventaire** → `Content/Systems/Inventory/Other/Inputs/Actions/`, mappĂ© dans `IMC_AGIS_Character` ou `IMC_AGIS_InventoryTab`. **Input Action de dĂ©placement/camĂ©ra gĂ©nĂ©rique** → `Content/Core/PlayerController/Input/`, mappĂ© dans `IMC_Sandbox`. - **Nouveau widget d'inventaire** → `Content/UI/Inventory_UI/Widgets/`. **Nouveau widget hors inventaire** (HUD, menus) → `Content/UI/Widgets/`. - Le clavier cible est **AZERTY** ; privilĂ©gier des touches identiques physiquement sur QWERTY/AZERTY pour les nouveaux raccourcis (ex. `V`, `B`). - RĂ©plication rĂ©seau : toute action qui modifie l'Ă©tat du jeu cĂŽtĂ© inventaire/stats doit suivre le patron `Request X SERVER` (Custom Event `...SERVER`, `Replicated From Client, Executes On Server`) dĂ©jĂ  prĂ©sent dans `Inventory_Player`. --- ## 2. Vue d'ensemble de l'arborescence racine ```text ProjectF/ ├── .gitattributes → RĂšgles Git (LFS, line-endings) ├── .gitignore → Exclut Binaries/, Intermediate/, Saved/, DerivedDataCache/, .vscode/
 ├── .mcp.json → DĂ©clare le serveur MCP "unreal-mcp" (http://127.0.0.1:8000/mcp) utilisĂ© par les agents IA ├── ProjectFv1.uproject → Fichier projet UE5.8 : liste des plugins activĂ©s (voir §1.2/§8) ├── README.md → Description minimale du projet ├── Architecture_Projet.md → CE DOCUMENT │ ├── .claude/ → Skills et configuration Claude Code pour ce projet │ └── skills/ │ └── maintain-architecture-doc/SKILL.md → Skill de maintenance de ce document (voir §10) │ ├── .codex/, .cursor/, .gemini/, .vscode/ → Configuration d'IDE / d'agents IA tiers (mcp.json, config.toml
) │ ├── Config/ → Configuration moteur & jeu (voir dĂ©tail §7) ├── Content/ → Tous les assets du jeu (voir dĂ©tail §3 Ă  §6) │ ├── Binaries/, Intermediate/, Saved/, DerivedDataCache/ → GĂ©nĂ©rĂ©s par l'Ă©diteur, exclus de Git, jamais Ă  Ă©diter/documenter ``` ### 2.1 ⚠ Fichiers centraux autrefois isolĂ©s Ă  la racine de `Content/` (rangĂ©s le 2026-09-13) Quelques fichiers importants vivent directement sous `Content/`, hors de toute organisation par dossier — Ă  connaĂźtre avant de chercher "oĂč est le personnage" ou "oĂč est le GameInstance" : ```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. ``` --- ## 3. `Content/Core/` — Socle inventaire (AGIS) + Player Controller + Tick Le cƓur technique de l'inventaire et des entrĂ©es gĂ©nĂ©riques du joueur. ```text Content/Core/ ├── Coreinventory/ → CƓur du plugin AGIS (composants, donnĂ©es, sauvegarde) │ ├── Inventory__Main.uasset → ActorComponent BASE : logique gĂ©nĂ©rique de containers/slots, rĂ©plication rĂ©seau. Racine de la hiĂ©rarchie d'inventaire. │ ├── Inventory_Equipper.uasset → hĂ©rite de Inventory__Main : ajoute la logique d'Ă©quipement (armes/objets tenus en main) │ ├── Inventory_Player.uasset → hĂ©rite de Inventory_Equipper : composant d'inventaire du JOUEUR. Contient toute la logique spĂ©cifique projet ajoutĂ©e cette session (SelectQuickSlot, ToggleQuickEquip, GetQuickSlotItemInfo, graphe INPUTS avec tous les bindings Enhanced Input du joueur). (2026-09-05) `ToggleQuickEquip`/`GetQuickSlotItemInfo` (touches V/B) Ă©taient des stubs de prototype (PrintString uniquement, aucun appel d'Ă©quipement rĂ©el, plus un bool `bQuickSlotArmed` inversĂ©) — corrigĂ©s pour appeler rĂ©ellement `Inventory_Equipper::SwitchWeaponByUID`/`EmptyHands` (hĂ©ritĂ©s). `GetQuickSlotItemInfo` retourne dĂ©sormais aussi le `ContainerUID` du slot (WEAPON/WEAPON2/Speed1/Speed2) via `WBContainer::GetContainerUID`, nĂ©cessaire pour cibler `SwitchWeaponByUID`. B Ă©quipe/dĂ©sĂ©quipe donc rĂ©ellement l'item du slot prĂ©sĂ©lectionnĂ© par V (le slot doit dĂ©jĂ  contenir un item via le drag&drop du paperdoll — la roue V/B ne fait que choisir PARMI les 4 emplacements dĂ©jĂ  Ă©quipĂ©s, elle ne pioche pas dans l'inventaire gĂ©nĂ©ral). Nouvelle fonction `CycleQuickSlot()` (Weapon→Weapon2→Speed1→Speed2→Weapon→
) ajoutĂ©e pour fiabiliser la sĂ©lection : `WB_QuickSelect::EventConstruct` (Content/UI/Inventory_UI/Widgets/Other/WB_QuickSelect.uasset) l'appelle dĂ©sormais automatiquement Ă  chaque pression de V (donc Ă  chaque crĂ©ation de la roue), sans dĂ©pendre du clic sur un bouton de la roue (`BtnWeapon1` etc. — dont le fonctionnement en jeu n'a pas pu ĂȘtre confirmĂ©). Les boutons de la roue restent cĂąblĂ©s Ă  `SelectQuickSlot` en plus, au cas oĂč le clic fonctionne rĂ©ellement. │ ├── Inventory_Storage.uasset → Inventaire des containers de stockage (coffres, trunk, etc.) │ ├── Inventory_Vendor.uasset → Inventaire des PNJ vendeurs │ ├── Inventory_Crafting.uasset → Inventaire des stations de craft (campfire, smelter, gĂ©nĂ©rateur) │ ├── BP_AttachmentHandler.uasset → ActorComponent gĂ©rant les attachements sur les armes (silencieux, lampe, chargeur
) │ ├── CombatComponent.uasset → ActorComponent : logique de combat (tir, dĂ©gĂąts) liĂ©e aux armes AGIS │ ├── BP_SM_DroppedMesh.uasset → Acteur reprĂ©sentant un objet lĂąchĂ© au sol (mesh statique + interaction de ramassage) │ ├── ItemMesh_STATIC.uasset / ItemMesh_Skeletal.uasset → Acteurs gĂ©nĂ©rant le rendu 3D d'un item tenu/lĂąchĂ© (mesh statique ou squelettal) │ ├── DD_Item.uasset → DataAsset dĂ©crivant un item (rĂ©fĂ©rencĂ© par ItemDefaults) │ ├── FL_AGIS.uasset → Function Library : fonctions statiques utilitaires du plugin AGIS │ ├── ML_AGISDefaults.uasset → Macro Library : macros par dĂ©faut du plugin │ ├── ML_AGIS_UMG.uasset → Macro Library : macros dĂ©diĂ©es Ă  l'UI (UMG) │ ├── ML_InventoryMacros.uasset → Macro Library : macros gĂ©nĂ©riques d'inventaire │ ├── GameInstance_AGIS.uasset → GameInstance de base du plugin (Ă©tat persistant entre les maps) │ ├── Gamemode_AGIS.uasset → GameMode de base du plugin (indĂ©pendant de GM_Sandbox, voir §4) │ ├── PlayerController_AGIS.uasset → PlayerController de base du plugin │ └── SG_AGIS_UID.uasset / SG_AGIS_World.uasset → SaveGame : compteur d'UID uniques / Ă©tat persistant du monde (sauvegarde) │ ├── PlayerController/ → Input gĂ©nĂ©rique du joueur (mouvement, camĂ©ra), indĂ©pendant de l'inventaire │ ├── IA_InitiateClimb / IA_LeapFromClimb / IA_MovingClimb.uasset → Input Actions liĂ©es Ă  l'escalade │ └── Input/ │ ├── IMC_Sandbox.uasset → Input Mapping Context PRINCIPAL, ajoutĂ© dans `SetupInput` par `SandboxCharacter_CMC` ET (depuis le 2026-09-15) par `SandboxCharacter_Mover` (mouvement, camĂ©ra, saut, + actions AGIS : `IA_ToggleInventory` Tab, `IA_InteractAGIS`, `IA_QuickEquip/Select/GiveAGIS`, `IA_UseItemPrimary/SecondaryAGIS`). Mappings `IA_TriggerRagdoll` (R, X manette) et `IA_Takedown` (clic gauche, RT) ajoutĂ©s le 2026-09-15 pour le Mover ragdoll │ └── IA_Move, IA_Look, IA_Jump, IA_Sprint, IA_Run, IA_Walk, IA_Crouch, IA_Prone, IA_Strafe, │ IA_Aim, IA_Interact, IA_ESC, IA_NextPawn, IA_Traverse, IA_TeleportToTarget, │ IA_SwimmingDeep, IA_TwinStick_AimDirection, IA_Move_WorldSpace, IA_Look_Gamepad, │ IA_NextVisualOverride, IA_Takedown, IA_TriggerRagdoll, IA_rool.uasset → Input Actions individuelles mappĂ©es dans IMC_Sandbox. Aussi Ă©coutĂ©es par la chaĂźne Mover (`SandboxCharacter_Mover`/`_Ragdoll`, `Systems/Mover/PC_Sandbox`, `Systems/Mover/SmartObjects/AC_SmartObjectAnimation`) ; le sprint du Mover Ă©coute `IA_Run` (Started/Completed). `IA_rool` et `IA_Traverse` ne sont Ă©coutĂ©s par aucun Blueprint │ └── Tick/ → SystĂšme de gestion centralisĂ©e du Tick (perf) ├── BPI_TickManager.uasset → Interface implĂ©mentĂ©e par les acteurs qui veulent ĂȘtre "tickĂ©s" par le manager ├── BP_TickManager.uasset → Acteur central qui distribue les ticks (probablement Ă  frĂ©quence configurable) └── E_TickFrequency.uasset → Enum des frĂ©quences de tick disponibles ``` --- ## 4. `Content/Systems/` — SystĂšmes de gameplay ### 4.1 `Systems/Inventory/` — Extension du socle AGIS pour ce projet ```text Content/Systems/Inventory/ ├── BP_Spawner.uasset → Acteur de spawn (probablement spawn d'items/loot en dĂ©but de partie) ├── DT_Items.uasset → DataTable listant tous les items du jeu (clĂ© pour crĂ©er/reconnaĂźtre un item) │ ├── Interactables/ → Tout ce que le joueur peut "interagir" avec (touche IA_InteractAGIS) │ ├── BP_EnemyPuppet.uasset → PNJ/mannequin pillable │ ├── BP_Vendor.uasset → PNJ vendeur (utilise Inventory_Vendor) │ ├── CraftingInteractables/ │ │ ├── Campfire/BP_Campfire.uasset → Station de cuisson/craft (feu de camp) + ses assets (mesh, matĂ©riaux) │ │ └── Smelter/BP_Smelter.uasset → Station de fonte de minerai + ses assets │ ├── FuelGenerator/BP_Generator.uasset → GĂ©nĂ©rateur Ă©lectrique (consomme du carburant) │ ├── KeycardReader/BP_KeycardReader.uasset → Lecteur de carte magnĂ©tique (dĂ©verrouillage) │ ├── Other/BP_SimpleDoor.uasset → Porte interactable simple │ └── Storages/ │ ├── BP_StorageBox.uasset, BP_Trunk.uasset, BP_SphereStorage.uasset, _BP_StorageBase.uasset → Coffres/contenants de stockage (hĂ©ritent de _BP_StorageBase) │ └── Deadbody/BP_Deadman.uasset → Cadavre pillable │ ├── Interfaces/ → Interfaces Blueprint (contrats partagĂ©s) │ ├── BPI_Interactable.uasset → Contrat pour tout objet interactible (implĂ©mentĂ© par tous les Interactables ci-dessus) │ ├── BPI_SlotWidgets.uasset → Contrat pour les widgets de slot d'inventaire │ ├── BPI_HoldableItem.uasset → Contrat pour un item tenable en main │ ├── BPI_WeaponAGIS.uasset → Contrat pour les armes │ ├── BPI_DamageFeedback.uasset → Contrat de retour visuel/sonore lors de dĂ©gĂąts │ └── BPI_GameInstance_AGIS.uasset → Contrat exposĂ© par le GameInstance cĂŽtĂ© AGIS │ ├── Other/ → Assets d'appoint de l'inventaire │ ├── Animations/ → Animations liĂ©es aux armes/mains nues (Jog, Rifle, TurnInPlace, WALK) — clips Motion Matching (MM_*) et montages (AM_*) │ ├── Fonts/ → Polices utilisĂ©es par l'UI d'inventaire │ ├── Inputs/ │ │ ├── Actions/ → **Toutes** les Input Actions liĂ©es Ă  l'inventaire (IA_*AGIS), y compris IA_QuickSelectAGIS et IA_QuickEquipAGIS (sĂ©lection rapide, ajoutĂ©es pour ce projet) │ │ ├── IMC_AGIS_Character.uasset → Mapping Context actif en jeu (personnage) : touches 1/2/3/4, F, V, B, etc. │ │ └── IMC_AGIS_InventoryTab.uasset → Mapping Context actif quand l'inventaire plein Ă©cran est ouvert │ ├── InspectCapture/ → Rendu d'inspection d'objet (RT_InspectRenderer + BP_InspectRenderer + M_Inspect) │ └── Materials/ → MatĂ©riaux gĂ©nĂ©riques rĂ©utilisĂ©s par les items (MI_Black, MI_Red, M_Metal, M_Outline
) │ └── Utilities/ → Outils d'Ă©diteur (Editor Utility Widgets) pour la crĂ©ation de containers/inventaires ├── EUW_ContainersCreator.uasset, EUW_WidgetToInventoryData.uasset └── Others/WB_ContainerSpecsUtility.uasset, WB_CreatorContainerUtility.uasset ``` ### 4.2 `Systems/Blueprints/` — Framework de personnage / locomotion ("Sandbox Character") Contenu trĂšs largement issu du sample Epic **Motion Matching** (plugins `Mover`, `MotionTrajectory`, `Chooser`, `AnimationLocomotionLibrary`). À traiter comme un framework tiers : prĂ©fĂ©rer l'Ă©tendre plutĂŽt que le réécrire. ```text Content/Systems/Blueprints/ ├── BPI_SandboxCharacter_Pawn.uasset → Interface du Pawn joueur (point d'entrĂ©e du framework de locomotion). (2026-09-14) + fonctions du sample GASP pour le Mover : `AddTarget`, `RemoveTarget`, `Set_IsPlayingRootMotion`, `Set_PhysicsProfile`, sorties typĂ©es de `Get_MMIResult` / `Get_PropertiesForRagdoll` ├── BPI_SandboxCharacter_ABP.uasset → Interface de l'Anim Blueprint du personnage. (2026-09-14) + `Get_Trajectory`, `Update_MMIConstraints` ├── AC_TraversalLogic.uasset → ActorComponent : logique de traversal (vault/mantle/climb contextuel) ├── AC_PreCMCTick.uasset → ActorComponent : logique exĂ©cutĂ©e avant le tick du mouvement (Mover/CMC) ├── AC_VisualOverrideManager.uasset → ActorComponent : gestion des overrides visuels du personnage ├── GM_Sandbox.uasset / PC_Sandbox.uasset → GameMode / PlayerController du framework de locomotion (indĂ©pendants de Gamemode_AGIS/PlayerController_AGIS, voir §3) │ ├── Cameras/ → SystĂšme de camĂ©ra (Camera Rigs modulaires) │ ├── CameraAsset_SandboxCharacter, CameraDirector_SandboxCharacter, CHT_CameraRig │ ├── E_CameraMode.uasset, E_CameraStyle.uasset │ └── Rigs/CameraRig_* (Close/Medium/Far × Aim/Freecam/Strafe, CrouchOffset, CollisionOffset, TwinStick
) │ ├── MovementModes/ → Modes de mouvement personnalisĂ©s (plugin Mover) │ ├── BP_MovementMode_Walking / _Falling / _Slide │ ├── BP_MovementTransition_ToSlide / _FromSlide │ └── BP_ClimbingMode.uasset │ ├── ControlRigs/CR_Biped_FootPlacement.uasset → Control Rig : placement des pieds (foot IK) ├── RetargetedCharacters/ABP_GenericRetarget.uasset → Anim BP gĂ©nĂ©rique pour le retargeting │ ├── AnimModifiers/ → Anim Modifiers (post-traitement de clips d'animation Ă  l'import) ├── AnimNotifies/ → Anim Notifies personnalisĂ©es (BP_AnimNotify_FoleyEvent*, BP_NotifyState_EarlyTransition/MontageBlendOut) + enums associĂ©s │ ├── Data/ → Structs/Enums/Curves partagĂ©s par tout le framework de locomotion │ ├── E_Gait, E_Stance, E_MovementMode, E_MovementState, E_MovementDirection(Bias), E_RotationMode, │ │ E_AnalogStickBehavior, E_ExperimentalStateMachineState, E_TraversalActionType │ │ (2026-09-14, convergence §8.2) valeurs du sample ajoutĂ©es EN FIN d'enum : E_MovementMode += Ragdoll, Flying ; │ │ E_ExperimentalStateMachineState += Debug Flying Loop. S_CharacterPropertiesForAnimation += BasedMovementDelta, │ │ Weapon_Type (`Data/Enums/E_WaponType`) ; S_BlendStackInputs += Blend Curve. Ne jamais rĂ©ordonner ces enums (valeurs stockĂ©es par nom interne). │ ├── S_CharacterPropertiesForAnimation / _ForCamera / _ForTraversal, S_BlendStackInputs, │ │ S_MoverCustomInputs, S_PlayerInputState, S_TraversalCheckInputs/Result, │ │ S_TraversalChooserInputs/Outputs (contexte des choosers `CHT_TraversalMontages_CMC/_Mover`), S_ChooserOutputs │ │ (contexte de `CHT_CMCCharacterAnimations`), S_MovementDirectionThresholds, │ │ S_RotationOffsetCurveChooser_Inputs, S_DebugGraphLineProperties │ ├── Curve_RotationOffset_* , Curve_StrafeSpeedMap, CHT_RotationOffsetCurve → Curve Tables pilotant les offsets d'animation │ └── BFL_HelpfulFunctions.uasset, BPI_InteractionTransform.uasset │ ├── SmartObjects/ → IntĂ©gration du plugin SmartObject (points d'ancrage d'animation contextuelle) │ ├── CHPA_SmartObject, AC_SmartObjectAnimation │ └── SmartObjectAnimationPayload, SmartObjectSelectionInputs/Outputs │ ├── SandboxCharacter_CMC_ABP.uasset → Anim Blueprint principal du personnage joueur (pilotĂ© par `/Game/Core/Character/SandboxCharacter_CMC`). Anciennement Ă©garĂ© dans un dossier `d/` mal nommĂ© — dĂ©placĂ© ici (nettoyage du 2026-09-04). │ ├── (SUPPRIMÉS de ce dossier) SandboxCharacter_Mover / _ABP / _Ragdoll → **Depuis le 2026-09-13 ces trois assets n'existent plus dans `Systems/Blueprints/`** : les versions actives (personnage Mover conservĂ© Ă  la demande de l'utilisateur) sont dans `Content/Systems/Mover/` (voir §4.2.1). `SandboxCharacter_CMC` (`Content/Core/Character/`) reste le personnage RÉEL du jeu. VĂ©rifiĂ© le 2026-09-14 : `GM_Dev` (GameMode de `MapDev1`), `Systems/Blueprints/GM_Sandbox` et `Core/Coreinventory/Gamemode_AGIS` ont `DefaultPawnClass = /Game/Core/Character/SandboxCharacter_CMC` ; `GM_Sandbox_Ragdoll` et `GM_MoverTest` (contenu de test du sample) restent Ă  `None` ; `Systems/Mover/GM_Sandbox` spawne `SandboxCharacter_Mover`. │ ├── GM_Sandbox_Ragdoll.uasset → Variante de `GM_Sandbox` avec `SandboxCharacter_Mover_Ragdoll` comme pawn par dĂ©faut (contenu du sample, non utilisĂ©e par le jeu rĂ©el). │ ├── AI/StateTree/ → **(2026-09-08)** StateTree + tĂąches pour l'interaction Smart Object du personnage (`ST_Player_SandboxCharacter_SmartObject`, `STT_CharacterIgnoreCollisionsWithOtherActor`, `STT_FindSlotTransforms`, `S_SmartObjectPayload`). Contenu du sample, AI/SmartObject non branchĂ© sur le gameplay AGIS. │ └── (2026-09-08) Contenu supplĂ©mentaire fusionnĂ© depuis un import du sample officiel Epic **Game Animation Sample** (voir note globale en fin de §8) : `RetargetedCharacters/` (BP_Echo, BP_Manny, BP_Quinn, BP_Twinblast, BP_UE4_Mannequin — **supprimĂ©s le 2026-09-13** avec les personnages de dĂ©mo ; seul `ABP_GenericRetarget` subsiste), des `Cameras/Rigs/` et `MovementModes/` supplĂ©mentaires (`CameraRig_Far_Ragdoll`, `CameraRigPrefab_ThirdPerson`, `BP_MovementMode_Ragdoll`, `B_MovementMode_Flying`), des `Data/` supplĂ©mentaires (`S_RagdollProperties`, `S_MoverCustomInputs_Ragdoll`, `E_RagdollInjuryState`, `Ragdoll_Fall_to_Ground_BlendCurve`, variantes `S_CHT_*_IN/OUT` pour les choosers de traversal/interaction/get-up), des `AnimNotifies/` supplĂ©mentaires (`BP_NotifyState_MMI_IK`, `_MMI_MotionWarping`, `_OverrideCapsuleCollision`, `_OverrideMovementMode`, enums `E_EarlyTransition_*`/`E_FoleyEventSide`/`E_TraversalBlendOutCondition`), et des `SmartObjects/` supplĂ©mentaires (`Bench/`, `DistanceToSmartObject`, `PSS_SmartObject`, `TasksAndConditions/STT_ClaimSlot|ClearHandle|PlayAnimFromBestCost|PlayAnimMontage`). ``` ### 4.2.1 `Systems/Mover/` et `Systems/Aiming/` — personnage Mover et framework du sample (isolĂ©s le 2026-09-14) Copie du framework "Sandbox Character" du sample Epic **Game Animation Sample**, arrivĂ©e avec la migration `Project_F` (§8.2) et conservĂ©e pour le personnage alternatif basĂ© sur le plugin **Mover** et pour le systĂšme de visĂ©e. DĂ©placĂ©e SANS fusion depuis `Content/Blueprints/` et `Content/Input/`. Beaucoup d'assets ont un homonyme dans `Systems/Blueprints/` (`AC_TraversalLogic`, `BPI_*`, `GM_Sandbox`, `PC_Sandbox`, structs `S_*`, camĂ©ras
) : ce sont des doublons DIVERGENTS, Ă  ne pas confondre ni fusionner aveuglĂ©ment (voir §9, piĂšge `consolidate_assets`). Les enums, eux, sont partagĂ©s avec `Systems/Blueprints/Data/` (fusionnĂ©s le 2026-09-14). ```text Content/Systems/Mover/ ⚠ (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/`) ├── BPI_SandboxCharacter_Pawn / _ABP.uasset → Interfaces GASP implĂ©mentĂ©es par la chaĂźne Mover ├── AI/StateTree/ → `ST_Player_SandboxCharacter_SmartObject` + tĂąches (copie GASP) ├── AnimModifiers/ → `AM_BakePhaseCurveFromFootstepNotifies`, `AM_FootSteps_Run` (rĂ©fĂ©rencĂ©s par quelques anims `UEFN_Mannequin`) ├── 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`, **`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`) 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 Content/Systems/ ├── Stats/ │ └── AC_Stats.uasset → ActorComponent ACTIF : gĂšre la vie du personnage (Health), la mort (bIsDead, dispatcher OnDeath), Heal, Revive (voir §1.3). AjoutĂ© cette session pour le systĂšme de mort/respawn. (2026-09-05) Extension additive pour la faune : nouveau dispatcher `OnDamaged(BodyPart, DMGValue)`, diffusĂ© au point de convergence partagĂ© de `TakeDamage` (aprĂšs le switch par bodypart, avant le calcul de mort) — permet Ă  un consommateur (ex. BP_AnimalBase) de rĂ©agir Ă  CHAQUE coup reçu, pas seulement Ă  la mort, sans dupliquer la logique de dĂ©gĂąts. │ ├── Weapons/ (2026-09-05) → Architecture d'armes gĂ©nĂ©rique, rĂ©utilisable par toute arme (arc, arme Ă  feu, futur mĂȘlĂ©e). Voir §1.3 pour le mĂ©canisme d'Ă©quipement. │ ├── AC_Weapon.uasset → ActorComponent commun Ă  TOUTE arme (ajoutĂ© Ă  BP_Item_Bow et BP_Item_AdvancedRifle). Ne contient AUCUNE logique spĂ©cifique Ă  un type d'arme. Variables : bIsEquipped, bIsBusy, CooldownDuration, LastUseTime, OwnerCharacter. Dispatchers : OnEquipped/OnUnequipped/OnPrimaryUse(Stopped)/OnSecondaryUse(Stopped). Fonctions : CanUse(), Equip/Unequip, TryUsePrimary/StopPrimary, TryUseSecondary/StopSecondary. Son EventGraph s'auto-abonne Ă  `OnOwnerChanged` de son propre acteur (pattern `Default|AssignOnOwnerChanged`) pour appeler Equip/Unequip automatiquement — zĂ©ro couplage avec Inventory_Player/Equipper. │ ├── BFL_WeaponDamage.uasset → Blueprint Function Library. `ApplyPointDamage(Target, Instigator, HitBoneName, Damage)` : rĂ©sout le composant `AC_Stats` de la cible (`GetComponentByClass` + cast, no-op silencieux si absent) et route vers `AC_Stats::TakeDamage`, en mappant le nom d'os touchĂ© (bones du squelette UEFN_Mannequin : head/neck_*→Head, thigh|calf|foot|ball_L/R→LeftLeg/RightLeg, clavicle|upperarm|lowerarm|hand_L/R→LeftArm/RightArm, tout le reste dont spine_*/pelvis/root→Torso par dĂ©faut). RĂ©utilisable par toute arme/projectile/piĂšge futur. │ ├── BP_Projectile_Base.uasset → Actor projectile gĂ©nĂ©rique : StaticMeshComponent racine `ArrowMesh` (mesh + collision, PAS de mesh par dĂ©faut — Ă  fournir par les enfants) + `ProjectileMovement`. `OnComponentHit` : ignore les hits sur son propre `Owner` (Ă©vite l'auto-hit au tir), appelle `BFL_WeaponDamage::ApplyPointDamage` puis `HandleImpact(Hit)` — fonction overridable (dĂ©faut : `DestroyActor`). Variable `BaseDamage` (instance-editable). │ └── 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 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=