· 9 years ago · Jun 07, 2017, 08:04 PM
1diff --git a/configure.ac b/configure.ac
2index 3111eac..732fa01 100644
3--- a/configure.ac
4+++ b/configure.ac
5@@ -273,6 +273,8 @@ AC_CONFIG_FILES([
6 src/realmd/realmd.conf.dist
7 src/mangosd/Makefile
8 src/mangosd/mangosd.conf.dist
9+ src/mangosd/mangchat.conf.dist
10+ src/game/mangchat/IRCConf.h
11 src/bindings/Makefile
12 src/bindings/universal/Makefile
13 ])
14diff --git a/sql/MangChat.sql b/sql/MangChat.sql
15new file mode 100644
16index 0000000..ad71f21
17--- a/sql/MangChat.sql
18+++ b/sql/MangChat.sql
19@@ -0,0 +1,74 @@
20+SET FOREIGN_KEY_CHECKS=0;
21+-- ----------------------------
22+-- Table structure for IRC_Commands
23+-- ----------------------------
24+DROP TABLE IF EXISTS `IRC_Commands`;
25+CREATE TABLE `IRC_Commands` (
26+ `Command` varchar(10) NOT NULL default '',
27+ `Description` varchar(150) NOT NULL default '',
28+ `gmlevel` tinyint(3) unsigned NOT NULL default '0',
29+ PRIMARY KEY (`Command`)
30+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='IRC Module System';
31+
32+-- ----------------------------
33+-- Records
34+-- ----------------------------
35+INSERT INTO `IRC_Commands` VALUES ('acct', '[acct <Player> <(un)lock/mail/pass/rename>] : Perform Action To <Player> Account.', '3');
36+INSERT INTO `IRC_Commands` VALUES ('ban', '[ban <Player/IP> <ip/acct/unban/reason>] : Ban/Unban <Player>', '3');
37+INSERT INTO `IRC_Commands` VALUES ('chan', '[chan <op/deop/voice/devoice> <*IRC Nick*>] : Set Mode On Yourself, If <IRC Nick> Is Specified Then Set mode On Nick.', '3');
38+INSERT INTO `IRC_Commands` VALUES ('char', '[char <Player> <mailcheat/taxicheat/maxskill/setskill>] : Perform Action To Character.', '3');
39+INSERT INTO `IRC_Commands` VALUES ('fun', '[fun <Player> <Sound/Say>] : Do Selected Fun Action To <Player>.', '3');
40+INSERT INTO `IRC_Commands` VALUES ('help', '[help Command] : Use No Paramaters For List Of Available Commands.', '0');
41+INSERT INTO `IRC_Commands` VALUES ('inchan', '[inchan <Channel>] : Display Users In Selected In Game <Channel>', '0');
42+INSERT INTO `IRC_Commands` VALUES ('info', '[info] : Display Server Info. (Number Of Players Online/Max Since Last Restart/Uptime)', '0');
43+INSERT INTO `IRC_Commands` VALUES ('item', '[item <Player> <add> <ItemID/[ItemName]> <Amount>] : Additem To <Player>, Use <ItemID> Or <[Exact Item Name]>.', '3');
44+INSERT INTO `IRC_Commands` VALUES ('jail', '[jail <Player> <release/Reason>] : Jail Selected <Player> For <Reason>. Using release As <Reason> Releases Player.', '3');
45+INSERT INTO `IRC_Commands` VALUES ('kick', '[kick <Player> <Reason>] : Kick <Player> For <Reason>.', '3');
46+INSERT INTO `IRC_Commands` VALUES ('kill', '[kill <Player> <Reason>] : Kill <Player> For <Reason>.', '3');
47+INSERT INTO `IRC_Commands` VALUES ('level', '[level <Player> <NewLevel>] : Level <Player> To <NewLevel>. *Can Be Done Offline*', '3');
48+INSERT INTO `IRC_Commands` VALUES ('lookup', '[lookup <acct/char/creature/faction/go/item/quest/skill/spell/tele> <ID/Name>] : ', '3');
49+INSERT INTO `IRC_Commands` VALUES ('login', '[login <UserName> <Password>] : Login To MangChat Admin Mode. (Must Be Done In A PM)', '0');
50+INSERT INTO `IRC_Commands` VALUES ('logout', '[logout] : Logout Of MangChat Admin Mode.', '0');
51+INSERT INTO `IRC_Commands` VALUES ('money', '[money <Player> <(-)Money>] : Give Money To <Player>, Use - To Take Money. *Can Be Done Offline*', '3');
52+INSERT INTO `IRC_Commands` VALUES ('mute', '[mute <Player> <release/TimeInMins> <Reason>] : Mute Player For Reason, For <TimeInMins>. Using release As Time Releases Player. *Can Be Done Offline*', '3');
53+INSERT INTO `IRC_Commands` VALUES ('online', '[online] : Display All Users Logged In Game.', '0');
54+INSERT INTO `IRC_Commands` VALUES ('pm', '[pm <Player> <Message>] : Whisper <Player> In WoW <Message>.', '3');
55+INSERT INTO `IRC_Commands` VALUES ('reload', '[reload] : Reload MangChat Config Options And Security Level From DataBase.', '3');
56+INSERT INTO `IRC_Commands` VALUES ('restart', '[restart] : Restart MangChat, NOT MaNGOS World Server Itself. Forces Reconnection To IRC Server.', '3');
57+INSERT INTO `IRC_Commands` VALUES ('revive', '[revive <Player>] : Revive <Player>.', '3');
58+INSERT INTO `IRC_Commands` VALUES ('saveall', '[saveall] : Forces MaNGOS To Save All Players.', '3');
59+INSERT INTO `IRC_Commands` VALUES ('shutdown', '[shutdown <TimeInSeconds>] : Shuts The Server Down In <TimeInSeconds>, Use 0 For Immediate Shut Down', '3');
60+INSERT INTO `IRC_Commands` VALUES ('spell', '[spell <Player> <Cast/Learn/UnLearn> <SpellID>] : Make <Player> <Learn> Or <UnLearn> A Spell, Or <Cast> A Spell On A <Player>.', '3');
61+INSERT INTO `IRC_Commands` VALUES ('sysmsg', '[sysmsg <a/n/e/add/del/list> <Message>] : Broadcasts A System Message. (a-Broadcast System Message)(n-Broadcast Notify Message)(e-Event Message)', '3');
62+INSERT INTO `IRC_Commands` VALUES ('tele', '[tele <Player> <l/c/r/to> <Loc.Name/MAPID X Y Z/Recall/Player>] : Teleport Player To Location, Coords, Or Another Player. (l-Location)(c-Coords)', '3');
63+INSERT INTO `IRC_Commands` VALUES ('top', '[top <accttime/chartime/money> <limit>] : Display top stats for given option. Only GM Higher Than Config Option Can Use Limit.', '3');
64+INSERT INTO `IRC_Commands` VALUES ('who', '[who] : Displays Users Currently Logged In To MangChat.', '1');
65+
66+SET FOREIGN_KEY_CHECKS=0;
67+-- ----------------------------
68+-- Table structure for IRC_Inchan
69+-- ----------------------------
70+DROP TABLE IF EXISTS `IRC_Inchan`;
71+CREATE TABLE `IRC_Inchan` (
72+ `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier',
73+ `name` varchar(12) NOT NULL default '',
74+ `channel` varchar(15) NOT NULL default '',
75+ PRIMARY KEY (`guid`,`channel`)
76+) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='IRC Module System';
77+
78+SET FOREIGN_KEY_CHECKS=0;
79+-- ----------------------------
80+-- Table structure for IRC_AutoAnnounce
81+-- ----------------------------
82+DROP TABLE IF EXISTS `IRC_AutoAnnounce`;
83+CREATE TABLE `IRC_AutoAnnounce` (
84+ `id` int(11) NOT NULL AUTO_INCREMENT,
85+ `message` longtext NOT NULL,
86+ `addedby` varchar(12) NOT NULL default '',
87+ PRIMARY KEY (`id`)
88+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='IRC Module System';
89+
90+-- ----------------------------
91+-- Record addition for IRC_AutoAnnounce
92+-- ----------------------------
93+INSERT INTO mangos_string (`entry`,`content_default`) VALUES ('3000','|cffff0000[Automatic System Message]: %s|r');
94\ No newline at end of file
95diff --git a/src/game/AuctionHouseHandler.cpp b/src/game/AuctionHouseHandler.cpp
96index f65b863..7fa6c6a 100644
97--- a/src/game/AuctionHouseHandler.cpp
98+++ b/src/game/AuctionHouseHandler.cpp
99@@ -27,6 +27,7 @@
100 #include "UpdateMask.h"
101 #include "AuctionHouseMgr.h"
102 #include "Util.h"
103+#include "mangchat/IRCClient.h"
104
105 //please DO NOT use iterator++, because it is slower than ++iterator!!!
106 //post-incrementation is always slower than pre-incrementation !
107@@ -303,6 +304,9 @@ void WorldSession::HandleAuctionSellItem( WorldPacket & recv_data )
108 pl->SaveInventoryAndGoldToDB();
109 CharacterDatabase.CommitTransaction();
110
111+ if((sIRC.BOTMASK & 1024) != 0)
112+ sIRC.AHFunc(it->GetEntry(), it->GetProto()->Name1, pl->GetName(), pl->getFaction());
113+
114 SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK);
115 }
116
117diff --git a/src/game/Channel.cpp b/src/game/Channel.cpp
118index 64bc508..227c78c 100644
119--- a/src/game/Channel.cpp
120+++ b/src/game/Channel.cpp
121@@ -20,6 +20,7 @@
122 #include "ObjectMgr.h"
123 #include "World.h"
124 #include "SocialMgr.h"
125+#include "mangchat/IRCClient.h"
126
127 Channel::Channel(const std::string& name, uint32 channel_id)
128 : m_announce(true), m_moderate(false), m_name(name), m_flags(0), m_channelId(channel_id), m_ownerGUID(0)
129@@ -112,14 +113,9 @@ void Channel::Join(uint64 p, const char *pass)
130 MakeYouJoined(&data);
131 SendToOne(&data, p);
132
133+ sIRC.Handle_WoW_Channel(m_name, objmgr.GetPlayer(p), CHANNEL_JOIN);
134 JoinNotify(p);
135
136- // if no owner first logged will become
137- if(!IsConstant() && !m_ownerGUID)
138- {
139- SetOwner(p, (players.size() > 1 ? true : false));
140- players[p].SetModerator(true);
141- }
142 }
143
144 void Channel::Leave(uint64 p, bool send)
145@@ -159,6 +155,7 @@ void Channel::Leave(uint64 p, bool send)
146
147 LeaveNotify(p);
148
149+ sIRC.Handle_WoW_Channel(m_name, objmgr.GetPlayer(p), CHANNEL_LEAVE);
150 if(changeowner)
151 {
152 uint64 newowner = !players.empty() ? players.begin()->second.player : 0;
153diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp
154index 3444776..d3a5d32 100644
155--- a/src/game/Chat.cpp
156+++ b/src/game/Chat.cpp
157@@ -714,6 +714,7 @@ ChatCommand * ChatHandler::getCommandTable()
158 { "flusharenapoints",SEC_ADMINISTRATOR, false, &ChatHandler::HandleFlushArenaPointsCommand, "", NULL },
159 { "repairitems", SEC_GAMEMASTER, true, &ChatHandler::HandleRepairitemsCommand, "", NULL },
160 { "waterwalk", SEC_GAMEMASTER, false, &ChatHandler::HandleWaterwalkCommand, "", NULL },
161+ { "ircpm", SEC_PLAYER, false, &ChatHandler::HandleIRCpmCommand, "", NULL },
162
163 { NULL, 0, false, NULL, "", NULL }
164 };
165diff --git a/src/game/Chat.h b/src/game/Chat.h
166index 18ef9cc..7428511 100644
167--- a/src/game/Chat.h
168+++ b/src/game/Chat.h
169@@ -533,6 +533,7 @@ class ChatHandler
170 bool HandleFlushArenaPointsCommand(const char *args);
171 bool HandleRepairitemsCommand(const char* args);
172 bool HandleWaterwalkCommand(const char* args);
173+ bool HandleIRCpmCommand(const char* args);
174
175 //! Development Commands
176 bool HandleSet32Bit(const char* args);
177diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp
178index eaf993f..e7e0c33 100644
179--- a/src/game/ChatHandler.cpp
180+++ b/src/game/ChatHandler.cpp
181@@ -34,6 +34,7 @@
182 #include "SpellAuras.h"
183 #include "Language.h"
184 #include "Util.h"
185+#include "mangchat/IRCClient.h"
186 #include "GridNotifiersImpl.h"
187 #include "CellImpl.h"
188
189@@ -442,6 +443,8 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
190 if(msg.empty())
191 break;
192
193+ sIRC.Send_WoW_IRC(_player, channel, msg);
194+
195 if(ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
196 {
197 if(Channel *chn = cMgr->GetChannel(channel,_player))
198diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h
199index 27646fd..c609908 100644
200--- a/src/game/DBCStructure.h
201+++ b/src/game/DBCStructure.h
202@@ -638,7 +638,7 @@ struct ChrClassesEntry
203 //uint32 flags; // 1, unused
204 uint32 powerType; // 2
205 // 3-4, unused
206- //char* name[16]; // 5-20 unused
207+ char* name[16]; // 5-20 unused
208 // 21 string flag, unused
209 //char* nameFemale[16]; // 21-36 unused, if different from base (male) case
210 // 37 string flag, unused
211diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h
212index 29fa119..670bcd7 100644
213--- a/src/game/DBCfmt.h
214+++ b/src/game/DBCfmt.h
215@@ -32,7 +32,7 @@ const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxx
216 const char CharTitlesEntryfmt[]="nxssssssssssssssssxxxxxxxxxxxxxxxxxxi";
217 const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx";
218 // ChatChannelsEntryfmt, index not used (more compact store)
219-const char ChrClassesEntryfmt[]="nxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
220+const char ChrClassesEntryfmt[]="nxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
221 const char ChrRacesEntryfmt[]="nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
222 const char CinematicSequencesEntryfmt[]="nxxxxxxxxx";
223 const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxxxx";
224diff --git a/src/game/GMTicketHandler.cpp b/src/game/GMTicketHandler.cpp
225index 8a36ff9..12aa487 100644
226--- a/src/game/GMTicketHandler.cpp
227+++ b/src/game/GMTicketHandler.cpp
228@@ -24,6 +24,7 @@
229 #include "ObjectAccessor.h"
230 #include "Player.h"
231 #include "Chat.h"
232+#include "mangchat/IRCClient.h"
233
234 void WorldSession::SendGMTicketGetTicket(uint32 status, char const* text)
235 {
236@@ -94,6 +95,16 @@ void WorldSession::HandleGMTicketDeleteTicketOpcode( WorldPacket & /*recv_data*/
237 SendPacket( &data );
238
239 SendGMTicketGetTicket(0x0A, 0);
240+
241+ std::string msg; // Start addition of IRC handling for GM Ticket
242+ msg = GetPlayer()->GetName();
243+ std::string str = "|cffff0000[GM Ticket]:|r";
244+ str += msg;
245+ std::string ircchan = "#";
246+ ircchan += sIRC._irc_chan[sIRC.Status].c_str();
247+ sIRC.Send_IRC_Channel(ircchan, sIRC.MakeMsg("\00304,08\037/!\\\037\017\00304 GM Ticket Deleted For:\00304,08\037/!\\\037\017 %s", "%s", msg.c_str()), true); // End of IRC handling
248+
249+
250 }
251
252 void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data )
253@@ -139,6 +150,16 @@ void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data )
254 if(itr->second->GetSession()->GetSecurity() >= SEC_GAMEMASTER && itr->second->isAcceptTickets())
255 ChatHandler(itr->second).PSendSysMessage(LANG_COMMAND_TICKETNEW,GetPlayer()->GetName());
256 }
257+ std::string msg; // Start addition of IRC handling for GM Ticket
258+ std::string msg2;
259+ msg = GetPlayer()->GetName();
260+ msg2 = ticketText;
261+ std::string str = "|cffff0000[GM Ticket]:|r";
262+ str += msg;
263+ std::string ircchan = "#";
264+ ircchan += sIRC._irc_chan[sIRC.Status].c_str();
265+ sIRC.Send_IRC_Channel(ircchan, sIRC.MakeMsg("\00304,08\037/!\\\037\017\00304 New GM Ticket from:\00304,08\037/!\\\037\017 %s", "%s", msg.c_str()), true);
266+ sIRC.Send_IRC_Channel(ircchan, sIRC.MakeMsg("\00304,08\037/!\\\037\017\00304 Ticket Details:\00304,08\037/!\\\037\017 %s", "%s", msg2.c_str()), true);// End of IRC handling
267 }
268
269 void WorldSession::HandleGMTicketSystemStatusOpcode( WorldPacket & /*recv_data*/ )
270diff --git a/src/game/GMTicketMgr.cpp b/src/game/GMTicketMgr.cpp
271index 621c18b..d199724 100644
272--- a/src/game/GMTicketMgr.cpp
273+++ b/src/game/GMTicketMgr.cpp
274@@ -26,6 +26,7 @@
275 #include "Policies/SingletonImp.h"
276 #include "Player.h"
277 #include "ObjectDefines.h"
278+#include "mangchat/IRCClient.h"
279
280 INSTANTIATE_SINGLETON_1(GMTicketMgr);
281
282@@ -78,4 +79,13 @@ void GMTicketMgr::DeleteAll()
283 }
284 CharacterDatabase.Execute("DELETE FROM character_ticket");
285 m_GMTicketMap.clear();
286+
287+ std::string msg; // Start addition of IRC handling for GM Ticket
288+ msg = "";
289+ std::string str = "|cffff0000[All Tickets Deleted]:|r";
290+ str += msg;
291+ std::string ircchan = "#";
292+ ircchan += sIRC._irc_chan[sIRC.Status].c_str();
293+ sIRC.Send_IRC_Channel(ircchan, sIRC.MakeMsg("\00304,08\037/!\\\037\017\00304 All Tickets Deleted\00304,08\037/!\\\037\017 %s", "%s", msg.c_str()), true); // End of IRC handling
294+
295 }
296diff --git a/src/game/GameEventMgr.cpp b/src/game/GameEventMgr.cpp
297index 3c08478..31be1bf 100644
298--- a/src/game/GameEventMgr.cpp
299+++ b/src/game/GameEventMgr.cpp
300@@ -26,6 +26,7 @@
301 #include "Log.h"
302 #include "MapManager.h"
303 #include "Policies/SingletonImp.h"
304+#include "mangchat/IRCClient.h"
305
306 INSTANTIATE_SINGLETON_1(GameEventMgr);
307
308@@ -483,6 +484,12 @@ void GameEventMgr::ApplyNewEvent(uint16 event_id)
309 {
310 if (sWorld.getConfig(CONFIG_BOOL_EVENT_ANNOUNCE))
311 sWorld.SendWorldText(LANG_EVENTMESSAGE, mGameEvent[event_id].description.c_str());
312+ if((sIRC.BOTMASK & 256) != 0)
313+ {
314+ std::string ircchan = "#";
315+ ircchan += sIRC._irc_chan[sIRC.anchn].c_str();
316+ sIRC.Send_IRC_Channel(ircchan, sIRC.MakeMsg("\00304,08\037/!\\\037\017\00304 Game Event \00304,08\037/!\\\037\017 %s", "%s", mGameEvent[event_id].description.c_str()), true);
317+ }
318
319 sLog.outString("GameEvent %u \"%s\" started.", event_id, mGameEvent[event_id].description.c_str());
320 // spawn positive event tagget objects
321diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp
322index a8d6a00..c9ef85d 100644
323--- a/src/game/Level1.cpp
324+++ b/src/game/Level1.cpp
325@@ -32,6 +32,7 @@
326 #include "CellImpl.h"
327 #include "InstanceSaveMgr.h"
328 #include "Util.h"
329+#include "mangchat/IRCClient.h"
330 #ifdef _DEBUG_VMAPS
331 #include "VMapFactory.h"
332 #endif
333@@ -147,6 +148,13 @@ bool ChatHandler::HandleNotifyCommand(const char* args)
334 data << str;
335 sWorld.SendGlobalMessage(&data);
336
337+ if((sIRC.BOTMASK & 256) != 0)
338+ {
339+ std::string ircchan = "#";
340+ ircchan += sIRC._irc_chan[sIRC.anchn].c_str();
341+ sIRC.Send_IRC_Channel(ircchan, sIRC.MakeMsg("\00304,08\037/!\\\037\017\00304 Global Notify \00304,08\037/!\\\037\017 %s", "%s", args), true);
342+ }
343+
344 return true;
345 }
346
347@@ -2454,7 +2462,23 @@ bool ChatHandler::HandleGoGridCommand(const char* args)
348
349 return HandleGoHelper(_player, mapid, x, y);
350 }
351-
352+bool ChatHandler::HandleIRCpmCommand(const char* args)
353+{
354+ std::string Msg = args;
355+ if (Msg.find(" ") == std::string::npos)
356+ return false;
357+ std::string To = Msg.substr(0, Msg.find(" "));
358+ Msg = Msg.substr(Msg.find(" ") + 1);
359+ std::size_t pos;
360+ while((pos = To.find("||")) != std::string::npos)
361+ {
362+ std::size_t find1 = To.find("||", pos);
363+ To.replace(pos, find1 - pos + 2, "|");
364+ }
365+ sIRC.SendIRC("PRIVMSG "+To+" : <WoW>["+m_session->GetPlayerName()+"] : " + Msg);
366+ sIRC.Send_WoW_Player(m_session->GetPlayer(), "|cffCC4ACCTo ["+To+"]: "+Msg);
367+ return true;
368+}
369 bool ChatHandler::HandleModifyDrunkCommand(const char* args)
370 {
371 if(!*args) return false;
372diff --git a/src/game/Makefile.am b/src/game/Makefile.am
373index 96f9ae3..cd11841 100644
374--- a/src/game/Makefile.am
375+++ b/src/game/Makefile.am
376@@ -159,7 +159,21 @@ libmangosgame_a_SOURCES = \
377 InstanceData.h \
378 InstanceSaveMgr.cpp \
379 InstanceSaveMgr.h \
380- Item.cpp \
381+ mangchat/IRCClient.cpp \
382+ mangchat/IRCClient.h \
383+ mangchat/IRCCmd.cpp \
384+ mangchat/IRCCmd.h \
385+ mangchat/IRCCmde.cpp \
386+ mangchat/IRCConf.cpp \
387+ mangchat/IRCConf.h \
388+ mangchat/IRCFunc.h \
389+ mangchat/IRCIO.cpp \
390+ mangchat/IRCLog.cpp \
391+ mangchat/IRCLog.h \
392+ mangchat/IRCSock.cpp \
393+ mangchat/MCS_OnlinePlayers.cpp \
394+ mangchat/MCS_OnlinePlayers.h \
395+ Item.cpp \
396 Item.h \
397 ItemEnchantmentMgr.cpp \
398 ItemEnchantmentMgr.h \
399diff --git a/src/game/Player.cpp b/src/game/Player.cpp
400index 68298e5..1234329 100644
401--- a/src/game/Player.cpp
402+++ b/src/game/Player.cpp
403@@ -61,6 +61,7 @@
404 #include "SocialMgr.h"
405 #include "AchievementMgr.h"
406 #include "Mail.h"
407+#include "mangchat/IRCClient.h"
408
409 #include <cmath>
410
411@@ -2017,6 +2018,8 @@ void Player::AddToWorld()
412 if(m_items[i])
413 m_items[i]->AddToWorld();
414 }
415+ if(sIRC.ajoin == 1)
416+ sIRC.AutoJoinChannel(this);
417 }
418
419 void Player::RemoveFromWorld()
420@@ -2611,6 +2614,17 @@ void Player::GiveLevel(uint32 level)
421
422 UpdateAllStats();
423
424+ if((sIRC.BOTMASK & 64) != 0)
425+ {
426+ char temp [5];
427+ sprintf(temp, "%u", level);
428+ std::string plevel = temp;
429+ std::string pname = GetName();
430+ std::string ircchan = "#";
431+ ircchan += sIRC._irc_chan[sIRC.Status].c_str();
432+ sIRC.Send_IRC_Channel(ircchan, "\00311["+pname+"] : Has Reached Level: "+plevel, true);
433+ }
434+
435 // set current level health and mana/energy to maximum after applying all mods.
436 SetHealth(GetMaxHealth());
437 SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
438diff --git a/src/game/World.cpp b/src/game/World.cpp
439index 1bfe545..86920e0 100644
440--- a/src/game/World.cpp
441+++ b/src/game/World.cpp
442@@ -62,6 +62,7 @@
443 #include "GMTicketMgr.h"
444 #include "Util.h"
445+#include "mangchat/IRCClient.h"
446 #include "CharacterDatabaseCleaner.h"
447
448 INSTANTIATE_SINGLETON_1( World );
449
450@@ -1261,13 +1262,17 @@ void World::SetInitialWorldSettings()
451 loginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, startstring, uptime) VALUES('%u', " UI64FMTD ", '%s', 0)",
452 realmID, uint64(m_startTime), isoDate);
453
454- m_timers[WUPDATE_OBJECTS].SetInterval(0);
455+ static uint32 autoanc = 1;
456+ autoanc = sIRC.autoanc;
457+
458+ m_timers[WUPDATE_OBJECTS].SetInterval(0);
459 m_timers[WUPDATE_SESSIONS].SetInterval(0);
460 m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILISECONDS);
461 m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILISECONDS);
462 m_timers[WUPDATE_UPTIME].SetInterval(m_configs[CONFIG_UPTIME_UPDATE]*MINUTE*IN_MILISECONDS);
463 //Update "uptime" table based on configuration entry in minutes.
464 m_timers[WUPDATE_CORPSES].SetInterval(20*MINUTE*IN_MILISECONDS);
465+ m_timers[WUPDATE_AUTOANC].SetInterval(autoanc*MINUTE*1000); //handles IRC autoannouncements
466 //erase corpses every 20 minutes
467
468 //to set mailtimer to return mails every day between 4 and 5 am
469@@ -1478,6 +1483,12 @@ void World::Update(uint32 diff)
470 m_timers[WUPDATE_EVENTS].Reset();
471 }
472
473+ if (m_timers[WUPDATE_AUTOANC].Passed())
474+ {
475+ m_timers[WUPDATE_AUTOANC].Reset();
476+ SendRNDBroadcast();
477+ }
478+
479 /// </ul>
480 ///- Move all creatures with "delayed move" and remove and delete all objects with "delayed remove"
481 MapManager::Instance().DoDelayedMovesAndRemoves();
482@@ -2707,7 +2718,21 @@ void World::ProcessCliCommands()
483 delete command;
484 }
485 }
486-
487+void World::SendRNDBroadcast()
488+{
489+ std::string msg;
490+ QueryResult *result = WorldDatabase.PQuery("SELECT `message` FROM `IRC_AutoAnnounce` ORDER BY RAND() LIMIT 1");
491+ if(!result)
492+ return;
493+ msg = result->Fetch()[0].GetString();
494+ delete result;
495+ std::string str = "|cffff0000[Automatic]:|r";
496+ str += msg;
497+ sWorld.SendWorldText(3000,msg.c_str()); //the number before msg.cstr() is a mangos string. So you can put in your own mangos string with unique id and make your announcement any color or show anyway you want in wow by altering the mangos_string table
498+ std::string ircchan = "#";
499+ ircchan += sIRC._irc_chan[sIRC.anchn].c_str();
500+ sIRC.Send_IRC_Channel(ircchan, sIRC.MakeMsg("\00304,08\037/!\\\037\017\00304 Automatic System Message \00304,08\037/!\\\037\017 %s", "%s", msg.c_str()), true);
501+}
502 void World::InitResultQueue()
503 {
504 m_resultQueue = new SqlResultQueue;
505diff --git a/src/game/World.h b/src/game/World.h
506index 5fdfb00..71c3508 100644
507--- a/src/game/World.h
508+++ b/src/game/World.h
509@@ -77,7 +77,8 @@ enum WorldTimers
510 WUPDATE_UPTIME = 4,
511 WUPDATE_CORPSES = 5,
512 WUPDATE_EVENTS = 6,
513- WUPDATE_COUNT = 7
514+ WUPDATE_AUTOANC = 7,
515+ WUPDATE_COUNT = 8
516 };
517
518 /// Configuration elements
519@@ -450,9 +451,11 @@ class World
520 World();
521 ~World();
522
523- WorldSession* FindSession(uint32 id) const;
524+ static volatile bool m_stopEvent;
525+ WorldSession* FindSession(uint32 id) const;
526 void AddSession(WorldSession *s);
527- bool RemoveSession(uint32 id);
528+ void SendRNDBroadcast();
529+ bool RemoveSession(uint32 id);
530 /// Get the number of current active sessions
531 void UpdateMaxSessionCounters();
532 uint32 GetActiveAndQueuedSessionCount() const { return m_sessions.size(); }
533@@ -608,7 +611,6 @@ class World
534 void InitDailyQuestResetTime();
535 void ResetDailyQuests();
536 private:
537- static volatile bool m_stopEvent;
538 static uint8 m_ExitCode;
539 uint32 m_ShutdownTimer;
540 uint32 m_ShutdownMask;
541diff --git a/src/game/mangchat/IRCClient.cpp b/src/game/mangchat/IRCClient.cpp
542new file mode 100644
543index 0000000..1ed04b1
544--- a/src/game/mangchat/IRCClient.cpp
545+++ b/src/game/mangchat/IRCClient.cpp
546@@ -0,0 +1,99 @@
547+/*
548+ * MangChat By |Death| And Cybrax
549+ *
550+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
551+ * Of The GNU General Public License
552+ * Written and Developed by Cybrax. cybraxvd@gmail.com
553+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
554+ * Modified for patch 3.0.8 by Shinzon <shinzon@wowgollum.com>
555+ * With Help And Support From The MaNGOS Project Community.
556+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
557+ */
558+#include "IRCClient.h"
559+#include "../World.h"
560+#include "../ObjectMgr.h"
561+#include "../MapManager.h"
562+#include <ace/Thread.h>
563+
564+#include "Policies/SingletonImp.h"
565+INSTANTIATE_SINGLETON_1( IRCClient );
566+
567+#ifdef WIN32
568+ #define Delay(x) Sleep(x)
569+#else
570+ #define Delay(x) sleep(x / 1000)
571+#endif
572+// IRCClient Constructor
573+IRCClient::IRCClient()
574+{
575+ for(int i = 0;i > 5;i++)
576+ sIRC.Script_Lock[i] = false;
577+}
578+// IRCClient Destructor
579+IRCClient::~IRCClient(){}
580+
581+// ZThread Entry This function is called when the thread is created in Master.cpp (mangosd)
582+void IRCClient::run()
583+{
584+ sIRC.iLog.WriteLog(" %s : ****** MaNGOS With MangChat Has Been Started ******", sIRC.iLog.GetLogDateTimeStr().c_str());
585+
586+ // before we begin we wait a few
587+ // mangos is still starting up.
588+ ACE_Based::Thread::Sleep(1000);
589+ sLog.outString("\n%s\n%s\n%s\n%s",
590+ "***************************************",
591+ "** MangChat Threaded IRC Client **",
592+ "** With Enhanced GM Control. **",
593+ "***************************************");
594+ sLog.outString("****** MangChat: %s ********", sIRC._Mver.c_str());
595+ int cCount = 0;
596+ // Clean Up MySQL Tables
597+ sLog.outString("*** MangChat: Cleaning Up Inchan Table*");
598+ WorldDatabase.PExecute("DELETE FROM `IRC_Inchan`");
599+ sIRC._Max_Script_Inst = 0;
600+ // Create a loop to keep the thread running untill active is set to false
601+ while(sIRC.Active && !World::m_stopEvent)
602+ {
603+ // Initialize socket library
604+ if(this->InitSock())
605+ {
606+ // Connect To The IRC Server
607+ sLog.outString("*** MangChat: Connecting to %s Try # %d ******", sIRC._Host.c_str(), cCount);
608+ if(this->Connect(sIRC._Host.c_str(), sIRC._Port))
609+ {
610+ // On connection success reset the connection counter
611+ cCount = 0;
612+ sLog.outString("*** MangChat: Connected And Logging In*");
613+ // Login to the IRC server
614+ if(this->Login(sIRC._Nick, sIRC._User, sIRC._Pass))
615+ {
616+ sLog.outString("*** MangChat: Logged In And Running!! *");
617+ // While we are connected to the irc server keep listening for data on the socket
618+ while(sIRC.Connected && !World::m_stopEvent){ sIRC.SockRecv(); }
619+ }
620+ sLog.outString("*** MangChat: Connection To IRC Server Lost! ***");
621+ }
622+ // When an error occures or connection lost cleanup
623+ Disconnect();
624+ // Increase the connection counter
625+ cCount++;
626+ // if MAX_CONNECT_ATTEMPT is reached stop trying
627+ if(sIRC._MCA != 0 && cCount == sIRC._MCA)
628+ sIRC.Active = false;
629+ // If we need to reattempt a connection wait WAIT_CONNECT_TIME milli seconds before we try again
630+ if(sIRC.Active)
631+ ACE_Based::Thread::Sleep(sIRC._wct);
632+ }
633+ else
634+ {
635+ // Socket could not initialize cancel
636+ sIRC.Active = false;
637+ sLog.outError("** MangChat: Could not initialize socket");
638+ }
639+ }
640+ // we need to keep the thread alive or mangos will crash
641+ // when sending chat or join/leave channels.
642+ // even when we are not connected the functions must still
643+ // be availlable where chat is sent to so we keep it running
644+ while(!World::m_stopEvent){};
645+}
646diff --git a/src/game/mangchat/IRCClient.h b/src/game/mangchat/IRCClient.h
647new file mode 100644
648index 0000000..65cc07e
649--- a/src/game/mangchat/IRCClient.h
650+++ b/src/game/mangchat/IRCClient.h
651@@ -0,0 +1,239 @@
652+/*
653+ * MangChat By |Death| And Cybrax
654+ *
655+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
656+ * Of The GNU General Public License
657+ * Written and Developed by Cybrax. cybraxvd@gmail.com
658+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
659+ * Modified for patch 3.0.8 by Shinzon <shinzon@wowgollum.com>
660+ * With Help And Support From The MaNGOS Project Community.
661+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
662+ */
663+#ifndef _IRC_CLIENT_H
664+#define _IRC_CLIENT_H
665+
666+#include "Policies/Singleton.h"
667+#include "../Player.h"
668+#include "IRCLog.h"
669+#include "IRCCmd.h"
670+
671+using namespace std;
672+// The maximum ammount of channels used, must be >= config option
673+#define MAX_CONF_CHANNELS 10
674+#define MAX_CHAT_LINES 10
675+// time we need to wait before we try another connecton attempt
676+// Default is 30 seconds
677+#define MAX_SCRIPT_INST 10
678+// CLINES is used for the default chatlines
679+// By using the GetChatLine function its easier and faster
680+// to receieve the line you need.
681+enum CLINES
682+{
683+ IRC_WOW = 0,
684+ WOW_IRC = 1,
685+ JOIN_WOW = 2,
686+ JOIN_IRC = 3,
687+ LEAVE_WOW = 4,
688+ LEAVE_IRC = 5,
689+ CHANGE_NICK = 6
690+};
691+// CACTION is used by the Handle_WoW_Channel function
692+// this function is called in channel.h when a player
693+// joins or leave a channel inside the client.
694+enum CACTION
695+{
696+ CHANNEL_JOIN,
697+ CHANNEL_LEAVE,
698+};
699+
700+enum script_Names
701+{
702+ MCS_Players_Online = 0,
703+};
704+
705+// IRCClient main class
706+class IRCClient : public ACE_Based::Runnable
707+{
708+ public:
709+ // IRCClient Constructor
710+ IRCClient();
711+ // IRCClient Destructor
712+ ~IRCClient();
713+ // ZThread Entry
714+ void run();
715+ public:
716+ // AH Function
717+ void AHFunc(uint64 itmid, std::string itmnme, std::string plname, uint32 faction);
718+ bool BeenToGMI(float posx, float posy, float postz, std::string player, std::string from);
719+ // IRCClient active
720+ bool Active;
721+ // Connected to IRC
722+ bool Connected;
723+ // Socket indentifier
724+ int SOCKET;
725+ fd_set sfdset;
726+ // Send data to IRC, in addition the endline is added \n
727+ bool SendIRC(std::string data);
728+ // This function is called in ChatHandler.cpp and processes the chat from game to IRC
729+ void Send_WoW_IRC(Player *plr, std::string Channel, std::string Msg);
730+ // Sends a message to all players on the specified channel
731+ void Send_WoW_Channel(const char *channel, std::string chat);
732+ // Send a system message to all players
733+ void Send_WoW_System(std::string Message);
734+ // Send a message to the specified IRC channel
735+ void Send_IRC_Channel(std::string sChannel, std::string sMsg, bool NoPrefix = false, std::string nType = "PRIVMSG");
736+ // Sends a message to all IRC Channels
737+ void Send_IRC_Channels(std::string sMsg);
738+ std::string MakeMsg(std::string msg, std::string var, std::string val)
739+ {
740+ std::size_t start = msg.find(var);
741+ if (start != std::string::npos)
742+ msg.replace(start, var.length(), val);
743+ return msg;
744+ }
745+ void Send_WoW_Player(string sPlayer, string sMsg);
746+ void Send_WoW_Player(Player *plr, string sMsg);
747+
748+ // This function is called in Channel.cpp and processes Join/leave messages
749+ void Handle_WoW_Channel(std::string Channel, Player *plr, int nAction);
750+ void ResetIRC();
751+ public:
752+ void AutoJoinChannel(Player *plr);
753+
754+ public:
755+ bool Script_Lock[5];
756+ bool _AmiOp;
757+
758+ public:
759+ string _Mver;
760+ // IRC Server host
761+ string _Host;
762+ // IRC Server Port
763+ int _Port;
764+ // IRC Username
765+ string _User;
766+ // IRC Password
767+ string _Pass;
768+ // IRC Nickname
769+ string _Nick;
770+ // Authentication type
771+ int _Auth;
772+ string _Auth_Nick;
773+ // IRC Connect code
774+ string _ICC;
775+ // IRC Default channel
776+ string _defchan;
777+ // IRC Leave Default channel
778+ int _ldefc;
779+ // Wait Connect Time
780+ int _wct;
781+ // BotMask Options
782+ int Botmask;
783+ // Status Channel
784+ int Status;
785+ // Announce Channel
786+ int anchn;
787+ int autoanc;
788+ // IRC Channel count
789+ int _chan_count;
790+ // IRC Channel list
791+ // Array to store our IRC channels
792+ // each element will corrospond
793+ // with _wow_chan array below.
794+ std::string _irc_chan[MAX_CONF_CHANNELS];
795+ // Game Channel list
796+ std::string _wow_chan[MAX_CONF_CHANNELS];
797+ // AutoJoin Options
798+ int ajoin;
799+ string ajchan;
800+ // Online Command Max Results
801+ int onlrslt;
802+ // Channel OnJoin/Restart/Kick Messages
803+ string JoinMsg;
804+ string RstMsg;
805+ string kikmsg;
806+ // Misc Options
807+ string ojGM1;
808+ string ojGM2;
809+ string ojGM3;
810+ string ojGM4;
811+ string ojGM5;
812+ string logfile;
813+ int games;
814+ int gmlog;
815+ // IRC Commands Security Level
816+ int CACCT;
817+ int CBAN;
818+ int CCHAN;
819+ int CCHAR;
820+ int CFUN;
821+ int CHELP;
822+ int CINCHAN;
823+ int CINFO;
824+ int CITEM;
825+ int CJAIL;
826+ int CKICK;
827+ int _KILL;
828+ int CLEVEL;
829+ int CLOOKUP;
830+ int CMONEY;
831+ int CMUTE;
832+ int CONLINE;
833+ int CPM;
834+ int CRESTART;
835+ int CREVIVE;
836+ int CSAVEALL;
837+ int CSHUTDOWN;
838+ int CSPELL;
839+ int CSYSMSG;
840+ int CTELE;
841+ int CTOP;
842+ int CWHO;
843+ // BotMask
844+ int BOTMASK;
845+ // Max connect attempt
846+ int _MCA;
847+ // Auto rejoin when kicked from irc
848+ int _autojoinkick;
849+ // IRC Command prefix
850+ string _cmd_prefx;
851+ int _op_gm;
852+ int _op_gm_lev;
853+ // Array that contains our chatlines from the conf file
854+ // To increase this value change the MAX_CHAT_LINE define above
855+ // Make sure the number of elements must match your items
856+ // (remeber this starts at 0 so 0..9 is 10 items)
857+ // and that you load the line in the LoadConfig function.
858+ string ILINES[MAX_CHAT_LINES];
859+ string GetChatLine(int nItem);
860+
861+ int _Max_Script_Inst;
862+ // MAX_SCRIPT_INST
863+
864+ IRCLog iLog;
865+
866+public:
867+ // Load TriniChat configuration file
868+ bool LoadConfig(char const* cfgfile);
869+ void SetCfg(char const* cfgfile);
870+ char const* CfgFile;
871+
872+private:
873+ // Returns default chatline based on enum CLINES
874+ // Initialize socket library
875+ bool InitSock();
876+ // Connect to IRC Server
877+ bool Connect(const char *cHost, int nPort);
878+ // Login to IRC Server
879+ bool Login(std::string sNick, std::string sUser, std::string sPass);
880+ // Send raw data to IRC
881+ bool SendData(const char *data);
882+ // Disconnect from IRC and cleanup socket
883+ void Disconnect();
884+ // Processes the data receieved from IRC
885+ void Handle_IRC(std::string sData);
886+ // Receieves data from the socket.
887+ void SockRecv();
888+};
889+#endif
890+#define sIRC MaNGOS::Singleton<IRCClient>::Instance()
891\ No newline at end of file
892diff --git a/src/game/mangchat/IRCCmd.cpp b/src/game/mangchat/IRCCmd.cpp
893new file mode 100644
894index 0000000..8b5768e
895--- a/src/game/mangchat/IRCCmd.cpp
896+++ b/src/game/mangchat/IRCCmd.cpp
897@@ -0,0 +1,861 @@
898+/*
899+ * MangChat By |Death| And Cybrax
900+ *
901+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
902+ * Of The GNU General Public License
903+ * Written and Developed by Cybrax. cybraxvd@gmail.com
904+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
905+ * Modified for patch 3.0.8 by Shinzon <shinzon@wowgollum.com>
906+ * With Help And Support From The MaNGOS Project Community.
907+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
908+ */
909+#include "IRCCmd.h"
910+#include "IRCClient.h"
911+#include "Database/DatabaseEnv.h"
912+#include "../ObjectMgr.h"
913+#include "../AccountMgr.h"
914+#include "../MapManager.h"
915+// Constructor
916+IRCCmd::IRCCmd(){}
917+// Destructor
918+IRCCmd::~IRCCmd(){}
919+
920+std::string IRCCmd::MakeUpper(std::string Channel)
921+{
922+ std::string tmpchan = Channel;
923+ std::transform(tmpchan.begin(), tmpchan.end(), tmpchan.begin(), towupper);
924+ return tmpchan;
925+}
926+bool IRCCmd::ParamsValid(_CDATA *CD, int pCnt)
927+{
928+ CD->PCOUNT = pCnt;
929+ if(CD->PARAMS.size() == 0)
930+ return false;
931+ return ValidParams(CD->PARAMS, pCnt);
932+}
933+
934+int IRCCmd::ParamsValid(_CDATA *CD, int pCnt, int rLev)
935+{
936+ //CD->PCOUNT = pCnt;
937+ if(!CanUse(CD->USER, rLev))
938+ return E_AUTH;
939+ else if(pCnt == 0)
940+ return E_OK;
941+ else if(CD->PARAMS.size() == 0)
942+ return E_SIZE;
943+ else if(!ValidParams(CD->PARAMS, pCnt))
944+ return E_SIZE;
945+ return E_OK;
946+}
947+
948+// This function checks if chat from irc is a command or not
949+// return true on yes and false on no
950+bool IRCCmd::IsValid(std::string USER, std::string FROM, std::string CHAT, std::string TYPE)
951+{
952+ // If the first line of our chat is the command prefix we have a command
953+ if(CHAT.substr(0, 1) == sIRC._cmd_prefx && CHAT.size() > 1 )
954+ {
955+ _CDATA CDATA;
956+ bool cValid = false;
957+ bool AuthValid = true;
958+ bool dontlog = true;
959+ std::string* _PARAMS = getArray(CHAT, 2);
960+ CDATA.USER = USER;
961+ CDATA.FROM = FROM;
962+ CDATA.TYPE = TYPE;
963+ CDATA.PCOUNT = 0;
964+ CDATA.CMD = MakeUpper(_PARAMS[0].substr(1, _PARAMS[0].size() - 1));
965+ CDATA.PARAMS = _PARAMS[1];
966+ if(CDATA.CMD == "LOGIN")
967+ {
968+ if(FROM == sIRC._Nick)
969+ {
970+ if(ParamsValid(&CDATA, 2))
971+ Handle_Login(&CDATA);
972+ else
973+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"login <Player> <Password> )", true, "ERROR");
974+ }
975+ else
976+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Please Send A PM To Login!", true, "ERROR");
977+ if(GetLevel(USER) >= sIRC.gmlog)
978+ dontlog = false;
979+ cValid = true;
980+ }
981+ else if(CDATA.CMD == "LOGOUT")
982+ {
983+ if(FROM == sIRC._Nick)
984+ {
985+ Handle_Logout(&CDATA);
986+ }
987+ else
988+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Please Send A PM To Logout!", true, "ERROR");
989+ cValid = true;
990+ }
991+ else if(CDATA.CMD == "ACCT")
992+ {
993+ switch(ParamsValid(&CDATA, 2, sIRC.CACCT))
994+ {
995+ case E_OK:
996+ Account_Player(&CDATA);
997+ break;
998+ case E_SIZE:
999+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"acct <Player> <(un)lock/mail/pass/rename> )", true, "ERROR");
1000+ break;
1001+ case E_AUTH:
1002+ AuthValid = false;
1003+ break;
1004+ }
1005+ cValid = true;
1006+ }
1007+ else if(CDATA.CMD == "BAN")
1008+ {
1009+ switch(ParamsValid(&CDATA, 2, sIRC.CBAN))
1010+ {
1011+ case E_OK:
1012+ Ban_Player(&CDATA);
1013+ break;
1014+ case E_SIZE:
1015+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"ban <Player> <acct/ip> )", true, "ERROR");
1016+ break;
1017+ case E_AUTH:
1018+ AuthValid = false;
1019+ break;
1020+ }
1021+ cValid = true;
1022+ }
1023+ else if(CDATA.CMD == "CHAN")
1024+ {
1025+ switch(ParamsValid(&CDATA, 1, sIRC.CCHAN))
1026+ {
1027+ case E_OK:
1028+ Chan_Control(&CDATA);
1029+ break;
1030+ case E_SIZE:
1031+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"chan <op> <IRC User> )", true, "ERROR");
1032+ break;
1033+ case E_AUTH:
1034+ AuthValid = false;
1035+ break;
1036+ }
1037+ cValid = true;
1038+ }
1039+ else if(CDATA.CMD == "CHAR")
1040+ {
1041+ switch(ParamsValid(&CDATA, 2, sIRC.CCHAR))
1042+ {
1043+ case E_OK:
1044+ Char_Player(&CDATA);
1045+ break;
1046+ case E_SIZE:
1047+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"char <Player> <mailcheat/taxicheat/maxskill/setskill> )", true, "ERROR");
1048+ break;
1049+ case E_AUTH:
1050+ AuthValid = false;
1051+ break;
1052+ }
1053+ cValid = true;
1054+ }
1055+ else if(CDATA.CMD == "FUN")
1056+ {
1057+ switch(ParamsValid(&CDATA, 2, sIRC.CFUN))
1058+ {
1059+ case E_OK:
1060+ Fun_Player(&CDATA);
1061+ break;
1062+ case E_SIZE:
1063+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"fun <Player> <Sound/Say> )", true, "ERROR");
1064+ break;
1065+ case E_AUTH:
1066+ AuthValid = false;
1067+ break;
1068+ }
1069+ cValid = true;
1070+ }
1071+ else if(CDATA.CMD == "HELP")
1072+ {
1073+ switch(ParamsValid(&CDATA, 0, sIRC.CHELP))
1074+ {
1075+ case E_OK:
1076+ Help_IRC(&CDATA);
1077+ break;
1078+ case E_SIZE:
1079+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"help <Command> )", true, "ERROR");
1080+ break;
1081+ case E_AUTH:
1082+ AuthValid = false;
1083+ break;
1084+ }
1085+ cValid = true;
1086+ }
1087+ else if(CDATA.CMD == "INCHAN")
1088+ {
1089+ switch(ParamsValid(&CDATA, 1, sIRC.CINCHAN))
1090+ {
1091+ case E_OK:
1092+ Inchan_Server(&CDATA);
1093+ break;
1094+ case E_SIZE:
1095+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"inchan <Channel> )", true, "ERROR");
1096+ break;
1097+ case E_AUTH:
1098+ AuthValid = false;
1099+ break;
1100+ }
1101+ cValid = true;
1102+ }
1103+ else if(CDATA.CMD == "INFO")
1104+ {
1105+ switch(ParamsValid(&CDATA, 0, sIRC.CINFO))
1106+ {
1107+ case E_OK:
1108+ Info_Server(&CDATA);
1109+ break;
1110+ case E_SIZE:
1111+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"info )", true, "ERROR");
1112+ break;
1113+ case E_AUTH:
1114+ AuthValid = false;
1115+ break;
1116+ }
1117+ cValid = true;
1118+ }
1119+ else if(CDATA.CMD == "ITEM")
1120+ {
1121+ CDATA.PCOUNT = 3;
1122+ switch(ParamsValid(&CDATA, 2, sIRC.CITEM))
1123+ {
1124+ case E_OK:
1125+ Item_Player(&CDATA);
1126+ break;
1127+ case E_SIZE:
1128+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"item <Player> <add> <ItemID/[ItemName]> <Amount> )", true, "ERROR");
1129+ break;
1130+ case E_AUTH:
1131+ AuthValid = false;
1132+ break;
1133+ }
1134+ cValid = true;
1135+ }
1136+ else if(CDATA.CMD == "JAIL")
1137+ {
1138+ CDATA.PCOUNT = 3;
1139+ switch(ParamsValid(&CDATA, 1, sIRC.CJAIL))
1140+ {
1141+ case E_OK:
1142+ Jail_Player(&CDATA);
1143+ break;
1144+ case E_SIZE:
1145+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"jail <Player> <release/Reason>)", true, "ERROR");
1146+ break;
1147+ case E_AUTH:
1148+ AuthValid = false;
1149+ break;
1150+ }
1151+ cValid = true;
1152+ }
1153+ else if(CDATA.CMD == "KICK")
1154+ {
1155+ CDATA.PCOUNT = 2;
1156+ switch(ParamsValid(&CDATA, 1, sIRC.CKICK))
1157+ {
1158+ case E_OK:
1159+ Kick_Player(&CDATA);
1160+ break;
1161+ case E_SIZE:
1162+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"kick <Player> <Reason> )", true, "ERROR");
1163+ break;
1164+ case E_AUTH:
1165+ AuthValid = false;
1166+ break;
1167+ }
1168+ cValid = true;
1169+ }
1170+ else if(CDATA.CMD == "KILL")
1171+ {
1172+ CDATA.PCOUNT = 2;
1173+ switch(ParamsValid(&CDATA, 1, sIRC._KILL))
1174+ {
1175+ case E_OK:
1176+ Kill_Player(&CDATA);
1177+ break;
1178+ case E_SIZE:
1179+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"kill <Player> <Reason> )", true, "ERROR");
1180+ break;
1181+ case E_AUTH:
1182+ AuthValid = false;
1183+ break;
1184+ }
1185+ cValid = true;
1186+ }
1187+ else if(CDATA.CMD == "LEVEL")
1188+ {
1189+ CDATA.PCOUNT = 2;
1190+ switch(ParamsValid(&CDATA, 2, sIRC.CLEVEL))
1191+ {
1192+ case E_OK:
1193+ Level_Player(&CDATA);
1194+ break;
1195+ case E_SIZE:
1196+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"level <Player> <NewLevel> )", true, "ERROR");
1197+ break;
1198+ case E_AUTH:
1199+ AuthValid = false;
1200+ break;
1201+ }
1202+ cValid = true;
1203+ }
1204+ else if(CDATA.CMD == "LOOKUP")
1205+ {
1206+ CDATA.PCOUNT = 2;
1207+ switch(ParamsValid(&CDATA, 2, sIRC.CLOOKUP))
1208+ {
1209+ case E_OK:
1210+ Lookup_Player(&CDATA);
1211+ break;
1212+ case E_SIZE:
1213+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"lookup <acct/char/creature/faction/go/item/quest/skill/spell/tele> <ID/Name> )", true, "ERROR");
1214+ break;
1215+ case E_AUTH:
1216+ AuthValid = false;
1217+ break;
1218+ }
1219+ cValid = true;
1220+ }
1221+ else if(CDATA.CMD == "MONEY")
1222+ {
1223+ CDATA.PCOUNT = 2;
1224+ switch(ParamsValid(&CDATA, 2, sIRC.CMONEY))
1225+ {
1226+ case E_OK:
1227+ Money_Player(&CDATA);
1228+ break;
1229+ case E_SIZE:
1230+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"money <Player> <(-)Money> )", true, "ERROR");
1231+ break;
1232+ case E_AUTH:
1233+ AuthValid = false;
1234+ break;
1235+ }
1236+ cValid = true;
1237+ }
1238+ else if(CDATA.CMD == "MUTE")
1239+ {
1240+ switch(ParamsValid(&CDATA, 2, sIRC.CMUTE))
1241+ {
1242+ case E_OK:
1243+ Mute_Player(&CDATA);
1244+ break;
1245+ case E_SIZE:
1246+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"mute <Player> <release/TimeInMins> <Reason> )", true, "ERROR");
1247+ break;
1248+ case E_AUTH:
1249+ AuthValid = false;
1250+ break;
1251+ }
1252+ cValid = true;
1253+ }
1254+ else if(CDATA.CMD == "ONLINE")
1255+ {
1256+ switch(ParamsValid(&CDATA, 0, sIRC.CONLINE))
1257+ {
1258+ case E_OK:
1259+ Online_Players(&CDATA);
1260+ break;
1261+ case E_SIZE:
1262+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"online )", true, "ERROR");
1263+ break;
1264+ case E_AUTH:
1265+ AuthValid = false;
1266+ break;
1267+ }
1268+ cValid = true;
1269+ }
1270+ else if(CDATA.CMD == "PM")
1271+ {
1272+ switch(ParamsValid(&CDATA, 2, sIRC.CPM))
1273+ {
1274+ case E_OK:
1275+ PM_Player(&CDATA);
1276+ break;
1277+ case E_SIZE:
1278+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"pm <Player> <Message> )", true, "ERROR");
1279+ break;
1280+ case E_AUTH:
1281+ AuthValid = false;
1282+ break;
1283+ }
1284+ cValid = true;
1285+ }
1286+ else if(CDATA.CMD == "RELOAD")
1287+ {
1288+ switch(ParamsValid(&CDATA, 0, sIRC.CRESTART))
1289+ {
1290+ case E_OK:
1291+ sIRC.Send_IRC_Channels("Reloading TriniChat Config Options. (Command Disabled)");
1292+ //sIRC.LoadConfig();
1293+ break;
1294+ case E_AUTH:
1295+ AuthValid = false;
1296+ break;
1297+ }
1298+ cValid = true;
1299+ }
1300+ else if(CDATA.CMD == "RESTART")
1301+ {
1302+ switch(ParamsValid(&CDATA, 0, sIRC.CRESTART))
1303+ {
1304+ case E_OK:
1305+ sIRC.Send_IRC_Channels(sIRC.RstMsg);
1306+ sIRC.ResetIRC();
1307+ break;
1308+ case E_AUTH:
1309+ AuthValid = false;
1310+ break;
1311+ }
1312+ cValid = true;
1313+ }
1314+ else if(CDATA.CMD == "REVIVE")
1315+ {
1316+ CDATA.PCOUNT = 2;
1317+ switch(ParamsValid(&CDATA, 1, sIRC.CREVIVE))
1318+ {
1319+ case E_OK:
1320+ Revive_Player(&CDATA);
1321+ break;
1322+ case E_SIZE:
1323+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"revive <Player> )", true, "ERROR");
1324+ break;
1325+ case E_AUTH:
1326+ AuthValid = false;
1327+ break;
1328+ }
1329+ cValid = true;
1330+ }
1331+ else if(CDATA.CMD == "SAVEALL")
1332+ {
1333+ switch(ParamsValid(&CDATA, 0, sIRC.CSAVEALL))
1334+ {
1335+ case E_OK:
1336+ Saveall_Player(&CDATA);
1337+ break;
1338+ case E_AUTH:
1339+ AuthValid = false;
1340+ break;
1341+ }
1342+ cValid = true;
1343+ }
1344+ else if(CDATA.CMD == "SHUTDOWN")
1345+ {
1346+ switch(ParamsValid(&CDATA, 1, sIRC.CSHUTDOWN))
1347+ {
1348+ case E_OK:
1349+ Shutdown_Mangos(&CDATA);
1350+ break;
1351+ case E_SIZE:
1352+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"shutdown <TimeInSeconds> )", true, "ERROR");
1353+ break;
1354+ case E_AUTH:
1355+ AuthValid = false;
1356+ break;
1357+ }
1358+ cValid = true;
1359+ }
1360+ else if(CDATA.CMD == "SPELL")
1361+ {
1362+ switch(ParamsValid(&CDATA, 2, sIRC.CSPELL))
1363+ {
1364+ case E_OK:
1365+ Spell_Player(&CDATA);
1366+ break;
1367+ case E_SIZE:
1368+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"spell <Player> <Cast/Learn/UnLearn> <SpellID> )", true, "ERROR");
1369+ break;
1370+ case E_AUTH:
1371+ AuthValid = false;
1372+ break;
1373+ }
1374+ cValid = true;
1375+ }
1376+ else if(CDATA.CMD == "SYSMSG")
1377+ {
1378+ CDATA.PCOUNT = 2;
1379+ switch(ParamsValid(&CDATA, 2, sIRC.CSYSMSG))
1380+ {
1381+ case E_OK:
1382+ Sysmsg_Server(&CDATA);
1383+ break;
1384+ case E_SIZE:
1385+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"sysmsg <a/e/n/add/del/list> <Message> )", true, "ERROR");
1386+ break;
1387+ case E_AUTH:
1388+ AuthValid = false;
1389+ break;
1390+ }
1391+ cValid = true;
1392+ }
1393+ else if(CDATA.CMD == "TELE")
1394+ {
1395+ switch(ParamsValid(&CDATA, 2, sIRC.CTELE))
1396+ {
1397+ case E_OK:
1398+ Tele_Player(&CDATA);
1399+ break;
1400+ case E_SIZE:
1401+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"tele <Player> <l/c/r/to> <Loc.Name/MAPID X Y Z/Recall/Player> )", true, "ERROR");
1402+ break;
1403+ case E_AUTH:
1404+ AuthValid = false;
1405+ break;
1406+ }
1407+ cValid = true;
1408+ }
1409+ else if(CDATA.CMD == "TOP")
1410+ {
1411+ CDATA.PCOUNT = 1;
1412+ switch(ParamsValid(&CDATA, 1, sIRC.CTOP))
1413+ {
1414+ case E_OK:
1415+ Top_Player(&CDATA);
1416+ break;
1417+ case E_SIZE:
1418+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"top <accttime/chartime/money> <limit> )", true, "ERROR");
1419+ break;
1420+ case E_AUTH:
1421+ AuthValid = false;
1422+ break;
1423+ }
1424+ cValid = true;
1425+ }
1426+ else if(CDATA.CMD == "WHO")
1427+ {
1428+ switch(ParamsValid(&CDATA, 0, sIRC.CWHO))
1429+ {
1430+ case E_OK:
1431+ Who_Logged(&CDATA);
1432+ break;
1433+ case E_AUTH:
1434+ AuthValid = false;
1435+ break;
1436+ }
1437+ cValid = true;
1438+ }
1439+ if(!AuthValid && IsLoggedIn(USER))
1440+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Access Denied! Your Security Level Is Too Low To Use This Command!", true, "ERROR");
1441+ if(cValid == false && (sIRC.BOTMASK & 4) != 0)
1442+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Unknown Command!", true, "ERROR");
1443+ if(cValid && dontlog)
1444+ {
1445+ sIRC.iLog.WriteLog(" %s : [ %s(%d) ] Used Command: [ %s ] With Parameters: [ %s ]", sIRC.iLog.GetLogDateTimeStr().c_str(), CDATA.USER.c_str(), GetLevel(USER), CDATA.CMD.c_str(), CDATA.PARAMS.c_str());
1446+ }
1447+ return cValid;
1448+ }
1449+ return false;
1450+}
1451+
1452+bool IRCCmd::CanUse(std::string USER, int nLevel)
1453+{
1454+ if(IsLoggedIn(USER))
1455+ {
1456+ if(GetLevel(USER) >= nLevel)
1457+ return true;
1458+ else
1459+ return false;
1460+ }
1461+ else if(nLevel == 0)
1462+ {
1463+ return true;
1464+ }
1465+ else
1466+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : You Are Not Logged In!", true, "ERROR");
1467+ return false;
1468+}
1469+
1470+std::string IRCCmd::ChanOrPM(_CDATA *CD)
1471+{
1472+ if(CD->FROM == sIRC._Nick)
1473+ return CD->USER;
1474+ else
1475+ return CD->FROM;
1476+}
1477+
1478+Player *IRCCmd::GetPlayer(std::string WHO)
1479+{
1480+ normalizePlayerName(WHO);
1481+ return ObjectAccessor::Instance().FindPlayerByName(WHO.c_str());
1482+}
1483+
1484+_client *IRCCmd::GetClient(std::string cname)
1485+{
1486+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
1487+ {
1488+ if((*i)->Name == cname)
1489+ return (*i);
1490+ }
1491+ return (NULL);
1492+}
1493+
1494+bool IRCCmd::IsLoggedIn(std::string USER)
1495+{
1496+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
1497+ {
1498+ if((*i)->Name == USER)
1499+ return true;
1500+ }
1501+ return false;
1502+}
1503+
1504+bool IRCCmd::AcctIsLoggedIn(std::string USER)
1505+{
1506+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
1507+ {
1508+ if(MakeUpper((*i)->UName) == MakeUpper(USER))
1509+ return true;
1510+ }
1511+ return false;
1512+}
1513+
1514+std::string IRCCmd::AcctIsBanned(std::string ACCT)
1515+{
1516+ uint32 acctid = accmgr.GetId(ACCT);
1517+ std::string banned = "NOTBANNED";
1518+ QueryResult *result = loginDatabase.PQuery("SELECT banreason FROM ip_banned WHERE ip=(SELECT last_ip FROM account WHERE id = '%i')", acctid);
1519+ if(result)
1520+ {
1521+ banned = (*result)[0].GetCppString();
1522+ delete result;
1523+ return "IP Banned. Reason:" + banned;
1524+ }
1525+ QueryResult *result2 = loginDatabase.PQuery("SELECT banreason FROM account_banned WHERE id='%i'", acctid);
1526+ if(result2)
1527+ {
1528+ banned = (*result2)[0].GetCppString();
1529+ delete result2;
1530+ return "Account Banned. Reason:" + banned;
1531+ }
1532+ return banned;
1533+}
1534+
1535+int IRCCmd::GetLevel(std::string sName)
1536+{
1537+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
1538+ {
1539+ if((*i)->Name == sName)
1540+ return (*i)->GMLevel;
1541+ }
1542+ return 0;
1543+}
1544+
1545+int IRCCmd::AcctLevel(std::string plnme)
1546+{
1547+ uint64 guid = objmgr.GetPlayerGUIDByName(plnme);
1548+ uint32 account_id = 0;
1549+ uint32 security = 0;
1550+ account_id = objmgr.GetPlayerAccountIdByGUID(guid);
1551+ security = accmgr.GetSecurity(account_id);
1552+ return security;
1553+}
1554+
1555+std::string IRCCmd::GetAccName(std::string sName)
1556+{
1557+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
1558+ {
1559+ if((*i)->Name == sName)
1560+ return (*i)->UName;
1561+ }
1562+ return "";
1563+}
1564+
1565+std::string IRCCmd::GetNameFromAcct(std::string sName)
1566+{
1567+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
1568+ {
1569+ if((*i)->UName == sName)
1570+ return (*i)->Name;
1571+ }
1572+ return "";
1573+}
1574+
1575+int IRCCmd::GetAcctIDFromName(std::string sName)
1576+{
1577+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
1578+ {
1579+ if((*i)->Name == sName)
1580+ {
1581+ uint32 acct_id = 0;
1582+ acct_id = accmgr.GetId((*i)->UName.c_str());
1583+ return acct_id;
1584+ }
1585+ }
1586+ return 0;
1587+}
1588+
1589+std::string IRCCmd::GetAcctNameFromID(uint32 acctid)
1590+{
1591+ QueryResult *result = loginDatabase.PQuery("SELECT username FROM account WHERE id = '%d'", acctid);
1592+ if(result)
1593+ {
1594+ std::string name = (*result)[0].GetCppString();
1595+ delete result;
1596+ return name;
1597+ }
1598+
1599+ return "";
1600+}
1601+
1602+std::string IRCCmd::GetIPFromPlayer(std::string player)
1603+{
1604+ QueryResult *result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'", player.c_str());
1605+ if(result)
1606+ {
1607+ std::string acctid = (*result)[0].GetCppString();
1608+ delete result;
1609+ QueryResult *result2 = loginDatabase.PQuery("SELECT last_ip FROM account WHERE id = '%s'", acctid.c_str());
1610+ if(result2)
1611+ {
1612+ std::string ip = (*result2)[0].GetCppString();
1613+ delete result2;
1614+ return ip;
1615+ }
1616+ }
1617+
1618+ return "";
1619+}
1620+
1621+std::string IRCCmd::SecToDay(std::string secons)
1622+{
1623+ unsigned int seconds = atoi(secons.c_str());
1624+ unsigned int days = seconds / 86400;
1625+ unsigned int hours = seconds / 3600 % 24;
1626+ unsigned int mins = seconds / 60 % 60;
1627+ char tottime[1000];
1628+ sprintf(tottime, "%iDays:%iHours:%iMinutes", days, hours, mins);
1629+
1630+ return tottime;
1631+}
1632+
1633+bool IRCCmd::ValidParams(std::string PARAMS, int nCount)
1634+{
1635+ if(nCount == 1 && PARAMS.size() == 0)
1636+ return false;
1637+ int PCOUNT = 0;
1638+ size_t p = -1;
1639+ for(int i = 0;i < nCount;i++)
1640+ {
1641+ p = PARAMS.find(" ", p + 1);
1642+ if(p == -1)
1643+ break;
1644+ else
1645+ PCOUNT++;
1646+ }
1647+ nCount--;
1648+ if(PCOUNT >= nCount)
1649+ return true;
1650+ else
1651+ return false;
1652+}
1653+
1654+std::string* IRCCmd::getArray(std::string PARAMS, int nCount)
1655+{
1656+ std::string *array = new std::string[nCount];
1657+ if(PARAMS.size() > 0)
1658+ {
1659+ int pcnt = 0;
1660+ size_t ps = 0;
1661+ size_t pc = -1;
1662+ for(int i = 0;i < nCount;i++)
1663+ {
1664+ pc = PARAMS.find(" ", pc + 1);
1665+ if(i + 1 == nCount && nCount != 1)
1666+ {
1667+ if(ps > 0 && pc > 0)
1668+ array[i] = PARAMS.substr(ps, PARAMS.size() - ps);
1669+ }
1670+ else
1671+ array[i] = PARAMS.substr(ps, pc - ps);
1672+ ps = pc + 1;
1673+ }
1674+ }
1675+ return array;
1676+}
1677+
1678+std::string IRCCmd::MakeMsg(const char *sLine, ... )
1679+{
1680+ va_list ap;
1681+ char tmpoutp[1024];
1682+ va_start(ap, sLine);
1683+ vsnprintf(tmpoutp, 1024, sLine, ap );
1684+ va_end(ap);
1685+ std::string outp = tmpoutp;
1686+ return outp;
1687+}
1688+
1689+void IRCClient::AHFunc(uint64 itmid, std::string itmnme, std::string plname, uint32 faction)
1690+{
1691+ IRCCmd Command;
1692+ Player* plr = Command.GetPlayer(plname);
1693+ if(plr)
1694+ {
1695+ std::string itemname = itmnme;
1696+
1697+ char temp [7];
1698+ sprintf(temp, "%u", itmid);
1699+ std::string itemid = temp;
1700+
1701+ std::string wowname = "";
1702+ std::string ircname = "";
1703+ switch (plr->GetTeam())
1704+ {
1705+ case 67:wowname="|cffff0000"+plname+"|r";ircname="\0034"+plname;break; //horde
1706+ case 469:wowname="|cff1589FF"+plname+"|r";ircname="\00312"+plname;break; //alliance
1707+ }
1708+
1709+ std::string wowfact = "|cffFF8040[Auction House]:|r";
1710+ std::string ircfact = "\00304,08\037/!\\\037\017\00307 Auction House \00304,08\037/!\\\037\017";
1711+ switch(faction)
1712+ {
1713+ //neutral
1714+ case 7:wowfact="|cffff8040[Neutral Auction House]:|r";ircfact="\00304,08\037/!\\\037\017\00307 Neutral Auction House \00304,08\037/!\\\037\017";break;
1715+ //horde
1716+ case 6:wowfact="|cffff0000[Horde Auction House]:|r";ircfact="\00304,08\037/!\\\037\017\00304 Horde Auction House \00304,08\037/!\\\037\017";break;
1717+ //alliance
1718+ case 2:wowfact="|cff1589FF[Alliance Auction House]:|r";ircfact="\00304,08\037/!\\\037\017\00312 Alliance Auction House \00304,08\037/!\\\037\017";break;
1719+ }
1720+ std::string wowstr = Command.MakeMsg("%s A New Item Has Been Added |cffffffff|Hitem:%s:0:0:0:0:0:0:0|h[%s]|h|r. By: %s",wowfact.c_str(), itemid.c_str(), itemname.c_str(), wowname.c_str());
1721+ std::string ircstr = Command.MakeMsg("%s A New Item Has Been Added [%s]. By: %s", ircfact.c_str(), itemname.c_str(), ircname.c_str());
1722+
1723+ sIRC.Send_WoW_Channel(sIRC._wow_chan[sIRC.Status].c_str(), wowstr.c_str());
1724+ sIRC.Send_IRC_Channel(sIRC._irc_chan[sIRC.Status].c_str(), ircstr.c_str());
1725+ }
1726+}
1727+
1728+bool IRCClient::BeenToGMI(float posx, float posy, float posz, std::string player, std::string from)
1729+{
1730+ IRCCmd Command;
1731+ //std::transform(location.begin(), location.end(), location.begin(), towupper);
1732+ //objmgr.GetAreaId
1733+ //if(location == "GMI" || location == "GMISLAND")
1734+ if(MapManager::Instance().GetZoneId(1,posx,posy,posz) == 876)
1735+ {
1736+ QueryResult *result = WorldDatabase.PQuery("SELECT name FROM Hell_GMI WHERE name = '%s'",player.c_str());
1737+ if(result)
1738+ {
1739+ delete result;
1740+ uint64 guid = objmgr.GetPlayerGUIDByName(player);
1741+ Player* plr = objmgr.GetPlayer(guid);
1742+
1743+ uint64 guid2 = objmgr.GetPlayerGUIDByName(from);
1744+ Player* plr2 = objmgr.GetPlayer(guid2);
1745+ if(plr) sIRC.Send_WoW_Player(plr, "You Have Already Had A Trip To GM Island. There Is Only One Tele To GM Island Per Player, Please Donate If You Would like The .tele Command.");
1746+ if(plr2) sIRC.Send_WoW_Player(plr2, "This Player Has Already Had Their Trip To GM Island. The Tele Has Been Canceled.");
1747+ else sIRC.Send_IRC_Channel(from.c_str(), MakeMsg(" \0034[ERROR] : $Player Has Already Had Their Trip To GMI! The Tele Has Been Canceled", "$Player", player.c_str()), true, "ERROR");
1748+ return true;
1749+ }
1750+ else
1751+ {
1752+ if(Command.AcctLevel(player) == 0)
1753+ WorldDatabase.PExecute("INSERT INTO `Hell_GMI` VALUES ('%s')", player.c_str());
1754+ return false;
1755+ }
1756+ }
1757+ return false;
1758+}
1759\ No newline at end of file
1760diff --git a/src/game/mangchat/IRCCmd.h b/src/game/mangchat/IRCCmd.h
1761new file mode 100644
1762index 0000000..c20a587
1763--- a/src/game/mangchat/IRCCmd.h
1764+++ b/src/game/mangchat/IRCCmd.h
1765@@ -0,0 +1,124 @@
1766+/* TriniChat Trinity Core IRC Client
1767+ *
1768+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
1769+ * Of The GNU General Public License
1770+ * Written And Developed By |Death|(death@hell360.net)
1771+ * - Based Off Of MangChat 1.0 By Cybrax(cybraxvf@gmail.com)
1772+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.*/
1773+#ifndef _IRC_CMD_H
1774+#define _IRC_CMD_H
1775+
1776+#define MAX_CLIENTS 50
1777+#include "Common.h"
1778+#include "../Player.h"
1779+#include "../ObjectAccessor.h"
1780+
1781+struct ChannelUser
1782+{
1783+ int UserType;
1784+ std::string Name;
1785+ std::string UName;
1786+ int UserLevel;
1787+};
1788+
1789+struct _client
1790+{
1791+ bool LoggedIn;
1792+ std::string Name;
1793+ std::string UName;
1794+ int GMLevel;
1795+};
1796+struct _CDATA
1797+{
1798+ std::string CMD;
1799+ std::string USER;
1800+ std::string FROM;
1801+ std::string PARAMS;
1802+ std::string TYPE;
1803+ int PCOUNT;
1804+};
1805+enum APVERR
1806+{
1807+ E_OK,
1808+ E_SIZE,
1809+ E_AUTH,
1810+ E_IVALID,
1811+};
1812+enum ESOUNDS
1813+{
1814+ S_ENTERWORLD = 602,
1815+ S_QUESTFAILED = 847,
1816+ S_INVITE = 880,
1817+ S_LEVELUP = 888,
1818+ S_COINSOUND = 895,
1819+ S_WHISPER = 3081,
1820+ S_STEALTH = 3325,
1821+};
1822+class IRCCmd
1823+{
1824+ public:
1825+ IRCCmd();
1826+ ~IRCCmd();
1827+
1828+ void Handle_Logout(_CDATA *CD);
1829+ bool IsLoggedIn(std::string USER);
1830+ bool IsValid(std::string USER, std::string FROM, std::string CHAT, std::string TYPE);
1831+ bool AcctIsLoggedIn(std::string USER);
1832+ _client *GetClient(std::string cname);
1833+
1834+ public:
1835+ static std::string MakeMsg(const char *sLine, ... );
1836+ static std::string ChanOrPM(_CDATA *CD);
1837+ int AcctLevel(std::string plnme);
1838+ int GetLevel(std::string sName);
1839+ std::string MakeUpper(std::string Channel);
1840+ std::string AcctIsBanned(std::string ACCT);
1841+ std::list<_client*> _CLIENTS;
1842+ Player* GetPlayer(std::string WHO);
1843+
1844+ private:
1845+ // TriniChat Commands
1846+ void Handle_Login(_CDATA *CD);
1847+ void Account_Player(_CDATA *CD);
1848+ void Ban_Player(_CDATA *CD);
1849+ void Chan_Control(_CDATA *CD);
1850+ void Char_Player(_CDATA *CD);
1851+ void Fun_Player(_CDATA *CD);
1852+ void Help_IRC(_CDATA *CD);
1853+ void Item_Player(_CDATA *CD);
1854+ void Inchan_Server(_CDATA *CD);
1855+ void Info_Server(_CDATA *CD);
1856+ void Jail_Player(_CDATA *CD);
1857+ void Kick_Player(_CDATA *CD);
1858+ void Kill_Player(_CDATA *CD);
1859+ void Level_Player(_CDATA *CD);
1860+ void Lookup_Player(_CDATA *CD);
1861+ void Money_Player(_CDATA *CD);
1862+ void Mute_Player(_CDATA *CD);
1863+ void Online_Players(_CDATA *CD);
1864+ void PM_Player(_CDATA *CD);
1865+ void Revive_Player(_CDATA *CD);
1866+ void Saveall_Player(_CDATA *CD);
1867+ void Shutdown_Mangos(_CDATA *CD);
1868+ void Spell_Player(_CDATA *CD);
1869+ void Sysmsg_Server(_CDATA *CD);
1870+ void Tele_Player(_CDATA *CD);
1871+ void Top_Player(_CDATA *CD);
1872+ void Who_Logged(_CDATA *CD);
1873+ bool CanUse(std::string USER, int nLevel);
1874+ bool ValidParams(std::string PARAMS, int nCount = 1);
1875+ bool ParamsValid(_CDATA *CD, int pCnt);
1876+ int ParamsValid(_CDATA *CD, int pCnt, int rLev);
1877+ std::string GetAccName(std::string sName);
1878+ std::string GetNameFromAcct(std::string sName);
1879+ std::string GetAcctNameFromID(uint32 acctid);
1880+ std::string GetIPFromPlayer(std::string player);
1881+ std::string SecToDay(std::string secons);
1882+ int GetAcctIDFromName(std::string sName);
1883+ std::string* getArray(std::string PARAMS, int nCount = 1);
1884+};
1885+inline void MakeLower(std::string& str)
1886+{
1887+ std::transform( str.begin(), str.end(), str.begin(), ::tolower );
1888+}
1889+#endif
1890\ No newline at end of file
1891diff --git a/src/game/mangchat/IRCCmde.cpp b/src/game/mangchat/IRCCmde.cpp
1892new file mode 100644
1893index 0000000..46244ed
1894--- a/src/game/mangchat/IRCCmde.cpp
1895+++ b/src/game/mangchat/IRCCmde.cpp
1896@@ -0,0 +1,1888 @@
1897+/*
1898+ * MangChat By |Death| And Cybrax
1899+ *
1900+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
1901+ * Of The GNU General Public License
1902+ * Written and Developed by Cybrax. cybraxvd@gmail.com
1903+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
1904+ * Modified for patch 3.0.8 by Shinzon <shinzon@wowgollum.com>
1905+ * With Help And Support From The MaNGOS Project Community.
1906+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
1907+ */
1908+#include "IRCCmd.h"
1909+#include "IRCClient.h"
1910+#include "MCS_OnlinePlayers.h"
1911+#include "WorldPacket.h"
1912+#include "Database/DatabaseEnv.h"
1913+#include "../Chat.h"
1914+#include "../MapManager.h"
1915+#include "../World.h"
1916+#include "../Guild.h"
1917+#include "../ObjectMgr.h"
1918+#include "../AccountMgr.h"
1919+#include "../Language.h"
1920+#include "../SpellAuras.h"
1921+#include "SystemConfig.h"
1922+#include "../Config/ConfigEnv.h"
1923+
1924+#define Send_Player(p, m) sIRC.Send_WoW_Player(p, m)
1925+#define Send_IRCA(c, m, b, t) sIRC.Send_IRC_Channel(c, m, b, t)
1926+
1927+#ifdef WIN32
1928+#define Delay(x) Sleep(x)
1929+#else
1930+#define Delay(x) sleep(x / 1000)
1931+#endif
1932+
1933+void IRCCmd::Handle_Login(_CDATA *CD)
1934+{
1935+ std::string* _PARAMS = getArray(CD->PARAMS, 2);
1936+ std::string isbanned = AcctIsBanned(_PARAMS[0]);
1937+ if(isbanned == "NOTBANNED")
1938+ {
1939+ if(!IsLoggedIn(CD->USER))
1940+ {
1941+ if(!AcctIsLoggedIn(_PARAMS[0].c_str()))
1942+ {
1943+ QueryResult *result = loginDatabase.PQuery("SELECT `gmlevel` FROM `account` WHERE `username`='%s' AND `sha_pass_hash`=SHA1(CONCAT(UPPER(`username`),':',UPPER('%s')));", _PARAMS[0].c_str(), _PARAMS[1].c_str());
1944+ if (result)
1945+ {
1946+ Field *fields = result->Fetch();
1947+ int GMLevel = fields[0].GetInt16();
1948+ if(GMLevel >= 0)
1949+ {
1950+ _client *NewClient = new _client();
1951+ NewClient->Name = CD->USER;
1952+ NewClient->UName = MakeUpper(_PARAMS[0]);
1953+ NewClient->GMLevel = fields[0].GetInt16();
1954+ _CLIENTS.push_back(NewClient);
1955+ Send_IRCA(CD->USER, MakeMsg("You Are Now Logged In As %s, Welcome To TriniChat Admin Mode.", _PARAMS[0].c_str()), true, CD->TYPE);
1956+
1957+ if(sIRC._op_gm == 1 && GMLevel >= sIRC._op_gm_lev)
1958+ {
1959+ for(int i=1;i < sIRC._chan_count + 1;i++)
1960+ sIRC.SendIRC("MODE #"+sIRC._irc_chan[i]+" +o "+CD->USER );
1961+ }
1962+ }
1963+ }else
1964+ Send_IRCA(CD->USER, "\0034[ERROR] : Sorry, Your Username Or Password Is Incorrect. Please Try Again. ", true, "ERROR");
1965+ }else
1966+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : %s Is Already Logged In With This Username. ", GetNameFromAcct(MakeUpper(_PARAMS[0])).c_str()), true, "ERROR");
1967+ }else
1968+ Send_IRCA(CD->USER, "\0034[ERROR] : You Are Already Logged In As "+ _PARAMS[0] +"!", true, "ERROR");
1969+ }else
1970+ Send_IRCA(CD->USER, "\0034[ERROR] : Sorry You Are "+isbanned+". You Cannot Log In To TriniChat "+CD->USER.c_str()+"!", true, "ERROR");
1971+}
1972+
1973+void IRCCmd::Handle_Logout(_CDATA *CD)
1974+{
1975+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
1976+ {
1977+ if((*i)->Name == CD->USER)
1978+ {
1979+ _CLIENTS.erase(i);
1980+ delete (*i);
1981+ Send_IRCA(CD->USER, "You Are Now Logged Out!", true, CD->TYPE);
1982+ return;
1983+ }
1984+ }
1985+ Send_IRCA(CD->USER, "\0034[ERROR] : You Are Not Logged In!", true, "ERROR");
1986+}
1987+
1988+void IRCCmd::Account_Player(_CDATA *CD)
1989+{
1990+ std::string* _PARAMS = getArray(CD->PARAMS, 3);
1991+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
1992+ {
1993+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
1994+ return;
1995+ }
1996+ normalizePlayerName(_PARAMS[0]);
1997+ uint64 guid = objmgr.GetPlayerGUIDByName(_PARAMS[0]);
1998+ uint32 account_id = 0;
1999+ account_id = objmgr.GetPlayerAccountIdByGUID(guid);
2000+ if(account_id)
2001+ {
2002+ if(account_id == GetAcctIDFromName(CD->USER) || GetLevel(CD->USER) >= sIRC._op_gm_lev)
2003+ {
2004+ Player* plr = objmgr.GetPlayer(guid);
2005+ if(_PARAMS[1] == "lock")
2006+ {
2007+ loginDatabase.PExecute( "UPDATE `account` SET `locked` = '1' WHERE `id` = '%d'",account_id);
2008+ if(plr) Send_Player(plr, MakeMsg("Your Account Has Been Locked To Your Current IP By: %s", CD->USER.c_str()));
2009+ Send_IRCA(ChanOrPM(CD), "\00313["+GetAcctNameFromID(account_id)+"] : Account Has Been Locked To Their Current IP Address.", true, CD->TYPE);
2010+ }
2011+ else if(_PARAMS[1] == "unlock")
2012+ {
2013+ loginDatabase.PExecute( "UPDATE `account` SET `locked` = '0' WHERE `id` = '%d'",account_id);
2014+ if(plr) Send_Player(plr, MakeMsg("Your Account Has Been UnLocked From The Associated IP By: %s", CD->USER.c_str()));
2015+ Send_IRCA(ChanOrPM(CD), "\00313["+GetAcctNameFromID(account_id)+"] : Account Has Been UnLocked From The Associated IP Address.", true, CD->TYPE);
2016+ }
2017+ else if(_PARAMS[1] == "mail")
2018+ {
2019+ loginDatabase.PExecute( "UPDATE `account` SET `email` = '%s' WHERE `id` = '%d'",_PARAMS[2].c_str() ,account_id);
2020+ if (plr) Send_Player(plr, MakeMsg("%s Has Changed Your EMail Adress To: %s", CD->USER.c_str(), _PARAMS[2].c_str()));
2021+ Send_IRCA(ChanOrPM(CD), "\00313["+GetAcctNameFromID(account_id)+"] : EMail Address Successfully Changed To: "+_PARAMS[2], true, CD->TYPE);
2022+ }
2023+ else if(_PARAMS[1] == "pass")
2024+ {
2025+ loginDatabase.PExecute( "UPDATE `account` SET `sha_pass_hash` = SHA1(CONCAT(UPPER(`username`),':',UPPER('%s'))) WHERE `id` = '%d'",_PARAMS[2].c_str() ,account_id);
2026+ if (plr) Send_Player(plr, MakeMsg("%s Has Changed Your Password To: %s", CD->USER.c_str(), _PARAMS[2].c_str()));
2027+ Send_IRCA(ChanOrPM(CD), "\00313["+GetAcctNameFromID(account_id)+"] : Password Successfully Changed To: "+_PARAMS[2], true, CD->TYPE);
2028+ }
2029+ else if(_PARAMS[1] == "rename")
2030+ {
2031+ if(plr)
2032+ {
2033+ plr->SetAtLoginFlag(AT_LOGIN_RENAME);
2034+ Send_Player(plr, MakeMsg("%s Has Requested You Change This Characters Name, Rename Will Be Forced On Next Login!", CD->USER.c_str()));
2035+ }
2036+ CharacterDatabase.PExecute("UPDATE `characters` SET `at_login` = `at_login` | '1' WHERE `guid` = '%u'", guid);
2037+ Send_IRCA(ChanOrPM(CD), "\00313["+GetAcctNameFromID(account_id)+"] : Has Been Forced To Change Their Characters Name, Rename Will Be Forced On Next Login!", true, CD->TYPE);
2038+ }
2039+ }
2040+ else
2041+ Send_IRCA(CD->USER, "\0034[ERROR] : You Are Not A GM, You May Only Change Settings In Your Own Account.", true, "ERROR");
2042+ }
2043+ else
2044+ Send_IRCA(CD->USER, "\0034[ERROR] : No Such Player Exists, So Account Cannot Be Looked Up.", true, "ERROR");
2045+}
2046+
2047+void IRCCmd::Ban_Player(_CDATA *CD)
2048+{
2049+ std::string* _PARAMS = getArray(CD->PARAMS, 3);
2050+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
2051+ {
2052+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
2053+ return;
2054+ }
2055+ if(_PARAMS[1] == "ip")
2056+ {
2057+ std::string ip = GetIPFromPlayer(_PARAMS[0]);
2058+ if(_PARAMS[2] == "")
2059+ _PARAMS[2] = "No Reason";
2060+ if(ip != "")
2061+ {
2062+ loginDatabase.PExecute( "INSERT IGNORE INTO `ip_banned` VALUES ('%s', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '%s', '%s')", ip.c_str(), CD->USER.c_str(), _PARAMS[2].c_str());
2063+ if (Player* plr = GetPlayer(_PARAMS[0]))
2064+ plr->GetSession()->KickPlayer();
2065+ Send_IRCA(ChanOrPM(CD), MakeMsg("\00313[%s] : Has Had Their IP Address Banned. [%s] Reason: %s",_PARAMS[0].c_str() ,ip.c_str() , _PARAMS[2].c_str()), true, CD->TYPE);
2066+ }
2067+ else
2068+ Send_IRCA(CD->USER, "\0034[ERROR] : I Cannot Locate An IP Address For The Character Name Given.", true, "ERROR");
2069+ }
2070+ if(_PARAMS[1] == "acct")
2071+ {
2072+ uint64 guid = objmgr.GetPlayerGUIDByName(_PARAMS[0].c_str());
2073+ uint32 acctid = objmgr.GetPlayerAccountIdByGUID(guid);
2074+ if(_PARAMS[2] == "")
2075+ _PARAMS[2] = "No Reason";
2076+ if(acctid)
2077+ {
2078+ loginDatabase.PExecute( "INSERT INTO `account_banned` VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '%s', '%s', 1)", acctid, CD->USER.c_str(), _PARAMS[2].c_str());
2079+ if (Player* plr = GetPlayer(_PARAMS[0]))
2080+ plr->GetSession()->KickPlayer();
2081+ Send_IRCA(ChanOrPM(CD), MakeMsg("\00313[%s] : Has Had Their Account Banned. Reason: %s",_PARAMS[0].c_str(), _PARAMS[2].c_str()), true, CD->TYPE);
2082+ }
2083+ else
2084+ Send_IRCA(CD->USER, "\0034[ERROR] : I Cannot Locate An Account For The Character Name Given.", true, "ERROR");
2085+ }
2086+ if(_PARAMS[1] == "unban")
2087+ {
2088+ std::string unbani = _PARAMS[0];
2089+ if(atoi(unbani.c_str()) > 0)
2090+ {
2091+ loginDatabase.PExecute( "DELETE FROM ip_banned WHERE ip = '%s'", _PARAMS[0].c_str());
2092+ Send_IRCA(ChanOrPM(CD), MakeMsg("\00313[%s] : Has Been Removed From The IP Ban List.", _PARAMS[0].c_str()), true, CD->TYPE);
2093+ }
2094+ else
2095+ {
2096+ QueryResult *result = loginDatabase.PQuery("SELECT id FROM `account` WHERE username = '%s'", _PARAMS[0].c_str());
2097+ if(result)
2098+ {
2099+ Field *fields = result->Fetch();
2100+ std::string id = fields[0].GetCppString();
2101+
2102+ loginDatabase.PExecute( "DELETE FROM account_banned WHERE id = %s", id.c_str());
2103+ delete result;
2104+ Send_IRCA(ChanOrPM(CD), MakeMsg("\00313[%s] : Has Been Removed From The Account Ban List.", _PARAMS[0].c_str()), true, CD->TYPE);
2105+
2106+ }
2107+ else
2108+ Send_IRCA(CD->USER, "\0034[ERROR] : I Cannot Locate An Account Or IP Address For The Paramaters Given.", true, "ERROR");
2109+ }
2110+ }
2111+}
2112+
2113+void IRCCmd::Chan_Control(_CDATA *CD)
2114+{
2115+ std::string* _PARAMS = getArray(CD->PARAMS, 2);
2116+ if(CD->FROM == sIRC._Nick)
2117+ {
2118+ Send_IRCA(CD->USER, "\0034[ERROR] : You Cannot Use This Command Through A PM Yet.", true, "ERROR");
2119+ return;
2120+ }
2121+ if(_PARAMS[0] == "op")
2122+ {
2123+ if(_PARAMS[1].length() > 1)
2124+ sIRC.SendIRC("MODE "+CD->FROM+" +o "+_PARAMS[1] );
2125+ else
2126+ sIRC.SendIRC("MODE "+CD->FROM+" +o "+CD->USER );
2127+ }
2128+ if(_PARAMS[0] == "deop")
2129+ {
2130+ if(_PARAMS[1].length() > 1)
2131+ sIRC.SendIRC("MODE "+CD->FROM+" -o "+_PARAMS[1] );
2132+ else
2133+ sIRC.SendIRC("MODE "+CD->FROM+" -o "+CD->USER );
2134+ }
2135+ if(_PARAMS[0] == "voice")
2136+ {
2137+ if(_PARAMS[1].length() > 1)
2138+ sIRC.SendIRC("MODE "+CD->FROM+" +v "+_PARAMS[1] );
2139+ else
2140+ sIRC.SendIRC("MODE "+CD->FROM+" +v "+CD->USER );
2141+ }
2142+ if(_PARAMS[0] == "devoice")
2143+ {
2144+ if(_PARAMS[1].length() > 1)
2145+ sIRC.SendIRC("MODE "+CD->FROM+" -v "+_PARAMS[1] );
2146+ else
2147+ sIRC.SendIRC("MODE "+CD->FROM+" -v "+CD->USER );
2148+ }
2149+}
2150+
2151+void IRCCmd::Char_Player(_CDATA *CD)
2152+{
2153+ std::string* _PARAMS = getArray(CD->PARAMS, 5);
2154+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
2155+ {
2156+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
2157+ return;
2158+ }
2159+ normalizePlayerName(_PARAMS[0]);
2160+ uint64 guid = objmgr.GetPlayerGUIDByName(_PARAMS[0]);
2161+ Player* plr = objmgr.GetPlayer(guid);
2162+ if(plr)
2163+ {
2164+ if(_PARAMS[1] == "mapcheat")
2165+ {
2166+ bool explore = false;
2167+ if (_PARAMS[2] != "0")
2168+ explore = true;
2169+ for (uint8 i=0; i<64; i++)
2170+ {
2171+ if (_PARAMS[2] != "0")
2172+ plr->SetFlag(PLAYER_EXPLORED_ZONES_1+i,0xFFFFFFFF);
2173+ else
2174+ plr->SetFlag(PLAYER_EXPLORED_ZONES_1+i,0);
2175+ }
2176+ if(explore)
2177+ {
2178+ Send_Player(plr, MakeMsg("All Your Zones Have Been Set To Explored By: %s", CD->USER.c_str()));
2179+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Now Explored All Zones.", true, CD->TYPE);
2180+ }
2181+ else
2182+ {
2183+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Now Had All Zones Set To Un-Explored.", true, CD->TYPE);
2184+ Send_Player(plr, MakeMsg("All Your Zones Have Been Set To Un-Explored By: %s", CD->USER.c_str()));
2185+ }
2186+ }
2187+ if(_PARAMS[1] == "taxicheat")
2188+ {
2189+ if (_PARAMS[2] != "0")
2190+ {
2191+ plr->SetTaxiCheater(true);
2192+ Send_Player(plr, MakeMsg("Taxi Node Cheat Has Been Enabled By: %s", CD->USER.c_str()));
2193+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Taxi Node Cheat Has Been Enabled.", true, CD->TYPE);
2194+ }
2195+ else
2196+ {
2197+ plr->SetTaxiCheater(false);
2198+ Send_Player(plr, MakeMsg("Taxi Node Cheat Has Been Disabled By: %s", CD->USER.c_str()));
2199+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Taxi Node Cheat Has Been Disabled.", true, CD->TYPE);
2200+ }
2201+ }
2202+ if(_PARAMS[1] == "maxskill")
2203+ {
2204+ plr->UpdateSkillsToMaxSkillsForLevel();
2205+ Send_Player(plr, MakeMsg("Your Skills Have Been Maxed Out By: %s", CD->USER.c_str()));
2206+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Skills Have Been Maxed Out.", true, CD->TYPE);
2207+ }
2208+ if(_PARAMS[1] == "setskill")
2209+ {
2210+ std::string* _PARAMSA = getArray(_PARAMS[2], 4);
2211+ uint32 skill = atoi(_PARAMS[2].c_str());
2212+ uint32 level = atol(_PARAMS[3].c_str());
2213+ int32 max = _PARAMS[4].c_str() ? atol (_PARAMS[4].c_str()) : plr->GetPureMaxSkillValue(skill);
2214+ SkillLineEntry const* skilllookup = sSkillLineStore.LookupEntry(skill);
2215+ //if skillid entered is not a number and greater then 0 then the command is being used wrong
2216+ if(skill >= 0)
2217+ {
2218+ //does the skill even exist
2219+ if(skilllookup)
2220+ {
2221+ //does player have the skill yet
2222+ if(plr->GetSkillValue(skill))
2223+ {
2224+ plr->SetSkill(skill,level,max);
2225+ Send_Player(plr, MakeMsg("Skill: %s Has Been Set To Level: %i Max: %i By: %s",skilllookup->name[0], level, max, CD->USER.c_str()));
2226+ Send_IRCA(ChanOrPM(CD), MakeMsg("\00313[%s] : Has Had Skill: %s Set To Level: %d Max: %d",_PARAMS[0].c_str() , skilllookup->name[0], level, max), true, CD->TYPE);
2227+ }
2228+ else
2229+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Player Does Not Have The %s Skill Yet.", skilllookup->name[0]), true, "ERROR");
2230+ }
2231+ else
2232+ Send_IRCA(CD->USER, "\0034[ERROR] : That Skill ID Does Not Exist.", true, "ERROR");
2233+ }
2234+ else
2235+ Send_IRCA(CD->USER, "\0034[ERROR] : The Skill ID Entered Is Invalid.", true, "ERROR");
2236+ }
2237+ }
2238+ else
2239+ Send_IRCA(CD->USER, "\0034[ERROR] : No Character With That Name Exists.", true, "ERROR");
2240+}
2241+
2242+void IRCCmd::Fun_Player(_CDATA *CD)
2243+{
2244+ std::string* _PARAMS = getArray(CD->PARAMS, 3);
2245+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
2246+ {
2247+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
2248+ return;
2249+ }
2250+ if (Player* plr = GetPlayer(_PARAMS[0]))
2251+ {
2252+ if(_PARAMS[1] == "say")
2253+ {
2254+ plr->Say(_PARAMS[2], LANG_UNIVERSAL);
2255+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Was Forced To Say: "+_PARAMS[2]+".", true, CD->TYPE);
2256+ }
2257+ // if(_PARAMS[1] == "sound")
2258+ // {
2259+ // uint32 sndid = atoi(_PARAMS[2].c_str());
2260+ // plr->PlaySound(sndid ,true);
2261+ // Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Just Heard Sound ID: "+_PARAMS[2]+".", true, CD->TYPE);
2262+ // }
2263+ }
2264+ else
2265+ Send_IRCA(CD->USER, "\0034[ERROR] : Player Not Online!", true, "ERROR");
2266+}
2267+
2268+void IRCCmd::Help_IRC(_CDATA *CD)
2269+{
2270+ std::string* _PARAMS = getArray(CD->PARAMS, 1);
2271+ QueryResult *result = WorldDatabase.PQuery("SELECT `Command`, `Description`, `gmlevel` FROM `IRC_Commands`");
2272+ if(result)
2273+ {
2274+ if(IsLoggedIn(CD->USER))
2275+ {
2276+ if(_PARAMS[0] == "")
2277+ {
2278+ QueryResult *result = WorldDatabase.PQuery("SELECT * FROM `IRC_Commands` WHERE `gmlevel` <= %u ORDER BY `Command`", GetLevel(CD->USER));
2279+ if(result)
2280+ {
2281+ std::string output = "\002TriniChat IRC Commands:\017 ";
2282+ for (uint64 i=0; i < result->GetRowCount(); i++)
2283+ {
2284+ Field *fields = result->Fetch();
2285+ output += fields[0].GetCppString() + ", ";
2286+ result->NextRow();
2287+ }
2288+ delete result;
2289+ Send_IRCA(CD->USER, output, true, CD->TYPE.c_str());
2290+ }
2291+ }
2292+ else
2293+ {
2294+ QueryResult *result = WorldDatabase.PQuery("SELECT `Description`, `gmlevel` FROM `IRC_Commands` WHERE `Command` = '%s'", _PARAMS[0].c_str());
2295+ if(result)
2296+ {
2297+ Field *fields = result->Fetch();
2298+ if(fields[1].GetUInt32() > GetLevel(CD->USER))
2299+ {
2300+ Send_IRCA(CD->USER, "You Do Not Have Access To That Command, So No Help Is Available.", true, CD->TYPE.c_str());
2301+ return;
2302+ }
2303+ if(result)
2304+ {
2305+ std::string cmdhlp = fields[0].GetCppString();
2306+ delete result;
2307+ Send_IRCA(CD->USER, cmdhlp, true, CD->TYPE.c_str());
2308+ }
2309+ }
2310+ else
2311+ Send_IRCA(CD->USER, "\0034[ERROR] : No Such Command Exists, Please Check The Spelling And Try Again.", true, "ERROR");
2312+ }
2313+ }
2314+ else if(!IsLoggedIn(CD->USER))
2315+ {
2316+ if(_PARAMS[0] == "")
2317+ {
2318+ QueryResult *result = WorldDatabase.PQuery("SELECT * FROM `IRC_Commands` WHERE `gmlevel` = 0 ORDER BY `Command`");
2319+ if(result)
2320+ {
2321+ std::string output = "\002TriniChat IRC Commands:\017 ";
2322+ for (uint64 i=0; i < result->GetRowCount(); i++)
2323+ {
2324+ Field *fields = result->Fetch();
2325+ output += fields[0].GetCppString() + ", ";
2326+ result->NextRow();
2327+ }
2328+ delete result;
2329+ Send_IRCA(CD->USER, output, true, CD->TYPE.c_str());
2330+ Send_IRCA(CD->USER, "You Are Currently Not Logged In, Please Login To See A Complete List Of Commands Available To You.", true, CD->TYPE.c_str());
2331+ }
2332+ }
2333+ else
2334+ {
2335+ QueryResult *result = WorldDatabase.PQuery("SELECT `Description`, `gmlevel` FROM `IRC_Commands` WHERE `Command` = '%s'", _PARAMS[0].c_str());
2336+ if(result)
2337+ {
2338+ Field *fields = result->Fetch();
2339+ if(fields[1].GetUInt32() > 0)
2340+ {
2341+ Send_IRCA(CD->USER, "You Do Not Have Access To That Command, So No Help Is Available.", true, CD->TYPE.c_str());
2342+ return;
2343+ }
2344+ std::string cmdhlp = fields[0].GetCppString();
2345+ delete result;
2346+ Send_IRCA(CD->USER, cmdhlp, true, CD->TYPE.c_str());
2347+ }
2348+ else
2349+ Send_IRCA(CD->USER, "\0034[ERROR] : No Such Command Exists, Please Check The Spelling And Try Again.", true, "ERROR");
2350+ }
2351+ }
2352+ }
2353+ else
2354+ Send_IRCA(CD->USER, "\0034[ERROR] : Database Error! Please Make Sure You Used IRC_Commands.sql, You Must Have A Table In Your World Database (IRC_Commands)!", true, "ERROR");
2355+}
2356+
2357+void IRCCmd::Inchan_Server(_CDATA *CD)
2358+{
2359+ std::string* _PARAMS = getArray(CD->PARAMS, 1);
2360+ if(_PARAMS[0] == "")
2361+ {
2362+ Send_IRCA(CD->USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"inchan <ChannelName> )", true, "ERROR");
2363+ return;
2364+ }
2365+ QueryResult *result = WorldDatabase.PQuery("SELECT * FROM `IRC_Inchan` WHERE `channel` = '%s' ORDER BY `name`", _PARAMS[0].c_str());
2366+ if(result)
2367+ {
2368+ Field *fields = result->Fetch();
2369+ std::string output = "\002Players In The [ "+fields[2].GetCppString()+" ] Channel:\017 ";
2370+ for (uint64 i=0; i < result->GetRowCount(); i++)
2371+ {
2372+ output += fields[1].GetCppString() + ", ";
2373+ result->NextRow();
2374+ }
2375+ delete result;
2376+ Send_IRCA(ChanOrPM(CD), output, true, CD->TYPE);
2377+ }
2378+ else
2379+ Send_IRCA(ChanOrPM(CD), "No Players Are Currently In [ "+_PARAMS[0]+" ] Channel!", true, CD->TYPE.c_str());
2380+}
2381+
2382+void IRCCmd::Info_Server(_CDATA *CD)
2383+{
2384+ std::string* _PARAMS = getArray(CD->PARAMS, 1);
2385+ char clientsNum [50];
2386+ sprintf(clientsNum, "%u", sWorld.GetActiveSessionCount());
2387+ char maxClientsNum [50];
2388+ sprintf(maxClientsNum, "%u", sWorld.GetMaxActiveSessionCount());
2389+ std::string str = secsToTimeString(sWorld.GetUptime());
2390+ std::string svnrev = "MaNGOS SVN Mirror";
2391+ Send_IRCA(ChanOrPM(CD), "\x2 Number Of Players Online:\x3\x31\x30 " + (std::string)clientsNum + "\xF |\x2 Max Since Last Restart:\x3\x31\x30 "+(std::string)maxClientsNum+"\xF |\x2 UpTime:\x3\x31\x30 "+str, true, CD->TYPE);
2392+ Send_IRCA(ChanOrPM(CD), "\x2 MaNGOS SVN Rev:\x3\x31\x30 "+svnrev, true, CD->TYPE);
2393+}
2394+
2395+void IRCCmd::Item_Player(_CDATA *CD)
2396+{
2397+ std::string* _PARAMS = getArray(CD->PARAMS, 3);
2398+
2399+ normalizePlayerName(_PARAMS[0]);
2400+ Player *chr = GetPlayer(_PARAMS[0].c_str());
2401+ if(_PARAMS[1] == "add")
2402+ {
2403+ std::string s_param = _PARAMS[2];
2404+
2405+ char *args = (char*)s_param.c_str();
2406+ uint32 itemId = 0;
2407+ if(args[0]=='[')
2408+ {
2409+ char* citemName = citemName = strtok((char*)args, "]");
2410+ if(citemName && citemName[0])
2411+ {
2412+ std::string itemName = citemName+1;
2413+ WorldDatabase.escape_string(itemName);
2414+ QueryResult *result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE name = '%s'", itemName.c_str());
2415+ if (!result)
2416+ {
2417+ Send_IRCA(CD->USER, "\0034[ERROR] : Item Not Found!", true, "ERROR");
2418+ return;
2419+ }
2420+ itemId = result->Fetch()->GetUInt16();
2421+ delete result;
2422+ }
2423+ else
2424+ {
2425+ Send_IRCA(CD->USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"item <Player> <add> [Exact Item Name] <Amount> )", true, "ERROR");
2426+ return;
2427+ }
2428+ }
2429+ else
2430+ {
2431+ std::string itemName = s_param;
2432+ WorldDatabase.escape_string(itemName);
2433+ QueryResult *result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE name = '%s'", itemName.c_str());
2434+ if (result)
2435+ {
2436+ itemId = result->Fetch()->GetUInt16();
2437+ }
2438+ delete result;
2439+
2440+ char* cId = strtok(args, " ");
2441+ if(!cId)
2442+ {
2443+ Send_IRCA(CD->USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"item <Player> <add> <ItemID> <Amount> )", true, "ERROR");
2444+ return;
2445+ }
2446+ itemId = atol(cId);
2447+ }
2448+ char* ccount = strtok(NULL, " ");
2449+ int32 count = 1;
2450+ if (ccount) { count = atol(ccount); }
2451+ Player* plTarget = chr;
2452+ if(!plTarget)
2453+ {
2454+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Not Online!", true, "ERROR");
2455+ return;
2456+ }
2457+ ItemPrototype const *pProto = objmgr.GetItemPrototype(itemId);
2458+ //Subtract
2459+ if (count < 0)
2460+ {
2461+ plTarget->DestroyItemCount(itemId, -count, true, false);
2462+ char itemid2[255];
2463+ sprintf(itemid2,"%d",itemId);
2464+ std::string itake = " \00313["+ _PARAMS[0] +"] : Has Had Item " +itemid2+ " Taken From Them!";
2465+ Send_IRCA(ChanOrPM(CD), itake, true, CD->TYPE);
2466+ return;
2467+ }
2468+ //Adding items
2469+ uint32 noSpaceForCount = 0;
2470+
2471+ // check space and find places
2472+ ItemPosCountVec dest;
2473+ uint8 msg = plTarget->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemId, count, &noSpaceForCount );
2474+ if( msg == EQUIP_ERR_INVENTORY_FULL ) // convert to possibel store amount
2475+ count -= noSpaceForCount;
2476+ else if( msg != EQUIP_ERR_OK ) // other error, can't add
2477+ {
2478+ char s_countForStore[255];
2479+ sprintf(s_countForStore,"%d",count);
2480+ std::string ierror = " \00313["+ _PARAMS[0] +"] : Could Not Create All Items! " +s_countForStore+ " Item(s) Were Not Created!";
2481+ Send_IRCA(ChanOrPM(CD), ierror, true, CD->TYPE);
2482+ return;
2483+ }
2484+ Item* item = plTarget->StoreNewItem( dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId));
2485+ if(count > 0 && item)
2486+ {
2487+ plTarget->SendNewItem(item,count,true,false);
2488+ QueryResult *result = WorldDatabase.PQuery("SELECT name FROM item_template WHERE entry = %d", itemId);
2489+ char* dbitemname = NULL;
2490+ if (result)
2491+ {
2492+ dbitemname = (char*)result->Fetch()->GetString();
2493+ }
2494+ std::string iinfo = " \00313[" + _PARAMS[0] + "] : Has Been Given Item "+dbitemname+". From: "+CD->USER.c_str()+".";
2495+ Send_IRCA(ChanOrPM(CD), iinfo, true, CD->TYPE);
2496+ delete result;
2497+ }
2498+ if(noSpaceForCount > 0)
2499+ {
2500+ char s_countForStore[255];
2501+ sprintf(s_countForStore,"%d",noSpaceForCount);
2502+ std::string ierror = " \00313["+ _PARAMS[0] +"] : Could Not Create All Items! " +s_countForStore+ " Item(s) Were Not Created!";
2503+ Send_IRCA(ChanOrPM(CD), ierror, true, CD->TYPE);
2504+ return;
2505+ }
2506+ }
2507+ else
2508+ {
2509+ Send_IRCA(CD->USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"item <Player> <add> <ItemID> <Amount> )", true, "ERROR");
2510+ return;
2511+ }
2512+}
2513+
2514+void IRCCmd::Jail_Player(_CDATA *CD)
2515+{
2516+ if(ValidParams(CD->PARAMS, 1))
2517+ {
2518+ std::string* _PARAMS = getArray(CD->PARAMS, 2);
2519+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
2520+ {
2521+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
2522+ return;
2523+ }
2524+ if (Player *plr = GetPlayer(_PARAMS[0]))
2525+ {
2526+ std::string sReason = "";
2527+ if(_PARAMS[1] == "release")
2528+ {
2529+ float rposx, rposy, rposz, rposo = 0;
2530+ uint32 rmapid = 0;
2531+ CharacterDatabase.escape_string(_PARAMS[0]);
2532+ QueryResult *result = CharacterDatabase.PQuery( "SELECT `map`, `position_x`, `position_y`, `position_z` FROM `character_homebind` WHERE `guid` = '" UI64FMTD "'", plr->GetGUID() );
2533+ if(result)
2534+ {
2535+ Field *fields = result->Fetch();
2536+ rmapid = fields[0].GetUInt16();
2537+ rposx = fields[1].GetFloat();
2538+ rposy = fields[2].GetFloat();
2539+ rposz = fields[3].GetFloat();
2540+ delete result;
2541+ plr->SetMovement(MOVE_UNROOT);
2542+ plr->TeleportTo(rmapid, rposx, rposy, rposz, rposo);
2543+ plr->RemoveAurasDueToSpell(42201);
2544+ plr->RemoveAurasDueToSpell(23775);
2545+ plr->RemoveAurasDueToSpell(9454);
2546+ Send_Player(plr, MakeMsg("You Have Been Released By: %s.", CD->USER.c_str()));
2547+ sReason = " \00313["+_PARAMS[0]+"] : Has Been Released By: "+CD->USER+".";
2548+ Send_IRCA(ChanOrPM(CD), sReason, true, CD->TYPE);
2549+ }
2550+ }
2551+ else
2552+ {
2553+ if(_PARAMS[1] == "")
2554+ _PARAMS[1] = "No Reason Given.";
2555+ plr->TeleportTo(13, 0, 0, 0, 0);
2556+ plr->SetMovement(MOVE_ROOT);
2557+ plr->CastSpell(plr, 42201, true);
2558+ plr->CastSpell(plr, 23775, true);
2559+ plr->CastSpell(plr, 9454, true);
2560+ Send_Player(plr, MakeMsg("You Have Been Jailed By: %s. Reason: %s.", CD->USER.c_str(), _PARAMS[1].c_str()));
2561+ sReason = " \00313["+_PARAMS[0]+"] : Has Been Jailed By: "+CD->USER+". Reason: "+_PARAMS[1]+".";
2562+ Send_IRCA(ChanOrPM(CD), sReason, true, CD->TYPE);
2563+ }
2564+ }
2565+ else
2566+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Not Online!", true, "ERROR");
2567+ }
2568+}
2569+
2570+void IRCCmd::Kick_Player(_CDATA *CD)
2571+{
2572+ std::string* _PARAMS = getArray(CD->PARAMS, CD->PCOUNT);
2573+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
2574+ {
2575+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
2576+ return;
2577+ }
2578+ if(_PARAMS[1] == "")
2579+ _PARAMS[1] = "No Reason Given.";
2580+ if (Player* plr = GetPlayer(_PARAMS[0]))
2581+ {
2582+ plr->GetSession()->KickPlayer();
2583+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Been Kicked By: "+CD->USER+". Reason: "+_PARAMS[1]+".", true, CD->TYPE);
2584+ }
2585+ else
2586+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Not Online!", true, "ERROR");
2587+}
2588+
2589+void IRCCmd::Kill_Player(_CDATA *CD)
2590+{
2591+ std::string* _PARAMS = getArray(CD->PARAMS, CD->PCOUNT);
2592+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
2593+ {
2594+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
2595+ return;
2596+ }
2597+ if (Player* plr = GetPlayer(_PARAMS[0]))
2598+ {
2599+ if(plr->isAlive())
2600+ {
2601+ plr->DealDamage(plr, plr->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
2602+ plr->SaveToDB();
2603+ if(_PARAMS[1] == "")
2604+ _PARAMS[1] = "No Reason Given.";
2605+ Send_IRCA(ChanOrPM(CD), MakeMsg("\00313[%s] : Has Been Killed By: %s.", _PARAMS[0].c_str(), CD->USER.c_str()) + + + " Reason: "+_PARAMS[1]+".", true, CD->TYPE);
2606+ Send_Player(plr, MakeMsg("You Have Been Killed By: %s. Reason: %s.", CD->USER.c_str(), _PARAMS[1].c_str()));
2607+ }
2608+ else
2609+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Already Dead!", true, "ERROR");
2610+ }
2611+ else
2612+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Not Online!", true, "ERROR");
2613+}
2614+
2615+void IRCCmd::Lookup_Player(_CDATA *CD)
2616+{
2617+ std::string* _PARAMS = getArray(CD->PARAMS, CD->PCOUNT);
2618+ if(_PARAMS[0] == "acct")
2619+ {
2620+ uint32 acctid = atoi(_PARAMS[1].c_str());
2621+ if(accmgr.GetId(_PARAMS[1]))
2622+ acctid = accmgr.GetId(_PARAMS[1]);
2623+ if(acctid > 0)
2624+ {
2625+ std::string DateTime = "%a, %b %d, %Y - %h:%i%p";
2626+ QueryResult *result = loginDatabase.PQuery("SELECT id, username, gmlevel, last_ip, (SELECT banreason FROM account_banned WHERE id = %d LIMIT 1) as banned, (SELECT banreason FROM ip_banned WHERE ip = last_ip) as bannedip, DATE_FORMAT(last_login, '%s') FROM `account` WHERE id = %d", acctid, DateTime.c_str(), acctid, acctid);
2627+ if(result)
2628+ {
2629+ Field *fields = result->Fetch();
2630+
2631+ uint32 id = fields[0].GetUInt32();
2632+ std::string usrname = fields[1].GetCppString();
2633+ uint32 gm = fields[2].GetUInt32();
2634+ std::string lastip = fields[3].GetCppString();
2635+ std::string banreason = fields[4].GetCppString();
2636+ std::string banreasonip = fields[5].GetCppString();
2637+ std::string lastlogin = fields[6].GetCppString();
2638+ delete result;
2639+
2640+ QueryResult *chars = CharacterDatabase.PQuery("SELECT guid, name, (SELECT SUM(totaltime) FROM characters WHERE account = %d) AS tottime FROM characters WHERE account = %u", id, id);
2641+ std::string characters = "None";
2642+ std::string totaccttime = "Never Logged In";
2643+ if(chars)
2644+ {
2645+ characters = "";
2646+ Field *fields = chars->Fetch();
2647+ totaccttime = SecToDay(fields[2].GetCppString());
2648+ for (uint64 i=0; i < chars->GetRowCount(); i++)
2649+ {
2650+ std::string guid = fields[0].GetCppString();
2651+ std::string charname = fields[1].GetCppString();
2652+ characters.append(charname+"("+guid+"), ");
2653+ chars->NextRow();
2654+ }
2655+ delete chars;
2656+ }
2657+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2Username:\x3\x31\x30 %s \xF|\x2 AccountID:\x3\x31\x30 %d \xF|\x2 GM Level:\x3\x31\x30 %d \xF|\x2 Last IP:\x3\x31\x30 %s \xF|\x2 Last Login:\x3\x31\x30 %s", usrname.c_str(), id, gm, lastip.c_str(), lastlogin.c_str()), true, CD->TYPE);
2658+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2Total Play Time:\x3\x31\x30 %s \xF|\x2 Characters:\x3\x31\x30 %s ", totaccttime.c_str(), characters.c_str()), true, CD->TYPE);
2659+ if(banreason.length() > 1)
2660+ Send_IRCA(ChanOrPM(CD), MakeMsg("\0034This User Has An Account Ban. Ban Reason: %s", banreason.c_str()), true, CD->TYPE);
2661+ if(banreasonip.length() > 1)
2662+ Send_IRCA(ChanOrPM(CD), MakeMsg("\0034This User Has An IP Ban. Ban Reason: %s", banreasonip.c_str()), true, CD->TYPE);
2663+ }
2664+ else
2665+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Account ID." ,true, "ERROR");
2666+ }
2667+ else
2668+ {
2669+ QueryResult *result = loginDatabase.PQuery("SELECT id, username FROM `account` WHERE username LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
2670+ if(result)
2671+ {
2672+ Field *fields = result->Fetch();
2673+ std::string accts = "\002Account Search Results:\x3\x31\x30 ";
2674+ for (uint64 i=0; i < result->GetRowCount(); i++)
2675+ {
2676+ std::string acctid = fields[0].GetCppString();
2677+ std::string acctname = fields[1].GetCppString();
2678+ accts.append(acctname+"("+acctid+")\xF | \x3\x31\x30\x2");
2679+ result->NextRow();
2680+ }
2681+ delete result;
2682+ Send_IRCA(ChanOrPM(CD), accts, true, CD->TYPE);
2683+ }
2684+ else
2685+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Username. I Cant Find Any Users With Those Search Terms." ,true, "ERROR");
2686+ }
2687+ }
2688+ if(_PARAMS[0] == "char")
2689+ {
2690+ uint32 plguid = atoi(_PARAMS[1].c_str());
2691+ if(objmgr.GetPlayerGUIDByName(_PARAMS[1].c_str()))
2692+ plguid = objmgr.GetPlayerGUIDByName(_PARAMS[1].c_str());
2693+ if(plguid > 0)
2694+ {
2695+ QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account, name, race, class, online, SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ' , 35), ' ' , -1) AS level, SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ' , 238), ' ' , -1) AS guildid, SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ' , 239), ' ' , -1) AS guildrank, SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ' , 927), ' ' , -1) AS xp, SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ' , 928), ' ' , -1) AS maxxp, SUBSTRING_INDEX(SUBSTRING_INDEX(data, ' ' , 1462), ' ' , -1) AS gold, SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ' , 1454), ' ' , -1) AS hk, totaltime FROM characters WHERE guid =%i", plguid);
2696+ uint32 latency = 0;
2697+ Player *chr = objmgr.GetPlayer(plguid);
2698+ if(chr)
2699+ {
2700+ latency = chr->GetSession()->GetLatency();
2701+ }
2702+ char templatency [100];
2703+ sprintf(templatency, "%ums", latency);
2704+ if(result)
2705+ {
2706+ Field *fields = result->Fetch();
2707+ std::string pguid = fields[0].GetCppString();
2708+ std::string pacct = fields[1].GetCppString();
2709+ std::string pname = fields[2].GetCppString();
2710+ uint32 praceid = fields[3].GetUInt32();
2711+ uint32 pclassid = fields[4].GetUInt32();
2712+ std::string ponline = (fields[5].GetInt32() == 1 ? "\x3\x30\x33Online" : "\x3\x30\x34Offline\xF");
2713+ std::string plevel = fields[6].GetCppString();
2714+ uint32 pguildid = fields[7].GetUInt32();
2715+ uint32 pguildrank = fields[8].GetUInt32();
2716+ std::string pxp = fields[9].GetCppString();
2717+ std::string pmaxxp = fields[10].GetCppString();
2718+ unsigned int money = fields[11].GetInt32();
2719+ std::string hk = fields[12].GetCppString();
2720+ std::string totaltim = SecToDay(fields[13].GetCppString());
2721+ delete result;
2722+ std::string sqlquery = "SELECT `gmlevel` FROM `account` WHERE `id` = '" + pacct + "';";
2723+ QueryResult *result = loginDatabase.Query(sqlquery.c_str());
2724+ Field *fields2 = result->Fetch();
2725+ std::string pgmlvl = fields2[0].GetCppString();
2726+ delete result;
2727+ std::string guildinfo = "";
2728+ if (pguildid != 0)
2729+ {
2730+ Guild* guild = objmgr.GetGuildById(pguildid);
2731+ if (guild)
2732+ {
2733+ guildinfo = " " + guild->GetRankName(pguildrank) + " Of " + guild->GetName();
2734+ }
2735+ }
2736+ else guildinfo = " None";
2737+ ChrRacesEntry const* prace = sChrRacesStore.LookupEntry(praceid);
2738+ ChrClassesEntry const* pclass = sChrClassesStore.LookupEntry(pclassid);
2739+
2740+ if (atoi(plevel.c_str()) < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
2741+ plevel += " (" + pxp + "/" + pmaxxp + ")";
2742+ unsigned int gold = money / 10000;
2743+ unsigned int silv = (money % 10000) / 100;
2744+ unsigned int cop = (money % 10000) % 100;
2745+ char tempgold [100];
2746+ sprintf(tempgold, "\x2\x3\x30\x37%ug \x3\x31\x34%us \x3\x30\x35%uc\xF", gold, silv, cop);
2747+ if (ponline == "\x3\x30\x33Online")
2748+ {
2749+ Player * plr = ObjectAccessor::Instance().FindPlayerByName(pname.c_str());
2750+ if (plr)
2751+ {
2752+ AreaTableEntry const* area = GetAreaEntryByAreaID(plr->GetAreaId());
2753+ ponline += " in " + (std::string) area->area_name[sWorld.GetDefaultDbcLocale()];
2754+ if (area->zone != 0)
2755+ {
2756+ AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone);
2757+ ponline += " (" + (std::string)zone->area_name[sWorld.GetDefaultDbcLocale()] + ")";
2758+ }
2759+ }
2760+ }
2761+ std::string pinfo = "\x2 About Player:\x3\x31\x30 " +pname+ "\xF |\x2 GM Level:\x3\x31\x30 " +pgmlvl+ "\xF |\x2 AcctID:\x3\x31\x30 " +pacct+ "\xF |\x2 CharID:\x3\x31\x30 " +pguid+ " \xF |\x2 Played Time:\x2\x3\x31\x30 " +totaltim.c_str()+" \xF |\x2 Latency:\x2\x3\x31\x30 "+templatency;
2762+ std::string pinfo2 = "\x2 Race:\x2\x3\x31\x30 " + (std::string)prace->name[sWorld.GetDefaultDbcLocale()] + "\xF |\x2 Class:\x2\x3\x31\x30 " + (std::string)pclass->name[sWorld.GetDefaultDbcLocale()] + "\xF |\x2 Level:\x2\x3\x31\x30 " + plevel + "\xF |\x2 Money:\x2 " + tempgold + "\xF |\x2 Guild Info:\x2\x3\x31\x30 "+guildinfo+"\xF |\x2 Status:\x2 " + ponline;
2763+ // pinfo3 = " :" + " \x2Honor Kills:\x2\x3\x31\x30 " + hk;
2764+ Send_IRCA(ChanOrPM(CD),pinfo , true, CD->TYPE);
2765+ Send_IRCA(ChanOrPM(CD),pinfo2 , true, CD->TYPE);
2766+ // Send_IRCA(ChanOrPM(CD),pinfo3 , true, CD->TYPE);
2767+ }
2768+ else
2769+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Character ID. (GUID)" ,true, "ERROR");
2770+ }
2771+ else
2772+ {
2773+ QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account, name FROM characters WHERE name LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
2774+ if(result)
2775+ {
2776+ Field *fields = result->Fetch();
2777+ std::string items = "\x2 Character Search Results:\x3\x31\x30 ";
2778+ for (uint64 i=0; i < result->GetRowCount(); i++)
2779+ {
2780+ std::string guid = fields[0].GetCppString();
2781+ std::string account = fields[1].GetCppString();
2782+ std::string name = fields[2].GetCppString();
2783+ MakeUpper(name);
2784+ items.append(name+"(Account:"+account+" - GUID:"+guid+")\xF | \x3\x31\x30\x2");
2785+ result->NextRow();
2786+ }
2787+ delete result;
2788+ Send_IRCA(ChanOrPM(CD), items, true, CD->TYPE);
2789+ }
2790+ else
2791+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Character. I Cant Find Any Characters With Those Search Terms." ,true, "ERROR");
2792+ }
2793+ }
2794+ if(_PARAMS[0] == "creature")
2795+ {
2796+ std::string creature = _PARAMS[1];
2797+ if(atoi(creature.c_str()) > 0)
2798+ {
2799+ WorldDatabase.escape_string(_PARAMS[1]);
2800+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, modelid_A, name, (minlevel*maxlevel/2) as level, faction_A, armor, (SELECT count(*) FROM creature WHERE id = '%s') as spawns FROM creature_template WHERE entry = '%s';", _PARAMS[1].c_str(), _PARAMS[1].c_str());
2801+ if(result)
2802+ {
2803+ Field *fields = result->Fetch();
2804+
2805+ uint32 entry = fields[0].GetUInt32();
2806+ uint32 modelid = fields[1].GetUInt32();
2807+ std::string name = fields[2].GetCppString();
2808+ uint32 level = fields[3].GetUInt32();
2809+ uint32 faction = fields[4].GetUInt32();
2810+ uint32 armor = fields[5].GetUInt32();
2811+ uint32 spawns = fields[6].GetUInt32();
2812+ delete result;
2813+
2814+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2Name:\x3\x31\x30 %s \xF|\x2 CreatureID:\x3\x31\x30 %d \xF|\x2 DisplayID:\x3\x31\x30 %d \xF|\x2 Spawns:\x3\x31\x30 %d", name.c_str(), entry, modelid, spawns), true, CD->TYPE);
2815+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2Level:\x3\x31\x30 %d \xF|\x2 Faction:\x3\x31\x30 %d \xF|\x2 Armor:\x3\x31\x30 %d", level, faction, armor), true, CD->TYPE);
2816+ }
2817+ else
2818+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Creature ID." ,true, "ERROR");
2819+ }
2820+ else
2821+ {
2822+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, name FROM creature_template WHERE name LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
2823+ if(result)
2824+ {
2825+ Field *fields = result->Fetch();
2826+ std::string items = "\002Creature Search Results:\x3\x31\x30 ";
2827+ //Send_IRCA(ChanOrPM(CD), "", true, CD->TYPE);
2828+ for (uint64 i=0; i < result->GetRowCount(); i++)
2829+ {
2830+ std::string CreatureID = fields[0].GetCppString();
2831+ std::string Name = fields[1].GetCppString();
2832+ items.append(Name+"("+CreatureID+")\xF | \x3\x31\x30\x2");
2833+ result->NextRow();
2834+ }
2835+ delete result;
2836+ Send_IRCA(ChanOrPM(CD), items, true, CD->TYPE);
2837+ }
2838+ else
2839+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Creature. I Cant Find Any Creatures With Those Search Terms." ,true, "ERROR");
2840+ }
2841+ }
2842+ if(_PARAMS[0] == "faction")
2843+ {
2844+ std::string faction = _PARAMS[1];
2845+ if(atoi(faction.c_str()) > 0)
2846+ {
2847+ FactionEntry const *factionEntry = sFactionStore.LookupEntry(atoi(faction.c_str()));
2848+ if(factionEntry)
2849+ {
2850+ std::string name = factionEntry->name[sWorld.GetDefaultDbcLocale()];
2851+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2 Faction:\x3\x31\x30 %s \xF|\x2 FactionID:\x3\x31\x30 %s",name.c_str(), faction.c_str()), true, CD->TYPE);
2852+ }
2853+ else
2854+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown FactionID." ,true, "ERROR");
2855+
2856+ }
2857+ else
2858+ {
2859+ uint32 counter = 0;
2860+ std::string factions = "\002Faction Search Results:\x3\x31\x30 ";
2861+ for (uint32 id = 0; id < sFactionStore.GetNumRows(); id++)
2862+ {
2863+ FactionEntry const *factionEntry = sFactionStore.LookupEntry(id);
2864+ if(factionEntry)
2865+ {
2866+ MakeLower( _PARAMS[1] );
2867+ std::string name = factionEntry->name[sWorld.GetDefaultDbcLocale()];
2868+ MakeLower( name );
2869+ if (name.find(_PARAMS[1]) != std::string::npos && counter < 10)
2870+ {
2871+ char factionid[100];
2872+ sprintf(factionid, "%d", id);
2873+ factions.append(name+"("+factionid+")\xF | \x3\x31\x30\x2");
2874+ ++counter;
2875+ }
2876+ }
2877+ }
2878+ if(counter == 0)
2879+ factions.append("No Factions Found.");
2880+ Send_IRCA(ChanOrPM(CD), factions, true, CD->TYPE);
2881+ }
2882+ }
2883+ if(_PARAMS[0] == "go")
2884+ {
2885+ std::string gobject = _PARAMS[1];
2886+ if(atoi(gobject.c_str()) > 0)
2887+ {
2888+ WorldDatabase.escape_string(_PARAMS[1]);
2889+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, type, displayId, name, faction, (SELECT count(*) FROM gameobject WHERE id = '%s') as spawns FROM gameobject_template WHERE entry = '%s';", _PARAMS[1].c_str(), _PARAMS[1].c_str());
2890+ if(result)
2891+ {
2892+ Field *fields = result->Fetch();
2893+
2894+ uint32 entry = fields[0].GetUInt32();
2895+ uint32 type = fields[1].GetUInt32();
2896+ uint32 modelid = fields[2].GetUInt32();
2897+ std::string name = fields[3].GetCppString();
2898+ uint32 faction = fields[4].GetUInt32();
2899+ uint32 spawns = fields[5].GetUInt32();
2900+ delete result;
2901+
2902+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2GO Name:\x3\x31\x30 %s \xF|\x2 GameobjectID:\x3\x31\x30 %d \xF|\x2 DisplayID:\x3\x31\x30 %d \xF|\x2 Spawns:\x3\x31\x30 %d", name.c_str(), entry, modelid, spawns), true, CD->TYPE);
2903+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2Type:\x3\x31\x30 %d \xF|\x2 Faction:\x3\x31\x30 %d", type, faction), true, CD->TYPE);
2904+ }
2905+ else
2906+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Creature ID." ,true, "ERROR");
2907+ }
2908+ else
2909+ {
2910+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, name FROM gameobject_template WHERE name LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
2911+ if(result)
2912+ {
2913+ Field *fields = result->Fetch();
2914+ std::string gos = "\002Gameobject Search Results:\x3\x31\x30 ";
2915+ for (uint64 i=0; i < result->GetRowCount(); i++)
2916+ {
2917+ std::string GOID = fields[0].GetCppString();
2918+ std::string GoName = fields[1].GetCppString();
2919+ gos.append(GoName+"("+GOID+")\xF | \x3\x31\x30\x2");
2920+ result->NextRow();
2921+ }
2922+ delete result;
2923+ Send_IRCA(ChanOrPM(CD), gos, true, CD->TYPE);
2924+ }
2925+ else
2926+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Game Object. I Cant Find Any Game Object's With Those Search Terms." ,true, "ERROR");
2927+ }
2928+ }
2929+ if(_PARAMS[0] == "item")
2930+ {
2931+ std::string item = _PARAMS[1];
2932+ if(atoi(item.c_str()) > 0)
2933+ {
2934+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, name, displayid, (SELECT count(*) FROM creature_loot_template WHERE item = '%s') as loot FROM `item_template` WHERE entry = %s", _PARAMS[1].c_str(), _PARAMS[1].c_str());
2935+ if(result)
2936+ {
2937+ Field *fields = result->Fetch();
2938+ QueryResult *result2 = CharacterDatabase.PQuery("SELECT count(*) FROM `character_inventory` WHERE item_template = %s", _PARAMS[1].c_str());
2939+ Field *fields2 = result2->Fetch();
2940+ uint32 charcnt = fields2[0].GetUInt32();
2941+ delete result2;
2942+
2943+ uint32 ItemID = fields[0].GetUInt32();
2944+ std::string ItmName = fields[1].GetCppString();
2945+ uint32 DisplayID = fields[2].GetUInt32();
2946+ uint32 loots = 0;
2947+ loots = fields[3].GetUInt32();
2948+ delete result;
2949+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2Item:\x3\x31\x30 %s \xF|\x2 ItemID:\x3\x31\x30 %d \xF|\x2 DisplayID:\x3\x31\x30 %d \xF|\x2 Owned By:\x3\x31\x30 %d players \xF|\x2 Dropped By:\x3\x31\x30 %d creatures", ItmName.c_str(), ItemID, DisplayID, charcnt, loots), true, CD->TYPE);
2950+ }
2951+ else
2952+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown ItemID." ,true, "ERROR");
2953+ }
2954+ else
2955+ {
2956+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, name FROM `item_template` WHERE name LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
2957+ if(result)
2958+ {
2959+ Field *fields = result->Fetch();
2960+ std::string items = "\002Item Search Results:\x3\x31\x30 ";
2961+ for (uint64 i=0; i < result->GetRowCount(); i++)
2962+ {
2963+ std::string ItemID = fields[0].GetCppString();
2964+ std::string ItemName = fields[1].GetCppString();
2965+ items.append(ItemName+"("+ItemID+")\xF | \x3\x31\x30\x2");
2966+ result->NextRow();
2967+ }
2968+ delete result;
2969+ Send_IRCA(ChanOrPM(CD), items, true, CD->TYPE);
2970+ }
2971+ else
2972+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Item. I Cant Find Any Items With Those Search Terms." ,true, "ERROR");
2973+ }
2974+ }
2975+ if(_PARAMS[0] == "quest")
2976+ {
2977+ std::string quest = _PARAMS[1];
2978+ if(atoi(quest.c_str()) > 0)
2979+ {
2980+ WorldDatabase.escape_string(_PARAMS[1]);
2981+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, Title FROM quest_template WHERE entry = '%s';", _PARAMS[1].c_str(), _PARAMS[1].c_str());
2982+ if(result)
2983+ {
2984+ QueryResult *result2 = CharacterDatabase.PQuery("SELECT count(*) FROM character_queststatus WHERE quest = '%s' AND status = '1';", _PARAMS[1].c_str());
2985+ Field *fields2 = result2->Fetch();
2986+ uint32 status = fields2[0].GetUInt32();
2987+ delete result2;
2988+
2989+ Field *fields = result->Fetch();
2990+ uint32 entry = fields[0].GetUInt32();
2991+ std::string name = fields[1].GetCppString();
2992+ delete result;
2993+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2Quest Name:\x3\x31\x30 %s \xF|\x2 QuestID:\x3\x31\x30 %d \xF|\x2 Completed:\x3\x31\x30 %d times", name.c_str(), entry, status), true, CD->TYPE);
2994+ }
2995+ else
2996+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Quest ID." ,true, "ERROR");
2997+ }
2998+ else
2999+ {
3000+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, Title FROM quest_template WHERE Title LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
3001+ if(result)
3002+ {
3003+ Field *fields = result->Fetch();
3004+ std::string quests = "\002Quest Search Results:\x3\x31\x30 ";
3005+ //Send_IRCA(ChanOrPM(CD), "", true, CD->TYPE);
3006+ for (uint64 i=0; i < result->GetRowCount(); i++)
3007+ {
3008+ std::string QuestID = fields[0].GetCppString();
3009+ std::string QuestName = fields[1].GetCppString();
3010+ quests.append(QuestName+"("+QuestID+")\xF | \x3\x31\x30\x2");
3011+ result->NextRow();
3012+ }
3013+ delete result;
3014+ Send_IRCA(ChanOrPM(CD), quests, true, CD->TYPE);
3015+ }
3016+ else
3017+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Quest. I Cant Find Any Quest's With Those Search Terms." ,true, "ERROR");
3018+ }
3019+ }
3020+ if(_PARAMS[0] == "skill")
3021+ {
3022+ std::string skill = _PARAMS[1];
3023+ if(atoi(skill.c_str()) > 0)
3024+ {
3025+ SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(atoi(skill.c_str()));
3026+ if(skillInfo)
3027+ {
3028+ std::string name = skillInfo->name[sWorld.GetDefaultDbcLocale()];
3029+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2Skill:\x3\x31\x30 %s \xF|\x2 SkillID:\x3\x31\x30 %s",name.c_str(), skill.c_str()), true, CD->TYPE);
3030+ }
3031+ else
3032+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown SkillID." ,true, "ERROR");
3033+
3034+ }
3035+ else
3036+ {
3037+ uint32 counter = 0;
3038+ std::string skills = "\002Skill Search Results:\x3\x31\x30 ";
3039+ for (uint32 id = 0; id < sSkillLineStore.GetNumRows(); id++)
3040+ {
3041+ SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(id);
3042+ if(skillInfo)
3043+ {
3044+ MakeLower( _PARAMS[1] );
3045+ std::string name = skillInfo->name[sWorld.GetDefaultDbcLocale()];
3046+ MakeLower( name );
3047+ if (name.find(_PARAMS[1]) != std::string::npos && counter < 10)
3048+ {
3049+ char skillid[100];
3050+ sprintf(skillid, "%d", id);
3051+ skills.append(name+"("+skillid+")\xF | \x3\x31\x30\x2");
3052+ ++counter;
3053+ }
3054+ }
3055+ }
3056+ if(counter == 0)
3057+ skills.append("No Skills Found.");
3058+ Send_IRCA(ChanOrPM(CD), skills, true, CD->TYPE);
3059+ }
3060+ }
3061+ if(_PARAMS[0] == "spell")
3062+ {
3063+ std::string spell = _PARAMS[1];
3064+ if(atoi(spell.c_str()) > 0)
3065+ {
3066+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(atoi(spell.c_str()));
3067+ if(spellInfo)
3068+ {
3069+ std::string name = spellInfo->SpellName[sWorld.GetDefaultDbcLocale()];
3070+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2Spell:\x3\x31\x30 %s \xF|\x2 SpellID:\x3\x31\x30 %s",name.c_str(), spell.c_str()), true, CD->TYPE);
3071+ }
3072+ else
3073+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown SpellID." ,true, "ERROR");
3074+
3075+ }
3076+ else
3077+ {
3078+ uint32 counter = 0;
3079+ std::string spells = "\002Spell Search Results:\x3\x31\x30 ";
3080+ for (uint32 id = 0; id < sSpellStore.GetNumRows(); id++)
3081+ {
3082+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(id);
3083+ if(spellInfo)
3084+ {
3085+ MakeLower( _PARAMS[1] );
3086+ std::string name = spellInfo->SpellName[sWorld.GetDefaultDbcLocale()];
3087+ MakeLower( name );
3088+ if (name.find(_PARAMS[1]) != std::string::npos && counter < 10)
3089+ {
3090+ char itemid[100];
3091+ sprintf(itemid, "%d", id);
3092+ spells.append(name+"("+itemid+")\xF | \x3\x31\x30\x2");
3093+ ++counter;
3094+ }
3095+ }
3096+ }
3097+ if(counter == 0)
3098+ spells.append("No Spells Found.");
3099+ Send_IRCA(ChanOrPM(CD), spells, true, CD->TYPE);
3100+ }
3101+ }
3102+ if(_PARAMS[0] == "tele")
3103+ {
3104+ std::string tele = _PARAMS[1];
3105+ if(atoi(tele.c_str()) > 0)
3106+ {
3107+ QueryResult *result = WorldDatabase.PQuery("SELECT * FROM `game_tele` WHERE id = %s", _PARAMS[1].c_str());
3108+ if(result)
3109+ {
3110+ Field *fields = result->Fetch();
3111+
3112+ uint32 teleid = fields[0].GetUInt32();
3113+ uint32 pos_x = fields[1].GetUInt32();
3114+ uint32 pos_y = fields[2].GetUInt32();
3115+ uint32 pos_z = fields[3].GetUInt32();
3116+ uint32 oriet = fields[4].GetUInt32();
3117+ uint32 map = fields[5].GetUInt32();
3118+ std::string telname = fields[6].GetCppString();
3119+ delete result;
3120+
3121+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2Tele Name:\x3\x31\x30 %s \xF|\x2 TeleID:\x3\x31\x30 %d \xF|\x2 Coordinates:\x3\x31\x30 [X: %d, Y: %d, Z: %d, MAP: %d, Orientation: %d]", telname.c_str(), teleid, pos_x, pos_y, pos_z, map, oriet), true, CD->TYPE);
3122+ }
3123+ else
3124+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Teleport Location ID." ,true, "ERROR");
3125+ }
3126+ else
3127+ {
3128+ QueryResult *result = WorldDatabase.PQuery("SELECT id, name FROM `game_tele` WHERE name LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
3129+ if(result)
3130+ {
3131+ Field *fields = result->Fetch();
3132+ std::string teles = "\002Tele Location Search Results:\x3\x31\x30 ";
3133+ for (uint64 i=0; i < result->GetRowCount(); i++)
3134+ {
3135+ std::string TeleID = fields[0].GetCppString();
3136+ std::string TeleName = fields[1].GetCppString();
3137+ teles.append(TeleName+"("+TeleID+")\xF | \x3\x31\x30\x2");
3138+ result->NextRow();
3139+ }
3140+ Send_IRCA(ChanOrPM(CD), teles, true, CD->TYPE);
3141+ delete result;
3142+ }
3143+ else
3144+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Item. I Cant Find Any Items With Those Search Terms." ,true, "ERROR");
3145+ }
3146+ }
3147+}
3148+
3149+void IRCCmd::Level_Player(_CDATA *CD)
3150+{
3151+ std::string* _PARAMS = getArray(CD->PARAMS, CD->PCOUNT);
3152+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
3153+ {
3154+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
3155+ return;
3156+ }
3157+ std::string player = _PARAMS[0];
3158+ normalizePlayerName(player);
3159+ uint64 guid = objmgr.GetPlayerGUIDByName(player.c_str());
3160+ std::string s_newlevel = _PARAMS[1];
3161+ uint8 i_newlvl = atoi(s_newlevel.c_str());
3162+ if(!guid)
3163+ {
3164+ Send_IRCA(CD->USER, "\0034[ERROR] : Player Not Found!", true, "ERROR");
3165+ return;
3166+ } else if ( i_newlvl < 1 || i_newlvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) )
3167+ {
3168+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Level Must Be Between 1 And %i!",sConfig.GetIntDefault("MaxPlayerLevel", 70)), true, "ERROR");
3169+ return;
3170+ } else
3171+ {
3172+ Player *chr = objmgr.GetPlayer(guid);
3173+ int32 i_oldlvl = chr ? chr->getLevel() : Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,guid);
3174+ if(chr)
3175+ {
3176+ chr->GiveLevel(i_newlvl);
3177+ chr->InitTalentForLevel();
3178+ chr->SetUInt32Value(PLAYER_XP,0);
3179+ WorldPacket data;
3180+ ChatHandler CH(chr->GetSession());
3181+ if(i_oldlvl == i_newlvl)
3182+ CH.FillSystemMessageData(&data, "Your level progress has been reset.");
3183+ else
3184+ if(i_oldlvl < i_newlvl)
3185+ CH.FillSystemMessageData(&data, fmtstring("You have been leveled up (%i)",i_newlvl-i_oldlvl));
3186+ else
3187+ if(i_oldlvl > i_newlvl)
3188+ CH.FillSystemMessageData(&data, fmtstring("You have been leveled down (%i)",i_newlvl-i_oldlvl));
3189+ chr->GetSession()->SendPacket( &data );
3190+ }
3191+ else
3192+ {
3193+ Tokens values;
3194+ Player::LoadValuesArrayFromDB(values,guid);
3195+ Player::SetUInt32ValueInArray(values,UNIT_FIELD_LEVEL,i_newlvl);
3196+ Player::SetUInt32ValueInArray(values,PLAYER_XP,0);
3197+ Player::SaveValuesArrayInDB(values,guid);
3198+ }
3199+ }
3200+ Send_IRCA(ChanOrPM(CD), "\00313[" + _PARAMS[0]+ "] : Has Been Leveled To " + _PARAMS[1] + ". By: "+CD->USER+".", true, CD->TYPE);
3201+}
3202+
3203+void IRCCmd::Money_Player(_CDATA *CD)
3204+{
3205+ std::string* _PARAMS = getArray(CD->PARAMS, 2);
3206+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
3207+ {
3208+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
3209+ return;
3210+ }
3211+ std::string player = _PARAMS[0];
3212+ normalizePlayerName(player);
3213+ uint64 guid = objmgr.GetPlayerGUIDByName(player.c_str());
3214+ Player *chr = objmgr.GetPlayer(guid);
3215+
3216+ std::string s_money = _PARAMS[1];
3217+ int32 money = atoi(s_money.c_str());
3218+ unsigned int gold = money / 10000;
3219+ unsigned int silv = (money % 10000) / 100;
3220+ unsigned int cop = (money % 10000) % 100;
3221+ char tempgold [100];
3222+ sprintf(tempgold, "\x2\x3\x30\x37%ug \x3\x31\x34%us \x3\x30\x35%uc\xF", gold, silv, cop);
3223+ if(!guid)
3224+ {
3225+ Send_IRCA(CD->USER, "\0034[ERROR] : Player Not Found!", true, "ERROR");
3226+ return;
3227+ }
3228+ else
3229+ {
3230+ Player *chr = objmgr.GetPlayer(guid);
3231+ uint32 moneyuser = 0;
3232+ if(chr)
3233+ moneyuser = chr->GetMoney();
3234+ else {
3235+ CharacterDatabase.escape_string(player);
3236+ std::string sqlquery = "SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(data, ' ' , 1462), ' ' , -1) AS `gold` FROM `characters` WHERE `name` = '"+player+"';";
3237+ QueryResult *result = CharacterDatabase.Query(sqlquery.c_str());
3238+ Field *fields = result->Fetch();
3239+ moneyuser = fields[0].GetInt32();
3240+ delete result;
3241+ }
3242+ int32 addmoney = money;
3243+ int32 newmoney = moneyuser + addmoney;
3244+ char s_newmoney[255];
3245+ sprintf(s_newmoney,"%d",newmoney);
3246+ if(addmoney < 0)
3247+ {
3248+ sLog.outDetail("USER1: %i, ADD: %i, DIF: %i\\n", moneyuser, addmoney, newmoney);
3249+ if(newmoney <= 0 )
3250+ {
3251+ Send_IRCA(ChanOrPM(CD), "\00313["+player+"] : Has Had All Money Taken By: "+CD->USER.c_str()+".", true, CD->TYPE);
3252+ if(chr)
3253+ {
3254+ chr->SetMoney(0);
3255+ Send_Player(chr, MakeMsg("You Have Been Liquidated By: %s. Total Money Is Now 0.", CD->USER.c_str()));
3256+ }
3257+ else
3258+ CharacterDatabase.PExecute("UPDATE `characters` SET data=concat(substring_index(data,' ',1462-1),' ','%u',' ', right(data,length(data)-length(substring_index(data,' ',1462))-1) ) where guid='%u'",newmoney, guid );
3259+ }
3260+ else
3261+ {
3262+ Send_IRCA(ChanOrPM(CD), "\00313["+player+"] : Has Had ("+s_money+"\00313) Taken From Them By: "+CD->USER.c_str()+".", true, CD->TYPE);
3263+ if(chr)
3264+ {
3265+ chr->SetMoney( newmoney );
3266+ Send_Player(chr, MakeMsg("You Have Had %s Copper Taken From You By: %s.", _PARAMS[1].c_str(), CD->USER.c_str()));
3267+ }
3268+ else
3269+ CharacterDatabase.PExecute("UPDATE `characters` SET data=concat(substring_index(data,' ',1462-1),' ','%u',' ', right(data,length(data)-length(substring_index(data,' ',1462))-1) ) where guid='%u'",newmoney, guid );
3270+ }
3271+ }
3272+ else
3273+ {
3274+ Send_IRCA(ChanOrPM(CD), "\00313["+player+"] : Has Been Given ("+tempgold+"\00313) From: "+CD->USER.c_str()+".", true, CD->TYPE);
3275+ if(chr)
3276+ {
3277+ chr->ModifyMoney( addmoney );
3278+ Send_Player(chr, MakeMsg("You Have Been Given %s Copper. From: %s.", _PARAMS[1].c_str(), CD->USER.c_str()));
3279+ }
3280+ else
3281+ CharacterDatabase.PExecute("UPDATE `characters` SET data=concat(substring_index(data,' ',1462-1),' ','%u',' ', right(data,length(data)-length(substring_index(data,' ',1462))-1) ) where guid='%u'",newmoney, guid );
3282+ }
3283+ }
3284+}
3285+
3286+void IRCCmd::Mute_Player(_CDATA *CD)
3287+{
3288+ std::string* _PARAMS = getArray(CD->PARAMS, 3);
3289+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
3290+ {
3291+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
3292+ return;
3293+ }
3294+ normalizePlayerName(_PARAMS[0]);
3295+ uint64 guid = objmgr.GetPlayerGUIDByName(_PARAMS[0]);
3296+ if(guid)
3297+ {
3298+ if(_PARAMS[1] == "release")
3299+ {
3300+ Player* plr = objmgr.GetPlayer(guid);
3301+ uint32 account_id = 0;
3302+ account_id = objmgr.GetPlayerAccountIdByGUID(guid);
3303+ loginDatabase.PExecute("UPDATE `account` SET `mutetime` = '0' WHERE `id` = '%u'", account_id );
3304+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Been UnMuted By: "+CD->USER+"." , true, CD->TYPE);
3305+ if(plr)
3306+ {
3307+ plr->GetSession()->m_muteTime = 0;
3308+ Send_Player(plr, MakeMsg("You Have Been UnMuted By: %s.", CD->USER.c_str()));
3309+ }
3310+ }
3311+ else
3312+ {
3313+ if(_PARAMS[2] == "")
3314+ _PARAMS[2] = "No Reason Given";
3315+ Player* plr = objmgr.GetPlayer(guid);
3316+ time_t mutetime = time(NULL) + atoi(_PARAMS[1].c_str())*60;
3317+ uint32 account_id = 0;
3318+ account_id = objmgr.GetPlayerAccountIdByGUID(guid);
3319+ if(plr) plr->GetSession()->m_muteTime = mutetime;
3320+ loginDatabase.PExecute("UPDATE `account` SET `mutetime` = " UI64FMTD " WHERE `id` = '%u'",uint64(mutetime), account_id );
3321+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Been Muted By: "+CD->USER+". For: "+_PARAMS[1]+" Minutes. Reason: "+_PARAMS[2] , true, CD->TYPE);
3322+ if(plr) Send_Player(plr, MakeMsg("You Have Been Muted By: %s. For: %s Minutes. Reason: %s", CD->USER.c_str(), _PARAMS[1].c_str(), _PARAMS[2].c_str()));
3323+ }
3324+ }
3325+ else
3326+ Send_IRCA(CD->USER, "\0034[ERROR] : Player Does Not Exist!", true, "ERROR");
3327+}
3328+
3329+void IRCCmd::Online_Players(_CDATA *CD)
3330+{
3331+ sIRC.Script_Lock[MCS_Players_Online] = true;
3332+ ACE_Based::Thread script(*new mcs_OnlinePlayers(CD));
3333+}
3334+
3335+void IRCCmd::PM_Player(_CDATA *CD)
3336+{
3337+ std::string* _PARAMS = getArray(CD->PARAMS, 2);
3338+ if (Player* plr = GetPlayer(_PARAMS[0]))
3339+ {
3340+ if(plr->isAcceptWhispers())
3341+ {
3342+ std::string sMsg = MakeMsg("|cffFE87FD[<IRC>%s] (use .ircpm NAME to reply) Whispers: %s|r", CD->USER.c_str(), _PARAMS[1].c_str());
3343+ WorldPacket data(SMSG_MESSAGECHAT, 200);
3344+ data << (uint8)CHAT_MSG_SYSTEM;
3345+ data << (uint32)LANG_UNIVERSAL;
3346+ data << (uint64)plr->GetGUID();
3347+ data << (uint32)0;
3348+ data << (uint64)plr->GetGUID();
3349+ data << (uint32)(sMsg.length()+1);
3350+ data << sMsg;
3351+ data << (uint8)0;
3352+ plr->GetSession()->SendPacket(&data);
3353+// plr->PlaySound(3081, true);
3354+ Send_IRCA(ChanOrPM(CD), "\00313To ["+_PARAMS[0]+"] : "+_PARAMS[1]+".", true, CD->TYPE);
3355+ }
3356+ else
3357+ Send_IRCA(CD->USER, "\0034[ERROR] : Is Not Accepting Private Messages!", true, "ERROR");
3358+ }
3359+ else
3360+ Send_IRCA(CD->USER, "\0034[ERROR] : Player not online!", true, "ERROR");
3361+}
3362+
3363+void IRCCmd::Revive_Player(_CDATA *CD)
3364+{
3365+ std::string* _PARAMS = getArray(CD->PARAMS, CD->PCOUNT);
3366+ if (Player* plr = GetPlayer(_PARAMS[0]))
3367+ {
3368+ if(plr->isDead())
3369+ {
3370+ plr->ResurrectPlayer(0.5f);
3371+ plr->SpawnCorpseBones();
3372+ plr->SaveToDB();
3373+ sIRC.Send_IRC_Channel(ChanOrPM(CD), " \00313["+_PARAMS[0]+"] : Has Been Revived By: " + CD->USER, true, CD->TYPE);
3374+ Send_Player(plr, MakeMsg("You Have Been Revived By: %s.", CD->USER.c_str()));
3375+ }
3376+ else
3377+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Not Dead!", true, "ERROR");
3378+ }
3379+ else
3380+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Not Online!", true, "ERROR");
3381+}
3382+
3383+void IRCCmd::Saveall_Player(_CDATA *CD)
3384+{
3385+ ObjectAccessor::Instance().SaveAllPlayers();
3386+ Send_IRCA(ChanOrPM(CD), "\00313["+CD->USER+"] : Has Saved All Players!", true, CD->TYPE);
3387+}
3388+
3389+void IRCCmd::Shutdown_Mangos(_CDATA *CD)
3390+{
3391+ std::string* _PARAMS = getArray(CD->PARAMS, 1);
3392+ if(_PARAMS[0] == "cancel")
3393+ {
3394+ sWorld.ShutdownCancel();
3395+ Send_IRCA(ChanOrPM(CD), "\0034Server Shutdown Has Been Cancelled.", true, CD->TYPE);
3396+ }
3397+
3398+ int32 i_time = atoi(_PARAMS[0].c_str());
3399+ if (i_time <= 0 && _PARAMS[0]!="0")
3400+ {
3401+ Send_IRCA(ChanOrPM(CD), "\00313["+CD->USER+"] : Please Enter A Number! And No Negative Numbers! "+_PARAMS[0]+" Seconds!?", true, CD->TYPE);
3402+ return;
3403+ }
3404+ if (i_time > 1) Send_IRCA(ChanOrPM(CD), "\00313["+CD->USER+"] : Has Requested Server To Be Shut Down In "+_PARAMS[0]+" Seconds!", true, CD->TYPE);
3405+ sWorld.ShutdownServ(i_time, 0, 0);
3406+ Delay(i_time*1000);
3407+ Send_IRCA(ChanOrPM(CD), "\0034Server Will Now Shut Down.. Good Bye!", true, CD->TYPE);
3408+ sIRC.Active = false;
3409+ sIRC.ResetIRC();
3410+}
3411+
3412+void IRCCmd::Spell_Player(_CDATA *CD)
3413+{
3414+ std::string* _PARAMS = getArray(CD->PARAMS, 3);
3415+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
3416+ {
3417+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
3418+ return;
3419+ }
3420+ uint32 spell = atoi(_PARAMS[2].c_str());
3421+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell);
3422+ if (Player* plr = GetPlayer(_PARAMS[0]))
3423+ {
3424+ if(spellInfo)
3425+ {
3426+ std::string name = spellInfo->SpellName[sWorld.GetDefaultDbcLocale()];
3427+ if(_PARAMS[1] == "cast")
3428+ {
3429+ plr->CastSpell(plr, spell, true);
3430+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Had Spell "+name+" Casted On Them.", true, CD->TYPE);
3431+ }
3432+ if(_PARAMS[1] == "learn")
3433+ {
3434+ plr->learnSpell(spell, true);
3435+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Learned Spell "+name+".", true, CD->TYPE);
3436+ }
3437+ if(_PARAMS[1] == "unlearn")
3438+ {
3439+ plr->removeSpell(spell, true);
3440+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Unlearned Spell "+name+".", true, CD->TYPE);
3441+ }
3442+ }
3443+ else
3444+ Send_IRCA(CD->USER, "\0034[ERROR] : Incorrect Spell ID!", true, "ERROR");
3445+ }
3446+ else
3447+ Send_IRCA(CD->USER, "\0034[ERROR] : Player Not Online!", true, "ERROR");
3448+}
3449+
3450+void IRCCmd::Sysmsg_Server(_CDATA *CD)
3451+{
3452+ std::string* _PARAMS = getArray(CD->PARAMS, CD->PCOUNT);
3453+ std::string ircchan = "#";
3454+ ircchan += sIRC._irc_chan[sIRC.anchn].c_str();
3455+ if(_PARAMS[0] == "a")
3456+ {
3457+ std::string str = _PARAMS[1];
3458+ std::string ancmsg = MakeMsg("\00304,08\037/!\\\037\017\00304 System Alert \00304,08\037/!\\\037\017 %s",_PARAMS[1].c_str());
3459+ sWorld.SendWorldText(3000,str.c_str());
3460+ sIRC.Send_IRC_Channel(ircchan, ancmsg, true);
3461+ }
3462+ else if (_PARAMS[0] == "e")
3463+ {
3464+ std::string str = _PARAMS[1];
3465+ std::string notstr = "[Server Event]: " + _PARAMS[1];
3466+ std::string notmsg = MakeMsg("\00304,08\037/!\\\037\017\00304 Game Event \00304,08\037/!\\\037\017 %s",_PARAMS[1].c_str());
3467+ WorldPacket data(SMSG_NOTIFICATION, (notstr.size()+1));
3468+ data << notstr;
3469+ WorldPacket data2(SMSG_PLAY_SOUND,32);
3470+ data2 << (uint32)1400;
3471+ sWorld.SendGlobalMessage(&data2);
3472+ sWorld.SendGlobalMessage(&data);
3473+ sWorld.SendWorldText(3000,str.c_str());
3474+ sIRC.Send_IRC_Channel(ircchan, notmsg, true);
3475+ }
3476+ else if (_PARAMS[0] == "n")
3477+ {
3478+ std::string str = "Global notify: " + _PARAMS[1];
3479+ std::string notmsg = MakeMsg("\00304,08\037/!\\\037\017\00304 Notification \00304,08\037/!\\\037\017 %s",_PARAMS[1].c_str());
3480+ WorldPacket data(SMSG_NOTIFICATION, (str.size()+1));
3481+ data << str;
3482+ sWorld.SendGlobalMessage(&data);
3483+ sIRC.Send_IRC_Channel(ircchan, notmsg, true);
3484+ }
3485+ else if (_PARAMS[0] == "add")
3486+ {
3487+ WorldDatabase.PExecute( "INSERT INTO IRC_AutoAnnounce (message, addedby) VALUES ('%s', '%s')", _PARAMS[1].c_str(), CD->USER.c_str());
3488+ std::string str = _PARAMS[1];
3489+ std::string ancmsg = MakeMsg("\00304,08\037/!\\\037\017\00304 Information \00304,08\037/!\\\037\017 %s",_PARAMS[1].c_str());
3490+ sWorld.SendWorldText(3000,str.c_str());
3491+ sIRC.Send_IRC_Channel(ircchan, ancmsg, true);
3492+ }
3493+ else if (_PARAMS[0] == "del")
3494+ {
3495+ WorldDatabase.PExecute( "DELETE FROM IRC_AutoAnnounce WHERE id = %s", _PARAMS[1].c_str());
3496+ Send_IRCA(ChanOrPM(CD), MakeMsg("Deleted Automatic Announcement Message ID: %s", _PARAMS[1].c_str()), true, CD->TYPE);
3497+ }
3498+ else if (_PARAMS[0] == "list")
3499+ {
3500+ QueryResult *result = WorldDatabase.PQuery("SELECT * FROM IRC_AutoAnnounce LIMIT 5;", _PARAMS[1].c_str());
3501+ if(result)
3502+ {
3503+ Field *fields = result->Fetch();
3504+ for (uint64 i=0; i < result->GetRowCount(); i++)
3505+ {
3506+ std::string id = fields[0].GetCppString();
3507+ std::string message = fields[1].GetCppString();
3508+ std::string addedby = fields[2].GetCppString();
3509+ Send_IRCA(ChanOrPM(CD), MakeMsg("ID: %s - Added By: %s - Message: %s", id.c_str(), addedby.c_str(), message.c_str()), true, CD->TYPE);
3510+ result->NextRow();
3511+ }
3512+ delete result;
3513+ }
3514+ else
3515+ Send_IRCA(CD->USER, "\0034[ERROR] : No Auto Announce Messages Are In The Database.", true, "ERROR");
3516+ }
3517+ else
3518+ Send_IRCA(CD->USER, "\0034[ERROR] : Please Use (a-Announce)(n-Notify)(e-Event) As Second Parameter!", true, "ERROR");
3519+}
3520+
3521+void IRCCmd::Tele_Player(_CDATA *CD)
3522+{
3523+ std::string* _PARAMS = getArray(CD->PARAMS, 4);
3524+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
3525+ {
3526+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
3527+ return;
3528+ }
3529+ bool DoTeleport = false;
3530+ float pX, pY, pZ, pO = 0;
3531+ uint32 mapid = 0;
3532+ std::string rMsg = " \0034[ERROR] : Teleport Failed!";
3533+ std::string wMsg = "Invalid Tele Location";
3534+ Player* plr = GetPlayer(_PARAMS[0]);
3535+ if(plr)
3536+ {
3537+ if(plr->isInFlight() || plr->isInCombat())
3538+ {
3539+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : %s Is Busy And Cannot Be Teleported! They Could Be In Combat, Or Flying.",_PARAMS[0].c_str()), true, "ERROR");
3540+ return;
3541+ }
3542+ }
3543+ if(_PARAMS[1] == "l" || _PARAMS[1].size() > 2)
3544+ {
3545+ if(_PARAMS[1].size() > 1)
3546+ _PARAMS[2] = _PARAMS[1];
3547+ WorldDatabase.escape_string(_PARAMS[2]);
3548+ QueryResult *result = WorldDatabase.PQuery("SELECT position_x, position_y, position_z, orientation, map FROM game_tele WHERE name='%s';", _PARAMS[2].c_str());
3549+ if (result)
3550+ {
3551+ Field *fields = result->Fetch();
3552+ pX = fields[0].GetFloat();
3553+ pY = fields[1].GetFloat();
3554+ pZ = fields[2].GetFloat();
3555+ pO = fields[3].GetFloat();
3556+ mapid = fields[4].GetUInt16();
3557+ delete result;
3558+ rMsg = MakeMsg(" \00313[%s] : Teleported To %s! By: %s.",
3559+ _PARAMS[0].c_str(),
3560+ _PARAMS[2].c_str(),
3561+ CD->USER.c_str());
3562+ wMsg = MakeMsg("You Have Been Teleported To %s By: %s.",
3563+ _PARAMS[2].c_str(),
3564+ CD->USER.c_str());
3565+ DoTeleport = true;
3566+ }
3567+ else
3568+ {
3569+ WorldDatabase.escape_string(_PARAMS[2]);
3570+ QueryResult *result = WorldDatabase.PQuery("SELECT name FROM game_tele WHERE name LIKE '%%%s%%' LIMIT 7;", _PARAMS[2].c_str());
3571+ if (result)
3572+ {
3573+ std::string telename = "<> ";
3574+ for (uint64 i=0; i < result->GetRowCount(); i++)
3575+ {
3576+ Field *fields = result->Fetch();
3577+ telename.append(fields[0].GetCppString());
3578+ result->NextRow();
3579+ telename.append(" <> ");
3580+ }
3581+ delete result;
3582+ Send_IRCA(CD->USER, "I Cannot Find Location: "+_PARAMS[2]+" . Perhaps One Of These Will Work For You.", true, "ERROR");
3583+ Send_IRCA(CD->USER, telename, true, "ERROR");
3584+ return;
3585+ }
3586+ else
3587+ Send_IRCA(CD->USER, "\0034[ERROR] : Location Not Found! Nothing Even Close Found!", true, "ERROR");
3588+ return;
3589+ }
3590+ }
3591+ else if(_PARAMS[1] == "c")
3592+ {
3593+ std::string* _PARAMSA = getArray(_PARAMS[2], 4);
3594+ pX = atof(_PARAMSA[1].c_str());
3595+ pY = atof(_PARAMSA[2].c_str());
3596+ pZ = atof(_PARAMSA[3].c_str());
3597+ mapid = atoi(_PARAMSA[0].c_str());
3598+ rMsg = MakeMsg(" \00313[%s] : Teleported To Map: %s. Position: X(%s) Y(%s) Z(%s)! By: %s.",
3599+ _PARAMS[0].c_str(),
3600+ _PARAMSA[0].c_str(),
3601+ _PARAMSA[1].c_str(),
3602+ _PARAMSA[2].c_str(),
3603+ _PARAMSA[3].c_str(),
3604+ CD->USER.c_str());
3605+ wMsg = MakeMsg("You Have Been Teleported To Map: %s. Position: X(%s) Y(%s) Z(%s)! By: %s.",
3606+ _PARAMSA[0].c_str(),
3607+ _PARAMSA[1].c_str(),
3608+ _PARAMSA[2].c_str(),
3609+ _PARAMSA[3].c_str(),
3610+ CD->USER.c_str());
3611+ DoTeleport = true;
3612+ }
3613+ else if(_PARAMS[1] == "r")
3614+ {
3615+ if(plr)
3616+ {
3617+ pX = plr->m_recallX;
3618+ pY = plr->m_recallY;
3619+ pZ = plr->m_recallZ;
3620+ pO = plr->m_recallO;
3621+ mapid = plr->m_recallMap;
3622+ rMsg = MakeMsg(" \00313[%s] : Has Been Recalled To Their Previous Location.",
3623+ _PARAMS[0].c_str());
3624+ wMsg = MakeMsg("You Have Been Recalled To Your Previous Location. By: %s",
3625+ CD->USER.c_str());
3626+ DoTeleport = true;
3627+ }
3628+ else
3629+ {
3630+ Send_IRCA(CD->USER, MakeMsg("\00313[%s] : Cannot Be Recalled, They Are Not Online.", _PARAMS[0].c_str()), true, "ERROR");
3631+ return;
3632+ }
3633+
3634+ }
3635+ else if(_PARAMS[1] == "to")
3636+ {
3637+ Player* plr2 = GetPlayer(_PARAMS[2]);
3638+ if(plr2)
3639+ {
3640+ plr2->GetContactPoint(plr, pX, pY, pZ);
3641+ mapid = plr2->GetMapId();
3642+ }
3643+ else
3644+ {
3645+ if(uint64 guid = objmgr.GetPlayerGUIDByName(_PARAMS[2].c_str()))
3646+ {
3647+ bool in_flight;
3648+ Player::LoadPositionFromDB(mapid, pX, pY, pZ, pO, in_flight, guid);
3649+ }
3650+ else
3651+ {
3652+ Send_IRCA(CD->USER, "\0034[ERROR] : Second Player Not Found!", true, "ERROR");
3653+ return;
3654+ }
3655+ }
3656+ rMsg = MakeMsg(" \00313[%s] : Teleported To Player: [%s] By: %s.",
3657+ _PARAMS[0].c_str(),
3658+ _PARAMS[2].c_str(),
3659+ CD->USER.c_str());
3660+ wMsg = MakeMsg("You Are Being Teleported To: %s. By: %s.",
3661+ _PARAMS[2].c_str(),
3662+ CD->USER.c_str());
3663+ DoTeleport = true;
3664+ }
3665+ if(DoTeleport)
3666+ {
3667+ if(MapManager::IsValidMapCoord(mapid, pX ,pY, pZ))
3668+ {
3669+ if(!sIRC.BeenToGMI(pX, pY, pZ, _PARAMS[0], CD->USER))
3670+ {
3671+ //if player is online teleport them in real time, if not set the DB to our coordinates.
3672+ if(plr)
3673+ {
3674+ plr->SaveRecallPosition();
3675+ plr->TeleportTo(mapid, pX, pY, pZ, pO);
3676+ sIRC.Send_IRC_Channel(ChanOrPM(CD), rMsg, true, CD->TYPE);
3677+ Send_Player(plr, wMsg);
3678+ sIRC.Send_WoW_Channel(sIRC._wow_chan[1].c_str(), IRCCmd::MakeMsg("|cffffff21 %s : Teleported To %s. By: %s.|r", _PARAMS[0].c_str(), _PARAMS[2].c_str(), CD->USER.c_str()));
3679+ }
3680+ else
3681+ {
3682+ uint64 guid = objmgr.GetPlayerGUIDByName(_PARAMS[0]);
3683+ Player::SavePositionInDB(mapid,pX,pY,pZ,pO,MapManager::Instance().GetZoneId(mapid,pX,pY,pZ),guid);
3684+ sIRC.Send_IRC_Channel(ChanOrPM(CD), rMsg + " \0034*Offline Tele.* ", true, CD->TYPE);
3685+ }
3686+ }
3687+ }
3688+ else
3689+ Send_IRCA(CD->USER, "\0034[ERROR] : Invalid Location!", true, "ERROR");
3690+ }
3691+ else
3692+ Send_IRCA(CD->USER, "\0034[ERROR] : Invalid Paramaters, Please Try Again [ "+sIRC._cmd_prefx+"help tele ] For More Information. ", true, "ERROR");
3693+}
3694+
3695+void IRCCmd::Top_Player(_CDATA *CD)
3696+{
3697+ std::string* _PARAMS = getArray(CD->PARAMS, 2);
3698+ uint32 limitr = 10;
3699+ if(atoi(_PARAMS[1].c_str()) > 0 && GetLevel(CD->USER) >= sIRC._op_gm_lev)
3700+ limitr = atoi(_PARAMS[1].c_str());
3701+ if(_PARAMS[0] == "accttime")
3702+ {
3703+ QueryResult *result = CharacterDatabase.PQuery("SELECT account, name, (SUM(totaltime)) AS combinetime FROM characters GROUP BY account ORDER BY combinetime DESC LIMIT 0, %d ", limitr);
3704+ if(result)
3705+ {
3706+ Field *fields = result->Fetch();
3707+ std::string tptime = MakeMsg("\x2 Top%d Accounts By Played Time:\x3\x31\x30 ", limitr);
3708+ for (uint64 i=0; i < result->GetRowCount(); i++)
3709+ {
3710+ uint32 account = fields[0].GetUInt32();
3711+ std::string PlName = GetAcctNameFromID(account);
3712+ std::string Time = SecToDay(fields[2].GetCppString());
3713+ uint32 rank = i+1;
3714+ tptime.append(MakeMsg("[%u]%s %s \xF| \x3\x31\x30\x2", rank, PlName.c_str(), Time.c_str()));
3715+ result->NextRow();
3716+ }
3717+ delete result;
3718+ Send_IRCA(ChanOrPM(CD), tptime, true, CD->TYPE);
3719+ }
3720+ else
3721+ Send_IRCA(CD->USER, "\0034[ERROR] : No Accounts Returned." ,true, "ERROR");
3722+ }
3723+ if(_PARAMS[0] == "chartime")
3724+ {
3725+ QueryResult *result = CharacterDatabase.PQuery("SELECT name, totaltime FROM characters ORDER BY totaltime DESC LIMIT 0, %d ", limitr);
3726+ if(result)
3727+ {
3728+ Field *fields = result->Fetch();
3729+ std::string tptime = MakeMsg("\x2 Top%d Characters By Played Time:\x3\x31\x30 ", limitr);
3730+ for (uint64 i=0; i < result->GetRowCount(); i++)
3731+ {
3732+ std::string Name = fields[0].GetCppString();
3733+ std::string Time = SecToDay(fields[1].GetCppString());
3734+ uint32 rank = i+1;
3735+ tptime.append(MakeMsg("[%u]%s %s \xF| \x3\x31\x30\x2", rank, Name.c_str(), Time.c_str()));
3736+ result->NextRow();
3737+ }
3738+ delete result;
3739+ Send_IRCA(ChanOrPM(CD), tptime, true, CD->TYPE);
3740+ }
3741+ else
3742+ Send_IRCA(CD->USER, "\0034[ERROR] : No Characters Returned." ,true, "ERROR");
3743+ }
3744+ if(_PARAMS[0] == "money")
3745+ {
3746+ QueryResult *result = CharacterDatabase.PQuery("SELECT name, CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(data, ' ', 1462), ' ', -1) AS UNSIGNED) AS money FROM characters ORDER BY money DESC LIMIT 0, %d ", limitr);
3747+ if(result)
3748+ {
3749+ Field *fields = result->Fetch();
3750+ std::string tptime = MakeMsg("\x2 Top%d Characters By Money:\x3\x31\x30 ", limitr);
3751+ for (uint64 i=0; i < result->GetRowCount(); i++)
3752+ {
3753+ std::string Name = fields[0].GetCppString();
3754+ unsigned int money = fields[1].GetInt32();
3755+
3756+ uint32 rank = i+1;
3757+
3758+ unsigned int gold = money / 10000;
3759+ unsigned int silv = (money % 10000) / 100;
3760+ unsigned int cop = (money % 10000) % 100;
3761+ char tempgold [100];
3762+ sprintf(tempgold, "\x2\x3\x30\x37%ug \x3\x31\x34%us \x3\x30\x35%uc\xF", gold, silv, cop);
3763+
3764+ tptime.append(MakeMsg("[%u]%s %s \xF| \x3\x31\x30\x2", rank, Name.c_str(), tempgold));
3765+ result->NextRow();
3766+ }
3767+ delete result;
3768+ Send_IRCA(ChanOrPM(CD), tptime, true, CD->TYPE);
3769+ }
3770+ else
3771+ Send_IRCA(CD->USER, "\0034[ERROR] : No Characters Returned." ,true, "ERROR");
3772+ }
3773+
3774+}
3775+
3776+void IRCCmd::Who_Logged(_CDATA *CD)
3777+{
3778+ std::string OPS = "";
3779+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
3780+ {
3781+ OPS.append(MakeMsg(" \002[GM:%d IRC: %s - WoW: %s]\002 ", (*i)->GMLevel, (*i)->Name.c_str(), (*i)->UName.c_str()));
3782+ }
3783+ Send_IRCA(ChanOrPM(CD), OPS, true, CD->TYPE);
3784+}
3785\ No newline at end of file
3786diff --git a/src/game/mangchat/IRCConf.cpp b/src/game/mangchat/IRCConf.cpp
3787new file mode 100644
3788index 0000000..b536641
3789--- a/src/game/mangchat/IRCConf.cpp
3790+++ b/src/game/mangchat/IRCConf.cpp
3791@@ -0,0 +1,173 @@
3792+/*
3793+ * MangChat By |Death| And Cybrax
3794+ *
3795+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
3796+ * Of The GNU General Public License
3797+ * Written and Developed by Cybrax. cybraxvd@gmail.com
3798+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
3799+ * Modified for patch 3.0.8 by Shinzon <shinzon@wowgollum.com>
3800+ * With Help And Support From The MaNGOS Project Community.
3801+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
3802+ */
3803+#include "IRCClient.h"
3804+#include "IRCCmd.h"
3805+#include "../../shared/Config/Config.h"
3806+#include "IRCConf.h"
3807+Config MCConfig;
3808+void IRCClient::SetCfg(char const* cfgfile)
3809+{
3810+ sIRC.CfgFile = cfgfile;
3811+}
3812+bool IRCClient::LoadConfig(char const* cfgfile)
3813+{
3814+ if (!MCConfig.SetSource(cfgfile))
3815+ sLog.outString("*** MangChat: Unable to open configuration file, All default options are being used.");
3816+ else sLog.outString("*** MangChat: Found the configuration file, %s", cfgfile);
3817+
3818+ int ConfCnt = 0;
3819+ sIRC._chan_count = 0;
3820+ if(MCConfig.GetIntDefault("irc.active", 1) == 1)
3821+ sIRC.Active = true;
3822+ else
3823+ sIRC.Active = false;
3824+ sIRC._Host = MCConfig.GetStringDefault("irc.host", "irc.freenode.net");
3825+ if(sIRC._Host.size() > 0)
3826+ ConfCnt++;
3827+ sIRC._Mver = MCConfig.GetStringDefault("irc.mver", "Version 1.6.5");
3828+ sIRC._Port = MCConfig.GetIntDefault("irc.port", 6667);
3829+ sIRC._User = MCConfig.GetStringDefault("irc.user", "MangChat");
3830+ sIRC._Pass = MCConfig.GetStringDefault("irc.pass", "MyDumbPass");
3831+ sIRC._Nick = MCConfig.GetStringDefault("irc.nick", "MangChat");
3832+ sIRC._Auth = MCConfig.GetIntDefault("irc.auth", 0);
3833+ sIRC._Auth_Nick = MCConfig.GetStringDefault("irc.auth.nick", "AuthNick");
3834+ sIRC._ICC = MCConfig.GetStringDefault("irc.icc", "001");
3835+ sIRC._defchan = MCConfig.GetStringDefault("irc.defchan", "lobby");
3836+ sIRC._ldefc = MCConfig.GetIntDefault("irc.ldef", 0);
3837+ sIRC._wct = MCConfig.GetIntDefault("irc.wct", 30000);
3838+ sIRC.ajoin = MCConfig.GetIntDefault("irc.ajoin", 1);
3839+ sIRC.ajchan = MCConfig.GetStringDefault("irc.ajchan", "world");
3840+ sIRC.onlrslt = MCConfig.GetIntDefault("irc.online.result", 10);
3841+ sIRC.BOTMASK = MCConfig.GetIntDefault("Botmask", 0);
3842+ sIRC.logfile = MCConfig.GetStringDefault("irc.logfile.prefix", "IRC_");
3843+ for(int i = 1; i < MAX_CONF_CHANNELS;i++)
3844+ {
3845+ std::ostringstream ss;
3846+ ss << i;
3847+ std::string ci = "irc.chan_" + ss.str();
3848+ std::string t_chan = MCConfig.GetStringDefault(ci.c_str(), "");
3849+ if(t_chan.size() > 0)
3850+ {
3851+ sIRC._chan_count++;
3852+ sIRC._irc_chan[sIRC._chan_count] = t_chan;
3853+ ci = "wow.chan_" + ss.str();
3854+ sIRC._wow_chan[sIRC._chan_count] = MCConfig.GetStringDefault(ci.c_str(), t_chan.c_str());
3855+ }
3856+ }
3857+ sIRC.JoinMsg = MCConfig.GetStringDefault("irc.joinmsg", "Whhaaazzzzaaaa, MangChat $Ver Baby!!");
3858+ sIRC.RstMsg = MCConfig.GetStringDefault("irc.rstmsg", "MangChat Is Restarting, I Will Be Right Back!");
3859+ sIRC.kikmsg = MCConfig.GetStringDefault("irc.kickmsg", "Do Not Kick Me Again, Severe Actions Will Be Taken!");
3860+ // IRC LINES
3861+ sIRC.ILINES[WOW_IRC] = MCConfig.GetStringDefault("chat.wow_irc", "\003<WoW>[\002$Name($Level)\002\003] $Msg");
3862+ sIRC.ILINES[IRC_WOW] = MCConfig.GetStringDefault("chat.irc_wow", "\003<IRC>[$Name]: $Msg");
3863+ sIRC.ILINES[JOIN_WOW] = MCConfig.GetStringDefault("chat.join_wow", "\00312>>\00304 $Name \003Joined The Channel!");
3864+ sIRC.ILINES[JOIN_IRC] = MCConfig.GetStringDefault("chat.join_irc", "\003[$Name]: Has Joined IRC!");
3865+ sIRC.ILINES[LEAVE_WOW] = MCConfig.GetStringDefault("chat.leave_wow", "\00312<<\00304 $Name \003Left The Channel!");
3866+ sIRC.ILINES[LEAVE_IRC] = MCConfig.GetStringDefault("chat.leave_irc", "\003[$Name]: Has Left IRC!");
3867+ sIRC.ILINES[CHANGE_NICK] = MCConfig.GetStringDefault("chat.change_nick", "\003<> $Name Is Now Known As $NewName!");
3868+ // MangChat Options
3869+ sIRC._MCA = MCConfig.GetIntDefault("irc.maxattempt", 10);
3870+ sIRC._autojoinkick = MCConfig.GetIntDefault("irc.autojoin_kick", 1);
3871+ sIRC._cmd_prefx = MCConfig.GetStringDefault("irc.command_prefix", ".");
3872+
3873+ sIRC._op_gm = MCConfig.GetIntDefault("irc.op_gm_login", 0);
3874+ sIRC._op_gm_lev = MCConfig.GetIntDefault("irc.op_gm_level", 3);
3875+
3876+ // Misc Options
3877+ sIRC.games = MCConfig.GetIntDefault("irc.fun.games", 0);
3878+ sIRC.gmlog = MCConfig.GetIntDefault("irc.gmlog", 1);
3879+ sIRC.BOTMASK = MCConfig.GetIntDefault("BotMask", 0);
3880+ sIRC.Status = MCConfig.GetIntDefault("irc.StatusChannel", 1);
3881+ sIRC.anchn = MCConfig.GetIntDefault("irc.AnnounceChannel", 1);
3882+ sIRC.autoanc = MCConfig.GetIntDefault("irc.auto.announce", 30);
3883+ sIRC.ojGM1 = MCConfig.GetStringDefault("irc.gm1", "[Moderator]");
3884+ sIRC.ojGM2 = MCConfig.GetStringDefault("irc.gm2", "[Game Master]");
3885+ sIRC.ojGM3 = MCConfig.GetStringDefault("irc.gm3", "[BugTracker]");
3886+ sIRC.ojGM4 = MCConfig.GetStringDefault("irc.gm4", "[DevTeam Admin]");
3887+ sIRC.ojGM5 = MCConfig.GetStringDefault("irc.gm5", "[Root Admin]");
3888+ // REQUIRED GM LEVEL
3889+ QueryResult *result = WorldDatabase.PQuery("SELECT `Command`, `gmlevel` FROM `IRC_Commands` ORDER BY `Command`");
3890+ if(result)
3891+ {
3892+ Field *fields = result->Fetch();
3893+ for (uint64 i=0; i < result->GetRowCount(); i++)
3894+ {
3895+ std::string command = fields[0].GetCppString();
3896+ uint32 gmlvl = fields[1].GetUInt32();
3897+ if(command == "acct") sIRC.CACCT = gmlvl;
3898+ if(command == "ban") sIRC.CBAN = gmlvl;
3899+ if(command == "char") sIRC.CCHAN = gmlvl;
3900+ if(command == "char") sIRC.CCHAR = gmlvl;
3901+ if(command == "fun") sIRC.CFUN = gmlvl;
3902+ if(command == "help") sIRC.CHELP = gmlvl;
3903+ if(command == "inchan") sIRC.CINCHAN = gmlvl;
3904+ if(command == "info") sIRC.CINFO = gmlvl;
3905+ if(command == "item") sIRC.CITEM = gmlvl;
3906+ if(command == "jail") sIRC.CJAIL = gmlvl;
3907+ if(command == "kick") sIRC.CKICK = gmlvl;
3908+ if(command == "kill") sIRC._KILL = gmlvl;
3909+ if(command == "level") sIRC.CLEVEL = gmlvl;
3910+ if(command == "lookup") sIRC.CLOOKUP = gmlvl;
3911+ if(command == "money") sIRC.CMONEY = gmlvl;
3912+ if(command == "mute") sIRC.CMUTE = gmlvl;
3913+ if(command == "online") sIRC.CONLINE = gmlvl;
3914+ if(command == "pm") sIRC.CPM = gmlvl;
3915+ if(command == "restart") sIRC.CRESTART = gmlvl;
3916+ if(command == "revive") sIRC.CREVIVE = gmlvl;
3917+ if(command == "saveall") sIRC.CSAVEALL = gmlvl;
3918+ if(command == "shutdown") sIRC.CSHUTDOWN = gmlvl;
3919+ if(command == "spell") sIRC.CSPELL = gmlvl;
3920+ if(command == "sysmsg") sIRC.CSYSMSG = gmlvl;
3921+ if(command == "tele") sIRC.CTELE = gmlvl;
3922+ if(command == "top") sIRC.CTOP = gmlvl;
3923+ if(command == "who") sIRC.CWHO = gmlvl;
3924+ result->NextRow();
3925+ }
3926+ delete result;
3927+ }
3928+ else
3929+ {
3930+ sIRC.CACCT = 3;
3931+ sIRC.CBAN = 3;
3932+ sIRC.CCHAN = 3;
3933+ sIRC.CCHAR = 3;
3934+ sIRC.CFUN = 3;
3935+ sIRC.CHELP = 3;
3936+ sIRC.CINCHAN = 3;
3937+ sIRC.CINFO = 3;
3938+ sIRC.CITEM = 3;
3939+ sIRC.CJAIL = 3;
3940+ sIRC.CKICK = 3;
3941+ sIRC._KILL = 3;
3942+ sIRC.CLEVEL = 3;
3943+ sIRC.CLOOKUP = 3;
3944+ sIRC.CMONEY = 3;
3945+ sIRC.CMUTE = 3;
3946+ sIRC.CONLINE = 3;
3947+ sIRC.CPM = 3;
3948+ sIRC.CRESTART = 3;
3949+ sIRC.CREVIVE = 3;
3950+ sIRC.CSAVEALL = 3;
3951+ sIRC.CSHUTDOWN = 3;
3952+ sIRC.CSPELL = 3;
3953+ sIRC.CSYSMSG = 3;
3954+ sIRC.CTELE = 3;
3955+ sIRC.CTOP = 3;
3956+ sIRC.CWHO = 3;
3957+ }
3958+ return true;
3959+}
3960+
3961+std::string IRCClient::GetChatLine(int nItem)
3962+{
3963+ return sIRC.ILINES[nItem];
3964+}
3965\ No newline at end of file
3966diff --git a/src/game/mangchat/IRCConf.h b/src/game/mangchat/IRCConf.h
3967new file mode 100644
3968index 0000000..669bc18
3969--- a/src/game/mangchat/IRCConf.h
3970+++ b/src/game/mangchat/IRCConf.h
3971@@ -0,0 +1,23 @@
3972+/* TriniChat Trinity Core IRC Client
3973+ *
3974+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
3975+ * Of The GNU General Public License
3976+ * Written And Developed By |Death|(death@hell360.net)
3977+ * - Based Off Of MangChat 1.0 By Cybrax(cybraxvf@gmail.com)
3978+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.*/
3979+#ifndef MC_CONFIG_H
3980+#define MC_CONFIG_H
3981+
3982+#include "../../framework/Platform/CompilerDefs.h"
3983+
3984+// Format is YYYYMMDDRR where RR is the change in the conf file
3985+// for that day.
3986+#define MangChat_CONF_VERSION 2008011901
3987+
3988+#if PLATFORM == PLATFORM_WINDOWS
3989+ #define _MangChat_CONFIG "mangchat.conf"
3990+#else
3991+ #define _MangChat_CONFIG "@sysconfdir@/mangchat.conf"
3992+#endif
3993+
3994+#endif
3995\ No newline at end of file
3996diff --git a/src/game/mangchat/IRCConf.h.in b/src/game/mangchat/IRCConf.h.in
3997new file mode 100644
3998index 0000000..638f423
3999--- a/src/game/mangchat/IRCConf.h.in
4000+++ b/src/game/mangchat/IRCConf.h.in
4001@@ -0,0 +1,16 @@
4002+#ifndef MC_CONFIG_H
4003+#define MC_CONFIG_H
4004+
4005+#include "../../framework/Platform/CompilerDefs.h"
4006+
4007+// Format is YYYYMMDDRR where RR is the change in the conf file
4008+// for that day.
4009+#define MANGCHAT_CONF_VERSION 2008011901
4010+
4011+#if PLATFORM == PLATFORM_WINDOWS
4012+ #define _MANGCHAT_CONFIG "mangchat.conf"
4013+#else
4014+ #define _MANGCHAT_CONFIG "@sysconfdir@/mangchat.conf"
4015+#endif
4016+
4017+#endif
4018diff --git a/src/game/mangchat/IRCFunc.h b/src/game/mangchat/IRCFunc.h
4019new file mode 100644
4020index 0000000..9394e6f
4021--- a/src/game/mangchat/IRCFunc.h
4022+++ b/src/game/mangchat/IRCFunc.h
4023@@ -0,0 +1,262 @@
4024+/*
4025+ * MangChat By |Death| And Cybrax
4026+ *
4027+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
4028+ * Of The GNU General Public License
4029+ * Written and Developed by Cybrax. cybraxvd@gmail.com
4030+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
4031+ * Modified for patch 3.0.8 by Shinzon <shinzon@wowgollum.com>
4032+ * With Help And Support From The MaNGOS Project Community.
4033+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
4034+ */
4035+#ifndef _IRC_CLIENT_FUNC
4036+#define _IRC_CLIENT_FUNC
4037+
4038+std::string GetUser(std::string szU)
4039+{
4040+ int pos = szU.find("!");
4041+ return szU.substr(0, pos);
4042+}
4043+// Delink will remove anything considered "non chat" from a string
4044+// Linked items (items that players can click on to see a description)
4045+// contain extra characters wich the client filter out, this function
4046+// makes sure people on irc do not see those characters.
4047+std::string Delink(std::string msg)
4048+{
4049+ std::size_t pos;
4050+ while((pos = msg.find("|Hitem")) != std::string::npos)
4051+ {
4052+ std::size_t find1 = msg.find("|h", pos);
4053+ std::size_t find2 = msg.find("|h", find1 + 2);
4054+ msg.replace(pos, find1 - pos + 2, "\x2");
4055+ msg.replace(msg.find("|h", pos), 2, "\x2");
4056+ }
4057+ while((pos = msg.find("|Henchant")) != std::string::npos)
4058+ {
4059+ std::size_t find1 = msg.find("|h", pos);
4060+ std::size_t find2 = msg.find("|h", find1 + 2);
4061+ msg.replace(pos, find1 - pos + 2, "\x2");
4062+ msg.replace(msg.find("|h", pos), 2, "\x2");
4063+ //msg.replace(find2, 2, "\x2");
4064+ }
4065+ return msg;
4066+}
4067+
4068+// This function converts the characters used by the client to identify colour to IRC format.
4069+std::string WoWcol2IRC(std::string msg)
4070+{
4071+ std::size_t pos;
4072+ char IRCCol[9][4] = { "\xF", "\xF", "\x3\x31\x34", "\x3\x30\x33", "\x3\x31\x32", "\x3\x30\x36", "\x3\x30\x37", "\x3\x30\x34", "\x3\x30\x37"};
4073+ char WoWCol[9][12] = { "|r", "|cffffffff", "|cff9d9d9d", "|cff1eff00", "|cff0070dd", "|cffa335ee", "|cffff8000", "|cffe6cc80", "|cffffd000"};
4074+ for (int i=0; i<=8; i++)
4075+ {
4076+ while ((pos = msg.find(WoWCol[i])) != std::string::npos)
4077+ {
4078+ if (i == 0)
4079+ msg.replace(pos, 2, IRCCol[i]);
4080+ else
4081+ msg.replace(pos, 10, IRCCol[i]);
4082+ }
4083+ }
4084+ return msg;
4085+}
4086+
4087+// This function converts the characters used by IRC to identify colour to a format the client can understand.
4088+std::string IRCcol2WoW(std::string msg)
4089+{
4090+ std::size_t pos;
4091+ char IRCCol[16][4] = { "\x3\x30", "\x3\x31", "\x3\x32", "\x3\x33", "\x3\x34", "\x3\x35", "\x3\x36", "\x3\x37", "\x3\x38", "\x3\x39", "\x3\x31\x30", "\x3\x31\x31", "\x3\x31\x32", "\x3\x31\x33", "\x3\x31\x34", "\x3\x31\x35"};
4092+ char IRCCol2[10][4] = { "\x3\x30\x30", "\x3\x30\x31", "\x3\x30\x32", "\x3\x30\x33", "\x3\x30\x34", "\x3\x30\x35", "\x3\x30\x36", "\x3\x30\x37", "\x3\x30\x38", "\x3\x30\x39"};
4093+ char WoWcol[16][12] = { "|cffffffff", "|cff000000", "|cff00007f", "|cff009300", "|cffff0000", "|cff7f0000", "|cff9c009c", "|cfffc9300", "|cffffff00", "|cff00fc00", "|cff009393", "|cff00ffff", "|cff0000fc", "|cffff00ff", "|cff7f7f7f", "|cffd2d2d2"};
4094+ for (int i=15; i>=0; i--)
4095+ {
4096+ if (i<10)
4097+ {
4098+ while ((pos = msg.find(IRCCol2[i])) != std::string::npos)
4099+ {
4100+ msg.replace(pos, 3, WoWcol[i]);
4101+ }
4102+ while ((pos = msg.find(IRCCol[i])) != std::string::npos)
4103+ {
4104+ msg.replace(pos, 2, WoWcol[i]);
4105+ }
4106+
4107+ }
4108+ else
4109+ {
4110+ while ((pos = msg.find(IRCCol[i])) != std::string::npos)
4111+ {
4112+ msg.replace(pos, 3, WoWcol[i]);
4113+ }
4114+ }
4115+
4116+ // Remove Bold, Reverse, Underline from IRC
4117+ char Checker[3][3] = {"\x2","\x16","\x1F"}; // This is the Hex part not Dec. In Decimal its (2,22,31)
4118+ for(int I=0; I < 3; I++)
4119+ {
4120+ while ((pos = msg.find(Checker[I])) != std::string::npos)
4121+ {
4122+ msg.replace(pos, 1, "");
4123+ }
4124+ }
4125+ // Finished Removing !
4126+
4127+ }
4128+
4129+ while ((pos = msg.find("\x3")) != std::string::npos)
4130+ {
4131+ msg.replace(pos, 1, "|r");
4132+ }
4133+ while ((pos = msg.find("\xF")) != std::string::npos)
4134+ {
4135+ msg.replace(pos, 1, "|r");
4136+ }
4137+
4138+ return msg;
4139+}
4140+
4141+// This function compares 2 strings
4142+int nocase_cmp(const string & s1, const string& s2)
4143+{
4144+ string::const_iterator it1=s1.begin();
4145+ string::const_iterator it2=s2.begin();
4146+
4147+ //stop when either string's end has been reached
4148+ while ( (it1!=s1.end()) && (it2!=s2.end()) )
4149+ {
4150+ if(::toupper(*it1) != ::toupper(*it2)) //letters differ?
4151+ // return -1 to indicate smaller than, 1 otherwise
4152+ return (::toupper(*it1) < ::toupper(*it2)) ? -1 : 1;
4153+ //proceed to the next character in each string
4154+ ++it1;
4155+ ++it2;
4156+ }
4157+ size_t size1=s1.size(), size2=s2.size(); // cache lengths
4158+ //return -1,0 or 1 according to strings' lengths
4159+ if (size1==size2)
4160+ return 0;
4161+ return (size1<size2) ? -1 : 1;
4162+}
4163+
4164+std::string MakeMsgA(const char *sLine, ... )
4165+{
4166+ va_list ap;
4167+ char tmpoutp[1024];
4168+ va_start(ap, sLine);
4169+ vsnprintf(tmpoutp, 1024, sLine, ap );
4170+ va_end(ap);
4171+ std::string outp = tmpoutp;
4172+ return outp;
4173+}
4174+
4175+std::string MakeMsgP(int CLINE, std::string Msg, Player *plr)
4176+{
4177+ // std::string ChatTag = "";
4178+ // switch (plr->GetTeam())
4179+ // {
4180+ // case 67:ChatTag.append("4");break; //horde
4181+ // case 469:ChatTag.append("12");break; //alliance
4182+ // }
4183+ std::string sMsg = sIRC.MakeMsg(sIRC.GetChatLine(CLINE), "$Msg", Msg);
4184+ // sMsg = ChatTag + MakeMsg(sMsg, "$Name", plr->GetName());
4185+ if (plr->GetTeam() == 67)
4186+ sMsg = sIRC.MakeMsg(sMsg, "$Name", MakeMsgA("\0034%s\003", plr->GetName()));
4187+ else if (plr->GetTeam() == 469)
4188+ sMsg = sIRC.MakeMsg(sMsg, "$Name", MakeMsgA("\00312%s\003", plr->GetName()));
4189+ if(plr->isAFK())
4190+ sMsg = sIRC.MakeMsg(sMsg, "$Tag", "<AFK>");
4191+ else if(plr->isDND())
4192+ sMsg = sIRC.MakeMsg(sMsg, "$Tag", "<DND>");
4193+ else
4194+ sMsg = sIRC.MakeMsg(sMsg, "$Tag", "");
4195+ sMsg = sIRC.MakeMsg(sMsg, "$Level", MakeMsgA("%d", plr->getLevel()));
4196+ sMsg = Delink(sMsg);
4197+ sMsg = WoWcol2IRC(sMsg);
4198+ return sMsg;
4199+}
4200+
4201+/*
4202+std::string MakeMsg(std::string msg, std::string var, int val)
4203+{
4204+ std::ostringstream ss;
4205+ ss << val;
4206+
4207+ std::string nval = ss.str();
4208+ std::size_t start = msg.find(var);
4209+ if (start != std::string::npos)
4210+ msg.replace(start, var.length(), val);
4211+ return msg;
4212+}
4213+*/
4214+/*
4215+std::string MakeMsg(const char *sLine, ... )
4216+{
4217+ va_list ap;
4218+ char tmpoutp[1024];
4219+ va_start(ap, sLine);
4220+ vsnprintf(tmpoutp, 1024, sLine, ap );
4221+ va_end(ap);
4222+ std::string outp = tmpoutp;
4223+ return outp;
4224+}
4225+*/
4226+
4227+// This function checks if a channel exists in out configuration
4228+// Mangchat supports as many channels as you like
4229+// However the default has been set to 10
4230+// if you wish to increase this you must edit the:
4231+// MAX_CONF_CHANNELS variable in IRCClient.h
4232+bool Channel_Valid(std::string Channel)
4233+{
4234+ for(int i=1;i < sIRC._chan_count + 1;i++)
4235+ {
4236+ if(nocase_cmp(sIRC._wow_chan[i], Channel)==0)
4237+ return true;
4238+ }
4239+ return false;
4240+}
4241+
4242+std::string GetWoWChannel(std::string Channel)
4243+{
4244+ for(int i=1;i < sIRC._chan_count + 1;i++)
4245+ {
4246+ if("#" + sIRC._irc_chan[i] == Channel)
4247+ return sIRC._wow_chan[i];
4248+ }
4249+ return "";
4250+}
4251+
4252+std::string GetIRCChannel(std::string Channel)
4253+{
4254+ for(int i=1;i < sIRC._chan_count + 1;i++)
4255+ {
4256+ if(sIRC._wow_chan[i] == Channel)
4257+ return sIRC._irc_chan[i];
4258+ }
4259+ return "";
4260+}
4261+
4262+std::string* getArray(std::string PARAMS, int nCount, std::string )
4263+{
4264+ std::string *array = new std::string[nCount];
4265+ if(PARAMS.size() > 0)
4266+ {
4267+ int pcnt = 0;
4268+ size_t ps = 0;
4269+ size_t pc = -1;
4270+ for(int i = 0;i < nCount;i++)
4271+ {
4272+ pc = PARAMS.find(" ", pc + 1);
4273+ if(i + 1 == nCount && nCount != 1)
4274+ {
4275+ if(ps > 0 && pc > 0)
4276+ array[i] = PARAMS.substr(ps, PARAMS.size() - ps);
4277+ }
4278+ else
4279+ array[i] = PARAMS.substr(ps, pc - ps);
4280+ ps = pc + 1;
4281+ }
4282+ }
4283+ return array;
4284+}
4285+#endif
4286\ No newline at end of file
4287diff --git a/src/game/mangchat/IRCIO.cpp b/src/game/mangchat/IRCIO.cpp
4288new file mode 100644
4289index 0000000..6e3c398
4290--- a/src/game/mangchat/IRCIO.cpp
4291+++ b/src/game/mangchat/IRCIO.cpp
4292@@ -0,0 +1,447 @@
4293+/*
4294+ * MangChat By |Death| And Cybrax
4295+ *
4296+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
4297+ * Of The GNU General Public License
4298+ * Written and Developed by Cybrax. cybraxvd@gmail.com
4299+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
4300+ * Modified for patch 3.0.8 by Shinzon <shinzon@wowgollum.com>
4301+ * With Help And Support From The MaNGOS Project Community.
4302+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
4303+ */
4304+#include "IRCClient.h"
4305+#include "IRCCmd.h"
4306+#include "IRCFunc.h"
4307+#include "../ObjectAccessor.h"
4308+#include "../ObjectMgr.h"
4309+#include "../WorldPacket.h"
4310+#include "../ChannelMgr.h"
4311+#include "../Config/ConfigEnv.h"
4312+#include "../Channel.h"
4313+#include "../World.h"
4314+
4315+IRCCmd Command;
4316+void IRCClient::Handle_IRC(std::string sData)
4317+{
4318+ sLog.outDebug(sData.c_str());
4319+ // If first 5 chars are ERROR then something is wrong
4320+ // either link is being closed, nickserv ghost command, etc...
4321+ if(sData.substr(0, 5) == "ERROR")
4322+ {
4323+ Disconnect();
4324+ return;
4325+ }
4326+ if(sData.substr(0, 4) == "PING")
4327+ {
4328+ // if the first 4 characters contain PING
4329+ // the server is checking if we are still alive
4330+ // sen back PONG back plus whatever the server send with it
4331+ SendIRC("PONG " + sData.substr(4, sData.size() - 4));
4332+ }
4333+ else
4334+ {
4335+ // if the first line contains : its an irc message
4336+ // such as private messages channel join etc.
4337+ if(sData.substr(0, 1) == ":")
4338+ {
4339+ // find the spaces in the receieved line
4340+ size_t p1 = sData.find(" ");
4341+ size_t p2 = sData.find(" ", p1 + 1);
4342+ // because the irc protocol uses simple spaces
4343+ // to seperate data we can easy pick them out
4344+ // since we know the position of the spaces
4345+ std::string USR = sData.substr(1, p1 - 1);
4346+ std::string CMD = sData.substr(p1 + 1, p2 - p1 - 1);
4347+ // trasform the commands to lowercase to make sure they always match
4348+ std::transform(CMD.begin(), CMD.end(), CMD.begin(), towlower);
4349+ // Extract the username from the first part
4350+ std::string szUser = GetUser(USR);
4351+ // if we receieved the internet connect code
4352+ // we know for sure that were in and we can
4353+ // authenticate ourself.
4354+ if(CMD == sIRC._ICC)
4355+ {
4356+ // _Auth is defined in mangosd.conf (irc.auth)
4357+ // 0 do not authenticate
4358+ // 1 use nickserv
4359+ // 2 use quakenet
4360+ // aditionally you can provide you own authentication method here
4361+ switch(sIRC._Auth)
4362+ {
4363+ case 1:
4364+ SendIRC("PRIVMSG nickserv :IDENTIFY " + sIRC._Pass);
4365+ break;
4366+ case 2:
4367+ SendIRC("PRIVMSG nickserv :IDENTIFY " + sIRC._Auth_Nick + " " + sIRC._Pass);
4368+ break;
4369+ case 3:
4370+ SendIRC("PRIVMSG Q@CServe.quakenet.org :AUTH " + sIRC._Nick + " " + sIRC._Pass);
4371+ break;
4372+ case 4:
4373+ SendIRC("PRIVMSG Q@CServe.quakenet.org :AUTH " + sIRC._Auth_Nick + " " + sIRC._Pass);
4374+ break;
4375+ }
4376+ // if we join a default channel leave this now.
4377+ if(sIRC._ldefc==1)
4378+ SendIRC("PART #" + sIRC._defchan);
4379+ // Loop thru the channel array and send a command to join them on IRC.
4380+ for(int i=1;i < sIRC._chan_count + 1;i++)
4381+ {
4382+ SendIRC("JOIN #" + sIRC._irc_chan[i]);
4383+ }
4384+ }
4385+ // someone joined the channel this could be the bot or another user
4386+ if(CMD == "join")
4387+ {
4388+ size_t p = sData.find(":", p1);
4389+ std::string CHAN = sData.substr(p + 1, sData.size() - p - 2);
4390+ // if the user is us it means we join the channel
4391+ if ((szUser == sIRC._Nick) )
4392+ {
4393+ // its us that joined the channel
4394+ Send_IRC_Channel(CHAN, MakeMsg(MakeMsg(sIRC.JoinMsg, "$Ver", sIRC._Mver.c_str()), "$Trigger", sIRC._cmd_prefx.c_str()), true);
4395+ }
4396+ else
4397+ {
4398+ // if the user is not us its someone else that joins
4399+ // so we construct a message and send this to the clients.
4400+ // MangChat now uses Send_WoW_Channel to send to the client
4401+ // this makes MangChat handle the packets instead of previously the world.
4402+ if((sIRC.BOTMASK & 2) != 0)
4403+ Send_WoW_Channel(GetWoWChannel(CHAN).c_str(), IRCcol2WoW(MakeMsg(MakeMsg(GetChatLine(JOIN_IRC), "$Name", szUser), "$Channel", GetWoWChannel(CHAN))));
4404+ }
4405+ }
4406+ // someone on irc left or quit the channel
4407+ if(CMD == "part" || CMD == "quit")
4408+ {
4409+ size_t p3 = sData.find(" ", p2 + 1);
4410+ std::string CHAN = sData.substr(p2 + 1, p3 - p2 - 1);
4411+ // Logout IRC Nick From MangChat If User Leaves Or Quits IRC.
4412+ if(Command.IsLoggedIn(szUser))
4413+ {
4414+ _CDATA CDATA;
4415+ CDATA.USER = szUser;
4416+ Command.Handle_Logout(&CDATA);
4417+ }
4418+ // Construct a message and inform the clients on the same channel.
4419+ if((sIRC.BOTMASK & 2) != 0)
4420+ Send_WoW_Channel(GetWoWChannel(CHAN).c_str(), IRCcol2WoW(MakeMsg(MakeMsg(GetChatLine(LEAVE_IRC), "$Name", szUser), "$Channel", GetWoWChannel(CHAN))));
4421+ }
4422+ // someone changed their nick
4423+ if (CMD == "nick" && (sIRC.BOTMASK & 128) != 0)
4424+ {
4425+ MakeMsg(MakeMsg(GetChatLine(CHANGE_NICK), "$Name", szUser), "$NewName", sData.substr(sData.find(":", p2) + 1));
4426+ // If the user is logged in and changes their nick
4427+ // then we want to either log them out or update
4428+ // their nick in the bot. I chose to update the bots user list.
4429+ if(Command.IsLoggedIn(szUser))
4430+ {
4431+ std::string NewNick = sData.substr(sData.find(":", p2) + 1);
4432+ // On freenode I noticed the server sends an extra character
4433+ // at the end of the string, so we need to erase the last
4434+ // character of the string. if you have a problem with getting
4435+ // the last letter of your nick erased, then remove the - 1.
4436+ NewNick.erase(NewNick.length() - 1, 1);
4437+
4438+ for(std::list<_client*>::iterator i=Command._CLIENTS.begin(); i!=Command._CLIENTS.end();i++)
4439+ {
4440+ if((*i)->Name == szUser)
4441+ {
4442+ (*i)->Name = NewNick;
4443+ sIRC.Send_IRC_Channel(NewNick.c_str(), "I Noticed You Changed Your Nick, I Have Updated My Internal Database Accordingly.", true, "NOTICE");
4444+
4445+ // Figure why not output to the logfile, makes tracing problems easier.
4446+ sIRC.iLog.WriteLog(" %s : %s Changed Nick To: %s", sIRC.iLog.GetLogDateTimeStr().c_str(), szUser.c_str(), NewNick.c_str());
4447+ }
4448+ }
4449+ }
4450+
4451+ }
4452+ // someone was kicked from irc
4453+ if (CMD == "kick")
4454+ {
4455+ // extract the details
4456+ size_t p3 = sData.find(" ", p2 + 1);
4457+ size_t p4 = sData.find(" ", p3 + 1);
4458+ size_t p5 = sData.find(":", p4);
4459+ std::string CHAN = sData.substr(p2 + 1, p3 - p2 - 1);
4460+ std::string WHO = sData.substr(p3 + 1, p4 - p3 - 1);
4461+ std::string BY = sData.substr(p4 + 1, sData.size() - p4 - 1);
4462+ // if the one kicked was us
4463+ if(WHO == sIRC._Nick)
4464+ {
4465+ // and autojoin is enabled
4466+ // return to the channel
4467+ if(sIRC._autojoinkick == 1)
4468+ {
4469+ SendIRC("JOIN " + CHAN);
4470+ Send_IRC_Channel(CHAN, sIRC.kikmsg, true);
4471+ }
4472+ }
4473+ else
4474+ {
4475+ // if it is not us who was kicked we need to inform the clients someone
4476+ // was removed from the channel
4477+ // construct a message and send it to the players.
4478+ Send_WoW_Channel(GetWoWChannel(CHAN).c_str(), "<IRC>[" + WHO + "]: Was Kicked From " + CHAN + " By: " + szUser);
4479+ }
4480+ }
4481+ // a private chat message was receieved.
4482+ if(CMD == "privmsg" || CMD == "notice")
4483+ {
4484+ // extract the values
4485+ size_t p = sData.find(" ", p2 + 1);
4486+ std::string FROM = sData.substr(p2 + 1, p - p2 - 1);
4487+ std::string CHAT = sData.substr(p + 2, sData.size() - p - 3);
4488+ // if this is our username it means we recieved a PM
4489+ if(FROM == sIRC._Nick)
4490+ {
4491+ if(CHAT.find("\001VERSION\001") < CHAT.size())
4492+ {
4493+ Send_IRC_Channel(szUser, MakeMsg("\001VERSION MangChat %s �2009 |Death|\001", "%s" , sIRC._Mver.c_str()), true, "PRIVMSG");
4494+ }
4495+ // a pm is required for certain commands
4496+ // such as login. to validate the command
4497+ // we send it to the command class wich handles
4498+ // evrything else.
4499+ Command.IsValid(szUser, FROM, CHAT, CMD);
4500+ }
4501+ else
4502+ {
4503+ // if our name is not in it, it means we receieved chat on one of the channels
4504+ // magchat is in. the first thing we do is check if it is a command or not
4505+ if(!Command.IsValid(szUser, FROM, CHAT, CMD))
4506+ {
4507+ Send_WoW_Channel(GetWoWChannel(FROM).c_str(), IRCcol2WoW(MakeMsg(MakeMsg(GetChatLine(IRC_WOW), "$Name", szUser), "$Msg", CHAT)));
4508+ }
4509+ // if we indeed receieved a command we do not want to display this to the players
4510+ // so only incanse the isvalid command returns false it will be sent to all player.
4511+ // the isvalid function will automaitcly process the command on true.
4512+ }
4513+ }
4514+ if(CMD == "mode")
4515+ {
4516+ // extract the mode details
4517+ size_t p3 = sData.find(" ", p2 + 1);
4518+ size_t p4 = sData.find(" ", p3 + 1);
4519+ size_t p5 = sData.find(" ", p4 + 1);
4520+ std::string CHAN = sData.substr(p2 + 1, p3 - p2 - 1);
4521+ std::string MODE = sData.substr(p3 + 1, p4 - p3 - 1);
4522+ std::string NICK = sData.substr(p4 + 1, p5 - p4 - 1);
4523+ bool _AmiOp;
4524+ _AmiOp = false;
4525+ //A mode was changed on us
4526+ if(NICK.c_str() == sIRC._Nick)
4527+ _AmiOp = true;
4528+
4529+ }
4530+ }
4531+ }
4532+}
4533+
4534+// This function is called in Channel.h
4535+// based on nAction it will inform the people on
4536+// irc when someone leaves one of the game channels.
4537+// nAction is based on the struct CACTION
4538+void IRCClient::Handle_WoW_Channel(std::string Channel, Player *plr, int nAction)
4539+{
4540+ // make sure that we are connected
4541+ if(sIRC.Connected && (sIRC.BOTMASK & 1)!= 0)
4542+ {
4543+ if(Channel_Valid(Channel))
4544+ {
4545+ std::string GMRank = "";
4546+ std::string pname = plr->GetName();
4547+ bool DoGMAnnounce = false;
4548+ if (plr->GetSession()->GetSecurity() > 0 && (sIRC.BOTMASK & 8)!= 0)
4549+ DoGMAnnounce = true;
4550+ if (plr->isGameMaster() && (sIRC.BOTMASK & 16)!= 0)
4551+ DoGMAnnounce = true;
4552+ if(DoGMAnnounce)
4553+ {
4554+ switch(plr->GetSession()->GetSecurity()) //switch case to determine what rank the "gm" is
4555+ {
4556+ case 0: GMRank = "";break;
4557+ case 1: GMRank = "\0037"+sIRC.ojGM1;break;
4558+ case 2: GMRank = "\0037"+sIRC.ojGM2;break;
4559+ case 3: GMRank = "\0037"+sIRC.ojGM3;break;
4560+ case 4: GMRank = "\0037"+sIRC.ojGM4;break;
4561+ case 5: GMRank = "\0037"+sIRC.ojGM5;break;
4562+ }
4563+ }
4564+ std::string ChatTag = "";
4565+ switch (plr->GetTeam())
4566+ {
4567+ case 67:ChatTag.append("\0034");break; //horde
4568+ case 469:ChatTag.append("\00312");break; //alliance
4569+ }
4570+ std::string query = "INSERT INTO `IRC_Inchan` VALUES (%d,'"+pname+"','"+Channel+"')";
4571+ std::string lchan = "DELETE FROM `IRC_Inchan` WHERE `guid` = %d AND `channel` = '"+Channel+"'";
4572+ switch(nAction)
4573+ {
4574+ case CHANNEL_JOIN:
4575+ Send_IRC_Channel(GetIRCChannel(Channel), MakeMsg(MakeMsg(MakeMsg(GetChatLine(JOIN_WOW), "$Name", ChatTag + plr->GetName()), "$Channel", Channel), "$GM", GMRank));
4576+ WorldDatabase.PExecute(lchan.c_str(), plr->GetGUID());
4577+ WorldDatabase.PExecute(query.c_str(), plr->GetGUID());
4578+ break;
4579+ case CHANNEL_LEAVE:
4580+ Send_IRC_Channel(GetIRCChannel(Channel), MakeMsg(MakeMsg(MakeMsg(GetChatLine(LEAVE_WOW), "$Name", ChatTag + plr->GetName()), "$Channel", Channel), "$GM", GMRank));
4581+ WorldDatabase.PExecute(lchan.c_str(), plr->GetGUID());
4582+ break;
4583+ }
4584+ }
4585+ }
4586+}
4587+
4588+// This function sends chat to a irc channel or user
4589+// to prevent the # beeing appended to send a msg to a user
4590+// set the NoPrefix to true
4591+void IRCClient::Send_IRC_Channel(std::string sChannel, std::string sMsg, bool NoPrefix, std::string nType)
4592+{
4593+ std::string mType = "PRIVMSG";
4594+ if(Command.MakeUpper(nType.c_str()) == "NOTICE")
4595+ mType = "NOTICE";
4596+ if(Command.MakeUpper(nType.c_str()) == "ERROR" && (sIRC.BOTMASK & 32)!= 0)
4597+ mType = "NOTICE";
4598+ if(sIRC.Connected)
4599+ {
4600+ if(NoPrefix)
4601+ SendIRC(mType + " " + sChannel + " :" + sMsg);
4602+ else
4603+ SendIRC(mType + " #" + sChannel + " :" + sMsg);
4604+ }
4605+}
4606+
4607+// This function sends a message to all irc channels
4608+// that mangchat has in its configuration
4609+void IRCClient::Send_IRC_Channels(std::string sMsg)
4610+{
4611+ for(int i=1;i < sIRC._chan_count + 1;i++)
4612+ Send_IRC_Channel(sIRC._irc_chan[i], sMsg);
4613+}
4614+
4615+// This function is called in ChatHandler.cpp, any channel chat from wow will come
4616+// to this function, validates the channel and constructs a message that is send to IRC
4617+void IRCClient::Send_WoW_IRC(Player *plr, std::string Channel, std::string Msg)
4618+{
4619+ // Check if the channel exist in our configuration
4620+ if(Channel_Valid(Channel) && Msg.substr(0, 1) != ".")
4621+ Send_IRC_Channel(GetIRCChannel(Channel), MakeMsgP(WOW_IRC, Msg, plr));
4622+}
4623+
4624+void IRCClient::Send_WoW_Player(std::string sPlayer, std::string sMsg)
4625+{
4626+ normalizePlayerName(sPlayer);
4627+ if (Player* plr = ObjectAccessor::Instance().FindPlayerByName(sPlayer.c_str()))
4628+ Send_WoW_Player(plr, sMsg);
4629+}
4630+
4631+void IRCClient::Send_WoW_Player(Player *plr, string sMsg)
4632+{
4633+ WorldPacket data(SMSG_MESSAGECHAT, 200);
4634+ data << (uint8)CHAT_MSG_SYSTEM;
4635+ data << (uint32)LANG_UNIVERSAL;
4636+ data << (uint64)plr->GetGUID();
4637+ data << (uint32)0;
4638+ data << (uint64)plr->GetGUID();
4639+ data << (uint32)(sMsg.length()+1);
4640+ data << sMsg;
4641+ data << (uint8)0;
4642+ plr->GetSession()->SendPacket(&data);
4643+}
4644+
4645+// This function will construct and send a packet to all players
4646+// on the given channel ingame. (previuosly found in world.cpp)
4647+// it loops thru all sessions and checks if they are on the channel
4648+// if so construct a packet and send it.
4649+void IRCClient::Send_WoW_Channel(const char *channel, std::string chat)
4650+{
4651+ if(!(strlen(channel) > 0))
4652+ return;
4653+
4654+ #ifdef USE_UTF8
4655+ std::string chat2 = chat;
4656+ if(ConvertUTF8(chat2.c_str(), chat2))
4657+ chat = chat2;
4658+ #endif
4659+
4660+ HashMapHolder<Player>::MapType& m = ObjectAccessor::Instance().GetPlayers();
4661+ for(HashMapHolder<Player>::MapType::iterator itr = m.begin(); itr != m.end(); ++itr)
4662+ {
4663+ if (itr->second && itr->second->GetSession()->GetPlayer() && itr->second->GetSession()->GetPlayer()->IsInWorld())
4664+ {
4665+ if(ChannelMgr* cMgr = channelMgr(itr->second->GetSession()->GetPlayer()->GetTeam()))
4666+ {
4667+ if(Channel *chn = cMgr->GetChannel(channel, itr->second->GetSession()->GetPlayer()))
4668+ {
4669+ WorldPacket data;
4670+ data.Initialize(SMSG_MESSAGECHAT);
4671+ data << (uint8)CHAT_MSG_CHANNEL;
4672+ data << (uint32)LANG_UNIVERSAL;
4673+ data << (uint64)0;
4674+ data << (uint32)0;
4675+ data << channel;
4676+ data << (uint64)0;
4677+ data << (uint32) (strlen(chat.c_str()) + 1);
4678+ data << IRCcol2WoW(chat.c_str());
4679+ data << (uint8)0;
4680+ itr->second->GetSession()->SendPacket(&data);
4681+ }
4682+ }
4683+ }
4684+ }
4685+}
4686+
4687+void IRCClient::Send_WoW_System(std::string Message)
4688+{
4689+ HashMapHolder<Player>::MapType& m = ObjectAccessor::Instance().GetPlayers();
4690+ for(HashMapHolder<Player>::MapType::iterator itr = m.begin(); itr != m.end(); ++itr)
4691+ {
4692+ if (itr->second && itr->second->GetSession()->GetPlayer() && itr->second->GetSession()->GetPlayer()->IsInWorld())
4693+ {
4694+ WorldPacket data;
4695+ data.Initialize(CHAT_MSG_SYSTEM);
4696+ data << (uint8)CHAT_MSG_SYSTEM;
4697+ data << (uint32)LANG_UNIVERSAL;
4698+ data << (uint64)0;
4699+ data << (uint32)0;
4700+ data << (uint64)0;
4701+ data << (uint32) (strlen(Message.c_str()) + 1);
4702+ data << Message.c_str();
4703+ data << (uint8)0;
4704+ itr->second->GetSession()->SendPacket(&data);
4705+ }
4706+ }
4707+}
4708+void IRCClient::ResetIRC()
4709+{
4710+ SendData("QUIT");
4711+ Disconnect();
4712+}
4713+
4714+#define CHAT_INVITE_NOTICE 0x18
4715+
4716+// this function should be called on player login Player::AddToWorld
4717+void IRCClient::AutoJoinChannel(Player *plr)
4718+{
4719+ //this will work if at least 1 player is logged in regrdless if he is on the channel or not
4720+ // the first person that login empty server is the one with bad luck and wont be invited,
4721+ // if at least 1 player is online the player will be inited to the chanel
4722+
4723+ std::string m_name = sIRC.ajchan;
4724+ WorldPacket data;
4725+ data.Initialize(SMSG_CHANNEL_NOTIFY, 1+m_name.size()+1);
4726+ data << uint8(CHAT_INVITE_NOTICE);
4727+ data << m_name.c_str();
4728+
4729+ HashMapHolder<Player>::MapType& m = ObjectAccessor::Instance().GetPlayers();
4730+ for(HashMapHolder<Player>::MapType::iterator itr = m.begin(); itr != m.end(); ++itr)
4731+ {
4732+ if (itr->second && itr->second->GetSession()->GetPlayer() && itr->second->GetSession()->GetPlayer()->IsInWorld())
4733+ {
4734+ data << uint64(itr->second->GetGUID());
4735+ break;
4736+ }
4737+ }
4738+ plr->GetSession()->SendPacket(&data);
4739+}
4740\ No newline at end of file
4741diff --git a/src/game/mangchat/IRCLog.cpp b/src/game/mangchat/IRCLog.cpp
4742new file mode 100644
4743index 0000000..af5cab8
4744--- a/src/game/mangchat/IRCLog.cpp
4745+++ b/src/game/mangchat/IRCLog.cpp
4746@@ -0,0 +1,71 @@
4747+/*
4748+ * MangChat By |Death| And Cybrax
4749+ *
4750+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
4751+ * Of The GNU General Public License
4752+ * Written and Developed by Cybrax. cybraxvd@gmail.com
4753+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
4754+ * Modified for patch 3.0.8 by Shinzon <shinzon@wowgollum.com>
4755+ * With Help And Support From The MaNGOS Project Community.
4756+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
4757+ */
4758+#include "IRCLog.h"
4759+#include "Config/ConfigEnv.h"
4760+#include "IRCClient.h"
4761+#include <stdarg.h>
4762+
4763+IRCLog::IRCLog()
4764+{
4765+ std::string logsDir = sConfig.GetStringDefault("LogsDir","");
4766+ std::string ircLogName = logsDir + "/IRC_";
4767+ std::string ircLogTimestamp = GetLogDateStr();
4768+ ircLogName += ircLogTimestamp +".log";
4769+ ircLogfile.open (ircLogName.c_str(), std::ios::app);
4770+}
4771+
4772+IRCLog::~IRCLog()
4773+{
4774+ ircLogfile.close();
4775+}
4776+// Was added because using the time for logs is very annoying... one log per day.. much cleaner looking..
4777+std::string IRCLog::GetLogDateStr() const
4778+{
4779+ time_t t = time(NULL);
4780+ tm* aTm = localtime(&t);
4781+ // YYYY year
4782+ // MM month (2 digits 01-12)
4783+ // DD day (2 digits 01-31)
4784+ // HH hour (2 digits 00-23)
4785+ // MM minutes (2 digits 00-59)
4786+ // SS seconds (2 digits 00-59)
4787+ char buf[20];
4788+ snprintf(buf,20,"%04d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday);
4789+ return std::string(buf);
4790+}
4791+
4792+std::string IRCLog::GetLogDateTimeStr() const
4793+{
4794+ time_t t = time(NULL);
4795+ tm* aTm = localtime(&t);
4796+ // YYYY year
4797+ // MM month (2 digits 01-12)
4798+ // DD day (2 digits 01-31)
4799+ // HH hour (2 digits 00-23)
4800+ // MM minutes (2 digits 00-59)
4801+ // SS seconds (2 digits 00-59)
4802+ char buf[30];
4803+ snprintf(buf,30,"[ %04d-%02d-%02d ] [ %02d:%02d:%02d ]",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec);
4804+ return std::string(buf);
4805+}
4806+
4807+void IRCLog::WriteLog(const char *what, ...)
4808+{
4809+ va_list ap;
4810+ char tmpoutp[1024];
4811+ va_start(ap, what);
4812+ vsnprintf(tmpoutp, 1024, what, ap );
4813+ va_end(ap);
4814+ ircLogfile << tmpoutp;
4815+ ircLogfile << "\n";
4816+ ircLogfile.flush();
4817+}
4818\ No newline at end of file
4819diff --git a/src/game/mangchat/IRCLog.h b/src/game/mangchat/IRCLog.h
4820new file mode 100644
4821index 0000000..547b786
4822--- a/src/game/mangchat/IRCLog.h
4823+++ b/src/game/mangchat/IRCLog.h
4824@@ -0,0 +1,33 @@
4825+/*
4826+ * MangChat By |Death| And Cybrax
4827+ *
4828+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
4829+ * Of The GNU General Public License
4830+ * Written and Developed by Cybrax. cybraxvd@gmail.com
4831+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
4832+ * Modified for patch 3.0.8 by Shinzon <shinzon@wowgollum.com>
4833+ * With Help And Support From The MaNGOS Project Community.
4834+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
4835+ */
4836+#ifndef _IRC_LOG_H
4837+#define _IRC_LOG_H
4838+
4839+#include "Common.h"
4840+#include <fstream>
4841+
4842+class IRCLog
4843+{
4844+ public:
4845+ IRCLog();
4846+ ~IRCLog();
4847+
4848+ public:
4849+ void WriteLog(const char *what, ...);
4850+ std::string GetLogDateStr() const;
4851+ std::string GetLogDateTimeStr() const;
4852+ private:
4853+ std::ofstream ircLogfile;
4854+};
4855+
4856+
4857+#endif
4858\ No newline at end of file
4859diff --git a/src/game/mangchat/IRCSock.cpp b/src/game/mangchat/IRCSock.cpp
4860new file mode 100644
4861index 0000000..4d2683a
4862--- /dev/null
4863+++ b/src/game/mangchat/IRCSock.cpp
4864@@ -0,0 +1,157 @@
4865+/*
4866+ * MangChat By |Death| And Cybrax
4867+ *
4868+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
4869+ * Of The GNU General Public License
4870+ * Written and Developed by Cybrax. cybraxvd@gmail.com
4871+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
4872+ * Modified for patch 3.0.8 by Shinzon <shinzon@wowgollum.com>
4873+ * With Help And Support From The MaNGOS Project Community.
4874+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
4875+ */
4876+#include "IRCClient.h"
4877+#define MAXDATASIZE 512
4878+#include <fcntl.h>
4879+
4880+#include <stdio.h>
4881+#include <sys/types.h>
4882+
4883+
4884+#define _UNICODE
4885+
4886+#ifdef _MBCS
4887+#undef _MBCS
4888+#endif
4889+
4890+bool IRCClient::InitSock()
4891+{
4892+ #ifdef _WIN32
4893+ WSADATA wsaData; //WSAData
4894+ if(WSAStartup(MAKEWORD(2,0),&wsaData) != 0)
4895+ {
4896+ sLog.outError("IRC Error: Winsock Initialization Error");
4897+ return false;
4898+ }
4899+ #endif
4900+ if ((sIRC.SOCKET = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
4901+ {
4902+ sLog.outError("IRC Error: Socket Error");
4903+ return false;
4904+ }
4905+ int on = 1;
4906+ if ( setsockopt ( sIRC.SOCKET, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 )
4907+ {
4908+ sLog.outError("IRC Error: Invalid Socket");
4909+ return false;
4910+ }
4911+ #ifdef _WIN32
4912+ u_long iMode = 0;
4913+ ioctlsocket(sIRC.SOCKET, FIONBIO, &iMode);
4914+ #else
4915+ fcntl(sIRC.SOCKET, F_SETFL, O_NONBLOCK); // set to non-blocking
4916+ fcntl(sIRC.SOCKET, F_SETFL, O_ASYNC); // set to asynchronous I/O
4917+ #endif
4918+ return true;
4919+}
4920+
4921+bool IRCClient::Connect(const char *cHost, int nPort)
4922+{
4923+ sIRC.Connected = false;
4924+ struct hostent *he;
4925+ if ((he=gethostbyname(cHost)) == NULL)
4926+ {
4927+ sLog.outError("IRCLIENT: Could not resolve host: %s", cHost);
4928+ return false;
4929+ }
4930+ struct sockaddr_in their_addr;
4931+ their_addr.sin_family = AF_INET;
4932+ their_addr.sin_port = htons(nPort);
4933+ their_addr.sin_addr = *((struct in_addr *)he->h_addr);
4934+ memset(&(their_addr.sin_zero), '\0', 8);
4935+ if (::connect(sIRC.SOCKET, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)
4936+ {
4937+ sLog.outError("IRCLIENT: Cannot connect to %s", cHost);
4938+ return false;
4939+ }
4940+ //FD_ZERO(&sIRC.sfdset);
4941+ //FD_SET(sIRC.SOCKET,&sIRC.sfdset);
4942+ sIRC.Connected = true;
4943+ return true;
4944+}
4945+
4946+bool IRCClient::Login(std::string sNick, std::string sUser, std::string sPass)
4947+{
4948+ char hostname[128];
4949+ gethostname(hostname, sizeof(hostname));
4950+ if(SendIRC("HELLO"))
4951+ if(SendIRC("PASS " + sPass))
4952+ if(SendIRC("NICK " + sNick))
4953+ if(SendIRC("USER " + sUser + " " + (std::string)hostname + " MangChat :MangChat "+sIRC._Mver.c_str()))
4954+ return true;
4955+ return false;
4956+}
4957+
4958+bool IRCClient::SendData(const char *data)
4959+{
4960+ if(sIRC.Connected)
4961+ {
4962+ if (send(sIRC.SOCKET, data, strlen(data), 0) == -1)
4963+ {
4964+ sLog.outError("IRC Error: Socket Receieve ** \n");
4965+ //Disconnect();
4966+ return false;
4967+ }
4968+ }
4969+ return true;
4970+}
4971+
4972+bool IRCClient::SendIRC(std::string data)
4973+{
4974+ std::string RealData = data + "\n";
4975+ return SendData(RealData.c_str());
4976+}
4977+
4978+void IRCClient::Disconnect()
4979+{
4980+ if(sIRC.SOCKET)
4981+ {
4982+ #ifdef _WIN32
4983+ closesocket(sIRC.SOCKET);
4984+ //WSACleanup();
4985+ #else
4986+ close(sIRC.SOCKET);
4987+ #endif
4988+ }
4989+}
4990+
4991+void IRCClient::SockRecv()
4992+{
4993+// wchar_t bufferdata;
4994+
4995+ char szBuffer[MAXDATASIZE];
4996+
4997+ memset(szBuffer, 0, MAXDATASIZE );
4998+
4999+ int nBytesRecv = ::recv(sIRC.SOCKET, szBuffer, MAXDATASIZE - 1, 0 );
5000+ if ( nBytesRecv == -1 )
5001+ {
5002+ sLog.outError("Connection lost.");
5003+ sIRC.Connected = false;
5004+ }
5005+ else
5006+ {
5007+ if (-1 == nBytesRecv)
5008+ {
5009+ sLog.outError("Error occurred while receiving from socket.");
5010+ }
5011+ else
5012+ {
5013+ std::string reply;
5014+ std::istringstream iss(szBuffer);
5015+ while(getline(iss, reply))
5016+ {
5017+ Handle_IRC(reply);
5018+ }
5019+ }
5020+ }
5021+}
5022\ No newline at end of file
5023diff --git a/src/game/mangchat/MCS_OnlinePlayers.cpp b/src/game/mangchat/MCS_OnlinePlayers.cpp
5024new file mode 100644
5025index 0000000..4b95593
5026--- a/src/game/mangchat/MCS_OnlinePlayers.cpp
5027+++ b/src/game/mangchat/MCS_OnlinePlayers.cpp
5028@@ -0,0 +1,84 @@
5029+/*
5030+ * MangChat By |Death| And Cybrax
5031+ *
5032+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
5033+ * Of The GNU General Public License
5034+ * Written and Developed by Cybrax. cybraxvd@gmail.com
5035+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
5036+ * With Help And Support From The MaNGOS Project Community.
5037+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
5038+ */
5039+#include "MCS_OnlinePlayers.h"
5040+
5041+#include "../MapManager.h"
5042+#include "../ObjectMgr.h"
5043+#include "../Config/ConfigEnv.h"
5044+
5045+mcs_OnlinePlayers::mcs_OnlinePlayers() { CD = NULL; }
5046+
5047+mcs_OnlinePlayers::mcs_OnlinePlayers(_CDATA *_CD)
5048+{
5049+ //create a new instance of data struct and copy its data
5050+ CD = new _CDATA();
5051+ CD->CMD = _CD->CMD;
5052+ CD->FROM = _CD->FROM;
5053+ CD->PARAMS = _CD->PARAMS;
5054+ CD->PCOUNT = _CD->PCOUNT;
5055+ CD->USER = _CD->USER;
5056+ CD->TYPE = _CD->TYPE;
5057+}
5058+
5059+mcs_OnlinePlayers::~mcs_OnlinePlayers()
5060+{
5061+ if(CD)
5062+ delete CD;
5063+}
5064+
5065+void mcs_OnlinePlayers::run()
5066+{
5067+ int OnlineCount = 0;
5068+ std::string IRCOut = "";
5069+ HashMapHolder<Player>::MapType& m = ObjectAccessor::Instance().GetPlayers();
5070+ for(HashMapHolder<Player>::MapType::iterator itr = m.begin(); itr != m.end(); ++itr)
5071+ {
5072+ if (itr->second && itr->second->GetSession()->GetPlayer() && itr->second->GetSession()->GetPlayer()->IsInWorld())
5073+ {
5074+ OnlineCount++;
5075+ Player *plr = itr->second->GetSession()->GetPlayer();
5076+ std::string ChatTag = " ";
5077+ switch(plr->GetSession()->GetSecurity())
5078+ {
5079+ case 0: ChatTag.append("");break;
5080+ case 1: ChatTag.append("\0037"+sIRC.ojGM1);break;
5081+ case 2: ChatTag.append("\0037"+sIRC.ojGM2);break;
5082+ case 3: ChatTag.append("\0037"+sIRC.ojGM3);break;
5083+ case 4: ChatTag.append("\0037"+sIRC.ojGM4);break;
5084+ case 5: ChatTag.append("\0037"+sIRC.ojGM5);break;
5085+ }
5086+ if(plr->isAFK())
5087+ ChatTag.append("\002\0037<AFK>\003\002");
5088+ else if(plr->isDND())
5089+ ChatTag.append("\002\0037<DND>\003\002");
5090+ switch (plr->GetTeam())
5091+ {
5092+ case 67:ChatTag.append("\0034");break; //horde
5093+ case 469:ChatTag.append("\00312");break; //alliance
5094+ }
5095+
5096+ IRCOut.append(IRCCmd::MakeMsg("%s\002%s\003\017\002(%d)\002\017", ChatTag.c_str(), plr->GetName(), plr->getLevel()));
5097+
5098+ // after XX players have been added to the string
5099+ // output to irc and reset for the next XX
5100+ if(OnlineCount % sIRC.onlrslt == 0)
5101+ {
5102+ sIRC.Send_IRC_Channel(IRCCmd::ChanOrPM(CD), IRCCmd::MakeMsg("\002 %s", IRCOut.c_str()), true, CD->TYPE.c_str());
5103+ IRCOut = "";
5104+ ACE_Based::Thread::Sleep(1000);
5105+ }
5106+ }
5107+ }
5108+ // Remainder in IRCOUT && Total plyersonline
5109+ sIRC.Send_IRC_Channel(IRCCmd::ChanOrPM(CD), IRCCmd::MakeMsg("\002Players Online(%d):\017 %s", OnlineCount, IRCOut.c_str()), true, CD->TYPE);
5110+
5111+ sIRC.Script_Lock[MCS_Players_Online] = false;
5112+}
5113\ No newline at end of file
5114diff --git a/src/game/mangchat/MCS_OnlinePlayers.h b/src/game/mangchat/MCS_OnlinePlayers.h
5115new file mode 100644
5116index 0000000..a14b116
5117--- a/src/game/mangchat/MCS_OnlinePlayers.h
5118+++ b/src/game/mangchat/MCS_OnlinePlayers.h
5119@@ -0,0 +1,27 @@
5120+#ifndef _IRC_CLIENT_ONLINE
5121+#define _IRC_CLIENT_ONLINE
5122+
5123+#include "IRCClient.h"
5124+#include "IRCCmd.h"
5125+
5126+// the reason to run this command multithreaded
5127+// is to be able to "spread" the output over irc
5128+// for servers with high player count
5129+// in order not to freeze the mangchat core with sleep
5130+// a new thread is spawned it will output the player data
5131+// evry "10 players" and pauzes to not spam irc
5132+// in addition the command is locked so i cannot be used
5133+// while active.
5134+
5135+class mcs_OnlinePlayers : public ACE_Based::Runnable
5136+{
5137+ public:
5138+ mcs_OnlinePlayers();
5139+ mcs_OnlinePlayers(_CDATA *_CD);
5140+ ~mcs_OnlinePlayers();
5141+ void run();
5142+ public:
5143+ _CDATA *CD;
5144+};
5145+
5146+#endif
5147\ No newline at end of file
5148diff --git a/src/mangosd/Main.cpp b/src/mangosd/Main.cpp
5149index 24c372b..f68b5af 100644
5150--- a/src/mangosd/Main.cpp
5151+++ b/src/mangosd/Main.cpp
5152@@ -26,6 +26,8 @@
5153 #include "Log.h"
5154 #include "Master.h"
5155 #include "SystemConfig.h"
5156+#include "../game/mangchat/IRCConf.h"
5157+#include "../game/mangchat/IRCClient.h"
5158 #include "revision.h"
5159 #include "revision_nr.h"
5160 #include <openssl/opensslv.h>
5161@@ -59,6 +61,7 @@ void usage(const char *prog)
5162 sLog.outString("Usage: \n %s [<options>]\n"
5163 " --version print version and exist\n\r"
5164 " -c config_file use config_file as configuration file\n\r"
5165+ " -m MangChat_config use MangChat_config as configuration file for MangChat\n\r"
5166 #ifdef WIN32
5167 " Running as service functions:\n\r"
5168 " --service run as service\n\r"
5169@@ -77,6 +80,7 @@ extern int main(int argc, char **argv)
5170 //char *leak = new char[1000]; // test leak detection
5171
5172 ///- Command line parsing to get the configuration file name
5173+ char const* mc_cfg_file = _MangChat_CONFIG;
5174 char const* cfg_file = _MANGOSD_CONFIG;
5175 int c=1;
5176 while( c < argc )
5177@@ -91,6 +95,18 @@ extern int main(int argc, char **argv)
5178 cfg_file = argv[c];
5179 }
5180
5181+ if( strcmp(argv[c],"-m") == 0)
5182+ {
5183+ if( ++c >= argc )
5184+ {
5185+ sLog.outError("Runtime-Error: -m requires the name of the mangchat config file you would like to use. ");
5186+ usage(argv[0]);
5187+ return 1;
5188+ }
5189+ else
5190+ mc_cfg_file = argv[c];
5191+ }
5192+
5193 if( strcmp(argv[c],"--version") == 0)
5194 {
5195 printf("%s\n", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID));
5196@@ -142,6 +158,8 @@ extern int main(int argc, char **argv)
5197 sLog.outError("Could not find configuration file %s.", cfg_file);
5198 return 1;
5199 }
5200+
5201+ sIRC.SetCfg(mc_cfg_file);
5202
5203 sLog.outString( "%s [world-daemon]", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID) );
5204 sLog.outString( "<Ctrl-C> to stop.\n\n" );
5205diff --git a/src/mangosd/Makefile.am b/src/mangosd/Makefile.am
5206index d853203..a23a045 100644
5207--- a/src/mangosd/Makefile.am
5208+++ b/src/mangosd/Makefile.am
5209@@ -39,11 +39,14 @@ mangos_worldd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/g3dlite -L../bin
5210 ## Additional files to include when running 'make dist'
5211 # Include world daemon configuration
5212 EXTRA_DIST = \
5213- mangosd.conf.dist
5214+ mangosd.conf.dist \
5215+ mangchat.conf.dist
5216+
5217
5218 ## Additional files to install
5219 sysconf_DATA = \
5220- mangosd.conf.dist
5221+ mangosd.conf.dist \
5222+ mangchat.conf.dist
5223
5224 install-data-hook:
5225 @list='$(sysconf_DATA)'
5226diff --git a/src/mangosd/Master.cpp b/src/mangosd/Master.cpp
5227index b6c2c2e..a840f39 100644
5228--- a/src/mangosd/Master.cpp
5229+++ b/src/mangosd/Master.cpp
5230@@ -38,6 +38,7 @@
5231 #include "RASocket.h"
5232 #include "ScriptCalls.h"
5233 #include "Util.h"
5234+#include "mangchat/IRCClient.h"
5235
5236 #include "sockets/TcpSocket.h"
5237 #include "sockets/Utility.h"
5238@@ -216,6 +217,9 @@ int Master::Run()
5239 if (!_StartDB())
5240 return 1;
5241
5242+ ///- Load MangChat Config (MangChat needs DB for gm levels, AutoBroadcast uses world timers)
5243+ sIRC.LoadConfig(sIRC.CfgFile);
5244+
5245 ///- Initialize the World
5246 sWorld.SetInitialWorldSettings();
5247
5248@@ -294,6 +298,13 @@ int Master::Run()
5249 uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / socketSelecttime));
5250 uint32 loopCounter = 0;
5251
5252+ // Start up MangChat
5253+ ACE_Based::Thread irc(*new IRCClient);
5254+ ACE_Based::Low;
5255+
5256+ // ACE_Based::Thread irc(new IRCClient);
5257+ // irc.setPriority ((ACE_Based::Priority::Low);
5258+
5259 ///- Start up freeze catcher thread
5260 uint32 freeze_delay = sConfig.GetIntDefault("MaxCoreStuckTime", 0);
5261 if(freeze_delay)
5262diff --git a/src/mangosd/mangchat.conf.dist.in b/src/mangosd/mangchat.conf.dist.in
5263new file mode 100644
5264index 0000000..9d75f07
5265--- /dev/null
5266+++ b/src/mangosd/mangchat.conf.dist.in
5267@@ -0,0 +1,228 @@
5268+###################################################################################################################
5269+# MangChat IRC BOT FOR MaNGOS Configuration File #
5270+##################################################
5271+# irc.active
5272+# Enable MangChat Addon
5273+# Default: 1 - Enable
5274+# 0 - Disable
5275+#
5276+irc.active = 1
5277+
5278+##################################################
5279+# irc.icc
5280+# IRC connect code
5281+# Default: 001 - Welcome To Network msg
5282+# 375 - Beginning Of MOTD
5283+# 376 - End Of MOTD
5284+#
5285+irc.icc = 001
5286+
5287+##################################################
5288+# irc.host
5289+# IRC server to have MangChat connect to
5290+#
5291+irc.host = "irc.freenode.net"
5292+
5293+##################################################
5294+# irc.port
5295+# IRC server port to use
5296+#
5297+irc.port = "6667"
5298+
5299+##################################################
5300+# irc.user
5301+# The username to have MangChat use to connect to the IRC server
5302+# irc.nick
5303+# IRC nickname to be used by the bot
5304+# irc.pass
5305+# The password to be used to identify to NickServ (IRC NickName Enforcement Services)
5306+#
5307+irc.user = "MangChat"
5308+irc.nick = "MangChat"
5309+irc.pass = "MyDumbPass"
5310+
5311+##################################################
5312+# irc.auth
5313+# IRC Authentication Method
5314+# Default: 0 - Disable
5315+# 1 - NickServ - Normal Method - PRIVMSG NickServ :IDENTIFY Password
5316+# 2 - NickServ - Alternate Method To Identify To A Different Nick - PRIVMSG NickServ :IDENTIFY irc.auth.nick Password
5317+# 3 - QuakeNet - Normal Method - PRIVMSG Q@CServe.quakenet.org :AUTH irc.nick Password
5318+# 4 - QuakeNet - Alternate Method To Identify To A Different Nick - PRIVMSG Q@CServe.quakenet.org :AUTH irc.auth.nick Password
5319+# irc.auth.nick
5320+# IRC Nickname to use if Auth method 2 or 4 is used
5321+#
5322+irc.auth = 1
5323+irc.auth.nick = "AuthNick"
5324+
5325+##################################################
5326+# irc.ldef
5327+# Leave a defined IRC channel on server connect
5328+# Default: 0 - Disable
5329+# 1 - Enable
5330+# irc.defchan
5331+# IRC channel to leave on server connect if irc.ldef is on
5332+#
5333+irc.ldef = 0
5334+irc.defchan = "lobby"
5335+
5336+##################################################
5337+# irc.wct
5338+# Time to wait before (re)attemptimg connection to IRC server
5339+# Default: 30000 - (30 Seconds)
5340+# irc.maxattempt
5341+# Maximum attempts to try IRC server
5342+# Default: 20
5343+#
5344+irc.wct = 30000
5345+irc.maxattempt = 20
5346+
5347+##################################################
5348+# irc.auto.announce
5349+# Time to wait in Minutes to announce random messages from database.
5350+# Default: 30 - (30 Minutes)
5351+#
5352+irc.auto.announce = 30
5353+
5354+##################################################
5355+# irc.autojoin_kick
5356+# Autojoin IRC channel if kicked
5357+# Default: 1 - Enable
5358+# 0 - Disable
5359+#
5360+irc.autojoin_kick = 1
5361+
5362+##################################################
5363+# irc.command_prefix
5364+# IRC command prefix
5365+# Example: (.)online all
5366+#
5367+irc.command_prefix = "."
5368+
5369+##################################################
5370+# irc.joinmsg
5371+# irc.rstmsg
5372+# irc.kickmsg
5373+# MangChat bot join/restart/kick messages
5374+#
5375+irc.joinmsg = "Whhaaazzzzaaaa, MangChat $Ver Is Up And Running! Command Trigger Is: $Trigger"
5376+irc.rstmsg = "MangChat Is Restarting, I Will Be Right Back!!"
5377+irc.kickmsg = "Do Not Kick Me Again, Severe Actions Will Be Taken!"
5378+
5379+##################################################
5380+# irc.chan_#
5381+# wow.chan_#
5382+# IRC and WOW channels to link. Leave # out of IRC channel. Both channels _ARE_ case sensitive
5383+# Example: irc.chan_1 = "Mangos"
5384+# irc.chan_2 = "mangos2"
5385+# wow.chan_1 = "world"
5386+# wow.chan_2 = "LookingForGroup"
5387+#
5388+irc.chan_1 = "mangos"
5389+wow.chan_1 = "world"
5390+
5391+##################################################
5392+# irc.StatusChannel
5393+# Channel Number To Display Status Messages In (AuctionHouse, Levels, Deaths, Etc)
5394+# Default: 1 - Channel ID 1
5395+# irc.AnnounceChannel
5396+# Channel Number To Display Announcements In (Announces, Notifies, Event)
5397+# Default: 1 - Channel ID 1
5398+#
5399+irc.StatusChannel = 1
5400+irc.AnnounceChannel = 1
5401+
5402+##################################################
5403+# irc.op_gm_login
5404+# Op The GM In All Channels The Bot Is On When They Log In To MangChat
5405+# Default: 0 - Disable
5406+# 1 - Enable
5407+# irc.op_gm_level
5408+# The Minimum GM Level Required To Have The Bot Op The User
5409+# Default: 5 - GM Level 5
5410+#
5411+irc.op_gm_login = 0
5412+irc.op_gm_level = 3
5413+
5414+##################################################
5415+# irc.ajoin (Experimental/Under Development)
5416+# Force players to autojoin a WOW in game channel
5417+# Atleast one player must be in the channel on server start, and atleast one person online for invite to work
5418+# Default: 0 - Disable
5419+# 1 - Enable
5420+# irc.ajchan
5421+# Channel to join if above is Enabled.
5422+#
5423+irc.ajoin = 1
5424+irc.ajchan = "world"
5425+
5426+##################################################
5427+# irc.online.result
5428+# Maximum number of results per line for the online command
5429+#
5430+irc.online.result = 30
5431+
5432+##################################################
5433+# chat.*** (Defineable Strings) (maybe more in future)
5434+# wow_* - String is displayed in IRC channel
5435+# irc_* - String is displayed in WOW channel
5436+# Options: $Name, $Level, $Msg, $GM (not all options work in every string)
5437+#
5438+chat.wow_irc = "<WoW>[$Name($Level)] $Msg"
5439+chat.irc_wow = "<IRC>[$Name]: $Msg"
5440+chat.join_wow = "12>>04 $GM$Name Joined The $Channel Channel!"
5441+chat.join_irc = "[$Name]: Has Joined IRC!"
5442+chat.leave_wow = "12<<04 $GM$Name Left The $Channel Channel!"
5443+chat.leave_irc = "[$Name]: Has Left IRC!"
5444+chat.change_nick = "<> $Name Is Now Known As $NewName!"
5445+
5446+##################################################
5447+# Botmask
5448+# This defines what the bot announces, if its 0 everything is disabled
5449+# simply add the values of the elements you want to create this mask.
5450+# Example: WoW join/leaves are 1 and IRC join/leaves are 2, if you want both of these active then the BotMask is 3.
5451+# (1)Display WoW Chan Join/Leaves In IRC
5452+# (2)Display IRC Chan Join/Leaves/NickChanges In WoW
5453+# (4)Display Unknown Command Message When Trigger Is Used And No Command Exists
5454+# (8)Announce Security Level > 0 As GM At Login
5455+# (16)Announce GM In GM ON State AS GM At Login
5456+# (32)Return Errors To Notice. (If disabled then default is Private Message)
5457+# (64)Display WoW Status Messages (Levels/Deaths)
5458+# (128)Display Nick Changes From IRC In WOW
5459+# (256)Display WoW Announces/Notifies In IRC
5460+# (512)Do Not Let Players Use Commands On Higher GM Level Players
5461+# (1024)Enable AuctionHouse Announcements
5462+#
5463+Botmask = 1023
5464+
5465+##################################################
5466+# irc.gmlog
5467+# Minimum GM level to not show login/pass info in IRC logs
5468+# irc.logfile.prefix
5469+# The prefix of the IRC logfile. Directories can be added here.
5470+# Example: "IRC/IRC_" outputs IRC_YYYY-MM-DD.log to the IRC subdirectory in your logs dir
5471+#
5472+irc.gmlog = 1
5473+irc.logfile.prefix = "IRC_"
5474+
5475+##################################################
5476+# irc.fun.games (Experimental/Under Development)
5477+# Enable MangChat Games
5478+# Default: 0 - Disable
5479+# 1 - Enable
5480+#
5481+irc.fun.games = 0
5482+
5483+##################################################
5484+# irc.gm#
5485+# GM tag to append to (GM onjoin / online command) IRC color codes are acceptable
5486+#
5487+irc.gm1 = "[Moderator]"
5488+irc.gm2 = "[Game Master]"
5489+irc.gm3 = "[BugTracker]"
5490+irc.gm4 = "[DevTeam Admin]"
5491+irc.gm5 = "[SysOP]"
5492+
5493+##################################################
5494+# End Of MangChat Config File #
5495+###################################################################################################################
5496\ No newline at end of file
5497diff --git a/src/shared/Makefile.am b/src/shared/Makefile.am
5498index e72c2fb..13b2b53 100644
5499--- a/src/shared/Makefile.am
5500+++ b/src/shared/Makefile.am
5501@@ -71,7 +71,8 @@ EXTRA_DIST = \
5502
5503 # System configuration
5504 EXTRA_DIST += \
5505- SystemConfig.h
5506+ SystemConfig.h \
5507+ ../game/mangchat/IRCConf.h
5508
5509 # System Win32 files
5510 EXTRA_DIST += \
5511diff --git a/win/VC80/game.vcproj b/win/VC80/game.vcproj
5512index e4b1c45..e4f5b79 100644
5513--- a/win/VC80/game.vcproj
5514+++ b/win/VC80/game.vcproj
5515@@ -1590,6 +1590,62 @@
5516 >
5517 </File>
5518 </Filter>
5519+ <Filter
5520+ Name="IRC"
5521+ >
5522+ <File
5523+ RelativePath="..\..\src\game\mangchat\IRCClient.cpp"
5524+ >
5525+ </File>
5526+ <File
5527+ RelativePath="..\..\src\game\mangchat\IRCClient.h"
5528+ >
5529+ </File>
5530+ <File
5531+ RelativePath="..\..\src\game\mangchat\IRCCmd.cpp"
5532+ >
5533+ </File>
5534+ <File
5535+ RelativePath="..\..\src\game\mangchat\IRCCmd.h"
5536+ >
5537+ </File>
5538+ <File
5539+ RelativePath="..\..\src\game\mangchat\IRCCmde.cpp"
5540+ >
5541+ </File>
5542+ <File
5543+ RelativePath="..\..\src\game\mangchat\IRCConf.cpp"
5544+ >
5545+ </File>
5546+ <File
5547+ RelativePath="..\..\src\game\mangchat\IRCFunc.h"
5548+ >
5549+ </File>
5550+ <File
5551+ RelativePath="..\..\src\game\mangchat\IRCIO.cpp"
5552+ >
5553+ </File>
5554+ <File
5555+ RelativePath="..\..\src\game\mangchat\IRCLog.cpp"
5556+ >
5557+ </File>
5558+ <File
5559+ RelativePath="..\..\src\game\mangchat\IRCLog.h"
5560+ >
5561+ </File>
5562+ <File
5563+ RelativePath="..\..\src\game\mangchat\IRCSock.cpp"
5564+ >
5565+ </File>
5566+ <File
5567+ RelativePath="..\..\src\game\mangchat\MCS_OnlinePlayers.cpp"
5568+ >
5569+ </File>
5570+ <File
5571+ RelativePath="..\..\src\game\mangchat\MCS_OnlinePlayers.h"
5572+ >
5573+ </File>
5574+ </Filter>
5575 <File
5576 RelativePath="..\..\src\game\pchdef.cpp"
5577 >
5578diff --git a/win/VC80/mangosd.vcproj b/win/VC80/mangosd.vcproj
5579index 9b49a89..7fea791 100644
5580--- a/win/VC80/mangosd.vcproj
5581+++ b/win/VC80/mangosd.vcproj
5582@@ -1,7 +1,7 @@
5583 <?xml version="1.0" encoding="Windows-1252"?>
5584 <VisualStudioProject
5585 ProjectType="Visual C++"
5586- Version="8,00"
5587+ Version="8.00"
5588 Name="mangosd"
5589 ProjectGUID="{A3A04E47-43A2-4C08-90B3-029CEF558594}"
5590 RootNamespace="mangosd"
5591diff --git a/win/VC90/game.vcproj b/win/VC90/game.vcproj
5592index a634b2e..163b835 100644
5593--- a/win/VC90/game.vcproj
5594+++ b/win/VC90/game.vcproj
5595@@ -1590,6 +1590,62 @@
5596 >
5597 </File>
5598 </Filter>
5599+ <Filter
5600+ Name="IRC"
5601+ >
5602+ <File
5603+ RelativePath="..\..\src\game\mangchat\IRCClient.cpp"
5604+ >
5605+ </File>
5606+ <File
5607+ RelativePath="..\..\src\game\mangchat\IRCClient.h"
5608+ >
5609+ </File>
5610+ <File
5611+ RelativePath="..\..\src\game\mangchat\IRCCmd.cpp"
5612+ >
5613+ </File>
5614+ <File
5615+ RelativePath="..\..\src\game\mangchat\IRCCmd.h"
5616+ >
5617+ </File>
5618+ <File
5619+ RelativePath="..\..\src\game\mangchat\IRCCmde.cpp"
5620+ >
5621+ </File>
5622+ <File
5623+ RelativePath="..\..\src\game\mangchat\IRCConf.cpp"
5624+ >
5625+ </File>
5626+ <File
5627+ RelativePath="..\..\src\game\mangchat\IRCFunc.h"
5628+ >
5629+ </File>
5630+ <File
5631+ RelativePath="..\..\src\game\mangchat\IRCIO.cpp"
5632+ >
5633+ </File>
5634+ <File
5635+ RelativePath="..\..\src\game\mangchat\IRCLog.cpp"
5636+ >
5637+ </File>
5638+ <File
5639+ RelativePath="..\..\src\game\mangchat\IRCLog.h"
5640+ >
5641+ </File>
5642+ <File
5643+ RelativePath="..\..\src\game\mangchat\IRCSock.cpp"
5644+ >
5645+ </File>
5646+ <File
5647+ RelativePath="..\..\src\game\mangchat\MCS_OnlinePlayers.cpp"
5648+ >
5649+ </File>
5650+ <File
5651+ RelativePath="..\..\src\game\mangchat\MCS_OnlinePlayers.h"
5652+ >
5653+ </File>
5654+ </Filter>
5655 <File
5656 RelativePath="..\..\src\game\pchdef.cpp"
5657 >