diff --git a/src/common/Collision/DynamicTree.cpp b/src/common/Collision/DynamicTree.cpp index 34c38d98fa7c3..ceddd74061360 100644 --- a/src/common/Collision/DynamicTree.cpp +++ b/src/common/Collision/DynamicTree.cpp @@ -150,22 +150,6 @@ struct DynamicTreeIntersectionCallback bool didHit() const { return did_hit;} }; -struct DynamicTreeAreaInfoCallback -{ - DynamicTreeAreaInfoCallback(uint32 phaseMask) : _phaseMask(phaseMask) {} - - void operator()(G3D::Vector3 const& p, GameObjectModel const& obj) - { - obj.intersectPoint(p, _areaInfo, _phaseMask); - } - - VMAP::AreaInfo const& GetAreaInfo() const { return _areaInfo; } - -private: - uint32 _phaseMask; - VMAP::AreaInfo _areaInfo; -}; - struct DynamicTreeLocationInfoCallback { DynamicTreeLocationInfoCallback(uint32 phaseMask) : _phaseMask(phaseMask), _hitModel(nullptr) {} @@ -265,24 +249,7 @@ float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, return -G3D::finf(); } -bool DynamicMapTree::getAreaInfo(float x, float y, float& z, uint32 phasemask, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const -{ - G3D::Vector3 v(x, y, z + 0.5f); - DynamicTreeAreaInfoCallback intersectionCallBack(phasemask); - impl->intersectPoint(v, intersectionCallBack); - if (intersectionCallBack.GetAreaInfo().result) - { - flags = intersectionCallBack.GetAreaInfo().flags; - adtId = intersectionCallBack.GetAreaInfo().adtId; - rootId = intersectionCallBack.GetAreaInfo().rootId; - groupId = intersectionCallBack.GetAreaInfo().groupId; - z = intersectionCallBack.GetAreaInfo().ground_Z; - return true; - } - return false; -} - -void DynamicMapTree::getAreaAndLiquidData(float x, float y, float z, uint32 phasemask, uint8 reqLiquidType, VMAP::AreaAndLiquidData& data) const +bool DynamicMapTree::getAreaAndLiquidData(float x, float y, float z, uint32 phasemask, Optional reqLiquidType, VMAP::AreaAndLiquidData& data) const { G3D::Vector3 v(x, y, z + 0.5f); DynamicTreeLocationInfoCallback intersectionCallBack(phasemask); @@ -292,13 +259,16 @@ void DynamicMapTree::getAreaAndLiquidData(float x, float y, float z, uint32 phas data.floorZ = intersectionCallBack.GetLocationInfo().ground_Z; uint32 liquidType = intersectionCallBack.GetLocationInfo().hitModel->GetLiquidType(); float liquidLevel; - if (!reqLiquidType || VMAP::VMapFactory::createOrGetVMapManager()->GetLiquidFlagsPtr(liquidType) & reqLiquidType) + if (!reqLiquidType || VMAP::VMapFactory::createOrGetVMapManager()->GetLiquidFlagsPtr(liquidType) & *reqLiquidType) if (intersectionCallBack.GetHitModel()->GetLiquidLevel(v, intersectionCallBack.GetLocationInfo(), liquidLevel)) data.liquidInfo.emplace(liquidType, liquidLevel); - data.areaInfo.emplace(0, + data.areaInfo.emplace(intersectionCallBack.GetLocationInfo().hitModel->GetWmoID(), + 0, intersectionCallBack.GetLocationInfo().rootId, - intersectionCallBack.GetLocationInfo().hitModel->GetWmoID(), - intersectionCallBack.GetLocationInfo().hitModel->GetMogpFlags()); + intersectionCallBack.GetLocationInfo().hitModel->GetMogpFlags(), + 0); + return true; } + return false; } diff --git a/src/common/Collision/DynamicTree.h b/src/common/Collision/DynamicTree.h index b62044b95448d..0bcdbed423612 100644 --- a/src/common/Collision/DynamicTree.h +++ b/src/common/Collision/DynamicTree.h @@ -19,6 +19,7 @@ #define _DYNTREE_H #include "Define.h" +#include "Optional.h" namespace G3D { @@ -48,8 +49,7 @@ class TC_COMMON_API DynamicMapTree bool getIntersectionTime(uint32 phasemask, const G3D::Ray& ray, 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; - void getAreaAndLiquidData(float x, float y, float z, uint32 phasemask, uint8 reqLiquidType, VMAP::AreaAndLiquidData& data) const; + bool getAreaAndLiquidData(float x, float y, float z, uint32 phasemask, Optional reqLiquidType, VMAP::AreaAndLiquidData& data) const; bool getObjectHitPos(uint32 phasemask, const G3D::Vector3& pPos1, const G3D::Vector3& pPos2, G3D::Vector3& pResultHitPos, diff --git a/src/common/Collision/Management/IVMapManager.h b/src/common/Collision/Management/IVMapManager.h index b25d93bd9b4da..e48b4f38b7516 100644 --- a/src/common/Collision/Management/IVMapManager.h +++ b/src/common/Collision/Management/IVMapManager.h @@ -53,17 +53,21 @@ namespace VMAP { struct AreaInfo { - AreaInfo(int32 _adtId, int32 _rootId, int32 _groupId, uint32 _flags) : adtId(_adtId), rootId(_rootId), groupId(_groupId), mogpFlags(_flags) { } - int32 const adtId; - int32 const rootId; - int32 const groupId; - uint32 const mogpFlags; + AreaInfo() = default; + AreaInfo(int32 _groupId, int32 _adtId, int32 _rootId, uint32 _mogpFlags, uint32 _uniqueId) + : groupId(_groupId), adtId(_adtId), rootId(_rootId), mogpFlags(_mogpFlags), uniqueId(_uniqueId) { } + int32 groupId = 0; + int32 adtId = 0; + int32 rootId = 0; + uint32 mogpFlags = 0; + uint32 uniqueId = 0; }; struct LiquidInfo { + LiquidInfo() = default; LiquidInfo(uint32 _type, float _level) : type(_type), level(_level) { } - uint32 const type; - float const level; + uint32 type = 0; + float level = 0.0f; }; float floorZ = VMAP_INVALID_HEIGHT; @@ -117,14 +121,12 @@ namespace VMAP bool isMapLoadingEnabled() const { return(iEnableLineOfSightCalc || iEnableHeightCalc ); } virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const =0; + /** Query world model area info. \param z gets adjusted to the ground height for which this are info is valid */ - virtual bool getAreaInfo(uint32 mapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const=0; - virtual bool GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const=0; - // get both area + liquid data in a single vmap lookup - virtual void getAreaAndLiquidData(unsigned int mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const=0; + virtual bool getAreaAndLiquidData(unsigned int mapId, float x, float y, float z, Optional reqLiquidType, AreaAndLiquidData& data) const = 0; }; } diff --git a/src/common/Collision/Management/VMapManager2.cpp b/src/common/Collision/Management/VMapManager2.cpp index 9ee1d5a0b3fad..4fed17787de6f 100644 --- a/src/common/Collision/Management/VMapManager2.cpp +++ b/src/common/Collision/Management/VMapManager2.cpp @@ -233,63 +233,8 @@ namespace VMAP return VMAP_INVALID_HEIGHT_VALUE; } - bool VMapManager2::getAreaInfo(uint32 mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const + bool VMapManager2::getAreaAndLiquidData(unsigned int mapId, float x, float y, float z, Optional reqLiquidType, AreaAndLiquidData& data) const { - if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG)) - { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos = convertPositionToInternalRep(x, y, z); - bool result = instanceTree->second->getAreaInfo(pos, flags, adtId, rootId, groupId); - // z is not touched by convertPositionToInternalRep(), so just copy - z = pos.z; - return result; - } - } - - return false; - } - - bool VMapManager2::GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const - { - if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS)) - { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); - if (instanceTree != iInstanceMapTrees.end()) - { - LocationInfo info; - Vector3 pos = convertPositionToInternalRep(x, y, z); - if (instanceTree->second->GetLocationInfo(pos, info)) - { - floor = info.ground_Z; - ASSERT(floor < std::numeric_limits::max()); - ASSERT(info.hitModel); - type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc - mogpFlags = info.hitModel->GetMogpFlags(); - if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType)) - return false; - ASSERT(info.hitInstance); - if (info.hitInstance->GetLiquidLevel(pos, info, level)) - return true; - } - } - } - - return false; - } - - void VMapManager2::getAreaAndLiquidData(unsigned int mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const - { - if (IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS)) - { - data.floorZ = z; - int32 adtId, rootId, groupId; - uint32 flags; - if (getAreaInfo(mapId, x, y, data.floorZ, flags, adtId, rootId, groupId)) - data.areaInfo.emplace(adtId, rootId, groupId, flags); - return; - } InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); if (instanceTree != iInstanceMapTrees.end()) { @@ -300,16 +245,23 @@ namespace VMAP ASSERT(info.hitModel); ASSERT(info.hitInstance); data.floorZ = info.ground_Z; - uint32 liquidType = info.hitModel->GetLiquidType(); - float liquidLevel; - if (!reqLiquidType || (GetLiquidFlagsPtr(liquidType) & reqLiquidType)) - if (info.hitInstance->GetLiquidLevel(pos, info, liquidLevel)) - data.liquidInfo.emplace(liquidType, liquidLevel); + if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS)) + { + uint32 liquidType = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc + float liquidLevel; + if (!reqLiquidType || (GetLiquidFlagsPtr(liquidType) & *reqLiquidType)) + if (info.hitInstance->GetLiquidLevel(pos, info, liquidLevel)) + data.liquidInfo.emplace(liquidType, liquidLevel); + } if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG)) - data.areaInfo.emplace(info.hitInstance->adtId, info.rootId, info.hitModel->GetWmoID(), info.hitModel->GetMogpFlags()); + data.areaInfo.emplace(info.hitModel->GetWmoID(), info.hitInstance->adtId, info.rootId, info.hitModel->GetMogpFlags(), info.hitInstance->ID); + + return true; } } + + return false; } WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */) diff --git a/src/common/Collision/Management/VMapManager2.h b/src/common/Collision/Management/VMapManager2.h index 10a357318abb7..25f4257997f7a 100644 --- a/src/common/Collision/Management/VMapManager2.h +++ b/src/common/Collision/Management/VMapManager2.h @@ -115,9 +115,7 @@ namespace VMAP bool processCommand(char* /*command*/) override { return false; } // for debug and extensions - bool getAreaInfo(uint32 mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const override; - bool GetLiquidLevel(uint32 mapId, 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; + bool getAreaAndLiquidData(uint32 mapId, float x, float y, float z, Optional reqLiquidType, AreaAndLiquidData& data) const override; WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags = 0); void releaseModelInstance(const std::string& filename); diff --git a/src/common/Collision/Maps/MapDefines.h b/src/common/Collision/Maps/MapDefines.h index 6e7aa4410e55d..1877d3eec1caf 100644 --- a/src/common/Collision/Maps/MapDefines.h +++ b/src/common/Collision/Maps/MapDefines.h @@ -19,7 +19,8 @@ #define _MAPDEFINES_H #include "Define.h" -#include "DetourNavMesh.h" +#include "Optional.h" +#include const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP' #define MMAP_VERSION 15 @@ -69,4 +70,47 @@ enum NavTerrainFlag NAV_MAGMA_SLIME = 1 << (NAV_AREA_MAX_VALUE - NAV_AREA_MAGMA_SLIME) }; -#endif /* _MAPDEFINES_H */ +enum ZLiquidStatus : uint32 +{ + LIQUID_MAP_NO_WATER = 0x00000000, + LIQUID_MAP_ABOVE_WATER = 0x00000001, + LIQUID_MAP_WATER_WALK = 0x00000002, + LIQUID_MAP_IN_WATER = 0x00000004, + LIQUID_MAP_UNDER_WATER = 0x00000008, +}; + +#define MAP_LIQUID_STATUS_SWIMMING (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER) +#define MAP_LIQUID_STATUS_IN_CONTACT (MAP_LIQUID_STATUS_SWIMMING | LIQUID_MAP_WATER_WALK) + +struct LiquidData +{ + uint32 type_flags; + uint32 entry; + float level; + float depth_level; +}; + +struct WmoLocation +{ + WmoLocation() = default; + WmoLocation(int32 groupId, int32 nameSetId, int32 rootId, uint32 uniqueId) + : GroupId(groupId), NameSetId(nameSetId), RootId(rootId), UniqueId(uniqueId) { } + + int32 GroupId = 0; + int32 NameSetId = 0; + int32 RootId = 0; + uint32 UniqueId = 0; +}; + +struct PositionFullTerrainStatus +{ + PositionFullTerrainStatus() : areaId(0), floorZ(0.0f), outdoors(true), liquidStatus(LIQUID_MAP_NO_WATER) { } + uint32 areaId; + float floorZ; + bool outdoors; + ZLiquidStatus liquidStatus; + Optional wmoLocation; + Optional liquidInfo; +}; + +#endif // _MAPDEFINES_H diff --git a/src/common/Collision/Maps/MapTree.cpp b/src/common/Collision/Maps/MapTree.cpp index b023e134cd396..55d33e7ee6ce5 100644 --- a/src/common/Collision/Maps/MapTree.cpp +++ b/src/common/Collision/Maps/MapTree.cpp @@ -50,22 +50,6 @@ namespace VMAP ModelIgnoreFlags flags; }; - class AreaInfoCallback - { - public: - AreaInfoCallback(ModelInstance* val): prims(val) { } - void operator()(Vector3 const& point, uint32 entry) - { -#ifdef VMAP_DEBUG - TC_LOG_DEBUG("maps", "AreaInfoCallback: trying to intersect '{}'", prims[entry].name); -#endif - prims[entry].intersectPoint(point, aInfo); - } - - ModelInstance* prims; - AreaInfo aInfo; - }; - class LocationInfoCallback { public: @@ -96,22 +80,6 @@ namespace VMAP return tilefilename.str(); } - bool StaticMapTree::getAreaInfo(Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const - { - AreaInfoCallback intersectionCallBack(iTreeValues); - iTree.intersectPoint(pos, intersectionCallBack); - if (intersectionCallBack.aInfo.result) - { - flags = intersectionCallBack.aInfo.flags; - adtId = intersectionCallBack.aInfo.adtId; - rootId = intersectionCallBack.aInfo.rootId; - groupId = intersectionCallBack.aInfo.groupId; - pos.z = intersectionCallBack.aInfo.ground_Z; - return true; - } - return false; - } - bool StaticMapTree::GetLocationInfo(Vector3 const& pos, LocationInfo &info) const { LocationInfoCallback intersectionCallBack(iTreeValues, info); diff --git a/src/common/Collision/Maps/MapTree.h b/src/common/Collision/Maps/MapTree.h index c70e94a635224..9fed79314b426 100644 --- a/src/common/Collision/Maps/MapTree.h +++ b/src/common/Collision/Maps/MapTree.h @@ -79,7 +79,6 @@ namespace VMAP 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; bool GetLocationInfo(const G3D::Vector3 &pos, LocationInfo &info) const; bool InitMap(const std::string &fname, VMapManager2* vm); diff --git a/src/common/Collision/Models/GameObjectModel.cpp b/src/common/Collision/Models/GameObjectModel.cpp index 88357333e6bcc..1b3bb2ff09225 100644 --- a/src/common/Collision/Models/GameObjectModel.cpp +++ b/src/common/Collision/Models/GameObjectModel.cpp @@ -183,27 +183,6 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto return hit; } -void GameObjectModel::intersectPoint(G3D::Vector3 const& point, VMAP::AreaInfo& info, uint32 ph_mask) const -{ - if (!(phasemask & ph_mask) || !owner->IsSpawned() || !isMapObject()) - return; - - if (!iBound.contains(point)) - return; - - // child bounds are defined in object space: - Vector3 pModel = iInvRot * (point - iPos) * iInvScale; - Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); - float zDist; - if (iModel->IntersectPoint(pModel, zDirModel, zDist, info)) - { - Vector3 modelGround = pModel + zDist * zDirModel; - float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; - if (info.ground_Z < world_Z) - info.ground_Z = world_Z; - } -} - bool GameObjectModel::GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const { if (!(phasemask & ph_mask) || !owner->IsSpawned() || !isMapObject()) diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h index 78f17b7539164..46de9bec4c3b6 100644 --- a/src/common/Collision/Models/GameObjectModel.h +++ b/src/common/Collision/Models/GameObjectModel.h @@ -71,7 +71,6 @@ class TC_COMMON_API GameObjectModel /*, public Intersectable*/ bool isMapObject() const { return isWmo; } 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; 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; diff --git a/src/common/Collision/Models/ModelInstance.cpp b/src/common/Collision/Models/ModelInstance.cpp index 616488bd9a16b..32415be8fc0ff 100644 --- a/src/common/Collision/Models/ModelInstance.cpp +++ b/src/common/Collision/Models/ModelInstance.cpp @@ -63,40 +63,6 @@ namespace VMAP return hit; } - void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo &info) const - { - if (!iModel) - { -#ifdef VMAP_DEBUG - std::cout << "\n"; -#endif - return; - } - - // M2 files don't contain area info, only WMO files - if (flags & MOD_M2) - return; - if (!iBound.contains(p)) - return; - // child bounds are defined in object space: - Vector3 pModel = iInvRot * (p - iPos) * iInvScale; - Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); - float zDist; - if (iModel->IntersectPoint(pModel, zDirModel, zDist, info)) - { - Vector3 modelGround = pModel + zDist * zDirModel; - // Transform back to world space. Note that: - // Mat * vec == vec * Mat.transpose() - // and for rotation matrices: Mat.inverse() == Mat.transpose() - float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; - if (info.ground_Z < world_Z) - { - info.ground_Z = world_Z; - info.adtId = adtId; - } - } - } - bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const { if (!iModel) diff --git a/src/common/Collision/Models/ModelInstance.h b/src/common/Collision/Models/ModelInstance.h index e984aa1065ac8..366f1eee97b1f 100644 --- a/src/common/Collision/Models/ModelInstance.h +++ b/src/common/Collision/Models/ModelInstance.h @@ -67,7 +67,6 @@ namespace VMAP ModelInstance(ModelSpawn const& spawn, WorldModel* model); void setUnloaded() { iModel = nullptr; } bool intersectRay(G3D::Ray const& pRay, float& pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const; - void intersectPoint(G3D::Vector3 const& p, AreaInfo &info) const; bool GetLocationInfo(G3D::Vector3 const& p, LocationInfo &info) const; bool GetLiquidLevel(G3D::Vector3 const& p, LocationInfo &info, float &liqHeight) const; WorldModel* getWorldModel() { return iModel; } diff --git a/src/common/Collision/Models/WorldModel.cpp b/src/common/Collision/Models/WorldModel.cpp index 8b59bb49887af..454b45c3490f2 100644 --- a/src/common/Collision/Models/WorldModel.cpp +++ b/src/common/Collision/Models/WorldModel.cpp @@ -529,25 +529,6 @@ namespace VMAP } }; - bool WorldModel::IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const - { - if (groupModels.empty()) - return false; - - WModelAreaCallback callback(groupModels, down); - groupTree.intersectPoint(p, callback); - if (callback.hit != groupModels.end()) - { - info.rootId = RootWMOID; - info.groupId = callback.hit->GetWmoID(); - info.flags = callback.hit->GetMogpFlags(); - info.result = true; - dist = callback.zDist; - return true; - } - return false; - } - bool WorldModel::GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, GroupLocationInfo& info) const { if (groupModels.empty()) diff --git a/src/common/Collision/Models/WorldModel.h b/src/common/Collision/Models/WorldModel.h index 24954e57b686a..10fa529f00583 100644 --- a/src/common/Collision/Models/WorldModel.h +++ b/src/common/Collision/Models/WorldModel.h @@ -113,7 +113,6 @@ namespace VMAP void setGroupModels(std::vector &models); void setRootWmoID(uint32 id) { RootWMOID = id; } 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, GroupLocationInfo& info) const; bool writeFile(const std::string &filename); bool readFile(const std::string &filename); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 56cfb3713e826..fa44b3deac50c 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1062,9 +1062,9 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u } { // area/zone id is needed immediately for ZoneScript::GetCreatureEntry hook before it is known which creature template to load (no model/scale available yet) - PositionFullTerrainStatus data; - GetMap()->GetFullTerrainStatusForPosition(GetPhaseMask(), GetPositionX(), GetPositionY(), GetPositionZ(), data, MAP_ALL_LIQUIDS, DEFAULT_COLLISION_HEIGHT); - ProcessPositionDataChanged(data); + PositionFullTerrainStatus terrainStatus; + GetMap()->GetFullTerrainStatusForPosition(GetPhaseMask(), GetPositionX(), GetPositionY(), GetPositionZ(), terrainStatus); + ProcessPositionDataChanged(terrainStatus); } // Allow players to see those units while dead, do it here (mayby altered by addon auras) diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index f74b666884652..df73ba3c1d797 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1048,7 +1048,7 @@ void WorldObject::_Create(ObjectGuid::LowType guidlow, HighGuid guidhigh, uint32 void WorldObject::UpdatePositionData() { PositionFullTerrainStatus data; - GetMap()->GetFullTerrainStatusForPosition(GetPhaseMask(), GetPositionX(), GetPositionY(), GetPositionZ(), data, MAP_ALL_LIQUIDS, GetCollisionHeight()); + GetMap()->GetFullTerrainStatusForPosition(GetPhaseMask(), GetPositionX(), GetPositionY(), GetPositionZ(), data, {}, GetCollisionHeight()); ProcessPositionDataChanged(data); } diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 8b31f2ed2d02e..f9587e64f4d10 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -21,6 +21,7 @@ #include "Common.h" #include "Duration.h" #include "EventProcessor.h" +#include "MapDefines.h" #include "ModelIgnoreFlags.h" #include "MovementInfo.h" #include "ObjectDefines.h" @@ -57,9 +58,7 @@ class WorldObject; class WorldPacket; class ZoneScript; struct FactionTemplateEntry; -struct PositionFullTerrainStatus; struct QuaternionData; -enum ZLiquidStatus : uint32; typedef std::unordered_map UpdateDataMapType; diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index d9dba83832f0a..ecc900b41bd10 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2352,7 +2352,7 @@ float GridMap::getLiquidLevel(float x, float y) const } // Get water state on map -inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data, float collisionHeight) +inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, Optional ReqLiquidType, LiquidData* data, float collisionHeight) { // Check water type (if no water return) if (!_liquidGlobalFlags && !_liquidFlags) @@ -2400,7 +2400,7 @@ inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, uint8 R return LIQUID_MAP_NO_WATER; // Check req liquid type mask - if (ReqLiquidType && !(ReqLiquidType&type)) + if (ReqLiquidType && !(*ReqLiquidType & type)) return LIQUID_MAP_NO_WATER; // Check water level: @@ -2466,7 +2466,7 @@ float Map::GetWaterOrGroundLevel(uint32 phasemask, float x, float y, float z, fl LiquidData liquid_status; - ZLiquidStatus res = GetLiquidStatus(phasemask, x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status, collisionHeight); + ZLiquidStatus res = GetLiquidStatus(phasemask, x, y, ground_z, {}, &liquid_status, collisionHeight); switch (res) { case LIQUID_MAP_ABOVE_WATER: @@ -2542,27 +2542,18 @@ static inline bool IsInWMOInterior(uint32 mogpFlags) bool Map::GetAreaInfo(uint32 phaseMask, float x, float y, float z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const { - float vmap_z = z; - float dynamic_z = z; float check_z = z; VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); - uint32 vflags; - int32 vadtId; - int32 vrootId; - int32 vgroupId; - uint32 dflags; - int32 dadtId; - int32 drootId; - int32 dgroupId; - - bool hasVmapAreaInfo = vmgr->getAreaInfo(GetId(), x, y, vmap_z, vflags, vadtId, vrootId, vgroupId); - bool hasDynamicAreaInfo = _dynamicTree.getAreaInfo(x, y, dynamic_z, phaseMask, dflags, dadtId, drootId, dgroupId); - auto useVmap = [&]() { check_z = vmap_z; flags = vflags; adtId = vadtId; rootId = vrootId; groupId = vgroupId; }; - auto useDyn = [&]() { check_z = dynamic_z; flags = dflags; adtId = dadtId; rootId = drootId; groupId = dgroupId; }; + VMAP::AreaAndLiquidData vdata; + VMAP::AreaAndLiquidData ddata; + bool hasVmapAreaInfo = vmgr->getAreaAndLiquidData(GetId(), x, y, z, {}, vdata) && vdata.areaInfo.has_value(); + bool hasDynamicAreaInfo = _dynamicTree.getAreaAndLiquidData(x, y, z, phaseMask, {}, ddata) && ddata.areaInfo.has_value(); + auto useVmap = [&] { check_z = vdata.floorZ; groupId = vdata.areaInfo->groupId; adtId = vdata.areaInfo->adtId; rootId = vdata.areaInfo->rootId; flags = vdata.areaInfo->mogpFlags; }; + auto useDyn = [&] { check_z = ddata.floorZ; groupId = ddata.areaInfo->groupId; adtId = ddata.areaInfo->adtId; rootId = ddata.areaInfo->rootId; flags = ddata.areaInfo->mogpFlags; }; if (hasVmapAreaInfo) { - if (hasDynamicAreaInfo && dynamic_z > vmap_z) + if (hasDynamicAreaInfo && ddata.floorZ > vdata.floorZ) useDyn(); else useVmap(); @@ -2641,34 +2632,31 @@ void Map::GetZoneAndAreaId(uint32 phaseMask, uint32& zoneid, uint32& areaid, flo zoneid = area->ParentAreaID; } -ZLiquidStatus Map::GetLiquidStatus(uint32 phaseMask, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data, float collisionHeight) const +ZLiquidStatus Map::GetLiquidStatus(uint32 phaseMask, float x, float y, float z, Optional ReqLiquidType, LiquidData* data, float collisionHeight) const { ZLiquidStatus result = LIQUID_MAP_NO_WATER; VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); - float liquid_level = INVALID_HEIGHT; - float ground_level = INVALID_HEIGHT; - uint32 liquid_type = 0; - uint32 mogpFlags = 0; + VMAP::AreaAndLiquidData vmapData; bool useGridLiquid = true; - if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type, mogpFlags)) + if (vmgr->getAreaAndLiquidData(GetId(), x, y, z, ReqLiquidType, vmapData) && vmapData.liquidInfo) { - useGridLiquid = !IsInWMOInterior(mogpFlags); - TC_LOG_DEBUG("maps", "GetLiquidStatus(): vmap liquid level: {} ground: {} type: {}", liquid_level, ground_level, liquid_type); + useGridLiquid = !vmapData.areaInfo || !IsInWMOInterior(vmapData.areaInfo->mogpFlags); + TC_LOG_DEBUG("maps", "GetLiquidStatus(): vmap liquid level: {} ground: {} type: {}", vmapData.liquidInfo->level, vmapData.floorZ, vmapData.liquidInfo->type); // Check water level and ground level - if (liquid_level > ground_level && G3D::fuzzyGe(z, ground_level - GROUND_HEIGHT_TOLERANCE)) + if (vmapData.liquidInfo->level > vmapData.floorZ && G3D::fuzzyGe(z, vmapData.floorZ - GROUND_HEIGHT_TOLERANCE)) { // All ok in water -> store data if (data) { // hardcoded in client like this - if (GetId() == 530 && liquid_type == 2) - liquid_type = 15; + if (GetId() == 530 && vmapData.liquidInfo->type == 2) + vmapData.liquidInfo->type = 15; uint32 liquidFlagType = 0; - if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(liquid_type)) + if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(vmapData.liquidInfo->type)) liquidFlagType = liq->SoundBank; - if (liquid_type && liquid_type < 21) + if (vmapData.liquidInfo->type && vmapData.liquidInfo->type < 21) { if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(phaseMask, x, y, z))) { @@ -2682,20 +2670,20 @@ ZLiquidStatus Map::GetLiquidStatus(uint32 phaseMask, float x, float y, float z, if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid)) { - liquid_type = overrideLiquid; + vmapData.liquidInfo->type = overrideLiquid; liquidFlagType = liq->SoundBank; } } } - data->level = liquid_level; - data->depth_level = ground_level; + data->level = vmapData.liquidInfo->level; + data->depth_level = vmapData.floorZ; - data->entry = liquid_type; + data->entry = vmapData.liquidInfo->type; data->type_flags = 1 << liquidFlagType; } - float delta = liquid_level - z; + float delta = vmapData.liquidInfo->level - z; // Get position delta if (delta > collisionHeight) // Under water @@ -2715,7 +2703,7 @@ ZLiquidStatus Map::GetLiquidStatus(uint32 phaseMask, float x, float y, float z, LiquidData map_data; ZLiquidStatus map_result = gmap->GetLiquidStatus(x, y, z, ReqLiquidType, &map_data, collisionHeight); // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER: - if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > ground_level)) + if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > vmapData.floorZ)) { if (data) { @@ -2732,7 +2720,7 @@ ZLiquidStatus Map::GetLiquidStatus(uint32 phaseMask, float x, float y, float z, return result; } -void Map::GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType, float collisionHeight) const +void Map::GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, float z, PositionFullTerrainStatus& data, Optional reqLiquidType, float collisionHeight) const { VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); VMAP::AreaAndLiquidData vmapData; @@ -2779,7 +2767,7 @@ void Map::GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, fl { if (wmoData->areaInfo) { - data.areaInfo.emplace(wmoData->areaInfo->adtId, wmoData->areaInfo->rootId, wmoData->areaInfo->groupId, wmoData->areaInfo->mogpFlags); + data.wmoLocation.emplace(wmoData->areaInfo->groupId, wmoData->areaInfo->adtId, wmoData->areaInfo->rootId, wmoData->areaInfo->uniqueId); // wmo found WMOAreaTableEntry const* wmoEntry = GetWMOAreaTableEntryByTripple(wmoData->areaInfo->rootId, wmoData->areaInfo->adtId, wmoData->areaInfo->groupId); data.outdoors = (wmoData->areaInfo->mogpFlags & 0x8) != 0; @@ -2908,7 +2896,7 @@ bool Map::IsInWater(uint32 phaseMask, float x, float y, float pZ, LiquidData* da { LiquidData liquid_status; LiquidData* liquid_ptr = data ? data : &liquid_status; - return (GetLiquidStatus(phaseMask, x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0; + return (GetLiquidStatus(phaseMask, x, y, pZ, {}, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0; } bool Map::IsUnderWater(uint32 phaseMask, float x, float y, float z) const diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index af77c925858ec..dfe0ff4a37a7d 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -24,6 +24,7 @@ #include "DynamicTree.h" #include "GridDefines.h" #include "GridRefManager.h" +#include "MapDefines.h" #include "MapRefManager.h" #include "MPSCQueue.h" #include "ObjectGuid.h" @@ -140,18 +141,6 @@ struct map_liquidHeader float liquidLevel; }; -enum ZLiquidStatus : uint32 -{ - LIQUID_MAP_NO_WATER = 0x00000000, - LIQUID_MAP_ABOVE_WATER = 0x00000001, - LIQUID_MAP_WATER_WALK = 0x00000002, - LIQUID_MAP_IN_WATER = 0x00000004, - LIQUID_MAP_UNDER_WATER = 0x00000008 -}; - -#define MAP_LIQUID_STATUS_SWIMMING (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER) -#define MAP_LIQUID_STATUS_IN_CONTACT (MAP_LIQUID_STATUS_SWIMMING | LIQUID_MAP_WATER_WALK) - #define MAP_LIQUID_TYPE_NO_WATER 0x00 #define MAP_LIQUID_TYPE_WATER 0x01 #define MAP_LIQUID_TYPE_OCEAN 0x02 @@ -162,34 +151,6 @@ enum ZLiquidStatus : uint32 #define MAP_LIQUID_TYPE_DARK_WATER 0x10 -struct LiquidData -{ - uint32 type_flags; - uint32 entry; - float level; - float depth_level; -}; - -struct PositionFullTerrainStatus -{ - struct AreaInfo - { - AreaInfo(int32 _adtId, int32 _rootId, int32 _groupId, uint32 _flags) : adtId(_adtId), rootId(_rootId), groupId(_groupId), mogpFlags(_flags) { } - int32 const adtId; - int32 const rootId; - int32 const groupId; - uint32 const mogpFlags; - }; - - PositionFullTerrainStatus() : areaId(0), floorZ(0.0f), outdoors(true), liquidStatus(LIQUID_MAP_NO_WATER) { } - uint32 areaId; - float floorZ; - bool outdoors; - ZLiquidStatus liquidStatus; - Optional areaInfo; - Optional liquidInfo; -}; - class TC_GAME_API GridMap { uint32 _flags; @@ -250,7 +211,7 @@ class TC_GAME_API GridMap inline float getHeight(float x, float y) const {return (this->*_gridGetHeight)(x, y);} float getMinHeight(float x, float y) const; float getLiquidLevel(float x, float y) const; - ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h + ZLiquidStatus GetLiquidStatus(float x, float y, float z, Optional ReqLiquidType, LiquidData* data = 0, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h }; #pragma pack(push, 1) @@ -400,8 +361,8 @@ class TC_GAME_API Map : public GridRefManager Map const* GetParent() const { return m_parentMap; } - void GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType, float collisionHeight) const; - ZLiquidStatus GetLiquidStatus(uint32 phaseMask, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h + void GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, float z, PositionFullTerrainStatus& data, Optional reqLiquidType = {}, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h + ZLiquidStatus GetLiquidStatus(uint32 phaseMask, float x, float y, float z, Optional ReqLiquidType, LiquidData* data = nullptr, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h bool GetAreaInfo(uint32 phaseMask, float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const; uint32 GetAreaId(uint32 phaseMask, float x, float y, float z) const; diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 08de2f4e12c67..bb90f2885962a 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -184,7 +184,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con // Check both start and end points, if they're both in water, then we can *safely* let the creature move for (uint32 i = 0; i < _pathPoints.size(); ++i) { - ZLiquidStatus status = _source->GetMap()->GetLiquidStatus(_source->GetPhaseMask(), _pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, nullptr, _source->GetCollisionHeight()); + ZLiquidStatus status = _source->GetMap()->GetLiquidStatus(_source->GetPhaseMask(), _pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, {}, nullptr, _source->GetCollisionHeight()); // One of the points is not in the water, cancel movement. if (status == LIQUID_MAP_NO_WATER) { @@ -696,7 +696,7 @@ void PathGenerator::UpdateFilter() NavTerrainFlag PathGenerator::GetNavTerrain(float x, float y, float z) { LiquidData data; - ZLiquidStatus liquidStatus = _source->GetMap()->GetLiquidStatus(_source->GetPhaseMask(), x, y, z, MAP_ALL_LIQUIDS, &data, _source->GetCollisionHeight()); + ZLiquidStatus liquidStatus = _source->GetMap()->GetLiquidStatus(_source->GetPhaseMask(), x, y, z, {}, &data, _source->GetCollisionHeight()); if (liquidStatus == LIQUID_MAP_NO_WATER) return NAV_GROUND; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index c5fe2d9dfd247..53be3ce0f1b01 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1377,7 +1377,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffectInfo const& spellEffectIn float ground = m_caster->GetMapHeight(x, y, z); float liquidLevel = VMAP_INVALID_HEIGHT_VALUE; LiquidData liquidData; - if (m_caster->GetMap()->GetLiquidStatus(m_caster->GetPhaseMask(), x, y, z, MAP_ALL_LIQUIDS, &liquidData, m_caster->GetCollisionHeight())) + if (m_caster->GetMap()->GetLiquidStatus(m_caster->GetPhaseMask(), x, y, z, {}, &liquidData, m_caster->GetCollisionHeight())) liquidLevel = liquidData.level; if (liquidLevel <= ground) // When there is no liquid Map::GetWaterOrGroundLevel returns ground level diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 65c671bef2fe0..8b26d375c28d2 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -296,7 +296,7 @@ class misc_commandscript : public CommandScript zoneX, zoneY, groundZ, floorZ, map->GetMinHeight(object->GetPositionX(), object->GetPositionY()), haveMap, haveVMap, haveMMap); LiquidData liquidStatus; - ZLiquidStatus status = map->GetLiquidStatus(object->GetPhaseMask(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus, object->GetCollisionHeight()); + ZLiquidStatus status = map->GetLiquidStatus(object->GetPhaseMask(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), {}, &liquidStatus); if (status) handler->PSendSysMessage(LANG_LIQUID_STATUS, liquidStatus.level, liquidStatus.depth_level, liquidStatus.entry, liquidStatus.type_flags, status); diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 8126459250927..f9a30113a37bf 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -214,7 +214,7 @@ class spell_spawn_blood_pool : public SpellScript Unit* caster = GetCaster(); Position summonPos = caster->GetPosition(); LiquidData liquidStatus; - if (caster->GetMap()->GetLiquidStatus(caster->GetPhaseMask(), caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus, caster->GetCollisionHeight())) + if (caster->GetMap()->GetLiquidStatus(caster->GetPhaseMask(), caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ(), {}, &liquidStatus, caster->GetCollisionHeight())) summonPos.m_positionZ = liquidStatus.level; dest.Relocate(summonPos); }