Core/Vmaps: Stop M2s from occluding for spellcast LoS

Closes #18528
This commit is contained in:
HelloKitty
2017-01-21 14:44:31 +01:00
committed by Shauren
parent 998efa55d8
commit 01d715eaef
19 changed files with 108 additions and 48 deletions

View File

@@ -26,6 +26,7 @@
#include "Timer.h"
#include "GameObjectModel.h"
#include "ModelInstance.h"
#include "ModelIgnoreFlags.h"
#include <G3D/AABox.h>
#include <G3D/Ray.h>
@@ -151,7 +152,7 @@ struct DynamicTreeIntersectionCallback
DynamicTreeIntersectionCallback(uint32 phasemask) : did_hit(false), phase_mask(phasemask) { }
bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance)
{
did_hit = obj.intersectRay(r, distance, true, phase_mask);
did_hit = obj.intersectRay(r, distance, true, phase_mask, VMAP::ModelIgnoreFlags::Nothing);
return did_hit;
}
bool didHit() const { return did_hit;}
@@ -168,7 +169,7 @@ struct DynamicTreeIntersectionCallback_WithLogger
bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance)
{
TC_LOG_DEBUG("maps", "testing intersection with %s", obj.name.c_str());
bool hit = obj.intersectRay(r, distance, true, phase_mask);
bool hit = obj.intersectRay(r, distance, true, phase_mask, VMAP::ModelIgnoreFlags::Nothing);
if (hit)
{
did_hit = true;

View File

@@ -21,6 +21,7 @@
#include <string>
#include "Define.h"
#include "ModelIgnoreFlags.h"
//===========================================================
@@ -60,7 +61,7 @@ namespace VMAP
virtual void unloadMap(unsigned int pMapId, int x, int y) = 0;
virtual void unloadMap(unsigned int pMapId) = 0;
virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) = 0;
virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags) = 0;
virtual float getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist) = 0;
/**
test if we hit an object. return true if we hit one. rx, ry, rz will hold the hit position or the dest position, if no intersection was found

View File

@@ -162,7 +162,7 @@ namespace VMAP
}
}
bool VMapManager2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2)
bool VMapManager2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags)
{
if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS))
return true;
@@ -174,7 +174,7 @@ namespace VMAP
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
if (pos1 != pos2)
{
return instanceTree->second->isInLineOfSight(pos1, pos2);
return instanceTree->second->isInLineOfSight(pos1, pos2, ignoreFlags);
}
}
@@ -279,7 +279,7 @@ namespace VMAP
return false;
}
WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename)
WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */)
{
//! Critical section, thread safe access to iLoadedModelFiles
std::lock_guard<std::mutex> lock(LoadedModelFilesLock);
@@ -295,6 +295,9 @@ namespace VMAP
return NULL;
}
VMAP_DEBUG_LOG("maps", "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str());
worldmodel->Flags = flags;
model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first;
model->second.setModel(worldmodel);
}

View File

@@ -107,7 +107,7 @@ namespace VMAP
void unloadMap(unsigned int mapId, int x, int y) override;
void unloadMap(unsigned int mapId) override;
bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2) override ;
bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags) override ;
/**
fill the hit pos and return true, if an object was hit
*/
@@ -119,7 +119,7 @@ namespace VMAP
bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const override;
bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const override;
WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename);
WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags = 0);
void releaseModelInstance(const std::string& filename);
// what's the use of this? o.O

View File

