Index: /trunk/src/game/SpellEffects.cpp
===================================================================
--- /trunk/src/game/SpellEffects.cpp (revision 229)
+++ /trunk/src/game/SpellEffects.cpp (revision 233)
@@ -3491,4 +3491,7 @@
 void Spell::EffectAddFarsight(uint32 i)
 {
+    if (m_caster->GetTypeId() != TYPEID_PLAYER)
+        return;
+
     float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
     int32 duration = GetSpellDuration(m_spellInfo);
@@ -3502,6 +3505,16 @@
     dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
     m_caster->AddDynObject(dynObj);
-    MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj)->Add(dynObj);
-    m_caster->SetUInt64Value(PLAYER_FARSIGHT, dynObj->GetGUID());
+
+    CellPair pair = Trinity::ComputeCellPair(dynObj->GetPositionX(), dynObj->GetPositionY());
+    Cell cell(pair);
+    Map* map = MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj);
+    map->LoadGrid(cell);                        // In case the spell is casted into a different grid by player
+    map->Add(dynObj);
+    map->SwitchGridContainers(dynObj, true);    // Needed for forwarding player packets
+    dynObj->setActive(true);                    // Keep the grid updated even if there are no players in it
+      
+    // Need to update visibility of object for client to accept farsight guid
+    ((Player*)m_caster)->UpdateVisibilityOf(dynObj);
+    ((Player*)m_caster)->SetFarsightTarget(dynObj);
 }
 
Index: /trunk/src/game/Level3.cpp
===================================================================
--- /trunk/src/game/Level3.cpp (revision 232)
+++ /trunk/src/game/Level3.cpp (revision 233)
@@ -6816,2 +6816,25 @@
     return true;
 }
+
+bool ChatHandler::HandleBindSightCommand(const char* args)
+{
+    Unit* pUnit = getSelectedUnit();
+    if (!pUnit)
+        return false;
+        
+    if (m_session->GetPlayer()->isPossessing())
+        return false;
+
+    pUnit->AddPlayerToVision(m_session->GetPlayer());
+
+    return true;
+}
+
+bool ChatHandler::HandleUnbindSightCommand(const char* args)
+{
+    if (m_session->GetPlayer()->isPossessing())
+        return false;
+        
+    m_session->GetPlayer()->RemoveFarsightTarget();
+    return true;
+}
Index: /trunk/src/game/SpellHandler.cpp
===================================================================
--- /trunk/src/game/SpellHandler.cpp (revision 207)
+++ /trunk/src/game/SpellHandler.cpp (revision 233)
@@ -353,7 +353,7 @@
         return;
 
-    // Remove possess/charm aura from the possessed/charmed as well
+    // Remove possess/charm/sight aura from the possessed/charmed as well
     // TODO: Remove this once the ability to cancel aura sets at once is implemented
-    if(_player->GetCharm())
+    if(_player->GetCharm() || _player->GetFarsightTarget())
     {
         for (int i = 0; i < 3; ++i)
@@ -361,8 +361,12 @@
             if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_POSSESS ||
                 spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_POSSESS_PET ||
-                spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_CHARM)
+                spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_CHARM ||
+                spellInfo->EffectApplyAuraName[i] == SPELL_AURA_BIND_SIGHT)
             {
                 _player->RemoveAurasDueToSpellByCancel(spellId);
-                _player->GetCharm()->RemoveAurasDueToSpellByCancel(spellId);
+                if (_player->GetCharm())
+                    _player->GetCharm()->RemoveAurasDueToSpellByCancel(spellId);
+                else if (_player->GetFarsightTarget()->GetTypeId() != TYPEID_DYNAMICOBJECT)
+                    ((Unit*)_player->GetFarsightTarget())->RemoveAurasDueToSpellByCancel(spellId);
                 return;
             }
@@ -465,5 +469,6 @@
 
     Creature* totem = ObjectAccessor::GetCreature(*_player,_player->m_TotemSlot[slotId]);
-    if(totem && totem->isTotem())
+    // Don't unsummon sentry totem
+    if(totem && totem->isTotem() && totem->GetEntry() != SENTRY_TOTEM_ENTRY)
         ((Totem*)totem)->UnSummon();
 }
