From 5a8ab87a78a441eef502ac721a5c37107f6366e2 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sat, 28 Mar 2026 11:34:07 -0700 Subject: [PATCH] fix: warmup checks WMO floor proximity, not just terrain existence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stormwind players stand on WMO floors ~95m above terrain. The previous check only tested if terrain existed at the spawn XY (it did — far below). Now checks WMO floor first, then terrain, requiring the ground to be within 15 units of spawn Z. Falls back to tile count after 10s. Also adds diagnostic logging for useItemBySlot (hearthstone debug). --- src/core/application.cpp | 29 ++++++++++++++++++----------- src/game/inventory_handler.cpp | 5 +++++ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/core/application.cpp b/src/core/application.cpp index 7b51c8b1..4efc3557 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -5327,19 +5327,26 @@ void Application::loadOnlineWorldTerrain(uint32_t mapId, float x, float y, float glm::vec3(x, y, z)); float rx = renderSpawn.x, ry = renderSpawn.y, rz = renderSpawn.z; - // Check terrain - if (auto* tm = renderer->getTerrainManager()) { - if (tm->getHeightAt(rx, ry).has_value()) groundReady = true; - } - // Check WMO floor (cities, buildings) - if (!groundReady) { - if (auto* wmo = renderer->getWMORenderer()) { - if (wmo->getFloorHeight(rx, ry, rz + 5.0f).has_value()) groundReady = true; + // Check WMO floor FIRST (cities like Stormwind stand on WMO floors). + // Terrain exists below WMOs but at the wrong height. + if (auto* wmo = renderer->getWMORenderer()) { + auto wmoH = wmo->getFloorHeight(rx, ry, rz + 5.0f); + if (wmoH.has_value() && std::abs(*wmoH - rz) < 15.0f) { + groundReady = true; } } - // After minimum warmup, also accept if enough terrain tiles are loaded - // (player may be on M2 collision or other surface) - if (!groundReady && elapsed >= 8.0f) { + // Check terrain — but only if it's close to spawn Z (within 15 units). + // Terrain far below a WMO city doesn't count as ground. + if (!groundReady) { + if (auto* tm = renderer->getTerrainManager()) { + auto tH = tm->getHeightAt(rx, ry); + if (tH.has_value() && std::abs(*tH - rz) < 15.0f) { + groundReady = true; + } + } + } + // After 10s, accept any loaded terrain (fallback for unusual spawns) + if (!groundReady && elapsed >= 10.0f) { if (auto* tm = renderer->getTerrainManager()) { groundReady = (tm->getLoadedTileCount() >= 4); } diff --git a/src/game/inventory_handler.cpp b/src/game/inventory_handler.cpp index 5c468306..a7602b5d 100644 --- a/src/game/inventory_handler.cpp +++ b/src/game/inventory_handler.cpp @@ -1086,12 +1086,17 @@ void InventoryHandler::useItemBySlot(int backpackIndex) { break; } } + LOG_WARNING("useItemBySlot: item='", slot.item.name, "' entry=", slot.item.itemId, + " guid=0x", std::hex, itemGuid, std::dec, + " spellId=", useSpellId, " spellCount=", info->spells.size()); } auto packet = owner_.packetParsers_ ? owner_.packetParsers_->buildUseItem(0xFF, static_cast(23 + backpackIndex), itemGuid, useSpellId) : UseItemPacket::build(0xFF, static_cast(23 + backpackIndex), itemGuid, useSpellId); owner_.socket->send(packet); } else if (itemGuid == 0) { + LOG_WARNING("useItemBySlot: itemGuid=0 for item='", slot.item.name, + "' entry=", slot.item.itemId, " — cannot use"); owner_.addSystemChatMessage("Cannot use that item right now."); } }