Index: trunk/src/game/Chat.h
===================================================================
--- trunk/src/game/Chat.h (revision 112)
+++ trunk/src/game/Chat.h (revision 132)
@@ -72,4 +72,5 @@
         int ParseCommands(const char* text);
 
+    virtual char const* GetName() const;
     protected:
 		explicit ChatHandler() : m_session(NULL) {}      // for CLI subclass
@@ -78,4 +79,5 @@
 
 		virtual bool isAvailable(ChatCommand const& cmd) const;
+        virtual bool needReportToTarget(Player* chr) const;
 
         void SendGlobalSysMessage(const char *str);
@@ -151,4 +153,7 @@
         bool HandleModifyRepCommand(const char* args);
         bool HandleModifyArenaCommand(const char* args);
+        
+        bool HandleNpcFollowCommand(const char* args);
+        bool HandleNpcUnFollowCommand(const char* args);
 
         bool HandleReloadCommand(const char* args);
@@ -350,4 +355,5 @@
         bool HandleNpcInfoCommand(const char* args);
         bool HandleHoverCommand(const char* args);
+        bool HandleWaterwalkCommand(const char* args);
         bool HandleLevelUpCommand(const char* args);
         bool HandleShowAreaCommand(const char* args);
@@ -417,5 +423,7 @@
         bool HandleComeToMeCommand(const char *args);
         bool HandleCombatStopCommand(const char *args);
+        bool HandleCharDeleteCommand(const char *args);
 		bool HandleSendMessageCommand(const char * args);
+        bool HandleRepairitemsCommand(const char* args);
         bool HandleFlushArenaPointsCommand(const char *args);
 
@@ -474,4 +482,6 @@
 		bool isAvailable(ChatCommand const& cmd) const;
 		void SendSysMessage(const char *str);
+        char const* GetName() const;
+        bool needReportToTarget(Player* chr) const;
 
 	private:
Index: trunk/src/game/Level1.cpp
===================================================================
--- trunk/src/game/Level1.cpp (revision 112)
+++ trunk/src/game/Level1.cpp (revision 132)
@@ -325,5 +325,5 @@
 
     sLog.outDebug("Player %s GPS call for %s '%s' (%s: %u):",
-        m_session->GetPlayer()->GetName(),
+        GetName(),
         (obj->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), obj->GetName(),
         (obj->GetTypeId() == TYPEID_PLAYER ? "GUID" : "Entry"), (obj->GetTypeId() == TYPEID_PLAYER ? obj->GetGUIDLow(): obj->GetEntry()) );
@@ -397,7 +397,6 @@
 
         PSendSysMessage(LANG_SUMMONING, chr->GetName(),"");
-
-        if (m_session->GetPlayer()->IsVisibleGloballyFor(chr))
-            ChatHandler(chr).PSendSysMessage(LANG_SUMMONED_BY, m_session->GetPlayer()->GetName());
+        if (needReportToTarget(chr))
+            ChatHandler(chr).PSendSysMessage(LANG_SUMMONED_BY, GetName());
 
         // stop flight if need
@@ -698,5 +697,6 @@
 
     PSendSysMessage(LANG_YOU_CHANGE_HP, chr->GetName(), hp, hpm);
-    ChatHandler(chr).PSendSysMessage(LANG_YOURS_HP_CHANGED, m_session->GetPlayer()->GetName(), hp, hpm);
+    if (needReportToTarget(chr))
+        ChatHandler(chr).PSendSysMessage(LANG_YOURS_HP_CHANGED, GetName(), hp, hpm);
 
     chr->SetMaxHealth( hpm );
@@ -741,5 +741,6 @@
 
     PSendSysMessage(LANG_YOU_CHANGE_MANA, chr->GetName(), mana, manam);
-    ChatHandler(chr).PSendSysMessage(LANG_YOURS_MANA_CHANGED, m_session->GetPlayer()->GetName(), mana, manam);
+    if (needReportToTarget(chr))
+        ChatHandler(chr).PSendSysMessage(LANG_YOURS_MANA_CHANGED, GetName(), mana, manam);
 
     chr->SetMaxPower(POWER_MANA,manam );
@@ -785,5 +786,6 @@
 
     PSendSysMessage(LANG_YOU_CHANGE_ENERGY, chr->GetName(), energy/10, energym/10);
-    ChatHandler(chr).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, m_session->GetPlayer()->GetName(), energy/10, energym/10);
+    if (needReportToTarget(chr))
+        ChatHandler(chr).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, GetName(), energy/10, energym/10);
 
     chr->SetMaxPower(POWER_ENERGY,energym );
