Core/Vmaps: Stop M2s from occluding for spellcast LoS

Closes #18528

(cherry-picked from 01d715eaef)
This commit is contained in:
HelloKitty
2017-01-21 14:44:31 +01:00
committed by Shauren
parent da3783876b
commit 46c69df3a7
20 changed files with 104 additions and 44 deletions

View File

@@ -21,6 +21,7 @@
#include "GameObjectModel.h"
#include "Log.h"
#include "MapTree.h"
#include "ModelIgnoreFlags.h"
#include "ModelInstance.h"
#include "RegularGrid.h"
#include "Timer.h"
@@ -142,7 +143,7 @@ struct DynamicTreeIntersectionCallback
bool operator()(G3D::Ray const& r, GameObjectModel const& obj, float& distance)
{
_didHit = obj.intersectRay(r, distance, true, _phaseShift);
_didHit = obj.intersectRay(r, distance, true, _phaseShift, VMAP::ModelIgnoreFlags::Nothing);
return _didHit;
}

View File

@@ -21,6 +21,7 @@
#include <string>
#include "Define.h"
#include "ModelIgnoreFlags.h"
//===========================================================
@@ -60,7 +61,7 @@ namespace VMAP
virtual void unloadMap(unsigned int pMapId, int x, int y) = 0;
virtual void unloadMap(unsigned int pMapId) = 0;
virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) = 0;
virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags) = 0;
virtual float getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist) = 0;
/**
test if we hit an object. return true if we hit one. rx, ry, rz will hold the hit position or the dest position, if no intersection was found

View File

@@ -191,7 +191,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;
@@ -202,7 +202,7 @@ namespace VMAP
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
if (pos1 != pos2)
return instanceTree->second->isInLineOfSight(pos1, pos2);
return instanceTree->second->isInLineOfSight(pos1, pos2, ignoreFlags);
}
return true;
@@ -306,7 +306,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);
@@ -322,6 +322,9 @@ namespace VMAP
return NULL;
}
TC_LOG_DEBUG("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);
}

View File

@@ -111,7 +111,7 @@ namespace VMAP
void unloadMap(unsigned int mapId) override;
void unloadSingleMap(uint32 mapId);
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
*/
@@ -123,7 +123,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

View File

@@ -33,14 +33,13 @@ using G3D::Vector3;
namespace VMAP
{
class MapRayCallback
{
public:
MapRayCallback(ModelInstance* val): prims(val), hit(false) { }
MapRayCallback(ModelInstance* val, ModelIgnoreFlags ignoreFlags): prims(val), hit(false), flags(ignoreFlags) { }
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true)
{
bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit);
bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit, flags);
if (result)
hit = true;
return result;
@@ -49,6 +48,7 @@ namespace VMAP
protected:
ModelInstance* prims;
bool hit;
ModelIgnoreFlags flags;
};
class AreaInfoCallback
@@ -142,10 +142,10 @@ namespace VMAP
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;
@@ -153,7 +153,7 @@ namespace VMAP
}
//=========================================================
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
@@ -167,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;
@@ -193,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)
@@ -229,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;
}
@@ -371,7 +371,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)
TC_LOG_ERROR("misc", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY);

View File

@@ -28,6 +28,7 @@ namespace VMAP
class ModelInstance;
class GroupModel;
class VMapManager2;
enum class ModelIgnoreFlags : uint32;
struct TC_COMMON_API LocationInfo
{
@@ -65,7 +66,7 @@ namespace VMAP
private:
static TileFileOpenResult OpenMapTileFile(std::string const& basePath, uint32 mapID, uint32 tileX, uint32 tileY, VMapManager2* vm);
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);
@@ -76,7 +77,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;

View File

