# đŸ—ïž 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. │ **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/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 du personnage (mouvement, camĂ©ra, saut
) │ └── 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_rool.uasset → Input Actions individuelles mappĂ©es dans IMC_Sandbox │ └── 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/ ├── SandboxCharacter_Mover.uasset → Personnage basĂ© sur le plugin Mover (utilisĂ© par aucune map du jeu ; le joueur rĂ©el est `Core/Character/SandboxCharacter_CMC`) ├── SandboxCharacter_Mover_Ragdoll.uasset → Variante ragdoll du personnage Mover ├── SandboxCharacter_Mover_ABP.uasset → Anim Blueprint du Mover (utilise `Systems/Aiming/ABP_AimingMaster`) ├── 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 sample. ⚠ Sa recherche de rebords ne marchait que sur les blocs de dĂ©mo `LevelBlock_Traversable` : cette branche a Ă©tĂ© retirĂ©e le 2026-09-14 avec la dĂ©mo, le Mover ne trouve donc plus aucun rebord (`TraversalCheckFailed`). Pour une vraie traversal, remplacer ce composant par `Systems/Blueprints/AC_TraversalLogic` (dette de convergence). ├── 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` ├── Input/ → `IMC_Sandbox` + 18 `IA_*` du Mover (anciennement `Content/Input/`), distincts de `Core/PlayerController/Input/` ├── MovementModes/ → `BP_MovementMode_Walking/Falling/Slide/Ragdoll`, `B_MovementMode_Flying`, `BP_MovementTransition_To/FromSlide` └── 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.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 (voir `BP_AnimalBase::PlayStateAnimation`) ; le StateTree stocke en interne l'Ă©tat courant sous forme de `byte` (les outils Blueprint disponibles ne permettent pas d'ajouter une variable membre ou un paramĂštre de fonction/dispatcher directement typĂ© sur un enum utilisateur — limitation dĂ©jĂ  documentĂ©e §9 pour AC_Stats, confirmĂ©e Ă  nouveau ici). │ ├── AC_AnimalSenses.uasset → ActorComponent gĂ©nĂ©rique (vue + odorat), ajoutĂ© Ă  `BP_AnimalBase`. Vue : ne fait AUCUNE dĂ©tection elle-mĂȘme — se contente de variables (`bCanSeePlayer`, `DistanceToPlayer`, `LastKnownPlayerLocation`) mises Ă  jour par `BP_AnimalAIController` via `ReportPlayerSighted`/`ReportPlayerLostSight`. Odorat : self-contained, `CheckScent` tourne sur un timer (`ScentCheckInterval`, 0.5s par dĂ©faut) dĂ©marrĂ© au `BeginPlay`, interroge `GetAllActorsOfClass(BP_ScentPoint)` et retient le plus proche (`bScentDetected`/`ScentSourceLocation` si distance ≀ `ScentDetectionRadius`, 800 par dĂ©faut). `DistanceToPlayer` est recalculĂ©e Ă  CHAQUE tick de `CheckScent` (pas seulement quand le joueur est vu) — nĂ©cessaire pour que le StateTree puisse dĂ©tecter le retour au calme (`DistanceToPlayer >= SafeDistance`) mĂȘme aprĂšs que l'animal ait fui hors de vue (bug rencontrĂ© et corrigĂ© en test PIE, voir §9). │ ├── BP_AnimalAIController.uasset → AIController, `AIPerceptionComponent` natif configurĂ© en Python (`AISenseConfig_Sight`, rayon 2500/3000, FOV 90°). `OnTargetPerceptionUpdated` relaie vers `AC_AnimalSenses` du pion possĂ©dĂ© (`ReportPlayerSighted`/`ReportPlayerLostSight` selon `Stimulus.WasSuccessfullySensed()`) — ne fonctionne QUE parce que le joueur porte un `AIPerceptionStimuliSourceComponent` (voir §1.3). │ ├── BP_AnimalBase.uasset → Character gĂ©nĂ©rique, base de TOUTE la faune. Composants : `Stats` (AC_Stats), `AnimalSenses` (AC_AnimalSenses), `StateTree` (StateTreeComponent, schema `StateTreeComponentSchema`, contexte = l'acteur lui-mĂȘme — PAS `StateTreeAIComponentSchema`, pour rester dĂ©tachĂ© de l'AIController et garder le StateTree simple). `AIControllerClass` = `BP_AnimalAIController`, `AutoPossessAI` = Placed in World or Spawned. Tunables instance-editable : WalkSpeed/RunSpeed, WanderRadius, IdleTime/GrazeTime/RestTime(Min/Max), AlertTime, FleeDistance (400-600 : distance de panique immĂ©diate si vu de prĂšs), SafeDistance (doit ĂȘtre largement > FleeDistance : distance Ă  atteindre pour se recalmer), HerdID (Name — animaux partageant le mĂȘme HerdID se relaient une alerte), DebugEnabled, Anim_Idle/Wander/Graze/Rest/Alert/Flee/Dead/Hit (AnimSequence, un jeu Ă  fournir par espĂšce). Fonctions clĂ©s : `MoveTo`/`StopMovementAnimal` (wrappers autour de l'AIController cachĂ©, utilisĂ©s par les tĂąches StateTree), `SetCurrentState` (met Ă  jour l'enum de debug ET dĂ©clenche `PlayStateAnimation` — lecture d'anim en **Single Node** via `SkeletalMeshComponent::PlayAnimation`, PAS d'AnimBlueprint/State Machine : suffisant pour un premier jet crĂ©dible sans blending, cf. §9), `GetThreatLocation` (position du joueur si vu, sinon source d'odeur, sinon position de l'animal), `BroadcastAlertToHerd`/`ReceiveHerdAlert` (alerte les autres membres du mĂȘme HerdID sans jamais lire une variable d'une AUTRE instance directement — le HerdID appelant est passĂ© en paramĂštre de fonction, voir piĂšge §9), `HandleDeath` (ragdoll `SetAllBodiesSimulatePhysics`, liĂ© Ă  `AC_Stats::OnDeath` via un Custom Event `OnAnimalDeathEvt` — PAS un binding direct sur une fonction classique, voir piĂšge §9), `CheckHealthChanged` (polling toutes les 0.2s de `AC_Stats::GetHealth` : une baisse de vie hors mort → `bWasHitRecently=true` ; prĂ©fĂ©rĂ© Ă  un binding direct sur le dispatcher `AC_Stats::OnDamaged`, qui provoque une erreur interne du compilateur Blueprint dans ce projet, voir piĂšge §9). │ ├── ST_AnimalBase.uasset → StateTree partagĂ© par toute la faune (schema `StateTreeComponentSchema`, contexte = `BP_AnimalBase`). États : `Normal` (groupe) {Idle→Wander→Graze→Rest→Idle, cycle via transitions `OnStateCompleted`/`NextState`}, `Alert` (hĂ©site `AlertTime` secondes puis retourne Ă  Idle si la menace n'est pas confirmĂ©e — deny-timeout), `Flee` (fuite), `Dead` (terminal). Transitions clĂ©s, TOUTES en conditions liĂ©es par binding direct au contexte (`bind_transition_condition_property_to_context`, propriĂ©tĂ©s imbriquĂ©es type `AnimalSenses.bCanSeePlayer` — inclure le prĂ©fixe `b` des boolĂ©ens, voir piĂšge §9), aucune n'exige de Blueprint condition custom : `Normal→Alert` (vue OU odorat OU alerte de horde, combinĂ©es en OR via `set_transition_condition_operand`), `Normal→Flee` et `Alert→Flee` (prioritĂ© High : vu ET distance ≀ FleeDistance — "trop prĂšs, panique immĂ©diate"), `Flee→Normal/Idle` (distance ≄ SafeDistance ET plus vu), transitions globales posĂ©es sur `Root` (s'appliquent depuis N'IMPORTE quel Ă©tat actif) : `→Flee` (prioritĂ© High, `bWasHitRecently` ET pas mort — coup reçu non-lĂ©tal) et `→Dead` (prioritĂ© Critical, `bIsDead`). │ └── Tasks/ → StateTree Tasks en Blueprint (parent natif `StateTreeTaskBlueprintBase`), chacune rĂ©utilisĂ©e par PLUSIEURS Ă©tats via ses propriĂ©tĂ©s instance-editable liĂ©es au contexte (`bind_task_property_to_context`) : │ ├── STT_SetAnimalState.uasset → Appelle `BP_AnimalBase::SetCurrentState(NewState)` puis termine immĂ©diatement (`FinishTask`). Un exemplaire par Ă©tat-feuille, seul `NewState` diffĂšre. │ ├── STT_Wait.uasset → Attend une durĂ©e alĂ©atoire entre `MinTime`/`MaxTime` (liĂ©s au contexte : IdleTimeMin/Max, GrazeTimeMin/Max, RestTimeMin/Max, ou AlertTime/AlertTime pour une durĂ©e fixe). NĂ©cessite `should_call_tick_only_on_events = true` sur la classe (sinon `ReceiveLatentTick` n'est jamais appelĂ© — propriĂ©tĂ© peu intuitive, voir piĂšge §9). │ ├── STT_MoveToRandomPoint.uasset → UtilisĂ© par `Wander`. Tire un point via `NavigationSystem::GetRandomReachablePointInRadius` autour de `HomeLocation` (capturĂ©e une fois au spawn), appelle `BP_AnimalBase::MoveTo`, termine en arrivant (ou aprĂšs 30s de timeout de sĂ©curitĂ©). │ └── STT_MoveAwayFromThreat.uasset → UtilisĂ© par `Flee`. À l'entrĂ©e : diffuse l'alerte Ă  la horde puis calcule un point de fuite (direction opposĂ©e Ă  `GetThreatLocation`, projetĂ© sur le NavMesh, distance ≈ SafeDistance×1.3). Se rĂ©-Ă©met automatiquement un nouveau point de fuite si l'animal arrive Ă  destination mais reste encore trop proche. │ │ EspĂšces (enfants de BP_AnimalBase, aucun nouvel asset graphique créé — rĂ©utilisent les meshes/anims │ dĂ©jĂ  prĂ©sents sous Content/Characters/Animal/DeerStagAndDoe/ et Content/Animations/DeerAndDoe/) : │ ├── BP_Deer_Stag.uasset → SK_DeerStag + jeu d'anims ANIM_DeerStag_*, HerdID "DeerHerd_A". │ └── BP_Deer_Doe.uasset → SK_DeerDoe + jeu d'anims ANIM_DeerDoe_*, HerdID "DeerHerd_A" (mĂȘme horde que le cerf → rĂ©activitĂ© croisĂ©e via BroadcastAlertToHerd/ReceiveHerdAlert). │ │ Une instance de chaque a Ă©tĂ© placĂ©e dans `Content/Maps/DevMap/MapDev1` avec un `NavMeshBoundsVolume` │ (`NavMeshBounds_Wildlife`, RuntimeGeneration = Dynamic — le mode par dĂ©faut `Static` ne (re)gĂ©nĂšre │ JAMAIS le NavMesh automatiquement, voir piĂšge §9). Étend le NavMesh existant du niveau (aucun n'existait │ avant cette session). │ ├── Door/ │ ├── Garage_Door/BP_Garage_door.uasset → Porte de garage interactable │ └── Simply_Door/BP_Simply_Door.uasset → Porte simple interactable │ ├── 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) │ ├── 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 ├── Interact_Interface.uasset → Interface d'interaction gĂ©nĂ©rique (racine de Systems/, Ă  distinguer de BPI_Interactable dans Inventory/Interfaces/) │ └── Weather/ ├── Tornado/BP_Tornado.uasset, NS_Tornado.uasset → Tornade dynamique (acteur + systĂšme Niagara), spĂ©cifique au projet (`NS_Tornado.uasset`, supprimĂ© du disque avant le 2026-09-13 sans commit, restaurĂ© depuis git le 2026-09-14 Ă  la demande de l'utilisateur) └── UltraDynamicSky/ → đŸ§© **Asset marketplace tiers complet** (~789 fichiers : Blueprints, matĂ©riaux, sons, textures de ciel/mĂ©tĂ©o dynamique). Ne pas modifier directement ; utiliser ses points d'extension documentĂ©s par le plugin (Weather_Presets, Climate_Presets, Sky_Modifiers). Structure interne : Blueprints/ (Enum, Functions, Occlusion, Sky_Modifiers, Sound, System, Tools, Utilities, Weather_Effects, Widgets), Materials/, Meshes/, Particles/, Sound/, Textures/, Maps/ (map de dĂ©mo du plugin). ``` --- ## 5. `Content/Data/` — Structures de donnĂ©es globales ```text Content/Data/ ├── DataTable/DT_Season.uasset → DataTable des saisons (mĂ©tĂ©o) │ ├── Enums/ │ ├── E_CoverD.uasset, E_WeaponType.uasset │ ├── E_WaponType.uasset → (2026-09-14, venu de `Characters/UEFN_Mannequin/Animations/Props/`) type d'arme lu par les choosers d'aim offset de `Systems/Aiming/` et par `S_CharacterPropertiesForAnimation.Weapon_Type` ; volontairement NON fusionnĂ© avec `E_WeaponType` │ ├── Enums/E_BodyPart.uasset │ └── Movement_enum/Weapon_Equip.uasset │ (⚠ Ă  ne pas confondre avec Data/Inventory_Data/Enumerations/ ci-dessous — deux emplacements d'enums coexistent) │ ├── Structure/Weather/ → Structs mĂ©tĂ©o (ST_Season, ST_WeatherZoneState, ST_Weather_Zone_CurentWeather/forecasts/_Data, ST_Zone_Influance) │ └── Inventory_Data/ → DonnĂ©es du systĂšme d'inventaire AGIS ├── DataAssets/ │ ├── AttachmentData/ → AttachmentData (base) + AttachmentData_AdvancedRifle, AttachmentData_Flashlight : configuration des attachements d'armes │ ├── ContainerGroupData/ → Un DataAsset par "groupe de containers" (Backpack BIG/SMALL, Box/Chest Storage, Vest_1/2, ExampleStorage
) : dĂ©finit la mise en page des slots d'un contenant │ └── InventoryData/ → Un DataAsset par inventaire prĂ©dĂ©fini (PlayerInventoryPart1/2, CardReader_Inventory, Generator_Inventory, Vehicle_Inventory) ├── Enumerations/ → Enums spĂ©cifiques AGIS : EAnimOverlayState, EBallDirections, EFourDirections/ETwoDirections, EInteractionType, EItemActions, ENestingRules, EPrintType, EReloadType, EServerVerificationType, ESlotAppearance, EVendorBuyOption └── Structures/ → Structs spĂ©cifiques AGIS ├── ItemDefaults.uasset → Struct CENTRALE dĂ©crivant un item (Name, etc.) — lue par WB_Item et par la logique de sĂ©lection rapide (Inventory_Player) ├── ItemInfo, SlotInfo, SlotAddress, SlotAppearance, SubItemInfo, RandomSubItem ├── ContainerInfo, ContainerAppearance ├── AttachmentInfo, EquipSlot_KeySettings/_OwnContainersSettings/_TextureSettings/_TitleSettings ├── ClientWidgetData, CombinedTexturesInfo, TextureInfo ├── CraftingSlotRowInfo, DragSounds, DebugPrint, FindResult, InspectCameraInfo, InteractCosmetics, ItemActorInfo, MenuActions └── SaveStructures/SaveData_Player, SaveData_Storages, Savedata_ItemActor → Structures de sauvegarde (non encore branchĂ©es Ă  un vrai systĂšme de save, voir §1.3 du systĂšme de mort) ``` --- ## 6. `Content/UI/` — Interfaces utilisateur ```text Content/UI/ ├── Inventory_UI/ → TOUTE l'UI de l'inventaire (socle AGIS + ajouts projet) │ ├── MaterialResources/ → MatĂ©riaux/Material Instances de fond des slots (MI_Background_*, M_RuntimeItemMaterial
) │ └── Widgets/ │ ├── WB_Container.uasset → Widget reprĂ©sentant un container (grille de slots) — contient SlotWidgets[] │ ├── WB_EquipSlot.uasset → Widget d'un slot d'Ă©quipement (arme/speed) — contient Container. Var `OwnContainersHost` (2026-09-04) : si dĂ©finie (WB_InventoryPart2), `OnContainerUpdate` ajoute les sous-containers de l'item Ă©quipĂ© (ex. grille du sac Ă  dos) dans ce widget via `AddContainerBelowPockets` au lieu de son propre `ContainersCanvas` interne. CĂąblĂ©e uniquement pour `EquipSlotBACKPACK` par `WB_InventoryScreen::InitializeWidgets`. │ ├── WB_InventorySlot.uasset → Widget d'un slot individuel dans une grille — expose "ItemWidget On Slot" │ ├── WB_Item.uasset → Widget reprĂ©sentant un item posĂ© dans un slot — expose "Item Defaults" (struct ItemDefaults) │ │ │ ├── InventoryMenu/ │ │ ├── WB_InventoryScreen.uasset → Widget racine de l'inventaire plein Ă©cran (contient InventoryPart1/InventoryPart2) │ │ ├── WB_InventoryPart1.uasset → Contient les 4 slots d'Ă©quipement (EquipSlotWEAPON, EquipSlotWEAPON2, EquipSlotSpeed1, EquipSlotSpeed2) + autres slots d'Ă©quipement (casque, gilet, gants, sac Ă  dos
) │ │ └── WB_InventoryPart2.uasset → Grille(s) d'inventaire principale(s) (PocketContainer + titre, dans `VerticalBox_0`). Fonction `Add Container Below Pockets(Container)` (2026-09-04) : insĂšre un WB_Container juste aprĂšs le bloc Pockets (`PocketContainer.GetParent().GetParent()`) — utilisĂ©e par `WB_EquipSlot` (sac Ă  dos) pour afficher ses slots supplĂ©mentaires sous les slots Pocket plutĂŽt que dans son propre canvas. │ │ │ ├── ItemActionsMenu/WB_ItemMenu.uasset, WB_GeneralButton.uasset → Menu contextuel d'actions sur un item │ │ │ ├── LootWidgets/ → FenĂȘtres de pillage, une par type de source (Human, Storage, Vendor, Vehicle, Generator, KeycardReader) hĂ©ritant de _WB_LootWidgetBASE ; LootingCrafting/ pour les stations de craft │ │ │ ├── MovableWindows/ → SystĂšme de fenĂȘtres dĂ©plaçables (_WB_Window_Base) : ItemInspect/ (inspection 3D d'un item), ItemInventory/ (fenĂȘtre d'inventaire flottante), WB_TitleBar_Window (barre de titre commune) │ │ │ └── Other/ │ ├── WB_QuickSelect.uasset → 🆕 Roue de sĂ©lection rapide (4 slots : Arme1/Arme2/Speed1/Speed2 + "Aucun"). RĂ©sout seule son Inventory_Player propriĂ©taire au Construct (GetOwningPlayerPawn → GetComponentByClass). Ouverte/fermĂ©e depuis Inventory_Player (touche V maintenue). Le graphe `INPUTS` d'Inventory_Player bascule aussi Input Mode/curseur/Ignore Look Input Ă  l'ouverture/fermeture (mĂȘme pattern que `ToggleInventory`) — fix du 2026-09-04. **Cause rĂ©elle du bug (2026-09-04, deuxiĂšme fix)** : IA_QuickSelectAGIS/IA_QuickEquipAGIS (touches V/B) n'Ă©taient mappĂ©es QUE dans `IMC_AGIS_Character` (Systems/Inventory/Other/Inputs/), un Input Mapping Context jamais ajoutĂ© au joueur nulle part dans le projet (seule une variable `Input Mapping Context` orpheline sur Inventory_Player y faisait rĂ©fĂ©rence, sans AddMappingContext associĂ©) — donc l'input V n'atteignait mĂȘme pas l'Enhanced Input, avant tout problĂšme de widget. Fix : V et B ajoutĂ©s directement dans `IMC_Sandbox` (Core/PlayerController/Input/), l'unique IMC rĂ©ellement ajoutĂ© au joueur (via SandboxCharacter_CMC/SetupInput). `IMC_AGIS_Character` reste inutilisĂ©e — Ă  nettoyer/fusionner un jour si confirmĂ© obsolĂšte. │ ├── WB_QuickGive.uasset → 🆕 (2026-09-05) Menu debug "Quick Give" (touche F9, mappĂ©e dans `IMC_Sandbox` via `IA_QuickGiveAGIS`). Champ Item ID + Amount + bouton "Give" gĂ©nĂ©rique, plus des boutons raccourcis "Give Bow"/"Give 20 Arrows". Fonction `GiveItem(ItemID, Amount)` : rĂ©sout l'`Inventory_Player` du joueur possĂ©dant (`GetOwningPlayerPawn`+`GetComponentByClass`), construit un item via `FL_AGIS::Create Item Structure`, trouve un slot libre via `Inventory__Main::Find Space For Item`, puis le pose via `Inventory__Main::Set Item On Container` — mĂȘme chaĂźne AGIS bas niveau que celle utilisĂ©e en interne par `Reload Graph` de `BP_Item_AdvancedRifle`. Toggle (crĂ©er/`AddToViewport`+InputMode GameAndUI vs `RemoveFromParent`+InputMode GameOnly) cĂąblĂ© dans `SandboxCharacter_CMC::EventGraph` sur `IA_QuickGiveAGIS` (Started), variable `QuickGiveWidget` sur le Character. Outil de test, pas une fonctionnalitĂ© shippable. │ ├── WB_YouDied.uasset → Écran "Vous ĂȘtes mort" (systĂšme de mort/respawn) │ ├── WB_ActionScreen, WB_InteractScreen, WB_InteractBall, WB_PickupDisplay → Feedback d'interaction/pickup au sol │ ├── WB_CombatHUD, WB_DisplayHUD, WB_WeaponAmmoInfo → HUD de combat/munitions │ ├── WB_InventoryBackground, WB_ItemInfo, WB_SlotTitle → ÉlĂ©ments visuels d'appoint │ └── WidgetTextures/ → IcĂŽnes des slots d'Ă©quipement (T_EquipSlot_*) et textures d'UI diverses │ ├── TextureUI/M_CharacterUI.uasset, RT_CharacterView.uasset → Rendu de la vue personnage dans l'UI (ex. Ă©cran d'inspection du personnage) │ └── Widgets/ → UI HORS inventaire ├── HUD/WB_HUD.uasset, WB_New_HUD.uasset, WB_New_InterfacePlayer.uasset ├── PauseMenu/WBP_PauseMenu.uasset, WBP_Options.uasset └── interaction/WB_Interact.uasset ``` --- ## 7. `Content/Items/`, `Content/PCG/`, `Content/Maps/`, `Content/VFX/`, `Content/Prop/` ```text Content/Items/ → Objets ramassables/Ă©quipables du jeu ├── BaseBlueprints/ │ ├── _BP_ItemBase.uasset → Blueprint BASE de tout item (racine de hiĂ©rarchie). Event `Custom|UpdateCollisionandPhysics` (appelĂ© Ă  l'attache/au drop) bascule aussi la rĂ©ponse au canal `Visibility` (Ignore quand Ă©quipĂ© / Block quand lĂąchĂ©) du mesh principal ET de tous les `WidgetComponent` de l'item (ex. `AmmoUI`) — fix du 2026-09-04 : un item Ă©quipĂ© bloquait les BoxTrace (canal Visibility) du systĂšme de grimpe/parkour (`AC_ClimbingComponent`), empĂȘchant de grimper une fois une arme en main. │ ├── BP_Item_HoldableBase.uasset → Base des items tenables en main. ImplĂ©mente `BPI_HoldableItem::On Item Attached(ShouldHold)` (seul signal fiable du VRAI Ă©tat main/pas-en-main) et diffuse ce boolĂ©en via son propre dispatcher `OnHeldStateChanged(bIsHeld)` (2026-09) — c'est CE dispatcher (et non `_BP_ItemBase::OnOwnerChanged`, qui se dĂ©clenche aussi pour un simple rangement en inventaire) qu'`AC_Weapon` Ă©coute pour piloter Equip/Unequip, voir §4.3. │ ├── BP_Item_Armor_Base.uasset → Base des items d'armure/Ă©quipement portĂ© │ └── BP_Item_Skeletal_Base.uasset → Base des items avec mesh squelettal │ ├── BP_Item_AdvancedRifle / _Backpack_Camper / _Backpack_Sport / _BodyArmor / _Flashlight / │ _Gloves / _Helmet / _KevlarVest / _LightVest / _Siren / _Bow.uasset → Blueprints d'items "portĂ©s" (racine d'Items/). `BP_Item_Bow` (hĂ©rite `BP_Item_HoldableBase`) porte un composant `ItemMesh_STATIC` (mesh Fab `survival_kit_bow_fixed` — voir §8 pour l'incident de corruption/rĂ©-import du 2026-09-05 —, socket `ArrowSocket` ajoutĂ© pour l'encoche — position approximative, Ă  ajuster visuellement), Ă©quipĂ© sur le socket `weapon_l` (Spine `SpineRifle`, rĂ©utilisĂ© faute de socket dĂ©diĂ©). `BP_Item_AdvancedRifle` a reçu le mĂȘme composant `AC_Weapon` (2026-09-05, retrofit de validation) pour l'Ă©quipement/dĂ©sĂ©quipement gĂ©nĂ©rique ; sa cadence de tir reste pilotĂ©e par sa propre macro interne `Weapon|FiringGate` (non branchĂ©e sur `AC_Weapon.CanUse()` — dette technique documentĂ©e, voir §9). │ │ **Gameplay de l'arc** (`BP_Item_Bow`, 2026-09-05/06) — override des hooks existants `Custom|PrimaryUse`/`StopPrimaryUsing` de `_BP_ItemBase`, sans nouveau systĂšme d'input : `PrimaryUse` vĂ©rifie `AC_Weapon->CanUse()` ET `CountArrows() >= 1` (fonction propre, voir §1.3 pour `Owner Inventory`) avant de dĂ©marrer la tension (horodatage `DrawStartTime`, pas de Timeline), puis joue `Draw Montage` (`AM_Bow_Draw`, voir ci-dessous) sur le mesh du personnage. `StopPrimaryUsing` calcule la puissance (`Clamp((Now-DrawStartTime)/MaxDrawTime, MinDrawPower, 1.0)`), joue `Fire Montage` (`AM_Bow_Fire`), appelle `ConsumeArrow()` et, si rĂ©ussi, spawn `BP_Projectile_Arrow` au socket `ArrowSocket` avec vitesse/dĂ©gĂąts scalĂ©s par la puissance, puis appelle `AC_Weapon->TryUsePrimary()`. │ **`ConsumeArrow()` — fix du 2026-09-06** : retrouve le stack "Arrow" via `BOTH|FindItem`, puis rĂ©duit son montant via `Inventory__Main::AddItemAmount(ItemAddress, -1)` — une opĂ©ration purement sur les DONNÉES de l'inventaire, par adresse, ne nĂ©cessitant aucun acteur monde. L'implĂ©mentation d'origine appelait `Utilities|GetItemActor` (macro `ML_InventoryMacros::Get Item Actor`) puis `SERVER|ReduceAmount` sur cet acteur — ce qui Ă©choue TOUJOURS silencieusement pour un item empilĂ© passif comme "Arrow" qui, tant qu'il n'est pas Ă©quipĂ©/lĂąchĂ© dans le monde, n'a jamais d'acteur spawnĂ© (`GetItemActor` retourne systĂ©matiquement invalide). SymptĂŽme observĂ© : le tir semblait dĂ©marrer (logs "TIR EN COURS") mais aucune flĂšche ne partait et aucune munition n'Ă©tait consommĂ©e. Voir aussi §9 pour la mĂȘme leçon appliquĂ©e Ă  toute consommation de stock passif (ne jamais utiliser `GetItemActor`+fonction-sur-acteur pour un item qui n'est pas garanti d'ĂȘtre spawnĂ© dans le monde — utiliser `Inventory__Main::AddItemAmount` par adresse Ă  la place). │ **Animations de l'arc** (2026-09-06) — `AM_Bow_Draw`/`AM_Bow_Fire.uasset` (`Content/Items/`) sont des `AnimMontage` Ă  piste unique gĂ©nĂ©rĂ©s depuis `standingdrawarrow_UE`/`standingaimrecoil_UE` (`Content/Animations/humain/Armed_mov/Bow/`), assignĂ©s au **slot `UpperBody`** (voir `SandboxCharacter_CMC_ABP` ci-dessous — PAS `DefaultSlot`). Variables `Draw Montage`/`Fire Montage` sur `BP_Item_Bow`, jouĂ©es via un nƓud natif `Animation|Montage|PlayMontage` sur le mesh du personnage (`Cast Owner Character → Character → GetMesh`). Appel direct (pas de variante Multicast `...CLIENTS` comme pour `PlayReloadMontageCLIENTS` du fusil) — suffisant en PIE solo ; Ă  revoir si une rĂ©plication multijoueur de l'anim est nĂ©cessaire plus tard. │ **IntĂ©gration Ă  la locomotion (2026-09-06)** — un montage plein-corps sur `DefaultSlot` remplaçait TOUT le squelette (jambes comprises) par la pose figĂ©e de l'animation source, ce qui semblait correct Ă  l'arrĂȘt (la pose "debout" du montage coĂŻncide avec Motion Matching Ă  l'arrĂȘt) mais cassait la marche/course/crouch (jambes figĂ©es dans la pose d'arc "debout" enregistrĂ©e). Fix : ajout d'un **`Slot 'UpperBody'`** + nƓud **`Layered Blend Per Bone`** dans l'`AnimGraph` de `SandboxCharacter_CMC_ABP`, avec un filtre de branche sur l'os `spine_01` (BlendDepth=-1 → toute la branche colonne+bras+tĂȘte, jambes/bassin exclus) — voir §9 pour le dĂ©tail technique (le skeleton `SK_UEFN_Mannequin` avait dĂ©jĂ  un Blend Profile "UpperBody" masquant exactement les mĂȘmes os, confirmant que `spine_01` est le bon point de coupure, mais ce Blend Profile n'est pas directement utilisable par ce nƓud en 5.8 — filtre de branche manuel utilisĂ© Ă  la place). Le `DefaultSlot` existant (plein corps) n'est pas touchĂ©, rĂ©utilisable tel quel pour de futures actions plein-corps. Motion Matching, Pose Search, Aim Offset (`Enable_AO`/`Get_AOValue`), Foot/Leg IK et Orientation Warping — tous dĂ©jĂ  prĂ©sents dans cet AnimBP — continuent de piloter le bas du corps et la visĂ©e sans changement. ├── Attachments/BP_Item_MagazineBase, BP_Item_RifleFlashlight, BP_Item_Suppressor.uasset → Attachements d'armes ├── ItemObjects/BPI_MergeableItemObject, ItemObject__BASE, ItemObject_ConsumableBASE, ItemObject_Magazine.uasset → Objets "monde" associĂ©s aux items (empilables, consommables, munitions) │ ├── Ammo/ (Arrow), Weapon/ (Base_Bow, Base_knife), Tool/ (saucepan), Water/ (water_bottle), │ Food/ (Red_Apple, meat, cooked_Meat, Burnt_Meat), Resource/ (Stick, Stone) │ → Chaque sous-dossier contient les assets (mesh/matĂ©riau/texture/Thumbnail) d'un item ; les Blueprints correspondants sont soit Ă  la racine d'Items/, soit dans Resources/. `Weapon/Base_Bow/Thumbnail` et `Ammo/Arrow/Thumbnail` ne contenaient que des icĂŽnes prĂ©parĂ©es Ă  l'avance (2026-09-04) — item "Bow" et "Arrow" ajoutĂ©s dans DT_Items pour les utiliser (voir §5). │ ├── Resources/ → Assets 3D (mesh/matĂ©riau/texture) groupĂ©s par Ă©quipement portĂ©, + cas particuliers │ ├── Backpack_Camper/, Backpack_Sport/, BodyArmor/, Gloves/, Helmet/, KevlarVest/, LightVest/, Rifle/ │ ├── _Others/ → Assets des petits objets (Keycard, Log, Meat, AmmoBox, Battery, Flashlight, FuelCanister, GoldIngot/GoldOre, Headphone, MoneyBag, WaterBottle) │ └── ABP_SkeletalEquippables.uasset → Anim Blueprint partagĂ© par les items squelettaux Ă©quipĂ©s │ └── ItemTextures/ → Textures d'icĂŽnes/inventaire communes Ă  tous les items (T_*) Content/PCG/ → GĂ©nĂ©ration procĂ©durale de contenu (plugin PCG) ├── Road/ │ ├── PCG_Road.uasset → Graphe PCG gĂ©nĂ©rant la route procĂ©durale (matĂ©riaux vieillis/mousse/humiditĂ©, potholes via GeometryScript) │ ├── BP_AbandonedRoad.uasset → Acteur portant le graphe PCG │ ├── M_Road.uasset, ST_Road_data.uasset, EM_Road_Type.uasset → MatĂ©riau, struct de donnĂ©es et enum de types de route ├── Vegetation/TreeTest.uasset → Graphe PCG de placement de vĂ©gĂ©tation (arbres, gĂ©nĂ©rĂ©s via PVE pour la route) └── test/NewPCGGraph1.uasset → Graphe de test/brouillon Content/Maps/DevMap/ ├── MapDev1.umap → đŸ—ș Map de dĂ©veloppement PRINCIPALE (GameDefaultMap / EditorStartupMap, voir Config/DefaultEngine.ini) ├── GM_Dev.uasset → GameMode utilisĂ© sur MapDev1 (hĂ©rite directement de GameModeBase, indĂ©pendant de GM_Sandbox/Gamemode_AGIS) ├── pcg_Test_Dev.umap → Map de test PCG └── PCG_Test_Dev_HLODLayer_*, Untitled_HLOD0_Instancing.uasset → Assets HLOD gĂ©nĂ©rĂ©s pour les maps de test Content/VFX/ ├── Firetrail/BP_FireTrail.uasset, Effects/P_BulletTrail.uasset, Materials/M_BulletTrail.uasset → TraĂźnĂ©e de balle └── MI_MuzzleFlash, M_MuzzleFlash, MuzzleFlash, P_MuzzleFlash → Effet de tir (bouche de canon) ├── M_Blood.uasset, T_Blood.uasset → Effet de sang └── crosshair.uasset, hitmarker.uasset → ÉlĂ©ments de HUD de tir Content/Prop/Wooden_Door/ → Prop de porte en bois (mesh + matĂ©riaux), utilisĂ© par les BP de porte interactable ``` --- ## 8. Assets tiers / bibliothĂšques (peu ou pas de logique de gameplay) Ces dossiers contiennent des assets achetĂ©s/importĂ©s (Marketplace, Fab/Quixel Megascans, Megaplant, packs d'animation mocap). Ils sont volumineux (des centaines de fichiers) et **ne sont volontairement pas dĂ©taillĂ©s fichier par fichier** ici — voir §10 pour la rĂšgle sur quand les documenter. ```text Content/Animations/ → Clips de mocap tiers : DeerAndDoe/, Fox/, Wolf/, humain/ (Armed_mov, Avoid, Carrying, Cover, Effect_Animation, INteraction, Prone, Push, SwimmingAnimation
) Content/Characters/ → Meshes/matĂ©riaux/textures des personnages et animaux (Animal/DeerStagAndDoe|Fox|Wolf, UEFN_Mannequin/ avec ses donnĂ©es de Motion Matching : AimOffset, Crouch, Idle, Jump, MotionMatchingData/ [Channels, Databases, Normalization_Sets, Schemas], Poses, Run, Slide, Sprint, Traversal, Walk, Rigs, Materials, Meshes, Textures) Content/Fab/ → Assets Fab/Quixel Megascans : MaterialFunctions/, MaterialParameterCollection/, Materials/ (Standard/VT), Megascans/Plants/ (Common_Hemp_Nettle, Wild_Grass ×2), Megascans/Surfaces/ (Damaged_Asphalt, Dirt_Ground, Forest_Floor), Textures/ (Standard/VT) Survival_Kit_-_Bow/ et CC0_-_Wooden_Arrow/ (StaticMesh + Textures + MI_SurvivalBow/MI_WoodenArrow, utilisĂ©s par les items Bow/Arrow, voir §4.4) — ⚠ ces deux imports glTF avaient leurs slots de matĂ©riau pointant vers un `MaterialInstanceDynamic` transitoire (jamais sauvegardable, cause d'Ă©checs d'auto-save « Illegal reference to private object »). CorrigĂ© le 2026-09-04 en crĂ©ant de vraies `MaterialInstanceConstant` (parent `/InterchangeAssets/gltf/Substrate/M_GLTF`) avec les mĂȘmes textures. Si un futur import Fab/glTF Ă©choue Ă  l'auto-save de la mĂȘme façon, vĂ©rifier le(s) slot(s) de matĂ©riau du StaticMesh importĂ© pour ce mĂȘme symptĂŽme. ⚠ **2026-09-05** : aprĂšs une coupure de courant, `survival_kit_bow.uasset` (StaticMesh) s'est retrouvĂ© avec 0 vertex/0 triangle/bounds nuls (asset vidĂ©, probablement une sauvegarde tronquĂ©e en cours d'Ă©criture) — l'arc n'avait plus de mesh visible ni de collision en jeu. Diagnostic : toujours vĂ©rifier `mesh.get_num_vertices(0)` / `get_bounds()` aprĂšs une fermeture anormale de l'Ă©diteur sur un asset suspect avant de chercher ailleurs. Fix : rĂ©-import depuis la source Fab d'origine (chemin retrouvĂ© via `mesh.get_editor_property("asset_import_data").extract_filenames()`, cache `%LOCALAPPDATA%/Temp/FabLibrary//`) vers un dossier scratch, puis renommage vers `.../StaticMeshes/survival_kit_bow_fixed` (le nom d'origine `survival_kit_bow` n'a pas pu ĂȘtre rĂ©utilisĂ© : `delete_asset`/`consolidate_assets` Ă©chouaient silencieusement sur l'asset corrompu malgrĂ© 0 rĂ©fĂ©renceur restant — laissĂ© orphelin en l'Ă©tat, sans danger). Toutes les rĂ©fĂ©rences (`BP_Item_Bow::ItemMesh_STATIC`, `DT_Items` ligne "Bow" → `Spawner Preview Mesh`) repointĂ©es vers `survival_kit_bow_fixed`. Le socket `ArrowSocket` a dĂ» ĂȘtre recréé (perdu avec l'ancien asset). Content/Megaplant_Library/ → VĂ©gĂ©tation Megaplant : Plant_Bilberry/, Tree_European_Aspen/, Tree_Hornbeam/ (chacun avec Instances/, Materials/, Textures/) Content/Audio/Foley/ → **(2026-09-08)** SystĂšme de sons de pas/foley du sample Game Animation Sample : `AC_FoleyEvents` (ActorComponent, ajoutĂ© Ă  `SandboxCharacter_Mover`, voir §8.2), `S_FoleyEventParams`, `DefaultFoleyEventAudioBank`. Reste du dossier `Content/Audio/` : sons/bancs audio divers du sample, non branchĂ©s sur le gameplay AGIS. Content/MetaHumans/ et Content/Characters/Echo|Paragon|UE4_Mannequin|UE5_Mannequins/ → **SUPPRIMÉS le 2026-09-13** (nettoyage) : assets MetaHuman et personnages de dĂ©monstration du sample Game Animation Sample (~2,6 Go), utilisĂ©s uniquement par les BP de dĂ©mo `RetargetedCharacters/BP_*` (supprimĂ©s aussi). Copie de sauvegarde : `E:\projet\ProjectFv1_backup_migration_2026-09-13\nettoyage_etape1_demo\`. `UEFN_Mannequin` reste le seul squelette de personnage humanoĂŻde du projet. Content/Levels/, Content/Widgets/, Content/dev_map → **SUPPRIMÉS le 2026-09-14** : dĂ©mo du sample Game Animation Sample (kit de blockout LevelPrototyping, widgets et map de dĂ©mo). Seul lien avec le projet : le cast vers `LevelBlock_Traversable` dans `Systems/Mover/AC_TraversalLogic`, retirĂ© (voir §4.2.1). Sauvegarde : commit git `6eb7516`. Content/Thumbnails/ → Miniatures gĂ©nĂ©rĂ©es pour la Content Browser Content/Misc/ → SandboxAnimCurveCompressionSettings.uasset (rĂ©glages de compression d'anim) Content/__ExternalActors__/ → ⚙ GĂ©nĂ©rĂ© automatiquement par World Partition (donnĂ©es par-acteur des maps, ex. LocomotionAnimPack). Content/__ExternalObjects__/ → ⚙ GĂ©nĂ©rĂ© automatiquement par World Partition (objets externes liĂ©s aux maps). → Ces deux derniers dossiers ne doivent JAMAIS ĂȘtre Ă©ditĂ©s ou documentĂ©s Ă  la main : leur contenu suit automatiquement les maps et les acteurs qu'elles contiennent. ``` ### 8.1 Import du sample Epic "Game Animation Sample" (2026-09-07/08) L'utilisateur a importĂ© le contenu brut du sample officiel Epic **Game Animation Sample** directement dans `Content/Blueprints/` (structure de dossier d'origine du sample), dans le but de disposer d'une rĂ©fĂ©rence complĂšte/fonctionnelle du framework "Sandbox Character" (voir §4.2) pendant que sa migration vers le plugin `Mover` Ă©tait en cours. Ce sample est la source originelle du framework `Systems/Blueprints/` dĂ©jĂ  prĂ©sent dans ce projet : l'import a donc créé **95 collisions de nom exactes** (mĂȘmes noms : `SandboxCharacter_CMC`, `AC_TraversalLogic`, `BP_MovementMode_Walking`, `E_Gait`, `IMC_Sandbox`, tous les `IA_*` gĂ©nĂ©riques, etc.) entre le contenu fraĂźchement importĂ© et les versions dĂ©jĂ  personnalisĂ©es de ce projet. **Politique appliquĂ©e (dĂ©cision utilisateur explicite)** : garder la version du projet partout, ne conserver du nouvel import que le contenu rĂ©ellement nouveau (RetargetedCharacters, SmartObjects/AI supplĂ©mentaires, Ragdoll, Audio/Foley, MetaHumans, Characters de dĂ©mo — voir §4.2/§8). Les 95+17 doublons (17 supplĂ©mentaires dĂ©couverts aprĂšs coup sous `Content/Input/` et `Content/Data/`, dont `IMC_Sandbox` lui-mĂȘme) ont Ă©tĂ© fusionnĂ©s via `EditorAssetLibrary.consolidate_assets()` (redirecteur automatique + suppression du doublon) quand c'Ă©tait possible, ou supprimĂ©s directement (`delete_asset`) quand rien ne rĂ©fĂ©rençait plus la copie importĂ©e. Le contenu unique restant a ensuite Ă©tĂ© dĂ©placĂ© vers son emplacement dĂ©finitif (`Content/Systems/Blueprints/`, `Content/Core/PlayerController/Input/`) via `AssetToolsHelpers.get_asset_tools().rename_assets()` (dĂ©placement avec réécriture de toutes les rĂ©fĂ©rences, pas un dĂ©placement de fichier brut). **Reste Ă  faire / connu (2026-09-08)** : - `Content/Systems/Mover/SmartObjects/AC_SmartObjectAnimation` (anciennement `Content/Blueprints/SmartObjects/`, dĂ©placĂ© le 2026-09-14) : un doublon n'a **pas** pu ĂȘtre fusionnĂ©/supprimĂ© (l'outil `consolidate_assets` fait planter l'Ă©diteur sur cet ActorComponent prĂ©cis, voir §9) — laissĂ© en l'Ă©tat intentionnellement, sans impact gameplay (fonctionnalitĂ© SmartObject annexe). - ⚠ *ObsolĂšte depuis le 2026-09-13 (voir §8.2)* — `Content/Blueprints/` contenait alors de nombreux fichiers `ObjectRedirector` (rĂ©sidus de `consolidate_assets`) — passer un **"Fixup Redirectors" manuel** (clic droit sur le dossier dans le Content Browser) quand pratique ; aucune API Python trouvĂ©e pour cette opĂ©ration, et forcer une suppression brute des redirecteurs risquerait de casser des rĂ©fĂ©rences logicielles (soft references) non encore réécrites. ### 8.2 Migration `Project_F` → `ProjectFv1` (2026-09-13) — incident et Ă©tat aprĂšs rĂ©paration `E:\projet\Project_F` est un **autre dĂ©pĂŽt git** (projet Game Animation Sample nettoyĂ©, oĂč l'utilisateur a dĂ©veloppĂ© un systĂšme de visĂ©e). Le 2026-09-13 (~22:00–22:12), l'Ă©diteur de `Project_F` a migrĂ© **3073 packages** directement dans `ProjectFv1/Content` **pendant que l'Ă©diteur de ProjectFv1 Ă©tait ouvert** (preuve : `Project_F/Saved/Logs/Project_F.log`, lignes `LogSavePackage: Moving ... to E:/projet/ProjectFv1/Content/...`). ⚠ Ne jamais migrer vers ce projet avec son Ă©diteur ouvert. DĂ©gĂąts constatĂ©s : 1449 assets suivis par git de `Characters/UEFN_Mannequin/` Ă©crasĂ©s (animations + chooser tables, liĂ©es dĂ©sormais aux notifies/enums de `Content/Blueprints/`), 782 fichiers `Systems/Weather/UltraDynamicSky/` Ă©crasĂ©s (widgets mĂ©tĂ©o sans leurs structs `ST_Weather*` → 149 erreurs), `Content/Blueprints/` recréé comme copie complĂšte (137 vrais assets) du framework de `Systems/Blueprints/`. Les enums/structs des deux copies DIVERGENT (ex. `E_MovementDirection` : `F/B/LL/LR/RL/RR` vs `Forward/Back/left/
`, `E_Gait` sans Prone/Swimming) : ne JAMAIS les fusionner aveuglĂ©ment. RĂ©paration (dĂ©cisions utilisateur) : - **MĂ©tĂ©o** : les 782 fichiers UltraDynamicSky restaurĂ©s depuis le commit `d29748b` (LFS). Versions migrĂ©es sauvegardĂ©es dans `E:\projet\ProjectFv1_backup_migration_2026-09-13\`. - **Anims/choosers migrĂ©s conservĂ©s**. Contexte (`ContextData`) des 7 chooser tables CMC/traversal remis aux valeurs du commit : `CHT_PoseSearchDatabases(+_Dense/_Sparse/_ExtremeSparse)` et `CHT_CMCCharacterAnimations` → `Systems/Blueprints/SandboxCharacter_CMC_ABP` (+ `S_ChooserOutputs` Systems) ; `CHT_TraversalMontages_CMC/_Mover` → `Systems/Blueprints/Data/S_TraversalChooserInputs/Outputs`. Lignes Bow du chooser Dense perdues (voir §1.3). - **Structs strictement identiques fusionnĂ©es** (`consolidate_assets`, redirecteurs laissĂ©s) : `Content/Blueprints/Data/S_CHT_TraversalMontages_IN/OUT` → `Systems/.../S_TraversalChooserInputs/Outputs`, `Content/Blueprints/Data/S_ChooserOutputs` → `Systems/.../S_ChooserOutputs`. Pins de `Content/Blueprints/AC_TraversalLogic` (traversal du Mover) rebranchĂ©es. - **Doublon GASP du personnage CMC supprimĂ©** : `Content/Blueprints/SandboxCharacter_CMC` + `_ABP`. RĂ©fĂ©rences de dĂ©mo redirigĂ©es vers `/Game/SandboxCharacter_CMC` (depuis dĂ©placĂ© dans `/Game/Core/Character/`) / l'ABP Systems (`PC_Sandbox.Characters`, `AC_PreCMCTick`, `GM_Sandbox.PawnClasses_Soft`, `EUW_PawnOverrideButton.Object`, variable locale de `BP_NotifyState_EarlyTransition`). (`Content/Widgets/` a Ă©tĂ© supprimĂ© le 2026-09-14.) - `STT_PlayAnimFromBestCost` (Systems) pointe dĂ©sormais vers `Systems/Blueprints/SmartObjects/AC_SmartObjectAnimation`. - `Config/DefaultGameplayTags.ini` : ajout des tags du sample `Foley.Event.*` et `SmartObject.ObjectType.Player/Bench` (manquants → avertissements massifs + StateTree SmartObject non liable). Contenu du framework du sample conservĂ© volontairement (dĂ©placĂ© le 2026-09-14, voir §4.2.1 et « Convergence partielle » ci-dessous) : - `Systems/Aiming/` (`ABP_AimingMaster`, `ABP_AimingMaster_UEFN`, `CH_AO`, `CH_Base_AO_Animechooser`) → systĂšme de visĂ©e/aim offset dĂ©veloppĂ© dans `Project_F`, utilisĂ© par `SandboxCharacter_Mover_ABP`. - `Systems/Mover/SandboxCharacter_Mover` / `_ABP` / `_Ragdoll` → personnage alternatif plugin Mover (+ `Systems/Mover/GM_Sandbox`/`PC_Sandbox` ; `dev_map` de dĂ©mo supprimĂ© le 2026-09-14). - le reste du framework dupliquĂ©, dans `Systems/Mover/` (AC_TraversalLogic, BPI_*, Data/, Cameras/
) ; ses notifies restent dans `Content/Blueprints/AnimNotifies/` (liĂ©s Ă  1278 animations). Chooser tables toujours liĂ©es Ă  ce framework : `CHT_PoseSearchDatabases_Relaxed`, `CHT_MoverCharacterAnimations_PoseMatch`, `CHT_GetUpMontages`, `CHT_CharacterInteractionPSDs`. **Convergence partielle (2026-09-14)** : - **Enums fusionnĂ©s** : les 17 enums du sample de `Content/Blueprints/Data|Cameras|AnimNotifies/` (`E_Gait`, `E_Stance`, `E_MovementMode`, `E_MovementState`, `E_MovementDirection`, `E_MovementDirectionBias`, `E_RotationMode`, `E_AnalogStickBehavior`, `E_ExperimentalStateMachineState`, `E_RagdollInjuryState`, `E_TraversalActionType`, `E_CameraMode`, `E_CameraStyle`, `E_EarlyTransition_Condition`, `E_EarlyTransition_Destination`, `E_FoleyEventSide`, `E_TraversalBlendOutCondition`) ont Ă©tĂ© fusionnĂ©s dans leurs jumeaux de `Systems/Blueprints/` (17 redirecteurs laissĂ©s Ă  l'ancien emplacement). Valeurs propres au sample ajoutĂ©es en fin d'enum cĂŽtĂ© projet (voir §4.2) et pins/switchs de la chaĂźne Mover remappĂ©s dessus. Interfaces et structs Systems enrichies en consĂ©quence (§4.2). - **RĂ©parations consĂ©cutives** (piĂšge dĂ©crit en §9) : variables d'enum vidĂ©es retypĂ©es et liens rebranchĂ©s dans `SandboxCharacter_Mover`, `SandboxCharacter_Mover_Ragdoll`, `SandboxCharacter_Mover_ABP` (restaurĂ© depuis sauvegarde puis remappĂ©), `BP_AnimNotify_TriggerRagdoll`, `AnimNotifies/BP_NotifyState_EarlyTransition` et `BP_NotifyState_MontageBlendOut` (liens comparĂ©s un Ă  un Ă  leurs jumeaux Systems). Chaque asset validĂ© par rechargement de son package. - **ArrĂȘt de la convergence (dĂ©cision utilisateur)** : Ă  cause de ce piĂšge, le reste de `Content/Blueprints/` (Mover, Aiming, AC/BPI/structs/notifies/camĂ©ras du sample) n'est PAS fusionnĂ©. Il a Ă©tĂ© seulement dĂ©placĂ©, sans fusion, le 2026-09-14 (voir §4.2.1) ; les doublons restants sont une dette connue. **Restauration Motion Matching (2026-09-14, dĂ©cision utilisateur)** : un audit des 189 donnĂ©es Motion Matching modifiĂ©es depuis `d29748b` (comparaison des rĂ©fĂ©rences `/Game/...` des blobs git avant/aprĂšs) a trouvĂ© 7 assets dĂ©gradĂ©s par la migration, tous restaurĂ©s depuis `d29748b` (toutes leurs rĂ©fĂ©rences existent encore) : `CHT_PoseSearchDatabases_Dense` (19 bases perdues : Bow, Prone, nage, cover accroupi, Push ; colonnes `E_CoverD`/`Weapon_Equip`), `Channels/PSC_Traversal_Head` et `_Pos` (pointaient sur la BPI du sample au lieu de `Systems/Blueprints/BPI_SandboxCharacter_ABP`), `Schemas/PSS_Default` et `PSS_Idle` (table miroir `Rigs/MDT_UEFN_Mannequin` perdue), `Normalization_Sets/PSN_Relaxed_All` (le Mover y perd `PSD_SM_Mover_TraversalTransitions`), `Databases/Dense/PSD_Dense_Stand_Idles` (mesh d'aperçu). Seul autre Ă©cart trouvĂ©, conservĂ© : `Traversal/CHT_TraversalMontages_Mover` (montages Climb Relaxed → Neutral, chooser du Mover). État vĂ©rifiĂ© en fin de rĂ©paration : passe de compilation complĂšte, **435 Blueprints, 0 erreur** (non encore testĂ© en PIE). Dettes connues non liĂ©es Ă  la migration : tags `Attachments.*` (§2.1), animations AGIS sans squelette (voir §9 : `Systems/Inventory/Other/Animations/DeathAnim_AGIS` et `Rifle/*` — compatibles Ă  100 % avec `SK_UEFN_Mannequin`, Ă  assigner Ă  la main dans l'Ă©diteur ; `Jog/`, `WALK/`, `TurnInPlace/`, `AIM_Rifle_Idle_ADS` inutilisĂ©es et incompatibles), « Unknown structure » au chargement de `Systems/Blueprints/BPI_SandboxCharacter_Pawn` (antĂ©rieur au 2026-09-07). --- ## 9. Notes pour les IA : piĂšges connus de l'outillage 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 : - **`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. - Appeler une fonction Blueprint **prĂ©existante** (créée dans une session antĂ©rieure/par le plugin marketplace) sur un **autre** Blueprint peut Ă©chouer silencieusement selon la mĂ©thode utilisĂ©e. PrivilĂ©gier l'accĂšs direct aux propriĂ©tĂ©s (`member_get`, fiable) plutĂŽt que l'appel de fonction cross-Blueprint quand c'est possible ; sinon tester `add_function_call_on_variable` et vĂ©rifier le rĂ©sultat via `get_node_pins`/`get_nodes_in_graph`. - Écrire une valeur littĂ©rale sur un pin de type `Text`, `Object` ou `Class` via `set_node_pin_value` Ă©choue souvent **silencieusement Ă  l'affichage** (`get_node_pins` renvoie toujours `default_value: ""`) mĂȘme quand l'assignation a rĂ©ellement fonctionnĂ© — vĂ©rifier via une **compilation** (erreurs de compilation manquantes = probablement OK) plutĂŽt que via une relecture du pin. - **Toujours compiler ET sauvegarder** un Blueprint aprĂšs modification (`BlueprintEditorLibrary.compile_blueprint` + `EditorAssetLibrary.save_loaded_asset`), puis **tester en PIE** et lire les logs (`EditorToolset.LogsToolset.GetLogEntries`, filtrer sur `"Blueprint Runtime Error"`) pour dĂ©tecter les erreurs Ă  l'exĂ©cution qu'une compilation rĂ©ussie ne rĂ©vĂšle pas (ex. accĂšs Ă  un Ă©lĂ©ment de tableau hors limites). - Le clavier cible du jeu est **AZERTY** : vĂ©rifier les mappings de touches existants (`IMC_Sandbox`, `IMC_AGIS_Character`, `IMC_AGIS_InventoryTab`) avant d'assigner une nouvelle touche, et choisir des touches physiquement identiques entre QWERTY/AZERTY. **PiĂšges du toolset `editor_toolset.toolsets.blueprint.BlueprintTools`** (create_node/connect_pins/write_graph_dsl/get_node_infos, utilisĂ© depuis le systĂšme d'armes du 2026-09-05) : - La **DSL `write_graph_dsl`** casse sur un `type_id` contenant une parenthĂšse fermante suivie d'autres caractĂšres (ex. `BOTH|GetItem(copy)ByUID` Ă©choue avec "does not exist" car le tokenizer coupe au premier `)`) ; un `type_id` se terminant PAR une parenthĂšse fonctionne (`Utilities|Array|Get(acopy)`). Dans ce cas, construire le nƓud Ă  la main (`create_node`/`connect_pins`) plutĂŽt que via la DSL. - Un `type_id` retournĂ© par `find_node_types` (ex. `Variables|Default|GetACWeapon`) peut diffĂ©rer du `type_id` affichĂ© ensuite par `get_node_infos` pour CE nƓud (ex. `|GetAC_Weapon`, avec underscore) : toujours utiliser la chaĂźne de `find_node_types` pour **crĂ©er**/rĂ©fĂ©rencer un nƓud dans la DSL, jamais celle affichĂ©e aprĂšs coup par `get_node_infos`. - Éditer une propriĂ©tĂ© d'un **composant SCS hĂ©ritĂ©** (ex. changer le mesh d'un `StaticMeshComponent` dĂ©fini dans une classe parente, depuis le Blueprint enfant) : `SubobjectDataBlueprintFunctionLibrary.get_object`/`get_associated_object` renvoient le **template du PARENT** (le modifier casse le parent pour toutes ses classes filles !). Utiliser `get_object_for_blueprint(data, child_blueprint)` qui crĂ©e correctement l'override propre Ă  l'enfant. - ItĂ©rer un `Array[SubobjectDataHandle]` avec `for h in handles:` casse `get_data`/`get_variable_name` (erreur de nativisation) ; indexer explicitement (`for i in range(len(handles)): h = handles[i]`) fonctionne. - Un Blueprint Function Library (BFL) se crĂ©e avec `unreal.BlueprintFunctionLibraryFactory()` (pas le `BlueprintFactory` gĂ©nĂ©rique + `parent_class`, qui Ă©choue avec "Cannot create a blueprint based on the class"). - Depuis `execute_python_code`, appeler une fonction Blueprint sur une instance PIE via `actor.call_method(...)` nĂ©cessite le nom **d'affichage exact avec ses espaces** (ex. `"Set Item Actor Owner"`, `"Primary Use"`), pas une version condensĂ©e/snake_case — sauf pour certains getters de variable auto-gĂ©nĂ©rĂ©s dont le nom interne rĂ©el ne correspond ni Ă  l'un ni Ă  l'autre (Ă  vĂ©rifier au cas par cas). - CrĂ©er un `InputAction` en Python : `unreal.InputAction_Factory()` (PAS `unreal.InputActionFactory`, qui n'existe pas) + `AssetToolsHelpers.get_asset_tools().create_asset(...)`. Pour mapper une touche dans un `InputMappingContext` existant, prĂ©fĂ©rer `unreal.InputService.add_key_mapping(imc_path, ia_path, "F9")` (service VibeUE dĂ©diĂ©) plutĂŽt que d'Ă©diter la propriĂ©tĂ© dĂ©prĂ©ciĂ©e `mappings` de l'IMC directement en Python. - Construire un widget UMG en Python : `unreal.WidgetService.add_component`/`set_property`/`bind_event` fonctionnent bien pour la hiĂ©rarchie et les propriĂ©tĂ©s, mais il n'existe **aucun** `unreal.WidgetBlueprintLibrary.create_widget` exposĂ© pour instancier un widget Ă  la volĂ©e. Pour un test rapide en PIE, utiliser `unreal.WidgetService.spawn_widget_in_pie(chemin)` (retourne un handle qu'on repasse Ă  `remove_widget_from_pie`) — mais ce handle n'expose pas d'appel de fonction arbitraire sur l'instance ; il ne sert qu'Ă  l'afficher/la retirer et lire ses propriĂ©tĂ©s (`get_live_property`). - `EditorToolset.EditorAppToolset.CaptureAssetImage`/`CaptureViewport` sont le seul moyen fiable de **voir** un rĂ©sultat (mesh, matĂ©riau, scĂšne) : le retour JSON est trop volumineux pour ĂȘtre lu tel quel (limite de tokens) — toujours passer par un script Python (`base64.b64decode` du champ `returnValue.data`, Ă©crit dans le scratchpad) puis `Read` sur le PNG obtenu. - Un asset `.uasset` peut se retrouver **corrompu Ă  vide** (0 vertex/triangle, bounds nuls) aprĂšs une fermeture anormale de l'Ă©diteur (coupure de courant, crash) sans que sa taille de fichier ni son chargement ne signalent d'erreur — toujours vĂ©rifier `get_num_vertices(0)`/`get_bounds()` (StaticMesh) aprĂšs un redĂ©marrage suspect avant de chercher un autre bug. `delete_asset`/`consolidate_assets` peuvent Ă©chouer silencieusement (retour `False`, sans exception) sur un tel asset corrompu mĂȘme sans rĂ©fĂ©renceur restant — dans ce cas, renommer le nouvel asset importĂ© sous un autre nom plutĂŽt que de s'acharner Ă  rĂ©utiliser le chemin d'origine. - Toute variable membre **boolĂ©enne** (`bXxx`) affiche son nom SANS le prĂ©fixe `b` dans les nƓuds Get/Set gĂ©nĂ©rĂ©s par la DSL (`GetCanSeePlayer`, pas `GetbCanSeePlayer`) — mais son **nom de propriĂ©tĂ© brut**, tel qu'attendu par `get_editor_property`/`set_editor_property` en Python ET par `StateTreeService.bind_*_property_to_context` (chemins de contexte), **conserve le prĂ©fixe `b`** (`"bCanSeePlayer"`, `"AnimalSenses.bScentDetected"`). Utiliser le nom sans `b` dans l'un de ces deux contextes Ă©choue silencieusement en DSL (nƓud introuvable) ou avec "Malformed target property path" cĂŽtĂ© StateTree. - `delete_node` sur un nƓud dont une pin est encore rĂ©fĂ©rencĂ©e par un AUTRE nƓud (ex. un nƓud `Self`/`GetXxx` pur, rĂ©utilisĂ© par plusieurs consommateurs) peut laisser une **connexion fantĂŽme** cĂŽtĂ© survivant : `get_node_infos` continue de lister une pin connectĂ©e vers le node supprimĂ© (qui n'apparaĂźt plus dans `find_nodes`), et la compilation Ă©choue avec l'erreur gĂ©nĂ©rique `Internal compiler error inside CreateExecutionSchedule` sans dĂ©signer le nƓud fautif. Diagnostic : dumper `get_node_infos` de TOUS les nƓuds du graphe et chercher une pin connectĂ©e vers un node absent de `find_nodes` ; le node fantĂŽme existe encore assez longtemps en mĂ©moire (non garbage-collectĂ©) pour que `break_pins` fonctionne dessus malgrĂ© tout — l'appeler explicitement sur cette connexion rĂšgle l'erreur. - Une **UserDefinedEnum** (créée via `unreal.EnumStructService.create_enum`) ne peut PAS servir de type Ă  une variable membre, un paramĂštre de fonction ou un paramĂštre de dispatcher via les outils disponibles (`add_variable`/`add_function_param` n'acceptent que bool/int/float/byte/name/string/text/Vector/Rotator/Transform/Vector2D/LinearColor) — limitation dĂ©jĂ  notĂ©e pour `AC_Stats::OnDamaged`, reconfirmĂ©e pour `E_AnimalState`. Contournement : stocker en `byte` et convertir Ă  l'affichage seulement si besoin (`Utilities|String|ToString(Byte)`). - Une **StateTree Task Blueprint** (`StateTreeTaskBlueprintBase`) ne tique QUE si sa CDO a `should_call_tick_only_on_events = true` — malgrĂ© son nom qui suggĂšre l'inverse ("seulement sur Ă©vĂ©nements"), c'est en rĂ©alitĂ© l'interrupteur gĂ©nĂ©ral qui active `ReceiveLatentTick`. Aucune property `bShouldCallTick` distincte n'est exposĂ©e. - ChaĂźner plus de deux concatĂ©nations `(+ a b)` de **String** dans une mĂȘme expression DSL imbriquĂ©e casse avec `Could not connect pin ReturnValue to A` (constatĂ© sur `BP_AnimalBase::DebugTick`) — mĂȘme en sĂ©parant chaque Ă©tape par un `bind` intermĂ©diaire. Contournement : limiter chaque nƓud `+` Ă  DEUX opĂ©randes littĂ©raux/variables simples, et multiplier les appels `DrawDebugString`/lignes plutĂŽt que de construire une seule chaĂźne longue. - Une donnĂ©e cross-instance (lire la variable d'un AUTRE acteur de mĂȘme classe, ex. le `HerdID` d'un autre `BP_AnimalBase` pendant `BroadcastAlertToHerd`) n'est PAS accessible via le getter `Variables|Default|GetXxx` gĂ©nĂ©rĂ© par la DSL (celui-ci n'a pas de pin `self`/cible, contrairement aux nƓuds `Class|MaClasse|MaFonction` qui, eux, exposent bien un `self` substituable). Solution : passer la donnĂ©e nĂ©cessaire en PARAMÈTRE de la fonction appelĂ©e sur l'autre instance plutĂŽt que de tenter de la lire directement (voir `ReceiveHerdAlert(ThreatLocation, CallerHerdID)`). - Une nouvelle **StateTree** (`unreal.StateTreeService.create_state_tree`) dĂ©marre SANS aucun Ă©tat racine : `add_state(path, "Root", ...)` Ă©choue silencieusement (retourne `False`) tant qu'un premier `add_state(path, "", "Root", "State")` (parent_path **vide**) n'a pas créé l'Ă©tat racine lui-mĂȘme. - Lier une `AC_Stats::OnDamaged` (dispatcher avec paramĂštres) directement Ă  une fonction Blueprint CLASSIQUE (pas un Custom Event) via `K2Node_CreateDelegate.set_create_delegate_function` **compile sans erreur immĂ©diate** mais casse la compilation Ă  la volĂ©e suivante avec `Internal compiler error inside CreateExecutionSchedule` — et peut mĂȘme faire apparaĂźtre des nƓuds `AddEvent` parasites (EventTick, EventActorBeginOverlap
) ailleurs dans le graphe. Un dispatcher avec paramĂštres doit ĂȘtre liĂ© Ă  un **Custom Event** (`add_event` avec un nom arbitraire crĂ©e un vrai `K2Node_CustomEvent`, contrairement Ă  `write_graph_dsl`'s `(event Nom ...)` qui n'accepte que les noms d'Ă©vĂ©nements natifs "AddEvent|Nom" connus). Un dispatcher SANS paramĂštre (ex. `AC_Stats::OnDeath`) ne pose aucun problĂšme liĂ© Ă  une fonction classique. - Un **NavMeshBoundsVolume** ajoutĂ© par script (`SceneTools.add_to_scene_from_class`) ne gĂ©nĂšre PAS automatiquement de NavMesh : le `RecastNavMesh-Default` correspondant naĂźt avec `RuntimeGeneration = Static` (aucune rĂ©gĂ©nĂ©ration, ni en Ă©diteur ni au runtime, sans un "Build Paths" manuel — introuvable dans l'API Python exposĂ©e). Fix : `recastNavMesh.set_editor_property("runtime_generation", unreal.RuntimeGenerationType.DYNAMIC)` PUIS `unreal.NavigationSystem.on_navigation_bounds_updated(nav_sys, volume)` pour forcer une premiĂšre gĂ©nĂ©ration immĂ©diate (sans ce second appel, le volume reste sans tuiles jusqu'au premier changement de gĂ©omĂ©trie pertinent). - **FAUX AMI corrigĂ© (2026-09-05)** : `read_graph_dsl` insĂšre parfois un `_` de lisibilitĂ© dans le nom affichĂ© d'une variable membre commençant par un prĂ©fixe court en majuscule (ex. la variable rĂ©elle `LContainer` s'affiche `(|GetL_Container)`, PAS `(|GetLContainer)` — idem `LItemName`→`L_ItemName`). Utiliser cette forme AVEC underscore pour crĂ©er/Ă©crire un nƓud (`create_node`, `write_graph_dsl`) Ă©choue avec "... does not exist", ce qui peut faire croire Ă  tort Ă  une variable locale non-crĂ©able (variables locales et membres se comportent en rĂ©alitĂ© de façon identique cĂŽtĂ© crĂ©ation). Avant toute chirurgie sur un Get/Set qui Ă©choue ainsi, vĂ©rifier le nom SANS underscore via `find_node_types` (ex. filtrer `"LContainer"`) plutĂŽt que de supposer une limitation de l'outil — le nom rĂ©el de la propriĂ©tĂ© (`get_editor_property` en Python inclus) ne contient jamais cet underscore ajoutĂ© par l'affichage. - Un Blueprint qui est la classe d'un **composant actif dans une session PIE en cours** peut compiler sans erreur mais **Ă©chouer silencieusement Ă  la sauvegarde** (`save_loaded_asset` renvoie `False` sans exception) tant que le PIE n'est pas arrĂȘtĂ© — toujours `StopPIE` avant de sauvegarder un asset qu'une session PIE utilise, et re-tenter la sauvegarde aprĂšs l'arrĂȘt. - **CORROLAIRE DANGEREUX** : aprĂšs tout Ă©chec de `save_loaded_asset` dĂ» au PIE, **StopPIE PUIS ressauvegarder IMMÉDIATEMENT**, et **toujours revĂ©rifier via `read_graph_dsl`/`find_nodes` aprĂšs un redĂ©marrage/arrĂȘt du PIE** qu'une Ă©dition rĂ©cente est bien encore prĂ©sente avant de continuer Ă  construire dessus — une Ă©dition compilĂ©e avec succĂšs pendant que le PIE tournait peut sembler perdue Ă  la prochaine lecture si la sauvegarde qui a suivi a Ă©chouĂ© silencieusement. - **PIÈGE MAJEUR — graphe d'implĂ©mentation d'interface Blueprint fragile et auto-rĂ©gĂ©nĂ©rĂ© (2026-09-06)** : le graphe qui implĂ©mente une fonction de Blueprint Interface (ex. `BP_Item_HoldableBase:On Item Attached`, implĂ©mentant `BPI_HoldableItem::On Item Attached`) peut **revenir tout seul Ă  son Ă©tat d'origine** aprĂšs une compilation ultĂ©rieure — de N'IMPORTE QUEL Blueprint de la hiĂ©rarchie, pas seulement celui qu'on Ă©dite — mĂȘme quand `read_graph_dsl` avait confirmĂ© l'Ă©dition juste aprĂšs une sauvegarde rĂ©ussie (`save_loaded_asset` → `True`, mtime du `.uasset` Ă  jour). Un `reload_packages` forcĂ© depuis Python confirme que c'est bien le contenu SUR DISQUE qui a rĂ©gressĂ©, pas juste l'Ă©tat en mĂ©moire — la persistance de ce type de graphe est donc bien plus fragile qu'une fonction normale. Reproduit 3 fois de suite sur le mĂȘme graphe dans cette session malgrĂ© des re-sauvegardes systĂ©matiques. **Ne JAMAIS hĂ©berger de logique mĂ©tier propre (dispatcher broadcast, etc.) directement dans un graphe d'implĂ©mentation d'interface** — s'en servir seulement comme passe-plat trivial si besoin, ou mieux : contourner entiĂšrement l'interface et appeler la fonction/le dispatcher cible directement depuis l'appelant via un `Cast` explicite vers la classe concrĂšte (ex. `Inventory_Equipper::AttachItemToOwner` caste `Item` en `BP_Item_HoldableBase` et appelle `CallOnHeldStateChanged` directement, sans jamais passer par l'interface) — cette approche s'est rĂ©vĂ©lĂ©e stable aprĂšs le contournement. - **RĂ©fĂ©rence d'interface `K2Node_Message`/`K2Node_CallFunction` corrompue aprĂšs un renommage d'interface (2026-09-06)** : un appel d'interface existant peut afficher un `type_id`/catĂ©gorie qui ne correspond Ă  AUCUN asset actuel du projet (ex. `BPIEquippableItem|OnItemAttached` alors que seule `BPI_HoldableItem` existe — probablement un renommage `BPI_EquippableItem`→`BPI_HoldableItem` fait avant cette session) tout en compilant sans erreur et en affichant des types de pins statiquement cohĂ©rents (`get_node_type_pins` montrait bien `self: BPI Holdable Item Interface`) — la compilation rĂ©ussit car un systĂšme de redirection (CoreRedirects ou Ă©quivalent) fait correspondre le nom au niveau des TYPES, mais l'appel ne dĂ©clenche RIEN Ă  l'exĂ©cution (confirmĂ© par prints de debug ne s'affichant jamais cĂŽtĂ© rĂ©cepteur, malgrĂ© la classe cible confirmĂ©e implĂ©menter l'interface via `unreal.SystemLibrary.does_class_implement_interface`). Un nƓud fraĂźchement créé avec le MÊME `type_id` peut mĂȘme se rĂ©soudre en un type de nƓud DIFFÉRENT (`K2Node_CallFunction` au lieu du `K2Node_Message` d'origine) — signe supplĂ©mentaire d'une rĂ©fĂ©rence historique corrompue plutĂŽt que d'un vrai type_id valide. Diagnostic : ajouter un print cĂŽtĂ© rĂ©cepteur et vĂ©rifier empiriquement qu'il se dĂ©clenche ; si l'appelant confirme passer par le nƓud (print juste avant) mais que le rĂ©cepteur reste silencieux, suspecter ce piĂšge. Fix : ne pas rĂ©utiliser l'ancien nƓud ni recrĂ©er un nƓud du mĂȘme `type_id` — contourner l'interface entiĂšrement (voir point ci-dessus). - **Consommer un stock d'inventaire PASSIF (jamais Ă©quipĂ©/lĂąchĂ©) ne doit jamais passer par un acteur monde (2026-09-06)** : la macro `ML_InventoryMacros::Get Item Actor` (et donc tout appel `Utilities|GetItemActor`) retourne TOUJOURS invalide pour un item empilĂ© qui n'a jamais Ă©tĂ© spawnĂ© comme acteur (ex. un stack de flĂšches "Arrow" qui reste en inventaire, jamais Ă©quipĂ©) — ce n'est pas un bug ponctuel, c'est le comportement normal : ces items n'ont simplement pas d'acteur tant qu'ils ne sont pas Ă©quipĂ©s/lĂąchĂ©s dans le monde. Une fonction du type `ConsumeArrow`/`ReduceAmmo` qui suit le patron `FindItem → GetItemActor → SERVER|ReduceAmount(item_actor, ...)` Ă©choue donc silencieusement (retourne false) pour ce genre d'item, mĂȘme quand `FindItem` a bien trouvĂ© le stack. Fix correct : opĂ©rer directement sur les DONNÉES via l'adresse de l'item, avec `Inventory__Main::AddItemAmount(ItemAddress, DeltaAmount)` (nĂ©gatif pour consommer) — une fonction RPC serveur qui gĂšre nativement le retrait de l'array si le montant tombe Ă  0, sans jamais nĂ©cessiter d'acteur. Le mĂ©canisme `GetItemActor`+fonction-sur-acteur reste correct UNIQUEMENT pour des items dont l'acteur est garanti d'exister (ex. un chargeur d'arme Ă©quipĂ©, actif comme `Magazine Reference`). - **PIÈGE CRITIQUE — brancher UNE sortie de pose sur PLUSIEURS entrĂ©es dans un `AnimGraph` casse toute la locomotion (2026-09-06)** : contrairement Ă  un graphe Blueprint normal, une sortie `Pose Link` (`AnimGraphNode_*`) qui alimente directement 2+ entrĂ©es fait ÉVALUER EN DOUBLE, Ă  chaque frame, TOUT le sous-graphe en amont — pas seulement recalculer une valeur, mais rĂ©ellement re-tick les nƓuds AVEC ÉTAT (State Machine, Motion Matching, Blend Space avec accumulation de temps, Inertialization) une deuxiĂšme fois. SymptĂŽme observĂ© : le personnage "bouge de façon bizarre" (mouvement erratique/saccadĂ©) dĂšs qu'un nƓud en amont d'un fan-out a un Ă©tat interne dĂ©pendant du temps — la Motion Matching et les State Machines de ce projet en amont de `Slot 'DefaultSlot'` Ă©taient tickĂ©es deux fois par frame aprĂšs l'ajout (sans prĂ©caution) d'un second consommateur sur la sortie de ce Slot. Fix obligatoire : **ne jamais connecter directement une sortie de pose partagĂ©e Ă  plusieurs entrĂ©es** — insĂ©rer un `Save Cached Pose 'NomUnique'` juste aprĂšs la source, puis un `Use Cached Pose 'NomUnique'` par consommateur (le projet utilise dĂ©jĂ  ce patron ailleurs dans `SandboxCharacter_CMC_ABP`, ex. cache `MotionMachin` consommĂ© par `Mirror_0` ET `BlendListByBool_3` — repĂ©rable via `find_nodes`/`get_node_infos` avant de dupliquer une sortie, pour voir si le patron existe dĂ©jĂ ). Une rĂ©gression de ce type NE PROVOQUE AUCUNE ERREUR DE COMPILATION — le graphe compile et sauvegarde sans avertissement, le bug n'est visible qu'en jouant. - **CrĂ©er un nƓud de Get/Set VARIABLE d'une AUTRE classe (pas une fonction) via `create_node` (2026-09-06)** : `find_node_types` avec `context_pins` pointant vers une pin dĂ©jĂ  castĂ©e Ă  la classe cible retourne bien le type_id correct (ex. `Variables|Default|SetWeapon`), mais ce type_id Ă©choue Ă  la crĂ©ation via `create_node` (`does not exist`) MÊME avec `declaring_class` renseignĂ© — `declaring_class` ne sert qu'Ă  dĂ©sambiguĂŻser un type_id dĂ©jĂ  trouvĂ©, pas Ă  Ă©largir la recherche. Fix : rappeler `find_node_types` avec `context_pins: []` (SANS contexte) sur le mĂȘme filtre — la forme SANS contexte rĂ©vĂšle le type_id RÉELLEMENT crĂ©able, qui suit la convention `Class||` (ex. `Class|SandboxCharacterCMC|SetWeapon`), diffĂ©rent de la forme `Variables|Default|...` que le contexte affichait. Une fois créé, le nƓud peut ensuite s'afficher avec un LABEL DSL trompeur (catĂ©gorie `SandboxCharacterCMCABP` au lieu de `SandboxCharacterCMC` par ex.) — vĂ©rifier le type rĂ©el de la pin `self` via `get_node_infos` (pas la catĂ©gorie DSL) pour confirmer la bonne classe cible. - **Configurer un nƓud `AnimGraphNode_*` (Slot, LayeredBoneBlend, etc.) au-delĂ  de ses pins (2026-09-06)** : le nom d'un `Slot` (`SlotName`) et les filtres de branche d'un `Layered Blend Per Bone` (`LayerSetup[i].BranchFilters`) ne sont PAS des pins — ce sont des propriĂ©tĂ©s du sous-struct `Node` (le `FAnimNode_*` runtime) portĂ© par le `AnimGraphNode_*`. Invisibles via `get_node_infos`/`create_node`/`set_pin_value`. AccĂšs uniquement via Python : `node.get_editor_property("Node")` renvoie le struct runtime, dont les champs se lisent/Ă©crivent avec `get_editor_property`/`set_editor_property` en snake_case (`slot_name`, `layer_setup`, `blend_weights`...) — mais pour un ARRAY de structs imbriquĂ©s (ex. `layer_setup: [InputBlendPose]`, chaque `InputBlendPose.branch_filters: [BranchFilter]`), modifier un Ă©lĂ©ment en place ne suffit pas : construire les structs indĂ©pendamment (`unreal.BranchFilter()`, `unreal.InputBlendPose()`), les remplir via `set_editor_property`, PUIS rĂ©assigner le tableau complet sur le struct parent (`ibp.set_editor_property("branch_filters", [bf])`, puis `node_struct.set_editor_property("layer_setup", [ibp])`, puis `node.set_editor_property("Node", node_struct)`) — une mutation in-place sans cette rĂ©assignation finale ne persiste pas. `to_dict()` sur ces structs renvoie souvent `{}` de façon trompeuse mĂȘme quand les propriĂ©tĂ©s sont bien accessibles individuellement via `get_editor_property` — ne pas se fier Ă  `to_dict()` pour vĂ©rifier un struct AnimGraph, toujours relire chaque propriĂ©tĂ© nommĂ©ment. - Le cache de dĂ©couverte de `find_node_types` pour un AUTRE Blueprint rĂ©fĂ©rençant fraĂźchement une fonction ajoutĂ©e ailleurs (ex. `Class|InventoryPlayer|MaNouvelleFonction` cherchĂ© depuis un Widget qui possĂšde une variable de type `Inventory_Player`) peut rester pĂ©rimĂ© et ne rien retourner mĂȘme aprĂšs compilation+sauvegarde de la classe modifiĂ©e — `create_node` avec le `type_id` dĂ©duit par convention (`Class||`) fonctionne quand mĂȘme ; ne pas conclure Ă  une impossibilitĂ© sur la seule base d'un `find_node_types` vide. - `unreal.get_editor_subsystem(unreal.EditorActorSubsystem).get_all_level_actors()` (et plus gĂ©nĂ©ralement les APIs `EditorActorSubsystem`) redevient **silencieusement vide** pendant qu'une session PIE est active — ces APIs ciblent le monde Ă©diteur, pas le monde PIE. Pour inspecter/piloter des acteurs PENDANT une session PIE (vĂ©rifier qu'une IA se dĂ©place, lire une variable en temps rĂ©el), utiliser `editor_toolset.toolsets.scene.SceneTools.find_actors` (qui rĂ©sout correctement vers le monde `UEDPIE_0_`) puis `unreal.load_object(None, refPath)` sur le chemin PIE retournĂ©. - **`write_graph_dsl` (réécriture complĂšte d'un graphe) casse sur 2 instances DIFFÉREMMENT TYPÉES d'un mĂȘme nƓud wildcard enum (2026-09-06)** : `Utilities|Enum|NotEqual(Enum)`/`Equal(Enum)` sont des nƓuds gĂ©nĂ©riques dont le type se fixe au premier pin connectĂ© — un graphe EXISTANT peut trĂšs bien contenir plusieurs instances typĂ©es diffĂ©remment (constatĂ© sur `Get_MMInterruptMode` : 3× `NotEqual(Enum)` + 2× `Equal(Enum)`, types `E_MovementMode`/`E_MovementState`/`E_Gait` mĂ©langĂ©s, qui coexistent sans problĂšme). Mais **reconstruire ce mĂȘme graphe en un seul appel `write_graph_dsl`** en y ajoutant une NOUVELLE instance sur un type enum diffĂ©rent (ex. `Weapon_Equip`) Ă©choue systĂ©matiquement avec `Could not connect pin ReturnValue to B`, quel que soit l'ordre des clauses — le compilateur DSL semble partager le typage wildcard entre toutes les instances créées dans une mĂȘme passe, contrairement au graphe dĂ©jĂ  compilĂ© oĂč chaque instance est indĂ©pendante. Heureusement l'Ă©chec est bien transactionnel (`read_graph_dsl` confirme le graphe intact aprĂšs l'erreur, aucun Ă©tat partiel). Fix : ne PAS passer par une réécriture DSL complĂšte pour ce genre d'ajout — construire les nƓuds un par un (`create_node` pour les 2 `Variables|Default|GetXxx` + le nouveau `NotEqual(Enum)`, `connect_pins` pour les typer), puis brancher le rĂ©sultat sur le nƓud logique existant. Un nƓud `Math|Boolean|ORBoolean`/`ANDBoolean` (`K2Node_CommutativeAssociativeBinaryOperator`) accepte nativement un pin de PLUS via `add_node_pin` (retourne le nouveau `PinID`, ex. `C` aprĂšs `A`/`B`) — pas besoin de recrĂ©er tout l'arbre logique, juste ajouter le pin et y connecter la nouvelle condition. `read_graph_dsl` n'affiche ensuite QUE les 2 premiers pins d'un `or`/`and` Ă  3+ entrĂ©es (limite d'affichage du lecteur DSL) — vĂ©rifier un ajout de ce type via `get_node_infos` sur le nƓud lui-mĂȘme, pas via une relecture DSL qui semblerait ignorer l'Ă©dition. - **Architecture Motion Matching — pourquoi une nouvelle base de donnĂ©es "valide" peut ĂȘtre ignorĂ©e indĂ©finiment (2026-09-06)** : `Update_MotionMatching` (fonction ABP thread-safe, tourne chaque frame) fait `EvaluateChooser → SetValidDatabases → MotionMatchingAnimNodeLibrary.SetDatabasesToSearch(node, databases, InterruptMode)` — le 3ᔉ paramĂštre (`Get_MMInterruptMode`, une fonction sĂ©parĂ©e) contrĂŽle si le nƓud `AnimGraphNode_MotionMatching` a le DROIT de remettre en cause la pose en cours (`DoNotInterrupt` = non, il continue de jouer/boucler l'ancienne sĂ©lection MÊME SI elle n'appartient plus Ă  `DatabasesToSearch` ; `InterruptOnDatabaseChange(AndInvalidateContinuingPose)` = oui, force une recherche complĂšte). **Changer `ValidDatabases` ne suffit donc JAMAIS Ă  lui seul Ă  faire rĂ©agir Motion Matching** si `Get_MMInterruptMode` ne dĂ©tecte pas la transition responsable — vĂ©rifier scrupuleusement, pour TOUT nouveau contexte de sĂ©lection (nouvelle variable de state driving un chooser), qu'il existe bien une condition correspondante dans cette fonction (schĂ©ma dĂ©jĂ  en place : une paire `GetXxx`/`GetXxxLastFrame`, mise Ă  jour chaque frame dans `Update_States`, comparĂ©e avec `Utilities|Enum|NotEqual(Enum)` puis OR-Ă©e dans la condition racine). Diagnostic fiable : `obj dump` sur l'instance `AnimInstance` vivante en PIE (`unreal.SystemLibrary.execute_console_command(actor, 'obj dump ""')`, rĂ©sultat lu via `EditorToolset.LogsToolset.GetLogEntries`) expose le struct COMPLET `AnimGraphNode_MotionMatching=(...)`, notamment `MotionMatchingState.SearchResult.(SelectedAnim|SelectedDatabase|bIsContinuingPoseSearch|SearchCost)` et `AnimPlayers[].InternalTimeAccumulator` (qui doit AVANCER entre deux dumps espacĂ©s dans le temps — sinon la pose est rĂ©ellement figĂ©e, pas juste "en cours de transition"). - **`PoseSearchDatabase` — Ă©chec silencieux de build d'index et non-avancement figĂ© sur une frame (2026-09-06)** : un `PoseSearchDatabase` en mode `PCAKD_TREE` (valeur par dĂ©faut) peut Ă©chouer Ă  construire son index dĂšs le chargement du projet si son jeu d'animations sources est trop petit/peu variĂ© pour que le calcul PCA converge — log `LogPoseSearch: Error: - BuildIndex Failed because of 'No Convergence' while calculating PCA data` (visible uniquement via `GetLogEntries` sur `LogPoseSearch`, jamais remontĂ© cĂŽtĂ© Blueprint/PIE). Tant que l'index reste dans cet Ă©tat, TOUTE recherche dessus Ă©choue en silence (`SearchCost=FLT_MAX`, `SelectedAnim=None`) et spam `LogPoseSearch: Warning: UPoseSearchLibrary::MotionMatch - some searches have been skipped, since databases AsyncBuildIndex are in still in progress or failed` Ă  chaque tick. Fix testĂ© et qui fonctionne : `db.set_editor_property("PoseSearchMode", unreal.PoseSearchMode.BRUTE_FORCE)` (au lieu de `PCAKD_TREE`) + sauvegarde (`EditorAssetLibrary.save_asset(path, only_if_is_dirty=False)` — nĂ©cessite PIE ARRÊTÉ, sinon retourne `False` sans erreur) — `BRUTE_FORCE` n'a pas besoin de PCA et convient trĂšs bien Ă  une petite database (coĂ»t de recherche linĂ©aire nĂ©gligeable Ă  cette Ă©chelle). **Second piĂšge indĂ©pendant, NON contournable trouvĂ© Ă  ce jour** : le tableau `DatabaseAnimationAssets` (alias historique `AnimationAssets`) d'un `PoseSearchDatabase` est protĂ©gĂ© en lecture ET Ă©criture pour TOUTE mĂ©thode testĂ©e (`get_editor_property`/`set_editor_property` Python, ET `ObjectTools.get_properties`/`set_properties` en C++ natif — qui pourtant contournent d'autres restrictions Python) ; seule la lecture BRUTE via `obj dump "."` (PAS juste `` seul, qui ne dump que le Package) expose son contenu texte (`DatabaseAnimationAssets(i)=(AnimAsset=...,SamplingRange=(Min=...,Max=...),...)`), sans Ă©quivalent en Ă©criture connu. **ATTENTION Ă  la sĂ©mantique de `SamplingRange`** (erreur de diagnostic commise puis corrigĂ©e le 2026-09-06) : `(Min=0, Max=0)` ne signifie PAS « plage vide » mais « ÉCHANTILLONNER TOUT LE CLIP » — c'est la valeur NORMALE, utilisĂ©e par toutes les databases saines du projet (vĂ©rifiĂ© sur `PSD_Dense_Stand_Walk_Loops`, `PSD_Dense_Stand_Idles`). Le cas rĂ©ellement pathologique est `Min == Max != 0`, en particulier `(longueur_du_clip, longueur_du_clip)` : fenĂȘtre de largeur nulle collĂ©e Ă  la FIN du clip. Double consĂ©quence : (a) plus rien Ă  lire, et (b) `FPoseSearchDatabaseSequence::IsLooping()` exige `SamplingRange == (0,0)` EN PLUS de `AnimSequence->bLoop`, donc l'asset devient non-bouclable (`bLoopAnimation=False` dans le dump du nƓud) mĂȘme si l'AnimSequence source est bien `Loop=True` — d'oĂč un gel sur une frame unique. SymptĂŽme observable : `AnimPlayers[].InternalTimeAccumulator` identique entre deux `obj dump` espacĂ©s de plusieurs secondes rĂ©elles en PIE. Correction = remettre la plage Ă  `0 / 0` Ă  la main dans l'Ă©diteur Pose Search Database. - **PIÈGE CRITIQUE — `EditorAssetLibrary.consolidate_assets()` fait planter l'Ă©diteur sur certains types de classes (2026-09-08, dĂ©doublonnage de l'import Game Animation Sample)** : cette fonction (fusionne toutes les rĂ©fĂ©rences d'un doublon vers l'asset gardĂ©, supprime le doublon, laisse un `ObjectRedirector`) est **fiable Ă  100% sur les assets de donnĂ©es pures** (UserDefinedEnum, UserDefinedStruct, CurveFloat, ChooserTable, CameraRigAsset, CameraAsset, ControlRigBlueprint, ProxyAsset — testĂ© sur ~85 assets sans un seul Ă©chec) mais **crashe le processus Ă©diteur de façon reproductible** (`Assertion failed: NewEditorElement.Private_GetInternalData()->GetRefCount() <= 1 ... The old and new element both have external references!`, `LogPython: Error: Python execution caused a crash (exception code: 0xC0000005)` — l'Ă©diteur entier finit par `Engine exit requested`, pas juste l'interprĂ©teur Python) sur les **ActorComponent Blueprints activement utilisĂ©s comme composant** (constatĂ© sur `AC_PreCMCTick`, `AC_SmartObjectAnimation`) et sur les **Blueprint Interfaces largement implĂ©mentĂ©es** (`BPI_SandboxCharacter_Pawn`). Les Blueprints "de classe" simples (GameMode, modes de mouvement `Mover`, transitions) consolident sans problĂšme. **Ne jamais retenter `consolidate_assets` une seconde fois sur le mĂȘme asset aprĂšs un premier crash** — utiliser Ă  la place, dans l'ordre de prĂ©fĂ©rence : (1) `EditorAssetLibrary.delete_asset()` en brut si `AssetRegistry.get_referencers()` confirme que plus rien ne rĂ©fĂ©rence le doublon (le plus sĂ»r, fonctionne mĂȘme sur les types Ă  risque — mais peut prendre 1 Ă  4 minutes sur un projet avec des dizaines de milliers d'assets, l'appel `execute_python_code` timeout cĂŽtĂ© client mais l'opĂ©ration continue et rĂ©ussit cĂŽtĂ© serveur : revĂ©rifier via `does_asset_exist` plutĂŽt que de conclure Ă  un Ă©chec sur un timeout) ; (2) si des rĂ©fĂ©rences externes subsistent, les repointer manuellement d'abord — `BlueprintTools.set_parent()` pour un reparentage, `BlueprintTools.retarget_node_class(node, old_class, new_class)` pour un nƓud de cast/appel de fonction/Ă©vĂ©nement avec une classe figĂ©e Ă  l'ancien doublon (fonctionne bien, contrairement Ă  `consolidate_assets`) — puis `delete_asset` une fois les rĂ©fĂ©renceurs Ă  zĂ©ro. **Effet de bord du crash** : le processus Ă©diteur entier redĂ©marre, ce qui **remet l'interprĂ©teur Python Ă  zĂ©ro mais PAS l'Ă©tat sauvegardĂ© sur disque** — toute opĂ©ration dĂ©jĂ  sauvegardĂ©e (compile+save) avant le crash est conservĂ©e ; seule la commande en cours au moment du crash est perdue. Toujours vĂ©rifier `is_in_pie`/un `print("ping")` trivial aprĂšs CE type d'erreur avant de continuer : contrairement Ă  une simple corruption d'interprĂ©teur (`SystemError: unknown opcode`, rĂ©cupĂ©rable seulement par redĂ©marrage Ă©diteur elle aussi), celle-ci relance le processus tout seul en quelques dizaines de secondes. - **Corollaire — reparenter un Blueprint dont les enfants rĂ©fĂ©rencent des COMPOSANTS PAR NOM (2026-09-08)** : si un Blueprint enfant (ex. `SandboxCharacter_Mover_Ragdoll`) a des nƓuds `Variables|Default|GetXxx`/`SetXxx` qui lisent des variables membres du PARENT (ex. `SkeletalMesh`, `Capsule`, `CharacterMover` — des variables de CACHE exposant les composants SCS rĂ©els, PAS les composants eux-mĂȘmes) et qu'on reparente vers un parent qui n'a pas ces variables sous ce nom exact, la compilation Ă©choue avec `The property associated with could not be found`. **Fix simple et Ă  fort effet de levier** : ajouter au NOUVEAU parent des variables membres du mĂȘme nom/type exacts (`BlueprintTools.add_object_variable`/`add_struct_variable`/`add_variable`) — TOUS les nƓuds orphelins portant ce nom, dans TOUTES les fonctions de TOUS les enfants, se re-rĂ©solvent automatiquement Ă  la compilation suivante, sans toucher un seul nƓud individuellement (testĂ© sur ~90 rĂ©fĂ©rences rĂ©parties dans 28 fonctions, rĂ©solu par l'ajout de 8 variables). Il n'est PAS nĂ©cessaire que ces variables soient effectivement peuplĂ©es/cĂąblĂ©es pour que la compilation rĂ©ussisse — seule leur EXISTENCE avec le bon nom/type compte pour le compilateur ; les peupler (ex. dans `EventBeginPlay`) reste nĂ©cessaire pour un comportement correct Ă  l'exĂ©cution. - **`connect_pins`/`write_graph_dsl` peuvent devenir silencieusement des no-op aprĂšs une session trĂšs longue avec plusieurs crashs Ă©diteur (2026-09-08)** : en fin de session, aprĂšs plusieurs cycles crash/redĂ©marrage, `connect_pins(PinID_output, PinID_input)` a cessĂ© de produire une erreur mais aussi de produire un effet (`get_node_infos` confirme aprĂšs coup qu'aucune des deux pins n'est connectĂ©e) — reproduit mĂȘme sur une paire de nƓuds fraĂźchement créés dans le MÊME appel Python, et mĂȘme sur un Blueprint diffĂ©rent qui avait fonctionnĂ© plus tĂŽt dans la session. Aucune cause identifiĂ©e avec certitude (suspectĂ© : Ă©tat de l'Ă©diteur dĂ©gradĂ© par l'accumulation de crashs, pas un bug systĂ©matique de l'outil — `connect_pins` a fonctionnĂ© de façon fiable pendant le reste de la session). Si `connect_pins` semble rĂ©ussir sans erreur mais que `get_node_infos` ne montre ensuite AUCUNE connexion sur les pins concernĂ©es, ne pas insister : passer Ă  une mĂ©thode alternative (repenser le fix pour n'avoir besoin que d'ajouts de variables/fonctions, voir point ci-dessus) plutĂŽt que de perdre du temps Ă  re-essayer la mĂȘme primitive. - **Écrire dans une `ChooserTable` (colonnes) depuis un script (2026-09-06)** : `ColumnsStructs` se LIT en Python (`get_editor_property` + `.export_text()` sur chaque `InstancedStruct`) mais ne s'ÉCRIT PAS par cette voie — `InstancedStruct.import_text(nouveau_texte)` renvoie `True` en mentant (le contenu de l'Ă©lĂ©ment reste inchangĂ©), et le `set_editor_property("ColumnsStructs", ...)` qui suit ne remonte donc rien, sans lever d'exception. **Voie qui fonctionne** : le toolset Python `editor_toolset.toolsets.object.ObjectTools` (importable directement : `from editor_toolset.toolsets.object import ObjectTools`), qui expose la table en JSON — `json.loads(ObjectTools.get_properties(chooser, ["ColumnsStructs"]))`, modification du dict (ex. `col["rowValuesWithAny"][i] = "MatchAny"`), puis `ObjectTools.set_properties(chooser, json.dumps(data))` qui renvoie `True` et applique rĂ©ellement. `ResultsStructs` (rĂ©sultats des lignes) reste inaccessible par toutes les voies testĂ©es : on peut donc MODIFIER une ligne existante mais pas en AJOUTER une nouvelle par script. - **`EditorAssetLibrary.save_asset`/`save_loaded_asset` peuvent renvoyer `False` alors que l'asset est parfaitement sauvegardable, PIE arrĂȘtĂ© et fichier non-verrouillĂ©** (constatĂ© sur `CHT_PoseSearchDatabases_Dense` aprĂšs une Ă©criture via `ObjectTools.set_properties`, probablement parce que le package n'est pas marquĂ© dirty par cette voie). Ne pas en conclure Ă  un Ă©chec : passer par `unreal.EditorLoadingAndSavingUtils.save_packages([obj.get_outermost()], False)` qui renvoie `True` et met bien Ă  jour le `mtime` du `.uasset` (Ă  vĂ©rifier via `os.path.getmtime`, seule preuve fiable d'Ă©criture disque). - **Outillage dĂ©couvert le 2026-09-13 (rĂ©paration post-migration)** : (a) `BlueprintEditorLibrary.compile_blueprint` / `BlueprintTools.compile_blueprint` ne lĂšvent AUCUNE exception sur erreur de compilation — encadrer les compilations de marqueurs `unreal.log_warning("MARQUEUR")` puis lire `Saved/Logs/ProjectFv1.log` entre les marqueurs (`LogBlueprint: Error`). (b) `BlueprintTools.set_pin_value` (et d'autres outils du toolset) peut SAUVEGARDER l'asset sur disque sans le dire — sauvegarder le fichier avant d'expĂ©rimenter. (c) `retarget_node_class` / `change_member_variable_type` ne rafraĂźchissent pas les types de pins en cache (erreurs « X is not compatible with X ») : sauvegarder, `EditorLoadingAndSavingUtils.reload_packages`, recompiler — le rechargement reconstruit les nƓuds. (d) Le struct `PinID` n'est pas exposĂ© en Python : pour `connect_pins`/`break_pins`, passer par `ProgrammaticToolset.execute_tool_script` (appel `get_execution_environment` requis avant) avec des PinID JSON `{direction, index_id, node:{refPath}}`. (e) Les pins d'un nƓud `Evaluate Chooser` portent le NOM de l'asset struct de contexte : changer/renommer/fusionner la struct laisse des pins orphelines liĂ©es (« In use pin ... no longer exists ») Ă  rebrancher. (f) `EditorAssetLibrary.consolidate_assets` sur des `UserDefinedStruct` sauvegarde automatiquement les rĂ©fĂ©renceurs et crĂ©e les redirecteurs. (g) `ChooserTable.ContextData` s'Ă©crit via `ObjectTools.set_properties` (JSON `_structType`/`class`/`struct` → `refPath`) + `EditorLoadingAndSavingUtils.save_packages`. (h) Une rĂ©fĂ©rence passant par un `.ini` (ex. `GameplayTagTableList`) est invisible pour l'Asset Registry : vĂ©rifier `Config/` avant de dĂ©clarer un asset « sans rĂ©fĂ©rence ». - **PIÈGE CRITIQUE — `consolidate_assets` sur une UserDefinedEnum (probablement aussi une UserDefinedStruct) vide silencieusement les types de variables des rĂ©fĂ©renceurs (2026-09-14)** : les rĂ©fĂ©rences dures sont réécrites, mais le `PinSubCategoryObject` des variables membres (et types de valeur de map) typĂ©es par l'enum fusionnĂ© tombe Ă  `None` : la variable devient un simple `byte`. La classe compilĂ©e garde le bon type, donc tout compile. Au rechargement suivant du package (les rĂ©fĂ©renceurs sont auto-sauvegardĂ©s par la fusion), les liens devenus incompatibles sont supprimĂ©s, des nƓuds `Equal/NotEqual (Enum)` redeviennent Wildcard et l'Ă©diteur insĂšre des `CastByteToEnum`. Une entrĂ©e qui garde une valeur littĂ©rale compile toujours : la logique est fausse SANS erreur (ex. `SandboxCharacter_Mover_ABP` : 19 variables vidĂ©es → 2259 erreurs au rechargement ; `BP_NotifyState_EarlyTransition` : 5 liens perdus dont 1 sans erreur). Les `K2Node_SwitchEnum` ne reconstruisent leurs sorties qu'au rechargement du package. ProcĂ©dure : sauvegarder tous les rĂ©fĂ©renceurs avant la fusion ; juste aprĂšs et AVANT tout rechargement, scanner `BlueprintEditorLibrary.get_member_variable_type(bp, v).export_text()` (`PinSubCategoryObject=None`) et retyper via `change_member_variable_type` ; si un rĂ©fĂ©renceur a dĂ©jĂ  Ă©tĂ© rechargĂ© cassĂ©, le restaurer depuis la sauvegarde (Ă©diteur fermĂ©) ou comparer ses liens Ă  un jumeau intact (`BlueprintTools.get_node_infos`), rebrancher et supprimer les casts (`delete_node`) ; valider par `reload_packages` d'UN seul package Ă  la fois (jamais un Blueprint en mĂȘme temps qu'un Blueprint dont il dĂ©pend). Pour des Blueprints entiers, prĂ©fĂ©rer un dĂ©placement Ă  une fusion. - **CRASH ÉDITEUR — handles Python sur des nƓuds supprimĂ©s (2026-09-14)** : `BlueprintTools.delete_node` puis `compile_blueprint` dans le MÊME `exec`, alors que des variables Python gardent les handles de nƓuds / structs de pins (`get_node_infos`) des nƓuds supprimĂ©s → `EXCEPTION_ACCESS_VIOLATION` dans python311.dll et fermeture de l'Ă©diteur. Fix qui a fonctionnĂ© : exĂ©cuter l'Ă©dition, la compilation/sauvegarde et tout ce qui dĂ©clenche un GC (suppression d'assets, `reload_packages`) dans des callbacks `register_slate_post_tick_callback` SÉPARÉS, chacun dans un dictionnaire de globals neuf, avec `scope.clear()` + `gc.collect()` entre les Ă©tapes et `unreal.SystemLibrary.collect_garbage()` au dĂ©but de l'Ă©tape suivante. Ne sauvegarder qu'aprĂšs une vĂ©rification : un crash ne laisse alors rien de corrompu sur disque. Relance : `E:\UE_5.8\Engine\Binaries\Win64\UnrealEditor.exe "E:\projet\ProjectFv1\ProjectFv1.uproject"` (MCP disponible ~20 s aprĂšs). - **Asset Registry pĂ©rimĂ© aprĂšs sauvegarde + rechargement (2026-09-14)** : `get_dependencies`/`get_referencers` peuvent encore lister une rĂ©fĂ©rence qu'un asset n'a plus (ex. `PC_Sandbox` → widget de dĂ©mo retirĂ©, alors que le `.uasset` ne contient plus ce nom). Forcer `AssetRegistry.scan_paths_synchronous([dossier], True)` avant de vĂ©rifier des rĂ©fĂ©renceurs. - **`EditorAssetLibrary.delete_asset` sur une map non chargĂ©e** (`/Game/dev_map`) peut renvoyer `True` en laissant le `.umap` sur disque et une dĂ©pendance fantĂŽme dans l'Asset Registry (qui ferait recharger/rĂ©enregistrer la map lors d'un renommage de ses dĂ©pendances). VĂ©rifier le fichier sur disque ; s'il reste, le supprimer puis `scan_files_synchronous([fichier], True)`. - **Assigner un squelette Ă  une animation qui n'en a pas (2026-09-14)** : `AnimSequence.Skeleton` est en lecture seule pour `set_editor_property` ET refusĂ© par `ObjectTools.set_properties` ; aucun service VibeUE (`SkeletonService`, `AnimSequenceService`, `AnimMontageService`) ne l'expose (lecture/compatibilitĂ© seulement). Seule voie : ouvrir l'asset dans l'Ă©diteur, qui propose de choisir un squelette, puis sauvegarder. Avant, vĂ©rifier la compatibilitĂ© : `AnimationLibrary.get_animation_track_names(anim)` comparĂ© aux os du mesh cible (`SkinnedMeshComponent.get_num_bones`/`get_bone_name` sur le composant mesh du CDO du personnage). - **DĂ©tecter des rĂ©gressions d'assets binaires via git** : `git show : | git lfs smudge` restitue l'ancien `.uasset` ; comparer l'ensemble des chaĂźnes `/Game/...` (table des noms) entre ancienne et nouvelle version rĂ©vĂšle les rĂ©fĂ©rences perdues (lignes de chooser, bases d'un schĂ©ma, BPI d'un canal) sans ouvrir l'Ă©diteur. - **DĂ©placer un dossier via `AssetTools.rename_assets`** (liste d'`AssetRenameData`, un seul appel pour tout le lot) réécrit et sauvegarde lui-mĂȘme les rĂ©fĂ©renceurs, sans laisser de redirecteur quand tous sont chargeables (112 assets en ~32 s le 2026-09-14). Le coĂ»t dĂ©pend du nombre de rĂ©fĂ©renceurs : un notify utilisĂ© par des milliers d'animations oblige Ă  toutes les rĂ©enregistrer. --- ## 10. Maintenir ce document Ă  jour Ce document **doit toujours reflĂ©ter l'Ă©tat rĂ©el du projet**. Un skill dĂ©diĂ© — **`maintain-architecture-doc`** (`.claude/skills/maintain-architecture-doc/SKILL.md`) — rappelle systĂ©matiquement aux modĂšles d'IA de : 1. Consulter ce document avant de modifier la structure du projet. 2. Le mettre Ă  jour aprĂšs toute crĂ©ation/suppression/dĂ©placement/renommage de fichier ou dossier important. 3. Ajouter une description pour tout nouveau fichier important. 4. Retirer les entrĂ©es obsolĂštes (fichiers supprimĂ©s). 5. Corriger les chemins aprĂšs un dĂ©placement. 6. Mettre Ă  jour les descriptions quand un systĂšme Ă©volue significativement. 7. VĂ©rifier pĂ©riodiquement la cohĂ©rence entre ce document et l'arborescence rĂ©elle. 8. Ne jamais laisser ce document dans un Ă©tat sciemment obsolĂšte aprĂšs une modification de structure. **RĂšgle de detail** : un fichier "important" Ă  documenter est un Blueprint/Widget/Data Asset/Struct/Enum/Input Action qui porte de la **logique ou des donnĂ©es de gameplay**. Les assets purement artistiques individuels (textures, meshes, clips d'animation, miniatures) n'ont pas besoin d'entrĂ©e dĂ©diĂ©e — il suffit que leur **dossier parent** soit listĂ© et dĂ©crit (cf. §8). *Historique de nettoyage :* - *2026-09-04 : `Content/Systems/Blueprints/d/SandboxCharacter_CMC_ABP` renommĂ©/dĂ©placĂ© vers `Content/Systems/Blueprints/SandboxCharacter_CMC_ABP` via l'outil de renommage Unreal (les 7 rĂ©fĂ©rences ont Ă©tĂ© recĂąblĂ©es automatiquement, compilation vĂ©rifiĂ©e OK).* - *2026-09-04 : suppression de 8 redirecteurs Unreal morts (rĂ©sidus de renommages passĂ©s, 0 rĂ©fĂ©rence chacun, confirmĂ©s sans danger) : `Content/Systems/Stats/ACStats.uasset`, `Content/Systems/Movement/BPC_ClimbingComponent.uasset`, `Content/Systems/Movement/ClimbingMaterial.uasset`, `Content/Systems/Movement/CR_ClimbingGraphV2.uasset`, `Content/Systems/Movement/CR_Mannequin_BasicFootIK.uasset`, `Content/BP_TickManager.uasset`, `Content/dqs.uasset`, `Content/E_WeaponType.uasset`. Les vraies versions de ces assets restent Ă  `Content/Systems/Movement/Climbing/`, `Content/Core/Tick/BP_TickManager` et `Content/Data/Enums/E_WeaponType`.* - *2026-09-13 : rĂ©paration aprĂšs la migration `Project_F` → `ProjectFv1` (voir §8.2) — 782 fichiers UltraDynamicSky restaurĂ©s depuis git, contexte de 7 chooser tables remis sur `Systems/Blueprints`, 3 structs identiques de `Content/Blueprints/Data/` fusionnĂ©es (redirecteurs), suppression de `Content/Blueprints/SandboxCharacter_CMC` + `_ABP` (doublon GASP), tags `Foley.Event.*`/`SmartObject.ObjectType.*` ajoutĂ©s. Compilation complĂšte : 435 Blueprints, 0 erreur.* - *2026-09-13 (nettoyage, Ă©tapes 1-2) : suppression des personnages de dĂ©mo Echo/Paragon/UE4_Mannequin/UE5_Mannequins, de `MetaHumans/` et des BP `RetargetedCharacters/BP_*` ; rangement de `SandboxCharacter_CMC` → `Core/Character/`, `BP_GameInstance` → `Core/`, `DT_DemoTags` → `Data/` (config mise Ă  jour) ; suppression de `DT_DemoTags.T3D` et des dossiers vides (dont `Content/Collections/`, `Content/Developers/`). Compilation : 405 Blueprints, 0 erreur.* - *2026-09-13/14 (nettoyage, Ă©tape 3) : suppression des redirecteurs morts aprĂšs re-sauvegarde de leurs rĂ©fĂ©renceurs (dont `Animations/anim_Swim*`, `Core/PlayerController/IA_InitiateClimb|IA_LeapFromClimb|IA_MovingClimb`, `PSD_Relaxed_Stand_Sprint_Pivots`, les redirecteurs du 2026-09-04 encore suivis par git, et les redirecteurs de structs de `Content/Blueprints/Data/`).* - *2026-09-14 : convergence des enums du framework dupliquĂ© et rĂ©paration des Blueprints touchĂ©s (voir §8.2) ; `GM_Dev` → `SandboxCharacter_CMC`. Passe complĂšte : 405 Blueprints ; seule erreur restante `BP_Item_AdvancedRifle` (`Reload_Rifle_Hip` sans squelette, antĂ©rieure) + avertissement `Ultra_Dynamic_Weather`. Commit intermĂ©diaire (point de restauration) avant le dĂ©placement du reste de `Content/Blueprints/` vers `Content/Systems/Mover/`.* - *2026-09-14 (isolation du framework du sample) : dĂ©mo GASP supprimĂ©e (`dev_map`, `Content/Levels/LevelPrototyping/`, `Content/Widgets/`) aprĂšs avoir dĂ©tachĂ© `AC_TraversalLogic` (branche `LevelBlock_Traversable`) et `PC_Sandbox` (widget de dĂ©mo) ; 17 redirecteurs d'enum supprimĂ©s ; 112 assets dĂ©placĂ©s sans fusion (`Content/Blueprints/` → `Systems/Mover/` sauf `AnimNotifies/`, `Aiming/` → `Systems/Aiming/`, `Content/Input/` → `Systems/Mover/Input/`, `E_WaponType` → `Data/Enums/`), rĂ©fĂ©rences réécrites, aucun redirecteur restant. ContrĂŽle aprĂšs redĂ©marrage complet de l'Ă©diteur : liens de graphe, valeurs de pins et types de variables des 66 Blueprints concernĂ©s encore existants identiques au relevĂ© pris avant le dĂ©placement (seuls Ă©carts : chemins réécrits et artefacts de l'outil de comparaison). Compilation complĂšte : 379 Blueprints, seule erreur `BP_Item_AdvancedRifle` (`Reload_Rifle_Hip` sans squelette, antĂ©rieure).* - *2026-09-14 (reprise) : test PIE sur `MapDev1` — `GM_Dev` fait apparaĂźtre `SandboxCharacter_CMC`, aucune erreur de Blueprint Ă  l'exĂ©cution. Seuls messages, antĂ©rieurs : `Systems/Weather/UltraDynamicSky/Particles/Snow` rĂ©fĂ©rence encore l'ancien chemin `/Game/UltraDynamicSky/Particles/UDW_Niagara_Parameters`, et 4 avertissements Pose Search d'entrĂ©es vides dans `PSD_SwimmingIdle`/`PSD_SwimmingMovingSprint` (contenu inchangĂ© depuis `d29748b`, de nouveau chargĂ© grĂące au chooser restaurĂ©). Restauration depuis `d29748b` des 7 donnĂ©es Motion Matching dĂ©gradĂ©es par la migration (voir §8.2) avec fix MatchAny refait, et de `NS_Tornado`. Compilation complĂšte : 379 Blueprints, seule erreur `BP_Item_AdvancedRifle` (`Reload_Rifle_Hip` sans squelette, antĂ©rieure).* *`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).*