Merge e86727c5b96054a678088aaf0e6b7309784656fc into 3ad79541f6d0e425bed473d0bd37962d6afdb5ba

This commit is contained in:
天鹭 2025-11-09 19:15:54 +00:00 committed by GitHub
commit 89017af6ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 165 additions and 335 deletions

View File

@ -70,6 +70,7 @@ private:
{ {
tree.clear(); tree.clear();
objects.clear(); objects.clear();
bounds = G3D::AABox::empty();
// create space for the first node // create space for the first node
tree.push_back(3u << 30u); // dummy leaf tree.push_back(3u << 30u); // dummy leaf
tree.insert(tree.end(), 2, 0); tree.insert(tree.end(), 2, 0);
@ -116,6 +117,7 @@ public:
delete[] dat.indices; delete[] dat.indices;
} }
[[nodiscard]] uint32 primCount() const { return objects.size(); } [[nodiscard]] uint32 primCount() const { return objects.size(); }
G3D::AABox const& bound() const { return bounds; }
template<typename RayCallback> template<typename RayCallback>
void intersectRay(const G3D::Ray& r, RayCallback& intersectCallback, float& maxDist, bool stopAtFirstHit) const void intersectRay(const G3D::Ray& r, RayCallback& intersectCallback, float& maxDist, bool stopAtFirstHit) const

View File

@ -170,25 +170,6 @@ private:
VMAP::ModelIgnoreFlags _ignoreFlags; VMAP::ModelIgnoreFlags _ignoreFlags;
}; };
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 struct DynamicTreeLocationInfoCallback
{ {
DynamicTreeLocationInfoCallback(uint32 phaseMask) DynamicTreeLocationInfoCallback(uint32 phaseMask)
@ -308,24 +289,7 @@ float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist,
} }
} }
bool DynamicMapTree::GetAreaInfo(float x, float y, float& z, uint32 phasemask, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const bool DynamicMapTree::GetAreaAndLiquidData(float x, float y, float z, uint32 phasemask, Optional<uint8> reqLiquidType, VMAP::AreaAndLiquidData& data) 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
{ {
G3D::Vector3 v(x, y, z + 0.5f); G3D::Vector3 v(x, y, z + 0.5f);
DynamicTreeLocationInfoCallback intersectionCallBack(phasemask); DynamicTreeLocationInfoCallback intersectionCallBack(phasemask);
@ -335,13 +299,16 @@ void DynamicMapTree::GetAreaAndLiquidData(float x, float y, float z, uint32 phas
data.floorZ = intersectionCallBack.GetLocationInfo().ground_Z; data.floorZ = intersectionCallBack.GetLocationInfo().ground_Z;
uint32 liquidType = intersectionCallBack.GetLocationInfo().hitModel->GetLiquidType(); uint32 liquidType = intersectionCallBack.GetLocationInfo().hitModel->GetLiquidType();
float liquidLevel; float liquidLevel;
if (!reqLiquidType || (dynamic_cast<VMAP::VMapMgr2*>(VMAP::VMapFactory::createOrGetVMapMgr())->GetLiquidFlagsPtr(liquidType) & reqLiquidType)) if (!reqLiquidType || (dynamic_cast<VMAP::VMapMgr2*>(VMAP::VMapFactory::createOrGetVMapMgr())->GetLiquidFlagsPtr(liquidType) & *reqLiquidType))
if (intersectionCallBack.GetHitModel()->GetLiquidLevel(v, intersectionCallBack.GetLocationInfo(), liquidLevel)) if (intersectionCallBack.GetHitModel()->GetLiquidLevel(v, intersectionCallBack.GetLocationInfo(), liquidLevel))
data.liquidInfo.emplace(liquidType, liquidLevel); data.liquidInfo.emplace(liquidType, liquidLevel);
data.areaInfo.emplace(0, data.areaInfo.emplace(intersectionCallBack.GetLocationInfo().hitModel->GetWmoID(),
0,
intersectionCallBack.GetLocationInfo().rootId, intersectionCallBack.GetLocationInfo().rootId,
intersectionCallBack.GetLocationInfo().hitModel->GetWmoID(), intersectionCallBack.GetLocationInfo().hitModel->GetMogpFlags(),
intersectionCallBack.GetLocationInfo().hitModel->GetMogpFlags()); 0);
return true;
} }
return false;
} }

View File

