LifePlay-Revival/Docs/Migration/etat/ST/STA/STA-T2b-GIVAR-DIAG.md
edujiro5972 8084622450 LifePlay UE 5.8 : état de développement au 2026-10-19
Tickets : REP1-T4

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 22:57:42 +02:00

26 KiB
Raw Blame History

Fiche STA-T2b-GIVAR — Niveau N3 — Modèle prévu modèle de l'agent lp-cart (valeur non relue) | utilisé claude-opus-5-5 — Agent lp-cart — Skills sk-protocol, ue-cpp-build, lp-commandlets, lp-paths

STA-T2b-GIVAR-DIAG : cause et correctif proposé pour clearVariable, Get_SpinBox_0_Value_0, determinePersonVars (2026-10-09)

Hors gabarit (partiel, annoncé par la fiche) : trois familles, donc trois blocs DIAG (F1, F2, F3). Chacun reprend dans l'ordre les sections 1 à 5 du gabarit DIAG. Le tableau récapitulatif, les commandes et le compte rendu sont en § Constats.

Sources lues (lecture seule) :

  • CIBLE = D:\Game\LifePlay_Build_5.8_Development_U8_essai\Windows\LifePlay\Saved\Logs\LifePlay.log
  • REF = D:\Game\LifePlay-master 5.5\Docs\Migration\etat\U58\U6\LifePlay_58_session2.log
  • 55 = D:\Game\LifePlay-master 5.5\Docs\Migration\etat\U58\U6\LifePlay_55_session2.log (contrôle ajouté : le défaut existait-il déjà en 5.5 ?)
  • dumps = D:\Game\LifePlay-master 5.5\Docs\Migration\etat\ST\STA\dumps\
  • moteur = D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\ (sources installées)