Index: /trunk/src/game/Chat.cpp
===================================================================
--- /trunk/src/game/Chat.cpp (revision 232)
+++ /trunk/src/game/Chat.cpp (revision 233)
@@ -566,4 +566,6 @@
         { "possess",        SEC_ADMINISTRATOR,  false, &ChatHandler::HandlePossessCommand,             "", NULL },
         { "unpossess",      SEC_ADMINISTRATOR,  false, &ChatHandler::HandleUnPossessCommand,           "", NULL },
+        { "bindsight",      SEC_ADMINISTRATOR,  false, &ChatHandler::HandleBindSightCommand,           "", NULL },
+        { "unbindsight",    SEC_ADMINISTRATOR,  false, &ChatHandler::HandleUnbindSightCommand,         "", NULL },
 
         { NULL,             0,                  false, NULL,                                           "", NULL }
Index: /trunk/src/game/ObjectAccessor.h
===================================================================
--- /trunk/src/game/ObjectAccessor.h (revision 206)
+++ /trunk/src/game/ObjectAccessor.h (revision 233)
@@ -213,4 +213,5 @@
             void Visit(PlayerMapType &);
             void Visit(CreatureMapType &);
+            void Visit(DynamicObjectMapType &);
             void BuildPacket(Player* plr);
             template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
Index: /trunk/src/game/DynamicObject.cpp
===================================================================
--- /trunk/src/game/DynamicObject.cpp (revision 120)
+++ /trunk/src/game/DynamicObject.cpp (revision 233)
@@ -137,4 +137,7 @@
 void DynamicObject::Delete()
 {
+    // Make sure the object is back to grid container for removal as farsight targets
+    // are switched to world container on creation
+    GetMap()->SwitchGridContainers(this, false);
     SendObjectDeSpawnAnim(GetGUID());
     AddObjectToRemoveList();
@@ -151,4 +154,4 @@
 bool DynamicObject::isVisibleForInState(Player const* u, bool inVisibleList) const
 {
-    return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f));
+    return IsInWorld() && u->IsInWorld() /*&& IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f))*/;
 }
Index: /trunk/src/game/GridNotifiers.h
===================================================================
--- /trunk/src/game/GridNotifiers.h (revision 174)
+++ /trunk/src/game/GridNotifiers.h (revision 233)
@@ -96,8 +96,10 @@
         std::set<uint64> plr_list;
         bool i_toPossessor;
+        bool i_toSelf;
         float i_dist;
-        Deliverer(WorldObject &src, WorldPacket *msg, bool to_possessor, float dist = 0.0f) : i_source(src), i_message(msg), i_toPossessor(to_possessor), i_dist(dist) {}
+        Deliverer(WorldObject &src, WorldPacket *msg, bool to_possessor, bool to_self, float dist = 0.0f) : i_source(src), i_message(msg), i_toPossessor(to_possessor), i_toSelf(to_self), i_dist(dist) {}
         void Visit(PlayerMapType &m);
         void Visit(CreatureMapType &m);
+        void Visit(DynamicObjectMapType &m);
         virtual void VisitObject(Player* plr) = 0;
         void SendPacket(Player* plr);
@@ -107,6 +109,5 @@
     struct TRINITY_DLL_DECL MessageDeliverer : public Deliverer
     {
-        bool i_toSelf;
-        MessageDeliverer(Player &pl, WorldPacket *msg, bool to_possessor, bool to_self) : Deliverer(pl, msg, to_possessor), i_toSelf(to_self) {}
+        MessageDeliverer(Player &pl, WorldPacket *msg, bool to_possessor, bool to_self) : Deliverer(pl, msg, to_possessor, to_self) {}
         void VisitObject(Player* plr);
     };
@@ -114,5 +115,5 @@
     struct TRINITY_DLL_DECL ObjectMessageDeliverer : public Deliverer
     {
-        explicit ObjectMessageDeliverer(WorldObject &src, WorldPacket *msg, bool to_possessor) : Deliverer(src, msg, to_possessor) {}
+        explicit ObjectMessageDeliverer(WorldObject &src, WorldPacket *msg, bool to_possessor) : Deliverer(src, msg, to_possessor, false) {}
         void VisitObject(Player* plr) { SendPacket(plr); }
     };
