mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-25 06:36:24 +00:00
fix(Core/Vmaps): Stop M2s from occluding for spellcast LoS. Original autho… (#11341)
* Core/Vmaps: Stop M2s from occluding for spellcast LoS. Original authors: @Shauren & @HelloKitty Fixes #11293 * buildfix. Co-Authored-By: HelloKitty <5829095+HelloKitty@users.noreply.github.com>
This commit is contained in:
@@ -647,6 +647,25 @@ struct GameObjectTemplate
|
||||
{
|
||||
return IsForQuests;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsIgnoringLOSChecks() const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GAMEOBJECT_TYPE_BUTTON:
|
||||
return button.losOK == 0;
|
||||
case GAMEOBJECT_TYPE_QUESTGIVER:
|
||||
return questgiver.losOK == 0;
|
||||
case GAMEOBJECT_TYPE_CHEST:
|
||||
return chest.losOK == 0;
|
||||
case GAMEOBJECT_TYPE_GOOBER:
|
||||
return goober.losOK == 0;
|
||||
case GAMEOBJECT_TYPE_FLAGSTAND:
|
||||
return flagstand.losOK == 0;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// From `gameobject_template_addon`
|
||||
|
||||
@@ -1320,7 +1320,7 @@ bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare,
|
||||
return obj && IsInMap(obj) && InSamePhase(obj) && _IsWithinDist(obj, dist2compare, is3D, useBoundingRadius);
|
||||
}
|
||||
|
||||
bool WorldObject::IsWithinLOS(float ox, float oy, float oz, LineOfSightChecks checks) const
|
||||
bool WorldObject::IsWithinLOS(float ox, float oy, float oz, VMAP::ModelIgnoreFlags ignoreFlags, LineOfSightChecks checks) const
|
||||
{
|
||||
if (IsInWorld())
|
||||
{
|
||||
@@ -1336,12 +1336,12 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz, LineOfSightChecks ch
|
||||
GetHitSpherePointFor({ ox, oy, oz }, x, y, z);
|
||||
}
|
||||
|
||||
return GetMap()->isInLineOfSight(x, y, z, ox, oy, oz, GetPhaseMask(), checks);
|
||||
return GetMap()->isInLineOfSight(x, y, z, ox, oy, oz, GetPhaseMask(), checks, ignoreFlags);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldObject::IsWithinLOSInMap(WorldObject const* obj, LineOfSightChecks checks) const
|
||||
bool WorldObject::IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlags ignoreFlags, LineOfSightChecks checks) const
|
||||
{
|
||||
if (!IsInMap(obj))
|
||||
return false;
|
||||
@@ -1364,7 +1364,7 @@ bool WorldObject::IsWithinLOSInMap(WorldObject const* obj, LineOfSightChecks che
|
||||
else
|
||||
GetHitSpherePointFor({ obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ() + obj->GetCollisionHeight() }, x, y, z);
|
||||
|
||||
return GetMap()->isInLineOfSight(x, y, z, ox, oy, oz, GetPhaseMask(), checks);
|
||||
return GetMap()->isInLineOfSight(x, y, z, ox, oy, oz, GetPhaseMask(), checks, ignoreFlags);
|
||||
}
|
||||
|
||||
void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "GridDefines.h"
|
||||
#include "GridReference.h"
|
||||
#include "Map.h"
|
||||
#include "ModelIgnoreFlags.h"
|
||||
#include "ObjectDefines.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "Optional.h"
|
||||
@@ -455,8 +456,8 @@ public:
|
||||
// use only if you will sure about placing both object at same map
|
||||
bool IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D = true, bool useBoundingRadius = true) const;
|
||||
bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true, bool useBoundingRadius = true) const;
|
||||
[[nodiscard]] bool IsWithinLOS(float x, float y, float z, LineOfSightChecks checks = LINEOFSIGHT_ALL_CHECKS) const;
|
||||
bool IsWithinLOSInMap(WorldObject const* obj, LineOfSightChecks checks = LINEOFSIGHT_ALL_CHECKS) const;
|
||||
[[nodiscard]] bool IsWithinLOS(float x, float y, float z, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing, LineOfSightChecks checks = LINEOFSIGHT_ALL_CHECKS) const;
|
||||
[[nodiscard]] bool IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing, LineOfSightChecks checks = LINEOFSIGHT_ALL_CHECKS) const;
|
||||
[[nodiscard]] Position GetHitSpherePointFor(Position const& dest) const;
|
||||
void GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const;
|
||||
bool GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D = true) const;
|
||||
|
||||
@@ -2023,7 +2023,7 @@ Transport* Map::GetTransportForPos(uint32 phase, float x, float y, float z, Worl
|
||||
if ((*itr)->IsInWorld() && (*itr)->GetExactDistSq(x, y, z) < 75.0f * 75.0f && (*itr)->m_model)
|
||||
{
|
||||
float dist = 30.0f;
|
||||
bool hit = (*itr)->m_model->intersectRay(r, dist, false, phase);
|
||||
bool hit = (*itr)->m_model->intersectRay(r, dist, false, phase, VMAP::ModelIgnoreFlags::Nothing);
|
||||
if (hit)
|
||||
return *itr;
|
||||
}
|
||||
@@ -2033,7 +2033,7 @@ Transport* Map::GetTransportForPos(uint32 phase, float x, float y, float z, Worl
|
||||
if (staticTrans->m_model)
|
||||
{
|
||||
float dist = 10.0f;
|
||||
bool hit = staticTrans->m_model->intersectRay(r, dist, false, phase);
|
||||
bool hit = staticTrans->m_model->intersectRay(r, dist, false, phase, VMAP::ModelIgnoreFlags::Nothing);
|
||||
if (hit)
|
||||
if (GetHeight(phase, x, y, z, true, 30.0f) < (v.z - dist + 1.0f))
|
||||
return staticTrans->ToTransport();
|
||||
@@ -2440,14 +2440,27 @@ float Map::GetWaterLevel(float x, float y) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, LineOfSightChecks checks) const
|
||||
bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const
|
||||
{
|
||||
if ((checks & LINEOFSIGHT_CHECK_VMAP) && !VMAP::VMapFactory::createOrGetVMapMgr()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2))
|
||||
if ((checks & LINEOFSIGHT_CHECK_VMAP) && !VMAP::VMapFactory::createOrGetVMapMgr()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2, ignoreFlags))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_CHECK_GOBJECT_LOS) && (checks & LINEOFSIGHT_CHECK_GOBJECT_ALL))
|
||||
{
|
||||
ignoreFlags = VMAP::ModelIgnoreFlags::Nothing;
|
||||
if (!(checks & LINEOFSIGHT_CHECK_GOBJECT_M2))
|
||||
{
|
||||
ignoreFlags = VMAP::ModelIgnoreFlags::M2;
|
||||
}
|
||||
|
||||
if (!_dynamicTree.isInLineOfSight(x1, y1, z1, x2, y2, z2, phasemask, ignoreFlags))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_CHECK_GOBJECT_LOS) && (checks & LINEOFSIGHT_CHECK_GOBJECT)
|
||||
&& !_dynamicTree.isInLineOfSight(x1, y1, z1, x2, y2, z2, phasemask))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,11 @@ class PathGenerator;
|
||||
|
||||
enum WeatherState : uint32;
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
enum class ModelIgnoreFlags : uint32;
|
||||
}
|
||||
|
||||
namespace Acore
|
||||
{
|
||||
struct ObjectUpdater;
|
||||
@@ -183,10 +188,13 @@ struct PositionFullTerrainStatus
|
||||
|
||||
enum LineOfSightChecks
|
||||
{
|
||||
LINEOFSIGHT_CHECK_VMAP = 0x1, // check static floor layout data
|
||||
LINEOFSIGHT_CHECK_GOBJECT = 0x2, // check dynamic game object data
|
||||
LINEOFSIGHT_CHECK_VMAP = 0x1, // check static floor layout data
|
||||
LINEOFSIGHT_CHECK_GOBJECT_WMO = 0x2, // check dynamic game object data (wmo models)
|
||||
LINEOFSIGHT_CHECK_GOBJECT_M2 = 0x4, // check dynamic game object data (m2 models)
|
||||
|
||||
LINEOFSIGHT_ALL_CHECKS = (LINEOFSIGHT_CHECK_VMAP | LINEOFSIGHT_CHECK_GOBJECT)
|
||||
LINEOFSIGHT_CHECK_GOBJECT_ALL = LINEOFSIGHT_CHECK_GOBJECT_WMO | LINEOFSIGHT_CHECK_GOBJECT_M2,
|
||||
|
||||
LINEOFSIGHT_ALL_CHECKS = LINEOFSIGHT_CHECK_VMAP | LINEOFSIGHT_CHECK_GOBJECT_ALL
|
||||
};
|
||||
|
||||
class GridMap
|
||||
@@ -539,7 +547,7 @@ public:
|
||||
|
||||
float GetWaterOrGroundLevel(uint32 phasemask, float x, float y, float z, float* ground = nullptr, bool swim = false, float collisionHeight = DEFAULT_COLLISION_HEIGHT) const;
|
||||
[[nodiscard]] float GetHeight(uint32 phasemask, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const;
|
||||
[[nodiscard]] bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, LineOfSightChecks checks) const;
|
||||
[[nodiscard]] bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const;
|
||||
bool CanReachPositionAndGetValidCoords(WorldObject const* source, PathGenerator *path, float &destX, float &destY, float &destZ, bool failOnCollision = true, bool failOnSlopes = true) const;
|
||||
bool CanReachPositionAndGetValidCoords(WorldObject const* source, float &destX, float &destY, float &destZ, bool failOnCollision = true, bool failOnSlopes = true) const;
|
||||
bool CanReachPositionAndGetValidCoords(WorldObject const* source, float startX, float startY, float startZ, float &destX, float &destY, float &destZ, bool failOnCollision = true, bool failOnSlopes = true) const;
|
||||
|
||||
@@ -1052,12 +1052,10 @@ void PathGenerator::ShortenPathUntilDist(G3D::Vector3 const& target, float dist)
|
||||
|
||||
// check if the shortened path is still in LoS with the target and it is walkable
|
||||
_source->GetHitSpherePointFor({ _pathPoints[i - 1].x, _pathPoints[i - 1].y, _pathPoints[i - 1].z + collisionHeight }, x, y, z);
|
||||
if (!_source->GetMap()->isInLineOfSight(x, y, z, _pathPoints[i - 1].x, _pathPoints[i - 1].y, _pathPoints[i - 1].z + collisionHeight, _source->GetPhaseMask(), LINEOFSIGHT_ALL_CHECKS)
|
||||
|| (canCheckSlope
|
||||
&& !IsSwimmableSegment(_source->GetPositionX(), _source->GetPositionY(), _source->GetPositionZ(), _pathPoints[i - 1].x, _pathPoints[i - 1].y, _pathPoints[i - 1].z)
|
||||
&& !IsWalkableClimb(_source->GetPositionX(), _source->GetPositionY(), _source->GetPositionZ(), _pathPoints[i - 1].x, _pathPoints[i - 1].y, _pathPoints[i - 1].z)
|
||||
)
|
||||
)
|
||||
if (!_source->GetMap()->isInLineOfSight(x, y, z, _pathPoints[i - 1].x, _pathPoints[i - 1].y, _pathPoints[i - 1].z + collisionHeight,
|
||||
_source->GetPhaseMask(), LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::Nothing) || (canCheckSlope &&
|
||||
!IsSwimmableSegment(_source->GetPositionX(), _source->GetPositionY(), _source->GetPositionZ(), _pathPoints[i - 1].x, _pathPoints[i - 1].y, _pathPoints[i - 1].z) &&
|
||||
!IsWalkableClimb(_source->GetPositionX(), _source->GetPositionY(), _source->GetPositionZ(), _pathPoints[i - 1].x, _pathPoints[i - 1].y, _pathPoints[i - 1].z)))
|
||||
{
|
||||
// whenver we find a point that is not valid anymore, simply use last valid path
|
||||
_pathPoints.resize(i + 1);
|
||||
|
||||
@@ -165,7 +165,8 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!map->isInLineOfSight((*itr).x, (*itr).y, (*itr).z + 2.f, (*itrNext).x, (*itrNext).y, (*itrNext).z + 2.f, creature->GetPhaseMask(), LINEOFSIGHT_ALL_CHECKS))
|
||||
if (!map->isInLineOfSight((*itr).x, (*itr).y, (*itr).z + 2.f, (*itrNext).x, (*itrNext).y, (*itrNext).z + 2.f, creature->GetPhaseMask(),
|
||||
LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::Nothing))
|
||||
{
|
||||
_validPointsVector[_currentPoint].erase(randomIter);
|
||||
_preComputedPaths.erase(pathIdx);
|
||||
|
||||
@@ -2049,7 +2049,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
|
||||
if (Unit* unit = (*itr)->ToUnit())
|
||||
{
|
||||
uint32 deficit = unit->GetMaxHealth() - unit->GetHealth();
|
||||
if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit, LINEOFSIGHT_ALL_CHECKS))
|
||||
if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::M2))
|
||||
{
|
||||
foundItr = itr;
|
||||
maxHPDeficit = deficit;
|
||||
@@ -2064,10 +2064,10 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
|
||||
{
|
||||
if (foundItr == tempTargets.end())
|
||||
{
|
||||
if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr, LINEOFSIGHT_ALL_CHECKS))
|
||||
if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
|
||||
foundItr = itr;
|
||||
}
|
||||
else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr, LINEOFSIGHT_ALL_CHECKS))
|
||||
else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
|
||||
foundItr = itr;
|
||||
}
|
||||
}
|
||||
@@ -5617,9 +5617,38 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||
if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER) && !target->HasInArc(static_cast<float>(M_PI), m_caster))
|
||||
return SPELL_FAILED_NOT_INFRONT;
|
||||
|
||||
if (m_caster->GetEntry() != WORLD_TRIGGER) // Ignore LOS for gameobjects casts (wrongly casted by a trigger)
|
||||
if ((!m_caster->IsTotem() || !m_spellInfo->IsPositive()) && !m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) && !m_spellInfo->HasAttribute(SPELL_ATTR5_ALWAYS_AOE_LINE_OF_SIGHT) && !m_caster->IsWithinLOSInMap(target, LINEOFSIGHT_ALL_CHECKS) && !(m_spellFlags & SPELL_FLAG_REDIRECTED))
|
||||
if ((!m_caster->IsTotem() || !m_spellInfo->IsPositive()) && !m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) &&
|
||||
!m_spellInfo->HasAttribute(SPELL_ATTR5_ALWAYS_AOE_LINE_OF_SIGHT) && !(m_spellFlags & SPELL_FLAG_REDIRECTED))
|
||||
{
|
||||
WorldObject* losCenter = nullptr;
|
||||
uint32 losChecks = LINEOFSIGHT_ALL_CHECKS;
|
||||
if (m_originalCasterGUID.IsGameObject())
|
||||
{
|
||||
losCenter = m_caster->GetMap()->GetGameObject(m_originalCasterGUID);
|
||||
}
|
||||
else if (m_caster->GetEntry() == WORLD_TRIGGER)
|
||||
{
|
||||
if (TempSummon* tempSummon = m_caster->ToTempSummon())
|
||||
{
|
||||
losCenter = tempSummon->GetSummonerGameObject();
|
||||
}
|
||||
}
|
||||
|
||||
if (losCenter)
|
||||
{
|
||||
// If spell casted by gameobject then ignore M2 models
|
||||
losChecks &= ~LINEOFSIGHT_CHECK_GOBJECT_M2;
|
||||
}
|
||||
else
|
||||
{
|
||||
losCenter = m_caster;
|
||||
}
|
||||
|
||||
if (!losCenter->IsWithinLOSInMap(target, VMAP::ModelIgnoreFlags::M2, LineOfSightChecks(losChecks)))
|
||||
{
|
||||
return SPELL_FAILED_LINE_OF_SIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5629,8 +5658,38 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||
float x, y, z;
|
||||
m_targets.GetDstPos()->GetPosition(x, y, z);
|
||||
|
||||
if ((!m_caster->IsTotem() || !m_spellInfo->IsPositive()) && !m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) && !m_spellInfo->HasAttribute(SPELL_ATTR5_ALWAYS_AOE_LINE_OF_SIGHT) && !m_caster->IsWithinLOS(x, y, z, LINEOFSIGHT_ALL_CHECKS))
|
||||
return SPELL_FAILED_LINE_OF_SIGHT;
|
||||
if ((!m_caster->IsTotem() || !m_spellInfo->IsPositive()) && !m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) &&
|
||||
!m_spellInfo->HasAttribute(SPELL_ATTR5_ALWAYS_AOE_LINE_OF_SIGHT))
|
||||
{
|
||||
WorldObject* losCenter = nullptr;
|
||||
uint32 losChecks = LINEOFSIGHT_ALL_CHECKS;
|
||||
if (m_originalCasterGUID.IsGameObject())
|
||||
{
|
||||
losCenter = m_caster->GetMap()->GetGameObject(m_originalCasterGUID);
|
||||
}
|
||||
else if (m_caster->GetEntry() == WORLD_TRIGGER)
|
||||
{
|
||||
if (TempSummon* tempSummon = m_caster->ToTempSummon())
|
||||
{
|
||||
losCenter = tempSummon->GetSummonerGameObject();
|
||||
}
|
||||
}
|
||||
|
||||
if (losCenter)
|
||||
{
|
||||
// If spell casted by gameobject then ignore M2 models
|
||||
losChecks &= ~LINEOFSIGHT_CHECK_GOBJECT_M2;
|
||||
}
|
||||
else
|
||||
{
|
||||
losCenter = m_caster;
|
||||
}
|
||||
|
||||
if (!losCenter->IsWithinLOS(x, y, z, VMAP::ModelIgnoreFlags::M2, LineOfSightChecks((losChecks))))
|
||||
{
|
||||
return SPELL_FAILED_LINE_OF_SIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check pet presence
|
||||
@@ -7626,7 +7685,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
|
||||
{
|
||||
case SPELL_EFFECT_RESURRECT_NEW:
|
||||
// player far away, maybe his corpse near?
|
||||
if (target != m_caster && !target->IsWithinLOSInMap(m_caster, LINEOFSIGHT_ALL_CHECKS))
|
||||
if (target != m_caster && !target->IsWithinLOSInMap(m_caster))
|
||||
{
|
||||
if (!m_targets.GetCorpseTargetGUID())
|
||||
return false;
|
||||
@@ -7638,7 +7697,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
|
||||
if (target->GetGUID() != corpse->GetOwnerGUID())
|
||||
return false;
|
||||
|
||||
if (!corpse->IsWithinLOSInMap(m_caster, LINEOFSIGHT_ALL_CHECKS) && !(m_spellFlags & SPELL_FLAG_REDIRECTED))
|
||||
if (!corpse->IsWithinLOSInMap(m_caster) && !(m_spellFlags & SPELL_FLAG_REDIRECTED))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -7646,7 +7705,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
|
||||
{
|
||||
if (!m_targets.GetCorpseTargetGUID())
|
||||
{
|
||||
if (target->IsWithinLOSInMap(m_caster, LINEOFSIGHT_ALL_CHECKS) && target->HasUnitFlag(UNIT_FLAG_SKINNABLE))
|
||||
if (target->IsWithinLOSInMap(m_caster, VMAP::ModelIgnoreFlags::M2) && target->HasUnitFlag(UNIT_FLAG_SKINNABLE))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -7662,7 +7721,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
|
||||
if (!corpse->HasFlag(CORPSE_FIELD_FLAGS, CORPSE_FLAG_LOOTABLE))
|
||||
return false;
|
||||
|
||||
if (!corpse->IsWithinLOSInMap(m_caster, LINEOFSIGHT_ALL_CHECKS))
|
||||
if (!corpse->IsWithinLOSInMap(m_caster, VMAP::ModelIgnoreFlags::M2))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -7676,14 +7735,40 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
|
||||
if (target->ToPlayer()->getLevel() >= sWorld->getIntConfig(CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL))
|
||||
return false;
|
||||
break;
|
||||
|
||||
default: // normal case
|
||||
// Get GO cast coordinates if original caster -> GO
|
||||
WorldObject* caster = nullptr;
|
||||
default: // normal case
|
||||
{
|
||||
uint32 losChecks = LINEOFSIGHT_ALL_CHECKS;
|
||||
GameObject* gobCaster = nullptr;
|
||||
if (m_originalCasterGUID.IsGameObject())
|
||||
caster = m_caster->GetMap()->GetGameObject(m_originalCasterGUID);
|
||||
if (!caster)
|
||||
{
|
||||
gobCaster = m_caster->GetMap()->GetGameObject(m_originalCasterGUID);
|
||||
}
|
||||
else if (m_caster->GetEntry() == WORLD_TRIGGER)
|
||||
{
|
||||
if (TempSummon* tempSummon = m_caster->ToTempSummon())
|
||||
{
|
||||
gobCaster = tempSummon->GetSummonerGameObject();
|
||||
}
|
||||
}
|
||||
|
||||
WorldObject* caster = nullptr;
|
||||
if (gobCaster)
|
||||
{
|
||||
if (gobCaster->GetGOInfo()->IsIgnoringLOSChecks())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
caster = gobCaster;
|
||||
|
||||
// If spell casted by gameobject then ignore M2 models
|
||||
losChecks &= ~LINEOFSIGHT_CHECK_GOBJECT_M2;
|
||||
}
|
||||
else
|
||||
{
|
||||
caster = m_caster;
|
||||
}
|
||||
|
||||
if (target != m_caster)
|
||||
{
|
||||
if (m_targets.HasDst())
|
||||
@@ -7692,13 +7777,18 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
|
||||
float y = m_targets.GetDstPos()->GetPositionY();
|
||||
float z = m_targets.GetDstPos()->GetPositionZ();
|
||||
|
||||
if (!target->IsWithinLOS(x, y, z, LINEOFSIGHT_ALL_CHECKS))
|
||||
if (!target->IsWithinLOS(x, y, z, VMAP::ModelIgnoreFlags::M2, LineOfSightChecks(losChecks)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!target->IsWithinLOSInMap(caster, LINEOFSIGHT_ALL_CHECKS))
|
||||
else if (!target->IsWithinLOSInMap(caster, VMAP::ModelIgnoreFlags::M2, LineOfSightChecks(losChecks)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -4229,12 +4229,6 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
spellInfo->AttributesEx |= SPELL_ATTR1_EXCLUDE_CASTER;
|
||||
});
|
||||
|
||||
// Suppression Aura
|
||||
ApplySpellFix({ 22247 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT;
|
||||
});
|
||||
|
||||
// Cosmetic - Lightning Beam Channel
|
||||
ApplySpellFix({ 45537 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
|
||||
@@ -1000,8 +1000,8 @@ public:
|
||||
{
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
handler->PSendSysMessage("Checking LoS %s -> %s:", player->GetName().c_str(), unit->GetName().c_str());
|
||||
handler->PSendSysMessage(" VMAP LoS: %s", player->IsWithinLOSInMap(unit, LINEOFSIGHT_CHECK_VMAP) ? "clear" : "obstructed");
|
||||
handler->PSendSysMessage(" GObj LoS: %s", player->IsWithinLOSInMap(unit, LINEOFSIGHT_CHECK_GOBJECT) ? "clear" : "obstructed");
|
||||
handler->PSendSysMessage(" VMAP LoS: %s", player->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::Nothing, LINEOFSIGHT_CHECK_VMAP) ? "clear" : "obstructed");
|
||||
handler->PSendSysMessage(" GObj LoS: %s", player->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::Nothing, LINEOFSIGHT_CHECK_GOBJECT_ALL) ? "clear" : "obstructed");
|
||||
handler->PSendSysMessage("%s is %sin line of sight of %s.", unit->GetName().c_str(), (player->IsWithinLOSInMap(unit) ? "" : "not "), player->GetName().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1763,7 +1763,9 @@ public:
|
||||
{
|
||||
float destX = summoner->GetPositionX() + cos(angle + a * M_PI) * i * 10.0f;
|
||||
float destY = summoner->GetPositionY() + std::sin(angle + a * M_PI) * i * 10.0f;
|
||||
if (summoner->GetMap()->isInLineOfSight(summoner->GetPositionX(), summoner->GetPositionY(), summoner->GetPositionZ() + 10.0f, destX, destY, summoner->GetPositionZ() + 10.0f, summoner->GetPhaseMask(), LINEOFSIGHT_ALL_CHECKS) && destX > 4585.0f && destY > 2716.0f && destY < 2822.0f)
|
||||
if (summoner->GetMap()->isInLineOfSight(summoner->GetPositionX(), summoner->GetPositionY(), summoner->GetPositionZ() + 10.0f, destX, destY,
|
||||
summoner->GetPositionZ() + 10.0f, summoner->GetPhaseMask(), LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::Nothing) &&
|
||||
destX > 4585.0f && destY > 2716.0f && destY < 2822.0f)
|
||||
{
|
||||
float destZ = summoner->GetMapHeight(summoner->GetPhaseMask(), destX, destY, summoner->GetPositionZ());
|
||||
if (std::fabs(destZ - summoner->GetPositionZ()) < 10.0f) // valid z found
|
||||
|
||||
@@ -1285,7 +1285,7 @@ public:
|
||||
float ox, oy, oz;
|
||||
_caster->GetPosition(ox, oy, oz);
|
||||
DynamicMapTree const& dTree = unit->GetMap()->GetDynamicMapTree();
|
||||
return !dTree.isInLineOfSight(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ() + 2.f, ox, oy, oz + 2.f, unit->GetPhaseMask());
|
||||
return !dTree.isInLineOfSight(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ() + 2.f, ox, oy, oz + 2.f, unit->GetPhaseMask(), VMAP::ModelIgnoreFlags::Nothing);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -125,7 +125,8 @@ public:
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!activated && who->GetTypeId() == TYPEID_PLAYER)
|
||||
if (me->GetExactDist2d(who) <= 25.0f && me->GetMap()->isInLineOfSight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 5.0f, who->GetPositionX(), who->GetPositionY(), who->GetPositionZ() + 5.0f, 2, LINEOFSIGHT_ALL_CHECKS))
|
||||
if (me->GetExactDist2d(who) <= 25.0f && me->GetMap()->isInLineOfSight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 5.0f,
|
||||
who->GetPositionX(), who->GetPositionY(), who->GetPositionZ() + 5.0f, 2, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::Nothing))
|
||||
{
|
||||
activated = true;
|
||||
me->RemoveAura(64615);
|
||||
|
||||
Reference in New Issue
Block a user