From 267825bbcb558da922784ee17d549caffefb2086 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 18 Feb 2026 03:56:12 -0800 Subject: [PATCH] Use speed-based walk/run selection for NPC movement - choose run only when movement speed is above threshold - prefer walk for duration-less synthesized movement deltas - keep animation fallback behavior when specific sequence is unavailable --- src/rendering/character_renderer.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/rendering/character_renderer.cpp b/src/rendering/character_renderer.cpp index 830fa9a1..31216866 100644 --- a/src/rendering/character_renderer.cpp +++ b/src/rendering/character_renderer.cpp @@ -1706,15 +1706,21 @@ void CharacterRenderer::moveInstanceTo(uint32_t instanceId, const glm::vec3& des // Don't move dead instances (corpses shouldn't slide around) if (inst.isDead) return; - auto pickMoveAnim = [&]() -> uint32_t { - // Prefer run when available to avoid "gliding with attack pose" on chase. - if (hasAnimation(instanceId, 5)) return 5; // Run - if (hasAnimation(instanceId, 4)) return 4; // Walk + auto pickMoveAnim = [&](bool preferRun) -> uint32_t { + // Choose movement anim from estimated speed; fall back if missing. + if (preferRun) { + if (hasAnimation(instanceId, 5)) return 5; // Run + if (hasAnimation(instanceId, 4)) return 4; // Walk + } else { + if (hasAnimation(instanceId, 4)) return 4; // Walk + if (hasAnimation(instanceId, 5)) return 5; // Run + } return 0; }; float planarDist = glm::length(glm::vec2(destination.x - inst.position.x, destination.y - inst.position.y)); + bool synthesizedDuration = false; if (durationSeconds <= 0.0f) { if (planarDist < 0.01f) { // Stop at current location. @@ -1728,6 +1734,7 @@ void CharacterRenderer::moveInstanceTo(uint32_t instanceId, const glm::vec3& des // Some cores send movement-only deltas without spline duration. // Synthesize a tiny duration so movement anim/rotation still updates. durationSeconds = std::clamp(planarDist / 7.0f, 0.05f, 0.20f); + synthesizedDuration = true; } inst.moveStart = inst.position; @@ -1744,7 +1751,10 @@ void CharacterRenderer::moveInstanceTo(uint32_t instanceId, const glm::vec3& des } // Play movement animation while moving. - uint32_t moveAnim = pickMoveAnim(); + // Prefer run only when speed is clearly above normal walk pace. + float moveSpeed = planarDist / std::max(durationSeconds, 0.001f); + bool preferRun = (!synthesizedDuration && moveSpeed >= 4.5f); + uint32_t moveAnim = pickMoveAnim(preferRun); if (moveAnim != 0 && inst.currentAnimationId != moveAnim) { playAnimation(instanceId, moveAnim, true); }