Skip to content

Commit a0c8e02

Browse files
committed
Core/Spells: Fix teleports within transports (like Blink)
1 parent 73a32a5 commit a0c8e02

File tree

3 files changed

+63
-25
lines changed

3 files changed

+63
-25
lines changed

src/server/game/Entities/Unit/Unit.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12801,20 +12801,24 @@ bool Unit::CanSwim() const
1280112801
return HasUnitFlag(UNIT_FLAG_RENAME | UNIT_FLAG_CAN_SWIM);
1280212802
}
1280312803

12804-
void Unit::NearTeleportTo(Position const& pos, bool casting /*= false*/)
12804+
void Unit::NearTeleportTo(TeleportLocation const& target, bool casting)
1280512805
{
1280612806
DisableSpline();
12807-
TeleportLocation target{ .Location = { GetMapId(), pos } };
1280812807
if (GetTypeId() == TYPEID_PLAYER)
1280912808
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));
1281012809
else
1281112810
{
1281212811
SendTeleportPacket(target);
12813-
UpdatePosition(pos, true);
12812+
UpdatePosition(target.Location, true);
1281412813
UpdateObjectVisibility();
1281512814
}
1281612815
}
1281712816

12817+
void Unit::NearTeleportTo(Position const& pos, bool casting /*= false*/)
12818+
{
12819+
NearTeleportTo(TeleportLocation{ .Location = { GetMapId(), pos } }, casting);
12820+
}
12821+
1281812822
void Unit::SendTeleportPacket(TeleportLocation const& teleportLocation)
1281912823
{
1282012824
// SMSG_MOVE_UPDATE_TELEPORT is sent to nearby players to signal the teleport
@@ -12856,7 +12860,10 @@ void Unit::SendTeleportPacket(TeleportLocation const& teleportLocation)
1285612860
moveUpdateTeleport.Status->transport.pos.Relocate(teleportLocation.Location);
1285712861
}
1285812862
else
12863+
{
1285912864
moveUpdateTeleport.Status->pos.Relocate(teleportLocation.Location);
12865+
moveUpdateTeleport.Status->transport.Reset();
12866+
}
1286012867
}
1286112868

1286212869
// Broadcast the packet to everyone except self.

src/server/game/Entities/Unit/Unit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,7 @@ class TC_GAME_API Unit : public WorldObject
11221122
void SendSpellDamageResist(Unit* target, uint32 spellId);
11231123
void SendSpellDamageImmune(Unit* target, uint32 spellId, bool isPeriodic);
11241124

1125+
void NearTeleportTo(TeleportLocation const& target, bool casting = false);
11251126
void NearTeleportTo(Position const& pos, bool casting = false);
11261127
void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false) { NearTeleportTo(Position(x, y, z, orientation), casting); }
11271128
void SendTeleportPacket(TeleportLocation const& teleportLocation);

src/server/game/Spells/SpellEffects.cpp

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,44 +1010,50 @@ void Spell::EffectTeleportUnits()
10101010
}
10111011

10121012
// Init dest coordinates
1013-
WorldLocation targetDest(*destTarget);
1014-
if (targetDest.GetMapId() == MAPID_INVALID)
1015-
targetDest.m_mapId = unitTarget->GetMapId();
1013+
TeleportLocation targetDest{ .Location = *destTarget };
1014+
if (targetDest.Location.GetMapId() == MAPID_INVALID)
1015+
targetDest.Location.m_mapId = unitTarget->GetMapId();
10161016

1017-
if (!targetDest.GetOrientation() && m_targets.GetUnitTarget())
1018-
targetDest.SetOrientation(m_targets.GetUnitTarget()->GetOrientation());
1017+
if (!targetDest.Location.GetOrientation() && m_targets.GetUnitTarget())
1018+
targetDest.Location.SetOrientation(m_targets.GetUnitTarget()->GetOrientation());
10191019

10201020
Player* player = unitTarget->ToPlayer();
10211021

10221022
if (player)
10231023
{
10241024
// Custom loading screen
10251025
if (uint32 customLoadingScreenId = effectInfo->MiscValue)
1026-
if (targetDest.GetMapId() != unitTarget->GetMapId() || !unitTarget->IsInDist2d(targetDest, TELEPORT_MIN_LOAD_SCREEN_DISTANCE))
1026+
if (targetDest.Location.GetMapId() != unitTarget->GetMapId() || !unitTarget->IsInDist2d(targetDest.Location, TELEPORT_MIN_LOAD_SCREEN_DISTANCE))
10271027
player->SendDirectMessage(WorldPackets::Spells::CustomLoadScreen(m_spellInfo->Id, customLoadingScreenId).Write());
10281028

1029+
if (ObjectGuid transportGuid = m_destTargets[effectInfo->EffectIndex]._transportGUID; !transportGuid.IsEmpty())
1030+
{
1031+
targetDest.TransportGuid = transportGuid;
1032+
targetDest.Location.Relocate(m_destTargets[effectInfo->EffectIndex]._transportOffset);
1033+
}
1034+
10291035
TeleportToOptions options = GetTeleportOptions(m_caster, unitTarget, m_destTargets[effectInfo->EffectIndex]);
1030-
player->TeleportTo(targetDest, options, {}, m_spellInfo->Id);
1036+
player->TeleportTo(targetDest, options, m_spellInfo->Id);
10311037

10321038
}
1033-
else if (targetDest.GetMapId() == unitTarget->GetMapId())
1034-
unitTarget->NearTeleportTo(targetDest, unitTarget == m_caster);
1039+
else if (targetDest.Location.GetMapId() == unitTarget->GetMapId())
1040+
unitTarget->NearTeleportTo(targetDest.Location, unitTarget == m_caster);
10351041
else
10361042
TC_LOG_ERROR("spells", "Spell::EffectTeleportUnits - spellId {} attempted to teleport creature to a different map.", m_spellInfo->Id);
10371043
}
10381044