@ -19,6 +19,7 @@
#define _DYNTREE_H #define _DYNTREE_H
#include "Define.h" #include "Define.h"
#include "Optional.h"
namespace G3D namespace G3D
{ {
@ -47,8 +48,7 @@ public:
bool GetIntersectionTime(uint32 phasemask, const G3D::Ray& ray, const G3D::Vector3& endPos, float& maxDist) const; 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; bool GetAreaAndLiquidData(float x, float y, float z, uint32 phasemask, Optional<uint8> reqLiquidType, VMAP::AreaAndLiquidData& data) const;
void GetAreaAndLiquidData(float x, float y, float z, uint32 phasemask, uint8 reqLiquidType, VMAP::AreaAndLiquidData& data) const;
bool GetObjectHitPos(uint32 phasemask, const G3D::Vector3& pPos1, bool GetObjectHitPos(uint32 phasemask, const G3D::Vector3& pPos1,
const G3D::Vector3& pPos2, G3D::Vector3& pResultHitPos, const G3D::Vector3& pPos2, G3D::Vector3& pResultHitPos,

View File

@ -52,20 +52,23 @@ namespace VMAP
{ {
struct AreaInfo struct AreaInfo
{ {
AreaInfo(int32 _adtId, int32 _rootId, int32 _groupId, uint32 _flags) AreaInfo() = default;
: adtId(_adtId), rootId(_rootId), groupId(_groupId), mogpFlags(_flags) { } AreaInfo(int32 _groupId, int32 _adtId, int32 _rootId, uint32 _mogpFlags, uint32 _uniqueId)
int32 const adtId; : groupId(_groupId), adtId(_adtId), rootId(_rootId), mogpFlags(_mogpFlags), uniqueId(_uniqueId) { }
int32 const rootId; int32 groupId = 0;
int32 const groupId; int32 adtId = 0;
uint32 const mogpFlags; int32 rootId = 0;
uint32 mogpFlags = 0;
uint32 uniqueId = 0;
}; };
struct LiquidInfo struct LiquidInfo
{ {
LiquidInfo() = default;
LiquidInfo(uint32 _type, float _level) LiquidInfo(uint32 _type, float _level)
: type(_type), level(_level) {} : type(_type), level(_level) {}
uint32 const type; uint32 type = 0;
float const level; float level = 0.0f;
}; };
float floorZ = VMAP_INVALID_HEIGHT; float floorZ = VMAP_INVALID_HEIGHT;
@ -120,14 +123,12 @@ namespace VMAP
[[nodiscard]] bool isMapLoadingEnabled() const { return (iEnableLineOfSightCalc || iEnableHeightCalc ); } [[nodiscard]] bool isMapLoadingEnabled() const { return (iEnableLineOfSightCalc || iEnableHeightCalc ); }
[[nodiscard]] virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const = 0; [[nodiscard]] virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const = 0;
/** /**
Query world model area info. Query world model area info.
\param z gets adjusted to the ground height for which this are info is valid \param z gets adjusted to the ground height for which this are info is valid
*/ */
virtual bool GetAreaInfo(uint32 pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const = 0; virtual bool GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, Optional<uint8> reqLiquidType, AreaAndLiquidData& data) const = 0;
virtual bool GetLiquidLevel(uint32 pMapId, 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(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const = 0;
}; };
} }

View File

@ -253,70 +253,8 @@ namespace VMAP
return VMAP_INVALID_HEIGHT_VALUE; return VMAP_INVALID_HEIGHT_VALUE;
} }
bool VMapMgr2::GetAreaInfo(uint32 mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const bool VMapMgr2::GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, Optional<uint8> reqLiquidType, AreaAndLiquidData& data) const
{ {
#if defined(ENABLE_VMAP_CHECKS)
if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG))
#endif
{
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 VMapMgr2::GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const
{
#if defined(ENABLE_VMAP_CHECKS)
if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS))
#endif
{
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<float>::max());
type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc
mogpFlags = info.hitModel->GetMogpFlags();
if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType))
{
return false;
}
if (info.hitInstance->GetLiquidLevel(pos, info, level))
{
return true;
}
}
}
}
return false;
}
void VMapMgr2::GetAreaAndLiquidData(uint32 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); InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end()) if (instanceTree != iInstanceMapTrees.end())
{ {
@ -325,16 +263,22 @@ namespace VMAP
if (instanceTree->second->GetLocationInfo(pos, info)) if (instanceTree->second->GetLocationInfo(pos, info))
{ {
data.floorZ = info.ground_Z; data.floorZ = info.ground_Z;
uint32 liquidType = info.hitModel->GetLiquidType(); if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS))
float liquidLevel; {
if (!reqLiquidType || (GetLiquidFlagsPtr(liquidType) & reqLiquidType)) uint32 liquidType = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc
if (info.hitInstance->GetLiquidLevel(pos, info, liquidLevel)) float liquidLevel;
data.liquidInfo.emplace(liquidType, liquidLevel); if (!reqLiquidType || (GetLiquidFlagsPtr(liquidType) & *reqLiquidType))
if (info.hitInstance->GetLiquidLevel(pos, info, liquidLevel))
data.liquidInfo.emplace(liquidType, liquidLevel);
}
if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG)) 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* VMapMgr2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */) WorldModel* VMapMgr2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */)

View File