Rappel moteur commun aux trois familles (établi, sources 5.8 lues) :

  • CoreUObject\Private\UObject\ScriptCore.cpp:3203-3216 : « Accessed None trying to read (real) property X in … » nomme la propriété qui contient l'objet nul servant de contexte, pas la propriété qu'on voulait lire. « in not an UClass » veut dire que X n'appartient pas à une classe : c'est ici la variable temporaire locale de la fonction (CallFunc_Array_Get_Item = sortie d'un Array Get).
  • ScriptCore.cpp:3220-3228 : « Accessed None » sans nom de propriété = contexte issu d'une expression déjà en échec (la propriété la plus récente est remise à nul en :3238-3240).
  • ScriptCore.cpp:3274-3284 : « Accessed None reading structure X » = lecture du membre X d'une structure dont l'expression source a échoué.
  • ScriptCore.cpp:3191-3201 : un objet détruit (pending kill) donne un autre message (« … is not valid (pending kill or garbage) »). Les trois familles portent donc sur des références réellement nulles, pas sur des objets détruits.
  • ScriptCore.cpp:3234-3245 : après l'avertissement, l'appel ou la lecture est sauté, la valeur de retour remise à zéro, et l'exécution continue.
  • Engine\Private\KismetArrayLibrary.cpp:466-479 : un Array Get hors plage écrit « Attempted to access index %d from array '%s' of length %d in '%s'! » puis remet la sortie à sa valeur par défaut (objet nul).

F1 — GI_C:clearVariable (72 CIBLE / 94 REF)

1. Symptôme et reproduction

  • Occurrence 1 : CIBLE:38010 « Script Msg: Attempted to access index 0 from array 'Person_24_4B712C904750AD4CE1580DBEBD9E7396' of length 0 in '/Game/Structs/Variable.Variable'! », puis CIBLE:38012-38014 « Accessed None trying to read (real) property CallFunc_Array_Get_Item in not an UClass … GI_C:clearVariable:64X ». Pile en CIBLE:38015-38023 : ExecuteUbergraph_GI → UpdateCheckForScenes → ExecuteUbergraph_GI → CheckConditionsWho → ReadSceneLine → CallFunction → getPerson → clearVariable.
  • Occurrence 2 (même appel, même horodatage 16.43.43:225) : CIBLE:38025-38036, même pile.
  • REF : REF:8713-8726, même paire de messages. Pile : SceneOption_C … OnButtonClickedEvent → GI.ContinueScene → ReadSceneLine → CallFunction → GeneratePerson → clearVariable.
  • Le défaut existait déjà en 5.5 : 55:9060-9062 (« Accessed None trying to read property CallFunc_Array_Get_Item », clearVariable:012F).
  • Recomptage sur CIBLE : Grep "GI_C:clearVariable:" donne 73 lignes. L'une est la ligne de synthèse LogLifePlay (CIBLE:52495, « 72 »), il reste donc 72 avertissements. Ils vont par paires de même horodatage (ex. 38014/38027, 43444/43457), soit 36 appels.
  • Appelants (Grep multiligne « GI_C:\n Function …GI_C:clearVariable\n ») : getRelative 28, GetSpecific 30, getPerson 10, GeneratePerson 4. Somme 72, égale au compte du motif générique (72).
  • Un message hors plage Person_24 … of length 0 précède un avertissement clearVariable (4 lignes plus bas) 36 fois. Il y a 39 messages hors plage Person_24 en tout : les 3 autres viennent d'ailleurs (hors périmètre).

2. Hypothèse testée

Le tableau Person de la structure Variable que rend GetVariable(Var) est vide. Array Get [0] sort donc de la plage et rend None, et chaque lecture de membre sur cette sortie lève l'avertissement. Hypothèses écartées par la même mesure : un élément nul dans un tableau rempli, ou un problème d'ordre d'exécution.

3. Essai et résultat brut

Nœuds (dumps\GI__clearVariable.txt) :

  • :34-38 K2Node_IfThenElse_0 : Len(Var) > 0. :98-103 K2Node_SwitchString_0 sur Var : le cas AI ne mène à rien, le cas Default va à GetVariable.
  • :5-10 K2Node_CallFunction_0 GetVariable(Name = Var) → :11-19 K2Node_BreakStruct_0 (structure Variable). Son membre Person_24_… va à K2Node_GetArrayItem_0.Array (:19).
  • :21-24 K2Node_GetArrayItem_0, index '0' (:23). La sortie (:24) a 8 consommateurs : DestroyPerson, deux EqualEqual_ObjectObject (Companion, Interacting), OccupyingMoreVar, un EqualEqual sur la valeur de Map_Find, et 3 lectures de membre : Name_First (:91-93), Prefix (:137-139) et SaveSlot (:145-147).
  • :54-58 K2Node_IfThenElse_1 a pour condition BooleanOR(A, B, C) (:59-64). then est vide. else va à OccupyingMoreVar → IfThenElse_2 → PrintString (« … cleared and destroyed, who is <Name_First> ») → DestroyPerson.
  • Entrée C du OR : BooleanAND(Map_Find(Room.KnownNpcsHere, Prefix + ToString(SaveSlot)), Value == Person[0]) (:115-136, :140-151). Ces nœuds sont purs et le OR ne court-circuite pas : Prefix et SaveSlot sont lus sur la sortie de l'Array Get à chaque évaluation de la condition.

Résultat brut :

  • Le message moteur hors plage (KismetArrayLibrary.cpp:472-479) précède la paire d'avertissements dans 36 cas sur 36, avec longueur 0 et index 0.
  • 2 avertissements par appel : ce sont les lectures de Prefix et SaveSlot dans la condition. La 3e lecture possible (Name_First, branche PrintString) n'apparaît jamais avec un objet nul : CIBLE ne contient qu'une ligne « cleared and destroyed » (CIBLE:50695), et elle porte un nom.
  • Aucun avertissement au nom de OccupyingMoreVar. Grep OccupyingMoreVar|DestroyPerson sort 3 lignes, toutes des messages DestroyDummy was from DestroyPerson (CIBLE:49651, 50702, 51639).
  • Origine du tableau : Variable.Person de la variable de scène nommée Var. Les 4 appelants appellent clearVariable avant d'affecter une personne. Exemple lu : GeneratePerson fait Set currentMatchRace puis clearVariable(Var = VariableToClear) dès l'entrée (dumps\GI__GeneratePerson.txt:2-8, :969-973). Si la variable est encore vide, le tableau a une longueur 0. Si elle n'existe pas encore, on suppose que GetVariable rend une structure par défaut, mais ce cas n'est pas vérifié (incertain).

4. Verdict

Confirmée : index 0 hors plage sur un tableau Person vide (aucun élément nul). C'est un défaut de logique qui existait déjà en 5.5, sans lien avec la montée en 5.8. Dans le cas vide, la fonction ne fait aujourd'hui rien d'observable en dehors des 72 avertissements et des 36 messages hors plage. Le passage par la branche then, vide, est estimé à partir du compte de 2 avertissements par appel.

5. Correctif proposé et suite

Correctif dans clearVariable (une seule fonction à corriger au lieu de ses 4 appelants) :

  • Insérer un nouveau K2Node_IfThenElse entre K2Node_CallFunction_0.then (GetVariable) et K2Node_IfThenElse_1.execute.
  • Condition : KismetArrayLibrary::Array_IsValidIndex(TargetArray ← K2Node_BreakStruct_0.Person_24_4B712C904750AD4CE1580DBEBD9E7396, Index = 0) (variante : Greater_IntInt(Array_Length(Person), 0)).
  • then → K2Node_IfThenElse_1.execute (le reste de la chaîne ne change pas). else : rien, la fonction s'arrête.
  • En option : un BooleanAND avec KismetSystemLibrary::IsValid(K2Node_GetArrayItem_0.Output) pour couvrir un élément nul (cas non observé).

La garde est justifiée : un tableau vide est un état normal qui veut dire « rien à effacer », pas une erreur à remonter. Le comportement observé dans ce cas est déjà « aucune action » : la garde le garde tel quel et supprime les 72 + 36 lignes. Ce n'est pas un masquage, car on n'attend pas de personne dans ce cas.

Suite :

  • IMPL N2 (édition du Blueprint GI).
  • VAL : rejouer la session, puis compter GI_C:clearVariable: (attendu : 0) et array 'Person_24…' of length 0 (attendu : 3, les autres sources).
  • À confirmer avant l'IMPL (N1) : dump de getRelative, GetSpecific et getPerson, pour vérifier qu'aucun ne dépend d'un effet du cas vide.

F2 — MainMenu_C:Get_SpinBox_0_Value_0 (30 CIBLE / 30 REF)

1. Symptôme et reproduction

  • Évaluation 1 : CIBLE:911-939, 5 avertissements de suite au même horodatage 16.43.06:237, image 0, instance MainMenu_C_2147482360 :
    • 911 « Accessed None trying to read (real) property GI in /Game/UI/MainMenu.MainMenu_C » ;
    • 917 « Accessed None » ;
    • 923 « … property CallFunc_Array_Get_Item in not an UClass » ;
    • 929 « Accessed None » ;
    • 935 « Accessed None reading structure DepthOfFieldFarBlurSize ».
  • Pile : une seule ligne, Function /Game/UI/MainMenu.MainMenu_C:Get_SpinBox_0_Value_0 (CIBLE:914-915). Aucun appelant Blueprint : l'appel vient du code natif.
  • Évaluation 2 (même instance, même image) : CIBLE:941-969, même séquence.
  • Les lignes « property GI in /Game/UI/MainMenu.MainMenu_C » (Grep) sont 911, 941, 971, 1001, 51979, 52009, 52039 et 52069. Parmi elles, 1001 et 52069 relèvent d'une autre famille : ExecuteUbergraph_MainMenu, appelé par BndEvt__SpinBoxSquirtMult … OnSpinBoxValueChangedEvent (CIBLE:1001-1013, 52069-52073).
  • Pour cette famille, cela fait 3 évaluations à l'image 0 (911, 941, 971) et 3 à l'image 843 (51979, 52009, 52039, 16.45.57:707). L'image 843 concerne une nouvelle instance MainMenu_C_2147459502, créée à la suite de PC.InpActEvt_MainMenu → GI.MainMenuInput → OpenMainMenu (pile de l'avertissement précédent, CIBLE:51970-51977). Total : 6 évaluations × 5 = 30, égal au compte INV.
  • REF : REF:974-978, même message sur GI, même instance MainMenu_C_2147482360, image 0.
  • 5.5 : 45 lignes MainMenu_C:Get_SpinBox_0_Value_0: dans le journal 55, donc défaut préexistant (45 = 9 × 5, estimé à 3 instances).

