diff options
Diffstat (limited to 'src/game/Map.cpp')
-rw-r--r-- | src/game/Map.cpp | 221 |
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) |