[8524] New cell search algorithm implemented. You can now choose different visibility distances on continents, in BG/Arenas and instances.

Please, update your config files and check new options:

Visibility.Distance.Continents    = 90
Visibility.Distance.Instances     = 120
Visibility.Distance.BGArenas      = 180

Thanks everyone involved in patch tests!

Signed-off-by: Ambal <pogrebniak@gala.net>
This commit is contained in:
Ambal 2009-09-21 23:25:18 +03:00
parent 81456dc416
commit cfea99ea62
28 changed files with 434 additions and 123 deletions

View file

@ -79,8 +79,19 @@ class MANGOS_DLL_DECL NGrid
i_GridInfo = GridInfo(expiry, unload);
}
const GridType& operator()(unsigned short x, unsigned short y) const { return i_cells[x][y]; }
GridType& operator()(unsigned short x, unsigned short y) { return i_cells[x][y]; }
const GridType& operator()(unsigned short x, unsigned short y) const
{
ASSERT(x < N);
ASSERT(y < N);
return i_cells[x][y];
}
GridType& operator()(unsigned short x, unsigned short y)
{
ASSERT(x < N);
ASSERT(y < N);
return i_cells[x][y];
}
const uint32& GetGridId(void) const { return i_gridId; }
void SetGridId(const uint32 id) const { i_gridId = id; }
@ -108,12 +119,12 @@ class MANGOS_DLL_DECL NGrid
template<class SPECIFIC_OBJECT> void AddWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl)
{
i_cells[x][y].AddWorldObject(obj, hdl);
getGridType(x, y).AddWorldObject(obj, hdl);
}
template<class SPECIFIC_OBJECT> void RemoveWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl)
{
i_cells[x][y].RemoveWorldObject(obj, hdl);
getGridType(x, y).RemoveWorldObject(obj, hdl);
}
template<class T, class TT> void Visit(TypeContainerVisitor<T, TypeMapContainer<TT> > &visitor)
@ -125,7 +136,7 @@ class MANGOS_DLL_DECL NGrid
template<class T, class TT> void Visit(const uint32 &x, const uint32 &y, TypeContainerVisitor<T, TypeMapContainer<TT> > &visitor)
{
i_cells[x][y].Visit(visitor);
getGridType(x, y).Visit(visitor);
}
unsigned int ActiveObjectsInGrid(void) const
@ -139,26 +150,33 @@ class MANGOS_DLL_DECL NGrid
template<class SPECIFIC_OBJECT> const SPECIFIC_OBJECT* GetGridObject(const uint32 x, const uint32 y, OBJECT_HANDLE hdl) const
{
return i_cells[x][y].template GetGridObject<SPECIFIC_OBJECT>(hdl);
return getGridType(x, y).template GetGridObject<SPECIFIC_OBJECT>(hdl);
}
template<class SPECIFIC_OBJECT> SPECIFIC_OBJECT* GetGridObject(const uint32 x, const uint32 y, OBJECT_HANDLE hdl)
{
return i_cells[x][y].template GetGridObject<SPECIFIC_OBJECT>(hdl);
return getGridType(x, y).template GetGridObject<SPECIFIC_OBJECT>(hdl);
}
template<class SPECIFIC_OBJECT> bool AddGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl)
{
return i_cells[x][y].AddGridObject(hdl, obj);
return getGridType(x, y).AddGridObject(hdl, obj);
}
template<class SPECIFIC_OBJECT> bool RemoveGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl)
{
return i_cells[x][y].RemoveGridObject(obj, hdl);
return getGridType(x, y).RemoveGridObject(obj, hdl);
}
private:
GridType& getGridType(const uint32& x, const uint32& y)
{
ASSERT(x < N);
ASSERT(y < N);
return i_cells[x][y];
}
uint32 i_gridId;
GridInfo i_GridInfo;
GridReference<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES, ThreadModel> > i_Reference;

View file

@ -605,7 +605,7 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement)
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::AchievementChatBuilder> > say_worker(GetPlayer(),sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY),say_do);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::AchievementChatBuilder> >, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetPlayer()->GetMap());
cell_lock->Visit(cell_lock, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY));
}
WorldPacket data(SMSG_ACHIEVEMENT_EARNED, 8+4+8);

View file

@ -25,6 +25,7 @@
#include <cmath>
class Map;
class WorldObject;
enum District
{
@ -42,6 +43,26 @@ enum District
template<class T> struct CellLock;
struct MANGOS_DLL_DECL CellArea
{
CellArea() : right_offset(0), left_offset(0), upper_offset(0), lower_offset(0) {}
CellArea(int right, int left, int upper, int lower) : right_offset(right), left_offset(left), upper_offset(upper), lower_offset(lower) {}
bool operator!() const { return !right_offset && !left_offset && !upper_offset && !lower_offset; }
void ResizeBorders(CellPair& begin_cell, CellPair& end_cell) const
{
begin_cell << left_offset;
begin_cell -= lower_offset;
end_cell >> right_offset;
end_cell += upper_offset;
}
int right_offset;
int left_offset;
int upper_offset;
int lower_offset;
};
struct MANGOS_DLL_DECL Cell
{
Cell() { data.All = 0; }
@ -131,15 +152,21 @@ struct MANGOS_DLL_DECL Cell
{
unsigned grid_x : 6;
unsigned grid_y : 6;
unsigned cell_x : 4;
unsigned cell_y : 4;
unsigned cell_x : 6;
unsigned cell_y : 6;
unsigned nocreate : 1;
unsigned reserved : 11;
unsigned reserved : 7;
} Part;
uint32 All;
} data;
template<class LOCK_TYPE, class T, class CONTAINER> void Visit(const CellLock<LOCK_TYPE> &, TypeContainerVisitor<T, CONTAINER> &visitor, Map &) const;
template<class LOCK_TYPE, class T, class CONTAINER> void Visit(const CellLock<LOCK_TYPE> &, TypeContainerVisitor<T, CONTAINER> &visitor, Map &m, const WorldObject &obj, float radius) const;
static CellArea CalculateCellArea(const WorldObject &obj, float radius);
private:
template<class LOCK_TYPE, class T, class CONTAINER> void VisitCircle(const CellLock<LOCK_TYPE> &, TypeContainerVisitor<T, CONTAINER> &, Map &, const CellPair& , const CellPair& ) const;
};
template<class T>

