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/Maps/Map.cpp | 13 | ||||
-rw-r--r-- | src/server/game/Maps/TerrainMgr.cpp | 17 | ||||
-rw-r--r-- | src/server/game/Maps/TerrainMgr.h | 5 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 74 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_priest.cpp | 3 |
7 files changed, 78 insertions, 48 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/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index b95bd2b9359..e9e4748b440 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -138,20 +138,9 @@ i_mapEntry(sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(Inst m_unloadTimer(0), m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE), m_mapRefIter(m_mapRefManager.end()), m_VisibilityNotifyPeriod(DEFAULT_VISIBILITY_NOTIFY_PERIOD), m_activeNonPlayersIter(m_activeNonPlayers.end()), _transportsUpdateIter(_transports.end()), -i_gridExpiry(expiry), m_terrain(sTerrainMgr.LoadTerrain(id)), m_forceEnabledNavMeshFilterFlags(0), m_forceDisabledNavMeshFilterFlags(0), +i_gridExpiry(expiry), m_terrain(sTerrainMgr.LoadTerrain(id)), m_forceEnabledNavMeshFilterFlags(0), m_forceDisabledNavMeshFilterFlags(0), i_grids(), i_scriptLock(false), _respawnTimes(std::make_unique<RespawnListContainer>()), _respawnCheckTimer(0), _vignetteUpdateTimer(5200, 5200) { - for (uint32 x = 0; x < MAX_NUMBER_OF_GRIDS; ++x) - { - for (uint32 y = 0; y < MAX_NUMBER_OF_GRIDS; ++y) - { - //z code - setNGrid(nullptr, x, y); - } - } - - _zonePlayerCountMap.clear(); - //lets initialize visibility distance for map Map::InitVisibilityDistance(); diff --git a/src/server/game/Maps/TerrainMgr.cpp b/src/server/game/Maps/TerrainMgr.cpp index 65655e6e84b..7dc70479a96 100644 --- a/src/server/game/Maps/TerrainMgr.cpp +++ b/src/server/game/Maps/TerrainMgr.cpp @@ -32,7 +32,7 @@ #include "World.h" #include <G3D/g3dmath.h> -TerrainInfo::TerrainInfo(uint32 mapId) : _mapId(mapId), _parentTerrain(nullptr), _cleanupTimer(randtime(CleanupInterval / 2, CleanupInterval)) +TerrainInfo::TerrainInfo(uint32 mapId) : _mapId(mapId), _parentTerrain(nullptr), _loadedGrids(), _cleanupTimer(randtime(CleanupInterval / 2, CleanupInterval)) { } @@ -180,7 +180,7 @@ void TerrainInfo::LoadMapAndVMapImpl(int32 gx, int32 gy) for (std::shared_ptr<TerrainInfo> const& childTerrain : _childTerrain) childTerrain->LoadMapAndVMapImpl(gx, gy); - _loadedGrids[GetBitsetIndex(gx, gy)] = true; + _loadedGrids[gx] |= UI64LIT(1) << gy; } void TerrainInfo::LoadMMapInstanceImpl(uint32 mapId, uint32 instanceId) @@ -279,7 +279,7 @@ void TerrainInfo::UnloadMapImpl(int32 gx, int32 gy) for (std::shared_ptr<TerrainInfo> const& childTerrain : _childTerrain) childTerrain->UnloadMapImpl(gx, gy); - _loadedGrids[GetBitsetIndex(gx, gy)] = false; + _loadedGrids[gx] &= ~(UI64LIT(1) << gy); } void TerrainInfo::UnloadMMapInstanceImpl(uint32 mapId, uint32 instanceId) @@ -294,7 +294,7 @@ GridMap* TerrainInfo::GetGrid(uint32 mapId, float x, float y, bool loadIfMissing int32 gy = (int)(CENTER_GRID_ID - y / SIZE_OF_GRIDS); //grid y // ensure GridMap is loaded - if (!_loadedGrids[GetBitsetIndex(gx, gy)] && loadIfMissing) + if (!(_loadedGrids[gx] & (UI64LIT(1) << gy)) && loadIfMissing) { std::lock_guard<std::mutex> lock(_loadMutex); LoadMapAndVMapImpl(gx, gy); @@ -303,7 +303,7 @@ GridMap* TerrainInfo::GetGrid(uint32 mapId, float x, float y, bool loadIfMissing GridMap* grid = _gridMap[gx][gy].get(); if (mapId != GetId()) { - auto childMapItr = std::find_if(_childTerrain.begin(), _childTerrain.end(), [mapId](std::shared_ptr<TerrainInfo> const& childTerrain) { return childTerrain->GetId() == mapId; }); + auto childMapItr = std::ranges::find(_childTerrain, mapId, [](std::shared_ptr<TerrainInfo> const& childTerrain) { return childTerrain->GetId(); }); if (childMapItr != _childTerrain.end() && (*childMapItr)->_gridMap[gx][gy]) grid = (*childMapItr)->GetGrid(mapId, x, y, false); } @@ -319,9 +319,10 @@ void TerrainInfo::CleanUpGrids(uint32 diff) // delete those GridMap objects which have refcount = 0 for (int32 x = 0; x < MAX_NUMBER_OF_GRIDS; ++x) - for (int32 y = 0; y < MAX_NUMBER_OF_GRIDS; ++y) - if (_loadedGrids[GetBitsetIndex(x, y)] && !_referenceCountFromMap[x][y]) - UnloadMapImpl(x, y); + if (_loadedGrids[x]) + for (int32 y = 0; y < MAX_NUMBER_OF_GRIDS; ++y) + if ((_loadedGrids[x] & (UI64LIT(1) << y)) && !_referenceCountFromMap[x][y]) + UnloadMapImpl(x, y); _cleanupTimer.Reset(CleanupInterval); } diff --git a/src/server/game/Maps/TerrainMgr.h b/src/server/game/Maps/TerrainMgr.h index 6d3879043b5..ccd06b67e42 100644 --- a/src/server/game/Maps/TerrainMgr.h +++ b/src/server/game/Maps/TerrainMgr.h @@ -23,6 +23,7 @@ #include "MapDefines.h" #include "Position.h" #include "Timer.h" +#include <array> #include <atomic> #include <bitset> #include <memory> @@ -111,8 +112,8 @@ private: std::mutex _loadMutex; std::unique_ptr<GridMap> _gridMap[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; std::atomic<uint16> _referenceCountFromMap[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; - std::bitset<MAX_NUMBER_OF_GRIDS* MAX_NUMBER_OF_GRIDS> _loadedGrids; - std::bitset<MAX_NUMBER_OF_GRIDS* MAX_NUMBER_OF_GRIDS> _gridFileExists; // cache what grids are available for this map (not including parent/child maps) + std::array<uint64, (MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS + 63) / 64> _loadedGrids; + std::bitset<MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS> _gridFileExists; // cache what grids are available for this map (not including parent/child maps) static constexpr Milliseconds CleanupInterval = 1min; 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() diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 2b65dd903fb..622c6d65142 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -2628,7 +2628,8 @@ class spell_pri_assured_safety : public spell_pri_prayer_of_mending_SpellScriptB bool Load() override { - return GetCaster()->HasAura(SPELL_PRIEST_ASSURED_SAFETY); + return spell_pri_prayer_of_mending_SpellScriptBase::Load() + && GetCaster()->HasAura(SPELL_PRIEST_ASSURED_SAFETY); } void HandleEffectHitTarget(SpellEffIndex /*effIndex*/) const |