2. Hypothèse testée

Get_SpinBox_0_Value_0 est la fonction de liaison (binding) de la propriété Value du widget SpinBox_0. Le moteur l'évalue pendant la construction du widget Slate, avant que l'Event Graph de MainMenu n'ait rempli la variable GI. Toute la chaîne de lectures part donc d'un GI nul.

3. Essai et résultat brut

Nœuds (dumps\MainMenu__Get_SpinBox_0_Value_0.txt) :

  • :2-6 FunctionEntry.then → FunctionResult (fonction avec exécution, valeur de retour ReturnValue).
  • Chaîne :
    • :7-9 VariableGet_0 GI (self) ;
    • :10-12 VariableGet_1 ChargenCameras sur GI ;
    • :13-16 K2Node_GetArrayItem_0 index '0' ;
    • :17-19 VariableGet_2 CameraComponent sur la sortie de l'Array Get ;
    • :20-22 VariableGet_3 PostProcessSettings ;
    • :23-25 K2Node_BreakStruct_0 DepthOfFieldFarBlurSize ;
    • :26-30 Multiply_DoubleDouble(…, 2.0) → retour.
  • Correspondance message → nœud : 911 ↔ VariableGet_1 lue sur un GI nul (établi par le nom). 923 ↔ VariableGet_2 lue sur la sortie nulle de l'Array Get (établi). 935 ↔ BreakStruct_0 (établi). 929 ↔ VariableGet_3, dont le contexte vient d'une lecture déjà en échec (estimé, ScriptCore.cpp:3220-3240). 917 : origine exacte incertaine, probablement une seconde évaluation du contexte GI.ChargenCameras, le tableau étant passé par référence à l'Array Get.