@@ -120,7 +121,6 @@
     struct TRINITY_DLL_DECL MessageDistDeliverer : public Deliverer
     {
-        bool i_toSelf;
         bool i_ownTeamOnly;
-        MessageDistDeliverer(Player &pl, WorldPacket *msg, bool to_possessor, float dist, bool to_self, bool ownTeamOnly) : Deliverer(pl, msg, to_possessor, dist), i_toSelf(to_self), i_ownTeamOnly(ownTeamOnly) {}
+        MessageDistDeliverer(Player &pl, WorldPacket *msg, bool to_possessor, float dist, bool to_self, bool ownTeamOnly) : Deliverer(pl, msg, to_possessor, to_self, dist), i_ownTeamOnly(ownTeamOnly) {}
         void VisitObject(Player* plr);
     };
@@ -128,5 +128,5 @@
     struct TRINITY_DLL_DECL ObjectMessageDistDeliverer : public Deliverer
     {
-        ObjectMessageDistDeliverer(WorldObject &obj, WorldPacket *msg, bool to_possessor, float dist) : Deliverer(obj, msg, to_possessor, dist) {}
+        ObjectMessageDistDeliverer(WorldObject &obj, WorldPacket *msg, bool to_possessor, float dist) : Deliverer(obj, msg, to_possessor, false, dist) {}
         void VisitObject(Player* plr) { SendPacket(plr); }
     };
Index: /trunk/src/game/Unit.h
===================================================================
--- /trunk/src/game/Unit.h (revision 231)
+++ /trunk/src/game/Unit.h (revision 233)
@@ -639,4 +639,6 @@
 };
 
+typedef std::list<Player*> SharedVisionList;
+
 struct CharmInfo
 {
@@ -1019,4 +1021,8 @@
         CharmInfo* GetCharmInfo() { return m_charmInfo; }
         CharmInfo* InitCharmInfo(Unit* charm);
+        SharedVisionList const& GetSharedVisionList() { return m_sharedVision; }
+        void AddPlayerToVision(Player* plr);
+        void RemovePlayerFromVision(Player* plr);
+        void RemoveAllFromVision();
         void UncharmSelf();
         void UnpossessSelf(bool attack);
@@ -1351,4 +1357,5 @@
         CharmInfo *m_charmInfo;
         bool m_isPossessed;
+        SharedVisionList m_sharedVision;
 
         virtual SpellSchoolMask GetMeleeDamageSchoolMask() const;
Index: /trunk/src/game/SpellAuras.cpp
===================================================================
--- /trunk/src/game/SpellAuras.cpp (revision 229)
+++ /trunk/src/game/SpellAuras.cpp (revision 233)
@@ -1965,12 +1965,8 @@
     else
     {
-        if( m_target->GetTypeId() == TYPEID_PLAYER &&
-            ( GetSpellProto()->Effect[0]==72 || GetSpellProto()->Effect[0]==6 &&
-            ( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) )
+        if( m_target->GetTypeId() == TYPEID_PLAYER && GetSpellProto()->Effect[0]==72 )
         {
             // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425
-            m_target->SetUInt64Value(PLAYER_FARSIGHT, 0);
-            WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
-            ((Player*)m_target)->GetSession()->SendPacket(&data);
+            ((Player*)m_target)->ClearFarsight();
             return;
         }
@@ -2228,4 +2224,22 @@
 
                 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
+                return;
+            }
+
+            // Sentry Totem
+            if (GetId() == 6495 && caster->GetTypeId() == TYPEID_PLAYER)
+            {
+                if (apply)
+                {
+                    uint64 guid = caster->m_TotemSlot[3];
+                    if (guid)
+                    {
+                        Creature *totem = ObjectAccessor::GetCreature(*caster, guid);
+                        if (totem && totem->isTotem())
+                            totem->AddPlayerToVision((Player*)caster);
+                    }
+                } 
+                else
+                    ((Player*)caster)->RemoveFarsightTarget();
                 return;
             }
@@ -2831,5 +2845,8 @@
         return;
 
-    caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_target->GetGUID() : 0);
+    if (apply)
+        m_target->AddPlayerToVision((Player*)caster);
+    else
+        m_target->RemovePlayerFromVision((Player*)caster);
 }
 
