fix: hearthstone from action bar, far teleport loading screen

Action bar hearthstone: the slot was type SPELL (spell 8690) not ITEM.
castSpell sends CMSG_CAST_SPELL which the server rejects for item-use
spells. Now detects item-use spells via getItemIdForSpell() and routes
through useItemById() instead, sending CMSG_USE_ITEM correctly.

Far same-map teleport: hearthstone on the same continent (e.g., Westfall
→ Stormwind on Azeroth) skipped the loading screen, so the player fell
through unloaded terrain. Now triggers a full world reload with loading
screen for teleports > 500 units, with the warmup ground check ensuring
WMO floors are loaded before spawning.
This commit is contained in:
Kelsi 2026-03-28 14:55:58 -07:00
parent 4e709692f1
commit 11571c582b
4 changed files with 54 additions and 6 deletions

View file

@ -2436,13 +2436,25 @@ void Application::setupUICallbacks() {
return;
}
// Same-map teleport (taxi landing, GM teleport on same continent):
// just update position, let terrain streamer handle tile loading incrementally.
// A full reload is only needed on first entry or map change.
// Same-map teleport (taxi landing, GM teleport, hearthstone on same continent):
if (mapId == loadedMapId_ && renderer && renderer->getTerrainManager()) {
LOG_INFO("Same-map teleport (map ", mapId, "), skipping full world reload");
// Check if teleport is far enough to need terrain loading (>500 render units)
glm::vec3 oldPos = renderer->getCharacterPosition();
glm::vec3 canonical = core::coords::serverToCanonical(glm::vec3(x, y, z));
glm::vec3 renderPos = core::coords::canonicalToRender(canonical);
float teleportDistSq = glm::dot(renderPos - oldPos, renderPos - oldPos);
bool farTeleport = (teleportDistSq > 500.0f * 500.0f);
if (farTeleport) {
// Far same-map teleport (hearthstone, etc.): do a full world reload
// with loading screen to prevent falling through unloaded terrain.
LOG_WARNING("Far same-map teleport (dist=", std::sqrt(teleportDistSq),
"), triggering full world reload with loading screen");
loadOnlineWorldTerrain(mapId, x, y, z);
return;
}
LOG_INFO("Same-map teleport (map ", mapId, "), skipping full world reload");
// canonical and renderPos already computed above for distance check
renderer->getCharacterPosition() = renderPos;
if (renderer->getCameraController()) {
auto* ft = renderer->getCameraController()->getFollowTargetMutable();