Mécanisme moteur (établi, sources 5.8) :

  • UMG\Private\Components\SpinBox.cpp:120-122 : USpinBox::SynchronizeProperties fait PROPERTY_BINDING(float, Value) puis MySpinBox->SetValue(ValueBinding).
  • Slate\Private\Widgets\Input\SSpinBox.cpp:723-727 : SSpinBox::SetValue lit tout de suite ValueAttribute.Get(), ce qui exécute le binding, puis fait CommitValue.
  • UMG\Private\Components\Widget.cpp:993 puis :1094-1096 : TakeWidget_Private appelle RebuildWidget(), puis SynchronizeProperties() et OnWidgetRebuilt().
  • UMG\Private\UserWidget.cpp:1214 : le RebuildWidget du UserWidget prend le widget de la racine, ce qui synchronise les enfants, dont SpinBox_0.
  • UserWidget.cpp:1231-1234 : NativePreConstruct / NativeConstruct (Event Pre Construct / Event Construct) ne viennent qu'ensuite, dans le OnWidgetRebuilt du parent.

Origine de GI : dumps\MainMenu__EventGraph.txt:2-24. K2Node_Event_1 → GetGameInstance → Cast To GI (K2Node_DynamicCast_0) → Set GI (K2Node_VariableSet_2904) → K2Node_CallFunction_1278. Le dump n'imprime pas le nom de l'événement (incertain). Une chose est sûre : ce n'est pas Event On Initialized. Cet événement part de UUserWidget::Initialize (UserWidget.cpp:135, :175), avant tout TakeWidget, et GI serait alors rempli. K2Node_Event_1 est donc estimé être Construct ou Pre Construct.

