diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index ded540a57a..3a56cc8ab5 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2739,6 +2739,34 @@ Position WorldObject::GetRandomNearPosition(float radius) return pos; } +Position WorldObject::GetRandomNearPositionWithCollisionCheck(Unit* caster, float radius) +{ + Position pos = GetRandomNearPosition(radius); + + for (float angle = float(M_PI) / 8; angle < float(M_PI) * 2; angle += float(M_PI) / 8) + { + Position endPos = pos; + endPos.RelocatePolarOffset(angle, radius); + + G3D::Vector3 hitResult; + + if (GetMap()->GetObjectHitPos(caster->GetPhaseMask(), pos.m_positionX, pos.m_positionY, pos.m_positionZ, + endPos.m_positionX, endPos.m_positionY, endPos.m_positionZ, + hitResult.x, hitResult.y, hitResult.z, 0.0f)) + { + + G3D::Vector3 newPos; + newPos.x = 2 * pos.GetPositionX() - endPos.GetPositionX(); + newPos.y = 2 * pos.GetPositionY() - endPos.GetPositionY(); + newPos.z = 2 * pos.GetPositionZ() - endPos.GetPositionZ(); + pos.Relocate(newPos.x, newPos.y, newPos.z); + break; + } + } + + return pos; +} + void WorldObject::GetContactPoint(WorldObject const* obj, float& x, float& y, float& z, float distance2d) const { // angle to face `obj` to `this` using distance includes size of `obj` diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index d9d168ed47..b49bd39745 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -427,6 +427,7 @@ public: Position GetFirstCollisionPosition(float destX, float destY, float destZ); Position GetFirstCollisionPosition(float dist, float angle); Position GetRandomNearPosition(float radius); + Position GetRandomNearPositionWithCollisionCheck(Unit* caster, float radius); void GetContactPoint(WorldObject const* obj, float& x, float& y, float& z, float distance2d = CONTACT_DISTANCE) const; void GetChargeContactPoint(WorldObject const* obj, float& x, float& y, float& z, float distance2d = CONTACT_DISTANCE) const; diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp index dc739c53eb..b8dc69f9f2 100644 --- a/src/server/game/Entities/Object/Position.cpp +++ b/src/server/game/Entities/Object/Position.cpp @@ -177,17 +177,6 @@ bool Position::IsPositionValid() const return Acore::IsValidMapCoord(m_positionX, m_positionY, m_positionZ, m_orientation); } -bool Position::IsRadiusPositionValid(Unit* caster, Position startPos, float distance) const -{ - if (!IsPositionValid()) - return false; - - if (caster->GetMap()->CheckForObjectsAround(startPos, distance, caster->GetPhaseMask())) - return false; - - return true; -} - ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer) { float x, y, z, o; diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h index 2e12760631..69ff77a3a3 100644 --- a/src/server/game/Entities/Object/Position.h +++ b/src/server/game/Entities/Object/Position.h @@ -153,7 +153,6 @@ struct Position } [[nodiscard]] bool IsPositionValid() const; - [[nodiscard]] bool IsRadiusPositionValid(Unit* caster, Position startPos, float distance) const; [[nodiscard]] float GetExactDist2dSq(const float x, const float y) const { diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 4693b5f046..ec3dffb8fa 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2751,25 +2751,6 @@ uint32 Map::GetPlayersCountExceptGMs() const return count; } -bool Map::CheckForObjectsAround(Position startPos, float distance, uint32 phasemask) const -{ - for (float angle = float(M_PI) / 8; angle < float(M_PI) * 2; angle += float(M_PI) / 8) - { - Position endPos = startPos; - endPos.RelocatePolarOffset(angle, distance); - - G3D::Vector3 startVec(startPos.m_positionX, startPos.m_positionY, startPos.m_positionZ); - G3D::Vector3 endVec(endPos.m_positionX, endPos.m_positionY, endPos.m_positionZ); - G3D::Vector3 resultHit; - - if (_dynamicTree.GetObjectHitPos(phasemask, startVec, endVec, resultHit, 0.0f)) - return true; - } - - // No object found - return false; -} - void Map::SendToPlayers(WorldPacket const* data) const { for (MapRefMgr::const_iterator itr = m_mapRefMgr.begin(); itr != m_mapRefMgr.end(); ++itr) diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index dda92a33ee..c4410d3843 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -480,8 +480,6 @@ public: void AddWorldObject(WorldObject* obj) { i_worldObjects.insert(obj); } void RemoveWorldObject(WorldObject* obj) { i_worldObjects.erase(obj); } - [[nodiscard]] bool CheckForObjectsAround(Position startPos, float distance, uint32 phasemask) const; - void SendToPlayers(WorldPacket const* data) const; typedef MapRefMgr PlayerList; diff --git a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp index 109fc75185..8f60c7e83f 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp @@ -212,19 +212,7 @@ class spell_mother_shahraz_fatal_attraction : public SpellScript void SetDest(SpellDestination& dest) { - // Initialize a first destination - Position teleportDest = GetCaster()->GetRandomNearPosition(50.0f); - - // Ensure that the destination is not too close to the caster. - // Add a check for LOS, to ensure to not be teleported under the map - while (!teleportDest.IsRadiusPositionValid(GetCaster(), teleportDest, 25.0f)) - { - // If the conditions are not met, find a new destination. - teleportDest = GetCaster()->GetRandomNearPosition(50.0f); - } - - // When a valid destination is found, relocate it. - dest.Relocate(teleportDest); + dest.Relocate(GetCaster()->GetRandomNearPositionWithCollisionCheck(GetCaster(), 50.0f)); } void HandleTeleportUnits(SpellEffIndex /*effIndex*/)