rendered paste bodyIndex: src/game/AggressorAI.cpp===================================================================--- src/game/AggressorAI.cpp (revision 3914)+++ src/game/AggressorAI.cpp (working copy)@@ -166,7 +166,7 @@ assert((i_victimGuid != 0) == (i_creature.getVictim() != NULL) && "i_victimGuid and i_creature.getVictim() not synchronized."); - if( i_creature.IsWithinDistInMap(i_creature.getVictim(), ATTACK_DIST))+ if( i_creature.IsWithinDistInMap(i_creature.getVictim(), OBJECT_ATTACK_DIST)) { if( i_creature.isAttackReady() ) {@@ -181,7 +181,7 @@ AggressorAI::IsVisible(Unit *pl) const { return i_creature.GetDistanceSq(pl) < sWorld.getConfig(CONFIG_SIGHT_MONSTER)- && pl->isVisibleFor(&i_creature,true);+ && pl->isVisibleForOrDetect(&i_creature,true); } voidIndex: src/game/Corpse.cpp===================================================================--- src/game/Corpse.cpp (revision 3914)+++ src/game/Corpse.cpp (working copy)@@ -27,7 +27,6 @@ #include "WorldSession.h" #include "WorldPacket.h" #include "GossipDef.h"-#include "RedZoneDistrict.h" Corpse::Corpse( WorldObject *instantiator, CorpseType type ) : WorldObject( instantiator ) {@@ -102,10 +101,7 @@ sLog.outError("Bones %u not found in world.", GetGUIDLow()); } else- {- ObjectAccessor::Instance().RemoveBonesFromPlayerView(corpse); ObjectAccessor::Instance().AddObjectToRemoveList(this);- } RemoveFromWorld(); }@@ -265,3 +261,8 @@ else bones->DeleteBonesFromWorld(); }++bool Corpse::isVisibleForInState(Player const* u, bool inVisibleList) const+{+ return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleGrayDistance() : 0));+}Index: src/game/Corpse.h===================================================================--- src/game/Corpse.h (revision 3914)+++ src/game/Corpse.h (working copy)@@ -57,6 +57,8 @@ GridPair const& GetGrid() const { return m_grid; } + bool isVisibleForInState(Player const* u, bool inVisibleList) const;+ void _ConvertCorpseToBones(); // only call from ObjectAccessor::ConvertCorpseForPlayer private: CorpseType m_type;Index: src/game/Creature.cpp===================================================================--- src/game/Creature.cpp (revision 3914)+++ src/game/Creature.cpp (working copy)@@ -186,7 +186,7 @@ { m_deathTimer = 0; DEBUG_LOG("Removing corpse... %u ", GetUInt32Value(OBJECT_FIELD_ENTRY));- ObjectAccessor::Instance().RemoveCreatureCorpseFromPlayerView(this);+ ObjectAccessor::UpdateObjectVisibility(this); lootForPickPocketed = false; lootForBody = false; loot.clear();Index: src/game/CreatureAIRegistry.cpp===================================================================--- src/game/CreatureAIRegistry.cpp (revision 3914)+++ src/game/CreatureAIRegistry.cpp (working copy)@@ -28,7 +28,6 @@ #include "MovementGeneratorImpl.h" #include "MapManager.h" #include "WaypointMovementGenerator.h"-#include "RedZoneDistrict.h" #include "CreatureAIRegistry.h" #include "WaypointMovementGenerator.h" Index: src/game/DynamicObject.cpp===================================================================--- src/game/DynamicObject.cpp (revision 3914)+++ src/game/DynamicObject.cpp (working copy)@@ -127,3 +127,8 @@ if (*iunit) (*iunit)->DelayAura(m_spellId, m_effIndex, delaytime); }++bool DynamicObject::isVisibleForInState(Player const* u, bool inVisibleList) const+{+ return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleGrayDistance() : 0));+}Index: src/game/DynamicObject.h===================================================================--- src/game/DynamicObject.h (revision 3914)+++ src/game/DynamicObject.h (working copy)@@ -43,7 +43,7 @@ void AddAffected(Unit *unit) { m_affected.insert(unit); } void RemoveAffected(Unit *unit) { m_affected.erase(unit); } void Delay(int32 delaytime);-+ bool isVisibleForInState(Player const* u, bool inVisibleList) const; protected: uint64 m_casterGuid; uint32 m_spellId;Index: src/game/GameObject.cpp===================================================================--- src/game/GameObject.cpp (revision 3914)+++ src/game/GameObject.cpp (working copy)@@ -508,3 +508,9 @@ if(m_respawnTime > time(NULL) && !GetOwnerGUID()) objmgr.SaveGORespawnTime(m_DBTableGuid,GetInstanceId(),m_respawnTime); }++bool GameObject::isVisibleForInState(Player const* u, bool inVisibleList) const+{+ return IsInWorld() && u->IsInWorld() && ( IsTransport() && IsInMap(u) ||+ isSpawned() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleGrayDistance() : 0)) );+}Index: src/game/GameObject.h===================================================================--- src/game/GameObject.h (revision 3914)+++ src/game/GameObject.h (working copy)@@ -166,6 +166,8 @@ bool hasQuest(uint32 quest_id) const; bool hasInvolvedQuest(uint32 quest_id) const;++ bool isVisibleForInState(Player const* u, bool inVisibleList) const; protected: uint32 m_spellId; time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),Index: src/game/GridNotifiers.cpp===================================================================--- src/game/GridNotifiers.cpp (revision 3914)+++ src/game/GridNotifiers.cpp (working copy)@@ -24,258 +24,90 @@ #include "Map.h" #include "MapManager.h" #include "Transports.h"+#include "ObjectAccessor.h" using namespace MaNGOS; -void PlayerNotifier::Visit(PlayerMapType &m)+void+MaNGOS::PlayerNotifier::Visit(PlayerMapType &m) {- BuildForMySelf();- for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) { if( iter->second == &i_player ) continue; - if( i_player.isAlive() && iter->second->isAlive() ||- i_player.isDead() && iter->second->isDead() )- {- if (iter->second->isVisibleFor(&i_player,false))- iter->second->SendUpdateToPlayer(&i_player);- if (i_player.isVisibleFor(iter->second,false))- i_player.SendUpdateToPlayer(iter->second);- }- else- {- i_player.DestroyForPlayer(iter->second);- iter->second->DestroyForPlayer(&i_player);- }+ iter->second->UpdateVisibilityOf(&i_player);+ i_player.UpdateVisibilityOf(iter->second); } } void-PlayerNotifier::BuildForMySelf()+VisibleChangesNotifier::Visit(PlayerMapType &m) {- if( !i_player.IsInWorld() )+ for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) {- WorldPacket packet;- UpdateData data;+ if(iter->second == &i_object)+ continue; - Transport *t = i_player.GetTransport();- if (t)- {- t->BuildCreateUpdateBlockForPlayer(&data, &i_player);- }-- sLog.outDetail("Creating player data for himself %u", i_player.GetGUIDLow());- i_player.BuildCreateUpdateBlockForPlayer(&data, &i_player);- data.BuildPacket(&packet);- i_player.GetSession()->SendPacket(&packet);- i_player.AddToWorld();-- // Hack to send out transports- WorldPacket packet2;- UpdateData transData;- if (MapManager::Instance().m_TransportsByMap.find(i_player.GetMapId()) != MapManager::Instance().m_TransportsByMap.end())- {- for (size_t i = 0; i < MapManager::Instance().m_TransportsByMap[i_player.GetMapId()].size(); ++i)- {- Transport *t = MapManager::Instance().m_TransportsByMap[i_player.GetMapId()][i];- t->BuildCreateUpdateBlockForPlayer(&transData, &i_player);- }- transData.BuildPacket(&packet2);- i_player.GetSession()->SendPacket(&packet2);- }+ iter->second->UpdateVisibilityOf(&i_object); } } void-VisibleNotifier::Notify()+VisibleNotifier::Visit(PlayerMapType &m) {- if( i_data.HasData() )+ for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) {- // send update to other players (except player updates that already sent using SendUpdateToPlayer)- for(UpdateDataMapType::iterator iter = i_updateDatas.begin(); iter != i_updateDatas.end(); ++iter)- {- if(iter->first==&i_player)- continue;+ if( iter->second == &i_player )+ continue; - WorldPacket packet;- iter->second.BuildPacket(&packet);- iter->first->GetSession()->SendPacket(&packet);- }-- // send create packet to player (except player create updates that already sent using SendUpdateToPlayer)- WorldPacket packet;- i_data.BuildPacket(&packet);- i_player.GetSession()->SendPacket(&packet);-- // all object visible to i_player is updated/(create updated)+ iter->second->UpdateVisibilityOf(&i_player);+ i_player.UpdateVisibilityOf(iter->second,i_data,i_data_updates);+ i_clientGUIDs.erase(iter->second->GetGUID()); } } -template<class T> void-VisibleNotifier::Visit(std::map<OBJECT_HANDLE, T *> &m)+VisibleNotifier::Notify() {- for(typename std::map<OBJECT_HANDLE, T *>::iterator iter=m.begin(); iter != m.end(); ++iter)- {- iter->second->BuildUpdate(i_updateDatas);- iter->second->BuildCreateUpdateBlockForPlayer(&i_data, &i_player);- }-}+ // 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); -template<class T>-void-VisibleNotifier::Visit(std::map<OBJECT_HANDLE, CountedPtr<T> > &m)-{- for(typename std::map<OBJECT_HANDLE, CountedPtr<T> >::iterator iter=m.begin(); iter != m.end(); ++iter)+ // send update to other players (except player updates that already sent using SendUpdateToPlayer)+ for(UpdateDataMapType::iterator iter = i_data_updates.begin(); iter != i_data_updates.end(); ++iter) {- iter->second->BuildUpdate(i_updateDatas);- iter->second->BuildCreateUpdateBlockForPlayer(&i_data, &i_player);- }-}+ if(iter->first==&i_player)+ continue; -void-VisibleNotifier::Visit(GameObjectMapType &m)-{- for(GameObjectMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- {- if(iter->second->isSpawned()) // show only respawned GO- {- iter->second->BuildUpdate(i_updateDatas);- iter->second->BuildCreateUpdateBlockForPlayer(&i_data, &i_player);- }+ WorldPacket packet;+ iter->second.BuildPacket(&packet);+ iter->first->GetSession()->SendPacket(&packet); }-} -void-MaNGOS::VisibleChangesNotifier::Visit(PlayerMapType &m)-{- for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- {- // Invisibility for gms- if(iter->second != &i_player)- {- switch(i_player.GetUpdateVisibility())- {- case VISIBLE_SET_INVISIBLE:- {- i_player.DestroyForPlayer(iter->second);- iter->second->m_DetectInvTimer = 1;- }- break;- case VISIBLE_SET_INVISIBLE_FOR_GROUP:- if (!iter->second->IsGroupVisibleFor(&i_player))- {- i_player.DestroyForPlayer(iter->second);- iter->second->m_DetectInvTimer = 1;- }- break;- case VISIBLE_SET_VISIBLE:- i_player.SendUpdateToPlayer(iter->second);- break;- }-- // Detect invisible pjs- if (i_player.m_enableDetect && iter->second->GetVisibility() == VISIBILITY_GROUP && !iter->second->IsGroupVisibleFor(&i_player))- {- if(i_player.IsWithinDistInMap(iter->second, 20))- i_player.InvisiblePjsNear.push_back(iter->second);- }-- // Reveal Invisible Pjs- if (iter->second == i_player.m_DiscoveredPj)- iter->second->SendUpdateToPlayer(&i_player);- }- }-}--void-NotVisibleNotifier::Notify()-{ if( i_data.HasData() ) {+ // 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);- }-} -template<class T>-void-NotVisibleNotifier::Visit(std::map<OBJECT_HANDLE, T *> &m)-{- for(typename std::map<OBJECT_HANDLE, T *>::iterator iter=m.begin(); iter != m.end(); ++iter)- iter->second->BuildOutOfRangeUpdateBlock(&i_data);-}--template<class T>-void-NotVisibleNotifier::Visit(std::map<OBJECT_HANDLE, CountedPtr<T> > &m)-{- for(typename std::map<OBJECT_HANDLE, CountedPtr<T> >::iterator iter=m.begin(); iter != m.end(); ++iter)- iter->second->BuildOutOfRangeUpdateBlock(&i_data);-}--void-NotVisibleNotifier::Visit(GameObjectMapType &m)-{- for(GameObjectMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- // ignore transport gameobjects at same map- if(!i_player.IsInMap(iter->second) || !iter->second->IsTransport())- iter->second->BuildOutOfRangeUpdateBlock(&i_data);-}--void-MaNGOS::NotVisibleNotifier::Visit(PlayerMapType &m)-{- for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- {- if( iter->second == &i_player )- continue;- if( (i_player.isAlive() && iter->second->isAlive()) ||- (i_player.isDead() && iter->second->isDead()) )+ // 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) {- iter->second->BuildOutOfRangeUpdateBlock(&i_data);+ if(GUID_HIPART(*iter)!=HIGHGUID_PLAYER)+ continue; - UpdateData his_data;- WorldPacket his_pk;- i_player.BuildOutOfRangeUpdateBlock(&his_data);- his_data.BuildPacket(&his_pk);- iter->second->GetSession()->SendPacket(&his_pk);+ Player* plr = ObjectAccessor::Instance().GetPlayer(i_player,*iter);+ if(plr)+ plr->UpdateVisibilityOf(&i_player); } } } void-ObjectVisibleNotifier::Visit(PlayerMapType &m)-{- // ignore not respawned gameobjects- if(i_object.GetTypeId() == TYPEID_GAMEOBJECT && !((GameObject&)i_object).isSpawned())- return;-- for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- {- UpdateData update_data;- WorldPacket packet;- i_object.BuildCreateUpdateBlockForPlayer(&update_data, iter->second);- update_data.BuildPacket(&packet);- iter->second->GetSession()->SendPacket(&packet);- }-}--void-ObjectNotVisibleNotifier::Visit(PlayerMapType &m)-{- // ignore transport gameobjects at same map- bool transport = (i_object.GetTypeId() == TYPEID_GAMEOBJECT && ((GameObject&)i_object).IsTransport());-- for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- if(!i_object.IsInMap(iter->second) || !transport)- iter->second->SendOutOfRange(&i_object);-}--void MessageDeliverer::Visit(PlayerMapType &m) { for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)@@ -283,7 +115,8 @@ if( (iter->second != &i_player || i_toSelf) && (!i_ownTeamOnly || iter->second->GetTeam() == i_player.GetTeam()) ) {- iter->second->GetSession()->SendPacket(i_message);+ if(WorldSession* session = iter->second->GetSession())+ session->SendPacket(i_message); } } }@@ -293,34 +126,11 @@ { for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) {- iter->second->GetSession()->SendPacket(i_message);+ if(WorldSession* session = iter->second->GetSession())+ session->SendPacket(i_message); } } -void-CreatureVisibleMovementNotifier::Visit(PlayerMapType &m)-{- for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- {- if( i_creature.IsVisibleInGridForPlayer(iter->second) )- {- UpdateData update_data;- WorldPacket packet;- i_creature.BuildCreateUpdateBlockForPlayer(&update_data, iter->second);- update_data.BuildPacket(&packet);- iter->second->GetSession()->SendPacket(&packet);- }- }-}--void-CreatureNotVisibleMovementNotifier::Visit(PlayerMapType &m)-{- for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- if( iter->second->isAlive() )- iter->second->SendOutOfRange(&i_creature);-}- template<class T> void ObjectUpdater::Visit(std::map<OBJECT_HANDLE, T *> &m) {@@ -339,11 +149,5 @@ } } -template void VisibleNotifier::Visit<Corpse>(CorpseMapType &);-template void VisibleNotifier::Visit<DynamicObject>(DynamicObjectMapType &);--template void NotVisibleNotifier::Visit<Corpse>(CorpseMapType &);-template void NotVisibleNotifier::Visit<DynamicObject>(DynamicObjectMapType &);- template void ObjectUpdater::Visit<GameObject>(GameObjectMapType &); template void ObjectUpdater::Visit<DynamicObject>(DynamicObjectMapType &);Index: src/game/GridNotifiers.h===================================================================--- src/game/GridNotifiers.h (revision 3914)+++ src/game/GridNotifiers.h (working copy)@@ -43,7 +43,6 @@ void Visit(PlayerMapType &); template<class SKIP> void Visit(std::map<OBJECT_HANDLE, SKIP *> &) {} template<class SKIP> void Visit(std::map<OBJECT_HANDLE, CountedPtr<SKIP> > &m) {}- void BuildForMySelf(void); Player &i_player; }; @@ -51,61 +50,24 @@ { Player &i_player; UpdateData i_data;- UpdateDataMapType i_updateDatas;+ UpdateDataMapType i_data_updates;+ Player::ClientGUIDs i_clientGUIDs; - explicit VisibleNotifier(Player &player) : i_player(player) {}+ explicit VisibleNotifier(Player &player) : i_player(player),i_clientGUIDs(player.m_clientGUIDs) {} template<class T> void Visit(std::map<OBJECT_HANDLE, T *> &m); template<class T> void Visit(std::map<OBJECT_HANDLE, CountedPtr<T> > &m);- void Visit(GameObjectMapType &);+ void Visit(PlayerMapType &); void Notify(void);-- #ifdef WIN32- template<> void VisibleNotifier::Visit(CreatureMapType &);- template<> void VisibleNotifier::Visit(PlayerMapType &);- #endif }; struct MANGOS_DLL_DECL VisibleChangesNotifier {- Player &i_player;- explicit VisibleChangesNotifier(Player &player) : i_player(player) {}- void Visit(PlayerMapType &);- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, SKIP *> &) {}- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, CountedPtr<SKIP> > &m) {}- };-- struct MANGOS_DLL_DECL NotVisibleNotifier- {- Player &i_player;- UpdateData i_data;- explicit NotVisibleNotifier(Player &player) : i_player(player) {}- void Notify(void);- template<class T> void Visit(std::map<OBJECT_HANDLE, T *> &m);- template<class T> void Visit(std::map<OBJECT_HANDLE, CountedPtr<T> > &m);- void Visit(GameObjectMapType &);- void Visit(PlayerMapType &);-- #ifdef WIN32- template<> void NotVisibleNotifier::Visit(CreatureMapType &);- #endif- };-- struct MANGOS_DLL_DECL ObjectVisibleNotifier- { WorldObject &i_object;- explicit ObjectVisibleNotifier(WorldObject &obj) : i_object(obj) {}- void Visit(PlayerMapType &);- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, SKIP *> &) {}- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, CountedPtr<SKIP> > &m) {}- }; - struct MANGOS_DLL_DECL ObjectNotVisibleNotifier- {- WorldObject &i_object;- explicit ObjectNotVisibleNotifier(WorldObject &obj) : i_object(obj) {}+ explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) {}+ template<class T> void Visit(std::map<OBJECT_HANDLE, T *> &m) {}+ template<class T> void Visit(std::map<OBJECT_HANDLE, CountedPtr<T> > &m) {} void Visit(PlayerMapType &);- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, SKIP *> &) {}- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, CountedPtr<SKIP> > &m) {} }; struct MANGOS_DLL_DECL GridUpdater@@ -154,24 +116,6 @@ template<class SKIP> void Visit(std::map<OBJECT_HANDLE, CountedPtr<SKIP> > &m) {} }; - struct MANGOS_DLL_DECL CreatureVisibleMovementNotifier- {- Creature &i_creature;- explicit CreatureVisibleMovementNotifier(Creature &creature) : i_creature(creature) {}- void Visit(PlayerMapType &m);- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, SKIP *> &) {}- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, CountedPtr<SKIP> > &m) {}- };-- struct MANGOS_DLL_DECL CreatureNotVisibleMovementNotifier- {- Creature &i_creature;- explicit CreatureNotVisibleMovementNotifier(Creature &creature) : i_creature(creature) {}- void Visit(PlayerMapType &m);- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, SKIP *> &) {}- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, CountedPtr<SKIP> > &m) {}- };- struct MANGOS_DLL_DECL ObjectUpdater { uint32 i_timeDiff;@@ -236,10 +180,8 @@ PlayerRelocationNotifier(Player &pl) : i_player(pl) {} template<class T> void Visit(std::map<OBJECT_HANDLE, T *> &m) {} template<class T> void Visit(std::map<OBJECT_HANDLE, CountedPtr<T> > &m) {}- #ifdef WIN32- template<> void Visit(PlayerMapType &);- template<> void Visit(CreatureMapType &);- #endif+ void Visit(PlayerMapType &);+ void Visit(CreatureMapType &); }; struct MANGOS_DLL_DECL CreatureRelocationNotifier@@ -528,17 +470,14 @@ float i_range; }; - class AnyDeadUnitCheck+ struct AnyDeadUnitCheck {- public:- AnyDeadUnitCheck() {}- bool operator()(Unit* u)- {- if(!u->isAlive())- return true;+ bool operator()(Unit* u) { return !u->isAlive(); }+ }; - return false;- }+ struct AnyStealthedCheck+ {+ bool operator()(Unit* u) { return u->GetVisibility()==VISIBILITY_GROUP_STEALTH; } }; class CannibalizeUnitCheck@@ -590,9 +529,6 @@ }; #ifndef WIN32- template<> void VisibleNotifier::Visit<Creature>(CreatureMapType &);- template<> void VisibleNotifier::Visit<Player>(PlayerMapType &);- template<> void NotVisibleNotifier::Visit<Creature>(CreatureMapType &); template<> void PlayerRelocationNotifier::Visit<Creature>(CreatureMapType &); template<> void PlayerRelocationNotifier::Visit<Player>(PlayerMapType &); template<> void CreatureRelocationNotifier::Visit<Player>(PlayerMapType &);Index: src/game/GridNotifiersImpl.h===================================================================--- src/game/GridNotifiersImpl.h (revision 3914)+++ src/game/GridNotifiersImpl.h (working copy)@@ -27,56 +27,25 @@ #include "CreatureAI.h" #include "SpellAuras.h" -template<>+template<class T> inline void-MaNGOS::NotVisibleNotifier::Visit(CreatureMapType &m)+MaNGOS::VisibleNotifier::Visit(std::map<OBJECT_HANDLE, T *> &m) {- for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- if( ( i_player.isAlive() && iter->second->isAlive()) ||- (i_player.isDead() && iter->second->isDead()) )- iter->second->BuildOutOfRangeUpdateBlock(&i_data);-}--template<>-inline void-MaNGOS::VisibleNotifier::Visit(CreatureMapType &m)-{- for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter)+ for(typename std::map<OBJECT_HANDLE, T *>::iterator iter=m.begin(); iter != m.end(); ++iter) {- if( iter->second->IsVisibleInGridForPlayer(&i_player) )- {- iter->second->BuildUpdate(i_updateDatas);- iter->second->BuildCreateUpdateBlockForPlayer(&i_data, &i_player);- }- else- {- iter->second->DestroyForPlayer(&i_player);- }+ i_player.UpdateVisibilityOf(iter->second,i_data,i_data_updates);+ i_clientGUIDs.erase(iter->second->GetGUID()); } } -template<>+template<class T> inline void-MaNGOS::VisibleNotifier::Visit(PlayerMapType &m)+MaNGOS::VisibleNotifier::Visit(std::map<OBJECT_HANDLE, CountedPtr<T> > &m) {- for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)+ for(typename std::map<OBJECT_HANDLE, CountedPtr<T> >::iterator iter=m.begin(); iter != m.end(); ++iter) {- if( iter->second == &i_player )- continue;-- if( (i_player.isAlive() && iter->second->isAlive()) ||- (i_player.isDead() && iter->second->isDead()) )- {- if (iter->second->isVisibleFor(&i_player,false))- iter->second->SendUpdateToPlayer(&i_player);- if (i_player.isVisibleFor(iter->second,false))- i_player.SendUpdateToPlayer(iter->second);- }- else- {- i_player.DestroyForPlayer(iter->second);- iter->second->DestroyForPlayer(&i_player);- }+ i_player.UpdateVisibilityOf(&*iter->second,i_data,i_data_updates);+ i_clientGUIDs.erase(iter->second->GetGUID()); } } @@ -88,41 +57,27 @@ iter->second->Update(i_timeDiff); } -template<> inline void MaNGOS::PlayerRelocationNotifier::Visit(PlayerMapType &m) {- if(!i_player.isAlive() || i_player.isInFlight())- return;- for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) {- // Remove selection- if(i_player.GetSelection()==iter->second->GetGUID())- // visibility distance- if(!i_player.IsWithinDistInMap(iter->second, 160))- // valor under 160 can generate a bug of visibility, as a player- i_player.SendOutOfRange(iter->second); // can reach 158 yards until it disapears, without been selected+ if(&i_player==iter->second)+ continue; - if(iter->second->GetSelection()==i_player.GetGUID())- // visibility distance- if(!i_player.IsWithinDistInMap(iter->second, 160))- iter->second->SendOutOfRange(&i_player);+ // visibility for players updated by ObjectAccessor::UpdateVisibilityFor calls in appropriate places // Cancel Trade if(i_player.GetTrader()==iter->second) if(!i_player.IsWithinDistInMap(iter->second, 5)) // iteraction distance i_player.GetSession()->SendCancelTrade(); // will clode both side trade windows- } } inline void PlayerCreatureRelocationWorker(Player* pl, Creature* c) {- // Remove selection- if(pl->GetSelection()==c->GetGUID())- if(!pl->IsWithinDistInMap(c, 160)) // visibility distance- pl->SendOutOfRange(c);+ // update creature visibility at player/creature move+ pl->UpdateVisibilityOf(c); // Creature AI reaction if( c->AI() && c->AI()->IsVisible(pl) )@@ -138,7 +93,6 @@ c2->AI()->MoveInLineOfSight(c1); } -template<> inline void MaNGOS::PlayerRelocationNotifier::Visit(CreatureMapType &m) {@@ -146,7 +100,7 @@ return; for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- if( iter->second->isAlive() && !iter->second->isInFlight())+ if( iter->second->isAlive()) PlayerCreatureRelocationWorker(&i_player,iter->second); } @@ -154,7 +108,7 @@ inline void MaNGOS::CreatureRelocationNotifier::Visit(PlayerMapType &m) {- if(!i_creature.isAlive() || i_creature.isInFlight())+ if(!i_creature.isAlive()) return; for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)@@ -166,11 +120,11 @@ inline void MaNGOS::CreatureRelocationNotifier::Visit(CreatureMapType &m) {- if(!i_creature.isAlive() || i_creature.isInFlight())+ if(!i_creature.isAlive()) return; for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- if( iter->second->isAlive() && !iter->second->isInFlight())+ if( iter->second->isAlive()) CreatureCreatureRelocationWorker(iter->second, &i_creature); } Index: src/game/GuardAI.cpp===================================================================--- src/game/GuardAI.cpp (revision 3914)+++ src/game/GuardAI.cpp (working copy)@@ -150,7 +150,7 @@ assert((i_victimGuid != 0) == (i_creature.getVictim() != NULL) && "i_victimGuid and i_creature.getVictim() not synchronized."); - if( i_creature.IsWithinDistInMap(i_creature.getVictim(), ATTACK_DIST))+ if( i_creature.IsWithinDistInMap(i_creature.getVictim(), OBJECT_ATTACK_DIST)) { if( i_creature.isAttackReady() ) {@@ -164,7 +164,7 @@ bool GuardAI::IsVisible(Unit *pl) const { return i_creature.GetDistanceSq(pl) < sWorld.getConfig(CONFIG_SIGHT_GUARDER)- && pl->isVisibleFor(&i_creature,true);+ && pl->isVisibleForOrDetect(&i_creature,true); } void GuardAI::AttackStart(Unit *u)Index: src/game/HomeMovementGenerator.cpp===================================================================--- src/game/HomeMovementGenerator.cpp (revision 3914)+++ src/game/HomeMovementGenerator.cpp (working copy)@@ -20,9 +20,7 @@ #include "Creature.h" #include "Traveller.h" #include "MapManager.h"-#include "RedZoneDistrict.h"-#include "CellImpl.h"-#include "GridNotifiersImpl.h"+#include "ObjectAccessor.h" #include "DestinationHolderImp.h" void@@ -63,15 +61,8 @@ if (owner.GetTypeId() == TYPEID_UNIT) {- sLog.outDebug("HomeMovementGenerator::_reLocate() called, where Unit.GetGUIDLow()=%d", owner.GetGUIDLow());- CellPair p = MaNGOS::ComputeCellPair(owner.GetPositionX(), owner.GetPositionY());- Cell cell = RedZone::GetZone(p);- cell.data.Part.reserved = ALL_DISTRICT;- MaNGOS::CreatureVisibleMovementNotifier notifier(owner);- TypeContainerVisitor<MaNGOS::CreatureVisibleMovementNotifier, WorldTypeMapContainer > player_notifier(notifier);- CellLock<GridReadGuard> cell_lock(cell, p);- cell_lock->Visit(cell_lock, player_notifier, *MapManager::Instance().GetMap(owner.GetMapId(), &owner));+ ObjectAccessor::UpdateObjectVisibility(&owner); } } Index: src/game/Level0.cpp===================================================================--- src/game/Level0.cpp (revision 3914)+++ src/game/Level0.cpp (working copy)@@ -186,7 +186,7 @@ for(ObjectAccessor::PlayersMapType::iterator itr = m.begin(); itr != m.end(); ++itr) { if( itr->second->GetSession()->GetSecurity() && (itr->second->isGameMaster() || sWorld.getConfig(CONFIG_GM_IN_GM_LIST) ) &&- itr->second->isVisibleFor(m_session->GetPlayer(),false) )+ itr->second->isVisibleFor(m_session->GetPlayer()) ) { if(first) {Index: src/game/Level1.cpp===================================================================--- src/game/Level1.cpp (revision 3914)+++ src/game/Level1.cpp (working copy)@@ -247,7 +247,7 @@ PSendSysMessage(LANG_SUMMONING, chr->GetName(),""); - if (m_session->GetPlayer()->isVisibleFor(chr,false))+ if (m_session->GetPlayer()->isVisibleFor(chr)) { char buf0[256]; snprintf((char*)buf0,256,LANG_SUMMONED_BY, m_session->GetPlayer()->GetName());@@ -342,7 +342,7 @@ PSendSysMessage(LANG_APPEARING_AT, chr->GetName()); - if (_player->isVisibleFor(chr,false))+ if (_player->isVisibleFor(chr)) { char buf0[256]; sprintf((char*)buf0,LANG_APPEARING_TO, _player->GetName());@@ -1663,7 +1663,7 @@ PSendSysMessage(LANG_TELEPORTING_TO, chr->GetName(),"", location.c_str()); - if (m_session->GetPlayer()->isVisibleFor(chr,false))+ if (m_session->GetPlayer()->isVisibleFor(chr)) { WorldPacket data; char buf0[256];Index: src/game/Map.cpp===================================================================--- src/game/Map.cpp (revision 3914)+++ src/game/Map.cpp (working copy)@@ -422,22 +422,6 @@ } } -void-Map::NotifyPlayerVisibility(const Cell &cell, const CellPair &cell_pair, Player *player)-{- MaNGOS::PlayerNotifier pl_notifier(*player);- MaNGOS::VisibleNotifier obj_notifier(*player);- TypeContainerVisitor<MaNGOS::PlayerNotifier, WorldTypeMapContainer > player_notifier(pl_notifier);- TypeContainerVisitor<MaNGOS::VisibleNotifier, WorldTypeMapContainer > world_object_notifier(obj_notifier);- TypeContainerVisitor<MaNGOS::VisibleNotifier, GridTypeMapContainer > grid_object_notifier(obj_notifier);-- CellLock<ReadGuard> cell_lock(cell, cell_pair);- cell_lock->Visit(cell_lock, player_notifier, *this);- cell_lock->Visit(cell_lock, world_object_notifier, *this);- cell_lock->Visit(cell_lock, grid_object_notifier, *this);- obj_notifier.Notify();-}- bool Map::AddInstanced(Player *player) { if (!Instanceable())@@ -553,19 +537,23 @@ void Map::Add(Player *player) {- CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY());-- assert( player && p.x_coord >= 0 && p.x_coord < TOTAL_NUMBER_OF_CELLS_PER_MAP &&- p.y_coord >= 0 && p.y_coord < TOTAL_NUMBER_OF_CELLS_PER_MAP );- if (player->GetPet()) player->GetPet()->SetInstanceId(this->GetInstanceId()); player->SetInstanceId(this->GetInstanceId()); + SendInitSelf(player);++ player->AddToWorld();++ SendInitTransports(player);++ // update player state for other player and visa-versa+ CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); Cell cell = RedZone::GetZone(p); EnsureGridLoadedForPlayer(cell, player, true);- cell.data.Part.reserved = ALL_DISTRICT;- NotifyPlayerVisibility(cell, p, player); + UpdatePlayerVisibility(player,cell,p);+ UpdateObjectsVisibilityFor(player,cell,p);+ // reinitialize reset time InitResetTime(); }@@ -592,14 +580,8 @@ AddToGrid(obj,grid,cell); DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY());- cell.data.Part.reserved = ALL_DISTRICT;- cell.SetNoCreate(); // not create cells at object add notifier (if player near then cell will already loaded) - MaNGOS::ObjectVisibleNotifier notifier(*static_cast<WorldObject *>(obj));- TypeContainerVisitor<MaNGOS::ObjectVisibleNotifier, WorldTypeMapContainer > player_notifier(notifier);-- CellLock<ReadGuard> cell_lock(cell, p);- cell_lock->Visit(cell_lock, player_notifier, *this);+ UpdateObjectVisibility(obj,cell,p); } template<class T>@@ -622,15 +604,10 @@ assert( grid != NULL ); AddToGrid(obj,grid,cell);+ obj->AddToWorld(); DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY());- cell.data.Part.reserved = ALL_DISTRICT;-- MaNGOS::ObjectVisibleNotifier notifier(*static_cast<WorldObject *>(&(*obj)));- TypeContainerVisitor<MaNGOS::ObjectVisibleNotifier, WorldTypeMapContainer > player_notifier(notifier);-- CellLock<ReadGuard> cell_lock(cell, p);- cell_lock->Visit(cell_lock, player_notifier, *this);+ UpdateObjectVisibility(&*obj,cell,p); } template<class T>@@ -856,12 +833,7 @@ RemoveFromGrid(player,grid,cell); player->RemoveFromWorld(); - cell.data.Part.reserved = ALL_DISTRICT;- MaNGOS::NotVisibleNotifier notifier(*player);- TypeContainerVisitor<MaNGOS::NotVisibleNotifier, WorldTypeMapContainer > player_notifier(notifier);- CellLock<ReadGuard> cell_lock(cell, p);- cell_lock->Visit(cell_lock, player_notifier, *this);- notifier.Notify();+ UpdateObjectsVisibilityFor(player,cell,p); if( remove ) DeleteFromWorld(player);@@ -903,16 +875,9 @@ assert( grid != NULL ); RemoveFromGrid(obj,grid,cell);+ obj->RemoveFromWorld(); - {- Cell cell = RedZone::GetZone(p);- cell.data.Part.reserved = ALL_DISTRICT;- cell.SetNoCreate(); // not create cells at object remove- MaNGOS::ObjectNotVisibleNotifier notifier(*static_cast<WorldObject *>(obj));- TypeContainerVisitor<MaNGOS::ObjectNotVisibleNotifier, WorldTypeMapContainer > player_notifier(notifier);- CellLock<ReadGuard> cell_lock(cell, p);- cell_lock->Visit(cell_lock, player_notifier, *this);- }+ UpdateObjectVisibility(obj,cell,p); if( remove ) {@@ -943,15 +908,9 @@ assert( grid != NULL ); RemoveFromGrid(obj,grid,cell);+ obj->RemoveFromWorld(); - {- Cell cell = RedZone::GetZone(p);- cell.data.Part.reserved = ALL_DISTRICT;- MaNGOS::ObjectNotVisibleNotifier notifier(*static_cast<WorldObject *>(&*obj));- TypeContainerVisitor<MaNGOS::ObjectNotVisibleNotifier, WorldTypeMapContainer > player_notifier(notifier);- CellLock<ReadGuard> cell_lock(cell, p);- cell_lock->Visit(cell_lock, player_notifier, *this);- }+ UpdateObjectVisibility(&*obj,cell,p); if( remove ) {@@ -963,7 +922,7 @@ } void-Map::PlayerRelocation(Player *player, float x, float y, float z, float orientation, bool visibilityChanges )+Map::PlayerRelocation(Player *player, float x, float y, float z, float orientation) { assert(player); @@ -974,6 +933,7 @@ Cell new_cell = RedZone::GetZone(new_val); new_cell |= old_cell; bool same_cell = (new_cell == old_cell);+ player->Relocate(x, y, z, orientation); if( old_cell.DiffGrid(new_cell) || old_cell.DiffCell(new_cell) )@@ -995,54 +955,13 @@ EnsureGridLoadedForPlayer(new_cell, player, true); } - CellLock<ReadGuard> cell_lock(new_cell, new_val);+ // if move then update what player see and who seen+ UpdatePlayerVisibility(player,new_cell,new_val);+ UpdateObjectsVisibilityFor(player,new_cell,new_val);+ PlayerRelocationNotify(player,new_cell,new_val); - MaNGOS::VisibleNotifier notifier(*player);-- if( !same_cell || player->IsBeingTeleported() )- {- if( player->IsBeingTeleported() )- new_cell.data.Part.reserved = ALL_DISTRICT;-- TypeContainerVisitor<MaNGOS::VisibleNotifier, WorldTypeMapContainer > world_object_notifier(notifier);- TypeContainerVisitor<MaNGOS::VisibleNotifier, GridTypeMapContainer > grid_object_notifier(notifier);-- cell_lock->Visit(cell_lock, world_object_notifier, *this);- cell_lock->Visit(cell_lock, grid_object_notifier, *this);-- notifier.Notify();- }-- MaNGOS::PlayerRelocationNotifier relocationNotifier(*player);- new_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);- cell_lock->Visit(cell_lock, p2world_relocation, *this);-- if (visibilityChanges)- {- MaNGOS::VisibleChangesNotifier visualChangesNotifier(*player);- TypeContainerVisitor<MaNGOS::VisibleChangesNotifier, WorldTypeMapContainer > player_Vnotifier(visualChangesNotifier);- cell_lock->Visit(cell_lock, player_Vnotifier, *this);- }-- if( same_cell )- return;-- MaNGOS::NotVisibleNotifier notifier2(*player);- TypeContainerVisitor<MaNGOS::NotVisibleNotifier, WorldTypeMapContainer > world_object_notifier2(notifier2);- TypeContainerVisitor<MaNGOS::NotVisibleNotifier, GridTypeMapContainer > grid_object_notifier2(notifier2);-- cell_lock = CellLock<ReadGuard>(old_cell, old_val);-- cell_lock->Visit(cell_lock, world_object_notifier2, *this);- cell_lock->Visit(cell_lock, grid_object_notifier2, *this);-- i_grids[new_cell.GridX()][new_cell.GridY()]->SetGridState(GRID_STATE_ACTIVE);- notifier2.Notify();+ if( !same_cell )+ i_grids[new_cell.GridX()][new_cell.GridY()]->SetGridState(GRID_STATE_ACTIVE); } void@@ -1068,28 +987,11 @@ else { creature->Relocate(x, y, z, ang);- CreatureRelocationNotifying(creature,new_cell,new_val);+ CreatureRelocationNotify(creature,new_cell,new_val); } assert(CheckGridIntegrity(creature,true)); } -void Map::CreatureRelocationNotifying(Creature *creature, Cell new_cell, CellPair new_val)-{- if( !creature->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))- {- CellLock<ReadGuard> cell_lock(new_cell, new_val);- MaNGOS::CreatureRelocationNotifier relocationNotifier(*creature);- new_cell.data.Part.reserved = ALL_DISTRICT;- new_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);- cell_lock->Visit(cell_lock, c2grid_relocation, *this);- }-}- void Map::AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang) { if(!c) return;@@ -1116,7 +1018,7 @@ { // update pos c->Relocate(cm.x, cm.y, cm.z, cm.ang);- CreatureRelocationNotifying(c,new_cell,new_cell.cellPair());+ CreatureRelocationNotify(c,new_cell,new_cell.cellPair()); } else {@@ -1212,7 +1114,7 @@ { c->Relocate(resp_x, resp_y, resp_z, c->GetOrientation()); (*c)->Initialize(); // prevent possible problems with default move generators- CreatureRelocationNotifying(c,resp_cell,resp_cell.cellPair());+ CreatureRelocationNotify(c,resp_cell,resp_cell.cellPair()); return true; } else@@ -1496,6 +1398,112 @@ return i_mapEntry ? i_mapEntry->name[sWorld.GetDBClang()] : "UNNAMEDMAP\x0"; } +void Map::UpdateObjectVisibility( WorldObject* obj, Cell cell, CellPair cellpair)+{+ cell.data.Part.reserved = ALL_DISTRICT;+ cell.SetNoCreate();+ MaNGOS::VisibleChangesNotifier notifier(*obj);+ TypeContainerVisitor<MaNGOS::VisibleChangesNotifier, WorldTypeMapContainer > player_notifier(notifier);+ CellLock<GridReadGuard> cell_lock(cell, cellpair);+ cell_lock->Visit(cell_lock, player_notifier, *MapManager::Instance().GetMap(obj->GetMapId(), obj));+}++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);+}++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, *MapManager::Instance().GetMap(player->GetMapId(), player));+ cell_lock->Visit(cell_lock, grid_notifier, *MapManager::Instance().GetMap(player->GetMapId(), player));++ // 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);+ cell_lock->Visit(cell_lock, p2world_relocation, *this);+}++void Map::CreatureRelocationNotify(Creature *creature, Cell cell, CellPair cellpair)+{+ if(creature->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))+ return;++ 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);+ cell_lock->Visit(cell_lock, c2grid_relocation, *this);+}++void Map::SendInitSelf( Player * player )+{+ // build data for self presence in world at own client (one time for map)+ UpdateData data;++ Transport *t = player->GetTransport();+ if (t)+ {+ t->BuildCreateUpdateBlockForPlayer(&data, player);+ }++ sLog.outDetail("Creating player data for himself %u", player->GetGUIDLow());+ player->BuildCreateUpdateBlockForPlayer(&data, player);++ WorldPacket packet;+ data.BuildPacket(&packet);+ player->GetSession()->SendPacket(&packet);+}++void Map::SendInitTransports( Player * player )+{+ // Hack to send out transports+ if (MapManager::Instance().m_TransportsByMap.find(player->GetMapId()) == MapManager::Instance().m_TransportsByMap.end())+ return;++ UpdateData transData;++ for (size_t i = 0; i < MapManager::Instance().m_TransportsByMap[player->GetMapId()].size(); ++i)+ {+ Transport *t = MapManager::Instance().m_TransportsByMap[player->GetMapId()][i];+ t->BuildCreateUpdateBlockForPlayer(&transData, player);+ }++ WorldPacket packet;+ transData.BuildPacket(&packet);+ player->GetSession()->SendPacket(&packet);+}+ template void Map::Add(CorpsePtr&); template void Map::Add(Creature *); template void Map::Add(GameObject *);Index: src/game/Map.h===================================================================--- src/game/Map.h (revision 3914)+++ src/game/Map.h (working copy)@@ -105,6 +105,7 @@ template<class T> T* GetObjectNear(float x, float y, OBJECT_HANDLE hdl, T*); template<class T> void Add(CountedPtr<T>&);+ template<class T> void Remove(CountedPtr<T>&, bool); template<class T> bool Find(CountedPtr<T>&) const; @@ -117,7 +118,7 @@ void MessageBoardcast(WorldObject *, WorldPacket *); - void PlayerRelocation(Player *, float x, float y, float z, float angl, bool visibilityChanges = false);+ void PlayerRelocation(Player *, float x, float y, float z, float angl); void CreatureRelocation(Creature *creature, float x, float y, float, float); @@ -203,19 +204,26 @@ std::bitset<TOTAL_NUMBER_OF_CELLS_PER_MAP*TOTAL_NUMBER_OF_CELLS_PER_MAP> marked_cells; + void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair);+ void UpdatePlayerVisibility(Player* player, Cell cell, CellPair cellpair);+ void UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair); private: void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; } uint64 CalculateGridMask(const uint32 &y) const; + void SendInitSelf( Player * player );+ void SendInitTransports( Player * player );++ void PlayerRelocationNotify(Player* player, Cell cell, CellPair cellpair);+ bool CreatureCellRelocation(Creature *creature, Cell new_cell);- void CreatureRelocationNotifying(Creature *creature, Cell newcell, CellPair newval);+ void CreatureRelocationNotify(Creature *creature, Cell newcell, CellPair newval); void AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang); CreatureMoveList i_creaturesToMove; bool loaded(const GridPair &) const; void EnsureGridLoadedForPlayer(const Cell&, Player*, bool add_player);- void NotifyPlayerVisibility(const Cell &, const CellPair &, Player *); uint64 EnsureGridCreated(const GridPair &); template<class T> void AddType(T *obj);Index: src/game/MiscHandler.cpp===================================================================--- src/game/MiscHandler.cpp (revision 3914)+++ src/game/MiscHandler.cpp (working copy)@@ -166,7 +166,7 @@ (guild_name.length()?strstr(gname.c_str(), guild_name.c_str())!=0 : true) && (player_name.length()?strstr(pname, player_name.c_str())!=0 : true) && z_show && s_show &&- (itr->second->GetSession()->GetSecurity() == 0 || gmInWhoList && itr->second->isVisibleFor(_player,false) )))+ (itr->second->GetSession()->GetSecurity() == 0 || gmInWhoList && itr->second->isVisibleFor(_player) ))) { clientcount++; @@ -569,7 +569,7 @@ if (friendGuid && friendResult==FRIEND_NOT_FOUND) {- if( pfriend && pfriend->IsInWorld() && pfriend->isVisibleFor(GetPlayer(),false))+ if( pfriend && pfriend->IsInWorld() && pfriend->isVisibleFor(GetPlayer())) { friendResult = FRIEND_ADDED_ONLINE; friendArea = pfriend->GetZoneId();Index: src/game/MovementHandler.cpp===================================================================--- src/game/MovementHandler.cpp (revision 3914)+++ src/game/MovementHandler.cpp (working copy)@@ -32,7 +32,7 @@ { sLog.outDebug( "WORLD: got MSG_MOVE_WORLDPORT_ACK." ); - GetPlayer()->RemoveFromWorld();+ MapManager::Instance().GetMap(GetPlayer()->GetMapId(), GetPlayer())->Remove(GetPlayer(),false); MapManager::Instance().GetMap(GetPlayer()->GetMapId(), GetPlayer())->Add(GetPlayer()); WorldPacket data(SMSG_SET_REST_START, 4); data << uint32(time(NULL));//getMSTime();Index: src/game/Object.h===================================================================--- src/game/Object.h (revision 3914)+++ src/game/Object.h (working copy)@@ -31,8 +31,12 @@ #define M_PI 3.14159265358979323846 #endif -#define OBJECT_CONTACT_DISTANCE 0.5+#define OBJECT_CONTACT_DISTANCE 0.5 #define OBJECT_ITERACTION_DISTANCE 5+#define OBJECT_ATTACK_DIST 5+#define OBJECT_DETECT_DISTANCE 20 // max distance to successful detect stealthed unit+#define MAX_OBJECT_VISIBLE_DISTANCE (5*SIZE_OF_GRID_CELL/2) // max distance for visible object show, limited by active zone for player based at cell size (active zone = 5x5 cells)+#define OBJECT_VISIBLE_DISTANCE (SIZE_OF_GRID_CELL) // default visible distance enum TYPE {@@ -296,6 +300,11 @@ uint32 GetInstanceId() const { return m_InstanceId; } void SetInstanceId(uint32 val) { m_InstanceId = val; } + // main visibility check function in normal case (ignore grey zone distance check)+ bool isVisibleFor(Player const* u) const { return isVisibleForInState(u,false); }++ // low level function for visibility change code, must be define in all main world object subclasses+ virtual bool isVisibleForInState(Player const* u, bool inVisibleList) const = 0; protected: WorldObject( WorldObject *instantiator ); Index: src/game/ObjectAccessor.cpp===================================================================--- src/game/ObjectAccessor.cpp (revision 3914)+++ src/game/ObjectAccessor.cpp (working copy)@@ -76,37 +76,6 @@ template<class SKIP> void Visit(std::map<OBJECT_HANDLE, SKIP *> &) {} template<class SKIP> void Visit(std::map<OBJECT_HANDLE, CountedPtr<SKIP> > &) {} };-- struct MANGOS_DLL_DECL CreatureCorpseViewRemover- {- Creature &i_creature;- CreatureCorpseViewRemover(Creature &c) : i_creature(c) {}-- void Visit(PlayerMapType &m)- {- for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- i_creature.DestroyForPlayer(iter->second);- }-- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, SKIP *> &) {}- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, CountedPtr<SKIP> > &) {}- };-- struct MANGOS_DLL_DECL BonesViewRemover- {- CorpsePtr i_objects;-- BonesViewRemover(CorpsePtr& corpse) : i_objects(corpse) {}- - void Visit(PlayerMapType &m)- {- for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)- i_objects->DestroyForPlayer(iter->second);- }- - template<class SKIP> void Visit(std::map<OBJECT_HANDLE, SKIP *> &) {}- template<class SKIP> void Visit(std::map<OBJECT_HANDLE, CountedPtr<SKIP> > &) {}- }; } ObjectAccessor::ObjectAccessor() {}@@ -242,8 +211,6 @@ ObjectAccessor::InsertPlayer(Player *pl) { i_players[pl->GetGUID()] = pl;- _update();- } void@@ -423,9 +390,6 @@ void ObjectAccessor::_buildPacket(Player *pl, Object *obj, UpdateDataMapType &update_players) {- if(obj->isType(TYPE_UNIT) && !((Unit*)obj)->isVisibleFor(pl,false))- return;- UpdateDataMapType::iterator iter = update_players.find(pl); if( iter == update_players.end() )@@ -445,8 +409,8 @@ Cell cell = RedZone::GetZone(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate();- ObjectChangeAccumulator notifier(*obj, update_players);- TypeContainerVisitor<ObjectChangeAccumulator, WorldTypeMapContainer > player_notifier(notifier);+ WorldObjectChangeAccumulator notifier(*obj, update_players);+ TypeContainerVisitor<WorldObjectChangeAccumulator, WorldTypeMapContainer > player_notifier(notifier); CellLock<GridReadGuard> cell_lock(cell, p); cell_lock->Visit(cell_lock, player_notifier, *MapManager::Instance().GetMap(obj->GetMapId(), obj)); }@@ -662,34 +626,28 @@ } void-ObjectAccessor::ObjectChangeAccumulator::Visit(PlayerMapType &m)+ObjectAccessor::WorldObjectChangeAccumulator::Visit(PlayerMapType &m) { for(PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)- ObjectAccessor::_buildPacket(iter->second, &i_object, i_updateDatas);+ if(iter->second->HaveAtClient(&i_object))+ ObjectAccessor::_buildPacket(iter->second, &i_object, i_updateDatas); } void-ObjectAccessor::RemoveCreatureCorpseFromPlayerView(Creature *c)+ObjectAccessor::UpdateObjectVisibility(WorldObject *obj) {- MaNGOS::CreatureCorpseViewRemover remover(*c);- TypeContainerVisitor<MaNGOS::CreatureCorpseViewRemover, WorldTypeMapContainer > player_notifier(remover);- CellPair p = MaNGOS::ComputeCellPair(c->GetPositionX(), c->GetPositionY());+ CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); Cell cell = RedZone::GetZone(p);- cell.SetNoCreate();- cell.data.Part.reserved = ALL_DISTRICT;- CellLock<GridReadGuard> cell_lock(cell, p);- cell_lock->Visit(cell_lock, player_notifier, *MapManager::Instance().GetMap(c->GetMapId(), c));++ MapManager::Instance().GetMap(obj->GetMapId(), obj)->UpdateObjectVisibility(obj,cell,p); } -void-ObjectAccessor::RemoveBonesFromPlayerView(CorpsePtr& corpse)+void ObjectAccessor::UpdateVisibilityForPlayer( Player* player ) {- MaNGOS::BonesViewRemover remover(corpse);- TypeContainerVisitor<MaNGOS::BonesViewRemover, WorldTypeMapContainer > player_notifier(remover);- CellPair p = MaNGOS::ComputeCellPair(corpse->GetPositionX(), corpse->GetPositionY());+ CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); Cell cell = RedZone::GetZone(p);- cell.SetNoCreate();- cell.data.Part.reserved = ALL_DISTRICT;- CellLock<GridReadGuard> cell_lock(cell, p);- cell_lock->Visit(cell_lock, player_notifier, *MapManager::Instance().GetMap(corpse->GetMapId(), &(*corpse)));+ Map* m = MapManager::Instance().GetMap(player->GetMapId(),player);++ m->UpdatePlayerVisibility(player,cell,p);+ m->UpdateObjectsVisibilityFor(player,cell,p); }Index: src/game/ObjectAccessor.h===================================================================--- src/game/ObjectAccessor.h (revision 3914)+++ src/game/ObjectAccessor.h (working copy)@@ -81,9 +81,6 @@ void DoDelayedMovesAndRemoves(); - void RemoveCreatureCorpseFromPlayerView(Creature *);- void RemoveBonesFromPlayerView(CorpsePtr&);- void Update(const uint32 &diff); CorpsePtr& GetCorpseForPlayerGUID(uint64 guid);@@ -100,21 +97,24 @@ bool PlayersNearGrid(const uint32 &x, const uint32 &y, const uint32 &m_id, const uint32 &i_id) const; static void UpdateObject(Object* obj, Player* exceptPlayer);- static void _buildUpdateObject(Object *, UpdateDataMapType &);+ static void _buildUpdateObject(Object* obj, UpdateDataMapType &);++ static void UpdateObjectVisibility(WorldObject* obj);+ static void UpdateVisibilityForPlayer(Player* player); private: void RemoveAllObjectsInRemoveList(); - struct ObjectChangeAccumulator+ struct WorldObjectChangeAccumulator { UpdateDataMapType &i_updateDatas;- Object &i_object;- ObjectChangeAccumulator(Object &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj) {}+ WorldObject &i_object;+ WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj) {} void Visit(PlayerMapType &); template<class SKIP> void Visit(std::map<OBJECT_HANDLE, SKIP *> &) {} template<class SKIP> void Visit(std::map<OBJECT_HANDLE, CountedPtr<SKIP> > &) {} }; - friend struct ObjectChangeAccumulator;+ friend struct WorldObjectChangeAccumulator; PlayersMapType i_players; PetsMapType i_pets; Player2CorpsesMapType i_player2corpse;Index: src/game/PetAI.cpp===================================================================--- src/game/PetAI.cpp (revision 3914)+++ src/game/PetAI.cpp (working copy)@@ -179,7 +179,7 @@ _stopAttack(); // i_victimGuid == 0 && i_pet.getVictim() == NULL now return; }- else if( i_pet.IsStopped() || i_pet.IsWithinDistInMap(i_pet.getVictim(), ATTACK_DIST))+ else if( i_pet.IsStopped() || i_pet.IsWithinDistInMap(i_pet.getVictim(), OBJECT_ATTACK_DIST)) { SpellEntry const* spellInfo; // required to be stopped casesIndex: src/game/Player.cpp===================================================================--- src/game/Player.cpp (revision 3914)+++ src/game/Player.cpp (working copy)@@ -36,6 +36,10 @@ #include "Chat.h" #include "MapManager.h" #include "MapInstanced.h"+#include "RedZoneDistrict.h"+#include "GridNotifiers.h"+#include "GridNotifiersImpl.h"+#include "CellImpl.h" #include "ObjectMgr.h" #include "ObjectAccessor.h" #include "CreatureAI.h"@@ -160,8 +164,6 @@ m_resurrectingSicknessExpire = 0; m_DetectInvTimer = 1000;- m_DiscoveredPj = 0;- m_enableDetect = true; m_bgBattleGroundID = 0; m_bgBattleGroundQueueID = 0;@@ -755,7 +757,7 @@ // default combat reach 10 // TODO add weapon,skill check - float pldistance = ATTACK_DIST;+ float pldistance = OBJECT_ATTACK_DIST; if (isAttackReady(BASE_ATTACK)) {@@ -902,13 +904,13 @@ //Handle lava HandleLava(); - //Handle detect invisible players+ //Handle detect stealth players if (m_DetectInvTimer > 0) { if (p_time >= m_DetectInvTimer) { m_DetectInvTimer = 3000;- HandleInvisiblePjs();+ HandleStealthedUnitsDetection(); } else m_DetectInvTimer -= p_time;@@ -1174,7 +1176,7 @@ if( pObj && pObj->GetName() && ( security > 0 || ( pObj->GetTeam() == team || allowTwoSideWhoList ) &&- (pObj->GetSession()->GetSecurity() == 0 || gmInWhoList && pObj->isVisibleFor(this,false) )))+ (pObj->GetSession()->GetSecurity() == 0 || gmInWhoList && pObj->isVisibleFor(this) ))) { if(pObj->isAFK()) friendstr[i].Status = 2;@@ -1352,7 +1354,7 @@ WorldPacket data; BuildTeleportAckMsg(&data, x, y, z, orientation); GetSession()->SendPacket(&data);- SetPosition( x, y, z, orientation );+ SetPosition( x, y, z, orientation, true); BuildHeartBeatMsg(&data); SendMessageToSet(&data, true); }@@ -1403,20 +1405,27 @@ data << uint32(0); GetSession()->SendPacket( &data ); - SetMapId(mapid);+ // new final coordinates+ float final_x = x;+ float final_y = y;+ float final_z = z;+ float final_o = orientation; - // orientation+0.1 used to pressure SetPosition send notifiers at teleportaion like in normal move case if(m_transport) {- Relocate(x + m_transX, y + m_transY, z + m_transZ, orientation + m_transO+0.1);- SetPosition(x + m_transX, y + m_transY, z + m_transZ, orientation + m_transO);+ final_x += m_transX;+ final_y += m_transY;+ final_z += m_transZ;+ final_o += m_transO; }- else- {- Relocate(x, y, z, orientation+0.1);- SetPosition(x, y, z, orientation);- } + // set position+ SetMapId(mapid);+ Relocate(final_x, final_y, final_z,final_o);++ // move packet sent by client always after far teleport+ // SetPosition(final_x, final_y, final_z, final_o, true);+ // resurrect character at enter into instance where his corpse exist CorpsePtr corpse = GetCorpse(); if (corpse && corpse->GetType() == CORPSE_RESURRECTABLE && corpse->GetMapId() == mapid)@@ -1450,14 +1459,6 @@ { CombatStop(); - // remove selection- if(GetSelection())- {- Unit* unit = ObjectAccessor::Instance().GetUnit(*this, GetSelection());- if(unit)- SendOutOfRange(unit);- }- // unsummon pet if lost if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE)) RemovePet(pet, PET_SAVE_NOT_IN_SLOT);@@ -3294,6 +3295,9 @@ // dead player body showed at this moment, corpse will be show at Player ghost repop CreateCorpse();++ // update visibility+ ObjectAccessor::UpdateObjectVisibility(this); } void Player::CreateCorpse()@@ -3606,7 +3610,7 @@ if( pfriend && pfriend->IsInWorld() && ( pfriend->GetSession()->GetSecurity() > 0 || ( pfriend->GetTeam() == team || allowTwoSideWhoList ) &&- (security == 0 || gmInWhoList && isVisibleFor(pfriend,false) )))+ (security == 0 || gmInWhoList && isVisibleFor(pfriend) ))) { pfriend->GetSession()->SendPacket(packet); }@@ -4258,7 +4262,7 @@ m_dontMove = dontMove; } -bool Player::SetPosition(float x, float y, float z, float orientation)+bool Player::SetPosition(float x, float y, float z, float orientation, bool teleport) { Map *m = MapManager::Instance().GetMap(GetMapId(), this); @@ -4266,10 +4270,8 @@ const float old_y = GetPositionY(); const float old_r = GetOrientation(); - if( old_x != x || old_y != y || old_r != orientation)+ if( teleport || old_x != x || old_y != y || old_r != orientation ) {- m->PlayerRelocation(this, x, y, z, orientation);- // remove at movement non-move stealth aura if(HasFlag(UNIT_FIELD_BYTES_1,PLAYER_STATE_FLAG_STEALTH)) RemoveAurasDueToSpell(20580);@@ -4277,14 +4279,17 @@ // remove death simulation at move if(hasUnitState(UNIT_STAT_DIED)) RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);++ // move and update visible state if need+ m->PlayerRelocation(this, x, y, z, orientation);++ // reread after Map::Relocation+ m = MapManager::Instance().GetMap(GetMapId(), this);+ x = GetPositionX();+ y = GetPositionY();+ z = GetPositionZ(); } - // reread after Map::Relocation- m = MapManager::Instance().GetMap(GetMapId(), this);- x = GetPositionX();- y = GetPositionY();- z = GetPositionZ();- float water_z = m->GetWaterLevel(x,y); uint8 flag1 = m->GetTerrainType(x,y); @@ -12331,15 +12336,6 @@ /*** LOW LEVEL FUNCTIONS:Notifiers ***/ /*********************************************************/ -void Player::SendOutOfRange(Object* obj)-{- UpdateData his_data;- WorldPacket his_pk;- obj->BuildOutOfRangeUpdateBlock(&his_data);- his_data.BuildPacket(&his_pk);- GetSession()->SendPacket(&his_pk);-}- inline void Player::SendAttackSwingNotInRange() { WorldPacket data(SMSG_ATTACKSWING_NOTINRANGE, 0);@@ -12939,27 +12935,47 @@ SetUInt32Value(PLAYER_REST_STATE_EXPERIENCE, uint32(m_rest_bonus)); } -void Player::HandleInvisiblePjs()+void Player::HandleStealthedUnitsDetection() {- Map *m = MapManager::Instance().GetMap(GetMapId(), this);+ std::list<Unit*> stealthedUnits; - //this is to be sure that InvisiblePjsNear vector has active pjs only.- m->PlayerRelocation(this, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(), true);+ CellPair p(MaNGOS::ComputeCellPair(GetPositionX(),GetPositionY()));+ Cell cell = RedZone::GetZone(p);+ cell.data.Part.reserved = ALL_DISTRICT;+ cell.SetNoCreate(); - for (std::vector<Player *>::iterator i = InvisiblePjsNear.begin(); i != InvisiblePjsNear.end(); i++)+ MaNGOS::AnyStealthedCheck u_check;+ MaNGOS::UnitListSearcher<MaNGOS::AnyStealthedCheck > searcher(stealthedUnits, u_check);++ TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyStealthedCheck >, WorldTypeMapContainer > world_unit_searcher(searcher);+ TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyStealthedCheck >, GridTypeMapContainer > grid_unit_searcher(searcher);++ CellLock<GridReadGuard> cell_lock(cell, p);+ cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(GetMapId(), this));+ cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(GetMapId(), this));++ for (std::list<Unit*>::iterator i = stealthedUnits.begin(); i != stealthedUnits.end();) {- if ((*i)->isVisibleFor(this,true))+ if((*i)==this) {- m_DiscoveredPj = *i;- m_enableDetect = false;- m->PlayerRelocation(this, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(), true);- m_enableDetect = true;- m_DiscoveredPj = 0;+ i = stealthedUnits.erase(i);+ continue; }++ if ((*i)->isVisibleForOrDetect(this,true))+ {++ (*i)->SendUpdateToPlayer(this);+ m_clientGUIDs.insert((*i)->GetGUID());+ i = stealthedUnits.erase(i);+ continue;+ }++ ++i; }- if (!InvisiblePjsNear.size())++ if(stealthedUnits.empty()) m_DetectInvTimer = 0;- InvisiblePjsNear.clear(); } bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes)@@ -13712,3 +13728,101 @@ } return false; }++bool Player::IsVisibleInGridForPlayer( Player* pl ) const+{+ // Live player see live player or dead player with not realised corpse+ if(pl->isAlive() || pl->m_deathTimer > 0)+ {+ return isAlive() || m_deathTimer > 0;+ }++ // Dead player see live players near own corpse+ if(isAlive())+ {+ CorpsePtr &corpse = pl->GetCorpse();+ if(corpse)+ {+ // 20 - aggro distance for same level, 25 - max additional distance if player level less that creature level+ if(corpse->IsWithinDistInMap(this,(20+25)*sWorld.getRate(RATE_CREATURE_AGGRO)))+ return true;+ }+ }++ // and not see any other+ return false;+}++void Player::UpdateVisibilityOf(WorldObject* target)+{+ if(HaveAtClient(target))+ {+ if(!target->isVisibleForInState(this,true))+ {+ target->DestroyForPlayer(this);+ m_clientGUIDs.erase(target->GetGUID());++ // activate stealth detection system+ if(m_DetectInvTimer==0 && target->isType(TYPE_UNIT) && (+ ((Unit*)target)->GetVisibility()==VISIBILITY_GROUP_STEALTH || + ((Unit*)target)->GetVisibility()==VISIBILITY_GROUP_NO_DETECT ) )+ m_DetectInvTimer = 1;+ }+ }+ else+ {+ if(target->isVisibleForInState(this,false))+ {+ target->SendUpdateToPlayer(this);+ if(target->GetTypeId()!=TYPEID_GAMEOBJECT||!((GameObject*)target)->IsTransport())+ m_clientGUIDs.insert(target->GetGUID());+ }+ }+}++template<class T> +inline void UpdateVisibilityOf_helper(std::set<uint64>& s64, T* target)+{+ s64.insert(target->GetGUID());+}++template<> +inline void UpdateVisibilityOf_helper(std::set<uint64>& s64, GameObject* target)+{+ if(!target->IsTransport())+ s64.insert(target->GetGUID());+}++template<class T>+void Player::UpdateVisibilityOf(T* target, UpdateData& data, UpdateDataMapType& data_updates)+{+ if(HaveAtClient(target))+ {+ if(!target->isVisibleForInState(this,true))+ {+ target->BuildOutOfRangeUpdateBlock(&data);+ m_clientGUIDs.erase(target->GetGUID());++ // activate invisibility detection system+ if(m_DetectInvTimer==0 && target->isType(TYPE_UNIT) && (+ ((Unit*)target)->GetVisibility()==VISIBILITY_GROUP_STEALTH || + ((Unit*)target)->GetVisibility()==VISIBILITY_GROUP_NO_DETECT ) )+ m_DetectInvTimer = 1;+ }+ }+ else+ {+ if(target->isVisibleForInState(this,false))+ {+ target->BuildUpdate(data_updates);+ target->BuildCreateUpdateBlockForPlayer(&data, this);+ UpdateVisibilityOf_helper(m_clientGUIDs,target);+ }+ }+}++template void Player::UpdateVisibilityOf(Player* target, UpdateData& data, UpdateDataMapType& data_updates);+template void Player::UpdateVisibilityOf(Creature* target, UpdateData& data, UpdateDataMapType& data_updates);+template void Player::UpdateVisibilityOf(Corpse* target, UpdateData& data, UpdateDataMapType& data_updates);+template void Player::UpdateVisibilityOf(GameObject* target, UpdateData& data, UpdateDataMapType& data_updates);+template void Player::UpdateVisibilityOf(DynamicObject* target, UpdateData& data, UpdateDataMapType& data_updates);Index: src/game/Player.h===================================================================--- src/game/Player.h (revision 3914)+++ src/game/Player.h (working copy)@@ -1140,7 +1140,6 @@ void DestroyForPlayer( Player *target ) const; void SendDelayResponse(const uint32); void SendLogXPGain(uint32 GivenXP,Unit* victim,uint32 RestXP);- void SendOutOfRange(Object* obj); //Low Level Packets void PlaySound(uint32 Sound, bool OnlySelf);@@ -1156,7 +1155,7 @@ void SendDungeonDifficulty(); void SendAllowMove(); - bool SetPosition(float x, float y, float z, float orientation);+ bool SetPosition(float x, float y, float z, float orientation, bool teleport = false); void SendMessageToSet(WorldPacket *data, bool self);// overwrite Object::SendMessageToSet void SendMessageToOwnTeamSet(WorldPacket *data, bool self); @@ -1341,7 +1340,7 @@ bool IsFlying() const { return HasMovementFlags(MOVEMENTFLAG_FLYING); } // Transports- Transport * GetTransport() { return m_transport; }+ Transport * GetTransport() const { return m_transport; } void SetTransport(Transport * t) { m_transport = t; } void SetTransOffset(float x, float y, float z, float orientation)@@ -1371,12 +1370,22 @@ float m_homebindY; float m_homebindZ; - // Invisibility and detection system- std::vector<Player *> InvisiblePjsNear;- Player* m_DiscoveredPj;+ // currently visible objects at player client + typedef std::set<uint64> ClientGUIDs;+ ClientGUIDs m_clientGUIDs;++ bool HaveAtClient(WorldObject const* u) { return u==this || m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); }++ bool IsVisibleInGridForPlayer(Player* pl) const;++ void UpdateVisibilityOf(WorldObject* target);++ template<class T>+ void UpdateVisibilityOf(T* target, UpdateData& data, UpdateDataMapType& data_updates);++ // Stealth detection system uint32 m_DetectInvTimer;- void HandleInvisiblePjs();- bool m_enableDetect;+ void HandleStealthedUnitsDetection(); void ApplySpeedMod(UnitMoveType mtype, float rate, bool forced, bool apply); // overwrite Unit versionIndex: src/game/ReactorAI.cpp===================================================================--- src/game/ReactorAI.cpp (revision 3914)+++ src/game/ReactorAI.cpp (working copy)@@ -99,7 +99,7 @@ return; } - if( i_creature.IsWithinDistInMap(i_creature.getVictim(), ATTACK_DIST))+ if( i_creature.IsWithinDistInMap(i_creature.getVictim(), OBJECT_ATTACK_DIST)) { if( i_creature.isAttackReady() ) {Index: src/game/SpellAuras.cpp===================================================================--- src/game/SpellAuras.cpp (revision 3914)+++ src/game/SpellAuras.cpp (working copy)@@ -35,8 +35,6 @@ #include "UpdateData.h" #include "MapManager.h" #include "ObjectAccessor.h"-#include "RedZoneDistrict.h"-#include "CellImpl.h" #include "Policies/SingletonImp.h" #include "Totem.h" #include "Creature.h"@@ -69,7 +67,7 @@ &Aura::HandleNoImmediateEffect, // 14 SPELL_AURA_MOD_DAMAGE_TAKEN &Aura::HandleAuraDamageShield, // 15 SPELL_AURA_DAMAGE_SHIELD &Aura::HandleModStealth, // 16 SPELL_AURA_MOD_STEALTH- &Aura::HandleModDetect, // 17 SPELL_AURA_MOD_DETECT+ &Aura::HandleModStealthDetect, // 17 SPELL_AURA_MOD_STEALTH_DETECT &Aura::HandleInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY &Aura::HandleInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION &Aura::HandleAuraModTotalHealthPercentRegen, // 20 SPELL_AURA_OBS_MOD_HEALTH@@ -2017,9 +2015,10 @@ // only at real aura add if(Real) {- m_target->SetVisibility(VISIBILITY_GROUP);+ m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); if(m_target->GetTypeId() == TYPEID_PLAYER) m_target->SendUpdateToPlayer((Player*)m_target);+ m_target->SetVisibility(VISIBILITY_GROUP_STEALTH); // for RACE_NIGHTELF stealth if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)@@ -2053,7 +2052,7 @@ } } -void Aura::HandleModDetect(bool apply, bool Real)+void Aura::HandleModStealthDetect(bool apply, bool Real) { if(apply) {@@ -2069,20 +2068,21 @@ { if(Apply) {- m_target->m_stealthvalue = CalculateDamage();+ m_target->m_invisibilityvalue = CalculateDamage(); m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_STEALTH ); // only at real aura add if(Real) {- m_target->SetVisibility(VISIBILITY_GROUP);+ m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); if(m_target->GetTypeId() == TYPEID_PLAYER) m_target->SendUpdateToPlayer((Player*)m_target);+ m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY); } } else {- m_target->m_stealthvalue = 0;+ m_target->m_invisibilityvalue = 0; m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_STEALTH ); // only at real aura remove@@ -2099,12 +2099,15 @@ { if(Apply) {- m_target->m_detectStealth = CalculateDamage();+ m_target->m_detectInvisibility = CalculateDamage(); } else {- m_target->m_detectStealth = 0;+ m_target->m_detectInvisibility = 0; }++ if(Real && m_target->GetTypeId()==TYPEID_PLAYER)+ ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target); } void Aura::HandleAuraModRoot(bool apply, bool Real)Index: src/game/SpellAuras.h===================================================================--- src/game/SpellAuras.h (revision 3914)+++ src/game/SpellAuras.h (working copy)@@ -103,7 +103,7 @@ void HandleAuraSafeFall(bool Apply, bool Real); void HandleAuraDamageShield(bool Apply, bool Real); void HandleModStealth(bool Apply, bool Real);- void HandleModDetect(bool Apply, bool Real);+ void HandleModStealthDetect(bool Apply, bool Real); void HandleInvisibility(bool Apply, bool Real); void HandleInvisibilityDetect(bool Apply, bool Real); void HandleAuraModTotalHealthPercentRegen(bool Apply, bool Real);Index: src/game/SpellEffects.cpp===================================================================--- src/game/SpellEffects.cpp (revision 3914)+++ src/game/SpellEffects.cpp (working copy)@@ -1957,8 +1957,8 @@ pet->AddToWorld(); MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet); - ObjectAccessor::Instance().RemoveCreatureCorpseFromPlayerView(creatureTarget); creatureTarget->setDeathState(JUST_DIED);+ ObjectAccessor::UpdateObjectVisibility(creatureTarget); if(m_caster->GetTypeId() == TYPEID_PLAYER) {Index: src/game/Unit.cpp===================================================================--- src/game/Unit.cpp (revision 3914)+++ src/game/Unit.cpp (working copy)@@ -82,10 +82,11 @@ waterbreath = false; m_Visibility = VISIBILITY_ON;- m_UpdateVisibility = VISIBLE_NOCHANGES; m_detectStealth = 0;+ m_detectInvisibility = 0; m_stealthvalue = 0;+ m_invisibilityvalue = 0; m_transform = 0; m_ShapeShiftForm = 0; @@ -4934,7 +4935,7 @@ return gain; } -bool Unit::isVisibleFor(Unit const* u, bool detect) const+bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList) const { if(!u) return false;@@ -4943,26 +4944,92 @@ if (u==this) return true; - // Visible units, always are visible for all pjs- if (m_Visibility == VISIBILITY_ON)+ // not in world+ if(!IsInWorld() || !u->IsInWorld())+ return false;++ // Grid dead/alive checks+ if( u->GetTypeId()==TYPEID_PLAYER)+ {+ // non visible at grid for any stealth state+ if(!IsVisibleInGridForPlayer((Player *)u))+ return false;++ // if player is dead then he can't detect anyone in anycases+ if(!u->isAlive())+ detect = false;+ }+ else+ {+ // all dead creatures/players not visible for any creatures+ if(!u->isAlive() || !isAlive())+ return false;+ }++ // different visible distance checks+ if(u->isInFlight()) // what see player in flight+ {+ if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleGrayDistance() : 0)))+ return false;+ }+ else if(!isAlive()) // distance for show body+ {+ if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleGrayDistance() : 0)))+ return false;+ }+ else if(GetTypeId()==TYPEID_PLAYER) // distance for show player+ {+ // in case two player at same transport ignore distance checks+ if(!((Player*)this)->GetTransport() || u->GetTypeId()!=TYPEID_PLAYER || ((Player*)this)->GetTransport() != ((Player*)u)->GetTransport())+ {+ // Players far than max visible distance for player or not in our map are not visible too+ if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleGrayDistance() : 0)))+ 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(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleGrayDistance() : 0)))+ 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(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleGrayDistance() : 0)))+ return false;+ }++ // Visible units, always are visible for all units, except for units under invisibility+ if (m_Visibility == VISIBILITY_ON && u->GetVisibility()!= VISIBILITY_GROUP_INVISIBILITY) return true; // GMs are visible for higher gms (or players are visible for gms) if (u->GetTypeId() == TYPEID_PLAYER && ((Player *)u)->isGameMaster()) return (GetTypeId() == TYPEID_PLAYER && ((Player *)this)->GetSession()->GetSecurity() <= ((Player *)u)->GetSession()->GetSecurity()); - // non faction visibility non-breakable for non-GMs+ // non faction visibility non-breakable for non-GMs if (m_Visibility == VISIBILITY_OFF) return false; - // Units far than MAX_DIST_INVISIBLE or not in our map, that are not gms and are stealth, are not visibles too- if (!this->IsWithinDistInMap(u,MAX_DIST_INVISIBLE_UNIT))- return false;+ // Invisible units, always are visible for units under invisibility or unit that can detect this invisibility+ if (m_Visibility == VISIBILITY_GROUP_INVISIBILITY)+ {+ if(u->GetVisibility()== VISIBILITY_GROUP_INVISIBILITY || m_invisibilityvalue <= u->m_detectInvisibility)+ return true;+ } - // Stealth not hostile units, not visibles (except Player-with-Player case)+ // Units that can detect invisibility always are visible for units that can be detected+ if (u->GetVisibility()== VISIBILITY_GROUP_INVISIBILITY)+ {+ if(m_detectInvisibility >= u->m_invisibilityvalue)+ return true;+ }++ // Stealth/invisible not hostile units, not visible (except Player-with-Player case) if (!u->IsHostileTo(this)) {- // player auto-detect other player with stealth only if he in same group or raid or same team (raid/team case dependent from conf setting)+ // player see other player with stealth/invisibility only if he in same group or raid or same team (raid/team case dependent from conf setting) if(GetTypeId()==TYPEID_PLAYER && u->GetTypeId()==TYPEID_PLAYER) { if(((Player*)this)->IsGroupVisibleFor(((Player*)u)))@@ -4970,16 +5037,34 @@ // else apply same rules as for hostile case (detecting check) }- else- return true; }+ else+ {+ // Hunter mark functionality+ AuraList const& auras = GetAurasByType(SPELL_AURA_MOD_STALKED);+ for(AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)+ if((*iter)->GetCasterGUID()==u->GetGUID())+ return true;+ } - // if in non-detect mode then invisible for unit+ // unit got in stealth in this moment and must ignore old detected state+ // invisibility not have chance for detection+ if (m_Visibility == VISIBILITY_ON || m_Visibility == VISIBILITY_GROUP_NO_DETECT || m_Visibility == VISIBILITY_GROUP_INVISIBILITY)+ return false;++ // NOW ONLY STEALTH CASE++ // stealth and detected+ if (u->GetTypeId() == TYPEID_PLAYER && ((Player*)u)->HaveAtClient(this) )+ return true;++ // if in non-detect mode then stealthed for unit if(!detect) return false; + // STEALTH DETECTION CODE bool IsVisible = true;- bool notInFront = u->isInFront(this, MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT) ? 0 : 1;+ bool notInFront = u->isInFront(this, OBJECT_DETECT_DISTANCE * OBJECT_DETECT_DISTANCE) ? 0 : 1; float Distance = sqrt(GetDistanceSq(u)); float prob = 0; @@ -5002,33 +5087,22 @@ IsVisible = roll_chance_f(prob); - return IsVisible && ( Distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT) ;+ return IsVisible && ( Distance <= OBJECT_DETECT_DISTANCE * OBJECT_DETECT_DISTANCE) ; } void Unit::SetVisibility(UnitVisibility x) { m_Visibility = x; - switch (x)+ if(IsInWorld()) {- case VISIBILITY_ON:- m_UpdateVisibility = VISIBLE_SET_VISIBLE;- break;- case VISIBILITY_OFF:- m_UpdateVisibility = VISIBLE_SET_INVISIBLE;- break;- case VISIBILITY_GROUP:- m_UpdateVisibility = VISIBLE_SET_INVISIBLE_FOR_GROUP;- break;- }- if(GetTypeId() == TYPEID_PLAYER && IsInWorld())- { Map *m = MapManager::Instance().GetMap(GetMapId(), this);- m->PlayerRelocation((Player *)this,GetPositionX(),GetPositionY(),- GetPositionZ(),GetOrientation(), true);++ if(GetTypeId()==TYPEID_PLAYER)+ m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());+ else+ m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); }-- m_UpdateVisibility = VISIBLE_NOCHANGES; } float Unit::GetSpeed( UnitMoveType mtype ) const@@ -5474,7 +5548,7 @@ Map* map = MapManager::Instance().GetMap(GetMapId(), this); if((map->Instanceable() || (!((Creature*)this)->IsOutOfThreatArea(target))) && target->isInAccessablePlaceFor( ((Creature*)this) )) {- if((IsWithinDistInMap(target, ATTACK_DIST) && (iter->Threat > 1.1f * threat)) || (iter->Threat > 1.3f * threat))+ if((IsWithinDistInMap(target, OBJECT_ATTACK_DIST) && (iter->Threat > 1.1f * threat)) || (iter->Threat > 1.3f * threat)) { //implement 110% threat rule for targets in melee range SetCurrentVictimThreat(iter->Threat); //and 130% rule for targets in ranged distances return target; //for selecting alive targets@@ -5840,3 +5914,8 @@ { return ObjectAccessor::Instance().GetUnit(object,guid); }++bool Unit::isVisibleForInState( Player const* u, bool inVisibleList ) const+{+ return isVisibleForOrDetect(u,false,inVisibleList);+}\ No newline at end of fileIndex: src/game/Unit.h===================================================================--- src/game/Unit.h (revision 3914)+++ src/game/Unit.h (working copy)@@ -125,12 +125,6 @@ NULL_SLOT = 255 }; -enum Dist-{- MAX_DIST_INVISIBLE_UNIT = 20, // Max distance to be able to detect an invisible unit- ATTACK_DIST = 5-};- struct FactionTemplateEntry; struct Modifier; struct SpellEntry;@@ -221,19 +215,13 @@ SELF_DAMAGE = 5 }; -enum UnitVisibilityUpdate-{- VISIBLE_NOCHANGES = 0,- VISIBLE_SET_VISIBLE = 1,- VISIBLE_SET_INVISIBLE = 2,- VISIBLE_SET_INVISIBLE_FOR_GROUP = 3-};- enum UnitVisibility {- VISIBILITY_OFF = 0,- VISIBILITY_ON = 1,- VISIBILITY_GROUP = 2+ VISIBILITY_OFF = 0, // absolute, not detectable, GM-like, can see all other+ VISIBILITY_ON = 1,+ VISIBILITY_GROUP_STEALTH = 2, // detect chance, seen and can see group members+ VISIBILITY_GROUP_INVISIBILITY = 3, // invisibility, can see and can be seen only another invisible unit or invisible detection unit+ VISIBILITY_GROUP_NO_DETECT = 4 // state just at stealth apply for update Grid state }; // Value masks for UNIT_FIELD_FLAGS@@ -799,7 +787,9 @@ uint64 m_ObjectSlot[4]; uint32 m_canMove; uint32 m_detectStealth;+ uint32 m_detectInvisibility; uint32 m_stealthvalue;+ uint32 m_invisibilityvalue; uint32 m_ShapeShiftForm; uint32 m_form; int32 m_modHitChance;@@ -813,13 +803,18 @@ bool isInFront(Unit const* target,float distance) const; void SetInFront(Unit const* target); - // Invisibility and detection system+ // Visibility system UnitVisibility GetVisibility() const { return m_Visibility; }- UnitVisibilityUpdate GetUpdateVisibility() const { return m_UpdateVisibility; } void SetVisibility(UnitVisibility x);- void SetUpdateVisibility(UnitVisibilityUpdate x) { m_UpdateVisibility = x; }- bool isVisibleFor(Unit const* u, bool detect) const; + // common function for visibility checks for player/creatures with detection code+ bool isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList = false) const;+ + // virtual functions for all world objects types+ bool isVisibleForInState(Player const* u, bool inVisibleList) const;+ // function for low level grid visibility checks in player/creature cases+ virtual bool IsVisibleInGridForPlayer(Player* pl) const = 0;+ bool m_silenced; bool waterbreath; AuraList & GetSingleCastAuras() { return m_scAuras; }@@ -955,7 +950,6 @@ uint32 m_state; // Even derived shouldn't modify uint32 m_CombatTimer; - UnitVisibilityUpdate m_UpdateVisibility; UnitVisibility m_Visibility; Diminishing m_Diminishing;Index: src/game/World.cpp===================================================================--- src/game/World.cpp (revision 3914)+++ src/game/World.cpp (working copy)@@ -51,6 +51,12 @@ volatile bool World::m_stopEvent = false; +uint32 World::m_MaxVisibleDistanceForCreature = OBJECT_VISIBLE_DISTANCE;+uint32 World::m_MaxVisibleDistanceForPlayer = OBJECT_VISIBLE_DISTANCE;+uint32 World::m_MaxVisibleDistanceForObject = OBJECT_VISIBLE_DISTANCE;+uint32 World::m_MaxVisibleDistanceInFlight = OBJECT_VISIBLE_DISTANCE;+uint32 World::m_VisibleGreyDistance = 0;+ // ServerMessages.dbc enum ServerMessageType {@@ -324,7 +330,7 @@ m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState",2); m_configs[CONFIG_GM_LOG_TRADE] = sConfig.GetIntDefault("GM.LogTrade", 1); - m_configs[CONFIG_GROUP_VISIBILITY] = sConfig.GetIntDefault("GroupVisibility",0);+ m_configs[CONFIG_GROUP_VISIBILITY] = sConfig.GetIntDefault("Visibility.GroupMode",0); m_configs[CONFIG_MAIL_DELIVERY_DELAY] = sConfig.GetIntDefault("MailDeliveryDelay",HOUR); @@ -348,6 +354,48 @@ m_configs[CONFIG_CHATFLOOD_MESSAGE_DELAY] = sConfig.GetIntDefault("ChatFlood.MessageDelay",1); m_configs[CONFIG_CHATFLOOD_MUTE_TIME] = sConfig.GetIntDefault("ChatFlood.MuteTime",10); + m_MaxVisibleDistanceForCreature = sConfig.GetIntDefault("Visibility.Distance.Creature", OBJECT_VISIBLE_DISTANCE);+ if(m_MaxVisibleDistanceForCreature < uint32(45*sWorld.getRate(RATE_CREATURE_AGGRO)))+ {+ sLog.outError("Visibility.Distance.Creature can't be less max aggro radius %u",uint32(45*sWorld.getRate(RATE_CREATURE_AGGRO)));+ m_MaxVisibleDistanceForCreature = uint32(45*sWorld.getRate(RATE_CREATURE_AGGRO));+ }+ else if(m_MaxVisibleDistanceForCreature > MAX_OBJECT_VISIBLE_DISTANCE)+ {+ sLog.outError("Visibility. Distance .Creature can't be greater %u",MAX_OBJECT_VISIBLE_DISTANCE);+ m_MaxVisibleDistanceForCreature = MAX_OBJECT_VISIBLE_DISTANCE;+ }+ m_MaxVisibleDistanceForPlayer = sConfig.GetIntDefault("Visibility.Distance.Player", OBJECT_VISIBLE_DISTANCE);+ if(m_MaxVisibleDistanceForPlayer < uint32(45*sWorld.getRate(RATE_CREATURE_AGGRO)))+ {+ sLog.outError("Visibility.Distance.Player can't be less max aggro radius %u",uint32(45*sWorld.getRate(RATE_CREATURE_AGGRO)));+ m_MaxVisibleDistanceForPlayer = uint32(45*sWorld.getRate(RATE_CREATURE_AGGRO));+ }+ else if(m_MaxVisibleDistanceForPlayer > MAX_OBJECT_VISIBLE_DISTANCE)+ {+ sLog.outError("Visibility.Distance.Player can't be greater %u",MAX_OBJECT_VISIBLE_DISTANCE);+ m_MaxVisibleDistanceForPlayer = MAX_OBJECT_VISIBLE_DISTANCE;+ }+ m_MaxVisibleDistanceForObject = sConfig.GetIntDefault("Visibility.Distance.Gameobject", OBJECT_VISIBLE_DISTANCE);+ if(m_MaxVisibleDistanceForObject < OBJECT_ITERACTION_DISTANCE)+ {+ sLog.outError("Visibility.Distance.Object can't be less max aggro radius %u",OBJECT_ITERACTION_DISTANCE);+ m_MaxVisibleDistanceForObject = OBJECT_ITERACTION_DISTANCE;+ }+ else if(m_MaxVisibleDistanceForObject > MAX_OBJECT_VISIBLE_DISTANCE)+ {+ sLog.outError("Visibility.Distance.Object can't be greater %u",MAX_OBJECT_VISIBLE_DISTANCE);+ m_MaxVisibleDistanceForObject = MAX_OBJECT_VISIBLE_DISTANCE;+ }+ m_MaxVisibleDistanceInFlight = sConfig.GetIntDefault("Visibility.Distance.InFlight", OBJECT_VISIBLE_DISTANCE);+ if(m_MaxVisibleDistanceInFlight > MAX_OBJECT_VISIBLE_DISTANCE)+ {+ sLog.outError("Visibility.Distance.InFlight can't be greater %u",MAX_OBJECT_VISIBLE_DISTANCE);+ m_MaxVisibleDistanceInFlight = MAX_OBJECT_VISIBLE_DISTANCE;+ }++ m_VisibleGreyDistance = sConfig.GetIntDefault("Visibility.Distance.Grey", 1);+ ///- Read the "Data" directory from the config file m_dataPath = sConfig.GetStringDefault("DataDir","./"); if((m_dataPath.at(m_dataPath.length()-1)!='/') && (m_dataPath.at(m_dataPath.length()-1)!='\\'))Index: src/game/World.h===================================================================--- src/game/World.h (revision 3914)+++ src/game/World.h (working copy)@@ -255,6 +255,13 @@ void ScriptsStart(map<uint32, multimap<uint32, ScriptInfo> > const& scripts, uint32 id, Object* source, Object* target); + // for max speed access+ static uint32 GetMaxVisibleDistanceForCreature() { return m_MaxVisibleDistanceForCreature; }+ static uint32 GetMaxVisibleDistanceForPlayer() { return m_MaxVisibleDistanceForPlayer; }+ static uint32 GetMaxVisibleDistanceForObject() { return m_MaxVisibleDistanceForObject; }+ static uint32 GetMaxVisibleDistanceInFlight() { return m_MaxVisibleDistanceInFlight; }+ static uint32 GetVisibleGrayDistance() { return m_VisibleGreyDistance; }+ protected: void _UpdateGameTime(); void ScriptsProcess();@@ -286,6 +293,13 @@ uint32 m_ShutdownIdleMode; uint32 m_ShutdownTimer;++ // for max speed access+ static uint32 m_MaxVisibleDistanceForCreature;+ static uint32 m_MaxVisibleDistanceForPlayer;+ static uint32 m_MaxVisibleDistanceForObject;+ static uint32 m_MaxVisibleDistanceInFlight;+ static uint32 m_VisibleGreyDistance; }; extern uint32 realmID;Index: src/game/WorldSession.cpp===================================================================--- src/game/WorldSession.cpp (revision 3914)+++ src/game/WorldSession.cpp (working copy)@@ -489,7 +489,7 @@ { uint64 minTime = uint64(cur_time - lastTime); uint64 fullTime = uint64(lastTime - firstTime);- sLog.outDetail("Send all time packets count: " I64FMTD " bytes: " I64FMTD " avr.count/sec: %f avr.bytes/sec: %f",sendPacketCount,sendPacketBytes,float(sendPacketCount)/fullTime,float(sendPacketBytes)/fullTime);+ sLog.outDetail("Send all time packets count: " I64FMTD " bytes: " I64FMTD " avr.count/sec: %f avr.bytes/sec: %f time: %u",sendPacketCount,sendPacketBytes,float(sendPacketCount)/fullTime,float(sendPacketBytes)/fullTime,uint32(fullTime)); sLog.outDetail("Send last min packets count: " I64FMTD " bytes: " I64FMTD " avr.count/sec: %f avr.bytes/sec: %f",sendLastPacketCount,sendLastPacketBytes,float(sendLastPacketCount)/minTime,float(sendLastPacketBytes)/minTime); lastTime = cur_time;Index: src/mangosd/mangosd.conf.in===================================================================--- src/mangosd/mangosd.conf.in (revision 3914)+++ src/mangosd/mangosd.conf.in (working copy)@@ -219,8 +219,32 @@ # Default: 0 (standard setting: only members from same group can 100% auto detect invisible player) # 1 (raid members 100% auto detect invisible player from same raid) # 2 (players from same team can 100% auto detect invisible player)-GroupVisibility = 0+Visibility.GroupMode = 0 ++# Visibility distance for different in game object +# Max limited by active player zone: ~ 166+# Min limit dependent from objects+# Default: 66 (cell size)++# Min limit is max aggro radius (45) * Rate.Creature.Aggro+Visibility.Distance.Creature = 66+Visibility.Distance.Player = 66++# gameobject, dynobject, bodies, corpses, bones+# Min limit is iteraction distance (5)+Visibility.Distance.Object = 66++# visible distance for player in flight+# Min limit is 0 (not show any objects)+Visibility.Distance.InFlight = 66++# Visibility grey distance +# addition to appropriate object type Visibility.Distance.* use in case visibility removing to object (except corpse around distences)+# If В is distance and G is grey distance then object make visible if distance to it <= D but make non visible if distance > D+G+# Default: 1 yard+Visibility.Distance.Grey = 1+ # Mail delivery delay time in case sending item # Default: 3600 sec (1 hour) MailDeliveryDelay = 3600