@@ -33,14 +33,13 @@ using G3D::Vector3;
namespace VMAP
{
class MapRayCallback
{
public:
MapRayCallback(ModelInstance* val): prims(val), hit(false) { }
MapRayCallback(ModelInstance* val, ModelIgnoreFlags ignoreFlags): prims(val), hit(false), flags(ignoreFlags) { }
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true)
{
bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit);
bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit, flags);
if (result)
hit = true;
return result;
@@ -49,6 +48,7 @@ namespace VMAP
protected:
ModelInstance* prims;
bool hit;
ModelIgnoreFlags flags;
};
class AreaInfoCallback
@@ -142,19 +142,18 @@ namespace VMAP
If intersection is found within pMaxDist, sets pMaxDist to intersection distance and returns true.
Else, pMaxDist is not modified and returns false;
*/
bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit) const
bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
{
float distance = pMaxDist;
MapRayCallback intersectionCallBack(iTreeValues);
MapRayCallback intersectionCallBack(iTreeValues, ignoreFlags);
iTree.intersectRay(pRay, intersectionCallBack, distance, pStopAtFirstHit);
if (intersectionCallBack.didHit())
pMaxDist = distance;
return intersectionCallBack.didHit();
}
//=========================================================
bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) const
//=========================================================
bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2, ModelIgnoreFlags ignoreFlag) const
{
float maxDist = (pos2 - pos1).magnitude();
// return false if distance is over max float, in case of cheater teleporting to the end of the universe
@@ -168,7 +167,7 @@ namespace VMAP
return true;
// direction with length of 1
G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist);
if (getIntersectionTime(ray, maxDist, true))
if (getIntersectionTime(ray, maxDist, true, ignoreFlag))
return false;
return true;
@@ -194,7 +193,7 @@ namespace VMAP
Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1
G3D::Ray ray(pPos1, dir);
float dist = maxDist;
if (getIntersectionTime(ray, dist, false))
if (getIntersectionTime(ray, dist, false, ModelIgnoreFlags::Nothing))
{
pResultHitPos = pPos1 + dir * dist;
if (pModifyDist < 0)
@@ -230,7 +229,7 @@ namespace VMAP
Vector3 dir = Vector3(0, 0, -1);
G3D::Ray ray(pPos, dir); // direction with length of 1
float maxDist = maxSearchDist;
if (getIntersectionTime(ray, maxDist, false))
if (getIntersectionTime(ray, maxDist, false, ModelIgnoreFlags::Nothing))
{
height = pPos.z - maxDist;
}
@@ -306,7 +305,7 @@ namespace VMAP
#endif
if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn))
{
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name);
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags);
VMAP_DEBUG_LOG("maps", "StaticMapTree::InitMap() : loading %s", spawn.name.c_str());
if (model)
{
@@ -376,7 +375,7 @@ namespace VMAP
if (result)
{
// acquire model instance
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name);
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags);
if (!model)
VMAP_ERROR_LOG("misc", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY);

View File

@@ -23,11 +23,13 @@
#include "BoundingIntervalHierarchy.h"
#include <unordered_map>
namespace VMAP
{
class ModelInstance;
class GroupModel;
class VMapManager2;
enum class ModelIgnoreFlags : uint32;
struct TC_COMMON_API LocationInfo
{
@@ -57,7 +59,7 @@ namespace VMAP
std::string iBasePath;
private:
bool getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit) const;
bool getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
//bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); }
public:
static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY);
@@ -68,7 +70,7 @@ namespace VMAP
StaticMapTree(uint32 mapID, const std::string &basePath);
~StaticMapTree();
bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) const;
bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2, ModelIgnoreFlags ignoreFlags) const;
bool getObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const;
float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const;
bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const;

View File

@@ -153,7 +153,7 @@ GameObjectModel* GameObjectModel::Create(std::unique_ptr<GameObjectModelOwnerBas
return mdl;
}
bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const
bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask, VMAP::ModelIgnoreFlags ignoreFlags) const
{
if (!(phasemask & ph_mask) || !owner->IsSpawned())
return false;
@@ -166,7 +166,7 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto
Vector3 p = iInvRot * (ray.origin() - iPos) * iInvScale;
Ray modRay(p, iInvRot * ray.direction());
float distance = MaxDist * iInvScale;
bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit);
bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit, ignoreFlags);
if (hit)
{
distance *= iScale;

View File

@@ -30,6 +30,7 @@
namespace VMAP
{
class WorldModel;
enum class ModelIgnoreFlags : uint32;
}
class GameObject;
@@ -65,7 +66,7 @@ public:
bool isEnabled() const {return phasemask != 0;}
bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const;
bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask, VMAP::ModelIgnoreFlags ignoreFlags) const;
static GameObjectModel* Create(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath);

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ModelIgnoreFlags_h__
#define ModelIgnoreFlags_h__
#include "Define.h"
namespace VMAP
{
enum class ModelIgnoreFlags : uint32
{
Nothing = 0x00,
M2 = 0x01
};
inline ModelIgnoreFlags operator&(ModelIgnoreFlags left, ModelIgnoreFlags right) { return ModelIgnoreFlags(uint32(left) & uint32(right)); }
}
#endif // ModelIgnoreFlags_h__