10391045
class DelayedSpellTeleportEvent : public BasicEvent
10401046
{
10411047
public:
1042-
explicit DelayedSpellTeleportEvent(Unit* target, WorldLocation const& targetDest, TeleportToOptions options, uint32 spellId)
1048+
explicit DelayedSpellTeleportEvent(Unit* target, TeleportLocation const& targetDest, TeleportToOptions options, uint32 spellId)
10431049
: _target(target), _targetDest(targetDest), _options(options), _spellId(spellId){ }
10441050

10451051
bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override
10461052
{
10471053
if (Player* player = _target->ToPlayer())
10481054
player->TeleportTo(_targetDest, _options);
1049-
else if (_targetDest.GetMapId() == _target->GetMapId())
1050-
_target->NearTeleportTo(_targetDest, (_options & TELE_TO_SPELL) != TELE_TO_NONE);
1055+
else if (_targetDest.Location.GetMapId() == _target->GetMapId())
1056+
_target->NearTeleportTo(_targetDest.Location, (_options & TELE_TO_SPELL) != TELE_TO_NONE);
10511057
else
10521058
TC_LOG_ERROR("spells", "Spell::EffectTeleportUnitsWithVisualLoadingScreen - spellId {} attempted to teleport creature to a different map.", _spellId);
10531059

@@ -1056,7 +1062,7 @@ class DelayedSpellTeleportEvent : public BasicEvent
10561062

10571063
private:
10581064
Unit* _target;
1059-
WorldLocation _targetDest;
1065+
TeleportLocation _targetDest;
10601066
TeleportToOptions _options;
10611067
uint32 _spellId;
10621068
};
@@ -1077,12 +1083,18 @@ void Spell::EffectTeleportUnitsWithVisualLoadingScreen()
10771083
}
10781084

10791085
// Init dest coordinates
1080-
WorldLocation targetDest(*destTarget);
1081-
if (targetDest.GetMapId() == MAPID_INVALID)
1082-
targetDest.m_mapId = unitTarget->GetMapId();
1086+
TeleportLocation targetDest{ .Location = *destTarget };
1087+
if (targetDest.Location.GetMapId() == MAPID_INVALID)
1088+
targetDest.Location.m_mapId = unitTarget->GetMapId();
10831089

1084-
if (!targetDest.GetOrientation() && m_targets.GetUnitTarget())
1085-
targetDest.SetOrientation(m_targets.GetUnitTarget()->GetOrientation());
1090+
if (!targetDest.Location.GetOrientation() && m_targets.GetUnitTarget())
1091+
targetDest.Location.SetOrientation(m_targets.GetUnitTarget()->GetOrientation());
1092+
1093+
if (ObjectGuid transportGuid = m_destTargets[effectInfo->EffectIndex]._transportGUID; !transportGuid.IsEmpty())
1094+
{
1095+
targetDest.TransportGuid = transportGuid;
1096+
targetDest.Location.Relocate(m_destTargets[effectInfo->EffectIndex]._transportOffset);
1097+
}
10861098

10871099
if (effectInfo->MiscValueB)
10881100
if (Player* playerTarget = unitTarget->ToPlayer())
@@ -2330,8 +2342,20 @@ void Spell::EffectTeleUnitsFaceCaster()
23302342
if (unitTarget->IsInFlight())
23312343
return;
23322344

2333-
if (m_targets.HasDst())
2334-
unitTarget->NearTeleportTo(destTarget->GetPositionX(), destTarget->GetPositionY(), destTarget->GetPositionZ(), destTarget->GetAbsoluteAngle(m_caster), unitTarget == m_caster);
2345+
if (!m_targets.HasDst())
2346+
return;
2347+
2348+
TeleportLocation targetDest{ .Location = *destTarget };
2349+
if (ObjectGuid transportGuid = m_destTargets[effectInfo->EffectIndex]._transportGUID; !transportGuid.IsEmpty())
2350+
{
2351+
targetDest.TransportGuid = transportGuid;
2352+
targetDest.Location.Relocate(m_destTargets[effectInfo->EffectIndex]._transportOffset);
2353+
targetDest.Location.SetOrientation(destTarget->GetAbsoluteAngle(m_caster) - targetDest.Location.GetOrientation());
2354+
}
2355+
else
2356+
targetDest.Location.SetOrientation(destTarget->GetAbsoluteAngle(m_caster));
2357+
2358+
unitTarget->NearTeleportTo(destTarget->GetPositionX(), destTarget->GetPositionY(), destTarget->GetPositionZ(), destTarget->GetAbsoluteAngle(m_caster), unitTarget == m_caster);
23352359
}
23362360

23372361
void Spell::EffectLearnSkill()
@@ -3693,8 +3717,14 @@ void Spell::EffectLeap()
36933717
if (!m_targets.HasDst())
36943718
return;
36953719

3696-
Position pos = destTarget->GetPosition();
3697-
unitTarget->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), unitTarget == m_caster);
3720+
TeleportLocation targetDest{ .Location = *destTarget };
3721+
if (ObjectGuid transportGuid = m_destTargets[effectInfo->EffectIndex]._transportGUID; !transportGuid.IsEmpty())
3722+
{
3723+
targetDest.TransportGuid = transportGuid;
3724+
targetDest.Location.Relocate(m_destTargets[effectInfo->EffectIndex]._transportOffset);
3725+
}
3726+
3727+
unitTarget->NearTeleportTo(targetDest, unitTarget == m_caster);
36983728
}
36993729

37003730
void Spell::EffectReputation()

0 commit comments

Comments
 (0)