fix(anim): Phase L.1c anchor monster MoveTo prediction
Keep the retail MoveTo speed/runRate parsing from 9812965 for animation playback, but do not use the partial MoveTo state as a body-position solver. Until the full retail MoveToManager target path is ported, retain UpdatePosition-derived velocity for server-controlled creature position and prevent that velocity from clobbering the packet-derived animation cycle speed.
This commit is contained in:
parent
9812965183
commit
882a07cfde
1 changed files with 17 additions and 13 deletions
|
|
@ -226,8 +226,9 @@ public sealed class GameWindow : IDisposable
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True while a server MoveToObject/MoveToPosition packet is the
|
/// True while a server MoveToObject/MoveToPosition packet is the
|
||||||
/// active locomotion source. Retail runs these through MoveToManager
|
/// active locomotion source. Retail runs these through MoveToManager
|
||||||
/// and CMotionInterp using the packet's runRate; deriving velocity
|
/// and CMotionInterp using the packet's runRate; until we port the
|
||||||
/// from sparse UpdatePosition deltas under-speeds combat chases.
|
/// full target solver, use this only to protect packet-derived
|
||||||
|
/// animation speed from velocity-cycle clobbering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ServerMoveToActive;
|
public bool ServerMoveToActive;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -2452,16 +2453,6 @@ public sealed class GameWindow : IDisposable
|
||||||
if (_remoteDeadReckon.TryGetValue(update.Guid, out var remoteMot))
|
if (_remoteDeadReckon.TryGetValue(update.Guid, out var remoteMot))
|
||||||
{
|
{
|
||||||
remoteMot.ServerMoveToActive = update.MotionState.IsServerControlledMoveTo;
|
remoteMot.ServerMoveToActive = update.MotionState.IsServerControlledMoveTo;
|
||||||
if (remoteMot.ServerMoveToActive && !IsPlayerGuid(update.Guid))
|
|
||||||
{
|
|
||||||
// Retail MoveTo packets already carry enough state
|
|
||||||
// for CMotionInterp to drive velocity. A velocity
|
|
||||||
// inferred from sparse UpdatePosition packets lags
|
|
||||||
// during combat chases and visibly under-speeds the
|
|
||||||
// run cycle until the next hard snap.
|
|
||||||
remoteMot.HasServerVelocity = false;
|
|
||||||
remoteMot.ServerVelocity = System.Numerics.Vector3.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forward axis (Ready / WalkForward / RunForward / WalkBackward).
|
// Forward axis (Ready / WalkForward / RunForward / WalkBackward).
|
||||||
remoteMot.Motion.DoInterpretedMotion(
|
remoteMot.Motion.DoInterpretedMotion(
|
||||||
|
|
@ -2685,6 +2676,11 @@ public sealed class GameWindow : IDisposable
|
||||||
if (IsPlayerGuid(serverGuid)) return;
|
if (IsPlayerGuid(serverGuid)) return;
|
||||||
if (rm.Airborne) return;
|
if (rm.Airborne) return;
|
||||||
if (ae.Sequencer is null) return;
|
if (ae.Sequencer is null) return;
|
||||||
|
// MoveTo packets already seeded the retail speed/runRate cycle.
|
||||||
|
// Keep UpdatePosition-derived velocity for render position only;
|
||||||
|
// using it to choose the cycle reverts fast chases back to slow
|
||||||
|
// velocity-estimated animation.
|
||||||
|
if (rm.ServerMoveToActive) return;
|
||||||
|
|
||||||
var plan = AcDream.Core.Physics.ServerControlledLocomotion
|
var plan = AcDream.Core.Physics.ServerControlledLocomotion
|
||||||
.PlanFromVelocity(velocity);
|
.PlanFromVelocity(velocity);
|
||||||
|
|
@ -2771,7 +2767,6 @@ public sealed class GameWindow : IDisposable
|
||||||
System.Numerics.Vector3? serverVelocity = update.Velocity;
|
System.Numerics.Vector3? serverVelocity = update.Velocity;
|
||||||
if (serverVelocity is null
|
if (serverVelocity is null
|
||||||
&& !IsPlayerGuid(update.Guid)
|
&& !IsPlayerGuid(update.Guid)
|
||||||
&& !rmState.ServerMoveToActive
|
|
||||||
&& rmState.LastServerPosTime > 0.0)
|
&& rmState.LastServerPosTime > 0.0)
|
||||||
{
|
{
|
||||||
double elapsed = nowSec - rmState.LastServerPosTime;
|
double elapsed = nowSec - rmState.LastServerPosTime;
|
||||||
|
|
@ -5047,6 +5042,15 @@ public sealed class GameWindow : IDisposable
|
||||||
rm.Body.Velocity = rm.ServerVelocity;
|
rm.Body.Velocity = rm.ServerVelocity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!IsPlayerGuid(serverGuid) && rm.ServerMoveToActive)
|
||||||
|
{
|
||||||
|
// We only parse enough of MoveTo to recover retail
|
||||||
|
// animation speed. Do not let apply_current_movement
|
||||||
|
// extrapolate position from an incomplete target
|
||||||
|
// solver; hold until the next UpdatePosition-derived
|
||||||
|
// velocity arrives.
|
||||||
|
rm.Body.Velocity = System.Numerics.Vector3.Zero;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rm.Motion.apply_current_movement(cancelMoveTo: false, allowJump: false);
|
rm.Motion.apply_current_movement(cancelMoveTo: false, allowJump: false);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue