85 KiB
Fiche CAM-T5 — Niveau N3 — Modèle prévu opus (opus-xhigh) | utilisé claude-opus-5-5 — Agent opus-xhigh — Skills sk-protocol, lp-mcp, lp-lot (préchargé aussi : debug-verification) — amendée CAM-T5b (même agent, contexte gardé, 2026-10-11)
CAM-T5-SPEC : phase 2, réduction et repositionnement des caméras par Blueprints (voie B, MCP) (2026-10-11, amendée CAM-T5b)
Copie D:\Game\LifePlay-master 5.8, branche ue5.8, HEAD 4283c13. Lecture seule : aucun éditeur, MCP, commandlet ni
build ; seul ce fichier est écrit. Les décisions qui font foi sont celles de CAM-CIBLE.md § 4b
et § 4c (réponses de l'utilisateur aux Q1-Q20 de cette SPEC : « q4 lissage et évitement, le reste oui »).
Amendement CAM-T5b : § 4c intégré. Sections modifiées : en-tête, § 1, § 2, § 4 (R1, R5, R6, R12, R16 ; R17-R19
nouveaux ; Q1-Q20 décidées), § 5, § 6, § 7, (a) B0 à B6, (b), (c), (d), (e) C2, (f), (g), Constats.
Amendement CAM-B0a (session CAM, 2026-10-13, après la sonde B0, CAM-B0-IMPL.md) : R1, R2, B1-1, B1-13, B2-6, (c),
(d) ; nouveau § « Identifiants de nœuds (B0a) » après (g) ; amendement B1b (après l'IMPL de B1, CAM-B1-IMPL.md § 3) : B1-1, B1-3, B1-12, § 7 V5 ; amendement B1c (essai en jeu de l'utilisateur : caméra dans la tête) : B1-3, B1-12 ; amendement B1d (2e essai : rémanence d'une image, vue aux yeux) : B1-3 réordonnée, B1-4 sortie inversée ; amendement B2d (maniement Third Person, CAM-B2d-TPS.md ; copie d'avant Backup_5.5\CAM\SPEC-avant-B2d.md) ; amendement B2b (essais de B2, exigence « caméra toujours dans la pièce », option 1 de pilotage ; CAM-B2b-AMENDEMENT.md) : nouvelle section CAM-B2b, copie d'avant Backup_5.5\CAM\SPEC-avant-B2b\ (ecefee2f) ; complément (avis de commit STE-H10) : § 7 V2 et V5, (f) B5 (MD5 de Person D1B4C63D, arrêt par handle). Aucun autre changement ; liste des points de GI inchangée.
Copie d'avant : D:\Game\LifePlay_Backup_5.5\CAM\SPEC-avant-B0a\CAM-SPEC.md (MD5 3f0f59bf…).
Abréviations (dumps texte ; « HEAD » = version citée par la fiche) :
GI=Docs/Migration/etat/ST/STE/dumps/GI__EventGraph_V5.txt;GICF=.../ST/STE/dumps/GI__CallFunction_V5.txt;ROOM=.../ST/STE/dumps/Room__EventGraph_V5.txt;PC=.../ST/STE/dumps/PC__EventGraph.txt(tous avec broches).BV=Docs/Migration/etat/CAM/CAM-T6_LPDumpFunction_20261011-013552.txt(Birdview, 4 graphes, 366 nœuds) ;CM=...CAM-T6_LPDumpFunction_20261011-013659.txt(ContactMenu, 34 graphes, 1 430 nœuds) ;PERS=...CAM-T6_LPDumpFunction_20261011-013811.txt(Person.EventGraph à HEAD, 3 684 nœuds) : redumps avec broches (CAM-T6, amendement CAM-T5b).BV4,CM4,PERS4= les listes sans broches de CAM-T4 (CAM-T4_LPDumpFunction_20261011- 005305.txt,-005400.txt,-005458.txt,CAM-T4-BUILD.md:20-22), gardées seulement où le texte d'origine les cite.- HEAD au moment de l'amendement :
c01b543(commit U8 surDocsseulement ; assets inchangés, mêmes MD5, d'après l'orchestrateur) ; les dumps V5 et CAM-T6 restent valables. SMS=Docs/Migration/etat/ST/STB/dumps/StreetMap_Static__EventGraph.txt;PCOMP=Docs/Migration/etat/CAM/CAM-T4_LPDumpComponents_20261011-004910.txt(Person) ;RCOMP=Docs/Migration/etat/post-v1/PawnDyn/PawnDyn_LPDumpComponents_20261004-223842.txt(Room, copie 5.5, 2026-10-04 : valeurs indicatives seulement).TS=D:\Game\Launcher\Engine\UE_5.8\Engine\Plugins\Experimental\Toolsets\EditorToolset\Content\Python\editor_toolset\toolsets\(outils Epic du MCP) ;ENG=D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Engine\Private\.- Marques : (N) = nœud nouveau ; « coupe » =
break_pins; « relie » =connect_pins; « suppr. » =delete_node.
1. Objectif mesurable
Dans une pièce (GI.SpaceOn vrai, hors constructeur, hors CharGen et contacts), la vue est l'une de trois caméras qui
suivent le MC, et CameraScene (ChargenCameras[0]) ne sert plus qu'au CharGen (et au constructeur, Q9) :
- C1 :
FirstPersonSMexistant du MC (composant de Person), attaché à la tête comme la POV de sexe ; POV des partenaires inchangée pendant le sexe (décision Q5). - C2 : un
CameraActorcréé à l'exécution par Room (aucune écriture de.umap), non attaché au MC : posé à l'initialisation à 175 cm derrière le MC (horizontale), à la hauteur sol + taille du MC + 50 cm, regard vers la tête ; puis poursuite lissée avec évitement des murs par une minuterie de Room : cible recalculée à chaque passage, balayage en sphère (12 cm) sur le canal Camera depuis la tête, retrait de 12 cm sur impact,VInterpToetRInterpTovitesse 8 ; portage BP deFollowCamera(LPDirectControlSubsystem.cpp:929-940) ; la minuterie s'arrête d'elle-même quand la vue n'est plus une caméra de pièce (Q1-Q4 décidées,CAM-CIBLE.md§ 4c). - C3 : le même
CameraActor(Q19 décidée) placé sous le plafond au centre de la pièce ; en extérieur (échelle Z de la racine < 0,05), à 380 cm au-dessus du sol, au bout de l'axe long du lieu, regard dans l'axe (enfilade) (Q3 et Q1 décidées). - Touche C hors sexe : C1 → C2 → C3 → C1 ; pendant le sexe : cycle POV actuel (Q4 décidée) ; commandes de scène
cameraMove/cameraFocus/cameraFocusPoint→ C2 (Q8 décidée) ; Birdview, CameraFullBody, CameraPortrait inchangées (Q6 décidée) ; défauts du lot corrigés : pivot de l'acteur Room parCameraFocus, chaînes mortes, codeFollowCamera(Q9 décidée).
Mesures de réussite (rejouées en VAL, § 7) : SetViewTargetWithBlend vivants dans les dumps : GI 4 → 4, PC 3 → 3,
Room 0 → 3 (C1, C2, C3) ; MD5 de Birdview, ContactMenu, CentralLondon.umap et Person (Q18 décidée : non touchée)
identiques aux valeurs de CAM-T4 ; compilation : 0 diagnostic, CompileAllBlueprints 0 erreur ; build Development code 0 ;
essais en jeu de l'utilisateur § (f) tous PASS ; coût de la poursuite de C2 sous le seuil de V11 ;
FollowCamera|FollowView|BirdView dans Source/ : 0 ligne.
Sortes de caméras de vue : 6 avant (CAM-AUDIT § 2) ; 6 après (Q19 décidée : un seul acteur CamRoom ajouté, FollowView
retirée). La réduction porte surtout sur les rôles : CameraScene passe de 4 rôles à 1 (+ constructeur).
2. Fichiers touchés, ordre
Sous-lots, un commit chacun, dans cet ordre (dépendances au § (a)) :
| Ordre | Sous-lot | Fichiers (dépôt du jeu, branche ue5.8) |
Graphes |
|---|---|---|---|
| 0 | CAM-B0 sonde MCP (Q16 décidée) | aucun fichier suivi ; BP jetable /Game/Dev/CAM_Probe (non commité, déplacé ensuite vers D:\Game\LifePlay_Backup_5.5\CAM-B0\) |
— |
| 1 | CAM-B1 C1 hors sexe, commutation C, reclassement des appelants de ChargenCameras[0] |
Content/BPs/Room.uasset, Content/BPs/PC.uasset, Content/BPs/GI.uasset |
Room.EventGraph ; PC.EventGraph ; GI.EventGraph |
| 2 | CAM-B2 C2 en poursuite lissée avec évitement des murs (Q4) | Content/BPs/Room.uasset |
Room.EventGraph |
| 3 | CAM-B3 C3 intérieur, extérieur, enfilade | Content/BPs/Room.uasset |
Room.EventGraph |
| 4 | CAM-B4 commandes de scène → C2, correctif CameraFocus |
Content/BPs/Room.uasset, Content/BPs/GI.uasset |
Room.EventGraph ; GI.CallFunction ; GI.EventGraph (Q12 décidée) |
| 5 | CAM-B5 chaînes mortes et suppression d'AutoCamera (Q14) |
Content/BPs/Room.uasset, Content/BPs/PC.uasset, Content/BPs/GI.uasset (Person non touchée, Q18) |
Room.EventGraph ; PC.EventGraph ; GI.EventGraph |
| 6 | CAM-B6 suppression du C++ FollowCamera (Q15), après la VAL de B2 (portage) |
Source/LifePlay/LPDirectControlSubsystem.h, .cpp |
— |
Ordre dans un sous-lot MCP : Room d'abord (les événements appelés par PC et GI doivent exister et compiler), puis PC, puis
GI ; compile_blueprint après chaque asset ; save_assets à la fin. Aucun fichier hors de cette liste : Birdview,
ContactMenu, MainMenu, Person (Q18 décidée), CentralLondon.umap, Config/ ne sont pas modifiés.
3. Repli
- Par sous-lot, éditeur fermé, proposé à l'utilisateur, jamais lancé sans accord (lp-lot) :
.\Tools\Snapshot.ps1 -Lot CAM-Bn-retour -Path <mêmes chemins>puis.\Tools\Restore.ps1 -Lot CAM-Bn -WhatIf, puis.\Tools\Restore.ps1 -Lot CAM-Bn. Après commit : ticketRESTOREau gardien (git revertdu commit du sous-lot). - Les sous-lots B1 → B5 s'enchaînent sur les mêmes assets binaires : le retour de Bn impose celui de Bn+1… d'abord (ordre inverse). B6 (C++) est indépendant. B0 ne laisse rien dans le dépôt.
- Repli fonctionnel sans retour : B1 seul laisse le jeu au comportement actuel pour C2/C3 (repli
ChargenCameras[0], § (a) ligne B1-4) ; on peut s'arrêter après n'importe quel sous-lot validé. - Un échec de compilation, un diagnostic ou un
Accessed Nonenouveau : arrêt du sous-lot, aucun contournement, rapport (sk-protocol § 2).
4. Risques R#, questions Q#
Risques
- R1 Capacités MCP non prouvées dans le projet. Prouvées par usage :
find_nodes,get_connected_subgraph,get_node_infos,create_node(Branche, IsValid, appelsClasse|<BP>|<Fonction>,Définir<Var>),connect_pins,break_pins,delete_node,set_pin_value,compile_blueprint,save_assets(Docs/29_Projet_Stabilisation_V2.md:153,:166-169,:262-264; lp-mcp § 3). Présentes dans le code Epic mais jamais utilisées ici :add_variable(TS blueprint.py:1154-1185),add_object_variable(:1224-1251),add_event(:324-366),add_function_graph(:287-320), création d'un nœudSpawnActorFromClasset réglage de sa brocheClass(create_nodegénérique:877-915+set_pin_value:1091),VariableGetd'une variable d'un autre BP (contextefind_node_types context_pins,:752),ActorTools.add_componentsur un Blueprint (SCS,TS actor.py:392-484), pose d'acteur dans la carte (TS scene.py:102,:445). S'ajoutent pour la poursuite de C2 (Q4) : nœudsSphereTraceSingle,BreakHitResult,VInterpTo,RInterpTo,GetWorldDeltaSeconds,K2_ClearTimerDelegate, et le rebranchement de la brocheOutputDelegated'un événement vers la brocheDelegated'une minuterie. Variante : sonde CAM-B0 (Q16 décidée) ; si une capacité échoue : arrêt et retour à l'utilisateur (Q20 décidée), aucune variante lancée d'office. B0a (établi par la sonde,CAM-B0-IMPL.md§ 2) :add_variable,add_object_variable,add_struct_variable,add_event(personnalisé et surcharge),SpawnActorFromClass+Class, rebranchementOutputDelegate→Delegate,SphereTraceByChannel(TraceTypeQuery2),BreakHitResult,VInterpTo,RInterpTo,GetWorldDeltaSeconds,FindLookAtRotation,GetComponentBounds,GetActorBounds,GetSocketLocation,GetScaledCapsuleHalfHeight, affectation dePostProcessSettings, getter et appel d'un autre BP : faits. Échec :K2_ClearTimerDelegate(« ClearTimerbyEvent does not exist ») → remplacé parRoomCamTimer+ClearandInvalidateTimerbyHandle(B1-1, B1-13), prouvé par la sonde.VariableGetd'un autre BP : le type_id rendu parfind_node_types(context_pins)(Variables|…) est refusé parcreate_node; passer parClasse|<Classe>|Obtenir<Var>(§ « Identifiants de nœuds »). Non prouvé :ActorTools.add_component, pose d'acteur dans la carte (écartés, (c)). Réserve : la compilation des nœuds purs non câblés de la sonde n'est pas prouvée. - R2 Opérateurs et comparateurs (
Less_DoubleDouble, opérations sur vecteurs,EqualEqual_ObjectObject) : lp-mcp § 3 signale que les comparateurs ne sortent pas defind_node_types. Ils existent dans le projet (ROOM:3431,BV:1320-1324,PC:1816) mais l'outil n'a pas de copie de nœud. Variante : recherche par nom de fonctionKismetMathLibrary(create_nodeaccepteUtilities|Operators|Add,TS blueprint.py:886-887) ; la commutation C1-C3 est conçue sans comparateur (deux booléens, § (a) B1). SiLess_DoubleDoublereste introuvable pour le test extérieur : retour à l'utilisateur (Q20 décidée). B0a (établi) : les opérateurs génériquesUtilitaires|Opérateurs|Inférieurà(<),Égalà(==),Ajouter,Soustraire,Multiplier(K2Node_PromotableOperator) se créent et prennent leur type à la 1re liaison (float<floaten double,Equal(Object),vector+vector,vector-vector;Multiplieraccepte vecteur × double). Relier l'entrée avantset_pin_value. R2 levé ; le repliWallT.bHiddenInGamen'est plus nécessaire. - R3
hyper_blueprint_debug_inspectpeut manquer après relance de l'éditeur (mémoire du projet « unreal-mcp reconnect »). Variante :compile_blueprintsans erreur +CompileAllBlueprintséditeur fermé + redumpLPDumpFunction. - R4 Ordre des appels de vue. La SPEC suppose que
HideRender(GI:772-775) pose sa vue de façon synchrone avant de rendre la main (chemin lu sans nœud latent : GI:13526-13531, 782-787, 30049-30063, 4452-4466, 3117-3125, 17489-17492, 24207-24209 ; maillonCallFunction_38555→CallFunction_2919→CallFunction_5578non lu). Si un nœud latent existait,HideRenderreprendrait la vue aprèsApplyRoomCamera. Contrôle :get_connected_subgraphsurK2Node_CustomEvent_471en début de B1. Variante : appelerApplyRoomCameraau bout de la chaîne deHideRender(aprèsK2Node_CallFunction_693, GI:24207-24209) sous gardeCurrentCamera= 0 etSpaceOn(modifieHideRender). - R5 Évitement des murs (transformé par Q4) : l'attache rigide est abandonnée ; C2 fait le balayage de
FollowCamera(LPDirectControlSubsystem.cpp:933-938). Reste : le balayage ne voit que ce qui bloque le canal Camera. MursWall1-4de Room : profilCustom,QueryAndPhysics, tableau de réponses vide (= réponses par défaut, bloquer : estimé) ; plafondWallT:NoCollision, Camera ignoré (RCOMP:17-19, copie 5.5) : sans effet, C2 reste sous le plafond ; mobilier (acteurs d'objets de la pièce) : collision non lue. Contrôle en jeu § (f) (MC dos à un mur, puis près d'un meuble). - R6 Rendu : un
CameraActorneuf a le FOV 90 (ENG Camera/CameraActor.cpp:25-26) mais aucun réglage de post-traitement ; les caméras du studio ont gamma 0,85, AO, DOF (CAM-AUDIT § 3b) ; le réglage DOF du menu n'écrit queChargenCameras[0](GI:21058-21106 cité par CAM-T2). Traité par B2-2 : copie du post-traitement deCameraSceneà la création deCamRoom(Q17 décidée) ; un changement ultérieur du réglage DOF du menu ne suit pasCamRoom(constat, hors demande). - R7 Concurrence avec STE : GI (EventGraph, CallFunction) et Person sont des assets binaires partagés ; aucun nœud
commun avec
GI.destroyDummyn'est identifié ici (non lu), mais un même fichier ne se fusionne pas : passages l'un après l'autre, MD5 de départ relus à l'entrée de chaque sous-lot, noms de nœuds revérifiés parfind_nodes(les nomsK2Node_*de la SPEC sont ceux des dumps V5 à HEAD4283c13). B5 retire un appel mort àRoom.refreshIdleDummies(GI:24030-24035), domaine voisin des pantins de STE : à signaler à l'arbitrage. - R8 Point du studio : la base codée en dur
(-3131543, -14967213, 75)n'apparaît qu'enROOM:3576dans les dumps V5 (Grep-313[0-9]{4}|-1496[0-9]{4}sur*V5.txt: 1 ligne) ; la position réelle de l'acteur Room n'est pas établie. Les formules § (e) n'en dépendent pas (bornes lues à l'exécution) ;AutoCamerala garde si elle est conservée (Q14). - R9
FirstPersonSMpartagé entre C1 et la POV de sexe : chacun le rattache à la tête avant usage (PC:3364-3396 ; B1).SetViewTarget(Person)prend le premier composant caméra actif (ENG Actor.cpp:3688-3700,bFindCameraComponentWhenViewTarget = true:320) ; Person n'a qu'un composant caméra (8 SCS relevés,CAM-T4-BUILD.md:143) etbAutoActivate = True(CAM-T4-BUILD.md:123) : établi pour la classe, non vérifié par instance de PNJ. - R10 Vie de Room : si l'acteur Room est recréé (rechargement),
CamRoomest perdue ; la création paresseuse sousIsValid(§ (a) B2) la recrée. Acteur orphelin possible : optionReceiveEndPlay→DestroyActor(CamRoom)(B2, à confirmer : Room n'a pas d'EndPlaydansROOM, Grep « evenement ' » : seulReceiveBeginPlay, ROOM:2). - R11 Commandes de scène sans contenu de test : aucun module livré n'utilise
cameraMove/cameraFocus/cameraLock(CAM-AUDIT § 2) ; B4 seraPASS-STATICsauf script de scène d'essai fourni (etMods/vidé avant tout build ou commit, lp-lot). - R12 Trous restants (réduits par les redumps CAM-T6 avec broches) : fermés : conditions du relais Birdview →
Room (BV:124-180, 511-555, 1538-1577), index de
ReturnFromChargen(CM:5116-5118, 5146-5173, 5321-5340), état mort de la chaîne de Person à HEAD (PERS:13468-13529) (Constats) ; restent : qui remplitGI.ChargenCameras(script de niveau, non dumpable),ProjectionModenon affiché, dumpFirstPersonvide. Aucun ne bloque la SPEC. - R13 Build : tout sous-lot invalide le candidat Shipping d'U8 : rien avant la porte T11 (décision Q7).
- R14
K2Node_InputAction_51(PC:563-566, sans liens) : supprimer un nœud d'entrée peut changer la consommation de la touche ; gardé tant que son action n'est pas identifiée (get_node_infos). - R15 Événements sans appelant vu (
CenterCameraToAction, ROOM:2102-2104) : des appelants hors des dumps lus (widgets) ne sont pas exclus ; gardé. - R16 Commandes manuelles : en pièce, flèches, molette et souris passent par Birdview vers
Room.LeftRight,RotateCamera,CircleCamera,DownUp,ScrollDownUp(BV:1538-1577 ; relais pris sur la sortie « faux » deCheckIfCameraMovable, BV:511-555, qui rend faux dès queGI.SpaceOnest vrai :Moveable= ET(nonActionBox.HasAnyChildren, nonScrollBoxOn, nonCharGenOn,TopRightvisible, nonSpaceOn), BV:124-180), qui déplacentSceneCamera(ROOM:394-910) : avec C1-C3, ces commandes n'auraient plus d'effet visible (perte du réglage manuel de la vue, y compris pendant le sexe) : accepté pour un premier passage (Q10 décidée), aucun nœud de déplacement modifié. - R17 Coût de la minuterie de pièce (nouveau, Q4) :
UpdateRoomCamtourne à ≈ 60 Hz (Time0,016,bMaxOncePerFramevrai) tant qu'une caméra de pièce est la vue ; en C2, unSphereTraceSingleet ≈ 30 nœuds BP par passage (estimé : bien moins de 0,1 ms par image ; non mesuré). Bornes : arrêt automatique dès que la vue n'est plus une caméra de pièce (B1-13) ; aucun coût sur la carte ni en CharGen. Mesure : V11. Repli si le seuil est dépassé :Time0,033 (30 Hz), sur décision. - R18 État masqué de C1 (nouveau, Q11) : C1 masque cheveux, soleil de scène et mur ; une sortie de C1 par un autre
chemin qu'
ApplyRoomCamera(contacts, CharGen, sortie de pièce :HideRender/ShowRendernon modifiés) les laisserait masqués. Parade : drapeauC1Hiddenet événementRestoreC1, appelés par les voies C2 / C3 et par la garde de la minuterie quand la vue n'est plus le MC (B1-12, B1-13). Pendant le sexe la garde n'agit pas : la POV du PC gère soleil et mur (PC:2343-2355, 1797-1809). - R19 Canal du balayage (nouveau) : en BP,
SphereTraceSingleprend unETraceTypeQuery(ENG KismetSystemLibrary.cpp:1965) ;TraceTypeQuery2= Camera est déduit de l'ordre des canaux marquésTraceQuery="1"(D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Engine\Classes\Engine\EngineTypes.h:1104-1105,:1276-1277;ENG Collision/CollisionProfile.cpp:303-377) et d'aucune redéfinition dansConfig/DefaultEngine.ini(GrepCollisionProfile|DefaultChannelResponses|TraceType: 0 ligne) : estimé. Contrôle :get_node_infosmontre « Camera » sur la brocheTraceChannelaprèsset_pin_value.
Questions : toutes décidées (CAM-CIBLE.md § 4c, « q4 lissage et évitement, le reste oui »)
| Q | Décision | Où dans la SPEC |
|---|---|---|
| Q1 | décidée : derrière le MC, 175 cm à l'horizontale | (e) C2 |
| Q2 | décidée : taille = Z(head) − Z(sol) + 10 cm |
(e) C2 |
| Q3 | décidée : C2 regarde la tête | (e) C2 |
| Q4 | décidée autrement que proposé : poursuite lissée avec évitement des murs (portage BP de FollowCamera), pas d'attache |
§ 1, (a) B1-13, B2, (e) C2, R5, R17 |
| Q5 | décidée : C3 intérieure fixe, rotation qui suit le MC | (a) B3-2 |
| Q6 | décidée : enfilade au bout opposé au MC, lacet dans l'axe, tangage vers le MC | (e) C3 extérieur |
| Q7 | décidée : C2 à l'entrée ; mode gardé pendant la session, non sauvegardé | (d) |
| Q8 | décidée : étape hors POV du sexe = caméra de pièce (C2 si le mode est C1) | (a) B1-2, B1-8 |
| Q9 | décidée : constructeur et édition de personnage gardent CameraScene |
(d) |
| Q10 | décidée : flèches, molette, souris sans effet en pièce (premier passage) | R16 |
| Q11 | décidée : C1 masque cheveux, soleil, mur ; pas de regard à la souris | (a) B1-3, B1-12, R18 |
| Q12 | décidée : scène démarrée hors pièce → C2 | (a) B4-6 |
| Q13 | décidée : cameraMove « détache » C2, c'est-à-dire suspend sa poursuite (drapeau C2Scripted) jusqu'au prochain changement de vue ; cameraLock / cameraUnlock inchangés |
(a) B2-6, B4-1 |
| Q14 | décidée : AutoCamera supprimée |
(a) B5-5 |
| Q15 | décidée : FollowCamera C++ supprimée, après le portage |
(a) B6 |
| Q16 | décidée : sonde B0 accordée | (a) B0 |
| Q17 | décidée : post-traitement de CameraScene copié sur CamRoom |
(a) B2-2 |
| Q18 | décidée : Person non touchée | § 2, (a) B5, V2 |
| Q19 | décidée : un seul CameraActor (CamRoom) pour C2 et C3 |
(a) B2-1 |
| Q20 | décidée : si le MCP échoue, retour à l'utilisateur (aucune variante lancée d'office) | R1, R2, (c) |
Texte d'origine des questions (CAM-T5), gardé pour la trace :
- Q1 C2, 1,75 m : distance horizontale de 175 cm à l'axe du MC, derrière lui (sens opposé à son regard) ? (proposé ; la distance totale vaut alors ≈ 185 cm pour 60 cm d'écart de hauteur, calcul).
- Q2 Taille du MC :
Z(os head) − Z(sol) + 10 cm(proposé) ; la capsule ne convient pas (88 cm de demi-hauteur fixe pour toute Person, PCOMP:1767-1769) ; autre choix : bornes du maillage. - Q3 C2 regarde la tête du MC (proposé, comme
AutoCamera, ROOM:3441-3447) ou le centre du corps ? - Q4 Suivi de C2 : attachée au MC, rigide, sans anti-collision (proposé, aucun Tick) ; ou poursuite lissée par
minuterie avec balayage anti-murs (portage BP de
FollowCamera, plus de nœuds) ? - Q5 C3 intérieure : position fixe au plafond, rotation qui suit le MC (proposé, d'après « 3 caméras suivent les mouvements du MC », CAM-CIBLE § 1) ou regard fixe vers le bas ?
- Q6 Enfilade : caméra au bout de l'axe long opposé au MC, lacet fixe dans l'axe, tangage qui suit le MC (proposé) ; ou regard entièrement vers le MC ?
- Q7 Caméra à l'entrée dans une pièce : C2 (proposé) ; mode gardé d'une pièce à l'autre pendant la session, non sauvegardé (proposé) ?
- Q8 Sexe : le cycle POV actuel finit sur
CameraScene(PC:1752-1760) que la décision Q6 réserve au CharGen ; l'étape « hors POV » devient la caméra de pièce du mode courant, C2 si le mode est C1 (proposé) ? - Q9 Constructeur de pièce (
EditBedroom, ROOM:5-36) et édition de personnage : garderCameraScene(proposé) ? - Q10 Flèches, molette, souris en pièce (R16) : déplacer la caméra active (C2/C3 ; 8 nœuds
SceneCameraà rebrancher dans ROOM:394-910) ou rien (proposé pour un premier passage) ? - Q11 C1 hors sexe : masquer les cheveux (proposé, comme PC:2290-2297), le soleil de scène et le mur comme en POV
(PC:2346-2350, 1800-1804) ? Regard à la souris (non prévu : la souris pilote Birdview quand
SexCameraIndex= 0, PC:1813-1830) ? - Q12 Scène scriptée démarrée hors pièce (
SpaceOnfaux →HideRender(0), GI:5866-5870, 23705-23709) : C2 ouCameraScene? - Q13
cameraMovedétache C2 du MC (la caméra reste où le script la pose jusqu'au prochain changement de vue, proposé) ;cameraLock/cameraUnlock(GICF:6730-6739, lus par Birdview BV4:480) : gardés tels quels (proposé) ? - Q14
Room.AutoCamera(ROOM:3406-3593, 3796-3872), rendue sans objet en pièce : supprimer ou garder ? - Q15
FollowCameraC++ : supprimer le code (proposé, B6) ou le garder mort ? - Q16 Sonde CAM-B0 sur un BP jetable (non commité, déplacé vers la sauvegarde après) : accord ?
- Q17 Post-traitement : copier celui de
CameraScene(gamma 0,85, AO, DOF) surCamRoomà sa création ? - Q18 Chaîne morte de Person (suivi par
SceneCamera, PERS4:2605, 2614 ; à HEAD avec broches : PERS:13468-13529 ; L6f PERS-L6f:34520-34580) : supprimer (touche Person, asset de STE-H4) ou laisser ? - Q19 Un seul
CameraActor(CamRoom) pour C2 et C3 (proposé : un seul est actif à la fois) ou deux ? - Q20 Variante si
SpawnActorou le test extérieur ne se créent pas par MCP : (a) acteur posé dansCentralLondon.umap(écrit la carte, non prouvé) ; (b) petite fonction C++BlueprintCallable(voie mixte) ; (c) arrêt.
5. Interdits
- Aucune écriture de
.umap, de Birdview, ContactMenu, MainMenu, Person (Q18 décidée),Config/. - Ne pas modifier
HideRender,ShowRender,ZoomCharGen,OpenContacts,ResetSceneCamera,ResetCameraAndPlayer,secondScreen, nidestroyDummy(STE) ; ne pas toucher aux chaînes CharGen et édition de personnage (GI:750-752, 803-807, 3863-3866, 4397-4400, 22424-22427, 23975-23985). - Aucune écriture par HyperAIStudio (lp-mcp règle 1) ; aucun appel MCP chevauché ; aucune écriture sans instantané ni sans trace (fiche, CHG) ; gel de la copie annoncé à toutes les sessions (lp-mcp règle 7).
- Aucun sous-lot avant la porte T11 d'U8 ; aucune écriture dans GI pendant une fenêtre de STE ; un sous-lot = un commit, jamais de regroupement ; aucune commande git qui écrit hors du gardien ; rien poussé.
- Aucun
IsValidhors des états « vide » normaux nommés ici (CamRoomavant sa création) ; cascades de branches, pas de AND / OR purs (lp-mcp règle 4). - Aucune suppression d'événement personnalisé dont un appelant hors dumps n'est pas exclu (R15) ; aucun retour arrière lancé sans accord.
6. Valeurs moteur lues dans le moteur installé (chemin:ligne)
| Valeur | Source |
|---|---|
ACameraActor crée son CameraComponent, FOV 90 |
ENG Camera/CameraActor.cpp:25-26 |
UCameraComponent : FieldOfView 90, FirstPersonFieldOfView 90 |
ENG Camera/CameraComponent.cpp:78-79 |
| FOV par défaut du gestionnaire de caméra : 90 | ENG PlayerCameraManager.cpp:46 |
bFindCameraComponentWhenViewTarget = true ; CalcCamera prend le premier composant caméra actif |
ENG Actor.cpp:320 ; :3688-3700 |
Capsule par défaut d'un ACharacter : rayon 34, demi-hauteur 88 (Person : 20 / 88, PCOMP:1767-1769) |
ENG Character.cpp:78 |
APlayerController::SetViewTargetWithBlend |
ENG PlayerController.cpp:2819 |
USceneComponent::K2_AttachToComponent ; AActor::K2_AttachToComponent |
ENG Components/SceneComponent.cpp:2276 ; ENG Actor.cpp:2711 |
UKismetSystemLibrary::GetComponentBounds |
ENG KismetSystemLibrary.cpp:2591 |
UKismetSystemLibrary::SphereTraceSingle(WorldContext, Start, End, Radius, ETraceTypeQuery TraceChannel, bTraceComplex, ActorsToIgnore, DrawDebugType, OutHit, bIgnoreSelf, …) |
ENG KismetSystemLibrary.cpp:1965 |
UKismetSystemLibrary::K2_SetTimerDelegate(Delegate, Time, bLooping, bMaxOncePerFrame, …) ; K2_ClearTimerDelegate(Delegate) ; K2_ClearAndInvalidateTimerHandle |
ENG KismetSystemLibrary.cpp:735 ; :796 ; :828 |
UKismetMathLibrary::VInterpTo(Current, Target, DeltaTime, InterpSpeed) ; RInterpTo(Current, Target, DeltaTime, InterpSpeed) |
D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Engine\Classes\Kismet\KismetMathLibrary.inl:1705 ; :862 |
UGameplayStatics::GetWorldDeltaSeconds |
ENG GameplayStatics.cpp:2558 |
Canaux de requête : ECC_Visibility, ECC_Camera marqués TraceQuery="1" ; énumérés TraceTypeQuery1, TraceTypeQuery2 ; table remplie dans l'ordre des canaux (R19) |
…\Runtime\Engine\Classes\Engine\EngineTypes.h:1104-1105, :1276-1277 ; ENG Collision/CollisionProfile.cpp:303-377 |
Référence du portage FollowCamera : visée pawn + 50 cm, recul 340 cm, sphère 12 cm sur ECC_Camera en ignorant le pawn, retrait 12 cm le long de la normale, VInterpTo vitesse 8, rotation directe vers la visée |
Source/LifePlay/LPDirectControlSubsystem.cpp:929-940 |
Outils MCP Epic : create 177, compile_blueprint 199, add_function_graph 287-320, add_event 324-366, add_function_param 394, get_node_infos 597, find_nodes 681, find_node_types 752, create_node 877-915, delete_node 919, connect_pins 1058, break_pins 1074, set_pin_value 1091, add_variable 1154-1185 (types bool, int, float, Vector, Rotator, Transform…), add_object_variable 1224-1251, remove_variable 1372 |
TS blueprint.py |
ActorTools.add_component sur Blueprint = SCS via SubobjectDataSubsystem, puis compilation ; remove_component |
TS actor.py:392-484 ; :488-538 |
SceneTools.add_to_scene_from_class ; save_actor |
TS scene.py:102 ; :445 |
Jeu : seuil extérieur 0,05 sur l'échelle Z relative de la racine de GI.Room, plafond WallT |
Source/LifePlay/LPOutdoorRoomSubsystem.cpp:13-16, :55 |
Jeu : touche C = SwitchCamera |
Config/DefaultInput.ini:118 (CAM-T3 § 3.4) |
7. Critères de VAL (commande → attendu)
| # | Commande | Attendu |
|---|---|---|
| V1 | git -C "D:\Game\LifePlay-master 5.8" status --short -- Content Source |
seuls les fichiers du sous-lot (§ 2) |
| V2 | Get-FileHash -Algorithm MD5 sur Content\BPs\Birdview.uasset, Content\UI\ContactMenu.uasset, Content\Scenes\CentralLondon.umap, Content\BPs\Person.uasset (Q18) |
AC4B231463C3FF61335A33B81300793C, 369088B422E1D4F43788D91068114A64, 6CE42F91DCAEE468E073A1CDE465C4B5, D1B4C63D47621B1191AD9352C80C99CD (Birdview, ContactMenu, carte : CAM-T4-BUILD.md:78-84 ; Person : après STE-H10, commit 5b58ffd, B0a) |
| V3 | MCP : get_node_infos sur chaque nœud (N) et chaque nœud existant relié du § (a) |
liaisons exactement celles du tableau (a) |
| V4 | MCP : compile_blueprint (Room, PC, GI) puis hyper_blueprint_debug_inspect (si présent, R3) |
0 erreur, 0 diagnostic |
| V5 | .\Tools\RunCommandlet.ps1 -Lot CAM-Bn-VAL -EtatDir "D:\Game\LifePlay-master 5.8\Docs\Migration\etat\CAM" -Commandlet LPDumpFunction -Args "-BP=Room -Fn=* -Pins -Exec" (idem -BP=PC -Fn=EventGraph, -BP=GI -Fn=EventGraph, -BP=GI -Fn=CallFunction) |
code 0 ; Grep `evenement personnalise '(ApplyRoomCamera |
| V6 | CompileAllBlueprints éditeur fermé (RunCommandlet.ps1, lp-commandlets) |
code 0, 0 erreur, 0 avertissement nouveau |
| V7 | build Development empaqueté (lp-build, Tools/Build.ps1) |
code 0, 0 avertissement nouveau (Build.ps1 -FromLog) |
| V8 | journal du build empaqueté après les essais : Select-String -Path <journal> -Pattern "Accessed None" filtré sur `ApplyRoomCamera |
CycleRoomCamera |
| V9 | B6 : Grep `FollowCamera | FollowView |
| V10 | essais en jeu de l'utilisateur (§ (f)) | chaque case PASS |
| V11 | build Development, console stat unit : temps du fil Game relevé 30 s en pièce en C2 (MC qui marche), puis 30 s sur la carte Birdview, même partie |
écart ≤ 0,5 ms (seuil proposé, R17) ; au-delà : repli Time 0,033 sur décision |
Verdict attendu : PASS si V1-V10 ; PASS-STATIC pour B4 sans script de scène d'essai (R11).
(a) Modifications par asset et par graphe, en sous-lots commitables
Dépendances : B0 → B1 → B2 → B3 ; B4 après B2 ; B5 après B4 (B1 réemploie la minuterie morte de Room, que B5 ne
supprime donc pas) ; B6 après la VAL de B2 (portage de FollowCamera validé, Q15) ; tout après la porte T11. Fenêtres GI pour l'arbitrage avec STE : B1, B4, B5.
CAM-B0 — sonde (Q16 décidée), aucun fichier suivi
BlueprintTools.create d'un Actor BP jetable /Game/Dev/CAM_Probe, puis dans l'ordre : add_variable (bool, Vector) ;
add_object_variable (CameraActor) ; add_event (« ProbeEvent ») et surcharge ReceiveEndPlay ; create_node
SpawnActorFromClass + set_pin_value Class = /Script/Engine.CameraActor ; minuterie par événement : nœud
K2_SetTimerDelegate relié par ProbeEvent.OutputDelegate → Delegate, set_pin_value Time = 0,016 et
bMaxOncePerFrame = vrai, puis K2_ClearTimerDelegate sur le même délégué ; SphereTraceSingle avec
set_pin_value TraceChannel = Camera (TraceTypeQuery2, R19) et BreakHitResult ; VInterpTo, RInterpTo,
GetWorldDeltaSeconds ; GetComponentBounds, GetActorBounds, FindLookAtRotation, GetSocketLocation,
GetScaledCapsuleHalfHeight, Less_DoubleDouble, EqualEqual_ObjectObject, addition, soustraction et multiplication de
vecteurs ; affectation d'un champ PostProcessSettings d'un CameraComponent ; dans un 2e BP jetable, VariableGet
d'une variable du premier par find_node_types(context_pins) et appel de ProbeEvent ; compile_blueprint. Résultat
attendu : chaque capacité de R1 et R2 = « fait » ou message d'erreur exact. Fichiers déplacés ensuite vers la sauvegarde
(jamais supprimés).
CAM-B1 — C1 hors sexe, commutation C, reclassement (Room, PC, GI)
| # | Asset / graphe | Nœud existant ciblé (preuve) | Modification | Variables / valeurs |
|---|---|---|---|---|
| B1-1 | Room | — | add_variable ×4 ; add_struct_variable ×1 (B0a) |
CamC1On, CamC3On (bool, défaut faux : mode C2, Q7) ; C1Hidden (bool, Q11, R18) ; (B1b) WallWasHidden retirée : la lecture de bHidden d'un autre acteur n'est pas créable par MCP, le mur reprend la règle de PC (B1-12) ; RoomCamTimer (/Script/Engine.TimerHandle, B0a : remplace K2_ClearTimerDelegate, non créable) |
| B1-2 | Room.EventGraph | — | (N) événement ApplyRoomCamera : Branche(CamC1On) vrai → Branche(GI.SexOn) vrai → voie C2, faux → voie C1 ; faux → Branche(CamC3On) vrai → voie C3, faux → voie C2 |
voie C2 pendant le sexe si mode C1 (Q8) |
| B1-3 | Room.EventGraph | copie des valeurs de PC:3378-3388, 3389-3396 + 3403-3408, 3364-3373, 1788-1796, 2290-2297 | (N) voie C1 : GI.PlayerCharacter.FirstPersonSM → K2_AttachToComponent(Mesh, 'head', KeepRelative ×3) → K2_SetRelativeTransform(MakeTransform((0,0,0), (90,90,0), (1,1,1))) → K2_AttachToComponent(Mesh, None, KeepWorld ×3) → SetViewTargetWithBlend(GI.PC, GI.PlayerCharacter, 0, VTBlend_Linear) → Branche(C1Hidden) faux → HairSM.SetVisibility(false) (B1b : sans WallWasHidden) → GI.PlayerCharacter.Mesh.HideBoneByName('neckLower', PBO_None) (B1c, comme PC:2319-2324 ; omis par CAM-T2 : sans lui la caméra voit l'intérieur de la tête) → SetActorHiddenInGame(SceneSun, vrai) → SetActorHiddenInGame(GI.Wall, vrai) → C1Hidden := vrai ; puis (et si C1Hidden était vrai) → minuterie K2Node_CallFunction_329 (B1-13) |
Q11 décidée ; nœuds de même type dans PC : cheveux PC:2290-2297, soleil PC:2343-2355, mur PC:1797-1809 |
| B1-3d | Room.EventGraph (B1d, remplace l'ordre de B1-3) | — | voie C1 : Branche(C1Hidden) faux → attache head KeepRelative → MakeTransform((0,0,0),(90,90,0)) → (N) FirstPersonSM.SetWorldLocation(0,5 × (Mesh.GetSocketLocation('lEye') + Mesh.GetSocketLocation('rEye'))) (lu avant HideBoneByName : un os masqué sort des os requis et ne bouge plus, ENG SkeletalMeshComponent.cpp:2300-2330) → attache KeepWorld → cheveux, HideBoneByName('neckLower'), soleil, mur → C1Hidden := vrai → (N) DelayUntilNextFrame → SetViewTargetWithBlend(GI.PC, GI.PlayerCharacter) → 329 ; Branche vrai → SetViewTargetWithBlend → 329 |
os lEye, rEye (enfants de head) et neckLower présents sur Michael et Bridget (MCP get_bone_children) |
| B1-4d | Room.EventGraph (B1d) | — | voies provisoires C2 et C3 : SetViewTargetWithBlend(ChargenCameras[0]) puis RestoreC1 (la tête ne revient qu'une fois la vue partie) |
— |
| B1-4 | Room.EventGraph | GI:3117-3125 (vue actuelle) | (N) voies C2 et C3 provisoires : (N) appel RestoreC1 (B1-12) → SetViewTargetWithBlend(GI.PC, GI.ChargenCameras[0], 0) (comportement actuel) ; remplacées en B2 / B3 |
— |
| B1-5 | Room.EventGraph | — | (N) événement CycleRoomCamera : Branche(CamC1On) vrai → CamC1On:=faux ; faux → Branche(CamC3On) vrai → CamC3On:=faux → CamC1On:=vrai ; faux → CamC3On:=vrai ; puis → appel ApplyRoomCamera |
C1 → C2 → C3 → C1, sans comparateur (R2) |
| B1-6 | Room.EventGraph (LoadRoom) |
K2Node_CallFunction_290 MoveAllToCenterRoom then -> K2Node_IfThenElse_63 (ROOM:3330-3332, 4068-4069) |
coupe 290.then → 63.execute ; relie 290.then → (N) Branche(GI.BuilderOn) vrai → 63 ; faux → (N) Branche(GI.SexOn) vrai → 63 ; faux → (N) Branche(GI.SpaceOn) vrai → (N) ApplyRoomCamera → 63 ; faux → 63 |
replace C2/C3 après un changement de pièce |
| B1-7 | PC.EventGraph (touche C) | K2Node_IfThenElse_23 (SexOn) else (vide) (PC:1723-1727), amont InputAction_12 → IfThenElse_65 (BuilderOn) → PlayClick (PC:1713-1716, 3876-3880, 4430-4432) |
relie 23.else → (N) Branche(GI.SpaceOn) vrai → (N) appel Room_C::CycleRoomCamera (cible GI.Room) |
hors pièce : rien (comme aujourd'hui) |
| B1-8 | PC.EventGraph (fin du cycle POV, ResetCamera) |
K2Node_CallFunction_353 SetViewTargetWithBlend(ChargenCameras[0]) then -> K2Node_CallFunction_194 (PC:1752-1760, 1805-1807 ; entrée par CallFunction_1800, PC:2351-2355, ResetCamera PC:3344-3346) |
coupe 353.then → 194.execute ; relie 353.then → (N) appel Room_C::ApplyRoomCamera (cible GI.Room) → 194.execute |
Q8 |
| B1-9 | GI.EventGraph (OpenSpace) |
K2Node_CallFunction_30 HideRender(0) then -> K2Node_CallFunction_645 (GI:23596-23600, 23624-23628 ; chaîne CustomEvent_66 → … → SpaceOn:=vrai → Exit Action Menu, GI:23571-23595) |
coupe 30.then → 645.execute ; relie 30.then → (N) VariableGet Room + (N) appel Room_C::ApplyRoomCamera → 645.execute |
entrée dans une pièce |
| B1-10 | GI.EventGraph (CloseContacts, NPCSelector vrai) |
K2Node_CallFunction_3168 HideRender(0) then -> K2Node_CallFunction_1039 (GI:17470-17474, 17481-17485, 18982-18986) |
idem B1-9 entre 3168 et 1039 | retour des contacts en pièce |
| B1-11 | GI.EventGraph (fin de sexe) | K2Node_CallFunction_2699 SetViewTargetWithBlend(ChargenCameras[0]) then -> K2Node_MacroInstance_3053 (GI:14498-14513, 6793-6796) |
idem B1-9 entre 2699 et 3053 | — |
| B1-12 | Room.EventGraph | — | (N) événement RestoreC1 : Branche(C1Hidden) vrai → HairSM.SetVisibility(true) → Mesh.UnHideBoneByName('neckLower') (B1c, comme PC:2328-2340) → SetActorHiddenInGame(SceneSun, faux) → SetActorHiddenInGame(GI.Wall, NOT(Room.bHidden)) (B1b, décision de l'utilisateur : règle de PC, PC:194 ← 152) → C1Hidden := faux ; faux → fin |
R18 |
| B1-13 | Room.EventGraph (minuterie de pièce) | K2Node_CallFunction_329 K2_SetTimerDelegate mort (execute (vide), Delegate ← K2Node_CustomEvent_32.OutputDelegate d'AutoCamera, Time 1,0, bLooping vrai, bMaxOncePerFrame faux, ROOM:3643-3653) |
(N) événement UpdateRoomCam ; coupe 32.OutputDelegate → 329.Delegate ; relie UpdateRoomCam.OutputDelegate → 329.Delegate ; set_pin_value Time = 0,016, bMaxOncePerFrame = vrai ; 329.execute ← voie C1 (B1), voie C2 (B2), voie C3 (B3) ; (B0a) 329.then (vide, ROOM:3645) → (N) Définir RoomCamTimer ← 329.ReturnValue (vide, ROOM:3653). Corps en B1 (garde) : Branche(GI.SexOn) vrai → fin ; faux → Branche(CamC1On) vrai → Branche(GetViewTarget(GI.PC) = GI.PlayerCharacter) vrai → fin ; faux → RestoreC1 → (N) ClearandInvalidateTimerbyHandle(RoomCamTimer) ; CamC1On faux → RestoreC1 → ClearandInvalidateTimerbyHandle(RoomCamTimer) (B0a : K2_ClearTimerDelegate non créable par MCP, CAM-B0-IMPL § 2 n° 9) |
≈ 60 Hz ; arrêt automatique dès que la vue n'est plus une caméra de pièce (R17, R18) ; réemploi d'une chaîne morte ; un nouvel appel de 329 avec le même délégué remplace la minuterie en cours et rend un nouveau handle ; ENG KismetSystemLibrary.cpp:735, :828 |
| Comportement attendu après B1 : identique à aujourd'hui en mode C2/C3 (repli B1-4), plus C1 hors sexe par la touche C. |
CAM-B2 — C2 en poursuite lissée avec évitement des murs (Room seul ; Q4 décidée)
Portage BP de FollowCamera (LPDirectControlSubsystem.cpp:929-940) avec les valeurs décidées : cible derrière le MC
(Q1-Q3) au lieu de la rotation de contrôle, même balayage (sphère 12 cm, canal Camera, retrait 12 cm), même vitesse 8.
Pas de Tick : Room n'a aucun événement Tick (ROOM : seul ReceiveBeginPlay, ROOM:2) ; la minuterie de B1-13
(≈ 60 Hz, bMaxOncePerFrame) se démarre et s'arrête explicitement.
| # | Graphe | Nœud existant ciblé (preuve) | Modification | Variables / valeurs |
|---|---|---|---|---|
| B2-1 | Room | — | add_object_variable ; add_variable ×2 |
CamRoom : CameraActor (Q19) ; C2Target : Vector ; C2Scripted : bool, défaut faux (Q13) |
| B2-2 | Room.EventGraph | modèle : K2Node_SpawnActorFromClass_1 déjà présent dans Room (ROOM:248, SelectUnderCursor ROOM:191-198) ; post-traitement de CameraScene (CAM-AUDIT § 3b) |
(N) événement EnsureCamRoom : IsValid(CamRoom) non valide → (N) SpawnActorFromClass(CameraActor, transform du MC, AlwaysSpawn) → CamRoom := → CamRoom.CameraComponent.PostProcessSettings := GI.ChargenCameras[0].CameraComponent.PostProcessSettings (Q17) ; valide → fin |
« vide » normal avant la 1re pièce (garde écrite au CHG) |
| B2-3 | Room.EventGraph | référence : LPDirectControlSubsystem.cpp:931-938 |
(N) événement ComputeC2Target : calcul § (e) de Desired (MC, capsule, os head, avant à plat) → (N) SphereTraceSingle(Start = tête, End = Desired, Radius = 12, TraceChannel = Camera (TraceTypeQuery2, R19), bTraceComplex = faux, ActorsToIgnore = [GI.PlayerCharacter, CamRoom], DrawDebugType = None, bIgnoreSelf = vrai) → Branche(ReturnValue) vrai → (N) BreakHitResult → C2Target := Location + Normal × 12 ; faux → C2Target := Desired |
175 cm ; +50 cm ; 12 cm ; ENG KismetSystemLibrary.cpp:1965 |
| B2-4 | Room.EventGraph | — | (N) événement PlaceC2 (initialisation, sans lissage) : EnsureCamRoom → ComputeC2Target → K2_SetActorLocationAndRotation(CamRoom, C2Target, FindLookAtRotation(C2Target, tête)) |
« lors de l'initialisation, à 1,75 m » |
| B2-5 | Room.EventGraph | voie C2 provisoire de B1-4 | coupe et suppr. le SetViewTargetWithBlend(ChargenCameras[0]) de la voie C2 ; relie RestoreC1 → (N) C2Scripted := faux → (N) PlaceC2 → (N) SetViewTargetWithBlend(GI.PC, CamRoom, 0) → K2Node_CallFunction_329 (minuterie, B1-13) |
le repli reste pour C3 jusqu'à B3 |
| B2-6 | Room.EventGraph (UpdateRoomCam, B1-13) |
entrée de UpdateRoomCam |
insère en tête : (N) Branche(GetViewTarget(GI.PC) = CamRoom) vrai → Branche(CamC3On) faux → Branche(C2Scripted) vrai → fin ; faux → ComputeC2Target → (N) Next = VInterpTo(CamRoom.K2_GetActorLocation, C2Target, GetWorldDeltaSeconds, 8) → (N) Rot = RInterpTo(CamRoom.K2_GetActorRotation, FindLookAtRotation(Next, tête), GetWorldDeltaSeconds, 8) → K2_SetActorLocationAndRotation(CamRoom, Next, Rot) ; CamC3On vrai → voie de B3 ; vue ≠ CamRoom → garde de B1-13, inchangée (elle arrête la minuterie par ClearandInvalidateTimerbyHandle(RoomCamTimer), B0a) |
vitesse 8 (.cpp:939) ; RInterpTo ajouté (le C++ tourne directement, .cpp:940) ; KismetMathLibrary.inl:1705, :862 ; ENG GameplayStatics.cpp:2558 |
| B2-7 | Room.EventGraph | aucun EndPlay dans Room (ROOM:2) |
(N) surcharge ReceiveEndPlay → IsValid(CamRoom) vrai → K2_DestroyActor(CamRoom) |
R10 |
Arrêt de la minuterie : par la garde de B1-13 dès que la vue n'est ni CamRoom ni le MC en C1 (hors sexe) ; pendant une |
||||
commande de scène (C2Scripted vrai) la minuterie tourne sans déplacer C2. |
CAM-B2b — confinement de C2 dans la pièce, repli, trajectoire protégée, pilotage (option 1) (amendement B2b)
Origine : essais de B2 (« caméra trop proche près d'un mur », « perte de la commande de la caméra ») ; exigence de
l'utilisateur « la caméra doit toujours être placée dans la pièce et jamais dehors » ; option 1 choisie par l'utilisateur.
Justification et faits : CAM-B2b-AMENDEMENT.md (§ 2). Room seul. Identifiants : § « Identifiants de nœuds (B0a) » et
CAM-B2-journal.txt (B2).
| # | Graphe | Nœud existant ciblé | Modification | Variables / valeurs |
|---|---|---|---|---|
| B2b-0 | Room | — | add_variable ×5 |
C2BoxMin, C2BoxMax : Vector ; C2Yaw : float (0) ; C2Height : float (0) ; C2Dist : float (0 ; décalage, distance = 175 + C2Dist, car add_variable ne règle pas le défaut) |
| B2b-1 | Room.EventGraph | — | (N) événement ComputeRoomBox : sol = StaticMeshComponent.GetWorldLocation, R = GetActorLocation(self), Ex = Max(Abs(Wall2.X − sol.X) − 30, 0), Ey = Max(Abs(Wall4.Y − sol.Y) − 30, 0) (formule de isPointInsideRoom, marge 30) ; ZTop = SelectFloat(1000000, WallT.Z − 25, StaticMeshComponent.RelativeScale3D.Z < 0,05) ; C2BoxMin := (R.X − Ex, R.Y − Ey, sol.Z + 50) ; C2BoxMax := (R.X + Ex, R.Y + Ey, ZTop) |
extérieur : Z sans borne haute ; boîte alignée sur les axes du monde (comme isPointInsideRoom) |
| B2b-2 | Room.EventGraph (ComputeC2Target, CE47) |
47.then → 459 ; 458 → 459.End et → 62 ; 459.Radius 12 ; PO6 (12,12,12) | 47.then → (N) appel ComputeRoomBox → 459 ; Desired borné : (N) VectorBoundedToBox(458, C2BoxMin, C2BoxMax) → 459.End et 62 ; 459.Radius = 20 ; PO6 = (20,20,20) ; 61 reçoit VectorBoundedToBox(PO7, Min, Max) |
rayon 20 ; retrait 20 |
| B2b-3 | Room.EventGraph (ComputeC2Target) |
sorties 61 et 62 | (N) après 61 et 62 : Branche(Distance(C2Target, tête) < 80) vrai → Desired2 = VectorBoundedToBox(tête + (0,0,100) + Bdir × 60, Min, Max) → (N) SphereTraceByChannel(tête → Desired2, 20, TraceTypeQuery2, ignorer [MC, CamRoom]) → C2Target := VectorBoundedToBox(SelectVector(Hit.Location + Hit.Normal × 20, Desired2, ReturnValue), Min, Max) ; faux → fin |
repli vers le haut et vers l'intérieur ; Bdir = direction arrière de B2b-5 normalisée |
| B2b-4 | Room.EventGraph (poursuite, UpdateRoomCam) |
467.then → 474 ; 468 → 474.NewLocation et 473.Start | 467.then → (N) SphereTraceByChannel(tête → 468, 20, TraceTypeQuery2, ignorer [MC, CamRoom]) → 474 ; (N) Safe = VectorBoundedToBox(SelectVector(Hit.Location + Hit.Normal × 20, 468, ReturnValue), Min, Max) → 474.NewLocation et 473.Start |
le lissage ne sort jamais de la boîte et ne passe pas derrière un obstacle Camera |
| B2b-5 | Room.EventGraph (ComputeC2Target) |
PO3 (−175 ×3) ; 457 → PO5 (+60) | Bdir = (N) RotateVectorAroundAxis(Normalize2D(Fwd) × −1, C2Yaw, (0,0,1)) ; PO3 := Bdir × (175 + C2Dist) (remplace −175) ; Z := tête.Z + 60 + C2Height |
option 1 ; à C2Yaw = 0, C2Height = 0, C2Dist = 0 : identique à B2 (correction E3 de F3) |
| B2b-6 | Room.EventGraph (5 événements de déplacement) | CircleCamera CE1 → IfThenElse_26 ; LeftRight CE4 → IfThenElse_9 ; RotateCamera CE19 → IfThenElse_25 ; DownUp CE8 → IfThenElse_8 ; ScrollDownUp CE55 → IfThenElse_10 |
pour chacun : coupe CE.then → branche existante ; (N) Branche(GetViewTarget(GI.PC) = CamRoom) vrai → réglage ; faux → branche existante (inchangée). Réglages : CircleCamera C2Yaw += D ; LeftRight C2Yaw += AxisValue × 2 ; RotateCamera C2Height := Clamp(C2Height + D × 3, −40, 150) ; DownUp C2Height := Clamp(C2Height + AxisValue × 3, −40, 150) ; ScrollDownUp C2Dist := Clamp(C2Dist − Values × 15, −75, 125) (distance 100 à 300 cm) |
signes et gains ajustables à l'essai ; hors C2, comportement inchangé |
Règle : toute position posée par CAM sur CamRoom (initialisation PlaceC2, poursuite, repli) passe par VectorBoundedToBox(…, C2BoxMin, C2BoxMax) ; PlaceC2 pose sans lissage avant la bascule de vue (466), donc la première image de C2 est dans la pièce. C3 provisoire (ChargenCameras[0]) n'est pas couverte (ancienne vue) : B3 la remplace et doit utiliser la même boîte (B3-1 : ComputeRoomBox au lieu de GetActorBounds). |
||||
V5 après B2b : SphereTraceSingle 3 ; Vector_BoundedToBox ≥ 4 ; RotateAngleAxis 1 ; Vector_Distance 1 ; événement ComputeRoomBox 1 ; SetViewTargetWithBlend 3 ; 5 événements de déplacement : then → nouvelle branche, else → branche d'origine. |
CAM-B2d — C2 sur la rotation de contrôle, comme le modèle Third Person d'Epic (amendement B2d)
Origine : demande directe de l'utilisateur (« le personnage est difficile à manier »), analyse CAM-B2d-TPS.md, GO de Big Boss (2026-10-13). Room seul ; LPDirectControlSubsystem et Person non touchés (la marche lit déjà GetControlRotation().Yaw, LPDirectControlSubsystem.cpp:887).
| # | Graphe | Nœud existant ciblé | Modification | Valeurs |
|---|---|---|---|---|
| B2d-1 | Room.EventGraph (ComputeC2Target) |
453 GetActorForwardVector(MC) → 454.A |
coupe 453 → 454 ; (N) GetControlRotation(GI.PC 262) → (N) GetForwardVector(rotateur) → 454.A ; suppr. 453 |
la direction arrière de C2 suit le lacet de contrôle (454 met à plat) |
| B2d-2 | Room.EventGraph (CircleCamera, F6a) |
96.then → 67 Définir C2Yaw ← PO28 (292 + DeltaSeconds) |
(N) BreakRotator(GetControlRotation) → Yaw → PO28.A (au lieu de 292) ; (N) MakeRotator(Roll 0, Pitch 0, Yaw ← PO28) → (N) SetControlRotation(GI.PC 262) ; 96.then → ce nœud ; suppr. 67 et 292 |
lacet += delta souris |
| B2d-3 | Room.EventGraph (LeftRight, F6a) |
97.then → 68 ← PO30 (293 + AxisValue × 2) | idem : Yaw du BreakRotator → PO30.A ; MakeRotator(0, 0, PO30) → (N) SetControlRotation(262) ; 97.then → ce nœud ; suppr. 68 et 293 |
lacet += flèche × 2 |
| B2d-4 | Room.EventGraph (PlaceC2) |
CE48.then → 461 EnsureCamRoom |
coupe ; CE48.then → (N) SetControlRotation(262, MakeRotator(0, 0, BreakRotator(GetActorRotation(MC 261)).Yaw)) → 461 |
à l'entrée en C2, la caméra part derrière le personnage |
C2Yaw (288 → 497.AngleDeg) n'est plus écrit et reste à 0 : 497 garde sa place (aucun effet). Un seul GetControlRotation et un seul BreakRotator (purs) peuvent servir B2d-1 à B2d-3. |
||||
V5 après B2d : GetControlRotation ≥ 1 ; SetControlRotation 3 ; GetActorForwardVector absent de ComputeC2Target ; variable C2Yaw écrite 0 fois ; critères de B2b inchangés. |
CAM-B3 — C3 intérieur, extérieur, enfilade (Room seul)
| # | Graphe | Nœud existant ciblé (preuve) | Modification | Variables / valeurs |
|---|---|---|---|---|
| B3-1 | Room.EventGraph | StaticMeshComponent relu en ROOM:4050-4052 ; WallT en ROOM:4655 ; seuil LPOutdoorRoomSubsystem.cpp:14, 55 |
(N) événement PlaceC3 : EnsureCamRoom → Branche(Less(StaticMeshComponent.RelativeScale3D.Z, 0.05)) faux → position intérieure ; vrai → position extérieure (§ (e)) → K2_SetActorLocationAndRotation (C2 n'étant plus attachée, aucun détachement) |
0,05 ; 380 cm ; marge 5 cm / 50 cm |
| B3-2 | Room.EventGraph (UpdateRoomCam) |
branche CamC3On vrai de B2-6 |
relie → (N) K2_SetActorRotation(CamRoom, Rc3) (Rc3 § (e) : intérieur, regard vers la tête ; extérieur, lacet dans l'axe, tangage vers la tête) |
Q5, Q6 décidées ; sans lissage (non demandé) |
| B3-3 | Room.EventGraph | voie C3 provisoire de B1-4 | coupe et suppr. le repli ; relie RestoreC1 → (N) PlaceC3 → (N) SetViewTargetWithBlend(GI.PC, CamRoom, 0) → K2Node_CallFunction_329 (minuterie de B1-13, déjà en place) |
Room : 3 SetViewTargetWithBlend |
CAM-B4 — commandes de scène → C2, correctif CameraFocus (Room, GI)
| # | Asset / graphe | Nœud existant ciblé (preuve) | Modification | Valeurs |
|---|---|---|---|---|
| B4-1 | Room.EventGraph | — | (N) événement UseC2 : CamC1On := faux → CamC3On := faux → ApplyRoomCamera ; (N) événement ScriptC2 : UseC2 → C2Scripted := vrai (la poursuite de C2 est suspendue jusqu'au prochain ApplyRoomCamera, qui remet C2Scripted à faux, B2-5) |
Q13 décidée ; variable de B2-1 |
| B4-2 | Room.EventGraph (CameraFocus) |
K2Node_CustomEvent_40 then -> K2Node_CallFunction_320 ; 320 = K2_SetActorRotation, self (vide) = acteur Room (ROOM:4396-4399, 4435-4441) |
coupe 40.then → 320.execute ; relie 40.then → (N) ScriptC2 → 320.execute ; relie (N) VariableGet CamRoom → 320.self |
corrige le pivot de Room |
| B4-3 | Room.EventGraph (CameraFocus, point de départ du regard) |
K2Node_CallFunction_406 K2_GetActorLocation self ← K2Node_VariableGet_133.SceneCamera (ROOM:4416-4418 ; 133 en ROOM:2115) |
coupe 133 → 406.self ; relie VariableGet CamRoom → 406.self |
— |
| B4-4 | Room.EventGraph (CameraFocusPoint) |
K2Node_CustomEvent_41 then -> K2Node_CallFunction_404 ; 404 = K2_SetActorRotation(SceneCamera) (ROOM:4404-4410, 4431-4434) |
coupe 41.then → 404.execute ; relie 41.then → (N) ScriptC2 → 404.execute ; coupe 133 → 404.self ; relie VariableGet CamRoom → 404.self |
— |
| B4-5 | GI.CallFunction (cameraMove) |
K2Node_SwitchString_22.cameraMove -> K2Node_CallFunction_242 K2_SetActorTransform (GICF:13, 209, 6185-6193) ; self ← K2Node_VariableGet_177.SceneCamera (GICF:6182-6184), cible K2Node_VariableGet_176.Room (GICF:6179-6181) |
coupe 22.cameraMove → 242.execute ; relie 22.cameraMove → (N) appel Room_C::ScriptC2 (self ← 176) → 242.execute ; coupe 177 → 242.self ; relie (N) VariableGet CamRoom (cible 176) → 242.self ; suppr. 177 (orphelin) |
UpdateDOF (GICF:6200-6203) inchangé |
| B4-6 | GI.EventGraph (Q12 décidée : C2) | K2Node_CallFunction_637 HideRender(0) then -> K2Node_CallFunction_6127 (GI:5866-5870 ; amont IfThenElse_117 SpaceOn faux, GI:23705-23709) |
coupe 637.then → 6127.execute ; relie 637.then → (N) VariableGet Room + (N) appel Room_C::UseC2 → 6127.execute (comme B1-9 ; C2 suit le MC tant qu'aucune commande de scène ne la fige) |
— |
| — | GI.CallFunction | cameraFocus → IfThenElse_10 → Room.CameraFocus / CameraFocusPoint (GICF:210, 6418-6422, 6292-6299, 6466-6473) ; cameraLock / cameraUnlock (GICF:218-219, 6730-6739) |
inchangés (le correctif est dans Room) | — |
CAM-B5 — chaînes mortes et AutoCamera (CAM-T2 § 3.4 ; tête morte = execute (vide) ; Q14 et Q18 décidées)
Règle : supprimer la tête morte, puis chaque nœud aval resté sans entrée d'exécution et chaque VariableGet resté sans
sortie, après relecture get_node_infos (aucune suppression d'un nœud encore relié à un nœud vivant).
| # | Asset / graphe | Nœud (preuve) | Modification |
|---|---|---|---|
| B5-1 | Room.EventGraph | K2Node_CustomEvent_33 'TestAutoCamera' vide (ROOM:3453-3455) et son appel K2Node_CallFunction_307 (execute -> VariableSet_5.then, then (vide), ROOM:3456-3459) |
suppr. 307 puis 33 |
| B5-2 | Room.EventGraph | K2Node_CallFunction_26 DownUp, execute (vide) (ROOM:561-565) |
suppr. |
| B5-3 | Room.EventGraph | K2Node_IfThenElse_1 (BuilderOn), execute (vide) (ROOM:389-393) |
suppr. (+ aval resté mort, à relire : CallFunction_23, ROOM:417-418) |
| B5-4 | Room.EventGraph | K2Node_CallFunction_333 DrawDebugBox, execute (vide) (ROOM:3674-3677) |
suppr. |
| B5-5 | Room.EventGraph (Q14 décidée : supprimer) | AutoCamera : K2Node_CustomEvent_32 et sa chaîne (ROOM:3406-3593, 3796-3872) ; appel K2Node_CallFunction_363 (execute -> IfThenElse_63.else, ROOM:3873-3876) ; MacroInstance_5.Exec ← 363.then et 63.then (ROOM:1135-1136) |
relie IfThenElse_63.else → MacroInstance_5.Exec ; suppr. 363 puis la chaîne ; la minuterie 329, réemployée par B1-13 (son lien de délégué vers CustomEvent_32 y est déjà coupé), n'est pas supprimée |
| B5-6 | PC.EventGraph | K2Node_CallFunction_1077 SetRelativeRotation(FirstPersonSM, 90,90,0), execute (vide) (PC:2055-2062) |
suppr. |
| B5-7 | PC.EventGraph | K2Node_CallFunction_204 AddWorldRotation(FirstPersonSM), execute (vide) (PC:1888-1895) |
suppr. |
| B5-8 | PC.EventGraph | K2Node_CallFunction_61 Delay 1, execute (vide) (PC:1696-1702) |
suppr. (aval CallFunction_173 à relire) |
| B5-9 | GI.EventGraph | K2Node_CallFunction_682 Room_C::refreshIdleDummies, execute (vide), then -> CallFunction_2699 (GI:24030-24035) |
suppr. (R7) |
| B5-10 | GI.EventGraph | K2Node_CallFunction_370 StreetMap_Static_C::UpdateWall, execute (vide) (GI:20939-20943) ; VariableGet_269 (GI:20936-20938) |
suppr. 370 ; 269 si orphelin ; VariableGet_270 à relire |
| B5-11 | GI.EventGraph | K2Node_CallFunction_107 SetActorHiddenInGame(Skylight), execute (vide) (GI:21049-21053) ; VariableGet_279 (GI:21046-21048) |
suppr. 107, puis 279 si orphelin |
| B5-12 | Person.EventGraph | chaîne morte établie à HEAD : K2Node_IfThenElse_70 execute (vide) → K2Node_IfThenElse_71 (GetViewTarget = Room.SceneCamera, CallFunction_296 / _481) → K2Node_CallFunction_478 K2_SetActorRotation(SceneCamera) (PERS:13468-13472, 13482-13484, 13503-13529) |
aucune : Person non touchée (Q18 décidée) ; chaîne laissée en place, inerte |
| gardés | Room, PC | CenterCameraToAction (ROOM:2102-2104, R15) ; K2Node_InputAction_51 (PC:563-566, R14) |
aucun |
CAM-B6 — suppression du C++ FollowCamera (Q15 décidée), après la VAL de B2 (portage en BP validé)
| # | Fichier | Lignes (preuve) | Modification |
|---|---|---|---|
| B6-1 | Source/LifePlay/LPDirectControlSubsystem.h |
:12 (« La camera suiveuse n'est pas branchee »), :19 include Camera/CameraActor.h, :43 déclaration, :63-67 membres FollowView, BirdView |
retirer :43, :63-67, :19 si plus utilisé ; :12 réécrite (« la caméra suiveuse est portée en Blueprint dans Room, lot CAM ») |
| B6-2 | Source/LifePlay/LPDirectControlSubsystem.cpp |
:573-577 destruction de FollowView ; :897-941 définition ; includes :15-16 |
retirer ; includes retirés seulement si Grep `CameraActor |
Vérification : V9 ; aucun appelant à retirer (FollowCamera : 2 lignes, déclaration et définition, CAM-AUDIT § 5). |
(b) Fonctions et graphes touchés, par asset (arbitrage avec STE)
| Asset | Graphe | Sous-lot | Nœuds existants touchés (liens coupés ou relus) | Nœuds (N) |
|---|---|---|---|---|
| GI | EventGraph, chaîne OpenSpace (K2Node_CustomEvent_66) |
B1 | K2Node_CallFunction_30 → K2Node_CallFunction_645 (GI:23596-23600, 23624-23628) |
VariableGet Room, appel Room_C::ApplyRoomCamera |
| GI | EventGraph, chaîne CloseContacts (K2Node_CustomEvent_734) |
B1 | K2Node_CallFunction_3168 → K2Node_CallFunction_1039 (GI:17470-17474, 18982-18986) |
idem |
| GI | EventGraph, fin de sexe | B1 | K2Node_CallFunction_2699 → K2Node_MacroInstance_3053 (GI:14505-14513, 6793-6796) |
idem |
| GI | CallFunction (fonction), SwitchString_22.cameraMove |
B4 | K2Node_CallFunction_242, K2Node_VariableGet_177 (suppr.), K2Node_VariableGet_176 (GICF:6179-6193) |
appel Room_C::ScriptC2, VariableGet CamRoom |
| GI | EventGraph, démarrage de scène hors pièce | B4 (Q12 décidée) | K2Node_CallFunction_637 → K2Node_CallFunction_6127 (GI:5866-5870) |
VariableGet Room, appel Room_C::UseC2 (seul changement de GI dû à l'amendement : le nom de l'événement appelé ; la liste des points de GI est inchangée) |
| GI | EventGraph, nœuds morts | B5 | suppr. K2Node_CallFunction_682 (GI:24030-24035), K2Node_CallFunction_370 (+ VariableGet_269) (GI:20936-20943), K2Node_CallFunction_107 (+ VariableGet_279) (GI:21046-21053) |
— |
| GI | non touchés | — | HideRender (CustomEvent_471), ShowRender (519), ZoomCharGen, OpenContacts (531), édition de personnage, ResetCameraAndPlayer, secondScreen, Sex, PanToBuilding, destroyDummy, réglage DOF, variables de GI (aucune variable ajoutée à GI) |
— |
| Room | EventGraph | B1-B5 | K2Node_CallFunction_290, K2Node_IfThenElse_63 (LoadRoom) ; K2Node_CallFunction_329 (minuterie) ; K2Node_CustomEvent_40, _41, K2Node_CallFunction_320, _404, _406, K2Node_VariableGet_133 ; morts B5-1 à B5-5 |
événements ApplyRoomCamera, CycleRoomCamera, RestoreC1, UpdateRoomCam (B1) ; EnsureCamRoom, ComputeC2Target, PlaceC2, surcharge ReceiveEndPlay (B2) ; PlaceC3 (B3) ; UseC2, ScriptC2 (B4) ; variables CamC1On, CamC3On, C1Hidden, RoomCamTimer (B1 ; WallWasHidden retirée, B1b), CamRoom, C2Target, C2Scripted (B2) ; minuterie K2Node_CallFunction_329 réemployée dès B1 |
| PC | EventGraph | B1, B5 | K2Node_IfThenElse_23.else ; K2Node_CallFunction_353 → _194 ; morts _1077, _204, _61 |
Branche(SpaceOn), 2 appels Room |
| Person | — | aucun (Q18 décidée) | chaîne morte établie à HEAD (PERS:13468-13529), laissée en place | — |
| Birdview | — | aucun | — | — |
| ContactMenu, MainMenu | — | aucun | — | — |
CentralLondon.umap |
— | aucun | — | — |
(c) Choix technique de chaque caméra, et preuve MCP
| Caméra | Choix proposé | Ce que le MCP doit faire | Preuve | Variante sûre si non prouvé |
|---|---|---|---|---|
| C1 | composant existant FirstPersonSM de Person (aucun changement de Person) ; attache et vue posées par Room |
create_node d'appels (K2_AttachToComponent, K2_SetRelativeTransform, SetViewTargetWithBlend, SetVisibility), connect_pins, set_pin_value |
établi : mêmes familles d'outils utilisées en STB (29_Projet_Stabilisation_V2.md:262-264) ; nœuds de même type déjà dans PC (PC:3364-3396, 1788-1796) |
— |
| C2 / C3 | un CameraActor créé à l'exécution par Room (SpawnActorFromClass paresseux sous IsValid), tenu par la variable CamRoom, en poursuite du MC (C2, non attaché, Q4) ou posé au plafond (C3) ; aucune .umap écrite |
add_object_variable, add_variable, add_event, create_node SpawnActorFromClass + broche Class |
établi par B0a (CAM-B0-IMPL.md § 2 n° 2-7 ; CamRoom.CameraComponent par Classe|Acteurdecaméra|ObtenirCameraComponent, n° 22) ; avant B0 : non prouvé dans le projet (R1) ; code présent (TS blueprint.py:1224-1251, :1154-1185, :324-366, :877-915, :1091) ; un SpawnActorFromClass compile déjà dans Room (ROOM:248) |
CAM-B0 ; si échec : retour à l'utilisateur (Q20 décidée) |
| Poursuite de C2 (Q4) | minuterie de Room (nœud mort K2Node_CallFunction_329 réemployé, Time 0,016, bMaxOncePerFrame) + SphereTraceSingle sur le canal Camera + VInterpTo / RInterpTo vitesse 8 ; pas de Tick (Room n'en a pas, ROOM:2) |
connect_pins d'une broche OutputDelegate vers Delegate, set_pin_value (Time, bMaxOncePerFrame, TraceChannel), create_node des fonctions moteur |
fonctions établies dans le moteur (ENG KismetSystemLibrary.cpp:735, :796, :1965 ; KismetMathLibrary.inl:862, :1705 ; ENG GameplayStatics.cpp:2558) ; un K2_SetTimerDelegate relié au délégué d'un événement existe déjà dans Room (ROOM:3643-3653) ; création et rebranchement par MCP établis par B0a (n° 8-14), arrêt par handle au lieu de K2_ClearTimerDelegate (n° 9, 9b) |
CAM-B0 ; si échec : retour à l'utilisateur (Q20 décidée) |
| (écartée) composant ajouté à Person | ActorTools.add_component(Person, CameraComponent) |
code présent (TS actor.py:392-484, SCS par SubobjectDataSubsystem), non prouvé |
une instance par Person (même défaut que FirstPersonSM, CAM-AUDIT § 4) ; ne convient pas à C3 ; Person est l'asset de STE-H4 |
|
| (écartée) acteurs posés dans la carte | SceneTools.add_to_scene_from_class + enregistrement |
code présent (TS scene.py:102, :445), non prouvé |
écrit CentralLondon.umap (interdit § 5) ; références à poser par le script de niveau (non dumpable, R12) |
|
| Commutation | deux booléens CamC1On, CamC3On (C2 = les deux faux) |
Branche, Définir<Var> |
établi (lp-mcp § 3) | — |
| Test extérieur | Less_DoubleDouble(échelle Z, 0,05) |
création d'un comparateur | établi par B0a (Inférieurà(<) → float<float, n° 18) ; avant B0 : non prouvé (R2) |
lecture de WallT.bHiddenInGame (masqué par le C++ en extérieur, LPOutdoorRoomSubsystem.cpp:55-60, mais avec un décalage d'une image possible), seulement sur accord ; sinon retour à l'utilisateur (Q20 décidée) |
(d) Règle de priorité de vue et caméra par défaut
Le moteur garde le dernier SetViewTargetWithBlend (ENG PlayerController.cpp:2819) ; la SPEC place l'appel de la
caméra de pièce après les appels existants, dans les seuls contextes de pièce.
| Contexte (déclencheur) | Vue résultante | Mécanisme | Qui a le dernier mot |
|---|---|---|---|
Chargement, sortie de pièce, fin du constructeur (BeginAutoLoad, ShowRender) |
Birdview | inchangé (PC:521-529, GI:3144-3152) | Birdview hors pièce |
Entrée en pièce (OpenSpace → HideRender(0)) |
caméra de pièce du mode courant (C2 par défaut, Q7) | B1-9 | ApplyRoomCamera après HideRender |
LoadRoom en pièce, hors constructeur et hors sexe |
idem (replacée) | B1-6 | idem |
| Touche C hors sexe, en pièce | C1 → C2 → C3 | B1-7 | CycleRoomCamera |
| Touche C pendant le sexe | cycle POV actuel ; étape « hors POV » = caméra de pièce (C2 si mode C1) | PC inchangé + B1-8 (Q8) | PC |
ResetCamera (PC) |
caméra de pièce | B1-8 (même nœud 353) | — |
Fin de sexe (ChargenCameras[0], GI:14505) |
caméra de pièce | B1-11 | ApplyRoomCamera |
Contacts (HideRender(1), GI:6230-6234) |
ChargenCameras[1] |
inchangé | menus |
Fermeture des contacts avec NPCSelector |
caméra de pièce | B1-10 | ApplyRoomCamera |
CharGen, édition de personnage, ZoomCharGen, ContactMenu ReturnFromChargen → SelectCamera (CM:5116-5118, 5334-5340) |
ChargenCameras[0..2] ; ContactMenu : index 2 pour une créature, sinon 1 (SelectInt(2, 1, GI.isCreature(DummyPerson)), CM:5321-5333, 5146-5173) |
inchangé | menus |
Constructeur (EditBedroom → HideRender(0), ROOM:5-36) |
CameraScene |
inchangé (Q9) ; B1-6 ne s'applique pas sous BuilderOn |
constructeur |
cameraMove, cameraFocus, cameraFocusPoint |
C2 (forcée, poursuite suspendue, Q13) | B4 (ScriptC2) |
commande de scène |
| Scène démarrée hors pièce (GI:5866) | C2 (Q12 décidée) | B4-6 (UseC2) |
— |
ResetSceneCamera |
CameraScene replacée, vue inchangée |
inchangé (ROOM:1250-1264) | — |
| Toute vue posée hors des caméras de pièce (menus, carte, CharGen) pendant que la minuterie tourne | celle du menu | garde de UpdateRoomCam : RestoreC1 puis ClearandInvalidateTimerbyHandle(RoomCamTimer) (hors sexe) (B1-13, B0a) |
le menu ; la minuterie s'efface |
| Caméra par défaut à l'entrée : C2 (deux booléens faux), mode gardé tant que l'acteur Room vit, non sauvegardé (Q7 décidée). |
(e) Formules
C2 (Q1-Q4 décidées, CAM-CIBLE.md § 4c : 175 cm derrière, hauteur = taille + 50 cm, regard vers la tête, poursuite
lissée avec évitement des murs) :
Pmc=GI.PlayerCharacter.K2_GetActorLocation()(centre de capsule) ;HH=CapsuleComponent.GetScaledCapsuleHalfHeight()(capsule de Person : 88, PCOMP:1767-1768) ;Zsol=Pmc.Z − HH.Ztete=Mesh.GetSocketLocation('head').Z(socket déjà lu par Room, ROOM:3441-3447) ; tailleT=Ztete − Zsol + 10(Q2 : +10 cm = os de la tête au sommet du crâne, estimé).F=GetActorForwardVector()mis à plat (Z= 0, normalisé ; le MC s'oriente dans le sens de sa marche,LPDirectControlSubsystem.cpp:868-871cité par CAM-T3).Desired=(Pmc.X − 175·F.X, Pmc.Y − 175·F.Y, Zsol + T + 50)(Q1, Q2) ;tête=Mesh.GetSocketLocation('head').- Évitement (Q4, portage de
LPDirectControlSubsystem.cpp:933-938) :SphereTraceSingle(tête → Desired, rayon 12, canal Camera, en ignorant le MC et CamRoom); impact →C2Target=Hit.Location + Hit.Normal·12; sinonC2Target=Desired. Le balayage part de la tête (le C++ partait du pawn + 50 cm,.cpp:931). - Initialisation (
PlaceC2) :CamRoomposée directement enC2Target, rotationFindLookAtRotation(C2Target, tête)(Q3). - Poursuite, à chaque passage de la minuterie (Δt =
GetWorldDeltaSeconds, ≈ 1/60 s) :Next=VInterpTo(Pcam, C2Target, Δt, 8);Rot=RInterpTo(Rcam, FindLookAtRotation(Next, tête), Δt, 8);K2_SetActorLocationAndRotation(Next, Rot). Le C++ applique la rotation directement (.cpp:940) ;RInterpToest ajouté par l'amendement (vitesse 8, ajustable à l'essai). - Loi de lissage : chaque passage parcourt la fraction
min(Δt·8, 1)de l'écart (loi lue pour l'interpolation d'un scalaire,D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Core\Public\Math\UnrealMathUtility.h:1530; même loi supposée pourVInterpTo, définie ailleurs : estimé) ; à 60 Hz : 13,3 % de l'écart par image, 95 % rattrapé en ≈ 21 images, ≈ 0,35 s (calcul). - Écarts au C++ : recul 175 cm (C++ : 340), cible derrière l'avant du MC mis à plat (C++ : rotation de contrôle, tangage
borné −55 / −12°,
.cpp:929-930), hauteur sol + T + 50 (C++ : déduite du tangage), visée sur la tête (C++ : pawn + 50 cm). - Exemple (calcul) : MC de 170 cm, os de la tête à 160 cm → caméra à 220 cm du sol, 175 cm derrière, tangage
−atan(60/175)≈ −19° (sans impact).
C3 intérieur (échelle Z de StaticMeshComponent ≥ 0,05) :
(O, E)=GetActorBounds(Room, false);(Ot, Et)=GetComponentBounds(WallT)(ENG KismetSystemLibrary.cpp:2591).Pc3=(O.X, O.Y, Ot.Z − Et.Z − 5): centre de la pièce, 5 cm sous la sous-face du plafond (« collée au plafond »).Rc3=FindLookAtRotation(Pc3, tête du MC), recalculée toutes les 0,05 s tant que la vue est C3 (Q5).- Ordres de grandeur (indicatifs, RCOMP:24, :30, copie 5.5) :
WallTà Z relatif 2040, échelle relative (8, 8, 0,2) (attribution de cette échelle àWallTestimée) ; plafond 408-816 cm au-dessus de la racine pour une échelle Z de 0,2-0,4 (CAM-T3 § 3.5, calcul).
C3 extérieur = caméra de rue en enfilade (échelle Z < 0,05, comme LPOutdoorRoomSubsystem.cpp:55) :
(O, E)=GetActorBounds(Room, false)(en extérieur, murs et plafond sont écrasés à ≈ 1 % de leur hauteur : les bornes sont celles du sol, estimé) ; axeA= X siE.X ≥ E.Y, sinon Y.s= −signe(Pmc.A − O.A) (bout opposé au MC ; −1 si égal) ;Pc3=O + s·(E.A − 50)·Â,Z=Zsol + 380.Rc3: lacet fixe le long de l'axe, versO(enfilade) ; tangage vers la tête du MC, recalculé par la minuterie (Q6).- Proposition alternative argumentée (Q6) : si un lieu extérieur est presque carré (
E.X ≈ E.Y), l'axe est arbitraire ; on peut alors viser le MC entièrement.
(f) Instantanés, MD5, compilation, build, essais
Pour chaque sous-lot MCP, dans cet ordre (lp-lot, lp-mcp) : entrée git status --short -- <chemins> vide pour le
sous-lot ; ticket TAG CAM-avant au gardien avant B1 ; gel annoncé ; instantané ; MD5 de départ ; éditeur headless
(-ModelContextProtocolStartServer, attente Wait-HyperAIStudioMCP.ps1 -TimeoutSeconds 540) ; AssetTools.load_asset ;
find_nodes de chaque nœud existant du § (a) (noms revérifiés, R7) ; modifications ; V3 ; V4 ; save_assets ;
Stop-Process de l'éditeur ; Tools/UeState.ps1 = 0 ; V5, V6 ; build Development (V7) ; essais en jeu ; DOC (CHG) ;
ticket COMMIT.
| Sous-lot | Instantané | MD5 de départ attendus |
|---|---|---|
| B1 | .\Tools\Snapshot.ps1 -Lot CAM-B1 -Path Content\BPs\Room.uasset, Content\BPs\PC.uasset, Content\BPs\GI.uasset |
Room E8F58B2A4A79DA0D62D8FACC18411CE8, PC 09F54974D093893EA43AE10056B37220, GI 16394D438788E986AC23FAEB427402B8 (CAM-T4-BUILD.md:79-81) ; si STE a commité GI entre-temps, MD5 du commit de STE (R7) |
| B2, B3 | -Lot CAM-B2 (puis CAM-B3) -Path Content\BPs\Room.uasset |
MD5 de Room après le commit du sous-lot précédent (relevé dans son IMPL) |
| B4 | -Lot CAM-B4 -Path Content\BPs\Room.uasset, Content\BPs\GI.uasset |
idem |
| B5 | -Lot CAM-B5 -Path Content\BPs\Room.uasset, Content\BPs\PC.uasset, Content\BPs\GI.uasset (Person non touchée, Q18 ; son MD5 D1B4C63D47621B1191AD9352C80C99CD (après STE-H10, B0a) est contrôlé par V2) |
idem |
| B6 | -Lot CAM-B6 -Path Source\LifePlay\LPDirectControlSubsystem.h, Source\LifePlay\LPDirectControlSubsystem.cpp |
git HEAD |
(Paramètres de Snapshot.ps1 : -Lot, -Path tableau, -Recurse, sauvegarde D:\Game\LifePlay_Backup_5.5, Tools/Snapshot.ps1:17-22.) |
Essais en jeu de l'utilisateur (build Development ; cases reprises par la VAL) :
- Nouvelle partie (liste des villes) et Continuer ; Birdview au chargement, inchangée (flèches, molette, survol).
- Pièce intérieure : entrée en C2 (B2+) ; C → C1 (vue de la tête ; cheveux, soleil et mur masqués), C → C2 (cheveux, soleil et mur rendus), C → C3 (plafond, B3+), C → C1 ; marche du MC : C2 suit en douceur (rattrapage ≈ 0,35 s, sans à-coup), C3 le regarde.
- Évitement (Q4) : MC dos à un mur, puis près d'un meuble : C2 se rapproche du MC au lieu de passer derrière le mur ; aucun mur entre C2 et le MC.
- C1, puis contacts (ou CharGen), puis retour en pièce : cheveux, soleil et mur rendus (R18).
- Performance : V11.
- Lieu extérieur (un des 7) : C3 à ≈ 3,80 m, dans l'axe long, au bout opposé au MC.
- Sortie de pièce → Birdview ; réentrée → mode gardé (Q7).
- Contacts ouverts puis fermés (avec et sans
NPCSelector) ; CharGen et zoom (ZoomCharGen0 → 1 → 2) : caméras du studio inchangées ; retour en pièce sur la caméra de pièce. - Constructeur de pièce :
CameraScene(Q9) ; sortie → Birdview. - Sexe : C parcourt les POV du MC et des partenaires puis l'étape hors POV (Q8) ;
ResetCamera; fin de sexe → caméra de pièce. - Scène scriptée avec
cameraMove/cameraFocus/cameraFocusPoint(si un script d'essai existe, R11) : C2 ;cameraFocusne fait plus pivoter la pièce ; C2 reste où le script la pose et ne reprend sa poursuite qu'au changement de vue suivant (Q13) ; scène démarrée hors pièce : C2 qui suit le MC (Q12). - Sauvegarde puis rechargement : pas d'erreur,
CamRoomrecréée à la première pièce. - Journal : V8 = 0 ligne.
(g) Durée de copie UE par sous-lot (pour la BUILD-DEMANDE à Big Boss)
Bases mesurées : démarrage de l'éditeur ≈ 1 min et correctif STB de ~30 appels MCP ≈ 5 min
(29_Projet_Stabilisation_V2.md:264) ; commandlet 41-56 s (CAM-T4-BUILD.md:29-39) ; compilation C++ 55-62 s
(U8-T5b-BUILD.md:22, U8-T2r-BUILD.md:10) ; cuisson 2 min 17 s à 2 min 47 s (U8-T3r-BUILD.md:40,
U8-T3-BUILD.md:51) ; mise en scène et archive 49 s (U8-T4r-BUILD.md:63). Estimé : ≈ 1 min d'appels MCP par nœud
créé et relié, relecture comprise.
| Sous-lot | Nœuds (N) estimés | MCP | Commandlets (V5, V6) | Build Development | Total copie UE (estimé) |
|---|---|---|---|---|---|
| B0 | ≈ 25 (jetables : minuterie, balayage, interpolations en plus) | 30-40 min | — | — | ≈ 40 min |
| B1 | ≈ 70 (Room ≈ 60 dont RestoreC1 et la garde de UpdateRoomCam, PC 4, GI 6) |
70-85 min | ≈ 5 min | ≈ 5 min | ≈ 1 h 35 |
| B2 | ≈ 70 (ComputeC2Target ≈ 30, poursuite ≈ 15, EnsureCamRoom et post-traitement ≈ 10, PlaceC2, voie, EndPlay ≈ 15) |
70-85 min | ≈ 3 min | ≈ 5 min | ≈ 1 h 30 |
| B3 | ≈ 45 | 45-55 min | ≈ 3 min | ≈ 5 min | ≈ 1 h |
| B4 | ≈ 18 (Room 12, GI 6) | 20-25 min | ≈ 5 min | ≈ 5 min | ≈ 35 min |
| B5 | 0 créé, ≈ 65 supprimés (chaîne AutoCamera ≈ 50, Q14) |
30-40 min | ≈ 5 min | ≈ 5 min | ≈ 50 min |
| B6 | — (C++) | — | — | ≈ 6 min (compilation + paquet) | ≈ 10 min |
| Total ≈ 6 h 20 de copie UE (estimé ; ≈ 4 h 45 avant l'amendement), hors essais en jeu de l'utilisateur et mesure V11 ; | |||||
| GI est ouvert pendant B1, B4 et B5 seulement (inchangé). |
Identifiants de nœuds (B0a)
Relevés par la sonde B0 dans l'éditeur 5.8 en français (CAM-B0-IMPL.md § 2). Les noms de catégorie sont localisés : relire
par find_node_types (filtre court, sans context_pins) au début de chaque sous-lot ; un identifiant rendu avec
context_pins peut être refusé par create_node (« does not exist », même avec declaring_class).
| Besoin dans la SPEC | type_id à passer à create_node |
Remarque |
|---|---|---|
membre d'un autre BP (GI.SexOn, GI.Room, GI.PC, GI.Wall, GI.PlayerCharacter, GI.BuilderOn, GI.SpaceOn) |
Classe|<Classe affichée>|Obtenir<Var> / Définir<Var> |
prouvé sur Classe|CAMProbe|ObtenirProbeBool ; nom affiché sans _ ni _C ; broche self (0) ← référence |
appel d'un événement ou d'une fonction d'un autre BP (Room_C::ApplyRoomCamera, CycleRoomCamera, ScriptC2, UseC2) |
Classe|<Classe affichée>|<Fonction> |
prouvé sur Classe|CAMProbe|ProbeEvent (self 1) ; R1 citait déjà Classe|<BP>|<Fonction> en STB |
CamRoom.CameraComponent (B2-2) |
Classe|Acteurdecaméra|ObtenirCameraComponent |
repli : Acteur|GetComponentbyClass + ComponentClass = /Script/Engine.CameraComponent (sortie typée) |
PostProcessSettings (B2-2) |
Classe|CameraComponent|ObtenirPostProcessSettings / DéfinirPostProcessSettings |
K2Node_VariableSet : exécution 0, valeur 1, self 2 |
SpawnActorFromClass (B2-2) |
Jeu|Faireapparaîtreunacteuràpartird'uneclasse |
Class (1) = /Script/Engine.CameraActor ; ReturnValue (1) typé caméra |
| minuterie (B1-13) | nœud existant K2Node_CallFunction_329 ; neuf : Utilitaires|Temps|SetTimerbyEvent |
Delegate 1, Time 2, bLooping 3, bMaxOncePerFrame 4 ; ReturnValue 1 = handle |
| arrêt de la minuterie (B1-13, B2-6) | Utilitaires|Temps|ClearandInvalidateTimerbyHandle |
Handle (1, par référence) ← Obtenir RoomCamTimer ; K2_ClearTimerDelegate n'existe pas pour create_node |
RoomCamTimer (B1-1) |
add_struct_variable(struct_type = /Script/Engine.TimerHandle) ; getters Variables|Pardéfaut|Obtenir/DéfinirRoomCamTimer |
— |
SphereTraceSingle (B2-3) |
Collision|SphereTraceByChannel |
Radius 3, TraceChannel 4 = TraceTypeQuery2, ActorsToIgnore 6, DrawDebugType 7, bIgnoreSelf 8 ; OutHit 1, ReturnValue 2 |
BreakHitResult |
Collision|BreakHitResult |
entrée 0 |
VInterpTo, RInterpTo (B2-6) |
Math|Interpolation|VInterpTo / RInterpTo |
Current 0, Target 1, DeltaTime 2, InterpSpeed 3 |
GetWorldDeltaSeconds |
Utilitaires|Temps|GetWorldDeltaSeconds |
sortie double, acceptée sur DeltaTime float |
FindLookAtRotation |
Math|Rotateur|FindLookatRotation |
— |
GetComponentBounds, GetActorBounds |
Collision|GetComponentBounds, Collision|GetActorBounds |
broches non relues (nœuds non câblés en B0) |
GetSocketLocation (os head) |
Transformation|GetSocketLocation |
idem |
GetScaledCapsuleHalfHeight |
Composants|Capsule|GetScaledCapsuleHalfHeight |
self 0, sortie float |
Less_DoubleDouble, EqualEqual_ObjectObject, + − × de vecteurs |
Utilitaires|Opérateurs|Inférieurà(<), Égalà(==), Ajouter, Soustraire, Multiplier |
typés à la 1re liaison (R2) |
surcharge ReceiveEndPlay (B2-7) |
add_event(event_name = "ReceiveEndPlay") |
rend un K2Node_Event |
| Branche | Utilitaires|ContrôleDeFlux|Branche |
exécution 0, Condition 1 ; then 0, else 1 (lp-mcp § 3) |
Complément B1b : identifiants relevés pendant B1 (attache, transform, visibilité, GetViewTarget, tableau, appels
Classe|Room|… depuis PC et GI) dans CAM-B1-IMPL.md § 2 ; Variables|Rendu|ObtenirActorHiddenInGame ne lit que
l'acteur lui-même (aucune broche self), même avec declaring_class.
Fichiers à commiter
- A
Docs/Migration/etat/CAM/CAM-SPEC.md(dépôt du jeu, brancheue5.8, avec les livrables du lot, sur ticket du gardien). Aucun autre fichier écrit.
Tours : 29 / 60 (CAM-T5) ; CAM-T5b : 20 / 25
Constats
- Trous de CAM-T2 § 3.5 fermés ou réduits :
- Déclencheur de
OpenSpace/CloseSpace: le BPStreetMap_Static(GI_C::OpenSpacedepuisIfThenElse_32.elseet aprèsPlayerMoving:= faux ;GI_C::CloseSpaceaprèsCallFunction_71, SMS:5709-5719, 5743-5749), plus un appel interne de GI (K2Node_CallFunction_671, GI:23971-23974). Établi (dump STB, version non comparée à HEAD). - Amont de
Room.AutoCamera:LoadRoom(K2Node_CustomEvent_14, ROOM:1099-1102) → … →currentRoom→clearObjects→previousScale:= échelle →CallFunction_186→ murs (ROOM:4652-4665) →MoveAllToCenterRoom(ROOM:3330-3332) →IfThenElse_63« échelle inchangée » ;else→AutoCamera(ROOM:4059-4072, 3873-3876). Établi pour les maillons lus ;CallFunction_377→VariableSet_6et le contenu deCallFunction_186non lus (estimé :AutoCamerane joue que si l'échelle de la pièce change). - Birdview relaie vers Room quand
CheckIfCameraMovablerend faux : appelsRoom_C::LeftRight,RotateCamera,CircleCamera,DownUp,ScrollDownUpsur la sortie « faux » des branchesIfThenElse_24,_25,_26,_1,_0(BV:511-555, 1538-1577) ;Moveable= ET(nonActionBox.HasAnyChildren, nonScrollBoxOn, nonCharGenOn,TopRightvisible, nonSpaceOn) (BV:124-180) : en pièce, toujours relayé ; Room ne déplace alors queSceneCamera, invisible en C1-C3 : la décision Q10 (« rien ») ne demande aucun nœud (établi). Birdview écritGI.Birdviewà sonBeginPlay: établi (VariableSet_1937 GI→VariableSet_1 'Birdview':=Self, BV:436-446). Birdview litPreventCameraMove(BV4:480). - Écriture de
ChargenCameras: non fermé (script du niveau ; aucunVariableSet ChargenCamerasdans les dumps). - ContactMenu :
ReturnFromChargen→SelectCamera→CurrentCamera:=SelectInt(2, 1, GI.isCreature(DummyPerson))→SetViewTargetWithBlend(GI.ChargenCameras[CurrentCamera])(CM:5116-5118, 5334-5340, 5321-5333, 5168-5173, 5146-5154) : index 2 pour une créature, sinon 1, jamais 0 (établi) ; rôle CharGen, inchangé par la SPEC. ProjectionModenon affiché, dumpFirstPersonvide (CAM-T4) : sans effet (C1 garde le composant tel quel, FOV 90).
- Déclencheur de
- Reclassement des 4 rôles de
ChargenCameras[0]: pièce (GI:23596, 17470 ; ROOMLoadRoom) → caméra de pièce (B1) ; scène (GICF:6182 ; ROOMCameraFocus*; GI:5866) → C2 (B4, Q12) ; sexe (GI:14505 ; PC:1752) → caméra de pièce (B1, Q8) ; CharGen (GI:803-807, 3132-3140, 22424-22427 ; CM:5146-5173 ;ResetSceneCamera) → inchangé ; 5e rôle trouvé : constructeur (ROOM:28-36, déplacements ROOM:394-910) → inchangé (Q9, Q10). - Aucune décision du § 4b n'est contredite par un fait établi. Deux tensions, posées en questions : le cycle POV gardé
finit aujourd'hui sur
CameraScene, réservée au CharGen (Q8) ; « taille du MC » n'est portée par aucune donnée directe (capsule fixe de 88 cm de demi-hauteur pour toute Person, PCOMP:1768) (Q2). - Le but « moins de caméras » reste à 6 sortes avant comme après (Q19 décidée : un seul acteur ;
FollowView retirée,
CamRoomajoutée). Les décisions Q6 (garder Birdview et les 3 caméras du studio) expliquent ce plancher. - Redumps avec broches CAM-T6 (Birdview, ContactMenu, Person) lus par l'amendement : R12 réduit (items 3 et 5 ci-dessus) ;
chaîne de Person morte à HEAD (
IfThenElse_70 execute (vide), PERS:13468-13472), laissée en place (Q18). - Amendement CAM-T5b : C2 n'est plus attachée ; la minuterie de Room (nœud mort réemployé) sert dès B1 de garde pour C1 (R18) puis de moteur de la poursuite de C2 (B2) et du regard de C3 (B3) ; 7 nouveaux nœuds de fonctions moteur à prouver par la sonde B0 (R1) ; durée de copie UE ≈ 6 h 20 au lieu de ≈ 4 h 45 ; liste des points de GI inchangée.
RCOMP(composants de Room) vient de la copie 5.5 (2026-10-04) : unLPDumpComponents -BP=Room -Allsur la copie 5.8 confirmeraitBox,WallTet l'échelle de la racine (valeurs non utilisées comme constantes par la SPEC).- Méthode : lecture seule (Read, Grep, Glob) ; un Grep lancé avec un chemin erroné (
D:\Game\Launcher\..\LifePlay-master 5.8\...) a rendu 0 résultat, refait avec le bon chemin (7 lignesPreventCameraMove).