340 lines
26 KiB
Markdown
340 lines
26 KiB
Markdown
# CAM-COMMUN3-DIAG : D8 KO, caméra collée à la nuque (2026-10-13)
|
||
|
||
Demande de Big Boss : quel `Wall`, pourquoi la tête est dans sa collision, quel correctif parmi (a), (b), (c). Lecture
|
||
seule, sans UE ni MCP. Aucune écriture avant GO.
|
||
|
||
Sources :
|
||
- journal partiel `D:\Game\LifePlay_Backup_5.5\COMMUN-3\essais\LifePlay_commun3_partiel_2030_BOSS.log` (MD5
|
||
`d42c53f9…`, heures UTC = locale − 2 h) ;
|
||
- dump Room `CAM-B2f-VAL_LPDumpFunction_20261013-195332.txt` ;
|
||
- composants Person `CAM-T4_LPDumpComponents_20261011-004910.txt` ;
|
||
- carte `ST/STE/STE-D_LPDumpComponents_20261010-113200.txt` ;
|
||
- StreetMap_Static `ST/STA/dumps/StreetMap_Static__EventGraph.txt` ;
|
||
- `CAM-B1-IMPL.md` (B1-12).
|
||
|
||
## 1. Relevé du témoin (23 lignes `Temoin C2`, 18:25 à 18:29 UTC)
|
||
| Objet touché par les deux sondes (Camera et Visibility, toujours identiques) | Lignes | Pièces (largeur de boîte X × Y) |
|
||
|---|---|---|
|
||
| `StaticMeshComponent0` de `Wall` (caché), **départ déjà dedans** | 16 | 665 × 640 (15), 847 × 815 (1) |
|
||
| `StaticMeshComponent0` de `Wall` (caché), à 61-131 cm de la tête | 4 | 257 × 1515 (rue, 2), 1028 × 990, 665 × 640 |
|
||
| rien | 3 | rue 257 × 1515 (2), 847 × 815, marge de boîte 19 à 37 cm |
|
||
Aucune ligne ne touche un personnage (`Person_C` : 0).
|
||
|
||
## 2. DIAG
|
||
**Quel `Wall` (prouvé).** Ce n'est pas un mur de Room (`Wall1-4`, ignorés avec Room par `bIgnoreSelf`). C'est l'acteur
|
||
`StaticMeshActor` **`PersistentLevel.Wall`** de CentralLondon :
|
||
- il fait partie des `ShowOnlyActors` des SceneCapture (`STE-D_LPDumpComponents`, l. 11) ;
|
||
- `GI.Wall` le référence ;
|
||
- c'est le **panneau de fond** qui montre l'image du lieu : `StreetMap_Static.UpdateWall(Amenity)` lui donne la
|
||
texture `AmenityBackgrounds` (`WallDM`, paramètre `PNG`).
|
||
Il est **caché dès qu'une pièce est affichée** : Room B1-12, `GI.Wall` caché = NON(`Room.bHidden`), nœud 88 ; et
|
||
`Wall` caché en C1, nœud 438. Le témoin le donne toujours `cache=1`.
|
||
|
||
**Pourquoi la tête est dedans (prouvé pour le fond, estimé pour la position).**
|
||
- `Wall` est fixe dans le niveau. La pièce, elle, est toujours posée au même point (`Room loc = (-3131543,
|
||
-14967213, -115)` dans tous les relevés du journal COMMUN-2) mais change d'échelle selon le lieu (3,5 × 18,
|
||
8 × 8, 12 × 12, 45 × 45). Le panneau traverse donc l'intérieur de certaines pièces : 4 pièces différentes ici.
|
||
- Le joueur le traverse sans être arrêté : la capsule de `Person` **ignore WorldStatic** (profil `Custom`, écarts
|
||
Visibility / WorldStatic / Pawn Ignore, dump T4). `Wall` est un `StaticMeshActor`, donc WorldStatic (type par
|
||
défaut, estimé).
|
||
- Sa collision, invisible mais active, bloque Camera **et** Visibility. Les sondes partent de la douille `head` déjà
|
||
dans le panneau : impact à 0 cm, `bStartPenetrating`. La caméra se place alors à 20 cm de la tête, à hauteur 0
|
||
(à 18:28-18:29, joueur immobile, 13 lignes de suite).
|
||
|
||
**Correction du DIAG de COMMUN-2.** La cause « PNJ cachés en collision » était **fausse**. Le témoin ne voit aucun
|
||
personnage, et le passage au canal Visibility (B2f) n'a rien changé, puisque `Wall` bloque aussi ce canal. La vraie
|
||
cause de « caméra trop près autour des meubles » est très probablement `Wall` : le joueur debout près d'un meuble se
|
||
trouve dans la bande du panneau. Le passage à Visibility reste neutre et peut rester en place.
|
||
|
||
Les 3 lignes « rien » (marge de boîte de 19 à 37 cm, rue étroite surtout) relèvent de la boîte B2e. C'est l'effet
|
||
voulu, « toujours dans la pièce ».
|
||
|
||
## 3. Les 3 pistes
|
||
| Piste | Effet sur les 23 lignes | Coût | Risque | Avis |
|
||
|---|---|---|---|---|
|
||
| (a) `GI.Wall` dans les acteurs ignorés des sondes | les 20 lignes `Wall` (16 dedans + 4 à distance) | Room : `add_node_pin` sur `MakeArray_5` + `connect_pins` `VariableGet_260.Wall` (getter `GI.Wall` déjà présent) → nouvelle entrée [2] ; 2 écritures, aucun nœud créé | nul hors caméra : seule la liste `ActorsToIgnore` des 3 sondes (459, 499, 505) change ; `GI.Wall` nul → entrée ignorée | **retenue** |
|
||
| (b) ignorer un impact « départ déjà dedans » | 16 lignes sur 20 : les 4 `Wall` à distance restent | ≈ 4-6 nœuds par sonde (BreakHitResult, NOT, AND) × 3 | masque aussi les vrais cas « dedans » ; ne traite pas la cause | non |
|
||
| (c) collision des murs cachés en Ignore (Camera, Visibility) | les 20 lignes | 3 voies de masquage de `Wall` (PC, Room, GI) ou un sous-système C++ ; touche un acteur du niveau | change le jeu hors caméra (clics, scènes) ; hors périmètre CAM | non pour CAM ; voir § 5 |
|
||
|
||
## 4. Correctif proposé : B2g (Room par `lp-mcp-bp`, plus le témoin C++)
|
||
1. Instantané `.\Tools\Snapshot.ps1 -Lot CAM-B2g` (Room `F2B082D2911D9F7C7BE60C2CF30EE6D5` attendu).
|
||
2. Room :
|
||
- `get_node_infos` sur `K2Node_MakeArray_5` (entrées [0] PlayerCharacter et [1] CamRoom ; sortie vers 459, 499 et
|
||
505) et sur `K2Node_VariableGet_260` (`Wall`, self ← `VariableGet_257.GI`) ;
|
||
- `add_node_pin` sur `MakeArray_5`, puis `connect_pins` `260.Wall` → nouvelle entrée [2] ;
|
||
- relecture, `is_dirty` = vrai, compilation stricte, `save_assets` de Room seul, MD5 différent.
|
||
3. Témoin C++ (`LPCameraModeSubsystem.cpp`, `WitnessC2`) : ajouter `GI.Wall` aux acteurs ignorés, pour qu'il reste le
|
||
miroir de la sonde de Room (2 lignes : lecture de `Wall` sur GI, `AddIgnoredActor`).
|
||
- VAL :
|
||
- V5 : `MakeArray_5` a 3 entrées, [2] ← `260.Wall`, aucune autre différence ;
|
||
- V6 = référence ;
|
||
- V7 au prochain build commun.
|
||
- Essai : rejouer D8 dans la même chambre (665 × 640), près du meuble, debout immobile. La caméra reste derrière, à sa
|
||
distance. Les lignes `Temoin C2` ne doivent plus citer `Wall`.
|
||
- Barème :
|
||
- Room : a0 b1 c0 d0 e1 f0 = 2 → N1, ajusté à N3 (MCP par `lp-mcp-bp`) ; S = C3 1 + f 0 = 1 : une fiche ;
|
||
- C++ : a0 b0 c0 d0 e1 f0 = 1 → N1 ; S = 0.
|
||
|
||
## 5. Hors CAM, à signaler (avis seulement)
|
||
`Wall` caché garde une collision qui bloque Visibility au milieu de certaines pièces. Les clics à la souris
|
||
(`GetHitResultUnderCursor`, canal Visibility par défaut) pourraient donc buter sur ce panneau invisible, dans la même
|
||
bande. C'est un défaut probable du jeu d'origine, non mesuré ici. S'il est confirmé, la piste (c), par exemple
|
||
`Wall` en Ignore pour Visibility et Camera pendant qu'il est caché, relève du lot qui tient les clics ou le décor, pas
|
||
de CAM.
|
||
|
||
## 6. Second cas (18:30:11, 18:30:17, 18:30:23 UTC ; lignes relayées par Big Boss, après la copie partielle)
|
||
Signature : « caméra à 23 cm de la tête (hauteur +22) ; sonde Camera : rien ; sonde Visibility : rien ; boîte C2 :
|
||
marge 149 cm (largeur X 847, Y 815) ». À 18:30:05, c'était encore le cas « `Wall`, départ déjà dedans ».
|
||
|
||
**Hypothèses de Big Boss écartées (dump de Room après B2f)** :
|
||
- **distance restée au minimum après le repli** : non. `C2Target` n'a pas de mémoire. `UpdateRoomCam` appelle
|
||
`ComputeC2Target` (467) à chaque passage de la minuterie, et la cible est recalculée depuis la tête (61, 62, puis
|
||
66 en repli). Seule la poursuite `VInterpTo` (468, vitesse 8) lisse le trajet : environ 0,3 s pour combler 90 %,
|
||
pas 12 s.
|
||
- **molette** : non. `C2Dist` est borné entre −75 et +125 autour de 200 cm, donc au moins 125 cm, jamais 23.
|
||
- **boîte B2e** : non. La marge est de 149 cm.
|
||
|
||
**Cause estimée : le même `Wall`, cette fois juste derrière la tête et non autour d'elle.**
|
||
1. La sonde principale 459 va de la tête vers la cible, derrière la rotation de contrôle. Elle touche `Wall` à quelques
|
||
centimètres. La cible devient l'impact + normale × 20 (61), donc à moins de 80 cm.
|
||
2. Le repli s'enclenche (95, seuil 80). La sonde 505 va de la tête vers « tête + 100 en Z + 60 cm vers l'arrière »
|
||
(24, 23, 25). Elle traverse encore le panneau, juste derrière. La cible devient l'impact + normale × 20 (27, 66) :
|
||
un point à environ 20 cm de la tête et un peu au-dessus. C'est exactement la signature : 23 cm, hauteur +22.
|
||
3. Le témoin ne voit rien parce qu'il sonde **vers la caméra**, à plat. La caméra est presque à la verticale de la
|
||
tête, légèrement ramenée vers l'avant par la normale × 20. La sonde part donc à l'opposé du panneau. Le témoin
|
||
n'est pas faux, mais il est aveugle à ce cas : il ne refait pas le trajet de la sonde 459.
|
||
- **Statut : estimé.** Il est cohérent avec la position du joueur juste après le cas « dedans » de 18:30:05 : il en
|
||
sort de quelques centimètres et le panneau reste derrière lui. Il est à confirmer sur le journal définitif, ou par
|
||
le témoin corrigé ci-dessous.
|
||
|
||
**Effet du correctif (a)** : les 3 sondes (459, 499, 505) partagent `MakeArray_5`. Ignorer `GI.Wall` couvre donc aussi
|
||
ce second cas.
|
||
|
||
**Complément au témoin C++ (B2g)** pour que le cas devienne prouvable :
|
||
- sonder aussi **dans l'axe de la sonde 459** : à plat, vers l'arrière de la rotation de contrôle du PC, sur 250 cm ;
|
||
- journaliser la distance tête → `Room.C2Target`.
|
||
Une cible proche avec une sonde vers l'arrière qui touche désigne l'obstacle. Une cible lointaine avec une caméra
|
||
proche désignerait la poursuite. Barème inchangé : N1, S = 0.
|
||
|
||
## 7. KO C1 : « la souris ne fait plus tourner la vue » (vers 18:37:50 UTC)
|
||
**DIAG (prouvé par le dump de Room après B2f et par l'historique git).**
|
||
- **Ce n'est pas une régression de B2d, et l'orientation vers la marche n'est pas de B2d.**
|
||
- `bOrientRotationToMovement = true` et `bUseControllerRotationYaw = false` sont posés dans
|
||
`LPDirectControlSubsystem::Walk` depuis le commit d'origine `5e901be` (Proximité).
|
||
`git log -S bOrientRotationToMovement` ne donne que ce commit. Le diff non commité de STG (3a, 3b) n'y touche pas.
|
||
- En C1, la souris n'a **jamais** tourné la vue. C'est la décision Q11 de la SPEC (« C1 masque cheveux, soleil,
|
||
mur ; pas de regard à la souris »).
|
||
- Dans Room, `CircleCamera` (souris) et `LeftRight` (flèches) ne tournent la rotation de contrôle **qu'en C2**
|
||
(`IfThenElse_96` / `_97`, condition PO_8 : vue = `CamRoom`). Hors C2, sans constructeur, sexe ni espace
|
||
(`IfThenElse_26`, OR 19), la branche `else` est **vide**. Elle l'était déjà avant B2d.
|
||
- **Ce que voit le joueur en C1** :
|
||
- la vue est attachée au maillage, au niveau de la tête (B1-3) : elle tourne seulement avec le corps ;
|
||
- le corps se tourne vers la marche (`bOrientRotationToMovement`) ;
|
||
- la marche suit le lacet de la rotation de contrôle (`Walk`, l. 908), qui ne change qu'en C2 (souris, flèches,
|
||
`PlaceC2`).
|
||
En C1, on ne choisit donc la direction du regard qu'en marchant. Après Q ou D, le corps regarde de côté, mais Z
|
||
ramène vers l'axe de contrôle.
|
||
- **La piste « rétablir `bUseControllerRotationYaw = true` » ne marcherait pas (estimé fort).** Le joueur n'est **pas possédé** par
|
||
le PC : la marche tourne en « physique sans contrôleur », `bRunPhysicsWithNoController` (`Walk`, l. 875-879 ; la marche ne fonctionne que grâce à ce réglage).
|
||
`bUseControllerRotationYaw` n'agit que par `FaceRotation`, appelée par le contrôleur du pion possédé. Sans
|
||
contrôleur, le corps ne suivrait pas la souris.
|
||
- Autre point : `Walk` remet `bOrientRotationToMovement` à vrai à chaque passage où il est faux (l. 888-892). Le
|
||
couper ailleurs, dans Room par exemple, serait annulé à l'image suivante.
|
||
|
||
**Correctif proposé : regard horizontal à la souris en C1, comme un jeu à la première personne.** Il se fait en deux
|
||
parties qui vont ensemble.
|
||
1. **Room (CAM, `lp-mcp-bp`)** : la souris et les flèches gauche/droite tournent la rotation de contrôle en C1 aussi.
|
||
- (N) `BooleanOR` : A ← `PromotableOperator_8` (vue = `CamRoom`), B ← `VariableGet_269.CamC1On` ;
|
||
- sortie → `IfThenElse_96.Condition` et `IfThenElse_97.Condition` (remplace PO_8 sur ces deux seules entrées) ;
|
||
- PO_8 reste relié à 91, 98, 99 et 100 : molette et flèches haut/bas inchangées hors C2.
|
||
1 nœud, 4 liens. Barème : a0 b1 c0 d0 e1 f1 = 3 → N1, ajusté à N3 (MCP) ; S = C3 1 + f 1 = 2 < 3. Peut passer dans
|
||
la même ouverture d'éditeur que B2g.
|
||
2. **`LPDirectControlSubsystem::Walk` (fichier STG, correctif exact)** : en C1, le corps suit le lacet de contrôle et
|
||
n'est plus orienté par la marche. En sortant de C1, on revient à l'orientation vers la marche.
|
||
```cpp
|
||
// dans Walk, a la place du bloc « if (!Move->bOrientRotationToMovement) { ... } » (l. 888-892)
|
||
const bool bFirstPerson = FirstPersonView(GI, Pawn, PC); // C1 : Room.CamC1On et vue = le joueur
|
||
if (Move->bOrientRotationToMovement == bFirstPerson)
|
||
{
|
||
Move->bOrientRotationToMovement = !bFirstPerson;
|
||
Character->bUseControllerRotationYaw = false; // sans effet sans controleur ; garde l'etat d'origine
|
||
}
|
||
if (bFirstPerson)
|
||
{
|
||
// C1 : le corps (et la vue attachee a la tete) suit le lacet de la souris, a chaque image.
|
||
Character->SetActorRotation(FRotator(0.f, PC->GetControlRotation().Yaw, 0.f));
|
||
}
|
||
|
||
// espace anonyme, a cote de ScenePlaying
|
||
bool FirstPersonView(const UObject* GI, const APawn* Pawn, const APlayerController* PC)
|
||
{
|
||
const FObjectPropertyBase* RoomProp = GI ? CastField<FObjectPropertyBase>(GI->GetClass()->FindPropertyByName(TEXT("Room"))) : nullptr;
|
||
const UObject* Room = RoomProp ? RoomProp->GetObjectPropertyValue_InContainer(GI) : nullptr;
|
||
const FBoolProperty* C1 = IsValid(Room) ? CastField<FBoolProperty>(Room->GetClass()->FindPropertyByName(TEXT("CamC1On"))) : nullptr;
|
||
return C1 && C1->GetPropertyValue_InContainer(Room) && PC && PC->GetViewTarget() == Pawn;
|
||
}
|
||
```
|
||
- En entrant en C1 par C, le corps prend le lacet de contrôle, donc la direction où regardait C2. La vue reste
|
||
ainsi dans l'axe de la caméra précédente. Aucun alignement n'est nécessaire.
|
||
- Pas de regard vertical (tangage) dans ce correctif : il faudrait tourner `FirstPersonSM`. C'est à décider à part.
|
||
- Barème STG : a0 b1 c0 d1 e1 f1 = 4 → N1 ; S = 0 (code exact) + 1 = 1.
|
||
- Essai :
|
||
- en C1, la souris et les flèches gauche/droite tournent la vue sur place ;
|
||
- Z avance là où l'on regarde, Q et D font un pas de côté sans tourner la vue ;
|
||
- en C2, rien ne change ;
|
||
- en revenant en C1, la vue regarde dans l'axe de la caméra C2.
|
||
- **Dépendance** : sans la partie 1, la partie 2 fige le corps sur un lacet que rien ne change en C1. Les deux parties
|
||
doivent entrer dans le même build.
|
||
|
||
## 8. Troisième cas (session 2, joueur assis, 18:54:08-20) et géométrie de `Wall` (prouvée)
|
||
**Géométrie de `Wall` (prouvée, deux sources concordantes)** :
|
||
- relevé de la carte `portage55/L6f/L6f_LPDumpComponents_20260930-112932.txt` (`-Filter=Wall`) :
|
||
`StaticMesh = /Engine/BasicShapes/Cube`, `BodyInstance = (ObjectType=ECC_WorldStatic, CollisionProfileName="BlockAll")`,
|
||
`RelativeLocation = (-3131490, -14967219, 26)`, `RelativeScale3D = (0.1, 12.5625, 5.75)` ;
|
||
- boîte journalisée en jeu par ShowCouple (« coque Wall ignorée », journal COMMUN-2) :
|
||
`Min = (-3131495, -14967847.1, -261.5)`, `Max = (-3131485, -14966590.9, 313.5)`.
|
||
|
||
C'est une **plaque verticale de 10 cm d'épaisseur** (X), longue de 12,56 m (Y) et haute de 5,75 m. Elle est fixe et
|
||
se trouve à **53 cm du centre de la pièce** (Room toujours en X = -3131543), parallèle à Y. Elle traverse donc
|
||
**toutes les pièces**, pas seulement certaines (correction du § 2). Elle est cachée, mais `BlockAll` bloque Camera,
|
||
Visibility et tout le reste. Le joueur la traverse, car sa capsule ignore WorldStatic. ShowCouple l'ignorait déjà
|
||
comme « coque ».
|
||
|
||
**Recoupement avec le témoin (session 1, MD5 `27e654cc…`)** :
|
||
- la longue série « départ déjà dedans » de 18:28:08 à 18:29:21 a lieu joueur immobile en X = -3131499,6 : dans
|
||
la plaque, à 5 cm de la face X = -3131495 ;
|
||
- à 18:30:11-23 (« rien », 23 cm, +22) puis 18:30:29 (« dedans », même caméra), le joueur est immobile en
|
||
X = -3131522,9 : à 28 cm de la face, la tête oscille au bord de la plaque ;
|
||
- les autres lignes ont une position relevée jusqu'à 5 s plus tôt (vidage périodique), le joueur étant en marche :
|
||
elles ne se comparent pas.
|
||
|
||
**Le troisième cas est le même mécanisme que le § 6 : la plaque juste derrière la tête.**
|
||
- La sonde 459 touche la plaque à quelques centimètres derrière, et la cible passe sous 80 cm.
|
||
- Le repli 505 (haut 100, arrière 60) touche encore la plaque. Si la face est à environ 35 cm derrière la tête, la
|
||
sphère de 20 cm la touche à environ 15 cm en arrière et 25 cm en haut. Avec la normale × 20 vers le joueur, on
|
||
obtient environ 25 cm de la tête, hauteur +25 : la signature « 26 cm, +26 » est retrouvée.
|
||
- Assis, la tête est plus basse, mais le calcul part de la douille `head` du maillage (455, et pareil pour le témoin).
|
||
Les pistes « point de tête lu sur la capsule », « position assise décalée » et « tangage de C2 » sont donc écartées.
|
||
Le tangage n'existe pas : `MakeRotator(0, 0, lacet)`.
|
||
- Le témoin dit « rien » parce qu'il sonde à plat **vers la caméra**. Ici, elle est presque à la verticale de la tête
|
||
et un peu en avant, à cause de la normale × 20 : la sonde part à l'opposé de la plaque.
|
||
- **Contrôle à faire au journal définitif de la session 2** : X du joueur à 18:54 entre environ -3131560 et
|
||
-3131420 (plaque à ±70 cm, selon la direction du regard). Si X sort nettement de cette bande, l'hypothèse tombe et
|
||
le cas reste ouvert.
|
||
|
||
**Le correctif (a) couvre les trois cas.** Les 3 sondes (459, 499, 505) partagent `MakeArray_5`. Avec `GI.Wall`
|
||
ignoré, ni la sonde principale ni le repli ne voient plus la plaque. Rien d'autre que la plaque ne bloque Visibility
|
||
dans la pièce : les personnages l'ignorent, et Room est ignoré par `bIgnoreSelf`.
|
||
- Variante plus robuste, au choix de Big Boss : ignorer **tout acteur caché** dans les sondes. Il faudrait un filtre
|
||
sur `HitActor.bHidden` et un nouveau balayage, ce qui fait bien plus de nœuds. Non retenue : `Wall` est le seul cas
|
||
relevé.
|
||
|
||
**Conséquence hors CAM (renforce le § 5)** : une paroi invisible et `BlockAll` coupe chaque pièce en deux, à 53 cm
|
||
du centre. Pour la marche, le joueur ne la sent pas (WorldStatic ignoré). En revanche, tout tracé Visibility, comme
|
||
les clics, ou WorldStatic, comme la sonde de ShowCouple qui l'ignore déjà, peut buter dessus. Il faudrait la passer
|
||
en `NoCollision`, puisqu'elle ne sert que de fond aux SceneCapture, mais c'est une décision hors CAM : acteur du
|
||
niveau, lot de décor ou STG.
|
||
|
||
## 9. Finalisation sur les journaux définitifs (bilan `etat\BOSS\COMMUN-3-BILAN.md`)
|
||
Journaux lus :
|
||
- session 1 : `LifePlay_commun3_session1_definitif_BOSS.log` (`27e654cc…`, 275 relevés `Room loc`) ;
|
||
- session 2 : `LifePlay_commun3_session2_ferme_BOSS.log` (`61e37cf3…`, 164 relevés `Room loc`).
|
||
Dans les deux sessions, Room est toujours en (-3131543, -14967213, -115).
|
||
|
||
### D8 cas 1 et 2 : prouvés, cause `GI.Wall`
|
||
Voir le § 8. La plaque est fixe : aucun Blueprint relevé ne la déplace. GI, PC, Room et StreetMap ne font que la
|
||
cacher, changer sa visibilité ou son matériau (dumps lus). Les cas « dedans » relevés loin de la plaque ont une
|
||
position vieille de 1 à 4 s, joueur en marche ou changement de pièce (18:56:54-59 en session 2) : ils ne s'y
|
||
opposent pas.
|
||
|
||
### D8 cas 3 (session 2, 18:53:20 à 18:54:38 UTC, assis) : mécanisme prouvé par élimination, objet probable
|
||
- Le joueur (Bridget) est immobile pendant 80 s, en X = -3131579,5, Y = -14967396 (`fnt_chair06-f-0-sit`, `_48`).
|
||
La caméra reste stable, à 26-27 cm de la tête et hauteur +26 (14 lignes).
|
||
- **Une sonde a forcément touché.** Sans impact, la cible est à au moins 125 cm (`C2Dist` borné) et la caméra la
|
||
rejoint en environ 0,3 s. `C2Scripted` n'est jamais mis à vrai (B4 non fait, seule écriture = faux). La boîte a une
|
||
marge de 135 cm. Le repli sans impact place la cible à environ 117 cm. Seul un impact suivi du repli donne
|
||
« 26 cm, +26 ».
|
||
- **Ce qui peut bloquer Visibility à moins de 80 cm** :
|
||
- Room : ignoré par `bIgnoreSelf` ;
|
||
- le joueur et `CamRoom` : ignorés ;
|
||
- les personnages : capsule et maillage ignorent Visibility, et le plus proche, Laura, visible, est à 187 cm ; les
|
||
PNJ cachés sont à 212 cm et plus ;
|
||
- il ne reste que la plaque `Wall`, à 84 cm du centre de la capsule, dans l'axe X.
|
||
- **Point non mesuré** : la tête du personnage assis est-elle décalée d'environ 50 cm vers la plaque par rapport à la
|
||
capsule ? C'est la condition géométrique pour obtenir 26 cm, +26. Le journal ne donne pas la position de la tête.
|
||
- Le témoin dit « rien », car il sonde vers la caméra, presque à la verticale, et pas dans l'axe de la sonde 459.
|
||
- **Statut : probable.** Le correctif (a) le couvre si l'objet est bien `Wall`. Le témoin complété (§ 10, C) le
|
||
tranchera à COMMUN-4 : position de la tête, décalage par rapport à la capsule, distance de la cible et sonde dans
|
||
l'axe de 459.
|
||
|
||
### C1, souris : voir le § 7 (prouvé). Correctif en deux parties, Room (CAM) et `Walk` (STG).
|
||
|
||
## 10. Correctifs exacts pour COMMUN-4 (aucune écriture avant GO)
|
||
| Id | Fichier | MD5 attendu avant écriture | Écrit par | Jeton |
|
||
|---|---|---|---|---|
|
||
| A. B2g (D8) | `Content/BPs/Room.uasset` | `F2B082D2911D9F7C7BE60C2CF30EE6D5` | `lp-mcp-bp` | UE |
|
||
| B. B2h (C1, partie Room) | `Content/BPs/Room.uasset` (même ouverture que A) | idem, puis MD5 après A et B | `lp-mcp-bp` | UE |
|
||
| C. témoin C2 complété | `Source/LifePlay/LPCameraModeSubsystem.cpp` | `1DE73AA932AF2A056E1B8528CED4DCAB` (`.h` `84F9BA30…` inchangé) | session CAM | aucun (compilé au build) |
|
||
| D. C1, partie `Walk` | `Source/LifePlay/LPDirectControlSubsystem.cpp` (STG) | `827F19C0B7A78BDF578ACF4AE6C2289D` (relevé du 2026-10-13, état STG non commité) | STG | aucun (compilé au build) |
|
||
GI (`E64B5B37…`) et Person (`8668A47C…`) ne sont pas touchés.
|
||
|
||
**A. B2g : `GI.Wall` ignoré par les 3 sondes de C2.** Instantané `.\Tools\Snapshot.ps1 -Lot CAM-B2g -Path
|
||
Content\BPs\Room.uasset`. Préfixe `/Game/BPs/Room.Room:EventGraph.`, un appel MCP par message :
|
||
1. `get_node_infos` `K2Node_MakeArray_5` : entrées [0] ← `VariableGet_261.PlayerCharacter`, [1] ←
|
||
`VariableGet_268.CamRoom` ; sortie `Array` → 459, 499, 505 `.ActorsToIgnore`.
|
||
Et `K2Node_VariableGet_260` : `Wall`, self ← `VariableGet_257.GI`, sortie → 88 et 438 `.self`.
|
||
2. `add_node_pin` `K2Node_MakeArray_5` → nouvelle entrée [2] (relever son PinID).
|
||
3. `connect_pins` `260.Wall` (sortie) → `MakeArray_5.[2]`.
|
||
4. Relecture des 3 entrées et des 3 sorties de `MakeArray_5`, puis de 88 et 438 (liens de 260 conservés).
|
||
B ne crée ni ne supprime de nœud. Si elle vient seule, faire la séquence `create_node` / `delete_node` d'une Branche
|
||
isolée avant l'enregistrement (amendement B2f-a), si `is_dirty` est faux.
|
||
|
||
**B. B2h : en C1, la souris et les flèches gauche/droite tournent la rotation de contrôle** (§ 7, partie 1).
|
||
5. `create_node` du OU booléen. Même type que `K2Node_CommutativeAssociativeBinaryOperator_19` (`BooleanOR`) :
|
||
prendre le `type_id` par `find_node_types` (filtre « OR »). 2 entrées A et B.
|
||
6. `connect_pins` `PromotableOperator_8.ReturnValue` → OR.A ; `VariableGet_269.CamC1On` → OR.B.
|
||
7. `connect_pins` OR.ReturnValue → `IfThenElse_96.Condition`, puis → `IfThenElse_97.Condition`.
|
||
`connect_pins` remplace le lien d'entrée existant (PO_8) sur ces deux seules conditions.
|
||
8. Relecture :
|
||
- PO_8 reste relié à 91, 98, 99, **100** et OR.A, et ne l'est plus à 96 ni 97 (amendement E1 : 100 = `DownUp`, hauteur de C2, omis dans la première liste ; écritures inchangées) ;
|
||
- 269 garde ses liens (77, 82, 84) et ajoute OR.B ;
|
||
- 96.then → 516 et 97.then → 518 sont inchangés.
|
||
9. Pour A et B : `is_dirty` = vrai, compilation stricte, `save_assets` de Room seul, MD5 différent de `F2B082D2`.
|
||
VAL : V5, avec seulement ces différences (`MakeArray_5` [2], 1 nœud OR, conditions de 96 et 97), Room = 1261 nœuds ;
|
||
V6 = référence.
|
||
Barème A + B : a0 b1 c0 d0 e1 f1 = 3 → N1, ajusté à N3 (MCP) ; S = C3 1 + f 1 = 2 < 3 : une fiche.
|
||
|
||
**C. Témoin C2 complété** (`LPCameraModeSubsystem.cpp`, code exact) :
|
||
```cpp
|
||
// LPCameraModeLocal
|
||
const FName GIWall(TEXT("Wall"));
|
||
const FName RoomC2Target(TEXT("C2Target"));
|
||
|
||
// WitnessC2, apres Query.AddIgnoredActor(Cam) : meme liste que MakeArray_5 apres B2g
|
||
if (AActor* Wall = Cast<AActor>(LPCameraModeLocal::ReadObject(GI, LPCameraModeLocal::GIWall)))
|
||
{
|
||
Query.AddIgnoredActor(Wall);
|
||
}
|
||
// Probe prend la direction en parametre : auto Probe = [&](ECollisionChannel Channel, const FVector& Direction) -> FString
|
||
const FString CameraText = Probe(ECC_Camera, Dir);
|
||
const FString VisibilityText = Probe(ECC_Visibility, Dir);
|
||
// Axe de la sonde 459 : a plat, derriere la rotation de controle du PC.
|
||
const APlayerController* PC = World->GetFirstPlayerController();
|
||
const FVector Back = PC ? -FRotationMatrix(FRotator(0.f, PC->GetControlRotation().Yaw, 0.f)).GetUnitAxis(EAxis::X) : -Player->GetActorForwardVector();
|
||
const FString BackText = Probe(ECC_Visibility, Back);
|
||
FVector Target;
|
||
const FString TargetText = LPCameraModeLocal::ReadVector(Room, LPCameraModeLocal::RoomC2Target, Target) ? FString::Printf(TEXT("%.0f cm"), FVector::Dist(Head, Target)) : FString(TEXT("illisible"));
|
||
const FVector Offset = Head - Player->GetActorLocation();
|
||
UE_LOG(LogLifePlay, Log, TEXT("Temoin C2 : camera a %.0f cm de la tete (hauteur %+.0f) ; cible C2 a %s ; tete (%.0f, %.0f), decalage capsule %.0f cm ; vers la camera, Camera : %s, Visibility : %s ; vers l'arriere, Visibility : %s ; boite C2 : %s"),
|
||
Distance, CamLoc.Z - Head.Z, *TargetText, Head.X, Head.Y, Offset.Size2D(), *CameraText, *VisibilityText, *BackText, *BoxText);
|
||
```
|
||
Sauvegarde `Backup_5.5\CAM-B2g\Source\LifePlay\` avant modification. Barème : N1 ; S = 0.
|
||
|
||
**D. `Walk`, partie STG** : le code exact est au § 7. Le bloc à remplacer est maintenant aux **l. 935-939** de la
|
||
version `827F19C0` : `if (!Move->bOrientRotationToMovement) { … }`. La lecture de `GI` et `PC` se trouve en tête de
|
||
`Walk` (l. 908 et suivantes). **D n'a de sens qu'avec B** : il faut les mettre dans le même build.
|
||
|
||
**Cas de test pour COMMUN-4** :
|
||
- D8 : rejouer la chambre et le joueur assis. Aucune ligne `Temoin C2` sous 100 cm hors des rues étroites. Si une
|
||
ligne reste, elle donne la cible, la tête et la sonde vers l'arrière.
|
||
- C1 : la souris et les flèches gauche/droite tournent la vue ; Z avance là où l'on regarde ; C2 est inchangé.
|