Skip to content

Commit

Permalink
Core/Vmaps: Stop M2s from occluding for spellcast LoS
Browse files Browse the repository at this point in the history
Closes #18528
  • Loading branch information
HelloKitty authored and Shauren committed Jan 21, 2017
1 parent 998efa5 commit 01d715e
Show file tree
Hide file tree
Showing 19 changed files with 108 additions and 48 deletions.
5 changes: 3 additions & 2 deletions src/common/Collision/DynamicTree.cpp
Expand Up @@ -26,6 +26,7 @@
#include "Timer.h"
#include "GameObjectModel.h"
#include "ModelInstance.h"
#include "ModelIgnoreFlags.h"

#include <G3D/AABox.h>
#include <G3D/Ray.h>
Expand Down Expand Up @@ -151,7 +152,7 @@ struct DynamicTreeIntersectionCallback
DynamicTreeIntersectionCallback(uint32 phasemask) : did_hit(false), phase_mask(phasemask) { }
bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance)
{
did_hit = obj.intersectRay(r, distance, true, phase_mask);
did_hit = obj.intersectRay(r, distance, true, phase_mask, VMAP::ModelIgnoreFlags::Nothing);
return did_hit;
}
bool didHit() const { return did_hit;}
Expand All @@ -168,7 +169,7 @@ struct DynamicTreeIntersectionCallback_WithLogger
bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance)
{
TC_LOG_DEBUG("maps", "testing intersection with %s", obj.name.c_str());
bool hit = obj.intersectRay(r, distance, true, phase_mask);
bool hit = obj.intersectRay(r, distance, true, phase_mask, VMAP::ModelIgnoreFlags::Nothing);
if (hit)
{
did_hit = true;
Expand Down
3 changes: 2 additions & 1 deletion src/common/Collision/Management/IVMapManager.h
Expand Up @@ -21,6 +21,7 @@

#include <string>
#include "Define.h"
#include "ModelIgnoreFlags.h"

//===========================================================

Expand Down Expand Up @@ -60,7 +61,7 @@ namespace VMAP
virtual void unloadMap(unsigned int pMapId, int x, int y) = 0;
virtual void unloadMap(unsigned int pMapId) = 0;

virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) = 0;
virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags) = 0;
virtual float getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist) = 0;
/**
test if we hit an object. return true if we hit one. rx, ry, rz will hold the hit position or the dest position, if no intersection was found
Expand Down
9 changes: 6 additions & 3 deletions src/common/Collision/Management/VMapManager2.cpp
Expand Up @@ -162,7 +162,7 @@ namespace VMAP
}
}

bool VMapManager2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2)
bool VMapManager2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags)
{
if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS))
return true;
Expand All @@ -174,7 +174,7 @@ namespace VMAP
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
if (pos1 != pos2)
{
return instanceTree->second->isInLineOfSight(pos1, pos2);
return instanceTree->second->isInLineOfSight(pos1, pos2, ignoreFlags);
}
}

Expand Down Expand Up @@ -279,7 +279,7 @@ namespace VMAP
return false;
}

WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename)
WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */)
{
//! Critical section, thread safe access to iLoadedModelFiles
std::lock_guard<std::mutex> lock(LoadedModelFilesLock);
Expand All @@ -295,6 +295,9 @@ namespace VMAP
return NULL;
}
VMAP_DEBUG_LOG("maps", "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str());

worldmodel->Flags = flags;

model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first;
model->second.setModel(worldmodel);
}
Expand Down
4 changes: 2 additions & 2 deletions src/common/Collision/Management/VMapManager2.h
Expand Up @@ -107,7 +107,7 @@ namespace VMAP
void unloadMap(unsigned int mapId, int x, int y) override;
void unloadMap(unsigned int mapId) override;

bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2) override ;
bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags) override ;
/**
fill the hit pos and return true, if an object was hit
*/
Expand All @@ -119,7 +119,7 @@ namespace VMAP
bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const override;
bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const override;

WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename);
WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags = 0);
void releaseModelInstance(const std::string& filename);

// what's the use of this? o.O
Expand Down
25 changes: 12 additions & 13 deletions src/common/Collision/Maps/MapTree.cpp
Expand Up @@ -33,14 +33,13 @@ using G3D::Vector3;

