mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Core/Players: Allow targeting a specific transport during teleports
This commit is contained in:
@@ -1252,24 +1252,34 @@ uint16 Player::GetChatFlags() const
|
||||
|
||||
bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, TeleportToOptions options /*= TELE_TO_NONE*/, Optional<uint32> instanceId /*= {}*/)
|
||||
{
|
||||
if (!MapManager::IsValidMapCoord(mapid, x, y, z, orientation))
|
||||
return TeleportTo({ .Location = WorldLocation(mapid, x, y, z, orientation), .InstanceId = instanceId }, options);
|
||||
}
|
||||
|
||||
bool Player::TeleportTo(WorldLocation const& loc, TeleportToOptions options, Optional<uint32> instanceId)
|
||||
{
|
||||
return TeleportTo({ .Location = loc, .InstanceId = instanceId }, options);
|
||||
}
|
||||
|
||||
bool Player::TeleportTo(TeleportLocation const& teleportLocation, TeleportToOptions options /*= TELE_TO_NONE*/)
|
||||
{
|
||||
if (!MapManager::IsValidMapCoord(teleportLocation.Location))
|
||||
{
|
||||
TC_LOG_ERROR("maps", "Player::TeleportTo: Invalid map ({}) or invalid coordinates (X: {}, Y: {}, Z: {}, O: {}) given when teleporting player '{}' ({}, MapID: {}, X: {}, Y: {}, Z: {}, O: {}).",
|
||||
mapid, x, y, z, orientation, GetGUID().ToString(), GetName(), GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
|
||||
TC_LOG_ERROR("maps", "Player::TeleportTo: Invalid map ({}) or invalid coordinates ({}) given when teleporting player '{}' ({}, MapID: {}, {}).",
|
||||
teleportLocation.Location.GetMapId(), teleportLocation.Location.ToString(), GetGUID().ToString(), GetName(), GetMapId(), GetPosition().ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_DISABLE_MAP) && DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, mapid, this))
|
||||
if (!GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_DISABLE_MAP) && DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, teleportLocation.Location.GetMapId(), this))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.cheat", "Player::TeleportTo: Player '{}' ({}) tried to enter a forbidden map (MapID: {})", GetGUID().ToString(), GetName(), mapid);
|
||||
SendTransferAborted(mapid, TRANSFER_ABORT_MAP_NOT_ALLOWED);
|
||||
TC_LOG_ERROR("entities.player.cheat", "Player::TeleportTo: Player '{}' ({}) tried to enter a forbidden map (MapID: {})", GetGUID().ToString(), GetName(), teleportLocation.Location.GetMapId());
|
||||
SendTransferAborted(teleportLocation.Location.GetMapId(), TRANSFER_ABORT_MAP_NOT_ALLOWED);
|
||||
return false;
|
||||
}
|
||||
|
||||
// preparing unsummon pet if lost (we must get pet before teleportation or will not find it later)
|
||||
Pet* pet = GetPet();
|
||||
|
||||
MapEntry const* mEntry = sMapStore.LookupEntry(mapid);
|
||||
MapEntry const* mEntry = sMapStore.LookupEntry(teleportLocation.Location.GetMapId());
|
||||
|
||||
// don't let enter battlegrounds without assigned battleground id (for example through areatrigger)...
|
||||
// don't let gm level > 1 either
|
||||
@@ -1280,7 +1290,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
if (GetSession()->GetExpansion() < mEntry->Expansion())
|
||||
{
|
||||
TC_LOG_DEBUG("maps", "Player '{}' ({}) using client without required expansion tried teleporting to non accessible map (MapID: {})",
|
||||
GetName(), GetGUID().ToString(), mapid);
|
||||
GetName(), GetGUID().ToString(), teleportLocation.Location.GetMapId());
|
||||
|
||||
if (TransportBase* transport = GetTransport())
|
||||
{
|
||||
@@ -1288,12 +1298,12 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :)
|
||||
}
|
||||
|
||||
SendTransferAborted(mapid, TRANSFER_ABORT_INSUF_EXPAN_LVL, mEntry->Expansion());
|
||||
SendTransferAborted(teleportLocation.Location.GetMapId(), TRANSFER_ABORT_INSUF_EXPAN_LVL, mEntry->Expansion());
|
||||
|
||||
return false; // normal client can't teleport to this map...
|
||||
}
|
||||
else
|
||||
TC_LOG_DEBUG("maps", "Player {} ({}) is being teleported to map (MapID: {})", GetName(), GetGUID().ToString(), mapid);
|
||||
TC_LOG_DEBUG("maps", "Player {} ({}) is being teleported to map (MapID: {})", GetName(), GetGUID().ToString(), teleportLocation.Location.GetMapId());
|
||||
|
||||
if (m_vehicle)
|
||||
ExitVehicle();
|
||||
@@ -1305,18 +1315,17 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
GetMotionMaster()->Remove(EFFECT_MOTION_TYPE);
|
||||
|
||||
if (TransportBase* transport = GetTransport())
|
||||
{
|
||||
if (!(options & TELE_TO_NOT_LEAVE_TRANSPORT))
|
||||
transport->RemovePassenger(this);
|
||||
}
|
||||
if (!teleportLocation.TransportGuid || teleportLocation.TransportGuid != transport->GetTransportGUID())
|
||||
if (!(options & TELE_TO_NOT_LEAVE_TRANSPORT))
|
||||
transport->RemovePassenger(this);
|
||||
|
||||
// The player was ported to another map and loses the duel immediately.
|
||||
// We have to perform this check before the teleport, otherwise the
|
||||
// ObjectAccessor won't find the flag.
|
||||
if (duel && GetMapId() != mapid && GetMap()->GetGameObject(m_playerData->DuelArbiter))
|
||||
if (duel && GetMapId() != teleportLocation.Location.GetMapId() && GetMap()->GetGameObject(m_playerData->DuelArbiter))
|
||||
DuelComplete(DUEL_FLED);
|
||||
|
||||
if (GetMapId() == mapid && (!instanceId || GetInstanceId() == instanceId))
|
||||
if (GetMapId() == teleportLocation.Location.GetMapId() && (!teleportLocation.InstanceId || GetInstanceId() == teleportLocation.InstanceId))
|
||||
{
|
||||
//lets reset far teleport flag if it wasn't reset during chained teleport
|
||||
SetSemaphoreTeleportFar(false);
|
||||
@@ -1328,8 +1337,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
{
|
||||
SetSemaphoreTeleportNear(true);
|
||||
//lets save teleport destination for player
|
||||
m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
|
||||
m_teleport_instanceId = {};
|
||||
m_teleport_dest = teleportLocation;
|
||||
m_teleport_options = options;
|
||||
return true;
|
||||
}
|
||||
@@ -1337,7 +1345,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
if (!(options & TELE_TO_NOT_UNSUMMON_PET))
|
||||
{
|
||||
//same map, only remove pet if out of range for new position
|
||||
if (pet && !pet->IsWithinDist3d(x, y, z, GetMap()->GetVisibilityRange()))
|
||||
if (pet && !pet->IsWithinDist3d(&teleportLocation.Location, GetMap()->GetVisibilityRange()))
|
||||
UnsummonPetTemporaryIfAny();
|
||||
}
|
||||
|
||||
@@ -1348,8 +1356,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
CombatStop();
|
||||
|
||||
// this will be used instead of the current location in SaveToDB
|
||||
m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
|
||||
m_teleport_instanceId = {};
|
||||
m_teleport_dest = teleportLocation;
|
||||
m_teleport_options = options;
|
||||
SetFallInformation(0, GetPositionZ());
|
||||
|
||||
@@ -1364,7 +1371,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
{
|
||||
if (GetClass() == CLASS_DEATH_KNIGHT && GetMapId() == 609 && !IsGameMaster() && !HasSpell(50977))
|
||||
{
|
||||
SendTransferAborted(mapid, TRANSFER_ABORT_UNIQUE_MESSAGE, 1);
|
||||
SendTransferAborted(teleportLocation.Location.GetMapId(), TRANSFER_ABORT_UNIQUE_MESSAGE, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1374,15 +1381,15 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
|
||||
// Check enter rights before map getting to avoid creating instance copy for player
|
||||
// this check not dependent from map instance copy and same for all instance copies of selected map
|
||||
if (TransferAbortParams abortParams = Map::PlayerCannotEnter(mapid, this))
|
||||
if (TransferAbortParams abortParams = Map::PlayerCannotEnter(teleportLocation.Location.GetMapId(), this))
|
||||
{
|
||||
SendTransferAborted(mapid, abortParams.Reason, abortParams.Arg, abortParams.MapDifficultyXConditionId);
|
||||
SendTransferAborted(teleportLocation.Location.GetMapId(), abortParams.Reason, abortParams.Arg, abortParams.MapDifficultyXConditionId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Seamless teleport can happen only if cosmetic maps match
|
||||
if (!oldmap ||
|
||||
(oldmap->GetEntry()->CosmeticParentMapID != int32(mapid) && int32(GetMapId()) != mEntry->CosmeticParentMapID &&
|
||||
(oldmap->GetEntry()->CosmeticParentMapID != int32(teleportLocation.Location.GetMapId()) && int32(GetMapId()) != mEntry->CosmeticParentMapID &&
|
||||
!((oldmap->GetEntry()->CosmeticParentMapID != -1) ^ (oldmap->GetEntry()->CosmeticParentMapID != mEntry->CosmeticParentMapID))))
|
||||
options &= ~TELE_TO_SEAMLESS;
|
||||
|
||||
@@ -1396,8 +1403,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
{
|
||||
SetSemaphoreTeleportFar(true);
|
||||
//lets save teleport destination for player
|
||||
m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
|
||||
m_teleport_instanceId = instanceId;
|
||||
m_teleport_dest = teleportLocation;
|
||||
m_teleport_options = options;
|
||||
return true;
|
||||
}
|
||||
@@ -1414,7 +1420,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
// Note: at battleground join battleground id set before teleport
|
||||
// and we already will found "current" battleground
|
||||
// just need check that this is targeted map or leave
|
||||
if (bg->GetMapId() != mapid)
|
||||
if (bg->GetMapId() != teleportLocation.Location.GetMapId())
|
||||
LeaveBattleground(false); // don't teleport to entry point
|
||||
}
|
||||
|
||||
@@ -1450,13 +1456,19 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
{
|
||||
// send transfer packets
|
||||
WorldPackets::Movement::TransferPending transferPending;
|
||||
transferPending.MapID = mapid;
|
||||
transferPending.OldMapPosition = GetPosition();
|
||||
if (Transport* transport = dynamic_cast<Transport*>(GetTransport()))
|
||||
transferPending.MapID = teleportLocation.Location.GetMapId();
|
||||
transferPending.OldMapPosition = teleportLocation.Location.GetPosition();
|
||||
if (teleportLocation.TransportGuid.has_value())
|
||||
{
|
||||
transferPending.Ship.emplace();
|
||||
transferPending.Ship->ID = transport->GetEntry();
|
||||
transferPending.Ship->OriginMapID = GetMapId();
|
||||
if (TransportSpawn const* transportSpawn = sTransportMgr->GetTransportSpawn(teleportLocation.TransportGuid->GetCounter()))
|
||||
{
|
||||
transferPending.Ship->ID = transportSpawn->TransportGameObjectId;
|
||||
if (dynamic_cast<Transport*>(GetTransport()))
|
||||
transferPending.Ship->OriginMapID = GetMapId();
|
||||
else
|
||||
transferPending.Ship->OriginMapID = -1;
|
||||
}
|
||||
}
|
||||
|
||||
SendDirectMessage(transferPending.Write());
|
||||
@@ -1469,8 +1481,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
if (oldmap)
|
||||
oldmap->RemovePlayerFromMap(this, false);
|
||||
|
||||
m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
|
||||
m_teleport_instanceId = instanceId;
|
||||
m_teleport_dest = teleportLocation;
|
||||
m_teleport_options = options;
|
||||
SetFallInformation(0, GetPositionZ());
|
||||
// if the player is saved before worldportack (at logout for example)
|
||||
@@ -1491,11 +1502,6 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::TeleportTo(WorldLocation const& loc, TeleportToOptions options /*= TELE_TO_NONE*/, Optional<uint32> instanceId /*= {}*/)
|
||||
{
|
||||
return TeleportTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation(), options, instanceId);
|
||||
}
|
||||
|
||||
bool Player::TeleportToBGEntryPoint()
|
||||
{
|
||||
if (m_bgData.joinPos.m_mapId == MAPID_INVALID)
|
||||
@@ -20083,15 +20089,15 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
|
||||
}
|
||||
else
|
||||
{
|
||||
stmt->setUInt16(index++, (uint16)GetTeleportDest().GetMapId());
|
||||
stmt->setUInt16(index++, (uint16)GetTeleportDest().Location.GetMapId());
|
||||
stmt->setUInt32(index++, (uint32)0);
|
||||
stmt->setUInt8(index++, uint8(GetDungeonDifficultyID()));
|
||||
stmt->setUInt8(index++, uint8(GetRaidDifficultyID()));
|
||||
stmt->setUInt8(index++, uint8(GetLegacyRaidDifficultyID()));
|
||||
stmt->setFloat(index++, finiteAlways(GetTeleportDest().GetPositionX()));
|
||||
stmt->setFloat(index++, finiteAlways(GetTeleportDest().GetPositionY()));
|
||||
stmt->setFloat(index++, finiteAlways(GetTeleportDest().GetPositionZ()));
|
||||
stmt->setFloat(index++, finiteAlways(GetTeleportDest().GetOrientation()));
|
||||
stmt->setFloat(index++, finiteAlways(GetTeleportDest().Location.GetPositionX()));
|
||||
stmt->setFloat(index++, finiteAlways(GetTeleportDest().Location.GetPositionY()));
|
||||
stmt->setFloat(index++, finiteAlways(GetTeleportDest().Location.GetPositionZ()));
|
||||
stmt->setFloat(index++, finiteAlways(GetTeleportDest().Location.GetOrientation()));
|
||||
}
|
||||
|
||||
stmt->setFloat(index++, finiteAlways(GetTransOffsetX()));
|
||||
|
||||
@@ -1134,6 +1134,13 @@ enum class ZonePVPTypeOverride : uint32
|
||||
Combat = 4
|
||||
};
|
||||
|
||||
struct TeleportLocation
|
||||
{
|
||||
WorldLocation Location;
|
||||
Optional<uint32> InstanceId;
|
||||
Optional<ObjectGuid> TransportGuid;
|
||||
};
|
||||
|
||||
class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
{
|
||||
friend class WorldSession;
|
||||
@@ -1156,6 +1163,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
|
||||
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, TeleportToOptions options = TELE_TO_NONE, Optional<uint32> instanceId = {});
|
||||
bool TeleportTo(WorldLocation const& loc, TeleportToOptions options = TELE_TO_NONE, Optional<uint32> instanceId = {});
|
||||
bool TeleportTo(TeleportLocation const& teleportLocation, TeleportToOptions options = TELE_TO_NONE);
|
||||
bool TeleportToBGEntryPoint();
|
||||
|
||||
bool HasSummonPending() const;
|
||||
@@ -2267,8 +2275,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
void SetSkillTempBonus(uint32 pos, uint16 bonus) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::Skill).ModifyValue(&UF::SkillInfo::SkillTempBonus, pos), bonus); }
|
||||
void SetSkillPermBonus(uint32 pos, uint16 bonus) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::Skill).ModifyValue(&UF::SkillInfo::SkillPermBonus, pos), bonus); }
|
||||
|
||||
WorldLocation& GetTeleportDest() { return m_teleport_dest; }
|
||||
Optional<uint32> GetTeleportDestInstanceId() const { return m_teleport_instanceId; }
|
||||
TeleportLocation& GetTeleportDest() { return m_teleport_dest; }
|
||||
uint32 GetTeleportOptions() const { return m_teleport_options; }
|
||||
bool IsBeingTeleported() const { return IsBeingTeleportedNear() || IsBeingTeleportedFar(); }
|
||||
bool IsBeingTeleportedNear() const { return mSemaphoreTeleport_Near; }
|
||||
@@ -3226,8 +3233,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
uint8 m_MirrorTimerFlagsLast;
|
||||
|
||||
// Current teleport data
|
||||
WorldLocation m_teleport_dest;
|
||||
Optional<uint32> m_teleport_instanceId;
|
||||
TeleportLocation m_teleport_dest;
|
||||
TeleportToOptions m_teleport_options;
|
||||
bool mSemaphoreTeleport_Near;
|
||||
bool mSemaphoreTeleport_Far;
|
||||
|
||||
@@ -612,7 +612,7 @@ bool Transport::TeleportTransport(uint32 oldMapId, uint32 newMapId, float x, flo
|
||||
if (oldMapId != newMapId)
|
||||
{
|
||||
UnloadStaticPassengers();
|
||||
TeleportPassengersAndHideTransport(newMapId, x, y, z, o);
|
||||
TeleportPassengersAndHideTransport(newMapId);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -641,7 +641,7 @@ bool Transport::TeleportTransport(uint32 oldMapId, uint32 newMapId, float x, flo
|
||||
}
|
||||
}
|
||||
|
||||
void Transport::TeleportPassengersAndHideTransport(uint32 newMapid, float x, float y, float z, float o)
|
||||
void Transport::TeleportPassengersAndHideTransport(uint32 newMapid)
|
||||
{
|
||||
if (newMapid == GetMapId())
|
||||
{
|
||||
@@ -684,12 +684,11 @@ void Transport::TeleportPassengersAndHideTransport(uint32 newMapid, float x, flo
|
||||
{
|
||||
float destX, destY, destZ, destO;
|
||||
obj->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO);
|
||||
TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o);
|
||||
|
||||
switch (obj->GetTypeId())
|
||||
{
|
||||
case TYPEID_PLAYER:
|
||||
if (!obj->ToPlayer()->TeleportTo(newMapid, destX, destY, destZ, destO, TELE_TO_NOT_LEAVE_TRANSPORT))
|
||||
if (!obj->ToPlayer()->TeleportTo({ .Location = WorldLocation(newMapid, destX, destY, destZ, destO), .TransportGuid = GetTransportGUID() }, TELE_TO_NOT_LEAVE_TRANSPORT))
|
||||
RemovePassenger(obj);
|
||||
break;
|
||||
case TYPEID_DYNAMICOBJECT:
|
||||
|
||||
@@ -109,7 +109,7 @@ class TC_GAME_API Transport final : public GameObject, public TransportBase
|
||||
|
||||
private:
|
||||
bool TeleportTransport(uint32 oldMapId, uint32 newMapId, float x, float y, float z, float o);
|
||||
void TeleportPassengersAndHideTransport(uint32 newMapid, float x, float y, float z, float o);
|
||||
void TeleportPassengersAndHideTransport(uint32 newMapid);
|
||||
void UpdatePassengerPositions(PassengerSet const& passengers);
|
||||
|
||||
TransportTemplate const* _transportInfo;
|
||||
|
||||
@@ -12373,20 +12373,18 @@ bool Unit::CanSwim() const
|
||||
void Unit::NearTeleportTo(Position const& pos, bool casting /*= false*/)
|
||||
{
|
||||
DisableSpline();
|
||||
TeleportLocation target{ .Location = { GetMapId(), pos } };
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
WorldLocation target(GetMapId(), pos);
|
||||
ToPlayer()->TeleportTo(target, TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (casting ? TELE_TO_SPELL : TELE_TO_NONE));
|
||||
}
|
||||
else
|
||||
{
|
||||
SendTeleportPacket(pos);
|
||||
SendTeleportPacket(target);
|
||||
UpdatePosition(pos, true);
|
||||
UpdateObjectVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::SendTeleportPacket(Position const& pos)
|
||||
void Unit::SendTeleportPacket(TeleportLocation const& teleportLocation)
|
||||
{
|
||||
// SMSG_MOVE_UPDATE_TELEPORT is sent to nearby players to signal the teleport
|
||||
// SMSG_MOVE_TELEPORT is sent to self in order to trigger CMSG_MOVE_TELEPORT_ACK and update the position server side
|
||||
@@ -12400,16 +12398,11 @@ void Unit::SendTeleportPacket(Position const& pos)
|
||||
// should this really be the unit _being_ moved? not the unit doing the moving?
|
||||
if (Player* playerMover = Unit::ToPlayer(GetUnitBeingMoved()))
|
||||
{
|
||||
float x, y, z, o;
|
||||
pos.GetPosition(x, y, z, o);
|
||||
if (TransportBase* transportBase = GetDirectTransport())
|
||||
transportBase->CalculatePassengerOffset(x, y, z, &o);
|
||||
|
||||
WorldPackets::Movement::MoveTeleport moveTeleport;
|
||||
moveTeleport.MoverGUID = GetGUID();
|
||||
moveTeleport.Pos = Position(x, y, z);
|
||||
moveTeleport.TransportGUID = GetTransGUID();
|
||||
moveTeleport.Facing = o;
|
||||
moveTeleport.Pos = teleportLocation.Location;
|
||||
moveTeleport.TransportGUID = teleportLocation.TransportGuid;
|
||||
moveTeleport.Facing = teleportLocation.Location.GetOrientation();
|
||||
moveTeleport.SequenceIndex = m_movementCounter++;
|
||||
playerMover->SendDirectMessage(moveTeleport.Write());
|
||||
|
||||
@@ -12420,15 +12413,22 @@ void Unit::SendTeleportPacket(Position const& pos)
|
||||
// This is the only packet sent for creatures which contains MovementInfo structure
|
||||
// we do not update m_movementInfo for creatures so it needs to be done manually here
|
||||
moveUpdateTeleport.Status->guid = GetGUID();
|
||||
moveUpdateTeleport.Status->pos.Relocate(pos);
|
||||
moveUpdateTeleport.Status->time = getMSTime();
|
||||
if (TransportBase* transportBase = GetDirectTransport())
|
||||
|
||||
if (teleportLocation.TransportGuid)
|
||||
{
|
||||
float tx, ty, tz, to;
|
||||
pos.GetPosition(tx, ty, tz, to);
|
||||
transportBase->CalculatePassengerOffset(tx, ty, tz, &to);
|
||||
moveUpdateTeleport.Status->transport.pos.Relocate(tx, ty, tz, to);
|
||||
Transport* transport = GetMap()->GetTransport(*teleportLocation.TransportGuid);
|
||||
if (!transport)
|
||||
return;
|
||||
|
||||
float x, y, z, o;
|
||||
teleportLocation.Location.GetPosition(x, y, z, o);
|
||||
transport->CalculatePassengerPosition(x, y, z, &o);
|
||||
moveUpdateTeleport.Status->pos.Relocate(x, y, z, o);
|
||||
moveUpdateTeleport.Status->transport.pos.Relocate(teleportLocation.Location);
|
||||
}
|
||||
else
|
||||
moveUpdateTeleport.Status->pos.Relocate(teleportLocation.Location);
|
||||
}
|
||||
|
||||
// Broadcast the packet to everyone except self.
|
||||
|
||||
@@ -70,6 +70,7 @@ struct LiquidData;
|
||||
struct LiquidTypeEntry;
|
||||
struct MountCapabilityEntry;
|
||||
struct SpellValue;
|
||||
struct TeleportLocation;
|
||||
|
||||
class Aura;
|
||||
class AuraApplication;
|
||||
@@ -1118,7 +1119,7 @@ class TC_GAME_API Unit : public WorldObject
|
||||
|
||||
void NearTeleportTo(Position const& pos, bool casting = false);
|
||||
void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false) { NearTeleportTo(Position(x, y, z, orientation), casting); }
|
||||
void SendTeleportPacket(Position const& pos);
|
||||
void SendTeleportPacket(TeleportLocation const& teleportLocation);
|
||||
virtual bool UpdatePosition(float x, float y, float z, float ang, bool teleport = false);
|
||||
// returns true if unit's position really changed
|
||||
virtual bool UpdatePosition(Position const& pos, bool teleport = false);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -210,15 +210,11 @@ class spell_ioc_gunship_portal : public SpellScript
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Player* caster = GetCaster()->ToPlayer();
|
||||
/*
|
||||
* HACK: GetWorldLocation() returns real position and not transportposition.
|
||||
* ServertoClient: SMSG_MOVE_TELEPORT (0x0B39)
|
||||
* counter: 45
|
||||
* Tranpsort Guid: Full: xxxx Type: MOTransport Low: xxx
|
||||
* Transport Position X: 0 Y: 0 Z: 0 O: 0
|
||||
* Position: X: 7.305609 Y: -0.095246 Z: 34.51022 O: 0
|
||||
*/
|
||||
caster->TeleportTo(GetHitCreature()->GetWorldLocation(), TELE_TO_NOT_LEAVE_TRANSPORT);
|
||||
Optional<ObjectGuid> transportGuid;
|
||||
if (TransportBase const* transport = GetHitCreature()->GetTransport())
|
||||
transportGuid = transport->GetTransportGUID();
|
||||
|
||||
caster->TeleportTo({ .Location = WorldLocation(GetHitCreature()->GetMapId(), GetHitCreature()->GetTransOffset()), .TransportGuid = transportGuid });
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
||||
Reference in New Issue
Block a user