11 KiB
Fiche STE-G3 — Niveau N2 — Modèle prévu (modèle de l'agent lp-impl) | utilisé claude-opus-5-5 — Agent lp-impl — Skills sk-protocol, ue-cpp-build, lp-build, lp-ue-compat (préchargés), sk-change-safety (invoqué)
STE-G3-IMPL : NotifyCoupleTeleported(), reprise de LastSafe après une téléportation par CAM (2026-10-14)
Résultat : réussi (écrit, non compilé). Fonction publique ajoutée à ULPShowCoupleSubsystem : une seule
écriture de LastSafe à la place actuelle du meneur, aucun balayage, gardes avant toute écriture. Compilation
confiée au build COMMUN-11 (fiche § 3).
| Mesure | Avant (2026-10-14, entrée de fiche) | Après (2026-10-14) |
|---|---|---|
MD5 Source\LifePlay\LPShowCoupleSubsystem.h |
57dc8cd468d2fb5de231bfbe25346389 |
44c721ee9e82bdfdf7571e493af70e39 |
MD5 Source\LifePlay\LPShowCoupleSubsystem.cpp |
35cf128c8c3e059130e7cf48d9fa0454 |
3cdd572d78b691eef0a3f02b1b37a486 |
Fins de ligne (git ls-files --eol) |
i/crlf w/crlf (les deux) |
i/crlf w/crlf (les deux) |
Commande des MD5 : certutil -hashfile "<fichier>" MD5. Mesuré, git -C "D:/Game/LifePlay-master 5.8" diff --stat -- Source/LifePlay/LPShowCoupleSubsystem.h Source/LifePlay/LPShowCoupleSubsystem.cpp :
Source/LifePlay/LPShowCoupleSubsystem.cpp | 19 +++++++++++++++++++
Source/LifePlay/LPShowCoupleSubsystem.h | 4 ++++
2 files changed, 23 insertions(+)
1. Fichiers modifiés
D:\Game\LifePlay-master 5.8\Source\LifePlay\LPShowCoupleSubsystem.hl. 28-30 (sectionpublic, aprèsDeinitialize) : commentaire de deux lignes et déclarationvoid NotifyCoupleTeleported();.D:\Game\LifePlay-master 5.8\Source\LifePlay\LPShowCoupleSubsystem.cppl. 806-824 (aprèsKeepTogether) : définition.
Diff résumé de la définition :
void ULPShowCoupleSubsystem::NotifyCoupleTeleported()
{
ACharacter* Who = Lead.Get();
if (!bEngaged || !Who || !Partner.Get() || !GetWorld())
{
return;
}
const FVector Now = Who->GetActorLocation();
if (!(Now - LastSafe).IsNearlyZero())
{
UE_LOG(LogLifePlay, Warning, TEXT("Show couple : place reprise apres teleportation %s (ecart %.0f)"),
*Now.ToString(), FVector::Dist(LastSafe, Now));
}
LastSafe = Now;
LastBlocker.Reset();
}
(plus deux lignes de commentaire en tête du corps, non recopiées.)
1.1 Pour CAM : nom, signature, en-tête, appel
- Nom :
ULPShowCoupleSubsystem::NotifyCoupleTeleported. - Signature :
void NotifyCoupleTeleported();(publique, nonconst, sans paramètre, sans retour). - En-tête :
#include "LPShowCoupleSubsystem.h"(même moduleLifePlay, classeLIFEPLAY_API,LPShowCoupleSubsystem.h:20). - Appel depuis le C++, pas depuis un Blueprint : B2p-F est « C++
LPCameraModeSubsystem, aucun asset » (CAM-COMMUN9-DIAG.mdl. 129 et l. 215) ; G3 est « appelée par B2p-D après une pose libre validée par G1 » (l. 191-193) ; le glisser B2p-D est du C++ (LPCameraModeSubsystem.cpp:1064-1068). Donc pas deUFUNCTION(fiche § 3 : seulement si un Blueprint l'appelle). - Forme d'appel conseillée (même accès que
LPCameraModeSubsystem.cpp:287,UGameInstance::GetSubsystemGameInstance.h:440), après la boucle qui déplace le couple (LPCameraModeSubsystem.cpp:1065-1068) et seulement si G1 a validé la place :
if (ULPShowCoupleSubsystem* Show = GI->GetSubsystem<ULPShowCoupleSubsystem>())
{
Show->NotifyCoupleTeleported();
}
1.2 Grandeur reprise (point amont de la fiche § 3)
KeepTogetherécritLastSafe = Who->GetActorLocation();avecWho = Lead.Get()(.cpp:752,.cpp:804) ;Engageécrit la même grandeur (LastSafe = InLead->GetActorLocation();,.cpp:400). La fonction reprend exactement celle-là : la place de l'acteur meneur (Lead), pas la boîte ni le partenaire. Établi.- Effet sur l'image suivante :
KeepTogethercalculeDelta = Now - LastSafe(.cpp:760-761) ; si CAM n'a plus rien bougé,Deltaest nul etKeepTogethersort sans balayer (.cpp:762-765) ; sinon il balaie depuis la place libre posée par CAM (ResolveCoupleMove(…, LastSafe, Delta, …),.cpp:792-793). Établi par lecture.
1.3 États remis à zéro
LastBlocker(« dernier bloquant ») : vidé. Il n'est lu que pour dédoublonner le journal (.cpp:781coque,.cpp:794« bloque par ») ; aucun effet sur le mouvement. Conséquence : le prochain blocage (ou la coque) est réécrit une fois au journal, utile pour l'essai CAM-74. Établi (toutes les occurrences lues :.h:53,.cpp:781, 790, 794, 798, 823).- Aucun autre état de balayage dans le sous-système : profondeur, normale et bloquant sont des variables locales du
résultat
Move(.cpp:792-799).Box,FittedPair,RejectedPair,LoggedExtent(mesure de la boîte),bPawnLogged,SavedFurniture,SavedSeats,SavedPartnerMove(collisions, mouvement gelé) ne sont pas des états de balayage : non touchés. Établi par lecture de l'en-tête (.h:45-75). - Résolveur partagé :
Grep "static "surPlugins\LPAnimCore\Source\LPAnimCore\LPCoupleSimCore.cpp→ 1 résultat,static const TCHAR* Excluded[](l. 46), table constante : pas d'état gardé entre deux appels.LPCoupleSim.hcherché seulement avec le motifstatic … =(0 résultat) : absence d'autre état statique estimée.
1.4 Gardes, appel répété, appel hors scène
- Gardes avant toute lecture ou écriture :
bEngagedfaux (hors scène, ouReleasepassé :.cpp:668-674), meneur absent ou détruit (Lead.Get()nul), partenaire absent, monde absent (GetWorld()nul) → retour sans rien changer, sans plantage (aucun déréférencement avant les gardes). - Pas de garde sur la boîte (
Box) : non nécessaire pour reprendreLastSafe. - Appel répété : sans danger.
LastSafereçoit la même valeur (idempotent) ;LastBlockerest revidé ; la ligne de journal n'est écrite que si la place a bougé de plus deUE_KINDA_SMALL_NUMBER(Vector.h:600). - Appel hors scène : sans danger, la garde
bEngagedsort avant toute écriture. Au premier tour d'une scène,Engagerepose de toute façonLastSafesur le meneur (.cpp:400). - Contrat pour CAM : n'appeler qu'après une pose validée par G1. Si la place posée recouvrait un meuble, la
fonction en ferait la nouvelle place sûre et
KeepTogetherne dépénètrerait pas tant que le meneur ne bouge pas (Deltanul,.cpp:762-765). Estimé par lecture.
1.5 API moteur relues (UE 5.8, D:\Game\Launcher\Engine\UE_5.8\Engine\Source\)
TWeakObjectPtr::Get():Runtime\Core\Public\UObject\WeakObjectPtrTemplates.h:141([[nodiscard]], valeur utilisée).UObject::GetWorld() const:Runtime\CoreUObject\Public\UObject\Object.h:711(déjà appelé par le fichier,.cpp:289,.cpp:755;UGameInstanceSubsystemne le redéfinit pas :GameInstanceSubsystem.hetSubsystem.hsansGetWorld).AActor::GetActorLocation() const:Runtime\Engine\Classes\GameFramework\Actor.h:2502.TVector::IsNearlyZero(T Tolerance = UE_KINDA_SMALL_NUMBER) const:Runtime\Core\Public\Math\Vector.h:600.TVector::ToString() const:Vector.h:861;TVector::Dist(const TVector&, const TVector&)statique, rendT=doublepourFVector:Vector.h:1015(format%.0f, comme.cpp:796).FString::Reset(int32 NewReservedSize = 0):Runtime\Core\Public\Containers\UnrealString.h.inl:332.UGameInstance::GetSubsystem<T>() const(pour CAM) :Runtime\Engine\Classes\Engine\GameInstance.h:440.LogLifePlay:Source\LifePlay\LifePlay.h:9, inclus par.cpp:24.
2. Écarts à la SPEC
- E1 :
sk-change-safetyinvoqué après les deux Edit et non avant. Instantané pris par l'orchestrateur et vérifié ensuite :D:\Game\LifePlay_Backup_5.5\STE-G3\Source\LifePlay\LPShowCoupleSubsystem.hMD557dc8cd468d2fb5de231bfbe25346389,.cppMD535cf128c8c3e059130e7cf48d9fa0454(identiques à l'entrée de fiche),manifest.csvprésent. Sans effet sur le résultat. - E2 : la ligne
UE_LOGest conditionnelle (écrite seulement si la place a changé), pour ne pas écrire une ligne par appel sans déplacement. Elle reste une seule ligne, catégorieLogLifePlay, niveauWarningcomme le reste du fichier. - E3 : pas de
UFUNCTION: l'appelant est du C++ (§ 1.1), conforme à la fiche § 3. - E4 : la fiche ne dit pas où placer la fonction dans le
.cpp; placée aprèsKeepTogether, à la fin du fichier. - Budget suivi : rubrique 9 de la fiche (20 tours), et non le budget N3 du message de lancement.
3. Instantané
Pris par l'orchestrateur (fiche § 2) : D:\Game\LifePlay_Backup_5.5\STE-G3\ (2 fichiers + manifest.csv), relu par
MD5 le 2026-10-14 (§ 2 E1). Retour arrière (proposé, non lancé) : recopier les deux fichiers de l'instantané sur
Source\LifePlay\ (Tools\Restore.ps1 -Lot STE-G3, à décider par l'orchestrateur).
4. Ce qui n'a pas été fait
- Aucune compilation (build COMMUN-11,
lp-builder), aucun éditeur, MCP, commandlet ni jeu (fiche § 6). - L'appel côté CAM (B2p-F) n'est pas écrit : fichier CAM, hors périmètre.
- Ligne STE-G3 du registre
STE-TACHES.md, entrée CHG, commit : orchestrateur et gardien. - Le mode « tourner » de la prise (
CoupleGrabMode == 2,LPCameraModeSubsystem.cpp:1071-1085) déplace aussi le meneur autour du pivot ; le DIAG ne prévoit l'appel qu'après le glisser. Question pour CAM, non traitée.
5. Points à confirmer en VAL
- Diff limité aux deux fichiers :
git diff --stat= 2 fichiers, 23 insertions, 0 suppression. LastSafeécrit une seule fois, àLead.Get()->GetActorLocation(), même grandeur que.cpp:804.- Aucun appel à
ResolveCoupleMoveni à un balayage ou recouvrement dansNotifyCoupleTeleported. - Gardes
bEngaged, meneur, partenaire, monde placées avant toute lecture ou écriture. LastBlockerseul état remis à zéro, lu seulement pour le journal (.cpp:781,.cpp:794).- Déclaration en section
public(.h:30), sansUFUNCTION. - Fins de ligne CRLF conservées (
git ls-files --eol:w/crlfpour les deux fichiers). - Aucun nom local qui masque un membre (
Who,Now: pas de membre de ce nom,.h:45-75). - Build COMMUN-11 :
LPShowCoupleSubsystem.cppcompilé, 0 erreur, 0 avertissement nouveau (C4458, C4456 compris). - En jeu, CAM-74 : couple coincé, glisser vers le milieu de la pièce → ligne
Show couple : place reprise apres teleportation …puis plus debloque par … profondeur 3à chaque image. - En jeu : volume de la ligne « place reprise » pendant un glisser continu (une ligne par image déplacée si CAM appelle à chaque image).
6. Fichiers à commiter
Dépôt jeu D:\Game\LifePlay-master 5.8, branche ue5.8 :
- M Source/LifePlay/LPShowCoupleSubsystem.h
- M Source/LifePlay/LPShowCoupleSubsystem.cpp
- A Docs/Migration/etat/ST/STE/STE-G3-IMPL.md
Tours : 15 / 20