@@ -831,5 +833,6 @@
 
     PSendSysMessage(LANG_YOU_CHANGE_RAGE, chr->GetName(), rage/10, ragem/10);
-    ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_YOURS_RAGE_CHANGED), m_session->GetPlayer()->GetName(), rage/10, ragem/10);
+    if (needReportToTarget(chr))
+        ChatHandler(chr).PSendSysMessage(LANG_YOURS_RAGE_CHANGED, GetName(), rage/10, ragem/10);
 
     chr->SetMaxPower(POWER_RAGE,ragem );
@@ -908,9 +911,4 @@
 
     PSendSysMessage(LANG_YOU_CHANGE_FACTION, chr->GetGUIDLow(),factionid,flag,npcflag,dyflag);
-
-    //sprintf((char*)buf,"%s changed your Faction to %i.", m_session->GetPlayer()->GetName(), factionid);
-    //FillSystemMessageData(&data, m_session, buf);
-
-    //chr->GetSession()->SendPacket(&data);
 
     chr->setFaction(factionid);
@@ -959,6 +957,6 @@
 
     PSendSysMessage(LANG_YOU_CHANGE_SPELLFLATID, spellflatid, val, mark, chr->GetName());
-    if(chr != m_session->GetPlayer())
-        ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLFLATID_CHANGED, m_session->GetPlayer()->GetName(), spellflatid, val, mark);
+    if (needReportToTarget(chr))
+        ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLFLATID_CHANGED, GetName(), spellflatid, val, mark);
 
     WorldPacket data(SMSG_SET_FLAT_SPELL_MODIFIER, (1+1+2+2));
@@ -1016,8 +1014,6 @@
         chr->SetTaxiCheater(true);
         PSendSysMessage(LANG_YOU_GIVE_TAXIS, chr->GetName());
-
-        if(chr != m_session->GetPlayer())
-            // to send localized data to target
-            ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_YOURS_TAXIS_ADDED), m_session->GetPlayer()->GetName());
+        if (needReportToTarget(chr))
+            ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, GetName());
         return true;
     }
@@ -1027,7 +1023,6 @@
         chr->SetTaxiCheater(false);
         PSendSysMessage(LANG_YOU_REMOVE_TAXIS, chr->GetName());
-
-        if(chr != m_session->GetPlayer())
-            ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_YOURS_TAXIS_REMOVED), m_session->GetPlayer()->GetName());
+        if (needReportToTarget(chr))
+            ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, GetName());
 
         return true;
@@ -1070,7 +1065,6 @@
 
     PSendSysMessage(LANG_YOU_CHANGE_ASPEED, ASpeed, chr->GetName());
-
-    if(chr != m_session->GetPlayer())
-        ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_YOURS_ASPEED_CHANGED), m_session->GetPlayer()->GetName(), ASpeed);
+    if (needReportToTarget(chr))
+        ChatHandler(chr).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, GetName(), ASpeed);
 
     chr->SetSpeed(MOVE_WALK,    ASpeed,true);
@@ -1113,7 +1107,6 @@
 
     PSendSysMessage(LANG_YOU_CHANGE_SPEED, Speed, chr->GetName());
-
-    if(chr != m_session->GetPlayer())
-        ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_YOURS_SPEED_CHANGED), m_session->GetPlayer()->GetName(), Speed);
+    if (needReportToTarget(chr))
+        ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, GetName(), Speed);
 
     chr->SetSpeed(MOVE_RUN,Speed,true);
@@ -1153,7 +1146,6 @@
 
     PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, Swim, chr->GetName());
-
-    if(chr != m_session->GetPlayer())
-        ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_YOURS_SWIM_SPEED_CHANGED), m_session->GetPlayer()->GetName(), Swim);
+    if (needReportToTarget(chr))
+        ChatHandler(chr).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, GetName(), Swim);
 
     chr->SetSpeed(MOVE_SWIM,Swim,true);
@@ -1193,7 +1185,6 @@
 
     PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, BSpeed, chr->GetName());
-
-    if(chr != m_session->GetPlayer())
-        ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_YOURS_BACK_SPEED_CHANGED), m_session->GetPlayer()->GetName(), BSpeed);
+    if (needReportToTarget(chr))
+        ChatHandler(chr).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, GetName(), BSpeed);
 
     chr->SetSpeed(MOVE_WALKBACK,BSpeed,true);
@@ -1226,7 +1217,6 @@
 
     PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, FSpeed, chr->GetName());
