aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorXTZGZoReX <none@none>2008-10-12 14:03:38 -0500
committerXTZGZoReX <none@none>2008-10-12 14:03:38 -0500
commit054725122f1ef534063ffcbc54b25e167ec3ed9c (patch)
treee476f95db36b0599d54b74eb01d850d212a09d21 /src
parente539b4ca7f89eaaf3efe4cffea7e143f41fc592b (diff)
[svn] * Various small changes here and there.
* Implementing MangChat IRC system. * Added new config option, MAX_WHO, can be used to set the limit of characters being sent in a /who request from client. --HG-- branch : trunk
Diffstat (limited to 'src')
-rw-r--r--src/game/AuctionHouse.cpp4
-rw-r--r--src/game/Channel.cpp12
-rw-r--r--src/game/Chat.cpp1
-rw-r--r--src/game/Chat.h2
-rw-r--r--src/game/ChatHandler.cpp3
-rw-r--r--src/game/GameEvent.cpp9
-rw-r--r--src/game/IRCClient.cpp91
-rw-r--r--src/game/IRCClient.h230
-rw-r--r--src/game/IRCCmd.cpp827
-rw-r--r--src/game/IRCCmd.h117
-rw-r--r--src/game/IRCCmde.cpp1884
-rw-r--r--src/game/IRCConf.cpp172
-rw-r--r--src/game/IRCConf.h16
-rw-r--r--src/game/IRCConf.h.in16
-rw-r--r--src/game/IRCFunc.h251
-rw-r--r--src/game/IRCIO.cpp436
-rw-r--r--src/game/IRCLog.cpp60
-rw-r--r--src/game/IRCLog.h22
-rw-r--r--src/game/IRCSock.cpp146
-rw-r--r--src/game/Language.h2
-rw-r--r--src/game/Level1.cpp35
-rw-r--r--src/game/MCS_OnlinePlayers.cpp84
-rw-r--r--src/game/MCS_OnlinePlayers.h27
-rw-r--r--src/game/Makefile.am15
-rw-r--r--src/game/MiscHandler.cpp5
-rw-r--r--src/game/Player.cpp14
-rw-r--r--src/game/World.cpp36
-rw-r--r--src/game/World.h9
-rw-r--r--src/shared/Database/DBCStructure.h1
-rw-r--r--src/shared/Database/DBCfmt.cpp3
-rw-r--r--src/shared/Makefile.am1
-rw-r--r--src/trinitycore/CliRunnable.cpp9
-rw-r--r--src/trinitycore/Main.cpp6
-rw-r--r--src/trinitycore/Master.cpp10
-rw-r--r--src/trinitycore/trinitycore.conf.dist193
35 files changed, 4733 insertions, 16 deletions
diff --git a/src/game/AuctionHouse.cpp b/src/game/AuctionHouse.cpp
index 9b527400b04..b6eda29ac26 100644
--- a/src/game/AuctionHouse.cpp
+++ b/src/game/AuctionHouse.cpp
@@ -26,6 +26,7 @@
#include "UpdateMask.h"
#include "AuctionHouseObject.h"
#include "Util.h"
+#include "IRCClient.h"
//please DO NOT use iterator++, because it is slower than ++iterator!!!
//post-incrementation is always slower than pre-incrementation !
@@ -313,6 +314,9 @@ void WorldSession::HandleAuctionSellItem( WorldPacket & recv_data )
pl->SaveInventoryAndGoldToDB();
CharacterDatabase.CommitTransaction();
+ if((sIRC.BOTMASK & 1024) != 0)
+ sIRC.AHFunc(it->GetEntry(), it->GetProto()->Name1, pl->GetName(), location);
+
SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK);
}
diff --git a/src/game/Channel.cpp b/src/game/Channel.cpp
index 0fff8c7854b..a6a97a61656 100644
--- a/src/game/Channel.cpp
+++ b/src/game/Channel.cpp
@@ -20,6 +20,7 @@
#include "ObjectMgr.h"
#include "World.h"
#include "SocialMgr.h"
+#include "IRCClient.h"
Channel::Channel(std::string name, uint32 channel_id)
: m_name(name), m_announce(true), m_moderate(false), m_channelId(channel_id), m_ownerGUID(0), m_password(""), m_flags(0)
@@ -112,14 +113,9 @@ void Channel::Join(uint64 p, const char *pass)
MakeYouJoined(&data);
SendToOne(&data, p);
- JoinNotify(p);
+ sIRC.Handle_WoW_Channel(m_name, objmgr.GetPlayer(p), CHANNEL_JOIN);
- // if no owner first logged will become
- if(!IsConstant() && !m_ownerGUID)
- {
- SetOwner(p, (players.size() > 1 ? true : false));
- players[p].SetModerator(true);
- }
+ JoinNotify(p);
}
void Channel::Leave(uint64 p, bool send)
@@ -159,6 +155,8 @@ void Channel::Leave(uint64 p, bool send)
LeaveNotify(p);
+ sIRC.Handle_WoW_Channel(m_name, objmgr.GetPlayer(p), CHANNEL_LEAVE);
+
if(changeowner)
{
uint64 newowner = !players.empty() ? players.begin()->second.player : 0;
diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp
index b8e12a5a8b1..ad588c5a18d 100644
--- a/src/game/Chat.cpp
+++ b/src/game/Chat.cpp
@@ -456,6 +456,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "movegens", SEC_ADMINISTRATOR, &ChatHandler::HandleMovegensCommand, "", NULL },
{ "cometome", SEC_ADMINISTRATOR, &ChatHandler::HandleComeToMeCommand, "", NULL },
{ "damage", SEC_ADMINISTRATOR, &ChatHandler::HandleDamageCommand, "", NULL },
+ { "ircpm", SEC_PLAYER, &ChatHandler::HandleIRCpmCommand, "", NULL },
{ "combatstop", SEC_GAMEMASTER, &ChatHandler::HandleCombatStopCommand, "", NULL },
{ "flusharenapoints", SEC_ADMINISTRATOR, &ChatHandler::HandleFlushArenaPointsCommand, "", NULL },
diff --git a/src/game/Chat.h b/src/game/Chat.h
index ff0eac2caa6..28920c4d112 100644
--- a/src/game/Chat.h
+++ b/src/game/Chat.h
@@ -108,6 +108,8 @@ class ChatHandler
bool HandleGroupTeleCommand(const char* args);
bool HandleDrunkCommand(const char* args);
+ bool HandleIRCpmCommand(const char* args);
+
bool HandleEventActiveListCommand(const char* args);
bool HandleEventStartCommand(const char* args);
bool HandleEventStopCommand(const char* args);
diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp
index 80935be78c6..8ccf6788388 100644
--- a/src/game/ChatHandler.cpp
+++ b/src/game/ChatHandler.cpp
@@ -34,6 +34,7 @@
#include "Player.h"
#include "SpellAuras.h"
#include "Language.h"
+#include "IRCClient.h"
#include "Util.h"
void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
@@ -427,6 +428,8 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
if(msg.empty())
break;
+ sIRC.Send_WoW_IRC(_player, channel, msg);
+
if(ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
{
if(Channel *chn = cMgr->GetChannel(channel,_player))
diff --git a/src/game/GameEvent.cpp b/src/game/GameEvent.cpp
index e36cb6caae8..5380acf6ace 100644
--- a/src/game/GameEvent.cpp
+++ b/src/game/GameEvent.cpp
@@ -24,6 +24,7 @@
#include "Log.h"
#include "MapManager.h"
#include "Policies/SingletonImp.h"
+#include "IRCClient.h"
INSTANTIATE_SINGLETON_1(GameEvent);
@@ -421,6 +422,14 @@ void GameEvent::ApplyNewEvent(uint16 event_id)
}
sLog.outString("GameEvent %u \"%s\" started.", event_id, mGameEvent[event_id].description.c_str());
+
+ if((sIRC.BOTMASK & 256) != 0)
+ {
+ std::string ircchan = "#";
+ ircchan += sIRC._irc_chan[sIRC.anchn].c_str();
+ 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);
+ }
+
// spawn positive event tagget objects
GameEventSpawn(event_id);
// un-spawn negative event tagged objects
diff --git a/src/game/IRCClient.cpp b/src/game/IRCClient.cpp
new file mode 100644
index 00000000000..0cd6e7d5dcf
--- /dev/null
+++ b/src/game/IRCClient.cpp
@@ -0,0 +1,91 @@
+/*
+ * MangChat By |Death| And Cybrax
+ *
+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
+ * Of The GNU General Public License
+ * Written and Developed by Cybrax. cybraxvd@gmail.com
+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
+ * With Help And Support From The MaNGOS Project Community.
+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
+ */
+#include "IRCClient.h"
+#include "World.h"
+#include "ObjectMgr.h"
+#include "MapManager.h"
+
+#include "Policies/SingletonImp.h"
+INSTANTIATE_SINGLETON_1( IRCClient );
+
+#ifdef WIN32
+ #define Delay(x) Sleep(x)
+#else
+ #define Delay(x) sleep(x / 1000)
+#endif
+// IRCClient Constructor
+IRCClient::IRCClient()
+{
+ for(int i = 0;i > 5;i++)
+ sIRC.Script_Lock[i] = false;
+}
+// IRCClient Destructor
+IRCClient::~IRCClient(){}
+
+// ZThread Entry This function is called when the thread is created in Master.cpp (mangosd)
+void IRCClient::run()
+{
+ sIRC.iLog.WriteLog(" %s : IRC bot started.", sIRC.iLog.GetLogDateTimeStr().c_str());
+
+ // before we begin we wait a few
+ // mangos is still starting up.
+ ZThread::Thread::sleep(500);
+ int cCount = 0;
+ // Clean Up MySQL Tables
+ sLog.outString("Cleaning up IRC_Inchan table...");
+ WorldDatabase.PExecute("DELETE FROM `IRC_Inchan`");
+ sIRC._Max_Script_Inst = 0;
+ // Create a loop to keep the thread running untill active is set to false
+ while(sIRC.Active && !World::m_stopEvent)
+ {
+ // Initialize socket library
+ if(this->InitSock())
+ {
+ // Connect To The IRC Server
+ sLog.outString("IRC: Connecting to %s Try # %d ******", sIRC._Host.c_str(), cCount);
+ if(this->Connect(sIRC._Host.c_str(), sIRC._Port))
+ {
+ // On connection success reset the connection counter
+ cCount = 0;
+ sLog.outString("IRC connected and logging in");
+ // Login to the IRC server
+ if(this->Login(sIRC._Nick, sIRC._User, sIRC._Pass))
+ {
+ sLog.outString("IRC logged in and running");
+ // While we are connected to the irc server keep listening for data on the socket
+ while(sIRC.Connected && !World::m_stopEvent){ sIRC.SockRecv(); }
+ }
+ sLog.outString("Connection to IRC server lost!");
+ }
+ // When an error occures or connection lost cleanup
+ Disconnect();
+ // Increase the connection counter
+ cCount++;
+ // if MAX_CONNECT_ATTEMPT is reached stop trying
+ if(sIRC._MCA != 0 && cCount == sIRC._MCA)
+ sIRC.Active = false;
+ // If we need to reattempt a connection wait WAIT_CONNECT_TIME milli seconds before we try again
+ if(sIRC.Active)
+ ZThread::Thread::sleep(sIRC._wct);
+ }
+ else
+ {
+ // Socket could not initialize cancel
+ sIRC.Active = false;
+ sLog.outError("IRC: Could not initialize socket");
+ }
+ }
+ // we need to keep the thread alive or mangos will crash
+ // when sending chat or join/leave channels.
+ // even when we are not connected the functions must still
+ // be availlable where chat is sent to so we keep it running
+ while(!World::m_stopEvent){};
+}
diff --git a/src/game/IRCClient.h b/src/game/IRCClient.h
new file mode 100644
index 00000000000..31e7b9fbba9
--- /dev/null
+++ b/src/game/IRCClient.h
@@ -0,0 +1,230 @@
+#ifndef _IRC_CLIENT_H
+#define _IRC_CLIENT_H
+
+#include "Policies/Singleton.h"
+#include "Player.h"
+#include "IRCLog.h"
+#include "IRCCmd.h"
+
+using namespace std;
+// The maximum ammount of channels used
+// in the channel array you can have as much channels as you
+// want, but it is important to always have at least equal or more
+// channels then you specify in your mangosd.conf
+#define MAX_CONF_CHANNELS 10
+#define MAX_CHAT_LINES 10
+// time we need to wait before we try another connecton attempt
+// Default is 30 seconds
+#define MAX_SCRIPT_INST 10
+// CLINES is used for the default chatlines
+// By using the GetChatLine function its easier and faster
+// to receieve the line you need.
+enum CLINES
+{
+ IRC_WOW = 0,
+ WOW_IRC = 1,
+ JOIN_WOW = 2,
+ JOIN_IRC = 3,
+ LEAVE_WOW = 4,
+ LEAVE_IRC = 5,
+ CHANGE_NICK = 6
+}; // Chatlines
+// CACTION is used by the Handle_WoW_Channel function
+// this function is called in channel.h when a player
+// joins or leave a channel inside the client.
+enum CACTION
+{
+ CHANNEL_JOIN,
+ CHANNEL_LEAVE,
+};
+
+enum script_Names
+{
+ MCS_Players_Online = 0,
+};
+
+// IRCClient main class
+class IRCClient : public ZThread::Runnable
+{
+ public:
+ // IRCClient Constructor
+ IRCClient();
+ // IRCClient Destructor
+ ~IRCClient();
+ // ZThread Entry
+ void run();
+ public:
+ // AH Function
+ void AHFunc(uint64 itmid, std::string itmnme, std::string plname, uint32 faction);
+ // IRCClient active
+ bool Active;
+ // Connected to IRC
+ bool Connected;
+ // Socket indentifier
+ int SOCKET;
+ fd_set sfdset;
+ // Send data to IRC, in addition the endline is added \n
+ bool SendIRC(std::string data);
+ // This function is called in ChatHandler.cpp and processes the chat from game to IRC
+ void Send_WoW_IRC(Player *plr, std::string Channel, std::string Msg);
+ // Sends a message to all players on the specified channel
+ void Send_WoW_Channel(const char *channel, std::string chat);
+ // Send a system message to all players
+ void Send_WoW_System(std::string Message);
+ // Send a message to the specified IRC channel
+ void Send_IRC_Channel(std::string sChannel, std::string sMsg, bool NoPrefix = false, std::string nType = "PRIVMSG");
+ // Sends a message to all IRC Channels
+ void Send_IRC_Channels(std::string sMsg);
+ std::string MakeMsg(std::string msg, std::string var, std::string val)
+ {
+ std::size_t start = msg.find(var);
+ if (start != std::string::npos)
+ msg.replace(start, var.length(), val);
+ return msg;
+ }
+ void Send_WoW_Player(string sPlayer, string sMsg);
+ void Send_WoW_Player(Player *plr, string sMsg);
+
+ // This function is called in Channel.cpp and processes Join/leave messages
+ void Handle_WoW_Channel(std::string Channel, Player *plr, int nAction);
+ void ResetIRC();
+ public:
+ void AutoJoinChannel(Player *plr);
+
+ public:
+ bool Script_Lock[5];
+ bool _AmiOp;
+
+ public:
+ string _Mver;
+ // IRC Server host
+ string _Host;
+ // IRC Server Port
+ int _Port;
+ // IRC Username
+ string _User;
+ // IRC Password
+ string _Pass;
+ // IRC Nickname
+ string _Nick;
+ // Authentication type
+ int _Auth;
+ string _Auth_Nick;
+ // IRC Connect code
+ string _ICC;
+ // IRC Default channel
+ string _defchan;
+ // IRC Leave Default channel
+ int _ldefc;
+ // Wait Connect Time
+ int _wct;
+ // BotMask Options
+ int Botmask;
+ // Status Channel
+ int Status;
+ // Announce Channel
+ int anchn;
+ int autoanc;
+ // IRC Channel count
+ int _chan_count;
+ // IRC Channel list
+ // Array to store our IRC channels
+ // each element will corrospond
+ // with _wow_chan array below.
+ std::string _irc_chan[MAX_CONF_CHANNELS];
+ // Game Channel list
+ std::string _wow_chan[MAX_CONF_CHANNELS];
+ // AutoJoin Options
+ int ajoin;
+ string ajchan;
+ // Online Command Max Results
+ int onlrslt;
+ // Channel OnJoin/Restart/Kick Messages
+ string JoinMsg;
+ string RstMsg;
+ string kikmsg;
+ // Misc Options
+ string ojGM1;
+ string ojGM2;
+ string ojGM3;
+ string ojGM4;
+ string ojGM5;
+ string logfile;
+ int games;
+ int gmlog;
+ // IRC Commands Security Level
+ int CACCT;
+ int CBAN;
+ int CCHAN;
+ int CCHAR;
+ int CFUN;
+ int CHELP;
+ int CINCHAN;
+ int CINFO;
+ int CITEM;
+ int CJAIL;
+ int CKICK;
+ int _KILL;
+ int CLEVEL;
+ int CLOOKUP;
+ int CMONEY;
+ int CMUTE;
+ int CONLINE;
+ int CPM;
+ int CRESTART;
+ int CREVIVE;
+ int CSAVEALL;
+ int CSHUTDOWN;
+ int CSPELL;
+ int CSYSMSG;
+ int CTELE;
+ int CTOP;
+ int CWHO;
+ // BotMask
+ int BOTMASK;
+ // Max connect attempt
+ int _MCA;
+ // Auto rejoin when kicked from irc
+ int _autojoinkick;
+ // IRC Command prefix
+ string _cmd_prefx;
+ int _op_gm;
+ int _op_gm_lev;
+ // Array that contains our chatlines from the conf file
+ // To increase this value change the MAX_CHAT_LINE define above
+ // Make sure the number of elements must match your items
+ // (remeber this starts at 0 so 0..9 is 10 items)
+ // and that you load the line in the LoadConfig function.
+ string ILINES[MAX_CHAT_LINES];
+ string GetChatLine(int nItem);
+
+ int _Max_Script_Inst;
+ // MAX_SCRIPT_INST
+
+ IRCLog iLog;
+
+public:
+ // Load MangChat configuration file
+ bool LoadConfig(char const* cfgfile);
+ void SetCfg(char const* cfgfile);
+ char const* CfgFile;
+
+private:
+ // Returns default chatline based on enum CLINES
+ // Initialize socket library
+ bool InitSock();
+ // Connect to IRC Server
+ bool Connect(const char *cHost, int nPort);
+ // Login to IRC Server
+ bool Login(std::string sNick, std::string sUser, std::string sPass);
+ // Send raw data to IRC
+ bool SendData(const char *data);
+ // Disconnect from IRC and cleanup socket
+ void Disconnect();
+ // Processes the data receieved from IRC
+ void Handle_IRC(std::string sData);
+ // Receieves data from the socket.
+ void SockRecv();
+};
+#endif
+#define sIRC MaNGOS::Singleton<IRCClient>::Instance()
diff --git a/src/game/IRCCmd.cpp b/src/game/IRCCmd.cpp
new file mode 100644
index 00000000000..62e5e565d75
--- /dev/null
+++ b/src/game/IRCCmd.cpp
@@ -0,0 +1,827 @@
+/*
+ * MangChat By |Death| And Cybrax
+ *
+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
+ * Of The GNU General Public License
+ * Written and Developed by Cybrax. cybraxvd@gmail.com
+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
+ * With Help And Support From The MaNGOS Project Community.
+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
+ */
+#include "IRCCmd.h"
+#include "IRCClient.h"
+#include "Database/DatabaseEnv.h"
+#include "ObjectMgr.h"
+#include "MapManager.h"
+// Constructor
+IRCCmd::IRCCmd(){}
+// Destructor
+IRCCmd::~IRCCmd(){}
+
+std::string IRCCmd::MakeUpper(std::string Channel)
+{
+ std::string tmpchan = Channel;
+ std::transform(tmpchan.begin(), tmpchan.end(), tmpchan.begin(), towupper);
+ return tmpchan;
+}
+bool IRCCmd::ParamsValid(_CDATA *CD, int pCnt)
+{
+ CD->PCOUNT = pCnt;
+ if(CD->PARAMS.size() == 0)
+ return false;
+ return ValidParams(CD->PARAMS, pCnt);
+}
+
+int IRCCmd::ParamsValid(_CDATA *CD, int pCnt, int rLev)
+{
+ //CD->PCOUNT = pCnt;
+ if(!CanUse(CD->USER, rLev))
+ return E_AUTH;
+ else if(pCnt == 0)
+ return E_OK;
+ else if(CD->PARAMS.size() == 0)
+ return E_SIZE;
+ else if(!ValidParams(CD->PARAMS, pCnt))
+ return E_SIZE;
+ return E_OK;
+}
+
+// This function checks if chat from irc is a command or not
+// return true on yes and false on no
+bool IRCCmd::IsValid(std::string USER, std::string FROM, std::string CHAT, std::string TYPE)
+{
+ // If the first line of our chat is the command prefix we have a command
+ if(CHAT.substr(0, 1) == sIRC._cmd_prefx && CHAT.size() > 1 )
+ {
+ _CDATA CDATA;
+ bool cValid = false;
+ bool AuthValid = true;
+ bool dontlog = true;
+ std::string* _PARAMS = getArray(CHAT, 2);
+ CDATA.USER = USER;
+ CDATA.FROM = FROM;
+ CDATA.TYPE = TYPE;
+ CDATA.PCOUNT = 0;
+ CDATA.CMD = MakeUpper(_PARAMS[0].substr(1, _PARAMS[0].size() - 1));
+ CDATA.PARAMS = _PARAMS[1];
+ if(CDATA.CMD == "LOGIN")
+ {
+ if(FROM == sIRC._Nick)
+ {
+ if(ParamsValid(&CDATA, 2))
+ Handle_Login(&CDATA);
+ else
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"login <Player> <Password> )", true, "ERROR");
+ }
+ else
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Please Send A PM To Login!", true, "ERROR");
+ if(GetLevel(USER) >= sIRC.gmlog)
+ dontlog = false;
+ cValid = true;
+ }
+ else if(CDATA.CMD == "LOGOUT")
+ {
+ if(FROM == sIRC._Nick)
+ {
+ Handle_Logout(&CDATA);
+ }
+ else
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Please Send A PM To Logout!", true, "ERROR");
+ cValid = true;
+ }
+ else if(CDATA.CMD == "ACCT")
+ {
+ switch(ParamsValid(&CDATA, 2, sIRC.CACCT))
+ {
+ case E_OK:
+ Account_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"acct <Player> <(un)lock/mail/pass/rename> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "BAN")
+ {
+ switch(ParamsValid(&CDATA, 2, sIRC.CBAN))
+ {
+ case E_OK:
+ Ban_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"ban <Player> <acct/ip> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "CHAN")
+ {
+ switch(ParamsValid(&CDATA, 1, sIRC.CCHAN))
+ {
+ case E_OK:
+ Chan_Control(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"chan <op> <IRC User> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "CHAR")
+ {
+ switch(ParamsValid(&CDATA, 2, sIRC.CCHAR))
+ {
+ case E_OK:
+ Char_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"char <Player> <mailcheat/taxicheat/maxskill/setskill> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "FUN")
+ {
+ switch(ParamsValid(&CDATA, 2, sIRC.CFUN))
+ {
+ case E_OK:
+ Fun_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"fun <Player> <Sound/Say> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "HELP")
+ {
+ switch(ParamsValid(&CDATA, 0, sIRC.CHELP))
+ {
+ case E_OK:
+ Help_IRC(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"help <Command> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "INCHAN")
+ {
+ switch(ParamsValid(&CDATA, 1, sIRC.CINCHAN))
+ {
+ case E_OK:
+ Inchan_Server(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"inchan <Channel> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "INFO")
+ {
+ switch(ParamsValid(&CDATA, 0, sIRC.CINFO))
+ {
+ case E_OK:
+ Info_Server(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"info )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "ITEM")
+ {
+ CDATA.PCOUNT = 3;
+ switch(ParamsValid(&CDATA, 2, sIRC.CITEM))
+ {
+ case E_OK:
+ Item_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"item <Player> <add> <ItemID/[ItemName]> <Amount> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "JAIL")
+ {
+ CDATA.PCOUNT = 3;
+ switch(ParamsValid(&CDATA, 1, sIRC.CJAIL))
+ {
+ case E_OK:
+ Jail_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"jail <Player> <release/Reason>)", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "KICK")
+ {
+ CDATA.PCOUNT = 2;
+ switch(ParamsValid(&CDATA, 1, sIRC.CKICK))
+ {
+ case E_OK:
+ Kick_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"kick <Player> <Reason> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "KILL")
+ {
+ CDATA.PCOUNT = 2;
+ switch(ParamsValid(&CDATA, 1, sIRC._KILL))
+ {
+ case E_OK:
+ Kill_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"kill <Player> <Reason> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "LEVEL")
+ {
+ CDATA.PCOUNT = 2;
+ switch(ParamsValid(&CDATA, 2, sIRC.CLEVEL))
+ {
+ case E_OK:
+ Level_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"level <Player> <NewLevel> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "LOOKUP")
+ {
+ CDATA.PCOUNT = 2;
+ switch(ParamsValid(&CDATA, 2, sIRC.CLOOKUP))
+ {
+ case E_OK:
+ Lookup_Player(&CDATA);
+ break;
+ case E_SIZE:
+ 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");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "MONEY")
+ {
+ CDATA.PCOUNT = 2;
+ switch(ParamsValid(&CDATA, 2, sIRC.CMONEY))
+ {
+ case E_OK:
+ Money_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"money <Player> <(-)Money> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "MUTE")
+ {
+ switch(ParamsValid(&CDATA, 2, sIRC.CMUTE))
+ {
+ case E_OK:
+ Mute_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"mute <Player> <release/TimeInMins> <Reason> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "ONLINE")
+ {
+ switch(ParamsValid(&CDATA, 0, sIRC.CONLINE))
+ {
+ case E_OK:
+ Online_Players(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"online )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "PM")
+ {
+ switch(ParamsValid(&CDATA, 2, sIRC.CPM))
+ {
+ case E_OK:
+ PM_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"pm <Player> <Message> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "RELOAD")
+ {
+ switch(ParamsValid(&CDATA, 0, sIRC.CRESTART))
+ {
+ case E_OK:
+ sIRC.Send_IRC_Channels("Reloading MangChat Config Options. (Command Disabled)");
+ //sIRC.LoadConfig();
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "RESTART")
+ {
+ switch(ParamsValid(&CDATA, 0, sIRC.CRESTART))
+ {
+ case E_OK:
+ sIRC.Send_IRC_Channels(sIRC.RstMsg);
+ sIRC.ResetIRC();
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "REVIVE")
+ {
+ CDATA.PCOUNT = 2;
+ switch(ParamsValid(&CDATA, 1, sIRC.CREVIVE))
+ {
+ case E_OK:
+ Revive_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"revive <Player> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "SAVEALL")
+ {
+ switch(ParamsValid(&CDATA, 0, sIRC.CSAVEALL))
+ {
+ case E_OK:
+ Saveall_Player(&CDATA);
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "SHUTDOWN")
+ {
+ switch(ParamsValid(&CDATA, 1, sIRC.CSHUTDOWN))
+ {
+ case E_OK:
+ Shutdown_Mangos(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"shutdown <TimeInSeconds> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "SPELL")
+ {
+ switch(ParamsValid(&CDATA, 2, sIRC.CSPELL))
+ {
+ case E_OK:
+ Spell_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"spell <Player> <Cast/Learn/UnLearn> <SpellID> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "SYSMSG")
+ {
+ CDATA.PCOUNT = 2;
+ switch(ParamsValid(&CDATA, 2, sIRC.CSYSMSG))
+ {
+ case E_OK:
+ Sysmsg_Server(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"sysmsg <a/e/n/add/del/list> <Message> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "TELE")
+ {
+ switch(ParamsValid(&CDATA, 2, sIRC.CTELE))
+ {
+ case E_OK:
+ Tele_Player(&CDATA);
+ break;
+ case E_SIZE:
+ 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");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "TOP")
+ {
+ CDATA.PCOUNT = 1;
+ switch(ParamsValid(&CDATA, 1, sIRC.CTOP))
+ {
+ case E_OK:
+ Top_Player(&CDATA);
+ break;
+ case E_SIZE:
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"top <accttime/chartime/money> <limit> )", true, "ERROR");
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ else if(CDATA.CMD == "WHO")
+ {
+ switch(ParamsValid(&CDATA, 0, sIRC.CWHO))
+ {
+ case E_OK:
+ Who_Logged(&CDATA);
+ break;
+ case E_AUTH:
+ AuthValid = false;
+ break;
+ }
+ cValid = true;
+ }
+ if(!AuthValid && IsLoggedIn(USER))
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Access Denied! Your Security Level Is Too Low To Use This Command!", true, "ERROR");
+ if(cValid == false && (sIRC.BOTMASK & 4) != 0)
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : Unknown Command!", true, "ERROR");
+ if(cValid && dontlog)
+ {
+ 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());
+ }
+ return cValid;
+ }
+ return false;
+}
+
+bool IRCCmd::CanUse(std::string USER, int nLevel)
+{
+ if(IsLoggedIn(USER))
+ {
+ if(GetLevel(USER) >= nLevel)
+ return true;
+ else
+ return false;
+ }
+ else if(nLevel == 0)
+ {
+ return true;
+ }
+ else
+ sIRC.Send_IRC_Channel(USER, "\0034[ERROR] : You Are Not Logged In!", true, "ERROR");
+ return false;
+}
+
+std::string IRCCmd::ChanOrPM(_CDATA *CD)
+{
+ if(CD->FROM == sIRC._Nick)
+ return CD->USER;
+ else
+ return CD->FROM;
+}
+
+Player *IRCCmd::GetPlayer(std::string WHO)
+{
+ normalizePlayerName(WHO);
+ return ObjectAccessor::Instance().FindPlayerByName(WHO.c_str());
+}
+
+_client *IRCCmd::GetClient(std::string cname)
+{
+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
+ {
+ if((*i)->Name == cname)
+ return (*i);
+ }
+ return (NULL);
+}
+
+bool IRCCmd::IsLoggedIn(std::string USER)
+{
+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
+ {
+ if((*i)->Name == USER)
+ return true;
+ }
+ return false;
+}
+
+bool IRCCmd::AcctIsLoggedIn(std::string USER)
+{
+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
+ {
+ if(MakeUpper((*i)->UName) == MakeUpper(USER))
+ return true;
+ }
+ return false;
+}
+
+std::string IRCCmd::AcctIsBanned(std::string ACCT)
+{
+ uint32 acctid = objmgr.GetAccountByAccountName(ACCT);
+ std::string banned = "NOTBANNED";
+ QueryResult *result = loginDatabase.PQuery("SELECT banreason FROM ip_banned WHERE ip=(SELECT last_ip FROM account WHERE id = '%i')", acctid);
+ if(result)
+ {
+ banned = (*result)[0].GetCppString();
+ delete result;
+ return "IP Banned. Reason:" + banned;
+ }
+ QueryResult *result2 = loginDatabase.PQuery("SELECT banreason FROM account_banned WHERE id='%i'", acctid);
+ if(result2)
+ {
+ banned = (*result2)[0].GetCppString();
+ delete result2;
+ return "Account Banned. Reason:" + banned;
+ }
+ return banned;
+}
+
+int IRCCmd::GetLevel(std::string sName)
+{
+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
+ {
+ if((*i)->Name == sName)
+ return (*i)->GMLevel;
+ }
+ return 0;
+}
+
+int IRCCmd::AcctLevel(std::string plnme)
+{
+ uint64 guid = objmgr.GetPlayerGUIDByName(plnme);
+ uint32 account_id = 0;
+ uint32 security = 0;
+ account_id = objmgr.GetPlayerAccountIdByGUID(guid);
+ security = objmgr.GetSecurityByAccount(account_id);
+ return security;
+}
+
+std::string IRCCmd::GetAccName(std::string sName)
+{
+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
+ {
+ if((*i)->Name == sName)
+ return (*i)->UName;
+ }
+ return "";
+}
+
+std::string IRCCmd::GetNameFromAcct(std::string sName)
+{
+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
+ {
+ if((*i)->UName == sName)
+ return (*i)->Name;
+ }
+ return "";
+}
+
+int IRCCmd::GetAcctIDFromName(std::string sName)
+{
+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
+ {
+ if((*i)->Name == sName)
+ {
+ uint32 acct_id = 0;
+ acct_id = objmgr.GetAccountByAccountName((*i)->UName.c_str());
+ return acct_id;
+ }
+ }
+ return 0;
+}
+
+std::string IRCCmd::GetAcctNameFromID(uint32 acctid)
+{
+ QueryResult *result = loginDatabase.PQuery("SELECT username FROM account WHERE id = '%d'", acctid);
+ if(result)
+ {
+ std::string name = (*result)[0].GetCppString();
+ delete result;
+ return name;
+ }
+
+ return "";
+}
+
+std::string IRCCmd::GetIPFromPlayer(std::string player)
+{
+ QueryResult *result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'", player.c_str());
+ if(result)
+ {
+ std::string acctid = (*result)[0].GetCppString();
+ delete result;
+ QueryResult *result2 = loginDatabase.PQuery("SELECT last_ip FROM account WHERE id = '%s'", acctid.c_str());
+ if(result2)
+ {
+ std::string ip = (*result2)[0].GetCppString();
+ delete result2;
+ return ip;
+ }
+ }
+
+ return "";
+}
+
+std::string IRCCmd::SecToDay(std::string secons)
+{
+ unsigned int seconds = atoi(secons.c_str());
+ unsigned int days = seconds / 86400;
+ unsigned int hours = seconds / 3600 % 24;
+ unsigned int mins = seconds / 60 % 60;
+ char tottime[1000];
+ sprintf(tottime, "%iDays:%iHours:%iMinutes", days, hours, mins);
+
+ return tottime;
+}
+
+bool IRCCmd::ValidParams(std::string PARAMS, int nCount)
+{
+ if(nCount == 1 && PARAMS.size() == 0)
+ return false;
+ int pcount = 0;
+ size_t p = -1;
+ for(int i = 0;i < nCount;i++)
+ {
+ p = PARAMS.find(" ", p + 1);
+ if(p == -1)
+ break;
+ else
+ pcount++;
+ }
+ nCount--;
+ if(pcount >= nCount)
+ return true;
+ else
+ return false;
+}
+
+std::string* IRCCmd::getArray(std::string PARAMS, int nCount)
+{
+ std::string *array = new std::string[nCount];
+ if(PARAMS.size() > 0)
+ {
+ int pcnt = 0;
+ size_t ps = 0;
+ size_t pc = -1;
+ for(int i = 0;i < nCount;i++)
+ {
+ pc = PARAMS.find(" ", pc + 1);
+ if(i + 1 == nCount && nCount != 1)
+ {
+ if(ps > 0 && pc > 0)
+ array[i] = PARAMS.substr(ps, PARAMS.size() - ps);
+ }
+ else
+ array[i] = PARAMS.substr(ps, pc - ps);
+ ps = pc + 1;
+ }
+ }
+ return array;
+}
+
+std::string IRCCmd::MakeMsg(const char *sLine, ... )
+{
+ va_list ap;
+ char tmpoutp[1024];
+ va_start(ap, sLine);
+ vsnprintf(tmpoutp, 1024, sLine, ap );
+ va_end(ap);
+ std::string outp = tmpoutp;
+ return outp;
+}
+
+void IRCClient::AHFunc(uint64 itmid, std::string itmnme, std::string plname, uint32 faction)
+{
+ IRCCmd Command;
+ Player* plr = Command.GetPlayer(plname);
+ if(plr)
+ {
+ std::string itemname = itmnme;
+
+ char temp [7];
+ sprintf(temp, "%u", itmid);
+ std::string itemid = temp;
+
+ std::string wowname = "";
+ std::string ircname = "";
+ switch (plr->GetTeam())
+ {
+ case 67:wowname="|cffff0000"+plname+"|r";ircname="\0034"+plname;break; //horde
+ case 469:wowname="|cff1589FF"+plname+"|r";ircname="\00312"+plname;break; //alliance
+ }
+
+ std::string wowfact = "|cffFF8040[Auction House]:|r";
+ std::string ircfact = "\00304,08\037/!\\\037\017\00307 Auction House \00304,08\037/!\\\037\017";
+ switch(faction)
+ {
+ //neutral
+ case 7:wowfact="|cffff8040[Neutral Auction House]:|r";ircfact="\00304,08\037/!\\\037\017\00307 Neutral Auction House \00304,08\037/!\\\037\017";break;
+ //horde
+ case 6:wowfact="|cffff0000[Horde Auction House]:|r";ircfact="\00304,08\037/!\\\037\017\00304 Horde Auction House \00304,08\037/!\\\037\017";break;
+ //alliance
+ case 2:wowfact="|cff1589FF[Alliance Auction House]:|r";ircfact="\00304,08\037/!\\\037\017\00312 Alliance Auction House \00304,08\037/!\\\037\017";break;
+ }
+ 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());
+ std::string ircstr = Command.MakeMsg("%s A New Item Has Been Added [%s]. By: %s", ircfact.c_str(), itemname.c_str(), ircname.c_str());
+
+ sIRC.Send_WoW_Channel(sIRC._wow_chan[sIRC.Status].c_str(), wowstr.c_str());
+ sIRC.Send_IRC_Channel(sIRC._irc_chan[sIRC.Status].c_str(), ircstr.c_str());
+ }
+}
diff --git a/src/game/IRCCmd.h b/src/game/IRCCmd.h
new file mode 100644
index 00000000000..f2b442c6173
--- /dev/null
+++ b/src/game/IRCCmd.h
@@ -0,0 +1,117 @@
+#ifndef _IRC_CMD_H
+#define _IRC_CMD_H
+
+#define MAX_CLIENTS 50
+#include "Common.h"
+#include "Player.h"
+#include "ObjectAccessor.h"
+
+struct ChannelUser
+{
+ int UserType;
+ std::string Name;
+ std::string UName;
+ int UserLevel;
+};
+
+struct _client
+{
+ bool LoggedIn;
+ std::string Name;
+ std::string UName;
+ int GMLevel;
+};
+struct _CDATA
+{
+ std::string CMD;
+ std::string USER;
+ std::string FROM;
+ std::string PARAMS;
+ std::string TYPE;
+ int PCOUNT;
+};
+enum APVERR
+{
+ E_OK,
+ E_SIZE,
+ E_AUTH,
+ E_IVALID,
+};
+enum ESOUNDS
+{
+ S_ENTERWORLD = 602,
+ S_QUESTFAILED = 847,
+ S_INVITE = 880,
+ S_LEVELUP = 888,
+ S_COINSOUND = 895,
+ S_WHISPER = 3081,
+ S_STEALTH = 3325,
+};
+class IRCCmd
+{
+ public:
+ IRCCmd();
+ ~IRCCmd();
+
+ void Handle_Logout(_CDATA *CD);
+ bool IsLoggedIn(std::string USER);
+ bool IsValid(std::string USER, std::string FROM, std::string CHAT, std::string TYPE);
+ bool AcctIsLoggedIn(std::string USER);
+ _client *GetClient(std::string cname);
+
+ public:
+ static std::string MakeMsg(const char *sLine, ... );
+ static std::string ChanOrPM(_CDATA *CD);
+ int AcctLevel(std::string plnme);
+ int GetLevel(std::string sName);
+ std::string MakeUpper(std::string Channel);
+ std::string AcctIsBanned(std::string ACCT);
+ std::list<_client*> _CLIENTS;
+ Player* GetPlayer(std::string WHO);
+
+ private:
+ // MangChat Commands
+ void Handle_Login(_CDATA *CD);
+ void Account_Player(_CDATA *CD);
+ void Ban_Player(_CDATA *CD);
+ void Chan_Control(_CDATA *CD);
+ void Char_Player(_CDATA *CD);
+ void Fun_Player(_CDATA *CD);
+ void Help_IRC(_CDATA *CD);
+ void Item_Player(_CDATA *CD);
+ void Inchan_Server(_CDATA *CD);
+ void Info_Server(_CDATA *CD);
+ void Jail_Player(_CDATA *CD);
+ void Kick_Player(_CDATA *CD);
+ void Kill_Player(_CDATA *CD);
+ void Level_Player(_CDATA *CD);
+ void Lookup_Player(_CDATA *CD);
+ void Money_Player(_CDATA *CD);
+ void Mute_Player(_CDATA *CD);
+ void Online_Players(_CDATA *CD);
+ void PM_Player(_CDATA *CD);
+ void Revive_Player(_CDATA *CD);
+ void Saveall_Player(_CDATA *CD);
+ void Shutdown_Mangos(_CDATA *CD);
+ void Spell_Player(_CDATA *CD);
+ void Sysmsg_Server(_CDATA *CD);
+ void Tele_Player(_CDATA *CD);
+ void Top_Player(_CDATA *CD);
+ void Who_Logged(_CDATA *CD);
+ bool CanUse(std::string USER, int nLevel);
+ bool ValidParams(std::string PARAMS, int nCount = 1);
+ bool ParamsValid(_CDATA *CD, int pCnt);
+ int ParamsValid(_CDATA *CD, int pCnt, int rLev);
+ std::string GetAccName(std::string sName);
+ std::string GetNameFromAcct(std::string sName);
+ std::string GetAcctNameFromID(uint32 acctid);
+ std::string GetIPFromPlayer(std::string player);
+ std::string SecToDay(std::string secons);
+ int GetAcctIDFromName(std::string sName);
+ std::string* getArray(std::string PARAMS, int nCount = 1);
+};
+inline void MakeLower(std::string& str)
+{
+ std::transform( str.begin(), str.end(), str.begin(), ::tolower );
+}
+#endif
diff --git a/src/game/IRCCmde.cpp b/src/game/IRCCmde.cpp
new file mode 100644
index 00000000000..ec1ccfae808
--- /dev/null
+++ b/src/game/IRCCmde.cpp
@@ -0,0 +1,1884 @@
+/*
+ * MangChat By |Death| And Cybrax
+ *
+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
+ * Of The GNU General Public License
+ * Written and Developed by Cybrax. cybraxvd@gmail.com
+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
+ * With Help And Support From The MaNGOS Project Community.
+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
+ */
+#include "IRCCmd.h"
+#include "IRCClient.h"
+#include "MCS_OnlinePlayers.h"
+#include "WorldPacket.h"
+#include "Database/DatabaseEnv.h"
+#include "Chat.h"
+#include "MapManager.h"
+#include "World.h"
+#include "Guild.h"
+#include "ObjectMgr.h"
+#include "Language.h"
+#include "SpellAuras.h"
+#include "SystemConfig.h"
+#include "Config/ConfigEnv.h"
+
+#define Send_Player(p, m) sIRC.Send_WoW_Player(p, m)
+#define Send_IRCA(c, m, b, t) sIRC.Send_IRC_Channel(c, m, b, t)
+
+#ifdef WIN32
+#define Delay(x) Sleep(x)
+#else
+#define Delay(x) sleep(x / 1000)
+#endif
+
+void IRCCmd::Handle_Login(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 2);
+ std::string isbanned = AcctIsBanned(_PARAMS[0]);
+ if(isbanned == "NOTBANNED")
+ {
+ if(!IsLoggedIn(CD->USER))
+ {
+ if(!AcctIsLoggedIn(_PARAMS[0].c_str()))
+ {
+ 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());
+ if (result)
+ {
+ Field *fields = result->Fetch();
+ int GMLevel = fields[0].GetInt16();
+ if(GMLevel >= 0)
+ {
+ _client *NewClient = new _client();
+ NewClient->Name = CD->USER;
+ NewClient->UName = MakeUpper(_PARAMS[0]);
+ NewClient->GMLevel = fields[0].GetInt16();
+ _CLIENTS.push_back(NewClient);
+ Send_IRCA(CD->USER, MakeMsg("You Are Now Logged In As %s, Welcome To MangChat Admin Mode.", _PARAMS[0].c_str()), true, CD->TYPE);
+
+ if(sIRC._op_gm == 1 && GMLevel >= sIRC._op_gm_lev)
+ {
+ for(int i=1;i < sIRC._chan_count + 1;i++)
+ sIRC.SendIRC("MODE #"+sIRC._irc_chan[i]+" +o "+CD->USER );
+ }
+ }
+ }else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Sorry, Your Username Or Password Is Incorrect. Please Try Again. ", true, "ERROR");
+ }else
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : %s Is Already Logged In With This Username. ", GetNameFromAcct(MakeUpper(_PARAMS[0])).c_str()), true, "ERROR");
+ }else
+ Send_IRCA(CD->USER, "\0034[ERROR] : You Are Already Logged In As "+ _PARAMS[0] +"!", true, "ERROR");
+ }else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Sorry You Are "+isbanned+". You Cannot Log In To MangChat "+CD->USER.c_str()+"!", true, "ERROR");
+}
+
+void IRCCmd::Handle_Logout(_CDATA *CD)
+{
+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
+ {
+ if((*i)->Name == CD->USER)
+ {
+ _CLIENTS.erase(i);
+ delete (*i);
+ Send_IRCA(CD->USER, "You Are Now Logged Out!", true, CD->TYPE);
+ return;
+ }
+ }
+ Send_IRCA(CD->USER, "\0034[ERROR] : You Are Not Logged In!", true, "ERROR");
+}
+
+void IRCCmd::Account_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 3);
+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
+ return;
+ }
+ normalizePlayerName(_PARAMS[0]);
+ uint64 guid = objmgr.GetPlayerGUIDByName(_PARAMS[0]);
+ uint32 account_id = 0;
+ account_id = objmgr.GetPlayerAccountIdByGUID(guid);
+ if(account_id)
+ {
+ if(account_id == GetAcctIDFromName(CD->USER) || GetLevel(CD->USER) >= sIRC._op_gm_lev)
+ {
+ Player* plr = objmgr.GetPlayer(guid);
+ if(_PARAMS[1] == "lock")
+ {
+ loginDatabase.PExecute( "UPDATE `account` SET `locked` = '1' WHERE `id` = '%d'",account_id);
+ if(plr) Send_Player(plr, MakeMsg("Your Account Has Been Locked To Your Current IP By: %s", CD->USER.c_str()));
+ Send_IRCA(ChanOrPM(CD), "\00313["+GetAcctNameFromID(account_id)+"] : Account Has Been Locked To Their Current IP Address.", true, CD->TYPE);
+ }
+ else if(_PARAMS[1] == "unlock")
+ {
+ loginDatabase.PExecute( "UPDATE `account` SET `locked` = '0' WHERE `id` = '%d'",account_id);
+ if(plr) Send_Player(plr, MakeMsg("Your Account Has Been UnLocked From The Associated IP By: %s", CD->USER.c_str()));
+ Send_IRCA(ChanOrPM(CD), "\00313["+GetAcctNameFromID(account_id)+"] : Account Has Been UnLocked From The Associated IP Address.", true, CD->TYPE);
+ }
+ else if(_PARAMS[1] == "mail")
+ {
+ loginDatabase.PExecute( "UPDATE `account` SET `email` = '%s' WHERE `id` = '%d'",_PARAMS[2].c_str() ,account_id);
+ if (plr) Send_Player(plr, MakeMsg("%s Has Changed Your EMail Adress To: %s", CD->USER.c_str(), _PARAMS[2].c_str()));
+ Send_IRCA(ChanOrPM(CD), "\00313["+GetAcctNameFromID(account_id)+"] : EMail Address Successfully Changed To: "+_PARAMS[2], true, CD->TYPE);
+ }
+ else if(_PARAMS[1] == "pass")
+ {
+ loginDatabase.PExecute( "UPDATE `account` SET `sha_pass_hash` = SHA1(CONCAT(UPPER(`username`),':',UPPER('%s'))) WHERE `id` = '%d'",_PARAMS[2].c_str() ,account_id);
+ if (plr) Send_Player(plr, MakeMsg("%s Has Changed Your Password To: %s", CD->USER.c_str(), _PARAMS[2].c_str()));
+ Send_IRCA(ChanOrPM(CD), "\00313["+GetAcctNameFromID(account_id)+"] : Password Successfully Changed To: "+_PARAMS[2], true, CD->TYPE);
+ }
+ else if(_PARAMS[1] == "rename")
+ {
+ if(plr)
+ {
+ plr->SetAtLoginFlag(AT_LOGIN_RENAME);
+ Send_Player(plr, MakeMsg("%s Has Requested You Change This Characters Name, Rename Will Be Forced On Next Login!", CD->USER.c_str()));
+ }
+ CharacterDatabase.PExecute("UPDATE `characters` SET `at_login` = `at_login` | '1' WHERE `guid` = '%u'", guid);
+ 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);
+ }
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : You Are Not A GM, You May Only Change Settings In Your Own Account.", true, "ERROR");
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : No Such Player Exists, So Account Cannot Be Looked Up.", true, "ERROR");
+}
+
+void IRCCmd::Ban_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 3);
+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
+ return;
+ }
+ if(_PARAMS[1] == "ip")
+ {
+ std::string ip = GetIPFromPlayer(_PARAMS[0]);
+ if(_PARAMS[2] == "")
+ _PARAMS[2] = "No Reason";
+ if(ip != "")
+ {
+ 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());
+ if (Player* plr = GetPlayer(_PARAMS[0]))
+ plr->GetSession()->KickPlayer();
+ 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);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : I Cannot Locate An IP Address For The Character Name Given.", true, "ERROR");
+ }
+ if(_PARAMS[1] == "acct")
+ {
+ uint64 guid = objmgr.GetPlayerGUIDByName(_PARAMS[0].c_str());
+ uint32 acctid = objmgr.GetPlayerAccountIdByGUID(guid);
+ if(_PARAMS[2] == "")
+ _PARAMS[2] = "No Reason";
+ if(acctid)
+ {
+ loginDatabase.PExecute( "INSERT INTO `account_banned` VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '%s', '%s', 1)", acctid, CD->USER.c_str(), _PARAMS[2].c_str());
+ if (Player* plr = GetPlayer(_PARAMS[0]))
+ plr->GetSession()->KickPlayer();
+ 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);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : I Cannot Locate An Account For The Character Name Given.", true, "ERROR");
+ }
+ if(_PARAMS[1] == "unban")
+ {
+ std::string unbani = _PARAMS[0];
+ if(atoi(unbani.c_str()) > 0)
+ {
+ loginDatabase.PExecute( "DELETE FROM ip_banned WHERE ip = '%s'", _PARAMS[0].c_str());
+ Send_IRCA(ChanOrPM(CD), MakeMsg("\00313[%s] : Has Been Removed From The IP Ban List.", _PARAMS[0].c_str()), true, CD->TYPE);
+ }
+ else
+ {
+ QueryResult *result = loginDatabase.PQuery("SELECT id FROM `account` WHERE username = '%s'", _PARAMS[0].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string id = fields[0].GetCppString();
+
+ loginDatabase.PExecute( "DELETE FROM account_banned WHERE id = %s", id.c_str());
+ delete result;
+ Send_IRCA(ChanOrPM(CD), MakeMsg("\00313[%s] : Has Been Removed From The Account Ban List.", _PARAMS[0].c_str()), true, CD->TYPE);
+
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : I Cannot Locate An Account Or IP Address For The Paramaters Given.", true, "ERROR");
+ }
+ }
+}
+
+void IRCCmd::Chan_Control(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 2);
+ if(CD->FROM == sIRC._Nick)
+ {
+ Send_IRCA(CD->USER, "\0034[ERROR] : You Cannot Use This Command Through A PM Yet.", true, "ERROR");
+ return;
+ }
+ if(_PARAMS[0] == "op")
+ {
+ if(_PARAMS[1].length() > 1)
+ sIRC.SendIRC("MODE "+CD->FROM+" +o "+_PARAMS[1] );
+ else
+ sIRC.SendIRC("MODE "+CD->FROM+" +o "+CD->USER );
+ }
+ if(_PARAMS[0] == "deop")
+ {
+ if(_PARAMS[1].length() > 1)
+ sIRC.SendIRC("MODE "+CD->FROM+" -o "+_PARAMS[1] );
+ else
+ sIRC.SendIRC("MODE "+CD->FROM+" -o "+CD->USER );
+ }
+ if(_PARAMS[0] == "voice")
+ {
+ if(_PARAMS[1].length() > 1)
+ sIRC.SendIRC("MODE "+CD->FROM+" +v "+_PARAMS[1] );
+ else
+ sIRC.SendIRC("MODE "+CD->FROM+" +v "+CD->USER );
+ }
+ if(_PARAMS[0] == "devoice")
+ {
+ if(_PARAMS[1].length() > 1)
+ sIRC.SendIRC("MODE "+CD->FROM+" -v "+_PARAMS[1] );
+ else
+ sIRC.SendIRC("MODE "+CD->FROM+" -v "+CD->USER );
+ }
+}
+
+void IRCCmd::Char_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 5);
+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
+ return;
+ }
+ normalizePlayerName(_PARAMS[0]);
+ uint64 guid = objmgr.GetPlayerGUIDByName(_PARAMS[0]);
+ Player* plr = objmgr.GetPlayer(guid);
+ if(plr)
+ {
+ if(_PARAMS[1] == "mapcheat")
+ {
+ bool explore = false;
+ if (_PARAMS[2] != "0")
+ explore = true;
+ for (uint8 i=0; i<64; i++)
+ {
+ if (_PARAMS[2] != "0")
+ plr->SetFlag(PLAYER_EXPLORED_ZONES_1+i,0xFFFFFFFF);
+ else
+ plr->SetFlag(PLAYER_EXPLORED_ZONES_1+i,0);
+ }
+ if(explore)
+ {
+ Send_Player(plr, MakeMsg("All Your Zones Have Been Set To Explored By: %s", CD->USER.c_str()));
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Now Explored All Zones.", true, CD->TYPE);
+ }
+ else
+ {
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Now Had All Zones Set To Un-Explored.", true, CD->TYPE);
+ Send_Player(plr, MakeMsg("All Your Zones Have Been Set To Un-Explored By: %s", CD->USER.c_str()));
+ }
+ }
+ if(_PARAMS[1] == "taxicheat")
+ {
+ if (_PARAMS[2] != "0")
+ {
+ plr->SetTaxiCheater(true);
+ Send_Player(plr, MakeMsg("Taxi Node Cheat Has Been Enabled By: %s", CD->USER.c_str()));
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Taxi Node Cheat Has Been Enabled.", true, CD->TYPE);
+ }
+ else
+ {
+ plr->SetTaxiCheater(false);
+ Send_Player(plr, MakeMsg("Taxi Node Cheat Has Been Disabled By: %s", CD->USER.c_str()));
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Taxi Node Cheat Has Been Disabled.", true, CD->TYPE);
+ }
+ }
+ if(_PARAMS[1] == "maxskill")
+ {
+ plr->UpdateSkillsToMaxSkillsForLevel();
+ Send_Player(plr, MakeMsg("Your Skills Have Been Maxed Out By: %s", CD->USER.c_str()));
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Skills Have Been Maxed Out.", true, CD->TYPE);
+ }
+ if(_PARAMS[1] == "setskill")
+ {
+ std::string* _PARAMSA = getArray(_PARAMS[2], 4);
+ uint32 skill = atoi(_PARAMS[2].c_str());
+ uint32 level = atol(_PARAMS[3].c_str());
+ int32 max = _PARAMS[4].c_str() ? atol (_PARAMS[4].c_str()) : plr->GetPureMaxSkillValue(skill);
+ SkillLineEntry const* skilllookup = sSkillLineStore.LookupEntry(skill);
+ //if skillid entered is not a number and greater then 0 then the command is being used wrong
+ if(skill >= 0)
+ {
+ //does the skill even exist
+ if(skilllookup)
+ {
+ //does player have the skill yet
+ if(plr->GetSkillValue(skill))
+ {
+ plr->SetSkill(skill,level,max);
+ 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()));
+ 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);
+ }
+ else
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Player Does Not Have The %s Skill Yet.", skilllookup->name[0]), true, "ERROR");
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : That Skill ID Does Not Exist.", true, "ERROR");
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : The Skill ID Entered Is Invalid.", true, "ERROR");
+ }
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : No Character With That Name Exists.", true, "ERROR");
+}
+
+void IRCCmd::Fun_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 3);
+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
+ return;
+ }
+ if (Player* plr = GetPlayer(_PARAMS[0]))
+ {
+ if(_PARAMS[1] == "say")
+ {
+ plr->Say(_PARAMS[2], LANG_UNIVERSAL);
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Was Forced To Say: "+_PARAMS[2]+".", true, CD->TYPE);
+ }
+ if(_PARAMS[1] == "sound")
+ {
+ uint32 sndid = atoi(_PARAMS[2].c_str());
+ plr->SendPlaySound(sndid ,true);
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Just Heard Sound ID: "+_PARAMS[2]+".", true, CD->TYPE);
+ }
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Player Not Online!", true, "ERROR");
+}
+
+void IRCCmd::Help_IRC(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 1);
+ QueryResult *result = WorldDatabase.PQuery("SELECT `Command`, `Description`, `gmlevel` FROM `IRC_Commands`");
+ if(result)
+ {
+ if(IsLoggedIn(CD->USER))
+ {
+ if(_PARAMS[0] == "")
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT * FROM `IRC_Commands` WHERE `gmlevel` <= %u ORDER BY `Command`", GetLevel(CD->USER));
+ if(result)
+ {
+ std::string output = "\002MangChat IRC Commands:\017 ";
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ Field *fields = result->Fetch();
+ output += fields[0].GetCppString() + ", ";
+ result->NextRow();
+ }
+ delete result;
+ Send_IRCA(CD->USER, output, true, CD->TYPE.c_str());
+ }
+ }
+ else
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT `Description`, `gmlevel` FROM `IRC_Commands` WHERE `Command` = '%s'", _PARAMS[0].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ if(fields[1].GetUInt32() > GetLevel(CD->USER))
+ {
+ Send_IRCA(CD->USER, "You Do Not Have Access To That Command, So No Help Is Available.", true, CD->TYPE.c_str());
+ return;
+ }
+ if(result)
+ {
+ std::string cmdhlp = fields[0].GetCppString();
+ delete result;
+ Send_IRCA(CD->USER, cmdhlp, true, CD->TYPE.c_str());
+ }
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : No Such Command Exists, Please Check The Spelling And Try Again.", true, "ERROR");
+ }
+ }
+ else if(!IsLoggedIn(CD->USER))
+ {
+ if(_PARAMS[0] == "")
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT * FROM `IRC_Commands` WHERE `gmlevel` = 0 ORDER BY `Command`");
+ if(result)
+ {
+ std::string output = "\002MangChat IRC Commands:\017 ";
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ Field *fields = result->Fetch();
+ output += fields[0].GetCppString() + ", ";
+ result->NextRow();
+ }
+ delete result;
+ Send_IRCA(CD->USER, output, true, CD->TYPE.c_str());
+ 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());
+ }
+ }
+ else
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT `Description`, `gmlevel` FROM `IRC_Commands` WHERE `Command` = '%s'", _PARAMS[0].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ if(fields[1].GetUInt32() > 0)
+ {
+ Send_IRCA(CD->USER, "You Do Not Have Access To That Command, So No Help Is Available.", true, CD->TYPE.c_str());
+ return;
+ }
+ std::string cmdhlp = fields[0].GetCppString();
+ delete result;
+ Send_IRCA(CD->USER, cmdhlp, true, CD->TYPE.c_str());
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : No Such Command Exists, Please Check The Spelling And Try Again.", true, "ERROR");
+ }
+ }
+ }
+ else
+ 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");
+}
+
+void IRCCmd::Inchan_Server(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 1);
+ if(_PARAMS[0] == "")
+ {
+ Send_IRCA(CD->USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"inchan <ChannelName> )", true, "ERROR");
+ return;
+ }
+ QueryResult *result = WorldDatabase.PQuery("SELECT * FROM `IRC_Inchan` WHERE `channel` = '%s' ORDER BY `name`", _PARAMS[0].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string output = "\002Players In The [ "+fields[2].GetCppString()+" ] Channel:\017 ";
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ output += fields[1].GetCppString() + ", ";
+ result->NextRow();
+ }
+ delete result;
+ Send_IRCA(ChanOrPM(CD), output, true, CD->TYPE);
+ }
+ else
+ Send_IRCA(ChanOrPM(CD), "No Players Are Currently In [ "+_PARAMS[0]+" ] Channel!", true, CD->TYPE.c_str());
+}
+
+void IRCCmd::Info_Server(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 1);
+ char clientsNum [50];
+ sprintf(clientsNum, "%u", sWorld.GetActiveSessionCount());
+ char maxClientsNum [50];
+ sprintf(maxClientsNum, "%u", sWorld.GetMaxActiveSessionCount());
+ std::string str = secsToTimeString(sWorld.GetUptime());
+ std::string svnrev = _FULLVERSION;
+ 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);
+ Send_IRCA(ChanOrPM(CD), "\x2 Trinity Core SVN revision:\x3\x31\x30 "+svnrev, true, CD->TYPE);
+}
+
+void IRCCmd::Item_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 3);
+
+ normalizePlayerName(_PARAMS[0]);
+ Player *chr = GetPlayer(_PARAMS[0].c_str());
+ if(_PARAMS[1] == "add")
+ {
+ std::string s_param = _PARAMS[2];
+
+ char *args = (char*)s_param.c_str();
+ uint32 itemId = 0;
+ if(args[0]=='[')
+ {
+ char* citemName = citemName = strtok((char*)args, "]");
+ if(citemName && citemName[0])
+ {
+ std::string itemName = citemName+1;
+ WorldDatabase.escape_string(itemName);
+ QueryResult *result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE name = '%s'", itemName.c_str());
+ if (!result)
+ {
+ Send_IRCA(CD->USER, "\0034[ERROR] : Item Not Found!", true, "ERROR");
+ return;
+ }
+ itemId = result->Fetch()->GetUInt16();
+ delete result;
+ }
+ else
+ {
+ Send_IRCA(CD->USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"item <Player> <add> [Exact Item Name] <Amount> )", true, "ERROR");
+ return;
+ }
+ }
+ else
+ {
+ std::string itemName = s_param;
+ WorldDatabase.escape_string(itemName);
+ QueryResult *result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE name = '%s'", itemName.c_str());
+ if (result)
+ {
+ itemId = result->Fetch()->GetUInt16();
+ }
+ delete result;
+
+ char* cId = strtok(args, " ");
+ if(!cId)
+ {
+ Send_IRCA(CD->USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"item <Player> <add> <ItemID> <Amount> )", true, "ERROR");
+ return;
+ }
+ itemId = atol(cId);
+ }
+ char* ccount = strtok(NULL, " ");
+ int32 count = 1;
+ if (ccount) { count = atol(ccount); }
+ Player* plTarget = chr;
+ if(!plTarget)
+ {
+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Not Online!", true, "ERROR");
+ return;
+ }
+ ItemPrototype const *pProto = objmgr.GetItemPrototype(itemId);
+ //Subtract
+ if (count < 0)
+ {
+ plTarget->DestroyItemCount(itemId, -count, true, false);
+ char itemid2[255];
+ sprintf(itemid2,"%d",itemId);
+ std::string itake = " \00313["+ _PARAMS[0] +"] : Has Had Item " +itemid2+ " Taken From Them!";
+ Send_IRCA(ChanOrPM(CD), itake, true, CD->TYPE);
+ return;
+ }
+ //Adding items
+ uint32 noSpaceForCount = 0;
+
+ // check space and find places
+ ItemPosCountVec dest;
+ uint8 msg = plTarget->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemId, count, &noSpaceForCount );
+ if( msg == EQUIP_ERR_INVENTORY_FULL ) // convert to possibel store amount
+ count -= noSpaceForCount;
+ else if( msg != EQUIP_ERR_OK ) // other error, can't add
+ {
+ char s_countForStore[255];
+ sprintf(s_countForStore,"%d",count);
+ std::string ierror = " \00313["+ _PARAMS[0] +"] : Could Not Create All Items! " +s_countForStore+ " Item(s) Were Not Created!";
+ Send_IRCA(ChanOrPM(CD), ierror, true, CD->TYPE);
+ return;
+ }
+ Item* item = plTarget->StoreNewItem( dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId));
+ if(count > 0 && item)
+ {
+ plTarget->SendNewItem(item,count,true,false);
+ QueryResult *result = WorldDatabase.PQuery("SELECT name FROM item_template WHERE entry = %d", itemId);
+ char* dbitemname = NULL;
+ if (result)
+ {
+ dbitemname = (char*)result->Fetch()->GetString();
+ }
+ std::string iinfo = " \00313[" + _PARAMS[0] + "] : Has Been Given Item "+dbitemname+". From: "+CD->USER.c_str()+".";
+ Send_IRCA(ChanOrPM(CD), iinfo, true, CD->TYPE);
+ delete result;
+ }
+ if(noSpaceForCount > 0)
+ {
+ char s_countForStore[255];
+ sprintf(s_countForStore,"%d",noSpaceForCount);
+ std::string ierror = " \00313["+ _PARAMS[0] +"] : Could Not Create All Items! " +s_countForStore+ " Item(s) Were Not Created!";
+ Send_IRCA(ChanOrPM(CD), ierror, true, CD->TYPE);
+ return;
+ }
+ }
+ else
+ {
+ Send_IRCA(CD->USER, "\0034[ERROR] : Syntax Error! ( "+sIRC._cmd_prefx+"item <Player> <add> <ItemID> <Amount> )", true, "ERROR");
+ return;
+ }
+}
+
+void IRCCmd::Jail_Player(_CDATA *CD)
+{
+ if(ValidParams(CD->PARAMS, 1))
+ {
+ std::string* _PARAMS = getArray(CD->PARAMS, 2);
+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
+ return;
+ }
+ if (Player *plr = GetPlayer(_PARAMS[0]))
+ {
+ std::string sReason = "";
+ if(_PARAMS[1] == "release")
+ {
+ float rposx, rposy, rposz, rposo = 0;
+ uint32 rmapid = 0;
+ CharacterDatabase.escape_string(_PARAMS[0]);
+ QueryResult *result = CharacterDatabase.PQuery( "SELECT `map`, `position_x`, `position_y`, `position_z` FROM `character_homebind` WHERE `guid` = '" I64FMTD "'", plr->GetGUID() );
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ rmapid = fields[0].GetUInt16();
+ rposx = fields[1].GetFloat();
+ rposy = fields[2].GetFloat();
+ rposz = fields[3].GetFloat();
+ delete result;
+ plr->SetMovement(MOVE_UNROOT);
+ plr->TeleportTo(rmapid, rposx, rposy, rposz, rposo);
+ plr->RemoveAurasDueToSpell(42201);
+ plr->RemoveAurasDueToSpell(23775);
+ plr->RemoveAurasDueToSpell(9454);
+ Send_Player(plr, MakeMsg("You Have Been Released By: %s.", CD->USER.c_str()));
+ sReason = " \00313["+_PARAMS[0]+"] : Has Been Released By: "+CD->USER+".";
+ Send_IRCA(ChanOrPM(CD), sReason, true, CD->TYPE);
+ }
+ }
+ else
+ {
+ if(_PARAMS[1] == "")
+ _PARAMS[1] = "No Reason Given.";
+ plr->TeleportTo(13, 0, 0, 0, 0);
+ plr->SetMovement(MOVE_ROOT);
+ plr->CastSpell(plr, 42201, true);
+ plr->CastSpell(plr, 23775, true);
+ plr->CastSpell(plr, 9454, true);
+ Send_Player(plr, MakeMsg("You Have Been Jailed By: %s. Reason: %s.", CD->USER.c_str(), _PARAMS[1].c_str()));
+ sReason = " \00313["+_PARAMS[0]+"] : Has Been Jailed By: "+CD->USER+". Reason: "+_PARAMS[1]+".";
+ Send_IRCA(ChanOrPM(CD), sReason, true, CD->TYPE);
+ }
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Not Online!", true, "ERROR");
+ }
+}
+
+void IRCCmd::Kick_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, CD->PCOUNT);
+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
+ return;
+ }
+ if(_PARAMS[1] == "")
+ _PARAMS[1] = "No Reason Given.";
+ if (Player* plr = GetPlayer(_PARAMS[0]))
+ {
+ plr->GetSession()->KickPlayer();
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Been Kicked By: "+CD->USER+". Reason: "+_PARAMS[1]+".", true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Not Online!", true, "ERROR");
+}
+
+void IRCCmd::Kill_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, CD->PCOUNT);
+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
+ return;
+ }
+ if (Player* plr = GetPlayer(_PARAMS[0]))
+ {
+ if(plr->isAlive())
+ {
+ plr->DealDamage(plr, plr->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ plr->SaveToDB();
+ if(_PARAMS[1] == "")
+ _PARAMS[1] = "No Reason Given.";
+ 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);
+ Send_Player(plr, MakeMsg("You Have Been Killed By: %s. Reason: %s.", CD->USER.c_str(), _PARAMS[1].c_str()));
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Already Dead!", true, "ERROR");
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Not Online!", true, "ERROR");
+}
+
+void IRCCmd::Lookup_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, CD->PCOUNT);
+ if(_PARAMS[0] == "acct")
+ {
+ uint32 acctid = atoi(_PARAMS[1].c_str());
+ if(objmgr.GetAccountByAccountName(_PARAMS[1]))
+ acctid = objmgr.GetAccountByAccountName(_PARAMS[1]);
+ if(acctid > 0)
+ {
+ std::string DateTime = "%a, %b %d, %Y - %h:%i%p";
+ 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);
+ if(result)
+ {
+ Field *fields = result->Fetch();
+
+ uint32 id = fields[0].GetUInt32();
+ std::string usrname = fields[1].GetCppString();
+ uint32 gm = fields[2].GetUInt32();
+ std::string lastip = fields[3].GetCppString();
+ std::string banreason = fields[4].GetCppString();
+ std::string banreasonip = fields[5].GetCppString();
+ std::string lastlogin = fields[6].GetCppString();
+ delete result;
+
+ QueryResult *chars = CharacterDatabase.PQuery("SELECT guid, name, (SELECT SUM(totaltime) FROM characters WHERE account = %d) AS tottime FROM characters WHERE account = %u", id, id);
+ std::string characters = "None";
+ std::string totaccttime = "Never Logged In";
+ if(chars)
+ {
+ characters = "";
+ Field *fields = chars->Fetch();
+ totaccttime = SecToDay(fields[2].GetCppString());
+ for (uint64 i=0; i < chars->GetRowCount(); i++)
+ {
+ std::string guid = fields[0].GetCppString();
+ std::string charname = fields[1].GetCppString();
+ characters.append(charname+"("+guid+"), ");
+ chars->NextRow();
+ }
+ delete chars;
+ }
+ 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);
+ 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);
+ if(banreason.length() > 1)
+ Send_IRCA(ChanOrPM(CD), MakeMsg("\0034This User Has An Account Ban. Ban Reason: %s", banreason.c_str()), true, CD->TYPE);
+ if(banreasonip.length() > 1)
+ Send_IRCA(ChanOrPM(CD), MakeMsg("\0034This User Has An IP Ban. Ban Reason: %s", banreasonip.c_str()), true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Account ID." ,true, "ERROR");
+ }
+ else
+ {
+ QueryResult *result = loginDatabase.PQuery("SELECT id, username FROM `account` WHERE username LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string accts = "\002Account Search Results:\x3\x31\x30 ";
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ std::string acctid = fields[0].GetCppString();
+ std::string acctname = fields[1].GetCppString();
+ accts.append(acctname+"("+acctid+")\xF | \x3\x31\x30\x2");
+ result->NextRow();
+ }
+ delete result;
+ Send_IRCA(ChanOrPM(CD), accts, true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Username. I Cant Find Any Users With Those Search Terms." ,true, "ERROR");
+ }
+ }
+ if(_PARAMS[0] == "char")
+ {
+ uint32 plguid = atoi(_PARAMS[1].c_str());
+ if(objmgr.GetPlayerGUIDByName(_PARAMS[1].c_str()))
+ plguid = objmgr.GetPlayerGUIDByName(_PARAMS[1].c_str());
+ if(plguid > 0)
+ {
+ 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, SEC_TO_TIME(totaltime) AS tottime FROM characters WHERE guid =%i", plguid);
+ uint32 latency = 0;
+ Player *chr = objmgr.GetPlayer(plguid);
+ if(chr)
+ {
+ latency = chr->GetSession()->GetLatency();
+ }
+ char templatency [100];
+ sprintf(templatency, "%ums", latency);
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string pguid = fields[0].GetCppString();
+ std::string pacct = fields[1].GetCppString();
+ std::string pname = fields[2].GetCppString();
+ uint32 praceid = fields[3].GetUInt32();
+ uint32 pclassid = fields[4].GetUInt32();
+ std::string ponline = (fields[5].GetInt32() == 1 ? "\x3\x30\x33Online" : "\x3\x30\x34Offline\xF");
+ std::string plevel = fields[6].GetCppString();
+ uint32 pguildid = fields[7].GetUInt32();
+ uint32 pguildrank = fields[8].GetUInt32();
+ std::string pxp = fields[9].GetCppString();
+ std::string pmaxxp = fields[10].GetCppString();
+ unsigned int money = fields[11].GetInt32();
+ std::string hk = fields[12].GetCppString();
+ std::string totaltim = SecToDay(fields[13].GetCppString());
+ delete result;
+ std::string sqlquery = "SELECT `gmlevel` FROM `account` WHERE `id` = '" + pacct + "';";
+ QueryResult *result = loginDatabase.Query(sqlquery.c_str());
+ Field *fields2 = result->Fetch();
+ std::string pgmlvl = fields2[0].GetCppString();
+ delete result;
+ std::string guildinfo = "";
+ if (pguildid != 0)
+ {
+ Guild* guild = objmgr.GetGuildById(pguildid);
+ if (guild)
+ {
+ guildinfo = " " + guild->GetRankName(pguildrank) + " Of " + guild->GetName();
+ }
+ }
+ else guildinfo = " None";
+ ChrRacesEntry const* prace = sChrRacesStore.LookupEntry(praceid);
+ ChrClassesEntry const* pclass = sChrClassesStore.LookupEntry(pclassid);
+
+ if (atoi(plevel.c_str()) < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
+ plevel += " (" + pxp + "/" + pmaxxp + ")";
+ unsigned int gold = money / 10000;
+ unsigned int silv = (money % 10000) / 100;
+ unsigned int cop = (money % 10000) % 100;
+ char tempgold [100];
+ sprintf(tempgold, "\x2\x3\x30\x37%ug \x3\x31\x34%us \x3\x30\x35%uc\xF", gold, silv, cop);
+ if (ponline == "\x3\x30\x33Online")
+ {
+ Player * plr = ObjectAccessor::Instance().FindPlayerByName(pname.c_str());
+ if (plr)
+ {
+ AreaTableEntry const* area = GetAreaEntryByAreaID(plr->GetAreaId());
+ ponline += " in " + (std::string) area->area_name[sWorld.GetDefaultDbcLocale()];
+ if (area->zone != 0)
+ {
+ AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone);
+ ponline += " (" + (std::string)zone->area_name[sWorld.GetDefaultDbcLocale()] + ")";
+ }
+ }
+ }
+ 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+" \xF |\x2 Latency:\x2\x3\x31\x30 "+templatency;
+ 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;
+ // pinfo3 = " :" + " \x2Honor Kills:\x2\x3\x31\x30 " + hk;
+ Send_IRCA(ChanOrPM(CD),pinfo , true, CD->TYPE);
+ Send_IRCA(ChanOrPM(CD),pinfo2 , true, CD->TYPE);
+ // Send_IRCA(ChanOrPM(CD),pinfo3 , true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Character ID. (GUID)" ,true, "ERROR");
+ }
+ else
+ {
+ QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account, name FROM characters WHERE name LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string items = "\x2 Character Search Results:\x3\x31\x30 ";
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ std::string guid = fields[0].GetCppString();
+ std::string account = fields[1].GetCppString();
+ std::string name = fields[2].GetCppString();
+ MakeUpper(name);
+ items.append(name+"(Account:"+account+" - GUID:"+guid+")\xF | \x3\x31\x30\x2");
+ result->NextRow();
+ }
+ delete result;
+ Send_IRCA(ChanOrPM(CD), items, true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Character. I Cant Find Any Characters With Those Search Terms." ,true, "ERROR");
+ }
+ }
+ if(_PARAMS[0] == "creature")
+ {
+ std::string creature = _PARAMS[1];
+ if(atoi(creature.c_str()) > 0)
+ {
+ WorldDatabase.escape_string(_PARAMS[1]);
+ 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());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+
+ uint32 entry = fields[0].GetUInt32();
+ uint32 modelid = fields[1].GetUInt32();
+ std::string name = fields[2].GetCppString();
+ uint32 level = fields[3].GetUInt32();
+ uint32 faction = fields[4].GetUInt32();
+ uint32 armor = fields[5].GetUInt32();
+ uint32 spawns = fields[6].GetUInt32();
+ delete result;
+
+ 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);
+ 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);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Creature ID." ,true, "ERROR");
+ }
+ else
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, name FROM creature_template WHERE name LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string items = "\002Creature Search Results:\x3\x31\x30 ";
+ //Send_IRCA(ChanOrPM(CD), "", true, CD->TYPE);
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ std::string CreatureID = fields[0].GetCppString();
+ std::string Name = fields[1].GetCppString();
+ items.append(Name+"("+CreatureID+")\xF | \x3\x31\x30\x2");
+ result->NextRow();
+ }
+ delete result;
+ Send_IRCA(ChanOrPM(CD), items, true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Creature. I Cant Find Any Creatures With Those Search Terms." ,true, "ERROR");
+ }
+ }
+ if(_PARAMS[0] == "faction")
+ {
+ std::string faction = _PARAMS[1];
+ if(atoi(faction.c_str()) > 0)
+ {
+ FactionEntry const *factionEntry = sFactionStore.LookupEntry(atoi(faction.c_str()));
+ if(factionEntry)
+ {
+ std::string name = factionEntry->name[sWorld.GetDefaultDbcLocale()];
+ 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);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown FactionID." ,true, "ERROR");
+
+ }
+ else
+ {
+ uint32 counter = 0;
+ std::string factions = "\002Faction Search Results:\x3\x31\x30 ";
+ for (uint32 id = 0; id < sFactionStore.GetNumRows(); id++)
+ {
+ FactionEntry const *factionEntry = sFactionStore.LookupEntry(id);
+ if(factionEntry)
+ {
+ MakeLower( _PARAMS[1] );
+ std::string name = factionEntry->name[sWorld.GetDefaultDbcLocale()];
+ MakeLower( name );
+ if (name.find(_PARAMS[1]) != std::string::npos && counter < 10)
+ {
+ char factionid[100];
+ sprintf(factionid, "%d", id);
+ factions.append(name+"("+factionid+")\xF | \x3\x31\x30\x2");
+ ++counter;
+ }
+ }
+ }
+ if(counter == 0)
+ factions.append("No Factions Found.");
+ Send_IRCA(ChanOrPM(CD), factions, true, CD->TYPE);
+ }
+ }
+ if(_PARAMS[0] == "go")
+ {
+ std::string gobject = _PARAMS[1];
+ if(atoi(gobject.c_str()) > 0)
+ {
+ WorldDatabase.escape_string(_PARAMS[1]);
+ 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());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+
+ uint32 entry = fields[0].GetUInt32();
+ uint32 type = fields[1].GetUInt32();
+ uint32 modelid = fields[2].GetUInt32();
+ std::string name = fields[3].GetCppString();
+ uint32 faction = fields[4].GetUInt32();
+ uint32 spawns = fields[5].GetUInt32();
+ delete result;
+
+ 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);
+ Send_IRCA(ChanOrPM(CD), MakeMsg("\x2Type:\x3\x31\x30 %d \xF|\x2 Faction:\x3\x31\x30 %d", type, faction), true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Creature ID." ,true, "ERROR");
+ }
+ else
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, name FROM gameobject_template WHERE name LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string gos = "\002Gameobject Search Results:\x3\x31\x30 ";
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ std::string GOID = fields[0].GetCppString();
+ std::string GoName = fields[1].GetCppString();
+ gos.append(GoName+"("+GOID+")\xF | \x3\x31\x30\x2");
+ result->NextRow();
+ }
+ delete result;
+ Send_IRCA(ChanOrPM(CD), gos, true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Game Object. I Cant Find Any Game Object's With Those Search Terms." ,true, "ERROR");
+ }
+ }
+ if(_PARAMS[0] == "item")
+ {
+ std::string item = _PARAMS[1];
+ if(atoi(item.c_str()) > 0)
+ {
+ 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());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ QueryResult *result2 = CharacterDatabase.PQuery("SELECT count(*) FROM `character_inventory` WHERE item_template = %s", _PARAMS[1].c_str());
+ Field *fields2 = result2->Fetch();
+ uint32 charcnt = fields2[0].GetUInt32();
+ delete result2;
+
+ uint32 ItemID = fields[0].GetUInt32();
+ std::string ItmName = fields[1].GetCppString();
+ uint32 DisplayID = fields[2].GetUInt32();
+ uint32 loots = 0;
+ loots = fields[3].GetUInt32();
+ delete result;
+ 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);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown ItemID." ,true, "ERROR");
+ }
+ else
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, name FROM `item_template` WHERE name LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string items = "\002Item Search Results:\x3\x31\x30 ";
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ std::string ItemID = fields[0].GetCppString();
+ std::string ItemName = fields[1].GetCppString();
+ items.append(ItemName+"("+ItemID+")\xF | \x3\x31\x30\x2");
+ result->NextRow();
+ }
+ delete result;
+ Send_IRCA(ChanOrPM(CD), items, true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Item. I Cant Find Any Items With Those Search Terms." ,true, "ERROR");
+ }
+ }
+ if(_PARAMS[0] == "quest")
+ {
+ std::string quest = _PARAMS[1];
+ if(atoi(quest.c_str()) > 0)
+ {
+ WorldDatabase.escape_string(_PARAMS[1]);
+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, Title FROM quest_template WHERE entry = '%s';", _PARAMS[1].c_str(), _PARAMS[1].c_str());
+ if(result)
+ {
+ QueryResult *result2 = CharacterDatabase.PQuery("SELECT count(*) FROM character_queststatus WHERE quest = '%s' AND status = '1';", _PARAMS[1].c_str());
+ Field *fields2 = result2->Fetch();
+ uint32 status = fields2[0].GetUInt32();
+ delete result2;
+
+ Field *fields = result->Fetch();
+ uint32 entry = fields[0].GetUInt32();
+ std::string name = fields[1].GetCppString();
+ delete result;
+ 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);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Quest ID." ,true, "ERROR");
+ }
+ else
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, Title FROM quest_template WHERE Title LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string quests = "\002Quest Search Results:\x3\x31\x30 ";
+ //Send_IRCA(ChanOrPM(CD), "", true, CD->TYPE);
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ std::string QuestID = fields[0].GetCppString();
+ std::string QuestName = fields[1].GetCppString();
+ quests.append(QuestName+"("+QuestID+")\xF | \x3\x31\x30\x2");
+ result->NextRow();
+ }
+ delete result;
+ Send_IRCA(ChanOrPM(CD), quests, true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Quest. I Cant Find Any Quest's With Those Search Terms." ,true, "ERROR");
+ }
+ }
+ if(_PARAMS[0] == "skill")
+ {
+ std::string skill = _PARAMS[1];
+ if(atoi(skill.c_str()) > 0)
+ {
+ SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(atoi(skill.c_str()));
+ if(skillInfo)
+ {
+ std::string name = skillInfo->name[sWorld.GetDefaultDbcLocale()];
+ 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);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown SkillID." ,true, "ERROR");
+
+ }
+ else
+ {
+ uint32 counter = 0;
+ std::string skills = "\002Skill Search Results:\x3\x31\x30 ";
+ for (uint32 id = 0; id < sSkillLineStore.GetNumRows(); id++)
+ {
+ SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(id);
+ if(skillInfo)
+ {
+ MakeLower( _PARAMS[1] );
+ std::string name = skillInfo->name[sWorld.GetDefaultDbcLocale()];
+ MakeLower( name );
+ if (name.find(_PARAMS[1]) != std::string::npos && counter < 10)
+ {
+ char skillid[100];
+ sprintf(skillid, "%d", id);
+ skills.append(name+"("+skillid+")\xF | \x3\x31\x30\x2");
+ ++counter;
+ }
+ }
+ }
+ if(counter == 0)
+ skills.append("No Skills Found.");
+ Send_IRCA(ChanOrPM(CD), skills, true, CD->TYPE);
+ }
+ }
+ if(_PARAMS[0] == "spell")
+ {
+ std::string spell = _PARAMS[1];
+ if(atoi(spell.c_str()) > 0)
+ {
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(atoi(spell.c_str()));
+ if(spellInfo)
+ {
+ std::string name = spellInfo->SpellName[sWorld.GetDefaultDbcLocale()];
+ 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);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown SpellID." ,true, "ERROR");
+
+ }
+ else
+ {
+ uint32 counter = 0;
+ std::string spells = "\002Spell Search Results:\x3\x31\x30 ";
+ for (uint32 id = 0; id < sSpellStore.GetNumRows(); id++)
+ {
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(id);
+ if(spellInfo)
+ {
+ MakeLower( _PARAMS[1] );
+ std::string name = spellInfo->SpellName[sWorld.GetDefaultDbcLocale()];
+ MakeLower( name );
+ if (name.find(_PARAMS[1]) != std::string::npos && counter < 10)
+ {
+ char itemid[100];
+ sprintf(itemid, "%d", id);
+ spells.append(name+"("+itemid+")\xF | \x3\x31\x30\x2");
+ ++counter;
+ }
+ }
+ }
+ if(counter == 0)
+ spells.append("No Spells Found.");
+ Send_IRCA(ChanOrPM(CD), spells, true, CD->TYPE);
+ }
+ }
+ if(_PARAMS[0] == "tele")
+ {
+ std::string tele = _PARAMS[1];
+ if(atoi(tele.c_str()) > 0)
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT * FROM `game_tele` WHERE id = %s", _PARAMS[1].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+
+ uint32 teleid = fields[0].GetUInt32();
+ uint32 pos_x = fields[1].GetUInt32();
+ uint32 pos_y = fields[2].GetUInt32();
+ uint32 pos_z = fields[3].GetUInt32();
+ uint32 oriet = fields[4].GetUInt32();
+ uint32 map = fields[5].GetUInt32();
+ std::string telname = fields[6].GetCppString();
+ delete result;
+
+ 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);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Teleport Location ID." ,true, "ERROR");
+ }
+ else
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT id, name FROM `game_tele` WHERE name LIKE '%%%s%%' LIMIT 10", _PARAMS[1].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string teles = "\002Tele Location Search Results:\x3\x31\x30 ";
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ std::string TeleID = fields[0].GetCppString();
+ std::string TeleName = fields[1].GetCppString();
+ teles.append(TeleName+"("+TeleID+")\xF | \x3\x31\x30\x2");
+ result->NextRow();
+ }
+ Send_IRCA(ChanOrPM(CD), teles, true, CD->TYPE);
+ delete result;
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Unknown Item. I Cant Find Any Items With Those Search Terms." ,true, "ERROR");
+ }
+ }
+}
+
+void IRCCmd::Level_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, CD->PCOUNT);
+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
+ return;
+ }
+ std::string player = _PARAMS[0];
+ normalizePlayerName(player);
+ uint64 guid = objmgr.GetPlayerGUIDByName(player.c_str());
+ std::string s_newlevel = _PARAMS[1];
+ uint8 i_newlvl = atoi(s_newlevel.c_str());
+ if(!guid)
+ {
+ Send_IRCA(CD->USER, "\0034[ERROR] : Player Not Found!", true, "ERROR");
+ return;
+ } else if ( i_newlvl < 1 || i_newlvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) )
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Level Must Be Between 1 And %i!",sConfig.GetIntDefault("MaxPlayerLevel", 70)), true, "ERROR");
+ return;
+ } else
+ {
+ Player *chr = objmgr.GetPlayer(guid);
+ int32 i_oldlvl = chr ? chr->getLevel() : Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,guid);
+ if(chr)
+ {
+ chr->GiveLevel(i_newlvl);
+ chr->InitTalentForLevel();
+ chr->SetUInt32Value(PLAYER_XP,0);
+ WorldPacket data;
+ ChatHandler CH(chr->GetSession());
+ if(i_oldlvl == i_newlvl)
+ CH.FillSystemMessageData(&data, "Your level progress has been reset.");
+ else
+ if(i_oldlvl < i_newlvl)
+ CH.FillSystemMessageData(&data, fmtstring("You have been leveled up (%i)",i_newlvl-i_oldlvl));
+ else
+ if(i_oldlvl > i_newlvl)
+ CH.FillSystemMessageData(&data, fmtstring("You have been leveled down (%i)",i_newlvl-i_oldlvl));
+ chr->GetSession()->SendPacket( &data );
+ }
+ else
+ {
+ Tokens values;
+ Player::LoadValuesArrayFromDB(values,guid);
+ Player::SetUInt32ValueInArray(values,UNIT_FIELD_LEVEL,i_newlvl);
+ Player::SetUInt32ValueInArray(values,PLAYER_XP,0);
+ Player::SaveValuesArrayInDB(values,guid);
+ }
+ }
+ Send_IRCA(ChanOrPM(CD), "\00313[" + _PARAMS[0]+ "] : Has Been Leveled To " + _PARAMS[1] + ". By: "+CD->USER+".", true, CD->TYPE);
+}
+
+void IRCCmd::Money_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 2);
+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
+ return;
+ }
+ std::string player = _PARAMS[0];
+ normalizePlayerName(player);
+ uint64 guid = objmgr.GetPlayerGUIDByName(player.c_str());
+ Player *chr = objmgr.GetPlayer(guid);
+
+ std::string s_money = _PARAMS[1];
+ int32 money = atoi(s_money.c_str());
+ unsigned int gold = money / 10000;
+ unsigned int silv = (money % 10000) / 100;
+ unsigned int cop = (money % 10000) % 100;
+ char tempgold [100];
+ sprintf(tempgold, "\x2\x3\x30\x37%ug \x3\x31\x34%us \x3\x30\x35%uc\xF", gold, silv, cop);
+ if(!guid)
+ {
+ Send_IRCA(CD->USER, "\0034[ERROR] : Player Not Found!", true, "ERROR");
+ return;
+ }
+ else
+ {
+ Player *chr = objmgr.GetPlayer(guid);
+ uint32 moneyuser = 0;
+ if(chr)
+ moneyuser = chr->GetMoney();
+ else {
+ CharacterDatabase.escape_string(player);
+ std::string sqlquery = "SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(data, ' ' , 1462), ' ' , -1) AS `gold` FROM `characters` WHERE `name` = '"+player+"';";
+ QueryResult *result = CharacterDatabase.Query(sqlquery.c_str());
+ Field *fields = result->Fetch();
+ moneyuser = fields[0].GetInt32();
+ delete result;
+ }
+ int32 addmoney = money;
+ int32 newmoney = moneyuser + addmoney;
+ char s_newmoney[255];
+ sprintf(s_newmoney,"%d",newmoney);
+ if(addmoney < 0)
+ {
+ sLog.outDetail("USER1: %i, ADD: %i, DIF: %i\\n", moneyuser, addmoney, newmoney);
+ if(newmoney <= 0 )
+ {
+ Send_IRCA(ChanOrPM(CD), "\00313["+player+"] : Has Had All Money Taken By: "+CD->USER.c_str()+".", true, CD->TYPE);
+ if(chr)
+ {
+ chr->SetMoney(0);
+ Send_Player(chr, MakeMsg("You Have Been Liquidated By: %s. Total Money Is Now 0.", CD->USER.c_str()));
+ }
+ else
+ 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 );
+ }
+ else
+ {
+ Send_IRCA(ChanOrPM(CD), "\00313["+player+"] : Has Had ("+s_money+"\00313) Taken From Them By: "+CD->USER.c_str()+".", true, CD->TYPE);
+ if(chr)
+ {
+ chr->SetMoney( newmoney );
+ Send_Player(chr, MakeMsg("You Have Had %s Copper Taken From You By: %s.", _PARAMS[1].c_str(), CD->USER.c_str()));
+ }
+ else
+ 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 );
+ }
+ }
+ else
+ {
+ Send_IRCA(ChanOrPM(CD), "\00313["+player+"] : Has Been Given ("+tempgold+"\00313) From: "+CD->USER.c_str()+".", true, CD->TYPE);
+ if(chr)
+ {
+ chr->ModifyMoney( addmoney );
+ Send_Player(chr, MakeMsg("You Have Been Given %s Copper. From: %s.", _PARAMS[1].c_str(), CD->USER.c_str()));
+ }
+ else
+ 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 );
+ }
+ }
+}
+
+void IRCCmd::Mute_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 3);
+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
+ return;
+ }
+ normalizePlayerName(_PARAMS[0]);
+ uint64 guid = objmgr.GetPlayerGUIDByName(_PARAMS[0]);
+ if(guid)
+ {
+ if(_PARAMS[1] == "release")
+ {
+ Player* plr = objmgr.GetPlayer(guid);
+ uint32 account_id = 0;
+ account_id = objmgr.GetPlayerAccountIdByGUID(guid);
+ loginDatabase.PExecute("UPDATE `account` SET `mutetime` = '0' WHERE `id` = '%u'", account_id );
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Been UnMuted By: "+CD->USER+"." , true, CD->TYPE);
+ if(plr)
+ {
+ plr->GetSession()->m_muteTime = 0;
+ Send_Player(plr, MakeMsg("You Have Been UnMuted By: %s.", CD->USER.c_str()));
+ }
+ }
+ else
+ {
+ if(_PARAMS[2] == "")
+ _PARAMS[2] = "No Reason Given";
+ Player* plr = objmgr.GetPlayer(guid);
+ time_t mutetime = time(NULL) + atoi(_PARAMS[1].c_str())*60;
+ uint32 account_id = 0;
+ account_id = objmgr.GetPlayerAccountIdByGUID(guid);
+ if(plr) plr->GetSession()->m_muteTime = mutetime;
+ loginDatabase.PExecute("UPDATE `account` SET `mutetime` = " I64FMTD " WHERE `id` = '%u'",uint64(mutetime), account_id );
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Been Muted By: "+CD->USER+". For: "+_PARAMS[1]+" Minutes. Reason: "+_PARAMS[2] , true, CD->TYPE);
+ 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()));
+ }
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Player Does Not Exist!", true, "ERROR");
+}
+
+void IRCCmd::Online_Players(_CDATA *CD)
+{
+ sIRC.Script_Lock[MCS_Players_Online] = true;
+ ZThread::Thread script(new mcs_OnlinePlayers(CD));
+}
+
+void IRCCmd::PM_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 2);
+ if (Player* plr = GetPlayer(_PARAMS[0]))
+ {
+ if(plr->isAcceptWhispers())
+ {
+ std::string sMsg = MakeMsg("|cffFE87FD[<IRC>%s] Whispers: %s|r", CD->USER.c_str(), _PARAMS[1].c_str());
+ WorldPacket data(SMSG_MESSAGECHAT, 200);
+ data << (uint8)CHAT_MSG_SYSTEM;
+ data << (uint32)LANG_UNIVERSAL;
+ data << (uint64)plr->GetGUID();
+ data << (uint32)0;
+ data << (uint64)plr->GetGUID();
+ data << (uint32)(sMsg.length()+1);
+ data << sMsg;
+ data << (uint8)0;
+ plr->GetSession()->SendPacket(&data);
+ plr->SendPlaySound(3081, true);
+ Send_IRCA(ChanOrPM(CD), "\00313To ["+_PARAMS[0]+"] : "+_PARAMS[1]+".", true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Is Not Accepting Private Messages!", true, "ERROR");
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Player not online!", true, "ERROR");
+}
+
+void IRCCmd::Revive_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, CD->PCOUNT);
+ if (Player* plr = GetPlayer(_PARAMS[0]))
+ {
+ if(plr->isDead())
+ {
+ plr->ResurrectPlayer(0.5f);
+ plr->SpawnCorpseBones();
+ plr->SaveToDB();
+ sIRC.Send_IRC_Channel(ChanOrPM(CD), " \00313["+_PARAMS[0]+"] : Has Been Revived By: " + CD->USER, true, CD->TYPE);
+ Send_Player(plr, MakeMsg("You Have Been Revived By: %s.", CD->USER.c_str()));
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Not Dead!", true, "ERROR");
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : "+_PARAMS[0]+" Is Not Online!", true, "ERROR");
+}
+
+void IRCCmd::Saveall_Player(_CDATA *CD)
+{
+ ObjectAccessor::Instance().SaveAllPlayers();
+ Send_IRCA(ChanOrPM(CD), "\00313["+CD->USER+"] : Has Saved All Players!", true, CD->TYPE);
+}
+
+void IRCCmd::Shutdown_Mangos(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 1);
+ if(_PARAMS[0] == "cancel")
+ {
+ sWorld.ShutdownCancel();
+ Send_IRCA(ChanOrPM(CD), "\0034Server Shutdown Has Been Cancelled.", true, CD->TYPE);
+ }
+
+ int32 i_time = atoi(_PARAMS[0].c_str());
+ if (i_time <= 0 && _PARAMS[0]!="0")
+ {
+ Send_IRCA(ChanOrPM(CD), "\00313["+CD->USER+"] : Please Enter A Number! And No Negative Numbers! "+_PARAMS[0]+" Seconds!?", true, CD->TYPE);
+ return;
+ }
+ 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);
+ sWorld.ShutdownServ(i_time);
+ Delay(i_time*1000);
+ Send_IRCA(ChanOrPM(CD), "\0034Server Will Now Shut Down.. Good Bye!", true, CD->TYPE);
+ sIRC.Active = false;
+ sIRC.ResetIRC();
+}
+
+void IRCCmd::Spell_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 3);
+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
+ return;
+ }
+ uint32 spell = atoi(_PARAMS[2].c_str());
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell);
+ if (Player* plr = GetPlayer(_PARAMS[0]))
+ {
+ if(spellInfo)
+ {
+ std::string name = spellInfo->SpellName[sWorld.GetDefaultDbcLocale()];
+ if(_PARAMS[1] == "cast")
+ {
+ plr->CastSpell(plr, spell, true);
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Had Spell "+name+" Casted On Them.", true, CD->TYPE);
+ }
+ if(_PARAMS[1] == "learn")
+ {
+ plr->learnSpell(spell);
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Learned Spell "+name+".", true, CD->TYPE);
+ }
+ if(_PARAMS[1] == "unlearn")
+ {
+ plr->removeSpell(spell);
+ Send_IRCA(ChanOrPM(CD), "\00313["+_PARAMS[0]+"] : Has Unlearned Spell "+name+".", true, CD->TYPE);
+ }
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Incorrect Spell ID!", true, "ERROR");
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Player Not Online!", true, "ERROR");
+}
+
+void IRCCmd::Sysmsg_Server(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, CD->PCOUNT);
+ std::string ircchan = "#";
+ ircchan += sIRC._irc_chan[sIRC.anchn].c_str();
+ if(_PARAMS[0] == "a")
+ {
+ //std::string str = "|cffff0000[System Message]:|r" + _PARAMS[1];
+ std::string ancmsg = MakeMsg("\00304,08\037/!\\\037\017\00304 System Message \00304,08\037/!\\\037\017 %s",_PARAMS[1].c_str());
+ sWorld.SendWorldText(LANG_SYSTEMMESSAGE, _PARAMS[1].c_str());
+ sIRC.Send_IRC_Channel(ircchan, ancmsg, true);
+ }
+ else if (_PARAMS[0] == "e")
+ {
+ std::string str = "|cffff0000[Server Event]:|r " + _PARAMS[1];
+ std::string notstr = "[Server Event]: " + _PARAMS[1];
+ std::string notmsg = MakeMsg("\00304,08\037/!\\\037\017\00304 Server Event \00304,08\037/!\\\037\017 %s",_PARAMS[1].c_str());
+ WorldPacket data(SMSG_NOTIFICATION, (notstr.size()+1));
+ data << notstr;
+ WorldPacket data2(SMSG_PLAY_SOUND,32);
+ data2 << (uint32)1400;
+ sWorld.SendGlobalMessage(&data2);
+ sWorld.SendGlobalMessage(&data);
+ sWorld.SendWorldText(LANG_EVENTMESSAGE, _PARAMS[1].c_str());
+ sIRC.Send_IRC_Channel(ircchan, notmsg, true);
+ }
+ else if (_PARAMS[0] == "n")
+ {
+ std::string str = "Global notify: " + _PARAMS[1];
+ std::string notmsg = MakeMsg("\00304,08\037/!\\\037\017\00304 Global Notify \00304,08\037/!\\\037\017 %s",_PARAMS[1].c_str());
+ WorldPacket data(SMSG_NOTIFICATION, (str.size()+1));
+ data << str;
+ sWorld.SendGlobalMessage(&data);
+ sIRC.Send_IRC_Channel(ircchan, notmsg, true);
+ }
+ else if (_PARAMS[0] == "add")
+ {
+ sIRC.Send_IRC_Channel(ircchan, "This command is currently borken.", true);
+ // Commented for now -- timer broken
+ //WorldDatabase.PExecute( "INSERT INTO IRC_AutoAnnounce (message, addedby) VALUES ('%s', '%s')", _PARAMS[1].c_str(), CD->USER.c_str());
+ //std::string str = "|cffff0000[Automatic]:|r" + _PARAMS[1];
+ //std::string ancmsg = MakeMsg("\00304,08\037/!\\\037\017\00304 Automatic System Message \00304,08\037/!\\\037\017 %s",_PARAMS[1].c_str());
+ //sWorld.SendWorldText(LANG_AUTO_ANN, _PARAMS[1].c_str());
+ //sIRC.Send_IRC_Channel(ircchan, ancmsg, true);
+ }
+ else if (_PARAMS[0] == "del")
+ {
+ WorldDatabase.PExecute( "DELETE FROM IRC_AutoAnnounce WHERE id = %s", _PARAMS[1].c_str());
+ Send_IRCA(ChanOrPM(CD), MakeMsg("Deleted Automatic Announcement Message ID: %s", _PARAMS[1].c_str()), true, CD->TYPE);
+ }
+ else if (_PARAMS[0] == "list")
+ {
+ QueryResult *result = WorldDatabase.PQuery("SELECT * FROM IRC_AutoAnnounce LIMIT 5;", _PARAMS[1].c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ std::string id = fields[0].GetCppString();
+ std::string message = fields[1].GetCppString();
+ std::string addedby = fields[2].GetCppString();
+ Send_IRCA(ChanOrPM(CD), MakeMsg("ID: %s - Added By: %s - Message: %s", id.c_str(), addedby.c_str(), message.c_str()), true, CD->TYPE);
+ result->NextRow();
+ }
+ delete result;
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : No Auto Announce Messages Are In The Database.", true, "ERROR");
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Please Use (a-Announce)(n-Notify)(e-Event) As Second Parameter!", true, "ERROR");
+}
+
+void IRCCmd::Tele_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 4);
+ if(AcctLevel(_PARAMS[0]) > GetLevel(CD->USER) && (sIRC.BOTMASK & 512)!= 0)
+ {
+ Send_IRCA(CD->USER, MakeMsg("\0034[ERROR] : Nice Try, This Player Has A Higher GM Level Than You! [ %i ]", AcctLevel(_PARAMS[0])), true, "ERROR");
+ return;
+ }
+ bool DoTeleport = false;
+ float pX, pY, pZ, pO = 0;
+ uint32 mapid = 0;
+ std::string rMsg = " \0034[ERROR] : Teleport Failed!";
+ std::string wMsg = "Invalid Tele Location";
+ Player* plr = GetPlayer(_PARAMS[0]);
+ if(plr)
+ {
+ if(plr->isInFlight() || plr->isInCombat())
+ {
+ 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");
+ return;
+ }
+ }
+ if(_PARAMS[1] == "l" || _PARAMS[1].size() > 2)
+ {
+ if(_PARAMS[1].size() > 1)
+ _PARAMS[2] = _PARAMS[1];
+ WorldDatabase.escape_string(_PARAMS[2]);
+ QueryResult *result = WorldDatabase.PQuery("SELECT position_x, position_y, position_z, orientation, map FROM game_tele WHERE name='%s';", _PARAMS[2].c_str());
+ if (result)
+ {
+ Field *fields = result->Fetch();
+ pX = fields[0].GetFloat();
+ pY = fields[1].GetFloat();
+ pZ = fields[2].GetFloat();
+ pO = fields[3].GetFloat();
+ mapid = fields[4].GetUInt16();
+ delete result;
+ rMsg = MakeMsg(" \00313[%s] : Teleported To %s! By: %s.",
+ _PARAMS[0].c_str(),
+ _PARAMS[2].c_str(),
+ CD->USER.c_str());
+ wMsg = MakeMsg("You Have Been Teleported To %s By: %s.",
+ _PARAMS[2].c_str(),
+ CD->USER.c_str());
+ DoTeleport = true;
+ }
+ else
+ {
+ WorldDatabase.escape_string(_PARAMS[2]);
+ QueryResult *result = WorldDatabase.PQuery("SELECT name FROM game_tele WHERE name LIKE '%%%s%%' LIMIT 7;", _PARAMS[2].c_str());
+ if (result)
+ {
+ std::string telename = "<> ";
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ Field *fields = result->Fetch();
+ telename.append(fields[0].GetCppString());
+ result->NextRow();
+ telename.append(" <> ");
+ }
+ delete result;
+ Send_IRCA(CD->USER, "I Cannot Find Location: "+_PARAMS[2]+" . Perhaps One Of These Will Work For You.", true, "ERROR");
+ Send_IRCA(CD->USER, telename, true, "ERROR");
+ return;
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Location Not Found! Nothing Even Close Found!", true, "ERROR");
+ return;
+ }
+ }
+ else if(_PARAMS[1] == "c")
+ {
+ std::string* _PARAMSA = getArray(_PARAMS[2], 4);
+ pX = atof(_PARAMSA[1].c_str());
+ pY = atof(_PARAMSA[2].c_str());
+ pZ = atof(_PARAMSA[3].c_str());
+ mapid = atoi(_PARAMSA[0].c_str());
+ rMsg = MakeMsg(" \00313[%s] : Teleported To Map: %s. Position: X(%s) Y(%s) Z(%s)! By: %s.",
+ _PARAMS[0].c_str(),
+ _PARAMSA[0].c_str(),
+ _PARAMSA[1].c_str(),
+ _PARAMSA[2].c_str(),
+ _PARAMSA[3].c_str(),
+ CD->USER.c_str());
+ wMsg = MakeMsg("You Have Been Teleported To Map: %s. Position: X(%s) Y(%s) Z(%s)! By: %s.",
+ _PARAMSA[0].c_str(),
+ _PARAMSA[1].c_str(),
+ _PARAMSA[2].c_str(),
+ _PARAMSA[3].c_str(),
+ CD->USER.c_str());
+ DoTeleport = true;
+ }
+ else if(_PARAMS[1] == "r")
+ {
+ if(plr)
+ {
+ pX = plr->m_recallX;
+ pY = plr->m_recallY;
+ pZ = plr->m_recallZ;
+ pO = plr->m_recallO;
+ mapid = plr->m_recallMap;
+ rMsg = MakeMsg(" \00313[%s] : Has Been Recalled To Their Previous Location.",
+ _PARAMS[0].c_str());
+ wMsg = MakeMsg("You Have Been Recalled To Your Previous Location. By: %s",
+ CD->USER.c_str());
+ DoTeleport = true;
+ }
+ else
+ {
+ Send_IRCA(CD->USER, MakeMsg("\00313[%s] : Cannot Be Recalled, They Are Not Online.", _PARAMS[0].c_str()), true, "ERROR");
+ return;
+ }
+
+ }
+ else if(_PARAMS[1] == "to")
+ {
+ Player* plr2 = GetPlayer(_PARAMS[2]);
+ if(plr2)
+ {
+ plr2->GetContactPoint(plr, pX, pY, pZ);
+ mapid = plr2->GetMapId();
+ }
+ else
+ {
+ if(uint64 guid = objmgr.GetPlayerGUIDByName(_PARAMS[2].c_str()))
+ {
+ bool in_flight;
+ Player::LoadPositionFromDB(mapid, pX, pY, pZ, pO, in_flight, guid);
+ }
+ else
+ {
+ Send_IRCA(CD->USER, "\0034[ERROR] : Second Player Not Found!", true, "ERROR");
+ return;
+ }
+ }
+ rMsg = MakeMsg(" \00313[%s] : Teleported To Player: [%s] By: %s.",
+ _PARAMS[0].c_str(),
+ _PARAMS[2].c_str(),
+ CD->USER.c_str());
+ wMsg = MakeMsg("You Are Being Teleported To: %s. By: %s.",
+ _PARAMS[2].c_str(),
+ CD->USER.c_str());
+ DoTeleport = true;
+ }
+ if(DoTeleport)
+ {
+ if(MapManager::IsValidMapCoord(mapid, pX ,pY))
+ {
+ //if player is online teleport them in real time, if not set the DB to our coordinates.
+ if(plr)
+ {
+ plr->SaveRecallPosition();
+ plr->TeleportTo(mapid, pX, pY, pZ, pO);
+ sIRC.Send_IRC_Channel(ChanOrPM(CD), rMsg, true, CD->TYPE);
+ Send_Player(plr, wMsg);
+ }
+ else
+ {
+ uint64 guid = objmgr.GetPlayerGUIDByName(_PARAMS[0]);
+ Player::SavePositionInDB(mapid,pX,pY,pZ,pO,MapManager::Instance().GetZoneId(mapid,pX,pY),guid);
+ sIRC.Send_IRC_Channel(ChanOrPM(CD), rMsg + " \0034*Offline Tele.* ", true, CD->TYPE);
+ }
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Invalid Location!", true, "ERROR");
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : Invalid Paramaters, Please Try Again [ "+sIRC._cmd_prefx+"help tele ] For More Information. ", true, "ERROR");
+}
+
+void IRCCmd::Top_Player(_CDATA *CD)
+{
+ std::string* _PARAMS = getArray(CD->PARAMS, 2);
+ uint32 limitr = 10;
+ if(atoi(_PARAMS[1].c_str()) > 0 && GetLevel(CD->USER) >= sIRC._op_gm_lev)
+ limitr = atoi(_PARAMS[1].c_str());
+ if(_PARAMS[0] == "accttime")
+ {
+ QueryResult *result = CharacterDatabase.PQuery("SELECT account, name, (SUM(totaltime)) AS combinetime FROM characters GROUP BY account ORDER BY combinetime DESC LIMIT 0, %d ", limitr);
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string tptime = MakeMsg("\x2 Top%d Accounts By Played Time:\x3\x31\x30 ", limitr);
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ uint32 account = fields[0].GetUInt32();
+ std::string PlName = GetAcctNameFromID(account);
+ std::string Time = SecToDay(fields[2].GetCppString());
+ uint32 rank = i+1;
+ tptime.append(MakeMsg("[%u]%s %s \xF| \x3\x31\x30\x2", rank, PlName.c_str(), Time.c_str()));
+ result->NextRow();
+ }
+ delete result;
+ Send_IRCA(ChanOrPM(CD), tptime, true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : No Accounts Returned." ,true, "ERROR");
+ }
+ if(_PARAMS[0] == "chartime")
+ {
+ QueryResult *result = CharacterDatabase.PQuery("SELECT name, totaltime FROM characters ORDER BY totaltime DESC LIMIT 0, %d ", limitr);
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string tptime = MakeMsg("\x2 Top%d Characters By Played Time:\x3\x31\x30 ", limitr);
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ std::string Name = fields[0].GetCppString();
+ std::string Time = SecToDay(fields[1].GetCppString());
+ uint32 rank = i+1;
+ tptime.append(MakeMsg("[%u]%s %s \xF| \x3\x31\x30\x2", rank, Name.c_str(), Time.c_str()));
+ result->NextRow();
+ }
+ delete result;
+ Send_IRCA(ChanOrPM(CD), tptime, true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : No Characters Returned." ,true, "ERROR");
+ }
+ if(_PARAMS[0] == "money")
+ {
+ 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);
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string tptime = MakeMsg("\x2 Top%d Characters By Money:\x3\x31\x30 ", limitr);
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ std::string Name = fields[0].GetCppString();
+ unsigned int money = fields[1].GetInt32();
+
+ uint32 rank = i+1;
+
+ unsigned int gold = money / 10000;
+ unsigned int silv = (money % 10000) / 100;
+ unsigned int cop = (money % 10000) % 100;
+ char tempgold [100];
+ sprintf(tempgold, "\x2\x3\x30\x37%ug \x3\x31\x34%us \x3\x30\x35%uc\xF", gold, silv, cop);
+
+ tptime.append(MakeMsg("[%u]%s %s \xF| \x3\x31\x30\x2", rank, Name.c_str(), tempgold));
+ result->NextRow();
+ }
+ delete result;
+ Send_IRCA(ChanOrPM(CD), tptime, true, CD->TYPE);
+ }
+ else
+ Send_IRCA(CD->USER, "\0034[ERROR] : No Characters Returned." ,true, "ERROR");
+ }
+
+}
+
+void IRCCmd::Who_Logged(_CDATA *CD)
+{
+ std::string OPS = "";
+ for(std::list<_client*>::iterator i=_CLIENTS.begin(); i!=_CLIENTS.end();i++)
+ {
+ OPS.append(MakeMsg(" \002[GM:%d IRC: %s - WoW: %s]\002 ", (*i)->GMLevel, (*i)->Name.c_str(), (*i)->UName.c_str()));
+ }
+ Send_IRCA(ChanOrPM(CD), OPS, true, CD->TYPE);
+}
diff --git a/src/game/IRCConf.cpp b/src/game/IRCConf.cpp
new file mode 100644
index 00000000000..92102cd9e41
--- /dev/null
+++ b/src/game/IRCConf.cpp
@@ -0,0 +1,172 @@
+/*
+ * MangChat By |Death| And Cybrax
+ *
+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
+ * Of The GNU General Public License
+ * Written and Developed by Cybrax. cybraxvd@gmail.com
+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
+ * With Help And Support From The MaNGOS Project Community.
+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
+ */
+#include "IRCClient.h"
+#include "IRCCmd.h"
+#include "../shared/Config/Config.h"
+#include "IRCConf.h"
+Config MCConfig;
+void IRCClient::SetCfg(char const* cfgfile)
+{
+ sIRC.CfgFile = cfgfile;
+}
+bool IRCClient::LoadConfig(char const* cfgfile)
+{
+ if (!MCConfig.SetSource(cfgfile))
+ sLog.outString("*** MangChat: Unable to open configuration file, All default options are being used.");
+ else sLog.outString("*** MangChat: Found the configuration file, %s", cfgfile);
+
+ int ConfCnt = 0;
+ sIRC._chan_count = 0;
+ if(MCConfig.GetIntDefault("irc.active", 1) == 1)
+ sIRC.Active = true;
+ else
+ sIRC.Active = false;
+ sIRC._Host = MCConfig.GetStringDefault("irc.host", "irc.freenode.net");
+ if(sIRC._Host.size() > 0)
+ ConfCnt++;
+ sIRC._Mver = MCConfig.GetStringDefault("irc.mver", "Version 1.6.5");
+ sIRC._Port = MCConfig.GetIntDefault("irc.port", 6667);
+ sIRC._User = MCConfig.GetStringDefault("irc.user", "MangChat");
+ sIRC._Pass = MCConfig.GetStringDefault("irc.pass", "MyDumbPass");
+ sIRC._Nick = MCConfig.GetStringDefault("irc.nick", "MangChat");
+ sIRC._Auth = MCConfig.GetIntDefault("irc.auth", 0);
+ sIRC._Auth_Nick = MCConfig.GetStringDefault("irc.auth.nick", "AuthNick");
+ sIRC._ICC = MCConfig.GetStringDefault("irc.icc", "001");
+ sIRC._defchan = MCConfig.GetStringDefault("irc.defchan", "lobby");
+ sIRC._ldefc = MCConfig.GetIntDefault("irc.ldef", 0);
+ sIRC._wct = MCConfig.GetIntDefault("irc.wct", 30000);
+ sIRC.ajoin = MCConfig.GetIntDefault("irc.ajoin", 1);
+ sIRC.ajchan = MCConfig.GetStringDefault("irc.ajchan", "world");
+ sIRC.onlrslt = MCConfig.GetIntDefault("irc.online.result", 10);
+ sIRC.BOTMASK = MCConfig.GetIntDefault("Botmask", 0);
+ sIRC.logfile = MCConfig.GetStringDefault("irc.logfile.prefix", "IRC_");
+ for(int i = 1; i < MAX_CONF_CHANNELS;i++)
+ {
+ std::ostringstream ss;
+ ss << i;
+ std::string ci = "irc.chan_" + ss.str();
+ std::string t_chan = MCConfig.GetStringDefault(ci.c_str(), "");
+ if(t_chan.size() > 0)
+ {
+ sIRC._chan_count++;
+ sIRC._irc_chan[sIRC._chan_count] = t_chan;
+ ci = "wow.chan_" + ss.str();
+ sIRC._wow_chan[sIRC._chan_count] = MCConfig.GetStringDefault(ci.c_str(), t_chan.c_str());
+ }
+ }
+ sIRC.JoinMsg = MCConfig.GetStringDefault("irc.joinmsg", "Whhaaazzzzaaaa, MangChat $Ver Baby!!");
+ sIRC.RstMsg = MCConfig.GetStringDefault("irc.rstmsg", "MangChat Is Restarting, I Will Be Right Back!");
+ sIRC.kikmsg = MCConfig.GetStringDefault("irc.kickmsg", "Do Not Kick Me Again, Severe Actions Will Be Taken!");
+ // IRC LINES
+ sIRC.ILINES[WOW_IRC] = MCConfig.GetStringDefault("chat.wow_irc", "\003<WoW>[\002$Name($Level)\002\003] $Msg");
+ sIRC.ILINES[IRC_WOW] = MCConfig.GetStringDefault("chat.irc_wow", "\003<IRC>[$Name]: $Msg");
+ sIRC.ILINES[JOIN_WOW] = MCConfig.GetStringDefault("chat.join_wow", "\00312>>\00304 $Name \003Joined The Channel!");
+ sIRC.ILINES[JOIN_IRC] = MCConfig.GetStringDefault("chat.join_irc", "\003[$Name]: Has Joined IRC!");
+ sIRC.ILINES[LEAVE_WOW] = MCConfig.GetStringDefault("chat.leave_wow", "\00312<<\00304 $Name \003Left The Channel!");
+ sIRC.ILINES[LEAVE_IRC] = MCConfig.GetStringDefault("chat.leave_irc", "\003[$Name]: Has Left IRC!");
+ sIRC.ILINES[CHANGE_NICK] = MCConfig.GetStringDefault("chat.change_nick", "\003<> $Name Is Now Known As $NewName!");
+ // MangChat Options
+ sIRC._MCA = MCConfig.GetIntDefault("irc.maxattempt", 10);
+ sIRC._autojoinkick = MCConfig.GetIntDefault("irc.autojoin_kick", 1);
+ sIRC._cmd_prefx = MCConfig.GetStringDefault("irc.command_prefix", ".");
+
+ sIRC._op_gm = MCConfig.GetIntDefault("irc.op_gm_login", 0);
+ sIRC._op_gm_lev = MCConfig.GetIntDefault("irc.op_gm_level", 3);
+
+ // Misc Options
+ sIRC.games = MCConfig.GetIntDefault("irc.fun.games", 0);
+ sIRC.gmlog = MCConfig.GetIntDefault("irc.gmlog", 1);
+ sIRC.BOTMASK = MCConfig.GetIntDefault("BotMask", 0);
+ sIRC.Status = MCConfig.GetIntDefault("irc.StatusChannel", 1);
+ sIRC.anchn = MCConfig.GetIntDefault("irc.AnnounceChannel", 1);
+ sIRC.autoanc = MCConfig.GetIntDefault("irc.auto.announce", 30);
+ sIRC.ojGM1 = MCConfig.GetStringDefault("irc.gm1", "[Moderator]");
+ sIRC.ojGM2 = MCConfig.GetStringDefault("irc.gm2", "[Game Master]");
+ sIRC.ojGM3 = MCConfig.GetStringDefault("irc.gm3", "[BugTracker]");
+ sIRC.ojGM4 = MCConfig.GetStringDefault("irc.gm4", "[DevTeam Admin]");
+ sIRC.ojGM5 = MCConfig.GetStringDefault("irc.gm5", "[Root Admin]");
+ // REQUIRED GM LEVEL
+ QueryResult *result = WorldDatabase.PQuery("SELECT `Command`, `gmlevel` FROM `IRC_Commands` ORDER BY `Command`");
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ std::string command = fields[0].GetCppString();
+ uint32 gmlvl = fields[1].GetUInt32();
+ if(command == "acct") sIRC.CACCT = gmlvl;
+ if(command == "ban") sIRC.CBAN = gmlvl;
+ if(command == "char") sIRC.CCHAN = gmlvl;
+ if(command == "char") sIRC.CCHAR = gmlvl;
+ if(command == "fun") sIRC.CFUN = gmlvl;
+ if(command == "help") sIRC.CHELP = gmlvl;
+ if(command == "inchan") sIRC.CINCHAN = gmlvl;
+ if(command == "info") sIRC.CINFO = gmlvl;
+ if(command == "item") sIRC.CITEM = gmlvl;
+ if(command == "jail") sIRC.CJAIL = gmlvl;
+ if(command == "kick") sIRC.CKICK = gmlvl;
+ if(command == "kill") sIRC._KILL = gmlvl;
+ if(command == "level") sIRC.CLEVEL = gmlvl;
+ if(command == "lookup") sIRC.CLOOKUP = gmlvl;
+ if(command == "money") sIRC.CMONEY = gmlvl;
+ if(command == "mute") sIRC.CMUTE = gmlvl;
+ if(command == "online") sIRC.CONLINE = gmlvl;
+ if(command == "pm") sIRC.CPM = gmlvl;
+ if(command == "restart") sIRC.CRESTART = gmlvl;
+ if(command == "revive") sIRC.CREVIVE = gmlvl;
+ if(command == "saveall") sIRC.CSAVEALL = gmlvl;
+ if(command == "shutdown") sIRC.CSHUTDOWN = gmlvl;
+ if(command == "spell") sIRC.CSPELL = gmlvl;
+ if(command == "sysmsg") sIRC.CSYSMSG = gmlvl;
+ if(command == "tele") sIRC.CTELE = gmlvl;
+ if(command == "top") sIRC.CTOP = gmlvl;
+ if(command == "who") sIRC.CWHO = gmlvl;
+ result->NextRow();
+ }
+ delete result;
+ }
+ else
+ {
+ sIRC.CACCT = 3;
+ sIRC.CBAN = 3;
+ sIRC.CCHAN = 3;
+ sIRC.CCHAR = 3;
+ sIRC.CFUN = 3;
+ sIRC.CHELP = 3;
+ sIRC.CINCHAN = 3;
+ sIRC.CINFO = 3;
+ sIRC.CITEM = 3;
+ sIRC.CJAIL = 3;
+ sIRC.CKICK = 3;
+ sIRC._KILL = 3;
+ sIRC.CLEVEL = 3;
+ sIRC.CLOOKUP = 3;
+ sIRC.CMONEY = 3;
+ sIRC.CMUTE = 3;
+ sIRC.CONLINE = 3;
+ sIRC.CPM = 3;
+ sIRC.CRESTART = 3;
+ sIRC.CREVIVE = 3;
+ sIRC.CSAVEALL = 3;
+ sIRC.CSHUTDOWN = 3;
+ sIRC.CSPELL = 3;
+ sIRC.CSYSMSG = 3;
+ sIRC.CTELE = 3;
+ sIRC.CTOP = 3;
+ sIRC.CWHO = 3;
+ }
+ return true;
+}
+
+std::string IRCClient::GetChatLine(int nItem)
+{
+ return sIRC.ILINES[nItem];
+}
diff --git a/src/game/IRCConf.h b/src/game/IRCConf.h
new file mode 100644
index 00000000000..9fa646d79d5
--- /dev/null
+++ b/src/game/IRCConf.h
@@ -0,0 +1,16 @@
+#ifndef MC_CONFIG_H
+#define MC_CONFIG_H
+
+#include "../framework/Platform/CompilerDefs.h"
+
+// Format is YYYYMMDDRR where RR is the change in the conf file
+// for that day.
+#define MANGCHAT_CONF_VERSION 2008011901
+
+#if PLATFORM == PLATFORM_WINDOWS
+ #define _MANGCHAT_CONFIG "trinitycore.conf"
+#else
+ #define _MANGCHAT_CONFIG "@sysconfdir@/trinitycore.conf"
+#endif
+
+#endif
diff --git a/src/game/IRCConf.h.in b/src/game/IRCConf.h.in
new file mode 100644
index 00000000000..9fa646d79d5
--- /dev/null
+++ b/src/game/IRCConf.h.in
@@ -0,0 +1,16 @@
+#ifndef MC_CONFIG_H
+#define MC_CONFIG_H
+
+#include "../framework/Platform/CompilerDefs.h"
+
+// Format is YYYYMMDDRR where RR is the change in the conf file
+// for that day.
+#define MANGCHAT_CONF_VERSION 2008011901
+
+#if PLATFORM == PLATFORM_WINDOWS
+ #define _MANGCHAT_CONFIG "trinitycore.conf"
+#else
+ #define _MANGCHAT_CONFIG "@sysconfdir@/trinitycore.conf"
+#endif
+
+#endif
diff --git a/src/game/IRCFunc.h b/src/game/IRCFunc.h
new file mode 100644
index 00000000000..4dca2847727
--- /dev/null
+++ b/src/game/IRCFunc.h
@@ -0,0 +1,251 @@
+#ifndef _IRC_CLIENT_FUNC
+#define _IRC_CLIENT_FUNC
+
+std::string GetUser(std::string szU)
+{
+ int pos = szU.find("!");
+ return szU.substr(0, pos);
+}
+// Delink will remove anything considered "non chat" from a string
+// Linked items (items that players can click on to see a description)
+// contain extra characters wich the client filter out, this function
+// makes sure people on irc do not see those characters.
+std::string Delink(std::string msg)
+{
+ std::size_t pos;
+ while((pos = msg.find("|Hitem")) != std::string::npos)
+ {
+ std::size_t find1 = msg.find("|h", pos);
+ std::size_t find2 = msg.find("|h", find1 + 2);
+ msg.replace(pos, find1 - pos + 2, "\x2");
+ msg.replace(msg.find("|h", pos), 2, "\x2");
+ }
+ while((pos = msg.find("|Henchant")) != std::string::npos)
+ {
+ std::size_t find1 = msg.find("|h", pos);
+ std::size_t find2 = msg.find("|h", find1 + 2);
+ msg.replace(pos, find1 - pos + 2, "\x2");
+ msg.replace(msg.find("|h", pos), 2, "\x2");
+ //msg.replace(find2, 2, "\x2");
+ }
+ return msg;
+}
+
+// This function converts the characters used by the client to identify colour to IRC format.
+std::string WoWcol2IRC(std::string msg)
+{
+ std::size_t pos;
+ 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"};
+ char WoWCol[9][12] = { "|r", "|cffffffff", "|cff9d9d9d", "|cff1eff00", "|cff0070dd", "|cffa335ee", "|cffff8000", "|cffe6cc80", "|cffffd000"};
+ for (int i=0; i<=8; i++)
+ {
+ while ((pos = msg.find(WoWCol[i])) != std::string::npos)
+ {
+ if (i == 0)
+ msg.replace(pos, 2, IRCCol[i]);
+ else
+ msg.replace(pos, 10, IRCCol[i]);
+ }
+ }
+ return msg;
+}
+
+// This function converts the characters used by IRC to identify colour to a format the client can understand.
+std::string IRCcol2WoW(std::string msg)
+{
+ std::size_t pos;
+ 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"};
+ 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"};
+ char WoWcol[16][12] = { "|cffffffff", "|cff000000", "|cff00007f", "|cff009300", "|cffff0000", "|cff7f0000", "|cff9c009c", "|cfffc9300", "|cffffff00", "|cff00fc00", "|cff009393", "|cff00ffff", "|cff0000fc", "|cffff00ff", "|cff7f7f7f", "|cffd2d2d2"};
+ for (int i=15; i>=0; i--)
+ {
+ if (i<10)
+ {
+ while ((pos = msg.find(IRCCol2[i])) != std::string::npos)
+ {
+ msg.replace(pos, 3, WoWcol[i]);
+ }
+ while ((pos = msg.find(IRCCol[i])) != std::string::npos)
+ {
+ msg.replace(pos, 2, WoWcol[i]);
+ }
+
+ }
+ else
+ {
+ while ((pos = msg.find(IRCCol[i])) != std::string::npos)
+ {
+ msg.replace(pos, 3, WoWcol[i]);
+ }
+ }
+
+ // Remove Bold, Reverse, Underline from IRC
+ char Checker[3][3] = {"\x2","\x16","\x1F"}; // This is the Hex part not Dec. In Decimal its (2,22,31)
+ for(int I=0; I < 3; I++)
+ {
+ while ((pos = msg.find(Checker[I])) != std::string::npos)
+ {
+ msg.replace(pos, 1, "");
+ }
+ }
+ // Finished Removing !
+
+ }
+
+ while ((pos = msg.find("\x3")) != std::string::npos)
+ {
+ msg.replace(pos, 1, "|r");
+ }
+ while ((pos = msg.find("\xF")) != std::string::npos)
+ {
+ msg.replace(pos, 1, "|r");
+ }
+
+ return msg;
+}
+
+// This function compares 2 strings
+int nocase_cmp(const string & s1, const string& s2)
+{
+ string::const_iterator it1=s1.begin();
+ string::const_iterator it2=s2.begin();
+
+ //stop when either string's end has been reached
+ while ( (it1!=s1.end()) && (it2!=s2.end()) )
+ {
+ if(::toupper(*it1) != ::toupper(*it2)) //letters differ?
+ // return -1 to indicate smaller than, 1 otherwise
+ return (::toupper(*it1) < ::toupper(*it2)) ? -1 : 1;
+ //proceed to the next character in each string
+ ++it1;
+ ++it2;
+ }
+ size_t size1=s1.size(), size2=s2.size(); // cache lengths
+ //return -1,0 or 1 according to strings' lengths
+ if (size1==size2)
+ return 0;
+ return (size1<size2) ? -1 : 1;
+}
+
+std::string MakeMsgA(const char *sLine, ... )
+{
+ va_list ap;
+ char tmpoutp[1024];
+ va_start(ap, sLine);
+ vsnprintf(tmpoutp, 1024, sLine, ap );
+ va_end(ap);
+ std::string outp = tmpoutp;
+ return outp;
+}
+
+std::string MakeMsgP(int CLINE, std::string Msg, Player *plr)
+{
+ // std::string ChatTag = "";
+ // switch (plr->GetTeam())
+ // {
+ // case 67:ChatTag.append("4");break; //horde
+ // case 469:ChatTag.append("12");break; //alliance
+ // }
+ std::string sMsg = sIRC.MakeMsg(sIRC.GetChatLine(CLINE), "$Msg", Msg);
+ // sMsg = ChatTag + MakeMsg(sMsg, "$Name", plr->GetName());
+ if (plr->GetTeam() == 67)
+ sMsg = sIRC.MakeMsg(sMsg, "$Name", MakeMsgA("\0034%s\003", plr->GetName()));
+ else if (plr->GetTeam() == 469)
+ sMsg = sIRC.MakeMsg(sMsg, "$Name", MakeMsgA("\00312%s\003", plr->GetName()));
+ if(plr->isAFK())
+ sMsg = sIRC.MakeMsg(sMsg, "$Tag", "<AFK>");
+ else if(plr->isDND())
+ sMsg = sIRC.MakeMsg(sMsg, "$Tag", "<DND>");
+ else
+ sMsg = sIRC.MakeMsg(sMsg, "$Tag", "");
+ sMsg = sIRC.MakeMsg(sMsg, "$Level", MakeMsgA("%d", plr->getLevel()));
+ sMsg = Delink(sMsg);
+ sMsg = WoWcol2IRC(sMsg);
+ return sMsg;
+}
+
+/*
+std::string MakeMsg(std::string msg, std::string var, int val)
+{
+ std::ostringstream ss;
+ ss << val;
+
+ std::string nval = ss.str();
+ std::size_t start = msg.find(var);
+ if (start != std::string::npos)
+ msg.replace(start, var.length(), val);
+ return msg;
+}
+*/
+/*
+std::string MakeMsg(const char *sLine, ... )
+{
+ va_list ap;
+ char tmpoutp[1024];
+ va_start(ap, sLine);
+ vsnprintf(tmpoutp, 1024, sLine, ap );
+ va_end(ap);
+ std::string outp = tmpoutp;
+ return outp;
+}
+*/
+
+// This function checks if a channel exists in out configuration
+// Mangchat supports as many channels as you like
+// However the default has been set to 10
+// if you wish to increase this you must edit the:
+// MAX_CONF_CHANNELS variable in IRCClient.h
+bool Channel_Valid(std::string Channel)
+{
+ for(int i=1;i < sIRC._chan_count + 1;i++)
+ {
+ if(nocase_cmp(sIRC._wow_chan[i], Channel)==0)
+ return true;
+ }
+ return false;
+}
+
+std::string GetWoWChannel(std::string Channel)
+{
+ for(int i=1;i < sIRC._chan_count + 1;i++)
+ {
+ if("#" + sIRC._irc_chan[i] == Channel)
+ return sIRC._wow_chan[i];
+ }
+ return "";
+}
+
+std::string GetIRCChannel(std::string Channel)
+{
+ for(int i=1;i < sIRC._chan_count + 1;i++)
+ {
+ if(sIRC._wow_chan[i] == Channel)
+ return sIRC._irc_chan[i];
+ }
+ return "";
+}
+
+std::string* getArray(std::string PARAMS, int nCount, std::string )
+{
+ std::string *array = new std::string[nCount];
+ if(PARAMS.size() > 0)
+ {
+ int pcnt = 0;
+ size_t ps = 0;
+ size_t pc = -1;
+ for(int i = 0;i < nCount;i++)
+ {
+ pc = PARAMS.find(" ", pc + 1);
+ if(i + 1 == nCount && nCount != 1)
+ {
+ if(ps > 0 && pc > 0)
+ array[i] = PARAMS.substr(ps, PARAMS.size() - ps);
+ }
+ else
+ array[i] = PARAMS.substr(ps, pc - ps);
+ ps = pc + 1;
+ }
+ }
+ return array;
+}
+#endif
diff --git a/src/game/IRCIO.cpp b/src/game/IRCIO.cpp
new file mode 100644
index 00000000000..c8c0213ed0d
--- /dev/null
+++ b/src/game/IRCIO.cpp
@@ -0,0 +1,436 @@
+#include "IRCClient.h"
+#include "IRCCmd.h"
+#include "IRCFunc.h"
+#include "ObjectAccessor.h"
+#include "ObjectMgr.h"
+#include "WorldPacket.h"
+#include "ChannelMgr.h"
+#include "Config/ConfigEnv.h"
+#include "Channel.h"
+#include "World.h"
+
+IRCCmd Command;
+void IRCClient::Handle_IRC(std::string sData)
+{
+ sLog.outDebug(sData.c_str());
+ // If first 5 chars are ERROR then something is wrong
+ // either link is being closed, nickserv ghost command, etc...
+ if(sData.substr(0, 5) == "ERROR")
+ {
+ Disconnect();
+ return;
+ }
+ if(sData.substr(0, 4) == "PING")
+ {
+ // if the first 4 characters contain PING
+ // the server is checking if we are still alive
+ // sen back PONG back plus whatever the server send with it
+ SendIRC("PONG " + sData.substr(4, sData.size() - 4));
+ }
+ else
+ {
+ // if the first line contains : its an irc message
+ // such as private messages channel join etc.
+ if(sData.substr(0, 1) == ":")
+ {
+ // find the spaces in the receieved line
+ size_t p1 = sData.find(" ");
+ size_t p2 = sData.find(" ", p1 + 1);
+ // because the irc protocol uses simple spaces
+ // to seperate data we can easy pick them out
+ // since we know the position of the spaces
+ std::string USR = sData.substr(1, p1 - 1);
+ std::string CMD = sData.substr(p1 + 1, p2 - p1 - 1);
+ // trasform the commands to lowercase to make sure they always match
+ std::transform(CMD.begin(), CMD.end(), CMD.begin(), towlower);
+ // Extract the username from the first part
+ std::string szUser = GetUser(USR);
+ // if we receieved the internet connect code
+ // we know for sure that were in and we can
+ // authenticate ourself.
+ if(CMD == sIRC._ICC)
+ {
+ // _Auth is defined in mangosd.conf (irc.auth)
+ // 0 do not authenticate
+ // 1 use nickserv
+ // 2 use quakenet
+ // aditionally you can provide you own authentication method here
+ switch(sIRC._Auth)
+ {
+ case 1:
+ SendIRC("PRIVMSG nickserv :IDENTIFY " + sIRC._Pass);
+ break;
+ case 2:
+ SendIRC("PRIVMSG nickserv :IDENTIFY " + sIRC._Auth_Nick + " " + sIRC._Pass);
+ break;
+ case 3:
+ SendIRC("PRIVMSG Q@CServe.quakenet.org :AUTH " + sIRC._Nick + " " + sIRC._Pass);
+ break;
+ case 4:
+ SendIRC("PRIVMSG Q@CServe.quakenet.org :AUTH " + sIRC._Auth_Nick + " " + sIRC._Pass);
+ break;
+ }
+ // if we join a default channel leave this now.
+ if(sIRC._ldefc==1)
+ SendIRC("PART #" + sIRC._defchan);
+ // Loop thru the channel array and send a command to join them on IRC.
+ for(int i=1;i < sIRC._chan_count + 1;i++)
+ {
+ SendIRC("JOIN #" + sIRC._irc_chan[i]);
+ }
+ }
+ // someone joined the channel this could be the bot or another user
+ if(CMD == "join")
+ {
+ size_t p = sData.find(":", p1);
+ std::string CHAN = sData.substr(p + 1, sData.size() - p - 2);
+ // if the user is us it means we join the channel
+ if ((szUser == sIRC._Nick) )
+ {
+ // its us that joined the channel
+ Send_IRC_Channel(CHAN, MakeMsg(MakeMsg(sIRC.JoinMsg, "$Ver", sIRC._Mver.c_str()), "$Trigger", sIRC._cmd_prefx.c_str()), true);
+ }
+ else
+ {
+ // if the user is not us its someone else that joins
+ // so we construct a message and send this to the clients.
+ // MangChat now uses Send_WoW_Channel to send to the client
+ // this makes MangChat handle the packets instead of previously the world.
+ if((sIRC.BOTMASK & 2) != 0)
+ Send_WoW_Channel(GetWoWChannel(CHAN).c_str(), IRCcol2WoW(MakeMsg(MakeMsg(GetChatLine(JOIN_IRC), "$Name", szUser), "$Channel", GetWoWChannel(CHAN))));
+ }
+ }
+ // someone on irc left or quit the channel
+ if(CMD == "part" || CMD == "quit")
+ {
+ size_t p3 = sData.find(" ", p2 + 1);
+ std::string CHAN = sData.substr(p2 + 1, p3 - p2 - 1);
+ // Logout IRC Nick From MangChat If User Leaves Or Quits IRC.
+ if(Command.IsLoggedIn(szUser))
+ {
+ _CDATA CDATA;
+ CDATA.USER = szUser;
+ Command.Handle_Logout(&CDATA);
+ }
+ // Construct a message and inform the clients on the same channel.
+ if((sIRC.BOTMASK & 2) != 0)
+ Send_WoW_Channel(GetWoWChannel(CHAN).c_str(), IRCcol2WoW(MakeMsg(MakeMsg(GetChatLine(LEAVE_IRC), "$Name", szUser), "$Channel", GetWoWChannel(CHAN))));
+ }
+ // someone changed their nick
+ if (CMD == "nick" && (sIRC.BOTMASK & 128) != 0)
+ {
+ MakeMsg(MakeMsg(GetChatLine(CHANGE_NICK), "$Name", szUser), "$NewName", sData.substr(sData.find(":", p2) + 1));
+ // If the user is logged in and changes their nick
+ // then we want to either log them out or update
+ // their nick in the bot. I chose to update the bots user list.
+ if(Command.IsLoggedIn(szUser))
+ {
+ std::string NewNick = sData.substr(sData.find(":", p2) + 1);
+ // On freenode I noticed the server sends an extra character
+ // at the end of the string, so we need to erase the last
+ // character of the string. if you have a problem with getting
+ // the last letter of your nick erased, then remove the - 1.
+ NewNick.erase(NewNick.length() - 1, 1);
+
+ for(std::list<_client*>::iterator i=Command._CLIENTS.begin(); i!=Command._CLIENTS.end();i++)
+ {
+ if((*i)->Name == szUser)
+ {
+ (*i)->Name = NewNick;
+ sIRC.Send_IRC_Channel(NewNick.c_str(), "I Noticed You Changed Your Nick, I Have Updated My Internal Database Accordingly.", true, "NOTICE");
+
+ // Figure why not output to the logfile, makes tracing problems easier.
+ sIRC.iLog.WriteLog(" %s : %s Changed Nick To: %s", sIRC.iLog.GetLogDateTimeStr().c_str(), szUser.c_str(), NewNick.c_str());
+ }
+ }
+ }
+
+ }
+ // someone was kicked from irc
+ if (CMD == "kick")
+ {
+ // extract the details
+ size_t p3 = sData.find(" ", p2 + 1);
+ size_t p4 = sData.find(" ", p3 + 1);
+ size_t p5 = sData.find(":", p4);
+ std::string CHAN = sData.substr(p2 + 1, p3 - p2 - 1);
+ std::string WHO = sData.substr(p3 + 1, p4 - p3 - 1);
+ std::string BY = sData.substr(p4 + 1, sData.size() - p4 - 1);
+ // if the one kicked was us
+ if(WHO == sIRC._Nick)
+ {
+ // and autojoin is enabled
+ // return to the channel
+ if(sIRC._autojoinkick == 1)
+ {
+ SendIRC("JOIN " + CHAN);
+ Send_IRC_Channel(CHAN, sIRC.kikmsg, true);
+ }
+ }
+ else
+ {
+ // if it is not us who was kicked we need to inform the clients someone
+ // was removed from the channel
+ // construct a message and send it to the players.
+ Send_WoW_Channel(GetWoWChannel(CHAN).c_str(), "<IRC>[" + WHO + "]: Was Kicked From " + CHAN + " By: " + szUser);
+ }
+ }
+ // a private chat message was receieved.
+ if(CMD == "privmsg" || CMD == "notice")
+ {
+ // extract the values
+ size_t p = sData.find(" ", p2 + 1);
+ std::string FROM = sData.substr(p2 + 1, p - p2 - 1);
+ std::string CHAT = sData.substr(p + 2, sData.size() - p - 3);
+ // if this is our username it means we recieved a PM
+ if(FROM == sIRC._Nick)
+ {
+ if(CHAT.find("\001VERSION\001") < CHAT.size())
+ {
+ Send_IRC_Channel(szUser, MakeMsg("\001VERSION MangChat %s ©2008 |Death|\001", "%s" , sIRC._Mver.c_str()), true, "PRIVMSG");
+ }
+ // a pm is required for certain commands
+ // such as login. to validate the command
+ // we send it to the command class wich handles
+ // evrything else.
+ Command.IsValid(szUser, FROM, CHAT, CMD);
+ }
+ else
+ {
+ // if our name is not in it, it means we receieved chat on one of the channels
+ // magchat is in. the first thing we do is check if it is a command or not
+ if(!Command.IsValid(szUser, FROM, CHAT, CMD))
+ {
+ Send_WoW_Channel(GetWoWChannel(FROM).c_str(), IRCcol2WoW(MakeMsg(MakeMsg(GetChatLine(IRC_WOW), "$Name", szUser), "$Msg", CHAT)));
+ }
+ // if we indeed receieved a command we do not want to display this to the players
+ // so only incanse the isvalid command returns false it will be sent to all player.
+ // the isvalid function will automaitcly process the command on true.
+ }
+ }
+ if(CMD == "mode")
+ {
+ // extract the mode details
+ size_t p3 = sData.find(" ", p2 + 1);
+ size_t p4 = sData.find(" ", p3 + 1);
+ size_t p5 = sData.find(" ", p4 + 1);
+ std::string CHAN = sData.substr(p2 + 1, p3 - p2 - 1);
+ std::string MODE = sData.substr(p3 + 1, p4 - p3 - 1);
+ std::string NICK = sData.substr(p4 + 1, p5 - p4 - 1);
+ bool _AmiOp;
+ _AmiOp = false;
+ //A mode was changed on us
+ if(NICK.c_str() == sIRC._Nick)
+ _AmiOp = true;
+
+ }
+ }
+ }
+}
+
+// This function is called in Channel.h
+// based on nAction it will inform the people on
+// irc when someone leaves one of the game channels.
+// nAction is based on the struct CACTION
+void IRCClient::Handle_WoW_Channel(std::string Channel, Player *plr, int nAction)
+{
+ // make sure that we are connected
+ if(sIRC.Connected && (sIRC.BOTMASK & 1)!= 0)
+ {
+ if(Channel_Valid(Channel))
+ {
+ std::string GMRank = "";
+ std::string pname = plr->GetName();
+ bool DoGMAnnounce = false;
+ if (plr->GetSession()->GetSecurity() > 0 && (sIRC.BOTMASK & 8)!= 0)
+ DoGMAnnounce = true;
+ if (plr->isGameMaster() && (sIRC.BOTMASK & 16)!= 0)
+ DoGMAnnounce = true;
+ if(DoGMAnnounce)
+ {
+ switch(plr->GetSession()->GetSecurity()) //switch case to determine what rank the "gm" is
+ {
+ case 0: GMRank = "";break;
+ case 1: GMRank = "\0037"+sIRC.ojGM1;break;
+ case 2: GMRank = "\0037"+sIRC.ojGM2;break;
+ case 3: GMRank = "\0037"+sIRC.ojGM3;break;
+ case 4: GMRank = "\0037"+sIRC.ojGM4;break;
+ case 5: GMRank = "\0037"+sIRC.ojGM5;break;
+ }
+ }
+ std::string ChatTag = "";
+ switch (plr->GetTeam())
+ {
+ case 67:ChatTag.append("\0034");break; //horde
+ case 469:ChatTag.append("\00312");break; //alliance
+ }
+ std::string query = "INSERT INTO `IRC_Inchan` VALUES (%d,'"+pname+"','"+Channel+"')";
+ std::string lchan = "DELETE FROM `IRC_Inchan` WHERE `guid` = %d AND `channel` = '"+Channel+"'";
+ switch(nAction)
+ {
+ case CHANNEL_JOIN:
+ Send_IRC_Channel(GetIRCChannel(Channel), MakeMsg(MakeMsg(MakeMsg(GetChatLine(JOIN_WOW), "$Name", ChatTag + plr->GetName()), "$Channel", Channel), "$GM", GMRank));
+ WorldDatabase.PExecute(lchan.c_str(), plr->GetGUID());
+ WorldDatabase.PExecute(query.c_str(), plr->GetGUID());
+ break;
+ case CHANNEL_LEAVE:
+ Send_IRC_Channel(GetIRCChannel(Channel), MakeMsg(MakeMsg(MakeMsg(GetChatLine(LEAVE_WOW), "$Name", ChatTag + plr->GetName()), "$Channel", Channel), "$GM", GMRank));
+ WorldDatabase.PExecute(lchan.c_str(), plr->GetGUID());
+ break;
+ }
+ }
+ }
+}
+
+// This function sends chat to a irc channel or user
+// to prevent the # beeing appended to send a msg to a user
+// set the NoPrefix to true
+void IRCClient::Send_IRC_Channel(std::string sChannel, std::string sMsg, bool NoPrefix, std::string nType)
+{
+ std::string mType = "PRIVMSG";
+ if(Command.MakeUpper(nType.c_str()) == "NOTICE")
+ mType = "NOTICE";
+ if(Command.MakeUpper(nType.c_str()) == "ERROR" && (sIRC.BOTMASK & 32)!= 0)
+ mType = "NOTICE";
+ if(sIRC.Connected)
+ {
+ if(NoPrefix)
+ SendIRC(mType + " " + sChannel + " :" + sMsg);
+ else
+ SendIRC(mType + " #" + sChannel + " :" + sMsg);
+ }
+}
+
+// This function sends a message to all irc channels
+// that mangchat has in its configuration
+void IRCClient::Send_IRC_Channels(std::string sMsg)
+{
+ for(int i=1;i < sIRC._chan_count + 1;i++)
+ Send_IRC_Channel(sIRC._irc_chan[i], sMsg);
+}
+
+// This function is called in ChatHandler.cpp, any channel chat from wow will come
+// to this function, validates the channel and constructs a message that is send to IRC
+void IRCClient::Send_WoW_IRC(Player *plr, std::string Channel, std::string Msg)
+{
+ // Check if the channel exist in our configuration
+ if(Channel_Valid(Channel) && Msg.substr(0, 1) != ".")
+ Send_IRC_Channel(GetIRCChannel(Channel), MakeMsgP(WOW_IRC, Msg, plr));
+}
+
+void IRCClient::Send_WoW_Player(std::string sPlayer, std::string sMsg)
+{
+ normalizePlayerName(sPlayer);
+ if (Player* plr = ObjectAccessor::Instance().FindPlayerByName(sPlayer.c_str()))
+ Send_WoW_Player(plr, sMsg);
+}
+
+void IRCClient::Send_WoW_Player(Player *plr, string sMsg)
+{
+ WorldPacket data(SMSG_MESSAGECHAT, 200);
+ data << (uint8)CHAT_MSG_SYSTEM;
+ data << (uint32)LANG_UNIVERSAL;
+ data << (uint64)plr->GetGUID();
+ data << (uint32)0;
+ data << (uint64)plr->GetGUID();
+ data << (uint32)(sMsg.length()+1);
+ data << sMsg;
+ data << (uint8)0;
+ plr->GetSession()->SendPacket(&data);
+}
+
+// This function will construct and send a packet to all players
+// on the given channel ingame. (previuosly found in world.cpp)
+// it loops thru all sessions and checks if they are on the channel
+// if so construct a packet and send it.
+void IRCClient::Send_WoW_Channel(const char *channel, std::string chat)
+{
+ if(!(strlen(channel) > 0))
+ return;
+
+ #ifdef USE_UTF8
+ std::string chat2 = chat;
+ if(ConvertUTF8(chat2.c_str(), chat2))
+ chat = chat2;
+ #endif
+
+ HashMapHolder<Player>::MapType& m = ObjectAccessor::Instance().GetPlayers();
+ for(HashMapHolder<Player>::MapType::iterator itr = m.begin(); itr != m.end(); ++itr)
+ {
+ if (itr->second && itr->second->GetSession()->GetPlayer() && itr->second->GetSession()->GetPlayer()->IsInWorld())
+ {
+ if(ChannelMgr* cMgr = channelMgr(itr->second->GetSession()->GetPlayer()->GetTeam()))
+ {
+ if(Channel *chn = cMgr->GetChannel(channel, itr->second->GetSession()->GetPlayer()))
+ {
+ WorldPacket data;
+ data.Initialize(SMSG_MESSAGECHAT);
+ data << (uint8)CHAT_MSG_CHANNEL;
+ data << (uint32)LANG_UNIVERSAL;
+ data << (uint64)0;
+ data << (uint32)0;
+ data << channel;
+ data << (uint64)0;
+ data << (uint32) (strlen(chat.c_str()) + 1);
+ data << IRCcol2WoW(chat.c_str());
+ data << (uint8)0;
+ itr->second->GetSession()->SendPacket(&data);
+ }
+ }
+ }
+ }
+}
+
+void IRCClient::Send_WoW_System(std::string Message)
+{
+ HashMapHolder<Player>::MapType& m = ObjectAccessor::Instance().GetPlayers();
+ for(HashMapHolder<Player>::MapType::iterator itr = m.begin(); itr != m.end(); ++itr)
+ {
+ if (itr->second && itr->second->GetSession()->GetPlayer() && itr->second->GetSession()->GetPlayer()->IsInWorld())
+ {
+ WorldPacket data;
+ data.Initialize(CHAT_MSG_SYSTEM);
+ data << (uint8)CHAT_MSG_SYSTEM;
+ data << (uint32)LANG_UNIVERSAL;
+ data << (uint64)0;
+ data << (uint32)0;
+ data << (uint64)0;
+ data << (uint32) (strlen(Message.c_str()) + 1);
+ data << Message.c_str();
+ data << (uint8)0;
+ itr->second->GetSession()->SendPacket(&data);
+ }
+ }
+}
+void IRCClient::ResetIRC()
+{
+ SendData("QUIT");
+ Disconnect();
+}
+
+#define CHAT_INVITE_NOTICE 0x18
+
+// this function should be called on player login Player::AddToWorld
+void IRCClient::AutoJoinChannel(Player *plr)
+{
+ //this will work if at least 1 player is logged in regrdless if he is on the channel or not
+ // the first person that login empty server is the one with bad luck and wont be invited,
+ // if at least 1 player is online the player will be inited to the chanel
+
+ std::string m_name = sIRC.ajchan;
+ WorldPacket data;
+ data.Initialize(SMSG_CHANNEL_NOTIFY, 1+m_name.size()+1);
+ data << uint8(CHAT_INVITE_NOTICE);
+ data << m_name.c_str();
+
+ HashMapHolder<Player>::MapType& m = ObjectAccessor::Instance().GetPlayers();
+ for(HashMapHolder<Player>::MapType::iterator itr = m.begin(); itr != m.end(); ++itr)
+ {
+ if (itr->second && itr->second->GetSession()->GetPlayer() && itr->second->GetSession()->GetPlayer()->IsInWorld())
+ {
+ data << uint64(itr->second->GetGUID());
+ break;
+ }
+ }
+ plr->GetSession()->SendPacket(&data);
+}
diff --git a/src/game/IRCLog.cpp b/src/game/IRCLog.cpp
new file mode 100644
index 00000000000..07bde4a6326
--- /dev/null
+++ b/src/game/IRCLog.cpp
@@ -0,0 +1,60 @@
+#include "IRCLog.h"
+#include "Config/ConfigEnv.h"
+#include "IRCClient.h"
+#include <stdarg.h>
+
+IRCLog::IRCLog()
+{
+ std::string logsDir = sConfig.GetStringDefault("LogsDir","");
+ std::string ircLogName = logsDir + "/IRC_";
+ std::string ircLogTimestamp = GetLogDateStr();
+ ircLogName += ircLogTimestamp +".log";
+ ircLogfile.open (ircLogName.c_str(), std::ios::app);
+}
+
+IRCLog::~IRCLog()
+{
+ ircLogfile.close();
+}
+// Was added because using the time for logs is very annoying... one log per day.. much cleaner looking..
+std::string IRCLog::GetLogDateStr() const
+{
+ time_t t = time(NULL);
+ tm* aTm = localtime(&t);
+ // YYYY year
+ // MM month (2 digits 01-12)
+ // DD day (2 digits 01-31)
+ // HH hour (2 digits 00-23)
+ // MM minutes (2 digits 00-59)
+ // SS seconds (2 digits 00-59)
+ char buf[20];
+ snprintf(buf,20,"%04d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday);
+ return std::string(buf);
+}
+
+std::string IRCLog::GetLogDateTimeStr() const
+{
+ time_t t = time(NULL);
+ tm* aTm = localtime(&t);
+ // YYYY year
+ // MM month (2 digits 01-12)
+ // DD day (2 digits 01-31)
+ // HH hour (2 digits 00-23)
+ // MM minutes (2 digits 00-59)
+ // SS seconds (2 digits 00-59)
+ char buf[30];
+ 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);
+ return std::string(buf);
+}
+
+void IRCLog::WriteLog(const char *what, ...)
+{
+ va_list ap;
+ char tmpoutp[1024];
+ va_start(ap, what);
+ vsnprintf(tmpoutp, 1024, what, ap );
+ va_end(ap);
+ ircLogfile << tmpoutp;
+ ircLogfile << "\n";
+ ircLogfile.flush();
+}
diff --git a/src/game/IRCLog.h b/src/game/IRCLog.h
new file mode 100644
index 00000000000..fd35a0aaa79
--- /dev/null
+++ b/src/game/IRCLog.h
@@ -0,0 +1,22 @@
+#ifndef _IRC_LOG_H
+#define _IRC_LOG_H
+
+#include "Common.h"
+#include <fstream>
+
+class IRCLog
+{
+ public:
+ IRCLog();
+ ~IRCLog();
+
+ public:
+ void WriteLog(const char *what, ...);
+ std::string GetLogDateStr() const;
+ std::string GetLogDateTimeStr() const;
+ private:
+ std::ofstream ircLogfile;
+};
+
+
+#endif
diff --git a/src/game/IRCSock.cpp b/src/game/IRCSock.cpp
new file mode 100644
index 00000000000..cf76161cc02
--- /dev/null
+++ b/src/game/IRCSock.cpp
@@ -0,0 +1,146 @@
+#include "IRCClient.h"
+#define MAXDATASIZE 512
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+
+
+#define _UNICODE
+
+#ifdef _MBCS
+#undef _MBCS
+#endif
+
+bool IRCClient::InitSock()
+{
+ #ifdef _WIN32
+ WSADATA wsaData; //WSAData
+ if(WSAStartup(MAKEWORD(2,0),&wsaData) != 0)
+ {
+ sLog.outError("IRC Error: Winsock Initialization Error");
+ return false;
+ }
+ #endif
+ if ((sIRC.SOCKET = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
+ {
+ sLog.outError("IRC Error: Socket Error");
+ return false;
+ }
+ int on = 1;
+ if ( setsockopt ( sIRC.SOCKET, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 )
+ {
+ sLog.outError("IRC Error: Invalid Socket");
+ return false;
+ }
+ #ifdef _WIN32
+ u_long iMode = 0;
+ ioctlsocket(sIRC.SOCKET, FIONBIO, &iMode);
+ #else
+ fcntl(sIRC.SOCKET, F_SETFL, O_NONBLOCK); // set to non-blocking
+ fcntl(sIRC.SOCKET, F_SETFL, O_ASYNC); // set to asynchronous I/O
+ #endif
+ return true;
+}
+
+bool IRCClient::Connect(const char *cHost, int nPort)
+{
+ sIRC.Connected = false;
+ struct hostent *he;
+ if ((he=gethostbyname(cHost)) == NULL)
+ {
+ sLog.outError("IRCLIENT: Could not resolve host: %s", cHost);
+ return false;
+ }
+ struct sockaddr_in their_addr;
+ their_addr.sin_family = AF_INET;
+ their_addr.sin_port = htons(nPort);
+ their_addr.sin_addr = *((struct in_addr *)he->h_addr);
+ memset(&(their_addr.sin_zero), '\0', 8);
+ if (::connect(sIRC.SOCKET, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)
+ {
+ sLog.outError("IRCLIENT: Cannot connect to %s", cHost);
+ return false;
+ }
+ //FD_ZERO(&sIRC.sfdset);
+ //FD_SET(sIRC.SOCKET,&sIRC.sfdset);
+ sIRC.Connected = true;
+ return true;
+}
+
+bool IRCClient::Login(std::string sNick, std::string sUser, std::string sPass)
+{
+ char hostname[128];
+ gethostname(hostname, sizeof(hostname));
+ if(SendIRC("HELLO"))
+ if(SendIRC("PASS " + sPass))
+ if(SendIRC("NICK " + sNick))
+ if(SendIRC("USER " + sUser + " " + (std::string)hostname + " MangChat :MangChat "+sIRC._Mver.c_str()))
+ return true;
+ return false;
+}
+
+bool IRCClient::SendData(const char *data)
+{
+ if(sIRC.Connected)
+ {
+ if (send(sIRC.SOCKET, data, strlen(data), 0) == -1)
+ {
+ sLog.outError("IRC Error: Socket Receieve ** \n");
+ //Disconnect();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool IRCClient::SendIRC(std::string data)
+{
+ std::string RealData = data + "\n";
+ return SendData(RealData.c_str());
+}
+
+void IRCClient::Disconnect()
+{
+ if(sIRC.SOCKET)
+ {
+ #ifdef _WIN32
+ closesocket(sIRC.SOCKET);
+ //WSACleanup();
+ #else
+ close(sIRC.SOCKET);
+ #endif
+ }
+}
+
+void IRCClient::SockRecv()
+{
+// wchar_t bufferdata;
+
+ char szBuffer[MAXDATASIZE];
+
+ memset(szBuffer, 0, MAXDATASIZE );
+
+ int nBytesRecv = ::recv(sIRC.SOCKET, szBuffer, MAXDATASIZE - 1, 0 );
+ if ( nBytesRecv == -1 )
+ {
+ sLog.outError("Connection lost.");
+ sIRC.Connected = false;
+ }
+ else
+ {
+ if (-1 == nBytesRecv)
+ {
+ sLog.outError("Error occurred while receiving from socket.");
+ }
+ else
+ {
+ std::string reply;
+ std::istringstream iss(szBuffer);
+ while(getline(iss, reply))
+ {
+ Handle_IRC(reply);
+ }
+ }
+ }
+}
diff --git a/src/game/Language.h b/src/game/Language.h
index f805103047e..4bfe520ee78 100644
--- a/src/game/Language.h
+++ b/src/game/Language.h
@@ -640,6 +640,8 @@ enum MangosStrings
LANG_ARENA_TESTING = 745,
+ LANG_AUTO_ANN = 746,
+
// in game strings
LANG_PET_INVALID_NAME = 800,
LANG_NOT_ENOUGH_GOLD = 801,
diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp
index 9bcbb80b811..cf4123c2f24 100644
--- a/src/game/Level1.cpp
+++ b/src/game/Level1.cpp
@@ -31,6 +31,7 @@
#include "Language.h"
#include "CellImpl.h"
#include "InstanceSaveMgr.h"
+#include "IRCClient.h"
#include "Util.h"
#ifdef _DEBUG_VMAPS
#include "VMapFactory.h"
@@ -123,6 +124,14 @@ bool ChatHandler::HandleAnnounceCommand(const char* args)
return false;
sWorld.SendWorldText(LANG_SYSTEMMESSAGE,args);
+
+ if((sIRC.BOTMASK & 256) != 0)
+ {
+ std::string ircchan = "#";
+ ircchan += sIRC._irc_chan[sIRC.anchn].c_str();
+ sIRC.Send_IRC_Channel(ircchan, sIRC.MakeMsg("\00304,08\037/!\\\037\017\00304 System Message \00304,08\037/!\\\037\017 %s", "%s", args), true);
+ }
+
return true;
}
@@ -139,6 +148,13 @@ bool ChatHandler::HandleNotifyCommand(const char* args)
data << str;
sWorld.SendGlobalMessage(&data);
+ if((sIRC.BOTMASK & 256) != 0)
+ {
+ std::string ircchan = "#";
+ ircchan += sIRC._irc_chan[sIRC.anchn].c_str();
+ sIRC.Send_IRC_Channel(ircchan, sIRC.MakeMsg("\00304,08\037/!\\\037\017\00304 Global Notify \00304,08\037/!\\\037\017 %s", "%s", args), true);
+ }
+
return true;
}
@@ -2348,6 +2364,25 @@ bool ChatHandler::HandleGoXYZCommand(const char* args)
return true;
}
+bool ChatHandler::HandleIRCpmCommand(const char* args)
+{
+ std::string Msg = args;
+ if (Msg.find(" ") == std::string::npos)
+ return false;
+ std::string To = Msg.substr(0, Msg.find(" "));
+ Msg = Msg.substr(Msg.find(" ") + 1);
+ std::size_t pos;
+ while((pos = To.find("||")) != std::string::npos)
+ {
+ std::size_t find1 = To.find("||", pos);
+ To.replace(pos, find1 - pos + 2, "|");
+ }
+ sIRC.SendIRC("PRIVMSG "+To+" : <WoW>["+m_session->GetPlayerName()+"] : " + Msg);
+ //Msg = "|cffCC4ACCTo [" + To + "]: " + Msg + "|r";
+ sIRC.Send_WoW_Player(m_session->GetPlayer(), "|cffCC4ACCTo ["+To+"]: "+Msg);
+ return true;
+}
+
//teleport at coordinates
bool ChatHandler::HandleGoZoneXYCommand(const char* args)
{
diff --git a/src/game/MCS_OnlinePlayers.cpp b/src/game/MCS_OnlinePlayers.cpp
new file mode 100644
index 00000000000..8f48faa6adc
--- /dev/null
+++ b/src/game/MCS_OnlinePlayers.cpp
@@ -0,0 +1,84 @@
+/*
+ * MangChat By |Death| And Cybrax
+ *
+ * This Program Is Free Software; You Can Redistribute It And/Or Modify It Under The Terms
+ * Of The GNU General Public License
+ * Written and Developed by Cybrax. cybraxvd@gmail.com
+ * |Death| <death@hell360.net>, Lice <lice@yeuxverts.net>, Dj_baby & Sanaell, Tase
+ * With Help And Support From The MaNGOS Project Community.
+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHORS.
+ */
+#include "MCS_OnlinePlayers.h"
+
+#include "MapManager.h"
+#include "ObjectMgr.h"
+#include "Config/ConfigEnv.h"
+
+mcs_OnlinePlayers::mcs_OnlinePlayers() { CD = NULL; }
+
+mcs_OnlinePlayers::mcs_OnlinePlayers(_CDATA *_CD)
+{
+ //create a new instance of data struct and copy its data
+ CD = new _CDATA();
+ CD->CMD = _CD->CMD;
+ CD->FROM = _CD->FROM;
+ CD->PARAMS = _CD->PARAMS;
+ CD->PCOUNT = _CD->PCOUNT;
+ CD->USER = _CD->USER;
+ CD->TYPE = _CD->TYPE;
+}
+
+mcs_OnlinePlayers::~mcs_OnlinePlayers()
+{
+ if(CD)
+ delete CD;
+}
+
+void mcs_OnlinePlayers::run()
+{
+ int OnlineCount = 0;
+ std::string IRCOut = "";
+ HashMapHolder<Player>::MapType& m = ObjectAccessor::Instance().GetPlayers();
+ for(HashMapHolder<Player>::MapType::iterator itr = m.begin(); itr != m.end(); ++itr)
+ {
+ if (itr->second && itr->second->GetSession()->GetPlayer() && itr->second->GetSession()->GetPlayer()->IsInWorld())
+ {
+ OnlineCount++;
+ Player *plr = itr->second->GetSession()->GetPlayer();
+ std::string ChatTag = " ";
+ switch(plr->GetSession()->GetSecurity())
+ {
+ case 0: ChatTag.append("");break;
+ case 1: ChatTag.append("\0037"+sIRC.ojGM1);break;
+ case 2: ChatTag.append("\0037"+sIRC.ojGM2);break;
+ case 3: ChatTag.append("\0037"+sIRC.ojGM3);break;
+ case 4: ChatTag.append("\0037"+sIRC.ojGM4);break;
+ case 5: ChatTag.append("\0037"+sIRC.ojGM5);break;
+ }
+ if(plr->isAFK())
+ ChatTag.append("\002\0037<AFK>\003\002");
+ else if(plr->isDND())
+ ChatTag.append("\002\0037<DND>\003\002");
+ switch (plr->GetTeam())
+ {
+ case 67:ChatTag.append("\0034");break; //horde
+ case 469:ChatTag.append("\00312");break; //alliance
+ }
+
+ IRCOut.append(IRCCmd::MakeMsg("%s\002%s\003\017\002(%d)\002\017", ChatTag.c_str(), plr->GetName(), plr->getLevel()));
+
+ // after XX players have been added to the string
+ // output to irc and reset for the next XX
+ if(OnlineCount % sIRC.onlrslt == 0)
+ {
+ sIRC.Send_IRC_Channel(IRCCmd::ChanOrPM(CD), IRCCmd::MakeMsg("\002 %s", IRCOut.c_str()), true, CD->TYPE.c_str());
+ IRCOut = "";
+ ZThread::Thread::sleep(1000);
+ }
+ }
+ }
+ // Remainder in IRCOUT && Total plyersonline
+ sIRC.Send_IRC_Channel(IRCCmd::ChanOrPM(CD), IRCCmd::MakeMsg("\002Players Online(%d):\017 %s", OnlineCount, IRCOut.c_str()), true, CD->TYPE);
+
+ sIRC.Script_Lock[MCS_Players_Online] = false;
+}
diff --git a/src/game/MCS_OnlinePlayers.h b/src/game/MCS_OnlinePlayers.h
new file mode 100644
index 00000000000..c93db9afdac
--- /dev/null
+++ b/src/game/MCS_OnlinePlayers.h
@@ -0,0 +1,27 @@
+#ifndef _IRC_CLIENT_ONLINE
+#define _IRC_CLIENT_ONLINE
+
+#include "IRCClient.h"
+#include "IRCCmd.h"
+
+// the reason to run this command multithreaded
+// is to be able to "spread" the output over irc
+// for servers with high player count
+// in order not to freeze the mangchat core with sleep
+// a new thread is spawned it will output the player data
+// evry "10 players" and pauzes to not spam irc
+// in addition the command is locked so i cannot be used
+// while active.
+
+class mcs_OnlinePlayers : public ZThread::Runnable
+{
+ public:
+ mcs_OnlinePlayers();
+ mcs_OnlinePlayers(_CDATA *_CD);
+ ~mcs_OnlinePlayers();
+ void run();
+ public:
+ _CDATA *CD;
+};
+
+#endif
diff --git a/src/game/Makefile.am b/src/game/Makefile.am
index 9c953662a18..e839304ad8c 100644
--- a/src/game/Makefile.am
+++ b/src/game/Makefile.am
@@ -141,6 +141,21 @@ $(srcdir)/InstanceData.cpp \
$(srcdir)/InstanceData.h \
$(srcdir)/InstanceSaveMgr.cpp \
$(srcdir)/InstanceSaveMgr.h \
+$(srcdir)/IRCClient.cpp \
+$(srcdir)/IRCClient.h \
+$(srcdir)/IRCCmd.cpp \
+$(srcdir)/IRCCmd.h \
+$(srcdir)/IRCCmde.cpp \
+$(srcdir)/IRCConf.cpp \
+$(srcdir)/IRCConf.h \
+$(srcdir)/IRCConf.h \
+$(srcdir)/IRCFunc.h \
+$(srcdir)/IRCIO.cpp \
+$(srcdir)/IRCLog.cpp \
+$(srcdir)/IRCLog.h \
+$(srcdir)/IRCSock.cpp \
+$(srcdir)/MCS_OnlinePlayers.cpp \
+$(srcdir)/MCS_OnlinePlayers.h \
$(srcdir)/Item.cpp \
$(srcdir)/Item.h \
$(srcdir)/ItemEnchantmentMgr.cpp \
diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp
index 010af48e050..96f13891938 100644
--- a/src/game/MiscHandler.cpp
+++ b/src/game/MiscHandler.cpp
@@ -254,8 +254,9 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data )
data << uint8(0); // new 2.4.0
data << uint32( pzoneid ); // player zone id
- // 49 is maximum player count sent to client
- if ((++clientcount) == 49)
+ // 49 is maximum player count sent to client - can be overriden
+ // through config, but is unstable
+ if ((++clientcount) == sWorld.getConfig(CONFIG_MAX_WHO))
break;
}
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 3beadc88278..ce2b936229f 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -58,6 +58,7 @@
#include "Database/DatabaseImpl.h"
#include "Spell.h"
#include "SocialMgr.h"
+#include "IRCClient.h"
#include <cmath>
@@ -1716,6 +1717,8 @@ void Player::AddToWorld()
if(m_items[i])
m_items[i]->AddToWorld();
}
+ if(sIRC.ajoin == 1)
+ sIRC.AutoJoinChannel(this);
}
void Player::RemoveFromWorld()
@@ -2146,6 +2149,17 @@ void Player::GiveLevel(uint32 level)
UpdateAllStats();
+ if((sIRC.BOTMASK & 64) != 0)
+ {
+ char temp [5];
+ sprintf(temp, "%u", level);
+ std::string plevel = temp;
+ std::string pname = GetName();
+ std::string ircchan = "#";
+ ircchan += sIRC._irc_chan[sIRC.Status].c_str();
+ sIRC.Send_IRC_Channel(ircchan, "\00311["+pname+"] : Has Reached Level: "+plevel, true);
+ }
+
if(sWorld.getConfig(CONFIG_ALWAYS_MAXSKILL)) // Max weapon skill when leveling up
UpdateSkillsToMaxSkillsForLevel();
diff --git a/src/game/World.cpp b/src/game/World.cpp
index 0e2b535c8d2..e352983768e 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -56,6 +56,8 @@
#include "InstanceSaveMgr.h"
#include "WaypointManager.h"
#include "Util.h"
+#include "IRCClient.h"
+#include "Language.h"
INSTANTIATE_SINGLETON_1( World );
@@ -575,6 +577,8 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_CHARACTERS_CREATING_DISABLED] = sConfig.GetIntDefault("CharactersCreatingDisabled", 0);
+ m_configs[CONFIG_MAX_WHO] = sConfig.GetIntDefault("MaxWhoListReturns", 49);
+
m_configs[CONFIG_CHARACTERS_PER_REALM] = sConfig.GetIntDefault("CharactersPerRealm", 10);
if(m_configs[CONFIG_CHARACTERS_PER_REALM] < 1 || m_configs[CONFIG_CHARACTERS_PER_REALM] > 10)
{
@@ -1176,6 +1180,9 @@ void World::SetInitialWorldSettings()
WorldDatabase.PExecute("INSERT INTO uptime (startstring, starttime, uptime) VALUES('%s', %ld, 0)", isoDate, m_startTime );
+ static uint32 autoanc = 1;
+ autoanc = sIRC.autoanc;
+
m_timers[WUPDATE_OBJECTS].SetInterval(0);
m_timers[WUPDATE_SESSIONS].SetInterval(0);
m_timers[WUPDATE_WEATHERS].SetInterval(1000);
@@ -1184,6 +1191,8 @@ void World::SetInitialWorldSettings()
//Update "uptime" table based on configuration entry in minutes.
m_timers[WUPDATE_CORPSES].SetInterval(20*MINUTE*1000); //erase corpses every 20 minutes
+ m_timers[WUPDATE_AUTOANC].SetInterval(autoanc*MINUTE*1000);
+
//to set mailtimer to return mails every day between 4 and 5 am
//mailtimer is increased when updating auctions
//one second is 1000 -(tested on win system)
@@ -1420,9 +1429,12 @@ void World::Update(time_t diff)
m_timers[WUPDATE_EVENTS].Reset();
}
- /// </ul>
- ///- Move all creatures with "delayed move" and remove and delete all objects with "delayed remove"
- MapManager::Instance().DoDelayedMovesAndRemoves();
+ if (m_timers[WUPDATE_AUTOANC].Passed())
+ {
+ m_timers[WUPDATE_AUTOANC].Reset(); /// </ul>
+ SendRNDBroadcast();
+ }
+ MapManager::Instance().DoDelayedMovesAndRemoves(); ///- Move all creatures with "delayed move" and remove and delete all objects with "delayed remove"
// update the instance reset times
sInstanceSaveManager.Update();
@@ -2494,7 +2506,23 @@ void World::ProcessCliCommands()
delete command;
}
// print the console message here so it looks right
- p_zprintf("mangos>");
+ p_zprintf("Trinity Core> ");
+}
+
+void World::SendRNDBroadcast()
+{
+ std::string msg;
+ QueryResult *result = WorldDatabase.PQuery("SELECT `message` FROM `IRC_AutoAnnounce` ORDER BY RAND() LIMIT 1");
+ if(!result)
+ return;
+ msg = result->Fetch()[0].GetString();
+ delete result;
+ std::string str = "|cffff0000[Automatic]:|r";
+ str += msg;
+ sWorld.SendWorldText(LANG_AUTO_ANN);
+ std::string ircchan = "#";
+ ircchan += sIRC._irc_chan[sIRC.anchn].c_str();
+ 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);
}
void World::InitResultQueue()
diff --git a/src/game/World.h b/src/game/World.h
index c67d975ed07..742cd11385e 100644
--- a/src/game/World.h
+++ b/src/game/World.h
@@ -59,7 +59,10 @@ enum WorldTimers
WUPDATE_UPTIME = 4,
WUPDATE_CORPSES = 5,
WUPDATE_EVENTS = 6,
- WUPDATE_COUNT = 7
+ WUPDATE_COUNT = 7,
+
+ WUPDATE_AUTOANC = 7
+
};
/// Configuration elements
@@ -91,6 +94,7 @@ enum WorldConfigs
CONFIG_STRICT_CHARTER_NAMES,
CONFIG_STRICT_PET_NAMES,
CONFIG_CHARACTERS_CREATING_DISABLED,
+ CONFIG_MAX_WHO,
CONFIG_CHARACTERS_PER_ACCOUNT,
CONFIG_CHARACTERS_PER_REALM,
CONFIG_SKIP_CINEMATICS,
@@ -365,6 +369,9 @@ class World
WorldSession* FindSession(uint32 id) const;
void AddSession(WorldSession *s);
+
+ void SendRNDBroadcast();
+
bool RemoveSession(uint32 id);
/// Get the number of current active sessions
void UpdateMaxSessionCounters();
diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h
index bca75923394..ce0887687ef 100644
--- a/src/shared/Database/DBCStructure.h
+++ b/src/shared/Database/DBCStructure.h
@@ -147,6 +147,7 @@ struct ChrClassesEntry
uint32 powerType; // 3
// 4, unused
//char* name[16]; // 5-20 unused
+ char* name[16]; // 5-20 unused
// 21 string flag, unused
//char* string1[16]; // 21-36 unused
// 37 string flag, unused
diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp
index e131d9379c5..0b7e1439520 100644
--- a/src/shared/Database/DBCfmt.cpp
+++ b/src/shared/Database/DBCfmt.cpp
@@ -23,7 +23,8 @@ const char BattlemasterListEntryfmt[]="niiixxxxxiiiixxssssssssssssssssxx";
const char CharTitlesEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx";
// ChatChannelsEntryfmt, index not used (more compact store)
-const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix";
+//const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix";
+const char ChrClassesEntryfmt[]="nxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix";
const char ChrRacesEntryfmt[]="nxixiixxixxxxissssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxx";
const char CreatureFamilyfmt[]="nfifiiiissssssssssssssssxx";
diff --git a/src/shared/Makefile.am b/src/shared/Makefile.am
index fcdbd6e216b..5a64a45fc29 100644
--- a/src/shared/Makefile.am
+++ b/src/shared/Makefile.am
@@ -53,6 +53,7 @@ $(srcdir)/Util.cpp \
$(srcdir)/Util.h \
$(srcdir)/WorldPacket.h \
$(srcdir)/SystemConfig.h \
+$(srcdir)../game/IRCConf.h \
$(srcdir)/Auth/AuthCrypt.cpp \
$(srcdir)/Auth/AuthCrypt.h \
$(srcdir)/Auth/BigNumber.cpp \
diff --git a/src/trinitycore/CliRunnable.cpp b/src/trinitycore/CliRunnable.cpp
index 2a92273f764..5f1518483f5 100644
--- a/src/trinitycore/CliRunnable.cpp
+++ b/src/trinitycore/CliRunnable.cpp
@@ -36,6 +36,7 @@
#include "MapManager.h"
#include "PlayerDump.h"
#include "Player.h"
+#include "IRCClient.h"
//CliCommand and CliCommandHolder are defined in World.h to avoid cyclic deps
@@ -313,6 +314,14 @@ void CliBroadcast(char *text,pPrintf zprintf)
sWorld.SendWorldText(LANG_SYSTEMMESSAGE,textUtf8.c_str());
zprintf("Broadcasting to the world: %s\r\n",textUtf8.c_str());
+
+ if((sIRC.BOTMASK & 256) != 0)
+ {
+ std::string ircchan = "#";
+ ircchan += sIRC._irc_chan[sIRC.anchn].c_str();
+ sIRC.Send_IRC_Channel(ircchan, sIRC.MakeMsg("\00304,08\037/!\\\037\017\00304 System Message \00304,08\037/!\\\037\017 %s", "%s", text), true);
+ }
+
}
/// Print the list of commands and associated description
diff --git a/src/trinitycore/Main.cpp b/src/trinitycore/Main.cpp
index 27e8c0861ce..1c3ec6fea6e 100644
--- a/src/trinitycore/Main.cpp
+++ b/src/trinitycore/Main.cpp
@@ -25,6 +25,8 @@
#include "Config/ConfigEnv.h"
#include "Log.h"
#include "Master.h"
+#include "../game/IRCConf.h"
+#include "../game/IRCClient.h"
#ifndef _TRINITY_CORE_CONFIG
# define _TRINITY_CORE_CONFIG "trinitycore.conf"
@@ -75,6 +77,7 @@ extern int main(int argc, char **argv)
{
///- Command line parsing to get the configuration file name
char const* cfg_file = _TRINITY_CORE_CONFIG;
+ char const* mc_cfg_file = _TRINITY_CORE_CONFIG;
int c=1;
while( c < argc )
{
@@ -135,7 +138,8 @@ extern int main(int argc, char **argv)
sLog.outError("Could not find configuration file %s.", cfg_file);
return 1;
}
-
+
+ sIRC.SetCfg(mc_cfg_file);
sLog.outString("Using configuration file %s.", cfg_file);
uint32 confVersion = sConfig.GetIntDefault("ConfVersion", 0);
diff --git a/src/trinitycore/Master.cpp b/src/trinitycore/Master.cpp
index ee42f16b87a..216a48c59c0 100644
--- a/src/trinitycore/Master.cpp
+++ b/src/trinitycore/Master.cpp
@@ -38,6 +38,7 @@
#include "RASocket.h"
#include "ScriptCalls.h"
#include "Util.h"
+#include "IRCClient.h"
#include "sockets/TcpSocket.h"
#include "sockets/Utility.h"
@@ -226,6 +227,9 @@ int Master::Run()
if (!_StartDB())
return 1;
+ ///- Load IRC Config (need DB for gm levels, AutoBroadcast uses world timers)
+ sIRC.LoadConfig(sIRC.CfgFile);
+
///- Initialize the World
sWorld.SetInitialWorldSettings();
@@ -309,6 +313,12 @@ int Master::Run()
uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / socketSelecttime));
uint32 loopCounter = 0;
+ // Start up IRC bot
+ ZThread::Thread irc(new IRCClient);
+ irc.setPriority ((ZThread::Priority )2);
+
+
+
///- Start up freeze catcher thread
uint32 freeze_delay = sConfig.GetIntDefault("MaxCoreStuckTime", 0);
if(freeze_delay)
diff --git a/src/trinitycore/trinitycore.conf.dist b/src/trinitycore/trinitycore.conf.dist
index 5eeacc53561..b6cdd410a8b 100644
--- a/src/trinitycore/trinitycore.conf.dist
+++ b/src/trinitycore/trinitycore.conf.dist
@@ -388,6 +388,10 @@ LogColors = ""
# 2 - disabled only for Horde
# 3 - disabled for both teams
#
+# MaxWhoListReturns
+# Set the maximum number of players returned in the /who list and interface.
+# Default: 49 (stable)
+#
# CharactersPerAccount
# Limit numbers of characters per account (at all realms).
# Note: this setting limit character creating at _current_ realm base at characters amount at all realms
@@ -512,6 +516,7 @@ DeclinedNames = 0
StrictPlayerNames = 0
StrictCharterNames = 0
StrictPetNames = 0
+MaxWhoListReturns = 49
CharactersCreatingDisabled = 0
CharactersPerAccount = 50
CharactersPerRealm = 10
@@ -1184,3 +1189,191 @@ PvPToken.MapAllowType = 4
PvPToken.ItemID = 29434
PvPToken.ItemCount = 1
NoResetTalentsCost = 0
+
+###################################################################################################################
+# IRC SYSTEM CONFIG
+#
+# irc.active
+# Enable IRC bot/system
+# Default: 0 - Disable
+# 0 - Enable
+# irc.icc
+# IRC connect code
+# Default: 001 - Welcome To Network msg
+# 375 - Beginning Of MOTD
+# 376 - End Of MOTD
+#
+# irc.host
+# IRC server to connect to
+#
+# irc.port
+# IRC server port to use
+# Default: "6667" - Semi-standard IRC port
+#
+# irc.user
+# The username/ident to use when connecting to the IRC server
+#
+# irc.nick
+# IRC nickname to be used by the bot
+#
+# irc.pass
+# The password to be used to identify to NickServ
+#
+# irc.auth
+# IRC Authentication Method
+# Default: 0 - Disable
+# 1 - NickServ - Normal Method - PRIVMSG NickServ :IDENTIFY Password
+# 2 - NickServ - Alternate Method To Identify To A Different Nick - PRIVMSG NickServ :IDENTIFY irc.auth.nick Password
+# 3 - QuakeNet - Normal Method - PRIVMSG Q@CServe.quakenet.org :AUTH irc.nick Password
+# 4 - QuakeNet - Alternate Method To Identify To A Different Nick - PRIVMSG Q@CServe.quakenet.org :AUTH irc.auth.nick Password
+#
+# irc.auth.nick
+# IRC Nickname to use if Auth method 2 or 4 is used
+#
+# irc.ldef
+# Leave a defined IRC channel on server connect
+# Default: 0 - Disable
+# 1 - Enable
+# irc.defchan
+# IRC channel to leave on server connect if irc.ldef is on
+#
+# irc.wct
+# Time to wait before (re)attemptimg connection to IRC server
+# Default: 30000 - (30 Seconds)
+#
+# irc.maxattempt
+# Maximum attempts to try IRC server
+# Default: 20
+#
+# irc.auto.announce
+# Time to wait in Minutes to announce random messages from database.
+# Default: 30 - (30 Minutes)
+#
+# irc.autojoin_kick
+# Autojoin IRC channel if kicked
+# Default: 1 - Enable
+# 0 - Disable
+#
+# irc.command_prefix
+# IRC command prefix
+# Example: (.)online all
+#
+# irc.joinmsg
+# irc.rstmsg
+# irc.kickmsg
+# Bot join/restart/kick messages
+#
+# irc.chan_#
+# wow.chan_#
+# IRC and WOW channels to link. Leave # out of IRC channel. Both channels _ARE_ case sensitive
+# Example: irc.chan_1 = "Trinity"
+# irc.chan_2 = "trinity2"
+# wow.chan_1 = "world"
+# wow.chan_2 = "LookingForGroup"
+#
+# irc.StatusChannel
+# Channel Number To Display Status Messages In (AuctionHouse, Levels, Deaths, Etc)
+# Default: 1 - Channel ID 1
+#
+# irc.AnnounceChannel
+# Channel Number To Display Announcements In (Announces, Notifies, Event)
+# Default: 1 - Channel ID 1
+#
+# irc.op_gm_login
+# Op The GM In All Channels The Bot Is On When They Log In
+# Default: 0 - Disable
+# 1 - Enable
+#
+# irc.op_gm_level
+# The Minimum GM Level Required To Have The Bot Op The User
+# Default: 5 - GM Level 5
+#
+# irc.ajoin (Experimental/Under Development)
+# Force players to autojoin an in game channel
+# Atleast one player must be in the channel on server start, and atleast one person online for invite to work
+# Default: 0 - Disable
+# 1 - Enable
+# irc.ajchan
+# Channel to join if above is Enabled.
+#
+# irc.online.result
+# Maximum number of results per line for the online command
+#
+# chat.*** (Defineable Strings)
+# wow_* - String is displayed in IRC channel
+# irc_* - String is displayed in WOW channel
+# Options: $Name, $Level, $Msg, $GM (not all options work in every string)
+#
+# Botmask
+# This defines what the bot announces, if its 0 everything is disabled
+# simply add the values of the elements you want to create this mask.
+# Example: WoW join/leaves are 1 and IRC join/leaves are 2, if you want both of these active then the BotMask is 3.
+# (1)Display WoW Chan Join/Leaves In IRC
+# (2)Display IRC Chan Join/Leaves/NickChanges In WoW
+# (4)Display Unknown Command Message When Trigger Is Used And No Command Exists
+# (8)Announce Security Level > 0 As GM At Login
+# (16)Announce GM In GM ON State AS GM At Login
+# (32)Return Errors To Notice. (If disabled then default is Private Message)
+# (64)Display WoW Status Messages (Levels/Deaths)
+# (128)Display Nick Changes From IRC In WOW
+# (256)Display WoW Announces/Notifies In IRC
+# (512)Do Not Let Players Use Commands On Higher GM Level Players
+# (1024)Enable AuctionHouse Announcements
+#
+# irc.gmlog
+# Minimum GM level to not show login/pass info in IRC logs
+#
+# irc.logfile.prefix
+# The prefix of the IRC logfile. Directories can be added here.
+# Example: "IRC/IRC_" outputs IRC_YYYY-MM-DD.log to the IRC subdirectory in your logs dir
+#
+# irc.fun.games (Experimental/Under Development)
+# Enable IRC games
+# Default: 0 - Disable
+# 1 - Enable
+# irc.gm#
+# GM tag to append to (GM onjoin / online command) IRC color codes are acceptable
+#
+###################################################################################################################
+
+irc.active = 0
+irc.icc = 001
+irc.host = ""
+irc.port = "6667"
+irc.user = "TC"
+irc.nick = "TrinityCoreBot"
+irc.pass = ""
+irc.auth = 0
+irc.auth.nick = "TrinityCoreBot"
+irc.ldef = 0
+irc.defchan = "lobby"
+irc.wct = 30000
+irc.maxattempt = 20
+irc.auto.announce = 30
+irc.autojoin_kick = 1
+irc.command_prefix = "."
+irc.joinmsg = "Trinity Core running. Command trigger is $Trigger."
+irc.rstmsg = "Trinity Core is restarting..."
+irc.kickmsg = "Do not kick me."
+irc.chan_1 = "mangos"
+wow.chan_1 = "world"
+irc.StatusChannel = 1
+irc.AnnounceChannel = 1
+irc.op_gm_login = 0
+irc.op_gm_level = 3
+irc.ajoin = 1
+irc.ajchan = "world"
+irc.online.result = 30
+chat.wow_irc = "<WoW>$Name [$Level]: $Msg"
+chat.irc_wow = "<IRC>$Name: $Msg"
+chat.join_wow = "[$GM] $Name has joined IRC."
+chat.leave_wow = "[$GM] $Name has left IRC."
+Botmask = 1023
+irc.gmlog = 1
+irc.logfile.prefix = "irc_"
+irc.fun.games = 0
+irc.gm1 = "[Moderator]"
+irc.gm2 = "[Game Master]"
+irc.gm3 = "[BugTracker]"
+irc.gm4 = "[DevTeam Admin]"
+irc.gm5 = "[SysOP]"