diff options
author | HelloKitty <andrew.blakely@ymail.com> | 2017-01-21 14:44:31 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2017-01-21 14:44:31 +0100 |
commit | 01d715eaef99e91f0959dc85fb7f69eb26d01a22 (patch) | |
tree | 8c1c805c9eca9a0da828b4ddbf566cca4d464e84 /src/common | |
parent | 998efa55d8c81b923bb0725b5de8b0c5894b89da (diff) |
Core/Vmaps: Stop M2s from occluding for spellcast LoS
Closes #18528
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/Collision/DynamicTree.cpp | 5 | ||||
-rw-r--r-- | src/common/Collision/Management/IVMapManager.h | 3 | ||||
-rw-r--r-- | src/common/Collision/Management/VMapManager2.cpp | 9 | ||||
-rw-r--r-- | src/common/Collision/Management/VMapManager2.h | 4 | ||||
-rw-r--r-- | src/common/Collision/Maps/MapTree.cpp | 25 | ||||
-rw-r--r-- | src/common/Collision/Maps/MapTree.h | 6 | ||||
-rw-r--r-- | src/common/Collision/Models/GameObjectModel.cpp | 4 | ||||
-rw-r--r-- | src/common/Collision/Models/GameObjectModel.h | 3 | ||||
-rw-r--r-- | src/common/Collision/Models/ModelIgnoreFlags.h | 34 | ||||
-rw-r--r-- | src/common/Collision/Models/ModelInstance.cpp | 4 | ||||
-rw-r--r-- | src/common/Collision/Models/ModelInstance.h | 3 | ||||
-rw-r--r-- | src/common/Collision/Models/WorldModel.cpp | 11 | ||||
-rw-r--r-- | src/common/Collision/Models/WorldModel.h | 4 |
13 files changed, 84 insertions, 31 deletions
diff --git a/src/common/Collision/DynamicTree.cpp b/src/common/Collision/DynamicTree.cpp index a32ad1e17c8..1c6e856e46d 100644 --- a/src/common/Collision/DynamicTree.cpp +++ b/src/common/Collision/DynamicTree.cpp @@ -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; diff --git a/src/common/Collision/Management/IVMapManager.h b/src/common/Collision/Management/IVMapManager.h index 8d18463788e..a28f45c349f 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 4db878a117f..74d6c734053 100644 --- a/src/common/Collision/Management/VMapManager2.cpp +++ b/src/common/Collision/Management/VMapManager2.cpp @@ -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); } diff --git a/src/common/Collision/Management/VMapManager2.h b/src/common/Collision/Management/VMapManager2.h index f7b861d21a4..593f046412e 100644 --- a/src/common/Collision/Management/VMapManager2.h +++ b/src/common/Collision/Management/VMapManager2.h @@ -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 diff --git a/src/common/Collision/Maps/MapTree.cpp b/src/common/Collision/Maps/MapTree.cpp index f3dd8499e12..6b10c414103 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,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); diff --git a/src/common/Collision/Maps/MapTree.h b/src/common/Collision/Maps/MapTree.h index c91983948b5..7f1415ff939 100644 --- a/src/common/Collision/Maps/MapTree.h +++ b/src/common/Collision/Maps/MapTree.h @@ -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; diff --git a/src/common/Collision/Models/GameObjectModel.cpp b/src/common/Collision/Models/GameObjectModel.cpp index b111b0de301..2950a48c21b 100644 --- a/src/common/Collision/Models/GameObjectModel.cpp +++ b/src/common/Collision/Models/GameObjectModel.cpp @@ -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; diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h index a9fce400146..c121e421e6d 100644 --- a/src/common/Collision/Models/GameObjectModel.h +++ b/src/common/Collision/Models/GameObjectModel.h @@ -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); 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 b38f455e546..3390b233c82 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 91ce194ddf1..3036ac10117 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 50144a7b9fe..f653fe04d92 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; @@ -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) diff --git a/src/common/Collision/Models/WorldModel.h b/src/common/Collision/Models/WorldModel.h index 89a0ce472ee..59f0b74f31d 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; |