diff options
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 13 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 1 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 74 |
3 files changed, 63 insertions, 25 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 03205c45f78..153d1136dd7 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -12801,20 +12801,24 @@ bool Unit::CanSwim() const return HasUnitFlag(UNIT_FLAG_RENAME | UNIT_FLAG_CAN_SWIM); } -void Unit::NearTeleportTo(Position const& pos, bool casting /*= false*/) +void Unit::NearTeleportTo(TeleportLocation const& target, bool casting) { DisableSpline(); - TeleportLocation target{ .Location = { GetMapId(), pos } }; if (GetTypeId() == TYPEID_PLAYER) 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(target); - UpdatePosition(pos, true); + UpdatePosition(target.Location, true); UpdateObjectVisibility(); } } +void Unit::NearTeleportTo(Position const& pos, bool casting /*= false*/) +{ + NearTeleportTo(TeleportLocation{ .Location = { GetMapId(), pos } }, casting); +} + void Unit::SendTeleportPacket(TeleportLocation const& teleportLocation) { // SMSG_MOVE_UPDATE_TELEPORT is sent to nearby players to signal the teleport @@ -12856,7 +12860,10 @@ void Unit::SendTeleportPacket(TeleportLocation const& teleportLocation) moveUpdateTeleport.Status->transport.pos.Relocate(teleportLocation.Location); } else + { moveUpdateTeleport.Status->pos.Relocate(teleportLocation.Location); + moveUpdateTeleport.Status->transport.Reset(); + } } // 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 22a872a7020..8973b439717 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1122,6 +1122,7 @@ class TC_GAME_API Unit : public WorldObject void SendSpellDamageResist(Unit* target, uint32 spellId); void SendSpellDamageImmune(Unit* target, uint32 spellId, bool isPeriodic); + void NearTeleportTo(TeleportLocation const& target, bool casting = false); 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(TeleportLocation const& teleportLocation); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 8ab3c15d1a1..9954a89d928 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1010,12 +1010,12 @@ void Spell::EffectTeleportUnits() } // Init dest coordinates - WorldLocation targetDest(*destTarget); - if (targetDest.GetMapId() == MAPID_INVALID) - targetDest.m_mapId = unitTarget->GetMapId(); + TeleportLocation targetDest{ .Location = *destTarget }; + if (targetDest.Location.GetMapId() == MAPID_INVALID) + targetDest.Location.m_mapId = unitTarget->GetMapId(); - if (!targetDest.GetOrientation() && m_targets.GetUnitTarget()) - targetDest.SetOrientation(m_targets.GetUnitTarget()->GetOrientation()); + if (!targetDest.Location.GetOrientation() && m_targets.GetUnitTarget()) + targetDest.Location.SetOrientation(m_targets.GetUnitTarget()->GetOrientation()); Player* player = unitTarget->ToPlayer(); @@ -1023,15 +1023,21 @@ void Spell::EffectTeleportUnits() { // Custom loading screen if (uint32 customLoadingScreenId = effectInfo->MiscValue) - if (targetDest.GetMapId() != unitTarget->GetMapId() || !unitTarget->IsInDist2d(targetDest, TELEPORT_MIN_LOAD_SCREEN_DISTANCE)) + if (targetDest.Location.GetMapId() != unitTarget->GetMapId() || !unitTarget->IsInDist2d(targetDest.Location, TELEPORT_MIN_LOAD_SCREEN_DISTANCE)) player->SendDirectMessage(WorldPackets::Spells::CustomLoadScreen(m_spellInfo->Id, customLoadingScreenId).Write()); + if (ObjectGuid transportGuid = m_destTargets[effectInfo->EffectIndex]._transportGUID; !transportGuid.IsEmpty()) + { + targetDest.TransportGuid = transportGuid; + targetDest.Location.Relocate(m_destTargets[effectInfo->EffectIndex]._transportOffset); + } + TeleportToOptions options = GetTeleportOptions(m_caster, unitTarget, m_destTargets[effectInfo->EffectIndex]); - player->TeleportTo(targetDest, options, {}, m_spellInfo->Id); + player->TeleportTo(targetDest, options, m_spellInfo->Id); } - else if (targetDest.GetMapId() == unitTarget->GetMapId()) - unitTarget->NearTeleportTo(targetDest, unitTarget == m_caster); + else if (targetDest.Location.GetMapId() == unitTarget->GetMapId()) + unitTarget->NearTeleportTo(targetDest.Location, unitTarget == m_caster); else TC_LOG_ERROR("spells", "Spell::EffectTeleportUnits - spellId {} attempted to teleport creature to a different map.", m_spellInfo->Id); } @@ -1039,15 +1045,15 @@ void Spell::EffectTeleportUnits() class DelayedSpellTeleportEvent : public BasicEvent { public: - explicit DelayedSpellTeleportEvent(Unit* target, WorldLocation const& targetDest, TeleportToOptions options, uint32 spellId) + explicit DelayedSpellTeleportEvent(Unit* target, TeleportLocation const& targetDest, TeleportToOptions options, uint32 spellId) : _target(target), _targetDest(targetDest), _options(options), _spellId(spellId){ } bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override { if (Player* player = _target->ToPlayer()) player->TeleportTo(_targetDest, _options); - else if (_targetDest.GetMapId() == _target->GetMapId()) - _target->NearTeleportTo(_targetDest, (_options & TELE_TO_SPELL) != TELE_TO_NONE); + else if (_targetDest.Location.GetMapId() == _target->GetMapId()) + _target->NearTeleportTo(_targetDest.Location, (_options & TELE_TO_SPELL) != TELE_TO_NONE); else TC_LOG_ERROR("spells", "Spell::EffectTeleportUnitsWithVisualLoadingScreen - spellId {} attempted to teleport creature to a different map.", _spellId); @@ -1056,7 +1062,7 @@ public: private: Unit* _target; - WorldLocation _targetDest; + TeleportLocation _targetDest; TeleportToOptions _options; uint32 _spellId; }; @@ -1077,12 +1083,18 @@ void Spell::EffectTeleportUnitsWithVisualLoadingScreen() } // Init dest coordinates - WorldLocation targetDest(*destTarget); - if (targetDest.GetMapId() == MAPID_INVALID) - targetDest.m_mapId = unitTarget->GetMapId(); + TeleportLocation targetDest{ .Location = *destTarget }; + if (targetDest.Location.GetMapId() == MAPID_INVALID) + targetDest.Location.m_mapId = unitTarget->GetMapId(); - if (!targetDest.GetOrientation() && m_targets.GetUnitTarget()) - targetDest.SetOrientation(m_targets.GetUnitTarget()->GetOrientation()); + if (!targetDest.Location.GetOrientation() && m_targets.GetUnitTarget()) + targetDest.Location.SetOrientation(m_targets.GetUnitTarget()->GetOrientation()); + + if (ObjectGuid transportGuid = m_destTargets[effectInfo->EffectIndex]._transportGUID; !transportGuid.IsEmpty()) + { + targetDest.TransportGuid = transportGuid; + targetDest.Location.Relocate(m_destTargets[effectInfo->EffectIndex]._transportOffset); + } if (effectInfo->MiscValueB) if (Player* playerTarget = unitTarget->ToPlayer()) @@ -2330,8 +2342,20 @@ void Spell::EffectTeleUnitsFaceCaster() if (unitTarget->IsInFlight()) return; - if (m_targets.HasDst()) - unitTarget->NearTeleportTo(destTarget->GetPositionX(), destTarget->GetPositionY(), destTarget->GetPositionZ(), destTarget->GetAbsoluteAngle(m_caster), unitTarget == m_caster); + if (!m_targets.HasDst()) + return; + + TeleportLocation targetDest{ .Location = *destTarget }; + if (ObjectGuid transportGuid = m_destTargets[effectInfo->EffectIndex]._transportGUID; !transportGuid.IsEmpty()) + { + targetDest.TransportGuid = transportGuid; + targetDest.Location.Relocate(m_destTargets[effectInfo->EffectIndex]._transportOffset); + targetDest.Location.SetOrientation(destTarget->GetAbsoluteAngle(m_caster) - targetDest.Location.GetOrientation()); + } + else + targetDest.Location.SetOrientation(destTarget->GetAbsoluteAngle(m_caster)); + + unitTarget->NearTeleportTo(destTarget->GetPositionX(), destTarget->GetPositionY(), destTarget->GetPositionZ(), destTarget->GetAbsoluteAngle(m_caster), unitTarget == m_caster); } void Spell::EffectLearnSkill() @@ -3693,8 +3717,14 @@ void Spell::EffectLeap() if (!m_targets.HasDst()) return; - Position pos = destTarget->GetPosition(); - unitTarget->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), unitTarget == m_caster); + TeleportLocation targetDest{ .Location = *destTarget }; + if (ObjectGuid transportGuid = m_destTargets[effectInfo->EffectIndex]._transportGUID; !transportGuid.IsEmpty()) + { + targetDest.TransportGuid = transportGuid; + targetDest.Location.Relocate(m_destTargets[effectInfo->EffectIndex]._transportOffset); + } + + unitTarget->NearTeleportTo(targetDest, unitTarget == m_caster); } void Spell::EffectReputation() |