diff --git a/include/rendering/camera_controller.hpp b/include/rendering/camera_controller.hpp index e0cdcfe3..3e2e46f9 100644 --- a/include/rendering/camera_controller.hpp +++ b/include/rendering/camera_controller.hpp @@ -126,6 +126,7 @@ public: void setFacingYaw(float yaw) { facingYaw = yaw; } // For taxi/scripted movement void clearMovementInputs(); void suppressMovementFor(float seconds) { movementSuppressTimer_ = seconds; } + void suspendGravityFor(float seconds) { gravitySuspendTimer_ = seconds; } // Auto-follow: walk toward a target position each frame (WoW /follow). // The caller updates *targetPos every frame with the followed entity's render position. @@ -270,6 +271,8 @@ private: // Movement input suppression (after teleport/portal, ignore held keys) float movementSuppressTimer_ = 0.0f; + // Gravity suspension (after world entry, hold Z until ground detected) + float gravitySuspendTimer_ = 0.0f; // State bool enabled = true; diff --git a/src/core/application.cpp b/src/core/application.cpp index 67d01c81..41dbf211 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -2175,6 +2175,7 @@ void Application::update(float deltaTime) { if (renderer && renderer->getCameraController()) { renderer->getCameraController()->clearMovementInputs(); renderer->getCameraController()->suppressMovementFor(1.0f); + renderer->getCameraController()->suspendGravityFor(10.0f); } loadOnlineWorldTerrain(entry.mapId, entry.x, entry.y, entry.z); } @@ -2419,6 +2420,7 @@ void Application::setupUICallbacks() { if (ft) *ft = renderPos; renderer->getCameraController()->clearMovementInputs(); renderer->getCameraController()->suppressMovementFor(1.0f); + renderer->getCameraController()->suspendGravityFor(10.0f); } worldEntryMovementGraceTimer_ = 2.0f; taxiLandingClampTimer_ = 0.0f; @@ -2457,6 +2459,7 @@ void Application::setupUICallbacks() { if (ft) *ft = renderPos; renderer->getCameraController()->clearMovementInputs(); renderer->getCameraController()->suppressMovementFor(1.0f); + renderer->getCameraController()->suspendGravityFor(10.0f); } pendingWorldEntry_ = PendingWorldEntry{mapId, x, y, z}; return; diff --git a/src/game/chat_handler.cpp b/src/game/chat_handler.cpp index 93105454..1dd57e56 100644 --- a/src/game/chat_handler.cpp +++ b/src/game/chat_handler.cpp @@ -162,9 +162,12 @@ void ChatHandler::handleMessageChat(network::Packet& packet) { MessageChatData data; if (!owner_.packetParsers_->parseMessageChat(packet, data)) { - LOG_WARNING("Failed to parse SMSG_MESSAGECHAT"); + LOG_WARNING("Failed to parse SMSG_MESSAGECHAT, size=", packet.getSize()); return; } + LOG_WARNING("SMSG_MESSAGECHAT: type=", static_cast(data.type), + " sender='", data.senderName, "' msg='", + data.message.substr(0, 60), "'"); // Skip server echo of our own messages (we already added a local echo) if (data.senderGuid == owner_.playerGuid && data.senderGuid != 0) { diff --git a/src/rendering/camera_controller.cpp b/src/rendering/camera_controller.cpp index 8b23a8bf..c31ff01c 100644 --- a/src/rendering/camera_controller.cpp +++ b/src/rendering/camera_controller.cpp @@ -371,10 +371,23 @@ void CameraController::update(float deltaTime) { facingYaw = yaw; } + // Tick down gravity suspension timer (used after world entry to prevent + // falling through WMO floors before collision is loaded) + if (gravitySuspendTimer_ > 0.0f) { + gravitySuspendTimer_ -= deltaTime; + } + // Select physics constants based on mode float gravity = useWoWSpeed ? WOW_GRAVITY : GRAVITY; float jumpVel = useWoWSpeed ? WOW_JUMP_VELOCITY : JUMP_VELOCITY; + // Suspend gravity after world entry — hold Z position until timer expires + // OR a floor is detected. This prevents falling through unloaded WMO floors. + if (gravitySuspendTimer_ > 0.0f) { + gravity = 0.0f; + verticalVelocity = 0.0f; + } + // Calculate movement speed based on direction and modifiers float speed; if (useWoWSpeed) { @@ -1093,6 +1106,8 @@ void CameraController::update(float deltaTime) { if (groundH) { cachedFloorHeight_ = *groundH; hasCachedFloor_ = true; + // Ground found — cancel gravity suspension (WMO floor loaded) + if (gravitySuspendTimer_ > 0.0f) gravitySuspendTimer_ = 0.0f; } else { hasCachedFloor_ = false; }