View file

@ -127,4 +127,160 @@ Cell::Visit(const CellLock<LOCK_TYPE> &l, TypeContainerVisitor<T, CONTAINER> &vi
}
}
}
inline int CellHelper(const float radius)
{
if(radius < 1.0f)
return 0;
return (int)ceilf(radius/SIZE_OF_GRID_CELL);
}
inline CellArea Cell::CalculateCellArea(const WorldObject &obj, float radius)
{
if(radius <= 0.0f)
return CellArea();
//we should increase search radius by object's radius, otherwise
//we could have problems with huge creatures, which won't attack nearest players etc
radius += obj.GetObjectSize();
//lets calculate object coord offsets from cell borders.
//TODO: add more correct/generic method for this task
const float x_offset = (obj.GetPositionX() - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL;
const float y_offset = (obj.GetPositionY() - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL;
const float x_val = floor(x_offset + CENTER_GRID_CELL_ID + 0.5f);
const float y_val = floor(y_offset + CENTER_GRID_CELL_ID + 0.5f);
const float x_off = (x_offset - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL;
const float y_off = (y_offset - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL;
const float tmp_diff = radius - CENTER_GRID_CELL_OFFSET;
//lets calculate upper/lower/right/left corners for cell search
int right = CellHelper(tmp_diff + x_off);
int left = CellHelper(tmp_diff - x_off);
int upper = CellHelper(tmp_diff + y_off);
int lower = CellHelper(tmp_diff - y_off);
return CellArea(right, left, upper, lower);
}
template<class LOCK_TYPE, class T, class CONTAINER>
inline void
Cell::Visit(const CellLock<LOCK_TYPE> &l, TypeContainerVisitor<T, CONTAINER> &visitor, Map &m, const WorldObject &obj, float radius) const
{
const CellPair &standing_cell = l.i_cellPair;
if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
return;
//no jokes here... Actually placing ASSERT() here was good idea, but
//we had some problems with DynamicObjects, which pass radius = 0.0f (DB issue?)
//maybe it is better to just return when radius <= 0.0f?
if(radius <= 0.0f)
{
m.Visit(l, visitor);
return;
}
//lets calculate object coord offsets from cell borders.
CellArea area = Cell::CalculateCellArea(obj, radius);
//if radius fits inside standing cell
if(!area)
{
m.Visit(l, visitor);
return;
}
CellPair begin_cell = standing_cell;
CellPair end_cell = standing_cell;
area.ResizeBorders(begin_cell, end_cell);
//visit all cells, found in CalculateCellArea()
//if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle
//currently this technique works with MAX_NUMBER_OF_CELLS 16 and higher, with lower values
//there are nothing to optimize because SIZE_OF_GRID_CELL is too big...
if(((end_cell.x_coord - begin_cell.x_coord) > 4) && ((end_cell.y_coord - begin_cell.y_coord) > 4))
{
VisitCircle(l, visitor, m, begin_cell, end_cell);
return;
}
//ALWAYS visit standing cell first!!! Since we deal with small radiuses
//it is very essential to call visitor for standing cell firstly...
m.Visit(l, visitor);
// loop the cell range
for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++)
{
for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++)
{
CellPair cell_pair(x,y);
//lets skip standing cell since we already visited it
if(cell_pair != standing_cell)
{
Cell r_zone(cell_pair);
r_zone.data.Part.nocreate = l->data.Part.nocreate;
CellLock<LOCK_TYPE> lock(r_zone, cell_pair);
m.Visit(lock, visitor);
}
}
}
}
template<class LOCK_TYPE, class T, class CONTAINER>
inline void
Cell::VisitCircle(const CellLock<LOCK_TYPE> &l, TypeContainerVisitor<T, CONTAINER> &visitor, Map &m, const CellPair& begin_cell, const CellPair& end_cell) const
{
//here is an algorithm for 'filling' circum-squared octagon
uint32 x_shift = (uint32)ceilf((end_cell.x_coord - begin_cell.x_coord) * 0.3f - 0.5f);
//lets calculate x_start/x_end coords for central strip...
const uint32 x_start = begin_cell.x_coord + x_shift;
const uint32 x_end = end_cell.x_coord - x_shift;
//visit central strip with constant width...
for(uint32 x = x_start; x <= x_end; ++x)
{
for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y)
{
CellPair cell_pair(x,y);
Cell r_zone(cell_pair);
r_zone.data.Part.nocreate = l->data.Part.nocreate;
CellLock<LOCK_TYPE> lock(r_zone, cell_pair);
m.Visit(lock, visitor);
}
}
//if x_shift == 0 then we have too small cell area, which were already
//visited at previous step, so just return from procedure...
if(x_shift == 0)
return;
uint32 y_start = end_cell.y_coord;
uint32 y_end = begin_cell.y_coord;
//now we are visiting borders of an octagon...
for (uint32 step = 1; step <= (x_start - begin_cell.x_coord); ++step)
{
//each step reduces strip height by 2 cells...
y_end += 1;
y_start -= 1;
for (uint32 y = y_start; y >= y_end; --y)
{
//we visit cells symmetrically from both sides, heading from center to sides and from up to bottom
//e.g. filling 2 trapezoids after filling central cell strip...
CellPair cell_pair_left(x_start - step, y);
Cell r_zone_left(cell_pair_left);
r_zone_left.data.Part.nocreate = l->data.Part.nocreate;
CellLock<LOCK_TYPE> lock_left(r_zone_left, cell_pair_left);
m.Visit(lock_left, visitor);
//right trapezoid cell visit
CellPair cell_pair_right(x_end + step, y);
Cell r_zone_right(cell_pair_right);
r_zone_right.data.Part.nocreate = l->data.Part.nocreate;
CellLock<LOCK_TYPE> lock_right(r_zone_right, cell_pair_right);
m.Visit(lock_right, visitor);
}
}
}
#endif

View file

@ -584,7 +584,7 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > > emote_worker(GetPlayer(),sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),emote_do);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > >, WorldTypeMapContainer > message(emote_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetPlayer()->GetMap());
cell_lock->Visit(cell_lock, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE));
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);

View file