namespace VMAP
{

class MapRayCallback
{
public:
MapRayCallback(ModelInstance* val): prims(val), hit(false) { }
MapRayCallback(ModelInstance* val, ModelIgnoreFlags ignoreFlags): prims(val), hit(false), flags(ignoreFlags) { }
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true)
{
bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit);
bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit, flags);
if (result)
hit = true;
return result;
Expand All @@ -49,6 +48,7 @@ namespace VMAP
protected:
ModelInstance* prims;
bool hit;
ModelIgnoreFlags flags;
};

class AreaInfoCallback
Expand Down Expand Up @@ -142,19 +142,18 @@ namespace VMAP
If intersection is found within pMaxDist, sets pMaxDist to intersection distance and returns true.
Else, pMaxDist is not modified and returns false;
*/

bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit) const
bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
{
float distance = pMaxDist;
MapRayCallback intersectionCallBack(iTreeValues);
MapRayCallback intersectionCallBack(iTreeValues, ignoreFlags);
iTree.intersectRay(pRay, intersectionCallBack, distance, pStopAtFirstHit);
if (intersectionCallBack.didHit())
pMaxDist = distance;
return intersectionCallBack.didHit();
}
//=========================================================

bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) const
//=========================================================
bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2, ModelIgnoreFlags ignoreFlag) const
{
float maxDist = (pos2 - pos1).magnitude();
// return false if distance is over max float, in case of cheater teleporting to the end of the universe
Expand All @@ -168,7 +167,7 @@ namespace VMAP
return true;
// direction with length of 1
G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist);
if (getIntersectionTime(ray, maxDist, true))
if (getIntersectionTime(ray, maxDist, true, ignoreFlag))
return false;

return true;
Expand All @@ -194,7 +193,7 @@ namespace VMAP
Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1
G3D::Ray ray(pPos1, dir);
float dist = maxDist;
if (getIntersectionTime(ray, dist, false))
if (getIntersectionTime(ray, dist, false, ModelIgnoreFlags::Nothing))
{
pResultHitPos = pPos1 + dir * dist;
if (pModifyDist < 0)
Expand Down Expand Up @@ -230,7 +229,7 @@ namespace VMAP
Vector3 dir = Vector3(0, 0, -1);
G3D::Ray ray(pPos, dir); // direction with length of 1
float maxDist = maxSearchDist;
if (getIntersectionTime(ray, maxDist, false))
if (getIntersectionTime(ray, maxDist, false, ModelIgnoreFlags::Nothing))
{
height = pPos.z - maxDist;
}
Expand Down Expand Up @@ -306,7 +305,7 @@ namespace VMAP
#endif
if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn))
{
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name);
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags);
VMAP_DEBUG_LOG("maps", "StaticMapTree::InitMap() : loading %s", spawn.name.c_str());
if (model)
{
Expand Down Expand Up @@ -376,7 +375,7 @@ namespace VMAP
if (result)
{
// acquire model instance
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name);
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags);
if (!model)
VMAP_ERROR_LOG("misc", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY);

Expand Down
6 changes: 4 additions & 2 deletions src/common/Collision/Maps/MapTree.h
Expand Up @@ -23,11 +23,13 @@
#include "BoundingIntervalHierarchy.h"
#include <unordered_map>


namespace VMAP
{
class ModelInstance;
class GroupModel;
class VMapManager2;
enum class ModelIgnoreFlags : uint32;

struct TC_COMMON_API LocationInfo
{
Expand Down Expand Up @@ -57,7 +59,7 @@ namespace VMAP
std::string iBasePath;

private:
bool getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit) const;
bool getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
//bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); }
public:
static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY);
Expand All @@ -68,7 +70,7 @@ namespace VMAP
StaticMapTree(uint32 mapID, const std::string &basePath);
~StaticMapTree();

bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) const;
bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2, ModelIgnoreFlags ignoreFlags) const;
bool getObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const;
float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const;
bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const;
Expand Down
4 changes: 2 additions & 2 deletions src/common/Collision/Models/GameObjectModel.cpp
Expand Up @@ -153,7 +153,7 @@ GameObjectModel* GameObjectModel::Create(std::unique_ptr<GameObjectModelOwnerBas
return mdl;
}

bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const
bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask, VMAP::ModelIgnoreFlags ignoreFlags) const
{
if (!(phasemask & ph_mask) || !owner->IsSpawned())
return false;
Expand All @@ -166,7 +166,7 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto
Vector3 p = iInvRot * (ray.origin() - iPos) * iInvScale;
Ray modRay(p, iInvRot * ray.direction());
float distance = MaxDist * iInvScale;
bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit);
bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit, ignoreFlags);
if (hit)
{
distance *= iScale;
Expand Down
3 changes: 2 additions & 1 deletion src/common/Collision/Models/GameObjectModel.h
Expand Up @@ -30,6 +30,7 @@
namespace VMAP
{
class WorldModel;
enum class ModelIgnoreFlags : uint32;
}

class GameObject;
Expand Down Expand Up @@ -65,7 +66,7 @@ class TC_COMMON_API GameObjectModel /*, public Intersectable*/

bool isEnabled() const {return phasemask != 0;}

bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const;
bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask, VMAP::ModelIgnoreFlags ignoreFlags) const;

