aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2018-03-28 22:01:22 +0200
committerShauren <shauren.trinity@gmail.com>2020-06-27 20:23:30 +0200
commit0468c70dfe91794ad272594323dd7feb611d0a93 (patch)
treebb623c775fe215e4c0867fb2efa4bda0b360f7ec /src/common
parent54c701cf0db81c0062e8c5020e07db18984d0ffa (diff)
Core/Maps: Implemented getting area id from gameobject spawns
Yes, you can now spawn LK platform anywhere and it will treat you as inside Icecrown Citadel (cherry picked from commit 42f9deb21ec68e169f7ed1c8cf14092f144b22da)
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Collision/DynamicTree.cpp86
-rw-r--r--src/common/Collision/DynamicTree.h7
-rw-r--r--src/common/Collision/Models/GameObjectModel.cpp64
-rw-r--r--src/common/Collision/Models/GameObjectModel.h12
4 files changed, 160 insertions, 9 deletions
diff --git a/src/common/Collision/DynamicTree.cpp b/src/common/Collision/DynamicTree.cpp
index 40acfb6c49b..bae8ab38dc1 100644
--- a/src/common/Collision/DynamicTree.cpp
+++ b/src/common/Collision/DynamicTree.cpp
@@ -16,17 +16,16 @@
*/
#include "DynamicTree.h"
-//#include "QuadTree.h"
-//#include "RegularGrid.h"
#include "BoundingIntervalHierarchyWrapper.h"
-
+#include "GameObjectModel.h"
#include "Log.h"
+#include "MapTree.h"
+#include "ModelIgnoreFlags.h"
+#include "ModelInstance.h"
#include "RegularGrid.h"
#include "Timer.h"
-#include "GameObjectModel.h"
-#include "ModelInstance.h"
-#include "ModelIgnoreFlags.h"
-
+#include "VMapFactory.h"
+#include "VMapManager2.h"
#include <G3D/AABox.h>
#include <G3D/Ray.h>
#include <G3D/Vector3.h>
@@ -174,6 +173,41 @@ struct DynamicTreeIntersectionCallback_WithLogger
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) {}
+
+ void operator()(G3D::Vector3 const& p, GameObjectModel const& obj)
+ {
+ if (obj.GetLocationInfo(p, _locationInfo, _phaseMask))
+ _hitModel = &obj;
+ }
+
+ VMAP::LocationInfo& GetLocationInfo() { return _locationInfo; }
+ GameObjectModel const* GetHitModel() const { return _hitModel; }
+
+private:
+ uint32 _phaseMask;
+ VMAP::LocationInfo _locationInfo;
+ GameObjectModel const* _hitModel;
+};
+
bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray,
const G3D::Vector3& endPos, float& maxDist) const
{
@@ -253,3 +287,41 @@ float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist,
else
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
+{
+ G3D::Vector3 v(x, y, z + 0.5f);
+ DynamicTreeLocationInfoCallback intersectionCallBack(phasemask);
+ impl->intersectPoint(v, intersectionCallBack);
+ if (intersectionCallBack.GetLocationInfo().hitModel)
+ {
+ data.floorZ = intersectionCallBack.GetLocationInfo().ground_Z;
+ uint32 liquidType = intersectionCallBack.GetLocationInfo().hitModel->GetLiquidType();
+ float liquidLevel;
+ if (!reqLiquidType || (dynamic_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager())->GetLiquidFlagsPtr(liquidType) & reqLiquidType))
+ if (intersectionCallBack.GetHitModel()->GetLiquidLevel(v, intersectionCallBack.GetLocationInfo(), liquidLevel))
+ data.liquidInfo = boost::in_place(liquidType, liquidLevel);
+
+ data.areaInfo = boost::in_place(0,
+ intersectionCallBack.GetLocationInfo().rootId,
+ intersectionCallBack.GetLocationInfo().hitModel->GetWmoID(),
+ intersectionCallBack.GetLocationInfo().hitModel->GetMogpFlags());
+ }
+}
diff --git a/src/common/Collision/DynamicTree.h b/src/common/Collision/DynamicTree.h
index 8f2729cb76a..a890f828b96 100644
--- a/src/common/Collision/DynamicTree.h
+++ b/src/common/Collision/DynamicTree.h
@@ -30,6 +30,11 @@ namespace G3D
class GameObjectModel;
struct DynTreeImpl;
+namespace VMAP
+{
+ struct AreaAndLiquidData;
+}
+
class TC_COMMON_API DynamicMapTree
{
DynTreeImpl *impl;
@@ -44,6 +49,8 @@ public:
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 getObjectHitPos(uint32 phasemask, const G3D::Vector3& pPos1,
const G3D::Vector3& pPos2, G3D::Vector3& pResultHitPos,
diff --git a/src/common/Collision/Models/GameObjectModel.cpp b/src/common/Collision/Models/GameObjectModel.cpp
index 54b48714c90..2c95187fbb2 100644
--- a/src/common/Collision/Models/GameObjectModel.cpp
+++ b/src/common/Collision/Models/GameObjectModel.cpp
@@ -146,6 +146,7 @@ bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> model
#endif
owner = std::move(modelOwner);
+ isWmo = it->second.isWmo;
return true;
}
@@ -183,6 +184,69 @@ 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())
+ return false;
+
+ if (!iBound.contains(point))
+ return false;
+
+ // 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->GetLocationInfo(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;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool GameObjectModel::GetLiquidLevel(G3D::Vector3 const& point, VMAP::LocationInfo& info, float& liqHeight) const
+{
+ // 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 (info.hitModel->GetLiquidLevel(pModel, zDist))
+ {
+ // calculate world height (zDist in model coords):
+ // assume WMO not tilted (wouldn't make much sense anyway)
+ liqHeight = zDist * iScale + iPos.z;
+ return true;
+ }
+ return false;
+}
+
bool GameObjectModel::UpdatePosition()
{
if (!iModel)
diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h
index 99ffef0ee98..78f17b75391 100644
--- a/src/common/Collision/Models/GameObjectModel.h
+++ b/src/common/Collision/Models/GameObjectModel.h
@@ -29,6 +29,8 @@
namespace VMAP
{
class WorldModel;
+ struct AreaInfo;
+ struct LocationInfo;
enum class ModelIgnoreFlags : uint32;
}
@@ -38,6 +40,8 @@ struct GameObjectDisplayInfoEntry;
class TC_COMMON_API GameObjectModelOwnerBase
{
public:
+ virtual ~GameObjectModelOwnerBase() = default;
+
virtual bool IsSpawned() const = 0;
virtual uint32 GetDisplayId() const = 0;
virtual uint32 GetPhaseMask() const = 0;
@@ -45,12 +49,11 @@ public:
virtual float GetOrientation() const = 0;
virtual float GetScale() const = 0;
virtual void DebugVisualizeCorner(G3D::Vector3 const& /*corner*/) const = 0;
- virtual ~GameObjectModelOwnerBase() { }
};
class TC_COMMON_API GameObjectModel /*, public Intersectable*/
{
- GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(nullptr) { }
+ GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(nullptr), isWmo(false) { }
public:
std::string name;
@@ -65,8 +68,12 @@ public:
void enable(uint32 ph_mask) { phasemask = ph_mask;}
bool isEnabled() const {return phasemask != 0;}
+ 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;
static GameObjectModel* Create(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath);
@@ -83,6 +90,7 @@ private:
float iScale;
VMAP::WorldModel* iModel;
std::unique_ptr<GameObjectModelOwnerBase> owner;
+ bool isWmo;
};
TC_COMMON_API void LoadGameObjectModelList(std::string const& dataPath);