@ -534,7 +534,7 @@ void Creature::DoFleeToGetAssistance()
TypeContainerVisitor<MaNGOS::CreatureLastSearcher<MaNGOS::NearestAssistCreatureInCreatureRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *GetMap(), *this, radius);
SetNoSearchAssistance(true);
if(!pCreature)
@ -1776,7 +1776,7 @@ void Creature::CallAssistance()
TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::AnyAssistCreatureInRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *GetMap(), *this, radius);
}
if (!assistList.empty())
@ -1810,7 +1810,7 @@ void Creature::CallForHelp(float fRadius)
TypeContainerVisitor<MaNGOS::CreatureWorker<MaNGOS::CallOfHelpCreatureInRangeDo>, GridTypeMapContainer > grid_creature_searcher(worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *GetMap(), *this, fRadius);
}
bool Creature::CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction /*= true*/) const

View file

@ -1214,7 +1214,7 @@ Unit* CreatureEventAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff)
TypeContainerVisitor<MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRange>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_creature->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_creature->GetMap(), *m_creature, range);
return pUnit;
}
@ -1231,7 +1231,7 @@ void CreatureEventAI::DoFindFriendlyCC(std::list<Creature*>& _list, float range)
TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRange>, GridTypeMapContainer > grid_creature_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap(), *m_creature, range);
}
void CreatureEventAI::DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid)
@ -1247,7 +1247,7 @@ void CreatureEventAI::DoFindFriendlyMissingBuff(std::list<Creature*>& _list, flo
TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRange>, GridTypeMapContainer > grid_creature_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap(), *m_creature, range);
}
//*********************************

View file

@ -128,8 +128,8 @@ void DynamicObject::Update(uint32 p_time)
TypeContainerVisitor<MaNGOS::DynamicObjectUpdater, GridTypeMapContainer > grid_object_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_object_notifier, *GetMap());
cell_lock->Visit(cell_lock, grid_object_notifier, *GetMap());
cell_lock->Visit(cell_lock, world_object_notifier, *GetMap(), *this, m_radius);
cell_lock->Visit(cell_lock, grid_object_notifier, *GetMap(), *this, m_radius);
}
if(deleteThis)

View file

