13 KiB
Fiche CAM-B2b-F4 — 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-B2b-F4-IMPL : trajectoire protégée de la poursuite (B2b-4) (2026-10-13)
Consignes : CAM-B2b-FICHES.md § « Rubriques communes » (l. 23-63) et § « F4 » (l. 106-113) ; SPEC CAM-SPEC.md
§ « CAM-B2b », ligne B2b-4 (l. 378). UE-GO / BUILD-GO de Big Boss du 2026-10-13 (cité par l'orchestrateur). Éditeur
headless PID 10708, port 8000, connexion unreal-mcp partagée (MCPA-T1) ; Room chargé avec F1 à F3 en mémoire. Un seul
call_tool par message ; 33 appels MCP au total (6 create_node, 3 break_pins, 17 connect_pins, 3 set_pin_value,
3 get_node_infos, 1 compile_blueprint). Aucun delete_node, save_assets, write_graph_dsl ni ProgrammaticToolset.
1. Fichiers modifiés
Content/BPs/Room.uasset: modifié en mémoire de l'éditeur seulement, non enregistré (pas desave_assetsavant F7). Preuve : MD5 disque avant et après F4 = MD5 de l'instantané (§ 3).- Graphe
/Game/BPs/Room.Room:EventGraph, zone de la poursuite (UpdateRoomCam, 467 en 31050, 5100) ; nœuds neufs en x 31450-33050, y 4500-6350.
1.1 Lecture avant écriture (get_node_infos groupé, 8 nœuds existants)
Conforme à la fiche : CallFunction_467 (|ComputeC2Target, execute ← IfThenElse_93.1) then 0 → 474.execute 0 ;
CallFunction_468 (Math|Interpolation|VInterpTo, Current ← 471, Target ← VariableGet_280, DeltaTime ← 470,
InterpSpeed 8.0) sortie 0 → 473.Start 0 et → 474.NewLocation 2 ; CallFunction_474
(Transformation|SetActorLocationAndRotation, self ← VariableGet_268, NewRotation ← 469, bSweep false) ;
CallFunction_473 (FindLookAtRotation, Target ← 455, sortie → 469.1) ; CallFunction_455 (GetSocketLocation,
self ← VariableGet_264, head) sortie 0 → 457, 459, 464, 473 ; MakeArray_5 ([0] ← 261, [1] ← 268) → 459.6 ;
VariableGet_286 (|GetC2BoxMin) → 495.1, 496.1 ; VariableGet_287 (|GetC2BoxMax) → 495.2, 496.2.
1.2 Nœuds créés (préfixe refPath : /Game/BPs/Room.Room:EventGraph.)
| Rôle | refPath (suffixe) |
type_id demandé → relu |
Broches relues | Position |
|---|---|---|---|---|
| Trace de la poursuite | K2Node_CallFunction_499 |
Collision|SphereTraceByChannel → idem |
execute 0, Start 1, End 2, Radius 3, TraceChannel 4, bTraceComplex 5, ActorsToIgnore 6, DrawDebugType 7, bIgnoreSelf 8, TraceColor 9, TraceHitColor 10, DrawTime 11 ; then 0, OutHit 1, ReturnValue 2 | 31450, 4500 |
BreakHitResult |
K2Node_CallFunction_500 |
Collision|BreakHitResult → idem |
Hit 0 ; Location out 4, Normal out 6 (18 sorties) | 31900, 6100 |
| Normal × 20 | K2Node_PromotableOperator_20 |
Utilitaires|Opérateurs|Multiplier → Math|Vecteur|vector*vector (après liaison A) |
A 0, B 1 ; out 0 | 32250, 6350 |
| Location + (Normal × 20) | K2Node_PromotableOperator_21 |
Utilitaires|Opérateurs|Ajouter → Math|Vecteur|vector+vector (après liaison A) |
A 0, B 1 ; out 0 | 32500, 6150 |
SelectVector |
K2Node_CallFunction_501 |
Math|Vecteur|SelectVector → idem |
A 0, B 1, bPickA 2 ; out 0 | 32750, 5950 |
Safe = borne |
K2Node_CallFunction_502 |
Math|Vecteur|VectorBoundedtoBox → Math|Vecteur|Vector_BoundedToBox |
InVect 0, InBoxMin 1, InBoxMax 2 ; out 0 | 33050, 5950 |
Les deux opérateurs ont à la création le type_id trompeur déjà vu en F3 (Utilitaires|Gestiondutemps|Seconds*FrameRate,
…|FrameNumber+Int) et des broches Caractère de remplacement ; relus typés Vector à la relecture finale.
Réutilisés sans copie (nœuds purs) : 455, 468, MakeArray_5, VariableGet_286, VariableGet_287.
1.3 Liens coupés (break_pins, 3, tous {"returnValue":null})
| # | Sortie | Entrée | Point de la fiche |
|---|---|---|---|
| C1 | CallFunction_467.then 0 | CallFunction_474.execute 0 | 1 |
| C2 | CallFunction_468.ReturnValue 0 | CallFunction_474.NewLocation 2 | 3 |
| C3 | CallFunction_468.ReturnValue 0 | CallFunction_473.Start 0 | 3 |
1.4 Liens faits (connect_pins, 17, tous {"returnValue":null})
| # | Sortie | Entrée |
|---|---|---|
| L1 | CallFunction_467.then 0 | CallFunction_499.execute 0 |
| L2 | CallFunction_499.then 0 | CallFunction_474.execute 0 |
| L3 | CallFunction_455.0 (tête) | CallFunction_499.Start 1 |
| L4 | CallFunction_468.0 (VInterpTo) |
CallFunction_499.End 2 |
| L5 | MakeArray_5.0 ([MC, CamRoom]) | CallFunction_499.ActorsToIgnore 6 |
| L6 | CallFunction_499.OutHit 1 | CallFunction_500.Hit 0 |
| L7 | CallFunction_500.Normal 6 | PromotableOperator_20.A 0 |
| L8 | CallFunction_500.Location 4 | PromotableOperator_21.A 0 |
| L9 | PromotableOperator_20.0 | PromotableOperator_21.B 1 |
| L10 | PromotableOperator_21.0 | CallFunction_501.A 0 |
| L11 | CallFunction_468.0 | CallFunction_501.B 1 |
| L12 | CallFunction_499.ReturnValue 2 | CallFunction_501.bPickA 2 |
| L13 | CallFunction_501.0 | CallFunction_502.InVect 0 |
| L14 | VariableGet_286.0 (C2BoxMin) |
CallFunction_502.InBoxMin 1 |
| L15 | VariableGet_287.0 (C2BoxMax) |
CallFunction_502.InBoxMax 2 |
| L16 | CallFunction_502.0 (Safe) |
CallFunction_474.NewLocation 2 |
| L17 | CallFunction_502.0 (Safe) |
CallFunction_473.Start 0 |
1.5 Valeurs (set_pin_value, 3, toutes {"returnValue":null}, relues)
| Broche | Avant (relu à la création) | Après (relu) |
|---|---|---|
| CallFunction_499.Radius 3 | 0.0 |
20.0 |
| CallFunction_499.TraceChannel 4 | TraceTypeQuery1 |
TraceTypeQuery2 |
| PromotableOperator_20.B 1 | (neuf, "") |
20.0,20.0,20.0 |
Valeurs non prescrites de 499, laissées par défaut et relues identiques à 459 (trace de ComputeC2Target) :
bTraceComplex false, DrawDebugType None, bIgnoreSelf true, TraceColor (R=1,G=0,B=0,A=1), TraceHitColor
(R=0,G=1,B=0,A=1), DrawTime 5.000000.
1.6 Relecture et chaîne obtenue
get_node_infos final groupé sur les 14 nœuds touchés ou réutilisés (6 créés + 467, 468, 474, 473, 455, MakeArray_5,
286, 287) : les 3 coupures sont absentes des deux côtés (467.then ne sort plus que vers 499 ; 468.0 ne sort plus que vers
499.End et 501.B ; 474.NewLocation et 473.Start ne reçoivent plus que 502) ; les 17 liens apparaissent des deux côtés ;
les 3 valeurs relues ; types : vecteurs Vector, bPickA Booléen, Radius Float (simple précision). Liens non
touchés relus intacts : 467.execute ← IfThenElse_93.1 ; 468 ← 471, 280, 470 (InterpSpeed 8.0) ; 474.self ← 268,
474.NewRotation ← 469, bSweep false ; 473.Target ← 455, 473.0 → 469.1 ; 455 → 457, 459, 464, 473 (plus 499) ;
MakeArray_5 → 459.6 (plus 499.6), [0] ← 261, [1] ← 268 ; 286 / 287 → 495, 496 (plus 502). Aucune divergence.
Chaîne de la poursuite : IfThenElse_93.else → ComputeC2Target (467 ; recalcule la boîte par ComputeRoomBox, F3) →
SphereTraceByChannel(tête → VInterpTo, r 20, TraceTypeQuery2, ignorer [MC, CamRoom] + self) (499) →
SetActorLocationAndRotation(CamRoom, Safe, LookAt(Safe → tête)) (474), avec
Safe = Bound(touché ? Location + Normal × 20 : VInterpTo, C2BoxMin, C2BoxMax).
1.7 Compilation
compile_blueprint {blueprint:{refPath:"/Game/BPs/Room.Room"}, warnings_as_errors:true} → {"returnValue":null},
aucune exception (critère de la rubrique « Fin de chaque fiche »). hyper_blueprint_debug_inspect non appelé (absent
du serveur le 2026-10-10, mémoire unreal-mcp-reconnect ; non revérifié) ; journal de l'éditeur non lu (chemin
-abslog non fourni). Pas de save_assets (F7).
2. Écarts à la SPEC
- Aucun écart de câblage : la ligne B2b-4 (
CAM-SPEC.md:378) et la fiche F4 (CAM-B2b-FICHES.md:106-113) sont réalisées telles quelles, points 1 à 3 dans l'ordre ; aucun nœud hors fiche touché. Hit.Normal × 20(SPEC, scalaire) est réalisé parvector*vectoravec B = (20,20,20) (fiche) : équivalent composante par composante.- « Location » = sortie
Location(4) deBreakHitResult, centre de la sphère au contact, et nonImpactPoint(5) : comme460.Location → PO7.AdansComputeC2Target(lu en F3). - Garde
Accessed None: aucuneIsValidajoutée (aucune demandée). Les nœuds neufs ne lisent aucune référence d'objet (vecteurs, structure de touche, booléen).SelectVectorest pur et évalue A et B : ni l'un ni l'autre ne déréférence d'objet, donc pas de cascade de branches requise. En revanche, 455 (GetSocketLocation, self ←VariableGet_264) est désormais évalué une fois de plus par passage (499.Start, en plus de 473.Target) ; si sa cible est nulle, unAccessed Nonedéjà présent serait compté deux fois (point 3 du § 5). - Ordre des écritures :
set_pin_valuede PO20.B posé juste après la liaison A (typage), comme en F3 ; typage et valeur confirmés à la relecture finale (§ 1.6). - Positions des nœuds : choisies hors des nœuds existants (cosmétique, non prescrites).
3. Instantané
Fait par l'orchestrateur avant F1 (non refait, consigne). Manifeste relu :
grep -i "Room.uasset" "/d/Game/LifePlay_Backup_5.5/CAM-B2b/manifest.csv"
"Content\BPs\Room.uasset","True","6060745","A5FA970E821DC2D0D9BF220FD43B9DE6","2026-10-13T15:25:45"
Disque mesuré :
md5sum "/d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset"
a5fa970e821dc2d0d9bf220fd43b9de6 */d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset (2026-10-13T15:47:51+02:00, avant F4)
a5fa970e821dc2d0d9bf220fd43b9de6 */d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset (2026-10-13T15:50:09+02:00, après F4)
= instantané : rien d'enregistré. Retour arrière avant F7 : fermer l'éditeur sans enregistrer (perd F1 à F4) ; après
F7 : Tools\Restore.ps1 -Lot CAM-B2b -Only Content\BPs\Room.uasset, éditeur fermé, sur décision de l'orchestrateur
(jamais lancé ici).
4. Ce qui n'a pas été fait
- F5 et suivantes (repli vers le haut, pilotage, enregistrement) : hors périmètre.
hyper_blueprint_debug_inspect, journal de l'éditeur : non consultés (§ 1.7).save_assets: interdit avant F7 ; F1 à F4 vivent en mémoire de l'éditeur PID 10708 (une fermeture ou un plantage avant F7 les perd ; l'instantané reste intact).- Comportement à l'exécution : non mesuré (aucune PIE, aucun build) ; seulement déduit du câblage.
- Preuve en jeu (build empaqueté +
LogStats) : hors rôle.
5. Points à confirmer en VAL
- Cas « pas de touche, cible dans la boîte » :
Safe = 468(estimé par le câblage), donc trajectoire identique à B2. Hypothèse : 468 (VInterpTo, pur) rend la même valeur à ses trois évaluations du passage (499.End, 501.B via 474 et 473) car Current (471), Target (280) et DeltaTime (470) ne changent pas entre la trace et 474 (estimé). - Changement voulu : touche →
Location + Normal × 20; toujours borné parC2BoxMin/C2BoxMax. À confirmer en jeu : la caméra de poursuite ne sort jamais de la pièce et ne passe pas derrière un obstacle du canal Camera (TraceTypeQuery2, à rapprocher du canal Camera deDefaultEngine.ini, non relu ici). LogStats: aucunAccessed Nonenouveau ; en particulier surVariableGet_264(cible de 455), désormais lu deux fois par passage de la poursuite.- Boîte valide au moment de la trace :
ComputeRoomBoxest appelé parComputeC2Target(467) juste avant 499 (F3) ; une boîte dégénérée (min > max sur un axe) ferait renvoyer une borne fixe parVector_BoundedToBox(incertain : non lu dans le moteur ; relève de F1-F2). - Valeurs sérialisées après
save_assets(F7) :499.Radius = 20,499.TraceChannel = TraceTypeQuery2,PO20.B = (20,20,20), par dump (LPDumpFunction). - Compilation stricte jugée sur l'absence d'exception seulement ; recontrôle en F7 et par
CompileAllBlueprints. - V5 (
CAM-SPEC.md:382) :SphereTraceSingleattendu 3 après B2b ; F4 en ajoute 1 (459 + 499 + celle de F5 prévue).
6. Fichiers à commiter
A Docs/Migration/etat/CAM/CAM-B2b-IMPL-F4.md(dépôt du jeu, brancheue5.8).Content/BPs/Room.uasset: rien à commiter pour F4 (non enregistré) ; il le sera après F7 et la VAL.
Tours : 39 / 60
Constats
Collision|SphereTraceByChannelneuf : Radius0.0, TraceChannelTraceTypeQuery1par défaut ; les autres entrées par défaut sont celles de 459 (bIgnoreSelftrue, DrawDebugTypeNone).Collision|BreakHitResult: Hit 0 ; sorties bBlockingHit 0, bInitialOverlap 1, Time 2, Distance 3, Location 4, ImpactPoint 5, Normal 6, ImpactNormal 7, PhysMat 8, HitActor 9, HitComponent 10, HitBoneName 11, BoneName 12, HitItem 13, ElementIndex 14, FaceIndex 15, TraceStart 16, TraceEnd 17.Math|Vecteur|SelectVector: A 0, B 1, bPickA 2 (défautfalse) ; out 0.Utilitaires|Opérateurs|Ajouterrelié en A à un vecteur devientMath|Vecteur|vector+vector.- Économie : créer tous les nœuds, une lecture groupée (6 neufs + 459 pour comparer les défauts), câbler et poser les valeurs, une relecture finale (14 nœuds) : 33 appels pour 6 nœuds, 3 coupures, 17 liens, 3 valeurs.