Point amont (binding appelé à chaque image) :

  • Le binding est bien réévalué tant que le widget est affiché (attribut Slate lié).
  • Mais aucun avertissement de cette famille n'apparaît entre CIBLE:999 et CIBLE:51979 pour la première instance. Une fois GI rempli, la chaîne est donc valide.
  • Grep ChargenCameras sur CIBLE = 0 : aucun Array Get hors plage sur ce tableau.
  • Il n'y a donc pas un avertissement par image ici, seulement 3 évaluations fautives par construction d'instance. La raison du triple appel (Assign plus Get plus une préparation Slate ?) reste incertaine.
  • Valeur rendue aujourd'hui pendant ces 3 évaluations : toutes les lectures sont remises à zéro (ScriptCore.cpp:3242-3245), donc 0 × 2 = 0.0 (estimé).

4. Verdict

Confirmée : GI est nul parce que le binding s'exécute dans SynchronizeProperties, avant l'événement qui remplit GI. Ce n'est ni un élément de tableau nul ni un défaut de données. Le défaut existait déjà en 5.5. La même cause produit aussi CIBLE:1001 et 52069 (famille ExecuteUbergraph_MainMenu, BndEvt__SpinBoxSquirtMult) : même horodatage, déclenchés par le CommitValue de la construction (estimé).

5. Correctif proposé et suite

Correctif A (à la racine, recommandé) :

  • Déplacer GetGameInstance (K2Node_CallFunction_11) → Cast To GI (K2Node_DynamicCast_0) → Set GI (K2Node_VariableSet_2904) vers un nouveau nœud Event On Initialized du graphe MainMenu.
  • Brancher ensuite K2Node_Event_1.then directement sur K2Node_CallFunction_1278.execute.
  • Effet attendu : GI est rempli à la création du widget, avant toute synchronisation (UserWidget.cpp:175). Cela traite F2 et, par la même cause, la famille ExecuteUbergraph_MainMenu 2 / 2.
  • Prérequis à vérifier :
    • K2Node_Event_1 est bien Construct ;
    • ChargenCameras[0] est déjà rempli à la création (estimé oui : même image que le Construct qui réussit).

Correctif B (local, en complément ou à la place de A) :

  • Dans Get_SpinBox_0_Value_0, insérer un K2Node_IfThenElse entre FunctionEntry.then et FunctionResult_0.
  • Condition : KismetSystemLibrary::IsValid(GI). En option, un BooleanAND avec Array_IsValidIndex(GI.ChargenCameras, 0) et IsValid(ChargenCameras[0].CameraComponent).
  • then → FunctionResult_0 existant. else → second K2Node_FunctionResult avec ReturnValue = 0.0, la valeur rendue aujourd'hui, donc comportement inchangé.
  • La garde est justifiée : un GI nul pendant la construction est un état transitoire voulu par l'ordre du moteur (établi ci-dessus), pas une donnée absente. Seul, B ne traite pas BndEvt__SpinBoxSquirtMult.

Suite :

  • À vérifier avant IMPL (N1) : le nom de K2Node_Event_1, avec un dump qui imprime la référence d'événement ou un coup d'œil dans l'éditeur.
  • IMPL N2 : A, avec B selon la décision de l'orchestrateur.
  • VAL : rejouer, compter Get_SpinBox_0_Value_0:64X (attendu : 0) et property GI in /Game/UI/MainMenu.MainMenu_C (attendu : 0).

F3 — GI_C:determinePersonVars (30 CIBLE / 34 REF)