@ -319,13 +319,13 @@ void GameObject::Update(uint32 /*p_time*/)
CellLock<GridReadGuard> cell_lock(cell, p);
TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
cell_lock->Visit(cell_lock, grid_object_checker, *GetMap());
cell_lock->Visit(cell_lock, grid_object_checker, *GetMap(), *this, radius);
// or unfriendly player/pet
if(!ok)
{
TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
cell_lock->Visit(cell_lock, world_object_checker, *GetMap());
cell_lock->Visit(cell_lock, world_object_checker, *GetMap(), *this, radius);
}
}
else // environmental trap
@ -340,7 +340,7 @@ void GameObject::Update(uint32 /*p_time*/)
CellLock<GridReadGuard> cell_lock(cell, p);
TypeContainerVisitor<MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
cell_lock->Visit(cell_lock, world_object_checker, *GetMap());
cell_lock->Visit(cell_lock, world_object_checker, *GetMap(), *this, radius);
ok = p_ok;
}
@ -784,7 +784,7 @@ void GameObject::TriggeringLinkedGameObject( uint32 trapEntry, Unit* target)
TypeContainerVisitor<MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, object_checker, *GetMap());
cell_lock->Visit(cell_lock, object_checker, *GetMap(), *target, range);
}
// found correct GO
@ -806,7 +806,7 @@ GameObject* GameObject::LookupFishingHoleAround(float range)
CellLock<GridReadGuard> cell_lock(cell, p);
TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::NearestGameObjectFishingHole>, GridTypeMapContainer > grid_object_checker(checker);
cell_lock->Visit(cell_lock, grid_object_checker, *GetMap());
cell_lock->Visit(cell_lock, grid_object_checker, *GetMap(), *this, range);
return ok;
}
@ -1031,7 +1031,8 @@ void GameObject::Use(Unit* user)
//fish catched
player->UpdateFishingSkill();
GameObject* ok = LookupFishingHoleAround(DEFAULT_VISIBILITY_DISTANCE);
//TODO: find reasonable value for fishing hole search
GameObject* ok = LookupFishingHoleAround(20.0f + CONTACT_DISTANCE);
if (ok)
{
player->SendLoot(ok->GetGUID(),LOOT_FISHINGHOLE);

View file

@ -41,7 +41,7 @@ class Player;
#define MIN_GRID_DELAY (MINUTE*IN_MILISECONDS)
#define MIN_MAP_UPDATE_DELAY 50
#define MAX_NUMBER_OF_CELLS 4
#define MAX_NUMBER_OF_CELLS 8
#define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS)
#define CENTER_GRID_CELL_ID (MAX_NUMBER_OF_CELLS*MAX_NUMBER_OF_GRIDS/2)
@ -86,26 +86,34 @@ struct MANGOS_DLL_DECL CoordPair
void operator<<(const uint32 val)
{
if( x_coord >= val )
if( x_coord > val )
x_coord -= val;
else
x_coord = 0;
}
void operator>>(const uint32 val)
{
if( x_coord+val < LIMIT )
x_coord += val;
else
x_coord = LIMIT - 1;
}
void operator-=(const uint32 val)
{
if( y_coord >= val )
if( y_coord > val )
y_coord -= val;
else
y_coord = 0;
}
void operator+=(const uint32 val)
{
if( y_coord+val < LIMIT )
y_coord += val;
else
y_coord = LIMIT - 1;
}
uint32 x_coord;

View file

@ -190,6 +190,7 @@ bool ChatHandler::HandleReloadConfigCommand(const char* /*args*/)
{
sLog.outString( "Re-Loading config settings..." );
sWorld.LoadConfigSettings(true);
MapManager::Instance().InitializeVisibilityDistanceInfo();
SendGlobalSysMessage("World config settings reloaded.");
return true;
}

View file

@ -41,6 +41,7 @@
#define DEFAULT_GRID_EXPIRY 300
#define MAX_GRID_LOAD_TIME 50
#define MAX_CREATURE_ATTACK_RADIUS (45.0f * sWorld.getRate(RATE_CREATURE_AGGRO))
GridState* si_GridStates[MAX_GRID_STATE];
@ -198,7 +199,8 @@ Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _par
: i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode),
i_id(id), i_InstanceId(InstanceId), m_unloadTimer(0),
m_activeNonPlayersIter(m_activeNonPlayers.end()),
i_gridExpiry(expiry), m_parentMap(_parent ? _parent : this)
i_gridExpiry(expiry), m_parentMap(_parent ? _parent : this),
m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE)
{
for(unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
{
@ -209,6 +211,15 @@ Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _par
setNGrid(NULL, idx, j);
}
}
//lets initialize visibility distance for map
Map::InitVisibilityDistance();
}
void Map::InitVisibilityDistance()
{
//init visibility for continents
m_VisibleDistance = sWorld.GetMaxVisibleDistanceOnContinents();
}
// Template specialization of utility methods
@ -346,8 +357,8 @@ Map::EnsureGridCreated(const GridPair &p)
getNGrid(p.x_coord, p.y_coord)->SetGridState(GRID_STATE_IDLE);
//z coord
int gx=63-p.x_coord;
int gy=63-p.y_coord;
int gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord;
int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord;
if(!GridMaps[gx][gy])
LoadMapAndVMap(gx,gy);
@ -491,7 +502,7 @@ void Map::MessageBroadcast(Player *player, WorldPacket *msg, bool to_self)
MaNGOS::MessageDeliverer post_man(*player, msg, to_self);
TypeContainerVisitor<MaNGOS::MessageDeliverer, WorldTypeMapContainer > message(post_man);
CellLock<ReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *this);
cell_lock->Visit(cell_lock, message, *this, *player, GetVisibilityDistance());
}
void Map::MessageBroadcast(WorldObject *obj, WorldPacket *msg)
@ -511,10 +522,12 @@ void Map::MessageBroadcast(WorldObject *obj, WorldPacket *msg)
if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) )
return;
//TODO: currently on continents when Visibility.Distance.InFlight > Visibility.Distance.Continents
//we have alot of blinking mobs because monster move packet send is broken...
MaNGOS::ObjectMessageDeliverer post_man(*obj,msg);
TypeContainerVisitor<MaNGOS::ObjectMessageDeliverer, WorldTypeMapContainer > message(post_man);
CellLock<ReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *this);
cell_lock->Visit(cell_lock, message, *this, *obj, GetVisibilityDistance());
}
void Map::MessageDistBroadcast(Player *player, WorldPacket *msg, float dist, bool to_self, bool own_team_only)
@ -537,7 +550,7 @@ void Map::MessageDistBroadcast(Player *player, WorldPacket *msg, float dist, boo
MaNGOS::MessageDistDeliverer post_man(*player, msg, dist, to_self, own_team_only);
TypeContainerVisitor<MaNGOS::MessageDistDeliverer , WorldTypeMapContainer > message(post_man);
CellLock<ReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *this);
cell_lock->Visit(cell_lock, message, *this, *player, dist);
}
void Map::MessageDistBroadcast(WorldObject *obj, WorldPacket *msg, float dist)
@ -557,10 +570,10 @@ void Map::MessageDistBroadcast(WorldObject *obj, WorldPacket *msg, float dist)
if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) )
return;
MaNGOS::ObjectMessageDistDeliverer post_man(*obj, msg,dist);
MaNGOS::ObjectMessageDistDeliverer post_man(*obj, msg, dist);
TypeContainerVisitor<MaNGOS::ObjectMessageDistDeliverer, WorldTypeMapContainer > message(post_man);
CellLock<ReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *this);
cell_lock->Visit(cell_lock, message, *this, *obj, dist);
}
bool Map::loaded(const GridPair &p) const
@ -605,8 +618,9 @@ void Map::Update(const uint32 &t_diff)
// the overloaded operators handle range checking
// so ther's no need for range checking inside the loop
CellPair begin_cell(standing_cell), end_cell(standing_cell);
begin_cell << 1; begin_cell -= 1; // upper left
end_cell >> 1; end_cell += 1; // lower right
//lets update mobs/objects in ALL visible cells around player!
CellArea area = Cell::CalculateCellArea(*plr, GetVisibilityDistance());
area.ResizeBorders(begin_cell, end_cell);
for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x)
{
@ -1044,8 +1058,9 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce)
delete getNGrid(x, y);
setNGrid(NULL, x, y);
}
int gx=63-x;
int gy=63-y;
int gx = (MAX_NUMBER_OF_GRIDS - 1) - x;
int gy = (MAX_NUMBER_OF_GRIDS - 1) - y;
// delete grid map, but don't delete if it is from parent map (and thus only reference)
//+++if (GridMaps[gx][gy]) don't check for GridMaps[gx][gy], we might have to unload vmaps
@ -1921,7 +1936,7 @@ void Map::UpdateObjectVisibility( WorldObject* obj, Cell cell, CellPair cellpair
MaNGOS::VisibleChangesNotifier notifier(*obj);
TypeContainerVisitor<MaNGOS::VisibleChangesNotifier, WorldTypeMapContainer > player_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, cellpair);
cell_lock->Visit(cell_lock, player_notifier, *this);
cell_lock->Visit(cell_lock, player_notifier, *this, *obj, GetVisibilityDistance());
}
void Map::UpdatePlayerVisibility( Player* player, Cell cell, CellPair cellpair )
@ -1932,7 +1947,7 @@ void Map::UpdatePlayerVisibility( Player* player, Cell cell, CellPair cellpair )
TypeContainerVisitor<MaNGOS::PlayerNotifier, WorldTypeMapContainer > player_notifier(pl_notifier);
CellLock<ReadGuard> cell_lock(cell, cellpair);
cell_lock->Visit(cell_lock, player_notifier, *this);
cell_lock->Visit(cell_lock, player_notifier, *this, *player, GetVisibilityDistance());
}
void Map::UpdateObjectsVisibilityFor( Player* player, Cell cell, CellPair cellpair )
@ -1944,8 +1959,8 @@ void Map::UpdateObjectsVisibilityFor( Player* player, Cell cell, CellPair cellpa
TypeContainerVisitor<MaNGOS::VisibleNotifier, WorldTypeMapContainer > world_notifier(notifier);
TypeContainerVisitor<MaNGOS::VisibleNotifier, GridTypeMapContainer > grid_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, cellpair);
cell_lock->Visit(cell_lock, world_notifier, *this);
cell_lock->Visit(cell_lock, grid_notifier, *this);
cell_lock->Visit(cell_lock, world_notifier, *this, *player, GetVisibilityDistance());
cell_lock->Visit(cell_lock, grid_notifier, *this, *player, GetVisibilityDistance());
// send data
notifier.Notify();
@ -1960,8 +1975,8 @@ void Map::PlayerRelocationNotify( Player* player, Cell cell, CellPair cellpair )
TypeContainerVisitor<MaNGOS::PlayerRelocationNotifier, GridTypeMapContainer > p2grid_relocation(relocationNotifier);
TypeContainerVisitor<MaNGOS::PlayerRelocationNotifier, WorldTypeMapContainer > p2world_relocation(relocationNotifier);
cell_lock->Visit(cell_lock, p2grid_relocation, *this);
cell_lock->Visit(cell_lock, p2world_relocation, *this);
cell_lock->Visit(cell_lock, p2grid_relocation, *this, *player, MAX_CREATURE_ATTACK_RADIUS);
cell_lock->Visit(cell_lock, p2world_relocation, *this, *player, MAX_CREATURE_ATTACK_RADIUS);
}
void Map::CreatureRelocationNotify(Creature *creature, Cell cell, CellPair cellpair)
@ -1974,8 +1989,8 @@ void Map::CreatureRelocationNotify(Creature *creature, Cell cell, CellPair cellp
TypeContainerVisitor<MaNGOS::CreatureRelocationNotifier, WorldTypeMapContainer > c2world_relocation(relocationNotifier);
TypeContainerVisitor<MaNGOS::CreatureRelocationNotifier, GridTypeMapContainer > c2grid_relocation(relocationNotifier);
cell_lock->Visit(cell_lock, c2world_relocation, *this);
cell_lock->Visit(cell_lock, c2grid_relocation, *this);
cell_lock->Visit(cell_lock, c2world_relocation, *this, *creature, MAX_CREATURE_ATTACK_RADIUS);
cell_lock->Visit(cell_lock, c2grid_relocation, *this, *creature, MAX_CREATURE_ATTACK_RADIUS);
}
void Map::SendInitSelf( Player * player )
@ -2145,12 +2160,20 @@ void Map::SendToPlayers(WorldPacket const* data) const
bool Map::ActiveObjectsNearGrid(uint32 x, uint32 y) const
{
ASSERT(x < MAX_NUMBER_OF_GRIDS);
ASSERT(y < MAX_NUMBER_OF_GRIDS);
CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS);
CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS);
cell_min << 2;
cell_min -= 2;
cell_max >> 2;
cell_max += 2;
//we must find visible range in cells so we unload only non-visible cells...
float viewDist = GetVisibilityDistance();
int cell_range = (int)ceilf(viewDist / SIZE_OF_GRID_CELL) + 1;
cell_min << cell_range;
cell_min -= cell_range;
cell_max >> cell_range;
cell_max += cell_range;
for(MapRefManager::const_iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter)
{
@ -2234,6 +2257,9 @@ InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 Spaw
m_resetAfterUnload(false), m_unloadWhenEmpty(false),
i_data(NULL), i_script_id(0)
{
//lets initialize visibility distance for dungeons
InstanceMap::InitVisibilityDistance();
// the timer is started by default, and stopped when the first player joins
// this make sure it gets unloaded if for some reason no player joins
m_unloadTimer = std::max(sWorld.getConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY);
@ -2248,6 +2274,12 @@ InstanceMap::~InstanceMap()
}
}
void InstanceMap::InitVisibilityDistance()
{
//init visibility distance for instances
m_VisibleDistance = sWorld.GetMaxVisibleDistanceInInstances();
}
/*
Do map specific checks to see if the player can enter
*/
@ -2570,12 +2602,20 @@ uint32 InstanceMap::GetMaxPlayers() const
BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent)
: Map(id, expiry, InstanceId, DIFFICULTY_NORMAL, _parent)
{
//lets initialize visibility distance for BG/Arenas
BattleGroundMap::InitVisibilityDistance();
}
BattleGroundMap::~BattleGroundMap()
{
}
void BattleGroundMap::InitVisibilityDistance()
{
//init visibility distance for BG/Arenas
m_VisibleDistance = sWorld.GetMaxVisibleDistanceInBGArenas();
}
bool BattleGroundMap::CanEnter(Player * player)
{
if(player->GetMapRef().getTarget() == this)

View file

@ -279,6 +279,10 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
void MessageDistBroadcast(Player *, WorldPacket *, float dist, bool to_self, bool own_team_only = false);
void MessageDistBroadcast(WorldObject *, WorldPacket *, float dist);
float GetVisibilityDistance() const { return m_VisibleDistance; }
//function for setting up visibility distance for maps on per-type/per-Id basis
virtual void InitVisibilityDistance();
void PlayerRelocation(Player *, float x, float y, float z, float angl);
void CreatureRelocation(Creature *creature, float x, float y, float, float);
@ -424,7 +428,6 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
GridMap *GetGrid(float x, float y);
void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; }
//uint64 CalculateGridMask(const uint32 &y) const;
void SendInitSelf( Player * player );
@ -451,6 +454,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
NGridType* getNGrid(uint32 x, uint32 y) const
{
ASSERT(x < MAX_NUMBER_OF_GRIDS);
ASSERT(y < MAX_NUMBER_OF_GRIDS);
return i_grids[x][y];
}
@ -470,6 +475,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
uint32 i_id;
uint32 i_InstanceId;
uint32 m_unloadTimer;
float m_VisibleDistance;
MapRefManager m_mapRefManager;
MapRefManager::iterator m_mapRefIter;
@ -557,6 +563,8 @@ class MANGOS_DLL_SPEC InstanceMap : public Map
void SendResetWarnings(uint32 timeLeft) const;
void SetResetSchedule(bool on);
uint32 GetMaxPlayers() const;
virtual void InitVisibilityDistance();
private:
bool m_resetAfterUnload;
bool m_unloadWhenEmpty;
@ -575,6 +583,8 @@ class MANGOS_DLL_SPEC BattleGroundMap : public Map
bool CanEnter(Player* player);
void SetUnload();
void UnloadAll(bool pForce);
virtual void InitVisibilityDistance();
};
/*inline

View file

@ -32,6 +32,17 @@ MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, 0)
memset(&GridMapReference, 0, MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_GRIDS*sizeof(uint16));
}
void MapInstanced::InitVisibilityDistance()
{
if(m_InstancedMaps.empty())
return;
//initialize visibility distances for all instance copies
for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
{
(*i).second->InitVisibilityDistance();
}
}
void MapInstanced::Update(const uint32& t)
{
// take care of loaded GridMaps (when unused, unload it!)

View file

@ -57,6 +57,7 @@ class MANGOS_DLL_DECL MapInstanced : public Map
}
InstancedMaps &GetInstancedMaps() { return m_InstancedMaps; }
virtual void InitVisibilityDistance();
private:

View file

@ -70,6 +70,12 @@ MapManager::Initialize()
InitMaxInstanceId();
}
void MapManager::InitializeVisibilityDistanceInfo()
{
for(MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter)
(*iter).second->InitVisibilityDistance();
}
// debugging code, should be deleted some day
void MapManager::checkAndCorrectGridStatesArray()
{

View file

@ -122,6 +122,7 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::
void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y);
uint32 GenerateInstanceId() { return ++i_MaxInstanceId; }
void InitMaxInstanceId();
void InitializeVisibilityDistanceInfo();
/* statistics */
uint32 GetNumInstances();

