Core/Players: Allow targeting a specific transport during teleports

This commit is contained in:
Golrag
2024-05-25 21:02:41 +02:00
committed by Shauren
parent ebf8917b78
commit 5b130cfb42
8 changed files with 133 additions and 106 deletions

View File

@@ -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();
plMover->UpdatePosition(dest, true);
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.Location, true);
plMover->SetFallInformation(0, GetPlayer()->GetPositionZ());
uint32 newzone, newarea;