From 5b130cfb4253a94c08ff807e7f28e988651d2476 Mon Sep 17 00:00:00 2001 From: Golrag Date: Sat, 25 May 2024 21:02:41 +0200 Subject: Core/Players: Allow targeting a specific transport during teleports --- src/server/game/Handlers/MovementHandler.cpp | 65 ++++++++++++++++++---------- 1 file changed, 42 insertions(+), 23 deletions(-) (limited to 'src/server/game/Handlers/MovementHandler.cpp') diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 6a375051013..97f9cda44c8 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -58,34 +58,33 @@ void WorldSession::HandleMoveWorldportAck() player->SetSemaphoreTeleportFar(false); // get the teleport destination - WorldLocation const& loc = player->GetTeleportDest(); + TeleportLocation const& loc = player->GetTeleportDest(); // possible errors in the coordinate validity check - if (!MapManager::IsValidMapCoord(loc)) + if (!MapManager::IsValidMapCoord(loc.Location)) { LogoutPlayer(false); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting - MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId()); + MapEntry const* mEntry = sMapStore.LookupEntry(loc.Location.GetMapId()); // reset instance validity, except if going to an instance inside an instance if (player->m_InstanceValid == false && !mEntry->IsDungeon()) player->m_InstanceValid = true; Map* oldMap = player->GetMap(); - Map* newMap = GetPlayer()->GetTeleportDestInstanceId() ? - sMapMgr->FindMap(loc.GetMapId(), *GetPlayer()->GetTeleportDestInstanceId()) : - sMapMgr->CreateMap(loc.GetMapId(), GetPlayer()); + Map* newMap = loc.InstanceId ? + sMapMgr->FindMap(loc.Location.GetMapId(), *loc.InstanceId) : + sMapMgr->CreateMap(loc.Location.GetMapId(), GetPlayer()); - MovementInfo::TransportInfo transportInfo = player->m_movementInfo.transport; if (TransportBase* transport = player->GetTransport()) transport->RemovePassenger(player); if (player->IsInWorld()) { - TC_LOG_ERROR("network", "{} {} is still in world when teleported from map {} ({}) to new map {} ({})", player->GetGUID().ToString(), player->GetName(), oldMap->GetMapName(), oldMap->GetId(), newMap ? newMap->GetMapName() : "Unknown", loc.GetMapId()); + TC_LOG_ERROR("network", "{} {} is still in world when teleported from map {} ({}) to new map {} ({})", player->GetGUID().ToString(), player->GetName(), oldMap->GetMapName(), oldMap->GetId(), newMap ? newMap->GetMapName() : "Unknown", loc.Location.GetMapId()); oldMap->RemovePlayerFromMap(player, false); } @@ -94,13 +93,13 @@ void WorldSession::HandleMoveWorldportAck() // while the player is in transit, for example the map may get full if (!newMap || newMap->CannotEnter(player)) { - TC_LOG_ERROR("network", "Map {} ({}) could not be created for player {} ({}), porting player to homebind", loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown", player->GetGUID().ToString(), player->GetName()); + TC_LOG_ERROR("network", "Map {} ({}) could not be created for player {} ({}), porting player to homebind", loc.Location.GetMapId(), newMap ? newMap->GetMapName() : "Unknown", player->GetGUID().ToString(), player->GetName()); player->TeleportTo(player->m_homebind); return; } - float z = loc.GetPositionZ() + player->GetHoverOffset(); - player->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation()); + float z = loc.Location.GetPositionZ() + player->GetHoverOffset(); + player->Relocate(loc.Location.GetPositionX(), loc.Location.GetPositionY(), z, loc.Location.GetOrientation()); player->SetFallInformation(0, player->GetPositionZ()); player->ResetMap(); @@ -114,17 +113,25 @@ void WorldSession::HandleMoveWorldportAck() if (!seamlessTeleport) player->SendInitialPacketsBeforeAddToMap(); - // move player between transport copies on each map - if (Transport* newTransport = newMap->GetTransport(transportInfo.guid)) + if (player->m_teleport_dest.TransportGuid) { - player->m_movementInfo.transport = transportInfo; - newTransport->AddPassenger(player); + if (Transport* newTransport = newMap->GetTransport(*player->m_teleport_dest.TransportGuid)) + { + newTransport->AddPassenger(player); + player->m_movementInfo.transport.pos.Relocate(loc.Location); + float x, y, z, o; + loc.Location.GetPosition(x, y, z, o); + newTransport->CalculatePassengerPosition(x, y, z, &o); + player->Relocate(x, y, z, o); + } } + else if (TransportBase* transport = player->GetTransport()) + transport->RemovePassenger(player); if (!player->GetMap()->AddPlayerToMap(player, !seamlessTeleport)) { TC_LOG_ERROR("network", "WORLD: failed to teleport player {} {} to map {} ({}) because of unknown reason!", - player->GetName(), player->GetGUID().ToString(), loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown"); + player->GetName(), player->GetGUID().ToString(), loc.Location.GetMapId(), newMap ? newMap->GetMapName() : "Unknown"); player->ResetMap(); player->SetMap(oldMap); player->TeleportTo(player->m_homebind); @@ -245,18 +252,18 @@ void WorldSession::HandleSuspendTokenResponse(WorldPackets::Movement::SuspendTok if (!_player->IsBeingTeleportedFar()) return; - WorldLocation const& loc = GetPlayer()->GetTeleportDest(); + TeleportLocation const& loc = GetPlayer()->GetTeleportDest(); - if (sMapStore.AssertEntry(loc.GetMapId())->IsDungeon()) + if (sMapStore.AssertEntry(loc.Location.GetMapId())->IsDungeon()) { WorldPackets::Instance::UpdateLastInstance updateLastInstance; - updateLastInstance.MapID = loc.GetMapId(); + updateLastInstance.MapID = loc.Location.GetMapId(); SendPacket(updateLastInstance.Write()); } WorldPackets::Movement::NewWorld packet; - packet.MapID = loc.GetMapId(); - packet.Loc.Pos = loc; + packet.MapID = loc.Location.GetMapId(); + packet.Loc.Pos = loc.Location; packet.Reason = !_player->IsBeingTeleportedSeamlessly() ? NEW_WORLD_NORMAL : NEW_WORLD_SEAMLESS; SendPacket(packet.Write()); @@ -280,9 +287,21 @@ void WorldSession::HandleMoveTeleportAck(WorldPackets::Movement::MoveTeleportAck uint32 old_zone = plMover->GetZoneId(); - WorldLocation const& dest = plMover->GetTeleportDest(); + TeleportLocation const& dest = plMover->GetTeleportDest(); + + float x, y, z, o; + dest.Location.GetPosition(x, y, z, o); + if (dest.TransportGuid) + { + if (Transport* transport = plMover->GetMap()->GetTransport(*dest.TransportGuid)) + { + transport->AddPassenger(plMover); + plMover->m_movementInfo.transport.pos.Relocate(dest.Location.GetPosition()); + transport->CalculatePassengerPosition(x, y, z, &o); + } + } - plMover->UpdatePosition(dest, true); + plMover->UpdatePosition(dest.Location, true); plMover->SetFallInformation(0, GetPlayer()->GetPositionZ()); uint32 newzone, newarea; -- cgit v1.2.3