diff options
Diffstat (limited to 'src/game/Map.cpp')
-rw-r--r-- | src/game/Map.cpp | 257 |
1 files changed, 221 insertions, 36 deletions
diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 5a72c6ed8f0..0ddbf359f40 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -214,7 +214,10 @@ Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _par m_activeNonPlayersIter(m_activeNonPlayers.end()), i_gridExpiry(expiry), m_parentMap(_parent ? _parent : this), m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE) - , i_notifyLock(false), i_scriptLock(false) + , i_notifyLock(false), i_scriptLock(false), + m_PlayerVisibilityNotifyTimer(0.75*DEFAULT_VISIBILITY_NOTIFY_PERIOD, 0.25*DEFAULT_VISIBILITY_NOTIFY_PERIOD), + m_ObjectVisibilityNotifyTimer(DEFAULT_VISIBILITY_NOTIFY_PERIOD, 0 * DEFAULT_VISIBILITY_NOTIFY_PERIOD), + m_RelocationNotifyTimer(DEFAULT_VISIBILITY_NOTIFY_PERIOD,0.5*DEFAULT_VISIBILITY_NOTIFY_PERIOD) { m_notifyTimer.SetInterval(IN_MILISECONDS/2); @@ -236,6 +239,10 @@ void Map::InitVisibilityDistance() { //init visibility for continents m_VisibleDistance = World::GetMaxVisibleDistanceOnContinents(); + + m_PlayerVisibilityNotifyTimer.SetPeriodic(0.75*sWorld.GetVisibilityNotifyPeriodOnContinents(), 0.25*sWorld.GetVisibilityNotifyPeriodOnContinents()); + m_ObjectVisibilityNotifyTimer.SetPeriodic(sWorld.GetVisibilityNotifyPeriodOnContinents(), 0 * sWorld.GetVisibilityNotifyPeriodOnContinents()); + m_RelocationNotifyTimer.SetPeriodic(sWorld.GetVisibilityNotifyPeriodOnContinents(),0.5*sWorld.GetVisibilityNotifyPeriodOnContinents()); } // Template specialization of utility methods @@ -336,17 +343,13 @@ void Map::AddNotifier(T*) template<> void Map::AddNotifier(Player* obj) { - //obj->m_Notified = false; - //obj->m_IsInNotifyList = false; - AddUnitToNotify(obj); + obj->AddToNotify(NOTIFY_VISIBILITY_CHANGED | NOTIFY_AI_RELOCATION | NOTIFY_PLAYER_VISIBILITY); } template<> void Map::AddNotifier(Creature* obj) { - //obj->m_Notified = false; - //obj->m_IsInNotifyList = false; - AddUnitToNotify(obj); + obj->AddToNotify(NOTIFY_VISIBILITY_CHANGED | NOTIFY_AI_RELOCATION); } void @@ -444,13 +447,14 @@ bool Map::Add(Player *player) CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); Cell cell(p); EnsureGridLoadedAtEnter(cell, player); + player->ResetAllNotifies(); player->AddToWorld(); SendInitSelf(player); SendInitTransports(player); player->m_clientGUIDs.clear(); - //AddNotifier(player); + AddNotifier<Player>(player); return true; } @@ -494,8 +498,8 @@ Map::Add(T *obj) //something, such as vehicle, needs to be update immediately //also, trigger needs to cast spell, if not update, cannot see visual //if(obj->GetTypeId() != TYPEID_UNIT) - UpdateObjectVisibility(obj,cell,p); - AddNotifier(obj); + UpdateObjectVisibility(obj,cell,p); + AddNotifier<T>(obj); } /* @@ -601,7 +605,7 @@ bool Map::loaded(const GridPair &p) const void Map::RelocationNotify() { - i_notifyLock = true; +/* i_notifyLock = true; //Notify for (std::vector<Unit*>::iterator iter = i_unitsToNotify.begin(); iter != i_unitsToNotify.end(); ++iter) @@ -651,12 +655,12 @@ void Map::RelocationNotify() { i_unitsToNotify.insert(i_unitsToNotify.end(), i_unitsToNotifyBacklog.begin(), i_unitsToNotifyBacklog.end()); i_unitsToNotifyBacklog.clear(); - } + }*/ } void Map::AddUnitToNotify(Unit* u) { - if(u->m_NotifyListPos < 0 && u->IsInWorld()) +/* if(u->m_NotifyListPos < 0 && u->IsInWorld()) { u->oldX = u->GetPositionX(); u->oldY = u->GetPositionY(); @@ -671,7 +675,7 @@ void Map::AddUnitToNotify(Unit* u) u->m_NotifyListPos = i_unitsToNotify.size(); i_unitsToNotify.push_back(u); } - } + }*/ } void Map::RemoveUnitFromNotify(Unit *unit) @@ -714,13 +718,6 @@ void Map::Update(const uint32 &t_diff) plr->Update(t_diff); } - m_notifyTimer.Update(t_diff); - if (m_notifyTimer.Passed()) - { - m_notifyTimer.Reset(); - RelocationNotify(); - } - /// update active cells around players and active objects resetMarkedCells(); @@ -772,9 +769,6 @@ void Map::Update(const uint32 &t_diff) } } } - - if (plr->m_seer != plr && !plr->GetVehicle()) - AddUnitToNotify(plr); } // non-player active objects @@ -836,10 +830,191 @@ void Map::Update(const uint32 &t_diff) } MoveAllCreaturesInMoveList(); + + { + bool hasPlayers = !m_mapRefManager.isEmpty(); + bool hasActiveObjects = !m_activeNonPlayers.empty(); + + if(hasPlayers) + { + if(m_PlayerVisibilityNotifyTimer.Update(t_diff)) + { // process player-player visibility + ProcesssPlayersVisibility(); + ResetNotifies(NOTIFY_PLAYER_VISIBILITY); + } + + if(m_ObjectVisibilityNotifyTimer.Update(t_diff)) + { + ProcessObjectsVisibility(); + ResetNotifies(NOTIFY_VISIBILITY_CHANGED); + } + } + + if(hasActiveObjects || hasPlayers) + if(m_RelocationNotifyTimer.Update(t_diff)) + { + ProcessRelocationNotifies(); + ResetNotifies(NOTIFY_AI_RELOCATION); + } + } +} + +void Map::ProcesssPlayersVisibility() +{ + for(m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter) + { + Player* player = m_mapRefIter->getSource(); + + if (player->m_seer != player && !player->GetVehicle()) + AddNotifier<Player>(player); + + if(!player->IsInWorld() || !player->isNeedNotify(NOTIFY_PLAYER_VISIBILITY)) + continue; + + WorldObject const *viewPoint = player->m_seer; + CellPair cellpair(Trinity::ComputeCellPair(viewPoint->GetPositionX(), viewPoint->GetPositionY())); + + if (cellpair.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || cellpair.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + continue; + + Trinity::Player2PlayerNotifier notifier(*player); + + Cell cell(cellpair); + cell.data.Part.reserved = ALL_DISTRICT; + //cell.SetNoCreate(); + TypeContainerVisitor<Trinity::Player2PlayerNotifier, WorldTypeMapContainer > world_notifier(notifier); + CellLock<ReadGuard> cell_lock(cell, cellpair); + cell_lock->Visit(cell_lock, world_notifier, *this, *viewPoint, GetVisibilityDistance()); + + // send data + notifier.SendToSelf(); + player->RemoveFromNotify(NOTIFY_PLAYER_VISIBILITY); + player->SetNotified(NOTIFY_PLAYER_VISIBILITY); + } +} + +void Map::ProcessObjectsVisibility() +{ + for(m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter) + { + Player* player = m_mapRefIter->getSource(); + + if (player->m_seer != player && !player->GetVehicle()) + AddNotifier<Player>(player); + + if(!player->IsInWorld()) + continue; + + WorldObject const *viewPoint = player->m_seer; + CellPair cellpair(Trinity::ComputeCellPair(viewPoint->GetPositionX(), viewPoint->GetPositionY())); + + if (cellpair.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || cellpair.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + continue; + + Cell cell(cellpair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::VisibleNotifier notifier(*player); + + TypeContainerVisitor<Trinity::VisibleNotifier, WorldTypeMapContainer > world_notifier(notifier); + TypeContainerVisitor<Trinity::VisibleNotifier, GridTypeMapContainer > grid_notifier(notifier); + CellLock<ReadGuard> cell_lock(cell, cellpair); + cell_lock->Visit(cell_lock, world_notifier, *this, *viewPoint, GetVisibilityDistance()); + cell_lock->Visit(cell_lock, grid_notifier, *this, *viewPoint, GetVisibilityDistance()); + + // send data + notifier.SendToSelf(); + player->SetNotified(NOTIFY_VISIBILITY_CHANGED); + } +} + +void Map::ProcessRelocationNotifies() +{ + for(GridRefManager<NGridType>::iterator i = GridRefManager<NGridType>::begin(); i != GridRefManager<NGridType>::end(); ++i) + { + NGridType *grid = i->getSource(); + + if(!grid || grid->GetGridState() != GRID_STATE_ACTIVE) + continue; + + uint32 gx = grid->getX(), gy = grid->getY(); + + CellPair cell_min(gx*MAX_NUMBER_OF_CELLS, gy*MAX_NUMBER_OF_CELLS); + CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); + + for(uint32 x = cell_min.x_coord; x <= cell_max.x_coord; ++x) + { + for(uint32 y = cell_min.y_coord; y <= cell_max.y_coord; ++y) + { + uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; + if(!isCellMarked(cell_id)) + continue; + + CellPair pair(x,y); + Cell cell(pair); + cell.data.Part.reserved = CENTER_DISTRICT; + cell.SetNoCreate(); + + CellLock<ReadGuard> cell_lock(cell, pair); + Trinity::DelayedUnitRelocation cell_relocation(cell_lock, *this, GetVisibilityDistance()); + TypeContainerVisitor<Trinity::DelayedUnitRelocation, GridTypeMapContainer > grid_object_relocation(cell_relocation); + TypeContainerVisitor<Trinity::DelayedUnitRelocation, WorldTypeMapContainer > world_object_relocation(cell_relocation); + cell_lock->Visit(cell_lock, grid_object_relocation, *this); + cell_lock->Visit(cell_lock, world_object_relocation, *this); + } + } + } +} + +void Map::ResetNotifies(uint16 notify_mask) +{ + if(notify_mask == NOTIFY_PLAYER_VISIBILITY) + { + for(m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter) + m_mapRefIter->getSource()->ResetAllNotifiesbyMask(notify_mask); + return; + } + + Trinity::ResetNotifier reset(notify_mask); + TypeContainerVisitor<Trinity::ResetNotifier, GridTypeMapContainer > grid_notifier(reset); + TypeContainerVisitor<Trinity::ResetNotifier, WorldTypeMapContainer > world_notifier(reset); + + for(GridRefManager<NGridType>::iterator i = GridRefManager<NGridType>::begin(); i != GridRefManager<NGridType>::end(); ++i) + { + NGridType *grid = i->getSource(); + + if(!grid || grid->GetGridState() != GRID_STATE_ACTIVE) + continue; + + uint32 gx = grid->getX(), gy = grid->getY(); + + CellPair cell_min(gx*MAX_NUMBER_OF_CELLS, gy*MAX_NUMBER_OF_CELLS); + CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); + + for(uint32 x = cell_min.x_coord; x <= cell_max.x_coord; ++x) + { + for(uint32 y = cell_min.y_coord; y <= cell_max.y_coord; ++y) + { + uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; + if(!isCellMarked(cell_id)) + continue; + + CellPair pair(x,y); + Cell cell(pair); + cell.data.Part.reserved = CENTER_DISTRICT; + cell.SetNoCreate(); + CellLock<NullGuard> cell_lock(cell, pair); + cell_lock->Visit(cell_lock, grid_notifier, *this); + cell_lock->Visit(cell_lock, world_notifier, *this); + } + } + } } void Map::Remove(Player *player, bool remove) { + player->ResetAllNotifies(); player->RemoveFromWorld(); SendRemoveTransports(player); @@ -883,6 +1058,7 @@ template<class T> void Map::Remove(T *obj, bool remove) { + obj->ResetAllNotifies(); obj->RemoveFromWorld(); if (obj->isActiveObject()) RemoveFromActive(obj); @@ -946,7 +1122,7 @@ Map::PlayerRelocation(Player *player, float x, float y, float z, float orientati EnsureGridLoadedAtEnter(new_cell, player); } - AddUnitToNotify(player); + AddNotifier<Player>(player); NGridType* newGrid = getNGrid(new_cell.GridX(), new_cell.GridY()); if (!same_cell && newGrid->GetGridState()!= GRID_STATE_ACTIVE) @@ -979,7 +1155,7 @@ Map::CreatureRelocation(Creature *creature, float x, float y, float z, float ang else { creature->Relocate(x, y, z, ang); - AddUnitToNotify(creature); + AddNotifier<Creature>(creature); } if (creature->IsVehicle()) @@ -1033,7 +1209,7 @@ void Map::MoveAllCreaturesInMoveList() // update pos c->Relocate(cm.x, cm.y, cm.z, cm.ang); //CreatureRelocationNotify(c,new_cell,new_cell.cellPair()); - AddUnitToNotify(c); + AddNotifier<Creature>(c); } else { @@ -1140,7 +1316,7 @@ bool Map::CreatureRespawnRelocation(Creature *c) c->Relocate(resp_x, resp_y, resp_z, resp_o); c->GetMotionMaster()->Initialize(); // prevent possible problems with default move generators //CreatureRelocationNotify(c,resp_cell,resp_cell.cellPair()); - AddUnitToNotify(c); + AddNotifier<Creature>(c); return true; } else @@ -2141,34 +2317,35 @@ void Map::UpdateObjectVisibility( WorldObject* obj, Cell cell, CellPair cellpair 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); + Trinity::Player2PlayerNotifier pl_notifier(*player); + TypeContainerVisitor<Trinity::Player2PlayerNotifier, WorldTypeMapContainer > player_notifier(pl_notifier); CellLock<ReadGuard> cell_lock(cell, cellpair); cell_lock->Visit(cell_lock, player_notifier, *this, *player, GetVisibilityDistance()); + pl_notifier.SendToSelf(); } void Map::UpdateObjectsVisibilityFor( Player* player, Cell cell, CellPair cellpair ) { - MaNGOS::VisibleNotifier notifier(*player); + Trinity::VisibleNotifier notifier(*player, true); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - TypeContainerVisitor<MaNGOS::VisibleNotifier, WorldTypeMapContainer > world_notifier(notifier); - TypeContainerVisitor<MaNGOS::VisibleNotifier, GridTypeMapContainer > grid_notifier(notifier); + TypeContainerVisitor<Trinity::VisibleNotifier, WorldTypeMapContainer > world_notifier(notifier); + TypeContainerVisitor<Trinity::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(); + notifier.SendToSelf(); } - +/* void Map::PlayerRelocationNotify( Player* player, Cell cell, CellPair cellpair ) { CellLock<ReadGuard> cell_lock(cell, cellpair); @@ -2524,6 +2701,10 @@ void InstanceMap::InitVisibilityDistance() { //init visibility distance for instances m_VisibleDistance = World::GetMaxVisibleDistanceInInstances(); + + m_PlayerVisibilityNotifyTimer.SetPeriodic(0.75*sWorld.GetVisibilityNotifyPeriodInInstances(), 0.25*sWorld.GetVisibilityNotifyPeriodInInstances()); + m_ObjectVisibilityNotifyTimer.SetPeriodic(sWorld.GetVisibilityNotifyPeriodInInstances(), 0 * sWorld.GetVisibilityNotifyPeriodInInstances()); + m_RelocationNotifyTimer.SetPeriodic(sWorld.GetVisibilityNotifyPeriodInInstances(),0.5*sWorld.GetVisibilityNotifyPeriodInInstances()); } /* @@ -2873,6 +3054,10 @@ void BattleGroundMap::InitVisibilityDistance() { //init visibility distance for BG/Arenas m_VisibleDistance = World::GetMaxVisibleDistanceInBGArenas(); + + m_PlayerVisibilityNotifyTimer.SetPeriodic(0.75*sWorld.GetVisibilityNotifyPeriodInBGArenas(), 0.25*sWorld.GetVisibilityNotifyPeriodInBGArenas()); + m_ObjectVisibilityNotifyTimer.SetPeriodic(sWorld.GetVisibilityNotifyPeriodInBGArenas(), 0 * sWorld.GetVisibilityNotifyPeriodInBGArenas()); + m_RelocationNotifyTimer.SetPeriodic(sWorld.GetVisibilityNotifyPeriodInBGArenas(),0.5*sWorld.GetVisibilityNotifyPeriodInBGArenas()); } bool BattleGroundMap::CanEnter(Player * player) |