Runtime proxy spawn: Stage 3 PlaceAtMe

Promote a single runtime-spawned proxy as the preferred active remote-player representation (Stage 3 / 3.7) while preserving the placed reference as a fallback. Updates include: detailed architecture and dev-log additions describing staged diagnostics (3.1–3.7), PlaceAtMe-backed spawn candidate isolation/settle, vanilla/Codsworth diagnostics, console PlaceAtMe testing, near-player visibility holds, and PASS/PARTIAL/FAIL diagnostic outcomes.

Code changes (plugin/include & plugin/src): adjust header comment and implement numerous runtime proxy features and diagnostics: new constants, enums, structs, state variables, logging helpers, position/distance helpers, absolute FormID lookup, runtime actor base selection (custom vs vanilla), PlaceAtMe-backed spawn state machine, debug placement/hold timing, candidate snapshot/isolation, promotion to active runtime proxy, and many throttled/logged diagnostics. The placed CK reference remains the fallback if runtime spawn/validation fails. Docs changed: docs/architecture.md and docs/dev-log.md updated to describe the new Stage 3 behavior and testing notes.

Files changed: docs/architecture.md, docs/dev-log.md, plugin/include/F4TProxyActorController.h, plugin/src/F4TProxyActorController.cpp.

Behavioral notes: single-proxy only (Stage 4 mapping deferred), extensive diagnostic logging added, and in-game validation/testing remains pending.
This commit is contained in:
2026-06-02 22:27:42 +12:00
parent 9b19143477
commit 37ef52549c
4 changed files with 2861 additions and 99 deletions
+103 -24
View File
@@ -26,25 +26,76 @@ both send and receive paths:
10. The plugin and fake client remove disconnected players from their remote
player tables.
11. On the game-thread update path, the proxy controller performs a one-shot
runtime spawn diagnostic in `F4TTestCell01` from the resolved
`F4T_RemotePlayerProxy` actor base. This spawned actor is not yet driven
from remote-player state.
runtime spawn in `F4TTestCell01` from the selected runtime actor base. Stage
3.7 makes the preferred runtime spawn strategy PlaceAtMe-backed spawning:
the plugin snapshots existing matching candidates, executes a single
`player.placeatme <baseFormId> 1` command, isolates the newly spawned actor
by comparing pre/post candidate FormIDs, and lets that actor settle before
remote movement begins. The custom `F4T_RemotePlayerProxy` base is attempted
first, with Codsworth retained only as a diagnostic fallback.
12. On the same game-thread update path, the plugin reads a copied remote-player
snapshot and moves the single placed proxy actor in `F4TTestCell01`.
Proxy visual updates are independent from local movement log throttling:
normal movement is smoothed toward the latest target, while cell changes,
worldspace changes, and teleports snap directly.
snapshot and resolves one active proxy actor. The runtime-spawned actor is
preferred when its handle resolves and validates; otherwise the placed
fallback reference `F4TProxyRemotePlayer01REF` is used. Proxy visual updates
are independent from local movement log throttling: normal movement is
smoothed toward the latest target, while cell changes, worldspace changes,
and teleports snap directly.
13. When the selected remote player is missing, disconnected, or not in the same
test cell, the game-thread proxy controller moves the single placed proxy to
a hidden holding position inside `F4TTestCell01` until a valid same-cell
test cell, the game-thread proxy controller moves the active proxy to a
hidden holding position inside `F4TTestCell01` until a valid same-cell
remote player is available again.
14. As part of the staged runtime proxy actor manager work, the same game-thread proxy
controller also logs whether `Fallout4Together_Test.esp` is loaded and
14. As part of the staged runtime proxy actor manager work, the same game-thread
proxy controller also logs whether `Fallout4Together_Test.esp` is loaded and
whether the actor base `F4T_RemotePlayerProxy` resolves by editor ID.
15. Stage 3.1 adds a temporary diagnostic layer around the single runtime proxy:
post-spawn visibility data, loaded-3D pointer checks where safe, console
helper logs, active source logs, and throttled post-movement diagnostics.
The diagnostic mode can force the runtime proxy near the local player to
prove whether the created actor is visibly renderable.
16. Stage 3.2 adds a temporary near-player visibility hold for that same single
runtime proxy. During the hold, remote state is still selected and validated,
but runtime proxy restore and remote movement are deferred long enough to
test whether a runtime-created actor ref can load visible 3D while kept near
the local player.
17. Stage 3.3 adds a temporary vanilla actor-base diagnostic layer. It attempts
to resolve Codsworth as a visible vanilla `TESNPC` candidate, then passes
that actor base into the same runtime spawn, handle validation, near-player
hold, and visibility diagnostic path. This isolates custom actor-base issues
from runtime-spawn/init issues without changing the final architecture.
18. Stage 3.4 adds a temporary absolute FormID and existing-reference diagnostic
layer. It compares Codsworth base-form runtime spawning against moving the
existing placed Codsworth reference near the local player as a visibility
control. This separates runtime actor creation/init problems from vanilla
actor-base or placed-reference movement problems and does not change the
final architecture.
19. Stage 3.5 adds a temporary PlaceAtMe-equivalent diagnostic after manual
console validation proved `player.placeatme 000179FF 1` can spawn visible
Codsworth in `F4TTestCell01`. The plugin executes that console placement path
from the local player, resolves the newly created Codsworth actor near the
player, and holds/logs it separately from the `CreateReferenceAtLocation`
runtime proxy path.
20. Stage 3.6 refines that temporary PlaceAtMe diagnostic layer. It snapshots
known Codsworth refs before executing `player.placeatme 000179FF 1`, accepts
only a newly isolated Codsworth ref for the primary diagnostic, and preserves
that actor at the original console-spawned location during a short settle
window. This tests whether the actor becomes visible naturally or requires a
render/process refresh such as the manually observed pause-menu or alt-tab
behavior. Stage 3.6 does not change the final architecture.
21. Stage 3.7 promotes the working PlaceAtMe-style spawn pattern into the
preferred single runtime proxy spawn path. The proxy controller uses the
resolved runtime FormID for `F4T_RemotePlayerProxy` when available, falls
back to Codsworth only for diagnostics, defers active proxy selection during
candidate isolation and settle, then promotes the settled actor into the
existing single-proxy movement pipeline.
The Fallout 4 plugin now has a diagnostic-only runtime spawn test, but it still
does not dynamically spawn actors for remote player representation. The placed
proxy reference remains the active visual representation path.
The Fallout 4 plugin now dynamically spawns one runtime proxy actor for remote
player representation in the test cell. The placed proxy reference remains as a
fallback path if runtime spawn, handle validation, actor validation, or lookup
fails.
Stage 4 is still reserved for multiple runtime proxies and a
`remotePlayerId -> proxy actor handle` mapping. Stage 3.7 does not add that
mapping.
## Main Components
@@ -59,19 +110,41 @@ The native plugin is responsible for:
- Throttling normal transform sends separately from readable local movement logs
- Receiving server packets on a background thread
- Storing assigned and remote `playerId` state internally
- Moving the single placed test proxy actor from remote-player state on the game
thread
- Holding that proxy actor at a hidden in-cell position when no valid same-cell
remote player should be represented
- Moving the single active proxy actor from remote-player state on the game
thread, preferring the runtime-spawned actor and falling back to the placed
reference
- Holding that active proxy actor at a hidden in-cell position when no valid
same-cell remote player should be represented
- Logging staged runtime proxy actor base lookup diagnostics on the same
game-thread controller path
- Attempting one game-thread-only runtime spawn diagnostic from
`F4T_RemotePlayerProxy` in `F4TTestCell01`
- Attempting one game-thread-only PlaceAtMe-backed runtime spawn from the
selected Stage 3 actor base in `F4TTestCell01`, normally
`F4T_RemotePlayerProxy`
- Logging temporary Stage 3.1 visibility and movement diagnostics for the single
runtime proxy, including active proxy source, runtime FormID, local distance,
and safe loaded-3D checks
- Holding the single runtime proxy near the local player during temporary Stage
3.2 diagnostics so the plugin can determine whether runtime-created actor refs
can load visible 3D before remote movement resumes
- Temporarily comparing a vanilla visible NPC actor base against the custom
proxy actor base during Stage 3.3, while preserving the same runtime spawn
path and keeping Stage 4 reserved for later mapping work
- Temporarily resolving Codsworth base and placed-reference absolute FormIDs
during Stage 3.4, then moving the existing placed reference near the player as
a visibility control separate from runtime spawning
- Temporarily testing a local-player `player.placeatme`-equivalent console path
during Stage 3.5, then comparing the resulting visible actor behavior against
the existing `CreateReferenceAtLocation` runtime actor path
- Temporarily isolating the newly spawned PlaceAtMe ref during Stage 3.6 and
testing render/process settle behavior without changing active proxy mapping
- Using Stage 3.7 to isolate a PlaceAtMe-backed runtime proxy, preserve it
during a short settle window, and then promote it into the existing
single-proxy movement path
Planned later:
- Supporting one proxy actor per represented remote `playerId`
- Driving runtime-spawned proxy actors from remote-player state
- Mapping each represented remote `playerId` to its own proxy actor handle
### External Server
@@ -123,8 +196,14 @@ Networking thread receives packets
Networking thread stores remote player state
Game update reads a copied remote player snapshot
Game update resolves/logs proxy actor base diagnostics
Game update attempts one diagnostic runtime actor spawn in F4TTestCell01
Game update moves the placed test proxy actor
Game update selects the Stage 3 runtime actor base
Game update attempts one PlaceAtMe-backed runtime actor spawn in F4TTestCell01
Game update snapshots matching candidates, isolates the new actor, and waits for the Stage 3.7 settle window
Older standalone Stage 3.4/3.6 diagnostics stay disabled while Stage 3.7 is active
Game update logs temporary Stage 3.1 runtime visibility diagnostics
Game update can temporarily hold the Stage 3.2/3.3 runtime proxy near the local player
Game update prefers the validated runtime proxy, or falls back to F4TProxyRemotePlayer01REF
Game update moves the selected active proxy actor and logs throttled movement diagnostics
```
The networking receive thread does not directly modify Fallout 4 actors or game
@@ -134,8 +213,8 @@ update path.
## Out Of Scope For Current Prototype
- Using runtime-spawned actors for remote player representation
- Multiple proxy actors
- `remotePlayerId -> proxy actor handle` mapping before Stage 4
- Animation graph sync or animation application
- Combat sync
- Quest sync
+533
View File
@@ -1301,6 +1301,539 @@ remote player representation.
---
## 2026-06-02 - Runtime Proxy Spawning Stage 3
### Summary
Made the single runtime-spawned `F4T_RemotePlayerProxy` actor the preferred
active remote player representation in `F4TTestCell01`, while preserving
`F4TProxyRemotePlayer01REF` as the placed fallback if runtime spawn or runtime
handle validation is unavailable.
### Files Changed
- `plugin/src/F4TProxyActorController.cpp`
- `plugin/include/F4TProxyActorController.h`
- `docs/architecture.md`
- `docs/dev-log.md`
### Details
- Reframed the Stage 2 diagnostic runtime handle as the single Stage 3 runtime
proxy handle stored in `RE::ObjectRefHandle`.
- Added active-proxy selection that revalidates the runtime handle each
controller update and prefers it when it resolves as a non-player actor in
`F4TTestCell01`.
- Falls back to the placed reference path when runtime spawn has not completed,
spawn failed, the handle does not resolve, the handle does not resolve as an
actor, or runtime actor validation fails.
- Kept placed fallback lookup available through `F4TProxyRemotePlayer01REF` and
the ESP-local fallback FormID, and prevents placed fallback cell scanning from
selecting the runtime-spawned actor by base actor.
- Reused the existing single remote-player selection behavior: lowest
`playerId` only. Added TODO notes for Stage 4 one-proxy-per-player mapping.
- Routed existing smoothing, special movement snapping, same-cell gating,
holding-position lifecycle, restore behavior, and sneak-state observation
through the selected active proxy.
- Did not add visual sneak/crouch application, gameplay sync, animation sync,
multi-proxy mapping, protocol changes, networking changes, Python server
changes, or fake-client tooling changes.
### Testing
- Ran `xmake build` from `plugin`; it succeeded.
- Pending: launch Fallout 4 through F4SE, load `Fallout4Together_Test.esp`, and
`coc F4TTestCell01`.
- Pending: confirm runtime actor-base resolution, one runtime spawn, runtime
active selection, smooth fake-client movement, special movement snaps,
leave-cell holding, return-cell restore, disconnect holding, and sneak-state
observation.
- Pending: force or observe runtime validation failure and confirm the placed
fallback still represents the selected remote player.
### Known Issues
- Runtime support is still intentionally single-proxy only.
- Runtime proxy actors are held for reuse and are not disabled, deleted, made
invisible, or despawned in this milestone.
### Next Steps
- Run the build and in-game Stage 3 validation checklist.
- If Stage 3 is stable, proceed later to Stage 4 multi-proxy mapping with a
`remotePlayerId -> proxy actor handle` design.
---
## 2026-06-02 - Runtime Proxy Spawning Stage 3.1
### Summary
Added a temporary runtime proxy visibility diagnostic layer so the next in-game
test can prove whether the single runtime-spawned proxy actor is visibly
renderable, loaded, and being moved as expected.
### Files Changed
- `plugin/src/F4TProxyActorController.cpp`
- `docs/architecture.md`
- `docs/dev-log.md`
### Details
- Added post-spawn runtime proxy diagnostics for created ref FormID, actor base
FormID, handle value, resolved actor state, parent cell, proxy position, local
player position, and local distance.
- Added safe diagnostic checks for runtime form created/deleted/disabled flags,
available-in-game state, actor visibility, and `Get3D`/`GetFullyLoaded3D`/
`GetCurrent3D` pointer availability. Reference enable state remains logged as
unavailable rather than guessed.
- Added a temporary debug visibility mode,
`kDebugForceRuntimeProxyNearLocalPlayer`, which forces the runtime proxy near
the local player at X + 350 and Z + 20 after spawn and scales it to 1.5 for
easier visual confirmation.
- Added the runtime console helper log:
`prid <runtimeRef>` followed by `moveto player` or `enable`.
- Added explicit active source logs for runtime proxy selection and placed
fallback selection.
- Added throttled post-restore and post-move diagnostics with proxy source,
proxy FormID, assigned remote `playerId`, target remote position, actual proxy
position, local player position, local distance, same-cell result, and movement
mode (`restore`, `smooth`, or `snap`).
- Preserved Stage 3 single-proxy behavior: lowest remote `playerId`, same-cell
gating, holding lifecycle, smoothing, snap movement, movement-state
observation, placed fallback support, and skipping runtime-created actors
during fallback scans.
- Did not implement Stage 4 multi-proxy mapping or any
`remotePlayerId -> proxy actor handle` table.
### Testing
- Ran `xmake build` from `plugin`; it succeeded.
- Pending: launch two real clients in `F4TTestCell01` and confirm whether the
debug-forced runtime proxy appears near the local player.
- Pending: use the logged console helper command to run
`prid <runtimeRef>`, then `moveto player` or `enable`, to inspect the runtime
reference directly.
### Known Issues
- Runtime refs are created and moved according to logs, but visual rendering is
not yet confirmed in-game.
- The Stage 3.1 debug near-player placement and scale are temporary diagnostics
and should be disabled after visibility is proven.
### Next Steps
- Run two real clients, check for the debug-forced runtime proxy near the local
player, and try the console `prid <runtimeRef>` helper.
- Use the Stage 3.1 logs to decide whether the runtime actor is disabled,
missing 3D, unloaded, moving out of view, or valid but not rendered.
- Keep Stage 4 reserved for later multi-client
`remotePlayerId -> proxy actor handle` mapping.
---
## 2026-06-02 - Runtime Proxy Spawning Stage 3.2
### Summary
Added a temporary runtime proxy visibility hold so the single runtime-spawned
proxy remains near the local player before remote assignment. This should show
whether Fallout 4 ever creates visible 3D for the runtime-created actor ref when
it is kept in a loaded, nearby location.
### Files Changed
- `plugin/src/F4TProxyActorController.cpp`
- `docs/architecture.md`
- `docs/dev-log.md`
### Details
- Added `kDebugHoldRuntimeProxyNearLocalPlayer` and
`kDebugRuntimeProxyHoldSeconds` as temporary Stage 3.2 diagnostics.
- When the hold is active, the runtime proxy remains at the near-player debug
position for 15 seconds before remote assignment or remote movement resumes.
- Deferred runtime proxy restore and smooth/snap remote movement during the hold
while preserving remote-player snapshot storage, lowest `playerId` selection,
same-cell validation, placed fallback support, and the Stage 3 holding
lifecycle outside the hold.
- Added repeated hold diagnostics around every 2 seconds with runtime ref FormID,
actor base FormID, parent cell, proxy/local positions, local distance, safe
form-state checks, `Get3D`/`GetFullyLoaded3D`/`GetCurrent3D`, `IsVisible`,
hold elapsed time, hold remaining time, and whether the proxy had to be
re-placed near the local player.
- Added a hard hold conclusion: `PASS` if any safe 3D or visibility check becomes
true, otherwise `FAIL` with a note that placed fallback refs or another actor
spawn/init path may be safer before Stage 4.
- Kept safe post-spawn initialization limited to calls that build in the current
CommonLibF4 setup: `SetPosition`, `SetHeading`, `SetScale`,
`initializeScripts = true`, `initiallyDisabled = false`, and guarded
`Enable(false)` only if the spawned actor reports disabled. Forced 3D/load
update APIs remain logged as unavailable.
- Did not implement Stage 4 multi-proxy mapping or any
`remotePlayerId -> proxy actor handle` table.
### Testing
- Ran `xmake build` from `plugin`; it succeeded.
- Pending: run two real clients in `F4TTestCell01` and inspect whether the
Stage 3.2 hold diagnostics report any `Get3D`, `GetFullyLoaded3D`,
`GetCurrent3D`, or `IsVisible` transition to true.
### Known Issues
- The issue under investigation remains: runtime refs exist, are selected, and
can move in memory, but they may still fail to load visible actor 3D.
- The near-player hold is temporary diagnostic behavior and should be removed or
disabled after the runtime visibility path is proven or rejected.
### Next Steps
- Use the Stage 3.2 PASS/FAIL hold conclusion from an in-game test to decide
whether runtime-created actors can remain the preferred Stage 3 visual path.
- If Stage 3.2 fails, consider placed fallback refs or a different actor
spawn/init path before any Stage 4 multi-proxy work.
- Keep Stage 4 reserved for later
`remotePlayerId -> proxy actor handle` mapping.
---
## 2026-06-02 - Runtime Proxy Spawning Stage 3.3
### Summary
Added a temporary vanilla visible NPC diagnostic for the Stage 3 runtime spawn
path. The controller can now use Codsworth as the default diagnostic actor base
instead of `F4T_RemotePlayerProxy`, while keeping the same runtime spawn,
handle-validation, near-player hold, and repeated visibility diagnostic path.
### Files Changed
- `plugin/src/F4TProxyActorController.cpp`
- `docs/architecture.md`
- `docs/dev-log.md`
### Details
- Added `kDebugUseVanillaVisibleNpcForRuntimeSpawnTest` and
`kDebugVanillaVisibleNpcFormId` for the Stage 3.3 diagnostic. The candidate is
treated as Codsworth and resolved safely through the data-handler form lookup
path.
- Logged the diagnostic actor-base source as either `vanilla diagnostic NPC` or
`custom F4T_RemotePlayerProxy` so runtime spawn, visibility diagnostics, and
hold conclusions identify which base was tested.
- Validated that the Codsworth candidate resolves as `RE::TESNPC`, with logs for
resolved FormID, form type, editor ID, display name, and accepted state. If it
does not resolve as a valid `TESNPC`, the controller logs the failure and falls
back to the normal custom proxy actor base.
- Preserved the existing Stage 3 runtime spawn path: the selected `TESNPC*` is
passed into the current spawn function, with the same handle validation,
runtime proxy state, placed fallback support, Stage 3.2 hold, and repeated
diagnostics.
- Improved near-player debug placement to prefer forward-vector placement about
250 units in front of the local player at `Z + 20`, with a fixed X-offset
fallback if heading data is not usable.
- Expanded the hold conclusion for the vanilla diagnostic to report `PASS`,
`PARTIAL`, or `FAIL` based on whether `IsVisible` becomes true, 3D loads while
visibility remains false, or no 3D checks become true.
- Did not implement Stage 4 multi-proxy mapping or any
`remotePlayerId -> proxy actor handle` table.
### Testing
- Ran `xmake build` from `plugin`; it succeeded.
- Pending: launch Fallout 4 through F4SE, enter `F4TTestCell01`, and confirm
`Fallout4Together.log` reports whether the Stage 3.3 vanilla diagnostic is
active or fell back to `F4T_RemotePlayerProxy`.
- Pending: inspect the hold diagnostics and final PASS/PARTIAL/FAIL result to
determine whether the vanilla actor base appears visually through the same
runtime spawn path.
### Known Issues
- Stage 3.3 is temporary diagnostic behavior and does not prove the final proxy
representation path until a runtime actor is visually confirmed in-game.
- Stage 4 remains blocked until the visual representation problem is isolated to
either the custom actor base or the runtime spawn/init path.
### Next Steps
- Use the Stage 3.3 log result to decide whether to investigate
`F4T_RemotePlayerProxy` in Creation Kit or revisit the runtime spawn/init path
before any Stage 4 work.
- Keep Stage 4 reserved for later
`remotePlayerId -> proxy actor handle` mapping.
---
## 2026-06-02 - Runtime Proxy Spawning Stage 3.4
### Summary
Added an absolute FormID and existing-reference visibility diagnostic for
Codsworth. Stage 3.4 compares resolving Codsworth as a runtime spawn base against
moving the existing placed Codsworth reference near the local player as a
separate visibility control.
### Files Changed
- `plugin/src/F4TProxyActorController.cpp`
- `docs/architecture.md`
- `docs/dev-log.md`
### Details
- Added `kDebugUseExistingVanillaRefVisibilityTest`,
`kDebugCodsworthBaseFormId`, and `kDebugCodsworthRefFormId` for the Stage 3.4
diagnostic.
- Added absolute FormID lookup diagnostics for Codsworth base `000179FF` and
Codsworth placed ref `0001CA7D`, including requested FormID, resolved FormID,
form type, editor ID, display name, and whether the result casts to
`RE::TESNPC`, `RE::Actor`, or `RE::TESObjectREFR`.
- Updated the vanilla runtime-spawn diagnostic to use the Codsworth base only if
absolute FormID lookup resolves `000179FF` as `RE::TESNPC`. If it does not
resolve, the system logs the failure and keeps falling back to
`F4T_RemotePlayerProxy`.
- Added an existing placed-ref visibility control that moves the resolved
Codsworth placed reference near the local player for the diagnostic hold
duration, logs the same 3D/visibility checks, and defers normal proxy movement
while the control is active.
- Stored Codsworth's original position and original cell ID where available, then
attempts to restore the original position at the end of the control hold.
Cross-cell restoration remains logged as unavailable rather than guessed.
- Added a Stage 3.4 PASS/PARTIAL/FAIL conclusion to distinguish existing placed
ref visibility from runtime actor creation/init problems.
- Preserved the custom runtime proxy path, placed fallback support, same-cell
gating, lowest remote `playerId` selection, smoothing, snap movement, holding
lifecycle, remote state handling, fake client behavior, and server protocol.
- Did not implement Stage 4 multi-proxy mapping or any
`remotePlayerId -> proxy actor handle` table.
### Testing
- Ran `xmake build` from `plugin`; it succeeded.
- Pending: launch Fallout 4 through F4SE, enter `F4TTestCell01`, and confirm
`Fallout4Together.log` shows absolute lookup diagnostics for `000179FF` and
`0001CA7D`.
- Pending: confirm that a resolved Codsworth base is used for the vanilla
runtime-spawn diagnostic, or that the custom proxy fallback is logged clearly.
- Pending: confirm that a resolved Codsworth placed ref is moved near the local
player and reports a Stage 3.4 PASS/PARTIAL/FAIL conclusion.
### Known Issues
- Stage 3.4 is temporary diagnostic behavior and does not establish the final
remote player representation architecture.
- The existing placed-ref movement control only runs if `0001CA7D` resolves as
`RE::Actor`; if it resolves only as `RE::TESObjectREFR`, movement and
`IsVisible` diagnostics are logged as unavailable because those APIs are not
exposed on `TESObjectREFR` in the current CommonLibF4 setup.
- If only position restore is available, the diagnostic logs that cell restore is
unavailable rather than attempting a risky cross-cell move.
- Stage 4 remains blocked until visible representation is confirmed.
### Next Steps
- Use the Stage 3.4 control result to determine whether to investigate runtime
actor creation/init, the custom proxy actor base, or the visibility/placement
check itself before any Stage 4 work.
- Keep Stage 4 reserved for later
`remotePlayerId -> proxy actor handle` mapping.
---
## 2026-06-02 - Runtime Proxy Spawning Stage 3.5
### Summary
Added a temporary PlaceAtMe-equivalent diagnostic after manual console validation
confirmed `player.placeatme 000179FF 1` spawns visible Codsworth in
`F4TTestCell01`. The new diagnostic uses the local player as the placement
reference and compares that path against the existing `CreateReferenceAtLocation`
runtime spawn path.
### Files Changed
- `plugin/src/F4TProxyActorController.cpp`
- `docs/architecture.md`
- `docs/dev-log.md`
### Details
- Added `kDebugUseConsolePlaceAtMeSpawnTest` and
`kDebugPlaceAtMeActorBaseFormId` for the Stage 3.5 diagnostic.
- Uses the exposed CommonLibF4 `RE::Console::ExecuteCommand(const char*)`
wrapper to execute `player.placeatme 000179FF 1` once from the game-thread
proxy controller path.
- Snapshots pre-existing Codsworth candidate actors in the current cell before
executing the command, then scans the current cell for a newly created
Codsworth actor near the local player.
- Stores the resolved actor handle and runs a separate 15-second visibility hold
with repeated diagnostics for position, local-player distance, created/deleted
state, disabled state, available-in-game state, `Get3D`,
`GetFullyLoaded3D`, `GetCurrent3D`, and `IsVisible`.
- Defers normal proxy movement while the Stage 3.5 hold is active, without
changing remote state receive/update, placed fallback support, or the existing
Stage 3 runtime proxy path.
- Reports a Stage 3.5 PASS/PARTIAL/FAIL conclusion to distinguish the
local-player console placement path from `CreateReferenceAtLocation` runtime
spawning.
- Did not implement Stage 4 multi-proxy mapping or any
`remotePlayerId -> proxy actor handle` table.
### Testing
- Ran `xmake build` from `plugin`; it succeeded.
- Pending: launch Fallout 4 through F4SE, enter `F4TTestCell01`, and confirm
`Fallout4Together.log` shows the Stage 3.5 console command execution.
- Pending: confirm the diagnostic resolves a spawned Codsworth actor near the
local player and reports a Stage 3.5 PASS/PARTIAL/FAIL conclusion.
### Known Issues
- Stage 3.5 intentionally uses the console placement path as a temporary
diagnostic because manual validation proved that path can spawn visible
Codsworth. It is not the final proxy architecture.
- The diagnostic leaves the PlaceAtMe-spawned actor in the session; no safe
cleanup/despawn path is introduced in this stage.
- Stage 4 remains blocked until visible representation is confirmed and the
preferred spawn/init path is selected.
### Next Steps
- Compare the Stage 3.5 PlaceAtMe result against the existing
`CreateReferenceAtLocation` result to decide whether to replace the runtime
spawn path or investigate initialization differences before Stage 4.
- Keep Stage 4 reserved for later
`remotePlayerId -> proxy actor handle` mapping.
---
## 2026-06-02 - Runtime Proxy Spawning Stage 3.6
### Summary
Refined the PlaceAtMe-equivalent diagnostic so it isolates the Codsworth ref
created by the latest `player.placeatme 000179FF 1` command instead of
accidentally latching onto an older runtime Codsworth candidate.
### Files Changed
- `plugin/src/F4TProxyActorController.cpp`
- `docs/architecture.md`
- `docs/dev-log.md`
### Details
- Added Stage 3.6 constants for candidate isolation, post-spawn settle time, and
candidate search timeout.
- Snapshots known Codsworth candidates before executing PlaceAtMe, logging the
candidate count, FormIDs, 3D state, visibility, and position.
- Executes `player.placeatme 000179FF 1` once per diagnostic attempt, then polls
for a Codsworth actor whose FormID was not present in the pre-spawn snapshot.
- Logs each considered candidate with old/new status, position, distance from
the local player, loaded-3D checks, and `IsVisible`.
- Holds a newly isolated PlaceAtMe actor at its original console-spawned location
during the initial settle window instead of immediately moving it near the
player or assigning it as the active remote proxy.
- Reports a Stage 3.6 PASS/PARTIAL/FAIL conclusion and reminds manual testers
that pause-menu or alt-tab visibility changes point toward render/process
update flushing rather than actor-base selection.
### Testing
- Ran `xmake build` from `plugin`; it succeeded.
- Pending: launch Fallout 4 through F4SE, enter `F4TTestCell01`, and confirm the
log shows a Stage 3.6 pre-placeatme snapshot, one command execution, new
candidate isolation, settle diagnostics, and a final PASS/PARTIAL/FAIL result.
### Known Issues
- Stage 3.6 is still diagnostic-only and leaves the PlaceAtMe-spawned actor in
the session.
- Manual testing showed newly spawned Codsworth may appear only after opening
the pause menu or alt-tabbing, so render/process refresh behavior remains the
main open question.
- Stage 4 remains blocked until visible proxy spawning is fully understood.
### Next Steps
- Use the Stage 3.6 logs to determine whether PlaceAtMe visibility depends on a
delayed render/process update before selecting a final runtime proxy spawn
strategy.
- Keep Stage 4 reserved for later
`remotePlayerId -> proxy actor handle` mapping.
---
## 2026-06-02 - Runtime Proxy Spawning Stage 3.7
### Summary
Made the preferred Stage 3 runtime proxy spawn path PlaceAtMe-backed instead of
`CreateReferenceAtLocation`, reusing the successful Stage 3.6 candidate
isolation and settle window before the actor is promoted into normal remote
movement.
### Files Changed
- `plugin/src/F4TProxyActorController.cpp`
- `docs/architecture.md`
- `docs/dev-log.md`
### Details
- Added Stage 3.7 constants for enabling PlaceAtMe-backed runtime spawning,
trying the custom proxy base first, retaining a Codsworth diagnostic fallback,
and controlling candidate search/settle timings.
- Resolves `F4T_RemotePlayerProxy` through the existing plugin-local FormID path
and uses the resolved runtime FormID in `player.placeatme <baseFormId> 1`.
- Snapshots existing actors matching the selected base before spawning, then
polls for a newly isolated actor whose FormID was not present in the snapshot.
- Preserves the isolated actor at its original PlaceAtMe spawn location during
the settle window and defers active proxy selection/remote movement until the
settle completes.
- Promotes the settled actor into the existing single runtime proxy handle so
same-cell gating, lowest remote `playerId` selection, restore movement,
smoothing, snap movement, holding lifecycle, and movement-state observation
continue through the existing Stage 3 path.
- Skips the old `CreateReferenceAtLocation` runtime spawn when Stage 3.7 is
enabled, while keeping that code path available behind the Stage 3.7 guard.
- Disables the standalone Stage 3.4 existing-ref control and Stage 3.6 Codsworth
diagnostic while Stage 3.7 is active so they do not interfere with proxy
spawning.
- Leaves the placed CK fallback proxy available if PlaceAtMe-backed spawning
fails.
### Testing
- Ran `xmake build` from `plugin`; it succeeded.
- Pending: launch Fallout 4 through F4SE, enter `F4TTestCell01`, and confirm the
log shows Stage 3.7 custom proxy base resolution, one PlaceAtMe command per
attempt, candidate isolation, settle diagnostics, promotion, and normal remote
movement after promotion.
### Known Issues
- Codsworth fallback is diagnostic-only and indicates the custom
`F4T_RemotePlayerProxy` base still needs Creation Kit investigation if it is
the only PlaceAtMe-backed actor that becomes active.
- Stage 3.7 remains single-proxy only. It does not add a
`remotePlayerId -> proxy actor handle` mapping.
- Stage 4 remains blocked until single PlaceAtMe-backed proxy movement is
verified in game.
### Next Steps
- Test the custom PlaceAtMe-backed proxy in game with remote movement and compare
behavior against the Codsworth fallback if needed.
- Keep Stage 4 reserved for later
`remotePlayerId -> proxy actor handle` mapping.
---
## Entry Template
Use this format for future updates:
+1 -1
View File
@@ -2,7 +2,7 @@
namespace F4T::ProxyActorController
{
// Game-thread-only actor controller for proxy diagnostics and the active placed proxy test actor.
// Game-thread-only actor controller for the single active runtime proxy and placed fallback.
// Networking threads must only update plain remote-player state.
void Update();
File diff suppressed because it is too large Load Diff