mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
34
src/common/Collision/Models/ModelIgnoreFlags.h
Normal file
34
src/common/Collision/Models/ModelIgnoreFlags.h
Normal 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__
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user