Index: /trunk/src/game/Map.cpp
===================================================================
--- /trunk/src/game/Map.cpp (revision 229)
+++ /trunk/src/game/Map.cpp (revision 233)
@@ -316,14 +316,21 @@
     CellPair pair = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
     Cell cell(pair);
-    NGridType *grid = getNGrid(cell.GridX(), cell.GridY());
+    NGridType *ngrid = getNGrid(cell.GridX(), cell.GridY());
+    GridType &grid = (*ngrid)(cell.CellX(), cell.CellY());
 
     if (active)
     {
-        (*grid)(cell.CellX(), cell.CellY()).RemoveGridObject<T>(obj, obj->GetGUID());
-        (*grid)(cell.CellX(), cell.CellY()).AddWorldObject<T>(obj, obj->GetGUID());
+        if (!grid.GetWorldObject(obj->GetGUID(), obj))
+        {
+            grid.RemoveGridObject<T>(obj, obj->GetGUID());
+            grid.AddWorldObject<T>(obj, obj->GetGUID());
+        }
     } else
     {
-        (*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject<T>(obj, obj->GetGUID());
-        (*grid)(cell.CellX(), cell.CellY()).AddGridObject<T>(obj, obj->GetGUID());
+        if (!grid.GetGridObject(obj->GetGUID(), obj))
+        {
+            grid.RemoveWorldObject<T>(obj, obj->GetGUID());
+            grid.AddGridObject<T>(obj, obj->GetGUID());
+        }
     }
 }
@@ -331,4 +338,5 @@
 template void Map::SwitchGridContainers(Creature *, bool);
 template void Map::SwitchGridContainers(Corpse *, bool);
+template void Map::SwitchGridContainers(DynamicObject *, bool);
 
 template<class T>
Index: /trunk/src/game/Chat.h
===================================================================
--- /trunk/src/game/Chat.h (revision 232)
+++ /trunk/src/game/Chat.h (revision 233)
@@ -454,4 +454,6 @@
         bool HandlePossessCommand(const char* args);
         bool HandleUnPossessCommand(const char* args);
+        bool HandleBindSightCommand(const char* args);
+        bool HandleUnbindSightCommand(const char* args);
 
         Player*   getSelectedPlayer();
Index: /trunk/src/game/TotemAI.cpp
===================================================================
--- /trunk/src/game/TotemAI.cpp (revision 102)
+++ /trunk/src/game/TotemAI.cpp (revision 233)
@@ -123,3 +123,12 @@
 TotemAI::AttackStart(Unit *)
 {
+    // Sentry totem sends ping on attack
+    if (i_totem.GetEntry() == SENTRY_TOTEM_ENTRY && i_totem.GetOwner()->GetTypeId() == TYPEID_PLAYER)
+    {
+        WorldPacket data(MSG_MINIMAP_PING, (8+4+4));
+        data << i_totem.GetGUID();
+        data << i_totem.GetPositionX();
+        data << i_totem.GetPositionY();
+        ((Player*)i_totem.GetOwner())->GetSession()->SendPacket(&data);
+    }
 }
Index: /trunk/src/game/Player.h
===================================================================
--- /trunk/src/game/Player.h (revision 230)
+++ /trunk/src/game/Player.h (revision 233)
@@ -903,4 +903,11 @@
         void Possess(Unit *target);
         void RemovePossess(bool attack = true); 
+        WorldObject* GetFarsightTarget() const;
+        void ClearFarsight();
+        void RemoveFarsightTarget();
+        void SetFarsightTarget(WorldObject* target);
+        // Controls if vision is currently on farsight object, updated in FAR_SIGHT opcode
+        void SetFarsightVision(bool apply) { m_farsightVision = apply; }
+        bool HasFarsightVision() const { return m_farsightVision; }
 
         bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0);