static GameObjectModel* Create(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath);

Expand Down
34 changes: 34 additions & 0 deletions src/common/Collision/Models/ModelIgnoreFlags.h
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef ModelIgnoreFlags_h__
#define ModelIgnoreFlags_h__

#include "Define.h"

namespace VMAP
{
enum class ModelIgnoreFlags : uint32
{
Nothing = 0x00,
M2 = 0x01
};

inline ModelIgnoreFlags operator&(ModelIgnoreFlags left, ModelIgnoreFlags right) { return ModelIgnoreFlags(uint32(left) & uint32(right)); }
}

#endif // ModelIgnoreFlags_h__
4 changes: 2 additions & 2 deletions src/common/Collision/Models/ModelInstance.cpp
Expand Up @@ -31,7 +31,7 @@ namespace VMAP
iInvScale = 1.f/iScale;
}

bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const
bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
{
if (!iModel)
{
Expand All @@ -55,7 +55,7 @@ namespace VMAP
Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale;
Ray modRay(p, iInvRot * pRay.direction());
float distance = pMaxDist * iInvScale;
bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit);
bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit, ignoreFlags);
if (hit)
{
distance *= iScale;
Expand Down
3 changes: 2 additions & 1 deletion src/common/Collision/Models/ModelInstance.h
Expand Up @@ -31,6 +31,7 @@ namespace VMAP
class WorldModel;
struct AreaInfo;
struct LocationInfo;
enum class ModelIgnoreFlags : uint32;

enum ModelFlags
{
Expand Down Expand Up @@ -66,7 +67,7 @@ namespace VMAP
ModelInstance(): iInvScale(0.0f), iModel(nullptr) { }
ModelInstance(const ModelSpawn &spawn, WorldModel* model);
void setUnloaded() { iModel = nullptr; }
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const;
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
void intersectPoint(const G3D::Vector3& p, AreaInfo &info) const;
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const;
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const;
Expand Down
11 changes: 10 additions & 1 deletion src/common/Collision/Models/WorldModel.cpp
Expand Up @@ -19,6 +19,7 @@
#include "WorldModel.h"
#include "VMapDefinitions.h"
#include "MapTree.h"
#include "ModelIgnoreFlags.h"

using G3D::Vector3;
using G3D::Ray;
Expand Down Expand Up @@ -444,8 +445,16 @@ namespace VMAP
bool hit;
};

bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const
bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
{
// If the caller asked us to ignore certain objects we should check flags
if ((ignoreFlags & ModelIgnoreFlags::M2) != ModelIgnoreFlags::Nothing)
{
// M2 models are not taken into account for LoS calculation if caller requested their ignoring.
if (Flags & MOD_M2)

This comment has been minimized.

Copy link
@Undergarun

Undergarun Jan 21, 2017

Not defined.

This comment has been minimized.

Copy link
@Shauren

Shauren Jan 21, 2017

Member

Defined, in ModelInstance.h

return false;
}

// small M2 workaround, maybe better make separate class with virtual intersection funcs
// in any case, there's no need to use a bound tree if we only have one submodel
if (groupModels.size() == 1)
Expand Down
4 changes: 3 additions & 1 deletion src/common/Collision/Models/WorldModel.h
Expand Up @@ -32,6 +32,7 @@ namespace VMAP
class TreeNode;
struct AreaInfo;
struct LocationInfo;
enum class ModelIgnoreFlags : uint32;

class TC_COMMON_API MeshTriangle
{
Expand Down Expand Up @@ -111,12 +112,13 @@ namespace VMAP
//! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry!
void setGroupModels(std::vector<GroupModel> &models);
void setRootWmoID(uint32 id) { RootWMOID = id; }
bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const;
bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
bool IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const;
bool GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const;
bool writeFile(const std::string &filename);
bool readFile(const std::string &filename);
void getGroupModels(std::vector<GroupModel>& outGroupModels);
uint32 Flags;
protected:
uint32 RootWMOID;
std::vector<GroupModel> groupModels;
Expand Down

0 comments on commit 01d715e

Please sign in to comment.