diff options
author | Golrag <golrag.jeremy@gmail.com> | 2024-05-25 21:02:41 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2024-05-25 22:05:53 +0200 |
commit | 5b130cfb4253a94c08ff807e7f28e988651d2476 (patch) | |
tree | 18023dcbeb5f52ab8f10758b06e65b5489b624c6 /src | |
parent | ebf8917b788ca5cc5555c3cfe1ae224ec0ef1b7d (diff) |
Core/Players: Allow targeting a specific transport during teleports
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 96 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 14 | ||||
-rw-r--r-- | src/server/game/Entities/Transport/Transport.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Entities/Transport/Transport.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 38 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 3 | ||||
-rw-r--r-- | src/server/game/Handlers/MovementHandler.cpp | 65 | ||||
-rw-r--r-- | src/server/scripts/Battlegrounds/IsleOfConquest/isle_of_conquest.cpp | 14 |
8 files changed, 133 insertions, 106 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index dba5ded6b21..547655b5a0e 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -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())); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 25a16e48b1e..60cc99a0ae9 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -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; diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 18ec7943466..e1a3e72ef0a 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -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: diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index 291c2bee98c..8a4f272d135 100644 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -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; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 4cdac457f5b..7ffa74abba4 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -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. diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 77be8f57825..a8c9c110a5e 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -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); 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; diff --git a/src/server/scripts/Battlegrounds/IsleOfConquest/isle_of_conquest.cpp b/src/server/scripts/Battlegrounds/IsleOfConquest/isle_of_conquest.cpp index 2c9fdce6596..357e7bba238 100644 --- a/src/server/scripts/Battlegrounds/IsleOfConquest/isle_of_conquest.cpp +++ b/src/server/scripts/Battlegrounds/IsleOfConquest/isle_of_conquest.cpp @@ -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 |