LifePlay-Revival/Docs/Migration/etat/CAM/CAM-B2b-IMPL-F7.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

272 lines
17 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-F7 — 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-F7-IMPL : pilotage de C2 par `DownUp` (B2b-6, fin), relecture globale, compilation stricte, enregistrement de Room (2026-10-13)
Consignes : `CAM-B2b-FICHES.md` § « Rubriques communes » (l. 23-63) et § « F7 » (l. 134-142). Seul `DownUp` restait à
faire : `RotateCamera` a été traité en F6b. SPEC : `CAM-SPEC.md` § « CAM-B2b », ligne B2b-6 (l. 380). Modèle suivi :
`CAM-B2b-IMPL-F6b.md`, partie `RotateCamera` (même schéma).
Contexte : UE-GO de Big Boss B2b du 2026-10-13, cité par l'orchestrateur. Éditeur headless PID 10708, port 8000,
connexion `unreal-mcp` partagée (MCPA-T1). Room chargé, F1 à F6b en mémoire. Un seul `call_tool` par message.
**24 appels MCP** :
- 3 `get_node_infos`, 6 `create_node`, 1 `break_pins`, 9 `connect_pins` et 3 `set_pin_value` ;
- 1 `compile_blueprint` et 1 `save_assets`.
Aucun `delete_node`, `write_graph_dsl` ni `ProgrammaticToolset`. Aucune écriture par HyperAIStudio.
## 1. Fichiers modifiés
- `Content/BPs/Room.uasset` : **enregistré** par `save_assets` (§ 1.8). Il contient F1 à F7. MD5 avant
`a5fa970e…` (= instantané) ; après `e0517c63541f249bd9dbda5c39815ba5`. Taille passée de 6 060 745 à 6 318 319 octets.
- Graphe `/Game/BPs/Room.Room:EventGraph`, événement `DownUp` (CE8, x 5520, y 3952) : nœuds neufs en x 5700-6550,
y 4250-4550.
- Aucun autre asset n'a été ouvert en écriture ni enregistré (§ 3).
### 1.1 Lecture avant écriture (`get_node_infos` groupé, 3 nœuds existants)
La lecture est conforme aux faits de la fiche :
- `K2Node_CustomEvent_8` (`AddEvent|Custom|DownUp`) :
- `then` out 1 → `IfThenElse_8`.execute 0 ;
- `AxisValue` out 2 (`Float (double-précision)`) → `CommutativeAssociativeBinaryOperator_3`.0, `_5`.0 et `_8`.0.
- `K2Node_IfThenElse_8` : execute ← CE8.1 ; Condition ← `CommutativeAssociativeBinaryOperator_17`.0 ; then 0 →
`IfThenElse_17`.0 ; else 1 libre.
- `K2Node_PromotableOperator_8` (`Utilitaires|Equal(Object)`) : A ← `CallFunction_439`.0, B ← `VariableGet_268`.0 ; out 0
(`Booléen`) → `IfThenElse_91`.1, `_96`.1, `_97`.1, `_98`.1 et `_99`.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 |
|---|---|---|---|---|
| **Branche** C2 | `K2Node_IfThenElse_100` | `Utilitaires\|ContrôleDeFlux\|Branche` → idem | execute 0, Condition 1 ; then 0, else 1 | 5750, 4250 |
| Obtenir C2Height | `K2Node_VariableGet_296` | `Variables\|Pardéfaut\|ObtenirC2Height` → `\|GetC2Height` | C2Height out 0 (double) | 5700, 4450 |
| AxisValue × 3 | `K2Node_PromotableOperator_35` | `Utilitaires\|Opérateurs\|Multiplier` → `Math\|Flottant\|float*float` | A 0, B 1 ; out 0 (double) | 5900, 4550 |
| C2Height + produit | `K2Node_PromotableOperator_36` | `Utilitaires\|Opérateurs\|Ajouter` → `Math\|Flottant\|float+float` | A 0, B 1 ; out 0 (double) | 6100, 4450 |
| Clamp | `K2Node_CallFunction_511` | `Math\|Flottant\|Clamp(Float)` → idem | Value 0, Min 1, Max 2 ; ReturnValue out 0 (double) | 6300, 4500 |
| **Définir C2Height** | `K2Node_VariableSet_71` | `Variables\|Pardéfaut\|DéfinirC2Height` → `\|SetC2Height` | execute 0, C2Height 1 ; then 0, Output_Get 1 | 6550, 4400 |
Comme en F3 à F6b, les opérateurs naissent avec un `type_id` trompeur et des broches `Caractère de remplacement` :
- PO35 : `Utilitaires|Gestiondutemps|Seconds*FrameRate` ;
- PO36 : `…|FrameNumber+Int`.
À la relecture finale, ils sont typés `float*float` et `float+float`, en double précision. À la création, le Clamp avait
Min `0.0` et Max `1.0`. PO8 est réutilisé sans copie (nœud pur).
### 1.3 Lien coupé (`break_pins`, 1, `{"returnValue":null}`)
| # | Sortie | Entrée |
|---|---|---|
| C1 | CustomEvent_8.then 1 | IfThenElse_8.execute 0 |
Aucun autre lien n'a été coupé, et rien d'autre n'a été touché dans `DownUp`.
### 1.4 Liens faits (`connect_pins`, 9, tous `{"returnValue":null}`)
| # | Sortie | Entrée |
|---|---|---|
| L1 | CustomEvent_8.then 1 | IfThenElse_100.execute 0 |
| L2 | IfThenElse_100.else 1 | IfThenElse_8.execute 0 |
| L3 | PromotableOperator_8.0 | IfThenElse_100.Condition 1 |
| L4 | CustomEvent_8.AxisValue 2 | PromotableOperator_35.A 0 |
| L5 | VariableGet_296.0 (`C2Height`) | PromotableOperator_36.A 0 |
| L6 | PromotableOperator_35.0 | PromotableOperator_36.B 1 |
| L7 | PromotableOperator_36.0 | CallFunction_511.Value 0 |
| L8 | CallFunction_511.0 | VariableSet_71.C2Height 1 |
| L9 | IfThenElse_100.then 0 | VariableSet_71.execute 0 |
`VariableSet_71.then` reste libre : c'est la fin de l'événement côté C2, comme dans F6a et F6b.
### 1.5 Valeurs (`set_pin_value`, 3, tous `{"returnValue":null}`, relues)
| Broche | Avant (relu à la création) | Après (relu) |
|---|---|---|
| PromotableOperator_35.B 1 | (neuf, `""`, joker) | `3.0` (`Float (double-précision)`) |
| CallFunction_511.Min 1 | `0.0` | `-40.0` |
| CallFunction_511.Max 2 | `1.0` | `150.0` |
`PO35.B` a été posé après L4, qui type l'opérateur. La Condition de la Branche 100 garde sa valeur par défaut `true`, sans
effet puisque la broche est liée (L3).
### 1.6 Relecture globale (`get_node_infos` groupé, 23 nœuds)
Nœuds relus : les 6 nœuds créés, `IfThenElse_8`, PO8, CE1, CE4, CE8, CE19, CE55, `CallFunction_459`, `_467`, `_474`,
`_499`, `_505`, `VariableSet_61`, `_62`, `_66`, `CustomEvent_49` et `CallFunction_494`. Chaque lien a été comparé au
rapport de la fiche qui l'a posé :
**DownUp (F7)**
- Les 9 liens L1 à L9 apparaissent des deux côtés, et les 3 valeurs sont relues.
- `IfThenElse_8` : execute ← `IfThenElse_100`.1 ; Condition ← `CommutativeAssociativeBinaryOperator_17` ; then →
`IfThenElse_17` ; else libre.
- CE8.AxisValue → CABO_3.0, _5.0, _8.0, plus PO35.0.
**PO8** : sortie → `IfThenElse_91`, `_96`, `_97`, `_98`, `_99` et `_100` (6 branches).
**Événements de déplacement (F6a, F6b)**
- CE1 `CircleCamera` : then → `IfThenElse_96` ; DeltaSeconds → CABO_26.1, _16.1, _27.1, plus PO28.1 (F6a L1, L5).
- CE4 `LeftRight` : then → `IfThenElse_97` ; AxisValue → CABO_47.0, _13.0, _24.0, plus PO29.0 (F6a L8, L11).
- CE19 `RotateCamera` : then → `IfThenElse_99` ; DeltaSeconds → CABO_45.1, _12.1, _15.1, plus PO33.0 (F6b L10, L13).
- CE55 `ScrollDownUp` : then → `IfThenElse_98` ; Values → CABO_2.0, CF_26.2, CABO_20.0, _10.0, _22.0, plus PO31.0
(F6b L1, L4).
**`ComputeC2Target` et `ComputeRoomBox` (F2, F3, F5)**
- 494 `|ComputeRoomBox` : execute ← CE47.1 ; then → 459.0 (F3 L1, L2).
- 459 (trace de `Desired`) :
- execute ← 494, then → `IfThenElse_90`, ReturnValue → `IfThenElse_90`.1, OutHit → 460 ;
- Start ← 455, End ← 495 (F3 L6), ActorsToIgnore ← `MakeArray_5` ;
- Radius `20.0` (F3), TraceChannel `TraceTypeQuery2`.
- `VariableSet_61` : execute ← `IfThenElse_90`.0 ; C2Target ← 496 (F3 L11) ; then → `IfThenElse_95` (F5 L1).
- `VariableSet_62` : execute ← `IfThenElse_90`.1 ; C2Target ← 495 (F3 L7) ; then → `IfThenElse_95` (F5 L2).
- 505 (trace du repli) :
- execute ← `IfThenElse_95`.0, then → `VariableSet_66`, OutHit → 506, ReturnValue → 507.2 ;
- Start ← 455, End ← 504, ActorsToIgnore ← `MakeArray_5` ;
- Radius `20.0`, `TraceTypeQuery2` (F5 L14 à L18, L24, L29).
- `VariableSet_66` : execute ← 505 ; C2Target ← 508 (F5 L28) ; then libre.
- CE49 `ComputeRoomBox` : then → `VariableSet_64` (F2 L21).
**Poursuite (F4)**
- 467 `|ComputeC2Target` : execute ← `IfThenElse_93`.1 ; then → 499 (F4 L1).
- 499 (trace de la poursuite) :
- execute ← 467, then → 474, OutHit → 500, ReturnValue → 501.2 ;
- Start ← 455, End ← 468, ActorsToIgnore ← `MakeArray_5` ;
- Radius `20.0`, `TraceTypeQuery2` (F4 L1 à L6, L12).
- 474 : execute ← 499 (F4 L2) ; self ← `VariableGet_268` ; NewLocation ← 502 `Safe` (F4 L16) ; NewRotation ← 469 ; bSweep
`false`.
**Aucune divergence.** Chaîne obtenue pour `DownUp` : CE8 → Branche 100 (`GetViewTarget(PC) == CamRoom`).
- Vrai : `Définir C2Height` (71) := `Clamp(C2Height + AxisValue × 3, −40, 150)`, puis fin.
- Faux : `IfThenElse_8`, chaîne d'origine inchangée.
### 1.7 Compilation
`compile_blueprint {blueprint:{refPath:"/Game/BPs/Room.Room"}, warnings_as_errors:true}` a renvoyé
`{"returnValue":null}`, sans exception : c'est le critère de la fiche.
Deux contrôles n'ont pas été faits :
- `hyper_blueprint_debug_inspect`, absent du serveur le 2026-10-10 (mémoire `unreal-mcp-reconnect`, non revérifié) ;
- le journal de l'éditeur, faute du chemin `-abslog` : il n'est pas dans `Saved\Logs`, dont la fin de la liste ne montre
que `UnrealPak*.log`, `cef3.log` et `portage`.
### 1.8 Enregistrement
`editor_toolset.toolsets.asset.AssetTools` / `save_assets {"asset_paths":["/Game/BPs/Room"]}` a renvoyé
`{"returnValue":true}`. Il a été appelé une seule fois, pour Room seul, après la compilation stricte.
## 2. Écarts à la SPEC
- **Aucun écart de câblage.** La ligne B2b-6 (`CAM-SPEC.md:380`) et la fiche (`CAM-B2b-FICHES.md:137`) sont réalisées
telles quelles pour `DownUp`. Seul le lien CE8.then → `IfThenElse_8` a été coupé.
- **Formule** : `C2Height := Clamp(C2Height + AxisValue × 3, −40, 150)`. A de PO36 = C2Height, B = produit, relu.
- **Typage** : `AxisValue` est en double précision, comme `Clamp(Float)` : aucune conversion implicite.
- **Relecture** : la liste de la fiche (l. 139) a été élargie, à la demande de l'orchestrateur, à 499, 505,
`VariableSet_66`, CE49 et 494, plus `IfThenElse_8` et PO8.
- **Garde `Accessed None`** : aucune `IsValid` ajoutée, car ni la fiche ni la SPEC n'en demandent, et les nœuds neufs ne
lisent que des flottants. PO8 (→ 439 `GetViewTarget`, self ← `VariableGet_262` ; → `VariableGet_268` `CamRoom`) est
désormais évalué à chaque appel de `DownUp`. Même réserve qu'en F6a et F6b. PO8 alimente maintenant 6 branches.
- **Comportement** : quand C2 n'est pas la vue, il est identique à l'ancien (`else` → `IfThenElse_8`). Quand C2 est la
vue, la chaîne d'origine **n'est plus exécutée** : c'est le changement voulu par la SPEC.
- **Positions** : choisies près de CE8, sans prescription (cosmétique). Elles chevauchent visuellement les nœuds
`CircleCamera` de F6a (x 5650-6050, y 4250-4450), sans effet sur le graphe.
## 3. Instantané
L'orchestrateur l'a fait avant F1 (`D:\Game\LifePlay_Backup_5.5\CAM-B2b\`) ; il n'a pas été refait, selon la consigne.
Mesures avant et après `save_assets` :
```
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"; git -C "D:\Game\LifePlay-master 5.8" status --short -- Content Source Config
2026-10-13T16:10:25+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"
M Content/BPs/Person.uasset
M Content/BPs/Room.uasset
M Source/LifePlay/LPDebugSubsystem.cpp
M Source/LifePlay/LPDebugSubsystem.h
```
(save_assets → true)
```
date -Iseconds; md5sum "/d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset"; stat -c '%s %y' "/d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset"; git -C "D:\Game\LifePlay-master 5.8" status --short -- Content Source Config; md5sum "/d/Game/LifePlay-master 5.8/Content/BPs/Person.uasset"
2026-10-13T16:10:34+02:00
e0517c63541f249bd9dbda5c39815ba5 */d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset
6318319 2026-10-13 16:10:30.045597500 +0200
M Content/BPs/Person.uasset
M Content/BPs/Room.uasset
M Source/LifePlay/LPDebugSubsystem.cpp
M Source/LifePlay/LPDebugSubsystem.h
b239e1035cb028b78fbd4bb9f0c5f70a */d/Game/LifePlay-master 5.8/Content/BPs/Person.uasset
stat -c '%n %s %y' ".../Content/BPs/Person.uasset" ".../Content/BPs/Room.uasset"
/d/Game/LifePlay-master 5.8/Content/BPs/Person.uasset 20808711 2026-10-13 14:35:14.930487700 +0200
/d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset 6318319 2026-10-13 16:10:30.045597500 +0200
```
Lecture des mesures :
- Le MD5 de Room diffère de l'instantané `A5FA970E` : l'enregistrement a bien eu lieu.
- `Person.uasset` date de 14:35:14, avant B2b : ce n'est pas l'enregistrement de F7. `LPDebugSubsystem.*` viennent
d'autres lots ; aucun n'a été touché.
- Room figurait **déjà** en `M` avant l'enregistrement, avec le MD5 de l'instantané. L'instantané de 15:25 diffère donc
déjà de HEAD. Estimé : enregistrement d'un lot antérieur (B2) non encore commité. À trancher par le gardien avant le
commit.
Retour arrière, sur décision de l'orchestrateur et jamais lancé ici :
1. fermer l'éditeur ;
2. `.\Tools\Snapshot.ps1 -Lot CAM-B2b-retour -Path Content\BPs\Room.uasset` ;
3. `.\Tools\Restore.ps1 -Lot CAM-B2b -Only Content\BPs\Room.uasset -WhatIf`, puis sans `-WhatIf`.
Retour attendu à l'octet : MD5 `A5FA970E…`, 6 060 745 octets.
## 4. Ce qui n'a pas été fait
- `hyper_blueprint_debug_inspect` et journal de l'éditeur : non consultés (§ 1.7).
- `CompileAllBlueprints`, éditeur fermé : il revient à l'orchestrateur (`lp-mcp` § 1, règle 3).
- `IfThenElse_96`, `_97`, `_98`, `_99` n'ont pas été relus ici. Leurs `else` → `IfThenElse_26`, `_9`, `_10`, `_25` sont
établis par les relectures finales de F6a et F6b, pas par celle de F7. `CallFunction_473` (Start ← 502, F4 L17) n'a pas
été relu non plus.
- Comportement à l'exécution : non mesuré (aucune PIE, aucun build), seulement déduit du câblage.
- Preuve en jeu (build empaqueté + `LogStats`), V5 et V6 : hors rôle ; c'est la suite de l'orchestrateur.
- Fermeture de l'éditeur : non faite, selon la consigne. PID 10708 reste ouvert.
## 5. Points à confirmer en VAL
1. **Vue autre que C2** : `DownUp` prend `else` → `IfThenElse_8`, avec la chaîne d'origine inchangée (Condition ←
CABO_17, then → `IfThenElse_17`). Établi par le câblage ; à confirmer en jeu (hauteur de l'ancienne caméra identique).
2. **Vue C2** : `DownUp` ajoute `AxisValue × 3` à `C2Height`, borné à [−40, 150]. L'effet passe par `ComputeC2Target`
(F3) au prochain appel. Signe et gain sont à juger à l'essai.
3. **`LogStats`** : aucun `Accessed None` nouveau sur `CallFunction_439` / `VariableGet_262`. PO8 est évalué à chaque
`DownUp`, probablement à chaque image tant que l'axe est actif (estimé, appelant non lu).
4. **Cas limite (estimé, déjà noté en F6a et F6b)** : si `GetViewTarget` et `CamRoom` valent tous deux `None`, PO8 vaut
`true`, et `DownUp` écrit `C2Height` au lieu de piloter l'ancienne caméra.
5. **V5 (`CAM-SPEC.md:382`)** : pour les 5 événements, `then` → nouvelle branche et `else` → branche d'origine :
- CE1 → 96, `else` → 26 ;
- CE4 → 97, `else` → 9 ;
- CE19 → 99, `else` → 25 ;
- CE8 → 100, `else` → 8 ;
- CE55 → 98, `else` → 10.
Également : `SphereTraceSingle` 3 (459, 499, 505), `Vector_BoundedToBox` ≥ 4, `ComputeRoomBox` 1.
6. **Valeurs sérialisées**, à relire par dump (`LPDumpFunction`) sur le fichier enregistré :
- PO35.B = 3.0 ; 511 Min −40.0, Max 150.0 ;
- celles de F1 à F6b, déjà listées dans leurs IMPL (par exemple PO31.B 15.0, 509 [−75, 125], PO33.B 3.0,
510 [−40, 150], Radius 20 de 459, 499 et 505).
7. **Compilation** : jugée sur la seule absence d'exception de `compile_blueprint {warnings_as_errors:true}`. À
recontrôler par `CompileAllBlueprints`, éditeur fermé, avec 0 erreur et 0 avertissement nouveau sur Room.
8. **État git de Room** : il était déjà `M` avant F7 (§ 3). Le gardien doit établir ce que contient le diff par rapport à
HEAD (B2 et B2b ?) avant le commit.
## 6. Fichiers à commiter
Dépôt du jeu, branche `ue5.8` :
- `A Docs/Migration/etat/CAM/CAM-B2b-IMPL-F7.md`
- `M Content/BPs/Room.uasset`, après VAL (V5, V6), avec la réserve du point 8 du § 5.
`Content/BPs/Person.uasset` et `Source/LifePlay/LPDebugSubsystem.*` n'appartiennent pas à ce lot : ne pas les joindre.
Tours : 30 / 50 (ce Write et la remise du compte rendu compris ; 24 appels MCP, un par message)
## Constats
- Le schéma F6b se rejoue tel quel pour `DownUp` : 6 créations, 1 coupure, 9 liaisons et 3 valeurs, plus 2 lectures
groupées, soit 21 appels pour l'événement.
- Les index de broches sont identiques à F6b (Branche, `Clamp(Float)`, `|SetC2Height`) ; `|GetC2Height` → out 0.
- Dans le graphe, les numéros des nœuds créés suivent ceux de F6b : `IfThenElse_100`, `VariableGet_296`,
`PromotableOperator_35` et `_36`, `CallFunction_511`, `VariableSet_71`.
- `save_assets` sur `/Game/BPs/Room` renvoie `{"returnValue":true}` (booléen) ; les écritures de graphe renvoient
`null`.
- À verser : lp-mcp § 3 — `save_assets {asset_paths:["/Game/BPs/X"]}` (toolset `editor_toolset.toolsets.asset.AssetTools`)
renvoie `true`. Avant d'enregistrer, mesurer le MD5 et `git status` : un asset peut déjà être `M` du fait d'un lot
antérieur, ce qui change ce que le gardien commitera.