@@ -161,7 +161,7 @@ GameObjectModel* GameObjectModel::Create(std::unique_ptr<GameObjectModelOwnerBas
return mdl;
}
bool GameObjectModel::intersectRay(G3D::Ray const& ray, float& maxDist, bool stopAtFirstHit, PhaseShift const& phaseShift) const
bool GameObjectModel::intersectRay(G3D::Ray const& ray, float& maxDist, bool stopAtFirstHit, PhaseShift const& phaseShift, VMAP::ModelIgnoreFlags ignoreFlags) const
{
if (!isCollisionEnabled() || !owner->IsSpawned())
return false;
@@ -177,7 +177,7 @@ bool GameObjectModel::intersectRay(G3D::Ray const& 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;

View File

@@ -31,6 +31,7 @@ namespace VMAP
{
class WorldModel;
struct AreaInfo;
enum class ModelIgnoreFlags : uint32;
}
class GameObject;
@@ -69,7 +70,7 @@ public:
bool isCollisionEnabled() const { return _collisionEnabled; }
bool isMapObject() const { return isWmo; }
bool intersectRay(G3D::Ray const& ray, float& maxDist, bool stopAtFirstHit, PhaseShift const& phaseShift) const;
bool intersectRay(G3D::Ray const& ray, float& maxDist, bool stopAtFirstHit, PhaseShift const& phaseShift, VMAP::ModelIgnoreFlags ignoreFlags) const;
void intersectPoint(G3D::Vector3 const& point, VMAP::AreaInfo& info, PhaseShift const& phaseShift) const;
static GameObjectModel* Create(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath);

View File

@@ -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__

View File

@@ -31,7 +31,7 @@ namespace VMAP
iInvScale = 1.f/iScale;
}
bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const
bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
{
if (!iModel)
{
@@ -55,7 +55,7 @@ namespace VMAP
Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale;
Ray modRay(p, iInvRot * pRay.direction());
float distance = pMaxDist * iInvScale;
bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit);
bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit, ignoreFlags);
if (hit)
{
distance *= iScale;

View File

@@ -31,6 +31,7 @@ namespace VMAP
class WorldModel;
struct AreaInfo;
struct LocationInfo;
enum class ModelIgnoreFlags : uint32;
enum ModelFlags
{
@@ -66,7 +67,7 @@ namespace VMAP
ModelInstance(): iInvScale(0.0f), iModel(nullptr) { }
ModelInstance(const ModelSpawn &spawn, WorldModel* model);
void setUnloaded() { iModel = nullptr; }
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const;
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
void intersectPoint(const G3D::Vector3& p, AreaInfo &info) const;
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const;
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const;

View File

@@ -19,6 +19,7 @@
#include "WorldModel.h"
#include "VMapDefinitions.h"
#include "MapTree.h"
#include "ModelIgnoreFlags.h"
using G3D::Vector3;
using G3D::Ray;
@@ -472,8 +473,16 @@ namespace VMAP
bool hit;
};
bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const
bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
{
// If the caller asked us to ignore certain objects we should check flags
if ((ignoreFlags & ModelIgnoreFlags::M2) != ModelIgnoreFlags::Nothing)
{
// M2 models are not taken into account for LoS calculation if caller requested their ignoring.
if (Flags & MOD_M2)
return false;
}
// small M2 workaround, maybe better make separate class with virtual intersection funcs
// in any case, there's no need to use a bound tree if we only have one submodel
if (groupModels.size() == 1)

View File

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

View File

@@ -1671,7 +1671,7 @@ bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool
return distsq < maxdist * maxdist;
}
bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const
bool WorldObject::IsWithinLOSInMap(const WorldObject* obj, VMAP::ModelIgnoreFlags ignoreFlags) const
{
if (!IsInMap(obj))
return false;
@@ -1682,7 +1682,7 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const
else
obj->GetHitSpherePointFor(GetPosition(), x, y, z);
return IsWithinLOS(x, y, z);
return IsWithinLOS(x, y, z, ignoreFlags);
}
float WorldObject::GetDistance(const WorldObject* obj) const
@@ -1759,7 +1759,7 @@ bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare,
return obj && IsInMap(obj) && IsInPhase(obj) && _IsWithinDist(obj, dist2compare, is3D);
}
bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const
bool WorldObject::IsWithinLOS(float ox, float oy, float oz, VMAP::ModelIgnoreFlags ignoreFlags) const
{
/*float x, y, z;
GetPosition(x, y, z);
@@ -1773,7 +1773,7 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const
else
GetHitSpherePointFor({ ox, oy, oz }, x, y, z);
return GetMap()->isInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f);
return GetMap()->isInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f, ignoreFlags);
}
return true;

View File

@@ -22,6 +22,7 @@
#include "Common.h"
#include "GridReference.h"
#include "GridRefManager.h"
#include "ModelIgnoreFlags.h"
#include "MovementInfo.h"
#include "ObjectDefines.h"
#include "ObjectGuid.h"
@@ -449,8 +450,8 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
// use only if you will sure about placing both object at same map
bool IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D = true) const;
bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true) const;
bool IsWithinLOS(float x, float y, float z) const;
bool IsWithinLOSInMap(WorldObject const* obj) const;
bool IsWithinLOS(float x, float y, float z, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const;
bool IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const;
Position GetHitSpherePointFor(Position const& dest) const;
void GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const;
bool GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D = true) const;

View File

@@ -2878,9 +2878,9 @@ float Map::GetWaterLevel(PhaseShift const& phaseShift, float x, float y) const
return 0;
}
bool Map::isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2) const
bool Map::isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, VMAP::ModelIgnoreFlags ignoreFlags) const
{
return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(PhasingHandler::GetTerrainMapId(phaseShift, this, x1, y1), x1, y1, z1, x2, y2, z2)
return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(PhasingHandler::GetTerrainMapId(phaseShift, this, x1, y1), x1, y1, z1, x2, y2, z2, ignoreFlags)
&& _dynamicTree.isInLineOfSight({ x1, y1, z1 }, { x2, y2, z2 }, phaseShift);
}

View File

@@ -67,6 +67,7 @@ enum WeatherState : uint32;
namespace Trinity { struct ObjectUpdater; }
namespace G3D { class Plane; }
namespace VMAP { enum class ModelIgnoreFlags : uint32; }
struct ScriptAction
{
@@ -493,7 +494,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
float GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground = nullptr, bool swim = false) const;
float GetHeight(PhaseShift const& phaseShift, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const;
bool isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2) const;
bool isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, VMAP::ModelIgnoreFlags ignoreFlags) const;
void Balance() { _dynamicTree.balance(); }
void RemoveGameObjectModel(const GameObjectModel& model) { _dynamicTree.remove(model); }
void InsertGameObjectModel(const GameObjectModel& model) { _dynamicTree.insert(model); }

View File

@@ -54,7 +54,7 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner)
Position mypos = owner->GetPosition();
bool isInLOS = VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(
PhasingHandler::GetTerrainMapId(owner->GetPhaseShift(), owner->GetMap(), mypos.m_positionX, mypos.m_positionY),
mypos.m_positionX, mypos.m_positionY, mypos.m_positionZ + 2.0f, x, y, z + 2.0f);
mypos.m_positionX, mypos.m_positionY, mypos.m_positionZ + 2.0f, x, y, z + 2.0f, VMAP::ModelIgnoreFlags::Nothing);
if (!isInLOS)
{
i_nextCheckTime.Reset(200);

View File

@@ -1958,7 +1958,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
if (Unit* unit = (*itr)->ToUnit())
{
uint32 deficit = unit->GetMaxHealth() - unit->GetHealth();
if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit))
if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::M2))
{
foundItr = itr;
maxHPDeficit = deficit;
@@ -1973,10 +1973,10 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
{
if (foundItr == tempTargets.end())
{
if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr))
if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
foundItr = itr;
}
else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr))
else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
foundItr = itr;
}
}
@@ -5071,7 +5071,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
if (DynamicObject* dynObj = m_caster->GetDynObject(m_triggeredByAuraSpell->Id))
losTarget = dynObj;
if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !target->IsWithinLOSInMap(losTarget))
if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !target->IsWithinLOSInMap(losTarget, VMAP::ModelIgnoreFlags::M2))
return SPELL_FAILED_LINE_OF_SIGHT;
}
}
@@ -5083,7 +5083,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
float x, y, z;
m_targets.GetDstPos()->GetPosition(x, y, z);
if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOS(x, y, z))
if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOS(x, y, z, VMAP::ModelIgnoreFlags::M2))
return SPELL_FAILED_LINE_OF_SIGHT;
}
@@ -5366,6 +5366,10 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
if (!target)
return SPELL_FAILED_DONT_REPORT;
// first we must check to see if the target is in LoS. A path can usually be built but LoS matters for charge spells
if (!target->IsWithinLOSInMap(m_caster)) //Do full LoS/Path check. Don't exclude m2
return SPELL_FAILED_LINE_OF_SIGHT;
float objSize = target->GetObjectSize();
float range = m_spellInfo->GetMaxRange(true, m_caster, this) * 1.5f + objSize; // can't be overly strict
@@ -6916,7 +6920,7 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect,
/// @todo shit below shouldn't be here, but it's temporary
//Check targets for LOS visibility
if (losPosition)
return target->IsWithinLOS(losPosition->GetPositionX(), losPosition->GetPositionY(), losPosition->GetPositionZ());
return target->IsWithinLOS(losPosition->GetPositionX(), losPosition->GetPositionY(), losPosition->GetPositionZ(), VMAP::ModelIgnoreFlags::M2);
else
{
// Get GO cast coordinates if original caster -> GO
@@ -6925,7 +6929,7 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect,
caster = m_caster->GetMap()->GetGameObject(m_originalCasterGUID);
if (!caster)
caster = m_caster;
if (target != m_caster && !target->IsWithinLOSInMap(caster))
if (target != m_caster && !target->IsWithinLOSInMap(caster, VMAP::ModelIgnoreFlags::M2))
return false;
}

View File

@@ -20,6 +20,7 @@
#include "MotionMaster.h"
#include "ruby_sanctum.h"
#include "ScriptedCreature.h"
#include "SpellMgr.h"
#include "SpellScript.h"
enum Texts