185 lines
13 KiB
Markdown
185 lines
13 KiB
Markdown
|
|
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 de `save_assets`
|
|||
|
|
avant 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é par `vector*vector` avec B = (20,20,20) (fiche) : équivalent
|
|||
|
|
composante par composante.
|
|||
|
|
- « Location » = sortie `Location` (4) de `BreakHitResult`, centre de la sphère au contact, et non `ImpactPoint` (5) :
|
|||
|
|
comme `460.Location → PO7.A` dans `ComputeC2Target` (lu en F3).
|
|||
|
|
- Garde `Accessed None` : aucune `IsValid` ajoutée (aucune demandée). Les nœuds neufs ne lisent aucune référence
|
|||
|
|
d'objet (vecteurs, structure de touche, booléen). `SelectVector` est 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, un `Accessed None` déjà présent serait compté deux fois (point 3 du § 5).
|
|||
|
|
- Ordre des écritures : `set_pin_value` de 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
|
|||
|
|
|
|||
|
|
1. 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é).
|
|||
|
|
2. Changement voulu : touche → `Location + Normal × 20` ; toujours borné par `C2BoxMin` / `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 de `DefaultEngine.ini`, non relu ici).
|
|||
|
|
3. `LogStats` : aucun `Accessed None` nouveau ; en particulier sur `VariableGet_264` (cible de 455), désormais lu deux
|
|||
|
|
fois par passage de la poursuite.
|
|||
|
|
4. Boîte valide au moment de la trace : `ComputeRoomBox` est appelé par `ComputeC2Target` (467) juste avant 499 (F3) ;
|
|||
|
|
une boîte dégénérée (min > max sur un axe) ferait renvoyer une borne fixe par `Vector_BoundedToBox` (incertain : non
|
|||
|
|
lu dans le moteur ; relève de F1-F2).
|
|||
|
|
5. Valeurs sérialisées après `save_assets` (F7) : `499.Radius = 20`, `499.TraceChannel = TraceTypeQuery2`,
|
|||
|
|
`PO20.B = (20,20,20)`, par dump (`LPDumpFunction`).
|
|||
|
|
6. Compilation stricte jugée sur l'absence d'exception seulement ; recontrôle en F7 et par `CompileAllBlueprints`.
|
|||
|
|
7. V5 (`CAM-SPEC.md:382`) : `SphereTraceSingle` attendu 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, branche `ue5.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|SphereTraceByChannel` neuf : Radius `0.0`, TraceChannel `TraceTypeQuery1` par défaut ; les autres
|
|||
|
|
entrées par défaut sont celles de 459 (bIgnoreSelf `true`, DrawDebugType `None`).
|
|||
|
|
- `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éfaut `false`) ; out 0.
|
|||
|
|
- `Utilitaires|Opérateurs|Ajouter` relié en A à un vecteur devient `Math|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.
|