View File

@@ -31,7 +31,7 @@ namespace VMAP
iInvScale = 1.f/iScale;
}
bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const
bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
{
if (!iModel)
{
@@ -55,7 +55,7 @@ namespace VMAP
Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale;
Ray modRay(p, iInvRot * pRay.direction());
float distance = pMaxDist * iInvScale;
bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit);
bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit, ignoreFlags);
if (hit)
{
distance *= iScale;

View File

@@ -31,6 +31,7 @@ namespace VMAP
class WorldModel;
struct AreaInfo;
struct LocationInfo;
enum class ModelIgnoreFlags : uint32;
enum ModelFlags
{
@@ -66,7 +67,7 @@ namespace VMAP
ModelInstance(): iInvScale(0.0f), iModel(nullptr) { }
ModelInstance(const ModelSpawn &spawn, WorldModel* model);
void setUnloaded() { iModel = nullptr; }
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const;
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
void intersectPoint(const G3D::Vector3& p, AreaInfo &info) const;
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const;
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const;

View File

@@ -19,6 +19,7 @@
#include "WorldModel.h"
#include "VMapDefinitions.h"
#include "MapTree.h"
#include "ModelIgnoreFlags.h"
using G3D::Vector3;
using G3D::Ray;
@@ -444,8 +445,16 @@ namespace VMAP
bool hit;
};
bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const
bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
{
// If the caller asked us to ignore certain objects we should check flags
if ((ignoreFlags & ModelIgnoreFlags::M2) != ModelIgnoreFlags::Nothing)
{
// M2 models are not taken into account for LoS calculation if caller requested their ignoring.
if (Flags & MOD_M2)
return false;
}
// small M2 workaround, maybe better make separate class with virtual intersection funcs
// in any case, there's no need to use a bound tree if we only have one submodel
if (groupModels.size() == 1)

View File

@@ -32,6 +32,7 @@ namespace VMAP
class TreeNode;
struct AreaInfo;
struct LocationInfo;
enum class ModelIgnoreFlags : uint32;
class TC_COMMON_API MeshTriangle
{
@@ -111,12 +112,13 @@ namespace VMAP
//! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry!
void setGroupModels(std::vector<GroupModel> &models);
void setRootWmoID(uint32 id) { RootWMOID = id; }
bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const;
bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
bool IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const;
bool GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const;
bool writeFile(const std::string &filename);
bool readFile(const std::string &filename);
void getGroupModels(std::vector<GroupModel>& outGroupModels);
uint32 Flags;
protected:
uint32 RootWMOID;
std::vector<GroupModel> groupModels;

View File

@@ -1149,7 +1149,7 @@ bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool
return distsq < maxdist * maxdist;
}
bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const
bool WorldObject::IsWithinLOSInMap(const WorldObject* obj, VMAP::ModelIgnoreFlags ignoreFlags) const
{
if (!IsInMap(obj))
return false;
@@ -1160,7 +1160,7 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const
else
obj->GetHitSpherePointFor(GetPosition(), x, y, z);
return IsWithinLOS(x, y, z);
return IsWithinLOS(x, y, z, ignoreFlags);
}
float WorldObject::GetDistance(const WorldObject* obj) const
@@ -1237,7 +1237,7 @@ bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare,
return obj && IsInMap(obj) && InSamePhase(obj) && _IsWithinDist(obj, dist2compare, is3D);
}
bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const
bool WorldObject::IsWithinLOS(float ox, float oy, float oz, VMAP::ModelIgnoreFlags ignoreFlags) const
{
/*float x, y, z;
GetPosition(x, y, z);
@@ -1251,7 +1251,7 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const
else
GetHitSpherePointFor({ ox, oy, oz }, x, y, z);
return GetMap()->isInLineOfSight(x, y, z + 2.0f, ox, oy, oz + 2.0f, GetPhaseMask());
return GetMap()->isInLineOfSight(x, y, z + 2.0f, ox, oy, oz + 2.0f, GetPhaseMask(), ignoreFlags);
}
return true;

View File

@@ -25,6 +25,7 @@
#include "GridReference.h"
#include "ObjectDefines.h"
#include "Map.h"
#include "ModelIgnoreFlags.h"
#include <set>
#include <string>
@@ -489,8 +490,8 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
// use only if you will sure about placing both object at same map
bool IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D = true) const;
bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true) const;
bool IsWithinLOS(float x, float y, float z) const;
bool IsWithinLOSInMap(WorldObject const* obj) const;
bool IsWithinLOS(float x, float y, float z, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const;
bool IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const;
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

@@ -2593,9 +2593,9 @@ 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) const
bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, VMAP::ModelIgnoreFlags ignoreFlags) const
{
return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2)
return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2, ignoreFlags)
&& _dynamicTree.isInLineOfSight(x1, y1, z1, x2, y2, z2, phasemask);
}

View File

@@ -55,6 +55,7 @@ class BattlegroundMap;
class InstanceMap;
class Transport;
namespace Trinity { struct ObjectUpdater; }
namespace VMAP { enum class ModelIgnoreFlags : uint32; }
struct ScriptAction
{
@@ -496,7 +497,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
float GetWaterOrGroundLevel(uint32 phasemask, float x, float y, float z, float* ground = NULL, bool swim = false) const;
float GetHeight(uint32 phasemask, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const;
bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const;
bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, VMAP::ModelIgnoreFlags ignoreFlags) const;
void Balance() { _dynamicTree.balance(); }
void RemoveGameObjectModel(const GameObjectModel& model) { _dynamicTree.remove(model); }
void InsertGameObjectModel(const GameObjectModel& model) { _dynamicTree.insert(model); }

View File

@@ -55,7 +55,8 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner)
mypos.m_positionX,
mypos.m_positionY,
mypos.m_positionZ + 2.0f,
x, y, z + 2.0f);
x, y, z + 2.0f,
VMAP::ModelIgnoreFlags::Nothing);
if (!isInLOS)
{
i_nextCheckTime.Reset(200);

View File

@@ -1895,7 +1895,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))
if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::M2))
{
foundItr = itr;
maxHPDeficit = deficit;
@@ -1910,10 +1910,10 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
{
if (foundItr == tempTargets.end())
{
if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr))
if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
foundItr = itr;
}
else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr))
else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
foundItr = itr;
}
}
@@ -5004,7 +5004,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
if (DynamicObject* dynObj = m_caster->GetDynObject(m_triggeredByAuraSpell->Id))
losTarget = dynObj;
if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !target->IsWithinLOSInMap(losTarget))
if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !target->IsWithinLOSInMap(losTarget, VMAP::ModelIgnoreFlags::M2))
return SPELL_FAILED_LINE_OF_SIGHT;
}
}
@@ -5016,7 +5016,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
float x, y, z;
m_targets.GetDstPos()->GetPosition(x, y, z);
if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOS(x, y, z))
if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOS(x, y, z, VMAP::ModelIgnoreFlags::M2))
return SPELL_FAILED_LINE_OF_SIGHT;
}
@@ -5258,6 +5258,10 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
if (!target)
return SPELL_FAILED_DONT_REPORT;
// first we must check to see if the target is in LoS. A path can usually be built but LoS matters for charge spells
if (!target->IsWithinLOSInMap(m_caster)) //Do full LoS/Path check. Don't exclude m2
return SPELL_FAILED_LINE_OF_SIGHT;
float objSize = target->GetObjectSize();
float range = m_spellInfo->GetMaxRange(true, m_caster, this) * 1.5f + objSize; // can't be overly strict
@@ -6786,7 +6790,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo
default: // normal case
{
if (losPosition)
return target->IsWithinLOS(losPosition->GetPositionX(), losPosition->GetPositionY(), losPosition->GetPositionZ());
return target->IsWithinLOS(losPosition->GetPositionX(), losPosition->GetPositionY(), losPosition->GetPositionZ(), VMAP::ModelIgnoreFlags::M2);
else
{
// Get GO cast coordinates if original caster -> GO
@@ -6795,7 +6799,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo
caster = m_caster->GetMap()->GetGameObject(m_originalCasterGUID);
if (!caster)
caster = m_caster;
if (target != m_caster && !target->IsWithinLOSInMap(caster))
if (target != m_caster && !target->IsWithinLOSInMap(caster, VMAP::ModelIgnoreFlags::M2))
return false;
}
break;