From 5cc6effeecc464ea6d5d60962574e903ba97b1c9 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Tue, 10 Feb 2026 19:59:01 -0800 Subject: [PATCH] Fix mount idle fidget animations playing fully without interruption Fidgets were stuttering because normal animation updates immediately overrode them. Now tracks active fidget and prevents normal animation updates until fidget completes. Changes: - Added mountActiveFidget_ to track currently playing fidget animation - Check fidget completion using getAnimationState before allowing normal updates - Only trigger new fidgets when no fidget is active - Cancel active fidget on movement - Expanded fidget search criteria: duration up to 3000ms, ID range 1-20 - Added debug logging to show discovered fidgets and when they complete --- include/rendering/renderer.hpp | 1 + src/rendering/renderer.cpp | 30 ++++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/include/rendering/renderer.hpp b/include/rendering/renderer.hpp index a24379d7..a82024ca 100644 --- a/include/rendering/renderer.hpp +++ b/include/rendering/renderer.hpp @@ -330,6 +330,7 @@ private: MountAnimSet mountAnims_; // Cached animation IDs for current mount float mountIdleFidgetTimer_ = 0.0f; // Timer for random idle fidgets float mountIdleSoundTimer_ = 0.0f; // Timer for ambient idle sounds + uint32_t mountActiveFidget_ = 0; // Currently playing fidget animation ID (0 = none) bool taxiFlight_ = false; bool terrainEnabled = true; diff --git a/src/rendering/renderer.cpp b/src/rendering/renderer.cpp index 2968f16d..cd5fad6d 100644 --- a/src/rendering/renderer.cpp +++ b/src/rendering/renderer.cpp @@ -715,12 +715,15 @@ void Renderer::setMounted(uint32_t mountInstId, uint32_t mountDisplayId, float h // Discover idle fidget animations (head turn, tail swish, weight shift) mountAnims_.fidgets.clear(); + core::Logger::getInstance().info("Scanning for fidget animations in ", sequences.size(), " sequences"); for (const auto& seq : sequences) { bool isLoop = (seq.flags & 0x01) == 0; - if (!isLoop && seq.duration >= 500 && seq.duration <= 1500 && - std::abs(seq.movingSpeed) < 0.1f && seq.id >= 1 && seq.id <= 10) { - // Likely a fidget: non-looping, short, stationary, low ID near stand + // Relaxed criteria: non-looping, 500-3000ms, stationary, ID 1-20 + if (!isLoop && seq.duration >= 500 && seq.duration <= 3000 && + std::abs(seq.movingSpeed) < 0.1f && seq.id >= 1 && seq.id <= 20) { + // Likely a fidget: non-looping, short, stationary, low ID mountAnims_.fidgets.push_back(seq.id); + core::Logger::getInstance().info(" Found fidget: id=", seq.id, " duration=", seq.duration, "ms"); } } @@ -1041,8 +1044,21 @@ void Renderer::updateCharacterAnimation() { } } + // Check if active fidget has completed + if (mountActiveFidget_ != 0) { + uint32_t curAnim = 0; + float curTime = 0.0f, curDur = 0.0f; + if (characterRenderer->getAnimationState(mountInstanceId_, curAnim, curTime, curDur)) { + // If animation changed or completed, clear active fidget + if (curAnim != mountActiveFidget_ || curTime >= curDur * 0.95f) { + mountActiveFidget_ = 0; + LOG_INFO("Mount fidget completed"); + } + } + } + // Idle fidgets: random one-shot animations when standing still - if (!moving && mountAction_ == MountAction::None && !mountAnims_.fidgets.empty()) { + if (!moving && mountAction_ == MountAction::None && mountActiveFidget_ == 0 && !mountAnims_.fidgets.empty()) { mountIdleFidgetTimer_ += lastDeltaTime_; static float nextFidgetTime = 6.0f + (rand() % 7); // 6-12 seconds @@ -1053,6 +1069,7 @@ void Renderer::updateCharacterAnimation() { uint32_t fidgetAnim = mountAnims_.fidgets[dist(rng)]; characterRenderer->playAnimation(mountInstanceId_, fidgetAnim, false); + mountActiveFidget_ = fidgetAnim; // Track active fidget mountIdleFidgetTimer_ = 0.0f; nextFidgetTime = 6.0f + (rand() % 7); // Randomize next fidget time @@ -1060,6 +1077,7 @@ void Renderer::updateCharacterAnimation() { } } else if (moving) { mountIdleFidgetTimer_ = 0.0f; // Reset timer when moving + mountActiveFidget_ = 0; // Cancel any active fidget } // Idle ambient sounds: random snorts/stomps/breaths when standing still @@ -1076,8 +1094,8 @@ void Renderer::updateCharacterAnimation() { mountIdleSoundTimer_ = 0.0f; // Reset timer when moving } - // Only update animation if it changed and we're not in an action sequence - if (mountAction_ == MountAction::None && (!haveMountState || curMountAnim != mountAnimId)) { + // Only update animation if it changed and we're not in an action sequence or playing a fidget + if (mountAction_ == MountAction::None && mountActiveFidget_ == 0 && (!haveMountState || curMountAnim != mountAnimId)) { bool loop = true; // Normal movement animations loop characterRenderer->playAnimation(mountInstanceId_, mountAnimId, loop); }