-
-    if(chr != m_session->GetPlayer())
-        ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_YOURS_FLY_SPEED_CHANGED), m_session->GetPlayer()->GetName(), FSpeed);
+    if (needReportToTarget(chr))
+        ChatHandler(chr).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, GetName(), FSpeed);
 
     chr->SetSpeed(MOVE_FLY,FSpeed,true);
@@ -1258,7 +1248,6 @@
 
     PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, chr->GetName());
-
-    if(chr != m_session->GetPlayer())
-        ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_YOURS_SIZE_CHANGED), m_session->GetPlayer()->GetName(), Scale);
+    if (needReportToTarget(chr))
+        ChatHandler(chr).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, GetName(), Scale);
 
     chr->SetFloatValue(OBJECT_FIELD_SCALE_X, Scale);
@@ -1502,7 +1491,6 @@
 
     PSendSysMessage(LANG_YOU_GIVE_MOUNT, chr->GetName());
-
-    if(chr != m_session->GetPlayer())
-        ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_MOUNT_GIVED), m_session->GetPlayer()->GetName());
+    if (needReportToTarget(chr))
+        ChatHandler(chr).PSendSysMessage(LANG_MOUNT_GIVED, GetName());
 
     chr->SetUInt32Value( UNIT_FIELD_FLAGS , 0x001000 );
@@ -1551,7 +1539,6 @@
         {
             PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, chr->GetName());
-
-            if(chr != m_session->GetPlayer())
-                ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_YOURS_ALL_MONEY_GONE), m_session->GetPlayer()->GetName());
+            if (needReportToTarget(chr))
+                ChatHandler(chr).PSendSysMessage(LANG_YOURS_ALL_MONEY_GONE, GetName());
 
             chr->SetMoney(0);
@@ -1560,6 +1547,6 @@
         {
             PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), chr->GetName());
-            if(chr != m_session->GetPlayer())
-                ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_YOURS_MONEY_TAKEN), m_session->GetPlayer()->GetName(), abs(addmoney));
+            if (needReportToTarget(chr))
+                ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, GetName(), abs(addmoney));
             chr->SetMoney( newmoney );
         }
@@ -1568,6 +1555,6 @@
     {
         PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, chr->GetName());
-        if(chr != m_session->GetPlayer())
-            ChatHandler(chr).PSendSysMessage(ChatHandler(chr).GetTrinityString(LANG_YOURS_MONEY_GIVEN), m_session->GetPlayer()->GetName(), addmoney);
+        if (needReportToTarget(chr))
+            ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, GetName(), addmoney);
         chr->ModifyMoney( addmoney );
     }
@@ -1662,4 +1649,5 @@
     // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r
     GameTele const* tele = extractGameTeleFromLink((char*)args);
+
     if (!tele)
     {
@@ -2075,12 +2063,6 @@
 
         PSendSysMessage(LANG_TELEPORTING_TO, chr->GetName(),"", tele->name.c_str());
-
-        if (m_session)
-		{
-			if(m_session->GetPlayer()->IsVisibleGloballyFor(chr))
-				ChatHandler(chr).PSendSysMessage(LANG_TELEPORTED_TO_BY, m_session->GetPlayer()->GetName());
-		}
-		else
-			ChatHandler(chr).SendSysMessage(LANG_TELEPORTED_TO_BY_CONSOLE);
+        if (needReportToTarget(chr))
+            ChatHandler(chr).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetName());
 
         // stop flight if need
@@ -2159,7 +2141,6 @@
 
         PSendSysMessage(LANG_TELEPORTING_TO, pl->GetName(),"", tele->name.c_str());
-
-        if (m_session->GetPlayer() != pl && m_session->GetPlayer()->IsVisibleGloballyFor(pl))
-            ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, m_session->GetPlayer()->GetName());
+        if (needReportToTarget(pl))
+            ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetName());
 
         // stop flight if need
@@ -2253,7 +2234,6 @@
 
         PSendSysMessage(LANG_SUMMONING, pl->GetName(),"");
-
-        if (m_session->GetPlayer()->IsVisibleGloballyFor(pl))
-            ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, m_session->GetPlayer()->GetName());
+        if (needReportToTarget(pl))
+            ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, GetName());
 
         // stop flight if need
Index: trunk/src/game/Level3.cpp
===================================================================
--- trunk/src/game/Level3.cpp (revision 112)
+++ trunk/src/game/Level3.cpp (revision 132)
@@ -748,5 +748,5 @@
     if(targetPlayer)
     {
-        ChatHandler(targetPlayer).PSendSysMessage(LANG_YOURS_SECURITY_CHANGED,m_session->GetPlayer()->GetName(), gm);
+        ChatHandler(targetPlayer).PSendSysMessage(LANG_YOURS_SECURITY_CHANGED,GetName(), gm);
         targetPlayer->GetSession()->SetSecurity(gm);
     }
