aboutsummaryrefslogtreecommitdiff
path: root/src/game/Map.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/Map.cpp')
-rw-r--r--src/game/Map.cpp221
1 files changed, 205 insertions, 16 deletions
diff --git a/src/game/Map.cpp b/src/game/Map.cpp
index 6b51fb80d4d..2f8c4d0e152 100644
--- a/src/game/Map.cpp
+++ b/src/game/Map.cpp
@@ -45,6 +45,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];
@@ -210,7 +211,8 @@ void Map::DeleteStateMachine()
Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent)
: i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), 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)
, i_notifyLock(false), i_scriptLock(false)
{
m_notifyTimer.SetInterval(IN_MILISECONDS/2);
@@ -224,6 +226,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
@@ -356,8 +367,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);
@@ -486,6 +497,102 @@ Map::Add(T *obj)
AddNotifier(obj);
}
+/*
+void Map::MessageBroadcast(Player *player, WorldPacket *msg, bool to_self)
+{
+ CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY());
+
+ if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP )
+ {
+ sLog.outError("Map::MessageBroadcast: Player (GUID: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), p.x_coord, p.y_coord);
+ return;
+ }
+
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) )
+ return;
+
+ 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, *player, GetVisibilityDistance());
+}
+
+void Map::MessageBroadcast(WorldObject *obj, WorldPacket *msg)
+{
+ CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
+
+ if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP )
+ {
+ sLog.outError("Map::MessageBroadcast: Object (GUID: %u TypeId: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUIDLow(), obj->GetTypeId(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
+ return;
+ }
+
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ 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, *obj, GetVisibilityDistance());
+}
+
+void Map::MessageDistBroadcast(Player *player, WorldPacket *msg, float dist, bool to_self, bool own_team_only)
+{
+ CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY());
+
+ if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP )
+ {
+ sLog.outError("Map::MessageBroadcast: Player (GUID: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), p.x_coord, p.y_coord);
+ return;
+ }
+
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) )
+ return;
+
+ 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, *player, dist);
+}
+
+void Map::MessageDistBroadcast(WorldObject *obj, WorldPacket *msg, float dist)
+{
+ CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
+
+ if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP )
+ {
+ sLog.outError("Map::MessageBroadcast: Object (GUID: %u TypeId: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUIDLow(), obj->GetTypeId(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
+ return;
+ }
+
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) )
+ return;
+
+ 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, *obj, dist);
+}
+*/
+
bool Map::loaded(const GridPair &p) const
{
return ( getNGrid(p.x_coord, p.y_coord) && isGridObjectDataLoaded(p.x_coord, p.y_coord) );
@@ -513,7 +620,7 @@ void Map::RelocationNotify()
if(dist > 10.0f)
{
Trinity::VisibleChangesNotifier notifier(*unit);
- VisitWorld(unit->oldX, unit->oldY, World::GetMaxVisibleDistance(), notifier);
+ VisitWorld(unit->oldX, unit->oldY, GetVisibilityDistance(), notifier);
dist = 0;
}
@@ -521,15 +628,15 @@ void Map::RelocationNotify()
{
Trinity::PlayerRelocationNotifier notifier(*((Player*)unit));
//if(((Player*)unit)->m_seer != unit)
- VisitAll(((Player*)unit)->m_seer->GetPositionX(), ((Player*)unit)->m_seer->GetPositionY(), World::GetMaxVisibleDistance() + dist, notifier);
+ VisitAll(((Player*)unit)->m_seer->GetPositionX(), ((Player*)unit)->m_seer->GetPositionY(), unit->GetMap()->GetVisibilityDistance() + dist, notifier);
//else
- //VisitAll(((Player*)unit)->GetPositionX(), ((Player*)unit)->GetPositionY(), World::GetMaxVisibleDistance() + dist, notifier);
+ //VisitAll(((Player*)unit)->GetPositionX(), ((Player*)unit)->GetPositionY(), unit->GetMap()->GetVisibilityDistance() + dist, notifier);
notifier.Notify();
}
else
{
Trinity::CreatureRelocationNotifier notifier(*((Creature*)unit));
- VisitAll(unit->GetPositionX(), unit->GetPositionY(), World::GetMaxVisibleDistance() + dist, notifier);
+ VisitAll(unit->GetPositionX(), unit->GetPositionY(), GetVisibilityDistance() + dist, notifier);
}
}
for(std::vector<Unit*>::iterator iter = i_unitsToNotify.begin(); iter != i_unitsToNotify.end(); ++iter)
@@ -631,8 +738,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)
{
@@ -1067,8 +1175,8 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool unloadAll)
delete grid;
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
@@ -2003,8 +2111,64 @@ void Map::UpdateObjectVisibility( WorldObject* obj, Cell cell, CellPair cellpair
Trinity::VisibleChangesNotifier notifier(*obj);
TypeContainerVisitor<Trinity::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 )
+{
+ cell.data.Part.reserved = ALL_DISTRICT;
+
+ MaNGOS::PlayerNotifier pl_notifier(*player);
+ TypeContainerVisitor<MaNGOS::PlayerNotifier, WorldTypeMapContainer > player_notifier(pl_notifier);
+
+ CellLock<ReadGuard> cell_lock(cell, cellpair);
+ cell_lock->Visit(cell_lock, player_notifier, *this, *player, GetVisibilityDistance());
+}
+
+void Map::UpdateObjectsVisibilityFor( Player* player, Cell cell, CellPair cellpair )
+{
+ MaNGOS::VisibleNotifier notifier(*player);
+
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+ 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, *player, GetVisibilityDistance());
+ cell_lock->Visit(cell_lock, grid_notifier, *this, *player, GetVisibilityDistance());
+
+ // send data
+ notifier.Notify();
+}
+
+void Map::PlayerRelocationNotify( Player* player, Cell cell, CellPair cellpair )
+{
+ CellLock<ReadGuard> cell_lock(cell, cellpair);
+ MaNGOS::PlayerRelocationNotifier relocationNotifier(*player);
+ cell.data.Part.reserved = ALL_DISTRICT;
+
+ TypeContainerVisitor<MaNGOS::PlayerRelocationNotifier, GridTypeMapContainer > p2grid_relocation(relocationNotifier);
+ TypeContainerVisitor<MaNGOS::PlayerRelocationNotifier, WorldTypeMapContainer > p2world_relocation(relocationNotifier);
+
+ 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)
+{
+ CellLock<ReadGuard> cell_lock(cell, cellpair);
+ MaNGOS::CreatureRelocationNotifier relocationNotifier(*creature);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate(); // not trigger load unloaded grids at notifier call
+
+ TypeContainerVisitor<MaNGOS::CreatureRelocationNotifier, WorldTypeMapContainer > c2world_relocation(relocationNotifier);
+ TypeContainerVisitor<MaNGOS::CreatureRelocationNotifier, GridTypeMapContainer > c2grid_relocation(relocationNotifier);
+
+ 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 )
{
@@ -2214,12 +2378,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)
{
@@ -2303,6 +2475,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);
@@ -2317,6 +2492,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
*/
@@ -2630,12 +2811,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)