diff options
20 files changed, 104 insertions, 44 deletions
diff --git a/src/common/Collision/DynamicTree.cpp b/src/common/Collision/DynamicTree.cpp index 2fbdfe05b52..0b525fc1ab6 100644 --- a/src/common/Collision/DynamicTree.cpp +++ b/src/common/Collision/DynamicTree.cpp @@ -21,6 +21,7 @@ #include "GameObjectModel.h" #include "Log.h" #include "MapTree.h" +#include "ModelIgnoreFlags.h" #include "ModelInstance.h" #include "RegularGrid.h" #include "Timer.h" @@ -142,7 +143,7 @@ struct DynamicTreeIntersectionCallback bool operator()(G3D::Ray const& r, GameObjectModel const& obj, float& distance) { - _didHit = obj.intersectRay(r, distance, true, _phaseShift); + _didHit = obj.intersectRay(r, distance, true, _phaseShift, VMAP::ModelIgnoreFlags::Nothing); return _didHit; } diff --git a/src/common/Collision/Management/IVMapManager.h b/src/common/Collision/Management/IVMapManager.h index cec5657f5ed..d876136fe10 100644 --- a/src/common/Collision/Management/IVMapManager.h +++ b/src/common/Collision/Management/IVMapManager.h @@ -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 diff --git a/src/common/Collision/Management/VMapManager2.cpp b/src/common/Collision/Management/VMapManager2.cpp index 163769f33a9..1f3e001b054 100644 --- a/src/common/Collision/Management/VMapManager2.cpp +++ b/src/common/Collision/Management/VMapManager2.cpp @@ -191,7 +191,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; @@ -202,7 +202,7 @@ namespace VMAP Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1); Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2); if (pos1 != pos2) - return instanceTree->second->isInLineOfSight(pos1, pos2); + return instanceTree->second->isInLineOfSight(pos1, pos2, ignoreFlags); } return true; @@ -306,7 +306,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); @@ -322,6 +322,9 @@ namespace VMAP return NULL; } TC_LOG_DEBUG("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); } diff --git a/src/common/Collision/Management/VMapManager2.h b/src/common/Collision/Management/VMapManager2.h index 5bb556ccf64..32a4ec17e32 100644 --- a/src/common/Collision/Management/VMapManager2.h +++ b/src/common/Collision/Management/VMapManager2.h @@ -111,7 +111,7 @@ namespace VMAP void unloadMap(unsigned int mapId) override; void unloadSingleMap(uint32 mapId); - 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 */ @@ -123,7 +123,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 diff --git a/src/common/Collision/Maps/MapTree.cpp b/src/common/Collision/Maps/MapTree.cpp index 3ba9c860d6f..ab48c4ebe0c 100644 --- a/src/common/Collision/Maps/MapTree.cpp +++ b/src/common/Collision/Maps/MapTree.cpp @@ -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,10 +142,10 @@ namespace VMAP 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; @@ -153,7 +153,7 @@ namespace VMAP } //========================================================= - 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 @@ -167,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; @@ -193,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) @@ -229,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; } @@ -371,7 +371,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) TC_LOG_ERROR("misc", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY); diff --git a/src/common/Collision/Maps/MapTree.h b/src/common/Collision/Maps/MapTree.h index 122f5dc63eb..9b24c9abb1a 100644 --- a/src/common/Collision/Maps/MapTree.h +++ b/src/common/Collision/Maps/MapTree.h @@ -28,6 +28,7 @@ namespace VMAP class ModelInstance; class GroupModel; class VMapManager2; + enum class ModelIgnoreFlags : uint32; struct TC_COMMON_API LocationInfo { @@ -65,7 +66,7 @@ namespace VMAP private: static TileFileOpenResult OpenMapTileFile(std::string const& basePath, uint32 mapID, uint32 tileX, uint32 tileY, VMapManager2* vm); - 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); @@ -76,7 +77,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; diff --git a/src/common/Collision/Models/GameObjectModel.cpp b/src/common/Collision/Models/GameObjectModel.cpp index 07c1ffe548c..8e4ba0a9679 100644 --- a/src/common/Collision/Models/GameObjectModel.cpp +++ b/src/common/Collision/Models/GameObjectModel.cpp @@ -161,7 +161,7 @@ GameObjectModel* GameObjectModel::Create(std::unique_ptr<GameObjectModelOwnerBas return mdl; } -bool GameObjectModel::intersectRay(G3D::Ray const& ray, float& maxDist, bool stopAtFirstHit, PhaseShift const& phaseShift) const +bool GameObjectModel::intersectRay(G3D::Ray const& ray, float& maxDist, bool stopAtFirstHit, PhaseShift const& phaseShift, VMAP::ModelIgnoreFlags ignoreFlags) const { if (!isCollisionEnabled() || !owner->IsSpawned()) return false; @@ -177,7 +177,7 @@ bool GameObjectModel::intersectRay(G3D::Ray const& 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; diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h index 287f93f87ca..0ea8bbbbcfb 100644 --- a/src/common/Collision/Models/GameObjectModel.h +++ b/src/common/Collision/Models/GameObjectModel.h @@ -31,6 +31,7 @@ namespace VMAP { class WorldModel; struct AreaInfo; + enum class ModelIgnoreFlags : uint32; } class GameObject; @@ -69,7 +70,7 @@ public: bool isCollisionEnabled() const { return _collisionEnabled; } bool isMapObject() const { return isWmo; } - bool intersectRay(G3D::Ray const& ray, float& maxDist, bool stopAtFirstHit, PhaseShift const& phaseShift) const; + bool intersectRay(G3D::Ray const& ray, float& maxDist, bool stopAtFirstHit, PhaseShift const& phaseShift, VMAP::ModelIgnoreFlags ignoreFlags) const; void intersectPoint(G3D::Vector3 const& point, VMAP::AreaInfo& info, PhaseShift const& phaseShift) const; static GameObjectModel* Create(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath); diff --git a/src/common/Collision/Models/ModelIgnoreFlags.h b/src/common/Collision/Models/ModelIgnoreFlags.h new file mode 100644 index 00000000000..beb9f965523 --- /dev/null +++ b/src/common/Collision/Models/ModelIgnoreFlags.h @@ -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__ diff --git a/src/common/Collision/Models/ModelInstance.cpp b/src/common/Collision/Models/ModelInstance.cpp index a3d90ef7dec..a2c62bc565d 100644 --- a/src/common/Collision/Models/ModelInstance.cpp +++ b/src/common/Collision/Models/ModelInstance.cpp @@ -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; diff --git a/src/common/Collision/Models/ModelInstance.h b/src/common/Collision/Models/ModelInstance.h index 04fe5b06c7b..0bdcbc29393 100644 --- a/src/common/Collision/Models/ModelInstance.h +++ b/src/common/Collision/Models/ModelInstance.h @@ -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; diff --git a/src/common/Collision/Models/WorldModel.cpp b/src/common/Collision/Models/WorldModel.cpp index beab8f80a1c..73aef934b4e 100644 --- a/src/common/Collision/Models/WorldModel.cpp +++ b/src/common/Collision/Models/WorldModel.cpp @@ -19,6 +19,7 @@ #include "WorldModel.h" #include "VMapDefinitions.h" #include "MapTree.h" +#include "ModelIgnoreFlags.h" using G3D::Vector3; using G3D::Ray; @@ -472,8 +473,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) diff --git a/src/common/Collision/Models/WorldModel.h b/src/common/Collision/Models/WorldModel.h index 8951b3fdf89..64b15c8cba4 100644 --- a/src/common/Collision/Models/WorldModel.h +++ b/src/common/Collision/Models/WorldModel.h @@ -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; diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 359f0ef0652..47e07803819 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1671,7 +1671,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; @@ -1682,7 +1682,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 @@ -1759,7 +1759,7 @@ bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare, return obj && IsInMap(obj) && IsInPhase(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); @@ -1773,7 +1773,7 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const else GetHitSpherePointFor({ ox, oy, oz }, x, y, z); - return GetMap()->isInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f); + return GetMap()->isInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f, ignoreFlags); } return true; diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 2ebea15a58d..7823a2a2a68 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -22,6 +22,7 @@ #include "Common.h" #include "GridReference.h" #include "GridRefManager.h" +#include "ModelIgnoreFlags.h" #include "MovementInfo.h" #include "ObjectDefines.h" #include "ObjectGuid.h" @@ -449,8 +450,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; diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index e840569672e..dfd8b7fd5b7 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2878,9 +2878,9 @@ float Map::GetWaterLevel(PhaseShift const& phaseShift, float x, float y) const return 0; } -bool Map::isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2) const +bool Map::isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, VMAP::ModelIgnoreFlags ignoreFlags) const { - return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(PhasingHandler::GetTerrainMapId(phaseShift, this, x1, y1), x1, y1, z1, x2, y2, z2) + return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(PhasingHandler::GetTerrainMapId(phaseShift, this, x1, y1), x1, y1, z1, x2, y2, z2, ignoreFlags) && _dynamicTree.isInLineOfSight({ x1, y1, z1 }, { x2, y2, z2 }, phaseShift); } diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 7d453f0406a..5498b097b54 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -67,6 +67,7 @@ enum WeatherState : uint32; namespace Trinity { struct ObjectUpdater; } namespace G3D { class Plane; } +namespace VMAP { enum class ModelIgnoreFlags : uint32; } struct ScriptAction { @@ -493,7 +494,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType> float GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground = nullptr, bool swim = false) const; float GetHeight(PhaseShift const& phaseShift, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const; - bool isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2) const; + bool isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, VMAP::ModelIgnoreFlags ignoreFlags) const; void Balance() { _dynamicTree.balance(); } void RemoveGameObjectModel(const GameObjectModel& model) { _dynamicTree.remove(model); } void InsertGameObjectModel(const GameObjectModel& model) { _dynamicTree.insert(model); } diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index c4cd065ccbf..f3e3f7db303 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -54,7 +54,7 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner) Position mypos = owner->GetPosition(); bool isInLOS = VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight( PhasingHandler::GetTerrainMapId(owner->GetPhaseShift(), owner->GetMap(), mypos.m_positionX, mypos.m_positionY), - mypos.m_positionX, mypos.m_positionY, mypos.m_positionZ + 2.0f, x, y, z + 2.0f); + mypos.m_positionX, mypos.m_positionY, mypos.m_positionZ + 2.0f, x, y, z + 2.0f, VMAP::ModelIgnoreFlags::Nothing); if (!isInLOS) { i_nextCheckTime.Reset(200); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 5775b5e496a..e6130a9d08a 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1958,7 +1958,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; @@ -1973,10 +1973,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; } } @@ -5071,7 +5071,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; } } @@ -5083,7 +5083,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; } @@ -5366,6 +5366,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 @@ -6916,7 +6920,7 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, /// @todo shit below shouldn't be here, but it's temporary //Check targets for LOS visibility 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 @@ -6925,7 +6929,7 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, 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; } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp index a3d600830f5..79a0f293fb2 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp @@ -20,6 +20,7 @@ #include "MotionMaster.h" #include "ruby_sanctum.h" #include "ScriptedCreature.h" +#include "SpellMgr.h" #include "SpellScript.h" enum Texts |