@@ -2290,4 +2297,6 @@
         WorldLocation m_teleport_dest;
 
+        bool m_farsightVision;
+
         DeclinedName *m_declinedname;
     private:
Index: /trunk/src/game/MiscHandler.cpp
===================================================================
--- /trunk/src/game/MiscHandler.cpp (revision 232)
+++ /trunk/src/game/MiscHandler.cpp (revision 233)
@@ -1392,19 +1392,31 @@
     //recv_data.hexlike();
 
-    uint8 unk;
-    recv_data >> unk;
-
-    switch(unk)
+    uint8 apply;
+    recv_data >> apply;
+
+    CellPair pair;
+
+    switch(apply)
     {
         case 0:
-            //WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0)
-            //SendPacket(&data);
-            //_player->SetUInt64Value(PLAYER_FARSIGHT, 0);
-            sLog.outDebug("Removed FarSight from player %u", _player->GetGUIDLow());
+            _player->SetFarsightVision(false);
+            pair = Trinity::ComputeCellPair(_player->GetPositionX(), _player->GetPositionY());
+            sLog.outDebug("Player %u set vision to himself", _player->GetGUIDLow());
             break;
         case 1:
-            sLog.outDebug("Added FarSight " I64FMTD " to player %u", _player->GetUInt64Value(PLAYER_FARSIGHT), _player->GetGUIDLow());
+            _player->SetFarsightVision(true);
+            if (WorldObject* obj = _player->GetFarsightTarget())
+                pair = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
+            else
+                return;
+            sLog.outDebug("Player %u set vision to farsight target " I64FMTD ".", _player->GetGUIDLow(), _player->GetUInt64Value(PLAYER_FARSIGHT));
             break;
-    }
+        default:
+            sLog.outDebug("Unhandled mode in CMSG_FAR_SIGHT: %u", apply);
+            return;
+    }
+    // Update visibility after vision change
+    Cell cell(pair);
+    GetPlayer()->GetMap()->UpdateObjectsVisibilityFor(_player, cell, pair);
 }
 
Index: /trunk/src/game/Unit.cpp
===================================================================
--- /trunk/src/game/Unit.cpp (revision 232)
+++ /trunk/src/game/Unit.cpp (revision 233)
@@ -828,11 +828,4 @@
             he->DuelComplete(DUEL_INTERUPTED);
         }
-
-        // Possessed unit died, restore control to possessor
-        pVictim->UnpossessSelf(false);
-
-        // Possessor died, remove possession
-        if(pVictim->GetTypeId() == TYPEID_PLAYER && pVictim->isPossessing())
-            ((Player*)pVictim)->RemovePossess(false);
 
         // battleground things (do this at the end, so the death state flag will be properly set to handle in the bg->handlekill)
@@ -7184,4 +7177,36 @@
 }
 
+void Unit::AddPlayerToVision(Player* plr) 
+{ 
+    if (m_sharedVision.empty() && GetTypeId() == TYPEID_UNIT)
+    {
+        setActive(true);
+        GetMap()->SwitchGridContainers((Creature*)this, true);
+    }
+    m_sharedVision.push_back(plr);
+    plr->SetFarsightTarget(this);
+}
+
+void Unit::RemovePlayerFromVision(Player* plr) 
+{ 
+    m_sharedVision.remove(plr); 
+    if (m_sharedVision.empty() && GetTypeId() == TYPEID_UNIT)
+    {
+        setActive(false);
+        GetMap()->SwitchGridContainers((Creature*)this, false);
+    }
+    plr->ClearFarsight();
+}
+
+void Unit::RemoveAllFromVision()
+{
+    while (!m_sharedVision.empty())
+    {
+        Player* plr = *m_sharedVision.begin();
+        m_sharedVision.erase(m_sharedVision.begin());
+        plr->ClearFarsight();
+    }
+}
+
 void Unit::UncharmSelf()
 {
@@ -8936,4 +8961,8 @@
         UnsummonAllTotems();
 
+        // Possessed unit died, restore control to possessor
+        UnpossessSelf(false);
+        RemoveAllFromVision();
+
         ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false);
         ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false);
