diff --git a/include/core/application.hpp b/include/core/application.hpp index a1168ba4..af7ece0b 100644 --- a/include/core/application.hpp +++ b/include/core/application.hpp @@ -187,7 +187,9 @@ private: std::unordered_map creatureInstances_; // guid → render instanceId std::unordered_map creatureModelIds_; // guid → loaded modelId std::unordered_map creatureRenderPosCache_; // guid -> last synced render position - std::unordered_map creatureWasMoving_; // guid -> previous-frame movement state + std::unordered_map creatureWasMoving_; // guid -> previous-frame movement state + std::unordered_map creatureWasSwimming_; // guid -> previous-frame swim state (for anim transition detection) + std::unordered_map creatureWasFlying_; // guid -> previous-frame flying state (for anim transition detection) std::unordered_map creatureSwimmingState_; // guid -> currently in swim mode (SWIMMING flag) std::unordered_map creatureWalkingState_; // guid -> walking (WALKING flag, selects Walk(4) vs Run(5)) std::unordered_map creatureFlyingState_; // guid -> currently flying (FLYING flag) diff --git a/src/core/application.cpp b/src/core/application.cpp index 27fba61e..96838e29 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -750,6 +750,8 @@ void Application::logoutToLogin() { creatureWeaponsAttached_.clear(); creatureWeaponAttachAttempts_.clear(); creatureWasMoving_.clear(); + creatureWasSwimming_.clear(); + creatureWasFlying_.clear(); creatureSwimmingState_.clear(); creatureWalkingState_.clear(); creatureFlyingState_.clear(); @@ -1487,9 +1489,18 @@ void Application::update(float deltaTime) { const bool isSwimmingNow = creatureSwimmingState_.count(guid) > 0; const bool isWalkingNow = creatureWalkingState_.count(guid) > 0; const bool isFlyingNow = creatureFlyingState_.count(guid) > 0; - bool prevMoving = creatureWasMoving_[guid]; - if (isMovingNow != prevMoving) { - creatureWasMoving_[guid] = isMovingNow; + bool prevMoving = creatureWasMoving_[guid]; + bool prevSwimming = creatureWasSwimming_[guid]; + bool prevFlying = creatureWasFlying_[guid]; + // Trigger animation update on any locomotion-state transition, not just + // moving/idle — e.g. creature lands while still moving → FlyForward→Run. + const bool stateChanged = (isMovingNow != prevMoving) || + (isSwimmingNow != prevSwimming) || + (isFlyingNow != prevFlying); + if (stateChanged) { + creatureWasMoving_[guid] = isMovingNow; + creatureWasSwimming_[guid] = isSwimmingNow; + creatureWasFlying_[guid] = isFlyingNow; uint32_t curAnimId = 0; float curT = 0.0f, curDur = 0.0f; bool gotState = charRenderer->getAnimationState(instanceId, curAnimId, curT, curDur); if (!gotState || curAnimId != 1 /*Death*/) { @@ -6945,6 +6956,9 @@ void Application::despawnOnlinePlayer(uint64_t guid) { pendingOnlinePlayerEquipment_.erase(guid); creatureSwimmingState_.erase(guid); creatureWalkingState_.erase(guid); + creatureFlyingState_.erase(guid); + creatureWasSwimming_.erase(guid); + creatureWasFlying_.erase(guid); } void Application::spawnOnlineGameObject(uint64_t guid, uint32_t entry, uint32_t displayId, float x, float y, float z, float orientation) { @@ -8538,8 +8552,11 @@ void Application::despawnOnlineCreature(uint64_t guid) { creatureWeaponsAttached_.erase(guid); creatureWeaponAttachAttempts_.erase(guid); creatureWasMoving_.erase(guid); + creatureWasSwimming_.erase(guid); + creatureWasFlying_.erase(guid); creatureSwimmingState_.erase(guid); creatureWalkingState_.erase(guid); + creatureFlyingState_.erase(guid); LOG_DEBUG("Despawned creature: guid=0x", std::hex, guid, std::dec); }