@@ -3729,12 +3729,12 @@
     {
         PSendSysMessage(LANG_YOU_SET_EXPLORE_ALL, chr->GetName());
-        if(chr!=m_session->GetPlayer())
-            ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL,m_session->GetPlayer()->GetName());
+        if (needReportToTarget(chr))
+            ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL,GetName());
     }
     else
     {
         PSendSysMessage(LANG_YOU_SET_EXPLORE_NOTHING, chr->GetName());
-        if(chr!=m_session->GetPlayer())
-            ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING,m_session->GetPlayer()->GetName());
+        if (needReportToTarget(chr))
+            ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING,GetName());
     }
 
@@ -3771,4 +3771,34 @@
 
     return true;
+}
+
+bool ChatHandler::HandleWaterwalkCommand(const char* args)
+{
+    if(!args)
+        return false;
+
+    Player *player = getSelectedPlayer();
+    if(!player)
+    {
+        PSendSysMessage(LANG_NO_CHAR_SELECTED);
+        SetSentErrorMessage(true);
+        return false;
+    }
+        
+    if (strncmp(args, "on", 3) == 0)
+        player->SetMovement(MOVE_WATER_WALK);               // ON
+    else if (strncmp(args, "off", 4) == 0)
+        player->SetMovement(MOVE_LAND_WALK);                // OFF
+    else
+    {
+        SendSysMessage(LANG_USE_BOL);
+        return false;
+    }
+
+    PSendSysMessage(LANG_YOU_SET_WATERWALK, args, player->GetName());
+    if(needReportToTarget(player))
+        ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetName());
+    return true;
+
 }
 
Index: trunk/src/game/Chat.cpp
===================================================================
--- trunk/src/game/Chat.cpp (revision 129)
+++ trunk/src/game/Chat.cpp (revision 132)
@@ -387,4 +387,6 @@
 		{ "info",           SEC_ADMINISTRATOR,  false, &ChatHandler::HandleNpcInfoCommand,             "", NULL },
 		{ "playemote",      SEC_ADMINISTRATOR,  false, &ChatHandler::HandlePlayEmoteCommand,           "", NULL },
+        { "follow",         SEC_GAMEMASTER,     false, &ChatHandler::HandleNpcFollowCommand,           "", NULL },
+        { "unfollow",       SEC_GAMEMASTER,     false, &ChatHandler::HandleNpcUnFollowCommand,         "", NULL },
 
         //{ TODO: fix or remove this commands
@@ -511,4 +513,5 @@
 		{ "explorecheat",   SEC_ADMINISTRATOR,  false, &ChatHandler::HandleExploreCheatCommand,        "", NULL },
 		{ "hover",          SEC_ADMINISTRATOR,  false, &ChatHandler::HandleHoverCommand,               "", NULL },
+        { "waterwalk",          SEC_ADMINISTRATOR,  false, &ChatHandler::HandleWaterwalkCommand,               "", NULL },
 		{ "levelup",        SEC_ADMINISTRATOR,  false, &ChatHandler::HandleLevelUpCommand,             "", NULL },
 		{ "showarea",       SEC_ADMINISTRATOR,  false, &ChatHandler::HandleShowAreaCommand,            "", NULL },
@@ -536,6 +539,7 @@
 		{ "damage",         SEC_ADMINISTRATOR,  false, &ChatHandler::HandleDamageCommand,              "", NULL },
 		{ "combatstop",     SEC_GAMEMASTER,     false, &ChatHandler::HandleCombatStopCommand,          "", NULL },
-		{ "chardelete",     SEC_CONSOLE,        true,  &ChatHandler::HandleCombatStopCommand,          "", NULL },
+		{ "chardelete",     SEC_CONSOLE,        true,  &ChatHandler::HandleCharDeleteCommand,          "", NULL },
 		{ "sendmessage",    SEC_ADMINISTRATOR,  true,  &ChatHandler::HandleSendMessageCommand,         "", NULL },
+        { "repairitems",    SEC_GAMEMASTER,     false, &ChatHandler::HandleRepairitemsCommand,         "", NULL },
 		{ "freeze",         SEC_ADMINISTRATOR,  false, &ChatHandler::HandleFreezeCommand,              "", NULL }, 
 		{ "unfreeze",       SEC_ADMINISTRATOR,  false, &ChatHandler::HandleUnFreezeCommand,            "", NULL }, 
