diff options
| author | Rat <none@none> | 2010-06-05 23:40:08 +0200 |
|---|---|---|
| committer | Rat <none@none> | 2010-06-05 23:40:08 +0200 |
| commit | 75b80d9f5b02a643c983b2fb1ededed79fd5d133 (patch) | |
| tree | ebd1c2cc12a2715909dd04c1ed147a260c6ceb14 /src/server/game/Chat | |
| parent | 6a9357b13d7ea6bd7d77dbfc6587af9028caa401 (diff) | |
rearranged core files
--HG--
branch : trunk
Diffstat (limited to 'src/server/game/Chat')
| -rw-r--r-- | src/server/game/Chat/Channel.cpp | 1102 | ||||
| -rw-r--r-- | src/server/game/Chat/Channel.h | 292 | ||||
| -rw-r--r-- | src/server/game/Chat/ChannelHandler.cpp | 323 | ||||
| -rw-r--r-- | src/server/game/Chat/ChannelMgr.cpp | 110 | ||||
| -rw-r--r-- | src/server/game/Chat/ChannelMgr.h | 57 | ||||
| -rw-r--r-- | src/server/game/Chat/Chat.cpp | 2458 | ||||
| -rw-r--r-- | src/server/game/Chat/Chat.h | 654 | ||||
| -rw-r--r-- | src/server/game/Chat/ChatHandler.cpp | 756 | ||||
| -rw-r--r-- | src/server/game/Chat/Debugcmds.cpp | 1127 | ||||
| -rw-r--r-- | src/server/game/Chat/Level0.cpp | 295 | ||||
| -rw-r--r-- | src/server/game/Chat/Level1.cpp | 2960 | ||||
| -rw-r--r-- | src/server/game/Chat/Level2.cpp | 4526 | ||||
| -rw-r--r-- | src/server/game/Chat/Level3.cpp | 7743 |
13 files changed, 22403 insertions, 0 deletions
diff --git a/src/server/game/Chat/Channel.cpp b/src/server/game/Chat/Channel.cpp new file mode 100644 index 00000000000..0047892972b --- /dev/null +++ b/src/server/game/Chat/Channel.cpp @@ -0,0 +1,1102 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Channel.h" +#include "Chat.h" +#include "ObjectMgr.h" +#include "SocialMgr.h" +#include "World.h" + +Channel::Channel(const std::string& name, uint32 channel_id, uint32 Team) + : m_name(name), m_announce(true), m_moderate(false), m_channelId(channel_id), m_ownerGUID(0), m_password(""), m_flags(0), m_Team(Team) +{ + // set special flags if built-in channel + ChatChannelsEntry const* ch = GetChannelEntryFor(channel_id); + if (ch) // it's built-in channel + { + channel_id = ch->ChannelID; // built-in channel + m_announce = false; // no join/leave announces + + m_flags |= CHANNEL_FLAG_GENERAL; // for all built-in channels + + if (ch->flags & CHANNEL_DBC_FLAG_TRADE) // for trade channel + m_flags |= CHANNEL_FLAG_TRADE; + + if (ch->flags & CHANNEL_DBC_FLAG_CITY_ONLY2) // for city only channels + m_flags |= CHANNEL_FLAG_CITY; + + if (ch->flags & CHANNEL_DBC_FLAG_LFG) // for LFG channel + m_flags |= CHANNEL_FLAG_LFG; + else // for all other channels + m_flags |= CHANNEL_FLAG_NOT_LFG; + m_IsSaved = false; + } + else // it's custom channel + { + m_flags |= CHANNEL_FLAG_CUSTOM; + //load not built in channel if saved + std::string _name(name); + CharacterDatabase.escape_string(_name); + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT m_announce, m_moderate, m_public, m_password, BannedList FROM channels WHERE m_name = '%s' AND m_team = '%u'", _name.c_str(), m_Team); + if (result)//load + { + Field *fields = result->Fetch(); + m_announce = fields[0].GetBool(); + m_moderate = fields[1].GetBool(); + m_public = fields[2].GetBool(); + m_password = fields[3].GetString(); + const char* db_BannedList = fields[4].GetString(); + + m_IsSaved = true; + + if (db_BannedList) + { + Tokens tokens = StrSplit(db_BannedList, " "); + Tokens::iterator iter; + for (iter = tokens.begin(); iter != tokens.end(); ++iter) + { + uint64 banned_guid = atol((*iter).c_str()); + if (banned_guid) + { + sLog.outDebug("Channel(%s) loaded banned guid: %u",name.c_str(), banned_guid); + banned.insert(banned_guid); + } + } + } + } + else // save + { + // _name is already escaped at this point. + if (CharacterDatabase.PExecute("INSERT INTO channels (m_name, m_team, m_announce, m_moderate, m_public, m_password) " + "VALUES ('%s', '%u', '1', '0', '1', '')", _name.c_str(), m_Team)) + { + sLog.outDebug("New Channel(%s) saved", name.c_str()); + m_IsSaved = true; + } + } + } +} + +bool Channel::_UpdateStringInDB(const std::string& colName, const std::string& colValue) const +{ + // Prevent SQL-injection + std::string _name(m_name); + std::string _colValue(colValue); + CharacterDatabase.escape_string(_colValue); + CharacterDatabase.escape_string(_name); + return CharacterDatabase.PExecute("UPDATE channels SET %s = '%s' WHERE m_name = '%s' AND m_team = '%u'", + colName.c_str(), _colValue.c_str(), _name.c_str(), m_Team); +} + +bool Channel::_UpdateIntInDB(const std::string& colName, int colValue) const +{ + // Prevent SQL-injection + std::string _name(m_name); + CharacterDatabase.escape_string(_name); + return CharacterDatabase.PExecute("UPDATE channels SET %s = '%u' WHERE m_name = '%s' AND m_team = '%u'", + colName.c_str(), colValue, _name.c_str(), m_Team); +} + +void Channel::_UpdateBanListInDB() const +{ + // save banlist + if (m_IsSaved) + { + std::ostringstream banlist; + BannedList::const_iterator iter; + for (iter = banned.begin(); iter != banned.end(); ++iter) + banlist << (*iter) << " "; + std::string banListStr = banlist.str(); + if (_UpdateStringInDB("BannedList", banListStr)) + sLog.outDebug("Channel(%s) BannedList saved", m_name.c_str()); + } +} + +void Channel::Join(uint64 p, const char *pass) +{ + WorldPacket data; + if (IsOn(p)) + { + if (!IsConstant()) // non send error message for built-in channels + { + MakePlayerAlreadyMember(&data, p); + SendToOne(&data, p); + } + return; + } + + if (IsBanned(p)) + { + MakeBanned(&data); + SendToOne(&data, p); + return; + } + + if (m_password.length() > 0 && strcmp(pass, m_password.c_str())) + { + MakeWrongPassword(&data); + SendToOne(&data, p); + return; + } + + Player *plr = objmgr.GetPlayer(p); + + if (plr) + { + if (HasFlag(CHANNEL_FLAG_LFG) && + sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && plr->GetSession()->GetSecurity() == SEC_PLAYER && plr->GetGroup()) + { + MakeNotInLfg(&data); + SendToOne(&data, p); + return; + } + + if (plr->GetGuildId() && (GetFlags() == 0x38)) + return; + + plr->JoinedChannel(this); + } + + if (m_announce && (!plr || plr->GetSession()->GetSecurity() < SEC_GAMEMASTER || !sWorld.getConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL))) + { + MakeJoined(&data, p); + SendToAll(&data); + } + + data.clear(); + + PlayerInfo pinfo; + pinfo.player = p; + pinfo.flags = MEMBER_FLAG_NONE; + players[p] = pinfo; + + MakeYouJoined(&data); + SendToOne(&data, p); + + JoinNotify(p); + + // if no owner first logged will become + if (!IsConstant() && !m_ownerGUID) + { + SetOwner(p, (players.size() > 1 ? true : false)); + players[p].SetModerator(true); + } + /* + else if (!IsConstant() && m_ownerGUID && plr && m_ownerGUID == plr->GetGUID())) + { + SetOwner(p, (players.size() > 1 ? true : false)); + players[p].SetModerator(true); + }*/ +} + +void Channel::Leave(uint64 p, bool send) +{ + if (!IsOn(p)) + { + if (send) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + } + else + { + Player *plr = objmgr.GetPlayer(p); + + if (send) + { + WorldPacket data; + MakeYouLeft(&data); + SendToOne(&data, p); + if (plr) + plr->LeftChannel(this); + data.clear(); + } + + bool changeowner = players[p].IsOwner(); + + players.erase(p); + if (m_announce && (!plr || plr->GetSession()->GetSecurity() < SEC_GAMEMASTER || !sWorld.getConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL))) + { + WorldPacket data; + MakeLeft(&data, p); + SendToAll(&data); + } + + LeaveNotify(p); + + if (changeowner) + { + uint64 newowner = !players.empty() ? players.begin()->second.player : 0; + players[newowner].SetModerator(true); + SetOwner(newowner); + } + } +} + +void Channel::KickOrBan(uint64 good, const char *badname, bool ban) +{ + AccountTypes sec = SEC_PLAYER; + Player *gplr = objmgr.GetPlayer(good); + if (gplr) + sec = gplr->GetSession()->GetSecurity(); + + if (!IsOn(good)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, good); + } + else if (!players[good].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, good); + } + else + { + Player *bad = objmgr.GetPlayer(badname); + if (bad == NULL || !IsOn(bad->GetGUID())) + { + WorldPacket data; + MakePlayerNotFound(&data, badname); + SendToOne(&data, good); + } + else if (sec < SEC_GAMEMASTER && bad->GetGUID() == m_ownerGUID && good != m_ownerGUID) + { + WorldPacket data; + MakeNotOwner(&data); + SendToOne(&data, good); + } + else + { + bool changeowner = (m_ownerGUID == bad->GetGUID()); + + WorldPacket data; + + if (ban && !IsBanned(bad->GetGUID())) + { + banned.insert(bad->GetGUID()); + MakePlayerBanned(&data, bad->GetGUID(), good); + _UpdateBanListInDB(); + + } + else + MakePlayerKicked(&data, bad->GetGUID(), good); + + SendToAll(&data); + players.erase(bad->GetGUID()); + bad->LeftChannel(this); + + if (changeowner) + { + uint64 newowner = !players.empty() ? good : false; + players[newowner].SetModerator(true); + SetOwner(newowner); + } + } + } +} + +void Channel::UnBan(uint64 good, const char *badname) +{ + uint32 sec = 0; + Player *gplr = objmgr.GetPlayer(good); + if (gplr) + sec = gplr->GetSession()->GetSecurity(); + + if (!IsOn(good)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, good); + } + else if (!players[good].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, good); + } + else + { + Player *bad = objmgr.GetPlayer(badname); + if (bad == NULL || !IsBanned(bad->GetGUID())) + { + WorldPacket data; + MakePlayerNotFound(&data, badname); + SendToOne(&data, good); + } + else + { + banned.erase(bad->GetGUID()); + + WorldPacket data; + MakePlayerUnbanned(&data, bad->GetGUID(), good); + SendToAll(&data); + //save banlist + _UpdateBanListInDB(); + } + } +} + +void Channel::Password(uint64 p, const char *pass) +{ + std::string plName; + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if (plr) + sec = plr->GetSession()->GetSecurity(); + + ChatHandler chat(plr); + + if (!m_public && sec <= SEC_MODERATOR) + { + chat.PSendSysMessage(LANG_CHANNEL_NOT_PUBLIC); + return; + } + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if (!players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + m_password = pass; + + WorldPacket data; + MakePasswordChanged(&data, p); + SendToAll(&data); + if (m_IsSaved && _UpdateStringInDB("m_password", m_password)) + sLog.outDebug("Channel(%s) password saved", m_name.c_str()); + } +} + +void Channel::SetMode(uint64 p, const char *p2n, bool mod, bool set) +{ + Player *plr = objmgr.GetPlayer(p); + if (!plr) + return; + + uint32 sec = plr->GetSession()->GetSecurity(); + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if (!players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + Player *newp = objmgr.GetPlayer(p2n); + if (!newp) + { + WorldPacket data; + MakePlayerNotFound(&data, p2n); + SendToOne(&data, p); + return; + } + + if (p == m_ownerGUID && newp->GetGUID() == m_ownerGUID && mod) + return; + + if (!IsOn(newp->GetGUID())) + { + WorldPacket data; + MakePlayerNotFound(&data, p2n); + SendToOne(&data, p); + return; + } + + // allow make moderator from another team only if both is GMs + // at this moment this only way to show channel post for GM from another team + if ((plr->GetSession()->GetSecurity() < SEC_GAMEMASTER || newp->GetSession()->GetSecurity() < SEC_GAMEMASTER) && + plr->GetTeam() != newp->GetTeam() && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + { + WorldPacket data; + MakePlayerNotFound(&data, p2n); + SendToOne(&data, p); + return; + } + + if (m_ownerGUID == newp->GetGUID() && m_ownerGUID != p) + { + WorldPacket data; + MakeNotOwner(&data); + SendToOne(&data, p); + return; + } + + if (mod) + SetModerator(newp->GetGUID(), set); + else + SetMute(newp->GetGUID(), set); + } +} + +void Channel::SetOwner(uint64 p, const char *newname) +{ + Player *plr = objmgr.GetPlayer(p); + if (!plr) + return; + + uint32 sec = plr->GetSession()->GetSecurity(); + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + return; + } + + if (sec < SEC_GAMEMASTER && p != m_ownerGUID) + { + WorldPacket data; + MakeNotOwner(&data); + SendToOne(&data, p); + return; + } + + Player *newp = objmgr.GetPlayer(newname); + if (newp == NULL || !IsOn(newp->GetGUID())) + { + WorldPacket data; + MakePlayerNotFound(&data, newname); + SendToOne(&data, p); + return; + } + + if (newp->GetTeam() != plr->GetTeam() && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + { + WorldPacket data; + MakePlayerNotFound(&data, newname); + SendToOne(&data, p); + return; + } + + players[newp->GetGUID()].SetModerator(true); + SetOwner(newp->GetGUID()); +} + +void Channel::SendWhoOwner(uint64 p) +{ + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else + { + WorldPacket data; + MakeChannelOwner(&data); + SendToOne(&data, p); + } +} + +void Channel::List(Player* player) +{ + uint64 p = player->GetGUID(); + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else + { + WorldPacket data(SMSG_CHANNEL_LIST, 1+(GetName().size()+1)+1+4+players.size()*(8+1)); + data << uint8(1); // channel type? + data << GetName(); // channel name + data << uint8(GetFlags()); // channel flags? + + size_t pos = data.wpos(); + data << uint32(0); // size of list, placeholder + + uint32 gmLevelInWhoList = sWorld.getConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); + + uint32 count = 0; + for (PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + Player *plr = objmgr.GetPlayer(i->first); + + // PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters + // MODERATOR, GAME MASTER, ADMINISTRATOR can see all + if (plr && (player->GetSession()->GetSecurity() > SEC_PLAYER || plr->GetSession()->GetSecurity() <= gmLevelInWhoList) && + plr->IsVisibleGloballyFor(player)) + { + data << uint64(i->first); + data << uint8(i->second.flags); // flags seems to be changed... + ++count; + } + } + + data.put<uint32>(pos,count); + + SendToOne(&data, p); + } +} + +void Channel::Announce(uint64 p) +{ + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if (plr) + sec = plr->GetSession()->GetSecurity(); + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if (!players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + m_announce = !m_announce; + + WorldPacket data; + if (m_announce) + MakeAnnouncementsOn(&data, p); + else + MakeAnnouncementsOff(&data, p); + SendToAll(&data); + if (m_IsSaved && _UpdateIntInDB("m_announce", m_announce ? 1 : 0)) + sLog.outDebug("Channel(%s) announce saved", m_name.c_str()); + + } +} + +void Channel::Moderate(uint64 p) +{ + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if (plr) + sec = plr->GetSession()->GetSecurity(); + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if (!players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + m_moderate = !m_moderate; + + WorldPacket data; + if (m_moderate) + MakeModerationOn(&data, p); + else + MakeModerationOff(&data, p); + SendToAll(&data); + if (m_IsSaved && _UpdateIntInDB("m_announce", m_announce ? 1 : 0)) + sLog.outDebug("Channel(%s) announce saved", m_name.c_str()); + } +} + +void Channel::Say(uint64 p, const char *what, uint32 lang) +{ + if (!what) + return; + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + lang = LANG_UNIVERSAL; + + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if (plr) + sec = plr->GetSession()->GetSecurity(); + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if (players[p].IsMuted()) + { + WorldPacket data; + MakeMuted(&data); + SendToOne(&data, p); + } + else if (m_moderate && !players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + uint32 messageLength = strlen(what) + 1; + + WorldPacket data(SMSG_MESSAGECHAT, 1+4+8+4+m_name.size()+1+8+4+messageLength+1); + data << (uint8)CHAT_MSG_CHANNEL; + data << (uint32)lang; + data << p; // 2.1.0 + data << uint32(0); // 2.1.0 + data << m_name; + data << p; + data << messageLength; + data << what; + data << uint8(plr ? plr->chatTag() : 0); + + SendToAll(&data, !players[p].IsModerator() ? p : false); + } +} + +void Channel::Invite(uint64 p, const char *newname) +{ + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + return; + } + + Player *newp = objmgr.GetPlayer(newname); + if (!newp) + { + WorldPacket data; + MakePlayerNotFound(&data, newname); + SendToOne(&data, p); + return; + } + + Player *plr = objmgr.GetPlayer(p); + if (!plr) + return; + + if (newp->GetTeam() != plr->GetTeam() && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + { + WorldPacket data; + MakeInviteWrongFaction(&data); + SendToOne(&data, p); + return; + } + + if (IsOn(newp->GetGUID())) + { + WorldPacket data; + MakePlayerAlreadyMember(&data, newp->GetGUID()); + SendToOne(&data, p); + return; + } + + WorldPacket data; + if (!newp->GetSocial()->HasIgnore(GUID_LOPART(p))) + { + MakeInvite(&data, p); + SendToOne(&data, newp->GetGUID()); + data.clear(); + } + MakePlayerInvited(&data, newp->GetName()); + SendToOne(&data, p); +} + +void Channel::SetOwner(uint64 guid, bool exclaim) +{ + if (m_ownerGUID) + { + // [] will re-add player after it possible removed + PlayerList::iterator p_itr = players.find(m_ownerGUID); + if (p_itr != players.end()) + p_itr->second.SetOwner(false); + } + + m_ownerGUID = guid; + if (m_ownerGUID) + { + uint8 oldFlag = GetPlayerFlags(m_ownerGUID); + players[m_ownerGUID].SetModerator(true); + players[m_ownerGUID].SetOwner(true); + + WorldPacket data; + MakeModeChange(&data, m_ownerGUID, oldFlag); + SendToAll(&data); + + if (exclaim) + { + MakeOwnerChanged(&data, m_ownerGUID); + SendToAll(&data); + } + if (m_IsSaved && _UpdateIntInDB("m_moderate", m_moderate ? 1 : 0)) + sLog.outDebug("Channel(%s) moderate saved", m_name.c_str()); + + } +} + +void Channel::SendToAll(WorldPacket *data, uint64 p) +{ + for (PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + Player *plr = objmgr.GetPlayer(i->first); + if (plr) + { + if (!p || !plr->GetSocial()->HasIgnore(GUID_LOPART(p))) + plr->GetSession()->SendPacket(data); + } + } +} + +void Channel::SendToAllButOne(WorldPacket *data, uint64 who) +{ + for (PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + if (i->first != who) + { + Player *plr = objmgr.GetPlayer(i->first); + if (plr) + plr->GetSession()->SendPacket(data); + } + } +} + +void Channel::SendToOne(WorldPacket *data, uint64 who) +{ + Player *plr = objmgr.GetPlayer(who); + if (plr) + plr->GetSession()->SendPacket(data); +} + +void Channel::Voice(uint64 /*guid1*/, uint64 /*guid2*/) +{ + +} + +void Channel::DeVoice(uint64 /*guid1*/, uint64 /*guid2*/) +{ + +} + +// done +void Channel::MakeNotifyPacket(WorldPacket *data, uint8 notify_type) +{ + data->Initialize(SMSG_CHANNEL_NOTIFY, 1+m_name.size()+1); + *data << uint8(notify_type); + *data << m_name; +} + +// done 0x00 +void Channel::MakeJoined(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_JOINED_NOTICE); + *data << uint64(guid); +} + +// done 0x01 +void Channel::MakeLeft(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_LEFT_NOTICE); + *data << uint64(guid); +} + +// done 0x02 +void Channel::MakeYouJoined(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_YOU_JOINED_NOTICE); + *data << uint8(GetFlags()); + *data << uint32(GetChannelId()); + *data << uint32(0); +} + +// done 0x03 +void Channel::MakeYouLeft(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_YOU_LEFT_NOTICE); + *data << uint32(GetChannelId()); + *data << uint8(0); // can be 0x00 and 0x01 +} + +// done 0x04 +void Channel::MakeWrongPassword(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_WRONG_PASSWORD_NOTICE); +} + +// done 0x05 +void Channel::MakeNotMember(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_MEMBER_NOTICE); +} + +// done 0x06 +void Channel::MakeNotModerator(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_MODERATOR_NOTICE); +} + +// done 0x07 +void Channel::MakePasswordChanged(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_PASSWORD_CHANGED_NOTICE); + *data << uint64(guid); +} + +// done 0x08 +void Channel::MakeOwnerChanged(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_OWNER_CHANGED_NOTICE); + *data << uint64(guid); +} + +// done 0x09 +void Channel::MakePlayerNotFound(WorldPacket *data, const std::string& name) +{ + MakeNotifyPacket(data, CHAT_PLAYER_NOT_FOUND_NOTICE); + *data << name; +} + +// done 0x0A +void Channel::MakeNotOwner(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_OWNER_NOTICE); +} + +// done 0x0B +void Channel::MakeChannelOwner(WorldPacket *data) +{ + std::string name = ""; + + if (!objmgr.GetPlayerNameByGUID(m_ownerGUID, name) || name.empty()) + name = "PLAYER_NOT_FOUND"; + + MakeNotifyPacket(data, CHAT_CHANNEL_OWNER_NOTICE); + *data << ((IsConstant() || !m_ownerGUID) ? "Nobody" : name); +} + +// done 0x0C +void Channel::MakeModeChange(WorldPacket *data, uint64 guid, uint8 oldflags) +{ + MakeNotifyPacket(data, CHAT_MODE_CHANGE_NOTICE); + *data << uint64(guid); + *data << uint8(oldflags); + *data << uint8(GetPlayerFlags(guid)); +} + +// done 0x0D +void Channel::MakeAnnouncementsOn(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_ANNOUNCEMENTS_ON_NOTICE); + *data << uint64(guid); +} + +// done 0x0E +void Channel::MakeAnnouncementsOff(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_ANNOUNCEMENTS_OFF_NOTICE); + *data << uint64(guid); +} + +// done 0x0F +void Channel::MakeModerationOn(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_MODERATION_ON_NOTICE); + *data << uint64(guid); +} + +// done 0x10 +void Channel::MakeModerationOff(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_MODERATION_OFF_NOTICE); + *data << uint64(guid); +} + +// done 0x11 +void Channel::MakeMuted(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_MUTED_NOTICE); +} + +// done 0x12 +void Channel::MakePlayerKicked(WorldPacket *data, uint64 bad, uint64 good) +{ + MakeNotifyPacket(data, CHAT_PLAYER_KICKED_NOTICE); + *data << uint64(bad); + *data << uint64(good); +} + +// done 0x13 +void Channel::MakeBanned(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_BANNED_NOTICE); +} + +// done 0x14 +void Channel::MakePlayerBanned(WorldPacket *data, uint64 bad, uint64 good) +{ + MakeNotifyPacket(data, CHAT_PLAYER_BANNED_NOTICE); + *data << uint64(bad); + *data << uint64(good); +} + +// done 0x15 +void Channel::MakePlayerUnbanned(WorldPacket *data, uint64 bad, uint64 good) +{ + MakeNotifyPacket(data, CHAT_PLAYER_UNBANNED_NOTICE); + *data << uint64(bad); + *data << uint64(good); +} + +// done 0x16 +void Channel::MakePlayerNotBanned(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_PLAYER_NOT_BANNED_NOTICE); + *data << uint64(guid); +} + +// done 0x17 +void Channel::MakePlayerAlreadyMember(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_PLAYER_ALREADY_MEMBER_NOTICE); + *data << uint64(guid); +} + +// done 0x18 +void Channel::MakeInvite(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_INVITE_NOTICE); + *data << uint64(guid); +} + +// done 0x19 +void Channel::MakeInviteWrongFaction(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_INVITE_WRONG_FACTION_NOTICE); +} + +// done 0x1A +void Channel::MakeWrongFaction(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_WRONG_FACTION_NOTICE); +} + +// done 0x1B +void Channel::MakeInvalidName(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_INVALID_NAME_NOTICE); +} + +// done 0x1C +void Channel::MakeNotModerated(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_MODERATED_NOTICE); +} + +// done 0x1D +void Channel::MakePlayerInvited(WorldPacket *data, const std::string& name) +{ + MakeNotifyPacket(data, CHAT_PLAYER_INVITED_NOTICE); + *data << name; +} + +// done 0x1E +void Channel::MakePlayerInviteBanned(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_PLAYER_INVITE_BANNED_NOTICE); + *data << uint64(guid); +} + +// done 0x1F +void Channel::MakeThrottled(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_THROTTLED_NOTICE); +} + +// done 0x20 +void Channel::MakeNotInArea(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_IN_AREA_NOTICE); +} + +// done 0x21 +void Channel::MakeNotInLfg(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_IN_LFG_NOTICE); +} + +// done 0x22 +void Channel::MakeVoiceOn(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_VOICE_ON_NOTICE); + *data << uint64(guid); +} + +// done 0x23 +void Channel::MakeVoiceOff(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_VOICE_OFF_NOTICE); + *data << uint64(guid); +} + +void Channel::JoinNotify(uint64 guid) +{ + WorldPacket data; + + if (IsConstant()) + data.Initialize(SMSG_USERLIST_ADD, 8+1+1+4+GetName().size()+1); + else + data.Initialize(SMSG_USERLIST_UPDATE, 8+1+1+4+GetName().size()+1); + + data << uint64(guid); + data << uint8(GetPlayerFlags(guid)); + data << uint8(GetFlags()); + data << uint32(GetNumPlayers()); + data << GetName(); + SendToAll(&data); +} + +void Channel::LeaveNotify(uint64 guid) +{ + WorldPacket data(SMSG_USERLIST_REMOVE, 8+1+4+GetName().size()+1); + data << uint64(guid); + data << uint8(GetFlags()); + data << uint32(GetNumPlayers()); + data << GetName(); + SendToAll(&data); +} + diff --git a/src/server/game/Chat/Channel.h b/src/server/game/Chat/Channel.h new file mode 100644 index 00000000000..d0b5923e30e --- /dev/null +++ b/src/server/game/Chat/Channel.h @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CHANNEL_H +#define _CHANNEL_H + +#include <list> +#include <map> +#include <string> + +#include "Common.h" + +#include "Opcodes.h" +#include "Player.h" +#include "WorldPacket.h" + +enum ChatNotify +{ + CHAT_JOINED_NOTICE = 0x00, //+ "%s joined channel."; + CHAT_LEFT_NOTICE = 0x01, //+ "%s left channel."; + //CHAT_SUSPENDED_NOTICE = 0x01, // "%s left channel."; + CHAT_YOU_JOINED_NOTICE = 0x02, //+ "Joined Channel: [%s]"; -- You joined + //CHAT_YOU_CHANGED_NOTICE = 0x02, // "Changed Channel: [%s]"; + CHAT_YOU_LEFT_NOTICE = 0x03, //+ "Left Channel: [%s]"; -- You left + CHAT_WRONG_PASSWORD_NOTICE = 0x04, //+ "Wrong password for %s."; + CHAT_NOT_MEMBER_NOTICE = 0x05, //+ "Not on channel %s."; + CHAT_NOT_MODERATOR_NOTICE = 0x06, //+ "Not a moderator of %s."; + CHAT_PASSWORD_CHANGED_NOTICE = 0x07, //+ "[%s] Password changed by %s."; + CHAT_OWNER_CHANGED_NOTICE = 0x08, //+ "[%s] Owner changed to %s."; + CHAT_PLAYER_NOT_FOUND_NOTICE = 0x09, //+ "[%s] Player %s was not found."; + CHAT_NOT_OWNER_NOTICE = 0x0A, //+ "[%s] You are not the channel owner."; + CHAT_CHANNEL_OWNER_NOTICE = 0x0B, //+ "[%s] Channel owner is %s."; + CHAT_MODE_CHANGE_NOTICE = 0x0C, //? + CHAT_ANNOUNCEMENTS_ON_NOTICE = 0x0D, //+ "[%s] Channel announcements enabled by %s."; + CHAT_ANNOUNCEMENTS_OFF_NOTICE = 0x0E, //+ "[%s] Channel announcements disabled by %s."; + CHAT_MODERATION_ON_NOTICE = 0x0F, //+ "[%s] Channel moderation enabled by %s."; + CHAT_MODERATION_OFF_NOTICE = 0x10, //+ "[%s] Channel moderation disabled by %s."; + CHAT_MUTED_NOTICE = 0x11, //+ "[%s] You do not have permission to speak."; + CHAT_PLAYER_KICKED_NOTICE = 0x12, //? "[%s] Player %s kicked by %s."; + CHAT_BANNED_NOTICE = 0x13, //+ "[%s] You are banned from that channel."; + CHAT_PLAYER_BANNED_NOTICE = 0x14, //? "[%s] Player %s banned by %s."; + CHAT_PLAYER_UNBANNED_NOTICE = 0x15, //? "[%s] Player %s unbanned by %s."; + CHAT_PLAYER_NOT_BANNED_NOTICE = 0x16, //+ "[%s] Player %s is not banned."; + CHAT_PLAYER_ALREADY_MEMBER_NOTICE = 0x17, //+ "[%s] Player %s is already on the channel."; + CHAT_INVITE_NOTICE = 0x18, //+ "%2$s has invited you to join the channel '%1$s'."; + CHAT_INVITE_WRONG_FACTION_NOTICE = 0x19, //+ "Target is in the wrong alliance for %s."; + CHAT_WRONG_FACTION_NOTICE = 0x1A, //+ "Wrong alliance for %s."; + CHAT_INVALID_NAME_NOTICE = 0x1B, //+ "Invalid channel name"; + CHAT_NOT_MODERATED_NOTICE = 0x1C, //+ "%s is not moderated"; + CHAT_PLAYER_INVITED_NOTICE = 0x1D, //+ "[%s] You invited %s to join the channel"; + CHAT_PLAYER_INVITE_BANNED_NOTICE = 0x1E, //+ "[%s] %s has been banned."; + CHAT_THROTTLED_NOTICE = 0x1F, //+ "[%s] The number of messages that can be sent to this channel is limited, please wait to send another message."; + CHAT_NOT_IN_AREA_NOTICE = 0x20, //+ "[%s] You are not in the correct area for this channel."; -- The user is trying to send a chat to a zone specific channel, and they're not physically in that zone. + CHAT_NOT_IN_LFG_NOTICE = 0x21, //+ "[%s] You must be queued in looking for group before joining this channel."; -- The user must be in the looking for group system to join LFG chat channels. + CHAT_VOICE_ON_NOTICE = 0x22, //+ "[%s] Channel voice enabled by %s."; + CHAT_VOICE_OFF_NOTICE = 0x23, //+ "[%s] Channel voice disabled by %s."; +}; + +enum ChannelFlags +{ + CHANNEL_FLAG_NONE = 0x00, + CHANNEL_FLAG_CUSTOM = 0x01, + // 0x02 + CHANNEL_FLAG_TRADE = 0x04, + CHANNEL_FLAG_NOT_LFG = 0x08, + CHANNEL_FLAG_GENERAL = 0x10, + CHANNEL_FLAG_CITY = 0x20, + CHANNEL_FLAG_LFG = 0x40, + CHANNEL_FLAG_VOICE = 0x80 + // General 0x18 = 0x10 | 0x08 + // Trade 0x3C = 0x20 | 0x10 | 0x08 | 0x04 + // LocalDefence 0x18 = 0x10 | 0x08 + // GuildRecruitment 0x38 = 0x20 | 0x10 | 0x08 + // LookingForGroup 0x50 = 0x40 | 0x10 +}; + +enum ChannelDBCFlags +{ + CHANNEL_DBC_FLAG_NONE = 0x00000, + CHANNEL_DBC_FLAG_INITIAL = 0x00001, // General, Trade, LocalDefense, LFG + CHANNEL_DBC_FLAG_ZONE_DEP = 0x00002, // General, Trade, LocalDefense, GuildRecruitment + CHANNEL_DBC_FLAG_GLOBAL = 0x00004, // WorldDefense + CHANNEL_DBC_FLAG_TRADE = 0x00008, // Trade + CHANNEL_DBC_FLAG_CITY_ONLY = 0x00010, // Trade, GuildRecruitment + CHANNEL_DBC_FLAG_CITY_ONLY2 = 0x00020, // Trade, GuildRecruitment + CHANNEL_DBC_FLAG_DEFENSE = 0x10000, // LocalDefense, WorldDefense + CHANNEL_DBC_FLAG_GUILD_REQ = 0x20000, // GuildRecruitment + CHANNEL_DBC_FLAG_LFG = 0x40000 // LookingForGroup +}; + +enum ChannelMemberFlags +{ + MEMBER_FLAG_NONE = 0x00, + MEMBER_FLAG_OWNER = 0x01, + MEMBER_FLAG_MODERATOR = 0x02, + MEMBER_FLAG_VOICED = 0x04, + MEMBER_FLAG_MUTED = 0x08, + MEMBER_FLAG_CUSTOM = 0x10, + MEMBER_FLAG_MIC_MUTED = 0x20, + // 0x40 + // 0x80 +}; + +class Channel +{ + struct PlayerInfo + { + uint64 player; + uint8 flags; + + bool HasFlag(uint8 flag) { return flags & flag; } + void SetFlag(uint8 flag) { if (!HasFlag(flag)) flags |= flag; } + bool IsOwner() { return flags & MEMBER_FLAG_OWNER; } + void SetOwner(bool state) + { + if (state) flags |= MEMBER_FLAG_OWNER; + else flags &= ~MEMBER_FLAG_OWNER; + } + bool IsModerator() { return flags & MEMBER_FLAG_MODERATOR; } + void SetModerator(bool state) + { + if (state) flags |= MEMBER_FLAG_MODERATOR; + else flags &= ~MEMBER_FLAG_MODERATOR; + } + bool IsMuted() { return flags & MEMBER_FLAG_MUTED; } + void SetMuted(bool state) + { + if (state) flags |= MEMBER_FLAG_MUTED; + else flags &= ~MEMBER_FLAG_MUTED; + } + }; + + typedef std::map<uint64, PlayerInfo> PlayerList; + PlayerList players; + typedef std::set<uint64> BannedList; + BannedList banned; + bool m_announce; + bool m_moderate; + bool m_public; + std::string m_name; + std::string m_password; + uint8 m_flags; + uint32 m_channelId; + uint64 m_ownerGUID; + bool m_IsSaved; + + private: + // initial packet data (notify type and channel name) + void MakeNotifyPacket(WorldPacket *data, uint8 notify_type); + // type specific packet data + void MakeJoined(WorldPacket *data, uint64 guid); //+ 0x00 + void MakeLeft(WorldPacket *data, uint64 guid); //+ 0x01 + void MakeYouJoined(WorldPacket *data); //+ 0x02 + void MakeYouLeft(WorldPacket *data); //+ 0x03 + void MakeWrongPassword(WorldPacket *data); //? 0x04 + void MakeNotMember(WorldPacket *data); //? 0x05 + void MakeNotModerator(WorldPacket *data); //? 0x06 + void MakePasswordChanged(WorldPacket *data, uint64 guid); //+ 0x07 + void MakeOwnerChanged(WorldPacket *data, uint64 guid); //? 0x08 + void MakePlayerNotFound(WorldPacket *data, const std::string& name); //+ 0x09 + void MakeNotOwner(WorldPacket *data); //? 0x0A + void MakeChannelOwner(WorldPacket *data); //? 0x0B + void MakeModeChange(WorldPacket *data, uint64 guid, uint8 oldflags); //+ 0x0C + void MakeAnnouncementsOn(WorldPacket *data, uint64 guid); //+ 0x0D + void MakeAnnouncementsOff(WorldPacket *data, uint64 guid); //+ 0x0E + void MakeModerationOn(WorldPacket *data, uint64 guid); //+ 0x0F + void MakeModerationOff(WorldPacket *data, uint64 guid); //+ 0x10 + void MakeMuted(WorldPacket *data); //? 0x11 + void MakePlayerKicked(WorldPacket *data, uint64 bad, uint64 good); //? 0x12 + void MakeBanned(WorldPacket *data); //? 0x13 + void MakePlayerBanned(WorldPacket *data, uint64 bad, uint64 good); //? 0x14 + void MakePlayerUnbanned(WorldPacket *data, uint64 bad, uint64 good); //? 0x15 + void MakePlayerNotBanned(WorldPacket *data, uint64 guid); //? 0x16 + void MakePlayerAlreadyMember(WorldPacket *data, uint64 guid); //+ 0x17 + void MakeInvite(WorldPacket *data, uint64 guid); //? 0x18 + void MakeInviteWrongFaction(WorldPacket *data); //? 0x19 + void MakeWrongFaction(WorldPacket *data); //? 0x1A + void MakeInvalidName(WorldPacket *data); //? 0x1B + void MakeNotModerated(WorldPacket *data); //? 0x1C + void MakePlayerInvited(WorldPacket *data, const std::string& name); //+ 0x1D + void MakePlayerInviteBanned(WorldPacket *data, uint64 guid); //? 0x1E + void MakeThrottled(WorldPacket *data); //? 0x1F + void MakeNotInArea(WorldPacket *data); //? 0x20 + void MakeNotInLfg(WorldPacket *data); //? 0x21 + void MakeVoiceOn(WorldPacket *data, uint64 guid); //+ 0x22 + void MakeVoiceOff(WorldPacket *data, uint64 guid); //+ 0x23 + + void SendToAll(WorldPacket *data, uint64 p = 0); + void SendToAllButOne(WorldPacket *data, uint64 who); + void SendToOne(WorldPacket *data, uint64 who); + + bool IsOn(uint64 who) const { return players.find(who) != players.end(); } + bool IsBanned(uint64 guid) const { return banned.find(guid) != banned.end(); } + + bool _UpdateStringInDB(const std::string& colName, const std::string& colValue) const; + bool _UpdateIntInDB(const std::string& colName, int colValue) const; + void _UpdateBanListInDB() const; + + uint8 GetPlayerFlags(uint64 p) const + { + PlayerList::const_iterator p_itr = players.find(p); + if (p_itr == players.end()) + return 0; + + return p_itr->second.flags; + } + + void SetModerator(uint64 p, bool set) + { + if (players[p].IsModerator() != set) + { + uint8 oldFlag = GetPlayerFlags(p); + players[p].SetModerator(set); + + WorldPacket data; + MakeModeChange(&data, p, oldFlag); + SendToAll(&data); + } + } + + void SetMute(uint64 p, bool set) + { + if (players[p].IsMuted() != set) + { + uint8 oldFlag = GetPlayerFlags(p); + players[p].SetMuted(set); + + WorldPacket data; + MakeModeChange(&data, p, oldFlag); + SendToAll(&data); + } + } + + public: + uint32 m_Team; + Channel(const std::string& name, uint32 channel_id, uint32 Team = 0); + std::string GetName() const { return m_name; } + uint32 GetChannelId() const { return m_channelId; } + bool IsConstant() const { return m_channelId != 0; } + bool IsAnnounce() const { return m_announce; } + bool IsLFG() const { return GetFlags() & CHANNEL_FLAG_LFG; } + std::string GetPassword() const { return m_password; } + void SetPassword(const std::string& npassword) { m_password = npassword; } + void SetAnnounce(bool nannounce) { m_announce = nannounce; } + uint32 GetNumPlayers() const { return players.size(); } + uint8 GetFlags() const { return m_flags; } + bool HasFlag(uint8 flag) { return m_flags & flag; } + + void Join(uint64 p, const char *pass); + void Leave(uint64 p, bool send = true); + void KickOrBan(uint64 good, const char *badname, bool ban); + void Kick(uint64 good, const char *badname) { KickOrBan(good, badname, false); } + void Ban(uint64 good, const char *badname) { KickOrBan(good, badname, true); } + void UnBan(uint64 good, const char *badname); + void Password(uint64 p, const char *pass); + void SetMode(uint64 p, const char *p2n, bool mod, bool set); + void SetOwner(uint64 p, bool exclaim = true); + void SetOwner(uint64 p, const char *newname); + void SendWhoOwner(uint64 p); + void SetModerator(uint64 p, const char *newname) { SetMode(p, newname, true, true); } + void UnsetModerator(uint64 p, const char *newname) { SetMode(p, newname, true, false); } + void SetMute(uint64 p, const char *newname) { SetMode(p, newname, false, true); } + void UnsetMute(uint64 p, const char *newname) { SetMode(p, newname, false, false); } + void List(Player* p); + void Announce(uint64 p); + void Moderate(uint64 p); + void Say(uint64 p, const char *what, uint32 lang); + void Invite(uint64 p, const char *newp); + void Voice(uint64 guid1, uint64 guid2); + void DeVoice(uint64 guid1, uint64 guid2); + void JoinNotify(uint64 guid); // invisible notify + void LeaveNotify(uint64 guid); // invisible notify +}; +#endif + diff --git a/src/server/game/Chat/ChannelHandler.cpp b/src/server/game/Chat/ChannelHandler.cpp new file mode 100644 index 00000000000..0f615579cb6 --- /dev/null +++ b/src/server/game/Chat/ChannelHandler.cpp @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Policies/SingletonImp.h" + +#include "ObjectMgr.h" // for normalizePlayerName +#include "ChannelMgr.h" + +void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + + uint32 channel_id; + uint8 unknown1, unknown2; + std::string channelname, pass; + + recvPacket >> channel_id >> unknown1 >> unknown2; + recvPacket >> channelname; + + if (channelname.empty()) + return; + + recvPacket >> pass; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + { + cMgr->team = _player->GetTeam(); + if (Channel *chn = cMgr->GetJoinChannel(channelname, channel_id)) + chn->Join(_player->GetGUID(), pass.c_str()); + } +} + +void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + + uint32 unk; + std::string channelname; + recvPacket >> unk; // channel id? + recvPacket >> channelname; + + if (channelname.empty()) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + { + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Leave(_player->GetGUID(), true); + cMgr->LeftChannel(channelname); + } +} + +void WorldSession::HandleChannelList(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->List(_player); +} + +void WorldSession::HandleChannelPassword(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, pass; + recvPacket >> channelname; + + recvPacket >> pass; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Password(_player->GetGUID(), pass.c_str()); +} + +void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, newp; + recvPacket >> channelname; + + recvPacket >> newp; + + if (!normalizePlayerName(newp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->SetOwner(_player->GetGUID(), newp.c_str()); +} + +void WorldSession::HandleChannelOwner(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->SendWhoOwner(_player->GetGUID()); +} + +void WorldSession::HandleChannelModerator(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->SetModerator(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->UnsetModerator(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelMute(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->SetMute(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->UnsetMute(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelInvite(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Invite(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelKick(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Kick(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelBan(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Ban(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelUnban(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->UnBan(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelAnnouncements(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Announce(_player->GetGUID()); +} + +void WorldSession::HandleChannelModerate(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Moderate(_player->GetGUID()); +} + +void WorldSession::HandleChannelDisplayListQuery(WorldPacket &recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->List(_player); +} + +void WorldSession::HandleGetChannelMemberCount(WorldPacket &recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + { + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + { + WorldPacket data(SMSG_CHANNEL_MEMBER_COUNT, chn->GetName().size()+1+1+4); + data << chn->GetName(); + data << uint8(chn->GetFlags()); + data << uint32(chn->GetNumPlayers()); + SendPacket(&data); + } + } +} + +void WorldSession::HandleSetChannelWatch(WorldPacket &recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + /*if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->JoinNotify(_player->GetGUID());*/ +} + diff --git a/src/server/game/Chat/ChannelMgr.cpp b/src/server/game/Chat/ChannelMgr.cpp new file mode 100644 index 00000000000..f31d3ffde50 --- /dev/null +++ b/src/server/game/Chat/ChannelMgr.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ChannelMgr.h" +#include "Policies/SingletonImp.h" +#include "World.h" + +INSTANTIATE_SINGLETON_1(AllianceChannelMgr); +INSTANTIATE_SINGLETON_1(HordeChannelMgr); + +ChannelMgr* channelMgr(uint32 team) +{ + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + return &Trinity::Singleton<AllianceChannelMgr>::Instance(); // cross-faction + + if (team == ALLIANCE) + return &Trinity::Singleton<AllianceChannelMgr>::Instance(); + if (team == HORDE) + return &Trinity::Singleton<HordeChannelMgr>::Instance(); + + return NULL; +} + +ChannelMgr::~ChannelMgr() +{ + for (ChannelMap::iterator itr = channels.begin(); itr != channels.end(); ++itr) + delete itr->second; + + channels.clear(); +} + +Channel *ChannelMgr::GetJoinChannel(std::string name, uint32 channel_id) +{ + std::wstring wname; + Utf8toWStr(name,wname); + wstrToLower(wname); + + if (channels.find(wname) == channels.end()) + { + Channel *nchan = new Channel(name,channel_id, team); + channels[wname] = nchan; + return nchan; + } + + return channels[wname]; +} + +Channel *ChannelMgr::GetChannel(std::string name, Player *p, bool pkt) +{ + std::wstring wname; + Utf8toWStr(name,wname); + wstrToLower(wname); + + ChannelMap::const_iterator i = channels.find(wname); + + if (i == channels.end()) + { + if (pkt) + { + WorldPacket data; + MakeNotOnPacket(&data,name); + p->GetSession()->SendPacket(&data); + } + + return NULL; + } + else + return i->second; +} + +void ChannelMgr::LeftChannel(std::string name) +{ + std::wstring wname; + Utf8toWStr(name,wname); + wstrToLower(wname); + + ChannelMap::const_iterator i = channels.find(wname); + + if (i == channels.end()) + return; + + Channel* channel = i->second; + + if (channel->GetNumPlayers() == 0 && !channel->IsConstant()) + { + channels.erase(wname); + delete channel; + } +} + +void ChannelMgr::MakeNotOnPacket(WorldPacket *data, std::string name) +{ + data->Initialize(SMSG_CHANNEL_NOTIFY, (1+10)); // we guess size + (*data) << (uint8)0x05 << name; +} diff --git a/src/server/game/Chat/ChannelMgr.h b/src/server/game/Chat/ChannelMgr.h new file mode 100644 index 00000000000..6f3b7c415ae --- /dev/null +++ b/src/server/game/Chat/ChannelMgr.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __TRINITY_CHANNELMGR_H +#define __TRINITY_CHANNELMGR_H + +#include "Common.h" +#include "Channel.h" +#include "Policies/Singleton.h" + +#include <map> +#include <string> + +#include "Policies/Singleton.h" + +#include "Channel.h" +#include "World.h" + +class ChannelMgr +{ + public: + uint32 team; + typedef std::map<std::wstring,Channel*> ChannelMap; + ChannelMgr() {team = 0;} + ~ChannelMgr(); + + Channel *GetJoinChannel(std::string name, uint32 channel_id); + Channel *GetChannel(std::string name, Player *p, bool pkt = true); + void LeftChannel(std::string name); + private: + ChannelMap channels; + void MakeNotOnPacket(WorldPacket *data, std::string name); +}; + +class AllianceChannelMgr : public ChannelMgr {}; +class HordeChannelMgr : public ChannelMgr {}; + +ChannelMgr* channelMgr(uint32 team); + +#endif + diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp new file mode 100644 index 00000000000..6e1adffa625 --- /dev/null +++ b/src/server/game/Chat/Chat.cpp @@ -0,0 +1,2458 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "ObjectMgr.h" +#include "World.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Database/DatabaseEnv.h" + +#include "AccountMgr.h" +#include "CellImpl.h" +#include "Chat.h" +#include "GridNotifiersImpl.h" +#include "Language.h" +#include "Log.h" +#include "Opcodes.h" +#include "Player.h" +#include "UpdateMask.h" +#include "SpellMgr.h" + +// Supported shift-links (client generated and server side) +// |color|Hachievement:achievement_id:player_guid:0:0:0:0:0:0:0:0|h[name]|h|r +// - client, item icon shift click, not used in server currently +// |color|Harea:area_id|h[name]|h|r +// |color|Hcreature:creature_guid|h[name]|h|r +// |color|Hcreature_entry:creature_id|h[name]|h|r +// |color|Henchant:recipe_spell_id|h[prof_name: recipe_name]|h|r - client, at shift click in recipes list dialog +// |color|Hgameevent:id|h[name]|h|r +// |color|Hgameobject:go_guid|h[name]|h|r +// |color|Hgameobject_entry:go_id|h[name]|h|r +// |color|Hglyph:glyph_slot_id:glyph_prop_id|h[%s]|h|r - client, at shift click in glyphs dialog, GlyphSlot.dbc, GlyphProperties.dbc +// |color|Hitem:item_id:perm_ench_id:gem1:gem2:gem3:0:0:0:0:reporter_level|h[name]|h|r +// - client, item icon shift click +// |color|Hitemset:itemset_id|h[name]|h|r +// |color|Hplayer:name|h[name]|h|r - client, in some messages, at click copy only name instead link +// |color|Hquest:quest_id:quest_level|h[name]|h|r - client, quest list name shift-click +// |color|Hskill:skill_id|h[name]|h|r +// |color|Hspell:spell_id|h[name]|h|r - client, spellbook spell icon shift-click +// |color|Htalent:talent_id,rank|h[name]|h|r - client, talent icon shift-click +// |color|Htaxinode:id|h[name]|h|r +// |color|Htele:id|h[name]|h|r +// |color|Htitle:id|h[name]|h|r +// |color|Htrade:spell_id,cur_value,max_value,unk3int,unk3str|h[name]|h|r - client, spellbook profession icon shift-click + +bool ChatHandler::load_command_table = true; + +ChatCommand * ChatHandler::getCommandTable() +{ + static ChatCommand accountSetCommandTable[] = + { + { "addon", SEC_ADMINISTRATOR, true, &ChatHandler::HandleAccountSetAddonCommand, "", NULL }, + { "gmlevel", SEC_CONSOLE, true, &ChatHandler::HandleAccountSetGmLevelCommand, "", NULL }, + { "password", SEC_CONSOLE, true, &ChatHandler::HandleAccountSetPasswordCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand accountCommandTable[] = + { + { "addon", SEC_MODERATOR, false, &ChatHandler::HandleAccountAddonCommand, "", NULL }, + { "create", SEC_CONSOLE, true, &ChatHandler::HandleAccountCreateCommand, "", NULL }, + { "delete", SEC_CONSOLE, true, &ChatHandler::HandleAccountDeleteCommand, "", NULL }, + { "onlinelist", SEC_CONSOLE, true, &ChatHandler::HandleAccountOnlineListCommand, "", NULL }, + { "lock", SEC_PLAYER, false, &ChatHandler::HandleAccountLockCommand, "", NULL }, + { "set", SEC_ADMINISTRATOR, true, NULL, "", accountSetCommandTable }, + { "password", SEC_PLAYER, false, &ChatHandler::HandleAccountPasswordCommand, "", NULL }, + { "", SEC_PLAYER, false, &ChatHandler::HandleAccountCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand banCommandTable[] = + { + { "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanAccountCommand, "", NULL }, + { "character", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanCharacterCommand, "", NULL }, + { "ip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanIPCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand baninfoCommandTable[] = + { + { "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanInfoAccountCommand, "", NULL }, + { "character", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanInfoCharacterCommand, "", NULL }, + { "ip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanInfoIPCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand banlistCommandTable[] = + { + { "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanListAccountCommand, "", NULL }, + { "character", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanListCharacterCommand, "", NULL }, + { "ip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanListIPCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand castCommandTable[] = + { + { "back", SEC_ADMINISTRATOR, false, &ChatHandler::HandleCastBackCommand, "", NULL }, + { "dist", SEC_ADMINISTRATOR, false, &ChatHandler::HandleCastDistCommand, "", NULL }, + { "self", SEC_ADMINISTRATOR, false, &ChatHandler::HandleCastSelfCommand, "", NULL }, + { "target", SEC_ADMINISTRATOR, false, &ChatHandler::HandleCastTargetCommand, "", NULL }, + { "", SEC_ADMINISTRATOR, false, &ChatHandler::HandleCastCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand characterCommandTable[] = + { + { "customize", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterCustomizeCommand, "", NULL }, + { "delete", SEC_CONSOLE, true, &ChatHandler::HandleCharacterDeleteCommand, "", NULL }, + { "level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleCharacterLevelCommand, "", NULL }, + { "rename", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterRenameCommand, "", NULL }, + { "reputation", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterReputationCommand, "", NULL }, + { "titles", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterTitlesCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand channelSetCommandTable[] = + { + { "public", SEC_ADMINISTRATOR, true, &ChatHandler::HandleChannelSetPublic, "", NULL }, + }; + + static ChatCommand channelCommandTable[] = + { + { "set", SEC_ADMINISTRATOR, true, NULL, "", channelSetCommandTable }, + }; + + static ChatCommand debugPlayCommandTable[] = + { + { "cinematic", SEC_MODERATOR, false, &ChatHandler::HandleDebugPlayCinematicCommand, "", NULL }, + { "movie", SEC_MODERATOR, false, &ChatHandler::HandleDebugPlayMovieCommand, "", NULL }, + { "sound", SEC_MODERATOR, false, &ChatHandler::HandleDebugPlaySoundCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand debugSendCommandTable[] = + { + { "buyerror", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendBuyErrorCommand, "", NULL }, + { "channelnotify", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendChannelNotifyCommand, "", NULL }, + { "chatmmessage", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendChatMsgCommand, "", NULL }, + { "equiperror", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendEquipErrorCommand, "", NULL }, + { "largepacket", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendLargePacketCommand, "", NULL }, + { "opcode", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendOpcodeCommand, "", NULL }, + { "poi", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendPoiCommand, "", NULL }, + { "qpartymsg", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendQuestPartyMsgCommand, "", NULL }, + { "qinvalidmsg", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendQuestInvalidMsgCommand, "", NULL }, + { "sellerror", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendSellErrorCommand, "", NULL }, + { "setphaseshift", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendSetPhaseShiftCommand, "", NULL }, + { "spellfail", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendSpellFailCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand debugCommandTable[] = + { + { "setbit", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSet32Bit, "", NULL }, + { "threat", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugThreatList, "", NULL }, + { "hostil", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugHostileRefList, "", NULL }, + { "anim", SEC_GAMEMASTER, false, &ChatHandler::HandleDebugAnimCommand, "", NULL }, + { "arena", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugArenaCommand, "", NULL }, + { "bg", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugBattlegroundCommand, "", NULL }, + { "getitemstate", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetItemStateCommand, "", NULL }, + { "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleDebugGetLootRecipientCommand, "", NULL }, + { "getvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetValueCommand, "", NULL }, + { "getitemvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetItemValueCommand, "", NULL }, + { "Mod32Value", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugMod32ValueCommand, "", NULL }, + { "play", SEC_MODERATOR, false, NULL, "", debugPlayCommandTable }, + { "send", SEC_ADMINISTRATOR, false, NULL, "", debugSendCommandTable }, + { "setaurastate", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetAuraStateCommand, "", NULL }, + { "setitemvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetItemValueCommand, "", NULL }, + { "setvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetValueCommand, "", NULL }, + { "spawnvehicle", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSpawnVehicle, "", NULL }, + { "setvid", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetVehicleId, "", NULL }, + { "entervehicle", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugEnterVehicle, "", NULL }, + { "uws", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugUpdateWorldStateCommand, "", NULL }, + { "update", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugUpdateCommand, "", NULL }, + { "itemexpire", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugItemExpireCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand eventCommandTable[] = + { + { "activelist", SEC_GAMEMASTER, true, &ChatHandler::HandleEventActiveListCommand, "", NULL }, + { "start", SEC_GAMEMASTER, true, &ChatHandler::HandleEventStartCommand, "", NULL }, + { "stop", SEC_GAMEMASTER, true, &ChatHandler::HandleEventStopCommand, "", NULL }, + { "", SEC_GAMEMASTER, true, &ChatHandler::HandleEventInfoCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand gmCommandTable[] = + { + { "chat", SEC_MODERATOR, false, &ChatHandler::HandleGMChatCommand, "", NULL }, + { "fly", SEC_ADMINISTRATOR, false, &ChatHandler::HandleGMFlyCommand, "", NULL }, + { "ingame", SEC_PLAYER, true, &ChatHandler::HandleGMListIngameCommand, "", NULL }, + { "list", SEC_ADMINISTRATOR, true, &ChatHandler::HandleGMListFullCommand, "", NULL }, + { "visible", SEC_MODERATOR, false, &ChatHandler::HandleGMVisibleCommand, "", NULL }, + { "", SEC_MODERATOR, false, &ChatHandler::HandleGMCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand goCommandTable[] = + { + { "creature", SEC_MODERATOR, false, &ChatHandler::HandleGoCreatureCommand, "", NULL }, + { "graveyard", SEC_MODERATOR, false, &ChatHandler::HandleGoGraveyardCommand, "", NULL }, + { "grid", SEC_MODERATOR, false, &ChatHandler::HandleGoGridCommand, "", NULL }, + { "object", SEC_MODERATOR, false, &ChatHandler::HandleGoObjectCommand, "", NULL }, + { "taxinode", SEC_MODERATOR, false, &ChatHandler::HandleGoTaxinodeCommand, "", NULL }, + { "trigger", SEC_MODERATOR, false, &ChatHandler::HandleGoTriggerCommand, "", NULL }, + { "zonexy", SEC_MODERATOR, false, &ChatHandler::HandleGoZoneXYCommand, "", NULL }, + { "xy", SEC_MODERATOR, false, &ChatHandler::HandleGoXYCommand, "", NULL }, + { "xyz", SEC_MODERATOR, false, &ChatHandler::HandleGoXYZCommand, "", NULL }, + { "ticket", SEC_MODERATOR, false, &ChatHandler::HandleGoTicketCommand, "", NULL }, + { "", SEC_MODERATOR, false, &ChatHandler::HandleGoXYZCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand gobjectCommandTable[] = + { + { "activate", SEC_GAMEMASTER, false, &ChatHandler::HandleActivateObjectCommand, "", NULL }, + { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectAddCommand, "", NULL }, + { "delete", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectDeleteCommand, "", NULL }, + { "info", SEC_GAMEMASTER, false, &ChatHandler::HandleGOInfoCommand, "", NULL }, + { "move", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectMoveCommand, "", NULL }, + { "near", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectNearCommand, "", NULL }, + { "state", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectStateCommand, "", NULL }, + { "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectPhaseCommand, "", NULL }, + { "target", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectTargetCommand, "", NULL }, + { "tempadd", SEC_GAMEMASTER, false, &ChatHandler::HandleTempGameObjectCommand, "", NULL }, + { "turn", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectTurnCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand groupCommandTable[] = + { + { "leader", SEC_ADMINISTRATOR, false, &ChatHandler::HandleGroupLeaderCommand, "", NULL }, + { "disband", SEC_ADMINISTRATOR, false, &ChatHandler::HandleGroupDisbandCommand, "", NULL }, + { "remove", SEC_ADMINISTRATOR, false, &ChatHandler::HandleGroupRemoveCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand guildCommandTable[] = + { + { "create", SEC_GAMEMASTER, true, &ChatHandler::HandleGuildCreateCommand, "", NULL }, + { "delete", SEC_GAMEMASTER, true, &ChatHandler::HandleGuildDeleteCommand, "", NULL }, + { "invite", SEC_GAMEMASTER, true, &ChatHandler::HandleGuildInviteCommand, "", NULL }, + { "uninvite", SEC_GAMEMASTER, true, &ChatHandler::HandleGuildUninviteCommand, "", NULL }, + { "rank", SEC_GAMEMASTER, true, &ChatHandler::HandleGuildRankCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand honorCommandTable[] = + { + { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleHonorAddCommand, "", NULL }, + { "addkill", SEC_GAMEMASTER, false, &ChatHandler::HandleHonorAddKillCommand, "", NULL }, + { "update", SEC_GAMEMASTER, false, &ChatHandler::HandleHonorUpdateCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand instanceCommandTable[] = + { + { "listbinds", SEC_ADMINISTRATOR, false, &ChatHandler::HandleInstanceListBindsCommand, "", NULL }, + { "unbind", SEC_ADMINISTRATOR, false, &ChatHandler::HandleInstanceUnbindCommand, "", NULL }, + { "stats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleInstanceStatsCommand, "", NULL }, + { "savedata", SEC_ADMINISTRATOR, false, &ChatHandler::HandleInstanceSaveDataCommand, "", NULL }, + { "open", SEC_ADMINISTRATOR, true, &ChatHandler::HandleInstanceOpenCommand, "", NULL }, + { "close", SEC_ADMINISTRATOR, true, &ChatHandler::HandleInstanceCloseCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand learnCommandTable[] = + { + { "all", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllCommand, "", NULL }, + { "all_gm", SEC_GAMEMASTER, false, &ChatHandler::HandleLearnAllGMCommand, "", NULL }, + { "all_crafts", SEC_GAMEMASTER, false, &ChatHandler::HandleLearnAllCraftsCommand, "", NULL }, + { "all_default", SEC_MODERATOR, false, &ChatHandler::HandleLearnAllDefaultCommand, "", NULL }, + { "all_lang", SEC_MODERATOR, false, &ChatHandler::HandleLearnAllLangCommand, "", NULL }, + { "all_myclass", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllMyClassCommand, "", NULL }, + { "all_mypettalents",SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllMyPetTalentsCommand,"", NULL }, + { "all_myspells", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllMySpellsCommand, "", NULL }, + { "all_mytalents", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllMyTalentsCommand, "", NULL }, + { "all_recipes", SEC_GAMEMASTER, false, &ChatHandler::HandleLearnAllRecipesCommand, "", NULL }, + { "", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand listCommandTable[] = + { + { "creature", SEC_ADMINISTRATOR, true, &ChatHandler::HandleListCreatureCommand, "", NULL }, + { "item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleListItemCommand, "", NULL }, + { "object", SEC_ADMINISTRATOR, true, &ChatHandler::HandleListObjectCommand, "", NULL }, + { "auras", SEC_ADMINISTRATOR, false, &ChatHandler::HandleListAurasCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand lookupPlayerCommandTable[] = + { + { "ip", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupPlayerIpCommand, "", NULL }, + { "account", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupPlayerAccountCommand, "", NULL }, + { "email", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupPlayerEmailCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand lookupCommandTable[] = + { + { "area", SEC_MODERATOR, true, &ChatHandler::HandleLookupAreaCommand, "", NULL }, + { "creature", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupCreatureCommand, "", NULL }, + { "event", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupEventCommand, "", NULL }, + { "faction", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupFactionCommand, "", NULL }, + { "item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupItemCommand, "", NULL }, + { "itemset", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupItemSetCommand, "", NULL }, + { "object", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupObjectCommand, "", NULL }, + { "quest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupQuestCommand, "", NULL }, + { "player", SEC_GAMEMASTER, true, NULL, "", lookupPlayerCommandTable }, + { "skill", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupSkillCommand, "", NULL }, + { "spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupSpellCommand, "", NULL }, + { "taxinode", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupTaxiNodeCommand, "", NULL }, + { "tele", SEC_MODERATOR, true, &ChatHandler::HandleLookupTeleCommand, "", NULL }, + { "title", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupTitleCommand, "", NULL }, + { "map", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupMapCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand modifyCommandTable[] = + { + { "hp", SEC_MODERATOR, false, &ChatHandler::HandleModifyHPCommand, "", NULL }, + { "mana", SEC_MODERATOR, false, &ChatHandler::HandleModifyManaCommand, "", NULL }, + { "rage", SEC_MODERATOR, false, &ChatHandler::HandleModifyRageCommand, "", NULL }, + { "runicpower", SEC_MODERATOR, false, &ChatHandler::HandleModifyRunicPowerCommand, "", NULL }, + { "energy", SEC_MODERATOR, false, &ChatHandler::HandleModifyEnergyCommand, "", NULL }, + { "money", SEC_MODERATOR, false, &ChatHandler::HandleModifyMoneyCommand, "", NULL }, + { "speed", SEC_MODERATOR, false, &ChatHandler::HandleModifySpeedCommand, "", NULL }, + { "swim", SEC_MODERATOR, false, &ChatHandler::HandleModifySwimCommand, "", NULL }, + { "scale", SEC_MODERATOR, false, &ChatHandler::HandleModifyScaleCommand, "", NULL }, + { "bit", SEC_MODERATOR, false, &ChatHandler::HandleModifyBitCommand, "", NULL }, + { "bwalk", SEC_MODERATOR, false, &ChatHandler::HandleModifyBWalkCommand, "", NULL }, + { "fly", SEC_MODERATOR, false, &ChatHandler::HandleModifyFlyCommand, "", NULL }, + { "aspeed", SEC_MODERATOR, false, &ChatHandler::HandleModifyASpeedCommand, "", NULL }, + { "faction", SEC_MODERATOR, false, &ChatHandler::HandleModifyFactionCommand, "", NULL }, + { "spell", SEC_MODERATOR, false, &ChatHandler::HandleModifySpellCommand, "", NULL }, + { "tp", SEC_MODERATOR, false, &ChatHandler::HandleModifyTalentCommand, "", NULL }, + { "mount", SEC_MODERATOR, false, &ChatHandler::HandleModifyMountCommand, "", NULL }, + { "honor", SEC_MODERATOR, false, &ChatHandler::HandleModifyHonorCommand, "", NULL }, + { "rep", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyRepCommand, "", NULL }, + { "arena", SEC_MODERATOR, false, &ChatHandler::HandleModifyArenaCommand, "", NULL }, + { "drunk", SEC_MODERATOR, false, &ChatHandler::HandleModifyDrunkCommand, "", NULL }, + { "standstate", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyStandStateCommand, "", NULL }, + { "morph", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyMorphCommand, "", NULL }, + { "phase", SEC_ADMINISTRATOR, false, &ChatHandler::HandleModifyPhaseCommand, "", NULL }, + { "gender", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyGenderCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand npcCommandTable[] = + { + { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddCommand, "", NULL }, + { "additem", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddVendorItemCommand, "", NULL }, + { "addmove", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddMoveCommand, "", NULL }, + { "allowmove", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcAllowMovementCommand, "", NULL }, + { "changeentry", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcChangeEntryCommand, "", NULL }, + { "changelevel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcChangeLevelCommand, "", NULL }, + { "delete", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcDeleteCommand, "", NULL }, + { "delitem", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcDelVendorItemCommand, "", NULL }, + { "factionid", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFactionIdCommand, "", NULL }, + { "flag", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFlagCommand, "", NULL }, + { "follow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFollowCommand, "", NULL }, + { "info", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcInfoCommand, "", NULL }, + { "move", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcMoveCommand, "", NULL }, + { "playemote", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcPlayEmoteCommand, "", NULL }, + { "setmodel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetModelCommand, "", NULL }, + { "setmovetype", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetMoveTypeCommand, "", NULL }, + { "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetPhaseCommand, "", NULL }, + { "spawndist", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSpawnDistCommand, "", NULL }, + { "spawntime", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSpawnTimeCommand, "", NULL }, + { "say", SEC_MODERATOR, false, &ChatHandler::HandleNpcSayCommand, "", NULL }, + { "textemote", SEC_MODERATOR, false, &ChatHandler::HandleNpcTextEmoteCommand, "", NULL }, + { "unfollow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcUnFollowCommand, "", NULL }, + { "whisper", SEC_MODERATOR, false, &ChatHandler::HandleNpcWhisperCommand, "", NULL }, + { "yell", SEC_MODERATOR, false, &ChatHandler::HandleNpcYellCommand, "", NULL }, + { "tempadd", SEC_GAMEMASTER, false, &ChatHandler::HandleTempAddSpwCommand, "", NULL }, + { "tame", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcTameCommand, "", NULL }, + { "setdeathstate", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetDeathStateCommand, "", NULL }, + { "addformation", SEC_MODERATOR, false, &ChatHandler::HandleNpcAddFormationCommand, "", NULL }, + { "setlink", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetLinkCommand, "", NULL }, + + //{ TODO: fix or remove this commands + { "addweapon", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcAddWeaponCommand, "", NULL }, + { "name", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcNameCommand, "", NULL }, + { "subname", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSubNameCommand, "", NULL }, + //} + + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand petCommandTable[] = + { + { "create", SEC_GAMEMASTER, false, &ChatHandler::HandleCreatePetCommand, "", NULL }, + { "learn", SEC_GAMEMASTER, false, &ChatHandler::HandlePetLearnCommand, "", NULL }, + { "unlearn", SEC_GAMEMASTER, false, &ChatHandler::HandlePetUnlearnCommand, "", NULL }, + { "tp", SEC_GAMEMASTER, false, &ChatHandler::HandlePetTpCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand pdumpCommandTable[] = + { + { "load", SEC_ADMINISTRATOR, true, &ChatHandler::HandlePDumpLoadCommand, "", NULL }, + { "write", SEC_ADMINISTRATOR, true, &ChatHandler::HandlePDumpWriteCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand questCommandTable[] = + { + { "add", SEC_ADMINISTRATOR, false, &ChatHandler::HandleQuestAdd, "", NULL }, + { "complete", SEC_ADMINISTRATOR, false, &ChatHandler::HandleQuestComplete, "", NULL }, + { "remove", SEC_ADMINISTRATOR, false, &ChatHandler::HandleQuestRemove, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand reloadCommandTable[] = + { + { "all", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllCommand, "", NULL }, + { "all_achievement",SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllAchievementCommand,"", NULL }, + { "all_area", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllAreaCommand, "", NULL }, + { "all_eventai", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllEventAICommand, "", NULL }, + { "all_item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllItemCommand, "", NULL }, + { "all_locales", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllLocalesCommand, "", NULL }, + { "all_loot", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllLootCommand, "", NULL }, + { "all_npc", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllNpcCommand, "", NULL }, + { "all_quest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllQuestCommand, "", NULL }, + { "all_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllScriptsCommand, "", NULL }, + { "all_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllSpellCommand, "", NULL }, + + { "config", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadConfigCommand, "", NULL }, + + { "access_requirement", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAccessRequirementCommand, "", NULL }, + { "achievement_criteria_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAchievementCriteriaDataCommand, "", NULL }, + { "achievement_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAchievementRewardCommand, "", NULL }, + { "areatrigger_involvedrelation",SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestAreaTriggersCommand, "", NULL }, + { "areatrigger_tavern", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTavernCommand, "", NULL }, + { "areatrigger_teleport", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTeleportCommand, "", NULL }, + { "autobroadcast", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAutobroadcastCommand, "", NULL }, + { "command", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCommandCommand, "", NULL }, + { "conditions", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadConditions, "", NULL }, + { "creature_ai_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAIScriptsCommand, "", NULL }, + { "creature_ai_summons", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAISummonsCommand, "", NULL }, + { "creature_ai_texts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAITextsCommand, "", NULL }, + { "creature_involvedrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestInvRelationsCommand,"",NULL }, + { "creature_linked_respawn", SEC_GAMEMASTER, true, &ChatHandler::HandleReloadCreatureLinkedRespawnCommand, "", NULL }, + { "creature_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesCreatureCommand, "", NULL }, + { "creature_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestRelationsCommand, "", NULL }, + { "creature_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureTemplateCommand, "", NULL }, + //{ "db_script_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDbScriptStringCommand, "", NULL }, + { "disenchant_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesDisenchantCommand, "", NULL }, + { "event_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventScriptsCommand, "", NULL }, + { "fishing_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesFishingCommand, "", NULL }, + { "game_graveyard_zone", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameGraveyardZoneCommand, "", NULL }, + { "game_tele", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameTeleCommand, "", NULL }, + { "gameobject_involvedrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGOQuestInvRelationsCommand, "", NULL }, + { "gameobject_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesGameobjectCommand, "", NULL }, + { "gameobject_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGOQuestRelationsCommand, "", NULL }, + { "gameobject_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameObjectScriptsCommand, "", NULL }, + { "gossip_menu", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL }, + { "gossip_menu_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuOptionCommand, "", NULL }, + { "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL }, + { "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL }, + { "locales_achievement_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesAchievementRewardCommand,"", NULL }, + { "locales_creature", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesCreatureCommand, "", NULL }, + { "locales_gameobject", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesGameobjectCommand, "", NULL }, + { "locales_item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesItemCommand, "", NULL }, + { "locales_npc_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesNpcTextCommand, "", NULL }, + { "locales_page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesPageTextCommand, "", NULL }, + { "locales_points_of_interest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesPointsOfInterestCommand, "", NULL }, + { "locales_quest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesQuestCommand, "", NULL }, +// { "auctions", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAuctionsCommand, "", NULL }, + { "mail_level_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadMailLevelRewardCommand, "", NULL }, + { "mail_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMailCommand, "", NULL }, + { "milling_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMillingCommand, "", NULL }, + { "npc_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcGossipCommand, "", NULL }, + { "npc_spellclick_spells", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellClickSpellsCommand, "",NULL}, + { "npc_trainer", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcTrainerCommand, "", NULL }, + { "npc_vendor", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcVendorCommand, "", NULL }, + { "page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPageTextsCommand, "", NULL }, + { "pickpocketing_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesPickpocketingCommand,"",NULL}, + { "points_of_interest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPointsOfInterestCommand, "",NULL}, + { "prospecting_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesProspectingCommand,"", NULL }, + { "quest_end_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestEndScriptsCommand, "", NULL }, + { "quest_start_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestStartScriptsCommand, "", NULL }, + { "quest_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestTemplateCommand, "", NULL }, + { "reference_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesReferenceCommand, "", NULL }, + { "reserved_name", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadReservedNameCommand, "", NULL }, + { "skill_discovery_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSkillDiscoveryTemplateCommand, "", NULL }, + { "skill_extra_item_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSkillExtraItemTemplateCommand, "", NULL }, + { "skill_fishing_base_level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSkillFishingBaseLevelCommand, "", NULL }, + { "skinning_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSkinningCommand, "", NULL }, + { "spell_required", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellRequiredCommand, "", NULL }, + { "spell_area", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellAreaCommand, "", NULL }, + { "spell_bonus_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellBonusesCommand, "", NULL }, + { "spell_group", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellGroupsCommand, "", NULL }, + { "spell_learn_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL }, + { "spell_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSpellCommand, "", NULL }, + { "spell_linked_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLinkedSpellCommand, "", NULL }, + { "spell_pet_auras", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellPetAurasCommand, "", NULL }, + { "spell_proc_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellProcEventCommand, "", NULL }, + { "spell_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptsCommand, "", NULL }, + { "spell_target_position", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL }, + { "spell_threats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellThreatsCommand, "", NULL }, + { "spell_disabled", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellDisabledCommand, "", NULL }, + { "spell_group_stack_rules", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellGroupStackRulesCommand, "", NULL }, + { "trinity_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadTrinityStringCommand, "", NULL }, + { "auctions", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAuctionsCommand, "", NULL }, + { "waypoint_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadWpScriptsCommand, "", NULL }, + { "gm_tickets", SEC_ADMINISTRATOR, true, &ChatHandler::HandleGMTicketReloadCommand, "", NULL }, + + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand resetCommandTable[] = + { + { "achievements", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetAchievementsCommand, "", NULL }, + { "honor", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetHonorCommand, "", NULL }, + { "level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetLevelCommand, "", NULL }, + { "spells", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetSpellsCommand, "", NULL }, + { "stats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetStatsCommand, "", NULL }, + { "talents", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetTalentsCommand, "", NULL }, + { "all", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetAllCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand sendCommandTable[] = + { + { "items", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendItemsCommand, "", NULL }, + { "mail", SEC_MODERATOR, true, &ChatHandler::HandleSendMailCommand, "", NULL }, + { "message", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMessageCommand, "", NULL }, + { "money", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMoneyCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverIdleRestartCommandTable[] = + { + { "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL }, + { "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerIdleRestartCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverIdleShutdownCommandTable[] = + { + { "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL }, + { "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerIdleShutDownCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverRestartCommandTable[] = + { + { "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL }, + { "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerRestartCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverShutdownCommandTable[] = + { + { "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL }, + { "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverSetCommandTable[] = + { + { "difftime", SEC_CONSOLE, true, &ChatHandler::HandleServerSetDiffTimeCommand, "", NULL }, + { "loglevel", SEC_CONSOLE, true, &ChatHandler::HandleServerSetLogLevelCommand, "", NULL }, + { "logfilelevel", SEC_CONSOLE, true, &ChatHandler::HandleServerSetLogFileLevelCommand, "", NULL }, + { "motd", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerSetMotdCommand, "", NULL }, + { "closed", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerSetClosedCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverCommandTable[] = + { + { "corpses", SEC_GAMEMASTER, true, &ChatHandler::HandleServerCorpsesCommand, "", NULL }, + { "exit", SEC_CONSOLE, true, &ChatHandler::HandleServerExitCommand, "", NULL }, + { "idlerestart", SEC_ADMINISTRATOR, true, NULL, "", serverIdleRestartCommandTable }, + { "idleshutdown", SEC_ADMINISTRATOR, true, NULL, "", serverShutdownCommandTable }, + { "info", SEC_PLAYER, true, &ChatHandler::HandleServerInfoCommand, "", NULL }, + { "motd", SEC_PLAYER, true, &ChatHandler::HandleServerMotdCommand, "", NULL }, + { "plimit", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerPLimitCommand, "", NULL }, + { "restart", SEC_ADMINISTRATOR, true, NULL, "", serverRestartCommandTable }, + { "shutdown", SEC_ADMINISTRATOR, true, NULL, "", serverShutdownCommandTable }, + { "set", SEC_ADMINISTRATOR, true, NULL, "", serverSetCommandTable }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand teleCommandTable[] = + { + { "add", SEC_ADMINISTRATOR, false, &ChatHandler::HandleTeleAddCommand, "", NULL }, + { "del", SEC_ADMINISTRATOR, true, &ChatHandler::HandleTeleDelCommand, "", NULL }, + { "name", SEC_MODERATOR, true, &ChatHandler::HandleTeleNameCommand, "", NULL }, + { "group", SEC_MODERATOR, false, &ChatHandler::HandleTeleGroupCommand, "", NULL }, + { "", SEC_MODERATOR, false, &ChatHandler::HandleTeleCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand titlesCommandTable[] = + { + { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleTitlesAddCommand, "", NULL }, + { "current", SEC_GAMEMASTER, false, &ChatHandler::HandleTitlesCurrentCommand, "", NULL }, + { "remove", SEC_GAMEMASTER, false, &ChatHandler::HandleTitlesRemoveCommand, "", NULL }, + { "setmask", SEC_GAMEMASTER, false, &ChatHandler::HandleTitlesSetMaskCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand unbanCommandTable[] = + { + { "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanAccountCommand, "", NULL }, + { "character", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanCharacterCommand, "", NULL }, + { "ip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanIPCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand wpCommandTable[] = + { + { "show", SEC_GAMEMASTER, false, &ChatHandler::HandleWpShowCommand, "", NULL }, + { "addwp", SEC_GAMEMASTER, false, &ChatHandler::HandleWpAddCommand, "", NULL }, + { "load", SEC_GAMEMASTER, false, &ChatHandler::HandleWpLoadPathCommand, "", NULL }, + { "modify", SEC_GAMEMASTER, false, &ChatHandler::HandleWpModifyCommand, "", NULL }, + { "event", SEC_GAMEMASTER, false, &ChatHandler::HandleWpEventCommand, "", NULL }, + { "unload", SEC_GAMEMASTER, false, &ChatHandler::HandleWpUnLoadPathCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand ticketCommandTable[] = + { + { "list", SEC_MODERATOR, false, &ChatHandler::HandleGMTicketListCommand, "", NULL }, + { "onlinelist", SEC_MODERATOR, false, &ChatHandler::HandleGMTicketListOnlineCommand, "", NULL }, + { "viewname", SEC_MODERATOR, false, &ChatHandler::HandleGMTicketGetByNameCommand, "", NULL }, + { "viewid", SEC_MODERATOR, false, &ChatHandler::HandleGMTicketGetByIdCommand, "", NULL }, + { "close", SEC_MODERATOR, false, &ChatHandler::HandleGMTicketCloseByIdCommand, "", NULL }, + { "closedlist", SEC_MODERATOR, false, &ChatHandler::HandleGMTicketListClosedCommand, "", NULL }, + { "delete", SEC_ADMINISTRATOR, false, &ChatHandler::HandleGMTicketDeleteByIdCommand, "", NULL }, + { "assign", SEC_MODERATOR, false, &ChatHandler::HandleGMTicketAssignToCommand, "", NULL }, + { "unassign", SEC_MODERATOR, false, &ChatHandler::HandleGMTicketUnAssignCommand, "", NULL }, + { "comment", SEC_MODERATOR, false, &ChatHandler::HandleGMTicketCommentCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand commandTable[] = + { + { "account", SEC_PLAYER, true, NULL, "", accountCommandTable }, + { "gm", SEC_MODERATOR, true, NULL, "", gmCommandTable }, + { "npc", SEC_MODERATOR, false, NULL, "", npcCommandTable }, + { "go", SEC_MODERATOR, false, NULL, "", goCommandTable }, + { "learn", SEC_MODERATOR, false, NULL, "", learnCommandTable }, + { "modify", SEC_MODERATOR, false, NULL, "", modifyCommandTable }, + { "debug", SEC_MODERATOR, true, NULL, "", debugCommandTable }, + { "tele", SEC_MODERATOR, true, NULL, "", teleCommandTable }, + { "character", SEC_GAMEMASTER, false, NULL, "", characterCommandTable}, + { "event", SEC_GAMEMASTER, false, NULL, "", eventCommandTable }, + { "gobject", SEC_GAMEMASTER, false, NULL, "", gobjectCommandTable }, + { "honor", SEC_GAMEMASTER, false, NULL, "", honorCommandTable }, + { "wp", SEC_GAMEMASTER, false, NULL, "", wpCommandTable }, + { "titles", SEC_GAMEMASTER, false, NULL, "", titlesCommandTable }, + { "quest", SEC_ADMINISTRATOR, false, NULL, "", questCommandTable }, + { "reload", SEC_ADMINISTRATOR, true, NULL, "", reloadCommandTable }, + { "list", SEC_ADMINISTRATOR, true, NULL, "", listCommandTable }, + { "lookup", SEC_ADMINISTRATOR, true, NULL, "", lookupCommandTable }, + { "pdump", SEC_ADMINISTRATOR, true, NULL, "", pdumpCommandTable }, + { "guild", SEC_ADMINISTRATOR, true, NULL, "", guildCommandTable }, + { "cast", SEC_ADMINISTRATOR, false, NULL, "", castCommandTable }, + { "reset", SEC_ADMINISTRATOR, true, NULL, "", resetCommandTable }, + { "instance", SEC_ADMINISTRATOR, true, NULL, "", instanceCommandTable }, + { "server", SEC_ADMINISTRATOR, true, NULL, "", serverCommandTable }, + + { "channel", SEC_ADMINISTRATOR, true, NULL, "", channelCommandTable }, + + { "pet", SEC_GAMEMASTER, false, NULL, "", petCommandTable }, + { "loadpath", SEC_ADMINISTRATOR, false, &ChatHandler::HandleReloadAllPaths, "", NULL }, + { "ahbotoptions", SEC_GAMEMASTER, true, &ChatHandler::HandleAHBotOptionsCommand, "", NULL }, + { "ticket", SEC_MODERATOR, false, NULL, "", ticketCommandTable }, + + { "aura", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAuraCommand, "", NULL }, + { "unaura", SEC_ADMINISTRATOR, false, &ChatHandler::HandleUnAuraCommand, "", NULL }, + { "nameannounce", SEC_MODERATOR, false, &ChatHandler::HandleNameAnnounceCommand, "", NULL }, + { "gmnameannounce", SEC_MODERATOR, false, &ChatHandler::HandleGMNameAnnounceCommand, "", NULL }, + { "announce", SEC_MODERATOR, true, &ChatHandler::HandleAnnounceCommand, "", NULL }, + { "gmannounce", SEC_MODERATOR, true, &ChatHandler::HandleGMAnnounceCommand, "", NULL }, + { "notify", SEC_MODERATOR, true, &ChatHandler::HandleNotifyCommand, "", NULL }, + { "gmnotify", SEC_MODERATOR, true, &ChatHandler::HandleGMNotifyCommand, "", NULL }, + { "goname", SEC_MODERATOR, false, &ChatHandler::HandleGonameCommand, "", NULL }, + { "namego", SEC_MODERATOR, false, &ChatHandler::HandleNamegoCommand, "", NULL }, + { "groupgo", SEC_MODERATOR, false, &ChatHandler::HandleGroupgoCommand, "", NULL }, + { "commands", SEC_PLAYER, true, &ChatHandler::HandleCommandsCommand, "", NULL }, + { "demorph", SEC_GAMEMASTER, false, &ChatHandler::HandleDeMorphCommand, "", NULL }, + { "die", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDieCommand, "", NULL }, + { "revive", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReviveCommand, "", NULL }, + { "dismount", SEC_PLAYER, false, &ChatHandler::HandleDismountCommand, "", NULL }, + { "gps", SEC_MODERATOR, false, &ChatHandler::HandleGPSCommand, "", NULL }, + { "guid", SEC_GAMEMASTER, false, &ChatHandler::HandleGUIDCommand, "", NULL }, + { "help", SEC_PLAYER, true, &ChatHandler::HandleHelpCommand, "", NULL }, + { "itemmove", SEC_GAMEMASTER, false, &ChatHandler::HandleItemMoveCommand, "", NULL }, + { "cooldown", SEC_ADMINISTRATOR, false, &ChatHandler::HandleCooldownCommand, "", NULL }, + { "unlearn", SEC_ADMINISTRATOR, false, &ChatHandler::HandleUnLearnCommand, "", NULL }, + { "distance", SEC_ADMINISTRATOR, false, &ChatHandler::HandleGetDistanceCommand, "", NULL }, + { "recall", SEC_MODERATOR, false, &ChatHandler::HandleRecallCommand, "", NULL }, + { "save", SEC_PLAYER, false, &ChatHandler::HandleSaveCommand, "", NULL }, + { "saveall", SEC_MODERATOR, true, &ChatHandler::HandleSaveAllCommand, "", NULL }, + { "kick", SEC_GAMEMASTER, true, &ChatHandler::HandleKickPlayerCommand, "", NULL }, + { "ban", SEC_ADMINISTRATOR, true, NULL, "", banCommandTable }, + { "unban", SEC_ADMINISTRATOR, true, NULL, "", unbanCommandTable }, + { "baninfo", SEC_ADMINISTRATOR, false, NULL, "", baninfoCommandTable }, + { "banlist", SEC_ADMINISTRATOR, true, NULL, "", banlistCommandTable }, + { "start", SEC_PLAYER, false, &ChatHandler::HandleStartCommand, "", NULL }, + { "taxicheat", SEC_MODERATOR, false, &ChatHandler::HandleTaxiCheatCommand, "", NULL }, + { "linkgrave", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLinkGraveCommand, "", NULL }, + { "neargrave", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNearGraveCommand, "", NULL }, + { "explorecheat", SEC_ADMINISTRATOR, false, &ChatHandler::HandleExploreCheatCommand, "", NULL }, + { "hover", SEC_ADMINISTRATOR, false, &ChatHandler::HandleHoverCommand, "", NULL }, + { "levelup", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLevelUpCommand, "", NULL }, + { "showarea", SEC_ADMINISTRATOR, false, &ChatHandler::HandleShowAreaCommand, "", NULL }, + { "hidearea", SEC_ADMINISTRATOR, false, &ChatHandler::HandleHideAreaCommand, "", NULL }, + { "additem", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAddItemCommand, "", NULL }, + { "additemset", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAddItemSetCommand, "", NULL }, + { "bank", SEC_ADMINISTRATOR, false, &ChatHandler::HandleBankCommand, "", NULL }, + { "wchange", SEC_ADMINISTRATOR, false, &ChatHandler::HandleChangeWeather, "", NULL }, + { "maxskill", SEC_ADMINISTRATOR, false, &ChatHandler::HandleMaxSkillCommand, "", NULL }, + { "setskill", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSetSkillCommand, "", NULL }, + { "whispers", SEC_MODERATOR, false, &ChatHandler::HandleWhispersCommand, "", NULL }, + { "pinfo", SEC_GAMEMASTER, true, &ChatHandler::HandlePInfoCommand, "", NULL }, + { "respawn", SEC_ADMINISTRATOR, false, &ChatHandler::HandleRespawnCommand, "", NULL }, + { "send", SEC_MODERATOR, true, NULL, "", sendCommandTable }, + { "mute", SEC_MODERATOR, true, &ChatHandler::HandleMuteCommand, "", NULL }, + { "unmute", SEC_MODERATOR, true, &ChatHandler::HandleUnmuteCommand, "", NULL }, + { "movegens", SEC_ADMINISTRATOR, false, &ChatHandler::HandleMovegensCommand, "", NULL }, + { "cometome", SEC_ADMINISTRATOR, false, &ChatHandler::HandleComeToMeCommand, "", NULL }, + { "damage", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDamageCommand, "", NULL }, + { "combatstop", SEC_GAMEMASTER, false, &ChatHandler::HandleCombatStopCommand, "", NULL }, + { "flusharenapoints",SEC_ADMINISTRATOR, false, &ChatHandler::HandleFlushArenaPointsCommand, "", NULL }, + { "repairitems", SEC_GAMEMASTER, true, &ChatHandler::HandleRepairitemsCommand, "", NULL }, + { "waterwalk", SEC_GAMEMASTER, false, &ChatHandler::HandleWaterwalkCommand, "", NULL }, + + { "freeze", SEC_MODERATOR, false, &ChatHandler::HandleFreezeCommand, "", NULL }, + { "unfreeze", SEC_MODERATOR, false, &ChatHandler::HandleUnFreezeCommand, "", NULL }, + { "listfreeze", SEC_MODERATOR, false, &ChatHandler::HandleListFreezeCommand, "", NULL }, + + { "possess", SEC_ADMINISTRATOR, false, &ChatHandler::HandlePossessCommand, "", NULL }, + { "unpossess", SEC_ADMINISTRATOR, false, &ChatHandler::HandleUnPossessCommand, "", NULL }, + { "bindsight", SEC_ADMINISTRATOR, false, &ChatHandler::HandleBindSightCommand, "", NULL }, + { "unbindsight", SEC_ADMINISTRATOR, false, &ChatHandler::HandleUnbindSightCommand, "", NULL }, + { "playall", SEC_GAMEMASTER, false, &ChatHandler::HandlePlayAllCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + if (load_command_table) + { + load_command_table = false; + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT name,security,help FROM command"); + if (result) + { + do + { + Field *fields = result->Fetch(); + std::string name = fields[0].GetCppString(); + + SetDataForCommandInTable(commandTable, name.c_str(), fields[1].GetUInt16(), fields[2].GetCppString(), name); + + } while (result->NextRow()); + } + } + + return commandTable; +} + +const char *ChatHandler::GetTrinityString(int32 entry) const +{ + return m_session->GetTrinityString(entry); +} + +bool ChatHandler::isAvailable(ChatCommand const& cmd) const +{ + // check security level only for simple command (without child commands) + return m_session->GetSecurity() >= cmd.SecurityLevel; +} + +bool ChatHandler::HasLowerSecurity(Player* target, uint64 guid, bool strong) +{ + WorldSession* target_session = NULL; + uint32 target_account = 0; + + if (target) + target_session = target->GetSession(); + else if (guid) + target_account = objmgr.GetPlayerAccountIdByGUID(guid); + + if (!target_session && !target_account) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return true; + } + + return HasLowerSecurityAccount(target_session,target_account,strong); +} + +bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_account, bool strong) +{ + uint32 target_sec; + + // allow everything from console and RA console + if (!m_session) + return false; + + // ignore only for non-players for non strong checks (when allow apply command at least to same sec level) + if (m_session->GetSecurity() > SEC_PLAYER && !strong && !sWorld.getConfig(CONFIG_GM_LOWER_SECURITY)) + return false; + + if (target) + target_sec = target->GetSecurity(); + else if (target_account) + target_sec = accmgr.GetSecurity(target_account); + else + return true; // caller must report error for (target == NULL && target_account == 0) + + if (m_session->GetSecurity() < target_sec || (strong && m_session->GetSecurity() <= target_sec)) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + SetSentErrorMessage(true); + return true; + } + + return false; +} + +bool ChatHandler::hasStringAbbr(const char* name, const char* part) +{ + // non "" command + if (*name) + { + // "" part from non-"" command + if (!*part) + return false; + + for (;;) + { + if (!*part) + return true; + else if (!*name) + return false; + else if (tolower(*name) != tolower(*part)) + return false; + ++name; ++part; + } + } + // allow with any for "" + + return true; +} + +void ChatHandler::SendSysMessage(const char *str) +{ + WorldPacket data; + + // need copy to prevent corruption by strtok call in LineFromMessage original string + char* buf = strdup(str); + char* pos = buf; + + while (char* line = LineFromMessage(pos)) + { + FillSystemMessageData(&data, line); + m_session->SendPacket(&data); + } + + free(buf); +} + +void ChatHandler::SendGlobalSysMessage(const char *str) +{ + // Chat output + WorldPacket data; + + // need copy to prevent corruption by strtok call in LineFromMessage original string + char* buf = strdup(str); + char* pos = buf; + + while (char* line = LineFromMessage(pos)) + { + FillSystemMessageData(&data, line); + sWorld.SendGlobalMessage(&data); + } + + free(buf); +} + +void ChatHandler::SendGlobalGMSysMessage(const char *str) +{ + // Chat output + WorldPacket data; + + // need copy to prevent corruption by strtok call in LineFromMessage original string + char* buf = strdup(str); + char* pos = buf; + + while (char* line = LineFromMessage(pos)) + { + FillSystemMessageData(&data, line); + sWorld.SendGlobalGMMessage(&data); + } + free(buf); +} + +void ChatHandler::SendSysMessage(int32 entry) +{ + SendSysMessage(GetTrinityString(entry)); +} + +void ChatHandler::PSendSysMessage(int32 entry, ...) +{ + const char *format = GetTrinityString(entry); + va_list ap; + char str [2048]; + va_start(ap, entry); + vsnprintf(str,2048,format, ap); + va_end(ap); + SendSysMessage(str); +} + +void ChatHandler::PSendSysMessage(const char *format, ...) +{ + va_list ap; + char str [2048]; + va_start(ap, format); + vsnprintf(str,2048,format, ap); + va_end(ap); + SendSysMessage(str); +} + +bool ChatHandler::ExecuteCommandInTable(ChatCommand *table, const char* text, const std::string& fullcmd) +{ + char const* oldtext = text; + std::string cmd = ""; + + while (*text != ' ' && *text != '\0') + { + cmd += *text; + ++text; + } + + while (*text == ' ') ++text; + + for (uint32 i = 0; table[i].Name != NULL; ++i) + { + if (!hasStringAbbr(table[i].Name, cmd.c_str())) + continue; + + // select subcommand from child commands list + if (table[i].ChildCommands != NULL) + { + if (!ExecuteCommandInTable(table[i].ChildCommands, text, fullcmd)) + { + if (text && text[0] != '\0') + SendSysMessage(LANG_NO_SUBCMD); + else + SendSysMessage(LANG_CMD_SYNTAX); + + ShowHelpForCommand(table[i].ChildCommands,text); + } + + return true; + } + + // must be available and have handler + if (!table[i].Handler || !isAvailable(table[i])) + continue; + + SetSentErrorMessage(false); + // table[i].Name == "" is special case: send original command to handler + if ((this->*(table[i].Handler))(strlen(table[i].Name) != 0 ? text : oldtext)) + { + if (table[i].SecurityLevel > SEC_PLAYER) + { + // chat case + if (m_session) + { + Player* p = m_session->GetPlayer(); + uint64 sel_guid = p->GetSelection(); + sLog.outCommand(m_session->GetAccountId(),"Command: %s [Player: %s (Account: %u) X: %f Y: %f Z: %f Map: %u Selected: %s (GUID: %u)]", + fullcmd.c_str(),p->GetName(),m_session->GetAccountId(),p->GetPositionX(),p->GetPositionY(),p->GetPositionZ(),p->GetMapId(), + GetLogNameForGuid(sel_guid),GUID_LOPART(sel_guid)); + } + } + } + // some commands have custom error messages. Don't send the default one in these cases. + else if (!sentErrorMessage) + { + if (!table[i].Help.empty()) + SendSysMessage(table[i].Help.c_str()); + else + SendSysMessage(LANG_CMD_SYNTAX); + } + + return true; + } + + return false; +} + +bool ChatHandler::SetDataForCommandInTable(ChatCommand *table, const char* text, uint32 security, std::string const& help, std::string const& fullcommand) +{ + std::string cmd = ""; + + while (*text != ' ' && *text != '\0') + { + cmd += *text; + ++text; + } + + while (*text == ' ') ++text; + + for (uint32 i = 0; table[i].Name != NULL; i++) + { + // for data fill use full explicit command names + if (table[i].Name != cmd) + continue; + + // select subcommand from child commands list (including "") + if (table[i].ChildCommands != NULL) + { + if (SetDataForCommandInTable(table[i].ChildCommands, text, security, help, fullcommand)) + return true; + else if (*text) + return false; + + // fail with "" subcommands, then use normal level up command instead + } + // expected subcommand by full name DB content + else if (*text) + { + sLog.outErrorDb("Table `command` have unexpected subcommand '%s' in command '%s', skip.",text,fullcommand.c_str()); + return false; + } + + if (table[i].SecurityLevel != security) + sLog.outDetail("Table `command` overwrite for command '%s' default security (%u) by %u",fullcommand.c_str(),table[i].SecurityLevel,security); + + table[i].SecurityLevel = security; + table[i].Help = help; + return true; + } + + // in case "" command let process by caller + if (!cmd.empty()) + { + if (table == getCommandTable()) + sLog.outErrorDb("Table `command` have not existed command '%s', skip.",cmd.c_str()); + else + sLog.outErrorDb("Table `command` have not existed subcommand '%s' in command '%s', skip.",cmd.c_str(),fullcommand.c_str()); + } + + return false; +} + +int ChatHandler::ParseCommands(const char* text) +{ + ASSERT(text); + ASSERT(*text); + + std::string fullcmd = text; + + if (m_session && m_session->GetSecurity() <= SEC_PLAYER && sWorld.getConfig(CONFIG_ALLOW_PLAYER_COMMANDS) == 0) + return 0; + + if (m_session && !m_session->HandleOnPlayerChat(text)) + return 0; + + /// chat case (.command or !command format) + if (m_session) + { + if (text[0] != '!' && text[0] != '.') + return 0; + } + + /// ignore single . and ! in line + if (strlen(text) < 2) + return 0; + // original `text` can't be used. It content destroyed in command code processing. + + /// ignore messages staring from many dots. + if ((text[0] == '.' && text[1] == '.') || (text[0] == '!' && text[1] == '!')) + return 0; + + /// skip first . or ! (in console allowed use command with . and ! and without its) + if (text[0] == '!' || text[0] == '.') + ++text; + + if (!ExecuteCommandInTable(getCommandTable(), text, fullcmd)) + { + if (m_session && m_session->GetSecurity() == SEC_PLAYER) + return 0; + SendSysMessage(LANG_NO_CMD); + } + return 1; +} + +bool ChatHandler::isValidChatMessage(const char* message) +{ +/* + +valid examples: +|cffa335ee|Hitem:812:0:0:0:0:0:0:0:70|h[Glowing Brightwood Staff]|h|r +|cff808080|Hquest:2278:47|h[The Platinum Discs]|h|r +|cffffd000|Htrade:4037:1:150:1:6AAAAAAAAAAAAAAAAAAAAAAOAADAAAAAAAAAAAAAAAAIAAAAAAAAA|h[Engineering]|h|r +|cff4e96f7|Htalent:2232:-1|h[Taste for Blood]|h|r +|cff71d5ff|Hspell:21563|h[Command]|h|r +|cffffd000|Henchant:3919|h[Engineering: Rough Dynamite]|h|r +|cffffff00|Hachievement:546:0000000000000001:0:0:0:-1:0:0:0:0|h[Safe Deposit]|h|r +|cff66bbff|Hglyph:21:762|h[Glyph of Bladestorm]|h|r + +| will be escaped to || +*/ + + if (strlen(message) > 255) + return false; + + const char validSequence[6] = "cHhhr"; + const char* validSequenceIterator = validSequence; + + // more simple checks + if (sWorld.getConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY) < 3) + { + const std::string validCommands = "cHhr|"; + + while (*message) + { + // find next pipe command + message = strchr(message, '|'); + + if (!message) + return true; + + ++message; + char commandChar = *message; + if (validCommands.find(commandChar) == std::string::npos) + return false; + + ++message; + // validate sequence + if (sWorld.getConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY) == 2) + { + if (commandChar == *validSequenceIterator) + { + if (validSequenceIterator == validSequence+4) + validSequenceIterator = validSequence; + else + ++validSequenceIterator; + } + else + return false; + } + } + return true; + } + + std::istringstream reader(message); + char buffer[256]; + + uint32 color; + + ItemPrototype const* linkedItem; + Quest const* linkedQuest; + SpellEntry const *linkedSpell; + AchievementEntry const* linkedAchievement; + ItemRandomPropertiesEntry const* itemProperty; + ItemRandomSuffixEntry const* itemSuffix; + + while (!reader.eof()) + { + if (validSequence == validSequenceIterator) + { + linkedItem = NULL; + linkedQuest = NULL; + linkedSpell = NULL; + linkedAchievement = NULL; + itemProperty = NULL; + itemSuffix = NULL; + + reader.ignore(255, '|'); + } + else if (reader.get() != '|') + { +#ifdef TRINITY_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage sequence aborted unexpectedly"); +#endif + return false; + } + + // pipe has always to be followed by at least one char + if (reader.peek() == '\0') + { +#ifdef TRINITY_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage pipe followed by \\0"); +#endif + return false; + } + + // no further pipe commands + if (reader.eof()) + break; + + char commandChar; + reader >> commandChar; + + // | in normal messages is escaped by || + if (commandChar != '|') + { + if (commandChar == *validSequenceIterator) + { + if (validSequenceIterator == validSequence+4) + validSequenceIterator = validSequence; + else + ++validSequenceIterator; + } + else + { +#ifdef TRINITY_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage invalid sequence, expected %c but got %c", *validSequenceIterator, commandChar); +#endif + return false; + } + } + else if (validSequence != validSequenceIterator) + { + // no escaped pipes in sequences +#ifdef TRINITY_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage got escaped pipe in sequence"); +#endif + return false; + } + + switch (commandChar) + { + case 'c': + color = 0; + // validate color, expect 8 hex chars + for (int i=0; i<8; i++) + { + char c; + reader >> c; + if (!c) + { +#ifdef TRINITY_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage got \\0 while reading color in |c command"); +#endif + return false; + } + + color <<= 4; + // check for hex char + if (c >= '0' && c <= '9') + { + color |= c-'0'; + continue; + } + if (c >= 'a' && c <= 'f') + { + color |= 10+c-'a'; + continue; + } +#ifdef TRINITY_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage got non hex char '%c' while reading color", c); +#endif + return false; + } + break; + case 'H': + // read chars up to colon = link type + reader.getline(buffer, 256, ':'); + + if (strcmp(buffer, "item") == 0) + { + // read item entry + reader.getline(buffer, 256, ':'); + + linkedItem= objmgr.GetItemPrototype(atoi(buffer)); + if (!linkedItem) + { +#ifdef TRINITY_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage got invalid itemID %u in |item command", atoi(buffer)); +#endif + return false; + } + + if (color != ItemQualityColors[linkedItem->Quality]) + { +#ifdef TRINITY_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage linked item has color %u, but user claims %u", ItemQualityColors[linkedItem->Quality], + color); +#endif + return false; + } + + // the itementry is followed by several integers which describe an instance of this item + + // position relative after itemEntry + const uint8 randomPropertyPosition = 6; + + int32 propertyId = 0; + bool negativeNumber = false; + char c; + for (uint8 i=0; i<randomPropertyPosition; ++i) + { + propertyId = 0; + negativeNumber = false; + while ((c = reader.get()) != ':') + { + if (c >='0' && c <= '9') + { + propertyId*=10; + propertyId += c-'0'; + } else if (c == '-') + negativeNumber = true; + else + return false; + } + } + if (negativeNumber) + propertyId *= -1; + + if (propertyId > 0) + { + itemProperty = sItemRandomPropertiesStore.LookupEntry(propertyId); + if (!itemProperty) + return false; + } + else if (propertyId < 0) + { + itemSuffix = sItemRandomSuffixStore.LookupEntry(-propertyId); + if (!itemSuffix) + return false; + } + + // ignore other integers + while ((c >='0' && c <= '9') || c == ':') + { + reader.ignore(1); + c = reader.peek(); + } + } + else if (strcmp(buffer, "quest") == 0) + { + // no color check for questlinks, each client will adapt it anyway + uint32 questid= 0; + // read questid + char c = reader.peek(); + while (c >='0' && c <= '9') + { + reader.ignore(1); + questid *= 10; + questid += c-'0'; + c = reader.peek(); + } + + linkedQuest = objmgr.GetQuestTemplate(questid); + + if (!linkedQuest) + { +#ifdef MANOGS_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage Questtemplate %u not found", questid); +#endif + return false; + } + c = reader.peek(); + // level + while (c !='|' && c != '\0') + { + reader.ignore(1); + c = reader.peek(); + } + } + else if (strcmp(buffer, "trade") == 0) + { + if (color != CHAT_LINK_COLOR_TRADE) + return false; + + // read spell entry + reader.getline(buffer, 256, ':'); + linkedSpell = sSpellStore.LookupEntry(atoi(buffer)); + if (!linkedSpell) + return false; + + char c = reader.peek(); + // base64 encoded stuff + while (c !='|' && c != '\0') + { + reader.ignore(1); + c = reader.peek(); + } + } + else if (strcmp(buffer, "talent") == 0) + { + // talent links are always supposed to be blue + if (color != CHAT_LINK_COLOR_TALENT) + return false; + + // read talent entry + reader.getline(buffer, 256, ':'); + TalentEntry const *talentInfo = sTalentStore.LookupEntry(atoi(buffer)); + if (!talentInfo) + return false; + + linkedSpell = sSpellStore.LookupEntry(talentInfo->RankID[0]); + if (!linkedSpell) + return false; + + char c = reader.peek(); + // skillpoints? whatever, drop it + while (c !='|' && c != '\0') + { + reader.ignore(1); + c = reader.peek(); + } + } + else if (strcmp(buffer, "spell") == 0) + { + if (color != CHAT_LINK_COLOR_SPELL) + return false; + + uint32 spellid = 0; + // read spell entry + char c = reader.peek(); + while (c >='0' && c <= '9') + { + reader.ignore(1); + spellid *= 10; + spellid += c-'0'; + c = reader.peek(); + } + linkedSpell = sSpellStore.LookupEntry(spellid); + if (!linkedSpell) + return false; + } + else if (strcmp(buffer, "enchant") == 0) + { + if (color != CHAT_LINK_COLOR_ENCHANT) + return false; + + uint32 spellid = 0; + // read spell entry + char c = reader.peek(); + while (c >='0' && c <= '9') + { + reader.ignore(1); + spellid *= 10; + spellid += c-'0'; + c = reader.peek(); + } + linkedSpell = sSpellStore.LookupEntry(spellid); + if (!linkedSpell) + return false; + } + else if (strcmp(buffer, "achievement") == 0) + { + if (color != CHAT_LINK_COLOR_ACHIEVEMENT) + return false; + reader.getline(buffer, 256, ':'); + uint32 achievementId = atoi(buffer); + linkedAchievement = sAchievementStore.LookupEntry(achievementId); + + if (!linkedAchievement) + return false; + + char c = reader.peek(); + // skip progress + while (c !='|' && c != '\0') + { + reader.ignore(1); + c = reader.peek(); + } + } + else if (strcmp(buffer, "glyph") == 0) + { + if (color != CHAT_LINK_COLOR_GLYPH) + return false; + + // first id is slot, drop it + reader.getline(buffer, 256, ':'); + uint32 glyphId = 0; + char c = reader.peek(); + while (c >= '0' && c <= '9') + { + glyphId *= 10; + glyphId += c-'0'; + reader.ignore(1); + c = reader.peek(); + } + GlyphPropertiesEntry const* glyph = sGlyphPropertiesStore.LookupEntry(glyphId); + if (!glyph) + return false; + + linkedSpell = sSpellStore.LookupEntry(glyph->SpellId); + + if (!linkedSpell) + return false; + } + else + { +#ifdef TRINITY_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage user sent unsupported link type '%s'", buffer); +#endif + return false; + } + break; + case 'h': + // if h is next element in sequence, this one must contain the linked text :) + if (*validSequenceIterator == 'h') + { + // links start with '[' + if (reader.get() != '[') + { +#ifdef TRINITY_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage link caption doesn't start with '['"); +#endif + return false; + } + reader.getline(buffer, 256, ']'); + + // verify the link name + if (linkedSpell) + { + // spells with that flag have a prefix of "$PROFESSION: " + if (linkedSpell->Attributes & SPELL_ATTR_TRADESPELL) + { + // lookup skillid + SkillLineAbilityMapBounds bounds = spellmgr.GetSkillLineAbilityMapBounds(linkedSpell->Id); + if (bounds.first == bounds.second) + { + return false; + } + + SkillLineAbilityEntry const *skillInfo = bounds.first->second; + + if (!skillInfo) + { + return false; + } + + SkillLineEntry const *skillLine = sSkillLineStore.LookupEntry(skillInfo->skillId); + if (!skillLine) + { + return false; + } + + for (uint8 i=0; i<MAX_LOCALE; ++i) + { + uint32 skillLineNameLength = strlen(skillLine->name[i]); + if (skillLineNameLength > 0 && strncmp(skillLine->name[i], buffer, skillLineNameLength) == 0) + { + // found the prefix, remove it to perform spellname validation below + // -2 = strlen(": ") + uint32 spellNameLength = strlen(buffer)-skillLineNameLength-2; + memmove(buffer, buffer+skillLineNameLength+2, spellNameLength+1); + } + } + } + bool foundName = false; + for (uint8 i=0; i<MAX_LOCALE; ++i) + { + if (*linkedSpell->SpellName[i] && strcmp(linkedSpell->SpellName[i], buffer) == 0) + { + foundName = true; + break; + } + } + if (!foundName) + return false; + } + else if (linkedQuest) + { + if (linkedQuest->GetTitle() != buffer) + { + QuestLocale const *ql = objmgr.GetQuestLocale(linkedQuest->GetQuestId()); + + if (!ql) + { +#ifdef MANOGS_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage default questname didn't match and there is no locale"); +#endif + return false; + } + + bool foundName = false; + for (uint8 i=0; i<ql->Title.size(); i++) + { + if (ql->Title[i] == buffer) + { + foundName = true; + break; + } + } + if (!foundName) + { +#ifdef MANOGS_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage no quest locale title matched") +#endif + return false; + } + } + } + else if (linkedItem) + { + char* const* suffix = itemSuffix?itemSuffix->nameSuffix:(itemProperty?itemProperty->nameSuffix:NULL); + + std::string expectedName = std::string(linkedItem->Name1); + if (suffix) + { + expectedName += " "; + expectedName += suffix[LOCALE_enUS]; + } + + if (expectedName != buffer) + { + ItemLocale const *il = objmgr.GetItemLocale(linkedItem->ItemId); + + bool foundName = false; + for (uint8 i=LOCALE_koKR; i<MAX_LOCALE; ++i) + { + int8 dbIndex = objmgr.GetIndexForLocale(LocaleConstant(i)); + if (dbIndex == -1 || il == NULL || dbIndex >= il->Name.size()) + // using strange database/client combinations can lead to this case + expectedName = linkedItem->Name1; + else + expectedName = il->Name[dbIndex]; + if (suffix) + { + expectedName += " "; + expectedName += suffix[i]; + } + if (expectedName == buffer) + { + foundName = true; + break; + } + } + if (!foundName) + { +#ifdef TRINITY_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage linked item name wasn't found in any localization"); +#endif + return false; + } + } + } + else if (linkedAchievement) + { + bool foundName = false; + for (uint8 i=0; i<MAX_LOCALE; ++i) + { + if (*linkedAchievement->name[i] && strcmp(linkedAchievement->name[i], buffer) == 0) + { + foundName = true; + break; + } + } + if (!foundName) + return false; + } + // that place should never be reached - if nothing linked has been set in |H + // it will return false before + else + return false; + } + break; + case 'r': + case '|': + // no further payload + break; + default: +#ifdef TRINITY_DEBUG + sLog.outBasic("ChatHandler::isValidChatMessage got invalid command |%c", commandChar); +#endif + return false; + } + } + + // check if every opened sequence was also closed properly +#ifdef TRINITY_DEBUG + if (validSequence != validSequenceIterator) + sLog.outBasic("ChatHandler::isValidChatMessage EOF in active sequence"); +#endif + return validSequence == validSequenceIterator; +} + +bool ChatHandler::ShowHelpForSubCommands(ChatCommand *table, char const* cmd, char const* subcmd) +{ + std::string list; + for (uint32 i = 0; table[i].Name != NULL; ++i) + { + // must be available (ignore handler existence for show command with possibe avalable subcomands + if (!isAvailable(table[i])) + continue; + + /// for empty subcmd show all available + if (*subcmd && !hasStringAbbr(table[i].Name, subcmd)) + continue; + + if (m_session) + list += "\n "; + else + list += "\n\r "; + + list += table[i].Name; + + if (table[i].ChildCommands) + list += " ..."; + } + + if (list.empty()) + return false; + + if (table == getCommandTable()) + { + SendSysMessage(LANG_AVIABLE_CMD); + PSendSysMessage("%s",list.c_str()); + } + else + PSendSysMessage(LANG_SUBCMDS_LIST,cmd,list.c_str()); + + return true; +} + +bool ChatHandler::ShowHelpForCommand(ChatCommand *table, const char* cmd) +{ + if (*cmd) + { + for (uint32 i = 0; table[i].Name != NULL; ++i) + { + // must be available (ignore handler existence for show command with possibe avalable subcomands + if (!isAvailable(table[i])) + continue; + + if (!hasStringAbbr(table[i].Name, cmd)) + continue; + + // have subcommand + char const* subcmd = (*cmd) ? strtok(NULL, " ") : ""; + + if (table[i].ChildCommands && subcmd && *subcmd) + { + if (ShowHelpForCommand(table[i].ChildCommands, subcmd)) + return true; + } + + if (!table[i].Help.empty()) + SendSysMessage(table[i].Help.c_str()); + + if (table[i].ChildCommands) + if (ShowHelpForSubCommands(table[i].ChildCommands,table[i].Name,subcmd ? subcmd : "")) + return true; + + return !table[i].Help.empty(); + } + } + else + { + for (uint32 i = 0; table[i].Name != NULL; ++i) + { + // must be available (ignore handler existence for show command with possibe avalable subcomands + if (!isAvailable(table[i])) + continue; + + if (strlen(table[i].Name)) + continue; + + if (!table[i].Help.empty()) + SendSysMessage(table[i].Help.c_str()); + + if (table[i].ChildCommands) + if (ShowHelpForSubCommands(table[i].ChildCommands,"","")) + return true; + + return !table[i].Help.empty(); + } + } + + return ShowHelpForSubCommands(table,"",cmd); +} + +//Note: target_guid used only in CHAT_MSG_WHISPER_INFORM mode (in this case channelName ignored) +void ChatHandler::FillMessageData(WorldPacket *data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit *speaker) +{ + uint32 messageLength = (message ? strlen(message) : 0) + 1; + + data->Initialize(SMSG_MESSAGECHAT, 100); // guess size + *data << uint8(type); + if ((type != CHAT_MSG_CHANNEL && type != CHAT_MSG_WHISPER) || language == LANG_ADDON) + *data << uint32(language); + else + *data << uint32(LANG_UNIVERSAL); + + switch(type) + { + case CHAT_MSG_SAY: + case CHAT_MSG_PARTY: + case CHAT_MSG_PARTY_LEADER: + case CHAT_MSG_RAID: + case CHAT_MSG_GUILD: + case CHAT_MSG_OFFICER: + case CHAT_MSG_YELL: + case CHAT_MSG_WHISPER: + case CHAT_MSG_CHANNEL: + case CHAT_MSG_RAID_LEADER: + case CHAT_MSG_RAID_WARNING: + case CHAT_MSG_BG_SYSTEM_NEUTRAL: + case CHAT_MSG_BG_SYSTEM_ALLIANCE: + case CHAT_MSG_BG_SYSTEM_HORDE: + case CHAT_MSG_BATTLEGROUND: + case CHAT_MSG_BATTLEGROUND_LEADER: + target_guid = session ? session->GetPlayer()->GetGUID() : 0; + break; + case CHAT_MSG_MONSTER_SAY: + case CHAT_MSG_MONSTER_PARTY: + case CHAT_MSG_MONSTER_YELL: + case CHAT_MSG_MONSTER_WHISPER: + case CHAT_MSG_MONSTER_EMOTE: + case CHAT_MSG_RAID_BOSS_WHISPER: + case CHAT_MSG_RAID_BOSS_EMOTE: + case CHAT_MSG_BATTLENET: + { + *data << uint64(speaker->GetGUID()); + *data << uint32(0); // 2.1.0 + *data << uint32(strlen(speaker->GetName()) + 1); + *data << speaker->GetName(); + uint64 listener_guid = 0; + *data << uint64(listener_guid); + if (listener_guid && !IS_PLAYER_GUID(listener_guid)) + { + *data << uint32(1); // string listener_name_length + *data << uint8(0); // string listener_name + } + *data << uint32(messageLength); + *data << message; + *data << uint8(0); + return; + } + default: + if (type != CHAT_MSG_WHISPER_INFORM && type != CHAT_MSG_IGNORED && type != CHAT_MSG_DND && type != CHAT_MSG_AFK) + target_guid = 0; // only for CHAT_MSG_WHISPER_INFORM used original value target_guid + break; + } + + *data << uint64(target_guid); // there 0 for BG messages + *data << uint32(0); // can be chat msg group or something + + if (type == CHAT_MSG_CHANNEL) + { + ASSERT(channelName); + *data << channelName; + } + + *data << uint64(target_guid); + *data << uint32(messageLength); + *data << message; + if (session != 0 && type != CHAT_MSG_WHISPER_INFORM && type != CHAT_MSG_DND && type != CHAT_MSG_AFK) + *data << uint8(session->GetPlayer()->chatTag()); + else + *data << uint8(0); +} + +Player * ChatHandler::getSelectedPlayer() +{ + if (!m_session) + return NULL; + + uint64 guid = m_session->GetPlayer()->GetSelection(); + + if (guid == 0) + return m_session->GetPlayer(); + + return objmgr.GetPlayer(guid); +} + +Unit* ChatHandler::getSelectedUnit() +{ + if (!m_session) + return NULL; + + uint64 guid = m_session->GetPlayer()->GetSelection(); + + if (guid == 0) + return m_session->GetPlayer(); + + return ObjectAccessor::GetUnit(*m_session->GetPlayer(),guid); +} + +WorldObject *ChatHandler::getSelectedObject() +{ + if (!m_session) + return NULL; + + uint64 guid = m_session->GetPlayer()->GetSelection(); + + if (guid == 0) + return GetNearbyGameObject(); + + return ObjectAccessor::GetUnit(*m_session->GetPlayer(),guid); +} + +Creature* ChatHandler::getSelectedCreature() +{ + if (!m_session) + return NULL; + + return ObjectAccessor::GetCreatureOrPetOrVehicle(*m_session->GetPlayer(),m_session->GetPlayer()->GetSelection()); +} + +char* ChatHandler::extractKeyFromLink(char* text, char const* linkType, char** something1) +{ + // skip empty + if (!text) + return NULL; + + // skip spaces + while (*text == ' '||*text == '\t'||*text == '\b') + ++text; + + if (!*text) + return NULL; + + // return non link case + if (text[0] != '|') + return strtok(text, " "); + + // [name] Shift-click form |color|linkType:key|h[name]|h|r + // or + // [name] Shift-click form |color|linkType:key:something1:...:somethingN|h[name]|h|r + + char* check = strtok(text, "|"); // skip color + if (!check) + return NULL; // end of data + + char* cLinkType = strtok(NULL, ":"); // linktype + if (!cLinkType) + return NULL; // end of data + + if (strcmp(cLinkType,linkType) != 0) + { + strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after retturn from function + SendSysMessage(LANG_WRONG_LINK_TYPE); + return NULL; + } + + char* cKeys = strtok(NULL, "|"); // extract keys and values + char* cKeysTail = strtok(NULL, ""); + + char* cKey = strtok(cKeys, ":|"); // extract key + if (something1) + *something1 = strtok(NULL, ":|"); // extract something + + strtok(cKeysTail, "]"); // restart scan tail and skip name with possible spaces + strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after return from function + return cKey; +} + +char* ChatHandler::extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1) +{ + // skip empty + if (!text) + return NULL; + + // skip spaces + while (*text == ' '||*text == '\t'||*text == '\b') + ++text; + + if (!*text) + return NULL; + + // return non link case + if (text[0] != '|') + return strtok(text, " "); + + // [name] Shift-click form |color|linkType:key|h[name]|h|r + // or + // [name] Shift-click form |color|linkType:key:something1:...:somethingN|h[name]|h|r + // or + // [name] Shift-click form |linkType:key|h[name]|h|r + + char* tail; + + if (text[1] == 'c') + { + char* check = strtok(text, "|"); // skip color + if (!check) + return NULL; // end of data + + tail = strtok(NULL, ""); // tail + } + else + tail = text+1; // skip first | + + char* cLinkType = strtok(tail, ":"); // linktype + if (!cLinkType) + return NULL; // end of data + + for (int i = 0; linkTypes[i]; ++i) + { + if (strcmp(cLinkType,linkTypes[i]) == 0) + { + char* cKeys = strtok(NULL, "|"); // extract keys and values + char* cKeysTail = strtok(NULL, ""); + + char* cKey = strtok(cKeys, ":|"); // extract key + if (something1) + *something1 = strtok(NULL, ":|"); // extract something + + strtok(cKeysTail, "]"); // restart scan tail and skip name with possible spaces + strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after return from function + if (found_idx) + *found_idx = i; + return cKey; + } + } + + strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after return from function + SendSysMessage(LANG_WRONG_LINK_TYPE); + return NULL; +} + +char const *fmtstring(char const *format, ...) +{ + va_list argptr; + #define MAX_FMT_STRING 32000 + static char temp_buffer[MAX_FMT_STRING]; + static char string[MAX_FMT_STRING]; + static int index = 0; + char *buf; + int len; + + va_start(argptr, format); + vsnprintf(temp_buffer,MAX_FMT_STRING, format, argptr); + va_end(argptr); + + len = strlen(temp_buffer); + + if (len >= MAX_FMT_STRING) + return "ERROR"; + + if (len + index >= MAX_FMT_STRING-1) + { + index = 0; + } + + buf = &string[index]; + memcpy(buf, temp_buffer, len+1); + + index += len + 1; + + return buf; +} + +GameObject* ChatHandler::GetNearbyGameObject() +{ + if (!m_session) + return NULL; + + Player* pl = m_session->GetPlayer(); + GameObject* obj = NULL; + Trinity::NearestGameObjectCheck check(*pl); + Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectCheck> searcher(pl, obj, check); + pl->VisitNearbyGridObject(999, searcher); + return obj; +} + +GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry) +{ + if (!m_session) + return NULL; + + Player* pl = m_session->GetPlayer(); + + GameObject* obj = pl->GetMap()->GetGameObject(MAKE_NEW_GUID(lowguid, entry, HIGHGUID_GAMEOBJECT)); + + if (!obj && objmgr.GetGOData(lowguid)) // guid is DB guid of object + { + // search near player then + CellPair p(Trinity::ComputeCellPair(pl->GetPositionX(), pl->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + Trinity::GameObjectWithDbGUIDCheck go_check(*pl,lowguid); + Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(pl,obj,go_check); + + TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker); + cell.Visit(p, object_checker, *pl->GetMap()); + } + + return obj; +} + +enum SpellLinkType +{ + SPELL_LINK_SPELL = 0, + SPELL_LINK_TALENT = 1, + SPELL_LINK_ENCHANT = 2, + SPELL_LINK_TRADE = 3, + SPELL_LINK_GLYPH = 4 +}; + +static char const* const spellKeys[] = +{ + "Hspell", // normal spell + "Htalent", // talent spell + "Henchant", // enchanting recipe spell + "Htrade", // profession/skill spell + "Hglyph", // glyph + 0 +}; + +uint32 ChatHandler::extractSpellIdFromLink(char* text) +{ + // number or [name] Shift-click form |color|Henchant:recipe_spell_id|h[prof_name: recipe_name]|h|r + // number or [name] Shift-click form |color|Hglyph:glyph_slot_id:glyph_prop_id|h[%s]|h|r + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r + // number or [name] Shift-click form |color|Htalent:talent_id,rank|h[name]|h|r + // number or [name] Shift-click form |color|Htrade:spell_id,skill_id,max_value,cur_value|h[name]|h|r + int type = 0; + char* param1_str = NULL; + char* idS = extractKeyFromLink(text,spellKeys,&type,¶m1_str); + if (!idS) + return 0; + + uint32 id = (uint32)atol(idS); + + switch(type) + { + case SPELL_LINK_SPELL: + return id; + case SPELL_LINK_TALENT: + { + // talent + TalentEntry const* talentEntry = sTalentStore.LookupEntry(id); + if (!talentEntry) + return 0; + + int32 rank = param1_str ? (uint32)atol(param1_str) : 0; + if (rank >= MAX_TALENT_RANK) + return 0; + + if (rank < 0) + rank = 0; + + return talentEntry->RankID[rank]; + } + case SPELL_LINK_ENCHANT: + case SPELL_LINK_TRADE: + return id; + case SPELL_LINK_GLYPH: + { + uint32 glyph_prop_id = param1_str ? (uint32)atol(param1_str) : 0; + + GlyphPropertiesEntry const* glyphPropEntry = sGlyphPropertiesStore.LookupEntry(glyph_prop_id); + if (!glyphPropEntry) + return 0; + + return glyphPropEntry->SpellId; + } + } + + // unknown type? + return 0; +} + +GameTele const* ChatHandler::extractGameTeleFromLink(char* text) +{ + // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r + char* cId = extractKeyFromLink(text,"Htele"); + if (!cId) + return false; + + // id case (explicit or from shift link) + if (cId[0] >= '0' || cId[0] >= '9') + if (uint32 id = atoi(cId)) + return objmgr.GetGameTele(id); + + return objmgr.GetGameTele(cId); +} + +enum GuidLinkType +{ + SPELL_LINK_PLAYER = 0, // must be first for selection in not link case + SPELL_LINK_CREATURE = 1, + SPELL_LINK_GAMEOBJECT = 2 +}; + +static char const* const guidKeys[] = +{ + "Hplayer", + "Hcreature", + "Hgameobject", + 0 +}; + +uint64 ChatHandler::extractGuidFromLink(char* text) +{ + int type = 0; + + // |color|Hcreature:creature_guid|h[name]|h|r + // |color|Hgameobject:go_guid|h[name]|h|r + // |color|Hplayer:name|h[name]|h|r + char* idS = extractKeyFromLink(text,guidKeys,&type); + if (!idS) + return 0; + + switch(type) + { + case SPELL_LINK_PLAYER: + { + std::string name = idS; + if (!normalizePlayerName(name)) + return 0; + + if (Player* player = objmgr.GetPlayer(name.c_str())) + return player->GetGUID(); + + if (uint64 guid = objmgr.GetPlayerGUIDByName(name)) + return guid; + + return 0; + } + case SPELL_LINK_CREATURE: + { + uint32 lowguid = (uint32)atol(idS); + + if (CreatureData const* data = objmgr.GetCreatureData(lowguid)) + return MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT); + else + return 0; + } + case SPELL_LINK_GAMEOBJECT: + { + uint32 lowguid = (uint32)atol(idS); + + if (GameObjectData const* data = objmgr.GetGOData(lowguid)) + return MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_GAMEOBJECT); + else + return 0; + } + } + + // unknown type? + return 0; +} + +std::string ChatHandler::extractPlayerNameFromLink(char* text) +{ + // |color|Hplayer:name|h[name]|h|r + char* name_str = extractKeyFromLink(text,"Hplayer"); + if (!name_str) + return ""; + + std::string name = name_str; + if (!normalizePlayerName(name)) + return ""; + + return name; +} + +bool ChatHandler::extractPlayerTarget(char* args, Player** player, uint64* player_guid /*=NULL*/,std::string* player_name /*= NULL*/) +{ + if (args && *args) + { + std::string name = extractPlayerNameFromLink(args); + if (name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + Player* pl = objmgr.GetPlayer(name.c_str()); + + // if allowed player pointer + if (player) + *player = pl; + + // if need guid value from DB (in name case for check player existence) + uint64 guid = !pl && (player_guid || player_name) ? objmgr.GetPlayerGUIDByName(name) : 0; + + // if allowed player guid (if no then only online players allowed) + if (player_guid) + *player_guid = pl ? pl->GetGUID() : guid; + + if (player_name) + *player_name = pl || guid ? name : ""; + } + else + { + Player* pl = getSelectedPlayer(); + // if allowed player pointer + if (player) + *player = pl; + // if allowed player guid (if no then only online players allowed) + if (player_guid) + *player_guid = pl ? pl->GetGUID() : 0; + + if (player_name) + *player_name = pl ? pl->GetName() : ""; + } + + // some from req. data must be provided (note: name is empty if player not exist) + if ((!player || !*player) && (!player_guid || !*player_guid) && (!player_name || player_name->empty())) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +void ChatHandler::extractOptFirstArg(char* args, char** arg1, char** arg2) +{ + char* p1 = strtok(args, " "); + char* p2 = strtok(NULL, " "); + + if (!p2) + { + p2 = p1; + p1 = NULL; + } + + if (arg1) + *arg1 = p1; + + if (arg2) + *arg2 = p2; +} + +char* ChatHandler::extractQuotedArg(char* args) +{ + if (!*args) + return NULL; + + if (*args == '"') + return strtok(args+1, "\""); + else + { + char* space = strtok(args, "\""); + if (!space) + return false; + return strtok(NULL, "\""); + } +} + +bool ChatHandler::needReportToTarget(Player* chr) const +{ + Player* pl = m_session->GetPlayer(); + return pl != chr && pl->IsVisibleGloballyFor(chr); +} + +LocaleConstant ChatHandler::GetSessionDbcLocale() const +{ + return m_session->GetSessionDbcLocale(); +} + +int ChatHandler::GetSessionDbLocaleIndex() const +{ + return m_session->GetSessionDbLocaleIndex(); +} + +const char *CliHandler::GetTrinityString(int32 entry) const +{ + return objmgr.GetTrinityStringForDBCLocale(entry); +} + +bool CliHandler::isAvailable(ChatCommand const& cmd) const +{ + // skip non-console commands in console case + return cmd.AllowConsole; +} + +void CliHandler::SendSysMessage(const char *str) +{ + m_print(str); + m_print("\r\n"); +} + +std::string CliHandler::GetNameLink() const +{ + return GetTrinityString(LANG_CONSOLE_COMMAND); +} + +bool CliHandler::needReportToTarget(Player* /*chr*/) const +{ + return true; +} + +bool ChatHandler::GetPlayerGroupAndGUIDByName(const char* cname, Player* &plr, Group* &group, uint64 &guid, bool offline) +{ + plr = NULL; + guid = 0; + + if (cname) + { + std::string name = cname; + if (!name.empty()) + { + if (!normalizePlayerName(name)) + { + PSendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + plr = objmgr.GetPlayer(name.c_str()); + if (offline) + guid = objmgr.GetPlayerGUIDByName(name.c_str()); + } + } + + if (plr) + { + group = plr->GetGroup(); + if (!guid || !offline) + guid = plr->GetGUID(); + } + else + { + if (getSelectedPlayer()) + plr = getSelectedPlayer(); + else + plr = m_session->GetPlayer(); + + if (!guid || !offline) + guid = plr->GetGUID(); + group = plr->GetGroup(); + } + + return true; +} + +LocaleConstant CliHandler::GetSessionDbcLocale() const +{ + return sWorld.GetDefaultDbcLocale(); +} + +int CliHandler::GetSessionDbLocaleIndex() const +{ + return objmgr.GetDBCLocaleIndex(); +} diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h new file mode 100644 index 00000000000..58e6f6214c8 --- /dev/null +++ b/src/server/game/Chat/Chat.h @@ -0,0 +1,654 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYCORE_CHAT_H +#define TRINITYCORE_CHAT_H + +#include "SharedDefines.h" + +class ChatHandler; +class WorldSession; +class Creature; +class Player; +class Unit; +struct GameTele; + +class ChatCommand +{ + public: + const char * Name; + uint32 SecurityLevel; // function pointer required correct align (use uint32) + bool AllowConsole; + bool (ChatHandler::*Handler)(const char* args); + std::string Help; + ChatCommand * ChildCommands; +}; + +class ChatHandler +{ + public: + explicit ChatHandler(WorldSession* session) : m_session(session) {} + explicit ChatHandler(Player* player) : m_session(player->GetSession()) {} + ~ChatHandler() {} + + static void FillMessageData(WorldPacket *data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit *speaker); + + void FillMessageData(WorldPacket *data, uint8 type, uint32 language, uint64 target_guid, const char* message) + { + FillMessageData(data, m_session, type, language, NULL, target_guid, message, NULL); + } + + void FillSystemMessageData(WorldPacket *data, const char* message) + { + FillMessageData(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, 0, message); + } + + static char* LineFromMessage(char*& pos) { char* start = strtok(pos,"\n"); pos = NULL; return start; } + + // function with different implementation for chat/console + virtual const char *GetTrinityString(int32 entry) const; + virtual void SendSysMessage(const char *str); + + void SendSysMessage(int32 entry); + void PSendSysMessage(const char *format, ...) ATTR_PRINTF(2,3); + void PSendSysMessage(int32 entry, ...); + std::string PGetParseString(int32 entry, ...); + + int ParseCommands(const char* text); + + static ChatCommand* getCommandTable(); + + bool isValidChatMessage(const char* msg); + void SendGlobalSysMessage(const char *str); + protected: + explicit ChatHandler() : m_session(NULL) {} // for CLI subclass + + bool hasStringAbbr(const char* name, const char* part); + + // function with different implementation for chat/console + virtual bool isAvailable(ChatCommand const& cmd) const; + virtual std::string GetNameLink() const { return GetNameLink(m_session->GetPlayer()); } + virtual bool needReportToTarget(Player* chr) const; + virtual LocaleConstant GetSessionDbcLocale() const; + virtual int GetSessionDbLocaleIndex() const; + + bool HasLowerSecurity(Player* target, uint64 guid, bool strong = false); + bool HasLowerSecurityAccount(WorldSession* target, uint32 account, bool strong = false); + + void SendGlobalGMSysMessage(const char *str); + + static bool SetDataForCommandInTable(ChatCommand *table, const char* text, uint32 security, std::string const& help, std::string const& fullcommand); + bool ExecuteCommandInTable(ChatCommand *table, const char* text, const std::string& fullcommand); + bool ShowHelpForCommand(ChatCommand *table, const char* cmd); + bool ShowHelpForSubCommands(ChatCommand *table, char const* cmd, char const* subcmd); + + bool HandleAccountCommand(const char* args); + bool HandleAccountAddonCommand(const char* args); + bool HandleAccountCreateCommand(const char* args); + bool HandleAccountDeleteCommand(const char* args); + bool HandleAccountLockCommand(const char* args); + bool HandleAccountOnlineListCommand(const char* args); + bool HandleAccountPasswordCommand(const char* args); + bool HandleAccountSetAddonCommand(const char* args); + bool HandleAccountSetGmLevelCommand(const char* args); + bool HandleAccountSetPasswordCommand(const char* args); + + bool HandleAHBotOptionsCommand(const char * args); + bool HandleNameAnnounceCommand(const char* args); + bool HandleGMNameAnnounceCommand(const char* args); + bool HandleGMAnnounceCommand(const char* args); + bool HandleGMNotifyCommand(const char* args); + + bool HandleBanAccountCommand(const char* args); + bool HandleBanCharacterCommand(const char* args); + bool HandleBanIPCommand(const char* args); + bool HandleBanInfoAccountCommand(const char* args); + bool HandleBanInfoCharacterCommand(const char* args); + bool HandleBanInfoIPCommand(const char* args); + bool HandleBanListAccountCommand(const char* args); + bool HandleBanListCharacterCommand(const char* args); + bool HandleBanListIPCommand(const char* args); + + bool HandleCastCommand(const char *args); + bool HandleCastBackCommand(const char *args); + bool HandleCastDistCommand(const char *args); + bool HandleCastSelfCommand(const char *args); + bool HandleCastTargetCommand(const char *args); + + bool HandleCharacterCustomizeCommand(const char * args); + bool HandleCharacterDeleteCommand(const char* args); + bool HandleCharacterLevelCommand(const char* args); + bool HandleCharacterRenameCommand(const char * args); + bool HandleCharacterReputationCommand(const char* args); + bool HandleCharacterTitlesCommand(const char* args); + + bool HandleChannelSetPublic(const char *args); + + bool HandleDebugAnimCommand(const char* args); + bool HandleDebugArenaCommand(const char * args); + bool HandleDebugBattlegroundCommand(const char * args); + bool HandleDebugGetItemStateCommand(const char * args); + bool HandleDebugGetLootRecipientCommand(const char * args); + bool HandleDebugGetValueCommand(const char* args); + bool HandleDebugGetItemValueCommand(const char* args); + bool HandleDebugMod32ValueCommand(const char* args); + bool HandleDebugSetAuraStateCommand(const char * args); + bool HandleDebugSetItemValueCommand(const char * args); + bool HandleDebugItemExpireCommand(const char * args); + bool HandleDebugSetVehicleId(const char * args); + bool HandleDebugEnterVehicle(const char * args); + bool HandleDebugSetValueCommand(const char* args); + bool HandleDebugSpawnVehicle(const char * args); + bool HandleDebugSpellCheckCommand(const char* args); + bool HandleDebugUpdateCommand(const char* args); + bool HandleDebugUpdateWorldStateCommand(const char* args); + + bool HandleDebugSet32Bit(const char* args); + bool HandleDebugThreatList(const char * args); + bool HandleDebugHostileRefList(const char * args); + bool HandlePossessCommand(const char* args); + bool HandleUnPossessCommand(const char* args); + bool HandleBindSightCommand(const char* args); + bool HandleUnbindSightCommand(const char* args); + + bool HandleDebugPlayCinematicCommand(const char* args); + bool HandleDebugPlayMovieCommand(const char* args); + bool HandleDebugPlaySoundCommand(const char* args); + + bool HandleDebugSendBuyErrorCommand(const char* args); + bool HandleDebugSendChannelNotifyCommand(const char* args); + bool HandleDebugSendChatMsgCommand(const char* args); + bool HandleDebugSendEquipErrorCommand(const char* args); + bool HandleDebugSendLargePacketCommand(const char * args); + bool HandleDebugSendOpcodeCommand(const char* args); + bool HandleDebugSendPoiCommand(const char* args); + bool HandleDebugSendQuestPartyMsgCommand(const char* args); + bool HandleDebugSendQuestInvalidMsgCommand(const char* args); + bool HandleDebugSendSellErrorCommand(const char* args); + bool HandleDebugSendSetPhaseShiftCommand(const char * args); + bool HandleDebugSendSpellFailCommand(const char* args); + + bool HandleEventActiveListCommand(const char* args); + bool HandleEventStartCommand(const char* args); + bool HandleEventStopCommand(const char* args); + bool HandleEventInfoCommand(const char* args); + + bool HandleGameObjectAddCommand(const char* args); + bool HandleGameObjectDeleteCommand(const char* args); + bool HandleGOInfoCommand(const char* args); + bool HandleGameObjectMoveCommand(const char* args); + bool HandleGameObjectNearCommand(const char* args); + bool HandleGameObjectPhaseCommand(const char* args); + bool HandleGameObjectStateCommand(const char* args); + bool HandleGameObjectTargetCommand(const char* args); + bool HandleGameObjectTurnCommand(const char* args); + + bool HandleGMCommand(const char* args); + bool HandleGMChatCommand(const char* args); + bool HandleGMFlyCommand(const char* args); + bool HandleGMListFullCommand(const char* args); + bool HandleGMListIngameCommand(const char* args); + bool HandleGMVisibleCommand(const char* args); + + bool HandleGoCommand(const char* args); + bool HandleGoCreatureCommand(const char* args); + bool HandleGoGraveyardCommand(const char* args); + bool HandleGoGridCommand(const char* args); + bool HandleGoObjectCommand(const char* args); + bool HandleGoTaxinodeCommand(const char* args); + bool HandleGoTriggerCommand(const char* args); + bool HandleGoXYCommand(const char* args); + bool HandleGoXYZCommand(const char* args); + bool HandleGoZoneXYCommand(const char* args); + + bool HandleGoTicketCommand(const char* args); + + bool HandleGuildCreateCommand(const char* args); + bool HandleGuildInviteCommand(const char* args); + bool HandleGuildUninviteCommand(const char* args); + bool HandleGuildRankCommand(const char* args); + bool HandleGuildDeleteCommand(const char* args); + + bool HandleHonorAddCommand(const char* args); + bool HandleHonorAddKillCommand(const char* args); + bool HandleHonorUpdateCommand(const char* args); + + bool HandleInstanceListBindsCommand(const char* args); + bool HandleInstanceUnbindCommand(const char* args); + bool HandleInstanceStatsCommand(const char* args); + bool HandleInstanceSaveDataCommand(const char * args); + bool HandleInstanceOpenCommand(const char * args); + bool HandleInstanceCloseCommand(const char * args); + bool HandleInstanceOpenCloseCommand(const char * args, bool open); + + bool HandleLearnCommand(const char* args); + bool HandleLearnAllCommand(const char* args); + bool HandleLearnAllGMCommand(const char* args); + bool HandleLearnAllCraftsCommand(const char* args); + bool HandleLearnAllRecipesCommand(const char* args); + bool HandleLearnAllDefaultCommand(const char* args); + bool HandleLearnAllLangCommand(const char* args); + bool HandleLearnAllMyClassCommand(const char* args); + bool HandleLearnAllMyPetTalentsCommand(const char* args); + bool HandleLearnAllMySpellsCommand(const char* args); + bool HandleLearnAllMyTalentsCommand(const char* args); + + bool HandleListAurasCommand(const char * args); + bool HandleListCreatureCommand(const char* args); + bool HandleListItemCommand(const char* args); + bool HandleListObjectCommand(const char* args); + + bool HandleLookupAreaCommand(const char* args); + bool HandleLookupCreatureCommand(const char* args); + bool HandleLookupEventCommand(const char* args); + bool HandleLookupFactionCommand(const char * args); + bool HandleLookupItemCommand(const char * args); + bool HandleLookupItemSetCommand(const char * args); + bool HandleLookupObjectCommand(const char* args); + bool HandleLookupPlayerIpCommand(const char* args); + bool HandleLookupPlayerAccountCommand(const char* args); + bool HandleLookupPlayerEmailCommand(const char* args); + bool HandleLookupQuestCommand(const char* args); + bool HandleLookupSkillCommand(const char* args); + bool HandleLookupSpellCommand(const char* args); + bool HandleLookupTaxiNodeCommand(const char * args); + bool HandleLookupTeleCommand(const char * args); + bool HandleLookupMapCommand(const char* args); + bool HandleLookupTitleCommand(const char * args); + + bool HandleModifyHPCommand(const char* args); + bool HandleModifyManaCommand(const char* args); + bool HandleModifyRageCommand(const char* args); + bool HandleModifyRunicPowerCommand(const char* args); + bool HandleModifyEnergyCommand(const char* args); + bool HandleModifyMoneyCommand(const char* args); + bool HandleModifyASpeedCommand(const char* args); + bool HandleModifySpeedCommand(const char* args); + bool HandleModifyBWalkCommand(const char* args); + bool HandleModifyFlyCommand(const char* args); + bool HandleModifySwimCommand(const char* args); + bool HandleModifyScaleCommand(const char* args); + bool HandleModifyMountCommand(const char* args); + bool HandleModifyBitCommand(const char* args); + bool HandleModifyFactionCommand(const char* args); + bool HandleModifySpellCommand(const char* args); + bool HandleModifyTalentCommand (const char* args); + bool HandleModifyHonorCommand (const char* args); + bool HandleModifyRepCommand(const char* args); + bool HandleModifyArenaCommand(const char* args); + bool HandleModifyPhaseCommand(const char* args); + bool HandleModifyGenderCommand(const char* args); + + //-----------------------Npc Commands----------------------- + bool HandleNpcAddCommand(const char* args); + bool HandleNpcAddMoveCommand(const char* args); + bool HandleNpcAddVendorItemCommand(const char* args); + bool HandleNpcAllowMovementCommand(const char* args); + bool HandleNpcChangeEntryCommand(const char *args); + bool HandleNpcChangeLevelCommand(const char* args); + bool HandleNpcDeleteCommand(const char* args); + bool HandleNpcDelVendorItemCommand(const char* args); + bool HandleNpcFactionIdCommand(const char* args); + bool HandleNpcFlagCommand(const char* args); + bool HandleNpcFollowCommand(const char* args); + bool HandleNpcInfoCommand(const char* args); + bool HandleNpcMoveCommand(const char* args); + bool HandleNpcPlayEmoteCommand(const char* args); + bool HandleNpcSayCommand(const char* args); + bool HandleNpcSetDeathStateCommand(const char* args); + bool HandleNpcSetModelCommand(const char* args); + bool HandleNpcSetMoveTypeCommand(const char* args); + bool HandleNpcSetPhaseCommand(const char* args); + bool HandleNpcSpawnDistCommand(const char* args); + bool HandleNpcSpawnTimeCommand(const char* args); + bool HandleNpcTameCommand(const char* args); + bool HandleNpcTextEmoteCommand(const char* args); + bool HandleNpcUnFollowCommand(const char* args); + bool HandleNpcWhisperCommand(const char* args); + bool HandleNpcYellCommand(const char* args); + bool HandleNpcAddFormationCommand(const char* args); + bool HandleNpcSetLinkCommand(const char* args); + + //TODO: NpcCommands that needs to be fixed : + bool HandleNpcAddWeaponCommand(const char* args); + bool HandleNpcNameCommand(const char* args); + bool HandleNpcSubNameCommand(const char* args); + //---------------------------------------------------------- + + bool HandlePDumpLoadCommand(const char *args); + bool HandlePDumpWriteCommand(const char *args); + + bool HandleQuestAdd(const char * args); + bool HandleQuestRemove(const char * args); + bool HandleQuestComplete(const char * args); + + bool HandleReloadAllCommand(const char* args); + bool HandleReloadAllAchievementCommand(const char* args); + bool HandleReloadAllAreaCommand(const char* args); + bool HandleReloadAllItemCommand(const char* args); + bool HandleReloadAllLootCommand(const char* args); + bool HandleReloadAllNpcCommand(const char* args); + bool HandleReloadAllQuestCommand(const char* args); + bool HandleReloadAllScriptsCommand(const char* args); + bool HandleReloadAllEventAICommand(const char* args); + bool HandleReloadAllSpellCommand(const char* args); + bool HandleReloadAllLocalesCommand(const char* args); + + bool HandleReloadConfigCommand(const char* args); + + bool HandleReloadAccessRequirementCommand(const char* args); + bool HandleReloadAchievementCriteriaDataCommand(const char* args); + bool HandleReloadAchievementRewardCommand(const char* args); + bool HandleReloadAreaTriggerTavernCommand(const char* args); + bool HandleReloadAreaTriggerTeleportCommand(const char* args); + bool HandleReloadAutobroadcastCommand(const char* args); + bool HandleReloadEventScriptsCommand(const char* args); + bool HandleReloadEventAITextsCommand(const char* args); + bool HandleReloadEventAISummonsCommand(const char* args); + bool HandleReloadEventAIScriptsCommand(const char* args); + bool HandleReloadCommandCommand(const char* args); + bool HandleReloadCreatureTemplateCommand(const char* args); + bool HandleReloadCreatureQuestRelationsCommand(const char* args); + bool HandleReloadCreatureQuestInvRelationsCommand(const char* args); + bool HandleReloadCreatureLinkedRespawnCommand(const char* args); + bool HandleReloadDbScriptStringCommand(const char* args); + bool HandleReloadGameGraveyardZoneCommand(const char* args); + bool HandleReloadGameObjectScriptsCommand(const char* args); + bool HandleReloadGameTeleCommand(const char* args); + bool HandleReloadGossipMenuCommand(const char* args); + bool HandleReloadGossipMenuOptionCommand(const char* args); + bool HandleReloadGOQuestRelationsCommand(const char* args); + bool HandleReloadGOQuestInvRelationsCommand(const char* args); + bool HandleReloadItemEnchantementsCommand(const char* args); + bool HandleReloadLocalesAchievementRewardCommand(const char* args); + bool HandleReloadLocalesCreatureCommand(const char* args); + bool HandleReloadLocalesGameobjectCommand(const char* args); + bool HandleReloadLocalesItemCommand(const char* args); + bool HandleReloadLocalesNpcTextCommand(const char* args); + bool HandleReloadLocalesPageTextCommand(const char* args); + bool HandleReloadLocalesPointsOfInterestCommand(const char* args); + bool HandleReloadLocalesQuestCommand(const char* args); +// bool HandleReloadAuctionsCommand(const char* args); + bool HandleReloadLootTemplatesCreatureCommand(const char* args); + bool HandleReloadLootTemplatesDisenchantCommand(const char* args); + bool HandleReloadLootTemplatesFishingCommand(const char* args); + bool HandleReloadLootTemplatesGameobjectCommand(const char* args); + bool HandleReloadLootTemplatesItemCommand(const char* args); + bool HandleReloadLootTemplatesMailCommand(const char* args); + bool HandleReloadMailLevelRewardCommand(const char* args); + bool HandleReloadLootTemplatesMillingCommand(const char* args); + bool HandleReloadLootTemplatesPickpocketingCommand(const char* args); + bool HandleReloadLootTemplatesProspectingCommand(const char* args); + bool HandleReloadLootTemplatesReferenceCommand(const char* args); + bool HandleReloadLootTemplatesSkinningCommand(const char* args); + bool HandleReloadLootTemplatesSpellCommand(const char* args); + bool HandleReloadTrinityStringCommand(const char* args); + bool HandleReloadNpcGossipCommand(const char* args); + bool HandleReloadNpcTrainerCommand(const char* args); + bool HandleReloadNpcVendorCommand(const char* args); + bool HandleReloadPageTextsCommand(const char* args); + bool HandleReloadPointsOfInterestCommand(const char* args); + bool HandleReloadSpellClickSpellsCommand(const char* args); + bool HandleReloadQuestAreaTriggersCommand(const char* args); + bool HandleReloadQuestEndScriptsCommand(const char* args); + bool HandleReloadQuestStartScriptsCommand(const char* args); + bool HandleReloadQuestTemplateCommand(const char* args); + bool HandleReloadReservedNameCommand(const char*); + bool HandleReloadSkillDiscoveryTemplateCommand(const char* args); + bool HandleReloadSkillExtraItemTemplateCommand(const char* args); + bool HandleReloadSkillFishingBaseLevelCommand(const char* args); + bool HandleReloadSpellRequiredCommand(const char* args); + bool HandleReloadSpellAreaCommand(const char* args); + bool HandleReloadSpellGroupsCommand(const char* args); + bool HandleReloadSpellLearnSpellCommand(const char* args); + bool HandleReloadSpellLinkedSpellCommand(const char* args); + bool HandleReloadSpellProcEventCommand(const char* args); + bool HandleReloadSpellBonusesCommand(const char* args); + bool HandleReloadSpellScriptsCommand(const char* args); + bool HandleReloadSpellTargetPositionCommand(const char* args); + bool HandleReloadSpellThreatsCommand(const char* args); + bool HandleReloadSpellPetAurasCommand(const char* args); + bool HandleReloadSpellDisabledCommand(const char* args); + bool HandleReloadSpellGroupStackRulesCommand(const char* args); + bool HandleReloadAuctionsCommand(const char* args); + bool HandleReloadWpScriptsCommand(const char* args); + bool HandleReloadConditions(const char* args); + + bool HandleResetAchievementsCommand(const char * args); + bool HandleResetAllCommand(const char * args); + bool HandleResetHonorCommand(const char * args); + bool HandleResetLevelCommand(const char * args); + bool HandleResetSpellsCommand(const char * args); + bool HandleResetStatsCommand(const char * args); + bool HandleResetTalentsCommand(const char * args); + + bool HandleSendItemsCommand(const char* args); + bool HandleSendMailCommand(const char* args); + bool HandleSendMessageCommand(const char * args); + bool HandleSendMoneyCommand(const char* args); + + bool HandleServerCorpsesCommand(const char* args); + bool HandleServerExitCommand(const char* args); + bool HandleServerIdleRestartCommand(const char* args); + bool HandleServerIdleShutDownCommand(const char* args); + bool HandleServerInfoCommand(const char* args); + bool HandleServerMotdCommand(const char* args); + bool HandleServerPLimitCommand(const char* args); + bool HandleServerRestartCommand(const char* args); + bool HandleServerSetLogLevelCommand(const char* args); + bool HandleServerSetMotdCommand(const char* args); + bool HandleServerShutDownCommand(const char* args); + bool HandleServerShutDownCancelCommand(const char* args); + bool HandleServerSetClosedCommand(const char* args); + + bool HandleServerSetLogFileLevelCommand(const char* args); + bool HandleServerSetDiffTimeCommand(const char* args); + + bool HandleTeleCommand(const char * args); + bool HandleTeleAddCommand(const char * args); + bool HandleTeleDelCommand(const char * args); + bool HandleTeleGroupCommand(const char* args); + bool HandleTeleNameCommand(const char* args); + + bool HandleTitlesAddCommand(const char* args); + bool HandleTitlesCurrentCommand(const char* args); + bool HandleTitlesRemoveCommand(const char* args); + bool HandleTitlesSetMaskCommand(const char* args); + + bool HandleUnBanAccountCommand(const char* args); + bool HandleUnBanCharacterCommand(const char* args); + bool HandleUnBanIPCommand(const char* args); + + bool HandleWpAddCommand(const char* args); + bool HandleWpLoadPathCommand(const char* args); + bool HandleWpUnLoadPathCommand(const char* args); + bool HandleWpModifyCommand(const char* args); + bool HandleWpEventCommand(const char* args); + bool HandleWpShowCommand(const char* args); + bool HandleReloadAllPaths(const char *args); + + bool HandleHelpCommand(const char* args); + bool HandleCommandsCommand(const char* args); + bool HandleStartCommand(const char* args); + bool HandleDismountCommand(const char* args); + bool HandleSaveCommand(const char* args); + + bool HandleNamegoCommand(const char* args); + bool HandleGonameCommand(const char* args); + bool HandleGroupgoCommand(const char* args); + bool HandleRecallCommand(const char* args); + bool HandleAnnounceCommand(const char* args); + bool HandleNotifyCommand(const char* args); + bool HandleGPSCommand(const char* args); + bool HandleTaxiCheatCommand(const char* args); + bool HandleWhispersCommand(const char* args); + bool HandleModifyDrunkCommand(const char* args); + + bool HandleGUIDCommand(const char* args); + bool HandleItemMoveCommand(const char* args); + bool HandleDeMorphCommand(const char* args); + bool HandlePInfoCommand(const char* args); + bool HandleMuteCommand(const char* args); + bool HandleUnmuteCommand(const char* args); + bool HandleMovegensCommand(const char* args); + bool HandleFreezeCommand(const char *args); + bool HandleUnFreezeCommand(const char *args); + bool HandleListFreezeCommand(const char* args); + + bool HandleCooldownCommand(const char* args); + bool HandleUnLearnCommand(const char* args); + bool HandleGetDistanceCommand(const char* args); + bool HandleModifyStandStateCommand(const char* args); + bool HandleDieCommand(const char* args); + bool HandleDamageCommand(const char *args); + bool HandleReviveCommand(const char* args); + bool HandleModifyMorphCommand(const char* args); + bool HandleAuraCommand(const char* args); + bool HandleUnAuraCommand(const char* args); + bool HandleLinkGraveCommand(const char* args); + bool HandleNearGraveCommand(const char* args); + bool HandleActivateObjectCommand(const char* args); + bool HandleSpawnTransportCommand(const char* args); + bool HandleExploreCheatCommand(const char* args); + bool HandleHoverCommand(const char* args); + bool HandleWaterwalkCommand(const char* args); + bool HandleLevelUpCommand(const char* args); + bool HandleShowAreaCommand(const char* args); + bool HandleHideAreaCommand(const char* args); + bool HandleAddItemCommand(const char* args); + bool HandleAddItemSetCommand(const char* args); + bool HandlePetTpCommand(const char* args); + bool HandlePetUnlearnCommand(const char* args); + bool HandlePetLearnCommand(const char* args); + bool HandleCreatePetCommand(const char* args); + + bool HandleGroupLeaderCommand(const char* args); + bool HandleGroupDisbandCommand(const char* args); + bool HandleGroupRemoveCommand(const char* args); + + bool HandleBankCommand(const char* args); + bool HandleChangeWeather(const char* args); + bool HandleKickPlayerCommand(const char * args); + + // GM ticket command handlers + bool HandleGMTicketListCommand(const char* args); + bool HandleGMTicketListOnlineCommand(const char* args); + bool HandleGMTicketListClosedCommand(const char* args); + bool HandleGMTicketGetByIdCommand(const char* args); + bool HandleGMTicketGetByNameCommand(const char* args); + bool HandleGMTicketCloseByIdCommand(const char* args); + bool HandleGMTicketAssignToCommand(const char* args); + bool HandleGMTicketUnAssignCommand(const char* args); + bool HandleGMTicketCommentCommand(const char* args); + bool HandleGMTicketDeleteByIdCommand(const char* args); + bool HandleGMTicketReloadCommand(const char*); + + bool HandleMaxSkillCommand(const char* args); + bool HandleSetSkillCommand(const char* args); + bool HandleRespawnCommand(const char* args); + bool HandleComeToMeCommand(const char *args); + bool HandleCombatStopCommand(const char *args); + + /*bool HandleCharDeleteCommand(const char *args); + bool HandleSendMessageCommand(const char * args);*/ + + bool HandleFlushArenaPointsCommand(const char *args); + bool HandlePlayAllCommand(const char* args); + bool HandleRepairitemsCommand(const char* args); + + bool HandleTempGameObjectCommand(const char* args); + bool HandleTempAddSpwCommand(const char* args); + + //! Development Commands + + /*bool HandleQuestAdd(const char * args); + bool HandleQuestRemove(const char * args); + bool HandleQuestComplete(const char * args);*/ + + //bool HandleSet32Bit(const char* args); + bool HandleSaveAllCommand(const char* args); + + Player* getSelectedPlayer(); + Creature* getSelectedCreature(); + Unit* getSelectedUnit(); + WorldObject* getSelectedObject(); + + char* extractKeyFromLink(char* text, char const* linkType, char** something1 = NULL); + char* extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1 = NULL); + + // if args have single value then it return in arg2 and arg1 == NULL + void extractOptFirstArg(char* args, char** arg1, char** arg2); + char* extractQuotedArg(char* args); + + uint32 extractSpellIdFromLink(char* text); + uint64 extractGuidFromLink(char* text); + GameTele const* extractGameTeleFromLink(char* text); + bool GetPlayerGroupAndGUIDByName(const char* cname, Player* &plr, Group* &group, uint64 &guid, bool offline = false); + std::string extractPlayerNameFromLink(char* text); + // select by arg (name/link) or in-game selection online/offline player + bool extractPlayerTarget(char* args, Player** player, uint64* player_guid = NULL, std::string* player_name = NULL); + + std::string playerLink(std::string const& name) const { return m_session ? "|cffffffff|Hplayer:"+name+"|h["+name+"]|h|r" : name; } + std::string GetNameLink(Player* chr) const { return playerLink(chr->GetName()); } + + GameObject* GetNearbyGameObject(); + GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry); + + // Utility methods for commands + bool LookupPlayerSearchCommand(QueryResult_AutoPtr result, int32 limit); + bool HandleBanListHelper(QueryResult_AutoPtr result); + bool HandleBanHelper(BanMode mode,char const* args); + bool HandleBanInfoHelper(uint32 accountid, char const* accountname); + bool HandleUnBanHelper(BanMode mode,char const* args); + void HandleCharacterLevel(Player* player, uint64 player_guid, uint32 oldlevel, uint32 newlevel); + void HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id); + + void SetSentErrorMessage(bool val){ sentErrorMessage = val;}; + private: + WorldSession * m_session; // != NULL for chat command call and NULL for CLI command + + // common global flag + static bool load_command_table; + bool sentErrorMessage; +}; + +class CliHandler : public ChatHandler +{ + public: + typedef void Print(char const*); + explicit CliHandler(Print* zprint) : m_print(zprint) {} + + // overwrite functions + const char *GetTrinityString(int32 entry) const; + bool isAvailable(ChatCommand const& cmd) const; + void SendSysMessage(const char *str); + std::string GetNameLink() const; + bool needReportToTarget(Player* chr) const; + LocaleConstant GetSessionDbcLocale() const; + int GetSessionDbLocaleIndex() const; + + private: + Print* m_print; +}; + +char const *fmtstring(char const *format, ...); + +#endif + diff --git a/src/server/game/Chat/ChatHandler.cpp b/src/server/game/Chat/ChatHandler.cpp new file mode 100644 index 00000000000..88e2b5473a5 --- /dev/null +++ b/src/server/game/Chat/ChatHandler.cpp @@ -0,0 +1,756 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "World.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Database/DatabaseEnv.h" + +#include "CellImpl.h" +#include "Chat.h" +#include "ChannelMgr.h" +#include "GridNotifiersImpl.h" +#include "Group.h" +#include "Guild.h" +#include "Language.h" +#include "Log.h" +#include "Opcodes.h" +#include "Player.h" +#include "SpellAuras.h" +#include "SpellAuraEffects.h" +#include "Util.h" + +bool WorldSession::processChatmessageFurtherAfterSecurityChecks(std::string& msg, uint32 lang) +{ + if (lang != LANG_ADDON) + { + // strip invisible characters for non-addon messages + if (sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if (sWorld.getConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY) && GetSecurity() < SEC_MODERATOR + && !ChatHandler(this).isValidChatMessage(msg.c_str())) + { + sLog.outError("Player %s (GUID: %u) sent a chatmessage with an invalid link: %s", GetPlayer()->GetName(), + GetPlayer()->GetGUIDLow(), msg.c_str()); + if (sWorld.getConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_KICK)) + KickPlayer(); + return false; + } + } + + return true; +} + +void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data) +{ + uint32 type; + uint32 lang; + + recv_data >> type; + recv_data >> lang; + + if (type >= MAX_CHAT_MSG_TYPE) + { + sLog.outError("CHAT: Wrong message type received: %u", type); + return; + } + + //sLog.outDebug("CHAT: packet received. type %u, lang %u", type, lang); + + // prevent talking at unknown language (cheating) + LanguageDesc const* langDesc = GetLanguageDescByID(lang); + if (!langDesc) + { + SendNotification(LANG_UNKNOWN_LANGUAGE); + return; + } + if (langDesc->skill_id != 0 && !_player->HasSkill(langDesc->skill_id)) + { + // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language) + Unit::AuraEffectList const& langAuras = _player->GetAuraEffectsByType(SPELL_AURA_COMPREHEND_LANGUAGE); + bool foundAura = false; + for (Unit::AuraEffectList::const_iterator i = langAuras.begin(); i != langAuras.end(); ++i) + { + if ((*i)->GetMiscValue() == int32(lang)) + { + foundAura = true; + break; + } + } + if (!foundAura) + { + SendNotification(LANG_NOT_LEARNED_LANGUAGE); + return; + } + } + + if (lang == LANG_ADDON) + { + if (sWorld.getConfig(CONFIG_CHATLOG_ADDON)) + { + std::string msg = ""; + recv_data >> msg; + + if (msg.empty()) + { + sLog.outDebug("Player %s send empty addon msg", GetPlayer()->GetName()); + return; + } + + sLog.outChat("[ADDON] Player %s sends: %s", + GetPlayer()->GetName(), msg.c_str()); + } + + // Disabled addon channel? + if (!sWorld.getConfig(CONFIG_ADDON_CHANNEL)) + return; + } + // LANG_ADDON should not be changed nor be affected by flood control + else + { + // send in universal language if player in .gmon mode (ignore spell effects) + if (_player->isGameMaster()) + lang = LANG_UNIVERSAL; + else + { + // send in universal language in two side iteration allowed mode + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT)) + lang = LANG_UNIVERSAL; + else + { + switch(type) + { + case CHAT_MSG_PARTY: + case CHAT_MSG_RAID: + case CHAT_MSG_RAID_LEADER: + case CHAT_MSG_RAID_WARNING: + // allow two side chat at group channel if two side group allowed + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP)) + lang = LANG_UNIVERSAL; + break; + case CHAT_MSG_GUILD: + case CHAT_MSG_OFFICER: + // allow two side chat at guild channel if two side guild allowed + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD)) + lang = LANG_UNIVERSAL; + break; + } + } + + // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used) + Unit::AuraEffectList const& ModLangAuras = _player->GetAuraEffectsByType(SPELL_AURA_MOD_LANGUAGE); + if (!ModLangAuras.empty()) + lang = ModLangAuras.front()->GetMiscValue(); + } + + if (!_player->CanSpeak()) + { + std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); + SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING),timeStr.c_str()); + return; + } + + if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND) + GetPlayer()->UpdateSpeakTime(); + } + + if (GetPlayer()->HasAura(1852) && type != CHAT_MSG_WHISPER) + { + std::string msg=""; + recv_data >> msg; + + SendNotification(GetTrinityString(LANG_GM_SILENCE), GetPlayer()->GetName()); + return; + } + + switch(type) + { + case CHAT_MSG_SAY: + case CHAT_MSG_EMOTE: + case CHAT_MSG_YELL: + { + std::string msg; + recv_data >> msg; + + if (msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + if (_player->getLevel() < sWorld.getConfig(CONFIG_CHAT_SAY_LEVEL_REQ)) + { + SendNotification(GetTrinityString(LANG_SAY_REQ), sWorld.getConfig(CONFIG_CHAT_SAY_LEVEL_REQ)); + return; + } + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + if (type == CHAT_MSG_SAY) + GetPlayer()->Say(msg, lang); + else if (type == CHAT_MSG_EMOTE) + GetPlayer()->TextEmote(msg); + else if (type == CHAT_MSG_YELL) + GetPlayer()->Yell(msg, lang); + } break; + + case CHAT_MSG_WHISPER: + { + std::string to, msg; + recv_data >> to; + recv_data >> msg; + + if (_player->getLevel() < sWorld.getConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ)) + { + SendNotification(GetTrinityString(LANG_WHISPER_REQ), sWorld.getConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ)); + return; + } + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + if (!normalizePlayerName(to)) + { + SendPlayerNotFoundNotice(to); + break; + } + + Player *player = objmgr.GetPlayer(to.c_str()); + uint32 tSecurity = GetSecurity(); + uint32 pSecurity = player ? player->GetSession()->GetSecurity() : SEC_PLAYER; + if (!player || (tSecurity == SEC_PLAYER && pSecurity > SEC_PLAYER && !player->isAcceptWhispers())) + { + SendPlayerNotFoundNotice(to); + return; + } + + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) && tSecurity == SEC_PLAYER && pSecurity == SEC_PLAYER) + { + uint32 sidea = GetPlayer()->GetTeam(); + uint32 sideb = player->GetTeam(); + if (sidea != sideb) + { + SendWrongFactionNotice(); + return; + } + } + + if (GetPlayer()->HasAura(1852) && !player->isGameMaster()) + { + SendNotification(GetTrinityString(LANG_GM_SILENCE), GetPlayer()->GetName()); + return; + } + + GetPlayer()->Whisper(msg, lang, player->GetGUID()); + } break; + + case CHAT_MSG_PARTY: + case CHAT_MSG_PARTY_LEADER: + { + std::string msg; + recv_data >> msg; + + if (msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + // if player is in battleground, he cannot say to battleground members by /p + Group *group = GetPlayer()->GetOriginalGroup(); + if (!group) + { + group = _player->GetGroup(); + if (!group || group->isBGGroup()) + return; + } + + if ((type == CHAT_MSG_PARTY_LEADER) && !group->IsLeader(_player->GetGUID())) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, type, lang, NULL, 0, msg.c_str(), NULL); + group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetGUID())); + + if (sWorld.getConfig(CONFIG_CHATLOG_PARTY)) + sLog.outChat("[PARTY] Player %s tells group with leader %s: %s", + GetPlayer()->GetName(), group->GetLeaderName(), msg.c_str()); + } break; + + case CHAT_MSG_GUILD: + { + std::string msg; + recv_data >> msg; + + if (msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + if (GetPlayer()->GetGuildId()) + { + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + + if (guild) + guild->BroadcastToGuild(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); + + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHATLOG_GUILD)) + { + sLog.outChat("[GUILD] Player %s tells guild %s: %s", + GetPlayer()->GetName(), guild->GetName().c_str(), msg.c_str()); + } + else if (lang == LANG_ADDON && sWorld.getConfig(CONFIG_CHATLOG_ADDON)) + { + sLog.outChat("[ADDON] Player %s sends to guild %s: %s", + GetPlayer()->GetName(), guild->GetName().c_str(), msg.c_str()); + } + } + + break; + } + case CHAT_MSG_OFFICER: + { + std::string msg; + recv_data >> msg; + + if (msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + if (GetPlayer()->GetGuildId()) + { + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + + if (guild) + guild->BroadcastToOfficers(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); + + if (sWorld.getConfig(CONFIG_CHATLOG_GUILD)) + sLog.outChat("[OFFICER] Player %s tells guild %s officers: %s", + GetPlayer()->GetName(), guild->GetName().c_str(), msg.c_str()); + } + break; + } + case CHAT_MSG_RAID: + { + std::string msg; + recv_data >> msg; + + if (msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + // if player is in battleground, he cannot say to battleground members by /ra + Group *group = GetPlayer()->GetOriginalGroup(); + if (!group) + { + group = GetPlayer()->GetGroup(); + if (!group || group->isBGGroup() || !group->isRaidGroup()) + return; + } + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(), NULL); + group->BroadcastPacket(&data, false); + + if (sWorld.getConfig(CONFIG_CHATLOG_RAID)) + sLog.outChat("[RAID] Player %s tells raid with leader %s: %s", + GetPlayer()->GetName(), group->GetLeaderName(), msg.c_str()); + } break; + case CHAT_MSG_RAID_LEADER: + { + std::string msg; + recv_data >> msg; + + if (msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + // if player is in battleground, he cannot say to battleground members by /ra + Group *group = GetPlayer()->GetOriginalGroup(); + if (!group) + { + group = GetPlayer()->GetGroup(); + if (!group || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(_player->GetGUID())) + return; + } + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(), NULL); + group->BroadcastPacket(&data, false); + + if (sWorld.getConfig(CONFIG_CHATLOG_RAID)) + sLog.outChat("[RAID] Leader player %s tells raid: %s", + GetPlayer()->GetName(), msg.c_str()); + } break; + case CHAT_MSG_RAID_WARNING: + { + std::string msg; + recv_data >> msg; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + Group *group = GetPlayer()->GetGroup(); + if (!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetGUID()) || group->IsAssistant(GetPlayer()->GetGUID())) || group->isBGGroup()) + return; + + WorldPacket data; + //in battleground, raid warning is sent only to players in battleground - code is ok + ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(), NULL); + group->BroadcastPacket(&data, false); + + if (sWorld.getConfig(CONFIG_CHATLOG_RAID)) + sLog.outChat("[RAID] Leader player %s warns raid with: %s", + GetPlayer()->GetName(), msg.c_str()); + } break; + + case CHAT_MSG_BATTLEGROUND: + { + std::string msg; + recv_data >> msg; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + //battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() + Group *group = GetPlayer()->GetGroup(); + if (!group || !group->isBGGroup()) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(), NULL); + group->BroadcastPacket(&data, false); + + if (sWorld.getConfig(CONFIG_CHATLOG_BGROUND)) + sLog.outChat("[BATTLEGROUND] Player %s tells battleground with leader %s: %s", + GetPlayer()->GetName(), group->GetLeaderName(), msg.c_str()); + } break; + + case CHAT_MSG_BATTLEGROUND_LEADER: + { + std::string msg; + recv_data >> msg; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + // battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() + Group *group = GetPlayer()->GetGroup(); + if (!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetGUID())) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(), NULL); + group->BroadcastPacket(&data, false); + + if (sWorld.getConfig(CONFIG_CHATLOG_BGROUND)) + sLog.outChat("[RAID] Leader player %s tells battleground: %s", + GetPlayer()->GetName(), msg.c_str()); + } break; + + case CHAT_MSG_CHANNEL: + { + std::string channel, msg; + recv_data >> channel; + recv_data >> msg; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (_player->getLevel() < sWorld.getConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ)) + { + SendNotification(GetTrinityString(LANG_CHANNEL_REQ), sWorld.getConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ)); + return; + } + + if (msg.empty()) + break; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + { + + if (Channel *chn = cMgr->GetChannel(channel, _player)) + { + chn->Say(_player->GetGUID(), msg.c_str(), lang); + + if ((chn->HasFlag(CHANNEL_FLAG_TRADE) || + chn->HasFlag(CHANNEL_FLAG_GENERAL) || + chn->HasFlag(CHANNEL_FLAG_CITY) || + chn->HasFlag(CHANNEL_FLAG_LFG)) && + sWorld.getConfig(CONFIG_CHATLOG_SYSCHAN)) + sLog.outChat("[SYSCHAN] Player %s tells channel %s: %s", + GetPlayer()->GetName(), chn->GetName().c_str(), msg.c_str()); + else if (sWorld.getConfig(CONFIG_CHATLOG_CHANNEL)) + sLog.outChat("[CHANNEL] Player %s tells channel %s: %s", + GetPlayer()->GetName(), chn->GetName().c_str(), msg.c_str()); + } + } + } break; + + case CHAT_MSG_AFK: + { + std::string msg; + recv_data >> msg; + + if ((msg.empty() || !_player->isAFK()) && !_player->isInCombat()) + { + if (!_player->isAFK()) + { + if (msg.empty()) + msg = GetTrinityString(LANG_PLAYER_AFK_DEFAULT); + _player->afkMsg = msg; + } + _player->ToggleAFK(); + if (_player->isAFK() && _player->isDND()) + _player->ToggleDND(); + } + } break; + + case CHAT_MSG_DND: + { + std::string msg; + recv_data >> msg; + + if (msg.empty() || !_player->isDND()) + { + if (!_player->isDND()) + { + if (msg.empty()) + msg = GetTrinityString(LANG_PLAYER_DND_DEFAULT); + _player->dndMsg = msg; + } + _player->ToggleDND(); + if (_player->isDND() && _player->isAFK()) + _player->ToggleAFK(); + } + } break; + + default: + sLog.outError("CHAT: unknown message type %u, lang: %u", type, lang); + break; + } +} + +void WorldSession::HandleEmoteOpcode(WorldPacket & recv_data) +{ + if (!GetPlayer()->isAlive()) + return; + + uint32 emote; + recv_data >> emote; + GetPlayer()->HandleEmoteCommand(emote); +} + +namespace Trinity +{ + class EmoteChatBuilder + { + public: + EmoteChatBuilder(Player const& pl, uint32 text_emote, uint32 emote_num, Unit const* target) + : i_player(pl), i_text_emote(text_emote), i_emote_num(emote_num), i_target(target) {} + + void operator()(WorldPacket& data, int32 loc_idx) + { + char const* nam = i_target ? i_target->GetNameForLocaleIdx(loc_idx) : NULL; + uint32 namlen = (nam ? strlen(nam) : 0) + 1; + + data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); + data << i_player.GetGUID(); + data << (uint32)i_text_emote; + data << i_emote_num; + data << (uint32)namlen; + if (namlen > 1) + data.append(nam, namlen); + else + data << (uint8)0x00; + } + + private: + Player const& i_player; + uint32 i_text_emote; + uint32 i_emote_num; + Unit const* i_target; + }; +} // namespace Trinity + +void WorldSession::HandleTextEmoteOpcode(WorldPacket & recv_data) +{ + if (!GetPlayer()->isAlive()) + return; + + if (!GetPlayer()->CanSpeak()) + { + std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); + SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING),timeStr.c_str()); + return; + } + + uint32 text_emote, emoteNum; + uint64 guid; + + recv_data >> text_emote; + recv_data >> emoteNum; + recv_data >> guid; + + EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote); + if (!em) + return; + + uint32 emote_anim = em->textid; + + switch(emote_anim) + { + case EMOTE_STATE_SLEEP: + case EMOTE_STATE_SIT: + case EMOTE_STATE_KNEEL: + case EMOTE_ONESHOT_NONE: + break; + default: + GetPlayer()->HandleEmoteCommand(emote_anim); + break; + } + + Unit* unit = ObjectAccessor::GetUnit(*_player, guid); + + CellPair p = Trinity::ComputeCellPair(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()); + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit); + Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder > emote_do(emote_builder); + Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder > > emote_worker(GetPlayer(), sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), emote_do); + TypeContainerVisitor<Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder> >, WorldTypeMapContainer> message(emote_worker); + cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); + + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); + + //Send scripted event call + if (unit && unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI()) + ((Creature*)unit)->AI()->ReceiveEmote(GetPlayer(), text_emote); +} + +void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data) +{ + uint64 iguid; + uint8 unk; + //sLog.outDebug("WORLD: Received CMSG_CHAT_IGNORED"); + + recv_data >> iguid; + recv_data >> unk; // probably related to spam reporting + + Player *player = objmgr.GetPlayer(iguid); + if (!player || !player->GetSession()) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_IGNORED, LANG_UNIVERSAL, NULL, GetPlayer()->GetGUID(), GetPlayer()->GetName(), NULL); + player->GetSession()->SendPacket(&data); +} + +void WorldSession::HandleChannelDeclineInvite(WorldPacket &recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); +} + +void WorldSession::SendPlayerNotFoundNotice(std::string name) +{ + WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, name.size()+1); + data << name; + SendPacket(&data); +} + +void WorldSession::SendPlayerAmbiguousNotice(std::string name) +{ + WorldPacket data(SMSG_CHAT_PLAYER_AMBIGUOUS, name.size()+1); + data << name; + SendPacket(&data); +} + +void WorldSession::SendWrongFactionNotice() +{ + WorldPacket data(SMSG_CHAT_WRONG_FACTION, 0); + SendPacket(&data); +} + +void WorldSession::SendChatRestrictedNotice(ChatRestrictionType restriction) +{ + WorldPacket data(SMSG_CHAT_RESTRICTED, 1); + data << uint8(restriction); + SendPacket(&data); +} diff --git a/src/server/game/Chat/Debugcmds.cpp b/src/server/game/Chat/Debugcmds.cpp new file mode 100644 index 00000000000..ee8c623c3d0 --- /dev/null +++ b/src/server/game/Chat/Debugcmds.cpp @@ -0,0 +1,1127 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "Vehicle.h" +#include "Player.h" +#include "Opcodes.h" +#include "Chat.h" +#include "Log.h" +#include "Unit.h" +#include "GossipDef.h" +#include "Language.h" +#include "BattleGroundMgr.h" +#include <fstream> +#include "ObjectMgr.h" +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "SpellMgr.h" +#include "ScriptMgr.h" + +bool ChatHandler::HandleDebugSendSpellFailCommand(const char* args) +{ + if (!*args) + return false; + + char* px = strtok((char*)args, " "); + if (!px) + return false; + + uint8 failnum = (uint8)atoi(px); + if (failnum == 0 && *px != '0') + return false; + + char* p1 = strtok(NULL, " "); + uint8 failarg1 = p1 ? (uint8)atoi(p1) : 0; + + char* p2 = strtok(NULL, " "); + uint8 failarg2 = p2 ? (uint8)atoi(p2) : 0; + + WorldPacket data(SMSG_CAST_FAILED, 5); + data << uint8(0); + data << uint32(133); + data << uint8(failnum); + if (p1 || p2) + data << uint32(failarg1); + if (p2) + data << uint32(failarg2); + + m_session->SendPacket(&data); + + return true; +} + +bool ChatHandler::HandleDebugSendPoiCommand(const char* args) +{ + if (!*args) + return false; + + Player *pPlayer = m_session->GetPlayer(); + Unit* target = getSelectedUnit(); + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + return true; + } + + char* icon_text = strtok((char*)args, " "); + char* flags_text = strtok(NULL, " "); + if (!icon_text || !flags_text) + return false; + + uint32 icon = atol(icon_text); + uint32 flags = atol(flags_text); + + sLog.outDetail("Command : POI, NPC = %u, icon = %u flags = %u", target->GetGUIDLow(), icon,flags); + pPlayer->PlayerTalkClass->SendPointOfInterest(target->GetPositionX(), target->GetPositionY(), Poi_Icon(icon), flags, 30, "Test POI"); + return true; +} + +bool ChatHandler::HandleDebugSendEquipErrorCommand(const char* args) +{ + if (!*args) + return false; + + uint8 msg = atoi(args); + m_session->GetPlayer()->SendEquipError(msg, 0, 0); + return true; +} + +bool ChatHandler::HandleDebugSendSellErrorCommand(const char* args) +{ + if (!*args) + return false; + + uint8 msg = atoi(args); + m_session->GetPlayer()->SendSellError(msg, 0, 0, 0); + return true; +} + +bool ChatHandler::HandleDebugSendBuyErrorCommand(const char* args) +{ + if (!*args) + return false; + + uint8 msg = atoi(args); + m_session->GetPlayer()->SendBuyError(msg, 0, 0, 0); + return true; +} + +bool ChatHandler::HandleDebugSendOpcodeCommand(const char* /*args*/) +{ + Unit *unit = getSelectedUnit(); + Player *player = NULL; + if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) + player = m_session->GetPlayer(); + else + player = (Player*)unit; + if (!unit) unit = player; + + std::ifstream ifs("opcode.txt"); + if (ifs.bad()) + return false; + + uint32 opcode; + ifs >> opcode; + + WorldPacket data(opcode, 0); + + while (!ifs.eof()) + { + std::string type; + ifs >> type; + + if (type == "") + break; + + if (type == "uint8") + { + uint16 val1; + ifs >> val1; + data << uint8(val1); + } + else if (type == "uint16") + { + uint16 val2; + ifs >> val2; + data << val2; + } + else if (type == "uint32") + { + uint32 val3; + ifs >> val3; + data << val3; + } + else if (type == "uint64") + { + uint64 val4; + ifs >> val4; + data << val4; + } + else if (type == "float") + { + float val5; + ifs >> val5; + data << val5; + } + else if (type == "string") + { + std::string val6; + ifs >> val6; + data << val6; + } + else if (type == "appitsguid") + { + data.append(unit->GetPackGUID()); + } + else if (type == "appmyguid") + { + data.append(player->GetPackGUID()); + } + else if (type == "appgoguid") + { + GameObject *obj = GetNearbyGameObject(); + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, 0); + SetSentErrorMessage(true); + ifs.close(); + return false; + } + data.append(obj->GetPackGUID()); + } + else if (type == "goguid") + { + GameObject *obj = GetNearbyGameObject(); + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, 0); + SetSentErrorMessage(true); + ifs.close(); + return false; + } + data << uint64(obj->GetGUID()); + } + else if (type == "myguid") + { + data << uint64(player->GetGUID()); + } + else if (type == "itsguid") + { + data << uint64(unit->GetGUID()); + } + else if (type == "pos") + { + data << unit->GetPositionX(); + data << unit->GetPositionY(); + data << unit->GetPositionZ(); + } + else if (type == "mypos") + { + data << player->GetPositionX(); + data << player->GetPositionY(); + data << player->GetPositionZ(); + } + else + { + sLog.outDebug("Sending opcode: unknown type '%s'", type.c_str()); + break; + } + } + ifs.close(); + sLog.outDebug("Sending opcode %u", data.GetOpcode()); + data.hexlike(); + player->GetSession()->SendPacket(&data); + PSendSysMessage(LANG_COMMAND_OPCODESENT, data.GetOpcode(), unit->GetName()); + return true; +} + +bool ChatHandler::HandleDebugUpdateWorldStateCommand(const char* args) +{ + char* w = strtok((char*)args, " "); + char* s = strtok(NULL, " "); + + if (!w || !s) + return false; + + uint32 world = (uint32)atoi(w); + uint32 state = (uint32)atoi(s); + m_session->GetPlayer()->SendUpdateWorldState(world, state); + return true; +} + +bool ChatHandler::HandleDebugPlayCinematicCommand(const char* args) +{ + // USAGE: .debug play cinematic #cinematicid + // #cinematicid - ID decimal number from CinemaicSequences.dbc (1st column) + if (!*args) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + uint32 dwId = atoi((char*)args); + + if (!sCinematicSequencesStore.LookupEntry(dwId)) + { + PSendSysMessage(LANG_CINEMATIC_NOT_EXIST, dwId); + SetSentErrorMessage(true); + return false; + } + + m_session->GetPlayer()->SendCinematicStart(dwId); + return true; +} + +bool ChatHandler::HandleDebugPlayMovieCommand(const char* args) +{ + // USAGE: .debug play movie #movieid + // #movieid - ID decimal number from Movie.dbc (1st column) + if (!*args) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + uint32 dwId = atoi((char*)args); + + if (!sMovieStore.LookupEntry(dwId)) + { + PSendSysMessage(LANG_MOVIE_NOT_EXIST, dwId); + SetSentErrorMessage(true); + return false; + } + + m_session->GetPlayer()->SendMovieStart(dwId); + return true; +} + +//Play sound +bool ChatHandler::HandleDebugPlaySoundCommand(const char* args) +{ + // USAGE: .debug playsound #soundid + // #soundid - ID decimal number from SoundEntries.dbc (1st column) + if (!*args) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + uint32 dwSoundId = atoi((char*)args); + + if (!sSoundEntriesStore.LookupEntry(dwSoundId)) + { + PSendSysMessage(LANG_SOUND_NOT_EXIST, dwSoundId); + SetSentErrorMessage(true); + return false; + } + + Unit* unit = getSelectedUnit(); + if (!unit) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (m_session->GetPlayer()->GetSelection()) + unit->PlayDistanceSound(dwSoundId,m_session->GetPlayer()); + else + unit->PlayDirectSound(dwSoundId,m_session->GetPlayer()); + + PSendSysMessage(LANG_YOU_HEAR_SOUND, dwSoundId); + return true; +} + +//Send notification in channel +bool ChatHandler::HandleDebugSendChannelNotifyCommand(const char* args) +{ + if (!*args) + return false; + + const char *name = "test"; + uint8 code = atoi(args); + + WorldPacket data(SMSG_CHANNEL_NOTIFY, (1+10)); + data << code; // notify type + data << name; // channel name + data << uint32(0); + data << uint32(0); + m_session->SendPacket(&data); + return true; +} + +//Send notification in chat +bool ChatHandler::HandleDebugSendChatMsgCommand(const char* args) +{ + if (!*args) + return false; + + const char *msg = "testtest"; + uint8 type = atoi(args); + WorldPacket data; + ChatHandler::FillMessageData(&data, m_session, type, 0, "chan", m_session->GetPlayer()->GetGUID(), msg, m_session->GetPlayer()); + m_session->SendPacket(&data); + return true; +} + +bool ChatHandler::HandleDebugSendQuestPartyMsgCommand(const char* args) +{ + uint32 msg = atol((char*)args); + m_session->GetPlayer()->SendPushToPartyResponse(m_session->GetPlayer(), msg); + return true; +} + +bool ChatHandler::HandleDebugGetLootRecipientCommand(const char* /*args*/) +{ + Creature* target = getSelectedCreature(); + if (!target) + return false; + + PSendSysMessage("loot recipient: %s", target->hasLootRecipient()?(target->GetLootRecipient()?target->GetLootRecipient()->GetName():"offline"):"no loot recipient"); + return true; +} + +bool ChatHandler::HandleDebugSendQuestInvalidMsgCommand(const char* args) +{ + uint32 msg = atol((char*)args); + m_session->GetPlayer()->SendCanTakeQuestResponse(msg); + return true; +} + +bool ChatHandler::HandleDebugGetItemStateCommand(const char* args) +{ + if (!*args) + return false; + + std::string state_str = args; + + ItemUpdateState state = ITEM_UNCHANGED; + bool list_queue = false, check_all = false; + if (state_str == "unchanged") state = ITEM_UNCHANGED; + else if (state_str == "changed") state = ITEM_CHANGED; + else if (state_str == "new") state = ITEM_NEW; + else if (state_str == "removed") state = ITEM_REMOVED; + else if (state_str == "queue") list_queue = true; + else if (state_str == "check_all") check_all = true; + else return false; + + Player* player = getSelectedPlayer(); + if (!player) player = m_session->GetPlayer(); + + if (!list_queue && !check_all) + { + state_str = "The player has the following " + state_str + " items: "; + SendSysMessage(state_str.c_str()); + for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i) + { + if (i >= BUYBACK_SLOT_START && i < BUYBACK_SLOT_END) + continue; + + Item *item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); + if (!item) continue; + if (!item->IsBag()) + { + if (item->GetState() == state) + PSendSysMessage("bag: 255 slot: %d guid: %d owner: %d", item->GetSlot(), item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID())); + } + else + { + Bag *bag = (Bag*)item; + for (uint8 j = 0; j < bag->GetBagSize(); ++j) + { + Item* item2 = bag->GetItemByPos(j); + if (item2 && item2->GetState() == state) + PSendSysMessage("bag: 255 slot: %d guid: %d owner: %d", item2->GetSlot(), item2->GetGUIDLow(), GUID_LOPART(item2->GetOwnerGUID())); + } + } + } + } + + if (list_queue) + { + std::vector<Item *> &updateQueue = player->GetItemUpdateQueue(); + for (size_t i = 0; i < updateQueue.size(); ++i) + { + Item *item = updateQueue[i]; + if (!item) continue; + + Bag *container = item->GetContainer(); + uint8 bag_slot = container ? container->GetSlot() : uint8(INVENTORY_SLOT_BAG_0); + + std::string st; + switch(item->GetState()) + { + case ITEM_UNCHANGED: st = "unchanged"; break; + case ITEM_CHANGED: st = "changed"; break; + case ITEM_NEW: st = "new"; break; + case ITEM_REMOVED: st = "removed"; break; + } + + PSendSysMessage("bag: %d slot: %d guid: %d - state: %s", bag_slot, item->GetSlot(), item->GetGUIDLow(), st.c_str()); + } + if (updateQueue.empty()) + PSendSysMessage("updatequeue empty"); + } + + if (check_all) + { + bool error = false; + std::vector<Item *> &updateQueue = player->GetItemUpdateQueue(); + for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i) + { + if (i >= BUYBACK_SLOT_START && i < BUYBACK_SLOT_END) + continue; + + Item *item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); + if (!item) continue; + + if (item->GetSlot() != i) + { + PSendSysMessage("item at slot %d, guid %d has an incorrect slot value: %d", i, item->GetGUIDLow(), item->GetSlot()); + error = true; continue; + } + + if (item->GetOwnerGUID() != player->GetGUID()) + { + PSendSysMessage("for the item at slot %d and itemguid %d, owner's guid (%d) and player's guid (%d) don't match!", item->GetSlot(), item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID()), player->GetGUIDLow()); + error = true; continue; + } + + if (Bag *container = item->GetContainer()) + { + PSendSysMessage("item at slot: %d guid: %d has a container (slot: %d, guid: %d) but shouldnt!", item->GetSlot(), item->GetGUIDLow(), container->GetSlot(), container->GetGUIDLow()); + error = true; continue; + } + + if (item->IsInUpdateQueue()) + { + uint16 qp = item->GetQueuePos(); + if (qp > updateQueue.size()) + { + PSendSysMessage("item at slot: %d guid: %d has a queuepos (%d) larger than the update queue size! ", item->GetSlot(), item->GetGUIDLow(), qp); + error = true; continue; + } + + if (updateQueue[qp] == NULL) + { + PSendSysMessage("item at slot: %d guid: %d has a queuepos (%d) that points to NULL in the queue!", item->GetSlot(), item->GetGUIDLow(), qp); + error = true; continue; + } + + if (updateQueue[qp] != item) + { + PSendSysMessage("item at slot: %d guid: %d has has a queuepos (%d) that points to another item in the queue (bag: %d, slot: %d, guid: %d)", item->GetSlot(), item->GetGUIDLow(), qp, updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot(), updateQueue[qp]->GetGUIDLow()); + error = true; continue; + } + } + else if (item->GetState() != ITEM_UNCHANGED) + { + PSendSysMessage("item at slot: %d guid: %d is not in queue but should be (state: %d)!", item->GetSlot(), item->GetGUIDLow(), item->GetState()); + error = true; continue; + } + + if (item->IsBag()) + { + Bag *bag = (Bag*)item; + for (uint8 j = 0; j < bag->GetBagSize(); ++j) + { + Item* item2 = bag->GetItemByPos(j); + if (!item2) continue; + + if (item2->GetSlot() != j) + { + PSendSysMessage("the item in bag %d slot %d, guid %d has an incorrect slot value: %d", bag->GetSlot(), j, item2->GetGUIDLow(), item2->GetSlot()); + error = true; continue; + } + + if (item2->GetOwnerGUID() != player->GetGUID()) + { + PSendSysMessage("for the item in bag %d at slot %d and itemguid %d, owner's guid (%d) and player's guid (%d) don't match!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), GUID_LOPART(item2->GetOwnerGUID()), player->GetGUIDLow()); + error = true; continue; + } + + Bag *container = item2->GetContainer(); + if (!container) + { + PSendSysMessage("the item in bag %d at slot %d with guid %d has no container!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow()); + error = true; continue; + } + + if (container != bag) + { + PSendSysMessage("the item in bag %d at slot %d with guid %d has a different container(slot %d guid %d)!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), container->GetSlot(), container->GetGUIDLow()); + error = true; continue; + } + + if (item2->IsInUpdateQueue()) + { + uint16 qp = item2->GetQueuePos(); + if (qp > updateQueue.size()) + { + PSendSysMessage("item in bag: %d at slot: %d guid: %d has a queuepos (%d) larger than the update queue size! ", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), qp); + error = true; continue; + } + + if (updateQueue[qp] == NULL) + { + PSendSysMessage("item in bag: %d at slot: %d guid: %d has a queuepos (%d) that points to NULL in the queue!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), qp); + error = true; continue; + } + + if (updateQueue[qp] != item2) + { + PSendSysMessage("item in bag: %d at slot: %d guid: %d has has a queuepos (%d) that points to another item in the queue (bag: %d, slot: %d, guid: %d)", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), qp, updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot(), updateQueue[qp]->GetGUIDLow()); + error = true; continue; + } + } + else if (item2->GetState() != ITEM_UNCHANGED) + { + PSendSysMessage("item in bag: %d at slot: %d guid: %d is not in queue but should be (state: %d)!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), item2->GetState()); + error = true; continue; + } + } + } + } + + for (size_t i = 0; i < updateQueue.size(); ++i) + { + Item *item = updateQueue[i]; + if (!item) continue; + + if (item->GetOwnerGUID() != player->GetGUID()) + { + PSendSysMessage("queue(" SIZEFMTD "): for the an item (guid %d), the owner's guid (%d) and player's guid (%d) don't match!", i, item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID()), player->GetGUIDLow()); + error = true; continue; + } + + if (item->GetQueuePos() != i) + { + PSendSysMessage("queue(" SIZEFMTD "): for the an item (guid %d), the queuepos doesn't match it's position in the queue!", i, item->GetGUIDLow()); + error = true; continue; + } + + if (item->GetState() == ITEM_REMOVED) continue; + Item *test = player->GetItemByPos(item->GetBagSlot(), item->GetSlot()); + + if (test == NULL) + { + PSendSysMessage("queue(" SIZEFMTD "): the bag(%d) and slot(%d) values for the item with guid %d are incorrect, the player doesn't have an item at that position!", i, item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow()); + error = true; continue; + } + + if (test != item) + { + PSendSysMessage("queue(" SIZEFMTD "): the bag(%d) and slot(%d) values for the item with guid %d are incorrect, the item with guid %d is there instead!", i, item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow(), test->GetGUIDLow()); + error = true; continue; + } + } + if (!error) + SendSysMessage("All OK!"); + } + + return true; +} + +bool ChatHandler::HandleDebugBattlegroundCommand(const char * /*args*/) +{ + sBattleGroundMgr.ToggleTesting(); + return true; +} + +bool ChatHandler::HandleDebugArenaCommand(const char * /*args*/) +{ + sBattleGroundMgr.ToggleArenaTesting(); + return true; +} + +bool ChatHandler::HandleDebugThreatList(const char * /*args*/) +{ + Creature* target = getSelectedCreature(); + if (!target || target->isTotem() || target->isPet()) + return false; + + std::list<HostileReference*>& tlist = target->getThreatManager().getThreatList(); + std::list<HostileReference*>::iterator itr; + uint32 cnt = 0; + PSendSysMessage("Threat list of %s (guid %u)",target->GetName(), target->GetGUIDLow()); + for (itr = tlist.begin(); itr != tlist.end(); ++itr) + { + Unit* unit = (*itr)->getTarget(); + if (!unit) + continue; + ++cnt; + PSendSysMessage(" %u. %s (guid %u) - threat %f",cnt,unit->GetName(), unit->GetGUIDLow(), (*itr)->getThreat()); + } + SendSysMessage("End of threat list."); + return true; +} + +bool ChatHandler::HandleDebugHostileRefList(const char * /*args*/) +{ + Unit* target = getSelectedUnit(); + if (!target) + target = m_session->GetPlayer(); + HostileReference* ref = target->getHostileRefManager().getFirst(); + uint32 cnt = 0; + PSendSysMessage("Hostil reference list of %s (guid %u)",target->GetName(), target->GetGUIDLow()); + while (ref) + { + if (Unit * unit = ref->getSource()->getOwner()) + { + ++cnt; + PSendSysMessage(" %u. %s (guid %u) - threat %f",cnt,unit->GetName(), unit->GetGUIDLow(), ref->getThreat()); + } + ref = ref->next(); + } + SendSysMessage("End of hostil reference list."); + return true; +} + +bool ChatHandler::HandleDebugSetVehicleId(const char *args) +{ + Unit* target = getSelectedUnit(); + if (!target || target->IsVehicle()) + return false; + + if (!args) + return false; + + char* i = strtok((char*)args, " "); + if (!i) + return false; + + uint32 id = (uint32)atoi(i); + //target->SetVehicleId(id); + PSendSysMessage("Vehicle id set to %u", id); + return true; +} + +bool ChatHandler::HandleDebugEnterVehicle(const char * args) +{ + Unit* target = getSelectedUnit(); + if (!target || !target->IsVehicle()) + return false; + + if (!args) + return false; + + char* i = strtok((char*)args, " "); + if (!i) + return false; + + char* j = strtok(NULL, " "); + + uint32 entry = (uint32)atoi(i); + int8 seatId = j ? (int8)atoi(j) : -1; + + if (!entry) + m_session->GetPlayer()->EnterVehicle(target, seatId); + else + { + Creature *passenger = NULL; + Trinity::AllCreaturesOfEntryInRange check(m_session->GetPlayer(), entry, 20.0f); + Trinity::CreatureSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(m_session->GetPlayer(), passenger, check); + m_session->GetPlayer()->VisitNearbyObject(30.0f, searcher); + if (!passenger || passenger == target) + return false; + passenger->EnterVehicle(target, seatId); + } + + PSendSysMessage("Unit %u entered vehicle %d", entry, (int32)seatId); + return true; +} + +bool ChatHandler::HandleDebugSpawnVehicle(const char* args) +{ + if (!*args) + return false; + + char* e = strtok((char*)args, " "); + char* i = strtok(NULL, " "); + + if (!e) + return false; + + uint32 entry = (uint32)atoi(e); + + float x, y, z, o = m_session->GetPlayer()->GetOrientation(); + m_session->GetPlayer()->GetClosePoint(x, y, z, m_session->GetPlayer()->GetObjectSize()); + + if (!i) + return m_session->GetPlayer()->SummonCreature(entry, x, y, z, o); + + uint32 id = (uint32)atoi(i); + + CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry); + + if (!ci) + return false; + + VehicleEntry const *ve = sVehicleStore.LookupEntry(id); + + if (!ve) + return false; + + Creature *v = new Creature; + + Map *map = m_session->GetPlayer()->GetMap(); + + if (!v->Create(objmgr.GenerateLowGuid(HIGHGUID_VEHICLE), map, m_session->GetPlayer()->GetPhaseMask(), entry, id, m_session->GetPlayer()->GetTeam(), x, y, z, o)) + { + delete v; + return false; + } + + map->Add(v->ToCreature()); + + return true; +} + +bool ChatHandler::HandleDebugSendLargePacketCommand(const char* /*args*/) +{ + const char* stuffingString = "This is a dummy string to push the packet's size beyond 128000 bytes. "; + std::ostringstream ss; + while (ss.str().size() < 128000) + ss << stuffingString; + SendSysMessage(ss.str().c_str()); + return true; +} + +bool ChatHandler::HandleDebugSendSetPhaseShiftCommand(const char* args) +{ + if (!*args) + return false; + + uint32 PhaseShift = atoi(args); + m_session->SendSetPhaseShift(PhaseShift); + return true; +} + +bool ChatHandler::HandleDebugGetItemValueCommand(const char* args) +{ + if (!*args) + return false; + + char* e = strtok((char*)args, " "); + char* f = strtok(NULL, " "); + + if (!e || !f) + return false; + + uint32 guid = (uint32)atoi(e); + uint32 index = (uint32)atoi(f); + + Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM)); + + if (!i) + return false; + + if (index >= i->GetValuesCount()) + return false; + + uint32 value = i->GetUInt32Value(index); + + PSendSysMessage("Item %u: value at %u is %u", guid, index, value); + + return true; +} + +bool ChatHandler::HandleDebugSetItemValueCommand(const char* args) +{ + if (!*args) + return false; + + char* e = strtok((char*)args, " "); + char* f = strtok(NULL, " "); + char* g = strtok(NULL, " "); + + if (!e || !f || !g) + return false; + + uint32 guid = (uint32)atoi(e); + uint32 index = (uint32)atoi(f); + uint32 value = (uint32)atoi(g); + + Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM)); + + if (!i) + return false; + + if (index >= i->GetValuesCount()) + return false; + + i->SetUInt32Value(index, value); + + return true; +} + +bool ChatHandler::HandleDebugItemExpireCommand(const char* args) +{ + if (!*args) + return false; + + char* e = strtok((char*)args, " "); + if (!e) + return false; + + uint32 guid = (uint32)atoi(e); + + Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM)); + + if (!i) + return false; + + m_session->GetPlayer()->DestroyItem(i->GetBagSlot(),i->GetSlot(), true); + sScriptMgr.ItemExpire(m_session->GetPlayer(),i->GetProto()); + + return true; +} + +//show animation +bool ChatHandler::HandleDebugAnimCommand(const char* args) +{ + if (!*args) + return false; + + uint32 anim_id = atoi((char*)args); + m_session->GetPlayer()->HandleEmoteCommand(anim_id); + return true; +} + +bool ChatHandler::HandleDebugSetAuraStateCommand(const char* args) +{ + if (!*args) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Unit* unit = getSelectedUnit(); + if (!unit) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + int32 state = atoi((char*)args); + if (!state) + { + // reset all states + for (int i = 1; i <= 32; ++i) + unit->ModifyAuraState(AuraState(i),false); + return true; + } + + unit->ModifyAuraState(AuraState(abs(state)),state > 0); + return true; +} + +bool ChatHandler::HandleDebugSetValueCommand(const char* args) +{ + if (!*args) + return false; + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + + if (!px || !py) + return false; + + WorldObject* target = getSelectedObject(); + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = target->GetGUID(); + + uint32 Opcode = (uint32)atoi(px); + if (Opcode >= target->GetValuesCount()) + { + PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, GUID_LOPART(guid), target->GetValuesCount()); + return false; + } + uint32 iValue; + float fValue; + bool isint32 = true; + if (pz) + isint32 = (bool)atoi(pz); + if (isint32) + { + iValue = (uint32)atoi(py); + sLog.outDebug(GetTrinityString(LANG_SET_UINT), GUID_LOPART(guid), Opcode, iValue); + target->SetUInt32Value(Opcode , iValue); + PSendSysMessage(LANG_SET_UINT_FIELD, GUID_LOPART(guid), Opcode,iValue); + } + else + { + fValue = (float)atof(py); + sLog.outDebug(GetTrinityString(LANG_SET_FLOAT), GUID_LOPART(guid), Opcode, fValue); + target->SetFloatValue(Opcode , fValue); + PSendSysMessage(LANG_SET_FLOAT_FIELD, GUID_LOPART(guid), Opcode,fValue); + } + + return true; +} + +bool ChatHandler::HandleDebugGetValueCommand(const char* args) +{ + if (!*args) + return false; + + char* px = strtok((char*)args, " "); + char* pz = strtok(NULL, " "); + + if (!px) + return false; + + Unit* target = getSelectedUnit(); + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = target->GetGUID(); + + uint32 Opcode = (uint32)atoi(px); + if (Opcode >= target->GetValuesCount()) + { + PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, GUID_LOPART(guid), target->GetValuesCount()); + return false; + } + uint32 iValue; + float fValue; + bool isint32 = true; + if (pz) + isint32 = (bool)atoi(pz); + + if (isint32) + { + iValue = target->GetUInt32Value(Opcode); + sLog.outDebug(GetTrinityString(LANG_GET_UINT), GUID_LOPART(guid), Opcode, iValue); + PSendSysMessage(LANG_GET_UINT_FIELD, GUID_LOPART(guid), Opcode, iValue); + } + else + { + fValue = target->GetFloatValue(Opcode); + sLog.outDebug(GetTrinityString(LANG_GET_FLOAT), GUID_LOPART(guid), Opcode, fValue); + PSendSysMessage(LANG_GET_FLOAT_FIELD, GUID_LOPART(guid), Opcode, fValue); + } + + return true; +} + +bool ChatHandler::HandleDebugMod32ValueCommand(const char* args) +{ + if (!*args) + return false; + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + + if (!px || !py) + return false; + + uint32 Opcode = (uint32)atoi(px); + int Value = atoi(py); + + if (Opcode >= m_session->GetPlayer()->GetValuesCount()) + { + PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, m_session->GetPlayer()->GetGUIDLow(), m_session->GetPlayer()->GetValuesCount()); + return false; + } + + sLog.outDebug(GetTrinityString(LANG_CHANGE_32BIT), Opcode, Value); + + int CurrentValue = (int)m_session->GetPlayer()->GetUInt32Value(Opcode); + + CurrentValue += Value; + m_session->GetPlayer()->SetUInt32Value(Opcode , (uint32)CurrentValue); + + PSendSysMessage(LANG_CHANGE_32BIT_FIELD, Opcode,CurrentValue); + + return true; +} + +bool ChatHandler::HandleDebugUpdateCommand(const char* args) +{ + if (!*args) + return false; + + uint32 updateIndex; + uint32 value; + + char* pUpdateIndex = strtok((char*)args, " "); + + Unit* chr = getSelectedUnit(); + if (chr == NULL) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (!pUpdateIndex) + { + return true; + } + updateIndex = atoi(pUpdateIndex); + //check updateIndex + if (chr->GetTypeId() == TYPEID_PLAYER) + { + if (updateIndex >= PLAYER_END) return true; + } + else + { + if (updateIndex >= UNIT_END) return true; + } + + char* pvalue = strtok(NULL, " "); + if (!pvalue) + { + value=chr->GetUInt32Value(updateIndex); + + PSendSysMessage(LANG_UPDATE, chr->GetGUIDLow(),updateIndex,value); + return true; + } + + value=atoi(pvalue); + + PSendSysMessage(LANG_UPDATE_CHANGE, chr->GetGUIDLow(),updateIndex,value); + + chr->SetUInt32Value(updateIndex,value); + + return true; +} diff --git a/src/server/game/Chat/Level0.cpp b/src/server/game/Chat/Level0.cpp new file mode 100644 index 00000000000..ed021ac00d4 --- /dev/null +++ b/src/server/game/Chat/Level0.cpp @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "World.h" +#include "Player.h" +#include "Opcodes.h" +#include "Chat.h" +#include "ObjectAccessor.h" +#include "Language.h" +#include "AccountMgr.h" +#include "SystemConfig.h" +#include "revision.h" +#include "Util.h" + +bool ChatHandler::HandleHelpCommand(const char* args) +{ + char* cmd = strtok((char*)args, " "); + if (!cmd) + { + ShowHelpForCommand(getCommandTable(), "help"); + ShowHelpForCommand(getCommandTable(), ""); + } + else + { + if (!ShowHelpForCommand(getCommandTable(), cmd)) + SendSysMessage(LANG_NO_HELP_CMD); + } + + return true; +} + +bool ChatHandler::HandleCommandsCommand(const char* /*args*/) +{ + ShowHelpForCommand(getCommandTable(), ""); + return true; +} + +bool ChatHandler::HandleAccountCommand(const char* /*args*/) +{ + AccountTypes gmlevel = m_session->GetSecurity(); + PSendSysMessage(LANG_ACCOUNT_LEVEL, uint32(gmlevel)); + return true; +} + +bool ChatHandler::HandleStartCommand(const char* /*args*/) +{ + Player *chr = m_session->GetPlayer(); + + if (chr->isInFlight()) + { + SendSysMessage(LANG_YOU_IN_FLIGHT); + SetSentErrorMessage(true); + return false; + } + + if (chr->isInCombat()) + { + SendSysMessage(LANG_YOU_IN_COMBAT); + SetSentErrorMessage(true); + return false; + } + + if ((chr->isDead()) || (chr->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))) + { + // if player is dead and stuck, send ghost to graveyard + chr->RepopAtGraveyard(); + return true; + } + + // cast spell Stuck + chr->CastSpell(chr,7355,false); + return true; +} + +bool ChatHandler::HandleServerInfoCommand(const char* /*args*/) +{ + uint32 PlayersNum = sWorld.GetPlayerCount(); + uint32 MaxPlayersNum = sWorld.GetMaxPlayerCount(); + uint32 activeClientsNum = sWorld.GetActiveSessionCount(); + uint32 queuedClientsNum = sWorld.GetQueuedSessionCount(); + uint32 maxActiveClientsNum = sWorld.GetMaxActiveSessionCount(); + uint32 maxQueuedClientsNum = sWorld.GetMaxQueuedSessionCount(); + std::string uptime = secsToTimeString(sWorld.GetUptime()); + uint32 updateTime = sWorld.GetUpdateTime(); + + PSendSysMessage(_FULLVERSION); + //if (m_session) + // full = _FULLVERSION(REVISION_DATE,REVISION_TIME,"|cffffffff|Hurl:" REVISION_ID "|h" REVISION_ID "|h|r"); + //else + // full = _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_ID); + + //SendSysMessage(full); + //PSendSysMessage(LANG_USING_WORLD_DB,sWorld.GetDBVersion()); + //PSendSysMessage(LANG_USING_EVENT_AI,sWorld.GetCreatureEventAIVersion()); + PSendSysMessage(LANG_CONNECTED_PLAYERS, PlayersNum, MaxPlayersNum); + PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); + PSendSysMessage(LANG_UPTIME, uptime.c_str()); + PSendSysMessage("Update time diff: %u.", updateTime); + + return true; +} + +bool ChatHandler::HandleDismountCommand(const char* /*args*/) +{ + //If player is not mounted, so go out :) + if (!m_session->GetPlayer()->IsMounted()) + { + SendSysMessage(LANG_CHAR_NON_MOUNTED); + SetSentErrorMessage(true); + return false; + } + + if (m_session->GetPlayer()->isInFlight()) + { + SendSysMessage(LANG_YOU_IN_FLIGHT); + SetSentErrorMessage(true); + return false; + } + + m_session->GetPlayer()->Unmount(); + m_session->GetPlayer()->RemoveAurasByType(SPELL_AURA_MOUNTED); + return true; +} + +bool ChatHandler::HandleSaveCommand(const char* /*args*/) +{ + Player *player=m_session->GetPlayer(); + + // save GM account without delay and output message (testing, etc) + if (m_session->GetSecurity() > SEC_PLAYER) + { + player->SaveToDB(); + SendSysMessage(LANG_PLAYER_SAVED); + return true; + } + + // save or plan save after 20 sec (logout delay) if current next save time more this value and _not_ output any messages to prevent cheat planning + uint32 save_interval = sWorld.getConfig(CONFIG_INTERVAL_SAVE); + if ((save_interval == 0 || save_interval > 20*IN_MILISECONDS && player->GetSaveTimer() <= save_interval - 20*IN_MILISECONDS)) + player->SaveToDB(); + + return true; +} + +bool ChatHandler::HandleGMListIngameCommand(const char* /*args*/) +{ + bool first = true; + + ObjectAccessor::Guard guard(*HashMapHolder<Player>::GetLock()); + HashMapHolder<Player>::MapType &m = ObjectAccessor::Instance().GetPlayers(); + for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) + { + AccountTypes itr_sec = itr->second->GetSession()->GetSecurity(); + if ((itr->second->isGameMaster() || (itr_sec > SEC_PLAYER && itr_sec <= sWorld.getConfig(CONFIG_GM_LEVEL_IN_GM_LIST))) && + (!m_session || itr->second->IsVisibleGloballyFor(m_session->GetPlayer()))) + { + if (first) + { + SendSysMessage(LANG_GMS_ON_SRV); + first = false; + } + + SendSysMessage(GetNameLink(itr->second).c_str()); + } + } + + if (first) + SendSysMessage(LANG_GMS_NOT_LOGGED); + + return true; +} + +bool ChatHandler::HandleAccountPasswordCommand(const char* args) +{ + if (!*args) + return false; + + char *old_pass = strtok ((char*)args, " "); + char *new_pass = strtok (NULL, " "); + char *new_pass_c = strtok (NULL, " "); + + if (!old_pass || !new_pass || !new_pass_c) + return false; + + std::string password_old = old_pass; + std::string password_new = new_pass; + std::string password_new_c = new_pass_c; + + if (strcmp(new_pass, new_pass_c) != 0) + { + SendSysMessage (LANG_NEW_PASSWORDS_NOT_MATCH); + SetSentErrorMessage (true); + return false; + } + + if (!accmgr.CheckPassword (m_session->GetAccountId(), password_old)) + { + SendSysMessage (LANG_COMMAND_WRONGOLDPASSWORD); + SetSentErrorMessage (true); + return false; + } + + AccountOpResult result = accmgr.ChangePassword(m_session->GetAccountId(), password_new); + + switch(result) + { + case AOR_OK: + SendSysMessage(LANG_COMMAND_PASSWORD); + break; + case AOR_PASS_TOO_LONG: + SendSysMessage(LANG_PASSWORD_TOO_LONG); + SetSentErrorMessage(true); + return false; + case AOR_NAME_NOT_EXIST: // not possible case, don't want get account name for output + default: + SendSysMessage(LANG_COMMAND_NOTCHANGEPASSWORD); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleAccountAddonCommand(const char* args) +{ + if (!*args) + return false; + + char *szExp = strtok((char*)args," "); + + uint32 account_id = m_session->GetAccountId(); + + int expansion=atoi(szExp); //get int anyway (0 if error) + if (expansion < 0 || expansion > sWorld.getConfig(CONFIG_EXPANSION)) + return false; + + // No SQL injection + LoginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE id = '%u'", expansion, account_id); + PSendSysMessage(LANG_ACCOUNT_ADDON, expansion); + return true; +} + +bool ChatHandler::HandleAccountLockCommand(const char* args) +{ + if (!*args) + { + SendSysMessage(LANG_USE_BOL); + return true; + } + + std::string argstr = (char*)args; + if (argstr == "on") + { + LoginDatabase.PExecute("UPDATE account SET locked = '1' WHERE id = '%d'",m_session->GetAccountId()); + PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED); + return true; + } + + if (argstr == "off") + { + LoginDatabase.PExecute("UPDATE account SET locked = '0' WHERE id = '%d'",m_session->GetAccountId()); + PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED); + return true; + } + + SendSysMessage(LANG_USE_BOL); + return true; +} + +/// Display the 'Message of the day' for the realm +bool ChatHandler::HandleServerMotdCommand(const char* /*args*/) +{ + PSendSysMessage(LANG_MOTD_CURRENT, sWorld.GetMotd()); + return true; +} + diff --git a/src/server/game/Chat/Level1.cpp b/src/server/game/Chat/Level1.cpp new file mode 100644 index 00000000000..11189d519a0 --- /dev/null +++ b/src/server/game/Chat/Level1.cpp @@ -0,0 +1,2960 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "AccountMgr.h" +#include "Opcodes.h" +#include "Chat.h" +#include "Log.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "Language.h" +#include "CellImpl.h" +#include "InstanceSaveMgr.h" +#include "Util.h" + +#ifdef _DEBUG_VMAPS +#include "VMapFactory.h" +#endif + +//-----------------------Npc Commands----------------------- +bool ChatHandler::HandleNpcSayCommand(const char* args) +{ + if (!*args) + return false; + + Creature* pCreature = getSelectedCreature(); + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->MonsterSay(args, LANG_UNIVERSAL, 0); + + // make some emotes + char lastchar = args[strlen(args) - 1]; + switch(lastchar) + { + case '?': pCreature->HandleEmoteCommand(EMOTE_ONESHOT_QUESTION); break; + case '!': pCreature->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); break; + default: pCreature->HandleEmoteCommand(EMOTE_ONESHOT_TALK); break; + } + + return true; +} + +bool ChatHandler::HandleNpcYellCommand(const char* args) +{ + if (!*args) + return false; + + Creature* pCreature = getSelectedCreature(); + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->MonsterYell(args, LANG_UNIVERSAL, 0); + + // make an emote + pCreature->HandleEmoteCommand(EMOTE_ONESHOT_SHOUT); + + return true; +} + +//show text emote by creature in chat +bool ChatHandler::HandleNpcTextEmoteCommand(const char* args) +{ + if (!*args) + return false; + + Creature* pCreature = getSelectedCreature(); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->MonsterTextEmote(args, 0); + + return true; +} + +// make npc whisper to player +bool ChatHandler::HandleNpcWhisperCommand(const char* args) +{ + if (!*args) + return false; + + char* receiver_str = strtok((char*)args, " "); + char* text = strtok(NULL, ""); + + uint64 guid = m_session->GetPlayer()->GetSelection(); + Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(guid); + + if (!pCreature || !receiver_str || !text) + { + return false; + } + + uint64 receiver_guid= atol(receiver_str); + + // check online security + if (HasLowerSecurity(objmgr.GetPlayer(receiver_guid), 0)) + return false; + + pCreature->MonsterWhisper(text,receiver_guid); + + return true; +} +//---------------------------------------------------------- + +bool ChatHandler::HandleNameAnnounceCommand(const char* args) +{ + WorldPacket data; + if (!*args) + return false; + + sWorld.SendWorldText(LANG_ANNOUNCE_COLOR, m_session->GetPlayer()->GetName(), args); + return true; +} + +bool ChatHandler::HandleGMNameAnnounceCommand(const char* args) +{ + WorldPacket data; + if (!*args) + return false; + + sWorld.SendGMText(LANG_GM_ANNOUNCE_COLOR, m_session->GetPlayer()->GetName(), args); + return true; +} + +// global announce +bool ChatHandler::HandleAnnounceCommand(const char* args) +{ + if (!*args) + return false; + + sWorld.SendWorldText(LANG_SYSTEMMESSAGE,args); + return true; +} + +// announce to logged in GMs +bool ChatHandler::HandleGMAnnounceCommand(const char* args) +{ + if (!*args) + return false; + + sWorld.SendGMText(LANG_GM_BROADCAST,args); + return true; +} + +//notification player at the screen +bool ChatHandler::HandleNotifyCommand(const char* args) +{ + if (!*args) + return false; + + std::string str = GetTrinityString(LANG_GLOBAL_NOTIFY); + str += args; + + WorldPacket data(SMSG_NOTIFICATION, (str.size()+1)); + data << str; + sWorld.SendGlobalMessage(&data); + + return true; +} + +//notification GM at the screen +bool ChatHandler::HandleGMNotifyCommand(const char* args) +{ + if (!*args) + return false; + + std::string str = GetTrinityString(LANG_GM_NOTIFY); + str += args; + + WorldPacket data(SMSG_NOTIFICATION, (str.size()+1)); + data << str; + sWorld.SendGlobalGMMessage(&data); + + return true; +} + +//Enable\Dissable GM Mode +bool ChatHandler::HandleGMCommand(const char* args) +{ + if (!*args) + { + if (m_session->GetPlayer()->isGameMaster()) + m_session->SendNotification(LANG_GM_ON); + else + m_session->SendNotification(LANG_GM_OFF); + return true; + } + + std::string argstr = (char*)args; + + if (argstr == "on") + { + m_session->GetPlayer()->SetGameMaster(true); + m_session->SendNotification(LANG_GM_ON); + m_session->GetPlayer()->UpdateTriggerVisibility(); + #ifdef _DEBUG_VMAPS + VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); + vMapManager->processCommand("stoplog"); + #endif + return true; + } + + if (argstr == "off") + { + m_session->GetPlayer()->SetGameMaster(false); + m_session->SendNotification(LANG_GM_OFF); + m_session->GetPlayer()->UpdateTriggerVisibility(); + #ifdef _DEBUG_VMAPS + VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); + vMapManager->processCommand("startlog"); + #endif + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +// Enables or disables hiding of the staff badge +bool ChatHandler::HandleGMChatCommand(const char* args) +{ + if (!*args) + { + if (m_session->GetPlayer()->isGMChat()) + m_session->SendNotification(LANG_GM_CHAT_ON); + else + m_session->SendNotification(LANG_GM_CHAT_OFF); + return true; + } + + std::string argstr = (char*)args; + + if (argstr == "on") + { + m_session->GetPlayer()->SetGMChat(true); + m_session->SendNotification(LANG_GM_CHAT_ON); + return true; + } + + if (argstr == "off") + { + m_session->GetPlayer()->SetGMChat(false); + m_session->SendNotification(LANG_GM_CHAT_OFF); + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +std::string ChatHandler::PGetParseString(int32 entry, ...) +{ + const char *format = GetTrinityString(entry); + va_list ap; + char str [1024]; + va_start(ap, entry); + vsnprintf(str,1024,format, ap); + va_end(ap); + return (std::string)str; +} + +bool ChatHandler::HandleGMTicketListCommand(const char* /*args*/) +{ + SendSysMessage(LANG_COMMAND_TICKETSHOWLIST); + for (GmTicketList::iterator itr = objmgr.m_GMTicketList.begin(); itr != objmgr.m_GMTicketList.end(); ++itr) + { + if ((*itr)->closed != 0) + continue; + std::string gmname; + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str()); + if (objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname)) + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + } + SendSysMessage(ss.str().c_str()); + } + return true; +} + +bool ChatHandler::HandleGMTicketListOnlineCommand(const char* /*args*/) +{ + SendSysMessage(LANG_COMMAND_TICKETSHOWONLINELIST); + for (GmTicketList::iterator itr = objmgr.m_GMTicketList.begin(); itr != objmgr.m_GMTicketList.end(); ++itr) + { + if ((*itr)->closed != 0 || !objmgr.GetPlayer((*itr)->playerGuid)) + continue; + + std::string gmname; + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str()); + if (objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname)) + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + } + SendSysMessage(ss.str().c_str()); + } + return true; +} + +bool ChatHandler::HandleGMTicketListClosedCommand(const char* /*args*/) +{ + SendSysMessage(LANG_COMMAND_TICKETSHOWCLOSEDLIST); + for (GmTicketList::iterator itr = objmgr.m_GMTicketList.begin(); itr != objmgr.m_GMTicketList.end(); ++itr) + { + if ((*itr)->closed == 0) + continue; + + std::string gmname; + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str()); + if (objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname)) + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + } + SendSysMessage(ss.str().c_str()); + } + return true; +} + +bool ChatHandler::HandleGMTicketGetByIdCommand(const char* args) +{ + if (!*args) + return false; + + uint64 tguid = atoi(args); + GM_Ticket *ticket = objmgr.GetGMTicket(tguid); + if (!ticket || ticket->closed != 0) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + + std::string gmname; + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - ticket->createtime, true, false)).c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - ticket->timestamp, true, false)).c_str()); + if (objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname)) + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + } + ss << PGetParseString(LANG_COMMAND_TICKETLISTMESSAGE, ticket->message.c_str()); + if (ticket->comment != "") + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTCOMMENT, ticket->comment.c_str()); + } + SendSysMessage(ss.str().c_str()); + return true; +} + +bool ChatHandler::HandleGMTicketGetByNameCommand(const char* args) +{ + if (!*args) + return false; + + std::string name = (char*)args; + normalizePlayerName(name); + + Player *plr = objmgr.GetPlayer(name.c_str()); + if (!plr) + { + SendSysMessage(LANG_NO_PLAYERS_FOUND); + return true; + } + + GM_Ticket *ticket = objmgr.GetGMTicketByPlayer(plr->GetGUID()); + if (!ticket) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + + std::string gmname; + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - ticket->createtime, true, false)).c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - ticket->timestamp, true, false)).c_str()); + if (objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname)) + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + } + ss << PGetParseString(LANG_COMMAND_TICKETLISTMESSAGE, ticket->message.c_str()); + if (ticket->comment != "") + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTCOMMENT, ticket->comment.c_str()); + } + SendSysMessage(ss.str().c_str()); + return true; +} + +bool ChatHandler::HandleGMTicketCloseByIdCommand(const char* args) +{ + if (!*args) + return false; + + uint64 tguid = atoi(args); + GM_Ticket *ticket = objmgr.GetGMTicket(tguid); + if (!ticket || ticket->closed != 0) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + if (ticket && ticket->assignedToGM != 0 && ticket->assignedToGM != m_session->GetPlayer()->GetGUID()) + { + PSendSysMessage(LANG_COMMAND_TICKETCANNOTCLOSE, ticket->guid); + return true; + } + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETCLOSED, m_session->GetPlayer()->GetName()); + SendGlobalGMSysMessage(ss.str().c_str()); + Player *plr = objmgr.GetPlayer(ticket->playerGuid); + objmgr.RemoveGMTicket(ticket, m_session->GetPlayer()->GetGUID()); + + if (!plr || !plr->IsInWorld()) + return true; + + // send abandon ticket + WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); + data << uint32(9); + plr->GetSession()->SendPacket(&data); + return true; +} + +bool ChatHandler::HandleGMTicketAssignToCommand(const char* args) +{ + if (!*args) + return false; + + char* tguid = strtok((char*)args, " "); + uint64 ticketGuid = atoi(tguid); + char* targetgm = strtok(NULL, " "); + + if (!targetgm) + return false; + + std::string targm = targetgm; + if (!normalizePlayerName(targm)) + return false; + + Player *cplr = m_session->GetPlayer(); + GM_Ticket *ticket = objmgr.GetGMTicket(ticketGuid); + + if (!ticket || ticket->closed != 0) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + + uint64 tarGUID = objmgr.GetPlayerGUIDByName(targm.c_str()); + uint64 accid = objmgr.GetPlayerAccountIdByGUID(tarGUID); + uint32 gmlevel = accmgr.GetSecurity(accid, realmID); + + if (!tarGUID || gmlevel == SEC_PLAYER) + { + SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A); + return true; + } + + if (ticket->assignedToGM == tarGUID) + { + PSendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_B, ticket->guid); + return true; + } + + std::string gmname; + objmgr.GetPlayerNameByGUID(tarGUID, gmname); + if (ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID()) + { + PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid, gmname.c_str()); + return true; + } + + ticket->assignedToGM = tarGUID; + objmgr.AddOrUpdateGMTicket(*ticket); + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + SendGlobalGMSysMessage(ss.str().c_str()); + return true; +} + +bool ChatHandler::HandleGMTicketUnAssignCommand(const char* args) +{ + if (!*args) + return false; + + uint64 ticketGuid = atoi(args); + Player *cplr = m_session->GetPlayer(); + GM_Ticket *ticket = objmgr.GetGMTicket(ticketGuid); + + if (!ticket|| ticket->closed != 0) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + if (ticket->assignedToGM == 0) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTASSIGNED, ticket->guid); + return true; + } + + std::string gmname; + objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname); + Player *plr = objmgr.GetPlayer(ticket->assignedToGM); + if (plr && plr->IsInWorld() && plr->GetSession()->GetSecurity() > cplr->GetSession()->GetSecurity()) + { + SendSysMessage(LANG_COMMAND_TICKETUNASSIGNSECURITY); + return true; + } + + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTUNASSIGNED, cplr->GetName()); + SendGlobalGMSysMessage(ss.str().c_str()); + ticket->assignedToGM = 0; + objmgr.AddOrUpdateGMTicket(*ticket); + return true; +} + +bool ChatHandler::HandleGMTicketCommentCommand(const char* args) +{ + if (!*args) + return false; + + char* tguid = strtok((char*)args, " "); + uint64 ticketGuid = atoi(tguid); + char* comment = strtok(NULL, "\n"); + + if (!comment) + return false; + + Player *cplr = m_session->GetPlayer(); + GM_Ticket *ticket = objmgr.GetGMTicket(ticketGuid); + + if (!ticket || ticket->closed != 0) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + if (ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID()) + { + PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid); + return true; + } + + std::string gmname; + objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname); + ticket->comment = comment; + objmgr.AddOrUpdateGMTicket(*ticket); + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + if (objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname)) + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + } + ss << PGetParseString(LANG_COMMAND_TICKETLISTADDCOMMENT, cplr->GetName(), ticket->comment.c_str()); + SendGlobalGMSysMessage(ss.str().c_str()); + return true; +} + +bool ChatHandler::HandleGMTicketDeleteByIdCommand(const char* args) +{ + if (!*args) + return false; + uint64 ticketGuid = atoi(args); + GM_Ticket *ticket = objmgr.GetGMTicket(ticketGuid); + + if (!ticket) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + if (ticket->closed == 0) + { + SendSysMessage(LANG_COMMAND_TICKETCLOSEFIRST); + return true; + } + + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETDELETED, m_session->GetPlayer()->GetName()); + SendGlobalGMSysMessage(ss.str().c_str()); + Player *plr = objmgr.GetPlayer(ticket->playerGuid); + objmgr.RemoveGMTicket(ticket, -1, true); + if (plr && plr->IsInWorld()) + { + // Force abandon ticket + WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); + data << uint32(9); + plr->GetSession()->SendPacket(&data); + } + + ticket = NULL; + return true; +} + +bool ChatHandler::HandleGMTicketReloadCommand(const char*) +{ + objmgr.LoadGMTickets(); + return true; +} + +//Enable\Dissable Invisible mode +bool ChatHandler::HandleGMVisibleCommand(const char* args) +{ + if (!*args) + { + PSendSysMessage(LANG_YOU_ARE, m_session->GetPlayer()->isGMVisible() ? GetTrinityString(LANG_VISIBLE) : GetTrinityString(LANG_INVISIBLE)); + return true; + } + + std::string argstr = (char*)args; + + if (argstr == "on") + { + m_session->GetPlayer()->SetGMVisible(true); + m_session->SendNotification(LANG_INVISIBLE_VISIBLE); + return true; + } + + if (argstr == "off") + { + m_session->SendNotification(LANG_INVISIBLE_INVISIBLE); + m_session->GetPlayer()->SetGMVisible(false); + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +bool ChatHandler::HandleGPSCommand(const char* args) +{ + WorldObject *obj = NULL; + if (*args) + { + uint64 guid = extractGuidFromLink((char*)args); + if (guid) + obj = (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*m_session->GetPlayer(),guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + + if (!obj) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + } + else + { + obj = getSelectedUnit(); + + if (!obj) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + } + CellPair cell_val = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + Cell cell(cell_val); + + uint32 zone_id, area_id; + obj->GetZoneAndAreaId(zone_id,area_id); + + MapEntry const* mapEntry = sMapStore.LookupEntry(obj->GetMapId()); + AreaTableEntry const* zoneEntry = GetAreaEntryByAreaID(zone_id); + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(area_id); + + float zone_x = obj->GetPositionX(); + float zone_y = obj->GetPositionY(); + + Map2ZoneCoordinates(zone_x,zone_y,zone_id); + + Map const *map = obj->GetMap(); + float ground_z = map->GetHeight(obj->GetPositionX(), obj->GetPositionY(), MAX_HEIGHT); + float floor_z = map->GetHeight(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ()); + + GridPair p = Trinity::ComputeGridPair(obj->GetPositionX(), obj->GetPositionY()); + + int gx=63-p.x_coord; + int gy=63-p.y_coord; + + uint32 have_map = Map::ExistMap(obj->GetMapId(),gx,gy) ? 1 : 0; + uint32 have_vmap = Map::ExistVMap(obj->GetMapId(),gx,gy) ? 1 : 0; + + if(have_vmap) + { + if(map->IsOutdoors(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ())) + PSendSysMessage("You are outdoors"); + else + PSendSysMessage("You are indoor"); + } + else PSendSysMessage("no VMAP available for area info"); + + PSendSysMessage(LANG_MAP_POSITION, + obj->GetMapId(), (mapEntry ? mapEntry->name[GetSessionDbcLocale()] : "<unknown>"), + zone_id, (zoneEntry ? zoneEntry->area_name[GetSessionDbcLocale()] : "<unknown>"), + area_id, (areaEntry ? areaEntry->area_name[GetSessionDbcLocale()] : "<unknown>"), + obj->GetPhaseMask(), + obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(), + cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(), + zone_x, zone_y, ground_z, floor_z, have_map, have_vmap); + + sLog.outDebug("Player %s GPS call for %s '%s' (%s: %u):", + m_session ? GetNameLink().c_str() : GetTrinityString(LANG_CONSOLE_COMMAND), + (obj->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), obj->GetName(), + (obj->GetTypeId() == TYPEID_PLAYER ? "GUID" : "Entry"), (obj->GetTypeId() == TYPEID_PLAYER ? obj->GetGUIDLow(): obj->GetEntry())); + sLog.outDebug(GetTrinityString(LANG_MAP_POSITION), + obj->GetMapId(), (mapEntry ? mapEntry->name[sWorld.GetDefaultDbcLocale()] : "<unknown>"), + zone_id, (zoneEntry ? zoneEntry->area_name[sWorld.GetDefaultDbcLocale()] : "<unknown>"), + area_id, (areaEntry ? areaEntry->area_name[sWorld.GetDefaultDbcLocale()] : "<unknown>"), + obj->GetPhaseMask(), + obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(), + cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(), + zone_x, zone_y, ground_z, floor_z, have_map, have_vmap); + + LiquidData liquid_status; + ZLiquidStatus res = map->getLiquidStatus(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), MAP_ALL_LIQUIDS, &liquid_status); + if (res) + { + PSendSysMessage(LANG_LIQUID_STATUS, liquid_status.level, liquid_status.depth_level, liquid_status.type, res); + } + return true; +} + +//Summon Player +bool ChatHandler::HandleNamegoCommand(const char* args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + Player* _player = m_session->GetPlayer(); + if (target == _player || target_guid == _player->GetGUID()) + { + PSendSysMessage(LANG_CANT_TELEPORT_SELF); + SetSentErrorMessage(true); + return false; + } + + if (target) + { + std::string nameLink = playerLink(target_name); + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + if (target->IsBeingTeleported()) + { + PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + Map* pMap = m_session->GetPlayer()->GetMap(); + + if (pMap->IsBattleGroundOrArena()) + { + // only allow if gm mode is on + if (!target->isGameMaster()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,nameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + // if both players are in different bgs + else if (target->GetBattleGroundId() && m_session->GetPlayer()->GetBattleGroundId() != target->GetBattleGroundId()) + { + target->LeaveBattleground(false); // Note: should be changed so target gets no Deserter debuff + //PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,nameLink.c_str()); + //SetSentErrorMessage(true); + //return false; + } + // all's well, set bg id + // when porting out from the bg, it will be reset to 0 + target->SetBattleGroundId(m_session->GetPlayer()->GetBattleGroundId(), m_session->GetPlayer()->GetBattleGroundTypeId()); + // remember current position as entry point for return at bg end teleportation + if (!target->GetMap()->IsBattleGroundOrArena()) + target->SetBattleGroundEntryPoint(); + } + else if (pMap->IsDungeon()) + { + Map* cMap = target->GetMap(); + if (cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId()) + { + target->UnbindInstance(pMap->GetInstanceId(), target->GetDungeonDifficulty(), true); + // cannot summon from instance to instance + //PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str()); + //SetSentErrorMessage(true); + //return false; + } + + // we are in instance, and can summon only player in our group with us as lead + if (!m_session->GetPlayer()->GetGroup() || !target->GetGroup() || + (target->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || + (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID())) + // the last check is a bit excessive, but let it be, just in case + { + PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),""); + if (needReportToTarget(target)) + ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, playerLink(_player->GetName()).c_str()); + + // stop flight if need + if (target->isInFlight()) + { + target->GetMotionMaster()->MovementExpired(); + target->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + target->SaveRecallPosition(); + + // before GM + float x,y,z; + m_session->GetPlayer()->GetClosePoint(x,y,z,target->GetObjectSize()); + target->TeleportTo(m_session->GetPlayer()->GetMapId(),x,y,z,target->GetOrientation()); + target->SetPhaseMask(m_session->GetPlayer()->GetPhaseMask(), true); + } + else + { + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + return false; + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),GetTrinityString(LANG_OFFLINE)); + + // in point where GM stay + Player::SavePositionInDB(m_session->GetPlayer()->GetMapId(), + m_session->GetPlayer()->GetPositionX(), + m_session->GetPlayer()->GetPositionY(), + m_session->GetPlayer()->GetPositionZ(), + m_session->GetPlayer()->GetOrientation(), + m_session->GetPlayer()->GetZoneId(), + target_guid); + } + + return true; +} + +//Teleport to Player +bool ChatHandler::HandleGonameCommand(const char* args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + Player* _player = m_session->GetPlayer(); + if (target == _player || target_guid == _player->GetGUID()) + { + SendSysMessage(LANG_CANT_TELEPORT_SELF); + SetSentErrorMessage(true); + return false; + } + + if (target) + { + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + std::string chrNameLink = playerLink(target_name); + + Map* cMap = target->GetMap(); + if (cMap->IsBattleGroundOrArena()) + { + // only allow if gm mode is on + if (!_player->isGameMaster()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + // if both players are in different bgs + else if (_player->GetBattleGroundId() && _player->GetBattleGroundId() != target->GetBattleGroundId()) + { + _player->LeaveBattleground(false); // Note: should be changed so _player gets no Deserter debuff + //PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chrNameLink.c_str()); + //SetSentErrorMessage(true); + //return false; + } + // all's well, set bg id + // when porting out from the bg, it will be reset to 0 + _player->SetBattleGroundId(target->GetBattleGroundId(), target->GetBattleGroundTypeId()); + // remember current position as entry point for return at bg end teleportation + if (!_player->GetMap()->IsBattleGroundOrArena()) + _player->SetBattleGroundEntryPoint(); + } + else if (cMap->IsDungeon()) + { + //Map* pMap = _player->GetMap(); + + // we have to go to instance, and can go to player only if: + // 1) we are in his group (either as leader or as member) + // 2) we are not bound to any group and have GM mode on + if (_player->GetGroup()) + { + // we are in group, we can go only if we are in the player group + if (_player->GetGroup() != target->GetGroup()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_INST_PARTY,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + } + else + { + // we are not in group, let's verify our GM mode + if (!_player->isGameMaster()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_INST_GM,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + // if the player or the player's group is bound to another instance + // the player will not be bound to another one + InstancePlayerBind *pBind = _player->GetBoundInstance(target->GetMapId(), target->GetDifficulty(cMap->IsRaid())); + if (!pBind) + { + Group *group = _player->GetGroup(); + // if no bind exists, create a solo bind + InstanceGroupBind *gBind = group ? group->GetBoundInstance(target) : NULL; // if no bind exists, create a solo bind + if (!gBind) + if (InstanceSave *save = sInstanceSaveManager.GetInstanceSave(target->GetInstanceId())) + _player->BindToInstance(save, !save->CanReset()); + } + + if (cMap->IsRaid()) + _player->SetRaidDifficulty(target->GetRaidDifficulty()); + else + _player->SetDungeonDifficulty(target->GetDungeonDifficulty()); + } + + PSendSysMessage(LANG_APPEARING_AT, chrNameLink.c_str()); + //if (needReportToTarget(target)) + // ChatHandler(target).PSendSysMessage(LANG_APPEARING_TO, GetNameLink().c_str()); + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + // to point to see at target with same orientation + float x,y,z; + target->GetContactPoint(_player,x,y,z); + + _player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE); + _player->SetPhaseMask(target->GetPhaseMask(), true); + } + else + { + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + return false; + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_APPEARING_AT, nameLink.c_str()); + + // to point where player stay (if loaded) + float x,y,z,o; + uint32 map; + bool in_flight; + if (!Player::LoadPositionFromDB(map,x,y,z,o,in_flight,target_guid)) + return false; + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(map, x, y, z,_player->GetOrientation()); + } + + return true; +} + +// Teleport player to last position +bool ChatHandler::HandleRecallCommand(const char* args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + if (target->IsBeingTeleported()) + { + PSendSysMessage(LANG_IS_TELEPORTED, GetNameLink(target).c_str()); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (target->isInFlight()) + { + target->GetMotionMaster()->MovementExpired(); + target->CleanupAfterTaxiFlight(); + } + + target->TeleportTo(target->m_recallMap, target->m_recallX, target->m_recallY, target->m_recallZ, target->m_recallO); + return true; +} + +//Edit Player HP +bool ChatHandler::HandleModifyHPCommand(const char* args) +{ + if (!*args) + return false; + + int32 hp = atoi((char*)args); + int32 hpm = atoi((char*)args); + + if (hp < 1 || hpm < 1 || hpm < hp) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_HP, GetNameLink(chr).c_str(), hp, hpm); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_HP_CHANGED, GetNameLink().c_str(), hp, hpm); + + chr->SetMaxHealth(hpm); + chr->SetHealth(hp); + + return true; +} + +//Edit Player Mana +bool ChatHandler::HandleModifyManaCommand(const char* args) +{ + if (!*args) + return false; + + // char* pmana = strtok((char*)args, " "); + // if (!pmana) + // return false; + + // char* pmanaMax = strtok(NULL, " "); + // if (!pmanaMax) + // return false; + + // int32 manam = atoi(pmanaMax); + // int32 mana = atoi(pmana); + int32 mana = atoi((char*)args); + int32 manam = atoi((char*)args); + + if (mana <= 0 || manam <= 0 || manam < mana) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_MANA, GetNameLink(chr).c_str(), mana, manam); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MANA_CHANGED, GetNameLink().c_str(), mana, manam); + + chr->SetMaxPower(POWER_MANA,manam); + chr->SetPower(POWER_MANA, mana); + + return true; +} + +//Edit Player Energy +bool ChatHandler::HandleModifyEnergyCommand(const char* args) +{ + if (!*args) + return false; + + // char* pmana = strtok((char*)args, " "); + // if (!pmana) + // return false; + + // char* pmanaMax = strtok(NULL, " "); + // if (!pmanaMax) + // return false; + + // int32 manam = atoi(pmanaMax); + // int32 mana = atoi(pmana); + + int32 energy = atoi((char*)args)*10; + int32 energym = atoi((char*)args)*10; + + if (energy <= 0 || energym <= 0 || energym < energy) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (!chr) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_ENERGY, GetNameLink(chr).c_str(), energy/10, energym/10); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, GetNameLink().c_str(), energy/10, energym/10); + + chr->SetMaxPower(POWER_ENERGY,energym); + chr->SetPower(POWER_ENERGY, energy); + + sLog.outDetail(GetTrinityString(LANG_CURRENT_ENERGY),chr->GetMaxPower(POWER_ENERGY)); + + return true; +} + +//Edit Player Rage +bool ChatHandler::HandleModifyRageCommand(const char* args) +{ + if (!*args) + return false; + + // char* pmana = strtok((char*)args, " "); + // if (!pmana) + // return false; + + // char* pmanaMax = strtok(NULL, " "); + // if (!pmanaMax) + // return false; + + // int32 manam = atoi(pmanaMax); + // int32 mana = atoi(pmana); + + int32 rage = atoi((char*)args)*10; + int32 ragem = atoi((char*)args)*10; + + if (rage <= 0 || ragem <= 0 || ragem < rage) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_RAGE, GetNameLink(chr).c_str(), rage/10, ragem/10); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_RAGE_CHANGED, GetNameLink().c_str(), rage/10, ragem/10); + + chr->SetMaxPower(POWER_RAGE,ragem); + chr->SetPower(POWER_RAGE, rage); + + return true; +} + +// Edit Player Runic Power +bool ChatHandler::HandleModifyRunicPowerCommand(const char* args) +{ + if (!*args) + return false; + + int32 rune = atoi((char*)args)*10; + int32 runem = atoi((char*)args)*10; + + if (rune <= 0 || runem <= 0 || runem < rune) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_RUNIC_POWER, GetNameLink(chr).c_str(), rune/10, runem/10); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_RUNIC_POWER_CHANGED, GetNameLink().c_str(), rune/10, runem/10); + + chr->SetMaxPower(POWER_RUNIC_POWER,runem); + chr->SetPower(POWER_RUNIC_POWER, rune); + + return true; +} + +//Edit Player Faction +bool ChatHandler::HandleModifyFactionCommand(const char* args) +{ + if (!*args) + return false; + + char* pfactionid = extractKeyFromLink((char*)args,"Hfaction"); + + Creature* chr = getSelectedCreature(); + if (!chr) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (!pfactionid) + { + if (chr) + { + uint32 factionid = chr->getFaction(); + uint32 flag = chr->GetUInt32Value(UNIT_FIELD_FLAGS); + uint32 npcflag = chr->GetUInt32Value(UNIT_NPC_FLAGS); + uint32 dyflag = chr->GetUInt32Value(UNIT_DYNAMIC_FLAGS); + PSendSysMessage(LANG_CURRENT_FACTION,chr->GetGUIDLow(),factionid,flag,npcflag,dyflag); + } + return true; + } + + if (!chr) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + uint32 factionid = atoi(pfactionid); + uint32 flag; + + char *pflag = strtok(NULL, " "); + if (!pflag) + flag = chr->GetUInt32Value(UNIT_FIELD_FLAGS); + else + flag = atoi(pflag); + + char* pnpcflag = strtok(NULL, " "); + + uint32 npcflag; + if (!pnpcflag) + npcflag = chr->GetUInt32Value(UNIT_NPC_FLAGS); + else + npcflag = atoi(pnpcflag); + + char* pdyflag = strtok(NULL, " "); + + uint32 dyflag; + if (!pdyflag) + dyflag = chr->GetUInt32Value(UNIT_DYNAMIC_FLAGS); + else + dyflag = atoi(pdyflag); + + if (!sFactionTemplateStore.LookupEntry(factionid)) + { + PSendSysMessage(LANG_WRONG_FACTION, factionid); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_FACTION, chr->GetGUIDLow(),factionid,flag,npcflag,dyflag); + + chr->setFaction(factionid); + chr->SetUInt32Value(UNIT_FIELD_FLAGS,flag); + chr->SetUInt32Value(UNIT_NPC_FLAGS,npcflag); + chr->SetUInt32Value(UNIT_DYNAMIC_FLAGS,dyflag); + + return true; +} + +//Edit Player Spell +bool ChatHandler::HandleModifySpellCommand(const char* args) +{ + if (!*args) return false; + char* pspellflatid = strtok((char*)args, " "); + if (!pspellflatid) + return false; + + char* pop = strtok(NULL, " "); + if (!pop) + return false; + + char* pval = strtok(NULL, " "); + if (!pval) + return false; + + uint16 mark; + + char* pmark = strtok(NULL, " "); + + uint8 spellflatid = atoi(pspellflatid); + uint8 op = atoi(pop); + uint16 val = atoi(pval); + if (!pmark) + mark = 65535; + else + mark = atoi(pmark); + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_SPELLFLATID, spellflatid, val, mark, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLFLATID_CHANGED, GetNameLink().c_str(), spellflatid, val, mark); + + WorldPacket data(SMSG_SET_FLAT_SPELL_MODIFIER, (1+1+2+2)); + data << uint8(spellflatid); + data << uint8(op); + data << uint16(val); + data << uint16(mark); + chr->GetSession()->SendPacket(&data); + + return true; +} + +//Edit Player TP +bool ChatHandler::HandleModifyTalentCommand (const char* args) +{ + if (!*args) + return false; + + int tp = atoi((char*)args); + if (tp < 0) + return false; + + Unit* target = getSelectedUnit(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (target->GetTypeId() == TYPEID_PLAYER) + { + // check online security + if (HasLowerSecurity((Player*)target, 0)) + return false; + target->ToPlayer()->SetFreeTalentPoints(tp); + target->ToPlayer()->SendTalentsInfoData(false); + return true; + } + else if (target->ToCreature()->isPet()) + { + Unit *owner = target->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet *)target)->IsPermanentPetFor(owner->ToPlayer())) + { + // check online security + if (HasLowerSecurity((Player*)owner, 0)) + return false; + ((Pet *)target)->SetFreeTalentPoints(tp); + owner->ToPlayer()->SendTalentsInfoData(true); + return true; + } + } + + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; +} + +//Enable On\OFF all taxi paths +bool ChatHandler::HandleTaxiCheatCommand(const char* args) +{ + if (!*args) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + std::string argstr = (char*)args; + + Player *chr = getSelectedPlayer(); + if (!chr) + { + chr=m_session->GetPlayer(); + } + + // check online security + else if (HasLowerSecurity(chr, 0)) + return false; + + if (argstr == "on") + { + chr->SetTaxiCheater(true); + PSendSysMessage(LANG_YOU_GIVE_TAXIS, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, GetNameLink().c_str()); + return true; + } + + if (argstr == "off") + { + chr->SetTaxiCheater(false); + PSendSysMessage(LANG_YOU_REMOVE_TAXIS, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, GetNameLink().c_str()); + + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +//Edit Player Aspeed +bool ChatHandler::HandleModifyASpeedCommand(const char* args) +{ + if (!*args) + return false; + + float ASpeed = (float)atof((char*)args); + + if (ASpeed > 50.0f || ASpeed < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = GetNameLink(chr); + + if (chr->isInFlight()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_ASPEED, ASpeed, chrNameLink.c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, GetNameLink().c_str(), ASpeed); + + chr->SetSpeed(MOVE_WALK, ASpeed,true); + chr->SetSpeed(MOVE_RUN, ASpeed,true); + chr->SetSpeed(MOVE_SWIM, ASpeed,true); + //chr->SetSpeed(MOVE_TURN, ASpeed,true); + chr->SetSpeed(MOVE_FLIGHT, ASpeed,true); + return true; +} + +//Edit Player Speed +bool ChatHandler::HandleModifySpeedCommand(const char* args) +{ + if (!*args) + return false; + + float Speed = (float)atof((char*)args); + + if (Speed > 50.0f || Speed < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = GetNameLink(chr); + + if (chr->isInFlight()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_SPEED, Speed, chrNameLink.c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, GetNameLink().c_str(), Speed); + + chr->SetSpeed(MOVE_RUN,Speed,true); + + return true; +} + +//Edit Player Swim Speed +bool ChatHandler::HandleModifySwimCommand(const char* args) +{ + if (!*args) + return false; + + float Swim = (float)atof((char*)args); + + if (Swim > 50.0f || Swim < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = GetNameLink(chr); + + if (chr->isInFlight()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, Swim, chrNameLink.c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, GetNameLink().c_str(), Swim); + + chr->SetSpeed(MOVE_SWIM,Swim,true); + + return true; +} + +//Edit Player Walk Speed +bool ChatHandler::HandleModifyBWalkCommand(const char* args) +{ + if (!*args) + return false; + + float BSpeed = (float)atof((char*)args); + + if (BSpeed > 50.0f || BSpeed < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = GetNameLink(chr); + + if (chr->isInFlight()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, BSpeed, chrNameLink.c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, GetNameLink().c_str(), BSpeed); + + chr->SetSpeed(MOVE_RUN_BACK,BSpeed,true); + + return true; +} + +//Edit Player Fly +bool ChatHandler::HandleModifyFlyCommand(const char* args) +{ + if (!*args) + return false; + + float FSpeed = (float)atof((char*)args); + + if (FSpeed > 50.0f || FSpeed < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, FSpeed, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, GetNameLink().c_str(), FSpeed); + + chr->SetSpeed(MOVE_FLIGHT,FSpeed,true); + + return true; +} + +//Edit Player Scale +bool ChatHandler::HandleModifyScaleCommand(const char* args) +{ + if (!*args) + return false; + + float Scale = (float)atof((char*)args); + if (Scale > 10.0f || Scale < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, GetNameLink().c_str(), Scale); + + chr->SetFloatValue(OBJECT_FIELD_SCALE_X, Scale); + + return true; +} + +//Enable Player mount +bool ChatHandler::HandleModifyMountCommand(const char* args) +{ + if (!*args) + return false; + + uint16 mId = 1147; + float speed = (float)15; + uint32 num = 0; + + num = atoi((char*)args); + switch(num) + { + case 1: + mId=14340; + break; + case 2: + mId=4806; + break; + case 3: + mId=6471; + break; + case 4: + mId=12345; + break; + case 5: + mId=6472; + break; + case 6: + mId=6473; + break; + case 7: + mId=10670; + break; + case 8: + mId=10719; + break; + case 9: + mId=10671; + break; + case 10: + mId=10672; + break; + case 11: + mId=10720; + break; + case 12: + mId=14349; + break; + case 13: + mId=11641; + break; + case 14: + mId=12244; + break; + case 15: + mId=12242; + break; + case 16: + mId=14578; + break; + case 17: + mId=14579; + break; + case 18: + mId=14349; + break; + case 19: + mId=12245; + break; + case 20: + mId=14335; + break; + case 21: + mId=207; + break; + case 22: + mId=2328; + break; + case 23: + mId=2327; + break; + case 24: + mId=2326; + break; + case 25: + mId=14573; + break; + case 26: + mId=14574; + break; + case 27: + mId=14575; + break; + case 28: + mId=604; + break; + case 29: + mId=1166; + break; + case 30: + mId=2402; + break; + case 31: + mId=2410; + break; + case 32: + mId=2409; + break; + case 33: + mId=2408; + break; + case 34: + mId=2405; + break; + case 35: + mId=14337; + break; + case 36: + mId=6569; + break; + case 37: + mId=10661; + break; + case 38: + mId=10666; + break; + case 39: + mId=9473; + break; + case 40: + mId=9476; + break; + case 41: + mId=9474; + break; + case 42: + mId=14374; + break; + case 43: + mId=14376; + break; + case 44: + mId=14377; + break; + case 45: + mId=2404; + break; + case 46: + mId=2784; + break; + case 47: + mId=2787; + break; + case 48: + mId=2785; + break; + case 49: + mId=2736; + break; + case 50: + mId=2786; + break; + case 51: + mId=14347; + break; + case 52: + mId=14346; + break; + case 53: + mId=14576; + break; + case 54: + mId=9695; + break; + case 55: + mId=9991; + break; + case 56: + mId=6448; + break; + case 57: + mId=6444; + break; + case 58: + mId=6080; + break; + case 59: + mId=6447; + break; + case 60: + mId=4805; + break; + case 61: + mId=9714; + break; + case 62: + mId=6448; + break; + case 63: + mId=6442; + break; + case 64: + mId=14632; + break; + case 65: + mId=14332; + break; + case 66: + mId=14331; + break; + case 67: + mId=8469; + break; + case 68: + mId=2830; + break; + case 69: + mId=2346; + break; + default: + SendSysMessage(LANG_NO_MOUNT); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_GIVE_MOUNT, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_MOUNT_GIVED, GetNameLink().c_str()); + + chr->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); + chr->Mount(mId); + + WorldPacket data(SMSG_FORCE_RUN_SPEED_CHANGE, (8+4+1+4)); + data.append(chr->GetPackGUID()); + data << (uint32)0; + data << (uint8)0; //new 2.1.0 + data << float(speed); + chr->SendMessageToSet(&data, true); + + data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, (8+4+4)); + data.append(chr->GetPackGUID()); + data << (uint32)0; + data << float(speed); + chr->SendMessageToSet(&data, true); + + return true; +} + +//Edit Player money +bool ChatHandler::HandleModifyMoneyCommand(const char* args) +{ + if (!*args) + return false; + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + int32 addmoney = atoi((char*)args); + + uint32 moneyuser = chr->GetMoney(); + + if (addmoney < 0) + { + int32 newmoney = int32(moneyuser) + addmoney; + + sLog.outDetail(GetTrinityString(LANG_CURRENT_MONEY), moneyuser, addmoney, newmoney); + if (newmoney <= 0) + { + PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ALL_MONEY_GONE, GetNameLink().c_str()); + + chr->SetMoney(0); + } + else + { + if (newmoney > MAX_MONEY_AMOUNT) + newmoney = MAX_MONEY_AMOUNT; + + PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, GetNameLink().c_str(), abs(addmoney)); + chr->SetMoney(newmoney); + } + } + else + { + PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, GetNameLink().c_str(), addmoney); + + if (addmoney >=MAX_MONEY_AMOUNT) + chr->SetMoney(MAX_MONEY_AMOUNT); + else + chr->ModifyMoney(addmoney); + } + + sLog.outDetail(GetTrinityString(LANG_NEW_MONEY), moneyuser, addmoney, chr->GetMoney()); + + return true; +} + +//Edit Unit field +bool ChatHandler::HandleModifyBitCommand(const char* args) +{ + if (!*args) + return false; + + Unit *unit = getSelectedUnit(); + if (!unit) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (unit->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity(unit->ToPlayer(), 0)) + return false; + + char* pField = strtok((char*)args, " "); + if (!pField) + return false; + + char* pBit = strtok(NULL, " "); + if (!pBit) + return false; + + uint16 field = atoi(pField); + uint32 bit = atoi(pBit); + + if (field < OBJECT_END || field >= unit->GetValuesCount()) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + if (bit < 1 || bit > 32) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + if (unit->HasFlag(field, (1<<(bit-1)))) + { + unit->RemoveFlag(field, (1<<(bit-1))); + PSendSysMessage(LANG_REMOVE_BIT, bit, field); + } + else + { + unit->SetFlag(field, (1<<(bit-1))); + PSendSysMessage(LANG_SET_BIT, bit, field); + } + return true; +} + +bool ChatHandler::HandleModifyHonorCommand (const char* args) +{ + if (!*args) + return false; + + Player *target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + int32 amount = (uint32)atoi(args); + + target->ModifyHonorPoints(amount); + + PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, GetNameLink(target).c_str(), target->GetHonorPoints()); + + return true; +} + +bool ChatHandler::HandleTeleCommand(const char * args) +{ + if (!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r + GameTele const* tele = extractGameTeleFromLink((char*)args); + + if (!tele) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + + if (_player->isInCombat()) + { + SendSysMessage(LANG_YOU_IN_COMBAT); + SetSentErrorMessage(true); + return false; + } + + MapEntry const * me = sMapStore.LookupEntry(tele->mapId); + if (!me || me->IsBattleGroundOrArena()) + { + SendSysMessage(LANG_CANNOT_TELE_TO_BG); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); + return true; +} + +bool ChatHandler::HandleLookupAreaCommand(const char* args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr (namepart,wnamepart)) + return false; + + bool found = false; + + // converting string that we try to find to lower case + wstrToLower (wnamepart); + + // Search in AreaTable.dbc + for (uint32 areaflag = 0; areaflag < sAreaStore.GetNumRows (); ++areaflag) + { + AreaTableEntry const *areaEntry = sAreaStore.LookupEntry (areaflag); + if (areaEntry) + { + int loc = GetSessionDbcLocale (); + std::string name = areaEntry->area_name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo (name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale ()) + continue; + + name = areaEntry->area_name[loc]; + if (name.empty ()) + continue; + + if (Utf8FitTo (name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + // send area in "id - [name]" format + std::ostringstream ss; + if (m_session) + ss << areaEntry->ID << " - |cffffffff|Harea:" << areaEntry->ID << "|h[" << name << " " << localeNames[loc]<< "]|h|r"; + else + ss << areaEntry->ID << " - " << name << " " << localeNames[loc]; + + SendSysMessage (ss.str ().c_str()); + + if (!found) + found = true; + } + } + } + + if (!found) + SendSysMessage (LANG_COMMAND_NOAREAFOUND); + + return true; +} + +//Find tele in game_tele order by name +bool ChatHandler::HandleLookupTeleCommand(const char * args) +{ + if (!*args) + { + SendSysMessage(LANG_COMMAND_TELE_PARAMETER); + SetSentErrorMessage(true); + return false; + } + + char const* str = strtok((char*)args, " "); + if (!str) + return false; + + std::string namepart = str; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + std::ostringstream reply; + + GameTeleMap const & teleMap = objmgr.GetGameTeleMap(); + for (GameTeleMap::const_iterator itr = teleMap.begin(); itr != teleMap.end(); ++itr) + { + GameTele const* tele = &itr->second; + + if (tele->wnameLow.find(wnamepart) == std::wstring::npos) + continue; + + if (m_session) + reply << " |cffffffff|Htele:" << itr->first << "|h[" << tele->name << "]|h|r\n"; + else + reply << " " << itr->first << " " << tele->name << "\n"; + } + + if (reply.str().empty()) + SendSysMessage(LANG_COMMAND_TELE_NOLOCATION); + else + PSendSysMessage(LANG_COMMAND_TELE_LOCATION,reply.str().c_str()); + + return true; +} + +//Enable\Dissable accept whispers (for GM) +bool ChatHandler::HandleWhispersCommand(const char* args) +{ + if (!*args) + { + PSendSysMessage(LANG_COMMAND_WHISPERACCEPTING, m_session->GetPlayer()->isAcceptWhispers() ? GetTrinityString(LANG_ON) : GetTrinityString(LANG_OFF)); + return true; + } + + std::string argstr = (char*)args; + // whisper on + if (argstr == "on") + { + m_session->GetPlayer()->SetAcceptWhispers(true); + SendSysMessage(LANG_COMMAND_WHISPERON); + return true; + } + + // whisper off + if (argstr == "off") + { + m_session->GetPlayer()->SetAcceptWhispers(false); + SendSysMessage(LANG_COMMAND_WHISPEROFF); + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +//Save all players in the world +bool ChatHandler::HandleSaveAllCommand(const char* /*args*/) +{ + ObjectAccessor::Instance().SaveAllPlayers(); + SendSysMessage(LANG_PLAYERS_SAVED); + return true; +} + +//Send mail by command +bool ChatHandler::HandleSendMailCommand(const char* args) +{ + // format: name "subject text" "mail text" + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + char* tail1 = strtok(NULL, ""); + if (!tail1) + return false; + + char* msgSubject = extractQuotedArg(tail1); + if (!msgSubject) + return false; + + char* tail2 = strtok(NULL, ""); + if (!tail2) + return false; + + char* msgText = extractQuotedArg(tail2); + if (!msgText) + return false; + + // msgSubject, msgText isn't NUL after prev. check + std::string subject = msgSubject; + std::string text = msgText; + + // from console show not existed sender + MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + + MailDraft(subject, text) + .SendMailTo(MailReceiver(target,GUID_LOPART(target_guid)),sender); + + std::string nameLink = playerLink(target_name); + PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); + return true; +} + +// teleport player to given game_tele.entry +bool ChatHandler::HandleTeleNameCommand(const char * args) +{ + char* nameStr; + char* teleStr; + extractOptFirstArg((char*)args,&nameStr,&teleStr); + if (!teleStr) + return false; + + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) + return false; + + // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r + GameTele const* tele = extractGameTeleFromLink(teleStr); + if (!tele) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + +/* MapEntry const * me = sMapStore.LookupEntry(tele->mapId); + if (!me || me->IsBattleGroundOrArena()) + { + SendSysMessage(LANG_CANNOT_TELE_TO_BG); + SetSentErrorMessage(true); + return false; + } + + Player *chr = objmgr.GetPlayer(name.c_str());*/ + + if (target) + { + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + std::string chrNameLink = playerLink(target_name); + + if (target->IsBeingTeleported() == true) + { + PSendSysMessage(LANG_IS_TELEPORTED, chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_TELEPORTING_TO, chrNameLink.c_str(),"", tele->name.c_str()); + if (needReportToTarget(target)) + ChatHandler(target).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetNameLink().c_str()); + + // stop flight if need + if (target->isInFlight()) + { + target->GetMotionMaster()->MovementExpired(); + target->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + target->SaveRecallPosition(); + + target->TeleportTo(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation); + } + else + { + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + return false; + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_TELEPORTING_TO, nameLink.c_str(), GetTrinityString(LANG_OFFLINE), tele->name.c_str()); + Player::SavePositionInDB(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation, + MapManager::Instance().GetZoneId(tele->mapId,tele->position_x,tele->position_y,tele->position_z),target_guid); + } + + return true; +} + +//Teleport group to given game_tele.entry +bool ChatHandler::HandleTeleGroupCommand(const char * args) +{ + if (!*args) + return false; + + Player *player = getSelectedPlayer(); + if (!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(player, 0)) + return false; + + // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r + GameTele const* tele = extractGameTeleFromLink((char*)args); + if (!tele) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + + MapEntry const * me = sMapStore.LookupEntry(tele->mapId); + if (!me || me->IsBattleGroundOrArena()) + { + SendSysMessage(LANG_CANNOT_TELE_TO_BG); + SetSentErrorMessage(true); + return false; + } + + std::string nameLink = GetNameLink(player); + + Group *grp = player->GetGroup(); + if (!grp) + { + PSendSysMessage(LANG_NOT_IN_GROUP,nameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pl = itr->getSource(); + + if (!pl || !pl->GetSession()) + continue; + + // check online security + if (HasLowerSecurity(pl, 0)) + return false; + + std::string plNameLink = GetNameLink(pl); + + if (pl->IsBeingTeleported()) + { + PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); + continue; + } + + PSendSysMessage(LANG_TELEPORTING_TO, plNameLink.c_str(),"", tele->name.c_str()); + if (needReportToTarget(pl)) + ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, nameLink.c_str()); + + // stop flight if need + if (pl->isInFlight()) + { + pl->GetMotionMaster()->MovementExpired(); + pl->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + pl->SaveRecallPosition(); + + pl->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); + } + + return true; +} + +//Summon group of player +bool ChatHandler::HandleGroupgoCommand(const char* args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + Group *grp = target->GetGroup(); + + std::string nameLink = GetNameLink(target); + + if (!grp) + { + PSendSysMessage(LANG_NOT_IN_GROUP,nameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + Map* gmMap = m_session->GetPlayer()->GetMap(); + bool to_instance = gmMap->Instanceable(); + + // we are in instance, and can summon only player in our group with us as lead + if (to_instance && ( + !m_session->GetPlayer()->GetGroup() || (grp->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || + (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()))) + // the last check is a bit excessive, but let it be, just in case + { + SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); + SetSentErrorMessage(true); + return false; + } + + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pl = itr->getSource(); + + if (!pl || pl == m_session->GetPlayer() || !pl->GetSession()) + continue; + + // check online security + if (HasLowerSecurity(pl, 0)) + return false; + + std::string plNameLink = GetNameLink(pl); + + if (pl->IsBeingTeleported() == true) + { + PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + if (to_instance) + { + Map* plMap = pl->GetMap(); + + if (plMap->Instanceable() && plMap->GetInstanceId() != gmMap->GetInstanceId()) + { + // cannot summon from instance to instance + PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,plNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(),""); + if (needReportToTarget(pl)) + ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, GetNameLink().c_str()); + + // stop flight if need + if (pl->isInFlight()) + { + pl->GetMotionMaster()->MovementExpired(); + pl->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + pl->SaveRecallPosition(); + + // before GM + float x,y,z; + m_session->GetPlayer()->GetClosePoint(x,y,z,pl->GetObjectSize()); + pl->TeleportTo(m_session->GetPlayer()->GetMapId(),x,y,z,pl->GetOrientation()); + } + + return true; +} + +bool ChatHandler::HandleGoTaxinodeCommand(const char* args) +{ + Player* _player = m_session->GetPlayer(); + + if (!*args) + return false; + + char* cNodeId = extractKeyFromLink((char*)args,"Htaxinode"); + if (!cNodeId) + return false; + + int32 i_nodeId = atoi(cNodeId); + if (!i_nodeId) + return false; + + TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i_nodeId); + if (!node) + { + PSendSysMessage(LANG_COMMAND_GOTAXINODENOTFOUND,i_nodeId); + SetSentErrorMessage(true); + return false; + } + + if ((node->x == 0.0f && node->y == 0.0f && node->z == 0.0f) || + !MapManager::IsValidMapCoord(node->map_id,node->x,node->y,node->z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,node->x,node->y,node->map_id); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(node->map_id, node->x, node->y, node->z, _player->GetOrientation()); + return true; +} + +//teleport at coordinates +bool ChatHandler::HandleGoXYCommand(const char* args) +{ + if (!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pmapid = strtok(NULL, " "); + + if (!px || !py) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + uint32 mapid; + if (pmapid) + mapid = (uint32)atoi(pmapid); + else mapid = _player->GetMapId(); + + if (!MapManager::IsValidMapCoord(mapid,x,y)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + Map const *map = MapManager::Instance().CreateBaseMap(mapid); + float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + + _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); + + return true; +} + +//teleport at coordinates, including Z +bool ChatHandler::HandleGoXYZCommand(const char* args) +{ + if (!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + char* pmapid = strtok(NULL, " "); + + if (!px || !py || !pz) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + float z = (float)atof(pz); + uint32 mapid; + if (pmapid) + mapid = (uint32)atoi(pmapid); + else + mapid = _player->GetMapId(); + + if (!MapManager::IsValidMapCoord(mapid,x,y,z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); + + return true; +} + +//teleport at coordinates +bool ChatHandler::HandleGoZoneXYCommand(const char* args) +{ + if (!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* tail = strtok(NULL,""); + + char* cAreaId = extractKeyFromLink(tail,"Harea"); // string or [name] Shift-click form |color|Harea:area_id|h[name]|h|r + + if (!px || !py) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + + // prevent accept wrong numeric args + if ((x == 0.0f && *px != '0') || (y == 0.0f && *py != '0')) + return false; + + uint32 areaid = cAreaId ? (uint32)atoi(cAreaId) : _player->GetZoneId(); + + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaid); + + if (x<0 || x>100 || y<0 || y>100 || !areaEntry) + { + PSendSysMessage(LANG_INVALID_ZONE_COORD,x,y,areaid); + SetSentErrorMessage(true); + return false; + } + + // update to parent zone if exist (client map show only zones without parents) + AreaTableEntry const* zoneEntry = areaEntry->zone ? GetAreaEntryByAreaID(areaEntry->zone) : areaEntry; + + Map const *map = MapManager::Instance().CreateBaseMap(zoneEntry->mapid); + + if (map->Instanceable()) + { + PSendSysMessage(LANG_INVALID_ZONE_MAP,areaEntry->ID,areaEntry->area_name[GetSessionDbcLocale()],map->GetId(),map->GetMapName()); + SetSentErrorMessage(true); + return false; + } + + Zone2MapCoordinates(x,y,zoneEntry->ID); + + if (!MapManager::IsValidMapCoord(zoneEntry->mapid,x,y)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,zoneEntry->mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + _player->TeleportTo(zoneEntry->mapid, x, y, z, _player->GetOrientation()); + + return true; +} + +//teleport to grid +bool ChatHandler::HandleGoGridCommand(const char* args) +{ + if (!*args) return false; + Player* _player = m_session->GetPlayer(); + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pmapid = strtok(NULL, " "); + + if (!px || !py) + return false; + + float grid_x = (float)atof(px); + float grid_y = (float)atof(py); + uint32 mapid; + if (pmapid) + mapid = (uint32)atoi(pmapid); + else mapid = _player->GetMapId(); + + // center of grid + float x = (grid_x-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS; + float y = (grid_y-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS; + + if (!MapManager::IsValidMapCoord(mapid,x,y)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + Map const *map = MapManager::Instance().CreateBaseMap(mapid); + float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); + + return true; +} + +bool ChatHandler::HandleModifyDrunkCommand(const char* args) +{ + if (!*args) return false; + + uint32 drunklevel = (uint32)atoi(args); + if (drunklevel > 100) + drunklevel = 100; + + uint16 drunkMod = drunklevel * 0xFFFF / 100; + + m_session->GetPlayer()->SetDrunkValue(drunkMod); + + return true; +} + diff --git a/src/server/game/Chat/Level2.cpp b/src/server/game/Chat/Level2.cpp new file mode 100644 index 00000000000..4f299c932e8 --- /dev/null +++ b/src/server/game/Chat/Level2.cpp @@ -0,0 +1,4526 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "DBCStores.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "Item.h" +#include "GameObject.h" +#include "Opcodes.h" +#include "Chat.h" +#include "MapManager.h" +#include "Language.h" +#include "World.h" +#include "GameEventMgr.h" +#include "SpellMgr.h" +#include "PoolHandler.h" +#include "AccountMgr.h" +#include "WaypointManager.h" +#include "Util.h" +#include <cctype> +#include <iostream> +#include <fstream> +#include <map> +#include "GlobalEvents.h" +#include "OutdoorPvPMgr.h" + +#include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand +#include "CreatureGroups.h" + +//mute player for some times +bool ChatHandler::HandleMuteCommand(const char* args) +{ + char* nameStr; + char* delayStr; + extractOptFirstArg((char*)args,&nameStr,&delayStr); + if (!delayStr) + return false; + + char *mutereason = strtok(NULL, "\r"); + std::string mutereasonstr = "No reason"; + if (mutereason != NULL) + mutereasonstr = mutereason; + + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) + return false; + + uint32 account_id = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid); + + // find only player from same account if any + if (!target) + if (WorldSession* session = sWorld.FindSession(account_id)) + target = session->GetPlayer(); + + uint32 notspeaktime = (uint32) atoi(delayStr); + + // must have strong lesser security level + if (HasLowerSecurity (target,target_guid,true)) + return false; + + time_t mutetime = time(NULL) + notspeaktime*60; + + if (target) + target->GetSession()->m_muteTime = mutetime; + + LoginDatabase.PExecute("UPDATE account SET mutetime = " UI64FMTD " WHERE id = '%u'",uint64(mutetime), account_id); + + if (target) + ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime, mutereasonstr.c_str()); + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_YOU_DISABLE_CHAT, nameLink.c_str(), notspeaktime, mutereasonstr.c_str()); + + return true; +} + +//unmute player +bool ChatHandler::HandleUnmuteCommand(const char* args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + uint32 account_id = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid); + + // find only player from same account if any + if (!target) + if (WorldSession* session = sWorld.FindSession(account_id)) + target = session->GetPlayer(); + + // must have strong lesser security level + if (HasLowerSecurity (target,target_guid,true)) + return false; + + if (target) + { + if (target->CanSpeak()) + { + SendSysMessage(LANG_CHAT_ALREADY_ENABLED); + SetSentErrorMessage(true); + return false; + } + + target->GetSession()->m_muteTime = 0; + } + + LoginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id); + + if (target) + ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_ENABLED); + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_YOU_ENABLE_CHAT, nameLink.c_str()); + return true; +} + +bool ChatHandler::HandleGoTicketCommand(const char * args) +{ + if (!*args) + return false; + + char *cstrticket_id = strtok((char*)args, " "); + + if (!cstrticket_id) + return false; + + uint64 ticket_id = atoi(cstrticket_id); + if (!ticket_id) + return false; + + GM_Ticket *ticket = objmgr.GetGMTicket(ticket_id); + if (!ticket) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + + float x, y, z; + int mapid; + + x = ticket->pos_x; + y = ticket->pos_y; + z = ticket->pos_z; + mapid = ticket->map; + + Player* _player = m_session->GetPlayer(); + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, 1, 0); + return true; +} + +bool ChatHandler::HandleGoTriggerCommand(const char* args) +{ + Player* _player = m_session->GetPlayer(); + + if (!*args) + return false; + + char *atId = strtok((char*)args, " "); + if (!atId) + return false; + + int32 i_atId = atoi(atId); + + if (!i_atId) + return false; + + AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId); + if (!at) + { + PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId); + SetSentErrorMessage(true); + return false; + } + + if (!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation()); + return true; +} + +bool ChatHandler::HandleGoGraveyardCommand(const char* args) +{ + Player* _player = m_session->GetPlayer(); + + if (!*args) + return false; + + char *gyId = strtok((char*)args, " "); + if (!gyId) + return false; + + int32 i_gyId = atoi(gyId); + + if (!i_gyId) + return false; + + WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId); + if (!gy) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId); + SetSentErrorMessage(true); + return false; + } + + if (!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation()); + return true; +} + +/** \brief Teleport the GM to the specified creature +* +* .gocreature <GUID> --> TP using creature.guid +* .gocreature azuregos --> TP player to the mob with this name +* Warning: If there is more than one mob with this name +* you will be teleported to the first one that is found. +* .gocreature id 6109 --> TP player to the mob, that has this creature_template.entry +* Warning: If there is more than one mob with this "id" +* you will be teleported to the first one that is found. +*/ +//teleport to creature +bool ChatHandler::HandleGoCreatureCommand(const char* args) +{ + if (!*args) + return false; + Player* _player = m_session->GetPlayer(); + + // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + char* pParam1 = extractKeyFromLink((char*)args,"Hcreature"); + if (!pParam1) + return false; + + std::ostringstream whereClause; + + // User wants to teleport to the NPC's template entry + if (strcmp(pParam1, "id") == 0) + { + //sLog.outError("DEBUG: ID found"); + + // Get the "creature_template.entry" + // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + char* tail = strtok(NULL,""); + if (!tail) + return false; + char* cId = extractKeyFromLink(tail,"Hcreature_entry"); + if (!cId) + return false; + + int32 tEntry = atoi(cId); + //sLog.outError("DEBUG: ID value: %d", tEntry); + if (!tEntry) + return false; + + whereClause << "WHERE id = '" << tEntry << "'"; + } + else + { + //sLog.outError("DEBUG: ID *not found*"); + + int32 guid = atoi(pParam1); + + // Number is invalid - maybe the user specified the mob's name + if (!guid) + { + std::string name = pParam1; + WorldDatabase.escape_string(name); + whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'"; + } + else + { + whereClause << "WHERE guid = '" << guid << "'"; + } + } + //sLog.outError("DEBUG: %s", whereClause.c_str()); + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } + if (result->GetRowCount() > 1) + SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE); + + Field *fields = result->Fetch(); + float x = fields[0].GetFloat(); + float y = fields[1].GetFloat(); + float z = fields[2].GetFloat(); + float ort = fields[3].GetFloat(); + int mapid = fields[4].GetUInt16(); + + if (!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, ort); + return true; +} + +//teleport to gameobject +bool ChatHandler::HandleGoObjectCommand(const char* args) +{ + if (!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if (!cId) + return false; + + int32 guid = atoi(cId); + if (!guid) + return false; + + float x, y, z, ort; + int mapid; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(guid)) + { + x = go_data->posX; + y = go_data->posY; + z = go_data->posZ; + ort = go_data->orientation; + mapid = go_data->mapid; + } + else + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + if (!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, ort); + return true; +} + +bool ChatHandler::HandleGameObjectTargetCommand(const char* args) +{ + Player* pl = m_session->GetPlayer(); + QueryResult_AutoPtr result; + GameEventMgr::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList(); + if (*args) + { + // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry"); + if (!cId) + return false; + + uint32 id = atol(cId); + + if (id) + result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, orientation, map, phaseMask, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE map = '%i' AND id = '%u' ORDER BY order_ ASC LIMIT 1", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id); + else + { + std::string name = cId; + WorldDatabase.escape_string(name); + result = WorldDatabase.PQuery( + "SELECT guid, id, position_x, position_y, position_z, orientation, map, phaseMask, (POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ " + "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str()); + } + } + else + { + std::ostringstream eventFilter; + eventFilter << " AND (event IS NULL "; + bool initString = true; + + for (GameEventMgr::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr) + { + if (initString) + { + eventFilter << "OR event IN (" <<*itr; + initString =false; + } + else + eventFilter << "," << *itr; + } + + if (!initString) + eventFilter << "))"; + else + eventFilter << ")"; + + result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, phaseMask, " + "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject " + "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 10", + m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str()); + } + + if (!result) + { + SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND); + return true; + } + + bool found = false; + float x, y, z, o; + uint32 lowguid, id; + uint16 mapid, pool_id, phase; + + do + { + Field *fields = result->Fetch(); + lowguid = fields[0].GetUInt32(); + id = fields[1].GetUInt32(); + x = fields[2].GetFloat(); + y = fields[3].GetFloat(); + z = fields[4].GetFloat(); + o = fields[5].GetFloat(); + mapid = fields[6].GetUInt16(); + phase = fields[7].GetUInt16(); + pool_id = poolhandler.IsPartOfAPool<GameObject>(lowguid); + if (!pool_id || poolhandler.IsSpawnedObject<GameObject>(lowguid)) + found = true; + } while (result->NextRow() && (!found)); + + if (!found) + { + PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); + return false; + } + + GameObjectInfo const* goI = objmgr.GetGameObjectInfo(id); + + if (!goI) + { + PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); + return false; + } + + GameObject* target = m_session->GetPlayer()->GetMap()->GetGameObject(MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT)); + + PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o, phase); + + if (target) + { + int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL); + if (curRespawnDelay < 0) + curRespawnDelay = 0; + + std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true); + std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true); + + PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str()); + } + return true; +} + +//delete object by selection or guid +bool ChatHandler::HandleGameObjectDeleteCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + uint64 owner_guid = obj->GetOwnerGUID(); + if (owner_guid) + { + Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid); + if (!owner || !IS_PLAYER_GUID(owner_guid)) + { + PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow()); + SetSentErrorMessage(true); + return false; + } + + owner->RemoveGameObject(obj,false); + } + + obj->SetRespawnTime(0); // not save respawn time + obj->Delete(); + obj->DeleteFromDB(); + + PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow()); + + return true; +} + +//turn selected object +bool ChatHandler::HandleGameObjectTurnCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* po = strtok(NULL, " "); + float o; + + if (po) + { + o = (float)atof(po); + } + else + { + Player *chr = m_session->GetPlayer(); + o = chr->GetOrientation(); + } + + obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o); + obj->UpdateRotationFields(); + obj->DestroyForNearbyPlayers(); + obj->UpdateObjectVisibility(); + + obj->SaveToDB(); + obj->Refresh(); + + PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow(), o); + + return true; +} + +//move selected object +bool ChatHandler::HandleGameObjectMoveCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* px = strtok(NULL, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + + if (!px) + { + Player *chr = m_session->GetPlayer(); + obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation()); + obj->DestroyForNearbyPlayers(); + obj->UpdateObjectVisibility(); + } + else + { + if (!py || !pz) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + float z = (float)atof(pz); + + if (!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId()); + SetSentErrorMessage(true); + return false; + } + + obj->Relocate(x, y, z, obj->GetOrientation()); + obj->DestroyForNearbyPlayers(); + obj->UpdateObjectVisibility(); + } + + obj->SaveToDB(); + obj->Refresh(); + + PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow()); + + return true; +} + +//spawn go +bool ChatHandler::HandleGameObjectAddCommand(const char* args) +{ + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry"); + if (!cId) + return false; + + uint32 id = atol(cId); + if (!id) + return false; + + char* spawntimeSecs = strtok(NULL, " "); + + const GameObjectInfo *gInfo = objmgr.GetGameObjectInfo(id); + + if (!gInfo) + { + PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); + SetSentErrorMessage(true); + return false; + } + + if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId)) + { + // report to DB errors log as in loading case + sLog.outErrorDb("Gameobject (Entry %u GoType: %u) have invalid displayId (%u), not spawned.",id, gInfo->type, gInfo->displayId); + PSendSysMessage(LANG_GAMEOBJECT_HAVE_INVALID_DATA,id); + SetSentErrorMessage(true); + return false; + } + + Player *chr = m_session->GetPlayer(); + float x = float(chr->GetPositionX()); + float y = float(chr->GetPositionY()); + float z = float(chr->GetPositionZ()); + float o = float(chr->GetOrientation()); + Map *map = chr->GetMap(); + + GameObject* pGameObj = new GameObject; + uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); + + if (!pGameObj->Create(db_lowGUID, gInfo->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) + { + delete pGameObj; + return false; + } + + if (spawntimeSecs) + { + uint32 value = atoi((char*)spawntimeSecs); + pGameObj->SetRespawnTime(value); + //sLog.outDebug("*** spawntimeSecs: %d", value); + } + + // fill the gameobject data and save to the db + pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()),chr->GetPhaseMaskForSpawn()); + + // this will generate a new guid if the object is in an instance + if (!pGameObj->LoadFromDB(db_lowGUID, map)) + { + delete pGameObj; + return false; + } + + sLog.outDebug(GetTrinityString(LANG_GAMEOBJECT_CURRENT), gInfo->name, db_lowGUID, x, y, z, o); + + map->Add(pGameObj); + + // TODO: is it really necessary to add both the real and DB table guid here ? + objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID)); + + PSendSysMessage(LANG_GAMEOBJECT_ADD,id,gInfo->name,db_lowGUID,x,y,z); + return true; +} + +//set pahsemask for selected object +bool ChatHandler::HandleGameObjectPhaseCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* phaseStr = strtok (NULL, " "); + uint32 phasemask = phaseStr? atoi(phaseStr) : 0; + if (phasemask == 0) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + obj->SetPhaseMask(phasemask,true); + obj->SaveToDB(); + return true; +} + +bool ChatHandler::HandleGameObjectNearCommand(const char* args) +{ + float distance = (!*args) ? 10 : atol(args); + uint32 count = 0; + + Player* pl = m_session->GetPlayer(); + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, map, " + "(POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ " + "FROM gameobject WHERE map='%u' AND (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) <= '%f' ORDER BY order_", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), + pl->GetMapId(),pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),distance*distance); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + uint32 entry = fields[1].GetUInt32(); + float x = fields[2].GetFloat(); + float y = fields[3].GetFloat(); + float z = fields[4].GetFloat(); + int mapid = fields[5].GetUInt16(); + + GameObjectInfo const * gInfo = objmgr.GetGameObjectInfo(entry); + + if (!gInfo) + continue; + + PSendSysMessage(LANG_GO_LIST_CHAT, guid, guid, gInfo->name, x, y, z, mapid); + + ++count; + } while (result->NextRow()); + } + + PSendSysMessage(LANG_COMMAND_NEAROBJMESSAGE,distance,count); + return true; +} + +bool ChatHandler::HandleGUIDCommand(const char* /*args*/) +{ + uint64 guid = m_session->GetPlayer()->GetSelection(); + + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid)); + return true; +} + +bool ChatHandler::HandleModifyRepCommand(const char * args) +{ + if (!*args) return false; + + Player* target = NULL; + target = getSelectedPlayer(); + + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + char* factionTxt = extractKeyFromLink((char*)args,"Hfaction"); + if (!factionTxt) + return false; + + uint32 factionId = atoi(factionTxt); + + int32 amount = 0; + char *rankTxt = strtok(NULL, " "); + if (!factionTxt || !rankTxt) + return false; + + amount = atoi(rankTxt); + if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0])) + { + std::string rankStr = rankTxt; + std::wstring wrankStr; + if (!Utf8toWStr(rankStr,wrankStr)) + return false; + wstrToLower(wrankStr); + + int r = 0; + amount = -42000; + for (; r < MAX_REPUTATION_RANK; ++r) + { + std::string rank = GetTrinityString(ReputationRankStrIndex[r]); + if (rank.empty()) + continue; + + std::wstring wrank; + if (!Utf8toWStr(rank,wrank)) + continue; + + wstrToLower(wrank); + + if (wrank.substr(0,wrankStr.size()) == wrankStr) + { + char *deltaTxt = strtok(NULL, " "); + if (deltaTxt) + { + int32 delta = atoi(deltaTxt); + if ((delta < 0) || (delta > ReputationMgr::PointsInRank[r] -1)) + { + PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (ReputationMgr::PointsInRank[r]-1)); + SetSentErrorMessage(true); + return false; + } + amount += delta; + } + break; + } + amount += ReputationMgr::PointsInRank[r]; + } + if (r >= MAX_REPUTATION_RANK) + { + PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt); + SetSentErrorMessage(true); + return false; + } + } + + FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId); + + if (!factionEntry) + { + PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId); + SetSentErrorMessage(true); + return false; + } + + if (factionEntry->reputationListID < 0) + { + PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[GetSessionDbcLocale()], factionId); + SetSentErrorMessage(true); + return false; + } + + target->GetReputationMgr().SetReputation(factionEntry,amount); + PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[GetSessionDbcLocale()], factionId, + GetNameLink(target).c_str(), target->GetReputationMgr().GetReputation(factionEntry)); + return true; +} + +//-----------------------Npc Commands----------------------- +//add spawn of creature +bool ChatHandler::HandleNpcAddCommand(const char* args) +{ + if (!*args) + return false; + char* charID = extractKeyFromLink((char*)args,"Hcreature_entry"); + if (!charID) + return false; + + char* team = strtok(NULL, " "); + int32 teamval = 0; + if (team) { teamval = atoi(team); } + if (teamval < 0) { teamval = 0; } + + uint32 id = atoi(charID); + + Player *chr = m_session->GetPlayer(); + float x = chr->GetPositionX(); + float y = chr->GetPositionY(); + float z = chr->GetPositionZ(); + float o = chr->GetOrientation(); + Map *map = chr->GetMap(); + + Creature* pCreature = new Creature; + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, (uint32)teamval, x, y, z, o)) + { + delete pCreature; + return false; + } + + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + + uint32 db_guid = pCreature->GetDBTableGUIDLow(); + + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + pCreature->LoadFromDB(db_guid, map); + + map->Add(pCreature); + objmgr.AddCreatureToGrid(db_guid, objmgr.GetCreatureData(db_guid)); + return true; +} + +//add item in vendorlist +bool ChatHandler::HandleNpcAddVendorItemCommand(const char* args) +{ + if (!*args) + return false; + + char* pitem = extractKeyFromLink((char*)args,"Hitem"); + if (!pitem) + { + SendSysMessage(LANG_COMMAND_NEEDITEMSEND); + SetSentErrorMessage(true); + return false; + } + + uint32 itemId = atol(pitem); + + char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0 + uint32 maxcount = 0; + if (fmaxcount) + maxcount = atol(fmaxcount); + + char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0 + uint32 incrtime = 0; + if (fincrtime) + incrtime = atol(fincrtime); + + char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0 + uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0; + + Creature* vendor = getSelectedCreature(); + + uint32 vendor_entry = vendor ? vendor->GetEntry() : 0; + + if (!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer())) + { + SetSentErrorMessage(true); + return false; + } + + objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost); + + ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId); + + PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost); + return true; +} + +//del item from vendor list +bool ChatHandler::HandleNpcDelVendorItemCommand(const char* args) +{ + if (!*args) + return false; + + Creature* vendor = getSelectedCreature(); + if (!vendor || !vendor->isVendor()) + { + SendSysMessage(LANG_COMMAND_VENDORSELECTION); + SetSentErrorMessage(true); + return false; + } + + char* pitem = extractKeyFromLink((char*)args,"Hitem"); + if (!pitem) + { + SendSysMessage(LANG_COMMAND_NEEDITEMSEND); + SetSentErrorMessage(true); + return false; + } + uint32 itemId = atol(pitem); + + if (!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId)) + { + PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId); + SetSentErrorMessage(true); + return false; + } + + ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId); + + PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1); + return true; +} + +//add move for creature +bool ChatHandler::HandleNpcAddMoveCommand(const char* args) +{ + if (!*args) + return false; + + char* guid_str = strtok((char*)args, " "); + char* wait_str = strtok((char*)NULL, " "); + + uint32 lowguid = atoi((char*)guid_str); + + Creature* pCreature = NULL; + + /* FIXME: impossible without entry + if (lowguid) + pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); + */ + + // attempt check creature existence by DB data + if (!pCreature) + { + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if (!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + } + else + { + // obtain real GUID for DB operations + lowguid = pCreature->GetDBTableGUIDLow(); + } + + int wait = wait_str ? atoi(wait_str) : 0; + + if (wait < 0) + wait = 0; + + //Player* player = m_session->GetPlayer(); + + //WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0); + + // update movement type + WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid); + if (pCreature && pCreature->GetWaypointPath()) + { + pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); + pCreature->GetMotionMaster()->Initialize(); + if (pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(true); + } + pCreature->SaveToDB(); + } + + SendSysMessage(LANG_WAYPOINT_ADDED); + + return true; +} + +//change level of creature or pet +bool ChatHandler::HandleNpcChangeLevelCommand(const char* args) +{ + if (!*args) + return false; + + uint8 lvl = (uint8) atoi((char*)args); + if (lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature* pCreature = getSelectedCreature(); + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (pCreature->isPet()) + { + if (((Pet*)pCreature)->getPetType() == HUNTER_PET) + { + pCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(lvl)/4); + pCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); + } + ((Pet*)pCreature)->GivePetLevel(lvl); + } + else + { + pCreature->SetMaxHealth(100 + 30*lvl); + pCreature->SetHealth(100 + 30*lvl); + pCreature->SetLevel(lvl); + pCreature->SaveToDB(); + } + + return true; +} + +//set npcflag of creature +bool ChatHandler::HandleNpcFlagCommand(const char* args) +{ + if (!*args) + return false; + + uint32 npcFlags = (uint32) atoi((char*)args); + + Creature* pCreature = getSelectedCreature(); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags); + + WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry()); + + SendSysMessage(LANG_VALUE_SAVED_REJOIN); + + return true; +} + +bool ChatHandler::HandleNpcDeleteCommand(const char* args) +{ + Creature* unit = NULL; + + if (*args) + { + // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid)) + unit = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT)); + } + else + unit = getSelectedCreature(); + + if (!unit || unit->isPet() || unit->isTotem()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // Delete the creature + unit->CombatStop(); + unit->DeleteFromDB(); + unit->AddObjectToRemoveList(); + + SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); + + return true; +} + +//move selected creature +bool ChatHandler::HandleNpcMoveCommand(const char* args) +{ + uint32 lowguid = 0; + + Creature* pCreature = getSelectedCreature(); + + if (!pCreature) + { + // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature"); + if (!cId) + return false; + + lowguid = atoi(cId); + + /* FIXME: impossibel without entry + if (lowguid) + pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); + */ + + // Attempting creature load from DB data + if (!pCreature) + { + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if (!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + uint32 map_id = data->mapid; + + if (m_session->GetPlayer()->GetMapId() != map_id) + { + PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); + SetSentErrorMessage(true); + return false; + } + } + else + { + lowguid = pCreature->GetDBTableGUIDLow(); + } + } + else + { + lowguid = pCreature->GetDBTableGUIDLow(); + } + + float x = m_session->GetPlayer()->GetPositionX(); + float y = m_session->GetPlayer()->GetPositionY(); + float z = m_session->GetPlayer()->GetPositionZ(); + float o = m_session->GetPlayer()->GetOrientation(); + + if (pCreature) + { + if (CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow())) + { + const_cast<CreatureData*>(data)->posX = x; + const_cast<CreatureData*>(data)->posY = y; + const_cast<CreatureData*>(data)->posZ = z; + const_cast<CreatureData*>(data)->orientation = o; + } + pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o); + pCreature->GetMotionMaster()->Initialize(); + if (pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); + } + } + + WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid); + PSendSysMessage(LANG_COMMAND_CREATUREMOVED); + return true; +} + +/**HandleNpcSetMoveTypeCommand + * Set the movement type for an NPC.<br/> + * <br/> + * Valid movement types are: + * <ul> + * <li> stay - NPC wont move </li> + * <li> random - NPC will move randomly according to the spawndist </li> + * <li> way - NPC will move with given waypoints set </li> + * </ul> + * additional parameter: NODEL - so no waypoints are deleted, if you + * change the movement type + */ +bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args) +{ + if (!*args) + return false; + + // 3 arguments: + // GUID (optional - you can also select the creature) + // stay|random|way (determines the kind of movement) + // NODEL (optional - tells the system NOT to delete any waypoints) + // this is very handy if you want to do waypoints, that are + // later switched on/off according to special events (like escort + // quests, etc) + char* guid_str = strtok((char*)args, " "); + char* type_str = strtok((char*)NULL, " "); + char* dontdel_str = strtok((char*)NULL, " "); + + bool doNotDelete = false; + + if (!guid_str) + return false; + + uint32 lowguid = 0; + Creature* pCreature = NULL; + + if (dontdel_str) + { + //sLog.outError("DEBUG: All 3 params are set"); + + // All 3 params are set + // GUID + // type + // doNotDEL + if (stricmp(dontdel_str, "NODEL") == 0) + { + //sLog.outError("DEBUG: doNotDelete = true;"); + doNotDelete = true; + } + } + else + { + // Only 2 params - but maybe NODEL is set + if (type_str) + { + sLog.outError("DEBUG: Only 2 params "); + if (stricmp(type_str, "NODEL") == 0) + { + //sLog.outError("DEBUG: type_str, NODEL "); + doNotDelete = true; + type_str = NULL; + } + } + } + + if (!type_str) // case .setmovetype $move_type (with selected creature) + { + type_str = guid_str; + pCreature = getSelectedCreature(); + if (!pCreature || pCreature->isPet()) + return false; + lowguid = pCreature->GetDBTableGUIDLow(); + } + else // case .setmovetype #creature_guid $move_type (with selected creature) + { + lowguid = atoi((char*)guid_str); + + /* impossible without entry + if (lowguid) + pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); + */ + + // attempt check creature existence by DB data + if (!pCreature) + { + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if (!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + } + else + { + lowguid = pCreature->GetDBTableGUIDLow(); + } + } + + // now lowguid is low guid really existed creature + // and pCreature point (maybe) to this creature or NULL + + MovementGeneratorType move_type; + + std::string type = type_str; + + if (type == "stay") + move_type = IDLE_MOTION_TYPE; + else if (type == "random") + move_type = RANDOM_MOTION_TYPE; + else if (type == "way") + move_type = WAYPOINT_MOTION_TYPE; + else + return false; + + // update movement type + //if (doNotDelete == false) + // WaypointMgr.DeletePath(lowguid); + + if (pCreature) + { + // update movement type + if (doNotDelete == false) + pCreature->LoadPath(0); + + pCreature->SetDefaultMovementType(move_type); + pCreature->GetMotionMaster()->Initialize(); + if (pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); + } + pCreature->SaveToDB(); + } + if (doNotDelete == false) + { + PSendSysMessage(LANG_MOVE_TYPE_SET,type_str); + } + else + { + PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str); + } + + return true; +} + +//set model of creature +bool ChatHandler::HandleNpcSetModelCommand(const char* args) +{ + if (!*args) + return false; + + uint32 displayId = (uint32) atoi((char*)args); + + Creature *pCreature = getSelectedCreature(); + + if (!pCreature || pCreature->isPet()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetDisplayId(displayId); + pCreature->SetNativeDisplayId(displayId); + + pCreature->SaveToDB(); + + return true; +} +//set faction of creature +bool ChatHandler::HandleNpcFactionIdCommand(const char* args) +{ + if (!*args) + return false; + + uint32 factionId = (uint32) atoi((char*)args); + + if (!sFactionTemplateStore.LookupEntry(factionId)) + { + PSendSysMessage(LANG_WRONG_FACTION, factionId); + SetSentErrorMessage(true); + return false; + } + + Creature* pCreature = getSelectedCreature(); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->setFaction(factionId); + + // faction is set in creature_template - not inside creature + + // update in memory + if (CreatureInfo const *cinfo = pCreature->GetCreatureInfo()) + { + const_cast<CreatureInfo*>(cinfo)->faction_A = factionId; + const_cast<CreatureInfo*>(cinfo)->faction_H = factionId; + } + + // and DB + WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry()); + + return true; +} +//set spawn dist of creature +bool ChatHandler::HandleNpcSpawnDistCommand(const char* args) +{ + if (!*args) + return false; + + float option = atof((char*)args); + if (option < 0.0f) + { + SendSysMessage(LANG_BAD_VALUE); + return false; + } + + MovementGeneratorType mtype = IDLE_MOTION_TYPE; + if (option >0.0f) + mtype = RANDOM_MOTION_TYPE; + + Creature *pCreature = getSelectedCreature(); + uint32 u_guidlow = 0; + + if (pCreature) + u_guidlow = pCreature->GetDBTableGUIDLow(); + else + return false; + + pCreature->SetRespawnRadius((float)option); + pCreature->SetDefaultMovementType(mtype); + pCreature->GetMotionMaster()->Initialize(); + if (pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); + } + + WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow); + PSendSysMessage(LANG_COMMAND_SPAWNDIST,option); + return true; +} +//spawn time handling +bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args) +{ + if (!*args) + return false; + + char* stime = strtok((char*)args, " "); + + if (!stime) + return false; + + int i_stime = atoi((char*)stime); + + if (i_stime < 0) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature *pCreature = getSelectedCreature(); + uint32 u_guidlow = 0; + + if (pCreature) + u_guidlow = pCreature->GetDBTableGUIDLow(); + else + return false; + + WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow); + pCreature->SetRespawnDelay((uint32)i_stime); + PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime); + + return true; +} +//npc follow handling +bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/) +{ + Player *player = m_session->GetPlayer(); + Creature *creature = getSelectedCreature(); + + if (!creature) + { + PSendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // Follow player - Using pet's default dist and angle + creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, creature->GetFollowAngle()); + + PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName()); + return true; +} +//npc unfollow handling +bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/) +{ + Player *player = m_session->GetPlayer(); + Creature *creature = getSelectedCreature(); + + if (!creature) + { + PSendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (/*creature->GetMotionMaster()->empty() ||*/ + creature->GetMotionMaster()->GetCurrentMovementGeneratorType () != TARGETED_MOTION_TYPE) + { + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); + SetSentErrorMessage(true); + return false; + } + + TargetedMovementGenerator<Creature> const* mgen + = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top())); + + if (mgen->GetTarget() != player) + { + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); + SetSentErrorMessage(true); + return false; + } + + // reset movement + creature->GetMotionMaster()->MovementExpired(true); + + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName()); + return true; +} +//npc tame handling +bool ChatHandler::HandleNpcTameCommand(const char* /*args*/) +{ + Creature *creatureTarget = getSelectedCreature (); + if (!creatureTarget || creatureTarget->isPet ()) + { + PSendSysMessage (LANG_SELECT_CREATURE); + SetSentErrorMessage (true); + return false; + } + + Player *player = m_session->GetPlayer (); + + if (player->GetPetGUID ()) + { + SendSysMessage (LANG_YOU_ALREADY_HAVE_PET); + SetSentErrorMessage (true); + return false; + } + + CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo(); + + if (!cInfo->isTameable (player->CanTameExoticPets())) + { + PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); + SetSentErrorMessage (true); + return false; + } + + // Everything looks OK, create new pet + Pet* pet = player->CreateTamedPetFrom (creatureTarget); + if (!pet) + { + PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); + SetSentErrorMessage (true); + return false; + } + + // place pet before player + float x,y,z; + player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE); + pet->Relocate (x,y,z,M_PI-player->GetOrientation ()); + + // set pet to defensive mode by default (some classes can't control controlled pets in fact). + pet->SetReactState(REACT_DEFENSIVE); + + // calculate proper level + uint8 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel(); + + // prepare visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); + + // add to world + pet->GetMap()->Add(pet->ToCreature()); + + // visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); + + // caster have pet now + player->SetMinion(pet, true); + + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + player->PetSpellInitialize(); + + return true; +} +//npc phasemask handling +//change phasemask of creature or pet +bool ChatHandler::HandleNpcSetPhaseCommand(const char* args) +{ + if (!*args) + return false; + + uint32 phasemask = (uint32) atoi((char*)args); + if (phasemask == 0) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature* pCreature = getSelectedCreature(); + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetPhaseMask(phasemask,true); + + if (!pCreature->isPet()) + pCreature->SaveToDB(); + + return true; +} +//npc deathstate handling +bool ChatHandler::HandleNpcSetDeathStateCommand(const char* args) +{ + if (!*args) + return false; + + Creature* pCreature = getSelectedCreature(); + if (!pCreature || pCreature->isPet()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (strncmp(args, "on", 3) == 0) + pCreature->SetDeadByDefault(true); + else if (strncmp(args, "off", 4) == 0) + pCreature->SetDeadByDefault(false); + else + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + pCreature->SaveToDB(); + pCreature->Respawn(); + + return true; +} + +//TODO: NpcCommands that need to be fixed : + +bool ChatHandler::HandleNpcNameCommand(const char* /*args*/) +{ + /* Temp. disabled + if (!*args) + return false; + + if (strlen((char*)args)>75) + { + PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75); + return true; + } + + for (uint8 i = 0; i < strlen(args); ++i) + { + if (!isalpha(args[i]) && args[i] != ' ') + { + SendSysMessage(LANG_CHARS_ONLY); + return false; + } + } + + uint64 guid; + guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + pCreature->SetName(args); + uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName()); + pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); + + pCreature->SaveToDB(); + */ + + return true; +} + +bool ChatHandler::HandleNpcSubNameCommand(const char* /*args*/) +{ + /* Temp. disabled + + if (!*args) + args = ""; + + if (strlen((char*)args)>75) + { + + PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75); + return true; + } + + for (uint8 i = 0; i < strlen(args); i++) + { + if (!isalpha(args[i]) && args[i] != ' ') + { + SendSysMessage(LANG_CHARS_ONLY); + return false; + } + } + uint64 guid; + guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID)); + pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); + + pCreature->SaveToDB(); + */ + return true; +} + +//move item to other slot +bool ChatHandler::HandleItemMoveCommand(const char* args) +{ + if (!*args) + return false; + uint8 srcslot, dstslot; + + char* pParam1 = strtok((char*)args, " "); + if (!pParam1) + return false; + + char* pParam2 = strtok(NULL, " "); + if (!pParam2) + return false; + + srcslot = (uint8)atoi(pParam1); + dstslot = (uint8)atoi(pParam2); + + if (srcslot == dstslot) + return true; + + if (!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) + return false; + + if (!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) + return false; + + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); + uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); + + m_session->GetPlayer()->SwapItem(src, dst); + + return true; +} + +//demorph player or unit +bool ChatHandler::HandleDeMorphCommand(const char* /*args*/) +{ + Unit *target = getSelectedUnit(); + if (!target) + target = m_session->GetPlayer(); + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + target->DeMorph(); + + return true; +} + +//morph creature or player +bool ChatHandler::HandleModifyMorphCommand(const char* args) +{ + if (!*args) + return false; + + uint16 display_id = (uint16)atoi((char*)args); + + Unit *target = getSelectedUnit(); + if (!target) + target = m_session->GetPlayer(); + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + target->SetDisplayId(display_id); + + return true; +} + +//kick player +bool ChatHandler::HandleKickPlayerCommand(const char *args) +{ +/* const char* kickName = strtok((char*)args, " "); + char* kickReason = strtok(NULL, "\n"); + std::string reason = "No Reason"; + std::string kicker = "Console"; + if (kickReason) + reason = kickReason; + if (m_session) + kicker = m_session->GetPlayer()->GetName(); + + if (!kickName) + { + Player* player = getSelectedPlayer(); + if (!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (player == m_session->GetPlayer()) + { + SendSysMessage(LANG_COMMAND_KICKSELF); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(player, 0)) + return false; + + if (sWorld.getConfig(CONFIG_SHOW_KICK_IN_WORLD) == 1) + { + sWorld.SendWorldText(LANG_COMMAND_KICKMESSAGE, player->GetName(), kicker.c_str(), reason.c_str()); + } + else + { + PSendSysMessage(LANG_COMMAND_KICKMESSAGE, player->GetName(), kicker.c_str(), reason.c_str()); + } + + player->GetSession()->KickPlayer(); + } + else + { + std::string name = extractPlayerNameFromLink((char*)kickName); + if (name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if (m_session && name == m_session->GetPlayer()->GetName()) + { + SendSysMessage(LANG_COMMAND_KICKSELF); + SetSentErrorMessage(true); + return false; + } + + Player* player = objmgr.GetPlayer(kickName); + if (!player) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if (HasLowerSecurity(player, 0)) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); //maybe replacement string for this later on + SetSentErrorMessage(true); + return false; + } + + std::string nameLink = playerLink(name); + + if (sWorld.KickPlayer(name)) + { + if (sWorld.getConfig(CONFIG_SHOW_KICK_IN_WORLD) == 1) + { + sWorld.SendWorldText(LANG_COMMAND_KICKMESSAGE, nameLink.c_str(), kicker.c_str(), reason.c_str()); + } + else + { + PSendSysMessage(LANG_COMMAND_KICKMESSAGE,nameLink.c_str()); + } + } + else + { + PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,nameLink.c_str()); + return false; + } + }*/ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + if (m_session && target == m_session->GetPlayer()) + { + SendSysMessage(LANG_COMMAND_KICKSELF); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + // send before target pointer invalidate + PSendSysMessage(LANG_COMMAND_KICKMESSAGE,GetNameLink(target).c_str()); + target->GetSession()->KickPlayer(); + return true; +} + +//set temporary phase mask for player +bool ChatHandler::HandleModifyPhaseCommand(const char* args) +{ + if (!*args) + return false; + + uint32 phasemask = (uint32)atoi((char*)args); + + Unit *target = getSelectedUnit(); + if (!target) + target = m_session->GetPlayer(); + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + target->SetPhaseMask(phasemask,true); + + return true; +} +//show info of gameobject +bool ChatHandler::HandleGOInfoCommand(const char* args) +{ + uint32 entry = 0; + uint32 type = 0; + uint32 displayid = 0; + std::string name; + + if (!*args) + { + if (WorldObject * obj = getSelectedObject()) + entry = obj->GetEntry(); + } + else + entry = atoi((char*)args); + + GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry); + + if (!goinfo) + return false; + + type = goinfo->type; + displayid = goinfo->displayId; + name = goinfo->name; + + PSendSysMessage(LANG_GOINFO_ENTRY, entry); + PSendSysMessage(LANG_GOINFO_TYPE, type); + PSendSysMessage(LANG_GOINFO_DISPLAYID, displayid); + PSendSysMessage(LANG_GOINFO_NAME, name.c_str()); + + return true; +} + +//show info of player +bool ChatHandler::HandlePInfoCommand(const char* args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + uint32 accId = 0; + uint32 money = 0; + uint32 total_player_time = 0; + uint8 level = 0; + uint32 latency = 0; + uint8 race; + uint8 Class; + + // get additional information from Player object + if (target) + { + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + accId = target->GetSession()->GetAccountId(); + money = target->GetMoney(); + total_player_time = target->GetTotalPlayedTime(); + level = target->getLevel(); + latency = target->GetSession()->GetLatency(); + race = target->getRace(); + Class = target->getClass(); + } + // get additional information from DB + else + { + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + return false; + + // 0 1 2 3 4 5 + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT totaltime, level, money, account, race, class FROM characters WHERE guid = '%u'", GUID_LOPART(target_guid)); + if (!result) + return false; + + Field *fields = result->Fetch(); + total_player_time = fields[0].GetUInt32(); + level = fields[1].GetUInt32(); + money = fields[2].GetUInt32(); + accId = fields[3].GetUInt32(); + race = fields[4].GetUInt8(); + Class = fields[5].GetUInt8(); + } + + std::string username = GetTrinityString(LANG_ERROR); + std::string email = GetTrinityString(LANG_ERROR); + std::string last_ip = GetTrinityString(LANG_ERROR); + uint32 security = 0; + std::string last_login = GetTrinityString(LANG_ERROR); + + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT a.username,aa.gmlevel,a.email,a.last_ip,a.last_login " + "FROM account a " + "LEFT JOIN account_access aa " + "ON (a.id = aa.id) " + "WHERE a.id = '%u'",accId); + if (result) + { + Field* fields = result->Fetch(); + username = fields[0].GetCppString(); + security = fields[1].GetUInt32(); + email = fields[2].GetCppString(); + + if (email.empty()) + email = "-"; + + if (!m_session || m_session->GetSecurity() >= security) + { + last_ip = fields[3].GetCppString(); + last_login = fields[4].GetCppString(); + } + else + { + last_ip = "-"; + last_login = "-"; + } + } + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetTrinityString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(target_guid), username.c_str(), accId, email.c_str(), security, last_ip.c_str(), last_login.c_str(), latency); + + std::string race_s, Class_s; + switch(race) + { + case RACE_HUMAN: race_s = "Human"; break; + case RACE_ORC: race_s = "Orc"; break; + case RACE_DWARF: race_s = "Dwarf"; break; + case RACE_NIGHTELF: race_s = "Night Elf"; break; + case RACE_UNDEAD_PLAYER: race_s = "Undead"; break; + case RACE_TAUREN: race_s = "Tauren"; break; + case RACE_GNOME: race_s = "Gnome"; break; + case RACE_TROLL: race_s = "Troll"; break; + case RACE_BLOODELF: race_s = "Blood Elf"; break; + case RACE_DRAENEI: race_s = "Draenei"; break; + } + switch(Class) + { + case CLASS_WARRIOR: Class_s = "Warrior"; break; + case CLASS_PALADIN: Class_s = "Paladin"; break; + case CLASS_HUNTER: Class_s = "Hunter"; break; + case CLASS_ROGUE: Class_s = "Rogue"; break; + case CLASS_PRIEST: Class_s = "Priest"; break; + case CLASS_DEATH_KNIGHT: Class_s = "Death Knight"; break; + case CLASS_SHAMAN: Class_s = "Shaman"; break; + case CLASS_MAGE: Class_s = "Mage"; break; + case CLASS_WARLOCK: Class_s = "Warlock"; break; + case CLASS_DRUID: Class_s = "Druid"; break; + } + + std::string timeStr = secsToTimeString(total_player_time,true,true); + uint32 gold = money /GOLD; + uint32 silv = (money % GOLD) / SILVER; + uint32 copp = (money % GOLD) % SILVER; + PSendSysMessage(LANG_PINFO_LEVEL, race_s.c_str(), Class_s.c_str(), timeStr.c_str(), level, gold, silv, copp); + + return true; +} + +/////WAYPOINT COMMANDS + +/** + * Add a waypoint to a creature. + * + * The user can either select an npc or provide its GUID. + * + * The user can even select a visual waypoint - then the new waypoint + * is placed *after* the selected one - this makes insertion of new + * waypoints possible. + * + * eg: + * .wp add 12345 + * -> adds a waypoint to the npc with the GUID 12345 + * + * .wp add + * -> adds a waypoint to the currently selected creature + * + * + * @param args if the user did not provide a GUID, it is NULL + * + * @return true - command did succeed, false - something went wrong + */ +bool ChatHandler::HandleWpAddCommand(const char* args) +{ + sLog.outDebug("DEBUG: HandleWpAddCommand"); + + // optional + char* path_number = NULL; + uint32 pathid = 0; + + if (*args) + path_number = strtok((char*)args, " "); + + uint32 point = 0; + Creature* target = getSelectedCreature(); + + if (!path_number) + { + if (target) + pathid = target->GetWaypointPath(); + else + { + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT MAX(id) FROM waypoint_data"); + uint32 maxpathid = result->Fetch()->GetInt32(); + pathid = maxpathid+1; + sLog.outDebug("DEBUG: HandleWpAddCommand - New path started."); + PSendSysMessage("%s%s|r", "|cff00ff00", "New path started."); + } + } + else + pathid = atoi(path_number); + + // path_id -> ID of the Path + // point -> number of the waypoint (if not 0) + + if (!pathid) + { + sLog.outDebug("DEBUG: HandleWpAddCommand - Current creature haven't loaded path."); + PSendSysMessage("%s%s|r", "|cffff33ff", "Current creature haven't loaded path."); + return true; + } + + sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0"); + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT MAX(point) FROM waypoint_data WHERE id = '%u'",pathid); + + if (result) + point = (*result)[0].GetUInt32(); + + Player* player = m_session->GetPlayer(); + //Map *map = player->GetMap(); + + WorldDatabase.PExecuteLog("INSERT INTO waypoint_data (id, point, position_x, position_y, position_z) VALUES ('%u','%u','%f', '%f', '%f')", + pathid, point+1, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); + + PSendSysMessage("%s%s%u%s%u%s|r", "|cff00ff00", "PathID: |r|cff00ffff", pathid, "|r|cff00ff00: Waypoint |r|cff00ffff", point+1,"|r|cff00ff00 created. "); + return true; +} // HandleWpAddCommand + +bool ChatHandler::HandleWpLoadPathCommand(const char *args) +{ + if (!*args) + return false; + + // optional + char* path_number = NULL; + + if (*args) + path_number = strtok((char*)args, " "); + + uint32 pathid = 0; + uint32 guidlow = 0; + Creature* target = getSelectedCreature(); + + // Did player provide a path_id? + if (!path_number) + sLog.outDebug("DEBUG: HandleWpLoadPathCommand - No path number provided"); + + if (!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (target->GetEntry() == 1) + { + PSendSysMessage("%s%s|r", "|cffff33ff", "You want to load path to a waypoint? Aren't you?"); + SetSentErrorMessage(true); + return false; + } + + pathid = atoi(path_number); + + if (!pathid) + { + PSendSysMessage("%s%s|r", "|cffff33ff", "No vallid path number provided."); + return true; + } + + guidlow = target->GetDBTableGUIDLow(); + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid FROM creature_addon WHERE guid = '%u'",guidlow); + + if (result) + WorldDatabase.PExecute("UPDATE creature_addon SET path_id = '%u' WHERE guid = '%u'", pathid, guidlow); + else + WorldDatabase.PExecute("INSERT INTO creature_addon(guid,path_id) VALUES ('%u','%u')", guidlow, pathid); + + WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE, guidlow); + + target->LoadPath(pathid); + target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); + target->GetMotionMaster()->Initialize(); + target->MonsterSay("Path loaded.",0,0); + + return true; +} + +bool ChatHandler::HandleReloadAllPaths(const char* args) +{ + if (!*args) + return false; + + uint32 id = atoi(args); + + if (!id) + return false; + + PSendSysMessage("%s%s|r|cff00ffff%u|r", "|cff00ff00", "Loading Path: ", id); + sWaypointMgr->UpdatePath(id); + return true; +} + +bool ChatHandler::HandleWpUnLoadPathCommand(const char * /*args*/) +{ + uint32 guidlow = 0; + Creature* target = getSelectedCreature(); + + if (!target) + { + PSendSysMessage("%s%s|r", "|cff33ffff", "You must select target."); + return true; + } + + if (target->GetCreatureAddon()) + { + if (target->GetCreatureAddon()->path_id != 0) + { + WorldDatabase.PExecute("DELETE FROM creature_addon WHERE guid = %u", target->GetGUIDLow()); + target->UpdateWaypointID(0); + WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", IDLE_MOTION_TYPE, guidlow); + target->LoadPath(0); + target->SetDefaultMovementType(IDLE_MOTION_TYPE); + target->GetMotionMaster()->MoveTargetedHome(); + target->GetMotionMaster()->Initialize(); + target->MonsterSay("Path unloaded.",0,0); + return true; + } + PSendSysMessage("%s%s|r", "|cffff33ff", "Target have no loaded path."); + } + return true; +} + +bool ChatHandler::HandleWpEventCommand(const char* args) +{ + if (!*args) + return false; + + char* show_str = strtok((char*)args, " "); + std::string show = show_str; + + // Check + if ((show != "add") && (show != "mod") && (show != "del") && (show != "listid")) return false; + + char* arg_id = strtok(NULL, " "); + uint32 id = 0; + + if (show == "add") + { + if (arg_id) + id = atoi(arg_id); + + if (id) + { + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id FROM waypoint_scripts WHERE guid = %u", id); + + if (!result) + { + WorldDatabase.PExecute("INSERT INTO waypoint_scripts(guid)VALUES(%u)", id); + PSendSysMessage("%s%s%u|r", "|cff00ff00", "Wp Event: New waypoint event added: ", id); + } + else + PSendSysMessage("|cff00ff00Wp Event: You have choosed an existing waypoint script guid: %u|r", id); + } + else + { + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT MAX(guid) FROM waypoint_scripts"); + id = result->Fetch()->GetUInt32(); + WorldDatabase.PExecute("INSERT INTO waypoint_scripts(guid)VALUES(%u)", id+1); + PSendSysMessage("%s%s%u|r", "|cff00ff00","Wp Event: New waypoint event added: |r|cff00ffff", id+1); + } + + return true; + } + + if (show == "listid") + { + if (!arg_id) + { + PSendSysMessage("%s%s|r", "|cff33ffff","Wp Event: You must provide waypoint script id."); + return true; + } + + id = atoi(arg_id); + + uint32 a2, a3, a4, a5, a6; + float a8, a9, a10, a11; + char const* a7; + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = %u", id); + + if (!result) + { + PSendSysMessage("%s%s%u|r", "|cff33ffff", "Wp Event: No waypoint scripts found on id: ", id); + return true; + } + + Field *fields; + + do + { + fields = result->Fetch(); + a2 = fields[0].GetUInt32(); + a3 = fields[1].GetUInt32(); + a4 = fields[2].GetUInt32(); + a5 = fields[3].GetUInt32(); + a6 = fields[4].GetUInt32(); + a7 = fields[5].GetString(); + a8 = fields[6].GetFloat(); + a9 = fields[7].GetFloat(); + a10 = fields[8].GetFloat(); + a11 = fields[9].GetFloat(); + + PSendSysMessage("|cffff33ffid:|r|cff00ffff %u|r|cff00ff00, guid: |r|cff00ffff%u|r|cff00ff00, delay: |r|cff00ffff%u|r|cff00ff00, command: |r|cff00ffff%u|r|cff00ff00, datalong: |r|cff00ffff%u|r|cff00ff00, datalong2: |r|cff00ffff%u|r|cff00ff00, datatext: |r|cff00ffff%s|r|cff00ff00, posx: |r|cff00ffff%f|r|cff00ff00, posy: |r|cff00ffff%f|r|cff00ff00, posz: |r|cff00ffff%f|r|cff00ff00, orientation: |r|cff00ffff%f|r", id, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + } + while (result->NextRow()); + } + + if (show == "del") + { + id = atoi(arg_id); + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid FROM waypoint_scripts WHERE guid = %u", id); + + if (result) + { + WorldDatabase.PExecuteLog("DELETE FROM waypoint_scripts WHERE guid = %u", id); + PSendSysMessage("%s%s%u|r","|cff00ff00","Wp Event: Waypoint script removed: ", id); + } + else + PSendSysMessage("|cffff33ffWp Event: ERROR: you have selected a non existing script: %u|r", id); + + return true; + } + + if (show == "mod") + { + if (!arg_id) + { + SendSysMessage("|cffff33ffERROR: Waypoint script guid not present.|r"); + return true; + } + + id = atoi(arg_id); + + if (!id) + { + SendSysMessage("|cffff33ffERROR: No vallid waypoint script id not present.|r"); + return true; + } + + char* arg_2 = strtok(NULL," "); + + if (!arg_2) + { + SendSysMessage("|cffff33ffERROR: No argument present.|r"); + return true; + } + + std::string arg_string = arg_2; + + if ((arg_string != "setid") && (arg_string != "delay") && (arg_string != "command") + && (arg_string != "datalong") && (arg_string != "datalong2") && (arg_string != "dataint") && (arg_string != "posx") + && (arg_string != "posy") && (arg_string != "posz") && (arg_string != "orientation")) + { + SendSysMessage("|cffff33ffERROR: No valid argument present.|r"); + return true; + } + + char* arg_3; + std::string arg_str_2 = arg_2; + arg_3 = strtok(NULL," "); + + if (!arg_3) + { + SendSysMessage("|cffff33ffERROR: No additional argument present.|r"); + return true; + } + + float coord; + + if (arg_str_2 == "setid") + { + uint32 newid = atoi(arg_3); + PSendSysMessage("%s%s|r|cff00ffff%u|r|cff00ff00%s|r|cff00ffff%u|r","|cff00ff00","Wp Event: Wypoint scipt guid: ", newid," id changed: ", id); + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET id='%u' WHERE guid='%u'", + newid, id); return true; + } + else + { + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id FROM waypoint_scripts WHERE guid='%u'",id); + + if (!result) + { + SendSysMessage("|cffff33ffERROR: You have selected an non existing waypoint script guid.|r"); + return true; + } + + if (arg_str_2 == "posx") + { + coord = atof(arg_3); + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET x='%f' WHERE guid='%u'", + coord, id); + PSendSysMessage("|cff00ff00Waypoint script:|r|cff00ffff %u|r|cff00ff00 position_x updated.|r", id); + return true; + } + else if (arg_str_2 == "posy") + { + coord = atof(arg_3); + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET y='%f' WHERE guid='%u'", + coord, id); + PSendSysMessage("|cff00ff00Waypoint script: %u position_y updated.|r", id); + return true; + } + else if (arg_str_2 == "posz") + { + coord = atof(arg_3); + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET z='%f' WHERE guid='%u'", + coord, id); + PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 position_z updated.|r", id); + return true; + } + else if (arg_str_2 == "orientation") + { + coord = atof(arg_3); + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET o='%f' WHERE guid='%u'", + coord, id); + PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 orientation updated.|r", id); + return true; + } + else if (arg_str_2 == "dataint") + { + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET %s='%u' WHERE guid='%u'", + arg_2, atoi(arg_3), id); + PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 dataint updated.|r", id); + return true; + } + else + { + std::string arg_str_3 = arg_3; + WorldDatabase.escape_string(arg_str_3); + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET %s='%s' WHERE guid='%u'", + arg_2, arg_str_3.c_str(), id); + } + } + PSendSysMessage("%s%s|r|cff00ffff%u:|r|cff00ff00 %s %s|r","|cff00ff00","Waypoint script:", id, arg_2,"updated."); + } + return true; +} + +bool ChatHandler::HandleWpModifyCommand(const char* args) +{ + sLog.outDebug("DEBUG: HandleWpModifyCommand"); + + if (!*args) + return false; + + // first arg: add del text emote spell waittime move + char* show_str = strtok((char*)args, " "); + if (!show_str) + { + return false; + } + + std::string show = show_str; + // Check + // Remember: "show" must also be the name of a column! + if ((show != "delay") && (show != "action") && (show != "action_chance") + && (show != "move_flag") && (show != "del") && (show != "move") && (show != "wpadd") +) + { + return false; + } + + // Next arg is: <PATHID> <WPNUM> <ARGUMENT> + char* arg_str = NULL; + + // Did user provide a GUID + // or did the user select a creature? + // -> variable lowguid is filled with the GUID of the NPC + uint32 pathid = 0; + uint32 point = 0; + uint32 wpGuid = 0; + Creature* target = getSelectedCreature(); + + if (!target || target->GetEntry() != VISUAL_WAYPOINT) + { + SendSysMessage("|cffff33ffERROR: You must select a waypoint.|r"); + return false; + } + + sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC"); + // The visual waypoint + Creature* wpCreature = NULL; + wpGuid = target->GetGUIDLow(); + + // Did the user select a visual spawnpoint? + if (wpGuid) + wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); + // attempt check creature existence by DB data + else + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, wpGuid); + return false; + } + // User did select a visual waypoint? + // Check the creature + if (wpCreature->GetEntry() == VISUAL_WAYPOINT) + { + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id, point FROM waypoint_data WHERE wpguid = %u", wpGuid); + + if (!result) + { + sLog.outDebug("DEBUG: HandleWpModifyCommand - No waypoint found - used 'wpguid'"); + + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow()); + // Select waypoint number from database + // Since we compare float values, we have to deal with + // some difficulties. + // Here we search for all waypoints that only differ in one from 1 thousand + // (0.001) - There is no other way to compare C++ floats with mySQL floats + // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html + const char* maxDIFF = "0.01"; + result = WorldDatabase.PQuery("SELECT id, point FROM waypoint_data WHERE (abs(position_x - %f) <= %s) and (abs(position_y - %f) <= %s) and (abs(position_z - %f) <= %s)", + wpCreature->GetPositionX(), maxDIFF, wpCreature->GetPositionY(), maxDIFF, wpCreature->GetPositionZ(), maxDIFF); + if (!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid); + return true; + } + } + sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid"); + + do + { + Field *fields = result->Fetch(); + pathid = fields[0].GetUInt32(); + point = fields[1].GetUInt32(); + } + while (result->NextRow()); + + // We have the waypoint number and the GUID of the "master npc" + // Text is enclosed in "<>", all other arguments not + arg_str = strtok((char*)NULL, " "); + } + + sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command"); + + // Check for argument + if (show != "del" && show != "move" && arg_str == NULL) + { + PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str); + return false; + } + + if (show == "del" && target) + { + PSendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff%u|r", pathid); + + // wpCreature + Creature* wpCreature = NULL; + + if (wpGuid != 0) + { + wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); + wpCreature->CombatStop(); + wpCreature->DeleteFromDB(); + wpCreature->AddObjectToRemoveList(); + } + + WorldDatabase.PExecuteLog("DELETE FROM waypoint_data WHERE id='%u' AND point='%u'", + pathid, point); + WorldDatabase.PExecuteLog("UPDATE waypoint_data SET point=point-1 WHERE id='%u' AND point>'%u'", + pathid, point); + + PSendSysMessage(LANG_WAYPOINT_REMOVED); + return true; + } // del + + if (show == "move" && target) + { + PSendSysMessage("|cff00ff00DEBUG: wp move, PathID: |r|cff00ffff%u|r", pathid); + + Player *chr = m_session->GetPlayer(); + Map *map = chr->GetMap(); + { + // wpCreature + Creature* wpCreature = NULL; + // What to do: + // Move the visual spawnpoint + // Respawn the owner of the waypoints + if (wpGuid != 0) + { + wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); + wpCreature->CombatStop(); + wpCreature->DeleteFromDB(); + wpCreature->AddObjectToRemoveList(); + // re-create + Creature* wpCreature2 = new Creature; + if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation())) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + delete wpCreature2; + return false; + } + + wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map); + map->Add(wpCreature2); + //MapManager::Instance().GetMap(npcCreature->GetMapId())->Add(wpCreature2); + } + + WorldDatabase.PExecuteLog("UPDATE waypoint_data SET position_x = '%f',position_y = '%f',position_z = '%f' where id = '%u' AND point='%u'", + chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), pathid, point); + + PSendSysMessage(LANG_WAYPOINT_CHANGED); + } + return true; + } // move + + const char *text = arg_str; + + if (text == 0) + { + // show_str check for present in list of correct values, no sql injection possible + WorldDatabase.PExecuteLog("UPDATE waypoint_data SET %s=NULL WHERE id='%u' AND point='%u'", + show_str, pathid, point); + } + else + { + // show_str check for present in list of correct values, no sql injection possible + std::string text2 = text; + WorldDatabase.escape_string(text2); + WorldDatabase.PExecuteLog("UPDATE waypoint_data SET %s='%s' WHERE id='%u' AND point='%u'", + show_str, text2.c_str(), pathid, point); + } + + PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str); + return true; +} + +bool ChatHandler::HandleWpShowCommand(const char* args) +{ + sLog.outDebug("DEBUG: HandleWpShowCommand"); + + if (!*args) + return false; + + // first arg: on, off, first, last + char* show_str = strtok((char*)args, " "); + if (!show_str) + return false; + + // second arg: GUID (optional, if a creature is selected) + char* guid_str = strtok((char*)NULL, " "); + sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str); + + uint32 pathid = 0; + Creature* target = getSelectedCreature(); + + // Did player provide a PathID? + + if (!guid_str) + { + sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str"); + // No PathID provided + // -> Player must have selected a creature + + if (!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pathid = target->GetWaypointPath(); + } + else + { + sLog.outDebug("|cff00ff00DEBUG: HandleWpShowCommand: PathID provided|r"); + // PathID provided + // Warn if player also selected a creature + // -> Creature selection is ignored <- + if (target) + SendSysMessage(LANG_WAYPOINT_CREATSELECTED); + + pathid = atoi((char*)guid_str); + } + + sLog.outDebug("DEBUG: HandleWpShowCommand: danach"); + + std::string show = show_str; + uint32 Maxpoint; + + sLog.outDebug("DEBUG: HandleWpShowCommand: PathID: %u", pathid); + + //PSendSysMessage("wpshow - show: %s", show); + + // Show info for the selected waypoint + if (show == "info") + { + // Check if the user did specify a visual waypoint + if (target->GetEntry() != VISUAL_WAYPOINT) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id, point, delay, move_flag, action, action_chance FROM waypoint_data WHERE wpguid = %u", target->GetGUIDLow()); + + if (!result) + { + SendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM); + return true; + } + + SendSysMessage("|cff00ffffDEBUG: wp show info:|r"); + do + { + Field *fields = result->Fetch(); + pathid = fields[0].GetUInt32(); + uint32 point = fields[1].GetUInt32(); + uint32 delay = fields[2].GetUInt32(); + uint32 flag = fields[3].GetUInt32(); + uint32 ev_id = fields[4].GetUInt32(); + uint32 ev_chance = fields[5].GetUInt32(); + + PSendSysMessage("|cff00ff00Show info: for current point: |r|cff00ffff%u|r|cff00ff00, Path ID: |r|cff00ffff%u|r", point, pathid); + PSendSysMessage("|cff00ff00Show info: delay: |r|cff00ffff%u|r", delay); + PSendSysMessage("|cff00ff00Show info: Move flag: |r|cff00ffff%u|r", flag); + PSendSysMessage("|cff00ff00Show info: Waypoint event: |r|cff00ffff%u|r", ev_id); + PSendSysMessage("|cff00ff00Show info: Event chance: |r|cff00ffff%u|r", ev_chance); + } + while (result->NextRow()); + + return true; + } + + if (show == "on") + { + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT point, position_x,position_y,position_z FROM waypoint_data WHERE id = '%u'", pathid); + + if (!result) + { + SendSysMessage("|cffff33ffPath no found.|r"); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage("|cff00ff00DEBUG: wp on, PathID: |cff00ffff%u|r", pathid); + + // Delete all visuals for this NPC + QueryResult_AutoPtr result2 = WorldDatabase.PQuery("SELECT wpguid FROM waypoint_data WHERE id = '%u' and wpguid <> 0", pathid); + + if (result2) + { + bool hasError = false; + do + { + Field *fields = result2->Fetch(); + uint32 wpguid = fields[0].GetUInt32(); + Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT)); + + if (!pCreature) + { + PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid); + hasError = true; + WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid); + } + else + { + pCreature->CombatStop(); + pCreature->DeleteFromDB(); + pCreature->AddObjectToRemoveList(); + } + + } + while (result2->NextRow()); + + if (hasError) + { + PSendSysMessage(LANG_WAYPOINT_TOOFAR1); + PSendSysMessage(LANG_WAYPOINT_TOOFAR2); + PSendSysMessage(LANG_WAYPOINT_TOOFAR3); + } + } + + do + { + Field *fields = result->Fetch(); + uint32 point = fields[0].GetUInt32(); + float x = fields[1].GetFloat(); + float y = fields[2].GetFloat(); + float z = fields[3].GetFloat(); + + uint32 id = VISUAL_WAYPOINT; + + Player *chr = m_session->GetPlayer(); + Map *map = chr->GetMap(); + float o = chr->GetOrientation(); + + Creature* wpCreature = new Creature; + if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); + delete wpCreature; + return false; + } + + sLog.outDebug("DEBUG: UPDATE waypoint_data SET wpguid = '%u"); + // set "wpguid" column to the visual waypoint + WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), pathid, point); + + wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map); + map->Add(wpCreature); + + if (target) + { + wpCreature->SetDisplayId(target->GetDisplayId()); + wpCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5); + wpCreature->SetLevel(point > MAX_LEVEL ? MAX_LEVEL : point); + } + } + while (result->NextRow()); + + SendSysMessage("|cff00ff00Showing the current creature's path.|r"); + return true; + } + + if (show == "first") + { + PSendSysMessage("|cff00ff00DEBUG: wp first, GUID: %u|r", pathid); + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z FROM waypoint_data WHERE point='1' AND id = '%u'",pathid); + if (!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND, pathid); + SetSentErrorMessage(true); + return false; + } + + Field *fields = result->Fetch(); + float x = fields[0].GetFloat(); + float y = fields[1].GetFloat(); + float z = fields[2].GetFloat(); + uint32 id = VISUAL_WAYPOINT; + + Player *chr = m_session->GetPlayer(); + float o = chr->GetOrientation(); + Map *map = chr->GetMap(); + + Creature* pCreature = new Creature; + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); + delete pCreature; + return false; + } + + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map); + map->Add(pCreature); + + if (target) + { + pCreature->SetDisplayId(target->GetDisplayId()); + pCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5); + } + + return true; + } + + if (show == "last") + { + PSendSysMessage("|cff00ff00DEBUG: wp last, PathID: |r|cff00ffff%u|r", pathid); + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT MAX(point) FROM waypoint_data WHERE id = '%u'",pathid); + if (result) + Maxpoint = (*result)[0].GetUInt32(); + else + Maxpoint = 0; + + result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z FROM waypoint_data WHERE point ='%u' AND id = '%u'",Maxpoint, pathid); + if (!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, pathid); + SetSentErrorMessage(true); + return false; + } + Field *fields = result->Fetch(); + float x = fields[0].GetFloat(); + float y = fields[1].GetFloat(); + float z = fields[2].GetFloat(); + uint32 id = VISUAL_WAYPOINT; + + Player *chr = m_session->GetPlayer(); + float o = chr->GetOrientation(); + Map *map = chr->GetMap(); + + Creature* pCreature = new Creature; + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) + { + PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); + delete pCreature; + return false; + } + + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map); + map->Add(pCreature); + + if (target) + { + pCreature->SetDisplayId(target->GetDisplayId()); + pCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5); + } + + return true; + } + + if (show == "off") + { + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%u'", 1); + if (!result) + { + SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + bool hasError = false; + do + { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT)); + if (!pCreature) + { + PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid); + hasError = true; + WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid); + } + else + { + pCreature->CombatStop(); + pCreature->DeleteFromDB(); + pCreature->AddObjectToRemoveList(); + } + } + while (result->NextRow()); + // set "wpguid" column to "empty" - no visual waypoint spawned + WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '0'"); + //WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'"); + + if (hasError) + { + PSendSysMessage(LANG_WAYPOINT_TOOFAR1); + PSendSysMessage(LANG_WAYPOINT_TOOFAR2); + PSendSysMessage(LANG_WAYPOINT_TOOFAR3); + } + + SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED); + return true; + } + + PSendSysMessage("|cffff33ffDEBUG: wpshow - no valid command found|r"); + return true; +} + +//////////// WAYPOINT COMMANDS // + +//rename characters +bool ChatHandler::HandleCharacterRenameCommand(const char* args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + if (target) + { + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + PSendSysMessage(LANG_RENAME_PLAYER, GetNameLink(target).c_str()); + target->SetAtLoginFlag(AT_LOGIN_RENAME); + } + else + { + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + return false; + + std::string oldNameLink = playerLink(target_name); + + PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid)); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(target_guid)); + } + + return true; +} + +// customize characters +bool ChatHandler::HandleCharacterCustomizeCommand(const char* args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + if (target) + { + PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str()); + target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow()); + } + else + { + std::string oldNameLink = playerLink(target_name); + + PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid)); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(target_guid)); + } + + return true; +} + +bool ChatHandler::HandleCharacterReputationCommand(const char* args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + LocaleConstant loc = GetSessionDbcLocale(); + + FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList(); + for (FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr) + { + FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID); + char const* factionName = factionEntry ? factionEntry->name[loc] : "#Not found#"; + ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); + std::string rankName = GetTrinityString(ReputationRankStrIndex[rank]); + std::ostringstream ss; + if (m_session) + ss << itr->second.ID << " - |cffffffff|Hfaction:" << itr->second.ID << "|h[" << factionName << " " << localeNames[loc] << "]|h|r"; + else + ss << itr->second.ID << " - " << factionName << " " << localeNames[loc]; + + ss << " " << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ")"; + + if (itr->second.Flags & FACTION_FLAG_VISIBLE) + ss << GetTrinityString(LANG_FACTION_VISIBLE); + if (itr->second.Flags & FACTION_FLAG_AT_WAR) + ss << GetTrinityString(LANG_FACTION_ATWAR); + if (itr->second.Flags & FACTION_FLAG_PEACE_FORCED) + ss << GetTrinityString(LANG_FACTION_PEACE_FORCED); + if (itr->second.Flags & FACTION_FLAG_HIDDEN) + ss << GetTrinityString(LANG_FACTION_HIDDEN); + if (itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED) + ss << GetTrinityString(LANG_FACTION_INVISIBLE_FORCED); + if (itr->second.Flags & FACTION_FLAG_INACTIVE) + ss << GetTrinityString(LANG_FACTION_INACTIVE); + + SendSysMessage(ss.str().c_str()); + } + return true; +} + +//change standstate +bool ChatHandler::HandleModifyStandStateCommand(const char* args) +{ + if (!*args) + return false; + + uint32 anim_id = atoi((char*)args); + m_session->GetPlayer()->SetUInt32Value(UNIT_NPC_EMOTESTATE , anim_id); + + return true; +} + +bool ChatHandler::HandleHonorAddCommand(const char* args) +{ + if (!*args) + return false; + + Player *target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + uint32 amount = (uint32)atoi(args); + target->RewardHonor(NULL, 1, amount); + return true; +} + +bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/) +{ + Unit *target = getSelectedUnit(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + m_session->GetPlayer()->RewardHonor(target, 1); + return true; +} + +bool ChatHandler::HandleHonorUpdateCommand(const char* /*args*/) +{ + Player *target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + target->UpdateHonorFields(); + return true; +} + +bool ChatHandler::HandleLookupEventCommand(const char* args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + bool found = false; + + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + + for (uint32 id = 0; id < events.size(); ++id) + { + GameEventData const& eventData = events[id]; + + std::string descr = eventData.description; + if (descr.empty()) + continue; + + if (Utf8FitTo(descr, wnamepart)) + { + char const* active = activeEvents.find(id) != activeEvents.end() ? GetTrinityString(LANG_ACTIVE) : ""; + + if (m_session) + PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active); + else + PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active); + + if (!found) + found = true; + } + } + + if (!found) + SendSysMessage(LANG_NOEVENTFOUND); + + return true; +} + +bool ChatHandler::HandleEventActiveListCommand(const char* /*args*/) +{ + uint32 counter = 0; + + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + + char const* active = GetTrinityString(LANG_ACTIVE); + + for (GameEventMgr::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr) + { + uint32 event_id = *itr; + GameEventData const& eventData = events[event_id]; + + if (m_session) + PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active); + else + PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active); + + ++counter; + } + + if (counter == 0) + SendSysMessage(LANG_NOEVENTFOUND); + + return true; +} + +bool ChatHandler::HandleEventInfoCommand(const char* args) +{ + if (!*args) + return false; + + // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameevent"); + if (!cId) + return false; + + uint32 event_id = atoi(cId); + + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + + if (event_id >=events.size()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventData const& eventData = events[event_id]; + if (!eventData.isValid()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + bool active = activeEvents.find(event_id) != activeEvents.end(); + char const* activeStr = active ? GetTrinityString(LANG_ACTIVE) : ""; + + std::string startTimeStr = TimeToTimestampStr(eventData.start); + std::string endTimeStr = TimeToTimestampStr(eventData.end); + + uint32 delay = gameeventmgr.NextCheck(event_id); + time_t nextTime = time(NULL)+delay; + std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-"; + + std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE); + std::string lengthStr = secsToTimeString(eventData.length * MINUTE); + + PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr, + startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(), + nextStr.c_str()); + return true; +} + +bool ChatHandler::HandleEventStartCommand(const char* args) +{ + if (!*args) + return false; + + // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameevent"); + if (!cId) + return false; + + int32 event_id = atoi(cId); + + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + + if (event_id < 1 || event_id >=events.size()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventData const& eventData = events[event_id]; + if (!eventData.isValid()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + if (activeEvents.find(event_id) != activeEvents.end()) + { + PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id); + SetSentErrorMessage(true); + return false; + } + + gameeventmgr.StartEvent(event_id,true); + return true; +} + +bool ChatHandler::HandleEventStopCommand(const char* args) +{ + if (!*args) + return false; + + // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameevent"); + if (!cId) + return false; + + int32 event_id = atoi(cId); + + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + + if (event_id < 1 || event_id >=events.size()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventData const& eventData = events[event_id]; + if (!eventData.isValid()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + + if (activeEvents.find(event_id) == activeEvents.end()) + { + PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id); + SetSentErrorMessage(true); + return false; + } + + gameeventmgr.StopEvent(event_id,true); + return true; +} + +bool ChatHandler::HandleCombatStopCommand(const char* args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + target->CombatStop(); + target->getHostileRefManager().deleteReferences(); + return true; +} + +void ChatHandler::HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id) +{ + uint32 classmask = player->getClassMask(); + + for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) + { + SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j); + if (!skillLine) + continue; + + // wrong skill + if (skillLine->skillId != skill_id) + continue; + + // not high rank + if (skillLine->forward_spellid) + continue; + + // skip racial skills + if (skillLine->racemask != 0) + continue; + + // skip wrong class skills + if (skillLine->classmask && (skillLine->classmask & classmask) == 0) + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,player,false)) + continue; + + player->learnSpell(skillLine->spellId, false); + } +} + +bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/) +{ + + for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i) + { + SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i); + if (!skillInfo) + continue; + + if ((skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY) && + skillInfo->canLink) // only prof. with recipes have + { + HandleLearnSkillRecipesHelper(m_session->GetPlayer(),skillInfo->id); + } + } + + SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT); + return true; +} + +bool ChatHandler::HandleLearnAllRecipesCommand(const char* args) +{ + // Learns all recipes of specified profession and sets skill to max + // Example: .learn all_recipes enchanting + + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + return false; + } + + if (!*args) + return false; + + std::wstring wnamepart; + + if (!Utf8toWStr(args,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + std::string name; + + SkillLineEntry const *targetSkillInfo = NULL; + for (uint32 i = 1; i < sSkillLineStore.GetNumRows(); ++i) + { + SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i); + if (!skillInfo) + continue; + + if ((skillInfo->categoryId != SKILL_CATEGORY_PROFESSION && + skillInfo->categoryId != SKILL_CATEGORY_SECONDARY) || + !skillInfo->canLink) // only prof with recipes have set + continue; + + int loc = GetSessionDbcLocale(); + name = skillInfo->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = skillInfo->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + targetSkillInfo = skillInfo; + break; + } + } + + if (!targetSkillInfo) + return false; + + HandleLearnSkillRecipesHelper(target,targetSkillInfo->id); + + uint16 maxLevel = target->GetPureMaxSkillValue(targetSkillInfo->id); + target->SetSkill(targetSkillInfo->id, target->GetSkillStep(targetSkillInfo->id), maxLevel, maxLevel); + PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str()); + return true; +} + +bool ChatHandler::HandleLookupPlayerIpCommand(const char* args) +{ + + if (!*args) + return false; + + std::string ip = strtok ((char*)args, " "); + char* limit_str = strtok (NULL, " "); + int32 limit = limit_str ? atoi (limit_str) : -1; + + LoginDatabase.escape_string (ip); + + QueryResult_AutoPtr result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ()); + + return LookupPlayerSearchCommand (result,limit); +} + +bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args) +{ + if (!*args) + return false; + + std::string account = strtok ((char*)args, " "); + char* limit_str = strtok (NULL, " "); + int32 limit = limit_str ? atoi (limit_str) : -1; + + if (!AccountMgr::normalizeString (account)) + return false; + + LoginDatabase.escape_string (account); + + QueryResult_AutoPtr result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ()); + + return LookupPlayerSearchCommand (result,limit); +} + +bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args) +{ + + if (!*args) + return false; + + std::string email = strtok ((char*)args, " "); + char* limit_str = strtok (NULL, " "); + int32 limit = limit_str ? atoi (limit_str) : -1; + + LoginDatabase.escape_string (email); + + QueryResult_AutoPtr result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ()); + + return LookupPlayerSearchCommand (result,limit); +} + +bool ChatHandler::LookupPlayerSearchCommand(QueryResult_AutoPtr result, int32 limit) +{ + if (!result) + { + PSendSysMessage(LANG_NO_PLAYERS_FOUND); + SetSentErrorMessage(true); + return false; + } + + int i =0; + do + { + Field* fields = result->Fetch(); + uint32 acc_id = fields[0].GetUInt32(); + std::string acc_name = fields[1].GetCppString(); + + QueryResult_AutoPtr chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id); + if (chars) + { + PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id); + + uint64 guid = 0; + std::string name; + + do + { + Field* charfields = chars->Fetch(); + guid = charfields[0].GetUInt64(); + name = charfields[1].GetCppString(); + + PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid); + ++i; + + } while (chars->NextRow() && (limit == -1 || i < limit)); + } + } while (result->NextRow()); + + if (i == 0) // empty accounts only + { + PSendSysMessage(LANG_NO_PLAYERS_FOUND); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +/// Triggering corpses expire check in world +bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/) +{ + CorpsesErase(); + return true; +} + +bool ChatHandler::HandleRepairitemsCommand(const char* args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + // Repair items + target->DurabilityRepairAll(false, 0, false); + + PSendSysMessage(LANG_YOU_REPAIR_ITEMS, GetNameLink(target).c_str()); + if (needReportToTarget(target)) + ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetNameLink().c_str()); + return true; +} + +bool ChatHandler::HandleWaterwalkCommand(const char* args) +{ + if (!*args) + return false; + + Player *player = getSelectedPlayer(); + + if (!player) + { + PSendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(player, 0)) + return false; + + if (strncmp(args, "on", 3) == 0) + player->SetMovement(MOVE_WATER_WALK); // ON + else if (strncmp(args, "off", 4) == 0) + player->SetMovement(MOVE_LAND_WALK); // OFF + else + { + SendSysMessage(LANG_USE_BOL); + return false; + } + + PSendSysMessage(LANG_YOU_SET_WATERWALK, args, GetNameLink(player).c_str()); + if (needReportToTarget(player)) + ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetNameLink().c_str()); + return true; +} + +bool ChatHandler::HandleCreatePetCommand(const char* /*args*/) +{ + Player *player = m_session->GetPlayer(); + Creature *creatureTarget = getSelectedCreature(); + + if (!creatureTarget || creatureTarget->isPet() || creatureTarget->GetTypeId() == TYPEID_PLAYER) + { + PSendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + CreatureInfo const* cInfo = objmgr.GetCreatureTemplate(creatureTarget->GetEntry()); + // Creatures with family 0 crashes the server + if (cInfo->family == 0) + { + PSendSysMessage("This creature cannot be tamed. (family id: 0)."); + SetSentErrorMessage(true); + return false; + } + + if (player->GetPetGUID()) + { + PSendSysMessage("You already have a pet"); + SetSentErrorMessage(true); + return false; + } + + // Everything looks OK, create new pet + Pet* pet = new Pet(player, HUNTER_PET); + + if (!pet) + return false; + + if (!pet->CreateBaseAtCreature(creatureTarget)) + { + delete pet; + PSendSysMessage("Error 1"); + return false; + } + + creatureTarget->setDeathState(JUST_DIED); + creatureTarget->RemoveCorpse(); + creatureTarget->SetHealth(0); // just for nice GM-mode view + + pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, player->GetGUID()); + pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, player->getFaction()); + + if (!pet->InitStatsForLevel(creatureTarget->getLevel())) + { + sLog.outError("ERROR: InitStatsForLevel() in EffectTameCreature failed! Pet deleted."); + PSendSysMessage("Error 2"); + delete pet; + return false; + } + + // prepare visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1); + + pet->GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true); + // this enables pet details window (Shift+P) + pet->InitPetCreateSpells(); + pet->SetHealth(pet->GetMaxHealth()); + + pet->GetMap()->Add(pet->ToCreature()); + + // visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()); + + player->SetMinion(pet, true); + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + player->PetSpellInitialize(); + + return true; +} + +bool ChatHandler::HandlePetLearnCommand(const char* args) +{ + if (!*args) + return false; + + Player *plr = m_session->GetPlayer(); + Pet *pet = plr->GetPet(); + + if (!pet) + { + PSendSysMessage("You have no pet"); + SetSentErrorMessage(true); + return false; + } + + uint32 spellId = extractSpellIdFromLink((char*)args); + + if (!spellId || !sSpellStore.LookupEntry(spellId)) + return false; + + // Check if pet already has it + if (pet->HasSpell(spellId)) + { + PSendSysMessage("Pet already has spell: %u", spellId); + SetSentErrorMessage(true); + return false; + } + + // Check if spell is valid + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo)) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spellId); + SetSentErrorMessage(true); + return false; + } + + pet->learnSpell(spellId); + + PSendSysMessage("Pet has learned spell %u", spellId); + return true; +} + +bool ChatHandler::HandlePetUnlearnCommand(const char *args) +{ + if (!*args) + return false; + + Player *plr = m_session->GetPlayer(); + Pet *pet = plr->GetPet(); + + if (!pet) + { + PSendSysMessage("You have no pet"); + SetSentErrorMessage(true); + return false; + } + + uint32 spellId = extractSpellIdFromLink((char*)args); + + if (pet->HasSpell(spellId)) + pet->removeSpell(spellId, false); + else + PSendSysMessage("Pet doesn't have that spell"); + + return true; +} + +bool ChatHandler::HandlePetTpCommand(const char *args) +{ + if (!*args) + return false; + + Player *plr = m_session->GetPlayer(); + Pet *pet = plr->GetPet(); + + if (!pet) + { + PSendSysMessage("You have no pet"); + SetSentErrorMessage(true); + return false; + } + + uint32 tp = atol(args); + + //pet->SetTP(tp); + + PSendSysMessage("Pet's tp changed to %u", tp); + return true; +} + +bool ChatHandler::HandleActivateObjectCommand(const char *args) +{ + if (!*args) + return false; + + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + // Activate + obj->SetLootState(GO_READY); + obj->UseDoorOrButton(10000); + + PSendSysMessage("Object activated!"); + + return true; +} + +// add creature, temp only +bool ChatHandler::HandleTempAddSpwCommand(const char* args) +{ + if (!*args) + return false; + char* charID = strtok((char*)args, " "); + if (!charID) + return false; + + Player *chr = m_session->GetPlayer(); + + uint32 id = atoi(charID); + if (!id) + return false; + + chr->SummonCreature(id, *chr, TEMPSUMMON_CORPSE_DESPAWN, 120); + + return true; +} + +// add go, temp only +bool ChatHandler::HandleTempGameObjectCommand(const char* args) +{ + if (!*args) + return false; + char* charID = strtok((char*)args, " "); + if (!charID) + return false; + + Player *chr = m_session->GetPlayer(); + + char* spawntime = strtok(NULL, " "); + uint32 spawntm = 300; + + if (spawntime) + spawntm = atoi((char*)spawntime); + + float x = chr->GetPositionX(); + float y = chr->GetPositionY(); + float z = chr->GetPositionZ(); + float ang = chr->GetOrientation(); + + float rot2 = sin(ang/2); + float rot3 = cos(ang/2); + + uint32 id = atoi(charID); + + chr->SummonGameObject(id,x,y,z,ang,0,0,rot2,rot3,spawntm); + + return true; +} + +bool ChatHandler::HandleNpcAddFormationCommand(const char* args) +{ + if (!*args) + return false; + + uint32 leaderGUID = (uint32) atoi((char*)args); + Creature *pCreature = getSelectedCreature(); + + if (!pCreature || !pCreature->GetDBTableGUIDLow()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint32 lowguid = pCreature->GetDBTableGUIDLow(); + if (pCreature->GetFormation()) + { + PSendSysMessage("Selected creature is already member of group %u", pCreature->GetFormation()->GetId()); + return false; + } + + if (!lowguid) + return false; + + Player *chr = m_session->GetPlayer(); + FormationInfo *group_member; + + group_member = new FormationInfo; + group_member->follow_angle = (pCreature->GetAngle(chr) - chr->GetOrientation()) * 180 / M_PI; + group_member->follow_dist = sqrtf(pow(chr->GetPositionX() - pCreature->GetPositionX(),int(2))+pow(chr->GetPositionY()-pCreature->GetPositionY(),int(2))); + group_member->leaderGUID = leaderGUID; + group_member->groupAI = 0; + + CreatureGroupMap[lowguid] = group_member; + pCreature->SearchFormation(); + + WorldDatabase.PExecuteLog("INSERT INTO creature_formations (leaderGUID, memberGUID, dist, angle, groupAI) VALUES ('%u','%u','%f', '%f', '%u')", + leaderGUID, lowguid, group_member->follow_dist, group_member->follow_angle, group_member->groupAI); + + PSendSysMessage("Creature %u added to formation with leader %u", lowguid, leaderGUID); + + return true; + } + +bool ChatHandler::HandleNpcSetLinkCommand(const char* args) +{ + if (!*args) + return false; + + uint32 linkguid = (uint32) atoi((char*)args); + + Creature* pCreature = getSelectedCreature(); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (!pCreature->GetDBTableGUIDLow()) + { + PSendSysMessage("Selected creature isn't in creature table", pCreature->GetGUIDLow()); + SetSentErrorMessage(true); + return false; + } + + if (!objmgr.SetCreatureLinkedRespawn(pCreature->GetDBTableGUIDLow(), linkguid)) + { + PSendSysMessage("Selected creature can't link with guid '%u'", linkguid); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage("LinkGUID '%u' added to creature with DBTableGUID: '%u'", linkguid, pCreature->GetDBTableGUIDLow()); + return true; +} + +bool ChatHandler::HandleLookupTitleCommand(const char* args) +{ + if (!*args) + return false; + + // can be NULL in console call + Player* target = getSelectedPlayer(); + + // title name have single string arg for player name + char const* targetName = target ? target->GetName() : "NAME"; + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + uint32 counter = 0; // Counter for figure out that we found smth. + + // Search in CharTitles.dbc + for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++) + { + CharTitlesEntry const *titleInfo = sCharTitlesStore.LookupEntry(id); + if (titleInfo) + { + int loc = GetSessionDbcLocale(); + std::string name = titleInfo->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = titleInfo->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + char const* knownStr = target && target->HasTitle(titleInfo) ? GetTrinityString(LANG_KNOWN) : ""; + + char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index + ? GetTrinityString(LANG_ACTIVE) + : ""; + + char titleNameStr[80]; + snprintf(titleNameStr,80,name.c_str(),targetName); + + // send title in "id (idx:idx) - [namedlink locale]" format + if (m_session) + PSendSysMessage(LANG_TITLE_LIST_CHAT,id,titleInfo->bit_index,id,titleNameStr,localeNames[loc],knownStr,activeStr); + else + PSendSysMessage(LANG_TITLE_LIST_CONSOLE,id,titleInfo->bit_index,titleNameStr,localeNames[loc],knownStr,activeStr); + + ++counter; + } + } + } + if (counter == 0) // if counter == 0 then we found nth + SendSysMessage(LANG_COMMAND_NOTITLEFOUND); + return true; +} + +bool ChatHandler::HandleTitlesAddCommand(const char* args) +{ + // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r + char* id_p = extractKeyFromLink((char*)args,"Htitle"); + if (!id_p) + return false; + + int32 id = atoi(id_p); + if (id <= 0) + { + PSendSysMessage(LANG_INVALID_TITLE_ID, id); + SetSentErrorMessage(true); + return false; + } + + Player * target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); + if (!titleInfo) + { + PSendSysMessage(LANG_INVALID_TITLE_ID, id); + SetSentErrorMessage(true); + return false; + } + + std::string tNameLink = GetNameLink(target); + + char const* targetName = target->GetName(); + char titleNameStr[80]; + snprintf(titleNameStr,80,titleInfo->name[GetSessionDbcLocale()],targetName); + + target->SetTitle(titleInfo); + PSendSysMessage(LANG_TITLE_ADD_RES, id, titleNameStr, tNameLink.c_str()); + + return true; +} + +bool ChatHandler::HandleTitlesRemoveCommand(const char* args) +{ + // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r + char* id_p = extractKeyFromLink((char*)args,"Htitle"); + if (!id_p) + return false; + + int32 id = atoi(id_p); + if (id <= 0) + { + PSendSysMessage(LANG_INVALID_TITLE_ID, id); + SetSentErrorMessage(true); + return false; + } + + Player * target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); + if (!titleInfo) + { + PSendSysMessage(LANG_INVALID_TITLE_ID, id); + SetSentErrorMessage(true); + return false; + } + + target->SetTitle(titleInfo,true); + + std::string tNameLink = GetNameLink(target); + + char const* targetName = target->GetName(); + char titleNameStr[80]; + snprintf(titleNameStr,80,titleInfo->name[GetSessionDbcLocale()],targetName); + + PSendSysMessage(LANG_TITLE_REMOVE_RES, id, titleNameStr, tNameLink.c_str()); + + if (!target->HasTitle(target->GetInt32Value(PLAYER_CHOSEN_TITLE))) + { + target->SetUInt32Value(PLAYER_CHOSEN_TITLE,0); + PSendSysMessage(LANG_CURRENT_TITLE_RESET, tNameLink.c_str()); + } + + return true; +} + +//Edit Player KnownTitles +bool ChatHandler::HandleTitlesSetMaskCommand(const char* args) +{ + if (!*args) + return false; + + uint64 titles = 0; + + sscanf((char*)args, UI64FMTD, &titles); + + Player *target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + uint64 titles2 = titles; + + for (uint32 i = 1; i < sCharTitlesStore.GetNumRows(); ++i) + if (CharTitlesEntry const* tEntry = sCharTitlesStore.LookupEntry(i)) + titles2 &= ~(uint64(1) << tEntry->bit_index); + + titles &= ~titles2; // remove not existed titles + + target->SetUInt64Value(PLAYER__FIELD_KNOWN_TITLES, titles); + SendSysMessage(LANG_DONE); + + if (!target->HasTitle(target->GetInt32Value(PLAYER_CHOSEN_TITLE))) + { + target->SetUInt32Value(PLAYER_CHOSEN_TITLE,0); + PSendSysMessage(LANG_CURRENT_TITLE_RESET,GetNameLink(target).c_str()); + } + + return true; +} + +bool ChatHandler::HandleCharacterTitlesCommand(const char* args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + LocaleConstant loc = GetSessionDbcLocale(); + char const* targetName = target->GetName(); + char const* knownStr = GetTrinityString(LANG_KNOWN); + + // Search in CharTitles.dbc + for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++) + { + CharTitlesEntry const *titleInfo = sCharTitlesStore.LookupEntry(id); + if (titleInfo && target->HasTitle(titleInfo)) + { + std::string name = titleInfo->name[loc]; + if (name.empty()) + continue; + + char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index + ? GetTrinityString(LANG_ACTIVE) + : ""; + + char titleNameStr[80]; + snprintf(titleNameStr,80,name.c_str(),targetName); + + // send title in "id (idx:idx) - [namedlink locale]" format + if (m_session) + PSendSysMessage(LANG_TITLE_LIST_CHAT,id,titleInfo->bit_index,id,titleNameStr,localeNames[loc],knownStr,activeStr); + else + PSendSysMessage(LANG_TITLE_LIST_CONSOLE,id,titleInfo->bit_index,name.c_str(),localeNames[loc],knownStr,activeStr); + } + } + return true; +} + +bool ChatHandler::HandleTitlesCurrentCommand(const char* args) +{ + // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r + char* id_p = extractKeyFromLink((char*)args,"Htitle"); + if (!id_p) + return false; + + int32 id = atoi(id_p); + if (id <= 0) + { + PSendSysMessage(LANG_INVALID_TITLE_ID, id); + SetSentErrorMessage(true); + return false; + } + + Player * target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); + if (!titleInfo) + { + PSendSysMessage(LANG_INVALID_TITLE_ID, id); + SetSentErrorMessage(true); + return false; + } + + std::string tNameLink = GetNameLink(target); + + target->SetTitle(titleInfo); // to be sure that title now known + target->SetUInt32Value(PLAYER_CHOSEN_TITLE,titleInfo->bit_index); + + PSendSysMessage(LANG_TITLE_CURRENT_RES, id, titleInfo->name[GetSessionDbcLocale()], tNameLink.c_str()); + + return true; +} diff --git a/src/server/game/Chat/Level3.cpp b/src/server/game/Chat/Level3.cpp new file mode 100644 index 00000000000..f7ced44922b --- /dev/null +++ b/src/server/game/Chat/Level3.cpp @@ -0,0 +1,7743 @@ +/* +* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> +* +* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "AuctionHouseMgr.h" +#include "AccountMgr.h" +#include "PlayerDump.h" +#include "SpellMgr.h" +#include "Player.h" +#include "Opcodes.h" +#include "GameObject.h" +#include "Chat.h" +#include "Log.h" +#include "Guild.h" +#include "ObjectAccessor.h" +#include "MapManager.h" +#include "Language.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" +#include "Weather.h" +#include "PointMovementGenerator.h" +#include "TargetedMovementGenerator.h" +#include "SkillDiscovery.h" +#include "SkillExtraItems.h" +#include "SystemConfig.h" +#include "Config/ConfigEnv.h" +#include "Util.h" +#include "ItemEnchantmentMgr.h" +#include "BattleGroundMgr.h" +#include "InstanceSaveMgr.h" +#include "InstanceData.h" +#include "AuctionHouseBot.h" +#include "CreatureEventAIMgr.h" +#include "SpellAuraEffects.h" +#include "DBCEnums.h" +#include "ConditionMgr.h" + +bool ChatHandler::HandleAHBotOptionsCommand(const char *args) +{ + uint32 ahMapID = 0; + char * opt = strtok((char*)args, " "); + char * ahMapIdStr = strtok(NULL, " "); + if (ahMapIdStr) + { + ahMapID = (uint32) strtoul(ahMapIdStr, NULL, 0); + switch (ahMapID) + { + case 2: + case 6: + case 7: + break; + default: + opt = NULL; + break; + } + } + if (!opt) + { + PSendSysMessage("Syntax is: ahbotoptions $option $ahMapID (2, 6 or 7) $parameter"); + PSendSysMessage("Try ahbotoptions help to see a list of options."); + return false; + } + int l = strlen(opt); + + if (strncmp(opt,"help",l) == 0) + { + PSendSysMessage("AHBot commands:"); + PSendSysMessage("ahexpire"); + PSendSysMessage("minitems"); + PSendSysMessage("maxitems"); + //PSendSysMessage(""); + //PSendSysMessage(""); + PSendSysMessage("percentages"); + PSendSysMessage("minprice"); + PSendSysMessage("maxprice"); + PSendSysMessage("minbidprice"); + PSendSysMessage("maxbidprice"); + PSendSysMessage("maxstack"); + PSendSysMessage("buyerprice"); + PSendSysMessage("bidinterval"); + PSendSysMessage("bidsperinterval"); + return true; + } + else if (strncmp(opt,"ahexpire",l) == 0) + { + if (!ahMapIdStr) + { + PSendSysMessage("Syntax is: ahbotoptions ahexpire $ahMapID (2, 6 or 7)"); + return false; + } + auctionbot.Commands(0, ahMapID, NULL, NULL); + } + else if (strncmp(opt,"minitems",l) == 0) + { + char * param1 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1)) + { + PSendSysMessage("Syntax is: ahbotoptions minitems $ahMapID (2, 6 or 7) $minItems"); + return false; + } + auctionbot.Commands(1, ahMapID, NULL, param1); + } + else if (strncmp(opt,"maxitems",l) == 0) + { + char * param1 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1)) + { + PSendSysMessage("Syntax is: ahbotoptions maxitems $ahMapID (2, 6 or 7) $maxItems"); + return false; + } + auctionbot.Commands(2, ahMapID, NULL, param1); + } + else if (strncmp(opt,"mintime",l) == 0) + { + PSendSysMessage("ahbotoptions mintime has been deprecated"); + return false; + /* + char * param1 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1)) + { + PSendSysMessage("Syntax is: ahbotoptions mintime $ahMapID (2, 6 or 7) $mintime"); + return false; + } + auctionbot.Commands(3, ahMapID, NULL, param1); + */ + } + else if (strncmp(opt,"maxtime",l) == 0) + { + PSendSysMessage("ahbotoptions maxtime has been deprecated"); + return false; + /* + char * param1 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1)) + { + PSendSysMessage("Syntax is: ahbotoptions maxtime $ahMapID (2, 6 or 7) $maxtime"); + return false; + } + auctionbot.Commands(4, ahMapID, NULL, param1); + */ + } + else if (strncmp(opt,"percentages",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + char * param3 = strtok(NULL, " "); + char * param4 = strtok(NULL, " "); + char * param5 = strtok(NULL, " "); + char * param6 = strtok(NULL, " "); + char * param7 = strtok(NULL, " "); + char * param8 = strtok(NULL, " "); + char * param9 = strtok(NULL, " "); + char * param10 = strtok(NULL, " "); + char * param11 = strtok(NULL, " "); + char * param12 = strtok(NULL, " "); + char * param13 = strtok(NULL, " "); + char * param14 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param14)) + { + PSendSysMessage("Syntax is: ahbotoptions percentages $ahMapID (2, 6 or 7) $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14"); + PSendSysMessage("1 GreyTradeGoods 2 WhiteTradeGoods 3 GreenTradeGoods 4 BlueTradeGoods 5 PurpleTradeGoods"); + PSendSysMessage("6 OrangeTradeGoods 7 YellowTradeGoods 8 GreyItems 9 WhiteItems 10 GreenItems 11 BlueItems"); + PSendSysMessage("12 PurpleItems 13 OrangeItems 14 YellowItems"); + PSendSysMessage("The total must add up to 100%"); + return false; + } + uint32 greytg = (uint32) strtoul(param1, NULL, 0); + uint32 whitetg = (uint32) strtoul(param2, NULL, 0); + uint32 greentg = (uint32) strtoul(param3, NULL, 0); + uint32 bluetg = (uint32) strtoul(param3, NULL, 0); + uint32 purpletg = (uint32) strtoul(param5, NULL, 0); + uint32 orangetg = (uint32) strtoul(param6, NULL, 0); + uint32 yellowtg = (uint32) strtoul(param7, NULL, 0); + uint32 greyi = (uint32) strtoul(param8, NULL, 0); + uint32 whitei = (uint32) strtoul(param9, NULL, 0); + uint32 greeni = (uint32) strtoul(param10, NULL, 0); + uint32 bluei = (uint32) strtoul(param11, NULL, 0); + uint32 purplei = (uint32) strtoul(param12, NULL, 0); + uint32 orangei = (uint32) strtoul(param13, NULL, 0); + uint32 yellowi = (uint32) strtoul(param14, NULL, 0); + uint32 totalPercent = greytg + whitetg + greentg + bluetg + purpletg + orangetg + yellowtg + greyi + whitei + greeni + bluei + purplei + orangei + yellowi; + if ((totalPercent == 0) || (totalPercent != 100)) + { + PSendSysMessage("Syntax is: ahbotoptions percentages $ahMapID (2, 6 or 7) $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14"); + PSendSysMessage("1 GreyTradeGoods 2 WhiteTradeGoods 3 GreenTradeGoods 4 BlueTradeGoods 5 PurpleTradeGoods"); + PSendSysMessage("6 OrangeTradeGoods 7 YellowTradeGoods 8 GreyItems 9 WhiteItems 10 GreenItems 11 BlueItems"); + PSendSysMessage("12 PurpleItems 13 OrangeItems 14 YellowItems"); + PSendSysMessage("The total must add up to 100%"); + return false; + } + char param[100]; + param[0] = '\0'; + strcat(param, param1); + strcat(param, " "); + strcat(param, param2); + strcat(param, " "); + strcat(param, param3); + strcat(param, " "); + strcat(param, param4); + strcat(param, " "); + strcat(param, param5); + strcat(param, " "); + strcat(param, param6); + strcat(param, " "); + strcat(param, param7); + strcat(param, " "); + strcat(param, param8); + strcat(param, " "); + strcat(param, param9); + strcat(param, " "); + strcat(param, param10); + strcat(param, " "); + strcat(param, param11); + strcat(param, " "); + strcat(param, param12); + strcat(param, " "); + strcat(param, param13); + strcat(param, " "); + strcat(param, param14); + auctionbot.Commands(5, ahMapID, NULL, param); + } + else if (strncmp(opt,"minprice",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1) || (!param2)) + { + PSendSysMessage("Syntax is: ahbotoptions minprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + if (strncmp(param1,"grey",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_GREY, param2); + } + else if (strncmp(param1,"white",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_WHITE, param2); + } + else if (strncmp(param1,"green",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_GREEN, param2); + } + else if (strncmp(param1,"blue",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_BLUE, param2); + } + else if (strncmp(param1,"purple",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_PURPLE, param2); + } + else if (strncmp(param1,"orange",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_ORANGE, param2); + } + else if (strncmp(param1,"yellow",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_YELLOW, param2); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions minprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + } + else if (strncmp(opt,"maxprice",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1) || (!param2)) + { + PSendSysMessage("Syntax is: ahbotoptions maxprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + if (strncmp(param1,"grey",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_GREY, param2); + } + else if (strncmp(param1,"white",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_WHITE, param2); + } + else if (strncmp(param1,"green",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_GREEN, param2); + } + else if (strncmp(param1,"blue",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_BLUE, param2); + } + else if (strncmp(param1,"purple",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_PURPLE, param2); + } + else if (strncmp(param1,"orange",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_ORANGE, param2); + } + else if (strncmp(param1,"yellow",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_YELLOW, param2); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions maxprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + } + else if (strncmp(opt,"minbidprice",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1) || (!param2)) + { + PSendSysMessage("Syntax is: ahbotoptions minbidprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + uint32 minBidPrice = (uint32) strtoul(param2, NULL, 0); + if ((minBidPrice < 1) || (minBidPrice > 100)) + { + PSendSysMessage("The min bid price multiplier must be between 1 and 100"); + return false; + } + if (strncmp(param1,"grey",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_GREY, param2); + } + else if (strncmp(param1,"white",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_WHITE, param2); + } + else if (strncmp(param1,"green",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_GREEN, param2); + } + else if (strncmp(param1,"blue",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_BLUE, param2); + } + else if (strncmp(param1,"purple",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_PURPLE, param2); + } + else if (strncmp(param1,"orange",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_ORANGE, param2); + } + else if (strncmp(param1,"yellow",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_YELLOW, param2); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions minbidprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + } + else if (strncmp(opt,"maxbidprice",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1) || (!param2)) + { + PSendSysMessage("Syntax is: ahbotoptions maxbidprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + uint32 maxBidPrice = (uint32) strtoul(param2, NULL, 0); + if ((maxBidPrice < 1) || (maxBidPrice > 100)) + { + PSendSysMessage("The max bid price multiplier must be between 1 and 100"); + return false; + } + if (strncmp(param1,"grey",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_GREY, param2); + } + else if (strncmp(param1,"white",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_WHITE, param2); + } + else if (strncmp(param1,"green",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_GREEN, param2); + } + else if (strncmp(param1,"blue",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_BLUE, param2); + } + else if (strncmp(param1,"purple",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_PURPLE, param2); + } + else if (strncmp(param1,"orange",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_ORANGE, param2); + } + else if (strncmp(param1,"yellow",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_YELLOW, param2); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions max bidprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + } + else if (strncmp(opt,"maxstack",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1) || (!param2)) + { + PSendSysMessage("Syntax is: ahbotoptions maxstack $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $value"); + return false; + } + uint32 maxStack = (uint32) strtoul(param2, NULL, 0); + if (maxStack < 0) + { + PSendSysMessage("maxstack can't be a negative number."); + return false; + } + if (strncmp(param1,"grey",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_GREY, param2); + } + else if (strncmp(param1,"white",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_WHITE, param2); + } + else if (strncmp(param1,"green",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_GREEN, param2); + } + else if (strncmp(param1,"blue",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_BLUE, param2); + } + else if (strncmp(param1,"purple",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_PURPLE, param2); + } + else if (strncmp(param1,"orange",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_ORANGE, param2); + } + else if (strncmp(param1,"yellow",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_YELLOW, param2); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions maxstack $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $value"); + return false; + } + } + else if (strncmp(opt,"buyerprice",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1) || (!param2)) + { + PSendSysMessage("Syntax is: ahbotoptions buyerprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue or purple) $price"); + return false; + } + if (strncmp(param1,"grey",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_GREY, param2); + } + else if (strncmp(param1,"white",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_WHITE, param2); + } + else if (strncmp(param1,"green",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_GREEN, param2); + } + else if (strncmp(param1,"blue",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_BLUE, param2); + } + else if (strncmp(param1,"purple",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_PURPLE, param2); + } + else if (strncmp(param1,"orange",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_ORANGE, param2); + } + else if (strncmp(param1,"yellow",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_YELLOW, param2); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions buyerprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue or purple) $price"); + return false; + } + } + else if (strncmp(opt,"bidinterval",l) == 0) + { + char * param1 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1)) + { + PSendSysMessage("Syntax is: ahbotoptions bidinterval $ahMapID (2, 6 or 7) $interval(in minutes)"); + return false; + } + auctionbot.Commands(12, ahMapID, NULL, param1); + } + else if (strncmp(opt,"bidsperinterval",l) == 0) + { + char * param1 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1)) + { + PSendSysMessage("Syntax is: ahbotoptions bidsperinterval $ahMapID (2, 6 or 7) $bids"); + return false; + } + auctionbot.Commands(13, ahMapID, NULL, param1); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions $option $ahMapID (2, 6 or 7) $parameter"); + PSendSysMessage("Try ahbotoptions help to see a list of options."); + return false; + } + return true; +} + +//reload commands +bool ChatHandler::HandleReloadAllCommand(const char*) +{ + HandleReloadSkillFishingBaseLevelCommand(""); + + HandleReloadAllAchievementCommand(""); + HandleReloadAllAreaCommand(""); + HandleReloadAllEventAICommand(""); + HandleReloadAllLootCommand(""); + HandleReloadAllNpcCommand(""); + HandleReloadAllQuestCommand(""); + HandleReloadAllSpellCommand(""); + HandleReloadAllItemCommand(""); + HandleReloadAllLocalesCommand(""); + + HandleReloadAccessRequirementCommand(""); + HandleReloadMailLevelRewardCommand(""); + HandleReloadCommandCommand(""); + HandleReloadReservedNameCommand(""); + HandleReloadTrinityStringCommand(""); + HandleReloadGameTeleCommand(""); + + HandleReloadAutobroadcastCommand(""); + return true; +} + +bool ChatHandler::HandleReloadAllAchievementCommand(const char*) +{ + HandleReloadAchievementCriteriaDataCommand(""); + HandleReloadAchievementRewardCommand(""); + return true; +} + +bool ChatHandler::HandleReloadAllAreaCommand(const char*) +{ + //HandleReloadQuestAreaTriggersCommand(""); -- reloaded in HandleReloadAllQuestCommand + HandleReloadAreaTriggerTeleportCommand(""); + HandleReloadAreaTriggerTavernCommand(""); + HandleReloadGameGraveyardZoneCommand(""); + return true; +} + +bool ChatHandler::HandleReloadAllLootCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables..."); + LoadLootTables(); + SendGlobalGMSysMessage("DB tables `*_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadAllNpcCommand(const char* /*args*/) +{ + HandleReloadNpcGossipCommand("a"); + HandleReloadNpcTrainerCommand("a"); + HandleReloadNpcVendorCommand("a"); + HandleReloadPointsOfInterestCommand("a"); + HandleReloadSpellClickSpellsCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadAllQuestCommand(const char* /*args*/) +{ + HandleReloadQuestAreaTriggersCommand("a"); + HandleReloadQuestTemplateCommand("a"); + + sLog.outString("Re-Loading Quests Relations..."); + objmgr.LoadQuestRelations(); + SendGlobalGMSysMessage("DB tables `*_questrelation` and `*_involvedrelation` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAllScriptsCommand(const char*) +{ + if (sWorld.IsScriptScheduled()) + { + PSendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + sLog.outString("Re-Loading Scripts..."); + HandleReloadGameObjectScriptsCommand("a"); + HandleReloadEventScriptsCommand("a"); + HandleReloadQuestEndScriptsCommand("a"); + HandleReloadQuestStartScriptsCommand("a"); + HandleReloadSpellScriptsCommand("a"); + SendGlobalGMSysMessage("DB tables `*_scripts` reloaded."); + HandleReloadDbScriptStringCommand("a"); + HandleReloadWpScriptsCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadAllEventAICommand(const char*) +{ + HandleReloadEventAITextsCommand("a"); + HandleReloadEventAISummonsCommand("a"); + HandleReloadEventAIScriptsCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadAllSpellCommand(const char*) +{ + HandleReloadSkillDiscoveryTemplateCommand("a"); + HandleReloadSkillExtraItemTemplateCommand("a"); + HandleReloadSpellRequiredCommand("a"); + HandleReloadSpellAreaCommand("a"); + HandleReloadSpellGroupsCommand("a"); + HandleReloadSpellLearnSpellCommand("a"); + HandleReloadSpellLinkedSpellCommand("a"); + HandleReloadSpellProcEventCommand("a"); + HandleReloadSpellBonusesCommand("a"); + HandleReloadSpellTargetPositionCommand("a"); + HandleReloadSpellThreatsCommand("a"); + HandleReloadSpellGroupStackRulesCommand("a"); + HandleReloadSpellPetAurasCommand("a"); + HandleReloadSpellDisabledCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadAllItemCommand(const char*) +{ + HandleReloadPageTextsCommand("a"); + HandleReloadItemEnchantementsCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadAllLocalesCommand(const char* /*args*/) +{ + HandleReloadLocalesAchievementRewardCommand("a"); + HandleReloadLocalesCreatureCommand("a"); + HandleReloadLocalesGameobjectCommand("a"); + HandleReloadLocalesItemCommand("a"); + HandleReloadLocalesNpcTextCommand("a"); + HandleReloadLocalesPageTextCommand("a"); + HandleReloadLocalesPointsOfInterestCommand("a"); + HandleReloadLocalesQuestCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadConfigCommand(const char* /*args*/) +{ + sLog.outString("Re-Loading config settings..."); + sWorld.LoadConfigSettings(true); + MapManager::Instance().InitializeVisibilityDistanceInfo(); + SendGlobalGMSysMessage("World config settings reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAccessRequirementCommand(const char*) +{ + sLog.outString("Re-Loading Access Requirement definitions..."); + objmgr.LoadAccessRequirements(); + SendGlobalGMSysMessage("DB table `access_requirement` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAchievementCriteriaDataCommand(const char*) +{ + sLog.outString("Re-Loading Additional Achievement Criteria Data..."); + achievementmgr.LoadAchievementCriteriaData(); + SendGlobalGMSysMessage("DB table `achievement_criteria_data` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAchievementRewardCommand(const char*) +{ + sLog.outString("Re-Loading Achievement Reward Data..."); + achievementmgr.LoadRewards(); + SendGlobalGMSysMessage("DB table `achievement_reward` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAreaTriggerTavernCommand(const char*) +{ + sLog.outString("Re-Loading Tavern Area Triggers..."); + objmgr.LoadTavernAreaTriggers(); + SendGlobalGMSysMessage("DB table `areatrigger_tavern` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAreaTriggerTeleportCommand(const char*) +{ + sLog.outString("Re-Loading AreaTrigger teleport definitions..."); + objmgr.LoadAreaTriggerTeleports(); + SendGlobalGMSysMessage("DB table `areatrigger_teleport` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAutobroadcastCommand(const char*) +{ + sLog.outString("Re-Loading Autobroadcast..."); + sWorld.LoadAutobroadcasts(); + SendGlobalGMSysMessage("DB table `autobroadcast` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadCommandCommand(const char*) +{ + load_command_table = true; + SendGlobalGMSysMessage("DB table `command` will be reloaded at next chat command use."); + return true; +} + +bool ChatHandler::HandleReloadCreatureTemplateCommand(const char* args) +{ + if (!*args) + return false; + + uint32 entry = (uint32) atoi((char*)args); + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT difficulty_entry_1,difficulty_entry_2,difficulty_entry_3,KillCredit1,KillCredit2,modelid1,modelid2,modelid3,modelid4,name,subname,IconName,gossip_menu_id,minlevel,maxlevel,exp,faction_A,faction_H,npcflag,speed_walk,speed_run,scale,rank,mindmg,maxdmg,dmgschool,attackpower,dmg_multiplier,baseattacktime,rangeattacktime,unit_class,unit_flags,dynamicflags,family,trainer_type,trainer_spell,trainer_class,trainer_race,minrangedmg,maxrangedmg,rangedattackpower,type,type_flags,lootid,pickpocketloot,skinloot,resistance1,resistance2,resistance3,resistance4,resistance5,resistance6,spell1,spell2,spell3,spell4,spell5,spell6,spell7,spell8,PetSpellDataId,VehicleId,mingold,maxgold,AIName,MovementType,InhabitType,Health_mod,Mana_mod,Armor_mod,RacialLeader,questItem1,questItem2,questItem3,questItem4,questItem5,questItem6,movementId,RegenHealth,equipment_id,mechanic_immune_mask,flags_extra,ScriptName FROM creature_template WHERE entry = %u", entry); + if (!result) + { + PSendSysMessage(LANG_COMMAND_CREATURETEMPLATE_NOTFOUND, entry); + SetSentErrorMessage(true); + return false; + } + + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(entry); + if (!cInfo) + { + PSendSysMessage(LANG_COMMAND_CREATURESTORAGE_NOTFOUND, entry); + SetSentErrorMessage(true); + return false; + } + + sLog.outString("Reloading creature template entry %u", entry); + + Field *fields = result->Fetch(); + + const_cast<CreatureInfo*>(cInfo)->DifficultyEntry[0] = fields[0].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->DifficultyEntry[1] = fields[1].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->DifficultyEntry[2] = fields[2].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->KillCredit[0] = fields[3].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->KillCredit[1] = fields[4].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->Modelid1 = fields[5].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->Modelid2 = fields[6].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->Modelid3 = fields[7].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->Modelid4 = fields[8].GetUInt32(); + size_t len = 0; + if (const char* temp = fields[9].GetString()) + { + if (cInfo->Name) + delete cInfo->Name; + len = strlen(temp)+1; + const_cast<CreatureInfo*>(cInfo)->Name = new char[len]; + strncpy(cInfo->Name, temp, len); + } + if (const char* temp = fields[10].GetString()) + { + if (cInfo->SubName) + delete cInfo->SubName; + len = strlen(temp)+1; + const_cast<CreatureInfo*>(cInfo)->SubName = new char[len]; + strncpy(cInfo->SubName, temp, len); + } + if (const char* temp = fields[11].GetString()) + { + if (cInfo->IconName) + delete cInfo->IconName; + len = strlen(temp)+1; + const_cast<CreatureInfo*>(cInfo)->IconName = new char[len]; + strncpy(cInfo->IconName, temp, len); + } + const_cast<CreatureInfo*>(cInfo)->GossipMenuId = fields[12].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->minlevel = fields[13].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->maxlevel = fields[14].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->expansion = fields[15].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->faction_A = fields[16].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->faction_H = fields[17].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->npcflag = fields[18].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->speed_walk = fields[19].GetFloat(); + const_cast<CreatureInfo*>(cInfo)->speed_run = fields[20].GetFloat(); + const_cast<CreatureInfo*>(cInfo)->scale = fields[21].GetFloat(); + const_cast<CreatureInfo*>(cInfo)->rank = fields[22].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->mindmg = fields[23].GetFloat(); + const_cast<CreatureInfo*>(cInfo)->maxdmg = fields[24].GetFloat(); + const_cast<CreatureInfo*>(cInfo)->dmgschool = fields[25].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->attackpower = fields[26].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->dmg_multiplier = fields[27].GetFloat(); + const_cast<CreatureInfo*>(cInfo)->baseattacktime = fields[28].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->rangeattacktime = fields[29].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->unit_class = fields[30].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->unit_flags = fields[31].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->dynamicflags = fields[32].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->family = fields[33].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->trainer_type = fields[34].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->trainer_spell = fields[35].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->trainer_class = fields[36].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->trainer_race = fields[37].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->minrangedmg = fields[38].GetFloat(); + const_cast<CreatureInfo*>(cInfo)->maxrangedmg = fields[39].GetFloat(); + const_cast<CreatureInfo*>(cInfo)->rangedattackpower = fields[40].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->type = fields[41].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->type_flags = fields[42].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->lootid = fields[43].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->pickpocketLootId = fields[44].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->SkinLootId = fields[45].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->resistance1 = fields[46].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->resistance2 = fields[47].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->resistance3 = fields[48].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->resistance4 = fields[49].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->resistance5 = fields[50].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->resistance6 = fields[51].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->spells[0] = fields[52].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->spells[1] = fields[53].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->spells[2] = fields[54].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->spells[3] = fields[55].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->spells[4] = fields[56].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->spells[5] = fields[57].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->spells[6] = fields[58].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->spells[7] = fields[59].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->PetSpellDataId = fields[60].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->VehicleId = fields[61].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->mingold = fields[62].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->maxgold = fields[63].GetUInt32(); + if (const char* temp = fields[64].GetString()) + { + if (cInfo->AIName) + delete cInfo->AIName; + len = strlen(temp)+1; + const_cast<CreatureInfo*>(cInfo)->AIName = new char[len]; + strncpy(const_cast<char*>(cInfo->AIName), temp, len); + } + const_cast<CreatureInfo*>(cInfo)->MovementType = fields[65].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->InhabitType = fields[66].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->ModHealth = fields[67].GetFloat(); + const_cast<CreatureInfo*>(cInfo)->ModMana = fields[68].GetFloat(); + const_cast<CreatureInfo*>(cInfo)->ModArmor = fields[69].GetFloat(); + const_cast<CreatureInfo*>(cInfo)->RacialLeader = fields[70].GetBool(); + const_cast<CreatureInfo*>(cInfo)->questItems[0] = fields[71].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->questItems[1] = fields[72].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->questItems[2] = fields[73].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->questItems[3] = fields[74].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->questItems[4] = fields[75].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->questItems[5] = fields[76].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->movementId = fields[77].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->RegenHealth = fields[78].GetBool(); + const_cast<CreatureInfo*>(cInfo)->equipmentId = fields[79].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->MechanicImmuneMask = fields[80].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->flags_extra = fields[81].GetUInt32(); + const_cast<CreatureInfo*>(cInfo)->ScriptID = objmgr.GetScriptId(fields[82].GetString()); + + objmgr.CheckCreatureTemplate(cInfo); + + SendGlobalGMSysMessage("Creature template reloaded."); + return true; +} + +bool ChatHandler::HandleReloadCreatureQuestRelationsCommand(const char*) +{ + sLog.outString("Loading Quests Relations... (`creature_questrelation`)"); + objmgr.LoadCreatureQuestRelations(); + SendGlobalGMSysMessage("DB table `creature_questrelation` (creature quest givers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadCreatureLinkedRespawnCommand(const char * /*args*/) +{ + sLog.outString("Loading Linked Respawns... (`creature_linked_respawn`)"); + objmgr.LoadCreatureLinkedRespawn(); + SendGlobalGMSysMessage("DB table `creature_linked_respawn` (creature linked respawns) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadCreatureQuestInvRelationsCommand(const char*) +{ + sLog.outString("Loading Quests Relations... (`creature_involvedrelation`)"); + objmgr.LoadCreatureInvolvedRelations(); + SendGlobalGMSysMessage("DB table `creature_involvedrelation` (creature quest takers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadGossipMenuCommand(const char*) +{ + sLog.outString("Re-Loading `gossip_menu` Table!"); + objmgr.LoadGossipMenu(); + SendGlobalGMSysMessage("DB table `gossip_menu` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadGossipMenuOptionCommand(const char*) +{ + sLog.outString("Re-Loading `gossip_menu_option` Table!"); + objmgr.LoadGossipMenuItems(); + SendGlobalGMSysMessage("DB table `gossip_menu_option` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadGOQuestRelationsCommand(const char*) +{ + sLog.outString("Loading Quests Relations... (`gameobject_questrelation`)"); + objmgr.LoadGameobjectQuestRelations(); + SendGlobalGMSysMessage("DB table `gameobject_questrelation` (gameobject quest givers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadGOQuestInvRelationsCommand(const char*) +{ + sLog.outString("Loading Quests Relations... (`gameobject_involvedrelation`)"); + objmgr.LoadGameobjectInvolvedRelations(); + SendGlobalGMSysMessage("DB table `gameobject_involvedrelation` (gameobject quest takers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadQuestAreaTriggersCommand(const char*) +{ + sLog.outString("Re-Loading Quest Area Triggers..."); + objmgr.LoadQuestAreaTriggers(); + SendGlobalGMSysMessage("DB table `areatrigger_involvedrelation` (quest area triggers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadQuestTemplateCommand(const char*) +{ + sLog.outString("Re-Loading Quest Templates..."); + objmgr.LoadQuests(); + SendGlobalGMSysMessage("DB table `quest_template` (quest definitions) reloaded."); + + /// dependent also from `gameobject` but this table not reloaded anyway + sLog.outString("Re-Loading GameObjects for quests..."); + objmgr.LoadGameObjectForQuests(); + SendGlobalGMSysMessage("Data GameObjects for quests reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesCreatureCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`creature_loot_template`)"); + LoadLootTemplates_Creature(); + LootTemplates_Creature.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `creature_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesDisenchantCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`disenchant_loot_template`)"); + LoadLootTemplates_Disenchant(); + LootTemplates_Disenchant.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `disenchant_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesFishingCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`fishing_loot_template`)"); + LoadLootTemplates_Fishing(); + LootTemplates_Fishing.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `fishing_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesGameobjectCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`gameobject_loot_template`)"); + LoadLootTemplates_Gameobject(); + LootTemplates_Gameobject.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `gameobject_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesItemCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`item_loot_template`)"); + LoadLootTemplates_Item(); + LootTemplates_Item.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `item_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesMillingCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`milling_loot_template`)"); + LoadLootTemplates_Milling(); + LootTemplates_Milling.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `milling_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesPickpocketingCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`pickpocketing_loot_template`)"); + LoadLootTemplates_Pickpocketing(); + LootTemplates_Pickpocketing.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `pickpocketing_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesProspectingCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`prospecting_loot_template`)"); + LoadLootTemplates_Prospecting(); + LootTemplates_Prospecting.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `prospecting_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesMailCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`mail_loot_template`)"); + LoadLootTemplates_Mail(); + LootTemplates_Mail.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `mail_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesReferenceCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`reference_loot_template`)"); + LoadLootTemplates_Reference(); + SendGlobalGMSysMessage("DB table `reference_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesSkinningCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`skinning_loot_template`)"); + LoadLootTemplates_Skinning(); + LootTemplates_Skinning.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `skinning_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesSpellCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`spell_loot_template`)"); + LoadLootTemplates_Spell(); + LootTemplates_Spell.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `spell_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadTrinityStringCommand(const char*) +{ + sLog.outString("Re-Loading trinity_string Table!"); + objmgr.LoadTrinityStrings(); + SendGlobalGMSysMessage("DB table `trinity_string` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadNpcGossipCommand(const char*) +{ + sLog.outString("Re-Loading `npc_gossip` Table!"); + objmgr.LoadNpcTextId(); + SendGlobalGMSysMessage("DB table `npc_gossip` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadNpcTrainerCommand(const char*) +{ + sLog.outString("Re-Loading `npc_trainer` Table!"); + objmgr.LoadTrainerSpell(); + SendGlobalGMSysMessage("DB table `npc_trainer` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadNpcVendorCommand(const char*) +{ + sLog.outString("Re-Loading `npc_vendor` Table!"); + objmgr.LoadVendors(); + SendGlobalGMSysMessage("DB table `npc_vendor` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadPointsOfInterestCommand(const char*) +{ + sLog.outString("Re-Loading `points_of_interest` Table!"); + objmgr.LoadPointsOfInterest(); + SendGlobalGMSysMessage("DB table `points_of_interest` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellClickSpellsCommand(const char*) +{ + sLog.outString("Re-Loading `npc_spellclick_spells` Table!"); + objmgr.LoadNPCSpellClickSpells(); + SendGlobalGMSysMessage("DB table `npc_spellclick_spells` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadReservedNameCommand(const char*) +{ + sLog.outString("Loading ReservedNames... (`reserved_name`)"); + objmgr.LoadReservedPlayersNames(); + SendGlobalGMSysMessage("DB table `reserved_name` (player reserved names) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSkillDiscoveryTemplateCommand(const char* /*args*/) +{ + sLog.outString("Re-Loading Skill Discovery Table..."); + LoadSkillDiscoveryTable(); + SendGlobalGMSysMessage("DB table `skill_discovery_template` (recipes discovered at crafting) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSkillExtraItemTemplateCommand(const char* /*args*/) +{ + sLog.outString("Re-Loading Skill Extra Item Table..."); + LoadSkillExtraItemTable(); + SendGlobalGMSysMessage("DB table `skill_extra_item_template` (extra item creation when crafting) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSkillFishingBaseLevelCommand(const char* /*args*/) +{ + sLog.outString("Re-Loading Skill Fishing base level requirements..."); + objmgr.LoadFishingBaseSkillLevel(); + SendGlobalGMSysMessage("DB table `skill_fishing_base_level` (fishing base level for zone/subzone) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellAreaCommand(const char*) +{ + sLog.outString("Re-Loading SpellArea Data..."); + spellmgr.LoadSpellAreas(); + SendGlobalGMSysMessage("DB table `spell_area` (spell dependences from area/quest/auras state) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellRequiredCommand(const char*) +{ + sLog.outString("Re-Loading Spell Required Data... "); + spellmgr.LoadSpellRequired(); + SendGlobalGMSysMessage("DB table `spell_required` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellGroupsCommand(const char*) +{ + sLog.outString("Re-Loading Spell Groups..."); + spellmgr.LoadSpellGroups(); + SendGlobalGMSysMessage("DB table `spell_group` (spell groups) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellLearnSpellCommand(const char*) +{ + sLog.outString("Re-Loading Spell Learn Spells..."); + spellmgr.LoadSpellLearnSpells(); + SendGlobalGMSysMessage("DB table `spell_learn_spell` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellLinkedSpellCommand(const char*) +{ + sLog.outString("Re-Loading Spell Linked Spells..."); + spellmgr.LoadSpellLinked(); + SendGlobalGMSysMessage("DB table `spell_linked_spell` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellProcEventCommand(const char*) +{ + sLog.outString("Re-Loading Spell Proc Event conditions..."); + spellmgr.LoadSpellProcEvents(); + SendGlobalGMSysMessage("DB table `spell_proc_event` (spell proc trigger requirements) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellBonusesCommand(const char*) +{ + sLog.outString("Re-Loading Spell Bonus Data..."); + spellmgr.LoadSpellBonusess(); + SendGlobalGMSysMessage("DB table `spell_bonus_data` (spell damage/healing coefficients) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellTargetPositionCommand(const char*) +{ + sLog.outString("Re-Loading Spell target coordinates..."); + spellmgr.LoadSpellTargetPositions(); + SendGlobalGMSysMessage("DB table `spell_target_position` (destination coordinates for spell targets) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellThreatsCommand(const char*) +{ + sLog.outString("Re-Loading Aggro Spells Definitions..."); + spellmgr.LoadSpellThreats(); + SendGlobalGMSysMessage("DB table `spell_threat` (spell aggro definitions) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellGroupStackRulesCommand(const char*) +{ + sLog.outString("Re-Loading Spell Group Stack Rules..."); + spellmgr.LoadSpellGroupStackRules(); + SendGlobalGMSysMessage("DB table `spell_group_stack_rules` (spell stacking definitions) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellPetAurasCommand(const char*) +{ + sLog.outString("Re-Loading Spell pet auras..."); + spellmgr.LoadSpellPetAuras(); + SendGlobalGMSysMessage("DB table `spell_pet_auras` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadPageTextsCommand(const char*) +{ + sLog.outString("Re-Loading Page Texts..."); + objmgr.LoadPageTexts(); + SendGlobalGMSysMessage("DB table `page_texts` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadItemEnchantementsCommand(const char*) +{ + sLog.outString("Re-Loading Item Random Enchantments Table..."); + LoadRandomEnchantmentsTable(); + SendGlobalGMSysMessage("DB table `item_enchantment_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadGameObjectScriptsCommand(const char* arg) +{ + if (sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*arg != 'a') + sLog.outString("Re-Loading Scripts from `gameobject_scripts`..."); + + objmgr.LoadGameObjectScripts(); + + if (*arg != 'a') + SendGlobalGMSysMessage("DB table `gameobject_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadEventScriptsCommand(const char* arg) +{ + if (sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*arg != 'a') + sLog.outString("Re-Loading Scripts from `event_scripts`..."); + + objmgr.LoadEventScripts(); + + if (*arg != 'a') + SendGlobalGMSysMessage("DB table `event_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadWpScriptsCommand(const char* arg) +{ + if (sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*arg != 'a') + sLog.outString("Re-Loading Scripts from `waypoint_scripts`..."); + + objmgr.LoadWaypointScripts(); + + if (*arg != 'a') + SendGlobalGMSysMessage("DB table `waypoint_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadEventAITextsCommand(const char* /*args*/) +{ + + sLog.outString("Re-Loading Texts from `creature_ai_texts`..."); + CreatureEAI_Mgr.LoadCreatureEventAI_Texts(); + SendGlobalGMSysMessage("DB table `creature_ai_texts` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadEventAISummonsCommand(const char* /*args*/) +{ + sLog.outString("Re-Loading Summons from `creature_ai_summons`..."); + CreatureEAI_Mgr.LoadCreatureEventAI_Summons(); + SendGlobalGMSysMessage("DB table `creature_ai_summons` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadEventAIScriptsCommand(const char* /*args*/) +{ + sLog.outString("Re-Loading Scripts from `creature_ai_scripts`..."); + CreatureEAI_Mgr.LoadCreatureEventAI_Scripts(); + SendGlobalGMSysMessage("DB table `creature_ai_scripts` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadQuestEndScriptsCommand(const char* arg) +{ + if (sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*arg != 'a') + sLog.outString("Re-Loading Scripts from `quest_end_scripts`..."); + + objmgr.LoadQuestEndScripts(); + + if (*arg != 'a') + SendGlobalGMSysMessage("DB table `quest_end_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadQuestStartScriptsCommand(const char* arg) +{ + if (sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*arg != 'a') + sLog.outString("Re-Loading Scripts from `quest_start_scripts`..."); + + objmgr.LoadQuestStartScripts(); + + if (*arg != 'a') + SendGlobalGMSysMessage("DB table `quest_start_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadSpellScriptsCommand(const char* arg) +{ + if (sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*arg != 'a') + sLog.outString("Re-Loading Scripts from `spell_scripts`..."); + + objmgr.LoadSpellScripts(); + + if (*arg != 'a') + SendGlobalGMSysMessage("DB table `spell_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadDbScriptStringCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Script strings from `db_script_string`..."); + objmgr.LoadDbScriptStrings(); + SendGlobalGMSysMessage("DB table `db_script_string` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadGameGraveyardZoneCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Graveyard-zone links..."); + + objmgr.LoadGraveyardZones(); + + SendGlobalGMSysMessage("DB table `game_graveyard_zone` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadGameTeleCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Game Tele coordinates..."); + + objmgr.LoadGameTele(); + + SendGlobalGMSysMessage("DB table `game_tele` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadSpellDisabledCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading spell disabled table..."); + + objmgr.LoadSpellDisabledEntrys(); + + SendGlobalGMSysMessage("DB table `spell_disabled` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadLocalesAchievementRewardCommand(const char*) +{ + sLog.outString("Re-Loading Locales Achievement Reward Data..."); + achievementmgr.LoadRewardLocales(); + SendGlobalGMSysMessage("DB table `locales_achievement_reward` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesCreatureCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales Creature ..."); + objmgr.LoadCreatureLocales(); + SendGlobalGMSysMessage("DB table `locales_creature` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesGameobjectCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales Gameobject ... "); + objmgr.LoadGameObjectLocales(); + SendGlobalGMSysMessage("DB table `locales_gameobject` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesItemCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales Item ... "); + objmgr.LoadItemLocales(); + SendGlobalGMSysMessage("DB table `locales_item` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesNpcTextCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales NPC Text ... "); + objmgr.LoadNpcTextLocales(); + SendGlobalGMSysMessage("DB table `locales_npc_text` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesPageTextCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales Page Text ... "); + objmgr.LoadPageTextLocales(); + SendGlobalGMSysMessage("DB table `locales_page_text` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesPointsOfInterestCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales Points Of Interest ... "); + objmgr.LoadPointOfInterestLocales(); + SendGlobalGMSysMessage("DB table `locales_points_of_interest` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesQuestCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales Quest ... "); + objmgr.LoadQuestLocales(); + SendGlobalGMSysMessage("DB table `locales_quest` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadMailLevelRewardCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Player level dependent mail rewards..."); + objmgr.LoadMailLevelRewards(); + SendGlobalGMSysMessage("DB table `mail_level_reward` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAuctionsCommand(const char * /*args*/) +{ + ///- Reload dynamic data tables from the database + sLog.outString("Re-Loading Auctions..."); + auctionmgr.LoadAuctionItems(); + auctionmgr.LoadAuctions(); + SendGlobalGMSysMessage("Auctions reloaded."); + return true; +} + +bool ChatHandler::HandleReloadConditions(const char* args) +{ + sLog.outString("Re-Loading Conditions..."); + sConditionMgr.LoadConditions(true); + SendGlobalGMSysMessage("Conditions reloaded."); + return true; +} + +bool ChatHandler::HandleAccountSetGmLevelCommand(const char *args) +{ + if (!*args) + return false; + + std::string targetAccountName; + uint32 targetAccountId = 0; + uint32 targetSecurity = 0; + uint32 gm = 0; + char* arg1 = strtok((char*)args, " "); + char* arg2 = strtok(NULL, " "); + char* arg3 = strtok(NULL, " "); + bool isAccountNameGiven = true; + + if (arg1 && !arg3) + { + if (!getSelectedPlayer()) + return false; + isAccountNameGiven = false; + } + + // Check for second parameter + if (!isAccountNameGiven && !arg2) + return false; + + // Check for account + if (isAccountNameGiven) + { + targetAccountName = arg1; + if (!AccountMgr::normalizeString(targetAccountName)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,targetAccountName.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + // Check for invalid specified GM level. + gm = (isAccountNameGiven) ? atoi(arg2) : atoi(arg1); + if (gm < SEC_PLAYER) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + // m_session == NULL only for console + targetAccountId = (isAccountNameGiven) ? accmgr.GetId(targetAccountName) : getSelectedPlayer()->GetSession()->GetAccountId(); + int32 gmRealmID = (isAccountNameGiven) ? atoi(arg3) : atoi(arg2); + uint32 plSecurity = m_session ? accmgr.GetSecurity(m_session->GetAccountId(), gmRealmID) : SEC_CONSOLE; + + // can set security level only for target with less security and to less security that we have + // This is also reject self apply in fact + targetSecurity = accmgr.GetSecurity(targetAccountId, gmRealmID); + if (targetSecurity >= plSecurity || gm >= plSecurity) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + SetSentErrorMessage(true); + return false; + } + + // Check and abort if the target gm has a higher rank on one of the realms and the new realm is -1 + if (gmRealmID == -1) + { + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT * FROM account_access WHERE id = '%u' AND gmlevel > '%d'", targetAccountId, gm); + if (result) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + SetSentErrorMessage(true); + return false; + } + } + + // Check if provided realmID has a negative value other than -1 + if (gmRealmID < -1) + { + SendSysMessage(LANG_INVALID_REALMID); + SetSentErrorMessage(true); + return false; + } + + // If gmRealmID is -1, delete all values for the account id, else, insert values for the specific realmID + if (gmRealmID == -1) + LoginDatabase.PExecute("DELETE FROM account_access WHERE id = '%u'", targetAccountId); + else + LoginDatabase.PExecute("DELETE FROM account_access WHERE id = '%u' AND (RealmID = '%d' OR RealmID = '-1')", targetAccountId, realmID); + + if (gm != 0) + LoginDatabase.PExecute("INSERT INTO account_access VALUES ('%u','%d','%d')", targetAccountId, gm, realmID); + PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm); + return true; +} + +/// Set password for account +bool ChatHandler::HandleAccountSetPasswordCommand(const char *args) +{ + if (!*args) + return false; + + ///- Get the command line arguments + char *szAccount = strtok ((char*)args," "); + char *szPassword1 = strtok (NULL," "); + char *szPassword2 = strtok (NULL," "); + + if (!szAccount||!szPassword1 || !szPassword2) + return false; + + std::string account_name = szAccount; + if (!AccountMgr::normalizeString(account_name)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + uint32 targetAccountId = accmgr.GetId(account_name); + if (!targetAccountId) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + /// can set password only for target with less security + /// This is also reject self apply in fact + if (HasLowerSecurityAccount (NULL,targetAccountId,true)) + return false; + + if (strcmp(szPassword1,szPassword2)) + { + SendSysMessage (LANG_NEW_PASSWORDS_NOT_MATCH); + SetSentErrorMessage (true); + return false; + } + + AccountOpResult result = accmgr.ChangePassword(targetAccountId, szPassword1); + + switch (result) + { + case AOR_OK: + SendSysMessage(LANG_COMMAND_PASSWORD); + break; + case AOR_NAME_NOT_EXIST: + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + case AOR_PASS_TOO_LONG: + SendSysMessage(LANG_PASSWORD_TOO_LONG); + SetSentErrorMessage(true); + return false; + default: + SendSysMessage(LANG_COMMAND_NOTCHANGEPASSWORD); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleMaxSkillCommand(const char* /*args*/) +{ + Player* SelectedPlayer = getSelectedPlayer(); + if (!SelectedPlayer) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // each skills that have max skill value dependent from level seted to current level max skill value + SelectedPlayer->UpdateSkillsToMaxSkillsForLevel(); + return true; +} + +bool ChatHandler::HandleSetSkillCommand(const char *args) +{ + // number or [name] Shift-click form |color|Hskill:skill_id|h[name]|h|r + char* skill_p = extractKeyFromLink((char*)args,"Hskill"); + if (!skill_p) + return false; + + char *level_p = strtok (NULL, " "); + + if (!level_p) + return false; + + char *max_p = strtok (NULL, " "); + + int32 skill = atoi(skill_p); + if (skill <= 0) + { + PSendSysMessage(LANG_INVALID_SKILL_ID, skill); + SetSentErrorMessage(true); + return false; + } + + int32 level = atol (level_p); + + Player * target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + SkillLineEntry const* sl = sSkillLineStore.LookupEntry(skill); + if (!sl) + { + PSendSysMessage(LANG_INVALID_SKILL_ID, skill); + SetSentErrorMessage(true); + return false; + } + + std::string tNameLink = GetNameLink(target); + + if (!target->GetSkillValue(skill)) + { + PSendSysMessage(LANG_SET_SKILL_ERROR, tNameLink.c_str(), skill, sl->name[GetSessionDbcLocale()]); + SetSentErrorMessage(true); + return false; + } + + int32 max = max_p ? atol (max_p) : target->GetPureMaxSkillValue(skill); + + if (level <= 0 || level > max || max <= 0) + return false; + + target->SetSkill(skill, target->GetSkillStep(skill), level, max); + PSendSysMessage(LANG_SET_SKILL, skill, sl->name[GetSessionDbcLocale()], tNameLink.c_str(), level, max); + + return true; +} + +bool ChatHandler::HandleUnLearnCommand(const char *args) +{ + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r + uint32 spell_id = extractSpellIdFromLink((char*)args); + if (!spell_id) + return false; + + char const* allStr = strtok(NULL," "); + bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false; + + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (allRanks) + spell_id = spellmgr.GetFirstSpellInChain (spell_id); + + if (target->HasSpell(spell_id)) + target->removeSpell(spell_id,false,!allRanks); + else + SendSysMessage(LANG_FORGET_SPELL); + + if (GetTalentSpellCost(spell_id)) + target->SendTalentsInfoData(false); + + return true; +} + +bool ChatHandler::HandleCooldownCommand(const char *args) +{ + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + std::string tNameLink = GetNameLink(target); + + if (!*args) + { + target->RemoveAllSpellCooldown(); + PSendSysMessage(LANG_REMOVEALL_COOLDOWN, tNameLink.c_str()); + } + else + { + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell_id = extractSpellIdFromLink((char*)args); + if (!spell_id) + return false; + + if (!sSpellStore.LookupEntry(spell_id)) + { + PSendSysMessage(LANG_UNKNOWN_SPELL, target == m_session->GetPlayer() ? GetTrinityString(LANG_YOU) : tNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + target->RemoveSpellCooldown(spell_id,true); + PSendSysMessage(LANG_REMOVE_COOLDOWN, spell_id, target == m_session->GetPlayer() ? GetTrinityString(LANG_YOU) : tNameLink.c_str()); + } + return true; +} + +bool ChatHandler::HandleLearnAllCommand(const char* /*args*/) +{ + static const char *allSpellList[] = + { + "3365", + "6233", + "6247", + "6246", + "6477", + "6478", + "22810", + "8386", + "21651", + "21652", + "522", + "7266", + "8597", + "2479", + "22027", + "6603", + "5019", + "133", + "168", + "227", + "5009", + "9078", + "668", + "203", + "20599", + "20600", + "81", + "20597", + "20598", + "20864", + "1459", + "5504", + "587", + "5143", + "118", + "5505", + "597", + "604", + "1449", + "1460", + "2855", + "1008", + "475", + "5506", + "1463", + "12824", + "8437", + "990", + "5145", + "8450", + "1461", + "759", + "8494", + "8455", + "8438", + "6127", + "8416", + "6129", + "8451", + "8495", + "8439", + "3552", + "8417", + "10138", + "12825", + "10169", + "10156", + "10144", + "10191", + "10201", + "10211", + "10053", + "10173", + "10139", + "10145", + "10192", + "10170", + "10202", + "10054", + "10174", + "10193", + "12826", + "2136", + "143", + "145", + "2137", + "2120", + "3140", + "543", + "2138", + "2948", + "8400", + "2121", + "8444", + "8412", + "8457", + "8401", + "8422", + "8445", + "8402", + "8413", + "8458", + "8423", + "8446", + "10148", + "10197", + "10205", + "10149", + "10215", + "10223", + "10206", + "10199", + "10150", + "10216", + "10207", + "10225", + "10151", + "116", + "205", + "7300", + "122", + "837", + "10", + "7301", + "7322", + "6143", + "120", + "865", + "8406", + "6141", + "7302", + "8461", + "8407", + "8492", + "8427", + "8408", + "6131", + "7320", + "10159", + "8462", + "10185", + "10179", + "10160", + "10180", + "10219", + "10186", + "10177", + "10230", + "10181", + "10161", + "10187", + "10220", + "2018", + "2663", + "12260", + "2660", + "3115", + "3326", + "2665", + "3116", + "2738", + "3293", + "2661", + "3319", + "2662", + "9983", + "8880", + "2737", + "2739", + "7408", + "3320", + "2666", + "3323", + "3324", + "3294", + "22723", + "23219", + "23220", + "23221", + "23228", + "23338", + "10788", + "10790", + "5611", + "5016", + "5609", + "2060", + "10963", + "10964", + "10965", + "22593", + "22594", + "596", + "996", + "499", + "768", + "17002", + "1448", + "1082", + "16979", + "1079", + "5215", + "20484", + "5221", + "15590", + "17007", + "6795", + "6807", + "5487", + "1446", + "1066", + "5421", + "3139", + "779", + "6811", + "6808", + "1445", + "5216", + "1737", + "5222", + "5217", + "1432", + "6812", + "9492", + "5210", + "3030", + "1441", + "783", + "6801", + "20739", + "8944", + "9491", + "22569", + "5226", + "6786", + "1433", + "8973", + "1828", + "9495", + "9006", + "6794", + "8993", + "5203", + "16914", + "6784", + "9635", + "22830", + "20722", + "9748", + "6790", + "9753", + "9493", + "9752", + "9831", + "9825", + "9822", + "5204", + "5401", + "22831", + "6793", + "9845", + "17401", + "9882", + "9868", + "20749", + "9893", + "9899", + "9895", + "9832", + "9902", + "9909", + "22832", + "9828", + "9851", + "9883", + "9869", + "17406", + "17402", + "9914", + "20750", + "9897", + "9848", + "3127", + "107", + "204", + "9116", + "2457", + "78", + "18848", + "331", + "403", + "2098", + "1752", + "11278", + "11288", + "11284", + "6461", + "2344", + "2345", + "6463", + "2346", + "2352", + "775", + "1434", + "1612", + "71", + "2468", + "2458", + "2467", + "7164", + "7178", + "7367", + "7376", + "7381", + "21156", + "5209", + "3029", + "5201", + "9849", + "9850", + "20719", + "22568", + "22827", + "22828", + "22829", + "6809", + "8972", + "9005", + "9823", + "9827", + "6783", + "9913", + "6785", + "6787", + "9866", + "9867", + "9894", + "9896", + "6800", + "8992", + "9829", + "9830", + "780", + "769", + "6749", + "6750", + "9755", + "9754", + "9908", + "20745", + "20742", + "20747", + "20748", + "9746", + "9745", + "9880", + "9881", + "5391", + "842", + "3025", + "3031", + "3287", + "3329", + "1945", + "3559", + "4933", + "4934", + "4935", + "4936", + "5142", + "5390", + "5392", + "5404", + "5420", + "6405", + "7293", + "7965", + "8041", + "8153", + "9033", + "9034", + //"9036", problems with ghost state + "16421", + "21653", + "22660", + "5225", + "9846", + "2426", + "5916", + "6634", + //"6718", phasing stealth, annoying for learn all case. + "6719", + "8822", + "9591", + "9590", + "10032", + "17746", + "17747", + "8203", + "11392", + "12495", + "16380", + "23452", + "4079", + "4996", + "4997", + "4998", + "4999", + "5000", + "6348", + "6349", + "6481", + "6482", + "6483", + "6484", + "11362", + "11410", + "11409", + "12510", + "12509", + "12885", + "13142", + "21463", + "23460", + "11421", + "11416", + "11418", + "1851", + "10059", + "11423", + "11417", + "11422", + "11419", + "11424", + "11420", + "27", + "31", + "33", + "34", + "35", + "15125", + "21127", + "22950", + "1180", + "201", + "12593", + "16770", + "6057", + "12051", + "18468", + "12606", + "12605", + "18466", + "12502", + "12043", + "15060", + "12042", + "12341", + "12848", + "12344", + "12353", + "18460", + "11366", + "12350", + "12352", + "13043", + "11368", + "11113", + "12400", + "11129", + "16766", + "12573", + "12580", + "12472", + "12953", + "12488", + "11189", + "12985", + "12519", + "16758", + "11958", + "12490", + "11426", + "3565", + "3562", + "18960", + "3567", + "3561", + "3566", + "3563", + "1953", + "2139", + "12505", + "13018", + "12522", + "12523", + "5146", + "5144", + "5148", + "8419", + "8418", + "10213", + "10212", + "10157", + "12524", + "13019", + "12525", + "13020", + "12526", + "13021", + "18809", + "13031", + "13032", + "13033", + "4036", + "3920", + "3919", + "3918", + "7430", + "3922", + "3923", + "7411", + "7418", + "7421", + "13262", + "7412", + "7415", + "7413", + "7416", + "13920", + "13921", + "7745", + "7779", + "7428", + "7457", + "7857", + "7748", + "7426", + "13421", + "7454", + "13378", + "7788", + "14807", + "14293", + "7795", + "6296", + "20608", + "755", + "444", + "427", + "428", + "442", + "447", + "3578", + "3581", + "19027", + "3580", + "665", + "3579", + "3577", + "6755", + "3576", + "2575", + "2577", + "2578", + "2579", + "2580", + "2656", + "2657", + "2576", + "3564", + "10248", + "8388", + "2659", + "14891", + "3308", + "3307", + "10097", + "2658", + "3569", + "16153", + "3304", + "10098", + "4037", + "3929", + "3931", + "3926", + "3924", + "3930", + "3977", + "3925", + "136", + "228", + "5487", + "43", + "202", + "0" + }; + + int loop = 0; + while (strcmp(allSpellList[loop], "0")) + { + uint32 spell = atol((char*)allSpellList[loop++]); + + if (m_session->GetPlayer()->HasSpell(spell)) + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + continue; + } + + m_session->GetPlayer()->learnSpell(spell, false); + } + + SendSysMessage(LANG_COMMAND_LEARN_MANY_SPELLS); + + return true; +} + +bool ChatHandler::HandleLearnAllGMCommand(const char* /*args*/) +{ + static const char *gmSpellList[] = + { + "24347", // Become A Fish, No Breath Bar + "35132", // Visual Boom + "38488", // Attack 4000-8000 AOE + "38795", // Attack 2000 AOE + Slow Down 90% + "15712", // Attack 200 + "1852", // GM Spell Silence + "31899", // Kill + "31924", // Kill + "29878", // Kill My Self + "26644", // More Kill + + "28550", //Invisible 24 + "23452", //Invisible + Target + "0" + }; + + uint16 gmSpellIter = 0; + while (strcmp(gmSpellList[gmSpellIter], "0")) + { + uint32 spell = atol((char*)gmSpellList[gmSpellIter++]); + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + continue; + } + + m_session->GetPlayer()->learnSpell(spell, false); + } + + SendSysMessage(LANG_LEARNING_GM_SKILLS); + return true; +} + +bool ChatHandler::HandleLearnAllMyClassCommand(const char* /*args*/) +{ + HandleLearnAllMySpellsCommand(""); + HandleLearnAllMyTalentsCommand(""); + return true; +} + +bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/) +{ + ChrClassesEntry const* clsEntry = sChrClassesStore.LookupEntry(m_session->GetPlayer()->getClass()); + if (!clsEntry) + return true; + uint32 family = clsEntry->spellfamily; + + for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(i); + if (!spellInfo) + continue; + + // skip server-side/triggered spells + if (spellInfo->spellLevel == 0) + continue; + + // skip wrong class/race skills + if (!m_session->GetPlayer()->IsSpellFitByClassAndRace(spellInfo->Id)) + continue; + + // skip other spell families + if (spellInfo->SpellFamilyName != family) + continue; + + // skip spells with first rank learned as talent (and all talents then also) + uint32 first_rank = spellmgr.GetFirstSpellInChain(spellInfo->Id); + if (GetTalentSpellCost(first_rank) > 0) + continue; + + // skip broken spells + if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) + continue; + + m_session->GetPlayer()->learnSpell(i, false); + } + + SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS); + return true; +} + +bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + uint32 classMask = player->getClassMask(); + + for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) + { + TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); + if (!talentInfo) + continue; + + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); + if (!talentTabInfo) + continue; + + if ((classMask & talentTabInfo->ClassMask) == 0) + continue; + + // search highest talent rank + uint32 spellId = 0; + for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) + { + if (talentInfo->RankID[rank] != 0) + { + spellId = talentInfo->RankID[rank]; + break; + } + } + + if (!spellId) // ??? none spells in talent + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) + continue; + + // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) + player->learnSpellHighRank(spellId); + player->AddTalent(spellId, player->GetActiveSpec(), true); + } + + player->SetFreeTalentPoints(0); + + SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); + return true; +} + +bool ChatHandler::HandleLearnAllMyPetTalentsCommand(const char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + + Pet* pet = player->GetPet(); + if (!pet) + { + SendSysMessage(LANG_NO_PET_FOUND); + SetSentErrorMessage(true); + return false; + } + + CreatureInfo const *ci = pet->GetCreatureInfo(); + if (!ci) + { + SendSysMessage(LANG_WRONG_PET_TYPE); + SetSentErrorMessage(true); + return false; + } + + CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family); + if (!pet_family) + { + SendSysMessage(LANG_WRONG_PET_TYPE); + SetSentErrorMessage(true); + return false; + } + + if (pet_family->petTalentType < 0) // not hunter pet + { + SendSysMessage(LANG_WRONG_PET_TYPE); + SetSentErrorMessage(true); + return false; + } + + for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) + { + TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); + if (!talentInfo) + continue; + + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); + if (!talentTabInfo) + continue; + + // prevent learn talent for different family (cheating) + if (((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask) == 0) + continue; + + // search highest talent rank + uint32 spellid = 0; + + for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) + { + if (talentInfo->RankID[rank] != 0) + { + spellid = talentInfo->RankID[rank]; + break; + } + } + + if (!spellid) // ??? none spells in talent + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) + continue; + + // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) + pet->learnSpellHighRank(spellid); + } + + pet->SetFreeTalentPoints(0); + + SendSysMessage(LANG_COMMAND_LEARN_PET_TALENTS); + return true; +} + +bool ChatHandler::HandleLearnAllLangCommand(const char* /*args*/) +{ + // skipping UNIVERSAL language (0) + for (uint8 i = 1; i < LANGUAGES_COUNT; ++i) + m_session->GetPlayer()->learnSpell(lang_description[i].spell_id, false); + + SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG); + return true; +} + +bool ChatHandler::HandleLearnAllDefaultCommand(const char *args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + target->learnDefaultSpells(); + target->learnQuestRewardedSpells(); + + PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST,GetNameLink(target).c_str()); + return true; +} + +bool ChatHandler::HandleLearnCommand(const char *args) +{ + Player* targetPlayer = getSelectedPlayer(); + + if (!targetPlayer) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if (!spell || !sSpellStore.LookupEntry(spell)) + return false; + + char const* allStr = strtok(NULL," "); + bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + SetSentErrorMessage(true); + return false; + } + + if (!allRanks && targetPlayer->HasSpell(spell)) + { + if (targetPlayer == m_session->GetPlayer()) + SendSysMessage(LANG_YOU_KNOWN_SPELL); + else + PSendSysMessage(LANG_TARGET_KNOWN_SPELL,GetNameLink(targetPlayer).c_str()); + SetSentErrorMessage(true); + return false; + } + + if (allRanks) + targetPlayer->learnSpellHighRank(spell); + else + targetPlayer->learnSpell(spell, false); + + uint32 first_spell = spellmgr.GetFirstSpellInChain(spell); + if (GetTalentSpellCost(first_spell)) + targetPlayer->SendTalentsInfoData(false); + + return true; +} + +bool ChatHandler::HandleAddItemCommand(const char *args) +{ + if (!*args) + return false; + + uint32 itemId = 0; + + if (args[0] == '[') // [name] manual form + { + char* citemName = strtok((char*)args, "]"); + + if (citemName && citemName[0]) + { + std::string itemName = citemName+1; + WorldDatabase.escape_string(itemName); + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE name = '%s'", itemName.c_str()); + if (!result) + { + PSendSysMessage(LANG_COMMAND_COULDNOTFIND, citemName+1); + SetSentErrorMessage(true); + return false; + } + itemId = result->Fetch()->GetUInt16(); + } + else + return false; + } + else // item_id or [name] Shift-click form |color|Hitem:item_id:0:0:0|h[name]|h|r + { + char* cId = extractKeyFromLink((char*)args,"Hitem"); + if (!cId) + return false; + itemId = atol(cId); + } + + char* ccount = strtok(NULL, " "); + + int32 count = 1; + + if (ccount) + count = strtol(ccount, NULL, 10); + + if (count == 0) + count = 1; + + Player* pl = m_session->GetPlayer(); + Player* plTarget = getSelectedPlayer(); + if (!plTarget) + plTarget = pl; + + sLog.outDetail(GetTrinityString(LANG_ADDITEM), itemId, count); + + ItemPrototype const *pProto = objmgr.GetItemPrototype(itemId); + if (!pProto) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId); + SetSentErrorMessage(true); + return false; + } + + //Subtract + if (count < 0) + { + plTarget->DestroyItemCount(itemId, -count, true, false); + PSendSysMessage(LANG_REMOVEITEM, itemId, -count, GetNameLink(plTarget).c_str()); + return true; + } + + //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_OK) // convert to possible store amount + count -= noSpaceForCount; + + if (count == 0 || dest.empty()) // can't add any + { + PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, noSpaceForCount); + SetSentErrorMessage(true); + return false; + } + + Item* item = plTarget->StoreNewItem(dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId)); + + // remove binding (let GM give it to another player later) + if (pl == plTarget) + for (ItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end(); ++itr) + if (Item* item1 = pl->GetItemByPos(itr->pos)) + item1->SetBinding(false); + + if (count > 0 && item) + { + pl->SendNewItem(item,count,false,true); + if (pl != plTarget) + plTarget->SendNewItem(item,count,true,false); + } + + if (noSpaceForCount > 0) + PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, noSpaceForCount); + + return true; +} + +bool ChatHandler::HandleAddItemSetCommand(const char *args) +{ + if (!*args) + return false; + + char* cId = extractKeyFromLink((char*)args,"Hitemset"); // number or [name] Shift-click form |color|Hitemset:itemset_id|h[name]|h|r + if (!cId) + return false; + + uint32 itemsetId = atol(cId); + + // prevent generation all items with itemset field value '0' + if (itemsetId == 0) + { + PSendSysMessage(LANG_NO_ITEMS_FROM_ITEMSET_FOUND,itemsetId); + SetSentErrorMessage(true); + return false; + } + + Player* pl = m_session->GetPlayer(); + Player* plTarget = getSelectedPlayer(); + if (!plTarget) + plTarget = pl; + + sLog.outDetail(GetTrinityString(LANG_ADDITEMSET), itemsetId); + + bool found = false; + for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) + { + ItemPrototype const *pProto = sItemStorage.LookupEntry<ItemPrototype>(id); + if (!pProto) + continue; + + if (pProto->ItemSet == itemsetId) + { + found = true; + ItemPosCountVec dest; + uint8 msg = plTarget->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, pProto->ItemId, 1); + if (msg == EQUIP_ERR_OK) + { + Item* item = plTarget->StoreNewItem(dest, pProto->ItemId, true); + + // remove binding (let GM give it to another player later) + if (pl == plTarget) + item->SetBinding(false); + + pl->SendNewItem(item,1,false,true); + if (pl != plTarget) + plTarget->SendNewItem(item,1,true,false); + } + else + { + pl->SendEquipError(msg, NULL, NULL); + PSendSysMessage(LANG_ITEM_CANNOT_CREATE, pProto->ItemId, 1); + } + } + } + + if (!found) + { + PSendSysMessage(LANG_NO_ITEMS_FROM_ITEMSET_FOUND,itemsetId); + + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleListItemCommand(const char *args) +{ + if (!*args) + return false; + + char* cId = extractKeyFromLink((char*)args,"Hitem"); + if (!cId) + return false; + + uint32 item_id = atol(cId); + if (!item_id) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + ItemPrototype const* itemProto = objmgr.GetItemPrototype(item_id); + if (!itemProto) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + char* c_count = strtok(NULL, " "); + int count = c_count ? atol(c_count) : 10; + + if (count < 0) + return false; + + QueryResult_AutoPtr result; + + // inventory case + uint32 inv_count = 0; + result=CharacterDatabase.PQuery("SELECT COUNT(item_template) FROM character_inventory WHERE item_template='%u'",item_id); + if (result) + inv_count = (*result)[0].GetUInt32(); + + result=CharacterDatabase.PQuery( + // 0 1 2 3 4 5 + "SELECT ci.item, cibag.slot AS bag, ci.slot, ci.guid, characters.account,characters.name " + "FROM character_inventory AS ci LEFT JOIN character_inventory AS cibag ON (cibag.item=ci.bag),characters " + "WHERE ci.item_template='%u' AND ci.guid = characters.guid LIMIT %u ", + item_id,uint32(count)); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 item_guid = fields[0].GetUInt32(); + uint32 item_bag = fields[1].GetUInt32(); + uint32 item_slot = fields[2].GetUInt32(); + uint32 owner_guid = fields[3].GetUInt32(); + uint32 owner_acc = fields[4].GetUInt32(); + std::string owner_name = fields[5].GetCppString(); + + char const* item_pos = 0; + if (Player::IsEquipmentPos(item_bag,item_slot)) + item_pos = "[equipped]"; + else if (Player::IsInventoryPos(item_bag,item_slot)) + item_pos = "[in inventory]"; + else if (Player::IsBankPos(item_bag,item_slot)) + item_pos = "[in bank]"; + else + item_pos = ""; + + PSendSysMessage(LANG_ITEMLIST_SLOT, + item_guid,owner_name.c_str(),owner_guid,owner_acc,item_pos); + } while (result->NextRow()); + + int64 res_count = result->GetRowCount(); + + if (count > res_count) + count-=res_count; + else if (count) + count = 0; + } + + // mail case + uint32 mail_count = 0; + result=CharacterDatabase.PQuery("SELECT COUNT(item_template) FROM mail_items WHERE item_template='%u'", item_id); + if (result) + mail_count = (*result)[0].GetUInt32(); + + if (count > 0) + { + result=CharacterDatabase.PQuery( + // 0 1 2 3 4 5 6 + "SELECT mail_items.item_guid, mail.sender, mail.receiver, char_s.account, char_s.name, char_r.account, char_r.name " + "FROM mail,mail_items,characters as char_s,characters as char_r " + "WHERE mail_items.item_template='%u' AND char_s.guid = mail.sender AND char_r.guid = mail.receiver AND mail.id=mail_items.mail_id LIMIT %u", + item_id,uint32(count)); + } + else + result = QueryResult_AutoPtr(NULL); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 item_guid = fields[0].GetUInt32(); + uint32 item_s = fields[1].GetUInt32(); + uint32 item_r = fields[2].GetUInt32(); + uint32 item_s_acc = fields[3].GetUInt32(); + std::string item_s_name = fields[4].GetCppString(); + uint32 item_r_acc = fields[5].GetUInt32(); + std::string item_r_name = fields[6].GetCppString(); + + char const* item_pos = "[in mail]"; + + PSendSysMessage(LANG_ITEMLIST_MAIL, + item_guid,item_s_name.c_str(),item_s,item_s_acc,item_r_name.c_str(),item_r,item_r_acc,item_pos); + } while (result->NextRow()); + + int64 res_count = result->GetRowCount(); + + if (count > res_count) + count-=res_count; + else if (count) + count = 0; + } + + // auction case + uint32 auc_count = 0; + result=CharacterDatabase.PQuery("SELECT COUNT(item_template) FROM auctionhouse WHERE item_template='%u'",item_id); + if (result) + auc_count = (*result)[0].GetUInt32(); + + if (count > 0) + { + result=CharacterDatabase.PQuery( + // 0 1 2 3 + "SELECT auctionhouse.itemguid, auctionhouse.itemowner, characters.account, characters.name " + "FROM auctionhouse,characters WHERE auctionhouse.item_template='%u' AND characters.guid = auctionhouse.itemowner LIMIT %u", + item_id,uint32(count)); + } + else + result = QueryResult_AutoPtr(NULL); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 item_guid = fields[0].GetUInt32(); + uint32 owner = fields[1].GetUInt32(); + uint32 owner_acc = fields[2].GetUInt32(); + std::string owner_name = fields[3].GetCppString(); + + char const* item_pos = "[in auction]"; + + PSendSysMessage(LANG_ITEMLIST_AUCTION, item_guid, owner_name.c_str(), owner, owner_acc,item_pos); + } while (result->NextRow()); + } + + // guild bank case + uint32 guild_count = 0; + result=CharacterDatabase.PQuery("SELECT COUNT(item_entry) FROM guild_bank_item WHERE item_entry='%u'",item_id); + if (result) + guild_count = (*result)[0].GetUInt32(); + + result=CharacterDatabase.PQuery( + // 0 1 2 + "SELECT gi.item_guid, gi.guildid, guild.name " + "FROM guild_bank_item AS gi, guild WHERE gi.item_entry='%u' AND gi.guildid = guild.guildid LIMIT %u ", + item_id,uint32(count)); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 item_guid = fields[0].GetUInt32(); + uint32 guild_guid = fields[1].GetUInt32(); + std::string guild_name = fields[2].GetCppString(); + + char const* item_pos = "[in guild bank]"; + + PSendSysMessage(LANG_ITEMLIST_GUILD,item_guid,guild_name.c_str(),guild_guid,item_pos); + } while (result->NextRow()); + + int64 res_count = result->GetRowCount(); + + if (count > res_count) + count-=res_count; + else if (count) + count = 0; + } + + if (inv_count+mail_count+auc_count+guild_count == 0) + { + SendSysMessage(LANG_COMMAND_NOITEMFOUND); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_COMMAND_LISTITEMMESSAGE,item_id,inv_count+mail_count+auc_count+guild_count,inv_count,mail_count,auc_count,guild_count); + + return true; +} + +bool ChatHandler::HandleListObjectCommand(const char *args) +{ + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry"); + if (!cId) + return false; + + uint32 go_id = atol(cId); + if (!go_id) + { + PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); + SetSentErrorMessage(true); + return false; + } + + GameObjectInfo const * gInfo = objmgr.GetGameObjectInfo(go_id); + if (!gInfo) + { + PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); + SetSentErrorMessage(true); + return false; + } + + char* c_count = strtok(NULL, " "); + int count = c_count ? atol(c_count) : 10; + + if (count < 0) + return false; + + QueryResult_AutoPtr result; + + uint32 obj_count = 0; + result=WorldDatabase.PQuery("SELECT COUNT(guid) FROM gameobject WHERE id='%u'",go_id); + if (result) + obj_count = (*result)[0].GetUInt32(); + + if (m_session) + { + Player* pl = m_session->GetPlayer(); + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),go_id,uint32(count)); + } + else + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map FROM gameobject WHERE id = '%u' LIMIT %u", + go_id,uint32(count)); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + float x = fields[1].GetFloat(); + float y = fields[2].GetFloat(); + float z = fields[3].GetFloat(); + int mapid = fields[4].GetUInt16(); + + if (m_session) + PSendSysMessage(LANG_GO_LIST_CHAT, guid, guid, gInfo->name, x, y, z, mapid); + else + PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name, x, y, z, mapid); + } while (result->NextRow()); + } + + PSendSysMessage(LANG_COMMAND_LISTOBJMESSAGE,go_id,obj_count); + return true; +} + +bool ChatHandler::HandleGameObjectStateCommand(const char *args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args, "Hgameobject"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + GameObject* gobj = NULL; + + if (GameObjectData const* goData = objmgr.GetGOData(lowguid)) + gobj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid, goData->id); + + if (!gobj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* ctype = strtok(NULL, " "); + if (!ctype) + return false; + + int32 type = atoi(ctype); + if (type < 0) + { + if (type == -1) + gobj->SendObjectDeSpawnAnim(gobj->GetGUID()); + else if (type == -2) + { + return false; + } + return true; + } + + char* cstate = strtok(NULL, " "); + if (!cstate) + return false; + + int32 state = atoi(cstate); + + if (type < 4) + gobj->SetByteValue(GAMEOBJECT_BYTES_1, type, state); + else if (type == 4) + { + WorldPacket data(SMSG_GAMEOBJECT_CUSTOM_ANIM,8+4); + data << gobj->GetGUID(); + data << (uint32)(state); + gobj->SendMessageToSet(&data, true); + } + PSendSysMessage("Set gobject type %d state %d", type, state); + + return true; +} + +bool ChatHandler::HandleListCreatureCommand(const char *args) +{ + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature_entry"); + if (!cId) + return false; + + uint32 cr_id = atol(cId); + if (!cr_id) + { + PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); + SetSentErrorMessage(true); + return false; + } + + CreatureInfo const* cInfo = objmgr.GetCreatureTemplate(cr_id); + if (!cInfo) + { + PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); + SetSentErrorMessage(true); + return false; + } + + char* c_count = strtok(NULL, " "); + int count = c_count ? atol(c_count) : 10; + + if (count < 0) + return false; + + QueryResult_AutoPtr result; + + uint32 cr_count = 0; + result=WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id='%u'",cr_id); + if (result) + cr_count = (*result)[0].GetUInt32(); + + if (m_session) + { + Player* pl = m_session->GetPlayer(); + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM creature WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), cr_id,uint32(count)); + } + else + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map FROM creature WHERE id = '%u' LIMIT %u", + cr_id,uint32(count)); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + float x = fields[1].GetFloat(); + float y = fields[2].GetFloat(); + float z = fields[3].GetFloat(); + int mapid = fields[4].GetUInt16(); + + if (m_session) + PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, cInfo->Name, x, y, z, mapid); + else + PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name, x, y, z, mapid); + } while (result->NextRow()); + } + + PSendSysMessage(LANG_COMMAND_LISTCREATUREMESSAGE,cr_id,cr_count); + return true; +} + +bool ChatHandler::HandleLookupItemCommand(const char *args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + bool found = false; + + // Search in `item_template` + for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) + { + ItemPrototype const *pProto = sItemStorage.LookupEntry<ItemPrototype >(id); + if (!pProto) + continue; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId); + if (il) + { + if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty()) + { + std::string name = il->Name[loc_idx]; + + if (Utf8FitTo(name, wnamepart)) + { + if (m_session) + PSendSysMessage(LANG_ITEM_LIST_CHAT, id, id, name.c_str()); + else + PSendSysMessage(LANG_ITEM_LIST_CONSOLE, id, name.c_str()); + + if (!found) + found = true; + + continue; + } + } + } + } + + std::string name = pProto->Name1; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + { + if (m_session) + PSendSysMessage(LANG_ITEM_LIST_CHAT, id, id, name.c_str()); + else + PSendSysMessage(LANG_ITEM_LIST_CONSOLE, id, name.c_str()); + + if (!found) + found = true; + } + } + + if (!found) + SendSysMessage(LANG_COMMAND_NOITEMFOUND); + + return true; +} + +bool ChatHandler::HandleLookupItemSetCommand(const char *args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + bool found = false; + + // Search in ItemSet.dbc + for (uint32 id = 0; id < sItemSetStore.GetNumRows(); id++) + { + ItemSetEntry const *set = sItemSetStore.LookupEntry(id); + if (set) + { + int loc = GetSessionDbcLocale(); + std::string name = set->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = set->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + // send item set in "id - [namedlink locale]" format + if (m_session) + PSendSysMessage(LANG_ITEMSET_LIST_CHAT,id,id,name.c_str(),localeNames[loc]); + else + PSendSysMessage(LANG_ITEMSET_LIST_CONSOLE,id,name.c_str(),localeNames[loc]); + + if (!found) + found = true; + } + } + } + if (!found) + SendSysMessage(LANG_COMMAND_NOITEMSETFOUND); + return true; +} + +bool ChatHandler::HandleLookupSkillCommand(const char *args) +{ + if (!*args) + return false; + + // can be NULL in console call + Player* target = getSelectedPlayer(); + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + bool found = false; + + // Search in SkillLine.dbc + for (uint32 id = 0; id < sSkillLineStore.GetNumRows(); id++) + { + SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(id); + if (skillInfo) + { + int loc = GetSessionDbcLocale(); + std::string name = skillInfo->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = skillInfo->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + char valStr[50] = ""; + char const* knownStr = ""; + if (target && target->HasSkill(id)) + { + knownStr = GetTrinityString(LANG_KNOWN); + uint32 curValue = target->GetPureSkillValue(id); + uint32 maxValue = target->GetPureMaxSkillValue(id); + uint32 permValue = target->GetSkillPermBonusValue(id); + uint32 tempValue = target->GetSkillTempBonusValue(id); + + char const* valFormat = GetTrinityString(LANG_SKILL_VALUES); + snprintf(valStr,50,valFormat,curValue,maxValue,permValue,tempValue); + } + + // send skill in "id - [namedlink locale]" format + if (m_session) + PSendSysMessage(LANG_SKILL_LIST_CHAT,id,id,name.c_str(),localeNames[loc],knownStr,valStr); + else + PSendSysMessage(LANG_SKILL_LIST_CONSOLE,id,name.c_str(),localeNames[loc],knownStr,valStr); + + if (!found) + found = true; + } + } + } + if (!found) + SendSysMessage(LANG_COMMAND_NOSKILLFOUND); + return true; +} + +bool ChatHandler::HandleLookupSpellCommand(const char *args) +{ + if (!*args) + return false; + + // can be NULL at console call + Player* target = getSelectedPlayer(); + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + bool found = false; + + // Search in Spell.dbc + for (uint32 id = 0; id < sSpellStore.GetNumRows(); id++) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(id); + if (spellInfo) + { + int loc = GetSessionDbcLocale(); + std::string name = spellInfo->SpellName[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = spellInfo->SpellName[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + bool known = target && target->HasSpell(id); + bool learn = (spellInfo->Effect[0] == SPELL_EFFECT_LEARN_SPELL); + + uint32 talentCost = GetTalentSpellCost(id); + + bool talent = (talentCost > 0); + bool passive = IsPassiveSpell(id); + bool active = target && target->HasAura(id); + + // unit32 used to prevent interpreting uint8 as char at output + // find rank of learned spell for learning spell, or talent rank + uint32 rank = talentCost ? talentCost : spellmgr.GetSpellRank(learn ? spellInfo->EffectTriggerSpell[0] : id); + + // send spell in "id - [name, rank N] [talent] [passive] [learn] [known]" format + std::ostringstream ss; + if (m_session) + ss << id << " - |cffffffff|Hspell:" << id << "|h[" << name; + else + ss << id << " - " << name; + + // include rank in link name + if (rank) + ss << GetTrinityString(LANG_SPELL_RANK) << rank; + + if (m_session) + ss << " " << localeNames[loc] << "]|h|r"; + else + ss << " " << localeNames[loc]; + + if (talent) + ss << GetTrinityString(LANG_TALENT); + if (passive) + ss << GetTrinityString(LANG_PASSIVE); + if (learn) + ss << GetTrinityString(LANG_LEARN); + if (known) + ss << GetTrinityString(LANG_KNOWN); + if (active) + ss << GetTrinityString(LANG_ACTIVE); + + SendSysMessage(ss.str().c_str()); + + if (!found) + found = true; + } + } + } + if (!found) + SendSysMessage(LANG_COMMAND_NOSPELLFOUND); + return true; +} + +bool ChatHandler::HandleLookupQuestCommand(const char *args) +{ + if (!*args) + return false; + + // can be NULL at console call + Player* target = getSelectedPlayer(); + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + bool found = false; + + ObjectMgr::QuestMap const& qTemplates = objmgr.GetQuestTemplates(); + for (ObjectMgr::QuestMap::const_iterator iter = qTemplates.begin(); iter != qTemplates.end(); ++iter) + { + Quest * qinfo = iter->second; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + QuestLocale const *il = objmgr.GetQuestLocale(qinfo->GetQuestId()); + if (il) + { + if (il->Title.size() > loc_idx && !il->Title[loc_idx].empty()) + { + std::string title = il->Title[loc_idx]; + + if (Utf8FitTo(title, wnamepart)) + { + char const* statusStr = ""; + + if (target) + { + QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); + + if (status == QUEST_STATUS_COMPLETE) + { + if (target->GetQuestRewardStatus(qinfo->GetQuestId())) + statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); + else + statusStr = GetTrinityString(LANG_COMMAND_QUEST_COMPLETE); + } + else if (status == QUEST_STATUS_INCOMPLETE) + statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); + } + + if (m_session) + PSendSysMessage(LANG_QUEST_LIST_CHAT,qinfo->GetQuestId(),qinfo->GetQuestId(),qinfo->GetQuestLevel(),title.c_str(),statusStr); + else + PSendSysMessage(LANG_QUEST_LIST_CONSOLE,qinfo->GetQuestId(),title.c_str(),statusStr); + + if (!found) + found = true; + + continue; + } + } + } + } + + std::string title = qinfo->GetTitle(); + if (title.empty()) + continue; + + if (Utf8FitTo(title, wnamepart)) + { + char const* statusStr = ""; + + if (target) + { + QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); + + if (status == QUEST_STATUS_COMPLETE) + { + if (target->GetQuestRewardStatus(qinfo->GetQuestId())) + statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); + else + statusStr = GetTrinityString(LANG_COMMAND_QUEST_COMPLETE); + } + else if (status == QUEST_STATUS_INCOMPLETE) + statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); + } + + if (m_session) + PSendSysMessage(LANG_QUEST_LIST_CHAT,qinfo->GetQuestId(),qinfo->GetQuestId(),qinfo->GetQuestLevel(),title.c_str(),statusStr); + else + PSendSysMessage(LANG_QUEST_LIST_CONSOLE,qinfo->GetQuestId(),title.c_str(),statusStr); + + if (!found) + found = true; + } + } + + if (!found) + SendSysMessage(LANG_COMMAND_NOQUESTFOUND); + + return true; +} + +bool ChatHandler::HandleLookupCreatureCommand(const char *args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if (!Utf8toWStr (namepart,wnamepart)) + return false; + + wstrToLower (wnamepart); + + bool found = false; + + for (uint32 id = 0; id< sCreatureStorage.MaxEntry; ++id) + { + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo> (id); + if (!cInfo) + continue; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + CreatureLocale const *cl = objmgr.GetCreatureLocale (id); + if (cl) + { + if (cl->Name.size() > loc_idx && !cl->Name[loc_idx].empty ()) + { + std::string name = cl->Name[loc_idx]; + + if (Utf8FitTo (name, wnamepart)) + { + if (m_session) + PSendSysMessage (LANG_CREATURE_ENTRY_LIST_CHAT, id, id, name.c_str ()); + else + PSendSysMessage (LANG_CREATURE_ENTRY_LIST_CONSOLE, id, name.c_str ()); + + if (!found) + found = true; + + continue; + } + } + } + } + + std::string name = cInfo->Name; + if (name.empty ()) + continue; + + if (Utf8FitTo(name, wnamepart)) + { + if (m_session) + PSendSysMessage (LANG_CREATURE_ENTRY_LIST_CHAT, id, id, name.c_str ()); + else + PSendSysMessage (LANG_CREATURE_ENTRY_LIST_CONSOLE, id, name.c_str ()); + + if (!found) + found = true; + } + } + + if (!found) + SendSysMessage (LANG_COMMAND_NOCREATUREFOUND); + + return true; +} + +bool ChatHandler::HandleLookupObjectCommand(const char *args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + bool found = false; + + for (uint32 id = 0; id< sGOStorage.MaxEntry; id++) + { + GameObjectInfo const* gInfo = sGOStorage.LookupEntry<GameObjectInfo>(id); + if (!gInfo) + continue; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + GameObjectLocale const *gl = objmgr.GetGameObjectLocale(id); + if (gl) + { + if (gl->Name.size() > loc_idx && !gl->Name[loc_idx].empty()) + { + std::string name = gl->Name[loc_idx]; + + if (Utf8FitTo(name, wnamepart)) + { + if (m_session) + PSendSysMessage(LANG_GO_ENTRY_LIST_CHAT, id, id, name.c_str()); + else + PSendSysMessage(LANG_GO_ENTRY_LIST_CONSOLE, id, name.c_str()); + + if (!found) + found = true; + + continue; + } + } + } + } + + std::string name = gInfo->name; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + { + if (m_session) + PSendSysMessage(LANG_GO_ENTRY_LIST_CHAT, id, id, name.c_str()); + else + PSendSysMessage(LANG_GO_ENTRY_LIST_CONSOLE, id, name.c_str()); + + if (!found) + found = true; + } + } + + if (!found) + SendSysMessage(LANG_COMMAND_NOGAMEOBJECTFOUND); + + return true; +} + +bool ChatHandler::HandleLookupFactionCommand(const char *args) +{ + if (!*args) + return false; + + // Can be NULL at console call + Player *target = getSelectedPlayer (); + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr (namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower (wnamepart); + + bool found = false; + + for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id) + { + FactionEntry const *factionEntry = sFactionStore.LookupEntry (id); + if (factionEntry) + { + FactionState const* repState = target ? target->GetReputationMgr().GetState(factionEntry) : NULL; + + int loc = GetSessionDbcLocale(); + std::string name = factionEntry->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = factionEntry->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format + // or "id - [faction] [no reputation]" format + std::ostringstream ss; + if (m_session) + ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r"; + else + ss << id << " - " << name << " " << localeNames[loc]; + + if (repState) // and then target != NULL also + { + ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); + std::string rankName = GetTrinityString(ReputationRankStrIndex[rank]); + + ss << " " << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ")"; + + if (repState->Flags & FACTION_FLAG_VISIBLE) + ss << GetTrinityString(LANG_FACTION_VISIBLE); + if (repState->Flags & FACTION_FLAG_AT_WAR) + ss << GetTrinityString(LANG_FACTION_ATWAR); + if (repState->Flags & FACTION_FLAG_PEACE_FORCED) + ss << GetTrinityString(LANG_FACTION_PEACE_FORCED); + if (repState->Flags & FACTION_FLAG_HIDDEN) + ss << GetTrinityString(LANG_FACTION_HIDDEN); + if (repState->Flags & FACTION_FLAG_INVISIBLE_FORCED) + ss << GetTrinityString(LANG_FACTION_INVISIBLE_FORCED); + if (repState->Flags & FACTION_FLAG_INACTIVE) + ss << GetTrinityString(LANG_FACTION_INACTIVE); + } + else + ss << GetTrinityString(LANG_FACTION_NOREPUTATION); + + SendSysMessage(ss.str().c_str()); + + if (!found) + found = true; + } + } + } + + if (!found) + SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND); + return true; +} + +bool ChatHandler::HandleLookupTaxiNodeCommand(const char * args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + bool found = false; + + // Search in TaxiNodes.dbc + for (uint32 id = 0; id < sTaxiNodesStore.GetNumRows(); id++) + { + TaxiNodesEntry const *nodeEntry = sTaxiNodesStore.LookupEntry(id); + if (nodeEntry) + { + int loc = GetSessionDbcLocale(); + std::string name = nodeEntry->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = nodeEntry->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + // send taxinode in "id - [name] (Map:m X:x Y:y Z:z)" format + if (m_session) + PSendSysMessage (LANG_TAXINODE_ENTRY_LIST_CHAT, id, id, name.c_str(),localeNames[loc], + nodeEntry->map_id,nodeEntry->x,nodeEntry->y,nodeEntry->z); + else + PSendSysMessage (LANG_TAXINODE_ENTRY_LIST_CONSOLE, id, name.c_str(), localeNames[loc], + nodeEntry->map_id,nodeEntry->x,nodeEntry->y,nodeEntry->z); + + if (!found) + found = true; + } + } + } + if (!found) + SendSysMessage(LANG_COMMAND_NOTAXINODEFOUND); + return true; +} + +bool ChatHandler::HandleLookupMapCommand(const char *args) +{ + if (!*args) + return false; + + /*std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if (!Utf8toWStr(namepart, wnamepart)) + return false; + + wstrToLower(wnamepart); + + bool found = false; + + // search in Map.dbc + for (uint32 id = 0; id < sMapStore.GetNumRows(); id++) + { + MapEntry const* MapInfo = sMapStore.LookupEntry(id); + if (MapInfo) + { + uint8 loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale(); + + std::string name = MapInfo->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = LOCALE_enUS; + for (; loc < MAX_LOCALE; loc++) + { + if (m_session && loc == m_session->GetSessionDbcLocale()) + continue; + + name = MapInfo->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + // send map in "id - [name][Continent][Instance/Battleground/Arena][Raid reset time:][Heroic reset time:][Mountable]" format + std::ostringstream ss; + + if (m_session) + ss << id << " - |cffffffff|Hmap:" << id << "|h[" << name << "]"; + else // console + ss << id << " - [" << name << "]"; + + if (MapInfo->IsContinent()) + ss << GetTrinityString(LANG_CONTINENT); + + switch(MapInfo->map_type) + { + case MAP_INSTANCE: ss << GetTrinityString(LANG_INSTANCE); break; + case MAP_BATTLEGROUND: ss << GetTrinityString(LANG_BATTLEGROUND); break; + case MAP_ARENA: ss << GetTrinityString(LANG_ARENA); break; + } + + if (MapInfo->IsRaid()) + ss << GetTrinityString(LANG_RAID); + + if (MapInfo->SupportsHeroicMode()) + ss << GetTrinityString(LANG_HEROIC); + + uint32 ResetTimeRaid = MapInfo->resetTimeRaid; + + std::string ResetTimeRaidStr; + if (ResetTimeRaid) + ResetTimeRaidStr = secsToTimeString(ResetTimeRaid, true, false); + + uint32 ResetTimeHeroic = MapInfo->resetTimeHeroic; + std::string ResetTimeHeroicStr; + if (ResetTimeHeroic) + ResetTimeHeroicStr = secsToTimeString(ResetTimeHeroic, true, false); + + if (MapInfo->IsMountAllowed()) + ss << GetTrinityString(LANG_MOUNTABLE); + + if (ResetTimeRaid && !ResetTimeHeroic) + PSendSysMessage(ss.str().c_str(), ResetTimeRaidStr.c_str()); + else if (!ResetTimeRaid && ResetTimeHeroic) + PSendSysMessage(ss.str().c_str(), ResetTimeHeroicStr.c_str()); + else if (ResetTimeRaid && ResetTimeHeroic) + PSendSysMessage(ss.str().c_str(), ResetTimeRaidStr.c_str(), ResetTimeHeroicStr.c_str()); + else + SendSysMessage(ss.str().c_str()); + + if (!found) + found = true; + } + } + } + + if (!found) + SendSysMessage(LANG_COMMAND_NOMAPFOUND); + */ + return true; +} + +/** \brief GM command level 3 - Create a guild. + * + * This command allows a GM (level 3) to create a guild. + * + * The "args" parameter contains the name of the guild leader + * and then the name of the guild. + * + */ +bool ChatHandler::HandleGuildCreateCommand(const char *args) +{ + if (!*args) + return false; + + // if not guild name only (in "") then player name + Player* target; + if (!extractPlayerTarget(*args != '"' ? (char*)args : NULL, &target)) + return false; + + char* tailStr = *args != '"' ? strtok(NULL, "") : (char*)args; + if (!tailStr) + return false; + + char* guildStr = extractQuotedArg(tailStr); + if (!guildStr) + return false; + + std::string guildname = guildStr; + + if (target->GetGuildId()) + { + SendSysMessage (LANG_PLAYER_IN_GUILD); + return true; + } + + Guild *guild = new Guild; + if (!guild->Create (target,guildname)) + { + delete guild; + SendSysMessage (LANG_GUILD_NOT_CREATED); + SetSentErrorMessage (true); + return false; + } + + objmgr.AddGuild (guild); + return true; +} + +bool ChatHandler::HandleGuildInviteCommand(const char *args) +{ + if (!*args) + return false; + + // if not guild name only (in "") then player name + uint64 target_guid; + if (!extractPlayerTarget(*args != '"' ? (char*)args : NULL, NULL, &target_guid)) + return false; + + char* tailStr = *args != '"' ? strtok(NULL, "") : (char*)args; + if (!tailStr) + return false; + + char* guildStr = extractQuotedArg(tailStr); + if (!guildStr) + return false; + + std::string glName = guildStr; + Guild* targetGuild = objmgr.GetGuildByName (glName); + if (!targetGuild) + return false; + + // player's guild membership checked in AddMember before add + if (!targetGuild->AddMember (target_guid,targetGuild->GetLowestRank ())) + return false; + + return true; +} + +bool ChatHandler::HandleGuildUninviteCommand(const char *args) +{ + Player* target; + uint64 target_guid; + if (!extractPlayerTarget((char*)args,&target,&target_guid)) + return false; + + uint32 glId = target ? target->GetGuildId () : Player::GetGuildIdFromDB (target_guid); + if (!glId) + return false; + + Guild* targetGuild = objmgr.GetGuildById (glId); + if (!targetGuild) + return false; + + targetGuild->DelMember (target_guid); + return true; +} + +bool ChatHandler::HandleGuildRankCommand(const char *args) +{ + char* nameStr; + char* rankStr; + extractOptFirstArg((char*)args,&nameStr,&rankStr); + if (!rankStr) + return false; + + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) + return false; + + uint32 glId = target ? target->GetGuildId () : Player::GetGuildIdFromDB (target_guid); + if (!glId) + return false; + + Guild* targetGuild = objmgr.GetGuildById (glId); + if (!targetGuild) + return false; + + uint32 newrank = uint32 (atoi (rankStr)); + if (newrank > targetGuild->GetLowestRank ()) + return false; + + targetGuild->ChangeRank (target_guid,newrank); + return true; +} + +bool ChatHandler::HandleGuildDeleteCommand(const char *args) +{ + if (!*args) + return false; + + char* guildStr = extractQuotedArg((char*)args); + if (!guildStr) + return false; + + std::string gld = guildStr; + + Guild* targetGuild = objmgr.GetGuildByName (gld); + if (!targetGuild) + return false; + + targetGuild->Disband (); + + return true; +} + +bool ChatHandler::HandleGetDistanceCommand(const char *args) +{ + WorldObject* obj = NULL; + + if (*args) + { + uint64 guid = extractGuidFromLink((char*)args); + if (guid) + obj = (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*m_session->GetPlayer(),guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + + if (!obj) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + } + else + { + obj = getSelectedUnit(); + + if (!obj) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + } + + PSendSysMessage(LANG_DISTANCE, m_session->GetPlayer()->GetDistance(obj), m_session->GetPlayer()->GetDistance2d(obj), m_session->GetPlayer()->GetExactDist(obj), m_session->GetPlayer()->GetExactDist2d(obj)); + return true; +} + +bool ChatHandler::HandleDieCommand(const char* /*args*/) +{ + Unit* target = getSelectedUnit(); + + if (!target || !m_session->GetPlayer()->GetSelection()) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (target->GetTypeId() == TYPEID_PLAYER) + { + if (HasLowerSecurity((Player*)target,0,false)) + return false; + } + + if (target->isAlive()) + { + if (sWorld.getConfig(CONFIG_DIE_COMMAND_MODE)) + m_session->GetPlayer()->Kill(target); + else + m_session->GetPlayer()->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + return true; +} + +bool ChatHandler::HandleDamageCommand(const char * args) +{ + if (!*args) + return false; + + Unit* target = getSelectedUnit(); + + if (!target || !m_session->GetPlayer()->GetSelection()) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (!target->isAlive()) + return true; + + char* damageStr = strtok((char*)args, " "); + if (!damageStr) + return false; + + int32 damage_int = atoi((char*)damageStr); + if (damage_int <= 0) + return true; + + uint32 damage = damage_int; + + char* schoolStr = strtok((char*)NULL, " "); + + // flat melee damage without resistence/etc reduction + if (!schoolStr) + { + m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + if (target != m_session->GetPlayer()) + m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); + return true; + } + + uint32 school = schoolStr ? atoi((char*)schoolStr) : SPELL_SCHOOL_NORMAL; + if (school >= MAX_SPELL_SCHOOL) + return false; + + SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); + + if (schoolmask & SPELL_SCHOOL_MASK_NORMAL) + damage = m_session->GetPlayer()->CalcArmorReducedDamage(target, damage, NULL, BASE_ATTACK); + + char* spellStr = strtok((char*)NULL, " "); + + // melee damage by specific school + if (!spellStr) + { + uint32 absorb = 0; + uint32 resist = 0; + + m_session->GetPlayer()->CalcAbsorbResist(target,schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + + if (damage <= absorb + resist) + return true; + + damage -= absorb + resist; + + m_session->GetPlayer()->DealDamageMods(target,damage,&absorb); + m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); + m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, schoolmask, damage, absorb, resist, VICTIMSTATE_NORMAL, 0); + return true; + } + + // non-melee damage + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellid = extractSpellIdFromLink((char*)args); + if (!spellid || !sSpellStore.LookupEntry(spellid)) + return false; + + m_session->GetPlayer()->SpellNonMeleeDamageLog(target, spellid, damage); + return true; +} + +bool ChatHandler::HandleModifyArenaCommand(const char * args) +{ + if (!*args) + return false; + + Player *target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + int32 amount = (uint32)atoi(args); + + target->ModifyArenaPoints(amount); + + PSendSysMessage(LANG_COMMAND_MODIFY_ARENA, GetNameLink(target).c_str(), target->GetArenaPoints()); + + return true; +} + +bool ChatHandler::HandleReviveCommand(const char *args) +{ + Player* target; + uint64 target_guid; + if (!extractPlayerTarget((char*)args,&target,&target_guid)) + return false; + + if (target) + { + target->ResurrectPlayer(target->GetSession()->GetSecurity() > SEC_PLAYER ? 1.0f : 0.5f); + target->SpawnCorpseBones(); + target->SaveToDB(); + } + else + // will resurrected at login without corpse + ObjectAccessor::Instance().ConvertCorpseForPlayer(target_guid); + + return true; +} + +bool ChatHandler::HandleAuraCommand(const char *args) +{ + Unit *target = getSelectedUnit(); + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellID = extractSpellIdFromLink((char*)args); + + if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID)) + Aura::TryCreate(spellInfo, target, target); + + return true; +} + +bool ChatHandler::HandleUnAuraCommand(const char *args) +{ + Unit *target = getSelectedUnit(); + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + std::string argstr = args; + if (argstr == "all") + { + target->RemoveAllAuras(); + return true; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellID = extractSpellIdFromLink((char*)args); + if (!spellID) + return false; + + target->RemoveAurasDueToSpell(spellID); + + return true; +} + +bool ChatHandler::HandleLinkGraveCommand(const char *args) +{ + if (!*args) + return false; + + char* px = strtok((char*)args, " "); + if (!px) + return false; + + uint32 g_id = (uint32)atoi(px); + + uint32 g_team; + + char* px2 = strtok(NULL, " "); + + if (!px2) + g_team = 0; + else if (strncmp(px2,"horde",6) == 0) + g_team = HORDE; + else if (strncmp(px2,"alliance",9) == 0) + g_team = ALLIANCE; + else + return false; + + WorldSafeLocsEntry const* graveyard = sWorldSafeLocsStore.LookupEntry(g_id); + + if (!graveyard) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST, g_id); + SetSentErrorMessage(true); + return false; + } + + Player* player = m_session->GetPlayer(); + + uint32 zoneId = player->GetZoneId(); + + AreaTableEntry const *areaEntry = GetAreaEntryByAreaID(zoneId); + if (!areaEntry || areaEntry->zone !=0) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDWRONGZONE, g_id,zoneId); + SetSentErrorMessage(true); + return false; + } + + if (objmgr.AddGraveYardLink(g_id,zoneId,g_team)) + PSendSysMessage(LANG_COMMAND_GRAVEYARDLINKED, g_id,zoneId); + else + PSendSysMessage(LANG_COMMAND_GRAVEYARDALRLINKED, g_id,zoneId); + + return true; +} + +bool ChatHandler::HandleNearGraveCommand(const char *args) +{ + uint32 g_team; + + size_t argslen = strlen(args); + + if (!*args) + g_team = 0; + else if (strncmp((char*)args,"horde",argslen) == 0) + g_team = HORDE; + else if (strncmp((char*)args,"alliance",argslen) == 0) + g_team = ALLIANCE; + else + return false; + + Player* player = m_session->GetPlayer(); + uint32 zone_id = player->GetZoneId(); + + WorldSafeLocsEntry const* graveyard = objmgr.GetClosestGraveYard( + player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(),player->GetMapId(),g_team); + + if (graveyard) + { + uint32 g_id = graveyard->ID; + + GraveYardData const* data = objmgr.FindGraveYardData(g_id,zone_id); + if (!data) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDERROR,g_id); + SetSentErrorMessage(true); + return false; + } + + g_team = data->team; + + std::string team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_NOTEAM); + + if (g_team == 0) + team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_ANY); + else if (g_team == HORDE) + team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_HORDE); + else if (g_team == ALLIANCE) + team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_ALLIANCE); + + PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, g_id,team_name.c_str(),zone_id); + } + else + { + std::string team_name; + + if (g_team == 0) + team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_ANY); + else if (g_team == HORDE) + team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_HORDE); + else if (g_team == ALLIANCE) + team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_ALLIANCE); + + if (g_team == ~uint32(0)) + PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, zone_id); + else + PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, zone_id,team_name.c_str()); + } + + return true; +} + +//-----------------------Npc Commands----------------------- +bool ChatHandler::HandleNpcAllowMovementCommand(const char* /*args*/) +{ + if (sWorld.getAllowMovement()) + { + sWorld.SetAllowMovement(false); + SendSysMessage(LANG_CREATURE_MOVE_DISABLED); + } + else + { + sWorld.SetAllowMovement(true); + SendSysMessage(LANG_CREATURE_MOVE_ENABLED); + } + return true; +} + +bool ChatHandler::HandleNpcChangeEntryCommand(const char *args) +{ + if (!*args) + return false; + + uint32 newEntryNum = atoi(args); + if (!newEntryNum) + return false; + + Unit* unit = getSelectedUnit(); + if (!unit || unit->GetTypeId() != TYPEID_UNIT) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + Creature* creature = unit->ToCreature(); + if (creature->UpdateEntry(newEntryNum)) + SendSysMessage(LANG_DONE); + else + SendSysMessage(LANG_ERROR); + return true; +} + +bool ChatHandler::HandleNpcInfoCommand(const char* /*args*/) +{ + Creature* target = getSelectedCreature(); + + if (!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint32 faction = target->getFaction(); + uint32 npcflags = target->GetUInt32Value(UNIT_NPC_FLAGS); + uint32 displayid = target->GetDisplayId(); + uint32 nativeid = target->GetNativeDisplayId(); + uint32 Entry = target->GetEntry(); + CreatureInfo const* cInfo = target->GetCreatureInfo(); + + int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL); + if (curRespawnDelay < 0) + curRespawnDelay = 0; + std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true); + std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true); + + PSendSysMessage(LANG_NPCINFO_CHAR, target->GetDBTableGUIDLow(), faction, npcflags, Entry, displayid, nativeid); + PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel()); + PSendSysMessage(LANG_NPCINFO_HEALTH,target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth()); + PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction()); + PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str()); + PSendSysMessage(LANG_NPCINFO_LOOT, cInfo->lootid,cInfo->pickpocketLootId,cInfo->SkinLootId); + PSendSysMessage(LANG_NPCINFO_DUNGEON_ID, target->GetInstanceId()); + PSendSysMessage(LANG_NPCINFO_PHASEMASK, target->GetPhaseMask()); + PSendSysMessage(LANG_NPCINFO_ARMOR, target->GetArmor()); + PSendSysMessage(LANG_NPCINFO_POSITION,float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ())); + if (const CreatureData* const linked = target->GetLinkedRespawnCreatureData()) + if (CreatureInfo const *master = GetCreatureInfo(linked->id)) + PSendSysMessage(LANG_NPCINFO_LINKGUID, objmgr.GetLinkedRespawnGuid(target->GetDBTableGUIDLow()), linked->id, master->Name); + + if ((npcflags & UNIT_NPC_FLAG_VENDOR)) + { + SendSysMessage(LANG_NPCINFO_VENDOR); + } + if ((npcflags & UNIT_NPC_FLAG_TRAINER)) + { + SendSysMessage(LANG_NPCINFO_TRAINER); + } + + return true; +} + +//play npc emote +bool ChatHandler::HandleNpcPlayEmoteCommand(const char *args) +{ + uint32 emote = atoi((char*)args); + + Creature* target = getSelectedCreature(); + if (!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote); + + return true; +} + +//TODO: NpcCommands that needs to be fixed : + +bool ChatHandler::HandleNpcAddWeaponCommand(const char* /*args*/) +{ + /*if (!*args) + return false; + + uint64 guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature *pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + char* pSlotID = strtok((char*)args, " "); + if (!pSlotID) + return false; + + char* pItemID = strtok(NULL, " "); + if (!pItemID) + return false; + + uint32 ItemID = atoi(pItemID); + uint32 SlotID = atoi(pSlotID); + + ItemPrototype* tmpItem = objmgr.GetItemPrototype(ItemID); + + bool added = false; + if (tmpItem) + { + switch(SlotID) + { + case 1: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, ItemID); + added = true; + break; + case 2: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, ItemID); + added = true; + break; + case 3: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02, ItemID); + added = true; + break; + default: + PSendSysMessage(LANG_ITEM_SLOT_NOT_EXIST,SlotID); + added = false; + break; + } + + if (added) + PSendSysMessage(LANG_ITEM_ADDED_TO_SLOT,ItemID,tmpItem->Name1,SlotID); + } + else + { + PSendSysMessage(LANG_ITEM_NOT_FOUND,ItemID); + return true; + } + */ + return true; +} +//---------------------------------------------------------- + +bool ChatHandler::HandleExploreCheatCommand(const char *args) +{ + if (!*args) + return false; + + int flag = atoi((char*)args); + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (flag != 0) + { + PSendSysMessage(LANG_YOU_SET_EXPLORE_ALL, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL,GetNameLink().c_str()); + } + else + { + PSendSysMessage(LANG_YOU_SET_EXPLORE_NOTHING, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING,GetNameLink().c_str()); + } + + for (uint8 i=0; i<PLAYER_EXPLORED_ZONES_SIZE; ++i) + { + if (flag != 0) + { + m_session->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i,0xFFFFFFFF); + } + else + { + m_session->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i,0); + } + } + + return true; +} + +bool ChatHandler::HandleHoverCommand(const char *args) +{ + char* px = strtok((char*)args, " "); + uint32 flag; + if (!px) + flag = 1; + else + flag = atoi(px); + + m_session->GetPlayer()->SetHover(flag); + + if (flag) + SendSysMessage(LANG_HOVER_ENABLED); + else + SendSysMessage(LANG_HOVER_DISABLED); + + return true; +} + +void ChatHandler::HandleCharacterLevel(Player* player, uint64 player_guid, uint32 oldlevel, uint32 newlevel) +{ + if (player) + { + player->GiveLevel(newlevel); + player->InitTalentForLevel(); + player->SetUInt32Value(PLAYER_XP,0); + + if (needReportToTarget(player)) + { + if (oldlevel == newlevel) + ChatHandler(player).PSendSysMessage(LANG_YOURS_LEVEL_PROGRESS_RESET,GetNameLink().c_str()); + else if (oldlevel < newlevel) + ChatHandler(player).PSendSysMessage(LANG_YOURS_LEVEL_UP,GetNameLink().c_str(),newlevel); + else // if (oldlevel > newlevel) + ChatHandler(player).PSendSysMessage(LANG_YOURS_LEVEL_DOWN,GetNameLink().c_str(),newlevel); + } + } + else + { + // update level and XP at level, all other will be updated at loading + CharacterDatabase.PExecute("UPDATE characters SET level = '%u', xp = 0 WHERE guid = '%u'", newlevel, GUID_LOPART(player_guid)); + } +} + +bool ChatHandler::HandleCharacterLevelCommand(const char *args) +{ + char* nameStr; + char* levelStr; + extractOptFirstArg((char*)args,&nameStr,&levelStr); + if (!levelStr) + return false; + + // exception opt second arg: .character level $name + if (isalpha(levelStr[0])) + { + nameStr = levelStr; + levelStr = NULL; // current level will used + } + + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) + return false; + + int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromDB(target_guid); + int32 newlevel = levelStr ? atoi(levelStr) : oldlevel; + + if (newlevel < 1) + return false; // invalid level + + if (newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level + newlevel = STRONG_MAX_LEVEL; + + HandleCharacterLevel(target,target_guid,oldlevel,newlevel); + + if (!m_session || m_session->GetPlayer() != target) // including player == NULL + { + std::string nameLink = playerLink(target_name); + PSendSysMessage(LANG_YOU_CHANGE_LVL,nameLink.c_str(),newlevel); + } + + return true; +} + +bool ChatHandler::HandleLevelUpCommand(const char *args) +{ + char* nameStr; + char* levelStr; + extractOptFirstArg((char*)args,&nameStr,&levelStr); + + // exception opt second arg: .character level $name + if (levelStr && isalpha(levelStr[0])) + { + nameStr = levelStr; + levelStr = NULL; // current level will used + } + + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) + return false; + + int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromDB(target_guid); + int32 addlevel = levelStr ? atoi(levelStr) : 1; + int32 newlevel = oldlevel + addlevel; + + if (newlevel < 1) + newlevel = 1; + + if (newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level + newlevel = STRONG_MAX_LEVEL; + + HandleCharacterLevel(target,target_guid,oldlevel,newlevel); + + if (!m_session || m_session->GetPlayer() != target) // including chr == NULL + { + std::string nameLink = playerLink(target_name); + PSendSysMessage(LANG_YOU_CHANGE_LVL,nameLink.c_str(),newlevel); + } + + return true; +} + +bool ChatHandler::HandleShowAreaCommand(const char *args) +{ + if (!*args) + return false; + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + int area = GetAreaFlagByAreaID(atoi((char*)args)); + int offset = area / 32; + uint32 val = (uint32)(1 << (area % 32)); + + if (area<0 || offset >= PLAYER_EXPLORED_ZONES_SIZE) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + uint32 currFields = chr->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); + chr->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields | val)); + + SendSysMessage(LANG_EXPLORE_AREA); + return true; +} + +bool ChatHandler::HandleHideAreaCommand(const char *args) +{ + if (!*args) + return false; + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + int area = GetAreaFlagByAreaID(atoi((char*)args)); + int offset = area / 32; + uint32 val = (uint32)(1 << (area % 32)); + + if (area<0 || offset >= PLAYER_EXPLORED_ZONES_SIZE) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + uint32 currFields = chr->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); + chr->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields ^ val)); + + SendSysMessage(LANG_UNEXPLORE_AREA); + return true; +} + +bool ChatHandler::HandleBankCommand(const char* /*args*/) +{ + m_session->SendShowBank(m_session->GetPlayer()->GetGUID()); + + return true; +} + +bool ChatHandler::HandleChangeWeather(const char *args) +{ + if (!*args) + return false; + + //Weather is OFF + if (!sWorld.getConfig(CONFIG_WEATHER)) + { + SendSysMessage(LANG_WEATHER_DISABLED); + SetSentErrorMessage(true); + return false; + } + + //*Change the weather of a cell + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + + if (!px || !py) + return false; + + uint32 type = (uint32)atoi(px); //0 to 3, 0: fine, 1: rain, 2: snow, 3: sand + float grade = (float)atof(py); //0 to 1, sending -1 is instand good weather + + Player *player = m_session->GetPlayer(); + uint32 zoneid = player->GetZoneId(); + + Weather* wth = sWorld.FindWeather(zoneid); + + if (!wth) + wth = sWorld.AddWeather(zoneid); + if (!wth) + { + SendSysMessage(LANG_NO_WEATHER); + SetSentErrorMessage(true); + return false; + } + + wth->SetWeather(WeatherType(type), grade); + + return true; +} + +bool ChatHandler::HandleDebugSet32Bit(const char *args) +{ + if (!*args) + return false; + + WorldObject* target = getSelectedObject(); + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + + if (!px || !py) + return false; + + uint32 Opcode = (uint32)atoi(px); + uint32 Value = (uint32)atoi(py); + if (Value > 32) //uint32 = 32 bits + return false; + + sLog.outDebug(GetTrinityString(LANG_SET_32BIT), Opcode, Value); + + uint32 iValue = Value ? 1 << (Value - 1) : 0; + target->SetUInt32Value(Opcode , iValue); + + PSendSysMessage(LANG_SET_32BIT_FIELD, Opcode, iValue); + return true; +} + +bool ChatHandler::HandleTeleAddCommand(const char * args) +{ + if (!*args) + return false; + + Player *player=m_session->GetPlayer(); + if (!player) + return false; + + std::string name = args; + + if (objmgr.GetGameTele(name)) + { + SendSysMessage(LANG_COMMAND_TP_ALREADYEXIST); + SetSentErrorMessage(true); + return false; + } + + GameTele tele; + tele.position_x = player->GetPositionX(); + tele.position_y = player->GetPositionY(); + tele.position_z = player->GetPositionZ(); + tele.orientation = player->GetOrientation(); + tele.mapId = player->GetMapId(); + tele.name = name; + + if (objmgr.AddGameTele(tele)) + { + SendSysMessage(LANG_COMMAND_TP_ADDED); + } + else + { + SendSysMessage(LANG_COMMAND_TP_ADDEDERR); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleTeleDelCommand(const char * args) +{ + if (!*args) + return false; + + std::string name = args; + + if (!objmgr.DeleteGameTele(name)) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + + SendSysMessage(LANG_COMMAND_TP_DELETED); + return true; +} + +bool ChatHandler::HandleListAurasCommand (const char * /*args*/) +{ + Unit *unit = getSelectedUnit(); + if (!unit) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + char const* talentStr = GetTrinityString(LANG_TALENT); + char const* passiveStr = GetTrinityString(LANG_PASSIVE); + + Unit::AuraApplicationMap const& uAuras = unit->GetAppliedAuras(); + PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, uAuras.size()); + for (Unit::AuraApplicationMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr) + { + bool talent = GetTalentSpellCost(itr->second->GetBase()->GetId()) > 0; + + AuraApplication const * aurApp = itr->second; + Aura const * aura = aurApp->GetBase(); + char const* name = aura->GetSpellProto()->SpellName[GetSessionDbcLocale()]; + + if (m_session) + { + std::ostringstream ss_name; + ss_name << "|cffffffff|Hspell:" << aura->GetId() << "|h[" << name << "]|h|r"; + + PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, aura->GetId(), aurApp->GetEffectMask(), + aura->GetCharges(), aura->GetStackAmount(), aurApp->GetSlot(), + aura->GetDuration(), aura->GetMaxDuration(), + ss_name.str().c_str(), + (aura->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), + IS_PLAYER_GUID(aura->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(aura->GetCasterGUID())); + } + else + { + PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, aura->GetId(), aurApp->GetEffectMask(), + aura->GetCharges(), aura->GetStackAmount(), aurApp->GetSlot(), + aura->GetDuration(), aura->GetMaxDuration(), + name, + (aura->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), + IS_PLAYER_GUID(aura->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(aura->GetCasterGUID())); + } + } + for (uint16 i = 0; i < TOTAL_AURAS; ++i) + { + Unit::AuraEffectList const& uAuraList = unit->GetAuraEffectsByType(AuraType(i)); + if (uAuraList.empty()) continue; + PSendSysMessage(LANG_COMMAND_TARGET_LISTAURATYPE, uAuraList.size(), i); + for (Unit::AuraEffectList::const_iterator itr = uAuraList.begin(); itr != uAuraList.end(); ++itr) + { + //bool talent = GetTalentSpellCost((*itr)->GetId()) > 0; + + char const* name = (*itr)->GetSpellProto()->SpellName[GetSessionDbcLocale()]; + + std::ostringstream ss_name; + ss_name << "|cffffffff|Hspell:" << (*itr)->GetId() << "|h[" << name << "]|h|r"; + + PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), + (*itr)->GetAmount()); + } + } + return true; +} + +bool ChatHandler::HandleResetAchievementsCommand (const char * args) +{ + Player* target; + uint64 target_guid; + if (!extractPlayerTarget((char*)args,&target,&target_guid)) + return false; + + if (target) + target->GetAchievementMgr().Reset(); + else + AchievementMgr::DeleteFromDB(GUID_LOPART(target_guid)); + + return true; +} + +bool ChatHandler::HandleResetHonorCommand (const char * args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + target->SetUInt32Value(PLAYER_FIELD_KILLS, 0); + target->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0); + target->SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, 0); + target->SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); + target->SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); + target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL); + + return true; +} + +static bool HandleResetStatsOrLevelHelper(Player* player) +{ + ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(player->getClass()); + if (!cEntry) + { + sLog.outError("Class %u not found in DBC (Wrong DBC files?)",player->getClass()); + return false; + } + + uint8 powertype = cEntry->powerType; + + // reset m_form if no aura + if (!player->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT)) + player->m_form = FORM_NONE; + + player->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); + player->SetFloatValue(UNIT_FIELD_COMBATREACH, DEFAULT_COMBAT_REACH); + + player->setFactionForRace(player->getRace()); + + player->SetUInt32Value(UNIT_FIELD_BYTES_0, ((player->getRace()) | (player->getClass() << 8) | (player->getGender() << 16) | (powertype << 24))); + + // reset only if player not in some form; + if (player->m_form == FORM_NONE) + player->InitDisplayIds(); + + player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); + player->SetByteValue(UNIT_FIELD_BYTES_2, 3, player->m_form); + + player->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + + //-1 is default value + player->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); + + //player->SetUInt32Value(PLAYER_FIELD_BYTES, 0xEEE00000); + return true; +} + +bool ChatHandler::HandleResetLevelCommand(const char * args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + if (!HandleResetStatsOrLevelHelper(target)) + return false; + + // set starting level + uint32 start_level = target->getClass() != CLASS_DEATH_KNIGHT + ? sWorld.getConfig(CONFIG_START_PLAYER_LEVEL) + : sWorld.getConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); + + target->_ApplyAllLevelScaleItemMods(false); + + target->SetLevel(start_level); + target->InitRunes(); + target->InitStatsForLevel(true); + target->InitTaxiNodesForLevel(); + target->InitGlyphsForLevel(); + target->InitTalentForLevel(); + target->SetUInt32Value(PLAYER_XP,0); + + target->_ApplyAllLevelScaleItemMods(true); + + // reset level for pet + if (Pet* pet = target->GetPet()) + pet->SynchronizeLevelWithOwner(); + + return true; +} + +bool ChatHandler::HandleResetStatsCommand(const char * args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + if (!HandleResetStatsOrLevelHelper(target)) + return false; + + target->InitRunes(); + target->InitStatsForLevel(true); + target->InitTaxiNodesForLevel(); + target->InitGlyphsForLevel(); + target->InitTalentForLevel(); + + return true; +} + +bool ChatHandler::HandleResetSpellsCommand(const char * args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + if (target) + { + target->resetSpells(/* bool myClassOnly */); + + ChatHandler(target).SendSysMessage(LANG_RESET_SPELLS); + if (!m_session || m_session->GetPlayer() != target) + PSendSysMessage(LANG_RESET_SPELLS_ONLINE,GetNameLink(target).c_str()); + } + else + { + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",uint32(AT_LOGIN_RESET_SPELLS), GUID_LOPART(target_guid)); + PSendSysMessage(LANG_RESET_SPELLS_OFFLINE,target_name.c_str()); + } + + return true; +} + +bool ChatHandler::HandleResetTalentsCommand(const char * args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + { + // Try reset talents as Hunter Pet + Creature* creature = getSelectedCreature(); + if (!*args && creature && creature->isPet()) + { + Unit *owner = creature->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet *)creature)->IsPermanentPetFor(owner->ToPlayer())) + { + ((Pet *)creature)->resetTalents(true); + owner->ToPlayer()->SendTalentsInfoData(true); + + ChatHandler(owner->ToPlayer()).SendSysMessage(LANG_RESET_PET_TALENTS); + if (!m_session || m_session->GetPlayer() != owner->ToPlayer()) + PSendSysMessage(LANG_RESET_PET_TALENTS_ONLINE,GetNameLink(owner->ToPlayer()).c_str()); + } + return true; + } + + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (target) + { + target->resetTalents(true); + target->SendTalentsInfoData(false); + ChatHandler(target).SendSysMessage(LANG_RESET_TALENTS); + if (!m_session || m_session->GetPlayer() != target) + PSendSysMessage(LANG_RESET_TALENTS_ONLINE,GetNameLink(target).c_str()); + + Pet* pet = target->GetPet(); + Pet::resetTalentsForAllPetsOf(target,pet); + if (pet) + target->SendTalentsInfoData(true); + return true; + } + else if (target_guid) + { + uint32 at_flags = AT_LOGIN_NONE | AT_LOGIN_RESET_PET_TALENTS; + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",at_flags, GUID_LOPART(target_guid)); + std::string nameLink = playerLink(target_name); + PSendSysMessage(LANG_RESET_TALENTS_OFFLINE,nameLink.c_str()); + return true; + } + + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; +} + +bool ChatHandler::HandleResetAllCommand(const char * args) +{ + if (!*args) + return false; + + std::string casename = args; + + AtLoginFlags atLogin; + + // Command specially created as single command to prevent using short case names + if (casename == "spells") + { + atLogin = AT_LOGIN_RESET_SPELLS; + sWorld.SendWorldText(LANG_RESETALL_SPELLS); + if (!m_session) + SendSysMessage(LANG_RESETALL_SPELLS); + } + else if (casename == "talents") + { + atLogin = AtLoginFlags(AT_LOGIN_RESET_TALENTS | AT_LOGIN_RESET_PET_TALENTS); + sWorld.SendWorldText(LANG_RESETALL_TALENTS); + if (!m_session) + SendSysMessage(LANG_RESETALL_TALENTS); + } + else + { + PSendSysMessage(LANG_RESETALL_UNKNOWN_CASE,args); + SetSentErrorMessage(true); + return false; + } + + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE (at_login & '%u') = '0'",atLogin,atLogin); + + ObjectAccessor::Guard guard(*HashMapHolder<Player>::GetLock()); + HashMapHolder<Player>::MapType const& plist = ObjectAccessor::Instance().GetPlayers(); + for (HashMapHolder<Player>::MapType::const_iterator itr = plist.begin(); itr != plist.end(); ++itr) + itr->second->SetAtLoginFlag(atLogin); + + return true; +} + +bool ChatHandler::HandleServerShutDownCancelCommand(const char* /*args*/) +{ + sWorld.ShutdownCancel(); + return true; +} + +bool ChatHandler::HandleServerShutDownCommand(const char *args) +{ + if (!*args) + return false; + + char* time_str = strtok ((char*) args, " "); + char* exitcode_str = strtok (NULL, ""); + + int32 time = atoi (time_str); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0')) || time < 0) + return false; + + if (exitcode_str) + { + int32 exitcode = atoi (exitcode_str); + + // Handle atoi() errors + if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitcode < 0 || exitcode > 125) + return false; + + sWorld.ShutdownServ (time, 0, exitcode); + } + else + sWorld.ShutdownServ(time,0,SHUTDOWN_EXIT_CODE); + return true; +} + +bool ChatHandler::HandleServerRestartCommand(const char *args) +{ + if (!*args) + return false; + + char* time_str = strtok ((char*) args, " "); + char* exitcode_str = strtok (NULL, ""); + + int32 time = atoi (time_str); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0') || time < 0)) + return false; + + if (exitcode_str) + { + int32 exitcode = atoi (exitcode_str); + + // Handle atoi() errors + if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitcode < 0 || exitcode > 125) + return false; + + sWorld.ShutdownServ (time, SHUTDOWN_MASK_RESTART, exitcode); + } + else + sWorld.ShutdownServ(time, SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE); + return true; +} + +bool ChatHandler::HandleServerIdleRestartCommand(const char *args) +{ + if (!*args) + return false; + + char* time_str = strtok ((char*) args, " "); + char* exitcode_str = strtok (NULL, ""); + + int32 time = atoi (time_str); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0') || time < 0)) + return false; + + if (exitcode_str) + { + int32 exitcode = atoi (exitcode_str); + + // Handle atoi() errors + if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitcode < 0 || exitcode > 125) + return false; + + sWorld.ShutdownServ (time, SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE, exitcode); + } + else + sWorld.ShutdownServ(time,SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE,RESTART_EXIT_CODE); + return true; +} + +bool ChatHandler::HandleServerIdleShutDownCommand(const char *args) +{ + if (!*args) + return false; + + char* time_str = strtok ((char*) args, " "); + char* exitcode_str = strtok (NULL, ""); + + int32 time = atoi (time_str); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if (time == 0 && (time_str[0] != '0' || time_str[1] != '\0') || time < 0) + return false; + + if (exitcode_str) + { + int32 exitcode = atoi (exitcode_str); + + // Handle atoi() errors + if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitcode < 0 || exitcode > 125) + return false; + + sWorld.ShutdownServ (time, SHUTDOWN_MASK_IDLE, exitcode); + } + else + sWorld.ShutdownServ(time,SHUTDOWN_MASK_IDLE,SHUTDOWN_EXIT_CODE); + return true; +} + +bool ChatHandler::HandleQuestAdd(const char *args) +{ + Player* player = getSelectedPlayer(); + if (!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // .addquest #entry' + // number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hquest"); + if (!cId) + return false; + + uint32 entry = atol(cId); + + Quest const* pQuest = objmgr.GetQuestTemplate(entry); + + if (!pQuest) + { + PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND,entry); + SetSentErrorMessage(true); + return false; + } + + // check item starting quest (it can work incorrectly if added without item in inventory) + for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) + { + ItemPrototype const *pProto = sItemStorage.LookupEntry<ItemPrototype>(id); + if (!pProto) + continue; + + if (pProto->StartQuest == entry) + { + PSendSysMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry, pProto->ItemId); + SetSentErrorMessage(true); + return false; + } + } + + // ok, normal (creature/GO starting) quest + if (player->CanAddQuest(pQuest, true)) + { + player->AddQuest(pQuest, NULL); + + if (player->CanCompleteQuest(entry)) + player->CompleteQuest(entry); + } + + return true; +} + +bool ChatHandler::HandleQuestRemove(const char *args) +{ + Player* player = getSelectedPlayer(); + if (!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // .removequest #entry' + // number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hquest"); + if (!cId) + return false; + + uint32 entry = atol(cId); + + Quest const* pQuest = objmgr.GetQuestTemplate(entry); + + if (!pQuest) + { + PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, entry); + SetSentErrorMessage(true); + return false; + } + + // remove all quest entries for 'entry' from quest log + for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot) + { + uint32 quest = player->GetQuestSlotQuestId(slot); + if (quest == entry) + { + player->SetQuestSlot(slot,0); + + // we ignore unequippable quest items in this case, its' still be equipped + player->TakeQuestSourceItem(quest, false); + } + } + + // set quest status to not started (will updated in DB at next save) + player->SetQuestStatus(entry, QUEST_STATUS_NONE); + + // reset rewarded for restart repeatable quest + player->getQuestStatusMap()[entry].m_rewarded = false; + + SendSysMessage(LANG_COMMAND_QUEST_REMOVED); + return true; +} + +bool ChatHandler::HandleQuestComplete(const char *args) +{ + Player* player = getSelectedPlayer(); + if (!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // .quest complete #entry + // number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hquest"); + if (!cId) + return false; + + uint32 entry = atol(cId); + + Quest const* pQuest = objmgr.GetQuestTemplate(entry); + + // If player doesn't have the quest + if (!pQuest || player->GetQuestStatus(entry) == QUEST_STATUS_NONE) + { + PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, entry); + SetSentErrorMessage(true); + return false; + } + + // Add quest items for quests that require items + for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x) + { + uint32 id = pQuest->ReqItemId[x]; + uint32 count = pQuest->ReqItemCount[x]; + if (!id || !count) + continue; + + uint32 curItemCount = player->GetItemCount(id,true); + + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count-curItemCount); + if (msg == EQUIP_ERR_OK) + { + Item* item = player->StoreNewItem(dest, id, true); + player->SendNewItem(item,count-curItemCount,true,false); + } + } + + // All creature/GO slain/casted (not required, but otherwise it will display "Creature slain 0/10") + for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) + { + uint32 creature = pQuest->ReqCreatureOrGOId[i]; + uint32 creaturecount = pQuest->ReqCreatureOrGOCount[i]; + + if (uint32 spell_id = pQuest->ReqSpell[i]) + { + for (uint16 z = 0; z < creaturecount; ++z) + player->CastedCreatureOrGO(creature,0,spell_id); + } + else if (creature > 0) + { + if (CreatureInfo const* cInfo = objmgr.GetCreatureTemplate(creature)) + for (uint16 z = 0; z < creaturecount; ++z) + player->KilledMonster(cInfo,0); + } + else if (creature < 0) + { + for (uint16 z = 0; z < creaturecount; ++z) + player->CastedCreatureOrGO(creature,0,0); + } + } + + // If the quest requires reputation to complete + if (uint32 repFaction = pQuest->GetRepObjectiveFaction()) + { + uint32 repValue = pQuest->GetRepObjectiveValue(); + uint32 curRep = player->GetReputationMgr().GetReputation(repFaction); + if (curRep < repValue) + if (FactionEntry const *factionEntry = sFactionStore.LookupEntry(repFaction)) + player->GetReputationMgr().SetReputation(factionEntry,repValue); + } + + // If the quest requires a SECOND reputation to complete + if (uint32 repFaction = pQuest->GetRepObjectiveFaction2()) + { + uint32 repValue2 = pQuest->GetRepObjectiveValue2(); + uint32 curRep = player->GetReputationMgr().GetReputation(repFaction); + if (curRep < repValue2) + if (FactionEntry const *factionEntry = sFactionStore.LookupEntry(repFaction)) + player->GetReputationMgr().SetReputation(factionEntry,repValue2); + } + + // If the quest requires money + int32 ReqOrRewMoney = pQuest->GetRewOrReqMoney(); + if (ReqOrRewMoney < 0) + player->ModifyMoney(-ReqOrRewMoney); + + player->CompleteQuest(entry); + return true; +} + +bool ChatHandler::HandleBanAccountCommand(const char *args) +{ + return HandleBanHelper(BAN_ACCOUNT,args); +} + +bool ChatHandler::HandleBanCharacterCommand(const char *args) +{ + return HandleBanHelper(BAN_CHARACTER,args); +} + +bool ChatHandler::HandleBanIPCommand(const char *args) +{ + return HandleBanHelper(BAN_IP,args); +} + +bool ChatHandler::HandleBanHelper(BanMode mode, const char *args) +{ + if (!*args) + return false; + + char* cnameOrIP = strtok ((char*)args, " "); + if (!cnameOrIP) + return false; + + std::string nameOrIP = cnameOrIP; + + char* duration = strtok (NULL," "); + if (!duration || !atoi(duration)) + return false; + + char* reason = strtok (NULL,""); + if (!reason) + return false; + + switch(mode) + { + case BAN_ACCOUNT: + if (!AccountMgr::normalizeString(nameOrIP)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,nameOrIP.c_str()); + SetSentErrorMessage(true); + return false; + } + break; + case BAN_CHARACTER: + if (!normalizePlayerName(nameOrIP)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + break; + case BAN_IP: + if (!IsIPAddress(nameOrIP.c_str())) + return false; + break; + } + + switch(sWorld.BanAccount(mode, nameOrIP, duration, reason,m_session ? m_session->GetPlayerName() : "")) + { + case BAN_SUCCESS: + if (atoi(duration)>0) + PSendSysMessage(LANG_BAN_YOUBANNED,nameOrIP.c_str(),secsToTimeString(TimeStringToSecs(duration),true).c_str(),reason); + else + PSendSysMessage(LANG_BAN_YOUPERMBANNED,nameOrIP.c_str(),reason); + break; + case BAN_SYNTAX_ERROR: + return false; + case BAN_NOTFOUND: + switch(mode) + { + default: + PSendSysMessage(LANG_BAN_NOTFOUND,"account",nameOrIP.c_str()); + break; + case BAN_CHARACTER: + PSendSysMessage(LANG_BAN_NOTFOUND,"character",nameOrIP.c_str()); + break; + case BAN_IP: + PSendSysMessage(LANG_BAN_NOTFOUND,"ip",nameOrIP.c_str()); + break; + } + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleUnBanAccountCommand(const char *args) +{ + return HandleUnBanHelper(BAN_ACCOUNT,args); +} + +bool ChatHandler::HandleUnBanCharacterCommand(const char *args) +{ + return HandleUnBanHelper(BAN_CHARACTER,args); +} + +bool ChatHandler::HandleUnBanIPCommand(const char *args) +{ + return HandleUnBanHelper(BAN_IP,args); +} + +bool ChatHandler::HandleUnBanHelper(BanMode mode, const char *args) +{ + if (!*args) + return false; + + char* cnameOrIP = strtok ((char*)args, " "); + if (!cnameOrIP) + return false; + + std::string nameOrIP = cnameOrIP; + + switch(mode) + { + case BAN_ACCOUNT: + if (!AccountMgr::normalizeString(nameOrIP)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,nameOrIP.c_str()); + SetSentErrorMessage(true); + return false; + } + break; + case BAN_CHARACTER: + if (!normalizePlayerName(nameOrIP)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + break; + case BAN_IP: + if (!IsIPAddress(nameOrIP.c_str())) + return false; + break; + } + + if (sWorld.RemoveBanAccount(mode,nameOrIP)) + PSendSysMessage(LANG_UNBAN_UNBANNED,nameOrIP.c_str()); + else + PSendSysMessage(LANG_UNBAN_ERROR,nameOrIP.c_str()); + + return true; +} + +bool ChatHandler::HandleBanInfoAccountCommand(const char *args) +{ + if (!*args) + return false; + + char* cname = strtok((char*)args, ""); + if (!cname) + return false; + + std::string account_name = cname; + if (!AccountMgr::normalizeString(account_name)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + uint32 accountid = accmgr.GetId(account_name); + if (!accountid) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + return true; + } + + return HandleBanInfoHelper(accountid,account_name.c_str()); +} + +bool ChatHandler::HandleBanInfoCharacterCommand(const char *args) +{ + Player* target; + uint64 target_guid; + if (!extractPlayerTarget((char*)args,&target,&target_guid)) + return false; + + uint32 accountid = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid); + + std::string accountname; + if (!accmgr.GetName(accountid,accountname)) + { + PSendSysMessage(LANG_BANINFO_NOCHARACTER); + return true; + } + + return HandleBanInfoHelper(accountid,accountname.c_str()); +} + +bool ChatHandler::HandleBanInfoHelper(uint32 accountid, char const* accountname) +{ + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate,banreason,bannedby FROM account_banned WHERE id = '%u' ORDER BY bandate ASC",accountid); + if (!result) + { + PSendSysMessage(LANG_BANINFO_NOACCOUNTBAN, accountname); + return true; + } + + PSendSysMessage(LANG_BANINFO_BANHISTORY,accountname); + do + { + Field* fields = result->Fetch(); + + time_t unbandate = time_t(fields[3].GetUInt64()); + bool active = false; + if (fields[2].GetBool() && (fields[1].GetUInt64() == (uint64)0 ||unbandate >= time(NULL))) + active = true; + bool permanent = (fields[1].GetUInt64() == (uint64)0); + std::string bantime = permanent?GetTrinityString(LANG_BANINFO_INFINITE):secsToTimeString(fields[1].GetUInt64(), true); + PSendSysMessage(LANG_BANINFO_HISTORYENTRY, + fields[0].GetString(), bantime.c_str(), active ? GetTrinityString(LANG_BANINFO_YES):GetTrinityString(LANG_BANINFO_NO), fields[4].GetString(), fields[5].GetString()); + }while (result->NextRow()); + + return true; +} + +bool ChatHandler::HandleBanInfoIPCommand(const char *args) +{ + if (!*args) + return false; + + char* cIP = strtok ((char*)args, ""); + if (!cIP) + return false; + + if (!IsIPAddress(cIP)) + return false; + + std::string IP = cIP; + + LoginDatabase.escape_string(IP); + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT ip, FROM_UNIXTIME(bandate), FROM_UNIXTIME(unbandate), unbandate-UNIX_TIMESTAMP(), banreason,bannedby,unbandate-bandate FROM ip_banned WHERE ip = '%s'",IP.c_str()); + if (!result) + { + PSendSysMessage(LANG_BANINFO_NOIP); + return true; + } + + Field *fields = result->Fetch(); + bool permanent = !fields[6].GetUInt64(); + PSendSysMessage(LANG_BANINFO_IPENTRY, + fields[0].GetString(), fields[1].GetString(), permanent ? GetTrinityString(LANG_BANINFO_NEVER):fields[2].GetString(), + permanent ? GetTrinityString(LANG_BANINFO_INFINITE):secsToTimeString(fields[3].GetUInt64(), true).c_str(), fields[4].GetString(), fields[5].GetString()); + + return true; +} + +bool ChatHandler::HandleBanListCharacterCommand(const char *args) +{ + LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); + + char* cFilter = strtok ((char*)args, " "); + if (!cFilter) + return false; + + std::string filter = cFilter; + LoginDatabase.escape_string(filter); + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),filter.c_str()); + if (!result) + { + PSendSysMessage(LANG_BANLIST_NOCHARACTER); + return true; + } + + return HandleBanListHelper(result); +} + +bool ChatHandler::HandleBanListAccountCommand(const char *args) +{ + LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); + + char* cFilter = strtok((char*)args, " "); + std::string filter = cFilter ? cFilter : ""; + LoginDatabase.escape_string(filter); + + QueryResult_AutoPtr result; + + if (filter.empty()) + { + result = LoginDatabase.Query("SELECT account.id, username FROM account, account_banned" + " WHERE account.id = account_banned.id AND active = 1 GROUP BY account.id"); + } + else + { + result = LoginDatabase.PQuery("SELECT account.id, username FROM account, account_banned" + " WHERE account.id = account_banned.id AND active = 1 AND username "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" GROUP BY account.id", + filter.c_str()); + } + + if (!result) + { + PSendSysMessage(LANG_BANLIST_NOACCOUNT); + return true; + } + + return HandleBanListHelper(result); +} + +bool ChatHandler::HandleBanListHelper(QueryResult_AutoPtr result) +{ + PSendSysMessage(LANG_BANLIST_MATCHINGACCOUNT); + + // Chat short output + if (m_session) + { + do + { + Field* fields = result->Fetch(); + uint32 accountid = fields[0].GetUInt32(); + + QueryResult_AutoPtr banresult = LoginDatabase.PQuery("SELECT account.username FROM account,account_banned WHERE account_banned.id='%u' AND account_banned.id=account.id",accountid); + if (banresult) + { + Field* fields2 = banresult->Fetch(); + PSendSysMessage("%s",fields2[0].GetString()); + } + } while (result->NextRow()); + } + // Console wide output + else + { + SendSysMessage(LANG_BANLIST_ACCOUNTS); + SendSysMessage(" ==============================================================================="); + SendSysMessage(LANG_BANLIST_ACCOUNTS_HEADER); + do + { + SendSysMessage("-------------------------------------------------------------------------------"); + Field *fields = result->Fetch(); + uint32 account_id = fields[0].GetUInt32 (); + + std::string account_name; + + // "account" case, name can be get in same query + if (result->GetFieldCount() > 1) + account_name = fields[1].GetCppString(); + // "character" case, name need extract from another DB + else + accmgr.GetName (account_id,account_name); + + // No SQL injection. id is uint32. + QueryResult_AutoPtr banInfo = LoginDatabase.PQuery("SELECT bandate,unbandate,bannedby,banreason FROM account_banned WHERE id = %u ORDER BY unbandate", account_id); + if (banInfo) + { + Field *fields2 = banInfo->Fetch(); + do + { + time_t t_ban = fields2[0].GetUInt64(); + tm* aTm_ban = localtime(&t_ban); + + if (fields2[0].GetUInt64() == fields2[1].GetUInt64()) + { + PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", + account_name.c_str(),aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, + fields2[2].GetString(),fields2[3].GetString()); + } + else + { + time_t t_unban = fields2[1].GetUInt64(); + tm* aTm_unban = localtime(&t_unban); + PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", + account_name.c_str(),aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, + aTm_unban->tm_year%100, aTm_unban->tm_mon+1, aTm_unban->tm_mday, aTm_unban->tm_hour, aTm_unban->tm_min, + fields2[2].GetString(),fields2[3].GetString()); + } + }while (banInfo->NextRow()); + } + }while (result->NextRow()); + SendSysMessage(" ==============================================================================="); + } + return true; +} + +bool ChatHandler::HandleBanListIPCommand(const char *args) +{ + LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); + + char* cFilter = strtok((char*)args, " "); + std::string filter = cFilter ? cFilter : ""; + LoginDatabase.escape_string(filter); + + QueryResult_AutoPtr result; + + if (filter.empty()) + { + result = LoginDatabase.Query ("SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned" + " WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP())" + " ORDER BY unbandate"); + } + else + { + result = LoginDatabase.PQuery("SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned" + " WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP()) AND ip "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'") + " ORDER BY unbandate",filter.c_str()); + } + + if (!result) + { + PSendSysMessage(LANG_BANLIST_NOIP); + return true; + } + + PSendSysMessage(LANG_BANLIST_MATCHINGIP); + // Chat short output + if (m_session) + { + do + { + Field* fields = result->Fetch(); + PSendSysMessage("%s",fields[0].GetString()); + } while (result->NextRow()); + } + // Console wide output + else + { + SendSysMessage(LANG_BANLIST_IPS); + SendSysMessage(" ==============================================================================="); + SendSysMessage(LANG_BANLIST_IPS_HEADER); + do + { + SendSysMessage("-------------------------------------------------------------------------------"); + Field *fields = result->Fetch(); + time_t t_ban = fields[1].GetUInt64(); + tm* aTm_ban = localtime(&t_ban); + if (fields[1].GetUInt64() == fields[2].GetUInt64()) + { + PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", + fields[0].GetString(), aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, + fields[3].GetString(), fields[4].GetString()); + } + else + { + time_t t_unban = fields[2].GetUInt64(); + tm* aTm_unban = localtime(&t_unban); + PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", + fields[0].GetString(), aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, + aTm_unban->tm_year%100, aTm_unban->tm_mon+1, aTm_unban->tm_mday, aTm_unban->tm_hour, aTm_unban->tm_min, + fields[3].GetString(), fields[4].GetString()); + } + }while (result->NextRow()); + SendSysMessage(" ==============================================================================="); + } + + return true; +} + +bool ChatHandler::HandleRespawnCommand(const char* /*args*/) +{ + Player* pl = m_session->GetPlayer(); + + // accept only explicitly selected target (not implicitly self targeting case) + Unit* target = getSelectedUnit(); + if (pl->GetSelection() && target) + { + if (target->GetTypeId() != TYPEID_UNIT || target->isPet()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (target->isDead()) + target->ToCreature()->Respawn(); + return true; + } + + CellPair p(Trinity::ComputeCellPair(pl->GetPositionX(), pl->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::RespawnDo u_do; + Trinity::WorldObjectWorker<Trinity::RespawnDo> worker(pl,u_do); + + TypeContainerVisitor<Trinity::WorldObjectWorker<Trinity::RespawnDo>, GridTypeMapContainer > obj_worker(worker); + cell.Visit(p, obj_worker, *pl->GetMap()); + + return true; +} + +bool ChatHandler::HandleGMFlyCommand(const char *args) +{ + if (!*args) + return false; + + Player *target = getSelectedPlayer(); + if (!target) + target = m_session->GetPlayer(); + + WorldPacket data(12); + if (strncmp(args, "on", 3) == 0) + data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); + else if (strncmp(args, "off", 4) == 0) + data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); + else + { + SendSysMessage(LANG_USE_BOL); + return false; + } + data.append(target->GetPackGUID()); + data << uint32(0); // unknown + target->SendMessageToSet(&data, true); + PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, GetNameLink(target).c_str(), args); + return true; +} + +bool ChatHandler::HandlePDumpLoadCommand(const char *args) +{ + if (!*args) + return false; + + char * file = strtok((char*)args, " "); + if (!file) + return false; + + char * account = strtok(NULL, " "); + if (!account) + return false; + + std::string account_name = account; + if (!AccountMgr::normalizeString(account_name)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + uint32 account_id = accmgr.GetId(account_name); + if (!account_id) + { + account_id = atoi(account); // use original string + if (!account_id) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + if (!accmgr.GetName(account_id,account_name)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + char* guid_str = NULL; + char* name_str = strtok(NULL, " "); + + std::string name; + if (name_str) + { + name = name_str; + // normalize the name if specified and check if it exists + if (!normalizePlayerName(name)) + { + PSendSysMessage(LANG_INVALID_CHARACTER_NAME); + SetSentErrorMessage(true); + return false; + } + + if (ObjectMgr::CheckPlayerName(name,true) != CHAR_NAME_SUCCESS) + { + PSendSysMessage(LANG_INVALID_CHARACTER_NAME); + SetSentErrorMessage(true); + return false; + } + + guid_str = strtok(NULL, " "); + } + + uint32 guid = 0; + + if (guid_str) + { + guid = atoi(guid_str); + if (!guid) + { + PSendSysMessage(LANG_INVALID_CHARACTER_GUID); + SetSentErrorMessage(true); + return false; + } + + if (objmgr.GetPlayerAccountIdByGUID(guid)) + { + PSendSysMessage(LANG_CHARACTER_GUID_IN_USE,guid); + SetSentErrorMessage(true); + return false; + } + } + + switch(PlayerDumpReader().LoadDump(file, account_id, name, guid)) + { + case DUMP_SUCCESS: + PSendSysMessage(LANG_COMMAND_IMPORT_SUCCESS); + break; + case DUMP_FILE_OPEN_ERROR: + PSendSysMessage(LANG_FILE_OPEN_FAIL,file); + SetSentErrorMessage(true); + return false; + case DUMP_FILE_BROKEN: + PSendSysMessage(LANG_DUMP_BROKEN,file); + SetSentErrorMessage(true); + return false; + case DUMP_TOO_MANY_CHARS: + PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL,account_name.c_str(),account_id); + SetSentErrorMessage(true); + return false; + default: + PSendSysMessage(LANG_COMMAND_IMPORT_FAILED); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandlePDumpWriteCommand(const char *args) +{ + if (!*args) + return false; + + char* file = strtok((char*)args, " "); + char* p2 = strtok(NULL, " "); + + if (!file || !p2) + return false; + + uint32 guid; + // character name can't start from number + if (isNumeric(p2[0])) + guid = atoi(p2); + else + { + std::string name = extractPlayerNameFromLink(p2); + if (name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + guid = objmgr.GetPlayerGUIDByName(name); + } + + if (!objmgr.GetPlayerAccountIdByGUID(guid)) + { + PSendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + switch(PlayerDumpWriter().WriteDump(file, guid)) + { + case DUMP_SUCCESS: + PSendSysMessage(LANG_COMMAND_EXPORT_SUCCESS); + break; + case DUMP_FILE_OPEN_ERROR: + PSendSysMessage(LANG_FILE_OPEN_FAIL,file); + SetSentErrorMessage(true); + return false; + default: + PSendSysMessage(LANG_COMMAND_EXPORT_FAILED); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleMovegensCommand(const char* /*args*/) +{ + Unit* unit = getSelectedUnit(); + if (!unit) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_MOVEGENS_LIST,(unit->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"),unit->GetGUIDLow()); + + MotionMaster* mm = unit->GetMotionMaster(); + for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i) + { + MovementGenerator* mg = mm->GetMotionSlot(i); + if (!mg) + { + SendSysMessage("Empty"); + continue; + } + switch(mg->GetMovementGeneratorType()) + { + case IDLE_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_IDLE); break; + case RANDOM_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_RANDOM); break; + case WAYPOINT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_WAYPOINT); break; + case ANIMAL_RANDOM_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_ANIMAL_RANDOM); break; + case CONFUSED_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_CONFUSED); break; + case TARGETED_MOTION_TYPE: + { + if (unit->GetTypeId() == TYPEID_PLAYER) + { + TargetedMovementGenerator<Player> const* mgen = static_cast<TargetedMovementGenerator<Player> const*>(mg); + Unit* target = mgen->GetTarget(); + if (target) + PSendSysMessage(LANG_MOVEGENS_TARGETED_PLAYER,target->GetName(),target->GetGUIDLow()); + else + SendSysMessage(LANG_MOVEGENS_TARGETED_NULL); + } + else + { + TargetedMovementGenerator<Creature> const* mgen = static_cast<TargetedMovementGenerator<Creature> const*>(mg); + Unit* target = mgen->GetTarget(); + if (target) + PSendSysMessage(LANG_MOVEGENS_TARGETED_CREATURE,target->GetName(),target->GetGUIDLow()); + else + SendSysMessage(LANG_MOVEGENS_TARGETED_NULL); + } + break; + } + case HOME_MOTION_TYPE: + if (unit->GetTypeId() == TYPEID_UNIT) + { + float x,y,z; + mg->GetDestination(x,y,z); + PSendSysMessage(LANG_MOVEGENS_HOME_CREATURE,x,y,z); + } + else + SendSysMessage(LANG_MOVEGENS_HOME_PLAYER); + break; + case FLIGHT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_FLIGHT); break; + case POINT_MOTION_TYPE: + { + float x,y,z; + mg->GetDestination(x,y,z); + PSendSysMessage(LANG_MOVEGENS_POINT,x,y,z); + break; + } + case FLEEING_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_FEAR); break; + case DISTRACT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_DISTRACT); break; + default: + PSendSysMessage(LANG_MOVEGENS_UNKNOWN,mg->GetMovementGeneratorType()); + break; + } + } + return true; +} + +bool ChatHandler::HandleServerPLimitCommand(const char *args) +{ + if (*args) + { + char* param = strtok((char*)args, " "); + if (!param) + return false; + + int l = strlen(param); + + if (strncmp(param,"player",l) == 0) + sWorld.SetPlayerSecurityLimit(SEC_PLAYER); + else if (strncmp(param,"moderator",l) == 0) + sWorld.SetPlayerSecurityLimit(SEC_MODERATOR); + else if (strncmp(param,"gamemaster",l) == 0) + sWorld.SetPlayerSecurityLimit(SEC_GAMEMASTER); + else if (strncmp(param,"administrator",l) == 0) + sWorld.SetPlayerSecurityLimit(SEC_ADMINISTRATOR); + else if (strncmp(param,"reset",l) == 0) + sWorld.SetPlayerLimit(sConfig.GetIntDefault("PlayerLimit", DEFAULT_PLAYER_LIMIT)); + else + { + int val = atoi(param); + if (val < 0) + sWorld.SetPlayerSecurityLimit(AccountTypes(uint32(-val))); + else + sWorld.SetPlayerLimit(val); + } + + // kick all low security level players + if (sWorld.GetPlayerSecurityLimit() > SEC_PLAYER) + sWorld.KickAllLess(sWorld.GetPlayerSecurityLimit()); + } + + uint32 pLimit = sWorld.GetPlayerAmountLimit(); + AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit(); + char const* secName = ""; + switch(allowedAccountType) + { + case SEC_PLAYER: secName = "Player"; break; + case SEC_MODERATOR: secName = "Moderator"; break; + case SEC_GAMEMASTER: secName = "Gamemaster"; break; + case SEC_ADMINISTRATOR: secName = "Administrator"; break; + default: secName = "<unknown>"; break; + } + + PSendSysMessage("Player limits: amount %u, min. security level %s.",pLimit,secName); + + return true; +} + +bool ChatHandler::HandleCastCommand(const char *args) +{ + if (!*args) + return false; + + Unit* target = getSelectedUnit(); + + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if (!spell) + return false; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo) + { + PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + SetSentErrorMessage(true); + return false; + } + + if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + SetSentErrorMessage(true); + return false; + } + + char* trig_str = strtok(NULL, " "); + if (trig_str) + { + int l = strlen(trig_str); + if (strncmp(trig_str,"triggered",l) != 0) + return false; + } + + bool triggered = (trig_str != NULL); + + m_session->GetPlayer()->CastSpell(target,spell,triggered); + + return true; +} + +bool ChatHandler::HandleCastBackCommand(const char *args) +{ + Creature* caster = getSelectedCreature(); + + if (!caster) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if (!spell || !sSpellStore.LookupEntry(spell)) + { + PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + SetSentErrorMessage(true); + return false; + } + + char* trig_str = strtok(NULL, " "); + if (trig_str) + { + int l = strlen(trig_str); + if (strncmp(trig_str,"triggered",l) != 0) + return false; + } + + bool triggered = (trig_str != NULL); + + caster->SetFacingToObject(m_session->GetPlayer()); + + caster->CastSpell(m_session->GetPlayer(),spell,triggered); + + return true; +} + +bool ChatHandler::HandleCastDistCommand(const char *args) +{ + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if (!spell) + return false; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo) + { + PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + SetSentErrorMessage(true); + return false; + } + + if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + SetSentErrorMessage(true); + return false; + } + + char *distStr = strtok(NULL, " "); + + float dist = 0; + + if (distStr) + sscanf(distStr, "%f", &dist); + + char* trig_str = strtok(NULL, " "); + if (trig_str) + { + int l = strlen(trig_str); + if (strncmp(trig_str,"triggered",l) != 0) + return false; + } + + bool triggered = (trig_str != NULL); + + float x,y,z; + m_session->GetPlayer()->GetClosePoint(x,y,z,dist); + + m_session->GetPlayer()->CastSpell(x,y,z,spell,triggered); + return true; +} + +bool ChatHandler::HandleCastTargetCommand(const char *args) +{ + Creature* caster = getSelectedCreature(); + + if (!caster) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (!caster->getVictim()) + { + SendSysMessage(LANG_SELECTED_TARGET_NOT_HAVE_VICTIM); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if (!spell || !sSpellStore.LookupEntry(spell)) + { + PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + SetSentErrorMessage(true); + return false; + } + + char* trig_str = strtok(NULL, " "); + if (trig_str) + { + int l = strlen(trig_str); + if (strncmp(trig_str,"triggered",l) != 0) + return false; + } + + bool triggered = (trig_str != NULL); + + caster->SetFacingToObject(m_session->GetPlayer()); + + caster->CastSpell(caster->getVictim(),spell,triggered); + + return true; +} + +/* +ComeToMe command REQUIRED for 3rd party scripting library to have access to PointMovementGenerator +Without this function 3rd party scripting library will get linking errors (unresolved external) +when attempting to use the PointMovementGenerator +*/ +bool ChatHandler::HandleComeToMeCommand(const char *args) +{ + char* newFlagStr = strtok((char*)args, " "); + + if (!newFlagStr) + return false; + + uint32 newFlags = (uint32)strtoul(newFlagStr, NULL, 0); + + Creature* caster = getSelectedCreature(); + if (!caster) + { + m_session->GetPlayer()->SetUnitMovementFlags(newFlags); + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + caster->SetUnitMovementFlags(newFlags); + + Player* pl = m_session->GetPlayer(); + + caster->GetMotionMaster()->MovePoint(0, pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ()); + return true; +} + +bool ChatHandler::HandleCastSelfCommand(const char *args) +{ + if (!*args) + return false; + + Unit* target = getSelectedUnit(); + + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if (!spell) + return false; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo) + return false; + + if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + SetSentErrorMessage(true); + return false; + } + + target->CastSpell(target,spell,false); + + return true; +} + +std::string GetTimeString(uint32 time) +{ + uint16 days = time / DAY, hours = (time % DAY) / HOUR, minute = (time % HOUR) / MINUTE; + std::ostringstream ss; + if (days) ss << days << "d "; + if (hours) ss << hours << "h "; + ss << minute << "m"; + return ss.str(); +} + +bool ChatHandler::HandleInstanceListBindsCommand(const char* /*args*/) +{ + Player* player = getSelectedPlayer(); + if (!player) player = m_session->GetPlayer(); + uint32 counter = 0; + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i)); + for (Player::BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end(); ++itr) + { + InstanceSave *save = itr->second.save; + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + PSendSysMessage("map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); + counter++; + } + } + PSendSysMessage("player binds: %d", counter); + counter = 0; + Group *group = player->GetGroup(); + if (group) + { + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Group::BoundInstancesMap &binds = group->GetBoundInstances(Difficulty(i)); + for (Group::BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end(); ++itr) + { + InstanceSave *save = itr->second.save; + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + PSendSysMessage("map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); counter++; + } + } + } + PSendSysMessage("group binds: %d", counter); + + return true; +} + +bool ChatHandler::HandleInstanceUnbindCommand(const char *args) +{ + if (!*args) + return false; + + std::string cmd = args; + if (cmd == "all") + { + Player* player = getSelectedPlayer(); + if (!player) player = m_session->GetPlayer(); + uint32 counter = 0; + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i)); + for (Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) + { + if (itr->first != player->GetMapId()) + { + InstanceSave *save = itr->second.save; + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + PSendSysMessage("unbinding map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); + player->UnbindInstance(itr, Difficulty(i)); + counter++; + } + else + ++itr; + } + } + PSendSysMessage("instances unbound: %d", counter); + } + return true; +} + +bool ChatHandler::HandleInstanceStatsCommand(const char* /*args*/) +{ + PSendSysMessage("instances loaded: %d", MapManager::Instance().GetNumInstances()); + PSendSysMessage("players in instances: %d", MapManager::Instance().GetNumPlayersInInstances()); + PSendSysMessage("instance saves: %d", sInstanceSaveManager.GetNumInstanceSaves()); + PSendSysMessage("players bound: %d", sInstanceSaveManager.GetNumBoundPlayersTotal()); + PSendSysMessage("groups bound: %d", sInstanceSaveManager.GetNumBoundGroupsTotal()); + return true; +} + +bool ChatHandler::HandleInstanceSaveDataCommand(const char * /*args*/) +{ + Player* pl = m_session->GetPlayer(); + + Map* map = pl->GetMap(); + if (!map->IsDungeon()) + { + PSendSysMessage("Map is not a dungeon."); + SetSentErrorMessage(true); + return false; + } + + if (!((InstanceMap*)map)->GetInstanceData()) + { + PSendSysMessage("Map has no instance data."); + SetSentErrorMessage(true); + return false; + } + + ((InstanceMap*)map)->GetInstanceData()->SaveToDB(); + return true; +} + +bool ChatHandler::HandleInstanceOpenCommand(const char *args) +{ + return HandleInstanceOpenCloseCommand(args,true); +} + +bool ChatHandler::HandleInstanceCloseCommand(const char *args) +{ + return HandleInstanceOpenCloseCommand(args,false); +} + +bool ChatHandler::HandleInstanceOpenCloseCommand(const char *args,bool open) +{ + char *mapIdStr; + char *instanceModeStr; + extractOptFirstArg((char*)args,&mapIdStr,&instanceModeStr); + if (!mapIdStr || !instanceModeStr) + return false; + + uint32 mapid = atoi(mapIdStr); + + InstanceTemplate const* instance = objmgr.GetInstanceTemplate(mapid); + if (!instance) + { + PSendSysMessage("Invalid map id"); + SetSentErrorMessage(true); + return false; + } + + uint8 status = objmgr.GetAccessRequirement(instance->access_id)->status; + uint8 flag = 0; + + if (strcmp(instanceModeStr,"normal") || strcmp(instanceModeStr,"10normal")) + flag = DUNGEON_STATUSFLAG_NORMAL; + else if (strcmp(instanceModeStr,"heroic") || strcmp(instanceModeStr,"25normal")) + flag = DUNGEON_STATUSFLAG_HEROIC; + else if (strcmp(instanceModeStr,"10heroic")) + flag = RAID_STATUSFLAG_10MAN_HEROIC; + else if (strcmp(instanceModeStr,"25heroic")) + flag = RAID_STATUSFLAG_25MAN_HEROIC; + else + { + PSendSysMessage("Unrecognized difficulty string"); + SetSentErrorMessage(true); + return false; + } + if (open) + status |= flag; + else + status &= ~flag; + + WorldDatabase.PExecute("UPDATE access_requirement SET status = '%u' WHERE id = '%u'", status, instance->access_id); + PSendSysMessage("Instance status changed. Don't forget to reload access_requirement table"); + return true; +} + +/// Display the list of GMs +bool ChatHandler::HandleGMListFullCommand(const char* /*args*/) +{ + ///- Get the accounts with GM Level >0 + QueryResult_AutoPtr result = LoginDatabase.Query("SELECT a.username,aa.gmlevel FROM account a, account_access aa WHERE a.id=aa.id AND aa.gmlevel > 0"); + if (result) + { + SendSysMessage(LANG_GMLIST); + SendSysMessage(" ======================== "); + SendSysMessage(LANG_GMLIST_HEADER); + SendSysMessage(" ======================== "); + + ///- Circle through them. Display username and GM level + do + { + Field *fields = result->Fetch(); + PSendSysMessage("|%15s|%6s|", fields[0].GetString(),fields[1].GetString()); + }while (result->NextRow()); + + PSendSysMessage(" ======================== "); + } + else + PSendSysMessage(LANG_GMLIST_EMPTY); + return true; +} + +/// Define the 'Message of the day' for the realm +bool ChatHandler::HandleServerSetMotdCommand(const char *args) +{ + sWorld.SetMotd(args); + PSendSysMessage(LANG_MOTD_NEW, args); + return true; +} + +/// Set whether we accept new clients +bool ChatHandler::HandleServerSetClosedCommand(const char *args) +{ + std::string arg = args; + + if (strncmp(args, "on", 3) == 0) + { + SendSysMessage(LANG_WORLD_CLOSED); + sWorld.SetClosed(true); + return true; + } + else if (strncmp(args, "off", 4) == 0) + { + SendSysMessage(LANG_WORLD_OPENED); + sWorld.SetClosed(false); + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +/// Set/Unset the expansion level for an account +bool ChatHandler::HandleAccountSetAddonCommand(const char *args) +{ + ///- Get the command line arguments + char *szAcc = strtok((char*)args," "); + char *szExp = strtok(NULL," "); + + if (!szAcc) + return false; + + std::string account_name; + uint32 account_id; + + if (!szExp) + { + Player* player = getSelectedPlayer(); + if (!player) + return false; + + account_id = player->GetSession()->GetAccountId(); + accmgr.GetName(account_id,account_name); + szExp = szAcc; + } + else + { + ///- Convert Account name to Upper Format + account_name = szAcc; + if (!AccountMgr::normalizeString(account_name)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + account_id = accmgr.GetId(account_name); + if (!account_id) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + } + + // Let set addon state only for lesser (strong) security level + // or to self account + if (m_session && m_session->GetAccountId () != account_id && + HasLowerSecurityAccount (NULL,account_id,true)) + return false; + + int expansion = atoi(szExp); //get int anyway (0 if error) + if (expansion < 0 || expansion > sWorld.getConfig(CONFIG_EXPANSION)) + return false; + + // No SQL injection + LoginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE id = '%u'",expansion,account_id); + PSendSysMessage(LANG_ACCOUNT_SETADDON,account_name.c_str(),account_id,expansion); + return true; +} + +//Send items by mail +bool ChatHandler::HandleSendItemsCommand(const char *args) +{ + // format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] + Player* receiver; + uint64 receiver_guid; + std::string receiver_name; + if (!extractPlayerTarget((char*)args,&receiver,&receiver_guid,&receiver_name)) + return false; + + char* tail1 = strtok(NULL, ""); + if (!tail1) + return false; + + char* msgSubject = extractQuotedArg(tail1); + if (!msgSubject) + return false; + + char* tail2 = strtok(NULL, ""); + if (!tail2) + return false; + + char* msgText = extractQuotedArg(tail2); + if (!msgText) + return false; + + // msgSubject, msgText isn't NUL after prev. check + std::string subject = msgSubject; + std::string text = msgText; + + // extract items + typedef std::pair<uint32,uint32> ItemPair; + typedef std::list< ItemPair > ItemPairs; + ItemPairs items; + + // get all tail string + char* tail = strtok(NULL, ""); + + // get from tail next item str + while (char* itemStr = strtok(tail, " ")) + { + // and get new tail + tail = strtok(NULL, ""); + + // parse item str + char* itemIdStr = strtok(itemStr, ":"); + char* itemCountStr = strtok(NULL, " "); + + uint32 item_id = atoi(itemIdStr); + if (!item_id) + return false; + + ItemPrototype const* item_proto = objmgr.GetItemPrototype(item_id); + if (!item_proto) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + uint32 item_count = itemCountStr ? atoi(itemCountStr) : 1; + if (item_count < 1 || (item_proto->MaxCount > 0 && item_count > uint32(item_proto->MaxCount))) + { + PSendSysMessage(LANG_COMMAND_INVALID_ITEM_COUNT, item_count,item_id); + SetSentErrorMessage(true); + return false; + } + + while (item_count > item_proto->GetMaxStackSize()) + { + items.push_back(ItemPair(item_id,item_proto->GetMaxStackSize())); + item_count -= item_proto->GetMaxStackSize(); + } + + items.push_back(ItemPair(item_id,item_count)); + + if (items.size() > MAX_MAIL_ITEMS) + { + PSendSysMessage(LANG_COMMAND_MAIL_ITEMS_LIMIT, MAX_MAIL_ITEMS); + SetSentErrorMessage(true); + return false; + } + } + + // from console show not existed sender + MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + + // fill mail + MailDraft draft(subject, text); + + for (ItemPairs::const_iterator itr = items.begin(); itr != items.end(); ++itr) + { + if (Item* item = Item::CreateItem(itr->first,itr->second,m_session ? m_session->GetPlayer() : 0)) + { + item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted + draft.AddItem(item); + } + } + + draft.SendMailTo(MailReceiver(receiver,GUID_LOPART(receiver_guid)), sender); + + std::string nameLink = playerLink(receiver_name); + PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); + return true; +} + +///Send money by mail +bool ChatHandler::HandleSendMoneyCommand(const char *args) +{ + /// format: name "subject text" "mail text" money + + Player* receiver; + uint64 receiver_guid; + std::string receiver_name; + if (!extractPlayerTarget((char*)args,&receiver,&receiver_guid,&receiver_name)) + return false; + + char* tail1 = strtok(NULL, ""); + if (!tail1) + return false; + + char* msgSubject = extractQuotedArg(tail1); + if (!msgSubject) + return false; + + char* tail2 = strtok(NULL, ""); + if (!tail2) + return false; + + char* msgText = extractQuotedArg(tail2); + if (!msgText) + return false; + + char* money_str = strtok(NULL, ""); + int32 money = money_str ? atoi(money_str) : 0; + if (money <= 0) + return false; + + // msgSubject, msgText isn't NUL after prev. check + std::string subject = msgSubject; + std::string text = msgText; + + // from console show not existed sender + MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + + MailDraft(subject, text) + .AddMoney(money) + .SendMailTo(MailReceiver(receiver,GUID_LOPART(receiver_guid)),sender); + + std::string nameLink = playerLink(receiver_name); + PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); + return true; +} + +/// Send a message to a player in game +bool ChatHandler::HandleSendMessageCommand(const char *args) +{ + ///- Find the player + Player *rPlayer; + if (!extractPlayerTarget((char*)args, &rPlayer)) + return false; + + char* msg_str = strtok(NULL, ""); + if (!msg_str) + return false; + + ///- Check that he is not logging out. + if (rPlayer->GetSession()->isLogingOut()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + ///- Send the message + //Use SendAreaTriggerMessage for fastest delivery. + rPlayer->GetSession()->SendAreaTriggerMessage("%s", msg_str); + rPlayer->GetSession()->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); + + //Confirmation message + std::string nameLink = GetNameLink(rPlayer); + PSendSysMessage(LANG_SENDMESSAGE,nameLink.c_str(),msg_str); + return true; +} + +bool ChatHandler::HandleFlushArenaPointsCommand(const char * /*args*/) +{ + sBattleGroundMgr.DistributeArenaPoints(); + return true; +} + +bool ChatHandler::HandleModifyGenderCommand(const char *args) +{ + if (!*args) + return false; + + Player *player = getSelectedPlayer(); + + if (!player) + { + PSendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + PlayerInfo const* info = objmgr.GetPlayerInfo(player->getRace(), player->getClass()); + if (!info) + return false; + + char const* gender_str = (char*)args; + int gender_len = strlen(gender_str); + + Gender gender; + + if (!strncmp(gender_str, "male", gender_len)) // MALE + { + if (player->getGender() == GENDER_MALE) + return true; + + gender = GENDER_MALE; + } + else if (!strncmp(gender_str, "female", gender_len)) // FEMALE + { + if (player->getGender() == GENDER_FEMALE) + return true; + + gender = GENDER_FEMALE; + } + else + { + SendSysMessage(LANG_MUST_MALE_OR_FEMALE); + SetSentErrorMessage(true); + return false; + } + + // Set gender + player->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender); + player->SetByteValue(PLAYER_BYTES_3, 0, gender); + + // Change display ID + player->InitDisplayIds(); + + char const* gender_full = gender ? "female" : "male"; + + PSendSysMessage(LANG_YOU_CHANGE_GENDER, GetNameLink(player).c_str(), gender_full); + + if (needReportToTarget(player)) + ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full, GetNameLink().c_str()); + + return true; +} + +bool ChatHandler::HandleChannelSetPublic(const char *args) +{ + if (!*args) + return false; + std::string channel = strtok((char*)args, " "); + uint32 val = atoi((char*)args); + + if (val) + { + CharacterDatabase.PExecute("UPDATE channels SET m_public = 1 WHERE m_name LIKE '%s'", channel.c_str()); + val = 1; + } + else + { + CharacterDatabase.PExecute("UPDATE channels SET m_public = 0 WHERE m_name LIKE '%s'", channel.c_str()); + val = 0; + } + + PSendSysMessage(LANG_CHANNEL_PUBLIC_CHANGED, channel.c_str(), val); + + return true; +} + + +/*------------------------------------------ + *-------------TRINITY---------------------- + *-------------------------------------*/ + +bool ChatHandler::HandlePlayAllCommand(const char *args) +{ + if (!*args) + return false; + + uint32 soundId = atoi((char*)args); + + if (!sSoundEntriesStore.LookupEntry(soundId)) + { + PSendSysMessage(LANG_SOUND_NOT_EXIST, soundId); + SetSentErrorMessage(true); + return false; + } + + WorldPacket data(SMSG_PLAY_SOUND, 4); + data << uint32(soundId) << m_session->GetPlayer()->GetGUID(); + sWorld.SendGlobalMessage(&data); + + PSendSysMessage(LANG_COMMAND_PLAYED_TO_ALL, soundId); + return true; +} + +bool ChatHandler::HandleFreezeCommand(const char *args) +{ + std::string name; + Player *player; + char *TargetName = strtok((char*)args, " "); //get entered name + if (!TargetName) //if no name entered use target + { + player = getSelectedPlayer(); + if (player) //prevent crash with creature as target + { + name = player->GetName(); + normalizePlayerName(name); + } + } + else // if name entered + { + name = TargetName; + normalizePlayerName(name); + player = objmgr.GetPlayer(name.c_str()); //get player by name + } + + if (!player) + { + SendSysMessage(LANG_COMMAND_FREEZE_WRONG); + return true; + } + + if (player == m_session->GetPlayer()) + { + SendSysMessage(LANG_COMMAND_FREEZE_ERROR); + return true; + } + + //effect + if (player && player != m_session->GetPlayer()) + { + PSendSysMessage(LANG_COMMAND_FREEZE,name.c_str()); + + //stop combat + make player unattackable + duel stop + stop some spells + player->setFaction(35); + player->CombatStop(); + if (player->IsNonMeleeSpellCasted(true)) + player->InterruptNonMeleeSpells(true); + player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + player->SetUInt32Value(PLAYER_DUEL_TEAM, 1); + + //if player class = hunter || warlock remove pet if alive + if ((player->getClass() == CLASS_HUNTER) || (player->getClass() == CLASS_WARLOCK)) + { + if (Pet *pet = player->GetPet()) + { + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + // not let dismiss dead pet + if (pet && pet->isAlive()) + player->RemovePet(pet,PET_SAVE_NOT_IN_SLOT); + } + } + + //m_session->GetPlayer()->CastSpell(player,spellID,false); + if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(9454)) + Aura::TryCreate(spellInfo, player, player); + + //save player + player->SaveToDB(); + } + return true; +} + +bool ChatHandler::HandleUnFreezeCommand(const char *args) +{ + std::string name; + Player *player; + char *TargetName = strtok((char*)args, " "); //get entered name + if (!TargetName) //if no name entered use target + { + player = getSelectedPlayer(); + if (player) //prevent crash with creature as target + name = player->GetName(); + } + + else // if name entered + { + name = TargetName; + normalizePlayerName(name); + player = objmgr.GetPlayer(name.c_str()); //get player by name + } + + //effect + if (player) + { + PSendSysMessage(LANG_COMMAND_UNFREEZE,name.c_str()); + + //Reset player faction + allow combat + allow duels + player->setFactionForRace(player->getRace()); + player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + //allow movement and spells + player->RemoveAurasDueToSpell(9454); + + //save player + player->SaveToDB(); + } + + if (!player) + { + if (TargetName) + { + //check for offline players + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT characters.guid FROM characters WHERE characters.name = '%s'",name.c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_FREEZE_WRONG); + return true; + } + //if player found: delete his freeze aura + Field *fields=result->Fetch(); + uint64 pguid = fields[0].GetUInt64(); + + CharacterDatabase.PQuery("DELETE FROM character_aura WHERE character_aura.spell = 9454 AND character_aura.guid = '%u'",pguid); + PSendSysMessage(LANG_COMMAND_UNFREEZE,name.c_str()); + return true; + } + else + { + SendSysMessage(LANG_COMMAND_FREEZE_WRONG); + return true; + } + } + + return true; +} + +bool ChatHandler::HandleListFreezeCommand(const char * /*args*/) +{ + //Get names from DB + QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT characters.name FROM characters LEFT JOIN character_aura ON (characters.guid = character_aura.guid) WHERE character_aura.spell = 9454"); + if (!result) + { + SendSysMessage(LANG_COMMAND_NO_FROZEN_PLAYERS); + return true; + } + //Header of the names + PSendSysMessage(LANG_COMMAND_LIST_FREEZE); + + //Output of the results + do + { + Field *fields = result->Fetch(); + std::string fplayers = fields[0].GetCppString(); + PSendSysMessage(LANG_COMMAND_FROZEN_PLAYERS,fplayers.c_str()); + } while (result->NextRow()); + + return true; +} + +bool ChatHandler::HandleGroupLeaderCommand(const char *args) +{ + Player* plr = NULL; + Group* group = NULL; + uint64 guid = 0; + char* cname = strtok((char*)args, " "); + + if (GetPlayerGroupAndGUIDByName(cname, plr, group, guid)) + if (group && group->GetLeaderGUID() != guid) + group->ChangeLeader(guid); + + return true; +} + +bool ChatHandler::HandleGroupDisbandCommand(const char *args) +{ + Player* plr = NULL; + Group* group = NULL; + uint64 guid = 0; + char* cname = strtok((char*)args, " "); + + if (GetPlayerGroupAndGUIDByName(cname, plr, group, guid)) + if (group) + group->Disband(); + + return true; +} + +bool ChatHandler::HandleGroupRemoveCommand(const char *args) +{ + Player* plr = NULL; + Group* group = NULL; + uint64 guid = 0; + char* cname = strtok((char*)args, " "); + + if (GetPlayerGroupAndGUIDByName(cname, plr, group, guid, true)) + if (group) + group->RemoveMember(guid, 0); + + return true; +} + +bool ChatHandler::HandlePossessCommand(const char * /*args*/) +{ + Unit *pUnit = getSelectedUnit(); + if (!pUnit) + return false; + + m_session->GetPlayer()->CastSpell(pUnit, 530, true); + return true; +} + +bool ChatHandler::HandleUnPossessCommand(const char * /*args*/) +{ + Unit *pUnit = getSelectedUnit(); + if (!pUnit) + pUnit = m_session->GetPlayer(); + + pUnit->RemoveCharmAuras(); + + return true; +} + +bool ChatHandler::HandleBindSightCommand(const char * /*args*/) +{ + Unit *pUnit = getSelectedUnit(); + if (!pUnit) + return false; + + m_session->GetPlayer()->CastSpell(pUnit, 6277, true); + return true; +} + +bool ChatHandler::HandleUnbindSightCommand(const char * /*args*/) +{ + if (m_session->GetPlayer()->isPossessing()) + return false; + + m_session->GetPlayer()->StopCastingBindSight(); + return true; +} |
