# CAM-COMMUN6-DIAG : caméra immobile en mode Scene pendant le sexe (lecture seule, sans UE, 2026-10-14) Origine : essai COMMUN-6 (relais de Big Boss). L'utilisateur : « J'ai perdu à nouveau le droit de déplacer la caméra dans la scène de sexe ». Journal lu sans le modifier : `D:\Game\LifePlay_Build_5.8_COMMUN-6_Development\Windows\LifePlay\Saved\Logs\LifePlay.log` (05:11 à 05:18 UTC). Sources : dumps de la VAL B2kmn (Room `CAM-B2kmn-VAL_LPDumpFunction_20261014-011706.txt`, PC `…-011816.txt`), état actuel (Room `3A451FDD`, PC `F45BE57A`). Aucune écriture, aucun appel MCP. ## 0. Ordre de traitement (priorité de l'utilisateur : « injouable à cause de C1 ») | Rang | Défaut | Section | Cause | Correctif | Fiche | Avant ORG4 ? | |---|---|---|---|---|---|---| | 1 | Après CharGen : C bloqué, souris C1 sans effet | § 10 | établie pour `SpaceOn` (GI `ShowRender` → 233 ; `CloseCharGen` en cours de partie ne le remet pas) ; souris : H-M (`MainMenuOn` resté vrai), à prouver | B2r : C++ CAM, remet `SpaceOn` (et `MainMenuOn` si le menu est fermé) à la sortie de CharGen ; témoins étendus | `CAM-B2r-FICHE.md` | **oui** : environ 45 min, plus 10 min de compilation, sans éditeur | | 2 | C1 à côté de la tête après un lever ; à-coup à la sortie de CharGen | § 9, § 10.3 | orientation de C1 figée à l'entrée (la minuterie B2k tourne et ne recale que la position) ; pose prise une image avant le retour de la vue | B2s : P5 (orientation à chaque passage) + P6 (pose avant `434`) | `CAM-B2s-FICHE.md` | **oui** : environ 35 min d'éditeur, plus 15 min de VAL | | 3 | Vue C1 au plafond au retour d'une scène | § 7 | même cause que 2 (pose prise sur la tête couchée de fin de scène) | B2s, P5 | `CAM-B2s-FICHE.md` | avec 2 | | 4 | Maj + souris pendant une scène lancée depuis C1 | § 6 | pas de défaut de code trouvé ; POV hors voie Room par conception ; `MoveCamera` requis | B2p, P2 (flèches sans Maj) + témoin | `CAM-B2p-SPEC.md` | non | | 5 | Personnages assis éliminés par le rendu ; caméra immobile en Scene ; ZQSD et flèches | § 8, § 2-3, SPEC | bornes de pose de référence ; Q8 + B2i | B2q (lot à attribuer) ; B2p (P1, P2, P3) | `CAM-B2p-SPEC.md` | non | B2r et B2s se suivent dans un seul jeton UE : compilation C++ (B2r), puis éditeur MCP (B2s), puis VAL. Les fichiers touchés sont distincts : `LPCameraModeSubsystem.*` et `Room.uasset`. ## 1. Ce que dit le journal | Heure | Ligne | Lecture | |---|---|---| | 05:12:30 | C : C2 → C3, vue `CameraScene` | `CameraScene` = `ChargenCameras[0]` = `Room.SceneCamera` (C3 « old ») | | 05:12:33 | C : C3 → C1, `CamC1On=1`, `C1Hidden=1` | vue `PlayerCharacter` à l'image suivante | | 05:12:39 | « Camera: Scene » | entrée en sexe **depuis C1** ; aucun `SetViewTarget` à l'entrée (`CAM-COMMUN4-DIAG.md` § 2) : la vue reste `PlayerCharacter` | | 05:12:43 | C → POV, vue `PlayerCharacter` | POV de `SexPersons[0]` (le MC) | | 05:12:53 | C → POV, vue `Person_C_2147481881` | POV du partenaire | | 05:13:04 | C → Scene, vue **`CameraActor_2147480656`**, `C1Hidden` 1 → 0 | `CameraActor_…` = **`CamRoom`**, la caméra C2 (même acteur qu'à 05:12:08 en C2 ; cf. `CAM-COMMUN5-DIAG.md` § 0) | | 05:13:18 à 05:15:11 | même cycle | à chaque retour en Scene : `CamRoom` | | 05:18:57 | « Camera: C1 First person » | après la scène, C1 revient (fin de sexe, crochet B1-11 de GI : `2699` → `ApplyRoomCamera`, `SexOn` faux) | En mode Scene, la vue n'est donc **jamais** `SceneCamera` : d'abord `PlayerCharacter` (vue C1 conservée à l'entrée), puis `CamRoom` après chaque passage POV → Scene. ## 2. Cause (prouvée par les dumps) Deux choses s'additionnent. **a) La vue pendant le sexe est la caméra C2 (décision Q8, B1-2 et B1-8).** - PC, retour en Scene : `VariableSet_12` (`SexCameraIndex` = 0) → `1800` → `353` `SetViewTargetWithBlend(ChargenCameras[0])` → **`140` `Room.ApplyRoomCamera`** (B1-8). - Room, `ApplyRoomCamera` (`CustomEvent_43`) → `77` (`CamC1On`) vrai → `78` (`SexOn`) vrai → `VariableSet_63` (`C2Scripted` = faux) → `465` `PlaceC2` → `466` `SetViewTargetWithBlend(CamRoom)` → `94` `RestoreC1` (d'où `C1Hidden` = 0) → `329` minuterie. Si `CamC1On` est faux et `CamC3On` faux (mode C2), `79.else` mène au même `VariableSet_63`. **Seul le mode C3** prend `79.then` → `394` `SetViewTargetWithBlend(ChargenCameras[0])`. - Minuterie `UpdateRoomCam` : `91` (vue = `CamRoom`) vrai → `92` (`CamC3On` faux) → `93` (`C2Scripted` faux) → `467` : `CamRoom` suit la tête du joueur, **sans garde `SexOn`**. **b) La souris sans Maj fait tourner `SceneCamera`, qui n'est pas en vue (B2i).** - PC, souris X pendant le sexe : `InputAxisEvent_0` → `244` → `VariableSet_27` (`leftright`) → `73` (`MoveCamera`) → `37` → `101` (`SexOn`) vrai → `75` (`SexCameraIndex` = 0) vrai → `71` (`Room.bHidden`) faux → `499` `Birdview.CircleCamera(leftright)`. - Room, `CircleCamera` (`CustomEvent_1`) → `96` : condition `AND_61` = (`OR_60` (vue = `CamRoom` OU `CamC1On`)) ET **`NOT SexOn` (`453`, B2i)**. Pendant le sexe, 96 est toujours faux → `26` → `19` (`MoveObject`, Maj) faux → `149` `SetActorRotation(SceneCamera)` → B2n (orbite de `SceneCamera`). La même garde ferme 97 (`AND_61`) et 98, 99, 100 (`AND_62`). - Avant B2i, avec la vue sur `CamRoom`, 96 était vrai et la souris faisait tourner `CamRoom` (C2) : la caméra bougeait, mais Maj ne déplaçait plus les personnages (défaut corrigé par B2i). **B2i a fermé la voie C2 pendant le sexe, alors que Q8 garde la vue sur la caméra C2.** Rien de visible ne répond plus à la souris en mode Scene. **Pourquoi COMMUN-5 n'a rien montré** : le cas H1 portait sur Maj + souris (personnages), qui marche. La scène lancée depuis C2 a exactement le même défaut (vue `CamRoom`, souris vers `SceneCamera`). Le départ depuis C1 n'est pas la cause : il change seulement la vue de la première phase (`PlayerCharacter` au lieu de `CamRoom`). **Hors de cause** : - STG : `LPDirectControlSubsystem` s'arrête pendant le sexe (`ScenePlaying`, `.cpp:759` et `:889`) ; - B2m : le POV passe par `75.else` → `136` → `204`, sans lien avec le mode Scene ; - B2k : sa branche est derrière `81` (`SexOn` faux) ; - B2n : il est correct, mais il fait tourner une caméra qui n'est pas en vue. ## 3. Correctif proposé (Room seul, fiche lp-mcp-bp « B2p ») : option A recommandée **Option A : pendant le sexe, la vue Scene est `SceneCamera`, comme dans le jeu d'origine.** Cela revient sur Q8 (décision de l'utilisateur : « étape hors POV = caméra de pièce, C2 si le mode est C1 »). C'est donc à l'utilisateur de décider. L'option A rend B2n utile (orbite autour du couple) et règle aussi la limite B2o (vue de la première phase). - E1 : `ApplyRoomCamera` : Branche S1 (`VariableGet_258.SexOn`) entre `CustomEvent_43.then` et `77`. S1.then → `394` (`SetViewTargetWithBlend(ChargenCameras[0])` → `303` `RestoreC1`, nœuds existants), S1.else → `77`. Le nœud 78 devient inatteignable quand `SexOn` est vrai (laissé en place). - E2 : `UpdateRoomCam` : Branche S2 (`258.SexOn`) entre `CustomEvent_45.then` et `91`. S2.then → `394`, S2.else → `91`. À l'entrée du sexe, la minuterie (qui tourne en C1 et en C2) pose `SceneCamera` dans les 16 ms. - E3 : `303.then` → `441` (`K2_ClearAndInvalidateTimerHandle(RoomCamTimer)`, existant) : la minuterie s'arrête après la pose. Sans cela, elle reprendrait la vue à chaque passage en POV. Hors sexe, en C3, elle s'arrêtait déjà au passage suivant (`82.else` → `440` → `441`) : le résultat est le même. - Fin du sexe : inchangée. Le crochet de fin de sexe (B1-11, GI `2699` → `ApplyRoomCamera`) rappelle `ApplyRoomCamera`, qui rend C1 ou C2 et relance la minuterie (vu à 05:18:57). - Volume : 2 nœuds (Branche), 9 liens, environ 30 appels MCP. Barème : a0 b1 c1 d0 e1 f1 = 4 → N1, ajusté à N3 ; S = C3 1 + f 1 = 2 (moins de 3) : une fiche. Case C9a. - Garde `Accessed None` : `ChargenCameras[0]` est déjà lu sans garde par 394 et par le PC 353. `SexOn` est lu sur `258`, comme 78 et 81. - Risque : le cadrage de `SceneCamera` en début de scène est celui que le jeu d'origine pose (`pickPreset`, `moveToBedIfPossible`). Non revu depuis la migration : à vérifier en V7. **Option B : garder Q8 (vue `CamRoom`) et rendre la souris à C2 hors Maj.** Le `NOT` de 453 lirait `SexOn ET MoveObject` au lieu de `SexOn` (1 nœud AND, 3 liens). La caméra tournerait alors autour de la tête du joueur, à 1 m (cadrage C2), et non autour du couple. B2n resterait sans effet (sauf départ en C3). La première phase depuis C1 tournerait le regard C1. C'est moins proche du jeu d'origine : **non recommandée**. ## 4. Cas de test (à ajouter, V7) | N° | Action | Attendu | |---|---|---| | CAM-41 | Lancer une scène depuis C1, puis depuis C2, puis depuis C3. Souris sans Maj dès le début. | Vue de scène (`SceneCamera`) dès l'entrée ; la caméra tourne autour du couple. | | CAM-42 | C : POV, POV, Scene. Souris sans Maj. | Même orbite ; aucune reprise de la vue par C2. | | CAM-43 | Maj + souris, flèches. | Les personnages tournent et se déplacent (B2i). | | CAM-44 | Fin de la scène. | Retour au mode d'avant (C1, C2 ou C3), minuterie relancée en C1 et C2. | ## 5. Estimation et ordre - Rédaction de la fiche et instantané : 15 min. Passage UE (lp-mcp-bp, puis VAL V5 et V6 par lp-validator) : environ 45 min d'éditeur, plus 1 min de compilation stricte et 1 à 2 min par commandlet. - Room seul. Aucun recouvrement avec STE (ORG4) tant que STE ne touche pas Room. **Pas besoin de passer avant ORG4** : le défaut ne bloque pas l'essai en cours (POV et Maj marchent), et il entre au prochain passage UE. - Décision attendue de l'utilisateur : **option A (revenir sur Q8 pendant le sexe)** ou option B. ## 6. Complément : KO « souris + déplacement » = Maj + souris pour déplacer le couple (précision de l'utilisateur) Question de Big Boss : B2n (après 149) ou B2k (voie C1 de la minuterie) prennent-ils ou coupent-ils la voie Maj quand `CamC1On` est vrai pendant le sexe ? **Non, ni l'un ni l'autre (établi par les dumps).** - B2n est sur `19.else` (sans Maj), après 149. La voie Maj est `19.then` → `29` (`SexOn`) → `ForEach SexPersons` → `SetActorRotation` : B2n ne la touche pas. - B2k est sur `83.then`, derrière `81` (`SexOn` faux). Pendant le sexe, la minuterie s'arrête à `81.then`, qui est vide. - `CamC1On` n'entre dans la voie de la souris que par `OR_60`, qui est masqué par `NOT SexOn` (B2i) dans `AND_61`. Pendant le sexe, 96 et 97 sont faux quel que soit `CamC1On`. Les flèches (97 → 9 → 14 → 27 → 139) suivent la même garde. - STG est coupé pendant le sexe (`LPDirectControlSubsystem.cpp:759`). Aucun C++ ne consomme Maj, la souris ou les flèches (pas d'`InputComponent`, seulement des lectures d'état). - **Preuve au journal que la voie couple marche** : les relevés « LPDebug persons » montrent le couple déplacé ensemble entre 05:13:17 et 05:13:27 (MC et partenaire : (-3131513, -14967009) → (-3131471, -14967049) → (-3131558, -14967097)). Cela se passe en mode Scene, dans une scène lancée depuis C1. Ensuite, la position ne change plus jusqu'à la fin (05:18:57). Le journal ne dit pas si l'utilisateur a essayé. Pistes qui expliqueraient le ressenti sans défaut de code (à confirmer avec l'utilisateur) : 1. **En POV, Maj + souris n'a jamais tourné le couple**, même dans le jeu d'origine : la souris va à `75.else` → `136` → `204` (regard), et Room n'est pas appelée. La scène a passé environ 52 s en POV (05:12:43-05:13:04, 05:13:18-19, 05:14:19-05:15:11). Le cas CAM-38 (« en POV : Maj + souris ») attendait à tort une rotation. 2. **La rotation demande aussi `MoveCamera`** (PC `73`, `InputAction_50` : estimé bouton du milieu ou Alt). Sans ce bouton, la souris va vers `247`/`246` (vitesse d'animation avec `Manual`). 3. Le déplacement par flèches demande Maj (`14`/`17`). Proposition : pas de correctif propre à ce KO. `CAM-B2p-SPEC.md` le couvre : - P2 : les flèches déplacent le couple sans Maj pendant le sexe ; - P3 : un témoin « Sexe : touches … » journalise Maj, `MoveObject`, `MoveCamera` et la vue si le cas revient. ## 7. Complément : après la scène, la vue C1 regarde le plafond (cinéma, assis, `fnt_new047`, dès 05:23) Journal : C1 rétabli à 05:18:57 (fin de scène). Aucune ligne caméra jusqu'à 05:26:00 : C passe de C1 à C2, puis `RestoreC1` remet `C1Hidden` à 0. L'utilisateur dit qu'un passage en C2 rétablit la vue. **Cause (établie par le dump de Room ; seul le moment de la pose est estimé).** En C1, l'orientation de la vue est celle du composant caméra `FirstPersonSM` (classe `FirstPerson_C`, une `UCameraComponent`). Elle est **figée une fois pour toutes à l'entrée en C1, sur la pose de la tête à cet instant** : - voie C1 d'`ApplyRoomCamera`, seulement si `C1Hidden` est faux (`80.else`) : - `430` : `AttachToComponent(Mesh, head, KeepRelative)` ; - `431` : `SetRelativeTransform` à la rotation (90, 90, 0) **par rapport à l'os `head`** ; - `446` : `SetWorldLocation` au milieu des yeux ; - `433` : `AttachToComponent(Mesh, KeepWorld)`. À partir de là, la caméra suit le corps (lacet de l'acteur), mais son tangage reste celui que la tête avait à l'instant de la pose ; - si `C1Hidden` est déjà vrai (`80.then`), on passe directement à `434` `SetViewTarget`, sans aucune remise ; - minuterie C1 : B2k (`512`) recale la **position** à chaque passage, jamais l'**orientation** ; - en C1, hors sexe, aucune voie ne règle le tangage de `FirstPersonSM` : la souris Y va vers `RotateCamera` → 99, qui est faux hors `CamRoom` ; 316 n'est que dans la voie sexe. Enchaînement probable (estimé) : - pendant la scène, chaque retour en Scene passe par `RestoreC1`, qui met `C1Hidden` à 0 (05:13:04, 05:15:11) ; - à la fin de la scène, `ApplyRoomCamera` (crochet B1-11 de GI) prend `80.else` et pose `FirstPersonSM` sur la tête **alors que le corps est encore dans la pose de fin de scène** (`SF_ft04_0`, couché au relevé de 05:18:47). La tête regarde vers le haut, et la vue est figée vers le plafond ; - `C1Hidden` passe à vrai : les `ApplyRoomCamera` suivants (cinéma) prennent `80.then`, sans nouvelle pose ; - le passage en C2 (05:26:00) refait `RestoreC1`. Au retour en C1, la pose est refaite sur une tête droite : la vue revient. - Ce n'est pas B2m : `204` et `316` tournent le `FirstPersonSM` de `SexPersons[i]`, et `431` remplace ensuite toute la rotation relative. B2m n'agit que si `80.then` est pris sans remise. - Le même mécanisme explique toute vue C1 penchée quand on entre en C1 dans une pose où la tête est inclinée (assis, allongé, animation de meuble). **Correctif (B2p, partie P5, Room, même passage que P1 et P2).** Dans la minuterie C1, après `512` (B2k) : `K2_SetWorldRotation(FirstPersonSM 265, MakeRotator(Pitch 0, Yaw ← 514.Yaw, Roll 0))`, avec 514 = `BreakRotator(GetControlRotation)`, qui existe déjà. La vue C1 est remise à l'horizontale, dans la direction de contrôle, à chaque passage (0,016 s), quelle que soit la pose de la tête. Effet de bord voulu : assis, la souris fait aussi tourner la vue (le lacet de contrôle est réglé par B2h). 2 nœuds, 4 liens. Le tangage à la souris en C1 n'est pas traité (ce serait une demande à part). **Déplacement impossible** au même moment : piste STG, hors CAM. Le relevé de 05:19:02 montre que le joueur occupe de nouveau `NODE_AddStaticMeshComponent-0_37` après la scène (`OnSeat` : la marche ne tourne pas le corps). ## 8. PRIORITAIRE (C5-2 bis) : personnages assis éliminés par le rendu (bar, C2, 05:28-05:29 et 05:31-05:32) Cas 1 (05:28-05:29) : la PNJ assise en face disparaît selon l'angle. Cas 2 (05:31-05:32) : le joueur (Bridget, assise à la place `_93`, `hidden=0`, `fnt_new048-f-0-sit`, meshZ -80,4) disparaît quand la caméra bouge ; la chaise est vide au premier plan, les deux PNJ restent visibles. **Preuve que ce n'est pas un meuble entre la caméra et la tête (établi)** : la vue est C2 sans interruption de 05:26:00 à 05:32:57 (lignes « Touche C »). T-occ trace de `CamRoom` vers la tête toutes les 0,5 s (canal Visibility, collision complexe, Room compris). Il n'a écrit qu'une ligne, à 05:26:03 (`fnt_new163`), puis **rien** jusqu'à 05:32:57. Le rayon caméra → tête était donc libre pendant les deux disparitions. C'est le rendu qui élimine le maillage : frustum ou requête d'occlusion, sur des bornes fausses. Cela touche **tous les personnages assis** (et sans doute aussi couchés ou en animation de meuble). **Ce qui est établi (lecture des assets, sans éditeur)** : - `bridget_gp.uasset` et `michael.uasset` n'importent **aucun asset physique** (imports : matériaux, squelette, `/Script/Engine.SkeletalMesh` ; aucun `PhysicsAsset` en import). Sans asset physique, UE calcule les bornes d'un `SkeletalMeshComponent` à partir des **bornes importées de la pose de référence** (debout), décalées de la seule translation de l'os racine. Elles ne suivent pas la pose (moteur, `USkinnedMeshComponent::CalcMeshBound`) ; - `Person.uasset` contient `BoundsScale` (3 fois) et `bUseAttachParentBound` (2 fois) dans sa table des noms : un ou plusieurs composants de Person les modifient. Lesquels et avec quelles valeurs : c'est à lire par MCP ; - aucun C++ du projet ne règle les bornes ni le culling. `r.AllowOcclusionQueries=True` (`DefaultEngine.ini:30`). **Hypothèse (forte, pas encore prouvée)** : la pose assise des meubles (`fnt_*`) déplace le corps par rapport à la racine (meshZ -80,4 au lieu de -90 et décalage du siège). Les bornes debout, centrées sur la racine, peuvent alors se retrouver derrière la table ou le dossier, alors que le corps est visible. La requête d'occlusion matérielle juge ces bornes cachées et élimine tout le maillage. C'est la « chaise vide » sous un angle voisin. Si le maillage du corps utilise en plus `bUseAttachParentBound`, ses bornes sont celles de la capsule, et l'écart est encore plus grand. **Preuve proposée, rapide et sans écriture** : le build COMMUN-6 est en Development, donc la console est disponible. Au même endroit, avec le même angle : - `r.AllowOcclusionQueries 0` : si la PNJ ne disparaît plus, c'est l'occlusion qui est en cause (la commande ne se sauvegarde pas) ; - `show Bounds` : affiche les bornes, on voit si elles sont décalées du corps. **Correctif proposé (CAM-B2q, C++, environ 40 lignes)** : balayage léger toutes les 2 s des `ACharacter` de classe `Person_C`. Pour chacun, on ne retouche que si les valeurs diffèrent, ce qui couvre aussi le changement de maillage. Sur le `SkeletalMeshComponent` du corps et ses enfants maillés (vêtements, cheveux) : - `bUseAttachParentBound = false` pour le corps (les enfants gardent leur réglage) ; - `BoundsScale = 3,0`. `BoundsScale` agrandit la boîte autour de son centre, sans la déplacer : un facteur 2 (environ ±50 × ±25 × ±90 cm → ±100 × ±50 × ±180) peut ne pas couvrir un corps assis décalé de plus d'un mètre de la racine ; 3 laisse de la marge. À ajuster à l'essai avec `show Bounds` ; - `UpdateBounds()` et `MarkRenderStateDirty()`. **Coût** : - Écriture : 30 min, compilation 10 min (sous jeton UE), VAL statique 15 min, essai au build suivant. - En jeu : seuls les personnages de la pièce courante sont concernés (les autres sont cachés). Avec des bornes 3 fois plus grandes, un personnage juste hors écran ou juste caché est encore dessiné (ombres comprises). Pour une dizaine de maillages Daz, le surcoût GPU est faible ; à mesurer par `stat unit` au bar avant et après. Le jeu ne fait aucun travail CPU de plus par image. - Risque : aucun sur la collision et les tracés (les bornes de rendu ne servent pas aux collisions). **Alternatives** : - Un asset physique pour `bridget_gp` et `michael` donnerait des bornes qui suivent les os. C'est plus juste, mais il faut modifier deux gros assets dans l'éditeur, et ses corps entreraient en jeu dans les tracés Visibility (sondes C2 de B2f, T-occ). Hors alpha. - `r.AllowOcclusionQueries 0` dans `DefaultEngine.ini` supprimerait le cas d'occlusion pour tout le jeu, avec un coût de rendu global, et ne règle pas le cas frustum. Non recommandé. **Attention au périmètre** : il ne s'agit pas d'éditer `Person.uasset`, mais de régler en jeu les composants des instances. Le domaine Person relève de STG/STE : **Big Boss attribue le lot**. Le même correctif couvrirait les disparitions du joueur assis dues aux bornes. Celles dues à un vrai meuble entre la caméra et le joueur (T-occ, 05:26:03, `fnt_new163`) relèvent de B2l, après l'alpha. **Témoin proposé avec B2q (T-cull)** : toutes les 0,5 s, pour chaque Person à moins de 15 m dont le bassin est dans l'écran mais qui n'a pas été rendue depuis 0,2 s (`WasRecentlyRendered(0.2)` faux), écrire : `Temoin culling : non rendue, bassin a %.0f cm du centre des bornes, bornes %.0f x %.0f x %.0f, BoundsScale %.1f, parent=%d`. Le témoin peut entrer **avant** le correctif, dans le même build, pour chiffrer le décalage. Il touche le même fichier et prend 15 min de plus. ## 9. Complément (J5) : C1 décalée après le lever au bar (épaule et bras visibles, 05:33-05:34) Journal : - 05:33:02 : passage en C1, assis à `_93` (`C1Hidden=1`, indicateur « C1 First person ») ; - 05:33:04 : « Marche : le joueur quitte …_93 (unOccupyFnt) », puis la marche ; - aucune ligne d'indicateur avant le C de 05:34:22 : la vue est restée `PlayerCharacter` en C1 ; - après le cycle C2 → C3 → C1 (05:34:22-05:34:28), la vue est correcte. **La minuterie de B2k tourne (établi par le dump)** : - elle part sur la voie C1 d'`ApplyRoomCamera` (`434` → `329` `SetTimerDelegate(UpdateRoomCam, 0,016, en boucle)`) ; - elle ne s'arrête que par `441`, après `440` `RestoreC1`, quand `CamC1On` est faux (`82.else`) ou que la vue n'est plus le joueur (`83.else`), ou par un passage en C2 ou C3 ; - ni le lever (`unOccupyFnt`, KO3c) ni la marche de STG n'y touchent : le C++ ne lit et n'écrit aucune variable de Room liée à la caméra. La vue n'a pas quitté le joueur (aucune ligne d'indicateur) ; - l'utilisateur voit la vue « à peu près à hauteur d'yeux » : le recalage de **position** fonctionne. **Cause : l'orientation, la même que § 7 (établi pour le mécanisme, estimé pour la pose)** : - l'orientation de `FirstPersonSM` est posée une fois, à l'entrée en C1 (`431`, par rapport à l'os `head`). Ici, c'était en position assise, la tête tournée ou penchée selon `fnt_new048` ; - ensuite, la caméra est accrochée au corps (`433`, KeepWorld) : elle suit le lacet de l'acteur, mais garde l'écart d'orientation de la tête assise ; - une fois debout, la marche de STG aligne le corps sur le lacet de contrôle (`LPDirectControlSubsystem.cpp:1034`), et la caméra garde l'écart. On voit son épaule et son bras gauches ; - le cycle C refait la pose sur une tête droite, ce qui corrige. - B2k ne recale que la position (`512` `SetWorldLocation`), jamais l'orientation. **Correctif : P5 de `CAM-B2p-SPEC.md`** (`SetWorldRotation(0, lacet de contrôle, 0)` après 512, à chaque passage). Il règle § 7 et § 9 d'un coup : 2 nœuds, 4 liens dans Room. Remarque pour STG : `currentAnimation` reste `fnt_new048-f-0-sit` après le lever (relevés LPDebug). Si `RestoreAnim` rend l'Anim BP `Daily_F_C`, qui relit cette chaîne, le corps pourrait reprendre la pose assise à l'arrêt. Ce n'est pas de mon ressort ; à signaler à STG. ## 10. Complément : après un changement de personnage (CharGen) en C1, C bloqué et souris sans effet (05:35-05:37) Journal : - 05:34:28 : C1 (`SpaceOn=1`) ; - 05:35:55-57 : menu principal, puis CharGen (`LOAD ROOM chargenroom`) ; - 05:36:09 : `LOAD ROOM pub___vin01`, puis `GI FOLLOWUP` ; - 05:37:28 : témoin « Touche C » : `BuilderOn=0 SpaceOn=0 SexOn=0 CamC1On=1 C1Hidden=1 ; entree PC=1 regard ignore=0 viewport ignore=0 ; vue PlayerCharacter`. **H1 est établie** (C bloqué par la garde `SpaceOn` du PC, B1-7, `131`) ; **H4 est écartée** (entrées du PC intactes). ### 10.1 Qui met `SpaceOn` à faux, et pourquoi rien ne le remet (établi, dump GI EventGraph de B1-VAL) Dump du 2026-10-13. Depuis, GI n'a été modifié que par STE-H3d (`CallFunctionReturnBool`), pas sur ces chaînes ; à redumper à la fiche. - Écritures de `SpaceOn` dans GI : 5 nœuds. - Vrai : `240` (`OpenSpace`), `296` (`CreateCharGenWidget`), `297` (`CreateInventoryWidget`). - Faux : `241` (`CloseSpace`), **`233` (`ShowRender`)**. - Sortie de CharGen (`CloseCharGen`, `CustomEvent_101`) : … `RevertStripAll` → `4263` `MovePlayerBack` → `346` `ShowUI` → **`347` `ShowRender`** → `6009` `ClearCharGenWidget` → `1337` `CharGenOn` = faux → `1563` (`GameStart`) : - vrai (nouvelle partie) : `InventoryInput` → `CreateInventoryWidget` → `SpaceOn` = vrai (297) ; - **faux (changement de personnage en cours de partie) : `167` `DelayThenFollowUp`, et rien ne remet `SpaceOn`.** - `ShowRender` (`CustomEvent_519`) : `3014` → `213`, et **les deux branches de 213** mènent à `2920` → `2977` `SetViewTargetWithBlend(PC, Birdview)` → **`233` `SpaceOn` = faux** → `694` `updateAllPersonButtons`. `ShowRender` remet le jeu en mode carte de la ville. Or, ici, le joueur revient dans une pièce (`MovePlayerBack`, puis `LOAD ROOM pub`). - Le seul appel d'`OpenSpace` dans GI est `671`, sur la chaîne de fin de scène (`SceneOn`, `PregnancyBlocked`, `ConsolidateBeautyStandards`). `SpaceOn` reste donc faux jusqu'à la prochaine fin de scène ou la prochaine ouverture de l'inventaire. - C'est un **défaut latent du jeu d'origine**. Il est devenu visible avec nos gardes `SpaceOn` : B1-7 (touche C) et B1-6 (`LoadRoom` n'appelle `ApplyRoomCamera` que si `SpaceOn` est vrai). Après CharGen, un changement de pièce ne réapplique donc plus le mode de caméra. ### 10.2 Souris sans effet en C1 : `SpaceOn` n'en est pas la cause ; hypothèse H-M (à prouver) - Le regard C1 passe par `CircleCamera` → `96.then` (`OR_60` contient `CamC1On`) → `516` `SetControlRotation`. Cette voie ne lit pas `SpaceOn`. - Côté PC, la souris n'appelle `CircleCamera` que si `MoveCamera` est vrai (`73`). `MoveCamera` passe à vrai par `StartMoveCamera`, sur appui d'un bouton de souris (`InputKey_10` et `_14` → `108` / `106`). **Sauf si `JournalOn` OU `ContactsOn` OU `MainMenuOn` est vrai** (`OR_33`, `OR_37` : la branche « vrai » est vide). - **H-M** : CharGen a été ouvert **depuis le menu principal** (`menus=[MainMenu_C]` à 05:35:57). `MainMenuOn` ne passe à faux que par `CloseMainMenu` (GI `CustomEvent_904`). Il est appelé par le PC (`273`) et par le widget `MainMenu` (le nom est dans `MainMenu.uasset`, mais ce widget n'a pas été dumpé). Si le bouton « changer de personnage » ne ferme pas le menu par `CloseMainMenu`, `MainMenuOn` reste vrai : les boutons de souris ne lancent plus `MoveCamera`, et aucune caméra ne répond plus à la souris, dans aucun mode. - Test sans écriture : après CharGen, ouvrir puis fermer le menu principal (Échap, Échap). Si la souris revient, H-M est établie. Le témoin « Touche C » pourrait aussi écrire `MainMenuOn`, `JournalOn`, `ContactsOn` et `MoveCamera` (environ 10 lignes, fichier CAM). ### 10.3 À-coup de la caméra à la sortie de CharGen (estimé) Ordre probable : 1. `MovePlayerBack` recharge la pièce (`LOAD ROOM pub` à 05:36:09.212, avant `FOLLOWUP` à .226). `SpaceOn` est encore vrai (posé par `CreateCharGenWidget`), donc B1-6 appelle `ApplyRoomCamera`. La voie C1 pose `FirstPersonSM` sur la tête (430 à 433), puis attend une image (`449` `DelayUntilNextFrame`). 2. Pendant cette image, `ShowRender` met la vue sur `Birdview` et `SpaceOn` à faux. 3. À l'image suivante, `434` remet la vue sur le joueur et relance la minuterie. B2k recale la position 16 ms plus tard. On voit donc une image de `Birdview`, puis une vue C1 posée sur une tête qui n'est pas encore à sa place (joueur déplacé, pose de CharGen), recalée au passage suivant : c'est l'à-coup. - Avec P5 (B2p), le recalage de l'orientation se fait aussi au premier passage. - Option P6 (Room, environ 3 nœuds), pour supprimer l'à-coup : recaler position et orientation entre `449` et `434`, avant que la vue revienne. ### 10.4 Correctif proposé (CAM-B2r) **F-S (`SpaceOn`)**. Trois options : - (a) **GI**, dans `CloseCharGen`, branche `GameStart` faux : remettre `SpaceOn` à vrai, ou appeler `HideRender` et `OpenSpace`. C'est la réparation la plus juste, mais **GI n'est pas un fichier CAM** : propriétaire à désigner par Big Boss. - (b) **C++ CAM** (`LPCameraModeSubsystem`, environ 30 lignes) : sur le passage de `GI.CharGenOn` de vrai à faux, dès que la vue est de nouveau une caméra de pièce (le joueur avec `CamC1On`, `CamRoom`, ou `SceneCamera` avec `CamC3On`), si `SpaceOn` est faux : mise à vrai par réflexion, avec une ligne au journal (`SpaceOn remis a vrai apres CharGen`). Il agit seulement après CharGen, une fois. 30 min + compilation. Il écrit une variable de GI en jeu, ce qui relève du domaine GI : **à valider par Big Boss**. - (c) Retirer `SpaceOn` des gardes B1-6 et B1-7 (PC et Room). Non recommandé : ces gardes empêchent C et `ApplyRoomCamera` de jouer sur la carte de la ville. **Recommandation : (b) pour l'alpha, (a) ensuite.** **H-M** : correctif seulement si le test le prouve. Ce serait un appel `CloseMainMenu` sur la voie du bouton CharGen du widget `MainMenu` (fichier UI, propriétaire à désigner), ou la même méthode que (b) : `MainMenuOn` remis à faux à la sortie de CharGen si le widget `MainMenu` n'est plus à l'écran. **À-coup** : P6, facultatif, avec B2p-R. **Estimation de B2r** : - (b) et le témoin étendu : environ 45 min, plus la compilation, sous jeton UE ; - (a) et la correction de H-M : 30 à 45 min de MCP chacune, chez leur propriétaire.