@@ -1208,4 +1212,15 @@
 }
 
+const char *ChatHandler::GetName() const
+{
+    return m_session->GetPlayer()->GetName();
+}
+
+bool ChatHandler::needReportToTarget(Player* chr) const
+{
+    Player* pl = m_session->GetPlayer();
+    return pl != chr && pl->IsVisibleGloballyFor(chr);
+}
+    
 const char *CliHandler::GetTrinityString(int32 entry) const
 {
@@ -1223,4 +1238,14 @@
 	m_print(str);
 	m_print("\r\n");
+}
+
+const char *CliHandler::GetName() const
+{
+    return GetTrinityString(LANG_CONSOLE_COMMAND);
+}
+
+bool CliHandler::needReportToTarget(Player* /*chr*/) const
+{
+    return true;
 }
 
Index: trunk/src/game/Group.h
===================================================================
--- trunk/src/game/Group.h (revision 111)
+++ trunk/src/game/Group.h (revision 132)
@@ -184,6 +184,6 @@
 
         // member manipulation methods
-        bool IsMember(uint64 guid) const { return _getMemberCSlot(guid) != m_memberSlots.end(); }
-        bool IsLeader(uint64 guid) const { return (GetLeaderGUID() == guid); }
+        bool IsMember(const uint64& guid) const { return _getMemberCSlot(guid) != m_memberSlots.end(); }
+		bool IsLeader(const uint64& guid) const { return (GetLeaderGUID() == guid); }
         bool IsAssistant(uint64 guid) const
         {
@@ -195,5 +195,5 @@
         }
 
-        bool SameSubGroup(uint64 guid1, uint64 guid2) const
+        bool SameSubGroup(uint64 guid1,const uint64& guid2) const
         {
             member_citerator mslot2 = _getMemberCSlot(guid2);
@@ -212,4 +212,9 @@
             return (mslot1->group==slot2->group);
         }
+		
+		bool HasFreeSlotSubGroup(uint8 subgroup) const
+		{
+			return (m_subGroupsCounts && m_subGroupsCounts[subgroup] < MAXGROUPSIZE);
+		}
 
         bool SameSubGroup(Player const* member1, Player const* member2) const;
@@ -229,9 +234,6 @@
 
         // some additional raid methods
-        void ConvertToRaid()
-        {
-            _convertToRaid();
-            SendUpdate();
-        }
+        void ConvertToRaid();
+
         void SetBattlegroundGroup(BattleGround *bg) { m_bgGroup = bg; }
         uint32 CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot);
@@ -240,5 +242,5 @@
         void ChangeMembersGroup(Player *player, const uint8 &group);
 
-        void SetAssistant(const uint64 &guid, const bool &state)
+        void SetAssistant(uint64 guid, const bool &state)
         {
             if(!isRaidGroup())
@@ -247,5 +249,5 @@
                 SendUpdate();
         }
-        void SetMainTank(const uint64 &guid)
+        void SetMainTank(uint64 guid)
         {
             if(!isRaidGroup())
@@ -255,5 +257,5 @@
                 SendUpdate();
         }
-        void SetMainAssistant(const uint64 &guid)
+        void SetMainAssistant(uint64 guid)
         {
             if(!isRaidGroup())
@@ -286,10 +288,10 @@
 
         void SendLootStartRoll(uint32 CountDown, const Roll &r);
-        void SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r);
-        void SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r);
+        void SendLootRoll(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r);
+        void SendLootRollWon(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r);
         void SendLootAllPassed(uint32 NumberOfPlayers, const Roll &r);
-        void GroupLoot(uint64 playerGUID, Loot *loot, Creature *creature);
-        void NeedBeforeGreed(uint64 playerGUID, Loot *loot, Creature *creature);
-        void MasterLoot(uint64 playerGUID, Loot *loot, Creature *creature);
+        void GroupLoot(const uint64& playerGUID, Loot *loot, Creature *creature);
+		void NeedBeforeGreed(const uint64& playerGUID, Loot *loot, Creature *creature);
+		void MasterLoot(const uint64& playerGUID, Loot *loot, Creature *creature);
         Rolls::iterator GetRoll(uint64 Guid)
         {
@@ -305,5 +307,5 @@
         }
         void CountTheRoll(Rolls::iterator roll, uint32 NumberOfPlayers);
-        void CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise);
+        void CountRollVote(const uint64& playerGUID, const uint64& Guid, uint32 NumberOfPlayers, uint8 Choise);
         void EndRoll();
 