@@ -9757,7 +9786,10 @@
 
         UnpossessSelf(false);
+        RemoveAllFromVision();
     }
     RemoveFromWorld();
 }
+
+
 
 CharmInfo* Unit::InitCharmInfo(Unit *charm)
Index: /trunk/src/game/Player.cpp
===================================================================
--- /trunk/src/game/Player.cpp (revision 230)
+++ /trunk/src/game/Player.cpp (revision 233)
@@ -428,4 +428,6 @@
 
     m_isActive = true;
+
+    m_farsightVision = false;
 }
 
@@ -1292,4 +1294,10 @@
         RemoveGuardians();
 
+        // remove possession
+        if(isPossessing())
+            RemovePossess(false);
+        else
+            RemoveFarsightTarget();
+
         // save value before aura remove in Unit::setDeathState
         ressSpellId = GetUInt32Value(PLAYER_SELF_RES_SPELL);
@@ -1545,5 +1553,13 @@
         ((Player*)GetCharmer())->RemovePossess();
 
-    // The player was ported to another map and looses the duel immediately.
+    // Remove player's possession before teleporting
+    if (isPossessing())
+        RemovePossess(false);
+
+    // Empty vision list and clear farsight (if it hasn't already been cleared by RemovePossess) before teleporting
+    RemoveAllFromVision();
+    RemoveFarsightTarget();
+
+    // The player was ported to another map and looses the duel immediatly.
     // We have to perform this check before the teleport, otherwise the
     // ObjectAccessor won't find the flag.
@@ -1763,4 +1779,5 @@
         RemoveMiniPet();
         RemoveGuardians();
+        RemoveFarsightTarget();
     }
 
@@ -17294,6 +17311,8 @@
         return false;
 
-    // If the player is currently possessing, update visibility from the possessed unit's location
-    const Unit* target = isPossessing() ? GetCharm() : this;
+    // If the player is currently channeling vision, update visibility from the target unit's location
+    const WorldObject* target = GetFarsightTarget();
+    if (!target || !HasFarsightVision()) // Vision needs to be on the farsight target
+        target = this;
 
     // different visible distance checks
@@ -18744,4 +18763,7 @@
     SetPossessedTarget(target);
 
+    // Start channeling packets to possessor
+    target->AddPlayerToVision(this);
+
     target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction());
     target->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
@@ -18749,13 +18771,7 @@
     target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
     SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
