30 KiB
Fiche STE-H3b — 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-H3b-SPEC : gardes F2 / F3 restantes du moteur de scènes (sites get / set / modifyActorVar, _30, _41) (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. Suite de
STE-H3-SPEC.md (gardes G1 à G6) : mêmes conventions (§ 2.1 de H3S), numérotation G7 et suivantes, R9 et Q4 et suivants.
Statut : partiel. 4 gardes spécifiées (G7, G8, G10, G11) ; G9 (modifyActorVar) arrêtée : dump de la fonction
absent (§ 2.4) ; G10 et G11 ont deux variantes, choix de l'utilisateur (Q4, Q5).
Abréviations (chemins absolus) :
- D =
D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STE\dumps\; CF = DGI__CallFunction.txt; CRB = DGI__CallFunctionReturnBool.txt(585 nœuds, STE-D2) ; GAV = DGI__getActorVar.txt; - H3S =
D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STE\STE-H3-SPEC.md; - L2 =
D:\Game\LifePlay_Build_5.8_STB-JEU2_Development\Windows\LifePlay\Saved\Logs\LifePlay.log(journal STB-JEU2) ; - AI =
D:\Game\LifePlay-master 5.8\Content\Modules\vin_Base\AI\(routines.lpai) ; - UE =
D:\Game\Launcher\Engine\UE_5.8\Engine\Source\(moteur installé, lu).
État du Blueprint : MD5 de Content\BPs\GI.uasset = 606eb43714c1f4317300b797edd02e62 (commande
md5sum "/d/Game/LifePlay-master 5.8/Content/BPs/GI.uasset"), égal à l'état STE-GI (STE-TACHES.md:17, « GI 606EB437… ») ;
git status --short -- Content/BPs/GI.uasset = M (STE-GI non commité) ; dernier commit du fichier bc4d91f (STC).
Les dumps D datent de STE-D / STE-D2 (MD5 d93785fc…) ; STE-GI n'a touché que l'EventGraph (fiche § 3) : les nœuds de
CallFunction et CallFunctionReturnBool cités ici sont ceux du GI actuel (estimé fort ; contrôle P4). STE-H3 (G1-G6)
n'est pas encore implémentée (STE-TACHES.md:19).
1. Objectif mesurable
Supprimer, sans changer ce que le jeu fait, les lectures restantes de personnage vide citées par Q3 de H3S
(H3S:196-198, décision « oui, fiche à part », STE-TACHES.md:32). Référence L2, comptes Grep rejouables (§ Constats) :
| Famille (motif Grep sur le journal de jeu) | L2 | Attendu après H3 + H3b |
|---|---|---|
F3, property CallFunc_Array_Get_Item_41 (CallFunctionReturnBool) |
14 | 0 (G11) |
F3, property CallFunc_Array_Get_Item_30 (CallFunction) |
4 | 0 (G10 ; 4 si Q4 = c) |
F2 suivie d'un F1 dans getActorVar (multiligne, § Constats) |
71 | F2 du site supprimée (G7) |
F2 suivie d'un F1 dans setActorVar (multiligne) |
16 | F2 du site supprimée (G8) |
F2 suivie de _41 ou de Per (multiligne) |
9 (7 + 2) | 2 (les 2 Per de getRelatedPerson restent, R13) |
F2 Person_24_4B712C904750AD4CE1580DBEBD9E7396' of length 0 / CHECKING: |
351 / 2 318 | baisse de 94 lignes (71 + 16 + 7) à parcours égal, en plus de H3 |
property Per in (getRelatedPerson) |
4 | 4 (hors SPEC, R13) |
Gardes : CallFunction site getActorVar (G7, 2 nœuds), site setActorVar (G8, 2 nœuds), site modifyActorVar
(G9, arrêtée), commande getUntil (G10, _30, 7 nœuds en variante a) ; CallFunctionReturnBool commande
hasRelationship (G11, _41, 6 nœuds en variante a). Total (variantes a) : 17 nœuds créés, 4 break_pins,
37 connect_pins, 3 set_pin_value (+ relectures), 0 suppression.
2. Fichiers touchés, ordre
Un seul fichier : Content\BPs\GI.uasset, graphes de fonction CallFunction (G7, G8, G10) et CallFunctionReturnBool
(G11). Ni l'EventGraph, ni les fonctions appelées (getActorVar, setActorVar, modifyActorVar, getRelatedPerson,
hasRelationship), ni le C++, ni le contenu des modules. Ordre : après l'IMPL de STE-H3 (G1 à G6), puis G8, G7
(exige G2), G11, G10. G9 : non exécutable (§ 2.4).
2.0 Préalables (dans l'ordre, avant tout create_node)
- P1. IMPL STE-H3 faite (G1-G6 compilées, enregistrées) ; réponses de l'utilisateur à Q4 (G10) et Q5 (G11).
- P2. Dumps « avant » neufs des 2 graphes (GI a changé avec STE-GI puis changera avec H3) :
.\Tools\RunCommandlet.ps1 -Lot STE-H3b -Commandlet LPDumpFunction -Args '-BP=GI -Fn=CallFunction -Pins -Exec'et... -Args '-BP=GI -Fn=CallFunctionReturnBool -Pins -Exec'; MD5 deGI.uassetrelevé (valeur de retour du repli). - P3. Gel annoncé (lp-mcp § 1.7),
.\Tools\Snapshot.ps1 -Lot STE-H3b(GI.uasset),AssetTools.load_asset/Game/BPs/GI. - P4. 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 » (§ 2.2 à 2.6) ; tout écart arrête la garde concernée. - P5.
type_idhors lp-mcp § 3 (G10, G11 seulement), lus parfind_node_types {graph:{refPath:"/Game/BPs/GI.GI:<Graphe>"}, type_id_filter:"<filtre>", context_pins:[]}; aprèscreate_node,get_node_infosdoit montrer la classe et la fonction attendues, sinon arrêt et repli (§ 3) :
| Nœud | Filtre | Attendu (estimé) | Contrôle get_node_infos |
|---|---|---|---|
| AddVariable (G10-A) | AddVariable |
Classe|GI|AddVariable (forme lp-mcp § 3) |
appel GI_C::AddVariable, broches comme CallFunction_203 |
| Map Find (G10-F, variante a) | Map puis Find |
catégorie Utilities|Map, nom Find (UE Runtime\Engine\Classes\Kismet\BlueprintMapLibrary.h:48-49), libellé localisé à lire |
fonction Map_Find, pure |
| Make Array (G10-M) | Array / Tableau |
nœud K2Node_MakeArray (libellé localisé incertain) |
classe K2Node_MakeArray |
| hasRelationship (G11-H, variante a) | hasRelationship |
Classe|GI|hasRelationship |
appel GI_C::hasRelationship, pur (pas de broche execute) comme CallFunction_177622 |
| Set BoolToReturn (G11-S) | BoolToReturn |
Variables|…|DéfinirBoolToReturn (lp-mcp § 3) |
K2Node_VariableSet de la même variable que VariableSet_57739 (` |
2.1 Conventions communes
Reprises à l'identique de H3S § 2.1 (H3S:55-70) : type_id Branch = Utilitaires|ContrôleDeFlux|Branche, IsValid =
Utilitaires|IsValid, IsValidIndex = Utilitaires|Tableau|IsValidIndex ; indices de broches par direction (Branch
entrée exécution 0 / Condition 1, sorties then 0 / else 1 ; VariableSet entrées exécution 0 / valeur 1, sortie then 0 ;
tous les autres relus par get_node_infos avant connect_pins, valeurs attendues estimées : IsValid Object entrée 1,
ReturnValue sortie 0 ; IsValidIndex TargetArray entrée 1, Index entrée 2, ReturnValue sortie 0) ; IsValidIndex
Index laissé à 0 (relu) ; cascades de Branch, jamais AND / OR / Select purs ; une sortie de données peut alimenter
plusieurs entrées, une entrée d'exécution peut recevoir plusieurs liens ; après chaque graphe : compile_blueprint +
hyper_blueprint_debug_inspect {blueprintAssetPath:"/Game/BPs/GI.GI", graphName:"<Graphe>"} = 0 diagnostic ;
save_assets {asset_paths:["/Game/BPs/GI"]} à la fin.
Ajouts H3b : nom complet de la broche du tableau = Person_24_4B712C904750AD4CE1580DBEBD9E7396 (noté Person_24_…) ;
broches génériques (wildcard) : câbler d'abord la broche typée (G10-F.TargetMap avant Key ; G10-M.Array vers
G10-A.Float avant [0]), puis set_pin_value ; valeur littérale relue par get_node_infos.
« Chemin non valide » (lp-mcp § 4) : refaire ce que l'exécution fait aujourd'hui avec la référence nulle. Avec un contexte
nul, la VM saute l'expression et efface la valeur rendue (UE Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:3234-3244) :
Prefix lu = "", SaveSlot lu = 0, donc la clé Prefix + Conv_IntToString(SaveSlot) vaut "0" (établi).
2.2 G7 — site getActorVar de CallFunction (F2 : 71 dans L2) — CF
Avant : CallFunction_141 (GetVariable, cas SwitchString_22.getActorVar) .then → CallFunction_142.execute,
Variable → BreakStruct_40 (CF:4793-4798) ; BreakStruct_40.Person_24_… → GetArrayItem_51.Array (CF:4801-4809),
index 0, Output → 142.Person (CF:4811-4814) ; 142 = getActorVar (fonction de GI, self vide), then →
CallFunction_143.execute, Var ← GetArrayItem_52, Float → MakeArray_96.[0] (CF:4815-4821) ; 143 = AddVariable
(Name ← VariableGet_103, Class = 'Float', Float ← MakeArray_96), then vide (CF:4828-4846).
Après : IsValidIndex G7-I, Branch G7-B ; break_pins (141.then, 142.execute) ; connect_pins (5) :
141.then → G7-B.execute (0) ; BreakStruct_40.Person_24_… → G7-I.TargetArray ; G7-I.ReturnValue → G7-B.Condition (1) ;
G7-B.then (0) → 142.execute ; G7-B.else (1) → 143.execute.
Comportement : aujourd'hui, tableau vide → F2 (UE Runtime\Engine\Private\KismetArrayLibrary.cpp:472-478), getActorVar(None)
rend, une fois G2 posée, FunctionResult_1.Float = '0.0' (GAV:125-127, H3S § 2.3), puis 143 écrit [0.0]. Après :
142 non exécuté, 143 lit la sortie Float de 142 jamais écrite dans ce cadre ; le cadre de CallFunction (fonction,
pas l'ubergraph) est alloué et mis à zéro à chaque appel (UE ScriptCore.cpp:984-993 ; cadre persistant réservé à
l'ubergraph, UE Runtime\Engine\Private\BlueprintGeneratedClass.cpp:1882-1897) : [0.0]. Identique à l'état après G2
(estimé fort) ; par rapport à l'état actuel (avant G2), identique si ActorVars n'a pas de clé "0" (R1 de H3S, déjà
accepté par Q1 = A). Élément nul dans un tableau de longueur 1 : pas de F2, G2 le traite dans getActorVar (R14).
2.3 G8 — site setActorVar de CallFunction (F2 : 16 dans L2) — CF
Avant : CallFunction_150 (GetVariable, cas setActorVar) .then → CallFunction_162.execute, Variable →
BreakStruct_45 (CF:4851-4860) ; BreakStruct_45.Person_24_… → GetArrayItem_63.Array (CF:4867), index 0, Output →
162.Person (CF:4869-4872) ; 162 = setActorVar (Var ← GetArrayItem_64, Float ← GetArrayItem_65), then vide
(CF:4873-4879).
Après : IsValidIndex G8-I, Branch G8-B ; break_pins (150.then, 162.execute) ; connect_pins (4) :
150.then → G8-B.execute ; BreakStruct_45.Person_24_… → G8-I.TargetArray ; G8-I.ReturnValue → G8-B.Condition ;
G8-B.then → 162.execute. G8-B.else : rien.
Comportement : setActorVar(None) n'écrit rien, avant comme après G1 (H3S § 2.2, établi), et 162.then est vide. Après :
rien n'est appelé. Identique (établi).
2.4 bis G9 — complément de l'orchestrateur LOT STE (2026-10-10, après STE-D3)
Dump STE-D3 dumps\GI__modifyActorVar_D3.txt (31 nœuds, code 0). modifyActorVar(Person = None) : Prefix et
SaveSlot lus sur la personne vide (avertissements Accessed None), clé Concat("" , "0") = "0", Map_Find
puis boucle, puis Map_Add(ActorVars, "0", …) : écriture parasite de ActorVars["0"] (CallFunction_1,
CallArrayFunction_1). Les 5 fonctions déjà dumpées sont identiques ligne pour ligne entre STE-D / STE-D2 et STE-D3
(GI 606EB437…) : les nœuds cités par cette SPEC restent valables.
Forme retenue : celle de G8. IsValidIndex G9-I, Branch G9-B ; break_pins (CallFunction_144.then,
CallFunction_163.execute) ; connect_pins (4) : 144.then → G9-B.execute ; BreakStruct_39.Person_24_… →
G9-I.TargetArray ; G9-I.ReturnValue → G9-B.Condition ; G9-B.then → 163.execute. G9-B.else : rien
(163.then est vide, CF:5143-5149).
Comportement : avec une personne, identique ; sans personne, l'écriture ActorVars["0"] et les avertissements
disparaissent. Décision de l'utilisateur (2026-10-10, dans la session LOT STE) : « Oui, poser G9 », par analogie avec Q2 (G5).
L2 : 0 occurrence (Grep GI_C:modifyActorVar = 0).
2.4 G9 — site modifyActorVar de CallFunction — arrêtée (dump manquant)
Structure relevée : CallFunction_144 (GetVariable, cas modifyActorVar) .then → CallFunction_163.execute,
Variable → BreakStruct_39 (CF:5111-5120) ; BreakStruct_39.Person_24_… → GetArrayItem_49.Array (CF:5127), index 0,
Output → 163.Person (CF:5129-5132) ; 163 = modifyActorVar (Var ← GetArrayItem_50, Float ← GetArrayItem_53),
then vide (CF:5143-5149). Forme probable : celle de G8 (IsValidIndex + Branch, else vide).
Blocage : ce que fait modifyActorVar(None) (chemin « non valide ») ne se lit dans aucun dump (Glob **/*modifyActorVar*
sous etat\ : 0 fichier). Garde non spécifiée, sans improviser. Commande à joindre à un STE-D3 :
.\Tools\RunCommandlet.ps1 -Lot STE-D -Commandlet LPDumpFunction -Args '-BP=GI -Fn=modifyActorVar -Pins -Exec'.
Constat L2 : 0 lecture fautive dans modifyActorVar (Grep GI_C:modifyActorVar : 0 ligne) ; la F2 de ce site, si elle
existe, n'est pas attribuable (le message F2 ne nomme pas la fonction).
2.5 G10 — commande getUntil de CallFunction (F3 _30, 4 dans L2) — CF, variante selon Q4
Avant : CallFunction_200 (GetVariable, cas getUntil) .then → CallFunction_203.execute, Variable → BreakStruct_56
(CF:5674-5683) ; BreakStruct_56.Person_24_… → GetArrayItem_78.Array (CF:5690), index 0, Output → VariableGet_150.self
(Prefix) et VariableGet_151.self (SaveSlot) (CF:5692-5701) → Conv_IntToString 201 et Concat_StrStr
CommutativeAssociativeBinaryOperator_3 → CallFunction_202.Key (CF:5702-5710) ; 202 = Map_Find pur, TargetMap ←
VariableGet_152.AI_Untils, Value → MakeArray_147.[0] (CF:5711-5719) ; 203 = AddVariable (Name ←
VariableGet_153.VariableName, Class = 'Float', Array = 'false', Bool ← MakeArray_149, Float ← MakeArray_147,
String ← MakeArray_148, Person ← MakeArray_146, Building vide), then vide (CF:5720-5742).
Pourquoi pas « else → 203 » comme G6 : l'entrée Float de 203 vient d'une chaîne pure (Map_Find ← Concat ←
Prefix / SaveSlot ← GetArrayItem_78), réévaluée quand 203 s'exécute : les deux lectures fautives resteraient.
Le chemin « non valide » doit donc rejouer AddVariable avec la clé "0".
Après, variante a (rejeu exact) : IsValidIndex G10-I, Branch G10-B1, IsValid G10-V, Branch G10-B2, Map Find
G10-F, Make Array G10-M, AddVariable G10-A (7 nœuds) ; break_pins (200.then, 203.execute) ; connect_pins (16) :
200.then→G10-B1.execute; 2.BreakStruct_56.Person_24_…→G10-I.TargetArray; 3.G10-I.ReturnValue→G10-B1.Condition;G10-B1.then→G10-B2.execute; 5.GetArrayItem_78.Output→G10-V.Object; 6.G10-V.ReturnValue→G10-B2.Condition;G10-B2.then→203.execute; 8.G10-B1.else→G10-A.execute; 9.G10-B2.else→G10-A.execute;VariableGet_152.AI_Untils→G10-F.TargetMap; 11.G10-F.Value→G10-M.[0]; 12.G10-M.Array→G10-A.Float;VariableGet_153.VariableName→G10-A.Name; 14.MakeArray_149.Array→G10-A.Bool; 15.MakeArray_148.Array→G10-A.String; 16.MakeArray_146.Array→G10-A.Person.set_pin_value:G10-F.Key=0(chaîne) ;G10-A.Class= valeur relue sur203(Float) ;G10-A.Array=false(relire, ne poser que si le défaut diffère).G10-A.then: rien (comme203). Comportement (a) : aujourd'hui, personne nulle →Until = [Map_Find(AI_Untils, "0").Value], soit la valeur de la clé"0"si elle existe, sinon la valeur remise à zéro (UERuntime\Engine\Private\BlueprintMapLibrary.cpp:35-55,ResetToDefaultl. 49) : 0.0. Après : même appel, même clé, mêmeAddVariable. Identique (établi par construction). Variante b (valeur neutre) : sansG10-F(6 nœuds, 14 liens : sans 10 et 11),G10-M.[0]=0.0. Diffère de l'actuel quandAI_Untilsa une clé"0"(Q4). Variante c : pas de garde (_30reste à 4 lignes).
2.6 G11 — commande hasRelationship de CallFunctionReturnBool (F3 _41, 14 dans L2 ; F2 : 7) — CRB, variante selon Q5
Avant : cas SwitchString_77.hasRelationship → CallFunction_177620 (GetVariable, CRB:162, 1267-1272), Name ←
VariableGet_128293.ActualVariable, .then → VariableSet_57739.execute, Variable → BreakStruct_6891 (CRB:1273-1276) ;
BreakStruct_6891.Person_24_… → GetArrayItem_12254.Array (CRB:1283), index 0, Output → VariableGet_128294.self
(Prefix) et VariableGet_128295.self (SaveSlot) (CRB:1285-1294) → Conv_IntToString 177621 et Concat_StrStr
CommutativeAssociativeBinaryOperator_16749 → CallFunction_177622.Slot (CRB:1295-1303) ; 177622 = hasRelationship
pur, Types ← VariableGet_128296.ActualParameters, sortie hasRelationship → VariableSet_57739.BoolToReturn
(CRB:1304-1310) ; VariableSet_57739.then → IfThenElse_8994.execute (CRB:1311-1315) ; IfThenElse_8994 : Condition ←
Reverse, then → FunctionResult_0 (rend !BoolToReturn), else → FunctionResult_1 (rend BoolToReturn)
(CRB:300-302, 325-338).
Même raison qu'en G10 : l'entrée de VariableSet_57739 vient d'une chaîne pure, réévaluée ; le chemin « non valide »
rejoue l'affectation.
Après, variante a (rejeu exact) : IsValidIndex G11-I, Branch G11-B1, IsValid G11-V, Branch G11-B2,
hasRelationship G11-H, Set BoolToReturn G11-S (6 nœuds) ; break_pins (177620.then, VariableSet_57739.execute) ;
connect_pins (12) :
177620.then→G11-B1.execute; 2.BreakStruct_6891.Person_24_…→G11-I.TargetArray; 3.G11-I.ReturnValue→G11-B1.Condition; 4.G11-B1.then→G11-B2.execute; 5.GetArrayItem_12254.Output→G11-V.Object;G11-V.ReturnValue→G11-B2.Condition; 7.G11-B2.then→VariableSet_57739.execute; 8.G11-B1.else→G11-S.execute; 9.G11-B2.else→G11-S.execute; 10.VariableGet_128296.ActualParameters→G11-H.Types;G11-H.hasRelationship→G11-S.BoolToReturn(entrée 1) ; 12.G11-S.then(0) →IfThenElse_8994.execute.set_pin_value:G11-H.Slot=0(chaîne). Comportement (a) : aujourd'hui, personne absente → F2,BoolToReturn = hasRelationship("0", Types), puisIfThenElse_8994. Après : même appel pur avecSlot = "0", même variable, même suite. Identique (établi par construction). Variante b (valeur neutre) : sansG11-H(5 nœuds, 10 liens : sans 10 et 11),G11-S.BoolToReturn=false(relu). Identique seulement sihasRelationship("0", …)est faux (Q5). Variante c : pas de garde.
2.7 Correspondance nom compilé → nœud (_30, _41)
Méthode de H3S § 2.8 (le suffixe _N ne se lit pas dans un dump) : empreinte dans L2 et contenu joué.
_41=GetArrayItem_12254(hasRelationship), estimé fort :- empreinte : par événement, 1 F2 puis 2 lectures
_41(L2:21375-21397), soit unArray_Getsur tableau vide dont la sortie est lue par 2 propriétés dans une seule évaluation ; dans CRB, 4GetArrayItemont une sortie vers 2self(GrepOutput +-> K2Node_VariableGet_\d+\.self, K2Node_VariableGet_\d+\.self: CRB:709, 738, 1288, 2522), soitisSameGender(519,521),hasRelationship(12254),wantsBabies(34) ; - moment : les 7 événements (14 lignes : L2:21377, 21388, 22906, 22917, 24344, 24355, 25676, 25687, 26940, 26951, 28458,
28469, 29515, 29526) tombent entre 21:32:11.093 et 21:32:21.141, dans la rafale du cas B (
AIabsente, H3S § 4 Q1) ; - contenu : dans
AI, la seule conditionIfqui appelle une fonction booléenne sur une personne estAI\high_priority\so_follows.lpai:7If AI.hasRelationship(Spouses, Dating)(Grep^\s*(If|Elseif|ElseIf)\b.*\b\w+\.\w+\(sousAI: 7 lignes, les 6 autres surDest,Current,Type) ; les scènes vérifiées autour des 7 événements (lignesCHECKING:les plus proches, ex. L2:21374, 22893, 24336, 25663, 26935, 28449, 29512) n'appellent nihasRelationship, niwantsBabies, niisSameGender(Grep^(OTHER|WHO|WHERE):sur ces.lpscene).
- empreinte : par événement, 1 F2 puis 2 lectures
_30=GetArrayItem_78(getUntil), estimé fort :- empreinte : par événement, 2 lectures
_30sans F2 propre (L2:12087-12105, 22396-22414) : tableau de longueur 1 qui contientNone; la seule F2 précède les 2PerdegetRelatedPerson(L2:12063-12085, 22372-22394) ; - suite L2:22372-22438 =
so_follows.lpai:8-17:getRelatedPersonQuick(F2 + 2Per;CallFunction_175951, sonReturnpart dansAddVariable12409viaMakeArray_120.[0], CF:2431-2467, d'oùSO = [None]),SO.getUntil()(2_30),SO.getBuilding(current)etSO.getBuilding(work)(2_33, L2:22416-22434), « [AI] 4 moves to (test0104) » (destination vide, L2:22436), « for 1.0 hours by 4 » (L2:22437),SO.delete()(« DestroyDummy was from callfunction Delete », L2:22438) ; l'événement de L2:12063-12106 s'arrête après_30(Until - HoursElapsed > 1faux) ; - candidats de même forme dans CF (Grep du motif ci-dessus : CF:2751, 5522, 5695, 6113, 7000) :
deletePerson(2368),setUntil(75, =_31, H3S),getUntil(78),setWantsBabies(99),setDatingID(144) ; seulgetUntilest dansso_follows.lpai. Statut : estimé fort ; la VAL tranche (comptes à 0, § 7). Écart possible : R9.
- empreinte : par événement, 2 lectures
3. Repli
- Avant écriture : instantané
.\Tools\Snapshot.ps1 -Lot STE-H3b(P3) ; MD5 de départ relevé (P2). - Échec de compilation, diagnostic,
type_idintrouvable (P5) ou lien relu différent : arrêt,.\Tools\Restore.ps1 -Lot STE-H3béditeur fermé (GI entier, retour à l'état après H3), puis contrôle MD5 = valeur de P2. - Après commit (gardien) :
git revertdu commit du ticket STE-H3b (n'annule pas STE-H3 si commits distincts). - Indépendance : G8, G10, G11 sont indépendantes entre elles et de H3 ; G7 exige G2 (sinon R1 de H3S s'applique). Une réponse c à Q4 ou Q5 retire seule la garde concernée.
4. Risques R#, questions Q#
Q4 (utilisateur) — G10, getUntil sur personne nulle : (a) rejeu exact Map_Find(AI_Untils, "0") (7 nœuds,
comportement identique) ; (b) Until = 0.0 (6 nœuds) ; (c) pas de garde. Établi : la clé "0" d'AI_Untils est écrite
aujourd'hui par setUntil avec AI vide (H3S § 2.6), écriture supprimée par G5 (Q2 acceptée, STE-TACHES.md:29) ; dans L2
elle existait à 21:32:11 (PNJ 4 envoyé suivre un partenaire inexistant vers une destination vide, L2:22436). (b) changerait ce
cas (le PNJ ne bouge plus), ce qui ressemble à une correction mais n'est pas « comportement inchangé ». Avec G5 posée, (a) et
(b) ne diffèrent plus que pour une sauvegarde qui contient déjà la clé "0" (essai : LPDumpSave, § 7.4). Recommandation : (a),
conforme à Q1 = A.
Q5 (utilisateur) — G11, hasRelationship sur personne absente : (a) rejeu exact hasRelationship("0", Types)
(6 nœuds, identique) ; (b) BoolToReturn = false (5 nœuds) ; (c) pas de garde. Estimé : dans L2, aucune des 7 évaluations
n'a été suivie d'un getRelatedPerson fautif (les 4 lignes Per sont à L2:12065-12078 et 22374-22387, hors des 7
événements), donc hasRelationship("0", Spouses, Dating) y a probablement rendu faux ; non établi sans dump de
hasRelationship (clé "0" = joueur ? R1 de H3S). Recommandation : (a).
Q6 (orchestrateur) — dumps manquants (STE-D3) :
.\Tools\RunCommandlet.ps1 -Lot STE-D -Commandlet LPDumpFunction -Args '-BP=GI -Fn=modifyActorVar -Pins -Exec' (G9, bloquante) ;
... -Args '-BP=GI -Fn=getRelatedPerson -Pins -Exec' (R13 : F2 + Per, 2 événements, 4 lignes) ;
... -Args '-BP=GI -Fn=hasRelationship -Pins -Exec' (Q5 b seulement).
- R9 : correspondances
_41→GetArrayItem_12254et_30→GetArrayItem_78estimées (§ 2.7). Autres candidats :isSameGender(519,521: un seul des deux absent donne aussi 1 F2 + 2 lectures),wantsBabies(34) ;deletePerson,setWantsBabies,setDatingID. Si_41ou_30reste > 0 en VAL : rapport, pas de correctif improvisé. - R10 : G7 repose sur la sortie non écrite de
142(cadre mis à zéro, § 6) et sur G2 posée avant (ordre § 2). - R11 :
type_idd'AddVariable,Map_Find,MakeArray,hasRelationship,Set BoolToReturnhors lp-mcp § 3 (P5) ; broches génériques deMap_FindetMakeArraytypées au câblage ; échec → arrêt et repli, pas dedelete_node. - R12 : masquage : les variantes a gardent les comportements du chemin nul (PNJ envoyé vers une destination vide,
hasRelationshipdu créneau"0"), liés au cas B (H5) et au retour nul degetRelatedPerson. - R13 : non couvert : F2 + 2
PerdansgetRelatedPerson(L2:12063-12085, 22372-22394, fonction sans dump) ; autres lecteurs dePerson[0](R7 de H3S). - R14 : G7 et G8 n'ajoutent pas d'
IsValid: l'élément nul d'un tableau de longueur 1 ne lève pas de F2 au site et est traité dans la fonction appelée (G2, G1).
5. Interdits
- Aucune modification de l'EventGraph, des fonctions appelées (
getActorVar,setActorVar,modifyActorVar,getRelatedPerson,hasRelationship), du C++ ; G9 non posée sans dump et complément de SPEC. - 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 « Accessed None trying to read (real) property X in not an UClass » : UE
Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:3213-3216; contexte nul : expression sautée, valeur rendue effacée (ClearValue),:3234-3244. - Cadre d'une fonction script : alloué puis mis à zéro s'il n'est pas persistant,
ScriptCore.cpp:984-993; cadre persistant seulement pour la fonction ubergraph :Runtime\Engine\Private\BlueprintGeneratedClass.cpp:1882-1897. - Message F2 « Attempted to access index %d from array '%s' of length %d » :
Runtime\Engine\Private\KismetArrayLibrary.cpp:472-478;GenericArray_IsValidIndexsans message ::583-589. Map_Findpur, catégorieUtilities|Map, nom affichéFind:Runtime\Engine\Classes\Kismet\BlueprintMapLibrary.h:48-49; clé absente → valeur remise au défaut :Runtime\Engine\Private\BlueprintMapLibrary.cpp:35-55(l. 47-50).- Suffixe
_Net ordre de compilation : repris de H3S § 6 (KismetCompilerMisc.h:287-302,KismetCompiler.cpp:3918-3927,EdGraphCompiler.cpp:244-249), non relus ici.
7. Critères de VAL (commande → attendu)
- Dumps après IMPL (
.\Tools\RunCommandlet.ps1 -Lot STE-H3b -Commandlet LPDumpFunction -Args '-BP=GI -Fn=<f> -Pins -Exec') comparés à P2 :CallFunction+11 nœuds (G7 2, G8 2, G10a 7 ; +10 si Q4 = b, +4 si c ; base H3 : 1 550,H3S:258) ;CallFunctionReturnBool585 → 591 (Q5 = a), 590 (b), 585 (c) ; liens du § 2 relus ;python Tools\DiffRemplacementNoeuds.pysans autre écart. hyper_blueprint_debug_inspect0 diagnostic pourCallFunctionetCallFunctionReturnBool;CompileAllBlueprintséditeur fermé : 0 erreur (lp-validate).- Journal de jeu (build Development, parcours STB-JEU2,
STD-SCN-DIAG.md:198-206), Grep en modecount:property CallFunc_Array_Get_Item_41→ 0 (L2 : 14) ;property CallFunc_Array_Get_Item_30→ 0 (L2 : 4 ; inchangé si Q4 = c) ;- multiligne
of length 0[^\n]*\r?\n[^\n]*\r?\n[^\n]*property (CallFunc_Array_Get_Item_41|Per) in→ nombre de lignesproperty Per in/ 2 (L2 : 9 = 7 + 2) ; Person_24_4B712C904750AD4CE1580DBEBD9E7396' of length 0/CHECKING:→ inférieur au rapport mesuré en VAL de H3, de l'ordre de 94 / 2 318 = 0,041 à parcours égal (L2 : 351 / 2 318 = 0,151 avant H3) ;property Per in→ information (L2 : 4, R13) ;moves to \(test0104\)→ information (L2 : 1, L2:22436) : présent possible en variante a, absent attendu en b ;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).
- Q4 / Q5 :
LPDumpSave -File=<sauvegarde du parcours> -Out=<txt>(lp-commandlets) avant / après : clés"0"d'AI_Untilset d'ActorVarsrelevées (même essai que H3S § 7.4).
Fichiers à commiter (dépôt jeu, branche ue5.8, ticket au gardien) :
- A
Docs/Migration/etat/ST/STE/STE-H3b-SPEC.md
Tours : 33 / 60
Constats
- Comptes rejoués sur L2 (Grep) :
CallFunc_Array_Get_Item_(30|41)→ 4 et 14 lignes (contenu, numéros cités § 2.7) ; multiligneFunction /Game/BPs/GI\.GI_C:CallFunction\r?\n\s+Function /Game/BPs/GI\.GI_C:(getActorVar|setActorVar|modifyActorVar)\r?\n→ 174 ; multiligneFunction /Game/BPs/GI\.GI_C:\w+\r?\n\s+Function /Game/BPs/GI\.GI_C:getActorVar\r?\n→ 142 ; doncgetActorVar142 (toutes depuisCallFunction) +setActorVar32 (H3S:72) +modifyActorVar0 = 174 ;GI_C:modifyActorVar|GI_C:getUntil|GI_C:hasRelationship→ 0 ;GI_C:(modifyActorVar|getRelatedPerson):→ 4 (les 4Per). - F2 suivie d'une lecture fautive (multiligne
Script Msg: Attempted to access index 0 from array 'Person_24_…' of length 0[^\n]*\r?\n[^\n]*\r?\n[^\n]*property (Person|Per|CallFunc_Array_Get_Item_\d+) in) → 285 sur 351 ; dont suivie d'un F1getActorVar→ 71, d'un F1setActorVar→ 16, de_41ouPer→ 9. getRelatedPersonreçoit un nom de variable (Person←VariableGet_127193.VariableGet, CF:2435, 2441-2442 ;VariableGetest une chaîne,VariableSet_163.VariableGet←Split.LeftS, CF:452-456) : la F2 et lesPernaissent dans la fonction, sans dump.- Grep de
etat\…\dumps: passerglob*__*.txt(les.txty sont ignorés par git) ; un motif finissant par$ne trouve rien dans ces dumps (fins de ligne CRLF) : essai de cette fiche. - Écart de chemin : aucun ; journal et gabarits 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) ; journal non relu (aucune entrée nécessaire ici).