@@ -324,5 +326,4 @@
         void _removeRolls(const uint64 &guid);
 
-        void _convertToRaid();
         bool _setMembersGroup(const uint64 &guid, const uint8 &group);
         bool _setAssistantFlag(const uint64 &guid, const bool &state);
@@ -331,4 +332,16 @@
 
         void _homebindIfInstance(Player *player);
+		
+		void _initRaidSubGroupsCounter()
+		{
+			// Sub group counters initialization
+			if (!m_subGroupsCounts)
+				m_subGroupsCounts = new uint8[MAXRAIDSIZE / MAXGROUPSIZE];
+				
+			memset((void*)m_subGroupsCounts, 0, (MAXRAIDSIZE / MAXGROUPSIZE)*sizeof(uint8));
+			
+			for (member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
+				++m_subGroupsCounts[itr->group];
+		}
 
         member_citerator _getMemberCSlot(uint64 Guid) const
@@ -351,4 +364,16 @@
             return m_memberSlots.end();
         }
+		
+		void SubGroupCounterIncrease(uint8 subgroup)
+		{
+			if (m_subGroupsCounts)
+				++m_subGroupsCounts[subgroup];
+		}
+		
+		void SubGroupCounterDecrease(uint8 subgroup)
+		{
+			if (m_subGroupsCounts)
+				--m_subGroupsCounts[subgroup];
+		}
 
         MemberSlotList      m_memberSlots;
@@ -368,4 +393,5 @@
         Rolls               RollId;
         BoundInstancesMap   m_boundInstances[TOTAL_DIFFICULTIES];
+		uint8*              m_subGroupsCounts;
 };
 #endif
Index: trunk/src/game/GroupHandler.cpp
===================================================================
--- trunk/src/game/GroupHandler.cpp (revision 102)
+++ trunk/src/game/GroupHandler.cpp (revision 132)
@@ -552,4 +552,7 @@
     if(!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
         return;
+        
+    if (!group->HasFreeSlotSubGroup(groupNr))
+        return;
     /********************/
 
Index: trunk/src/game/MapManager.cpp
===================================================================
--- trunk/src/game/MapManager.cpp (revision 102)
+++ trunk/src/game/MapManager.cpp (revision 132)
@@ -166,5 +166,5 @@
                     // probably there must be special opcode, because client has this string constant in GlobalStrings.lua
                     // TODO: this is not a good place to send the message
-                    player->GetSession()->SendAreaTriggerMessage("You must be in a raid group to enter %s instance", mapName);
+                    player->GetSession()->SendAreaTriggerMessage(player->GetSession()->GetTrinityString(810), mapName);
                     sLog.outDebug("MAP: Player '%s' must be in a raid group to enter instance of '%s'", player->GetName(), mapName);
                     return false;
@@ -198,5 +198,5 @@
                 if (!instance_map)
                 {
-                    player->GetSession()->SendAreaTriggerMessage("You cannot enter %s while in a ghost mode", mapName);
+                    player->GetSession()->SendAreaTriggerMessage(player->GetSession()->GetTrinityString(811), mapName);
                     sLog.outDebug("MAP: Player '%s' doesn't has a corpse in instance '%s' and can't enter", player->GetName(), mapName);
                     return false;
Index: trunk/src/game/Level2.cpp
===================================================================
--- trunk/src/game/Level2.cpp (revision 112)
+++ trunk/src/game/Level2.cpp (revision 132)
@@ -44,4 +44,6 @@
 #include <map>
 #include "GlobalEvents.h"
+
+#include "TargetedMovementGenerator.h"                      // for HandleNpcUnFollowCommand
 
 static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] =
@@ -4053,2 +4055,78 @@
 	return true;
 }
