Add Papyrus sync scripts and proxy spawn refactor

Add new Papyrus scripts (CoSync.psc, CoSyncPlayer.psc, CoSyncQuest.psc) providing native bindings and quest/player proxy logic for networking: connection/session APIs, entity management, world/weather/workshop/companion sync, consumable/pipboy/door/power-armor events, and proxy animation/initialization handlers. Refactor the proxy actor controller (F4TProxyActorController.cpp) to support dynamic/runtime proxy spawning and improved lifecycle/visibility handling: change proxy base/form IDs to COPlayerProxy/CommonwealthOnline, add process-list actor lookup, spawn helpers, play-space/cell checks, 3D visibility refresh, ActorHandle usage, and spawn mutexes and globals for safer spawning. Update docs and setup (architecture.md, limitations.md, plugin/setup.md) to describe global dynamic spawn behavior, max runtime proxies (kMaxRuntimeProxyActors = 4), and validation checklist; update launch-two-fallout4.bat to show instance log locations. Misc: small tweaks to logging and debug flags to gate diagnostics.
This commit is contained in:
2026-06-07 20:31:51 +12:00
parent 21c8bf9593
commit cc4d8aac5a
10 changed files with 1645 additions and 190 deletions
File diff suppressed because it is too large Load Diff
+6 -2
View File
@@ -53,6 +53,7 @@ namespace
};
constexpr auto kTransformSendInterval = 100ms;
constexpr auto kIdleTransformHeartbeatInterval = 2s;
constexpr auto kTransformLogInterval = 1s;
constexpr auto kTransformSendPositionThreshold = 3.0F;
constexpr auto kTransformSendRotationThreshold = 0.02F;
@@ -524,13 +525,16 @@ namespace
const auto isSpecialMovement = movementType != std::string_view{ "normal" };
const auto hasMeaningfulTransformDelta = HasMeaningfulTransformDelta(lastSentTransform, currentTransform);
const auto hasMovementStateChanged = HasMovementStateChanged(lastSentMovementState, networkMovementState);
if (!isSpecialMovement && !hasMeaningfulTransformDelta && !hasMovementStateChanged) {
const auto idleHeartbeatDue = (currentTime - lastSendTime) >= kIdleTransformHeartbeatInterval;
if (!isSpecialMovement && !hasMeaningfulTransformDelta && !hasMovementStateChanged && !idleHeartbeatDue) {
lastDebugSampleTransform = currentTransform;
lastDebugSampleTime = currentTime;
return;
}
if (!isSpecialMovement && currentTime - lastSendTime < kTransformSendInterval) {
if (!isSpecialMovement && !hasMeaningfulTransformDelta && !hasMovementStateChanged) {
// Idle heartbeat: keep remote clients updated even when both players are standing still.
} else if (!isSpecialMovement && currentTime - lastSendTime < kTransformSendInterval) {
return;
}