aboutsummaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/game')
-rw-r--r--src/game/GridNotifiers.cpp154
-rw-r--r--src/game/GridNotifiers.h63
-rw-r--r--src/game/GridNotifiersImpl.h98
-rw-r--r--src/game/Map.cpp257
-rw-r--r--src/game/Map.h11
-rw-r--r--src/game/MapManager.h2
-rw-r--r--src/game/Object.cpp4
-rw-r--r--src/game/Object.h23
-rw-r--r--src/game/Player.cpp38
-rw-r--r--src/game/Player.h2
-rw-r--r--src/game/Unit.cpp24
-rw-r--r--src/game/World.cpp8
-rw-r--r--src/game/World.h7
13 files changed, 526 insertions, 165 deletions
diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp
index cf403208389..8d3b906da8f 100644
--- a/src/game/GridNotifiers.cpp
+++ b/src/game/GridNotifiers.cpp
@@ -30,6 +30,92 @@
using namespace Trinity;
void
+Player2PlayerNotifier::Visit(PlayerMapType &m)
+{
+ for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
+ {
+ Player* plr = iter->getSource();
+ if(plr == &i_player)
+ continue;
+
+ vis_guids.erase(plr->GetGUID());
+ i_player.UpdateVisibilityOf(plr,i_data,i_visibleNow);
+
+ // force == true - update i_player visibility for all player in cell, ignore optimization flags.
+ if(!force && (plr->NotifyExecuted(NOTIFY_PLAYER_VISIBILITY) || plr->isNeedNotify(NOTIFY_PLAYER_VISIBILITY)))
+ continue;
+
+ plr->UpdateVisibilityOf(&i_player);
+ }
+}
+
+void
+VisibleNotifier::SendToSelf()
+{
+ for(Player::ClientGUIDs::const_iterator it = vis_guids.begin();it != vis_guids.end();++it)
+ { //player guids processed in Player2PlayerNotifier
+ if(IS_PLAYER_GUID(*it))
+ continue;
+
+ i_player.m_clientGUIDs.erase(*it);
+ i_data.AddOutOfRangeGUID(*it);
+ }
+
+ if(!i_data.HasData())
+ return;
+
+ WorldPacket packet;
+ i_data.BuildPacket(&packet);
+ i_player.GetSession()->SendPacket(&packet);
+
+ for(std::set<Unit*>::const_iterator it = i_visibleNow.begin(); it != i_visibleNow.end(); ++it)
+ i_player.SendInitialVisiblePackets(*it);
+}
+
+void
+Player2PlayerNotifier::SendToSelf()
+{
+ // at this moment i_clientGUIDs have guids that not iterate at grid level checks
+ // but exist one case when this possible and object not out of range: transports
+ if (Transport* transport = i_player.GetTransport())
+ for(Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr!=transport->GetPassengers().end();++itr)
+ {
+ if(vis_guids.find((*itr)->GetGUID()) != vis_guids.end())
+ {
+ vis_guids.erase((*itr)->GetGUID());
+
+ i_player.UpdateVisibilityOf((*itr), i_data, i_visibleNow);
+
+ if(!(*itr)->isNeedNotify(NOTIFY_PLAYER_VISIBILITY))
+ (*itr)->UpdateVisibilityOf(&i_player);
+ }
+ }
+
+ for(Player::ClientGUIDs::const_iterator it = vis_guids.begin();it != vis_guids.end(); ++it)
+ {
+ //since its player-player notifier we work only with player guids
+ if(!IS_PLAYER_GUID(*it))
+ continue;
+
+ i_player.m_clientGUIDs.erase(*it);
+ i_data.AddOutOfRangeGUID(*it);
+ Player* plr = ObjectAccessor::FindPlayer(*it);
+ if(plr && plr->IsInWorld() && !plr->NotifyExecuted(NOTIFY_PLAYER_VISIBILITY) && !plr->isNeedNotify(NOTIFY_PLAYER_VISIBILITY))
+ plr->UpdateVisibilityOf(&i_player);
+ }
+
+ if(!i_data.HasData())
+ return;
+
+ WorldPacket packet;
+ i_data.BuildPacket(&packet);
+ i_player.GetSession()->SendPacket(&packet);
+
+ for(std::set<Unit*>::const_iterator it = i_visibleNow.begin(); it != i_visibleNow.end(); ++it)
+ i_player.SendInitialVisiblePackets(*it);
+}
+
+void
VisibleChangesNotifier::Visit(PlayerMapType &m)
{
for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
@@ -71,74 +157,6 @@ VisibleChangesNotifier::Visit(DynamicObjectMapType &m)
void
PlayerVisibilityNotifier::Notify()
{
- // at this moment i_clientGUIDs have guids that not iterate at grid level checks
- // but exist one case when this possible and object not out of range: transports
- if(Transport* transport = i_player.GetTransport())
- {
- for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin(); itr!=transport->GetPassengers().end(); ++itr)
- {
- if(i_clientGUIDs.find((*itr)->GetGUID())!=i_clientGUIDs.end())
- {
- (*itr)->UpdateVisibilityOf(&i_player);
- i_player.UpdateVisibilityOf((*itr),i_data,i_visibleNow);
- i_clientGUIDs.erase((*itr)->GetGUID());
- }
- }
- }
-
- // generate outOfRange for not iterate objects
- i_data.AddOutOfRangeGUID(i_clientGUIDs);
- for (Player::ClientGUIDs::iterator itr = i_clientGUIDs.begin(); itr!=i_clientGUIDs.end(); ++itr)
- {
- i_player.m_clientGUIDs.erase(*itr);
-
- #ifdef TRINITY_DEBUG
- if((sLog.getLogFilter() & LOG_FILTER_VISIBILITY_CHANGES)==0)
- sLog.outDebug("Object %u (Type: %u) is out of range (no in active cells set) now for player %u",GUID_LOPART(*itr),GuidHigh2TypeId(GUID_HIPART(*itr)),i_player.GetGUIDLow());
- #endif
- }
-
- if( i_data.HasData() )
- {
- /*uint32 entry = 0, map;
- float x,y;
- if(!i_visibleNow.empty())
- {
- entry = (*i_visibleNow.begin())->GetEntry();
- map = (*i_visibleNow.begin())->GetMapId();
- x = (*i_visibleNow.begin())->GetPositionX();
- y = (*i_visibleNow.begin())->GetPositionY();
- sLog.outError("notify %u %u %f %f", entry, map, x, y);
- }*/
-
- // send create/outofrange packet to player (except player create updates that already sent using SendUpdateToPlayer)
- WorldPacket packet;
- i_data.BuildPacket(&packet);
- i_player.GetSession()->SendPacket(&packet);
-
- // send out of range to other players if need
- std::set<uint64> const& oor = i_data.GetOutOfRangeGUIDs();
- for (std::set<uint64>::const_iterator iter = oor.begin(); iter != oor.end(); ++iter)
- {
- if(!IS_PLAYER_GUID(*iter))
- continue;
-
- Player* plr = ObjectAccessor::GetPlayer(i_player,*iter);
- if(plr)
- plr->UpdateVisibilityOf(&i_player);
- }
- }
-
- // Now do operations that required done at object visibility change to visible
-
- // send data at target visibility change (adding to client)
- for (std::set<WorldObject*>::const_iterator vItr = i_visibleNow.begin(); vItr != i_visibleNow.end(); ++vItr)
- // target aura duration for caster show only if target exist at caster client
- if((*vItr)!=&i_player && (*vItr)->isType(TYPEMASK_UNIT))
- i_player.SendInitialVisiblePackets((Unit*)(*vItr));
-
- if(i_visibleNow.size() >= 30)
- i_player.SetToNotify();
}
void
diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h
index 9deb5cb2e24..97bba42fe93 100644
--- a/src/game/GridNotifiers.h
+++ b/src/game/GridNotifiers.h
@@ -38,6 +38,35 @@ class Player;
namespace Trinity
{
+ struct MANGOS_DLL_DECL VisibleNotifier
+ {
+ bool force;
+ Player &i_player;
+ UpdateData i_data;
+ std::set<Unit*> i_visibleNow;
+ Player::ClientGUIDs vis_guids;
+
+ explicit VisibleNotifier(Player &player, bool forced) :
+ i_player(player), vis_guids(player.m_clientGUIDs), force(forced) {}
+ explicit VisibleNotifier(Player &player) :
+ i_player(player), vis_guids(player.m_clientGUIDs),
+ force(player.isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) {}
+ template<class T> void Visit(GridRefManager<T> &m);
+ void Visit(CreatureMapType &m);
+ void Visit(PlayerMapType &m) {}
+ void SendToSelf(void);
+ };
+
+ struct MANGOS_DLL_DECL Player2PlayerNotifier : public VisibleNotifier
+ {
+ Player2PlayerNotifier(Player &player, bool forced = false) :
+ VisibleNotifier(player, forced) {}
+
+ template<class T> void Visit(GridRefManager<T> &) {}
+ void Visit(PlayerMapType &);
+ void SendToSelf(void);
+ };
+
struct TRINITY_DLL_DECL PlayerVisibilityNotifier
{
Player &i_player;
@@ -52,12 +81,12 @@ namespace Trinity
void Notify(void);
};
- struct TRINITY_DLL_DECL PlayerRelocationNotifier : public PlayerVisibilityNotifier
+ struct MANGOS_DLL_DECL PlayerRelocationNotifier
{
- PlayerRelocationNotifier(Player &player) : PlayerVisibilityNotifier(player) {}
- template<class T> inline void Visit(GridRefManager<T> &m) { PlayerVisibilityNotifier::Visit(m); }
+ Player &i_player;
+ PlayerRelocationNotifier(Player &pl) : i_player(pl) {}
+ template<class T> void Visit(GridRefManager<T> &) {}
#ifdef WIN32
- template<> inline void Visit(PlayerMapType &);
template<> inline void Visit(CreatureMapType &);
#endif
};
@@ -84,6 +113,31 @@ namespace Trinity
void Visit(DynamicObjectMapType &);
};
+ struct MANGOS_DLL_DECL DelayedUnitRelocation
+ {
+ typedef GridReadGuard ReadGuard;
+ Map &i_map;
+ CellLock<ReadGuard> &i_lock;
+ const float i_radius;
+ DelayedUnitRelocation(CellLock<ReadGuard> &lock, Map &map, float radius) :
+ i_lock(lock), i_map(map), i_radius(radius) {}
+ template<class T> void Visit(GridRefManager<T> &) {}
+ void Visit(CreatureMapType &m) { Notify<Creature,CreatureRelocationNotifier >(m); }
+ void Visit(PlayerMapType &m) { Notify<Player,PlayerRelocationNotifier >(m); }
+ template<class T, class VISITOR>
+ void Notify(GridRefManager<T> &);
+ };
+
+ struct MANGOS_DLL_DECL ResetNotifier
+ {
+ uint16 reset_mask;
+ ResetNotifier(uint16 notifies) : reset_mask(notifies) {}
+ template<class T> void Visit(GridRefManager<T> &m) { /*resetNotify(m);*/}
+ template<class T> void resetNotify(GridRefManager<T> &);
+ void Visit(CreatureMapType &m) { resetNotify<Creature>(m);}
+ void Visit(PlayerMapType &m) { resetNotify<Player>(m);}
+ };
+
struct TRINITY_DLL_DECL GridUpdater
{
GridType &i_grid;
@@ -1236,7 +1290,6 @@ namespace Trinity
#ifndef WIN32
template<> inline void PlayerRelocationNotifier::Visit<Creature>(CreatureMapType &);
- template<> inline void PlayerRelocationNotifier::Visit<Player>(PlayerMapType &);
template<> inline void CreatureRelocationNotifier::Visit<Player>(PlayerMapType &);
template<> inline void CreatureRelocationNotifier::Visit<Creature>(CreatureMapType &);
template<> inline void DynamicObjectUpdater::Visit<Creature>(CreatureMapType &);
diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h
index fd73119f0d3..e1738af4324 100644
--- a/src/game/GridNotifiersImpl.h
+++ b/src/game/GridNotifiersImpl.h
@@ -29,6 +29,32 @@
#include "CreatureAI.h"
#include "SpellAuras.h"
+
+template<class T>
+inline void
+Trinity::VisibleNotifier::Visit(GridRefManager<T> &m)
+{
+ for(typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
+ {
+ vis_guids.erase(iter->getSource()->GetGUID());
+
+ if(force/* || iter->getSource()->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)*/)
+ i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_visibleNow);
+ }
+}
+
+inline void
+Trinity::VisibleNotifier::Visit(CreatureMapType &m)
+{
+ for(CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
+ {
+ vis_guids.erase(iter->getSource()->GetGUID());
+
+ if(force || iter->getSource()->isNeedNotify(NOTIFY_VISIBILITY_CHANGED))
+ i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_visibleNow);
+ }
+}
+
inline void
Trinity::ObjectUpdater::Visit(CreatureMapType &m)
{
@@ -70,45 +96,47 @@ Trinity::PlayerVisibilityNotifier::Visit(GridRefManager<T> &m)
}
}
-template<>
+template<class T, class VISITOR>
inline void
-Trinity::PlayerRelocationNotifier::Visit(PlayerMapType &m)
+MaNGOS::DelayedUnitRelocation::Notify(GridRefManager<T> &m)
{
- for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
+ for(typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
{
- i_clientGUIDs.erase(iter->getSource()->GetGUID());
-
- if(iter->getSource()->m_Notified) //self is also skipped in this check
+ T * unit = iter->getSource();
+ if(!unit->isAlive() || !unit->isNeedNotify(NOTIFY_AI_RELOCATION))
continue;
- i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_visibleNow);
- iter->getSource()->UpdateVisibilityOf(&i_player);
+ VISITOR relocate(*unit);
+ TypeContainerVisitor<VISITOR, WorldTypeMapContainer > c2world_relocation(relocate);
+ TypeContainerVisitor<VISITOR, GridTypeMapContainer > c2grid_relocation(relocate);
- //if (!i_player.GetSharedVisionList().empty())
- // for (SharedVisionList::const_iterator it = i_player.GetSharedVisionList().begin(); it != i_player.GetSharedVisionList().end(); ++it)
- // (*it)->UpdateVisibilityOf(iter->getSource());
+ i_lock->Visit(i_lock, c2world_relocation, i_map, *unit, i_radius);
+ i_lock->Visit(i_lock, c2grid_relocation, i_map, *unit, i_radius);
- // Cancel Trade
- if(i_player.GetTrader()==iter->getSource())
- if(!i_player.IsWithinDistInMap(iter->getSource(), 5)) // iteraction distance
- i_player.GetSession()->SendCancelTrade(); // will clode both side trade windows
+ unit->SetNotified(NOTIFY_AI_RELOCATION);
}
}
+template<class T>
+inline void
+MaNGOS::ResetNotifier::resetNotify(GridRefManager<T> &m)
+{
+ for(typename GridRefManager<T>::iterator iter=m.begin(); iter != m.end(); ++iter)
+ iter->getSource()->ResetAllNotifiesbyMask(reset_mask);
+}
+
template<>
inline void
Trinity::PlayerRelocationNotifier::Visit(CreatureMapType &m)
{
+ if(!i_player.isAlive() || i_player.isInFlight())
+ return;
+
for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
- i_clientGUIDs.erase(iter->getSource()->GetGUID());
-
- if(iter->getSource()->m_Notified)
- continue;
-
- i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_visibleNow);
-
- PlayerCreatureRelocationWorker(&i_player, iter->getSource());
+ Creature * c = iter->getSource();
+ if(c->isAlive() && !c->NotifyExecuted(NOTIFY_AI_RELOCATION))
+ PlayerCreatureRelocationWorker(&i_player, c);
}
}
@@ -116,14 +144,14 @@ template<>
inline void
Trinity::CreatureRelocationNotifier::Visit(PlayerMapType &m)
{
- for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
- {
- if(iter->getSource()->m_Notified)
- continue;
-
- iter->getSource()->UpdateVisibilityOf(&i_creature);
+ if(!i_creature.isAlive())
+ return;
- PlayerCreatureRelocationWorker(iter->getSource(), &i_creature);
+ for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
+ {
+ Player * pl = iter->getSource();
+ if( pl->isAlive() && !pl->isInFlight() && !pl->NotifyExecuted(NOTIFY_AI_RELOCATION))
+ PlayerCreatureRelocationWorker(pl, &i_creature);
}
}
@@ -136,13 +164,9 @@ Trinity::CreatureRelocationNotifier::Visit(CreatureMapType &m)
for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
- if(iter->getSource()->m_Notified)
- continue;
-
- if(!iter->getSource()->isAlive())
- continue;
-
- CreatureCreatureRelocationWorker(iter->getSource(), &i_creature);
+ Creature* c = iter->getSource();
+ if( c != &i_creature && c->isAlive() && !c->NotifyExecuted(NOTIFY_AI_RELOCATION))
+ CreatureCreatureRelocationWorker(c, &i_creature);
}
}
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)
diff --git a/src/game/Map.h b/src/game/Map.h
index 981a48bbbb6..9144624b23d 100644
--- a/src/game/Map.h
+++ b/src/game/Map.h
@@ -405,6 +405,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
virtual bool RemoveBones(uint64 guid, float x, float y);
void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair);
+ void UpdatePlayerVisibility( Player* player, Cell cell, CellPair cellpair );
+ void UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair );
void resetMarkedCells() { marked_cells.reset(); }
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }
@@ -517,6 +519,10 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
MapRefManager m_mapRefManager;
MapRefManager::iterator m_mapRefIter;
+ PeriodicTimer m_ObjectVisibilityNotifyTimer;
+ PeriodicTimer m_PlayerVisibilityNotifyTimer;
+ PeriodicTimer m_RelocationNotifyTimer;
+
typedef std::set<WorldObject*> ActiveNonPlayers;
ActiveNonPlayers m_activeNonPlayers;
ActiveNonPlayers::iterator m_activeNonPlayersIter;
@@ -537,6 +543,11 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
IntervalTimer m_notifyTimer;
+ void ProcessObjectsVisibility();
+ void ProcesssPlayersVisibility();
+ void ProcessRelocationNotifies();
+ void ResetNotifies(uint16 notify_mask);
+
bool i_notifyLock, i_scriptLock;
std::vector<Unit*> i_unitsToNotifyBacklog;
std::vector<Unit*> i_unitsToNotify;
diff --git a/src/game/MapManager.h b/src/game/MapManager.h
index f4bc5feafa2..df90add4d57 100644
--- a/src/game/MapManager.h
+++ b/src/game/MapManager.h
@@ -31,6 +31,8 @@
class Transport;
+#define DEFAULT_VISIBILITY_NOTIFY_PERIOD 1000
+
class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::ClassLevelLockable<MapManager, ACE_Thread_Mutex> >
{
diff --git a/src/game/Object.cpp b/src/game/Object.cpp
index f3cff243e93..0c8c215d09a 100644
--- a/src/game/Object.cpp
+++ b/src/game/Object.cpp
@@ -240,9 +240,6 @@ void Object::BuildUpdate(UpdateDataMapType &update_players)
void Object::SendUpdateToPlayer(Player* player)
{
- // send update to another players
- SendUpdateObjectToAllExcept(player);
-
// send create update to player
UpdateData upd;
WorldPacket packet;
@@ -1108,6 +1105,7 @@ WorldObject::WorldObject()
, m_zoneScript(NULL)
, m_isActive(false), m_isWorldObject(false)
, m_name("")
+ , m_notifyflags(0), m_executed_notifies(0)
{
}
diff --git a/src/game/Object.h b/src/game/Object.h
index 83189f30b23..93cf0d40e85 100644
--- a/src/game/Object.h
+++ b/src/game/Object.h
@@ -93,6 +93,15 @@ enum PhaseMasks
PHASEMASK_ANYWHERE = 0xFFFFFFFF
};
+enum NotifyFlags
+{
+ NOTIFY_NONE = 0x00,
+ NOTIFY_AI_RELOCATION = 0x01,
+ NOTIFY_VISIBILITY_CHANGED = 0x02,
+ NOTIFY_PLAYER_VISIBILITY = 0x04,
+ NOTIFY_ALL = 0xFF
+};
+
class WorldPacket;
class UpdateData;
class ByteBuffer;
@@ -620,6 +629,17 @@ class TRINITY_DLL_SPEC WorldObject : public Object, public WorldLocation
void DestroyForNearbyPlayers();
+ //new relocation and visibility system functions
+ void AddToNotify(uint16 f) { m_notifyflags |= f;}
+ void RemoveFromNotify(uint16 f) { m_notifyflags &= ~f;}
+ bool isNeedNotify(uint16 f) const { return m_notifyflags & f;}
+
+ bool NotifyExecuted(uint16 f) const { return m_executed_notifies & f;}
+ void SetNotified(uint16 f) { m_executed_notifies |= f;}
+ void ResetNotifies(uint16 f) { m_executed_notifies |= ~f;}
+ void ResetAllNotifies() { m_notifyflags = 0; m_executed_notifies = 0; }
+ void ResetAllNotifiesbyMask(uint16 f) { m_notifyflags &= ~f; m_executed_notifies &= ~f; }
+
bool isActiveObject() const { return m_isActive; }
void setActive(bool isActiveObject);
void SetWorldObject(bool apply);
@@ -654,5 +674,8 @@ class TRINITY_DLL_SPEC WorldObject : public Object, public WorldLocation
//uint32 m_mapId; // object at map with map_id
uint32 m_InstanceId; // in map copy with instance id
uint32 m_phaseMask; // in area phase state
+
+ uint16 m_notifyflags;
+ uint16 m_executed_notifies;
};
#endif
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 69571eb9ee1..51fbc3413c0 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -6015,6 +6015,9 @@ bool Player::SetPosition(float x, float y, float z, float orientation, bool tele
// code block for underwater state update
UpdateUnderwaterState(GetMap(), x, y, z);
+ if(GetTrader() && !IsWithinDistInMap(GetTrader(), 5))
+ GetSession()->SendCancelTrade();
+
CheckExploreSystem();
}
else if(turn)
@@ -19292,18 +19295,32 @@ bool Player::IsVisibleGloballyFor( Player* u ) const
}
template<class T>
-inline void UpdateVisibilityOf_helper(std::set<uint64>& s64, T* target)
+inline void UpdateVisibilityOf_helper(std::set<uint64>& s64, T* target, std::set<Unit*>& v)
{
s64.insert(target->GetGUID());
}
template<>
-inline void UpdateVisibilityOf_helper(std::set<uint64>& s64, GameObject* target)
+inline void UpdateVisibilityOf_helper(std::set<uint64>& s64, GameObject* target, std::set<Unit*>& v)
{
if(!target->IsTransport())
s64.insert(target->GetGUID());
}
+template<>
+inline void UpdateVisibilityOf_helper(std::set<uint64>& s64, Creature* target, std::set<Unit*>& v)
+{
+ s64.insert(target->GetGUID());
+ v.insert(target);
+}
+
+template<>
+inline void UpdateVisibilityOf_helper(std::set<uint64>& s64, Player* target, std::set<Unit*>& v)
+{
+ s64.insert(target->GetGUID());
+ v.insert(target);
+}
+
void Player::UpdateVisibilityOf(WorldObject* target)
{
if(HaveAtClient(target))
@@ -19327,7 +19344,7 @@ void Player::UpdateVisibilityOf(WorldObject* target)
// UpdateVisibilityOf(((Unit*)target)->m_Vehicle);
target->SendUpdateToPlayer(this);
- UpdateVisibilityOf_helper(m_clientGUIDs, target);
+ m_clientGUIDs.insert(target->GetGUID());
#ifdef TRINITY_DEBUG
if((sLog.getLogFilter() & LOG_FILTER_VISIBILITY_CHANGES)==0)
@@ -19355,7 +19372,7 @@ void Player::SendInitialVisiblePackets(Unit* target)
}
template<class T>
-void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<WorldObject*>& visibleNow)
+void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& visibleNow)
{
if(HaveAtClient(target))
{
@@ -19377,9 +19394,8 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<WorldObjec
//if(target->isType(TYPEMASK_UNIT) && ((Unit*)target)->m_Vehicle)
// UpdateVisibilityOf(((Unit*)target)->m_Vehicle, data, visibleNow);
- visibleNow.insert(target);
target->BuildCreateUpdateBlockForPlayer(&data, this);
- UpdateVisibilityOf_helper(m_clientGUIDs,target);
+ UpdateVisibilityOf_helper(m_clientGUIDs,target,visibleNow);
#ifdef TRINITY_DEBUG
if((sLog.getLogFilter() & LOG_FILTER_VISIBILITY_CHANGES)==0)
@@ -19389,11 +19405,11 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<WorldObjec
}
}
-template void Player::UpdateVisibilityOf(Player* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
-template void Player::UpdateVisibilityOf(Creature* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
-template void Player::UpdateVisibilityOf(Corpse* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
-template void Player::UpdateVisibilityOf(GameObject* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
-template void Player::UpdateVisibilityOf(DynamicObject* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
+template void Player::UpdateVisibilityOf(Player* target, UpdateData& data, std::set<Unit*>& visibleNow);
+template void Player::UpdateVisibilityOf(Creature* target, UpdateData& data, std::set<Unit*>& visibleNow);
+template void Player::UpdateVisibilityOf(Corpse* target, UpdateData& data, std::set<Unit*>& visibleNow);
+template void Player::UpdateVisibilityOf(GameObject* target, UpdateData& data, std::set<Unit*>& visibleNow);
+template void Player::UpdateVisibilityOf(DynamicObject* target, UpdateData& data, std::set<Unit*>& visibleNow);
void Player::InitPrimaryProfessions()
{
diff --git a/src/game/Player.h b/src/game/Player.h
index 9038c8926b9..f216f4e548b 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -2154,7 +2154,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void SendInitialVisiblePackets(Unit* target);
template<class T>
- void UpdateVisibilityOf(T* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
+ void UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& visibleNow);
// Stealth detection system
void HandleStealthedUnitsDetection();
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index af07f8eee97..4f3e90bf507 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -11220,7 +11220,22 @@ void Unit::SetVisibility(UnitVisibility x)
{
m_Visibility = x;
- SetToNotify();
+ if(IsInWorld())
+ {
+ Map *m = GetMap();
+ CellPair p(Trinity::ComputeCellPair(GetPositionX(), GetPositionY()));
+ Cell cell(p);
+
+ if(GetTypeId() == TYPEID_PLAYER)
+ {
+ m->UpdatePlayerVisibility((Player*)this, cell, p);
+ m->UpdateObjectsVisibilityFor((Player*)this, cell, p);
+ }
+ else
+ m->UpdateObjectVisibility(this, cell, p);
+
+ AddToNotify(NOTIFY_AI_RELOCATION);
+ }
if (x == VISIBILITY_GROUP_STEALTH)
DestroyForNearbyPlayers();
@@ -14034,9 +14049,10 @@ bool Unit::HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura)
void Unit::SetToNotify()
{
- // it is called somewhere when obj is not in world (crash when log in instance)
- if (m_NotifyListPos < 0)
- GetMap()->AddUnitToNotify(this);
+ if (GetTypeId() == TYPEID_PLAYER)
+ AddToNotify(NOTIFY_VISIBILITY_CHANGED | NOTIFY_AI_RELOCATION | NOTIFY_PLAYER_VISIBILITY);
+ else
+ AddToNotify(NOTIFY_VISIBILITY_CHANGED | NOTIFY_AI_RELOCATION);
}
void Unit::Kill(Unit *pVictim, bool durabilityLoss)
diff --git a/src/game/World.cpp b/src/game/World.cpp
index dc14a5229e0..05d7e5cef21 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -84,6 +84,10 @@ float World::m_MaxVisibleDistanceInFlight = DEFAULT_VISIBILITY_DISTANCE;
float World::m_VisibleUnitGreyDistance = 0;
float World::m_VisibleObjectGreyDistance = 0;
+int32 World::m_visibility_notify_periodOnContinents = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
+int32 World::m_visibility_notify_periodInInstances = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
+int32 World::m_visibility_notify_periodInBGArenas = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
+
/// World constructor
World::World()
{
@@ -1132,6 +1136,10 @@ void World::LoadConfigSettings(bool reload)
m_MaxVisibleDistanceInFlight = MAX_VISIBILITY_DISTANCE - m_VisibleObjectGreyDistance;
}
+ m_visibility_notify_periodOnContinents = sConfig.GetIntDefault("Visibility.Notify.Period.OnContinents", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
+ m_visibility_notify_periodInInstances = sConfig.GetIntDefault("Visibility.Notify.Period.InInstances", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
+ m_visibility_notify_periodInBGArenas = sConfig.GetIntDefault("Visibility.Notify.Period.InBGArenas", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
+
///- Read the "Data" directory from the config file
std::string dataPath = sConfig.GetStringDefault("DataDir","./");
if (dataPath.at(dataPath.length()-1)!='/' && dataPath.at(dataPath.length()-1)!='\\')
diff --git a/src/game/World.h b/src/game/World.h
index 6baff8aac4d..9777e97a046 100644
--- a/src/game/World.h
+++ b/src/game/World.h
@@ -613,6 +613,9 @@ class World
static float GetVisibleUnitGreyDistance() { return m_VisibleUnitGreyDistance; }
static float GetVisibleObjectGreyDistance() { return m_VisibleObjectGreyDistance; }
+ static int32 GetVisibilityNotifyPeriodOnContinents(){ return m_visibility_notify_periodOnContinents; }
+ static int32 GetVisibilityNotifyPeriodInInstances() { return m_visibility_notify_periodInInstances; }
+ static int32 GetVisibilityNotifyPeriodInBGArenas() { return m_visibility_notify_periodInBGArenas; }
void SetWintergrapsTimer(uint32 timer, uint32 state)
{
@@ -723,6 +726,10 @@ class World
static float m_VisibleUnitGreyDistance;
static float m_VisibleObjectGreyDistance;
+ static int32 m_visibility_notify_periodOnContinents;
+ static int32 m_visibility_notify_periodInInstances;
+ static int32 m_visibility_notify_periodInBGArenas;
+
// CLI command holder to be thread safe
ACE_Based::LockedQueue<CliCommandHolder*,ACE_Thread_Mutex> cliCmdQueue;
SqlResultQueue *m_resultQueue;