-    SetUInt64Value(PLAYER_FARSIGHT, target->GetGUID());
 
     if(target->GetTypeId() == TYPEID_UNIT)
     {
-        // Set target to active in the grid and place it in the world container to be picked up by all regular player cell visits
-        Map* map = target->GetMap();
-        map->SwitchGridContainers((Creature*)target, true);
-        target->setActive(true);
-
         ((Creature*)target)->InitPossessedAI(); // Initialize the possessed AI
         target->StopMoving();
@@ -18810,13 +18826,11 @@
     RemovePossessedTarget();
 
+    // Stop channeling packets back to possessor
+    target->RemovePlayerFromVision(this);
+
     if(target->GetTypeId() == TYPEID_PLAYER)
         ((Player*)target)->setFactionForRace(target->getRace());
     else if(target->GetTypeId() == TYPEID_UNIT)
     {
-        // Set creature to inactive in grid and place it back into the grid container
-        Map* map = target->GetMap();
-        target->setActive(false);
-        map->SwitchGridContainers((Creature*)target, false);
-
         if(((Creature*)target)->isPet())
         {
@@ -18832,5 +18846,4 @@
     target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
     RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
-    SetUInt64Value(PLAYER_FARSIGHT, 0);
 
     // Remove pet spell action bar
@@ -18898,4 +18911,43 @@
 }
 
+WorldObject* Player::GetFarsightTarget() const
+{
+    // Players can have in farsight field another player's guid, a creature's guid, or a dynamic object's guid
+    if (uint64 guid = GetUInt64Value(PLAYER_FARSIGHT))
+        return (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*this, guid, TYPEMASK_PLAYER | TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT);
+    return NULL;
+}
+
+void Player::RemoveFarsightTarget()
+{
+    if (WorldObject* fTarget = GetFarsightTarget())
+    {
+        if (fTarget->isType(TYPEMASK_PLAYER | TYPEMASK_UNIT))
+            ((Unit*)fTarget)->RemovePlayerFromVision(this);
+    }
+    ClearFarsight();
+}
+
+void Player::ClearFarsight()
+{
+    if (GetUInt64Value(PLAYER_FARSIGHT))
+    {
+        SetUInt64Value(PLAYER_FARSIGHT, 0);
+        WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
+        GetSession()->SendPacket(&data);
+    }
+}
+
+void Player::SetFarsightTarget(WorldObject* obj)
+{
+    if (!obj || !obj->isType(TYPEMASK_PLAYER | TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT))
+        return;
+
+    // Remove the current target if there is one
+    RemoveFarsightTarget();
+
+    SetUInt64Value(PLAYER_FARSIGHT, obj->GetGUID());
+}
+
 bool Player::isAllowUseBattleGroundObject()
 {
Index: /trunk/src/game/GridDefines.h
===================================================================
--- /trunk/src/game/GridDefines.h (revision 102)
+++ /trunk/src/game/GridDefines.h (revision 233)
@@ -58,5 +58,5 @@
 
 // Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case)
-typedef TYPELIST_3(Player, Creature/*pets*/, Corpse/*resurrectable*/)                   AllWorldObjectTypes;
+typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, DynamicObject/*farsight target*/) AllWorldObjectTypes;
 typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes;
 
Index: /trunk/src/game/GridNotifiers.cpp
===================================================================
--- /trunk/src/game/GridNotifiers.cpp (revision 221)
+++ /trunk/src/game/GridNotifiers.cpp (revision 233)
@@ -41,6 +41,8 @@
         iter->getSource()->UpdateVisibilityOf(&i_player);
         i_player.UpdateVisibilityOf(iter->getSource());
-        if (i_player.isPossessedByPlayer())
-            ((Player*)i_player.GetCharmer())->UpdateVisibilityOf(iter->getSource());
+
+        if (!i_player.GetSharedVisionList().empty())
+            for (SharedVisionList::const_iterator it = i_player.GetSharedVisionList().begin(); it != i_player.GetSharedVisionList().end(); ++it)
+                (*it)->UpdateVisibilityOf(iter->getSource());
     }
 }
@@ -149,7 +151,12 @@
         if (!i_dist || iter->getSource()->GetDistance(&i_source) <= i_dist)
         {
-            // Send packet to possessor
-            if (iter->getSource()->isPossessedByPlayer())
-                SendPacket((Player*)iter->getSource()->GetCharmer());
+            // Send packet to all who are sharing the player's vision
+            if (!iter->getSource()->GetSharedVisionList().empty())
+            {
+                SharedVisionList::const_iterator it = iter->getSource()->GetSharedVisionList().begin();
+                for ( ; it != iter->getSource()->GetSharedVisionList().end(); ++it)
+                    SendPacket(*it);
+            }
+
             VisitObject(iter->getSource());
         }
@@ -164,7 +171,27 @@
         if (!i_dist || iter->getSource()->GetDistance(&i_source) <= i_dist)
         {
-            // Send packet to possessor
-            if (iter->getSource()->isPossessedByPlayer())
-                SendPacket((Player*)iter->getSource()->GetCharmer());
+            // Send packet to all who are sharing the creature's vision
+            if (!iter->getSource()->GetSharedVisionList().empty())
+            {
+                SharedVisionList::const_iterator it = iter->getSource()->GetSharedVisionList().begin();
+                for ( ; it != iter->getSource()->GetSharedVisionList().end(); ++it)
+                    SendPacket(*it);
+            }
+        }
+    }
+}
+
+void
+Deliverer::Visit(DynamicObjectMapType &m)
+{
+    for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
+    {
+        if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID()))
+        {
+            // Send packet back to the caster if the caster has vision of dynamic object
+            Player* caster = (Player*)iter->getSource()->GetCaster();
+            if (caster->GetUInt64Value(PLAYER_FARSIGHT) == iter->getSource()->GetGUID() &&
+                (!i_dist || iter->getSource()->GetDistance(&i_source) <= i_dist))
+                SendPacket(caster);
         }
     }
