From 91c6eef9674918fb3755fe882e7c6255b48fea36 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sat, 28 Mar 2026 15:50:13 -0700 Subject: [PATCH] fix: suspend gravity for 10s after world entry to prevent WMO fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stormwind WMO collision takes 25+ seconds to fully load. The warmup ground check couldn't detect the WMO floor because collision data wasn't finalized yet. Player spawned and immediately fell through the unloaded WMO floor into the terrain below (Dun Morogh). New approach: suspendGravityFor(10s) after world entry. Gravity is disabled (Z position frozen) until either: 1. A floor is detected by the collision system (gravity resumes instantly) 2. The 10-second timer expires (gravity resumes as fallback) This handles the case where WMO collision loads during the first few seconds of gameplay — the player hovers at spawn Z until the floor appears, then lands normally. Also fixes faction language for chat (ORCISH for Horde, COMMON for Alliance) and adds SMSG_MESSAGECHAT diagnostic logging. --- include/rendering/camera_controller.hpp | 3 +++ src/core/application.cpp | 3 +++ src/game/chat_handler.cpp | 5 ++++- src/rendering/camera_controller.cpp | 15 +++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) 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; }