All pastes #571716 Raw Edit

visibility patch

public cpp v1 · immutable
·published 2007-06-17 08:51 UTC
rendered paste body
Index: src/game/AggressorAI.cpp===================================================================--- src/game/AggressorAI.cpp	(revision 3877)+++ 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 3877)+++ src/game/Corpse.cpp	(working copy)@@ -102,10 +102,7 @@         sLog.outError("Bones %u not found in world.", GetGUIDLow());     }     else-    {-        ObjectAccessor::Instance().RemoveBonesFromPlayerView(corpse);         ObjectAccessor::Instance().AddObjectToRemoveList(this);-    }      RemoveFromWorld(); }@@ -265,3 +262,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 3877)+++ 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 3877)+++ src/game/Creature.cpp	(working copy)@@ -185,7 +185,6 @@             {                 m_deathTimer = 0;                 DEBUG_LOG("Removing corpse... %u ", GetUInt32Value(OBJECT_FIELD_ENTRY));-                ObjectAccessor::Instance().RemoveCreatureCorpseFromPlayerView(this);                 lootForPickPocketed = false;                 lootForBody         = false;                 loot.clear();@@ -1466,8 +1465,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 +1476,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/DynamicObject.cpp===================================================================--- src/game/DynamicObject.cpp	(revision 3877)+++ 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 3877)+++ 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 3877)+++ 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 isSpawned() && IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject())+        || IsTransport() && IsInWorld() && u->IsInWorld() && IsInMap(u);+}Index: src/game/GameObject.h===================================================================--- src/game/GameObject.h	(revision 3877)+++ src/game/GameObject.h	(working copy)@@ -136,20 +136,20 @@             m_respawnDelayTime = respawn > 0 ? respawn : 0;         }         void Respawn() { if(m_respawnTime > 0) m_respawnTime = time(NULL); }-        bool isSpawned() { return m_respawnDelayTime == 0 || m_respawnTime > 0 && GetOwnerGUID() || m_respawnTime == 0 && !GetOwnerGUID(); }+        bool isSpawned() const { return m_respawnDelayTime == 0 || m_respawnTime > 0 && GetOwnerGUID() || m_respawnTime == 0 && !GetOwnerGUID(); }         void Refresh();         void Delete();         void SetSpellId(uint32 id) { m_spellId = id;}-        uint32 GetSpellId() { return m_spellId;}+        uint32 GetSpellId() const { return m_spellId;}         void getFishLoot(Loot *loot);-        uint32 GetGoType() { return GetUInt32Value(GAMEOBJECT_TYPE_ID); }+        uint32 GetGoType() const { return GetUInt32Value(GAMEOBJECT_TYPE_ID); } -        LootState getLootState() { return m_lootState; }+        LootState getLootState() const { return m_lootState; }          void AddToSkillupList(uint32 PlayerGuidLow) { m_SkillupList.push_back(PlayerGuidLow); }-        bool IsInSkillupList(uint32 PlayerGuidLow)+        bool IsInSkillupList(uint32 PlayerGuidLow) const         {-            for (std::list<uint32>::iterator i = m_SkillupList.begin(); i != m_SkillupList.end(); ++i)+            for (std::list<uint32>::const_iterator i = m_SkillupList.begin(); i != m_SkillupList.end(); ++i)                 if (*i == PlayerGuidLow) return true;             return false;         }@@ -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 3877)+++ src/game/GridNotifiers.cpp	(working copy)@@ -27,255 +27,7 @@  using namespace MaNGOS; -void 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);-        }-    }-}- void-PlayerNotifier::BuildForMySelf()-{-    if( !i_player.IsInWorld() )-    {-        WorldPacket packet;-        UpdateData data;--        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);-        }-    }-}--void-VisibleNotifier::Notify()-{-    if( i_data.HasData() )-    {-        // 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;--            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)-    }-}--template<class T>-void-VisibleNotifier::Visit(std::map<OBJECT_HANDLE, T *> &m)-{-    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);-    }-}--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)-    {-        iter->second->BuildUpdate(i_updateDatas);-        iter->second->BuildCreateUpdateBlockForPlayer(&i_data, &i_player);-    }-}--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);-        }-    }-}--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() )-    {-        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()) )-        {-            iter->second->BuildOutOfRangeUpdateBlock(&i_data);--            UpdateData his_data;-            WorldPacket his_pk;-            i_player.BuildOutOfRangeUpdateBlock(&his_data);-            his_data.BuildPacket(&his_pk);-            iter->second->GetSession()->SendPacket(&his_pk);-        }-    }-}--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 +49,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 +67,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 3877)+++ src/game/GridNotifiers.h	(working copy)@@ -36,78 +36,6 @@  namespace MaNGOS {--    struct MANGOS_DLL_DECL PlayerNotifier-    {-        explicit PlayerNotifier(Player &pl) : i_player(pl) {}-        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;-    };--    struct MANGOS_DLL_DECL VisibleNotifier-    {-        Player &i_player;-        UpdateData i_data;-        UpdateDataMapType i_updateDatas;--        explicit VisibleNotifier(Player &player) : i_player(player) {}-        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 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) {}-        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     {         GridType &i_grid;@@ -154,24 +82,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 +146,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 +436,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 +495,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 3877)+++ src/game/GridNotifiersImpl.h	(working copy)@@ -27,60 +27,7 @@ #include "CreatureAI.h" #include "SpellAuras.h" -template<> inline void-MaNGOS::NotVisibleNotifier::Visit(CreatureMapType &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)-    {-        if( iter->second->IsVisibleInGridForPlayer(&i_player) )-        {-            iter->second->BuildUpdate(i_updateDatas);-            iter->second->BuildCreateUpdateBlockForPlayer(&i_data, &i_player);-        }-        else-        {-            iter->second->DestroyForPlayer(&i_player);-        }-    }-}--template<>-inline void-MaNGOS::VisibleNotifier::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()) )-        {-            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);-        }-    }-}--inline void MaNGOS::ObjectUpdater::Visit(CreatureMapType &m) {     for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter)@@ -88,41 +35,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 +71,6 @@         c2->AI()->MoveInLineOfSight(c1); } -template<> inline void MaNGOS::PlayerRelocationNotifier::Visit(CreatureMapType &m) {@@ -146,7 +78,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 +86,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 +98,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 3877)+++ 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 3877)+++ 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/Map.cpp===================================================================--- src/game/Map.cpp	(revision 3877)+++ src/game/Map.cpp	(working copy)@@ -411,7 +411,7 @@             ObjectGridLoader loader(*grid, this, cell);             loader.LoadN(); -            // Add resurrectable corpses to world obect list in grid+            // Add resurrectable corpses to world object list in grid             ObjectAccessor::Instance().AddCorpsesToGrid(GridPair(cell.GridX(),cell.GridY()),(*grid)(cell.CellX(), cell.CellY()), this);              i_gridStatus[cell.GridX()] |= mask;@@ -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())@@ -563,9 +547,41 @@      Cell cell = RedZone::GetZone(p);     EnsureGridLoadedForPlayer(cell, player, true);-    cell.data.Part.reserved = ALL_DISTRICT;-    NotifyPlayerVisibility(cell, p, player); +    // build data for self presence in world at own client+    WorldPacket packet;+    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);+    data.BuildPacket(&packet);+    player->GetSession()->SendPacket(&packet);++    player->AddToWorld();++    // Hack to send out transports+    WorldPacket packet2;+    UpdateData transData;+    if (MapManager::Instance().m_TransportsByMap.find(player->GetMapId()) != MapManager::Instance().m_TransportsByMap.end())+    {+        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);+        }+        transData.BuildPacket(&packet2);+        player->GetSession()->SendPacket(&packet2);+    }++    // send data for other players who can see+    ObjectAccessor::UpdateVisibilityFor(player);+     // reinitialize reset time     InitResetTime(); }@@ -592,14 +608,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);+    ObjectAccessor::UpdateObjectVisibility(obj); }  template<class T>@@ -622,15 +632,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);+    ObjectAccessor::UpdateObjectVisibility(&*obj); }  template<class T>@@ -856,12 +861,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();+    ObjectAccessor::UpdateVisibilityFor(player);      if( remove )         DeleteFromWorld(player);@@ -903,16 +903,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);-    }+    ObjectAccessor::UpdateObjectVisibility(obj);      if( remove )     {@@ -943,15 +936,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);-    }+    ObjectAccessor::UpdateObjectVisibility(&*obj);      if( remove )     {@@ -963,7 +950,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); @@ -973,7 +960,9 @@     Cell old_cell = RedZone::GetZone(old_val);     Cell new_cell = RedZone::GetZone(new_val);     new_cell |= old_cell;+    bool same_point = (x==player->GetPositionX() && y==player->GetPositionY() && z==player->GetPositionZ());     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 +984,24 @@             EnsureGridLoadedForPlayer(new_cell, player, true);     } -    CellLock<ReadGuard> cell_lock(new_cell, new_val);+    // if move then update what player see and who seen+    if(!same_point)+        ObjectAccessor::UpdateVisibilityFor(player); -    MaNGOS::VisibleNotifier notifier(*player);--    if( !same_cell || player->IsBeingTeleported() )     {-        if( player->IsBeingTeleported() )-            new_cell.data.Part.reserved = ALL_DISTRICT;+        CellLock<ReadGuard> cell_lock(new_cell, new_val);+        MaNGOS::PlayerRelocationNotifier relocationNotifier(*player);+        new_cell.data.Part.reserved = ALL_DISTRICT; -        TypeContainerVisitor<MaNGOS::VisibleNotifier, WorldTypeMapContainer > world_object_notifier(notifier);-        TypeContainerVisitor<MaNGOS::VisibleNotifier, GridTypeMapContainer >  grid_object_notifier(notifier);+        TypeContainerVisitor<MaNGOS::PlayerRelocationNotifier, GridTypeMapContainer >  p2grid_relocation(relocationNotifier);+        TypeContainerVisitor<MaNGOS::PlayerRelocationNotifier, WorldTypeMapContainer > p2world_relocation(relocationNotifier); -        cell_lock->Visit(cell_lock, world_object_notifier, *this);-        cell_lock->Visit(cell_lock, grid_object_notifier, *this);--        notifier.Notify();+        cell_lock->Visit(cell_lock, p2grid_relocation, *this);+        cell_lock->Visit(cell_lock, p2world_relocation, *this);     } -    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@@ -1075,6 +1034,8 @@  void Map::CreatureRelocationNotifying(Creature *creature, Cell new_cell, CellPair new_val) {+    ObjectAccessor::UpdateObjectVisibility(creature);+     if( !creature->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))     {         CellLock<ReadGuard> cell_lock(new_cell, new_val);Index: src/game/Map.h===================================================================--- src/game/Map.h	(revision 3877)+++ src/game/Map.h	(working copy)@@ -117,7 +117,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); @@ -215,7 +215,6 @@          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 3877)+++ 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 3877)+++ 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 (SIZE_OF_GRID_CELL)     // max distance for visible object show, limited by active zone for player based at cell size+#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 3877)+++ 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,156 @@ }  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); } +struct VisibleChangesNotifier+{+    WorldObject &i_object;++    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 &);+};+ void-ObjectAccessor::RemoveCreatureCorpseFromPlayerView(Creature *c)+VisibleChangesNotifier::Visit(PlayerMapType &m) {-    MaNGOS::CreatureCorpseViewRemover remover(*c);-    TypeContainerVisitor<MaNGOS::CreatureCorpseViewRemover, WorldTypeMapContainer > player_notifier(remover);-    CellPair p = MaNGOS::ComputeCellPair(c->GetPositionX(), c->GetPositionY());+    for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)+    {+        if(iter->second == &i_object)+            continue;++        iter->second->UpdateVisibilityOf(&i_object);+    }+}++void+ObjectAccessor::UpdateObjectVisibility(WorldObject *obj)+{+    CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());     Cell cell = RedZone::GetZone(p);+    cell.data.Part.reserved = ALL_DISTRICT;     cell.SetNoCreate();-    cell.data.Part.reserved = ALL_DISTRICT;+    VisibleChangesNotifier notifier(*obj);+    TypeContainerVisitor<VisibleChangesNotifier, WorldTypeMapContainer > player_notifier(notifier);     CellLock<GridReadGuard> cell_lock(cell, p);-    cell_lock->Visit(cell_lock, player_notifier, *MapManager::Instance().GetMap(c->GetMapId(), c));+    cell_lock->Visit(cell_lock, player_notifier, *MapManager::Instance().GetMap(obj->GetMapId(), obj)); } +struct VisibleNotifier+{+    Player &i_player;+    UpdateData i_data;+    UpdateDataMapType i_data_updates;+    Player::ClientGUIDs i_clientGUIDs;++    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(PlayerMapType &);+    void Notify(void);+};++inline void+VisibleNotifier::Visit(PlayerMapType &m)+{+    for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)+    {+        if( iter->second == &i_player )+            continue;++        iter->second->UpdateVisibilityOf(&i_player);+        i_player.UpdateVisibilityOf(iter->second,i_data,i_data_updates);+        i_clientGUIDs.erase(iter->second->GetGUID());+    }+}++template<class T>+inline void+VisibleNotifier::Visit(std::map<OBJECT_HANDLE, T *> &m)+{+    for(typename std::map<OBJECT_HANDLE, T *>::iterator iter=m.begin(); iter != m.end(); ++iter)+    {+        i_player.UpdateVisibilityOf(iter->second,i_data,i_data_updates);+        i_clientGUIDs.erase(iter->second->GetGUID());+    }+}++template<class T>+inline 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)+    {+        i_player.UpdateVisibilityOf(&*iter->second,i_data,i_data_updates);+        i_clientGUIDs.erase(iter->second->GetGUID());+    }+}+ void-ObjectAccessor::RemoveBonesFromPlayerView(CorpsePtr& corpse)+VisibleNotifier::Notify() {-    MaNGOS::BonesViewRemover remover(corpse);-    TypeContainerVisitor<MaNGOS::BonesViewRemover, WorldTypeMapContainer > player_notifier(remover);-    CellPair p = MaNGOS::ComputeCellPair(corpse->GetPositionX(), corpse->GetPositionY());+    // 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);++    // 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)+    {+        if(iter->first==&i_player)+            continue;++        WorldPacket packet;+        iter->second.BuildPacket(&packet);+        iter->first->GetSession()->SendPacket(&packet);+    }++    if( i_data.HasData() )+    {+        // send out of range to other players if need+        std::set<uint64> const& oor = i_data.GetOutOfRangeGUIDs();+        for(std::set<uint64>::const_iterator iter = oor.begin(); iter != oor.end(); ++iter)+        {+            if(GUID_HIPART(*iter)!=HIGHGUID_PLAYER)+                continue;++            Player* plr = ObjectAccessor::Instance().GetPlayer(i_player,*iter);+            if(plr)+                plr->UpdateVisibilityOf(&i_player);+        }++        // 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);++        // all object visible to i_player is updated/(create updated)+    }+}++void+ObjectAccessor::UpdateVisibilityFor(Player *player)+{+    VisibleNotifier notifier(*player);++    // current position list+    CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY());     Cell cell = RedZone::GetZone(p);+    cell.data.Part.reserved = ALL_DISTRICT;     cell.SetNoCreate();-    cell.data.Part.reserved = ALL_DISTRICT;+    TypeContainerVisitor<VisibleNotifier, WorldTypeMapContainer > world_notifier(notifier);+    TypeContainerVisitor<VisibleNotifier, GridTypeMapContainer  > grid_notifier(notifier);     CellLock<GridReadGuard> cell_lock(cell, p);-    cell_lock->Visit(cell_lock, player_notifier, *MapManager::Instance().GetMap(corpse->GetMapId(), &(*corpse)));+    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(); }Index: src/game/ObjectAccessor.h===================================================================--- src/game/ObjectAccessor.h	(revision 3877)+++ 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);+        static void UpdateVisibilityFor(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 3877)+++ 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 3877)+++ 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;@@ -1288,18 +1290,10 @@     if(!InBattleGround() && mEntry->map_type == MAP_BATTLEGROUND && !GetSession()->GetSecurity())         return; -    QueryResult *result = loginDatabase.PQuery("SELECT `tbc` FROM `account` WHERE `id`='%u'", GetSession()->GetAccountId());--    if(!result)-        return;                                             // unknown client or error--    Field *fields = result->Fetch();-     uint32 not_tbc_map = 0x10;                              // if any problems, then check 0x80000 also...     // with 0x80000 we can teleport to Kharazan with normal client     // with 0x10 we can't teleport to Kharazan with normal client-    bool tbc = (fields[0].GetUInt8()) && sWorld.getConfig(CONFIG_EXPANSION);-    delete result;+    bool tbc = GetSession()->IsTBC() && sWorld.getConfig(CONFIG_EXPANSION);      if(!tbc && (mEntry->map_flag & not_tbc_map) == 0)   // normal client and TBC map     {@@ -1457,14 +1451,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);@@ -2059,6 +2045,13 @@         SetResistanceBuffMods(SpellSchools(i), false, 0);     } +    //clear mana draining field+    if (GetUInt32Value(UNIT_FIELD_POWER_COST_MODIFIER) != 0)+    {+        sLog.outError("Removing power cost draining/increasing for player : %u name : %s", GetGUIDLow(), m_name.c_str());+        SetUInt32Value(UNIT_FIELD_POWER_COST_MODIFIER,0);+    }+     InitDataForForm();      // save new stats@@ -2068,13 +2061,6 @@     SetMaxPower(POWER_FOCUS, 0 );     SetMaxPower(POWER_HAPPINESS, 0 ); -    //clear power draining field-    if (GetUInt32Value(UNIT_FIELD_POWER_COST_MODIFIER) != 0)-    {-        sLog.outError("Removing power cost draining/increasing for player : %u name : %s", GetGUIDLow(), m_name.c_str());-        SetUInt32Value(UNIT_FIELD_POWER_COST_MODIFIER,0);-    }-     SetMaxHealth(info.health);      // cleanup mounted state (it will set correctly at aura loading if player saved at mount.@@ -3301,6 +3287,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()@@ -4275,8 +4264,6 @@      if( 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);@@ -4284,7 +4271,13 @@         // 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);     }+    // or just update visibility for new place+    else+        ObjectAccessor::UpdateVisibilityFor(this);      // reread after Map::Relocation     m = MapManager::Instance().GetMap(GetMapId(), this);@@ -4840,7 +4833,7 @@ //How much honor Player gains from uVictim void Player::CalculateHonor(Unit *uVictim) {-    if(!uVictim || uVictim->GetTypeId() == TYPEID_UNIT)+    if(!uVictim || uVictim == this || uVictim->GetTypeId() == TYPEID_UNIT)         return;     if(uVictim->GetAura(2479, 0))         return;@@ -12251,15 +12244,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);@@ -12866,27 +12850,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)@@ -13639,3 +13643,81 @@     }     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 3877)+++ 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);@@ -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 3877)+++ 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 3877)+++ 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,10 +2015,16 @@         // 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); +                // notify other players+                ObjectAccessor::UpdateObjectVisibility(m_target);+            }+            m_target->SetVisibility(VISIBILITY_GROUP);+             // for RACE_NIGHTELF stealth             if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)             {@@ -2075,9 +2079,15 @@         // 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);++                // notify other players+                ObjectAccessor::UpdateObjectVisibility(m_target);+            }+            m_target->SetVisibility(VISIBILITY_GROUP);         }     }     elseIndex: src/game/SpellEffects.cpp===================================================================--- src/game/SpellEffects.cpp	(revision 3879)+++ 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/TargetedMovementGenerator.cpp===================================================================--- src/game/TargetedMovementGenerator.cpp	(revision 3877)+++ src/game/TargetedMovementGenerator.cpp	(working copy)@@ -144,72 +144,6 @@                 owner.Attack(&i_target);         }     }-    /*--         //SpellEntry* spellInfo;-        if( reach )-        {-            if( owner.GetDistance2dSq( &i_target ) > 0.0f )-            {-                DEBUG_LOG("MOVEMENT : Distance = %f",owner.GetDistance2dSq( &i_target ));-                owner.addUnitState(UNIT_STAT_CHASE);-                _setTargetLocation(owner, 0);-            }-            else if ( !owner.HasInArc( 0.0f, &i_target ) )-            {-                DEBUG_LOG("MOVEMENT : Orientation = %f",owner.GetAngle(&i_target));-                owner.SetInFront(&i_target);-                if( i_target.GetTypeId() == TYPEID_PLAYER )-                    owner.SendUpdateToPlayer( (Player*)&i_target );-            }-            if( !owner.isInCombat() )-            {-                owner.AIM_Initialize();-                return;-            }-        }-        else if( i_target.isAlive() )-        {-            if( !owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.isInCombat() )-            {-                if( spellInfo = owner.reachWithSpellAttack( &i_target ) )-                {-                    _spellAtack(owner, spellInfo);-                    return;-                }-            }-            if( owner.GetDistance2dSq( &i_target ) > 0.0f )-            {-                DEBUG_LOG("MOVEMENT : Distance = %f",owner.GetDistance2dSq( &i_target ));-                owner.addUnitState(UNIT_STAT_CHASE);-                _setTargetLocation(owner, 0);-            }-        }-        else if( !i_targetedHome )-        {-            if( !owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.isInCombat() && (spellInfo = owner.reachWithSpellAttack(&i_target)) )-            {-                _spellAtack(owner, spellInfo);-                return;-            }-            _setTargetLocation(owner, 0);-            if(reach)-            {-                if( reach && owner.canReachWithAttack(&i_target) )-                {-                    owner.StopMoving();-                    if(!owner.hasUnitState(UNIT_STAT_FOLLOW))-                        owner.Attack(&i_target);-                    owner.clearUnitState(UNIT_STAT_CHASE);-                    DEBUG_LOG("UNIT IS THERE");-                }-                else-                {-                    _setTargetLocation(owner, 0);-                    DEBUG_LOG("Continue to chase");-                }-            }-        }*/     return true; } Index: src/game/Unit.cpp===================================================================--- src/game/Unit.cpp	(revision 3877)+++ 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;@@ -448,9 +447,12 @@         // self or owner of pet         if(player)         {-            player->CalculateHonor(pVictim);+            if(player!=pVictim)+            {+                player->CalculateHonor(pVictim); -            player->CalculateReputation(pVictim);+                player->CalculateReputation(pVictim);+            }              if(!PvP)             {@@ -2124,7 +2126,7 @@     } } -bool Unit::isInFront(Unit const* target, float radius)+bool Unit::isInFront(Unit const* target, float radius) const {     return IsWithinDistInMap(target, radius) && HasInArc( M_PI, target ); }@@ -4931,19 +4933,61 @@     return gain; } -bool Unit::isVisibleFor(Unit* u, bool detect)+bool Unit::isVisibleFor(Unit const* u, bool detect) const {     if(!u)         return false; +    // Always can see self+    if (u==this)+        return true;++    // not in world+    if(!IsInWorld() || !u->IsInWorld())+        return false;++    // different visible distance check+    if(!isAlive())+    {+        if (!this->IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()))+            return false;+    }+    if(GetTypeId()==TYPEID_PLAYER)+    {+        // Units far than MAX_DIST_INVISIBLE or not in our map are not visible too+        if (!this->IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()))+            return false;+    }+    else+    {+        // 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; -    // Always can see self-    if (u==this)-        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());@@ -4952,10 +4996,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))     {@@ -4971,12 +5011,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; @@ -4999,33 +5047,23 @@      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)-    {-        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);+        m->PlayerRelocation((Player *)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());     }--    m_UpdateVisibility = VISIBLE_NOCHANGES; }  float Unit::GetSpeed( UnitMoveType mtype ) const@@ -5443,7 +5481,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 3877)+++ 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@@ -810,15 +797,15 @@         float m_threatModifier[MAX_SPELL_SCHOOL];         float m_modAttackSpeedPct[3]; -        bool isInFront(Unit const* target,float distance);+        bool isInFront(Unit const* target,float distance) const;         void SetInFront(Unit const* target);          // Invisibility and detection system-        UnitVisibility GetVisibility() {return m_Visibility;}-        UnitVisibilityUpdate GetUpdateVisibility() { return m_UpdateVisibility; }+        UnitVisibility GetVisibility() const {return m_Visibility;}         void SetVisibility(UnitVisibility x);-        void SetUpdateVisibility(UnitVisibilityUpdate x) { m_UpdateVisibility = x; }-        bool isVisibleFor(Unit* u, bool detect);+        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/UpdateData.cpp===================================================================--- src/game/UpdateData.cpp	(revision 3877)+++ src/game/UpdateData.cpp	(working copy)@@ -29,6 +29,11 @@ { } +void UpdateData::AddOutOfRangeGUID(std::set<uint64>& guids)+{+    m_outOfRangeGUIDs.insert(guids.begin(),guids.end());+}+ void UpdateData::AddOutOfRangeGUID(const uint64 &guid) {     m_outOfRangeGUIDs.insert(guid);Index: src/game/UpdateData.h===================================================================--- src/game/UpdateData.h	(revision 3877)+++ src/game/UpdateData.h	(working copy)@@ -47,12 +47,15 @@     public:         UpdateData(); +        void AddOutOfRangeGUID(std::set<uint64>& guids);         void AddOutOfRangeGUID(const uint64 &guid);         void AddUpdateBlock(const ByteBuffer &block);         bool BuildPacket(WorldPacket *packet);         bool HasData() { return m_blockCount > 0 || m_outOfRangeGUIDs.size() > 0; }         void Clear(); +        std::set<uint64> const& GetOutOfRangeGUIDs() const { return m_outOfRangeGUIDs; }+     protected:         uint32 m_blockCount;         std::set<uint64> m_outOfRangeGUIDs;Index: src/game/WaypointMovementGenerator.h===================================================================--- src/game/WaypointMovementGenerator.h	(revision 3877)+++ src/game/WaypointMovementGenerator.h	(working copy)@@ -132,7 +132,7 @@             {                 float x, y, z;                 i_destinationHolder.GetLocationNow(x, y, z);-                i_player.SetPosition(x, y, z, true);+                i_player.SetPosition(x, y, z, i_player.GetOrientation());                 i_player.FlightComplete();                 return true;             }Index: src/game/World.cpp===================================================================--- src/game/World.cpp	(revision 3877)+++ src/game/World.cpp	(working copy)@@ -51,6 +51,10 @@  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;+ // ServerMessages.dbc enum ServerMessageType {@@ -119,7 +123,7 @@             continue;         if( player->IsInWorld() && player->GetZoneId() == zone )         {-            // Used by the weather system. We return the player to brodcast the change weather message to him and all players in the zone.+            // Used by the weather system. We return the player to broadcast the change weather message to him and all players in the zone.             return player;         }     }@@ -162,7 +166,7 @@     m_sessions[s->GetAccountId()] = s;     m_maxSessionsCount = max(m_maxSessionsCount,uint32(m_sessions.size())); -    // if session already exist, prepere to it deleting at next world update+    // if session already exist, prepare to it deleting at next world update     if(old)         m_kicked_sessions.insert(old); }@@ -324,7 +328,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 +352,40 @@     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;+    }+     ///- 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)!='\\'))@@ -916,7 +954,7 @@     return; } -/// Send a packet to all players (except self if mentionned)+/// Send a packet to all players (except self if mentioned) void World::SendGlobalMessage(WorldPacket *packet, WorldSession *self, uint32 team) {     SessionMap::iterator itr;@@ -959,7 +997,7 @@     } } -/// Send a System Message to all players in the zone (except self if mentionned)+/// Send a System Message to all players in the zone (except self if mentioned) void World::SendZoneText(uint32 zone, const char* text, WorldSession *self, uint32 team)  {     WorldPacket data;Index: src/game/World.h===================================================================--- src/game/World.h	(revision 3877)+++ src/game/World.h	(working copy)@@ -250,6 +250,10 @@          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;   }     protected:          void _UpdateGameTime();@@ -283,6 +287,11 @@          uint32 m_ShutdownIdleMode;         uint32 m_ShutdownTimer;++        // for max speed access+        static uint32 m_MaxVisibleDistanceForCreature;+        static uint32 m_MaxVisibleDistanceForPlayer;+        static uint32 m_MaxVisibleDistanceForObject; };  extern uint32 realmID;Index: src/game/WorldSession.cpp===================================================================--- src/game/WorldSession.cpp	(revision 3877)+++ src/game/WorldSession.cpp	(working copy)@@ -39,8 +39,8 @@ #include "Language.h"                                       // for CMSG_DISMOUNT handler  /// WorldSession constructor-WorldSession::WorldSession(uint32 id, WorldSocket *sock, uint32 sec, time_t mute_time) : _player(NULL), _socket(sock),-_security(sec), _accountId(id), _logoutTime(0), m_playerLoading(false), m_playerRecentlyLogout(false),+WorldSession::WorldSession(uint32 id, WorldSocket *sock, uint32 sec, bool tbc, time_t mute_time) : _player(NULL), _socket(sock),+_security(sec), _accountId(id), m_isTBC(tbc), _logoutTime(0), m_playerLoading(false), m_playerRecentlyLogout(false), LookingForGroup_auto_join(false), LookingForGroup_auto_add(false), m_muteTime(mute_time) {     FillOpcodeHandlerHashTable();@@ -540,8 +540,13 @@     {         ///- If the player just died before logging out, make him appear as a ghost         //FIXME: logout must be delayed in case lost connection with client in time of combat-        if (_player->GetDeathTimer() || _player->isAttacked())+        if (_player->GetDeathTimer())         {+            _player->DeleteInHateListOf();+            _player->BuildPlayerRepop();+        }+        else if (_player->isAttacked())+        {             _player->CombatStop(true);             _player->DeleteInHateListOf();             _player->KillPlayer();@@ -602,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/game/WorldSession.h===================================================================--- src/game/WorldSession.h	(revision 3877)+++ src/game/WorldSession.h	(working copy)@@ -40,7 +40,7 @@ class MANGOS_DLL_SPEC WorldSession {     public:-        WorldSession(uint32 id, WorldSocket *sock, uint32 sec, time_t mute_time);+        WorldSession(uint32 id, WorldSocket *sock, uint32 sec, bool tbc, time_t mute_time);         ~WorldSession();          bool PlayerLoading() { return m_playerLoading; }@@ -60,6 +60,7 @@         void SetSecurity(uint32 security) { _security = security; }         void SetSocket(WorldSocket *sock);         void SetPlayer(Player *plr) { _player = plr; }+        bool IsTBC() const { return m_isTBC; }          /// Is the user engaged in a log out process?         bool isLogingOut() const@@ -520,6 +521,7 @@          uint32 _security;         uint32 _accountId;+        bool m_isTBC;          time_t _logoutTime;         bool m_playerLoading;Index: src/game/WorldSocket.cpp===================================================================--- src/game/WorldSocket.cpp	(revision 3877)+++ src/game/WorldSocket.cpp	(working copy)@@ -384,7 +384,7 @@     SendPacket(&packet);      ///- Create a new WorldSession for the player and add it to the World-    _session = new WorldSession(id, this,security,mutetime);+    _session = new WorldSession(id, this,security,tbc,mutetime);     sWorld.AddSession(_session);      sLog.outDebug( "SOCKET: Client '%s' authenticated successfully.", account.c_str() );Index: src/mangosd/CliRunnable.cpp===================================================================--- src/mangosd/CliRunnable.cpp	(revision 3877)+++ src/mangosd/CliRunnable.cpp	(working copy)@@ -182,7 +182,7 @@             if(Player* p = objmgr.GetPlayer(MAKE_GUID(guidlo,HIGHGUID_PLAYER)))                 p->GetSession()->KickPlayer(); -            WorldSession acc_s(account_id,NULL,0,0);        // some invalid session+            WorldSession acc_s(account_id,NULL,0,true,0);        // some invalid session             Player acc_player(&acc_s);              acc_player.LoadFromDB(guidlo);Index: src/mangosd/mangosd.conf.in===================================================================--- src/mangosd/mangosd.conf.in	(revision 3877)+++ src/mangosd/mangosd.conf.in	(working copy)@@ -205,8 +205,16 @@ # 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, min limited by interaction distance for objects and max aggro radius for creatures/players )+# Default: 64 (standard setting)+Visibility.Distance.Creature      = 64+Visibility.Distance.Player        = 64++# gameobject/dynobject/creature's bodies+Visibility.Distance.Object        = 64+ # Mail delivery delay time in case sending item # Default: 3600 sec (1 hour) MailDeliveryDelay = 3600