All pastes #583747 Raw Edit

visibility patch 1.03 with invis

public cpp v1 · immutable
·published 2007-06-22 14:36 UTC
rendered paste body
Index: 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 &#1042; 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