aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities/Player
diff options
context:
space:
mode:
authorGolrag <golrag.jeremy@gmail.com>2024-05-25 21:02:41 +0200
committerShauren <shauren.trinity@gmail.com>2024-05-25 22:05:53 +0200
commit5b130cfb4253a94c08ff807e7f28e988651d2476 (patch)
tree18023dcbeb5f52ab8f10758b06e65b5489b624c6 /src/server/game/Entities/Player
parentebf8917b788ca5cc5555c3cfe1ae224ec0ef1b7d (diff)
Core/Players: Allow targeting a specific transport during teleports
Diffstat (limited to 'src/server/game/Entities/Player')
-rw-r--r--src/server/game/Entities/Player/Player.cpp96
-rw-r--r--src/server/game/Entities/Player/Player.h14
2 files changed, 61 insertions, 49 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;