1. Symptôme et reproduction

  • Occurrence 1 : CIBLE:8041-8043 « Accessed None trying to read (real) property currentMatchRace in /Game/BPs/GI.GI_C … GI_C:determinePersonVars:64X ». Pile en CIBLE:8044-8054 : Room.AfterLoadRoom → ShowNpcsHere → getKnownNpcsHere → GenerateUnknownNpcs → GI.GeneratePerson → determinePersonVars.
  • Occurrence 2 (même appel, même horodatage 16.43.38:978) : CIBLE:8056-8069, même pile.
  • REF : REF:8742-8753. Pile : SceneOption_C … OnButtonClickedEvent → GI.ContinueScene → ReadSceneLine → CallFunction → GeneratePerson → determinePersonVars.
  • 5.5 : 36 lignes GI_C:determinePersonVars: dans le journal 55 (défaut préexistant).
  • Recomptage sur CIBLE : Grep multiligne « property currentMatchRace in /Game/BPs/GI.GI_C » suivi de determinePersonVars: = 30.

2. Hypothèse testée

currentMatchRace (variable membre de GI, une référence à une personne) vaut None quand GeneratePerson est appelé sans personne de référence. determinePersonVars appelle pourtant getRace et getEthnicity sur elle sans condition.

3. Essai et résultat brut

Nœuds (dumps\GI__determinePersonVars.txt) :

  • :2-3 K2Node_FunctionEntry_0.then → K2Node_CallFunction_18 Person_C::getRace() (:439-443) → .then → K2Node_CallFunction_28 Person_C::getEthnicity() (:444-448) → .then → K2Node_VariableSet_27 Dice (:23-27).
  • self de ces deux appels ← K2Node_VariableGet_11 currentMatchRace (:436-438). Ce sont 2 appels avec exécution, passés à l'entrée de la fonction sans aucun test.
  • La même fonction teste ensuite KismetSystemLibrary::IsValid(currentMatchRace) (K2Node_CallFunction_30, :455-461). Ce test sert de bPickA à deux SelectString :
    • K2Node_CallFunction_31 (:449-454) : getEthnicity.Ethnicity si la référence est valide, sinon returnEthnicity → FunctionResult_1.ethnicity ;
    • K2Node_CallFunction_29 (:462-467) : getRace.Race si la référence est valide, sinon returnFantasy → FunctionResult_1.fantasy.

Origine de la valeur (dumps\GI__GeneratePerson.txt) :

  • :2-8 et :1176-1181 : le paramètre d'entrée MatchRace de GeneratePerson va dans Set currentMatchRace.
  • :1095-1097 : appel de determinePersonVars (K2Node_CallFunction_51).
  • :1182-1187 : currentMatchRace est ensuite remis à None (K2Node_VariableSet_26, entrée vide).
  • Les deux appelants vus (Room.GenerateUnknownNpcs, commande de scène) passent MatchRace = None.

Résultat brut : 2 avertissements par appel, un pour getRace et un pour getEthnicity. La paire 8041/8056 a le même horodatage. 30 = 15 appels × 2 (estimé à partir de la structure : 2 nœuds qui lisent la référence).

4. Verdict

Confirmée : la référence est nulle par conception (paramètre facultatif), et la fonction le sait déjà, puisqu'elle teste IsValid en :458-461. Mais les deux appels qui la lisent passent avant ce test. Ce défaut existait déjà en 5.5. Les sorties des deux appels ne sont utilisées que si IsValid est vrai. Sur un contexte nul, le moteur saute l'appel (ScriptCore.cpp:3234-3245) : le résultat de la fonction est donc le même avec ou sans les deux appels quand la référence est nulle.

5. Correctif proposé et suite