View file

@ -1482,7 +1482,7 @@ void WorldObject::MonsterSay(int32 textId, uint32 language, uint64 TargetGuid)
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY),say_do);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> >, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap());
cell_lock->Visit(cell_lock, message, *GetMap(), *this, sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY));
}
void WorldObject::MonsterYell(int32 textId, uint32 language, uint64 TargetGuid)
@ -1498,7 +1498,7 @@ void WorldObject::MonsterYell(int32 textId, uint32 language, uint64 TargetGuid)
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL),say_do);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> >, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap());
cell_lock->Visit(cell_lock, message, *GetMap(), *this, sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL));
}
void WorldObject::MonsterYellToZone(int32 textId, uint32 language, uint64 TargetGuid)
@ -1527,7 +1527,7 @@ void WorldObject::MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossE
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),say_do);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> >, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap());
cell_lock->Visit(cell_lock, message, *GetMap(), *this, sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE));
}
void WorldObject::MonsterWhisper(int32 textId, uint64 receiver, bool IsBossWhisper)
@ -1758,8 +1758,8 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y,
TypeContainerVisitor<MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo>, WorldTypeMapContainer > world_obj_worker(worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_obj_worker, *GetMap());
cell_lock->Visit(cell_lock, world_obj_worker, *GetMap());
cell_lock->Visit(cell_lock, grid_obj_worker, *GetMap(), *this, distance2d);
cell_lock->Visit(cell_lock, world_obj_worker, *GetMap(), *this, distance2d);
}
// maybe can just place in primary position

