[10272] Add option for search distance to getHeight() functions and make Creature::FallGround() use VMaps properly.

This finally prevents flying creatures from falling to infinity (basically instantly diappearing) in several instances,
aswell as prevent creatures from falling inside larger solid object around the world.

Default height search is untouched, needs more research on how creature AI etc. will be affected.
This commit is contained in:
Lynx3d 2010-07-26 08:08:36 +02:00
parent 747d1ebdcf
commit 730b4deaaf
10 changed files with 18 additions and 26 deletions

View file

@ -1375,8 +1375,8 @@ bool Creature::FallGround()
if (getDeathState() == DEAD_FALLING) if (getDeathState() == DEAD_FALLING)
return false; return false;
// Let's do with no vmap because no way to get far distance with vmap high call // use larger distance for vmap height search than in most other cases
float tz = GetMap()->GetHeight(GetPositionX(), GetPositionY(), GetPositionZ(), false); float tz = GetMap()->GetHeight(GetPositionX(), GetPositionY(), GetPositionZ(), true, MAX_FALL_DISTANCE);
// Abort too if the ground is very near // Abort too if the ground is very near
if (fabs(GetPositionZ() - tz) < 0.1f) if (fabs(GetPositionZ() - tz) < 0.1f)
@ -1815,7 +1815,7 @@ bool Creature::LoadCreaturesAddon(bool reload)
} }
SpellAuraHolder *holder = GetSpellAuraHolder(cAura->spell_id, GetGUID()); SpellAuraHolder *holder = GetSpellAuraHolder(cAura->spell_id, GetGUID());
bool addedToExisting = true; bool addedToExisting = true;
if (!holder) if (!holder)
{ {
@ -1834,7 +1834,7 @@ bool Creature::LoadCreaturesAddon(bool reload)
} }
else else
AddSpellAuraHolder(holder); AddSpellAuraHolder(holder);
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell: %u - Aura %u added to creature (GUIDLow: %u Entry: %u )", cAura->spell_id, AdditionalSpellInfo->EffectApplyAuraName[EFFECT_INDEX_0],GetGUIDLow(),GetEntry()); DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell: %u - Aura %u added to creature (GUIDLow: %u Entry: %u )", cAura->spell_id, AdditionalSpellInfo->EffectApplyAuraName[EFFECT_INDEX_0],GetGUIDLow(),GetEntry());
} }
} }
@ -2213,4 +2213,4 @@ void Creature::RelocationNotify()
MaNGOS::CreatureRelocationNotifier relocationNotifier(*this); MaNGOS::CreatureRelocationNotifier relocationNotifier(*this);
float radius = MAX_CREATURE_ATTACK_RADIUS * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO); float radius = MAX_CREATURE_ATTACK_RADIUS * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO);
Cell::VisitAllObjects(this, relocationNotifier, radius); Cell::VisitAllObjects(this, relocationNotifier, radius);
} }

View file

@ -1012,7 +1012,7 @@ inline GridMap *Map::GetGrid(float x, float y)
return GridMaps[gx][gy]; return GridMaps[gx][gy];
} }
float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const float Map::GetHeight(float x, float y, float z, bool pUseVmaps, float maxSearchDist) const
{ {
// find raw .map surface under Z coordinates // find raw .map surface under Z coordinates
float mapHeight; float mapHeight;
@ -1036,7 +1036,7 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
if(vmgr->isHeightCalcEnabled()) if(vmgr->isHeightCalcEnabled())
{ {
// look from a bit higher pos to find the floor // look from a bit higher pos to find the floor
vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f); vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f, maxSearchDist);
} }
else else
vmapHeight = VMAP_INVALID_HEIGHT_VALUE; vmapHeight = VMAP_INVALID_HEIGHT_VALUE;

View file

@ -79,6 +79,8 @@ enum LevelRequirementVsMode
#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface #define MAX_HEIGHT 100000.0f // can be use for find ground height at surface
#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE #define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE
#define MAX_FALL_DISTANCE 250000.0f // "unlimited fall" to find VMap ground if it is available, just larger than MAX_HEIGHT - INVALID_HEIGHT
#define DEFAULT_HEIGHT_SEARCH 10.0f // default search distance to find height at nearby locations
#define MIN_UNLOAD_DELAY 1 // immediate unload #define MIN_UNLOAD_DELAY 1 // immediate unload
class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::ObjectLevelLockable<Map, ACE_Thread_Mutex> class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::ObjectLevelLockable<Map, ACE_Thread_Mutex>
@ -150,7 +152,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
// some calls like isInWater should not use vmaps due to processor power // some calls like isInWater should not use vmaps due to processor power
// can return INVALID_HEIGHT if under z+2 z coord not found height // can return INVALID_HEIGHT if under z+2 z coord not found height
float GetHeight(float x, float y, float z, bool pCheckVMap=true) const; float GetHeight(float x, float y, float z, bool pCheckVMap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH) const;
bool IsInWater(float x, float y, float z, GridMapLiquidData *data = 0) const; bool IsInWater(float x, float y, float z, GridMapLiquidData *data = 0) const;
GridMapLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, GridMapLiquidData *data = 0) const; GridMapLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, GridMapLiquidData *data = 0) const;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "10271" #define REVISION_NR "10272"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__