@@ -176,4 +203,9 @@
     if (!plr)
         return;
+
+    // Don't send the packet to self if not supposed to
+    if (!i_toSelf && plr == &i_source)
+        return;
+
     // Don't send the packet to possesor if not supposed to
     if (!i_toPossessor && plr->isPossessing() && plr->GetCharmGUID() == i_source.GetGUID())
@@ -191,6 +223,5 @@
 MessageDeliverer::VisitObject(Player* plr)
 {
-    if (i_toSelf || plr != &i_source)
-        SendPacket(plr);
+    SendPacket(plr);
 }
 
@@ -198,6 +229,5 @@
 MessageDistDeliverer::VisitObject(Player* plr)
 {
-    if( (i_toSelf || plr != &i_source ) &&
-        (!i_ownTeamOnly || (i_source.GetTypeId() == TYPEID_PLAYER && plr->GetTeam() == ((Player&)i_source).GetTeam())) )
+    if( !i_ownTeamOnly || (i_source.GetTypeId() == TYPEID_PLAYER && plr->GetTeam() == ((Player&)i_source).GetTeam()) )
     {
         SendPacket(plr);
Index: /trunk/src/game/Totem.h
===================================================================
--- /trunk/src/game/Totem.h (revision 102)
+++ /trunk/src/game/Totem.h (revision 233)
@@ -30,4 +30,6 @@
     TOTEM_STATUE     = 2
 };
+
+#define SENTRY_TOTEM_ENTRY  3968
 
 class Totem : public Creature
Index: /trunk/src/game/ObjectAccessor.cpp
===================================================================
--- /trunk/src/game/ObjectAccessor.cpp (revision 206)
+++ /trunk/src/game/ObjectAccessor.cpp (revision 233)
@@ -625,6 +625,10 @@
     {
         BuildPacket(iter->getSource());
-        if (iter->getSource()->isPossessedByPlayer())
-            BuildPacket((Player*)iter->getSource()->GetCharmer());
+        if (!iter->getSource()->GetSharedVisionList().empty())
+        {
+            SharedVisionList::const_iterator it = iter->getSource()->GetSharedVisionList().begin();
+            for ( ; it != iter->getSource()->GetSharedVisionList().end(); ++it)
+                BuildPacket(*it);
+        }
     }
 }
@@ -634,6 +638,26 @@
 {
     for(CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
-        if (iter->getSource()->isPossessedByPlayer())
-            BuildPacket((Player*)iter->getSource()->GetCharmer());
+    {
+        if (!iter->getSource()->GetSharedVisionList().empty())
+        {
+            SharedVisionList::const_iterator it = iter->getSource()->GetSharedVisionList().begin();
+            for ( ; it != iter->getSource()->GetSharedVisionList().end(); ++it)
+                BuildPacket(*it);
+        }
+    }
+}
+
+void
+ObjectAccessor::WorldObjectChangeAccumulator::Visit(DynamicObjectMapType &m)
+{
+    for(DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
+    {
+        if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID()))
+        {
+            Player* caster = (Player*)iter->getSource()->GetCaster();
+            if (caster->GetUInt64Value(PLAYER_FARSIGHT) == iter->getSource()->GetGUID())
+                BuildPacket(caster);
+        }
+    }
 }
 
Index: /trunk/sql/updates/241_world.sql
===================================================================
--- /trunk/sql/updates/241_world.sql (revision 233)
+++ /trunk/sql/updates/241_world.sql (revision 233)
@@ -0,0 +1,4 @@
+DELETE FROM `command` WHERE name IN ('bindsight', 'unbindsight');
+INSERT INTO `command` (name,security,help) VALUES
+('bindsight',3,'Syntax: .bindsight\r\n\r\nBinds vision to the selected unit indefinitely. Cannot be used while currently possessing a target.'),
+('unbindsight',3,'Syntax: .unbindsight\r\n\r\nRemoves bound vision. Cannot be used while currently possessing a target.');
