From 53639f9592fe88bf7aafee1b6a32237cd5273d50 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sun, 5 Apr 2026 17:52:18 -0700 Subject: [PATCH] fix(animation): re-probe capabilities on melee swing, add combat diagnostics If the capability probe ran before the model was fully loaded, all melee animation IDs would be 0 and auto-attack swings would silently fall back to STAND (no visible animation). Now re-probes when a melee swing fires but hasMelee is false. Added WARNING-level logging to triggerMeleeSwing and CombatFSM to diagnose the night elf stationary combat animation issue. --- src/rendering/animation/combat_fsm.cpp | 6 +++++- src/rendering/animation_controller.cpp | 26 +++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/rendering/animation/combat_fsm.cpp b/src/rendering/animation/combat_fsm.cpp index 997fb938..67e301fe 100644 --- a/src/rendering/animation/combat_fsm.cpp +++ b/src/rendering/animation/combat_fsm.cpp @@ -1,6 +1,7 @@ #include "rendering/animation/combat_fsm.hpp" #include "rendering/animation/animation_ids.hpp" #include "game/inventory.hpp" +#include "core/logger.hpp" namespace wowee { namespace rendering { @@ -378,7 +379,10 @@ AnimOutput CombatFSM::resolve(const Input& in, const AnimCapabilitySet& caps, animId = caps.resolvedMelee1H; } } - if (animId == 0) animId = anim::STAND; // Melee must play something + if (animId == 0) { + LOG_WARNING("CombatFSM: MELEE_SWING resolved animId=0, falling back to STAND"); + animId = anim::STAND; + } loop = false; break; diff --git a/src/rendering/animation_controller.cpp b/src/rendering/animation_controller.cpp index 2ee06414..8cdf6d0a 100644 --- a/src/rendering/animation_controller.cpp +++ b/src/rendering/animation_controller.cpp @@ -245,6 +245,18 @@ void AnimationController::triggerMeleeSwing() { if (durationSec < 0.25f) durationSec = 0.25f; if (durationSec > 1.0f) durationSec = 1.0f; meleeSwingTimer_ = durationSec; + + // Diagnostic: log the melee swing trigger with key state + const auto& caps = characterAnimator_.getCapabilities(); + auto* cc = renderer_->getCameraController(); + LOG_WARNING("triggerMeleeSwing: meleeAnimId=", meleeAnimId_, + " dur=", durationSec, + " caps.melee1H=", caps.resolvedMelee1H, + " caps.melee2H=", caps.resolvedMelee2H, + " caps.meleeUnarmed=", caps.resolvedMeleeUnarmed, + " grounded=", (cc ? cc->isGrounded() : false), + " probed=", capabilitiesProbed_); + if (renderer_->getAudioCoordinator()->getActivitySoundManager()) { renderer_->getAudioCoordinator()->getActivitySoundManager()->playMeleeSwing(); } @@ -1043,9 +1055,17 @@ void AnimationController::updateCharacterAnimation() { auto* cameraController = renderer_->getCameraController(); uint32_t characterInstanceId = renderer_->getCharacterInstanceId(); - // Lazy probe: populate capability set once per model - if (!capabilitiesProbed_ && characterRenderer && characterInstanceId != 0) { - probeCapabilities(); + // Lazy probe: populate capability set once per model. + // Re-probe if melee capabilities are missing (model may not have been fully + // loaded on the first probe attempt). + if (characterRenderer && characterInstanceId != 0) { + if (!capabilitiesProbed_) { + probeCapabilities(); + } else if (meleeSwingTimer_ > 0.0f && !characterAnimator_.getCapabilities().hasMelee) { + LOG_WARNING("Re-probing capabilities: melee swing active but hasMelee=false"); + capabilitiesProbed_ = false; + probeCapabilities(); + } } // When mounted, delegate to MountFSM and handle positioning