Correctif dans determinePersonVars :

  • Insérer un K2Node_IfThenElse entre K2Node_FunctionEntry_0.then et K2Node_CallFunction_18.execute.
  • Condition ← K2Node_CallFunction_30.ReturnValue, le IsValid(currentMatchRace) qui existe déjà : un nœud pur peut alimenter plusieurs broches.
  • then → K2Node_CallFunction_18 → K2Node_CallFunction_28 → K2Node_VariableSet_27, sans changement.
  • else → K2Node_VariableSet_27.execute.
  • Variante : la macro IsValid des StandardMacros, avec ses sorties d'exécution Is Valid / Is Not Valid.

La garde est justifiée : None est une valeur prévue et déjà testée. Comportement inchangé (voir § 4) et 30 lignes en moins.

Suite : IMPL N2. VAL : rejouer et compter property currentMatchRace in /Game/BPs/GI.GI_C (attendu : 0).

Constats

Tableau récapitulatif

Famille CIBLE / REF Nœud fautif (dump:ligne) Pile (journal:ligne) Cause Verdict Correctif proposé Garde justifiée
GI_C:clearVariable 72 / 94 (36 appels × 2) K2Node_GetArrayItem_0 index 0 sur BreakStruct_0.Person_24 (GI__clearVariable.txt:19-24) ; lectures Prefix :137-139, SaveSlot :145-147 CIBLE:38010-38023 (getPerson), CIBLE:38025-38036 ; REF:8713-8726 (GeneratePerson) tableau Person vide (longueur 0, message hors plage 36 / 36) ; appelants : getRelative 28, GetSpecific 30, getPerson 10, GeneratePerson 4 confirmée (préexistant 5.5) IfThenElse après GetVariable sur Array_IsValidIndex(Person, 0), else = fin oui : vide = rien à effacer, comportement observé conservé
MainMenu_C:Get_SpinBox_0_Value_0 30 / 30 (6 évaluations × 5) VariableGet_0/1 GI.ChargenCameras puis Array Get, CameraComponent, PostProcessSettings, BreakStruct (MainMenu__Get_SpinBox_0_Value_0.txt:7-30) CIBLE:911-939 (pile native seule :914-915), CIBLE:51979+ (2e instance) ; REF:974-978 binding évalué dans SynchronizeProperties (SpinBox.cpp:120-122, SSpinBox.cpp:726) avant l'événement qui remplit GI (MainMenu__EventGraph.txt:2-24) confirmée (préexistant 5.5) A : Set GI dans Event On Initialized (traite aussi ExecuteUbergraph_MainMenu 2 / 2) ; B : IsValid(GI) dans le binding, else retour 0.0 B oui (état transitoire voulu par le moteur) ; A préféré (racine)
GI_C:determinePersonVars 30 / 34 (15 appels × 2) K2Node_CallFunction_18 getRace, _28 getEthnicity sur VariableGet_11 currentMatchRace (GI__determinePersonVars.txt:436-448) CIBLE:8041-8054, CIBLE:8056-8069 ; REF:8742-8753 MatchRace None passé à GeneratePerson (GI__GeneratePerson.txt:2-8, :1176-1187), appels sans test confirmée (préexistant 5.5) IfThenElse sur le IsValid existant (_30) avant _18, else → VariableSet_27 oui : None prévu et déjà testé (:455-461)