@ -115,9 +115,7 @@ namespace VMAP
bool processCommand(char* /*command*/) override { return false; } // for debug and extensions bool processCommand(char* /*command*/) override { return false; } // for debug and extensions
bool GetAreaInfo(uint32 pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const override; bool GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, Optional<uint8> reqLiquidType, AreaAndLiquidData& data) const override;
bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const override;
void GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const override;
WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags); WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags);
void releaseModelInstance(const std::string& filename); void releaseModelInstance(const std::string& filename);

View File

@ -51,22 +51,6 @@ namespace VMAP
bool hit; bool hit;
}; };
class AreaInfoCallback
{
public:
AreaInfoCallback(ModelInstance* val): prims(val) {}
void operator()(const Vector3& point, uint32 entry)
{
#if defined(VMAP_DEBUG)
LOG_DEBUG("maps", "AreaInfoCallback: trying to intersect '{}'", prims[entry].name);
#endif
prims[entry].intersectPoint(point, aInfo);
}
ModelInstance* prims;
AreaInfo aInfo;
};
class LocationInfoCallback class LocationInfoCallback
{ {
public: public:
@ -99,22 +83,6 @@ namespace VMAP
return tilefilename.str(); 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(const Vector3& pos, LocationInfo& info) const bool StaticMapTree::GetLocationInfo(const Vector3& pos, LocationInfo& info) const
{ {
LocationInfoCallback intersectionCallBack(iTreeValues, info); LocationInfoCallback intersectionCallBack(iTreeValues, info);

View File

@ -30,6 +30,12 @@ namespace VMAP
enum class ModelIgnoreFlags : uint32; enum class ModelIgnoreFlags : uint32;
enum class LoadResult : uint8; enum class LoadResult : uint8;
struct GroupLocationInfo
{
const GroupModel* hitModel = nullptr;
int32 rootId = -1;
};
struct LocationInfo struct LocationInfo
{ {
LocationInfo(): ground_Z(-G3D::inf()) { } LocationInfo(): ground_Z(-G3D::inf()) { }
@ -73,7 +79,6 @@ namespace VMAP
[[nodiscard]] bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2, ModelIgnoreFlags ignoreFlags) const; [[nodiscard]] bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2, ModelIgnoreFlags ignoreFlags) const;
bool GetObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const; bool GetObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const;
[[nodiscard]] float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const; [[nodiscard]] float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const;
bool GetAreaInfo(G3D::Vector3& pos, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const;
bool GetLocationInfo(const G3D::Vector3& pos, LocationInfo& info) const; bool GetLocationInfo(const G3D::Vector3& pos, LocationInfo& info) const;
bool InitMap(const std::string& fname, VMapMgr2* vm); bool InitMap(const std::string& fname, VMapMgr2* vm);

View File

@ -203,27 +203,6 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto
return hit; 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 bool GameObjectModel::GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const
{ {
if (!(phasemask & ph_mask) || !owner->IsSpawned() || !IsMapObject()) if (!(phasemask & ph_mask) || !owner->IsSpawned() || !IsMapObject())
@ -236,7 +215,9 @@ bool GameObjectModel::GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationI
Vector3 pModel = iInvRot * (point - iPos) * iInvScale; Vector3 pModel = iInvRot * (point - iPos) * iInvScale;
Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
float zDist; float zDist;
if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info))
VMAP::GroupLocationInfo groupInfo;
if (iModel->GetLocationInfo(pModel, zDirModel, zDist, groupInfo))
{ {
Vector3 modelGround = pModel + zDist * zDirModel; Vector3 modelGround = pModel + zDist * zDirModel;
float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;

View File

@ -70,7 +70,6 @@ public:
[[nodiscard]] bool IsMapObject() const { return isWmo; } [[nodiscard]] bool IsMapObject() const { return isWmo; }
bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask, VMAP::ModelIgnoreFlags ignoreFlags) const; bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask, VMAP::ModelIgnoreFlags ignoreFlags) const;
void IntersectPoint(G3D::Vector3 const& point, VMAP::AreaInfo& info, uint32 ph_mask) const;
bool GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const; bool GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const;
bool GetLiquidLevel(G3D::Vector3 const& point, VMAP::LocationInfo& info, float& liqHeight) const; bool GetLiquidLevel(G3D::Vector3 const& point, VMAP::LocationInfo& info, float& liqHeight) const;

View File

@ -63,44 +63,6 @@ namespace VMAP
return hit; return hit;
} }
void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo& info) const
{
if (!iModel)
{
#ifdef VMAP_DEBUG
std::cout << "<object not loaded>\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 bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const
{ {
if (!iModel) if (!iModel)
@ -124,7 +86,9 @@ namespace VMAP
Vector3 pModel = iInvRot * (p - iPos) * iInvScale; Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
float zDist; float zDist;
if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info))
GroupLocationInfo groupInfo;
if (iModel->GetLocationInfo(pModel, zDirModel, zDist, groupInfo))
{ {
Vector3 modelGround = pModel + zDist * zDirModel; Vector3 modelGround = pModel + zDist * zDirModel;
// Transform back to world space. Note that: // Transform back to world space. Note that:
@ -133,6 +97,8 @@ namespace VMAP
float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection? if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection?
{ {
info.rootId = groupInfo.rootId;
info.hitModel = groupInfo.hitModel;
info.ground_Z = world_Z; info.ground_Z = world_Z;
info.hitInstance = this; info.hitInstance = this;
return true; return true;

View File

@ -66,7 +66,6 @@ namespace VMAP
ModelInstance(const ModelSpawn& spawn, WorldModel* model); ModelInstance(const ModelSpawn& spawn, WorldModel* model);
void setUnloaded() { iModel = nullptr; } void setUnloaded() { iModel = nullptr; }
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit, ModelIgnoreFlags ignoreFlags) const; bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
void intersectPoint(const G3D::Vector3& p, AreaInfo& info) const;
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const; bool GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const;
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const; bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const;
WorldModel* getWorldModel() { return iModel; } WorldModel* getWorldModel() { return iModel; }

View File

@ -20,9 +20,9 @@
#include "ModelIgnoreFlags.h" #include "ModelIgnoreFlags.h"
#include "ModelInstance.h" #include "ModelInstance.h"
#include "VMapDefinitions.h" #include "VMapDefinitions.h"
#include <array>
using G3D::Vector3; using G3D::Vector3;
using G3D::Ray;
template<> struct BoundsTrait<VMAP::GroupModel> template<> struct BoundsTrait<VMAP::GroupModel>
{ {
@ -451,21 +451,46 @@ namespace VMAP
return callback.hit; return callback.hit;
} }
bool GroupModel::IsInsideObject(const Vector3& pos, const Vector3& down, float& z_dist) const inline bool IsInsideOrAboveBound(G3D::AABox const& bounds, const G3D::Point3& point)
{ {
if (triangles.empty() || !iBound.contains(pos)) return point.x >= bounds.low().x
&& point.y >= bounds.low().y
&& point.z >= bounds.low().z
&& point.x <= bounds.high().x
&& point.y <= bounds.high().y;
}
GroupModel::InsideResult GroupModel::IsInsideObject(G3D::Ray const& ray, float& z_dist) const
{
if (triangles.empty() || !IsInsideOrAboveBound(iBound, ray.origin()))
return OUT_OF_BOUNDS;
if (meshTree.bound().high().z >= ray.origin().z)
{ {
return false; float dist = G3D::finf();
if (IntersectRay(ray, dist, false))
{
z_dist = dist - 0.1f;
return INSIDE;
}
if (meshTree.bound().contains(ray.origin()))
return MAYBE_INSIDE;
} }
Vector3 rPos = pos - 0.1f * down; else
float dist = G3D::inf();
G3D::Ray ray(rPos, down);
bool hit = IntersectRay(ray, dist, false);
if (hit)
{ {
z_dist = dist - 0.1f; // some group models don't have any floor to intersect with
// so we should attempt to intersect with a model part below this group
// then find back where we originated from (in WorldModel::GetLocationInfo)
float dist = G3D::finf();
float delta = ray.origin().z - meshTree.bound().high().z;
if (IntersectRay(ray.bumpedRay(delta), dist, false))
{
z_dist = dist - 0.1f + delta;
return ABOVE;
}
} }
return hit;
return OUT_OF_BOUNDS;
} }
bool GroupModel::GetLiquidLevel(const Vector3& pos, float& liqHeight) const bool GroupModel::GetLiquidLevel(const Vector3& pos, float& liqHeight) const
@ -541,76 +566,58 @@ namespace VMAP
class WModelAreaCallback class WModelAreaCallback
{ {
public: public:
WModelAreaCallback(const std::vector<GroupModel>& vals, const Vector3& down): WModelAreaCallback(std::vector<GroupModel> const& vals) :
prims(vals.begin()), hit(vals.end()), minVol(G3D::inf()), zDist(G3D::inf()), zVec(down) { } prims(vals), hit() { }
std::vector<GroupModel>::const_iterator prims; std::vector<GroupModel> const& prims;
std::vector<GroupModel>::const_iterator hit; std::array<GroupModel const*, 3> hit;
float minVol; bool operator()(G3D::Ray const& ray, uint32 entry, float& distance, bool /*stopAtFirstHit*/)
float zDist;
Vector3 zVec;
void operator()(const Vector3& point, uint32 entry)
{ {
float group_Z; float group_Z;
//float pVol = prims[entry].GetBound().volume(); if (GroupModel::InsideResult result = prims[entry].IsInsideObject(ray, group_Z); result != GroupModel::OUT_OF_BOUNDS)
//if (pVol < minVol)
//{
/* if (prims[entry].iBound.contains(point)) */
if (prims[entry].IsInsideObject(point, zVec, group_Z))
{ {
//minVol = pVol; if (result != GroupModel::MAYBE_INSIDE)
//hit = prims + entry;
if (group_Z < zDist)
{ {
zDist = group_Z; if (group_Z < distance)
hit = prims + entry; {
distance = group_Z;
hit[result] = &prims[entry];
return true;
}
} }
#ifdef VMAP_DEBUG else
const GroupModel& gm = prims[entry]; hit[result] = &prims[entry];
printf("%10u %8X %7.3f, %7.3f, %7.3f | %7.3f, %7.3f, %7.3f | z=%f, p_z=%f\n", gm.GetWmoID(), gm.GetMogpFlags(),
gm.GetBound().low().x, gm.GetBound().low().y, gm.GetBound().low().z,
gm.GetBound().high().x, gm.GetBound().high().y, gm.GetBound().high().z, group_Z, point.z);
#endif
} }
//} return false;
//std::cout << "trying to intersect '" << prims[entry].name << "'\n";
} }
}; };
bool WorldModel::IntersectPoint(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, AreaInfo& info) const bool WorldModel::GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, GroupLocationInfo& info) const
{ {
if (groupModels.empty()) if (groupModels.empty())
{ {
return false; return false;
} }
WModelAreaCallback callback(groupModels, down); WModelAreaCallback callback(groupModels);
groupTree.intersectPoint(p, callback); G3D::Ray r(p - down * 0.1f, down);
if (callback.hit != groupModels.end()) float zDist = groupTree.bound().extent().length();
groupTree.intersectRay(r, callback, zDist, false);
if (callback.hit[GroupModel::INSIDE])
{ {
info.rootId = RootWMOID; info.rootId = RootWMOID;
info.groupId = callback.hit->GetWmoID(); info.hitModel = callback.hit[GroupModel::INSIDE];
info.flags = callback.hit->GetMogpFlags(); dist = zDist;
info.result = true;
dist = callback.zDist;
return true; return true;
} }
return false;
}
bool WorldModel::GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const // some group models don't have any floor to intersect with
{ // so we should attempt to intersect with a model part below the group `p` is in (stored in GroupModel::ABOVE)
if (groupModels.empty()) // then find back where we originated from (GroupModel::MAYBE_INSIDE)
{ if (callback.hit[GroupModel::MAYBE_INSIDE] && callback.hit[GroupModel::ABOVE])
return false;
}
WModelAreaCallback callback(groupModels, down);
groupTree.intersectPoint(p, callback);
if (callback.hit != groupModels.end())
{ {
info.rootId = RootWMOID; info.rootId = RootWMOID;
info.hitModel = &(*callback.hit); info.hitModel = callback.hit[GroupModel::MAYBE_INSIDE];
dist = callback.zDist; dist = zDist;
return true; return true;
} }
return false; return false;

View File

@ -29,6 +29,7 @@ namespace VMAP
class TreeNode; class TreeNode;
struct AreaInfo; struct AreaInfo;
struct LocationInfo; struct LocationInfo;
struct GroupLocationInfo;
enum class ModelIgnoreFlags : uint32; enum class ModelIgnoreFlags : uint32;
class MeshTriangle class MeshTriangle
@ -81,12 +82,14 @@ namespace VMAP
void setMeshData(std::vector<G3D::Vector3>& vert, std::vector<MeshTriangle>& tri); void setMeshData(std::vector<G3D::Vector3>& vert, std::vector<MeshTriangle>& tri);
void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = nullptr; } void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = nullptr; }
bool IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const; bool IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const;
bool IsInsideObject(const G3D::Vector3& pos, const G3D::Vector3& down, float& z_dist) const; enum InsideResult { INSIDE = 0, MAYBE_INSIDE = 1, ABOVE = 2, OUT_OF_BOUNDS = -1 };
InsideResult IsInsideObject(G3D::Ray const& ray, float& z_dist) const;
bool GetLiquidLevel(const G3D::Vector3& pos, float& liqHeight) const; bool GetLiquidLevel(const G3D::Vector3& pos, float& liqHeight) const;
[[nodiscard]] uint32 GetLiquidType() const; [[nodiscard]] uint32 GetLiquidType() const;
bool writeToFile(FILE* wf); bool writeToFile(FILE* wf);
bool readFromFile(FILE* rf); bool readFromFile(FILE* rf);
[[nodiscard]] const G3D::AABox& GetBound() const { return iBound; } [[nodiscard]] G3D::AABox const& GetBound() const { return iBound; }
[[nodiscard]] G3D::AABox const& GetMeshTreeBound() const { return meshTree.bound(); }
[[nodiscard]] uint32 GetMogpFlags() const { return iMogpFlags; } [[nodiscard]] uint32 GetMogpFlags() const { return iMogpFlags; }
[[nodiscard]] uint32 GetWmoID() const { return iGroupWMOID; } [[nodiscard]] uint32 GetWmoID() const { return iGroupWMOID; }
void GetMeshData(std::vector<G3D::Vector3>& outVertices, std::vector<MeshTriangle>& outTriangles, WmoLiquid*& liquid); void GetMeshData(std::vector<G3D::Vector3>& outVertices, std::vector<MeshTriangle>& outTriangles, WmoLiquid*& liquid);
@ -109,8 +112,7 @@ namespace VMAP
void setGroupModels(std::vector<GroupModel>& models); void setGroupModels(std::vector<GroupModel>& models);
void setRootWmoID(uint32 id) { RootWMOID = id; } void setRootWmoID(uint32 id) { RootWMOID = id; }
bool IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) 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, GroupLocationInfo& info) const;
bool GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const;
bool writeFile(const std::string& filename); bool writeFile(const std::string& filename);
bool readFile(const std::string& filename); bool readFile(const std::string& filename);
void GetGroupModels(std::vector<GroupModel>& outGroupModels); void GetGroupModels(std::vector<GroupModel>& outGroupModels);

View File

@ -527,9 +527,11 @@ float GridTerrainData::getLiquidLevel(float x, float y) const
} }
// Get water state on map // Get water state on map
LiquidData const GridTerrainData::GetLiquidData(float x, float y, float z, float collisionHeight, uint8 ReqLiquidType) const LiquidData const GridTerrainData::GetLiquidData(float x, float y, float z, float collisionHeight, Optional<uint8> ReqLiquidType) const
{ {
LiquidData liquidData; LiquidData liquidData;
liquidData.Status = LIQUID_MAP_NO_WATER;
if (!_loadedLiquidData) if (!_loadedLiquidData)
return liquidData; return liquidData;
@ -575,7 +577,7 @@ LiquidData const GridTerrainData::GetLiquidData(float x, float y, float z, float
} }
// Check req liquid type mask // Check req liquid type mask
if (type != 0 && (!ReqLiquidType || (ReqLiquidType & type) != 0)) if (type != 0 && (!ReqLiquidType || (*ReqLiquidType & type) != 0))
{ {
// Check water level: // Check water level:
// Check water height map // Check water height map

View File

@ -186,7 +186,7 @@ struct LoadedHoleData
HolesType holes; HolesType holes;
}; };
enum LiquidStatus enum LiquidStatus : uint32
{ {
LIQUID_MAP_NO_WATER = 0x00000000, LIQUID_MAP_NO_WATER = 0x00000000,
LIQUID_MAP_ABOVE_WATER = 0x00000001, LIQUID_MAP_ABOVE_WATER = 0x00000001,
@ -249,7 +249,7 @@ public:
inline float getHeight(float x, float y) const { return (this->*_gridGetHeight)(x, y); } inline float getHeight(float x, float y) const { return (this->*_gridGetHeight)(x, y); }
float getMinHeight(float x, float y) const; float getMinHeight(float x, float y) const;
float getLiquidLevel(float x, float y) const; float getLiquidLevel(float x, float y) const;
LiquidData const GetLiquidData(float x, float y, float z, float collisionHeight, uint8 ReqLiquidType) const; LiquidData const GetLiquidData(float x, float y, float z, float collisionHeight, Optional<uint8> ReqLiquidType) const;
}; };
#endif #endif

View File

@ -1097,7 +1097,7 @@ float Map::GetWaterOrGroundLevel(uint32 phasemask, float x, float y, float z, fl
if (ground) if (ground)
*ground = ground_z; *ground = ground_z;
LiquidData const& liquidData = const_cast<Map*>(this)->GetLiquidData(phasemask, x, y, ground_z, collisionHeight, MAP_ALL_LIQUIDS); LiquidData const& liquidData = const_cast<Map*>(this)->GetLiquidData(phasemask, x, y, ground_z, collisionHeight, {});
switch (liquidData.Status) switch (liquidData.Status)
{ {
case LIQUID_MAP_ABOVE_WATER: case LIQUID_MAP_ABOVE_WATER:
@ -1198,27 +1198,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 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; float check_z = z;
VMAP::IVMapMgr* vmgr = VMAP::VMapFactory::createOrGetVMapMgr(); VMAP::IVMapMgr* vmgr = VMAP::VMapFactory::createOrGetVMapMgr();
uint32 vflags; VMAP::AreaAndLiquidData vdata;
int32 vadtId; VMAP::AreaAndLiquidData ddata;
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; };
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 (hasVmapAreaInfo)
{ {
if (hasDynamicAreaInfo && dynamic_z > vmap_z) if (hasDynamicAreaInfo && ddata.floorZ > vdata.floorZ)
useDyn(); useDyn();
else else
useVmap(); useVmap();
@ -1299,32 +1290,30 @@ void Map::GetZoneAndAreaId(uint32 phaseMask, uint32& zoneid, uint32& areaid, flo
zoneid = area->zone; zoneid = area->zone;
} }
LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z, float collisionHeight, uint8 ReqLiquidType) LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z, float collisionHeight, Optional<uint8> ReqLiquidType)
{ {
LiquidData liquidData; LiquidData liquidData;
liquidData.Status = LIQUID_MAP_NO_WATER;
VMAP::IVMapMgr* vmgr = VMAP::VMapFactory::createOrGetVMapMgr(); VMAP::IVMapMgr* vmgr = VMAP::VMapFactory::createOrGetVMapMgr();
float liquid_level = INVALID_HEIGHT; VMAP::AreaAndLiquidData vmapData;
float ground_level = INVALID_HEIGHT;
uint32 liquid_type = 0;
uint32 mogpFlags = 0;
bool useGridLiquid = true; 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); useGridLiquid = !vmapData.areaInfo || !IsInWMOInterior(vmapData.areaInfo->mogpFlags);
LOG_DEBUG("maps", "GetLiquidStatus(): vmap liquid level: {} ground: {} type: {}", liquid_level, ground_level, liquid_type); LOG_DEBUG("maps", "GetLiquidStatus(): vmap liquid level: {} ground: {} type: {}", vmapData.liquidInfo->level, vmapData.floorZ, vmapData.liquidInfo->type);
// Check water level and ground level // 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))
{ {
// hardcoded in client like this // hardcoded in client like this
if (GetId() == MAP_OUTLAND && liquid_type == 2) if (GetId() == MAP_OUTLAND && vmapData.liquidInfo->type == 2)
liquid_type = 15; vmapData.liquidInfo->type = 15;
uint32 liquidFlagType = 0; uint32 liquidFlagType = 0;
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(liquid_type)) if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(vmapData.liquidInfo->type))
liquidFlagType = liq->Type; liquidFlagType = liq->Type;
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))) if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(phaseMask, x, y, z)))
{ {
@ -1338,19 +1327,19 @@ LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z,
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid)) if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
{ {
liquid_type = overrideLiquid; vmapData.liquidInfo->type = overrideLiquid;
liquidFlagType = liq->Type; liquidFlagType = liq->Type;
} }
} }
} }
liquidData.Level = liquid_level; liquidData.Level = vmapData.liquidInfo->level;
liquidData.DepthLevel = ground_level; liquidData.DepthLevel = vmapData.floorZ;
liquidData.Entry = liquid_type; liquidData.Entry = vmapData.liquidInfo->type;
liquidData.Flags = 1 << liquidFlagType; liquidData.Flags = 1 << liquidFlagType;
} }
float delta = liquid_level - z; float delta = vmapData.liquidInfo->level - z;
// Get position delta // Get position delta
if (delta > collisionHeight) if (delta > collisionHeight)
@ -1369,7 +1358,7 @@ LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z,
{ {
LiquidData const& map_data = gmap->GetLiquidData(x, y, z, collisionHeight, ReqLiquidType); LiquidData const& map_data = gmap->GetLiquidData(x, y, z, collisionHeight, ReqLiquidType);
// Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER: // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
if (map_data.Status != LIQUID_MAP_NO_WATER && (map_data.Level > ground_level)) if (map_data.Status != LIQUID_MAP_NO_WATER && (map_data.Level > vmapData.floorZ))
{ {
// hardcoded in client like this // hardcoded in client like this
uint32 liquidEntry = map_data.Entry; uint32 liquidEntry = map_data.Entry;
@ -1385,7 +1374,7 @@ LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z,
return liquidData; return liquidData;
} }
void Map::GetFullTerrainStatusForPosition(uint32 /*phaseMask*/, float x, float y, float z, float collisionHeight, PositionFullTerrainStatus& data, uint8 reqLiquidType) void Map::GetFullTerrainStatusForPosition(uint32 /*phaseMask*/, float x, float y, float z, float collisionHeight, PositionFullTerrainStatus& data, Optional<uint8> reqLiquidType)
{ {
GridTerrainData* gmap = GetGridTerrainData(x, y); GridTerrainData* gmap = GetGridTerrainData(x, y);
@ -1600,7 +1589,7 @@ float Map::GetHeight(uint32 phasemask, float x, float y, float z, bool vmap/*=tr
bool Map::IsInWater(uint32 phaseMask, float x, float y, float pZ, float collisionHeight) const bool Map::IsInWater(uint32 phaseMask, float x, float y, float pZ, float collisionHeight) const
{ {
LiquidData const& liquidData = const_cast<Map*>(this)->GetLiquidData(phaseMask, x, y, pZ, collisionHeight, MAP_ALL_LIQUIDS); LiquidData const& liquidData = const_cast<Map*>(this)->GetLiquidData(phaseMask, x, y, pZ, collisionHeight, {});
return (liquidData.Status & MAP_LIQUID_STATUS_SWIMMING) != 0; return (liquidData.Status & MAP_LIQUID_STATUS_SWIMMING) != 0;
} }

View File

@ -243,8 +243,8 @@ public:
[[nodiscard]] float GetMinHeight(float x, float y) const; [[nodiscard]] float GetMinHeight(float x, float y) const;
Transport* GetTransportForPos(uint32 phase, float x, float y, float z, WorldObject* worldobject = nullptr); Transport* GetTransportForPos(uint32 phase, float x, float y, float z, WorldObject* worldobject = nullptr);
void GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, float z, float collisionHeight, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS); void GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, float z, float collisionHeight, PositionFullTerrainStatus& data, Optional<uint8> reqLiquidType = {});
LiquidData const GetLiquidData(uint32 phaseMask, float x, float y, float z, float collisionHeight, uint8 ReqLiquidType); LiquidData const GetLiquidData(uint32 phaseMask, float x, float y, float z, float collisionHeight, Optional<uint8> ReqLiquidType);
[[nodiscard]] bool GetAreaInfo(uint32 phaseMask, float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const; [[nodiscard]] bool GetAreaInfo(uint32 phaseMask, float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const;
[[nodiscard]] uint32 GetAreaId(uint32 phaseMask, float x, float y, float z) const; [[nodiscard]] uint32 GetAreaId(uint32 phaseMask, float x, float y, float z) const;

View File

@ -211,8 +211,8 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
{ {
bool buildShortcut = false; bool buildShortcut = false;
auto liquidDataStart = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), startPos.x, startPos.y, startPos.z, _source->GetCollisionHeight(), MAP_ALL_LIQUIDS); auto liquidDataStart = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), startPos.x, startPos.y, startPos.z, _source->GetCollisionHeight(), {});
auto liquidDataEnd = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), endPos.x, endPos.y, endPos.z, _source->GetCollisionHeight(), MAP_ALL_LIQUIDS); auto liquidDataEnd = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), endPos.x, endPos.y, endPos.z, _source->GetCollisionHeight(), {});
bool startUnderWaterEndInWater = liquidDataStart.Status == LIQUID_MAP_UNDER_WATER && bool startUnderWaterEndInWater = liquidDataStart.Status == LIQUID_MAP_UNDER_WATER &&
(liquidDataEnd.Status & MAP_LIQUID_STATUS_IN_CONTACT) != 0; (liquidDataEnd.Status & MAP_LIQUID_STATUS_IN_CONTACT) != 0;
@ -698,7 +698,7 @@ void PathGenerator::UpdateFilter()
NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) const NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) const
{ {
LiquidData const& liquidData = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), x, y, z, _source->GetCollisionHeight(), MAP_ALL_LIQUIDS); LiquidData const& liquidData = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), x, y, z, _source->GetCollisionHeight(), {});
if (liquidData.Status == LIQUID_MAP_NO_WATER) if (liquidData.Status == LIQUID_MAP_NO_WATER)
return NAV_GROUND; return NAV_GROUND;

View File

@ -1384,7 +1384,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
float ground = m_caster->GetMapHeight(x, y, z, true); float ground = m_caster->GetMapHeight(x, y, z, true);
float liquidLevel = VMAP_INVALID_HEIGHT_VALUE; float liquidLevel = VMAP_INVALID_HEIGHT_VALUE;
LiquidData const& liquidData = m_caster->GetMap()->GetLiquidData(m_caster->GetPhaseMask(), x, y, z, m_caster->GetCollisionHeight(), MAP_ALL_LIQUIDS); LiquidData const& liquidData = m_caster->GetMap()->GetLiquidData(m_caster->GetPhaseMask(), x, y, z, m_caster->GetCollisionHeight(), {});
if (liquidData.Status) if (liquidData.Status)
liquidLevel = liquidData.Level; liquidLevel = liquidData.Level;

View File

@ -2045,7 +2045,7 @@ class spell_spawn_blood_pool : public SpellScript
void SetDest(SpellDestination &dest) void SetDest(SpellDestination &dest)
{ {
Unit* caster = GetCaster(); Unit* caster = GetCaster();
LiquidData liquidStatus = caster->GetMap()->GetLiquidData(caster->GetPhaseMask(), caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ(), caster->GetCollisionHeight(), MAP_ALL_LIQUIDS); LiquidData liquidStatus = caster->GetMap()->GetLiquidData(caster->GetPhaseMask(), caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ(), caster->GetCollisionHeight(), {});
float level = liquidStatus.Level > INVALID_HEIGHT ? liquidStatus.Level : caster->GetPositionZ(); float level = liquidStatus.Level > INVALID_HEIGHT ? liquidStatus.Level : caster->GetPositionZ();
Position pos = Position(caster->GetPositionX(), caster->GetPositionY(), level, caster->GetOrientation()); Position pos = Position(caster->GetPositionX(), caster->GetPositionY(), level, caster->GetOrientation());