+
+bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/)
+{
+    Player *target = getSelectedPlayer();
+
+    if(!target)
+    {
+        PSendSysMessage(LANG_NO_CHAR_SELECTED);
+        SetSentErrorMessage(true);
+        return false;
+	}
+
+    // Repair items
+    target->DurabilityRepairAll(false, 0, false);
+
+    PSendSysMessage(LANG_YOU_REPAIR_ITEMS, target->GetName());
+    if(needReportToTarget(target))
+        ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetName());
+    return true;
+}
+
+bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
+{
+    Player *player = m_session->GetPlayer();
+    Creature *creature = getSelectedCreature();
+
+    if(!creature)
+    {
+        PSendSysMessage(LANG_SELECT_CREATURE);
+        SetSentErrorMessage(true);
+        return false;
+    }
+
+    // Follow player - Using pet's default dist and angle
+    creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+
+    PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
+    return true;
+}
+
+bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
+{
+    Player *player = m_session->GetPlayer();
+    Creature *creature = getSelectedCreature();
+
+    if(!creature)
+    {
+        PSendSysMessage(LANG_SELECT_CREATURE);
+        SetSentErrorMessage(true);
+        return false;
+    }
+
+    if (creature->GetMotionMaster()->empty() ||
+        creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE)
+    {
+        PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
+        SetSentErrorMessage(true);
+        return false;
+    }
+
+    TargetedMovementGenerator<Creature> const* mgen
+        = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
+
+    if(mgen->GetTarget()!=player)
+    {
+        PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
+        SetSentErrorMessage(true);
+        return false;
+    }
+
+    // reset movement
+    creature->GetMotionMaster()->MovementExpired(true);
+
+    PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
+    return true;
+}
Index: trunk/src/game/Group.cpp
===================================================================
--- trunk/src/game/Group.cpp (revision 111)
+++ trunk/src/game/Group.cpp (revision 132)
@@ -45,4 +45,5 @@
     m_looterGuid        = 0;
     m_lootThreshold     = ITEM_QUALITY_UNCOMMON;
+	m_subGroupsCounts   = NULL;
 
     for(int i=0; i<TARGETICONCOUNT; i++)
@@ -74,4 +75,6 @@
         for(BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
             itr->second.save->RemoveGroup(this);
+	if (m_subGroupsCounts)
+		delete[] m_subGroupsCounts;
 }
 
@@ -82,4 +85,8 @@
 
     m_groupType  = isBGGroup() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL;
+	
+	if (m_groupType == GROUPTYPE_RAID)
+		_initRaidSubGroupsCounter();
+		
     m_lootMethod = GROUP_LOOT;
     m_lootThreshold = ITEM_QUALITY_UNCOMMON;
@@ -137,4 +144,8 @@
 
     m_groupType  = (*result)[13].GetBool() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL;
+	
+	if (m_groupType == GROUPTYPE_RAID)
+		_initRaidSubGroupsCounter();
+		
     m_difficulty = (*result)[14].GetUInt8();
     m_mainTank = (*result)[0].GetUInt64();
@@ -179,5 +190,18 @@
     member.assistant = assistant;
     m_memberSlots.push_back(member);
+	
+	SubGroupCounterIncrease(subgroup);
+	
     return true;
+}
+
+void Group::ConvertToRaid()
+{
+	m_groupType = GROUPTYPE_RAID;
+	
+	_initRaidSubGroupsCounter();
+	
+	if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
+	SendUpdate();
 }
 
@@ -387,5 +411,5 @@
 }
 
-void Group::SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r)
+void Group::SendLootRoll(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r)
 {
     WorldPacket data(SMSG_LOOT_ROLL, (8+4+8+4+4+4+1+1));
@@ -411,5 +435,5 @@
 }
 
-void Group::SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r)
+void Group::SendLootRollWon(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r)
 {
     WorldPacket data(SMSG_LOOT_ROLL_WON, (8+4+4+4+4+8+1+1));
@@ -454,5 +478,5 @@
 }
 
-void Group::GroupLoot(uint64 playerGUID, Loot *loot, Creature *creature)
+void Group::GroupLoot(const uint64& playerGUID, Loot *loot, Creature *creature)
 {
     std::vector<LootItem>::iterator i;
@@ -510,5 +534,5 @@
 }
 
-void Group::NeedBeforeGreed(uint64 playerGUID, Loot *loot, Creature *creature)
+void Group::NeedBeforeGreed(const uint64& playerGUID, Loot *loot, Creature *creature)
 {
     ItemPrototype const *item;
@@ -564,5 +588,5 @@
 }
 
-void Group::MasterLoot(uint64 playerGUID, Loot* /*loot*/, Creature *creature)
+void Group::MasterLoot(const uint64& playerGUID, Loot* /*loot*/, Creature *creature)
 {
     Player *player = objmgr.GetPlayer(playerGUID);
@@ -600,5 +624,5 @@
 }
 
