LifePlay UE 5.8 : état de développement au 2026-10-21 (alpha 2026.10.2.2a)
Tickets : PUB-20261021-T1
This commit is contained in:
parent
56dfcfc3d2
commit
a82436224a
72 changed files with 7336 additions and 93 deletions
|
|
@ -1,7 +1,7 @@
|
|||
[/Script/EngineSettings.GeneralProjectSettings]
|
||||
ProjectID=543F4F9E4DE525696C82F5A52303C15C
|
||||
ProjectName=LifePlay
|
||||
ProjectVersion=2026.10.2.1a
|
||||
ProjectVersion=2026.10.2.2a
|
||||
Description=Portage UE 5.5 - assets integres depuis LifePlay 5.9 Full Source
|
||||
|
||||
[/Script/MoviePlayer.MoviePlayerSettings]
|
||||
|
|
|
|||
|
|
@ -122,6 +122,10 @@ r.PostProcessAAQuality=2
|
|||
|
||||
[AntiAliasingQuality@2]
|
||||
r.PostProcessAAQuality=4
|
||||
; QPERS (2026-10-20) : nettete a l etalonnage, essai console approuve par l utilisateur (un peu plus net)
|
||||
r.Tonemapper.Sharpen=0.5
|
||||
|
||||
[AntiAliasingQuality@3]
|
||||
r.PostProcessAAQuality=4
|
||||
; QPERS (2026-10-20) : nettete a l etalonnage, essai console approuve par l utilisateur (un peu plus net)
|
||||
r.Tonemapper.Sharpen=0.5
|
||||
|
|
|
|||
|
|
@ -1131,6 +1131,13 @@ Validation L7c/L7d (2026-10-02, parc, même cadrage) : la nuit reste claire (sol
|
|||
| CHG-155 | 2026-10-05 | ShowCouple | Un lit est reconnu par son nom. Il ne bloque un déplacement que vers le bas, pour se poser ; le retour horizontal n'est plus arrêté et le contact ne renvoie plus la boîte | après avoir quitté le lit, la boîte ne pouvait plus y revenir | revenir au test `DoesPackageExist` et au filtre du flanc seul |
|
||||
| CHG-156 | 2026-10-05 | Clavier | `LPKeyboardSubsystem` : bouton « Clavier » ajouté à l'exécution dans `MainMenu.SettingsScrollBox` ; panneau pour changer, ajouter ou retirer une touche (actions et axes clavier). Écrit dans `Saved/Config/Windows`, pas dans `GameSettings.sav` | pouvoir réaffecter les touches, dont Q, sans modifier les Blueprints | retirer `LPKeyboardSubsystem.h/.cpp` et la dépendance `UMG` |
|
||||
| CHG-158 | 2026-10-05 | Réglages | `LPSettingsSubsystem` : onglets Audio, Video, Lewd, General, Keyboard, Misc au-dessus de `SettingsScrollBox`. Les lignes du Blueprint restent en place et sont montrées selon leur texte ; le reste va dans Misc. Keyboard affiche la liste des touches | la liste unique ne montrait pas le clavier | retirer `LPSettingsSubsystem.h/.cpp` |
|
||||
| CHG-387 | 2026-10-21 | REL2 | Jeu (`ue5.8`) : `Config/DefaultGame.ini` ; livrables `Docs/Migration/etat/REL/REL2/` (`REL2-T1-IMPL.md`, `REL2-VAL.md`, `REL2-T2-BUILD.md`, `REL2-ESSAI-FINAL.md`, `REL2-ESSAI-RESULTAT.md`) | Lot REL2 : version de la build 1 = alpha 2026.10.2.2a. **Changement** : `DefaultGame.ini` l. 4, `ProjectVersion=2026.10.2.1a` → `2026.10.2.2a` (`ParseVersion` lit {2026,10,2,2}). **Preuves** : VAL commune `REL2-VAL.md` PASS-STATIC (34 fichiers depuis le tag `v2026.10.2.1a`, PubCheck 0) ; build Shipping `REL2-T2-BUILD.md` (compilation 0 erreur, 0 avertissement ; FULL COOK 8929 paquets ; CheckPackage PASS ; exe MD5 `E6A90334` ; PDB et `BUILD-ID.txt` dans `D:\Game\LifePlay_Build_5.8_ALPHA-2026.10.2.2a_Shipping_PDB`) ; essai final `REL2-ESSAI-RESULTAT.md` 11/11 PASS, dont E9 de F6 (sauvegardes sous `%LOCALAPPDATA%\LifePlay-Revival\Saved\Saves`, sauvegarde de l'alpha 2026.10.2.1a rechargée). **Note** : le `LifePlay.uproject` local (non suivi par décision) limite le plugin éditeur HyperAIStudio à la cible Editor pour que le Shipping ne l'embarque pas (réserve C6) ; ce fichier n'est pas commité | `DefaultGame.ini` `4f89f2d1` → `8d7f4bdf` (une ligne modifiée) ; instantané `D:\Game\LifePlay_Backup_5.5\REL2` | `Tools\Restore.ps1 -Lot REL2` (remet `DefaultGame.ini` à `4f89f2d1`), simulation d'abord avec `-WhatIf` ; ou `git revert` du commit du ticket REL2 par le gardien |
|
||||
| CHG-386 | 2026-10-21 | QPERS | Jeu (`ue5.8`) : `Config/DefaultScalability.ini` ; livrable `Docs/Migration/etat/REL/QPERS/QPERS-PRE.md` | Lot QPERS (netteté du personnage en gros plan). Essai console de l'utilisateur sur la build COM23 (`QPERS-PRE.md` ; `BOSS-JOURNAL.md`, lignes du 2026-10-20 de 23:20 à 23:45) : R2 (`r.Tonemapper.Sharpen 0.5`) « un peu plus net » ; R1 (`r.ScreenPercentage` 125), R3 (`r.TemporalAACurrentFrameWeight` 0.08) et R4 (ombres 4096) « pareil » ou « pas vraiment ». Ordre de l'utilisateur, cité : « Oui, grave r.Tonemapper.Sharpen 0.5 aux niveaux High et Epic, et note le lot assets (profil de peau, ombres de contact) pour la build 2. » **Changement** : ajout de `r.Tonemapper.Sharpen=0.5`, avec une ligne de commentaire, aux sections `[AntiAliasingQuality@2]` (High) et `[AntiAliasingQuality@3]` (Epic). **Constats de l'étude** : la peau est en `MSM_Subsurface`, donc les `r.SSS.*` n'ont aucun effet ; GI repose sur `r.ScreenPercentage`, `r.Streaming.PoolSize` et `r.SSS.Scale` ; le lot QPERS-ASSETS (profil de peau, ombres de contact) est reporté en build 2. **Non vérifié** : pas encore vu en jeu après gravure ; ce sera dans la build de REL2 | `DefaultScalability.ini` `3dca7e5d` → `b3ecb28c` (deux lignes de réglage et leur commentaire ajoutés dans chacune des deux sections), CRLF gardé ; instantané `D:\Game\LifePlay_Backup_5.5\QPERS` | `Tools\Restore.ps1 -Lot QPERS` (remet `DefaultScalability.ini` à `3dca7e5d`), simulation d'abord avec `-WhatIf` ; ou `git revert` du commit du ticket QPERS par le gardien |
|
||||
| CHG-385 | 2026-10-20 | SET1 | Jeu (`ue5.8`) : `Source/LifePlay/LPSettingsSubsystem.cpp`, `Source/LifePlay/LPSettingsSubsystem.h`, `Source/LifePlay/LPColorGradeSubsystem.cpp`, `Source/LifePlay/LPVideoQualitySubsystem.cpp`, `Source/LifePlay/LPModInfoSubsystem.cpp` ; livrables `Docs/Migration/etat/REL/SET1/` (`SET1-PRE.md`, `SET1-V1-IMPL.md`, `SET1-V1b-IMPL.md`, deux copies d'état `SET1-V1_CopieEtat_*.json`, deux `SET1-V1b_CopieEtat_*.json`, quatre résumés de build `SET1_Build_…`), `Docs/Migration/etat/BOSS/COMMUN-23-TESTS.md`, `COMMUN-23-BILAN.md` | Lot SET1 (réglages en partie). Demande de l'utilisateur, citée : « je souhaite passer la désactivation de l ancien panneau settings du menu du jeu et le remplacer par celui du menu principal. » (`BOSS-JOURNAL.md` l. 1030). Défaut établi par l'étude `SET1-PRE.md` et les captures 29 et 30 de l'utilisateur : en partie, l'ancienne liste longue des réglages s'affichait, puis était remplacée par les onglets au bout d'environ 30 s, avec une superposition. Cause (`SET1-V1-IMPL.md` § 0) : `GI.CreateMainMenuWidget` crée un `MainMenu` neuf à chaque ouverture, `ClearMainMenuWidget` ne fait que `RemoveFromParent` ; les anciennes instances restent en mémoire jusqu'au ramasse-miettes avec leur `SettingsScrollBox`, et le `Tick` prenait la première liste trouvée par `TObjectIterator`. **V1** (`LPSettingsSubsystem.cpp`) : choix de la `SettingsScrollBox` du `MainMenu` **à l'écran** (`IsInViewport`, non détruit, visible ; la liste ouverte d'abord, puis celle déjà suivie) par `FindOnScreenSettingsList` (+ `IsUsableObject`, `IsMenuOnScreen`, `IsTitleMenu`, `DropTabs`) ; au changement d'instance, les onglets de l'ancienne sont retirés, l'état par instance remis à zéro, les onglets reposés sur la nouvelle ; `PlaceSettingsButton` filtre aussi sur l'écran ; journaux `Reglages : onglets poses sur <MainMenu_C_n> (ecran titre|partie)` et `Reglages : onglets retires de <ancienne> (instance quittee)`. **V1b** : la fonction de recherche devient une statique publique de `ULPSettingsSubsystem`, partagée par `LPColorGradeSubsystem`, `LPVideoQualitySubsystem` et `LPModInfoSubsystem` à la place de leurs trois boucles « première liste trouvée » ; journaux de Couleur, Video et Mods portant le nom de l'instance. **Preuves** : deux compilations (éditeur et jeu) par étape, code 0, 0 erreur, 0 avertissement (V1 et V1b) ; **essai COMMUN-23** (build Development `COM23`, exe `0f7b0a39…`, `COMMUN-23-BILAN.md`) : cas .1 à .5 **PASS** (utilisateur : « 1 ok , 2 ok », « 3 ok », « 4 ok », « caméra conservé ») ; journal du jeu : 6 instances de menu, chacune avec les trois lignes Couleur, Modules, Video du **même** nom, 5 `onglets poses` (1 `(ecran titre)`, 4 `(partie)`) et 5 `onglets retires`, 0 `already has a parent`, 0 erreur grave. **Non prouvé** : sur le cas .4 (retour au titre), la ligne `onglets poses … (ecran titre)` du second titre manque au journal avant la fermeture du jeu (verdict « 4 ok » de l'utilisateur gardé) ; le correctif ne supprime ni les anciennes instances ni le ramasse-miettes ; périodes des tickers (0,5 s) non modifiées | `LPSettingsSubsystem.cpp` `5ff9f26d` → `3591f579` (V1, +123 −23, CRLF gardé) → `6277a8fc` (V1b, +6) ; `LPSettingsSubsystem.h` `0f98c055` → `138350ef` (+8) ; `LPColorGradeSubsystem.cpp` `f818c7f5` → `5be40054` (+8 −16) ; `LPVideoQualitySubsystem.cpp` `dff29f3f` → `c3055197` (+8 −17) ; `LPModInfoSubsystem.cpp` `1d0fff7d` → `98206e68` (+8 −18, LF gardé) ; V1b au total 5 fichiers +38 −51 | `Tools\Restore.ps1 -Lot SET1-V1b` (remet les 5 fichiers depuis `D:\Game\LifePlay_Backup_5.5\SET1-V1b`, `LPSettingsSubsystem.cpp` à son état de fin de V1) puis `Tools\Restore.ps1 -Lot SET1` (remet `LPSettingsSubsystem.cpp` à `5ff9f26d`), simulation d'abord avec `-WhatIf` ; ou `git revert` du commit du ticket SET1 par le gardien ; puis recompiler |
|
||||
| CHG-384 | 2026-10-20 | FIX1 (M-Z et talons, F8b) | Jeu (`ue5.8`) : `Source/LifePlay/LPDirectControlSubsystem.cpp` ; livrables `Docs/Migration/etat/REL/FIX1/` (`FIX1-F7-PRE.md`, `FIX1-MES.md`, `FIX1-MZ-IMPL.md`, `FIX1-MZ2-IMPL.md`, quatre résumés de build `FIX1_Build_20261020-200728.txt`, `-200822`, `-205618`, `-205639`), `Docs/Migration/etat/BOSS/COMMUN-23-TESTS.md`, `COMMUN-23-BILAN.md` | Lot FIX1 (F8b), en deux temps. **FIX1-MZ** (instrumentation, ordre de l'utilisateur cité par la fiche d'IMPL : « Oui : F7a, F7c et F8b en build 2 ; en build 1, ajoute la hauteur de talons et l'animation à la trace M-Z, et prépare la séance de mesure -LPPersonsLog=2. ») : la ligne de journal `M-Z :` de `FitPersonBounds` gagne `HeelHeight`, `currentAnimation` et `-90+12*HeelHeight`, lus par réflexion après la correction, sans effet sur elle ; build d'essai COMMUN-22 et séance `FIX1-MES.md`. **Constat de la séance** (`BOSS-JOURNAL.md` l. 1023 à 1027, captures 23 à 26) : l'écart de maillage relevé au lever était la compensation normale des talons (−90 + 12 × HeelHeight, soit −80,4 pour 0,8) ; la correction M-Z (introduite par STG-COMMUN9-DIAG) la ramenait à −90 et **enfonçait les pieds en talons d'environ 9,6 cm depuis son introduction** (régression, capture 25 : semelles cachées, pieds dans le parquet). **FIX1-MZ2** (approbation citée, « approuvé », `BOSS-JOURNAL.md` l. 1028, 20:51) : la cible de M-Z devient −90 + 12 × HeelHeight (repli sur la hauteur du gabarit si `HeelHeight` est illisible ou non fini), pour le déclenchement (`Abs(Relative.Z - TargetZ) > 1.0`) comme pour la valeur écrite ; le suffixe `(talons)` n'apparaît que pour un HeelHeight non nul. **Preuves** : compilations éditeur et jeu à code 0, 0 erreur, 0 avertissement (MZ puis MZ2) ; **essai COMMUN-23.6 PASS** (utilisateur : « 6ok », capture 31 : joueur en talons debout, pieds au sol) ; journal du jeu : joueur debout en talons à `meshZ=-80.4` (137 relevés debout, puis 50 après le lever), **0 ligne `M-Z :`** dans la session, 0 `HeelHeight=?` (`COMMUN-23-BILAN.md`). **Non prouvé** : le cas sans talons rejoué par sous-partie (b, c) n'est pas détaillé par l'utilisateur ; des relevés `meshZ=-88.0` du joueur (48) restent inexpliqués ; la lévitation de PNJ (HeelHeight surestimé selon la chaussure) et F7b (posture après « regarder ») sont reportées en build 2 | `LPDirectControlSubsystem.cpp` `5f9d7e00` (62 510 o) → `687c63d8` (64 858 o, MZ, +49 −2) → `86ef519e` (65 503 o, MZ2, +15 −9 ; cumulé +59 −6), CRLF gardé | `Tools\Restore.ps1 -Lot FIX1-MZ2` (remet le fichier à `687c63d8` depuis `D:\Game\LifePlay_Backup_5.5\FIX1-MZ2`), puis `Tools\Restore.ps1 -Lot FIX1-MZ` (remet `5f9d7e00`), simulation d'abord avec `-WhatIf` ; ou `git revert` du commit du ticket FIX1 par le gardien ; puis recompiler |
|
||||
| CHG-383 | 2026-10-20 | FIX1 (F8a) | Jeu (`ue5.8`) : `Source/LifePlay/LPCameraModeSubsystem.cpp` ; livrables `Docs/Migration/etat/REL/FIX1/` (`FIX1-F8a-IMPL.md`, résumés de build `FIX1_Build_20261020-195129.txt` et `FIX1_Build_20261020-195230.txt`), `Docs/Migration/etat/BOSS/COMMUN-23-TESTS.md`, `COMMUN-23-BILAN.md` | Lot FIX1 (F8a) : l'avertissement de compilation C4701 (« variable locale 'Aim' potentiellement non initialisée », `LPCameraModeSubsystem.cpp(2378)`, vu au build du lot F6) est levé en initialisant les deux déclarations `FVector Aim;` de `TickCoupleMouse` à `FVector::ZeroVector` (l. 2278 et 2369). Décision citée par la fiche d'IMPL : « approuvé » (proposition de Big Boss : « F8 (Aim) est trivial et sans risque, il tient en build 1 » ; `BOSS-JOURNAL.md` l. 1010, 19:50). Logique inchangée par construction : `TraceScreen` n'écrit `Out` qu'avant de renvoyer `true`, `Aim` n'est lu que si l'appel a réussi (`:2279`, `:2376-2378`). **Preuves** : compilations éditeur (50 s) et jeu (65 s) code 0, **0 erreur, 0 avertissement** (C4701 absent des deux journaux) ; diff lu par Big Boss (2 lignes) ; **essai COMMUN-23.7 a PASS** (utilisateur : « 7 ok », glissé du couple), 0 erreur grave au journal du jeu. **Non prouvé** : le glissé n'est pas détaillé par sous-partie ; aucune VAL séparée (le diff lu tient lieu) | `LPCameraModeSubsystem.cpp` `4fd44bd4` (136 950 o) → `976bf0a4` (136 994 o, +2 −2, LF gardé) | `Tools\Restore.ps1 -Lot FIX1-F8` (remet le fichier depuis `D:\Game\LifePlay_Backup_5.5\FIX1-F8`, simulation d'abord avec `-WhatIf`) ; ou `git revert` du commit du ticket FIX1 par le gardien ; puis recompiler (l'avertissement C4701 revient) |
|
||||
| CHG-382 | 2026-10-20 | KEY2 | Jeu (`ue5.8`) : `Source/LifePlay/LPKeyboardSubsystem.cpp` ; livrables `Docs/Migration/etat/REL/KEY2/` (`KEY2-DIAG-03.md`, `KEY2-BUILD-04.md`), `Docs/Migration/etat/BOSS/COMMUN-21-TESTS.md`, `COMMUN-21-BILAN.md` | Lot KEY2 (KEY2-IMPL-03, suite de CHG-378) : une touche déjà liée à une autre action n'est plus retirée d'office à la capture. Le premier appui avertit sur la ligne d'état du menu Clavier (« <touche> is used by <action>. Press it again to replace, Escape to cancel. ») et n'écrit rien ; un second appui de la même touche remplace comme avant (« <touche> saved. Removed from: <action>. ») ; Échap annule (« Capture cancelled. ») ; une touche tenue (répétition) ne compte pas comme second appui (`!Event.IsRepeat()`). Une autre liaison de la même action, ou du même sens du même axe, ne compte pas comme conflit. Décision de l'utilisateur sur `KEY2-DIAG-03.md` (option 1), citée par Big Boss : « 1 ». Changement : `FLiveKeyboard` gagne la touche en attente (`ConfirmKey` et ses modificateurs) ; `CommitKey` cherche le conflit avant toute écriture ; `BeginWait` et `CancelWait` oublient la touche en attente. En-tête, `DefaultInput.ini`, `LPKeyboard.ini` et migration non touchés. **Preuves** : compilations éditeur (30 s) et Development `-NoUBA` (49 s) code 0, 0 erreur, 0 avertissement nouveau (`KEY2-BUILD-04.md`) ; **essai COMMUN-21** (build Development `COM21`, `COMMUN-21-BILAN.md`) : cas .7 à .11 **PASS** (utilisateur, captures 18 à 22, 19:28 à 19:30) : avertissement sans écriture, Échap, second appui (« Num 7 saved. Removed from: Favorite 7. »), Reset (« Original keys restored, AZERTY layout kept. »), touche tenue sans remplacement ; journal du jeu : `Clavier : 51 actions` (17:28:35 UTC) puis **50** (17:29:20) puis **51** (17:29:57) comme attendu. **Non prouvé** : le nombre d'actions relues à une relance après le Reset (aucune relance) | `LPKeyboardSubsystem.cpp` `0eb6a592` (1 491 lignes) → `611c2148` (1 537 lignes, +47 −1, CRLF gardé) | `Tools\Restore.ps1 -Lot KEY2-IMPL4` (remet le fichier depuis `D:\Game\LifePlay_Backup_5.5\KEY2-IMPL4`, simulation d'abord avec `-WhatIf`) ; ou `git revert` du commit du ticket KEY2 par le gardien ; puis recompiler |
|
||||
| CHG-381 | 2026-10-20 | FIX1 (F6, ERR-042) | Jeu (`ue5.8`) : `Plugins/ModdingExtra/Source/ModdingExtra/Private/ModdingExtraBPLibrary.cpp` ; livrables `Docs/Migration/etat/REL/FIX1/` (`FIX1-F6-PRE.md`, `FIX1-F6-SPEC.md`, `FIX1-F6-IMPL.md`, `FIX1-F6-VAL.md`, deux résumés de build `FIX1_Build_…` et deux journaux `FIX1-VAL_BuildLog_…`), `Docs/Migration/etat/BOSS/COMMUN-21-TESTS.md`, `COMMUN-21-BILAN.md` | Lot FIX1 (F6, ERR-042) : les fichiers de partie `Saves/…` (personnages `.lpcharacter`) étaient lus et écrits sous `<jeu>\Content\Saves`, hors du dossier de sauvegarde. Ordre de l'utilisateur, cité par la fiche d'IMPL : « Oui, les 7 recommandations de FIX1-F6-SPEC (Q1 à Q7) ; lance l'IMPL. ». **Décisions Q1 à Q7** (`FIX1-F6-SPEC.md` § 8) : Q1 racine `<Saved>\Saves\…`, chemin relatif `Saves/…` gardé tel quel ; Q2 guides de modding corrigés en DOC du lot si la porte J4 passe ; Q3 porte J4 : V1-V6 et E1-E8 ; Q4 témoin en catégorie `LogModdingExtra` ; Q5 interrupteur `-LPNoSavesRedirect` ; Q6 repli de lecture permanent en build 1, réexaminé en build 2 ; Q7 message de GI corrigé en build 2. **Changement** (un seul fichier, une voie C++, 0 Blueprint) : espace de noms `LPSavesRedirect` ; dans `LoadTxt` et `SaveTxt`, les chemins commençant par `Saves/` sont résolus vers `ProjectSavedDir()/Saves` ; en lecture, repli **par slot** sur l'ancien `Content/Saves` si le slot n'existe que là ; `_session` sans repli ; écriture toujours dans la nouvelle racine ; `-LPNoSavesRedirect` rétablit l'ancien chemin ; avertissement si une liste (`GetAllFilesFromFolder`, `GetAllSubfolders`) vise `Saves` ; témoins `Saves redirige : racine …`, `Saves slot '<Slot>' : …` et ligne `Saves : n lecture(s) nouvelle racine ...` au bilan de `LoadTxt`. **Preuves** : VAL `FIX1-F6-VAL.md` **PASS-STATIC avec réserves** (V1 à V6 conformes, diff +120 −2, deux compilations à 0 erreur) ; **essai COMMUN-21** (`COMMUN-21-BILAN.md`) : cas .1 à .3 et .6 **PASS** (utilisateur, « 1,23, ok », 19:26), journal du jeu : racine `…/Saved/Saves` annoncée une fois par lancement, bilans 4/0/4, 4/0/0 et 8/0/4 (nouvelle racine, repli, écritures), 0 ligne de repli, 0 `FIX1-F6` ; relevé des dossiers : 3 fichiers sous `Saved\Saves` (`1`, `Default`, `_session`), `Content\Saves` absent ; **porte J4 franchie le 2026-10-20**. **Non prouvé en jeu** (réserves 1 à 3 de la VAL, reportées en build 2) : le repli de lecture (cas .4 sans objet, aucune ancienne partie), l'interrupteur (cas .5 non joué), E9 sur le Shipping, la concurrence, `..` dans un chemin, les cas limites de `Saves/` ; le message de GI reste à corriger en build 2 | `ModdingExtraBPLibrary.cpp` `7628837e` → `1f93601c` (+120 −2, LF) | `Tools\Restore.ps1 -Lot FIX1` (remet le fichier depuis `D:\Game\LifePlay_Backup_5.5\FIX1`, simulation d'abord avec `-WhatIf`, puis recompiler) ; ou `git revert` du commit du ticket FIX1 par le gardien ; à chaud : lancer le jeu avec `-LPNoSavesRedirect` ; les parties écrites dans `Saved\Saves` pendant l'essai se déplacent vers `D:\Game\LifePlay_Backup_5.5\FIX1` (jamais supprimer) |
|
||||
| CHG-380 | 2026-10-20 | DISC1 | Jeu (`ue5.8`) : `Content/UI/MainMenu.uasset` ; spécification `Tools/ui/MainMenu_Discord_20261020.json` (outil local, non suivi par git) ; livrables `Docs/Migration/etat/REL/DISC1/` (`DISC1-B1.md` et deux résumés `DISC1_LPEditWidget_20261020-163515.txt`, `DISC1_LPEditWidget_20261020-163636.txt`), `Docs/Migration/etat/BOSS/COMMUN-20-BILAN.md` | Lot DISC1 (DISC1-B1) : le bouton Discord du menu principal ouvre `https://discord.gg/TsKJw3Wvja` au lieu de `https://discord.gg/q4689pNSy`. Ordre de l'utilisateur, cité : « modifies le lien discord par la nouvelle invitation TsKJw3Wvja l'autre va bientôt expiré », puis, pour borner le périmètre : « non le discord du jeu » (seul le lien du menu principal du jeu change ; devlog et docs historiques laissés tels quels, `BOSS-JOURNAL.md` l. 960 et 962). Écrit par la commandlet `LPEditWidget` avec la spécification `MainMenu_Discord_20261020.json` (nœud `K2Node_CallFunction_32` de l'`EventGraph`, propriété `URL`, valeur attendue contrôlée), sous instantané `DISC1` pris par Big Boss : essai à blanc (`-DryRun`) code 0 en 57 s, écriture réelle code 0 en 61 s, 0 erreur, 1 modification, « compile sans erreur », aucune compilation C++. **Preuves** : recherche binaire dans `MainMenu.uasset` : `TsKJw3Wvja` 2 occurrences, `q4689pNSy` 0 (`DISC1-B1.md`) ; essai COMMUN-20 (build Development `COM20`, `COMMUN-20-BILAN.md`) : cas .9 **PASS**, « 9ok » (utilisateur, 17:14), et le journal du jeu porte `LogWindows: LaunchURL https://discord.gg/TsKJw3Wvja` (17:12:56 locale) ; l'ancienne adresse : 0 occurrence dans les deux journaux. **Non fait** : aucune lecture de l'asset ouvert dans l'éditeur ; la page ouverte dans le navigateur n'est pas contrôlée (l'utilisateur ne devait pas rejoindre le serveur) | `MainMenu.uasset` `7292c6be` (2 260 418 octets) → `2815910e` (2 245 771 octets) ; la spécification JSON est neuve (— → créée, hors dépôt) ; aucun autre asset ni source touché | `Tools\Restore.ps1 -Lot DISC1` (remet `Content/UI/MainMenu.uasset` depuis `D:\Game\LifePlay_Backup_5.5\DISC1`, éditeur fermé ; simulation d'abord avec `-WhatIf`) ; ou `git revert` du commit du ticket DISC1 par le gardien ; la spécification JSON se déplace vers `D:\Game\LifePlay_Backup_5.5\DISC1` (jamais supprimer) |
|
||||
| CHG-379 | 2026-10-20 | STM1 (O3 liste, O2 masque d'eau) | Jeu (`ue5.8`) : `Source/LifePlay/LPCityWaterMask.h` (neuf), `Source/LifePlay/LPCityWaterSubsystem.h`, `.cpp`, `Source/LifePlayEditorTools/LPBuildCityWaterCommandlet.cpp` ; asset hors git `Content/Heavy/StreetMap/Water/CentralLondon_Mask.uasset` (neuf) ; livrables `Docs/Migration/etat/REL/STM1/` (`STM1-SPEC-04.md`, `STM1-O3-LISTE.md`, `STM1-O3-BRUT.md`, `STM1-O3-DRYRUN.md`, `STM1-SPEC-08.md`, `STM1-B6-FIN.md`), `Docs/Migration/etat/BOSS/COMMUN-20-BILAN.md` | Lot STM1 (SPEC-04, suite de CHG-372) : des maisons génériques posées sur la Tamise en mode par défaut. Ordre de l'utilisateur, cité : « Oui, O2 avec un seuil de 1 500 m², en faisant d'abord la liste O3 des bâtiments dans l'eau pour vérifier le seuil. » **O3** : option `-ListBuildingsInWater=<f.md>` (et `-ThresholdM2`) du commandlet `LPBuildCityWater`, exécutée en `-DryRun` : 59 bâtiments sur 49 425 ont leur centre dans l'eau (même recalage, mêmes polygones que l'asset d'eau, centre = celui de `MapMarkers`). Le contrôle du seuil a **échoué** (un bâtiment notable sous 1 500 m², un navire au-dessus) : arrêt avant O2 et décision laissée à l'utilisateur, qui a répondu : « option D » (tout masquer, sans seuil). **O2 option D** (`STM1-SPEC-08.md`) : classe de données `ULPCityWaterMask : UDataAsset` (centres de boîte dans le repère de la carte, en cm, et aires) ; option `-MaskOnly` du commandlet qui écrit `Water/CentralLondon_Mask` (59 centres, garde contre l'écrasement, maillage d'eau ni relu ni réécrit) ; `ULPCityWaterSubsystem` : à chaque changement de carte puis à chaque changement du nombre d'instances, les instances de maisons (maillage commençant par `House` ou `Skyscraper`) des `MapMarkers` dont le centre est à 50 cm ou moins d'un centre du masque sont mises à l'échelle 0 (`UpdateInstanceTransform`, indices conservés) ; arbres et jeeps non touchés ; constantes `SpareAboveAreaM2 = 0`, `MatchToleranceCm = 50` ; témoin `[LPCity] EAU <Ville> : masque n centres ; instances maisons N ; masquees m ; epargnees k (seuil s m2) ; centres sans instance c`. Aucun Blueprint, GI, `MapMarkers`, carte ni `Water/CentralLondon` modifié. **Preuves** : O3 build éditeur code 0 (61 s), `-DryRun` code 0 (29 s) ; O2 build éditeur code 0 (52 s) et Development code 0 (53 s), 0 erreur, seul avertissement C4701 `Aim` antérieur (CAM2), `-MaskOnly -DryRun` puis `-MaskOnly` code 0 (21 s), « 59 centres sur 49425 batiments » ; assets de l'eau inchangés (`CentralLondon` `5BDF4F0A`, `M_LP_Water` `D413292C`). **Essai COMMUN-20** (build Development `COM20`, `COMMUN-20-BILAN.md`) : cas .6 **PASS** (« 6 oui »), cas .8 **PASS** (« 8 oui », Bath inchangée), cas .7 **PASS au journal** du jeu (15:11:16 UTC) : `masque 59 centres ; instances maisons 49417 ; masquees 59 ; epargnees 0 ; centres sans instance 0`. **Non résolu** : un second passage, 34 s plus tard (15:11:50 UTC), voit 0 instance (`centres sans instance 59`) après le rechoix de la même ville au sélecteur (aucune nouvelle ligne `POSE` de cette ville) ; le masque n'est pas en cause (`BOSS-JOURNAL.md` l. 970), parade à programmer par STM1 | `LPCityWaterMask.h` — → `966DC14D` (34 lignes, LF) ; `LPCityWaterSubsystem.h` `DEB58EC1` → `2CDC1001` (72 lignes) ; `LPCityWaterSubsystem.cpp` `EC0946C5` → `9C0B257E` (323 lignes) ; `LPBuildCityWaterCommandlet.cpp` `69746A35` → `C5709BDD` (O3, 688 lignes) → `FA6FBB72` (O2, 731 lignes, LF, 0 CR) ; `CentralLondon_Mask.uasset` — → `F6F684B2` (2 712 octets) ; assets de l'eau, GI, `MapMarkers` et cartes inchangés | `Tools\Restore.ps1 -Lot STM1-O2` (remet les trois sources à l'état d'avant O2, dont le commandlet à `C5709BDD`), puis `-Lot STM1-O3` pour le commandlet d'avant O3 (`69746A35`) ; déplacer `Source/LifePlay/LPCityWaterMask.h` et `Content/Heavy/StreetMap/Water/CentralLondon_Mask.uasset` vers `D:\Game\LifePlay_Backup_5.5\STM1-O2` (jamais supprimer ; le masque est cuit avec `/Game`, et le `.h` neuf doit partir avec le `.cpp` qui l'inclut) ; ou `git revert` du commit du ticket STM1 par le gardien pour le code |
|
||||
| CHG-378 | 2026-10-20 | KEY2 | Jeu (`ue5.8`) : `Source/LifePlay/LPKeyboardSubsystem.cpp` ; livrables `Docs/Migration/etat/REL/KEY2/` (`KEY2-SPEC-02.md`, `KEY2-TACHES.md`, `KEY2-BUILD-03.md`, `KEY2-VAL-04.md`), `Docs/Migration/etat/BOSS/COMMUN-20-TESTS.md`, `COMMUN-20-BILAN.md` | Lot KEY2 (KEY2-IMPL-02, suite de CHG-376) : regroupement du menu Clavier par fonctionnalité, en **9 sections** dans l'ordre Movement, Camera, Map & World, Couple (scene), Actions & Interaction, Menus, Time, Favorites, System. Demande de l'utilisateur après COMMUN-18.14 : « 14 ok mais il faudrait regroupé les touche par fonctionalité » ; décision, citée : « regroupement des touches ok » (`BOSS-JOURNAL.md` l. 954), avec les recommandations de `KEY2-SPEC-02.md` § 0 : flèches à deux places (« Map Right / Left / Forward / Back » et « Couple Right / Left / Forward / Back », même liaison : changer l'une change l'autre), Pause dans Time, TestScenes dans System, RotateCamera dans Camera, « Move couple with » en tête de Couple (scene), libellés « Camera Height Up / Down (scene) » et « Action Panel (also Alt / middle click) ». **Affichage seul** : `GroupFor` réécrit, champ `Section` ajouté à `FBindRow`, nouvelle fonction `KbArrowLabel`, `Rebuild` trie et dessine par section ; noms internes, `DefaultInput.ini`, `LPKeyboard.ini`, migration (`KbVersion = 2`) et appels de lecture et d'écriture des liaisons non touchés. **Preuves** : compilations éditeur (41 s) et Development `-NoUBA` (80 s) code 0, 0 erreur, seul avertissement C4701 `Aim` antérieur (`KEY2-BUILD-03.md`) ; `KEY2-VAL-04.md` : **PASS-STATIC**, diff lu en entier (+63 −62), aucune action en « Other », 3 réserves non bloquantes (R1 dossier parasite de résumés, déplacé par Big Boss ; R2 code mort des libellés de flèches dans `AxisLabel` ; R3 axe de zoom `ScrollDownUp` sans libellé, hérité) ; **essai COMMUN-20** (build Development `COM20`, `COMMUN-20-BILAN.md`) : cas .1 à .5 **PASS**, « 1 OK 2 oui,3 vérifié, 4 ok, 5 oui » (utilisateur, 17:14), le rendu est vu à l'écran pour la première fois ; journal : 50 actions et 17 axes relus à la relance. **Non prouvé** : l'écart d'une action entre la première écriture du fichier de touches (51) et les suivantes (50), non expliqué ; la persistance de la disposition AZERTY n'est pas tracée au journal | `LPKeyboardSubsystem.cpp` `9d450aaf` (1 490 lignes) → `0eb6a592` (1 491 lignes, +63 −62, CRLF gardé) ; `DefaultInput.ini` inchangé | `Tools\Restore.ps1 -Lot KEY2-IMPL3` (remet `LPKeyboardSubsystem.cpp` à `9d450aaf` depuis `D:\Game\LifePlay_Backup_5.5\KEY2-IMPL3`) ; ou `git revert` du commit du ticket KEY2 par le gardien |
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ Consignes permanentes :
|
|||
## Dépôts
|
||||
|
||||
- **Jeu** `D:\Game\LifePlay-master 5.8` (`ue5.8`) :
|
||||
- HEAD : `e411b70` avant la vague 9 (vague 8, 2026-10-20, Vague.ps1 ; 542ee7f, 018dd4e, 9a68cf5, 5997880, e411b70) ;
|
||||
- HEAD : `0536487` (vague 12, 2026-10-21, Vague.ps1 ; b207e29, 56fe4d6, 0536487 ; vague 11 : 3b32c5d) ;
|
||||
- tag local **`v2026.10.2.1a`** sur `2f5d51b` (non poussé) ;
|
||||
- **publié** : `pub/ue5.8` `8084622` (un commit sur `origin/main` `d4d9726`) poussé par l'utilisateur vers `origin/ue5.8`
|
||||
le 2026-10-20. `origin` = Forgejo auto-hébergé (`forgejo.edujiro5972.fr`), destination voulue (utilisateur, 2026-10-20 :
|
||||
|
|
@ -67,10 +67,10 @@ Consignes permanentes :
|
|||
|
||||
## Copie UE et jeton
|
||||
|
||||
- **Jeton UE : libre** (BUILD-COM20 rendue 2026-10-20 17:04). Essai COMMUN-20 à l'utilisateur ; push des vagues 7 et 8 en attente.
|
||||
- **Jeton UE : libre** (REL2-T2-BUILD fini le 2026-10-21 08:52, UeState 0). Tout commité jusqu'à 3b32c5d (vague 11). Build 1 : reste REL2 (rejouer COMMUN-23.4, écran titre). Publication du 2026-10-20 : origin/ue5.8 = 56dfcfc (vagues 10-11 non publiées).
|
||||
- **Build Development commune** (décision de l'utilisateur, 2026-10-20 04:30) : générée une fois toutes les opérations en cours finies (CG2, trace STM1-SPEC-01, …) ; elle porte la trace StreetMap pour l'essai de l'utilisateur.
|
||||
- ~~À faire après la BUILD-FIN de CG2~~ **fait le 2026-10-20 08:20** : déplacé `Plugins\McpAutomationBridge` (2,1 Go, non suivi, désactivé) vers `LifePlay_Backup_5.5\MCPAB-20261020\`, CopieEtat avant et après. Aucun build ni essai en cours. Réserve « mesure » : aucune.
|
||||
- **Jeton du journal : libre** (DOC-20261020-VERS3 fini 2026-10-20 17:26 : CHG-378, 379, 380 versés, non commités).
|
||||
- **Jeton du journal : libre** (DOC-20261021-VERS6 fini 2026-10-21 00:16 : CHG-386 versé, commité en vague 12).
|
||||
- Réservations de fichiers partagés : aucune (UES1 levée à sa FIN-LOT, commits `b25c253` addon, `f21061b` jeu, CHG-366). Gels : aucun. Les gels du doc 35 et d'EVAL2 sont levés depuis le commit `08d222f`.
|
||||
- Assets à HEAD : Room `93138747`, PC `707220a6`, GI `32fc0a97`, Person `8668a47c`, TopRight `cb835360`.
|
||||
- C++ : CameraMode `1f10631f`/`9aee8d04`, ShowCouple `3cdd572d`/`44c721ee`, DirectControl `5f9d7e00`/`01d5ea3c`, OutdoorRoom `dc68ed8a`/`6a3edd73`, Debug `f0081f9f`/`78d3a079`, SaveRelaunch `a0cd6687`/`f31173f6`, BonusReward `16147626`/`87177c7a`, LifePlay.cpp `3f7ffa30`, LPModGuard (REL-ALPHA, CHG-349). Version `2026.10.2.1a`.
|
||||
|
|
@ -101,6 +101,21 @@ Consignes permanentes :
|
|||
- référence « avant » : `AMEL1-MESURE-P3.md`.
|
||||
- **R4** : `lp-mcp-bp` en Sonnet, essai ORGA2 après le **2026-10-18**.
|
||||
|
||||
## REPRISE du 2026-10-21 (préparée le 2026-10-21 00:04 par Big Boss `local_104ff22d`)
|
||||
|
||||
**Où on en est.** HEAD jeu `0536487` (vague 12, faite le 2026-10-21 00:17 : tout est commité) ; publié : origin/ue5.8 = `56dfcfc` (vagues 7 à 9 ; vagues 10 à 12 **non publiées**). Jeton UE **libre**, jeton du journal **libre**, aucun processus UE. Builds à 0 avertissement.
|
||||
Rien de non commité (hors fichiers locaux : LifePlay.uproject, LP-PROJET.ini, ORGA2).
|
||||
|
||||
**Build 1 (alpha 2026.10.2.2a, gel le 24 octobre)** : développement fini (F1 partiel, F2, F3, F6, F8, K1-K6, SET1, M-Z talons, QPERS). Reste **REL2** : VAL commune, build Shipping 2026.10.2.2a (y compris E9 de F6 : sauvegardes sous `%LOCALAPPDATA%\LifePlay-Revival`), essai final avec **COMMUN-23.4 à rejouer** (Settings depuis l'écran titre après un retour de partie : ligne « onglets poses … (ecran titre) » absente), dernière vague, publication des vagues 10 à 12, décision de tag.
|
||||
|
||||
**Build 2 ouverte le 2026-10-20**, en attente de l'utilisateur :
|
||||
1. **ERR-145** (`etat\REL\ERR145\ERR145-DIAG.md`) : **H1 confirmée par l'utilisateur le 2026-10-21 07:11** (essai de départage sur COM23, capture 33 : corps assis vu de dessus, sans tête). En cours : SPEC (`ERR145-SPEC`), puis IMPL de l'option A (C++, `LPCameraModeSubsystem.cpp`, AlwaysTickPoseAndRefreshBones en C1, environ 20 lignes ; couvre aussi ERR-106 et ERR-111). Si H2, autre piste (tangage).
|
||||
2. **Révision unique de GI** (`etat\REL\GIREV\GIREV-PRE.md`) : réponses de l'utilisateur le 2026-10-21 07:21 : GQ2 correction (M8) ; GQ6 F7a hors révision ; GQ7 une sauvegarde par sous-lot ; GQ8 C8, Q7, Q8, R7 vers CharGen et Y/N vers PC ; GQ9 liste au doc 37 § 2.7. **Tranché le 2026-10-21 08:10** : GQ1 supprimer la garde D2 ; GQ4 voie V3 (GIREV-MCP-01 § B.5) ; D8 = B1 + B2 (traces et cheveux), dans la révision (GIREV-D8-RECH) ; DQ5 oui (règle écrite dans le guide de moddage). GQ5 tranchée à 07:28 : corriger D10, vérifier n° 32, supprimer D1, D12 et les lignes r.SSS.* / r.DynamicRes.* (si le dump confirme), D8 inchangé ; GQ3 tranchée à 07:21 : D17 fermé, M6 retiré. Ensuite : dumps 5.8 (SavePreset, GenerateAndApply*, CalculateHeadtrack), SPEC GIREV (N3, lp-mcp-bp), révision après la publication de la build 1.
|
||||
3. Autres reports build 2 : voir « Reports en build 2 » ci-dessous.
|
||||
|
||||
**Gestes et rappels.** Le PowerShell 7.6.6 de l'utilisateur plante au démarrage (avis de mise à jour) : lancer le jeu pour lui par Bash en arrière-plan, ou donner la forme `cmd` ; correctif proposé : `setx POWERSHELL_UPDATECHECK Off`. Claude in Chrome (Edge) a fonctionné le 2026-10-20 au second essai. `SauverTranscriptions.ps1 -Session` ne trouve plus les métadonnées : utiliser `-Tout` (à verser par VAG1).
|
||||
**Sessions actives** : Medium · KEY2 (`local_3df0f077`), Medium · STM1 (`local_232546c8`, au repos), Sonnet · VAG1 (`local_345cbd76`, versements aux skills en retard). Archivées le 2026-10-20 : CAM3, KEY1, CAM2, CG2.
|
||||
|
||||
## PASSATION avant redémarrage (2026-10-20 vers 05:45, Big Boss `local_4c0c1de7`, renommée « Big Boss »)
|
||||
|
||||
Feuille de route : `Docs\37_Feuille_De_Route_Alpha2.md` (build 1 = 2026.10.2.2a vers le 24 octobre, build 2 = 2026.11.3.1a vers le
|
||||
|
|
@ -140,7 +155,9 @@ connus), CG2 Q1-Q6, QG1 Q7, CopieEtat pour GO/FIN, K2-K6 tout en build 1, post P
|
|||
ordre « lance KEY1 » dans la session KEY1 ; archivage de Low · MEN1 et Medium-High après `SauverTranscriptions.ps1` ;
|
||||
CG2 Q7 et Q8 (build 2).
|
||||
|
||||
**Reports en build 2 (doc 37 § 2.7, à verser)** : C8, C10, C11, D2, D9, D17, Q7, Q8, ERR-142, R7, ERR-145, remappage de Y/N, branche « pièce cachée » de CAM2 ; décidé le 2026-10-20 : chaîne des packs de villes (STM1-SPEC-07 : outil de téléchargement, pack Paris 3 × 3 km gratuit) et déploiement du serveur Forgejo (Caddy, citypacks, lp-osmium, mot de passe de la base). Jeu de base : Londres et Bath. Monétisation : build 3. En attente : KEY2-SPEC-02 (4 questions), push des vagues 7 et 8.
|
||||
**Reports en build 2 (doc 37 § 2.7, à verser)** : C8, C10, C11, D2, D9, D17, Q7, Q8, ERR-142, R7, ERR-145, remappage de Y/N, F7a (CenterBrow), F7c (accessoires), F8b (lévitation de PNJ : HeelHeight surestimé selon la chaussure, audit des données), F7b (posture après « regarder », passagère ; currentAnimation jamais effacé au lever), lot QPERS-ASSETS (qualité des personnages : peau en Subsurface Profile avec SSP_Girl_Head, ombres de contact sur les lumières des pièces ; essai console du 2026-10-20 : seul Sharpen utile, gravé), piste Fab PRISMIX Diagnostics (profileur UE 5.8, déjà dans la bibliothèque ; essai éventuel dans l'addon, comparé au CSV Profiler), branche « pièce cachée » de CAM2 ; décidé le 2026-10-20 : chaîne des packs de villes (STM1-SPEC-07 : outil de téléchargement, pack Paris 3 × 3 km gratuit) et déploiement du serveur Forgejo (Caddy, citypacks, lp-osmium, mot de passe de la base). Jeu de base : Londres et Bath. Monétisation : build 3. En attente : KEY2-SPEC-02 (4 questions), publication faite (56dfcfc).
|
||||
|
||||
**Horizon builds 6-7 (décidé le 2026-10-20)** : PNJ conversationnel par petit LLM local (pistes : Qwen3 1.7B / 4B ou SmolLM3 3B, Apache 2.0 ; llama.cpp, MIT ; modèle en pack optionnel ; Gemma et Llama écartés pour leurs licences). Préalables : définir l'interconnexion jeu ↔ modèle (état de scène, personnalité, intentions permises, sortie contrainte, repli scripté) et dépasser les limites actuelles du jeu (dialogues et actions figés) ; s'appuie sur l'interaction filtrée de la build 2 (§ 2.5).
|
||||
|
||||
**Leçon** : les sessions de lot ne reconnaissent pas toujours un message d'une session Big Boss dont l'id n'est pas dans
|
||||
BOSS-ETAT : à la reprise, la nouvelle session Big Boss s'annonce à chaque session avec son id, ou l'utilisateur confirme.
|
||||
|
|
|
|||
|
|
@ -970,3 +970,133 @@ Demandes annoncées, pas encore déposées (toutes attendent la clôture de STC)
|
|||
| 2026-10-20 17:20 | STM1 / Big Boss | Constat S5 (LifePlay.log COM20) : CityMenu rouvert et Central London rechoisi a 15:11:44 ; MapMarkers vide ses maisons (0 a 15:11:50) et ne les recree pas avant Bath ; masque non en cause ; risque : recreation au meme nombre dans 0,25 s, la passe ne se relance pas ; parade proposee (relancer si une instance visee a une echelle non nulle) | **accepte** ; parade et comparaison 5.5 (rechoix de la meme ville = 0 maison ?) notees en suite STM1, a programmer ; question posee a l utilisateur | `etat\REL\STM1\STM1-TACHES.md` |
|
||||
| 2026-10-20 17:26 | lp-writer / Big Boss | DOC-20261020-VERS3 + COMMUN-20-BILAN : bilan 12/12 PASS (.7 et .9 prouves au journal ; .12 fleches sur parole ; 50 actions relues au lieu de 51, a suivre par KEY2) ; CHG-378, 379, 380 au journal (LF, +3) ; NUMEROS 3 lignes « utilise » (CRLF 159 inchange) | **accepte** (MD5 et comptes relus) ; **jeton du journal libre** ; vague 9 deposee : KEY2-T5, STM1-T5, DISC1-T1, COMMUN20-T1, PARTAGES | `Docs\Journal_Modifications.md` |
|
||||
| 2026-10-20 17:27 | Big Boss | Vague 9 : PubCheck 0 sur chaque fichier des 5 tickets ; Vague.ps1 -Essai : 5 essai-OK | execution lancee (ordre « prépare et lance la vague 9 ») | `etat\REPO\FILE.md` |
|
||||
| 2026-10-20 17:28 | Big Boss | Vague 9 executee (code 0) : 2357225 KEY2-T5 (5), 91ad15e STM1-T5 (12), d15ffaa DISC1-T1 (2), 09b42cc COMMUN20-T1 (3), b5feae4 PARTAGES (11) | **contre-verifiee** (noreply, trailer, nombre de fichiers = tickets, PubCheck -Arbre ue5.8 = 0, arbre propre hors fichiers locaux) ; FILE videe ; HEAD jeu b5feae4 ; aucun push | `etat\REPO\FILE.md` |
|
||||
| 2026-10-20 17:29 | utilisateur / Big Boss | « je n ai rien constaté sur la disparition des maisons » | S5 (0 instance apres rechoix de la meme ville) sans effet visible : suite STM1 build 2, priorite basse (parade puis comparaison 5.5) ; DIAG KEY2 demande (50 actions relues au lieu de 51, lecture seule) | `etat\BOSS\COMMUN-20-BILAN.md` |
|
||||
| 2026-10-20 17:31 | utilisateur / Big Boss | « donnes moi la commande de push » | ue5.8 (b5feae4) n est pas fille d origin/ue5.8 (8084622, commit d arbre publie) : un push direct serait refuse ; procedure REP1-T4 / PUB3 § 7 : nouveau commit d arbre sur pub/ue5.8 (parent 8084622) par lp-gardien apres controle de contenu ; VAL PUB-20261020-VAL lancee (lp-validator) | `etat\REPO ickets\REP1-T4.md` |
|
||||
| 2026-10-20 17:33 | KEY2 / Big Boss | KEY2-DIAG-03 : action perdue = Favorite7 sur pave 7, retiree par la regle de conflit de CommitKey (l. 973) au cas .3, jamais rendue ; options (1) confirmation avant remplacement (recommande, environ 25 lignes), (2) echange, (3) documenter | **acceptee** ; choix soumis a l utilisateur ; parade joueur : Reset puis Apply AZERTY | `etat\REL\KEY2\KEY2-DIAG-03.md` |
|
||||
| 2026-10-20 17:33 | lp-validator / Big Boss | PUB-20261020-VAL : **PASS** (PubCheck -Arbre ue5.8 -Binaires 0 ; aucun contenu explicite nouveau ; aucun secret ; fichiers locaux hors arbre ; 6 uasset modifies, 0 ajoute) ; reserve : nom d hote forgejo.edujiro5972.fr nouveau dans l arbre (6 lignes, BOSS-ETAT, BOSS-JOURNAL, REP1-DOC-02) ; precaution : prendre b5feae4^{tree} | **acceptee** ; precaution appliquee par le ticket du gardien ; nom d hote soumis a l utilisateur | `etat\REPO\PUB\PUB-20261020-VAL.md` |
|
||||
| 2026-10-20 17:34 | utilisateur / Big Boss | « On garde le nom forgejo.edujiro5972.fr dans la publication ; prépare pub/ue5.8. » | ticket PUB-20261020-T1 (BRANCHE : commit d arbre b5feae4^{tree}, parent 8084622, ref locale pub/ue5.8) remis a lp-gardien ; aucun push | `etat\REPO ickets\PUB-20261020-T1.md` |
|
||||
| 2026-10-20 17:36 | lp-gardien / Big Boss | PUB-20261020-T1 fait : pub/ue5.8 = 56dfcfc (commit-tree b5feae4^{tree}, parent 8084622, noreply) ; diff vide, 1 commit d avance, pre-push simule : pub/ue5.8 passe, ue5.8 refuse ; PubCheck -Arbre et -Pointe = 0 ; aucun push | **contre-verifie** (refs, auteur, arbre identique, 1 commit) ; commande de push donnee a l utilisateur ; ticket et ligne REPO-JOURNAL a commiter en PARTAGES de la prochaine vague | `etat\REPO ickets\PUB-20261020-T1.md` |
|
||||
| 2026-10-20 17:38 | utilisateur / Big Boss | push par l utilisateur : dry-run puis « git push origin pub/ue5.8:ue5.8 » : PubCheck 0, 8084622..56dfcfc pub/ue5.8 -> ue5.8 (247 objets, 1,43 Mio) | **publie** ; origin/ue5.8 relu apres fetch | `etat\REPO ickets\PUB-20261020-T1.md` |
|
||||
| 2026-10-20 17:38 | utilisateur / Big Boss | « 1 » (KEY2-DIAG-03 : touche deja prise) | **decide** : option 1, confirmation avant remplacement ; **GO KEY2-IMPL-03** et **jeton UE a KEY2** (compilation) | `etat\REL\KEY2\KEY2-DIAG-03.md` |
|
||||
| 2026-10-20 17:42 | KEY2 / Big Boss | BUILD-FIN KEY2-IMPL-03 / KEY2-BUILD-04 : confirmation par second appui ; LPKeyboardSubsystem.cpp 0eb6a592 -> 611c2148, CRLF ; editeur et Development code 0, 0 avertissement ; exe 181dc8e6 ; jeton rendu | **acceptee** (MD5, journaux, UeState relus) ; **jeton UE libre** ; preuve en jeu a la prochaine build d essai ; FIX1 propose a l utilisateur | `etat\REL\KEY2\KEY2-BUILD-04.md` |
|
||||
| 2026-10-20 17:43 | utilisateur / Big Boss | « lances F6, demande une étude préliminaire pour savoir quel model affecté à la tache. quels sont les agents à archiver? » | lot FIX1 ouvert pour F6 seul (ERR-042, personnages de partie dans Content\Saves) ; etude preliminaire FIX1-F6-PRE (lp-cart, lecture seule) : etat de SAV1 / REL-SAV, points d ecriture, GI touche ou non, agent et modele recommandes, build 1 ou 2 ; liste des sessions a archiver remise a l utilisateur | `etat\REL\FIX1\` |
|
||||
| 2026-10-20 17:44 | utilisateur / Big Boss | « Oui, archive CAM3, KEY1, CAM2 et CG2 après copie des transcriptions ; garde STM1, KEY2 et VAG1. » | SauverTranscriptions -Session : metadonnees introuvables (chemin de l application change ?) ; repli -Tout : 345 fichiers copies (401 Mo), 0 avertissement, vers Backup_5.5\TRANSCRIPTIONS\complet ; **archivees** : Sonnet · CAM3, Lower · KEY1, Medium-High · CAM2, Medium-xHigh · CG2 (session fille, archivee avec CAM2) ; gardees : STM1, KEY2, VAG1 ; a verser : chemin des metadonnees de SauverTranscriptions -Session | `D:\Game\LifePlay_Backup_5.5\TRANSCRIPTIONS\complet\` |
|
||||
| 2026-10-20 17:52 | lp-cart / Big Boss | FIX1-F6-PRE : reste d ERR-042 = personnages de partie (Saves/_session, Saves/<Slot>/Characters) ecrits dans Content\Saves via LoadTxt/SaveTxt de ModdingExtra (ProjectContentDir) ; voie C++ (redirection dans ModdingExtraBPLibrary.cpp, 40-80 lignes, 0 BP, GI non touche) ; voie BP ecartee (GI : 29 litteraux) ; lot N3, SPEC opus medium, IMPL lp-impl ; environ 1 j ; build 1 tenable sous porte J4 | **acceptee** (LoadTxt l. 190 et SaveTxt l. 236 relus) ; decision build 1 / build 2 a l utilisateur ; ligne FIX1 du doc 37 a reclasser | `etat\REL\FIX1\FIX1-F6-PRE.md` |
|
||||
| 2026-10-20 17:58 | utilisateur / Big Boss | « F6 en build 1 avec la porte J4 : lance la SPEC (opus, effort medium) sur la voie C++. » | **F6 en build 1, porte J4** (essai concluant au plus tard le 2026-10-23 au soir, sinon build 2) ; SPEC FIX1-F6-SPEC lancee (lp-cart, opus, effort medium) ; IMPL prevue par lp-impl | `etat\REL\FIX1\` |
|
||||
| 2026-10-20 18:05 | lp-cart (opus medium) / Big Boss | FIX1-F6-SPEC : redirection C++ dans ModdingExtraBPLibrary.cpp (MD5 avant 7628837e, LPSavesRedirect::ResolvePath, l. 190 et 236), Saves/... vers ProjectSavedDir()/Saves, repli de lecture par slot, _session sans repli, interrupteur -LPNoSavesRedirect, temoin LogModdingExtra ; aucun BP ni GI ; PubCheck 0 | **acceptee** (MD5 relu) ; Q1-Q7 soumises a l utilisateur | `etat\REL\FIX1\FIX1-F6-SPEC.md` |
|
||||
| 2026-10-20 19:04 | utilisateur / Big Boss | « Oui, les 7 recommandations de FIX1-F6-SPEC (Q1 à Q7) ; lance l IMPL. » | Q1-Q7 decidees ; instantane FIX1 de ModdingExtraBPLibrary.cpp ; IMPL par lp-impl (Sonnet), puis compilation par lp-builder ; **jeton UE a FIX1** | `etat\REL\FIX1\FIX1-F6-SPEC.md` |
|
||||
| 2026-10-20 19:14 | lp-impl / Big Boss | BUILD-FIN FIX1-F6-IMPL : diff de la SPEC applique tel quel (+120 -2), ModdingExtraBPLibrary.cpp 7628837e -> 1f93601c ; editeur et Development code 0, seul C4701 connu ; exe 811f72f2 ; jeton rendu | **acceptee** (MD5, journaux, UeState relus) ; B1 arbitre : les binaires portent aussi KEY2-IMPL-03 (611c2148), les deux seront essayes ensemble en COMMUN-21 ; VAL statique FIX1-F6-VAL lancee (lp-validator) ; **jeton UE libre** | `etat\REL\FIX1\FIX1-F6-IMPL.md` |
|
||||
| 2026-10-20 19:15 | lp-validator / Big Boss | FIX1-F6-VAL : **PASS-STATIC** avec reserves (1 compteurs non proteges, thread de jeu seul ; 2 traversee .. non filtree ; 3 cas limites Saves seul, slot vide, ./Saves) ; diff = SPEC a-g, builds 2 x Succeeded | **acceptee** ; reserves 1-3 acceptees pour la build 1 (meme exposition qu avant la redirection : chemins fournis par les BP), suite en build 2 (normalisation du chemin) ; essai E1-E8 en COMMUN-21 sur ordre | `etat\REL\FIX1\FIX1-F6-VAL.md` |
|
||||
| 2026-10-20 19:16 | utilisateur / Big Boss | « Oui, lance la build Development COMMUN-21 (F6 redirection des sauvegardes, KEY2 confirmation des touches) et prépare le cahier de tests. » | **BUILD-GO BUILD-COM21** (lp-builder, -ArchiveDir COM21) ; jeton UE a BUILD-COM21 ; cahier COMMUN-21 (lp-writer) | — |
|
||||
| 2026-10-20 19:18 | lp-writer / Big Boss | COMMUN-21-TESTS redige (14 cas : F6 .1-.6, KEY2 .7-.11, non-regressions .12-.14 ; commandes PowerShell de releve ; dossier Development = <build>\Windows\LifePlay\Saved\Saves) | contre-verifie (MD5 f7625c9d, PubCheck 0) ; § 1 a completer a la remise de BUILD-COM21 | `etat\BOSS\COMMUN-21-TESTS.md` |
|
||||
| 2026-10-20 19:20 | lp-builder / Big Boss | BUILD-COM21 : Build.ps1 a jour (0 unite), BuildDebug -SkipBuild, UAT code 0 (83 s), CheckPackage PASS, 0 paquet recuit ; exe 811f72f2 = projet (F6 + KEY2) ; pas de Content\Saves livre | **acceptee** ; § 1 de COMMUN-21-TESTS complete ; **jeton UE libre** ; essai donne a l utilisateur | `etat\BOSS\COMMUN-21\COMMUN-21-BUILD.md` |
|
||||
| 2026-10-20 19:25 | utilisateur / Big Boss | COMMUN-21 : releve avant fait (vide, build neuve) ; « pas de maison sur la tamise » | **PASS** .13 | `etat\BOSS\COMMUN-21-TESTS.md` |
|
||||
| 2026-10-20 19:26 | utilisateur / Big Boss | COMMUN-21 : « 1,23, ok » | **PASS** .1-.3, prouves sur disque et au journal : Saved\Saves et Saved\Saves\Default crees, Content\Saves absent ; LogModdingExtra « Saves redirige » puis « 4 lecture(s) nouvelle racine, 0 repli, 4 ecriture(s) » ; avertissement LoadTxt ECHEC OldPlayer.lpcharacter (fichier facultatif absent, a confirmer contre COM20) | `etat\BOSS\COMMUN-21-TESTS.md` |
|
||||
| 2026-10-20 19:26 | utilisateur / Big Boss | COMMUN-21.4 : « 4 pas d ancienne partie » | .4 **sans objet** (aucune ancienne partie dans la build neuve) ; repli de lecture non eprouve en jeu, couvert par la VAL statique ; a rejouer en build 2 ou avec une partie copiee | `etat\BOSS\COMMUN-21-TESTS.md` |
|
||||
| 2026-10-20 19:28 | utilisateur / Big Boss | COMMUN-21.7 : capture du menu Clavier (18.webp) : « Num 7 is used by Favorite 7. Press it again to replace, Escape to cancel. », Map Left garde Left, section Map & World visible | **PASS** .7 (avertissement seul, rien d ecrit) | `etat\BOSS\COMMUN-21-TESTS.md` |
|
||||
| 2026-10-20 19:29 | utilisateur / Big Boss | COMMUN-21.8 : capture (19.webp) : « Capture cancelled. », Map Left garde Left ; disposition passee en AZERTY | **PASS** .8 (Echap annule, rien d ecrit) | `etat\BOSS\COMMUN-21-TESTS.md` |
|
||||
| 2026-10-20 19:29 | utilisateur / Big Boss | COMMUN-21.9 : capture (20.webp) : « Num 7 saved. Removed from: Favorite 7. », Map Left = Num 7 | **PASS** .9 (second appui remplace) | `etat\BOSS\COMMUN-21-TESTS.md` |
|
||||
| 2026-10-20 19:30 | utilisateur / Big Boss | COMMUN-21.10 : capture (21.webp) : « Original keys restored, AZERTY layout kept. », Map Left = Left | **PASS** .10 (Reset rend les touches et garde AZERTY ; compte de 51 actions a confirmer au journal) | `etat\BOSS\COMMUN-21-TESTS.md` |
|
||||
| 2026-10-20 19:30 | utilisateur / Big Boss | COMMUN-21.11 : capture (22.webp) : touche tenue, la ligne d etat reste sur « Num 7 is used by Favorite 7. Press it again… », Map Left = Left | **PASS** .11 (touche tenue ne remplace pas) | `etat\BOSS\COMMUN-21-TESTS.md` |
|
||||
| 2026-10-20 19:31 | utilisateur / Big Boss | COMMUN-21.12 : « 12 ok » | **PASS** .12 (menu Clavier en 9 sections) | `etat\BOSS\COMMUN-21-TESTS.md` |
|
||||
| 2026-10-20 19:35 | utilisateur / Big Boss | COMMUN-21.14 : « cc14 ok » | **PASS** .14 (POV de scene) ; reste le releve apres et le .6 (bilan LoadTxtStats a la fermeture) | `etat\BOSS\COMMUN-21-TESTS.md` |
|
||||
| 2026-10-20 19:36 | utilisateur / Big Boss | PowerShell de l utilisateur plante au demarrage (UpdatesNotification, largeur de fenetre negative : sans lien avec le jeu) ; releve apres fait par Big Boss (jeu encore ouvert) dans Backup_5.5\COM21-apres.txt : 3 fichiers sous Saved\Saves (1, Default, _session), Content\Saves absent | **PASS** .6 (LogModdingExtra : « 4 lecture(s) nouvelle racine | 0 repli | 4 ecriture(s) ») ; essai COMMUN-21 : PASS .1-.3, .6-.14, .4 sans objet, .5 facultatif non joue ; **porte J4 de F6 franchie** (2026-10-20) | `etat\BOSS\COMMUN-21-TESTS.md` |
|
||||
| 2026-10-20 19:37 | utilisateur / Big Boss | « Oui : bilan COMMUN-21, versement des CHG (F6, KEY2-IMPL-03) puis prépare et lance la vague 10. » | CHG-381 (F6), CHG-382 (KEY2-IMPL-03) reserves (verrou 247) ; **jeton du journal a lp-writer** (DOC-20261020-VERS4 : CHG-381, 382, mise a jour d ERR-042) ; bilan COMMUN-21 ; vague 10 ensuite | `etat\REPO\NUMEROS.md` |
|
||||
| 2026-10-20 19:41 | lp-writer / Big Boss | DOC-20261020-VERS4 + COMMUN-21-BILAN : 12 PASS, .4 sans objet, .5 non joue ; CHG-381 et 382 au journal ; ERR-042 corrige (F6) au registre ; NUMEROS CRLF garde | **accepte** (MD5, CRLF, instantanes FIX1 et KEY2-IMPL4 presents) ; **jeton du journal libre** ; vague 10 deposee : FIX1-T1, KEY2-T6, COMMUN21-T1, PARTAGES | `etat\BOSS\COMMUN-21-BILAN.md` |
|
||||
| 2026-10-20 19:43 | Big Boss | Vague 10 -Essai : PARTAGES refuse P6-V5 (Registre_Erreurs : ligne ERR-042 modifiee en place ; le registre n accepte que des ajouts) | **pas de contournement** : modification d ERR-042 mise de cote (copie dans le dossier temporaire de la session), registre retabli a HEAD (c91ac468) ; ERR-042 retire du ticket ; CHG-381 porte la correction ; le marquage du statut d ERR-042 est soumis a l utilisateur ; tickets STM1-T6 et PUB-20261020-T2 ajoutes pour STM1-TACHES et PUB-VAL (refus P5) | `etat\REPO\FILE.md` |
|
||||
| 2026-10-20 19:44 | Big Boss | Vague 10 executee (code 0) : 30681e2 FIX1-T1 (5), c45958d KEY2-T6 (4), e66867b COMMUN21-T1 (3), 2042c99 STM1-T6 (1), 56d1007 PUB-20261020-T2 (1), ad3c9c6 PARTAGES (13) | **contre-verifiee** (noreply, trailer, nombre de fichiers, PubCheck -Arbre ue5.8 = 0) ; FILE videe ; HEAD jeu ad3c9c6 ; aucun push | `etat\REPO\FILE.md` |
|
||||
| 2026-10-20 19:48 | utilisateur / Big Boss | « Option (c) : laisse le registre tel quel, CHG-381 fait foi. » | **decide** : ERR-042 laisse en l etat au registre ; CHG-381 fait foi pour la correction F6 ; copie de la modification abandonnee (dossier temporaire de la session) | `Docs\Journal_Modifications.md` |
|
||||
| 2026-10-20 19:50 | utilisateur / Big Boss | « approuvé » (F7 et F8 : F8 Aim en build 1, etude preliminaire pour F7 et F8 meshZ) | instantane FIX1-F8 de LPCameraModeSubsystem.cpp ; **GO FIX1-F8a** (initialiser Aim, lp-impl, compilation) et **jeton UE a FIX1** ; etude FIX1-F7-PRE (lp-cart, lecture seule) | `etat\REL\FIX1\` |
|
||||
| 2026-10-20 19:51 | utilisateur / Big Boss | « lance une étude sur https://www.fab.com/listings/1c24b8ec-8120-4b80-b253-323ac90c01c2 » | Claude in Chrome : aucun navigateur connecte ; regle fab-par-claude-in-chrome : arret, connexion demandee a l utilisateur (pas de repli sur un autre outil) | — |
|
||||
| 2026-10-20 19:56 | lp-impl / Big Boss | BUILD-FIN FIX1-F8a : Aim initialise a FVector::ZeroVector (l. 2278 et 2369, +2 -2) ; LPCameraModeSubsystem.cpp 4fd44bd4 -> 976bf0a4 ; editeur et Development code 0, **0 avertissement** ; exe b178a8be | **acceptee** (diff lu par Big Boss : 2 lignes, logique inchangee, tient lieu de VAL ; C4701 absent des 2 journaux) ; **jeton UE libre** ; commit a la prochaine vague, essai en jeu du glisser avec la build suivante | `etat\REL\FIX1\FIX1-F8a-IMPL.md` |
|
||||
| 2026-10-20 20:03 | lp-cart / Big Boss | FIX1-F7-PRE : F7a CenterBrow lu dans GI (CalculateHeadtrack) -> build 2 ; F7b look sans mesure depuis COMMUN-8 ; F7c accessoires sans recette ; F8b meshZ deja neutralise en C++ (M-Z), cause possible = hauteur de talons (-90 + 12 x HeelHeight) ; proposition build 1 : seance de mesure -LPPersonsLog=2 sur COM21 et instrumentation de la ligne M-Z | **acceptee** ; choix soumis a l utilisateur ; ligne FIX1 du doc 37 a reclasser | `etat\REL\FIX1\FIX1-F7-PRE.md` |
|
||||
| 2026-10-20 20:04 | utilisateur / Big Boss | « Oui : F7a, F7c et F8b en build 2 ; en build 1, ajoute la hauteur de talons et l animation à la trace M-Z, et prépare la séance de mesure -LPPersonsLog=2. » | **decide** : F7a, F7c, F8b en build 2 ; **GO FIX1-MZ** (trace M-Z enrichie, lp-impl, sous instantane, compilation) ; **jeton UE a FIX1** ; protocole de mesure FIX1-MES (lp-writer) | `etat\REL\FIX1\FIX1-F7-PRE.md` |
|
||||
| 2026-10-20 20:06 | lp-writer / Big Boss | FIX1-MES : protocole de mesure de 20-30 min, 11 cas (F8b MES.1-.6, F7b MES.7-.11), -LPPersonsLog=2 = releve toutes les 2 s ; PubCheck 0 | **accepte** ; 3 champs « a completer » (ligne M-Z enrichie, build COMMUN-22) a remplir apres FIX1-MZ | `etat\REL\FIX1\FIX1-MES.md` |
|
||||
| 2026-10-20 20:08 | utilisateur / Big Boss | « essaies la connexion edge » ; fiche Fab 1c24b8ec lue par Claude in Chrome (lecture seule, onglet ferme) : PRISMIX Diagnostics, profileur de performance UE 5.8 (plugin Windows, PIE / standalone / Development / Shipping, rapports HTML et CSV, sans reseau ni telemetrie), Standard License, publie le 2026-10-20, 0 avis, « Generated with AI : Yes », deja dans la bibliotheque de l utilisateur | etude rendue a l utilisateur ; lien avec build 2 § 2.2 (optimisation, pipeline de mesure) et A4 (B2-ter) ; aucune installation sans accord | — |
|
||||
| 2026-10-20 20:09 | utilisateur / Big Boss | « garde le sous le coude » (PRISMIX Diagnostics) | **mis en reserve** : piste pour la build 2 (§ 2.2 optimisation, A4) ; essai eventuel dans l addon Sandbox, compare au CSV Profiler ; rien d installe | — |
|
||||
| 2026-10-20 20:12 | lp-impl / Big Boss | BUILD-FIN FIX1-MZ : ligne M-Z enrichie (HeelHeight, currentAnimation, -90+12*HeelHeight), lecture par reflexion, correction inchangee ; LPDirectControlSubsystem.cpp 5f9d7e00 -> 687c63d8 (CRLF) ; editeur et Development code 0, 0 avertissement ; exe e2ba7dec | **acceptee** (diff lu par Big Boss : lecture seule, tient lieu de VAL) ; **jeton UE libre** ; build d essai COMMUN-22 (F8a + MZ) pour la seance FIX1-MES sur ordre | `etat\REL\FIX1\FIX1-MZ-IMPL.md` |
|
||||
| 2026-10-20 20:24 | utilisateur / Big Boss | « Oui, lance la build Development COMMUN-22 (F8a, trace M-Z enrichie) et complète le protocole FIX1-MES. » | **BUILD-GO BUILD-COM22** (lp-builder, -ArchiveDir COM22, exe e2ba7dec) ; jeton UE a BUILD-COM22 ; FIX1-MES complete a la remise | — |
|
||||
| 2026-10-20 20:27 | lp-builder / Big Boss | BUILD-COM22 : Build.ps1 a jour, BuildDebug -SkipBuild, UAT code 0 (72 s), CheckPackage PASS ; exe e2ba7dec = projet (F8a + MZ) | **acceptee** ; FIX1-MES complete par Big Boss (build, format M-Z) ; **jeton UE libre** ; seance de mesure donnee a l utilisateur | `etat\BOSS\COMMUN-22\COMMUN-22-BUILD.md` |
|
||||
| 2026-10-20 20:29 | utilisateur / Big Boss | « build 6 ou 7 plutôt. il faut définir l interconnexion et dépasser les limites actuelles du jeu » (PNJ conversationnel par petit LLM local) | **reporte en build 6 ou 7** ; prealables notes : definir l interconnexion (jeu <-> modele : etat de scene, personnalite, intentions permises, sortie contrainte) et depasser les limites actuelles du jeu (dialogues et actions figes) ; pistes retenues : Qwen3 1.7B / 4B ou SmolLM3 3B (Apache 2.0), llama.cpp (MIT), pack optionnel ; Gemma et Llama ecartes (licences) | — |
|
||||
| 2026-10-20 20:37 | utilisateur / Big Boss | PowerShell de l utilisateur plante au demarrage (avis de mise a jour, largeur negative), a repetition | jeu COM22 lance par Big Boss avec -LPPersonsLog=2 (seance FIX1-MES) | `etat\REL\FIX1\FIX1-MES.md` |
|
||||
| 2026-10-20 20:44 | utilisateur / Big Boss | Seance FIX1-MES (COM22) : captures 23-25 (talons debout, assis, leve) ; journal : M-Z ramene le joueur en talons de -80.4 (= -90+12*HeelHeight, HeelHeight=0.8) a -90 ; debout ensuite meshZ=-90 ; capture 25 : semelles cachees, pieds dans le parquet | **F8b etabli** : l ecart releve etait la compensation normale des talons ; la correction C++ M-Z l annule et enfonce les pieds d environ 9,6 cm (regression de M-Z) ; constat annexe F7b : currentAnimation reste fnt_chair11-f-0-sit apres le lever ; correctif propose a l utilisateur : M-Z vise -90+12*HeelHeight au lieu de -90 | `etat\REL\FIX1\FIX1-MES.md` |
|
||||
| 2026-10-20 20:45 | utilisateur / Big Boss | capture 26 : « pnj en lévitation » (PNJ en talons moyens, debout) ; journal : PNJ debout a meshZ -81.6 (HeelHeight 0.7) et -85.2 (0.4), sans ligne M-Z (M-Z ne les a pas touches) ; currentAnimation encore « …-sit » | second effet : la compensation de talons du Blueprint depasse la hauteur reelle de certaines chaussures -> PNJ qui flotte (donnee HeelHeight par chaussure ; anteriorite 5.5 a verifier) ; distinct de la regression M-Z (pieds enfonces) | `etat\REL\FIX1\FIX1-MES.md` |
|
||||
| 2026-10-20 20:48 | utilisateur / Big Boss | FIX1-MES.9 : « 9 un peu penché et tête toutné » (apres l action regarder) | **F7b reproduit** : posture penchee et tete tournee apres la fin de l action ; journal du joueur a relire (currentAnimation) | `etat\REL\FIX1\FIX1-MES.md` |
|
||||
| 2026-10-20 20:49 | utilisateur / Big Boss | FIX1-MES.10 : « 10 oui » (posture normale apres etre sorti et avoir marche) | F7b : posture residuelle apres « regarder », effacee par le deplacement hors du lieu ; effet visible mais passager | `etat\REL\FIX1\FIX1-MES.md` |
|
||||
| 2026-10-20 20:50 | utilisateur / Big Boss | FIX1-MES.11 : « 11 normal je pense » ; seance FIX1-MES close | **constat** : F8b = regression M-Z (pieds en talons enfonces de 12 x HeelHeight, joueur apres lever) + lévitation de PNJ par HeelHeight surestime selon la chaussure (donnees, build 2) ; F7b = posture penchee et tete tournee apres « regarder », non reproduite au 2e essai, effacee par un deplacement ; currentAnimation jamais efface apres le lever (variable non fiable) ; F7b en build 2 ; decision M-Z en build 1 attendue | `etat\REL\FIX1\FIX1-MES.md` |
|
||||
| 2026-10-20 20:51 | utilisateur / Big Boss | « approuvé » (correction de M-Z en build 1) | **GO FIX1-MZ2** : M-Z vise -90+12*HeelHeight (repli -90 si HeelHeight illisible), sous instantane FIX1-MZ2 ; lp-impl ; **jeton UE a FIX1** | `etat\REL\FIX1\` |
|
||||
| 2026-10-20 20:59 | lp-impl / Big Boss | BUILD-FIN FIX1-MZ2 : cible M-Z = -90+12*HeelHeight (declenchement et ecriture ; repli gabarit si illisible ou non fini) ; LPDirectControlSubsystem.cpp 687c63d8 -> 86ef519e ; editeur et Development 0 erreur, 0 avertissement ; exe 963927f3 | **acceptee** (diff lu par Big Boss : +15 -9, logique conforme, tient lieu de VAL ; lecture de HeelHeight a chaque balayage, cout faible) ; **jeton UE libre** ; preuve en jeu (talons au lever) dans la build de REL2 | `etat\REL\FIX1\FIX1-MZ2-IMPL.md` |
|
||||
| 2026-10-20 21:04 | utilisateur / Big Boss | « non je souhaite passer la désactivation de l ancien panneau settings du menu du jeu et le remplacer par celui du menu principal. » (doc 37 § 2.4 avance) | REL2 differe ; lot SET1 ouvert ; etude preliminaire SET1-PRE (lp-cart, lecture seule) : panneaux ancien et nouveau, ecart de reglages, voies, GI touche ou non, build 1 ou 2 | `etat\REL\SET1\` |
|
||||
| 2026-10-20 21:12 | lp-cart / Big Boss | SET1-PRE : un seul panneau de reglages (MainMenu.SettingsScrollBox), MainMenu_C sert d ecran titre et de menu en partie ; LPSettingsSubsystem le met en onglets sans BP ; hypothese H1 : en partie, les onglets peuvent manquer (Tick prend la premiere SettingsScrollBox) ; voies V0 essai en jeu, V1 correctif C++ (15-40 l.), V2 reecriture (build 2) | **acceptee** ; Q1 posee a l utilisateur (ce qu il voit en partie) ; aucune IMPL ouverte | `etat\REL\SET1\SET1-PRE.md` |
|
||||
| 2026-10-20 21:17 | utilisateur / Big Boss | captures 29-30 : en partie, l ancienne liste sans onglets s affiche, remplacee au bout d environ 30 s par la vue a onglets, avec superposition | **H1 confirmee** (les onglets se posent sur la copie de l ecran titre tant qu elle n est pas collectee) ; **GO SET1-V1** (correctif C++ dans LPSettingsSubsystem.cpp, sous instantane SET1, lp-impl) ; **jeton UE a SET1** | `etat\REL\SET1\SET1-PRE.md` |
|
||||
| 2026-10-20 21:31 | lp-impl / Big Boss | BUILD-FIN SET1-V1 : choix de la SettingsScrollBox du MainMenu a l ecran (IsInViewport), onglets reposes au changement d instance ; LPSettingsSubsystem.cpp 5ff9f26d -> 3591f579 ; 2 builds 0 erreur 0 avertissement ; defaut identique releve dans ColorGrade, VideoQuality, ModInfo (premiere liste trouvee) | **acceptee** ; **GO SET1-V1b** dans la foulee (fonction de recherche partagee, 3 sous-systemes), instantane SET1-V1b ; jeton UE garde par SET1 ; puis VAL et build d essai | `etat\REL\SET1\SET1-V1-IMPL.md` |
|
||||
| 2026-10-20 21:42 | lp-impl / Big Boss | BUILD-FIN SET1-V1b : FindOnScreenSettingsList statique publique, partagee par ColorGrade, VideoQuality, ModInfo ; 5 fichiers, +38 -51 ; 2 builds 0 erreur 0 avertissement | **acceptee** (MD5, journaux, UeState relus) ; **jeton UE libre** ; essai en jeu (SET1, talons M-Z) a proposer en COMMUN-23 | `etat\REL\SET1\SET1-V1b-IMPL.md` |
|
||||
| 2026-10-20 21:42 | utilisateur / Big Boss | « Oui, lance la build Development COMMUN-23 (SET1 réglages en partie, M-Z talons, F8a) et prépare le cahier de tests. » | **BUILD-GO BUILD-COM23** (lp-builder, -ArchiveDir COM23, exe 0f7b0a39) ; jeton UE a BUILD-COM23 ; cahier COMMUN-23 (lp-writer) | — |
|
||||
| 2026-10-20 21:44 | lp-writer / Big Boss | COMMUN-23-TESTS redige (7 cas : SET1 .1-.5, talons .6 a-c, non-regressions .7 a-c ; lancement en cmd et PowerShell) | contre-verifie (PubCheck 0) ; § 1 a completer a la remise de BUILD-COM23 | `etat\BOSS\COMMUN-23-TESTS.md` |
|
||||
| 2026-10-20 21:46 | lp-builder / Big Boss | BUILD-COM23 : Build.ps1 a jour, BuildDebug -SkipBuild, UAT code 0 (119 s), CheckPackage PASS ; exe 0f7b0a39 = projet (SET1, MZ2, F8a) | **acceptee** ; § 1 de COMMUN-23-TESTS complete ; **jeton UE libre** ; essai donne a l utilisateur | `etat\BOSS\COMMUN-23\COMMUN-23-BUILD.md` |
|
||||
| 2026-10-20 21:46 | utilisateur / Big Boss | « Oui, lance le jeu COMMUN-23 avec -LPPersonsLog=2. » | jeu COM23 lance par Big Boss (essai COMMUN-23) | `etat\BOSS\COMMUN-23-TESTS.md` |
|
||||
| 2026-10-20 21:53 | utilisateur / Big Boss | COMMUN-23 : « 1 ok , 2 ok » + capture 31 (joueur en talons debout, pieds au sol) | **PASS** .1, .2 ; journal : « onglets poses sur MainMenu_C_… (partie) » a chaque nouvelle instance, anciennes retirees ; joueur debout en talons a meshZ -80.4 (compensation conservee, aucune ligne M-Z) | `etat\BOSS\COMMUN-23-TESTS.md` |
|
||||
| 2026-10-20 21:54 | utilisateur / Big Boss | COMMUN-23.3 : « 3 ok » | **PASS** .3 (reouvertures en partie) | `etat\BOSS\COMMUN-23-TESTS.md` |
|
||||
| 2026-10-20 21:54 | utilisateur / Big Boss | COMMUN-23.5 : « caméra conservé » | **PASS** .5 (Camera Speed conserve apres reouverture) | `etat\BOSS\COMMUN-23-TESTS.md` |
|
||||
| 2026-10-20 21:56 | utilisateur / Big Boss | capture 32 (carte de Londres, COM23) : Tamise visible ; quelques blocs gris restent dans le fleuve (un grand au premier plan, petits piliers plus loin) | masque O2 applique (59 masquees au journal 19:50:49) ; les blocs restants sont estimes etre des volumes de batiments de la carte StreetMap elle-meme (navire, pontons, piles de ponts), hors du masque des maisons MapMarkers ; suite STM1 en build 2 ; .7c Tamise : PASS au regard du masque | `etat\BOSS\COMMUN-23-TESTS.md` |
|
||||
| 2026-10-20 21:59 | utilisateur / Big Boss | COMMUN-23.4 : « 4 ok » | **PASS** .4 (retour au titre puis Settings) ; SET1 complet : .1-.5 PASS | `etat\BOSS\COMMUN-23-TESTS.md` |
|
||||
| 2026-10-20 21:59 | utilisateur / Big Boss | COMMUN-23.6 : « 6ok » | **PASS** .6 (talons au lever : pieds au sol) | `etat\BOSS\COMMUN-23-TESTS.md` |
|
||||
| 2026-10-20 22:03 | utilisateur / Big Boss | COMMUN-23.7 : « 7 ok » ; jeu ferme | **PASS** .7 ; essai COMMUN-23 clos : **7/7 PASS** (SET1 .1-.5, talons .6, non-regressions .7) ; aucune erreur grave au journal ; suites : bilan, CHG (F8a, MZ, MZ2, SET1), vague 11 ; puis REL2 | `etat\BOSS\COMMUN-23-TESTS.md` |
|
||||
| 2026-10-20 22:03 | utilisateur / Big Boss | « Oui : bilan COMMUN-23, versement des CHG (F8a, M-Z talons, SET1) puis prépare et lance la vague 11. » | CHG reserves ; **jeton du journal a lp-writer** (DOC-20261020-VERS5) ; bilan COMMUN-23 ; vague 11 ensuite | `etat\REPO\NUMEROS.md` |
|
||||
| 2026-10-20 22:08 | lp-writer / Big Boss | DOC-20261020-VERS5 + COMMUN-23-BILAN : 7/7 PASS (.4 note incertain : pas de ligne « onglets poses … (ecran titre) » pour le second ecran titre), CHG-383, 384, 385 au journal, NUMEROS CRLF garde ; annexe FIX1-MES | **accepte** ; **jeton du journal libre** ; .4 a rejouer dans l essai de REL2 ; vague 11 deposee (FIX1-T2, SET1-T1, COMMUN22-23-T1, PARTAGES) | `etat\BOSS\COMMUN-23-BILAN.md` |
|
||||
| 2026-10-20 22:10 | Big Boss | Vague 11 executee (code 0) : dc08d3b FIX1-T2 (7), 3967951 SET1-T1 (8), e6194ff COMMUN22-23-T1 (4), 3b32c5d PARTAGES (10) | **contre-verifiee** (noreply, trailer, nombre de fichiers, PubCheck -Arbre ue5.8 = 0, arbre propre) ; FILE videe ; HEAD jeu 3b32c5d ; aucun push | `etat\REPO\FILE.md` |
|
||||
| 2026-10-20 22:16 | utilisateur / Big Boss | « un quick win sur la qualité des personnages » | lot QPERS ouvert : etude QPERS-PRE (lp-cart, lecture seule) : 2 a 5 reglages de rendu essayables a la console de COM23 sans compilation, protocole d essai, diff d ini propose | `etat\REL\QPERS\` |
|
||||
| 2026-10-20 22:28 | lp-cart / Big Boss | QPERS-PRE : peau en MSM_Subsurface (r.SSS sans effet), ombres de contact sans levier, SkinCache inutilisable ; GI repose ScreenPercentage, PoolSize, SSS.Scale ; candidats console R1-R5 (resolution, nettete, poids TAA, ombres, textures) ; pistes fortes hors console : peau en Subsurface Profile, ContactShadowLength des lumieres | **accepte** ; protocole console donne a l utilisateur | `etat\REL\QPERS\QPERS-PRE.md` |
|
||||
| 2026-10-20 22:38 | utilisateur / Big Boss | QPERS R2 (r.Tonemapper.Sharpen 0.5) : « un peu plus net » | R2 : **mieux** (a graver si confirme) | `etat\REL\QPERS\QPERS-PRE.md` |
|
||||
| 2026-10-20 22:41 | utilisateur / Big Boss | QPERS R3 (r.TemporalAACurrentFrameWeight 0.08) : « pas vraiment » | R3 : **pareil** (non grave) | `etat\REL\QPERS\QPERS-PRE.md` |
|
||||
| 2026-10-20 22:45 | utilisateur / Big Boss | QPERS R4 (ombres 4096) : « pas vraiment » | R4 : **pareil** (non grave) | `etat\REL\QPERS\QPERS-PRE.md` |
|
||||
| 2026-10-20 22:48 | utilisateur / Big Boss | QPERS R1 (r.ScreenPercentage 125) : « pareil » ; essai console clos | bilan : seul R2 (Sharpen 0.5) apporte « un peu plus net » ; R1, R3, R4 sans effet visible ; R5 non joue ; le vrai levier est dans les assets (peau en Subsurface Profile, ombres de contact des lumieres) | `etat\REL\QPERS\QPERS-PRE.md` |
|
||||
| 2026-10-20 22:49 | utilisateur / Big Boss | « Oui, grave r.Tonemapper.Sharpen 0.5 aux niveaux High et Epic, et note le lot assets (profil de peau, ombres de contact) pour la build 2. » | Config/DefaultScalability.ini : r.Tonemapper.Sharpen=0.5 ajoute a [AntiAliasingQuality@2] et @3 (instantane QPERS, 3dca7e5d -> b3ecb28c, CRLF 127 -> 131, PubCheck 0) ; aucune autre ecriture de cette CVar dans Source ou Config ; CHG a reserver au prochain versement ; lot QPERS-ASSETS (peau en Subsurface Profile SSP_Girl_Head, ContactShadowLength des lumieres des pieces) note en build 2 | `etat\REL\QPERS\QPERS-PRE.md` |
|
||||
| 2026-10-20 22:59 | utilisateur / Big Boss | « Lance l etude de la revision unique de GI (liste et ordre des modifications) et, en parallele, le diagnostic d ERR-145. » | build 2 ouverte (REL2 de la build 1 en attente) ; GIREV-PRE (lp-cart, lecture seule) et ERR145-DIAG (lp-diag, lecture seule) lances en parallele | `etat\REL\GIREV\`, `etat\RELRR145\` |
|
||||
| 2026-10-20 23:04 | lp-diag / Big Boss | ERR145-DIAG : H1 (estime fort) : en C1, HideBoneByName(neckLower) retire les os de la tete des os requis (5.8), lEye/rEye figes ; la minuterie de Room recale la camera sur ces os -> entre debout puis assis, camera restee a hauteur debout, corps vu de l exterieur sans tete ; H2 concurrente (tangage) ; correctif C++ option A (AlwaysTickPoseAndRefreshBones en C1, 15-25 l.), couvre aussi ERR-106/111 ; hors GI | **accepte** ; essai de departage H1/H2 soumis a l utilisateur | `etat\RELRR145RR145-DIAG.md` |
|
||||
| 2026-10-20 23:13 | lp-cart / Big Boss | GIREV-PRE : perimetre corrige (C8, Q7, Q8, R7 dans CharGen ; Y/N dans PC ; ERR-145 en C++) ; dans GI : C10, C11, D2, D9, D17, ERR-142, F7a, message F6 (= noeud orphelin de C11), 2 commandes de console ; ordre en sous-lots A/B/C, un instantane, un commit, 50-90 ecritures ; dumps 5.8 a produire ; questions GQ1-GQ9 | **accepte** ; GQ soumises a l utilisateur ; revision apres la publication de la build 1 | `etat\REL\GIREV\GIREV-PRE.md` |
|
||||
| 2026-10-21 00:04 | utilisateur / Big Boss | « prépare la reprise pour demain » | section REPRISE du 2026-10-21 ecrite en tete de BOSS-ETAT (etat, build 1 = REL2 restant, build 2 : ERR-145 essai, GIREV GQ1-GQ9, gestes) ; fichiers non commites listes | `etat\BOSS\BOSS-ETAT.md` |
|
||||
| 2026-10-21 00:14 | utilisateur / Big Boss | « Oui, verse le CHG de QPERS et lance la vague 12 ce soir, sans push. » | CHG reserve ; **jeton du journal a lp-writer** (DOC-20261021-VERS6) ; vague 12 ensuite | `etat\REPO\NUMEROS.md` |
|
||||
| 2026-10-21 00:16 | lp-writer / Big Boss | DOC-20261021-VERS6 : CHG-386 (QPERS) au journal (+1), NUMEROS CRLF 165 garde, PubCheck 0 | **accepte** ; **jeton du journal libre** ; vague 12 deposee (QPERS-T1, BUILD2-PRE-T1, PARTAGES) | `Docs\Journal_Modifications.md` |
|
||||
| 2026-10-21 00:17 | Big Boss | Vague 12 executee (code 0) : b207e29 QPERS-T1 (2), 56fe4d6 BUILD2-PRE-T1 (2), 0536487 PARTAGES (9) | **contre-verifiee** (noreply, trailer, nombre de fichiers, PubCheck -Arbre ue5.8 = 0) ; FILE videe ; HEAD jeu 0536487 ; aucun push ; reprise prete en tete de BOSS-ETAT | `etat\REPO\FILE.md` |
|
||||
| 2026-10-21 07:11 | utilisateur / Big Boss | ERR-145, essai de departage sur COM23 (capture 33 : vue de dessus, corps assis penche sans tete) : « H1 confirmé » | **H1 retenue** (os masques figes) ; H2 ecartee ; SPEC de l option A lancee (lp-impl, etude seule, sans compilation ni copie UE) | `etat\REL\ERR145\ERR145-DIAG.md` |
|
||||
| 2026-10-21 07:13 | utilisateur / Big Boss | ERR-145, suite de l essai (capture 34, apres C -> C2 -> C1 assis) : « la vue n'est toujours pas bonne » ; camera contre le cou ou l epaule, haut violet et collier en tres gros plan | le cycle C ne corrige pas : H1 seule ne suffit pas (H1 + H2 possible) ; fait transmis a la SPEC en cours (lp-impl), qui doit dire si l option A suffit ou s il faut decalage, plan proche, masquage ou tangage borne | `etat\REL\ERR145\ERR145-DIAG.md` |
|
||||
| 2026-10-21 07:15 | utilisateur / Big Boss | « fermé » : jeu COM23 ferme apres l essai de departage ERR-145 (captures 33, 34) | note ; journal de session local (non commite) | — |
|
||||
| 2026-10-21 07:21 | utilisateur / Big Boss | GIREV, reponses : « GQ2 correction, GQ1 ne pas la « corriger » sans connaître son rôle, GQ3 ok, GQ4 mesurer l'impact, GQ5 besoin de plus d'information, GQ6 ok, GQ7 Une sauvegarde par sous-lot, GQ8 oui confirmé. GQ9 oui » | **decide** : GQ2 = M8 corrige (preset incomplet laisse le morph inchange) ; GQ6 = F7a hors revision (M7 retire) ; GQ7 = un instantane, une sauvegarde par sous-lot, un commit ; GQ8 = C8, Q7, Q8, R7 vers CharGen, Y/N vers PC ; GQ9 = liste au doc 37 § 2.7. **Ouvert** : GQ1 (role de la garde D2 a etablir, M4 en attente), GQ4 (mesure d impact du message F6 / C11, relecture MCP), GQ5 (explications donnees a l utilisateur), GQ3 (« ok » a preciser : fermer D17 ou ajouter les traces) | `etat\REL\GIREV\GIREV-PRE.md` |
|
||||
| 2026-10-21 07:21 | utilisateur / Big Boss | GIREV : « GQ3 : fermer D17, pas de traces ajoutées. » | **decide** : D17 ferme, M6 retire du sous-lot A ; restent GQ1, GQ4, GQ5 | `etat\REL\GIREV\GIREV-PRE.md` |
|
||||
| 2026-10-21 07:27 | lp-impl / Big Boss | ERR145-SPEC (434 l.) : A seule ne suffit pas (le cycle C de 05:12:14 UTC a deja mis les yeux dans la pose assise, vue restee mauvaise) ; recommande A (AlwaysTickPoseAndRefreshBones + bRequiredBonesUpToDate=false) + temoin C1 refait + partie C (lp.C1NearClip, lp.C1Forward, bascule lp.C1RefreshBones), ~140 lignes ; lectures L1 (tete qui plonge) / L2 (plan proche a 1 cm, DefaultEngine.ini:50) ; essai T0 sans build ; Q1-Q3 | **accepte** apres contre-verification (DefaultEngine.ini:50 NearClipPlane=1, SkeletalMeshComponent.h:894-896, log COM23 l. 1787-1800, Source intact) ; T0 et Q1-Q3 soumis a l utilisateur | `etat\REL\ERR145\ERR145-SPEC.md` |
|
||||
| 2026-10-21 07:28 | utilisateur / Big Boss | GIREV GQ5 : « corrigeons les erreur, améliorons les vérification, supprimons l'inutile » | **decide** (lecture de Big Boss) : D10 corrige (BlendPreset, recherche par nom exact, garde du Split) ; n° 32 verification ajoutee (ReadLine, ligne mal formee ignoree et tracee) ; D1 et D12 traces mortes supprimees ; lignes r.SSS.* et r.DynamicRes.* de UpdateGraphicsQuality supprimees si le dump 5.8 confirme qu elles sont sans effet ; D8 inchange (conception, pas une erreur) ; a integrer a la SPEC GIREV | `etat\REL\GIREV\GIREV-PRE.md` |
|
||||
| 2026-10-21 07:35 | utilisateur / Big Boss | « GQ1 oui, GQ4 on l rebranche et on évalue .D8 recherche ce qui se fait en best proctice sur D8 » | **decide** : GQ1 = relecture MCP de GI autorisee (role de la garde D2) ; GQ4 = message F6 / C11 a rebrancher, evaluation d abord (ou le brancher, quand il doit s afficher, effet joueur) ; D8 = recherche de bonnes pratiques (lp-cart, web) ; jeton UE pris par Big Boss pour l editeur headless (lecture seule) | `etat\REL\GIREV\GIREV-PRE.md` |
|
||||
| 2026-10-21 07:43 | utilisateur / Big Boss | « unreal-mcp est reconnecté, lance la relecture de GI (GQ1, GQ4). » | GO : GIREV-MCP-01 (lp-mcp, lecture seule, editeur pid 21652 laisse ouvert) ; recherche D8 (lp-cart) toujours en cours | `etat\REL\GIREV\GIREV-MCP-01.md` |
|
||||
| 2026-10-21 07:47 | lp-cart / Big Boss | GIREV-D8-RECH (184 l.) : ResolveConflictingMorphs sans parametre, appele par LoadPreset seul ; corps seul ; egalite = Max annule ; aucune norme d egalite dans les 13 sources ; Unreal additionne sans arbitrer ; 1 prefabrique sur 145 a une paire min/max ; options A / B1-B3 / C, recommande B1 (regle identique + trace au journal) ; DQ1-DQ6 | **accepte** (citation moteur SkeletalMeshComponent.cpp:4019-4021 verifiee) ; DQ1-DQ6 soumises a l utilisateur | `etat\REL\GIREV\GIREV-D8-RECH.md` |
|
||||
| 2026-10-21 07:49 | lp-mcp / Big Boss | GIREV-MCP-01 (29 appels MCP, lecture seule) : GQ1 garde D2 jamais declenchee (10 appelants, aucun chemin a antislash avec extension ; aucun 0.lpcharacter ; slot 0 deja protege par SaveSlot > 0), reco (a) laisser ou (b) supprimer, pas (c) ; GQ4 : premisse de GIREV-PRE M2 fausse, _20748 et _13122 morts mais leur jumeau _340 (ShowTutorialTxt, meme texte) est vivant sur DuplicateCharacters (LoadGame, Player.lpcharacter absent) : le message s affiche deja ; voies V1 / V2 / V3, reco V3 (supprimer les 2 morts, reecrire le texte de _340 vers Saved/Saves) | **accepte** (Content intact, git status vide) ; editeur pid 21652 ferme, UeState 0, **jeton UE libre** ; GQ1 et GQ4 re-soumises a l utilisateur | `etat\REL\GIREV\GIREV-MCP-01.md` |
|
||||
| 2026-10-21 08:10 | utilisateur / Big Boss | « Q4 : V3, D8 B2 + tracer les conflits, GQ1 supprimer » | **decide** : GQ4 = V3 (supprimer _20748 et _13122, reecrire Content de _340 avec le texte de GIREV-MCP-01 § B.5, essai de la cle NSLOCTEXT sur copie) ; D8 = B1 + B2 (trace au journal de chaque conflit, arbitrage etendu aux cheveux ; egalite inchangee « Max annule », DQ2 non demande) et D8 entre dans la revision (DQ6) ; GQ1 = (b) supprimer la garde D2 (M4) ; reste DQ5 (guide de moddage) | `etat\REL\GIREV\GIREV-MCP-01.md` |
|
||||
| 2026-10-21 08:11 | utilisateur / Big Boss | « DQ5 oui » | **decide** : la regle de resolution des conflits de morphs (le plus fort gagne, egalite = Max annule, corps et cheveux) sera ecrite dans le guide de moddage livre avec le jeu (publication, regle doc 27), avec la revision de GI ; GIREV entierement cadree | `etat\REL\GIREV\GIREV-D8-RECH.md` |
|
||||
| 2026-10-21 08:19 | utilisateur / Big Boss | ERR-145 T0 (COM23) : « C1 n'est pas réaligné quand assis, je vois mon corp en contrebas » | releve : assis en C1, camera restee haute (pose debout), corps vu en contrebas = H1 reproduite ; effet des cycles C demande | `etat\REL\ERR145\ERR145-SPEC.md` |
|
||||
| 2026-10-21 08:21 | utilisateur / Big Boss | ERR-145 T0a : « au second cycle je suis bien positionné » | releve : 1er cycle C sans effet, 2e cycle = vue correcte assis ; le remasquage depend du moment (pose relue pendant une transition, compatible L1 / H1) ; suite : 3e cycle et T0b, T0c | `etat\REL\ERR145\ERR145-SPEC.md` |
|
||||
| 2026-10-21 08:23 | utilisateur / Big Boss | ERR-145 T0a : « 3 ième cycle ok, je constate que ma tête par sur la droite les 2 fois je suis obligé de réaxé pour regarder droit devant moi » | releve : 3e cycle correct ; aux 2e et 3e retours en C1 assis, la vue part vers la droite (lacet decale), recentrage a la souris necessaire ; fait nouveau a joindre a l IMPL (orientation C1 en entree assis : lacet de la tete de l animation ou du controleur, cf. B2s) | `etat\REL\ERR145\ERR145-SPEC.md` |
|
||||
| 2026-10-21 08:25 | utilisateur / Big Boss | ERR-145 : « T0b non, T0c 1 cycle mauvais, les 2 qui suivent bons » | **T0 conclu** : une fois bien placee, aucune peau proche (L2 ecartee, partie C de la SPEC sans objet) ; chaise sans repas : meme defaut, 1er cycle mauvais puis bons (cause commune = yeux figes, H1/L1) ; IMPL = option A + temoin C1 + recentrage du lacet en entree de C1 assis ; partie C retiree sauf avis contraire ; restent Q2, Q3 | `etat\REL\ERR145\ERR145-SPEC.md` |
|
||||
| 2026-10-21 08:26 | utilisateur / Big Boss | ERR-145 Q2 : « non : la caméra C1 doit rester stable, sans suivre les mouvements de tête des animations. » | **decide** : camera C1 stable ; l option A seule (suivre les yeux animes) ne convient plus ; SPEC complementaire ERR145-SPEC-02 lancee (lp-impl, etude seule) : ancrage sur un os visible et stable plus decalage, orientation par le controleur, recentrage du lacet ; partie C retiree (T0b) ; Q3 ouverte | `etat\REL\ERR145\ERR145-SPEC.md` |
|
||||
| 2026-10-21 08:27 | utilisateur / Big Boss | ERR-145 Q3 : « Q3 oui » | **decide** : la camera stable de C1 sera etendue a la POV de scene dans une fiche a part (apres l IMPL d ERR-145) ; fait transmis a ERR145-SPEC-02 en cours | `etat\REL\ERR145\ERR145-SPEC.md` |
|
||||
| 2026-10-21 08:27 | utilisateur / Big Boss | « fermé » : jeu COM23 ferme apres l essai T0 d ERR-145 | processus LifePlay restants : 0 ; journal de session local (non commite), lu par ERR145-SPEC-02 | — |
|
||||
| 2026-10-21 08:30 | utilisateur / Big Boss | « ok REL2 » | GO REL2 (doc 37 l. 172) ; T1 fait par Big Boss : instantane REL2, ProjectVersion 2026.10.2.1a -> 2026.10.2.2a (MD5 4f89f2d1 -> 8d7f4bdf, LF) ; VAL commune lancee (lp-validator) | `etat\REL\REL2\REL2-T1-IMPL.md` |
|
||||
| 2026-10-21 08:39 | lp-validator / Big Boss | REL2-VAL (VAL commune) : PASS-STATIC, 34 fichiers depuis v2026.10.2.1a (11 A, 23 M), tous couverts (fiche, MD5, CHG-370 a 386), PubCheck 0 ; reserves C1 (Sharpen sans build d essai), C2 (COMMUN-23.4), C3 (CG2 essai partiel), C4 (piece cachee, build 2), C5 (E9 de F6 en Shipping), C6 (uproject local avec HyperAIStudio), C7 (Content/Saves, Heavy, README) | **accepte** ; C1, C2, C5 a l essai final ; C6 soumise a l utilisateur avant T2 | `etat\REL\REL2\REL2-VAL.md` |
|
||||
| 2026-10-21 08:43 | utilisateur / Big Boss | « C6 : ajoute TargetAllowList Editor à l'entrée HyperAIStudio du uproject local (sous instantané), puis lance la build Shipping. » | fait : instantane REL2 du uproject (C4DA6E2B), TargetAllowList Editor ajoute a HyperAIStudio (JSON valide, MD5 62335aef, fichier local non commite) ; **jeton UE donne a lp-builder** (REL2-T2-BUILD, Shipping 2026.10.2.2a) | `etat\REL\REL2\REL2-VAL.md` |
|
||||
| 2026-10-21 08:45 | lp-impl / Big Boss | ERR145-SPEC-02 : camera C1 stable 100 % C++ (ancre = parent de neckLower + decalage etalonne, pose par LPRoomBoundsCameraModifier apres la minuterie de Room ; rotation du controleur seul ; lacet aligne sur le buste a l entree en C1 assis ; bascules lp.C1Stable, C1AlignYaw, C1Smooth, C1EyeSource ; temoin refait) ; option A et partie C abandonnees ; ~+320/-40 l. sur 4 fichiers ; lacet -90 exact aux 2e et 3e entrees (journal COM23) ; Q4, Q5 | **accepte** ; IMPL apres la publication de la build 1 (arbre gele pour REL2) ; Q4, Q5 soumises | `etat\REL\ERR145\ERR145-SPEC-02.md` |
|
||||
| 2026-10-21 08:52 | lp-builder / Big Boss | REL2-T2-BUILD : Shipping 2026.10.2.2a, compilation code 0 (0 avert.), FULL COOK 8929 paquets 0 erreur 0 avert., paquet code 0, CheckPackage PASS, archive 2078 fichiers, 0 HyperAIStudio / McpAutomationBridge / sentry / LPSaveLocation.ini, exe E6A90334 ; controle 7 : 40 MD5 identiques ; PDB et BUILD-ID.txt non faits (refus du crochet a REL-ALPHA, non tente) | **accepte** ; **jeton UE libre** (UeState 0) ; copie du PDB soumise a l utilisateur | `etat\REL\REL2\REL2-T2-BUILD.md` |
|
||||
| 2026-10-21 08:53 | Big Boss | REL2 R0 (lecture seule) avant l essai final : LifePlay-Revival 28 fichiers 8 876 821 o (derniere ecriture 2026-10-17 12:35) ; ancien LifePlay 67 fichiers 17 342 009 o (derniere 2026-10-20 00:08, a change depuis REL-ALPHA : builds Development) ; Content\Saves absent de l archive ; 141 .lpcharacter de Content\Modules = meme compte que l archive 2026.10.2.1a (normal) | note | `etat\REL\REL2\REL2-releve-R0.csv` |
|
||||
| 2026-10-21 09:09 | utilisateur / Big Boss | « Oui, copie le PDB dans le dossier _PDB avec BUILD-ID.txt, puis lance le Shipping pour l'essai final. » | fait : PDB copie (SHA-256 BBB0C7C7, = source), BUILD-ID.txt (exe E6A90334, RSDS 15328E4F…1) dans LifePlay_Build_5.8_ALPHA-2026.10.2.2a_Shipping_PDB ; Shipping lance pour l essai final (REL2-ESSAI-FINAL) | `etat\REL\REL2\REL2-ESSAI-FINAL.md` |
|
||||
| 2026-10-21 09:11 | utilisateur / Big Boss | REL2 EF.1 : « 1, 2026.10.2.2a » | **EF.1 PASS** (version affichee au menu principal) | `etat\REL\REL2\REL2-ESSAI-FINAL.md` |
|
||||
| 2026-10-21 09:13 | utilisateur / Big Boss | REL2 EF.2 : « 2 sauvé » | **EF.2 PASS (E9 de F6)** : jeu ferme (0 processus) ; LifePlay-Revival\Saved\SaveGames\1.sav (145 462 o, 09:12:58) ; Saved\Saves\1\Characters\ 1, 2, Player.lpcharacter (09:12:58) et Saves\_session ; archive : Content\Saves toujours absent, aucun fichier ecrit dans l archive depuis 09:05 | `etat\REL\REL2\REL2-ESSAI-FINAL.md` |
|
||||
| 2026-10-21 09:15 | utilisateur / Big Boss | REL2 EF.3 : « ef3 les 2 sauvegardes passent » | **EF.3 PASS** (chargement sans message) ; « les 2 sauvegardes » lu comme celle d EF.2 et une ancienne (EF.11 probable, a confirmer) | `etat\REL\REL2\REL2-ESSAI-FINAL.md` |
|
||||
| 2026-10-21 09:16 | utilisateur / Big Boss | REL2 EF.4 : « EF4 complet » | **EF.4 PASS** : COMMUN-23.4 rejoue en Shipping (Settings depuis le nouvel ecran titre, onglets, Video et Misc complets) ; reserve C2 levee | `etat\REL\REL2\REL2-ESSAI-FINAL.md` |
|
||||
| 2026-10-21 09:17 | utilisateur / Big Boss | REL2 EF.5 : « EF5 OK » | **EF.5 PASS** (reglages en partie : nouveau panneau seul) | `etat\REL\REL2\REL2-ESSAI-FINAL.md` |
|
||||
| 2026-10-21 09:18 | utilisateur / Big Boss | REL2 EF.6 : « EF6 net, pas de halo » | **EF.6 PASS** (Sharpen 0.5 en High/Epic, CHG-386) ; reserve C1 levee | `etat\REL\REL2\REL2-ESSAI-FINAL.md` |
|
||||
| 2026-10-21 09:19 | utilisateur / Big Boss | REL2 EF.7 : « EF7 confirmé » | **EF.7 PASS** (KEY2 : 9 sections, confirmation avant remplacement d une touche prise) | `etat\REL\REL2\REL2-ESSAI-FINAL.md` |
|
||||
| 2026-10-21 09:22 | utilisateur / Big Boss | REL2 EF.8 : « EF8 ok » | **EF.8 PASS** (cameras C1, C2, C3, POV souris ; ERR-145 hors compte) | `etat\REL\REL2\REL2-ESSAI-FINAL.md` |
|
||||
| 2026-10-21 09:24 | utilisateur / Big Boss | REL2 EF.9 : « EF9 ok » | **EF.9 PASS** (talons debout et assis, M-Z) | `etat\REL\REL2\REL2-ESSAI-FINAL.md` |
|
||||
| 2026-10-21 09:25 | utilisateur / Big Boss | REL2 EF.10 : « EF10 ok » | **EF.10 PASS** (invitation Discord dans le menu du jeu) ; EF.1 a EF.10 PASS ; EF.11 a confirmer | `etat\REL\REL2\REL2-ESSAI-FINAL.md` |
|
||||
| 2026-10-21 09:25 | utilisateur / Big Boss | REL2 EF.11 : « EF11 oui » | **EF.11 PASS** (sauvegarde de l alpha 2026.10.2.1a chargee dans le Shipping 2026.10.2.2a) ; essai final 11/11 PASS | `etat\REL\REL2\REL2-ESSAI-FINAL.md` |
|
||||
| 2026-10-21 09:26 | utilisateur / Big Boss | « fer mé » | R1 : 0 processus, LifePlay-Revival 36 fichiers (derniere 09:26:15), ancien LifePlay inchange, archive non ecrite ; **essai final REL2 : 11/11 PASS** ; resultat ecrit | `etat\REL\REL2\REL2-ESSAI-RESULTAT.md` |
|
||||
| 2026-10-21 09:28 | lp-writer / Big Boss | DOC-20261021-VERS7 : CHG-387 (REL2) au journal, NUMEROS l. 166 utilise (CR 166 garde), PubCheck 0 | **accepte** ; **jeton du journal libre** ; REL2-VAL l. 121 : nom de profil neutralise (<profil>) ; vague 13 deposee (REL2-T1, BUILD2-PRE-T2, PARTAGES), PubCheck 0 sur 21 fichiers | `etat\REPO\FILE.md` |
|
||||
|
|
|
|||
141
Docs/Migration/etat/BOSS/COMMUN-21-BILAN.md
Normal file
141
Docs/Migration/etat/BOSS/COMMUN-21-BILAN.md
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
Fiche COMMUN-21-BILAN — Niveau N1 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-writer (rôle A-DOC) — Skills sk-protocol, lp-doc, lp-lot
|
||||
# COMMUN-21-BILAN : bilan de l'essai de la build Development commune COMMUN-21 (FIX1-F6 redirection des sauvegardes, KEY2-IMPL-03 confirmation des touches) (2026-10-20)
|
||||
|
||||
Rédigé par un `lp-writer` pour Big Boss (`local_104ff22d`), à partir de `COMMUN-21-TESTS.md`, des lignes du 2026-10-20 de 19:20 à 19:37 de `BOSS-JOURNAL.md` (l. 993 à 1005 ; résultats rapportés par l'utilisateur et cités mot pour mot ; les captures 18 à 22 sont décrites par ces lignes, aucune image relue), des trois journaux de jeu de la build, **complets, relus après la fermeture du jeu** (voir § 1), et des relevés `COM21-avant.txt` / `COM21-apres.txt`. Aucune transcription lue. Il n'existe pas de `COMMUN-21-ENTREE.md` : le journal de Big Boss en tient lieu. Aucun contenu de jeu : les citations de l'utilisateur sont reproduites telles quelles ; la scène intime est dite « scène ».
|
||||
|
||||
**Lecture des journaux** : interrogés par Grep sur la totalité de chaque fichier (comptes et lignes par motif) ; les fenêtres autour des lignes citées ont été lues par les sorties de Grep. Ils n'ont **pas** été lus ligne à ligne en entier (voir « Incertain »).
|
||||
|
||||
## 1. Essai
|
||||
|
||||
| Élément | Valeur |
|
||||
|---|---|
|
||||
| Fiche de tests | `etat\BOSS\COMMUN-21-TESTS.md` (14 cas : F6 6, KEY2 5, non-régression 3) |
|
||||
| Entrée de bilan | pas de `COMMUN-21-ENTREE.md` ; 11 lignes de résultats de `BOSS-JOURNAL.md` : l. 994 à 1004 (19:25 à 19:36), plus la l. 993 (19:20, remise de la build) et la l. 1005 (19:37, ordre de l'utilisateur) |
|
||||
| Build | `D:\Game\LifePlay_Build_5.8_Development_COM21\Windows\`, exe `Windows\LifePlay\Binaries\Win64\LifePlay.exe`, 335 846 400 octets, MD5 `811f72f20545613b93eb913f384ca1b2` (`COMMUN-21-TESTS.md` § 1 ; `BOSS-JOURNAL.md` l. 993), UAT code 0 en 83 s, CheckPackage PASS, 0 paquet recuit, pas de dossier `Content\Saves` livré. Sources contrôlées à la rédaction (`md5sum`) : `ModdingExtraBPLibrary.cpp` `1f93601c71d126f173fe30636aec0660`, `LPKeyboardSubsystem.cpp` `611c21489d80374a4817f70e408cf4db` : conformes aux MD5 attendus de la fiche de tests |
|
||||
| Début et fin de l'essai | **3 lancements**, journaux en UTC (heure locale = UTC + 2 h, bilan exprimé en heure locale). **Lancement 1** : ouverture 19:24:09, fermeture 19:25:35 (`Log file closed`, journal tourné). **Lancement 2** : ouverture 19:25:44, fermeture 19:27:13 (journal tourné). **Lancement 3** : ouverture 19:27:22, fermeture 19:38:07 (`Log file closed, 10/20/26 19:38:07`, dernière ligne du journal). Premier verdict rapporté à 19:25, dernier à 19:36 |
|
||||
| État du jeu à la rédaction | **Le jeu était encore ouvert** quand l'ordre est arrivé (processus `LifePlay.exe` visible à 19:37:53, journal en cours d'écriture : 2 968 lignes à 19:37, 430 552 octets). Il s'est fermé à 19:38:07 ; les copies ont été faites **après** la fermeture (relecture juste avant d'écrire, MD5 des sources identiques à ceux des copies) |
|
||||
| Qui a joué | l'utilisateur (aucun cas joué par un agent) |
|
||||
| Journaux de jeu | 3 fichiers, **local, non commité** (comme COMMUN-17 à COMMUN-20 ; ne pas les mettre au ticket du gardien). Copies sous `etat\BOSS\COMMUN-21\` ; le nom porte l'heure locale de lancement ; MD5 et tailles relevés par `md5sum` et `wc -lc` sur la copie, identiques à la source (`md5sum` de la source avant la copie) : `COMMUN-21_session_1924_rotation.log` (copie de `LifePlay-backup-2026.10.20-17.25.35.log`, lancement 1, 1 546 lignes, 159 570 octets, MD5 `543b4420606d68ff1385b3f225ebc80e`) ; `COMMUN-21_session_1925_rotation.log` (copie de `LifePlay-backup-2026.10.20-17.27.13.log`, lancement 2, 1 510 lignes, 167 196 octets, MD5 `8628df68def62424c5d829620d9fbc06`) ; `COMMUN-21_session_1927.log` (copie de `LifePlay.log`, lancement 3, 2 976 lignes, 431 102 octets, MD5 `90202cb10081d959d7a7ff76a4ec2997`). Le fichier de rotation porte l'heure UTC de fermeture |
|
||||
| Relevés des dossiers | `D:\Game\LifePlay_Backup_5.5\COM21-avant.txt` : **vide** (0 octet, 19:22 : build neuve, ni `Content\Saves` ni `Saved\Saves`). `COM21-apres.txt` (242 octets, 19:36) : **3 fichiers** sous `Saved\Saves` (`1\Characters\Player.lpcharacter`, `Default\Characters\Player.lpcharacter`, `_session\Characters\1.lpcharacter`), pas de `Content\Saves`. Le relevé « après » a été fait **par Big Boss**, le PowerShell de l'utilisateur ayant planté au démarrage (`UpdatesNotification`, largeur de fenêtre négative : sans lien avec le jeu, `BOSS-JOURNAL.md` l. 1004). Relevé fait **pendant** que le jeu était ouvert, donc avant les écritures éventuelles de la fermeture (voir « Incertain ») |
|
||||
| Écriture du bilan | le 2026-10-20, après 19:38 (fermeture du jeu) |
|
||||
|
||||
Comptes des verdicts (14 cas) : **PASS 12** (.1 à .3 et .6 à .14) ; **FAIL 0** ; **non concluant 0** ; **sans objet 1** (.4, aucune ancienne partie) ; **non joué 1** (.5, facultatif). Total 12 + 0 + 0 + 1 + 1 = 14.
|
||||
|
||||
Répartition des lignes du journal de Big Boss :
|
||||
- l. 994 (19:25) : « pas de maison sur la tamise » : `.13` PASS ; relevé avant fait (vide, build neuve) ;
|
||||
- l. 995 (19:26) : « 1,23, ok » : `.1` à `.3` PASS ;
|
||||
- l. 996 (19:26) : « 4 pas d ancienne partie » : `.4` sans objet ;
|
||||
- l. 997 à 1001 (19:28 à 19:30) : captures 18 à 22 : `.7` à `.11` PASS ;
|
||||
- l. 1002 (19:31) : « 12 ok » : `.12` PASS ;
|
||||
- l. 1003 (19:35) : « cc14 ok » : `.14` PASS ;
|
||||
- l. 1004 (19:36) : relevé après par Big Boss ; `.6` PASS (bilan `LoadTxt` du journal) ; **porte J4 de F6 franchie (2026-10-20)** ;
|
||||
- l. 993 (19:20) et l. 1005 (19:37) : remise de la build ; ordre de l'utilisateur, citation : « Oui : bilan COMMUN-21, versement des CHG (F6, KEY2-IMPL-03) puis prépare et lance la vague 10. ».
|
||||
|
||||
## 2. Verdict par cas
|
||||
|
||||
Citations exactes de l'utilisateur tirées de `BOSS-JOURNAL.md` (numéro de ligne entre parenthèses). Heure = celle de l'entrée du journal de Big Boss, heure locale (heure du rapport, pas celle du geste). Journal : L1 = `COMMUN-21_session_1924_rotation.log`, L2 = `COMMUN-21_session_1925_rotation.log`, L3 = `COMMUN-21_session_1927.log` ; l. = numéro de ligne dans ce fichier ; heures des lignes citées en UTC.
|
||||
|
||||
| Cas | Verdict | Heure | Découvreur | Preuve |
|
||||
|---|---|---|---|---|
|
||||
| COMMUN-21.1 | PASS | 19:26 | utilisateur | « 1,23, ok » (l. 995). Disque (`COM21-apres.txt`) : `Saved\Saves\_session\Characters\1.lpcharacter` créé ; `Content\Saves` **absent** (relevé avant vide, relevé après sans `Content\Saves`). Journal L1 : `Saves redirige : racine 'D:/Game/LifePlay_Build_5.8_Development_COM21/Windows/LifePlay/Saved/Saves'` (l. 1175, 17:24:21) : racine finissant par `\Saved\Saves`, **1 ligne** par lancement ; `Saves slot '_session' : nouvelle racine` l. 1176. `LoadTxt ECHEC` sur un chemin `Saves/` : 1, `OldPlayer.lpcharacter` (voir § 3, observation) ; `SaveTxt ECHEC` : 0. Écritures bilan L1 : 4 |
|
||||
| COMMUN-21.2 | PASS | 19:26 | utilisateur | « 1,23, ok » (l. 995, le « 2 » en fait partie). Disque : `Saved\Saves\1\Characters\Player.lpcharacter` et `Saved\Saves\Default\Characters\Player.lpcharacter` créés. Journal L1 : `Saves slot 'Default' : nouvelle racine` (l. 1198), `Saves slot '1' : nouvelle racine` (l. 1452, 17:25:21) ; bilan `Saves : 4 lecture(s) nouvelle racine \| 0 lecture(s) repli \| 4 ecriture(s)` (l. 1520). L'emplacement de partie utilisé porte le nom `1`. Le `.sav` dans `Saved\SaveGames` n'est pas vérifié par le relevé (non demandé à Big Boss, voir « Incertain ») ; la comparaison des familles de fichiers avec `_session` (numérotés, `F…`, `C…`) n'est pas faite : le relevé ne montre que `Player` / `1` |
|
||||
| COMMUN-21.3 | PASS | 19:26 | utilisateur | « 1,23, ok » (l. 995). Relance faite (lancements 2 et 3). L2 : `Saves slot '1' : nouvelle racine` (l. 1209, 17:25:58), **0** ligne `lu dans l'ancien Content/Saves` dans les trois journaux ; bilan L2 `4 lecture(s) nouvelle racine \| 0 lecture(s) repli \| 0 ecriture(s)` (l. 1484) : rechargement sans écriture. L3 : `Saves slot '1' : nouvelle racine` (l. 1271). `Fatal` / `Unhandled` / `Critical error` / `Assertion failed` : 0 dans les trois fichiers. Ancien dossier toujours absent. Le texte « missing crucial \*.lpcharacter files » n'a pas été cherché au journal (message d'écran ; l'utilisateur dit « ok ») |
|
||||
| COMMUN-21.4 | sans objet | 19:26 | utilisateur | « 4 pas d ancienne partie » (l. 996). Aucune ancienne partie dans la build neuve. Le **repli de lecture n'est pas éprouvé en jeu** : 0 ligne `lu dans l'ancien Content/Saves` ; il reste couvert par la VAL statique seule (`FIX1-F6-VAL.md`) ; à rejouer en build 2 ou avec une partie copiée (réserve de l'ERR-042) |
|
||||
| COMMUN-21.5 | non joué | — | — | Facultatif, non joué (consigne de Big Boss). `-LPNoSavesRedirect` n'est **pas** éprouvé en jeu (0 ligne `Saves non redirige` dans les trois journaux) ; couvert par la VAL statique |
|
||||
| COMMUN-21.6 | PASS | 19:36 | Big Boss (journal du jeu) | Rapporté à 19:36 (l. 1004) : « 4 lecture(s) nouvelle racine \| 0 repli \| 4 ecriture(s) ». Relu : L1 l. 1520 : 4 / 0 / 4 ; L2 l. 1484 : 4 / 0 / 0 ; L3 l. 2950 (17:38:05, fermeture) : **8 / 0 / 4**. Donc n > 0 et k > 0 (L1 et L3) ; repli : 0 sur les trois lancements. Motif `FIX1-F6` : **0** ligne (aucun avertissement de liste sur `Saves`) ; `LoadTxt CACHE ECART` : 0. `Cache de donnees pret : 2033 fichier(s)` : L1 0 depuis le cache, 2033 relus (14,541 s au premier lancement), L2 et L3 2033 depuis le cache (0,287 s et 0,226 s) ; en COM20 (sans F6) : 2033 aussi (21,074 s puis 0,227 s) : même nombre de fichiers, aucun écart. Durée de chargement d'une partie : pas mesurée (constat J4 de la fiche : l'utilisateur ne rapporte aucune gêne) |
|
||||
| COMMUN-21.7 | PASS | 19:28 | utilisateur | Capture 18 (l. 997) : « Num 7 is used by Favorite 7. Press it again to replace, Escape to cancel. », Map Left garde Left, section Map & World visible. Avertissement seul, rien d'écrit. Journal L3 : aucune ligne `enregistres` entre l. 1021 (17:28:35, AZERTY) et l. 1027 (17:29:20) : conforme (estimé : la fenêtre 17:28:35 à 17:29:20 contient le geste de .7 et celui de .8, aucune écriture) |
|
||||
| COMMUN-21.8 | PASS | 19:29 | utilisateur | Capture 19 (l. 998) : « Capture cancelled. », Map Left garde Left ; disposition passée en AZERTY. Journal L3 l. 1021 `51 actions et 17 axes enregistres` puis l. 1022 `disposition AZERTY appliquee, 0 liaisons retirees ailleurs` (17:28:35) : 51 actions (jamais 50), conforme. `Fatal` : 0 |
|
||||
| COMMUN-21.9 | PASS | 19:29 | utilisateur | Capture 20 (l. 999) : « Num 7 saved. Removed from: Favorite 7. », Map Left = Num 7. Journal L3 l. 1027 (17:29:20) : `Clavier : 50 actions et 17 axes enregistres` : 1 ligne, 51 → **50** comme attendu |
|
||||
| COMMUN-21.10 | PASS | 19:30 | utilisateur | Capture 21 (l. 1000) : « Original keys restored, AZERTY layout kept. », Map Left = Left. Journal L3 l. 1029 (17:29:57) : `Clavier : 51 actions et 17 axes enregistres` : 51 actions rendues (le « compte à confirmer au journal » de la l. 1000 est levé). Le compte « relus » à la relance suivante n'est pas observé : aucune relance après le Reset (le jeu est fermé à 19:38) |
|
||||
| COMMUN-21.11 | PASS | 19:30 | utilisateur | Capture 22 (l. 1001) : touche tenue, la ligne d'état reste sur « Num 7 is used by Favorite 7. Press it again… », Map Left = Left. Journal L3 : aucune ligne `enregistres` à ce moment (les écritures du fichier de touches sont aux l. 1021, 1027, 1029 seulement : 3 écritures pour 3 gestes d'écriture AZERTY, remplacement, Reset) |
|
||||
| COMMUN-21.12 | PASS | 19:31 | utilisateur | « 12 ok » (l. 1002). Constat visuel (9 sections), sans trace au journal |
|
||||
| COMMUN-21.13 | PASS | 19:25 | utilisateur | « pas de maison sur la tamise » (l. 994). Journal : trois lancements, chacun une ligne `[LPCity] EAU CentralLondon : masque 59 centres ; instances maisons 49417 ; masquees 59 ; epargnees 0 (seuil 0 m2) ; centres sans instance 0` (L1 l. 1380 à 17:24:36 ; L2 l. 1281 à 17:25:58 ; L3 l. 1343 à 17:32:08), **dernière ligne comprise** (aucun second passage à 0 instance, à la différence de COMMUN-20 l. 1417 ; Londres n'a été chargée qu'une fois par lancement) |
|
||||
| COMMUN-21.14 | PASS | 19:35 | utilisateur | « cc14 ok » (l. 1003). Journal L3 : **38** lignes `POV souris : ` (première l. 2107, 17:34:01), dont 8 en `index 2` ; **0** `AUTRE acteur que la vue` ; 35 lignes `Scene : …` (CoupleMoveY, DownUp, LeftRight confondues, non détaillées). `LoadTxt ECHEC` autre que `OldPlayer` et `ModLauncher.config` : 0. `Fatal` : 0. Nouvelle partie de scène chargée : `Saves slot '_session' : nouvelle racine` (l. 1590, 17:33:21) |
|
||||
|
||||
Comptes de contrôle (Grep sur les copies) : `Fatal|Unhandled|Critical error|Assertion failed` L1 0, L2 0, L3 0 ; `Accessed None` L1 6, L2 0, L3 4 (non triés contre la liste des connus) ; `POV souris : ` L3 38 ; `C1 souris` L3 0 (cas non demandé) ; `LoadTxt ECHEC` : `Modules/ModLauncher.config` (une fois par lancement, connu) et `Saves/…/OldPlayer.lpcharacter` (une fois par lancement : `_session` L1, `1` L1 L2 L3) ; `LogPlayerController: Error: InputMode:UIOnly` L1 4, L2 2, L3 2 (non triés).
|
||||
|
||||
## 3. KO horodatés
|
||||
|
||||
Aucun KO. Aucun cas FAIL ni non concluant.
|
||||
|
||||
| Heure | Cas | Symptôme observé | Découvreur | Ligne du brouillon (proposée, non écrite) |
|
||||
|---|---|---|---|---|
|
||||
| — | — | aucun | — | sans objet : aucun KO |
|
||||
|
||||
Observations hors cas, à porter aux brouillons par les sessions de lot (aucune écrite ici) :
|
||||
- **FIX1** : l'avertissement `LoadTxt ECHEC | 'Saves/…/OldPlayer.lpcharacter' introuvable ou illisible` (une fois par lancement) **existait déjà en COM20** (`COMMUN-20_session_1710.log` l. 1172, chemin `Saves/_session/Characters/OldPlayer.lpcharacter`, avant F6, donc non causé par F6). Le fichier `OldPlayer` est facultatif et absent d'une partie neuve (journal de Big Boss, l. 995 : « fichier facultatif absent, a confirmer contre COM20 » : confirmé par cette ligne). Il n'est pas écrit dans `Saved\Saves` (3 fichiers au relevé, aucun `OldPlayer`) ;
|
||||
- **KEY2** : le compte d'actions suit l'attendu de la fiche : 51 (création du fichier, L1 l. 878 ; AZERTY L3 l. 1021), **50** après un remplacement confirmé (l. 1027), **51** après Reset (l. 1029) ; au lancement le fichier est relu à 51 (L2 l. 894, L3 l. 894). L'écart 51 → 50 relevé en COM20 (BILAN COM20, § 3) venait donc de changements de touche qui retiraient une liaison : explication **estimée**, non démontrée ici (le cas COM20 .5 n'a pas été rejoué) ;
|
||||
- `Accessed None` : L1 6 (dont `GI` dans `CityMenu`, `CharGen`), L3 4 (`ThemeSong` dans `GI`, `getFirstDick` à l'ouverture du panneau d'action en scène, l. 2178) : non triés.
|
||||
|
||||
## 4. Report sur les VAL
|
||||
|
||||
| Cas | VAL (chemin) | Verdict statique | Verdict en jeu | Écart |
|
||||
|---|---|---|---|---|
|
||||
| COMMUN-21.1 à .3, .6 | `etat\REL\FIX1\FIX1-F6-VAL.md` | PASS-STATIC avec réserves (V1 à V6 conformes) | PASS | E1 à E3, E7 et E8 de `FIX1-F6-SPEC.md` § 7.2 vus en jeu ; E4 (`_session`) vu ; réserves 1 à 3 (concurrence, `..` dans un chemin, cas limites de `Saves/`) non exercées |
|
||||
| COMMUN-21.4 | idem | PASS-STATIC | sans objet | repli de lecture non éprouvé en jeu |
|
||||
| COMMUN-21.5 | idem | PASS-STATIC | non joué | interrupteur non éprouvé en jeu (E6) |
|
||||
| COMMUN-21.7 à .11 | `etat\REL\KEY2\KEY2-BUILD-04.md` | build seule (0 erreur) | PASS | preuve en 5 points de `KEY2-BUILD-04.md` § 3 vue : avertissement, Échap, second appui (50 actions), Reset (51), touche tenue |
|
||||
| COMMUN-21.12 | `COMMUN-20-BILAN.md` (cas .1 à .4) | PASS en jeu en COMMUN-20 | PASS | identique |
|
||||
| COMMUN-21.13 | `COMMUN-20-BILAN.md` (cas .6, .7) | PASS en jeu en COMMUN-20 | PASS | pas de second passage à 0 instance cette fois |
|
||||
| COMMUN-21.14 | `COMMUN-19-BILAN.md` (cas .1) | PASS en jeu en COMMUN-19 | PASS | identique |
|
||||
|
||||
Lignes à ajouter aux VAL concernées (**non écrites ici** ; à ajouter par la session du lot) :
|
||||
- `FIX1-F6-VAL.md` : `Suite en jeu : COMMUN-21.1 à .3 PASS (19:26), .6 PASS (19:36), .4 sans objet (aucune ancienne partie), .5 non joué ; E9 (Shipping) reste hors essai ; porte J4 franchie le 2026-10-20 ; réserves 1 à 3 reportées en build 2`.
|
||||
- `KEY2-BUILD-04.md` : `Suite en jeu : COMMUN-21.7 à .11 PASS (19:28 à 19:30) ; Échap, second appui (50 actions), Reset (51 actions), touche tenue vus`.
|
||||
|
||||
## 5. Contrôles automatiques
|
||||
|
||||
`Tools\EssaiJournal.ps1` : non lancé par ce bilan (hors fiche) ; `etat\BOSS\COMMUN-21\COMMUN-21-ESSAIJOURNAL.md` : **absent** (le dossier contient `COMMUN-21-BUILD.md`, un résumé de build `.txt` et les trois copies de journal). Les relevés ci-dessous sont des comptes par Grep sur les copies, informatifs.
|
||||
|
||||
| Journal | Lignes | `Fatal` / `Unhandled` / `Critical error` / `Assertion failed` | `Accessed None` (non triés) | Cas rattachés |
|
||||
|---|---|---|---|---|
|
||||
| `COMMUN-21_session_1924_rotation.log` | 1 546 | 0 | 6 | .1, .2, .13 |
|
||||
| `COMMUN-21_session_1925_rotation.log` | 1 510 | 0 | 0 | .3 |
|
||||
| `COMMUN-21_session_1927.log` | 2 976 | 0 | 4 | .3, .6 à .14 |
|
||||
|
||||
| Cas | Motif | Attendu | Relevé |
|
||||
|---|---|---|---|
|
||||
| .1 | `Saves redirige : racine` ; `Saves slot '_session' : nouvelle racine` ; `SaveTxt ECHEC` | 1 par lancement ; au moins 1 ; 0 | 1 par lancement (L1 l. 1175, L2 l. 1208, L3 l. 1270) ; L1 l. 1176 et L3 l. 1590 ; 0 |
|
||||
| .2 | `Saves slot '<Slot>' : nouvelle racine` ; `Saves : .* ecriture\(s\)` | au moins 1 ; > 0 | slots `Default` (L1 l. 1198) et `1` ; 4 écritures (L1 l. 1520) |
|
||||
| .3 | `lu dans l'ancien Content/Saves` ; `Fatal…` | 0 ; 0 | 0 ; 0 |
|
||||
| .4, .5 | `lu dans l'ancien…` ; `Saves non redirige` | sans objet / non joué | 0 ; 0 |
|
||||
| .6 | `Saves : .* lecture\(s\) nouvelle racine` ; `FIX1-F6` ; `LoadTxt CACHE ECART` | au moins 1 ; 0 ; 0 | 3 bilans (4/0/4, 4/0/0, 8/0/4) ; 0 ; 0 |
|
||||
| .7 à .11 | `Clavier : .* enregistres` | aucune ligne à l'avertissement ; 50 après .9 ; 51 après .10 | 51 (l. 1021), 50 (l. 1027), 51 (l. 1029) |
|
||||
| .13 | `\[LPCity\] EAU CentralLondon : masque 59 centres` ; `epargnees 0` | au moins 1 ; dernière ligne 0 | 3 lancements, 1 ligne chacun, `epargnees 0`, `centres sans instance 0` |
|
||||
| .14 | `POV souris : ` ; `LoadTxt ECHEC` ; `Fatal…` | au moins 1 par geste ; 0 ; 0 | 38 ; seulement les deux connus ; 0 |
|
||||
| .12 | sans objet | constat visuel | — |
|
||||
|
||||
Build (`COMMUN-21-BUILD.md`, `BOSS-JOURNAL.md` l. 993) : UAT code 0 en 83 s, CheckPackage PASS, 0 paquet recuit. Temps de chargement des parties : non mesuré.
|
||||
|
||||
## 6. Suite
|
||||
|
||||
Constats établis pendant et après l'essai :
|
||||
- **F6** : les fichiers de partie sont écrits sous `Saved\Saves` (trois dossiers : `_session`, `Default`, `1`), `Content\Saves` n'est ni créé ni touché ; la partie se recharge (lancements 2 et 3) en lisant la nouvelle racine, sans repli ; la porte J4 est franchie (2026-10-20). Non vus : le repli de lecture (.4), l'interrupteur `-LPNoSavesRedirect` (.5), E9 (Shipping), le message de GI (build 2).
|
||||
- **KEY2-IMPL-03** : l'avertissement, l'annulation, le second appui, le Reset et la touche tenue se comportent comme prévu (captures 18 à 22) ; les comptes du journal sont 51, 50, 51.
|
||||
- **Non-régressions** : Londres sans maison sur la Tamise (3 lancements), menu Clavier en 9 sections, POV de scène.
|
||||
|
||||
Suites par lot :
|
||||
|
||||
| Lot | Suite | Qui décide ou agit |
|
||||
|---|---|---|
|
||||
| Journal | À verser : **CHG-381** (FIX1-F6) et **CHG-382** (KEY2-IMPL-03), mise à jour d'ERR-042 ; réservés à `NUMEROS.md` (verrou 247) ; versés par la fiche DOC-20261020-VERS4 | DOC de versement, sous jeton |
|
||||
| Gardien | Vague 10 : fichiers partagés (journal, registre, NUMEROS, BOSS-*) et fichiers de lot ; les trois journaux de jeu de COMMUN-21 ne sont pas au ticket | Big Boss (lance la vague), gardien |
|
||||
| FIX1 | Build 2 : message de GI (« copy your old LifePlay\Content\Saves folder… », Q7), repli de lecture à revoir (Q6), réserves 1 à 3 de la VAL, E9 sur le Shipping (sur accord), guides de modding (Q2) puisque J4 passe | session FIX1, utilisateur |
|
||||
| KEY2 | Réserves R2 (code mort d'`AxisLabel`) et R3 (libellé de `ScrollDownUp`) de `KEY2-VAL-04.md` | session KEY2 |
|
||||
|
||||
Aucune décision n'est prise par ce bilan.
|
||||
|
||||
## Établi / estimé / incertain
|
||||
|
||||
- **Établi** : tous les verdicts et citations (`BOSS-JOURNAL.md` l. 993 à 1005, relues) ; les comptes et lignes par motif (Grep sur les copies) : trois lancements, racine redirigée une fois par lancement, bilans `Saves :` 4/0/4, 4/0/0 et 8/0/4, 0 ligne de repli, 0 `FIX1-F6`, 51 → 50 → 51 actions (L3 l. 1021, 1027, 1029), 38 `POV souris`, 0 `AUTRE acteur`, 0 erreur grave ; le relevé des dossiers (`COM21-avant.txt` vide, `COM21-apres.txt` à 3 fichiers, lus) ; la fermeture du jeu à 19:38:07 (dernière ligne de L3) ; MD5, tailles et lignes des trois copies (`md5sum`, `wc -lc`) ; l'avertissement `OldPlayer` déjà présent en COM20 (`COMMUN-20_session_1710.log` l. 1172).
|
||||
- **Estimé** : l'heure par cas = heure du rapport dans le journal de Big Boss ; l'attribution des écritures de fichier de touches aux gestes (une écriture par geste d'écriture) ; l'explication de l'écart 51 / 50 de COM20.
|
||||
- **Incertain** : le contenu des captures 18 à 22 (décrit par le journal de Big Boss, non revu) ; le `.sav` dans `Saved\SaveGames` du cas .2 et les familles de fichiers comparées à `_session` (non relevés) ; le relevé « après » fait jeu ouvert (écritures de la fermeture non couvertes ; L3 indique 4 écritures au bilan de fermeture, dont `_session` à 17:33) ; le compte « relus » après Reset (pas de relance) ; le message d'écran « missing crucial » (non cherché) ; la durée de chargement d'une partie (non mesurée) ; la nature des `Accessed None` et des `InputMode:UIOnly` ; les parties des journaux hors motifs (non lues ligne à ligne).
|
||||
- Non fait par ce bilan (consigne) : aucune ligne de brouillon ni de VAL écrite ; `EssaiJournal.ps1` non lancé ; à faire par les sessions de lot.
|
||||
|
||||
## Fichiers à commiter
|
||||
- `Docs/Migration/etat/BOSS/COMMUN-21-BILAN.md` (A).
|
||||
- `Docs/Migration/etat/BOSS/COMMUN-21/COMMUN-21_session_1924_rotation.log`, `COMMUN-21_session_1925_rotation.log` et `COMMUN-21_session_1927.log` : **local, non commité** (comme COMMUN-17 à COMMUN-20) ; 159 570, 167 196 et 431 102 octets ; pas dans le ticket.
|
||||
|
||||
PubCheck : voir le compte rendu de la fiche DOC-20261020-VERS4 (relancé sur ce fichier après écriture).
|
||||
|
||||
Tours : 9 / 40
|
||||
178
Docs/Migration/etat/BOSS/COMMUN-21-TESTS.md
Normal file
178
Docs/Migration/etat/BOSS/COMMUN-21-TESTS.md
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
Fiche COMMUN-21-FIT — Niveau N1 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-writer (rôle A-DOC) — Skills sk-protocol, lp-doc, lp-lot
|
||||
# COMMUN-21-TESTS : fiche de tests commune de la build Development COMMUN-21 (F6 redirection des sauvegardes, KEY2 confirmation des touches) (2026-10-20)
|
||||
|
||||
Demande de Big Boss (`local_104ff22d`), 2026-10-20, sur ordre de l'utilisateur : « Oui, lance la build Development COMMUN-21 (F6 redirection des sauvegardes, KEY2 confirmation des touches) et prépare le cahier de tests. » Cette fiche reprend `FIX1-F6-SPEC.md` § 7.2 (E1 à E8), `FIX1-F6-IMPL.md` § 5, `FIX1-F6-VAL.md` (réserves), le lot REL-SAV (`etat\REL\SAV\REL-SAV-SPEC.md` § 3), `KEY2-BUILD-04.md` § 3 (preuve en 5 points) et `KEY2-DIAG-03.md`, puis des non-régressions courtes. Fiche **prête** : § 1 (MD5, heure) à compléter par Big Boss à la remise de la build. Rédigée sans copie UE, sans MCP, sans lancer le jeu. Aucun contenu de jeu : chaque action est décrite par sa fonction. Forme reprise de `COMMUN-20-TESTS.md`.
|
||||
|
||||
**Porte J4 : au plus tard le 2026-10-23 au soir** (`FIX1-F6-SPEC.md` § 7.2). F6 est acceptée si E1 à E8 sont conformes ce soir-là ; sinon retour arrière à froid, F6 passe en build 2 (`FIX1-F6-SPEC.md` § 3). Les cas F6 de cette fiche doivent donc être joués **avant** cette date.
|
||||
|
||||
**Hors fiche** : E9 (build Shipping, sur accord de l'utilisateur, `%LOCALAPPDATA%\LifePlay-Revival\Saved\Saves\…`) ; la branche « pièce cachée » et ERR-145 ; le libellé de l'axe de zoom (`ScrollDownUp`) ; les réserves 1 à 3 de `FIX1-F6-VAL.md` § 5 (concurrence, `..` dans un chemin, cas limites de `Saves/`), sans effet attendu à l'écran.
|
||||
|
||||
## 1. Build testé
|
||||
|
||||
| Élément | Valeur |
|
||||
|---|---|
|
||||
| Chemin de la build | `D:\Game\LifePlay_Build_5.8_Development_COM21\Windows\` (lancer `Windows\LifePlay.exe`) ; confirmé par Big Boss à la remise ; pas de dossier `Content\Saves` livré dans l'archive (relevé du builder) |
|
||||
| Exe | `Windows\LifePlay\Binaries\Win64\LifePlay.exe` |
|
||||
| MD5 de l'exe | `811f72f20545613b93eb913f384ca1b2` (identique à `Binaries\Win64\LifePlay.exe`, compilation FIX1-F6 ; contient aussi KEY2 611c2148), 335 846 400 octets |
|
||||
| Date de génération | exe lié le 2026-10-20 à 19:09:31 ; paquet `BuildDebug.ps1 -SkipBuild` lancé à 19:17:55, UAT code 0 en 83 s, CheckPackage PASS, cuisson 0 erreur (0 paquet recuit : aucun asset modifié depuis COM20) ; journal `Saved\Logs\portage\BuildDebug_Development_20261020-191755.log` |
|
||||
| Configuration | Development, commune à plusieurs lots |
|
||||
| Base | HEAD du dépôt + sources non commitées de F6 (`ModdingExtraBPLibrary.cpp`) et de KEY2 (`LPKeyboardSubsystem.cpp`) |
|
||||
|
||||
MD5 des sources attendus (relevés dans les livrables amont) :
|
||||
- `ModdingExtraBPLibrary.cpp` `1f93601c71d126f173fe30636aec0660` (`FIX1-F6-IMPL.md` § 1 ; `FIX1-F6-VAL.md` § 3) ;
|
||||
- `LPKeyboardSubsystem.cpp` `611c2148` (`KEY2-BUILD-04.md` § 1 ; `FIX1-F6-VAL.md` § 2, B1) ;
|
||||
- binaires de contrôle de la dernière compilation de F6 (à titre de repère, la build COM21 peut différer) : `LifePlay.exe` `811f72f2…` dans `FIX1-F6-IMPL.md` Constats, `181dc8e6` dans `KEY2-BUILD-04.md` § 2 (deux compilations différentes ; seul le MD5 relevé par Big Boss fait foi).
|
||||
|
||||
Lots et correctifs couverts :
|
||||
- **FIX1-F6** (ERR-042) : les fichiers de partie `Saves/…` (personnages `.lpcharacter`) sont écrits sous `<Saved>\Saves\…` au lieu de `<jeu>\Content\Saves` ; lecture au même endroit, avec repli **par slot** sur l'ancien `Content\Saves` ; `_session` jamais de repli ; interrupteur `-LPNoSavesRedirect`. VAL statique : PASS-STATIC avec réserves ; **aucun essai en jeu** (E1 à E9 non faits, `FIX1-F6-VAL.md` § 2).
|
||||
- **KEY2-IMPL-03 / BUILD-04** (décision « 1 » sur `KEY2-DIAG-03.md`) : une touche déjà liée à une autre action n'est plus retirée d'office ; le premier appui avertit, un second appui de la même touche remplace. Construit à 0 erreur ; **jamais vu en jeu**.
|
||||
|
||||
Les deux lots sont dans le **même** exe : l'essai porte sur « F6 + KEY2 » (`FIX1-F6-IMPL.md` § 5, B1).
|
||||
|
||||
## 2. Faisabilité
|
||||
|
||||
Machine calme : réserve « mesure » non requise.
|
||||
|
||||
### 2.1 Où est le dossier de sauvegarde de cette build (établi)
|
||||
|
||||
Source : `REL-SAV-SPEC.md` § 2 (ligne 45) et § 3 (lignes 50-61) ; `FIX1-F6-SPEC.md` résumé.
|
||||
|
||||
| Contexte | Racine `Saved` | Dossier des parties (nouveau) |
|
||||
|---|---|---|
|
||||
| **Build Development COM21, sans `LPSaveLocation.ini`** (cas prévu) | `<build>\Windows\LifePlay\Saved\` | `<build>\Windows\LifePlay\Saved\Saves\` |
|
||||
| Development avec `LPSaveLocation.ini` (`[SaveLocation] SaveDir=…`) dans `<build>\Windows\LifePlay\` | `<SaveDir>\Saved\` (relance du jeu avec `-UserDir`) | `<SaveDir>\Saved\Saves\` |
|
||||
| Shipping, sans `.ini` (hors fiche, E9) | `%LOCALAPPDATA%\LifePlay-Revival\Saved\` | `%LOCALAPPDATA%\LifePlay-Revival\Saved\Saves\` |
|
||||
|
||||
- **Ancien dossier** (ne doit **rien** recevoir) : `<build>\Windows\LifePlay\Content\Saves\`.
|
||||
- Dans une Development, la garde de relance n'est active **que si `LPSaveLocation.ini` existe** (`REL-SAV-SPEC.md:45`). Vérifier d'abord, avant l'essai :
|
||||
```powershell
|
||||
Test-Path "D:\Game\LifePlay_Build_5.8_Development_COM21\Windows\LifePlay\LPSaveLocation.ini"
|
||||
```
|
||||
`False` = cas prévu. `True` = noter le contenu du fichier au BILAN et relever le dossier `<SaveDir>\Saved\Saves` à la place.
|
||||
- Le journal annonce le dossier retenu : ligne `Dossier de sauvegarde : … (relance=…, source=…, motif=…)` (`REL-SAV-SPEC.md:82`) ; lire aussi `Saves redirige : racine '…'` (cas F6.1).
|
||||
- Le dossier de sauvegarde « réel » des parties de l'utilisateur sur les versions précédentes (Shipping) est `%LOCALAPPDATA%\LifePlay\Saved` (`REL-SAV-DOC.md:14`) : **lecture seule**, jamais touché par cet essai.
|
||||
|
||||
### 2.2 Relevés avant et après (à faire à la remise de la build)
|
||||
|
||||
**Avant l'essai** : copier la sauvegarde du joueur, puis relever les deux dossiers. Commandes PowerShell prêtes (adapter `$B` seulement si la build est ailleurs) :
|
||||
|
||||
```powershell
|
||||
# Copie de sécurité de la sauvegarde existante (lecture seule sur l'original) ; le dossier de copie est neuf.
|
||||
$B = "D:\Game\LifePlay_Build_5.8_Development_COM21\Windows\LifePlay"
|
||||
Copy-Item -Recurse -Path "$env:LOCALAPPDATA\LifePlay\Saved" -Destination "D:\Game\LifePlay_Backup_5.5\COM21-sauvegarde-avant" -ErrorAction SilentlyContinue
|
||||
|
||||
# Relevé AVANT : ancien dossier (Content\Saves) et nouveau dossier (Saved\Saves), avec dates et tailles.
|
||||
Get-ChildItem -Recurse -File "$B\Content\Saves" -ErrorAction SilentlyContinue | Select-Object FullName, Length, LastWriteTime | Format-Table -AutoSize
|
||||
Get-ChildItem -Recurse -File "$B\Saved\Saves" -ErrorAction SilentlyContinue | Select-Object FullName, Length, LastWriteTime | Format-Table -AutoSize
|
||||
|
||||
# Relevé AVANT avec MD5 (pour comparer exactement à l'après) ; sortie rangée dans un fichier du lot.
|
||||
Get-ChildItem -Recurse -File "$B\Content\Saves" -ErrorAction SilentlyContinue | Get-FileHash -Algorithm MD5 | Select-Object Hash, Path | Out-File "D:\Game\LifePlay_Backup_5.5\COM21-avant-Content-Saves.txt"
|
||||
Get-ChildItem -Recurse -File "$B\Saved\Saves" -ErrorAction SilentlyContinue | Get-FileHash -Algorithm MD5 | Select-Object Hash, Path | Out-File "D:\Game\LifePlay_Backup_5.5\COM21-avant-Saved-Saves.txt"
|
||||
```
|
||||
|
||||
Dossier absent ou vide = cas normal avant l'essai (`FIX1-F6-SPEC.md` § 7.2, préparation). Noter au BILAN le nombre de fichiers de chaque dossier.
|
||||
|
||||
**Après l'essai** (après chaque cas F6 qui écrit) : refaire les mêmes deux relevés avec `-ErrorAction SilentlyContinue` ; pour les MD5, sortie vers `…-apres-….txt`, puis :
|
||||
|
||||
```powershell
|
||||
Compare-Object (Get-Content "D:\Game\LifePlay_Backup_5.5\COM21-avant-Content-Saves.txt") (Get-Content "D:\Game\LifePlay_Backup_5.5\COM21-apres-Content-Saves.txt")
|
||||
```
|
||||
Aucune sortie = ancien dossier **identique** (attendu).
|
||||
|
||||
### 2.3 Journal et témoins
|
||||
|
||||
« Journal » = `<build>\Windows\LifePlay\Saved\Logs\LifePlay.log` (le jeu en sauvegarde un exemplaire horodaté à chaque lancement : lire le fichier du lancement jugé). Motifs exacts de F6, lus dans `ModdingExtraBPLibrary.cpp` (catégorie `LogModdingExtra`, niveau `Display` sauf mention) :
|
||||
|
||||
| Motif (texte exact du code) | Ligne du code | Quand |
|
||||
|---|---|---|
|
||||
| `Saves redirige : racine '<chemin>\Saved\Saves' (repli de lecture par slot : '<chemin>\Content\Saves')` | `:73` | **une fois**, au premier accès redirigé |
|
||||
| `Saves slot '_session' : nouvelle racine` | `:83` | première lecture ou écriture de `_session` |
|
||||
| `Saves slot '<Slot>' : nouvelle racine` | `:83` | première lecture ou écriture d'un slot dans le nouveau dossier |
|
||||
| `Saves slot '<Slot>' : lu dans l'ancien Content/Saves (repli)` | `:83` | slot trouvé seulement dans l'ancien dossier |
|
||||
| `Saves non redirige (-LPNoSavesRedirect) : ancien chemin Content/Saves` | `:102` | avec l'interrupteur, une fois |
|
||||
| `Saves : <n> lecture(s) nouvelle racine \| <m> lecture(s) repli \| <k> ecriture(s)` (suivi de ` (redirection desactivee)` avec l'interrupteur) | `:269` | bilan `LoadTxt` (console `ModdingExtra.LoadTxtStats`, et à la fermeture) |
|
||||
| `LoadTxt ECHEC \| '<chemin>' introuvable ou illisible` (Warning) | `:332` | **jamais attendu** sur un chemin `Saves/` pendant F6.1 à F6.4 |
|
||||
| `SaveTxt ECHEC \| '<chemin>' (<n> car.) : ecriture impossible` (Warning) | `:361` | jamais attendu |
|
||||
| `GetAllFilesFromFolder \| '…' : liste lue dans Content, Saves non redirige pour les listes (FIX1-F6)` (Warning) | `:136` | jamais attendu (E7) |
|
||||
|
||||
Relevé commun du journal pour F6 (commande prête, à lancer après chaque lancement) :
|
||||
```powershell
|
||||
Select-String -Path "D:\Game\LifePlay_Build_5.8_Development_COM21\Windows\LifePlay\Saved\Logs\LifePlay.log" -Pattern 'LogModdingExtra: (Display|Warning): Saves','FIX1-F6','LoadTxt ECHEC','SaveTxt ECHEC','Dossier de sauvegarde'
|
||||
```
|
||||
|
||||
Témoins de KEY2 (`LPKeyboardSubsystem.cpp`, catégorie `LogLifePlay`, `Display`) :
|
||||
- `Clavier : <n> actions et <m> axes relus depuis …\LPKeyboard.ini` (`:1467`, au lancement) ;
|
||||
- `Clavier : <n> actions et <m> axes enregistres dans …` (`:1509`, à chaque écriture du fichier) ;
|
||||
- messages de la **ligne d'état** du menu Clavier (à l'écran, pas au journal) : `Capture cancelled.` (`:978`), `<touche> is used by <action>. Press it again to replace, Escape to cancel.` (`:1027`), `<touche> saved. Removed from: <action>.` (`:1083`).
|
||||
|
||||
Compte attendu des actions : **51** au départ (`DefaultInput.ini`), 50 après un remplacement confirmé, 51 après Reset (`KEY2-DIAG-03.md` § 1 et § 4). Si le fichier `LPKeyboard.ini` de la build COM21 est neuf (dossier `Saved` neuf), il part à 51 ; s'il affiche 50 dès le départ, faire d'abord **Reset** dans le menu Clavier et le noter au BILAN.
|
||||
|
||||
| Cas | Fonction ou réglage dans la build ? | Dépend d'un travail non fini ou d'une observation |
|
||||
|---|---|---|
|
||||
| .1 à .6 (F6) | oui (FIX1-F6, compilée, VAL statique PASS-STATIC avec réserves) | jamais vu en jeu ; .4 demande une ancienne partie ; .5 est facultatif |
|
||||
| .7 à .11 (KEY2) | oui (KEY2-IMPL-03, compilée à 0 erreur) | jamais vu en jeu |
|
||||
| .12 à .14 | oui | non-régressions de COMMUN-20 ; POV de scène : voir COMMUN-19.1 |
|
||||
|
||||
## 3. Cas
|
||||
|
||||
Contrôle automatique : motif cherché dans le journal de jeu, lancé avant la remise par `Tools\EssaiJournal.ps1` quand il existe. Verdict, Découvreur et Heure restent vides : le BILAN les remplit. « Journal » = `Saved\Logs\LifePlay.log` de la build. « Ancien dossier » = `<build>\Windows\LifePlay\Content\Saves` ; « nouveau dossier » = `<build>\Windows\LifePlay\Saved\Saves` (§ 2.1).
|
||||
|
||||
### 3.1 FIX1-F6 : sauvegardes redirigées
|
||||
|
||||
Prérequis communs : § 2.2 fait (copie de la sauvegarde, relevés AVANT des deux dossiers, `LPSaveLocation.ini` vérifié). Jeu lancé **sans** argument, sauf le cas .6. Pour chaque cas qui écrit, refaire les relevés APRÈS.
|
||||
|
||||
| Cas | Lot | Correctif (CHG / ERR / ticket) | Action de l'utilisateur | Attendu | Contrôle automatique du journal | Verdict | Découvreur | Heure |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| COMMUN-21.1 | FIX1 | FIX1-F6 ; ERR-042 ; `FIX1-F6-SPEC.md` § 7.2 E1, E4 | 1. Relevés AVANT. 2. Lancer le jeu, **Nouvelle partie** ; 3. créer un personnage (création complète, jusqu'à la validation) ; 4. relever le nouveau dossier (§ 2.2) sans quitter | Le **nouveau dossier** contient `Saves\_session\Characters\*.lpcharacter` (fichiers créés, dates du jour) ; l'**ancien dossier** : relevé APRÈS **identique** au relevé AVANT (0 fichier créé ou modifié) | motif `Saves redirige : racine` : **1** ligne (recopier la racine annoncée, doit finir par `\Saved\Saves`) ; motif `Saves slot '_session' : nouvelle racine` : au moins 1 ; motif `LoadTxt ECHEC.*Saves/` et `SaveTxt ECHEC` : 0 | | | |
|
||||
| COMMUN-21.2 | FIX1 | idem ; E2 | Dans la partie du cas .1, **enregistrer dans un emplacement neuf** (nom jamais utilisé) ; relever le nouveau dossier | `Saved\Saves\<Slot>\Characters\` existe et contient les mêmes familles de fichiers que `_session` (numérotés, `F…`, `C…`, `OldPlayer`, `Player` : comparer les noms avec ceux de `_session`) ; un `.sav` apparaît dans `Saved\SaveGames` ; ancien dossier toujours identique | motif `Saves slot '<Slot>' : nouvelle racine` : au moins 1 (le nom du slot est celui choisi) ; motif `Saves : .* ecriture\(s\)` au bilan : nombre d'écritures **> 0** | | | |
|
||||
| COMMUN-21.3 | FIX1 | idem ; E3 | **Quitter** le jeu complètement, **relancer**, puis **Continuer** (ou Charger l'emplacement du cas .2) ; vérifier que la partie est identique (même personnage, même lieu) | Partie rechargée **sans** message « missing crucial \*.lpcharacter files » ; personnage identique ; ancien dossier toujours identique | nouvelle session de journal : motif `Saves slot '<Slot>' : nouvelle racine` : au moins 1 ; motif `lu dans l'ancien Content/Saves` : **0** ; motif `LoadTxt ECHEC` sur un chemin `Saves/` : 0 ; motif `Fatal\|Unhandled\|Critical error\|Assertion failed` : 0 | | | |
|
||||
| COMMUN-21.4 | FIX1 | idem ; E5, repli de lecture | **Seulement si l'utilisateur a une ancienne partie** : recopier **une copie** d'un ancien emplacement de partie dans l'**ancien dossier** `Content\Saves\<SlotX>` (jamais l'original), avec son `.sav` dans `Saved\SaveGames` ; relancer, charger cette partie ; la rejouer un instant, **enregistrer** dans le même emplacement, quitter, relancer, recharger. Sans ancienne partie : noter « sans objet : aucune ancienne partie » | Chargement **sans** message d'erreur ; après l'enregistrement, `Saved\Saves\<SlotX>` **existe** ; le rechargement suivant lit la nouvelle racine ; le dossier copié dans l'ancien dossier reste **identique** (MD5 avant et après) | motif `Saves slot '<SlotX>' : lu dans l'ancien Content/Saves \(repli\)` : 1 au premier chargement ; motif `Saves slot '<SlotX>' : nouvelle racine` : 1 après l'enregistrement et le rechargement ; motif `LoadTxt ECHEC` : 0 | | | |
|
||||
| COMMUN-21.5 | FIX1 | idem ; E6, interrupteur (**facultatif**) | Fermer le jeu. Relever les deux dossiers (AVANT), puis lancer : `& "D:\Game\LifePlay_Build_5.8_Development_COM21\Windows\LifePlay.exe" -LPNoSavesRedirect` ; **Nouvelle partie** et création d'un personnage ; quitter ; relever les deux dossiers (APRÈS). Après l'essai, **relancer sans l'argument** pour la suite | **Ancien comportement** : de nouveaux fichiers dans l'**ancien dossier** `Content\Saves\_session\Characters\` ; rien de nouveau dans le nouveau dossier pour cette partie | motif `Saves non redirige \(-LPNoSavesRedirect\)` : 1 ; motif `Saves redirige : racine` : **0** dans ce journal ; au bilan `\(redirection desactivee\)` | | | |
|
||||
| COMMUN-21.6 | FIX1 | idem ; E7, E8 | Dans une session des cas .1 à .3, ouvrir la console et saisir `ModdingExtra.LoadTxtStats` (ou fermer le jeu : le bilan s'écrit aussi à la fermeture) ; recopier au BILAN les lignes du bilan `LoadTxt` | Ligne `Saves : n lecture(s) nouvelle racine \| m lecture(s) repli \| k ecriture(s)` avec **n > 0** et **k > 0** après .1 à .3 ; aucune liste n'a visé `Saves` ; la ligne `Cache de donnees pret : <x> fichier(s)` : noter x (la référence « même build sans F6 » reste à choisir : réserve de `FIX1-F6-VAL.md` § 6 ; la build COM20 contient KEY2 sans F6 et peut servir de repère) | motif `FIX1-F6` : **0** ligne (aucun avertissement de liste sur `Saves`) ; motif `Saves : .* lecture\(s\) nouvelle racine` : au moins 1 ; motif `LoadTxt CACHE ECART` : 0 | | | |
|
||||
|
||||
Constats à relever pour la porte J4 (hors verdict de cas) : durée du chargement d'une partie (le repli ajoute deux tests de dossier par lecture d'un slot, risque R4 de la SPEC : une gêne perceptible est à signaler) ; toute ligne `Saves slot ''` (fichier posé directement dans `Saves/` : cosmétique, `FIX1-F6-VAL.md` § 5 réserve 3).
|
||||
|
||||
### 3.2 KEY2 : confirmation avant de prendre une touche déjà liée
|
||||
|
||||
Prérequis communs : ouvrir le menu **Clavier** des réglages (menu principal ou pause). Choisir une action de départ dont on connaît la touche d'origine (**noter la touche d'origine** avant tout changement). L'exemple de la preuve (`KEY2-BUILD-04.md` § 3) est la flèche « **Map Left** » (section Map & World) et le **pavé 7**, déjà liée à l'action « **Favorite 7** » (section Favorites). Si le menu indique un autre nom, prendre une flèche et une action du même genre, et le dire. Relever le nombre d'actions du journal avant (`Clavier : <n> actions` : attendu 51, § 2.3).
|
||||
|
||||
| Cas | Lot | Correctif (CHG / ERR / ticket) | Action de l'utilisateur | Attendu | Contrôle automatique du journal | Verdict | Découvreur | Heure |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| COMMUN-21.7 | KEY2 | KEY2-IMPL-03 ; `KEY2-BUILD-04.md` § 3 point 1 ; `KEY2-DIAG-03.md` § 4 option 1 | Dans Map & World, cliquer **Change** sur une flèche (exemple : Map Left), puis appuyer sur le **pavé 7** (déjà pris par Favorite 7) **une seule fois**, sans maintenir | La ligne d'état affiche « … is used by **Favorite 7**. Press it again to replace, Escape to cancel. » ; **rien n'est changé** : la flèche garde sa touche d'origine, Favorite 7 garde le pavé 7 ; la capture reste en attente | motif `Clavier : .* actions et .* axes enregistres` : **aucune** ligne neuve à ce moment ; à la relecture ultérieure, 51 actions (jamais 50) | | | |
|
||||
| COMMUN-21.8 | KEY2 | idem ; point 2 | Même montage que .7 (Change, pavé 7 une fois), puis appuyer sur **Échap** ; ouvrir de nouveau le menu pour relire la flèche et Favorite 7 | Ligne d'état « **Capture cancelled.** » ; la flèche et Favorite 7 gardent leurs touches d'origine ; aucune action perdue | motif `Clavier : .* enregistres` : aucune ligne neuve ; motif `Fatal\|Unhandled\|Critical error\|Assertion failed` : 0 | | | |
|
||||
| COMMUN-21.9 | KEY2 | idem ; point 3 | Change sur la même flèche, pavé 7 (message d'avertissement), puis **second appui** du pavé 7 (appui bref, sans maintenir) | Ligne d'état « **NumPad 7 saved. Removed from: Favorite 7.** » (le nom d'affichage de la touche peut différer, le reste du texte est exact) ; la flèche a le pavé 7 ; Favorite 7 n'a plus le pavé 7 (elle garde l'autre touche qu'elle avait) | motif `Clavier : 50 actions et 17 axes enregistres` : 1 ligne (51 → **50**) | | | |
|
||||
| COMMUN-21.10 | KEY2 | idem ; point 4 | Après le cas .9, cliquer **Reset** dans le menu Clavier (confirmer s'il le demande) ; relire la flèche et Favorite 7 | Les **51 actions** sont rendues : la flèche a sa touche d'origine, Favorite 7 retrouve le pavé 7 ; aucune ligne manquante | motif `Clavier : 51 actions et 17 axes enregistres` : 1 ligne après le Reset ; à la relance suivante : `Clavier : 51 actions et 17 axes relus` | | | |
|
||||
| COMMUN-21.11 | KEY2 | idem ; point 5 | Change sur une flèche, puis **maintenir** le pavé 7 enfoncé plusieurs secondes (sans relâcher) pour provoquer la répétition de touche ; relâcher | Une touche **tenue** ne remplace pas : la ligne d'état reste sur l'avertissement « … is used by Favorite 7. Press it again… » ; ni « saved » ni « Removed from » ; Favorite 7 garde le pavé 7. Terminer par **Échap** | motif `Clavier : .* enregistres` : aucune ligne neuve pendant la touche tenue ; 51 actions inchangées | | | |
|
||||
|
||||
Après .7 à .11 : vérifier que le menu est revenu à l'état d'origine (51 actions) ; sinon **Reset** et le noter.
|
||||
|
||||
### 3.3 Non-régression
|
||||
|
||||
| Cas | Lot | Correctif (CHG / ERR / ticket) | Action de l'utilisateur | Attendu | Contrôle automatique du journal | Verdict | Découvreur | Heure |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| COMMUN-21.12 | KEY2 | menu regroupé de KEY2-IMPL-02 (COMMUN-20.1 à .4) | Faire défiler tout le menu Clavier et **noter l'ordre des titres de section** (capture bienvenue) | **9 sections dans cet ordre** : Movement, Camera, Map & World, Couple (scene), Actions & Interaction, Menus, Time, Favorites, System ; aucune section « Other » ; Pause dans Time, TestScenes dans System ; les flèches présentes dans Map & World **et** Couple (scene) | sans objet : constat visuel | | | |
|
||||
| COMMUN-21.13 | STM1 | STM1-B6 (COMMUN-20.6, .7) | Charger la carte de **Londres** (mode par défaut) ; laisser finir le chargement ; suivre le fleuve en vue de dessus ; regarder ponts et quais ; puis lire la **dernière** ligne `[LPCity] EAU CentralLondon` du journal | **Plus aucune maison générique sur la Tamise** ; ponts, quais, jeeps, arbres intacts ; maisons des berges en place | motif `\[LPCity\] EAU CentralLondon : masque 59 centres` : au moins 1 ; `epargnees 0` sur la dernière ligne ; recopier N, `masquees` et `centres sans instance` | | | |
|
||||
| COMMUN-21.14 | CAM2 | POV de scène (voir COMMUN-19.1 pour la méthode ; COMMUN-20.10) | Lancer une **scène** en pièce visible, passer en **POV** (tête du personnage 1) ; souris bouton tenu : haut, bas, gauche, droite ; **C** pour le personnage 2 et recommencer | Même comportement qu'au BILAN de COMMUN-19 / COMMUN-20 : la vue **bouge** à la souris ; noter les sens. F6 et la confirmation des touches ne doivent rien changer ici. Une partie lancée à la scène doit aussi se **charger** sans erreur (les personnages de la scène viennent du nouveau dossier) | motif `POV souris : ` : au moins 1 ligne par geste ; motif `Fatal\|Unhandled\|Critical error\|Assertion failed` : 0 ; motif `LoadTxt ECHEC` : 0 | | | |
|
||||
|
||||
Décompte : **14 cas** : F6 6 (.1 à .6, dont .4 conditionnel à une ancienne partie et .5 facultatif), KEY2 5 (.7 à .11), non-régression 3 (.12 à .14).
|
||||
|
||||
Relevés communs au journal (hors cas) : `Fatal|Unhandled|Critical error|Assertion failed` = 0 ; `Accessed None` : aucun nouveau ; toute ligne `LogModdingExtra: Display: Saves` de la session recopiée au BILAN ; relevé final des deux dossiers (§ 2.2) recopié au BILAN avec le nombre de fichiers de chacun.
|
||||
|
||||
## 4. Cas témoins
|
||||
|
||||
| Cas | VAL statique (chemin) | Verdict statique |
|
||||
|---|---|---|
|
||||
| COMMUN-21.1 à .6 | `Docs\Migration\etat\REL\FIX1\FIX1-F6-VAL.md` | PASS-STATIC avec réserves (V1 à V6 conformes, deux compilations à 0 erreur) ; E1 à E9 **reportés**, aucun essai en jeu |
|
||||
| COMMUN-21.7 à .11 | `Docs\Migration\etat\REL\KEY2\KEY2-BUILD-04.md` | build seule : compilation à 0 erreur, `Compile LPKeyboardSubsystem.cpp` ; **aucune VAL** de comportement, preuve « à faire à la prochaine build d'essai » |
|
||||
| COMMUN-21.12 | `COMMUN-20-TESTS.md` (cas .1 à .4) et son BILAN | à relever dans le BILAN de COMMUN-20 |
|
||||
| COMMUN-21.13 | `COMMUN-20-TESTS.md` (cas .6, .7) et son BILAN | à relever dans le BILAN de COMMUN-20 |
|
||||
| COMMUN-21.14 | `COMMUN-19-TESTS.md` (cas .1) et son BILAN | à relever dans le BILAN de COMMUN-19 |
|
||||
|
||||
Aucune VAL de comportement n'existe pour les cas .1 à .11 : aucun verdict statique ne vaut pour un cas de jeu.
|
||||
|
||||
PubCheck : à lancer par l'auteur après écriture (`pwsh -NoProfile -File Tools/PubCheck.ps1 -Fichiers Docs/Migration/etat/BOSS/COMMUN-21-TESTS.md -Depot "D:/Game/LifePlay-master 5.8"`, stdin sur `/dev/null`) ; résultat cité au compte rendu.
|
||||
|
||||
Tours : 5 / 40
|
||||
|
||||
## Fichiers à commiter
|
||||
- `Docs/Migration/etat/BOSS/COMMUN-21-TESTS.md` (A).
|
||||
104
Docs/Migration/etat/BOSS/COMMUN-21/COMMUN-21-BUILD.md
Normal file
104
Docs/Migration/etat/BOSS/COMMUN-21/COMMUN-21-BUILD.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
Fiche BUILD-COM21 — Niveau N0 — Modèle prévu non précisé dans la fiche | utilisé claude-haiku-5-5 (Haiku 5.5) — Agent lp-builder — Skills sk-protocol, sk-windows-shell, lp-build
|
||||
# COMMUN-21-BUILD : build Development COMMUN-21 (F6 redirection des sauvegardes, KEY2 confirmation des touches) empaquetée (2026-10-20)
|
||||
|
||||
## 1. Commande exacte
|
||||
|
||||
Deux commandes, dans cet ordre (heures d'après les noms des journaux) :
|
||||
|
||||
1. `pwsh -NoProfile -File "D:\Game\LifePlay-master 5.8\Tools\Build.ps1" -Lot COMMUN-21 -EtatDir "D:\Game\LifePlay-master 5.8\Docs\Migration\etat\BOSS\COMMUN-21"` (19:16:49, arrière-plan)
|
||||
Build LifePlayEditor Win64 Development (`Build.bat LifePlayEditor Win64 Development "-Project=D:\Game\LifePlay-master 5.8\LifePlay.uproject" -WaitMutex -NoHotReloadFromIDE`). Sortie : `Makefile : Target is up to date`, 0 unité.
|
||||
2. `pwsh -NoProfile -File "D:\Game\LifePlay-master 5.8\Tools\BuildDebug.ps1" -Config Development -SkipBuild -ArchiveDir "D:\Game\LifePlay_Build_5.8_Development_COM21"` (19:17:55, arrière-plan)
|
||||
Commande UAT écrite par le script : `RunUAT.bat BuildCookRun -project="D:\Game\LifePlay-master 5.8\LifePlay.uproject" -platform=Win64 -clientconfig=Development -cook -iterate -stage -pak -iostore -compressed -archive -archivedirectory=D:\Game\LifePlay_Build_5.8_Development_COM21 -unattended -utf8output -nop4`.
|
||||
|
||||
Préconditions : `Read` de `D:\Game\LifePlay_Build_5.8_Development_COM21` : « File does not exist » (archive neuve, aucune build existante touchée). Glob sur `D:\Game` non exécutable (délai dépassé, disque D: lent) : l'absence a été relevée par Read sur le chemin exact. Aucun verrou pris, aucune suppression, aucun déplacement.
|
||||
|
||||
Écart à la fiche : la fiche ne demande que `Build.ps1` puis `BuildDebug.ps1 -SkipBuild`. La cible jeu (`Build.ps1 -Target LifePlay`, comme COMMUN-20 étape 2) n'a pas été relancée : hors fiche. Voir Constats, point 3.
|
||||
|
||||
## 2. Code de sortie
|
||||
|
||||
- Build éditeur (étape 1) : `code=0 duree=2s erreurs=0 avertissements=0 autres=20 unites=0` (sortie de `Build.ps1`). Résumé : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\BOSS\COMMUN-21\COMMUN-21_Build_20261020-191649.txt` ; journal : `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\COMMUN-21_Build_20261020-191649.log`.
|
||||
- UAT (étape 2) : `UAT code=0 duree=83s journal=D:\Game\LifePlay-master 5.8\Saved\Logs\portage\BuildDebug_Development_20261020-191755.log`. Ligne du journal : `BuildCookRun time: 82.04 s`, `AutomationTool exiting with ExitCode=0 (Success)` (l. 753 et 756).
|
||||
- CheckPackage (sortie de l'étape 2) : `[1] PASS 0` (Manifest_NonUFSFiles_Win64.txt), `[2] PASS 0` (Manifest_UFSFiles_Win64.txt), `[3] PASS 0` (LifePlay.exe.rsp), `[4] PASS 0` (LifePlay.target), `Resultat : PASS (code 0)`.
|
||||
- Durée totale des deux étapes : 2 s (éditeur) + 83 s (UAT).
|
||||
|
||||
Cuisson (journal `BuildDebug_Development_20261020-191755.log`, comptes bruts) :
|
||||
- l. 263 : `LogCook: Display: Cooked packages 8929 Packages Remain 9529 Total 18458` ; l. 268 : `Cooked packages 8929 Packages Remain 0 Total 8929`.
|
||||
- l. 290 : `LogCook: Display: Packages Cooked: 0, Packages Incrementally Skipped: 8921, Packages Skipped by Platform: 8, Total Packages: 8929`. Aucun paquet recuit : la cuisson a réutilisé la précédente.
|
||||
- l. 498 : `LogInit: Display: Success - 0 error(s), 1 warning(s)`. l. 501 : `Execution of commandlet took: 6.63 seconds, PeakPhysMemoryMB=2439 MB`.
|
||||
- Avertissement l. 253 (= l. 496) : `CookIncremental and UnversionedCookedContent were requested, but LegacyIterative is required due to ZenStore not being used`. Connu (`lp-build` § 4 : `-iterate` de `BuildDebug.ps1`).
|
||||
- Erreurs de cuisson : aucune (Grep `Error` sur le journal : seules les lignes de résumé ci-dessus).
|
||||
|
||||
## 3. Modules recompilés
|
||||
|
||||
Aucun module recompilé dans ce lot. Établi :
|
||||
- `COMMUN-21_Build_20261020-191649.log:29` : `Target is up to date` ; l. 30 `Using Unreal Build Accelerator local executor to run 0 action(s)` ; l. 34 `Result: Succeeded` ; l. 35 `Total execution time: 1.79 seconds`.
|
||||
- Résumé `COMMUN-21_Build_20261020-191649.txt` l. 8 : `Makefile : Target is up to date` ; l. 40 : `DLL liees : 0` ; l. 38 : `Unites compilees : 0`.
|
||||
- Binaires du projet (commandes `Get-FileHash -Algorithm MD5` et `Get-Item`, sorties brutes) : `D:\Game\LifePlay-master 5.8\Binaries\Win64\LifePlay.exe` : MD5 `811F72F20545613B93EB913F384CA1B2`, date `20/10/2026 19:09:31`, taille 335846400 o. Identique à l'empreinte de la fiche (811f72f2). `UnrealEditor-LifePlay.dll` : date `20/10/2026 19:08:04`, taille 1992704 o.
|
||||
- Estimé : l'exe 19:09:31 est postérieur à la DLL éditeur 19:08:04 et au correctif FIX1 (fiche) ; le contenu KEY2 (611c2148) dans le binaire n'est pas prouvé par une recherche de symbole.
|
||||
- Effet sur l'archive : `LifePlay.exe` packagé = 335846400 o, 19:09:31, MD5 `811F72F20545613B93EB913F384CA1B2` (identique au projet).
|
||||
- Le lot ne recompile pas la cible jeu : la date 19:09:31 est celle du lien existant (fiche : FIX1, 19:08). Non établi que la cible jeu soit à jour sans `Build.ps1 -Target LifePlay`.
|
||||
|
||||
## 4. Erreurs et avertissements nouveaux
|
||||
|
||||
- Éditeur : `erreurs=0 avertissements=0 autres=20` (`COMMUN-21_Build_20261020-191649.txt`). Les 20 lignes « autres » sont les `Warning: Plugin 'HyperAIStudio' does not list plugin …` attendues pour LifePlayEditor (`lp-build` § 7 : 20 exactement, comptées l. 17 à l. 36 du résumé).
|
||||
- Cuisson : 0 erreur, 1 avertissement `LegacyIterative` (connu, section 2).
|
||||
- Nouveaux avertissements de compilation : aucun (aucune unité compilée).
|
||||
- Comptes par code C et fichier:ligne : sans objet, aucune unité compilée (`Unites compilees : 0`).
|
||||
|
||||
## 5. Toolchain
|
||||
|
||||
Non établi : le journal `COMMUN-21_Build_20261020-191649.log` ne contient pas de ligne `Using Visual Studio` (recherche par Grep : aucun match sur `Using Visual Studio`). Le MSVC épinglé de référence est `14.50.35717` (`lp-build` § 1). Sans compilation, la chaîne n'a pas été sollicitée ; à ne pas tenir pour vérifiée.
|
||||
|
||||
## 6. Preuve de chargement (addon)
|
||||
|
||||
sans objet : la fiche ne demande pas de preuve d'addon et le jeu n'a pas été lancé.
|
||||
|
||||
## 7. Journal archivé et empreintes
|
||||
|
||||
- Journal de cuisson : `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\BuildDebug_Development_20261020-191755.log`.
|
||||
- Journal de compilation : `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\COMMUN-21_Build_20261020-191649.log`.
|
||||
- Résumé : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\BOSS\COMMUN-21\COMMUN-21_Build_20261020-191649.txt` (chemin fourni par `-EtatDir`, pas de lot hors table).
|
||||
- Archive : `D:\Game\LifePlay_Build_5.8_Development_COM21` (dossier neuf, 2108 fichiers, `Get-ChildItem -Recurse -File | Measure-Object`).
|
||||
- Exe packagé `D:\Game\LifePlay_Build_5.8_Development_COM21\Windows\LifePlay\Binaries\Win64\LifePlay.exe` : MD5 `811F72F20545613B93EB913F384CA1B2`, date `20/10/2026 19:09:31`, 335846400 o. CheckPackage cite le même chemin et la même date.
|
||||
- Paquets : `Windows\LifePlay\Content\Paks\` contient `LifePlay-Windows.pak`, `LifePlay-Windows.ucas`, `LifePlay-Windows.utoc`, `global.ucas`, `global.utoc` (Glob, sortie brute).
|
||||
|
||||
### Présence de `Content\Saves` dans l'archive (essai F6)
|
||||
|
||||
- Source : `D:\Game\LifePlay-master 5.8\Content\Saves\` existe, avec `Default\Characters\Player.lpcharacter` et `_session\Characters\1.lpcharacter`, `2.lpcharacter`, `3.lpcharacter` (Glob, sortie brute).
|
||||
- Archive, fichiers détachés : `Read` sur `D:\Game\LifePlay_Build_5.8_Development_COM21\Windows\LifePlay\Content\Saves` : « File does not exist ». Établi : aucun dossier `Content\Saves` détaché dans l'archive (build en `-pak -iostore`, pas de fichiers loose).
|
||||
- Cuisson : `Saved\Cooked\Windows\LifePlay\Content\Saves` n'existe pas (Glob : « Directory does not exist »). Établi.
|
||||
- Règle de staging : Grep `Saves|lpcharacter` sur `D:\Game\LifePlay-master 5.8\Config` : aucun match. Établi : aucune règle de staging non-UFS ne couvre `Saves`.
|
||||
- Dans le `.pak` / `.utoc` : non établi. Grep `Saves[/\\]` sur `Content\Paks` : 0 match, mais l'index IoStore est binaire et ses chemins sont hachés : ce zéro ne prouve pas l'absence. Grep `Saves|lpcharacter` sur le journal de cuisson : 0 match.
|
||||
- Estimé : les `.lpcharacter` ne sont pas des paquets UE et ne sont pas cuits ; `Content\Saves` n'est donc vraisemblablement pas dans l'archive, ni en loose ni en paquet. Pour trancher : monter le `.utoc` (outil UE `UnrealPak`/`IoStore` de la version 5.8, liste des fichiers) ou essayer F6 sur le paquet et lire le journal d'exécution.
|
||||
|
||||
## Écarts à la fiche
|
||||
|
||||
1. Cible jeu non relancée (`Build.ps1 -Target LifePlay`) : hors fiche ; la date du binaire est celle du lien précédent (19:09:31).
|
||||
2. Résumé `Build.ps1` écrit dans `Docs\Migration\etat\BOSS\COMMUN-21\` via `-EtatDir` absolu, comme demandé : pas de dossier parasite créé.
|
||||
3. Cahier de tests : non rédigé. Demandé dans la même phrase de l'utilisateur, mais hors fiche BUILD (lp-builder ne rédige pas le cahier).
|
||||
4. Aucune correction, aucune commande git, aucune suppression ni déplacement. Journaux `Saved\Logs\portage` et `Saved\Cooked` hors dépôt suivi.
|
||||
|
||||
## Constats
|
||||
|
||||
1. Établi : build Development COMMUN-21 empaquetée. Code 0 à chaque étape, CheckPackage PASS, archive neuve créée.
|
||||
2. Établi : aucune recompilation (`Target is up to date`, 0 unité). L'exe packagé est identique à l'exe du projet (MD5 811F72F2, 19:09:31).
|
||||
3. Point à confirmer : la cible jeu (`LifePlay.exe`) n'a pas été recompilée par ce lot. Essai : `Build.ps1 -Lot COMMUN-21 -Target LifePlay -Config Development -ExtraArgs '-NoUBA'` (sortie attendue : `Target is up to date` ou unités compilées), à décider par l'orchestrateur.
|
||||
4. Point à confirmer (F6) : `Content\Saves` n'est pas détaché dans l'archive ni dans `Saved\Cooked` (établi), et n'a pas de règle de staging (établi). Sa présence dans le `.pak` n'est pas établie. Essai qui tranche : extraction ou liste du `.utoc` avec l'outil IoStore de 5.8, ou essai F6 en jeu sur le paquet (lecture de `Saves`).
|
||||
5. Cuisson : 0 paquet recuit (`Packages Cooked: 0`) : l'archive reprend la cuisson COMMUN-20 ; le contenu KEY2 vient de l'exe 19:09:31, pas d'une recuisson. Non établi : que la cuisson des assets modifiés par COMMUN-21 soit à jour (aucun asset listé comme modifié dans ce lot n'a été vérifié).
|
||||
6. Non mesuré : tests en jeu, preuve de chargement, présence des symboles KEY2 ou F6 dans le binaire, comptes `Build.ps1 -FromLog`, toolchain en ligne, cahier de tests.
|
||||
|
||||
## État de reprise
|
||||
|
||||
sans objet : la fiche est menée à son terme (pas d'arrêt au budget).
|
||||
|
||||
Tours : 16 / 40 (estimé par l'agent ; `python -I Tools/FicheStats.py --lot BUILD-COM21` fait foi)
|
||||
|
||||
## Fichiers à commiter
|
||||
|
||||
- `Docs/Migration/etat/BOSS/COMMUN-21/COMMUN-21-BUILD.md` (A, nouveau).
|
||||
- `Docs/Migration/etat/BOSS/COMMUN-21/COMMUN-21_Build_20261020-191649.txt` (A, généré par `Build.ps1`).
|
||||
Journaux (`Saved\Logs\portage`), archive et `Saved\Cooked` : hors dépôt suivi, non commités. Aucune commande git en écriture.
|
||||
|
||||
## À verser
|
||||
|
||||
aucun
|
||||
106
Docs/Migration/etat/BOSS/COMMUN-22/COMMUN-22-BUILD.md
Normal file
106
Docs/Migration/etat/BOSS/COMMUN-22/COMMUN-22-BUILD.md
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
Fiche BUILD-COM22 — Niveau N0 — Modèle prévu non précisé dans la fiche | utilisé claude-haiku-5-5 (Haiku 5.5) — Agent lp-builder — Skills sk-protocol, sk-windows-shell, lp-build
|
||||
# COMMUN-22-BUILD : build Development COMMUN-22 (F8a, trace M-Z enrichie) empaquetée (2026-10-20)
|
||||
|
||||
## 1. Commande exacte
|
||||
|
||||
Deux commandes, dans cet ordre (heures d'après les noms des journaux) :
|
||||
|
||||
1. `pwsh -NoProfile -File "D:/Game/LifePlay-master 5.8/Tools/Build.ps1" -Lot COMMUN-22 -EtatDir "D:/Game/LifePlay-master 5.8/Docs/Migration/etat/BOSS/COMMUN-22"` (20:24:25, arrière-plan, identifiant de tâche bit973lcj).
|
||||
Build LifePlayEditor Win64 Development (`Build.bat LifePlayEditor Win64 Development "-Project=D:\Game\LifePlay-master 5.8\LifePlay.uproject" -WaitMutex -NoHotReloadFromIDE`). Sortie : `Makefile : Target is up to date`, 0 unité.
|
||||
2. `pwsh -NoProfile -File "D:/Game/LifePlay-master 5.8/Tools/BuildDebug.ps1" -Config Development -SkipBuild -ArchiveDir "D:/Game/LifePlay_Build_5.8_Development_COM22"` (20:24:39, arrière-plan, identifiant de tâche b1p8sbnb3).
|
||||
Commande UAT écrite par le script (sortie brute, l. 1 du journal) : `RunUAT.bat BuildCookRun -project="D:\Game\LifePlay-master 5.8\LifePlay.uproject" -platform=Win64 -clientconfig=Development -cook -iterate -stage -pak -iostore -compressed -archive -archivedirectory="D:/Game/LifePlay_Build_5.8_Development_COM22" -unattended -utf8output -nop4`.
|
||||
|
||||
Préconditions : `Read` de `D:\Game\LifePlay_Build_5.8_Development_COM22` : « File does not exist » (archive neuve, aucune build existante touchée). Dossier `Docs\Migration\etat\BOSS\COMMUN-22\` absent avant le lot (Glob : aucun fichier) ; `Build.ps1` l'a créé pour son résumé. Aucun verrou pris, aucune suppression, aucun déplacement, aucune commande git.
|
||||
|
||||
Écarts à la fiche : aucun sur la commande. La cible jeu (`Build.ps1 -Target LifePlay`) n'a pas été relancée (hors fiche) ; voir Constats, point 3.
|
||||
|
||||
## 2. Code de sortie
|
||||
|
||||
- Build éditeur (étape 1) : `code=0 duree=2s erreurs=0 avertissements=0 autres=20 unites=0` (sortie de `Build.ps1`). Résumé : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\BOSS\COMMUN-22\COMMUN-22_Build_20261020-202425.txt` ; journal : `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\COMMUN-22_Build_20261020-202425.log`.
|
||||
- UAT (étape 2) : `UAT code=0 duree=72s journal=D:\Game\LifePlay-master 5.8\Saved\Logs\portage\BuildDebug_Development_20261020-202439.log`. Durée du BuildCookRun : `BuildCookRun time: 70.92 s` (journal l. 755) ; `AutomationTool exiting with ExitCode=0 (Success)` (l. 758).
|
||||
- Durée totale des deux étapes : 2 s (éditeur) + 72 s (UAT).
|
||||
- Décomposition UAT (journal, lignes brutes) : cuisson `Cook command time: 18.61 s` (l. 513) ; UnrealPak `Took 0,49s` (l. 611) et `Took 12,39s` (l. 743) ; archive `Archive command time: 19.67 s` (l. 753).
|
||||
- CheckPackage (sortie de l'étape 2, brute) :
|
||||
`[1] PASS 0 D:\Game\LifePlay_Build_5.8_Development_COM22\Windows\Manifest_NonUFSFiles_Win64.txt`
|
||||
`[2] PASS 0 D:\Game\LifePlay_Build_5.8_Development_COM22\Windows\Manifest_UFSFiles_Win64.txt`
|
||||
`[3] PASS 0 D:\Game\LifePlay-master 5.8\Intermediate\Build\Win64\x64\LifePlay\Development\LifePlay.exe.rsp`
|
||||
`[4] PASS 0 D:\Game\LifePlay-master 5.8\Binaries\Win64\LifePlay.target`
|
||||
`Resultat : PASS (code 0)`.
|
||||
Exe comparé : `exe archive ... (2026-10-20 20:09:16, 335850496 o)` = `exe du projet ... (2026-10-20 20:09:16, 335850496 o)`.
|
||||
|
||||
Cuisson (journal `BuildDebug_Development_20261020-202439.log`, comptes bruts) :
|
||||
- l. 257 : `LogCook: Display: Keeping 8921. Recooking 0. Removing 0. 0 generated packages to be evaluated for legacyiterative skipping later.`
|
||||
- l. 263 : `LogCook: Display: Cooked packages 8929 Packages Remain 9529 Total 18458` ; l. 268 : `Cooked packages 8929 Packages Remain 0 Total 8929`.
|
||||
- l. 290 : `LogCook: Display: Packages Cooked: 0, Packages Incrementally Skipped: 8921, Packages Skipped by Platform: 8, Total Packages: 8929`. Aucun paquet recuit : la cuisson a réutilisé la précédente (comme COMMUN-21).
|
||||
- l. 498 : `LogInit: Display: Success - 0 error(s), 1 warning(s)`. l. 501 : `Execution of commandlet took: 5.25 seconds, PeakPhysMemoryMB=2453 MB`.
|
||||
- Avertissement l. 253 (= l. 496) : `CookIncremental and UnversionedCookedContent were requested, but LegacyIterative is required due to ZenStore not being used`. Connu (`lp-build` § 4 : `-iterate` de `BuildDebug.ps1`).
|
||||
- Lignes l. 265 à 267 (Display, non Error) : `Package /Game/Heavy/Daz/Anims/MF has a dependency on package /Game/Heavy/Characters/CauM/M_Cau which does not exist.`, `/Game/Heavy/Daz/BoneMapping_bridget` et `/Game/Heavy/Daz/BoneMapping` dépendant de `/Engine/EngineMeshes/Humanoid` (qui n'existe pas). Non comparées au journal COMMUN-21 : nouveauté non établie (voir Constats).
|
||||
- Erreurs de cuisson : aucune (`Error:` absent du journal ; seules les lignes de résumé ci-dessus).
|
||||
|
||||
## 3. Modules recompilés
|
||||
|
||||
Aucun module recompilé dans ce lot. Établi :
|
||||
- `COMMUN-22_Build_20261020-202425.log` : `Target is up to date` (résumé l. 8 : `Makefile : Target is up to date`) ; `Using Unreal Build Accelerator local executor to run 0 action(s)` (l. 9) ; `Total execution time: 1.71 seconds` (l. 10).
|
||||
- Résumé `COMMUN-22_Build_20261020-202425.txt` l. 38 : `Unites compilees : 0` ; l. 40 : `DLL liees : 0`.
|
||||
- Binaires du projet (`Get-FileHash -Algorithm MD5` et `Get-Item`, sorties brutes) : `D:\Game\LifePlay-master 5.8\Binaries\Win64\LifePlay.exe` : MD5 `E2BA7DEC63D479974394E2CFFD1EFC19`, date `20/10/2026 20:09:16`, taille 335850496 o. Égal à l'empreinte de la fiche (e2ba7dec).
|
||||
- Exe empaqueté `D:\Game\LifePlay_Build_5.8_Development_COM22\Windows\LifePlay\Binaries\Win64\LifePlay.exe` : MD5 `E2BA7DEC63D479974394E2CFFD1EFC19`, date `20/10/2026 20:09:16`, taille 335850496 o. Identique au projet, égal à l'empreinte de la fiche.
|
||||
- Estimé : l'exe de 20:09:16 contient le code F8a (fiche) ; la preuve est l'empreinte et la date, pas une recherche de symbole dans le binaire (non faite).
|
||||
- Le lot ne recompile pas la cible jeu : la date 20:09:16 est celle du lien existant. Non établi que la cible jeu soit à jour sans `Build.ps1 -Target LifePlay`.
|
||||
|
||||
## 4. Erreurs et avertissements nouveaux
|
||||
|
||||
- Éditeur : `erreurs=0 avertissements=0 autres=20` (`COMMUN-22_Build_20261020-202425.txt`, l. 12 à 14 et l. 16 à 36). Les 20 lignes « autres » sont les `Warning: Plugin 'HyperAIStudio' does not list plugin …` attendues pour LifePlayEditor (`lp-build` § 7 : 20 exactement) : 20 comptées, 20 attendues.
|
||||
- Cuisson : 0 erreur, 1 avertissement `LegacyIterative` (connu, section 2). Lignes « has a dependency … which does not exist » (l. 265 à 267) : à confirmer (section Constats).
|
||||
- Nouveaux avertissements de compilation : aucun (aucune unité compilée).
|
||||
- Comptes par code C et fichier:ligne : sans objet, aucune unité compilée (`Unites compilees : 0`).
|
||||
|
||||
## 5. Toolchain
|
||||
|
||||
Non établi : la ligne `chaine :` du résumé `COMMUN-22_Build_20261020-202425.txt` l. 7 est vide, et le journal ne contient pas de ligne `Using Visual Studio` (même constat que COMMUN-21). Le MSVC épinglé de référence est `14.50.35717` (`lp-build` § 1). Sans compilation, la chaîne n'a pas été sollicitée ; à ne pas tenir pour vérifiée.
|
||||
|
||||
## 6. Preuve de chargement (addon)
|
||||
|
||||
sans objet : la fiche ne demande pas de preuve d'addon et le jeu n'a pas été lancé.
|
||||
|
||||
## 7. Journal archivé et empreintes
|
||||
|
||||
- Journal de cuisson : `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\BuildDebug_Development_20261020-202439.log`.
|
||||
- Journal de compilation : `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\COMMUN-22_Build_20261020-202425.log`.
|
||||
- Résumé : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\BOSS\COMMUN-22\COMMUN-22_Build_20261020-202425.txt` (chemin fourni par `-EtatDir`).
|
||||
- Archive : `D:\Game\LifePlay_Build_5.8_Development_COM22` (dossier neuf, 2108 fichiers, `Get-ChildItem -Recurse -File | Measure-Object`, sortie brute : `2108`).
|
||||
- Exe packagé : `D:\Game\LifePlay_Build_5.8_Development_COM22\Windows\LifePlay\Binaries\Win64\LifePlay.exe` : MD5 `E2BA7DEC63D479974394E2CFFD1EFC19`, date `20/10/2026 20:09:16`, 335850496 o. CheckPackage cite le même chemin et la même date.
|
||||
- Binaries du projet : `D:\Game\LifePlay-master 5.8\Binaries\Win64\LifePlay.exe` : MD5 `E2BA7DEC63D479974394E2CFFD1EFC19`, date `20/10/2026 20:09:16`.
|
||||
- Paquet : `Windows\LifePlay\Content\Paks\LifePlay-Windows.pak` créé par UnrealPak (`Created pak file`, journal l. 599 ; 1737 fichiers, 20244692 o). Les `.ucas`/`.utoc` IoStore ne sont pas listés ici (non vérifiés par Glob dans ce lot).
|
||||
|
||||
## Écarts à la fiche
|
||||
|
||||
1. Cible jeu non relancée (`Build.ps1 -Target LifePlay`) : hors fiche ; la date du binaire est celle du lien existant (20:09:16).
|
||||
2. Le protocole FIX1-MES (demande de l'utilisateur dans la même phrase que la build) n'est pas rédigé ici : hors fiche BUILD (lp-builder ne rédige que le livrable BUILD).
|
||||
3. Résumé `Build.ps1` écrit dans `Docs\Migration\etat\BOSS\COMMUN-22\` via `-EtatDir` absolu : dossier créé par le script, pas de dossier parasite.
|
||||
4. Aucune correction, aucune commande git, aucune suppression ni déplacement. Journaux `Saved\Logs\portage` et `Saved\Cooked` hors dépôt suivi.
|
||||
|
||||
## Constats
|
||||
|
||||
1. Établi : build Development COMMUN-22 empaquetée. Code 0 à chaque étape (`Build.ps1` code=0 ; UAT code=0, `AutomationTool exiting with ExitCode=0 (Success)`), CheckPackage `Resultat : PASS (code 0)`, archive neuve créée (2108 fichiers).
|
||||
2. Établi : aucune recompilation (`Target is up to date`, 0 unité). L'exe packagé est identique à l'exe du projet (MD5 E2BA7DEC, 20:09:16), et l'empreinte égale celle de la fiche.
|
||||
3. Point à confirmer : la cible jeu (`LifePlay.exe`) n'a pas été recompilée par ce lot. Essai : `Build.ps1 -Lot COMMUN-22 -Target LifePlay -Config Development -ExtraArgs '-NoUBA'` (sortie attendue : `Target is up to date` ou unités compilées), à décider par l'orchestrateur.
|
||||
4. Point à confirmer : lignes `has a dependency … which does not exist` (journal l. 265 à 267, Display) sur `/Game/Heavy/Daz/...` et `/Engine/EngineMeshes/Humanoid`. Non comparées au journal COMMUN-21 (`BuildDebug_Development_20261020-191755.log`) : nouveauté non établie. Essai qui tranche : Grep `does not exist` sur les deux journaux.
|
||||
5. Cuisson : 0 paquet recuit (`Packages Cooked: 0`) : l'archive reprend la cuisson COMMUN-21 pour les assets inchangés ; la cuisson des assets modifiés par COMMUN-22 n'a pas été vérifiée asset par asset (non établi).
|
||||
6. Contrôle de publication : `pwsh -NoProfile -File "D:/Game/LifePlay-master 5.8/Tools/PubCheck.ps1" -Fichiers "Docs/Migration/etat/BOSS/COMMUN-22/COMMUN-22-BUILD.md" -Depot "D:/Game/LifePlay-master 5.8" < /dev/null` : sortie brute `PubCheck : 0 constat(s)`, code 0 (lancé après l'écriture de ce livrable, donc sur sa version qui suit ; ce livrable lui-même n'a pas été modifié depuis).
|
||||
7. Non mesuré : tests en jeu, preuve de chargement, présence des symboles F8a dans le binaire, comptes `Build.ps1 -FromLog`, toolchain en ligne, FIX1-MES.
|
||||
|
||||
## État de reprise
|
||||
|
||||
sans objet : la fiche est menée à son terme (pas d'arrêt au budget).
|
||||
|
||||
Tours : 35 / 40 (estimé par l'agent ; `python -I Tools/FicheStats.py --lot BUILD-COM22` fait foi)
|
||||
|
||||
## Fichiers à commiter
|
||||
|
||||
- `Docs/Migration/etat/BOSS/COMMUN-22/COMMUN-22-BUILD.md` (A, nouveau).
|
||||
- `Docs/Migration/etat/BOSS/COMMUN-22/COMMUN-22_Build_20261020-202425.txt` (A, généré par `Build.ps1`).
|
||||
Journaux (`Saved\Logs\portage`), archive et `Saved\Cooked` : hors dépôt suivi, non commités. Aucune commande git en écriture.
|
||||
|
||||
## À verser
|
||||
|
||||
aucun
|
||||
150
Docs/Migration/etat/BOSS/COMMUN-23-BILAN.md
Normal file
150
Docs/Migration/etat/BOSS/COMMUN-23-BILAN.md
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
Fiche DOC-20261020-VERS5 (COMMUN-23-BILAN) — Niveau N1 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-writer (rôle A-DOC) — Skills sk-protocol, lp-doc, lp-lot
|
||||
# COMMUN-23-BILAN : bilan de l'essai de la build Development commune COMMUN-23 (SET1 réglages en partie, FIX1 M-Z talons, FIX1-F8a) (2026-10-20)
|
||||
|
||||
Rédigé par un `lp-writer` pour Big Boss (`local_104ff22d`), à partir de `COMMUN-23-TESTS.md`, des lignes du 2026-10-20 de 21:42 à 22:03 de `BOSS-JOURNAL.md` (l. 1035 à 1046 ; verdicts de l'utilisateur cités mot pour mot ; les captures 31 et 32 sont décrites par ces lignes, aucune image relue) et du journal de jeu de la build, **complet, relu après la fermeture du jeu** (voir § 1). Aucune transcription lue. Il n'existe pas de `COMMUN-23-ENTREE.md` : le journal de Big Boss en tient lieu. Aucun contenu de jeu : les citations de l'utilisateur sont reproduites telles quelles (doc 27).
|
||||
|
||||
**Lecture du journal** : interrogé par Grep sur la totalité du fichier (comptes et lignes par motif) ; les fenêtres citées viennent des sorties de Grep. Il n'a **pas** été lu ligne à ligne en entier (voir « Incertain »).
|
||||
|
||||
## 1. Essai
|
||||
|
||||
| Élément | Valeur |
|
||||
|---|---|
|
||||
| Fiche de tests | `etat\BOSS\COMMUN-23-TESTS.md` (7 cas : SET1 .1 à .5, M-Z talons .6, non-régressions .7) |
|
||||
| Entrée de bilan | pas de `COMMUN-23-ENTREE.md` ; 12 lignes de `BOSS-JOURNAL.md` : l. 1035 (21:42, ordre de lancement de la build), l. 1037 (21:46, remise de la build), l. 1038 (21:46, lancement du jeu), l. 1039 à 1045 (21:53 à 22:03, résultats) et l. 1046 (22:03, ordre de l'utilisateur) ; l. 1036 (21:44) : fiche de tests rédigée |
|
||||
| Build | `D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\`, exe `Windows\LifePlay\Binaries\Win64\LifePlay.exe`, 335 855 104 octets, MD5 `0f7b0a39eb48753d3b6bf436f43032a0` (`COMMUN-23-TESTS.md` § 1), UAT code 0 en 119 s, CheckPackage PASS, 0 paquet recuit (`COMMUN-23-BUILD.md`, `BOSS-JOURNAL.md` l. 1037) |
|
||||
| Sources contrôlées à la rédaction (`md5sum`) | `LPSettingsSubsystem.cpp` `6277a8fc139c05dc10e302f88de0f8d9`, `LPSettingsSubsystem.h` `138350efe8473c430db984db63c8feac`, `LPColorGradeSubsystem.cpp` `5be400543166b6de7a4a88f6097a9d93`, `LPVideoQualitySubsystem.cpp` `c3055197030bdbbce813df4cc6d7cd63`, `LPModInfoSubsystem.cpp` `98206e688308e908b04ae15cf408e1bb`, `LPDirectControlSubsystem.cpp` `86ef519e880989941e033edeadda7c26`, `LPCameraModeSubsystem.cpp` `976bf0a458b87f9aecf974fcec3209f0` : tous conformes aux MD5 attendus de `COMMUN-23-TESTS.md` § 1 |
|
||||
| Début et fin de l'essai | **1 lancement**, avec `-LPPersonsLog=2`. Journal en UTC (heure locale = UTC + 2 h, bilan en heure locale). Ouverture `Log file open, 10/20/26 21:46:56` (heure locale, première ligne) ; fermeture `Log file closed, 10/20/26 22:03:19` (dernière ligne). Premier verdict rapporté à 21:53, dernier à 22:03 |
|
||||
| État du jeu à la rédaction | **Jeu fermé** (dernière ligne du journal : `Log file closed`, `LogExit: Exiting.`) ; `BOSS-JOURNAL.md` l. 1045 : « jeu ferme ». Copie faite après la fermeture ; journal relu juste avant l'écriture |
|
||||
| Qui a joué | l'utilisateur (aucun cas joué par un agent) |
|
||||
| Journal de jeu | 1 fichier, **local, non commité** (comme COMMUN-17 à COMMUN-21 ; ne pas le mettre au ticket du gardien). Copie `etat\BOSS\COMMUN-23\COMMUN-23_session_2146.log` (nom = heure locale de lancement), source `LifePlay\Saved\Logs\LifePlay.log` de la build : 28 549 lignes, 5 272 268 octets, MD5 `f3450727de944b0c45bc6d670d795a28`, identique à la source (`md5sum` des deux) ; `Log file closed` en dernière ligne. Il n'existe qu'un fichier dans `Saved\Logs` (un seul lancement, pas de journal de rotation) |
|
||||
| Relevés des dossiers | sans objet : aucun relevé demandé par la fiche (pas de `COM23-avant.txt`) |
|
||||
| Écriture du bilan | le 2026-10-20, après 22:03 (fermeture du jeu) |
|
||||
|
||||
Comptes des verdicts (7 cas) : **PASS 7** (.1 à .7) ; **FAIL 0** ; **non concluant 0** ; **sans objet 0** ; **non joué 0**. Total 7. Sous-parties : .6 a) et b) PASS ; .6 c) (facultatif, PNJ à talons) : non rapporté séparément ; .7 a) b) c) : « 7 ok » englobe les trois (voir § 2 et « Incertain »).
|
||||
|
||||
Répartition des lignes du journal de Big Boss :
|
||||
- l. 1039 (21:53) : « 1 ok , 2 ok » + capture 31 : `.1`, `.2` PASS ;
|
||||
- l. 1040 (21:54) : « 3 ok » : `.3` PASS ;
|
||||
- l. 1041 (21:54) : « caméra conservé » : `.5` PASS ;
|
||||
- l. 1042 (21:56) : capture 32 : `.7` c) Tamise (voir § 2 et § 6) ;
|
||||
- l. 1043 (21:59) : « 4 ok » : `.4` PASS ;
|
||||
- l. 1044 (21:59) : « 6ok » : `.6` PASS ;
|
||||
- l. 1045 (22:03) : « 7 ok », jeu fermé : `.7` PASS, essai clos 7/7 ;
|
||||
- l. 1035, 1037, 1038 et 1046 : lancement de la build, remise, lancement du jeu ; ordre de l'utilisateur, citation : « Oui : bilan COMMUN-23, versement des CHG (F8a, M-Z talons, SET1) puis prépare et lance la vague 11. ».
|
||||
|
||||
## 2. Verdict par cas
|
||||
|
||||
Citations exactes de l'utilisateur tirées de `BOSS-JOURNAL.md` (numéro de ligne entre parenthèses). Heure = celle de l'entrée du journal de Big Boss, heure locale (heure du rapport, pas celle du geste). Journal : `l.` = numéro de ligne dans `COMMUN-23_session_2146.log` ; heures des lignes citées en **UTC** (heure locale − 2 h). `<n>` = suffixe `MainMenu_C_<n>`, ramené aux cinq derniers chiffres pour la lisibilité (les noms complets sont de la forme `MainMenu_C_21474xxxxx`).
|
||||
|
||||
| Cas | Verdict | Heure | Découvreur | Preuve |
|
||||
|---|---|---|---|---|
|
||||
| COMMUN-23.1 | PASS | 21:53 | utilisateur | « 1 ok » (l. 1039). Journal : écran titre, `Reglages : onglets poses sur MainMenu_C_2147482350 (ecran titre)` (l. 1056, 19:47:14) : **1 ligne** `(ecran titre)` dans la session ; les trois familles sur la **même** instance : `Couleur : reglages de couleur ajoutes sur`, `Modules : cases de controle des mods … sur`, `Video : controles ajoutes avant les reglages de couleur (sur …)` aux l. 976 à 978 (19:47:00), nom `…482350` identique |
|
||||
| COMMUN-23.2 | PASS | 21:53 | utilisateur | « 2 ok » (l. 1039). Journal : première ouverture en partie, `onglets poses sur MainMenu_C_2147463772 (partie)` (l. 4292, 19:50:59), après `onglets retires de MainMenu_C_2147482350 (instance quittee)` (l. 4179, 19:50:55) ; Couleur, Modules, Video sur `…463772` aux l. 4197, 4233, 4256 (19:50:55, soit 0,2 s après le retrait de l'ancienne instance) ; `already has a parent` : **0** |
|
||||
| COMMUN-23.3 | PASS | 21:54 | utilisateur | « 3 ok » (l. 1040). Journal : à chaque nouvelle ouverture, `retires de <ancienne>` puis `poses sur <nouvelle> (partie)`, nom **nouveau** à chaque fois : `…463772` (l. 4292), `…463495` (l. 6234, 19:52:48), `…462808` (l. 8345, 19:54:38), `…442066` (l. 24674, 20:02:51) ; **une** ligne par famille et par instance (6 instances, 3 familles, 3 lignes chacune, 18 lignes) ; Couleur, Modules, Video du même nom à 0,29 s à 0,4 s après le retrait de l'ancienne (ex. `…462808` : retrait l. 8105 à 19:54:27.705, Couleur l. 8163 à 19:54:28.119) : conforme au ticker de 0,5 s de W7 |
|
||||
| COMMUN-23.4 | PASS | 21:59 | utilisateur | « 4 ok » (l. 1043). Journal : retour au titre, `onglets retires de MainMenu_C_2147442066 (instance quittee)` (l. 27345, 20:03:10) ; les trois lignes Couleur, Modules, Video sur la nouvelle instance `MainMenu_C_2147441492` (l. 27369, 27371, 27380, 20:03:10), nom **différent** de celui du premier titre (`…482350`). **Pas de ligne `onglets poses sur MainMenu_C_2147441492 (ecran titre)`** avant la fermeture (20:03:19) : voir « Incertain » |
|
||||
| COMMUN-23.5 | PASS | 21:54 | utilisateur | « caméra conservé » (l. 1041). Constat visuel (valeur de Camera Speed conservée après réouverture), sans ligne de journal propre ; les réouvertures sont celles de .3 (instances `…463495` à `…442066`) |
|
||||
| COMMUN-23.6 | PASS | 21:59 | utilisateur | « 6ok » (l. 1044) ; capture 31 (l. 1039, 21:53) : joueur en talons debout, pieds au sol. Journal (`-LPPersonsLog=2` pris : `LPDebug persons : releve toutes les 2 s`, l. 870, 19:46:59) : **487** lignes `STATE PlayerCharacter` ; `M-Z :` : **0** ligne dans la session ; `HeelHeight=?` : 0. Séquence du joueur (valeurs de `meshZ=` en séries) : −90,0 (64 relevés, 19:47:02) ; **−80,4 (137 relevés, 19:49:10 à 19:53:46, debout, `currentAnimation=-`)** ; −90,0 (79) ; assis −90,0 (`…-sit`, 19:56:24 à 19:58:14) ; **−80,4 (50 relevés dès 19:58:14, `currentAnimation=fnt_new053-f-0-sit` encore posé après le lever)** ; −80,4 puis −88,0 (voir « Incertain ») ; −80,4 (25) à la fin. Valeurs distinctes de `meshZ=` du joueur : −80,4 (241), −88,0 (48), −90,0 (198). Donc en talons : meshZ −80,4 **conservé** au lever, aucune correction M-Z déclenchée (cible = −90 + 12 × 0,8 = −80,4) |
|
||||
| COMMUN-23.7 | PASS | 22:03 | utilisateur | « 7 ok » (l. 1045). a) glissé du couple (F8a) : constat visuel ; `Fatal\|Unhandled\|Critical error\|Assertion failed` : **0** dans le journal. b) menu Clavier : constat visuel (9 sections) ; journal : `Clavier : 51 actions et 17 axes enregistres` (création du fichier l. 879, AZERTY l. 6307, Reset l. 26598). c) Tamise : capture 32 (l. 1042, 21:56) : « Tamise visible ; quelques blocs gris restent dans le fleuve (un grand au premier plan, petits piliers plus loin) » ; journal : `[LPCity] EAU CentralLondon : masque 59 centres ; instances maisons 49417 ; masquees 59 ; epargnees 0 (seuil 0 m2) ; centres sans instance 0` (l. 4056, 19:50:49) ; second passage à 0 instance : voir « Notes » |
|
||||
|
||||
Comptes de contrôle (Grep sur la copie) : `Fatal|Unhandled|Critical error|Assertion failed` 0 ; `already has a parent` 0 ; `Accessed None` 10 lignes (dont 2 du résumé de fermeture, l. 28502 et 28504 : 8 occurrences réelles, voir « Notes ») ; `LogPlayerController: Error` 10 (non triés) ; `onglets poses` 5 (1 `(ecran titre)`, 4 `(partie)`), `onglets retires` 5 ; `M-Z :` 0.
|
||||
|
||||
## 3. KO horodatés
|
||||
|
||||
Aucun KO. Aucun cas FAIL ni non concluant.
|
||||
|
||||
| Heure | Cas | Symptôme observé | Découvreur | Ligne du brouillon (proposée, non écrite) |
|
||||
|---|---|---|---|---|
|
||||
| — | — | aucun | — | sans objet : aucun KO |
|
||||
|
||||
Notes (aucune n'est un KO du lot) :
|
||||
- **Blocs gris dans la Tamise** (capture 32, `BOSS-JOURNAL.md` l. 1042) : ce sont les volumes de la carte StreetMap elle-même (navire, pontons, piles de ponts : estimé, non vérifié sur la carte), **hors du masque des maisons** (le masque a fait son travail : 59 masquées, 0 épargnée, l. 4056). Suite STM1, en build 2.
|
||||
- **Second passage du masque à 0 instance** : `[LPCity] EAU CentralLondon : masque 59 centres ; instances maisons 0 ; masquees 0 ; epargnees 0 (seuil 0 m2) ; centres sans instance 59` (l. 9142, 19:55:23), après le passage utile de l'l. 4056. **Connu** (S5 de la suite STM1 : masque après un rechoix de la ville) ; déjà vu en COMMUN-20 (l. 1417 selon `COMMUN-21-BILAN.md`). Sans effet visible rapporté.
|
||||
- **Clé « meshZ = −88,0 »** : voir « Incertain ».
|
||||
- **`Accessed None`** (8 occurrences réelles, non triées contre la liste des connus) : `CallFunc_GetSkeletalMesh_ReturnValue` ×2 (l. 1859, 1914), `GI` dans `CityMenu` ×2 (l. 3971, 9047), `K2Node_CustomEvent_Person` / « assign variable » ×3 (l. 12074, 12087, 12100), `getFirstDick` ×1 (l. 19649) : mêmes familles qu'en COMMUN-21.
|
||||
|
||||
## 4. Report sur les VAL
|
||||
|
||||
| Cas | VAL (chemin) | Verdict statique | Verdict en jeu | Écart |
|
||||
|---|---|---|---|---|
|
||||
| COMMUN-23.1 à .5 | `etat\REL\SET1\SET1-V1-IMPL.md` (§ 5, V1 à V10), `SET1-V1b-IMPL.md` (§ 5, W1 à W9) | IMPL seulement : compilation à 0 erreur et 0 avertissement, aucune VAL de comportement | PASS | les points V1 à V10 et W1 à W9 « à rejouer sur un build Development » sont couverts par .1 à .5 ; V6 (`IsInViewport()` vrai pour le titre) : **vu** (onglets posés au titre, l. 1056) ; W7 (≈ 0,5 s) : vu, 0,29 à 0,42 s après le retrait de l'ancienne instance ; le « 30 s » d'origine n'a pas reparu (utilisateur : « 2 ok », « 3 ok ») |
|
||||
| COMMUN-23.6 | `etat\REL\FIX1\FIX1-MZ2-IMPL.md` (§ 5, points 2 à 6), `FIX1-MES.md` | IMPL seulement : comportement calculé sur les journaux de COM22 | PASS | meshZ −80,4 conservé, 0 ligne `M-Z :` ; l'essai sans talons (.6 b) donne −90,0 et 0 ligne `M-Z :` (séries −90,0 du joueur, 19:53:46 et 19:56:24) |
|
||||
| COMMUN-23.7 a | `etat\REL\FIX1\FIX1-F8a-IMPL.md` (C1) | build seule : 0 avertissement, 0 erreur | PASS | glissé exécuté, 0 erreur grave |
|
||||
| COMMUN-23.7 b, c | `COMMUN-21-BILAN.md` (.12, .13) | PASS en jeu en COMMUN-21 | PASS | identique ; second passage du masque à 0 instance revu (S5) |
|
||||
|
||||
Lignes à ajouter aux IMPL concernées (**non écrites ici** ; à ajouter par les sessions de lot) :
|
||||
- `SET1-V1-IMPL.md` et `SET1-V1b-IMPL.md` : `Suite en jeu : COMMUN-23.1 à .5 PASS (21:53 à 21:59) ; onglets posés sur l'instance à l'écran au titre et à chaque nouvelle instance en partie ; trois familles Couleur, Video, Modules sur le même nom d'instance`.
|
||||
- `FIX1-MZ2-IMPL.md` : `Suite en jeu : COMMUN-23.6 PASS (21:59) ; joueur en talons debout à meshZ −80,4, 0 ligne M-Z`.
|
||||
- `FIX1-F8a-IMPL.md` : `Suite en jeu : COMMUN-23.7 a PASS (22:03)`.
|
||||
|
||||
## 5. Contrôles automatiques
|
||||
|
||||
`Tools\EssaiJournal.ps1` : non lancé par ce bilan (hors fiche) ; `etat\BOSS\COMMUN-23\COMMUN-23-ESSAIJOURNAL.md` : **absent** (le dossier contient `COMMUN-23-BUILD.md`, un résumé de build `.txt` et la copie du journal). Les relevés ci-dessous sont des comptes par Grep sur la copie, informatifs.
|
||||
|
||||
| Journal | Lignes | `Fatal` / `Unhandled` / `Critical error` / `Assertion failed` | `Accessed None` (non triés) | Cas rattachés |
|
||||
|---|---|---|---|---|
|
||||
| `COMMUN-23_session_2146.log` | 28 549 | 0 | 10 lignes (8 réelles) | .1 à .7 |
|
||||
|
||||
| Cas | Motif | Attendu | Relevé |
|
||||
|---|---|---|---|
|
||||
| .1 | `onglets poses sur … (ecran titre)` ; Couleur, Video, Modules | 1 ; 1 chacune, même `<n>` | 1 (l. 1056) ; 1 chacune (l. 976 à 978), `…482350` |
|
||||
| .2 | `onglets poses sur … (partie)` ; `already has a parent` | 1 ; 0 | 1 pour `…463772` (l. 4292) ; 0 |
|
||||
| .3 | `retires de` puis `poses sur … (partie)` ; une ligne par famille et instance | nom nouveau à chaque fois | 4 instances `(partie)`, 4 noms différents ; 18 lignes pour 6 instances |
|
||||
| .4 | `poses sur … (ecran titre)` avec `<m>` ≠ premier titre | 1, nom différent | **0** ligne ; Couleur, Modules, Video sur `…441492` (nom différent) |
|
||||
| .5 | sans objet | constat visuel | — |
|
||||
| .6 | `STATE PlayerCharacter … meshZ=` ; `M-Z :` ; `HeelHeight=?` | −90 + 12 × HeelHeight avant et après le lever ; 0 ; 0 | −80,4 (241), −88,0 (48), −90,0 (198) ; 0 ; 0 |
|
||||
| .7 a | `Fatal…` | 0 | 0 |
|
||||
| .7 b | `Clavier : 51 actions` | 51 au départ | 51 (l. 879) |
|
||||
| .7 c | `\[LPCity\] EAU CentralLondon : masque 59 centres` ; `epargnees 0` | au moins 1 ; 0 | 2 lignes (l. 4056, 9142) ; `epargnees 0` aux deux |
|
||||
|
||||
Build (`COMMUN-23-BUILD.md`, `BOSS-JOURNAL.md` l. 1037) : UAT code 0 en 119 s, CheckPackage PASS. Délai de 0,5 s de W7 : relevé au journal seulement (pas de verdict de temps de trame, comme prévu par la fiche).
|
||||
|
||||
## 6. Suite
|
||||
|
||||
Constats établis pendant et après l'essai :
|
||||
- **SET1** : les onglets des réglages se posent sur l'instance du menu à l'écran, au titre et en partie, à chaque nouvelle instance ; l'ancienne est retirée (« onglets retires de … ») ; les lignes de couleur, de vidéo et de contrôle des mods suivent la même instance ; la vitesse de caméra se conserve. Demande de l'utilisateur honorée au niveau du comportement (l'ancien panneau de réglages du menu du jeu remplacé par celui du menu principal).
|
||||
- **FIX1 M-Z / talons** : le joueur en talons reste debout à meshZ −80,4 (= −90 + 12 × 0,8), aucune ligne `M-Z :` ; la régression « pieds enfoncés » (FIX1-MES) n'est plus observée.
|
||||
- **FIX1-F8a** : le glissé du couple fonctionne, 0 erreur grave.
|
||||
- **Non-régressions** : menu Clavier, Londres (59 centres masqués).
|
||||
|
||||
Suites par lot :
|
||||
|
||||
| Lot | Suite | Qui décide ou agit |
|
||||
|---|---|---|
|
||||
| Journal | À verser : **CHG-383** (FIX1-F8a), **CHG-384** (FIX1 M-Z et talons, deux temps), **CHG-385** (SET1) ; réservés à `NUMEROS.md` (verrou 249) ; versés par la fiche DOC-20261020-VERS5 | DOC de versement, sous jeton |
|
||||
| Gardien | Vague 11 : fichiers partagés et fichiers de lot ; le journal de jeu de COMMUN-23 n'est pas au ticket | Big Boss (lance la vague), gardien |
|
||||
| STM1 | Blocs gris de la Tamise (volumes de la carte), second passage du masque à 0 instance (S5), en build 2 | session STM1 |
|
||||
| FIX1 | Lévitation de PNJ (HeelHeight surestimé selon la chaussure, données), F7b (posture après « regarder »), `currentAnimation` jamais effacé après le lever : build 2 ; `meshZ=-88,0` à expliquer | session FIX1 |
|
||||
| SET1 | Ouverture du panneau au titre après retour (cas .4, voir « Incertain »), puis REL2 | session SET1 |
|
||||
|
||||
Aucune décision n'est prise par ce bilan.
|
||||
|
||||
## Annexe : constat de la séance FIX1-MES (COM22, 2026-10-20 de 20:37 à 20:52)
|
||||
|
||||
Sources : `etat\REL\FIX1\FIX1-MES.md` (protocole de la séance, 11 cas, build COMMUN-22 : exe `e2ba7dec63d479974394e2cffd1efc19`, F8a + trace M-Z enrichie) et les lignes de `BOSS-JOURNAL.md` l. 1022 à 1028 (20:37 à 20:51). **Aucun journal de la séance COM22 relu par ce bilan** : les valeurs citées viennent des lignes du journal de Big Boss, qui les a tirées du journal de jeu de COM22 (non copié ici). Rappel : `FIX1-MES.md` ne contient pas de verdicts (protocole seul).
|
||||
|
||||
| Heure | Source | Constat |
|
||||
|---|---|---|
|
||||
| 20:37 | l. 1022 | le PowerShell de l'utilisateur plante au démarrage (avis de mise à jour, largeur négative), à répétition ; jeu COM22 lancé par Big Boss avec `-LPPersonsLog=2` |
|
||||
| 20:44 | l. 1023 | captures 23 à 25 (talons debout, assis, levé) ; journal : M-Z ramène le joueur en talons de −80,4 (= −90 + 12 × HeelHeight, HeelHeight = 0,8) à −90 ; debout ensuite meshZ −90 ; capture 25 : semelles cachées, pieds dans le parquet. **F8b établi** : l'écart relevé était la compensation normale des talons ; la correction C++ M-Z l'annule et enfonce les pieds d'environ 9,6 cm (régression de M-Z). Constat annexe **F7b** : `currentAnimation` reste sur une animation d'assise après le lever |
|
||||
| 20:45 | l. 1024 | capture 26, citation « pnj en lévitation » (PNJ en talons moyens, debout) ; journal : PNJ debout à meshZ −81,6 (HeelHeight 0,7) et −85,2 (0,4), sans ligne M-Z. Second effet : la compensation de talons du Blueprint dépasse la hauteur réelle de certaines chaussures (donnée HeelHeight par chaussure ; antériorité 5.5 à vérifier), distinct de la régression M-Z |
|
||||
| 20:48 | l. 1025 | FIX1-MES.9, citation « 9 un peu penché et tête toutné » (après l'action « regarder ») : **F7b reproduit** |
|
||||
| 20:49 | l. 1026 | FIX1-MES.10, citation « 10 oui » (posture normale après être sorti et avoir marché) : F7b, posture résiduelle effacée par le déplacement ; effet visible mais passager |
|
||||
| 20:50 | l. 1027 | FIX1-MES.11, citation « 11 normal je pense » ; séance close. **Constat** : F8b = régression M-Z (pieds en talons enfoncés de 12 × HeelHeight, joueur après le lever) + lévitation de PNJ par HeelHeight surestimé selon la chaussure (données, build 2) ; F7b = posture penchée et tête tournée après « regarder », non reproduite au 2e essai, effacée par un déplacement ; `currentAnimation` jamais effacé après le lever (variable non fiable) ; F7b en build 2 |
|
||||
| 20:51 | l. 1028 | citation « approuvé » (correction de M-Z en build 1) : GO FIX1-MZ2 (M-Z vise −90 + 12 × HeelHeight) ; suite : COMMUN-23.6 PASS |
|
||||
|
||||
F8b est **établi** (régression de M-Z, corrigée par MZ2 et vue en COMMUN-23.6) ; **F7b est passager** (effacé par un déplacement) et reste en build 2.
|
||||
|
||||
## Établi / estimé / incertain
|
||||
|
||||
- **Établi** : tous les verdicts et citations (`BOSS-JOURNAL.md` l. 1035 à 1046, relues) ; les comptes et lignes par motif (Grep sur la copie, relue après la fermeture du jeu) : un lancement, 0 erreur grave, 0 `M-Z :`, 0 `already has a parent`, 6 instances de menu avec chacune les trois familles, 5 `onglets poses` (1 titre, 4 partie), 487 relevés du joueur, séries de `meshZ=` ; MD5, taille et lignes de la copie (`md5sum`, `wc -lc`) ; MD5 des sept sources (`md5sum`) conformes ; la fermeture du jeu à 22:03:19 (dernière ligne).
|
||||
- **Estimé** : l'heure par cas = heure du rapport dans le journal de Big Boss ; l'attribution des séries de `meshZ=` aux gestes de la fiche (le journal ne porte pas les gestes, seulement des séries ; les heures de rapport 21:53 à 22:03 ne se calent pas sur les heures UTC + 2 du journal : p. ex. « 4 ok » à 21:59 alors que le retour au titre est à 22:03:10 locale) ; la nature des blocs gris (volumes de la carte).
|
||||
- **Incertain** : (1) **cas .4** : la ligne `onglets poses sur … (ecran titre)` pour le second titre manque au journal (dernière instance `…441492`, lignes Couleur/Modules/Video à 22:03:10 locale, fermeture à 22:03:19) ; l'utilisateur dit « 4 ok » avant la fin (l. 1043 à 21:59) : écart d'heure non expliqué, verdict gardé comme rapporté ; essai qui trancherait : rejouer .4 en une session et relever la ligne. (2) **meshZ = −88,0 du joueur** : 48 relevés (20:00:52 à 20:02:28 UTC), hors grille des talons, déjà noté par `FIX1-MES.md` § 4 (7 cas sur 18 aux journaux antérieurs, chemin d'écriture inconnu) ; non couvert par un cas, non expliqué ici. (3) **.6 c)** (PNJ à talons) et les sous-parties de .7 : « 6ok » et « 7 ok » englobent tout, aucun détail par sous-partie. (4) le contenu des captures 31 et 32 (décrit par le journal de Big Boss, non revu). (5) la nature des `Accessed None` et des `LogPlayerController: Error` ; les parties du journal hors motifs (non lues ligne à ligne). (6) l'annexe : le journal de jeu de COM22 n'est pas copié ni relu ici.
|
||||
- Non fait par ce bilan (consigne) : aucune ligne de brouillon ni d'IMPL écrite ; `EssaiJournal.ps1` non lancé.
|
||||
|
||||
## Fichiers à commiter
|
||||
- `Docs/Migration/etat/BOSS/COMMUN-23-BILAN.md` (A).
|
||||
- `Docs/Migration/etat/BOSS/COMMUN-23/COMMUN-23_session_2146.log` : **local, non commité** (comme COMMUN-17 à COMMUN-21) ; 5 272 268 octets, MD5 `f3450727de944b0c45bc6d670d795a28` ; pas dans le ticket.
|
||||
|
||||
PubCheck : voir le compte rendu de la fiche DOC-20261020-VERS5 (relancé sur ce fichier après écriture).
|
||||
|
||||
Tours : 10 / 40
|
||||
126
Docs/Migration/etat/BOSS/COMMUN-23-TESTS.md
Normal file
126
Docs/Migration/etat/BOSS/COMMUN-23-TESTS.md
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
Fiche COMMUN-23-FIT — Niveau N1 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-writer (rôle A-DOC) — Skills sk-protocol, lp-doc, lp-lot
|
||||
# COMMUN-23-TESTS : fiche de tests commune de la build Development COMMUN-23 (SET1 réglages en partie, M-Z talons, F8a) (2026-10-20)
|
||||
|
||||
Demande de Big Boss (`local_104ff22d`), 2026-10-20, sur ordre de l'utilisateur : « Oui, lance la build Development COMMUN-23 (SET1 réglages en partie, M-Z talons, F8a) et prépare le cahier de tests. » Cette fiche reprend `etat\REL\SET1\SET1-V1-IMPL.md` (§ 5 V1 à V10, § 10), `SET1-V1b-IMPL.md` (§ 5 W1 à W9), `etat\REL\FIX1\FIX1-MZ2-IMPL.md` (§ 5), `FIX1-MES.md` (constat de la séance : talons enfoncés au lever) et `FIX1-F8a-IMPL.md`. Constat de départ côté SET1 (captures de l'utilisateur, avant correctif) : en partie, l'ancienne liste longue des réglages s'affichait, puis était remplacée par les onglets au bout d'environ 30 s, avec une superposition. Fiche **prête** : § 1 (MD5, heure) à compléter par Big Boss à la remise de la build. Rédigée sans copie UE, sans MCP, sans lancer le jeu. Aucun contenu de jeu : chaque action est décrite par sa fonction (doc 27). Forme reprise de `COMMUN-21-TESTS.md`.
|
||||
|
||||
**Hors fiche** : E9 de F6 et la redirection des sauvegardes (COMMUN-21) ; la branche « pièce cachée » ; la correction de la page Keyboard au-delà de son affichage ; F7b (animation « look », séance FIX1-MES) ; mesure du délai de 0,5 s de W7 (relevé au journal seulement, pas de verdict de temps de trame).
|
||||
|
||||
## 1. Build testé
|
||||
|
||||
| Élément | Valeur |
|
||||
|---|---|
|
||||
| Chemin de la build | `D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\` (lancer `Windows\LifePlay.exe`) ; confirmé par Big Boss à la remise |
|
||||
| Exe | `Windows\LifePlay\Binaries\Win64\LifePlay.exe` |
|
||||
| MD5 de l'exe | `0f7b0a39eb48753d3b6bf436f43032a0` (identique à `Binaries\Win64\LifePlay.exe`, compilation SET1-V1b), 335 855 104 octets |
|
||||
| Date de génération | exe lié le 2026-10-20 à 21:37:17 ; paquet `BuildDebug.ps1 -SkipBuild` lancé à 21:43:16, UAT code 0 en 119 s, CheckPackage PASS, 0 paquet recuit ; journal `Saved\Logs\portage\BuildDebug_Development_20261020-214316.log` |
|
||||
| Configuration | Development, commune à plusieurs lots |
|
||||
| Base | HEAD du dépôt + sources non commitées de SET1 (V1 et V1b) et de FIX1 (MZ2, F8a) |
|
||||
|
||||
MD5 des sources attendus (relevés dans les livrables amont) :
|
||||
- `LPSettingsSubsystem.cpp` `6277a8fc139c05dc10e302f88de0f8d9`, `LPSettingsSubsystem.h` `138350efe8473c430db984db63c8feac`, `LPColorGradeSubsystem.cpp` `5be400543166b6de7a4a88f6097a9d93`, `LPVideoQualitySubsystem.cpp` `c3055197030bdbbce813df4cc6d7cd63`, `LPModInfoSubsystem.cpp` `98206e688308e908b04ae15cf408e1bb` (`SET1-V1b-IMPL.md` § 9) ;
|
||||
- `LPDirectControlSubsystem.cpp` `86ef519e880989941e033edeadda7c26` (`FIX1-MZ2-IMPL.md` § 1) ;
|
||||
- `LPCameraModeSubsystem.cpp` `976bf0a458b87f9aecf974fcec3209f0` (`FIX1-F8a-IMPL.md` § 1) ;
|
||||
- ces MD5 sont ceux des livrables amont, à la date de leurs fiches : si un fichier a bougé depuis, seul le relevé de Big Boss fait foi.
|
||||
|
||||
Lots et correctifs couverts :
|
||||
- **SET1-V1 / V1b** : les onglets des réglages (General, Audio, Video, Keyboard, Lewd, Misc) et les lignes de couleur, de vidéo et de contrôle des mods se posent sur l'instance du menu qui est **à l'écran**, plus sur la première liste trouvée en mémoire (cause établie : une instance neuve du menu à chaque ouverture en partie, les anciennes restent en mémoire jusqu'au ramasse-miettes). Compilé à 0 erreur, 0 avertissement ; **jamais vu en jeu**.
|
||||
- **FIX1-MZ2** : la correction M-Z (maillage relevé au lever) vise −90 + 12 × HeelHeight au lieu de −90 fixe ; en talons (−80,4 pour 0,8) le maillage est déjà à sa hauteur voulue et M-Z ne se déclenche plus. Valeurs calculées sur les journaux de COM22, **jamais vues en jeu**.
|
||||
- **FIX1-F8a** : initialisation de `Aim` dans `TickCoupleMouse` (avertissement C4701) ; logique inchangée par construction, aucune exécution (`FIX1-F8a-IMPL.md` C1).
|
||||
|
||||
## 2. Faisabilité
|
||||
|
||||
Machine calme : réserve « mesure » non requise.
|
||||
|
||||
### 2.1 Lignes de lancement
|
||||
|
||||
Le PowerShell de l'utilisateur plante au démarrage : donner les deux formes. Elles sont équivalentes.
|
||||
|
||||
Forme `cmd` (sans `&`), jeu lancé **sans** argument (cas 1 à 5 et 7) :
|
||||
```cmd
|
||||
"D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay.exe"
|
||||
```
|
||||
Forme PowerShell (avec `&`) :
|
||||
```powershell
|
||||
& "D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay.exe"
|
||||
```
|
||||
|
||||
Forme `cmd` avec le relevé des personnages, **cas 6** (un relevé toutes les 2 s au journal) :
|
||||
```cmd
|
||||
"D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay.exe" -LPPersonsLog=2
|
||||
```
|
||||
Forme PowerShell :
|
||||
```powershell
|
||||
& "D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay.exe" -LPPersonsLog=2
|
||||
```
|
||||
Après le chargement, la ligne `LPDebug persons : releve toutes les 2 s` doit être au journal (`LPDebugSubsystem.cpp:649`, cité par `FIX1-MES.md` § 1) ; absente, l'argument n'a pas été pris : arrêter et le dire.
|
||||
|
||||
### 2.2 Journal et motifs
|
||||
|
||||
« Journal » = `D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay\Saved\Logs\LifePlay.log` du lancement jugé (le jeu en garde un exemplaire horodaté à chaque lancement). Préfixe `LogLifePlay: Display:`. Motifs exacts, lus dans le code :
|
||||
|
||||
| Motif (texte exact) | Fichier : ligne | Quand |
|
||||
|---|---|---|
|
||||
| `Reglages : onglets General, Audio, Video, Keyboard, Lewd, Misc` | `LPSettingsSubsystem.cpp:938` | à chaque création de barre d'onglets |
|
||||
| `Reglages : onglets poses sur <MainMenu_C_n> (ecran titre)` ou `(partie)` | `LPSettingsSubsystem.cpp:940` | juste après la précédente |
|
||||
| `Reglages : onglets retires de <MainMenu_C_k> (instance quittee)` | `LPSettingsSubsystem.cpp:180` | au changement d'instance, avant les deux précédentes |
|
||||
| `Reglages : entree Settings ajoutee sur l'ecran titre` ; `Reglages : Settings place apres Mod Manager` | `LPSettingsSubsystem.cpp:791`, `:857` | création du bouton Settings de l'écran titre |
|
||||
| `Couleur : reglages de couleur ajoutes sur <MainMenu_C_n>` | `LPColorGradeSubsystem.cpp:314` | les 5 lignes de couleur viennent d'être ajoutées à la liste de cette instance |
|
||||
| `Video : controles ajoutes avant les reglages de couleur (sur <MainMenu_C_n>)` | `LPVideoQualitySubsystem.cpp:595` | les lignes de vidéo et Recommended viennent d'être ajoutées |
|
||||
| `Modules : cases de controle des mods ajoutees a Settings > Misc (moteur a, version min b, version max c) sur <MainMenu_C_n>` | `LPModInfoSubsystem.cpp:303` | les 3 cases de contrôle des mods viennent d'être ajoutées |
|
||||
| `M-Z : <acteur> maillage relatif Z <avant> -> <cible>[ (talons)] (gabarit <classe>), debout sans meuble ; HeelHeight=<h> ; currentAnimation=<nom> ; -90+12*HeelHeight=<z>` | `LPDirectControlSubsystem.cpp:1268` | une correction M-Z |
|
||||
| `LPDebug persons : STATE <acteur> coll=… meshZ=… anim=… currentAnimation=…` | `LPDebugSubsystem.cpp:414`, `:580` | un relevé toutes les 2 s avec `-LPPersonsLog=2` |
|
||||
|
||||
Relevé commun des réglages (commande prête, à lancer après chaque lancement) :
|
||||
```powershell
|
||||
Select-String -Path "D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay\Saved\Logs\LifePlay.log" -Pattern 'onglets (poses|retires)','reglages de couleur ajoutes sur','controles ajoutes avant','cases de controle des mods'
|
||||
```
|
||||
Rapprocher ensuite les noms `MainMenu_C_<n>` : pour une instance donnée, les quatre familles de lignes portent le **même** `<n>` (`SET1-V1b-IMPL.md` § 10).
|
||||
|
||||
Relevé commun des personnages (cas 6) :
|
||||
```powershell
|
||||
$J = "D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay\Saved\Logs\LifePlay.log"
|
||||
Select-String -Path $J -Pattern 'LPDebug persons : STATE PlayerCharacter' | Select-Object LineNumber, Line
|
||||
Select-String -Path $J -Pattern 'M-Z :'
|
||||
```
|
||||
|
||||
| Cas | Fonction ou réglage dans la build ? | Dépend d'un travail non fini ou d'une observation |
|
||||
|---|---|---|
|
||||
| .1 à .5 (SET1) | oui (V1 et V1b, compilées à 0 erreur) | jamais vu en jeu ; `IsInViewport()` vrai pour l'instance de l'écran titre non observé (V6) : si faux, aucun onglet au titre |
|
||||
| .6 (M-Z) | oui (MZ2, compilée à 0 erreur) | jamais vu en jeu ; demande une tenue à talons (`HeelHeight` > 0), une tenue sans talons, un siège |
|
||||
| .7 (non-régressions) | oui | F8a jamais exécutée ; menu Clavier et Tamise : voir COMMUN-21 et COMMUN-20 |
|
||||
|
||||
## 3. Cas
|
||||
|
||||
Contrôle automatique : motif cherché dans le journal de jeu par Big Boss (lancé avant la remise par `Tools\EssaiJournal.ps1` quand il existe). Verdict, Découvreur et Heure restent vides : le BILAN les remplit. « Onglets tout de suite » = les onglets sont visibles dès l'ouverture, **sans** liste longue, **sans** superposition et **sans** attente d'environ 30 s.
|
||||
|
||||
| Cas | Lot | Correctif (CHG / ERR / ticket) | Action de l'utilisateur | Attendu | Contrôle automatique du journal | Verdict | Découvreur | Heure |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| COMMUN-23.1 | SET1 | SET1-V1 (V1, V4 partiel, V6), SET1-V1b (W3) | Lancer le jeu (ligne § 2.1, sans argument) ; sur l'**écran titre**, cliquer **Settings** | Onglets General, Audio, Video, Keyboard, Lewd, Misc **tout de suite** ; onglet **Video** complet (qualité globale, ombres, textures, effets, anticrénelage, Recommended, puis les cinq réglages de couleur) ; onglet **Misc** complet (les trois cases de contrôle des mods) | `onglets poses sur MainMenu_C_<n> (ecran titre)` : 1 ligne ; `reglages de couleur ajoutes sur`, `controles ajoutes avant`, `cases de controle des mods` : 1 ligne chacune, avec le **même** `<n>` ; symptôme de V6 : aucune de ces lignes au titre | | | |
|
||||
| COMMUN-23.2 | SET1 | SET1-V1 (V2, V7, V8), SET1-V1b (W1, W9) | **Nouvelle partie** ou Continuer ; en partie, **Échap**, puis **Settings** (première ouverture) ; parcourir **Video**, **Misc** et **Keyboard** | Onglets **tout de suite**, sans liste longue ni superposition, sans attente de 30 s ; **Video** et **Misc** complets (comme .1) ; **Keyboard** s'affiche (la page des touches est présente) | `onglets poses sur MainMenu_C_<n> (partie)` : 1 ligne ; les trois lignes Couleur, Video, Modules avec le même `<n>` ; écart entre `onglets poses` et ces trois lignes ≤ environ 0,5 s (W7) ; motif `already has a parent` : 0 | | | |
|
||||
| COMMUN-23.3 | SET1 | SET1-V1 (V3, V9, V10), SET1-V1b (W2, W5, W6, W8) | Fermer les réglages (Back), les **rouvrir**, recommencer **2 ou 3 fois** en partie (chaque ouverture crée une instance neuve) ; à chaque fois regarder Video, Misc, Keyboard ; sur **une** ouverture, ouvrir les réglages, **Back**, rouvrir sans quitter l'écran de pause | Onglets **tout de suite** à chaque ouverture, sans liste longue ni superposition ; Video et Misc complets ; curseurs et afficheurs de valeur Video et couleur à leur valeur en cours (pas la valeur par défaut) ; un curseur déplacé met à jour **son** afficheur ; cases ×2 et style sombre sur la nouvelle instance | à chaque nouvelle ouverture : `onglets retires de <ancienne>` puis `onglets poses sur <nouvelle> (partie)`, `<n>` **nouveau** à chaque fois, repris par les trois lignes Couleur, Video, Modules ; une seule ligne par famille et par instance ; réouverture sur la même instance : **aucune** nouvelle ligne de ces familles | | | |
|
||||
| COMMUN-23.4 | SET1 | SET1-V1 (V4, V5), SET1-V1b (W4) | Depuis la partie, **retourner au titre** ; sur le nouvel écran titre, cliquer **Settings** | Bouton Settings présent dès l'affichage du nouvel écran titre ; réglages ouverts avec les onglets **tout de suite** ; Video et Misc complets | `onglets poses sur MainMenu_C_<m> (ecran titre)` avec `<m>` **différent** de celui du premier titre (.1) ; étiquette `(ecran titre)` exacte (pas `(partie)`) ; trois lignes Couleur, Video, Modules avec `<m>` | | | |
|
||||
| COMMUN-23.5 | SET1 | SET1-V1 (V1 à V3, persistance) ; réglage de caméra 1 à 7, défaut 3 (`SET1-PRE.md:91`) | En partie, ouvrir Settings, changer la **vitesse de caméra** (Camera Speed) à une valeur qui n'est pas la valeur d'origine (**noter l'ancienne et la nouvelle**) ; fermer les réglages, les **rouvrir** ; puis, si le temps le permet, retourner au titre et rouvrir Settings | La nouvelle valeur est **conservée** à la réouverture (même instance ou instance neuve) ; la caméra réagit à la nouvelle vitesse | sans objet : constat visuel (aucune ligne de journal propre à ce réglage dans les sources relues) ; en cas de doute, rapprocher des lignes `onglets poses` de la réouverture | | | |
|
||||
| COMMUN-23.6 | FIX1 | FIX1-MZ2 (`FIX1-MZ2-IMPL.md` § 5 points 2 à 6) ; constat `FIX1-MES.md` | Lancer avec la ligne **`-LPPersonsLog=2`** (§ 2.1). **a)** Joueur **en talons** (`HeelHeight` > 0) : noter l'heure, **s'asseoir** sur un siège, rester 10 s, **se lever**, rester debout immobile 10 s, regarder les pieds. **b)** Même séance **sans talons** (tenue plate). **c)** Observer si un personnage non joueur à talons s'assoit et se lève (facultatif) | **a)** Après le lever, pieds **sur le sol** (pas enfoncés, pas suspendus) ; **b)** inchangé par rapport à avant : pieds au sol ; **c)** idem a) | **a)** `STATE PlayerCharacter … meshZ=` égal à −90 + 12 × HeelHeight (−80,4 pour 0,8 ; −85,2 pour 0,4) **avant et après** le lever ; **0** ligne `M-Z :` visant le joueur ; **b)** `meshZ=-90.0`, 0 ligne `M-Z :` ; si une ligne sort sans talons, elle porte `-> -90.0 (gabarit Person_C)` **sans** `(talons)` et `HeelHeight=0.000` ; **toute** ligne `M-Z :` : le `<avant>` est différent de `<cible>` (la ligne **ne sort plus** pour un personnage déjà à sa cible) ; aucune ligne avec `HeelHeight=?` ; `Fatal\|Unhandled\|Critical error\|Assertion failed` : 0 | | | |
|
||||
| COMMUN-23.7 | FIX1 / KEY2 / STM1 | FIX1-F8a (`FIX1-F8a-IMPL.md` C1) ; non-régressions de COMMUN-21 (.12) et COMMUN-20 | **a)** En scène, **glisser** le couple à la souris (saisir, déplacer, relâcher), plusieurs fois. **b)** Ouvrir le menu **Clavier** et faire défiler : noter l'ordre des titres de section. **c)** Charger la carte de **Londres**, suivre la Tamise en vue de dessus | **a)** Le couple se déplace avec le curseur, se pose au relâchement, sans saut ni blocage (logique inchangée par construction) ; **b)** 9 sections dans cet ordre : Movement, Camera, Map & World, Couple (scene), Actions & Interaction, Menus, Time, Favorites, System ; aucune section « Other » ; **c)** plus aucune maison générique sur la Tamise, ponts et quais intacts | **a)** `Fatal\|Unhandled\|Critical error\|Assertion failed` : 0 ; **b)** sans objet : constat visuel (51 actions au départ : `Clavier : 51 actions et 17 axes relus`) ; **c)** `\[LPCity\] EAU CentralLondon : masque 59 centres` : au moins 1, `epargnees 0` sur la dernière ligne | | | |
|
||||
|
||||
Décompte : **7 cas** : SET1 5 (.1 à .5), M-Z 1 (.6, trois sous-parties a, b, c dont c facultative), non-régressions 1 (.7, trois sous-parties a, b, c).
|
||||
|
||||
Relevés communs au journal (hors cas) : `Fatal|Unhandled|Critical error|Assertion failed` = 0 ; `Accessed None` : aucun nouveau ; avertissements Slate (`already has a parent`, `ensure`) : 0 ; toute ligne `Reglages :` de la session recopiée au BILAN.
|
||||
|
||||
## 4. Cas témoins
|
||||
|
||||
| Cas | VAL statique (chemin) | Verdict statique |
|
||||
|---|---|---|
|
||||
| COMMUN-23.1 à .5 | `Docs\Migration\etat\REL\SET1\SET1-V1-IMPL.md` (§ 5, V1 à V10) et `SET1-V1b-IMPL.md` (§ 5, W1 à W9) | IMPL seulement : compilation à 0 erreur, **aucune VAL** de comportement, preuve « à rejouer sur un build Development » ; V1 à V10 et W1 à W9 **reportés**, aucun essai en jeu |
|
||||
| COMMUN-23.6 | `Docs\Migration\etat\REL\FIX1\FIX1-MZ2-IMPL.md` (§ 5, points 2 à 6) et `FIX1-MES.md` | IMPL seulement : comportement **calculé** sur les journaux de COM22, jamais observé |
|
||||
| COMMUN-23.7 a | `Docs\Migration\etat\REL\FIX1\FIX1-F8a-IMPL.md` (C1) | build seule : 0 avertissement, 0 erreur ; aucune exécution du glissé |
|
||||
| COMMUN-23.7 b, c | `COMMUN-21-TESTS.md` (.12 et .13) et son BILAN | à relever dans le BILAN de COMMUN-21 |
|
||||
|
||||
Aucune VAL de comportement n'existe pour les cas .1 à .6 : aucun verdict statique ne vaut pour un cas de jeu.
|
||||
|
||||
PubCheck : à lancer par l'auteur après écriture (`pwsh -NoProfile -File Tools/PubCheck.ps1 -Fichiers Docs/Migration/etat/BOSS/COMMUN-23-TESTS.md -Depot "D:/Game/LifePlay-master 5.8"`, stdin sur `/dev/null`) ; résultat cité au compte rendu.
|
||||
|
||||
Tours : 5 / 40
|
||||
|
||||
## Fichiers à commiter
|
||||
- `Docs/Migration/etat/BOSS/COMMUN-23-TESTS.md` (A).
|
||||
105
Docs/Migration/etat/BOSS/COMMUN-23/COMMUN-23-BUILD.md
Normal file
105
Docs/Migration/etat/BOSS/COMMUN-23/COMMUN-23-BUILD.md
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
Fiche BUILD-COM23 — Niveau N0 — Modèle prévu non précisé dans la fiche | utilisé claude-haiku-5-5 (Haiku 5.5) — Agent lp-builder — Skills sk-protocol, sk-windows-shell, lp-build
|
||||
# COMMUN-23-BUILD : build Development COMMUN-23 (SET1 réglages en partie, M-Z talons, F8a) empaquetée (2026-10-20)
|
||||
|
||||
## 1. Commande exacte
|
||||
|
||||
Deux commandes, dans cet ordre, en arrière-plan (sorties brutes dans les journaux cités en section 7) :
|
||||
|
||||
1. `pwsh -NoProfile -File "D:/Game/LifePlay-master 5.8/Tools/Build.ps1" -Lot COMMUN-23 -EtatDir "D:/Game/LifePlay-master 5.8/Docs/Migration/etat/BOSS/COMMUN-23"` (21:42:55, tâche b8tqu5s0y).
|
||||
Build LifePlayEditor Win64 Development (`Build.bat LifePlayEditor Win64 Development "-Project=D:\Game\LifePlay-master 5.8\LifePlay.uproject" -WaitMutex -NoHotReloadFromIDE`). Sortie : `Makefile : Target is up to date`, 0 unité.
|
||||
2. `pwsh -NoProfile -File "D:/Game/LifePlay-master 5.8/Tools/BuildDebug.ps1" -Config Development -SkipBuild -ArchiveDir "D:/Game/LifePlay_Build_5.8_Development_COM23"` (21:43:16, tâche bfk74yl7v).
|
||||
Commande UAT écrite par le script (sortie brute, journal l. 1) : `RunUAT.bat BuildCookRun -project="D:\Game\LifePlay-master 5.8\LifePlay.uproject" -platform=Win64 -clientconfig=Development -cook -iterate -stage -pak -iostore -compressed -archive -archivedirectory="D:/Game/LifePlay_Build_5.8_Development_COM23" -unattended -utf8output -nop4`.
|
||||
|
||||
Préconditions (établies) : `UeState.ps1 -Kind Editeur,Compilation` : `processus=0 editeur=0 compilation=0 shaders=0 jeu=0` avant le lot. Archive `D:\Game\LifePlay_Build_5.8_Development_COM23` : « Directory does not exist » (Glob). Aucun dossier de build existant touché. Aucune suppression, aucun déplacement, aucune commande git.
|
||||
|
||||
Écarts à la fiche sur la commande : aucun.
|
||||
|
||||
## 2. Code de sortie
|
||||
|
||||
- Build éditeur (étape 1) : `code=0 duree=2s erreurs=0 avertissements=0 autres=20 unites=0` (sortie de `Build.ps1`, tâche b8tqu5s0y). Résumé : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\BOSS\COMMUN-23\COMMUN-23_Build_20261020-214255.txt`.
|
||||
- UAT (étape 2) : `UAT code=0 duree=119s journal=D:\Game\LifePlay-master 5.8\Saved\Logs\portage\BuildDebug_Development_20261020-214316.log` (sortie de `BuildDebug.ps1`).
|
||||
- Durée du BuildCookRun : `BuildCookRun time: 116.59 s` (journal l. 754) ; `AutomationTool exiting with ExitCode=0 (Success)` (l. 757).
|
||||
- Décomposition UAT (journal, lignes brutes) : cuisson `Cook command time: 61.03 s` (l. 514) ; UnrealPak `Took 1,42s` (l. 612) et `Took 15,67s` (l. 742) ; archive `Archive command time: 17.70 s` (l. 752).
|
||||
- Durée totale des deux étapes : 2 s (éditeur) + 119 s (UAT).
|
||||
- CheckPackage (sortie brute de l'étape 2) :
|
||||
`exe archive : D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay\Binaries\Win64\LifePlay.exe (2026-10-20 21:37:17, 335855104 o)`
|
||||
`exe du projet : D:\Game\LifePlay-master 5.8\Binaries\Win64\LifePlay.exe (2026-10-20 21:37:17, 335855104 o)`
|
||||
`[1] PASS 0 ...Manifest_NonUFSFiles_Win64.txt` ; `[2] PASS 0 ...Manifest_UFSFiles_Win64.txt` ; `[3] PASS 0 ...LifePlay.exe.rsp` ; `[4] PASS 0 ...LifePlay.target`
|
||||
`Resultat : PASS (code 0)`.
|
||||
|
||||
Cuisson (journal `BuildDebug_Development_20261020-214316.log`, comptes bruts) :
|
||||
- l. 255 : `INCREMENTAL COOK: -legacyiterative was specified and global settings are still valid. Keeping previously cooked packages for platform Windows and cooking only packages that have been modified.`
|
||||
- l. 258 : `LogCook: Display: Keeping 8921. Recooking 0. Removing 0. 0 generated packages to be evaluated for legacyiterative skipping later.`
|
||||
- l. 264 : `LogCook: Display: Cooked packages 8929 Packages Remain 9529 Total 18458` ; l. 269 : `Cooked packages 8929 Packages Remain 0 Total 8929`.
|
||||
- l. 291 : `LogCook: Display: Packages Cooked: 0, Packages Incrementally Skipped: 8921, Packages Skipped by Platform: 8, Total Packages: 8929`. Aucun paquet recuit : la cuisson a réutilisé la précédente (comme COMMUN-22).
|
||||
- Lignes Display l. 266 à 268 : `Package /Game/Heavy/Daz/Anims/MF has a dependency on package /Game/Heavy/Characters/CauM/M_Cau which does not exist.` ; `/Game/Heavy/Daz/BoneMapping_bridget` et `/Game/Heavy/Daz/BoneMapping` dépendant de `/Engine/EngineMeshes/Humanoid`. Mêmes lignes que COMMUN-22 (l. 265 à 267 de ce journal-là) ; comparaison ligne à ligne non faite dans ce lot.
|
||||
- Erreurs de cuisson : la recherche `Error:` ne retourne aucune ligne d'erreur de cuisson (`Grep`, journal ci-dessus) ; deux lignes longues (l. 254 et 497) ont été tronquées par l'outil et n'ont pas été relues : sans conclusion sur leur contenu.
|
||||
- Avertissement `LegacyIterative` : attendu (`lp-build` § 4), non relu en entier (ligne 254 tronquée, voir ci-dessus).
|
||||
|
||||
## 3. Modules recompilés
|
||||
|
||||
Aucun module recompilé dans ce lot. Établi :
|
||||
- Résumé `COMMUN-23_Build_20261020-214255.txt` l. 8 : `Makefile : Target is up to date` ; l. 9 : `Using Unreal Build Accelerator local executor to run 0 action(s)` ; l. 38 : `Unites compilees : 0` ; l. 40 : `DLL liees : 0`.
|
||||
- Binaires du projet (`Get-FileHash -Algorithm MD5`, `Get-Item`, sorties brutes) : `D:\Game\LifePlay-master 5.8\Binaries\Win64\LifePlay.exe` : MD5 `0F7B0A39EB48753D3B6BF436F43032A0`, date `20/10/2026 21:37:17`, 335855104 o.
|
||||
- Exe empaqueté `D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay\Binaries\Win64\LifePlay.exe` : MD5 `0F7B0A39EB48753D3B6BF436F43032A0`, date `20/10/2026 21:37:17`, 335855104 o.
|
||||
- Empreinte attendue par la fiche : `0f7b0a39` (SET1-V1b). Identique, établi.
|
||||
- Écart de date : la fiche indique Binaries à 21:36 (SET1-V1b) ; la date relevée est 21:37:17 pour les deux exe. L'empreinte est identique, donc le contenu est le même ; la cause du décalage de date (copie ou relien par UAT) n'est pas établie.
|
||||
- Non établi : la cible jeu (`LifePlay.exe` côté Game) n'a pas été recompilée par ce lot (hors fiche).
|
||||
|
||||
## 4. Erreurs et avertissements nouveaux
|
||||
|
||||
- Éditeur : `erreurs=0 avertissements=0 autres=20` (`COMMUN-23_Build_20261020-214255.txt`, l. 12 à 14 et l. 16 à 36). Les 20 lignes « autres » sont les `Warning: Plugin 'HyperAIStudio' does not list plugin … as a dependency` attendues pour LifePlayEditor (`lp-build` § 7) : 20 comptées, 20 attendues.
|
||||
- Cuisson : 0 erreur de cuisson relevée (section 2, avec la réserve sur les l. 254 et 497) ; lignes `has a dependency … which does not exist` (l. 266 à 268, Display) : à confirmer (Constats).
|
||||
- Nouveaux avertissements de compilation : aucun (aucune unité compilée).
|
||||
- Comptes par code C et fichier:ligne : sans objet : aucune unité compilée (`Unites compilees : 0`).
|
||||
|
||||
## 5. Toolchain
|
||||
|
||||
Non établi : la ligne `Chaine :` du résumé `COMMUN-23_Build_20261020-214255.txt` (l. 7) est vide, et le journal de compilation ne contient pas de ligne `Using Visual Studio`. Même constat que COMMUN-22. Le MSVC épinglé de référence est `14.50.35717` (`lp-build` § 1). Sans compilation, la chaîne n'a pas été sollicitée ; à ne pas tenir pour vérifiée.
|
||||
|
||||
## 6. Preuve de chargement (addon)
|
||||
|
||||
sans objet : la fiche ne demande pas de preuve d'addon et le jeu n'a pas été lancé.
|
||||
|
||||
## 7. Journal archivé et empreintes
|
||||
|
||||
- Journal de cuisson : `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\BuildDebug_Development_20261020-214316.log`.
|
||||
- Journal de compilation : `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\COMMUN-23_Build_20261020-214255.log`.
|
||||
- Résumé : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\BOSS\COMMUN-23\COMMUN-23_Build_20261020-214255.txt` (chemin fourni par `-EtatDir`).
|
||||
- Archive : `D:\Game\LifePlay_Build_5.8_Development_COM23` (dossier neuf, créé par cette build).
|
||||
- Exe packagé : `D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay\Binaries\Win64\LifePlay.exe` : MD5 `0F7B0A39EB48753D3B6BF436F43032A0`, 21:37:17, 335855104 o.
|
||||
- Binaries du projet : `D:\Game\LifePlay-master 5.8\Binaries\Win64\LifePlay.exe` : MD5 `0F7B0A39EB48753D3B6BF436F43032A0`, 21:37:17.
|
||||
- Paquet : `D:/Game/LifePlay-master 5.8/Saved/StagedBuilds/Windows/LifePlay/Content/Paks/LifePlay-Windows.pak` créé par UnrealPak (`Created pak file`, journal l. 600).
|
||||
|
||||
## Écarts à la fiche
|
||||
|
||||
1. Date de `Binaries\Win64\LifePlay.exe` relevée à 21:37:17, la fiche indique 21:36 ; empreinte MD5 conforme (0F7B0A39), cause de la date non établie (section 3).
|
||||
2. Cible jeu non relancée (`Build.ps1 -Target LifePlay`) : hors fiche.
|
||||
3. Aucune correction, aucune commande git, aucune suppression ni déplacement. Journaux `Saved\Logs\portage` et `Saved\Cooked` hors dépôt suivi.
|
||||
4. PubCheck lancé après l'écriture de ce livrable (voir Constats, point 6).
|
||||
|
||||
## Constats
|
||||
|
||||
1. Établi : build Development COMMUN-23 empaquetée. Code 0 à chaque étape (`Build.ps1` code=0 ; UAT code=0, `AutomationTool exiting with ExitCode=0 (Success)`), CheckPackage `Resultat : PASS (code 0)`, archive neuve créée.
|
||||
2. Établi : aucune recompilation (`Target is up to date`, 0 unité). L'exe packagé est identique à l'exe du projet (MD5 0F7B0A39EB48753D3B6BF436F43032A0) et l'empreinte égale celle de la fiche.
|
||||
3. Point à confirmer : la cible jeu n'a pas été recompilée par ce lot. Essai : `Build.ps1 -Lot COMMUN-23 -Target LifePlay -Config Development -ExtraArgs '-NoUBA'`, à décider par l'orchestrateur.
|
||||
4. Point à confirmer : lignes `has a dependency … which does not exist` (journal l. 266 à 268) sur `/Game/Heavy/Daz/...` et `/Engine/EngineMeshes/Humanoid`. Essai qui tranche : Grep `does not exist` sur les journaux COMMUN-22 et COMMUN-23.
|
||||
5. Cuisson : 0 paquet recuit (`Packages Cooked: 0`) : l'archive reprend la cuisson précédente pour les assets inchangés ; la cuisson des assets modifiés par COMMUN-23 n'a pas été vérifiée asset par asset (non établi).
|
||||
6. Contrôle de publication : `PubCheck` lancé après écriture de ce livrable, résultat rapporté dans le compte rendu de l'agent (pas de modification du livrable après ce contrôle).
|
||||
7. Non mesuré : tests en jeu, preuve de chargement, présence des symboles de SET1 / M-Z / F8a dans le binaire, comptes `Build.ps1 -FromLog`, toolchain en ligne.
|
||||
|
||||
## État de reprise
|
||||
|
||||
sans objet : la fiche est menée à son terme (pas d'arrêt au budget).
|
||||
|
||||
Tours : 10 / 40 (estimé par l'agent ; `python -I -X utf8 Tools/FicheStats.py --lot BUILD-COM23` fait foi)
|
||||
|
||||
## Fichiers à commiter
|
||||
|
||||
- `Docs/Migration/etat/BOSS/COMMUN-23/COMMUN-23-BUILD.md` (A, nouveau).
|
||||
- `Docs/Migration/etat/BOSS/COMMUN-23/COMMUN-23_Build_20261020-214255.txt` (A, généré par `Build.ps1`).
|
||||
Journaux (`Saved\Logs\portage`), archive et `Saved\StagedBuilds` : hors dépôt suivi, non commités. Aucune commande git en écriture.
|
||||
|
||||
## À verser
|
||||
|
||||
aucun
|
||||
122
Docs/Migration/etat/REL/ERR145/ERR145-DIAG.md
Normal file
122
Docs/Migration/etat/REL/ERR145/ERR145-DIAG.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
Fiche ERR145-DIAG — Niveau N3− — Modèle prévu non précisé par la fiche | utilisé claude-opus-5-5 — Agent lp-diag — Skills sk-protocol, ue-cpp-build, lp-commandlets, lp-paths
|
||||
# ERR145-DIAG : C1 assis, le joueur se voit sans tête (2026-10-20)
|
||||
|
||||
Ordonnateur : Big Boss (local_104ff22d). Lecture seule : ni copie UE, ni MCP, ni compilation. Seul fichier écrit : ce livrable.
|
||||
|
||||
## 1. Symptôme et reproduction
|
||||
- Symptôme (établi) : « bug à référencer en C1 quand assis. On se contemple décapité. à voir en build 2 »
|
||||
(`etat/BOSS/BOSS-JOURNAL.md:872`, 2026-10-20 13:08 ; capture non enregistrée, `:873`) ; ERR-145
|
||||
(`Docs/Registre_Erreurs.md:152`) ; `etat/BOSS/COMMUN-17-BILAN.md:65`.
|
||||
- Journal de l'essai (établi, horodatage du journal en UTC, heure locale = UTC + 2 ; 13:08 locale = 11:08 UTC) :
|
||||
`D:\Game\LifePlay_Build_5.8_Development_COM17\Windows\LifePlay\Saved\Logs\LifePlay.log`
|
||||
- l. 1869 (11:04:41) : touche C, `CamC1On=1 C1Hidden=1` ; l. 1874-1894 : C1 debout, souris, tangage jusqu'à -60 ;
|
||||
- l. 1898 (11:05:08) : sortie de C1 (tangage remis à 0) ; l. 1972 (11:05:33) : joueur assis au meuble `_3` ;
|
||||
l. 1975 : menu `Scene_C` ; l. 1978 (11:05:34) : « place `_3` libérée sans marche, joueur posé à gauche à 80 cm du siège » ;
|
||||
- l. 2111 (11:05:40.384) : fin du blocage par `Scene_C` ; l. 2329 (11:05:40.724) : retour en C1 (`C1 souris`,
|
||||
`minuterie RoomCam active=1`), **aucune ligne « Touche C » entre l. 1869 et l. 2472** : la vue C1 est remise par le
|
||||
jeu à la fermeture du menu, joueur **debout** (posé à côté du siège) ;
|
||||
- l. 2387-2388 (11:05:42.397) : le joueur s'assoit au meuble `_20` : « racine Genesis8Female à 128 cm du bassin,
|
||||
**à 104 cm du composant** » ;
|
||||
- l. 2390-2417 (11:05:43 → 11:07:56) : C1 assis, regard vers le bas (tangage -38 à -60) ; l. 2472 (11:08:12) : touche C
|
||||
vers C2. La plainte (13:08 locale) tombe dans cette fenêtre.
|
||||
- Recette de reproduction proposée (non jouée) : en jeu, **debout**, touche C jusqu'à l'indicateur « C1 First person » ;
|
||||
aller s'asseoir sur une chaise (clic) **sans quitter C1** ; regarder autour et vers le bas. Puis, toujours assis, C → C2 → C1.
|
||||
Puis se lever (Z) en C1.
|
||||
|
||||
## 2. Hypothèse testée (une seule)
|
||||
H1 (reformulation précise de l'hypothèse de la fiche) : en C1, la tête est masquée par `HideBoneByName(Mesh, 'neckLower')`
|
||||
et la caméra est recalée à chaque passage de la minuterie sur le milieu des os `lEye` / `rEye`. Or un os masqué sort des
|
||||
os requis et **n'est plus animé** : `lEye` et `rEye` restent dans la pose (en espace composant) qu'ils avaient au moment
|
||||
du masquage. Entré debout en C1 puis assis, le joueur garde une « tête fantôme » à la position debout, la caméra la suit,
|
||||
et le corps assis (déplacé par l'animation de siège, racine à environ 1 m du composant) est vu de l'extérieur, sans tête.
|
||||
|
||||
## 3. Essai et résultat brut
|
||||
Lectures (aucune exécution du jeu ; aucune commande ne modifie de fichier).
|
||||
|
||||
### 3.1 Ce que fait C1 (établi)
|
||||
- Entrée en C1 (`Room.ApplyRoomCamera`, voie C1, `C1Hidden` faux) : attache `FirstPersonSM` à `head`, transformée relative,
|
||||
`SetWorldLocation(FirstPersonSM, 0,5 × (GetSocketLocation(Mesh,'lEye') + GetSocketLocation(Mesh,'rEye')))` calculé
|
||||
**avant** le masquage, détache, `HairSM.SetVisibility(faux)`, `HideBoneByName(PlayerCharacter.Mesh,'neckLower',PBO_None)`,
|
||||
`C1Hidden := vrai`, une image d'attente, `SetViewTargetWithBlend` (`etat/CAM/CAM-B1-IMPL.md:22`, `:87`, `:104-109`).
|
||||
B1d note déjà : « un os masqué sort des os requis et ne bouge plus » (`CAM-B1-IMPL.md:107`).
|
||||
- Si `C1Hidden` est déjà vrai, la voie saute toute remise et va directement à la vue (`etat/CAM/CAM-COMMUN6-DIAG.md:155`).
|
||||
- Minuterie `UpdateRoomCam` (0,016 s) : en C1 avec vue = `PlayerCharacter`, `83.then → 512 K2_SetWorldLocation(FirstPersonSM,
|
||||
milieu de lEye/rEye) → 540 K2_SetWorldRotation` (`etat/CAM/CAM-B2s-IMPL.md:137`, `CAM-B2k-IMPL.md:75-76`, `:102`). La
|
||||
position de la caméra suit donc en permanence les os des yeux… **qui sont sous `neckLower`, donc masqués** (`lEye`, `rEye`
|
||||
sous `head`, sous `neckLower` : `CAM-B1-IMPL.md:110-111`).
|
||||
- `RestoreC1` (sortie de C1 ou vue ≠ joueur) fait `UnHideBoneByName(neckLower)` et `C1Hidden := faux` (`CAM-B1-IMPL.md:29-30`, `:87-88`).
|
||||
- C++ : `LPCameraModeSubsystem.cpp` ne masque rien (aucun `HideBone`, `SetOwnerNoSee`) ; il règle le tangage (`TickC1Pitch`,
|
||||
`:770-806`), remet `C1Hidden` à faux en entrée de scène (`:752-760`) et écrit le témoin C1 (`:1196-1231`).
|
||||
Grep `VisibilityBasedAnimTickOption|AlwaysTickPose` sur `Source` : 0 résultat.
|
||||
|
||||
### 3.2 Moteur 5.8 installé (établi, `D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Engine\Private\`)
|
||||
- `Components/SkeletalMeshComponent.cpp:2255-2258` : `ComputeRequiredBones` appelle `ExcludeHiddenBones` (« Purge invisible
|
||||
bones and their children »).
|
||||
- `Components/SkeletalMeshComponent.cpp:2321-2332` : un os n'est gardé que s'il est `BVS_Visible`, **ou** si
|
||||
`VisibilityBasedAnimTickOption == AlwaysTickPoseAndRefreshBones` ; les autres sont retirés des os requis.
|
||||
- `Components/SkeletalMeshComponent.cpp:2271-2275` puis `SkinnedAsset.cpp:522-536` : l'espace composant n'est recalculé que
|
||||
pour les os de cette liste : les os masqués gardent leur dernière transformée.
|
||||
- `Components/SkinnedMeshComponent.cpp:2433` : une position d'os = transformée en espace composant × `LocalToWorld` (branche
|
||||
avec leader ; branche sans leader estimée identique) : `GetSocketLocation('lEye')` = pose figée × position actuelle du composant.
|
||||
- `Character.cpp:125` : `ACharacter` règle `Mesh->VisibilityBasedAnimTickOption = AlwaysTickPose`, pas `…AndRefreshBones`.
|
||||
- Surcharge dans Person : `rg -a -c 'AlwaysTickPose|VisibilityBasedAnimTickOption'` sur `Content/BPs/Person.uasset`,
|
||||
`Room.uasset`, `FirstPerson.uasset` → `0`, `0`, `0` (sortie : `Person.uasset: 0` / `Room.uasset: 0` / `FirstPerson.uasset: 0`).
|
||||
|
||||
### 3.3 Le témoin C1 ne peut pas voir le défaut (établi)
|
||||
`WitnessC1` mesure la distance caméra ↔ milieu de `LeftEyeSocket` / `RightEyeSocket` du même `Mesh`
|
||||
(`LPCameraModeSubsystem.cpp:1214-1215`) : les mêmes os figés que ceux sur lesquels la minuterie pose la caméra. La distance
|
||||
reste proche de 0 même quand la caméra est à 1 m du corps. Grep `Temoin C1` sur les journaux COM16 à COM23 : 0 ligne
|
||||
(seules lignes trouvées : `unOccupyFnt`, `C1 : tangage … remis a 0`, pile `PlayFntAnim`). L'absence de ligne ne prouve donc rien.
|
||||
|
||||
### 3.4 Même mécanisme déjà vu, attribué à autre chose (établi pour les constats, rapprochement estimé)
|
||||
- ERR-106 (C5-3) : « après être entré assis puis changé de pose, la caméra est dans le buste » ; résidu après B2k « décalage
|
||||
après un lever » (`Registre_Erreurs.md:113`).
|
||||
- ERR-111 : « C1 à côté de la tête après un lever … un cycle C corrige » (`Registre_Erreurs.md:118`). Un cycle C passe par
|
||||
`RestoreC1` (démasque) puis remasque dans la pose nouvelle : c'est exactement ce que prédit H1. B2k (recalage de position)
|
||||
et B2s (orientation) ne pouvaient pas corriger le fond, puisqu'ils relisent les os figés.
|
||||
- ERR-145 est le cas inverse : entré debout, puis assis.
|
||||
|
||||
## 4. Verdict : confirmée sur le mécanisme (estimé fort), non prouvée en jeu
|
||||
- **Établi** : la caméra C1 suit `lEye` / `rEye` à chaque passage (§ 3.1) ; ces os sont masqués en C1 ; le moteur 5.8 retire
|
||||
les os masqués des os requis et ne recalcule plus leur pose sauf `AlwaysTickPoseAndRefreshBones` (§ 3.2) ; le maillage du
|
||||
joueur est en `AlwaysTickPose` (défaut `ACharacter`, aucune surcharge lue dans les assets) ; à 11:05:40 le joueur revient en
|
||||
C1 debout puis s'assoit à 11:05:42 avec une racine à 104 cm du composant (journal COM17 l. 1978, 2329, 2388).
|
||||
- **Estimé** : la tête (et donc la caméra) reste dans la pose debout en espace composant ; le corps, déplacé par l'animation
|
||||
de siège, est vu de dehors et sans tête ; le témoin est aveugle (§ 3.3). Cause d'ERR-145 = os masqués figés.
|
||||
- **Inconnu** : le moment exact de l'entrée en C1 à 11:05:40 (pas de ligne « Touche C », remise par le jeu à la fermeture de
|
||||
`Scene_C`, voie exacte non lue) ; la capture (absente) ; la distance réelle caméra ↔ corps ; l'effet du double tampon des
|
||||
transformées (`bDoubleBufferedComponentSpaceTransforms`) sur la valeur figée (sans effet sur la conclusion, estimé).
|
||||
- Hypothèse concurrente non exclue, H2 : caméra bien aux yeux, mais le tangage vers le bas (nouveau depuis A1, journal l. 2390-2417
|
||||
jusqu'à -60) montre le cou coupé à `neckLower`. Essai qui départage : § 5, point 2 (cycle C assis).
|
||||
|
||||
### Endroit du correctif
|
||||
**C++ (`Source/LifePlay/LPCameraModeSubsystem.cpp`)**, recommandé. Ni GI, ni PC, ni Person : la révision unique de GI n'est pas concernée.
|
||||
|
||||
### Correctifs proposés
|
||||
| Option | Constat traité | Coût | Risque |
|
||||
|---|---|---|---|
|
||||
| **A (recommandée)** C++ : quand la vue est C1 (`LabelC1`), mettre `PlayerCharacter.Mesh.VisibilityBasedAnimTickOption = AlwaysTickPoseAndRefreshBones` (valeur d'origine gardée, remise en sortie de C1, même endroit que `ResetC1PitchOnExit`, `:811-827`) ; les os masqués restent requis et animés (`SkeletalMeshComponent.cpp:2322`), le masquage visuel reste par l'état de visibilité des os | ERR-145, et le fond d'ERR-106 / ERR-111 (lever, rasseoir) | 15 à 25 lignes, une compilation, aucune écriture d'asset | à confirmer en SPEC : le changement d'option doit forcer un recalcul des os requis (`RecalcRequiredBones` ou équivalent, API 5.8 à lire) ; une image de retard possible au passage ; un os masqué non requis est-il bien rendu masqué quand il redevient requis (`SkeletalRender.cpp:477-487`, cité par `CAM-B1e-CART.md:68-72`) |
|
||||
| B Room (MCP) : dans `UpdateRoomCam`, poser la caméra depuis un os visible (parent de `neckLower`) plus un décalage | ERR-145 en partie | ~5 nœuds, instantané Room, VAL BP | décalage homme / femme à calibrer ; regard qui ne suit plus les mouvements de tête de l'animation |
|
||||
| C C++ ou PC : au changement d'`OccupyingFnt` en C1, rejouer `RestoreC1` puis `ApplyRoomCamera` (le cycle C qui corrige déjà) | assis / levé seulement | ~20 lignes C++ (appel d'événements par nom) | une image de transition ; ne couvre pas les autres changements de pose (fin de scène, CharGen) |
|
||||
|
||||
Ajout à toute option : corriger le témoin C1 pour qu'il mesure la caméra contre un os **non masqué** (ex. distance caméra ↔
|
||||
os parent de `neckLower`, attendu 15 à 40 cm), sinon il reste aveugle.
|
||||
|
||||
## 5. Hypothèse suivante proposée, et à quel niveau
|
||||
1. **Preuve en jeu attendue** (build suivant, C++ seulement, avant ou avec l'option A) : ligne de témoin nouvelle, une par
|
||||
seconde en C1 : distance caméra ↔ os visible (`neckLower` parent), `assis=`, racine ↔ composant. Avant correctif, après la
|
||||
recette du § 1 : distance > 60 cm assis (attendu 15-40 cm debout) ; après correctif A : 15-40 cm dans tous les états.
|
||||
2. **Essai qui départage H1 / H2** (sans build, par l'utilisateur) : debout → C1 → s'asseoir : vue décapitée de l'extérieur ;
|
||||
puis, assis, C → C2 → C1 : si la vue revient aux yeux et que le corps n'est plus vu « de dehors », H1 ; si la coupe du cou
|
||||
reste visible en regardant vers le bas, H2 (alors masquer en plus le haut du buste ou borner le tangage bas, N2).
|
||||
3. SPEC de l'option A : N3 (`lp-impl`), lecture de l'API 5.8 de recalcul des os requis avant écriture.
|
||||
|
||||
Tours : 21 / 30
|
||||
|
||||
## Constats
|
||||
- `FIX1-F7-PRE.md` (currentAnimation non vidé au lever) : sans lien établi avec ERR-145 (concerne l'animation « look » et
|
||||
`meshZ` au lever, `FIX1-F7-PRE.md:10`, `:18`).
|
||||
- `KEY2-CART-02.md` : aucune mention de C1 ni de la tête (Grep `C1|tête|neckLower` : 0 ligne).
|
||||
- Dumps `L6f_dump_*` / `CAM-B1-PRE_LPDumpFunction_*` non relus directement : les nœuds de C1 sont cités depuis les livrables
|
||||
CAM qui les ont relus (`CAM-B1-IMPL.md`, `CAM-B2k-IMPL.md`, `CAM-B2s-IMPL.md`, `CAM-B1e-CART.md:61-63`).
|
||||
- Fichiers à commiter : `A Docs/Migration/etat/REL/ERR145/ERR145-DIAG.md` (dépôt du jeu, `ue5.8`).
|
||||
741
Docs/Migration/etat/REL/ERR145/ERR145-SPEC-02.md
Normal file
741
Docs/Migration/etat/REL/ERR145/ERR145-SPEC-02.md
Normal file
|
|
@ -0,0 +1,741 @@
|
|||
Fiche ERR145-SPEC-02 — Niveau N3 — Modèle prévu non précisé par la fiche | utilisé claude-opus-5-5 — Agent lp-impl — Skills sk-protocol, ue-cpp-build, lp-build, lp-ue-compat
|
||||
# ERR145-SPEC-02 : caméra C1 stable — ancre sur le buste, lacet recentré, témoin refait (2026-10-21)
|
||||
|
||||
Ordonnateur : Big Boss (local_104ff22d). SPEC complémentaire de `ERR145-SPEC.md`, étude seule : aucun code modifié, aucune
|
||||
compilation, ni copie UE, ni MCP, ni commit. Seul fichier écrit : ce livrable.
|
||||
Amont : `ERR145-DIAG.md` (H1), `ERR145-SPEC.md` (option A, témoin, partie C), essai T0 de l'utilisateur sur la build COM23
|
||||
(2026-10-21, 08:13-08:25 locales), décisions de l'utilisateur relayées par l'ordonnateur (Q2, Q3, abandon de la partie C).
|
||||
Journal lu : `D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay\Saved\Logs\LifePlay.log`, lu par une copie faite
|
||||
le 2026-10-21 (2773 lignes, dernière ligne 06:24:31 UTC ; le jeu tournait peut-être encore). Heures du journal en UTC, locale = UTC + 2.
|
||||
Les numéros de ligne « l. n » du § 1 renvoient à ce journal.
|
||||
|
||||
## 1. Objectif mesurable
|
||||
|
||||
### 1.1 Essai T0 : ce que dit le journal (établi)
|
||||
| UTC | Lignes | Événement |
|
||||
|---|---|---|
|
||||
| 06:14:39 | 1519, 1581 | assis au meuble `_40`, en C2 (`fnt_new048-f-0-sit`) ; lever à 06:15:01 (l. 1635) |
|
||||
| 06:15:14 | 1649, 1652 | C3 → C1, **debout** (`C1Hidden=1`) |
|
||||
| 06:15:28 | 1712, 1722 | assis au meuble `_34` **sans quitter C1** (aucune touche C entre l. 1649 et l. 1738) : fait 1 (H1) |
|
||||
| 06:16:02 → 06:16:10 | 1737-1746 | cycle C2 → C3 → C1, assis `_34` |
|
||||
| 06:17:00 → 06:17:15 | 1762-1785 | lever en C1, puis cycle debout |
|
||||
| 06:17:58 | 1857, 1891 | assis `_39` en C1 ; menu `Scene_C` de 06:18:00 à 06:18:08 (l. 1972, 2088) |
|
||||
| 06:19:19 → 06:20:16 | 2256-2593 | cycle, assis `_39` ; lever en C1 à 06:21:13 (l. 2612) |
|
||||
| 06:21:33 | 2716, 2726 | assis `_35`, **en C2** (C2 depuis 06:21:16, l. 2620-2622, `C1Hidden=0`) |
|
||||
| 06:21:36 → 06:21:40 | 2727-2733 | C3 → C1 assis `_35` ; lacet de contrôle +275 à 06:21:41 (l. 2734) |
|
||||
| 06:22:09.8 → 06:22:11.2 | 2742-2752 | cycle, **C2 pendant 0,6 s** ; lacet de contrôle **-90** à 06:22:11.9 (l. 2753) |
|
||||
| 06:22:14.3 → 06:22:15.5 | 2755-2764 | cycle, C2 pendant 0,6 s ; lacet de contrôle **-90** à 06:22:16.2 (l. 2765) |
|
||||
| 06:22:17 → 06:22:21 | 2766-2770 | lacet -121, -179, -198, -203, -193 (souris vers la gauche) ; tangage jusqu'à -60 |
|
||||
| 06:24:31 | 2773 | dernière ligne, toujours en C1 assis |
|
||||
|
||||
- Les quatre assises du joueur jouent `fnt_new048-f-0-sit` (l. 1519, 1712, 1857, 2716). Aucune animation de repas
|
||||
(`fnt_new017-f-0-use`, vue le matin) n'apparaît dans la fenêtre T0 (Grep `fnt_|-f-0-` sur la copie du journal).
|
||||
- Entrées en C1 assis : 5 (06:16:10, 06:20:16, 06:21:40, 06:22:11, 06:22:15). Le récit de l'utilisateur compte deux séries de trois
|
||||
cycles. **Correspondance estimée** : la série « Sit » est `_35` (06:21:40 mauvaise, 06:22:11 et 06:22:15 bonnes) ; l'autre série
|
||||
(`_34`, `_39`) n'a que deux entrées dans cette fenêtre. **Inconnu** : la chaise « repas » du récit.
|
||||
|
||||
### 1.2 Lecture du code
|
||||
**Position (établi, DIAG § 3)** : la minuterie `UpdateRoomCam` de Room (0,016 s) pose `FirstPersonSM` au milieu de `lEye` / `rEye`
|
||||
(`etat/CAM/CAM-B2s-IMPL.md:137`, nœud 512). Ces os sont sous `neckLower`, masqué en C1. Ils sortent donc des os requis et restent figés
|
||||
(`SkeletalMeshComponent.cpp:2321-2332`). Le fait 1 (06:15:28) le confirme une fois de plus.
|
||||
|
||||
**Premier cycle mauvais (fait 2), inconnu** :
|
||||
- Avant l'entrée de 06:21:40, le cou était démasqué depuis 06:21:16 (`C1Hidden=0`, l. 2620). La voie C1 lit les yeux avant de les masquer
|
||||
(`CAM-B1-IMPL.md:22`, `:104-107`). H1 seul prédit donc une bonne vue dès ce premier cycle, et le code lu n'explique pas l'échec.
|
||||
- Pistes estimées :
|
||||
- (a) la pose assise n'est pas encore finale 7 s après l'assise (transition ou fondu de l'animation de meuble), et le masquage la fige
|
||||
à mi-course ; les entrées de 06:22:11 et 06:22:15 tombent 38 et 42 s après l'assise ;
|
||||
- (b) une tête animée en boucle (L1 de `ERR145-SPEC.md` § 1.2) est figée à une phase quelconque.
|
||||
- Pour la conception qui suit, la question devient sans objet : la position ne dépend plus ni de l'instant du masquage ni des os de la tête.
|
||||
|
||||
**Lacet vers la droite (fait 3)** :
|
||||
- Établi : aucune étape de l'entrée en C1 n'écrit le lacet de contrôle.
|
||||
- La voie P6 de Room lit ce lacet (`524 GetControlRotation → 514 → 539`) et l'écrit sur `FirstPersonSM` avant `SetViewTargetWithBlend`
|
||||
(`CAM-B2s-IMPL.md:138`, `:124`). La minuterie fait de même à chaque passage (`:137`).
|
||||
- Côté C++, `ResetC1PitchOnExit` ne remet que le tangage (`LPCameraModeSubsystem.cpp:811-828`), et `TickC1Pitch` n'écrit que le
|
||||
tangage (`:787-790`).
|
||||
- Établi : le lacet de contrôle est écrit ailleurs :
|
||||
- par `PlaceC2`, à l'entrée en C2 : lacet de l'acteur joueur (`CAM-B2d-IMPL.md:117`) ;
|
||||
- en C2 et en C1, par `CircleCamera` et `LeftRight`, à la souris X et aux flèches (`etat/CAM/CAM2/CAM2-IMPL-02.md:28`,
|
||||
`CAM-COMMUN6-DIAG.md:315`).
|
||||
C3 ne l'écrit pas : la garde de `CircleCamera` exige la vue `CamRoom` ou `CamC1On` (même source). Une entrée en C1 hérite donc du lacet
|
||||
laissé par C2.
|
||||
- Établi : assis, l'acteur n'est pas tourné par la marche. `Walk` ne pose le lacet de l'acteur que hors siège
|
||||
(`LPDirectControlSubsystem.cpp:1545-1547`). Le commentaire `:564` dit « son lacet est celui de la place ». Le joueur n'est pas possédé :
|
||||
`SetControlRotation` ne tourne pas l'acteur (`CAM-COMMUN3-DIAG.md:137-139`).
|
||||
- Établi par le journal : aux 2e et 3e entrées, C2 a duré 0,6 s et le lacet vaut exactement -90 (l. 2753, 2765), soit le lacet de l'acteur
|
||||
posé par `PlaceC2`, sans souris (estimé fort). L'utilisateur tourne ensuite vers la gauche jusqu'à -193 / -203 (l. 2766-2770).
|
||||
- **Estimé** : l'avant du corps assis sur `_35` est vers -190 ± 15°, soit environ 100° à gauche du lacet de l'acteur. La vue part donc
|
||||
vers la droite parce que l'animation de siège ne regarde pas dans l'axe de l'acteur.
|
||||
- **Inconnu** : pourquoi l'animation et l'acteur diffèrent (données de meuble ou d'animation). Le témoin le mesure (`lacet buste` contre
|
||||
`lacet acteur`, § 2.4).
|
||||
|
||||
### 1.3 Décisions de l'utilisateur prises en compte (relayées par l'ordonnateur)
|
||||
- Q2 : « non : la caméra C1 doit rester stable, sans suivre les mouvements de tête des animations. »
|
||||
- T0b : une fois la vue bien placée, aucune peau proche n'est visible. L2 est écartée et la partie C (`lp.C1NearClip`, `lp.C1Forward`)
|
||||
est retirée.
|
||||
- Q3 : « oui ». La caméra stable sera étendue à la POV de scène dans une fiche à part, après l'IMPL d'ERR-145. Ici, seulement ce qui
|
||||
sera réutilisable (§ 4.5).
|
||||
|
||||
### 1.4 Objectifs (critères chiffrés au § 7)
|
||||
1. **Position** : en C1, à chaque image, la vue est posée sur une **ancre** : l'os parent de `neckLower` (os visible, donc animé) plus un
|
||||
décalage fixe dans son repère. La vue ne lit plus les yeux. Témoin `vue-ancre` ≤ 0,5 cm sans lissage, debout, assis, après un lever
|
||||
et à chaque cycle C, quel que soit l'ordre (entrer en C1 puis s'asseoir, ou l'inverse).
|
||||
2. **Stabilité** : assis immobile, la vue ne suit aucun mouvement de tête de l'animation (décision Q2). Elle ne bouge qu'avec le buste.
|
||||
3. **Lacet** : à chaque entrée en C1 assis, et 0,5 s après s'être assis en C1, le lacet de contrôle est aligné sur l'avant du corps.
|
||||
Témoin `ecart vue-buste` dans ±10° sur la première ligne qui suit ; l'utilisateur regarde droit devant sans toucher la souris.
|
||||
4. **Rotation** : en C1, la rotation de la vue est celle du contrôleur seul (tangage, lacet), roulis nul ; jamais celle de la tête.
|
||||
5. **Repli** : `lp.C1Stable 0` à la console rend la vue d'avant dès l'image suivante.
|
||||
6. **Inchangés** : POV de scène, Scene, C2, C3, Overview, studio, PNJ. Room, PC, GI, Person et tout asset restent intacts.
|
||||
|
||||
## 2. Fichiers touchés, ordre
|
||||
|
||||
### 2.0 Conception et ordre d'exécution
|
||||
Le cœur de la conception : le **modificateur de vue** `ULPRoomBoundsCameraModifier`, déjà installé en permanence
|
||||
(`LPCameraModeSubsystem.cpp:873-881`), est le dernier à écrire la vue. Il la reprend en C1. Room continue d'écrire `FirstPersonSM`,
|
||||
mais cette écriture n'est plus vue.
|
||||
- Ordre dans une image, établi :
|
||||
- le monde d'abord : `GEngine->Tick` (`LaunchEngineLoop.cpp:5859`), puis le ticker du cœur (`:6103`), dans `FEngineLoop::Tick`
|
||||
(`:5575-6200`). Le sous-système (`FTSTicker`, `LPCameraModeSubsystem.cpp:733-735`) tourne donc **après** le monde de l'image N et
|
||||
prépare l'image N+1 ;
|
||||
- dans `UWorld::Tick`, viennent dans l'ordre les groupes d'acteurs (`LevelTick.cpp:1750-1778`), les minuteries, dont `UpdateRoomCam`
|
||||
de Room (`:1816`), puis les caméras, « after all actors have been ticked » (`:1835-1847`) ;
|
||||
- dans la caméra, `UpdateViewTarget` appelle `CalcCamera` (vue de `FirstPersonSM`), puis `ApplyCameraModifiers`
|
||||
(`PlayerCameraManager.cpp:456-463`).
|
||||
Le modificateur passe donc après la minuterie de Room, dans la même image. Il n'y a ni ordre de tick à établir ni asset à écrire.
|
||||
- Voies écartées :
|
||||
- (i) un `FTickableGameObject` (`LevelTick.cpp:1821`, entre les minuteries et les caméras) qui écrirait `FirstPersonSM` : faisable,
|
||||
mais il écrit un composant partagé avec la POV (`CAM-B1e-CART.md:89`) et la minuterie le réécrit à chaque passage ;
|
||||
- (ii) un tick de composant en `TG_PostUpdateWork` : il passe après les caméras (`LevelTick.cpp:1877` contre `:1847`), donc avec une
|
||||
image de retard ;
|
||||
- (iii) attacher `FirstPersonSM` au buste : Room le détache et le replace à chaque entrée et à chaque passage de minuterie
|
||||
(`CAM-B1-IMPL.md:22`, `CAM-B2s-IMPL.md:137-138`) ;
|
||||
- (iv) l'option B du DIAG (Room, MCP) : la fiche demande du 100 % C++.
|
||||
- Partage des rôles :
|
||||
- le **sous-système** étalonne le décalage hors C1, lit les variables, choisit les réglages et écrit le témoin ;
|
||||
- le **modificateur** calcule l'ancre et pose la vue et le lacet dans l'image même.
|
||||
L'entrée en C1 est vue par le modificateur dès la première image où la cible de vue est le joueur, sans attendre le libellé. Aucune
|
||||
image n'est donc montrée avec l'ancien lacet.
|
||||
|
||||
Ordre des fichiers (tous sous `D:\Game\LifePlay-master 5.8\Source\LifePlay\`) : (1) `LPRoomBoundsCameraModifier.h`,
|
||||
(2) `LPRoomBoundsCameraModifier.cpp`, (3) `LPCameraModeSubsystem.h`, (4) `LPCameraModeSubsystem.cpp`.
|
||||
Volume estimé : ≈ +320 / −40 lignes (modificateur ≈ +160, sous-système ≈ +160 dont 50 de témoin qui en remplacent 36). Aucune écriture
|
||||
d'asset, une compilation.
|
||||
|
||||
### 2.1 `LPRoomBoundsCameraModifier.h`
|
||||
- Commentaire de tête (l. 6-7) : ajouter « ERR145-SPEC-02 : en C1, la vue est posée sur l'ancre du buste et tournée par le contrôleur ».
|
||||
- Après `#include "Camera/CameraModifier.h"` (l. 12), déclaration avancée `class USkeletalMeshComponent;`. Avant `UCLASS()` (l. 15), une
|
||||
structure C++ simple, hors réflexion :
|
||||
```cpp
|
||||
/** ERR145-SPEC-02 : parametres de la vue C1 stable, poses a chaque image par ULPCameraModeSubsystem (etat de la fin de
|
||||
* l'image precedente). Player nul = vue C1 stable inactive. */
|
||||
struct FLPC1StableParams
|
||||
{
|
||||
TWeakObjectPtr<AActor> Player;
|
||||
TWeakObjectPtr<USkeletalMeshComponent> Mesh;
|
||||
/** Parent de neckLower : os visible (Room ne masque que neckLower), donc requis et anime. */
|
||||
FName Chest;
|
||||
/** Milieu des yeux dans le repere du buste (espace composant). */
|
||||
FVector LocalEye = FVector::ZeroVector;
|
||||
/** Avant du corps dans le repere du buste ; nul = inconnu (repli sur les clavicules). */
|
||||
FVector LocalForward = FVector::ZeroVector;
|
||||
/** Person.OccupyingFnt valide. */
|
||||
bool bSeated = false;
|
||||
/** lp.C1AlignYaw : 0 jamais, 1 entree assis et assise en C1, 2 toute entree. */
|
||||
int32 AlignYaw = 1;
|
||||
/** lp.C1Smooth, constante de temps en s (0 = aucun lissage). */
|
||||
float SmoothTime = 0.f;
|
||||
};
|
||||
```
|
||||
- Section publique, après `SetStudio` (l. 38) :
|
||||
```cpp
|
||||
/** ERR145-SPEC-02 : vue C1 stable pour les images suivantes (Player nul = inactive). */
|
||||
void SetC1Stable(const FLPC1StableParams& InC1);
|
||||
/** Vrai si la derniere image a pose la vue C1 stable (temoin). */
|
||||
bool IsC1Applied() const { return bC1Active; }
|
||||
|
||||
/** Ancre de tete non lissee, en monde : transformee du buste (espace composant) x LocalEye x transformee du composant.
|
||||
* Fonctions statiques, sans etat : reprises telles quelles par la future POV stable (ERR145-SPEC-02 § 4.5). */
|
||||
static FVector ComputeHeadAnchor(const USkeletalMeshComponent* Mesh, FName Chest, const FVector& LocalEye);
|
||||
/** Lacet de l'avant du corps : repere du buste etalonne, sinon clavicules (lCollar, rCollar). Faux sans source. */
|
||||
static bool ComputeBodyYaw(const USkeletalMeshComponent* Mesh, FName Chest, const FVector& LocalForward, double& OutYaw, const TCHAR*& OutSource);
|
||||
/** Milieu des yeux dans le repere du buste, en pose de reference du maillage (repli avant tout etalonnage). */
|
||||
static bool ComputeRefLocalEye(const USkeletalMeshComponent* Mesh, FName Chest, FVector& OutLocalEye);
|
||||
```
|
||||
- Section privée, à la fin :
|
||||
```cpp
|
||||
void ApplyC1Stable(float DeltaTime, FMinimalViewInfo& InOutPOV, AActor* Player, USkeletalMeshComponent* Mesh);
|
||||
FLPC1StableParams C1;
|
||||
bool bC1Active = false;
|
||||
bool bC1SeatedWas = false;
|
||||
/** Delai avant l'alignement qui suit une assise en C1 ; negatif = aucun. */
|
||||
float C1SeatAlignLeft = -1.f;
|
||||
/** Ancre lissee, en espace composant (la marche et le deplacement du composant ne creent aucun retard). */
|
||||
FVector C1SmoothedCS = FVector::ZeroVector;
|
||||
uint64 C1LastFrame = 0;
|
||||
FVector C1LastLocation = FVector::ZeroVector;
|
||||
FRotator C1LastRotation = FRotator::ZeroRotator;
|
||||
```
|
||||
|
||||
### 2.2 `LPRoomBoundsCameraModifier.cpp`
|
||||
- Includes à ajouter : `Components/SkeletalMeshComponent.h`, `GameFramework/PlayerController.h`, `CoreGlobals.h` (`GFrameCounter`,
|
||||
`CoreGlobals.h:532`), `LifePlay.h` (`LogLifePlay`, `LifePlay.h:9`).
|
||||
- `ModifyCamera` : insérer après le bloc Studio (l. 42-47), **avant** le filtre des l. 49-54, qui rend `false` pour toute vue non bornée,
|
||||
C1 comprise :
|
||||
```cpp
|
||||
// ERR145-SPEC-02 : vue C1 stable. Cible de vue relue a chaque image : hors de la vue du joueur, rien.
|
||||
AActor* C1Player = C1.Player.Get();
|
||||
USkeletalMeshComponent* C1Mesh = C1.Mesh.Get();
|
||||
if (C1Player && C1Mesh && !C1.Chest.IsNone() && CameraOwner && CameraOwner->GetViewTarget() == C1Player)
|
||||
{
|
||||
ApplyC1Stable(DeltaTime, InOutPOV, C1Player, C1Mesh);
|
||||
}
|
||||
else if (bC1Active)
|
||||
{
|
||||
bC1Active = false;
|
||||
C1SeatAlignLeft = -1.f;
|
||||
}
|
||||
```
|
||||
- Nouvelles fonctions :
|
||||
```cpp
|
||||
void ULPRoomBoundsCameraModifier::SetC1Stable(const FLPC1StableParams& InC1)
|
||||
{
|
||||
C1 = InC1;
|
||||
}
|
||||
|
||||
FVector ULPRoomBoundsCameraModifier::ComputeHeadAnchor(const USkeletalMeshComponent* Mesh, FName Chest, const FVector& LocalEye)
|
||||
{
|
||||
const FTransform ChestCS = Mesh->GetSocketTransform(Chest, RTS_Component);
|
||||
return Mesh->GetComponentTransform().TransformPosition(ChestCS.TransformPosition(LocalEye));
|
||||
}
|
||||
|
||||
bool ULPRoomBoundsCameraModifier::ComputeBodyYaw(const USkeletalMeshComponent* Mesh, FName Chest, const FVector& LocalForward, double& OutYaw, const TCHAR*& OutSource)
|
||||
{
|
||||
if (!LocalForward.IsNearlyZero())
|
||||
{
|
||||
const FVector Forward = Mesh->GetSocketTransform(Chest, RTS_World).TransformVectorNoScale(LocalForward);
|
||||
const FVector Flat(Forward.X, Forward.Y, 0.0);
|
||||
// Buste a plus de ~72 degres de la verticale (couche) : pas de lacet fiable.
|
||||
if (Flat.SizeSquared() > 0.09)
|
||||
{
|
||||
OutYaw = Flat.Rotation().Yaw;
|
||||
OutSource = TEXT("buste");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
static const FName LeftCollar(TEXT("lCollar"));
|
||||
static const FName RightCollar(TEXT("rCollar"));
|
||||
if (Mesh->GetBoneIndex(LeftCollar) != INDEX_NONE && Mesh->GetBoneIndex(RightCollar) != INDEX_NONE)
|
||||
{
|
||||
// UE : X avant, Y droite, Z haut ; (droite - gauche) x haut = avant.
|
||||
const FVector Across = Mesh->GetSocketLocation(RightCollar) - Mesh->GetSocketLocation(LeftCollar);
|
||||
const FVector Flat = FVector::CrossProduct(Across, FVector::UpVector).GetSafeNormal2D();
|
||||
if (!Flat.IsNearlyZero())
|
||||
{
|
||||
OutYaw = Flat.Rotation().Yaw;
|
||||
OutSource = TEXT("clavicules");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
OutSource = TEXT("aucune");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ULPRoomBoundsCameraModifier::ComputeRefLocalEye(const USkeletalMeshComponent* Mesh, FName Chest, FVector& OutLocalEye)
|
||||
{
|
||||
// Transformee de reference en espace composant : produit des transformees locales de reference de l'os jusqu'a la racine,
|
||||
// dans l'ordre enfant puis parent (C = A * B applique A puis B, TransformNonVectorized.h:472-473).
|
||||
auto RefComponentSpace = [Mesh](FName Bone, FTransform& Out)
|
||||
{
|
||||
Out = FTransform::Identity;
|
||||
for (FName Name = Bone; !Name.IsNone(); Name = Mesh->GetParentBone(Name))
|
||||
{
|
||||
const int32 Index = Mesh->GetBoneIndex(Name);
|
||||
if (Index == INDEX_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Out = Out * Mesh->GetRefPoseTransform(Index);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
FTransform ChestRef, LeftRef, RightRef;
|
||||
if (!RefComponentSpace(Chest, ChestRef) || !RefComponentSpace(FName(TEXT("lEye")), LeftRef) || !RefComponentSpace(FName(TEXT("rEye")), RightRef))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
OutLocalEye = ChestRef.InverseTransformPosition((LeftRef.GetLocation() + RightRef.GetLocation()) * 0.5);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ERR145-SPEC-02 § 2.2 : la vue C1 ne lit plus les yeux (masques sous neckLower, donc figes, ERR145-DIAG § 3.2). Position = ancre
|
||||
// du buste ; rotation = controleur seul ; lacet aligne sur l'avant du corps a l'entree assis et apres une assise en C1.
|
||||
void ULPRoomBoundsCameraModifier::ApplyC1Stable(float DeltaTime, FMinimalViewInfo& InOutPOV, AActor* Player, USkeletalMeshComponent* Mesh)
|
||||
{
|
||||
// Second appel dans la meme image (fondu de vue : PlayerCameraManager.cpp:903 et :916) : meme resultat, etat inchange.
|
||||
if (bC1Active && C1LastFrame == GFrameCounter)
|
||||
{
|
||||
InOutPOV.Location = C1LastLocation;
|
||||
InOutPOV.Rotation = C1LastRotation;
|
||||
return;
|
||||
}
|
||||
const bool bEntry = !bC1Active;
|
||||
bC1Active = true;
|
||||
C1LastFrame = GFrameCounter;
|
||||
|
||||
// Position : buste (espace composant) x decalage ; lissage dans l'espace composant, saut de plus de 30 cm = recale.
|
||||
const FVector EyeCS = Mesh->GetSocketTransform(C1.Chest, RTS_Component).TransformPosition(C1.LocalEye);
|
||||
if (bEntry || C1.SmoothTime <= 0.f || FVector::DistSquared(EyeCS, C1SmoothedCS) > FMath::Square(30.0))
|
||||
{
|
||||
C1SmoothedCS = EyeCS;
|
||||
}
|
||||
else
|
||||
{
|
||||
C1SmoothedCS = FMath::Lerp(C1SmoothedCS, EyeCS, 1.0 - FMath::Exp(-DeltaTime / C1.SmoothTime));
|
||||
}
|
||||
InOutPOV.Location = Mesh->GetComponentTransform().TransformPosition(C1SmoothedCS);
|
||||
|
||||
// Lacet : entree en C1 assise (ou toute entree si AlignYaw = 2) ; assise pendant C1 : 0,5 s apres (pose posee).
|
||||
bool bAlign = bEntry && (C1.AlignYaw >= 2 || (C1.AlignYaw >= 1 && C1.bSeated));
|
||||
if (bEntry)
|
||||
{
|
||||
C1SeatAlignLeft = -1.f;
|
||||
}
|
||||
else if (C1.bSeated && !bC1SeatedWas)
|
||||
{
|
||||
C1SeatAlignLeft = 0.5f;
|
||||
}
|
||||
bC1SeatedWas = C1.bSeated;
|
||||
if (C1SeatAlignLeft >= 0.f)
|
||||
{
|
||||
C1SeatAlignLeft -= DeltaTime;
|
||||
if (C1SeatAlignLeft < 0.f)
|
||||
{
|
||||
bAlign = C1.AlignYaw >= 1 && C1.bSeated;
|
||||
}
|
||||
}
|
||||
APlayerController* PC = CameraOwner->GetOwningPlayerController();
|
||||
FRotator Control = PC ? PC->GetControlRotation() : InOutPOV.Rotation;
|
||||
if (PC && bAlign)
|
||||
{
|
||||
double BodyYaw = 0.0;
|
||||
const TCHAR* Source = nullptr;
|
||||
if (ComputeBodyYaw(Mesh, C1.Chest, C1.LocalForward, BodyYaw, Source))
|
||||
{
|
||||
UE_LOG(LogLifePlay, Log, TEXT("C1 stable : lacet de controle %+.0f -> %+.0f (avant du corps, source %s ; %s ; lacet de l'acteur %+.0f)"),
|
||||
FRotator::NormalizeAxis(Control.Yaw), BodyYaw, Source, bEntry ? TEXT("entree en C1") : TEXT("assise en C1"),
|
||||
FRotator::NormalizeAxis(Player->GetActorRotation().Yaw));
|
||||
Control.Yaw = BodyYaw;
|
||||
PC->SetControlRotation(FRotator(Control.Pitch, Control.Yaw, 0.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogLifePlay, Log, TEXT("C1 stable : lacet non aligne (aucune source pour l'avant du corps)"));
|
||||
}
|
||||
}
|
||||
// Rotation : controleur seul (tangage : TickC1Pitch ; lacet : Room.CircleCamera a la souris), sans roulis.
|
||||
InOutPOV.Rotation = FRotator(Control.Pitch, Control.Yaw, 0.0);
|
||||
C1LastLocation = InOutPOV.Location;
|
||||
C1LastRotation = InOutPOV.Rotation;
|
||||
}
|
||||
```
|
||||
Le contrôleur écrit est celui que lit Room. `SetControlRotation` ne tourne pas l'acteur assis : seul `Walk` le tourne, et seulement hors
|
||||
siège (`LPDirectControlSubsystem.cpp:1545-1547`). Au lever en C1, `Walk` tourne le corps vers ce lacet : continuité voulue.
|
||||
|
||||
### 2.3 `LPCameraModeSubsystem.h`
|
||||
- Déclaration avancée `class USkeletalMeshComponent;` (l. 17-25).
|
||||
- Remplacer le commentaire du témoin C1 (l. 71) par « Témoin C1 (ERR145-SPEC-02) : une ligne par seconde en C1, vue mesurée contre
|
||||
l'ancre du buste ».
|
||||
- Après `float C1Cooldown = 0.f;` (l. 74) :
|
||||
```cpp
|
||||
/** ERR145-SPEC-02 : vue C1 stable, a chaque image (TickSwitchKey). Etalonne le decalage yeux-buste hors C1 (joueur debout,
|
||||
* immobile, cou non masque), puis transmet les parametres au modificateur de vue (ancre, lacet, lissage). */
|
||||
void TickC1Stable(const FString& FrameLabel, float DeltaTime);
|
||||
/** Maillage etalonne, son buste (parent de neckLower) et ses decalages (reference, etalonne), avant du corps etalonne. */
|
||||
TWeakObjectPtr<USkeletalMeshComponent> C1CalMesh;
|
||||
FName C1Chest;
|
||||
FVector C1RefEye = FVector::ZeroVector;
|
||||
bool bC1RefEye = false;
|
||||
FVector C1CalEye = FVector::ZeroVector;
|
||||
FVector C1CalForward = FVector::ZeroVector;
|
||||
int32 C1CalCount = 0;
|
||||
float C1CalCooldown = 0.f;
|
||||
```
|
||||
|
||||
### 2.4 `LPCameraModeSubsystem.cpp`
|
||||
- Includes : `HAL/IConsoleManager.h` (`TAutoConsoleVariable`, `IConsoleManager.h:2028`), `Engine/SkinnedAsset.h` (nom de l'asset au
|
||||
journal ; `SkinnedAsset.h:57`).
|
||||
- Espace `LPCameraModeLocal` :
|
||||
- ajouter `const FName NeckLowerBone(TEXT("neckLower"));`, `const float C1CalInterval = 0.5f;` et `const float C1CalMaxSpeed = 10.f;` ;
|
||||
- retirer `C1Interval`, `C1MaxEyeDistance`, `C1MaxPitch`, `C1MaxYawGap` (l. 104, 106-108). Grep : ils ne servent qu'à l'ancien
|
||||
`WitnessC1` (l. 1203, 1220-1221) ;
|
||||
- garder `C1LogInterval` (l. 105), `C1PitchMin` / `C1PitchMax` (l. 132-133, utilisés par `TickC1Pitch`), `LeftEyeSocket` /
|
||||
`RightEyeSocket` (l. 102-103).
|
||||
- Après la fermeture de l'espace de noms (l. 728) :
|
||||
```cpp
|
||||
// ERR145-SPEC-02 : bascules de l'essai en jeu (console, touche ² ou ~, DefaultInput.ini:166-168), sans recompiler.
|
||||
static TAutoConsoleVariable<int32> CVarLPC1Stable(TEXT("lp.C1Stable"), 1,
|
||||
TEXT("ERR145 : 1 = vue C1 stable (ancre sur le buste, rotation du controleur) ; 0 = vue d'avant (camera de Room sur les yeux)."));
|
||||
static TAutoConsoleVariable<int32> CVarLPC1AlignYaw(TEXT("lp.C1AlignYaw"), 1,
|
||||
TEXT("ERR145 : lacet aligne sur l'avant du corps : 0 = jamais ; 1 = entree en C1 assis et 0,5 s apres une assise en C1 ; 2 = toute entree en C1."));
|
||||
static TAutoConsoleVariable<float> CVarLPC1Smooth(TEXT("lp.C1Smooth"), 0.f,
|
||||
TEXT("ERR145 : lissage de la position C1, constante de temps en s (espace du maillage) ; 0 = aucun."));
|
||||
static TAutoConsoleVariable<int32> CVarLPC1EyeSource(TEXT("lp.C1EyeSource"), 0,
|
||||
TEXT("ERR145 : decalage yeux-buste : 0 = etalonne debout, sinon pose de reference ; 1 = pose de reference ; 2 = etalonne seulement."));
|
||||
```
|
||||
- Nouvelle méthode, après `ResetC1PitchOnExit` (l. 828). Les accès suivent `TickC1Pitch` (l. 800-801) :
|
||||
```cpp
|
||||
// ERR145-SPEC-02 § 2.4 : la vue C1 est posee par le modificateur sur le parent de neckLower plus un decalage fixe. Le decalage est
|
||||
// etalonne hors C1, joueur debout, immobile et rendu, cou non masque (yeux animes) ; a defaut, pose de reference du maillage.
|
||||
void ULPCameraModeSubsystem::TickC1Stable(const FString& FrameLabel, float DeltaTime)
|
||||
{
|
||||
UGameInstance* GI = GetGameInstance();
|
||||
UWorld* World = GI ? GI->GetWorld() : nullptr;
|
||||
APlayerController* PC = World ? World->GetFirstPlayerController() : nullptr;
|
||||
APlayerCameraManager* Manager = PC ? PC->PlayerCameraManager.Get() : nullptr;
|
||||
ULPRoomBoundsCameraModifier* Modifier = Manager ? Cast<ULPRoomBoundsCameraModifier>(Manager->FindCameraModifierByClass(ULPRoomBoundsCameraModifier::StaticClass())) : nullptr;
|
||||
ACharacter* Player = Cast<ACharacter>(LPCameraModeLocal::ReadObject(GI, LPCameraModeLocal::GIPlayerCharacter));
|
||||
USkeletalMeshComponent* Mesh = IsValid(Player) ? Player->GetMesh() : nullptr;
|
||||
|
||||
// Maillage nouveau (chargement, CharGen) : buste, reference et etalonnage repris de zero.
|
||||
if (Mesh != C1CalMesh.Get())
|
||||
{
|
||||
C1CalMesh = Mesh;
|
||||
C1Chest = Mesh ? Mesh->GetParentBone(LPCameraModeLocal::NeckLowerBone) : NAME_None;
|
||||
C1CalCount = 0;
|
||||
C1CalEye = FVector::ZeroVector;
|
||||
C1CalForward = FVector::ZeroVector;
|
||||
bC1RefEye = Mesh && !C1Chest.IsNone() && ULPRoomBoundsCameraModifier::ComputeRefLocalEye(Mesh, C1Chest, C1RefEye);
|
||||
if (Mesh)
|
||||
{
|
||||
UE_LOG(LogLifePlay, Log, TEXT("C1 stable : maillage %s, buste %s, decalage de reference %s"), *GetNameSafe(Mesh->GetSkinnedAsset()),
|
||||
*C1Chest.ToString(), bC1RefEye ? *FString::Printf(TEXT("%.0f cm (%.0f, %.0f, %.0f)"), C1RefEye.Size(), C1RefEye.X, C1RefEye.Y, C1RefEye.Z) : TEXT("absent"));
|
||||
}
|
||||
}
|
||||
const bool bSexOn = LPCameraModeLocal::ReadBool(GI, LPCameraModeLocal::GISexOn);
|
||||
const UObject* Room = LPCameraModeLocal::ReadObject(GI, LPCameraModeLocal::GIRoom);
|
||||
const bool bSeated = Mesh && IsValid(LPCameraModeLocal::ReadObject(Player, LPCameraModeLocal::PlayerOccupyingFnt));
|
||||
|
||||
// Etalonnage : toutes les 0,5 s, moyenne glissante (poids 0,2 apres la premiere mesure).
|
||||
C1CalCooldown = FMath::Max(0.f, C1CalCooldown - DeltaTime);
|
||||
if (Mesh && !C1Chest.IsNone() && C1CalCooldown <= 0.f && FrameLabel != LPCameraModeLocal::LabelC1 && !bSexOn && !bSeated
|
||||
&& Player->GetVelocity().Size2D() < LPCameraModeLocal::C1CalMaxSpeed && Mesh->WasRecentlyRendered()
|
||||
&& !Mesh->IsBoneHiddenByName(LPCameraModeLocal::NeckLowerBone)
|
||||
&& Mesh->GetBoneIndex(LPCameraModeLocal::LeftEyeSocket) != INDEX_NONE && Mesh->GetBoneIndex(LPCameraModeLocal::RightEyeSocket) != INDEX_NONE)
|
||||
{
|
||||
C1CalCooldown = LPCameraModeLocal::C1CalInterval;
|
||||
const FTransform ChestCS = Mesh->GetSocketTransform(C1Chest, RTS_Component);
|
||||
const FVector EyesCS = (Mesh->GetSocketTransform(LPCameraModeLocal::LeftEyeSocket, RTS_Component).GetLocation()
|
||||
+ Mesh->GetSocketTransform(LPCameraModeLocal::RightEyeSocket, RTS_Component).GetLocation()) * 0.5;
|
||||
// Debout hors C1, le corps regarde l'avant de l'acteur (orientation vers la marche, LPDirectControlSubsystem.cpp:1538-1544).
|
||||
const FVector ForwardCS = Mesh->GetComponentTransform().InverseTransformVectorNoScale(Player->GetActorForwardVector());
|
||||
const double Weight = C1CalCount == 0 ? 1.0 : 0.2;
|
||||
C1CalEye = FMath::Lerp(C1CalEye, ChestCS.InverseTransformPosition(EyesCS), Weight);
|
||||
C1CalForward = FMath::Lerp(C1CalForward, ChestCS.InverseTransformVectorNoScale(ForwardCS).GetSafeNormal(), Weight).GetSafeNormal();
|
||||
++C1CalCount;
|
||||
if (C1CalCount == 1 || C1CalCount == 20)
|
||||
{
|
||||
UE_LOG(LogLifePlay, Log, TEXT("C1 stable : etalonnage %d (decalage yeux-buste %.0f cm, ecart a la reference %.0f cm)"), C1CalCount,
|
||||
C1CalEye.Size(), bC1RefEye ? FVector::Dist(C1CalEye, C1RefEye) : -1.0);
|
||||
}
|
||||
}
|
||||
|
||||
// Parametres de l'image suivante ; arme si CamC1On et hors scene (le modificateur verifie en plus la cible de vue).
|
||||
if (!Modifier)
|
||||
{
|
||||
return; // pose par TickViewBounds, appele juste avant dans la meme image (l. 1262, :873-881)
|
||||
}
|
||||
const int32 Source = CVarLPC1EyeSource.GetValueOnGameThread();
|
||||
const bool bUseCal = C1CalCount > 0 && Source != 1;
|
||||
const bool bUseRef = !bUseCal && bC1RefEye && Source != 2;
|
||||
FLPC1StableParams Params;
|
||||
if (Mesh && !C1Chest.IsNone() && (bUseCal || bUseRef) && CVarLPC1Stable.GetValueOnGameThread() != 0 && !bSexOn
|
||||
&& LPCameraModeLocal::ReadBool(Room, LPCameraModeLocal::RoomCamC1On))
|
||||
{
|
||||
Params.Player = Player;
|
||||
Params.Mesh = Mesh;
|
||||
Params.Chest = C1Chest;
|
||||
Params.LocalEye = bUseCal ? C1CalEye : C1RefEye;
|
||||
Params.LocalForward = C1CalForward;
|
||||
Params.bSeated = bSeated;
|
||||
Params.AlignYaw = CVarLPC1AlignYaw.GetValueOnGameThread();
|
||||
Params.SmoothTime = FMath::Max(0.f, CVarLPC1Smooth.GetValueOnGameThread());
|
||||
}
|
||||
Modifier->SetC1Stable(Params);
|
||||
}
|
||||
```
|
||||
- `TickSwitchKey`, après la l. 1264 (`ResetC1PitchOnExit(...)`) : `TickC1Stable(FrameLabel, DeltaTime);`.
|
||||
- `Deinitialize` : rien à ajouter. `RemoveViewBounds` (l. 744) retire le modificateur avec son état (`:970-979`).
|
||||
- **Témoin C1** : remplace `WitnessC1` (l. 1196-1231). Appel inchangé (`Tick`, l. 1140-1143, libellé C1).
|
||||
```cpp
|
||||
// ERR145-SPEC-02 : une ligne par seconde en C1, sans condition. L'ancre est recalculee ici, que la vue stable soit active ou non :
|
||||
// avec lp.C1Stable 0, « vue-ancre » chiffre le defaut d'origine (yeux figes) ; avec 1, il vaut 0.
|
||||
void ULPCameraModeSubsystem::WitnessC1(float DeltaTime)
|
||||
{
|
||||
C1Cooldown = FMath::Max(0.f, C1Cooldown - DeltaTime);
|
||||
if (C1Cooldown > 0.f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
C1Cooldown = LPCameraModeLocal::C1LogInterval;
|
||||
UGameInstance* GI = GetGameInstance();
|
||||
UWorld* World = GI ? GI->GetWorld() : nullptr;
|
||||
APlayerController* PC = World ? World->GetFirstPlayerController() : nullptr;
|
||||
APlayerCameraManager* Manager = PC ? PC->PlayerCameraManager.Get() : nullptr;
|
||||
ACharacter* Player = Cast<ACharacter>(LPCameraModeLocal::ReadObject(GI, LPCameraModeLocal::GIPlayerCharacter));
|
||||
USkeletalMeshComponent* Mesh = IsValid(Player) ? Player->GetMesh() : nullptr;
|
||||
const USceneComponent* Camera = IsValid(Player) ? Cast<USceneComponent>(LPCameraModeLocal::ReadObject(Player, LPCameraModeLocal::PlayerFirstPersonSM)) : nullptr;
|
||||
if (!Manager || !Mesh || !IsValid(Camera) || Mesh != C1CalMesh.Get() || C1Chest.IsNone())
|
||||
{
|
||||
return;
|
||||
}
|
||||
const bool bCal = C1CalCount > 0 && CVarLPC1EyeSource.GetValueOnGameThread() != 1;
|
||||
const FVector Anchor = ULPRoomBoundsCameraModifier::ComputeHeadAnchor(Mesh, C1Chest, bCal ? C1CalEye : C1RefEye);
|
||||
const FVector ChestAt = Mesh->GetSocketLocation(C1Chest);
|
||||
const FVector Eyes = (Mesh->GetSocketLocation(LPCameraModeLocal::LeftEyeSocket) + Mesh->GetSocketLocation(LPCameraModeLocal::RightEyeSocket)) * 0.5;
|
||||
const FVector ViewAt = Manager->GetCameraLocation();
|
||||
const FRotator ViewRotation = Manager->GetCameraRotation();
|
||||
double BodyYaw = 0.0;
|
||||
const TCHAR* BodySource = TEXT("aucune");
|
||||
const bool bBody = ULPRoomBoundsCameraModifier::ComputeBodyYaw(Mesh, C1Chest, C1CalForward, BodyYaw, BodySource);
|
||||
const ULPRoomBoundsCameraModifier* Modifier = Cast<ULPRoomBoundsCameraModifier>(Manager->FindCameraModifierByClass(ULPRoomBoundsCameraModifier::StaticClass()));
|
||||
const UObject* RoomObject = LPCameraModeLocal::ReadObject(GI, LPCameraModeLocal::GIRoom);
|
||||
UE_LOG(LogLifePlay, Log, TEXT("Temoin C1 : stable=%d appliquee=%d ; vue-ancre %.1f cm ; yeux-ancre %.0f cm ; camera-yeux %.0f cm ; ancre-buste %.0f cm (haut %+.0f) ; decalage %s (%d mesures, ecart a la reference %.0f cm) ; lacet vue %+.0f controle %+.0f buste %+.0f (%s) acteur %+.0f ; ecart vue-buste %+.0f ; tangage %+.0f ; assis=%d ; cou masque=%d ; rendu=%d ; lissage %.2f s ; minuterie=%d"),
|
||||
CVarLPC1Stable.GetValueOnGameThread(), (Modifier && Modifier->IsC1Applied()) ? 1 : 0,
|
||||
FVector::Dist(ViewAt, Anchor), FVector::Dist(Eyes, Anchor), FVector::Dist(Camera->GetComponentLocation(), Eyes),
|
||||
FVector::Dist(Anchor, ChestAt), Anchor.Z - ChestAt.Z,
|
||||
bCal ? TEXT("etalonne") : TEXT("reference"), C1CalCount, (C1CalCount > 0 && bC1RefEye) ? FVector::Dist(C1CalEye, C1RefEye) : -1.0,
|
||||
FRotator::NormalizeAxis(ViewRotation.Yaw), FRotator::NormalizeAxis(PC->GetControlRotation().Yaw), bBody ? BodyYaw : 0.0, BodySource,
|
||||
FRotator::NormalizeAxis(Player->GetActorRotation().Yaw), bBody ? FRotator::NormalizeAxis(ViewRotation.Yaw - BodyYaw) : 0.0,
|
||||
FRotator::NormalizeAxis(ViewRotation.Pitch),
|
||||
IsValid(LPCameraModeLocal::ReadObject(Player, LPCameraModeLocal::PlayerOccupyingFnt)) ? 1 : 0,
|
||||
Mesh->IsBoneHiddenByName(LPCameraModeLocal::NeckLowerBone) ? 1 : 0, Mesh->WasRecentlyRendered() ? 1 : 0,
|
||||
CVarLPC1Smooth.GetValueOnGameThread(),
|
||||
LPCameraModeLocal::TimerActive(IsValid(RoomObject) ? RoomObject : nullptr, LPCameraModeLocal::RoomCamTimer, World) ? 1 : 0);
|
||||
}
|
||||
```
|
||||
La chaîne de format a 22 champs pour 22 arguments (comptés). Le préfixe « Temoin C1 : » est gardé pour les recherches de journal.
|
||||
- **Plages attendues** (estimées, proportions Genesis 8, non mesurées ; la VAL les cale sur la première ligne debout) :
|
||||
|
||||
| Champ | Debout, `stable=1` | Assis, `stable=1` | `stable=0`, debout → C1 → assis (défaut d'origine) |
|
||||
|---|---|---|---|
|
||||
| `appliquee` | 1 | 1 | 0 |
|
||||
| `vue-ancre` | 0.0 (≤ lissage) | 0.0 | > 10 cm (vue sur les yeux figés) |
|
||||
| `yeux-ancre` | 0 à 5 cm | > 10 cm possible (yeux figés, sans effet sur la vue) | > 10 cm |
|
||||
| `camera-yeux` | 0 à 3 cm (Room, minuterie) | idem | idem |
|
||||
| `ancre-buste` / `haut` | 20 à 35 cm / +15 à +30 | idem (repère du buste) | idem |
|
||||
| `decalage` | `etalonne`, mesures ≥ 1 ; écart à la référence < 5 cm | idem | idem |
|
||||
| `ecart vue-buste` | libre (souris) | ±10° à la 1re ligne après une entrée ou une assise | quelconque |
|
||||
| `lacet acteur` contre `lacet buste` | ≈ égaux | écart à mesurer (≈ 100° estimé sur `_35`) | idem |
|
||||
| `cou masque` / `rendu` | 1 / 1 | 1 / 1 (0 si le corps sort de l'image) | 1 / 1 |
|
||||
|
||||
### 2.5 Retiré par rapport à `ERR145-SPEC.md`
|
||||
- Option A (`TickC1BoneRefresh`, `lp.C1RefreshBones`, écriture de `VisibilityBasedAnimTickOption`) : non livrée (§ 4.1).
|
||||
- Partie C (`SetC1View`, `lp.C1NearClip`, `lp.C1Forward`, plan proche par vue, avance de la vue) : retirée (décision T0b).
|
||||
- `BodyForward` par les clavicules seules : remplacé par `ComputeBodyYaw` (repère du buste étalonné, puis clavicules).
|
||||
- Le témoin de `ERR145-SPEC.md` § 2.3 est remplacé par celui du § 2.4.
|
||||
|
||||
## 3. Repli
|
||||
- **Sans build** :
|
||||
- `lp.C1Stable 0` à la console : le sous-système transmet des paramètres vides, et le modificateur cesse d'agir dès l'image suivante
|
||||
(vue de Room, comportement d'avant) ;
|
||||
- `lp.C1AlignYaw 0` garde la position stable sans toucher au lacet ;
|
||||
- `lp.C1EyeSource 1` force la pose de référence si l'étalonnage est mauvais ;
|
||||
- en Shipping, sans console, les variables gardent leur valeur par défaut.
|
||||
- **Code** : instantané par la session principale avant l'IMPL (`Tools\Snapshot.ps1 -Lot ERR145`). Retour arrière seulement proposé
|
||||
(`Tools\Restore.ps1 -Lot ERR145`). Les quatre fichiers ne touchent ni Room, ni PC, ni GI, ni Person, ni aucun asset.
|
||||
|
||||
## 4. Risques R#, questions Q#
|
||||
|
||||
### 4.1 L'option A reste-t-elle utile ? Non, elle devient inutile
|
||||
- La vue ne lit plus aucun os sous `neckLower`. L'ancre est l'os parent de `neckLower`, qui est visible donc gardé dans les os requis
|
||||
(`SkeletalMeshComponent.cpp:2321-2332`) et animé. Le gel des os masqués n'a plus d'effet visible : la tête est masquée, et
|
||||
`FirstPersonSM`, posé par Room sur les yeux figés, n'est plus la vue.
|
||||
- A n'apporterait plus qu'une chose : le rafraîchissement des os quand le maillage n'est pas rendu (`SkinnedMeshComponent.h:98-101` ;
|
||||
`ACharacter` est en `AlwaysTickPose`, `Character.cpp:125` cité par le DIAG). Son coût reste entier : deux recalculs des os requis par
|
||||
passage en C1, R4 de `ERR145-SPEC.md`.
|
||||
- Recours seulement si T4 montre un saut au retour d'un regard au plafond (`rendu=0`, R2).
|
||||
|
||||
### 4.2 Choix de l'ancre
|
||||
- **Os** : parent de `neckLower`, lu à l'exécution (`GetParentBone`, `SkinnedMeshComponent.h:1263` ; racine → `NAME_None`,
|
||||
`SkinnedMeshComponent.cpp:2506-2516`). `chestUpper` est attendu sur Genesis 8, mais c'est une **estimation** : la hiérarchie n'a pas été
|
||||
relue dans les assets. `neckLower` lui-même est exclu, car il est masqué donc figé.
|
||||
- **Décalage** :
|
||||
- **étalonné** sur le maillage vivant, hors C1, debout et immobile, cou non masqué, maillage rendu. Il couvre homme, femme et
|
||||
proportions propres au maillage. Moyenne glissante sur des mesures espacées de 0,5 s ;
|
||||
- repli sur la **pose de référence** (`GetRefPoseTransform`, locale : `SkinnedMeshComponent.h:2045-2053`, `.cpp:2727-2737`), si la
|
||||
partie commence directement en C1.
|
||||
Le témoin écrit l'écart entre les deux.
|
||||
- **Repère** : la rotation complète du buste. Penché pour manger, le point de vue avance avec le buste ; couché, il prolonge le buste. Un
|
||||
repère de lacet seul mettrait le point de vue à la verticale d'un buste couché.
|
||||
- **Lissage** en espace composant : la marche et le déplacement du composant (assise, racine à 77-104 cm du composant selon le DIAG)
|
||||
ne créent aucun retard. Un saut de plus de 30 cm est recalé.
|
||||
|
||||
### 4.3 Risques
|
||||
- **R1** : l'étalonnage debout fige la tête de l'animation de repos au moment des mesures (regard un peu baissé, tête tournée). Erreur
|
||||
attendue de quelques cm, moyennée ; `lp.C1EyeSource 1` sert de repli. Témoin : `ecart a la reference`.
|
||||
- **R2** : en `AlwaysTickPose`, les os ne sont rafraîchis que si le maillage est rendu (`SkinnedMeshComponent.h:100-101`). Assis en C1, le
|
||||
regard au plafond peut sortir le corps de l'image : le buste reste figé en espace composant. La position de l'acteur reste juste, et
|
||||
l'erreur est petite au repos (estimé). Témoin : `rendu`. Recours : option A (§ 4.1).
|
||||
- **R3** : le sous-système arme la vue stable sur l'état de l'image précédente (`LaunchEngineLoop.cpp:5859`, `:6103`). À l'entrée en scène
|
||||
depuis C1, si la POV vise le joueur dans la même image, l'ancre peut s'appliquer **une image** en POV. Négligeable (estimé). Le
|
||||
désarmement suit à l'image suivante, au front de `SexOn`.
|
||||
- **R4** : pendant un fondu de vue, `GetViewTarget()` rend la cible **en attente** (`PlayerCameraManager.cpp:249-256`) et les deux cibles
|
||||
sont évaluées (`:903`, `:916`). L'ancre s'appliquerait alors aux deux, et le fondu deviendrait une coupe. Établi sans effet
|
||||
aujourd'hui : C1 est posée sans fondu (`SetViewTargetWithBlend(…, 0, Linear)`, `CAM-B1-IMPL.md:22` ; « fondu 0 partout »,
|
||||
`CAM-AUDIT.md:44`). Le garde-image (`GFrameCounter`) rend le même résultat au second appel.
|
||||
- **R5** : `FirstPersonSM` (posé par Room aux yeux figés) n'est plus à la place de la vue. Un Blueprint qui lirait sa position en C1
|
||||
serait décalé. Côté C++, Grep `FirstPersonSM` sur `Source/LifePlay` ne trouve que des lectures de témoin et la POV (l. 99, 801, 1209,
|
||||
1643, 1675-1676). Les lecteurs Blueprint ne sont pas relus (incertain). Les clics à l'écran passent par la vue finale du gestionnaire
|
||||
de caméra, donc par l'ancre (estimé). Essai : T6.
|
||||
- **R6** : l'alignement 0,5 s après une assise en C1 lit l'avant du corps à ce moment. Une transition plus longue donnerait un angle
|
||||
faux (piste (a) du § 1.2). La souris corrige ; `lp.C1AlignYaw 0` coupe. Le témoin écrit chaque alignement.
|
||||
- **R7** : buste couché (plus de 72° de la verticale) : le lacet n'est pas aligné. Le repli sur les clavicules peut alors donner un angle
|
||||
quelconque (`ComputeBodyYaw`). C1 couché n'a pas été vu en essai : inconnu, à couvrir par T5.
|
||||
- **R8** : l'étalonnage de l'avant du corps suppose que le maillage debout regarde l'avant de l'acteur (orientation vers la marche,
|
||||
`LPDirectControlSubsystem.cpp:1538-1544`). Une animation de repos qui tourne le buste fausserait `C1CalForward` (estimé faible).
|
||||
Le repli clavicules est mesuré à part par le témoin (`buste` contre `clavicules` selon la source).
|
||||
- **R9** : compilation unitaire. Noms neufs uniques (`CVarLPC1*`, `FLPC1StableParams`) ou membres de classe ; aucun espace anonyme
|
||||
(`lp-build` § 8).
|
||||
- **R10** : un `FTSTicker` tourne aussi au menu principal. Sans `PlayerCharacter`, aucun paramètre n'est armé (`Player` nul).
|
||||
|
||||
### 4.4 Questions pour l'utilisateur
|
||||
- **Q4** : faut-il aussi aligner le lacet à l'entrée en C1 **debout** ? Proposition : non (`lp.C1AlignYaw 1`). Debout, l'entrée garde le
|
||||
lacet de C2, comme aujourd'hui ; `2` est essayé en T6.
|
||||
- **Q5** : un lissage par défaut ? Proposition : 0 (vue fixée au buste). Valeur retenue après T5 (`lp.C1Smooth 0.15`), puis écrite dans le
|
||||
code ou dans `[SystemSettings]` de `DefaultEngine.ini` pour la Shipping.
|
||||
|
||||
### 4.5 POV de scène (Q3 : oui, fiche à part après l'IMPL d'ERR-145)
|
||||
- **Effet de cette conception sur la POV** : aucun. La vue stable n'est armée qu'avec `CamC1On` et hors `SexOn` (§ 2.4). Le libellé
|
||||
« POV » vient de `PC.POVOn` pendant `SexOn` (`LPCameraModeSubsystem.cpp:2620-2625`). Seule exception, une image au plus (R3).
|
||||
- **Réutilisable tel quel** :
|
||||
- `ComputeHeadAnchor`, `ComputeBodyYaw` et `ComputeRefLocalEye` : statiques, sans état, valables pour tout maillage de Person ;
|
||||
- le schéma du modificateur : branche avant le filtre des bornes, cible de vue relue à chaque image, garde-image, lissage en
|
||||
espace composant ;
|
||||
- la règle « l'ancre est le parent de l'os masqué » ;
|
||||
- le modèle de bascule (`lp.POVStable`, par exemple) et le modèle du témoin (`vue-ancre`, `yeux-ancre`, `ancre-buste`, `rendu`).
|
||||
- **Particularités connues** :
|
||||
- **Cible de vue** : `SexPersons[SexCameraIndex]` (`CAM-B1e-CART.md:88`), parfois un **PNJ**. L'étalonnage de cette fiche ne couvre
|
||||
que le joueur. Pour la POV : pose de référence, ou étalonnage par maillage (une table par composant) pris avant la scène.
|
||||
- **Masquage** : le cou est masqué par **PC** sur `CurrentActor` (`CAM-B1e-CART.md:62-63`). `FirstPersonSM` reste **attaché** à `head`
|
||||
(`CAM-B1e-CART.md:88-89`). Un os sous l'os masqué donne donc le même gel que H1 : estimé, non observé.
|
||||
- **Rotation** : en POV, ce n'est pas le contrôleur qui tourne la vue. C'est `FirstPersonSM`, par `AddWorldRotation` côté PC
|
||||
(`CAM-B1e-CART.md:89`) et par ZQSD côté C++ (`LPCameraModeSubsystem.cpp:1642-1643`). La POV gardera la rotation du composant, ou
|
||||
la rebasera sur le repère du buste : choix de la fiche POV.
|
||||
- **Torse** : les poses de scène le bougent beaucoup (couché, à genoux). Le repère complet du buste est donc nécessaire, et le
|
||||
lissage sans doute plus utile qu'en C1.
|
||||
- **Entrée en scène** : `ClearC1HiddenOnSexEntry` remet `C1Hidden` à faux (`LPCameraModeSubsystem.cpp:750-764`).
|
||||
|
||||
## 5. Interdits
|
||||
- Aucun changement de Room, PC, GI, Person ni d'asset ; aucun MCP ; aucun changement du plan proche global (`DefaultEngine.ini:50`).
|
||||
- Ne jamais écrire `VisibilityBasedAnimTickOption`, appeler `RecalcRequiredBones` ou `RecalcRequiredCurves`, ni écrire la position ou
|
||||
l'attache de `FirstPersonSM` (composant partagé avec la POV) : la vue C1 passe par le modificateur seul.
|
||||
- Ne toucher à aucun maillage, ni à aucun contrôleur hors du `GetOwningPlayerController()` du gestionnaire de caméra ; aucune écriture sur un PNJ.
|
||||
- Ne pas retirer ni modifier `LPStringCompat`, `LPMeshCompat`, `LPNavigationHelpers` et voisins (`lp-ue-compat` § 4).
|
||||
- Pas de compilation par l'IMPL (fiche BUILD à `lp-builder`), pas de commande git qui écrit, modification par Edit uniquement.
|
||||
|
||||
## 6. Valeurs moteur lues dans le moteur installé
|
||||
Moteur `D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\` (préfixe omis : `Engine/` sauf mention).
|
||||
- Ordre d'une image :
|
||||
- `Launch/Private/LaunchEngineLoop.cpp:5575` (`FEngineLoop::Tick`), `:5859` (`GEngine->Tick`), `:6103` (`FTSTicker::GetCoreTicker().Tick`,
|
||||
seul appel de la fonction, après le monde) ;
|
||||
- `Private/LevelTick.cpp:1750-1778` (groupes d'acteurs), `:1816` (minuteries), `:1821` (`FTickableGameObject::TickObjects`),
|
||||
`:1835-1847` (caméras « after all actors have been ticked »), `:1877` (`TG_PostUpdateWork`, après les caméras).
|
||||
- Caméra :
|
||||
- `Private/PlayerCameraManager.cpp:244-261` : `GetViewTarget` rend la cible en attente pendant un fondu ;
|
||||
- `:287-307` : `ApplyCameraModifiers`, modificateur sauté s'il est désactivé, et arrêt si `ModifyCamera` rend vrai ;
|
||||
- `:446-464` : modificateurs appliqués après `UpdateViewTargetInternal`, sauf caméras de débogage ;
|
||||
- `:881-916` : deux `UpdateViewTarget` pendant un fondu.
|
||||
- `Classes/Camera/PlayerCameraManager.h:552` (`GetOwningPlayerController`), `:701` (`GetCameraRotation`), `:705` (`GetCameraLocation`).
|
||||
- `Classes/Camera/CameraModifier.h:51` (`CameraOwner`), `:95` (`ModifyCamera(float, FMinimalViewInfo&)`).
|
||||
- Contrôleur : `Classes/GameFramework/Controller.h:159` (`GetControlRotation`), `:163` (`SetControlRotation`).
|
||||
- Maillage :
|
||||
- `Classes/Components/SkinnedMeshComponent.h` :
|
||||
- `:98-101` : `AlwaysTickPoseAndRefreshBones` / `AlwaysTickPose` (« Refresh BoneTransforms only when rendered ») ;
|
||||
- `:1156` : `GetBoneIndex` ; `:1223` : `GetSkinnedAsset` ; `:1263` : `GetParentBone` ;
|
||||
- `:1360` : `GetSocketTransform(FName, ERelativeTransformSpace)` ; `:1516` : `GetBoneTransform` ;
|
||||
- `:2036-2053` : `GetRefPosePosition` / `GetRefPoseTransform`, en espace local ;
|
||||
- `:2171` : `IsBoneHiddenByName`, non const.
|
||||
- `Private/Components/SkinnedMeshComponent.cpp:2506-2516` : `GetParentBone` rend `NAME_None` à la racine ; `:2727-2737` :
|
||||
`GetRefPoseTransform` = `GetRefBonePose()[i]`.
|
||||
- `Private/Components/SkeletalMeshComponent.cpp:2321-2332` : un os visible reste requis. `:2358-2408` : `RecalcRequiredBones` remet la
|
||||
pose locale à la référence (`:2369`) et ne recalcule l'espace composant que des os requis (DIAG § 3.2).
|
||||
- `Classes/Components/PrimitiveComponent.h:999` : `WasRecentlyRendered(float Tolerance = 0.2f) const`.
|
||||
- `Classes/Engine/SkinnedAsset.h:57` : `GetRefSkeleton`.
|
||||
- Cœur :
|
||||
- `Core/Public/Math/TransformNonVectorized.h:472-473` : `C = A * B` applique A puis B. `:532`, `:536`, `:539`, `:546` :
|
||||
`TransformPosition`, `InverseTransformPosition`, `TransformVectorNoScale`, `InverseTransformVectorNoScale` ;
|
||||
- `Core/Public/CoreGlobals.h:532` : `GFrameCounter` ;
|
||||
- `Core/Public/HAL/IConsoleManager.h:2028` : `TAutoConsoleVariable(Name, DefaultValue, Help, Flags)`.
|
||||
- Jeu, lu dans les sources du projet :
|
||||
- `LPCameraModeSubsystem.cpp` : `:733-735` (tickers), `:787-790` et `:811-828` (tangage), `:873-881` (modificateur toujours
|
||||
installé), `:970-979` (retrait), `:1196-1231` (ancien témoin), `:1258-1268` (ordre par image), `:2620-2635` (libellés POV et C1) ;
|
||||
- `LPDirectControlSubsystem.cpp:556-569` (`FirstPersonView`, `OnSeat`) et `:1538-1548` (lacet de l'acteur en C1, hors siège) ;
|
||||
- `LPRoomBoundsCameraModifier.cpp:40-88`.
|
||||
|
||||
## 7. Critères de VAL (commande → attendu)
|
||||
|
||||
### 7.1 Contrôles de code et de build (`lp-validator`, après BUILD par `lp-builder`)
|
||||
1. `git -C "D:\Game\LifePlay-master 5.8" diff --stat` → les 4 fichiers du § 2, et eux seuls.
|
||||
2. Grep `VisibilityBasedAnimTickOption|RecalcRequiredBones|PerspectiveNearClipPlane|AddAdditiveOffset|lp\.C1NearClip|lp\.C1Forward|lp\.C1RefreshBones`
|
||||
sur `Source/LifePlay` → 0. Grep `lp\.C1(Stable|AlignYaw|Smooth|EyeSource)` → 4 définitions, toutes dans `LPCameraModeSubsystem.cpp`.
|
||||
Grep `SetControlRotation` → les deux d'avant (`LPCameraModeSubsystem.cpp:790`, `:822`) plus une dans `LPRoomBoundsCameraModifier.cpp`.
|
||||
3. `.\Tools\Build.ps1 -Lot ERR145` (LifePlayEditor) → code 0, module `LifePlay` compilé, 0 C4996 nouveau, « autres lignes : 20 ». Puis une
|
||||
build Development empaquetée neuve (`BuildDebug.ps1`, `-ArchiveDir` neuf) pour l'utilisateur.
|
||||
4. Journal de l'essai : `.\Tools\LogStats.ps1 -Log <LifePlay.log> -Pattern 'Temoin C1', 'C1 stable'`. Attendu :
|
||||
- une ligne « C1 stable : maillage … buste chestUpper » au chargement (nom d'os à confirmer) ;
|
||||
- des lignes « etalonnage 1 » puis « 20 » avant la première entrée en C1 ;
|
||||
- une ligne « lacet de controle » par entrée assis ;
|
||||
- des lignes « Temoin C1 » à 1 s d'écart en C1.
|
||||
|
||||
### 7.2 Cahier de tests pour l'utilisateur
|
||||
Essai dans la build ERR145 ; console = touche ². Pour chaque ligne : « vue correcte / non », une capture si non, et trois lignes
|
||||
« Temoin C1 » recopiées.
|
||||
- **T1, recette du DIAG § 1** : debout, attendre 5 s hors C1 (étalonnage), puis C1, puis s'asseoir sans quitter C1, sur une chaise « Sit »
|
||||
puis sur la chaise du repas (`have_a_meal_in`). Regarder autour, en bas, à l'horizontale.
|
||||
- Attendu : vue à hauteur des yeux du corps assis, corps jamais vu de dehors ; 0,5 s après l'assise, le regard se tourne droit devant.
|
||||
- Témoin : `stable=1 appliquee=1`, `vue-ancre 0.0`, `assis=1`, une ligne « C1 stable : lacet de controle … (assise en C1) ».
|
||||
- **T2, preuve par bascule** : même recette avec `lp.C1Stable 0`. Le défaut d'origine revient (vue restée à hauteur debout), et
|
||||
`vue-ancre` dépasse 10 cm. Puis `lp.C1Stable 1` : la vue revient à l'image suivante, et `vue-ancre` repasse à `0.0`.
|
||||
- **T3, cycles C assis** (faits 2 et 3) : sur chacune des deux chaises, trois cycles C2 → C3 → C1, dont un avec un long passage en C2 en
|
||||
tournant la souris.
|
||||
- Attendu : chaque retour en C1 est bien placé et regarde droit devant, dès le premier cycle.
|
||||
- Témoin : `ecart vue-buste` dans ±10° sur la première ligne. Noter `lacet acteur` contre `lacet buste`, pour mesurer l'écart.
|
||||
- **T4, lever, marche, plafond** : assis en C1, regarder au plafond 3 s puis revenir ; se lever (Z) ; marcher en C1 ; s'arrêter.
|
||||
- Attendu : aucun saut de vue ; caméra aux yeux debout ; le corps se tourne vers le regard au lever.
|
||||
- Témoin : `assis=0`, `vue-ancre 0.0`. Noter les lignes où `rendu=0`.
|
||||
- **T5, stabilité, lissage, source** :
|
||||
- assis 30 s sans souris, sur la chaise du repas : la vue ne suit aucun mouvement de tête ;
|
||||
- `lp.C1Smooth 0.15`, puis marche en C1 : noter si c'est plus agréable ; remettre à 0 ;
|
||||
- `lp.C1EyeSource 1`, puis `2` : noter tout écart de hauteur de vue ; remettre à 0 ;
|
||||
- si un lit le permet en C1, se coucher (R7).
|
||||
- **T6, non-régression** :
|
||||
- C2, C3, Overview, studio ;
|
||||
- scène lancée depuis C1, puis POV sur le joueur et sur le partenaire (comportement d'avant), puis retour en C1 après la scène ;
|
||||
- clic sur un objet en C1 (interaction juste) ;
|
||||
- `lp.C1AlignYaw 0` (lacet d'avant), puis `2` (alignement aussi debout, Q4).
|
||||
|
||||
### 7.3 Effet attendu sur ERR-106, ERR-111 et ERR-145
|
||||
- **ERR-145** (`Registre_Erreurs.md:152`) : position corrigée par construction, quel que soit l'ordre et à chaque cycle (T1, T2, T3) ;
|
||||
lacet recentré à l'entrée assis (T3).
|
||||
- **ERR-111** (`Registre_Erreurs.md:118`), volet « C1 à côté de la tête après un lever » : corrigé, car la vue ne lit plus les yeux figés
|
||||
(T4 ; estimé fort). Les volets orientation au retour de scène et sortie de CharGen ne sont pas visés.
|
||||
- **ERR-106** (`Registre_Erreurs.md:113`), résidu « décalage après un lever » : corrigé pour la même raison (estimé fort).
|
||||
|
||||
Fichiers à commiter :
|
||||
- `A Docs/Migration/etat/REL/ERR145/ERR145-SPEC-02.md` (dépôt du jeu, branche `ue5.8`)
|
||||
|
||||
Tours : 27 / 60
|
||||
|
||||
## Constats
|
||||
- Le journal T0 n'a aucune animation de repas pour le joueur (seulement `fnt_new048-f-0-sit`), alors que le récit parle d'une chaise
|
||||
avec repas. La correspondance entre cycles et chaises est donc estimée (§ 1.1). T1 et T3 nomment les deux chaises.
|
||||
- À 06:22:11.092 (l. 2748), le libellé « Camera: Studio » apparaît une fois pendant le passage C3 → C1. Sans lien établi avec ERR-145.
|
||||
- Le premier cycle mauvais (fait 2) n'est pas expliqué par le code lu (§ 1.2). La conception le rend sans objet, et `yeux-ancre` le
|
||||
chiffrera dans la build ERR145 si on le veut.
|
||||
- Écart à la fiche : la fiche demandait d'« étudier un décalage calibré (homme / femme) ou une constante ». La SPEC retient un décalage
|
||||
étalonné **par maillage** à l'exécution, avec repli sur la pose de référence, plutôt que deux constantes. Ainsi aucune valeur n'est
|
||||
à mesurer à la main, et les proportions propres au maillage sont couvertes.
|
||||
- Il reste à vérifier par MCP en lecture (hors fiche) : le parent de `neckLower` sur Michael et Bridget, et l'existence de `lCollar` /
|
||||
`rCollar`. Le journal de la build l'écrira de toute façon (ligne « C1 stable : maillage … buste … »).
|
||||
- La copie du journal lue est dans le dossier temporaire de la session : elle n'est pas un livrable. Le journal d'origine reste à son chemin.
|
||||
434
Docs/Migration/etat/REL/ERR145/ERR145-SPEC.md
Normal file
434
Docs/Migration/etat/REL/ERR145/ERR145-SPEC.md
Normal file
|
|
@ -0,0 +1,434 @@
|
|||
Fiche ERR145-SPEC — Niveau N3 — Modèle prévu non précisé par la fiche | utilisé claude-opus-5-5 — Agent lp-impl — Skills sk-protocol, ue-cpp-build, lp-build, lp-ue-compat
|
||||
# ERR145-SPEC : C1 assis, os masqués figés — option A, témoin C1 et réglages de vue (2026-10-21)
|
||||
|
||||
Ordonnateur : Big Boss (local_104ff22d). Étude seule : aucun code modifié, aucune compilation, ni copie UE, ni MCP, ni commit.
|
||||
Seul fichier écrit : ce livrable. Amont : `ERR145-DIAG.md` (H1), confirmation de l'utilisateur du 2026-10-21 07:11, puis
|
||||
fait nouveau relayé par Big Boss (capture 34 : le cycle C assis ne corrige pas la vue).
|
||||
|
||||
## 1. Objectif mesurable
|
||||
|
||||
### 1.1 Ce qui est établi avant d'écrire
|
||||
- **H1 (mécanisme)** : Room masque `neckLower` sur `PlayerCharacter.Mesh` (`etat/CAM/CAM-B1-IMPL.md:87`) ; un os masqué sort des os
|
||||
requis sauf si `VisibilityBasedAnimTickOption == AlwaysTickPoseAndRefreshBones` (`SkeletalMeshComponent.cpp:2321-2332`) ;
|
||||
`lEye` / `rEye` (sous `head`, sous `neckLower`) gardent leur pose en espace composant ; `UpdateRoomCam` pose la caméra au milieu
|
||||
de ces os à chaque passage (`CAM-B2k-IMPL.md:75`, nœud `SWL_512`). Confirmé en jeu par l'utilisateur à 07:11 (debout → C1 → assis).
|
||||
- **Journal de l'essai du 2026-10-21** (`D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay\Saved\Logs\LifePlay.log`,
|
||||
heure UTC, locale = UTC + 2) :
|
||||
- l. 1725 (05:08:56) : entrée en C1 debout ; l. 1736 : action « Sit » (`have_a_meal_in`) ; l. 1755-1757 (05:09:13) : assis au
|
||||
meuble `_196`, « racine Genesis8Female à 77 cm du bassin, à 9 cm du composant » ; l. 1758-1768 : C1 assis, tangage -11 à -57,
|
||||
lacet de contrôle de -175 à +187 (vue décapitée, cas ERR-145) ;
|
||||
- l. 1781 (05:11:21) C1 → C2 (`C1Hidden=0`, donc `RestoreC1` passé) ; l. 1784 (05:12:10) → C3 ; l. 1787-1790 (05:12:14.978) → C1,
|
||||
toujours assis (aucun `unOccupyFnt` entre l. 1757 et l. 1809) ;
|
||||
- l. 1791-1792 (05:12:15 à 05:12:16) : **tangage -0,1 puis -2,1**, lacet de contrôle +133 puis +86 ; plus aucune ligne « C1 souris »
|
||||
jusqu'à la sortie de C1 en l. 1800 (05:14:01). `TickC1Pitch` n'écrit qu'au mouvement vertical de la souris
|
||||
(`LPCameraModeSubsystem.cpp:782-786`) et c'est le seul code qui change le tangage hors sortie (`:790`, `:811-828`).
|
||||
- **Capture 34** (description de Big Boss) : C1 assis après le cycle, surface de peau cylindrique collée à gauche, haut violet et collier
|
||||
vus de très près à droite. Elle tombe dans la fenêtre 05:12:15 → 05:14:01 (07:12 → 07:14 locales), seule fenêtre « C1 assis après
|
||||
un cycle » du journal (estimé : l'heure exacte de la capture n'est pas dans le journal).
|
||||
|
||||
### 1.2 Conséquences du fait nouveau (établi / estimé)
|
||||
- **Établi** : après le cycle, les yeux ont été relus dans la pose assise du moment (os démasqués en C2 et C3, puis remasqués à
|
||||
l'entrée en C1 ; la voie C1 lit les yeux avant le masquage, `CAM-B1-IMPL.md:104-107`). C'est l'état que l'option A maintient en
|
||||
permanence pour une pose immobile. La vue reste mauvaise : **l'option A seule n'est pas prouvée suffisante**.
|
||||
- **Établi** : le tangage valait environ -2° pendant la capture. « Borner le tangage » ne traite pas ce cas, et l'hypothèse H2
|
||||
du DIAG (regard vers le bas sur la coupe du cou) n'explique pas la capture 34.
|
||||
- **Estimé** (géométrie) : la largeur horizontale vue à 90° (FOV de `FirstPersonSM`, `CAM-B1e-CART.md:79`) ne couvre verticalement
|
||||
qu'environ ±29° en 16:9. Pour qu'une épaule ou un cou remplisse la gauche de l'image à un tangage de -2°, il faut que le point de vue
|
||||
soit **à hauteur d'épaule ou de cou**, pas à hauteur des yeux d'une tête droite. Deux lectures restent ouvertes :
|
||||
- **L1, gel à une phase basse** : la pose « repas » plonge peut-être la tête vers l'assiette en boucle. Le remasquage a figé les
|
||||
yeux à un instant où la tête était baissée. A corrige le gel, mais la caméra suivra alors la tête qui plonge et remonte.
|
||||
- **L2, point de vue trop près du corps visible**, yeux vivants : tête très penchée, regard de côté (lacet de contrôle +86, orientation
|
||||
du buste inconnue), ou sommets du cou à poids mixtes étirés (voir R8). Le tout avec un plan proche à **1 cm**
|
||||
(`Config/DefaultEngine.ini:50`, contre 10 cm par défaut dans `BaseEngine.ini:361`) : toute peau à plus de 1 cm est dessinée.
|
||||
- **Inconnu** : le contenu de l'animation `fnt_new017-f-0-use` (l. 1748) ; l'orientation du buste pendant la capture ; la distance
|
||||
réelle entre la caméra et la peau.
|
||||
|
||||
### 1.3 Objectifs (critères chiffrés au § 7)
|
||||
1. **A** : en C1, les os masqués du joueur restent requis et animés. Le témoin montre « yeux-buste » dans la plage debout,
|
||||
assis comme debout, et la recette du DIAG § 1 ne montre plus le corps décapité vu de dehors.
|
||||
2. **Témoin** : une ligne par seconde en C1. Elle mesure la vue contre un os **visible** (parent de `neckLower`) et contre l'avant du
|
||||
buste. Elle donne aussi les yeux, `assis=`, l'écart racine ↔ composant, l'option d'animation et l'état du masquage.
|
||||
3. **Réglages de vue C1** (partie C, sans effet par défaut) : plan proche propre à la vue C1 et décalage du point de vue vers l'avant
|
||||
du buste, réglables à la console. Ils servent à trancher L1 / L2 dans la même build, sans second aller-retour.
|
||||
4. PNJ, POV de sexe, C2, C3, Overview, studio : comportement inchangé.
|
||||
|
||||
## 2. Fichiers touchés, ordre
|
||||
Ordre : (1) `LPCameraModeSubsystem.h`, (2) `LPCameraModeSubsystem.cpp`, (3) `LPRoomBoundsCameraModifier.h`, (4)
|
||||
`LPRoomBoundsCameraModifier.cpp` (tous sous `D:\Game\LifePlay-master 5.8\Source\LifePlay\`). Les parties 3 et 4 portent seulement la
|
||||
partie C. Elles débordent du périmètre de la fiche, qui ne nommait que le sous-système (écart, voir Constats). Si l'orchestrateur ne
|
||||
retient pas C, on retire § 2.4, les appels à `SetC1View` et `CVarLPC1NearClip` / `CVarLPC1Forward` ; le témoin écrit alors `plan proche 0.0`.
|
||||
|
||||
Volume estimé : partie A ≈ 45 lignes ; témoin ≈ 60 lignes, dont 36 remplacées ; partie C ≈ 35 lignes. Total ≈ 140 lignes touchées
|
||||
(≈ +115 / −30), aucune écriture d'asset, une compilation.
|
||||
|
||||
### 2.1 `LPCameraModeSubsystem.h`
|
||||
- Ajouter `class USkeletalMeshComponent;` aux déclarations avancées (l. 17-25).
|
||||
- Remplacer le commentaire du témoin C1 (l. 71) par : « Témoin C1 (ERR145) : une ligne par seconde en C1, vue mesurée contre le
|
||||
parent de neckLower (os visible) et l'avant du buste ».
|
||||
- Après `float C1Cooldown = 0.f;` (l. 74) :
|
||||
```cpp
|
||||
/** ERR145 (option A) : en C1, les os masques par Room restent requis et animes sur le maillage du joueur
|
||||
* (AlwaysTickPoseAndRefreshBones) ; option d'origine rendue des que le libelle quitte C1 ou que le joueur change.
|
||||
* Transmet aussi les reglages de vue C1 au modificateur (partie C). Appele a chaque image depuis TickSwitchKey. */
|
||||
void TickC1BoneRefresh(bool bC1Now);
|
||||
/** Maillage dont l'option a ete changee, et sa valeur d'origine (EVisibilityBasedAnimTickOption). */
|
||||
TWeakObjectPtr<USkeletalMeshComponent> C1RefreshMesh;
|
||||
uint8 C1SavedTickOption = 0;
|
||||
```
|
||||
|
||||
### 2.2 `LPCameraModeSubsystem.cpp` : partie A
|
||||
- Include : `#include "HAL/IConsoleManager.h"` (`TAutoConsoleVariable`, `IConsoleManager.h:2028`).
|
||||
- Dans `namespace LPCameraModeLocal`, après la l. 108 :
|
||||
```cpp
|
||||
// ERR145 : os masque par Room en C1 (CAM-B1c) ; son parent (chestUpper attendu sur Genesis 8, lu a l'execution) est le
|
||||
// repere visible du temoin ; les clavicules donnent l'avant du buste.
|
||||
const FName NeckLowerBone(TEXT("neckLower"));
|
||||
const FName LeftCollarBone(TEXT("lCollar"));
|
||||
const FName RightCollarBone(TEXT("rCollar"));
|
||||
|
||||
// Avant horizontal du buste : perpendiculaire a la ligne des clavicules (UE : X avant, Y droite, Z haut, donc
|
||||
// (droite - gauche) x haut = avant) ; a defaut, avant de l'acteur. OutFrom nomme la source pour le temoin.
|
||||
FVector BodyForward(const ACharacter* Player, const USkeletalMeshComponent* Mesh, const TCHAR*& OutFrom)
|
||||
{
|
||||
OutFrom = TEXT("acteur");
|
||||
FVector Forward = Player->GetActorForwardVector();
|
||||
if (Mesh->GetBoneIndex(LeftCollarBone) != INDEX_NONE && Mesh->GetBoneIndex(RightCollarBone) != INDEX_NONE)
|
||||
{
|
||||
const FVector Across = Mesh->GetSocketLocation(RightCollarBone) - Mesh->GetSocketLocation(LeftCollarBone);
|
||||
const FVector Candidate = FVector::CrossProduct(Across, FVector::UpVector).GetSafeNormal2D();
|
||||
if (!Candidate.IsNearlyZero())
|
||||
{
|
||||
Forward = Candidate;
|
||||
OutFrom = TEXT("clavicules");
|
||||
}
|
||||
}
|
||||
return Forward.GetSafeNormal2D();
|
||||
}
|
||||
```
|
||||
`BodyForward` doit être défini après les includes de `GameFramework/Character.h` et `Components/SkeletalMeshComponent.h`
|
||||
(déjà en l. 20 et 26). Il reste dans l'espace nommé, avec appel qualifié (règle C2374, `lp-build` § 8).
|
||||
- Après la fermeture de l'espace de noms (l. 728) :
|
||||
```cpp
|
||||
// ERR145 : bascules de l'essai en jeu (console, touche ² ou ~, DefaultInput.ini:166-168), sans recompiler.
|
||||
static TAutoConsoleVariable<int32> CVarLPC1RefreshBones(TEXT("lp.C1RefreshBones"), 1,
|
||||
TEXT("ERR145 : 1 = en C1, les os masques du joueur restent animes (option A) ; 0 = comportement d'avant (os figes)."));
|
||||
static TAutoConsoleVariable<float> CVarLPC1NearClip(TEXT("lp.C1NearClip"), 0.f,
|
||||
TEXT("ERR145 : plan proche de la vue C1, en cm (0 = plan global du projet, 1 cm)."));
|
||||
static TAutoConsoleVariable<float> CVarLPC1Forward(TEXT("lp.C1Forward"), 0.f,
|
||||
TEXT("ERR145 : avance du point de vue C1 vers l'avant du buste, en cm (0 = aucune)."));
|
||||
```
|
||||
- Nouvelle méthode, placée après `ResetC1PitchOnExit` (l. 828) :
|
||||
```cpp
|
||||
// ERR145 (option A, ERR145-SPEC § 2.2) : Room masque neckLower en C1 ; un os masque sort des os requis et sa pose reste
|
||||
// figee (SkeletalMeshComponent.cpp:2321-2332), or UpdateRoomCam pose la camera sur lEye / rEye, sous neckLower. En C1,
|
||||
// le maillage du joueur passe en AlwaysTickPoseAndRefreshBones : les os masques restent requis et animes, le rendu les
|
||||
// garde masques (SkeletalRender.cpp:516-520). Le drapeau bRequiredBonesUpToDate = faux fait recalculer les os requis au
|
||||
// prochain passage d'animation (SkeletalMeshComponent.cpp:1707-1712, 2879-2884), comme HideBone (:3950).
|
||||
void ULPCameraModeSubsystem::TickC1BoneRefresh(bool bC1Now)
|
||||
{
|
||||
UGameInstance* GI = GetGameInstance();
|
||||
ACharacter* Player = bC1Now ? Cast<ACharacter>(LPCameraModeLocal::ReadObject(GI, LPCameraModeLocal::GIPlayerCharacter)) : nullptr;
|
||||
if (!IsValid(Player))
|
||||
{
|
||||
Player = nullptr;
|
||||
}
|
||||
USkeletalMeshComponent* Mesh = (Player && CVarLPC1RefreshBones.GetValueOnGameThread() != 0) ? Player->GetMesh() : nullptr;
|
||||
USkeletalMeshComponent* Applied = C1RefreshMesh.Get();
|
||||
if (Applied && Applied != Mesh)
|
||||
{
|
||||
Applied->VisibilityBasedAnimTickOption = static_cast<EVisibilityBasedAnimTickOption>(C1SavedTickOption);
|
||||
Applied->bRequiredBonesUpToDate = false;
|
||||
UE_LOG(LogLifePlay, Log, TEXT("C1 : os du joueur rendus a l'option %d (sortie de C1, scene, joueur change ou lp.C1RefreshBones 0)"), C1SavedTickOption);
|
||||
Applied = nullptr;
|
||||
}
|
||||
if (!Applied)
|
||||
{
|
||||
C1RefreshMesh.Reset();
|
||||
}
|
||||
if (Mesh && !Applied)
|
||||
{
|
||||
C1SavedTickOption = static_cast<uint8>(Mesh->VisibilityBasedAnimTickOption);
|
||||
Mesh->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::AlwaysTickPoseAndRefreshBones;
|
||||
Mesh->bRequiredBonesUpToDate = false;
|
||||
C1RefreshMesh = Mesh;
|
||||
UE_LOG(LogLifePlay, Log, TEXT("C1 : os masques du joueur gardes animes (option %d -> %d ; neckLower masque=%d)"),
|
||||
C1SavedTickOption, static_cast<int32>(EVisibilityBasedAnimTickOption::AlwaysTickPoseAndRefreshBones),
|
||||
Mesh->IsBoneHiddenByName(LPCameraModeLocal::NeckLowerBone) ? 1 : 0);
|
||||
}
|
||||
// Partie C (§ 2.4) : reglages de vue C1 transmis au modificateur a chaque image ; nul hors C1.
|
||||
UWorld* World = GI ? GI->GetWorld() : nullptr;
|
||||
APlayerController* PC = World ? World->GetFirstPlayerController() : nullptr;
|
||||
APlayerCameraManager* Manager = PC ? PC->PlayerCameraManager.Get() : nullptr;
|
||||
ULPRoomBoundsCameraModifier* Modifier = Manager ? Cast<ULPRoomBoundsCameraModifier>(Manager->FindCameraModifierByClass(ULPRoomBoundsCameraModifier::StaticClass())) : nullptr;
|
||||
if (Modifier)
|
||||
{
|
||||
FVector Offset = FVector::ZeroVector;
|
||||
const float Forward = CVarLPC1Forward.GetValueOnGameThread();
|
||||
if (Player && Player->GetMesh() && Forward != 0.f)
|
||||
{
|
||||
const TCHAR* From = nullptr;
|
||||
Offset = LPCameraModeLocal::BodyForward(Player, Player->GetMesh(), From) * Forward;
|
||||
}
|
||||
Modifier->SetC1View(Player, CVarLPC1NearClip.GetValueOnGameThread(), Offset);
|
||||
}
|
||||
}
|
||||
```
|
||||
- `TickSwitchKey`, après la l. 1264 (`ResetC1PitchOnExit(...)`) :
|
||||
`TickC1BoneRefresh(FrameLabel == LPCameraModeLocal::LabelC1);`. Le libellé est calculé à chaque image (l. 1261). Il vaut C1 seulement
|
||||
si la vue est `PlayerCharacter` et `CamC1On` (l. 2632). Pendant une scène, il vaut « Scene » ou « POV » (l. 2620-2627). L'entrée en
|
||||
scène rend donc l'option dans la même image ; aucun autre point d'appel n'est nécessaire. Un menu ouvert en C1 garde le libellé C1
|
||||
et l'option : voulu, car la vue reste C1 derrière le menu.
|
||||
- `Deinitialize`, avant `RemoveViewBounds` (l. 744) : `TickC1BoneRefresh(false);` (rend l'option si le jeu se ferme en C1).
|
||||
|
||||
### 2.3 `LPCameraModeSubsystem.cpp` : témoin C1 (remplace `WitnessC1`, l. 1196-1231)
|
||||
```cpp
|
||||
// ERR145 : une ligne par seconde en C1, sans condition. L'ancien ecart aux yeux etait aveugle : Room pose la camera sur ces
|
||||
// memes yeux (ERR145-DIAG § 3.3). Reperes : parent de neckLower (os visible) et avant du buste (clavicules).
|
||||
void ULPCameraModeSubsystem::WitnessC1(float DeltaTime)
|
||||
{
|
||||
C1Cooldown = FMath::Max(0.f, C1Cooldown - DeltaTime);
|
||||
if (C1Cooldown > 0.f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
C1Cooldown = LPCameraModeLocal::C1LogInterval;
|
||||
const UGameInstance* GI = GetGameInstance();
|
||||
const UWorld* World = GI ? GI->GetWorld() : nullptr;
|
||||
const APlayerController* PC = World ? World->GetFirstPlayerController() : nullptr;
|
||||
const ACharacter* Player = Cast<ACharacter>(LPCameraModeLocal::ReadObject(GI, LPCameraModeLocal::GIPlayerCharacter));
|
||||
USkeletalMeshComponent* Mesh = IsValid(Player) ? Player->GetMesh() : nullptr;
|
||||
const USceneComponent* Camera = IsValid(Player) ? Cast<USceneComponent>(LPCameraModeLocal::ReadObject(Player, LPCameraModeLocal::PlayerFirstPersonSM)) : nullptr;
|
||||
const FName Chest = Mesh ? Mesh->GetParentBone(LPCameraModeLocal::NeckLowerBone) : NAME_None;
|
||||
if (!PC || !Mesh || !IsValid(Camera) || Chest.IsNone())
|
||||
{
|
||||
return;
|
||||
}
|
||||
const FVector ChestAt = Mesh->GetSocketLocation(Chest);
|
||||
const FVector Eyes = (Mesh->GetSocketLocation(LPCameraModeLocal::LeftEyeSocket) + Mesh->GetSocketLocation(LPCameraModeLocal::RightEyeSocket)) * 0.5f;
|
||||
const FVector CameraAt = Camera->GetComponentLocation();
|
||||
const FVector ViewAt = PC->PlayerCameraManager ? PC->PlayerCameraManager->GetCameraLocation() : CameraAt;
|
||||
const TCHAR* From = nullptr;
|
||||
const FVector Forward = LPCameraModeLocal::BodyForward(Player, Mesh, From);
|
||||
const FVector Right = FVector::CrossProduct(FVector::UpVector, Forward);
|
||||
const FVector Rel = ViewAt - ChestAt;
|
||||
const FRotator CameraRotation = Camera->GetComponentRotation();
|
||||
const FVector Root = Mesh->GetBoneLocation(Mesh->GetBoneName(0));
|
||||
const UObject* RoomObject = LPCameraModeLocal::ReadObject(GI, LPCameraModeLocal::GIRoom);
|
||||
UE_LOG(LogLifePlay, Log, TEXT("Temoin C1 : vue-%s %.0f cm (avant %+.0f, droite %+.0f, haut %+.0f) ; yeux-buste %.0f cm ; camera-yeux %.0f cm ; vue-camera %.0f cm ; lacet vue-buste %+.0f (%s) ; tangage %+.0f ; assis=%d ; racine-composant %.0f cm ; option os %d ; cou masque=%d ; plan proche %.1f ; minuterie=%d"),
|
||||
*Chest.ToString(), Rel.Size(), FVector::DotProduct(Rel, Forward), FVector::DotProduct(Rel, Right), Rel.Z,
|
||||
FVector::Dist(Eyes, ChestAt), FVector::Dist(CameraAt, Eyes), FVector::Dist(ViewAt, CameraAt),
|
||||
FRotator::NormalizeAxis(CameraRotation.Yaw - Forward.Rotation().Yaw), From, FRotator::NormalizeAxis(CameraRotation.Pitch),
|
||||
IsValid(LPCameraModeLocal::ReadObject(Player, LPCameraModeLocal::PlayerOccupyingFnt)) ? 1 : 0,
|
||||
FVector::Dist(Root, Mesh->GetComponentLocation()), static_cast<int32>(Mesh->VisibilityBasedAnimTickOption),
|
||||
Mesh->IsBoneHiddenByName(LPCameraModeLocal::NeckLowerBone) ? 1 : 0, CVarLPC1NearClip.GetValueOnGameThread(),
|
||||
LPCameraModeLocal::TimerActive(IsValid(RoomObject) ? RoomObject : nullptr, LPCameraModeLocal::RoomCamTimer, World) ? 1 : 0);
|
||||
}
|
||||
```
|
||||
- Constantes devenues orphelines (`C1Interval`, `C1MaxEyeDistance`, `C1MaxPitch`, `C1MaxYawGap`, l. 104-108) : l'IMPL les cherche par
|
||||
Grep et retire celles qui ne servent plus. Le préfixe « Temoin C1 : » est gardé pour les recherches de journal.
|
||||
- **Plages attendues** (estimées sur les proportions Genesis 8, non mesurées ; la VAL les cale sur la première ligne debout) :
|
||||
|
||||
| Champ | Debout, A actif | Assis, A actif | A coupé (`lp.C1RefreshBones 0`) après debout → assis |
|
||||
|---|---|---|---|
|
||||
| `yeux-buste` | 20 à 35 cm (référence R0) | R0 ± 5 cm (la chaîne du cou est rigide) | s'écarte de R0 de plus de 10 cm (COM17 : racine à 104 cm du composant) |
|
||||
| `camera-yeux` | 0 à 3 cm (minuterie de 0,016 s, une image de retard) | 0 à 3 cm | 0 à 3 cm (la caméra suit les yeux figés : aveugle, comme l'ancien témoin) |
|
||||
| `vue-buste` haut / avant | +15 à +30 / 0 à +15 cm | idem si la tête est droite ; haut < +10 = tête baissée (L1 / L2) | quelconque |
|
||||
| `vue-camera` | 0 (= `lp.C1Forward` si réglé) | idem | idem |
|
||||
| `lacet vue-buste` | libre (souris X) ; au-delà de ±90 = regard par-dessus l'épaule | idem | idem |
|
||||
| `option os` / `cou masque` | 0 / 1 | 0 / 1 | 1 / 1 (valeur d'`ACharacter`, `Character.cpp:125` cité par le DIAG) |
|
||||
|
||||
### 2.4 Partie C : réglages de vue C1 (`LPRoomBoundsCameraModifier.h/.cpp`)
|
||||
- `.h`, section publique, à côté de `SetBounds` (l. 28) :
|
||||
```cpp
|
||||
/** ERR145-SPEC § 2.4 : vue C1 (cible de vue = joueur) : plan proche propre en cm (0 = plan global) et decalage du point
|
||||
* de vue en coordonnees monde. Joueur nul = rien. Rafraichi a chaque image par LPCameraModeSubsystem. */
|
||||
void SetC1View(AActor* InPlayer, float InNearClip, const FVector& InOffset);
|
||||
```
|
||||
Section privée : `TWeakObjectPtr<AActor> C1View; float C1NearClip = 0.f; FVector C1Offset = FVector::ZeroVector;`
|
||||
- `.cpp` : `SetC1View` recopie les trois valeurs. Dans `ModifyCamera`, après le bloc Studio (l. 42-47) et **avant** le filtre des
|
||||
l. 50-54 (qui rend `false` pour toute vue non bornée, C1 comprise) :
|
||||
```cpp
|
||||
// ERR145 : vue C1 seulement (le joueur est aussi cible de vue en POV : SetC1View recoit nul hors C1).
|
||||
const AActor* C1 = C1View.Get();
|
||||
if (C1 && CameraOwner && CameraOwner->GetViewTarget() == C1)
|
||||
{
|
||||
if (C1NearClip > 0.f)
|
||||
{
|
||||
InOutPOV.PerspectiveNearClipPlane = C1NearClip;
|
||||
}
|
||||
InOutPOV.Location += C1Offset;
|
||||
}
|
||||
```
|
||||
- Pourquoi un modificateur et pas `FirstPersonSM` : `UCameraComponent` n'a pas de plan proche en perspective en 5.8, seulement
|
||||
`OrthoNearClipPlane` (`CameraComponent.h:84-86`). Son décalage additif (`:221`, `:311`, `:330-334`) resterait posé sur un composant
|
||||
partagé avec la POV de sexe (`CAM-B1e-CART.md:89`). Le champ `FMinimalViewInfo::PerspectiveNearClipPlane` (`CameraTypes.h:92-94`) est
|
||||
pris par le calcul de projection (`CameraStackTypes.cpp:342`, appelé par `LocalPlayer.cpp:1285`). Il ne touche que la vue, pas le
|
||||
plan global. Le modificateur est toujours installé, quel que soit le libellé (`LPCameraModeSubsystem.cpp:873-881`).
|
||||
|
||||
## 3. Repli
|
||||
- **Sans build** : `lp.C1RefreshBones 0` à la console rend l'option d'origine dès l'image suivante (§ 2.2) ; `lp.C1NearClip 0` et
|
||||
`lp.C1Forward 0` (valeurs par défaut) annulent la partie C. En Shipping, sans console, ces variables gardent leur défaut.
|
||||
- **Code** : instantané pris par la session principale avant l'IMPL (`Tools\Snapshot.ps1 -Lot ERR145`). Retour arrière seulement
|
||||
proposé (`Tools\Restore.ps1 -Lot ERR145`). Les quatre fichiers ne touchent ni Room, ni Person, ni aucun asset.
|
||||
|
||||
## 4. Risques R#, questions Q#
|
||||
|
||||
### 4.1 L'option A suffit-elle ? (réponse à Big Boss)
|
||||
**Non prouvé, et la capture 34 dit plutôt non pour la pose « repas ».** A est **nécessaire** : le mécanisme est établi et confirmé en
|
||||
jeu, et c'est lui qui donne la vue décapitée de dehors (COM17 ; COM23, l. 1757-1768). Mais le cycle C a produit, pour cette pose, l'état
|
||||
que A maintient, et la vue est restée mauvaise à un tangage de -2°. Mesures proposées par Big Boss, jugées sur le code :
|
||||
|
||||
| Mesure | Effet sur la capture 34 | Verdict |
|
||||
|---|---|---|
|
||||
| Borner le tangage | aucun : tangage -0,1 / -2,1 (l. 1791-1792), borne actuelle -60 (`LPCameraModeSubsystem.cpp:132`) jamais atteinte dans la fenêtre | écartée (et contraire à la décision A1-R « tous les axes », `:766`) |
|
||||
| Masquer plus haut (`neckUpper`) | laisse `neckLower` visible, donc de la peau **plus près** des yeux | écartée (aggrave, estimé) |
|
||||
| Masquer plus bas (`chestUpper`) | masque aussi les clavicules et les bras, s'ils descendent de `chestUpper` (estimé, hiérarchie Genesis 8 non relue) ; c'est un changement de Room (Blueprint), pas du C++ | écartée |
|
||||
| Plan proche propre à C1 (C, `lp.C1NearClip`) | retire toute peau à moins de N cm du point de vue (projet : 1 cm, `DefaultEngine.ini:50`) ; ne déplace rien | **1er complément**, réglage en jeu |
|
||||
| Décalage vers l'avant (C, `lp.C1Forward`) | sort le point de vue du volume du buste quel que soit le lacet, s'il suit l'avant **du buste** ; s'il suivait le regard, il pousserait la vue dans l'épaule en regardant de côté | **2e complément**, réglage en jeu |
|
||||
|
||||
Recommandation : livrer A, le témoin et C (C sans effet par défaut) dans la **même build**. On choisit les valeurs par défaut de C
|
||||
d'après les essais T0 (sans build) et T6 (§ 7.2). Décision par les chiffres du témoin, A actif, assis, vue mauvaise :
|
||||
- `yeux-buste` hors de R0 ± 5 → A n'agit pas (option non posée, voir `option os`) : retour à l'IMPL ;
|
||||
- `haut` < +10 (tête baissée, L1 ou L2) → `lp.C1Forward` 10 à 20, ou plan proche 10 à 15 ;
|
||||
- `haut` ≥ +15 et |lacet| > 90 → regard par-dessus l'épaule : plan proche ; une borne de lacet relative au buste serait une mesure
|
||||
nouvelle, hors de cette fiche ;
|
||||
- `haut` ≥ +15, |lacet| ≤ 60, vue mauvaise → peau étirée du cou (R8) : plan proche ;
|
||||
- vue bonne → A suffit ; C reste à 0.
|
||||
|
||||
### 4.2 Risques
|
||||
- **R1** : A seul ne corrige pas la capture 34 (§ 4.1) ; couvert par C et le témoin.
|
||||
- **R2** : avec A, la caméra suit la tête animée : plongée vers l'assiette si la pose « repas » en a une (L1), petits mouvements de
|
||||
tête des poses de repos. Gêne possible ; réponse par `lp.C1Forward` ou plus tard un lissage (Q2).
|
||||
- **R3** : 1 à 3 images de gel à l'entrée en C1. Room masque, attend une image, puis change la vue (`CAM-B1-IMPL.md:104-105`) ; le
|
||||
libellé C1 n'est vu qu'après ce changement (l. 2632). Les yeux viennent d'être lus : écart négligeable (estimé).
|
||||
- **R4** : A demande deux recalculs des os requis par passage en C1, un à l'entrée et un à la sortie, le même chemin que
|
||||
`HideBone` / `UnHideBone` (`SkeletalMeshComponent.cpp:3950`, `:3983`). `RecalcRequiredBones` remet la pose locale à la référence
|
||||
(`:2369`) avant l'évaluation de la même image (`:1707-1712` puis `:2879-2884`). Pas d'image en pose de référence attendue (estimé).
|
||||
C'est la raison pour laquelle on n'appelle **pas** `RecalcRequiredBones` hors du passage d'animation.
|
||||
- **R5** : coût : les os de la tête (visage compris) redeviennent évalués en C1, comme hors C1. `AlwaysTickPoseAndRefreshBones`
|
||||
rafraîchit même sans rendu (`SkinnedMeshComponent.cpp:1805-1808`), mais le corps est rendu en C1 : surcoût nul attendu (estimé).
|
||||
- **R6** : avec un plan proche au-dessus de 1 cm, un mur à moins de N cm du point de vue est traversé du regard. Les passes qui liraient
|
||||
`GNearClippingPlane` directement plutôt que la vue ne sont pas relues (incertain). Le risque n'existe que si `lp.C1NearClip` > 0.
|
||||
- **R7** : la POV de sexe n'est pas couverte. PC masque aussi `neckLower` sur `CurrentActor` (`CAM-B1e-CART.md:62-63`) et y attache
|
||||
`FirstPersonSM` à `head`, un os sous l'os masqué : même gel possible (estimé, non observé). Voir Q3.
|
||||
- **R8** : les sommets à poids mixtes du cou (`chestUpper` et `neckLower`) sont dessinés entre leur place et l'**origine** de la
|
||||
matrice du parent. En effet `ApplyScale(0)` = `ScaleMatrix * M` annule les trois axes et garde la ligne de translation
|
||||
(`Matrix.inl:897-905` ; `SkeletalRender.cpp:486`, `:519`). Ce point est solidaire de `chestUpper`, à l'endroit où se trouvait
|
||||
l'origine du modèle en pose de liaison, donc loin sous le buste. D'où un « tube » de peau étiré (les « lambeaux » de
|
||||
`CAM-B1e-CART.md:72`). A ne le change pas, C ne le cache que près de la vue. Candidat (estimé) pour la « surface de peau
|
||||
cylindrique » de la capture 34.
|
||||
- **R9** : sans os `lCollar` / `rCollar`, `BodyForward` prend l'avant de l'acteur ; le témoin l'écrit (`acteur`). Une pose de meuble
|
||||
qui tourne le corps par rapport à l'acteur fausserait alors `avant` et `lacet` : sans effet sur A.
|
||||
- **R10** : compilation unitaire. Les noms neufs sont uniques (`CVarLPC1*`) ou dans l'espace nommé `LPCameraModeLocal` (`lp-build` § 8).
|
||||
|
||||
### 4.3 Questions pour l'utilisateur
|
||||
- **Q1** : quelles valeurs par défaut pour `lp.C1NearClip` et `lp.C1Forward` dans la build d'essai ? Proposition : 0 (aucun effet).
|
||||
Réglage à la console pendant T6, puis valeur retenue écrite dans le code, ou dans `[SystemSettings]` de `DefaultEngine.ini`, pour la
|
||||
Shipping.
|
||||
- **Q2** : la vue C1 doit-elle suivre les mouvements de tête des animations, au risque de plonger avec la tête dans la pose « repas » ?
|
||||
Si non, la position doit venir d'un os du buste plus un décalage fixe (option B du DIAG, voir `vue-buste` du témoin).
|
||||
- **Q3** : étendre A à la POV de sexe (personne filmée = joueur ou PNJ) dans une fiche à part ?
|
||||
|
||||
## 5. Interdits
|
||||
- Aucun changement de Room, PC, GI, Person ni d'asset ; aucun MCP ; aucun changement du plan proche global (`DefaultEngine.ini:50`).
|
||||
- Ne toucher à aucun maillage autre que `GI.PlayerCharacter->GetMesh()`. Les PNJ gardent leur option : la propriété est par instance
|
||||
de composant (`SkinnedMeshComponent.h:793-794`).
|
||||
- Pas d'appel direct à `RecalcRequiredBones` ni à `RecalcRequiredCurves` (R4) ; pas de décalage additif sur `FirstPersonSM` (§ 2.4).
|
||||
- Ne pas retirer ni modifier `LPStringCompat`, `LPMeshCompat`, `LPNavigationHelpers` et voisins (`lp-ue-compat` § 4).
|
||||
- Pas de compilation par l'IMPL (fiche BUILD à `lp-builder`), pas de commande git qui écrit, modification par Edit uniquement.
|
||||
|
||||
## 6. Valeurs moteur lues dans le moteur installé
|
||||
Moteur `D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\` (préfixe omis : `Engine/` sauf mention).
|
||||
- `Classes/Components/SkinnedMeshComponent.h:94-113` : `EVisibilityBasedAnimTickOption` ; `AlwaysTickPoseAndRefreshBones` = « Always
|
||||
Tick and Refresh BoneTransforms whether rendered or not ». Lignes `:787-794` : `VisibilityBasedAnimTickOption` est publique,
|
||||
`UPROPERTY(… BlueprintReadWrite, Config …)`, sans setter (Grep sur `Classes/Components` : seulement `:794`, `:797-798`, et des
|
||||
commentaires). Lignes `:1156`, `:1165` : `GetBoneIndex`, `GetBoneName` ; `:1263` : `GetParentBone` ; `:2014` : `GetBoneLocation` ;
|
||||
`:2153`, `:2161`, `:2171` : `HideBoneByName`, `UnHideBoneByName`, `IsBoneHiddenByName` (non const) ; `:1759-1772` : états de
|
||||
visibilité.
|
||||
- `Classes/Components/SkeletalMeshComponent.h:894-896` : `bRequiredBonesUpToDate` est public et transitoire ; à faux, les os requis
|
||||
sont recalculés au prochain passage. Lignes `:1862-1868` : `RecalcRequiredBones` (public) ; `:1885` : `ExcludeHiddenBones` ;
|
||||
`:1898` : `RecalcRequiredCurves`. Aucune API `MarkRequiredCurvesDirty` à appeler : `RecalcRequiredBones` marque les courbes à jour
|
||||
(`SkeletalMeshComponent.cpp:2400`) après le recalcul des instances d'animation (`:2383-2396`).
|
||||
- `Private/Components/SkeletalMeshComponent.cpp:1707-1718` (passage d'animation) et `:2879-2890` (`RefreshBoneTransforms`) :
|
||||
recalcul si le drapeau est faux. Lignes `:2246-2258` : les os demandés par les suiveurs sont ajoutés, puis les os masqués purgés.
|
||||
Lignes `:2296-2336` : `ExcludeHiddenBones` garde un os s'il est `BVS_Visible` **ou** si l'option vaut
|
||||
`AlwaysTickPoseAndRefreshBones` (`:2321-2322`). Lignes `:2358-2408` : `RecalcRequiredBones`. Lignes `:3933-3965` et `:3967-3983` :
|
||||
`HideBone` / `UnHideBone` mettent le drapeau à faux, sauf sur un suiveur (`:3942-3945`, `:3976-3979`).
|
||||
- `Private/Components/SkinnedMeshComponent.cpp:2119-2123` : un suiveur ne met pas à jour sa visibilité. Lignes `:2124-2163` :
|
||||
propagation `BVS_HiddenByParent`. Lignes `:4424-4448`, `:4482-4500` : masquage par nom et par index. Lignes `:2413-2434` et
|
||||
`:2468-2474` : position d'un os = transformée en espace composant (celle du leader pour un suiveur) × `LocalToWorld`.
|
||||
Lignes `:1805-1808`, `:1881-1897` : rafraîchissement selon le rendu ou l'option.
|
||||
- `Private/SkeletalRender.cpp:453`, `:458-466` : le rendu parcourt les os actifs de la LOD (`ActiveBoneIndices`), **pas** les os
|
||||
requis. Lignes `:483-487` (suiveur, états du leader) et `:516-520` (sans leader) : un os non visible reçoit la matrice du parent à
|
||||
l'échelle 0. **Un os masqué mais requis reste invisible au rendu.** Établi.
|
||||
- `Core/Public/Math/Matrix.inl:897-905` : `ApplyScale` = `ScaleMatrix * M` ; la ligne de translation de M est gardée (R8).
|
||||
- `Classes/GameFramework/Character.h:487` : `GetMesh() const` rend un pointeur non const.
|
||||
`Classes/Camera/PlayerCameraManager.h:705` : `GetCameraLocation() const`. `Classes/Camera/CameraModifier.h:95` :
|
||||
`ModifyCamera(float, FMinimalViewInfo&)`.
|
||||
- `Classes/Camera/CameraTypes.h:92-94`, `:178`, `:216-219` : `PerspectiveNearClipPlane` (négatif = plan global, -1 par défaut).
|
||||
`Private/Camera/CameraStackTypes.cpp:342` (et `:210`) : pris par la projection. `Private/LocalPlayer.cpp:1285` : appel de la vue du
|
||||
joueur. `Classes/Camera/CameraComponent.h:84-86` : seul un plan proche orthographique existe sur la caméra ;
|
||||
`Private/Camera/CameraComponent.cpp:448-461` : décalage additif.
|
||||
- `Private/UnrealEngine.cpp:19090-19102` : commande console `r.SetNearClipPlane <cm>`, minimum 1, 20 sans argument, réglage
|
||||
**global**. Aucune garde de compilation lue entre les l. 19050 et 19102 ; présence en Development estimée.
|
||||
- `Core/Public/HAL/IConsoleManager.h:2028` : `TAutoConsoleVariable(const TCHAR* Name, const T& DefaultValue, const TCHAR* Help, uint32 Flags = ECVF_Default)`.
|
||||
- Configuration : `Engine/Config/BaseEngine.ini:361` `NearClipPlane=10.0` ; projet `Config/DefaultEngine.ini:50`
|
||||
`NearClipPlane=1.000000` ; console `Config/DefaultInput.ini:166-168` (`Tilde`, `²`).
|
||||
- Leader et suiveurs dans le jeu : Room masque sur `PlayerCharacter.Mesh` = `CharacterMesh0` (`CAM-B1-IMPL.md:87` ;
|
||||
`CAM-B1e-CART.md:48`, `:61`). Ce maillage est le leader de `HairSM`, `PenisSM` et des tenues (`SetLeaderPoseComponent(Mesh)`,
|
||||
`CAM-B1e-CART.md:52-57`). Les suiveurs lisent les transformées et la visibilité du leader : A ne demande rien sur eux.
|
||||
|
||||
## 7. Critères de VAL (commande → attendu)
|
||||
|
||||
### 7.1 Contrôles de code et de build (`lp-validator`, après BUILD par `lp-builder`)
|
||||
1. `git -C "D:\Game\LifePlay-master 5.8" diff --stat` → les 4 fichiers du § 2 seulement, ou 2 si C n'est pas retenue.
|
||||
2. Grep `VisibilityBasedAnimTickOption` sur `Source/` → occurrences dans `LPCameraModeSubsystem.cpp` seulement. Grep
|
||||
`RecalcRequiredBones|ApplyScale|AddAdditiveOffset` sur `Source/LifePlay` → 0.
|
||||
3. `.\Tools\Build.ps1 -Lot ERR145` (LifePlayEditor) → code 0, module `LifePlay` compilé, 0 C4996 nouveau, « autres lignes : 20 ».
|
||||
Puis build Development empaquetée neuve (`BuildDebug.ps1`, `-ArchiveDir` neuf) pour l'utilisateur.
|
||||
4. Journal de l'essai : `.\Tools\LogStats.ps1 -Log <LifePlay.log> -Pattern 'Temoin C1', 'C1 : os'` → une ligne « gardes animes » par
|
||||
entrée en C1, une ligne « rendus » par sortie, et des lignes « Temoin C1 » à 1 s d'écart en C1.
|
||||
|
||||
### 7.2 Cahier de tests pour l'utilisateur
|
||||
Essai dans une build donnée ; console = touche ² ; chaque ligne rapporte « vue correcte / non », plus une capture si non.
|
||||
- **T0, sans build, sur COM23, maintenant** (oriente le défaut de C, Q1) :
|
||||
- T0a : s'asseoir à la même chaise « repas », en C1. Faire trois cycles C (C2 → C3 → C1) espacés de 5 s, en regardant à l'horizontale.
|
||||
La vue change d'un cycle à l'autre (plus ou moins basse) → L1 (gel à une phase de la boucle) ; toujours la même → L2.
|
||||
- T0b : dans la vue mauvaise, `r.SetNearClipPlane 10`, puis `r.SetNearClipPlane 20` ; noter si la peau proche disparaît.
|
||||
Remettre ensuite `r.SetNearClipPlane 1` (valeur du projet), ou relancer le jeu.
|
||||
- T0c : même essai sur une chaise sans repas (autre action « Sit »).
|
||||
- **T1, recette du DIAG § 1** (build ERR145) : debout → C1 → s'asseoir sans quitter C1 → regarder autour, en bas, à l'horizontale.
|
||||
Attendu : vue depuis les yeux, plus de corps décapité vu de dehors. Témoin : `yeux-buste` = R0 ± 5, `option os 0`, `cou masque=1`.
|
||||
- **T2, preuve par bascule** : même recette avec `lp.C1RefreshBones 0` → le défaut d'origine revient, et `yeux-buste` s'écarte de R0 de
|
||||
plus de 10 cm. Puis `lp.C1RefreshBones 1` → la vue revient aux yeux dans la seconde.
|
||||
- **T3, lever en C1** (ERR-111, ERR-106) : assis en C1, se lever (Z) sans quitter C1. Attendu : caméra aux yeux, pas à côté de la tête ;
|
||||
témoin : `yeux-buste` = R0 ± 5 et `assis=0`.
|
||||
- **T4, cycle C** debout et assis : aucun écart ; une ligne « C1 : os … rendus » à chaque sortie de C1.
|
||||
- **T5, PNJ et scènes inchangés** : en C2, PNJ assis et en marche (tête visible, aucun changement) ; lancer une scène depuis C1 (ligne
|
||||
« rendus » à l'entrée), POV sur le partenaire (tête normale), retour en C1 après la scène.
|
||||
- **T6, compléments** (si T1 assis reste mauvais, pose « repas ») : `lp.C1NearClip 10`, puis 15 ; remettre à 0 ; `lp.C1Forward 10`,
|
||||
puis 20 ; remettre à 0. Noter le réglage qui donne une vue correcte et recopier trois lignes « Temoin C1 » de chaque réglage.
|
||||
|
||||
### 7.3 Effet attendu sur ERR-106 et ERR-111
|
||||
- **ERR-111** (`Registre_Erreurs.md:118`). Volet « C1 à côté de la tête après un lever … un cycle C corrige » : même mécanisme dans le
|
||||
sens inverse (yeux figés assis, corps levé). **Corrigé par A** (estimé fort), preuve par T3. Volets « vue au plafond au retour d'une
|
||||
scène » (orientation, B2s) et « à-coup à la sortie de CharGen » : sans effet attendu de A.
|
||||
- **ERR-106** (`Registre_Erreurs.md:113`). Résidu « décalage après un lever » : **corrigé par A** (estimé fort). Le recalage de B2k à
|
||||
chaque passage de minuterie lit enfin des yeux vivants. La partie principale (caméra posée une seule fois) était déjà corrigée par B2k.
|
||||
- **ERR-145** (`Registre_Erreurs.md:152`) : volet « entré debout puis assis » corrigé par A (T1, T2) ; volet « capture 34 » (assis,
|
||||
après cycle) : A plus un complément C, selon T0 et T6.
|
||||
|
||||
Fichiers à commiter :
|
||||
- `A Docs/Migration/etat/REL/ERR145/ERR145-SPEC.md` (dépôt du jeu, branche `ue5.8`)
|
||||
|
||||
Tours : 30 / 60
|
||||
|
||||
## Constats
|
||||
- Écart au périmètre de la fiche : la partie C touche `LPRoomBoundsCameraModifier.h/.cpp`, non nommés par la fiche. Raison : aucun
|
||||
plan proche par vue n'existe sur `UCameraComponent` en 5.8 (§ 2.4). Partie séparable, décision de l'orchestrateur.
|
||||
- Écart au DIAG : la plage du témoin « 15 à 40 cm » (`ERR145-DIAG.md:103`) devient « R0 ± 5 », calée sur la première ligne debout de la
|
||||
build. Les 20 à 35 cm sont une estimation Genesis 8 non mesurée.
|
||||
- Le journal COM23 contient aussi, à l'action « Sit », trois `Divide by zero: Divide_DoubleDouble` de GI (l. 1740-1745) : sans lien
|
||||
établi avec ERR-145.
|
||||
- Il reste à vérifier, par MCP en lecture (hors fiche) : la hiérarchie Genesis 8 sous `chestUpper` (`get_bone_children`), et
|
||||
l'existence de `lCollar` / `rCollar` sur Michael et Bridget. Le témoin écrit aussi `clavicules` ou `acteur`.
|
||||
180
Docs/Migration/etat/REL/FIX1/FIX1-F6-IMPL.md
Normal file
180
Docs/Migration/etat/REL/FIX1/FIX1-F6-IMPL.md
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
Fiche FIX1-F6-IMPL — Niveau N3 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-impl — Skills sk-protocol, ue-cpp-build, lp-paths
|
||||
# FIX1-F6-IMPL : redirection de `Saves/…` vers le dossier de sauvegarde, voie C++ (2026-10-20)
|
||||
|
||||
Ordre de l'utilisateur, cité par la fiche : « Oui, les 7 recommandations de FIX1-F6-SPEC (Q1 à Q7) ; lance l'IMPL. »
|
||||
Base : `FIX1-F6-SPEC.md` § 2.1 (étapes a à g). Ordonnateur : Big Boss (`local_104ff22d`), qui a donné le jeton UE.
|
||||
Hors gabarit : la compilation de contrôle (demandée par la fiche) est rendue dans `## Constats`, avec sa note TRACE.
|
||||
Écart de skills : la fiche cite `sk-protocol, ue-cpp-build, lp-paths`. Dans mon contexte sont chargés `sk-protocol`, `ue-cpp-build`, `lp-build`, `lp-ue-compat` ; `lp-paths` ne l'est pas (non utilisé : aucun chemin de dépôt à décider).
|
||||
Niveaux de preuve : **établi** (fichier:ligne ou sortie de commande), **estimé** (raisonnement donné), **inconnu** (essai nommé).
|
||||
|
||||
## 1. Fichiers modifiés
|
||||
|
||||
Un seul fichier de source : `D:\Game\LifePlay-master 5.8\Plugins\ModdingExtra\Source\ModdingExtra\Private\ModdingExtraBPLibrary.cpp`.
|
||||
|
||||
| Mesure | Valeur | Commande |
|
||||
|---|---|---|
|
||||
| MD5 avant (exigé `7628837e…`) | `7628837e7b77c68c3921acfad3d92ec0`, conforme | `md5sum` avant la première édition |
|
||||
| MD5 après | `1f93601c71d126f173fe30636aec0660` | `md5sum` après les 7 éditions et après les 2 builds (inchangé) |
|
||||
| Fins de ligne | `i/lf w/lf attr/-text` ; 0 CR | `git ls-files --eol` ; `tr -cd '\r' \| wc -c` -> `0` |
|
||||
| Bilan du diff | `1 file changed, 120 insertions(+), 2 deletions(-)` | `git diff --stat -- Plugins/ModdingExtra` |
|
||||
| Autres fichiers touchés dans `Plugins/ModdingExtra` | aucun | `git status --porcelain -- Plugins/ModdingExtra` -> une seule ligne ` M …ModdingExtraBPLibrary.cpp` |
|
||||
|
||||
Étapes appliquées avec l'outil Edit, dans l'ordre a à g (numéros de ligne du fichier **après** édition) :
|
||||
|
||||
| Étape | SPEC | Lignes finales | Contenu |
|
||||
|---|---|---|---|
|
||||
| a | § 2.1 a | 15-16 | `#include "Misc/CommandLine.h"`, `#include "Misc/Parse.h"` après `Misc/Paths.h` (:14) |
|
||||
| b | § 2.1 b | 30-140 (espace de noms `LPSavesRedirect` : 36-140) | `IsDisabled` :40, `Match` :48, `Note` :67, `ResolvePath` :89, `WarnListOnSaves` :124 ; placé après `DEFINE_LOG_CATEGORY_STATIC` (:29), avant le constructeur (:142) |
|
||||
| c | § 2.1 c | 156 | `LPSavesRedirect::WarnListOnSaves(TEXT("GetAllFilesFromFolder"), RootFolderFullPath);` après le garde `Len() < 1` de `GetAllFilesFromFolder` |
|
||||
| d | § 2.1 d | 231 | `LPSavesRedirect::WarnListOnSaves(TEXT("GetAllSubfolders"), RootFolderFullPath);` après le garde de `GetAllSubfolders` |
|
||||
| e | § 2.1 e | 269-271 | ligne `Saves : %d lecture(s) nouvelle racine \| %d lecture(s) repli \| %d ecriture(s)%s` dans `LPLoadTxtStats::Dump`, après la ligne `TOTAL` |
|
||||
| f | § 2.1 f | 308 | `LoadTxt` |
|
||||
| g | § 2.1 g | 354 | `SaveTxt` |
|
||||
|
||||
Les deux seules lignes retirées (étapes f et g), texte exact :
|
||||
|
||||
```cpp
|
||||
- const bool bOk = bFromCache || FFileHelper::LoadFileToString(SaveTextA, *(FPaths::ProjectContentDir() + FileNameA));
|
||||
+ const bool bOk = bFromCache || FFileHelper::LoadFileToString(SaveTextA, *LPSavesRedirect::ResolvePath(FileNameA, false));
|
||||
- const bool bOk = FFileHelper::SaveStringToFile(SaveTextB, *(FPaths::ProjectContentDir() + FileNameB));
|
||||
+ const bool bOk = FFileHelper::SaveStringToFile(SaveTextB, *LPSavesRedirect::ResolvePath(FileNameB, true));
|
||||
```
|
||||
|
||||
Lignes laissées intactes, comme l'exige la SPEC (§ 1.3, § 5) : relecture de vérification `:313` (ex-`:195`, `ProjectContentDir() + FileNameA`), `Cache.TryGet(FileNameA, …)` :307, `LPLoadTxtStats::Record(FileNameA, …)` :309, `OnWritten(FileNameB, SaveTextB)` :357 (ex-`:239`).
|
||||
|
||||
**Conformité du texte à la SPEC (établi).** Les 120 lignes `+` des blocs a à g de la SPEC (lignes 104-255, filtrées par `grep '^+'`, préfixe retiré) ont été comparées aux 120 lignes ajoutées par `git diff -U0` (même filtre) :
|
||||
|
||||
```
|
||||
sed -n '104,255p' FIX1-F6-SPEC.md | tr -d '\r' | grep '^+' | sed 's/^+//' -> 120 lignes
|
||||
git diff -U0 -- <fichier> | tr -d '\r' | grep '^+' | grep -v '^+++' | sed 's/^+//' -> 120 lignes
|
||||
diff : "3d2 < (vide)" et "113a113 > (vide)"
|
||||
```
|
||||
|
||||
Le seul écart du `diff` est la **place d'une ligne vide** : git l'affiche en fin de bloc b (avant le constructeur), la SPEC la montre en tête. Le texte final est le même : l. 29 `DEFINE_LOG_CATEGORY_STATIC`, l. 30 vide, l. 31 début du commentaire, l. 140 `}`, l. 141 vide, l. 142 constructeur (lu avec Read). Aucune ligne n'a été changée.
|
||||
|
||||
Vérification des API moteur employées (moteur 5.8, `D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Core`, lecture directe, toutes établies) :
|
||||
|
||||
| API | Source |
|
||||
|---|---|
|
||||
| `FPaths::ProjectContentDir()` (retourne `FString`) | `Public/Misc/Paths.h:276` |
|
||||
| `FPaths::ProjectSavedDir()` (`const FString&`) | `Paths.h:290` |
|
||||
| `FPaths::ConvertRelativePathToFull(const FString&)` | `Paths.h:637` |
|
||||
| `ProjectSavedDir` : `BaseDir + "Saved"` puis `+ "/"` ; `ProjectContentDir` : `ProjectDir() + "Content/"` | `Private/Misc/Paths.cpp:87, 107, 477` |
|
||||
| `IFileManager::DirectoryExists(const TCHAR*)` | `Public/HAL/FileManager.h:119` |
|
||||
| `FString::FindChar(ElementType, int32&)` | `Public/Containers/UnrealString.h.inl:1219` |
|
||||
| `FString::Equals(const FString&, SearchCase = CaseSensitive)`, `[[nodiscard]]` | `UnrealString.h.inl:1271` |
|
||||
| `FString::StartsWith(const TCHAR*, SearchCase = IgnoreCase)`, `[[nodiscard]]` | `UnrealString.h.inl:1505` |
|
||||
| `FString::Left(int32)`, `Mid(int32)`, `ToLower() const &`, `ReplaceInline(const TCHAR*, const TCHAR*, SearchCase)` | `UnrealString.h.inl:950, 1029, 1344, 1838` |
|
||||
| `FParse::Param(const TCHAR*, const TCHAR*)` | `Public/Misc/Parse.h:127` |
|
||||
| `FCommandLine::Get()` | `Public/Misc/CommandLine.h:58` |
|
||||
| `TSet::Add(const T&, bool*)`, `Add(T&&, bool*)` | `Public/Containers/SparseSet.h.inl:415, 419` (`Set.h` redirige `TSet` vers ce fichier, `Set.h:12-31`) |
|
||||
|
||||
## 2. Écarts à la SPEC
|
||||
|
||||
1. **Aucune correction de code n'a été nécessaire** : le diff a compilé tel quel (0 erreur, aucun avertissement venant de `ModdingExtraBPLibrary.cpp`, voir Constats).
|
||||
2. **Place de la ligne vide du bloc b** dans le `git diff` : présentation seulement, texte identique (§ 1 ci-dessus). Pas un écart de texte.
|
||||
3. **Taille du diff** : la SPEC annonce « ≈ 90 lignes » (résumé), « ≈ 100 lignes » (§ 2.1) et « ≈ 100 insertions » (V1). Le diff exact de la SPEC compte **120 lignes ajoutées**, 2 retirées. L'estimation de la SPEC était basse ; le texte appliqué est celui de la SPEC, pas une version raccourcie. La VAL doit lire V1 comme « 1 fichier, 120 insertions, 2 suppressions ».
|
||||
4. **Numéros de ligne cités par la SPEC** (`:190`, `:236`, `:195`, `:239`) : décalés de +118, +118, +118, +118 après l'insertion. Les lignes finales sont dans le tableau du § 1.
|
||||
5. **Alerte `CopieEtat.ps1 -Lot FIX1`** (code 1, `alertes=GIT`) : `jeu [ M] Source/LifePlay/LPKeyboardSubsystem.cpp`. Fichier modifié **avant** ce lot (présent dans le `git status` de départ, lot KEY2), donc hors périmètre. Il n'a pas été touché. Conséquence sur les binaires : voir Constats.
|
||||
6. **Section « Instantané »** : l'instantané a été pris par l'appelant avant mon intervention ; je ne l'ai pas refait (consigne de la fiche).
|
||||
|
||||
## 3. Instantané
|
||||
|
||||
- Dossier : `D:\Game\LifePlay_Backup_5.5\FIX1\` (lot FIX1), pris par l'ordonnateur.
|
||||
- Manifeste `D:\Game\LifePlay_Backup_5.5\FIX1\manifest.csv` : une ligne, `Plugins/ModdingExtra/Source/ModdingExtra/Private/ModdingExtraBPLibrary.cpp`, `Existed=True`, `Size=11994`, `MD5=7628837E7B77C68C3921ACFAD3D92EC0`, `Date=2026-10-20T19:04:55`.
|
||||
- Contrôle (établi) : `md5sum` de la copie de l'instantané -> `7628837e7b77c68c3921acfad3d92ec0`, identique au MD5 de départ du fichier du jeu.
|
||||
- Retour arrière à froid : `Tools\Restore.ps1 -Lot FIX1` (proposé, non lancé), ou `git revert` du commit d'IMPL ; recompilation ensuite (SPEC § 3).
|
||||
|
||||
## 4. Ce qui n'a pas été fait
|
||||
|
||||
- Aucun autre fichier : ni `.h`, ni `Build.cs`, ni `.uplugin`, ni Blueprint, ni GI, ni `LPDataCache.*`, ni `Source/LifePlay/*` (SPEC § 5).
|
||||
- Pas de build **Shipping**, pas d'empaquetage (`BuildDebug.ps1`), aucun jeu lancé : les essais E1-E9 (SPEC § 7.2) ne sont pas faits.
|
||||
- Pas de VAL (relecture indépendante), pas de DOC (README `:23-24, 74, 82-83, 117`, ERR-042, guides de modding Q2, REF1, doc 37 : lot DOC, Q2 « plus tard »).
|
||||
- Message de GI « copy your old LifePlay\Content\Saves folder… » non modifié (Q7 : build 2).
|
||||
- Aucune commande git qui écrit ; aucun commit ; rien publié.
|
||||
- Pas de relevé MD5 de `Content\Saves` ni de `<SavedDir>\Saves` : il se fait avant l'essai en jeu (SPEC § 7.2, préparation).
|
||||
- Pas de recherche du journal de référence « même build sans F6 » demandé par E8 : non cherché ici (voir § 5).
|
||||
- Pas de `Tools/FicheStats.py` : le nombre de tours ci-dessous est estimé par moi.
|
||||
|
||||
## 5. Points à confirmer en VAL
|
||||
|
||||
Un point par ligne. Les identifiants V1-V6 sont ceux de la SPEC § 7.1, les E1-E9 ceux de § 7.2.
|
||||
|
||||
- V1 : `git diff --stat -- Plugins/ModdingExtra` rend `1 file changed, 120 insertions(+), 2 deletions(-)` ; à accepter comme conforme malgré le « ≈ 100 » de la SPEC (écart 3).
|
||||
- V2 : relire `ResolvePath`, branche `!Match` (`ModdingExtraBPLibrary.cpp:92-95`) : `return FPaths::ProjectContentDir() + ContentRelativePath;`, expression identique à l'ancienne.
|
||||
- V3 : `:313` (relecture `bFromCache`), `:357` (`OnWritten(FileNameB, …)`), `:307` (`TryGet(FileNameA, …)`), `:309` (`Record(FileNameA, …)`) inchangés par rapport à l'instantané.
|
||||
- V4 : `_session` sans repli (`:107-111`) ; écriture jamais vers `ProjectContentDir()` quand la redirection est active (`:107-111` renvoie `NewPath` si `bForWrite`) ; l'ancien chemin n'est rendu que pour un chemin hors `Saves/` (`:92-95`) ou avec `-LPNoSavesRedirect` (`:96-105`).
|
||||
- V5 : `git ls-files --eol` du fichier -> `i/lf w/lf` (relevé ici : conforme, 0 CR).
|
||||
- V6 : build éditeur et build jeu à code 0, 0 erreur, aucun avertissement nouveau dans `ModdingExtraBPLibrary.cpp` ; seul avertissement : C4701 `Aim` (`LPCameraModeSubsystem.cpp:2378`), connu (relevé : conforme, voir Constats).
|
||||
- B1 : les binaires construits contiennent aussi la modification **non commitée** de `Source/LifePlay/LPKeyboardSubsystem.cpp` (lot KEY2) : `Module.LifePlay.cpp` a été recompilé pour cette raison, pas pour F6. L'essai E1-E9 se fait donc sur « F6 + KEY2 en cours », pas sur F6 seule. À signaler à l'ordonnateur avant de fixer le build de référence de la porte J4.
|
||||
- B2 : le build jeu Development est monolithique : `LifePlay.exe` embarque `ModdingExtra` (résumé `Build.ps1` : « DLL liées : 0 », journal `[4/5] Link [x64] LifePlay.exe`). Le « build Development du commun » demandé par SPEC § 7.2 est un **paquet** : il reste à le produire (`Tools\BuildDebug.ps1`, `-ArchiveDir` neuf, `lp-build` § 4) ; ce n'est pas fait ici.
|
||||
- B3 : Shipping non compilé. Les messages `UE_LOG` disparaissent en Shipping sans `bUseLoggingInShipping` (SPEC R5) ; une compilation Shipping pourrait lever des avertissements propres à cette configuration (variable inutilisée). **Inconnu** : à mesurer au premier build Shipping.
|
||||
- B4 : les chaînes nouvelles sont présentes dans les deux binaires (`LPNoSavesRedirect`, `Saves redirige`, `FIX1-F6`, recherche UTF-16 dans `UnrealEditor-ModdingExtra.dll` et `LifePlay.exe`, trois fois `True`). Cela prouve que le nouveau code est lié, pas qu'il s'exécute comme prévu.
|
||||
- E1-E4 : montage Development empaqueté, relevé MD5 de `<jeu>\Content\Saves` avant et après ; journal `LogModdingExtra: Display: Saves redirige : racine '…\Saved\Saves'` une fois, `Saves slot '_session' : nouvelle racine`.
|
||||
- E5 : copie d'un slot d'essai dans `<jeu>\Content\Saves\<SlotX>` (jamais l'original de l'alpha), son `.sav` dans `<SavedDir>\SaveGames` ; attendu `lu dans l'ancien Content/Saves (repli)` puis `nouvelle racine` après un enregistrement.
|
||||
- E6 : lancement avec `-LPNoSavesRedirect` : `Saves non redirige (-LPNoSavesRedirect)` et bilan `(redirection desactivee)`.
|
||||
- E7 : `Select-String -Path <journal> -Pattern 'FIX1-F6'` doit donner 0 ligne (aucune liste n'a visé `Saves`). Le texte du message d'avertissement contient `FIX1-F6`.
|
||||
- E8 : `ModdingExtra.LoadTxtStats` doit afficher `Saves : n lecture(s) nouvelle racine | m lecture(s) repli | k ecriture(s)` avec n > 0 et k > 0 ; la ligne `Cache de donnees pret : <x> fichier(s)` doit garder le même x qu'avant F6. **Inconnu** : quel journal sert de référence « même build sans F6 » (non cherché ; la référence doit tenir compte de B1).
|
||||
- E9 (Shipping, sur accord) : `%LOCALAPPDATA%\LifePlay-Revival\Saved\Saves\…` créé ; relevé de `<jeu>\Content\Saves` inchangé ; pas de journal en Shipping.
|
||||
- C1 : comportement à vérifier à la lecture, sans effet fonctionnel : un fichier posé directement dans `Saves/` (slot vide) journalise `Saves slot '' : nouvelle racine` (chaîne vide entre guillemets). Aucun usage connu (SPEC § 1.1, ligne 3).
|
||||
- C2 : `IsDisabled()` mémorise l'argument à son premier appel (variable `static const`) ; le premier appel survient au premier `LoadTxt`/`SaveTxt` sur un chemin `Saves/`, ou au `Dump`. L'interrupteur est lu après l'initialisation de la ligne de commande, donc sans risque d'ordre ; **estimé**, E6 le tranche.
|
||||
|
||||
## 6. Fichiers à commiter
|
||||
|
||||
Dépôt du jeu (`D:\Game\LifePlay-master 5.8`, branche `ue5.8`) :
|
||||
|
||||
- `M Plugins/ModdingExtra/Source/ModdingExtra/Private/ModdingExtraBPLibrary.cpp`
|
||||
- `A Docs/Migration/etat/REL/FIX1/FIX1-F6-IMPL.md`
|
||||
|
||||
Les deux résumés `FIX1_Build_20261020-190716.txt` et `FIX1_Build_20261020-190831.txt` sont écrits par `Build.ps1` dans `Docs/Migration/etat/REL/FIX1/` mais **ignorés par git** (`git check-ignore -v` : `.gitignore:75 /Docs/Migration/etat/**`, seul `*.md` est rétabli en `:77`) : rien à commiter pour eux. Ils sont en CRLF (48 et 25 CR, sortie du script, non retouchée) ; la règle « fins de ligne LF dans `etat/` » vise les fichiers suivis, donc sans objet ici. Contrôle du livrable : `FIX1-F6-IMPL.md` en LF (0 CR).
|
||||
|
||||
À **ne pas** inclure dans ce ticket (modifiés par d'autres lots, présents dans le `git status`) : `Source/LifePlay/LPKeyboardSubsystem.cpp`, `LifePlay.uproject`, les fichiers `Docs/Migration/etat/BOSS`, `REPO`, `REL/KEY2`, `REL/STM1`, `AG/ORGA2`, `Docs/LP-PROJET.ini`. Le gardien commite par chemins explicites (`sk-repo`).
|
||||
|
||||
Les journaux complets restent dans `Saved\Logs\portage\` (hors dépôt).
|
||||
|
||||
Tours : 36 / 60 (estimé ; `Tools/FicheStats.py --lot FIX1` fait foi)
|
||||
|
||||
## Constats
|
||||
|
||||
### Compilation de contrôle (demandée par la fiche)
|
||||
|
||||
Trace : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\FIX1\FIX1_Build_20261020-190716.txt` et `…\FIX1_Build_20261020-190831.txt` — Fiche FIX1-F6-IMPL — 2026-10-20 19:07 à 19:10
|
||||
Commande : `pwsh -NoProfile -File Tools/Build.ps1 -Lot FIX1 -EtatDir "D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\FIX1"` (éditeur), puis `… -Lot FIX1 -Target LifePlay -Config Development -ExtraArgs '-NoUBA' -EtatDir …` (jeu), dans `D:\Game\LifePlay-master 5.8`
|
||||
Environnement: copie 5.8, branche `ue5.8`, HEAD `b5feae4`, moteur UE 5.8 (`EngineAssociation 5.8`), machine calme (`UeState` : `processus=0 editeur=0 compilation=0 shaders=0 jeu=0` avant, entre et après), `CopieEtat.ps1 -Lot FIX1` lancé avant (`proc=0`)
|
||||
Attendu : code 0 ; 0 erreur ; aucun avertissement nouveau ; seul le C4701 `Aim` connu ; unités `ModdingExtraBPLibrary.cpp` + `Module.ModdingExtra.cpp` recompilées
|
||||
Obtenu : tableau ci-dessous
|
||||
Lecture : le champ `Makefile` des deux résumés est vide ; les journaux disent `Invalidating makefile for LifePlayEditor (working set of source files changed)` (l. 8 du journal 1) et `… for LifePlay …` (l. 8 du journal 2) : makefiles recréés. Le résumé du build jeu écrit « Unreal Build Accelerator local executor » alors que `-NoUBA` est passé : les unités sont marquées `[NoUba]`, le texte du résumé n'est pas le signe fiable.
|
||||
|
||||
| Mesure | Build 1 : LifePlayEditor Win64 Development | Build 2 : LifePlay Win64 Development `-NoUBA` |
|
||||
|---|---|---|
|
||||
| Résumé | `…\REL\FIX1\FIX1_Build_20261020-190716.txt` | `…\REL\FIX1\FIX1_Build_20261020-190831.txt` |
|
||||
| Journal | `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\FIX1_Build_20261020-190716.log` | `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\FIX1_Build_20261020-190831.log` |
|
||||
| Code de sortie, durée | 0 ; 58 s (`Total execution time: 57.83 seconds`) | 0 ; 61 s (`Total execution time: 60.91 seconds`) |
|
||||
| Ligne `Using Visual Studio` | `14.50.35739 toolchain (…\MSVC\14.50.35717) and Windows 10.0.22621.0 SDK` = MSVC épinglé de la copie 5.8 | identique |
|
||||
| Actions | 10 | 5 |
|
||||
| Erreurs du compilateur | 0 | 0 |
|
||||
| Avertissements du compilateur | 1 : C4701 `Aim`, `LPCameraModeSubsystem.cpp:2378` (connu) | 1 : le même (connu) |
|
||||
| Autres lignes (UBT, UHT, liens) | 20 : toutes `Plugin 'HyperAIStudio' does not list plugin '…'` (nombre attendu pour LifePlayEditor, `lp-build` § 7) | 0 (attendu pour la cible jeu) |
|
||||
| Unités compilées | 3 : `ModdingExtraBPLibrary.cpp`, `Module.LifePlay.cpp`, `Module.ModdingExtra.cpp` | 3 : les mêmes (`[NoUba]`) |
|
||||
| DLL liées / exécutable | 3 DLL : `UnrealEditor-LifePlay.dll`, `UnrealEditor-LifePlayEditorTools.dll`, `UnrealEditor-ModdingExtra.dll` | 0 DLL (cible monolithique) ; `[4/5] Link [x64] LifePlay.exe` |
|
||||
| `[Adaptive Build] Excluded from … unity file` | `LifePlay`: `LPKeyboardSubsystem.cpp` ; `ModdingExtra`: `ModdingExtraBPLibrary.cpp` | les mêmes |
|
||||
|
||||
Avertissement nouveau : aucun. Le module modifié figure dans les unités compilées et dans les DLL liées (`lp-build` § 9, points 4 et 6).
|
||||
|
||||
MD5 des produits (`md5sum`, après les deux builds) :
|
||||
|
||||
| Fichier | MD5 | Taille, heure |
|
||||
|---|---|---|
|
||||
| `Plugins\ModdingExtra\Binaries\Win64\UnrealEditor-ModdingExtra.dll` | `7e8eeec53c104ffd0ea3673addb64cb6` | 416 768 o, 19:08:14 |
|
||||
| `Binaries\Win64\LifePlay.exe` | `811f72f20545613b93eb913f384ca1b2` | 335 846 400 o, 19:09:31 |
|
||||
| `Binaries\Win64\UnrealEditor-LifePlay.dll` | `e5d2c9c9c27ac70c0be27871eaf224c0` | 1 992 704 o, 19:08:04 |
|
||||
| `Plugins\ModdingExtra\Source\ModdingExtra\Private\ModdingExtraBPLibrary.cpp` | `1f93601c71d126f173fe30636aec0660` | (source) |
|
||||
|
||||
Preuve de liaison du nouveau code : recherche UTF-16 des chaînes `LPNoSavesRedirect`, `Saves redirige`, `FIX1-F6` dans `UnrealEditor-ModdingExtra.dll` et `LifePlay.exe` : 3 fois `True` pour chacun. **Inconnu** : le comportement à l'exécution (essai E1-E9).
|
||||
|
||||
### Autres contrôles
|
||||
|
||||
- `pwsh -NoProfile -File Tools/PubCheck.ps1 -Fichiers Plugins/ModdingExtra/Source/ModdingExtra/Private/ModdingExtraBPLibrary.cpp -Depot "D:/Game/LifePlay-master 5.8"` (stdin `/dev/null`) -> `PubCheck : 0 constat(s)`, code 0.
|
||||
- PubCheck du livrable et des deux résumés de build : `pwsh -NoProfile -Command "& './Tools/PubCheck.ps1' -Fichiers '<f1>','<f2>','<f3>' -Depot 'D:/Game/LifePlay-master 5.8'"` (stdin `/dev/null`) -> `PubCheck : 0 constat(s)`, code 0. Piège : la forme `pwsh -File … -Fichiers <f1> -Fichiers <f2>` de `Tools\LISEZMOI.md` échoue (paramètre `-Fichiers` « spécifié plusieurs fois », code 1) ; la liste se passe en tableau, par `-Command` (comme `lp-build` § 8 pour `UeState`).
|
||||
- Fin de mission : `Tools\UeState.ps1` -> `processus=0 editeur=0 compilation=0 shaders=0 jeu=0`, code 0 ; jeton UE rendu.
|
||||
- Scripts : aucun script écrit. Deux fichiers de comparaison temporaires (lignes `+` de la SPEC et du diff) sont restés dans le dossier temporaire de la session, hors dépôt.
|
||||
178
Docs/Migration/etat/REL/FIX1/FIX1-F6-PRE.md
Normal file
178
Docs/Migration/etat/REL/FIX1/FIX1-F6-PRE.md
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
Fiche FIX1-F6-PRE — Niveau N2 — Modèle prévu non précisé par la fiche | utilisé claude-sonnet-5-5 — Agent lp-cart — Skills sk-protocol, ue-cpp-build, lp-commandlets, lp-paths
|
||||
# FIX1-F6-PRE : étude préliminaire de dimensionnement de F6, ERR-042, personnages de partie dans `Content\Saves` (2026-10-20)
|
||||
|
||||
Hors gabarit : étude préliminaire (pas une CART complète). Les rubriques 1 à 6 du gabarit CART sont gardées ; la rubrique 3 suit les quatre questions de la fiche (existant, localisation, dimensionnement, recommandation). Lecture seule : ni copie UE, ni MCP, ni éditeur, ni commandlet. Seul ce fichier est écrit.
|
||||
|
||||
## Résumé (à lire en premier)
|
||||
|
||||
1. **Ce qui reste d'ERR-042** : les fichiers `.lpcharacter` d'une partie sont lus et écrits dans `<dossier du jeu>\Content\Saves\…`, hors du nouveau dossier `%LOCALAPPDATA%\LifePlay-Revival\Saved` (établi : `Docs/Registre_Erreurs.md:49`, `README.md:82-83`).
|
||||
2. **Point d'étranglement unique en C++** : tous les accès Blueprint à ces fichiers passent par `UModdingExtraBPLibrary::LoadTxt` et `::SaveTxt`, qui préfixent `FPaths::ProjectContentDir()` (établi : `Plugins/ModdingExtra/Source/ModdingExtra/Private/ModdingExtraBPLibrary.cpp:190, 236`). Rediriger les chemins `Saves/…` à cet endroit demande 1 fichier C++ et **0 Blueprint** (estimé, à prouver en SPEC).
|
||||
3. **GI n'est pas exigé** par cette voie (estimé). La voie Blueprint, elle, toucherait GI (29 littéraux `Saves/…`) et au moins 3 widgets UI : à écarter.
|
||||
4. **La ligne du doc 37 est mal classée** : `37_Feuille_De_Route_Alpha2.md:171` range F6 dans « petits correctifs Blueprint par MCP, `lp-mcp-bp` ». L'existant dit autre chose : c'est un correctif C++ dans un plugin, sur le chemin de lecture de toutes les données du jeu.
|
||||
5. **Recommandation** : lot **N3** ; SPEC par un modèle opus (effort medium) ; IMPL par `lp-impl` (Sonnet) sur une SPEC qui dicte les lignes, ou `lp-impl-max` si la SPEC laisse des choix ; BUILD `lp-builder` ; VAL `lp-validator` distinct ; essai en jeu sous le jeton de la copie UE. **Build 1 sous condition** (porte au J4), sinon build 2 et la limite connue reste documentée. Détail en § 3.4.
|
||||
|
||||
## 1. Objet et périmètre
|
||||
|
||||
Un domaine : l'emplacement des fichiers `.lpcharacter` d'une partie (ERR-042, reste). Question posée par Big Boss : quel agent et quel modèle pour F6 (doc 37 § 1.2, ligne 59), build 1 (gel 2026-10-24) ou build 2. Hors périmètre : le dossier `SaveGames` et les réglages `*.ini` (déjà traités par REL-SAV), le contenu des modules, toute correction.
|
||||
|
||||
## 2. Commandes et lectures (exactes) avec compte brut
|
||||
|
||||
| # | Commande ou lecture | Résultat brut |
|
||||
|---|---|---|
|
||||
| 1 | Grep `ERR-042` dans `Docs` | ligne `Registre_Erreurs.md:49` ; `37_Feuille_De_Route_Alpha2.md:59` ; `BOSS-JOURNAL.md:983` |
|
||||
| 2 | Glob `**/SAV1*` sous `Docs/Migration/etat` | `No files found` (aucun dossier SAV1) |
|
||||
| 3 | Glob `**/REL-SAV*` sous `Docs/Migration/etat` | 13 fichiers dans `REL/SAV/` (DIAG, SPEC, IMPL, VAL, ESSAIS, DOC, TACHES, RESULTATS-COMMUN8, `fiches/T1-T4`) et `REPO/tickets/REL-SAV-R1.md` |
|
||||
| 4 | Read `REL-SAV-DIAG.md`, `REL-SAV-SPEC.md`, `REL-SAV-IMPL.md`, `Registre_Erreurs.md:49`, `37_…:30-100, 140-198` | cités en § 3 |
|
||||
| 5 | Grep `lpcharacter` dans `Source` (insensible à la casse) | 1 résultat : `Source/LifePlay/LPStringCompat.h:9` (commentaire) |
|
||||
| 6 | Grep `Content[\\/]+Saves\|"Saves\|/Saves/` dans `Source` | `No matches found` |
|
||||
| 7 | Grep `"Saves\|/Saves/\|Content/Saves\|lpcharacter` dans `Plugins` (`*.cpp,*.h,*.cs,*.py,*.ini`) | `No files found` (Plugins/Marketplace et McpAutomationBridge, ignorés par git, non parcourus) |
|
||||
| 8 | Grep `Saves` dans `Config` | `No matches found` |
|
||||
| 9 | Glob `Content/Saves/*` | `No files found` (dossier absent de la copie 5.8 ; `.gitignore:84` : `/Content/Saves/`) |
|
||||
| 10 | Grep `'Saves/` dans `Docs/Migration/etat/portage55/L6f/L6f_dump_GI.txt` (dump 5.5 de toutes les fonctions de GI, 2026-09-30) | 29 lignes (liste § 3.2) |
|
||||
| 11 | Grep `= 'Saves/\|'Saves/` en `*.txt` sous `etat` | 38 fichiers, tous des dumps GI (ou 1 fichier CAM-T6) |
|
||||
| 12 | Grep `appel ModdingExtraBPLibrary::(LoadTxt\|SaveTxt)` dans `L6f_dump_GI.txt` | 45 lignes (nœuds d'appel dans GI) |
|
||||
| 13 | `rg -a -l -e "Saves/_session" -e "Saves/Characters" -e "\.lpcharacter" -g "*.uasset" -g "*.umap" Content` (Bash, depuis la racine) | 6 fichiers : `Content/UI/BodyShapeMenu`, `UI/CharGen`, `UI/ContactMenu`, `UI/Contact`, `UI/StatMenu`, `BPs/GI` (.uasset) ; code de sortie 0 |
|
||||
| 14 | `rg -a -o -e 'Saves[A-Za-z_/]*' -e '[A-Za-z]*\.lpcharacter' <fichier>` puis `sort \| uniq -c` | tableau § 3.2 (comptes **bruts de correspondances dans le binaire**, pas de nœuds) |
|
||||
| 15 | `git ls-files Plugins/ModdingExtra \| wc -l` ; `git check-ignore -v Content/Saves/x` | `8` ; `.gitignore:84:/Content/Saves/` |
|
||||
|
||||
Écart de méthode à signaler : les commandes 13 et 14 passent par `rg -a` en Bash. L'outil Grep ne lit pas un `.uasset` en mode texte quand il parcourt un dossier : le Grep sur le dossier `Content` (motif `Saves/_session`, `*.uasset`) a rendu `No files found`, alors que le Grep sur le seul fichier `Content/BPs/GI.uasset` rend 54 occurrences. **Un résultat vide d'un Grep de dossier sur des `.uasset` ne prouve donc rien** (à verser).
|
||||
|
||||
## 3. Constats `fichier:ligne`
|
||||
|
||||
### 3.1 État de l'existant (question 1)
|
||||
|
||||
| Constat | Source | Niveau |
|
||||
|---|---|---|
|
||||
| ERR-042 porte le lot « SAV1 » et dit : dossier de sauvegarde partagé avec le jeu d'origine ; REL-SAV a posé la garde `LPSaveRelaunch` ; E9 PASS sur le Shipping `2026.10.2.1a` ; **reste** : « les personnages d'une partie sauvegardée restent dans le dossier du jeu (`LifePlay\Content\Saves`), annoncé comme limite connue de l'alpha » ; E5 non fait (facultatif) ; Mod Manager à refaire avec un zip | `Docs/Registre_Erreurs.md:49` | établi |
|
||||
| Le lot SAV1 n'a **aucun dossier** `etat/` propre ; son travail est le lot REL-SAV (`etat/REL/SAV/`). Le Cahier des charges le cite (§ 6) | Glob n° 2 et n° 3 ; `Registre_Erreurs.md:49` ; `Docs/21_Sandbox_Addon.md:213` | établi |
|
||||
| **Option retenue : B+ seul** (garde dans le jeu qui relance l'exe avec `-UserDir`), **aucun lanceur livré** (option B écartée) | `REL-SAV-SPEC.md:7-16` (« Aucun lanceur n'est donc livré », l. 16) | établi |
|
||||
| Aucune reprise des anciennes sauvegardes (décision R0) | `REL-SAV-TACHES.md:19` | établi |
|
||||
| **Déjà fait** : dossier `%LOCALAPPDATA%\LifePlay-Revival\Saved` (Config, Logs, LPDataCache, SaveGames) créé et utilisé en Shipping ; code `LPSaveRelaunch.cpp` (396 l.), `LPSaveRelaunch.h`, `LifePlay.cpp` (+3 l.) | `Registre_Erreurs.md:49` ; `REL-SAV-IMPL.md:13-15` | établi |
|
||||
| **Le dossier du jeu est hors du lot** : `Player.lpcharacter` est dans `Content\Saves`, « le renommage ne la touche pas ; le défaut existant (SAV1 / ERR-042) reste ouvert » | `REL-SAV-DIAG.md:58` | établi |
|
||||
| Conséquence pour le joueur : « une sauvegarde est donc répartie entre les deux dossiers » | `REL/ALPHA/REL-ALPHA-T6b.md:24` | établi |
|
||||
| Texte public actuel : limite connue (« keep the game folder when you update, or copy `LifePlay\Content\Saves` to the new one ») | `README.md:82-83` ; repris `MEN/MEN1/MEN1-B-PROPOSITION.md:24, 105-106` | établi |
|
||||
| Statut de F6 : « ERR-042 : personnages de partie dans `Content\Saves` (reste) », rubrique Fix ; FIX1 = « F6, F7, F8 : petits correctifs Blueprint par MCP · `lp-mcp-bp` · 7e jeton » | `37_Feuille_De_Route_Alpha2.md:59, 171` | établi |
|
||||
| ERR-042 avait été « non retenu » pour l'après-alpha (2026-10-14), puis F6 est entré dans la liste d'avant gel | `BOSS-ETAT.md:259` ; `37_…:59` | établi |
|
||||
|
||||
Cartographie des dossiers de sauvegarde d'une partie, aujourd'hui :
|
||||
|
||||
| Quoi | Où | Preuve |
|
||||
|---|---|---|
|
||||
| Emplacements `.sav` (UE `SaveGame`) et `GameSettings.sav` | `<…>\Saved\SaveGames` → nouveau dossier Revival | `Registre_Erreurs.md:49` |
|
||||
| Réglages `LP*.ini` | `<…>\Saved\Config\Windows` → nouveau dossier | `LPKeyboardSubsystem.cpp:77`, `LPColorGradeSubsystem.cpp:27`, `LPVideoQualitySubsystem.cpp:71` |
|
||||
| **Personnages de la partie en cours (copie de travail)** | `<jeu>\Content\Saves\_session\Characters\…` | dump GI `CAM-B1-PRE_LPDumpFunction_20261013-083048.txt:6469, 9655, 18018, 25060` |
|
||||
| **Personnages d'une partie enregistrée** | `<jeu>\Content\Saves\<Slot>\Characters\<N>.lpcharacter`, `F<N>`, `C<N>`, `OldPlayer`, `Player` | même dump : événement `DuplicateCharacters` l. 8397-8431 ; copies N l. 8459-8489, `F` l. 15288-15320, `OldPlayer` l. 18924-18955, `C` l. 19003-19020, `Player` l. 8505-8534 |
|
||||
| Sens de la copie | `Load = vrai` : `Saves/<Slot>/Characters/` → `_session` ; `Load = faux` : l'inverse | même dump l. 8400, 8402-8413 |
|
||||
|
||||
### 3.2 Où sont les accès (question 2)
|
||||
|
||||
**C++ (un seul fichier d'E/S, établi)**
|
||||
|
||||
| Point | Ligne | Rôle |
|
||||
|---|---|---|
|
||||
| `LoadTxt` : lecture `FFileHelper::LoadFileToString(…, ProjectContentDir() + FileNameA)` | `ModdingExtraBPLibrary.cpp:190` | **lecture** (1 point) |
|
||||
| `LoadTxt` : relecture de contrôle si le cache est en mode vérification | `ModdingExtraBPLibrary.cpp:195` | lecture de contrôle (même chemin) |
|
||||
| `SaveTxt` : `FFileHelper::SaveStringToFile(…, ProjectContentDir() + FileNameB)` | `ModdingExtraBPLibrary.cpp:236` | **écriture** (1 point) |
|
||||
| `GetAllFilesFromFolder`, `GetAllSubfolders`, `ContentDirectory` : base `ProjectContentDir()` | `ModdingExtraBPLibrary.cpp:50, 120, 254` | listes et chemin absolu ; usage sur `Saves/` **non démontré** (inconnu) |
|
||||
| Le cache de données ne couvre que `Modules` : « pour tout chemin hors Modules, la lecture se fait sur le disque » | `LPDataCache.h:10-11` ; `LPDataCache.cpp:25, 104, 110` | établi : `Saves/` n'est pas servi par le cache |
|
||||
|
||||
Aucun autre code C++ du jeu ne cite `Saves` ni `lpcharacter` : Grep n° 5 à 8 (Source : 1 commentaire ; Plugins et Config : rien). Le module d'outils de l'éditeur (`LPDumpSaveCommandlet.cpp`) ne lit que des `.sav`.
|
||||
|
||||
**Blueprint (chemins littéraux, base relative à `Content`)**
|
||||
|
||||
| Asset | Correspondances brutes `rg -a -o` | Lecture |
|
||||
|---|---|---|
|
||||
| `Content/BPs/GI.uasset` | `Saves/_session/Characters/` 41 ; `…/F` 10 ; `…/C` 4 ; `…/OldPlayer` 4 ; `Saves/` 7 ; `Saves` 5 ; `.lpcharacter` 80 ; `OldPlayer.lpcharacter` 5 ; `Player.lpcharacter` 4 ; presets de modèles `elf/orc/vampire/thirties/twenties` | GI porte **la quasi-totalité** des accès |
|
||||
| `Content/UI/Contact.uasset` | `Saves/_session/Characters/` 4 ; `…/C` 2 ; `…/F` 2 ; `.lpcharacter` 4 | 3 familles de chemins ; ≈ 4 littéraux (estimé : chaque littéral apparaît 2 fois dans le binaire) |
|
||||
| `Content/UI/ContactMenu.uasset` | `Saves/_session/Characters/` 2 ; `.lpcharacter` 2 | ≈ 1 littéral (estimé) |
|
||||
| `Content/UI/BodyShapeMenu.uasset` | `F.lpcharacter` 2 ; appel `SaveTxt` | ≈ 1 chemin ; écrit un personnage |
|
||||
| `Content/UI/CharGen.uasset`, `Content/UI/StatMenu.uasset` | `.lpcharacter` 2 chacun ; appels `LoadTxt`, `GetAllFilesFromFolder` (3 chacun) | pas de littéral `Saves` ; presets de `Modules` ; passent par `GI.SavePreset` / `LoadPreset` (`CG2-CART-01.md:44-45, 55, 74`) |
|
||||
|
||||
Littéraux `Saves/…` **dans les graphes de GI** (dump 5.5 `L6f_dump_GI.txt`, 29 lignes) : 22 dans 17 fonctions, 7 dans l'`EventGraph`. Lignes du dump, rattachées aux fonctions par l'ordre des en-têtes (déduit) : `GeneratePerson` (17478, 17709), `GetAllGeneratedCharacters` (23601, 23632, 23694), `getPerson` (24098), `GetSpecific` (26089, 26773), `getRelative` (29595), `isMarried` (29924), `GetNameFromSlot` (31346), `cloneFrom` (32249), `UpdateChildrenAges` (32922, 33014), `GetFratBros` (33397), `calculateStaffIntelligence` (34570), `calculateStaffInterpersonal` (34673), `GenerateCreature` (36231), `getCreature` (36531), `saveOldPlayer` (37959), `GenerateHomeAndWork` (43519), `populateGlassesAndVirgins` (44889). `EventGraph` : 55001, 56563, 56568, 56582, 57538, 64195, 69938, identiques aux 7 lignes du dump 5.8 `CAM-B1-PRE…txt:6469, 8405, 8410, 8428, 9655, 18018, 25060`.
|
||||
|
||||
Autres constats utiles :
|
||||
- `GI.SavePreset` choisit le préfixe d'après le chemin : `StartsWith(File, "Saves")` sinon `"Modules/"` (`L6f_dump_GI.txt:2325-2336`). Un chemin d'une autre forme tomberait dans `Modules/` : une migration par Blueprint devrait garder ce test (et la redirection C++ le laisse intact).
|
||||
- Appels `LoadTxt`/`SaveTxt` dans GI : 45 nœuds (grep n° 12). `SavePreset` en compte 2 écritures (l. 1134, 2288) et 2 lectures (l. 2188, 3045), `LoadPreset` 1 lecture (l. 3310) ; le sous-ensemble sur des chemins `Saves` n'a pas été isolé par flux de données (inconnu, estimé 20 à 25).
|
||||
- Message à l'écran quand les fichiers manquent : « The save you just loaded is missing crucial *.lpcharacter files. Please copy your old LifePlay\Content\Saves folder into the directory of the current version of the game… » (`CAM-B1-PRE…txt:14822-14823`, `EventGraph` de GI) : devient faux si F6 aboutit.
|
||||
- Les fichiers de presets de mods sont lus dans `Modules/<mod>/Presets/…` (`L6f_dump_GI.txt:17506, 35316-35326`) et non dans `Saves`.
|
||||
|
||||
### 3.3 Dimensionnement (question 3)
|
||||
|
||||
| Critère | Établi | Estimé | Inconnu |
|
||||
|---|---|---|---|
|
||||
| Écritures | 1 point C++ (`SaveTxt`, `.cpp:236`) | côté Blueprint : `DuplicateCharacters` (5 familles de fichiers), `SavePreset` (2 `SaveTxt`), `saveOldPlayer`, `BodyShapeMenu` ; toutes passent par `SaveTxt` | écritures hors `SaveTxt` (aucune trouvée dans Source, Plugins, ni dans les noms d'appel de GI) |
|
||||
| Lectures | 1 point C++ (`LoadTxt`, `.cpp:190`) ; 45 nœuds d'appel dans GI | ≈ 20 à 25 sur des chemins `Saves` | lectures par `GetAllFilesFromFolder` ou `ContentDirectory` sur `Saves` |
|
||||
| BP ou C++ | le chemin réel est construit en C++ (`ProjectContentDir() + chemin relatif`) | **C++ seul** si la redirection est faite dans `LoadTxt`/`SaveTxt` : ≈ 40 à 80 lignes dans 1 fichier (helper de résolution, repli de lecture, journal) | helper commun aux 3 fonctions de liste si elles servent `Saves` |
|
||||
| Voie BP (non retenue) | 29 littéraux dans GI + ≈ 6 dans 3 widgets UI ; le test `StartsWith "Saves"` de `SavePreset` ; ≈ 35 modifications par MCP | — | — |
|
||||
| GI touché ? | **non, par la voie C++** | le texte du message (`CAM-B1-PRE…txt:14823`) reste faux jusqu'à la build 2 | — |
|
||||
| GI touché ? (voie BP) | **oui** : 17 fonctions + `EventGraph` | contraire à la règle « GI.uasset n'est révisé qu'une fois, en build 2 » | — |
|
||||
| Migration des fichiers existants | R0 déjà décidé pour `SaveGames` (`REL-SAV-TACHES.md:19`) | **repli de lecture** vers l'ancien `Content\Saves` : aucune copie, aucune suppression ; l'écriture va dans le nouveau dossier | granularité du repli (par fichier ou par dossier de slot) : voir risque R2 |
|
||||
| Saves déjà faites (alpha 2026.10.2.1a, V1.x) | les `.sav` sont dans `…\SaveGames`, les personnages dans `<jeu>\Content\Saves` (`REL-ALPHA-T6b.md:24`) | avec le repli, une partie chargée depuis l'ancien emplacement fonctionne ; au premier enregistrement, les personnages passent dans le nouveau dossier | cas d'un joueur qui supprime l'ancien dossier du jeu avant d'avoir réenregistré |
|
||||
| Compatibilité des mods | le format `.lpcharacter` ne change pas ; les presets de mods sont dans `Modules` (`L6f_dump_GI.txt:17506`) ; le cache ne touche pas `Saves` (`LPDataCache.h:10-11`) | le contrat de données des mods n'est pas modifié | **les guides de modding décrivent l'emplacement** : `Docs/Modding/ShortGuides/explanation.lpcharacter:3`, `FullGuides/Creating_Presets.txt:7, 13, 15` (`Content/Saves`, `_session`, `Saves/Default`) : texte à corriger, décision de l'utilisateur car le contrat est « figé » (`REL-SAV-DIAG.md:48`) |
|
||||
| Éditeur et Development | `ProjectSavedDir()` = `<copie>\Saved` hors paquet (`REL-SAV-DIAG.md:59`) | les parties de test se rangeraient dans `Saved` au lieu de `Content\Saves` | règle de copie d'une sauvegarde de test (`21_Sandbox_Addon.md:213` ; `REF/REF1/REF1-CART-02.csv:65`) et règle « `Content/Saves` doit exister mais rester vide » (`REF1-CART-01.csv:41`) à réécrire |
|
||||
| Dossier cible et `-UserDir` | `ProjectSavedDir()` suit déjà `-UserDir` (`REL-SAV-DIAG.md:19-20`) | le nouveau chemin suit donc le dossier choisi par le joueur | création de dossiers : `SaveTxt` crée les sous-dossiers de slot aujourd'hui (le dossier `Content/Saves` est livré vide, `REF1-CART-01.csv:41`), donc `FFileHelper` crée l'arborescence (déduit) |
|
||||
| `Saves/Default` | cité par `Creating_Presets.txt:13` | — | lu ou non par GI, livré ou non : non vérifié |
|
||||
|
||||
### 3.4 Recommandation (question 4)
|
||||
|
||||
**Agent et niveau (estimé)**
|
||||
|
||||
| Étape | Agent | Modèle | Niveau | Raison |
|
||||
|---|---|---|---|---|
|
||||
| SPEC | Big Boss, ou une fiche opus (effort medium) | opus | **N3** | décisions à prendre (racine, repli par slot, journal, interrupteur de retour arrière, texte des guides) ; chemin chaud |
|
||||
| IMPL | `lp-impl` | Sonnet | N2 | ≈ 40 à 80 lignes dans 1 fichier, si la SPEC donne la signature et les cas ; passer à `lp-impl-max` (opus) si la SPEC laisse des choix |
|
||||
| BUILD | `lp-builder` | — | N1 à N2 | compilation d'un plugin du jeu, sans l'addon |
|
||||
| VAL | `lp-validator` distinct de l'IMPL | — | N2 | relecture du diff ; branche « hors `Saves/` » inchangée octet pour octet |
|
||||
| Essai en jeu | Big Boss, sous le jeton de la copie UE | — | — | nouvelle partie, sauvegarde, Continuer, ancien dossier présent / absent |
|
||||
| DOC | `lp-writer` | — | N1 | README, guides de modding, `lp-validate`, REF1, annonces, ERR-042 |
|
||||
|
||||
À ne **pas** confier : `lp-mcp-bp` (aucun Blueprint à modifier par cette voie ; GI est réservé à la build 2) ; un agent xhigh (pas d'analyse profonde nécessaire une fois la SPEC écrite). Le niveau « lot » à porter dans `FIX1-TACHES` : **N3** (le chemin touché est lu par toutes les données du jeu et l'essai exige la copie UE).
|
||||
|
||||
**Durée (estimée, non mesurée)** : SPEC 20 à 30 tours ; IMPL 15 à 25 tours, sans la copie UE ; compilation incrémentale du plugin (durée non mesurée) ; VAL 15 à 20 tours ; essai en jeu 30 à 60 minutes sous le jeton ; DOC 10 à 15 tours. Environ une journée de session répartie sur J2 à J4, dont **un seul créneau sur la copie UE** (compilation et essai).
|
||||
|
||||
**Risques**
|
||||
- R1, chemin chaud : `LoadTxt` sert toutes les données du jeu. Le test `Saves/` doit précéder tout et laisser les autres chemins inchangés (VAL par relecture du diff et par le bilan `ModdingExtra.LoadTxtStats` au démarrage).
|
||||
- R2, mélange de deux parties : un repli de lecture **par fichier** pourrait relire un personnage de l'ancienne partie du même numéro de slot. Préférer un repli **par dossier de slot** (si le dossier du slot existe dans le nouveau dossier, ne plus regarder l'ancien).
|
||||
- R3, retour arrière : prévoir un interrupteur (argument de lancement ou variable de configuration) qui rétablit le chemin d'origine, pour tenir le gel du 24.
|
||||
- R4, textes périmés : message de GI (`CAM-B1-PRE…txt:14823`), README (`:82-83`, et `:117` qui cite encore l'ancien dossier, non vérifié), annonces `REL/ALPHA/REL-ALPHA-ANNONCE-*.md`, guides de modding.
|
||||
- R5, file de la copie UE déjà chargée (`37_…:171, 179-185`) : un créneau de plus.
|
||||
|
||||
**Build 1 ou build 2 (estimé, décision de l'utilisateur)**
|
||||
- **Build 1 est tenable sous trois conditions** : (a) la voie C++ seule est confirmée par la SPEC (aucune modification de GI) ; (b) la SPEC est acceptée le J2 (2026-10-21) pour que l'IMPL se fasse hors copie UE ; (c) l'essai en jeu a lieu au J3 ou au J4 dans le créneau voisin de FIX1 (`37_…:183-184`). Porte : si l'essai n'est pas concluant au J4 soir, F6 passe en build 2 et la limite reste dans le README.
|
||||
- **Build 2 est préférable** si CG2 ou CAM2 glissent : F6 change l'emplacement des données de **tous** les joueurs juste avant le gel, pour un gain limité (une limite déjà annoncée). Le message de GI pourrait alors être corrigé avec la révision unique de GI.
|
||||
- Dans les deux cas, GI n'est pas touché en build 1.
|
||||
|
||||
## 4. Établi / estimé / incertain (synthèse)
|
||||
|
||||
**Établi (relu à la source)** : texte d'ERR-042 et ses mises à jour ; B+ seul retenu, aucun lanceur ; R0 ; `LPSaveRelaunch` livré et E9 PASS ; limite connue au README ; chemins de personnages `Saves/_session/Characters/…` et `Saves/<Slot>/Characters/…` ; point d'E/S unique `LoadTxt`/`SaveTxt` sur `ProjectContentDir()` ; aucun autre code C++ ne cite `Saves` ; 29 littéraux dans les graphes de GI (dump 5.5) dont 7 dans l'`EventGraph` (dump 5.8) ; 6 assets contiennent ces chaînes ; le cache de données ne couvre que `Modules` ; guides de modding qui citent `Content/Saves`.
|
||||
|
||||
**Estimé (déduit)** : la redirection en C++ suffit sans toucher GI ; le nombre de modifications Blueprint si on avait choisi cette voie (≈ 35) ; 20 à 25 nœuds `LoadTxt`/`SaveTxt` sur chemins `Saves` ; le repli de lecture couvre les parties existantes ; `FFileHelper` crée les dossiers ; durées et niveaux de § 3.4.
|
||||
|
||||
**Incertain, essai qui trancherait** :
|
||||
- Les dumps de fonctions de GI (29 littéraux) datent du 2026-09-30 (5.5) : `LPDumpFunction -BP=GI -Fn=<chaque fonction> -Pins` sur la 5.8, éditeur fermé, rendrait le compte actuel (utilise la copie UE).
|
||||
- Usage de `GetAllFilesFromFolder` / `GetAllSubfolders` / `ContentDirectory` sur `Saves` : suivi du flux de données dans ces dumps `-Pins`.
|
||||
- `Saves/Default` : lu ou non, livré ou non.
|
||||
- Comportement réel d'un Shipping avec un repli de lecture : essai en jeu seulement.
|
||||
|
||||
## 5. Points à confirmer (repris par la fiche suivante)
|
||||
|
||||
1. Rafraîchir par commandlet (copie UE) le relevé des littéraux `Saves` de GI en 5.8 et isoler, par flux de données, les nœuds `LoadTxt`/`SaveTxt` sur chemins `Saves`.
|
||||
2. Chercher les usages de `GetAllFilesFromFolder`, `GetAllSubfolders` et `ContentDirectory` avec une base `Saves`.
|
||||
3. Lire `LPDataCache::OnWritten` (`LPDataCache.cpp:269`) pour confirmer qu'elle ignore les chemins hors `Modules` (non lu ici).
|
||||
4. Vérifier que `FFileHelper::SaveStringToFile` crée l'arborescence dans le moteur 5.8 installé (`Engine/Source/Runtime/Core/…/FileHelper.cpp`) : déduit ici d'un comportement observé, non relu dans le moteur.
|
||||
5. Statuer sur `Saves/Default` (guides de modding `Creating_Presets.txt:13`).
|
||||
6. Vérifier `README.md:117` (cite encore `%LOCALAPPDATA%\LifePlay\Saved`).
|
||||
7. Corriger la classe de la ligne FIX1 du doc 37 (F6 n'est pas un correctif Blueprint) quand l'utilisateur aura tranché.
|
||||
|
||||
## 6. Questions pour la SPEC ou l'utilisateur
|
||||
|
||||
1. Racine du nouveau dossier : `ProjectSavedDir()/Saves/…` (même arbre que `SaveGames`) ou `ProjectSavedDir()/SaveGames/Characters/…` ?
|
||||
2. Repli de lecture sur l'ancien `Content\Saves` : oui ou non ; par slot (recommandé) ou par fichier ; durée de vie (jusqu'à quelle version) ?
|
||||
3. Copie des anciens personnages vers le nouveau dossier au premier chargement, ou aucune copie (cohérent avec R0) ?
|
||||
4. Guides de modding (`explanation.lpcharacter:3`, `Creating_Presets.txt:7, 13, 15`) : corriger le texte, sachant que le contrat des mods est « figé » ?
|
||||
5. Texte du message de GI (`CAM-B1-PRE…txt:14823`) : le laisser en build 1 et le corriger avec la révision unique de GI en build 2 ?
|
||||
6. Interrupteur de retour arrière : sous quelle forme (argument de lancement, `.ini`) ?
|
||||
7. F6 en build 1 sous la porte du J4, ou directement en build 2 ?
|
||||
8. Où classer la ligne FIX1 : garder `lp-mcp-bp` pour F7 et F8, et sortir F6 de FIX1 vers un lot propre (ex. FIX1-F6) piloté en C++ ?
|
||||
|
||||
Tours : 26 / 20 (budget « environ 20 » dépassé de 6 : recherche des chaînes dans les assets binaires et rattachement des littéraux aux fonctions de GI ; `Tools/FicheStats.py` fait foi)
|
||||
394
Docs/Migration/etat/REL/FIX1/FIX1-F6-SPEC.md
Normal file
394
Docs/Migration/etat/REL/FIX1/FIX1-F6-SPEC.md
Normal file
|
|
@ -0,0 +1,394 @@
|
|||
Fiche FIX1-F6-SPEC — Niveau N3 — Modèle prévu opus (effort medium) | utilisé claude-opus-5-5 — Agent lp-cart — Skills sk-protocol, ue-cpp-build, lp-commandlets, lp-paths
|
||||
# FIX1-F6-SPEC : fichiers de partie (`Saves/…`) redirigés vers le dossier de sauvegarde, voie C++ (2026-10-20)
|
||||
|
||||
Ordre de l'utilisateur, cité par la fiche : « F6 en build 1 avec la porte J4 : lance la SPEC (opus, effort medium) sur la voie C++. »
|
||||
Base : `FIX1-F6-PRE.md` (§ 3, 5, 6), ERR-042 (`Docs/Registre_Erreurs.md:49`), lot REL-SAV (`etat/REL/SAV/`).
|
||||
Lecture seule : ni code, ni copie UE, ni MCP ; seul ce fichier est écrit.
|
||||
Écart de skills : la fiche cite `sk-protocol, lp-lot, lp-paths`. `lp-lot` n'est pas chargé dans mon contexte ; `ue-cpp-build` et `lp-commandlets` le sont.
|
||||
Niveaux de preuve : **établi** (lu à la source, `fichier:ligne` ou commande), **estimé** (déduit, raisonnement donné), **inconnu** (essai qui trancherait nommé).
|
||||
|
||||
## Résumé (à lire en premier)
|
||||
|
||||
- **Un seul fichier change** : `Plugins/ModdingExtra/Source/ModdingExtra/Private/ModdingExtraBPLibrary.cpp` (MD5 avant `7628837e7b77c68c3921acfad3d92ec0`, LF). Il gagne un espace de noms `LPSavesRedirect` d'environ 90 lignes et 2 lignes modifiées (`:190`, `:236`). Aucun Blueprint, aucun `Build.cs`, aucun `.uplugin` ne change, GI non plus.
|
||||
- **Règle** : un chemin relatif à `Content` qui commence par `Saves/` (sans casse, `\` accepté) est **écrit** sous `FPaths::ProjectSavedDir() + "Saves/…"`. Il est **lu** au même endroit, sauf pour un slot absent de la nouvelle racine et présent dans l'ancien `Content/Saves` : le slot entier est alors lu dans l'ancien dossier (repli **par slot**). `_session` n'a jamais de repli. Tout autre chemin reste identique, octet pour octet.
|
||||
- **Racine obtenue** : Shipping `%LOCALAPPDATA%\LifePlay-Revival\Saved\Saves\…` ; Development sans `LPSaveLocation.ini` `<build>\Windows\LifePlay\Saved\Saves\…` ; éditeur `<copie>\Saved\Saves\…`.
|
||||
- **Retour arrière à chaud** : l'argument `-LPNoSavesRedirect` rétablit l'ancien chemin. **À froid** : `Tools\Restore.ps1` depuis l'instantané, ou `git revert` du commit (un seul fichier).
|
||||
- **Témoin** : `LogModdingExtra` et non `LogLifePlay`. `LogLifePlay` vit dans le module de jeu (`Source/LifePlay/LifePlay.h:9`), que le plugin ne peut pas voir (Q4).
|
||||
|
||||
## 1. Objectif mesurable
|
||||
|
||||
**O1. Écriture.** Après une nouvelle partie, un enregistrement, un rechargement et une création de personnage, les fichiers `*.lpcharacter` de la partie se trouvent sous `<ProjectSavedDir>/Saves/_session/Characters/` et `<ProjectSavedDir>/Saves/<Slot>/Characters/`. Rien n'est créé ni modifié sous `<jeu>/Content/Saves`, contrôlé par un relevé MD5 avant et après (§ 7, E1-E4).
|
||||
|
||||
**O2. Lecture et repli.** Une partie dont le slot n'existe que dans l'ancien `Content/Saves/<Slot>` se charge sans le message « missing crucial *.lpcharacter files ». Au premier enregistrement, ce slot est écrit dans la nouvelle racine (E5).
|
||||
|
||||
**O3. Rien d'autre ne bouge.** Les chemins hors `Saves/` (dont `Modules/…`) gardent exactement l'expression `FPaths::ProjectContentDir() + <chemin>`. Le cache `LPDataCache` sert le même nombre de fichiers (E8).
|
||||
|
||||
**O4. Désactivation.** Avec `-LPNoSavesRedirect`, le comportement d'avant F6 revient : écriture dans `Content/Saves` (E6).
|
||||
|
||||
### 1.1 Règle de redirection (demande n° 1)
|
||||
|
||||
| Chemin relatif reçu (exemples des Blueprints) | Lecture (`LoadTxt`) | Écriture (`SaveTxt`) | Source |
|
||||
|---|---|---|---|
|
||||
| `Saves/_session/Characters/<N>.lpcharacter`, `…/F<N>`, `…/C<N>`, `…/OldPlayer`, `…/Player` | `<SavedDir>/Saves/_session/…`, **sans repli** | `<SavedDir>/Saves/_session/…` | littéraux GI : `FIX1-F6-PRE.md` § 3.2 (41 + 10 + 4 + 4 correspondances `rg -a`) |
|
||||
| `Saves/<Slot>/Characters/…` (`DuplicateCharacters`, `Load` vrai ou faux) | `<SavedDir>/Saves/<Slot>/…` si le dossier `<SavedDir>/Saves/<Slot>` existe ; sinon `<Content>/Saves/<Slot>/…` si `<Content>/Saves/<Slot>` existe ; sinon `<SavedDir>/…` (l'échec de lecture y est alors journalisé) | `<SavedDir>/Saves/<Slot>/…` | `CAM-B1-PRE_LPDumpFunction_20261013-083048.txt:8397-8534` (cité par PRE § 3.1) |
|
||||
| `Saves/<fichier>` posé directement dans `Saves/` (slot vide) | `<SavedDir>/Saves/<fichier>`, sans repli | idem | aucun usage connu (estimé : pas de littéral de cette forme dans le relevé PRE § 3.2) |
|
||||
| `Saves/Default/…` | traité comme un slot nommé `Default` (repli par slot) | idem | **établi** : aucun asset ne contient `Saves/Default` (commande n° 9 : `rg -a -l -e "Saves/Default" … Content`, code 1, aucun fichier). Seul le guide `Docs/Modding/FullGuides/Creating_Presets.txt:13` le cite, comme reste d'une version ancienne (estimé). |
|
||||
| tout autre chemin (`Modules/…`, `ModLauncher.config`…) | `FPaths::ProjectContentDir() + chemin`, inchangé | inchangé | `ModdingExtraBPLibrary.cpp:190, 236` |
|
||||
|
||||
- `<SavedDir>` = `FPaths::ProjectSavedDir()`, qui se termine par `/` (`Paths.cpp:107`, moteur 5.8). Il suit `-UserDir`, donc le dossier choisi par REL-SAV (`REL-SAV-DIAG.md:19-20`, `Paths.cpp:451-471`).
|
||||
- `<Content>` = `FPaths::ProjectContentDir()`, qui se termine par `Content/` (`Paths.cpp:477`).
|
||||
- Le chemin redirigé garde le préfixe `Saves/`. La racine est donc `<SavedDir>/Saves/`, à côté de `SaveGames/` et sans s'y mêler (Q1).
|
||||
- Comparaison sans casse (`FString::StartsWith`, `IgnoreCase` par défaut : `UnrealString.h.inl:1505`). Le nom de slot `_session` est comparé sans casse (`Equals`, `UnrealString.h.inl:1271`).
|
||||
|
||||
### 1.2 Nom et place de la fonction utilitaire
|
||||
|
||||
- **Nom** : `LPSavesRedirect::ResolvePath(const FString& ContentRelativePath, bool bForWrite)`, qui renvoie le `FString` à passer à `FFileHelper`. Elle s'appuie sur trois aides du même espace de noms : `Match`, `Note`, `IsDisabled`. Les compteurs `NewReads`, `OldReads` et `Writes` sont `static int32`.
|
||||
- **Place** : dans `ModdingExtraBPLibrary.cpp`, après `DEFINE_LOG_CATEGORY_STATIC(LogModdingExtra, …)` (`:27`) et avant le constructeur (`:29`). Ce n'est pas le module `LifePlay`, et la raison est **établie** :
|
||||
- `LoadTxt` et `SaveTxt` sont dans le plugin `ModdingExtra` (`ModdingExtraBPLibrary.h:37-41`) ;
|
||||
- le plugin ne dépend que de `Core`, `CoreUObject`, `AssetRegistry`, `Json`, `Engine`, `Slate` et `SlateCore` (`ModdingExtra.Build.cs:22-44`) ;
|
||||
- `LifePlay.Build.cs` ne cite pas `ModdingExtra` (Grep `ModdingExtra|LogLifePlay` sur `Source/LifePlay`, filtré sur `*.Build.cs` et deux autres fichiers : aucune ligne de `LifePlay.Build.cs`) ;
|
||||
- un plugin chargé en `PreLoadingScreen` (`ModdingExtra.uplugin:20`) ne peut pas dépendre du module de jeu chargé en `Default` (`LifePlay.uproject:10`).
|
||||
- **Pas d'en-tête public** : tout reste `static` dans le `.cpp`. L'espace de noms `LPSavesRedirect` n'existe nulle part ailleurs dans le plugin (Grep `LPSavesRedirect|ResolvePath` sur `Plugins/ModdingExtra/Source` : 0). Aucun conflit n'est donc à craindre en build unity (`ue-cpp-build` § 4).
|
||||
|
||||
### 1.3 Fonctions de fichier de ModdingExtra : couverture (demande n° 2)
|
||||
|
||||
| Fonction | Lignes | Base actuelle | Décision F6 | Raison |
|
||||
|---|---|---|---|---|
|
||||
| `LoadTxt` | 181-232 ; disque `:190` | `ProjectContentDir() + FileNameA` | **redirigée** : `:190` lit `LPSavesRedirect::ResolvePath(FileNameA, false)` | point de lecture unique des personnages |
|
||||
| `LoadTxt`, relecture de vérification | `:192-204`, disque `:195` | `ProjectContentDir() + FileNameA` | **inchangée** | elle ne s'exécute que si `bFromCache`, c'est-à-dire pour `modules/…` seulement (`LPDataCache.cpp:256`) |
|
||||
| `SaveTxt` | 234-250 ; disque `:236` | `ProjectContentDir() + FileNameB` | **redirigée** : `:236` écrit vers `ResolvePath(FileNameB, true)` | point d'écriture unique |
|
||||
| `SaveTxt` → `OnWritten` | `:239` | chemin relatif | **inchangée** : on passe toujours `FileNameB` relatif | voir § 1.4 |
|
||||
| `GetAllFilesFromFolder` | 40-111 (base `:50-51`) | `ProjectContentDir()` absolu | **non redirigée** ; ajout d'un avertissement unique si la racine commence par `Saves` (`WarnListOnSaves`) | aucun appel sur `Saves` (voir ci-dessous) ; elle renvoie des chemins **absolus** que les Blueprints recoupent (`RightS`) : changer la base casserait ce découpage |
|
||||
| `GetAllSubfolders` | 114-127 (base `:120-121`) | `ProjectContentDir()` absolu | **non redirigée** ; même avertissement | aucune référence dans `Content` (voir ci-dessous) |
|
||||
| `ContentDirectory` | 252-257 | `ProjectContentDir()` absolu | **inchangée** | aucun appel du plugin dans `Content` (voir ci-dessous) |
|
||||
| `ModdingExtraSampleFunction`, `IsPointInsidePolygon` | 35-38, 259-277 | — | hors sujet | aucun accès fichier |
|
||||
|
||||
Preuves (établi) :
|
||||
- **`GetAllFilesFromFolder` dans GI** : 18 nœuds (`L6f_dump_GI.txt:17236 … 69567`). Leurs racines sont `'Modules'`, `'Modules/'`, `'Modules/vin_Base/Presets/{phenotypes,age_groups,female,male}'`, un `SelectString` entre deux chemins `Modules/…` (`:17456-17461`), ou un paramètre `PathFromContent` (`:47240-47243`, fonction d'images). Dans l'`EventGraph` 5.8, les racines sont `'Modules'` ou une concaténation commune, `K2Node_CommutativeAssociativeBinaryOperator_664` (`CAM-B1-PRE…083048.txt:1538, 1730, 1782, 1810, 10120, 10154, 21729, 24642`), pour des extensions de modules (`lpstat`, `lpaction`, `lpscene`, `lptalk`, `lpdesc`, `lpquest`, `lpai`).
|
||||
- **`GetAllSubfolders` et `ContentDirectory`** : `rg -a -l -e ContentDirectory -e GetAllSubfolders` sur `Content` trouve 4 fichiers. Le comptage par fichier montre que chaque occurrence de `ContentDirectory` est en fait `GetProjectContentDirectory`, une fonction **du moteur** : GI 2/2, `UI/ExtImg` 2/2, `UI/MainMenu` 1/1, `UI/FaceTexture` 1/1. `GetAllSubfolders` : 0 occurrence (commandes n° 5 et 6).
|
||||
|
||||
### 1.4 Interaction avec LPDataCache (demande n° 3)
|
||||
|
||||
- `TryGet` refuse toute clé qui ne commence pas par `modules/` (`LPDataCache.cpp:255-259`). La clé est le chemin relatif mis en minuscules, avec des `/` (`:71-78`). `LoadTxt` lui passe toujours `FileNameA` relatif, avant toute redirection (`ModdingExtraBPLibrary.cpp:189`) : rien ne change.
|
||||
- `OnWritten` sort aussitôt pour une clé hors `modules/` (`LPDataCache.cpp:271-275`). Ses relectures `ProjectContentDir() + chemin` (`:284, 289`) ne concernent donc que `Modules`. `SaveTxt` continue de lui passer `FileNameB` relatif.
|
||||
- Le chargement du cache parcourt `Content/Modules` seulement (`LPDataCache.cpp:103-110`) et écrit dans `<SavedDir>/LPDataCache` (`:105`). Le dossier `<SavedDir>/Saves` n'est **pas** parcouru.
|
||||
- Conclusion (établi) : **aucun effet sur `Modules`**, ni sur `LPDataCache.cpp` et `LPDataCache.h`, qui restent inchangés. Le court-circuit `bFromCache || …` (`:190`) garantit que `ResolvePath` n'est appelée que pour une lecture sur le disque.
|
||||
|
||||
### 1.5 Ce qui ne change pas (demande n° 4)
|
||||
|
||||
| Élément | Statut | Preuve |
|
||||
|---|---|---|
|
||||
| GI et tous les Blueprints | aucune écriture. Les littéraux `Saves/…` restent relatifs et c'est le C++ qui les place | `FIX1-F6-PRE.md` § 3.3 |
|
||||
| `GI.SavePreset` (`StartsWith(File, "Saves")`, sinon `Modules/`) | inchangé : un preset `Saves…` suit la redirection, un preset `Modules/…` non | `L6f_dump_GI.txt:2325-2336` |
|
||||
| `Content/Modules`, mods, format `.lpcharacter`, `LPDataCache` | inchangés | § 1.4 ; presets de mods dans `Modules/<mod>/Presets/…` (`L6f_dump_GI.txt:17345-17372, 30858-30872`) |
|
||||
| `SaveGames/*.sav`, `Config/*.ini`, `LPSaveRelaunch` | inchangés | `REL-SAV-SPEC.md` |
|
||||
| Message de GI « …copy your old LifePlay\Content\Saves folder… » | non modifié en build 1. Il reste **vrai à moitié** : grâce au repli, un ancien `Content/Saves/<Slot>` recopié dans le nouveau dossier du jeu est encore lu | `CAM-B1-PRE…083048.txt:14822-14823` (PRE § 3.2) |
|
||||
|
||||
**Fonctions Blueprint qui construisent un chemin absolu à partir du dossier `Content`** (elles échapperaient à toute redirection) :
|
||||
- `KismetSystemLibrary::GetProjectContentDirectory`, fonction du moteur et non `ModdingExtra::ContentDirectory` : GI, 1 nœud (`L6f_dump_GI.txt:47227`, concaténé à un paramètre `Path`, puis mis dans la table `LoadedImages`, `:47196-47226`), ainsi que `UI/ExtImg`, `UI/MainMenu` et `UI/FaceTexture` (commande n° 6).
|
||||
- **Aucune ne vise `Saves`** : la liste `rg -a -o 'Saves[A-Za-z_/]*'` de ExtImg, MainMenu et FaceTexture ne donne aucune ligne `Saves` (commande n° 5, résultat archivé par l'outil, lignes `== UI/ExtImg` à `== UI/FaceTexture`). Dans GI, le chemin vient d'un paramètre (images de modules, **estimé**). **Inconnu** : la valeur réelle de ce paramètre à l'exécution. L'essai E7 le tranche : aucun accès `Saves` hors `LoadTxt`/`SaveTxt` ne doit apparaître (un `Process Monitor` filtré sur `Content\Saves` pendant E1-E4 serait la preuve forte).
|
||||
- `GetAllFilesFromFolder` renvoie des chemins absolus `Content/…` (`ModdingExtraBPLibrary.cpp:62-66, 101`). Elle n'est appelée sur `Saves` nulle part (§ 1.3). L'avertissement `WarnListOnSaves` signalera tout appel futur, par exemple depuis un mod.
|
||||
|
||||
## 2. Fichiers touchés, ordre
|
||||
|
||||
1. **Instantané** : `.\Tools\Snapshot.ps1 -Lot FIX1 -Path Plugins\ModdingExtra\Source\ModdingExtra\Private\ModdingExtraBPLibrary.cpp`. Le MD5 attendu avant est `7628837e7b77c68c3921acfad3d92ec0` (commande n° 8). S'il diffère, **arrêt** : la SPEC porte sur ce fichier-là.
|
||||
2. **IMPL** (outil Edit, le fichier est en LF, `i/lf w/lf`) : appliquer le diff indicatif du § 2.1, dans l'ordre des blocs a → g. Aucun autre fichier n'est modifié.
|
||||
3. **BUILD** (`lp-builder`, éditeur fermé) : `Tools\Build.ps1` sur la cible éditeur, puis sur la cible de jeu Development (empaquetage commun de la porte J4).
|
||||
4. **VAL** statique (`lp-validator` distinct), puis **essai en jeu** sous le jeton de la copie UE (§ 7).
|
||||
5. **DOC** (`lp-writer`) : README (`:23-24, 74, 82-83`, et `:117`, encore sur l'ancien dossier), ERR-042, guides de modding si Q2 = oui, `lp-validate`, REF1 (« `Content/Saves` doit exister mais rester vide », `REF1-CART-01.csv:41`), doc 37 (classement de F6).
|
||||
|
||||
### 2.1 Diff indicatif (texte, rien n'est appliqué)
|
||||
|
||||
Numéros de ligne : ceux du fichier actuel (MD5 ci-dessus). Indentation : 4 espaces, comme les fonctions voisines.
|
||||
|
||||
**a. Includes, après `:14` (`#include "Misc/Paths.h"`)**
|
||||
```cpp
|
||||
+#include "Misc/CommandLine.h"
|
||||
+#include "Misc/Parse.h"
|
||||
```
|
||||
Les deux en-têtes existent dans le moteur 5.8 (`Runtime/Core/Public/Misc/CommandLine.h`, `Misc/Parse.h`, Glob). `LPDataCache.cpp:9, 87` emploie déjà `FParse::Param(FCommandLine::Get(), …)`.
|
||||
|
||||
**b. Après `:27` (`DEFINE_LOG_CATEGORY_STATIC(LogModdingExtra, Log, All);`), avant le constructeur `:29`**
|
||||
```cpp
|
||||
+
|
||||
+// Lot FIX1-F6 (Docs/Migration/etat/REL/FIX1/FIX1-F6-SPEC.md, ERR-042) : fichiers de partie hors du dossier du jeu.
|
||||
+// Un chemin relatif a Content qui commence par "Saves/" est lu et ecrit sous FPaths::ProjectSavedDir() + "Saves/..."
|
||||
+// (dossier de sauvegarde, -UserDir du lot REL-SAV compris). Lecture : repli sur l'ancien Content/Saves, par slot,
|
||||
+// tant que le slot n'existe pas dans la nouvelle racine ; jamais pour _session. Ecriture : toujours la nouvelle racine.
|
||||
+// Tout autre chemin : inchange. -LPNoSavesRedirect retablit l'ancien comportement. Thread de jeu seulement.
|
||||
+namespace LPSavesRedirect
|
||||
+{
|
||||
+ static int32 NewReads = 0, OldReads = 0, Writes = 0;
|
||||
+
|
||||
+ static bool IsDisabled()
|
||||
+ {
|
||||
+ static const bool bDisabled = FParse::Param(FCommandLine::Get(), TEXT("LPNoSavesRedirect"));
|
||||
+ return bDisabled;
|
||||
+ }
|
||||
+
|
||||
+ // Vrai si le chemin vise Saves/. OutRel : separateurs '/', sans '/' de tete. OutSlot : segment qui suit "Saves/"
|
||||
+ // (vide pour un fichier pose directement dans Saves/).
|
||||
+ static bool Match(const FString& ContentRelativePath, FString& OutRel, FString& OutSlot)
|
||||
+ {
|
||||
+ OutRel = ContentRelativePath;
|
||||
+ OutRel.ReplaceInline(TEXT("\\"), TEXT("/"));
|
||||
+ while (OutRel.StartsWith(TEXT("/")))
|
||||
+ {
|
||||
+ OutRel = OutRel.Mid(1);
|
||||
+ }
|
||||
+ if (!OutRel.StartsWith(TEXT("Saves/"), ESearchCase::IgnoreCase))
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
+ const FString AfterSaves = OutRel.Mid(6);
|
||||
+ int32 Slash = INDEX_NONE;
|
||||
+ OutSlot = AfterSaves.FindChar(TEXT('/'), Slash) ? AfterSaves.Left(Slash) : FString();
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ // Journal : une ligne au premier acces redirige, puis une par slot et par racine ; compteurs pour le bilan.
|
||||
+ static void Note(const FString& Slot, bool bOld, bool bWrite)
|
||||
+ {
|
||||
+ static bool bFirst = true;
|
||||
+ if (bFirst)
|
||||
+ {
|
||||
+ bFirst = false;
|
||||
+ UE_LOG(LogModdingExtra, Display, TEXT("Saves redirige : racine '%s' (repli de lecture par slot : '%s')"),
|
||||
+ *FPaths::ConvertRelativePathToFull(FPaths::ProjectSavedDir() + TEXT("Saves")),
|
||||
+ *FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir() + TEXT("Saves")));
|
||||
+ }
|
||||
+ if (bWrite) { ++Writes; } else if (bOld) { ++OldReads; } else { ++NewReads; }
|
||||
+ static TSet<FString> Seen;
|
||||
+ bool bAlready = false;
|
||||
+ Seen.Add(FString(bOld ? TEXT("ancien|") : TEXT("nouveau|")) + Slot.ToLower(), &bAlready);
|
||||
+ if (!bAlready)
|
||||
+ {
|
||||
+ UE_LOG(LogModdingExtra, Display, TEXT("Saves slot '%s' : %s"), *Slot,
|
||||
+ bOld ? TEXT("lu dans l'ancien Content/Saves (repli)") : TEXT("nouvelle racine"));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Chemin a passer a FFileHelper. Hors Saves/ : ProjectContentDir() + chemin, exactement comme avant F6.
|
||||
+ static FString ResolvePath(const FString& ContentRelativePath, bool bForWrite)
|
||||
+ {
|
||||
+ FString Rel, Slot;
|
||||
+ if (!Match(ContentRelativePath, Rel, Slot))
|
||||
+ {
|
||||
+ return FPaths::ProjectContentDir() + ContentRelativePath;
|
||||
+ }
|
||||
+ if (IsDisabled())
|
||||
+ {
|
||||
+ static bool bLogged = false;
|
||||
+ if (!bLogged)
|
||||
+ {
|
||||
+ bLogged = true;
|
||||
+ UE_LOG(LogModdingExtra, Display, TEXT("Saves non redirige (-LPNoSavesRedirect) : ancien chemin Content/Saves"));
|
||||
+ }
|
||||
+ return FPaths::ProjectContentDir() + ContentRelativePath;
|
||||
+ }
|
||||
+ const FString NewPath = FPaths::ProjectSavedDir() + Rel;
|
||||
+ if (bForWrite || Slot.IsEmpty() || Slot.Equals(TEXT("_session"), ESearchCase::IgnoreCase))
|
||||
+ {
|
||||
+ Note(Slot, false, bForWrite);
|
||||
+ return NewPath;
|
||||
+ }
|
||||
+ IFileManager& FileManager = IFileManager::Get();
|
||||
+ if (!FileManager.DirectoryExists(*(FPaths::ProjectSavedDir() + TEXT("Saves/") + Slot))
|
||||
+ && FileManager.DirectoryExists(*(FPaths::ProjectContentDir() + TEXT("Saves/") + Slot)))
|
||||
+ {
|
||||
+ Note(Slot, true, false);
|
||||
+ return FPaths::ProjectContentDir() + Rel;
|
||||
+ }
|
||||
+ Note(Slot, false, false);
|
||||
+ return NewPath;
|
||||
+ }
|
||||
+
|
||||
+ // Les listes (GetAllFilesFromFolder, GetAllSubfolders) ne sont pas redirigees : signaler un usage sur Saves.
|
||||
+ static void WarnListOnSaves(const TCHAR* Function, const FString& RootFolder)
|
||||
+ {
|
||||
+ FString Rel, Slot;
|
||||
+ if (!Match(RootFolder + TEXT("/"), Rel, Slot))
|
||||
+ {
|
||||
+ return;
|
||||
+ }
|
||||
+ static TSet<FString> Warned;
|
||||
+ bool bAlready = false;
|
||||
+ Warned.Add(FString(Function) + TEXT("|") + Rel.ToLower(), &bAlready);
|
||||
+ if (!bAlready)
|
||||
+ {
|
||||
+ UE_LOG(LogModdingExtra, Warning, TEXT("%s | '%s' : liste lue dans Content, Saves non redirige pour les listes (FIX1-F6)"),
|
||||
+ Function, *RootFolder);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
```
|
||||
|
||||
**c. `GetAllFilesFromFolder`, après `:42` (`if(RootFolderFullPath.Len() < 1) return false;`)**
|
||||
```cpp
|
||||
+ LPSavesRedirect::WarnListOnSaves(TEXT("GetAllFilesFromFolder"), RootFolderFullPath);
|
||||
```
|
||||
|
||||
**d. `GetAllSubfolders`, après `:116`**
|
||||
```cpp
|
||||
+ LPSavesRedirect::WarnListOnSaves(TEXT("GetAllSubfolders"), RootFolderFullPath);
|
||||
```
|
||||
|
||||
**e. `LPLoadTxtStats::Dump`, après `:153` (ligne `TOTAL`)**
|
||||
```cpp
|
||||
+ UE_LOG(LogModdingExtra, Display, TEXT(" Saves : %d lecture(s) nouvelle racine | %d lecture(s) repli | %d ecriture(s)%s"),
|
||||
+ LPSavesRedirect::NewReads, LPSavesRedirect::OldReads, LPSavesRedirect::Writes,
|
||||
+ LPSavesRedirect::IsDisabled() ? TEXT(" (redirection desactivee)") : TEXT(""));
|
||||
```
|
||||
|
||||
**f. `LoadTxt`, `:190`**
|
||||
```cpp
|
||||
- const bool bOk = bFromCache || FFileHelper::LoadFileToString(SaveTextA, *(FPaths::ProjectContentDir() + FileNameA));
|
||||
+ const bool bOk = bFromCache || FFileHelper::LoadFileToString(SaveTextA, *LPSavesRedirect::ResolvePath(FileNameA, false));
|
||||
```
|
||||
`:195` reste inchangée (§ 1.3).
|
||||
|
||||
**g. `SaveTxt`, `:236`**
|
||||
```cpp
|
||||
- const bool bOk = FFileHelper::SaveStringToFile(SaveTextB, *(FPaths::ProjectContentDir() + FileNameB));
|
||||
+ const bool bOk = FFileHelper::SaveStringToFile(SaveTextB, *LPSavesRedirect::ResolvePath(FileNameB, true));
|
||||
```
|
||||
`:239` (`OnWritten(FileNameB, SaveTextB)`) reste inchangée.
|
||||
|
||||
Bilan du diff : 2 lignes modifiées et ≈ 100 lignes ajoutées dans 1 fichier, 0 supprimée. Les messages de journal sont en ASCII sans accents, comme le reste du fichier.
|
||||
|
||||
## 3. Repli
|
||||
|
||||
**Repli de lecture (fonctionnel) : par slot**, et non par fichier :
|
||||
- Un slot lu dans l'ancien dossier l'est **en entier**. Dès que `<SavedDir>/Saves/<Slot>` existe (premier enregistrement dans ce slot), plus rien n'est lu dans l'ancien dossier pour ce slot. Une partie ne peut donc pas mêler les personnages de deux parties (risque R2 de PRE).
|
||||
- `_session` n'a **jamais** de repli. L'ancien `Content/Saves/_session` contient la copie de travail d'une partie passée, jamais effacée (ModdingExtra n'a aucune fonction de suppression, § 1.3). La relire mêlerait une partie ancienne à la partie en cours.
|
||||
|
||||
**Migration (demande n° 5, décision R0, `REL-SAV-TACHES.md:19`)** :
|
||||
- Aucune copie, aucun déplacement, aucune suppression.
|
||||
- `Content/Saves/<Slot>/…` existants sont lus par le repli jusqu'au premier enregistrement du slot, puis ne sont plus lus. Ils ne sont **jamais modifiés**.
|
||||
- `Content/Saves/_session/…` déjà présent **n'est plus jamais lu ni écrit**. Il reste sur le disque, inerte, et le joueur peut l'effacer.
|
||||
- Le paquet garde son dossier `Content/Saves` vide (`REF1-CART-01.csv:41`). Une nouvelle installation n'y trouve rien, le repli n'y trouve rien non plus, et tout part dans la nouvelle racine.
|
||||
- Portée réelle du repli (estimé) : avec R0, les `.sav` lus sont ceux de `LifePlay-Revival\Saved\SaveGames`, donc ceux de l'alpha `2026.10.2.1a`. Leurs personnages sont dans `<dossier de l'alpha>\Content\Saves`. Le repli les retrouve si le joueur met à jour **sur place**, ou s'il a recopié `Content\Saves` comme le demande le README (`README.md:82-83`).
|
||||
|
||||
**Repli technique (retour arrière)** :
|
||||
- **À chaud** : lancer avec `-LPNoSavesRedirect`. Tout `Saves/…` revient à `ProjectContentDir()`. Une ligne de journal le signale, et le bilan l'indique.
|
||||
- **À froid** : `Tools\Restore.ps1` depuis l'instantané `FIX1`, ou `git revert` du commit d'IMPL (1 fichier), puis recompilation.
|
||||
- Les fichiers déjà écrits dans `<SavedDir>/Saves` restent. Si on revient en arrière, le jeu ne les lit plus : les parties enregistrées pendant l'essai sous F6 perdent leurs personnages tant que le dossier n'est pas recopié dans `Content/Saves`. À écrire dans l'annonce si on revient en arrière après publication.
|
||||
|
||||
## 4. Risques R#, questions Q#
|
||||
|
||||
| R | Risque | Parade | Niveau |
|
||||
|---|---|---|---|
|
||||
| R1 | Chemin chaud : `LoadTxt` sert toutes les données | hors `Saves/`, la branche rend **la même expression** qu'avant. Seul coût ajouté : une copie de chaîne et un `ReplaceInline` par lecture sur le disque ; les lectures servies par le cache ne passent pas par `ResolvePath` (court-circuit `:190`). VAL : relecture de la branche et bilan `LoadTxtStats` avant et après | estimé : coût négligeable devant `LoadFileToString` ; à confirmer par le bilan E8 |
|
||||
| R2 | Mélange de deux parties | repli par slot, jamais pour `_session` | établi par construction (§ 2.1 b) |
|
||||
| R3 | Slot à moitié écrit dans la nouvelle racine (enregistrement interrompu), donc plus de repli et des fichiers manquants | même conséquence qu'aujourd'hui pour un enregistrement interrompu : le message de GI s'affiche | estimé |
|
||||
| R4 | `DirectoryExists` à chaque lecture d'un slot (deux appels à `stat`) pendant `DuplicateCharacters` | quelques centaines de lectures au chargement, estimé ; aucun cache par slot, pour ne pas devenir faux après une écriture | estimé ; mesurable par la durée du chargement E3 |
|
||||
| R5 | Journal absent en Shipping | `bUseLoggingInShipping` absent des `*.Target.cs` (Grep sur `Source`, 0 ligne), donc journal compilé hors du Shipping (estimé : valeur par défaut du moteur). La preuve en Shipping se fait par les fichiers (E9) | établi (absence) ; estimé (effet) |
|
||||
| R6 | Outils et règles qui supposent `Content/Saves` (REF1, `21_Sandbox_Addon.md:213`, copie d'une partie de test) | DOC du lot | établi (PRE § 3.3) |
|
||||
| R7 | Chemin piégé (`Saves/../Modules/x`) | non normalisé : il serait redirigé sous `<SavedDir>`. Aucun littéral de cette forme (PRE § 3.2). Pas de parade en build 1 | estimé |
|
||||
| R8 | Mods qui lisent ou écrivent `Saves/…` par `LoadTxt`/`SaveTxt` | ils suivent la même règle : comportement cohérent | estimé |
|
||||
| R9 | Écriture refusée dans `<SavedDir>` (droits) | `SaveTxt` journalise déjà l'échec (`:243`) ; aucun repli d'écriture vers `Content` (décision U3 de REL-SAV : aucun repli) | établi (U3, `REL-SAV-TACHES.md:16`) |
|
||||
| R10 | Le moteur crée-t-il les sous-dossiers du slot ? | oui : `CreateFileWriterInternal` appelle `MakeDirectory(GetPath(Filename), true)` quand l'ouverture échoue (`FileManagerGeneric.cpp:110-116`, 5.8) | établi |
|
||||
|
||||
Questions fermées : rubrique 8 ci-dessous (Q1-Q7).
|
||||
|
||||
## 5. Interdits
|
||||
|
||||
- Modifier un Blueprint (GI compris), `LPDataCache.*`, `ModdingExtra.Build.cs`, `.uplugin`, `.uproject`, `Source/LifePlay/*`.
|
||||
- Changer la ligne `:195`, l'appel `OnWritten(FileNameB, …)` ou la clé passée à `TryGet` et `LPLoadTxtStats::Record`.
|
||||
- Rediriger `GetAllFilesFromFolder`, `GetAllSubfolders` ou `ContentDirectory` (avertissement seulement).
|
||||
- Copier, déplacer ou supprimer un fichier de `Content/Saves` (R0).
|
||||
- Ajouter un cache par slot, un repli par fichier, ou un repli de lecture pour `_session`.
|
||||
- Compiler dans l'IMPL si la fiche confie la compilation à BUILD. Compiler avec l'éditeur ouvert (`ue-cpp-build` § 8).
|
||||
- Écrire hors de l'instantané et du fichier cible, ou commiter (gardien du dépôt seulement).
|
||||
|
||||
## 6. Valeurs moteur lues dans le moteur installé (`D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Core`)
|
||||
|
||||
| Valeur | Source |
|
||||
|---|---|
|
||||
| `FPaths::ProjectSavedDir()` : `const FString&` | `Public/Misc/Paths.h:290` |
|
||||
| `ProjectSavedDir` se termine par `/` (`BaseDir + "Saved"` + suffixe facultatif + `/`) | `Private/Misc/Paths.cpp:87, 107` |
|
||||
| `ProjectContentDir()` = `ProjectDir() + "Content/"` | `Paths.h:276` ; `Paths.cpp:477` |
|
||||
| `ProjectUserDir` suit `-UserDir` | `Paths.cpp:451-471` (lu par REL-SAV-DIAG, non relu ici) |
|
||||
| `IFileManager::DirectoryExists(const TCHAR*)` | `Public/HAL/FileManager.h:119` |
|
||||
| Écriture : création de l'arborescence quand l'ouverture échoue | `Private/HAL/FileManagerGeneric.cpp:110-116` |
|
||||
| `FString::StartsWith(const TCHAR*, SearchCase = IgnoreCase)` | `Public/Containers/UnrealString.h.inl:1505` |
|
||||
| `FString::FindChar(ElementType, int32&)` | `UnrealString.h.inl:1219` |
|
||||
| `FString::Equals(const FString&, SearchCase = CaseSensitive)` | `UnrealString.h.inl:1271` |
|
||||
| `FPaths::ConvertRelativePathToFull(const FString&)` | `Paths.h:637` |
|
||||
| En-têtes `Misc/CommandLine.h`, `Misc/Parse.h` | Glob dans `Public/Misc` |
|
||||
|
||||
## 7. Critères de VAL (commande → attendu)
|
||||
|
||||
### 7.1 VAL statique (lp-validator)
|
||||
|
||||
| # | Contrôle | Attendu |
|
||||
|---|---|---|
|
||||
| V1 | `git diff --stat -- Plugins/ModdingExtra` | 1 fichier, ≈ 100 insertions, 2 suppressions |
|
||||
| V2 | relecture de la branche `!Match` de `ResolvePath` | `return FPaths::ProjectContentDir() + ContentRelativePath;`, identique à l'ancienne expression |
|
||||
| V3 | `:195`, `:239`, `TryGet(FileNameA, …)`, `Record(FileNameA, …)` | inchangés |
|
||||
| V4 | `_session` sans repli ; écriture jamais vers `ProjectContentDir()` quand la redirection est active | lu dans le code |
|
||||
| V5 | `git ls-files --eol` du fichier | `i/lf w/lf` |
|
||||
| V6 | `Tools\Build.ps1` (BUILD) | code 0 ; 0 erreur et 0 avertissement nouveaux dans `ModdingExtraBPLibrary.cpp` |
|
||||
|
||||
### 7.2 Essai en jeu (jeton de la copie UE ; build Development du commun, puis Shipping sur accord)
|
||||
|
||||
Préparation, écrite avant de lancer (TRACE) : relevé MD5 de `<jeu>\Content\Saves` (dossier absent ou vide = cas normal), et de `<SavedDir>\Saves` (absent attendu), par `Get-ChildItem -Recurse -File <dossier> | Get-FileHash -Algorithm MD5`.
|
||||
|
||||
| Cas | Montage | Attendu |
|
||||
|---|---|---|
|
||||
| E1 | nouvelle partie (Development, `Saved` à côté de l'exe ou `-UserDir` d'essai) | `<SavedDir>\Saves\_session\Characters\*.lpcharacter` créés ; journal : `LogModdingExtra: Display: Saves redirige : racine '…\Saved\Saves'` une fois, et `Saves slot '_session' : nouvelle racine` |
|
||||
| E2 | enregistrement dans un slot | `<SavedDir>\Saves\<Slot>\Characters\` contient les familles N, F, C, `OldPlayer`, `Player` présentes dans `_session` |
|
||||
| E3 | Quitter, puis Continuer ou Charger | partie identique, sans le message « missing crucial *.lpcharacter files » ; `Saves slot '<Slot>' : nouvelle racine` |
|
||||
| E4 | création de personnage (CharGen, BodyShapeMenu) | fichiers écrits sous `<SavedDir>\Saves\…` |
|
||||
| E1-E4 | relevé de `<jeu>\Content\Saves` après l'essai | **identique au relevé d'avant** (0 fichier créé ni modifié) |
|
||||
| E5 | repli : copier un slot d'essai (copie d'un slot de l'alpha, jamais l'original) dans `<jeu>\Content\Saves\<SlotX>`, avec son `.sav` dans `<SavedDir>\SaveGames` | chargement sans message ; journal `Saves slot '<SlotX>' : lu dans l'ancien Content/Saves (repli)` ; après enregistrement dans `<SlotX>`, `<SavedDir>\Saves\<SlotX>` existe et un nouveau chargement donne `nouvelle racine` ; relevé MD5 de `Content\Saves\<SlotX>` inchangé |
|
||||
| E6 | `-LPNoSavesRedirect`, nouvelle partie | `Saves non redirige (-LPNoSavesRedirect)` ; fichiers dans `<jeu>\Content\Saves\_session\…` (ancien comportement) ; bilan `(redirection desactivee)` |
|
||||
| E7 | `Select-String -Path <journal> -Pattern 'FIX1-F6'` | 0 ligne : aucune liste n'a visé `Saves` |
|
||||
| E8 | `ModdingExtra.LoadTxtStats` à la console et à la fermeture | ligne `Saves : n lecture(s) nouvelle racine \| m repli \| k ecriture(s)`, avec n > 0 et k > 0 après E1-E4 ; ligne `Cache de donnees pret : <x> fichier(s)` avec le même x qu'avant F6 (journal de référence du même build sans F6) ; aucune `LoadTxt CACHE ECART` avec `-LPDataCacheVerify` |
|
||||
| E9 (Shipping, sur accord) | Shipping sans `.ini` | `%LOCALAPPDATA%\LifePlay-Revival\Saved\Saves\…` créé ; relevé de `<jeu>\Content\Saves` inchangé (sans journal en Shipping : R5) |
|
||||
|
||||
Lecture des journaux : `Select-String -Path <journal> -Pattern 'LogModdingExtra: (Display|Warning): Saves','FIX1-F6','LoadTxt ECHEC'`. Toute ligne `LoadTxt ECHEC` sur un chemin `Saves/` pendant E1-E5 est un écart à rapporter.
|
||||
|
||||
**Porte J4 (proposition)** : PASS si V1-V6 sont conformes et si E1-E8 le sont au J4 soir. Sinon, retour arrière à froid (§ 3), F6 passe en build 2, et le README garde la limite connue.
|
||||
|
||||
**Coût (estimé, non mesuré)** :
|
||||
- IMPL `lp-impl` (Sonnet) : 8 à 15 tours, sans la copie UE ;
|
||||
- BUILD : une compilation incrémentale du plugin et du jeu ;
|
||||
- VAL statique : 8 à 12 tours ;
|
||||
- essai en jeu : 45 à 60 minutes sous le jeton (E5 demande de préparer une copie de slot) ;
|
||||
- DOC : 10 à 15 tours.
|
||||
|
||||
## 8. Questions fermées pour l'utilisateur (avec recommandation)
|
||||
|
||||
| Q | Question | Choix | Recommandation |
|
||||
|---|---|---|---|
|
||||
| Q1 | Nom de la racine | (a) `<SavedDir>\Saves\…` ; (b) `<SavedDir>\SaveGames\Saves\…` ; (c) `<SavedDir>\Characters\…` | **(a)** : le chemin relatif `Saves/…` est gardé tel quel (pas de réécriture du chemin, donc moins de risque). Les deux dossiers restent distincts : `SaveGames` (moteur, `.sav`) et `Saves` (personnages). Le joueur sauvegarde tout le dossier `Saved` d'un coup. |
|
||||
| Q2 | Corriger les guides de modding (`Docs/Modding/ShortGuides/explanation.lpcharacter:3`, `Docs/Modding/FullGuides/Creating_Presets.txt:7, 13, 15`) | oui / non | **Oui, en DOC du lot**, seulement si la porte J4 passe. Ces lignes décrivent l'emplacement des fichiers que le jeu génère, pas le contrat des mods : format et `Modules/<mod>/Presets` sont inchangés. Retirer `Saves/Default` (absent de tous les assets, commande n° 9). |
|
||||
| Q3 | Porte J4 | critères du § 7.2 / autre | **Garder les critères du § 7.2** : V1-V6 et E1-E8 au J4 soir, sinon build 2. E9 (Shipping) sur accord. |
|
||||
| Q4 | Catégorie du témoin | `LogModdingExtra` / `LogLifePlay` | **`LogModdingExtra`**. `LogLifePlay` n'est pas visible depuis le plugin (§ 1.2). Redéclarer une catégorie statique du même nom dans le plugin serait trompeur, puisque `log LogLifePlay …` ne réglerait qu'une des deux. |
|
||||
| Q5 | Nom de l'interrupteur | `-LPNoSavesRedirect` / autre | **`-LPNoSavesRedirect`**, sur le modèle de `-LPNoDataCache` (`LPDataCache.cpp:87`) et `-LPNoSaveRelaunch` (`REL-SAV-SPEC.md:39`). |
|
||||
| Q6 | Durée de vie du repli de lecture | jusqu'à la build 2 / permanent | **Permanent en build 1, réexaminé en build 2** (coût : deux tests de dossier par lecture d'un slot). |
|
||||
| Q7 | Message de GI « copy your old LifePlay\Content\Saves folder… » | corriger en build 1 / en build 2 | **Build 2**, avec la révision unique de GI. Le message reste juste à moitié grâce au repli (§ 1.5). |
|
||||
|
||||
## Constats
|
||||
|
||||
- Écart de méthode (établi) : `rg -a` sur des `.uasset` compte des correspondances dans le binaire, pas des nœuds. Le comptage `ContentDirectory` contre `GetProjectContentDirectory`, fichier par fichier (commande n° 6), est ce qui prouve que la fonction du plugin n'est pas appelée. Un Grep sur le seul mot `ContentDirectory` donnait 4 fichiers « positifs » à tort.
|
||||
- Inconnu restant : les relevés de GI datent du dump 5.5 (`L6f`, 2026-09-30) et de l'`EventGraph` 5.8 (`CAM-B1-PRE`, 2026-10-13). Les fonctions de GI n'ont pas été relevées de nouveau en 5.8. La redirection ne dépend pas de ce relevé, puisqu'elle est faite en C++ quel que soit l'appelant. E7 et le relevé MD5 de `Content\Saves` couvrent le cas d'un accès oublié.
|
||||
|
||||
Commandes et lectures de la fiche (comptes bruts) :
|
||||
1. Read `FIX1-F6-PRE.md`, `REL-SAV-SPEC.md`, `REL-SAV-DIAG.md`, `REL-SAV-TACHES.md`, `ModdingExtraBPLibrary.cpp` (279 l.), `.h`, `ModdingExtra.Build.cs`, `.uplugin`, `LPDataCache.h`, `LPDataCache.cpp:60-99, 240-293`, `LPSaveRelaunch.h`.
|
||||
2. Grep `appel ModdingExtraBPLibrary::(GetAllFilesFromFolder|GetAllSubfolders|ContentDirectory)` dans `L6f_dump_GI.txt` → 18 lignes, toutes `GetAllFilesFromFolder`.
|
||||
3. Grep `GetAllFilesFromFolder` (-A 8) dans `CAM-B1-PRE…083048.txt` → 8 nœuds, racines `'Modules'` ou concaténation `_664`.
|
||||
4. Grep `ContentDirectory|GetAllSubfolders` dans `L6f_dump_GI.txt` → 1 nœud, `KismetSystemLibrary::GetProjectContentDirectory()` (`:47227`).
|
||||
5. `rg -a -l -e ContentDirectory -e GetAllSubfolders -g "*.uasset" -g "*.umap" Content` → `BPs\GI`, `UI\ExtImg`, `UI\MainMenu`, `UI\FaceTexture`, code 0. Puis `rg -a -o … | sort | uniq -c` sur ces 4 fichiers : `Saves…` seulement dans GI.
|
||||
6. `rg -a -o -e GetProjectContentDirectory -e ModdingExtraBPLibrary -e "[A-Za-z]*ContentDir[A-Za-z]*"` sur 9 assets → GI 2 / 2, ExtImg 2, MainMenu 1, FaceTexture 1 (`GetProjectContentDirectory`) ; `ModdingExtraBPLibrary` 2 dans GI, MainMenu, CharGen, StatMenu, Contact, ContactMenu, BodyShapeMenu.
|
||||
7. `rg -a -l -e BlueprintFileUtils -e ImportFileAsTexture2D -e DeleteFile -e DirectoryExists -e LoadFileToString … Content` → code 1 (aucun fichier).
|
||||
8. `git log --oneline -3 -- …ModdingExtraBPLibrary.cpp` → `b8414af`, `d443257`, `4dfb70e` ; `git status --porcelain -- Plugins/ModdingExtra` → vide ; `md5sum` → `7628837e7b77c68c3921acfad3d92ec0` ; `git ls-files --eol` → `i/lf w/lf attr/-text`.
|
||||
9. `rg -a -l -e "Saves/Default" -e "Saves\\\\" … Content` → code 1 ; `rg -n -i Saves README.md Docs/Modding` → `README.md:23-24, 74, 82-83, 117, 259`, `Creating_Presets.txt:7, 13, 15`, `explanation.lpcharacter:3`.
|
||||
10. Grep moteur : `FileManagerGeneric.cpp:95-116`, `Paths.cpp:84-115, 477`, `Paths.h:276, 290, 637`, `FileManager.h:119`, `UnrealString.h.inl:1219, 1271, 1505`.
|
||||
11. Grep `bUseLoggingInShipping` dans `Source/*.Target.cs` → aucune ligne.
|
||||
|
||||
Fichiers à commiter (dépôt du jeu, `ue5.8`) :
|
||||
- `A Docs/Migration/etat/REL/FIX1/FIX1-F6-SPEC.md`
|
||||
|
||||
Tours : 20 / 25
|
||||
79
Docs/Migration/etat/REL/FIX1/FIX1-F6-VAL.md
Normal file
79
Docs/Migration/etat/REL/FIX1/FIX1-F6-VAL.md
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
Fiche FIX1-F6-VAL — Niveau N1 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-validator — Skills sk-protocol, sk-recount, debug-verification, lp-validate
|
||||
# FIX1-F6-VAL : validation statique de la redirection `Saves/…` (2026-10-20)
|
||||
|
||||
Verdict : **PASS-STATIC avec réserves** (équivalent de « PASS avec réserves » de la fiche : statique complet et rejoué, aucun essai en jeu).
|
||||
Rien n'a été modifié hors ce livrable. Seule écriture par commande : deux résumés `FIX1-VAL_BuildLog_20261020-191429.txt` et `-191430.txt` produits par `Build.ps1 -FromLog` dans `etat\REL\FIX1\` (ignorés par git, `.gitignore:75`).
|
||||
|
||||
## 1. Fiches amont relues
|
||||
- `etat\REL\FIX1\FIX1-F6-SPEC.md` (lue en entier, § 2.1 a-g et § 7.1).
|
||||
- `etat\REL\FIX1\FIX1-F6-IMPL.md` (lue en entier, § 5 points à confirmer).
|
||||
- `etat\REL\FIX1\FIX1-F6-PRE.md` : existe, non relue (la SPEC la cite, elle n'est pas un critère).
|
||||
- Journaux `Saved\Logs\portage\FIX1_Build_20261020-190716.log` et `-190831.log`.
|
||||
- Instantané `D:\Game\LifePlay_Backup_5.5\FIX1\` (manifeste et copie du fichier).
|
||||
|
||||
## 2. Points à confirmer des IMPL
|
||||
| Id | Verdict | Preuve |
|
||||
|---|---|---|
|
||||
| V1 | PASS | `git diff --stat -- Plugins/ModdingExtra` : `1 file changed, 120 insertions(+), 2 deletions(-)` ; recompté par `git diff --no-index --numstat <instantané> <fichier>` : `120 2`. Le « ≈ 100 » de la SPEC est bien une estimation basse (IMPL écart 3), le texte est celui de la SPEC. |
|
||||
| V2 | PASS | `ResolvePath`, branche `!Match` : `return FPaths::ProjectContentDir() + ContentRelativePath;` (diff, bloc b). Identique à l'ancienne expression. |
|
||||
| V3 | PASS | Diff complet : seules `LoadTxt` (`:308`) et `SaveTxt` (`:354`) changent. `:313` (relecture `ProjectContentDir() + FileNameA`), `:307` `TryGet(FileNameA…)`, `:309` `Record(FileNameA…)`, `:357` `OnWritten(FileNameB…)` hors hunks, donc inchangées. |
|
||||
| V4 | PASS | `_session` : `Slot.Equals("_session", IgnoreCase)` renvoie `NewPath` sans test de dossier. Écriture : `bForWrite` renvoie `NewPath`. L'ancien chemin n'est rendu que hors `Saves/` ou avec `-LPNoSavesRedirect`, ou pour une lecture de slot de repli. |
|
||||
| V5 | PASS | `git ls-files --eol` : `i/lf w/lf attr/-text` ; CR comptés par `tr -cd '\r' \| wc -c` : `0`. |
|
||||
| V6 | PASS | § 3. |
|
||||
| B1 | PASS (constat) | `LPKeyboardSubsystem.cpp` : MD5 `611c21489d80374a4817f70e408cf4db` (attendu `611c2148`), `i/crlf w/crlf`, lot KEY2, non touché par F6. Les binaires contiennent donc F6 + KEY2 ; à retenir pour le build de référence. |
|
||||
| B2 | reporté | Paquet Development non produit (IMPL § 5 B2) : hors périmètre VAL statique, étape suivante de l'ordonnateur. |
|
||||
| B3 | reporté | Shipping non compilé. |
|
||||
| B4 | non rejoué | Recherche UTF-16 de chaînes dans les binaires : non refaite (preuve de liaison seulement, sans valeur de comportement). Les unités compilées (§ 3) suffisent pour la liaison. |
|
||||
| C1 | PASS (lu) | Fichier posé directement dans `Saves/` : `Slot` vide, journal `Saves slot '' : nouvelle racine`, cosmétique. Voir § 5 réserve 3. |
|
||||
| C2 | PASS-STATIC | `static const bool` dans `IsDisabled()` : initialisation thread-safe C++11, lue au premier appel après l'initialisation de la ligne de commande (premier `LoadTxt` BP). E6 le tranchera en jeu. |
|
||||
| E1-E9 | reporté | Essais en jeu non faits (aucun jeu lancé). |
|
||||
|
||||
## 3. Critères rejoués
|
||||
| Contrôle | Commande | Résultat |
|
||||
|---|---|---|
|
||||
| MD5 du fichier | `md5sum Plugins/ModdingExtra/…/ModdingExtraBPLibrary.cpp` | `1f93601c71d126f173fe30636aec0660` (attendu 1f93601c : conforme) |
|
||||
| MD5 instantané | `md5sum D:/Game/LifePlay_Backup_5.5/FIX1/Plugins/…/ModdingExtraBPLibrary.cpp` | `7628837e7b77c68c3921acfad3d92ec0` (conforme) |
|
||||
| Autres fichiers de plugin/source | `git status --porcelain -- Plugins Source` | ` M …ModdingExtraBPLibrary.cpp` et ` M Source/LifePlay/LPKeyboardSubsystem.cpp` (KEY2, MD5 ci-dessus). `LPDataCache.*`, `Build.cs`, `.uplugin` non modifiés. `LifePlay.uproject` est modifié (date 2026-10-19 23:32, antérieur au lot, 15+/7-) : hors F6. |
|
||||
| Build 1 (LifePlayEditor) | `pwsh -NoProfile -File Tools/Build.ps1 -Lot FIX1-VAL -FromLog …190716.log -EtatDir <abs>` | `erreurs=0 avertissements=1 autres=20 unites=3` ; `Result: Succeeded` (log l. 61) ; `Total execution time: 57.83 seconds` ; l. 51 `Compile [x64] ModdingExtraBPLibrary.cpp`, l. 52 `Module.ModdingExtra.cpp`, l. 42 `Module.LifePlay.cpp`. Le code `-1` du résumé est celui de `-FromLog` (code de sortie non dans le journal), pas un échec. |
|
||||
| Build 2 (LifePlay Development) | idem, `…190831.log` | `erreurs=0 avertissements=1 autres=0 unites=3` ; `Result: Succeeded` (l. 33) ; 60.91 s ; mêmes 3 unités `[NoUba]`. |
|
||||
| Avertissement | Grep `warning C` dans les deux journaux | seul `LPCameraModeSubsystem.cpp(2378) : warning C4701` (`Aim`), connu ; aucun dans `ModdingExtraBPLibrary.cpp`. |
|
||||
| Toolchain | ligne `Using Visual Studio` des deux résumés | `14.50.35739 toolchain (…\MSVC\14.50.35717)` : conforme à la copie 5.8. |
|
||||
| PubCheck | `pwsh -NoProfile -File Tools/PubCheck.ps1 -Fichiers Plugins/ModdingExtra/Source/ModdingExtra/Private/ModdingExtraBPLibrary.cpp -Depot "D:/Game/LifePlay-master 5.8"` (stdin `/dev/null`) | `PubCheck : 0 constat(s)`, code 0. |
|
||||
|
||||
Non rejoué : `LPTestStringCompat` (la fiche ne le demande pas ; le test ne couvre pas ce code), compilation (la fiche demande de recompter seulement).
|
||||
|
||||
## 4. Diff lu en entier
|
||||
`git diff -U3 -- Plugins/ModdingExtra` lu en entier : 1 fichier, 120 insertions, 2 suppressions, hunks a, b, c, d, e, f, g de la SPEC § 2.1 et rien d'autre. Les deux lignes retirées sont exactement celles de la SPEC (f, g). L'IMPL signale que la ligne vide du bloc b est en fin de bloc plutôt qu'en tête : présentation uniquement, constatée dans le diff (l. 29-31 et 140-142 du fichier). Texte des blocs a-g relu ligne à ligne contre la SPEC : conforme, aucun ajout. Fichier non modifié par script d'après l'IMPL (outil Edit).
|
||||
|
||||
Revue de logique (établi par lecture du code) :
|
||||
| Exigence | Constat |
|
||||
|---|---|
|
||||
| Seul le préfixe exact `Saves/` est redirigé | `\` remplacé par `/`, `/` de tête retirés, `StartsWith("Saves/", IgnoreCase)`. `saves\x`, `/Saves/x` redirigés ; `Modules/…` et tout autre : `ProjectContentDir() + chemin` d'origine. Chemin absolu (`C:/…`) : non redirigé, comme avant. |
|
||||
| Repli par slot | Si `<SavedDir>/Saves/<Slot>` absent ET `<Content>/Saves/<Slot>` présent : lecture dans l'ancien. Sinon nouvelle racine. |
|
||||
| `_session` jamais de repli | confirmé (V4). |
|
||||
| Écriture toujours vers la nouvelle racine | confirmé, hors `-LPNoSavesRedirect`. |
|
||||
| `-LPNoSavesRedirect` | rétablit `ProjectContentDir() + chemin` pour `Saves/…` ; ligne de journal unique ; bilan `(redirection desactivee)`. |
|
||||
| Témoin sans débordement | une ligne racine, puis une par couple (racine, slot en minuscules) via `TSet`, plus 3 compteurs. Borné par le nombre de slots. |
|
||||
| LPDataCache | `TryGet` et `OnWritten` reçoivent `FileNameA`/`FileNameB` relatifs d'origine ; `TryGet` ne sert que `modules/` ; `ResolvePath` n'est appelée que si le cache n'a pas servi (court-circuit `bFromCache ||`). Aucun effet sur `Modules`. |
|
||||
| Accès concurrent | non sûr s'il y a plusieurs threads : voir réserve 1. |
|
||||
|
||||
## 5. Verdict et réserves numérotées
|
||||
Verdict : **PASS-STATIC avec réserves**. V1-V6 conformes ; build 2/2 `Succeeded`, seul C4701 connu ; essais en jeu non faits.
|
||||
|
||||
Réserves :
|
||||
1. **Concurrence** : `NewReads`/`OldReads`/`Writes` (`static int32` non atomiques), `Seen` et `Warned` (`TSet` statiques) et les `static bool` (`bFirst`, `bLogged`) ne sont pas protégés. Sûr seulement sur le thread de jeu (le commentaire du code le dit). C'est cohérent avec le code existant (`ReportedFailures`, commentaire l. 326 « Appele uniquement depuis les Blueprints »), et la SPEC prescrit ce code ; mais si un appel arrive d'un autre thread, courses possibles (compteurs faux, corruption du `TSet`). Aucun appel hors thread de jeu n'a été mesuré ici (**incertain**).
|
||||
2. **Traversée `..`** (R7 de la SPEC, accepté) : `Saves/../Modules/x` est redirigé sous `<SavedDir>/Modules/x` ; `Saves/../../x` écrirait au-dessus de `<SavedDir>` (aucune normalisation). Cas inverse : `Modules/../Saves/x` n'est pas détecté et reste dans l'ancien `Content/Saves`. Aucun littéral connu de ces formes ; un mod pourrait les produire.
|
||||
3. **Cas limites non couverts par un traitement dédié** : (a) `Saves` seul (sans `/`) : non redirigé, ancien chemin ; (b) `Saves/` final ou `Saves//x` : redirigé, `Slot` vide, traité comme fichier direct sans repli, journal `Saves slot '' …` ; (c) nom de slot vide : même cas ; (d) `./Saves/x` non détecté. Aucun usage connu (SPEC § 1.1).
|
||||
4. **Binaires** : contiennent aussi KEY2 non commité (B1) ; la référence E8 « même build sans F6 » est à choisir en tenant compte de cela.
|
||||
5. **Écart de format** : l'IMPL n'a pas de section ordonnée exactement « Constats » avant « Fichiers à commiter » : la section « Constats » est après `Tours :`, conforme au gabarit (section libre à la fin). Aucun écart.
|
||||
|
||||
## 6. Points à confirmer par l'utilisateur
|
||||
- [ ] Accepter les réserves 1 à 3 (SPEC R7 déjà acceptée) pour la build 1.
|
||||
- [ ] Faire produire le paquet Development (IMPL B2) puis jouer E1-E8 (SPEC § 7.2) ; les cas E1-E9 restent à passer.
|
||||
- [ ] Choisir le journal de référence de E8 en tenant compte de KEY2.
|
||||
|
||||
Témoin en jeu : COMMUN-<n> à créer (le cas de la fiche de tests commune pour F6 n'est pas identifié ici ; demande à l'ordonnateur : E1-E8 de la SPEC § 7.2).
|
||||
|
||||
Fichiers à commiter : `A Docs/Migration/etat/REL/FIX1/FIX1-F6-VAL.md` (les deux `FIX1-VAL_BuildLog_*.txt` sont ignorés par git).
|
||||
|
||||
Tours : 9 / 40
|
||||
235
Docs/Migration/etat/REL/FIX1/FIX1-F7-PRE.md
Normal file
235
Docs/Migration/etat/REL/FIX1/FIX1-F7-PRE.md
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
Fiche FIX1-F7-PRE — Niveau N2 — Modèle prévu non précisé par la fiche | utilisé claude-sonnet-5-5 — Agent lp-cart — Skills sk-protocol, ue-cpp-build, lp-commandlets, lp-paths
|
||||
# FIX1-F7-PRE : étude préliminaire de dimensionnement de F7 (ERR-011 : CenterBrow, animation « look », accessoires) et de F8b (meshZ au lever) (2026-10-20)
|
||||
|
||||
Hors gabarit : étude préliminaire (pas une CART complète), sur le modèle de `FIX1-F6-PRE.md`. Les rubriques 1 à 6 du gabarit CART sont gardées ; la rubrique 3 suit les quatre questions de la fiche (existant, localisation, dimensionnement et reproductibilité, recommandation), pour chacun des 4 sous-points : **F7a** avertissement CenterBrow, **F7b** animation « look » restée active, **F7c** accessoires détachés, **F8b** meshZ au lever. Lecture seule : ni copie UE, ni MCP, ni éditeur, ni commandlet. Seul ce fichier est écrit.
|
||||
|
||||
## Résumé (à lire en premier)
|
||||
|
||||
1. **La ligne FIX1 du doc 37 est à reclasser** : `37_Feuille_De_Route_Alpha2.md:171` range F6, F7 et F8 en « petits correctifs Blueprint par MCP » (`lp-mcp-bp`). Sur ces 4 sous-points, aucun n'est à la fois un correctif Blueprint net, avec un effet visible établi, et hors de GI.
|
||||
2. **F7a CenterBrow** : le lecteur est dans **GI** (`CalculateHeadtrack`, établi sur le dump 5.5) ; la garde utile est donc en **build 2** (GI n'est révisé qu'une fois). Aucun effet visible (`Registre_Erreurs.md:25`). Présent dans 8 journaux sur 11 relevés (141 à 6 138 lignes) : pas déterministe.
|
||||
3. **F7b « look »** : un seul constat (COMMUN-8, 2026-10-14), **aucune mesure depuis** (les lignes `STATE … currentAnimation=` n'existent que sous `-LPPersonsLog`, absent des 7 journaux COMMUN-15 à 21). Effet visible non établi. Un correctif d'un nœud dans Person est imaginable, mais ses consommateurs (`UpdateDailyPose`) sont à risque.
|
||||
4. **F7c accessoires** : un seul constat « mineur » (COMMUN-7), sans recette, lieu du défaut non lu (Person `spawnProp` / attaches, ou donnée d'animation : inconnu).
|
||||
5. **F8b meshZ** : **déjà neutralisé en C++** par M-Z (`LPDirectControlSubsystem.cpp:1200-1223`), validé en jeu (COMMUN-10) ; M-Z se déclenche **18 fois dans 9 journaux** (COMMUN-15 à 21), donc le défaut Blueprint est vivant, mais masqué. **Constat nouveau (estimé)** : les trois valeurs relevées −80,4 / −82,8 / −85,2 sont exactement −90 + 12 × {0,8 ; 0,6 ; 0,4}, la formule de `Person::updateHeelHeight` (talons). Si c'est la cause, forcer −90 (Blueprint ou M-Z) n'est pas un correctif et la ligne F8b est mal posée.
|
||||
6. **Recommandation** : build 1 = F8a seul (déjà fait) plus, au choix de l'utilisateur, **une séance de mesure** sur le build COM21 existant (sans copie UE) et **l'instrumentation de la ligne M-Z** (C++, quelques lignes, dans la compilation déjà prévue). F7a, F7c, F8b en **build 2** ; F7b en build 1 **seulement** si la mesure montre un effet visible avant la porte du 23 au soir. Détail en § 3.4.
|
||||
|
||||
| Sous-point | Où (établi ou estimé) | Effet visible | Reproduction | Agent · niveau | Build |
|
||||
|---|---|---|---|---|---|
|
||||
| F7a CenterBrow | GI `CalculateHeadtrack` (établi, dump 5.5) ; appelé par les AnimBP `Daily` et `Daily_F` (estimé) | aucun (journal seul) | 8 journaux sur 11, apparition non déterministe | `lp-mcp-bp` N2 (garde dans GI), dump 5.8 d'abord | **2** |
|
||||
| F7b « look » | Person : variable `currentAnimation` non vidée au lever (estimé) | non établi | 1 constat (14 octobre), aucune mesure depuis | `lp-diag` N2 (mesure), puis `lp-mcp-bp` N1 si effet | 1 sous condition, sinon après l'alpha |
|
||||
| F7c accessoires | inconnu (Person `spawnProp` / attaches, ou donnée) | « mineur » | 1 constat, pas de recette | `lp-diag` N2 | pas en 1 |
|
||||
| F8b meshZ | `Person::updateHeelHeight` (estimé) contre animations de place (hypothèse STG) : non tranché ; M-Z (C++) corrige déjà | corrigé en jeu | M-Z : 18 déclenchements en 9 journaux | `lp-impl` N1 (journal M-Z) ; correctif Blueprint : pas avant la mesure | **2** ou abandon |
|
||||
|
||||
## 1. Objet et périmètre
|
||||
|
||||
Un domaine : les défauts « animation et placement » de la ligne FIX1 hors F6 et hors F8a, soit F7 (`37_…:60` : « ERR-011 : avertissement CenterBrow ; animation « look » restée active ; accessoires détachés ») et la seconde moitié de F8 (`37_…:61` : « meshZ au lever dans le Blueprint »). Demande de Big Boss : ce qui est établi, ce qui reste et où (Blueprint : lequel ; C++ ; GI), dimensionnement et reproductibilité, recommandation (agent, niveau, durée, risque ; build 1 ou 2). Hors périmètre : F8a (`Aim`), F6, toute correction, tout essai.
|
||||
|
||||
## 2. Commandes et lectures (exactes) avec compte brut
|
||||
|
||||
| # | Commande ou lecture | Résultat brut |
|
||||
|---|---|---|
|
||||
| 1 | Read `gabarits.md` (CART), `FIX1-F6-PRE.md` | gabarit et modèle lus |
|
||||
| 2 | Grep `ERR-011` dans `Docs/Registre_Erreurs.md` ; Read `:25` | 1 ligne, `Registre_Erreurs.md:25` (citée en § 3.1) |
|
||||
| 3 | Grep `F7`, `F8b`, `meshZ`, `CenterBrow` dans `37_Feuille_De_Route_Alpha2.md` ; Read `:50-69`, `:160-194` | `:60`, `:61`, `:171` ; calendrier `:177-185` |
|
||||
| 4 | Grep `CenterBrow`, `meshZ`, `PlayerBusy` dans `BOSS-ETAT.md` ; Read `:222-243`, `:62-73` | `:70`, `:234`, `:235` |
|
||||
| 5 | Grep (compte) `CenterBrow` dans `etat/BOSS`, glob `*.log` | `Found 11033 total occurrences across 8 files.` (détail en § 3.1) |
|
||||
| 6 | Glob `*.log` dans `D:\Game\LifePlay_Build_5.8_Development_COM21\Windows\LifePlay\Saved\Logs` | 3 fichiers : `LifePlay.log`, `LifePlay-backup-2026.10.20-17.25.35.log`, `LifePlay-backup-2026.10.20-17.27.13.log` |
|
||||
| 7 | Grep (compte) `CenterBrow` puis `GetSocketInfoByName` dans ce dossier | `LifePlay.log:148` ; `LifePlay.log:669` et `…17.27.13.log:119` |
|
||||
| 8 | Grep (compte) `GetSocketInfoByName` dans `etat/BOSS`, glob `COMMUN-2*/*.log` | `COMMUN-21_session_1925_rotation.log:119`, `COMMUN-21_session_1927.log:669`, `COMMUN-20_session_1710.log:790` ; total 1578 |
|
||||
| 9 | Grep (compte) `GetSocketInfoByName\((Head\|hip\|pelvis\|chestUpper)\)` dans `LifePlay.log` (COM21) | `521` |
|
||||
| 10 | Grep `GetSocketInfoByName\(CenterBrow\)` dans `LifePlay.log` (COM21), 3 premières lignes puis `offset 145` | `:1645` (17:33:24.838), `:1676`, `:1712` ; `:2872`, `:2873` (17:36:01.238), `:2916` (ligne de bilan « 147 [LogSkinnedMeshComp Warning] … ») |
|
||||
| 11 | Grep `Person_C_2147481923` dans `LifePlay.log` (COM21), 8 premières | `:1060` (BeginPlay), `:1275-1276` (`index SPAWN`, `DESTROY…`), `:1278-1281` (Head ×2, pelvis, chestUpper à 17:32:08.569) |
|
||||
| 12 | Grep `M-Z :` dans `etat/BOSS`, glob `COMMUN-{15..21}/*.log`, mode contenu ; puis mode compte (`COMMUN-*/*.log`) | 18 lignes (liste en § 3.1) ; compte : 9 fichiers, `Found 18 total occurrences across 9 files.` |
|
||||
| 13 | Grep (compte) `currentAnimation=fnt` et `meshZ=` dans les journaux COMMUN-15 à 21 ; `currentAnimation=fnt` dans `LifePlay.log` COM21 | `No matches found` (trois fois) |
|
||||
| 14 | Read `LPDirectControlSubsystem.cpp:1196-1227` ; Grep `meshZ`, `M-Z` dans `Source` | M-Z `:1200-1223`, `MeshZScans` (`.h:88-89`) ; `LPDebugSubsystem.cpp:414` (ligne `STATE … meshZ= … currentAnimation=`) |
|
||||
| 15 | Read `LPDebugSubsystem.cpp:385-424`, `:628-647` | `STATE` écrit par `WritePersonsDump` ; déclenché par `-LPPersonsLog[=s]` (`:639-643`) ou la console `LifePlay.PersonsDump` (`:631-634`) |
|
||||
| 16 | Grep `CenterBrow`, `CalculateHeadtrack`, `HeadtrackTarget` dans `etat/portage55/L6f/L6f_dump_GI.txt` ; Read `:42272-42301` | `:42284`, `:42296`, `:42592`, `:42609` ; en-tête `:42273` ; appels `Person_C::FaceHeadtrackTarget` `:42832`, `:42834` |
|
||||
| 17 | Grep `^=== Person ::` (par tranches), `NewLocation = '`, `RelativeLocation\|currentAnimation\|…`, `updateHeelHeight`, `HeelHeight` sur `L6f_dump_Person.txt` (fichier nommé) ; Read `:19736-19835`, `:39405-39430` | en-têtes cités en § 3.2 ; `updateHeelHeight` appelée `:2528`, `:3767`, `:3772`, `:3794` ; définie `:19714` |
|
||||
| 18 | Grep `updateHeelHeight` sur `L6f_dump_GI.txt` (fichier nommé) | `:25258` (`Person_C::updateHeelHeight()`) |
|
||||
| 19 | Bash, depuis la racine : `for f in $(rg --files -g "Person.uasset" -g "GI.uasset" -g "Daily.uasset" -g "Daily_F.uasset" Content); do echo "== $f"; rg -a -o -e CalculateHeadtrack -e updateHeelHeight -e unOccupyFnt -e HeadtrackTarget -e CenterBrow -e spawnProp -e PlayFntAnim "$f" \| sort \| uniq -c; done` | `Daily` : CalculateHeadtrack 3, HeadtrackTarget 1 ; `Daily_F` : idem ; `GI` : CalculateHeadtrack 12, CenterBrow 5, HeadtrackTarget 2, spawnProp 2, unOccupyFnt 1, updateHeelHeight 1 ; `Person` : CenterBrow 3, HeadtrackTarget 3, PlayFntAnim 2, spawnProp 5, unOccupyFnt 8, updateHeelHeight 4 ; `exit=0` (comptes **bruts de correspondances dans le binaire** : preuve de présence du nom, pas de nœuds) |
|
||||
| 20 | Read `STE-H4-DIAG.md`, `STE-J6-TRACE.md:187-232`, `STG-COMMUN8-DIAG.md`, `STG-COMMUN9-DIAG.md`, `STG-MZ-IMPL.md`, `KEY2-DIAG-01.md:14-25`, `JOURNAUX1/ERR-brouillons.md` | cités en § 3 |
|
||||
| 21 | Glob `**/*D8*` sous `etat/ST/STE` ; Glob `*` sous `etat/REL/FIX1` | `No files found` ; 10 fichiers (F6 PRE, SPEC, IMPL, VAL, journaux de build) |
|
||||
|
||||
Écart de méthode à signaler, deux Grep de dossier **non concluants** : un Grep de dossier sur `etat/portage55/L6f` (motifs `unOccupyFnt`, `^=== Person :: …`, `updateHeelHeight`) a rendu `No matches found` alors que les mêmes motifs trouvent des lignes quand le fichier `.txt` est nommé (n° 17 et 18 : `updateHeelHeight` `:19714`, `:2528`…). Les `.txt` d'`etat/` sont ignorés par git (`.gitignore:53`) et un Grep de dossier les saute. **Un résultat vide d'un Grep de dossier sur `etat/` (hors `.md`/`.csv`) ne prouve rien** ; nommer le fichier (à verser). Les dumps de Blueprint lus sont ceux de 5.5 (L6f, 2026-09-30) : l'état des Blueprint en 5.8 n'a pas été relu (le `rg -a` du n° 19 ne prouve que la présence des noms).
|
||||
|
||||
## 3. Constats `fichier:ligne`
|
||||
|
||||
### 3.1 État de l'existant (question 1)
|
||||
|
||||
**F7a, avertissement CenterBrow**
|
||||
|
||||
| Constat | Source | Niveau |
|
||||
|---|---|---|
|
||||
| ERR-011 : signature `GetSocketInfoByName … No SkeletalMesh for CharacterMesh`, « 80/perso en 4.27, 76 en 5.5 », gravité « bruit (existe en 4.27) » ; part F5 du DESTROY corrigée (CHG-326) ; mise à jour JOURNAUX1 du 2026-10-14 : variante `CenterBrow` « à chaque image sur des Person détruites, sans effet visible (COMMUN-5, COMMUN-6) ; rattachement à confirmer » | `Docs/Registre_Erreurs.md:25` ; `COMMUN-6-BILAN.md:33` | établi |
|
||||
| Le brouillon JOURNAUX1 classe le rattachement « non établi » (statut « en cours ») | `JOURNAUX1/ERR-brouillons.md:91`, `:104` | établi |
|
||||
| Classé « Après l'alpha (non ouverts) » avec la « animation look » et les « accessoires détachés » | `BOSS-ETAT.md:235` | établi |
|
||||
| STE-H4 (J5) : 6 408 lignes `CenterBrow` (31,3 % du journal) ; lecteur **estimé fort** : GI `CalculateHeadtrack`, appelé par l'`EventGraph` des AnimBP `Daily` et `Daily_F` pour un vivant dont le `HeadtrackTarget` est resté sur un mannequin caché ; voie D = garde dans `CalculateHeadtrack` (`IsValid(Target)` et corps présent) ou vider le `HeadtrackTarget` au DESTROY ; **dumps STE-D8 requis** | `STE-H4-DIAG.md:6`, `:53`, `:88-105`, `:205-208`, `:262-273` | établi (texte) ; lecteur estimé |
|
||||
| Les dumps STE-D8 n'ont pas été produits | Glob `**/*D8*` sous `etat/ST/STE` : `No files found` | établi (cherché dans ce dossier seulement) |
|
||||
| Effet de C0 sur `CenterBrow` : 6 408 (J5), 6 227 (H9), 528 (J6) ; « la part de C0 dans cette baisse reste incertaine » | `STE-J6-TRACE.md:223`, `:229-231` | établi |
|
||||
| Aucune garde `CenterBrow` n'a été livrée : la ligne `CenterBrow` revient dans les journaux de COM21 | § 3.1 ci-dessous | établi |
|
||||
|
||||
Comptes de `CenterBrow` dans les journaux récents (Grep en mode compte, n° 5 et 7 ; un fichier absent de la sortie compte pour 0) :
|
||||
|
||||
| Journal | `CenterBrow` | `GetSocketInfoByName` (tous sockets) |
|
||||
|---|---|---|
|
||||
| `COMMUN-14\COMMUN-14.4-17_LifePlay_20261020-0757.log` | 141 | non mesuré |
|
||||
| `COMMUN-15\…_encours.log` | 0 | non mesuré |
|
||||
| `COMMUN-16\COMMUN-16_session_1131.log` | 0 | non mesuré |
|
||||
| `COMMUN-16\COMMUN-16_session_1136.log` | 649 | non mesuré |
|
||||
| `COMMUN-16\COMMUN-16_session_1207.log` | 151 | non mesuré |
|
||||
| `COMMUN-17\COMMUN-17_session_1253.log` | 302 | non mesuré |
|
||||
| `COMMUN-18\COMMUN-18_session_1358.log` | 6 138 | non mesuré |
|
||||
| `COMMUN-19\COMMUN-19_session_1457.log` | 3 355 | non mesuré |
|
||||
| `COMMUN-20\COMMUN-20_session_1710.log` | 149 | 790 |
|
||||
| `COMMUN-21\COMMUN-21_session_1925_rotation.log` | 0 | 119 |
|
||||
| `COMMUN-21\COMMUN-21_session_1927.log` | 148 | 669 |
|
||||
| COM21 `Saved\Logs\LifePlay.log` | 148 | 669 |
|
||||
| COM21 `…backup-2026.10.20-17.27.13.log` | 0 | 119 |
|
||||
|
||||
Somme des 8 journaux non nuls : 11 033 (concorde avec la sortie de l'outil). Le journal `COMMUN-21_session_1927.log` a les mêmes comptes que `LifePlay.log` de COM21 (148 et 669) : copie probable (MD5 non comparés). **Précision** : sur COM21, le compte 148 inclut **la ligne de bilan du journal** (`LifePlay.log:2916`, « 147 [LogSkinnedMeshComp Warning] GetSocketInfoByName(CenterBrow) … ») : il y a **147 avertissements**, et de même 669 = 148 + 521 (n° 9) ; la présence d'une ligne de bilan dans les autres journaux n'a pas été vérifiée.
|
||||
|
||||
Détail COM21 : les premières et dernières lignes `CenterBrow` (`:1645`, `:1676`, `:1712`, `:2872`, `:2873`) visent toutes `Person_C_2147481923`, acteur qui passe par `index SPAWN` puis `DESTROY…` (`:1275-1276`) ; les avertissements `CenterBrow` commencent à 17:33:24.838 (`:1645`), 76 s après le SPAWN, et finissent à 17:36:01.238 (`:2873`), soit 2 min 36 s. La cadence (une ligne par image ou non) n'a pas été établie. Les 521 autres lignes sont les sockets Head, hip, pelvis, chestUpper (part « bruit accepté » d'ERR-011).
|
||||
|
||||
**F7b, animation « look » restée active**
|
||||
|
||||
| Constat | Source | Niveau |
|
||||
|---|---|---|
|
||||
| COMMUN-8 (2026-10-14, 09:13:44-09:14:04) : le joueur garde `currentAnimation = fnt_new038-f-0-look` dans la rue puis au café, avec `meshZ -80,4` ; « animation de meuble restée active après le changement de pièce (Blueprint d'origine, estimé) » ; « Elle peut ajouter une posture penchée, mais ce n'est pas elle qui enfonce » ; versé à STE, « après l'alpha sauf effet visible » | `STG-COMMUN8-DIAG.md:22`, `:61-63`, `:73-74`, `:84-85` | établi (observation) ; cause estimée |
|
||||
| `currentAnimation` reste aussi renseigné après un lever ordinaire (`fnt_new048-f-0-sit`, journal COMMUN-9) : M-Z ne l'utilise donc pas comme garde | `STG-MZ-IMPL.md:45-46` | établi |
|
||||
| Registre des brouillons : N45, gravité faible (« mineur »), « ouvert, non instruit », 1 constat | `JOURNAUX1/ERR-brouillons.md:76` ; `JOURNAUX1/SUIVI-propositions.md:53` | établi |
|
||||
| Effet visible : non établi ; **aucune mesure depuis le 14 octobre** : les journaux COMMUN-15 à 21 ne contiennent ni `currentAnimation=fnt` ni `meshZ=` (n° 13), parce que la ligne `STATE` n'est écrite que sous `-LPPersonsLog` ou `LifePlay.PersonsDump` | `LPDebugSubsystem.cpp:414`, `:631-643` | établi |
|
||||
|
||||
**F7c, accessoires détachés**
|
||||
|
||||
| Constat | Source | Niveau |
|
||||
|---|---|---|
|
||||
| Seul constat : « Accessoire de place mal attaché (assiette et sandwich près de l'épaule) : mineur » (COMMUN-7) ; « hors B2q » | `BOSS/COMMUN-7-BILAN.md:28` ; `STG-B2q-IMPL.md:70` ; `JOURNAUX1/ERR-brouillons.md:76` | établi |
|
||||
| À ne pas confondre : « les accessoires restent visibles » pendant que le personnage assis disparaît (N36) est un autre défaut, **corrigé et validé en jeu** (B2q, COMMUN-9 P1, COMMUN-10 Q6) | `COMMUN-7-BILAN.md:20` ; `JOURNAUX1/ERR-brouillons.md:70` | établi (le bilan COMMUN-10 lui-même n'a pas été relu) |
|
||||
| La formule « accessoires détachés » de `BOSS-ETAT.md:235` et du doc 37 résume ce seul constat (estimé) | `BOSS-ETAT.md:235` ; `37_…:60` | estimé |
|
||||
|
||||
**F8b, meshZ au lever**
|
||||
|
||||
| Constat | Source | Niveau |
|
||||
|---|---|---|
|
||||
| Symptôme (COMMUN-9) : les pieds sont à 9,8 cm au-dessus du sol (`delta -9.8`) alors que la capsule est au sol ; `meshZ` relatif −80,4 (ou −82,8) au lieu de −90 ; « rien ne remet −90 au lever » ; PNJ féminines debout concernées (12 relevés, `currentAnimation=-`) ; lecture : `unOccupyFnt` et `PlayIdle` ne rétablissent pas la position du maillage (Blueprint d'origine, **estimé**) | `STG-COMMUN9-DIAG.md:16-31` | établi (mesure) ; cause estimée |
|
||||
| **Contournement C++ livré** : M-Z dans `FitPersonBounds` (balayage de 0,5 s) remet le Z relatif du maillage à celui du gabarit de la classe (−90 pour `Person_C`) si : aucun meuble, pas de scène, capsule en collision, écart > 1 cm, **2 balayages de suite** | `LPDirectControlSubsystem.cpp:1200-1223` ; `STG-MZ-IMPL.md:26-46` | établi |
|
||||
| Validé en jeu : « plus de flottement après le lever, M-Z confirmé » (COMMUN-10 Q4) | `JOURNAUX1/ERR-brouillons.md:75` (qui cite `C10-BILAN:14`) | établi (bilan non relu) |
|
||||
| **M-Z se déclenche encore** : 18 lignes `M-Z :` dans 9 journaux (COMMUN-15 : 1 ; 16/1131 : 1 ; 16/1136 : 3 ; 16/1207 : 1 ; 17 : 4 ; 18 : 4 ; 19 : 1 ; 20 : 2 ; 21 : 1). 16 sur `PlayerCharacter`, 2 sur des PNJ. Valeurs d'origine : −80,4 ×5 ; −85,2 ×6 ; −88,0 ×7 | n° 12 (ex. `COMMUN-20_session_1710.log:1666`, `COMMUN-17_session_1253.log:1484`, `COMMUN-18_session_1358.log:3367`) | établi |
|
||||
| Dans le dump 5.5 de Person, la seule fonction qui écrit un Z de maillage autre que −90 est **`updateHeelHeight`** : si le tableau de chaînes contient `Heels`, `HeelHeight` = dernière chaîne convertie en nombre, puis `Mesh.K2_SetRelativeLocation(0, 0, −90 + 12 × HeelHeight)` ; sinon `HeelHeight = 0` et Z = −90. Les autres écritures de Z sont le −90 littéral (`:19832`, `:39421`) | `L6f_dump_Person.txt:19714`, `:19754`, `:19778-19790`, `:19804-19832` ; grep `NewLocation` : `:8315-8370` (X/Y des composants de pénis), `:19832`, `:39421` | établi (dump 5.5) |
|
||||
| `updateHeelHeight` est appelée par `Strip` (`:2528`) et `Dress` (`:3767`, `:3772`, `:3794`) dans Person, et une fois dans GI (`:25258`) ; **pas** par `PlayIdle`, `unOccupyFnt`, `standIdle` ni `jumpOffFnt` (leurs en-têtes : `:12042`, `:12836`, `:13117`, `:13536` ; aucune occurrence entre ces lignes dans le Grep du fichier) | `L6f_dump_Person.txt` ; `L6f_dump_GI.txt:25258` | établi (dump 5.5) |
|
||||
| Les valeurs relevées sont exactement −90 + 12 × H pour H = 0,8 (−80,4), 0,6 (−82,8), 0,4 (−85,2) ; −88,0 (7 occurrences sur 18) n'est pas sur cette grille (2,0 / 12 = 0,1667) | calcul sur § 3.1 et `STG-COMMUN9-DIAG.md:22` | **estimé** (coïncidence arithmétique, non mesurée) |
|
||||
| `meshZ = −88` figure aussi dans l'étude des caméras de scène | `CAM-COMMUN9-DIAG.md:14` | établi (ligne seule lue) |
|
||||
| À ne pas confondre avec « personnage enfoncé » : l'enfoncement dans la rue (ancien ERR-128) vu à COMMUN-15 venait de `PlayerBusy` resté vrai après une visite de l'onglet Clavier (`LiftSunkPersons` ne relevait pas le joueur) ; corrigé en C++ (fermeture des réglages pendant une capture, `5ff9f26d`), COMMUN-16.22 PASS. Le `meshZ` relevé, lui, **fait flotter**, il ne fait pas enfoncer | `KEY2-DIAG-01.md:20-24` ; `BOSS-JOURNAL.md:815`, `:840` | établi |
|
||||
|
||||
### 3.2 Où est le reste (question 2)
|
||||
|
||||
| Sous-point | Où | Preuve | Niveau |
|
||||
|---|---|---|---|
|
||||
| F7a | **GI** : fonction `CalculateHeadtrack` (44 nœuds) lit `GetSocketLocation('CenterBrow')` sur le `Mesh` de `From` (`K2Node_CallFunction_3`) et de `To` (`K2Node_CallFunction_1`) ; elle appelle `Person_C::FaceHeadtrackTarget` ; deux autres lectures de `CenterBrow` dans GI, fonction non identifiée | `L6f_dump_GI.txt:42273-42296`, `:42592`, `:42609`, `:42832`, `:42834` | établi (dump 5.5) |
|
||||
| F7a | **AnimBP `Daily` et `Daily_F`** portent le nom `CalculateHeadtrack` (3 correspondances chacun) : appelants (estimé, déjà dit par STE-H4) | `rg -a -o` n° 19 ; `STE-H4-DIAG.md:95-97` | estimé |
|
||||
| F7a | **Person** : `FaceHeadtrackTarget` lit aussi `CenterBrow` ; `Person.uasset` : 3 correspondances | `STE-H4-DIAG.md:91-94` ; n° 19 | établi (texte STE-H4) |
|
||||
| F7a | Aucun C++ ne lit `CenterBrow` : **non cherché ici** (STE-H4 : 0 pour `chestUpper` dans `Source` et `Plugins`) | `STE-H4-DIAG.md:302-304` | incertain |
|
||||
| F7b | **Person** : la variable `currentAnimation` est lue par `UpdateDailyPose` (`SetAnimationMode` puis deux affectations `Animation` ← `currentAnimation`), `SetAnimationAsset`, `unOccupyFnt` (lectures seules) ; elle est écrite dans le graphe d'événements (affectée `:33526`, vidée `:33341` et `:38779`) | `L6f_dump_Person.txt:12615-12682` (en-tête `UpdateDailyPose` `:12615`), `:12780-12815`, `:12836-12844`, `:13042`, `:33341`, `:33526`, `:38779` | établi (dump 5.5) |
|
||||
| F7b | `unOccupyFnt` ne contient **pas** d'affectation de `currentAnimation` (les trois affectations sont au-delà de la ligne 33000) ; si l'une des deux remises à vide tourne au lever ou au changement de pièce : inconnu | grep `currentAnimation` sur le dump | établi (absence dans la fonction) ; reste inconnu |
|
||||
| F7c | **Person** : `spawnProp` (`:14529`), `clearProps` (`:14582`) ; 7 nœuds `K2_AttachToComponent` dans le graphe d'événements (`:37915-38461`) ; `spawnProp` 5 correspondances dans Person et 2 dans GI | dump Person ; n° 19 | établi (existence) ; lieu du défaut inconnu |
|
||||
| F8b | **Person** `updateHeelHeight` (Blueprint, appelée par `Strip`, `Dress`, GI) ; **C++** M-Z dans `LPDirectControlSubsystem` | § 3.1 | établi |
|
||||
| F8b | `PlayIdle` / `unOccupyFnt` ne rétablissent pas le Z (STG) : consistant avec l'absence d'appel à `updateHeelHeight` ; `PlayFntAnim` (2 correspondances dans `Person.uasset`) : sa définition n'est pas dans les en-têtes lus, le dump la montre appelée au graphe d'événements (`:33740`) | `L6f_dump_Person.txt:33740` ; n° 19 | établi (appel) ; effet sur le Z inconnu |
|
||||
|
||||
GI touché ? **F7a : oui** (la garde naturelle est dans `GI::CalculateHeadtrack`, voie A de § 3.3), donc build 2 selon la révision unique de GI (`BOSS-JOURNAL.md:693`, `:870` : « révision unique en build 2 »). F7b, F8b : **non** (Person, C++). F7c : inconnu. Les AnimBP `Daily` et `Daily_F` ne seraient pas à modifier pour la voie A.
|
||||
|
||||
### 3.3 Dimensionnement et reproductibilité (question 3)
|
||||
|
||||
**F7a**
|
||||
|
||||
| Voie | Contenu | Taille (estimée) | GI ? |
|
||||
|---|---|---|---|
|
||||
| A, garde dans `CalculateHeadtrack` | avant `K2Node_CallFunction_1` et `_3` : `IsValid(From)`, `IsValid(To)` et maillage présent (`GetSkinnedAsset` valide), sinon retour sans calcul | 4 à 8 nœuds sur 44, 2 coupures (comparable aux 2 à 3 nœuds de la voie C de STE-H4, `STE-H4-DIAG.md:199`) | **oui** |
|
||||
| B, à la cause | vider le `HeadtrackTarget` des vivants qui visent un mannequin au DESTROY, ou exclure les mannequins cachés de `getNearestDummy` | non dimensionnable : « la chaîne exacte (qui pose le `HeadtrackTarget`, pourquoi il reste) » est inconnue (`STE-H4-DIAG.md:252`) | probablement (GI et Person) |
|
||||
| C, réglage de journal | abaisser la verbosité de `LogSkinnedMeshComp` par configuration | 1 ligne de configuration ; **masque** aussi les 521 lignes des autres sockets et les vrais cas ; effet en Shipping non lu | non |
|
||||
| D, ne rien faire | l'avertissement existe depuis la 4.27 (`Registre_Erreurs.md:25`) | 0 | non |
|
||||
|
||||
Reproduction : non déterministe. 8 journaux sur 11 contiennent `CenterBrow` (de 141 à 6 138 lignes), 3 n'en ont aucune ; sur COM21 la série commence 76 s après le SPAWN d'un mannequin et dure 2 min 36 s. La condition d'apparition (un vivant dont le `HeadtrackTarget` pointe un mannequin sans corps) est **estimée**, pas démontrée. **Preuve en jeu** : build Development (journal avec avertissements), jouer jusqu'à au moins un `index SPAWN` suivi de `DESTROY`, attendre 3 minutes, compter `GetSocketInfoByName(CenterBrow)` (Grep en mode compte, moins la ligne de bilan). Critère : 0 ligne `CenterBrow` avec au moins un SPAWN, les 521 autres lignes inchangées. Une session à 0 sans SPAWN ne prouve rien (3 journaux de référence sont à 0). Le Shipping n'a pas été examiné (`bUseLoggingInShipping` non lu, `STE-H4-DIAG.md:253-254`).
|
||||
|
||||
**F7b**
|
||||
|
||||
| Critère | Établi | Estimé | Inconnu |
|
||||
|---|---|---|---|
|
||||
| Correctif | — | un nœud « affecter `currentAnimation` = vide » en fin de `unOccupyFnt` ou à l'entrée d'une pièce (Person seul, 1 nœud, 2 liens) | si un autre chemin relit `currentAnimation` après le lever : `UpdateDailyPose` le réaffecte à `Animation` (`:12635-12682`), donc vider peut changer ce que ce chemin joue ; risque moyen |
|
||||
| Effet visible | aucun établi | posture penchée possible (`STG-COMMUN8-DIAG.md:62-63`) | tout |
|
||||
| Reproduction | 1 constat (COMMUN-8) : `look` d'un meuble (vitrine), puis changement de pièce | — | si le clip joue encore (`anim=single:…`) ou si seule la variable est périmée |
|
||||
|
||||
Preuve en jeu : sans copie UE, avec le build COM21 lancé avec `-LPPersonsLog=2` (`LPDebugSubsystem.cpp:639-643`), utiliser l'action « regarder » sur un meuble de boutique, sortir, relever pendant 30 s la ligne `STATE PlayerCharacter … anim=… currentAnimation=…`. Attendu avant correctif : `currentAnimation=fnt_…-look` (COMMUN-8). Après : `currentAnimation=-`, et `anim=` sans `single:…look`. Un essai sans effet visible clôt F7b (« ne pas corriger »).
|
||||
|
||||
**F7c**
|
||||
|
||||
Taille : non dimensionnable. Une attache de prop mal placée peut venir du Blueprint (`spawnProp`, 7 attaches), d'un décalage de donnée d'animation, ou de la pose de la place (lien avec le Z du maillage : non démontré). Reproduction : aucune recette (1 constat, « mineur », assiette et sandwich ; meuble et animation non notés dans le bilan). **Preuve en jeu** à définir après une première reproduction avec capture d'écran (même place, mêmes accessoires, avant et après).
|
||||
|
||||
**F8b**
|
||||
|
||||
| Critère | Établi | Estimé | Inconnu |
|
||||
|---|---|---|---|
|
||||
| Cause | le Z relatif du maillage n'est pas −90 après le lever et rien dans `PlayIdle` / `unOccupyFnt` ne le remet | −90 + 12 × HeelHeight (talons, `updateHeelHeight`) pour −80,4 / −82,8 / −85,2 | le chemin qui écrit −88,0 (7 cas sur 18) ; si le joueur et les PNJ concernés portent des talons ; le lien avec le premier meuble utilisé (`STG-COMMUN9-DIAG.md:24`) |
|
||||
| Contournement | M-Z, 18 déclenchements en 9 journaux | M-Z corrige 1 s au plus tard après le lever | M-Z force −90 **sans lire `HeelHeight`** : si les talons sont la cause, il retire un décalage voulu par le Blueprint ; sa validation (« plus de flottement ») ne dit rien sur les talons |
|
||||
| Correctif Blueprint | — | « appeler `updateHeelHeight` en fin de `unOccupyFnt` » (Person seul, 1 nœud d'appel) rétablirait −90 + 12 H plutôt que −90 : **hypothèse**, `updateHeelHeight` lit le tableau de vêtements | effet sur la pose assise ; GI appelle `unOccupyFnt` (1 correspondance dans `GI.uasset`) |
|
||||
|
||||
Reproduction : **fiable avec les journaux** (M-Z écrit une ligne à chaque correction). Preuve en jeu : (1) compter les lignes `M-Z :` sur une séance avec au moins un meuble utilisé puis quitté : valeur de référence 1 à 4 par séance (COMMUN-15 à 21) ; (2) après un correctif Blueprint, M-Z doit rester **silencieux** (0 ligne) sur la même séance ; (3) départage talons / place : habiller le joueur sans talons, s'asseoir, se lever, relever `meshZ=` (nécessite `-LPPersonsLog`) ; ou ajouter `HeelHeight` à la ligne M-Z (voir § 3.4).
|
||||
|
||||
### 3.4 Recommandation (question 4)
|
||||
|
||||
**Agent, niveau, durée (estimés), risque, build**
|
||||
|
||||
| Sous-point | Étape | Agent · niveau | Durée (estimée, non mesurée) | Risque | Build |
|
||||
|---|---|---|---|---|---|
|
||||
| F7a | dump 5.8 de `CalculateHeadtrack` (`LPDumpFunction -BP=GI -Fn=CalculateHeadtrack -Pins -Exec`, éditeur fermé : copie UE) ; IMPL de la garde ; VAL | `lp-mcp-bp` N2 pour l'IMPL (GI par MCP, instantané avant) ; `lp-validator` N2 | dump 5 tours ; IMPL 15 à 25 tours ; VAL 10 à 15 tours ; essai 15 à 20 min de jeu | faible pour le jeu (garde sur un nœud lu) ; risque de calendrier : GI n'est révisé qu'une fois, la garde doit partir avec les autres retouches de GI | **build 2** |
|
||||
| F7b | mesure sans copie UE (build COM21, `-LPPersonsLog=2`), puis éventuellement 1 nœud dans Person | `lp-diag` N2 pour la mesure ; `lp-mcp-bp` N1 pour l'IMPL | mesure : 20 min de jeu par l'utilisateur ou Big Boss + 10 à 15 tours d'analyse ; IMPL 10 à 15 tours ; VAL 10 tours | moyen : consommateurs de `currentAnimation` (`UpdateDailyPose`) | build 1 **seulement si** la mesure montre un effet visible avant le **23 au soir** (créneau FIX1 sur la copie UE au J3, VAL au J4, `37_…:183-184`) ; sinon après l'alpha |
|
||||
| F7c | reproduction avec capture, lecture MCP de `spawnProp` et des attaches | `lp-diag` N2 | 15 à 20 tours après une reproduction | non évaluable | pas en build 1 |
|
||||
| F8b | instrumenter la ligne M-Z (C++, dans `LPDirectControlSubsystem.cpp:1216`) : y ajouter `HeelHeight` et `currentAnimation` du Person (lecture par réflexion, comme les autres lectures de variables Blueprint du même module) | `lp-impl` N1 | 5 à 10 tours, **dans la compilation déjà prévue pour F8a** (pas de jeton UE supplémentaire, hors essai) | très faible (journal) | build 1 (option) |
|
||||
| F8b | correctif Blueprint | aucun avant la mesure | — | forcer −90 peut retirer un décalage de talons | **build 2** ou abandon (M-Z couvre) |
|
||||
|
||||
**Ordre conseillé (estimé)** : (1) une séance de jeu de 20 à 30 minutes sur le build COM21 existant, **sans copie UE**, avec `-LPPersonsLog=2`, qui sert F7b et F8b : le joueur avec talons puis sans talons s'assied et se lève ; « regarder » un meuble de boutique puis changer de pièce ; (2) lecture des lignes `STATE`, `M-Z :` et `CenterBrow` (Grep, 10 tours) ; (3) décision par sous-point. Si l'instrumentation de M-Z est acceptée, la réponse « talons ou place » arrive aussi **gratuitement** dans les essais suivants.
|
||||
|
||||
**Ce qu'il ne faut pas faire (estimé)** : confier F7 et F8b à `lp-mcp-bp` en bloc comme le dit le doc 37 (`:171`) ; toucher GI en build 1 pour un avertissement sans effet visible ; corriger le Z du maillage au lever avant d'avoir départagé talons et place ; ajouter une garde sur `currentAnimation` dans M-Z (M-Z l'écarte exprès, `STG-MZ-IMPL.md:45-46`).
|
||||
|
||||
**Build 1 ou build 2 (décision de l'utilisateur)** : build 1 = F8a (fait) et, au plus, F7b et l'instrumentation de M-Z. Aucun de ces sous-points ne justifie de risquer le gel du 24 octobre ; F7a est de toute façon bloqué par la règle GI. F7a, F7c, F8b : build 2 (le journal du dépôt garde ERR-011 ouvert ; aucun texte public à corriger n'a été trouvé, README et annonces non relus ici).
|
||||
|
||||
## 4. Établi / estimé / incertain (synthèse)
|
||||
|
||||
**Établi (relu à la source)** : ERR-011 et sa mise à jour JOURNAUX1 (`Registre_Erreurs.md:25`) ; classement « après l'alpha » (`BOSS-ETAT.md:235`) ; comptes de `CenterBrow` des 13 journaux de § 3.1 ; sur COM21, 147 avertissements (+ 1 ligne de bilan), un seul acteur sur les 5 lignes vues, 76 s après le SPAWN ; `GI::CalculateHeadtrack` lit `CenterBrow` sur `From.Mesh` et `To.Mesh` (dump 5.5) ; les dumps STE-D8 n'existent pas ; constat « look » du 14 octobre (`STG-COMMUN8-DIAG.md`) ; `currentAnimation` jamais affectée dans `unOccupyFnt` (dump 5.5) ; STATE seulement sous `-LPPersonsLog` ; un seul constat d'accessoire (`COMMUN-7-BILAN.md:28`) ; M-Z (code, journal, 18 déclenchements) ; `updateHeelHeight` (formule et appelants dans le dump 5.5) ; l'enfoncement KEY2 est une autre cause (`PlayerBusy`).
|
||||
|
||||
**Estimé (déduit)** : le lecteur de `CenterBrow` est `CalculateHeadtrack` appelé par `Daily` et `Daily_F` ; la cible est un mannequin sans corps ; la garde de la voie A suffit (4 à 8 nœuds) ; une variable `currentAnimation` périmée peut être réappliquée par `UpdateDailyPose` ; −80,4 / −82,8 / −85,2 sont des décalages de talons (arithmétique exacte, non mesurée) ; M-Z force −90 sans égard aux talons ; durées et niveaux de § 3.4.
|
||||
|
||||
**Incertain, essai qui trancherait** :
|
||||
- F7a : appelants réels de `CalculateHeadtrack` et origine du `HeadtrackTarget` : `LPDumpFunction -BP=Daily -Fn=EventGraph -Pins -Exec` (AnimBP accepté par la commande : incertain, `STE-H4-DIAG.md:271`) ; état en 5.8 de la fonction : dump 5.8 (copie UE).
|
||||
- F7a : effet visible éventuel (regard tourné vers l'origine jusqu'à 57 s, `STE-H4-DIAG.md:285-286`) : jamais observé.
|
||||
- F7b : le clip joue-t-il encore ou seule la variable est-elle périmée ? Séance `-LPPersonsLog=2` (§ 3.3).
|
||||
- F7c : tout (lieu, cause, recette).
|
||||
- F8b : talons ou place ; chemin du −88,0 ; talons portés par les PNJ concernés : séance avec et sans talons, ou `HeelHeight` dans la ligne M-Z.
|
||||
- Dumps 5.5 contre Blueprint 5.8 : Person et GI ont été retouchés depuis le 30 septembre (par exemple `IsValid(Person)` dans `moveToPersonStand`, `JOURNAUX1/ERR-brouillons.md:23`) : les fonctions citées sont à relire en 5.8 avant toute SPEC.
|
||||
|
||||
## 5. Points à confirmer (repris par la fiche suivante)
|
||||
|
||||
1. Rafraîchir en 5.8, par commandlet (copie UE, éditeur fermé), les dumps `GI :: CalculateHeadtrack`, `Person :: updateHeelHeight`, `Person :: unOccupyFnt`, `Person :: UpdateDailyPose` et l'`EventGraph` de Person (affectations de `currentAnimation`), avec `lp-commandlets` (forme : `.\Tools\RunCommandlet.ps1 -Lot FIX1-F7 -Commandlet LPDumpFunction -Args '-BP=<nom> -Fn=<fonction> -Pins -Exec'`).
|
||||
2. Chercher `CenterBrow` dans `Source` et `Plugins` (non fait ici).
|
||||
3. Identifier la fonction de GI qui appelle `updateHeelHeight` (`L6f_dump_GI.txt:25258`) et les deux autres lectures de `CenterBrow` dans GI (`:42592`, `:42609`).
|
||||
4. Lire `C10-BILAN` (Q4, Q6) et `COMMUN-7-BILAN` en entier pour F7c (meuble, animation, circonstances).
|
||||
5. Vérifier si les autres journaux portent une ligne de bilan comptée dans les 141 à 6 138.
|
||||
6. Vérifier que le Shipping écrit ou non l'avertissement (`bUseLoggingInShipping`, non lu).
|
||||
|
||||
## 6. Questions pour la SPEC ou l'utilisateur
|
||||
|
||||
1. F7a : laisser l'avertissement en build 1 (bruit depuis la 4.27, sans effet visible) et le traiter dans la révision unique de GI en build 2 ?
|
||||
2. Autoriser une séance de jeu de 20 à 30 minutes sur le build COM21 avec `-LPPersonsLog=2` (sans copie UE) pour F7b et F8b ?
|
||||
3. Autoriser l'ajout de `HeelHeight` et `currentAnimation` à la ligne M-Z dans la compilation de F8a (une ligne C++, journal seul) ?
|
||||
4. F8b : si les talons sont la cause, M-Z doit-il cesser de forcer −90 pour un personnage à talons ? (le « flottement » constaté à COMMUN-9 était-il réel à l'écran ?)
|
||||
5. F7c : l'utilisateur se souvient-il de la place et du repas concernés (capture) ?
|
||||
6. Reclasser la ligne FIX1 du doc 37 : F7a et F8b hors des « petits correctifs Blueprint par MCP » de la build 1, F7b conditionnel ?
|
||||
|
||||
## Fichiers à commiter
|
||||
|
||||
A `Docs/Migration/etat/REL/FIX1/FIX1-F7-PRE.md` (dépôt jeu, branche `ue5.8`), par le gardien sur ticket. Aucun autre fichier écrit.
|
||||
|
||||
Tours : 26 / 25 (budget « environ 25 » dépassé de 1 : recherche des appelants de `updateHeelHeight` et vérification que les Grep de dossier sur `etat/` sautent les `.txt` ; `Tools/FicheStats.py` fait foi)
|
||||
|
||||
## Constats
|
||||
|
||||
- Quatre Grep de dossier sur `etat/portage55/L6f` ont rendu un résultat vide à tort (fichiers `.txt` ignorés par git) ; les mêmes motifs, sur le fichier nommé, trouvent les lignes. Rejouer toute recherche négative sur un fichier nommé avant de conclure à une absence.
|
||||
- Les comptes d'un Grep en mode compte sur des journaux qui portent une ligne de bilan `LogStats` incluent cette ligne (+ 1 sur COM21).
|
||||
137
Docs/Migration/etat/REL/FIX1/FIX1-F8a-IMPL.md
Normal file
137
Docs/Migration/etat/REL/FIX1/FIX1-F8a-IMPL.md
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
Fiche FIX1-F8a — Niveau N2 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-impl — Skills sk-protocol, ue-cpp-build
|
||||
# FIX1-F8a-IMPL : initialisation de `Aim` dans `TickCoupleMouse`, avertissement C4701 (2026-10-20)
|
||||
|
||||
Décision citée par la fiche : l'utilisateur a répondu « approuvé » à la proposition de Big Boss (`local_104ff22d`, qui a donné le jeton UE) : « F8 (Aim) est trivial et sans risque, il tient en build 1 ». La fiche ne donne ni la session ni l'heure de cette réponse (`sk-protocol` § 2) : je la traite comme une consigne de fiche, sans en tirer d'autre décision (aucune publication, aucun arbitrage de risque de mon côté).
|
||||
Hors gabarit : la compilation de contrôle (demandée par la fiche) est rendue dans `## Constats`, avec sa note TRACE.
|
||||
Écart de skills : la fiche cite `sk-protocol, ue-cpp-build`. Dans mon contexte sont aussi chargés `lp-build` et `lp-ue-compat` (utilisés pour les commandes de build et la liste des lignes connues).
|
||||
Niveaux de preuve : **établi** (fichier:ligne ou sortie de commande), **estimé** (raisonnement donné), **incertain** (essai nommé).
|
||||
|
||||
## 1. Fichiers modifiés
|
||||
|
||||
Un seul fichier de source : `D:\Game\LifePlay-master 5.8\Source\LifePlay\LPCameraModeSubsystem.cpp`.
|
||||
|
||||
| Mesure | Valeur | Commande |
|
||||
|---|---|---|
|
||||
| MD5 avant (exigé `4fd44bd4`) | `4fd44bd4b636c1f8d14c601bea513d14`, conforme ; identique à l'instantané | `md5sum Source/LifePlay/LPCameraModeSubsystem.cpp` avant la première édition |
|
||||
| MD5 après | `976bf0a458b87f9aecf974fcec3209f0` (inchangé après les deux builds) | `md5sum` après les 2 éditions et après les 2 builds |
|
||||
| Taille avant, après | 136 950 o, 136 994 o (+44 = 2 x 22 caractères ` = FVector::ZeroVector`) | manifeste de l'instantané ; `wc -c` |
|
||||
| Fins de ligne | `i/lf w/lf attr/-text` ; 0 CR | `git ls-files --eol Source/LifePlay/LPCameraModeSubsystem.cpp` ; `tr -cd '\r' < … \| wc -c` -> `0` |
|
||||
| Bilan du diff | `1 file changed, 2 insertions(+), 2 deletions(-)` | `git diff --stat -- Source/LifePlay/LPCameraModeSubsystem.cpp` |
|
||||
| Autres fichiers touchés dans `Source` et `Plugins/ModdingExtra` | aucun | `git status --porcelain -- Source Plugins/ModdingExtra` -> une seule ligne ` M Source/LifePlay/LPCameraModeSubsystem.cpp` |
|
||||
|
||||
Les deux éditions (outil Edit) ; le nombre de lignes du fichier ne change pas, donc les numéros de ligne sont les mêmes avant et après :
|
||||
|
||||
```diff
|
||||
@@ -2277,3 +2277,3 @@ bool ULPCameraModeSubsystem::TickCoupleMouse(UGameInstance* GI, APlayerControlle
|
||||
GrabHeight = bGrabHasHeight ? LPCameraModeLocal::CoupleLowestRoot(Couple) - SurfaceZ : 0.0;
|
||||
- FVector Aim;
|
||||
+ FVector Aim = FVector::ZeroVector;
|
||||
GrabOffset = TraceScreen(GrabMouseStart, Aim) ? FVector(Pivot.X - Aim.X, Pivot.Y - Aim.Y, 0.0) : FVector::ZeroVector;
|
||||
@@ -2368,3 +2368,3 @@ bool ULPCameraModeSubsystem::TickCoupleMouse(UGameInstance* GI, APlayerControlle
|
||||
bGrabMoved |= FVector2D::Distance(GrabMouseStart, GrabCursor) >= LPCameraModeLocal::CoupleDragThreshold;
|
||||
- FVector Aim;
|
||||
+ FVector Aim = FVector::ZeroVector;
|
||||
const bool bAim = bGrabMoved && TraceScreen(GrabCursor, Aim);
|
||||
```
|
||||
|
||||
Positions : déclaration 1 = `LPCameraModeSubsystem.cpp:2278` (lecture à `:2279`) ; déclaration 2 = `:2369` (lecture gardée par `bAim` à `:2370`, `:2376`, `:2378`, qui est la ligne citée par l'avertissement).
|
||||
|
||||
**Logique inchangée (établi).** `TraceScreen` est le lambda `:2149-2161` : il renvoie `false` avant d'écrire `Out` (`:2157`) et n'écrit `Out = Hit.ImpactPoint` (`:2159`) qu'avant de renvoyer `true` (`:2160`). `Aim` n'est donc lu que si `TraceScreen` a réussi : `:2279` (opérateur ternaire) et `:2376-2378` (`if (bAim)`, avec `bAim = bGrabMoved && TraceScreen(...)`, `:2370`). La valeur d'initialisation n'est jamais lue ; elle ne sert qu'à lever l'avertissement.
|
||||
|
||||
API moteur employée : `FVector::ZeroVector`, `CORE_API static const TVector<T> ZeroVector;` dans `D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Core\Public\Math\Vector.h:79` (établi). Même expression que celle déjà présente à `LPCameraModeSubsystem.cpp:2279`. Aucun code de compatibilité UE4 (`LPStringCompat`, `LPMeshCompat`, `LPNavigationHelpers`) touché.
|
||||
|
||||
## 2. Écarts à la SPEC
|
||||
|
||||
La fiche tient lieu de SPEC (pas de SPEC séparée). Écarts :
|
||||
|
||||
1. **Aucun écart de code** : les deux déclarations ont reçu `= FVector::ZeroVector`, rien d'autre.
|
||||
2. **Numéros de ligne** : la fiche cite l. 2278 et 2369 pour les déclarations et l. 2378 pour l'avertissement ; relevés conformes dans le fichier de départ (`Grep` : `2278`, `2369`, `2378`).
|
||||
3. **Approbation** citée sans session ni heure : voir l'en-tête. Sans conséquence sur le périmètre (changement de deux lignes, aucune publication).
|
||||
4. **Unités recompilées** : le build 1 a recompilé `Module.ModdingExtra.cpp` et lié `UnrealEditor-ModdingExtra.dll` alors que ce lot ne touche pas `ModdingExtra`. Cause relevée dans le journal : `Invalidating makefile for LifePlayEditor (working set of source files changed)` (`FIX1_Build_20261020-195129.log:8`) ; le fichier `ModdingExtraBPLibrary.cpp` (lot F6) était compilé hors du fichier unity au build précédent et rentre maintenant dans `Module.ModdingExtra.cpp`. **Estimé** (le journal ne dit pas pourquoi `ModdingExtra` est rejoué). Sans effet sur la source.
|
||||
|
||||
## 3. Instantané
|
||||
|
||||
- Dossier : `D:\Game\LifePlay_Backup_5.5\FIX1-F8\` (lot FIX1-F8), pris par l'ordonnateur avant mon intervention ; je ne l'ai pas refait (consigne de la fiche).
|
||||
- Manifeste `D:\Game\LifePlay_Backup_5.5\FIX1-F8\manifest.csv` : une ligne, `Source/LifePlay/LPCameraModeSubsystem.cpp`, `Existed=True`, `Size=136950`, `MD5=4FD44BD4B636C1F8D14C601BEA513D14`, `Date=2026-10-20T19:50:03`.
|
||||
- Contrôle (établi) : `md5sum D:/Game/LifePlay_Backup_5.5/FIX1-F8/Source/LifePlay/LPCameraModeSubsystem.cpp` -> `4fd44bd4b636c1f8d14c601bea513d14`, identique au MD5 de départ du fichier du jeu.
|
||||
- Retour arrière à froid : `Tools\Restore.ps1 -Lot FIX1-F8` (proposé, non lancé), ou `git revert` du commit d'IMPL ; recompilation ensuite.
|
||||
|
||||
## 4. Ce qui n'a pas été fait
|
||||
|
||||
- Aucun autre fichier ni autre déclaration : seules les deux déclarations `FVector Aim;` de `TickCoupleMouse` ont changé. Je n'ai pas cherché d'autres variables locales non initialisées dans le fichier (le build n'en signale aucune : 0 avertissement).
|
||||
- Pas de build Shipping, pas d'empaquetage (`BuildDebug.ps1`), aucun jeu lancé : le comportement à l'exécution n'est pas mesuré (il est inchangé par construction, voir § 1).
|
||||
- Pas de VAL (relecture indépendante), pas de DOC, pas de CHG ni de ligne de journal (hors fiche).
|
||||
- Pas de `Tools/FicheStats.py` : le nombre de tours ci-dessous est estimé par moi.
|
||||
- Aucune commande git qui écrit ; aucun commit ; rien publié.
|
||||
|
||||
## 5. Points à confirmer en VAL
|
||||
|
||||
Un point par ligne.
|
||||
|
||||
- V1 : `git diff --stat -- Source/LifePlay/LPCameraModeSubsystem.cpp` rend `1 file changed, 2 insertions(+), 2 deletions(-)` ; `git diff -U1` ne montre que les deux lignes `FVector Aim = FVector::ZeroVector;` (aux l. 2278 et 2369).
|
||||
- V2 : `md5sum` du fichier = `976bf0a458b87f9aecf974fcec3209f0` ; `git ls-files --eol` = `i/lf w/lf` ; 0 CR.
|
||||
- V3 : journal `Saved\Logs\portage\FIX1_Build_20261020-195129.log` (éditeur) et `…-195230.log` (jeu) : 0 ligne `C4701|warning C[0-9]+|error C[0-9]+|error LNK` (témoin positif : le journal `FIX1_Build_20261020-190716.log`, avant correction, donne 1 ligne, `LPCameraModeSubsystem.cpp(2378) : warning C4701`).
|
||||
- V4 : les deux journaux montrent `Compile [x64] LPCameraModeSubsystem.cpp` (l. 41 et l. 20) : le fichier modifié a bien été recompilé (hors fichier unity, `[Adaptive Build]`), pas seulement relié.
|
||||
- V5 : résumés `Build.ps1` : build 1 `erreurs=0 avertissements=0 autres=20` (les 20 lignes `HyperAIStudio` attendues pour LifePlayEditor, `lp-build` § 7) ; build 2 `erreurs=0 avertissements=0 autres=0`.
|
||||
- V6 : les binaires du jeu ne contiennent aucune autre modification de source que les deux lignes (`git status --porcelain -- Source Plugins` ne montre que ce fichier) : l'exe `b178a8be…` et la DLL `a1d61a56…` correspondent à « HEAD `ad3c9c6` + F8a ». Contrairement à F6, `LPKeyboardSubsystem.cpp` n'est plus modifié (KEY2 commité).
|
||||
- C1 : **incertain**, essai non fait : aucune exécution en jeu du glissé de couple (`TickCoupleMouse`) ; la logique est inchangée par construction (§ 1) mais rien n'a été lancé.
|
||||
|
||||
## 6. Fichiers à commiter
|
||||
|
||||
Dépôt du jeu (`D:\Game\LifePlay-master 5.8`, branche `ue5.8`) :
|
||||
|
||||
- `M Source/LifePlay/LPCameraModeSubsystem.cpp`
|
||||
- `A Docs/Migration/etat/REL/FIX1/FIX1-F8a-IMPL.md`
|
||||
|
||||
Les deux résumés `FIX1_Build_20261020-195129.txt` et `FIX1_Build_20261020-195230.txt` sont écrits par `Build.ps1` dans `Docs/Migration/etat/REL/FIX1/` mais **ignorés par git** (`git check-ignore -v` : `.gitignore:75 /Docs/Migration/etat/**` pour les deux `.txt` ; le livrable `.md` est rétabli par `.gitignore:77 !/Docs/Migration/etat/**/*.md`) : rien à commiter pour les résumés.
|
||||
|
||||
À **ne pas** inclure dans ce ticket (modifiés par d'autres lots, présents dans le `git status`) : `LifePlay.uproject`, `Docs/Migration/etat/BOSS/BOSS-ETAT.md`, `BOSS-JOURNAL.md`, `Docs/Migration/etat/REPO/FILE.md`, `Docs/LP-PROJET.ini`, `Docs/Migration/etat/AG/ORGA2/`. Le gardien commite par chemins explicites (`sk-repo`).
|
||||
|
||||
Les journaux complets restent dans `Saved\Logs\portage\` (hors dépôt).
|
||||
|
||||
Tours : 21 / 40 (estimé ; `Tools/FicheStats.py --lot FIX1` fait foi)
|
||||
|
||||
## Constats
|
||||
|
||||
### Compilation de contrôle (demandée par la fiche)
|
||||
|
||||
Trace : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\FIX1\FIX1_Build_20261020-195129.txt` et `…\FIX1_Build_20261020-195230.txt` — Fiche FIX1-F8a — 2026-10-20 19:51 à 19:54
|
||||
Commande : `CopieEtat.ps1 -Lot FIX1 -Assets Source/LifePlay/LPCameraModeSubsystem.cpp` avant ; puis `pwsh -NoProfile -File Tools/Build.ps1 -Lot FIX1 -EtatDir "D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\FIX1"` (éditeur), puis `… -Lot FIX1 -Target LifePlay -Config Development -ExtraArgs '-NoUBA' -EtatDir …` (jeu), dans `D:\Game\LifePlay-master 5.8`, stdin sur `/dev/null`
|
||||
Environnement: copie 5.8, branche `ue5.8`, HEAD `ad3c9c6`, moteur UE 5.8 (`EngineAssociation 5.8`), machine calme (`UeState` : `processus=0 editeur=0 compilation=0 shaders=0 jeu=0` avant, entre les deux builds et après ; `CopieEtat` : `COPIE OK … proc=0 … alertes=aucune`, code 0, avant et après)
|
||||
Attendu : code 0 ; 0 erreur ; 0 avertissement C4701 (et aucun autre) ; unité `LPCameraModeSubsystem.cpp` recompilée
|
||||
Obtenu : tableau ci-dessous
|
||||
Lecture : le champ `Makefile` des deux résumés est vide ; les journaux disent `Invalidating makefile for LifePlayEditor (working set of source files changed)` (l. 8 du journal 1) et `… for LifePlay …` (l. 8 du journal 2) : makefiles recréés. Le résumé du build jeu écrit « Unreal Build Accelerator local executor » alors que `-NoUBA` est passé : les unités sont marquées `[NoUba]`, le texte du résumé n'est pas le signe fiable. Piège de comptage : `pwsh -NoProfile -File Tools/LogStats.ps1 -Log <journal> -Pattern 'a','b','c'` passe la liste en une seule chaîne et rend **0 ligne** à tort, même sur le journal d'avant la correction (faux zéro, relevé ici : `0 lignes sur 57`, puis écarté) ; le comptage retenu est une seule expression à alternatives `C4701|warning C[0-9]+|error C[0-9]+|error LNK`, validée par un témoin positif sur le journal d'avant (1 ligne).
|
||||
|
||||
| Mesure | Build 1 : LifePlayEditor Win64 Development | Build 2 : LifePlay Win64 Development `-NoUBA` |
|
||||
|---|---|---|
|
||||
| Résumé | `…\REL\FIX1\FIX1_Build_20261020-195129.txt` | `…\REL\FIX1\FIX1_Build_20261020-195230.txt` |
|
||||
| Journal | `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\FIX1_Build_20261020-195129.log` | `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\FIX1_Build_20261020-195230.log` |
|
||||
| Code de sortie, durée | 0 ; 50 s (`Total execution time: 49.70 seconds`, journal l. 56) | 0 ; 65 s (`Total execution time: 64.22 seconds`, journal l. 31) |
|
||||
| `Result:` | `Succeeded` (journal l. 55) | `Succeeded` (journal l. 30) |
|
||||
| Ligne `Using Visual Studio` | `14.50.35739 toolchain (…\MSVC\14.50.35717) and Windows 10.0.22621.0 SDK` = MSVC épinglé de la copie 5.8 (journal l. 34) | identique (journal l. 13) |
|
||||
| Actions | 8 | 5 |
|
||||
| Erreurs du compilateur | 0 | 0 |
|
||||
| Avertissements du compilateur | **0** (0 C4701) | **0** (0 C4701) |
|
||||
| Autres lignes (UBT, UHT, liens) | 20 : toutes `Plugin 'HyperAIStudio' does not list plugin '…'` (nombre attendu pour LifePlayEditor, `lp-build` § 7) | 0 (attendu pour la cible jeu) |
|
||||
| Unités compilées | 3 : `LPCameraModeSubsystem.cpp` (l. 41), `Module.LifePlay.cpp` (l. 42), `Module.ModdingExtra.cpp` (l. 46) | 3 : les mêmes, `[NoUba]` (l. 20, 21, 22) |
|
||||
| DLL liées / exécutable | 2 DLL : `UnrealEditor-LifePlay.dll` (l. 45), `UnrealEditor-ModdingExtra.dll` (l. 47) | 0 DLL (cible monolithique) ; `[4/5] Link [x64] LifePlay.exe [NoUba]` (l. 23) |
|
||||
|
||||
Avant la correction (journal du lot F6, `FIX1_Build_20261020-190716.log:43`) : `LPCameraModeSubsystem.cpp(2378) : warning C4701: variable locale 'Aim' potentiellement non initialisée utilisée`, `while compiling ULPCameraModeSubsystem::TickCoupleMouse`. Après : plus aucune ligne d'avertissement dans les deux journaux. Le module modifié figure dans les unités compilées et dans les DLL liées (`lp-build` § 9, points 4 et 6). Avertissement nouveau : aucun.
|
||||
|
||||
MD5 des produits (`md5sum` / `ls -l`, après les deux builds) :
|
||||
|
||||
| Fichier | MD5 | Taille, heure |
|
||||
|---|---|---|
|
||||
| `Binaries\Win64\LifePlay.exe` | `b178a8be373c2d0ac527e4ec0ff4c31e` | 335 847 424 o, 19:53:32 |
|
||||
| `Binaries\Win64\UnrealEditor-LifePlay.dll` | `a1d61a56b3c8e5cbbf9c13907031811d` | 1 990 656 o, 19:52:11 |
|
||||
| `Plugins\ModdingExtra\Binaries\Win64\UnrealEditor-ModdingExtra.dll` | `78a0129d1dd94d2c427c3bae60e0d4df` | 416 768 o, 19:52:18 |
|
||||
| `Binaries\Win64\UnrealEditor-LifePlayEditorTools.dll` | non relié ce coup-ci (19:08:04, build du lot F6) | 659 968 o |
|
||||
| `Source\LifePlay\LPCameraModeSubsystem.cpp` | `976bf0a458b87f9aecf974fcec3209f0` | (source) |
|
||||
|
||||
Rappel des produits du lot F6 (avant) : `LifePlay.exe` `811f72f2…` (335 846 400 o), `UnrealEditor-LifePlay.dll` `e5d2c9c9…` (1 992 704 o), `UnrealEditor-ModdingExtra.dll` `7e8eeec5…` (416 768 o), d'après `FIX1-F6-IMPL.md`. Ces binaires ont donc changé ; l'essai en jeu éventuel de F6 doit se refaire sur le nouvel exe (`b178a8be…`).
|
||||
|
||||
### Autres contrôles
|
||||
|
||||
- `pwsh -NoProfile -File Tools/PubCheck.ps1 -Fichiers Source/LifePlay/LPCameraModeSubsystem.cpp -Depot "D:/Game/LifePlay-master 5.8"` (stdin `/dev/null`) -> `PubCheck : 0 constat(s)`, code 0.
|
||||
- Fin de mission : `Tools\UeState.ps1` -> `processus=0 editeur=0 compilation=0 shaders=0 jeu=0`, code 0 ; jeton UE rendu.
|
||||
- Scripts : aucun script écrit. Les sorties des deux builds ont été redirigées vers le dossier temporaire de la session (hors dépôt).
|
||||
125
Docs/Migration/etat/REL/FIX1/FIX1-MES.md
Normal file
125
Docs/Migration/etat/REL/FIX1/FIX1-MES.md
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
Fiche FIX1-MES — Niveau N1 — Modèle prévu non précisé par la fiche | utilisé claude-sonnet-5-5 — Agent lp-writer (rôle A-DOC) — Skills sk-protocol, lp-doc, lp-lot
|
||||
# FIX1-MES : protocole de séance de mesure `-LPPersonsLog=2` (hauteur de talons et animation « look », F8b et F7b) (2026-10-20)
|
||||
|
||||
Demande de Big Boss (`local_104ff22d`), 2026-10-20, sur ordre de l'utilisateur, cité mot pour mot : « … en build 1, ajoute la hauteur de talons et l'animation à la trace M-Z, et prépare la séance de mesure -LPPersonsLog=2. » Protocole de **20 à 30 minutes**, pour l'utilisateur, au ton et au format de `etat\BOSS\COMMUN-21-TESTS.md` (pas à pas, résultat attendu, motif de journal). Il reprend `FIX1-F7-PRE.md` (§ 3.1 F7b et F8b, § 3.3, § 3.4 « Ordre conseillé », § 6 questions 2 et 3). Rédigé sans copie UE, sans MCP, sans lancer le jeu. Aucun contenu de jeu : tenue et actions décrites de façon neutre (doc 27).
|
||||
|
||||
**Ce que la séance doit trancher** (`FIX1-F7-PRE.md` § 4, « Incertain »)
|
||||
- **F8b** : le décalage du maillage au lever (meshZ −80,4 / −82,8 / −85,2 au lieu de −90) vient-il des **talons** (formule estimée −90 + 12 × HeelHeight, `FIX1-F7-PRE.md:119`, `:170`) ou de la **place** (animation de meuble) ? Question 4 de `FIX1-F7-PRE.md` § 6 : le personnage flotte-t-il réellement à l'écran ?
|
||||
- **F7b** : l'animation « look » reste-t-elle **jouée** après la fin de l'action (`anim=single:…look`), ou seule la variable `currentAnimation` est-elle périmée ? Effet visible ? (`FIX1-F7-PRE.md:158`, `:203`).
|
||||
|
||||
## 1. Build à utiliser
|
||||
|
||||
| Élément | Valeur |
|
||||
|---|---|
|
||||
| Build visée | **COMMUN-22** : `D:\Game\LifePlay_Build_5.8_Development_COM22\Windows\LifePlay.exe` ; exe `e2ba7dec63d479974394e2cffd1efc19` (F8a + trace M-Z enrichie), paquet du 2026-10-20 20:24 (`etat\BOSS\COMMUN-22\COMMUN-22-BUILD.md`) |
|
||||
| Trace M-Z enrichie | fiche `FIX1-MZ-IMPL.md` (LPDirectControlSubsystem.cpp 687c63d8, exe e2ba7dec) ; format exact : `M-Z : <acteur> maillage relatif Z <avant> -> <après> (gabarit <classe>), debout sans meuble ; HeelHeight=<%.3f|?> ; currentAnimation=<nom|-|?> ; -90+12*HeelHeight=<%.2f|?>` ; `?` = variable introuvable, `-` = animation vide ; comparer `<avant>` à `-90+12*HeelHeight=` |
|
||||
| Repli | la build **COM21** actuelle, `D:\Game\LifePlay_Build_5.8_Development_COM21\Windows\LifePlay.exe`, **sans** la trace enrichie : la séance reste utile, car les lignes `STATE … meshZ= … currentAnimation=` suffisent (§ 4) ; seule la ligne `M-Z :` reste sans talons ni animation |
|
||||
| Copie UE | non requise : la séance se joue sur une build empaquetée, sans éditeur |
|
||||
|
||||
**Ligne de commande prête** (PowerShell, build COMMUN-22) :
|
||||
|
||||
```powershell
|
||||
& "D:\Game\LifePlay_Build_5.8_Development_COM22\Windows\LifePlay.exe" -LPPersonsLog=2
|
||||
```
|
||||
|
||||
Sens exact de `-LPPersonsLog=2` (lu dans `Source\LifePlay\LPDebugSubsystem.cpp:638-650`) :
|
||||
- `=2` = un relevé **toutes les 2 secondes** au journal (valeur par défaut sans nombre : 5 s ; plancher : 1 s) ;
|
||||
- au lancement, une ligne `LPDebug persons : releve toutes les 2 s` (catégorie `LogLifePlay`, niveau `Display`) ; absente = l'argument n'a pas été pris, arrêter et le dire ;
|
||||
- le relevé périodique n'écrit **pas** de fichier (`WritePersonsDump(…, false)`, `:646`) : tout est au journal `<build>\Windows\LifePlay\Saved\Logs\LifePlay.log` ;
|
||||
- chaque relevé contient, par personnage, une ligne `LPDebug persons : STATE <acteur> coll=… grav=… moveTick=… meshZ=… anim=… currentAnimation=…` (`:414`, préfixe `LPDebug persons : ` ajouté par `:580`) : `meshZ` = Z **relatif** du maillage ; `anim` = `single:<clip>` si un clip isolé est joué, `bp:<AnimBP>` si l'AnimBP pilote, `-` sinon (`:404-413`) ; `currentAnimation` = variable Blueprint du personnage, `-` quand elle est vide (`FIX1-F7-PRE.md:160`).
|
||||
- Au journal, **l'heure** de chaque ligne sert à retrouver l'instant noté à la main (§ 3 et § 4).
|
||||
|
||||
Alternative ponctuelle, sans relancer : console `LifePlay.PersonsDump` (un seul relevé, **avec** un fichier `PersonsDump_<date>_<heure>.txt`, `:631-634`, `:584-587`).
|
||||
|
||||
## 2. Préparation (3 minutes)
|
||||
|
||||
1. Fermer le jeu s'il est ouvert. Ouvrir une montre ou une horloge visible : **chaque geste est noté avec l'heure** (heure:minute:seconde, celle du poste).
|
||||
2. Lancer la ligne de commande du § 1. Charger une partie existante (ou nouvelle partie) avec un personnage joueur, dans une rue ou une pièce dégagée, **sans scène en cours**.
|
||||
3. Vérifier, une fois le jeu chargé, la présence de `releve toutes les 2 s` :
|
||||
```powershell
|
||||
Select-String -Path "D:\Game\LifePlay_Build_5.8_Development_COM22\Windows\LifePlay\Saved\Logs\LifePlay.log" -Pattern 'LPDebug persons : releve toutes les'
|
||||
```
|
||||
Attendu : 1 ligne.
|
||||
4. Préparer le **cahier** (papier ou fichier, hors jeu) : une ligne par geste, colonnes `heure | geste | ce qu'on voit à l'écran`.
|
||||
5. Prévoir : une tenue **avec chaussures à talons** pour le joueur, la même sans talons (ou des chaussures plates), une **chaise ou un canapé** utilisable, et un **meuble de boutique** avec l'action « regarder » (celui de COMMUN-8 était une vitrine).
|
||||
|
||||
## 3. Cas
|
||||
|
||||
Format comme `COMMUN-21-TESTS.md` § 3 : Verdict, Découvreur, Heure restent vides, le BILAN les remplit. Contrôle automatique = motif cherché par Big Boss dans le journal (§ 4).
|
||||
|
||||
### 3.1 F8b : talons contre place (≈ 12 minutes)
|
||||
|
||||
| Cas | Lot | Objet | Action de l'utilisateur | Attendu | Contrôle automatique du journal | Verdict | Découvreur | Heure |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| FIX1-MES.1 | FIX1 | F8b, point de départ | Joueur **en chaussures plates ou sans talons**, debout, immobile 10 s. Noter l'heure. | Personnage debout normalement, pieds au sol. | lignes `STATE PlayerCharacter` sur ces 10 s (5 relevés) : `meshZ=-90.0` | | | |
|
||||
| FIX1-MES.2 | FIX1 | F8b, sans talons | Toujours sans talons : **s'asseoir** sur la chaise (noter l'heure), rester 10 s, **se lever** (noter l'heure), rester debout et immobile 10 s. Regarder les pieds avant l'assise et après le lever. | Après le lever : pieds posés sur le sol, ni suspendus ni enfoncés. | juste après le lever : `meshZ=-90.0` dans les relevés de la fenêtre ; `M-Z :` : **0** ligne sur cette fenêtre | | | |
|
||||
| FIX1-MES.3 | FIX1 | F8b, changement de tenue | **Changer de tenue** : mettre les **chaussures à talons** (noter l'heure). Rester debout et immobile 10 s. Comparer à l'écran avec MES.1. | Le personnage est un peu **rehaussé** par les talons : noter ce qu'on voit (« pieds au sol », « flotte », « trop haut »). | relevés debout : `meshZ=` **différent de −90** ; valeur attendue −90 + 12 × HeelHeight (par exemple −85,2 / −82,8 / −80,4 pour HeelHeight 0,4 / 0,6 / 0,8) | | | |
|
||||
| FIX1-MES.4 | FIX1 | F8b, talons et assise | Avec les talons : **s'asseoir** (heure), rester 10 s, **se lever** (heure), rester debout immobile **10 s sans bouger**. Regarder les pieds : le personnage **flotte-t-il** au-dessus du sol après le lever ? Noter aussi si cela dure plus de 1 à 2 s. | Réponse visuelle sans ambiguïté : « flotte » ou « ne flotte pas ». Si M-Z a fonctionné, le flottement dure au plus environ 1 s (2 balayages de 0,5 s, `LPDirectControlSubsystem.cpp:1211-1213`). | une ligne `M-Z : PlayerCharacter maillage relatif Z <avant> -> <après> (gabarit …), debout sans meuble` dans la minute qui suit le lever, ou son absence ; `<avant>` à comparer à la formule des talons ; **COMMUN-22 : hauteur de talons et animation à lire sur la même ligne** (format : à compléter, `FIX1-MZ-IMPL.md`) | | | |
|
||||
| FIX1-MES.5 | FIX1 | F8b, retour sans talons | Reprendre les chaussures plates ou **retirer** les talons (changer de tenue). Répéter **s'asseoir puis se lever** (heures notées). | Sans talons, au lever : retour à −90,0 ; **aucune** ligne `M-Z :` si MES.2 n'en avait pas. Si une ligne `M-Z :` apparaît **sans talons**, la place est en cause (pas les talons). | relevés après le lever : `meshZ=-90.0` ; nombre de lignes `M-Z :` sur la fenêtre : noter | | | |
|
||||
| FIX1-MES.6 | FIX1 | F8b, personnages non joueurs (facultatif) | Si un personnage non joueur est visible et utilise un siège : l'observer s'asseoir puis se lever (heure), noter s'il flotte. Passer si aucun n'est visible. | Même lecture que MES.4 ; noter « sans objet : aucun personnage non joueur à portée » sinon. | lignes `STATE <acteur>` du personnage observé (nom lu dans le journal) ; lignes `M-Z :` visant ce nom (2 sur 18 visaient des personnages non joueurs, `FIX1-F7-PRE.md:116`) | | | |
|
||||
|
||||
### 3.2 F7b : animation « look » restée active (≈ 8 minutes)
|
||||
|
||||
| Cas | Lot | Objet | Action de l'utilisateur | Attendu | Contrôle automatique du journal | Verdict | Découvreur | Heure |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| FIX1-MES.7 | FIX1 | F7b, référence | Joueur debout, **hors de tout meuble**, immobile 10 s, avant l'action. Noter l'heure. | Aucune animation de meuble. | `STATE PlayerCharacter … currentAnimation=-` | | | |
|
||||
| FIX1-MES.8 | FIX1 | F7b, action « regarder » | Devant le meuble de boutique, lancer l'action « **regarder** ». Noter l'heure du **début** puis celle de la **fin** de l'action (quand le personnage reprend la main). Laisser l'animation aller à son terme. | Le personnage joue l'animation de regard, puis l'action se termine. | pendant l'action : `currentAnimation=fnt_…-look` (nom d'animation finissant par `look`) avec `anim=single:…` ; noter la première heure où il apparaît | | | |
|
||||
| FIX1-MES.9 | FIX1 | F7b, après la fin | **Dès la fin** de l'action, ne rien toucher 20 s : le personnage est debout, dans la même pièce. Noter à l'écran : posture **penchée** ou normale, tête tournée ou non. | Posture normale. | **Cas à retenir** : `currentAnimation=fnt_…-look` encore présent **après** l'heure de fin ; `anim=single:…look` encore présent (le clip joue encore) ou `anim=bp:…` avec la variable seule périmée | | | |
|
||||
| FIX1-MES.10 | FIX1 | F7b, changement de pièce | **Sortir** du lieu (rue, autre pièce ou autre étage), marcher 10 s, noter l'heure et la posture. Puis revenir et marcher encore 10 s. | Posture normale, marche normale. | après le changement de pièce : `currentAnimation=` (valeur) et `anim=` ; COMMUN-8 montrait `fnt_new038-f-0-look` conservé dans la rue puis au café (`STG-COMMUN8-DIAG.md:22`) | | | |
|
||||
| FIX1-MES.11 | FIX1 | F7b, répétition | Refaire MES.8 à MES.10 **une fois** sur un autre meuble offrant « regarder » (ou le même). | Même résultat qu'à MES.9 : si `currentAnimation` reste en `look` deux fois, le défaut est reproductible. | idem MES.9 | | | |
|
||||
|
||||
Arrêt anticipé : si le personnage reste **bloqué** (animation qui ne se termine pas, plus de contrôle), noter l'heure, ne pas relancer d'action, passer au § 5.
|
||||
|
||||
## 4. Ce que Big Boss lira ensuite au journal
|
||||
|
||||
Journal : `<build>\Windows\LifePlay\Saved\Logs\LifePlay.log` du lancement jugé (le jeu en garde un exemplaire horodaté à chaque lancement). Lecture par **Grep sur fichier nommé** (un Grep de dossier saute les `.txt` ignorés par git, `FIX1-F7-PRE.md` § 2). Les heures du cahier se retrouvent sur les horodatages des lignes.
|
||||
|
||||
Motifs exacts (code lu) :
|
||||
|
||||
| Motif | Source | Lecture |
|
||||
|---|---|---|
|
||||
| `LPDebug persons : releve toutes les 2 s` | `LPDebugSubsystem.cpp:649` | 1 ligne : trace active |
|
||||
| `LPDebug persons : STATE PlayerCharacter ` | `LPDebugSubsystem.cpp:414`, `:580` | une ligne toutes les 2 s environ ; champs `meshZ=`, `anim=`, `currentAnimation=` |
|
||||
| `M-Z : <acteur> maillage relatif Z <avant> -> <après> (gabarit <classe>), debout sans meuble ; HeelHeight=<%.3f|?> ; currentAnimation=<nom|-|?> ; -90+12*HeelHeight=<%.2f|?>` | `LPDirectControlSubsystem.cpp` (FIX1-MZ) | une correction ; si `<avant>` = `-90+12*HeelHeight`, les talons expliquent l'écart ; sinon (ex. −88,0), autre cause |
|
||||
| `Fatal\|Unhandled\|Critical error\|Assertion failed` | relevé commun | 0 attendu |
|
||||
|
||||
Commandes prêtes (adapter le chemin à la build de la séance) :
|
||||
|
||||
```powershell
|
||||
$J = "D:\Game\LifePlay_Build_5.8_Development_COM22\Windows\LifePlay\Saved\Logs\LifePlay.log"
|
||||
Select-String -Path $J -Pattern 'LPDebug persons : STATE PlayerCharacter' | Select-Object LineNumber, Line
|
||||
Select-String -Path $J -Pattern 'M-Z :'
|
||||
Select-String -Path $J -Pattern 'currentAnimation=fnt_'
|
||||
```
|
||||
|
||||
**Seuils et lectures de décision** (estimés ; la formule vient du dump 5.5, `FIX1-F7-PRE.md:117`) :
|
||||
|
||||
| Constat au journal | Lecture | Suite |
|
||||
|---|---|---|
|
||||
| debout sans talons : `meshZ=-90.0` partout, **et** debout avec talons : `meshZ=-90+12×HeelHeight` (−85,2 / −82,8 / −80,4) | le décalage vient des **talons** : forcer −90 n'est pas un correctif ; M-Z retire un décalage voulu | F8b : ne pas corriger en Blueprint ; M-Z doit lire la hauteur de talons (décision de l'utilisateur, `FIX1-F7-PRE.md` § 6 question 4) |
|
||||
| `meshZ` ≠ −90 **sans talons** après un lever, ou lignes `M-Z :` sans talons | la **place** (animation de meuble) est en cause | F8b : correctif Blueprint à étudier en build 2 |
|
||||
| `meshZ=-88.0` (7 cas sur 18 aux journaux antérieurs) | hors grille des talons (2,0 / 12 ≈ 0,167) : chemin d'écriture inconnu | noter heure et circonstances, item ouvert |
|
||||
| `M-Z : … Z <avant>` de la forme −90 + 12 × H avec talons (COMMUN-22) | confirme la cause « talons » par la ligne même | idem première ligne |
|
||||
| `currentAnimation=fnt_…-look` **après l'heure de fin** de l'action (MES.9, MES.10) **et** `anim=single:…look` | le clip **joue encore** : effet visible probable | F7b : correctif d'un nœud dans Person envisageable, build 1 seulement avant la porte du 2026-10-23 au soir (`FIX1-F7-PRE.md:183`) |
|
||||
| `currentAnimation=fnt_…-look` après la fin, mais `anim=bp:…` | seule la **variable** est périmée, sans effet à l'écran | F7b : « ne pas corriger » |
|
||||
| `currentAnimation=-` après la fin | défaut non reproduit | F7b : pas de correctif ; noter la date |
|
||||
|
||||
Décompte de contrôle à recopier au BILAN : nombre de lignes `STATE PlayerCharacter` (≈ une toutes les 2 s : ≈ 600 pour 20 minutes), nombre de lignes `M-Z :`, valeurs de `meshZ=` distinctes.
|
||||
|
||||
## 5. Durée cible et arrêt
|
||||
|
||||
- **Durée cible : 20 à 30 minutes** : préparation 3 min, F8b ≈ 12 min, F7b ≈ 8 min, relève du cahier ≈ 3 min.
|
||||
- **Arrêt** : fermer le jeu **normalement** (menu), pour que le journal se termine ; ne pas supprimer ni déplacer `Saved\Logs\LifePlay.log`. Un journal qui n'est pas celui de la séance est à ne pas utiliser : le fichier le plus récent porte l'heure de la séance.
|
||||
- **Arrêt avant le terme** : blocage, plantage, `Fatal` au journal, ou plus de 30 minutes : arrêter, noter l'heure et le dernier cas fait, **ne pas** relancer ; la séance partielle reste exploitable cas par cas.
|
||||
- À rendre à Big Boss : le cahier (heures, observations), le journal de la séance (fichier nommé ci-dessus), et la mention de la build utilisée (COMMUN-22 avec trace enrichie, ou COM21).
|
||||
|
||||
## Fichiers à commiter
|
||||
|
||||
A `Docs/Migration/etat/REL/FIX1/FIX1-MES.md` (dépôt jeu, branche `ue5.8`), par le gardien sur ticket. Aucun autre fichier écrit. Pas de CHG réservé à ce livrable (protocole d'essai, aucune modification du jeu) ; pas de ligne d'index à ajouter.
|
||||
|
||||
## Points à compléter ou à confirmer
|
||||
|
||||
1. **Complété par Big Boss (2026-10-20)** : build COMMUN-22 et format de la ligne `M-Z :` enrichie (voir § 1 et § 3).
|
||||
2. **Non vérifié** : nom exact des états `HeelHeight` visibles au journal COM21 (la COM21 n'a pas la trace enrichie : les talons ne se lisent alors que par `meshZ=`).
|
||||
3. **Estimé** : formule −90 + 12 × HeelHeight (dump 5.5, pas relu en 5.8) ; cadence « environ 600 relevés pour 20 minutes ».
|
||||
4. **Non mesuré** : aucune exécution de la séance ; aucun journal produit.
|
||||
204
Docs/Migration/etat/REL/FIX1/FIX1-MZ-IMPL.md
Normal file
204
Docs/Migration/etat/REL/FIX1/FIX1-MZ-IMPL.md
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
Fiche FIX1-MZ — Niveau N2 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-impl — Skills sk-protocol, ue-cpp-build
|
||||
# FIX1-MZ-IMPL : instrumentation de la ligne de journal M-Z (HeelHeight, currentAnimation, −90 + 12 × HeelHeight) (2026-10-20)
|
||||
|
||||
Décision citée par la fiche : l'ordre de l'utilisateur, recopié mot pour mot dans la fiche : « Oui : F7a, F7c et F8b en build 2 ; en build 1, ajoute la hauteur de talons et l'animation à la trace M-Z, et prépare la séance de mesure -LPPersonsLog=2. » La fiche ne donne ni la session ni l'heure (`sk-protocol` § 2) : je la traite comme une consigne de fiche, sans en tirer d'autre décision. Ma part se limite à l'instrumentation C++ ; la séance de mesure n'est pas dans cette fiche (voir § 4).
|
||||
Hors gabarit : les deux compilations, `CopieEtat`, `PubCheck` et la preuve de présence de la chaîne dans les binaires sont rendus dans `## Constats` (notes TRACE).
|
||||
Écart de skills : la fiche cite `sk-protocol, ue-cpp-build` ; `lp-build` et `lp-ue-compat` sont aussi chargés dans mon contexte (utilisés pour les commandes de build et la liste des lignes connues).
|
||||
Niveaux de preuve : **établi** (fichier:ligne ou sortie de commande), **estimé** (raisonnement donné), **incertain** (essai nommé).
|
||||
|
||||
## 1. Fichiers modifiés
|
||||
|
||||
Un seul fichier de source : `D:\Game\LifePlay-master 5.8\Source\LifePlay\LPDirectControlSubsystem.cpp`. Comportement inchangé (établi par lecture du diff : la correction `Body->SetRelativeLocation(…)` `:1255` et `MeshZScans.Remove(Person)` `:1256` sont intactes ; seules des lectures et le texte du `UE_LOG` ont changé).
|
||||
|
||||
| Mesure | Valeur | Commande |
|
||||
|---|---|---|
|
||||
| MD5 avant (exigé `5f9d7e00`) | `5f9d7e00402688822687e7eb32979bd1`, conforme ; identique à l'instantané | `certutil -hashfile Source/LifePlay/LPDirectControlSubsystem.cpp MD5` avant la première édition ; colonne MD5 de `D:\Game\LifePlay_Backup_5.5\FIX1-MZ\manifest.csv` |
|
||||
| MD5 après | `687c63d85395888b8a334cb537c16a53` (inchangé après les deux builds) | `certutil -hashfile …` après les 2 éditions, puis après les 2 builds |
|
||||
| Taille avant, après | 62 510 o, 64 858 o | manifeste de l'instantané ; `ls -la` |
|
||||
| Fins de ligne | `i/crlf w/crlf attr/-text` ; 1818 CR = 1818 LF (aucune fin de ligne mixte) | `git ls-files --eol Source/LifePlay/LPDirectControlSubsystem.cpp` ; `tr -cd '\r' < … \| wc -c` et `tr -cd '\n' < … \| wc -c` |
|
||||
| Bilan du diff | `1 file changed, 49 insertions(+), 2 deletions(-)` | `git diff --stat -- Source/LifePlay/LPDirectControlSubsystem.cpp` |
|
||||
| Autres fichiers de `Source` modifiés | `Source/LifePlay/LPCameraModeSubsystem.cpp` (déjà modifié avant ma fiche : F8a, `FIX1-F8a-IMPL.md`) ; aucun autre | `git status --short -- Source Tools` |
|
||||
|
||||
Les deux éditions (outil Edit, sans script) ; le premier essai du second `Edit` a échoué (indentation à 5 tabulations au lieu de 4, aucune écriture), repris à 4 tabulations.
|
||||
|
||||
```diff
|
||||
@@ -151,6 +151,47 @@ namespace
|
||||
return Prop ? Cast<AActor>(Prop->GetObjectPropertyValue_InContainer(Object)) : nullptr;
|
||||
}
|
||||
|
||||
+ // FIX1-MZ (instrumentation de la ligne M-Z, lecture seule) : formule de Person::updateHeelHeight, Z relatif du maillage =
|
||||
+ // -90 + 12 x HeelHeight (L6f_dump_Person.txt:19818-19827, A='-90.000000', B='12.000000').
|
||||
+ constexpr double MZHeelBaseZ = -90.0;
|
||||
+ constexpr double MZHeelFactor = 12.0;
|
||||
+
|
||||
+ // Variable Blueprint numerique lue par reflexion (HeelHeight est un double : Conv_StringToDouble, L6f_dump_Person.txt:19774-19781).
|
||||
+ // Faux si la variable est introuvable ou non numerique : aucun journal, l'appelant ecrit "?".
|
||||
+ bool MZReadNumber(const UObject* Object, const TCHAR* Name, double& OutValue)
|
||||
+ {
|
||||
+ const FNumericProperty* Prop = Object ? CastField<FNumericProperty>(Object->GetClass()->FindPropertyByName(Name)) : nullptr;
|
||||
+ if (!Prop)
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
+ const void* Data = Prop->ContainerPtrToValuePtr<void>(Object);
|
||||
+ if (Prop->IsFloatingPoint())
|
||||
+ {
|
||||
+ OutValue = Prop->GetFloatingPointPropertyValue(Data);
|
||||
+ return true;
|
||||
+ }
|
||||
+ if (Prop->IsInteger())
|
||||
+ {
|
||||
+ OutValue = static_cast<double>(Prop->GetSignedIntPropertyValue(Data));
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // Nom de l'objet d'une variable Blueprint objet (currentAnimation) : "?" si la variable est introuvable, "-" si elle est vide
|
||||
+ // (meme convention de vide que ReadObjectName de LPDebugSubsystem.cpp).
|
||||
+ FString MZReadObjectName(const UObject* Object, const TCHAR* Name)
|
||||
+ {
|
||||
+ const FObjectPropertyBase* Prop = Object ? CastField<FObjectPropertyBase>(Object->GetClass()->FindPropertyByName(Name)) : nullptr;
|
||||
+ if (!Prop)
|
||||
+ {
|
||||
+ return TEXT("?");
|
||||
+ }
|
||||
+ const UObject* Value = Prop->GetObjectPropertyValue_InContainer(Object);
|
||||
+ return Value ? Value->GetName() : FString(TEXT("-"));
|
||||
+ }
|
||||
+
|
||||
bool KeyDown(const APlayerController* PC, const FKey& Key)
|
||||
@@ -1213,8 +1254,14 @@ void ULPDirectControlSubsystem::FitPersonBounds(float DeltaTime)
|
||||
Body->SetRelativeLocation(FVector(Relative.X, Relative.Y, TemplateZ));
|
||||
MeshZScans.Remove(Person);
|
||||
- UE_LOG(LogLifePlay, Display, TEXT("M-Z : %s maillage relatif Z %.1f -> %.1f (gabarit %s), debout sans meuble"),
|
||||
- *Person->GetName(), Relative.Z, TemplateZ, *Person->GetClass()->GetName());
|
||||
+ // FIX1-MZ : instrumentation seule (F8b), lue par reflexion apres la correction, sans effet sur elle. "?" = variable introuvable.
|
||||
+ double HeelHeight = 0.0;
|
||||
+ const bool bHeelRead = MZReadNumber(Person, TEXT("HeelHeight"), HeelHeight);
|
||||
+ const FString HeelText = bHeelRead ? FString::Printf(TEXT("%.3f"), HeelHeight) : FString(TEXT("?"));
|
||||
+ const FString HeelZText = bHeelRead ? FString::Printf(TEXT("%.2f"), MZHeelBaseZ + MZHeelFactor * HeelHeight) : FString(TEXT("?"));
|
||||
+ UE_LOG(LogLifePlay, Display, TEXT("M-Z : %s maillage relatif Z %.1f -> %.1f (gabarit %s), debout sans meuble ; HeelHeight=%s ; currentAnimation=%s ; -90+12*HeelHeight=%s"),
|
||||
+ *Person->GetName(), Relative.Z, TemplateZ, *Person->GetClass()->GetName(),
|
||||
+ *HeelText, *MZReadObjectName(Person, TEXT("currentAnimation")), *HeelZText);
|
||||
}
|
||||
}
|
||||
else
|
||||
```
|
||||
|
||||
**Texte exact de la nouvelle ligne de journal** (catégorie `LogLifePlay`, niveau `Display`, une ligne par déclenchement de M-Z, émise après la correction) :
|
||||
|
||||
```
|
||||
M-Z : <acteur> maillage relatif Z <Z avant> -> <Z gabarit> (gabarit <classe>), debout sans meuble ; HeelHeight=<h> ; currentAnimation=<nom> ; -90+12*HeelHeight=<z>
|
||||
```
|
||||
|
||||
- `<h>` : `%.3f`, ou `?` si `HeelHeight` est introuvable (ou ni flottant ni entier). `<z>` : `%.2f`, de la même formule que `Person::updateHeelHeight` (`-90 + 12 × h`), ou `?` si `<h>` vaut `?`.
|
||||
- `<nom>` : nom de l'objet de `currentAnimation`, `-` si la variable existe mais est vide, `?` si elle est introuvable (ou n'est pas une propriété objet).
|
||||
- Forme attendue, **non observée en jeu** : `M-Z : <acteur> maillage relatif Z -80.4 -> -90.0 (gabarit Person_C), debout sans meuble ; HeelHeight=0.800 ; currentAnimation=<nom> ; -90+12*HeelHeight=-80.40`. Lecture : `<Z avant>` égal à `<z>` (à 0,05 près) = décalage de talons ; différent = autre cause.
|
||||
- **Motif à chercher** : chaîne fixe `HeelHeight=` sur les lignes `M-Z :`, ou l'expression régulière `M-Z : .* maillage relatif Z (-?[0-9.]+) -> (-?[0-9.]+) \(gabarit (\S+)\), debout sans meuble ; HeelHeight=(\S+) ; currentAnimation=(\S+) ; -90\+12\*HeelHeight=(\S+)`. Le début de ligne (`M-Z : … debout sans meuble`) est inchangé : une recherche de `M-Z :` retrouve les anciennes et les nouvelles lignes. Aucun consommateur de cette ligne dans `Tools` (Grep `M-Z` sur `D:\Game\LifePlay-master 5.8\Tools` : aucun résultat).
|
||||
|
||||
APIs moteur utilisées, lues dans UE 5.8.3 (`Build.version` : 5.8.3) : `UStruct::FindPropertyByName(FName)` `Class.h:663` ; `FNumericProperty::IsFloatingPoint` `UnrealType.h:1819`, `IsInteger` `:1822`, `GetSignedIntPropertyValue(void const*)` `:1886`, `GetFloatingPointPropertyValue(void const*)` `:1902` (pas de variante `_InContainer` pour les flottants, d'où `ContainerPtrToValuePtr`) ; `FProperty::ContainerPtrToValuePtr<ValueType>(UObject const*, int32)` `:811` ; `FObjectPropertyBase::GetObjectPropertyValue_InContainer(const void*, int32)` `:2896`. Les mêmes signatures existent en 5.5.4 (`UnrealType.h:1720, 1723, 1787, 1803`, vérifiées par Grep).
|
||||
|
||||
## 2. Écarts à la SPEC
|
||||
|
||||
La fiche tient lieu de SPEC. Écarts et choix :
|
||||
1. **Référence inexacte de la fiche** : `LPDebugSubsystem.cpp:631-643` ne lit ni `currentAnimation` ni `meshZ` (ce sont l'enregistrement de `PersonsDumpCommand` et le ticker `-LPPersonsLog`). La lecture par réflexion est à `LPDebugSubsystem.cpp:316-321` (`ReadObjectName`), `:333` (`SeatPlace`), `:414-418` (ligne `STATE … meshZ= … currentAnimation=`). Modèle suivi : `ReadObjectName`.
|
||||
2. **`?` et `-` distincts** : la fiche demande `?` si une variable est introuvable. Pour `currentAnimation`, un objet **vide** s'écrit `-` (convention de `ReadObjectName`, `LPDebugSubsystem.cpp:320`), pour ne pas confondre « variable absente » (`?`) et « aucune animation » (`-`).
|
||||
3. **Constantes −90 et 12 littérales** (nommées `MZHeelBaseZ`, `MZHeelFactor`), comme dans la formule de l'ordre de l'utilisateur et du Blueprint (`L6f_dump_Person.txt:19820, 19826`), et non `TemplateZ + 12 × HeelHeight` ; `TemplateZ` figure déjà dans la ligne (`-> %.1f`). Si un jour le gabarit n'est plus à −90, les deux valeurs divergent, ce qui se verra.
|
||||
4. **Types admis pour `HeelHeight`** : flottant (cas attendu : `double`, `Conv_StringToDouble`, `L6f_dump_Person.txt:19774-19781`) ou entier ; tout autre type donne `?`. Le dump est celui de la 5.5 (L6f) : le type en 5.8 n'est pas relu dans le `.uasset` 5.8.
|
||||
5. **Noms préfixés `MZ`** dans le `namespace` anonyme (unity build : un nom identique dans un autre `.cpp` du module donnerait C2374, `lp-build` § 8) ; Grep `\bMZ[A-Z][A-Za-z]*` sur `Source` avant édition : aucun résultat.
|
||||
6. **Instantané non refait** : `D:\Game\LifePlay_Backup_5.5\FIX1-MZ\` existait déjà (voir § 3).
|
||||
7. **`CopieEtat.ps1 -Lot FIX1` rend le code 1** (alerte GIT) : voir `## Constats`. La commande est celle de la fiche, sans `-Assets`.
|
||||
|
||||
## 3. Instantané
|
||||
|
||||
- Lot `FIX1-MZ`, dossier `D:\Game\LifePlay_Backup_5.5\FIX1-MZ\` : créé avant ma fiche (par l'ordonnateur ; date du manifeste `2026-10-20T20:04:15`), contient `Source\LifePlay\LPDirectControlSubsystem.cpp` et `manifest.csv`.
|
||||
- Manifeste (lu) : `"Source/LifePlay/LPDirectControlSubsystem.cpp","True","62510","5F9D7E00402688822687E7EB32979BD1","2026-10-20T20:04:15"`.
|
||||
- Vérifié par `certutil -hashfile D:\Game\LifePlay_Backup_5.5\FIX1-MZ\Source\LifePlay\LPDirectControlSubsystem.cpp MD5` = `5f9d7e00402688822687e7eb32979bd1` : la copie d'instantané est l'état de départ exact.
|
||||
- Retour arrière (proposé, non lancé) : `Tools\Restore.ps1 -Lot FIX1-MZ`, ou recopie de ce fichier d'instantané.
|
||||
|
||||
## 4. Ce qui n'a pas été fait
|
||||
|
||||
- **Aucune mesure en jeu, aucune séance** : la ligne n'a jamais été émise par un exécutable lancé. La préparation de la séance `-LPPersonsLog=2` n'est pas dans cette fiche (périmètre : instrumentation C++ seule) ; elle revient à l'ordonnateur.
|
||||
- **Aucun paquet** (`BuildDebug.ps1`, cuisson) : seuls `LifePlayEditor` et `LifePlay` Development ont été compilés dans `Binaries\Win64` de la copie. Une séance sur un build empaqueté demande une fiche de paquet ; le build COM21 existant n'a pas ce code.
|
||||
- Aucune modification de comportement (M-Z force toujours le Z du gabarit), aucun correctif Blueprint (F8b reste en build 2), aucun fichier hors `LPDirectControlSubsystem.cpp`.
|
||||
- Pas de test de la branche `?` : elle n'a pas été déclenchée (aucune exécution).
|
||||
- Aucune commande git qui écrit.
|
||||
|
||||
## 5. Points à confirmer en VAL
|
||||
|
||||
1. La chaîne `HeelHeight=%s ; currentAnimation=%s ; -90+12*HeelHeight=%s` est dans `Binaries\Win64\LifePlay.exe` et `UnrealEditor-LifePlay.dll` (rejouer les deux recherches de `## Constats`, ou `LogStats` sur un journal d'une séance).
|
||||
2. Dans un journal de séance, chaque ligne `M-Z :` porte les trois champs ; relever le nombre de lignes avec `HeelHeight=?` (attendu 0 si la variable existe sous ce nom dans `Person_C` 5.8) et avec `currentAnimation=?` (attendu 0).
|
||||
3. Pour chaque ligne : comparer `<Z avant>` (valeur avant `->`) et `-90+12*HeelHeight=` ; égalité à 0,05 près = décalage de talons ; écart (cas à −88,0 de `FIX1-F7-PRE.md`, 7 sur 18) = autre cause à instruire.
|
||||
4. Contrôle de non-régression : le Z gabarit après correction (`-> -90.0`) et le moment du déclenchement (2 balayages) sont ceux des journaux précédents (même nombre de lignes `M-Z :` par séance comparable).
|
||||
5. Type réel de `HeelHeight` en 5.8 : si une ligne porte `HeelHeight=?` alors que le personnage porte des talons, la variable n'est pas flottante ou entière sous ce nom (relire `Person.uasset` 5.8 par `LPDumpFunction`/MCP).
|
||||
6. Le build `LifePlayEditor` compte exactement **20** lignes UBT `HyperAIStudio` et le build `LifePlay` **0** (`lp-build` § 7) : retrouvés ici (20 et 0).
|
||||
|
||||
## 6. Fichiers à commiter
|
||||
|
||||
Dépôt du jeu (`D:\Game\LifePlay-master 5.8`, branche `ue5.8`) :
|
||||
- `M Source/LifePlay/LPDirectControlSubsystem.cpp`
|
||||
- `A Docs/Migration/etat/REL/FIX1/FIX1-MZ-IMPL.md`
|
||||
|
||||
Ne pas inclure `Source/LifePlay/LPCameraModeSubsystem.cpp` (autre lot, F8a). Les résumés de build `FIX1_Build_20261020-200728.txt` et `FIX1_Build_20261020-200822.txt` (même dossier) n'apparaissent pas dans `git status --short -- Docs/Migration/etat/REL/FIX1` (les `.txt` de ce dossier sont ignorés par git) : à ne pas commiter. Les journaux bruts `Saved\Logs\portage\FIX1_Build_*.log` restent hors dépôt. Aucun fichier de l'addon ni des Modules.
|
||||
|
||||
Tours : 25 / 40 (budget N2 par défaut : la fiche ne donne pas de rubrique 9 ; `Tools/FicheStats.py` fait foi)
|
||||
|
||||
## Constats
|
||||
|
||||
### Compilation (hors gabarit, deux relevés)
|
||||
|
||||
Trace : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\FIX1\FIX1_Build_20261020-200728.txt` — Fiche FIX1-MZ — 2026-10-20 20:07
|
||||
```
|
||||
Commande : cd 'D:\Game\LifePlay-master 5.8'; pwsh -NoProfile -File Tools/Build.ps1 -Lot FIX1 -EtatDir "D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\FIX1" (LifePlayEditor Win64 Development, après Tools\CopieEtat.ps1 -Lot FIX1)
|
||||
Environnement: copie 5.8, branche ue5.8, HEAD ad3c9c6 ; UE 5.8.3 ; éditeur fermé (UeState : processus=0) ; une seule compilation à la fois ; machine calme (cpu=1 % au CopieEtat)
|
||||
Attendu : code 0, 0 erreur, 0 avertissement du compilateur ; 20 lignes UBT HyperAIStudio (connues)
|
||||
Obtenu : code=0 duree=43s erreurs=0 avertissements=0 autres=20 unites=2 ; unités LPDirectControlSubsystem.cpp et Module.LifePlay.cpp ; DLL liée UnrealEditor-LifePlay.dll ; journal Saved\Logs\portage\FIX1_Build_20261020-200728.log
|
||||
Lecture : « Makefile : » vide dans le résumé (statut non relevé par Build.ps1) ; module modifié bien recompilé (unité + DLL) ; chaîne « Using Visual Studio 14.50.35739 toolchain (…\MSVC\14.50.35717) and Windows 10.0.22621.0 SDK » = MSVC épinglé de la 5.8
|
||||
```
|
||||
|
||||
Trace : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\FIX1\FIX1_Build_20261020-200822.txt` — Fiche FIX1-MZ — 2026-10-20 20:08
|
||||
```
|
||||
Commande : cd 'D:\Game\LifePlay-master 5.8'; pwsh -NoProfile -File Tools/Build.ps1 -Lot FIX1 -Target LifePlay -Config Development -ExtraArgs '-NoUBA' -EtatDir "D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\FIX1"
|
||||
Environnement: identique ; lancé après la fin du premier build (UeState -Kind Editeur,Compilation -WaitExit : « plus rien ne tourne » avant lancement)
|
||||
Attendu : code 0, 0 erreur, 0 avertissement ; 0 ligne UBT (cible jeu)
|
||||
Obtenu : code=0 duree=56s erreurs=0 avertissements=0 autres=0 unites=2 ; unités LPDirectControlSubsystem.cpp [NoUba] et Module.LifePlay.cpp [NoUba] ; « DLL liées : 0 » (cible monolithique) ; exécutable Binaries\Win64\LifePlay.exe daté 2026-10-20 20:09:16 ; journal Saved\Logs\portage\FIX1_Build_20261020-200822.log
|
||||
Lecture : « DLL liées : 0 » est normal pour la cible jeu ; la preuve de l'exécutable passe par la date, le MD5 et la recherche de chaîne ci-dessous ; 0 avertissement : le C4701 de F8a est bien absent
|
||||
```
|
||||
|
||||
MD5 des binaires (`certutil -hashfile … MD5`) : `Binaries\Win64\LifePlay.exe` = **`e2ba7dec63d479974394e2cffd1efc19`** (335 850 496 o, 2026-10-20 20:09:16) ; `Binaries\Win64\UnrealEditor-LifePlay.dll` = `68aee3039e0a320a4a085db1aa6e6018` (1 996 800 o, 20:08:10). L'exécutable livré dans `Binaries\Win64\LifePlay-Win64-Shipping.exe` (2026-10-14) n'est pas touché.
|
||||
|
||||
### Présence de la nouvelle chaîne dans les binaires
|
||||
|
||||
Trace : sortie de commande, Fiche FIX1-MZ — 2026-10-20 ~20:12
|
||||
```
|
||||
Commande : grep -a -c -P 'H\x00e\x00e\x00l\x00H\x00e\x00i\x00g\x00h\x00t\x00=\x00%\x00s\x00' <binaire> puis grep -a -c -P 'd\x00e\x00b\x00o\x00u\x00t\x00 \x00s\x00a\x00n\x00s\x00 \x00m\x00e\x00u\x00b\x00l\x00e\x00 \x00;\x00' <binaire> (chaînes UTF-16LE de TEXT())
|
||||
Environnement: depuis D:\Game\LifePlay-master 5.8 ; binaires ci-dessus
|
||||
Attendu : ≥ 1 ligne correspondante dans chaque binaire (chaîne nouvelle compilée)
|
||||
Obtenu : LifePlay.exe : 1 et 1 ; UnrealEditor-LifePlay.dll : 1 et 1
|
||||
Lecture : `grep -c` compte des « lignes » binaires, pas des occurrences ; 1 = au moins une. Exception à la règle « Grep, pas grep » : l'outil Grep ne cherche pas de l'UTF-16 dans un binaire (lecture seule, ponctuelle). Preuve de présence seulement : elle ne dit pas que le code s'exécute (voir § 4)
|
||||
```
|
||||
|
||||
### CopieEtat (avant les builds)
|
||||
|
||||
```
|
||||
COPIE ALERTE lot=FIX1 copie=LifePlay-master 5.8 proc=0 assets=0 absents=0 modifies=0 git=2/0/0 hors_declares=2 parasites=0 jeu_hors_docs=3 jeu_docs=8 head=ad3c9c6/30beef0/c8661cd verrou=248:libre cpu=1% alertes=GIT
|
||||
ALERTE GIT : jeu [ M] Source/LifePlay/LPCameraModeSubsystem.cpp
|
||||
ALERTE GIT : jeu [ M] Source/LifePlay/LPDirectControlSubsystem.cpp
|
||||
INFO : controle d'instantane non fait (parametre -Depuis absent)
|
||||
code=1
|
||||
```
|
||||
Lecture : les deux entrées sont des fichiers modifiés non déclarés par `-Assets` (la fiche n'en passe pas) : `LPDirectControlSubsystem.cpp` est le mien, `LPCameraModeSubsystem.cpp` vient de F8a (déjà modifié avant ma fiche, `git status` initial de la session). Aucun processus (`proc=0`), aucun parasite. Alerte attendue, non bloquante ; rien corrigé.
|
||||
|
||||
### PubCheck
|
||||
|
||||
```
|
||||
Commande : pwsh -NoProfile -File Tools/PubCheck.ps1 -Fichiers Source/LifePlay/LPDirectControlSubsystem.cpp -Depot "D:/Game/LifePlay-master 5.8" < /dev/null
|
||||
Sortie : PubCheck : 0 constat(s)
|
||||
code=0
|
||||
```
|
||||
Le livrable `FIX1-MZ-IMPL.md` et les résumés de build ne sont pas passés à `PubCheck` (la fiche ne demande que le fichier source ; chemins `D:\Game\…` présents dans les textes, comme dans `FIX1-F8a-IMPL.md`) : à contrôler par le gardien avant commit si la règle l'exige.
|
||||
|
||||
### État final
|
||||
|
||||
`Tools\UeState.ps1` en fin de fiche : `processus=0 editeur=0 compilation=0 shaders=0 jeu=0` (code 0). Aucun processus Unreal lancé par moi n'est resté ouvert.
|
||||
218
Docs/Migration/etat/REL/FIX1/FIX1-MZ2-IMPL.md
Normal file
218
Docs/Migration/etat/REL/FIX1/FIX1-MZ2-IMPL.md
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
Fiche FIX1-MZ2 — Niveau N2 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-impl — Skills sk-protocol, ue-cpp-build
|
||||
# FIX1-MZ2-IMPL : M-Z vise −90 + 12 × HeelHeight au lieu de −90 fixe, déclenchement et valeur écrite (2026-10-20)
|
||||
|
||||
Décision citée par la fiche : l'utilisateur a répondu « approuvé » à la recommandation de Big Boss : « corriger M-Z dès la build 1, pour qu'il vise −90 + 12 × la hauteur des talons au lieu de −90 fixe ». La fiche ne donne ni la session ni l'heure (`sk-protocol` § 2) : je la traite comme une consigne de fiche et n'en tire aucune autre décision.
|
||||
Hors gabarit : les deux compilations, `CopieEtat`, la preuve de présence dans les binaires, `PubCheck` et le tableau de comportement attendu sont rendus dans `## Constats` (notes TRACE).
|
||||
Écart de skills : la fiche cite `sk-protocol, ue-cpp-build` ; `lp-build` et `lp-ue-compat` sont aussi chargés dans mon contexte (commandes de build, liste des lignes connues).
|
||||
Niveaux de preuve : **établi** (fichier:ligne ou sortie de commande), **estimé** (raisonnement donné), **incertain** (essai nommé).
|
||||
|
||||
## 1. Fichiers modifiés
|
||||
|
||||
Un seul fichier de source : `D:\Game\LifePlay-master 5.8\Source\LifePlay\LPDirectControlSubsystem.cpp`, fonction `ULPDirectControlSubsystem::FitPersonBounds`, bloc M-Z `:1241-1272` (établi, `Read` et `Grep` après édition).
|
||||
|
||||
| Mesure | Valeur | Commande |
|
||||
|---|---|---|
|
||||
| MD5 avant (exigé `687c63d8`) | `687c63d85395888b8a334cb537c16a53`, conforme ; identique à l'instantané | `certutil -hashfile Source/LifePlay/LPDirectControlSubsystem.cpp MD5` avant l'édition ; colonne MD5 de `D:\Game\LifePlay_Backup_5.5\FIX1-MZ2\manifest.csv` |
|
||||
| MD5 après | `86ef519e880989941e033edeadda7c26` (inchangé après les deux builds) | `certutil -hashfile …` après l'édition, puis après les builds |
|
||||
| Taille avant, après | 64 858 o, 65 503 o | manifeste de l'instantané ; `ls -l` |
|
||||
| Fins de ligne | `i/crlf w/crlf attr/-text` ; 1824 CR = 1824 LF (aucune fin de ligne mixte) | `git ls-files --eol Source/LifePlay/LPDirectControlSubsystem.cpp` ; `tr -cd '\r' < … \| wc -c` et `tr -cd '\n' < … \| wc -c` |
|
||||
| Diff contre l'instantané | 9 lignes retirées, 15 ajoutées | `diff <instantané> <fichier> \| grep -c '^<'` puis `'^>'` |
|
||||
| Diff contre HEAD (cumulé avec FIX1-MZ, non commité) | `1 file changed, 59 insertions(+), 6 deletions(-)` | `git diff --stat -- Source/LifePlay/LPDirectControlSubsystem.cpp` |
|
||||
|
||||
Une seule édition (outil Edit, sans script). Le premier essai a échoué (un tabulateur de trop sur chaque ligne, aucune écriture), repris avec l'indentation vérifiée par Grep (`^\t{2}// M-Z`, `^\t{4}Body->SetRelativeLocation`).
|
||||
|
||||
```diff
|
||||
--- D:/Game/LifePlay_Backup_5.5/FIX1-MZ2/Source/LifePlay/LPDirectControlSubsystem.cpp
|
||||
+++ Source/LifePlay/LPDirectControlSubsystem.cpp
|
||||
@@ -1239,28 +1239,34 @@
|
||||
MeasuredSeats.Remove(Person);
|
||||
}
|
||||
// M-Z (STG-COMMUN9-DIAG) : une place feminine releve le maillage (-80,4 au lieu de -90) et rien ne le redescend au lever ; la
|
||||
- // Person debout flotte. Debout (aucun meuble), hors sexe et hors scene, capsule en collision, maillage hors de la hauteur relative
|
||||
- // du gabarit de sa classe (CDO) depuis 2 balayages (1 s) : on remet la hauteur du gabarit (X et Y inchanges).
|
||||
+ // Person debout flotte. Debout (aucun meuble), hors sexe et hors scene, capsule en collision, maillage hors de sa hauteur relative
|
||||
+ // cible depuis 2 balayages (1 s) : on remet cette hauteur (X et Y inchanges).
|
||||
+ // FIX1-MZ2 : la cible est -90 + 12 x HeelHeight (Person::updateHeelHeight, L6f_dump_Person.txt:19818-19827), pas le -90 seul : en
|
||||
+ // talons (-80,4 pour 0,8) le maillage est deja a sa hauteur voulue et M-Z ne se declenche plus. HeelHeight illisible ou non
|
||||
+ // fini : la cible reste la hauteur relative du gabarit de la classe (CDO), comme avant.
|
||||
const ACharacter* Template = Person->GetClass()->GetDefaultObject<ACharacter>();
|
||||
const USkeletalMeshComponent* TemplateBody = Template ? Template->GetMesh() : nullptr;
|
||||
const UCapsuleComponent* Capsule = Person->GetCapsuleComponent();
|
||||
const double TemplateZ = TemplateBody ? TemplateBody->GetRelativeLocation().Z : 0.0;
|
||||
+ double HeelHeight = 0.0;
|
||||
+ const bool bHeelRead = MZReadNumber(Person, TEXT("HeelHeight"), HeelHeight) && FMath::IsFinite(HeelHeight);
|
||||
+ const double TargetZ = bHeelRead ? MZHeelBaseZ + MZHeelFactor * HeelHeight : TemplateZ;
|
||||
+ // "(talons)" seulement si la cible vient de talons reels (HeelHeight non nul) : sans talons la ligne reste celle d'avant.
|
||||
+ const bool bHeelTarget = bHeelRead && !FMath::IsNearlyZero(HeelHeight);
|
||||
const FVector Relative = Body->GetRelativeLocation();
|
||||
if (TemplateBody && !bSceneRunning && !IsValid(Seat) && Capsule && Capsule->GetCollisionEnabled() != ECollisionEnabled::NoCollision
|
||||
- && FMath::Abs(Relative.Z - TemplateZ) > 1.0)
|
||||
+ && FMath::Abs(Relative.Z - TargetZ) > 1.0)
|
||||
{
|
||||
int32& Scans = MeshZScans.FindOrAdd(Person);
|
||||
if (++Scans >= 2)
|
||||
{
|
||||
- Body->SetRelativeLocation(FVector(Relative.X, Relative.Y, TemplateZ));
|
||||
+ Body->SetRelativeLocation(FVector(Relative.X, Relative.Y, TargetZ));
|
||||
MeshZScans.Remove(Person);
|
||||
- // FIX1-MZ : instrumentation seule (F8b), lue par reflexion apres la correction, sans effet sur elle. "?" = variable introuvable.
|
||||
- double HeelHeight = 0.0;
|
||||
- const bool bHeelRead = MZReadNumber(Person, TEXT("HeelHeight"), HeelHeight);
|
||||
+ // FIX1-MZ : champs de diagnostic (F8b), lus apres la correction. "?" = variable introuvable.
|
||||
const FString HeelText = bHeelRead ? FString::Printf(TEXT("%.3f"), HeelHeight) : FString(TEXT("?"));
|
||||
const FString HeelZText = bHeelRead ? FString::Printf(TEXT("%.2f"), MZHeelBaseZ + MZHeelFactor * HeelHeight) : FString(TEXT("?"));
|
||||
- UE_LOG(LogLifePlay, Display, TEXT("M-Z : %s maillage relatif Z %.1f -> %.1f (gabarit %s), debout sans meuble ; HeelHeight=%s ; currentAnimation=%s ; -90+12*HeelHeight=%s"),
|
||||
- *Person->GetName(), Relative.Z, TemplateZ, *Person->GetClass()->GetName(),
|
||||
+ UE_LOG(LogLifePlay, Display, TEXT("M-Z : %s maillage relatif Z %.1f -> %.1f%s (gabarit %s), debout sans meuble ; HeelHeight=%s ; currentAnimation=%s ; -90+12*HeelHeight=%s"),
|
||||
+ *Person->GetName(), Relative.Z, TargetZ, bHeelTarget ? TEXT(" (talons)") : TEXT(""), *Person->GetClass()->GetName(),
|
||||
*HeelText, *MZReadObjectName(Person, TEXT("currentAnimation")), *HeelZText);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Logique des balayages relue en entier** (`:1157-1163` nettoyage de `MeshZScans`, `:1164-1165` `bSceneRunning`, `:1166-1174` filtre des `Person_C` visibles, `:1241-1275` bloc M-Z) :
|
||||
- Le compteur `MeshZScans` monte d'un cran à chaque balayage où la condition tient et retombe (`else` → `MeshZScans.Remove(Person)`, `:1273-1275`) dès qu'un balayage ne la remplit plus : un personnage à sa cible n'accumule donc rien. La condition d'entrée comparait `Relative.Z` à `TemplateZ` (tolérance 1,0 cm) : c'est cette comparaison qui rendait M-Z actif sur un joueur en talons à −80,4. Elle compare maintenant à `TargetZ`, **même tolérance** (`> 1.0`). La valeur écrite (`SetRelativeLocation`) et la valeur affichée après `->` sont la même `TargetZ`.
|
||||
- `TemplateBody` reste dans la condition (inchangé) ; `TemplateZ` ne sert plus qu'au repli (HeelHeight illisible) et n'est plus affiché (`(gabarit %s)` donne toujours la classe).
|
||||
- `HeelHeight` est lu **à chaque balayage et pour chaque `Person_C` visible** (et non plus seulement à l'émission du journal) : un `FindPropertyByName` par personne et par balayage, comme `OccupyingFnt` juste au-dessus (`:1225`). Coût négligeable ; mesure de temps de trame non faite.
|
||||
|
||||
**Texte exact de la ligne de journal** (catégorie `LogLifePlay`, niveau `Display`) :
|
||||
```
|
||||
M-Z : <acteur> maillage relatif Z <Z avant> -> <cible>[ (talons)] (gabarit <classe>), debout sans meuble ; HeelHeight=<h> ; currentAnimation=<nom> ; -90+12*HeelHeight=<z>
|
||||
```
|
||||
- `<cible>` : `%.1f`, la valeur écrite (`−90 + 12 × h` si `h` est lisible, sinon le Z du gabarit). ` (talons)` n'apparaît que si `h` est lisible **et non nul** ; sans talons la ligne est octet pour octet celle de FIX1-MZ.
|
||||
- Regex à jour (remplace celle de `FIX1-MZ-IMPL.md:98`) : `M-Z : .* maillage relatif Z (-?[0-9.]+) -> (-?[0-9.]+)( \(talons\))? \(gabarit (\S+)\), debout sans meuble ; HeelHeight=(\S+) ; currentAnimation=(\S+) ; -90\+12\*HeelHeight=(\S+)`. Le préfixe `M-Z :` est inchangé. Aucun consommateur de la ligne dans `Tools` (Grep `M-Z` sur `D:\Game\LifePlay-master 5.8\Tools` au lot FIX1-MZ : aucun résultat ; non rejoué ici).
|
||||
|
||||
APIs moteur nouvelles, lues dans UE 5.8.3 : `FMath::IsFinite(double)` — `GenericPlatformMath.h:587`, surcharge Windows `MicrosoftPlatformMath.h:18` (`_finite`), appelée comme `FMath::IsFinite` à `UnrealMathUtility.h:439` ; `FMath::IsNearlyZero(double, double = UE_DOUBLE_SMALL_NUMBER)` — `UnrealMathUtility.h:418-421`, tolérance `1.e-8` (`:139`). Les autres appels (`FMath::Abs`, `SetRelativeLocation`, `MZReadNumber`) sont ceux d'avant. Le code de 5.5.4 n'a pas été relu (développement 5.5 arrêté, mémoire projet du 2026-10-12).
|
||||
|
||||
## 2. Écarts à la SPEC
|
||||
|
||||
La fiche tient lieu de SPEC. Écarts et choix :
|
||||
1. **« (talons) » seulement pour des talons réels.** La fiche dit « si la cible vient de HeelHeight ». Une lecture littérale l'ajouterait à toute ligne dont `HeelHeight` est lisible, donc à toutes (la variable existe sur `Person_C`) y compris `HeelHeight=0.000`, ce qui ne distinguerait plus rien et changerait les lignes sans talons. J'ai retenu `bHeelRead && !IsNearlyZero(HeelHeight)`. Si l'ordonnateur veut la lecture littérale : remplacer `bHeelTarget` par `bHeelRead` (une ligne).
|
||||
2. **Position de « (talons) »** : juste après la cible (`-> -80.4 (talons) (gabarit …)`), la fiche ne précise pas l'emplacement. La regex de `FIX1-MZ-IMPL.md:98` ne reconnaît plus ces lignes (champ optionnel ajouté, ci-dessus) ; aucun outil du dépôt ne la consomme.
|
||||
3. **Cible à `HeelHeight = 0` = constante −90**, non le Z du gabarit : la fiche écrit « −90 + 12 × HeelHeight » et « le gabarit seulement si HeelHeight est illisible ». Pour `Person_C` les deux valent −90,0 : les 41 lignes `M-Z :` des journaux archivés de `D:\Game\LifePlay_Build_5.8_*` portent toutes `-> -90.0 (gabarit Person_C)` (Grep `M-Z : .*gabarit [A-Za-z_0-9]+` sur `D:\Game`, glob `LifePlay*.log` : 17 fichiers, aucune autre classe ni autre valeur). Une classe `Person_C*` à gabarit ≠ −90 donnerait une cible différente du gabarit pour `h = 0` ; **non observée**, estimé improbable.
|
||||
4. **Garde `FMath::IsFinite(HeelHeight)`** ajoutée à la lecture : une valeur non finie compte comme « illisible » (cible = gabarit). Sans elle, `Abs(Z − NaN) > 1.0` est faux et M-Z se désactiverait en silence pour ce personnage. Cas non observé (`Conv_StringToDouble` donne 0 sur texte invalide, `L6f_dump_Person.txt:19774-19781`) ; la ligne affiche alors `HeelHeight=?` au lieu de `nan`.
|
||||
5. **Aucun bornage** de `HeelHeight` (négatif, très grand) : la formule du Blueprint n'en a pas non plus (`L6f_dump_Person.txt:19818-19827`).
|
||||
6. **Symétrie de la comparaison** : la valeur absolue écarte aussi une Person avec talons restée à −90, qui est maintenant **remontée** à −80,4 (ligne avec « (talons) »). C'est la conséquence directe de « la cible est −90 + 12 × HeelHeight » ; **aucun cas de ce genre** dans les 5 lignes COM22 (toutes à la valeur de la formule). Voir § 5, point 3.
|
||||
7. **Instantané non refait** : `D:\Game\LifePlay_Backup_5.5\FIX1-MZ2\` existait déjà (voir § 3).
|
||||
8. **`CopieEtat.ps1 -Lot FIX1` rend le code 1** (alerte GIT, deux fichiers modifiés non déclarés) : voir `## Constats`. Commande de la fiche, sans `-Assets`.
|
||||
|
||||
## 3. Instantané
|
||||
|
||||
- Lot `FIX1-MZ2`, dossier `D:\Game\LifePlay_Backup_5.5\FIX1-MZ2\` : créé avant ma fiche (par l'ordonnateur ; manifeste daté `2026-10-20T20:51:54`), contient `Source\LifePlay\LPDirectControlSubsystem.cpp` et `manifest.csv`.
|
||||
- Manifeste (lu) : `"Source/LifePlay/LPDirectControlSubsystem.cpp","True","64858","687C63D85395888B8A334CB537C16A53","2026-10-20T20:51:54"`.
|
||||
- Vérifié par `certutil -hashfile D:/Game/LifePlay_Backup_5.5/FIX1-MZ2/Source/LifePlay/LPDirectControlSubsystem.cpp MD5` = `687c63d85395888b8a334cb537c16a53` : la copie d'instantané est l'état de départ exact.
|
||||
- Retour arrière (proposé, non lancé) : `Tools\Restore.ps1 -Lot FIX1-MZ2`, ou recopie de ce fichier.
|
||||
|
||||
## 4. Ce qui n'a pas été fait
|
||||
|
||||
- **Aucune exécution en jeu** : ni éditeur, ni paquet, ni séance. Le comportement décrit en § Constats « Comportement attendu » est **calculé** à partir des valeurs des journaux COM22, pas observé.
|
||||
- **Aucun paquet** (`BuildDebug.ps1`, cuisson) : seuls `LifePlayEditor` et `LifePlay` Development ont été compilés dans `Binaries\Win64` de la copie. Le jeu COM22 de l'utilisateur tourne peut-être depuis une autre archive : non touché, non fermé (`UeState` : aucun processus Unreal dans cette copie).
|
||||
- Pas de correctif Blueprint (`updateHeelHeight`, `unOccupyFnt`), pas de changement de la tolérance (1,0), du nombre de balayages (2), des conditions debout/scène/capsule.
|
||||
- Pas d'essai de la branche `HeelHeight=?` ni de la garde `IsFinite` (aucune exécution).
|
||||
- Pas de mesure du coût par trame de la lecture de `HeelHeight` à chaque balayage.
|
||||
- Aucune commande git qui écrit.
|
||||
|
||||
## 5. Points à confirmer en VAL
|
||||
|
||||
1. La chaîne `%.1f%s (gabarit` et ` (talons)` est dans `Binaries\Win64\LifePlay.exe` et `UnrealEditor-LifePlay.dll`, et l'ancienne forme `%.1f (gabarit` n'y est plus (rejouer les recherches de `## Constats`).
|
||||
2. **En jeu, talons** : joueur avec talons (`HeelHeight` > 0) qui s'assied puis se lève : aucune ligne `M-Z :` pour lui sur la fenêtre ; relevés `STATE PlayerCharacter … meshZ=` égaux à `−90 + 12 × HeelHeight` (−80,4 pour 0,8) avant et après le lever ; à l'écran, pieds sur le sol (capture de l'utilisateur, comme en COM22).
|
||||
3. **En jeu, sans talons** : même séance sans talons ; `meshZ=-90.0`, **0** ligne `M-Z :` si MES.2 n'en avait pas ; si une ligne sort (cas −88,0 ou −80,4 sans talons), elle porte `-> -90.0 (gabarit Person_C)` **sans** « (talons) » et `HeelHeight=0.000`.
|
||||
4. Toute ligne `M-Z : … (talons)` d'une séance : `<Z avant>` ≠ `<cible>` par construction ; relever `<Z avant>` : une valeur −90,0 avec talons dit qu'un chemin du Blueprint écrase le Z sans passer par `updateHeelHeight` (cas non vu en COM22) ; une valeur à −88,0 avec talons rouvre la question du chemin −88,0 (`FIX1-F7-PRE.md:170`).
|
||||
5. Aucune ligne avec `HeelHeight=?` (variable introuvable ou non numérique).
|
||||
6. Non-régression du déclenchement : après 2 balayages (≈ 1 s), même nombre de lignes `M-Z :` que dans les séances sans talons comparables.
|
||||
7. Les builds comptent **20** lignes UBT `HyperAIStudio` pour `LifePlayEditor` et **0** pour `LifePlay` (`lp-build` § 7) : retrouvés ici (20 et 0).
|
||||
|
||||
## 6. Fichiers à commiter
|
||||
|
||||
Dépôt du jeu (`D:\Game\LifePlay-master 5.8`, branche `ue5.8`) :
|
||||
- `M Source/LifePlay/LPDirectControlSubsystem.cpp` (porte aussi l'instrumentation FIX1-MZ, encore non commitée : `FIX1-MZ-IMPL.md`)
|
||||
- `A Docs/Migration/etat/REL/FIX1/FIX1-MZ2-IMPL.md`
|
||||
|
||||
Ne pas inclure `Source/LifePlay/LPCameraModeSubsystem.cpp` (F8a). Les résumés de build `FIX1_Build_20261020-205618.txt` et `FIX1_Build_20261020-205639.txt` ne figurent pas dans `git status --short -- Docs/Migration/etat/REL/FIX1` (les `.txt` de ce dossier sont ignorés) : à ne pas commiter. Les journaux bruts `Saved\Logs\portage\FIX1_Build_*.log` restent hors dépôt. Aucun fichier de l'addon ni des Modules.
|
||||
|
||||
Tours : 25 / 40 (budget N2 par défaut : la fiche ne donne pas de rubrique 9 ; `Tools/FicheStats.py` fait foi)
|
||||
|
||||
## Constats
|
||||
|
||||
### Comportement attendu (calculé, non observé)
|
||||
|
||||
Source des valeurs : `D:\Game\LifePlay_Build_5.8_Development_COM22\Windows\LifePlay\Saved\Logs\LifePlay.log` lignes 2382, 4204, 5378, 13544, 13545 (Grep `M-Z : .*gabarit`) ; formule `L6f_dump_Person.txt:19818-19827` (si « Heels » dans l'inventaire : `Z = −90 + 12 × HeelHeight`, `:19804-19827` ; sinon `HeelHeight = 0` et Z = −90, `:19786-19790`, `:19828-19835`) ; la nouvelle condition `|Z − cible| > 1,0`.
|
||||
|
||||
| Cas | Z relatif | HeelHeight | Cible nouvelle | \|Z − cible\| | M-Z |
|
||||
|---|---|---|---|---|---|
|
||||
| COM22:2382 et :5378, joueur levé (`currentAnimation=-` puis `fnt_chair11-f-0-sit`) | −80,4 | 0,800 | −80,4 | 0 | ne se déclenche plus (avant : `-80.4 -> -90.0`, pieds enfoncés d'environ 9,6 cm) |
|
||||
| COM22:13544, PNJ | −85,2 | 0,400 | −85,2 | 0 | ne se déclenche plus |
|
||||
| COM22:4204 et :13545, PNJ | −80,4 | 0,800 | −80,4 | 0 | ne se déclenche plus |
|
||||
| sans talons, debout normal | −90,0 | 0 | −90,0 | 0 | ne se déclenche pas (inchangé) |
|
||||
| sans talons, siège féminin non redescendu | −80,4 | 0 | −90,0 | 9,6 | se déclenche comme avant : `-80.4 -> -90.0 (gabarit …)`, ligne identique à l'ancienne |
|
||||
| sans talons, cas −88,0 (7 sur 18 de `FIX1-F7-PRE.md`, `HeelHeight` alors non journalisé) | −88,0 | supposé 0 | −90,0 | 2,0 | se déclenche comme avant |
|
||||
| talons restés à −90 (non observé) | −90,0 | 0,800 | −80,4 | 9,6 | se déclenche : `-90.0 -> -80.4 (talons)` — comportement nouveau (écart 6) |
|
||||
| `HeelHeight` illisible | z | ? | Z du gabarit | selon z | comme avant, ligne `HeelHeight=?` |
|
||||
|
||||
Estimé (calcul : −90 + 12 × 0,8 = −80,4 ; −90 + 12 × 0,4 = −85,2 ; les 5 lignes COM22 donnent `-90+12*HeelHeight=` égal à `<Z avant>` à 0,05 près). Preuve en jeu : § 5, points 2 à 4.
|
||||
|
||||
### Compilation (hors gabarit, deux relevés)
|
||||
|
||||
Trace : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\FIX1\FIX1_Build_20261020-205618.txt` — Fiche FIX1-MZ2 — 2026-10-20 20:56
|
||||
```
|
||||
Commande : cd 'D:\Game\LifePlay-master 5.8'; pwsh -NoProfile -File Tools/Build.ps1 -Lot FIX1 -EtatDir "D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\FIX1" < /dev/null (LifePlayEditor Win64 Development, après Tools\CopieEtat.ps1 -Lot FIX1)
|
||||
Environnement: copie 5.8, branche ue5.8, HEAD ad3c9c6 ; UE 5.8.3 ; éditeur fermé (UeState : processus=0 editeur=0) ; une seule compilation à la fois ; machine calme (cpu=2 % au CopieEtat)
|
||||
Attendu : code 0, 0 erreur, 0 avertissement du compilateur ; 20 lignes UBT HyperAIStudio (connues)
|
||||
Obtenu : code=0 duree=12s erreurs=0 avertissements=0 autres=20 unites=1 ; unité LPDirectControlSubsystem.cpp ; DLL liée UnrealEditor-LifePlay.dll ; 4 actions (UBA local) ; journal Saved\Logs\portage\FIX1_Build_20261020-205618.log
|
||||
Lecture : « Makefile : » vide dans le résumé (statut non relevé par Build.ps1) ; module modifié bien recompilé (unité + DLL) ; une seule unité (la précédente en comptait deux : Module.LifePlay.cpp n'a pas été regroupé cette fois) ; chaîne « Using Visual Studio 14.50.35739 toolchain (…\MSVC\14.50.35717) and Windows 10.0.22621.0 SDK » = MSVC épinglé de la 5.8
|
||||
```
|
||||
|
||||
Trace : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\FIX1\FIX1_Build_20261020-205639.txt` — Fiche FIX1-MZ2 — 2026-10-20 20:56
|
||||
```
|
||||
Commande : cd 'D:\Game\LifePlay-master 5.8'; pwsh -NoProfile -File Tools/Build.ps1 -Lot FIX1 -Target LifePlay -Config Development -ExtraArgs '-NoUBA' -EtatDir "D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\FIX1" < /dev/null
|
||||
Environnement: identique ; lancé après la fin du premier build (UeState -Kind Editeur,Compilation : processus=0 editeur=0 compilation=0 avant lancement)
|
||||
Attendu : code 0, 0 erreur, 0 avertissement ; 0 ligne UBT (cible jeu)
|
||||
Obtenu : code=0 duree=23s erreurs=0 avertissements=0 autres=0 unites=1 ; unité LPDirectControlSubsystem.cpp [NoUba] ; « DLL liées : 0 » (cible monolithique) ; 3 actions ; journal Saved\Logs\portage\FIX1_Build_20261020-205639.log
|
||||
Lecture : « DLL liées : 0 » est normal pour la cible jeu ; la preuve de l'exécutable passe par la date, le MD5 et la recherche de chaîne ci-dessous
|
||||
```
|
||||
|
||||
Sortie de commande, binaires (`certutil -hashfile <fichier> MD5` et `ls -l --time-style=full-iso`) :
|
||||
```
|
||||
Binaries/Win64/LifePlay.exe 335850496 o 2026-10-20 20:57:01 MD5 963927f34716cc1ee278d94f3eff8334
|
||||
Binaries/Win64/UnrealEditor-LifePlay.dll 1996800 o 2026-10-20 20:56:29 MD5 596d9e75f4cab01d351e419f5a078939
|
||||
```
|
||||
(références FIX1-MZ : `LifePlay.exe` e2ba7dec63d479974394e2cffd1efc19, DLL 68aee3039e0a320a4a085db1aa6e6018). Le fichier `Binaries\Win64\LifePlay-Win64-Shipping.exe` (2026-10-14) n'est pas touché.
|
||||
|
||||
### Présence de la nouvelle chaîne dans les binaires
|
||||
|
||||
Trace : sortie de commande, Fiche FIX1-MZ2 — 2026-10-20 ~20:58
|
||||
```
|
||||
Commande : grep -a -c -P '<motif UTF-16LE>' <binaire>, trois motifs : ' (talons)' ; '%.1f (gabarit' (ancienne forme) ; '%.1f%s (gabarit' (nouvelle forme) ; octets séparés par \x00, depuis D:\Game\LifePlay-master 5.8
|
||||
Environnement: Binaries\Win64\LifePlay.exe et UnrealEditor-LifePlay.dll ci-dessus
|
||||
Attendu : ' (talons)' ≥ 1, ancienne forme 0, nouvelle forme ≥ 1 dans chaque binaire
|
||||
Obtenu : LifePlay.exe : 1 / 0 / 1 ; UnrealEditor-LifePlay.dll : 1 / 0 / 1
|
||||
Lecture : `grep -c` compte des « lignes » binaires, pas des occurrences ; exception à la règle « Grep, pas grep » (l'outil Grep ne cherche pas d'UTF-16 dans un binaire ; lecture seule, ponctuelle). Preuve de présence seulement : elle ne dit pas que le code s'exécute (voir § 4)
|
||||
```
|
||||
|
||||
### CopieEtat (avant les builds)
|
||||
|
||||
```
|
||||
COPIE ALERTE lot=FIX1 copie=LifePlay-master 5.8 proc=0 assets=0 absents=0 modifies=0 git=2/0/0 hors_declares=2 parasites=0 jeu_hors_docs=3 jeu_docs=10 head=ad3c9c6/30beef0/c8661cd verrou=248:libre cpu=2% alertes=GIT
|
||||
ALERTE GIT : jeu [ M] Source/LifePlay/LPCameraModeSubsystem.cpp
|
||||
ALERTE GIT : jeu [ M] Source/LifePlay/LPDirectControlSubsystem.cpp
|
||||
INFO : controle d'instantane non fait (parametre -Depuis absent)
|
||||
code=1
|
||||
```
|
||||
Lecture : les deux entrées sont des fichiers modifiés non déclarés par `-Assets` (la fiche n'en passe pas) : `LPDirectControlSubsystem.cpp` est le mien (et FIX1-MZ), `LPCameraModeSubsystem.cpp` vient de F8a. Aucun processus (`proc=0`), aucun parasite. Alerte attendue, non bloquante ; rien corrigé.
|
||||
|
||||
### PubCheck
|
||||
|
||||
```
|
||||
Commande : pwsh -NoProfile -File Tools/PubCheck.ps1 -Fichiers Source/LifePlay/LPDirectControlSubsystem.cpp -Depot "D:/Game/LifePlay-master 5.8" < /dev/null
|
||||
Sortie : PubCheck : 0 constat(s)
|
||||
code=0
|
||||
```
|
||||
Le livrable et les résumés de build ne sont pas passés à `PubCheck` (la fiche ne demande que le fichier source ; chemins `D:\Game\…` présents dans les textes, comme dans `FIX1-MZ-IMPL.md`) : à contrôler par le gardien avant commit si la règle l'exige.
|
||||
|
||||
### État final
|
||||
|
||||
`Tools\UeState.ps1` en fin de fiche : `processus=0 editeur=0 compilation=0 shaders=0 jeu=0` (code 0). Aucun processus Unreal lancé par moi n'est resté ouvert.
|
||||
|
||||
### À verser
|
||||
|
||||
`aucun` skill à modifier. Observation : `Build.ps1` a groupé 2 unités au premier build de FIX1-MZ (`Module.LifePlay.cpp` en plus) et 1 seule ici ; le critère « module modifié recompilé » reste l'unité `LPDirectControlSubsystem.cpp` plus la DLL liée.
|
||||
184
Docs/Migration/etat/REL/GIREV/GIREV-D8-RECH.md
Normal file
184
Docs/Migration/etat/REL/GIREV/GIREV-D8-RECH.md
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
Fiche GIREV-D8-RECH — Niveau N2 — Modèle prévu non précisé par la fiche | utilisé claude-sonnet-5-5 — Agent lp-cart — Skills sk-protocol, ue-cpp-build, lp-commandlets, lp-paths
|
||||
# GIREV-D8-RECH : conflits entre morphs opposés, comportement actuel de `GI.ResolveConflictingMorphs` (D8) et bonnes pratiques (2026-10-21)
|
||||
|
||||
Hors gabarit : la rubrique 3 est subdivisée (3.1 à 3.6) pour porter le comportement actuel, les sources web, la comparaison et les options demandées par la fiche. Lecture seule : ni MCP, ni éditeur, ni commandlet, aucun téléchargement (les pages web sont lues par l'outil de lecture, rien n'est enregistré sur le disque). Le code source du moteur 5.8 installé est lu en place. Seul ce fichier est écrit. Descriptions neutres (doc 27) : aucun nom de morph, de préréglage ni de section réservée n'est cité ; « morph » désigne une cible de forme. Les questions sont numérotées `DQ1` à `DQ6` pour ne pas les confondre avec les `GQ1` à `GQ9` de `GIREV-PRE.md`. La recherche répond à la consigne de l'utilisateur rapportée par la fiche : « recherche ce qui se fait en best practice sur D8 ». Aucune décision n'est prise ici.
|
||||
|
||||
## Résumé (à lire en premier)
|
||||
|
||||
1. **Comportement actuel (établi, § 3.1)** : à la fin de `LoadPreset`, pour chaque ligne de la table `MorphTable` dont le côté `Min` est renseigné, si les deux morphs opposés (`Min` et `Max`) sont non nuls sur le composant corps, le **plus faible est remis à 0** ; à égalité stricte, c'est le morph **`Max`** qui est annulé. Aucun journal, aucun paramètre, un seul appelant connu.
|
||||
2. **Pourquoi seulement le corps : non documenté** (établi comme absence). Aucune source interne ne donne la raison ; R04 range D8 en « information » et CG2-CART-01 en « conception » (`CG2-CART-01.md:51`). Conséquence structurelle (établi) : `Person.setMorphTarget` écrit un nom de morph sur le corps **et** sur les cheveux, la résolution ne corrige que le corps ; un conflit résolu côté corps reste donc entier côté cheveux (effet visuel : estimé).
|
||||
3. **Pratique observée dans les sources lues (§ 3.2)** : on évite le conflit **par construction** (un seul paramètre signé pilote les deux côtés : MakeHuman, Character Creator), ou on le **borne** (limites Daz, option de bornage Unity, saturation VRM), ou on fixe une **priorité explicite et documentée** (recouvrements VRM `block` / `blend`). Unreal ne normalise pas et le dit dans son code. **Aucune source lue ne fixe de règle d'égalité universelle** : le choix de D8 est une décision de conception, pas l'application d'une norme.
|
||||
4. **Mesure (§ 3.5)** : dans les 145 fichiers `.lpcharacter` du dossier `Content`, **un seul** contient les deux côtés d'une même paire sous l'hypothèse « mêmes radicaux `_min` / `_max` » (estimé : les paires réelles de `MorphTable` ne sont pas lues). Le conflit vient donc surtout de l'**empilement** de préréglages (`Blend`) ou de tirages, pas des fichiers pris isolément (estimé).
|
||||
5. **Options (§ 3.6)** : A garder (0 écriture) ; **B règle déterministe documentée** (égalité écrite, une trace au journal, cheveux en variante) ; C groupes exclusifs ou normalisation (net signé, ou exclusivité à l'écriture). **Recommandation non contraignante : B1** (règle actuelle conservée et écrite, une ligne de journal par conflit, aucun changement d'aspect) ; la décision revient à l'utilisateur (DQ1 à DQ6).
|
||||
|
||||
## 1. Objet et périmètre
|
||||
|
||||
Un domaine : le défaut **D8** de R04 (`04-defauts.md:20`), repris au n° 8 du tableau de `CG2-CART-01.md` (**fichier ligne 51** ; « ligne 8 » de la fiche = n° 8 du tableau, pas la ligne 8 du fichier). Décrire précisément `GI.ResolveConflictingMorphs`, rechercher les bonnes pratiques de résolution de conflits entre morph targets / blend shapes / curseurs, comparer, proposer 2 ou 3 options avec coût, risque et recommandation. Contexte de calendrier : `GI.uasset` n'est révisé qu'une fois, en build 2 (`GIREV-PRE.md:6`) ; D8 est un candidat non retenu par `BOSS-ETAT.md:143`, posé en question `GQ5` (`GIREV-PRE.md:149`, `:246`). Hors périmètre : toute écriture, tout essai, la décision, la mesure des paires réelles de `MorphTable`.
|
||||
|
||||
## 2. Commandes et lectures (exactes) avec compte brut
|
||||
|
||||
| # | Commande ou lecture | Résultat brut |
|
||||
|---|---|---|
|
||||
| 1 | Read `lp-doc/gabarits.md` (CART) ; Read `REL/GIREV/GIREV-PRE.md:1-80` (gabarit d'en-tête) ; Read `CG/CG2/CG2-CART-01.md` (entier) ; Glob `**/*GIREV*` sous `etat` | gabarit lu ; D8 = `CG2-CART-01.md:51` ; Glob : `REL\GIREV\GIREV-PRE.md` seul (le livrable n'existait pas) |
|
||||
| 2 | Grep `ResolveConflictingMorphs` dans `D:\Game\LifePlay-Sandbox-5.8\Docs\CG` | 12 lignes dans 4 fichiers : `04-defauts.md:20`, `:60`, `:75` ; `03-parcours.md:116`, `:134` ; `06-rapport-audit.md:33`, `:37` ; `archive/CG-REFERENTIEL.md:280`, `:297`, `:305`, `:318`, `:336` (copie ancienne) |
|
||||
| 3 | `rg --no-ignore -l "ResolveConflictingMorphs" "D:/Game/LifePlay-master 5.8/Docs" "D:/Game/LifePlay-Sandbox-5.8/Docs"` | 16 fichiers : 7 dumps sous `etat` (`portage55/L6f/L6f_dump_GI.txt`, `portage55/L6f/L6f_LPDumpFunction_20260930-102202.txt`, `ST/STA/dumps/GI__graphes.txt`, `ST/STA/STA-T2a_LPDumpFunction_20261009-192922.txt`, `ST/STE/STE-D_LPDumpFunction_20261010-110623.txt`, `ST/STE/dumps/GI__LoadPreset.txt`, `sandbox/DOC-MOD/DOC-MOD_LPDumpFunction_20261007-083441.txt`) ; `Docs/01_Architecture_Initiale.md` ; `CG2-CART-01.md` ; 4 fichiers du référentiel de l'addon (`04-defauts`, `03-parcours`, `06-rapport-audit`, `archive/CG-REFERENTIEL`) ; 3 fichiers `CGREF1-*` de l'addon (`T3-MCP`, `T3b-FICHE`, `T3b-MCP`). Aucun dump d'`EventGraph` (`CAM-B1-PRE`, `STE-ORG4cV`) dans la liste |
|
||||
| 4 | Read `CGREF1-T3b-MCP.md:1-70` (addon `Docs/etat/CG/CGREF1/`) | lecture MCP 5.8 du 2026-10-16 : A11 `:24`, règle `:44-49`, D8 `:92` |
|
||||
| 5 | Read `L6f_dump_GI.txt:18210-18300` et `:3505-3530` ; Grep `ResolveConflictingMorphs\|MorphTable` dans ce fichier | fonction à `:18214` (24 nœuds) ; appel `:3518` ; `MorphTable` aussi à `:50274-50316` (construction des curseurs) |
|
||||
| 6 | Grep `ResolveConflictingMorphs` + `-C 8` dans `ST/STE/dumps/GI__LoadPreset.txt` ; Grep `K2Node_IfThenElse_5` (`-A 8`) ; `rg --no-ignore -m3 "^Commandlet\|^Date\|^Moteur\|Engine"` sur `STE-D_…` | appel `:410-412` ; condition `LoadPresetLite` `:496` ; en-tête STE-D : `LPDumpFunction -BP=GI -Fn=LoadPreset -Pins -Exec`, `2026-10-10T11:07:09 … code de sortie : 0` |
|
||||
| 7 | Read `04-defauts.md:1-83`, `03-parcours.md:100-197`, `02-format.md:1-40`, `06-rapport-audit.md:29-35`, `:123-178` | cités en § 3 |
|
||||
| 8 | Read `Engine/Source/Runtime/Engine/Private/Components/SkeletalMeshComponent.cpp:4005-4079` et `SkeletalRender.cpp:20-59` (moteur `D:\Game\Launcher\Engine\UE_5.8`) ; Grep `MaxMorphTargetBlendWeight\|MinMorphTargetBlendWeight\|MorphTarget\.MaxBlendWeight\|MorphTarget\.MinBlendWeight\|define ZERO_ANIMWEIGHT_THRESH` sous `Engine/Source/Runtime` (`*.h`, `*.cpp`) | `SetMorphTarget` `:4011-4035`, `GetMorphTarget` `:4042-4054` ; `MaxMorphTargetBlendWeight = 5.0f` `SkeletalRender.cpp:26` ; `#define ZERO_ANIMWEIGHT_THRESH (0.00001f)` `VectorRegister.h:133` |
|
||||
| 9 | `rg --no-ignore --files -g "*.lpcharacter" .` (depuis `Content`) puis `\| wc -l` ; idem avec les racines `Modules` et `Saves` | `145` ; `141` ; `4` |
|
||||
| 10 | `rg --no-ignore --pcre2 -U -l -g "*.lpcharacter" "(?ms)^MORPH ([^:\r\n]+)_min:.*?^MORPH \1_max:" . \| wc -l` ; formulation inverse (`_max` puis `_min`) | `0` ; `1` |
|
||||
| 11 | Contrôle du motif : `rg --no-ignore -l -g "*.lpcharacter" "^MORPH [^:]*_min:" . \| wc -l` ; idem `_max` ; `rg --no-ignore -c …` sommé par `awk` ; fichiers ayant au moins une ligne `^MORPH ` | `58` ; `59` ; lignes `472` (`_min`) et `523` (`_max`) ; `126` |
|
||||
| 12 | Recherche web et lecture de pages (13 lignes au § 3.2) | statut de lecture par ligne du tableau § 3.2 |
|
||||
| 13 | `git log -1 -- Content/BPs/GI.uasset` ; `md5sum` ; `date` | `c4cf6f3 2026-10-14 …` ; `32fc0a970ab194626e8dc07df3a9633d` (égal à `GIREV-PRE.md:57`) ; `2026-10-21 07:41` |
|
||||
|
||||
Écart de méthode : une première forme de la commande 9 (`rg --files` suivi de `cut`, `sort`, `uniq -c`, sans `wc -l`) a **affiché les noms** des fichiers dans la sortie de l'outil, dont certains à caractère réservé ; ils ne sont **pas** repris ici. Compter, ne pas lister (à verser).
|
||||
|
||||
## 3. Constats `fichier:ligne`
|
||||
|
||||
### 3.1 Comportement actuel de `GI.ResolveConflictingMorphs` (établi sauf mention)
|
||||
|
||||
Notation : `L6f` = `Docs/Migration/etat/portage55/L6f/L6f_dump_GI.txt` (dump 5.5 du 2026-09-30, 24 nœuds) ; `T3b` = `CGREF1-T3b-MCP.md` (lecture MCP **5.8** du 2026-10-16, 24 nœuds : même nombre, `T3b:24`).
|
||||
|
||||
- **Signature** : `FunctionEntry_192` sans broche d'entrée ni de sortie (`L6f:18215`). La fonction n'a donc **aucun paramètre**.
|
||||
- **Entrées implicites** :
|
||||
- la variable membre `MorphTable`, tableau de la structure `MorphSlider` (champs `DisplayName`, `Max`, `Min`, `Female`, `Male` : `L6f:18219-18232`, `T3b:44`). La même table construit les curseurs de l'écran du générateur (`L6f:50274-50316`) : **une ligne = un curseur à deux côtés**, `Min` et `Max` étant les noms de deux morphs opposés ;
|
||||
- le personnage édité `CharacterBeingEdited` (`L6f:18216`, `:18285`) et, via lui, le composant `Mesh` (`L6f:18240-18242`, `:18288-18290`) ;
|
||||
- les valeurs courantes des deux morphs, lues par `SkeletalMeshComponent::GetMorphTarget` (`L6f:18243-18256`). Dans le moteur 5.8, cette lecture rend la valeur de la liste `MorphTargetCurves` du composant, ou `0.0` si le morph n'y figure pas (`SkeletalMeshComponent.cpp:4042-4054`).
|
||||
- **Règle**, ligne par ligne de `MorphTable`, indépendamment des autres lignes (`T3b:44-49`, câblage relu dans `L6f:18233-18300`) :
|
||||
1. si `Min` vaut le nom « None », la ligne est ignorée (`L6f:18233-18238`) ;
|
||||
2. lecture de `Max` et de `Min` sur le corps (`L6f:18243-18256`) ;
|
||||
3. si `Max != 0` **et** `Min != 0` (comparaison exacte à `0.0`, `L6f:18257-18273`), sinon rien ;
|
||||
4. si `Max > Min` (comparaison **stricte** : `L6f:18278-18284`), `SetMorphTarget(nom Min, 0.0, bRemoveZeroWeight = true)` ; sinon `SetMorphTarget(nom Max, 0.0, true)` (`L6f:18291-18300` ; branche vraie → `Min`, branche fausse → `Max` : `T3b:48`).
|
||||
- **Cas d'égalité** : `Max > Min` est faux, donc le morph **`Max` est annulé** et le `Min` est gardé (`T3b:49`, `04-defauts.md:20`). Le départage est donc **asymétrique** (toujours le même côté), mais déterministe.
|
||||
- **Effet moteur de l'annulation** : avec `bRemoveZeroWeight = true`, le moteur retire l'entrée du composant quand `|valeur| ≤ 0,00001` (`SkeletalMeshComponent.cpp:4014`, `:4028-4034` ; `VectorRegister.h:133`). Le perdant est donc **supprimé de la liste active**, pas seulement mis à zéro.
|
||||
- **Propriétés déduites de la structure** (établi pour la structure, estimé pour l'usage) :
|
||||
- **idempotente** : après un passage, l'un des deux côtés vaut 0 et la condition 3 est fausse ;
|
||||
- **silencieuse** : aucun nœud de journal ni de message parmi les 24 (`L6f:18214-18300`) ; l'audit R06 range « le silence » parmi ses faiblesses (`06-rapport-audit.md:69`, titre § 3.1) ;
|
||||
- **destructive** : la valeur perdante n'est pas conservée ;
|
||||
- **« le plus fort gagne »**, pas « le dernier écrit gagne » : la fonction ne voit que des valeurs finales, pas l'ordre des écritures (estimé : déduit du fait qu'elle ne lit que `GetMorphTarget`).
|
||||
- **Pourquoi seulement le corps** : aucune source interne ne le dit. Faits établis : la fonction lit et écrit **uniquement** sur `Mesh` (`L6f:18240-18242`, `:18288-18290`) ; le défaut est consigné ainsi : « ne traite que `GetMesh` (ignore `HairSM`) » (`04-defauts.md:20`) ; `Person.setMorphTarget` applique, lui, le **même nom** au composant cheveux puis au corps, chacun deux fois (`T3b:35-41`, D7 `04-defauts.md:19`). Hypothèses (estimé, non départagées) : (a) une fonction écrite autour d'un composant de référence unique ; (b) le maillage de cheveux n'a pas tous ces morphs ; (c) oubli. Essai qui trancherait (b) : lire la liste des morph targets de l'asset de cheveux (lecture MCP ou dump), voir § 5.
|
||||
- **Appelant** : un seul site connu, `K2Node_CallFunction_6074` dans `LoadPreset`, branche « faux » de `IfThenElse_5` dont la condition est `LoadPresetLite` (`GI__LoadPreset.txt:410-412`, `:496` ; `L6f:3518`), suivi de l'affichage approprié du personnage (`GI__LoadPreset.txt:414`). La fonction s'exécute donc **une fois, après le rejeu de toutes les lignes** du préréglage, et pas à chaque écriture de morph. Elle n'est pas appelée par le curseur de l'écran (le curseur écrit un seul côté : `Min` sous 0,5, `Max` au-dessus, `03-parcours.md:164`). Les corps des `Randomize*` et de `GeneratePerson` ne sont pas lus (`04-defauts.md:55`) : appelants inconnus possibles (estimé : aucun, car aucun dump d'`EventGraph` ne contient l'appel, commande 3). `01_Architecture_Initiale.md:151` place l'appel après `GenerateAndApplyBools` : résumé de l'ancienne architecture, **contredit par les dumps** (l'appel est dans `LoadPreset`).
|
||||
- **Lien avec la superposition** : `Blend = true` rejoue les lignes du fichier par-dessus l'état courant, sans moyenne (`03-parcours.md:114-116`, `06-rapport-audit.md:31`) ; `BlendPreset` ne fusionne rien, c'est un empilement de fichiers partiels (`06-rapport-audit.md:33`). Le texte de R06 dit que **le seul arbitrage automatique** de ce dispositif est `ResolveConflictingMorphs` (`06-rapport-audit.md:33`). Conséquence (estimé) : si un préréglage posé après un autre fixe le côté opposé à une valeur plus faible que celle déjà en place, **c'est la contribution la plus récente qui est annulée**.
|
||||
- **Ce qui n'est pas lu** : le contenu de `MorphTable` (nombre de lignes, lesquelles ont `Min` renseigné, drapeaux `Female` / `Male` : la fonction les ignore, `L6f:18231-18232`). La valeur par défaut d'une variable de Blueprint n'est lisible ni dans ces dumps ni dans `OUT1_uasset_rejeu_log_sans_emulation.txt:305` (qui ne donne que le type `Array<struct:MorphSlider>`).
|
||||
|
||||
### 3.2 Sources web : ce qui se fait ailleurs
|
||||
|
||||
Statut : **lu** = page récupérée et citée ; **résumé** = seulement le résumé du moteur de recherche, page non relue (indicatif) ; **non lu** = page tronquée ou inaccessible.
|
||||
|
||||
| # | Source (URL) | Ce qu'elle établit | Statut | Lien avec D8 |
|
||||
|---|---|---|---|---|
|
||||
| W1 | https://raw.githubusercontent.com/makehumancommunity/makehuman/master/makehuman/apps/humanmodifier.py | Modificateur à deux cibles : valeur bornée à `[-1, 1]` (ou `[0, 1]` sans cible gauche) ; poids gauche `-min(value, 0.0)`, poids droit `max(0.0, value)` ; cible centrale `1.0 - abs(value)` | lu | **Exclusion par construction** : un seul paramètre signé, l'un des deux côtés vaut toujours 0 ; aucun conflit à résoudre |
|
||||
| W2 | https://manual.reallusion.com/Character-Creator-4/Content/ENU/4.0/06_Customizing_Morphing_Sliders/User_Interface.htm | « a morphing value can be within a range from -100 to 100 » ; Min et Max règlent les bornes du curseur | lu | Même principe : curseur signé unique ; la page ne traite pas des morphs opposés combinés |
|
||||
| W3 | https://docs.daz3d.com/public/software/dazstudio/4/userguide/creating_content/assembling/tutorials/creating_joint_controlled_morphs/start | « Change the Min Limit to 0. The JCM only works from 0 to 100 percent » ; « leaving limits on in negative values will cause problems when the shoulder joint is bent in the opposite direction » | lu | **Bornage** comme garde contre l'activation du côté opposé |
|
||||
| W4 | https://docs.daz3d.com/public/software/dazstudio/4/referenceguide/terms/property/start | Certaines propriétés ont les attributs « Clamped, Mappable, Must Map » ; la page n'explique pas le bornage ni l'ERC | lu | Confirme l'existence d'un attribut de bornage ; rien sur les conflits |
|
||||
| W5 | https://www.daz3d.com/forums/discussion/comment/381884 ; https://bitbucket.org/Diffeomorphic/import_daz/issues/480/plussing-morphs | Un « contrôleur » créé par ERC Freeze pilote plusieurs propriétés à la fois ; retirer les limites d'un morph peut casser la géométrie (résumé de recherche) | résumé | Pattern « un contrôle, plusieurs morphs » ; prudence sur le retrait des bornes. Pas de règle d'arbitrage trouvée |
|
||||
| W6 | https://dev.epicgames.com/documentation/unreal-engine/BlueprintAPI/Components/SkeletalMesh/SetMorphTarget | Nœud « Set Morph Target with Name and Value(0-1) » ; « Remove Zero Weight : Used by editor code when it should stay in the active list with zero weight » | lu | Le nœud que D8 appelle ; plage documentée 0-1 |
|
||||
| W7 | Moteur 5.8 installé : `Engine/Source/Runtime/Engine/Private/Components/SkeletalMeshComponent.cpp:4019-4021` ; `.../Private/SkeletalRender.cpp:26-35` | Commentaire du moteur : « sum up, in the future we might normalize, but for now this just sums up / this won't work well if all of them have full weight - i.e. additive » (le code affecte `=`, `:4021`) ; poids absolu accepté jusqu'à `r.MorphTarget.MaxBlendWeight`, 5,0 par défaut | lu | **Unreal ne normalise ni n'arbitre** : la politique est laissée au contenu. Les valeurs hors `[0, 1]` sont tolérées jusqu'à 5,0 |
|
||||
| W8 | https://dev.epicgames.com/documentation/metahuman/metahuman-creator-blend-tool-in-unreal-engine | Mélange de un à trois préréglages par points de contrôle ; « As a control point moves closer to a preset, that preset's features blend with your character » ; la page ne donne ni formule de poids, ni normalisation, ni règle de conflit | lu | **Fusion pondérée par proximité**, sans conflit exposé à l'utilisateur ; la page est muette sur la normalisation |
|
||||
| W9 | https://docs.unity3d.com/ScriptReference/PlayerSettings-legacyClampBlendShapeWeights.html ; https://discussions.unity.com/t/removing-clamping-of-blendshapes-to-the-range-0-100/683047 | Option : « If set to true, the range of BlendShape weights in SkinnedMeshRenderers will be clamped, otherwise BlendShape weights can take any value » ; défaut non précisé par la page. Le fil indique que Unity a retiré le bornage 0-100 et que le code doit borner lui-même (résumé) | lu (page) / résumé (fil) | **Bornage configurable** ; la responsabilité de borner revient au contenu |
|
||||
| W10 | https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md | Recouvrements `overrideBlink` / `overrideLookAt` / `overrideMouth` : `none` (rien), `block` (« Set the target weight to 0 » tant que l'expression dominante a un poids > 0), `blend` (« Attenuates the target weight ») ; la somme des atténuations est saturée (`factor = 1.0 - saturate(value)`) ; valeurs d'expression à borner à `[0, 1]` ; « settings for the same kind are treated as invalid » | lu | **Priorité explicite et documentée**, avec deux modes (coupure ou atténuation) ; aucune règle d'égalité |
|
||||
| W11 | https://simscommunity.info/2018/07/10/learning-your-tools-the-sims-4-morphmaker/ | Les directions « haut » et « bas » d'un curseur sont deux modificateurs distincts rattachés au même curseur ; l'article ne traite ni des poids, ni des conflits | lu | Non concluant : structure à deux côtés, aucune règle de conflit publiée trouvée |
|
||||
| W12 | https://www.tech-artists.org/t/blendshape-condition-node/10797 | Un répondant déconseille de « couper des formes quand d'autres s'allument » au-delà des combinaisons de deux ; la voie courante est la forme corrective pour les combinaisons problématiques (résumé) | résumé | Mise en garde contre la logique d'extinction en chaîne |
|
||||
| W13 | https://docs.blender.org/manual/en/latest/animation/shape_keys/shape_keys_panel.html | Page tronquée à la lecture (215 969 caractères, 100 000 lus, partie utile absente) | non lu | Aucune conclusion tirée (additif par défaut : non vérifié ici) |
|
||||
|
||||
Recherches sans résultat utile : « Sims 4 modificateur bidirectionnel » (aucune documentation officielle sur un arbitrage), « Character Creator morphs opposés combinés » (aucune page officielle), « MetaHuman plausibilité » (la page ne donne ni borne ni règle). L'absence de résultat n'est pas une preuve d'absence de règle.
|
||||
|
||||
### 3.3 Les patrons de pratique qui se dégagent
|
||||
|
||||
| Patron | Sources | Idée |
|
||||
|---|---|---|
|
||||
| P1 Exclusion par construction | W1, W2 | un seul paramètre signé pilote les deux côtés ; l'état « les deux côtés actifs » n'existe pas |
|
||||
| P2 Bornage | W3, W9, W10, W7 | on limite l'amplitude (Daz, Unity, VRM, plafond 5,0 d'Unreal) ; borner n'arbitre pas entre deux côtés |
|
||||
| P3 Priorité explicite et documentée | W10 | une expression dominante coupe (`block`) ou atténue (`blend`) une autre, règle écrite dans la spécification |
|
||||
| P4 Fusion pondérée | W8, W10 | des poids continus plutôt qu'une coupure ; la normalisation reste souvent non documentée (W8) |
|
||||
| P5 Pas d'arbitrage dans le moteur | W7 | le moteur additionne et laisse la politique au contenu ou à l'outil |
|
||||
| P6 Forme corrective plutôt que chaîne d'extinctions | W12 (indicatif) | traiter la combinaison problématique par une forme dédiée |
|
||||
|
||||
### 3.4 Comparaison au comportement actuel
|
||||
|
||||
| Critère | `ResolveConflictingMorphs` actuel | Pratique observée |
|
||||
|---|---|---|
|
||||
| Où le conflit est-il évité ? | après coup, à la fin du chargement (`GI__LoadPreset.txt:410-412`) ; le curseur de l'écran, lui, est déjà signé (`03-parcours.md:164`, P1) | P1 évite l'état, la fonction le répare |
|
||||
| Règle de priorité | le plus fort gagne, perdant mis à 0 (`T3b:48-49`) | proche de P3 `block`, **sans atténuation** (P3 `blend`, P4 non utilisés) |
|
||||
| Égalité | `Max` annulé, asymétrique, non écrit hors R04 | aucune source lue ne fixe de règle d'égalité (W10 : même cas « invalide ») |
|
||||
| Périmètre | corps seul (`L6f:18240-18242`) | non documenté ; incohérence corps / cheveux possible (estimé) |
|
||||
| Visibilité | aucun journal | R06 demande des branches d'échec journalisées (`06-rapport-audit.md:166`) |
|
||||
| Dépendance à l'ordre | aucune (valeurs finales) | P3 documenté par priorité fixe ; ici l'ordre d'empilement est ignoré (estimé) |
|
||||
| Points solides | déterministe, idempotente, simple, indépendante par ligne, coût d'exécution nul | alignée avec le choix de R06 : superposition plutôt que moteur de fusion (`06-rapport-audit.md:144`) |
|
||||
|
||||
### 3.5 Mesure sur le corpus (hypothèse de paire par radical `_min` / `_max`)
|
||||
|
||||
- 145 fichiers `.lpcharacter` sous `Content` : 141 sous `Modules`, 4 sous `Saves` (commande 9).
|
||||
- Fichiers contenant au moins une clé `MORPH` se terminant par `_min` : 58 ; par `_max` : 59 ; lignes : 472 et 523 (commande 11).
|
||||
- Fichiers contenant **les deux côtés du même radical** : 0 (ordre `_min` puis `_max`) et 1 (ordre inverse), soit **1 sur 145** (commande 10, deux formulations).
|
||||
- Limites (incertain) : les noms de `MorphTable` ne sont pas lus ; seule une partie des morphs suit la convention de suffixe (`CGREF1-T2-KEYS.csv`, addon `Docs/etat/CG/CGREF1/` : 1 151 lignes dont 101 contiennent `_min` et 108 `_max` d'après `rg -c`, colonnes d'exemples comprises, donc compte indicatif) ; le fichier trouvé peut avoir un des deux côtés à 0 ; les sauvegardes des joueurs hors dépôt ne sont pas mesurées.
|
||||
- Lecture (estimé) : le conflit survient peu dans les fichiers isolés ; il vient de l'empilement (`Blend`, `generatePersonTemporary` à plusieurs noms : `02-format.md:23`) et des tirages d'intervalles.
|
||||
|
||||
### 3.6 Options
|
||||
|
||||
Échelle de coût de `CG2-CART-01.md:35-40` (S ≤ 30 min de MCP, M 0,5 à 2 h, L > 2 h). Le nombre d'écritures est une **estimation** par analogie avec `GIREV-PRE.md` (M1 : 8 à 12 écritures ; charge totale de la révision : 50 à 90). Toute écriture dans `GI` entre dans la révision unique de la build 2.
|
||||
|
||||
| | **A. Garder tel quel** | **B. Règle déterministe documentée** | **C. Groupes exclusifs / normalisation** |
|
||||
|---|---|---|---|
|
||||
| Principe | aucune modification de Blueprint ; la règle actuelle est seulement décrite (guide de moddage, fiche) | la règle « le plus fort gagne » est conservée et **écrite**, avec l'égalité nommée ; trace de journal ; variantes B2 (cheveux) et B3 (égalité neutre) | C1 : valeur nette signée `Max - Min` appliquée à un seul côté (P1 appliqué après coup) ; C2 : exclusivité imposée à **chaque écriture** de morph de `MorphTable` (le dernier écrit gagne) |
|
||||
| Changement Blueprint | aucun | B1 : 1 nœud de journal + 2 concaténations de noms sur les deux branches de `IfThenElse_643` ; B2 : remplacer les 2 `SetMorphTarget` du corps par `Person.setMorphTarget` ; B3 : un test `Max == Min` annulant les deux | C1 : calcul de la différence, choix du côté, 2 `SetMorphTarget` ; C2 : toucher `Person.setMorphTarget` (chemin chaud, D7 `CG2-CART-01.md:50`), la voie directe de `GenerateAndApplyFloats` (`T3b:42`), et lire des graphes non lus (`Randomize*`, `GeneratePerson`) |
|
||||
| Coût (échelle CG2) | 0 | B1 **S**, 8 à 15 écritures ; B2 **S-M**, + 6 à 10 ; B3 **S**, + 4 à 6 | C1 **M**, 15 à 25 ; C2 **L**, 40 à 80 + lectures préalables |
|
||||
| Effet sur les préréglages existants | aucun | B1 aucun (comportement identique) ; B2 : cheveux modifiés quand un conflit existe ; B3 : seules les égalités changent | C1 : **toute** paire en conflit change de valeur (le gagnant n'est plus gardé à sa valeur pleine) ; C2 : tout empilement `Blend` change (le plus récent gagne au lieu du plus fort) |
|
||||
| Effet sur les sauvegardes | aucun | B1 aucun ; B2 / B3 : un personnage rechargé avec un conflit peut changer d'aspect à l'ouverture (fréquence inconnue) | idem, sur un plus grand nombre de cas ; les fichiers eux-mêmes ne sont pas réécrits (la résolution est faite au chargement), l'aspect rechargé peut différer |
|
||||
| Risque | nul sur l'aspect ; la dette de silence reste (`06-rapport-audit.md:69`) | B1 très faible (un message journalisé) ; B2 / B3 faible à moyen selon la fréquence des conflits | moyen à élevé ; C2 s'éloigne du choix « superposition sans moteur de fusion » (`06-rapport-audit.md:144`) |
|
||||
| Bon point | rien à tester ; aucune charge sur la révision de GI | règle lisible pour un moddeur ; la trace mesure enfin la fréquence réelle des conflits ; aucun changement d'aspect en B1 | supprime l'asymétrie et l'état « deux côtés actifs » ; conforme à P1 |
|
||||
| Mauvais point | égalité asymétrique non écrite, cheveux incohérents, silence | ajoute des écritures à la révision de GI ; B2 / B3 changent l'aspect | redéfinit la sémantique de tous les préréglages et mods ; coût disproportionné pour un défaut de gravité « information » |
|
||||
|
||||
**Recommandation (non contraignante) : B1**, avec B2 seulement si un décalage corps / cheveux est constaté en jeu. Raisons : (1) aucune source lue n'impose une règle d'égalité, l'essentiel de la pratique est de **fixer et documenter** une priorité (W10) ; (2) B1 ne change aucun aspect de personnage, donc aucun risque sur les préréglages ni sur les sauvegardes ; (3) la trace donne la mesure qui manque (fréquence des conflits, § 3.5) avant d'envisager C ; (4) coût S, compatible avec la contrainte de révision unique de GI. **A** reste raisonnable si la révision de GI doit rester minimale (D8 est « information », `04-defauts.md:20`). **C** n'est pas recommandé avant la mesure de B1 : il change la sémantique de tout le corpus pour un gain non démontré. Interaction à noter : la décision D9 (morph remis à 0 ou laissé, `CG2-CART-01.md:52`) change les valeurs effectives avant la résolution et donc la fréquence des conflits.
|
||||
|
||||
## 4. Établi / estimé / incertain
|
||||
|
||||
- **Établi** :
|
||||
- la règle, l'égalité, le périmètre « corps seul » et l'absence de journal (`L6f:18214-18300`, `T3b:44-49`) ;
|
||||
- l'appelant unique connu et sa condition (`GI__LoadPreset.txt:410-412`, `:496`) ;
|
||||
- l'usage de `MorphTable` pour les curseurs (`L6f:50274-50316`) ;
|
||||
- le comportement moteur de `SetMorphTarget` / `GetMorphTarget` et le plafond 5,0 (`SkeletalMeshComponent.cpp:4011-4054`, `SkeletalRender.cpp:26-35`) ;
|
||||
- le contenu des pages W1, W2, W3, W4, W6, W8, W9 (page), W10, W11 ;
|
||||
- les comptes des commandes 9 à 11.
|
||||
- **Estimé** :
|
||||
- l'incohérence corps / cheveux (déduite de `T3b:35-41` et `L6f:18240`) ;
|
||||
- « le plus fort gagne, pas le dernier » (déduit de la lecture des seules valeurs finales) ;
|
||||
- l'absence d'autre appelant (aucun dump d'`EventGraph` ne l'appelle ; `GeneratePerson`, `Randomize*` non lus) ;
|
||||
- la rareté des conflits dans les fichiers isolés (hypothèse de paire par radical) ;
|
||||
- les coûts et nombres d'écritures du § 3.6 ;
|
||||
- l'identité des dumps 5.5 et 5.8 de la fonction (même nombre de nœuds, règle identique dans les deux lectures, branches non comparées nœud par nœud).
|
||||
- **Incertain** :
|
||||
- le contenu et la taille de `MorphTable` ;
|
||||
- la raison historique du « corps seul » ;
|
||||
- si les maillages de cheveux possèdent ces morphs ;
|
||||
- si `SavePerson` écrit les valeurs après résolution ;
|
||||
- W5, W12 (résumés seuls), W13 (non lu) ;
|
||||
- la fréquence des conflits en jeu.
|
||||
|
||||
## 5. Points à confirmer (repris par la fiche suivante)
|
||||
|
||||
1. **Contenu de `MorphTable`** : nombre de lignes, nombre de lignes à `Min` renseigné, noms des paires (à garder hors livrable public). Lecture seule par MCP ou par un dump de valeurs par défaut de `GI` ; fonde la mesure de § 3.5.
|
||||
2. **Cheveux** : les assets de cheveux portent-ils les morphs de `MorphTable` ? (liste des morph targets). Tranche l'hypothèse (b) du § 3.1 et l'intérêt de B2.
|
||||
3. **Appelants** : confirmer que `LoadPreset` est l'unique appelant (`Room.LoadPreset` du mode constructeur, `GeneratePerson`, `Randomize*`, `BodyChange`), par `find_nodes` ou dump.
|
||||
4. **Sauvegardes** : `SavePerson` / `SavePreset` écrivent-ils les valeurs lues sur le composant après résolution ? Détermine si un personnage déjà sauvé porte l'état résolu.
|
||||
5. **Fréquence en jeu** : n'est mesurable qu'avec la trace de B1 (aucune trace aujourd'hui). Mesure alternative hors jeu : balayer `Content/Saves` et les dossiers de joueurs avec la liste de paires du point 1.
|
||||
6. **Pages non relues** : W5, W12 (résumés) et W13 (Blender, tronquée) à relire si l'utilisateur veut s'en servir.
|
||||
|
||||
## 6. Questions pour la SPEC ou l'utilisateur
|
||||
|
||||
- **DQ1** : option A, B (B1 seul, ou avec B2 / B3) ou C ? Recommandation : B1.
|
||||
- **DQ2** : à égalité, garder « `Max` annulé » (aucun changement d'aspect, à écrire) ou annuler les deux côtés (neutre, change les seuls cas d'égalité) ?
|
||||
- **DQ3** : étendre la résolution aux cheveux (B2) maintenant, ou seulement après un décalage constaté en jeu ?
|
||||
- **DQ4** : journaliser chaque conflit ? Niveau : journal seul (recommandé), jamais à l'écran (les textes de débogage à l'écran sont déjà un défaut : D18, D19 `04-defauts.md:35-36`).
|
||||
- **DQ5** : écrire la règle (le plus fort gagne, égalité) dans le guide de moddage livré avec le jeu, pour les auteurs de préréglages ? C'est une publication : règle doc 27.
|
||||
- **DQ6** : D8 entre-t-il dans la révision unique de GI (question `GQ5` de `GIREV-PRE.md:246`) ? B1 ajoute environ 8 à 15 écritures à une charge estimée de 50 à 90.
|
||||
|
||||
Tours : 31 / 40 (estimé ; `Tools/FicheStats.py` fait foi)
|
||||
|
||||
## Constats
|
||||
|
||||
- Fichier écrit : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\GIREV\GIREV-D8-RECH.md`. Aucun autre fichier écrit ; aucune lecture n'a modifié un fichier du projet.
|
||||
- Fichiers à commiter : `A Docs/Migration/etat/REL/GIREV/GIREV-D8-RECH.md` (dépôt du jeu, branche `ue5.8`, par le gardien sur ticket).
|
||||
- À verser : `lp-doc` (règle doc 27) — `rg --files -g "*.lpcharacter"` sans `| wc -l` affiche des noms de préréglages à caractère réservé dans la sortie de l'outil : compter, ne pas lister. `lp-commandlets` — `rg --no-ignore --pcre2 -U -l "(?ms)^MORPH ([^:\r\n]+)_min:.*?^MORPH \1_max:"` apparie deux clés d'un même fichier `.lpcharacter` (rétroréférence PCRE2, ripgrep 14.1.1). `lp-cart` — la page Blender du manuel dépasse 200 000 caractères et la partie utile est hors des 100 000 premiers : lire par `offset`.
|
||||
161
Docs/Migration/etat/REL/GIREV/GIREV-MCP-01.md
Normal file
161
Docs/Migration/etat/REL/GIREV/GIREV-MCP-01.md
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
Fiche GIREV-MCP-01 — Niveau N1 — Modèle prévu non précisé par la fiche | utilisé claude-sonnet-5-5 — Agent lp-mcp (lecture seule) — Skills sk-protocol, lp-mcp, sk-change-safety
|
||||
# GIREV-MCP-01 : lecture MCP de GI pour GQ1 (garde D2 de `SavePreset`) et GQ4 (message de F6 / C11) (2026-10-21)
|
||||
|
||||
Lecture seule par `unreal-mcp` (éditeur headless pid 21652, port 8000, jeton de Big Boss ; non lancé, non fermé). Aucune écriture, aucune sauvegarde, aucune compilation. Seul ce fichier est écrit. Préalable : `GIREV-PRE.md` § 3.2 M2, M4, § 5 points 1 et 4, § 6 GQ1 et GQ4. Décisions de l'utilisateur citées par l'ordonnateur : GQ1 « oui » (établir le rôle de la garde avant de décider), GQ4 « on le rebranche et on évalue ».
|
||||
|
||||
Notation : `EG` = `/Game/BPs/GI.GI:EventGraph`, `SP` = `/Game/BPs/GI.GI:SavePreset`.
|
||||
|
||||
## Résumé (à lire en premier)
|
||||
|
||||
1. **GQ1 : la garde D2 est inerte aujourd'hui et redondante** (établi pour l'inertie, estimé pour le rôle). Le littéral est `Characters\0.lpcharacter` (un antislash, une extension) ; **aucun** des 11 appelants lus ne passe un `File` de cette forme (tous : séparateur `/`, pas d'extension, ou nom saisi par le joueur). Le rôle voulu probable : ne jamais écrire le fichier du « slot 0 ». Cette protection existe déjà, effective, en amont : `SaveSlot > 0` dans `DestroyPerson` (`IfThenElse_436`) et dans `SavePerson` (`IfThenElse_18`). Recommandation : **(a) laisser** (0 écriture) ; (b) supprimer reste neutre ; (c) corriger le littéral change le comportement du seul appelant non gardé (`ContactMenu`) et n'a pas de rôle prouvé.
|
||||
2. **GQ4 : le message n'est pas du code mort** (établi). `K2Node_CallFunction_20748` (`ShowTutorial`, String) et `K2Node_CallFunction_13122` (`PrintString`) sont bien orphelins (`execute` sans liaison), **mais** `K2Node_CallFunction_340` (`ShowTutorialTxt`, même titre, même contenu, `Force` et `Warning` à `true`) est atteint par `IfThenElse_2861.else` : le message « missing crucial *.lpcharacter files » **s'affiche déjà** quand le chargement d'une partie ne lit rien dans `Player.lpcharacter`. La prémisse de GIREV-PRE M2 (« le message deviendrait atteignable ») est donc fausse pour le texte visible ; elle est vraie seulement pour le `PrintString` de journal.
|
||||
3. **Conséquence pour « on le rebranche »** : rebrancher `_20748` ferait afficher le message **deux fois** (établi par les liaisons). Les trois voies utiles sont au § B.5 ; recommandation : supprimer `_20748` et `_13122` (C11) et **réécrire le texte de `_340`** (2 `set_pin_value` sur des broches Text, faisabilité à confirmer).
|
||||
|
||||
## 1. Appels MCP (tous en lecture, dans l'ordre)
|
||||
|
||||
| # | Appel (toolset / outil) | Arguments | Résultat |
|
||||
|---|---|---|---|
|
||||
| 1 | `list_toolsets` | — | liste complète, `editor_toolset.toolsets.blueprint.BlueprintTools` présent : connexion établie |
|
||||
| 2 | `AssetTools.load_asset` | `/Game/BPs/GI` | `/Game/BPs/GI.GI` |
|
||||
| 3 | `BlueprintTools.get_node_infos` | `SP.K2Node_IfThenElse_2970`, `SP.K2Node_CallFunction_19325` | liaisons et littéral (§ A.1) |
|
||||
| 4 | `BlueprintTools.find_nodes` | `EG`, titre `SavePreset` | `_104`, `_16676`, `_8085` |
|
||||
| 5 | `get_node_infos` | ces 3 nœuds | broches `File`, `Var`, `StatOnly`, `IncludeStat` |
|
||||
| 6 | `get_node_infos` | `EG` `Concat_12`, `_2523`, `_827` | littéraux de `File` |
|
||||
| 7 | `get_node_infos` | `EG` `Concat_698`, `VariableGet_87`, `CallFunction_105`, `VariableGet_19305`, `CallFunction_8086` | `Saves/` + `Slot` + `/Characters/`, `Prefix`, `ToString(SaveSlot)` |
|
||||
| 8 | `get_graphs` (outil inexistant : « Unknown tool get_graphs ») puis `ObjectTools.list_properties` (refusé : paramètre `instance` manquant) | — | rien utilisé ; la liste des graphes de GI est tirée des dumps (§ A.2) |
|
||||
| 9-11 | `find_nodes` titre `SavePreset` | `GI:GeneratePerson`, `GI:GenerateCreature`, `GI:saveOldPlayer` | 2, 1, 1 appelants |
|
||||
| 12-13 | `get_node_infos` | `saveOldPlayer.CallFunction_1`, `GeneratePerson` `_20437`, `_684`, `GenerateCreature` `_684` ; leurs `Concat_2411` / `_827` | `File` |
|
||||
| 14 | `get_node_infos` | `GeneratePerson.CallFunction_4486`, puis `MacroInstance_1386` | `ToString` d'un `IncrementInt` |
|
||||
| 15-19 | `find_nodes` titre `SavePreset` | `/Game/UI/StatMenu`, `/Game/UI/ContactMenu`, `/Game/BPs/Room`, `/Game/UI/CharGen`, `/Game/UI/Builder` (graphe `EventGraph`) | 1, 1, 1 (événement), 1, 1 |
|
||||
| 20 | `get_node_infos` | les 5 nœuds ci-dessus | `Room` et `Builder` = événement `SavePreset` de `Room`, pas celui de GI |
|
||||
| 21-22 | `get_node_infos` | `StatMenu`/`CharGen` `CallFunction_5136`, `_5135` ; `ContactMenu` `Concat_827`, `CallFunction_8086` | `File` = texte du champ (StatMenu, CharGen) ; `Saves/_session/Characters/` + `VariableGet_4523` + `ToString` (ContactMenu) |
|
||||
| 23 | `get_node_infos` | `EG.IfThenElse_436`, `_4453`, `_39` | garde `SaveSlot > 0` de `DestroyPerson` |
|
||||
| 24 | `get_node_infos` | `EG` `_20748`, `_13122`, `_340`, `IfThenElse_2861` | broches du message (§ B.1) |
|
||||
| 25 | `get_node_infos` | `EG` `CallFunction_177`, `IfThenElse_2377`, `CallFunction_213` | condition `Len(...) > 0`, branche `Load` |
|
||||
| 26 | `get_node_infos` | `EG` `CallFunction_176`, `CustomEvent_17`, `Concat_15` | événement `DuplicateCharacters(Load, Slot)`, chemin `Player.lpcharacter` |
|
||||
| 27 | `get_node_infos` | `EG` `CallFunction_173`, `_408`, `_13784`, `VariableSet_541` | `LoadTxt` (ModdingExtra), `LoadPreset`, `SaveTxt` |
|
||||
| 28 | `find_nodes` | `EG`, titre `DuplicateCharacters` | `CustomEvent_17`, `CallFunction_14865`, `CallFunction_14866` |
|
||||
| 29 | `get_node_infos` | `CallFunction_14865`, `_14866` ; `CustomEvent_955`, `_16` | appelants : événements `LoadGame` et `SaveGame` |
|
||||
|
||||
Lectures hors MCP : Read `GIREV-PRE.md` ; `rg -a -l` sur `Content`, `Source`, `Plugins`, `Saved` ; `rg --no-ignore -a` sur les dumps `STE-ORG4cV_LPDumpFunction_20261014-103731.txt` (« GEV »), `STE-H10V_…20261013-071350.txt`, `L6f_dump_GI.txt` (5.5) ; Read `STE-H10-SPEC.md:160-200`.
|
||||
|
||||
## A. GQ1 : garde D2 de `SavePreset`
|
||||
|
||||
### A.1 Liaisons et valeur exacte (appels 3, établi)
|
||||
|
||||
- `SP.K2Node_IfThenElse_2970` : `execute` ← `FunctionEntry_799`.then ; `Condition` ← `CallFunction_19325`.ReturnValue ; **`then` : aucune liaison** (la fonction s'arrête) ; `else` → `IfThenElse_10253`.execute.
|
||||
- `SP.K2Node_CallFunction_19325` (`Utilities|String|EndsWith`) : `SourceString` ← `FunctionEntry_799`.pin 1 (`File`) ; `InSuffix` = `Characters\0.lpcharacter` (le dump JSON montre `"Characters\\0.lpcharacter"`, soit **un seul antislash**) ; `SearchCase` = `IgnoreCase`.
|
||||
- Conclusion de lecture : la garde ne vaut que pour un `File` finissant littéralement par `Characters\0.lpcharacter`, c'est-à-dire avec antislash **et** extension.
|
||||
|
||||
### A.2 Appelants de `SavePreset` de GI et valeur de `File` (appels 4-7, 9-22, établi)
|
||||
|
||||
Recherche : `find_nodes` titre `SavePreset` sur le graphe de chaque BP, plus `rg -a -l SavePreset Content` (BP contenant la chaîne : `GI`, `StatMenu`, `ContactMenu`, `Room`, `CharGen`, `Builder` ; **aucun** dans `Person`, `PC`, `MainMenu`). Les graphes de fonction de GI viennent du dump 5.5 (`L6f_dump_GI.txt:17470`, `:17701`, `:36223`, `:37957` → `GeneratePerson` ×2, `GenerateCreature`, `saveOldPlayer`) puis relus par MCP. Les graphes de fonction de `StatMenu`, `ContactMenu`, `CharGen` n'ont pas été énumérés (aucun outil de liste de graphes trouvé, appel 8) : un appelant dans une fonction de ces trois BP reste possible (incertain).
|
||||
|
||||
| # | Appelant (nœud) | `File` | Extension / séparateur | Garde D2 déclenchée ? |
|
||||
|---|---|---|---|---|
|
||||
| 1 | `EG.CallFunction_104` (dans `DestroyPerson`, `CustomEvent_3172`) | `Saves/_session/Characters/` + `Prefix` + `ToString(SaveSlot)` (`Concat_12`) | `/`, sans extension | non |
|
||||
| 2 | `EG.CallFunction_8085` (événement `SavePerson`, `CustomEvent_32`) | idem (`Concat_827`) | idem | non ; précédé de `IfThenElse_18` ← `Greater_IntInt(SaveSlot, 0)` (`CallFunction_2016`, dump `STE-ORG4cV:18040`) : jamais pour le slot 0 |
|
||||
| 3 | `EG.CallFunction_16676` (dans `DuplicateCharacters`, branche `Load` = faux) | `Saves/` + `Slot` + `/Characters/` + `Player` (`Concat_698` puis `_2523`) | `/`, sans extension | non |
|
||||
| 4 | `GeneratePerson.CallFunction_20437` | `Saves/_session/Characters/` + `ToString(IncrementInt)` (`Concat_2411`, `CallFunction_4486`, `MacroInstance_1386`) | `/` | non ; compteur incrémenté donc ≥ 1 (estimé : valeur initiale non lue) |
|
||||
| 5 | `GeneratePerson.CallFunction_684` | `Saves/_session/Characters/F` + chaîne (`Concat_827`) | `/` | non |
|
||||
| 6 | `GenerateCreature.CallFunction_684` | `Saves/_session/Characters/C` + chaîne | `/` | non |
|
||||
| 7 | `saveOldPlayer.CallFunction_1` | littéral `Saves/_session/Characters/OldPlayer` | `/` | non |
|
||||
| 8 | `StatMenu.EventGraph.CallFunction_5375` | texte du champ `TextBox` (`GetText` → `ToString`), `StatOnly` = vrai | libre (saisie du joueur) | non, sauf saisie volontaire du suffixe exact |
|
||||
| 9 | `CharGen.EventGraph.CallFunction_5375` | idem, `StatOnly` = faux, `IncludeStat` ← `EnumEquality_0` | libre | idem |
|
||||
| 10 | `ContactMenu.EventGraph.CallFunction_509` | `Saves/_session/Characters/` + `VariableGet_4523` + `ToString(…)` (`Concat_827`, `CallFunction_8086` ← `VariableGet_3021`) | `/` | non ; **seul appelant non gardé par `SaveSlot > 0` identifié** : la valeur de `VariableGet_3021` et la condition `CallFunction_72` n'ont pas été relues (incertain) |
|
||||
| — | `Room.CustomEvent_15` et `Builder.CallFunction_27` | n'appellent pas `GI.SavePreset` : événement `SavePreset(Path)` **propre à `Room`** | — | sans objet |
|
||||
|
||||
Aucun appelant ne passe un `File` avec antislash ni avec l'extension : le suffixe de la garde ne peut correspondre qu'à une saisie volontaire (et CG2 C7 filtre déjà `..`, `/`, `\` côté `CharGen`, `GIREV-PRE.md` § 3.2 M5).
|
||||
|
||||
### A.3 Qui crée, lit ou utilise `Characters/0.lpcharacter` (établi pour les absences, estimé pour le sens)
|
||||
|
||||
- **Existence sur disque** : `Content/Saves/` contient `Default/Characters/Player.lpcharacter` et `_session/Characters/{1,2,3}.lpcharacter` ; aucun `0.lpcharacter` (`find` sur `Content/Saves`). `Saved/Saves` absent de ce dépôt. Aucun fichier `*0.lpcharacter` ailleurs : `rg -a -l "0\.lpcharacter"` sur `Content`, `Source`, `Plugins`, `Saved/Saves`, `Docs` ne répond que `GI.uasset` et des dumps/fiches (`STE-H10-SPEC.md:176`, dumps `STE-H10V`, `STE-D9`, `L6f`). Aucune occurrence dans `Content/Modules` pour ce nom (la seule mention de `lpcharacter` y est `vin_Interracial/scenes/set_stereotypes.lpscene`) ; `Source` : seule mention `LPStringCompat.h:9` (commentaire sur les 141 préréglages).
|
||||
- **Journal du build COM21** (`COMMUN-21-BILAN.md:40`) : après une session, `Saved\Saves\_session\Characters\1.lpcharacter` créé ; relevé à 3 fichiers, aucun `0`.
|
||||
- **Le joueur n'est pas le slot 0** : le joueur est enregistré sous `…/Characters/Player` (appelant 3, `Concat_15` ajoute `Player.lpcharacter` : `EG.CommutativeAssociativeBinaryOperator_15.B` = `Player.lpcharacter`) et `Default/Characters/Player.lpcharacter` ; l'ancien joueur sous `OldPlayer` (appelant 7). Le slot 0 (`Prefix` vide, `SaveSlot` 0) est donc une personne sans emplacement attribué (estimé : l'unité de test `STA-T2b-PERSON-DIAG.md:203` lie `Len(Prefix) == 0` aux « numérotés » 1, 2, 3…).
|
||||
- **Qui écrirait `0.lpcharacter`** : un appel de `SavePreset` avec `Prefix` vide et `SaveSlot` 0 (cas des appelants 1, 2, 10) ; `SP.Append_762` ajoute `.lpcharacter` après la garde (`GIREV-PRE.md` § 3.2 M5), donc le fichier produit serait bien `Saves/_session/Characters/0.lpcharacter`. Les appelants 1 et 2 sont fermés au slot 0 par `SaveSlot > 0` : `DestroyPerson` — `EG.IfThenElse_436` (`Condition` ← `CallFunction_106`, `A` ← `VariableGet_86`.SaveSlot dans le dump `STE-ORG4cV:6474`) : `then` → `IfThenElse_39` (chaîne vers la sauvegarde), `else` → `IfThenElse_4453` → `IfThenElse_1766` (suite après `RestoreCbe`, `STE-H10-SPEC.md:172`) ; la seule liaison d'exécution vers `CallFunction_104` vient de `IfThenElse_216.then` et `VariableSet_393.then` (appel 5, établi). Que `CallFunction_106` soit bien `Greater_IntInt(SaveSlot, 0)` n'a pas été relu (estimé d'après `STE-H10-SPEC.md:168`).
|
||||
- **Qui lit `0.lpcharacter`** : aucun lecteur trouvé. Les lectures de personnage passent par `LoadPreset` (`CallFunction_213`, `_408`, chemin `…/Player.lpcharacter`) ; aucun chemin `Characters/0` dans les dumps.
|
||||
|
||||
### A.4 Conclusion GQ1
|
||||
|
||||
- **Rôle voulu probable (estimé)** : empêcher l'écriture d'un fichier « slot 0 » par `SavePreset`. La forme du littéral (antislash, extension complète) évoque une version ancienne où `File` était un chemin complet de fichier Windows ; la fonction a ensuite reçu l'extension en interne (`Append_762`), ce qui a rendu la garde inopérante.
|
||||
- **Se déclenche-t-elle aujourd'hui ?** Non : établi pour les 10 appelants lus (§ A.2) ; incertain pour d'éventuels appelants dans des fonctions de `StatMenu`/`ContactMenu`/`CharGen` non énumérées et pour la valeur de `SaveSlot` côté `ContactMenu`.
|
||||
- **Effets** :
|
||||
- **(a) laisser** : aucun changement ; la garde reste un code inerte de 2 nœuds ; 0 écriture MCP. Le slot 0 est déjà protégé par `SaveSlot > 0` (appelants 1, 2).
|
||||
- **(b) supprimer** : comportement inchangé tant que la garde est inerte (établi par A.2) ; coût estimé 5 écritures (`break_pins` ×2 sur `IfThenElse_2970`, `connect_pins` `FunctionEntry_799` → `IfThenElse_10253`, `delete_node` ×2) ; perte d'une défense dormante si un appelant futur passe cette forme.
|
||||
- **(c) corriger le littéral** (par exemple `Characters/0` sans extension) : **change le comportement** pour tout `File` finissant ainsi, c'est-à-dire pour l'appelant 10 (`ContactMenu`) s'il passe un slot 0 avec préfixe vide : il n'écrirait plus `0.lpcharacter`. Effet inconnu faute de preuve que ce cas se présente ; `set_pin_value` seul ne marque pas le paquet (`GIREV-PRE.md` § 3.9). **Non recommandé.**
|
||||
- **Recommandation : (a)**, éventuellement (b) si l'utilisateur veut supprimer le code mort ; (c) seulement si un test montre qu'un `0.lpcharacter` est produit en jeu (essai : build Development, parcours `ContactMenu` sur une personne de slot 0, relevé de `Saved\Saves\_session\Characters\`).
|
||||
|
||||
## B. GQ4 : message de F6 / C11
|
||||
|
||||
### B.1 Broches lues (appel 24, établi)
|
||||
|
||||
| Nœud | `execute` | `then` | Valeurs |
|
||||
|---|---|---|---|
|
||||
| `EG.K2Node_CallFunction_20748` (`|ShowTutorial`, String) | **aucune liaison** | aucune | `Title` = `Save Missing Character Data!` ; `Content` = `The save you just loaded is missing crucial *.lpcharacter files. Please copy your old LifePlay\Content\Saves folder into the directory of the current version of the game. You can Alt Tab and do this copying (no need to exit the game), then try load the save again.` ; `Force` = true ; `Warning` = true |
|
||||
| `EG.K2Node_CallFunction_13122` (`Development|PrintString`) | **aucune liaison** | → `CallFunction_340`.execute | `InString` = `Missing characters from save` ; `bPrintToScreen` = true ; `bPrintToLog` = true ; `TextColor` = (R=0, G=0.66, B=1, A=1) ; `Duration` = 2.0 ; `Key` = None |
|
||||
| `EG.K2Node_CallFunction_340` (`|ShowTutorialTxt`, Text) | ← `13122`.then **et** `IfThenElse_2861`.else | aucune | `Title` = NSLOCTEXT « Save Missing Character Data! » ; `Content` = NSLOCTEXT, **même texte** que `_20748` ; `Force` = true ; `Warning` = true |
|
||||
|
||||
Code mort : `_20748` et `_13122` (aucun `execute` entrant). **Pas code mort : `_340`**, atteint par `2861.else` ; `ShowTutorialTxt` convertit ses deux Text en String et appelle `ShowTutorial` avec `Force` et `Warning` (`STE-ORG4cV…:18487-18516`, `CustomEvent_33`, `CallFunction_136/137/138`). Donc l'écran du message est identique à celui que produirait `_20748`.
|
||||
|
||||
### B.2 Contexte amont (appels 24-29, établi)
|
||||
|
||||
Fonction : événement personnalisé `DuplicateCharacters(Load: bool, Slot: string)` (`EG.CustomEvent_17`), appelé par :
|
||||
- `CallFunction_14865` avec `Load` = true, `Slot` ← `CustomEvent_955` (événement `LoadGame(Name, Index)`) ;
|
||||
- `CallFunction_14866` avec `Load` = false, `Slot` ← `CustomEvent_16` (événement `SaveGame(Name, Index, Notes)`).
|
||||
|
||||
Chaîne (`Load` = vrai) : `IfThenElse_2377` (`Condition` ← `CustomEvent_17`.Load) `then` → **`IfThenElse_2861`** (`Condition` ← `CallFunction_177` = `Len(...) > 0`, B = 0 ; `A` ← `CallFunction_176` = `Len(S)` ; `S` ← `CallFunction_173`.`SaveTextA` = `LoadTxt`(`FileNameA` = `Append_15`) ; `Append_15` = `Saves/<Slot>/Characters/` + `Player.lpcharacter`) :
|
||||
- `then` (texte non vide) → `CallFunction_213` (`LoadPreset`, même `Path`, `Blend` = faux) → `CallFunction_408` (`LoadPreset`, `Blend` = vrai) ;
|
||||
- **`else`** (texte vide : fichier absent ou illisible) → `CallFunction_340` : le message.
|
||||
`2377.else` (`Load` = faux) → `CallFunction_16676` (`SavePreset` du joueur).
|
||||
|
||||
Sens de la condition « personnages manquants » (établi pour la lecture, estimé pour l'intention) : le chargement d'une partie ne rend aucune lecture de `Saves/<Slot>/Characters/Player.lpcharacter`. Seul le fichier du joueur est testé, pas les numérotés `1.lpcharacter`, `F…`, `C…` (le texte dit « missing crucial *.lpcharacter files » au pluriel : estimé, c'est le fichier crucial qui sert de témoin).
|
||||
|
||||
### B.3 Le message est-il déjà vu aujourd'hui ?
|
||||
|
||||
- Oui, sur un chargement dont `Player.lpcharacter` est absent de toutes les racines : **atteignable** (établi par les liaisons). Aucune preuve qu'il se soit présenté : le journal COM23 ne porte ni son texte ni `Missing characters` (`GIREV-PRE.md` n° 23) ; le bilan COM21 n'a relevé aucun `LoadTxt ECHEC` autre que `OldPlayer` et `ModLauncher.config` (`COMMUN-21-BILAN.md:53`, `:66`), donc `Player.lpcharacter` a été lu.
|
||||
- Avec F6 (`FIX1-F6-SPEC.md:33`) la lecture de `Saves/<Slot>/…` prend `<Saved>/Saves/<Slot>` si le dossier existe, sinon `<Content>/Saves/<Slot>`, sinon `<Saved>` : un ancien emplacement de `Content/Saves` est donc toujours lu (repli). Le message n'apparaît qu'en l'absence du fichier dans ces racines.
|
||||
|
||||
### B.4 Faux positifs et fréquence (estimé, aucun essai)
|
||||
|
||||
- Une partie enregistrée par ce jeu écrit toujours `Player.lpcharacter` : `SaveGame` → `DuplicateCharacters(Load=false)` → `SavePreset` (appelant 3). Pas de faux positif pour une partie créée par la build courante (non essayé en jeu).
|
||||
- Un `LoadGame` de partie « neuve » : la nouvelle partie utilise `Content/Saves/Default/Characters/Player.lpcharacter` (présent au dépôt) ; que la nouvelle partie passe par `LoadGame("Default")` n'est pas établi (appelants de `LoadGame` non lus). Pas de faux positif si `Default` est lu avec repli.
|
||||
- Partie sans personnage : le message se déclenche, comme voulu (le texte parle de fichiers manquants).
|
||||
- Fréquence attendue : rare (partie copiée d'une autre version sans `Characters`, dossier supprimé, ou slot renommé). Le jeu écrit déjà `LoadTxt ECHEC | '<chemin>'` au journal dans ce cas (`COMMUN-21-BILAN.md:66`) : le `PrintString` ajouterait une seconde trace.
|
||||
|
||||
### B.5 Où « rebrancher » et ce que cela donnerait (propositions, estimé)
|
||||
|
||||
| Voie | Écritures MCP | Effet visible | Remarque |
|
||||
|---|---|---|---|
|
||||
| **V1. Relier `_20748`** (la demande littérale) | 2 (`connect_pins` d'un `execute` vers `_20748`, par exemple `2861.else`, puis rupture de `2861.else` → `_340`) | le même message **deux fois** si les deux restent reliés ; une fois si `_340` est coupé | n'apporte rien : `_340` est déjà ce nœud. **Non recommandé.** |
|
||||
| **V2. Relier seulement le `PrintString` `_13122`** | 2 : `break_pins` (`2861.else` → `_340`.execute) et `connect_pins` (`2861.else` → `_13122`.execute) ; `_13122.then` → `_340` déjà relié | message à l'écran inchangé + ligne de journal `Missing characters from save` (Development) + texte bleu 2 s à l'écran (`PrintString` n'imprime rien en Shipping, `CG2-SPEC-01.md:115`) | trace redondante avec `LoadTxt ECHEC` ; `Key` = None : s'empile |
|
||||
| **V3 (recommandée). Supprimer `_20748` et `_13122`, réécrire le texte de `_340`** | 2 `delete_node` (+ 1 `break_pins` implicite) puis 2 `set_pin_value` (broches Text `Title`, `Content` de `_340`) | message corrigé au prochain chargement manquant ; aucune autre différence | la clé NSLOCTEXT (`[3787EBBA…]`, `F9D9C9AF…`) peut être perdue ou conservée selon le comportement du MCP sur une broche Text : **incertain** (essai éditeur sur une copie). Les suppressions marquent le paquet ; `set_pin_value` seul ne le ferait pas (`GIREV-PRE.md` § 3.9). |
|
||||
|
||||
Nouveau texte proposé (à valider, adapté à la redirection F6 vers `Saved/Saves`, `FIX1-F6-SPEC.md:32-33`) :
|
||||
- `Title` : conserver `Save Missing Character Data!`.
|
||||
- `Content` : `The save you just loaded is missing crucial *.lpcharacter files. Saves are now kept in LifePlay\Saved\Saves. If this save comes from an older version, copy its folder from your old LifePlay\Content\Saves (the folder named like the save) into LifePlay\Saved\Saves of the current version, then try to load the save again. You can Alt Tab and do this copying (no need to exit the game).`
|
||||
- `Force` = true, `Warning` = true : inchangés (valeurs actuelles de `_340`) ; aucune raison établie de les modifier.
|
||||
|
||||
Évaluation chiffrée (estimé) : V3 = 4 à 5 écritures, risque très faible (suppression de nœuds sans exécution entrante), une seule différence visible pour le joueur : le texte, uniquement dans le cas où le message s'affiche déjà. Preuve : relecture `get_node_infos` de `_340` et compilation ; en jeu, un chargement volontairement sans `Player.lpcharacter` (copie d'essai d'un slot, fichier renommé) lit l'écran et le journal (`LoadTxt ECHEC` attendu).
|
||||
|
||||
## C. Établi / estimé / incertain
|
||||
|
||||
**Établi (appels MCP cités)** : littéral, liaisons et `then` vide de la garde (appel 3) ; `File` de 10 appelants (appels 5-7, 12-14, 21-22) ; `Room`/`Builder` n'appellent pas `GI.SavePreset` (appel 20) ; `_20748` et `_13122` sans `execute` entrant, `_340` atteint par `2861.else`, textes et valeurs (appel 24) ; condition `Len(LoadTxt(Saves/<Slot>/Characters/Player.lpcharacter)) > 0` et appelants `LoadGame` / `SaveGame` (appels 25-29) ; `ShowTutorialTxt` = `ShowTutorial` après conversion (dump `STE-ORG4cV:18487-18516`) ; aucun `0.lpcharacter` dans les dossiers et sources cherchés.
|
||||
|
||||
**Estimé** : rôle de la garde (écriture du slot 0 interdite) ; slot 0 sans emplacement attribué ; `CallFunction_106` = `SaveSlot > 0` ; compteur de `GeneratePerson` ≥ 1 ; fréquence et faux positifs du message ; nombre d'écritures.
|
||||
|
||||
**Incertain (essai qui trancherait)** : appelants de `SavePreset` dans les fonctions de `StatMenu`, `ContactMenu`, `CharGen` (lister leurs graphes, `rg --no-ignore` sur de futurs dumps `LPDumpFunction -Fn=*`) ; valeur de `SaveSlot` et condition `CallFunction_72` côté `ContactMenu` (lire `VariableGet_3021`, `_4523`) ; conservation de la clé NSLOCTEXT par `set_pin_value` (essai sur une copie) ; si la nouvelle partie passe par `LoadGame("Default")` (lire les appelants de `CustomEvent_955`) ; fin de la chaîne `IfThenElse_1766` (non suivie).
|
||||
|
||||
## D. Écarts à la fiche et à GIREV-PRE
|
||||
|
||||
- **GIREV-PRE M2 est à corriger** : `_20748` n'est pas « le message affiché » mais un doublon mort de `_340` (qui l'est). « Le message deviendrait atteignable » (§ 3.2 M2) est faux pour l'écran ; la décision GQ4 « on le rebranche » repose sur cette prémisse : à re-soumettre à l'utilisateur avec V1/V2/V3.
|
||||
- GIREV-PRE M4 écrit que le suffixe a un antislash : confirmé (un seul).
|
||||
- Appel 8 : `get_graphs` n'existe pas et `list_properties` demande `instance` ; la liste des graphes n'a pas été obtenue par MCP (sans conséquence sur les chiffres de GI, tirés des dumps puis relus).
|
||||
|
||||
## Fichiers
|
||||
|
||||
- Écrit : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\GIREV\GIREV-MCP-01.md`.
|
||||
- À commiter : `A Docs/Migration/etat/REL/GIREV/GIREV-MCP-01.md` (par le gardien, sur ticket). Aucun autre fichier écrit ; éditeur laissé ouvert (pid 21652).
|
||||
|
||||
Tours : 36 / 40 (comptés à la main ; `python -I Tools/FicheStats.py --lot GIREV` fait foi)
|
||||
|
||||
À verser : `lp-mcp` § 3 — dans un BP, `find_nodes {graph:{refPath:"/Game/UI/X.X:EventGraph"}, title}` fonctionne sans `load_asset` préalable ; `get_graphs` n'existe pas ; un événement personnalisé et un appel peuvent porter le même nom (ex. `Room.SavePreset` ≠ `GI.SavePreset`) : lire le `type_id` du nœud (`Presets|SavePreset` pour GI, `AddEvent|Custom|SavePreset` ou `|SavePreset` pour Room). Avant de déclarer un nœud de message « mort », chercher son jumeau de type Text (`ShowTutorialTxt`) : il peut porter le même texte et être vivant.
|
||||
258
Docs/Migration/etat/REL/GIREV/GIREV-PRE.md
Normal file
258
Docs/Migration/etat/REL/GIREV/GIREV-PRE.md
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
Fiche GIREV-PRE — Niveau N2+ — Modèle prévu non précisé par la fiche | utilisé claude-sonnet-5-5 — Agent lp-cart — Skills sk-protocol, ue-cpp-build, lp-commandlets, lp-paths
|
||||
# GIREV-PRE : étude préliminaire de la révision unique de `GI.uasset` (liste, ordre, dumps, découpage, retour arrière) (2026-10-20)
|
||||
|
||||
Hors gabarit : la rubrique 3 est subdivisée (3.1 à 3.10) pour porter la liste ordonnée, les dumps à produire, le découpage, la durée et le retour arrière demandés par la fiche. Lecture seule : ni copie UE, ni MCP, ni éditeur, ni commandlet. Seul ce fichier est écrit. Descriptions neutres (doc 27) : les noms de sections et de morphs réservés ne sont pas cités. Les questions de cette étude sont numérotées `GQ1` à `GQ9` pour ne pas les confondre avec les Q7 et Q8 de CG2, le Q7 de KEY2 et le Q7 de FIX1-F6.
|
||||
|
||||
Ordre de l'utilisateur, cité : « Lance l'étude de la révision unique de GI (liste et ordre des modifications) » (`BOSS-JOURNAL.md:1056`). Règle : `GI.uasset` n'est révisé qu'une fois, en build 2 (`BOSS-JOURNAL.md:693`, `:870`).
|
||||
|
||||
## Résumé (à lire en premier)
|
||||
|
||||
1. **La liste de la fiche n'est pas entièrement dans GI** (établi, § 3.3). C8, Q7, Q8 et R7 visent `CharGen` ; le remappage de Y/N vise `PC` ; ERR-145 n'a pas de cause établie. Ces six points sortent de la révision de GI. Restent dans GI : C10, C11, D2, D9, D17, ERR-142, F7a, le message de F6 et les deux commandes de console.
|
||||
2. **Le message de F6 et C11 sont le même nœud** (établi pour la position, § 3.2 M2) : le texte « copy your old … Content\Saves … » est le champ `Content` du nœud `K2Node_CallFunction_20748`, que C11 supprime parce qu'il est orphelin (aucune liaison d'exécution dans le dump 5.8 du 2026-10-13). Les fiches F6 le traitent comme un message affiché : contradiction à lever avant d'écrire (GQ4).
|
||||
3. **D17 est en grande partie déjà couvert par le C++** (établi, § 3.2 M6) : le nœud appelle un assistant C++ qui journalise un avertissement pour tout chemin non résolu. Il ne reste que le cas « asset trouvé mais pas une texture ».
|
||||
4. **D9 est bloqué par deux inconnues** : la décision de comportement n'est pas prise (R06 § 5.5 n° 2) et la capacité du MCP à créer une variable locale n'est pas connue (§ 3.2 M8).
|
||||
5. **Dumps 5.8** : le dump EventGraph de GI du 2026-10-14 10:38 est postérieur à la dernière sauvegarde de GI (10:33) et reste utilisable tant que le MD5 vaut `32fc0a97…`. Trois dumps manquent ou sont à rafraîchir : `SavePreset`, `GenerateAndApplyFloats`, `CalculateHeadtrack` (§ 3.7).
|
||||
6. **Ordre** : préparation, puis EventGraph (M1, M2, M6), `SavePreset` (M3, M4, M5), enfin les fonctions à effet (M7, M8), clôture (§ 3.6). **Trois sous-lots** d'au plus 50 tours dans une seule session d'éditeur et un seul instantané (§ 3.8). Charge estimée : 50 à 90 écritures relues (§ 3.9).
|
||||
|
||||
## 1. Objet et périmètre
|
||||
|
||||
Un domaine : établir la liste exacte et ordonnée des modifications de `Content/BPs/GI.uasset` à faire en un seul passage (build 2, `2026.11.3.1a` vers le 3 novembre, `BOSS-ETAT.md:106`), avec nœuds, nature, dépendances, risque, voie, preuve en jeu, dumps préalables, découpage, durée et retour arrière. Sources demandées : lot CG2 (CART, SPEC, TACHES, IMPL, VAL, DOC), référentiel CG de l'addon, ERR-142, KEY2, FIX1-F7-PRE, FIX1-F6-SPEC, QPERS-PRE, BOSS-ETAT « Reports en build 2 », CAM2. Hors périmètre : toute écriture, tout essai, la décision sur chaque point.
|
||||
|
||||
## 2. Commandes et lectures (exactes) avec compte brut
|
||||
|
||||
| # | Commande ou lecture | Résultat brut |
|
||||
|---|---|---|
|
||||
| 1 | Read `lp-doc/gabarits.md` (CART) | gabarit lu |
|
||||
| 2 | Read `BOSS-ETAT.md:100-160`, `BOSS-JOURNAL.md:690-695`, `:767`, `:868-872` ; Grep `revision unique de GI[^|]{0,200}` dans `BOSS-JOURNAL.md` | `:1056` (ordre de l'utilisateur) ; autres lignes citées en § 3 |
|
||||
| 3 | Read `37_Feuille_De_Route_Alpha2.md:100-189` | § 2.7 = `:148-151` (ne liste pas C8, C10…) |
|
||||
| 4 | Read `CG2-SPEC-01.md` (226 l.), `CG2-IMPL-01.md:140-249`, `CG2-TACHES.md:15-64` et `:72`, `CG2-CART-01.md:1-140` | cités en § 3 |
|
||||
| 5 | Grep `CG2-VAL-01.md`, `CG2-DOC-01.md` (`GI.uasset`, `B2`, `C10`…) | VAL `:32-35`, `:143-144`, `:184` ; DOC `:33-35` |
|
||||
| 6 | Read `CGREF1-T3-MCP.md:55-102`, `CGREF1-T3c-MCP.md:56-71`, `CGREF1-T7-TEST.md:14-53` (addon, `Docs/etat/CG/CGREF1/`) | nœuds `SavePreset`, `LoadDefaultTextures`, `GenerateAndApplyFloats` |
|
||||
| 7 | Grep `Registre_Erreurs.md` `ERR-142\|ERR-145` ; Read `:49`, `:152` | `:149` (ERR-142), `:152` (ERR-145), `:49` (ERR-042) |
|
||||
| 8 | Grep `\bR7\b` dans `etat/REL/KEY2`, puis dans `etat` | KEY2 : aucun ; sens trouvé : `BOSS-JOURNAL.md:767`, `CG2-TACHES.md:72` |
|
||||
| 9 | Read `FIX1-F7-PRE.md`, `FIX1-F6-SPEC.md`, `QPERS-PRE.md` (entiers) | cités en § 3 |
|
||||
| 10 | Grep `KEY2` (`GI\.uasset\|build 2\|Y/N\|remapp`) ; Grep `\bGI\b` dans `KEY2-SPEC-02.md` (compte) | KEY2-SPEC-01 `:34`, `:246` ; KEY2-TACHES `:35` ; `KEY2-SPEC-02.md` : 0 occurrence |
|
||||
| 11 | Grep `\bGI\b` dans `CAM2-SPEC-02.md` ; Grep `GI\.uasset\|…build 2…` dans `CAM2-{CART,DIAG,TACHES,JOURNAL}*.md` | SPEC-02 `:24-82` ; autres fiches CAM2 : aucune ligne |
|
||||
| 12 | Grep `r[ée]vision (unique )?(de \|du \|des )?`?GI\|…\|S1-BP` (`-o`, `*.md`) dans `etat` | 24 lignes ; STM1-SPEC-01 `:87`, STM1-SPEC-02 `:54`, STM1-SPEC-06 `:39`, SET1-PRE `:123`, COMMUN-17-BILAN `:123`, CAM2-SPEC-02 `:58`, `:63` |
|
||||
| 13 | `git log --format="%h %ad %s" --date=short -8 -- Content/BPs/GI.uasset` | 8 lignes ; tête : `c4cf6f3 2026-10-14 STE : alpha 2026.10.2.1a, GI et TopRight …(CHG-347)` |
|
||||
| 14 | `ls -l Content/BPs/GI.uasset` ; `git ls-files --eol` ; `md5sum` | 52 686 555 octets, 14 oct. 10:33 ; `i/-text w/-text attr/-text` ; `32fc0a970ab194626e8dc07df3a9633d` |
|
||||
| 15 | `rg --no-ignore -N --no-filename -o "^Commandlet : LPDumpFunction -BP=GI -Fn=\S+" -g "*LPDumpFunction*.txt" Docs/Migration/etat \| sort \| uniq -c` | 55 variantes de `-Fn=` ; `EventGraph` ×16, `SavePreset` ×2, `LoadPreset` ×1, `GenerateAndApplyStrings` ×1, `GeneratePerson` ×1, `*` ×1 ; **aucune** ligne `GenerateAndApplyFloats`, **aucune** `CalculateHeadtrack` |
|
||||
| 16 | même `rg` limité aux noms `SavePreset\|LoadPreset\|GeneratePerson\|GenerateAndApplyStrings\|getSkeletalMeshFromPath` ; `rg -l "-Fn=\*"` | `SavePreset` : `STE-D9_…20261011-051838`, `STE-H10V_…20261013-071350` ; `-Fn=*` : seulement `portage55/L6f/L6f_LPDumpFunction_20260930-102202.txt` (5.5) |
|
||||
| 17 | Read dump `CAM-B1-PRE_LPDumpFunction_20261013-083048.txt` `:1-12`, `:5262-5357`, `:14770-14830`, `:20255-20305` | en-tête `-Fn=EventGraph -Pins -Exec`, 61 s, code 0 ; nœuds § 3.2 |
|
||||
| 18 | Grep dump `STE-ORG4cV_LPDumpFunction_20261014-103731.txt` (nœuds M1, M2) ; en-tête | en-tête : `Date : 2026-10-14T10:38:41 duree : 66 s code de sortie : 0` ; lignes `5312`, `5321`, `14818`, `20264`, `20273` (5 lignes, en-têtes de nœuds et littéraux seulement) |
|
||||
| 19 | Grep même dump `bIncludeOnlyOnDiskAssets\|K2Node_CallFunction_1048 \|K2Node_CustomEvent_96 ` | `28582` (événement `LoadDefaultTextures`), `28601`, `28604` (`'true'`) ; autres : `12342` (`'false'`), `12368`, `12384`, `28669` |
|
||||
| 20 | Grep dump `STE-H10V_LPDumpFunction_20261013-071350.txt` (nœuds `SavePreset`) | `135` (`Concat_762`), `141` (`VariableSet_930`), `1476-1479` (`EndsWith`, suffixe `Characters\0.lpcharacter`), `1482` (`IfThenElse_2970`), `1487` / `1503` (`PrintString` `_0`, `_1`), `2236-2299` (`_81`, `_86`, `_88`, `_89`, `VariableSet_10`, `_91`) |
|
||||
| 21 | Read `Source/LifePlay/LPAssetRegistryHelpers.cpp:1-60` ; Grep `GetAssetByObjectPath` dans `Source` | `:34-49` journalise `GetAssetByObjectPath ECHEC` ; 8 lignes (limite atteinte) |
|
||||
| 22 | Grep (compte) `GetAssetByObjectPath ECHEC` dans le `LifePlay.log` du build `LifePlay_Build_5.8_Development_COM23` | `Found 0 total occurrences across 0 files.` |
|
||||
| 23 | Grep même journal `Command not recognized: r\.PostProcessAAQuality\|r\.MorphTarget\.Mode is read only\|Missing characters from save\|missing crucial` | `1202` (`[2026.10.20-20.33.03:353][238]Command not recognized: r.PostProcessAAQuality 3`), `1219` (`Error: r.MorphTarget.Mode is read only!`) ; aucune ligne `Missing characters` ni `missing crucial` |
|
||||
| 24 | Grep `CAM2-IMPL-06.md` (`set_pin_value\|paquet\|dirty\|save_assets`) | `:28`, `:53`, `:78` (leçon IMPL-06) |
|
||||
| 25 | `ls Tools/{Snapshot,Restore,PubCheck,UeState,FileCheck,RunCommandlet}.ps1` ; `rg -n "GI" etat/REPO/FILE.md` | les 6 scripts présents ; FILE.md : 0 ligne contenant `GI` |
|
||||
|
||||
Écart de méthode : les `.txt` d'`etat/` sont ignorés par git ; un Grep de dossier ne les voit pas (FIX1-F7-PRE § 2). Chaque dump a été lu **par son nom**, et les comptages de dumps (n° 15, 16) par `rg --no-ignore` (sans cela, résultat vide à tort).
|
||||
|
||||
## 3. Constats `fichier:ligne`
|
||||
|
||||
### 3.1 État de GI
|
||||
|
||||
- MD5 `32fc0a970ab194626e8dc07df3a9633d`, 52 686 555 octets (n° 14), égal à la référence de `BOSS-JOURNAL.md:693` et de `CG2-IMPL-01.md:224`. Arbre de travail propre pour ce fichier (absent du `git status` de départ). Dernier commit : `c4cf6f3` (2026-10-14), précédé de `0745917`, `a08c134`, `b3ee785` (n° 13).
|
||||
- Aucun ticket de la file du dépôt ne mentionne GI (n° 25).
|
||||
- Plusieurs lots exigent que GI reste inchangé jusqu'à la build 2 : `COMMUN-17-BILAN.md:123`, `CAM2-SPEC-02.md:63`, `KEY2-CART-02-FICHE.md:33` (égalité du MD5 exigée avant et après). Après la révision, la référence `32fc0a97…` change dans BOSS-ETAT et dans ces fiches.
|
||||
- Le doc 37 § 2.7 (`37_Feuille_De_Route_Alpha2.md:148-151`) **ne contient pas** la liste C8, C10… : elle n'existe que dans `BOSS-ETAT.md:143`, avec la mention « à verser » ; `BOSS-JOURNAL.md:767` dit le report « à faire par une fiche ».
|
||||
|
||||
### 3.2 Modifications de GI : une fiche par modification
|
||||
|
||||
Notation : `EG` = `/Game/BPs/GI.GI:EventGraph`, `SP` = `/Game/BPs/GI.GI:SavePreset`. Les identifiants de nœuds se relisent par `get_node_infos` en tête de session (R1 de la SPEC CG2).
|
||||
|
||||
**M1. Commandes de console inutiles au démarrage** (QPERS-PRE, `:44`, `:177`)
|
||||
- Où : `EG`, événement `UpdateGraphicsQuality` (`K2Node_CustomEvent_1324`). Liaisons lues dans le dump 5.8 `CAM-B1-PRE…083048.txt:5274-5351` (13 octobre) ; le dump du 14 octobre `STE-ORG4cV…` porte les mêmes nœuds aux mêmes lignes (`:5312`, `:5321`, `:20264`, `:20273` : existence seule relue).
|
||||
- Chaîne lue : `CallFunction_244` (`r.ScreenPercentage`) → `CallFunction_11964` (`sg.PostProcessQuality`) → `CallFunction_11966` (`r.PostProcessAAQuality`, concaténation `…Operator_907`, `Conv_IntToString` `CallFunction_11967`, lecture `VariableGet_3740`) → `CallFunction_311` (`sg.ShadowQuality`) → `CallFunction_11960` (`r.MorphTarget.Mode`, concaténation `…Operator_973`, `SelectString` `CallFunction_316` choisi par `VariableGet_219`, sortie `then` vide : fin de chaîne). Le tronçon entre `CustomEvent_1324` et `CallFunction_244` (`CallFunction_13544` … `CallFunction_15965`) n'a pas été lu.
|
||||
- Nature : **liaisons et suppressions**.
|
||||
- a) `break_pins` (`_11964`.then → `_11966`.execute) et (`_11966`.then → `_311`.execute) ; `connect_pins` (`_11964`.then → `_311`.execute) ; `delete_node` `_11966`, `…Operator_907`, `_11967`, `VariableGet_3740` (seulement s'il n'a pas d'autre liaison).
|
||||
- b) `break_pins` (`_311`.then → `_11960`.execute) ; `delete_node` `_11960`, `…Operator_973`, `_316`, `VariableGet_219` (sa seule sortie va à `_316`.bPickA ; `VariableGet_220`, lecteur de `VariableSet_115`, reste).
|
||||
- Les variables membres `PostProcessAAQuality` et `CPUSkinning` restent (réglages enregistrés, autres lecteurs et écrivains : dump `:8581-8706`, `:20261-20295`).
|
||||
- Effet : aucun (établi) : le journal COM23 montre `Command not recognized: r.PostProcessAAQuality 3` (`LifePlay.log:1202`) et `Error: r.MorphTarget.Mode is read only!` (`:1219`) ; `r.PostProcessAAQuality` n'existe pas en 5.8 (`QPERS-PRE.md:42`).
|
||||
- Dépend de : rien. Risque : très faible (suppression de commandes rejetées) ; seule la rupture de la chaîne `then` est à contrôler.
|
||||
- Voie : MCP `lp-mcp-bp`. Écritures estimées : 8 à 12.
|
||||
- Preuve en jeu : journal d'un build Development : 0 ligne `Command not recognized: r.PostProcessAAQuality` et 0 ligne `r.MorphTarget.Mode is read only` (avant : 1 et 1 par session) ; les lignes `Set CVar` de `sg.PostProcessQuality`, `sg.ShadowQuality` et `r.ScreenPercentage` sont inchangées.
|
||||
|
||||
**M2. C11 / D27 : nœuds orphelins de l'`EventGraph`, et message de F6** (`CG2-SPEC-01.md:92`, `:193` ; `CG2-CART-01.md:70` ; `FIX1-F6-SPEC.md:85`, `:371`)
|
||||
- Où : `EG`. `K2Node_CallFunction_20748` (`?::ShowTutorial`, broches `Title`, `Content`, `Force`, `Warning` ; `execute` et `then` **sans liaison** dans le dump du 13 octobre : `CAM-B1-PRE…:14818-14825`). `K2Node_CallFunction_13122` (`PrintString` « Missing characters from save », `execute` sans liaison, `then` → `CallFunction_340`.execute : `CAM-B1-PRE…:14791-14801`). `CallFunction_340` reçoit aussi `IfThenElse_2861`.else (`:14790`) : il reste. Dans le dump du 14 octobre, `_20748` est à la même ligne (`:14818`) ; ses broches n'y ont pas été relues (estimé identique).
|
||||
- Contenu du nœud `_20748`, `Content` : le texte demandant de recopier l'ancien dossier `Content\Saves` (`CAM-B1-PRE…:14823`). **C'est le message visé par `FIX1-F6-SPEC.md` Q7.** `FIX1-F6-PRE.md:96` et `FIX1-F6-SPEC.md:85` le décrivent comme un message affiché ; le dump du 13 octobre montre qu'aucune exécution n'y mène ; le journal COM23 ne contient ni son texte ni celui du `PrintString` (n° 23 : un seul journal, sans preuve que le cas se soit présenté).
|
||||
- Nature : **suppression** (C11 : `delete_node` `_20748` ; `break_pins` (`_13122`.then → `_340`.execute) puis `delete_node` `_13122` et ses entrées pures exclusives ; `_340` gardé). Alternative F6 : `set_pin_value` sur `Content` **et** relier l'exécution (changement de comportement visible : le message deviendrait atteignable).
|
||||
- Dépend de : décision GQ4 (supprimer ou réécrire). Risque : très faible pour la suppression ; moyen pour la réécriture (réactive du code mort).
|
||||
- Voie : MCP `lp-mcp-bp`. Écritures estimées : 3 à 6 (suppression) ; plus si réécriture.
|
||||
- Preuve : statique (relecture `get_node_infos`, compilation, `CompileAllBlueprints`, 0 Accessed None nouveau). Aucune preuve en jeu possible pour un code non exécuté ; pour la réécriture : charger une partie dont un slot manque et lire l'écran et le journal.
|
||||
- Piège : `K2Node_CallFunction_340` n'est pas le même nœud dans le dump 5.5 (`ShowTutorialTxt`, `L6f_dump_GI.txt:64588`) : ne pas croiser avec le dump 5.5.
|
||||
|
||||
**M3. C10 / D3 : traces de débogage mortes dans `SavePreset`** (`CG2-SPEC-01.md:91`, `:193` ; `CGREF1-T3-MCP.md:98`)
|
||||
- Où : `SP`. Nœuds : `VariableSet_10` (`before`, `:2282`), `CallFunction_81` (`:2236`), `_88` et `_89` (`Left`, `:2272`, `:2277`), `_91` (`:2299`), `_0` (`:1487`), `_86` (`:2256`), `_1` (`:1503`) du dump 5.8 `STE-H10V_…20261013-071350.txt`.
|
||||
- Nature : **suppression**. Règle de la SPEC : supprimer seulement un nœud dont `execute` n'a aucune liaison et dont les sorties ne vont qu'à d'autres nœuds supprimés ; un nœud relié à un chemin atteignable est gardé et noté. La SPEC § 9 attend que seuls `_0` et `_1` soient supprimables ; le constat d'origine (IMPL v1, « E5 ») n'est plus dans `CG2-IMPL-01.md` (v4) : **non relu**.
|
||||
- Dépend de : rien. Risque : très faible. Voie : MCP. Écritures estimées : 4 à 8 (lecture groupée des 8 nœuds en tête).
|
||||
- Preuve : statique (compilation, relecture) ; en jeu, l'enregistrement d'un préréglage reste conforme (M4, M5).
|
||||
- Source : dump 5.8 (13 octobre), nœuds retrouvés par leur nom ; liaisons : lecture MCP de CGREF1-T3 (16 octobre).
|
||||
|
||||
**M4. D2 : garde de fin de chemin de `SavePreset`** (`CG2-CART-01.md:45` ; `CGREF1-T3-MCP.md:61`, `:97`)
|
||||
- Où : `SP`. `IfThenElse_2970` ← `CallFunction_19325` = `EndsWith(File, "Characters\0.lpcharacter", IgnoreCase)` (dump 5.8 `STE-H10V…:1476-1482`) ; `then` non relié (retour sans écrire) ; `else` → `IfThenElse_10253` (liaisons : `CGREF1-T3-MCP.md:61`).
|
||||
- Constat : le littéral contient un antislash, les chemins de session utilisent `/`, et `File` n'a pas d'extension quand il vient de `CharGen` (l'extension est ajoutée par `Append_762`) : la garde ne se déclenche **probablement jamais** (estimé, `CGREF1-T3-MCP.md:97`).
|
||||
- Nature : **décision d'abord**. Options : (a) laisser (aucune écriture) ; (b) supprimer la garde et relier `FunctionEntry_799` à `IfThenElse_10253` (≈ 5 écritures, comportement inchangé tant que la garde est inerte) ; (c) corriger le littéral : **change le comportement** si un appelant passe une extension ; non recommandé sans connaître le rôle voulu de la garde.
|
||||
- Dépend de : décision GQ1 ; M3 avant (même fonction). Risque : faible en (b), moyen en (c). Voie : MCP. Écritures : 0 à 5.
|
||||
- Preuve en jeu : enregistrer un préréglage sous un nom ordinaire : le fichier est créé ; enregistrement depuis l'écran de création inchangé.
|
||||
- Piège : une correction par `set_pin_value` seul ne marque pas le paquet (voir § 3.9, IMPL-06).
|
||||
|
||||
**M5. ERR-142 : extension `.lpcharacter` ajoutée deux fois** (`Registre_Erreurs.md:149` ; `COMMUN-14-BILAN.md:60`, `:123` ; `CG2-VAL-01.md:184`)
|
||||
- Où : `SP`. `Append_762` (`Concat_StrStr`, dump `:135`) : `A` ← `SelectString` (`Modules/` ou vide selon `StartsWith(File, "Saves")`), `B` ← `File`, `C` = `.lpcharacter` (`CGREF1-T3-MCP.md:64`) ; résultat → `VariableSet_930` (`FullPath`, dump `:141`). Une seconde chaîne `SaveTxt` relit `GetFullPath` (`CGREF1-T3-MCP.md:68-69`) : elle suit la correction.
|
||||
- Nature : **nœuds et liaison**. Proposition (estimée) : `EndsWith(File, ".lpcharacter", IgnoreCase)` (pure) et `SelectString` (A = vide, B = `.lpcharacter`, `bPickA` ← `EndsWith`) relié à `Append_762`.C à la place du littéral. Deux fonctions pures sans effet de bord ; la règle 4 de lp-mcp vise les gardes d'`Accessed None`, pas ce choix de valeur. Variante : deux `SetFullPath` derrière une Branche (plus de nœuds).
|
||||
- Dépend de : M3 (même fonction, ordre) ; indépendante de CG2 C7 (qui filtre `..`, `/`, `\` côté `CharGen`). Risque : faible. Voie : MCP. Écritures estimées : 7 à 10.
|
||||
- Preuve en jeu : enregistrer sous `test.lpcharacter` : un seul fichier `test.lpcharacter` ; sous `test` : `test.lpcharacter` ; la liste de chargement n'affiche pas de doublon.
|
||||
|
||||
**M6. D17 : texture par défaut absente du registre** (`CG2-CART-01.md:60` ; `CGREF1-T3c-MCP.md:58-70`, `:116`)
|
||||
- Où : `EG`, événement `LoadDefaultTextures` (`K2Node_CustomEvent_96`, dump 5.8 `STE-ORG4cV…:28582`) : `GetAssetByObjectPath` (`LPAssetRegistryHelpers`, `CallFunction_1048`, `bIncludeOnlyOnDiskAssets = 'true'`, `:28601-28604`) → `GetAsset` → `CastToTexture2D` (`DynamicCast_3` pour les textures par défaut, `DynamicCast_2` pour les visages : `CGREF1-T3c-MCP.md:64-65`) ; `CastFailed` non relié.
|
||||
- Constat nouveau : l'assistant C++ journalise un avertissement unique par chemin non résolu (`LPAssetRegistryHelpers.cpp:34-49`, lot L5, ERR-027), donc « sans message » n'est plus vrai pour l'absence du registre. Reste **le cas du cast** (asset trouvé mais pas une texture). 0 occurrence de l'avertissement dans le journal COM23 (n° 22) : aucune texture par défaut non résolue dans cette session ; que l'événement ait été exécuté dans cette session n'est pas établi.
|
||||
- Nature : **nœuds** (au plus deux `PrintString` sur les `CastFailed`, journal seul) ; ou aucune écriture si l'utilisateur ferme D17.
|
||||
- Dépend de : décision GQ3. Risque : très faible (journal seul ; `PrintString` n'imprime rien en Shipping, `CG2-SPEC-01.md:115`). Voie : MCP. Écritures : 0 ou 6 à 8.
|
||||
- Preuve : journal Development : aucune ligne nouvelle au démarrage normal ; l'effet du `PrintString` ne se voit qu'avec un chemin volontairement faux (essai éditeur, hors fiche).
|
||||
|
||||
**M7. F7a : avertissement `CenterBrow` dans `CalculateHeadtrack`** (`FIX1-F7-PRE.md:127`, `:137`, `:145`, `:182`)
|
||||
- Où : fonction `CalculateHeadtrack` (44 nœuds, dump **5.5** `L6f_dump_GI.txt:42273-42296`, lu de seconde main par FIX1-F7-PRE) : `GetSocketLocation('CenterBrow')` sur le maillage de `From` (`K2Node_CallFunction_3`) et de `To` (`K2Node_CallFunction_1`) ; appelée par les AnimBP `Daily` et `Daily_F` (estimé). **Aucun dump 5.8** (n° 15).
|
||||
- Nature : **nœuds et liaisons** : garde avant `_1` et `_3` (`IsValid(From)`, `IsValid(To)`, maillage présent par `GetSkinnedAsset`), sinon retour sans calcul (voie A de F7-PRE, 4 à 8 nœuds, 2 coupures). Les sorties de la fonction ne sont pas connues : la branche « non valide » doit renvoyer des valeurs neutres (inconnu).
|
||||
- Dépend de : dump 5.8 de la fonction ; décision GQ6 (aucun effet visible, avertissement présent depuis la 4.27, `Registre_Erreurs.md:25` d'après F7-PRE). Risque : faible pour le jeu, moyen pour la complexité (fonction appelée à chaque image par des AnimBP). Voie : MCP. Écritures estimées : 15 à 20.
|
||||
- Preuve en jeu : build Development, au moins un `SPAWN` suivi de `DESTROY`, 3 minutes de jeu : 0 ligne `GetSocketInfoByName(CenterBrow)` (avant : 141 à 6 138 lignes par session, 8 journaux sur 11) et les 521 autres lignes de sockets inchangées (`FIX1-F7-PRE.md:150`). Une session à 0 sans `SPAWN` ne prouve rien.
|
||||
|
||||
**M8. D9 : tirage sans alternative retenue** (`CG2-CART-01.md:52` ; `CGREF1-T7-TEST.md:14-36` ; `06-rapport-audit.md:175`)
|
||||
- Où : fonction `GenerateAndApplyFloats` (`FunctionEntry_11268`), boucle `MacroInstance_7962` (`ForEachLoopWithBreak` sur `Probs`), test `IfThenElse_13010` ← `CallFunction_106418` (`dé <= cumul`), seule écriture de `Value` = `VariableSet_1`, application après la boucle par `IfThenElse_0` (section réservée → `CallFunction_18` `SetMorphTarget`, `Value` ← `VariableGet_8`, `bRemoveZeroWeight = true` ; sinon `SwitchString_1` → `CallFunction_17`). `Value` est une variable **locale**, défaut estimé 0,0, illisible par MCP (`CGREF1-T7-TEST.md:17-20`). **Lecture MCP 5.8 du 2026-10-16 ; aucun dump 5.8** (n° 15).
|
||||
- Constat : sans alternative retenue, la boucle atteint `Completed`, l'application s'exécute avec la valeur initiale et **retire le morph**. 62 lignes du corpus sont concernées (`CG2-CART-01.md:52`).
|
||||
- Nature : **nœuds et variable** : distinguer « alternative retenue » de « aucune », puis sauter l'application dans le second cas. Une sortie `Break` et `Completed` mènent au même endroit, donc il faut un indicateur : une variable locale booléenne posée dans la branche vraie (**le MCP sait-il créer une variable locale ? inconnu**) ou une valeur sentinelle de `Value` posée avant la boucle (les comparateurs ne sortent pas de `find_node_types`, `lp-mcp` § 3). Même motif possible dans `GenerateAndApplyStrings` (dump 5.8 du 2026-10-10 présent) et `…Bools` (aucun dump) : non lu.
|
||||
- Dépend de : décision GQ2 (R06 § 5.5 n° 2 : « pas encore tranché ») ; dump 5.8 ; capacité MCP. Risque : **moyen** (change le résultat du chargement de préréglages). Voie : MCP. Écritures estimées : 12 à 20.
|
||||
- Preuve en jeu : un préréglage de test dont le total des poids d'une ligne est inférieur à 100 % : la valeur du morph après chargement reste celle d'avant ; comparaison avec un préréglage complet inchangée.
|
||||
|
||||
**M9 (conditionnelle, non planifiée). S1-BP : cadrage du studio** (`CAM2-SPEC-02.md:51`, `:58`, `:63` ; `BOSS-JOURNAL.md:870-871`)
|
||||
- Où : valeur par défaut de la variable membre `CameraSceneTransformDefault` (X -= d) et place du personnage (`GI.ActorTransforms[…]`, à lire). Nature : **valeur** (par défaut de variable, hors graphe) : la voie MCP pour modifier un défaut de variable membre est inconnue. Retenue seulement si S1-C++ est impossible (lecture MCP de la pose de `CharGen` au prochain jeton). Risque : moyen (`CameraSceneTransformDefault` sert d'autres vues).
|
||||
- STM1 S3 (PrintString dans GI : `STM1-SPEC-01.md:87`) est conditionnelle de la même façon et n'est pas retenue (S1 C++ retenue).
|
||||
|
||||
### 3.3 Points de la fiche qui ne sont pas dans GI
|
||||
|
||||
| Point | Où il se trouve | Source |
|
||||
|---|---|---|
|
||||
| C8 (D21) | `CharGen.PopulatePresets` : `ClearChildren` entre `CG.K2Node_CustomEvent_139` et `VariableSet_508`, Branche dans la boucle `MacroInstance_64` | `CG2-SPEC-01.md:75`, `:190` ; `CG2-IMPL-01.md:153`, `:237` |
|
||||
| Q7 (CG2) | masquer le champ anti-déformation de `CharGen` (décision « oui » de l'utilisateur) | `CG2-TACHES.md:22` |
|
||||
| Q8 (CG2) | fermer l'écran par `GI.CloseCharGen` au lieu de désactiver les boutons : écriture dans `CharGen` ; GI seulement **lu** (événement `CustomEvent_101`) ; suspendu jusqu'aux essais | `CG2-TACHES.md:23` ; `CGREF1-T3-MCP.md:84` ; `CG2-VAL-01.md:144` |
|
||||
| R7 | 2 `Accessed None` `GetSkeletalMesh` dans une fonction `Populate…SlidersDaz` de `CharGen`, antérieurs à CG2 | `CG2-TACHES.md:72` ; `BOSS-JOURNAL.md:767` |
|
||||
| Remappage de Y/N (KEY2 Q7) | `PC` : `K2Node_InputKey_2` et `_5` | `KEY2-SPEC-01.md:34`, `:246` ; `KEY2-TACHES.md:35` |
|
||||
| ERR-145 | cause non établie (pistes : `FirstPersonSM`, `C1Hidden`) : C++ ou Person | `Registre_Erreurs.md:152` |
|
||||
| F7b, F7c, F8b | Person et C++ | `FIX1-F7-PRE.md:137` |
|
||||
| Condition `IsMale` de `VisualMorph` | `VisualMorph` | `CG2-SPEC-01.md:195-196` |
|
||||
|
||||
Conséquence : ces points relèvent d'une révision de `CharGen` / `PC` / `Person`, pas de celle de GI. C8 et Q7 vont avec les fichiers `CharGen` (autre binaire) ; le report de BOSS-ETAT (`:143`) les range en « build 2 » sans dire que GI n'est pas le fichier.
|
||||
|
||||
### 3.4 Candidats « B2 » de la CART qui touchent GI et ne sont pas dans la liste
|
||||
|
||||
D1 (broches de sortie de `SavePreset`, incertain), D8 (conflits de morphs, décision), D10 (`BlendPreset` : collision `x` / `ax`), D12 (`LoadPreset` : trace `StatOnly` morte), n° 32 (`ReadLine` sans branche d'erreur), n° 37 (graphes non lus), n° 35 (listes fermées : hors lot) : `CG2-CART-01.md:44`, `:51`, `:53`, `:55`, `:75`, `:83`, `:85`. Non retenus par BOSS-ETAT `:143` ; à demander (GQ5). Autres candidats nés de QPERS : les lignes `r.SSS.Scale`, `r.DynamicRes.*`, `r.Streaming.PoolSize` posées par `UpdateGraphicsQuality` (`CAM-B1-PRE…:17106`, `:17113`, `:25642`, `:25656`), jugées sans effet par QPERS-PRE `:45`, `:50` (estimé) : non demandées.
|
||||
|
||||
### 3.5 Dépendances
|
||||
|
||||
- **Décisions préalables** : GQ4 avant M2 ; GQ1 avant M4 ; GQ3 avant M6 ; GQ2 et la capacité MCP avant M8 ; GQ6 avant M7.
|
||||
- **Même fonction** : M3, M4, M5 dans `SavePreset` ; M1, M2, M6 dans l'`EventGraph`. Les faire à la suite évite de relire deux fois le graphe.
|
||||
- **M3 avant M4 et M5** : les suppressions mortes simplifient la lecture de la tête de fonction ; M4 et M5 touchent des nœuds distincts (`IfThenElse_2970` / `Append_762`).
|
||||
- **Dumps 5.8** (§ 3.7) avant M4/M5 (rafraîchi), M7, M8.
|
||||
- **Externes** : CG2 (VAL et build 2 de CharGen) n'a pas besoin de GI ; publication de la build 1 (vers le 24 octobre) **avant** tout accès en écriture à GI ; CAM2 (lecture MCP du studio, S1-C++) pour savoir si M9 existe ; KEY2 et CAM2 ne modifient pas GI mais leurs fiches comparent le MD5 de GI.
|
||||
- **Gel** de `GI.uasset` annoncé à toutes les sessions pendant la révision (`lp-mcp` § 1 règle 7).
|
||||
|
||||
### 3.6 Ordre proposé (une seule session d'éditeur, un seul instantané)
|
||||
|
||||
0. **Préparation** : gel annoncé ; `Snapshot.ps1 -Lot GIREV -Path Content\BPs\GI.uasset` (MD5 attendu `32fc0a97…`) ; éditeur headless puis `list_toolsets` (`lp-mcp` § 2) ; `load_asset` de GI ; `is_dirty` ; compilation de référence de GI **sans modification** (durée et diagnostics « avant ») ; lectures de contrôle de tous les nœuds ci-dessous (tout écart arrête).
|
||||
1. **Sous-lot A, `EventGraph`** : M1, puis M2 (si GQ4 = supprimer), puis M6 (si GQ3 ≠ fermer). Compilation, journal propre, `save_assets`.
|
||||
2. **Sous-lot B, `SavePreset`** : M3, puis M4 (si GQ1 ≠ laisser), puis M5. Compilation, journal propre, `save_assets`.
|
||||
3. **Sous-lot C, fonctions à effet** : M7 (si GQ6 = oui), puis M8 (si GQ2 = oui et capacité MCP établie). Compilation, journal propre, `save_assets`.
|
||||
4. **Clôture** : `is_dirty`, date et MD5 du `.uasset` **avant** de fermer l'éditeur, `git status --short -- Content/`, fermeture, `UeState` = 0, `RunCommandlet.ps1 -Lot GIREV -Commandlet CompileAllBlueprints` (éditeur fermé), build Development, essai en jeu (§ 3.2, preuves).
|
||||
|
||||
Raison de l'ordre : du moins risqué au plus risqué (suppressions sans effet, puis réparations locales, puis changements de comportement) et par graphe, pour qu'un arrêt à la fin d'un sous-lot laisse GI cohérent.
|
||||
|
||||
### 3.7 Dumps 5.8 à produire avant (éditeur fermé, copie UE)
|
||||
|
||||
| Fonction | Dump 5.8 existant | À faire |
|
||||
|---|---|---|
|
||||
| `EventGraph` (M1, M2, M6, Q8 en lecture) | `STE-ORG4cV…20261014-103731.txt` (10:38, postérieur à la sauvegarde de GI à 10:33) ; liaisons de M1 et M2 lues dans `CAM-B1-PRE…083048.txt` (13 octobre) | **non** tant que le MD5 de GI vaut `32fc0a97…` (à recontrôler le jour du passage) ; relire les broches de `_20748` par MCP |
|
||||
| `SavePreset` (M3, M4, M5) | `STE-H10V…20261013-071350.txt`, antérieur au dernier commit de GI (`c4cf6f3`, 14 octobre) ; l'heure des commits du 13 octobre n'est pas relevée | **oui** : `.\Tools\RunCommandlet.ps1 -Lot GIREV -Commandlet LPDumpFunction -Args '-BP=GI -Fn=SavePreset -Pins -Exec'` |
|
||||
| `GenerateAndApplyFloats` (M8) | aucun (5.5 seulement, et lecture MCP du 2026-10-16) | **oui** : `-Fn=GenerateAndApplyFloats` ; ajouter `GenerateAndApplyStrings` (existant du 2026-10-10, à rafraîchir) et `GenerateAndApplyBools` (aucun) |
|
||||
| `CalculateHeadtrack` (M7) | aucun (5.5 : `L6f_dump_GI.txt:42273-42296`) | **oui** : `-Fn=CalculateHeadtrack` |
|
||||
|
||||
Quatre à six dumps ; 61 à 66 s pour l'EventGraph (n° 17, 18), moins pour une fonction (non mesuré). Le dump plein de GI en 5.8 n'existe pas (seul le 5.5 : n° 16). Un `LPDumpFunction` sur un AnimBP (`Daily`) pour confirmer les appelants de `CalculateHeadtrack` : accepté ou non par la commande, inconnu (`FIX1-F7-PRE.md:201`).
|
||||
|
||||
### 3.8 Découpage en sous-lots (une session de révision, un instantané)
|
||||
|
||||
| Sous-lot | Contenu | Écritures (estimées) | Fiche |
|
||||
|---|---|---|---|
|
||||
| A | préparation + M1 + M2 + M6 | 15 à 30 | 1 fiche N3 `lp-mcp-bp`, ≤ 50 tours |
|
||||
| B | M3 + M4 + M5 | 11 à 25 | 1 fiche, ≤ 50 tours |
|
||||
| C | M7 + M8 + clôture | 27 à 40 | 1 fiche, ≤ 50 tours (la clôture peut passer à l'orchestrateur) |
|
||||
|
||||
Chaque fiche finit par compilation, journal sans erreur ni avertissement nouveau, `save_assets`, MD5 noté. Un seul instantané en tête (A) ; **un seul commit** de `GI.uasset` à la fin, par le gardien. Chaque `save_assets` réécrit 52,7 Mo sur le disque : « révision unique » est entendue ici comme un instantané et un commit, pas comme une écriture disque unique (à confirmer, GQ7).
|
||||
|
||||
### 3.9 Voie, risques transverses, durée
|
||||
|
||||
- **Voie** : MCP `lp-mcp-bp`, écritures unitaires relues (`lp-mcp` § 1 règle 3). Alternative commandlet : aucun commandlet de modification de nœuds de GI n'existe en 5.8 (les 16 `LPFix*` ont été retirés en U2, `lp-commandlets`) ; un nouveau demanderait une compilation C++ et un modèle (`LPFixDeprecatedNodes`) pour ≈ 8 modifications : non recommandé (estimé).
|
||||
- **Leçon IMPL-06** (`CAM2-IMPL-06.md:28`, `:53`, `:78`) : `set_pin_value` seul ne marque pas le paquet ; `save_assets` renvoie vrai sans rien écrire. M4 (c) et toute réécriture de texte (M2) sont à risque. Règle : après un `set_pin_value` sans autre écriture de graphe, marquer le paquet par une opération réversible (couper puis rétablir à l'identique une liaison du même nœud), vérifier `is_dirty`, puis date et MD5 du fichier **avant** de fermer l'éditeur. Les suppressions et liaisons (M1, M2, M3, M5…) marquent le paquet.
|
||||
- **Permission** : en mode auto, un `create_node` a été refusé deux fois dans `CharGen` (`CG2-SPEC-01.md:210`) ; la règle de permission `mcp__unreal-mcp__call_tool` doit être en place avant la session, et il faut compter un tour par écriture relue (`CG2-IMPL-01.md:242-244`).
|
||||
- **Compilation de GI** : décrite comme « longue » (`CG2-SPEC-01.md:94`), durée **non mesurée** dans les sources lues ; la compilation de référence de l'étape 0 la mesure.
|
||||
- **Durée estimée** : 50 à 90 écritures relues (somme des fourchettes M1 à M8), donc 3 fiches de 25 à 45 tours. Base : 1 tour par écriture, `CG2-IMPL-01.md:242-244` (cœur : 22 tours, C7 : 23 tours). La cadence d'horloge par tour n'est pas mesurée (CG2-SPEC § 8 annonçait ≈ 5 h pour 22 tours : estimation de SPEC, non confirmée). À prévoir : 3 créneaux de jeton UE (demi-journée à une journée chacun), plus un créneau de build et d'essai en jeu (≈ 1 h de jeu par l'utilisateur). Fenêtre : après la publication de la build 1 (≈ 24 octobre) et assez avant la build 2 (≈ 3 novembre) pour l'essai.
|
||||
|
||||
### 3.10 Retour arrière
|
||||
|
||||
- **Instantané unique** : `Tools\Snapshot.ps1 -Lot GIREV -Path Content\BPs\GI.uasset` avant toute écriture ; manifeste cité dans chaque livrable ; MD5 de référence `32fc0a970ab194626e8dc07df3a9633d`. Retour à l'octet : `Tools\Restore.ps1 -Lot GIREV -WhatIf`, puis `-Only Content\BPs\GI.uasset`, **éditeur fermé** (`CG2-SPEC-01.md:104`).
|
||||
- **Second filet** : le fichier est identique à `c4cf6f3` (arbre propre) : le gardien peut le restaurer depuis git sur ticket.
|
||||
- **Retour partiel** : un sous-lot enregistré et validé reste ; un sous-lot en échec se défait par les opérations inverses (liaisons rétablies) si le graphe est lisible, sinon restauration complète. Chaque `save_assets` de fin de sous-lot est précédé d'une compilation sans erreur ; en cas de plantage de l'éditeur, le fichier sur disque est l'état du dernier `save_assets`.
|
||||
- **Après coup** : tout retour arrière après l'essai en jeu ramène aussi la référence MD5 de BOSS-ETAT.
|
||||
|
||||
## 4. Établi / estimé / incertain
|
||||
|
||||
**Établi (lu à la source)** :
|
||||
- MD5, taille, historique et arbre propre de GI (n° 13, 14) ; aucun ticket GI (n° 25).
|
||||
- Les liaisons de M1 et la position de `_20748` / `_13122` sans exécution entrante dans le dump 5.8 du 13 octobre (n° 17) ; les mêmes nœuds existent aux mêmes lignes dans le dump du 14 octobre (n° 18, existence seule).
|
||||
- Les nœuds de M3, M4, M5 existent dans le dump 5.8 du 13 octobre (n° 20), y compris le suffixe à antislash.
|
||||
- Le nœud de M6 est dans le dump 5.8 le plus récent, `bIncludeOnlyOnDiskAssets = 'true'` (n° 19) ; l'assistant C++ journalise les échecs (n° 21).
|
||||
- C8, Q7, Q8, R7, Y/N ne sont pas dans GI (§ 3.3, avec sources) ; ERR-145 n'a pas de cause.
|
||||
- Les deux commandes de M1 sont rejetées au démarrage (journal COM23, n° 23).
|
||||
- Aucun dump 5.8 de `GenerateAndApplyFloats` ni de `CalculateHeadtrack` (n° 15) ; aucun dump plein de GI en 5.8 (n° 16).
|
||||
- Le doc 37 § 2.7 ne porte pas la liste (§ 3.1).
|
||||
|
||||
**Estimé (déduit)** :
|
||||
- M2 : `_20748` encore sans exécution entrante le 14 octobre (même ligne) ; l'absence de message « fichiers manquants » vient du code mort (une seule preuve : dump, sans exécution).
|
||||
- M4 : garde inerte ; M7 : appelants `Daily` et `Daily_F` (FIX1-F7-PRE) ; M8 : défaut de `Value` = 0,0 ; décompte des écritures, durée et ordre de grandeur de la compilation ; l'absence d'effet de `r.SSS.*` et `r.DynamicRes.*` (QPERS-PRE).
|
||||
|
||||
**Incertain (essai qui trancherait)** :
|
||||
- Le MCP peut-il créer une variable locale ou modifier le défaut d'une variable membre ? (`describe_toolset` filtré sur `variable`, sans écriture.)
|
||||
- Les sorties de `CalculateHeadtrack` et le rôle exact des appelants (dump 5.8 + dump AnimBP).
|
||||
- Le motif de M8 existe-t-il dans `…Strings` et `…Bools` ? (lecture des dumps.)
|
||||
- Le tronçon de `UpdateGraphicsQuality` entre `CustomEvent_1324` et `CallFunction_244` (lecture MCP).
|
||||
- Pourquoi la règle stricte de C10 ne retient d'abord aucun nœud (IMPL v1 non conservé).
|
||||
- Durée de compilation de GI ; cadence d'horloge d'une écriture MCP.
|
||||
- Si le message « fichiers manquants » est atteignable par un chemin que le dump n'affiche pas (relecture MCP de la broche `execute` de `_20748`).
|
||||
|
||||
## 5. Points à confirmer (repris par la fiche suivante)
|
||||
|
||||
1. Relire par MCP `execute` et `then` de `K2Node_CallFunction_20748` et `K2Node_CallFunction_13122` (confirmation du code mort) avant de trancher GQ4.
|
||||
2. Produire les dumps du § 3.7 et relire `GenerateAndApplyStrings` / `…Bools` pour le motif de D9.
|
||||
3. `describe_toolset` (filtre `variable`) : création de variable locale, défaut d'une variable membre.
|
||||
4. Lire le tronçon de `UpdateGraphicsQuality` non relu et les autres lecteurs de `PostProcessAAQuality` et `CPUSkinning` (aucun nœud supprimé ne doit porter une autre liaison).
|
||||
5. Recontrôler le MD5 de GI le jour du passage (`32fc0a97…`) et le journal des lots qui comparent ce MD5.
|
||||
6. Compilation de référence de GI : durée et diagnostics.
|
||||
|
||||
## 6. Questions pour la SPEC ou l'utilisateur
|
||||
|
||||
1. **GQ1 (D2)** : quel est le rôle voulu de la garde `Characters\0.lpcharacter` ? Recommandation : laisser (a) ou supprimer (b) ; ne pas corriger le littéral (c) sans ce rôle.
|
||||
2. **GQ2 (D9)** : un préréglage incomplet doit-il **laisser le morph inchangé** (correction) ou le **remettre à zéro** (comportement actuel) ? Décision pas prise (`06-rapport-audit.md:175`).
|
||||
3. **GQ3 (D17)** : fermer D17 (journal C++ déjà présent pour le chemin non résolu) ou ajouter les deux traces de cast ?
|
||||
4. **GQ4 (message de F6 / C11)** : supprimer le nœud mort et clore le message de F6, ou le réécrire **et** le relier (comportement nouveau pour le joueur) ?
|
||||
5. **GQ5** : D1, D8, D10, D12, n° 32 et les lignes `r.SSS.*` / `r.DynamicRes.*` entrent-ils dans la révision ?
|
||||
6. **GQ6 (F7a)** : garder l'avertissement `CenterBrow` (sans effet visible) hors de la révision ? Le coût est le plus élevé de la liste (15 à 20 écritures) pour un gain de journal.
|
||||
7. **GQ7** : « révision unique » = un instantané et un commit (une sauvegarde par sous-lot) ou une seule sauvegarde en fin de session (risque de perte en cas de plantage) ?
|
||||
8. **GQ8** : confirmer que C8, Q7, Q8, R7 vont dans une révision de `CharGen` (et Y/N dans une de `PC`), et que la ligne de BOSS-ETAT `:143` est corrigée en conséquence.
|
||||
9. **GQ9** : le doc 37 § 2.7 doit-il recevoir la liste (BOSS-JOURNAL `:767` : « à faire par une fiche ») ?
|
||||
|
||||
Tours : 32 / 35 (28 jusqu'à la première écriture du livrable, un contrôle PubCheck, la réécriture, un second contrôle et le rendu du compte rendu ; `Tools/FicheStats.py` fait foi)
|
||||
|
||||
## Constats
|
||||
|
||||
- Fichier écrit : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\GIREV\GIREV-PRE.md`.
|
||||
- Fichiers à commiter : `A Docs/Migration/etat/REL/GIREV/GIREV-PRE.md` (dépôt du jeu, branche `ue5.8`, par le gardien sur ticket). Aucun autre fichier écrit.
|
||||
- À verser : `lp-mcp` § 3 — le message de GI « copy your old … Content\Saves » est le champ `Content` d'un nœud `ShowTutorial` orphelin : lire `execute` d'un nœud de message avant de le déclarer « affiché ». À verser : `lp-commandlets` — un `rg --no-ignore` ciblé sur les `LPDumpFunction*.txt` donne la couverture des dumps par fonction (`-Fn=`) ; un Grep de dossier sur `etat/` saute les `.txt`.
|
||||
38
Docs/Migration/etat/REL/KEY2/KEY2-BUILD-04.md
Normal file
38
Docs/Migration/etat/REL/KEY2/KEY2-BUILD-04.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# KEY2-IMPL-03 et KEY2-BUILD-04 : confirmation avant de prendre une touche déjà liée (KEY2-DIAG-03, option 1)
|
||||
|
||||
Fiche KEY2-IMPL-03 / KEY2-BUILD-04 — Niveau N3 — Modèle prévu opus (session) | utilisé Opus 5.5 — Session « Medium · KEY2 » — Skills : lp-build, sk-protocol.
|
||||
Date : 2026-10-20 17:40. Décision de l'utilisateur sur KEY2-DIAG-03, citée par Big Boss : « 1 ». GO d'IMPL et de jeton UE de Big Boss `local_104ff22d`.
|
||||
|
||||
## 1. Changement (`Source/LifePlay/LPKeyboardSubsystem.cpp` seul)
|
||||
|
||||
Instantané : `Tools\Snapshot.ps1 -Lot KEY2-IMPL4` (avant : 0eb6a592, version commitée en 2357225). Après : **611c2148** ; +47 / −1 ; CRLF gardé (1537 / 1537). En-tête, `DefaultInput.ini` et `LPKeyboard.ini` inchangés.
|
||||
|
||||
| Endroit | Changement |
|
||||
|---|---|
|
||||
| `FLiveKeyboard` (état du panneau) | touche en attente de confirmation : `ConfirmKey` et ses modificateurs |
|
||||
| `CommitKey` | avant toute écriture, cherche si la touche (mêmes modificateurs) est liée à une autre action, ou à un autre axe ou sens d'axe. Si oui et que ce n'est pas la touche en attente : rien n'est écrit, la capture continue et la ligne d'état dit « <touche> is used by <action>. Press it again to replace, Escape to cancel. ». Si c'est le second appui de la même touche, le remplacement se fait comme avant (« Removed from: … ») |
|
||||
| `BeginWait`, `CancelWait` | oublient la touche en attente : nouvelle capture, ou Échap |
|
||||
| `HandleKeyDownEvent` | une répétition (touche tenue) n'est pas prise comme second appui (`!Event.IsRepeat()`) |
|
||||
|
||||
Une autre liaison de la même action, ou du même sens du même axe, ne compte pas comme conflit.
|
||||
|
||||
## 2. Contrôle et compilation (mesuré)
|
||||
|
||||
- `Tools\CopieEtat.ps1 -Lot KEY2 -Assets <5 assets>` : `proc=0 assets=5 absents=0 modifies=0 … verrou=246:libre alertes=GIT` ; seule alerte : ` M Source/LifePlay/LPKeyboardSubsystem.cpp` (ce lot).
|
||||
|
||||
| Build | Code | Durée | Erreurs | Avertissements | Unités | Journal |
|
||||
|---|---|---|---|---|---|---|
|
||||
| LifePlayEditor Development | 0 (`Result: Succeeded`, l. 50) | 30 s | 0 | 0 (20 lignes UBT HyperAIStudio, connues) | `Compile LPKeyboardSubsystem.cpp` (l. 41), `Link UnrealEditor-LifePlay.dll` (l. 44) | `Saved\Logs\portage\KEY2_Build_20261020-174030.log` |
|
||||
| LifePlay Development `-NoUBA` | 0 (`Result: Succeeded`, l. 27) | 49 s | 0 | 0 | `Compile LPKeyboardSubsystem.cpp` (l. 19), `Link LifePlay.exe` (l. 20) | `Saved\Logs\portage\KEY2_Build_20261020-174107.log` |
|
||||
|
||||
Binaires : `UnrealEditor-LifePlay.dll` 698dce01 ; `LifePlay.exe` 181dc8e6. Après : `UeState` = 0 ; `git status --short -- Source Config Content` : ` M Source/LifePlay/LPKeyboardSubsystem.cpp`.
|
||||
|
||||
## 3. Preuve à faire à la prochaine build d'essai
|
||||
|
||||
1. Change sur une flèche, puis une touche prise (par exemple pavé 7) : message « … is used by Favorite 7. Press it again to replace, Escape to cancel. », et toujours 51 actions dans le journal (aucune ligne « enregistres » à ce moment).
|
||||
2. Échap : « Capture cancelled. », rien n'est changé.
|
||||
3. Même chose, puis un second appui sur pavé 7 : « … saved. Removed from: Favorite 7. », 50 actions.
|
||||
4. Reset : 51 actions.
|
||||
5. Touche tenue : la répétition ne remplace pas.
|
||||
|
||||
À commiter : M `Source/LifePlay/LPKeyboardSubsystem.cpp` ; A ce livrable. Aucun git qui écrit.
|
||||
56
Docs/Migration/etat/REL/KEY2/KEY2-DIAG-03.md
Normal file
56
Docs/Migration/etat/REL/KEY2/KEY2-DIAG-03.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# KEY2-DIAG-03 : 51 puis 50 actions dans le fichier de touches (essai COMMUN-20)
|
||||
|
||||
Fiche KEY2-DIAG-03 — Niveau N3 — Modèle prévu opus (Medium) | utilisé Opus 5.5 — Session « Medium · KEY2 » — Skills : sk-protocol.
|
||||
Date : 2026-10-20. Ordre de Big Boss `local_104ff22d` (« sans urgence »). Lecture seule : journaux et fichier de touches de la build COM20, code de `LPKeyboardSubsystem.cpp` ; aucune écriture hors de ce livrable.
|
||||
|
||||
## 1. Constat (établi)
|
||||
|
||||
Journal du premier lancement : `D:\Game\LifePlay_Build_5.8_Development_COM20\Windows\LifePlay\Saved\Logs\LifePlay-backup-2026.10.20-15.10.23.log`.
|
||||
|
||||
| Ligne | Heure (UTC) | Message |
|
||||
|---|---|---|
|
||||
| 877-878 | 15:05:56 | fichier absent, création : 51 actions, 17 axes |
|
||||
| 999-1000 | 15:06:13 | 51 actions, 17 axes ; « disposition AZERTY appliquee » |
|
||||
| 1003 | 15:09:01 | **50** actions, 17 axes |
|
||||
| 1006 | 15:09:47 | 50 actions, 17 axes |
|
||||
|
||||
Au relancement : « 50 actions et 17 axes relus » (`etat\BOSS\COMMUN-20\COMMUN-20_session_1710.log:878`).
|
||||
|
||||
## 2. Action perdue (établi)
|
||||
|
||||
J'ai comparé les liaisons d'actions de `Config/DefaultInput.ini` (51) à celles du fichier du joueur, `…\COM20\Windows\LifePlay\Saved\Config\Windows\LPKeyboard.ini` (50), après avoir retiré les modificateurs faux :
|
||||
- **seule absente : `Favorite7` sur `NumPadSeven`**. Favorite7 garde `Seven`.
|
||||
- `ActionPanel` Q → A : attendu, c'est le préréglage AZERTY.
|
||||
- `inventory` et `recommended` en minuscules : casse d'origine de l'ancien nom (FName), sans effet. FName et FString se comparent sans tenir compte de la casse.
|
||||
|
||||
Côté axes (17 de part et d'autre) : `LeftRight −1 (Left)` est passé en **dernière** position du fichier (l. 68), alors que les autres axes gardent l'ordre d'origine. Cette liaison a donc été retirée, puis rajoutée.
|
||||
|
||||
## 3. Cause (établie par le code ; touche exacte estimée)
|
||||
|
||||
Le cas COMMUN-20.3 consistait à changer une flèche, puis à la remettre. Lecture :
|
||||
1. **15:09:01** : « Change » sur la flèche gauche (`LeftRight −1`, ligne « Map Left » ou « Couple Left »), puis appui sur une touche déjà liée à Favorite7, très probablement **pavé 7** (estimé : c'est la seule action qui manque). `CommitKey` (`LPKeyboardSubsystem.cpp:973`, message `:1037`) :
|
||||
- retire l'ancienne liaison (`Left`) ;
|
||||
- **retire la même touche de toute autre action**, Favorite7 / NumPadSeven, et l'annonce dans la ligne d'état (« … saved. Removed from: Favorite 7. ») ;
|
||||
- ajoute la nouvelle.
|
||||
Résultat : 51 → 50 actions, 17 axes.
|
||||
2. **15:09:47** : « Change » sur la même flèche, puis `Left` : la flèche revient (ajoutée en fin de liste), mais **rien ne rend pavé 7 à Favorite7**. Résultat : 50 actions, 17 axes.
|
||||
|
||||
Ce n'est pas la double place des flèches (option A) : les deux lignes de l'affichage portent la même liaison, et une écriture reste une écriture. C'est la règle de conflit de `CommitKey`, voulue par la SPEC (KEY2-SPEC-01 § 2, « retire la même touche des autres actions … et l'annonce »), qui n'a pas de retour arrière.
|
||||
|
||||
## 4. Correctif proposé (aucune IMPL sans GO ; `LPKeyboardSubsystem.cpp` seul)
|
||||
|
||||
| Option | Effet | Coût |
|
||||
|---|---|---|
|
||||
| **(1) Confirmation, recommandé** | si la touche est déjà prise ailleurs, `CommitKey` n'écrit rien. Il affiche « NumPad 7 is used by Favorite 7. Press it again to replace, Escape to cancel. » ; un second appui sur la même touche confirme | environ 25 lignes (état « touche en attente de confirmation », remis à zéro par Échap ou par une autre touche) |
|
||||
| (2) Échange | la touche prise passe à la nouvelle action, et l'ancienne touche de celle-ci va à l'action qui l'avait (pavé 7 ↔ Left) | environ 20 lignes ; surprend quand l'ancienne touche était vide (Add) ou entre en conflit à son tour |
|
||||
| (3) Rien, documenter | comportement actuel : retrait annoncé ; Reset rend tout | 0 |
|
||||
|
||||
Avec (1), le cas de COMMUN-20.3 n'aurait rien perdu : le premier appui sur pavé 7 aurait seulement averti.
|
||||
|
||||
Preuve exigée : Change d'une flèche, appui sur une touche prise. On attend le message et 51 actions inchangées ; Échap annule. Un second appui confirme : 50 actions et « Removed from » ; Reset rend 51.
|
||||
|
||||
## 5. Pour le joueur de COMMUN-20
|
||||
|
||||
Pour retrouver pavé 7 sur Favorite 7 : Reset dans le menu Clavier, puis Apply AZERTY. Ou bien Add sur Favorite 7, puis pavé 7.
|
||||
|
||||
Fichiers écrits : ce livrable. À commiter : A `Docs/Migration/etat/REL/KEY2/KEY2-DIAG-03.md`. Aucun git qui écrit.
|
||||
|
|
@ -15,6 +15,8 @@ Aucune écriture git. Contenu adulte : règle du doc 27 (`Docs\27_Plan_Migration
|
|||
| KEY2-BUILD-02 | recompilation après DIAG-01 (LifePlayEditor, LifePlay Development) | lp-builder | oui (BUILD-GO) | **rendue** : 2 builds à code 0 (49 s, 60 s), 0 erreur, 0 avertissement du compilateur, 20 lignes UBT connues ; `LPKeyboardSubsystem.cpp` et `LPSettingsSubsystem.cpp` compilés | `KEY2-BUILD-02.md` |
|
||||
| KEY2-DIAG-02 | COMMUN-16 : V / X et flèches haut / bas sans effet en scène | la session (opus) | non (lecture) | rendue : V / X, cause établie (garde « pièce cachée » reprise de `PC`, alors que la pièce de l'essai est visible, J l. 10478) ; haut / bas, comportement d'origine de `PC` (Birdview dans une pièce visible), pas une régression ; correctif proposé, option (a) ou (b) à trancher par l'utilisateur | `KEY2-DIAG-02.md` |
|
||||
| KEY2-SUITE-ST | COMMUN-16 : clic gauche seul refusé, **PASS** ; défaut mineur : la ligne d'état est coupée à droite. Proposé : `.AutoWrapText(true)` sur `StatusBlock` (`LPKeyboardSubsystem.cpp:403`, comme le texte d'en-tête du panneau), et un message plus court (`:1150`) : « Left click needs Shift, Ctrl, Alt or Cmd. Escape cancels. » | KEY2 (`LPKeyboardSubsystem.cpp`, sous instantané) | au dégel ; compilé avec le passage de CAM2 | **écrite** le 2026-10-20 (instantané KEY2-SUITE ; LPKeyboardSubsystem.cpp 7960e871 → 9d450aaf) ; compilation par CAM2 | — |
|
||||
| KEY2-DIAG-03 | COMMUN-20 : 51 puis 50 actions dans le fichier de touches. Cause : en .3, une flèche changée vers une touche prise (pavé 7, estimé) ; `CommitKey` retire cette touche de Favorite7, puis la flèche est remise sur Left, mais rien ne rend pavé 7. Règle de conflit voulue, sans retour arrière ; ce n'est pas la double place des flèches. Correctif proposé : confirmation par un second appui (option 1) | la session (opus) | non (lecture) | **acceptée** : décision de l'utilisateur « 1 » (confirmation) | `KEY2-DIAG-03.md` |
|
||||
| KEY2-IMPL-03 / BUILD-04 | confirmation au second appui avant de prendre une touche déjà liée ; Échap annule ; répétition ignorée | la session (opus) | oui (GO de jeton) | **rendue** : instantané `KEY2-IMPL4`, `LPKeyboardSubsystem.cpp` 0eb6a592 → 611c2148, +47 / −1, CRLF ; 2 builds à code 0 (30 s, 49 s), 0 avertissement ; UeState 0 | `KEY2-BUILD-04.md` |
|
||||
| KEY2-SPEC-02 | Regroupement du menu Clavier par fonctionnalité (demande de l'utilisateur après COMMUN-18.14 : « 14 ok mais il faudrait regroupé les touche par fonctionalité ») : 9 sections, actions à deux groupes, options (A) deux places / (B) une seule, coût | la session (opus) | non (étude) | **acceptée** : « regroupement des touches ok » ; recommandations appliquées (9 sections, option A, Pause dans Time, TestScenes dans System, RotateCamera en Camera) | `KEY2-SPEC-02.md` |
|
||||
| KEY2-IMPL-02 | regroupement, affichage seul : `GroupFor` en 9 sections, flèches à deux places (« Map … » et « Couple … »), « Move couple with » en tête de Couple (scene), libellés « Camera Height … (scene) » et « Action Panel (also Alt / middle click) » | la session (opus) | non pour l'écriture | **écrite, non compilée** : instantané `KEY2-IMPL3` ; `LPKeyboardSubsystem.cpp` 9d450aaf → 0eb6a592, +63 / −62, CRLF gardé ; compilée par KEY2-BUILD-03 | — |
|
||||
| KEY2-BUILD-03 | compilation de KEY2-IMPL-02 (LifePlayEditor, LifePlay Development -NoUBA) | la session | oui (GO de jeton) | **rendue** : 2 builds à code 0 (41 s, 80 s), 0 erreur, seul le C4701 `Aim` connu ; `LPKeyboardSubsystem.cpp` compilé et lié ; UeState 0 ; VAL statique par Big Boss | `KEY2-BUILD-03.md` |
|
||||
|
|
|
|||
180
Docs/Migration/etat/REL/QPERS/QPERS-PRE.md
Normal file
180
Docs/Migration/etat/REL/QPERS/QPERS-PRE.md
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
Fiche QPERS-PRE — Niveau N2 — Modèle prévu non précisé par la fiche | utilisé Sonnet 5.5 (claude-sonnet-5-5) — Agent lp-cart — Skills sk-protocol, ue-cpp-build, lp-commandlets, lp-paths
|
||||
# QPERS-PRE : quick win sur la qualité des personnages, réglages de rendu à essayer en console (2026-10-20)
|
||||
|
||||
Hors gabarit : les sections 7 (protocole d'essai console) et 8 (recommandation et diff d'ini) sont demandées par la fiche et s'ajoutent aux six sections CART. Lecture seule : rien n'a été lancé (ni jeu, ni éditeur, ni MCP) ; aucun effet visuel ni coût GPU n'a été mesuré par l'auteur de cette fiche.
|
||||
|
||||
## 1. Objet et périmètre
|
||||
|
||||
Demande de l'utilisateur, citée mot pour mot : « un quick win sur la qualité des personnages ».
|
||||
|
||||
Domaine : le rendu des personnages (peau, visage, cheveux, yeux) dans le build Development `D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay.exe` (présent, 301 568 octets), moteur 5.8.3 (`D:\Game\Launcher\Engine\UE_5.8\Engine\Build\Build.version` : `"PatchVersion": 3`, `"Changelist": 58210709`). Réglages visés : essayables par la console (touche `²`, `Config/DefaultInput.ini:166-168`), sans compilation, à graver ensuite dans `Config/DefaultScalability.ini` ou `Config/DefaultEngine.ini`. Machine de la session relevée dans le journal du build COM23 : processeur Ryzen 7 5800H, carte AMD Radeon RX 6600M (`Saved/Logs/LifePlay.log:295`), mémoire vidéo dédiée détectée 8,0 Go (`LifePlay.log:1503`).
|
||||
|
||||
Hors périmètre : toute modification d'asset ou de code (décrite en section 6 comme piste, non traitée).
|
||||
|
||||
## 2. Commandes et lectures (exactes) avec compte brut
|
||||
|
||||
Raccourcis : `LOG` = `D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay\Saved\Logs\LifePlay.log` ; `MOT` = `D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime`.
|
||||
|
||||
| # | Commande ou lecture | Compte brut |
|
||||
|---|---|---|
|
||||
| 1 | Read `Config/DefaultScalability.ini` ; Read `Config/DefaultEngine.ini` l.1-60 ; Grep `r\.|sg\.|TemporalAA|SSS|SkinCache|Streaming|Sharpen|ContactShadow…` dans `DefaultEngine.ini` | 127 lignes lues ; `DefaultEngine.ini` : réglages de rendu aux l.17-30 seulement, aucune ligne SSS, SkinCache, Substrate, DynamicRes, Sharpen |
|
||||
| 2 | Grep `r\.…|sg\.…` dans `Source/LifePlay/LPVideoQualitySubsystem.cpp` ; Read l.225-285 | 4 `sg.*` posés (l.265-268), 3 noms `r.*` cités en commentaire (l.256) |
|
||||
| 3 | `rg -a -o ".{0,70}(SubsurfaceProfile\|MSM_Subsurface\|SSP_Girl).{0,70}" DazSkin.uasset DazSkin_Face.uasset DazSkinHide.uasset` (dossier `Content/Heavy/Daz/Bridget`) | les trois : `ShadingModel…MSM_Subsurface…ShadingModels…(ShadingModelField=4)` ; `DazSkin` et `DazSkinHide` : en plus `SubsurfaceProfile`, `/Game/Heavy/New3/Characters/SSP_Girl_Head` |
|
||||
| 4 | `rg -a -o --with-filename -g "*.uasset" "ShadingModel.{1,6}MSM_[A-Za-z]+\|MSM_(Subsurface\|…)\b" Bridget Michael -d 1` | 21 lignes : 9 matériaux de corps `B_*` / `M_*` + `DazSkin`, `DazSkin_Face`, `DazSkinHide` en `MSM_Subsurface` ; `Cornea`, `EyeMoisture`, `Eyelashes`, `Transparent`, `DazBump`, `DazRough` en `MSM_DefaultLit` |
|
||||
| 5 | Dans `Content` : `rg --no-ignore -a -l -g "*.uasset" -g "*.umap" -g "!**/Anims/**" "MSM_(SubsurfaceProfile\|Eye\|Hair\|PreintegratedSkin\|Cloth)" .` | **sortie vide, code 1** (aucun fichier) ; témoin : même commande avec `MSM_Subsurface` = **227** fichiers ; `rg --files -g "*.uasset"` = 8525 (filtre git) et 9074 (`--no-ignore`) |
|
||||
| 6 | `rg -a -o --with-filename "ShadingModel.{1,8}MSM_…\|BLEND_…" Bridget/Hairs -d 1` | 26 lignes : cartes de cheveux en `BLEND_Masked` ; `DazHair` : `BLEND_Masked` ×2 + `MSM_Subsurface` ; `DazAcessory` : `BLEND_Opaque` + `MSM_DefaultLit` |
|
||||
| 7 | `rg -a -o ".{0,100}(r\.SSS\.Scale\|r\.Streaming\.PoolSize\|r\.ScreenPercentage\|r\.DynamicRes…).{0,60}" Content/BPs/GI.uasset` | `r.SSS.Scale 0` et `r.SSS.Scale 1`, `r.Streaming.PoolSize 1500`, `r.ScreenPercentage `, `r.DynamicRes.MinScreenPercentage 50`, `…Max… 100`, `…FrameTimeBudget 33.3`, `sg.PostProcessQuality `, `r.MorphTarget.Mode ` |
|
||||
| 8 | Grep sur `LOG` (motifs `r\.DynamicRes\|r\.ScreenPercentage\|r\.SSS\.Scale\|r\.Streaming\.PoolSize\|Video :…`, puis `OperationMode\|r\.TemporalAA…`) | 30 lignes (limite de sortie) puis 14 lignes : voir constats |
|
||||
| 9 | `rg -a -l "ContactShadowLength" .` dans `Content` (`*.uasset`, `*.umap`, filtre git actif : 8525 `.uasset`) | **0 fichier** |
|
||||
| 10 | Lectures de sources moteur (`MOT` et `Engine/Shaders`, `Engine/Config`) | fichiers et lignes cités en section 3 |
|
||||
| 11 | `rg -a -l "SkeletalMeshLODInfo\|LODInfo" Heavy/Daz/Bridget Heavy/Daz/Michael -d 1` | 2 fichiers : `Michael/michael.uasset`, `Bridget/bridget_gp.uasset` |
|
||||
| 12 | `ls -l` des textures de peau (`Bridget8TorsoD_1002`, `Bridget8Face01D_1001`, `Bridget8_Torso_NM_1002`) | 7 368 606 / 10 834 981 / 1 616 354 octets |
|
||||
| 13 | Grep `LifePlay.uproject` (`HairStrands\|Groom\|SkinCache\|Nanite`) | 1 ligne : `LifePlay.uproject:135` `"Name": "HairStrands"` |
|
||||
|
||||
## 3. Constats `fichier:ligne`
|
||||
|
||||
### 3.1 Ce qui est déjà réglé
|
||||
- **AA** : `Config/DefaultEngine.ini:17` `r.AntiAliasingMethod=2` (TAA, commentaire l.14-16, ERR-032). Le journal confirme `LOG:389` `Set CVar [[r.AntiAliasingMethod:2]]`.
|
||||
- **Rendu figé** : `DefaultEngine.ini:22-24` pas de GI dynamique, reflets SSR, pas d'ombres virtuelles ; `:26` streaming de textures actif ; `:28` éclairage statique autorisé.
|
||||
- **Ombres** : `DefaultScalability.ini:34-50` : `r.Shadow.MaxResolution` et `r.Shadow.MaxCSMResolution` valent 2048 à la fois au niveau 2 (High) et au niveau 3 (Epic) ; seuls le nombre de cascades (3 / 4), `RadiusThreshold` (0.04 / 0.03) et `PreShadowResolutionFactor` (0.75 / 1.0) diffèrent. Journal niveau 3 : `LOG:455-456`.
|
||||
- **Textures** : `DefaultScalability.ini:67-77` : `r.Streaming.MipBias=0` aux niveaux 2 et 3, `r.MaxAnisotropy` 4 / 8, `r.Streaming.PoolSize` 700 / 1000, `r.Streaming.MaxEffectiveScreenSize=0`. Journal : anisotropie 8 au niveau 3 (`LOG:584`), 4 au niveau 2 (`LOG:1520`).
|
||||
- **SSS** : `DefaultScalability.ini:85-86, 94-95, 101-102, 109-110` : `r.SSS.Scale` 0.25 / 0.5 / 0.75 / 1.0 et `r.SSS.SampleSet` 0 / 1 / 2 / 2.
|
||||
- **Qualité d'AA** : `DefaultScalability.ini:117-128` ne pose que `r.PostProcessAAQuality` (0 / 2 / 4 / 4). **Cette variable n'existe pas en 5.8** : `LOG:1805` `Command not recognized: r.PostProcessAAQuality 3` ; `LOG:450`, `LOG:1546` `CVar [[r.PostProcessAAQuality:4]] deferred - dummy variable created` ; aucun résultat dans `Engine/Config` ni dans `MOT`. Ce qui varie réellement avec le niveau d'AA vient de `Engine/Config/BaseScalability.ini:52-94` : `r.TemporalAA.Quality` = 0 / 1 / 1 / 2 (journal : 2 au niveau 3 `LOG:442`, 1 au niveau 2 `LOG:1542`).
|
||||
- **Panneau Video** : `Source/LifePlay/LPVideoQualitySubsystem.cpp:258-269` n'écrit que `sg.ShadowQuality`, `sg.TextureQuality`, `sg.EffectsQuality`, `sg.AntiAliasingQuality` en SetByConsole (commentaire l.255-257). Session COM23 : niveaux lus depuis Scalability = 3 (`LOG:902`), puis « Recommended = High (niveau 2), VRAM dediee detectee 8.0 Go » (`LOG:1503`), puis niveaux 2 appliqués (`LOG:1547`).
|
||||
- **Réglages posés par le Blueprint `GI`** (SetByConsole, plus prioritaires que le Scalability) : `LOG:1683` `r.Streaming.PoolSize = "1500"`, `LOG:1688-1690` `r.DynamicRes.MinScreenPercentage = "50"`, `…Max… = "100"`, `…FrameTimeBudget = "33.3"`, `LOG:1786-1787` `r.SSS.Scale = "1"`, `r.ScreenPercentage = "100"`, `LOG:1804` `sg.PostProcessQuality = "2"`, `LOG:1822` `Error: r.MorphTarget.Mode is read only!`. Preuve de priorité : `LOG:4250, 4252` « `SetByScalability` was ignored as it is lower priority than the previous `SetByConsole` ». **Conséquence : graver en ini `r.ScreenPercentage`, `r.Streaming.PoolSize` ou `r.SSS.Scale` ne changerait rien tant que le Blueprint les repose.**
|
||||
- **Résolution dynamique** : `r.DynamicRes.OperationMode` vaut 0 (désactivée) par défaut (`MOT/Engine/Private/UnrealEngine.cpp:538-545`) ; absent de `Config/` (Grep « OperationMode|DynamicRes » : aucun résultat) et du journal COM23. Les valeurs 50 / 100 / 33.3 du Blueprint sont donc, selon ces sources, sans effet (voir section 4, estimé).
|
||||
|
||||
### 3.2 Comment les personnages sont rendus
|
||||
- **Peau** : `Content/Heavy/Daz/Bridget/DazSkin.uasset`, `DazSkin_Face.uasset`, `DazSkinHide.uasset` portent `ShadingModel = MSM_Subsurface` et `ShadingModelField=4` (4 = 1<<2, indice de `MSM_Subsurface` : `MOT/Engine/Classes/Engine/EngineTypes.h:707-714`). `DazSkin` et `DazSkinHide` référencent un asset de profil de diffusion (`/Game/Heavy/New3/Characters/SSP_Girl_Head`, le fichier existe) ; `DazSkin_Face` n'en référence aucun. Les 9 matériaux de corps `B_*` et `M_*` sont aussi en `MSM_Subsurface` (tableau 2, ligne 4).
|
||||
- **Aucun matériau n'utilise un modèle à diffusion écran** : 0 fichier avec `MSM_SubsurfaceProfile`, `MSM_Eye`, `MSM_Hair`, `MSM_PreintegratedSkin` ou `MSM_Cloth` sur 9074 `.uasset` et les `.umap` (tableau 2, ligne 5) ; 227 fichiers en `MSM_Subsurface`.
|
||||
- **Pourquoi c'est décisif** : la passe de diffusion écran ne s'exécute que si la vue contient un modèle à profil : `MOT/Engine/Public/MaterialShared.h:131-139` (`UseSubsurfaceProfile` = Subsurface Profile ou Eye ; masque = Subsurface Profile | Eye | Preintegrated Skin seulement si Substrate) et `MOT/Renderer/Private/PostProcess/PostProcessSubsurface.cpp:338-344` (`IsSubsurfaceRequiredForView` exige ce masque). Substrate est désactivé (`MOT/RenderCore/Private/RenderUtils.cpp:2069-2072` : défaut 0, lecture seule, non posé dans `DefaultEngine.ini`). Les descriptions des variables le disent : `r.SSS.Scale` « use shadingmodel SubsurfaceProfile » (`PostProcessSubsurface.cpp:36-46`), `r.SSS.Quality` « when using the SubsurfaceScatteringProfile shading model » (`:62-69`). **Donc `r.SSS.Quality`, `r.SSS.HalfRes`, `r.SSS.Checkerboard`, `r.SSS.Burley.*`, `r.SSS.SampleSet`, `r.SSS.Scale` n'ont, par lecture du code, aucun effet sur la peau actuelle**, y compris les lignes `r.SSS.*` de `DefaultScalability.ini` et les `r.SSS.Scale` du Blueprint `GI`. Le modèle `MSM_Subsurface` est éclairé par `SubsurfaceBxDF` (`Engine/Shaders/Private/ShadingModels.ush:1145-1146`) ; aucune variable de console de qualité n'a été trouvée pour lui.
|
||||
- **Yeux** : `Cornea`, `EyeMoisture`, `Eyelashes` en `MSM_DefaultLit` (tableau 2, ligne 4) ; pas de modèle `Eye`.
|
||||
- **Cheveux** : cartes en `BLEND_Masked` (≈ 25 matériaux, tableau 2, ligne 6). Le plugin `HairStrands` est déclaré (`LifePlay.uproject:135`), mais aucun asset de mèches n'a été établi : les occurrences de « Strands » dans les fichiers trouvés sont des noms de textures et de matériaux de cartes.
|
||||
- **Maillages squelettiques** : `Michael/michael.uasset` et `Bridget/bridget_gp.uasset` contiennent le nom `LODInfo` ; le nombre de LOD n'est pas lu. `r.SkeletalMeshLODBias` : défaut 0, ajouté au LOD souhaité (`MOT/Engine/Private/Components/SkinnedMeshComponent.cpp:87-93, 4626-4633`). `r.SkeletalMeshLODRadiusScale` : défaut 1.0, **borné à 0.25-1.0** (`MOT/Core/Private/HAL/ConsoleManager.cpp:4585-4588` ; `MOT/Engine/Private/SkeletalRender.cpp:144-147`) : déjà au maximum. `r.ForceLOD` : défaut -1 (`MOT/RenderCore/Private/RenderCore.cpp:223-226`).
|
||||
- **Textures de peau** : fichiers `.uasset` de 7,4 Mo (corps, diffuse), 10,8 Mo (visage, diffuse), 1,6 Mo (normale) ; la diffuse du corps porte `TEXTUREGROUP_World`, `TMGS_FromTextureGroup` et le nom de propriété `NeverStream` (valeur non lue). Dimensions non lues.
|
||||
- **Ombres de contact** : `r.ContactShadows` vaut 1 par défaut (`MOT/Core/Private/HAL/ConsoleManager.cpp:4222-4227`) mais la longueur vient de la lumière (`MOT/Renderer/Private/LightRendering.cpp:669-688`) ; `ContactShadowLength` vaut 0 par défaut (`MOT/Engine/Private/Components/LightComponent.cpp:470`, propriété `LightComponent.h:129-131` « Zero is disabled ») et aucun fichier du contenu ne pose cette propriété (tableau 2, ligne 9). **La variable de console n'a donc rien à activer** : le levier est la propriété de chaque lumière (modification d'asset).
|
||||
- **Cache de peau (skin cache)** : `r.SkinCache.CompileShaders` vaut 0 par défaut et est en lecture seule (`MOT/Engine/Private/GPUSkinCache.cpp:92-100`) ; `r.SkinCache.Mode` exige `CompileShaders != 0` (`:104-115`) ; `r.SkinCache.RecomputeTangents` vaut 2 (`:128-139`). Le projet ne pose rien de tel (`DefaultEngine.ini`). **Non essayable en console** : réglage de projet + recompilation des shaders.
|
||||
- **Netteté** : `r.TemporalAACurrentFrameWeight` 0.04 (« Low values cause blurriness and ghosting, high values fail to hide jittering », `MOT/Renderer/Private/PostProcess/TemporalAA.cpp:40-44`) ; `r.TemporalAA.Quality` 2 (`:46-53`) ; `r.TemporalAASamples` 8 (`MOT/Renderer/Private/SceneVisibility.cpp:100-103`) ; `r.TemporalAA.Upsampling` 1, ne joue qu'en mise à l'échelle (`MOT/Engine/Private/SceneView.cpp:336-342`) ; `r.Tonemapper.Sharpen` -1 = hérite du volume de post-traitement (`MOT/Renderer/Private/PostProcess/PostProcessTonemap.cpp:34-42`) ; `r.ScreenPercentage` accepte > 100 (« supersampling », `MOT/Engine/Private/LegacyScreenPercentageDriver.cpp:38-42`) ; `sg.ResolutionQuality=0` est sans action (`MOT/Engine/Private/Scalability.cpp:532-538`).
|
||||
- **Ombres des personnages** : `r.Shadow.MaxResolution` et `r.Shadow.MaxCSMResolution` valent 2048 par défaut (`ConsoleManager.cpp:4366-4376`) ; `r.Shadow.TexelsPerPixel` vaut 1.27324 « for per-object shadows », sans drapeau Scalability (`MOT/Renderer/Private/ShadowSetup.cpp:277-280`) ; le plafond lu est `r.Shadow.MaxResolution` (`ShadowSetup.cpp:707-724`) ; sur D3D11 et D3D12 la taille maximale de carte d'ombre suit `GMaxTextureDimensions` (`MOT/Windows/D3D11RHI/Private/D3D11Device.cpp:200`, `MOT/D3D12RHI/Private/D3D12RHI.cpp:231`), donc 4096 n'est pas bloqué par le RHI (valeur de `GMaxTextureDimensions` non relue).
|
||||
- **Streaming** : `r.Streaming.Boost` 1.0, `r.Streaming.MipBias` 0, `r.Streaming.PoolSize` -1, `r.Streaming.FullyLoadUsedTextures` 0 (`MOT/Engine/Private/Streaming/TextureStreamingHelpers.cpp:79-86, 119-123, 191-199, 208-212`). Dans le jeu, `PoolSize` vaut 1500 (Blueprint `GI`, `LOG:1683`).
|
||||
- **Capture** : `HighResShot` (`MOT/Engine/Private/GameViewportClient.cpp:3577`), `Shot` / `Screenshot` (`:3585`) ; dossier : `FPaths::ScreenShotDir` (`MOT/Core/Private/Misc/Paths.cpp:553`).
|
||||
|
||||
## 4. Établi / estimé / incertain
|
||||
|
||||
**Établi** (lu à la source) :
|
||||
- La peau (3 matériaux principaux + 9 matériaux de corps) est en `MSM_Subsurface` ; aucun matériau du contenu n'est en Subsurface Profile / Eye / Hair (0 fichier sur 9074).
|
||||
- La passe SSS écran est conditionnée à ces modèles (`MaterialShared.h:131-139`, `PostProcessSubsurface.cpp:338-344`) ; Substrate est désactivé.
|
||||
- Aucune lumière du contenu ne pose `ContactShadowLength` (0 fichier sur 8525 `.uasset` filtrés) et le défaut moteur est 0.
|
||||
- `r.PostProcessAAQuality` n'existe pas en 5.8 (journal l.1805) : les quatre sections `AntiAliasingQuality` de `DefaultScalability.ini` ne règlent rien ; l'AA varie par `r.TemporalAA.Quality` de `BaseScalability.ini`.
|
||||
- `r.SkinCache.CompileShaders` = 0 en lecture seule, non posé par le projet.
|
||||
- Le Blueprint `GI` repose en SetByConsole `r.ScreenPercentage`, `r.Streaming.PoolSize`, `r.SSS.Scale` : l'ini ne peut pas gagner contre lui (`LOG:1683, 1786-1787, 4250-4252`).
|
||||
- Sur la machine d'essai, le jeu recommande et applique le niveau High (2) (`LOG:1503, 1547`), pas Epic.
|
||||
- Noms et valeurs par défaut des variables du tableau de la section 7 : lus dans les sources 5.8.3 (section 3).
|
||||
|
||||
**Estimé** (déduit) :
|
||||
- Résolution dynamique inactive : `OperationMode` à 0 par défaut, jamais posé dans `Config/` ni dans le journal COM23 → les valeurs 50 / 100 du Blueprint n'agissent pas (à vérifier par `r.DynamicRes.OperationMode`, section 7).
|
||||
- Cheveux = cartes à masque, pas des mèches (aucun asset de mèches établi).
|
||||
- Les lumières des pièces n'ont donc pas d'ombres de contact ; la diffusion de la peau n'est pas floutée en espace écran, d'où un aspect plus « mat » qu'avec un profil (jugement visuel non vérifié).
|
||||
- Coûts : supersampling 125 % ≈ 1,56 fois plus de pixels → temps GPU des passes liées aux pixels ≈ +30 à +55 % ; netteté de l'étalonnage, poids TAA : < 0,1 ms ; ombres : +0,2 à +1,5 ms selon le nombre de lumières à ombre ; anisotropie 16 : < 0,3 ms ; chargement complet des textures : mémoire vidéo, pas de GPU. Raisonnement : proportionnalité aux pixels et aux texels d'ombre, passes plein écran déjà présentes ; **aucune mesure**.
|
||||
- Les textures de peau ont peut-être `NeverStream` actif (nom de propriété présent, donc probablement non défaut) : dans ce cas `MipBias` et `PoolSize` ne changent rien pour elles.
|
||||
|
||||
**Incertain** (essai qui trancherait) :
|
||||
- Nombre de LOD des deux maillages de personnages (essai : `r.ForceLOD 0` / `-1` à 5 m, section 7 ; ou lecture éditeur).
|
||||
- Valeur de `NeverStream` et dimensions des textures de peau (lecture éditeur ou commandlet).
|
||||
- Conditions et ordre des commandes du Blueprint `GI` (lecture par MCP, lot dédié).
|
||||
- Effet visuel réel de chaque réglage et coût en millisecondes sur la RX 6600M (protocole section 7).
|
||||
- Contenu hors `Content/` : `Plugins/*/Content` et `Mods/` non parcourus ; le filtre git a écarté 549 `.uasset` pour la ligne 9 du tableau 2 (ombres de contact).
|
||||
- Une capture par `Shot` contient-elle la console fermée ? (à constater à la première capture).
|
||||
|
||||
## 5. Points à confirmer (repris par la fiche suivante)
|
||||
1. Contrôle négatif : `r.SSS.Scale 0` ne change rien à la peau (section 7, étape 6). Un changement visible invaliderait la section 3.2.
|
||||
2. `r.DynamicRes.OperationMode` relevé = 0 en jeu.
|
||||
3. Valeurs relevées avant essai (étape 2) : `r.ScreenPercentage`, `r.TemporalAA.Quality`, `r.MaxAnisotropy`, niveaux `sg.*` ; elles servent de commandes de retour.
|
||||
4. GPU en ms avant / après (`stat unit`) pour chaque réglage retenu.
|
||||
5. Verdict de l'utilisateur par réglage : graver / non (grille de la section 7).
|
||||
|
||||
## 6. Questions pour la SPEC ou l'utilisateur
|
||||
1. **Piste hors console, à plus fort potentiel (non essayable ici)** : faire passer la peau de `MSM_Subsurface` à Subsurface Profile (le profil `SSP_Girl_Head` est déjà référencé par `DazSkin` et `DazSkinHide`, pas par `DazSkin_Face`). Ce changement rend `r.SSS.*` utile et coûte du GPU. Il touche des assets (227 fichiers contiennent `MSM_Subsurface`, dont des matériaux autres que la peau) : à ouvrir comme lot avec instantané, essai éditeur sur un matériau, puis décision. Voulez-vous ce lot ?
|
||||
2. Même nature : `ContactShadowLength` des lumières des pièces (propriété de lumière, ex. 0.02 d'après la plage `UIMax 0.1` de `LightComponent.h:130`) pour obtenir des ombres de contact (visage, mains, objets). Voulez-vous l'essayer dans l'éditeur ?
|
||||
3. Niveau cible : la machine d'essai joue en High (niveau 2) ; graver les réglages gratuits aux niveaux 2 et 3, les coûteux au niveau 3 seul ?
|
||||
4. Corriger la clé morte `r.PostProcessAAQuality` (les quatre sections AA ne règlent rien) : la remplacer par `r.TemporalAA.Quality` ou la retirer ? Hors périmètre de cette fiche.
|
||||
5. Le Blueprint `GI` repose résolution, pool de textures et `r.SSS.Scale` : un éventuel supersampling doit passer par ce Blueprint ou par une option du panneau Video, pas par l'ini.
|
||||
|
||||
## 7. Protocole d'essai console (≈ 15 minutes)
|
||||
|
||||
**Préparation (3 min)**
|
||||
1. Lancer `D:\Game\LifePlay_Build_5.8_Development_COM23\Windows\LifePlay.exe`, entrer dans une pièce éclairée avec un personnage immobile. Fixer la caméra : gros plan du visage et des cheveux (≈ 1 m). Ne pas ouvrir le panneau Video pendant l'essai : il réapplique les quatre `sg.*` (`LPVideoQualitySubsystem.cpp:258-269`) ; les valeurs posées en console restent prioritaires sur le Scalability (`LOG:4250`).
|
||||
2. Ouvrir la console (`²`). **Relever** en tapant chaque nom seul (la console répond `nom = "valeur"`, format vu en `LOG:1683`) et noter : `r.ScreenPercentage`, `r.DynamicRes.OperationMode`, `r.TemporalAA.Quality`, `r.TemporalAACurrentFrameWeight`, `r.Tonemapper.Sharpen`, `r.MaxAnisotropy`, `r.Shadow.MaxResolution`, `r.Shadow.MaxCSMResolution`, `r.Shadow.TexelsPerPixel`, `r.Streaming.FullyLoadUsedTextures`, `sg.ShadowQuality`.
|
||||
3. Taper `stat unit` et laisser affiché (temps image / jeu / dessin / **GPU** en ms). Capture : taper `Shot` (la console se ferme à la validation) ; les fichiers sont dans le dossier `Saved\Screenshots` du build (`Paths.cpp:553`). Une « capture » = un `Shot`, dans l'ordre : avant, après.
|
||||
|
||||
**Pour chaque réglage** : (a) `Shot` « avant » (état de départ), (b) taper la commande, attendre 3 s (5 s pour les textures), (c) `Shot` « après », noter le GPU en ms, (d) taper la commande de retour.
|
||||
|
||||
| Étape | Réglage | Commande à taper | Ce qu'il faut regarder | Coût attendu (estimé) | Commande de retour |
|
||||
|---|---|---|---|---|---|
|
||||
| 3 | **R1 Netteté de l'image par suréchantillonnage** | `r.ScreenPercentage 125` | bords des cartes de cheveux, cils, contour du visage, scintillement ; netteté de près | GPU ≈ +30 à +55 % sur les passes liées aux pixels ; si le GPU dépasse 16 ms, ne pas pousser | `r.ScreenPercentage 100` (valeur relevée) |
|
||||
| 4 | **R2 Accentuation à l'étalonnage** | `r.Tonemapper.Sharpen 0.5` | détail de la peau et des yeux en gros plan, halos aux contours des cheveux, grain | < 0,1 ms | `r.Tonemapper.Sharpen -1` |
|
||||
| 4 | **R3 Poids de l'image courante du TAA** | `r.TemporalAACurrentFrameWeight 0.08` | tourner lentement la caméra : texture de la peau et mèches plus nettes en mouvement, mais scintillement des cheveux et du visage (voir ERR-032) | ≈ 0 | `r.TemporalAACurrentFrameWeight 0.04` |
|
||||
| 5 | **R4 Ombres des personnages** | `r.Shadow.TexelsPerPixel 2.5`, puis `r.Shadow.MaxResolution 4096`, puis `r.Shadow.MaxCSMResolution 4096` | ombre du personnage sur le sol et le mur : contour net ou crénelé, ombre sous le nez et le menton, ombre sur les vêtements | +0,2 à +1,5 ms selon les lumières à ombre ; relever le GPU après la troisième commande | `r.Shadow.TexelsPerPixel 1.27324`, `r.Shadow.MaxResolution 2048`, `r.Shadow.MaxCSMResolution 2048` |
|
||||
| 6 | **R5 Textures (diagnostic)** | `r.Streaming.FullyLoadUsedTextures 1`, puis `r.MaxAnisotropy 16` | peau de très près, vêtements, sol en oblique ; si « après » = « avant », les textures sont déjà au maximum : rien à graver | pas de GPU notable ; mémoire vidéo en hausse (8 Go) : au moindre à-coup, retour | `r.Streaming.FullyLoadUsedTextures 0`, `r.MaxAnisotropy <valeur relevée>` |
|
||||
| 6bis | Contrôle négatif (1 min) | `r.SSS.Scale 0` | la peau ne doit **pas** changer (section 5, point 1) | 0 | `r.SSS.Scale 1` |
|
||||
| 7 | Diagnostic LOD (optionnel, 1 min) | à 5 m du personnage : `r.ForceLOD 0` | aucun changement = un seul LOD ou LOD 0 déjà choisi ; changement = des LOD existent et basculent tôt | ≈ 0 | `r.ForceLOD -1` |
|
||||
|
||||
**Grille à remplir**
|
||||
|
||||
| Réglage | Capture avant | Capture après | GPU avant (ms) | GPU après (ms) | Visible ? (oui / non / dégrade) | Graver ? |
|
||||
|---|---|---|---|---|---|---|
|
||||
| R1 | | | | | | |
|
||||
| R2 | | | | | | |
|
||||
| R3 | | | | | | |
|
||||
| R4 | | | | | | |
|
||||
| R5 | | | | | | |
|
||||
|
||||
Fin : taper les commandes de retour restantes, ou quitter le jeu (les valeurs de console ne sont pas conservées entre deux lancements).
|
||||
|
||||
## 8. Recommandation et diff d'ini proposé (non appliqué)
|
||||
|
||||
**Ce qu'il faut savoir avant de choisir.** Sur cinq candidats de la fiche, trois ne s'appliquent pas à la peau actuelle : `r.SSS.*` (aucun matériau à profil), `r.ContactShadows` (aucune lumière à longueur non nulle), `r.SkinCache.*` (non compilé, lecture seule) ; `r.SkeletalMeshLODBias` et `r.SkeletalMeshLODRadiusScale` sont soit déjà au maximum, soit sans objet si un seul LOD. Les réglages réellement essayables sont R1 à R5. Aucun effet visuel n'a été vu : la recommandation est **conditionnelle** aux captures de l'utilisateur.
|
||||
|
||||
**Ordre proposé (rapport effet estimé / coût)**
|
||||
1. **R2 et R3 (netteté, coût nul)** : à graver aux niveaux High (2) et Epic (3) si les captures « après » sont meilleures sans scintillement gênant. Valeurs d'essai : `r.Tonemapper.Sharpen 0.5`, `r.TemporalAACurrentFrameWeight 0.08` ; si le scintillement apparaît, redescendre à 0.06.
|
||||
2. **R4 (ombres)** : à graver **au niveau Epic seulement**. Aujourd'hui High et Epic ont les mêmes tailles d'ombre (2048) ; 4096 différencie enfin Epic. À essayer d'abord sur la machine d'essai en GPU ms (budget suggéré : ≤ +1 ms).
|
||||
3. **R5 (textures)** : à graver (`r.MaxAnisotropy=16` au niveau 3) seulement si « après » diffère de « avant ». `FullyLoadUsedTextures` n'est pas à graver (mémoire).
|
||||
4. **R1 (suréchantillonnage)** : **ne pas graver en ini** (le Blueprint `GI` repose la résolution en SetByConsole, `LOG:1787`) ; coût élevé sur une carte de 8 Go. À traiter, si l'essai plaît, comme option du panneau Video (lot de code, hors quick win).
|
||||
5. **Pistes à plus fort potentiel mais hors console** : voir section 6, questions 1 et 2 (profil de diffusion pour la peau, longueur d'ombre de contact des lumières).
|
||||
|
||||
**Diff proposé** (texte, non appliqué ; numéros de lignes de la version actuelle de `Config/DefaultScalability.ini`). Avant d'appliquer : `Tools/Snapshot.ps1` et entrée CHG. Les valeurs `0.5` et `0.08` sont celles de l'essai ; les remplacer par celles que l'utilisateur aura retenues.
|
||||
|
||||
```
|
||||
--- a/Config/DefaultScalability.ini
|
||||
+++ b/Config/DefaultScalability.ini
|
||||
@@ [ShadowQuality@3] (l.43-50)
|
||||
-r.Shadow.MaxResolution=2048
|
||||
-r.Shadow.MaxCSMResolution=2048
|
||||
+r.Shadow.MaxResolution=4096
|
||||
+r.Shadow.MaxCSMResolution=4096
|
||||
@@ [TextureQuality@3] (l.73-77) ; seulement si R5 est visible
|
||||
-r.MaxAnisotropy=8
|
||||
+r.MaxAnisotropy=16
|
||||
@@ [AntiAliasingQuality@2] (l.123-124)
|
||||
r.PostProcessAAQuality=4
|
||||
+r.TemporalAACurrentFrameWeight=0.08
|
||||
+r.Tonemapper.Sharpen=0.5
|
||||
@@ [AntiAliasingQuality@3] (l.126-127)
|
||||
r.PostProcessAAQuality=4
|
||||
+r.TemporalAACurrentFrameWeight=0.08
|
||||
+r.Tonemapper.Sharpen=0.5
|
||||
```
|
||||
|
||||
Notes sur le diff :
|
||||
- `r.Shadow.TexelsPerPixel` n'a pas de drapeau Scalability (`ShadowSetup.cpp:277-280`) : si R4 plaît avec `2.5`, la poser dans `Config/DefaultEngine.ini` section `[SystemSettings]` (`r.Shadow.TexelsPerPixel=2.5`), valable pour tous les niveaux, ou l'ajouter à `[ShadowQuality@3]` (une variable sans drapeau Scalability posée par une section Scalability est, par estimation, acceptée ; à vérifier dans le journal par une ligne `Set CVar [[r.Shadow.TexelsPerPixel:…]]`).
|
||||
- La ligne `r.PostProcessAAQuality=4` est inchangée dans le diff : elle est inerte (section 3.1) ; son sort relève de la question 4 de la section 6.
|
||||
- Les clés ajoutées à `AntiAliasingQuality` restent dans le périmètre de l'en-tête du fichier (pas de méthode d'AA, pas de GI, pas de VSM, pas de reflets : `DefaultScalability.ini:7-8`).
|
||||
- Vérification après application : relancer le build, lire `LifePlay.log` pour `Set CVar [[r.Tonemapper.Sharpen:0.5]]` aux niveaux 2 et 3 (même méthode que `LOG:442`).
|
||||
|
||||
Tours : 24 / 25
|
||||
|
||||
## Constats
|
||||
- Anomalie hors périmètre, à signaler : le Blueprint `GI` exécute `r.MorphTarget.Mode` alors que la variable est en lecture seule (`LOG:1822` `Error: r.MorphTarget.Mode is read only!`) et `r.PostProcessAAQuality 3` (`LOG:1805`, commande non reconnue). Deux erreurs de console à chaque démarrage.
|
||||
- Fichiers écrits : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\QPERS\QPERS-PRE.md`.
|
||||
- Fichiers à commiter : `A Docs/Migration/etat/REL/QPERS/QPERS-PRE.md` (dépôt du jeu, `.md` suivi sous `etat/`).
|
||||
- À verser : `lp-perf` ou `lp-build` — le journal d'un build Development (`Saved/Logs/LifePlay.log`) donne les valeurs de console réellement appliquées (`Set CVar`, priorité SetByConsole vs SetByScalability) : le lire avant de graver un réglage en ini.
|
||||
30
Docs/Migration/etat/REL/REL2/REL2-ESSAI-FINAL.md
Normal file
30
Docs/Migration/etat/REL/REL2/REL2-ESSAI-FINAL.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
Fiche REL2-ESSAI-FINAL — Niveau N1 — Modèle prévu opus (orchestration) | utilisé claude-opus-5-5 — Big Boss (local_104ff22d) — Skills lp-lot, lp-paths
|
||||
|
||||
# REL2 : cahier de l'essai final sur le Shipping 2026.10.2.2a (2026-10-21)
|
||||
|
||||
Archive : `D:\Game\LifePlay_Build_5.8_ALPHA-2026.10.2.2a_Shipping` (exe et MD5 : `REL2-T2-BUILD.md`). Le Shipping n'écrit **aucun journal** (FIX1-F6-SPEC R5) :
|
||||
les preuves sont l'écran (utilisateur) et les fichiers (relevés par Big Boss avant et après). Réserves de REL2-VAL couvertes : C1 (EF.6), C2 (EF.4), C5 (EF.2, EF.3).
|
||||
|
||||
## Avant l'essai (Big Boss, lecture seule)
|
||||
- R0 : relevé de `%LOCALAPPDATA%\LifePlay-Revival` (fichiers, octets, dates) et de `<archive>\Windows\LifePlay\Content\Saves` ; `%LOCALAPPDATA%\LifePlay` (ancienne version) inchangé depuis REL-ALPHA (68 fichiers, 19 650 943 o).
|
||||
- Aucun autre LifePlay lancé ; `UeState` = 0.
|
||||
|
||||
## Essais (l'utilisateur joue, Big Boss relève les fichiers)
|
||||
|
||||
| N° | Sujet (lot) | Geste | Attendu |
|
||||
|---|---|---|---|
|
||||
| EF.1 | Version (REL2-T1) | Lancer `LifePlay.exe` de l'archive ; regarder la version au menu principal | `2026.10.2.2a` affichée ; démarrage sans erreur |
|
||||
| EF.2 | E9 de F6, sauvegardes (FIX1-F6) | Nouvelle partie ; jouer 1 min ; sauvegarder dans un emplacement libre ; quitter le jeu | Big Boss relève : nouveau `.sav` sous `LifePlay-Revival\Saved\SaveGames`, dossier du slot sous `LifePlay-Revival\Saved\Saves\<slot>` (fichiers `.lpcharacter`) ; `<archive>\…\Content\Saves` **inchangé** |
|
||||
| EF.3 | Rechargement (FIX1-F6) | Relancer ; charger la sauvegarde de EF.2 | Partie rechargée, personnages présents, **aucun** message « Save Missing Character Data! » |
|
||||
| EF.4 | COMMUN-23.4 rejoué (SET1) | En partie, revenir au titre ; sur le nouvel écran titre, cliquer **Settings** | Onglets présents **tout de suite** ; Video et Misc complets ; aucune superposition d'ancienne vue |
|
||||
| EF.5 | Réglages en partie (SET1) | En partie, ouvrir les réglages | Nouveau panneau seul, pas d'ancienne vue au bout de 30 s |
|
||||
| EF.6 | Netteté (QPERS, CHG-386) | Qualité High ou Epic ; regarder un personnage de près | Personnage net, sans halo gênant (« un peu plus net » qu'avant) |
|
||||
| EF.7 | Touches (KEY2) | Menu Keyboard : 9 sections ; réattribuer une touche déjà prise | Demande de confirmation par seconde pression ; la touche est remplacée après confirmation |
|
||||
| EF.8 | Caméras (CAM2) | C → C1, C2, C3 ; POV souris | Comportement de COMMUN-19 (POV « d'avant ») ; ERR-145 assis en C1 **connu** (build 2), à ne pas compter |
|
||||
| EF.9 | Talons (FIX1 M-Z) | Personnage en talons debout puis assis | Pieds posés au sol, ni enfoncés ni flottants (lévitation de PNJ F8b connue, build 2) |
|
||||
| EF.10 | Discord (DISC1) | Menu du jeu | Invitation `TsKJw3Wvja` présente et cliquable |
|
||||
| EF.11 | Facultatif : sauvegarde de l'alpha 2026.10.2.1a | Charger `1.sav` de l'alpha (dans `LifePlay-Revival\Saved\SaveGames`) | Soit la partie charge, soit le message « Save Missing Character Data! » s'affiche (cas attendu si les `.lpcharacter` de l'alpha sont restés dans son archive) : noter lequel, sans plantage |
|
||||
|
||||
## Après l'essai
|
||||
- Big Boss relève de nouveau les dossiers (R1) et écrit `REL2-ESSAI-RESULTAT.md` (verdict par ligne).
|
||||
- Échec bloquant : correction, nouvelle build Shipping. Sinon : dernière vague, publication `pub/ue5.8` (push par l'utilisateur), décision de tag `v2026.10.2.2a`, mise à jour du `README.md` (version, C7).
|
||||
33
Docs/Migration/etat/REL/REL2/REL2-ESSAI-RESULTAT.md
Normal file
33
Docs/Migration/etat/REL/REL2/REL2-ESSAI-RESULTAT.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
Fiche REL2-ESSAI-RESULTAT — Niveau N1 — Modèle prévu opus (orchestration) | utilisé claude-opus-5-5 — Big Boss (local_104ff22d) — Skills lp-lot, lp-paths
|
||||
|
||||
# REL2 : résultat de l'essai final sur le Shipping 2026.10.2.2a (2026-10-21)
|
||||
|
||||
Tenu par Big Boss. Archive `D:\Game\LifePlay_Build_5.8_ALPHA-2026.10.2.2a_Shipping`, exe MD5 `E6A9033458DB3E09B59B807725061BA4` (`REL2-T2-BUILD.md`) ;
|
||||
PDB et `BUILD-ID.txt` dans `…_Shipping_PDB` (SHA-256 du PDB `BBB0C7C7…`, identique à `Binaries\Win64`). Cahier : `REL2-ESSAI-FINAL.md`.
|
||||
Réponses de l'utilisateur citées depuis `etat\BOSS\BOSS-JOURNAL.md` (09:09 à 09:27). Le Shipping n'écrit aucun journal : preuves = écran et fichiers.
|
||||
|
||||
## Relevés
|
||||
- Lancement 09:09 : trois processus (lanceur, parent, enfant avec `-UserDir="%LOCALAPPDATA%\LifePlay-Revival"`).
|
||||
- R0 (avant, `REL2-releve-R0.csv`) : `LifePlay-Revival` 28 fichiers, 8 876 821 o, dernière écriture 2026-10-17 12:35 ; ancien `LifePlay` 67 fichiers, 17 342 009 o (2026-10-20 00:08) ; `Content\Saves` absent de l'archive.
|
||||
- Après EF.2 (09:13) : `Saved\SaveGames\1.sav` (145 462 o, 09:12:58) ; `Saved\Saves\1\Characters\` `1`, `2`, `Player.lpcharacter` (09:12:58) ; `Saved\Saves\_session\Characters\` (09:12:38).
|
||||
- R1 (après, `REL2-releve-R1.csv`, jeu fermé, 0 processus) : `LifePlay-Revival` 36 fichiers, 8 794 195 o, dernière écriture 09:26:15 ; ancien `LifePlay` **inchangé** (67 fichiers, 17 342 009 o) ; `Content\Saves` toujours absent ; **0 fichier** de l'archive écrit depuis 09:05.
|
||||
|
||||
## Verdicts
|
||||
|
||||
| N° | Sujet | Réponse de l'utilisateur | Verdict |
|
||||
|---|---|---|---|
|
||||
| EF.1 | Version | « 1, 2026.10.2.2a » | PASS |
|
||||
| EF.2 | E9 de F6 (sauvegardes) | « 2 sauvé » + relevé ci-dessus | PASS |
|
||||
| EF.3 | Rechargement | « ef3 les 2 sauvegardes passent » | PASS |
|
||||
| EF.4 | COMMUN-23.4 rejoué (SET1) | « EF4 complet » | PASS (réserve C2 levée) |
|
||||
| EF.5 | Réglages en partie (SET1) | « EF5 OK » | PASS |
|
||||
| EF.6 | Netteté (QPERS) | « EF6 net, pas de halo » | PASS (réserve C1 levée) |
|
||||
| EF.7 | Touches (KEY2) | « EF7 confirmé » | PASS |
|
||||
| EF.8 | Caméras (CAM2) | « EF8 ok » | PASS (ERR-145 hors compte, build 2) |
|
||||
| EF.9 | Talons (M-Z) | « EF9 ok » | PASS |
|
||||
| EF.10 | Discord (DISC1) | « EF10 ok » | PASS |
|
||||
| EF.11 | Sauvegarde de l'alpha 2026.10.2.1a | « EF11 oui » (une des 2 sauvegardes d'EF.3) | PASS |
|
||||
|
||||
**Essai final : 11 / 11 PASS.** Réserve C5 (E9 en Shipping) levée. Restent hors build 1 : C3 (CG2, essai partiel), C4 (pièce cachée), lecture de repli et `-LPNoSavesRedirect` de F6 (non jouées), ERR-145, F7, F8b (build 2).
|
||||
|
||||
Suite : CHG de REL2 (version), `README.md` (version), dernière vague, publication `pub/ue5.8` (push par l'utilisateur), décision de tag `v2026.10.2.2a`.
|
||||
12
Docs/Migration/etat/REL/REL2/REL2-T1-IMPL.md
Normal file
12
Docs/Migration/etat/REL/REL2/REL2-T1-IMPL.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
Fiche REL2-T1-IMPL — Niveau N1 — Modèle prévu opus (orchestration) | utilisé claude-opus-5-5 — Big Boss (local_104ff22d), sans sous-agent — Skills lp-lot, lp-paths
|
||||
|
||||
# REL2-T1-IMPL : version 2026.10.2.2a (2026-10-21 08:30)
|
||||
|
||||
Ordre de l'utilisateur : « ok REL2 » (2026-10-21). Modèle : REL-ALPHA T1 (option B de REL-ALPHA : `ParseVersion` accepte le suffixe de lettres, `LPModGuard.cpp` V2).
|
||||
|
||||
- Instantané : `Tools\Snapshot.ps1 -Lot REL2 -Path Config\DefaultGame.ini` → `D:\Game\LifePlay_Backup_5.5\REL2\` (MD5 avant 4F89F2D1B63DD7D6BCAE0FA1575F6727 = valeur de REL-ALPHA T2).
|
||||
- Changement : `Config/DefaultGame.ini` ligne 4, `ProjectVersion=2026.10.2.1a` → `ProjectVersion=2026.10.2.2a` (sed sur la ligne 4 seule).
|
||||
- Contrôle : `git diff --stat` = 1 fichier, +1 / −1 ; fins de ligne LF gardées (`git ls-files --eol` : i/lf w/lf) ; MD5 après 8d7f4bdf45e4f36620ccfe043b380c66.
|
||||
- À vérifier par la VAL commune (agent distinct) : diff d'une ligne, MD5 de l'instantané = HEAD, format accepté par `ParseVersion`.
|
||||
|
||||
Fichiers : M `Config/DefaultGame.ini` ; A `Docs/Migration/etat/REL/REL2/REL2-T1-IMPL.md`.
|
||||
151
Docs/Migration/etat/REL/REL2/REL2-T2-BUILD.md
Normal file
151
Docs/Migration/etat/REL/REL2/REL2-T2-BUILD.md
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
Fiche REL2-T2 — Niveau N0 — Modèle prévu haiku/sonnet | utilisé claude-haiku-5-5 — Agent lp-builder — Skills lp-build, sk-windows-shell, sk-protocol
|
||||
# REL2-T2-BUILD : build Shipping de livraison de l'alpha 2026.10.2.2a (2026-10-21)
|
||||
|
||||
Résultat : **partiel**. Contrôle d'entrée, compilation Shipping, cuisson à froid FULL COOK, mise en paquet, CheckPackage : réussis (code 0, comptes ci-dessous). Étape 4 (copie du PDB dans `D:\Game\LifePlay_Build_5.8_ALPHA-2026.10.2.2a_Shipping_PDB` et `BUILD-ID.txt`) : **non faite, non tentée** (voir § 1 et § 11). Aucun commit, aucune modification de source, de configuration ou de Blueprint. Le lot REL-ALPHA (2026.10.2.1a) n'a pas été touché.
|
||||
|
||||
Hors gabarit : la fiche REL2-T2 demande aussi le contrôle d'entrée, la cuisson, la mise en paquet, CheckPackage, les contrôles d'archive et les durées ; ces sections sont ajoutées après le § 7 du gabarit BUILD (sections 1 à 7 conservées dans l'ordre).
|
||||
|
||||
Relevés des commandes (heures locales, 2026-10-21) : build 08:44:12 → 08:46:13 ; cuisson 08:46:44 → 08:49:34 ; paquet 08:49:50 → 08:50:42.
|
||||
|
||||
## 1. Commande exacte
|
||||
Étape 1, contrôle d'entrée (lecture seule) :
|
||||
- `pwsh -NoProfile -File "D:\Game\LifePlay-master 5.8\Tools\UeState.ps1"` (puis version `-Kind` non nécessaire, la forme sans argument répond à tous les types)
|
||||
- MD5 : `pwsh -NoProfile -Command '… Get-FileHash -Algorithm MD5 -LiteralPath … '` sur les 40 fichiers de la liste Contrôle 7 de `REL2-VAL.md` (l. 142-146), plus `Config\DefaultGame.ini` et `LifePlay.uproject` ; `Mods` (`Get-ChildItem`) ; ligne 4 de `DefaultGame.ini` (`Get-Content -TotalCount 5`).
|
||||
- `LPSaveLocation.ini` : Glob `**/LPSaveLocation.ini` sur la copie (« No files found »).
|
||||
|
||||
Étape 2, compilation :
|
||||
`pwsh -NoProfile -Command 'Set-Location "D:\Game\LifePlay-master 5.8"; & .\Tools\Build.ps1 -Lot REL2 -Target LifePlay -Config Shipping -ExtraArgs "-NoUBA" -EtatDir "D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\REL2"'` (arrière-plan, une exécution). Le `-EtatDir` absolu évite un dossier parasite `etat\REL2` (lp-build § 2).
|
||||
Équivalent UBT lancé par le script : `Build.bat LifePlay Win64 Shipping "-Project=…\LifePlay.uproject" -WaitMutex -NoHotReloadFromIDE -NoUBA`.
|
||||
|
||||
Étape 3, cuisson : `.cmd` écrit par Write, `Saved\Logs\portage\REL2-T2_Cook_20261021-085000.cmd`, une ligne :
|
||||
`@call "D:\Game\Launcher\Engine\UE_5.8\Engine\Build\BatchFiles\RunUAT.bat" BuildCookRun -project="D:\Game\LifePlay-master 5.8\LifePlay.uproject" -platform=Win64 -clientconfig=Shipping -skipbuild -cook -createreleaseversion=2026.10.2.2a -unattended -utf8output -nop4 > "…\Saved\Logs\portage\REL2-T2_Cook_20261021-085000.log" 2>&1`
|
||||
Lancé par `pwsh -NoProfile -Command '… & cmd /c "…\REL2-T2_Cook_20261021-085000.cmd" …'` (arrière-plan). Sans `-iterate`.
|
||||
|
||||
Étape 4, mise en paquet : `Saved\Logs\portage\REL2-T2_Package_20261021-085000.cmd`, une ligne :
|
||||
`@call "…\RunUAT.bat" BuildCookRun -project="…\LifePlay.uproject" -platform=Win64 -clientconfig=Shipping -skipbuild -skipcook -stage -pak -iostore -compressed -createreleaseversion=2026.10.2.2a -archive -archivedirectory="D:\Game\LifePlay_Build_5.8_ALPHA-2026.10.2.2a_Shipping" -nodebuginfo -unattended -utf8output -nop4 > "…\REL2-T2_Package_20261021-085000.log" 2>&1`
|
||||
|
||||
Étape 5, CheckPackage : `pwsh -NoProfile -File "D:\Game\LifePlay-master 5.8\Tools\CheckPackage.ps1" -Build "D:\Game\LifePlay_Build_5.8_ALPHA-2026.10.2.2a_Shipping" -Config Shipping`.
|
||||
|
||||
Étape 4 (PDB) : **non exécutée** (§ 11).
|
||||
|
||||
## 2. Code de sortie
|
||||
- Contrôle d'entrée : `UeState.ps1` code 0, `processus=0 editeur=0 compilation=0 shaders=0 jeu=0`. Ligne 4 de `Config\DefaultGame.ini` : `ProjectVersion=2026.10.2.2a`.
|
||||
- Compilation : `code=0 duree=120s erreurs=0 avertissements=0 autres=0 unites=2`, `BUILD EXIT=0` (sortie de tâche `b8l6dx3ul`).
|
||||
- Cuisson : `COOK EXIT=0` (sortie `bvj6ymj6a`) ; journal `Took 155,89s to run UnrealEditor-Cmd.exe, ExitCode=0` (l. 581), `BUILD SUCCESSFUL` (l. 585), `AutomationTool exiting with ExitCode=0 (Success)` (l. 587).
|
||||
- Paquet : `PACKAGE EXIT=0` (sortie `b359d1c17`) ; `Took 2,48s` et `Took 10,09s to run UnrealPak.exe, ExitCode=0` (l. 106, 236), `Archive command time: 15.47 s` (l. 245), `BUILD SUCCESSFUL` (l. 248).
|
||||
- CheckPackage : `Resultat : PASS (code 0)`, `CHECK EXIT=0`.
|
||||
- UeState final : `processus=0 editeur=0 compilation=0 shaders=0 jeu=0`, code 0.
|
||||
|
||||
## 3. Modules recompilés
|
||||
Journal `Saved\Logs\portage\REL2_Build_20261021-084413.log` (Grep) :
|
||||
- `Creating makefile for LifePlay (.uproject file is newer)` (l. 7) : makefile recréé (le `LifePlay.uproject` local est plus récent).
|
||||
- `[1/4] Compile [x64] Module.LifePlay.cpp [NoUba]` (l. 19) ; `[2/4] Compile [x64] Module.ModdingExtra.cpp [NoUba]` (l. 20) ; `[3/4] Link [x64] LifePlay-Win64-Shipping.exe [NoUba]` (l. 21) ; `Output binary: D:\Game\LifePlay-master 5.8\Binaries\Win64\LifePlay-Win64-Shipping.exe` (l. 26) ; `Result: Succeeded` (l. 28).
|
||||
- Résumé : `=== Unites compilees : 2` (`Module.LifePlay.cpp`, `Module.ModdingExtra.cpp`) ; `=== DLL liees : 0`.
|
||||
- Lecture (estimé) : `Module.LifePlay.cpp` est un fichier unity qui regroupe les sources du module ; les 34 fichiers modifiés depuis le tag (`REL2-VAL.md` contrôle 2) y sont donc inclus. Le journal ne contient aucune ligne `Excluded from … unity file` (le mode adaptatif n'a pas exclu de fichier). Non établi fichier par fichier : à trancher par la preuve de chargement (exe daté 08:46:12, § 6) et par un essai en jeu. Durée de 120 s courte pour un module complet : incertain.
|
||||
- Le module `LifePlayEditorTools` n'est pas dans la cible Shipping (sans objet).
|
||||
|
||||
## 4. Erreurs et avertissements nouveaux
|
||||
- Compilation : erreurs 0, avertissements 0, autres lignes d'erreur (UBT, UHT, liens) 0 (`REL2_Build_20261021-084413.txt`, l. 12-16). Le C4701 de `LPCameraModeSubsystem.cpp:1643` relevé au lot REL-ALPHA ne réapparaît pas (le code à cette ligne a changé depuis : constat, non interprété).
|
||||
- Cuisson (`REL2-T2_Cook_20261021-085000.log`, `Tools\LogStats.ps1 -Log`) :
|
||||
```
|
||||
Lignes : 587
|
||||
Erreurs : 0
|
||||
Avertissements : 0
|
||||
Fatal : 0
|
||||
FailedToLoad : 0
|
||||
LogClassError : 0
|
||||
AccessedNone : 0
|
||||
```
|
||||
`FULL COOK` (l. 253) : `FULL COOK: Incremental Cook Dependencies are disabled, and -legacyiterative was not specified.` ; `LegacyIterative` (casse exacte) : 0 ligne (Grep). Ligne l. 242 : `Falling back to legacy iterative cook mode` (Display, message informatif, même famille que REL-ALPHA).
|
||||
Paquets : `Cooked packages 8929 Packages Remain 0 Total 8929` (l. 319).
|
||||
- Paquet (`REL2-T2_Package_20261021-085000.log`) : `Packages read 8,921 files` (l. 145), `Input: 8921 Packages` (l. 218), `Input: 1.68 GiB UExp`, `819.93 MiB UBulk`. Écart 8 paquets entre cuits (8929) et paquetés (8921) : même écart que le lot REL-ALPHA (8925 / 8917) ; cause non recherchée.
|
||||
- Aucune erreur ni avertissement nouveau.
|
||||
|
||||
## 5. Toolchain
|
||||
Résumé l. 7 et journal l. 13 : `Using Visual Studio 14.50.35739 toolchain (C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.50.35717) and Windows 10.0.22621.0 SDK`. MSVC épinglé 14.50.35717 de la copie 5.8 (lp-build § 1) : **conforme**. Moteur `D:\Game\Launcher\Engine\UE_5.8\Engine` (EngineAssociation 5.8).
|
||||
|
||||
## 6. Preuve de chargement d'addon
|
||||
sans objet : la fiche ne demande pas de ligne d'addon. Le code lié est prouvé par `[1/4] Compile … Module.LifePlay.cpp` (§ 3) et par la date de l'exe : `LifePlay-Win64-Shipping.exe` daté 2026-10-21 08:46:12, 168 002 560 o (`Get-Item`, sortie Bash § 11).
|
||||
|
||||
## 7. Journaux archivés (chemins absolus)
|
||||
- Résumé compté : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\REL2\REL2_Build_20261021-084413.txt`
|
||||
- Build : `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\REL2_Build_20261021-084413.log`
|
||||
- Cuisson : `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\REL2-T2_Cook_20261021-085000.log` (+ `.cmd`)
|
||||
- Paquet : `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\REL2-T2_Package_20261021-085000.log` (+ `.cmd`)
|
||||
- Sortie de cuisson UAT (chemin cité par le journal) : `D:\Game\Launcher\Engine\UE_5.8\Engine\Programs\AutomationTool\Saved\Cook-2026.10.21-08.46.58.txt`
|
||||
|
||||
## 8. Durées par étape
|
||||
| Étape | Durée | Source |
|
||||
|---|---|---|
|
||||
| a. contrôle d'entrée | < 1 min (non chronométrée) | sortie § 1 |
|
||||
| b. compilation | 120 s (`duree=120s`) ; `Total execution time: 118.38 seconds` | résumé l. 5 ; journal l. 10 |
|
||||
| c. cuisson | 169 s (08:46:44 → 08:49:34) ; `UnrealEditor-Cmd` 155,89 s | journal l. 581 |
|
||||
| d. paquet | 52 s (08:49:50 → 08:50:42) ; archive 15,47 s | journal l. 245 |
|
||||
| e. PDB | non faite | § 11 |
|
||||
| f. CheckPackage | < 1 min (non chronométrée) | sortie § 9 |
|
||||
|
||||
## 9. CheckPackage et contrôles d'archive (établi)
|
||||
- `CheckPackage` (sortie brute) :
|
||||
```
|
||||
exe archive : D:\Game\LifePlay_Build_5.8_ALPHA-2026.10.2.2a_Shipping\Windows\LifePlay\Binaries\Win64\LifePlay-Win64-Shipping.exe (2026-10-21 08:46:12, 168002560 o)
|
||||
exe du projet : D:\Game\LifePlay-master 5.8\Binaries\Win64\LifePlay-Win64-Shipping.exe (2026-10-21 08:46:12, 168002560 o)
|
||||
[1] PASS 0 …\Windows\Manifest_NonUFSFiles_Win64.txt
|
||||
[2] PASS 0 …\Windows\Manifest_UFSFiles_Win64.txt
|
||||
[3] PASS 0 …\Intermediate\Build\Win64\x64\LifePlay\Shipping\LifePlay-Win64-Shipping.exe.rsp
|
||||
[4] PASS 0 …\Binaries\Win64\LifePlay-Win64-Shipping.target
|
||||
Resultat : PASS (code 0)
|
||||
```
|
||||
- Archive (`Get-ChildItem -Recurse -File -Force`) : **2 078 fichiers, 1 597 268 759 octets** (REL-ALPHA : 2 078 fichiers, 1 573 482 014 o).
|
||||
- Noms contenant `HyperAIStudio` ou `McpAutomationBridge` : **0**. Noms `*sentry*` : **0**. `LPSaveLocation.ini` : **0** (Get-ChildItem et Glob).
|
||||
- Liste du pak (`UnrealPak.exe … LifePlay-Windows.pak -List`, `D:\Game\Launcher\Engine\UE_5.8\Engine\Binaries\Win64\UnrealPak.exe`) : **1 735 lignes** ; `HyperAIStudio|McpAutomationBridge` : **0** ; `sentry` : **0** ; `LPSaveLocation` : **0** ; `.lpcharacter` : **0** (relevé) ; `DefaultGame.ini` : 1 entrée (contenu non lu).
|
||||
- Fichiers `.lpcharacter` hors pak (relevé seul) : **141**, tous sous `Windows\LifePlay\Content\Modules\` (vin_Base presets et quêtes, vin_Interracial, vin_NonConsensual). Aucun sous `Content\Saves` (4 fichiers dans la copie, `REL2-VAL.md` C7). Constat à décider : des données de `Content\Modules` (dépôt local non suivi, lp-paths) sont livrées en fichiers libres dans l'archive, hors pak.
|
||||
- MD5 de l'exe : `Windows\LifePlay\Binaries\Win64\LifePlay-Win64-Shipping.exe` = **E6A9033458DB3E09B59B807725061BA4** (168 002 560 o, 2026-10-21 08:46:12) ; `Binaries\Win64\LifePlay-Win64-Shipping.exe` du projet = **E6A9033458DB3E09B59B807725061BA4**, mêmes taille et date : identiques (établi).
|
||||
- Dossiers de sortie : `Releases\2026.10.2.2a` présent après cuisson (créé par la cuisson ; absence avant la cuisson non relevée). `…Shipping_PDB` : absent (`Test-Path` False, relevé après le paquet).
|
||||
|
||||
## 10. Contrôles d'entrée (établi)
|
||||
- MD5 (8 premiers caractères, `Get-FileHash`), 40 fichiers de la liste Contrôle 7 (`REL2-VAL.md` l. 142-146) : **40 identiques** à la fiche. Config : `DefaultGame.ini` 8D7F4BDF (complet 8D7F4BDF45E4F36620CCFE043B380C66, identique), `DefaultInput.ini` 1A8E89A1, `DefaultScalability.ini` B3ECB28C ; `LifePlay.uproject` complet 62335AEF2180DDA2E4FFF0874B8263CF (identique) ; Content : PC 6603C77F, Room 2B1CFA2E, CharGen 8D781EC0, CharGenSlider CBE53469, MainMenu 2815910E, VisualMorph 84DD9B17 ; Plugin ModdingExtraBPLibrary.cpp 1F93601C ; Source\LifePlay : 27 fichiers, tous identiques ; Source\LifePlayEditorTools : 5 fichiers, identiques.
|
||||
- `Mods\` : 0 entrée. `LPSaveLocation.ini` : aucun (Glob `**/LPSaveLocation.ini`, « No files found »).
|
||||
- Non rejoués (hors liste Contrôle 7, `REL-ALPHA.md` § T2.1) : MD5 de CameraMode, GI, Person, TopRight, ShowCouple, DirectControl, OutdoorRoom, Debug, SaveRelaunch, BonusReward, LifePlay.cpp (ces valeurs de COMMUN-13 sont périmées pour les fichiers modifiés depuis, `REL2-VAL.md` l. 147). Point à confirmer.
|
||||
- Arbre git : non relu dans cette session (lecture seule non faite ; le statut de départ de la conversation montre `M Config/DefaultGame.ini`, `M LifePlay.uproject`, `M` de trois fichiers `Docs/Migration/etat/BOSS|REPO`). Le build porte donc sur l'arbre de travail, `LifePlay.uproject` local compris (HyperAIStudio activé, `REL2-VAL.md` C6). Ce plugin n'a apporté aucun fichier à l'archive (§ 9 : 0 nom `HyperAIStudio`).
|
||||
|
||||
## 11. Écarts et arrêt
|
||||
- **Étape 4, copie du PDB non faite** : `…_Shipping_PDB` absent ; `BUILD-ID.txt` non écrit ; GUID RSDS non calculé. **Non tenté** : le même écrit a été refusé par le crochet `ecriture-gardien` au lot REL-ALPHA (`REL-ALPHA-T2-BUILD.md` § 11, E-D, « Chemins libres : etat/, Saved/Logs/portage/, Saved/<lot>/, le dossier temporaire »). Tenter à nouveau hors de ces chemins serait contourner la garde ; l'étape est donc laissée à un rôle autorisé ou à l'utilisateur. Commande à confier : créer `D:\Game\LifePlay_Build_5.8_ALPHA-2026.10.2.2a_Shipping_PDB`, copier le `.pdb` de `Binaries\Win64\LifePlay-Win64-Shipping.pdb` (source conservée), écrire `BUILD-ID.txt` (GUID RSDS de l'exe, SHA-256).
|
||||
- Écart de méthode : la liste d'entrée de REL-ALPHA § T2.1 (GI, Person…) n'a pas été rejouée (la fiche REL2-T2 renvoie à la seule liste Contrôle 7).
|
||||
- Rien n'a été supprimé, déplacé ni modifié hors des `.cmd` et des sorties de build. Aucun processus laissé (UeState = 0). Aucune tâche de fond en cours (trois tâches terminées : `b8l6dx3ul`, `bvj6ymj6a`, `b359d1c17`).
|
||||
|
||||
## Points à confirmer (décision de Big Boss ou de l'utilisateur)
|
||||
- Étape PDB (§ 11) : à confier à un rôle autorisé.
|
||||
- Fichiers `.lpcharacter` de `Content\Modules` livrés hors pak (141, § 9) : accepter ou exclure avant publication.
|
||||
- C1 (`DefaultScalability.ini`, CHG-386, sans IMPL ni essai en build) et C6 (`LifePlay.uproject` local) du `REL2-VAL.md` : toujours ouverts, la build les contient.
|
||||
- Unités `Module.LifePlay.cpp` seul en 120 s : confirmer la recompilation complète par un essai (exe daté, comptes déjà relevés).
|
||||
|
||||
## Constats
|
||||
- Le contrôle 7 de `REL2-VAL.md` est complet : 40 MD5 sur 40 identiques ; `LifePlay.uproject` et `DefaultGame.ini` conformes à la fiche.
|
||||
- Le C4701 de REL-ALPHA n'apparaît plus (0 avertissement). Aucun avertissement de cuisson, aucun `LegacyIterative`.
|
||||
- Écart paquets cuits / paquetés : 8 (8929 / 8921), comme le lot précédent (8925 / 8917).
|
||||
|
||||
## Trace (TRACE1)
|
||||
Trace : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\REL2\REL2_Build_20261021-084413.txt` — Fiche REL2-T2 — 2026-10-21 08:46:13
|
||||
- Commande : `Tools\Build.ps1 -Lot REL2 -Target LifePlay -Config Shipping -ExtraArgs "-NoUBA" -EtatDir …\etat\REL\REL2` ; cuisson `REL2-T2_Cook_20261021-085000.cmd` ; paquet `REL2-T2_Package_20261021-085000.cmd`.
|
||||
- Environnement: copie `D:\Game\LifePlay-master 5.8`, branche `ue5.8`, moteur UE 5.8 (`D:\Game\Launcher\Engine\UE_5.8`), MSVC 14.50.35717 ; machine calme (aucun processus Unreal au départ ni à la fin, UeState 0).
|
||||
- Attendu : code 0, 0 erreur, 0 avertissement ; FULL COOK, 0 erreur, 0 avertissement ; paquet PASS ; 0 nom HyperAIStudio/McpAutomationBridge/sentry.
|
||||
- Obtenu : compilation code 0, erreurs 0, avertissements 0, unités 2 ; cuisson 8929 paquets, LogStats Erreurs 0 / Avertissements 0 ; paquet 8921 fichiers lus, UAT code 0 ; CheckPackage PASS ; archive 2078 fichiers, 0 nom HyperAIStudio/McpAutomationBridge/sentry, pak 1735 lignes, 0 `.lpcharacter` dans le pak, 141 `.lpcharacter` libres dans `Content\Modules`.
|
||||
- Lecture : `unites=2` (unity, estimé) ; écart cuits / paquetés 8 (non expliqué) ; PDB non fait (§ 11).
|
||||
|
||||
Tours : 16 / 40 (estimé ; `python -I Tools/FicheStats.py --lot REL2` fait foi)
|
||||
|
||||
## Fichiers à commiter
|
||||
- `A Docs/Migration/etat/REL/REL2/REL2-T2-BUILD.md` (ce livrable, dépôt `D:\Game\LifePlay-master 5.8`, branche `ue5.8`).
|
||||
- Hors git ou générés par le build (à classer par le gardien si besoin) : `Docs\Migration\etat\REL\REL2\REL2_Build_20261021-084413.txt` ; `Saved\Logs\portage\REL2_Build_*`, `REL2-T2_Cook_*`, `REL2-T2_Package_*` (`.cmd` et `.log`) ; `Releases\2026.10.2.2a\` (cuisson) ; `Binaries\`, `Intermediate\` (build).
|
||||
- Aucun fichier de `Source/`, `Config/`, `Content/`, `Plugins/`, `Tools/` écrit ou modifié.
|
||||
|
||||
## À verser
|
||||
- `À verser : lp-build § 8 — Tools\EtatDir.ps1 : le lot REL2 est hors table ; passer -EtatDir absolu (etat\REL\REL2) évite un dossier parasite.`
|
||||
- `À verser : lp-build § 8 — UnrealPak -List se lit en capturant la sortie dans une variable PowerShell (\$l = & \$u \$pak -List), sans redirection (crochet).`
|
||||
|
||||
## État de reprise
|
||||
- Établi : étapes 1, 2, 3, 4 (paquet), 5 (CheckPackage) faites et PASS ; aucun processus laissé.
|
||||
- Reste : étape 4 PDB (`…_Shipping_PDB`, `.pdb`, `BUILD-ID.txt`) par un rôle autorisé ; décisions des points à confirmer.
|
||||
- Prochaine commande (rôle autorisé) : copie du `LifePlay-Win64-Shipping.pdb` de `D:\Game\LifePlay-master 5.8\Binaries\Win64\` vers `D:\Game\LifePlay_Build_5.8_ALPHA-2026.10.2.2a_Shipping_PDB`, puis `BUILD-ID.txt`.
|
||||
|
||||
Suite : orchestrateur doit confier l'étape PDB (§ 11) à un rôle autorisé ou à l'utilisateur, et trancher les points à confirmer ; état : build, cuisson, paquet et CheckPackage faits, PDB en attente.
|
||||
190
Docs/Migration/etat/REL/REL2/REL2-VAL.md
Normal file
190
Docs/Migration/etat/REL/REL2/REL2-VAL.md
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
Fiche REL2-VAL — Niveau N1 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-validator (A-VAL) — Skills sk-protocol, sk-recount, debug-verification, lp-validate
|
||||
# REL2-VAL : VAL commune de la build 1 (alpha 2026.10.2.2a), statique, sans jeton UE (2026-10-21)
|
||||
|
||||
Ordonnateur : Big Boss (`local_104ff22d`). Rien n'a été modifié hors ce livrable ; aucun jeton UE, aucun jeu lancé, aucune compilation, aucune commande git qui écrit.
|
||||
Copie : `D:\Game\LifePlay-master 5.8`, branche `ue5.8` (`git rev-parse --abbrev-ref HEAD`), HEAD `05364875f7783502376fa8f2b4e0669cd4ecc93f` (0536487). Tag de base `v2026.10.2.1a` = `2f5d51b74d1c99ede72126a7ced12034eea768a9` (2026-10-14 18:25).
|
||||
État de l'arbre au contrôle (`git status --short`) : `M Config/DefaultGame.ini`, `M LifePlay.uproject`, `M` de trois fichiers `Docs/Migration/etat/BOSS|REPO`, plus des fichiers non suivis (`Docs/LP-PROJET.ini`, `etat\AG\ORGA2`, `etat\REL\ERR145|GIREV|REL2`). Aucun fichier de `Source`, `Plugins`, `Content` modifié ou non suivi ; `git diff --stat HEAD -- Config Source Plugins Content` : `Config/DefaultGame.ini | 2 +-`, 1 fichier.
|
||||
|
||||
## 1. Fiches amont relues
|
||||
|
||||
- `etat\REL\REL2\REL2-T1-IMPL.md` (seule IMPL de REL2 ; lue en entier, 13 lignes).
|
||||
- `etat\REL\ALPHA\REL-ALPHA.md` (T1v, T2.1 lus l. 1 à 80) ; `Source\LifePlay\LPModGuard.cpp` l. 40 à 119.
|
||||
- Bilans d'essai `etat\BOSS\COMMUN-14, 16, 17, 18, 19, 20, 21, 23-BILAN.md` (comptes de verdicts et cas liés aux changements) ; `COMMUN-15-TESTS.md` et `COMMUN-22\COMMUN-22-BUILD.md` (pas de bilan : voir C4) ; `BOSS-JOURNAL.md` l. 1049 à 1062 (QPERS) ; `BOSS-ETAT.md` (extraits).
|
||||
- IMPL/BUILD/VAL citées par MD5 (colonne « Fiche qui cite le MD5 actuel » du contrôle 2).
|
||||
- `Docs\Journal_Modifications.md` l. 1134 à 1150 (CHG-370 à CHG-386).
|
||||
- Non relus ligne à ligne : les journaux de jeu (`COMMUN-*\*.log`), lus seulement via les bilans.
|
||||
|
||||
## 2. Points à confirmer des IMPL amont
|
||||
|
||||
| Id | Point (REL2-T1-IMPL, l. 10) | Résultat |
|
||||
|---|---|---|
|
||||
| P1 | Diff d'une ligne | PASS (contrôle 1.1) |
|
||||
| P2 | MD5 de l'instantané = MD5 de HEAD | PASS (contrôle 1.2) |
|
||||
| P3 | Format accepté par `ParseVersion` | PASS-STATIC (contrôle 1.4, lecture du code ; non exécuté) |
|
||||
|
||||
## 3. Critères rejoués
|
||||
|
||||
Légende : PASS, CONSTAT (écart ou réserve, non bloquant), ÉCHEC (bloquant). Aucun ÉCHEC.
|
||||
|
||||
### Contrôle 1 — T1v
|
||||
|
||||
| N° | Contrôle | Commande | Résultat brut | Verdict |
|
||||
|---|---|---|---|---|
|
||||
| 1.1 | `git diff -- Config/DefaultGame.ini` = 1 ligne | `git diff -- Config/DefaultGame.ini` | un seul hunk `@@ -1,7 +1,7 @@` : `-ProjectVersion=2026.10.2.1a` / `+ProjectVersion=2026.10.2.2a` (ligne 4) ; `git diff --stat HEAD -- Config` : `1 file changed, 1 insertion(+), 1 deletion(-)` | PASS |
|
||||
| 1.2 | MD5 instantané = MD5 HEAD | `md5sum "D:/Game/LifePlay_Backup_5.5/REL2/Config/DefaultGame.ini"` ; `git show HEAD:Config/DefaultGame.ini \| md5sum` ; `manifest.csv` | `4f89f2d1b63dd7d6bcae0fa1575f6727` des deux côtés ; manifeste : `"Config\DefaultGame.ini","True","3324","4F89F2D1B63DD7D6BCAE0FA1575F6727","2026-10-21T08:29:55"`, seul fichier du manifeste | PASS |
|
||||
| 1.3 | Aucun autre fichier de Config modifié | `git diff --name-only HEAD -- Config` | `Config/DefaultGame.ini` (1 ligne de sortie) | PASS |
|
||||
| 1.4 | Format accepté par `ParseVersion` | Read `LPModGuard.cpp:55-92` ; `git diff --stat v2026.10.2.1a HEAD -- Source/LifePlay/LPModGuard.cpp Source/LifePlay/LPModGuard.h` | découpe sur `.` → `2026`,`10`,`2`,`2a` ; lettres ASCII de fin de la dernière composante retirées (l. 61-75) → `2` ; composantes non vides, ≤ 9 chiffres, chiffres seuls (l. 76-89) → `{2026,10,2,2}`, `true`. `LPModGuard.cpp` et `.h` : 0 ligne de différence depuis le tag (MD5 `54aac4d9…` / `c09543be…` = valeurs de `REL-ALPHA.md` l. 46). Estimé par lecture, non exécuté | PASS-STATIC |
|
||||
| 1.5 | Fins de ligne conservées | `git ls-files --eol Config/DefaultGame.ini` | `i/lf w/lf attr/-text` | PASS |
|
||||
| 1.6 | MD5 de la nouvelle valeur | `md5sum Config/DefaultGame.ini` | `8d7f4bdf45e4f36620ccfe043b380c66` = valeur citée par `REL2-T1-IMPL.md` l. 9 | PASS |
|
||||
|
||||
### Contrôle 2 — Inventaire `v2026.10.2.1a..HEAD` (Source, Plugins, Config, Content)
|
||||
|
||||
Commandes : `git diff --name-status v2026.10.2.1a..HEAD -- Source Plugins Config Content` → **34 fichiers** ; recompte `… | cut -c1 | sort | uniq -c` : `11 A`, `23 M`, 0 `D` (11 + 23 = 34) ; `git diff --stat …` : `34 files changed, 3634 insertions(+), 141 deletions(-)`. Hors liste : `Content/Heavy` (ignoré, `git ls-files Content/Heavy | wc -l` = 0). Les 586 fichiers du diff global du tag comprennent `Docs/`, `Tools/` (retirés de l'index par CHG-357), `.gitignore`, `README.md` : hors périmètre.
|
||||
|
||||
Les 34 fichiers sont propres par rapport à HEAD (`git diff --quiet HEAD -- <fichier>` : 34 « CLEAN »). Aucun fichier de `Source`, `Plugins/ModdingExtra`, `Content/BPs`, `Content/UI`, `Config` n'est plus récent que le 2026-10-20 21:40 (`find … -newermt`) sauf `Config/DefaultScalability.ini` (22:49) et `Config/DefaultGame.ini` (2026-10-21 08:29) ; l'exe de la dernière build d'essai (COM23) date de 21:37.
|
||||
|
||||
« Fiche » = fiche qui cite le MD5 actuel (grep des 8 premiers caractères dans `etat\**\*.md`). Recoupé avec la date du dernier commit du fichier (`git log -1`) : aucun fichier n'a de MD5 plus récent que celui cité. PASS = fiche IMPL/BUILD/VAL/BILAN et CHG trouvés et MD5 du disque cité.
|
||||
|
||||
| Fichier | CHG (journal l. 1134-1150) | Fiche qui cite le MD5 actuel | MD5 disque (complet) | Verdict |
|
||||
|---|---|---|---|---|
|
||||
| Config/DefaultInput.ini | 373 | KEY2-BUILD-01/02, KEY2-IMPL-01, KEY2-VAL-01 | 1a8e89a1ac4acc462280e654ffe4ffd8 | PASS |
|
||||
| Config/DefaultScalability.ini | 386 | **seulement** `BOSS-JOURNAL.md` l. 1055 (`3dca7e5d -> b3ecb28c`) et `QPERS-PRE.md` ; **aucune IMPL, BUILD ni VAL** | b3ecb28c561866d90bb96476387e298c | CONSTAT C1 |
|
||||
| Content/BPs/PC.uasset | 375, 376 | CAM2-IMPL-06, COMMUN-19-BILAN, STM1-B5-FIN | 6603c77ff670d51927863cbd9d56203c | PASS |
|
||||
| Content/BPs/Room.uasset | 375, 376 | CAM2-IMPL-02 à 06, CAM2-VAL-02/03, COMMUN-17-BUILD | 2b1cfa2eb1ea51f632eef80d4271b9e4 | PASS |
|
||||
| Content/UI/CharGen.uasset | 371 | CG2-IMPL-01, CG2-VAL-01, COMMUN-14-BUILD | 8d781ec0b94318b5bfbf22ee3b33556a | PASS |
|
||||
| Content/UI/CharGenSlider.uasset | 371 | idem | cbe53469fc73e7829a00710126095c7e | PASS |
|
||||
| Content/UI/VisualMorph.uasset | 371 | idem | 84dd9b17b977a007f9a13940406e970a | PASS |
|
||||
| Content/UI/MainMenu.uasset | 380 | DISC1-B1, COMMUN-20-BUILD/BILAN | 2815910e8a7f0f48a9fdb1e172c7eac5 | PASS |
|
||||
| Plugins/ModdingExtra/…/ModdingExtraBPLibrary.cpp | 381 | FIX1-F6-IMPL, FIX1-F6-VAL, COMMUN-21-BILAN | 1f93601c71d126f173fe30636aec0660 | PASS |
|
||||
| Source/LifePlay/LPAssetRegistryHelpers.cpp | 370 | STM1-IMPL-01, STM1-B1-VAL | 61b641efdff8942d0cceb827e5668c8e | PASS |
|
||||
| Source/LifePlay/LifePlay.cpp | 370 | idem | c3d0b3b7ad8210404284f1faf1b27bbd | PASS |
|
||||
| Source/LifePlay/LifePlay.h | 370 | idem | df5da24a8457f802b87eb87e103e4352 | PASS |
|
||||
| Source/LifePlay/LPCityTraceSubsystem.cpp (A) | 370 | idem | e5a0d22de9889c9265456c9b4f66fa59 | PASS |
|
||||
| Source/LifePlay/LPCityTraceSubsystem.h (A) | 370 | idem | 47769ceca14092febc943cd499233117 | PASS |
|
||||
| Source/LifePlay/LPCityWaterMask.h (A) | 379 | STM1-B6-FIN, COMMUN-20-BILAN | 966dc14d525c34c7fd19d0f0b73b8a6d | PASS |
|
||||
| Source/LifePlay/LPCityWaterSubsystem.cpp (A) | 372, 379 | idem | 9c0b257ee0ae377146aeda72519330bf | PASS |
|
||||
| Source/LifePlay/LPCityWaterSubsystem.h (A) | 372, 379 | idem | 2cdc10018eb1287d7f9e302eee182185 | PASS |
|
||||
| Source/LifePlay/LPCameraModeSubsystem.cpp | 373-376, 383 | FIX1-F8a-IMPL, COMMUN-23-BILAN | 976bf0a458b87f9aecf974fcec3209f0 | PASS |
|
||||
| Source/LifePlay/LPCameraModeSubsystem.h | 373, 374 | CAM2-IMPL-02/03, KEY2-IMPL-01 | 36feac2a77e13529a8ea689be74c954f | PASS |
|
||||
| Source/LifePlay/LPRoomBoundsCameraModifier.cpp (A) | 375, 376 | CAM2-IMPL-03 à 06, CAM2-VAL-03 | a3b0319458288ceb69293563b0bea35b | PASS |
|
||||
| Source/LifePlay/LPRoomBoundsCameraModifier.h (A) | 375, 376 | idem | f5eeae0574f760ed2382c2538a23e1a9 | PASS |
|
||||
| Source/LifePlay/LPKeyboardSubsystem.cpp | 373, 376, 378, 382 | KEY2-BUILD-04, SET1-V1b-IMPL, COMMUN-21-BILAN | 611c21489d80374a4817f70e408cf4db | PASS |
|
||||
| Source/LifePlay/LPKeyboardSubsystem.h | 373 | KEY2-IMPL-01 | 06793e5749102b5a943ee8bbc8a1f625 | PASS |
|
||||
| Source/LifePlay/LPSettingsSubsystem.cpp | 373, 385 | SET1-V1b-IMPL, COMMUN-23-BILAN | 6277a8fc139c05dc10e302f88de0f8d9 | PASS |
|
||||
| Source/LifePlay/LPSettingsSubsystem.h | 385 | idem | 138350efe8473c430db984db63c8feac | PASS |
|
||||
| Source/LifePlay/LPColorGradeSubsystem.cpp | 385 | idem | 5be400543166b6de7a4a88f6097a9d93 | PASS |
|
||||
| Source/LifePlay/LPVideoQualitySubsystem.cpp | 385 | idem | c3055197030bdbbce813df4cc6d7cd63 | PASS |
|
||||
| Source/LifePlay/LPModInfoSubsystem.cpp | 385 | idem | 98206e688308e908b04ae15cf408e1bb | PASS |
|
||||
| Source/LifePlay/LPDirectControlSubsystem.cpp | 384 | FIX1-MZ2-IMPL, COMMUN-23-BILAN | 86ef519e880989941e033edeadda7c26 | PASS |
|
||||
| Source/LifePlayEditorTools/LPBuildCityWaterCommandlet.cpp (A) | 372, 379 | STM1-B6-FIN, COMMUN-20-BILAN | fa6fbb72cabc0fd73663ef0e86942309 | PASS |
|
||||
| Source/LifePlayEditorTools/LPBuildCityWaterCommandlet.h (A) | 372 | STM1-IMPL-02 | 7b1e1a523d914f1cad832ff40ada1710 | PASS |
|
||||
| Source/LifePlayEditorTools/LPImportCityOSMCommandlet.cpp (A) | 377 | STM1-B5-FIN | 1470d0b30d0eb5092aee4659a91bd342 | PASS |
|
||||
| Source/LifePlayEditorTools/LPImportCityOSMCommandlet.h (A) | 377 | STM1-B5-FIN | d3f90da28f235b21c1867f452344c24b | PASS |
|
||||
| Source/LifePlayEditorTools/LifePlayEditorTools.Build.cs | 372, 377 | STM1-B3-FIN | da4771a9ddd0a921a538ae52369f5c62 | PASS |
|
||||
|
||||
Compte : 34 lignes = 33 PASS + 1 CONSTAT (C1). Le module `LifePlayEditorTools` (5 fichiers du tableau) est un module éditeur : absent de la cible Shipping. Journal : 17 lignes CHG-370 à CHG-386 présentes (l. 1134-1150) ; CHG-379 cite aussi `CentralLondon_Mask.uasset` et CHG-377 `Paris.uasset`, sous `Content/Heavy` (ignoré, hors diff, non vérifiés ici : C7).
|
||||
|
||||
### Contrôle 3 — Builds d'essai utilisateur
|
||||
|
||||
| Changement (CHG) | Essai en jeu (bilan) | Verdict |
|
||||
|---|---|---|
|
||||
| CHG-370 trace de ville (STM1) | COMMUN-14.1 PASS (`COMMUN-14-BILAN.md`) ; COMMUN-16.25 PASS | PASS |
|
||||
| CHG-371 CG2 (3 Blueprints) | COMMUN-14 : .6 et .10 PASS partiel (boutons de créature non vus), .8 et .9 non joués (C8, Q8 reportés en build 2) ; aucun second essai | CONSTAT C3 |
|
||||
| CHG-372 eau de Londres | COMMUN-16.23 PASS partiel (maisons dans le fleuve), puis COMMUN-20.7 et COMMUN-21.13 PASS | PASS |
|
||||
| CHG-373 à 376 CAM2 et KEY2 | COMMUN-15 suspendu (KO bloquant) ; COMMUN-16 : 12 PASS, 4 KO ; COMMUN-17 : 3 PASS, 14 non joués ; COMMUN-18 : 18 PASS, 1 FAIL (.2), 1 non concluant (.10) ; COMMUN-19 : 11 PASS dont la résolution du FAIL .2 par CAM2-IMPL-06 ; COMMUN-20 : 12 PASS (dont V/X du couple .12). L'état final (MD5 actuels de `PC`, `Room`, `RoomBounds`, `Keyboard`) a été joué en COMMUN-19, 20 et 21 | PASS avec réserve (C4 : COMMUN-18.10 « pièce cachée » jamais atteint, reporté en build 2) |
|
||||
| CHG-377 commandlet OSM | éditeur seulement, aucun essai en jeu requis (STM1-B5-FIN, compilation) | sans objet |
|
||||
| CHG-378 KEY2 sections | COMMUN-20.1 à .5 PASS | PASS |
|
||||
| CHG-379 Tamise (option D) | COMMUN-20.6-.8 PASS, COMMUN-21.13 PASS, COMMUN-23.7c PASS (« quelques blocs gris restent » : volumes de la carte, build 2) | PASS |
|
||||
| CHG-380 lien Discord | COMMUN-20.9 PASS | PASS |
|
||||
| CHG-381 F6 sauvegardes | COMMUN-21.1-.3 et .6 PASS ; .4 sans objet (repli de lecture non éprouvé) ; .5 non joué (`-LPNoSavesRedirect`) ; **E9 (Shipping, `%LOCALAPPDATA%\LifePlay-Revival`) jamais joué** | PASS avec réserve (C5) |
|
||||
| CHG-382 KEY2 second appui | COMMUN-21.7 à .11 PASS | PASS |
|
||||
| CHG-383 F8a | COMMUN-23.7a PASS (22:03) | PASS |
|
||||
| CHG-384 M-Z talons | COMMUN-23.6 PASS (meshZ −80,4 conservé, 0 ligne `M-Z :`) | PASS |
|
||||
| CHG-385 SET1 | COMMUN-23.1 à .5 PASS ; **.4 (onglets au titre après retour de partie) incertain** : ligne `onglets poses … (ecran titre)` absente du journal, rejeu prévu à l'essai final | CONSTAT C2 |
|
||||
| CHG-386 QPERS (`r.Tonemapper.Sharpen=0.5`, High/Epic) | **aucun essai de l'ini** ; essai par commande console le 2026-10-20 22:38 (« un peu plus net »), gravé à 22:49 (`BOSS-JOURNAL.md` l. 1051, 1055), après la dernière build d'essai (COM23, exe 21:37) | CONSTAT C1 |
|
||||
|
||||
Bilans : COMMUN-17 à 23 existent sauf COMMUN-22 (ni fiche de tests ni bilan : séance FIX1-MES sur la build COM22 « F8a + trace M-Z », verdicts dans `BOSS-JOURNAL.md` l. 1022-1028 et annexe de `COMMUN-23-BILAN.md`). Dernière build d'essai : `D:\Game\LifePlay_Build_5.8_Development_COM23` (exe 335 855 104 octets, 2026-10-20 21:37). Aucun changement de code ou de Blueprint n'est postérieur à cette build (contrôle 2).
|
||||
|
||||
### Contrôle 4 — Restes de débogage (code modifié)
|
||||
|
||||
Commande : `git diff -U0 v2026.10.2.1a HEAD -- Source Plugins | grep -E '^\+\+\+ |^\+.*(UE_LOG|UE_BUILD_SHIPPING|WITH_EDITOR|FAutoConsole|IConsoleManager|RegisterConsole|Exec\(|FConsoleCommand|PersonsLog|DrawDebug)'` → 74 lignes, relues en entier (fichier du scratchpad).
|
||||
|
||||
| Point | Constat | Verdict |
|
||||
|---|---|---|
|
||||
| Traces `UE_LOG` Warning | 2 : `ModdingExtraBPLibrary.cpp` (« liste lue dans Content, Saves non redirige pour les listes ») et `LPCityWaterSubsystem.cpp` (« masque … illisible ») : cas d'exception seulement | PASS |
|
||||
| Traces `UE_LOG` Display | ModdingExtra F6 (4), `LPColorGrade`, `LPModInfo`, `LPSettings` (2), `LPVideoQuality`, `LPKeyboard` (2), `LPDirectControl` (M-Z, 1) : à l'ouverture d'un menu ou à l'événement, pas par trame ; COMMUN-23 : 0 ligne `M-Z :`, 5 `onglets poses` en 17 min | PASS |
|
||||
| Traces `Log` (CameraMode, CityTrace, CityWater) | niveau `Log`, par événement ; ex. `POV souris` 52 lignes, `C1 souris` 23 lignes sur un essai (COMMUN-20) | PASS |
|
||||
| Compilées en Shipping ? | non : ni `bUseLoggingInShipping` ni `NO_LOGGING` forcé dans `Source/*.Target.cs` ou `Config` (Grep sur `Source` : seul le commentaire `LPSessionLogSubsystem.cpp:25`) → `UE_LOG` supprimé du Shipping par défaut du moteur | PASS (estimé par le défaut moteur, non exécuté) |
|
||||
| `-LPPersonsLog` actif par défaut | non : `LPDebugSubsystem.cpp:638-642` lit le paramètre de ligne de commande ; fichier non modifié depuis le tag ; sous `#if !UE_BUILD_SHIPPING` (l. 7 à 820) | PASS |
|
||||
| `#if !UE_BUILD_SHIPPING` attendus | `LPCityTraceSubsystem.cpp` (corps, commande `LP.CityTrace`) et `.h` (commentaire) présents. Seule commande console ajoutée : `LP.CityTrace` (aucun autre `RegisterConsoleCommand`, `Exec(`, `FAutoConsole` dans le diff) | PASS |
|
||||
| Interrupteur de ligne de commande conservé en Shipping | `-LPNoSavesRedirect` (F6) : repli volontaire vers l'ancien chemin, sans effet par défaut | PASS (non éprouvé en jeu : C5) |
|
||||
| Chemins absolus de la machine | `git diff -U0 … -- Source Plugins Config \| grep -E '^\+' \| grep -nE '[A-Za-z]:[\\/]\|<profil>\|/Users/'` : sortie vide (motif non éprouvé sur un cas positif : lire « aucun trouvé ») | PASS |
|
||||
|
||||
### Contrôle 5 — `Mods\`, `LPSaveLocation.ini`, `LifePlay.uproject`
|
||||
|
||||
| Point | Commande | Résultat | Verdict |
|
||||
|---|---|---|---|
|
||||
| `Mods\` vide | `ls -d Mods` ; `ls -A Mods \| wc -l` | dossier présent, 0 entrée | PASS |
|
||||
| `LPSaveLocation.ini` | `find . -name LPSaveLocation.ini -not -path './.git/*'` | 0 résultat | PASS |
|
||||
| `Content/Saves` (ignoré, présent) | `find Content/Saves -type f` | 4 fichiers : `Default/Characters/Player.lpcharacter`, `_session/Characters/1.lpcharacter`, `2.lpcharacter`, `3.lpcharacter` ; `DirectoriesToAlwaysCook=/Game` ne cuit que des assets ; l'archive reste à contrôler | CONSTAT C7 |
|
||||
| `LifePlay.uproject` | `git diff HEAD -- LifePlay.uproject` ; JSON : `pwsh … Get-Content -Raw … \| ConvertFrom-Json \| Out-Null` sans erreur | modifié localement (15 insertions, 7 suppressions, daté 2026-10-19 23:32), **non committé volontairement** (`BOSS-ETAT.md` l. 145, 175). Diff : (a) `McpAutomationBridge` (Enabled false, TargetAllowList Editor) retiré de sa place d'origine (l. 52-57) et ajouté en fin de liste, contenu identique ; (b) **ajout de `HyperAIStudio`** (`Enabled: true`, `MarketplaceURL`, `SupportedTargetPlatforms: Win64`, **sans** `TargetAllowList`) en fin de liste. Le `.uproject` du tag n'a pas cette entrée | CONSTAT C6 |
|
||||
|
||||
Ce changement local d'`uproject` **entre dans toute build faite depuis cette copie** (UBT et UAT lisent le fichier sur disque, pas HEAD) ; les builds Development COMMUN-14 à 23 l'avaient déjà. HyperAIStudio : modules de type `Editor` (`HyperAIStudio.uplugin` l. 18-40 lues), donc non liés au Shipping ; le plugin a un dossier `Content` et `"CanContainContent": true`. Le Shipping `2026.10.2.1a` (tag) a été construit sans cette entrée. Incertain : effet sur le contenu de l'archive Shipping ; l'essai qui tranche est `CheckPackage` Shipping (T2.5).
|
||||
|
||||
### Contrôle 6 — PubCheck sur l'arbre
|
||||
|
||||
Commande : `pwsh -NoProfile -File Tools\PubCheck.ps1 -Arbre ue5.8 < /dev/null` → sortie : `PubCheck : 0 constat(s)` ; code de sortie `0`. PASS.
|
||||
|
||||
### Contrôle 7 — MD5 de contrôle d'entrée pour la build Shipping (comme REL-ALPHA T2.1)
|
||||
|
||||
À rejouer avant `Build.ps1` par `Get-FileHash -Algorithm MD5` ; écart = ARRÊT. Les 8 premiers caractères suffisent à la comparaison rapide ; valeurs complètes au contrôle 2. Cette liste remplace celle de COMMUN-13 (`REL-ALPHA.md` l. 37-46), périmée pour tous les fichiers ci-dessous.
|
||||
|
||||
- Config : `DefaultGame.ini` **8d7f4bdf** (`ProjectVersion=2026.10.2.2a`, LF) ; `DefaultInput.ini` 1a8e89a1 ; `DefaultScalability.ini` b3ecb28c.
|
||||
- Contenu : `PC.uasset` 6603c77f ; `Room.uasset` 2b1cfa2e ; `CharGen` 8d781ec0 ; `CharGenSlider` cbe53469 ; `MainMenu` 2815910e ; `VisualMorph` 84dd9b17.
|
||||
- Plugin : `ModdingExtraBPLibrary.cpp` 1f93601c.
|
||||
- `Source/LifePlay` : `LPAssetRegistryHelpers.cpp` 61b641ef ; `LPCameraModeSubsystem.cpp` 976bf0a4 / `.h` 36feac2a ; `LPCityTraceSubsystem.cpp` e5a0d22d / `.h` 47769cec ; `LPCityWaterMask.h` 966dc14d ; `LPCityWaterSubsystem.cpp` 9c0b257e / `.h` 2cdc1001 ; `LPColorGradeSubsystem.cpp` 5be40054 ; `LPDirectControlSubsystem.cpp` 86ef519e ; `LPKeyboardSubsystem.cpp` 611c2148 / `.h` 06793e57 ; `LPModInfoSubsystem.cpp` 98206e68 ; `LPRoomBoundsCameraModifier.cpp` a3b03194 / `.h` f5eeae05 ; `LPSettingsSubsystem.cpp` 6277a8fc / `.h` 138350ef ; `LPVideoQualitySubsystem.cpp` c3055197 ; `LifePlay.cpp` c3d0b3b7 ; `LifePlay.h` df5da24a ; `LPModGuard.cpp` 54aac4d9 ; `LPModGuard.h` c09543be.
|
||||
- `Source/LifePlayEditorTools` (hors cible Shipping, pour mémoire) : `LPBuildCityWaterCommandlet.cpp` fa6fbb72 / `.h` 7b1e1a52 ; `LPImportCityOSMCommandlet.cpp` 1470d0b3 / `.h` d3f90da2 ; `LifePlayEditorTools.Build.cs` da4771a9.
|
||||
- Inchangés depuis le tag (absents du diff) : GI, Person, TopRight, ShowCouple, OutdoorRoom, Debug, SaveRelaunch, BonusReward. Leurs MD5 de COMMUN-13 (`REL-ALPHA.md` l. 38-44) restent la référence ; **non rejoués ici** (chemins non relevés), à rejouer en T2.1.
|
||||
- Autres conditions de T2.1 : `UeState.ps1` = 0 processus ; `Mods\` vide ; aucun `LPSaveLocation.ini` (conformes à cet instant, contrôle 5).
|
||||
|
||||
## 4. Diff lu en entier
|
||||
|
||||
- Lu en entier : `Config/DefaultGame.ini` (1 ligne), `Config/DefaultInput.ini` et `DefaultScalability.ini` (diffs complets), `LifePlay.uproject` (diff complet).
|
||||
- `DefaultInput.ini` : retrait de `SpeedUp/SpeedDown` sur pavé, `Equals`, `Hyphen`, `TestScenes` sur `Tilde`, `MoveForward` sur `Z`, `MoveRight` sur `Q` ; ajout `ActionPanel` (Q), `CameraHeight` (G/B), `CoupleMoveY` (V/X) : cohérent avec `COMMUN-15-TESTS.md` § 1 (estimé, non comparé caractère à caractère à `KEY2-SPEC-01.md`). `DefaultScalability.ini` : +4 lignes (deux commentaires, deux `r.Tonemapper.Sharpen=0.5` sous `[AntiAliasingQuality@2]` et `@3`). Fins de ligne CRLF conservées pour ces deux fichiers (`git ls-files --eol` : `i/crlf w/crlf`).
|
||||
- Code C++ (Source, Plugins) : **non relu ligne à ligne** (3634 lignes ajoutées) ; validé par les IMPL/VAL/BUILD amont, les MD5 identiques à ceux des builds jouées et le balayage ciblé du contrôle 4. Les 6 `.uasset` sont binaires : seul le MD5 est comparé.
|
||||
- `REL2-T1-IMPL.md` l. 8 déclare « sed sur la ligne 4 seule » pour `DefaultGame.ini` : écart de méthode au sens de `sk-protocol` § 7 (Edit prescrit), sans effet mesuré (diff d'une ligne, LF gardé).
|
||||
|
||||
## 5. Verdict
|
||||
|
||||
**PASS-STATIC : prêt pour la build Shipping, aucun bloquant.**
|
||||
- T1v : PASS (diff, MD5 de l'instantané, aucun autre fichier de Config) ; format de version : PASS-STATIC.
|
||||
- Inventaire : 33 fichiers sur 34 couverts par IMPL/BUILD et CHG, à MD5 identique ; le 34e (`DefaultScalability.ini`) est couvert par CHG-386 et le journal de Big Boss, sans IMPL, VAL ni build.
|
||||
- Aucun reste de débogage actif en Shipping ; `Mods\` vide ; aucun `LPSaveLocation.ini` ; PubCheck 0.
|
||||
- Réserves à porter à l'essai final et à la décision de Big Boss : C1 à C7.
|
||||
|
||||
Témoin en jeu (R8) : les correctifs de comportement ont leur témoin au contrôle 3 (COMMUN-19.1, 20.1-.12, 21.1-.14, 23.1-.7). QPERS : `Témoin en jeu : à créer` (cas à demander à l'orchestrateur, fiche FIT).
|
||||
|
||||
## 6. Points à confirmer par l'utilisateur
|
||||
|
||||
- [ ] C1 : accepter de livrer `r.Tonemapper.Sharpen=0.5` (High/Epic) sans essai de l'ini en build, ou le faire contrôler à l'essai final Shipping.
|
||||
- [ ] C6 : `LifePlay.uproject` (HyperAIStudio activé) : construire avec la copie locale telle quelle, ou retirer l'entrée avant le Shipping (décision de Big Boss ; ce validateur ne le fait pas).
|
||||
- [ ] C5 : jouer E9 de F6 en Shipping (sauvegardes sous `%LOCALAPPDATA%\LifePlay-Revival`, lancement par le `.bat` avec `-UserDir`, relevé de `%LOCALAPPDATA%\LifePlay` avant et après la fermeture).
|
||||
- [ ] C2 : rejouer COMMUN-23.4 (écran titre après un retour de partie) à l'essai final.
|
||||
|
||||
## Constats
|
||||
|
||||
- **C1 (non bloquant, à décider)** : `Config/DefaultScalability.ini` (CHG-386, QPERS) sans IMPL/VAL/BUILD ; essai par console seulement ; gravé après la dernière build d'essai.
|
||||
- **C2** : COMMUN-23.4 incertain (bilan, « Incertain » 1) ; rejeu prévu à l'essai final.
|
||||
- **C3** : CHG-371 (CG2, trois Blueprints) : un seul essai (COMMUN-14), couverture partielle ; C8, Q7, Q8 et boutons de créature en build 2.
|
||||
- **C4** : COMMUN-18.10 non concluant (`Room cachee=1` : 0 ligne) reporté en build 2. COMMUN-22 sans fiche de tests ni bilan. COMMUN-20 : 51 actions à la première écriture contre 50 relues (cause non établie), flèches du couple sans ligne de trace.
|
||||
- **C5** : F6 : E9 (Shipping) jamais joué ; repli de lecture (COMMUN-21.4) et `-LPNoSavesRedirect` (.5) non éprouvés en jeu ; réserves 1 à 3 de `FIX1-F6-VAL.md` reportées en build 2.
|
||||
- **C6** : `LifePlay.uproject` local (HyperAIStudio) : voir contrôle 5. Le Shipping de l'alpha précédente est construit sans cette entrée.
|
||||
- **C7** : `Content/Saves` contient 4 fichiers `.lpcharacter` (ignorés par git) ; `CentralLondon_Mask.uasset` et `Paris.uasset` (CHG-379, CHG-377) non vérifiés ici ; à contrôler dans l'archive par `CheckPackage` (T2.5) et le contrôle T3 de `LPSaveLocation.ini`. `README.md` cite encore `2026.10.2.1a` (l. 10-14, 61-64) : mise à jour attendue à la publication, hors périmètre de cette VAL.
|
||||
|
||||
Non rejoué : compilation (`Build.ps1 -FromLog`), `LPTestStringCompat`, ouverture de l'éditeur (G-U3), lecture des journaux de jeu, MD5 des Blueprints inchangés (GI, Person…), relecture ligne à ligne du C++.
|
||||
|
||||
Tours : 25 / 40
|
||||
|
||||
## Fichiers à commiter
|
||||
|
||||
- `A Docs/Migration/etat/REL/REL2/REL2-VAL.md` (seul fichier écrit par ce validateur ; dépôt jeu, branche `ue5.8`).
|
||||
97
Docs/Migration/etat/REL/REL2/REL2-releve-R0.csv
Normal file
97
Docs/Migration/etat/REL/REL2/REL2-releve-R0.csv
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
"Racine","Chemin","Octets","Date"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\CrashReportClient\UECC-Windows-78FBA0CA4ADE2986E38845AFF0E927AF\CrashReportClient.ini","239","2026-10-16 19:10:06"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\CrashReportClient\UECC-Windows-A1A1456544F8C78C871CED9790561975\CrashReportClient.ini","239","2026-10-17 11:50:52"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\CrashReportClient\UECC-Windows-A4D20CE842CDC158C01DC88F314B1056\CrashReportClient.ini","239","2026-10-16 14:53:37"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\CrashReportClient\UECC-Windows-A9B4587F43A4CBB147872E8CAB3E0D76\CrashReportClient.ini","239","2026-10-15 14:18:50"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\CrashReportClient\UECC-Windows-C6FDAAF0432B2EA15754ABA955BCCD66\CrashReportClient.ini","239","2026-10-15 22:43:03"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\CrashReportClient\UECC-Windows-C8CEAF3C411702ADA452A0B77FB58F88\CrashReportClient.ini","239","2026-10-15 23:29:55"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\CrashReportClient\UECC-Windows-C9E0219E44C9CC75A310E7985E11F4EA\CrashReportClient.ini","239","2026-10-15 22:44:09"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\CrashReportClient\UECC-Windows-ECFB33804FD9E33BDB417FB21F45C859\CrashReportClient.ini","239","2026-10-16 20:09:03"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\Windows\GameUserSettings.ini","1460","2026-10-17 12:35:12"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\Windows\LPKeyboard.ini","3981","2026-10-17 11:50:54"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\Windows\LPVideoQuality.ini","82","2026-10-14 16:42:23"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpaction.json","367746","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpai.json","16324","2026-10-14 16:42:18"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpcharacter.json","363527","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpdesc.json","86381","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lphair.json","24954","2026-10-16 14:53:40"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpmod.json","21762","2026-10-16 14:53:40"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpnear.json","419","2026-10-14 16:42:18"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpquest.json","7155","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpscene.json","4666224","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpstat.json","64047","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lptalk.json","28054","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpworld.json","1796945","2026-10-14 16:42:18"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\txt.json","805345","2026-10-16 14:53:40"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\SaveGames\1.sav","220584","2026-10-14 17:03:39"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\SaveGames\2.sav","250570","2026-10-16 23:10:50"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\SaveGames\Default.sav","137283","2026-10-14 16:42:51"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\SaveGames\GameSettings.sav","12066","2026-10-16 23:10:50"
|
||||
"D:\Game\LifePlay_Build_5.8_ALPHA-2026.10.2.2a_Shipping\Windows\LifePlay\Content\Saves","(absent)","0",""
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UE4CC-Windows-0812D4C84D760C778C768584413A85E3\CrashReportClient.ini","114","2026-10-20 00:03:12"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UE4CC-Windows-83374FC5416C0AB392A05D8769D55595\CrashReportClient.ini","114","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UECC-Windows-34E87D6B4535F7A77357C4B4F2D10213\CrashReportClient.ini","160","2026-10-19 23:58:37"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UECC-Windows-43D5425B46EC5D79FBC820A1D0BDB760\CrashReportClient.ini","160","2026-10-19 23:56:39"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UECC-Windows-673D2DC344864C7D690925B403A8841D\CrashReportClient.ini","160","2026-10-20 00:06:48"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UECC-Windows-CE65F528473F5716220E069CB72B5417\CrashReportClient.ini","160","2026-10-19 23:54:19"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UECC-Windows-FAA787784EF0796B4725ECA79EFA1EBE\CrashReportClient.ini","160","2026-10-19 23:55:44"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\Windows\GameUserSettings.ini","1488","2026-10-20 00:07:54"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\Windows\LPColorGrade.ini","110","2026-10-07 02:57:56"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\Windows\LPKeyboard.ini","3981","2026-10-19 23:55:48"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\ApexDestruction.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Compat.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\DeviceProfiles.ini","2","2026-10-20 00:08:10"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Engine.ini","1758","2026-10-20 00:08:44"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Game.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\GameUserSettings.ini","1098","2026-10-20 00:08:44"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Hardware.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Input.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\LiveLink.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\MagicLeap.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\MagicLeapLightEstimation.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\MotoSynth.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Niagara.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\OculusVR.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Paper2D.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\PhysXVehicles.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\RuntimeOptions.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Scalability.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Synthesis.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\VariantManagerContent.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpaction.json","310498","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpai.json","16324","2026-10-19 23:56:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpcharacter.json","355961","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpdesc.json","78701","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lphair.json","18061","2026-10-20 00:06:51"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpmod.json","1791","2026-10-20 00:06:51"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpnear.json","419","2026-10-19 23:56:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpquest.json","4989","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpscene.json","2494222","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpstat.json","53834","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lptalk.json","10699","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpworld.json","1796945","2026-10-19 23:56:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\txt.json","800146","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames\Default.sav","107727","2026-10-13 23:08:28"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames\GameSettings.sav","2440","2026-10-13 23:08:28"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\1.sav","527130","2025-12-04 21:57:10"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\10.sav","1102123","2025-12-10 15:08:02"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\11.sav","647148","2025-12-02 20:22:28"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\12.sav","897498","2025-12-03 01:55:01"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\13.sav","944851","2025-12-03 02:50:21"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\14.sav","1107685","2025-12-03 23:56:08"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\16.sav","127695","2026-10-02 09:38:50"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\17.sav","258283","2026-10-01 21:34:53"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\18.sav","175309","2026-10-02 13:25:19"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\19.sav","159871","2026-10-02 21:05:59"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\2.sav","283585","2025-12-06 20:26:15"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\21.sav","134547","2026-10-09 18:41:22"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\3.sav","585755","2025-12-06 21:27:39"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\4.sav","596295","2025-12-06 21:38:49"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\5.sav","731898","2025-12-07 00:04:15"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\6.sav","492308","2025-12-08 21:10:53"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\7.sav","644714","2025-12-09 00:18:43"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\8.sav","848591","2025-12-09 18:06:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\9.sav","886830","2025-12-09 18:29:20"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\Central London.sav","2903","2025-09-17 03:38:23"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\Default.sav","103393","2025-03-19 22:52:05"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\GameSettings.sav","21341","2026-10-09 18:41:22"
|
||||
|
105
Docs/Migration/etat/REL/REL2/REL2-releve-R1.csv
Normal file
105
Docs/Migration/etat/REL/REL2/REL2-releve-R1.csv
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
"Racine","Chemin","Octets","Date"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\CrashReportClient\UECC-Windows-3E6BDF64457E3537973E5AAD70BF4D4A\CrashReportClient.ini","239","2026-10-21 09:09:51"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\CrashReportClient\UECC-Windows-4E6E5980414F7416CC002183919B2A8C\CrashReportClient.ini","239","2026-10-21 09:13:36"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\Windows\GameUserSettings.ini","1460","2026-10-21 09:26:15"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\Windows\LPKeyboard.ini","3950","2026-10-21 09:21:58"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Config\Windows\LPVideoQuality.ini","82","2026-10-21 09:14:25"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpaction.json","367746","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpai.json","16324","2026-10-14 16:42:18"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpcharacter.json","363527","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpdesc.json","86381","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lphair.json","18061","2026-10-21 09:09:54"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpmod.json","17354","2026-10-21 09:09:54"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpnear.json","419","2026-10-14 16:42:18"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpquest.json","7155","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpscene.json","4666224","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpstat.json","64047","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lptalk.json","28054","2026-10-14 23:38:16"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\lpworld.json","1796945","2026-10-14 16:42:18"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\LPDataCache\txt.json","800154","2026-10-21 09:09:54"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\SaveGames\1.sav","145462","2026-10-21 09:12:58"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\SaveGames\2.sav","250570","2026-10-16 23:10:50"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\SaveGames\Default.sav","137283","2026-10-14 16:42:51"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\SaveGames\GameSettings.sav","11547","2026-10-21 09:12:57"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\1\Characters\1.lpcharacter","3815","2026-10-21 09:12:58"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\1\Characters\2.lpcharacter","3388","2026-10-21 09:12:58"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\1\Characters\Player.lpcharacter","3769","2026-10-21 09:12:58"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\_session\Characters\1.lpcharacter","0","2026-10-21 09:15:19"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\_session\Characters\10.lpcharacter","0","2026-10-21 09:15:19"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\_session\Characters\11.lpcharacter","0","2026-10-21 09:15:19"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\_session\Characters\2.lpcharacter","0","2026-10-21 09:15:19"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\_session\Characters\3.lpcharacter","0","2026-10-21 09:15:19"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\_session\Characters\4.lpcharacter","0","2026-10-21 09:15:19"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\_session\Characters\5.lpcharacter","0","2026-10-21 09:15:19"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\_session\Characters\6.lpcharacter","0","2026-10-21 09:15:19"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\_session\Characters\7.lpcharacter","0","2026-10-21 09:15:19"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\_session\Characters\8.lpcharacter","0","2026-10-21 09:15:19"
|
||||
"%LOCALAPPDATA%\LifePlay-Revival","\Saved\Saves\_session\Characters\9.lpcharacter","0","2026-10-21 09:15:19"
|
||||
"D:\Game\LifePlay_Build_5.8_ALPHA-2026.10.2.2a_Shipping\Windows\LifePlay\Content\Saves","(absent)","0",""
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UE4CC-Windows-0812D4C84D760C778C768584413A85E3\CrashReportClient.ini","114","2026-10-20 00:03:12"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UE4CC-Windows-83374FC5416C0AB392A05D8769D55595\CrashReportClient.ini","114","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UECC-Windows-34E87D6B4535F7A77357C4B4F2D10213\CrashReportClient.ini","160","2026-10-19 23:58:37"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UECC-Windows-43D5425B46EC5D79FBC820A1D0BDB760\CrashReportClient.ini","160","2026-10-19 23:56:39"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UECC-Windows-673D2DC344864C7D690925B403A8841D\CrashReportClient.ini","160","2026-10-20 00:06:48"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UECC-Windows-CE65F528473F5716220E069CB72B5417\CrashReportClient.ini","160","2026-10-19 23:54:19"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\CrashReportClient\UECC-Windows-FAA787784EF0796B4725ECA79EFA1EBE\CrashReportClient.ini","160","2026-10-19 23:55:44"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\Windows\GameUserSettings.ini","1488","2026-10-20 00:07:54"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\Windows\LPColorGrade.ini","110","2026-10-07 02:57:56"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\Windows\LPKeyboard.ini","3981","2026-10-19 23:55:48"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\ApexDestruction.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Compat.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\DeviceProfiles.ini","2","2026-10-20 00:08:10"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Engine.ini","1758","2026-10-20 00:08:44"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Game.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\GameUserSettings.ini","1098","2026-10-20 00:08:44"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Hardware.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Input.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\LiveLink.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\MagicLeap.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\MagicLeapLightEstimation.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\MotoSynth.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Niagara.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\OculusVR.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Paper2D.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\PhysXVehicles.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\RuntimeOptions.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Scalability.ini","2","2026-10-20 00:08:09"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\Synthesis.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\Config\WindowsNoEditor\VariantManagerContent.ini","2","2026-09-28 15:08:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpaction.json","310498","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpai.json","16324","2026-10-19 23:56:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpcharacter.json","355961","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpdesc.json","78701","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lphair.json","18061","2026-10-20 00:06:51"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpmod.json","1791","2026-10-20 00:06:51"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpnear.json","419","2026-10-19 23:56:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpquest.json","4989","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpscene.json","2494222","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpstat.json","53834","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lptalk.json","10699","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\lpworld.json","1796945","2026-10-19 23:56:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\LPDataCache\txt.json","800146","2026-10-19 23:56:41"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames\Default.sav","107727","2026-10-13 23:08:28"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames\GameSettings.sav","2440","2026-10-13 23:08:28"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\1.sav","527130","2025-12-04 21:57:10"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\10.sav","1102123","2025-12-10 15:08:02"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\11.sav","647148","2025-12-02 20:22:28"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\12.sav","897498","2025-12-03 01:55:01"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\13.sav","944851","2025-12-03 02:50:21"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\14.sav","1107685","2025-12-03 23:56:08"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\16.sav","127695","2026-10-02 09:38:50"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\17.sav","258283","2026-10-01 21:34:53"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\18.sav","175309","2026-10-02 13:25:19"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\19.sav","159871","2026-10-02 21:05:59"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\2.sav","283585","2025-12-06 20:26:15"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\21.sav","134547","2026-10-09 18:41:22"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\3.sav","585755","2025-12-06 21:27:39"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\4.sav","596295","2025-12-06 21:38:49"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\5.sav","731898","2025-12-07 00:04:15"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\6.sav","492308","2025-12-08 21:10:53"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\7.sav","644714","2025-12-09 00:18:43"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\8.sav","848591","2025-12-09 18:06:00"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\9.sav","886830","2025-12-09 18:29:20"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\Central London.sav","2903","2025-09-17 03:38:23"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\Default.sav","103393","2025-03-19 22:52:05"
|
||||
"%LOCALAPPDATA%\LifePlay","\Saved\SaveGames.old\GameSettings.sav","21341","2026-10-09 18:41:22"
|
||||
|
168
Docs/Migration/etat/REL/SET1/SET1-PRE.md
Normal file
168
Docs/Migration/etat/REL/SET1/SET1-PRE.md
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
Fiche SET1-PRE — Niveau N2 — Modèle prévu non précisé par la fiche | utilisé claude-sonnet-5-5 — Agent lp-cart — Skills sk-protocol, ue-cpp-build, lp-commandlets, lp-paths
|
||||
# SET1-PRE : étude préliminaire, remplacer « l'ancien panneau settings du menu du jeu » par celui du menu principal (2026-10-20)
|
||||
|
||||
Hors gabarit : étude préliminaire (pas une CART complète), sur le modèle de `FIX1-F6-PRE.md`. Les six rubriques du gabarit CART sont gardées ; la rubrique 3 suit les cinq questions de la fiche. Lecture seule : ni copie UE, ni MCP, ni éditeur, ni commandlet. Seul ce fichier est écrit. Contenu adulte (doc 27) : noms techniques de widgets seulement, aucun libellé d'interface.
|
||||
|
||||
## Résumé (à lire en premier)
|
||||
|
||||
1. **Le dépôt ne contient pas deux panneaux de réglages.** Un seul asset porte la liste des réglages : `Content/UI/MainMenu.uasset` (`SettingsScrollBox`). Aucun autre widget n'en contient (rubrique 2, commandes 6 et 7). Le « nouveau panneau » (onglets General, Audio, Video, Keyboard, Lewd, Misc) n'est **pas un autre widget** : c'est la même liste, dont le C++ montre ou cache les lignes par onglet (`LPSettingsSubsystem.h:1-6`, établi).
|
||||
2. **`MainMenu_C` sert à la fois d'écran titre et de menu en partie** (boutons de partie et de titre dans le même widget, liaisons `OnlyVisibleForTitleScreen` / `ColapsedForTitleScreen`, `LPTitleModManagerCommandlet.h:4-9`). Seul le **bouton** « Settings » de l'écran titre est ajouté par le C++ (`LPSettingsSubsystem.cpp:571-762`, visible seulement sur l'écran titre, l. 757-761). En partie, le bouton d'origine ouvre la même liste, et les onglets s'y posent tout seuls (`Tick`, l. 498-561 : estimé).
|
||||
3. **La prémisse « ancien ≠ nouveau » n'est donc pas confirmée.** Désactiver « l'ancien panneau » reviendrait à désactiver **le seul panneau existant**, titre compris. Ce qui peut exister, et que ce dépôt ne prouve pas : un défaut d'affichage en partie (hypothèse H1, rubrique 3.3) que seul un essai en jeu tranche.
|
||||
4. **Recommandation** : ne pas ouvrir d'IMPL. Build 1 : un essai en jeu à trois captures (0 code), puis, **seulement si H1 est confirmée**, un correctif C++ d'un fichier (0 Blueprint, 0 GI). La réécriture complète du module en C++ que vise le doc 37 § 2.4 est un lot de **build 2** (rubrique 3.5).
|
||||
5. **Question bloquante pour l'utilisateur** : que voit-il, en partie, qui diffère du menu principal ? Une capture de chaque panneau lèverait le doute (rubrique 6, Q1).
|
||||
|
||||
## 1. Objet et périmètre
|
||||
|
||||
Un domaine : les panneaux de réglages (écran titre et menu en partie). Demande de l'utilisateur, citée dans `BOSS-JOURNAL.md:1030` (2026-10-20 21:04) : « non je souhaite passer la désactivation de l ancien panneau settings du menu du jeu et le remplacer par celui du menu principal. » Référence : `Docs/37_Feuille_De_Route_Alpha2.md:125-128` (§ 2.4 Dépréciation). Hors périmètre : le contenu des réglages (valeurs, textes), la correction de quoi que ce soit, le Mod Manager (widget distinct `UI/ModManager`).
|
||||
|
||||
Copie lue : `D:\Game\LifePlay-master 5.8`, branche `ue5.8`, HEAD `ad3c9c6`. `LPCameraModeSubsystem.cpp` et `LPDirectControlSubsystem.cpp` portent des modifications non commitées (statut git de départ) : leurs numéros de ligne peuvent bouger. `Content/UI/MainMenu.uasset` est propre (`git status --short` vide) ; dernier commit `d15ffaa` (DISC1, 2026-10-20).
|
||||
|
||||
## 2. Commandes et lectures (exactes) avec compte brut
|
||||
|
||||
| # | Commande ou lecture | Résultat brut |
|
||||
|---|---|---|
|
||||
| 1 | Read `Docs/37_Feuille_De_Route_Alpha2.md:95-198` ; Grep `2\.4\|Dépréciation` | § 2.4 l. 125-128 ; le tableau des lots (l. 161-172) **n'a pas de ligne SET1** |
|
||||
| 2 | Read `LPSettingsSubsystem.h` (69 l.), `LPSettingsSubsystem.cpp:1-330, 470-896` (896 l.), `LPUserSettings.h` (60 l.) | cités en 3 |
|
||||
| 3 | `wc -l` sur 4 sources | `896 LPSettingsSubsystem.cpp`, `1537 LPKeyboardSubsystem.cpp`, `36 LPModSettingsLibrary.cpp`, `115 LPUserSettings.cpp` |
|
||||
| 4 | Glob `Content/**/*{ettings,ptions,Pause,Esc}*.uasset` | 4 fichiers : `Heavy/Daz/Clothes/DazDiffuseOptions`, `Heavy/New/settings` (texture), `BPs/GameSettings` (SaveGame), `FreeAnimationsPack/.../Mannequin_LODSettings` : **aucun widget** |
|
||||
| 5 | Glob `Content/UI/MainMenu/**/*.uasset` | `No files found` (pas de dossier ; `MainMenu` est un seul asset `Content/UI/MainMenu.uasset`, 2 245 771 o) |
|
||||
| 6 | `rg -a -l -e "SettingsScrollBox" -g "*.uasset" Content` | 1 fichier : `Content\UI\MainMenu.uasset` ; code de sortie 0 |
|
||||
| 7 | `rg -a -l -e "SettingCheckbox" -e "SettingSlider" -e "SettingsScrollBox" -e "GameSettings" -g "*.uasset" -g "*.umap" Content/UI Content/BPs Content/Maps` | 6 fichiers : `BPs/PC`, `BPs/GameSettings`, `BPs/GI`, `UI/MainMenu`, `UI/SettingSlider`, `UI/SettingCheckbox` (code 2 : `Content/Maps` n'existe pas ; la sortie est valide) |
|
||||
| 8 | `rg -a -c -e SettingsScrollBox -e MainMenuOptions -e SettingsButton -e MainMenuOn` sur `MainMenu`, `GI`, `PC`, `TopRight` | `MainMenu.uasset:15`, `PC.uasset:1`, `GI.uasset:1`, `TopRight` : aucune ligne |
|
||||
| 9 | `rg -a -o "[A-Za-z_]*(Button\|ScrollBox\|Settings\|Setting)[A-Za-z_0-9]*" MainMenu.uasset \| sort \| uniq -c` | boutons du même widget : `ResumeButton`, `SaveButton`, `LoadButton`, `ContinueButton`, `NewGameButton`, `NewGameTfButton`, `NewGameTutorialButton`, `InventoryButton`, `StatMenuButton`, `CharGenButton`, `CityMenuButton`, `BodyShapeButton`, `ModManagerButton`, `ModManagerTitleButton`, `SettingsButton`, `ExitButton`, `FAQButton`, `DonateButton`, `DiscordButton`, `BackButton`, `FullscreenButton` ; `SettingsScrollBox` ×5 ; `SettingCheckbox_C` et `SettingSlider_C` ×1 |
|
||||
| 10 | `rg -a -o "[A-Za-z_]*(TitleScreen\|OnlyVisibleFor\|ColapsedFor\|CollapsedFor)[A-Za-z_]*" MainMenu.uasset \| sort \| uniq -c` | `ColapsedForTitleScreen` 3 ; `OnlyVisibleForTitleScreen` 3 ; `TitleScreen` 1 |
|
||||
| 11 | `rg -a -o "[A-Za-z_]{0,30}Settings[A-Za-z_]{0,30}" PC.uasset` | `GameSettings`, `GameSettings_C`, `GameSettingsInstance`, `ConcurrencySettings`, `Settings` ×2 ; et (commande 12) `MainMenuOn`, `MainMenuInput`, `MainMenu`, `InpActEvt_MainMenu_K…`, `CloseMainMenu` |
|
||||
| 12 | `rg -a -o "(MainMenu\|Settings\|PauseMenu\|OptionsMenu)" PC.uasset` | cités ci-dessus ; aucun `PauseMenu` ni `OptionsMenu` |
|
||||
| 13 | Grep `SettingsScrollBox\|TitleScreen\|ModManagerTitleButton` dans `Source` | 5 sous-systèmes cherchent la liste par son nom : `LPSettingsSubsystem.cpp:506`, `LPColorGradeSubsystem.cpp:263`, `LPVideoQualitySubsystem.cpp:466`, `LPKeyboardSubsystem.cpp:854`, `LPModInfoSubsystem.cpp:246` ; plus `LPReadableTextSubsystem.cpp:125` (remonte les parents) |
|
||||
| 14 | Grep `MainMenu\|IsMenuOpen` dans `Source/LifePlay/*.cpp` | `MainMenu_C` est une classe de « menu ouvert » dans 4 listes : `LPDirectControlSubsystem.cpp:60`, `LPDebugSubsystem.cpp:436`, `LPOutdoorRoomSubsystem.cpp:52`, `LPCameraModeSubsystem.cpp:262` ; `LPCameraModeSubsystem.cpp:91, 1189-1192` (remise à faux de `GI.MainMenuOn`) ; `LPKeyboardSubsystem.cpp:819-822` |
|
||||
| 15 | Read `Docs/Migration/etat/ST/STB/dumps/MainMenu__EventGraph.txt:100-270` | `EventGraph` de MainMenu (398 nœuds) : Resume, CharGen, CityMenu, ModManager, Inventory, Exit, **Settings**, **Back**, StatMenu |
|
||||
| 16 | Read `…/CAM/CAM-B1-PRE_LPDumpFunction_20261013-083048.txt:5126-5185` | `EventGraph` de GI : événements `MainMenuInput`, `OpenMainMenu`, `CloseMainMenu`, `CreateMainMenuWidget` (CreateWidget, `AddToViewport`, variable `MainMenu`) |
|
||||
| 17 | Read `LPTitleModManagerCommandlet.h:1-30` | commentaire d'en-tête : l. 4-9 |
|
||||
| 18 | Journal du jeu `D:\Game\LifePlay_Build_5.8_Development_COM22\Windows\LifePlay\Saved\Logs\LifePlay.log` : `rg -n "Reglages : "` ; `rg -c "Reglages : (onglets\|entree)"` | 2 lignes (957 `entree Settings ajoutee sur l'ecran titre`, 958 `Settings place apres Mod Manager`) ; compte 1 ; **aucune ligne `Reglages : onglets`** : les réglages n'ont jamais été ouverts dans cette session |
|
||||
| 19 | Journal COMMUN-21 `…/BOSS/COMMUN-21/COMMUN-21_session_1927.log` : Grep `Reglages :` | 971 `entree`, 972 `place`, **1014 `onglets General, Audio, Video, Keyboard, Lewd, Misc`**, 2880 `entree`, 2881 `place` |
|
||||
| 20 | `rg -a -w -e <45 noms de lignes du dump 5.5 de MainMenu> Content/UI/MainMenu.uasset \| sort -u` | 32 noms retrouvés (liste en 3.2) ; 14 absents (3.2) |
|
||||
| 21 | `rg -a -c -e SaveSettings -e LoadSettings Content/BPs/GI.uasset` | `4` |
|
||||
| 22 | Grep `module de r[ée]glages\|panneau (général\|…)\|nouveau panneau\|menu général` dans `Docs/[0-9]*.md` | seul résultat utile : `37_…md:127-128` ; aucune définition de « l'ancien module de réglages » ailleurs |
|
||||
|
||||
Écart de méthode : le dump des widgets de MainMenu (`portage55/L6e/L6e-CX-B09_LPDumpWidgetTree_20260930-083639.txt`) date du 2026-09-30 (5.5). Il sert à nommer les lignes ; le décompte exact des lignes actuelles demande un `LPDumpWidgetTree` (copie UE, éditeur fermé).
|
||||
|
||||
## 3. Constats `fichier:ligne`
|
||||
|
||||
### 3.1 Le « nouveau panneau » : celui du menu principal (question 1)
|
||||
|
||||
| Constat | Source | Niveau |
|
||||
|---|---|---|
|
||||
| Il **n'est pas un widget créé en C++ ni un Blueprint à part**. Le sous-système dit : « Les lignes existent déjà dans MainMenu.SettingsScrollBox (cases et curseurs du Blueprint). Ce sous-système ne les recrée pas : il les montre ou les cache selon l'onglet. […] Aucun Blueprint n'est modifié. » | `LPSettingsSubsystem.h:1-6` | établi |
|
||||
| Les onglets sont une `UHorizontalBox` nommée `LPSettingsTabs` ajoutée au `CanvasPanel` parent de la liste, 40 px au-dessus d'elle ; six boutons dont les clics appellent `ShowGeneral / ShowAudio / ShowVideo / ShowKeyboard / ShowLewd / ShowMisc` | `LPSettingsSubsystem.cpp:764-836` (liaison l. 790-817) ; noms des onglets l. 35-37 | établi |
|
||||
| Le classement d'une ligne dans un onglet se fait par **nom** (`NewAnimationsOnly` → General ; `ShowFPS`, `ScreenPercentage`, `FullscreenButton`, `ToonShading`, `Censore`, `CPUSkinning`, `DisableFurEffect`, `LPColor*`, `LPVideo*` → Video ; `LPModCheck*` → Misc), puis par **mots-clés du libellé**, sinon Misc. `ShadowQuality`, `PostProcessQuality`, `PostProcessAAQuality` sont repliés (remplacés par les lignes `LPVideo*`). `BackButton` est toujours visible | `LPSettingsSubsystem.cpp:145-212` | établi |
|
||||
| L'onglet Keyboard est une page Slate native (`UNativeWidgetHost` nommé `LPSettingsKeyboard`) fournie par `ULPKeyboardSubsystem::TakeEmbeddedPage()`, placée sous la barre d'onglets | `LPSettingsSubsystem.cpp:821-832, 877-888` | établi |
|
||||
| Ouverture depuis l'écran titre : bouton `LPSettingsTitleButton` créé en C++ dans la boîte `MainMenuOptions`, placé après `ModManagerTitleButton` ; son clic appelle `OpenSettings`, qui **diffuse `OnClicked` du bouton d'origine `SettingsButton`** (Blueprint) | `LPSettingsSubsystem.cpp:563-569, 571-690` | établi |
|
||||
| Le Blueprint d'origine, sur clic de `SettingsButton` : cache `MainMenuOptions`, montre `SettingsScrollBox` ; `BackButton` fait l'inverse | `MainMenu__EventGraph.txt:222-259` (`SetVisibility` Hidden / Visible) | établi |
|
||||
| Le bouton C++ prend la visibilité de `ModManagerTitleButton` (`Ours->SetVisibility(TitleVisibility)`) ; ce dernier n'est visible que sur l'écran titre (liaison `OnlyVisibleForTitleScreen`) : **le bouton ajouté est donc propre à l'écran titre** | `LPSettingsSubsystem.cpp:757-761` ; `LPTitleModManagerCommandlet.h:6-9` | établi |
|
||||
| Les onglets et les réglages C++ sont posés par un `Tick` à chaque image, sur la **première** `SettingsScrollBox` trouvée par `TObjectIterator` dont le propriétaire partage le `GameInstance` (`break` l. 516). Rien dans la sélection ne distingue écran titre et partie | `LPSettingsSubsystem.cpp:498-561` | établi |
|
||||
| Les quatre autres sous-systèmes injectent leurs lignes dans la même liste, par le même nom | observations 13 | établi |
|
||||
|
||||
**Peut-il s'ouvrir en cours de partie ?** Établi : le même widget `MainMenu_C` est celui du menu en partie (`LPTitleModManagerCommandlet.h:4-9` : « entrée "Mod Manager" du menu, masquée sur l'écran titre » ; boutons `ResumeButton`, `SaveButton`, `InventoryButton`… dans le même asset, observation 9 ; `GI.OpenMainMenu`, `MainMenuInput`, `CloseMainMenu`, `CreateMainMenuWidget`, observation 16). Les onglets s'y posent par construction (estimé, jamais observé en jeu : aucun journal ne montre `Reglages : onglets` après un lancement de partie ; observations 18-19).
|
||||
|
||||
| Point demandé | Établi | Inconnu |
|
||||
|---|---|---|
|
||||
| Entrée | touche → `PC.InpActEvt_MainMenu_K…` → `GI.MainMenuInput` (chaînes de `PC.uasset`, observation 12 ; `GI` : `CAM-B1-PRE…txt:5128`) | le test `IfThenElse_6451` de `MainMenuInput` (ouvre ou ferme) |
|
||||
| Focus | `LPKeyboardSubsystem::IsMenuOpen` traite les réglages ouverts comme un menu (`MainMenu_C`) ; marche, caméra et relevage sont coupés | focus clavier ou manette dans la liste : non lu |
|
||||
| Retour | `BackButton` (panneau → options) ; `CloseSelf` → `GI.CloseMainMenu` (`MainMenuOn` = faux) (`MainMenu__EventGraph.txt:144-150`, `CAM-B1-PRE…txt:5134-5150`) ; `KEY2-DIAG-01` : réglages fermés pendant une capture de touche → capture annulée (`LPSettingsSubsystem.cpp:528-541`) | — |
|
||||
| Pause du jeu pendant le menu | — | **inconnu** : `GI.MainMenuInput` n'a pas été lu jusqu'au bout ; la ligne `AutoPause` est un réglage, pas la pause du menu |
|
||||
|
||||
### 3.2 L'« ancien panneau » : celui du menu en partie (question 2)
|
||||
|
||||
**Constat central (établi, négatif)** : aucun autre widget de réglages. Observations 4 à 8 : un seul asset contient `SettingsScrollBox` (`MainMenu`) ; `SettingCheckbox` et `SettingSlider` ne sont référencés que par `MainMenu` (et eux-mêmes) ; `TopRight` ne contient rien ; `PC` et `GI` ne citent que `GameSettings` (le SaveGame) et les événements de menu. **Le menu de pause et le menu d'options en partie sont le même widget `MainMenu`**. Il n'existe pas de classe `PauseMenu` ni `OptionsMenu` (observation 12). *Limite* : ce relevé couvre `Content/UI`, `Content/BPs`, `Content` (Glob) ; un widget créé dynamiquement par C++ n'aurait pas de nom de ce type, mais aucun `CreateWidget` de réglages n'existe dans `Source` (Grep n° 13 : seuls les cinq sous-systèmes ci-dessus touchent la liste, par recherche d'objet, pas par création).
|
||||
|
||||
**Ce que l'ancien panneau porte** (lignes nommées, relevé 2026-09-30 de `L6e-CX-B09_LPDumpWidgetTree`, recontrôlé dans le binaire 5.8 par `rg -a -w`) :
|
||||
|
||||
32 noms retrouvés dans `MainMenu.uasset` : `24Hour`, `AiOnlySuggests`, `AllowHomeDye`, `AutoPause`, `BodyChange`, `CPUSkinning`, `Censore`, `Difficulty`, `DisableFurEffect`, `DisableTrans`, `FullscreenButton`, `NPCsRespectPlayerSex`, `NameToRelation`, `NewAnimationsOnly`, `NoActionTimeout`, `NoAnimConditions`, `NoForcedCondom`, `NoTransPreg`, `OldFilter`, `PostProcessAAQuality`, `PostProcessQuality`, `PregnancyNotification`, `PreventClothChanges`, `ScreenPercentage`, `ShadeDepth`, `ShadowQuality`, `ShowFPS`, `ShowUnknownBuildings`, `SpinBoxDOF`, `ToonShading`, `TutorialCompleted`, `UnderwearVisible`.
|
||||
|
||||
14 noms du dump 5.5 **non retrouvés** par `rg -a -w` : `ChildGrowthMult`, `SpinBoxBGA`, `SpinBoxCameraSpeed`, `SpinBoxMarkerSize`, `SpinBoxMoan`, `SpinBoxPhysicsMult`, `SpinBoxPregnancyTerm`, `SpinBoxSceneFrequency`, `SpinBoxSex`, `SpinBoxSexDescription`, `SpinBoxSexDurationMultiplier`, `SpinBoxSquirtMult`, `SpinBoxUI`, `SpinBox_0`. `SpinBox_0` est expliqué : remplacé par `SpinBoxDOF` (commit `547dcdd`, STF-T5 a). Pour les 13 autres, la cause n'est **pas établie** (renommage, ou nom enfoui dans une chaîne plus longue que le motif `-w` rejette). Ces lignes existent : `LISIB-T1-CART.md:76` compte 15 `SpinBox` dans `SettingsScrollBox`, et `2883b80` en protège 12. La liste exacte des réglages de partie, un par un, demande donc un `LPDumpWidgetTree -BP=MainMenu` (éditeur fermé, copie UE) : **inconnu**.
|
||||
|
||||
Lignes ajoutées par le C++ dans la même liste : `LPColor*` (`LPColorGradeSubsystem`), `LPVideo*` (`LPVideoQualitySubsystem`), `LPModCheck*` (3 cases de contrôle des mods, `LPModInfoSubsystem.h:16`), `LPKeyboardRow` (repliée, `LPSettingsSubsystem.cpp:862-868`), page Keyboard.
|
||||
|
||||
**Qui écrit ces réglages**
|
||||
|
||||
| Réglage | Écrit par | Support | Source | Niveau |
|
||||
|---|---|---|---|---|
|
||||
| Lignes Blueprint (cases, curseurs) | `GI.SaveSettings` / `GI.LoadSettings` (liaisons `Value ← GI` retirées, écriture sur `OnValueCommitted`, init dans `Construct`) | `GameSettings.sav` (SaveGame `Content/BPs/GameSettings`), dossier `…\Saved\SaveGames` | `rg -a -c` sur GI = 4 ; `STC-SPEC.md` ; commit `2883b80` (message) ; `Registre_Erreurs.md:49` (cité par `FIX1-F6-PRE.md:46`) | établi pour le principe ; **liste des champs de `GameSettings` : inconnue** (extraction vide, non relevée) |
|
||||
| Vitesse de caméra | `ULPUserSettingsLibrary::SetCameraSpeed` ; recopie dans `GI.CameraSpeed` | `GameUserSettings.ini`, section `/Script/LifePlay.LPUserSettings`, 1 à 7, 3 par défaut ; `GameSettings.sav` garde une recopie | `LPUserSettings.h:1-9, 19-27, 52-54` | établi |
|
||||
| Touches | `ULPKeyboardSubsystem` | `Saved/Config/Windows/LPKeyboard.ini` ; journal COM22 l. 879-880 : `Clavier : …LPKeyboard.ini absent, creation avec les touches actuelles` puis `51 actions et 17 axes enregistres` | `LifePlay.log` (COM22) | établi |
|
||||
| Couleur, qualité vidéo | `LPColorGradeSubsystem`, `LPVideoQualitySubsystem` | fichiers `LP*.ini` de `Saved/Config` | repris de `FIX1-F6-PRE.md:62` (`LPColorGradeSubsystem.cpp:27`, `LPVideoQualitySubsystem.cpp:71`), non relu ici | estimé |
|
||||
| Choix des mods | `ULPModSettingsLibrary::SaveModSelection` | `GameSettings.sav` (`ModEnableds`) | `UA-MODS.md:130` ; `LPModSettingsLibrary.cpp:34` | établi (par citation) |
|
||||
|
||||
Bouton qui ouvre : le bouton `SettingsButton` du menu en partie (Blueprint, `MainMenu__EventGraph.txt:222`) ; sur l'écran titre, `LPSettingsTitleButton` (C++) qui diffuse le même événement. Aucun autre point d'entrée de réglages n'est apparu (PC, TopRight, GI : aucune création de widget de réglages).
|
||||
|
||||
### 3.3 Écart fonctionnel et hypothèses (question 3)
|
||||
|
||||
**Écart par construction : nul.** Les deux « panneaux » sont une seule liste de lignes. Il n'existe pas de réglage « seulement dans l'ancien » au sens d'un second asset, ni de réglage de partie absent du nouveau : les lignes de partie (`Difficulty`, `NoActionTimeout`, `AutoPause`, `24Hour`, `TutorialCompleted`…) **sont** celles du « nouveau ». Seuls ajouts du C++ (« seulement dans le nouveau », mais dans la même liste, donc visibles en partie si les onglets s'y posent) : page Keyboard, lignes `LPColor*` / `LPVideo*` / `LPModCheck*`, vitesse de caméra adossée à l'ini.
|
||||
|
||||
**Risque de perte si « l'ancien » est désactivé** (établi par construction) : désactiver `MainMenu.SettingsScrollBox` ou `SettingsButton` retire **tous** les réglages, titre compris, et casse cinq sous-systèmes qui cherchent la liste par son nom (observation 13) et `ULPKeyboardSubsystem::IsMenuOpen`. Désactiver seulement `SettingsButton` en partie retire l'accès aux réglages en partie, sans remplaçant.
|
||||
|
||||
**Hypothèses sur ce que l'utilisateur voit** (aucune n'est établie ; un essai en jeu les départage) :
|
||||
|
||||
| # | Hypothèse | Mécanisme (code lu) | Niveau | Essai qui tranche |
|
||||
|---|---|---|---|---|
|
||||
| H1 | En partie, la liste n'a **pas les onglets** (ou affiche seulement les lignes de General) | `GI.CreateMainMenuWidget` crée un `MainMenu` (CreateWidget + `AddToViewport`, `CAM-B1-PRE…txt:5171-5185`). Le `Tick` prend la **première** `SettingsScrollBox` du `GameInstance` (`LPSettingsSubsystem.cpp:516`) et `EnsureTabs` sort si `TabBar` est encore valide (l. 766-769). Si l'instance de l'écran titre n'est pas encore collectée quand la partie crée la sienne, la barre d'onglets reste celle de l'ancienne instance, et `ApplyRows` filtre la nouvelle liste sans barre pour changer d'onglet | estimé (la création à chaque ouverture et le délai de collecte ne sont pas lus) | écran titre → Settings → Back → nouvelle partie ou Continuer → Échap → Settings : la barre d'onglets est-elle là ? Journal : une ligne `Reglages : onglets` après le lancement de partie |
|
||||
| H2 | L'utilisateur parle d'un écart **visuel** (arrière-plan, taille) entre titre et partie, pas fonctionnel | même widget, mais le fond de la scène 3D change | incertain | deux captures côte à côte |
|
||||
| H3 | « L'ancien module de réglages » du doc 37 désigne la **logique Blueprint** (`GI.LoadSettings` / `SaveSettings`, `GameSettings.sav`) à remplacer par du C++ (modèle `ULPUserSettings`) | `37_…md:127` ne définit pas le terme ; aucun autre doc ne le définit (observation 22) | incertain | question à l'utilisateur (Q2) |
|
||||
|
||||
### 3.4 Voies possibles (question 4)
|
||||
|
||||
Précision : comme les deux panneaux sont un seul widget, la voie (a) de la fiche (« rediriger le bouton ») n'a **rien à rediriger** : le bouton d'origine ouvre déjà la liste que le C++ met en onglets. Les voies ci-dessous reprennent l'esprit de la demande.
|
||||
|
||||
| Voie | Contenu | Fichiers et assets touchés | GI | Agent, niveau | Durée (estimée) | Risques | Preuve en jeu |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| **V0. Vérifier, sans code** | essai en jeu à trois captures, avec la build COM22 ou la suivante | aucun | non | Big Boss, utilisateur | 15 à 20 min | aucun | titre → Settings (onglets) ; partie → Échap → Settings (onglets ou non) ; journal : lignes `Reglages :` |
|
||||
| **V1. Corriger H1** (si V0 la confirme) | choisir la liste de l'instance **à l'écran** (`IsInViewport()`), reconstruire `TabBar` et `KeyboardHost` quand leur `Canvas` n'est plus celui de la liste | `Source/LifePlay/LPSettingsSubsystem.cpp` (≈ 15 à 40 lignes, estimé) ; 0 Blueprint | **non** | SPEC N2 ; IMPL `lp-impl` (Sonnet) ; BUILD `lp-builder` ; VAL `lp-validator` distinct | SPEC 8 à 12 tours, IMPL 10 à 15, VAL 10 à 15 ; essai sous jeton 30 min | `TObjectIterator` + durée de vie des widgets ; régression sur l'écran titre ; les quatre autres sous-systèmes ont le même motif de recherche (`ColorGrade:263`, `VideoQuality:466`, `Keyboard:854`, `ModInfo:246`) et pourraient avoir la même faille | idem V0 + redémarrage en partie, 2 allers-retours titre ↔ partie |
|
||||
| **V2. Réécriture C++ du module (doc 37 § 2.4 pris au pied de la lettre)** | nouveau panneau en C++ qui lit et écrit les réglages de partie (≈ 40 lignes) par réflexion sur `GI`, appelle `GI.SaveSettings` par `ProcessEvent`, remplace la liste ; `MainMenu.SettingsScrollBox` repliée et gardée « forkée » dans l'asset | nouveau `LPSettingsPanel.*`, retouche de `LPSettingsSubsystem.cpp` et des quatre autres sous-systèmes (leurs lignes migrent), `LPCameraModeSubsystem` / `LPDirectControlSubsystem` / `LPOutdoorRoomSubsystem` / `LPDebugSubsystem` si la classe `MainMenu_C` change | **non** si l'écriture passe par la réflexion (modèle `ApplyCameraSpeedAtStartup`, `LPUserSettings.h:44-54`) ; **oui** si le Blueprint doit appeler le C++ | SPEC N3 (opus) ; IMPL `lp-impl-max` ; BUILD ; VAL ; essai long | 2 à 3 jours, répartis sur au moins 2 créneaux de la copie UE | perte de réglages joueurs (champs de `GameSettings` non listés), `Construct` de `MainMenu` qui initialise les widgets de la liste, 14 lignes non identifiées, listes `MainMenu_C` des quatre sous-systèmes | partie complète : tous les réglages, Continuer, redémarrage, comparaison de `GameSettings.sav` avant et après |
|
||||
| **V3. Modifier `MainMenu` par MCP** | recâbler `SettingsButton` ou masquer la liste | `Content/UI/MainMenu.uasset` (`lp-mcp-bp`, instantané, jeton) | non | `lp-mcp-bp` N2 | 1 créneau | **non recommandée** : aucun gain (l'ouverture est déjà commune), asset partagé avec l'écran titre et avec DISC1, et la liste est cherchée par nom par cinq sous-systèmes | — |
|
||||
|
||||
**GI.uasset** (révisé une seule fois, en build 2, règle citée par la fiche et par `FIX1-F6-PRE.md:107-108`) : V0, V1 et V3 ne le touchent pas ; V2 ne le touche pas si l'écriture passe par la réflexion (estimé).
|
||||
|
||||
### 3.5 Recommandation (question 5)
|
||||
|
||||
- **Build 1 : V0 seulement, puis V1 si H1 est confirmée.** Justification : (i) la prémisse « deux panneaux » n'est pas établie ; ouvrir une IMPL sur une prémisse non vérifiée est le pire coût possible avec un gel au 24 ; (ii) V0 ne coûte aucun jeton de copie UE (build COM22, estimé) ; (iii) la file de la copie UE est pleine (`37_…md:179-185` : STM1, CG2, CAM2, FIX1 le J3, KEY2 le J4, REL2 le J5) ; V1 serait un créneau de plus, à placer au J3 (voisin de FIX1) ou à écarter ; (iv) le doc 37 range la dépréciation en § 2 (« après l'alpha »), pas dans le tableau des lots de la build 1 (`37_…md:161-172` : pas de ligne SET1).
|
||||
- **Build 2 : V2** si l'utilisateur confirme qu'il veut une réécriture C++ du module (H3), avec SPEC N3 et liste exacte des champs de `GameSettings`. À grouper avec la révision unique de GI si un appel Blueprint devient nécessaire.
|
||||
- **Porte proposée pour V1** : si V0 montre les onglets absents en partie, SPEC le 2026-10-21, IMPL hors copie UE, essai au J3 ou J4 ; sinon V1 passe en build 2. Aucune décision n'est prise ici : elle revient à l'utilisateur.
|
||||
|
||||
## 4. Établi / estimé / incertain (synthèse)
|
||||
|
||||
**Établi** : `MainMenu.uasset` est le seul asset portant `SettingsScrollBox` (observation 6) ; le « nouveau panneau » est cette liste montée en onglets par le C++ (`LPSettingsSubsystem.h:1-6`, `.cpp:764-889`) ; seul le bouton de l'écran titre est ajouté par le C++ et propre au titre (`.cpp:757-761`) ; le bouton `SettingsButton`, `Back` et le widget `MainMenu` servent titre et partie (observations 9, 10, 15, 17) ; cinq sous-systèmes injectent ou cherchent la liste par son nom (observation 13) ; `MainMenu_C` est compté « menu ouvert » dans quatre listes de classes (observation 14) ; `GI` porte `MainMenuInput`, `OpenMainMenu`, `CloseMainMenu`, `CreateMainMenuWidget` ; la vitesse de caméra vit dans `GameUserSettings.ini` ; `GI.SaveSettings` / `LoadSettings` existent dans l'asset (compte 4) ; le journal COM22 ne montre aucune ouverture des réglages (aucune ligne `onglets`).
|
||||
|
||||
**Estimé** : les onglets s'appliquent aussi en partie (le `Tick` ne distingue pas) ; H1 (instance périmée) comme cause possible d'un écart ; V1 : 15 à 40 lignes ; V2 : 2 à 3 jours ; V0 réalisable sans jeton de copie UE ; V2 sans GI si réflexion.
|
||||
|
||||
**Incertain, essai qui trancherait** :
|
||||
- Ce que l'utilisateur appelle « ancien panneau » : captures du titre et de la partie (V0).
|
||||
- Si `CreateMainMenuWidget` crée un widget neuf à chaque ouverture et quand l'ancien est collecté : lecture de `GI.OpenMainMenu` / `MainMenuInput` (`IfThenElse_6451`) et `LPDumpFunction -BP=GI`, ou le journal de V0.
|
||||
- Liste exacte des lignes actuelles de la liste (14 noms du dump 5.5 non retrouvés) : `LPDumpWidgetTree -BP=MainMenu`, éditeur fermé.
|
||||
- Champs de `GameSettings` (SaveGame) : `LPDumpSave` ou `LPDumpCDO` sur `GameSettings`, éditeur fermé.
|
||||
- Pause du jeu pendant le menu : lecture de `GI.MainMenuInput` en entier.
|
||||
- Sens de « forké » et de « release suivante » (doc 37 § 2.4).
|
||||
|
||||
## 5. Points à confirmer (repris par la fiche suivante)
|
||||
|
||||
1. Exécuter V0 (essai en jeu, trois captures + journal).
|
||||
2. Si H1 : lire `GI.OpenMainMenu` / `MainMenuInput` / `CreateMainMenuWidget` et la fin de vie du widget (`RemoveFromParent`, `CloseSelf`).
|
||||
3. Relever la liste des lignes de `MainMenu` (`LPDumpWidgetTree`, copie UE) et celle des champs de `GameSettings` (`LPDumpSave`) avant toute V2.
|
||||
4. Relire `LPColorGradeSubsystem.cpp:27` et `LPVideoQualitySubsystem.cpp:71` (fichiers `.ini`), repris ici de `FIX1-F6-PRE.md:62`.
|
||||
5. Vérifier si les quatre autres sous-systèmes partagent la faille H1 (même motif `TObjectIterator` + `break`).
|
||||
6. Si V2 : relever les appels de `ULPKeyboardSubsystem::TakeEmbeddedPage` et le test `MenuOnScreen` (`LPKeyboardSubsystem.cpp:819-860`) pour ne pas casser KEY2.
|
||||
7. Ajouter une ligne SET1 au tableau du doc 37 § 3.1 si l'utilisateur ouvre le lot (aujourd'hui absente).
|
||||
|
||||
## 6. Questions pour la SPEC ou l'utilisateur
|
||||
|
||||
1. **Q1 (bloquante)** : en partie, quel écran voyez-vous quand vous appuyez sur Échap puis sur Settings : les onglets General, Audio, Video, Keyboard, Lewd, Misc sont-ils présents ? Si non, une capture de chaque écran (titre, partie).
|
||||
2. **Q2** : le doc 37 § 2.4 (« l'ancien module de réglages est forké et désactivé ; le menu redirige vers le nouveau panneau du menu général ») vise-t-il (i) un défaut d'affichage en partie, (ii) la réécriture du module de réglages en C++ (V2), ou (iii) autre chose ? Que signifie « forké » ?
|
||||
3. **Q3** : « la release suivante » : laquelle (alpha 2.2a, ou après l'alpha) ?
|
||||
4. **Q4** : accord pour l'essai V0 avec la build COM22, ou faut-il attendre la prochaine build ?
|
||||
5. **Q5** : si H1 est confirmée, V1 en build 1 sous une porte au J4, ou directement en build 2 ?
|
||||
6. **Q6** : V2 : périmètre (tous les réglages de partie, ou seulement l'affichage) et risque accepté sur `GameSettings.sav` ?
|
||||
|
||||
## Fichiers à commiter
|
||||
|
||||
A `Docs/Migration/etat/REL/SET1/SET1-PRE.md` (dépôt du jeu, `.md` suivi sous `etat/`). Aucun autre fichier écrit.
|
||||
|
||||
Tours : 24 / 25 (déclaré par l'agent ; `Tools/FicheStats.py` fait foi)
|
||||
376
Docs/Migration/etat/REL/SET1/SET1-V1-IMPL.md
Normal file
376
Docs/Migration/etat/REL/SET1/SET1-V1-IMPL.md
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
Fiche SET1-V1 — Niveau N2 — Modèle prévu Sonnet (fiche) | utilisé claude-sonnet-5-5 — Agent lp-impl — Skills sk-protocol, ue-cpp-build (préchargés en plus : lp-build, lp-ue-compat)
|
||||
# SET1-V1-IMPL : poser les onglets des réglages sur l'instance de MainMenu qui est à l'écran (2026-10-20)
|
||||
|
||||
Hors gabarit : la fiche demande une mini-SPEC en tête (§ 0), puis les rubriques IMPL 1 à 6 ; les sections 7 à 11 (compilation, 4 autres sous-systèmes, journaux, preuve en jeu, diff) sont demandées par la fiche. Contenu adulte (doc 27) : noms techniques de widgets seulement.
|
||||
|
||||
Résultat : **réussi à la compilation** (éditeur et jeu : code 0, 0 erreur, 0 avertissement) ; **non éprouvé en jeu** (la preuve en jeu revient à la VAL, § 10). Un défaut voisin subsiste dans trois autres sous-systèmes (§ 8) et peut gâcher la preuve : à lire avant la VAL.
|
||||
|
||||
## 0. Mini-SPEC (écrite avant le code)
|
||||
|
||||
**Cause établie.** `GI.CreateMainMenuWidget` crée un `MainMenu` neuf à chaque ouverture (`CreateWidget` puis `AddToViewport` ZOrder 0, variable `MainMenu`) : `CAM-B1-PRE_LPDumpFunction_20261013-083048.txt:5171-5185`. `GI.ClearMainMenuWidget` ne fait que `Widget::RemoveFromParent()` sur cette variable : même fichier `:5209-5213`. Une ancienne instance sort donc du viewport mais reste en mémoire, avec sa `SettingsScrollBox`, jusqu'au ramasse-miettes. Le `Tick` prenait la **première** liste trouvée par `TObjectIterator` (`LPSettingsSubsystem.cpp` avant correction, `:498-517`, `break` l. 516) : une ancienne instance, souvent plus ancienne dans le tableau d'objets, passait avant la nouvelle. `EnsureTabs` sortait tant que `TabBar` était valide (`:766-769`), donc la barre restait sur l'ancienne. Quand l'ancienne était collectée (≈ 30 s), la nouvelle recevait enfin ses onglets : c'est le retard de la capture de l'utilisateur. *Estimé* : la superposition vient de ce passage (lignes rendues visibles par le Blueprint tant que le C++ ne filtre pas, puis filtrées d'un coup) ; non reproduite ici.
|
||||
|
||||
**Règle de choix de la liste.** Un candidat est une `SettingsScrollBox` non CDO, non archétype, vivante, dont le `UUserWidget` propriétaire (le `MainMenu`) est du même `GameInstance` et **à l'écran** : vivant (`IsValid`, ni `RF_BeginDestroyed` ni `RF_FinishDestroyed`), `IsInViewport()` vrai, visibilité ni `Collapsed` ni `Hidden`. Parmi plusieurs candidats : la liste ouverte d'abord, puis celle déjà suivie, sinon la première. Aucun candidat : rien n'est choisi, les réglages sont vus fermés.
|
||||
|
||||
**Cas écran titre.** Une seule instance, à l'écran. Le bouton `LPSettingsTitleButton` se pose sur son `MainMenuOptions` ; au clic, `OpenSettings` diffuse `SettingsButton` de cette instance ; dès que la liste est visible, `EnsureTabs` crée la barre et l'hôte du clavier sur son `CanvasPanel`. Journal : `Reglages : onglets poses sur <MainMenu_C_n> (ecran titre)`.
|
||||
|
||||
**Cas partie.** Chaque ouverture crée une instance neuve. Les instances précédentes sont hors viewport : ignorées. Si `SettingsList` pointe encore une autre instance, ou si `TabBar` n'est plus sur le canvas de la liste choisie, les onglets de l'ancienne sont retirés (`RemoveFromParent`, page du clavier lâchée, capture annulée, `TabBar` et `KeyboardHost` remis à nul), l'état par instance est remis à zéro (`bKeyboardPage`, `bControlsHardened`, `LastChildCount`), puis `EnsureTabs` pose une barre neuve sur la nouvelle liste, à la même image. Journal : `Reglages : onglets retires de <ancienne> (instance quittee)` puis `Reglages : onglets poses sur <MainMenu_C_n> (partie)`.
|
||||
|
||||
**Retour au titre.** L'instance de partie est retirée du viewport : plus de candidat tant que le nouvel écran titre n'est pas créé (les réglages sont vus fermés : capture de touche annulée, hôte du clavier replié). Le nouvel écran titre est à l'écran : il est choisi à son tour, le bouton C++ se pose sur **son** menu (`PlaceSettingsButton` filtre aussi sur l'écran), `SourceSettings` pointe son `SettingsButton`, les onglets se posent sur sa liste. Titre ou partie se lit par la variable Blueprint `MainMenu.TitleScreen` (`Docs/Migration/etat/ST/STB/dumps/MainMenu__EventGraph.txt:1061-1084` : elle commande `ClearMainMenuWidget` + `DelayedStart` sur l'écran titre), repli sur la visibilité de `ModManagerTitleButton`.
|
||||
|
||||
**Périmètre.** `Source/LifePlay/LPSettingsSubsystem.cpp` seul ; `.h` non modifié (aucun membre ajouté : la détection de l'instance compare `SettingsList` et le parent de `TabBar`). Ni Blueprint ni GI. Correctifs de compatibilité UE4 (`LPStringCompat`, `LPMeshCompat`, `LPNavigationHelpers`) non touchés.
|
||||
|
||||
## 1. Fichiers modifiés
|
||||
|
||||
| Fichier | Lignes (après modification) | Contenu |
|
||||
|---|---|---|
|
||||
| `Source/LifePlay/LPSettingsSubsystem.cpp` | 32 | `#include "Widgets/SNullWidget.h"` |
|
||||
| idem | 106-198 | 5 fonctions dans `namespace LPSettingsUi` : `IsUsableObject` (109), `IsMenuOnScreen` (115), `FindOnScreenSettingsList` (122), `IsTitleMenu` (149), `DropTabs` (166) |
|
||||
| idem | 596-616 | `Tick` (commence l. 592) : la boucle « première liste trouvée » est remplacée par `FindOnScreenSettingsList` ; changement d'instance → `DropTabs` + remise à zéro de l'état |
|
||||
| idem | 676-682 | `PlaceSettingsButton` (commence l. 664) : ajoute `!IsMenuOnScreen(MenuOwner)` à la condition d'exclusion |
|
||||
| idem | 930-935 | `EnsureTabs` (commence l. 860) : `bKeyboardPage = false` (930) à la création, journal `Reglages : onglets poses sur %s (%s)` (933-935) |
|
||||
|
||||
Total : `Source/LifePlay/LPSettingsSubsystem.cpp | 146 +++++++++++++++++++++++++++-----` (123 insertions, 23 suppressions), `git diff --stat`. Fins de ligne CRLF conservées (996 CRLF, 0 LF, § 9).
|
||||
|
||||
API moteur utilisée, lue dans `D:\Game\Launcher\Engine\UE_5.8\Engine\Source` (5.8.3) :
|
||||
|
||||
| API | Source |
|
||||
|---|---|
|
||||
| `UWidget::IsInViewport` : vrai si ajouté par `AddToViewport` ou `AddToPlayerScreen` | `Runtime/UMG/Public/Components/Widget.h:547-549` ; `Private/Components/Widget.cpp:344-354` (appelle `UGameViewportSubsystem::IsWidgetAdded`, `Private/Blueprint/GameViewportSubsystem.cpp:89-105`) |
|
||||
| `RemoveFromParent` sur un widget du viewport → `Subsystem->RemoveWidget` → `bIsManagedByGameViewportSubsystem = false` : `IsInViewport` devient faux | `Widget.cpp:895-905` ; `GameViewportSubsystem.cpp:199-214` |
|
||||
| `UWidget::RemoveFromParent` (virtuel public) ; sur un enfant de panneau → `CurrentParent->RemoveChild(this)` | `Widget.h:776` ; `Widget.cpp:906-909` |
|
||||
| `UUserWidget::AddToViewport` → `Subsystem->AddWidget` | `Runtime/UMG/Private/UserWidget.cpp:1366-1378` |
|
||||
| `IsValid(const UObject*)` : ni nul, ni `Garbage`, ni `Unreachable` | `Runtime/CoreUObject/Public/UObject/Object.h:1855-1862, 1886-1889` |
|
||||
| `RF_BeginDestroyed`, `RF_FinishDestroyed` | `Runtime/CoreUObject/Public/UObject/ObjectMacros.h:610-611` |
|
||||
| `UObject::GetTypedOuter<T>() const` | `Runtime/CoreUObject/Public/UObject/UObjectBaseUtility.h:550-551` |
|
||||
| `FBoolProperty::GetPropertyValue_InContainer(void const*, int32) const` | `Runtime/CoreUObject/Public/UObject/UnrealType.h:2688` |
|
||||
| `UUserWidget::GetWidgetFromName(const FName&) const` | `Runtime/UMG/Public/Blueprint/UserWidget.h:1426` ; `Private/UserWidget.cpp:1259-1262` |
|
||||
| `UNativeWidgetHost::SetContent(TSharedRef<SWidget>)` (remplace le contenu de l'`SBox` vivant) | `Runtime/UMG/Public/Components/NativeWidgetHost.h:20` ; `Private/Components/NativeWidgetHost.cpp:24-37` |
|
||||
| `SNullWidget::NullWidget` (`TSharedRef<SWidget>` statique) | `Runtime/SlateCore/Public/Widgets/SNullWidget.h:22` |
|
||||
|
||||
Les seules API nouvelles sont celles de ce tableau ; `IsOpen`, `TObjectIterator`, `CastField`, `FindPropertyByName`, `RemoveFromParent` de `UWidget` étaient déjà employées dans le fichier ou sont citées ci-dessus.
|
||||
|
||||
## 2. Écarts à la SPEC / à la fiche
|
||||
|
||||
| # | Écart | Motif |
|
||||
|---|---|---|
|
||||
| E1 | `PlaceSettingsButton` filtre aussi sur « MainMenu à l'écran » (fiche : la `SettingsScrollBox` seulement). | Même défaut, même fichier : sans cela, au retour au titre le bouton C++ et `SourceSettings` restent sur l'ancienne instance (premier `MainMenuOptions` trouvé, `break`), donc « retour au titre puis réouverture : idem » ne peut pas tenir. |
|
||||
| E2 | Journal supplémentaire `Reglages : onglets retires de <nom> (instance quittee)` (fiche : une seule ligne, au rattachement). | Preuve du « plus aucune superposition » : la ligne montre que la barre de l'ancienne instance est retirée. |
|
||||
| E3 | `bKeyboardPage = false` à la création d'une barre (`EnsureTabs`). | Défaut latent voisin : si l'ancienne instance disparaissait avec `bKeyboardPage` vrai, la page du clavier n'était jamais reposée sur l'hôte neuf. Nécessaire au rattachement sur nouvelle instance. |
|
||||
| E4 | Capture de touche annulée (`CancelWait`) quand la page du clavier change d'instance. | La page Slate est unique (`LPKeyboardSubsystem.cpp:898-903` renvoie la même tant qu'elle vit) ; chemin déjà employé par le code existant (`!bOpen`). |
|
||||
| E5 | Aucun candidat à l'écran → réglages vus fermés (chemin `!bOpen` existant : barre repliée, hôte replié, capture annulée). Avant, la liste d'une ancienne instance restait trouvée. | Conséquence directe de la règle de choix ; à observer en VAL (§ 10, V6). |
|
||||
| E6 | `.h` non modifié. | Conforme à la fiche ; cité ici pour qu'on ne le cherche pas. |
|
||||
| E7 | `CopieEtat.ps1 -Lot SET1` rend `ALERTE GIT` pour 3 fichiers (code 1). | Deux sont **antérieurs** à mon travail (statut git de départ : `LPCameraModeSubsystem.cpp`, `LPDirectControlSubsystem.cpp`, non ouverts ni modifiés par moi) ; le troisième est mon fichier, non déclaré par `-Assets` (la fiche n'en déclare aucun). |
|
||||
|
||||
## 3. Instantané
|
||||
|
||||
`D:\Game\LifePlay_Backup_5.5\SET1\` (fait par l'orchestrateur) : `Source\LifePlay\LPSettingsSubsystem.cpp`, 29138 octets, MD5 `5FF9F26D45634DE43113098FB9798597`, 2026-10-20T21:17:50 (`manifest.csv`). Le `.h` n'est pas dans le manifeste : il n'a pas été modifié (MD5 inchangé, § 9). Retour arrière (proposé, non lancé) : `Tools\Restore.ps1 -Lot SET1`.
|
||||
|
||||
## 4. Ce qui n'a pas été fait
|
||||
|
||||
- Aucun essai en jeu (la fiche n'en confie pas) ; aucun jeton de jeu ni d'éditeur utilisé.
|
||||
- `LPColorGradeSubsystem`, `LPVideoQualitySubsystem`, `LPModInfoSubsystem` non modifiés (consigne) ; leur défaut est décrit en § 8.
|
||||
- `LPKeyboardSubsystem.cpp`, `LPReadableTextSubsystem.cpp`, `LPCameraModeSubsystem.cpp`, `LPDirectControlSubsystem.cpp` : lus seulement ou non ouverts.
|
||||
- Pas de réécriture du module en C++ (V2 de `SET1-PRE.md`) ; pas de test automatique (aucun existant pour ce sous-système).
|
||||
- Pas de build de test empaqueté.
|
||||
|
||||
## 5. Points à confirmer en VAL (un par ligne)
|
||||
|
||||
1. V1 : Settings ouvert depuis l'écran titre, premier lancement : onglets visibles dès l'ouverture, sans liste longue ; journal `Reglages : onglets poses sur MainMenu_C_<n> (ecran titre)`.
|
||||
2. V2 : partie lancée, Échap, Settings : onglets tout de suite, sans liste longue ni superposition ; journal `(partie)`.
|
||||
3. V3 : deuxième et troisième ouverture en partie (nouvelle instance à chaque fois) : onglets tout de suite ; journal `onglets retires de <ancienne>` puis `onglets poses sur <nouvelle> (partie)` ; aucun `ensure`, aucun avertissement Slate « widget already has a parent » dans `LifePlay.log`.
|
||||
4. V4 : retour au titre puis réouverture : le bouton Settings C++ est présent sur le **nouvel** écran titre dès son affichage, il ouvre ses réglages, onglets tout de suite ; `(ecran titre)` dans le journal.
|
||||
5. V5 : étiquette `(ecran titre)` / `(partie)` exacte (lecture de `MainMenu.TitleScreen`, `LPSettingsSubsystem.cpp:149-162`) ; si elle est fausse, repli sur `ModManagerTitleButton` à envisager.
|
||||
6. V6 : `IsInViewport()` vrai pour l'instance **écran titre** (créée par `CreateMainMenuWidget` d'après les dumps, non observé en jeu) ; symptôme si faux : aucun onglet et aucune ligne `Reglages : onglets poses` au titre.
|
||||
7. V7 : onglet Keyboard : ouvrir en première instance, fermer, rouvrir en seconde instance : la page s'affiche (hôte neuf, page lâchée par l'ancien) ; une capture de touche en cours au moment du changement d'instance est annulée.
|
||||
8. V8 : onglets Video et Misc de l'instance de partie : présence de `LPColor*`, `LPVideo*`, `LPModCheck*` (§ 8 : ces lignes sont posées par trois sous-systèmes qui prennent encore la première liste trouvée ; elles peuvent manquer sur la nouvelle instance tant que l'ancienne n'est pas collectée).
|
||||
9. V9 : cases et curseurs de la nouvelle instance durcis (case ×2, style sombre : `HardenSettingsControls` rejoué, car `bControlsHardened` est remis à faux au changement d'instance).
|
||||
10. V10 : aucune régression sur l'ouverture des réglages hors changement d'instance (même instance, ouvrir, Back, rouvrir : une seule barre, pas de nouveau journal `onglets poses`).
|
||||
|
||||
## 6. Fichiers à commiter
|
||||
|
||||
M `Source/LifePlay/LPSettingsSubsystem.cpp` (dépôt du jeu, branche `ue5.8`)
|
||||
A `Docs/Migration/etat/REL/SET1/SET1-V1-IMPL.md` (dépôt du jeu)
|
||||
A `Docs/Migration/etat/REL/SET1/SET1_Build_20261020-212529.txt` (résumé `Build.ps1` éditeur)
|
||||
A `Docs/Migration/etat/REL/SET1/SET1_Build_20261020-212627.txt` (résumé `Build.ps1` jeu)
|
||||
A `Docs/Migration/etat/REL/SET1/SET1-V1_CopieEtat_avant_build.json`, `SET1-V1_CopieEtat_apres_build.json` (traces `CopieEtat.ps1`)
|
||||
|
||||
Hors lot, déjà modifiés avant moi et **à ne pas embarquer** : `Source/LifePlay/LPCameraModeSubsystem.cpp`, `Source/LifePlay/LPDirectControlSubsystem.cpp`.
|
||||
|
||||
## 7. Compilation (boucle demandée par la fiche)
|
||||
|
||||
Aucune erreur : pas de correctif de la boucle U3. Éditeur fermé et rien ne tournait avant les builds (`UeState -WaitExit` : `processus=0 editeur=0 compilation=0`) ; état final au § 9.
|
||||
|
||||
| | LifePlayEditor Win64 Development | LifePlay Win64 Development `-NoUBA` |
|
||||
|---|---|---|
|
||||
| Commande | `pwsh -NoProfile -File Tools/Build.ps1 -Lot SET1 -EtatDir "D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\SET1"` | idem + `-Target LifePlay -Config Development -ExtraArgs '-NoUBA'` |
|
||||
| Code de sortie | 0 | 0 |
|
||||
| Durée | 47 s | 54 s |
|
||||
| Erreurs / avertissements du compilateur | 0 / 0 | 0 / 0 |
|
||||
| Autres lignes (UBT, UHT, liens) | 20 (les 20 lignes `HyperAIStudio does not list plugin` connues, `lp-build` § 7 : attendu 20 pour l'éditeur) | 0 (attendu 0 pour la cible jeu) |
|
||||
| Unités compilées | `LPSettingsSubsystem.cpp`, `Module.LifePlay.cpp` | `LPSettingsSubsystem.cpp [NoUba]`, `Module.LifePlay.cpp [NoUba]` |
|
||||
| Liaison | `UnrealEditor-LifePlay.dll` (DLL liées : 1) | `[3/4] Link [x64] LifePlay.exe [NoUba]`, `Output binary: …\Binaries\Win64\LifePlay.exe`, `Result: Succeeded` (journal `:22, :27, :29`) ; le résumé compte « DLL liées : 0 » car le jeu lie un `.exe` |
|
||||
| Toolchain | `Using Visual Studio 14.50.35739 toolchain (C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.50.35717)` = MSVC épinglé de la 5.8 | idem |
|
||||
| Résumé | `Docs\Migration\etat\REL\SET1\SET1_Build_20261020-212529.txt` | `Docs\Migration\etat\REL\SET1\SET1_Build_20261020-212627.txt` |
|
||||
| Journal | `Saved\Logs\portage\SET1_Build_20261020-212529.log` | `Saved\Logs\portage\SET1_Build_20261020-212627.log` |
|
||||
|
||||
Limites : makefile (ligne `Makefile` du résumé) vide dans les deux résumés ; le module modifié figure bien dans les unités compilées. Le LifePlay.exe est daté du 2026-10-20 21:27:19. Aucune ligne de journal propre au nouveau code n'existe avant un lancement du jeu (§ 10).
|
||||
|
||||
## 8. Les quatre autres sous-systèmes (fiche, point 3)
|
||||
|
||||
Aucun ne partage une fonction de recherche avec `LPSettingsSubsystem` : chacun recopie la boucle. Rien n'a donc été modifié. Lectures faites dans ce lot (`Read`) :
|
||||
|
||||
| Sous-système | Lieu | Verdict |
|
||||
|---|---|---|
|
||||
| `LPColorGradeSubsystem` (`EnsureControls`) | `LPColorGradeSubsystem.cpp:259-274` : `TObjectIterator`, **`break` à la première liste** du `GameInstance`, aucune condition d'écran ; ajoute `LPColor*` si `LPColorBrightness` absent (`:279-288`) | **même défaut** |
|
||||
| `LPVideoQualitySubsystem` (`EnsureControls`) | `LPVideoQualitySubsystem.cpp:462-477`, présence testée sur `LPVideoOverall` (`:487-489`) | **même défaut** |
|
||||
| `LPModInfoSubsystem` (`EnsureSettingsRows`) | `LPModInfoSubsystem.cpp:242-257`, présence testée sur `RowNames[0]` (`:262-268`) | **même défaut** |
|
||||
| `LPKeyboardSubsystem` (`Tick`) | `LPKeyboardSubsystem.cpp:846-871` : boucle sans `break`, ne sert qu'à un indicateur `bFound` pour un journal (`Clavier : liste des reglages pas encore ouverte`) | pas de défaut de choix d'instance ; une ancienne liste compte comme « trouvée » (journal seulement) |
|
||||
| `LPReadableTextSubsystem` | `LPReadableTextSubsystem.cpp:118-125` : remonte les parents d'un widget donné jusqu'à une `SettingsScrollBox` | sans objet : pas de choix d'instance |
|
||||
|
||||
**Conséquence établie par lecture, non observée en jeu** (estimé pour l'ordre d'itération) : si une ancienne liste précède la nouvelle, les trois premiers y injectent leurs lignes (`LPColor*`, `LPVideo*`, `LPModCheck*`) et la nouvelle liste, déjà dotée d'onglets par ce lot, **n'a pas ces lignes** (onglets Video et Misc incomplets) tant que les anciennes instances ne sont pas collectées. Ce lot ne l'aggrave pas (avant lui, les onglets eux-mêmes étaient en retard), mais la preuve en jeu V8 peut le montrer.
|
||||
|
||||
**Suite proposée (non faite, hors périmètre de la fiche)** : un lot `SET1-V1b` qui expose `FindOnScreenSettingsList` (aujourd'hui dans `namespace LPSettingsUi` du `.cpp`) comme fonction statique publique de `ULPSettingsSubsystem` (`.h` + `.cpp`) et remplace les trois boucles par un appel (≈ 14 lignes → 1 par fichier, 3 fichiers). Risque : ces trois sous-systèmes testent la présence de leur première ligne sur la liste choisie ; avec la bonne liste, la nouvelle instance reçoit ses lignes à chaque ouverture (comportement voulu).
|
||||
|
||||
## 9. MD5 et fins de ligne
|
||||
|
||||
Commande : `md5sum Source/LifePlay/LPSettingsSubsystem.cpp Source/LifePlay/LPSettingsSubsystem.h ; git ls-files --eol …` (après modification) :
|
||||
|
||||
```
|
||||
3591f579d88c4ca3a44468c750c9a24e *Source/LifePlay/LPSettingsSubsystem.cpp
|
||||
0f98c05568ae789c5c0b78f6ec580503 *Source/LifePlay/LPSettingsSubsystem.h
|
||||
i/crlf w/crlf attr/-text Source/LifePlay/LPSettingsSubsystem.cpp
|
||||
i/crlf w/crlf attr/-text Source/LifePlay/LPSettingsSubsystem.h
|
||||
```
|
||||
|
||||
| Fichier | MD5 avant (relu avant d'écrire) | MD5 après |
|
||||
|---|---|---|
|
||||
| `LPSettingsSubsystem.cpp` | `5ff9f26d45634de43113098fb9798597` (= manifeste `5FF9F26D…`) | `3591f579d88c4ca3a44468c750c9a24e` |
|
||||
| `LPSettingsSubsystem.h` | `0f98c05568ae789c5c0b78f6ec580503` | inchangé |
|
||||
|
||||
`pwsh -NoProfile -File Tools/FileCheck.ps1 -Lot SET1` :
|
||||
```
|
||||
CRLF 996 0 0 - 3591F579D88C4CA3A44468C750C9A24E CRLF - modifie Source/LifePlay/LPSettingsSubsystem.cpp
|
||||
fichiers=1 CRLF=1 alertes=0 introuvables=0
|
||||
```
|
||||
`pwsh -NoProfile -File Tools/PubCheck.ps1 -Fichiers Source/LifePlay/LPSettingsSubsystem.cpp -Depot "D:/Game/LifePlay-master 5.8"` (stdin sur `/dev/null`) : `PubCheck : 0 constat(s)`, code 0.
|
||||
|
||||
Livrable : 0 CR (fins de ligne LF), `PubCheck` sur `SET1-V1-IMPL.md` : `PubCheck : 0 constat(s)`.
|
||||
|
||||
Fin de lot : `pwsh -NoProfile -File Tools/UeState.ps1 < /dev/null` → `processus=0 editeur=0 compilation=0 shaders=0 jeu=0`, code 0. **Jeton UE rendu.**
|
||||
|
||||
`CopieEtat.ps1 -Lot SET1` (avant et après build) : `COPIE ALERTE lot=SET1 … proc=0 assets=0 … git=3/0/0 hors_declares=3 parasites=0 … alertes=GIT` ; code 1 ; voir E7. Traces : `SET1-V1_CopieEtat_avant_build.json`, `SET1-V1_CopieEtat_apres_build.json`.
|
||||
|
||||
## 10. Journaux et preuve attendue en jeu
|
||||
|
||||
Lignes de journal (préfixe `LogLifePlay: ` dans `LifePlay.log`) :
|
||||
|
||||
| Ligne | Origine | Quand |
|
||||
|---|---|---|
|
||||
| `Reglages : onglets General, Audio, Video, Keyboard, Lewd, Misc` | existante (`LPSettingsSubsystem.cpp:932`) | à chaque création de barre |
|
||||
| `Reglages : onglets poses sur <MainMenu_C_n> (ecran titre|partie)` | **nouvelle** (`:934-935`), exigée par la fiche | juste après la précédente |
|
||||
| `Reglages : onglets retires de <MainMenu_C_k> (instance quittee)` | **nouvelle** (`DropTabs`, `:180`), E2 | au changement d'instance, avant les deux précédentes |
|
||||
| `Reglages : entree Settings ajoutee sur l'ecran titre`, `Reglages : Settings place apres Mod Manager` | existantes | création du bouton C++ |
|
||||
|
||||
Recette de lecture pour la VAL (journal de la session, pas de compte reconstitué de mémoire) : `pwsh -NoProfile -File Tools/LogStats.ps1 -Latest <nom> -Pattern 'Reglages : ' -Max 40` ou `-Log <LifePlay.log>`.
|
||||
|
||||
Preuve attendue (trois scénarios de la fiche, à rejouer par la VAL sur un build Development) :
|
||||
|
||||
| Scénario | Attendu à l'écran | Attendu au journal |
|
||||
|---|---|---|
|
||||
| Settings depuis l'écran titre | onglets General, Audio, Video, Keyboard, Lewd, Misc dès l'ouverture, aucune liste longue | `onglets poses sur MainMenu_C_<n> (ecran titre)`, une fois |
|
||||
| Settings en partie (Échap), plusieurs ouvertures | onglets dès l'ouverture, sans liste longue, sans superposition, sans attente de ≈ 30 s | `onglets poses sur MainMenu_C_<n> (partie)` à chaque nouvelle instance, précédé de `onglets retires de <ancienne>` si une barre existait |
|
||||
| Retour au titre puis réouverture | bouton Settings présent sur le nouvel écran titre, onglets dès l'ouverture | `onglets poses sur MainMenu_C_<m> (ecran titre)` avec un `<m>` différent du premier titre |
|
||||
|
||||
Limite : la lecture en jeu de `TitleScreen`, de `IsInViewport` pour l'instance du titre, et l'ordre réel d'itération de `TObjectIterator` ne sont pas observés ; ils sont établis par lecture de code et de dumps seulement (§ 0).
|
||||
|
||||
## 11. Diff (`git diff --unified=2 -- Source/LifePlay/LPSettingsSubsystem.cpp`, CR retirés pour la lecture)
|
||||
|
||||
```diff
|
||||
@@ -30,4 +30,5 @@
|
||||
#include "Styling/SlateTypes.h"
|
||||
#include "UObject/TextProperty.h"
|
||||
+#include "Widgets/SNullWidget.h"
|
||||
|
||||
namespace LPSettingsUi
|
||||
@@ -103,4 +104,97 @@ namespace LPSettingsUi
|
||||
}
|
||||
|
||||
+ // Lot SET1-V1. GI.CreateMainMenuWidget cree un MainMenu neuf a chaque ouverture (CreateWidget + AddToViewport) et
|
||||
+ // GI.ClearMainMenuWidget le retire seulement du viewport (RemoveFromParent) : les anciennes instances gardent leur
|
||||
+ // SettingsScrollBox en memoire jusqu'au ramasse-miettes. Seule l'instance a l'ecran compte.
|
||||
+ bool IsUsableObject(const UObject* Object)
|
||||
+ {
|
||||
+ return IsValid(Object) && !Object->HasAnyFlags(RF_BeginDestroyed | RF_FinishDestroyed);
|
||||
+ }
|
||||
+
|
||||
+ // Menu vivant, ajoute au viewport (UWidget::IsInViewport : AddToViewport ou AddToPlayerScreen) et visible.
|
||||
+ bool IsMenuOnScreen(const UUserWidget* Menu)
|
||||
+ {
|
||||
+ return IsUsableObject(Menu) && Menu->IsInViewport() && IsOpen(Menu);
|
||||
+ }
|
||||
+
|
||||
+ // Liste des reglages de l'instance de MainMenu qui est a l'ecran, nulle s'il n'y en a aucune. A egalite entre deux
|
||||
+ // instances a l'ecran : la liste ouverte d'abord, puis celle deja suivie (Current).
|
||||
+ UScrollBox* FindOnScreenSettingsList(const UGameInstance* GI, const UScrollBox* Current)
|
||||
+ {
|
||||
+ UScrollBox* Best = nullptr;
|
||||
+ int32 BestScore = -1;
|
||||
+ for (TObjectIterator<UScrollBox> It; It; ++It)
|
||||
+ {
|
||||
+ UScrollBox* Candidate = *It;
|
||||
+ if (!IsUsableObject(Candidate) || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
|
||||
+ {
|
||||
+ continue;
|
||||
+ }
|
||||
+ const UUserWidget* MenuOwner = Candidate->GetTypedOuter<UUserWidget>();
|
||||
+ if (!MenuOwner || MenuOwner->HasAnyFlags(RF_ClassDefaultObject) || MenuOwner->GetGameInstance() != GI || !IsMenuOnScreen(MenuOwner))
|
||||
+ {
|
||||
+ continue;
|
||||
+ }
|
||||
+ const int32 Score = (IsOpen(Candidate) ? 2 : 0) + (Candidate == Current ? 1 : 0);
|
||||
+ if (Score > BestScore)
|
||||
+ {
|
||||
+ Best = Candidate;
|
||||
+ BestScore = Score;
|
||||
+ }
|
||||
+ }
|
||||
+ return Best;
|
||||
+ }
|
||||
+
|
||||
+ // Ecran titre (MainMenu.TitleScreen, variable du Blueprint) ou partie. Repli : Mod Manager de l'ecran titre visible.
|
||||
+ bool IsTitleMenu(const UUserWidget* Menu)
|
||||
+ {
|
||||
+ if (!Menu)
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (const FBoolProperty* Title = CastField<FBoolProperty>(Menu->GetClass()->FindPropertyByName(TEXT("TitleScreen"))))
|
||||
+ {
|
||||
+ return Title->GetPropertyValue_InContainer(Menu);
|
||||
+ }
|
||||
+ const UWidget* TitleMods = Menu->GetWidgetFromName(TEXT("ModManagerTitleButton"));
|
||||
+ return TitleMods && IsOpen(TitleMods);
|
||||
+ }
|
||||
+
|
||||
+ // Retire la barre d'onglets et l'hote du clavier d'une instance quittee. La page Slate du clavier est unique
|
||||
+ // (ULPKeyboardSubsystem::TakeEmbeddedPage rend la meme tant qu'elle vit) : l'ancien hote la lache avant que le
|
||||
+ // nouveau la prenne. Une capture de touche en cours est annulee (la page change de place).
|
||||
+ void DropTabs(UGameInstance* GI, TWeakObjectPtr<UHorizontalBox>& Bar, TWeakObjectPtr<UNativeWidgetHost>& Host, TArray<TWeakObjectPtr<UTextBlock>>& Labels)
|
||||
+ {
|
||||
+ UHorizontalBox* OldBar = Bar.Get();
|
||||
+ UNativeWidgetHost* OldHost = Host.Get();
|
||||
+ if (OldBar || OldHost)
|
||||
+ {
|
||||
+ if (ULPKeyboardSubsystem* Keys = GI ? GI->GetSubsystem<ULPKeyboardSubsystem>() : nullptr)
|
||||
+ {
|
||||
+ if (Keys->IsWaiting())
|
||||
+ {
|
||||
+ Keys->CancelWait();
|
||||
+ }
|
||||
+ }
|
||||
+ const UUserWidget* OldMenu = OldBar ? OldBar->GetTypedOuter<UUserWidget>() : OldHost->GetTypedOuter<UUserWidget>();
|
||||
+ UE_LOG(LogLifePlay, Display, TEXT("Reglages : onglets retires de %s (instance quittee)"), OldMenu ? *OldMenu->GetName() : TEXT("?"));
|
||||
+ }
|
||||
+ if (OldHost)
|
||||
+ {
|
||||
+ OldHost->SetContent(SNullWidget::NullWidget);
|
||||
+ if (IsUsableObject(OldHost->GetParent()))
|
||||
+ {
|
||||
+ OldHost->RemoveFromParent();
|
||||
+ }
|
||||
+ }
|
||||
+ if (OldBar && IsUsableObject(OldBar->GetParent()))
|
||||
+ {
|
||||
+ OldBar->RemoveFromParent();
|
||||
+ }
|
||||
+ Bar.Reset();
|
||||
+ Host.Reset();
|
||||
+ Labels.Reset();
|
||||
+ }
|
||||
+
|
||||
// Libelle visible seulement : les infobulles provoquent des faux positifs
|
||||
// (ex. "on screen" → Video, "prefer quality" → Video pour NewAnimationsOnly).
|
||||
@@ -500,26 +594,25 @@ bool ULPSettingsSubsystem::Tick(float DeltaTime)
|
||||
(void)DeltaTime;
|
||||
PlaceSettingsButton();
|
||||
- UScrollBox* Scroll = nullptr;
|
||||
- for (TObjectIterator<UScrollBox> It; It; ++It)
|
||||
- {
|
||||
- UScrollBox* Candidate = *It;
|
||||
- if (!Candidate || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
|
||||
- {
|
||||
- continue;
|
||||
- }
|
||||
- const UUserWidget* MenuOwner = Candidate->GetTypedOuter<UUserWidget>();
|
||||
- if (!MenuOwner || MenuOwner->HasAnyFlags(RF_ClassDefaultObject) || MenuOwner->GetGameInstance() != GetGameInstance())
|
||||
- {
|
||||
- continue;
|
||||
- }
|
||||
- Scroll = Candidate;
|
||||
- break;
|
||||
- }
|
||||
- if (!Scroll)
|
||||
- {
|
||||
- return true;
|
||||
- }
|
||||
- SettingsList = Scroll;
|
||||
- const bool bOpen = LPSettingsUi::IsOpen(Scroll);
|
||||
+ // SET1-V1 : la liste de l'instance de MainMenu qui est a l'ecran, pas la premiere trouvee (une ancienne instance,
|
||||
+ // retiree du viewport et pas encore collectee, vient souvent avant). Aucune a l'ecran : Scroll reste nul et les
|
||||
+ // reglages sont vus fermes (capture de touche annulee, page du clavier lachee) ; les onglets restent sur leur
|
||||
+ // ancienne instance jusqu'au prochain rattachement.
|
||||
+ UScrollBox* Scroll = LPSettingsUi::FindOnScreenSettingsList(GetGameInstance(), SettingsList.Get());
|
||||
+ if (Scroll)
|
||||
+ {
|
||||
+ // Autre instance, ou barre qui n'est plus sur le Canvas de cette liste : on retire les onglets de l'ancienne
|
||||
+ // (plus de TabBar valide sur elle), EnsureTabs les repose sur celle-ci. Etat par instance remis a zero.
|
||||
+ const bool bOtherList = Scroll != SettingsList.Get();
|
||||
+ const bool bBarElsewhere = TabBar.IsValid() && TabBar->GetParent() != Scroll->GetParent();
|
||||
+ if (bOtherList || bBarElsewhere)
|
||||
+ {
|
||||
+ LPSettingsUi::DropTabs(GetGameInstance(), TabBar, KeyboardHost, TabLabels);
|
||||
+ bKeyboardPage = false;
|
||||
+ bControlsHardened = false;
|
||||
+ LastChildCount = -1;
|
||||
+ }
|
||||
+ SettingsList = Scroll;
|
||||
+ }
|
||||
+ const bool bOpen = Scroll && LPSettingsUi::IsOpen(Scroll);
|
||||
if (TabBar.IsValid())
|
||||
{
|
||||
@@ -582,6 +675,9 @@ void ULPSettingsSubsystem::PlaceSettingsButton()
|
||||
continue;
|
||||
}
|
||||
+ // SET1-V1 : seulement le menu a l'ecran. Une ancienne instance (retiree du viewport, pas encore collectee)
|
||||
+ // ferait poser le bouton et SourceSettings sur un widget que le joueur ne voit pas.
|
||||
const UUserWidget* MenuOwner = Box->GetTypedOuter<UUserWidget>();
|
||||
- if (!MenuOwner || MenuOwner->HasAnyFlags(RF_ClassDefaultObject) || MenuOwner->GetGameInstance() != GetGameInstance())
|
||||
+ if (!MenuOwner || MenuOwner->HasAnyFlags(RF_ClassDefaultObject) || MenuOwner->GetGameInstance() != GetGameInstance()
|
||||
+ || !LPSettingsUi::IsMenuOnScreen(MenuOwner))
|
||||
{
|
||||
continue;
|
||||
@@ -832,6 +928,10 @@ void ULPSettingsSubsystem::EnsureTabs(UScrollBox* Scroll)
|
||||
KeyboardHost = Host;
|
||||
ActiveTab = 0;
|
||||
+ bKeyboardPage = false;
|
||||
ApplyRows();
|
||||
UE_LOG(LogLifePlay, Display, TEXT("Reglages : onglets General, Audio, Video, Keyboard, Lewd, Misc"));
|
||||
+ const UUserWidget* Menu = Scroll->GetTypedOuter<UUserWidget>();
|
||||
+ UE_LOG(LogLifePlay, Display, TEXT("Reglages : onglets poses sur %s (%s)"), Menu ? *Menu->GetName() : TEXT("?"),
|
||||
+ LPSettingsUi::IsTitleMenu(Menu) ? TEXT("ecran titre") : TEXT("partie"));
|
||||
}
|
||||
```
|
||||
|
||||
## 12. Établi / estimé / incertain
|
||||
|
||||
- **Établi** : création d'une instance par ouverture et retrait par `RemoveFromParent` (`CAM-B1-PRE…:5171-5185, 5209-5213`) ; l'ancienne boucle prenait la première liste (`:498-517` avant correction) et `EnsureTabs` sortait si `TabBar` valide (`:766-769`) ; trois autres sous-systèmes ont la même boucle (§ 8) ; `IsInViewport` devient faux après `RemoveFromParent` (`Widget.cpp:895-905`, `GameViewportSubsystem.cpp:199-214`) ; compilation éditeur et jeu, 0 erreur / 0 avertissement (§ 7).
|
||||
- **Estimé** : l'ancienne instance précède la nouvelle dans l'itération de `TObjectIterator` ; la superposition vue par l'utilisateur vient du même passage ; l'instance de l'écran titre est aussi ajoutée par `AddToViewport` ; `MainMenu.TitleScreen` vaut vrai sur l'écran titre.
|
||||
- **Incertain** (essai qui trancherait : V1 à V10, § 5) : comportement réel en jeu des trois scénarios ; absence d'`ensure` Slate au changement de page du clavier ; incidence de l'écart E5.
|
||||
|
||||
Tours : 45 / 60 (déclaré par l'agent ; `Tools/FicheStats.py` fait foi)
|
||||
|
||||
## Constats
|
||||
|
||||
- La fiche annonce `LPSettingsSubsystem.cpp:~498-561` et `:516` pour le `Tick` : exacts avant ma modification, ils bougent après (le `Tick` commence à la ligne 592).
|
||||
- `Tools\FileCheck.ps1 Source/LifePlay/LPSettingsSubsystem.cpp -Lot SET1` (chemin relatif à barres obliques) répond `Contenu = pas sauvegarde` alors que le manifeste contient le fichier ; `-Lot SET1` sans chemin répond `Sauv = CRLF -`, `Contenu = modifie`. Cause non cherchée (estimé : séparateurs de chemin). À verser : `Tools\LISEZMOI.md`, ligne `FileCheck.ps1` : utiliser `-Lot` sans `-Path` pour comparer à l'instantané.
|
||||
- `rg` n'est pas appelable derrière `timeout` dans ce Git Bash (« failed to run command 'rg' ») : appel direct seulement.
|
||||
397
Docs/Migration/etat/REL/SET1/SET1-V1b-IMPL.md
Normal file
397
Docs/Migration/etat/REL/SET1/SET1-V1b-IMPL.md
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
Fiche SET1-V1b — Niveau N2 — Modèle prévu Sonnet (fiche) | utilisé claude-sonnet-5-5 — Agent lp-impl — Skills sk-protocol, ue-cpp-build (préchargés en plus : lp-build, lp-ue-compat)
|
||||
# SET1-V1b-IMPL : les lignes Couleur, Video et Mods se posent sur l'instance de MainMenu qui est à l'écran (2026-10-20)
|
||||
|
||||
Hors gabarit : la fiche demande, après les rubriques IMPL 1 à 6, la compilation, le diff, les MD5, les journaux et la preuve attendue en jeu (sections 7 à 12). Suite directe de `SET1-V1-IMPL.md` (§ 0 et § 8). Contenu adulte (doc 27) : noms techniques de widgets seulement.
|
||||
|
||||
Résultat : **réussi à la compilation** (éditeur et jeu : code 0, 0 erreur, 0 avertissement) ; **non éprouvé en jeu** (la preuve en jeu revient à la VAL, § 10). Les trois sous-systèmes choisissent maintenant la même liste que les onglets ; aucun état par instance à remettre à zéro n'a été trouvé chez eux (§ 2, constat C1).
|
||||
|
||||
## 1. Fichiers modifiés
|
||||
|
||||
| Fichier | Lignes (après modification) | Contenu |
|
||||
|---|---|---|
|
||||
| `Source/LifePlay/LPSettingsSubsystem.h` | 17 | `class UGameInstance;` (déclaration avancée) |
|
||||
| idem | 50-55 | `static UScrollBox* FindOnScreenSettingsList(const UGameInstance* GI, const UScrollBox* Current = nullptr);` publique, avec son commentaire |
|
||||
| `Source/LifePlay/LPSettingsSubsystem.cpp` | 592-596 | `ULPSettingsSubsystem::FindOnScreenSettingsList` : une ligne, renvoie `LPSettingsUi::FindOnScreenSettingsList(GI, Current)` (la fonction du `namespace LPSettingsUi`, `:122-146`, n'est pas touchée ; le `Tick` des onglets l'appelle comme avant) |
|
||||
| `Source/LifePlay/LPColorGradeSubsystem.cpp` | 18 | `#include "LPSettingsSubsystem.h"` |
|
||||
| idem | 260-264 | `EnsureControls` (commence l. 258) : la boucle « première `SettingsScrollBox` + `break` » (ancien 259-274) est remplacée par `ULPSettingsSubsystem::FindOnScreenSettingsList(GetGameInstance())` |
|
||||
| idem | 313-314 | nouvelle ligne de journal `Couleur : reglages de couleur ajoutes sur <MainMenu_C_n>` (fin d'`EnsureControls`) |
|
||||
| `Source/LifePlay/LPVideoQualitySubsystem.cpp` | 20 | `#include "LPSettingsSubsystem.h"` |
|
||||
| idem | 463-467 | `EnsureControls` (commence l. 461) : même remplacement (ancien 462-477) |
|
||||
| idem | 594-595 | journal `Video : controles ajoutes avant les reglages de couleur (sur <MainMenu_C_n>)` |
|
||||
| `Source/LifePlay/LPModInfoSubsystem.cpp` | 21 | `#include "LPSettingsSubsystem.h"` |
|
||||
| idem | 243-246 | `EnsureSettingsRows` (commence l. 241) : même remplacement (ancien 242-257) |
|
||||
| idem | 302-305 | journal `Modules : cases de controle des mods ajoutees a Settings > Misc (moteur …, version min …, version max …) sur <MainMenu_C_n>` |
|
||||
|
||||
Les numéros de ligne « après » ont été relevés par `grep -n` sur les fichiers actuels (après les builds).
|
||||
|
||||
Total (`diff -u --strip-trailing-cr` contre l'instantané, lignes `+` / `-` hors en-têtes ; § 11) : 5 fichiers, +38 / −51. Par fichier : `LPSettingsSubsystem.h` +8 / −0, `LPSettingsSubsystem.cpp` +6 / −0, `LPColorGradeSubsystem.cpp` +8 / −16, `LPVideoQualitySubsystem.cpp` +8 / −17, `LPModInfoSubsystem.cpp` +8 / −18. Fins de ligne conservées (§ 9) : CRLF pour quatre fichiers, LF pour `LPModInfoSubsystem.cpp` (le fichier est LF dans l'index, `git ls-files --eol`).
|
||||
|
||||
`LPKeyboardSubsystem.cpp` : non touché (consigne), MD5 `611c21489d80374a4817f70e408cf4db` avant et après.
|
||||
|
||||
API moteur utilisée, lue dans `D:\Game\Launcher\Engine\UE_5.8\Engine\Source` (5.8.3). Le lot n'ajoute aucune API moteur nouvelle par rapport à SET1-V1 (§ 1 de `SET1-V1-IMPL.md`) ; les seules lignes neuves s'appuient sur :
|
||||
|
||||
| API | Source |
|
||||
|---|---|
|
||||
| `UGameInstanceSubsystem::GetGameInstance() const` renvoie `UGameInstance*` (paramètre `const UGameInstance*` de la nouvelle fonction : conversion vers `const`) | `Runtime/Engine/Public/Subsystems/GameInstanceSubsystem.h:25` |
|
||||
| `class UGameInstance;` déjà déclarée par `GameInstanceSubsystem.h` (la redéclaration dans notre `.h` est sans effet) | `GameInstanceSubsystem.h:9` |
|
||||
| `UObject::GetTypedOuter<T>() const` (pour le nom du `MainMenu` dans les journaux) | `Runtime/CoreUObject/Public/UObject/UObjectBaseUtility.h:551-553` |
|
||||
|
||||
## 2. Écarts à la SPEC / à la fiche
|
||||
|
||||
| # | Écart | Motif |
|
||||
|---|---|---|
|
||||
| E1 | Le journal de Video et celui de Mods changent de texte (suffixe `(sur <nom>)` / `sur <nom>`), et le Color reçoit une ligne neuve. La fiche demande que « les lignes de journal de chaque sous-système visent l'instance à l'écran ». | Sans nom d'instance, aucune ligne ne prouve sur quelle liste les lignes ont été posées. Le début du texte est conservé, donc une recherche par préfixe trouve toujours les lignes : `VQ2-VAL.md:62` et `VQ2-SPEC.md:302` citent `Video : controles ajoutes avant les reglages de couleur` ; `U7-T7-IMPL.md:221` cite la ligne Mods **entière**, qui se terminait par `)` : une comparaison exacte avec cette trace ancienne échouerait. |
|
||||
| E2 | `Tick` des onglets inchangé : il appelle toujours la fonction du `namespace LPSettingsUi`, pas la fonction statique. | « Sans changer son comportement » : la statique est un renvoi d'une ligne vers la même fonction, aucun risque de divergence. |
|
||||
| E3 | Les trois appelants passent `Current` = nul (valeur par défaut) ; `Tick` des onglets passe `SettingsList`. | Ils ne suivent aucune liste. Conséquence : à égalité de score (deux instances à l'écran, aucune liste ouverte) ils prennent la première trouvée, les onglets la liste déjà suivie. Cas non rencontré (une seule instance à l'écran à la fois d'après `SET1-V1-IMPL.md` § 0), sans effet visible : dès qu'une liste est ouverte (score 2), les quatre sous-systèmes la choisissent. |
|
||||
| E4 | `LPSettingsSubsystem.h` est modifié (V1 : « `.h` non modifié »). | Exigé par la fiche (fonction statique publique déclarée dans le `.h`). |
|
||||
| E5 | Aucune remise à zéro d'état par instance n'a été ajoutée dans Color, Video et Mods (la fiche : « corrige au minimum »). | Constat C1 ci-dessous : leur « état » est lu sur les enfants de la liste choisie, donc par instance de fait. |
|
||||
| E6 | `CopieEtat.ps1 -Lot SET1` rend `ALERTE GIT` (code 1), 7 fichiers. | Deux sont **antérieurs** à ce travail (`LPCameraModeSubsystem.cpp`, `LPDirectControlSubsystem.cpp`, statut git de départ de la session) ; `LPSettingsSubsystem.cpp` porte aussi les changements de SET1-V1, non commités ; les quatre autres sont les fichiers de ce lot, non déclarés par `-Assets` (aucun asset). |
|
||||
|
||||
**Constat C1 — état par instance (lecture, non observé en jeu).** Pour chacun des trois sous-systèmes, ce qui décide « les lignes sont-elles déjà là ? » est lu sur la liste choisie, jamais mémorisé dans un indicateur :
|
||||
- Color : présence d'un enfant `LPColorBrightness` (`LPColorGradeSubsystem.cpp:273`, boucle sur `Scroll->GetChildrenCount()`). Les cinq afficheurs de valeur `BrightnessValue`…`TintValue` sont des `TWeakObjectPtr<UTextBlock>` (`LPColorGradeSubsystem.h:53-57`) réaffectés par `AddRow` (`LPColorGradeSubsystem.cpp:235-254`, test sur le nom de la ligne) puis remplis (`:293-312`). Aucun indicateur booléen.
|
||||
- Video : présence d'un enfant `LPVideoOverall` (`LPVideoQualitySubsystem.cpp:477`). `Rows[]` (`.h:104`) et `RecommendedButton` (`.h:105`) sont réaffectés par `AddRow` (`:426-427`) et `MakeRecommendedRow` (`:457`) ; `RefreshWidgets()` (`:591`) et `ApplyToScalability()` (`:593`) rejouent les valeurs sur les curseurs neufs. `Levels` et `bConfigured` sont globaux par conception (choix du joueur), pas par instance.
|
||||
- Mods : présence d'un enfant `LPModCheckEngine` (`LPModInfoSubsystem.cpp:254`, `RowNames[0]`) ; aucune variable membre liée à la liste des réglages (`ManagerList` et `bManagerListLogged`, `.h:75-76`, concernent le gestionnaire de mods, autre widget, déjà filtré par `IsInViewport` à `TickModManager`).
|
||||
Avec la bonne liste, une nouvelle instance n'a pas ces enfants : les lignes sont recréées à la première image où l'instance est à l'écran ; l'ancienne instance n'est plus regardée. Les noms `LPColor*` / `LPVideo*` / `LPModCheck*` sont classés par `LPSettingsUi::CategoryOf` (`LPSettingsSubsystem.cpp:267-275` : Video, Video, Misc) et `ApplyRows` est rejoué à chaque image où la liste est ouverte, donc une ligne ajoutée plus tard entre dans son onglet à l'image suivante.
|
||||
|
||||
**Constat C2 — délai.** Les lignes sont posées par des tickers à 0,5 s (`LPColorGradeSubsystem.cpp:77`, `LPVideoQualitySubsystem.cpp:160`, `LPModInfoSubsystem.cpp:150`), alors que `LPSettingsSubsystem` tourne à chaque image (`:583`, période 0). Entre l'apparition d'une instance à l'écran et ses lignes, il peut s'écouler jusqu'à ≈ 0,5 s ; un clic sur Settings dans cet intervalle montrerait les onglets Video et Misc incomplets quelques images (puis complétés). Estimé, non mesuré ; périodes non modifiées (hors fiche).
|
||||
|
||||
**Constat C3 — le défaut de V1 §8 est bien celui-ci.** Les trois boucles supprimées étaient les mêmes (`TObjectIterator<UScrollBox>`, nom `SettingsScrollBox`, même `GameInstance`, `break` à la première) : `git diff`/`diff -u` du § 11, lignes `-`.
|
||||
|
||||
## 3. Instantané
|
||||
|
||||
`D:\Game\LifePlay_Backup_5.5\SET1-V1b\` (fait par l'orchestrateur), `manifest.csv` relu : 5 fichiers, MD5 de départ **tous égaux** au manifeste avant écriture (relevé de session, § 9).
|
||||
|
||||
| Fichier (dans `Source\LifePlay\`) | Octets | MD5 du manifeste |
|
||||
|---|---|---|
|
||||
| `LPSettingsSubsystem.cpp` | 33904 | `3591F579D88C4CA3A44468C750C9A24E` |
|
||||
| `LPSettingsSubsystem.h` | 1792 | `0F98C05568AE789C5C0B78F6EC580503` |
|
||||
| `LPColorGradeSubsystem.cpp` | 12464 | `F818C7F56DA018ED97683F01717A9AFB` |
|
||||
| `LPVideoQualitySubsystem.cpp` | 19408 | `DFF29F3F1B976979E556501CEBBF2613` |
|
||||
| `LPModInfoSubsystem.cpp` | 16572 | `1D0FFF7D4327C493903F180868D00BDE` |
|
||||
|
||||
Retour arrière (proposé, non lancé) : `Tools\Restore.ps1 -Lot SET1-V1b`. Attention : `LPSettingsSubsystem.cpp` y revient à l'état **de fin de SET1-V1** (qui contient le travail de V1, non commité), pas à HEAD.
|
||||
|
||||
## 4. Ce qui n'a pas été fait
|
||||
|
||||
- Aucun essai en jeu (la fiche n'en confie pas) ; aucun éditeur ni jeu lancé.
|
||||
- `LPKeyboardSubsystem.cpp` non touché (consigne). `LPReadableTextSubsystem.cpp`, `LPCameraModeSubsystem.cpp`, `LPDirectControlSubsystem.cpp` non ouverts.
|
||||
- Pas de changement des périodes des tickers (C2), du `Tick` des onglets, de `PlaceSettingsButton`, d'un Blueprint ni du GI.
|
||||
- Pas de test automatique (aucun existant pour ces sous-systèmes). Pas de build empaqueté.
|
||||
- Aucune autre boucle `SettingsScrollBox` à reprendre : `Grep "SettingsScrollBox"` sur `Source` ne trouve plus que `LPSettingsSubsystem.cpp:129` (la fonction partagée), `LPKeyboardSubsystem.cpp:854` (hors consigne, indicateur de journal sans `break`), `LPReadableTextSubsystem.cpp:125` (remontée de parents) et des commentaires.
|
||||
|
||||
## 5. Points à confirmer en VAL (un par ligne)
|
||||
|
||||
1. W1 : en partie (Échap, Settings), première ouverture : l'onglet Video montre Overall Quality, Shadows, Textures, Effects, Anti-Aliasing, Recommended (`LPVideo*`) puis Brightness, Saturation, Contrast, White Balance, Tint (`LPColor*`) ; l'onglet Misc montre les trois cases de contrôle des mods (`LPModCheck*`) ; le tout dès l'ouverture, sans attendre la collecte d'une ancienne instance (≈ 30 s).
|
||||
2. W2 : deuxième et troisième ouverture en partie (nouvelle instance à chaque fois) : mêmes contenus Video et Misc dès l'ouverture ; pour chaque instance trois lignes de journal portant le **même** `MainMenu_C_<n>` que `Reglages : onglets poses sur MainMenu_C_<n> (partie)` : `Couleur : reglages de couleur ajoutes sur …`, `Video : controles ajoutes avant les reglages de couleur (sur …)`, `Modules : cases de controle des mods ajoutees a Settings > Misc (…) sur …`.
|
||||
3. W3 : écran titre, premier lancement, ouvrir Settings : mêmes contenus et mêmes trois lignes, `<n>` identique à celui de `onglets poses sur … (ecran titre)`. Symptôme du risque V6 de SET1-V1 (`IsInViewport()` faux pour l'instance du titre) : aucune des trois lignes et aucun `onglets poses` au titre ; ce lot l'aggraverait pour Video/Mods/Couleur, qui l'avaient avant (première liste trouvée, sans filtre d'écran).
|
||||
4. W4 : retour au titre puis réouverture : mêmes contenus et trois lignes avec un `<n>` différent de celui du premier titre.
|
||||
5. W5 : valeurs sur l'instance neuve : le curseur Overall et les quatre curseurs de Video affichent le niveau en cours (`RefreshWidgets`, pas la valeur par défaut) ; les cinq afficheurs de Couleur affichent les valeurs en cours (réaffectation des `TWeakObjectPtr`) ; un curseur déplacé sur l'instance neuve met bien à jour son afficheur (pas l'ancien).
|
||||
6. W6 : pas de doublon : une seule ligne de journal par sous-système et par instance ; les noms `LPColorBrightness`, `LPVideoOverall`, `LPModCheckEngine` présents une fois dans la liste de l'instance à l'écran.
|
||||
7. W7 : délai (C2) : mesurer, dans `LifePlay.log`, l'écart entre `Reglages : onglets poses sur …` et les trois lignes de la même instance ; attendu ≤ ≈ 0,5 s ; une ouverture de Settings dans cet intervalle ne doit rien casser.
|
||||
8. W8 : ouverture répétée sur la même instance (ouvrir, Back, rouvrir) : aucune nouvelle ligne `Couleur`/`Video`/`Modules` (présence déjà vue), onglet Video inchangé.
|
||||
9. W9 : reprise de V8 de `SET1-V1-IMPL.md` § 5 (onglets Video et Misc de l'instance de partie complets) : à juger sur W1 à W3 ; V1 à V10 de SET1-V1 restent à rejouer comme prévu.
|
||||
|
||||
## 6. Fichiers à commiter
|
||||
|
||||
Dépôt du jeu, branche `ue5.8` :
|
||||
M `Source/LifePlay/LPSettingsSubsystem.h`
|
||||
M `Source/LifePlay/LPSettingsSubsystem.cpp` (contient aussi le travail de SET1-V1, non commité à la date de cette fiche)
|
||||
M `Source/LifePlay/LPColorGradeSubsystem.cpp`
|
||||
M `Source/LifePlay/LPVideoQualitySubsystem.cpp`
|
||||
M `Source/LifePlay/LPModInfoSubsystem.cpp`
|
||||
A `Docs/Migration/etat/REL/SET1/SET1-V1b-IMPL.md`
|
||||
A `Docs/Migration/etat/REL/SET1/SET1_Build_20261020-213520.txt` (résumé `Build.ps1` éditeur)
|
||||
A `Docs/Migration/etat/REL/SET1/SET1_Build_20261020-213620.txt` (résumé `Build.ps1` jeu)
|
||||
A `Docs/Migration/etat/REL/SET1/SET1-V1b_CopieEtat_avant_build.json`, `SET1-V1b_CopieEtat_apres_build.json` (traces `CopieEtat.ps1`)
|
||||
|
||||
Hors lot, déjà modifiés avant ce travail, **à ne pas embarquer** : `Source/LifePlay/LPCameraModeSubsystem.cpp`, `Source/LifePlay/LPDirectControlSubsystem.cpp`.
|
||||
|
||||
## 7. Compilation
|
||||
|
||||
Éditeur fermé et rien ne tournait avant (`UeState` : `processus=0 editeur=0 compilation=0 shaders=0 jeu=0`, code 0). Les deux builds ont été lancés à la suite, l'éditeur d'abord, le jeu seulement après un code 0.
|
||||
|
||||
| | LifePlayEditor Win64 Development | LifePlay Win64 Development `-NoUBA` |
|
||||
|---|---|---|
|
||||
| Commande | `pwsh -NoProfile -Command "& 'D:/Game/LifePlay-master 5.8/Tools/Build.ps1' -Lot SET1 -EtatDir 'D:/Game/LifePlay-master 5.8/Docs/Migration/etat/REL/SET1'"` | idem + `-Target LifePlay -Config Development -ExtraArgs '-NoUBA'` |
|
||||
| Code de sortie | 0 | 0 |
|
||||
| Durée | 59 s | 59 s |
|
||||
| Erreurs / avertissements du compilateur | 0 / 0 | 0 / 0 |
|
||||
| Autres lignes (UBT, UHT, liens) | 20 (les 20 lignes `Plugin 'HyperAIStudio' does not list plugin …` connues, `lp-build` § 7 : attendu 20 pour l'éditeur) | 0 (attendu 0 pour la cible jeu) |
|
||||
| Unités compilées | 5 : `LPColorGradeSubsystem.cpp`, `LPModInfoSubsystem.cpp`, `LPSettingsSubsystem.cpp`, `LPVideoQualitySubsystem.cpp`, `Module.LifePlay.cpp` | les mêmes 5, marquées `[NoUba]` |
|
||||
| Liaison | `[6/8] Link [x64] UnrealEditor-LifePlay.dll` (DLL liées : 1) | `[6/7] Link [x64] LifePlay.exe [NoUba]`, `Output binary: D:\Game\LifePlay-master 5.8\Binaries\Win64\LifePlay.exe`, `Result: Succeeded` (journal `:26, :31, :33`) ; le résumé compte « DLL liées : 0 » car le jeu lie un `.exe` |
|
||||
| Toolchain | `Using Visual Studio 14.50.35739 toolchain (C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.50.35717)` = MSVC épinglé de la 5.8 | idem |
|
||||
| Résumé | `Docs\Migration\etat\REL\SET1\SET1_Build_20261020-213520.txt` | `Docs\Migration\etat\REL\SET1\SET1_Build_20261020-213620.txt` |
|
||||
| Journal | `Saved\Logs\portage\SET1_Build_20261020-213520.log` | `Saved\Logs\portage\SET1_Build_20261020-213620.log` |
|
||||
|
||||
Sorties brutes de `Build.ps1` (dernières lignes de chaque build) :
|
||||
```
|
||||
code=0 duree=59s erreurs=0 avertissements=0 autres=20 unites=5
|
||||
code=0 duree=59s erreurs=0 avertissements=0 autres=0 unites=5
|
||||
```
|
||||
Dates des binaires (`ls -l --time-style=full-iso`) : `UnrealEditor-LifePlay.dll` 2026-10-20 21:36:18, `LifePlay.exe` 2026-10-20 21:37:17 (postérieurs aux écritures du § 11). Limites : la ligne `Makefile` des deux résumés est vide (comme en V1) ; le module modifié figure bien dans les unités compilées. Aucune ligne de journal propre au nouveau code n'existe avant un lancement du jeu (§ 10).
|
||||
|
||||
## 8. Les quatre autres sous-systèmes (point 3 de la fiche)
|
||||
|
||||
`LPKeyboardSubsystem.cpp` : non modifié, MD5 `611c21489d80374a4817f70e408cf4db` identique avant et après (`md5sum`, § 9). Aucun défaut de choix d'instance d'après `SET1-V1-IMPL.md` § 8 (boucle sans `break`, ne sert qu'à un indicateur pour un journal). Trois sous-systèmes corrigés : Color, Video, Mods (§ 1). `LPReadableTextSubsystem` : sans objet (aucun choix d'instance).
|
||||
|
||||
## 9. MD5 et fins de ligne
|
||||
|
||||
Commande : `md5sum Source/LifePlay/LPSettingsSubsystem.cpp Source/LifePlay/LPSettingsSubsystem.h Source/LifePlay/LPColorGradeSubsystem.cpp Source/LifePlay/LPVideoQualitySubsystem.cpp Source/LifePlay/LPModInfoSubsystem.cpp Source/LifePlay/LPKeyboardSubsystem.cpp` (après modification et après les builds, identique aux deux relevés) :
|
||||
```
|
||||
6277a8fc139c05dc10e302f88de0f8d9 *Source/LifePlay/LPSettingsSubsystem.cpp
|
||||
138350efe8473c430db984db63c8feac *Source/LifePlay/LPSettingsSubsystem.h
|
||||
5be400543166b6de7a4a88f6097a9d93 *Source/LifePlay/LPColorGradeSubsystem.cpp
|
||||
c3055197030bdbbce813df4cc6d7cd63 *Source/LifePlay/LPVideoQualitySubsystem.cpp
|
||||
98206e688308e908b04ae15cf408e1bb *Source/LifePlay/LPModInfoSubsystem.cpp
|
||||
611c21489d80374a4817f70e408cf4db *Source/LifePlay/LPKeyboardSubsystem.cpp
|
||||
```
|
||||
|
||||
| Fichier | MD5 avant (relu avant d'écrire, = manifeste) | MD5 après |
|
||||
|---|---|---|
|
||||
| `LPSettingsSubsystem.cpp` | `3591f579d88c4ca3a44468c750c9a24e` | `6277a8fc139c05dc10e302f88de0f8d9` |
|
||||
| `LPSettingsSubsystem.h` | `0f98c05568ae789c5c0b78f6ec580503` | `138350efe8473c430db984db63c8feac` |
|
||||
| `LPColorGradeSubsystem.cpp` | `f818c7f56da018ed97683f01717a9afb` | `5be400543166b6de7a4a88f6097a9d93` |
|
||||
| `LPVideoQualitySubsystem.cpp` | `dff29f3f1b976979e556501cebbf2613` | `c3055197030bdbbce813df4cc6d7cd63` |
|
||||
| `LPModInfoSubsystem.cpp` | `1d0fff7d4327c493903f180868d00bde` | `98206e688308e908b04ae15cf408e1bb` |
|
||||
| `LPKeyboardSubsystem.cpp` (non touché) | `611c21489d80374a4817f70e408cf4db` | idem |
|
||||
|
||||
`git ls-files --eol` sur les cinq fichiers modifiés, puis comptes `tr -cd '\r' | wc -c` et `tr -cd '\n' | wc -c` :
|
||||
```
|
||||
i/crlf w/crlf attr/-text Source/LifePlay/LPColorGradeSubsystem.cpp (CR=370 LF=370)
|
||||
i/lf w/lf attr/-text Source/LifePlay/LPModInfoSubsystem.cpp (CR=0 LF=432)
|
||||
i/crlf w/crlf attr/-text Source/LifePlay/LPSettingsSubsystem.cpp (CR=1002 LF=1002)
|
||||
i/crlf w/crlf attr/-text Source/LifePlay/LPSettingsSubsystem.h (CR=76 LF=76)
|
||||
i/crlf w/crlf attr/-text Source/LifePlay/LPVideoQualitySubsystem.cpp (CR=596 LF=596)
|
||||
```
|
||||
|
||||
`pwsh -NoProfile -File Tools/FileCheck.ps1 -Lot SET1-V1b` (le lot de l'instantané donne le manifeste des 5 fichiers) :
|
||||
```
|
||||
Fichiers CRLF LF CR BOM : fichiers=5 CRLF=4 LF=1 alertes=0 introuvables=0
|
||||
contenu : modifie=5
|
||||
```
|
||||
(détail par fichier : CRLF 370 / LF 432 / CRLF 1002 / CRLF 76 / CRLF 596, `Sauv` = fins de ligne de l'instantané identiques, aucune alerte.)
|
||||
|
||||
`pwsh -NoProfile -File Tools/PubCheck.ps1 -Fichiers <chemin relatif> -Depot "D:/Game/LifePlay-master 5.8"` (stdin sur `/dev/null`, un fichier par appel) : `PubCheck : 0 constat(s)`, code 0, pour chacun des cinq fichiers source. Pour ce livrable : voir la fin de la section 12.
|
||||
|
||||
`pwsh -NoProfile -File Tools/CopieEtat.ps1 -Lot SET1 -Sortie …` avant et après les builds : `COPIE ALERTE lot=SET1 … proc=0 assets=0 absents=0 modifies=0 git=7/0/0 hors_declares=7 parasites=0 … alertes=GIT`, code 1 dans les deux cas (voir E6). Traces : `SET1-V1b_CopieEtat_avant_build.json`, `SET1-V1b_CopieEtat_apres_build.json`.
|
||||
|
||||
Fin de lot : `pwsh -NoProfile -File Tools/UeState.ps1 < /dev/null` → `processus=0 editeur=0 compilation=0 shaders=0 jeu=0`, code 0. **Jeton UE rendu.**
|
||||
|
||||
## 10. Journaux et preuve attendue en jeu
|
||||
|
||||
Lignes de journal (préfixe `LogLifePlay: ` dans `LifePlay.log`) :
|
||||
|
||||
| Ligne | Origine | Quand |
|
||||
|---|---|---|
|
||||
| `Reglages : onglets poses sur <MainMenu_C_n> (ecran titre|partie)` | SET1-V1 (`LPSettingsSubsystem.cpp`, fin d'`EnsureTabs`) | création d'une barre sur une instance |
|
||||
| `Couleur : reglages de couleur ajoutes sur <MainMenu_C_n>` | **nouvelle** (`LPColorGradeSubsystem.cpp:313-314`, texte à la ligne 314) | les 5 lignes `LPColor*` viennent d'être ajoutées à la liste de cette instance |
|
||||
| `Video : controles ajoutes avant les reglages de couleur (sur <MainMenu_C_n>)` | existante, suffixe **nouveau** (`LPVideoQualitySubsystem.cpp:594-595`) | les lignes `LPVideo*` et Recommended viennent d'être ajoutées |
|
||||
| `Modules : cases de controle des mods ajoutees a Settings > Misc (moteur a, version min b, version max c) sur <MainMenu_C_n>` | existante, suffixe **nouveau** (`LPModInfoSubsystem.cpp:302-305`) | les 3 cases `LPModCheck*` viennent d'être ajoutées |
|
||||
|
||||
Recette de lecture pour la VAL : `pwsh -NoProfile -File Tools/LogStats.ps1 -Log <LifePlay.log> -Pattern 'onglets (poses|retires)|reglages de couleur ajoutes sur|controles ajoutes avant|cases de controle des mods' -Max 60` (un seul motif à alternatives : `pwsh -File` refuse une liste ; journal de la session, pas de compte refait de mémoire). Rapprocher ensuite les noms `MainMenu_C_<n>` des quatre familles de lignes.
|
||||
|
||||
Preuve attendue, à rejouer par la VAL sur un build Development :
|
||||
|
||||
| Scénario | Attendu à l'écran | Attendu au journal |
|
||||
|---|---|---|
|
||||
| Partie : Échap, Settings, première ouverture | onglets Video et Misc complets dès l'ouverture (W1) | `onglets poses sur MainMenu_C_n (partie)` puis, avec le même `n`, les trois lignes Couleur, Video, Modules (ordre libre) |
|
||||
| Partie : deuxième, troisième ouverture | idem, sans attendre ≈ 30 s (W2) | `onglets retires de <ancienne>` si une barre existait ; un `n` nouveau à chaque ouverture, repris par les quatre lignes |
|
||||
| Écran titre, puis retour au titre | idem (W3, W4) | `(ecran titre)` ; un `n` différent au second titre, repris par les trois lignes |
|
||||
| Même instance rouverte | aucun changement (W8) | aucune nouvelle ligne Couleur, Video, Modules |
|
||||
|
||||
Limite : la présence d'une ligne `sur <n>` ne prouve que la liste choisie ; ce que le joueur voit (contenu des onglets) se juge à l'écran. Ni `IsInViewport()` sur l'instance du titre, ni l'ordre réel d'itération de `TObjectIterator`, ni le délai du ticker à 0,5 s ne sont observés ; établis par lecture seulement.
|
||||
|
||||
## 11. Diff (`diff -u --strip-trailing-cr` entre l'instantané `D:/Game/LifePlay_Backup_5.5/SET1-V1b/Source/LifePlay/` et `Source/LifePlay/`)
|
||||
|
||||
```diff
|
||||
=== LPSettingsSubsystem.h
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
class UButton;
|
||||
class UCanvasPanel;
|
||||
+class UGameInstance;
|
||||
class UHorizontalBox;
|
||||
class UNativeWidgetHost;
|
||||
class UScrollBox;
|
||||
@@ -46,6 +47,13 @@
|
||||
UFUNCTION()
|
||||
void OpenSettings();
|
||||
|
||||
+ // Lot SET1-V1b. Liste des reglages (MainMenu.SettingsScrollBox) de l'instance de MainMenu qui est a l'ecran, nulle s'il
|
||||
+ // n'y en a aucune. Partagee avec les sous-systemes qui ajoutent des lignes a cette liste (couleur, video, controle des
|
||||
+ // mods) : une ancienne instance, retiree du viewport et pas encore collectee, garde sa liste en memoire et ne doit pas
|
||||
+ // recevoir leurs lignes a la place de l'instance affichee. Current : liste deja suivie par l'appelant, elle departage
|
||||
+ // deux listes a l'ecran ; peut etre nulle.
|
||||
+ static UScrollBox* FindOnScreenSettingsList(const UGameInstance* GI, const UScrollBox* Current = nullptr);
|
||||
+
|
||||
private:
|
||||
bool Tick(float DeltaTime);
|
||||
void PlaceSettingsButton();
|
||||
=== LPSettingsSubsystem.cpp
|
||||
@@ -589,6 +589,12 @@
|
||||
Super::Deinitialize();
|
||||
}
|
||||
|
||||
+UScrollBox* ULPSettingsSubsystem::FindOnScreenSettingsList(const UGameInstance* GI, const UScrollBox* Current)
|
||||
+{
|
||||
+ // SET1-V1b : meme choix que le Tick des onglets (LPSettingsUi::FindOnScreenSettingsList), expose aux autres sous-systemes.
|
||||
+ return LPSettingsUi::FindOnScreenSettingsList(GI, Current);
|
||||
+}
|
||||
+
|
||||
bool ULPSettingsSubsystem::Tick(float DeltaTime)
|
||||
{
|
||||
(void)DeltaTime;
|
||||
=== LPColorGradeSubsystem.cpp
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "Engine/PostProcessVolume.h"
|
||||
#include "Engine/World.h"
|
||||
#include "LifePlay.h"
|
||||
+#include "LPSettingsSubsystem.h"
|
||||
#include "Misc/ConfigCacheIni.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "Styling/CoreStyle.h"
|
||||
@@ -256,22 +257,11 @@
|
||||
|
||||
void ULPColorGradeSubsystem::EnsureControls()
|
||||
{
|
||||
- UScrollBox* Scroll = nullptr;
|
||||
- for (TObjectIterator<UScrollBox> It; It; ++It)
|
||||
- {
|
||||
- UScrollBox* Candidate = *It;
|
||||
- if (!Candidate || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
|
||||
- {
|
||||
- continue;
|
||||
- }
|
||||
- const UUserWidget* Owner = Candidate->GetTypedOuter<UUserWidget>();
|
||||
- if (!Owner || Owner->HasAnyFlags(RF_ClassDefaultObject) || Owner->GetGameInstance() != GetGameInstance())
|
||||
- {
|
||||
- continue;
|
||||
- }
|
||||
- Scroll = Candidate;
|
||||
- break;
|
||||
- }
|
||||
+ // SET1-V1b : la liste de l'instance de MainMenu qui est a l'ecran, pas la premiere trouvee (une ancienne instance,
|
||||
+ // retiree du viewport et pas encore collectee, vient souvent avant). Aucune a l'ecran : rien a faire. Pas d'etat par
|
||||
+ // instance a remettre a zero : la presence de LPColorBrightness se lit sur les enfants de la liste choisie, et AddRow
|
||||
+ // rebranche les afficheurs de valeur (BrightnessValue...) sur les lignes de cette liste.
|
||||
+ UScrollBox* Scroll = ULPSettingsSubsystem::FindOnScreenSettingsList(GetGameInstance());
|
||||
if (!Scroll)
|
||||
{
|
||||
return;
|
||||
@@ -320,6 +310,8 @@
|
||||
{
|
||||
Readout->SetText(FText::FromString(LPColorGrade::FormatValue(Tint, 2)));
|
||||
}
|
||||
+ const UUserWidget* Menu = Scroll->GetTypedOuter<UUserWidget>();
|
||||
+ UE_LOG(LogLifePlay, Display, TEXT("Couleur : reglages de couleur ajoutes sur %s"), Menu ? *Menu->GetName() : TEXT("?"));
|
||||
}
|
||||
|
||||
void ULPColorGradeSubsystem::OnBrightnessChanged(float Value)
|
||||
=== LPVideoQualitySubsystem.cpp
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "Engine/World.h"
|
||||
#include "HAL/IConsoleManager.h"
|
||||
#include "LifePlay.h"
|
||||
+#include "LPSettingsSubsystem.h"
|
||||
#include "Misc/ConfigCacheIni.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "DynamicRHI.h"
|
||||
@@ -459,22 +460,11 @@
|
||||
|
||||
void ULPVideoQualitySubsystem::EnsureControls()
|
||||
{
|
||||
- UScrollBox* Scroll = nullptr;
|
||||
- for (TObjectIterator<UScrollBox> It; It; ++It)
|
||||
- {
|
||||
- UScrollBox* Candidate = *It;
|
||||
- if (!Candidate || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
|
||||
- {
|
||||
- continue;
|
||||
- }
|
||||
- const UUserWidget* Owner = Candidate->GetTypedOuter<UUserWidget>();
|
||||
- if (!Owner || Owner->HasAnyFlags(RF_ClassDefaultObject) || Owner->GetGameInstance() != GetGameInstance())
|
||||
- {
|
||||
- continue;
|
||||
- }
|
||||
- Scroll = Candidate;
|
||||
- break;
|
||||
- }
|
||||
+ // SET1-V1b : la liste de l'instance de MainMenu qui est a l'ecran, pas la premiere trouvee (une ancienne instance,
|
||||
+ // retiree du viewport et pas encore collectee, vient souvent avant). Aucune a l'ecran : rien a faire. Pas d'etat par
|
||||
+ // instance a remettre a zero : la presence de LPVideoOverall se lit sur les enfants de la liste choisie, et AddRow /
|
||||
+ // MakeRecommendedRow rebranchent Rows et RecommendedButton sur les lignes de cette liste.
|
||||
+ UScrollBox* Scroll = ULPSettingsSubsystem::FindOnScreenSettingsList(GetGameInstance());
|
||||
if (!Scroll)
|
||||
{
|
||||
return;
|
||||
@@ -601,5 +591,6 @@
|
||||
RefreshWidgets();
|
||||
// Nouvelle instance du menu : le Blueprint a pu reappliquer ses propres valeurs.
|
||||
ApplyToScalability();
|
||||
- UE_LOG(LogLifePlay, Display, TEXT("Video : controles ajoutes avant les reglages de couleur"));
|
||||
+ const UUserWidget* Menu = Scroll->GetTypedOuter<UUserWidget>();
|
||||
+ UE_LOG(LogLifePlay, Display, TEXT("Video : controles ajoutes avant les reglages de couleur (sur %s)"), Menu ? *Menu->GetName() : TEXT("?"));
|
||||
}
|
||||
=== LPModInfoSubsystem.cpp
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "LifePlay.h"
|
||||
#include "LPDataCompat.h"
|
||||
#include "LPModGuard.h"
|
||||
+#include "LPSettingsSubsystem.h"
|
||||
#include "Misc/EngineVersion.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Misc/Paths.h"
|
||||
@@ -239,22 +240,10 @@
|
||||
|
||||
void ULPModInfoSubsystem::EnsureSettingsRows()
|
||||
{
|
||||
- UScrollBox* Scroll = nullptr;
|
||||
- for (TObjectIterator<UScrollBox> It; It; ++It)
|
||||
- {
|
||||
- UScrollBox* Candidate = *It;
|
||||
- if (!Candidate || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
|
||||
- {
|
||||
- continue;
|
||||
- }
|
||||
- const UUserWidget* Owner = Candidate->GetTypedOuter<UUserWidget>();
|
||||
- if (!Owner || Owner->HasAnyFlags(RF_ClassDefaultObject) || Owner->GetGameInstance() != GetGameInstance())
|
||||
- {
|
||||
- continue;
|
||||
- }
|
||||
- Scroll = Candidate;
|
||||
- break;
|
||||
- }
|
||||
+ // SET1-V1b : la liste de l'instance de MainMenu qui est a l'ecran, pas la premiere trouvee (une ancienne instance,
|
||||
+ // retiree du viewport et pas encore collectee, vient souvent avant). Aucune a l'ecran : rien a faire. Pas d'etat par
|
||||
+ // instance a remettre a zero : la presence de LPModCheckEngine se lit sur les enfants de la liste choisie.
|
||||
+ UScrollBox* Scroll = ULPSettingsSubsystem::FindOnScreenSettingsList(GetGameInstance());
|
||||
if (!Scroll)
|
||||
{
|
||||
return;
|
||||
@@ -310,9 +299,10 @@
|
||||
Slot->SetPadding(FMargin(0.f, 0.f, 0.f, 10.f));
|
||||
}
|
||||
}
|
||||
- UE_LOG(LogLifePlay, Display, TEXT("Modules : cases de controle des mods ajoutees a Settings > Misc (moteur %d, version min %d, version max %d)"),
|
||||
+ const UUserWidget* Menu = Scroll->GetTypedOuter<UUserWidget>();
|
||||
+ UE_LOG(LogLifePlay, Display, TEXT("Modules : cases de controle des mods ajoutees a Settings > Misc (moteur %d, version min %d, version max %d) sur %s"),
|
||||
FLPModGuard::GetSavedCheck(ELPModCheck::Engine) ? 1 : 0, FLPModGuard::GetSavedCheck(ELPModCheck::MinVersion) ? 1 : 0,
|
||||
- FLPModGuard::GetSavedCheck(ELPModCheck::MaxVersion) ? 1 : 0);
|
||||
+ FLPModGuard::GetSavedCheck(ELPModCheck::MaxVersion) ? 1 : 0, Menu ? *Menu->GetName() : TEXT("?"));
|
||||
}
|
||||
```
|
||||
|
||||
## 12. Établi / estimé / incertain
|
||||
|
||||
- **Établi** : les trois boucles remplacées étaient identiques (`SettingsScrollBox`, même `GameInstance`, `break` à la première, § 11 lignes `-`) ; aucun autre site ne les reprend (`Grep "SettingsScrollBox"` sur `Source`, § 4) ; l'état de Color, Video et Mods se lit sur les enfants de la liste choisie (C1, avec lignes) ; la fonction statique renvoie la même valeur que celle des onglets (renvoi d'une ligne, `LPSettingsSubsystem.cpp:592-596`) ; MD5 de départ égaux au manifeste, MD5 d'arrivée et fins de ligne relevés (§ 9) ; `LPKeyboardSubsystem.cpp` inchangé ; compilation éditeur et jeu : code 0, 0 erreur, 0 avertissement, 5 unités compilées dans chaque (§ 7).
|
||||
- **Estimé** : une ancienne instance précède la nouvelle dans `TObjectIterator` (déjà estimé en V1) ; les lignes arrivent au plus ≈ 0,5 s après l'apparition de l'instance (tickers à 0,5 s, C2) ; `ApplyRows` classe sans autre changement les lignes ajoutées plus tard (rejoué à chaque image, `Tick` des onglets).
|
||||
- **Incertain** (essai qui trancherait : W1 à W9, § 5) : contenu réel des onglets Video et Misc aux trois scénarios ; `IsInViewport()` vrai pour l'instance du titre (V6 de V1) ; absence de régression de Video/Mods/Couleur au titre si ce filtre était faux ; mesure du délai de 0,5 s.
|
||||
- **Livrable** : 0 CR (fins de ligne LF, `tr -cd '\r' | wc -c` = 0) ; `PubCheck` sur ce fichier : `PubCheck : 0 constat(s)`, code 0 ; `UeState` final : `processus=0 editeur=0 compilation=0 shaders=0 jeu=0`, code 0 ; **jeton UE rendu**.
|
||||
|
||||
Tours : 36 / 40 (déclaré par l'agent ; `Tools/FicheStats.py` fait foi)
|
||||
|
||||
## Constats
|
||||
|
||||
- `Tools\FileCheck.ps1 -Lot SET1-V1b` (lot de l'instantané, sans `-Path`) compare bien les cinq fichiers au manifeste (`Sauv` = fins de ligne d'origine, `Contenu` = modifié). C'est le contournement du piège relevé en V1 (`Contenu = pas sauvegarde` avec un chemin relatif à barres obliques).
|
||||
- Les builds ont été enchaînés dans une commande d'arrière-plan (`CopieEtat` avant, `Build` éditeur, `Build` jeu seulement si l'éditeur rend 0, `CopieEtat` après, `UeState`), l'attente se faisant par `UeState.ps1 -Kind Compilation -WaitExit` (`lp-build` § 2) ; le jeu est lancé par `pwsh -Command "& '…/Build.ps1' … -ExtraArgs '-NoUBA'"` : la forme `-File … -ExtraArgs '-NoUBA'` risquerait de lire `-NoUBA` comme un nom de paramètre.
|
||||
- La ligne exacte `U7-T7-IMPL.md:221` (trace ancienne de la ligne Mods) ne correspond plus à la ligne produite par le code actuel (suffixe ` sur <nom>`) : voir E1.
|
||||
|
|
@ -28,7 +28,7 @@ J1 : CART seulement, sans copie UE. Aucune écriture git par la session.
|
|||
| S4 | STM1-SPEC-04 | essai COMMUN-16 : « la tamise est ok, mais des batiments sont sous l'eau » | Medium · STM1 | N2 | ≈ 4 | fait : les maisons dans l'eau sont les instances génériques de `MapMarkers`, une par bâtiment OSM (pontons, bateaux) ; indices non suivis par le Blueprint ; options O1-O5, O2 recommandée (masquer à la pose, épargner les grands bâtiments) ; 3 décisions attendues | `STM1-SPEC-04.md` |
|
||||
| O3 | STM1-O3 | GO de Big Boss : « Oui, O2 avec un seuil de 1 500 m², en faisant d'abord la liste O3 des bâtiments dans l'eau pour vérifier le seuil. » | Medium · STM1 | N3 | ≈ 2 | fait : 59 bâtiments dans l'eau, dont 5 au-dessus de 1 500 m² ; contrôle non rempli (London Eye à 1 168 m², HMS Belfast épargné) ; seuil proposé 1 100 m² (options A à D) ; O2 en attente de la décision de l'utilisateur | `STM1-O3-LISTE.md` |
|
||||
| O2 | STM1-SPEC-08 / B6 | choix de l'utilisateur : « option D » ; GO de Big Boss et jeton UE | Medium · STM1 | N3 | ≈ 3 | fait : masque `Water/CentralLondon_Mask` (59 centres), masquage à l'échelle 0 des maisons `House*` / `Skyscraper*` par `ULPCityWaterSubsystem`, builds éditeur et Development code 0 ; essai en jeu à faire | `STM1-SPEC-08.md`, `STM1-B6-FIN.md` |
|
||||
| S5 | suivi O2 | COMMUN-20 (Big Boss) : O2 option D PASS en jeu (plus de maison sur la Tamise ; ponts, quais et jeeps intacts ; Bath sans régression). Journal : 15:11:16 UTC « masque 59 centres ; instances maisons 49417 ; masquees 59 ; epargnees 0 ; centres sans instance 0 », puis 15:11:50 UTC « instances maisons 0 ; masquees 0 ; centres sans instance 59 » | Medium · STM1 | N2 | – | constat (lecture de `LifePlay.log` de COM20, GO de Big Boss) : à 15:11:44-49, CityMenu rouvert et « Central London » rechoisi (`GI … Central London`, `FOLLOWUP`) ; même carte, donc pas de nouvelle pose ; MapMarkers vide alors ses instances de maisons (0 à 15:11:50) sans les recréer avant le passage à Bath (15:12:02). Masquage non en cause. Reste ouvert : (1) ces 0 maisons sont-elles l'ancien comportement (comparaison avec 5.5 ou un essai sans STM1) ? (2) risque relevé : si MapMarkers vide et recrée le même nombre d'instances dans la même fenêtre de 0,25 s, la passe n'est pas relancée et les maisons réapparaissent dans l'eau ; parade possible sans GI : relancer aussi quand une instance du masque a une échelle non nulle. Question initiale : pourquoi le second passage voit 0 instance (re-pose, MapMarkers reconstruit, changement de vue) ? Le masquage tient-il si MapMarkers recrée ses instances ? Pas d'IMPL sans GO | `STM1-B6-FIN.md` |
|
||||
| S5 | suivi O2 | COMMUN-20 (Big Boss) : O2 option D PASS en jeu (plus de maison sur la Tamise ; ponts, quais et jeeps intacts ; Bath sans régression). Journal : 15:11:16 UTC « masque 59 centres ; instances maisons 49417 ; masquees 59 ; epargnees 0 ; centres sans instance 0 », puis 15:11:50 UTC « instances maisons 0 ; masquees 0 ; centres sans instance 59 » | Medium · STM1 | N2 | – | constat (lecture de `LifePlay.log` de COM20, GO de Big Boss) : à 15:11:44-49, CityMenu rouvert et « Central London » rechoisi (`GI … Central London`, `FOLLOWUP`) ; même carte, donc pas de nouvelle pose ; MapMarkers vide alors ses instances de maisons (0 à 15:11:50) sans les recréer avant le passage à Bath (15:12:02). Masquage non en cause. Reste ouvert : (1) ces 0 maisons sont-elles l'ancien comportement (comparaison avec 5.5 ou un essai sans STM1) ? (2) risque relevé : si MapMarkers vide et recrée le même nombre d'instances dans la même fenêtre de 0,25 s, la passe n'est pas relancée et les maisons réapparaissent dans l'eau ; parade possible sans GI : relancer aussi quand une instance du masque a une échelle non nulle. Classement de Big Boss (2026-10-20), après la réponse de l'utilisateur citée mot pour mot « je n'ai rien constaté sur la disparition des maisons » : **suite en build 2, priorité basse** ; d'abord la parade, puis la comparaison avec la 5.5 ; rien à faire d'ici là. Question initiale : pourquoi le second passage voit 0 instance (re-pose, MapMarkers reconstruit, changement de vue) ? Le masquage tient-il si MapMarkers recrée ses instances ? Pas d'IMPL sans GO | `STM1-B6-FIN.md` |
|
||||
| S5 | STM1-SPEC-05 | demande de l'utilisateur : villes factices ? pilote Paris | Medium · STM1 | N2 | ≈ 8 | fait : 278/280 gabarits importés de `MLExport/CitiesOSM/000Dummy.OSM` (Paris = 9 bâtiments de Liverpool Street) ; chaîne du plugin documentée ; pilote Paris (zone, P1 Overpass estimé 150-350 Mo, étapes, risques dont les anciennes parties) ; coût des 278 (frein : taille du jeu) ; rien téléchargé | `STM1-SPEC-05.md` |
|
||||
| D3 | téléchargement P1 Paris (accord « oui télécharge ») | requête QP sur Overpass, une seule fois | Medium · STM1 | — | — | **échec** : HTTP 502 « server at capacity », 534 o, aucune donnée ; arrêt sans nouvelle tentative ; options R-A, R-B, R-C | `STM1-SPEC-06.md` § 0 |
|
||||
| D3b | téléchargement P1 Paris, tentative R-A (accord « même serveur pour les tests ») | même requête, même serveur, une seule fois | Medium · STM1 | — | — | **réussi** : HTTP 200, 232 644 671 o, 0 erreur, SHA-256 `ecbdc20d…01683` ; 110 894 bâtiments, dont 4 157 nommés, 128 563 routes ; LISEZMOI complété ; pas d'import | `D:\Game\LifePlay_Data\OSM\STM1-PARIS-20261020\LISEZMOI.txt` |
|
||||
|
|
|
|||
|
|
@ -7,13 +7,11 @@ Après la vague, Big Boss contre-vérifie chaque commit et vide les lignes trait
|
|||
|
||||
| Rang | Ticket | Dépôt | Dépend de | Déposé (AAAA-MM-JJ HH:MM) | PubCheck relu | CHG / ERR |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 1 | KEY2-T5 (vague 9) | jeu | HEAD e411b70 | 2026-10-20 17:26 | oui (0 constat) | CHG-378 |
|
||||
| 2 | STM1-T5 (vague 9) | jeu | HEAD e411b70 | 2026-10-20 17:26 | oui (0 constat) | CHG-379 |
|
||||
| 3 | DISC1-T1 (vague 9) | jeu | HEAD e411b70 | 2026-10-20 17:26 | oui (0 constat) | CHG-380 |
|
||||
| 4 | COMMUN20-T1 (vague 9) | jeu | HEAD e411b70 | 2026-10-20 17:26 | oui (0 constat) | — |
|
||||
| 5 | VAGUE-20261020-9-PARTAGES (vague 9) | jeu | tous | 2026-10-20 17:26 | oui (0 constat) | CHG-378, 379, 380 |
|
||||
| 1 | REL2-T1 | jeu | — | 2026-10-21 09:28 | oui (0) | CHG-387 |
|
||||
| 2 | BUILD2-PRE-T2 | jeu | — | 2026-10-21 09:28 | oui (0) | — |
|
||||
| 3 | VAGUE-20261021-13-PARTAGES | jeu | 1, 2 | 2026-10-21 09:28 | oui (0) | CHG-387 |
|
||||
|
||||
Vague 8 faite le 2026-10-20 par Vague.ps1, contre-vérifiée par Big Boss (2026-10-20 15:36) et vidée : 542ee7f CAM2-T5, 018dd4e KEY2-T4, 9a68cf5 STM1-T4, 5997880 COMMUN17-19-T1, e411b70 PARTAGES (noreply, PubCheck -Arbre ue5.8 = 0). Vague 7 faite et vidée (fa86b6f). Vague 4 vidée (faite et contre-vérifiée, voir le paragraphe Vague 4). Vague 5 : exécution par `Tools\Vague.ps1` (première exécution réelle) ; vague 6 à suivre (CAM2-T2, COMMUN-14-T1).
|
||||
Vague 12 faite le 2026-10-21 par Vague.ps1, contre-vérifiée par Big Boss (2026-10-21 00:17) et vidée : b207e29 QPERS-T1, 56fe4d6 BUILD2-PRE-T1, 0536487 PARTAGES (noreply, PubCheck -Arbre ue5.8 = 0). Vague 11 faite le 2026-10-20 par Vague.ps1, contre-vérifiée par Big Boss (2026-10-20 22:10) et vidée : dc08d3b FIX1-T2, 3967951 SET1-T1, e6194ff COMMUN22-23-T1, 3b32c5d PARTAGES (noreply, PubCheck -Arbre ue5.8 = 0). Vague 10 faite le 2026-10-20 par Vague.ps1, contre-vérifiée par Big Boss (2026-10-20 19:44) et vidée : 30681e2 FIX1-T1, c45958d KEY2-T6, e66867b COMMUN21-T1, 2042c99 STM1-T6, 56d1007 PUB-20261020-T2, ad3c9c6 PARTAGES (noreply, PubCheck -Arbre ue5.8 = 0). Vague 9 faite le 2026-10-20 par Vague.ps1, contre-vérifiée par Big Boss (2026-10-20 17:28) et vidée : 2357225 KEY2-T5, 91ad15e STM1-T5, d15ffaa DISC1-T1, 09b42cc COMMUN20-T1, b5feae4 PARTAGES (noreply, PubCheck -Arbre ue5.8 = 0). Vague 8 faite le 2026-10-20 par Vague.ps1, contre-vérifiée par Big Boss (2026-10-20 15:36) et vidée : 542ee7f CAM2-T5, 018dd4e KEY2-T4, 9a68cf5 STM1-T4, 5997880 COMMUN17-19-T1, e411b70 PARTAGES (noreply, PubCheck -Arbre ue5.8 = 0). Vague 7 faite et vidée (fa86b6f). Vague 4 vidée (faite et contre-vérifiée, voir le paragraphe Vague 4). Vague 5 : exécution par `Tools\Vague.ps1` (première exécution réelle) ; vague 6 à suivre (CAM2-T2, COMMUN-14-T1).
|
||||
Vague 5 (Vague.ps1, 2026-10-20) : faits 30beef0 VAG1-T2 (addon), 6d5b326 ROAD1-T2, 644eb48 CG2-T2, 7c3574b STM1-T2, 3592e8e VAG1-T3 ; interrompue à KEY1-T1 (REPO-JOURNAL verrouillé) ; KEY1-T1, KEY2-T1, PARTAGES-5 retirés. Vague 6 : KEY1-T2, KEY2-T2, CAM2-T2, COMMUN14-T1, VAGUE-20261020-6-PARTAGES (HEAD 3592e8e).
|
||||
|
||||
Vague 4 faite le 2026-10-20 par lp-gardien, contre-vérifiée par Big Boss (addon 8cdcbd4..061dd83, jeu 00214f6..8ff3457) : rangs 1-13 à vider à la prochaine vague. Pas de pin du doc 21 dans cette vague (reste 6377ce6 ; à refaire avec la prochaine publication).
|
||||
|
|
|
|||
|
|
@ -157,3 +157,10 @@ et 5.8) et ce registre, plus un.
|
|||
| CHG | 378 | COMMUN20 | Big Boss (KEY2-IMPL-02 menu Clavier ; STM1 O3/O2 maisons dans l'eau ; DISC1 lien Discord) ; verrou 244 ; max lus : 5.8=377 5.5=297 registre=377 | 2026-10-20 17:19 | utilisé (journal `Docs/Journal_Modifications.md`, DOC-20261020-VERS3 ; non commité) |
|
||||
| CHG | 379 | COMMUN20 | Big Boss (KEY2-IMPL-02 menu Clavier ; STM1 O3/O2 maisons dans l'eau ; DISC1 lien Discord) ; verrou 244 ; max lus : 5.8=377 5.5=297 registre=377 | 2026-10-20 17:19 | utilisé (journal `Docs/Journal_Modifications.md`, DOC-20261020-VERS3 ; non commité) |
|
||||
| CHG | 380 | COMMUN20 | Big Boss (KEY2-IMPL-02 menu Clavier ; STM1 O3/O2 maisons dans l'eau ; DISC1 lien Discord) ; verrou 244 ; max lus : 5.8=377 5.5=297 registre=377 | 2026-10-20 17:19 | utilisé (journal `Docs/Journal_Modifications.md`, DOC-20261020-VERS3 ; non commité) |
|
||||
| CHG | 381 | COMMUN21 | Big Boss (FIX1-F6 redirection des sauvegardes ; KEY2-IMPL-03 confirmation des touches) ; verrou 247 ; max lus : 5.8=380 5.5=297 registre=380 | 2026-10-20 19:37 | utilisé (journal `Docs/Journal_Modifications.md`, FIX1-F6, DOC-20261020-VERS4 ; non commité) |
|
||||
| CHG | 382 | COMMUN21 | Big Boss (FIX1-F6 redirection des sauvegardes ; KEY2-IMPL-03 confirmation des touches) ; verrou 247 ; max lus : 5.8=380 5.5=297 registre=380 | 2026-10-20 19:37 | utilisé (journal `Docs/Journal_Modifications.md`, KEY2-IMPL-03, DOC-20261020-VERS4 ; non commité) |
|
||||
| CHG | 383 | COMMUN23 | Big Boss (FIX1-F8a Aim ; FIX1-MZ/MZ2 talons ; SET1 reglages en partie) ; verrou 249 ; max lus : 5.8=382 5.5=297 registre=382 | 2026-10-20 22:03 | utilisé (journal `Docs/Journal_Modifications.md`, FIX1-F8a, DOC-20261020-VERS5 ; non commité) |
|
||||
| CHG | 384 | COMMUN23 | Big Boss (FIX1-F8a Aim ; FIX1-MZ/MZ2 talons ; SET1 reglages en partie) ; verrou 249 ; max lus : 5.8=382 5.5=297 registre=382 | 2026-10-20 22:03 | utilisé (journal `Docs/Journal_Modifications.md`, FIX1-MZ et MZ2, DOC-20261020-VERS5 ; non commité) |
|
||||
| CHG | 385 | COMMUN23 | Big Boss (FIX1-F8a Aim ; FIX1-MZ/MZ2 talons ; SET1 reglages en partie) ; verrou 249 ; max lus : 5.8=382 5.5=297 registre=382 | 2026-10-20 22:03 | utilisé (journal `Docs/Journal_Modifications.md`, SET1, DOC-20261020-VERS5 ; non commité) |
|
||||
| CHG | 386 | QPERS | Big Boss (QPERS : r.Tonemapper.Sharpen 0.5 aux niveaux High et Epic) ; verrou 251 ; max lus : 5.8=385 5.5=297 registre=385 | 2026-10-21 00:14 | utilisé (journal `Docs/Journal_Modifications.md`, QPERS, DOC-20261021-VERS6 ; non commité) |
|
||||
| CHG | 387 | REL2 | Big Boss (REL2, version 2026.10.2.2a) ; verrou 253 ; max lus : 5.8=386 5.5=297 registre=386 | 2026-10-21 09:27 | utilisé (journal `Docs/Journal_Modifications.md`, REL2, DOC-20261021-VERS7 ; non commité) |
|
||||
|
|
|
|||
91
Docs/Migration/etat/REPO/PUB/PUB-20261020-VAL.md
Normal file
91
Docs/Migration/etat/REPO/PUB/PUB-20261020-VAL.md
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
Fiche PUB-20261020-VAL — Niveau N1 — Modèle prévu sonnet | utilisé sonnet (claude-sonnet-5-5) — Agent lp-validator — Skills sk-protocol, sk-recount, debug-verification, lp-validate
|
||||
# PUB-20261020-VAL : contrôle du contenu avant le push du commit de publication (2026-10-20)
|
||||
|
||||
Lecture seule du dépôt ; seul écrit : ce fichier. Modèle : `REP1-VAL-01.md`. Règle : doc 27 l. 70 (« sans contenu de jeu ni contenu sexuel »). Diff contrôlé : `git diff 8084622 b5feae4`.
|
||||
|
||||
## 1. Fiches amont relues
|
||||
- `etat\REPO\REP1\REP1-VAL-01.md` (modèle de contrôle, catégories T / E / S).
|
||||
- Fiche de la session (rubriques 1 à 5). `REP1-T4.md` et `PUB3-T3-SPEC.md` § 7 (procédure) : non relus ici, la procédure ne change pas le contenu contrôlé.
|
||||
- Pas d'IMPL amont : section 2 `sans objet : contrôle de contenu, aucune IMPL ni point à confirmer`.
|
||||
|
||||
## 2. Points à confirmer des IMPL
|
||||
sans objet : aucune IMPL dans cette fiche.
|
||||
|
||||
## 3. Critères rejoués
|
||||
|
||||
Refs (établi, `git rev-parse HEAD ue5.8 pub/ue5.8 origin/ue5.8`) : `ue5.8` = HEAD = `b5feae46e615724389a4008edc190ae03eec745d` ; `pub/ue5.8` = `origin/ue5.8` = `8084622450e0cce9c9dafcfea77c9afbd685d3e6`.
|
||||
|
||||
| # | Critère | Commande | Résultat | Verdict |
|
||||
|---|---|---|---|---|
|
||||
| 1 | PubCheck 0 constat | `pwsh -NoProfile -File Tools/PubCheck.ps1 -Arbre ue5.8 -Binaires -Depot "D:/Game/LifePlay-master 5.8" </dev/null` | `PubCheck : 0 constat(s)`, code 0 | PASS |
|
||||
| 2 | Contenu adulte explicite | voir § 3.2 | aucune phrase explicite ajoutée | PASS |
|
||||
| 3 | Secrets, données personnelles | voir § 3.3 | aucun secret ; 1 réserve (hôte) | PASS avec réserve |
|
||||
| 4 | Fichiers à exclure absents | voir § 3.4 | tous absents, sauf `LifePlay.uproject` (attendu) | PASS |
|
||||
| 5 | Binaires ajoutés | voir § 3.5 | 0 ajouté, 6 `.uasset` modifiés | PASS |
|
||||
|
||||
### 3.2 Contenu adulte
|
||||
Commande : `git diff -U0 8084622 b5feae4 | grep -E '^\+' | grep -v '^+++' | grep -a -i -w -o -E '<liste de 45 termes : organes, actes, violence sexuelle, nudité, sites adultes, grossièretés>' | sort | uniq -c`. Sortie brute : `4 xxx`, `3 sex`, `2 bondage`. Aucun autre terme (ni fuck, pussy, cock, cum, dick, penis, vagina, blowjob, orgasm, rape, porn, dildo, boob, genital, nude…).
|
||||
Les 9 occurrences, lues une à une (lignes 5755, 7550, 7561, 7595, 7671, 14439, 14441, 14444, 14477 du diff) :
|
||||
- `xxx` x4 : chemin local `D:\XxX\LifePlay_2023_04_Stable_64bit` (dossier d'un jeu empaqueté, journal de build) : cat. T, non sexuel.
|
||||
- `sex` x3 : noms de widgets `UI/SexAction`, `UI/SexInterface` (liste de tabulations), « Sex Show » (nom de section du menu clavier), citation d'une remarque de l'utilisateur sur l'axe vertical d'une caméra : cat. T / E, noms d'interface, aucune description.
|
||||
- `bondage` x2 : nom de widget `UI/Bondage` : cat. T.
|
||||
- Le texte l. 7561 dit lui-même que le détail n'est pas consigné (règle du doc 27) : conforme.
|
||||
Contrôle par nom de fichier : `git diff --name-only 8084622 b5feae4 | grep -i -E 'sex|nude|porn'` : 0 ligne.
|
||||
Binaires : comptes de termes explicites dans les 6 `.uasset` modifiés, avant et après (`git cat-file blob <ref>:<f> | tr -d '\000' | grep -a -o -i -E <motifs> | wc -l`) : PC 57 -> 57 ; Room 4 -> 4 ; CharGen 105 -> 105 ; CharGenSlider 7 -> 7 ; MainMenu 11 -> 11 ; VisualMorph 2 -> 2. Aucun terme nouveau.
|
||||
Les identifiants déjà admis dans REP1-VAL-01 (SexOn, vin_*, noms de variables) n'apparaissent pas comme ajouts du diff au-delà des 9 lignes ci-dessus.
|
||||
|
||||
### 3.3 Secrets et données personnelles
|
||||
- Jetons, mots de passe, clés (`password|passwd|mdp|token|secret|api[_-]?key|bearer|BEGIN … PRIVATE|ghp_|github_pat|AKIA|sk-…`) sur les lignes ajoutées : aucune valeur. Les seules occurrences de « PASSWORD / PASSWD » sont des noms de variables et des recommandations sans valeur (`STM1-SPEC-07.md` l. 408-413 : `POSTGRES_PASSWORD`, `FORGEJO__database__PASSWD`, `FORGEJO_DB_PASSWD=…`, `'<nouveau>'`). `git grep -n -i -E 'POSTGRES_USER|DB_USER|USER:|_USER=|PASSWD|PASSWORD|password' b5feae4 -- STM1-SPEC-07.md STM1-SPEC-08.md` : 4 lignes, toutes ci-dessus ; aucun nom d'utilisateur de base. « Tokens » dans le C++ = `TArray<FString> Tokens` (analyse de ligne de commande), sans rapport.
|
||||
- Fiches STM1-SPEC-07 et suivantes : pas de mot de passe de serveur (Forgejo, base). Établi.
|
||||
- E-mails : `grep -o -E '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}'` sur les lignes ajoutées : 0 résultat.
|
||||
- Adresses IP hors 127.0.0.1 et 0.0.0.0 : 0. Chemins de profil (`X:\Users\<nom>`) : 0. Nom de profil Windows : 0.
|
||||
- Domaines cités : sites de documentation et de référence publics (docker.io, github.com, openstreetmap, etc.) et `forgejo.edujiro5972.fr` (6 lignes, 3 fichiers : `BOSS-ETAT.md`, `BOSS-JOURNAL.md`, `REP1\REP1-DOC-02.md`). Absent de l'arbre `8084622` (`git grep -c` : 0 résultat) : **nouveauté de ce commit**. Réserve : c'est le nom d'hôte du serveur auto-hébergé de l'utilisateur, donné aussi par `STM1-SPEC-07.md` (noms de conteneurs, ports 80 / 443 / 2222, procédure de redéploiement). Ce n'est ni un secret ni une donnée personnelle au sens de PubCheck (0 constat), mais c'est une information d'infrastructure ; case en § 6.
|
||||
- Identité Git : la ligne citée `…@users.noreply.github.com` est le gabarit de contrôle C3, sans adresse réelle.
|
||||
|
||||
### 3.4 Fichiers à ne pas publier
|
||||
Commande : `git ls-tree -r --name-only b5feae4 | grep -i -E 'LifePlay\.uproject|LP-PROJET\.ini|AG/ORGA2|\.log$|DC2-BUILD'`. Sortie brute : `LifePlay.uproject` (une seule ligne).
|
||||
- `Docs/LP-PROJET.ini` : absent de l'arbre (non suivi : `?? Docs/LP-PROJET.ini` dans `git status --short`).
|
||||
- `Docs/Migration/etat/AG/ORGA2/` : absent (non suivi, `??`).
|
||||
- `*.log` (dont `etat\BOSS\COMMUN-*`) : 0 fichier suivi.
|
||||
- `Docs/Migration/etat/sandbox/DC2/DC2-BUILD.md` : absent.
|
||||
- `LifePlay.uproject` : **suivi, donc présent dans l'arbre**, mais c'est la version commitée (publique, présente aussi dans `8084622`), non la copie locale. `git diff 8084622 b5feae4 -- LifePlay.uproject | wc -l` : 0 (identique à ce qui est déjà publié). La modification locale (` M LifePlay.uproject` du statut) n'est pas dans le commit `b5feae4`. Conforme, à condition que le commit de publication prenne l'arbre de `b5feae4` et non l'index ou le répertoire de travail.
|
||||
- Autres fichiers modifiés localement et non commités (`BOSS-ETAT.md`, `BOSS-JOURNAL.md`, `STM1-TACHES.md`, `FILE.md`) : hors du commit si l'arbre vient de `b5feae4`.
|
||||
Arbre : 2 396 fichiers (`git ls-tree -r --name-only b5feae4 | grep -c .`) contre 2 215 pour `8084622`.
|
||||
|
||||
### 3.5 Binaires ajoutés
|
||||
`git diff --name-status 8084622 b5feae4 | grep -i -E 'uasset|umap|\.(png|jpg|wav|mp3|zip|dll|exe|bin)$'` : 6 lignes, toutes `M`, aucune `A`. Aucun binaire ajouté ; aucun média, archive, DLL ni exécutable.
|
||||
|
||||
| Fichier (modifié) | Taille avant (octets) | Taille après (octets) |
|
||||
|---|---|---|
|
||||
| Content/BPs/PC.uasset | 3 420 303 | 3 410 606 |
|
||||
| Content/BPs/Room.uasset | 6 428 769 | 6 392 085 |
|
||||
| Content/UI/CharGen.uasset | 5 054 038 | 5 063 130 |
|
||||
| Content/UI/CharGenSlider.uasset | 455 140 | 447 967 |
|
||||
| Content/UI/MainMenu.uasset | 2 260 418 | 2 245 771 |
|
||||
| Content/UI/VisualMorph.uasset | 327 185 | 333 578 |
|
||||
|
||||
Source : `git cat-file -s <ref>:<fichier>`. Le plus gros reste sous 6,5 Mo.
|
||||
|
||||
## 4. Diff lu en entier
|
||||
`git diff --name-status 8084622 b5feae4 | awk '{print $1}' | sort | uniq -c` : 181 A, 25 M, soit 206 fichiers (confirme `git diff --stat` : « 206 files changed, 16599 insertions(+), 79 deletions(-) »). Hors `.md` : 27 fichiers (`Config/DefaultInput.ini`, 6 `.uasset`, 15 sources `Source/LifePlay`, 5 sources `Source/LifePlayEditorTools`).
|
||||
Méthode : balayage des lignes ajoutées par motifs (§ 3.2, § 3.3) et lecture des lignes à constat. Les 16 599 lignes n'ont pas été lues une à une ; les sources C++ ne contiennent aucun des termes cherchés.
|
||||
|
||||
## 5. Verdict : **PASS** (avec une réserve, § 6)
|
||||
Les cinq contrôles de la fiche sont conformes. PubCheck : 0 constat. Aucun contenu sexuel explicite ajouté. Aucun secret. Les fichiers exclus sont absents. Aucun binaire ajouté.
|
||||
|
||||
PubCheck sur ce livrable : voir ligne finale.
|
||||
|
||||
## 6. Points à confirmer par l'utilisateur
|
||||
- [ ] Le nom d'hôte `forgejo.edujiro5972.fr` (3 fichiers `etat/`) peut apparaître dans le dépôt qui le reçoit. Si le dépôt de destination est public et que l'hôte doit rester discret, retirer ces lignes avant le commit (décision de l'utilisateur, non bloquante pour PubCheck).
|
||||
- [ ] Le commit de publication prend l'arbre de `b5feae4` (`git commit-tree b5feae4^{tree} -p pub/ue5.8`), pas le répertoire de travail : sinon `LifePlay.uproject` local et `Docs/LP-PROJET.ini` seraient embarqués.
|
||||
|
||||
## Limites (non mesuré)
|
||||
- Balayage lexical (anglais, français) : une phrase explicite sans l'un des termes n'est pas vue. Textures, icônes, sons non examinés. Contenu des modules hors dépôt hors périmètre.
|
||||
- Le contrôle du contenu porte sur le diff `8084622..b5feae4`, non sur les 2 215 fichiers déjà publiés (cf. REP1-VAL-01).
|
||||
|
||||
## Fichiers à commiter
|
||||
A : `Docs/Migration/etat/REPO/PUB/PUB-20261020-VAL.md` (ce livrable). Aucun autre fichier modifié par cette fiche.
|
||||
|
||||
Tours : 10 / 40
|
||||
À verser : lp-repo — avant le commit de publication, prendre l'arbre par `b5feae4^{tree}` : `LifePlay.uproject` et `Docs/LP-PROJET.ini` locaux ne sont pas dans le commit.
|
||||
Suite : Big Boss doit donner la commande de push (arbre de `b5feae4`, parent `pub/ue5.8`) après réponse aux deux cases du § 6 ; état : contrôle terminé, PASS.
|
||||
|
|
@ -215,3 +215,20 @@
|
|||
| 2026-10-20 | DISC1-T1 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 2 chemins explicites), aucun push (vague) | 91ad15e (HEAD d'avant ; hash : `git log --grep DISC1-T1`) | 2 (1 A + 1 M) | DISC1 / CHG-380 | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-20 | COMMUN20-T1 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 3 chemins explicites), aucun push (vague) | d15ffaa (HEAD d'avant ; hash : `git log --grep COMMUN20-T1`) | 3 (3 A) | COMMUN20 / sans CHG | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-20 | VAGUE-20261020-9-PARTAGES | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 11 chemins explicites), aucun push (vague) | 09b42cc (HEAD d'avant ; hash : `git log --grep VAGUE-20261020-9-PARTAGES`) | 11 (5 A + 6 M) | VAGUE / sans CHG | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-20 | PUB-20261020-T1 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | pub/ue5.8 (ref locale ; ue5.8 non déplacée) | BRANCHE : `git commit-tree b5feae4^{tree} -p 8084622` puis `git branch -f pub/ue5.8` ; aucun push | 8084622 (pub/ue5.8 = origin/ue5.8 d'avant) → 56dfcfc ; ue5.8 = b5feae4 inchangée | 0 (ref seule) | PUB / sans CHG | diff b5feae4 pub/ue5.8 vide ; origin/ue5.8..pub/ue5.8 = 1 ; filiation vraie ; DC2-BUILD.md absent ; pre-push simulé : pub/ue5.8 passe (0), ue5.8 refusée (746) ; PubCheck -Arbre pub/ue5.8 : 0 ; -Pointe pub/ue5.8 -Distant origin : 0 ; verrou 246 |
|
||||
| 2026-10-20 | FIX1-T1 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 5 chemins explicites), aucun push (vague) | b5feae4 (HEAD d'avant ; hash : `git log --grep FIX1-T1`) | 5 (4 A + 1 M) | FIX1 / CHG-381 | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-20 | KEY2-T6 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 4 chemins explicites), aucun push (vague) | 30681e2 (HEAD d'avant ; hash : `git log --grep KEY2-T6`) | 4 (2 A + 2 M) | KEY2 / CHG-382 | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-20 | COMMUN21-T1 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 3 chemins explicites), aucun push (vague) | c45958d (HEAD d'avant ; hash : `git log --grep COMMUN21-T1`) | 3 (3 A) | COMMUN21 / sans CHG | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-20 | STM1-T6 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 1 chemins explicites), aucun push (vague) | e66867b (HEAD d'avant ; hash : `git log --grep STM1-T6`) | 1 (1 M) | STM1 / sans CHG | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-20 | PUB-20261020-T2 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 1 chemins explicites), aucun push (vague) | 2042c99 (HEAD d'avant ; hash : `git log --grep PUB-20261020-T2`) | 1 (1 A) | PUB / sans CHG | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-20 | VAGUE-20261020-10-PARTAGES | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 13 chemins explicites), aucun push (vague) | 56d1007 (HEAD d'avant ; hash : `git log --grep VAGUE-20261020-10-PARTAGES`) | 13 (7 A + 6 M) | VAGUE / sans CHG | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-20 | FIX1-T2 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 7 chemins explicites), aucun push (vague) | ad3c9c6 (HEAD d'avant ; hash : `git log --grep FIX1-T2`) | 7 (5 A + 2 M) | FIX1 / sans CHG | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-20 | SET1-T1 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 8 chemins explicites), aucun push (vague) | dc08d3b (HEAD d'avant ; hash : `git log --grep SET1-T1`) | 8 (3 A + 5 M) | SET1 / CHG-385 | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-20 | COMMUN22-23-T1 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 4 chemins explicites), aucun push (vague) | 3967951 (HEAD d'avant ; hash : `git log --grep COMMUN22-23-T1`) | 4 (4 A) | COMMUN22 / sans CHG | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-20 | VAGUE-20261020-11-PARTAGES | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 10 chemins explicites), aucun push (vague) | e6194ff (HEAD d'avant ; hash : `git log --grep VAGUE-20261020-11-PARTAGES`) | 10 (4 A + 6 M) | VAGUE / sans CHG | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-21 | QPERS-T1 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 2 chemins explicites), aucun push (vague) | 3b32c5d (HEAD d'avant ; hash : `git log --grep QPERS-T1`) | 2 (1 A + 1 M) | QPERS / CHG-386 | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-21 | BUILD2-PRE-T1 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 2 chemins explicites), aucun push (vague) | b207e29 (HEAD d'avant ; hash : `git log --grep BUILD2-PRE-T1`) | 2 (2 A) | BUILD2 / sans CHG | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-21 | VAGUE-20261021-12-PARTAGES | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 9 chemins explicites), aucun push (vague) | 56fe4d6 (HEAD d'avant ; hash : `git log --grep VAGUE-20261021-12-PARTAGES`) | 9 (3 A + 6 M) | VAGUE / CHG-386 | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-21 | REL2-T1 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 8 chemins explicites), aucun push (vague) | 0536487 (HEAD d'avant ; hash : `git log --grep REL2-T1`) | 8 (7 A + 1 M) | REL2 / CHG-387 | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-21 | BUILD2-PRE-T2 | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 4 chemins explicites), aucun push (vague) | c8870b0 (HEAD d'avant ; hash : `git log --grep BUILD2-PRE-T2`) | 4 (4 A) | BUILD2 / sans CHG | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
| 2026-10-21 | VAGUE-20261021-13-PARTAGES | jeu 5.8 (`D:\Game\LifePlay-master 5.8`) | ue5.8 | COMMIT (index privé, 9 chemins explicites), aucun push (vague) | 7c57252 (HEAD d'avant ; hash : `git log --grep VAGUE-20261021-13-PARTAGES`) | 9 (3 A + 6 M) | VAGUE / CHG-387 | name-status = liste du ticket ; PubCheck -Index : 0 ; Vague.ps1 |
|
||||
|
|
|
|||
12
Docs/Migration/etat/REPO/tickets/BUILD2-PRE-T1.md
Normal file
12
Docs/Migration/etat/REPO/tickets/BUILD2-PRE-T1.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Ticket BUILD2-PRE-T1 — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 12) — Date : 2026-10-21 00:16
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : 3b32c5d
|
||||
Fichiers :
|
||||
A Docs/Migration/etat/REL/GIREV/GIREV-PRE.md
|
||||
A Docs/Migration/etat/REL/ERR145/ERR145-DIAG.md
|
||||
Message : Build 2 : étude de la révision unique de GI et diagnostic d'ERR-145 ; corps `Tickets : BUILD2-PRE-T1`
|
||||
Preuve : sans objet (études en lecture seule)
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-21 00:16)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui, verse le CHG de QPERS et lance la vague 12 ce soir, sans push. » (session Big Boss local_104ff22d, 2026-10-21)
|
||||
14
Docs/Migration/etat/REPO/tickets/BUILD2-PRE-T2.md
Normal file
14
Docs/Migration/etat/REPO/tickets/BUILD2-PRE-T2.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Ticket BUILD2-PRE-T2 — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 13) — Date : 2026-10-21 09:27
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : 0536487
|
||||
Fichiers :
|
||||
A Docs/Migration/etat/REL/ERR145/ERR145-SPEC.md
|
||||
A Docs/Migration/etat/REL/ERR145/ERR145-SPEC-02.md
|
||||
A Docs/Migration/etat/REL/GIREV/GIREV-D8-RECH.md
|
||||
A Docs/Migration/etat/REL/GIREV/GIREV-MCP-01.md
|
||||
Message : Build 2 : SPEC de la caméra C1 stable (ERR-145), recherche D8 et relecture MCP de GI (GQ1, GQ4) ; corps `Tickets : BUILD2-PRE-T2`
|
||||
Preuve : sans objet (études en lecture seule)
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-21 09:28)
|
||||
Suite : IMPL ERR-145 et SPEC GIREV après la publication de la build 1
|
||||
Accord utilisateur : « ok REL2 » (session Big Boss local_104ff22d, 2026-10-21 08:30 ; REL2 = VAL commune, Shipping, essai final, dernière vague, publication, doc 37 l. 172)
|
||||
13
Docs/Migration/etat/REPO/tickets/COMMUN21-T1.md
Normal file
13
Docs/Migration/etat/REPO/tickets/COMMUN21-T1.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Ticket COMMUN21-T1 — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 10) — Date : 2026-10-20 19:41
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : b5feae4
|
||||
Fichiers :
|
||||
A Docs/Migration/etat/BOSS/COMMUN-21-TESTS.md
|
||||
A Docs/Migration/etat/BOSS/COMMUN-21-BILAN.md
|
||||
A Docs/Migration/etat/BOSS/COMMUN-21/COMMUN-21-BUILD.md
|
||||
Message : COMMUN-21 : fiche de tests, build d'essai et bilan (journaux de session locaux, non commités) ; corps `Tickets : COMMUN21-T1`
|
||||
Preuve : sans objet (documentation d'essai)
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-20 19:41)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui : bilan COMMUN-21, versement des CHG (F6, KEY2-IMPL-03) puis prépare et lance la vague 10. » (session Big Boss local_104ff22d, 2026-10-20)
|
||||
14
Docs/Migration/etat/REPO/tickets/COMMUN22-23-T1.md
Normal file
14
Docs/Migration/etat/REPO/tickets/COMMUN22-23-T1.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Ticket COMMUN22-23-T1 — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 11) — Date : 2026-10-20 22:08
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : ad3c9c6
|
||||
Fichiers :
|
||||
A Docs/Migration/etat/BOSS/COMMUN-22/COMMUN-22-BUILD.md
|
||||
A Docs/Migration/etat/BOSS/COMMUN-23-TESTS.md
|
||||
A Docs/Migration/etat/BOSS/COMMUN-23-BILAN.md
|
||||
A Docs/Migration/etat/BOSS/COMMUN-23/COMMUN-23-BUILD.md
|
||||
Message : COMMUN-22 et 23 : builds d'essai, fiche de tests et bilan (journaux de session locaux, non commités) ; corps `Tickets : COMMUN22-23-T1`
|
||||
Preuve : sans objet (documentation d'essai)
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-20 22:08)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui : bilan COMMUN-23, versement des CHG (F8a, M-Z talons, SET1) puis prépare et lance la vague 11. » (session Big Boss local_104ff22d, 2026-10-20)
|
||||
16
Docs/Migration/etat/REPO/tickets/FIX1-T1.md
Normal file
16
Docs/Migration/etat/REPO/tickets/FIX1-T1.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Ticket FIX1-T1 — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 10) — Date : 2026-10-20 19:41
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : b5feae4
|
||||
CHG / ERR : CHG-381
|
||||
Fichiers :
|
||||
M Plugins/ModdingExtra/Source/ModdingExtra/Private/ModdingExtraBPLibrary.cpp
|
||||
A Docs/Migration/etat/REL/FIX1/FIX1-F6-PRE.md
|
||||
A Docs/Migration/etat/REL/FIX1/FIX1-F6-SPEC.md
|
||||
A Docs/Migration/etat/REL/FIX1/FIX1-F6-IMPL.md
|
||||
A Docs/Migration/etat/REL/FIX1/FIX1-F6-VAL.md
|
||||
Message : FIX1 : sauvegardes des parties redirigées vers Saved/Saves, F6 (CHG-381) ; corps `Tickets : FIX1-T1`
|
||||
Preuve : Docs/Migration/etat/BOSS/COMMUN-21-BILAN.md — .1-.3 et .6 PASS, relevé disque et journal ; FIX1-F6-VAL PASS-STATIC
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-20 19:41)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui : bilan COMMUN-21, versement des CHG (F6, KEY2-IMPL-03) puis prépare et lance la vague 10. » (session Big Boss local_104ff22d, 2026-10-20)
|
||||
18
Docs/Migration/etat/REPO/tickets/FIX1-T2.md
Normal file
18
Docs/Migration/etat/REPO/tickets/FIX1-T2.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Ticket FIX1-T2 — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 11) — Date : 2026-10-20 22:08
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : ad3c9c6
|
||||
CHG / ERR : CHG-383, CHG-384
|
||||
Fichiers :
|
||||
M Source/LifePlay/LPCameraModeSubsystem.cpp
|
||||
M Source/LifePlay/LPDirectControlSubsystem.cpp
|
||||
A Docs/Migration/etat/REL/FIX1/FIX1-F7-PRE.md
|
||||
A Docs/Migration/etat/REL/FIX1/FIX1-F8a-IMPL.md
|
||||
A Docs/Migration/etat/REL/FIX1/FIX1-MES.md
|
||||
A Docs/Migration/etat/REL/FIX1/FIX1-MZ-IMPL.md
|
||||
A Docs/Migration/etat/REL/FIX1/FIX1-MZ2-IMPL.md
|
||||
Message : FIX1 : Aim initialisé (F8a), M-Z respecte la hauteur des talons (CHG-383, CHG-384) ; corps `Tickets : FIX1-T2`
|
||||
Preuve : Docs/Migration/etat/BOSS/COMMUN-23-BILAN.md — .6 et .7 PASS, 0 ligne M-Z, builds à 0 avertissement
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-20 22:08)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui : bilan COMMUN-23, versement des CHG (F8a, M-Z talons, SET1) puis prépare et lance la vague 11. » (session Big Boss local_104ff22d, 2026-10-20)
|
||||
15
Docs/Migration/etat/REPO/tickets/KEY2-T6.md
Normal file
15
Docs/Migration/etat/REPO/tickets/KEY2-T6.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Ticket KEY2-T6 — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 10) — Date : 2026-10-20 19:41
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : b5feae4
|
||||
CHG / ERR : CHG-382
|
||||
Fichiers :
|
||||
M Source/LifePlay/LPKeyboardSubsystem.cpp
|
||||
M Docs/Migration/etat/REL/KEY2/KEY2-TACHES.md
|
||||
A Docs/Migration/etat/REL/KEY2/KEY2-DIAG-03.md
|
||||
A Docs/Migration/etat/REL/KEY2/KEY2-BUILD-04.md
|
||||
Message : KEY2 : confirmation par un second appui avant de remplacer une touche prise (CHG-382) ; corps `Tickets : KEY2-T6`
|
||||
Preuve : Docs/Migration/etat/BOSS/COMMUN-21-BILAN.md — .7-.11 PASS (captures et journal 51/50/51)
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-20 19:41)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui : bilan COMMUN-21, versement des CHG (F6, KEY2-IMPL-03) puis prépare et lance la vague 10. » (session Big Boss local_104ff22d, 2026-10-20)
|
||||
13
Docs/Migration/etat/REPO/tickets/PUB-20261020-T1.md
Normal file
13
Docs/Migration/etat/REPO/tickets/PUB-20261020-T1.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Ticket PUB-20261020-T1 — BRANCHE
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (publication des vagues 7 à 9) — Date : 2026-10-20 17:34
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : b5feae4
|
||||
Fichiers :
|
||||
(aucun : ref locale `pub/ue5.8`)
|
||||
Message : LifePlay UE 5.8 : état de développement au 2026-10-20
|
||||
Tickets : PUB-20261020-T1
|
||||
Preuve : Docs/Migration/etat/REPO/PUB/PUB-20261020-VAL.md — PASS (contrôle de contenu, doc 27) ; sinon ticket refusé
|
||||
PubCheck : `PubCheck -Arbre ue5.8 -Binaires` = 0 (VAL) ; à refaire : `-Arbre pub/ue5.8` = 0 et `-Pointe pub/ue5.8 -Distant origin` = 0
|
||||
Suite : push par l'utilisateur : `git push origin pub/ue5.8:ue5.8` (`--dry-run` d'abord, il exécute le pre-push)
|
||||
Geste : parent = `pub/ue5.8` = `origin/ue5.8` = `8084622` (vérifier les deux, sinon arrêt) ; arbre = `b5feae4^{tree}` (jamais l'index ni le répertoire de travail : LifePlay.uproject et Docs/LP-PROJET.ini locaux ne doivent pas entrer) ; `git commit-tree b5feae4^{tree} -p 8084622 -F <message>` avec l'identité noreply ; `git branch -f pub/ue5.8 <commit>` (ref locale seulement ; ue5.8 non déplacée). Contrôles : `git diff b5feae4 pub/ue5.8` vide ; `git rev-list --count origin/ue5.8..pub/ue5.8` = 1 ; `git merge-base --is-ancestor origin/ue5.8 pub/ue5.8` vrai ; `Docs/Migration/etat/sandbox/DC2/DC2-BUILD.md` absent de l'arbre ; hook pre-push simulé passant pour `pub/ue5.8` et refusant `ue5.8`. Aucun push.
|
||||
Accord utilisateur : « donnes moi la commande de push » puis « On garde le nom forgejo.edujiro5972.fr dans la publication ; prépare pub/ue5.8. » (session Big Boss local_104ff22d, 2026-10-20)
|
||||
11
Docs/Migration/etat/REPO/tickets/PUB-20261020-T2.md
Normal file
11
Docs/Migration/etat/REPO/tickets/PUB-20261020-T2.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Ticket PUB-20261020-T2 — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 10) — Date : 2026-10-20 19:41
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : b5feae4
|
||||
Fichiers :
|
||||
A Docs/Migration/etat/REPO/PUB/PUB-20261020-VAL.md
|
||||
Message : Publication du 2026-10-20 : contrôle de contenu avant push (PASS) ; corps `Tickets : PUB-20261020-T2`
|
||||
Preuve : sans objet (documentation d'essai)
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-20 19:41)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui : bilan COMMUN-21, versement des CHG (F6, KEY2-IMPL-03) puis prépare et lance la vague 10. » (session Big Boss local_104ff22d, 2026-10-20)
|
||||
13
Docs/Migration/etat/REPO/tickets/QPERS-T1.md
Normal file
13
Docs/Migration/etat/REPO/tickets/QPERS-T1.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Ticket QPERS-T1 — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 12) — Date : 2026-10-21 00:16
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : 3b32c5d
|
||||
CHG / ERR : CHG-386
|
||||
Fichiers :
|
||||
M Config/DefaultScalability.ini
|
||||
A Docs/Migration/etat/REL/QPERS/QPERS-PRE.md
|
||||
Message : QPERS : netteté à l'étalonnage aux niveaux High et Epic (CHG-386) ; corps `Tickets : QPERS-T1`
|
||||
Preuve : Docs/Migration/etat/REL/QPERS/QPERS-PRE.md — essai console de l'utilisateur, R2 « un peu plus net »
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-21 00:16)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui, verse le CHG de QPERS et lance la vague 12 ce soir, sans push. » (session Big Boss local_104ff22d, 2026-10-21)
|
||||
19
Docs/Migration/etat/REPO/tickets/REL2-T1.md
Normal file
19
Docs/Migration/etat/REPO/tickets/REL2-T1.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Ticket REL2-T1 — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 13) — Date : 2026-10-21 09:27
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : 0536487
|
||||
CHG / ERR : CHG-387
|
||||
Fichiers :
|
||||
M Config/DefaultGame.ini
|
||||
A Docs/Migration/etat/REL/REL2/REL2-T1-IMPL.md
|
||||
A Docs/Migration/etat/REL/REL2/REL2-VAL.md
|
||||
A Docs/Migration/etat/REL/REL2/REL2-T2-BUILD.md
|
||||
A Docs/Migration/etat/REL/REL2/REL2-ESSAI-FINAL.md
|
||||
A Docs/Migration/etat/REL/REL2/REL2-ESSAI-RESULTAT.md
|
||||
A Docs/Migration/etat/REL/REL2/REL2-releve-R0.csv
|
||||
A Docs/Migration/etat/REL/REL2/REL2-releve-R1.csv
|
||||
Message : REL2 : alpha 2026.10.2.2a, version, VAL commune, build Shipping et essai final 11/11 (CHG-387) ; corps `Tickets : REL2-T1`
|
||||
Preuve : Docs/Migration/etat/REL/REL2/REL2-ESSAI-RESULTAT.md — essai final 11/11 PASS sur le Shipping
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-21 09:28)
|
||||
Suite : publication pub/ue5.8 (push par l'utilisateur), décision de tag v2026.10.2.2a
|
||||
Accord utilisateur : « ok REL2 » (session Big Boss local_104ff22d, 2026-10-21 08:30 ; REL2 = VAL commune, Shipping, essai final, dernière vague, publication, doc 37 l. 172)
|
||||
19
Docs/Migration/etat/REPO/tickets/SET1-T1.md
Normal file
19
Docs/Migration/etat/REPO/tickets/SET1-T1.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Ticket SET1-T1 — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 11) — Date : 2026-10-20 22:08
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : ad3c9c6
|
||||
CHG / ERR : CHG-385
|
||||
Fichiers :
|
||||
M Source/LifePlay/LPSettingsSubsystem.cpp
|
||||
M Source/LifePlay/LPSettingsSubsystem.h
|
||||
M Source/LifePlay/LPColorGradeSubsystem.cpp
|
||||
M Source/LifePlay/LPVideoQualitySubsystem.cpp
|
||||
M Source/LifePlay/LPModInfoSubsystem.cpp
|
||||
A Docs/Migration/etat/REL/SET1/SET1-PRE.md
|
||||
A Docs/Migration/etat/REL/SET1/SET1-V1-IMPL.md
|
||||
A Docs/Migration/etat/REL/SET1/SET1-V1b-IMPL.md
|
||||
Message : SET1 : réglages à onglets aussi en partie, sur le menu affiché (CHG-385) ; corps `Tickets : SET1-T1`
|
||||
Preuve : Docs/Migration/etat/BOSS/COMMUN-23-BILAN.md — .1 à .5 PASS, « onglets poses … (partie) » au journal
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-20 22:08)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui : bilan COMMUN-23, versement des CHG (F8a, M-Z talons, SET1) puis prépare et lance la vague 11. » (session Big Boss local_104ff22d, 2026-10-20)
|
||||
11
Docs/Migration/etat/REPO/tickets/STM1-T6.md
Normal file
11
Docs/Migration/etat/REPO/tickets/STM1-T6.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Ticket STM1-T6 — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 10) — Date : 2026-10-20 19:41
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : b5feae4
|
||||
Fichiers :
|
||||
M Docs/Migration/etat/REL/STM1/STM1-TACHES.md
|
||||
Message : STM1 : suites notées (S5 masque après rechoix de la ville, reports en build 2) ; corps `Tickets : STM1-T6`
|
||||
Preuve : sans objet (documentation d'essai)
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-20 19:41)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui : bilan COMMUN-21, versement des CHG (F6, KEY2-IMPL-03) puis prépare et lance la vague 10. » (session Big Boss local_104ff22d, 2026-10-20)
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# Ticket VAGUE-20261020-10-PARTAGES — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 10) — Date : 2026-10-20 19:41
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : quelconque
|
||||
CHG / ERR : CHG-381, CHG-382
|
||||
Fichiers :
|
||||
M Docs/Journal_Modifications.md
|
||||
M Docs/Migration/etat/REPO/NUMEROS.md
|
||||
M Docs/Migration/etat/BOSS/BOSS-ETAT.md
|
||||
M Docs/Migration/etat/BOSS/BOSS-JOURNAL.md
|
||||
M Docs/Migration/etat/REPO/FILE.md
|
||||
M Docs/Migration/etat/REPO/REPO-JOURNAL.md
|
||||
A Docs/Migration/etat/REPO/tickets/PUB-20261020-T1.md
|
||||
A Docs/Migration/etat/REPO/tickets/FIX1-T1.md
|
||||
A Docs/Migration/etat/REPO/tickets/KEY2-T6.md
|
||||
A Docs/Migration/etat/REPO/tickets/COMMUN21-T1.md
|
||||
A Docs/Migration/etat/REPO/tickets/STM1-T6.md
|
||||
A Docs/Migration/etat/REPO/tickets/PUB-20261020-T2.md
|
||||
A Docs/Migration/etat/REPO/tickets/VAGUE-20261020-10-PARTAGES.md
|
||||
Message : Vague 10 : journal (CHG-381, 382), numéros, publication du 2026-10-20, état de Big Boss, file et journal du dépôt ; corps `Tickets : VAGUE-20261020-10-PARTAGES`
|
||||
Preuve : sans objet (fichiers partagés, W7)
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-20 19:41)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui : bilan COMMUN-21, versement des CHG (F6, KEY2-IMPL-03) puis prépare et lance la vague 10. » (session Big Boss local_104ff22d, 2026-10-20)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# Ticket VAGUE-20261020-11-PARTAGES — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 11) — Date : 2026-10-20 22:08
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : quelconque
|
||||
CHG / ERR : CHG-383, CHG-384, CHG-385
|
||||
Fichiers :
|
||||
M Docs/Journal_Modifications.md
|
||||
M Docs/Migration/etat/REPO/NUMEROS.md
|
||||
M Docs/Migration/etat/BOSS/BOSS-ETAT.md
|
||||
M Docs/Migration/etat/BOSS/BOSS-JOURNAL.md
|
||||
M Docs/Migration/etat/REPO/FILE.md
|
||||
M Docs/Migration/etat/REPO/REPO-JOURNAL.md
|
||||
A Docs/Migration/etat/REPO/tickets/FIX1-T2.md
|
||||
A Docs/Migration/etat/REPO/tickets/SET1-T1.md
|
||||
A Docs/Migration/etat/REPO/tickets/COMMUN22-23-T1.md
|
||||
A Docs/Migration/etat/REPO/tickets/VAGUE-20261020-11-PARTAGES.md
|
||||
Message : Vague 11 : journal (CHG-383, 384, 385), numéros, état de Big Boss, file et journal du dépôt ; corps `Tickets : VAGUE-20261020-11-PARTAGES`
|
||||
Preuve : sans objet (fichiers partagés, W7)
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-20 22:08)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui : bilan COMMUN-23, versement des CHG (F8a, M-Z talons, SET1) puis prépare et lance la vague 11. » (session Big Boss local_104ff22d, 2026-10-20)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# Ticket VAGUE-20261021-12-PARTAGES — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 12) — Date : 2026-10-21 00:16
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : quelconque
|
||||
CHG / ERR : CHG-386
|
||||
Fichiers :
|
||||
M Docs/Journal_Modifications.md
|
||||
M Docs/Migration/etat/REPO/NUMEROS.md
|
||||
M Docs/Migration/etat/BOSS/BOSS-ETAT.md
|
||||
M Docs/Migration/etat/BOSS/BOSS-JOURNAL.md
|
||||
M Docs/Migration/etat/REPO/FILE.md
|
||||
M Docs/Migration/etat/REPO/REPO-JOURNAL.md
|
||||
A Docs/Migration/etat/REPO/tickets/QPERS-T1.md
|
||||
A Docs/Migration/etat/REPO/tickets/BUILD2-PRE-T1.md
|
||||
A Docs/Migration/etat/REPO/tickets/VAGUE-20261021-12-PARTAGES.md
|
||||
Message : Vague 12 : journal (CHG-386), numéros, reprise du 2026-10-21, file et journal du dépôt ; corps `Tickets : VAGUE-20261021-12-PARTAGES`
|
||||
Preuve : sans objet (fichiers partagés, W7)
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-21 00:16)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « Oui, verse le CHG de QPERS et lance la vague 12 ce soir, sans push. » (session Big Boss local_104ff22d, 2026-10-21)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# Ticket VAGUE-20261021-13-PARTAGES — COMMIT
|
||||
Statut : fait
|
||||
Demandeur : Big Boss (vague 13) — Date : 2026-10-21 09:27
|
||||
Dépôt : D:\Game\LifePlay-master 5.8 — Branche attendue : ue5.8 — HEAD attendu : quelconque
|
||||
CHG / ERR : CHG-387
|
||||
Fichiers :
|
||||
M Docs/Journal_Modifications.md
|
||||
M Docs/Migration/etat/REPO/NUMEROS.md
|
||||
M Docs/Migration/etat/BOSS/BOSS-ETAT.md
|
||||
M Docs/Migration/etat/BOSS/BOSS-JOURNAL.md
|
||||
M Docs/Migration/etat/REPO/FILE.md
|
||||
M Docs/Migration/etat/REPO/REPO-JOURNAL.md
|
||||
A Docs/Migration/etat/REPO/tickets/REL2-T1.md
|
||||
A Docs/Migration/etat/REPO/tickets/BUILD2-PRE-T2.md
|
||||
A Docs/Migration/etat/REPO/tickets/VAGUE-20261021-13-PARTAGES.md
|
||||
Message : Vague 13 : journal (CHG-387), numéros, état de Big Boss, file et journal du dépôt ; corps `Tickets : VAGUE-20261021-13-PARTAGES`
|
||||
Preuve : sans objet (fichiers partagés, W7)
|
||||
PubCheck : 0 (Big Boss, -Fichiers sur la liste du ticket, 2026-10-21 09:28)
|
||||
Suite : aucune
|
||||
Accord utilisateur : « ok REL2 » (session Big Boss local_104ff22d, 2026-10-21 08:30 ; REL2 = VAL commune, Shipping, essai final, dernière vague, publication, doc 37 l. 172)
|
||||
|
|
@ -12,6 +12,8 @@
|
|||
#include "Modules/ModuleManager.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "Misc/CommandLine.h"
|
||||
#include "Misc/Parse.h"
|
||||
#if !UE_BUILD_SHIPPING
|
||||
#include "ProfilingDebugging/CpuProfilerTrace.h"
|
||||
#endif
|
||||
|
|
@ -26,6 +28,117 @@
|
|||
// - Un echec d'ecriture est toujours signale en Warning.
|
||||
DEFINE_LOG_CATEGORY_STATIC(LogModdingExtra, Log, All);
|
||||
|
||||
// Lot FIX1-F6 (Docs/Migration/etat/REL/FIX1/FIX1-F6-SPEC.md, ERR-042) : fichiers de partie hors du dossier du jeu.
|
||||
// Un chemin relatif a Content qui commence par "Saves/" est lu et ecrit sous FPaths::ProjectSavedDir() + "Saves/..."
|
||||
// (dossier de sauvegarde, -UserDir du lot REL-SAV compris). Lecture : repli sur l'ancien Content/Saves, par slot,
|
||||
// tant que le slot n'existe pas dans la nouvelle racine ; jamais pour _session. Ecriture : toujours la nouvelle racine.
|
||||
// Tout autre chemin : inchange. -LPNoSavesRedirect retablit l'ancien comportement. Thread de jeu seulement.
|
||||
namespace LPSavesRedirect
|
||||
{
|
||||
static int32 NewReads = 0, OldReads = 0, Writes = 0;
|
||||
|
||||
static bool IsDisabled()
|
||||
{
|
||||
static const bool bDisabled = FParse::Param(FCommandLine::Get(), TEXT("LPNoSavesRedirect"));
|
||||
return bDisabled;
|
||||
}
|
||||
|
||||
// Vrai si le chemin vise Saves/. OutRel : separateurs '/', sans '/' de tete. OutSlot : segment qui suit "Saves/"
|
||||
// (vide pour un fichier pose directement dans Saves/).
|
||||
static bool Match(const FString& ContentRelativePath, FString& OutRel, FString& OutSlot)
|
||||
{
|
||||
OutRel = ContentRelativePath;
|
||||
OutRel.ReplaceInline(TEXT("\\"), TEXT("/"));
|
||||
while (OutRel.StartsWith(TEXT("/")))
|
||||
{
|
||||
OutRel = OutRel.Mid(1);
|
||||
}
|
||||
if (!OutRel.StartsWith(TEXT("Saves/"), ESearchCase::IgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const FString AfterSaves = OutRel.Mid(6);
|
||||
int32 Slash = INDEX_NONE;
|
||||
OutSlot = AfterSaves.FindChar(TEXT('/'), Slash) ? AfterSaves.Left(Slash) : FString();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Journal : une ligne au premier acces redirige, puis une par slot et par racine ; compteurs pour le bilan.
|
||||
static void Note(const FString& Slot, bool bOld, bool bWrite)
|
||||
{
|
||||
static bool bFirst = true;
|
||||
if (bFirst)
|
||||
{
|
||||
bFirst = false;
|
||||
UE_LOG(LogModdingExtra, Display, TEXT("Saves redirige : racine '%s' (repli de lecture par slot : '%s')"),
|
||||
*FPaths::ConvertRelativePathToFull(FPaths::ProjectSavedDir() + TEXT("Saves")),
|
||||
*FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir() + TEXT("Saves")));
|
||||
}
|
||||
if (bWrite) { ++Writes; } else if (bOld) { ++OldReads; } else { ++NewReads; }
|
||||
static TSet<FString> Seen;
|
||||
bool bAlready = false;
|
||||
Seen.Add(FString(bOld ? TEXT("ancien|") : TEXT("nouveau|")) + Slot.ToLower(), &bAlready);
|
||||
if (!bAlready)
|
||||
{
|
||||
UE_LOG(LogModdingExtra, Display, TEXT("Saves slot '%s' : %s"), *Slot,
|
||||
bOld ? TEXT("lu dans l'ancien Content/Saves (repli)") : TEXT("nouvelle racine"));
|
||||
}
|
||||
}
|
||||
|
||||
// Chemin a passer a FFileHelper. Hors Saves/ : ProjectContentDir() + chemin, exactement comme avant F6.
|
||||
static FString ResolvePath(const FString& ContentRelativePath, bool bForWrite)
|
||||
{
|
||||
FString Rel, Slot;
|
||||
if (!Match(ContentRelativePath, Rel, Slot))
|
||||
{
|
||||
return FPaths::ProjectContentDir() + ContentRelativePath;
|
||||
}
|
||||
if (IsDisabled())
|
||||
{
|
||||
static bool bLogged = false;
|
||||
if (!bLogged)
|
||||
{
|
||||
bLogged = true;
|
||||
UE_LOG(LogModdingExtra, Display, TEXT("Saves non redirige (-LPNoSavesRedirect) : ancien chemin Content/Saves"));
|
||||
}
|
||||
return FPaths::ProjectContentDir() + ContentRelativePath;
|
||||
}
|
||||
const FString NewPath = FPaths::ProjectSavedDir() + Rel;
|
||||
if (bForWrite || Slot.IsEmpty() || Slot.Equals(TEXT("_session"), ESearchCase::IgnoreCase))
|
||||
{
|
||||
Note(Slot, false, bForWrite);
|
||||
return NewPath;
|
||||
}
|
||||
IFileManager& FileManager = IFileManager::Get();
|
||||
if (!FileManager.DirectoryExists(*(FPaths::ProjectSavedDir() + TEXT("Saves/") + Slot))
|
||||
&& FileManager.DirectoryExists(*(FPaths::ProjectContentDir() + TEXT("Saves/") + Slot)))
|
||||
{
|
||||
Note(Slot, true, false);
|
||||
return FPaths::ProjectContentDir() + Rel;
|
||||
}
|
||||
Note(Slot, false, false);
|
||||
return NewPath;
|
||||
}
|
||||
|
||||
// Les listes (GetAllFilesFromFolder, GetAllSubfolders) ne sont pas redirigees : signaler un usage sur Saves.
|
||||
static void WarnListOnSaves(const TCHAR* Function, const FString& RootFolder)
|
||||
{
|
||||
FString Rel, Slot;
|
||||
if (!Match(RootFolder + TEXT("/"), Rel, Slot))
|
||||
{
|
||||
return;
|
||||
}
|
||||
static TSet<FString> Warned;
|
||||
bool bAlready = false;
|
||||
Warned.Add(FString(Function) + TEXT("|") + Rel.ToLower(), &bAlready);
|
||||
if (!bAlready)
|
||||
{
|
||||
UE_LOG(LogModdingExtra, Warning, TEXT("%s | '%s' : liste lue dans Content, Saves non redirige pour les listes (FIX1-F6)"),
|
||||
Function, *RootFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UModdingExtraBPLibrary::UModdingExtraBPLibrary(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
|
|
@ -40,6 +153,7 @@ float UModdingExtraBPLibrary::ModdingExtraSampleFunction(float Param)
|
|||
bool UModdingExtraBPLibrary::GetAllFilesFromFolder(TArray<FString>& Files, FString RootFolderFullPath, FString Ext)
|
||||
{
|
||||
if(RootFolderFullPath.Len() < 1) return false;
|
||||
LPSavesRedirect::WarnListOnSaves(TEXT("GetAllFilesFromFolder"), RootFolderFullPath);
|
||||
|
||||
// FPaths::NormalizeDirectoryName(RootFolderFullPath);
|
||||
|
||||
|
|
@ -114,6 +228,7 @@ float UModdingExtraBPLibrary::ModdingExtraSampleFunction(float Param)
|
|||
bool UModdingExtraBPLibrary::GetAllSubfolders(TArray<FString>& Folders, FString RootFolderFullPath)
|
||||
{
|
||||
if(RootFolderFullPath.Len() < 1) return false;
|
||||
LPSavesRedirect::WarnListOnSaves(TEXT("GetAllSubfolders"), RootFolderFullPath);
|
||||
|
||||
IFileManager& FileManager = IFileManager::Get();
|
||||
|
||||
|
|
@ -151,6 +266,9 @@ namespace LPLoadTxtStats
|
|||
}
|
||||
UE_LOG(LogModdingExtra, Display, TEXT(" %-14s %6d appel(s) | %5d fichier(s) | %6d relecture(s) | %8.1f Ko | %7.3f s (premier appel a %.1f s, dernier a %.1f s)"),
|
||||
TEXT("TOTAL"), Calls, Files, Rereads, Bytes / 1024.0, Seconds, FirstCall, LastCall);
|
||||
UE_LOG(LogModdingExtra, Display, TEXT(" Saves : %d lecture(s) nouvelle racine | %d lecture(s) repli | %d ecriture(s)%s"),
|
||||
LPSavesRedirect::NewReads, LPSavesRedirect::OldReads, LPSavesRedirect::Writes,
|
||||
LPSavesRedirect::IsDisabled() ? TEXT(" (redirection desactivee)") : TEXT(""));
|
||||
}
|
||||
|
||||
static FAutoConsoleCommand Command(TEXT("ModdingExtra.LoadTxtStats"), TEXT("Bilan des lectures LoadTxt par type de fichier."),
|
||||
|
|
@ -187,7 +305,7 @@ namespace LPLoadTxtStats
|
|||
// Couche de donnees (etapes 2 et 3) : fichiers de Modules servis depuis la memoire quand le cache est pret.
|
||||
FLPDataCache& Cache = FLPDataCache::Get();
|
||||
const bool bFromCache = Cache.TryGet(FileNameA, SaveTextA);
|
||||
const bool bOk = bFromCache || FFileHelper::LoadFileToString(SaveTextA, *(FPaths::ProjectContentDir() + FileNameA));
|
||||
const bool bOk = bFromCache || FFileHelper::LoadFileToString(SaveTextA, *LPSavesRedirect::ResolvePath(FileNameA, false));
|
||||
LPLoadTxtStats::Record(FileNameA, SaveTextA.Len(), FPlatformTime::Seconds() - StartTime, bFromCache);
|
||||
if (bFromCache && Cache.IsVerifyEnabled())
|
||||
{
|
||||
|
|
@ -233,7 +351,7 @@ namespace LPLoadTxtStats
|
|||
|
||||
bool UModdingExtraBPLibrary::SaveTxt(FString SaveTextB, FString FileNameB)
|
||||
{
|
||||
const bool bOk = FFileHelper::SaveStringToFile(SaveTextB, *(FPaths::ProjectContentDir() + FileNameB));
|
||||
const bool bOk = FFileHelper::SaveStringToFile(SaveTextB, *LPSavesRedirect::ResolvePath(FileNameB, true));
|
||||
if (bOk)
|
||||
{
|
||||
FLPDataCache::Get().OnWritten(FileNameB, SaveTextB);
|
||||
|
|
|
|||
|
|
@ -2275,7 +2275,7 @@ bool ULPCameraModeSubsystem::TickCoupleMouse(UGameInstance* GI, APlayerControlle
|
|||
const UPrimitiveComponent* GrabSurface = nullptr;
|
||||
bGrabHasHeight = TraceDown(Pivot, SurfaceZ, GrabSurface);
|
||||
GrabHeight = bGrabHasHeight ? LPCameraModeLocal::CoupleLowestRoot(Couple) - SurfaceZ : 0.0;
|
||||
FVector Aim;
|
||||
FVector Aim = FVector::ZeroVector;
|
||||
GrabOffset = TraceScreen(GrabMouseStart, Aim) ? FVector(Pivot.X - Aim.X, Pivot.Y - Aim.Y, 0.0) : FVector::ZeroVector;
|
||||
UE_LOG(LogLifePlay, Log, TEXT("Sexe : couple pris (%s) a (%.0f, %.0f, %.0f), racine a %s de la surface %s"),
|
||||
CoupleGrabMode == 1 ? TEXT("deplacement") : TEXT("rotation"), Pivot.X, Pivot.Y, Pivot.Z,
|
||||
|
|
@ -2366,7 +2366,7 @@ bool ULPCameraModeSubsystem::TickCoupleMouse(UGameInstance* GI, APlayerControlle
|
|||
if (CoupleGrabMode == 1)
|
||||
{
|
||||
bGrabMoved |= FVector2D::Distance(GrabMouseStart, GrabCursor) >= LPCameraModeLocal::CoupleDragThreshold;
|
||||
FVector Aim;
|
||||
FVector Aim = FVector::ZeroVector;
|
||||
const bool bAim = bGrabMoved && TraceScreen(GrabCursor, Aim);
|
||||
if (bGrabMoved && !bAim && !bGrabAimWarned)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "Engine/PostProcessVolume.h"
|
||||
#include "Engine/World.h"
|
||||
#include "LifePlay.h"
|
||||
#include "LPSettingsSubsystem.h"
|
||||
#include "Misc/ConfigCacheIni.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "Styling/CoreStyle.h"
|
||||
|
|
@ -256,22 +257,11 @@ USlider* ULPColorGradeSubsystem::AddRow(UScrollBox* Scroll, const TCHAR* Name, c
|
|||
|
||||
void ULPColorGradeSubsystem::EnsureControls()
|
||||
{
|
||||
UScrollBox* Scroll = nullptr;
|
||||
for (TObjectIterator<UScrollBox> It; It; ++It)
|
||||
{
|
||||
UScrollBox* Candidate = *It;
|
||||
if (!Candidate || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const UUserWidget* Owner = Candidate->GetTypedOuter<UUserWidget>();
|
||||
if (!Owner || Owner->HasAnyFlags(RF_ClassDefaultObject) || Owner->GetGameInstance() != GetGameInstance())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Scroll = Candidate;
|
||||
break;
|
||||
}
|
||||
// SET1-V1b : la liste de l'instance de MainMenu qui est a l'ecran, pas la premiere trouvee (une ancienne instance,
|
||||
// retiree du viewport et pas encore collectee, vient souvent avant). Aucune a l'ecran : rien a faire. Pas d'etat par
|
||||
// instance a remettre a zero : la presence de LPColorBrightness se lit sur les enfants de la liste choisie, et AddRow
|
||||
// rebranche les afficheurs de valeur (BrightnessValue...) sur les lignes de cette liste.
|
||||
UScrollBox* Scroll = ULPSettingsSubsystem::FindOnScreenSettingsList(GetGameInstance());
|
||||
if (!Scroll)
|
||||
{
|
||||
return;
|
||||
|
|
@ -320,6 +310,8 @@ void ULPColorGradeSubsystem::EnsureControls()
|
|||
{
|
||||
Readout->SetText(FText::FromString(LPColorGrade::FormatValue(Tint, 2)));
|
||||
}
|
||||
const UUserWidget* Menu = Scroll->GetTypedOuter<UUserWidget>();
|
||||
UE_LOG(LogLifePlay, Display, TEXT("Couleur : reglages de couleur ajoutes sur %s"), Menu ? *Menu->GetName() : TEXT("?"));
|
||||
}
|
||||
|
||||
void ULPColorGradeSubsystem::OnBrightnessChanged(float Value)
|
||||
|
|
|
|||
|
|
@ -151,6 +151,47 @@ namespace
|
|||
return Prop ? Cast<AActor>(Prop->GetObjectPropertyValue_InContainer(Object)) : nullptr;
|
||||
}
|
||||
|
||||
// FIX1-MZ (instrumentation de la ligne M-Z, lecture seule) : formule de Person::updateHeelHeight, Z relatif du maillage =
|
||||
// -90 + 12 x HeelHeight (L6f_dump_Person.txt:19818-19827, A='-90.000000', B='12.000000').
|
||||
constexpr double MZHeelBaseZ = -90.0;
|
||||
constexpr double MZHeelFactor = 12.0;
|
||||
|
||||
// Variable Blueprint numerique lue par reflexion (HeelHeight est un double : Conv_StringToDouble, L6f_dump_Person.txt:19774-19781).
|
||||
// Faux si la variable est introuvable ou non numerique : aucun journal, l'appelant ecrit "?".
|
||||
bool MZReadNumber(const UObject* Object, const TCHAR* Name, double& OutValue)
|
||||
{
|
||||
const FNumericProperty* Prop = Object ? CastField<FNumericProperty>(Object->GetClass()->FindPropertyByName(Name)) : nullptr;
|
||||
if (!Prop)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const void* Data = Prop->ContainerPtrToValuePtr<void>(Object);
|
||||
if (Prop->IsFloatingPoint())
|
||||
{
|
||||
OutValue = Prop->GetFloatingPointPropertyValue(Data);
|
||||
return true;
|
||||
}
|
||||
if (Prop->IsInteger())
|
||||
{
|
||||
OutValue = static_cast<double>(Prop->GetSignedIntPropertyValue(Data));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Nom de l'objet d'une variable Blueprint objet (currentAnimation) : "?" si la variable est introuvable, "-" si elle est vide
|
||||
// (meme convention de vide que ReadObjectName de LPDebugSubsystem.cpp).
|
||||
FString MZReadObjectName(const UObject* Object, const TCHAR* Name)
|
||||
{
|
||||
const FObjectPropertyBase* Prop = Object ? CastField<FObjectPropertyBase>(Object->GetClass()->FindPropertyByName(Name)) : nullptr;
|
||||
if (!Prop)
|
||||
{
|
||||
return TEXT("?");
|
||||
}
|
||||
const UObject* Value = Prop->GetObjectPropertyValue_InContainer(Object);
|
||||
return Value ? Value->GetName() : FString(TEXT("-"));
|
||||
}
|
||||
|
||||
bool KeyDown(const APlayerController* PC, const FKey& Key)
|
||||
{
|
||||
return PC && PC->IsInputKeyDown(Key);
|
||||
|
|
@ -1198,23 +1239,35 @@ void ULPDirectControlSubsystem::FitPersonBounds(float DeltaTime)
|
|||
MeasuredSeats.Remove(Person);
|
||||
}
|
||||
// M-Z (STG-COMMUN9-DIAG) : une place feminine releve le maillage (-80,4 au lieu de -90) et rien ne le redescend au lever ; la
|
||||
// Person debout flotte. Debout (aucun meuble), hors sexe et hors scene, capsule en collision, maillage hors de la hauteur relative
|
||||
// du gabarit de sa classe (CDO) depuis 2 balayages (1 s) : on remet la hauteur du gabarit (X et Y inchanges).
|
||||
// Person debout flotte. Debout (aucun meuble), hors sexe et hors scene, capsule en collision, maillage hors de sa hauteur relative
|
||||
// cible depuis 2 balayages (1 s) : on remet cette hauteur (X et Y inchanges).
|
||||
// FIX1-MZ2 : la cible est -90 + 12 x HeelHeight (Person::updateHeelHeight, L6f_dump_Person.txt:19818-19827), pas le -90 seul : en
|
||||
// talons (-80,4 pour 0,8) le maillage est deja a sa hauteur voulue et M-Z ne se declenche plus. HeelHeight illisible ou non
|
||||
// fini : la cible reste la hauteur relative du gabarit de la classe (CDO), comme avant.
|
||||
const ACharacter* Template = Person->GetClass()->GetDefaultObject<ACharacter>();
|
||||
const USkeletalMeshComponent* TemplateBody = Template ? Template->GetMesh() : nullptr;
|
||||
const UCapsuleComponent* Capsule = Person->GetCapsuleComponent();
|
||||
const double TemplateZ = TemplateBody ? TemplateBody->GetRelativeLocation().Z : 0.0;
|
||||
double HeelHeight = 0.0;
|
||||
const bool bHeelRead = MZReadNumber(Person, TEXT("HeelHeight"), HeelHeight) && FMath::IsFinite(HeelHeight);
|
||||
const double TargetZ = bHeelRead ? MZHeelBaseZ + MZHeelFactor * HeelHeight : TemplateZ;
|
||||
// "(talons)" seulement si la cible vient de talons reels (HeelHeight non nul) : sans talons la ligne reste celle d'avant.
|
||||
const bool bHeelTarget = bHeelRead && !FMath::IsNearlyZero(HeelHeight);
|
||||
const FVector Relative = Body->GetRelativeLocation();
|
||||
if (TemplateBody && !bSceneRunning && !IsValid(Seat) && Capsule && Capsule->GetCollisionEnabled() != ECollisionEnabled::NoCollision
|
||||
&& FMath::Abs(Relative.Z - TemplateZ) > 1.0)
|
||||
&& FMath::Abs(Relative.Z - TargetZ) > 1.0)
|
||||
{
|
||||
int32& Scans = MeshZScans.FindOrAdd(Person);
|
||||
if (++Scans >= 2)
|
||||
{
|
||||
Body->SetRelativeLocation(FVector(Relative.X, Relative.Y, TemplateZ));
|
||||
Body->SetRelativeLocation(FVector(Relative.X, Relative.Y, TargetZ));
|
||||
MeshZScans.Remove(Person);
|
||||
UE_LOG(LogLifePlay, Display, TEXT("M-Z : %s maillage relatif Z %.1f -> %.1f (gabarit %s), debout sans meuble"),
|
||||
*Person->GetName(), Relative.Z, TemplateZ, *Person->GetClass()->GetName());
|
||||
// FIX1-MZ : champs de diagnostic (F8b), lus apres la correction. "?" = variable introuvable.
|
||||
const FString HeelText = bHeelRead ? FString::Printf(TEXT("%.3f"), HeelHeight) : FString(TEXT("?"));
|
||||
const FString HeelZText = bHeelRead ? FString::Printf(TEXT("%.2f"), MZHeelBaseZ + MZHeelFactor * HeelHeight) : FString(TEXT("?"));
|
||||
UE_LOG(LogLifePlay, Display, TEXT("M-Z : %s maillage relatif Z %.1f -> %.1f%s (gabarit %s), debout sans meuble ; HeelHeight=%s ; currentAnimation=%s ; -90+12*HeelHeight=%s"),
|
||||
*Person->GetName(), Relative.Z, TargetZ, bHeelTarget ? TEXT(" (talons)") : TEXT(""), *Person->GetClass()->GetName(),
|
||||
*HeelText, *MZReadObjectName(Person, TEXT("currentAnimation")), *HeelZText);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -112,6 +112,12 @@ namespace
|
|||
TSharedPtr<class SLPKeyboardMenu> Menu;
|
||||
TSharedPtr<IInputProcessor> Processor;
|
||||
bool bEmbedded = false;
|
||||
// KEY2-IMPL-03 (KEY2-DIAG-03, option 1) : touche deja prise ailleurs, en attente d'un second appui qui la remplace.
|
||||
FKey ConfirmKey;
|
||||
bool bConfirmShift = false;
|
||||
bool bConfirmCtrl = false;
|
||||
bool bConfirmAlt = false;
|
||||
bool bConfirmCmd = false;
|
||||
};
|
||||
|
||||
bool IsRemappable(const FKey& Key)
|
||||
|
|
@ -720,8 +726,9 @@ namespace
|
|||
PendingModifier = EKeys::Invalid;
|
||||
Sub->CancelWait();
|
||||
}
|
||||
else if (!Key.IsModifierKey())
|
||||
else if (!Key.IsModifierKey() && !Event.IsRepeat())
|
||||
{
|
||||
// KEY2-IMPL-03 : la repetition d'une touche tenue ne compte pas comme le second appui de confirmation.
|
||||
PendingModifier = EKeys::Invalid;
|
||||
Sub->CommitKey(Key, Event.IsShiftDown(), Event.IsControlDown(), Event.IsAltDown(), Event.IsCommandDown());
|
||||
}
|
||||
|
|
@ -958,6 +965,7 @@ void ULPKeyboardSubsystem::BeginWait(FName Name, bool bAxis, float Scale, FKey O
|
|||
bWaitCtrl = bCtrl;
|
||||
bWaitAlt = bAlt;
|
||||
bWaitCmd = bCmd;
|
||||
Live().ConfirmKey = EKeys::Invalid;
|
||||
Status = bAdd
|
||||
? FString::Printf(TEXT("New key for %s. Escape cancels."), bAxis ? *AxisLabel(Name, Scale) : *ActionLabel(Name))
|
||||
: FString::Printf(TEXT("Replaces %s. Escape cancels."), *OldKey.GetDisplayName().ToString());
|
||||
|
|
@ -966,6 +974,7 @@ void ULPKeyboardSubsystem::BeginWait(FName Name, bool bAxis, float Scale, FKey O
|
|||
void ULPKeyboardSubsystem::CancelWait()
|
||||
{
|
||||
bWaiting = false;
|
||||
Live().ConfirmKey = EKeys::Invalid;
|
||||
Status = TEXT("Capture cancelled.");
|
||||
RefreshMenu();
|
||||
}
|
||||
|
|
@ -984,6 +993,43 @@ bool ULPKeyboardSubsystem::CommitKey(const FKey& Key, bool bShift, bool bCtrl, b
|
|||
{
|
||||
return false;
|
||||
}
|
||||
// KEY2-IMPL-03 (KEY2-DIAG-03, option 1, decision « 1 ») : si la touche est deja prise par une autre action ou un
|
||||
// autre axe, rien n'est ecrit ; la ligne d'etat avertit et la capture continue. Le meme appui une seconde fois
|
||||
// remplace, Echap annule. Une autre liaison de la meme action ou du meme sens d'axe ne compte pas.
|
||||
TArray<FString> Taken;
|
||||
for (const FInputActionKeyMapping& Map : Settings->GetActionMappings())
|
||||
{
|
||||
if (Map.Key == Key && Map.bShift == bShift && Map.bCtrl == bCtrl && Map.bAlt == bAlt && Map.bCmd == bCmd
|
||||
&& (bWaitAxis || Map.ActionName != WaitName))
|
||||
{
|
||||
Taken.AddUnique(ActionLabel(Map.ActionName));
|
||||
}
|
||||
}
|
||||
for (const FInputAxisKeyMapping& Map : Settings->GetAxisMappings())
|
||||
{
|
||||
if (Map.Key == Key && !bShift && !bCtrl && !bAlt && !bCmd
|
||||
&& !(bWaitAxis && Map.AxisName == WaitName && (Map.Scale >= 0.f) == (WaitScale >= 0.f)))
|
||||
{
|
||||
Taken.AddUnique(AxisLabel(Map.AxisName, Map.Scale));
|
||||
}
|
||||
}
|
||||
FLiveKeyboard& Confirm = Live();
|
||||
const bool bConfirmed = Confirm.ConfirmKey == Key && Confirm.bConfirmShift == bShift && Confirm.bConfirmCtrl == bCtrl
|
||||
&& Confirm.bConfirmAlt == bAlt && Confirm.bConfirmCmd == bCmd;
|
||||
if (Taken.Num() > 0 && !bConfirmed)
|
||||
{
|
||||
Confirm.ConfirmKey = Key;
|
||||
Confirm.bConfirmShift = bShift;
|
||||
Confirm.bConfirmCtrl = bCtrl;
|
||||
Confirm.bConfirmAlt = bAlt;
|
||||
Confirm.bConfirmCmd = bCmd;
|
||||
bWaiting = true;
|
||||
Status = FString::Printf(TEXT("%s is used by %s. Press it again to replace, Escape to cancel."),
|
||||
*ChordText(Key, bShift, bCtrl, bAlt, bCmd), *FString::Join(Taken, TEXT(", ")));
|
||||
RefreshMenu();
|
||||
return false;
|
||||
}
|
||||
Confirm.ConfirmKey = EKeys::Invalid;
|
||||
TArray<FString> Cleared;
|
||||
if (!bWaitAdd && WaitOldKey.IsValid())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "LifePlay.h"
|
||||
#include "LPDataCompat.h"
|
||||
#include "LPModGuard.h"
|
||||
#include "LPSettingsSubsystem.h"
|
||||
#include "Misc/EngineVersion.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Misc/Paths.h"
|
||||
|
|
@ -239,22 +240,10 @@ bool ULPModInfoSubsystem::Tick(float DeltaTime)
|
|||
|
||||
void ULPModInfoSubsystem::EnsureSettingsRows()
|
||||
{
|
||||
UScrollBox* Scroll = nullptr;
|
||||
for (TObjectIterator<UScrollBox> It; It; ++It)
|
||||
{
|
||||
UScrollBox* Candidate = *It;
|
||||
if (!Candidate || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const UUserWidget* Owner = Candidate->GetTypedOuter<UUserWidget>();
|
||||
if (!Owner || Owner->HasAnyFlags(RF_ClassDefaultObject) || Owner->GetGameInstance() != GetGameInstance())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Scroll = Candidate;
|
||||
break;
|
||||
}
|
||||
// SET1-V1b : la liste de l'instance de MainMenu qui est a l'ecran, pas la premiere trouvee (une ancienne instance,
|
||||
// retiree du viewport et pas encore collectee, vient souvent avant). Aucune a l'ecran : rien a faire. Pas d'etat par
|
||||
// instance a remettre a zero : la presence de LPModCheckEngine se lit sur les enfants de la liste choisie.
|
||||
UScrollBox* Scroll = ULPSettingsSubsystem::FindOnScreenSettingsList(GetGameInstance());
|
||||
if (!Scroll)
|
||||
{
|
||||
return;
|
||||
|
|
@ -310,9 +299,10 @@ void ULPModInfoSubsystem::EnsureSettingsRows()
|
|||
Slot->SetPadding(FMargin(0.f, 0.f, 0.f, 10.f));
|
||||
}
|
||||
}
|
||||
UE_LOG(LogLifePlay, Display, TEXT("Modules : cases de controle des mods ajoutees a Settings > Misc (moteur %d, version min %d, version max %d)"),
|
||||
const UUserWidget* Menu = Scroll->GetTypedOuter<UUserWidget>();
|
||||
UE_LOG(LogLifePlay, Display, TEXT("Modules : cases de controle des mods ajoutees a Settings > Misc (moteur %d, version min %d, version max %d) sur %s"),
|
||||
FLPModGuard::GetSavedCheck(ELPModCheck::Engine) ? 1 : 0, FLPModGuard::GetSavedCheck(ELPModCheck::MinVersion) ? 1 : 0,
|
||||
FLPModGuard::GetSavedCheck(ELPModCheck::MaxVersion) ? 1 : 0);
|
||||
FLPModGuard::GetSavedCheck(ELPModCheck::MaxVersion) ? 1 : 0, Menu ? *Menu->GetName() : TEXT("?"));
|
||||
}
|
||||
|
||||
bool ULPModInfoSubsystem::TickModManager(float DeltaTime)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "Styling/CoreStyle.h"
|
||||
#include "Styling/SlateTypes.h"
|
||||
#include "UObject/TextProperty.h"
|
||||
#include "Widgets/SNullWidget.h"
|
||||
|
||||
namespace LPSettingsUi
|
||||
{
|
||||
|
|
@ -102,6 +103,99 @@ namespace LPSettingsUi
|
|||
return Visibility != ESlateVisibility::Collapsed && Visibility != ESlateVisibility::Hidden;
|
||||
}
|
||||
|
||||
// Lot SET1-V1. GI.CreateMainMenuWidget cree un MainMenu neuf a chaque ouverture (CreateWidget + AddToViewport) et
|
||||
// GI.ClearMainMenuWidget le retire seulement du viewport (RemoveFromParent) : les anciennes instances gardent leur
|
||||
// SettingsScrollBox en memoire jusqu'au ramasse-miettes. Seule l'instance a l'ecran compte.
|
||||
bool IsUsableObject(const UObject* Object)
|
||||
{
|
||||
return IsValid(Object) && !Object->HasAnyFlags(RF_BeginDestroyed | RF_FinishDestroyed);
|
||||
}
|
||||
|
||||
// Menu vivant, ajoute au viewport (UWidget::IsInViewport : AddToViewport ou AddToPlayerScreen) et visible.
|
||||
bool IsMenuOnScreen(const UUserWidget* Menu)
|
||||
{
|
||||
return IsUsableObject(Menu) && Menu->IsInViewport() && IsOpen(Menu);
|
||||
}
|
||||
|
||||
// Liste des reglages de l'instance de MainMenu qui est a l'ecran, nulle s'il n'y en a aucune. A egalite entre deux
|
||||
// instances a l'ecran : la liste ouverte d'abord, puis celle deja suivie (Current).
|
||||
UScrollBox* FindOnScreenSettingsList(const UGameInstance* GI, const UScrollBox* Current)
|
||||
{
|
||||
UScrollBox* Best = nullptr;
|
||||
int32 BestScore = -1;
|
||||
for (TObjectIterator<UScrollBox> It; It; ++It)
|
||||
{
|
||||
UScrollBox* Candidate = *It;
|
||||
if (!IsUsableObject(Candidate) || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const UUserWidget* MenuOwner = Candidate->GetTypedOuter<UUserWidget>();
|
||||
if (!MenuOwner || MenuOwner->HasAnyFlags(RF_ClassDefaultObject) || MenuOwner->GetGameInstance() != GI || !IsMenuOnScreen(MenuOwner))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const int32 Score = (IsOpen(Candidate) ? 2 : 0) + (Candidate == Current ? 1 : 0);
|
||||
if (Score > BestScore)
|
||||
{
|
||||
Best = Candidate;
|
||||
BestScore = Score;
|
||||
}
|
||||
}
|
||||
return Best;
|
||||
}
|
||||
|
||||
// Ecran titre (MainMenu.TitleScreen, variable du Blueprint) ou partie. Repli : Mod Manager de l'ecran titre visible.
|
||||
bool IsTitleMenu(const UUserWidget* Menu)
|
||||
{
|
||||
if (!Menu)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (const FBoolProperty* Title = CastField<FBoolProperty>(Menu->GetClass()->FindPropertyByName(TEXT("TitleScreen"))))
|
||||
{
|
||||
return Title->GetPropertyValue_InContainer(Menu);
|
||||
}
|
||||
const UWidget* TitleMods = Menu->GetWidgetFromName(TEXT("ModManagerTitleButton"));
|
||||
return TitleMods && IsOpen(TitleMods);
|
||||
}
|
||||
|
||||
// Retire la barre d'onglets et l'hote du clavier d'une instance quittee. La page Slate du clavier est unique
|
||||
// (ULPKeyboardSubsystem::TakeEmbeddedPage rend la meme tant qu'elle vit) : l'ancien hote la lache avant que le
|
||||
// nouveau la prenne. Une capture de touche en cours est annulee (la page change de place).
|
||||
void DropTabs(UGameInstance* GI, TWeakObjectPtr<UHorizontalBox>& Bar, TWeakObjectPtr<UNativeWidgetHost>& Host, TArray<TWeakObjectPtr<UTextBlock>>& Labels)
|
||||
{
|
||||
UHorizontalBox* OldBar = Bar.Get();
|
||||
UNativeWidgetHost* OldHost = Host.Get();
|
||||
if (OldBar || OldHost)
|
||||
{
|
||||
if (ULPKeyboardSubsystem* Keys = GI ? GI->GetSubsystem<ULPKeyboardSubsystem>() : nullptr)
|
||||
{
|
||||
if (Keys->IsWaiting())
|
||||
{
|
||||
Keys->CancelWait();
|
||||
}
|
||||
}
|
||||
const UUserWidget* OldMenu = OldBar ? OldBar->GetTypedOuter<UUserWidget>() : OldHost->GetTypedOuter<UUserWidget>();
|
||||
UE_LOG(LogLifePlay, Display, TEXT("Reglages : onglets retires de %s (instance quittee)"), OldMenu ? *OldMenu->GetName() : TEXT("?"));
|
||||
}
|
||||
if (OldHost)
|
||||
{
|
||||
OldHost->SetContent(SNullWidget::NullWidget);
|
||||
if (IsUsableObject(OldHost->GetParent()))
|
||||
{
|
||||
OldHost->RemoveFromParent();
|
||||
}
|
||||
}
|
||||
if (OldBar && IsUsableObject(OldBar->GetParent()))
|
||||
{
|
||||
OldBar->RemoveFromParent();
|
||||
}
|
||||
Bar.Reset();
|
||||
Host.Reset();
|
||||
Labels.Reset();
|
||||
}
|
||||
|
||||
// Libelle visible seulement : les infobulles provoquent des faux positifs
|
||||
// (ex. "on screen" → Video, "prefer quality" → Video pour NewAnimationsOnly).
|
||||
FString RowText(const UWidget* Widget)
|
||||
|
|
@ -495,32 +589,37 @@ void ULPSettingsSubsystem::Deinitialize()
|
|||
Super::Deinitialize();
|
||||
}
|
||||
|
||||
UScrollBox* ULPSettingsSubsystem::FindOnScreenSettingsList(const UGameInstance* GI, const UScrollBox* Current)
|
||||
{
|
||||
// SET1-V1b : meme choix que le Tick des onglets (LPSettingsUi::FindOnScreenSettingsList), expose aux autres sous-systemes.
|
||||
return LPSettingsUi::FindOnScreenSettingsList(GI, Current);
|
||||
}
|
||||
|
||||
bool ULPSettingsSubsystem::Tick(float DeltaTime)
|
||||
{
|
||||
(void)DeltaTime;
|
||||
PlaceSettingsButton();
|
||||
UScrollBox* Scroll = nullptr;
|
||||
for (TObjectIterator<UScrollBox> It; It; ++It)
|
||||
// SET1-V1 : la liste de l'instance de MainMenu qui est a l'ecran, pas la premiere trouvee (une ancienne instance,
|
||||
// retiree du viewport et pas encore collectee, vient souvent avant). Aucune a l'ecran : Scroll reste nul et les
|
||||
// reglages sont vus fermes (capture de touche annulee, page du clavier lachee) ; les onglets restent sur leur
|
||||
// ancienne instance jusqu'au prochain rattachement.
|
||||
UScrollBox* Scroll = LPSettingsUi::FindOnScreenSettingsList(GetGameInstance(), SettingsList.Get());
|
||||
if (Scroll)
|
||||
{
|
||||
UScrollBox* Candidate = *It;
|
||||
if (!Candidate || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
|
||||
// Autre instance, ou barre qui n'est plus sur le Canvas de cette liste : on retire les onglets de l'ancienne
|
||||
// (plus de TabBar valide sur elle), EnsureTabs les repose sur celle-ci. Etat par instance remis a zero.
|
||||
const bool bOtherList = Scroll != SettingsList.Get();
|
||||
const bool bBarElsewhere = TabBar.IsValid() && TabBar->GetParent() != Scroll->GetParent();
|
||||
if (bOtherList || bBarElsewhere)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const UUserWidget* MenuOwner = Candidate->GetTypedOuter<UUserWidget>();
|
||||
if (!MenuOwner || MenuOwner->HasAnyFlags(RF_ClassDefaultObject) || MenuOwner->GetGameInstance() != GetGameInstance())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Scroll = Candidate;
|
||||
break;
|
||||
}
|
||||
if (!Scroll)
|
||||
{
|
||||
return true;
|
||||
LPSettingsUi::DropTabs(GetGameInstance(), TabBar, KeyboardHost, TabLabels);
|
||||
bKeyboardPage = false;
|
||||
bControlsHardened = false;
|
||||
LastChildCount = -1;
|
||||
}
|
||||
SettingsList = Scroll;
|
||||
const bool bOpen = LPSettingsUi::IsOpen(Scroll);
|
||||
}
|
||||
const bool bOpen = Scroll && LPSettingsUi::IsOpen(Scroll);
|
||||
if (TabBar.IsValid())
|
||||
{
|
||||
TabBar->SetVisibility(bOpen ? ESlateVisibility::Visible : ESlateVisibility::Collapsed);
|
||||
|
|
@ -581,8 +680,11 @@ void ULPSettingsSubsystem::PlaceSettingsButton()
|
|||
{
|
||||
continue;
|
||||
}
|
||||
// SET1-V1 : seulement le menu a l'ecran. Une ancienne instance (retiree du viewport, pas encore collectee)
|
||||
// ferait poser le bouton et SourceSettings sur un widget que le joueur ne voit pas.
|
||||
const UUserWidget* MenuOwner = Box->GetTypedOuter<UUserWidget>();
|
||||
if (!MenuOwner || MenuOwner->HasAnyFlags(RF_ClassDefaultObject) || MenuOwner->GetGameInstance() != GetGameInstance())
|
||||
if (!MenuOwner || MenuOwner->HasAnyFlags(RF_ClassDefaultObject) || MenuOwner->GetGameInstance() != GetGameInstance()
|
||||
|| !LPSettingsUi::IsMenuOnScreen(MenuOwner))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -831,8 +933,12 @@ void ULPSettingsSubsystem::EnsureTabs(UScrollBox* Scroll)
|
|||
Host->SetVisibility(ESlateVisibility::Collapsed);
|
||||
KeyboardHost = Host;
|
||||
ActiveTab = 0;
|
||||
bKeyboardPage = false;
|
||||
ApplyRows();
|
||||
UE_LOG(LogLifePlay, Display, TEXT("Reglages : onglets General, Audio, Video, Keyboard, Lewd, Misc"));
|
||||
const UUserWidget* Menu = Scroll->GetTypedOuter<UUserWidget>();
|
||||
UE_LOG(LogLifePlay, Display, TEXT("Reglages : onglets poses sur %s (%s)"), Menu ? *Menu->GetName() : TEXT("?"),
|
||||
LPSettingsUi::IsTitleMenu(Menu) ? TEXT("ecran titre") : TEXT("partie"));
|
||||
}
|
||||
|
||||
void ULPSettingsSubsystem::SelectTab(int32 Index)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
class UButton;
|
||||
class UCanvasPanel;
|
||||
class UGameInstance;
|
||||
class UHorizontalBox;
|
||||
class UNativeWidgetHost;
|
||||
class UScrollBox;
|
||||
|
|
@ -46,6 +47,13 @@ public:
|
|||
UFUNCTION()
|
||||
void OpenSettings();
|
||||
|
||||
// Lot SET1-V1b. Liste des reglages (MainMenu.SettingsScrollBox) de l'instance de MainMenu qui est a l'ecran, nulle s'il
|
||||
// n'y en a aucune. Partagee avec les sous-systemes qui ajoutent des lignes a cette liste (couleur, video, controle des
|
||||
// mods) : une ancienne instance, retiree du viewport et pas encore collectee, garde sa liste en memoire et ne doit pas
|
||||
// recevoir leurs lignes a la place de l'instance affichee. Current : liste deja suivie par l'appelant, elle departage
|
||||
// deux listes a l'ecran ; peut etre nulle.
|
||||
static UScrollBox* FindOnScreenSettingsList(const UGameInstance* GI, const UScrollBox* Current = nullptr);
|
||||
|
||||
private:
|
||||
bool Tick(float DeltaTime);
|
||||
void PlaceSettingsButton();
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "Engine/World.h"
|
||||
#include "HAL/IConsoleManager.h"
|
||||
#include "LifePlay.h"
|
||||
#include "LPSettingsSubsystem.h"
|
||||
#include "Misc/ConfigCacheIni.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "DynamicRHI.h"
|
||||
|
|
@ -459,22 +460,11 @@ UWidget* ULPVideoQualitySubsystem::MakeRecommendedRow(UScrollBox* Scroll, const
|
|||
|
||||
void ULPVideoQualitySubsystem::EnsureControls()
|
||||
{
|
||||
UScrollBox* Scroll = nullptr;
|
||||
for (TObjectIterator<UScrollBox> It; It; ++It)
|
||||
{
|
||||
UScrollBox* Candidate = *It;
|
||||
if (!Candidate || Candidate->GetFName() != TEXT("SettingsScrollBox") || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const UUserWidget* Owner = Candidate->GetTypedOuter<UUserWidget>();
|
||||
if (!Owner || Owner->HasAnyFlags(RF_ClassDefaultObject) || Owner->GetGameInstance() != GetGameInstance())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Scroll = Candidate;
|
||||
break;
|
||||
}
|
||||
// SET1-V1b : la liste de l'instance de MainMenu qui est a l'ecran, pas la premiere trouvee (une ancienne instance,
|
||||
// retiree du viewport et pas encore collectee, vient souvent avant). Aucune a l'ecran : rien a faire. Pas d'etat par
|
||||
// instance a remettre a zero : la presence de LPVideoOverall se lit sur les enfants de la liste choisie, et AddRow /
|
||||
// MakeRecommendedRow rebranchent Rows et RecommendedButton sur les lignes de cette liste.
|
||||
UScrollBox* Scroll = ULPSettingsSubsystem::FindOnScreenSettingsList(GetGameInstance());
|
||||
if (!Scroll)
|
||||
{
|
||||
return;
|
||||
|
|
@ -601,5 +591,6 @@ void ULPVideoQualitySubsystem::EnsureControls()
|
|||
RefreshWidgets();
|
||||
// Nouvelle instance du menu : le Blueprint a pu reappliquer ses propres valeurs.
|
||||
ApplyToScalability();
|
||||
UE_LOG(LogLifePlay, Display, TEXT("Video : controles ajoutes avant les reglages de couleur"));
|
||||
const UUserWidget* Menu = Scroll->GetTypedOuter<UUserWidget>();
|
||||
UE_LOG(LogLifePlay, Display, TEXT("Video : controles ajoutes avant les reglages de couleur (sur %s)"), Menu ? *Menu->GetName() : TEXT("?"));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue