LifePlay-Revival/Docs/Migration/etat/CAM/CAM-B2b-IMPL-F5.md
edujiro5972 8084622450 LifePlay UE 5.8 : état de développement au 2026-10-19
Tickets : REP1-T4

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 22:57:42 +02:00

214 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Fiche CAM-B2b-F5 — 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-F5-IMPL : repli vers le haut (B2b-3) (2026-10-13)
Consignes : `CAM-B2b-FICHES.md` § « Rubriques communes » (l. 23-63) et § « F5 » (l. 115-125) ; SPEC `CAM-SPEC.md`
§ « CAM-B2b », ligne B2b-3 (l. 377). 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 à F4 en mémoire. Un seul
`call_tool` par message ; 54 appels MCP au total (15 `create_node`, 29 `connect_pins`, 6 `set_pin_value`,
3 `get_node_infos`, 1 `compile_blueprint`). Aucun `break_pins`, `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 après F5 = MD5 de l'instantané (§ 3).
- Graphe `/Game/BPs/Room.Room:EventGraph`, fin de `ComputeC2Target` (CE47), après `VariableSet_61` / `_62`
(x 36900) ; nœuds neufs en x 36700-40300, y 1500-2350.
### 1.1 Lecture avant écriture (`get_node_infos` groupé, 7 nœuds existants)
Conforme à la fiche : `VariableSet_61` (`|SetC2Target`, execute ← `IfThenElse_90`.0, C2Target ← `CallFunction_496`)
et `VariableSet_62` (`|SetC2Target`, execute ← `IfThenElse_90`.1, C2Target ← `CallFunction_495`) : `then` 0 **libre**
pour les deux ; `CallFunction_455` (`Transformation|GetSocketLocation`, self ← `VariableGet_264`, `head`) sortie 0 →
457, 459, 464, 473, 499 ; `CallFunction_497` (`Math|Vecteur|RotateVectorAroundAxis`, InVect ← PO17, AngleDeg ← 288,
Axis `0.0,0.0,1.0`) sortie 0 → PO3.A ; `MakeArray_5` ([0] ← 261, [1] ← 268) → 459.6, 499.6 ; `VariableGet_286`
(`|GetC2BoxMin`) → 495, 496, 502 ; `VariableGet_287` (`|GetC2BoxMax`) → 495, 496, 502.
### 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 |
|---|---|---|---|---|
| **Branche** du repli | `K2Node_IfThenElse_95` | `Utilitaires\|ContrôleDeFlux\|Branche` → idem | execute 0, Condition 1 ; then 0, else 1 | 37400, 1550 |
| Obtenir C2Target | `K2Node_VariableGet_291` | `Variables\|Pardéfaut\|ObtenirC2Target` → `\|GetC2Target` | C2Target out 0 (Vector) | 36700, 1900 |
| Distance(C2Target, tête) | `K2Node_CallFunction_503` | `Math\|Vecteur\|Distance(Vector)` → idem | V1 0, V2 1 ; out 0 (`Float (double-précision)`) | 36950, 1900 |
| Distance < 80 | `K2Node_PromotableOperator_22` | `Utilitaires\|Opérateurs\|Inférieurà(<)` → `Math\|Flottant\|float<float` (après liaison A) | A 0, B 1 (double) ; out 0 (Booléen) | 37150, 1900 |
| Bdir × 60 | `K2Node_PromotableOperator_23` | `Utilitaires\|Opérateurs\|Multiplier` → `Math\|Vecteur\|vector*vector` | A 0, B 1 ; out 0 | 37650, 2350 |
| tête + (0,0,100) | `K2Node_PromotableOperator_24` | `Utilitaires\|Opérateurs\|Ajouter` → `Math\|Vecteur\|vector+vector` | A 0, B 1 ; out 0 | 37650, 2150 |
| (tête + 100 Z) + Bdir × 60 | `K2Node_PromotableOperator_25` | `Utilitaires\|Opérateurs\|Ajouter` → `Math\|Vecteur\|vector+vector` | A 0, B 1 ; out 0 | 37900, 2250 |
| **`Desired2`** = borne | `K2Node_CallFunction_504` | `Math\|Vecteur\|VectorBoundedtoBox` → `Math\|Vecteur\|Vector_BoundedToBox` | InVect 0, InBoxMin 1, InBoxMax 2 ; out 0 | 38150, 2250 |
| **Trace** du repli | `K2Node_CallFunction_505` | `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 | 38450, 1500 |
| `BreakHitResult` | `K2Node_CallFunction_506` | `Collision\|BreakHitResult` → idem | Hit 0 ; Location out 4, Normal out 6 (18 sorties) | 38900, 2000 |
| Normal × 20 | `K2Node_PromotableOperator_26` | `Utilitaires\|Opérateurs\|Multiplier` → `Math\|Vecteur\|vector*vector` | A 0, B 1 ; out 0 | 39250, 2250 |
| Location + (Normal × 20) | `K2Node_PromotableOperator_27` | `Utilitaires\|Opérateurs\|Ajouter` → `Math\|Vecteur\|vector+vector` | A 0, B 1 ; out 0 | 39500, 2050 |
| `SelectVector` | `K2Node_CallFunction_507` | `Math\|Vecteur\|SelectVector` → idem | A 0, B 1, bPickA 2 ; out 0 | 39750, 1950 |
| Borne finale | `K2Node_CallFunction_508` | `Math\|Vecteur\|VectorBoundedtoBox` → `Math\|Vecteur\|Vector_BoundedToBox` | InVect 0, InBoxMin 1, InBoxMax 2 ; out 0 | 40000, 1950 |
| **Définir C2Target** (repli) | `K2Node_VariableSet_66` | `Variables\|Pardéfaut\|DéfinirC2Target` → `\|SetC2Target` | execute 0, C2Target 1 ; then 0, Output_Get 1 | 40300, 1500 |
À la création, les opérateurs portent le `type_id` trompeur déjà vu en F3 et F4 (`…|Seconds*FrameRate`,
`…|FrameNumber+Int`, et pour le comparateur `Math|Durée|Timespan<Timespan`), avec des broches `Caractère de
remplacement`. À la relecture finale, ils sont typés `Vector`, ou `Float (double-précision)` pour PO22.
Réutilisés sans copie (nœuds purs) : 455 (tête), 497 (`Bdir`), `MakeArray_5`, `VariableGet_286`, `VariableGet_287`.
### 1.3 Liens coupés
sans objet : la fiche F5 n'en prescrit aucun (61.then et 62.then étaient libres, relu au § 1.1) ; aucun `break_pins`.
### 1.4 Liens faits (`connect_pins`, 29, tous `{"returnValue":null}`)
| # | Sortie | Entrée | Point de la fiche |
|---|---|---|---|
| L1 | VariableSet_61.then 0 | IfThenElse_95.execute 0 | 1 |
| L2 | VariableSet_62.then 0 | IfThenElse_95.execute 0 | 1 |
| L3 | VariableGet_291.0 (`C2Target`) | CallFunction_503.V1 0 | 2 |
| L4 | CallFunction_455.0 (tête) | CallFunction_503.V2 1 | 2 |
| L5 | CallFunction_503.0 (distance) | PromotableOperator_22.A 0 | 2 |
| L6 | PromotableOperator_22.0 | IfThenElse_95.Condition 1 | 2 |
| L7 | CallFunction_497.0 (`Bdir`) | PromotableOperator_23.A 0 | 3 |
| L8 | CallFunction_455.0 (tête) | PromotableOperator_24.A 0 | 3 |
| L9 | PromotableOperator_24.0 | PromotableOperator_25.A 0 | 3 |
| L10 | PromotableOperator_23.0 | PromotableOperator_25.B 1 | 3 |
| L11 | PromotableOperator_25.0 | CallFunction_504.InVect 0 | 3 |
| L12 | VariableGet_286.0 (`C2BoxMin`) | CallFunction_504.InBoxMin 1 | 3 |
| L13 | VariableGet_287.0 (`C2BoxMax`) | CallFunction_504.InBoxMax 2 | 3 |
| L14 | IfThenElse_95.then 0 | CallFunction_505.execute 0 | 3 |
| L15 | CallFunction_455.0 (tête) | CallFunction_505.Start 1 | 3 |
| L16 | CallFunction_504.0 (`Desired2`) | CallFunction_505.End 2 | 3 |
| L17 | MakeArray_5.0 ([MC, CamRoom]) | CallFunction_505.ActorsToIgnore 6 | 3 |
| L18 | CallFunction_505.OutHit 1 | CallFunction_506.Hit 0 | 3 |
| L19 | CallFunction_506.Normal 6 | PromotableOperator_26.A 0 | 3 |
| L20 | CallFunction_506.Location 4 | PromotableOperator_27.A 0 | 3 |
| L21 | PromotableOperator_26.0 | PromotableOperator_27.B 1 | 3 |
| L22 | PromotableOperator_27.0 | CallFunction_507.A 0 | 3 |
| L23 | CallFunction_504.0 (`Desired2`) | CallFunction_507.B 1 | 3 |
| L24 | CallFunction_505.ReturnValue 2 | CallFunction_507.bPickA 2 | 3 |
| L25 | CallFunction_507.0 | CallFunction_508.InVect 0 | 3 |
| L26 | VariableGet_286.0 (`C2BoxMin`) | CallFunction_508.InBoxMin 1 | 3 |
| L27 | VariableGet_287.0 (`C2BoxMax`) | CallFunction_508.InBoxMax 2 | 3 |
| L28 | CallFunction_508.0 | VariableSet_66.C2Target 1 | 3 |
| L29 | CallFunction_505.then 0 | VariableSet_66.execute 0 | 3 |
`IfThenElse_95.else` 1 : laissé libre (fiche : « Faux → rien (fin) »).
### 1.5 Valeurs (`set_pin_value`, 6, toutes `{"returnValue":null}`, relues)
| Broche | Avant (relu à la création) | Après (relu) |
|---|---|---|
| PromotableOperator_22.B 1 | (neuf, `""`, joker) | `80.0` (`Float (double-précision)`) |
| PromotableOperator_23.B 1 | (neuf, `""`) | `60.0,60.0,60.0` |
| PromotableOperator_24.B 1 | (neuf, `""`) | `0.0,0.0,100.0` |
| CallFunction_505.Radius 3 | `0.0` | `20.0` |
| CallFunction_505.TraceChannel 4 | `TraceTypeQuery1` | `TraceTypeQuery2` |
| PromotableOperator_26.B 1 | (neuf, `""`) | `20.0,20.0,20.0` |
Valeurs non prescrites de 505, laissées par défaut et relues **identiques à 459 et 499** (F4 § 1.5) : 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`. `IfThenElse_95.Condition` garde la valeur par défaut `true`, sans effet puisque la broche est liée (L6).
### 1.6 Relecture et chaîne obtenue
`get_node_infos` final groupé sur les 21 nœuds touchés ou réutilisés : les 15 créés, plus 61, 62, 455, 497, `MakeArray_5`,
286 et 287. Les 29 liens apparaissent des deux côtés et les 6 valeurs sont relues. Types : vecteurs `Vector`, `bPickA`
et Condition `Booléen`, distance et PO22 `Float (double-précision)`, `Radius` `Float (simple précision)`. Liens non
touchés relus intacts : 61.execute ← `IfThenElse_90`.0, 61.C2Target ← 496 ; 62.execute ← `IfThenElse_90`.1,
62.C2Target ← 495 ; 455.self ← 264, `head` ; 455 → 457, 459, 464, 473, 499 (plus 503, PO24, 505) ; 497 ← PO17, 288,
Axis (0,0,1), 497 → PO3.A (plus PO23) ; `MakeArray_5` → 459.6, 499.6 (plus 505.6), [0] ← 261, [1] ← 268 ; 286 / 287 →
495, 496, 502 (plus 504, 508). Aucune divergence.
Chaîne obtenue en fin de `ComputeC2Target` : `IfThenElse_90` (impact / sans impact) → `Définir C2Target` (61 ou 62)
→ Branche 95 (`Distance(C2Target, tête) < 80`). Si vrai : `SphereTraceByChannel(tête → Desired2, r 20,
TraceTypeQuery2, ignorer [MC, CamRoom] + self)` (505), puis `Définir C2Target` (66) := `Bound(touché ? Location +
Normal × 20 : Desired2, C2BoxMin, C2BoxMax)`, avec `Desired2 = Bound(tête + (0,0,100) + Bdir × 60, C2BoxMin, C2BoxMax)`
(504). Si faux : fin, et `C2Target` garde la valeur de 61 ou 62, comme après F4.
### 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 : le chemin
`-abslog` n'a pas été fourni. Pas de `save_assets` (réservé à F7).
## 2. Écarts à la SPEC
- Aucun écart de câblage : la ligne B2b-3 (`CAM-SPEC.md:377`) et la fiche F5 (`CAM-B2b-FICHES.md:115-125`) sont
réalisées telles quelles (points 1 à 3) ; aucun nœud hors fiche touché ; aucun lien existant coupé.
- `Bdir × 60` et `Hit.Normal × 20` (SPEC, scalaires) sont réalisés par `vector*vector` avec B = (60,60,60) et
(20,20,20), comme le prescrit la fiche : c'est équivalent composante par composante.
- « Location » est la sortie `Location` (4) de `BreakHitResult`, centre de la sphère au contact, et non `ImpactPoint`
(5) : même choix que 460 → PO7 (ComputeC2Target) et 500 → PO21 (F4).
- Seuil 80 : `float<float` en double précision (la sortie de `Distance(Vector)` est en double), B = `80.0`.
- Garde `Accessed None` : aucune `IsValid` ajoutée, car la fiche n'en demande pas. Les nœuds neufs ne lisent aucune
référence d'objet : vecteurs, structure de touche, booléen. `MakeArray_5` est réutilisé tel quel, comme en 459 et 499.
`SelectVector` est pur et évalue A et B, mais aucun des deux ne déréférence d'objet : aucune cascade de branches n'est
requise. En revanche, 455 (`GetSocketLocation`, self ← `VariableGet_264`) est désormais lu en plus par 503 (condition)
et par 505 (Start, puis End via PO24). Si sa cible est nulle, un `Accessed None` déjà présent serait compté plus
souvent (point 4 du § 5).
- Ordre des écritures : chaque `set_pin_value` d'un opérateur a été posé juste après la liaison de son A, qui le type
(comme en F3 et F4). Typage et valeurs sont confirmés à la relecture finale (§ 1.6).
- Positions des nœuds : choisies hors des nœuds existants (cosmétique, non prescrit).
## 3. Instantané
Fait par l'orchestrateur avant F1 (non refait, consigne). Manifeste relu et disque mesuré après F5 :
```
date -Iseconds; md5sum "/d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset"; grep -i "Room.uasset" "/d/Game/LifePlay_Backup_5.5/CAM-B2b/manifest.csv"
2026-10-13T15:56:18+02:00
a5fa970e821dc2d0d9bf220fd43b9de6 */d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset
"Content\BPs\Room.uasset","True","6060745","A5FA970E821DC2D0D9BF220FD43B9DE6","2026-10-13T15:25:45"
```
Le MD5 du disque est celui de l'instantané : rien n'a été enregistré. Retour arrière avant F7 : fermer l'éditeur sans
enregistrer, ce qui perd F1 à F5. 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
- F6 et F7 (pilotage, compilation finale, enregistrement) : hors périmètre.
- `hyper_blueprint_debug_inspect`, journal de l'éditeur : non consultés (§ 1.7).
- `save_assets` : interdit avant F7 ; F1 à F5 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 « distance ≥ 80 » : 95 sort par `else` (libre), donc `C2Target` = valeur de 61 ou 62, comme après F4 ; comportement
inchangé hors repli (établi par le câblage ; à confirmer en jeu).
2. Changement voulu (distance < 80) : la cible passe à `Bound(tête + (0,0,100) + Bdir × 60)`, ou au point de contact
reculé de 20 le long de la normale, toujours borné par `C2BoxMin` / `C2BoxMax`. À confirmer en jeu : près d'un mur,
C2 se replie vers le haut et vers l'intérieur, sans sortir de la pièce.
3. `Bdir` unitaire et horizontal (estimé) : 497 = `RotateVectorAroundAxis(Normalize2D(Fwd) × −1, C2Yaw, (0,0,1))`
(F3) ; `Normalize2D` rend Z = 0 et une rotation autour de Z garde la norme. `Desired2` serait donc à 60 cm en
arrière (horizontal) et à 100 cm au-dessus de la tête, soit environ 117 cm, avant la borne (non lu dans le moteur).
4. `LogStats` : aucun `Accessed None` nouveau, en particulier sur `VariableGet_264` (cible de 455), désormais lu aussi
par 503 et 505.
5. Un seul passage : si la borne ou la touche ramènent la cible à moins de 80 cm, rien ne relance le repli (pas de
boucle, voulu par la SPEC). À observer en jeu dans un coin bas de plafond.
6. Ordre d'exécution : `ComputeC2Target` (CE47) est appelé par 467 (poursuite) avant la trace 499 (F4) et par
`PlaceC2`. Le repli s'exécute donc dans le même appel, avant que 499 et 474 lisent `C2Target` (estimé : un événement
appelé s'exécute de façon synchrone).
7. Valeurs sérialisées après `save_assets` (F7), par dump (`LPDumpFunction`) : `505.Radius = 20`,
`505.TraceChannel = TraceTypeQuery2`, `PO22.B = 80`, `PO23.B = (60,60,60)`, `PO24.B = (0,0,100)`,
`PO26.B = (20,20,20)`.
8. V5 (`CAM-SPEC.md:382`) : `SphereTraceSingle` 3 (459, 499, 505) ; `Vector_BoundedToBox` 5 (495, 496, 502, 504,
508 ; attendu ≥ 4) ; `Vector_Distance` 1 (503) ; `RotateAngleAxis` 1 (497).
9. Compilation stricte jugée sur l'absence d'exception seulement ; recontrôle en F7 et par `CompileAllBlueprints`.
## 6. Fichiers à commiter
- `A Docs/Migration/etat/CAM/CAM-B2b-IMPL-F5.md` (dépôt du jeu, branche `ue5.8`).
- `Content/BPs/Room.uasset` : rien à commiter pour F5 (non enregistré) ; il le sera après F7 et la VAL.
Tours : 62 / 60 (ce Write et la remise du compte rendu compris ; dépassement de 2 dans la marge `maxTurns`, sans
étape ouverte après le budget : la compilation a eu lieu au tour 59)
## Constats
- `Utilitaires|Opérateurs|Inférieurà(<)` se crée directement par `create_node` (pas besoin de `find_node_types`) ; à
la création, il est relu `Math|Durée|Timespan<Timespan`, broches joker. Relié en A à un double, il devient
`Math|Flottant|float<float` et accepte aussitôt `set_pin_value` B = "80.0".
- `Math|Vecteur|Distance(Vector)` : V1 0, V2 1 ; sortie 0 en `Float (double-précision)`.
- `Variables|Pardéfaut|ObtenirC2Target` → `|GetC2Target` (sortie 0) ; `DéfinirC2Target` → `|SetC2Target` (execute 0,
C2Target 1 ; then 0, Output_Get 1).
- Une Branche neuve a Condition = `true` par défaut.
- Économie : 1 lecture des existants, création de tous les nœuds, 1 lecture groupée, câblage et valeurs, 1 relecture
finale (21 nœuds), compilation. Au total, 54 appels pour 15 nœuds, 29 liens et 6 valeurs. Avec 5 tours de lecture
des consignes, le budget de 60 est juste : une fiche de cette taille devrait compter environ 65 tours.