-void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise)
+void Group::CountRollVote(const uint64& playerGUID, const uint64& Guid, uint32 NumberOfPlayers, uint8 Choise)
 {
     Rolls::iterator rollI = GetRoll(Guid);
@@ -936,11 +960,18 @@
     // get first not-full group
     uint8 groupid = 0;
-    std::vector<uint8> temp(MAXRAIDSIZE/MAXGROUPSIZE);
-    for(member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
-    {
-        if (itr->group >= temp.size()) continue;
-        ++temp[itr->group];
-        if(temp[groupid] >= MAXGROUPSIZE)
-            ++groupid;
+    if (m_subGroupsCounts)
+    {
+        bool groupFound = false;
+		for (; groupid < MAXRAIDSIZE/MAXGROUPSIZE; ++groupid)
+		{
+			if (m_subGroupsCounts[groupid] < MAXGROUPSIZE)
+			{
+				groupFound = true;
+				break;
+			}
+		}
+		// We are raid group and no one slot is free
+		if (!groupFound)
+				return false;
     }
 
@@ -964,4 +995,6 @@
     member.assistant = isAssistant;
     m_memberSlots.push_back(member);
+	
+	SubGroupCounterIncrease(group);
 
     if(player)
@@ -1002,5 +1035,8 @@
     member_witerator slot = _getMemberWSlot(guid);
     if (slot != m_memberSlots.end())
+	{
+		SubGroupCounterDecrease(slot->group);
         m_memberSlots.erase(slot);
+	}
 
     if(!isBGGroup())
@@ -1095,11 +1131,4 @@
 }
 
-void Group::_convertToRaid()
-{
-    m_groupType = GROUPTYPE_RAID;
-
-    if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
-}
-
 bool Group::_setMembersGroup(const uint64 &guid, const uint8 &group)
 {
@@ -1109,5 +1138,9 @@
 
     slot->group = group;
+	
+	SubGroupCounterIncrease(group);
+	
     if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE group_member SET subgroup='%u' WHERE memberGuid='%u'", group, GUID_LOPART(guid));
+	
     return true;
 }
@@ -1165,8 +1198,14 @@
     if (!player)
     {
+		uint8 prevSubGroup;
+		prevSubGroup = GetMemberGroup(guid);
+		
+		SubGroupCounterDecrease(prevSubGroup);
+		
         if(_setMembersGroup(guid, group))
             SendUpdate();
     }
-    else ChangeMembersGroup(player, group);
+    else
+		ChangeMembersGroup(player, group);
 }
 
@@ -1178,4 +1217,9 @@
     if(_setMembersGroup(player->GetGUID(), group))
     {
+		uint8 prevSubGroup;
+		prevSubGroup = player->GetSubGroup();
+		
+		SubGroupCounterDecrease(prevSubGroup);
+		
         player->GetGroupRef().setSubGroup(group);
         SendUpdate();
Index: trunk/src/game/Language.h
===================================================================
--- trunk/src/game/Language.h (revision 112)
+++ trunk/src/game/Language.h (revision 132)
@@ -168,5 +168,6 @@
     LANG_SOUND_NOT_EXIST                = 170,
     LANG_TELEPORTED_TO_BY_CONSOLE       = 171,
-	// Room for more level 1              172-199 not used
+    LANG_CONSOLE_COMMAND                = 172,
+	// Room for more level 1              173-199 not used
 
     // level 2 chat
@@ -317,5 +318,12 @@
     LANG_GM_CHAT_ON                     = 334,
     LANG_GM_CHAT_OFF                    = 335,
-    // Room for more level 2              336-399 not used
+    LANG_YOU_REPAIR_ITEMS               = 336,
+    LANG_YOUR_ITEMS_REPAIRED            = 337,
+    LANG_YOU_SET_WATERWALK              = 338,
+    LANG_YOUR_WATERWALK_SET             = 339,
+    LANG_CREATURE_FOLLOW_YOU_NOW        = 340,
+    LANG_CREATURE_NOT_FOLLOW_YOU        = 341,
+    LANG_CREATURE_NOT_FOLLOW_YOU_NOW    = 342,
+    // Room for more level 2              343-399 not used
 
     // level 3 chat
@@ -709,5 +717,5 @@
 	// Room for more level 3              1119-1199 not used
 	
-	// Trinity custom patches             5000-9999
+	// Trinity strings             5000-9999
     LANG_COMMAND_FREEZE                 = 5000,
     LANG_COMMAND_FREEZE_ERROR           = 5001,
@@ -717,5 +725,7 @@
     LANG_COMMAND_LIST_FREEZE            = 5005,
     LANG_COMMAND_FROZEN_PLAYERS         = 5006,
-	// Room for more Trinity custom patches 5007-9999
+    LANG_INSTANCE_MUST_RAID_GRP         = 5007,
+    LANG_INSTANCE_NOT_AS_GHOST          = 5008,
+	// Room for more Trinity strings 5009-9999
 
     // Use for not-in-svn patches         10000-10999
