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:
UltraNix
2022-04-10 14:24:35 +02:00
committed by GitHub
parent 6efc08f42e
commit 47790c9714
27 changed files with 295 additions and 101 deletions

View File

@@ -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`

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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:

View File

@@ -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);