26 KiB
Fiche STE-H3 — Niveau N3 — Modèle prévu (modèle de l'agent lp-cart) | utilisé claude-opus-5-5 — Agent lp-cart — Skills sk-protocol, lp-mcp (§ 3-4), lp-commandlets, lp-paths, ue-cpp-build (préchargés), lp-doc (gabarits)
STE-H3-SPEC : gardes F1 / F3 des lectures vides de personnages du moteur de scènes (2026-10-10)
Lecture seule stricte (aucun éditeur, commandlet, build ni écriture hors de ce fichier). Copie D:\Game\LifePlay-master 5.8,
branche ue5.8. Gabarit SPEC : D:\Game\LifePlay-master 5.8\.claude\skills\lp-doc\gabarits.md:36-38.
Statut : partiel. 6 gardes spécifiées (G1 à G6) ; la 4e lecture F3 (CallFunc_Array_Get_Item_41) n'est pas dans
CallFunction mais dans CallFunctionReturnBool, fonction sans dump 5.8 : écart au DIAG, rapporté sans improviser (§ 4, É1).
G5 dépend de Q2 ; toute l'IMPL dépend de Q1.
Abréviations (chemins absolus) :
- D =
D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STE\dumps\(dumps 5.8 après STC,STE-D-INV.md) ; - RSN =
D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STA\dumps\GI__ReturnStatIfNeeded.txt(dump STA, sans en-tête, antérieur à STB et STC) ; - EGB =
D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STB\dumps\GI__EventGraph.txt(antérieur à STC ; à reconfirmer sur STE-D2) ; - L2 =
D:\Game\LifePlay_Build_5.8_STB-JEU2_Development\Windows\LifePlay\Saved\Logs\LifePlay.log(journal STB-JEU2 du DIAG) ; - JM =
D:\Game\LifePlay-master 5.8\Docs\Journal_Modifications.md(déplacé par DOCMV, CHG-300 : JM:1135) ; modèle de garde CHG-282 (JM:1153), CHG-283 (JM:1152) ; - UE =
D:\Game\Launcher\Engine\UE_5.8\Engine\Source\(moteur installé, lu).
État du Blueprint : MD5 de Content\BPs\GI.uasset = d93785fca90e3342575fc0b601cc2e93 (commande
md5sum "/d/Game/LifePlay-master 5.8/Content/BPs/GI.uasset"), égal à celui relevé à la fin de STE-D (STE-D-INV.md:84) ;
git status --short -- Content/BPs/GI.uasset vide ; dernier commit bc4d91f (STC, CHG-296). Les dumps D décrivent
donc le GI actuel (établi).
1. Objectif mesurable
Supprimer, sans changer ce que le jeu fait, les avertissements des lectures de personnage vide dans GI, sur le parcours de STB-JEU2 rejoué (L2 comme référence, comptes par Grep, rejouables) :
| Famille (motif Grep sur le journal de jeu) | L2 | Attendu après IMPL |
|---|---|---|
F1 ciblée, multiligne property Person in not an UClass\r?\n[^\n]*\r?\n\s+Function /Game/BPs/GI\.GI_C:(getActorVar|setActorVar|ReturnStatIfNeeded): |
267 | 0 |
F3 de CallFunction, property CallFunc_Array_Get_Item_3[123] |
153 (_31 96, _32 24, _33 33) |
0 |
F3 de CallFunctionReturnBool, property CallFunc_Array_Get_Item_41 |
14 | inchangé (hors SPEC, É1) |
F2, Person_24_4B712C904750AD4CE1580DBEBD9E7396' of length 0 |
351 | en baisse par CHECKING: (résidu attendu, § 4 R7) |
Gardes spécifiées par fonction : setActorVar 1 (G1), getActorVar 1 (G2), ReturnStatIfNeeded 1 en cascade de
2 branches (G3), CallFunction 3 en cascade (G4 setCurrentLocation, G5 setUntil, G6 getBuilding),
CallFunctionReturnBool 0 (bloquée, É1). Total : 20 nœuds créés, 7 break_pins, 42 connect_pins, 0 suppression.
2. Fichiers touchés, ordre
Un seul fichier : Content\BPs\GI.uasset (graphes de fonction setActorVar, getActorVar, ReturnStatIfNeeded,
CallFunction ; ni l'EventGraph, ni le C++, ni le contenu des modules). Ordre d'exécution : G1, G2, G3, G4, G6, puis G5
(selon Q2).
2.0 Préalables (dans l'ordre, avant tout create_node)
- P1. Réponses de l'utilisateur à Q1 (et Q2 pour G5).
- P2. MD5 de
GI.uasset=d93785fc…; sinon (STE-GI passe avant H3 d'aprèsSTE-TACHES.md:26-28) refaire les dumpsLPDumpFunction -BP=GI -Fn=<f> -Pins -Execdes 4 fonctions et comparer les nœuds cités ici (lp-commandlets). - P3. Reconfirmer G3 sur un dump 5.8 neuf : RSN date d'avant STB/STC (aucune de ces fonctions n'est citée par CHG-281 à 296,
JM:1136, 1143-1154 ;
STD-SCN-DIAG.md:74-77) :.\Tools\RunCommandlet.ps1 -Lot STE-D -Commandlet LPDumpFunction -Args '-BP=GI -Fn=ReturnStatIfNeeded -Pins -Exec', à joindre à STE-D2. - P4. Gel annoncé (lp-mcp § 1.7),
.\Tools\Snapshot.ps1 -Lot STE-H3(GI.uasset),AssetTools.load_asset/Game/BPs/GI. - P5. Pour chaque nœud existant cité :
get_node_infos {nodes:[{refPath:"/Game/BPs/GI.GI:<Graphe>.K2Node_<Nom>"}]}; les liens doivent égaler la colonne « avant » ; tout écart arrête l'IMPL.
2.1 Conventions communes
type_id(lp-mcp § 3) : Branch =Utilitaires|ContrôleDeFlux|Branche; IsValid (fonction pure, nœudK2Node_CallFunctioncomme en CHG-290) =Utilitaires|IsValid; IsValidIndex =Utilitaires|Tableau|IsValidIndex.- Indices de broches : par direction, dans l'ordre des broches du nœud (règle déduite de lp-mcp § 3 : Branch entrées
exécution 0 / Condition 1, sorties then 0 / else 1 ; VariableSet entrées exécution 0 / valeur 1, sortie then 0).
Branch : indices établis par lp-mcp. Tous les autres (IsValid :
Objecten entrée,ReturnValueen sortie ; IsValidIndex :TargetArray,Indexen entrée,ReturnValueen sortie ; broches des nœuds existants) : le nom est donné ici, l'indice se relit parget_node_infosavantconnect_pins(lp-mcp § 3 « vérifier les autres »), la brocheselfcachée des fonctions statiques pouvant compter. Valeurs attendues (estimées, ordre des dumps) : IsValidObjectentrée 1,ReturnValuesortie 0 ; IsValidIndexTargetArrayentrée 1,Indexentrée 2,ReturnValuesortie 0. - IsValidIndex :
Indexlaissé à0(valeur par défaut, à relire) ;TargetArrayprend le typePersonau câblage (relu en CHG-282 : « tableaux typés Person »). - Cascades de
Branch, jamais de AND / OR / Select purs (lp-mcp § 1.4 et § 3-4). Une sortie de données peut alimenter plusieurs entrées : les liens existants restent. - Après chaque fonction :
compile_blueprint+hyper_blueprint_debug_inspect {blueprintAssetPath:"/Game/BPs/GI.GI", graphName:"<Graphe>"}= 0 diagnostic ;save_assets {asset_paths:["/Game/BPs/GI"]}à la fin.
2.2 G1 — setActorVar (F1, 32 dans L2) — D GI__setActorVar.txt
Avant : K2Node_FunctionEntry_0.then → K2Node_IfThenElse_2.execute (l. 121-122) ; FunctionEntry_0.Person →
VariableGet_0.self, VariableGet_1.self, VariableGet_8.self (l. 123) ; IfThenElse_2.Condition ← BooleanOR
(CommutativeAssociativeBinaryOperator_1, l. 253-257) de SaveSlot > 0 (CallFunction_5, l. 243-247) et isPlayer
(VariableGet_8, l. 258-260) ; IfThenElse_2.else (vide) (l. 252).
Après : create_node IsValid G1-V, Branch G1-B ; break_pins (FunctionEntry_0.then, IfThenElse_2.execute) ;
connect_pins : FunctionEntry_0.then → G1-B.execute (0) ; FunctionEntry_0.Person → G1-V.Object ;
G1-V.ReturnValue → G1-B.Condition (1) ; G1-B.then (0) → IfThenElse_2.execute. G1-B.else (1) : rien.
Comportement : personne nulle → aujourd'hui SaveSlot lu 0 et isPlayer lu faux (valeur effacée,
UE Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:3242-3244), OR faux, else vide : rien n'est écrit. Après : rien
n'est écrit. Identique (établi), sans les deux lectures.
2.3 G2 — getActorVar (F1, 142 dans L2) — D GI__getActorVar.txt
Écart au DIAG (STD-SCN-DIAG.md:161) : getActorVar ne lit pas Variable.Person[0] ; Person est son paramètre
d'entrée (l. 121-124). La garde est donc IsValid(Person) seul. Même constat pour setActorVar (G1).
Avant : FunctionEntry_0.then → VariableSet_0.execute (l. 122) ; Person → VariableGet_0.self (Prefix),
VariableGet_1.self (SaveSlot) (l. 123) ; FunctionResult_1.execute ← MacroInstance_1.Completed, Float = '0.0' (l. 125-127).
Après : IsValid G2-V, Branch G2-B ; break_pins (FunctionEntry_0.then, VariableSet_0.execute) ;
connect_pins : FunctionEntry_0.then → G2-B.execute ; FunctionEntry_0.Person → G2-V.Object ;
G2-V.ReturnValue → G2-B.Condition ; G2-B.then → VariableSet_0.execute ; G2-B.else → FunctionResult_1.execute.
Comportement : personne nulle → aujourd'hui clé = "" + "0" = "0" (Concat_0, l. 138-142), Map_Find(ActorVars, "0")
(l. 143-148) ; clé absente → tableau vide → Completed → FunctionResult_1 → 0.0. Après : 0.0 directement.
Identique si ActorVars n'a pas de clé "0" (R1).
2.4 G3 — ReturnStatIfNeeded (F1, 93 dans L2 ; F2 si tableau vide) — RSN (à reconfirmer, P3)
Avant : K2Node_CallFunction_81822 (GetVariable, Name ← Split.LeftS) .then → VariableSet_1019.execute (RSN:140-145) ;
BreakStruct_2805.Person_24_… → GetArrayItem_10794.Array (RSN:146-155), index 0, Output → VariableSet_1019.Person
(RSN:156-159) ; VariableSet_1019.then → CallFunction_7798.execute, Output_Get → 7798.self (RSN:39-43) ;
7798 = Person_C::QueryStat, then → FunctionResult_7, Value → FunctionResult_7.Float (RSN:160-171).
Les nœuds cités par le DIAG (_81822 → _7798) sont trouvés (établi).
Après : IsValidIndex G3-I, Branch G3-B1, IsValid G3-V, Branch G3-B2 ; break_pins (81822.then,
VariableSet_1019.execute) et (VariableSet_1019.then, 7798.execute) ; connect_pins (10) :
81822.then → G3-B1.execute ; BreakStruct_2805.Person_24_4B712C904750AD4CE1580DBEBD9E7396 → G3-I.TargetArray ;
G3-I.ReturnValue → G3-B1.Condition ; G3-B1.then → VariableSet_1019.execute ; G3-B1.else → FunctionResult_7.execute ;
VariableSet_1019.then → G3-B2.execute ; VariableSet_1019.Output_Get → G3-V.Object ; G3-V.ReturnValue →
G3-B2.Condition ; G3-B2.then → 7798.execute ; G3-B2.else → FunctionResult_7.execute.
Comportement : aujourd'hui QueryStat sur nul est sauté (ScriptCore.cpp:3234-3237) et FunctionResult_7 rend la
sortie Value jamais écrite dans ce cadre, mise à zéro à l'appel (ScriptCore.cpp:987-993) : 0.0 (STD-SCN-DIAG.md:161).
Après : même FunctionResult_7, 7798 non exécuté dans ce cadre : 0.0. Identique (estimé fort : lecture du VM).
Pas de FunctionResult neuf (aucun type_id connu en lp-mcp § 3).
2.5 G4 — CallFunction, commande setCurrentLocation (F3 _32) — D GI__CallFunction.txt
Avant : cas SwitchString_22.setCurrentLocation → CallFunction_184 (GetVariable, l. 5452-5457) ; BreakStruct_52.Person_24_…
→ GetArrayItem_73 (l. 5460-5473), Output → CallFunction_185.self ; CallFunction_186 (GetVariable(Parameters[0]))
.then → CallFunction_185.execute (l. 5479-5484) ; 185 = Person_C::setCurrentLocation, then (vide) (l. 5474-5478).
Après : IsValidIndex G4-I, Branch G4-B1, IsValid G4-V, Branch G4-B2 ; break_pins (186.then, 185.execute) ;
connect_pins (7) : 186.then → G4-B1.execute ; BreakStruct_52.Person_24_… → G4-I.TargetArray ; G4-I.ReturnValue
→ G4-B1.Condition ; G4-B1.then → G4-B2.execute ; GetArrayItem_73.Output → G4-V.Object ; G4-V.ReturnValue →
G4-B2.Condition ; G4-B2.then → 185.execute. Les deux else : rien.
Comportement : aujourd'hui 186 s'exécute, 185 est sauté, fin. Après : idem. Identique (établi).
2.6 G5 — CallFunction, commande setUntil (F3 _31) — soumise à Q2
Avant : CallFunction_187 (GetVariable, cas setUntil, l. 5501-5506) ; BreakStruct_54.Person_24_… → GetArrayItem_75
(l. 5509-5522), Output → VariableGet_139.self (Prefix) et VariableGet_140.self (SaveSlot) (l. 5523-5528) →
Concat_5 (l. 5529-5533) → CallFunction_190.Key (Map_Add(AI_Untils), l. 5567-5573) et Concat_1.D → PrintString
CallFunction_193 « (test0104) for … hours by <clé> » (l. 5586-5603) ; CallFunction_189 (GetVariable(Parameters[0]))
.then → 190.execute (l. 5538-5543) ; 190.then → 193.execute.
Après : IsValidIndex G5-I, Branch G5-B1, IsValid G5-V, Branch G5-B2 ; break_pins (189.then, 190.execute) ;
connect_pins (7) : 189.then → G5-B1.execute ; BreakStruct_54.Person_24_… → G5-I.TargetArray ; G5-I.ReturnValue
→ G5-B1.Condition ; G5-B1.then → G5-B2.execute ; GetArrayItem_75.Output → G5-V.Object ; G5-V.ReturnValue →
G5-B2.Condition ; G5-B2.then → 190.execute. Les deux else : rien.
Comportement : modifié. Aujourd'hui, personne nulle : Map_Add(AI_Untils, "0", Until) puis la ligne « by 0 ». Après :
ni l'un ni l'autre. Le chemin d'origine ne peut pas être gardé : le PrintString relit Prefix / SaveSlot du nul (Q2, R2).
2.7 G6 — CallFunction, commande getBuilding (F3 _33)
Avant : cas SwitchString_22.getBuilding → CallFunction_178 (GetVariable, l. 312, 5339-5344) ; BreakStruct_48.Person_24_…
→ GetArrayItem_71 (l. 5347-5360), Output → CallFunction_179.self ; 178.then → 179.execute ; 179 =
Person_C::getBuilding, then → CallFunction_180.execute, Building → 180.Building (l. 5361-5366) ; 180 =
AddVariable(VariableName, Class 'Building') (l. 5373-5384).
Après : IsValidIndex G6-I, Branch G6-B1, IsValid G6-V, Branch G6-B2 ; break_pins (178.then, 179.execute) ;
connect_pins (9) : 178.then → G6-B1.execute ; BreakStruct_48.Person_24_… → G6-I.TargetArray ; G6-I.ReturnValue
→ G6-B1.Condition ; G6-B1.then → G6-B2.execute ; GetArrayItem_71.Output → G6-V.Object ; G6-V.ReturnValue →
G6-B2.Condition ; G6-B2.then → 179.execute ; G6-B1.else → 180.execute ; G6-B2.else → 180.execute.
Comportement : aujourd'hui 179 est sauté et 180 définit la variable avec Building nul (sortie jamais écrite, cadre
mis à zéro, ScriptCore.cpp:987-993). Après : 180 reçoit la même sortie non écrite. Identique (estimé fort).
2.8 Correspondance nom compilé → nœud (F3)
Le suffixe _N de CallFunc_Array_Get_Item_N ne se lit pas dans un dump : il vient de l'ordre de compilation (§ 6). La
correspondance est établie par empreinte dans L2 :
- les 24 « (test0104) for … hours by 0 » viennent de
setUntil(CallFunctionl. 5599-5603 :by+Prefix+SaveSlot, soit"" + "0"pour un nul ; les PNJ valides imprimentby 1àby 4, 7 ligneshours by [^0]dans L2) ; _31= 96 = 4 × 24 (setUntilévalue deux fois le getter, pourMap_AddpuisPrintString, et lit deux propriétés : L2:20353-20387) ;_32= 24 = 1 × 24 (setCurrentLocation, un appel par routine) ;_33= 33 ≥ 24 (getBuilding, placé avant les branches des routines, deux fois dansmeal.lpai) ;- ordre dans L2:20255-20411 : 3 ×
getActorVar,_33,_32,_31× 4, « by 0 »,setActorVar, soit la suite deD:\Game\LifePlay-master 5.8\Content\Modules\vin_Base\AI\entertainment.lpai:7-20. Statut : estimé fort (comptes rejouables) ; la VAL le confirme (comptes à 0, § 7).
3. Repli
- Avant écriture : instantané
.\Tools\Snapshot.ps1 -Lot STE-H3(P4). - Échec de compilation, diagnostic ou lien relu différent : arrêt,
.\Tools\Restore.ps1 -Lot STE-H3éditeur fermé (GI entier, pas de retour partiel), puis contrôle MD5 =d93785fc…. - Après commit (gardien) :
git revertdu commit du ticket STE-H3. - G5 se retire seule (refus à Q2) : G4 et G6 restent valables. G1 à G3 sont indépendantes de G4 à G6.
4. Risques R#, questions Q#
Écart É1 (arrêt partiel, fiche § 9) : CallFunc_Array_Get_Item_41 (14 dans L2) est en tête de pile
GI_C:CallFunctionReturnBool (L2:21377-21397 ; Grep multiligne : 153 lignes F3 sous CallFunction: et 14 sous
CallFunctionReturnBool:), sous PlayScene → CheckConditionsOther → CheckEachCondition. Le DIAG la range dans
CallFunction (STD-SCN-DIAG.md:163). Aucun dump de CallFunctionReturnBool : garde non spécifiée. Commande proposée
(à joindre à STE-D2) : .\Tools\RunCommandlet.ps1 -Lot STE-D -Commandlet LPDumpFunction -Args '-BP=GI -Fn=CallFunctionReturnBool -Pins -Exec'.
Empreinte relevée : 1 F2 puis 2 « Accessed None » par lecture (même forme que setUntil).
Q1 (utilisateur) — « acteur vide = état normal ? » (fiche, point (a)) : non tranchable par les seuls dumps. Établi :
- Cas A, conditions des
.lpscene(CheckConditionsOther, ex.meet_new_person.lpscene:5isWithCompanion() && Random(0, 200) < CurrentCompanion:interpersonal,STD-SCN-DIAG.md:33-37) : l'absence est prévue par le contenu, qui la teste ; le calcul évalue tous les termes. État normal : concerne G3. - Cas B, routines d'IA
.lpailancées parPlayScene(24 démarrages « by 0 », tous entre 21:32:09 et 21:32:21, L2:20397 à 29995) : la variableAIa un tableauPersonde longueur 0, donc elle est absente (L2:20327). Or le moteur ajoute toujoursAI=[AIDummy](longueur 1) avant les routines (EGB:25006-25037SpawnDummy→AIDummy→AddVariable('AI')CallFunction_779; EGB:25149-25171AddVariable('AI')CallFunction_739). Le contenu des 17.lpaisupposeAIprésent (Grep\.setUntil\(sousContent\Modules: 23 fichiers, dont les 17.lpaidevin_Base\AI). Estimé : pas un état normal du contenu, mais un défaut d'enchaînement du moteur (variableAIretirée ou jamais posée pendant la rafale ; cause non identifiée). Concerne G1, G2, G4, G5, G6 et une partie de G3. - Question : (A) poser maintenant toutes les gardes (résultat identique sauf Q2 et R1 ; le défaut du cas B est masqué et
instruit à part, hypothèse H5 ci-dessous) ; ou (B) ne poser que G3 (cas A) et instruire H5 d'abord.
H5 proposée (N3, lp-cart) : pourquoi
AIest absente pendant la rafale 21:32:09-21 (dumps STE-D2 de l'EventGraph : boucle des routinesCheckingAiIndex, macroAsyncItersPerTck = 7EGB:24915-24918, effacement des variables de scène).
Q2 (utilisateur) : accepter que G5 supprime l'écriture AI_Untils["0"] et la ligne « (test0104) … by 0 » quand AI est
vide ? Sinon G5 est retirée et _31 (96) reste.
Q3 (utilisateur) : étendre plus tard aux lectures F2 restantes (sites d'appel getActorVar CallFunction_141,
setActorVar CallFunction_150, modifyActorVar CallFunction_144 qui passent Person[0] en paramètre ; _30, 4 lignes,
L2:12087-22406 ; _41) ? Chaque cas demande un second appel avec personne nulle sur le chemin « non valide ».
Choix C++ / Blueprint (fiche, point (b)) : gardes Blueprint IsValidIndex + IsValid. Motifs : Person_C est une
classe Blueprint, une fonction C++ GetPersonAtOrNone ne peut la rendre typée que par un thunk générique (comme
Array_Get) ou rendre AActor* / UObject* et ajouter un Cast par site (compatibilité de type des tableaux en
Blueprint : non vérifiée) ; il faut de toute façon un IsValid + Branch avant chaque appel (le nul reste un nul) ;
coût d'un build C++, d'un test et d'un ticket de plus. CHG-283 a pu le faire car FString est natif. Les gardes
Blueprint suivent CHG-282 / CHG-291 (JM:1153, 1144) : 4 nœuds par site, sans build.
- R1 : clé
"0"= joueur ?getActorVarsur nul lit aujourd'huiActorVars["0"]. Si le joueur aPrefixvide etSaveSlot0 (estimé :setActorVaradmetisPlayeren plus deSaveSlot > 0, DGI__setActorVar.txt:243-257; des PNJ ontPrefixvide, EGB:25082-25093), la valeur rendue aujourd'hui est celle du joueur, et G2 rend 0.0. Essai qui tranche :LPDumpSave -File=<sauvegarde de la partie STB-JEU2> -Out=<txt>(lp-commandlets) et recherche d'une clé"0"dansActorVarsetAI_Untils. - R2 : G5 change l'état (
AI_Untils["0"]) et retire le dénominateur « by 0 » du DIAG ; normaliser parCHECKING:. - R3 : correspondance
_31/_32/_33estimée (§ 2.8) ; la 2e ligne F2 avant chaque_33(L2:20327) n'est pas expliquée (incertain). Si un compte F3 deCallFunctionreste > 0 en VAL : rapport, pas de correctif improvisé. - R4 : STE-GI modifie GI avant H3 : noms de nœuds à recontrôler (P2, P5).
- R5 : G3 repose sur un dump antérieur à STB / STC (P3).
- R6 : évaluation des nœuds purs :
GetArrayItemest évalué pourIsValidpuis pour l'appel ; sans avertissement car l'index est valide à ce moment-là (UERuntime\Engine\Private\KismetArrayLibrary.cpp:466-468). - R7 : F2 ne tombe pas à 0 : restent les sites de Q3,
_41,_30et les autres lecteurs dePerson[0](96 lignesPerson_24 ->dansCallFunction, Grep^LogLPDump: Warning:.*Person_24_4B712C904750AD4CE1580DBEBD9E7396 ->). - R8 : masquage (Q1 cas B) : les gardes cachent le symptôme d'un défaut d'enchaînement de l'IA.
Nœuds de l'EventGraph cités d'après EGB (antérieur à STC), à reconfirmer sur dumps\GI__EventGraph.txt (STE-D2) :
K2Node_CustomEvent_404 PlayScene (EGB:6002-6005) ; K2Node_CommutativeAssociativeBinaryOperator_74 et
K2Node_CallFunction_778 (PrintString « (test0104) », execute vide, donc le fichier joué n'est jamais écrit au
journal, EGB:25133-25148) ; K2Node_CallFunction_768 SpawnDummy (EGB:25006-25010) ; K2Node_VariableSet_258
AIDummy (EGB:25011-25016) ; K2Node_CallFunction_779 AddVariable('AI') et K2Node_MakeArray_14 (EGB:25017-25037) ;
K2Node_CallFunction_739 AddVariable('AI'), K2Node_MakeArray_3, K2Node_VariableGet_525 (EGB:25149-25171) ;
K2Node_VariableSet_259 CheckingPkgIndex (EGB:24862-24866) ; K2Node_CallFunction_745 getAllSlots (EGB:24911-24913) ;
K2Node_MacroInstance_49 Async (EGB:24915-24918) ; K2Node_CallFunction_5384 GetAllFilesFromFolder(Ext 'lpai')
(EGB:24638-24643) ; K2Node_CustomEvent_72 ContinueAiAfterLoad (EGB:24623-24625). Aucun n'est modifié par cette SPEC.
5. Interdits
- Aucune modification de l'EventGraph, de
CallFunctionReturnBool(É1), des sites d'appel de Q3, du C++. - Aucune correction de contenu (
Content\Modules\…\*.lpai,.lpscene), aucun nœud AND / OR / Select pur, aucunFunctionResultcréé, aucundelete_node. - Pas d'écriture HyperAIStudio (lp-mcp § 1.1) ; outils Epic seulement ; pas d'IMPL sans P1 à P5.
- Pas de commit par l'agent : ticket au gardien (lp-repo).
6. Valeurs moteur lues dans le moteur installé (UE = D:\Game\Launcher\Engine\UE_5.8\Engine\Source\)
- Message F1 / F3 : UE
Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:3213-3216(« Accessed None trying to read (real) property X in not an UClass », X = variable qui tient le nul) ; contexte nul : expression sautée et valeur de retour effacée,:3234-3244. - Cadre d'une fonction script non persistant mis à zéro :
ScriptCore.cpp:987-993. - Lecture hors bornes : message F2 puis élément remis à sa valeur par défaut (nul) :
UE
Runtime\Engine\Private\KismetArrayLibrary.cpp:466-479. K2Node_GetArrayItemnon « par référence » devient un appelArray_Get, d'où le nom compiléCallFunc_Array_Get_Item: UEEditor\BlueprintGraph\Private\K2Node_GetArrayItem.cpp:335-349.- Suffixe
_N= n-ième doublon du nom de base : UEEditor\KismetCompiler\Public\KismetCompilerMisc.h:287-302; ordre d'enregistrement = liste d'exécution linéaire :Editor\KismetCompiler\Private\KismetCompiler.cpp:3918-3927, construite parEditor\KismetCompiler\Private\EdGraphCompiler.cpp:244-249(RemoveAtSwap) : le suffixe ne se déduit pas d'un dump.
7. Critères de VAL (commande → attendu)
- Dumps après IMPL,
.\Tools\RunCommandlet.ps1 -Lot STE-H3 -Commandlet LPDumpFunction -Args '-BP=GI -Fn=<f> -Pins -Exec': nœudssetActorVar32 → 34,getActorVar15 → 17,ReturnStatIfNeeded95 → 99,CallFunction1 538 → 1 550 (1 546 sans G5) ; liens du § 2 relus ;DiffRemplacementNoeuds.pysans autre écart. hyper_blueprint_debug_inspect0 diagnostic par graphe ;CompileAllBlueprintséditeur fermé : 0 erreur (lp-validate).- Journal de jeu (build Development, parcours de STB-JEU2 : nouvelle partie, ≥ 20 actions seul, ≥ 3 min en ville,
STD-SCN-DIAG.md:198-206), Grep en modecount:- F1 ciblée multiligne (§ 1) → 0 (L2 : 267) ;
property CallFunc_Array_Get_Item_3[123]→ 0 (L2 : 153) ; sans G5 :_3[23]→ 0,_31inchangé ;property CallFunc_Array_Get_Item_41→ information seulement (L2 : 14) ;property Person in→ seulement des lignes hors des 3 fonctions (L2 : 270 dont 267 ciblées) ;Person_24_4B712C904750AD4CE1580DBEBD9E7396' of length 0/CHECKING:→ inférieur à L2 (351 / 2 318 = 0,151) ;hours by 0→ 0 si G5 (L2 : 24) ;hours by [1-9]→ ≥ 1 si le parcours contient des routines de PNJ valides (L2 : 7), non-régression de l'IA ;- dénominateur :
CHECKING:(L2 : 2 318) ;index SPAWN> 0 avant de mesurer (lp-validate § 5).
- R1 / Q2 :
LPDumpSaveavant / après sur la même sauvegarde : clés"0"deActorVarsetAI_Untilsrelevées.
Fichiers à commiter (dépôt jeu, branche ue5.8, ticket au gardien) :
- A
Docs/Migration/etat/ST/STE/STE-H3-SPEC.md
Tours : 34 / 60
Constats
- Commandes de comptage rejouées (Grep, mode
count, sur L2) :property CallFunc_Array_Get_Item_31→ 96 ;property CallFunc_Array_Get_Item_32→ 24 ; multiligne F3 sousCallFunction:→ 153, sousCallFunctionReturnBool:→ 14 (somme 167 =STD-SCN-DIAG.md:26) ; F1 multiligne des 3 fonctions → 267 ;hours by 0→ 24 lignes ;hours by [^0]→ 7 lignes. - Dans
CallFunction, 96 lignesPerson_24 ->(Grep cité en R7), dont 35 nœudsGetArrayItemdont la sortie va à unself(Grep multiligneArray +-> K2Node_\w+\.Person_24_\w+\r?\n[^\n]*Dimension 1[^\n]*\r?\n[^\n]*Output +-> [^\n]*\.self, 35 blocs) : seuls les 3 de G4 à G6 sont observés en défaut dans L2. - Grep d'un dossier sous
etat\: les.txty sont ignorés par git ; passerglob(ex.*__*.txt) ou le fichier enpath, sinon 0 résultat trompeur (essai de cette fiche). - Journal et gabarits lus aux chemins DOCMV :
D:\Game\LifePlay-master 5.8\Docs\Journal_Modifications.md,D:\Game\LifePlay-master 5.8\.claude\skills\lp-doc\gabarits.md.