Autres constats

  • Les trois familles existaient déjà sous UE 5.5 (journal 55 : 9060-9062 ; 45 lignes et 36 lignes). Aucune n'est une régression de la montée 5.8.
  • Outillage, à noter pour les fiches suivantes : Grep en mode dossier sur dumps\ rend 0 résultat, même pour K2Node_FunctionEntry qui figure dans chaque dump, et Grep currentMatchRace sur le dossier rend aussi 0. Le même motif sur le fichier seul trouve la ligne (GI__determinePersonVars.txt:436). Avec un glob (MainMenu__*.txt), la recherche fonctionne. Cause incertaine (règle d'exclusion de ripgrep probable). Il faut chercher fichier par fichier ou avec un glob explicite.

Commandes et lectures (exactes, comptes bruts)

  • Read : gabarits.md:1-35, dumps\GI__clearVariable.txt (151 lignes), dumps\MainMenu__Get_SpinBox_0_Value_0.txt (30 lignes), dumps\GI__determinePersonVars.txt:405-467, dumps\MainMenu__EventGraph.txt:1-30.
  • Read sur CIBLE : 895-954, 960-1029, 37995-38063, 51960-51984, 52066-52073.
  • Grep sur CIBLE :
    • GI_C:clearVariable: (compte) → 73 ;
    • multiligne GI_C:(getPerson|GeneratePerson|GetSpecific|getRelative)\n…clearVariable\n → 10, 4, 30, 28 ; motif générique → 72 ;
    • Attempted to access index .* from array 'Person_24 → 39 ; même motif suivi de clearVariable: → 36 ;
    • property GI in /Game/UI/MainMenu\.MainMenu_C → 8 lignes (6 binding, 2 ExecuteUbergraph_MainMenu) ;
    • multiligne currentMatchRace … determinePersonVars: → 30 ;
    • ChargenCameras → 0 ;
    • OccupyingMoreVar|DestroyPerson → 3 ;
    • cleared and destroyed, who is → 1 (CIBLE:50695).
  • Grep sur REF : GI_C:clearVariable: (pile 8713-8726), GI_C:determinePersonVars: (8742-8753), MainMenu_C:Get_SpinBox_0_Value_0: (974-978).
  • Grep sur 55 : MainMenu_C:Get_SpinBox_0_Value_0: → 45 ; GI_C:determinePersonVars: → 36 ; GI_C:clearVariable: (9060-9062).
  • Grep sur les dumps (par fichier) : currentMatchRace dans GI__GeneratePerson.txt (7, 1176-1187) et GI__EventGraph.txt (0) ; determinePersonVars\(\) dans GI__GeneratePerson.txt (1095) ; nœuds FunctionEntry_192, CallFunction_28.
  • Moteur lu : KismetArrayLibrary.cpp:459-482, ScriptCore.cpp:3165-3289, SpinBox.cpp:84-123, SSpinBox.cpp:723-728, Widget.cpp:985-999 et :1085-1097, UserWidget.cpp:135, :175, :1190, :1214, :1219-1236.

Compte rendu (sk-protocol § 3)

[sk-protocol] Skills présents : sk-protocol, ue-cpp-build, lp-commandlets, lp-paths.

  1. Résultat : réussi. Les 3 familles ont leur nœud cité, leur pile, un verdict (3 confirmées) et un correctif proposé.
  2. Preuves : dumps et journaux cités fichier:ligne ci-dessus ; mécanismes moteur lus dans les sources UE 5.8.
  3. Chiffres :
    • clearVariable : 72 = 36 × 2 ; appelants 28 + 30 + 10 + 4 = 72 ; hors plage 36 / 36.
    • Get_SpinBox : 30 = 6 × 5 (2 instances × 3 évaluations).
    • determinePersonVars : 30 (Grep multiligne).
  4. Incertitudes :
    • nom de K2Node_Event_1 dans MainMenu (estimé Construct) ;
    • origine du 2e « Accessed None » sans nom (CIBLE:917) ;
    • cause du triple appel du binding ;
    • comportement de GetVariable sur une variable inexistante ;
    • comptes REF (94, 34) non recomptés, repris de STA-T1.
  5. Écarts : environ 55 appels d'outil pour un budget d'environ 40 tours ; journal 55 lu en plus pour vérifier que le défaut existait déjà. Fichier écrit : D:\Game\LifePlay-master 5.5\Docs\Migration\etat\ST\STA\STA-T2b-GIVAR-DIAG.md.
  6. Suite : l'orchestrateur doit arbitrer les correctifs (F2 : A, B ou A+B), puis lancer l'IMPL N2 Blueprint (GI, MainMenu) après vérification N1 de K2Node_Event_1. État : diagnostic terminé, aucune modification.