Files
Commonwealth-Online-Public/plugin/include/F4TRemotePlayerState.h
T
andrew abef899505 Add proxy puppet hook and graph speed sync
Introduce a puppet vtable hook to preserve networked locomotion Speed and fix proxy cadence. Added F4TProxyPuppet (header + impl) which installs an Actor::Update hook that writes the desired graph Speed and calls UpdateNoAI for proxy actors so the engine does not recompute/zero Speed from controller velocity. Publish active proxy FormIDs and per-proxy desired speeds so the hook targets only proxy actors.

Wire animationGraphSpeed through networking: parse/send a new "animationGraphSpeed" field and store it on RemotePlayerState. Proxy animation sync now prefers the authoritative animationGraphSpeed when present, otherwise maps movementSpeed ~1:1 to graph Speed (with sprint floor and clamping). Added graph variables speedSampled/speedDamped alongside Speed and updated snapshot population and diagnostics. Removed character-controller velocity injection (was causing physics/animation conflicts) and adjusted proxy movement logic to rely on graph variables plus kinematic SetPosition.

Also: Publish puppet diagnostics from the controller, add sender-side local graph speed read diagnostic, update fake_player to compute and send animationGraphSpeed, and append detailed dev-log entries describing the root cause, diagnostics, and fixes. Build and runtime diagnostics added to verify hook behavior and cadence changes.
2026-06-04 20:18:34 +12:00

63 lines
2.3 KiB
C++

#pragma once
#include <chrono>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
namespace F4T::RemotePlayerState
{
// Represents a remote action event captured from another player
// Used for action replay on proxy actors (combat idles, equipping, etc.)
struct RemoteActionEvent
{
std::uint32_t type{}; // Action type (see ActorMediator::ActorAction enum)
std::string eventName; // Action event name (e.g., "ActorMovementStart")
std::vector<float> animationVariablesFloat; // Float variables snapshot (Speed, Direction, etc.)
std::vector<bool> animationVariablesBool; // Bool variables snapshot (IsSprinting, IsSneaking, etc.)
std::vector<std::uint32_t> animationVariablesInt; // Int variables snapshot (weapon types, etc.)
std::uint32_t actorStateFlags1{}; // ActorState.flags1 at action time
std::uint32_t actorStateFlags2{}; // ActorState.flags2 at action time
std::chrono::steady_clock::time_point captureTime{};
};
struct RemotePlayerState
{
std::uint32_t playerId{};
float x{};
float y{};
float z{};
float angleZ{};
std::string movementType;
std::string cellId;
std::string worldspaceId;
std::optional<double> clientTime;
std::optional<double> serverTime;
bool isMoving{ false };
bool isSprinting{ false };
bool isSneaking{ false };
bool isJumping{ false };
bool weaponDrawn{ false };
float movementSpeed{ 0.0F };
// Authoritative Havok graph Speed from sender when available (>= 0). -1 means unset.
float animationGraphSpeed{ -1.0F };
std::chrono::steady_clock::time_point lastReceivedLocalTime{};
// Phase 2: Actor state and action events (TiltedEvolution alignment)
std::uint32_t actorStateFlags1{}; // ActorState.flags1 (combat, sneaking, etc.)
std::uint32_t actorStateFlags2{}; // ActorState.flags2 (additional state flags)
std::vector<RemoteActionEvent> actionEvents; // Queue of pending action events
};
void SetAssignedPlayerId(std::uint32_t a_playerId);
std::optional<std::uint32_t> GetAssignedPlayerId();
bool IsAssignedPlayerId(std::uint32_t a_playerId);
void ClearAssignedPlayerId();
void UpdateRemotePlayer(RemotePlayerState a_state);
bool RemoveRemotePlayer(std::uint32_t a_playerId);
void ClearRemotePlayers();
std::vector<RemotePlayerState> GetRemotePlayerSnapshot();
}