17 KiB
Fiche CAM-B2e — Niveau N3 — Modèle prévu opus | utilisé claude-opus-5-5 (Opus 5.5) — Agent lp-mcp-bp — Skills sk-protocol, sk-change-safety, lp-mcp, lp-lot
CAM-B2e-IMPL : boîte de pièce sur les faces intérieures des murs (2026-10-13)
Consignes : CAM-B2e-FICHE.md (règle, nœuds existants, écritures 1 à 8) ; rubriques communes de CAM-B2b-FICHES.md
(l. 23-63). UE-GO de Big Boss pour le passage Room B2d + B2e (2026-10-13, cité par l'orchestrateur). Éditeur headless
PID 22060, port 8000, connexion unreal-mcp partagée (MCPA-T1) ; Room chargé, B2d en mémoire (non touché).
Un seul call_tool par message. 60 appels MCP : 21 create_node, 2 get_node_infos, 29 connect_pins,
4 set_pin_value, 1 compile_blueprint, 1 save_assets, 2 ObjectTools.get_properties (dont 1 en erreur de
schéma). Aucun break_pins (§ 2 E1), delete_node, write_graph_dsl ni ProgrammaticToolset. Aucune écriture par
HyperAIStudio.
1. Fichiers modifiés
Content/BPs/Room.uasset: enregistré (save_assets {asset_paths:["/Game/BPs/Room"]}→true), B2d et B2e ensemble. MD5 avante0517c63…(= instantané), aprèsca2a9a0baaca4130fd5c318797f008ae(§ 3).- Graphe
/Game/BPs/Room.Room:EventGraph, nouveaux nœuds en x 38000-39150, y 1200-2000 (sousComputeRoomBox).
1.1 Nœuds créés (préfixe refPath : /Game/BPs/Room.Room:EventGraph.)
| Chaîne | Rôle | refPath (suffixe) |
type_id relu |
Position |
|---|---|---|---|---|
| Wall1 (−X) | getter Wall1 |
K2Node_VariableGet_297 |
|GetWall1 (créé par Variables|Pardéfaut|ObtenirWall1) |
38000, 1200 |
GetComponentBounds(Wall1) |
K2Node_CallFunction_525 |
Collision|GetComponentBounds |
38300, 1200 | |
| O + E | K2Node_PromotableOperator_37 |
Math|Vecteur|vector+vector |
38650, 1200 | |
| + (30,30,0) | K2Node_PromotableOperator_38 |
Math|Vecteur|vector+vector |
38900, 1200 | |
BreakVector → X |
K2Node_CallFunction_530 |
Math|Vecteur|BreakVector |
39150, 1200 | |
| Wall2 (+X) | GetComponentBounds(283) |
K2Node_CallFunction_526 |
Collision|GetComponentBounds |
38300, 1400 |
| O − E | K2Node_PromotableOperator_39 |
Math|Vecteur|vector-vector |
38650, 1400 | |
| − (30,30,0) | K2Node_PromotableOperator_40 |
Math|Vecteur|vector-vector |
38900, 1400 | |
BreakVector → X |
K2Node_CallFunction_531 |
Math|Vecteur|BreakVector |
39150, 1400 | |
| Wall3 (−Y) | getter Wall3 |
K2Node_VariableGet_298 |
|GetWall3 (créé par Variables|Pardéfaut|ObtenirWall3) |
38000, 1600 |
GetComponentBounds(Wall3) |
K2Node_CallFunction_527 |
Collision|GetComponentBounds |
38300, 1600 | |
| O + E | K2Node_PromotableOperator_41 |
Math|Vecteur|vector+vector |
38650, 1600 | |
| + (30,30,0) | K2Node_PromotableOperator_42 |
Math|Vecteur|vector+vector |
38900, 1600 | |
BreakVector → Y |
K2Node_CallFunction_532 |
Math|Vecteur|BreakVector |
39150, 1600 | |
| Wall4 (+Y) | GetComponentBounds(284) |
K2Node_CallFunction_528 |
Collision|GetComponentBounds |
38300, 1800 |
| O − E | K2Node_PromotableOperator_43 |
Math|Vecteur|vector-vector |
38650, 1800 | |
| − (30,30,0) | K2Node_PromotableOperator_44 |
Math|Vecteur|vector-vector |
38900, 1800 | |
BreakVector → Y |
K2Node_CallFunction_533 |
Math|Vecteur|BreakVector |
39150, 1800 | |
| WallT | GetComponentBounds(285) |
K2Node_CallFunction_529 |
Collision|GetComponentBounds |
38300, 2000 |
| O − E (face inférieure) | K2Node_PromotableOperator_45 |
Math|Vecteur|vector-vector |
38650, 2000 | |
BreakVector → Z |
K2Node_CallFunction_534 |
Math|Vecteur|BreakVector |
39150, 2000 |
Broches relues avant câblage (get_node_infos groupé, 7 créés + 492, 493, PO_15, 283, 284, 285) :
GetComponentBounds : Component in 0 (Scene Component Référence d'objet), Origin out 0 (Vector), BoxExtent out 1
(Vector), SphereRadius out 2 (Float (simple précision), non relié) ; getters out 0 (Static Mesh Component Référence d'objet) ; opérateurs A 0, B 1, sortie 0 (génériques à la création, typés Vector à la première liaison) ;
BreakVector InVec 0, X 0 / Y 1 / Z 2. État relu avant écriture : 492.X ← 484.0, 492.Y ← 484.1, 492.Z ← PO_14 ;
493.X ← 485.0, 493.Y ← 485.1, 493.Z ← 491 ; PO_15.A ← 488.2, PO_15.B = 25.0 ; 283 → 476, 284 → 477, 285 → 487
(conforme aux rapports F1, F2 et à la fiche).
1.2 Liens faits (connect_pins, 29, tous {"returnValue":null})
| # | Sortie (nœud.broche index) | Entrée (nœud.broche index) | Fiche |
|---|---|---|---|
| L1 | VariableGet_297.0 | CallFunction_525.Component 0 | 1 |
| L2 | CallFunction_525.Origin 0 | PromotableOperator_37.A 0 | 1 |
| L3 | CallFunction_525.BoxExtent 1 | PromotableOperator_37.B 1 | 1 |
| L4 | PromotableOperator_37.0 | PromotableOperator_38.A 0 | 1 |
| L5 | PromotableOperator_38.0 | CallFunction_530.InVec 0 | 1 |
| L6 | CallFunction_530.X 0 | CallFunction_492.X 0 (remplace 484.X) | 1 |
| L7 | VariableGet_283.0 | CallFunction_526.Component 0 | 2 |
| L8 | CallFunction_526.Origin 0 | PromotableOperator_39.A 0 | 2 |
| L9 | CallFunction_526.BoxExtent 1 | PromotableOperator_39.B 1 | 2 |
| L10 | PromotableOperator_39.0 | PromotableOperator_40.A 0 | 2 |
| L11 | PromotableOperator_40.0 | CallFunction_531.InVec 0 | 2 |
| L12 | CallFunction_531.X 0 | CallFunction_493.X 0 (remplace 485.X) | 2 |
| L13 | VariableGet_298.0 | CallFunction_527.Component 0 | 3 |
| L14 | CallFunction_527.Origin 0 | PromotableOperator_41.A 0 | 3 |
| L15 | CallFunction_527.BoxExtent 1 | PromotableOperator_41.B 1 | 3 |
| L16 | PromotableOperator_41.0 | PromotableOperator_42.A 0 | 3 |
| L17 | PromotableOperator_42.0 | CallFunction_532.InVec 0 | 3 |
| L18 | CallFunction_532.Y 1 | CallFunction_492.Y 1 (remplace 484.Y) | 3 |
| L19 | VariableGet_284.0 | CallFunction_528.Component 0 | 4 |
| L20 | CallFunction_528.Origin 0 | PromotableOperator_43.A 0 | 4 |
| L21 | CallFunction_528.BoxExtent 1 | PromotableOperator_43.B 1 | 4 |
| L22 | PromotableOperator_43.0 | PromotableOperator_44.A 0 | 4 |
| L23 | PromotableOperator_44.0 | CallFunction_533.InVec 0 | 4 |
| L24 | CallFunction_533.Y 1 | CallFunction_493.Y 1 (remplace 485.Y) | 4 |
| L25 | VariableGet_285.0 | CallFunction_529.Component 0 | 5 |
| L26 | CallFunction_529.Origin 0 | PromotableOperator_45.A 0 | 5 |
| L27 | CallFunction_529.BoxExtent 1 | PromotableOperator_45.B 1 | 5 |
| L28 | PromotableOperator_45.0 | CallFunction_534.InVec 0 | 5 |
| L29 | CallFunction_534.Z 2 | PromotableOperator_15.A 0 (remplace 488.Z) | 5 |
Valeurs (set_pin_value, toutes {"returnValue":null}, relues "value":"30,30,0") : B 1 de PromotableOperator_38,
_40, _42 et _44 = 30,30,0. PromotableOperator_15.B reste 25.0 (relu).
1.3 Liens coupés
Les 5 liens remplacés, coupés par connect_pins sur une entrée déjà reliée (§ 2 E1) : 484.X 0 → 492.X 0 ;
484.Y 1 → 492.Y 1 ; 485.X 0 → 493.X 0 ; 485.Y 1 → 493.Y 1 ; 488.Z 2 → PO_15.A 0. Aucun autre lien touché.
1.4 Relecture (get_node_infos groupé final, 24 nœuds : 21 créés + 492, 493, PO_15)
Les 29 liens apparaissent des deux côtés. Entrées cibles, un seul lien chacune : 492.X ← 530.X ; 492.Y ← 532.Y ;
492.Z ← PO_14 (inchangé) ; 493.X ← 531.X ; 493.Y ← 533.Y ; 493.Z ← 491 (inchangé) ; PO_15.A ← 534.Z, B = 25.0,
sortie → 491.B 1 (inchangée). Sorties de 492 → VariableSet_64.1 et de 493 → VariableSet_65.1 inchangées. Les huit
opérateurs sont typés (vector+vector 37, 38, 41, 42 ; vector-vector 39, 40, 43, 44, 45), A et B en Vector.
Aucune divergence avec la fiche.
Chaîne obtenue (ComputeRoomBox) :
C2BoxMin := (W1.O.X + W1.E.X + 30, W3.O.Y + W3.E.Y + 30, sol.Z + 50);C2BoxMax := (W2.O.X − W2.E.X − 30, W4.O.Y − W4.E.Y − 30, SelectFloat(1000000, WallT.O.Z − WallT.E.Z − 25, Ext)). Les anciens nœuds de calcul (PO_9 à PO_13, 476 à 485, 487, 488) restent en place, sans consommateur en aval de 484, 485 et 488 (fiche, point 6) ; purs, ils ne sont plus évalués.
1.5 Compilation et enregistrement
compile_blueprint {blueprint:{refPath:"/Game/BPs/Room.Room"}, warnings_as_errors:true}→{"returnValue":null}, aucune exception (B2d + B2e en mémoire).hyper_blueprint_debug_inspectnon appelé (absent du serveur le 2026-10-10, mémoireunreal-mcp-reconnect, non revérifié) ; journal de l'éditeur non lu (chemin-abslognon fourni).AssetTools.save_assets {asset_paths:["/Game/BPs/Room"]}→{"returnValue":true}, Room seul.
1.6 Lecture de la collision (point 7, lecture seule, arrêtée à Wall1 faute de tours)
ObjectTools.get_properties {instance:{refPath:"/Game/BPs/Room.Room_C:Wall1_GEN_VARIABLE"}, properties:["BodyInstance"]}
(gabarit du composant de Wall1 dans la classe générée), extrait tel quel :
"objectType":"ECC_WorldDynamic","collisionEnabled":"QueryAndPhysics", ... "collisionProfileName":"Custom",
"collisionResponses":{"responseArray":[]}, ... "bSimulatePhysics":false
Le premier appel (object, property_names) a échoué sur le schéma ; il a rendu le schéma exact
(instance, properties). Wall2, Wall3, Wall4 et WallT : non lus (budget atteint).
Lecture (estimé, non vérifié) : profil Custom avec responseArray vide, donc aucune réponse surchargée. Le canal
Camera garderait la réponse par défaut du conteneur, ECR_Block sauf réglage contraire dans
DefaultEngine.ini. Ce point est à confirmer : il faut lire DefaultEngine.ini (DefaultChannelResponses) et les
instances placées. Une instance de niveau ou le C++ (LPOutdoorRoomSubsystem) peuvent changer la collision à
l'exécution.
2. Écarts à la SPEC
- E1 (procédure, même résultat) : la fiche prescrit
break_pinsavant de relier 492.X (point 1) et PO_15.A (point 5), et par extension 493.X, 492.Y et 493.Y. Les 5 coupures sont faites parconnect_pinslui-même. Preuve par les sources du moteur installé :connect_pinsappelleout.try_create_connection(inp)(D:\Game\Launcher\Engine\UE_5.8\Engine\Plugins\Experimental\Toolsets\EditorToolset\Content\Python\editor_toolset\toolsets\blueprint.py:1067). Cet appel aboutit àUEdGraphSchema_K2::TryCreateConnection(…\Engine\Source\Editor\BlueprintEditorLibrary\Private\BlueprintEditorLibrary\BlueprintGraphPin.cpp:92-102). Pour une entrée de donnée déjà reliée, le schéma répondCONNECT_RESPONSE_BREAK_OTHERS_*(…\Engine\Source\Editor\BlueprintGraph\Private\EdGraphSchema_K2.cpp:2086-2088) : l'ancien lien est coupé, puis le nouveau est fait. Le § 1.4 vérifie le résultat : chaque entrée n'a qu'un lien, le nouveau. Motif : le budget. Les 5break_pinsauraient porté l'enregistrement au-delà des 65 tours (même motif que B2d E2). - E2 (ordre) : la lecture des nœuds existants est faite après la création des 21 nœuds et avant tout câblage, en
un seul appel groupé avec les nœuds créés, comme en B2d (§ 1.2 de
CAM-B2d-IMPL.md). Créer des nœuds non reliés ne touche aucun nœud existant. - Garde
Accessed None: aucuneIsValidajoutée (ni la SPEC ni la fiche n'en demandent). Lectures nouvelles :Wall1(297) etWall3(298) dansComputeRoomBox.Wall1a un gabarit de composant dans la classe générée (Room_C:Wall1_GEN_VARIABLE, lu au § 1.6). C'est un composant de la construction, « vide » n'y est pas un état normal (estimé).Wall3est supposé du même type, sans lecture.Wall2,Wall4etWallTétaient déjà lus (476, 477, 487). - Comportement : changement voulu (faces intérieures au lieu des centres des murs).
ZMin, le choix extérieur (491) et les affectations (64, 65) sont inchangés (relus). - Aucun nœud de B2d touché (513-524, PO28, PO30, 96, 97, CE48) : aucun appel ne les vise.
3. Instantané
Fait par l'orchestrateur (non refait, consigne) : D:\Game\LifePlay_Backup_5.5\CAM-B2d\. Relevé avant écriture :
date -Iseconds; md5sum "/d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset"; grep -i "Room.uasset" "/d/Game/LifePlay_Backup_5.5/CAM-B2d/manifest.csv"; git -C "/d/Game/LifePlay-master 5.8" rev-parse --short HEAD
2026-10-13T17:24:45+02:00
e0517c63541f249bd9dbda5c39815ba5 */d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset
"Content\BPs\Room.uasset","True","6318319","E0517C63541F249BD9DBDA5C39815BA5","2026-10-13T17:11:26"
0745917
Relevé après save_assets :
date -Iseconds; md5sum "/d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset"; ls -l "/d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset"; git -C "/d/Game/LifePlay-master 5.8" status --short -- Content Source Config
2026-10-13T17:29:45+02:00
ca2a9a0baaca4130fd5c318797f008ae */d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset
-rw-r--r-- 1 <compte> 197609 6378087 Oct 13 17:29 /d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset
M Content/BPs/Person.uasset
M Content/BPs/Room.uasset
M Source/LifePlay/LPDebugSubsystem.cpp
M Source/LifePlay/LPDebugSubsystem.h
M Source/LifePlay/LPOutdoorRoomSubsystem.cpp
M Source/LifePlay/LPOutdoorRoomSubsystem.h
?? Source/LifePlay/LPCameraModeSubsystem.cpp
?? Source/LifePlay/LPCameraModeSubsystem.h
Le MD5 diffère de E0517C63 (attendu). Le git status correspond à l'état annoncé par l'orchestrateur : Person,
LPDebugSubsystem., LPOutdoorRoomSubsystem. et LPCameraModeSubsystem.* viennent d'autres fiches et ne sont pas
touchés ici. Retour arrière, proposé et jamais lancé : Tools\Restore.ps1 -Lot CAM-B2d -Only Content\BPs\Room.uasset,
éditeur fermé, sur décision de l'orchestrateur. Il ramène Room à E0517C63, l'état B2b, et perd B2d et B2e.
4. Ce qui n'a pas été fait
- Point 7 : collision de Wall2, Wall3, Wall4 et WallT non lue (budget). Réponse effective au canal Camera non établie (§ 1.6).
- Anciens nœuds (point 6) laissés en place, conformément à la fiche (nettoyage plus tard).
hyper_blueprint_debug_inspect, journal de l'éditeur : non consultés (§ 1.5).- Valeurs de
C2BoxMin/C2BoxMaxà l'exécution : non mesurées (pas de PIE ni de build) ; preuve en jeu (build empaqueté +LogStats) hors rôle. Éditeur laissé ouvert (fermeture : orchestrateur, puisBUILD-FIN).
5. Points à confirmer en VAL
- V5 (fiche) par dump après fermeture de l'éditeur :
GetComponentBounds≥ 5 dansComputeRoomBox(525 à 529) ; 492.X ← 530.X, 492.Y ← 532.Y, 493.X ← 531.X, 493.Y ← 533.Y ; PO_15.A ← 534.Z (O − E de WallT) ; valeurs30,30,0sérialisées sur PO_38, _40, _42, _44. - Orientation (estimé, risque) : la règle suppose des pièces sans rotation, Wall1 en −X du monde et Wall2 en +X.
Une Room tournée de 180° en lacet donne MinX > MaxX : la boîte est croisée. Une Room tournée de 90° fait que X et Y
ne correspondent plus aux murs. L'ancienne formule (
Abs, F1) supportait 180°. Il faut vérifier que les pièces placées ou générées ont toutes un lacet de 0. - Bornes croisées : la garde
Vector_ComponentMaxde F1 (483) n'est plus sur le chemin. Une pièce de moins de 60 unités utiles entre les faces (ou WallT − 25 < sol + 50) donne Min > Max dansVectorBoundedToBox. Ce comportement n'est pas vérifié. - Extérieur : les murs sont écrasés en Z (échelle 0,01) mais gardent leur emprise XY.
WallTest toujours évalué (pur) même quandSelectFloatchoisit 1000000 : aucunAccessed Noneattendu, à vérifier parLogStats. - Lectures nouvelles
Wall1(297),Wall3(298) : à vérifier parLogStats(aucunAccessed NonesurComputeRoomBox). - Collision : réponse au canal Camera de Wall1 à Wall4 et WallT (gabarits et instances), et
DefaultEngine.ini(§ 1.6). Wall1 :Custom,responseArrayvide. - Essai de la fiche : dos au mur des 4 côtés, dans un coin, en hauteur, et dans une pièce redimensionnée. Aucune vue de l'extérieur ne doit apparaître.
- Compilation stricte jugée sur l'absence d'exception seulement : à recontrôler par
CompileAllBlueprints, éditeur fermé (V6).
6. Fichiers à commiter
A Docs/Migration/etat/CAM/CAM-B2e-IMPL.md(dépôt du jeu, brancheue5.8).M Content/BPs/Room.uasset(dépôt du jeu, brancheue5.8) : B2d et B2e enregistrés ensemble, MD5ca2a9a0b…. Commit après VAL et essai, sur ticket de l'orchestrateur.
Tours : 65 / 65 (63 de travail ; le livrable et le compte rendu sont dans la marge)
Constats
- À verser :
lp-mcp§ 3.connect_pinspasse parUEdGraphSchema_K2::TryCreateConnection(blueprint.py:1067,BlueprintGraphPin.cpp:92-102). Sur une entrée de donnée déjà reliée, il remplace l'ancien lien (EdGraphSchema_K2.cpp:2086-2088) : aucunbreak_pinspréalable n'est nécessaire, à relire ensuite.break_pinsvérifie le lien puis appellebreak_single_pin_link(blueprint.py:1074-1087). - À verser :
lp-mcp§ 3. Lecture d'un composant de Blueprint :ObjectTools.get_properties {instance:{refPath:"/Game/BPs/X.X_C:<Composant>_GEN_VARIABLE"}, properties:[…]}. Code des outils Epic :D:\Game\Launcher\Engine\UE_5.8\Engine\Plugins\Experimental\Toolsets\EditorToolset\Content\Python\editor_toolset\toolsets\. - À verser :
lp-mcp§ 3.Collision|GetComponentBounds: Component in 0 ; Origin out 0, BoxExtent out 1, SphereRadius out 2 (nœud pur).Variables|Pardéfaut|ObtenirWall1/ObtenirWall3acceptés tels quels. - Ordre efficace (60 appels pour 21 nœuds et 29 liens) : toutes les créations, puis une lecture groupée (créés +
existants), puis le câblage chaîne par chaîne,
set_pin_valuejuste après le typage de l'opérateur, puis une relecture finale groupée.