diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index ded540a57a9274..8dc14fde373e82 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2725,17 +2725,17 @@ bool WorldObject::GetClosePoint(float& x, float& y, float& z, float size, float return true; } -Position WorldObject::GetNearPosition(float dist, float angle) +Position WorldObject::GetNearPosition(float dist, float angle, bool disableWarning) { Position pos = GetPosition(); - MovePosition(pos, dist, angle); + MovePosition(pos, dist, angle, disableWarning); return pos; } -Position WorldObject::GetRandomNearPosition(float radius) +Position WorldObject::GetRandomNearPosition(float radius, bool disableWarning) { Position pos = GetPosition(); - MovePosition(pos, radius * (float) rand_norm(), (float) rand_norm() * static_cast(2 * M_PI)); + MovePosition(pos, radius * (float) rand_norm(), (float) rand_norm() * static_cast(2 * M_PI), disableWarning); return pos; } @@ -2773,7 +2773,7 @@ void WorldObject::GetChargeContactPoint(WorldObject const* obj, float& x, float& return (m_valuesCount > UNIT_FIELD_COMBATREACH) ? m_floatValues[UNIT_FIELD_COMBATREACH] : DEFAULT_WORLD_OBJECT_SIZE * GetObjectScale(); } -void WorldObject::MovePosition(Position& pos, float dist, float angle) +void WorldObject::MovePosition(Position& pos, float dist, float angle, bool disableWarning) { angle += GetOrientation(); float destx, desty, destz, ground, floor; @@ -2783,7 +2783,9 @@ void WorldObject::MovePosition(Position& pos, float dist, float angle) // Prevent invalid coordinates here, position is unchanged if (!Acore::IsValidMapCoord(destx, desty)) { - LOG_FATAL("entities.object", "WorldObject::MovePosition invalid coordinates X: {} and Y: {} were passed!", destx, desty); + if (!disableWarning) + LOG_FATAL("entities.object", "WorldObject::MovePosition invalid coordinates X: {} and Y: {} were passed!", destx, desty); + return; } diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index d9d168ed478ae1..e0792f840bd219 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -420,13 +420,13 @@ class WorldObject : public Object, public WorldLocation void GetNearPoint(WorldObject const* searcher, float& x, float& y, float& z, float searcher_size, float distance2d, float absAngle, float controlZ = 0, Position const* startPos = nullptr) const; void GetVoidClosePoint(float& x, float& y, float& z, float size, float distance2d = 0, float relAngle = 0, float controlZ = 0) const; bool GetClosePoint(float& x, float& y, float& z, float size, float distance2d = 0, float angle = 0, WorldObject const* forWho = nullptr, bool force = false) const; - void MovePosition(Position& pos, float dist, float angle); - Position GetNearPosition(float dist, float angle); + void MovePosition(Position& pos, float dist, float angle, bool disableWarning = false); + Position GetNearPosition(float dist, float angle, bool disableWarning = false); void MovePositionToFirstCollision(Position& pos, float dist, float angle); Position GetFirstCollisionPosition(float startX, float startY, float startZ, float destX, float destY); Position GetFirstCollisionPosition(float destX, float destY, float destZ); Position GetFirstCollisionPosition(float dist, float angle); - Position GetRandomNearPosition(float radius); + Position GetRandomNearPosition(float radius, bool disableWarning = false); 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/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp index 31bf701687f5c1..bbcc997684143c 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp @@ -196,6 +196,17 @@ class spell_mother_shahraz_saber_lash_aura : public AuraScript } }; +const Position validTeleportStairsPos[4] = +{ + {966.87f, 184.45f, 192.84f}, + {927.22f, 187.04f, 192.84f}, + {922.54f, 110.09f, 192.84f}, + {958.01f, 110.47f, 192.84f} +}; + +constexpr float minTeleportDist = 30.f; +constexpr float maxTeleportDist = 50.f; + class spell_mother_shahraz_fatal_attraction : public SpellScript { PrepareSpellScript(spell_mother_shahraz_fatal_attraction); @@ -212,7 +223,44 @@ class spell_mother_shahraz_fatal_attraction : public SpellScript void SetDest(SpellDestination& dest) { - dest.Relocate(GetCaster()->GetRandomNearPosition(50.0f)); + Position finalDest; + + // Check if the boss is near stairs to avoid players falling through the platform with random teleports. + if(GetCaster()->GetPositionY() < 194.f) + finalDest = validTeleportStairsPos[urand(0, 3)]; + else + { + finalDest = GetCaster()->GetNearPosition(frand(minTeleportDist, maxTeleportDist), static_cast(rand_norm()) * static_cast(2 * M_PI), true); + + // Maybe not necessary but just in case to avoid LOS issues with an object + if(!GetCaster()->IsWithinLOS(finalDest.GetPositionX(), finalDest.GetPositionY(), finalDest.GetPositionZ())) + finalDest = GetCaster()->GetNearPosition(frand(minTeleportDist, maxTeleportDist), static_cast(rand_norm()) * static_cast(2 * M_PI), true); + + /* @note: To avoid teleporting players near a walls, we will define a safe area. + * As the boss have an area boudary around y: 320.f. We will limit the safe area to this value, avoiding wird issues. + * x limit: 932.f/960.f | y limit: 224.f/320.f + */ + if (finalDest.m_positionX < 932.f) + finalDest.m_positionX = 932.f; + else if (finalDest.m_positionX > 960.f) + finalDest.m_positionX = 960.f; + + if (finalDest.m_positionY < 224.f) + finalDest.m_positionY = 224.f; + else if (finalDest.m_positionY > 320.f) + finalDest.m_positionY = 320.f; + + // After relocate a finalDest outside the safe area, we need to recheck the distance with the boss + if (GetCaster()->GetExactDist2d(finalDest) < minTeleportDist) + { + if (finalDest.m_positionX == 932.f || finalDest.m_positionX == 960.f) + finalDest.m_positionY = finalDest.m_positionY + (minTeleportDist - GetCaster()->GetExactDist2d(finalDest)); + else if (finalDest.m_positionY == 224.f || finalDest.m_positionY == 320.f) + finalDest.m_positionX = finalDest.m_positionX + (minTeleportDist - GetCaster()->GetExactDist2d(finalDest)); + } + } + + dest.Relocate(finalDest); } void HandleTeleportUnits(SpellEffIndex /*effIndex*/)