fix: stop creature run animation when movement interpolation completes

Creatures were stuck in Run/Walk animation during the dead-reckoning
overrun window (up to 2x movement duration). The animation check used
isEntityMoving() which stays true through dead reckoning, causing
creatures to "run in place" after reaching their destination.

Add isActivelyMoving() which is true only during the active
interpolation phase (moveElapsed < moveDuration), and use it for
animation state transitions. Dead reckoning still works for position
extrapolation — only the animation now correctly stops at arrival.
This commit is contained in:
Kelsi 2026-03-18 08:22:50 -07:00
parent 0b33bcbe53
commit 18c06d98ac
2 changed files with 12 additions and 1 deletions

View file

@ -135,6 +135,13 @@ public:
bool isEntityMoving() const { return isMoving_; }
/// True only during the active interpolation phase (before reaching destination).
/// Unlike isEntityMoving(), this does NOT include the dead-reckoning overrun window,
/// so animations (Run/Walk) should use this to avoid "running in place" after arrival.
bool isActivelyMoving() const {
return isMoving_ && moveElapsed_ < moveDuration_;
}
// Returns the latest server-authoritative position: destination if moving, current if not.
// Unlike getX/Y/Z (which only update via updateMovement), this always reflects the
// last known server position regardless of distance culling.

View file

@ -1647,7 +1647,11 @@ void Application::update(float deltaTime) {
// startMoveTo() in handleMonsterMove, regardless of distance-cull.
// This correctly detects movement for distant creatures (> 150u)
// where updateMovement() is not called and getX/Y/Z() stays stale.
const bool entityIsMoving = entity->isEntityMoving();
// Use isActivelyMoving() (not isEntityMoving()) so the
// Run/Walk animation stops when the creature reaches its
// destination, rather than persisting through the dead-
// reckoning overrun window.
const bool entityIsMoving = entity->isActivelyMoving();
const bool isMovingNow = !deadOrCorpse && (entityIsMoving || planarDist > 0.03f || dz > 0.08f);
if (deadOrCorpse || largeCorrection) {
charRenderer->setInstancePosition(instanceId, renderPos);