LifePlay-Revival/Docs/Migration/etat/ST/STE/STE-ORG5-SPEC.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

51 KiB
Raw Blame History

Fiche STE-ORG5 — Niveau N3 — Modèle prévu (modèle de l'agent lp-cart) | utilisé claude-sonnet-5-5 — Agent lp-cart — Skills lp-mcp (lecture), sk-protocol (préchargés avec l'agent : ue-cpp-build, lp-commandlets, lp-paths)

STE-ORG5-SPEC : reconstruction du bonus d'orgasme de l'auteur (grille de récompenses), découpage en fiches et version minimale pour l'alpha (2026-10-14)

Hors gabarit : les sections suivent l'ordre du gabarit SPEC (1 objectif, 2 fichiers touchés et ordre, 3 repli, 4 risques et questions, 5 interdits, 6 valeurs moteur, 7 critères de VAL) ; les rubriques demandées par la fiche (rubrique 7) sont des sous-sections : comportement cible = 1.1, table des 20 entrées = 1.2, formule = 1.3, conception 5.8 = 2.1 à 2.3, widgets et fonctions = 2.4, option DisableBonus = 2.5, découpage en fiches = 2.6, version minimale pour l'alpha = 3.1, estimation = 4.1, risques = 4.2, lectures MCP manquantes = 4.3, Q# = 4.4. Annexes A (commandes et lectures, comptes bruts) et B (établi / estimé / incertain) après la section 7. Lecture seule : ni éditeur, ni MCP, ni commandlet, ni build, ni jeu ; l'exécutable de l'auteur n'a pas été lancé ; aucun fichier du projet modifié hormis ce livrable. Aucun refus du crochet (outil de lecture : cinq scripts Python en fichier dans le scratchpad de session, le désassembleur kdis.py / kdbg.py / kall.py, calc.py et strs.py, lancés par python -I <fichier> en 20 exécutions, aucune écriture hors scratchpad). Changement par rapport à l'audit : le désassemblage du bytecode de PopulateBonusRewards (L14) et de GiveOrgasmReward (L15) est fait ; il corrige trois points de STE-ORG-AUDIT.md § 9 (voir 1.1, 1.3 et 2.5 : trois récompenses au plus et non cinq ; valeur à 100 = 0,2 ; branche DisableBonus résolue).

Sigles

Sigle Chemin Contenu
B D:\XxX\LifePlay_2023_04_Stable_64bit\LifePlay\Content build cuit de l'auteur, version 2023.04 Stable, UE 4.20, sans .pak ; les nombres après B\…\X.uexp sont des offsets d'octets absolus du .uexp
O D:\Game\LifePlay-master 5.8\Content nos assets (copie 5.8)
P-STG D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STG\dumps\Person__EventGraph.txt dump de l'EventGraph de Person (copie de travail)
L6f-G / L6f-P …\etat\portage55\L6f\L6f_dump_GI.txt / L6f_dump_Person.txt dumps 5.5 de tous les graphes
AUD …\etat\ST\STE\STE-ORG-AUDIT.md audit amont
DIS scratchpad de session : kdis.py, kdbg.py, kall.py désassembleur Kismet (Python, lecture seule), voir annexe A

1. Objectif mesurable

Reproduire dans les sources 5.8 le bonus d'orgasme de l'auteur (build 2023.04 Stable) : à chaque orgasme, jusqu'à 3 récompenses « stat ±valeur » tirées parmi 20 clés filtrées par les tags de la position, valeur décroissante avec la stat, application de la récompense choisie par ModifyStat, option de désactivation. Critères mesurables (reprennent la section 7) : (i) table de 1.2 identique (20 clés, mêmes tags) ; (ii) les 21 valeurs de 1.3 reproduites ; (iii) jamais plus de 3 récompenses ; (iv) application = un seul ModifyStat(Stat, Change, DifficultyAdjusted = false, NoDisplay = false) sur la personne qui vient de jouir ; (v) option désactivée : aucune récompense, bonus ancien intact ; (vi) version minimale : 0 asset modifié.

1.1 Comportement cible (établi par désassemblage du bytecode de B, sauf mention)

# Comportement Source Niveau
E1 Déclencheur : chaque exécution de l'événement GiveOrgasmReward de Person, donc chaque orgasme de toute personne (joueur ou PNJ). JUMPIFNOT sur GI.DisableBonus : faux → copie de GI.CurrentTags dans une structure StringArray, puis GI.Cursor.PopulateBonusRewards(self, tags), puis JUMP vers le bonus ancien ; vrai → saute directement au bonus ancien. Le bonus ancien est exécuté dans les deux cas (OrgasmIrBoost, mood +20 du joueur, attractiontoplayer ×3 ou ×6) : la grille s'y ajoute B\BPs\Person.uexp:21111 (JUMPIFNOT m413 (GI.DisableBonus)), :21184 (StringArray), :21218 (appel), :21262 (JUMP vers :21135), :21135-21652 (bonus ancien, identique à P-STG:16059-16110 et 17453-17496) établi
E2 Appel : PopulateBonusRewards(Person, Tags) est un talon qui copie ses deux paramètres et appelle ExecuteUbergraph_Cursor(10856) ; l'entrée 10856 saute à l'instruction m15 B\UI\Cursor.uexp:14450-14487 (talon), :14006 (JUMP m15) établi
E3 Temporisation : RetriggerableDelay(0,2 s) avant tout : un second appel dans les 0,2 s remplace le premier (comportement documenté du nœud, non relu dans le .cpp) ; seul le dernier orgasme produit des récompenses (« last person who came ») Cursor.uexp:7141 ; signature moteur KismetSystemLibrary.h:700-701 établi pour le nœud, estimé pour le remplacement
E4 Remise à zéro : ScrollBonuses.ClearChildren(), lastCum := Person Cursor.uexp:7198, :7218 établi
E5 Candidats : Map_Keys(statTags) (20 clés), Array_Shuffle, Array_Resize(·, 10) : 10 clés au hasard ; countBR := 0 Cursor.uexp:7236, :7281, :7306, :7336 établi
E6 Boucle sur les 10 clés (tant que la sortie anticipée n'est pas levée), pour chaque clé : (a) tags := statTags[clé].Strings ; (b) GI.Overlaps(Tags.Strings, tags, IfEmptyThenTrue = true) : faux → clé ignorée ; (c) si clé = attractiontoplayer : exige NON Person.isPlayer ET GI.IsInterestedIn(Person, GI.PlayerCharacter) ET GI.SexPersons contient GI.PlayerCharacter, sinon ignorée ; (d) acceptation : countBR++, création d'un widget BonusReward, Person, Stat = clé sans le - final, x := Person.QueryStat(Stat, false, false).Value, Change := signe × valeur(x) (1.3), ScrollBonuses.AddChild ; (e) NotEqual_IntInt(countBR, 3) : à 3 acceptées, sortie de boucle. Au plus 3 récompenses (a) Cursor.uexp:7545-7586 ; (b) :7606-7651 ; (c) :7692-7743 et :8686-8884 ; (d) :7753-8576 ; (e) :8607-8629, :8889 établi (la constante 3 est dans le code ; le journal 5.26 disait 5, Change_Logs.txt:39, le code du build 2023.04 fait foi)
E7 Widget BonusReward : bouton RewardButton + texte RewardText lié à Format("{stat} {sign}{change}"), signe vide si Change < 0 sinon +, change argument flottant. Clic : Person.ModifyStat(Stat, Change, false, false) puis GetParent().ClearChildren() (retire les 3 boutons). Aucune pause du jeu, aucun appel de son dans le bytecode B\UI\BonusReward.uexp:1371-1973 (texte), :1115-1201 (clic) établi
E8 Texte d'en-tête (Cursor.Get_TextBlock_0_Text_0) : DisableBonus → « Bonus rewards disabled » ; sinon si ScrollBonuses a des enfants → « Pick a bonus reward for {Name_First}'s last orgasm » ; sinon « Bonus rewards can be chosen here after each orgasm » Cursor.uexp:22465-23015 établi
E9 Visibilité du panneau SexExclusives : visible si GI.SexOn, sinon replié ; l'appartenance de TextBlock_0 et de ScrollBonuses à ce panneau n'est pas lue (arbre de widgets non lu) Cursor.uexp:19759-19818 établi pour la fonction, non établi pour l'arbre
E10 Aucun nettoyage des récompenses en fin de scène : les 45 fonctions décodées de Cursor ne touchent ScrollBonuses, lastCum, countBR, statTags que dans PopulateBonusRewards et Get_TextBlock_0_Text_0 ; seuls Person, BonusReward et Cursor citent ces noms (annexe A, point 8). Les boutons restent jusqu'au clic ou au prochain orgasme annexe A points 8 et 9 établi

1.2 Table des 20 entrées (statTags, valeur par défaut de la variable, relue à la source)

Clé finissant par - : la récompense baisse la stat (signe −1, nom de stat sans le -). « vide » : Overlaps renvoie vrai quelles que soient les tags de la position (drapeau IfEmptyThenTrue à vrai). Offset = chaîne dans B\UI\Cursor.uexp (annexe A point 6).

# Clé Tags de position Offset # Clé Tags de position Offset
1 perversion vide 4643 11 likes_missionary Missionary 5450
2 masochist Aggressive, AggressiveFM 4703 12 likes_oral Oral, Blowjob, Cunnilingus, LickPussy, LickAss, Rimjob 5531
3 prone_to_orgasm vide 4794 13 likes_rcowgirl ReverseCow, ReverseCowgirl 5665
4 attractiontoplayer vide (+ condition E6c) 4859 14 likes_rough Aggressive, AggressiveFM 5763
5 fitness Penetration, Foreplay, Cum 4927 15 likes_sidefuck Spooning, Sidefuck, Spoon 5856
6 likes_anal Anal 5021 16 likes_toys Toys, Dildo, Vibrator 5956
7 likes_boobjob Titfuck, Boobjob 5090 17 likes_tribadism Tribadism, Scissor, Scissoring 6048
8 likes_cowgirl Cow, Cowgirl 5177 18 likes_vaginal Vaginal 6154
9 likes_doggy Doggy, Doggystyle 5260 19 masochist- Aggressive, AggressiveFM 6229
10 likes_handjob Handjob, RubPussy, FingerPussy 5346 20 prone_to_orgasm- Penetration, Foreplay, Cum 6321
  • Identique à AUD § 9.4 (relue indépendamment, mêmes 20 clés, mêmes tags). Deux groupes partagent les mêmes tags : {1 masochist, 14 likes_rough, 19 masochist-} et {5 fitness, 20 prone_to_orgasm-}.
  • Les 18 stats (hors les deux clés en -) existent comme .lpstat chez l'auteur et chez nous (AUD § 9.4, 9.9 point 7 ; non rejoué).
  • Les 34 mots de tags figurent tous dans O\BPs\GI.uasset (grep -a -o -w -F, annexe A point 10 : Penetration 396, Foreplay 158, Cum 33, Anal 215, Vaginal 327, Missionary 148, Titfuck 3, Tribadism 2…), ce qui rend les tags atteignables en principe (estimé : le vocabulaire d'animations de GI ; la valeur réelle de Anim.Tags n'est pas lue).
  • Exemple (calculé sur la table) : position {Missionary, Vaginal, Penetration} → éligibles perversion, prone_to_orgasm, attractiontoplayer (si condition), fitness, likes_missionary, likes_vaginal, prone_to_orgasm- = 7 clés sur 20 ; CurrentTags vide → les 20 passent.

1.3 Formule de la valeur (établi pour les constantes et l'ordre, mesuré pour la table)

Change = signe × ceil((2,0 − MapRangeClamped(|x|, 0, 100, 0, 1,9)) × 10) / 10, x = valeur courante de la stat (QueryStat), signe = −1 si la clé finit par -, sinon +1. Instructions : Abs Cursor.uexp:8339, MapRangeClamped(·, 0, 100, 0, 1.9) :8360, Subtract(2, ·) :8401, Multiply(·, 10) :8427, FCeil :8453, Conv_IntToFloat :8474, Divide(·, 10) :8495, Multiply(·, signe) :8521, SelectFloat(−1, 1, EndsWith) :8308. Table calculée (script calc.py, double = arithmétique des Blueprints UE 5.x, float32 = UE 4.20 de l'auteur ; identiques sur les 21 points) :

x 0 1 5 10 20 25 30 40 45 50 55 60 70 75 80 90 95 99 100 120 −30
valeur 2,0 2,0 2,0 1,9 1,7 1,6 1,5 1,3 1,2 1,1 1,0 0,9 0,7 0,6 0,5 0,3 0,2 0,2 0,2 0,2 1,5
Lecture : 1,1 vers x = 50 (accord avec « fitness +1.1 » et « prone_to_orgasm -1.1 » des captures) ; 100 donne 0,2 et non 0,1 (arrondi flottant de 2,0 − 1,9 ; corrige l'hésitation de AUD § 9.5). Le rendement dépend de la valeur de la stat, pas du nombre d'orgasmes.

2. Fichiers touchés, ordre

2.1 Conception 5.8 : trois options

Critère A. Blueprint fidèle (comme l'auteur) B. C++ autonome (recommandée) C. Hybride (C++ pour table / tirage / formule, BP pour les widgets)
Assets créés / modifiés Cursor (variables statTags, Stats, countBR, lastCum, widgets ScrollBonuses et TextBlock_0, fonction, liaison de texte), BonusReward (nouveau), Person (+ ~6 nœuds), GI (DisableBonus + 2 nœuds Save / Load, GI.uexp:866870 et :869178 chez l'auteur), GameSettings (champ), SettingCheckbox / MainMenu (case) aucun (version minimale) ; 2 fichiers C++ neufs Cursor (widgets + appel), BonusReward (nouveau), Person (1 nœud), + 2 fichiers C++
Dont modifiés par d'autres lots Person (STG), GI (STG B7-a) : oui, git status du 2026-10-14 : M sur GI, Person, Room aucun (Room non touché) Person : oui
Faisable par MCP nœuds : oui en principe (BlueprintTools, ~70 instructions décodées de 7141 à 8896 ≈ 60 à 80 nœuds, estimé) ; arbre de widgets : non démontré (seuls scene.SceneTools, blueprint.BlueprintTools, asset.AssetTools, object.ObjectTools apparaissent dans les 40 premières occurrences de editor_toolset.toolsets.* des Docs ; aucun toolset de widget vu, recherche tronquée) ; valeur par défaut d'une Map<String, StringArray> : non démontrée sans objet (pas de MCP) nœuds oui ; widgets : mêmes réserves que A
Précédent dans le dépôt aucun pour de l'UMG créé par MCP UI construite en C++ sans toucher de Blueprint : LPSettingsSubsystem.h:6 (« Aucun Blueprint n'est modifié »), LPColorGradeSubsystem.cpp:188-302 (lignes injectées dans SettingsScrollBox), LPModInfoSubsystem.cpp:288-307 (cases), LPKeyboardSubsystem.cpp:636, LPDirectControlSubsystem.cpp:1259, LPCameraModeSubsystem.cpp:469 (panneaux Slate par AddViewportWidgetContent) ; appels de fonctions Blueprint par FindFunction + ProcessEvent : LPDirectControlSubsystem.cpp:411-455, LPDataCompat.cpp:149-164, LPPersonPropGuardSubsystem.cpp:129-131 ; réglages joueur hors GameSettings.sav : LPUserSettings.h:3-9 mixte
Build C++ aucun oui (module LifePlay, dépendances Slate, SlateCore, UMG déjà présentes LifePlay.Build.cs:38) oui
Apparence identique à l'auteur (police et styles du jeu) panneau Slate au style à régler (police et couleur à copier d'un widget existant, comme LPColorGradeSubsystem.cpp:289-297) identique à l'auteur
Testabilité hors jeu faible table, tirage et formule en fonctions statiques pures, contrôle de formule au démarrage moyenne
Effort estimé 5 à 8 sessions MCP (estimé, 4.1) 3 fiches pour la version minimale, 3 de plus pour la grille 4 à 5 sessions MCP + C++
Recommandation : B. Raisons : (1) aucun asset partagé touché (Person, GI sont en cours de modification par STG, Room par CAM) ; (2) aucune dépendance à des capacités MCP non démontrées (widgets, valeur par défaut de map) ; (3) tout le dépôt a déjà ce mode de construction ; (4) la version minimale n'a aucune interface, ce qui évite le point que l'auteur désigne comme suspect (Change_Logs.txt:34, plantages autour des orgasmes). Réserve : l'apparence du panneau (version 1) ne sera pas pixel-identique à celle de l'auteur. A et C restent possibles si l'utilisateur veut l'identique : elles exigent d'abord la lecture L-M1 (4.3).

2.2 Accroche à l'orgasme : deux manières, une seule active

H1. Sondage en C++ (recommandée pour l'alpha) H2. Un nœud dans GiveOrgasmReward
Principe le sous-système lit à 0,1 s GI.SexOn et, pour chaque GI.SexPersons[i], Person.Sex_OrgasmCounts : une hausse = un orgasme (la macro IncrementInt est dans l'événement Cum, P-STG:16118-16125 ; remise à 0 avec Sex_Energy et Sex_BoredCountdown, P-STG:15908-15911 et 16175-16178 : une baisse = remise à zéro, on resynchronise sans récompense) un nœud CallFunction (fonction statique C++ NotifyOrgasm(Person)) inséré entre K2Node_CustomEvent_87.then et K2Node_CallFunction_1005.execute (P-STG:16059-16061) : 1 nœud, 3 liens
Assets touchés aucun Person.uasset (STG + CAM non commités : annonce à Big Boss, instantané, session MCP, compilation, CompileAllBlueprints)
Couvre Endsex (STE-ORG4) oui si ORG4 passe par Person::Cum (le compteur monte) ; non si ORG4 appelle seulement GiveOrgasmReward oui dans les deux cas
Double déclenchement impossible : un incrément par Cum ; deux orgasmes en moins de 0,2 s : seul le dernier compte (comme l'auteur, E3) idem ; si H2 est ajouté plus tard, il écrit le compteur observé pour que H1 ne redéclenche pas
STE-ORG4-SPEC.md n'existe pas encore (Glob STE-ORG4* dans le dossier du lot : seule la fiche fiches\STE-ORG4.md) : la compatibilité avec ORG4 est donc non vérifiée (Q-ORG5-6).

2.3 Fichiers touchés (option B)

Fichier Action Version Autre lot concerné
Source/LifePlay/LPBonusRewardSubsystem.h et .cpp créer V-min, V-1 aucun (fichiers neufs ; git status actuel : LPCameraModeSubsystem.*, LPSaveRelaunch.* non suivis, LPDebugSubsystem.*, LPDirectControlSubsystem.*, LPOutdoorRoomSubsystem.*, LifePlay.cpp modifiés par d'autres lots : non touchés)
Source/LifePlay/LPSettingsSubsystem.cpp 1 règle d'onglet (GetName().StartsWith("LPBonus") → onglet Lewd), près de :173-181 V-2 aucun (fichier non modifié aujourd'hui)
Content/BPs/Person.uasset 1 nœud (H2) V-3, facultative STG, CAM
Saved/Config/Windows/GameUserSettings.ini (utilisateur, pas le dépôt) section [/Script/LifePlay.LPBonusRewardSettings], clé bDisabled V-min aucun
Aucun fichier de GI, Cursor, GameSettings, MainMenu, SettingCheckbox, Room n'est modifié par l'option B. Ordre : C++ (V-min) → build → VAL → essai en jeu → panneau (V-1) → réglage (V-2) → H2 (V-3).

2.4 Widgets et fonctions

(a) Éléments de l'auteur à reproduire (référence, option A / C) :

Élément Contenu Source
Cursor.PopulateBonusRewards(Person : Person, Tags : StringArray) E2 à E6 Cursor.uexp:14450-14487, :7141-8896
Cursor variables statTags (Map<String, StringArray>, 20 entrées par défaut), Stats (String[]), countBR (int), lastCum (Person) Cursor.uexp:7218-7336
Cursor widgets ScrollBonuses (ScrollBox ou panneau avec ClearChildren / AddChild / GetChildrenCount), TextBlock_0 + liaison Get_TextBlock_0_Text_0 Cursor.uexp:7198, :22465-23015
BonusReward (UserWidget) variables Person (Person), Stat (String), Change (réel) ; RewardButton (OnClicked) contenant RewardText lié à Get_RewardText_Text_0 BonusReward.uexp:1069-1985
Person.GiveOrgasmReward Branch(GI.DisableBonus) ; faux → MakeStruct StringArray(Strings = GI.CurrentTags) → GI.Cursor.PopulateBonusRewards(self, struct) → rejoint OrgasmIrBoost Person.uexp:21111-21262

(b) Conception C++ (option B), signatures à respecter :

UCLASS(config = GameUserSettings) class ULPBonusRewardSettings : public UObject   // dans LPBonusRewardSubsystem.h
    UPROPERTY(config) bool bDisabled = false;                                      // équivalent de DisableBonus

struct FLPBonusStat { FString Key; TArray<FString> Tags; };                        // 20 entrées, section 1.2
UCLASS() class ULPBonusRewardSubsystem : public UGameInstanceSubsystem
    Initialize / Deinitialize          // FTSTicker 0,1 s, comme LPColorGradeSubsystem.h:51
    bool Tick(float);                  // sondage 2.2 H1 ; débounce 0,2 s ; (V-1) retrait différé du panneau
    static const TArray<FLPBonusStat>& Table();
    static double RewardChange(double X, bool bNegative);                          // formule 1.3, ordre des opérations conservé, en double
    static bool   Overlaps(const TArray<FString>& A, const TArray<FString>& B, bool bIfEmptyThenTrue);   // GI.Overlaps, B:1073624-1074121
    static void   Pick(const TArray<FString>& PositionTags, FRandomStream& Rng, bool bAttractionAllowed,
                       TArray<FString>& OutStats /*sans le '-'*/, TArray<bool>& OutNegative);          // E5-E6, max 3, graine injectable
    bool QueryStat(UObject* Person, const FString& Stat, double& OutValue);        // FindFunction("QueryStat") + ProcessEvent, sortie Value
    bool ModifyStat(UObject* Person, const FString& Stat, double Change);          // FindFunction("ModifyStat"), DifficultyAdjusted = false, NoDisplay = false
    void OnOrgasm(UObject* Person, const TArray<FString>& TagsCapturedAtDetection);

Algorithme de Pick (équivalent exact de E5-E6) :

Keys = les 20 clés ; Shuffle(Keys, Rng) ; garder 10
Out = []
pour Key dans Keys :
    si NON Overlaps(PositionTags, Table[Key].Tags, true) : continuer
    si Key == "attractiontoplayer" et NON bAttractionAllowed : continuer
        // bAttractionAllowed = NON Person.isPlayer ET GI.IsInterestedIn(WhoIsInterested = Person, WhoInterests = GI.PlayerCharacter) ET SexPersons contient PlayerCharacter
    Out.Add(Key sans '-' final, Key finit par '-')
    si Out.Num() == 3 : arrêter

Sondage (V-min) : à 0,1 s, si GI.SexOn faux → vider le suivi ; sinon pour chaque personne de GI.SexPersons : premier passage → mémoriser le compteur sans récompense ; hausse → copier GI.CurrentTags, armer Pending = {personne, tags, t + 0,2 s} (remplace un Pending existant) ; baisse → resynchroniser. Quand t est atteint et la personne valide : OnOrgasm. Lecture des propriétés par réflexion, types contrôlés par CastField (précédents : LPCameraModeSubsystem.cpp:40,407, LPShowCoupleSubsystem.cpp:303, LPUserSettings.cpp:14-55 pour réel float ou double) ; type absent ou inattendu : un avertissement journalisé une fois (précédent LogParmsOnce, LPDirectControlSubsystem.cpp:425), jamais de plantage. Appels Blueprint (réflexion, paramètres par nom, valeurs initialisées puis détruites comme LPDirectControlSubsystem.cpp:426-455) : Person.QueryStat(Stat, WithoutBuff, RNG) sorties Value, Bonus (L6f-P:20-29) ; Person.ModifyStat(Stat, Change, DifficultyAdjusted, NoDisplay) sortie Value (L6f-P:561-567) ; GI.IsInterestedIn(WhoIsInterested, WhoInterests) sortie Interested (L6f-G:23421-23424). Ordre des paramètres de IsInterestedIn dans l'appel de l'auteur non relu : l'IMPL fixe WhoIsInterested = Person (estimé : l'auteur teste « le PNJ s'intéresse au joueur ») et le contrôle en VAL par le journal. Journal (LogLifePlay, niveau Display), formats imposés pour la VAL : Bonus : orgasme de <nom> (compteur <n>) ; Bonus : <nom> <stat> <±valeur> (x=<valeur>, tags=<n>) ; Bonus : aucune récompense éligible pour <nom> ; Bonus : désactivé (bDisabled) ; au démarrage Bonus : contrôle formule OK (ou Error avec la valeur fautive) sur 0, 10, 25, 50, 75, 90, 100 → 2,0 ; 1,9 ; 1,6 ; 1,1 ; 0,6 ; 0,3 ; 0,2. V-1 (panneau) : widget Slate SLPBonusPanel (titre vert « Pick a bonus reward for <Name_First>'s last orgasm », au plus 3 boutons « stat ±valeur ») ajouté par GEngine->GameViewport->AddViewportWidgetContent(Panel, ZOrder) (z entre 50 et 200 comme les précédents), SelfHitTestInvisible pour le conteneur et boutons Visible (le reste du jeu garde la souris). Clic : ModifyStat, puis retrait différé au tick suivant (jamais détruire le panneau dans le gestionnaire du bouton cliqué ; estimé : c'est la pratique à éviter, l'auteur le fait avec ClearChildren() dans le gestionnaire). Panneau retiré aussi si GI.SexOn devient faux (écart voulu : l'auteur laisse les boutons, E10). Texte du nombre : formatage par défaut de FText::Format avec un argument flottant ; attendu « 1.1 », « 2 » (non vérifié). Nom de la personne : Person.Name_First est du texte chez l'auteur (Cursor.uexp:22666, argument de type texte) ; chez nous le type n'est pas lu : accepter FTextProperty et FStrProperty.

2.5 Option DisableBonus (L15 résolu)

Point Constat Source
Sémantique DisableBonus vrai : pas de grille, bonus ancien conservé ; faux : grille + bonus ancien Person.uexp:21111 → :21135 (E1)
Stockage chez l'auteur variable GI.DisableBonus ; copiée dans GameSettings.DisableBonus à l'enregistrement et relue au chargement B\BPs\GI.uexp:866870 (GameSettingsInstance.DisableBonus = DisableBonus), :869178 (DisableBonus = GameSettings.DisableBonus)
Interface chez l'auteur SettingCheckbox : clic → GI.DisableBonus = bIsChecked ; état → BoolToCheckBoxState(GI.DisableBonus) ; libellé « Disable Bonus Orgasm Rewards » dans MainMenu (aucune des 62 fonctions de MainMenu ne cite DisableBonus) B\UI\SettingCheckbox.uexp:1921, :13472 ; AUD § 9.7
Message d'aide « If you get crashes during sex scenes, Esc > Settings > tick Disable Bonus Orgasm Rewards … » B\UI\SexInterface.uexp:42851 (AUD § 9.7)
Chez nous absent : GameSettings, GI, MainMenu, SettingCheckbox, Cursor, Person ne contiennent pas DisableBonus (AUD § 9.7, non rejoué) ; SettingCheckbox et MainMenu existent (ls O\UI) ; les réglages sont rangés en onglets par ULPSettingsSubsystem, dont Lewd (LPSettingsSubsystem.cpp:35-43, règle de mots :198-203, règle de préfixe de nom :173-181)
Conception retenue réglage C++ hors GameSettings.sav (comme LPUserSettings.h:3-9, LPColorGradeSubsystem.h:7) : ULPBonusRewardSettings::bDisabled dans GameUserSettings.ini ; version minimale : ini seulement ; V-2 : case injectée dans MainMenu.SettingsScrollBox (modèle LPModInfoSubsystem.cpp:288-307) nommée LPBonusCheck… + règle d'onglet Lewd ; aucune sauvegarde de partie touchée (A ajouterait un champ à GameSettings : valeur par défaut faux pour les anciennes sauvegardes, non testé)

2.6 Découpage en fiches (ordre et dépendances)

Les tours sont des estimations (comparées aux budgets des fiches du lot : 45 à 55 tours pour une SPEC N3) ; l'agent exact est à fixer par l'orchestrateur.

Fiche Rôle (agent) Niv. Contenu Dépend de Tours Jeton UE
ORG5-I1 IMPL (lp-impl) N3 LPBonusRewardSubsystem.h/.cpp V-min : table, Pick, RewardChange, sondage H1, QueryStat / ModifyStat par réflexion, application automatique, ini bDisabled, journal, contrôle de formule Q-ORG5-1, 2, 3, 4, 5 40 non (écriture de 2 fichiers)
ORG5-B1 BUILD (lp-builder) N1 build du module LifePlay, comptes par Build.ps1 -FromLog I1 12 éditeur fermé (UeState = 0), build partagé avec CAM
ORG5-V1 VAL (lp-validator) N2 critères 7.1 à 7.6 (PASS-STATIC) B1 25 CompileAllBlueprints et LPTestStringCompat : sous UE-GO
ORG5-J1 essai en jeu (utilisateur) – critères 7.7 à 7.9 V1 – une session de jeu (build empaqueté ; la PIE ne déroule pas ce parcours, lp-mcp § 1 règle 5)
ORG5-I2 IMPL N3 V-1 : panneau Slate, 3 boutons, clic, retrait différé J1 PASS, Q-ORG5-7, 8 55 non
ORG5-B2 / V2 / J2 BUILD / VAL / jeu N1 / N2 / – idem I2 12 / 25 / session idem
ORG5-I3 IMPL N2 V-2 : case dans les réglages + règle d'onglet Lewd I2 30 non
ORG5-B3 / V3 BUILD / VAL N1 / N2 idem I3 12 / 20 idem
ORG5-I4 IMPL par MCP (lp-impl, lp-mcp § 3-4) N3 H2 : 1 nœud dans GiveOrgasmReward, P1/P2 (MD5 de Person, dumps avant), instantané, compilation, save_assets, dumps après libération de Person (STG commité), Q-ORG5-6 25 oui (MCP, copie partagée ; gel annoncé à toutes les sessions)
Option A (non recommandée) : ~8 sessions MCP, ~200 tours, plus la lecture L-M1.

3. Repli

  • Repli de la version minimale : supprimer les deux fichiers neufs (ou git restore par le gardien) ; aucun asset, aucune sauvegarde à restaurer. Désactivation sans reconstruire : bDisabled=True dans l'ini utilisateur.
  • Repli du panneau : revenir à la version minimale (l'application automatique reste).
  • Si le build est bloqué ou le jeton UE indisponible avant le 2026-10-16 : rien dans l'alpha, la fonction reste dans le lot STE pour la suite.

3.1 Version minimale pour l'alpha (2026-10-18)

V-min = I1 + B1 + V1 + J1, option B, accroche H1 : à chaque orgasme (toute personne de la scène), tirage exact de E5-E6, application automatique de la première récompense retenue par ModifyStat(Stat, Change, false, false) (la ligne « stat ±n » s'affiche comme celle du mood), journal, ini bDisabled. Ce que V-min laisse de côté : la grille et le choix (E7), le texte d'en-tête (E8), la case de réglage (2.5), l'accroche exacte par GiveOrgasmReward (H2), le nettoyage en fin de scène (sans objet : pas de panneau), la couverture de Endsex si ORG4 n'appelle pas Cum. Ce qu'elle garde : table, filtre par tags, règle de attractiontoplayer, formule, débounce 0,2 s, bonus ancien intact, kill-switch. Faisabilité (estimée) : ≈ 80 tours d'agents (≈ 2 h) + 1 session de jeu ; build incrémental de référence 18,56 s (STE-H3d_Build_20261013-124425.txt:10, ajout de fichiers non mesuré). Entre dans l'alpha si : Q-ORG5-1 à 5 tranchées le 2026-10-14 ou 15, jeton UE de build libre le 15, V1 PASS-STATIC le 16, J1 le 16 ou 17. V-1 (panneau) : seulement si J1 est PASS le 16 et si Big Boss accepte le risque d'interface (R2) ; sinon après l'alpha. V-2 et H2 : après l'alpha.

4. Risques R#, questions Q#

4.1 Estimation (récapitulatif)

Périmètre Fiches Tours Sessions MCP Sessions de jeu Durée d'agent
V-min I1, B1, V1 ≈ 77 0 1 ≈ 2 h
+ V-1 (panneau) I2, B2, V2 ≈ 92 0 1 à 2 ≈ 2 h 30
+ V-2 (case de réglage) I3, B3, V3 ≈ 62 0 0 à 1 ≈ 1 h 30
+ H2 I4 (+ VAL) ≈ 45 1 0 ≈ 1 h
Option A complète (comparaison) ~10 fiches ≈ 200 ≈ 8 (estimé : 70 instructions ≈ 70 nœuds ≈ 300 appels MCP, plus widgets et DisableBonus) 2 ≈ 8 h

4.2 Risques

# Risque Parade
R1 Plantages autour des orgasmes : l'auteur a dû ajouter l'option 5.27 faute de reproduire des plantages (Change_Logs.txt:34) ; cause inconnue V-min sans widget ni création d'objet UMG dans la pile de l'orgasme ; sondage hors de la pile de Cum ; aucune destruction dans un gestionnaire de clic (V-1) ; ini bDisabled ; journal de chaque étape
R2 Interface (V-1) : panneau qui capte la souris, mauvais z-order avec le menu d'actions, apparence conteneur non cliquable, boutons seuls cliquables ; z-order entre les précédents 50 et 200 ; essai J2
R3 Appels par réflexion : nom ou paramètre renommé, type inattendu (réel float ou double) recherche par nom, CastField des deux types, avertissement unique, abandon sans effet
R4 Sondage : faux positif (remise à zéro du compteur, personne qui entre dans la scène), orgasme manqué (scène qui finit avant le tick) premier passage = mémorisation sans récompense ; baisse = resynchronisation ; tick 0,1 s ; l'orgasme manqué n'a pas d'autre effet que l'absence de récompense
R5 Équilibrage : modifier les stats des PNJ (l'auteur le fait) identique à l'auteur ; Q-ORG5-4
R6 Build partagé avec CAM (Room B2 non commité) et d'autres fichiers C++ modifiés fichiers neufs seulement ; un seul build à la fois ; annonce de gel
R7 ORG4 (fin par Endsex) : un appel direct de GiveOrgasmReward sans Cum n'incrémente pas le compteur Q-ORG5-6 ; H2 si nécessaire
R8 Licence : code de l'auteur sous MIT (Licenses\Vinfamy_License.txt:1, notre copie) ; la reconstruction reprend le comportement lu, pas le code commentaire d'origine et de licence en tête du .h ; décision de l'utilisateur (Q-ORG5-9)
R9 Délai : alpha le 2026-10-18 V-min seule dans l'alpha, 3.1
R10 Faux sentiment de preuve : tout le comportement est lu par désassemblage, jamais vu en jeu J1 obligatoire avant toute mention « conforme à l'auteur »

4.3 Lectures MCP / jeton UE manquantes (non lancées)

# Lecture Ce qu'elle trancherait
L-M1 MCP list_toolsets puis describe_toolset filtré sur les noms contenant widget, umg ou user_widget (pas de description complète, lp-mcp § 1 règle 6) si l'arbre de widgets et la valeur par défaut d'une map sont créables par MCP : seul point qui rend les options A et C réalistes
L-M2 MCP ObjectTools.get_properties sur /Game/BPs/GI.Default__GI_C (CurrentTags, SexPersons, Cursor, PlayerCharacter, SexOn) et /Game/BPs/Person.Default__Person_C (Sex_OrgasmCounts, isPlayer, Name_First) — forme déjà utilisée : STG-B1-IMPL.md:41 types des propriétés (texte ou chaîne, réel float ou double) ; facultative : l'IMPL les gère par CastField et les journalise
L-M3 MCP BlueprintTools.get_node_infos sur K2Node_CustomEvent_87 et K2Node_CallFunction_1005 de Person, puis find_node_types pour le nœud NotifyOrgasm seulement pour H2 (I4) : broches, type_id
L-M4 commandlet LPDumpWidgetTree -BP=Cursor (éditeur fermé, lp-commandlets) seulement pour A et C : où placer ScrollBonuses dans notre arbre de Cursor (nos SexExclusives, ActionBox, BondageBox existent, grep -a -c 10 / 5 / 7 ; ScrollBonuses, TextBlock_0 : 0)
L-J1 essai en jeu de J1 (7.7 à 7.9) effet réel : fréquence des récompenses, tags de CurrentTags à l'orgasme, texte du nombre
L-S1 lecture non faite par manque d'intérêt pour B : propriétaire du son ui_positive du bouton BonusReward (style de bouton), arbre de widgets de Cursor de B apparence uniquement

4.4 Questions (utilisateur / orchestrateur)

# Question Recommandation
Q-ORG5-1 La version minimale (application automatique de la première récompense retenue, sans grille) convient-elle pour l'alpha, ou ne rien mettre dans l'alpha ? oui, V-min ; la grille (V-1) seulement si J1 PASS le 16
Q-ORG5-2 Option B (C++ autonome) ou A / C (identique à l'auteur, exige L-M1) ? B
Q-ORG5-3 Nombre de récompenses : 3 (code du build 2023.04) ou 5 (journal 5.26) ? 3 (le code fait foi)
Q-ORG5-4 Récompenses pour toute personne qui jouit (comme l'auteur, PNJ compris) ou pour le joueur seulement ? comme l'auteur ; attractiontoplayer reste réservée aux PNJ intéressés par le joueur
Q-ORG5-5 Valeur par défaut de bDisabled dans l'alpha (faux = fonction active) ; case de réglage avant l'alpha (V-2) ou ini seulement ? faux ; ini seulement
Q-ORG5-6 Accroche H1 (sondage) ou H2 (nœud dans GiveOrgasmReward, touche Person) ; que fera ORG4 : Person::Cum ou GiveOrgasmReward seul ? H1 pour l'alpha ; H2 après, selon ORG4
Q-ORG5-7 Position du panneau (V-1) : à droite au centre (hypothèse), près du menu d'actions, ailleurs ? Retrait en fin de scène (écart voulu) ou boutons conservés comme l'auteur ? droite, centre ; retrait en fin de scène
Q-ORG5-8 Affichage du texte d'en-tête et des trois cas de E8 (textes de l'auteur en anglais, à garder tels quels ?) oui, tels quels
Q-ORG5-9 Licence : reconstruire le comportement lu dans le build de l'auteur (MIT, Licenses\Vinfamy_License.txt:1) est-il accepté, avec mention d'origine ? oui, avec commentaire d'origine
Q-ORG5-10 Garder le désassembleur Kismet (3 scripts du scratchpad de session) : le ranger dans Tools\ (lecture seule, utile à toute lecture de build cuit) ? oui, par une fiche d'outillage

5. Interdits

  • Version minimale : aucun asset modifié (ni GI, Person, Room, Cursor, GameSettings, MainMenu, SettingCheckbox) ; aucun champ ajouté à GameSettings.sav ; le bonus ancien (OrgasmIrBoost, mood, attractiontoplayer) reste intact.
  • Pas de création de widget, d'objet UMG ni d'AddToViewport dans la pile de l'événement Cum ; pas de destruction d'un widget dans son propre gestionnaire de clic.
  • Pas de ProcessEvent sans FindFunction valide, sans paramètres initialisés puis détruits ; pas d'accès à une personne sans IsValid.
  • Pas de contournement de garde : une propriété ou une fonction introuvable = avertissement unique et abandon, jamais de repli silencieux.
  • Pas de delete_node ni de type_id improvisé (H2) ; pas de commit par l'agent (le gardien) ; build et commandlets seulement sous jeton UE, éditeur fermé.
  • Aucune ligne de la grille d'un autre lot, aucun contenu de jeu (noms, textes) dans un skill ou un message de commit public (lp-paths).

6. Valeurs moteur lues dans le moteur installé

Valeur Source Établi
FCeil prend un double et rend un int32 ; MapRangeClamped prend et rend des double ; Subtract_DoubleDouble, Multiply_DoubleDouble D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Engine\Classes\Kismet\KismetMathLibrary.h:796, :836, :551, :555 oui
RetriggerableDelay(WorldContext, float Duration, FLatentActionInfo), latent …\Kismet\KismetSystemLibrary.h:700-701 signature oui, remplacement du délai non relu
GameViewportClient::AddViewportWidgetContent(TSharedRef<SWidget>, int32 ZOrder) et RemoveViewportWidgetContent …\Engine\GameViewportClient.h:258, :265 oui
EX_JumpIfNot = « Goto if not expression » (saute quand la condition est fausse) ; EX_Context, EX_VirtualFunction, EX_CallMath, EX_SwitchValue, EX_TextConst : formats d'instruction D:\Game\Launcher\Engine\UE_4.27\Engine\Source\Runtime\CoreUObject\Public\UObject\Script.h:173 ; …\ScriptSerialization.h:150-557 (moteur 4.27 le plus proche du 4.20 de l'auteur ; contrôle : décodage exact jusqu'à EX_EndOfScript et cibles de saut toutes sur un début d'instruction, annexe A) oui
FText::AsNumber / formatage par défaut des flottants (nombre de décimales) recherche de MaximumFractionalDigits dans Core\Public\Internationalization\FastDecimalFormat.h : aucune occurrence ; non lu ailleurs incertain : à lire à l'IMPL (Text.h, FastDecimalFormat.h voisins) avant de fixer l'attendu « 1.1 »

7. Critères de VAL (commande → attendu ; « attendu » écrit avant tout lancement)

# Fiche Commande ou lecture Attendu
7.1 V1 git status --porcelain -- Content Source Config (jeu) comparé à l'état d'entrée (10 M, 4 ?? au 2026-10-14) seules deux lignes ?? de plus : Source/LifePlay/LPBonusRewardSubsystem.h et .cpp ; aucun M de plus
7.2 V1 .\Tools\Build.ps1 (éditeur fermé) puis .\Tools\Build.ps1 -FromLog <journal> code de sortie 0 ; module LifePlay recompilé ; 0 erreur ; 0 avertissement C4996 nouveau sur les deux fichiers
7.3 V1 Grep des clés dans le .cpp : motifs des 20 clés de 1.2 20 clés, 20 listes de tags identiques à 1.2 (relecture ligne à ligne)
7.4 V1 lecture du .cpp contre 1.3 et 2.4 ordre des opérations de RewardChange identique ; Pick : 10 candidates, max 3, Overlaps avec drapeau vrai, règle attractiontoplayer ; aucun widget créé dans V-min
7.5 V1 .\Tools\LogStats.ps1 -Latest <journal de démarrage> -Pattern 'Bonus : contrôle formule' 1 ligne contrôle formule OK ; 0 ligne Error du sous-système
7.6 V1 CompileAllBlueprints éditeur fermé ; LPTestStringCompat 0 erreur /Game/ ; 3120 / 0 / 60 (aucun Blueprint modifié, valeurs de référence du lot)
7.7 J1 scène avec le joueur jusqu'à un orgasme, journal avec -ScriptStackOnWarnings ; LogStats -Pattern 'Bonus :' par orgasme : 1 ligne orgasme de, puis soit 1 ligne <stat> <±valeur> soit aucune récompense éligible ; la valeur suit 1.3 pour le x journalisé
7.8 J1 même journal, motifs Accessed None et PersonCumming 0 occurrence nouvelle par rapport au journal de référence du lot
7.9 J1 ini bDisabled=True, nouvel orgasme 1 ligne désactivé ; 0 ligne de récompense ; la ligne mood du bonus ancien est toujours là
7.10 V2 / J2 (V-1) clic sur un bouton 1 ModifyStat, panneau retiré au tick suivant, 3 boutons au plus, 0 plantage ; clic hors panneau : les actions du jeu répondent

Annexe A. Commandes et lectures (CART 2), comptes bruts

Aucun caractère de redirection dans les commandes ; B, O comme dans les sigles. <S> = scratchpad de session.

  1. Format du bytecode : Read de UE_4.27\…\ScriptSerialization.h (574 lignes) et Script.h:150-300.
  2. Liste des fonctions de Cursor : python -I <S>/kdis.py B/UI/Cursor.uasset B/UI/Cursor.uexp list → total=122954 names=703 exports=764 imports=293 ue=136556 ; ExecuteUbergraph_Cursor size=7504 uexp_off=6522 ; PopulateBonusRewards size=86 uexp_off=14414.
  3. Talon : … kdbg.py B/UI/Cursor.uasset B/UI/Cursor.uexp PopulateBonusRewards 0 99999999 300 → 5 instructions, 14470 v:ExecuteUbergraph_Cursor(10856).
  4. Corps : … kdbg.py … ExecuteUbergraph_Cursor 7000 9300 230 → q=7122 end=14014 tail=12 mem=10864 decoded=370 last_p=14014 err=None ; jumps=66 sur debut=66 (les 66 cibles de saut tombent sur un début d'instruction : le décodage est cohérent).
  5. Appel dans Person : … kdbg.py B/BPs/Person.uasset B/BPs/Person.uexp ExecuteUbergraph_Person 20700 21700 420 → decoded=5164 … err=None, jumps=911 sur debut=911.
  6. Table : python -I <S>/strs.py B/UI/Cursor.uexp 4620 6420 3 → 20 clés et leurs tags (offsets de 1.2).
  7. BonusReward : … kdis.py B/UI/BonusReward.uasset B/UI/BonusReward.uexp list → 3 fonctions ; kdbg.py … ExecuteUbergraph_BonusReward → decoded=8 ; Get_RewardText_Text_0 → decoded=27, texte {stat} {sign}{change}. Get_TextBlock_0_Text_0 → decoded=19.
  8. Utilisateurs des noms : … kall.py B/UI/Cursor.uasset B/UI/Cursor.uexp 'ScrollBonuses|lastCum|countBR|BonusReward|statTags' 120 → fonctions=45 decodees=45 correspondances=15 (13 dans l'ubergraph, 2 dans Get_TextBlock_0_Text_0). grep -r -l -a -E "ScrollBonuses|BonusReward_C|PopulateBonusRewards" B/BPs B/UI --include=*.uasset → Person.uasset, BonusReward.uasset, Cursor.uasset.
  9. DisableBonus : … kall.py sur BPs/GI, BPs/GameSettings, UI/MainMenu, UI/SettingCheckbox avec le motif DisableBonus → GI fonctions=609 decodees=609 correspondances=2 (:866870, :869178) ; GameSettings fonctions=0 ; MainMenu fonctions=62 decodees=62 correspondances=0 ; SettingCheckbox fonctions=5 decodees=5 correspondances=2 (:1921, :13472). Get_SexExclusives_Visibility_0 → decoded=6.
  10. GI.Overlaps et GI.IsInterestedIn du build : kdbg.py B/BPs/GI.uasset B/BPs/GI.uexp Overlaps (decoded=32, jumps=8 sur debut=8) et IsInterestedIn (decoded=20, jumps=6 sur debut=6) ; nos fonctions : L6f-G:19622-19673 (Overlaps, 14 nœuds, paramètres Array1, Array2, IfEmptyThenTrue) et :23421 (IsInterestedIn, 28 nœuds) ; noms dans O\BPs\GI.uasset (grep -a -c -F) : Overlaps 5, IsInterestedIn 11, Cursor 10, CurrentTags 1, PlayerCharacter 1, SexOn 1, SexPersons 33, PersonCumming 1. Tags dans O\BPs\GI.uasset (grep -a -o -w -F <mot> | wc -l) : Penetration 396, Foreplay 158, Cum 33, Anal 215, Titfuck 3, Boobjob 4, Cow 54, Cowgirl 204, Doggy 182, Doggystyle 11, Handjob 80, RubPussy 18, FingerPussy 9, Missionary 148, Oral 236, Blowjob 173, Cunnilingus 19, LickPussy 37, LickAss 4, Rimjob 20, ReverseCow 2, ReverseCowgirl 56, Aggressive 79, AggressiveFM 31, Spooning 19, Sidefuck 19, Spoon 5, Toys 30, Dildo 14, Vibrator 12, Tribadism 2, Scissor 12, Scissoring 2, Vaginal 327. Noms dans O\BPs\Person.uasset : Sex_OrgasmCounts 1, isPlayer 1, Name_First 1, ModifyStat 51, QueryStat 18, GiveOrgasmReward 2, OrgasmIrBoost 2. O\UI\Cursor.uasset : ScrollBonuses 0, TextBlock_0 0, PopulateBonusRewards 0, lastCum 0, SexExclusives 10, ActionBox 5, BondageBox 7.
  11. Formule : python -I <S>/calc.py → table de 1.3 (double et float32 identiques). Sortie recopiée : 0 → 2.0 ; 10 → 1.9 ; 25 → 1.6 ; 50 → 1.1 ; 75 → 0.6 ; 90 → 0.3 ; 95, 99, 100, 120 → 0.2 ; −30 → 1.5.
  12. Journal de l'auteur : Read D:\XxX\LifePlay_2023_04_Stable_64bit\Docs\Change_Logs.txt lignes 1-46 (:34 option 5.27 et plantages, :39 « 5 bonus rewards »).
  13. Dépôt : git -C "D:/Game/LifePlay-master 5.8" status --porcelain -- Content Source Config → M : Content/BPs/GI.uasset, Person.uasset, Room.uasset, Source/LifePlay/LPDebugSubsystem.cpp/.h, LPDirectControlSubsystem.cpp/.h, LPOutdoorRoomSubsystem.cpp/.h, LifePlay.cpp ; ?? : LPCameraModeSubsystem.cpp/.h, LPSaveRelaunch.cpp/.h ; rc=0. git log --oneline -3 : tête 0745917.
  14. Précédents C++ : Grep de FindFunction|ProcessEvent|AddViewportWidgetContent|… dans Source\LifePlay (lignes citées en 2.1) ; LifePlay.Build.cs:38 (Slate, SlateCore, UMG).
  15. Build de référence : Grep de Total execution time dans STE-H3d_Build_20261013-124425.txt → ligne 10 : 18.56 seconds ; ligne 7 : toolchain 14.50.35739.
  16. Licence : Read Licenses\Vinfamy_License.txt → ligne 1 : « … are under MIT ».
  17. Contrôle du livrable : fins de ligne (tr -cd '\r' | wc -c → 0 CR), aucun nom d'utilisateur ni C:\Users (Grep → 0). Désassembleur (méthode) : en-tête .uasset UE 4.20 lu à la main (variante 104 octets par export, 28 octets par import, noms avec 4 octets de hachage) ; le bytecode d'une fonction commence après 8 octets de tailles (mémoire, disque) ; EX_ décodés d'après ScriptSerialization.h 4.27 ; pointeurs de propriété ou d'objet = 4 octets sur disque, noms de fonction virtuelle = 8 octets sur disque et 12 en mémoire (c'est l'hypothèse qui rend toutes les cibles de saut cohérentes : 66 / 66, 911 / 911, 13 / 13 sur FilterActions, avec 8 octets : 2 sur 13). Les offsets d'instruction (m…) sont ceux de la mémoire, les autres ceux du .uexp.

Annexe B. Établi / estimé / incertain

  • Établi : tout E1 à E10 (bytecode décodé, cohérence des sauts contrôlée) ; la table de 1.2 ; la formule et ses 21 valeurs ; DisableBonus : sémantique, stockage, interface chez l'auteur ; absence chez nous de ScrollBonuses, PopulateBonusRewards, lastCum dans Cursor ; présence chez nous de Cursor dans GI, de Overlaps, IsInterestedIn, QueryStat, ModifyStat, Sex_OrgasmCounts ; précédents C++ cités ; licence MIT de la copie Licenses ; état git du 2026-10-14.
  • Estimé : la grille s'ajoute au bonus ancien (ordre des instructions, confirmé par le saut :21262) ; RetriggerableDelay remplace le délai en cours ; types des propriétés lues par réflexion (CurrentTags tableau de chaînes, Sex_OrgasmCounts entier, Name_First texte ou chaîne) ; WhoIsInterested = Person ; tags d'animation = mots présents dans GI ; tous les tours, durées et nombres de nœuds ; la pratique « ne pas détruire un widget dans son gestionnaire » (suspicion, non prouvée comme cause des plantages) ; faisabilité d'ici le 2026-10-18.
  • Incertain : comportement en jeu (rien n'a été lancé) ; capacité du MCP à créer des widgets ou à fixer la valeur par défaut d'une map (L-M1) ; apparence exacte et position du panneau de l'auteur (arbre de widgets de Cursor non lu) ; formatage de « 1.1 » par FText (section 6) ; ce que fera ORG4 (SPEC absente) ; son ui_positive ; effet réel des tags de position sur la fréquence des récompenses.

Tours : 38 / 55 (deux Write du livrable, contrôles et compte rendu compris ; le premier Write portait deux comptes erronés — scripts et exécutions — corrigés ici)

Constats

  • F-ORG10 : le nombre de récompenses est 3 dans le code (Cursor.uexp:8607), pas 5 (Change_Logs.txt:39, version 5.26) : le journal de l'auteur est antérieur au build 2023.04 ; corrige AUD § 9.1 et § 9.11 (L14 « origine du nombre 5 » résolu).
  • F-ORG11 : la valeur à stat = 100 est 0,2 (pas 0,1 ni « 0,1 ou 0,2 », AUD § 9.5) ; mesuré en double et en float32.
  • F-ORG12 : DisableBonus vrai garde le bonus ancien et supprime seulement la grille (L15 résolu, AUD § 9.3 et § 9.7 : « incertain » devient établi).
  • F-ORG13 : les deux lignes « prone_to_orgasm -1.1 » et « fitness +1.1 » des captures sont bien deux boutons proposés (AUD § 9.4) : elles partagent les tags {Penetration, Foreplay, Cum}, et la valeur 1,1 correspond à x vers 50 (1.3).
  • F-ORG14 : le bonus ancien et la grille sont indépendants : on peut livrer le tirage sans toucher GiveOrgasmReward (accroche H1).
  • F-ORG15 : un désassembleur Kismet de build cuit UE 4.20 existe maintenant (3 scripts Python de lecture seule dans le scratchpad de session) ; il décode 100 % des fonctions des assets lus (Cursor 45 / 45, GI 609 / 609, MainMenu 62 / 62, SettingCheckbox 5 / 5, ubergraph de Person 5 164 instructions) ; proposition : le ranger dans Tools\ (Q-ORG5-10), ce qui lèverait la limite « aucun lecteur de Kismet cuit » de AUD § 9.11 L14.
  • À verser : lp-commandlets (section à créer « Lire un build cuit ») : cohérence de lecture = toutes les cibles de saut sur un début d'instruction ; FName 12 octets en mémoire, pointeurs 4 octets sur disque ; l'EventGraph d'un événement personnalisé est un talon ExecuteUbergraph_X(entrée) et le corps est dans l'ubergraph. sk-protocol § 7 : python -I <fichier du scratchpad> n'a jamais été refusé par le crochet (20 exécutions), seuls python -c et les heredocs le sont.
  • Fichiers modifiés par cette fiche : le présent livrable seulement (deux Write, le second corrigeant le premier ; fins de ligne et noms d'utilisateur contrôlés sur le premier, texte inchangé hors les trois corrections).
  • Fichiers à commiter : A D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STE\STE-ORG5-SPEC.md (dépôt du jeu, branche ue5.8 ; .md suivi sous etat/).

Décisions de l'utilisateur (2026-10-14, session STE)

  • Q-ORG5-1 : version minimale pour l'alpha (tirage comme l'auteur, application automatique de la première récompense, sans grille) ; grille V-1 seulement si J1 PASS le 16.
  • Q-ORG5-2 : option B, C++ autonome. Q-ORG5-3 : 3 récompenses (le code fait foi). Q-ORG5-4 : toute personne qui jouit, PNJ compris, comme l'auteur. Q-ORG5-9 : licence MIT acceptée, origine et licence citées en tête du .h.
  • Orchestrateur : Q-ORG5-5 = bDisabled faux, ini seulement ; Q-ORG5-6 = H1 (sondage) pour l'alpha. Note : le bonus d'ORG4 à Endsex appelle GiveOrgasmReward sans incrémenter Sex_OrgasmCounts : H1 ne le verra pas (R7), accepté pour l'alpha.

Règle commune ORG4 / ORG5 (Big Boss, 2026-10-14)

  • Pour un même orgasme, une personne reçoit au plus une fois le bonus de base (GiveOrgasmReward) et au plus une fois les récompenses ORG5 (3 au plus) ; le cumul base + ORG5 est voulu, le même bonus deux fois non.
  • Orgasme réel (Person::Cum, jauge à 100 ou choix « Cum on … ») : GiveOrgasmReward une fois (chemin existant) ; ORG5 une fois, déclenché par l'incrément de Sex_OrgasmCounts (accroche H1).
  • Endsex (O4c) : GiveOrgasmReward une fois par participant éligible (homme > 90, femme = 100), sans Person::Cum : Sex_OrgasmCounts inchangé, donc pas de récompense ORG5 à Endsex ; un participant qui vient de jouir a sa jauge remise à 0 par Cum et n'est pas éligible : pas de second bonus de base.
  • Toute IMPL qui change l'un de ces déclencheurs relit cette règle et la VAL la contrôle (V6 : un orgasme = 1 marqueur de base + au plus 1 ligne ORG5 par personne).