# KEY2-DIAG-01 : marche coupée, indicateur de caméra absent et migration non jouée (essai COMMUN-15) Fiche KEY2-DIAG-01 — Niveau N3 — Modèle prévu opus (Medium) | utilisé Opus 5.5 — Session « Medium · KEY2 » — Skills : sk-protocol, lp-lot. Date : 2026-10-20. Ordre de Big Boss `local_104ff22d` (KO COMMUN-15). Lecture du code et des journaux, sans copie UE. Le correctif est décrit au § 4 : écrit sous instantané, **non compilé**. ## 1. Constats de l'essai (cités par Big Boss et par l'utilisateur) - Big Boss, COMMUN-15 : « les touches de direction ne fonctionnent plus ZQSD ou WAQSD. C1 toujours un seul axe. Le bouton apply AZERTY fonctionne les + et - ajustent la vitesse ». - Journal `etat\BOSS\COMMUN-15\COMMUN-15_LifePlay_20261020-1040_encours.log:1465-1470` : « M1e : touche Z vue par Slate ; PlayerInput=1 ; marche coupee (menu clavier) ; focus SViewport ». - Journal `…-1034.log:877-878` : - « Clavier : ../../../LifePlay/Saved/Config/Windows/LPKeyboard.ini illisible, les touches du jeu sont gardees » ; - puis « 51 actions et 17 axes enregistres » (le fichier du joueur est réécrit). - Utilisateur, dans cette session : « le nom de la caméra à l'écran à disparu ». ## 2. Cause 1 : la page Clavier compte comme menu ouvert pour toujours (établi par le code) 1. Les réglages intègrent la page Clavier par `TakeEmbeddedPage` (`LPSettingsSubsystem.cpp:873-875`). Celle-ci garde le panneau dans `Live().Menu` et met `Live().bEmbedded` à vrai (`LPKeyboardSubsystem.cpp`, `TakeEmbeddedPage`). 2. À la fermeture des réglages, `LPSettingsSubsystem` ne fait que replier l'hôte (`LPSettingsSubsystem.cpp:528-531`). `Live().Menu` reste valide : seul `CloseKeyboardMenu` le remet à zéro, et il n'est appelé que pour la fenêtre autonome. 3. `IsMenuOpen()` rendait `Live().Menu.IsValid() && Owner == this` (`LPKeyboardSubsystem.cpp:807-810` avant correctif) : il reste donc **vrai pour toute la partie** après une seule visite de l'onglet Clavier. 4. Trois appelants s'en servent pour couper le jeu : - la marche, « menu clavier » (`LPDirectControlSubsystem.cpp:683-687`) : c'est la cause des touches de direction sans effet ; - la caméra, `MenuOnScreen` (`LPCameraModeSubsystem.cpp:414-426`). `Tick` en déduit `bMenu` (`:748`) et **cache l'indicateur de caméra** quand `bMenu` est vrai (`:770-773`). C'est la cause de « le nom de la caméra à l'écran a disparu ». La même garde coupe sans doute le tangage souris de C1 (constat 3 de Big Boss, estimé) ; - la pièce extérieure (`LPOutdoorRoomSubsystem.cpp:87-92`, `PlayerBusy`) : `LiftSunkPersons` ne relève pas le joueur quand `PlayerBusy` est vrai (`:409-412`). C'est le **personnage enfoncé dans la rue** signalé par l'utilisateur (ancien ERR-128) ; les journaux de COMMUN-15 n'ont aucune ligne « releve de » ni « ecarte de » (relevé de Big Boss). 5. Le défaut est **antérieur à KEY2** : `IsMenuOpen` et `TakeEmbeddedPage` sont inchangés depuis HEAD. KEY2 l'a révélé, car l'essai demandait d'ouvrir l'onglet Clavier pour Apply. Lors des essais précédents, l'onglet n'était sans doute pas ouvert (estimé). ## 2b. Chemins de fermeture du panneau (vérifiés, piste de CAM2) Écritures de `Live().Menu` dans `LPKeyboardSubsystem.cpp` (grep `Live().Menu =` et `Live().Menu.Reset`) : posé par `TakeEmbeddedPage` (`:897`, page intégrée) et par `OpenKeyboardMenu` (`:917`, fenêtre) ; remis à zéro par `CloseKeyboardMenu` seul (`:938`). | Chemin de sortie | Fenêtre autonome | Page intégrée aux réglages | |---|---|---| | Échap | `CloseKeyboardMenu` (`:737`) | Échap n'est pas pris par la page (`return false`, `:732-735`) ; ce sont les réglages qui se ferment | | Bouton Close | `CloseKeyboardMenu` (`:677`) | bouton masqué | | Apply, Reset, liste des dispositions, Change, Add, Remove | ne ferment rien (seul `bWaiting = false`) | idem | | Fermeture des réglages | — | hôte replié (`LPSettingsSubsystem.cpp:528-531`) ; **`Live().Menu` jamais remis à zéro** | | Fin du sous-système | `CloseKeyboardMenu` (`:828`) | idem | Avec le correctif, la page intégrée ne compte comme menu que pendant une capture. Le dernier chemin ouvert était la fermeture des réglages **pendant** une capture (Change ou Add, puis sortie des réglages) : `bWaiting` serait resté vrai. Il est fermé par l'annulation de la capture à la fermeture des réglages (§ 4). ## 3. Cause 2 : le fichier du joueur n'est jamais relu (établi par le code du moteur 5.8) 1. `SaveSaved` écrit les liaisons sous les clés `+ActionMappings` et `+AxisMappings` (`AddToSection(InputSection, TEXT("+ActionMappings"), …)`). L'ancien fichier du joueur a bien cette forme (copie `…_COM15\Windows\LifePlay\Saved\Config\Windows\LPKeyboard.ini.avant` : `+ActionMappings=(ActionName="ActionX",Key=MouseX)`, 55 lignes). 2. `LoadSaved` relit par `FConfigFile::Read`, puis par `GetArray(InputSection, TEXT("ActionMappings"))`. 3. Dans le moteur 5.8, `FConfigFile::Read` appelle `FillFileFromDisk(this, Filename, false)` (`ConfigCacheIni.cpp:2216-2219`). Le troisième paramètre est `bHandleSymbolCommands`. Il est faux, donc le `+` n'est pas retiré du nom de la clé : seul le cas `bHandleSymbolCommands` traite `+ - . ! @ * ^` (`ConfigCacheIni.cpp:2076-2096`). 4. La clé lue s'appelle donc `+ActionMappings`. `GetArray("ActionMappings")` ne trouve rien, d'où 0 action et 0 axe, le message « illisible » (`LoadSaved`), puis la réécriture du fichier par `Initialize` (`if (!LoadSaved()) SaveSaved();`). 5. Conséquences : - la migration `Version=2`, placée après ce retour, **ne joue jamais** ; - plus largement, **aucune touche changée par le joueur ne survit à un redémarrage**. L'Apply AZERTY de COMMUN-15 a été écrit, mais il serait perdu au lancement suivant ; - ce défaut est antérieur à KEY2 : la lecture est inchangée depuis HEAD. ## 4. Correctif (fichier `Source/LifePlay/LPKeyboardSubsystem.cpp` seul) Instantané : `Tools\Snapshot.ps1 -Lot KEY2-FIX1` (avant : 7501ec6a). Après : 7960e871 ; CRLF gardé (1486 lignes, 1486 CR). | Cause | Changement | |---|---| | 1 | `IsMenuOpen()` rend `Live().Menu.IsValid() && Owner == this && (!Live().bEmbedded \|\| bWaiting)`. La page intégrée ne coupe le jeu que pendant une capture de touche. Les réglages ouverts restent vus comme menu par `MainMenu_C` (`LPDirectControlSubsystem.cpp:59-62`, `MenuOnScreen`). | | 2 | `LoadSaved` lit `+ActionMappings` et `+AxisMappings` (forme écrite par `SaveSaved`), puis ajoute ce qu'il trouve sous `ActionMappings` et `AxisMappings` (fichier édité à la main). La migration `Version=2` joue ensuite telle qu'écrite. | | 1 (chemin restant) | `LPSettingsSubsystem.cpp`, à la fermeture des réglages : si une capture est en cours, `CancelWait()`. Instantané `KEY2-FIX1` (avant : b72671af ; après : 5ff9f26d ; +9 lignes, CRLF gardé, 896 / 896). | Aucun autre fichier n'est touché ; `LPCameraModeSubsystem.cpp` n'a pas besoin d'être changé (gel CAM2 respecté). ## 5. Preuves exigées (après BUILD-GO) 1. Build `LifePlayEditor` et Development à code 0, sans nouvel avertissement. 2. Copier `LPKeyboard.ini.avant` (ancien fichier) à la place de `LPKeyboard.ini`, lancer le jeu. - Attendu dans le journal : « Clavier : … passe de la version 0 a 2 : N liaisons retirees … », puis « Clavier : X actions et Y axes relus » ; plus aucun « illisible ». - Attendu dans le fichier : `Version=2`, le pavé 4 / 6, Equals, Hyphen et Tilde retirés. 3. Ouvrir les réglages, onglet Clavier, puis les fermer : la marche ZQSD ou WASD répond ; l'indicateur de caméra s'affiche de nouveau ; plus aucune ligne « marche coupee (menu clavier) ». Pendant une capture (Change), la marche est coupée. Variante : Change sur une touche, puis fermer les réglages sans appuyer : la marche répond aussi. 4. Apply AZERTY, quitter, relancer : AZERTY est toujours en place (`Layout=AZERTY` relu et touches gardées). 5. C1 : le tangage souris est rendu (à confirmer avec CAM2). 6. Rue extérieure : un personnage enfoncé est relevé (ligne « releve de » dans le journal), même après une visite de l'onglet Clavier. Fichiers à commiter : M `Source/LifePlay/LPKeyboardSubsystem.cpp` et `Source/LifePlay/LPSettingsSubsystem.cpp` (avec le reste de KEY2) ; A ce livrable.