feat(motion): per-frame Interp.AdjustOffset in remote tick (L.3.1 Task 5)
Wraps the existing legacy per-frame remote tick (apply_current_movement + force-OnWalkable + Euler-extrapolate) in ACDREAM_INTERP_MANAGER=1 env-var guard. When set: - if Interp.IsActive: rm.Body.Position += Interp.AdjustOffset(dt, pos, maxSpeed) - still call body.UpdatePhysicsInternal so airborne arcs (gravity) continue to integrate via the OnLiveVectorUpdated-set velocity. When env-var unset (default), legacy path runs unchanged. Mirrors retail's per-tick CPhysicsObj::UpdateObjectInternal (acclient @ 0x00513730) which calls InterpolationManager::adjust_offset (@ 0x00555D30) every frame. Old legacy path will be removed in Task 8 cleanup commit after visual verification. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
062e19f463
commit
ae79e34a6d
1 changed files with 333 additions and 291 deletions
|
|
@ -5763,6 +5763,47 @@ public sealed class GameWindow : IDisposable
|
||||||
&& serverGuid != _playerServerGuid
|
&& serverGuid != _playerServerGuid
|
||||||
&& _remoteDeadReckon.TryGetValue(serverGuid, out var rm))
|
&& _remoteDeadReckon.TryGetValue(serverGuid, out var rm))
|
||||||
{
|
{
|
||||||
|
if (System.Environment.GetEnvironmentVariable("ACDREAM_INTERP_MANAGER") == "1")
|
||||||
|
{
|
||||||
|
// ── NEW PATH: queued position-chase via InterpolationManager ──
|
||||||
|
// (L.3.1 Task 5 — ACDREAM_INTERP_MANAGER=1 gates this path)
|
||||||
|
//
|
||||||
|
// Walking remotes have m_velocityVector == 0 in retail; all
|
||||||
|
// visible horizontal motion comes from
|
||||||
|
// InterpolationManager::adjust_offset (acclient @ 0x00555D30)
|
||||||
|
// walking the body toward the head of the waypoint queue at
|
||||||
|
// 2 × motion_max_speed × dt (clamped, 7.5 m/s fallback).
|
||||||
|
//
|
||||||
|
// Mirrors retail CPhysicsObj::UpdateObjectInternal
|
||||||
|
// (acclient @ 0x00513730) which calls adjust_offset every frame
|
||||||
|
// before UpdatePhysicsInternal integrates gravity.
|
||||||
|
//
|
||||||
|
// For airborne remotes, OnLiveVectorUpdated has set
|
||||||
|
// body.Velocity (launch arc); we still call
|
||||||
|
// UpdatePhysicsInternal below so gravity applies each frame and
|
||||||
|
// produces the parabolic arc. The IsActive gate prevents
|
||||||
|
// AdjustOffset from pulling against an in-flight arc when no
|
||||||
|
// waypoints are queued for a jumping remote.
|
||||||
|
if (rm.Interp.IsActive)
|
||||||
|
{
|
||||||
|
float maxSpeed = rm.Motion.GetMaxSpeed();
|
||||||
|
System.Numerics.Vector3 delta = rm.Interp.AdjustOffset((double)dt, rm.Body.Position, maxSpeed);
|
||||||
|
rm.Body.Position += delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gravity integration: retail's UpdatePhysicsInternal still
|
||||||
|
// fires every frame regardless of the interpolation path.
|
||||||
|
// For grounded remotes body.Velocity == 0 so this is a no-op;
|
||||||
|
// for airborne remotes it applies gravity to the arc.
|
||||||
|
rm.Body.UpdatePhysicsInternal(dt);
|
||||||
|
|
||||||
|
ae.Entity.Position = rm.Body.Position;
|
||||||
|
ae.Entity.Rotation = rm.Body.Orientation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ── LEGACY PATH (UNCHANGED — kept until Task 8 cleanup) ──
|
||||||
|
//
|
||||||
// Stop detection is handled explicitly on packet receipt:
|
// Stop detection is handled explicitly on packet receipt:
|
||||||
// - UpdateMotion with ForwardCommand flag CLEARED → Ready.
|
// - UpdateMotion with ForwardCommand flag CLEARED → Ready.
|
||||||
// - UpdatePosition with HasVelocity flag CLEARED → StopCompletely.
|
// - UpdatePosition with HasVelocity flag CLEARED → StopCompletely.
|
||||||
|
|
@ -6078,6 +6119,7 @@ public sealed class GameWindow : IDisposable
|
||||||
ae.Entity.Position = rm.Body.Position;
|
ae.Entity.Position = rm.Body.Position;
|
||||||
ae.Entity.Rotation = rm.Body.Orientation;
|
ae.Entity.Rotation = rm.Body.Orientation;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Get per-part (origin, orientation) from either sequencer or legacy ──
|
// ── Get per-part (origin, orientation) from either sequencer or legacy ──
|
||||||
IReadOnlyList<AcDream.Core.Physics.PartTransform>? seqFrames = null;
|
IReadOnlyList<AcDream.Core.Physics.PartTransform>? seqFrames = null;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue