Files
Commonwealth-Online-Public/plugin/include/F4TProxyAnimationSync.h
T
andrewandCursor b9ea0ac8a7 docs: proxy animation investigation conclusive - animations not feasible
Investigation summary:
- Tested velocity-based animation triggering: graph variable writes, animation
  events, character controller velocity manipulation, and Move() API calls
- All approaches failed: animations do not play on SetPosition-backed proxy actors
- Root cause: Fallout 4's animation system requires active AIProcess-driven
  locomotion packages, which are incompatible with networked puppet actors
- Fallout 4's animation system fundamentally ties animation evaluation to the
  character controller's actual velocity AND active AI-driven locomotion state
- PlaceAtMe proxies updated via SetPosition cannot provide either requirement

Proxy actors currently work correctly for:
- Smooth position synchronization
- Heading/rotation updates
- Jump animations (via Z-position)
- Network sync and lifecycle

What remains impossible without deep engine access:
- Walk/run/sneak animation playback
- Animation graph variable manipulation affecting behavior
- Character controller velocity synthesis for puppets

Recommendation: Accept this architectural limitation and provide alternative
visual feedback (particles, glows, state indicators) instead of animations.

Files changed:
- plugin/src/F4TProxyActorController.cpp: Reverted to SetPosition-only approach
- docs/dev-log.md: Added comprehensive investigation summary and conclusions

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 14:33:48 +12:00

52 lines
1.3 KiB
C++

#pragma once
#include "F4TRemotePlayerState.h"
#include <cstdint>
#include <optional>
#include <string_view>
namespace RE
{
class Actor;
}
namespace F4T::ProxyAnimationSync
{
// Confirmed via local read-by-name graph debug (Fallout4Together.log):
// - float "Speed" reads/writes while in-game (walk ~47-105)
// - bool "IsSprinting" reads while in-game
// - bIsMoving, bIsSneaking, bSprint, bInJumpState, bWeaponDrawn, Direction: unavailable by name
namespace GraphVar
{
inline constexpr const char* kSpeed = "Speed";
inline constexpr const char* kSpeedLower = "speed";
inline constexpr const char* kIsSprinting = "IsSprinting";
}
struct ProxyAppliedAnimationState
{
bool hasAppliedGraphState{ false };
bool lastIsMoving{ false };
bool lastIsSprinting{ false };
bool lastIsSneaking{ false };
bool lastIsJumping{ false };
bool lastWeaponDrawn{ false };
float lastGraphSpeed{ 0.0F };
float lastDirection{ 0.0F };
};
void ResetAppliedAnimationState(ProxyAppliedAnimationState& a_state);
void ApplyProxyAnimationFromRemoteState(
ProxyAppliedAnimationState& a_state,
RE::Actor& a_proxy,
const RemotePlayerState::RemotePlayerState& a_remotePlayer);
void ClearProxyAnimationState(
ProxyAppliedAnimationState& a_state,
RE::Actor& a_proxy,
std::uint32_t a_remotePlayerId,
std::string_view a_reason);
}