View file

@ -32,10 +32,13 @@
#define CONTACT_DISTANCE 0.5f
#define INTERACTION_DISTANCE 5.0f
#define ATTACK_DISTANCE 5.0f
#define MAX_VISIBILITY_DISTANCE (5*SIZE_OF_GRID_CELL/2.0f) // max distance for visible object show, limited by active zone for player based at cell size (active zone = 5x5 cells)
#define DEFAULT_VISIBILITY_DISTANCE (SIZE_OF_GRID_CELL) // default visible distance
#define MAX_VISIBILITY_DISTANCE 333.0f // max distance for visible object show, limited in 333 yards
#define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents
#define DEFAULT_VISIBILITY_INSTANCE 120.0f // default visible distance in instances, 120 yards
#define DEFAULT_VISIBILITY_BGARENAS 180.0f // default visible distance in BG/Arenas, 180 yards
#define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects
#define MAX_STEALTH_DETECT_RANGE 45.0f
enum TypeMask
{

View file

@ -254,7 +254,9 @@ ObjectAccessor::_buildChangeObjectForPlayer(WorldObject *obj, UpdateDataMapType
WorldObjectChangeAccumulator notifier(*obj, update_players);
TypeContainerVisitor<WorldObjectChangeAccumulator, WorldTypeMapContainer > player_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, player_notifier, *obj->GetMap());
Map& map = *obj->GetMap();
//we must build packets for all visible players
cell_lock->Visit(cell_lock, player_notifier, map, *obj, map.GetVisibilityDistance());
}
Pet*

View file

@ -16796,8 +16796,8 @@ void Player::HandleStealthedUnitsDetection()
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyStealthedCheck >, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *GetMap(), *this, MAX_PLAYER_STEALTH_DETECT_RANGE);
cell_lock->Visit(cell_lock, grid_unit_searcher, *GetMap(), *this, MAX_PLAYER_STEALTH_DETECT_RANGE);
WorldObject const* viewPoint = GetViewPoint();

View file

@ -466,12 +466,12 @@ WorldObject* Spell::FindCorpseUsing()
TypeContainerVisitor<MaNGOS::WorldObjectSearcher<T>, GridTypeMapContainer > grid_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_searcher, *m_caster->GetMap(), *m_caster, max_range);
if (!result)
{
TypeContainerVisitor<MaNGOS::WorldObjectSearcher<T>, WorldTypeMapContainer > world_searcher(searcher);
cell_lock->Visit(cell_lock, world_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, world_searcher, *m_caster->GetMap(), *m_caster, max_range);
}
return result;
@ -1346,8 +1346,8 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap(), *m_caster, max_range);
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap(), *m_caster, max_range);
}
if(tempUnitMap.empty())
@ -1416,8 +1416,8 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap(), *m_caster, max_range);
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap(), *m_caster, max_range);
}
if(tempUnitMap.empty())
@ -1512,8 +1512,8 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer> grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap(), *pUnitTarget, max_range);
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap(), *pUnitTarget, max_range);
}
if (tempUnitMap.empty())
break;
@ -4073,7 +4073,7 @@ SpellCastResult Spell::CheckCast(bool strict)
TypeContainerVisitor<MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, object_checker, *m_caster->GetMap());
cell_lock->Visit(cell_lock, object_checker, *m_caster->GetMap(), *m_caster, range);
if (p_GameObject)
{
@ -4112,7 +4112,7 @@ SpellCastResult Spell::CheckCast(bool strict)
TypeContainerVisitor<MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_caster->GetMap(), *m_caster, range);
if(p_Creature )
{
@ -5173,7 +5173,8 @@ SpellCastResult Spell::CheckItems()
TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::GameObjectFocusCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, object_checker, *m_caster->GetMap());
Map& map = *m_caster->GetMap();
cell_lock->Visit(cell_lock, object_checker, map, *m_caster, map.GetVisibilityDistance());
if(!ok)
return SPELL_FAILED_REQUIRES_SPELL_FOCUS;

