Commit Graph
6 Commits
Author SHA1 Message Date
andrew a137821406 Improve proxy locomotion, tier & jump sync
Fix multiple proxy animation issues: stale graph Speed collapsing jog into walk, missing slow-walk/jog tiers, and jump takeoff/landing not playing. Key changes:

- Prefer position-derived movementSpeed when animationGraphSpeed is missing/stale (ResolveLocomotionGraphSpeed) and fall back to graph Speed only when it agrees within a tolerance; sender now transmits movementSpeed when local graph read is 0 and TryReadLocalAnimationGraphSpeed falls back to SpeedSmoothed.
- Introduce locomotion tiers (Walk/Jog/Run) with ComputeLocomotionTier and sync ints (iSyncWalkRun/iSyncLocomotionSpeed/iSyncJumpState) to the graph; fire corresponding tier events when starting or changing tier.
- Fix proxy motion application: persist per-proxy velocity and worldDelta so the Update hook does not zero-out controller motion; use measured frame motion to drive animation when network flags are sparse.
- Restore correct jump behavior: fire MT/weapon-compatible jump events for takeoff and landing (JumpUp/JumpStartFrom*/jumpLand/jumpLandTo*), clear bInJumpState on landing and remove the extra proxy-side jump hold so landings exit the jump loop.
- Misc: add constants and thresholds for tier/run/walk/run-land decisions and update logs to include tier labels.

Files updated: plugin/include/F4TProxyAnimationSync.h, plugin/src/F4TProxyAnimationSync.cpp, plugin/src/F4AnimationDescriptor.cpp, plugin/src/F4TProxyPuppet.cpp, plugin/src/F4TProxyActorController.cpp, plugin/src/main.cpp, and docs/dev-log.md.
2026-06-05 15:48:16 +12:00
andrew 6a38e7226c Use authoritative FO4 animation variable names
Replace previously guessed graph variable names/types with the real FO4 humanoid movement behavior names (from MTBehavior.hkx) and update syncing logic accordingly. F4AnimationDescriptor now lists only the variables F4T drives (Speed, SpeedSmoothed, IsSprinting, bInJumpState, iIsInSneak) to avoid clobbering graph state; Direction is intentionally not written. Enable proxy sneak sync using the INT32 iIsInSneak, change SpeedSampled -> SpeedSmoothed, and update all Set/Get calls and diagnostic logging to the new names. Fix jump detection by relying on the actor IsJumping() API (removing the noisy vertical-speed heuristic that produced false positives and caused proxies to remain in jump state). Changes touch descriptor, proxy sync, puppet, main logic, and related docs to explain the rationale and testing notes.
2026-06-05 15:29:31 +12:00
andrew 5ba440ab5d Add crouch state and fix jump sync
Add isCrouching to network, state and animation systems; enable proxy jump syncing with a jump-hold debounce and update animation descriptor and server tooling.

Key changes:
- Networking: F4TNetworking.h/cpp: added a_isCrouching, include "isCrouching" in transform packets and parsing, and logging.
- Remote state: F4TRemotePlayerState.h: added isCrouching field.
- Proxy animation: F4TProxyAnimationSync.*: added crouch fields, enabled jump sync, implemented ApplyJumpHoldState and jump hold timing, wrote crouch/jump bools into descriptors when available, updated event firing and logs.
- Animation descriptor: F4AnimationDescriptor.cpp: added isJumping and isCrouching to bool variable list.
- Local detection: main.cpp: added isCrouching in movement state, stubbed GetCrouchState(), adjusted jump hold timing and included crouch in outgoing transform calls.
- Server/dev tooling: server/dev_server_app.py, fake_client.py, fake_player.py, README.md: added crouch reporting, toggle UI/control and fake client support for crouch, and updated docs/logging.
- Docs: docs/dev-log.md updated with notes on jump/crouch fixes and testing.

Rationale: ensure remote players can report crouch state and make jump animations transition reliably by debouncing jump state on proxies and writing available graph bools; also provide dev-server controls and fake-client support for testing.
2026-06-05 14:22:17 +12:00
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
andrew 2aab83087f Debounce movement stop for animations/network
Add a short "moving" hold to reduce flicker when movement briefly stops. Introduces a 300ms stop-hold for both proxy animation sync and local player movement sampling: add chrono include and movingHoldUntil to ProxyAppliedAnimationState, a kProxyMovingStopHoldDuration constant, ApplyMovingHoldState and BuildDebouncedDesiredState in F4TProxyAnimationSync, and replace direct desired-state usage with the debounced version. In main.cpp add kMovementStopHoldDuration, ResolveMovementHoldState, refactor BuildPlayerMovementState, add an overloaded GetPlayerMovementState, and separate debug vs network sampling (with separate movingHoldUntil variables) so logging uses per-frame debug state while network sends use the debounced network state. Also gate diagnostic logging behind a flag. These changes aim to stabilize isMoving/isSprinting transitions and avoid rapid toggles between frames and network updates.
2026-06-04 17:34:16 +12:00
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