View file

@ -61,7 +61,7 @@ namespace VMAP
virtual void unloadMap(unsigned int pMapId) = 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) = 0;
virtual float getHeight(unsigned int pMapId, float x, float y, float z) = 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 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
return a position, that is pReduceDist closer to the origin return a position, that is pReduceDist closer to the origin

View file

@ -217,12 +217,12 @@ namespace VMAP
//========================================================= //=========================================================
float StaticMapTree::getHeight(const Vector3& pPos) const float StaticMapTree::getHeight(const Vector3& pPos, float maxSearchDist) const
{ {
float height = G3D::inf(); float height = G3D::inf();
Vector3 dir = Vector3(0,0,-1); Vector3 dir = Vector3(0,0,-1);
G3D::Ray ray(pPos, dir); // direction with length of 1 G3D::Ray ray(pPos, dir); // direction with length of 1
float maxDist = VMapDefinitions::getMaxCanFallDistance(); float maxDist = maxSearchDist;
if (getIntersectionTime(ray, maxDist, false)) if (getIntersectionTime(ray, maxDist, false))
{ {
height = pPos.z - maxDist; height = pPos.z - maxDist;

View file

@ -70,7 +70,7 @@ namespace VMAP
bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) const; bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) 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;
float getHeight(const G3D::Vector3& pPos) const; float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const;
bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const; bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const;
bool GetLocationInfo(const Vector3 &pos, LocationInfo &info) const; bool GetLocationInfo(const Vector3 &pos, LocationInfo &info) const;

View file

@ -24,18 +24,8 @@
namespace VMAP namespace VMAP
{ {
//=====================================
#define MAX_CAN_FALL_DISTANCE 10.0f
const char VMAP_MAGIC[] = "VMAP_3.0"; const char VMAP_MAGIC[] = "VMAP_3.0";
class VMapDefinitions
{
public:
static float getMaxCanFallDistance() { return MAX_CAN_FALL_DISTANCE; }
};
//======================================
// defined in TileAssembler.cpp currently... // defined in TileAssembler.cpp currently...
bool readChunk(FILE *rf, char *dest, const char *compare, uint32 len); bool readChunk(FILE *rf, char *dest, const char *compare, uint32 len);
} }

View file

@ -234,7 +234,7 @@ namespace VMAP
get height or INVALID_HEIGHT if no height available get height or INVALID_HEIGHT if no height available
*/ */
float VMapManager2::getHeight(unsigned int pMapId, float x, float y, float z) float VMapManager2::getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist)
{ {
float height = VMAP_INVALID_HEIGHT_VALUE; //no height float height = VMAP_INVALID_HEIGHT_VALUE; //no height
if (isHeightCalcEnabled()) if (isHeightCalcEnabled())
@ -243,7 +243,7 @@ namespace VMAP
if (instanceTree != iInstanceMapTrees.end()) if (instanceTree != iInstanceMapTrees.end())
{ {
Vector3 pos = convertPositionToInternalRep(x,y,z); Vector3 pos = convertPositionToInternalRep(x,y,z);
height = instanceTree->second->getHeight(pos); height = instanceTree->second->getHeight(pos, maxSearchDist);
if (!(height < G3D::inf())) if (!(height < G3D::inf()))
{ {
height = VMAP_INVALID_HEIGHT_VALUE; //no height height = VMAP_INVALID_HEIGHT_VALUE; //no height

View file

@ -92,7 +92,7 @@ namespace VMAP
fill the hit pos and return true, if an object was hit fill the hit pos and return true, if an object was hit
*/ */
bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist); bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist);
float getHeight(unsigned int pMapId, float x, float y, float z); float getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist);
bool processCommand(char *pCommand) { return false; } // for debug and extensions bool processCommand(char *pCommand) { return false; } // for debug and extensions