View file

@ -749,8 +749,8 @@ void AreaAura::Update(uint32 diff)
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap(), *caster, m_radius);
cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap(), *caster, m_radius);
break;
}
case AREA_AURA_ENEMY:
@ -765,8 +765,8 @@ void AreaAura::Update(uint32 diff)
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap(), *caster, m_radius);
cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap(), *caster, m_radius);
break;
}
case AREA_AURA_OWNER:
@ -7050,8 +7050,8 @@ void Aura::PeriodicDummyTick()
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_object_checker, *caster->GetMap());
cell_lock->Visit(cell_lock, world_object_checker, *caster->GetMap());
cell_lock->Visit(cell_lock, grid_object_checker, *caster->GetMap(), *caster, radius);
cell_lock->Visit(cell_lock, world_object_checker, *caster->GetMap(), *caster, radius);
}
if(targets.empty())

View file

@ -91,8 +91,8 @@ TotemAI::UpdateAI(const uint32 /*diff*/)
TypeContainerVisitor<MaNGOS::UnitLastSearcher<MaNGOS::NearestAttackableUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_object_checker, *m_creature->GetMap());
cell_lock->Visit(cell_lock, world_object_checker, *m_creature->GetMap());
cell_lock->Visit(cell_lock, grid_object_checker, *m_creature->GetMap(), *m_creature, max_range);
cell_lock->Visit(cell_lock, world_object_checker, *m_creature->GetMap(), *m_creature, max_range);
}
// If have target

View file

