All pastes #573833 Raw Edit

visibility patch

public cpp v1 · immutable
·published 2007-06-18 08:51 UTC
rendered paste body
Index: src/game/AggressorAI.cpp===================================================================--- src/game/AggressorAI.cpp	(revision 3884)+++ 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() )             {Index: src/game/Corpse.cpp===================================================================--- src/game/Corpse.cpp	(revision 3884)+++ 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::isVisibleFor(Player const* u) const+{+    return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject());+}Index: src/game/Corpse.h===================================================================--- src/game/Corpse.h	(revision 3884)+++ src/game/Corpse.h	(working copy)@@ -57,6 +57,8 @@          GridPair const& GetGrid() const { return m_grid; } +        bool isVisibleFor(Player const* u) const;+         void _ConvertCorpseToBones();                       // only call from ObjectAccessor::ConvertCorpseForPlayer     private:         CorpseType m_type;Index: src/game/Creature.cpp===================================================================--- src/game/Creature.cpp	(revision 3884)+++ src/game/Creature.cpp	(working copy)@@ -185,7 +185,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();@@ -1466,8 +1466,8 @@  bool Creature::IsVisibleInGridForPlayer(Player* pl) const {-    // Live player see live creatures or death creatures with corpse dissappiring time > 0-    if(pl->isAlive())+    // Live player (or with not release body see live creatures or death creatures with corpse dissappiring time > 0+    if(pl->isAlive() || m_deathTimer > 0)     {         if( (this->GetEntry() == VISUAL_WAYPOINT) && !pl->isGameMaster() )         {@@ -1477,22 +1477,19 @@     }      // Dead player see live creatures near own corpse-    if(pl->getDeathState() == CORPSE)+    if(isAlive())     {-        if(isAlive())+        CorpsePtr &corpse = pl->GetCorpse();+        if(corpse)         {-            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;-            }+            // 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;         }     }      // Dead player see Spirit Healer or Spirit Guide-    if(pl->isDead() && isSpiritService())+    if(isSpiritService())         return true;      // and not see any otherIndex: src/game/CreatureAIRegistry.cpp===================================================================--- src/game/CreatureAIRegistry.cpp	(revision 3884)+++ 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 3884)+++ src/game/DynamicObject.cpp	(working copy)@@ -127,3 +127,8 @@         if (*iunit)             (*iunit)->DelayAura(m_spellId, m_effIndex, delaytime); }++bool DynamicObject::isVisibleFor(Player const* u) const+{+    return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject());+}Index: src/game/DynamicObject.h===================================================================--- src/game/DynamicObject.h	(revision 3884)+++ 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 isVisibleFor(Player const* u) const;     protected:         uint64 m_casterGuid;         uint32 m_spellId;Index: src/game/GameObject.cpp===================================================================--- src/game/GameObject.cpp	(revision 3884)+++ 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::isVisibleFor(Player const* u) const+{+    return IsInWorld() && u->IsInWorld() && ( IsTransport() && IsInMap(u) ||+        isSpawned() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()) );+}Index: src/game/GameObject.h===================================================================--- src/game/GameObject.h	(revision 3884)+++ src/game/GameObject.h	(working copy)@@ -166,6 +166,8 @@          bool hasQuest(uint32 quest_id) const;         bool hasInvolvedQuest(uint32 quest_id) const;++        bool isVisibleFor(Player const* u) 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 3884)+++ 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)@@ -297,30 +129,6 @@     } } -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 +147,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 3884)+++ 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 AnyDetectableInvisibleUnitCheck+    {+        bool operator()(Unit* u) { return u->GetVisibility()==VISIBILITY_GROUP; }     };      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 3884)+++ 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 3884)+++ 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() )             {Index: src/game/HomeMovementGenerator.cpp===================================================================--- src/game/HomeMovementGenerator.cpp	(revision 3884)+++ 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/Item.cpp===================================================================--- src/game/Item.cpp	(revision 3884)+++ src/game/Item.cpp	(working copy)@@ -837,9 +837,14 @@     if(IsBag() && !((Bag*)this)->IsEmpty())         return false; -    Player* owner = GetOwner();-    if(owner && owner->CanUnequipItem(uint16(GetBagSlot()) << 8 | GetSlot(),false) !=  EQUIP_ERR_OK )-        return false;+    if(Player* owner = GetOwner())+    {+        if(owner->CanUnequipItem(uint16(GetBagSlot()) << 8 | GetSlot(),false) !=  EQUIP_ERR_OK )+            return false;+        if(owner->GetLootGUID()==GetGUID())+            return false;+    }+     return true; } Index: src/game/Map.cpp===================================================================--- src/game/Map.cpp	(revision 3884)+++ 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();++    SebdInitTransports(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@@ -1491,6 +1393,111 @@     return true; } +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::SebdInitTransports( 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 3884)+++ 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 SebdInitTransports( 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/MovementHandler.cpp===================================================================--- src/game/MovementHandler.cpp	(revision 3884)+++ 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 3884)+++ 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 invisible 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,7 @@         uint32 GetInstanceId() const { return m_InstanceId; }         void SetInstanceId(uint32 val) { m_InstanceId = val; } +        virtual bool isVisibleFor(Player const* u) const =0;     protected:         WorldObject( WorldObject *instantiator ); Index: src/game/ObjectAccessor.cpp===================================================================--- src/game/ObjectAccessor.cpp	(revision 3884)+++ 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() {}@@ -423,9 +392,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 +411,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 +628,18 @@ }  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(i_object.isVisibleFor(iter->second))+            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));-} -void-ObjectAccessor::RemoveBonesFromPlayerView(CorpsePtr& corpse)-{-    MaNGOS::BonesViewRemover remover(corpse);-    TypeContainerVisitor<MaNGOS::BonesViewRemover, WorldTypeMapContainer > player_notifier(remover);-    CellPair p = MaNGOS::ComputeCellPair(corpse->GetPositionX(), corpse->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)));+    MapManager::Instance().GetMap(obj->GetMapId(), obj)->UpdateObjectVisibility(obj,cell,p); }Index: src/game/ObjectAccessor.h===================================================================--- src/game/ObjectAccessor.h	(revision 3884)+++ 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,23 @@         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);     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 3884)+++ 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 3884)+++ 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))             {@@ -908,7 +910,7 @@         if (p_time >= m_DetectInvTimer)         {             m_DetectInvTimer = 3000;-            HandleInvisiblePjs();+            HandleInvisibleUnitsDetection();         }         else             m_DetectInvTimer -= p_time;@@ -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);     }@@ -1404,17 +1406,10 @@              SetMapId(mapid); -            // 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);-            }+                SetPosition(x + m_transX, y + m_transY, z + m_transZ, orientation + m_transO, true);             else-            {-                Relocate(x, y, z, orientation+0.1);-                SetPosition(x, y, z, orientation);-            }+                SetPosition(x, y, z, orientation, true);              // resurrect character at enter into instance where his corpse exist             CorpsePtr corpse = GetCorpse();@@ -1449,14 +1444,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);@@ -3293,6 +3280,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()@@ -4257,7 +4247,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); @@ -4265,10 +4255,12 @@     const float old_y = GetPositionY();     const float old_r = GetOrientation(); -    if( old_x != x || old_y != y || old_r != orientation)+    // update position+    if(teleport)+        Relocate(x, y, z, 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);@@ -4276,6 +4268,9 @@         // 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@@ -12243,15 +12238,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);@@ -12858,27 +12844,47 @@     SetUInt32Value(PLAYER_REST_STATE_EXPERIENCE, uint32(m_rest_bonus)); } -void Player::HandleInvisiblePjs()+void Player::HandleInvisibleUnitsDetection() {-    Map *m = MapManager::Instance().GetMap(GetMapId(), this);+    std::list<Unit*> invisibleUnits; -    //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::AnyDetectableInvisibleUnitCheck u_check;+    MaNGOS::UnitListSearcher<MaNGOS::AnyDetectableInvisibleUnitCheck > searcher(invisibleUnits, u_check);++    TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyDetectableInvisibleUnitCheck >, WorldTypeMapContainer > world_unit_searcher(searcher);+    TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyDetectableInvisibleUnitCheck >, 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 = invisibleUnits.begin(); i != invisibleUnits.end();)     {+        if((*i)==this)+        {+            i = invisibleUnits.erase(i);+            continue;+        }+         if ((*i)->isVisibleFor(this,true))         {-            m_DiscoveredPj = *i;-            m_enableDetect = false;-            m->PlayerRelocation(this, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(), true);-            m_enableDetect = true;-            m_DiscoveredPj = 0;++            (*i)->SendUpdateToPlayer(this);+            m_clientGUIDs.insert((*i)->GetGUID());+            i = invisibleUnits.erase(i);+            continue;         }++        ++i;     }-    if (!InvisiblePjsNear.size())++    if(invisibleUnits.empty())         m_DetectInvTimer = 0;-    InvisiblePjsNear.clear(); }  bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes)@@ -13631,3 +13637,80 @@     }     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->isVisibleFor(this))+        {+            target->DestroyForPlayer(this);+            m_clientGUIDs.erase(target->GetGUID());++            // activate invisibility detection system+            if(m_DetectInvTimer==0 && target->isType(TYPE_UNIT) && (+                ((Unit*)target)->GetVisibility()==VISIBILITY_GROUP || +                ((Unit*)target)->GetVisibility()==VISIBILITY_GROUP_NO_DETECT ) )+                m_DetectInvTimer = 1;+        }+    }+    else+    {+        if(target->isVisibleFor(this))+        {+            target->SendUpdateToPlayer(this);+            m_clientGUIDs.insert(target->GetGUID());+        }+    }+}++void Player::UpdateVisibilityOf(WorldObject* target, UpdateData& data, UpdateDataMapType& data_updates)+{+    if(HaveAtClient(target))+    {+        if(!target->isVisibleFor(this))+        {+            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 || +                ((Unit*)target)->GetVisibility()==VISIBILITY_GROUP_NO_DETECT ) )+                m_DetectInvTimer = 1;+        }+    }+    else+    {+        if(target->isVisibleFor(this))+        {+            target->BuildUpdate(data_updates);+            target->BuildCreateUpdateBlockForPlayer(&data, this);+            m_clientGUIDs.insert(target->GetGUID());+        }+    }+}Index: src/game/Player.h===================================================================--- src/game/Player.h	(revision 3884)+++ src/game/Player.h	(working copy)@@ -1138,7 +1138,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);@@ -1154,7 +1153,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); @@ -1339,7 +1338,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)@@ -1369,12 +1368,20 @@         float m_homebindY;         float m_homebindZ; +        // currently visible objects at player client +        typedef std::set<uint64> ClientGUIDs;+        ClientGUIDs m_clientGUIDs;++        bool HaveAtClient(WorldObject const* u) { return m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); }++        bool IsVisibleInGridForPlayer(Player* pl) const;++        void UpdateVisibilityOf(WorldObject* target);+        void UpdateVisibilityOf(WorldObject* target, UpdateData& data, UpdateDataMapType& data_updates);+         // Invisibility and detection system-        std::vector<Player *> InvisiblePjsNear;-        Player* m_DiscoveredPj;         uint32 m_DetectInvTimer;-        void HandleInvisiblePjs();-        bool m_enableDetect;+        void HandleInvisibleUnitsDetection();          void ApplySpeedMod(UnitMoveType mtype, float rate, bool forced, bool apply);                                                             // overwrite Unit versionIndex: src/game/ReactorAI.cpp===================================================================--- src/game/ReactorAI.cpp	(revision 3884)+++ 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 3884)+++ 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"@@ -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);              // for RACE_NIGHTELF stealth             if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)@@ -2075,9 +2074,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);         }     }     elseIndex: src/game/SpellEffects.cpp===================================================================--- src/game/SpellEffects.cpp	(revision 3884)+++ src/game/SpellEffects.cpp	(working copy)@@ -1932,8 +1932,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 3884)+++ src/game/Unit.cpp	(working copy)@@ -82,7 +82,6 @@     waterbreath = false;      m_Visibility = VISIBILITY_ON;-    m_UpdateVisibility = VISIBLE_NOCHANGES;      m_detectStealth = 0;     m_stealthvalue = 0;@@ -4943,6 +4942,63 @@     if (u==this)         return true; +    // not in world+    if(!IsInWorld() || !u->IsInWorld())+        return false;++    // different visible distance checks+    if(u->isInFlight())                                     // what see player in flight+    {+        if (!this->IsWithinDistInMap(u,World::GetMaxVisibleDistanceInFlight()))+            return false;+    }+    else if(!isAlive())                                     // distance for show body+    {+        if (!this->IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()))+            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())+        {+            // Units far than MAX_DIST_INVISIBLE or not in our map are not visible too+            if (!this->IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()))+                return false;+        }+    }+    else if(GetCharmerOrOwnerGUID())                        // distance for show pet/charmed+    {+        // Units far than MAX_DIST_INVISIBLE or not in our map are not visible too+        if (!this->IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()))+            return false;+    }+    else                                                    // distance for show creature+    {+        // Units far than MAX_DIST_INVISIBLE or not in our map are not visible too+        if (!this->IsWithinDistInMap(u,World::GetMaxVisibleDistanceForCreature()))+            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;+    }+     // Visible units, always are visible for all pjs     if (m_Visibility == VISIBILITY_ON)         return true;@@ -4955,10 +5011,6 @@     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;-     // Stealth not hostile units, not visibles (except Player-with-Player case)     if (!u->IsHostileTo(this))     {@@ -4974,12 +5026,20 @@             return true;     } +    // unit got in stealth in this moment and must ignore old detected state+    if (m_Visibility == VISIBILITY_GROUP_NO_DETECT)+        return false;++    // invisible and detected+    if (u->GetTypeId() == TYPEID_PLAYER && ((Player*)u)->HaveAtClient(this) )+        return true;+     // if in non-detect mode then invisible for unit     if(!detect)         return false;      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 +5062,27 @@      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) ; } +bool Unit::isVisibleFor(Player const* u) const+{+    return isVisibleFor(u,false);+}+ 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@@ -5446,7 +5500,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 targetsIndex: src/game/Unit.h===================================================================--- src/game/Unit.h	(revision 3884)+++ 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,12 @@     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,+    VISIBILITY_ON              = 1,+    VISIBILITY_GROUP           = 2,                         // only detectable case+    VISIBILITY_GROUP_NO_DETECT = 3                          // state just at invisibility apply for update Grid state };  // Value masks for UNIT_FIELD_FLAGS@@ -815,10 +802,10 @@          // Invisibility and detection 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;+        bool isVisibleFor(Player const* u) const;+        virtual bool IsVisibleInGridForPlayer(Player* pl) const = 0;          bool m_silenced;         bool waterbreath;@@ -954,7 +941,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 3884)+++ src/game/World.cpp	(working copy)@@ -51,6 +51,11 @@  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;+ // ServerMessages.dbc enum ServerMessageType {@@ -324,7 +329,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 +353,46 @@     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;+    }+     ///- 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)!='\\'))@@ -1207,4 +1252,4 @@             m_sessions.erase(itr);         }     }-}+}\ No newline at end of fileIndex: src/game/World.h===================================================================--- src/game/World.h	(revision 3884)+++ src/game/World.h	(working copy)@@ -255,6 +255,11 @@          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;    }     protected:          void _UpdateGameTime();@@ -288,6 +293,12 @@          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; };  extern uint32 realmID;Index: src/game/WorldSession.cpp===================================================================--- src/game/WorldSession.cpp	(revision 3884)+++ src/game/WorldSession.cpp	(working copy)@@ -607,7 +607,6 @@         ///- Release charmed creatures and unsummon totems         _player->Uncharm();         _player->UnsummonAllTotems();-        _player->InvisiblePjsNear.clear();          ///- empty buyback items and save the player in the database         // some save parts only correctly work in case player present in map/player_lists (pets, etc)Index: src/mangosd/mangosd.conf.in===================================================================--- src/mangosd/mangosd.conf.in	(revision 3884)+++ src/mangosd/mangosd.conf.in	(working copy)@@ -205,8 +205,27 @@ # 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++ # Mail delivery delay time in case sending item # Default: 3600 sec (1 hour) MailDeliveryDelay = 3600