From 70f67db1901675c018627963633e7ae09c0adbe1 Mon Sep 17 00:00:00 2001 From: Grimdhex <176165533+Grimdhex@users.noreply.github.com> Date: Sun, 22 Sep 2024 10:06:29 +0200 Subject: [PATCH] raycast around the new position for check a valid dest --- src/server/game/Entities/Object/Position.cpp | 11 +++++++++++ src/server/game/Entities/Object/Position.h | 1 + src/server/game/Maps/Map.cpp | 19 +++++++++++++++++++ src/server/game/Maps/Map.h | 2 ++ .../BlackTemple/boss_mother_shahraz.cpp | 3 +-- 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp index b8dc69f9f2..dc739c53eb 100644 --- a/src/server/game/Entities/Object/Position.cpp +++ b/src/server/game/Entities/Object/Position.cpp @@ -177,6 +177,17 @@ 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 69ff77a3a3..2e12760631 100644 --- a/src/server/game/Entities/Object/Position.h +++ b/src/server/game/Entities/Object/Position.h @@ -153,6 +153,7 @@ 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 ec3dffb8fa..77094c9339 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2751,6 +2751,25 @@ 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 in the 16 directions + 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 c4410d3843..dda92a33ee 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -480,6 +480,8 @@ 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 4aac19e795..64a2fdb30b 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp @@ -223,8 +223,7 @@ class spell_mother_shahraz_fatal_attraction : public SpellScript // 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.GetExactDist(GetCaster()) < minDist || - !GetCaster()->IsWithinLOS(teleportDest.GetPositionX(), teleportDest.GetPositionY(), teleportDest.GetPositionZ())) + while (!teleportDest.IsRadiusPositionValid(GetCaster(), teleportDest, 25.0f)) { // If the conditions are not met, find a new destination. teleportDest = GetCaster()->GetRandomNearPosition(teleportDist);