LifePlay-Revival/Docs/Migration/etat/CAM/CAM-B2b-IMPL-F3.md

195 lines
14 KiB
Markdown
Raw Normal View History

Fiche CAM-B2b-F3 — 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-F3-IMPL : appel de la boîte, borne de `Desired`, rayon 20 (B2b-2) ; lacet, distance, hauteur (B2b-5) (2026-10-13)
Consignes : `CAM-B2b-FICHES.md` § « Rubriques communes » (l. 23-63) et § « F3 » (l. 88-104) ; SPEC `CAM-SPEC.md`
§ « CAM-B2b », lignes B2b-2 (l. 376) et B2b-5 (l. 379). 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 + F2 en mémoire. Un seul `call_tool` par message ; 51 appels MCP au total (13 `create_node`, 6 `break_pins`,
23 `connect_pins`, 5 `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 F3 = MD5 de l'instantané (§ 3).
- Graphe `/Game/BPs/Room.Room:EventGraph`, zone de `ComputeC2Target` (CE47 en 34000, 1500) ; nœuds neufs en
x 34100-36650, y 1300-2750.
### 1.1 Lecture avant écriture (`get_node_infos` groupé, 10 nœuds existants)
Conforme à la fiche : `CustomEvent_47.then` (out 1) → `CallFunction_459.execute` (in 0) ; `CallFunction_458.0` →
`459.End` (in 2) et → `VariableSet_62.C2Target` (in 1) ; `459.Radius` (in 3) = `12.0` (`Float (simple précision)`) ;
`CallFunction_454.0` → `PromotableOperator_3.A` (in 0) ; `PO3.B` (in 1) = `-175.0,-175.0,-175.0`, **sans lien**
(constante) ; `PO5.0` → `458.Z` (in 2), `PO5.B` = `60.0` ; `PO6.B` (in 1) = `12.0,12.0,12.0` ; `PO7.0` →
`VariableSet_61.C2Target` (in 1).
### 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 |
|---|---|---|---|---|
| Appel `ComputeRoomBox` | `K2Node_CallFunction_494` | `Appelerunefonction\|ComputeRoomBox` → `\|ComputeRoomBox` | execute 0, self 1 (vide = Room) ; then 0 | 34350, 1300 |
| Obtenir `C2BoxMin` | `K2Node_VariableGet_286` | `Variables\|Pardéfaut\|ObtenirC2BoxMin` → `\|GetC2BoxMin` | out 0 `Vector` | 35100, 2400 |
| Obtenir `C2BoxMax` | `K2Node_VariableGet_287` | `Variables\|Pardéfaut\|ObtenirC2BoxMax` → `\|GetC2BoxMax` | out 0 `Vector` | 35100, 2500 |
| **`DesiredB`** = borne de `Desired` | `K2Node_CallFunction_495` | `Math\|Vecteur\|VectorBoundedtoBox` → `Math\|Vecteur\|Vector_BoundedToBox` | InVect 0, InBoxMin 1, InBoxMax 2 ; out 0 | 35550, 2300 |
| Borne de PO7 (→ 61) | `K2Node_CallFunction_496` | idem → `Math\|Vecteur\|Vector_BoundedToBox` | idem | 36650, 2300 |
| `Normalize2D × (−1)` | `K2Node_PromotableOperator_17` | `Utilitaires\|Opérateurs\|Multiplier` → `Math\|Vecteur\|vector*vector` (après liaison A) | A 0, B 1 ; out 0 | 34450, 2300 |
| **`Bdir`** = rotation de lacet | `K2Node_CallFunction_497` | `Math\|Vecteur\|RotateVectorAroundAxis` → idem | InVect 0, AngleDeg 1 (`Float (simple précision)`), Axis 2 ; out 0 | 34700, 2450 |
| Obtenir `C2Yaw` | `K2Node_VariableGet_288` | `Variables\|Pardéfaut\|ObtenirC2Yaw` → `\|GetC2Yaw` | out 0 `Float (double-précision)` | 34400, 2550 |
| Obtenir `C2Dist` | `K2Node_VariableGet_289` | `Variables\|Pardéfaut\|ObtenirC2Dist` → `\|GetC2Dist` | out 0 `Float (double-précision)` | 34100, 2750 |
| **`d`** = `C2Dist + 175` | `K2Node_PromotableOperator_18` | `Utilitaires\|Opérateurs\|Ajouter` → `Math\|Flottant\|float+float` (après liaison A) | A 0, B 1 ; out 0 | 34300, 2750 |
| **`MakeVector(d, d, d)`** | `K2Node_CallFunction_498` | `Math\|Vecteur\|MakeVector` → idem | X 0, Y 1, Z 2 ; out 0 | 34500, 2750 |
| **Hauteur** = `PO5 + C2Height` | `K2Node_PromotableOperator_19` | `Utilitaires\|Opérateurs\|Ajouter` → `Math\|Flottant\|float+float` (après liaison A) | A 0, B 1 ; out 0 | 35200, 2150 |
| Obtenir `C2Height` | `K2Node_VariableGet_290` | `Variables\|Pardéfaut\|ObtenirC2Height` → `\|GetC2Height` | out 0 `Float (double-précision)` | 34950, 2250 |
Les trois opérateurs avaient à la création un `type_id` trompeur (`Utilitaires|Gestiondutemps|Seconds*FrameRate`,
`…|FrameNumber+Int`) et des broches `Caractère de remplacement` ; relus typés à la relecture finale.
### 1.3 Liens coupés (`break_pins`, 6, tous `{"returnValue":null}`)
| # | Sortie | Entrée | Point de la fiche |
|---|---|---|---|
| C1 | CustomEvent_47.then 1 | CallFunction_459.execute 0 | 1 |
| C2 | CallFunction_458.0 (`Desired`) | CallFunction_459.End 2 | 2 |
| C3 | CallFunction_458.0 | VariableSet_62.C2Target 1 | 2 |
| C4 | PromotableOperator_7.0 | VariableSet_61.C2Target 1 | 4 |
| C5 | CallFunction_454.0 (`Normalize2D`) | PromotableOperator_3.A 0 | 5 |
| C6 | PromotableOperator_5.0 | CallFunction_458.Z 2 | 5 (hauteur) |
### 1.4 Liens faits (`connect_pins`, 23, tous `{"returnValue":null}`)
| # | Sortie | Entrée |
|---|---|---|
| L1 | CustomEvent_47.then 1 | CallFunction_494.execute 0 |
| L2 | CallFunction_494.then 0 | CallFunction_459.execute 0 |
| L3 | CallFunction_458.0 | CallFunction_495.InVect 0 |
| L4 | VariableGet_286.0 | CallFunction_495.InBoxMin 1 |
| L5 | VariableGet_287.0 | CallFunction_495.InBoxMax 2 |
| L6 | CallFunction_495.0 | CallFunction_459.End 2 |
| L7 | CallFunction_495.0 | VariableSet_62.C2Target 1 |
| L8 | PromotableOperator_7.0 | CallFunction_496.InVect 0 |
| L9 | VariableGet_286.0 | CallFunction_496.InBoxMin 1 |
| L10 | VariableGet_287.0 | CallFunction_496.InBoxMax 2 |
| L11 | CallFunction_496.0 | VariableSet_61.C2Target 1 |
| L12 | CallFunction_454.0 | PromotableOperator_17.A 0 |
| L13 | PromotableOperator_17.0 | CallFunction_497.InVect 0 |
| L14 | VariableGet_288.0 (`C2Yaw`) | CallFunction_497.AngleDeg 1 |
| L15 | CallFunction_497.0 (`Bdir`) | PromotableOperator_3.A 0 |
| L16 | VariableGet_289.0 (`C2Dist`) | PromotableOperator_18.A 0 |
| L17 | PromotableOperator_18.0 | CallFunction_498.X 0 |
| L18 | PromotableOperator_18.0 | CallFunction_498.Y 1 |
| L19 | PromotableOperator_18.0 | CallFunction_498.Z 2 |
| L20 | CallFunction_498.0 | PromotableOperator_3.B 1 (constante −175 remplacée ; relue `""` après liaison) |
| L21 | PromotableOperator_5.0 | PromotableOperator_19.A 0 |
| L22 | VariableGet_290.0 (`C2Height`) | PromotableOperator_19.B 1 |
| L23 | PromotableOperator_19.0 | CallFunction_458.Z 2 |
### 1.5 Valeurs (`set_pin_value`, 5, toutes `{"returnValue":null}`, relues)
| Broche | Avant | Après (relu) |
|---|---|---|
| CallFunction_459.Radius 3 | `12.0` | `20.0` |
| PromotableOperator_6.B 1 | `12.0,12.0,12.0` | `20.0,20.0,20.0` |
| PromotableOperator_17.B 1 | (neuf) | `-1.0,-1.0,-1.0` |
| CallFunction_497.Axis 2 | (neuf, `0, 0, 0`) | `0.0,0.0,1.0` |
| PromotableOperator_18.B 1 | (neuf) | `175.0` |
### 1.6 Relecture et chaîne obtenue
`get_node_infos` final groupé sur les 23 nœuds touchés (13 créés + CE47, 454, 458, 459, PO3, PO5, PO6, PO7, 61, 62) :
les 6 coupures sont absentes des deux côtés (454.0 ne sort plus que vers PO17 ; 458.0 ne sort plus que vers 495 ;
PO7.0 ne sort plus que vers 496 ; PO5.0 ne sort plus que vers PO19 ; CE47.then ne sort plus que vers 494) ; les
23 liens apparaissent des deux côtés ; les 5 valeurs relues ; types : vecteurs `Vector`, `d`, hauteur et composantes
`Float (double-précision)`, `AngleDeg` et `Radius` `Float (simple précision)`. Liens non touchés relus intacts :
459.Start ← 455, 459.ActorsToIgnore ← MakeArray_5, 459.then / ReturnValue → IfThenElse_90, 459.OutHit → 460,
458.X / Y ← 456, PO5.A ← 457.Z, PO3.0 → PO4.B, PO6.A ← 460.Normal, PO7.A ← 460.Location, 61 / 62.execute ← IfThenElse_90.
Aucune divergence.
Chaîne : `ComputeC2Target` → `ComputeRoomBox` (C2BoxMin, C2BoxMax) → `SphereTraceByChannel(tête → Bound(Desired),
r 20)` ; `Desired = MakeVector(456.X, 456.Y, tête.Z + 60 + C2Height)`, avec en amont
`PO3 = RotateVectorAroundAxis(Normalize2D(Fwd) × −1, C2Yaw, (0,0,1)) × (C2Dist + 175)` ; touché →
`C2Target := Bound(Location + Normal × 20)` ; libre → `C2Target := Bound(Desired)`.
### 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
- **E3 (SPEC incohérente, fiche suivie)** : la colonne « valeurs » de B2b-5 (`CAM-SPEC.md:379`) dit « à C2Yaw = 0,
C2Height = 0, **C2Dist = 175** : identique à B2 », alors que B2b-0 (`CAM-SPEC.md:374`) fixe `C2Dist` = 0 (décalage,
distance = 175 + `C2Dist`) et que la fiche F3 (`CAM-B2b-FICHES.md:100-104`) prescrit `d = C2Dist + 175` et le
contrôle à `C2Dist = 0`. Appliqué : `d = C2Dist + 175` (PO18). À `C2Dist = 175`, la distance serait 350. Le texte de
la colonne B2b-5 est à corriger par l'orchestrateur (point 7).
- `Bdir × (175 + C2Dist)` (SPEC, scalaire) est réalisé par `vector*vector` avec `MakeVector(d, d, d)` (fiche) :
équivalent composante par composante.
- `AngleDeg` (simple précision) est alimenté par `C2Yaw` (double précision) : conversion implicite du moteur, la
compilation stricte l'accepte.
- Garde `Accessed None` : aucune `IsValid` ajoutée (aucune demandée). Les nœuds neufs ne lisent aucune référence
d'objet (vecteurs, flottants, appel d'événement sur `self`). En revanche, `ComputeRoomBox` (F1-F2 : lectures de
`StaticMeshComponent`, `Wall2`, `Wall4`, `WallT`) s'exécute désormais à chaque `ComputeC2Target` (point 3).
- Lecture intermédiaire des opérateurs après typage non faite (économie de tours) : `set_pin_value` posé juste après
la liaison A, typage et valeurs confirmés à la relecture finale (§ 1.6).
- Positions des nœuds : choisies hors des nœuds existants (cosmétique, non prescrites).
- Aucun autre écart : points 1 à 5 de la fiche faits dans l'ordre, aucun nœud hors fiche touché.
## 3. Instantané
Fait par l'orchestrateur avant F1 (non refait, consigne) : `D:\Game\LifePlay_Backup_5.5\CAM-B2b\manifest.csv`,
Room `A5FA970E…` (ligne citée par `CAM-B2b-IMPL-F2.md` § 3, non relue ici). 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:41:43+02:00, avant F3)
a5fa970e821dc2d0d9bf220fd43b9de6 */d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset (2026-10-13T15:45:08+02:00, après F3)
```
= instantané : rien d'enregistré. Retour arrière avant F7 : fermer l'éditeur sans enregistrer (perd F1 à F3) ; 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
- F4 et suivantes (poursuite protégée, repli, pilotage) : hors périmètre. `Bdir` = `K2Node_CallFunction_497` pour F5.
- `hyper_blueprint_debug_inspect`, journal de l'éditeur : non consultés (§ 1.7).
- `save_assets` : interdit avant F7 ; F1 à F3 vivent en mémoire de l'éditeur PID 10708 (une fermeture ou un plantage
avant F7 les perd ; l'instantané reste intact).
- Contrôle du point 6 de la fiche (`Desired` = valeur de B2 aux trois variables nulles) : non mesuré à l'exécution,
seulement déduit du câblage (point 1).
- Preuve en jeu (build empaqueté + `LogStats`) : hors rôle.
## 5. Points à confirmer en VAL
1. Point 6 de la fiche, estimé par le câblage : à `C2Yaw = 0`, `RotateVectorAroundAxis` rend son entrée, donc
`PO3 = −Normalize2D × (175,175,175) = Normalize2D × (−175,−175,−175)` (= B2) ; à `C2Height = 0`, `458.Z = PO5`
(= B2) ; `458.X / Y` inchangés (← 456). À mesurer (dump ou trace d'exécution).
2. Changement voulu : `Desired` borné par la boîte avant la trace (459.End) et avant `C2Target` (62) ; le cas touché
(61) borné aussi. À confirmer en jeu : C2 jamais hors de la pièce.
3. `ComputeRoomBox` appelé à chaque `ComputeC2Target` (fréquence d'appel de CE47 non relue ici) : aucun
`Accessed None` sur `StaticMeshComponent`, `Wall2`, `Wall4`, `WallT` dans `LogStats`.
4. Conversion double → simple de `C2Yaw` vers `AngleDeg` : sans perte utile pour un angle en degrés ; à revoir si la
compilation de `CompileAllBlueprints` (éditeur fermé) l'avertit.
5. Valeurs sérialisées après `save_assets` (F7) : `459.Radius = 20`, `PO6.B = (20,20,20)`, `PO17.B = (−1,−1,−1)`,
`497.Axis = (0,0,1)`, `PO18.B = 175`, `PO3.B` lié (plus de constante −175), par dump (`LPDumpFunction`).
6. Compilation stricte jugée sur l'absence d'exception seulement ; recontrôle en F7 et par `CompileAllBlueprints`.
7. E3 : corriger la colonne B2b-5 de `CAM-SPEC.md:379` (« C2Dist = 175 » → « C2Dist = 0 ») ; les bornes de B2b-6
(`C2Dist ∈ [−75, 125]`, distance 100 à 300) sont cohérentes avec `d = C2Dist + 175`.
## 6. Fichiers à commiter
- `A Docs/Migration/etat/CAM/CAM-B2b-IMPL-F3.md` (dépôt du jeu, branche `ue5.8`).
- `Content/BPs/Room.uasset` : rien à commiter pour F3 (non enregistré) ; il le sera après F7 et la VAL.
Tours : 57 / 60
## Constats
- `Appelerunefonction|ComputeRoomBox` crée `|ComputeRoomBox` : execute 0, self 1, then 0 (self vide = Room).
- `Math|Vecteur|VectorBoundedtoBox` se relit `Math|Vecteur|Vector_BoundedToBox` : InVect 0, InBoxMin 1, InBoxMax 2, out 0.
- `Math|Vecteur|RotateVectorAroundAxis` : InVect 0, AngleDeg 1 (simple précision, accepte un getter double), Axis 2.
- `Utilitaires|Opérateurs|Multiplier` apparaît `Utilitaires|Gestiondutemps|Seconds*FrameRate` à la création ; relié en A
à un vecteur, il devient `vector*vector` et accepte aussitôt `set_pin_value` B = "x,y,z".
- Lier une entrée constante (PO3.B) efface sa valeur (relue `""`) : vérifier l'absence de lien avant, comme demandé.
- Économie : créer tous les nœuds, une lecture groupée (13 nœuds), câbler et poser les valeurs, une relecture finale
(23 nœuds) : 51 appels pour 13 nœuds, 6 coupures, 23 liens, 5 valeurs.