@ -9458,7 +9458,7 @@ int32 Unit::ModifyPower(Powers power, int32 dVal)
bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, bool detect, bool inVisibleList, bool is3dDistance) const
{
if(!u)
if(!u || !IsInMap(u))
return false;
// Always can see self
@ -9481,6 +9481,7 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
if(m_Visibility==VISIBILITY_RESPAWN)
return false;
Map& _map = *u->GetMap();
// Grid dead/alive checks
if( u->GetTypeId()==TYPEID_PLAYER)
{
@ -9524,26 +9525,26 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
if(u->GetTypeId()==TYPEID_PLAYER)
{
// Players far than max visible distance for player or not in our map are not visible too
if (!at_same_transport && !IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
if (!at_same_transport && !IsWithinDistInMap(viewPoint, _map.GetVisibilityDistance() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
return false;
}
else
{
// Units far than max visible distance for creature or not in our map are not visible too
if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
if (!IsWithinDistInMap(viewPoint, _map.GetVisibilityDistance() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
return false;
}
}
else if(GetCharmerOrOwnerGUID()) // distance for show pet/charmed
{
// Pet/charmed far than max visible distance for player or not in our map are not visible too
if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
if (!IsWithinDistInMap(viewPoint, _map.GetVisibilityDistance() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
return false;
}
else // distance for show creature
{
// Units far than max visible distance for creature or not in our map are not visible too
if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
if (!IsWithinDistInMap(viewPoint, _map.GetVisibilityDistance() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
return false;
}
@ -11731,8 +11732,8 @@ Unit* Unit::SelectNearbyTarget(Unit* except /*= NULL*/) const
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *GetMap(), *this, ATTACK_DISTANCE);
cell_lock->Visit(cell_lock, grid_unit_searcher, *GetMap(), *this, ATTACK_DISTANCE);
}
// remove current target

View file

@ -69,9 +69,11 @@ volatile bool World::m_stopEvent = false;
uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
volatile uint32 World::m_worldLoopCounter = 0;
float World::m_MaxVisibleDistanceForCreature = DEFAULT_VISIBILITY_DISTANCE;
float World::m_MaxVisibleDistanceForPlayer = DEFAULT_VISIBILITY_DISTANCE;
float World::m_MaxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE;
float World::m_MaxVisibleDistanceInInctances = DEFAULT_VISIBILITY_INSTANCE;
float World::m_MaxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS;
float World::m_MaxVisibleDistanceForObject = DEFAULT_VISIBILITY_DISTANCE;
float World::m_MaxVisibleDistanceInFlight = DEFAULT_VISIBILITY_DISTANCE;
float World::m_VisibleUnitGreyDistance = 0;
float World::m_VisibleObjectGreyDistance = 0;
@ -996,28 +998,45 @@ void World::LoadConfigSettings(bool reload)
m_VisibleObjectGreyDistance = MAX_VISIBILITY_DISTANCE;
}
m_MaxVisibleDistanceForCreature = sConfig.GetFloatDefault("Visibility.Distance.Creature", DEFAULT_VISIBILITY_DISTANCE);
if(m_MaxVisibleDistanceForCreature < 45*sWorld.getRate(RATE_CREATURE_AGGRO))
//visibility on continents
m_MaxVisibleDistanceOnContinents = sConfig.GetFloatDefault("Visibility.Distance.Continents", DEFAULT_VISIBILITY_DISTANCE);
if(m_MaxVisibleDistanceOnContinents < 45*sWorld.getRate(RATE_CREATURE_AGGRO))
{
sLog.outError("Visibility.Distance.Creature can't be less max aggro radius %f",45*sWorld.getRate(RATE_CREATURE_AGGRO));
m_MaxVisibleDistanceForCreature = 45*sWorld.getRate(RATE_CREATURE_AGGRO);
sLog.outError("Visibility.Distance.Continents can't be less max aggro radius %f", 45*sWorld.getRate(RATE_CREATURE_AGGRO));
m_MaxVisibleDistanceOnContinents = 45*sWorld.getRate(RATE_CREATURE_AGGRO);
}
else if(m_MaxVisibleDistanceForCreature + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
else if(m_MaxVisibleDistanceOnContinents + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
{
sLog.outError("Visibility. Distance .Creature can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
m_MaxVisibleDistanceForCreature = MAX_VISIBILITY_DISTANCE-m_VisibleUnitGreyDistance;
sLog.outError("Visibility.Distance.Continents can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
m_MaxVisibleDistanceOnContinents = MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance;
}
m_MaxVisibleDistanceForPlayer = sConfig.GetFloatDefault("Visibility.Distance.Player", DEFAULT_VISIBILITY_DISTANCE);
if(m_MaxVisibleDistanceForPlayer < 45*sWorld.getRate(RATE_CREATURE_AGGRO))
//visibility in instances
m_MaxVisibleDistanceInInctances = sConfig.GetFloatDefault("Visibility.Distance.Instances", DEFAULT_VISIBILITY_INSTANCE);
if(m_MaxVisibleDistanceInInctances < 45*sWorld.getRate(RATE_CREATURE_AGGRO))
{
sLog.outError("Visibility.Distance.Player can't be less max aggro radius %f",45*sWorld.getRate(RATE_CREATURE_AGGRO));
m_MaxVisibleDistanceForPlayer = 45*sWorld.getRate(RATE_CREATURE_AGGRO);
sLog.outError("Visibility.Distance.Instances can't be less max aggro radius %f",45*sWorld.getRate(RATE_CREATURE_AGGRO));
m_MaxVisibleDistanceInInctances = 45*sWorld.getRate(RATE_CREATURE_AGGRO);
}
else if(m_MaxVisibleDistanceForPlayer + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
else if(m_MaxVisibleDistanceInInctances + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
{
sLog.outError("Visibility.Distance.Player can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
m_MaxVisibleDistanceForPlayer = MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance;
sLog.outError("Visibility.Distance.Instances can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
m_MaxVisibleDistanceInInctances = MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance;
}
//visibility in BG/Arenas
m_MaxVisibleDistanceInBGArenas = sConfig.GetFloatDefault("Visibility.Distance.BGArenas", DEFAULT_VISIBILITY_BGARENAS);
if(m_MaxVisibleDistanceInBGArenas < 45*sWorld.getRate(RATE_CREATURE_AGGRO))
{
sLog.outError("Visibility.Distance.BGArenas can't be less max aggro radius %f",45*sWorld.getRate(RATE_CREATURE_AGGRO));
m_MaxVisibleDistanceInBGArenas = 45*sWorld.getRate(RATE_CREATURE_AGGRO);
}
else if(m_MaxVisibleDistanceInBGArenas + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
{
sLog.outError("Visibility.Distance.BGArenas can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
m_MaxVisibleDistanceInBGArenas = MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance;
}
m_MaxVisibleDistanceForObject = sConfig.GetFloatDefault("Visibility.Distance.Object", DEFAULT_VISIBILITY_DISTANCE);
if(m_MaxVisibleDistanceForObject < INTERACTION_DISTANCE)
{

View file

@ -494,12 +494,14 @@ class World
bool IsScriptScheduled() const { return m_scheduledScripts > 0; }
// for max speed access
static float GetMaxVisibleDistanceForCreature() { return m_MaxVisibleDistanceForCreature; }
static float GetMaxVisibleDistanceForPlayer() { return m_MaxVisibleDistanceForPlayer; }
static float GetMaxVisibleDistanceForObject() { return m_MaxVisibleDistanceForObject; }
static float GetMaxVisibleDistanceInFlight() { return m_MaxVisibleDistanceInFlight; }
static float GetVisibleUnitGreyDistance() { return m_VisibleUnitGreyDistance; }
static float GetVisibleObjectGreyDistance() { return m_VisibleObjectGreyDistance; }
static float GetMaxVisibleDistanceOnContinents() { return m_MaxVisibleDistanceOnContinents; }
static float GetMaxVisibleDistanceInInstances() { return m_MaxVisibleDistanceInInctances; }
static float GetMaxVisibleDistanceInBGArenas() { return m_MaxVisibleDistanceInBGArenas; }
static float GetMaxVisibleDistanceForObject() { return m_MaxVisibleDistanceForObject; }
static float GetMaxVisibleDistanceInFlight() { return m_MaxVisibleDistanceInFlight; }
static float GetVisibleUnitGreyDistance() { return m_VisibleUnitGreyDistance; }
static float GetVisibleObjectGreyDistance() { return m_VisibleObjectGreyDistance; }
void ProcessCliCommands();
void QueueCliCommand( CliCommandHolder::Print* zprintf, char const* input ) { cliCmdQueue.add(new CliCommandHolder(input, zprintf)); }
@ -560,9 +562,11 @@ class World
std::string m_dataPath;
// for max speed access
static float m_MaxVisibleDistanceForCreature;
static float m_MaxVisibleDistanceForPlayer;
static float m_MaxVisibleDistanceOnContinents;
static float m_MaxVisibleDistanceInInctances;
static float m_MaxVisibleDistanceInBGArenas;
static float m_MaxVisibleDistanceForObject;
static float m_MaxVisibleDistanceInFlight;
static float m_VisibleUnitGreyDistance;
static float m_VisibleObjectGreyDistance;

View file

@ -962,12 +962,12 @@ GM.AllowAchievementGain = 1
# 1 (raid members 100% auto detect invisible player from same raid)
# 2 (players from same team can 100% auto detect invisible player)
#
# Visibility.Distance.Creature
# Visibility.Distance.Player
# Visibility distance for different in game object
# Visibility.Distance.Continents
# Visibility.Distance.Instances
# Visibility.Distance.BGArenas
# Visibility distance for different ingame object in different maps.
# Visibility on continents on offy ~90 yards. In BG/Arenas ~180. For instances default ~120.
# Max limited by active player zone: ~ 333
# Min limit dependent from objects
# Default: 132 (cell size)
# Min limit is max aggro radius (45) * Rate.Creature.Aggro
#
# Visibility.Distance.Object
@ -993,8 +993,9 @@ GM.AllowAchievementGain = 1
###################################################################################################################
Visibility.GroupMode = 0
Visibility.Distance.Creature = 100
Visibility.Distance.Player = 100
Visibility.Distance.Continents = 90
Visibility.Distance.Instances = 120
Visibility.Distance.BGArenas = 180
Visibility.Distance.Object = 100
Visibility.Distance.InFlight = 100
Visibility.Distance.Grey.Unit = 1