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:
@@ -19,6 +19,7 @@
|
|||||||
#include "BoundingIntervalHierarchyWrapper.h"
|
#include "BoundingIntervalHierarchyWrapper.h"
|
||||||
#include "GameObjectModel.h"
|
#include "GameObjectModel.h"
|
||||||
#include "MapTree.h"
|
#include "MapTree.h"
|
||||||
|
#include "ModelIgnoreFlags.h"
|
||||||
#include "ModelInstance.h"
|
#include "ModelInstance.h"
|
||||||
#include "RegularGrid.h"
|
#include "RegularGrid.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
@@ -145,25 +146,33 @@ void DynamicMapTree::update(uint32 t_diff)
|
|||||||
|
|
||||||
struct DynamicTreeIntersectionCallback
|
struct DynamicTreeIntersectionCallback
|
||||||
{
|
{
|
||||||
bool did_hit;
|
DynamicTreeIntersectionCallback(uint32 phasemask, VMAP::ModelIgnoreFlags ignoreFlags) :
|
||||||
uint32 phase_mask;
|
_didHit(false), _phaseMask(phasemask), _ignoreFlags(ignoreFlags) { }
|
||||||
DynamicTreeIntersectionCallback(uint32 phasemask) : did_hit(false), phase_mask(phasemask) { }
|
|
||||||
bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance, bool stopAtFirstHit)
|
bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance, bool stopAtFirstHit)
|
||||||
{
|
{
|
||||||
bool result = obj.intersectRay(r, distance, stopAtFirstHit, phase_mask);
|
bool result = obj.intersectRay(r, distance, stopAtFirstHit, _phaseMask, _ignoreFlags);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
did_hit = result;
|
_didHit = result;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
bool didHit() const { return did_hit;}
|
|
||||||
|
[[nodiscard]] bool didHit() const
|
||||||
|
{
|
||||||
|
return _didHit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _didHit;
|
||||||
|
uint32 _phaseMask;
|
||||||
|
VMAP::ModelIgnoreFlags _ignoreFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DynamicTreeAreaInfoCallback
|
struct DynamicTreeAreaInfoCallback
|
||||||
{
|
{
|
||||||
DynamicTreeAreaInfoCallback(uint32 phaseMask)
|
DynamicTreeAreaInfoCallback(uint32 phaseMask) : _phaseMask(phaseMask) { }
|
||||||
: _phaseMask(phaseMask) {}
|
|
||||||
|
|
||||||
void operator()(G3D::Vector3 const& p, GameObjectModel const& obj)
|
void operator()(G3D::Vector3 const& p, GameObjectModel const& obj)
|
||||||
{
|
{
|
||||||
@@ -176,7 +185,7 @@ struct DynamicTreeAreaInfoCallback
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32 _phaseMask;
|
uint32 _phaseMask;
|
||||||
VMAP::AreaInfo _areaInfo;
|
VMAP::AreaInfo _areaInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -206,11 +215,10 @@ private:
|
|||||||
GameObjectModel const* _hitModel;
|
GameObjectModel const* _hitModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool DynamicMapTree::GetIntersectionTime(const uint32 phasemask, const G3D::Ray& ray,
|
bool DynamicMapTree::GetIntersectionTime(const uint32 phasemask, const G3D::Ray& ray, const G3D::Vector3& endPos, float& maxDist) const
|
||||||
const G3D::Vector3& endPos, float& maxDist) const
|
|
||||||
{
|
{
|
||||||
float distance = maxDist;
|
float distance = maxDist;
|
||||||
DynamicTreeIntersectionCallback callback(phasemask);
|
DynamicTreeIntersectionCallback callback(phasemask, VMAP::ModelIgnoreFlags::Nothing);
|
||||||
impl->intersectRay(ray, callback, distance, endPos, false);
|
impl->intersectRay(ray, callback, distance, endPos, false);
|
||||||
if (callback.didHit())
|
if (callback.didHit())
|
||||||
{
|
{
|
||||||
@@ -265,7 +273,7 @@ bool DynamicMapTree::GetObjectHitPos(const uint32 phasemask, const G3D::Vector3&
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const
|
bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, VMAP::ModelIgnoreFlags ignoreFlags) const
|
||||||
{
|
{
|
||||||
G3D::Vector3 v1(x1, y1, z1), v2(x2, y2, z2);
|
G3D::Vector3 v1(x1, y1, z1), v2(x2, y2, z2);
|
||||||
|
|
||||||
@@ -277,17 +285,17 @@ bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, flo
|
|||||||
}
|
}
|
||||||
|
|
||||||
G3D::Ray r(v1, (v2 - v1) / maxDist);
|
G3D::Ray r(v1, (v2 - v1) / maxDist);
|
||||||
DynamicTreeIntersectionCallback callback(phasemask);
|
DynamicTreeIntersectionCallback callback(phasemask, ignoreFlags);
|
||||||
impl->intersectRay(r, callback, maxDist, v2, true);
|
impl->intersectRay(r, callback, maxDist, v2, true);
|
||||||
|
|
||||||
return !callback.did_hit;
|
return !callback.didHit();
|
||||||
}
|
}
|
||||||
|
|
||||||
float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, uint32 phasemask) const
|
float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, uint32 phasemask) const
|
||||||
{
|
{
|
||||||
G3D::Vector3 v(x, y, z);
|
G3D::Vector3 v(x, y, z);
|
||||||
G3D::Ray r(v, G3D::Vector3(0, 0, -1));
|
G3D::Ray r(v, G3D::Vector3(0, 0, -1));
|
||||||
DynamicTreeIntersectionCallback callback(phasemask);
|
DynamicTreeIntersectionCallback callback(phasemask, VMAP::ModelIgnoreFlags::Nothing);
|
||||||
impl->intersectZAllignedRay(r, callback, maxSearchDist);
|
impl->intersectZAllignedRay(r, callback, maxSearchDist);
|
||||||
|
|
||||||
if (callback.didHit())
|
if (callback.didHit())
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace G3D
|
|||||||
namespace VMAP
|
namespace VMAP
|
||||||
{
|
{
|
||||||
struct AreaAndLiquidData;
|
struct AreaAndLiquidData;
|
||||||
|
enum class ModelIgnoreFlags : uint32;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GameObjectModel;
|
class GameObjectModel;
|
||||||
@@ -42,11 +43,9 @@ public:
|
|||||||
DynamicMapTree();
|
DynamicMapTree();
|
||||||
~DynamicMapTree();
|
~DynamicMapTree();
|
||||||
|
|
||||||
[[nodiscard]] bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2,
|
[[nodiscard]] bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, VMAP::ModelIgnoreFlags ignoreFlags) const;
|
||||||
float z2, uint32 phasemask) const;
|
|
||||||
|
|
||||||
bool GetIntersectionTime(uint32 phasemask, const G3D::Ray& ray,
|
bool GetIntersectionTime(uint32 phasemask, const G3D::Ray& ray, const G3D::Vector3& endPos, float& maxDist) const;
|
||||||
const G3D::Vector3& endPos, float& maxDist) const;
|
|
||||||
|
|
||||||
bool GetAreaInfo(float x, float y, float& z, uint32 phasemask, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const;
|
bool GetAreaInfo(float x, float y, float& z, uint32 phasemask, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const;
|
||||||
void GetAreaAndLiquidData(float x, float y, float z, uint32 phasemask, uint8 reqLiquidType, VMAP::AreaAndLiquidData& data) const;
|
void GetAreaAndLiquidData(float x, float y, float z, uint32 phasemask, uint8 reqLiquidType, VMAP::AreaAndLiquidData& data) const;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#define _IVMAPMANAGER_H
|
#define _IVMAPMANAGER_H
|
||||||
|
|
||||||
#include "Define.h"
|
#include "Define.h"
|
||||||
|
#include "ModelIgnoreFlags.h"
|
||||||
#include "Optional.h"
|
#include "Optional.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -91,7 +92,7 @@ namespace VMAP
|
|||||||
virtual void unloadMap(unsigned int pMapId, int x, int y) = 0;
|
virtual void unloadMap(unsigned int pMapId, int x, int y) = 0;
|
||||||
virtual void unloadMap(unsigned int pMapId) = 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;
|
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
|
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
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ namespace VMAP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VMapMgr2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2)
|
bool VMapMgr2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags)
|
||||||
{
|
{
|
||||||
#if defined(ENABLE_VMAP_CHECKS)
|
#if defined(ENABLE_VMAP_CHECKS)
|
||||||
if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS))
|
if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS))
|
||||||
@@ -187,7 +187,7 @@ namespace VMAP
|
|||||||
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
|
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
|
||||||
if (pos1 != pos2)
|
if (pos1 != pos2)
|
||||||
{
|
{
|
||||||
return instanceTree->second->isInLineOfSight(pos1, pos2);
|
return instanceTree->second->isInLineOfSight(pos1, pos2, ignoreFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +337,7 @@ namespace VMAP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldModel* VMapMgr2::acquireModelInstance(const std::string& basepath, const std::string& filename)
|
WorldModel* VMapMgr2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */)
|
||||||
{
|
{
|
||||||
//! Critical section, thread safe access to iLoadedModelFiles
|
//! Critical section, thread safe access to iLoadedModelFiles
|
||||||
std::lock_guard<std::mutex> lock(LoadedModelFilesLock);
|
std::lock_guard<std::mutex> lock(LoadedModelFilesLock);
|
||||||
@@ -353,6 +353,9 @@ namespace VMAP
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
LOG_DEBUG("maps", "VMapMgr2: loading file '{}{}'", basepath, filename);
|
LOG_DEBUG("maps", "VMapMgr2: loading file '{}{}'", basepath, filename);
|
||||||
|
|
||||||
|
worldmodel->Flags = flags;
|
||||||
|
|
||||||
model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first;
|
model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first;
|
||||||
model->second.setModel(worldmodel);
|
model->second.setModel(worldmodel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ namespace VMAP
|
|||||||
void unloadMap(unsigned int mapId, int x, int y) override;
|
void unloadMap(unsigned int mapId, int x, int y) override;
|
||||||
void unloadMap(unsigned int mapId) 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
|
fill the hit pos and return true, if an object was hit
|
||||||
*/
|
*/
|
||||||
@@ -120,7 +120,7 @@ namespace VMAP
|
|||||||
bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const override;
|
bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const override;
|
||||||
void GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const override;
|
void GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const override;
|
||||||
|
|
||||||
WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename);
|
WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags);
|
||||||
void releaseModelInstance(const std::string& filename);
|
void releaseModelInstance(const std::string& filename);
|
||||||
|
|
||||||
// what's the use of this? o.O
|
// what's the use of this? o.O
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ namespace VMAP
|
|||||||
class MapRayCallback
|
class MapRayCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MapRayCallback(ModelInstance* val): prims(val), hit(false) {}
|
MapRayCallback(ModelInstance* val, ModelIgnoreFlags ignoreFlags): prims(val), flags(ignoreFlags), hit(false) { }
|
||||||
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool StopAtFirstHit)
|
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool StopAtFirstHit)
|
||||||
{
|
{
|
||||||
bool result = prims[entry].intersectRay(ray, distance, StopAtFirstHit);
|
bool result = prims[entry].intersectRay(ray, distance, StopAtFirstHit, flags);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
hit = true;
|
hit = true;
|
||||||
@@ -47,6 +47,7 @@ namespace VMAP
|
|||||||
bool didHit() { return hit; }
|
bool didHit() { return hit; }
|
||||||
protected:
|
protected:
|
||||||
ModelInstance* prims;
|
ModelInstance* prims;
|
||||||
|
ModelIgnoreFlags flags;
|
||||||
bool hit;
|
bool hit;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -143,10 +144,10 @@ namespace VMAP
|
|||||||
Else, pMaxDist is not modified and returns false;
|
Else, pMaxDist is not modified and returns false;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool StaticMapTree::GetIntersectionTime(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const
|
bool StaticMapTree::GetIntersectionTime(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
|
||||||
{
|
{
|
||||||
float distance = pMaxDist;
|
float distance = pMaxDist;
|
||||||
MapRayCallback intersectionCallBack(iTreeValues);
|
MapRayCallback intersectionCallBack(iTreeValues, ignoreFlags);
|
||||||
iTree.intersectRay(pRay, intersectionCallBack, distance, StopAtFirstHit);
|
iTree.intersectRay(pRay, intersectionCallBack, distance, StopAtFirstHit);
|
||||||
if (intersectionCallBack.didHit())
|
if (intersectionCallBack.didHit())
|
||||||
{
|
{
|
||||||
@@ -156,7 +157,7 @@ namespace VMAP
|
|||||||
}
|
}
|
||||||
//=========================================================
|
//=========================================================
|
||||||
|
|
||||||
bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) const
|
bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2, ModelIgnoreFlags ignoreFlags) const
|
||||||
{
|
{
|
||||||
float maxDist = (pos2 - pos1).magnitude();
|
float maxDist = (pos2 - pos1).magnitude();
|
||||||
// return false if distance is over max float, in case of cheater teleporting to the end of the universe
|
// return false if distance is over max float, in case of cheater teleporting to the end of the universe
|
||||||
@@ -175,7 +176,7 @@ namespace VMAP
|
|||||||
// direction with length of 1
|
// direction with length of 1
|
||||||
G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1) / maxDist);
|
G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1) / maxDist);
|
||||||
|
|
||||||
if (GetIntersectionTime(ray, maxDist, true))
|
if (GetIntersectionTime(ray, maxDist, true, ignoreFlags))
|
||||||
{
|
{
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -204,7 +205,7 @@ namespace VMAP
|
|||||||
Vector3 dir = (pPos2 - pPos1) / maxDist; // direction with length of 1
|
Vector3 dir = (pPos2 - pPos1) / maxDist; // direction with length of 1
|
||||||
G3D::Ray ray(pPos1, dir);
|
G3D::Ray ray(pPos1, dir);
|
||||||
float dist = maxDist;
|
float dist = maxDist;
|
||||||
if (GetIntersectionTime(ray, dist, false))
|
if (GetIntersectionTime(ray, dist, false, ModelIgnoreFlags::Nothing))
|
||||||
{
|
{
|
||||||
pResultHitPos = pPos1 + dir * dist;
|
pResultHitPos = pPos1 + dir * dist;
|
||||||
if (pModifyDist < 0)
|
if (pModifyDist < 0)
|
||||||
@@ -240,7 +241,7 @@ namespace VMAP
|
|||||||
Vector3 dir = Vector3(0, 0, -1);
|
Vector3 dir = Vector3(0, 0, -1);
|
||||||
G3D::Ray ray(pPos, dir); // direction with length of 1
|
G3D::Ray ray(pPos, dir); // direction with length of 1
|
||||||
float maxDist = maxSearchDist;
|
float maxDist = maxSearchDist;
|
||||||
if (GetIntersectionTime(ray, maxDist, false))
|
if (GetIntersectionTime(ray, maxDist, false, ModelIgnoreFlags::Nothing))
|
||||||
{
|
{
|
||||||
height = pPos.z - maxDist;
|
height = pPos.z - maxDist;
|
||||||
}
|
}
|
||||||
@@ -328,7 +329,7 @@ namespace VMAP
|
|||||||
#endif
|
#endif
|
||||||
if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn))
|
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(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : loading {}", spawn.name);
|
//VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : loading {}", spawn.name);
|
||||||
if (model)
|
if (model)
|
||||||
{
|
{
|
||||||
@@ -404,7 +405,7 @@ namespace VMAP
|
|||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
// acquire model instance
|
// acquire model instance
|
||||||
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name);
|
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags);
|
||||||
if (!model)
|
if (!model)
|
||||||
{
|
{
|
||||||
LOG_ERROR("maps", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [{}, {}]", tileX, tileY);
|
LOG_ERROR("maps", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [{}, {}]", tileX, tileY);
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace VMAP
|
|||||||
class ModelInstance;
|
class ModelInstance;
|
||||||
class GroupModel;
|
class GroupModel;
|
||||||
class VMapMgr2;
|
class VMapMgr2;
|
||||||
|
enum class ModelIgnoreFlags : uint32;
|
||||||
enum class LoadResult : uint8;
|
enum class LoadResult : uint8;
|
||||||
|
|
||||||
struct LocationInfo
|
struct LocationInfo
|
||||||
@@ -58,7 +59,7 @@ namespace VMAP
|
|||||||
std::string iBasePath;
|
std::string iBasePath;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool GetIntersectionTime(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const;
|
bool GetIntersectionTime(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
|
||||||
//bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); }
|
//bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); }
|
||||||
public:
|
public:
|
||||||
static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY);
|
static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY);
|
||||||
@@ -69,7 +70,7 @@ namespace VMAP
|
|||||||
StaticMapTree(uint32 mapID, const std::string& basePath);
|
StaticMapTree(uint32 mapID, const std::string& basePath);
|
||||||
~StaticMapTree();
|
~StaticMapTree();
|
||||||
|
|
||||||
[[nodiscard]] bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) const;
|
[[nodiscard]] 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;
|
bool GetObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const;
|
||||||
[[nodiscard]] float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const;
|
[[nodiscard]] float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const;
|
||||||
bool GetAreaInfo(G3D::Vector3& pos, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const;
|
bool GetAreaInfo(G3D::Vector3& pos, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "GameObjectModel.h"
|
#include "GameObjectModel.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "MapTree.h"
|
#include "MapTree.h"
|
||||||
|
#include "ModelInstance.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
#include "VMapDefinitions.h"
|
#include "VMapDefinitions.h"
|
||||||
#include "VMapFactory.h"
|
#include "VMapFactory.h"
|
||||||
@@ -123,7 +124,8 @@ bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> model
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
iModel = VMAP::VMapFactory::createOrGetVMapMgr()->acquireModelInstance(dataPath + "vmaps/", it->second.name);
|
iModel = VMAP::VMapFactory::createOrGetVMapMgr()->acquireModelInstance(dataPath + "vmaps/", it->second.name,
|
||||||
|
it->second.isWmo ? VMAP::ModelFlags::MOD_WORLDSPAWN : VMAP::ModelFlags::MOD_M2);
|
||||||
|
|
||||||
if (!iModel)
|
if (!iModel)
|
||||||
{
|
{
|
||||||
@@ -174,7 +176,7 @@ GameObjectModel* GameObjectModel::Create(std::unique_ptr<GameObjectModelOwnerBas
|
|||||||
return mdl;
|
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())
|
if (!(phasemask & ph_mask) || !owner->IsSpawned())
|
||||||
{
|
{
|
||||||
@@ -191,7 +193,7 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto
|
|||||||
Vector3 p = iInvRot * (ray.origin() - iPos) * iInvScale;
|
Vector3 p = iInvRot * (ray.origin() - iPos) * iInvScale;
|
||||||
Ray modRay(p, iInvRot * ray.direction());
|
Ray modRay(p, iInvRot * ray.direction());
|
||||||
float distance = MaxDist * iInvScale;
|
float distance = MaxDist * iInvScale;
|
||||||
bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit);
|
bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit, ignoreFlags);
|
||||||
if (hit)
|
if (hit)
|
||||||
{
|
{
|
||||||
distance *= iScale;
|
distance *= iScale;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace VMAP
|
|||||||
class WorldModel;
|
class WorldModel;
|
||||||
struct AreaInfo;
|
struct AreaInfo;
|
||||||
struct LocationInfo;
|
struct LocationInfo;
|
||||||
|
enum class ModelIgnoreFlags : uint32;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GameObject;
|
class GameObject;
|
||||||
@@ -68,7 +69,7 @@ public:
|
|||||||
[[nodiscard]] bool isEnabled() const { return phasemask != 0; }
|
[[nodiscard]] bool isEnabled() const { return phasemask != 0; }
|
||||||
[[nodiscard]] bool IsMapObject() const { return isWmo; }
|
[[nodiscard]] bool IsMapObject() const { return isWmo; }
|
||||||
|
|
||||||
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;
|
||||||
void IntersectPoint(G3D::Vector3 const& point, VMAP::AreaInfo& info, uint32 ph_mask) const;
|
void IntersectPoint(G3D::Vector3 const& point, VMAP::AreaInfo& info, uint32 ph_mask) const;
|
||||||
bool GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const;
|
bool GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const;
|
||||||
bool GetLiquidLevel(G3D::Vector3 const& point, VMAP::LocationInfo& info, float& liqHeight) const;
|
bool GetLiquidLevel(G3D::Vector3 const& point, VMAP::LocationInfo& info, float& liqHeight) const;
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 3 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 Affero 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__
|
||||||
@@ -30,7 +30,7 @@ namespace VMAP
|
|||||||
iInvScale = 1.f / iScale;
|
iInvScale = 1.f / iScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const
|
bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
|
||||||
{
|
{
|
||||||
if (!iModel)
|
if (!iModel)
|
||||||
{
|
{
|
||||||
@@ -54,7 +54,7 @@ namespace VMAP
|
|||||||
Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale;
|
Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale;
|
||||||
Ray modRay(p, iInvRot * pRay.direction());
|
Ray modRay(p, iInvRot * pRay.direction());
|
||||||
float distance = pMaxDist * iInvScale;
|
float distance = pMaxDist * iInvScale;
|
||||||
bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit);
|
bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit, ignoreFlags);
|
||||||
if (hit)
|
if (hit)
|
||||||
{
|
{
|
||||||
distance *= iScale;
|
distance *= iScale;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace VMAP
|
|||||||
class WorldModel;
|
class WorldModel;
|
||||||
struct AreaInfo;
|
struct AreaInfo;
|
||||||
struct LocationInfo;
|
struct LocationInfo;
|
||||||
|
enum class ModelIgnoreFlags : uint32;
|
||||||
|
|
||||||
enum ModelFlags
|
enum ModelFlags
|
||||||
{
|
{
|
||||||
@@ -64,7 +65,7 @@ namespace VMAP
|
|||||||
ModelInstance() { }
|
ModelInstance() { }
|
||||||
ModelInstance(const ModelSpawn& spawn, WorldModel* model);
|
ModelInstance(const ModelSpawn& spawn, WorldModel* model);
|
||||||
void setUnloaded() { iModel = nullptr; }
|
void setUnloaded() { iModel = nullptr; }
|
||||||
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const;
|
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
|
||||||
void intersectPoint(const G3D::Vector3& p, AreaInfo& info) const;
|
void intersectPoint(const G3D::Vector3& p, AreaInfo& info) const;
|
||||||
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const;
|
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const;
|
||||||
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const;
|
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "WorldModel.h"
|
#include "WorldModel.h"
|
||||||
#include "MapTree.h"
|
#include "MapTree.h"
|
||||||
|
#include "ModelIgnoreFlags.h"
|
||||||
#include "ModelInstance.h"
|
#include "ModelInstance.h"
|
||||||
#include "VMapDefinitions.h"
|
#include "VMapDefinitions.h"
|
||||||
|
|
||||||
@@ -485,8 +486,18 @@ namespace VMAP
|
|||||||
bool hit;
|
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
|
// 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
|
// in any case, there's no need to use a bound tree if we only have one submodel
|
||||||
if (groupModels.size() == 1)
|
if (groupModels.size() == 1)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace VMAP
|
|||||||
class TreeNode;
|
class TreeNode;
|
||||||
struct AreaInfo;
|
struct AreaInfo;
|
||||||
struct LocationInfo;
|
struct LocationInfo;
|
||||||
|
enum class ModelIgnoreFlags : uint32;
|
||||||
|
|
||||||
class MeshTriangle
|
class MeshTriangle
|
||||||
{
|
{
|
||||||
@@ -108,12 +109,13 @@ namespace VMAP
|
|||||||
//! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry!
|
//! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry!
|
||||||
void setGroupModels(std::vector<GroupModel>& models);
|
void setGroupModels(std::vector<GroupModel>& models);
|
||||||
void setRootWmoID(uint32 id) { RootWMOID = id; }
|
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 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 GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const;
|
||||||
bool writeFile(const std::string& filename);
|
bool writeFile(const std::string& filename);
|
||||||
bool readFile(const std::string& filename);
|
bool readFile(const std::string& filename);
|
||||||
void GetGroupModels(std::vector<GroupModel>& outGroupModels);
|
void GetGroupModels(std::vector<GroupModel>& outGroupModels);
|
||||||
|
uint32 Flags;
|
||||||
protected:
|
protected:
|
||||||
uint32 RootWMOID{0};
|
uint32 RootWMOID{0};
|
||||||
std::vector<GroupModel> groupModels;
|
std::vector<GroupModel> groupModels;
|
||||||
|
|||||||
@@ -647,6 +647,25 @@ struct GameObjectTemplate
|
|||||||
{
|
{
|
||||||
return IsForQuests;
|
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`
|
// 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);
|
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())
|
if (IsInWorld())
|
||||||
{
|
{
|
||||||
@@ -1336,12 +1336,12 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz, LineOfSightChecks ch
|
|||||||
GetHitSpherePointFor({ ox, oy, oz }, x, y, z);
|
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;
|
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))
|
if (!IsInMap(obj))
|
||||||
return false;
|
return false;
|
||||||
@@ -1364,7 +1364,7 @@ bool WorldObject::IsWithinLOSInMap(WorldObject const* obj, LineOfSightChecks che
|
|||||||
else
|
else
|
||||||
GetHitSpherePointFor({ obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ() + obj->GetCollisionHeight() }, x, y, z);
|
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
|
void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "GridDefines.h"
|
#include "GridDefines.h"
|
||||||
#include "GridReference.h"
|
#include "GridReference.h"
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
|
#include "ModelIgnoreFlags.h"
|
||||||
#include "ObjectDefines.h"
|
#include "ObjectDefines.h"
|
||||||
#include "ObjectGuid.h"
|
#include "ObjectGuid.h"
|
||||||
#include "Optional.h"
|
#include "Optional.h"
|
||||||
@@ -455,8 +456,8 @@ public:
|
|||||||
// use only if you will sure about placing both object at same map
|
// 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 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;
|
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;
|
[[nodiscard]] bool IsWithinLOS(float x, float y, float z, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing, LineOfSightChecks checks = LINEOFSIGHT_ALL_CHECKS) const;
|
||||||
bool IsWithinLOSInMap(WorldObject const* obj, 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;
|
[[nodiscard]] Position GetHitSpherePointFor(Position const& dest) const;
|
||||||
void GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) 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;
|
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)
|
if ((*itr)->IsInWorld() && (*itr)->GetExactDistSq(x, y, z) < 75.0f * 75.0f && (*itr)->m_model)
|
||||||
{
|
{
|
||||||
float dist = 30.0f;
|
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)
|
if (hit)
|
||||||
return *itr;
|
return *itr;
|
||||||
}
|
}
|
||||||
@@ -2033,7 +2033,7 @@ Transport* Map::GetTransportForPos(uint32 phase, float x, float y, float z, Worl
|
|||||||
if (staticTrans->m_model)
|
if (staticTrans->m_model)
|
||||||
{
|
{
|
||||||
float dist = 10.0f;
|
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 (hit)
|
||||||
if (GetHeight(phase, x, y, z, true, 30.0f) < (v.z - dist + 1.0f))
|
if (GetHeight(phase, x, y, z, true, 30.0f) < (v.z - dist + 1.0f))
|
||||||
return staticTrans->ToTransport();
|
return staticTrans->ToTransport();
|
||||||
@@ -2440,14 +2440,27 @@ float Map::GetWaterLevel(float x, float y) const
|
|||||||
return 0;
|
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;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ class PathGenerator;
|
|||||||
|
|
||||||
enum WeatherState : uint32;
|
enum WeatherState : uint32;
|
||||||
|
|
||||||
|
namespace VMAP
|
||||||
|
{
|
||||||
|
enum class ModelIgnoreFlags : uint32;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Acore
|
namespace Acore
|
||||||
{
|
{
|
||||||
struct ObjectUpdater;
|
struct ObjectUpdater;
|
||||||
@@ -183,10 +188,13 @@ struct PositionFullTerrainStatus
|
|||||||
|
|
||||||
enum LineOfSightChecks
|
enum LineOfSightChecks
|
||||||
{
|
{
|
||||||
LINEOFSIGHT_CHECK_VMAP = 0x1, // check static floor layout data
|
LINEOFSIGHT_CHECK_VMAP = 0x1, // check static floor layout data
|
||||||
LINEOFSIGHT_CHECK_GOBJECT = 0x2, // check dynamic game object 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
|
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;
|
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]] 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, 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 &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;
|
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
|
// 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);
|
_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)
|
if (!_source->GetMap()->isInLineOfSight(x, y, z, _pathPoints[i - 1].x, _pathPoints[i - 1].y, _pathPoints[i - 1].z + collisionHeight,
|
||||||
|| (canCheckSlope
|
_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)
|
!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)
|
!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
|
// whenver we find a point that is not valid anymore, simply use last valid path
|
||||||
_pathPoints.resize(i + 1);
|
_pathPoints.resize(i + 1);
|
||||||
|
|||||||
@@ -165,7 +165,8 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
|
|||||||
return;
|
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);
|
_validPointsVector[_currentPoint].erase(randomIter);
|
||||||
_preComputedPaths.erase(pathIdx);
|
_preComputedPaths.erase(pathIdx);
|
||||||
|
|||||||
@@ -2049,7 +2049,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
|
|||||||
if (Unit* unit = (*itr)->ToUnit())
|
if (Unit* unit = (*itr)->ToUnit())
|
||||||
{
|
{
|
||||||
uint32 deficit = unit->GetMaxHealth() - unit->GetHealth();
|
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;
|
foundItr = itr;
|
||||||
maxHPDeficit = deficit;
|
maxHPDeficit = deficit;
|
||||||
@@ -2064,10 +2064,10 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
|
|||||||
{
|
{
|
||||||
if (foundItr == tempTargets.end())
|
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;
|
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;
|
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))
|
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;
|
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) &&
|
||||||
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))
|
!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;
|
return SPELL_FAILED_LINE_OF_SIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5629,8 +5658,38 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||||||
float x, y, z;
|
float x, y, z;
|
||||||
m_targets.GetDstPos()->GetPosition(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))
|
if ((!m_caster->IsTotem() || !m_spellInfo->IsPositive()) && !m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) &&
|
||||||
return SPELL_FAILED_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
|
// check pet presence
|
||||||
@@ -7626,7 +7685,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
|
|||||||
{
|
{
|
||||||
case SPELL_EFFECT_RESURRECT_NEW:
|
case SPELL_EFFECT_RESURRECT_NEW:
|
||||||
// player far away, maybe his corpse near?
|
// 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())
|
if (!m_targets.GetCorpseTargetGUID())
|
||||||
return false;
|
return false;
|
||||||
@@ -7638,7 +7697,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
|
|||||||
if (target->GetGUID() != corpse->GetOwnerGUID())
|
if (target->GetGUID() != corpse->GetOwnerGUID())
|
||||||
return false;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -7646,7 +7705,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
|
|||||||
{
|
{
|
||||||
if (!m_targets.GetCorpseTargetGUID())
|
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 true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -7662,7 +7721,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
|
|||||||
if (!corpse->HasFlag(CORPSE_FIELD_FLAGS, CORPSE_FLAG_LOOTABLE))
|
if (!corpse->HasFlag(CORPSE_FIELD_FLAGS, CORPSE_FLAG_LOOTABLE))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!corpse->IsWithinLOSInMap(m_caster, LINEOFSIGHT_ALL_CHECKS))
|
if (!corpse->IsWithinLOSInMap(m_caster, VMAP::ModelIgnoreFlags::M2))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
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))
|
if (target->ToPlayer()->getLevel() >= sWorld->getIntConfig(CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
default: // normal case
|
||||||
default: // normal case
|
{
|
||||||
// Get GO cast coordinates if original caster -> GO
|
uint32 losChecks = LINEOFSIGHT_ALL_CHECKS;
|
||||||
WorldObject* caster = nullptr;
|
GameObject* gobCaster = nullptr;
|
||||||
if (m_originalCasterGUID.IsGameObject())
|
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;
|
caster = m_caster;
|
||||||
|
}
|
||||||
|
|
||||||
if (target != m_caster)
|
if (target != m_caster)
|
||||||
{
|
{
|
||||||
if (m_targets.HasDst())
|
if (m_targets.HasDst())
|
||||||
@@ -7692,13 +7777,18 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
|
|||||||
float y = m_targets.GetDstPos()->GetPositionY();
|
float y = m_targets.GetDstPos()->GetPositionY();
|
||||||
float z = m_targets.GetDstPos()->GetPositionZ();
|
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;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!target->IsWithinLOSInMap(caster, LINEOFSIGHT_ALL_CHECKS))
|
else if (!target->IsWithinLOSInMap(caster, VMAP::ModelIgnoreFlags::M2, LineOfSightChecks(losChecks)))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -4229,12 +4229,6 @@ void SpellMgr::LoadSpellInfoCorrections()
|
|||||||
spellInfo->AttributesEx |= SPELL_ATTR1_EXCLUDE_CASTER;
|
spellInfo->AttributesEx |= SPELL_ATTR1_EXCLUDE_CASTER;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Suppression Aura
|
|
||||||
ApplySpellFix({ 22247 }, [](SpellInfo* spellInfo)
|
|
||||||
{
|
|
||||||
spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Cosmetic - Lightning Beam Channel
|
// Cosmetic - Lightning Beam Channel
|
||||||
ApplySpellFix({ 45537 }, [](SpellInfo* spellInfo)
|
ApplySpellFix({ 45537 }, [](SpellInfo* spellInfo)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1000,8 +1000,8 @@ public:
|
|||||||
{
|
{
|
||||||
Player* player = handler->GetSession()->GetPlayer();
|
Player* player = handler->GetSession()->GetPlayer();
|
||||||
handler->PSendSysMessage("Checking LoS %s -> %s:", player->GetName().c_str(), unit->GetName().c_str());
|
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(" VMAP LoS: %s", player->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::Nothing, LINEOFSIGHT_CHECK_VMAP) ? "clear" : "obstructed");
|
||||||
handler->PSendSysMessage(" GObj LoS: %s", player->IsWithinLOSInMap(unit, LINEOFSIGHT_CHECK_GOBJECT) ? "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());
|
handler->PSendSysMessage("%s is %sin line of sight of %s.", unit->GetName().c_str(), (player->IsWithinLOSInMap(unit) ? "" : "not "), player->GetName().c_str());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1763,7 +1763,9 @@ public:
|
|||||||
{
|
{
|
||||||
float destX = summoner->GetPositionX() + cos(angle + a * M_PI) * i * 10.0f;
|
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;
|
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());
|
float destZ = summoner->GetMapHeight(summoner->GetPhaseMask(), destX, destY, summoner->GetPositionZ());
|
||||||
if (std::fabs(destZ - summoner->GetPositionZ()) < 10.0f) // valid z found
|
if (std::fabs(destZ - summoner->GetPositionZ()) < 10.0f) // valid z found
|
||||||
|
|||||||
@@ -1285,7 +1285,7 @@ public:
|
|||||||
float ox, oy, oz;
|
float ox, oy, oz;
|
||||||
_caster->GetPosition(ox, oy, oz);
|
_caster->GetPosition(ox, oy, oz);
|
||||||
DynamicMapTree const& dTree = unit->GetMap()->GetDynamicMapTree();
|
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:
|
private:
|
||||||
|
|||||||
@@ -125,7 +125,8 @@ public:
|
|||||||
void MoveInLineOfSight(Unit* who) override
|
void MoveInLineOfSight(Unit* who) override
|
||||||
{
|
{
|
||||||
if (!activated && who->GetTypeId() == TYPEID_PLAYER)
|
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;
|
activated = true;
|
||||||
me->RemoveAura(64615);
|
me->RemoveAura(64615);
|
||||||
|
|||||||
Reference in New Issue
Block a user