From 830229ac6968296b213e87eedbf2cfd69ebba422 Mon Sep 17 00:00:00 2001 From: Antz Date: Thu, 21 May 2020 17:46:24 +0100 Subject: [PATCH] The Big Command Files Reorganization. Based on the work of @Elmsroth for MangosZero (#90) * Command reorg Co-authored-by: Elmsroth --- src/game/ChatCommands/AHBotCommands.cpp | 236 + src/game/ChatCommands/AccountCommands.cpp | 433 + .../ChatCommands/AuctionHouseCommands.cpp | 174 + src/game/ChatCommands/BanAndKickCommands.cpp | 569 ++ src/game/ChatCommands/CastAndAuraCommands.cpp | 324 + .../ChatCommands/CommunicationCommands.cpp | 383 + src/game/ChatCommands/CreatureCommands.cpp | 1212 +++ .../{debugcmds.cpp => DebugCommands.cpp} | 4 + src/game/ChatCommands/EventCommands.cpp | 220 + src/game/ChatCommands/GMCommands.cpp | 427 + src/game/ChatCommands/GMTicketCommands.cpp | 485 ++ src/game/ChatCommands/GameObjectCommands.cpp | 615 ++ src/game/ChatCommands/GuildCommands.cpp | 214 + src/game/ChatCommands/InstanceCommands.cpp | 185 + src/game/ChatCommands/Level0.cpp | 312 - src/game/ChatCommands/Level2.cpp | 5967 ------------- src/game/ChatCommands/Level3.cpp | 7697 ----------------- src/game/ChatCommands/Level4.cpp | 613 -- src/game/ChatCommands/ListCommands.cpp | 567 ++ src/game/ChatCommands/LookupCommands.cpp | 1246 +++ src/game/ChatCommands/MMapCommands.cpp | 409 + src/game/ChatCommands/MailCommands.cpp | 354 + .../ChatCommands/MiscellanousCommands.cpp | 265 + .../PlayerAndCreatureCommands.cpp | 336 + src/game/ChatCommands/PlayerCommands.cpp | 2412 ++++++ src/game/ChatCommands/PlayerHonorCommands.cpp | 152 + src/game/ChatCommands/PlayerLearnCommands.cpp | 1118 +++ src/game/ChatCommands/PlayerMiscCommands.cpp | 247 + src/game/ChatCommands/PlayerTitleCommands.cpp | 372 + src/game/ChatCommands/PoolCommands.cpp | 289 + src/game/ChatCommands/QuestCommands.cpp | 237 + src/game/ChatCommands/RACommands.cpp | 38 + src/game/ChatCommands/ReloadCommands.cpp | 938 ++ src/game/ChatCommands/ServerCommands.cpp | 436 + ...p => TeleportationAndPositionCommands.cpp} | 3076 +++---- src/game/ChatCommands/TriggerCommands.cpp | 314 + src/game/ChatCommands/WaypointCommands.cpp | 944 ++ src/game/ChatCommands/ZZZ_CustomCommands.cpp | 67 + src/game/WorldHandlers/Chat.cpp | 193 + src/game/WorldHandlers/Chat.h | 7 + 40 files changed, 17520 insertions(+), 16567 deletions(-) create mode 100644 src/game/ChatCommands/AHBotCommands.cpp create mode 100644 src/game/ChatCommands/AccountCommands.cpp create mode 100644 src/game/ChatCommands/AuctionHouseCommands.cpp create mode 100644 src/game/ChatCommands/BanAndKickCommands.cpp create mode 100644 src/game/ChatCommands/CastAndAuraCommands.cpp create mode 100644 src/game/ChatCommands/CommunicationCommands.cpp create mode 100644 src/game/ChatCommands/CreatureCommands.cpp rename src/game/ChatCommands/{debugcmds.cpp => DebugCommands.cpp} (99%) create mode 100644 src/game/ChatCommands/EventCommands.cpp create mode 100644 src/game/ChatCommands/GMCommands.cpp create mode 100644 src/game/ChatCommands/GMTicketCommands.cpp create mode 100644 src/game/ChatCommands/GameObjectCommands.cpp create mode 100644 src/game/ChatCommands/GuildCommands.cpp create mode 100644 src/game/ChatCommands/InstanceCommands.cpp delete mode 100644 src/game/ChatCommands/Level0.cpp delete mode 100644 src/game/ChatCommands/Level2.cpp delete mode 100644 src/game/ChatCommands/Level3.cpp delete mode 100644 src/game/ChatCommands/Level4.cpp create mode 100644 src/game/ChatCommands/ListCommands.cpp create mode 100644 src/game/ChatCommands/LookupCommands.cpp create mode 100644 src/game/ChatCommands/MMapCommands.cpp create mode 100644 src/game/ChatCommands/MailCommands.cpp create mode 100644 src/game/ChatCommands/MiscellanousCommands.cpp create mode 100644 src/game/ChatCommands/PlayerAndCreatureCommands.cpp create mode 100644 src/game/ChatCommands/PlayerCommands.cpp create mode 100644 src/game/ChatCommands/PlayerHonorCommands.cpp create mode 100644 src/game/ChatCommands/PlayerLearnCommands.cpp create mode 100644 src/game/ChatCommands/PlayerMiscCommands.cpp create mode 100644 src/game/ChatCommands/PlayerTitleCommands.cpp create mode 100644 src/game/ChatCommands/PoolCommands.cpp create mode 100644 src/game/ChatCommands/QuestCommands.cpp create mode 100644 src/game/ChatCommands/RACommands.cpp create mode 100644 src/game/ChatCommands/ReloadCommands.cpp create mode 100644 src/game/ChatCommands/ServerCommands.cpp rename src/game/ChatCommands/{Level1.cpp => TeleportationAndPositionCommands.cpp} (50%) create mode 100644 src/game/ChatCommands/TriggerCommands.cpp create mode 100644 src/game/ChatCommands/WaypointCommands.cpp create mode 100644 src/game/ChatCommands/ZZZ_CustomCommands.cpp diff --git a/src/game/ChatCommands/AHBotCommands.cpp b/src/game/ChatCommands/AHBotCommands.cpp new file mode 100644 index 0000000000000..d49ad4c65d238 --- /dev/null +++ b/src/game/ChatCommands/AHBotCommands.cpp @@ -0,0 +1,236 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + + /* + * AHBot related commands + */ + +#include "Chat.h" +#include "Language.h" +#include "AuctionHouseBot/AuctionHouseBot.h" + + + /********************************************************************** + Useful constants definition + /***********************************************************************/ + +static uint32 ahbotQualityIds[MAX_AUCTION_QUALITY] = +{ + LANG_AHBOT_QUALITY_GREY, LANG_AHBOT_QUALITY_WHITE, + LANG_AHBOT_QUALITY_GREEN, LANG_AHBOT_QUALITY_BLUE, + LANG_AHBOT_QUALITY_PURPLE, LANG_AHBOT_QUALITY_ORANGE, + LANG_AHBOT_QUALITY_YELLOW +}; + + /********************************************************************** + CommandTable : ahbotCommandTable + /***********************************************************************/ + +bool ChatHandler::HandleAHBotRebuildCommand(char* args) +{ + bool all = false; + if (*args) + { + if (!ExtractLiteralArg(&args, "all")) + { + return false; + } + all = true; + } + + sAuctionBot.Rebuild(all); + return true; +} + +bool ChatHandler::HandleAHBotReloadCommand(char* /*args*/) +{ + if (sAuctionBot.ReloadAllConfig()) + { + SendSysMessage(LANG_AHBOT_RELOAD_OK); + return true; + } + else + { + SendSysMessage(LANG_AHBOT_RELOAD_FAIL); + SetSentErrorMessage(true); + return false; + } +} + +bool ChatHandler::HandleAHBotStatusCommand(char* args) +{ + bool all = false; + if (*args) + { + if (!ExtractLiteralArg(&args, "all")) + { + return false; + } + all = true; + } + + AuctionHouseBotStatusInfo statusInfo; + sAuctionBot.PrepareStatusInfos(statusInfo); + + if (!m_session) + { + SendSysMessage(LANG_AHBOT_STATUS_BAR_CONSOLE); + SendSysMessage(LANG_AHBOT_STATUS_TITLE1_CONSOLE); + SendSysMessage(LANG_AHBOT_STATUS_MIDBAR_CONSOLE); + } + else + { + SendSysMessage(LANG_AHBOT_STATUS_TITLE1_CHAT); + } + + uint32 fmtId = m_session ? LANG_AHBOT_STATUS_FORMAT_CHAT : LANG_AHBOT_STATUS_FORMAT_CONSOLE; + + PSendSysMessage(fmtId, GetMangosString(LANG_AHBOT_STATUS_ITEM_COUNT), + statusInfo[AUCTION_HOUSE_ALLIANCE].ItemsCount, + statusInfo[AUCTION_HOUSE_HORDE].ItemsCount, + statusInfo[AUCTION_HOUSE_NEUTRAL].ItemsCount, + statusInfo[AUCTION_HOUSE_ALLIANCE].ItemsCount + + statusInfo[AUCTION_HOUSE_HORDE].ItemsCount + + statusInfo[AUCTION_HOUSE_NEUTRAL].ItemsCount); + + if (all) + { + PSendSysMessage(fmtId, GetMangosString(LANG_AHBOT_STATUS_ITEM_RATIO), + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO), + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_HORDE_ITEM_AMOUNT_RATIO), + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO), + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO) + + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_HORDE_ITEM_AMOUNT_RATIO) + + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO)); + + if (!m_session) + { + SendSysMessage(LANG_AHBOT_STATUS_BAR_CONSOLE); + SendSysMessage(LANG_AHBOT_STATUS_TITLE2_CONSOLE); + SendSysMessage(LANG_AHBOT_STATUS_MIDBAR_CONSOLE); + } + else + { + SendSysMessage(LANG_AHBOT_STATUS_TITLE2_CHAT); + } + + for (int i = 0; i < MAX_AUCTION_QUALITY; ++i) + PSendSysMessage(fmtId, GetMangosString(ahbotQualityIds[i]), + statusInfo[AUCTION_HOUSE_ALLIANCE].QualityInfo[i], + statusInfo[AUCTION_HOUSE_HORDE].QualityInfo[i], + statusInfo[AUCTION_HOUSE_NEUTRAL].QualityInfo[i], + sAuctionBotConfig.getConfigItemQualityAmount(AuctionQuality(i))); + } + + if (!m_session) + { + SendSysMessage(LANG_AHBOT_STATUS_BAR_CONSOLE); + } + + return true; +} + +/********************************************************************** + CommandTable : ahbotItemsAmountCommandTable +/***********************************************************************/ + +bool ChatHandler::HandleAHBotItemsAmountCommand(char* args) +{ + uint32 qVals[MAX_AUCTION_QUALITY]; + for (int i = 0; i < MAX_AUCTION_QUALITY; ++i) + if (!ExtractUInt32(&args, qVals[i])) + { + return false; + } + + sAuctionBot.SetItemsAmount(qVals); + + for (int i = 0; i < MAX_AUCTION_QUALITY; ++i) + { + PSendSysMessage(LANG_AHBOT_ITEMS_AMOUNT, GetMangosString(ahbotQualityIds[i]), sAuctionBotConfig.getConfigItemQualityAmount(AuctionQuality(i))); + } + + return true; +} + +template +bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char* args) +{ + uint32 qVal; + if (!ExtractUInt32(&args, qVal)) + { + return false; + } + sAuctionBot.SetItemsAmountForQuality(AuctionQuality(Q), qVal); + PSendSysMessage(LANG_AHBOT_ITEMS_AMOUNT, GetMangosString(ahbotQualityIds[Q]), + sAuctionBotConfig.getConfigItemQualityAmount(AuctionQuality(Q))); + return true; +} + +template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); +template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); +template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); +template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); +template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); +template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); +template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); + +/********************************************************************** + CommandTable : ahbotItemsRatioCommandTable +/***********************************************************************/ + +bool ChatHandler::HandleAHBotItemsRatioCommand(char* args) +{ + uint32 rVal[MAX_AUCTION_HOUSE_TYPE]; + for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i) + if (!ExtractUInt32(&args, rVal[i])) + { + return false; + } + + sAuctionBot.SetItemsRatio(rVal[0], rVal[1], rVal[2]); + + for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i) + { + PSendSysMessage(LANG_AHBOT_ITEMS_RATIO, AuctionBotConfig::GetHouseTypeName(AuctionHouseType(i)), sAuctionBotConfig.getConfigItemAmountRatio(AuctionHouseType(i))); + } + return true; +} + +template +bool ChatHandler::HandleAHBotItemsRatioHouseCommand(char* args) +{ + uint32 rVal; + if (!ExtractUInt32(&args, rVal)) + { + return false; + } + sAuctionBot.SetItemsRatioForHouse(AuctionHouseType(H), rVal); + PSendSysMessage(LANG_AHBOT_ITEMS_RATIO, AuctionBotConfig::GetHouseTypeName(AuctionHouseType(H)), sAuctionBotConfig.getConfigItemAmountRatio(AuctionHouseType(H))); + return true; +} + +template bool ChatHandler::HandleAHBotItemsRatioHouseCommand(char*); +template bool ChatHandler::HandleAHBotItemsRatioHouseCommand(char*); +template bool ChatHandler::HandleAHBotItemsRatioHouseCommand(char*); \ No newline at end of file diff --git a/src/game/ChatCommands/AccountCommands.cpp b/src/game/ChatCommands/AccountCommands.cpp new file mode 100644 index 0000000000000..777dc2a85bc6e --- /dev/null +++ b/src/game/ChatCommands/AccountCommands.cpp @@ -0,0 +1,433 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +/* +* Account related commands +*/ + +#include "World.h" +#include "Chat.h" +#include "Language.h" +#include "AccountMgr.h" + + +/********************************************************************** + CommandTable : accountCommandTable +/***********************************************************************/ + +bool ChatHandler::HandleAccountCommand(char* args) +{ + // let show subcommands at unexpected data in args + if (*args) + { + return false; + } + + AccountTypes gmlevel = GetAccessLevel(); + PSendSysMessage(LANG_ACCOUNT_LEVEL, uint32(gmlevel)); + return true; +} + +bool ChatHandler::HandleAccountPasswordCommand(char* args) +{ + // allow use from RA, but not from console (not have associated account id) + if (!GetAccountId()) + { + SendSysMessage(LANG_RA_ONLY_COMMAND); + SetSentErrorMessage(true); + return false; + } + + // allow or quoted string with possible spaces or literal without spaces + char* old_pass = ExtractQuotedOrLiteralArg(&args); + char* new_pass = ExtractQuotedOrLiteralArg(&args); + char* new_pass_c = ExtractQuotedOrLiteralArg(&args); + + 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 (password_new != password_new_c) + { + SendSysMessage(LANG_NEW_PASSWORDS_NOT_MATCH); + SetSentErrorMessage(true); + return false; + } + + if (!sAccountMgr.CheckPassword(GetAccountId(), password_old)) + { + SendSysMessage(LANG_COMMAND_WRONGOLDPASSWORD); + SetSentErrorMessage(true); + return false; + } + + AccountOpResult result = sAccountMgr.ChangePassword(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; + } + + // OK, but avoid normal report for hide passwords, but log use command for anyone + LogCommand(".account password *** *** ***"); + SetSentErrorMessage(true); + return false; +} + +bool ChatHandler::HandleAccountLockCommand(char* args) +{ + // allow use from RA, but not from console (not have associated account id) + if (!GetAccountId()) + { + SendSysMessage(LANG_RA_ONLY_COMMAND); + SetSentErrorMessage(true); + return false; + } + + bool value; + if (!ExtractOnOff(&args, value)) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + if (value) + { + LoginDatabase.PExecute("UPDATE `account` SET `locked` = '1' WHERE `id` = '%u'", GetAccountId()); + PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED); + } + else + { + LoginDatabase.PExecute("UPDATE `account` SET `locked` = '0' WHERE `id` = '%u'", GetAccountId()); + PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED); + } + + return true; +} + +/// Display info on users currently in the realm +bool ChatHandler::HandleAccountOnlineListCommand(char* args) +{ + uint32 limit; + if (!ExtractOptUInt32(&args, limit, 100)) + { + return false; + } + + ///- Get the list of accounts ID logged to the realm + // 0 1 2 3 4 + QueryResult* result = LoginDatabase.PQuery("SELECT `id`, `username`, `last_ip`, `gmlevel`, `expansion` FROM `account` WHERE `active_realm_id` = %u", realmID); + + return ShowAccountListHelper(result, &limit); +} + +/// Delete a user account and all associated characters in this realm +/// \todo This function has to be enhanced to respect the login/realm split (delete char, delete account chars in realm, delete account chars in realm then delete account +bool ChatHandler::HandleAccountDeleteCommand(char* args) +{ + if (!*args) + { + return false; + } + + std::string account_name; + uint32 account_id = ExtractAccountId(&args, &account_name); + if (!account_id) + { + return false; + } + + /// Commands not recommended call from chat, but support anyway + /// can delete only for account with less security + /// This is also reject self apply in fact + if (HasLowerSecurityAccount(NULL, account_id, true)) + { + return false; + } + + AccountOpResult result = sAccountMgr.DeleteAccount(account_id); + switch (result) + { + case AOR_OK: + PSendSysMessage(LANG_ACCOUNT_DELETED, account_name.c_str()); + break; + case AOR_NAME_NOT_EXIST: + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, account_name.c_str()); + SetSentErrorMessage(true); + return false; + case AOR_DB_INTERNAL_ERROR: + PSendSysMessage(LANG_ACCOUNT_NOT_DELETED_SQL_ERROR, account_name.c_str()); + SetSentErrorMessage(true); + return false; + default: + PSendSysMessage(LANG_ACCOUNT_NOT_DELETED, account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +/// Create an account +bool ChatHandler::HandleAccountCreateCommand(char* args) +{ + ///- %Parse the command line arguments + char* szAcc = ExtractQuotedOrLiteralArg(&args); + char* szPassword = ExtractQuotedOrLiteralArg(&args); + if (!szAcc || !szPassword) + { + return false; + } + + // normalized in accmgr.CreateAccount + std::string account_name = szAcc; + std::string password = szPassword; + + AccountOpResult result; + uint32 expansion = 0; + if(ExtractUInt32(&args, expansion)) + { + // No point in assigning to result as it's never used on this side of the if/else branch + sAccountMgr.CreateAccount(account_name, password, expansion); + } + else + { + result = sAccountMgr.CreateAccount(account_name, password); + switch (result) + { + case AOR_OK: + PSendSysMessage(LANG_ACCOUNT_CREATED, account_name.c_str()); + break; + case AOR_NAME_TOO_LONG: + SendSysMessage(LANG_ACCOUNT_TOO_LONG); + SetSentErrorMessage(true); + return false; + case AOR_NAME_ALREADY_EXIST: + SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST); + SetSentErrorMessage(true); + return false; + case AOR_DB_INTERNAL_ERROR: + PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR, account_name.c_str()); + SetSentErrorMessage(true); + return false; + default: + PSendSysMessage(LANG_ACCOUNT_NOT_CREATED, account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + } + return true; +} + +/// Output list of character for account +bool ChatHandler::HandleAccountCharactersCommand(char* args) +{ + ///- Get the command line arguments + std::string account_name; + Player* target = NULL; // only for triggering use targeted player account + uint32 account_id = ExtractAccountId(&args, &account_name, &target); + if (!account_id) + { + return false; + } + + ///- Get the characters for account id + QueryResult* result = CharacterDatabase.PQuery("SELECT `guid`, `name`, `race`, `class`, `level` FROM `characters` WHERE `account` = %u", account_id); + + return ShowPlayerListHelper(result); +} + +/********************************************************************** + CommandTable : accountSetCommandTable +/***********************************************************************/ + +/// Set/Unset the expansion level for an account +bool ChatHandler::HandleAccountSetAddonCommand(char* args) +{ + ///- Get the command line arguments + char* accountStr = ExtractOptNotLastArg(&args); + + std::string account_name; + uint32 account_id = ExtractAccountId(&accountStr, &account_name); + if (!account_id) + { + return false; + } + + // Let set addon state only for lesser (strong) security level + // or to self account + if (GetAccountId() && GetAccountId() != account_id && HasLowerSecurityAccount(NULL, account_id, true)) + { + return false; + } + + uint32 lev; + if (!ExtractUInt32(&args, lev)) + { + return false; + } + + // No SQL injection + LoginDatabase.PExecute("UPDATE `account` SET `expansion` = '%u' WHERE `id` = '%u'", lev, account_id); + PSendSysMessage(LANG_ACCOUNT_SETADDON, account_name.c_str(), account_id, lev); + return true; +} + +bool ChatHandler::HandleAccountSetGmLevelCommand(char* args) +{ + char* accountStr = ExtractOptNotLastArg(&args); + + std::string targetAccountName; + Player* targetPlayer = NULL; + uint32 targetAccountId = ExtractAccountId(&accountStr, &targetAccountName, &targetPlayer); + if (!targetAccountId) + { + return false; + } + + /// only target player different from self allowed + if (GetAccountId() == targetAccountId) + { + return false; + } + + int32 gm; + if (!ExtractInt32(&args, gm)) + { + return false; + } + + if (gm < SEC_PLAYER || gm > SEC_ADMINISTRATOR) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + /// can set security level only for target with less security and to less security that we have + /// This will reject self apply by specify account name + if (HasLowerSecurityAccount(NULL, targetAccountId, true)) + { + return false; + } + + /// account can't set security to same or grater level, need more power GM or console + AccountTypes plSecurity = GetAccessLevel(); + if (AccountTypes(gm) >= plSecurity) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + SetSentErrorMessage(true); + return false; + } + + if (targetPlayer) + { + ChatHandler(targetPlayer).PSendSysMessage(LANG_YOURS_SECURITY_CHANGED, GetNameLink().c_str(), gm); + targetPlayer->GetSession()->SetSecurity(AccountTypes(gm)); + } + + PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm); + LoginDatabase.PExecute("UPDATE `account` SET `gmlevel` = '%i' WHERE `id` = '%u'", gm, targetAccountId); + + return true; +} + +/// Set password for account +bool ChatHandler::HandleAccountSetPasswordCommand(char* args) +{ + ///- Get the command line arguments + std::string account_name; + uint32 targetAccountId = ExtractAccountId(&args, &account_name); + if (!targetAccountId) + { + return false; + } + + // allow or quoted string with possible spaces or literal without spaces + char* szPassword1 = ExtractQuotedOrLiteralArg(&args); + char* szPassword2 = ExtractQuotedOrLiteralArg(&args); + if (!szPassword1 || !szPassword2) + { + 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 = sAccountMgr.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; + } + + // OK, but avoid normal report for hide passwords, but log use command for anyone + char msg[100]; + snprintf(msg, 100, ".account set password %s *** ***", account_name.c_str()); + LogCommand(msg); + SetSentErrorMessage(true); + return false; +} diff --git a/src/game/ChatCommands/AuctionHouseCommands.cpp b/src/game/ChatCommands/AuctionHouseCommands.cpp new file mode 100644 index 0000000000000..1fd7c30b4e860 --- /dev/null +++ b/src/game/ChatCommands/AuctionHouseCommands.cpp @@ -0,0 +1,174 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" + + /********************************************************************** + CommandTable : auctionCommandTable + /***********************************************************************/ + +bool ChatHandler::HandleAuctionCommand(char* /*args*/) +{ + m_session->GetPlayer()->SetAuctionAccessMode(0); + m_session->SendAuctionHello(m_session->GetPlayer()); + + return true; +} + +bool ChatHandler::HandleAuctionItemCommand(char* args) +{ + // format: (alliance|horde|goblin) item[:count] price [buyout] [short|long|verylong] + char* typeStr = ExtractLiteralArg(&args); + if (!typeStr) + { + return false; + } + + uint32 houseid; + if (strncmp(typeStr, "alliance", strlen(typeStr)) == 0) + { + houseid = 1; + } + else if (strncmp(typeStr, "horde", strlen(typeStr)) == 0) + { + houseid = 6; + } + else if (strncmp(typeStr, "goblin", strlen(typeStr)) == 0) + { + houseid = 7; + } + else + { + return false; + } + + // parse item str + char* itemStr = ExtractArg(&args); + if (!itemStr) + { + return false; + } + + uint32 item_id = 0; + uint32 item_count = 1; + if (sscanf(itemStr, "%u:%u", &item_id, &item_count) != 2) + if (sscanf(itemStr, "%u", &item_id) != 1) + { + return false; + } + + uint32 price; + if (!ExtractUInt32(&args, price)) + { + return false; + } + + uint32 buyout; + if (!ExtractOptUInt32(&args, buyout, 0)) + { + return false; + } + + uint32 etime = 4 * MIN_AUCTION_TIME; + if (char* timeStr = ExtractLiteralArg(&args)) + { + if (strncmp(timeStr, "short", strlen(timeStr)) == 0) + { + etime = 1 * MIN_AUCTION_TIME; + } + else if (strncmp(timeStr, "long", strlen(timeStr)) == 0) + { + etime = 2 * MIN_AUCTION_TIME; + } + else if (strncmp(timeStr, "verylong", strlen(timeStr)) == 0) + { + etime = 4 * MIN_AUCTION_TIME; + } + else + { + return false; + } + } + + AuctionHouseEntry const* auctionHouseEntry = sAuctionHouseStore.LookupEntry(houseid); + AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(auctionHouseEntry); + + if (!item_id) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + ItemPrototype const* item_proto = ObjectMgr::GetItemPrototype(item_id); + if (!item_proto) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + 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; + } + + do + { + uint32 item_stack = item_count > item_proto->GetMaxStackSize() ? item_proto->GetMaxStackSize() : item_count; + item_count -= item_stack; + + Item* newItem = Item::CreateItem(item_id, item_stack); + MANGOS_ASSERT(newItem); + + auctionHouse->AddAuction(auctionHouseEntry, newItem, etime, price, buyout); + } + while (item_count); + + return true; +} + +bool ChatHandler::HandleAuctionHordeCommand(char* /*args*/) +{ + m_session->GetPlayer()->SetAuctionAccessMode(m_session->GetPlayer()->GetTeam() != HORDE ? -1 : 0); + m_session->SendAuctionHello(m_session->GetPlayer()); + return true; +} + +bool ChatHandler::HandleAuctionGoblinCommand(char* /*args*/) +{ + m_session->GetPlayer()->SetAuctionAccessMode(1); + m_session->SendAuctionHello(m_session->GetPlayer()); + return true; +} + +bool ChatHandler::HandleAuctionAllianceCommand(char* /*args*/) +{ + m_session->GetPlayer()->SetAuctionAccessMode(m_session->GetPlayer()->GetTeam() != ALLIANCE ? -1 : 0); + m_session->SendAuctionHello(m_session->GetPlayer()); + return true; +} diff --git a/src/game/ChatCommands/BanAndKickCommands.cpp b/src/game/ChatCommands/BanAndKickCommands.cpp new file mode 100644 index 0000000000000..a18f3bfe18fc1 --- /dev/null +++ b/src/game/ChatCommands/BanAndKickCommands.cpp @@ -0,0 +1,569 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "World.h" +#include "AccountMgr.h" + + /********************************************************************** + CommandTable : banCommandTable + /***********************************************************************/ + + +bool ChatHandler::HandleBanListHelper(QueryResult* result) +{ + PSendSysMessage(LANG_BANLIST_MATCHINGACCOUNT); + + // Chat short output + if (m_session) + { + do + { + Field* fields = result->Fetch(); + uint32 accountid = fields[0].GetUInt32(); + + QueryResult* 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()); + delete banresult; + } + } + 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 + { + sAccountMgr.GetName(account_id, account_name); + } + + // No SQL injection. id is uint32. + QueryResult* 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()); + delete banInfo; + } + } + while (result->NextRow()); + SendSysMessage("==============================================================================="); + } + + delete result; + return true; +} + +bool ChatHandler::HandleBanHelper(BanMode mode, char* args) +{ + if (!*args) + { + return false; + } + + char* cnameOrIP = ExtractArg(&args); + if (!cnameOrIP) + { + return false; + } + + std::string nameOrIP = cnameOrIP; + + char* duration = ExtractArg(&args); // time string + if (!duration) + { + return false; + } + + uint32 duration_secs = TimeStringToSecs(duration); + + char* reason = ExtractArg(&args); + 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_secs, reason, m_session ? m_session->GetPlayerName() : "")) + { + case BAN_SUCCESS: + if (duration_secs > 0) + { + PSendSysMessage(LANG_BAN_YOUBANNED, nameOrIP.c_str(), secsToTimeString(duration_secs, 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::HandleBanIPCommand(char* args) +{ + return HandleBanHelper(BAN_IP, args); +} + +bool ChatHandler::HandleBanCharacterCommand(char* args) +{ + return HandleBanHelper(BAN_CHARACTER, args); +} + +bool ChatHandler::HandleBanAccountCommand(char* args) +{ + return HandleBanHelper(BAN_ACCOUNT, args); +} + + /********************************************************************** + CommandTable : baninfoCommandTable + /***********************************************************************/ + +bool ChatHandler::HandleBanInfoHelper(uint32 accountid, char const* accountname) +{ + QueryResult* 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 ? GetMangosString(LANG_BANINFO_INFINITE) : secsToTimeString(fields[1].GetUInt64(), true); + PSendSysMessage(LANG_BANINFO_HISTORYENTRY, + fields[0].GetString(), bantime.c_str(), active ? GetMangosString(LANG_BANINFO_YES) : GetMangosString(LANG_BANINFO_NO), fields[4].GetString(), fields[5].GetString()); + } + while (result->NextRow()); + + delete result; + return true; +} + +bool ChatHandler::HandleBanInfoIPCommand(char* args) +{ + if (!*args) + { + return false; + } + + char* cIP = ExtractQuotedOrLiteralArg(&args); + if (!cIP) + { + return false; + } + + if (!IsIPAddress(cIP)) + { + return false; + } + + std::string IP = cIP; + + LoginDatabase.escape_string(IP); + QueryResult* 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 ? GetMangosString(LANG_BANINFO_NEVER) : fields[2].GetString(), + permanent ? GetMangosString(LANG_BANINFO_INFINITE) : secsToTimeString(fields[3].GetUInt64(), true).c_str(), fields[4].GetString(), fields[5].GetString()); + delete result; + return true; +} + +bool ChatHandler::HandleBanInfoCharacterCommand(char* args) +{ + Player* target; + ObjectGuid target_guid; + if (!ExtractPlayerTarget(&args, &target, &target_guid)) + { + return false; + } + + uint32 accountid = target ? target->GetSession()->GetAccountId() : sObjectMgr.GetPlayerAccountIdByGUID(target_guid); + + std::string accountname; + if (!sAccountMgr.GetName(accountid, accountname)) + { + PSendSysMessage(LANG_BANINFO_NOCHARACTER); + return true; + } + + return HandleBanInfoHelper(accountid, accountname.c_str()); +} + +bool ChatHandler::HandleBanInfoAccountCommand(char* args) +{ + if (!*args) + { + return false; + } + + std::string account_name; + uint32 accountid = ExtractAccountId(&args, &account_name); + if (!accountid) + { + return false; + } + + return HandleBanInfoHelper(accountid, account_name.c_str()); +} + + /********************************************************************** + CommandTable : banlistCommandTable + /***********************************************************************/ + +bool ChatHandler::HandleBanListIPCommand(char* args) +{ + LoginDatabase.Execute("DELETE FROM `ip_banned` WHERE `unbandate`<=UNIX_TIMESTAMP() AND `unbandate`<>`bandate`"); + + char* cFilter = ExtractLiteralArg(&args); + std::string filter = cFilter ? cFilter : ""; + LoginDatabase.escape_string(filter); + + QueryResult* 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("==============================================================================="); + } + + delete result; + return true; +} + +bool ChatHandler::HandleBanListCharacterCommand(char* args) +{ + LoginDatabase.Execute("DELETE FROM `ip_banned` WHERE `unbandate`<=UNIX_TIMESTAMP() AND `unbandate`<>`bandate`"); + + char* cFilter = ExtractLiteralArg(&args); + if (!cFilter) + { + return false; + } + + std::string filter = cFilter; + LoginDatabase.escape_string(filter); + QueryResult* 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(char* args) +{ + LoginDatabase.Execute("DELETE FROM `ip_banned` WHERE `unbandate`<=UNIX_TIMESTAMP() AND `unbandate`<>`bandate`"); + + char* cFilter = ExtractLiteralArg(&args); + std::string filter = cFilter ? cFilter : ""; + LoginDatabase.escape_string(filter); + + QueryResult* 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); +} + +/********************************************************************** + CommandTable : unbanCommandTable +/***********************************************************************/ + +bool ChatHandler::HandleUnBanHelper(BanMode mode, char* args) +{ + if (!*args) + { + return false; + } + + char* cnameOrIP = ExtractArg(&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::HandleUnBanAccountCommand(char* args) +{ + return HandleUnBanHelper(BAN_ACCOUNT, args); +} + +bool ChatHandler::HandleUnBanCharacterCommand(char* args) +{ + return HandleUnBanHelper(BAN_CHARACTER, args); +} + +bool ChatHandler::HandleUnBanIPCommand(char* args) +{ + return HandleUnBanHelper(BAN_IP, args); +} + +/********************************************************************** + CommandTable : commandTable +/***********************************************************************/ + +// kick player +bool ChatHandler::HandleKickPlayerCommand(char* args) +{ + Player* target; + if (!ExtractPlayerTarget(&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)) + { + return false; + } + + // send before target pointer invalidate + PSendSysMessage(LANG_COMMAND_KICKMESSAGE, GetNameLink(target).c_str()); + target->GetSession()->KickPlayer(); + return true; +} \ No newline at end of file diff --git a/src/game/ChatCommands/CastAndAuraCommands.cpp b/src/game/ChatCommands/CastAndAuraCommands.cpp new file mode 100644 index 0000000000000..5e3316f18cdca --- /dev/null +++ b/src/game/ChatCommands/CastAndAuraCommands.cpp @@ -0,0 +1,324 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "SpellAuras.h" +#include "SpellMgr.h" + +/********************************************************************** + CommandTable : castCommandTable +/***********************************************************************/ + +bool ChatHandler::HandleCastCommand(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(&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; + } + + bool triggered = ExtractLiteralArg(&args, "triggered") != NULL; + if (!triggered && *args) // can be fail also at syntax error + { + return false; + } + + m_session->GetPlayer()->CastSpell(target, spell, triggered); + + return true; +} + +bool ChatHandler::HandleCastBackCommand(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(&args); + if (!spell || !sSpellStore.LookupEntry(spell)) + { + return false; + } + + bool triggered = ExtractLiteralArg(&args, "triggered") != NULL; + if (!triggered && *args) // can be fail also at syntax error + { + return false; + } + + caster->SetFacingToObject(m_session->GetPlayer()); + + caster->CastSpell(m_session->GetPlayer(), spell, triggered); + + return true; +} + +bool ChatHandler::HandleCastDistCommand(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(&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; + } + + float dist; + if (!ExtractFloat(&args, dist)) + { + return false; + } + + bool triggered = ExtractLiteralArg(&args, "triggered") != NULL; + if (!triggered && *args) // can be fail also at syntax error + { + return false; + } + + 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(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(&args); + if (!spell || !sSpellStore.LookupEntry(spell)) + { + return false; + } + + bool triggered = ExtractLiteralArg(&args, "triggered") != NULL; + if (!triggered && *args) // can be fail also at syntax error + { + return false; + } + + caster->SetFacingToObject(m_session->GetPlayer()); + + caster->CastSpell(caster->getVictim(), spell, triggered); + + return true; +} + +bool ChatHandler::HandleCastSelfCommand(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(&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; + } + + bool triggered = ExtractLiteralArg(&args, "triggered") != NULL; + if (!triggered && *args) // can be fail also at syntax error + { + return false; + } + + target->CastSpell(target, spell, triggered); + + return true; +} + +/********************************************************************** + CommandTable : Aura commands +/***********************************************************************/ + +bool ChatHandler::HandleAuraCommand(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(&args); + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellID); + if (!spellInfo) + { + return false; + } + + if (!IsSpellAppliesAura(spellInfo, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) && + !IsSpellHaveEffect(spellInfo, SPELL_EFFECT_PERSISTENT_AREA_AURA)) + { + PSendSysMessage(LANG_SPELL_NO_HAVE_AURAS, spellID); + SetSentErrorMessage(true); + return false; + } + + SpellAuraHolder* holder = CreateSpellAuraHolder(spellInfo, target, m_session->GetPlayer()); + + for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) + { + uint8 eff = spellInfo->Effect[i]; + if (eff >= TOTAL_SPELL_EFFECTS) + { + continue; + } + if (IsAreaAuraEffect(eff) || + eff == SPELL_EFFECT_APPLY_AURA || + eff == SPELL_EFFECT_PERSISTENT_AREA_AURA) + { + Aura* aur = CreateAura(spellInfo, SpellEffectIndex(i), NULL, holder, target); + holder->AddAura(aur, SpellEffectIndex(i)); + } + } + target->AddSpellAuraHolder(holder); + + return true; +} + +bool ChatHandler::HandleUnAuraCommand(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(&args); + if (!spellID) + { + return false; + } + + target->RemoveAurasDueToSpell(spellID); + + return true; +} \ No newline at end of file diff --git a/src/game/ChatCommands/CommunicationCommands.cpp b/src/game/ChatCommands/CommunicationCommands.cpp new file mode 100644 index 0000000000000..949b91e38df89 --- /dev/null +++ b/src/game/ChatCommands/CommunicationCommands.cpp @@ -0,0 +1,383 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "World.h" + +/* + All commands related to discussions +*/ + + /********************************************************************** + CommandTable : commandTable + /***********************************************************************/ + + // global announce +bool ChatHandler::HandleAnnounceCommand(char* args) +{ + if (!*args) + { + return false; + } + + sWorld.SendWorldText(LANG_SYSTEMMESSAGE, args); + return true; +} + +// notification player at the screen +bool ChatHandler::HandleNotifyCommand(char* args) +{ + if (!*args) + { + return false; + } + + std::string str = GetMangosString(LANG_GLOBAL_NOTIFY); + str += args; + + WorldPacket data(SMSG_NOTIFICATION, (str.size() + 1)); + data << str; + sWorld.SendGlobalMessage(&data); + + return true; +} + +// mute player for some times +bool ChatHandler::HandleMuteCommand(char* args) +{ + char* nameStr = ExtractOptNotLastArg(&args); + + Player* target; + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&nameStr, &target, &target_guid, &target_name)) + { + return false; + } + + uint32 notspeaktime; + if (!ExtractUInt32(&args, notspeaktime)) + { + return false; + } + + uint32 account_id = target ? target->GetSession()->GetAccountId() : sObjectMgr.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; + } + + 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); + } + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_YOU_DISABLE_CHAT, nameLink.c_str(), notspeaktime); + return true; +} + +// unmute player +bool ChatHandler::HandleUnmuteCommand(char* args) +{ + Player* target; + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) + { + return false; + } + + uint32 account_id = target ? target->GetSession()->GetAccountId() : sObjectMgr.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; +} + +// Enable\Dissable accept whispers (for GM) +bool ChatHandler::HandleWhispersCommand(char* args) +{ + if (!*args) + { + PSendSysMessage(LANG_COMMAND_WHISPERACCEPTING, GetOnOffStr(m_session->GetPlayer()->isAcceptWhispers())); + return true; + } + + bool value; + if (!ExtractOnOff(&args, value)) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + // whisper on + if (value) + { + m_session->GetPlayer()->SetAcceptWhispers(true); + SendSysMessage(LANG_COMMAND_WHISPERON); + } + // whisper off + else + { + m_session->GetPlayer()->SetAcceptWhispers(false); + SendSysMessage(LANG_COMMAND_WHISPEROFF); + } + + return true; +} + +// Enables or disables hiding of the staff badge +bool ChatHandler::HandleGMChatCommand(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; + } + + bool value; + if (!ExtractOnOff(&args, value)) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + if (value) + { + m_session->GetPlayer()->SetGMChat(true); + m_session->SendNotification(LANG_GM_CHAT_ON); + } + else + { + m_session->GetPlayer()->SetGMChat(false); + m_session->SendNotification(LANG_GM_CHAT_OFF); + } + + return true; +} + + +/********************************************************************** + CommandTable : npcCommandTable +/***********************************************************************/ + +bool ChatHandler::HandleNpcSayCommand(char* args) +{ + if (!*args) + { + return false; + } + + Creature* pCreature = getSelectedCreature(); + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->MonsterSay(args, LANG_UNIVERSAL, m_session->GetPlayer()); + + return true; +} + +bool ChatHandler::HandleNpcYellCommand(char* args) +{ + if (!*args) + { + return false; + } + + Creature* pCreature = getSelectedCreature(); + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->MonsterYell(args, LANG_UNIVERSAL, m_session->GetPlayer()); + + return true; +} + +// show text emote by creature in chat +bool ChatHandler::HandleNpcTextEmoteCommand(char* args) +{ + if (!*args) + { + return false; + } + + Creature* pCreature = getSelectedCreature(); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->MonsterTextEmote(args, m_session->GetPlayer()); + + return true; +} + +// make npc whisper to player +bool ChatHandler::HandleNpcWhisperCommand(char* args) +{ + Player* target; + if (!ExtractPlayerTarget(&args, &target)) + { + return false; + } + + ObjectGuid guid = m_session->GetPlayer()->GetSelectionGuid(); + if (!guid) + { + return false; + } + + Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(guid); + + if (!pCreature || !target || !*args) + { + return false; + } + + // check online security + if (HasLowerSecurity(target)) + { + return false; + } + + pCreature->MonsterWhisper(args, target); + + return true; +} + +/// Send a message to a player in game +bool ChatHandler::HandleSendMessageCommand(char* args) +{ + ///- Find the player + Player* rPlayer; + if (!ExtractPlayerTarget(&args, &rPlayer)) + { + return false; + } + + ///- message + if (!*args) + { + return false; + } + + WorldSession* rPlayerSession = rPlayer->GetSession(); + + ///- Check that he is not logging out. + if (rPlayerSession->isLogingOut()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + ///- Send the message + // Use SendAreaTriggerMessage for fastest delivery. + rPlayerSession->SendAreaTriggerMessage("%s", args); + rPlayerSession->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); + + // Confirmation message + std::string nameLink = GetNameLink(rPlayer); + PSendSysMessage(LANG_SENDMESSAGE, nameLink.c_str(), args); + return true; +} + diff --git a/src/game/ChatCommands/CreatureCommands.cpp b/src/game/ChatCommands/CreatureCommands.cpp new file mode 100644 index 0000000000000..7cfdd8a2e8cdc --- /dev/null +++ b/src/game/ChatCommands/CreatureCommands.cpp @@ -0,0 +1,1212 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "World.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" +#include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand +#include "TemporarySummon.h" +#include "WaypointManager.h" +#include "PathFinder.h" // for mmap commands +#include "Totem.h" + +#ifdef _DEBUG_VMAPS +#include "VMapFactory.h" +#endif + + /********************************************************************** + CommandTable : commandTable + /***********************************************************************/ + +/* +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(char* /*args*/) +{ + Creature* caster = getSelectedCreature(); + + if (!caster) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + Player* pl = m_session->GetPlayer(); + + caster->GetMotionMaster()->MovePoint(0, pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ()); + return true; +} + +bool ChatHandler::HandleRespawnCommand(char* /*args*/) +{ + Player* pl = m_session->GetPlayer(); + + // accept only explicitly selected target (not implicitly self targeting case) + Unit* target = getSelectedUnit(); + if (pl->GetSelectionGuid() && target) + { + if (target->GetTypeId() != TYPEID_UNIT) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (target->IsDead()) + { + ((Creature*)target)->Respawn(); + } + return true; + } + + MaNGOS::RespawnDo u_do; + MaNGOS::WorldObjectWorker worker(u_do); + Cell::VisitGridObjects(pl, worker, pl->GetMap()->GetVisibilityDistance()); + return true; +} + +// Edit Creature Faction +bool ChatHandler::HandleModifyFactionCommand(char* args) +{ + Creature* chr = getSelectedCreature(); + if (!chr) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (!*args) + { + 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; + if (!ExtractUint32KeyFromLink(&args, "Hfaction", factionid)) + { + return false; + } + + if (!sFactionTemplateStore.LookupEntry(factionid)) + { + PSendSysMessage(LANG_WRONG_FACTION, factionid); + SetSentErrorMessage(true); + return false; + } + + uint32 flag; + if (!ExtractOptUInt32(&args, flag, chr->GetUInt32Value(UNIT_FIELD_FLAGS))) + { + return false; + } + + uint32 npcflag; + if (!ExtractOptUInt32(&args, npcflag, chr->GetUInt32Value(UNIT_NPC_FLAGS))) + { + return false; + } + + uint32 dyflag; + if (!ExtractOptUInt32(&args, dyflag, chr->GetUInt32Value(UNIT_DYNAMIC_FLAGS))) + { + 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; +} + + +//-----------------------Npc Commands----------------------- +// add spawn of creature +bool ChatHandler::HandleNpcAddCommand(char* args) +{ + if (!*args) + { + return false; + } + + uint32 id; + if (!ExtractUint32KeyFromLink(&args, "Hcreature_entry", id)) + { + return false; + } + + CreatureInfo const* cinfo = ObjectMgr::GetCreatureTemplate(id); + if (!cinfo) + { + PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, id); + SetSentErrorMessage(true); + return false; + } + + Player* chr = m_session->GetPlayer(); + CreatureCreatePos pos(chr, chr->GetOrientation()); + Map* map = chr->GetMap(); + + Creature* pCreature = new Creature; + + // used guids from specially reserved range (can be 0 if no free values) + uint32 lowguid = sObjectMgr.GenerateStaticCreatureLowGuid(); + if (!lowguid) + { + SendSysMessage(LANG_NO_FREE_STATIC_GUID_FOR_SPAWN); + SetSentErrorMessage(true); + return false; + } + + if (!pCreature->Create(lowguid, pos, cinfo)) + { + delete pCreature; + return false; + } + + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + + uint32 db_guid = pCreature->GetGUIDLow(); + + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + pCreature->LoadFromDB(db_guid, map); + + return true; +} + +// add item in vendorlist +bool ChatHandler::HandleNpcAddVendorItemCommand(char* args) +{ + uint32 itemId; + if (!ExtractUint32KeyFromLink(&args, "Hitem", itemId)) + { + SendSysMessage(LANG_COMMAND_NEEDITEMSEND); + SetSentErrorMessage(true); + return false; + } + + uint32 maxcount; + if (!ExtractOptUInt32(&args, maxcount, 0)) + { + return false; + } + + uint32 incrtime; + if (!ExtractOptUInt32(&args, incrtime, 0)) + { + return false; + } + + uint32 extendedcost; + if (!ExtractOptUInt32(&args, extendedcost, 0)) + { + return false; + } + + Creature* vendor = getSelectedCreature(); + + uint32 vendor_entry = vendor ? vendor->GetEntry() : 0; + + if (!sObjectMgr.IsVendorItemValid(false, "npc_vendor", vendor_entry, itemId, maxcount, incrtime, extendedcost, 0, m_session->GetPlayer())) + { + SetSentErrorMessage(true); + return false; + } + + sObjectMgr.AddVendorItem(vendor_entry, itemId, maxcount, incrtime, extendedcost); + + ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(itemId); + + PSendSysMessage(LANG_ITEM_ADDED_TO_LIST, itemId, pProto->Name1, maxcount, incrtime, extendedcost); + return true; +} + +// del item from vendor list +bool ChatHandler::HandleNpcDelVendorItemCommand(char* args) +{ + if (!*args) + { + return false; + } + + Creature* vendor = getSelectedCreature(); + if (!vendor || !vendor->IsVendor()) + { + SendSysMessage(LANG_COMMAND_VENDORSELECTION); + SetSentErrorMessage(true); + return false; + } + + uint32 itemId; + if (!ExtractUint32KeyFromLink(&args, "Hitem", itemId)) + { + SendSysMessage(LANG_COMMAND_NEEDITEMSEND); + SetSentErrorMessage(true); + return false; + } + + if (!sObjectMgr.RemoveVendorItem(vendor->GetEntry(), itemId)) + { + PSendSysMessage(LANG_ITEM_NOT_IN_LIST, itemId); + SetSentErrorMessage(true); + return false; + } + + ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(itemId); + + PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST, itemId, pProto->Name1); + return true; +} + +// show info about AI +bool ChatHandler::HandleNpcAIInfoCommand(char* /*args*/) +{ + Creature* pTarget = getSelectedCreature(); + + if (!pTarget) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_NPC_AI_HEADER, pTarget->GetEntry()); + + std::string strScript = pTarget->GetScriptName(); + std::string strAI = pTarget->GetAIName(); + char const* cstrAIClass = pTarget->AI() ? typeid(*pTarget->AI()).name() : " - "; + + PSendSysMessage(LANG_NPC_AI_NAMES, + strAI.empty() ? " - " : strAI.c_str(), + cstrAIClass ? cstrAIClass : " - ", + strScript.empty() ? " - " : strScript.c_str()); + + if (pTarget->AI()) + { + pTarget->AI()->GetAIInformation(*this); + } + + return true; +} + +// change level of creature or pet +bool ChatHandler::HandleNpcChangeLevelCommand(char* args) +{ + if (!*args) + { + return false; + } + + uint8 lvl = (uint8)atoi(args); + if (lvl < 1 || lvl > sWorld.getConfig(CONFIG_UINT32_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()) + { + ((Pet*)pCreature)->GivePetLevel(lvl); + } + else + { + pCreature->SetMaxHealth(100 + 30 * lvl); + pCreature->SetHealth(100 + 30 * lvl); + pCreature->SetLevel(lvl); + + if (pCreature->HasStaticDBSpawnData()) + { + pCreature->SaveToDB(); + } + } + + return true; +} + +// set npcflag of creature +bool ChatHandler::HandleNpcFlagCommand(char* args) +{ + if (!*args) + { + return false; + } + + uint32 npcFlags = (uint32)atoi(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 `NpcFlags` = '%u' WHERE `entry` = '%u'", npcFlags, pCreature->GetEntry()); + + SendSysMessage(LANG_VALUE_SAVED_REJOIN); + + return true; +} + +bool ChatHandler::HandleNpcDeleteCommand(char* args) +{ + Creature* unit = NULL; + + if (*args) + { + // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r + uint32 lowguid; + if (!ExtractUint32KeyFromLink(&args, "Hcreature", lowguid)) + { + return false; + } + + if (!lowguid) + { + return false; + } + + if (CreatureData const* data = sObjectMgr.GetCreatureData(lowguid)) + { + unit = m_session->GetPlayer()->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); + } + } + else + { + unit = getSelectedCreature(); + } + + if (!unit) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + switch (unit->GetSubtype()) + { + case CREATURE_SUBTYPE_GENERIC: + { + unit->CombatStop(); + if (CreatureData const* data = sObjectMgr.GetCreatureData(unit->GetGUIDLow())) + { + Creature::AddToRemoveListInMaps(unit->GetGUIDLow(), data); + Creature::DeleteFromDB(unit->GetGUIDLow(), data); + } + else + { + unit->AddObjectToRemoveList(); + } + break; + } + case CREATURE_SUBTYPE_PET: + ((Pet*)unit)->Unsummon(PET_SAVE_AS_CURRENT); + break; + case CREATURE_SUBTYPE_TOTEM: + ((Totem*)unit)->UnSummon(); + break; + case CREATURE_SUBTYPE_TEMPORARY_SUMMON: + ((TemporarySummon*)unit)->UnSummon(); + break; + default: + return false; + } + + SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); + + return true; +} + +// move selected creature +bool ChatHandler::HandleNpcMoveCommand(char* args) +{ + uint32 lowguid = 0; + Player* player = m_session->GetPlayer(); + + Creature* pCreature = getSelectedCreature(); + if (!pCreature) + { + // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r + if (!ExtractUint32KeyFromLink(&args, "Hcreature", lowguid)) + { + return false; + } + + CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); + if (!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + if (player->GetMapId() != data->mapid) + { + PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); + SetSentErrorMessage(true); + return false; + } + + pCreature = player->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); + } + else + { + lowguid = pCreature->GetGUIDLow(); + } + + float x = player->GetPositionX(); + float y = player->GetPositionY(); + float z = player->GetPositionZ(); + float o = player->GetOrientation(); + + if (pCreature) + { + if (CreatureData const* data = sObjectMgr.GetCreatureData(pCreature->GetGUIDLow())) + { + const_cast(data)->posX = x; + const_cast(data)->posY = y; + const_cast(data)->posZ = z; + const_cast(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.
+ *
+ * Valid movement types are: + *
    + *
  • stay - NPC wont move
  • + *
  • random - NPC will move randomly according to the spawndist
  • + *
  • way - NPC will move with given waypoints set
  • + *
+ * additional parameter: NODEL - so no waypoints are deleted, if you + * change the movement type + */ +bool ChatHandler::HandleNpcSetMoveTypeCommand(char* args) +{ + // 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) + + uint32 lowguid; + Creature* pCreature; + if (!ExtractUInt32(&args, lowguid)) // case .setmovetype $move_type (with selected creature) + { + pCreature = getSelectedCreature(); + if (!pCreature || !pCreature->HasStaticDBSpawnData()) + { + return false; + } + lowguid = pCreature->GetGUIDLow(); + } + else // case .setmovetype #creature_guid $move_type (with guid) + { + CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); + if (!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + Player* player = m_session->GetPlayer(); + + if (player->GetMapId() != data->mapid) + { + PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); + SetSentErrorMessage(true); + return false; + } + + pCreature = player->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); + } + + MovementGeneratorType move_type; + char* type_str = ExtractLiteralArg(&args); + if (!type_str) + { + return false; + } + + if (strncmp(type_str, "stay", strlen(type_str)) == 0) + { + move_type = IDLE_MOTION_TYPE; + } + else if (strncmp(type_str, "random", strlen(type_str)) == 0) + { + move_type = RANDOM_MOTION_TYPE; + } + else if (strncmp(type_str, "way", strlen(type_str)) == 0) + { + move_type = WAYPOINT_MOTION_TYPE; + } + else + { + return false; + } + + bool doNotDelete = ExtractLiteralArg(&args, "NODEL") != NULL; + if (!doNotDelete && *args) // need fail if false in result wrong literal + { + return false; + } + + // now lowguid is low guid really existing creature + // and pCreature point (maybe) to this creature or NULL + + // update movement type + if (!doNotDelete) + { + sWaypointMgr.DeletePath(lowguid); + } + + if (pCreature) + { + 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) + { + PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL, type_str); + } + else + { + PSendSysMessage(LANG_MOVE_TYPE_SET, type_str); + } + + return true; +} + +// set model of creature +bool ChatHandler::HandleNpcSetModelCommand(char* args) +{ + if (!*args) + { + return false; + } + + uint32 displayId = (uint32)atoi(args); + + Creature* pCreature = getSelectedCreature(); + + if (!pCreature || pCreature->IsPet()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetDisplayId(displayId); + pCreature->SetNativeDisplayId(displayId); + + if (pCreature->HasStaticDBSpawnData()) + { + pCreature->SaveToDB(); + } + + return true; +} + +// set faction of creature +bool ChatHandler::HandleNpcFactionIdCommand(char* args) +{ + if (!*args) + { + return false; + } + + uint32 factionId = (uint32)atoi(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(cinfo)->FactionAlliance = factionId; + const_cast(cinfo)->FactionHorde = factionId; + } + + // and DB + WorldDatabase.PExecuteLog("UPDATE `creature_template` SET `FactionAlliance` = '%u', `FactionHorde` = '%u' WHERE `entry` = '%u'", factionId, factionId, pCreature->GetEntry()); + + return true; +} + +// set spawn dist of creature +bool ChatHandler::HandleNpcSpawnDistCommand(char* args) +{ + if (!*args) + { + return false; + } + + float option = (float)atof(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->GetGUIDLow(); + } + 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(char* args) +{ + uint32 stime; + if (!ExtractUInt32(&args, stime)) + { + return false; + } + + Creature* pCreature = getSelectedCreature(); + if (!pCreature) + { + PSendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint32 u_guidlow = pCreature->GetGUIDLow(); + + WorldDatabase.PExecuteLog("UPDATE `creature` SET `spawntimesecs`=%i WHERE `guid`=%u", stime, u_guidlow); + pCreature->SetRespawnDelay(stime); + PSendSysMessage(LANG_COMMAND_SPAWNTIME, stime); + + return true; +} +// npc follow handling +bool ChatHandler::HandleNpcFollowCommand(char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + Creature* creature = getSelectedCreature(); + + if (!creature) + { + PSendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // Follow player - Using pet's default dist and angle + creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + + PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName()); + return true; +} +// npc unfollow handling +bool ChatHandler::HandleNpcUnFollowCommand(char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + Creature* creature = getSelectedCreature(); + + if (!creature) + { + PSendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + MotionMaster* creatureMotion = creature->GetMotionMaster(); + if (creatureMotion->empty() || + creatureMotion->GetCurrentMovementGeneratorType() != FOLLOW_MOTION_TYPE) + { + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName()); + SetSentErrorMessage(true); + return false; + } + + FollowMovementGenerator const* mgen = static_cast const*>(creatureMotion->top()); + + if (mgen->GetTarget() != player) + { + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName()); + SetSentErrorMessage(true); + return false; + } + + // reset movement + creatureMotion->MovementExpired(true); + + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName()); + return true; +} +// npc tame handling +bool ChatHandler::HandleNpcTameCommand(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; + } + + player->CastSpell(creatureTarget, 13481, true); // Tame Beast, triggered effect + return true; +} + +// npc deathstate handling +bool ChatHandler::HandleNpcSetDeathStateCommand(char* args) +{ + bool value; + if (!ExtractOnOff(&args, value)) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + Creature* pCreature = getSelectedCreature(); + if (!pCreature || !pCreature->HasStaticDBSpawnData()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (value) + { + pCreature->SetDeadByDefault(true); + } + else + { + pCreature->SetDeadByDefault(false); + } + + pCreature->SaveToDB(); + pCreature->Respawn(); + + return true; +} + +// TODO: NpcCommands that need to be fixed : + +bool ChatHandler::HandleNpcNameCommand(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; + } + } + + ObjectGuid guid = m_session->GetPlayer()->GetSelectionGuid(); + if (guid.IsEmpty()) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature* pCreature = sObjectAccessor.GetCreature(*m_session->GetPlayer(), guid); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + pCreature->SetName(args); + uint32 idname = sObjectMgr.AddCreatureTemplate(pCreature->GetName()); + pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); + + pCreature->SaveToDB(); + */ + + return true; +} + +bool ChatHandler::HandleNpcSubNameCommand(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; + } + } + + ObjectGuid guid = m_session->GetPlayer()->GetSelectionGuid(); + if (guid.IsEmpty()) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature* pCreature = sObjectAccessor.GetCreature(*m_session->GetPlayer(), guid); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + uint32 idname = sObjectMgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID)); + pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); + + pCreature->SaveToDB(); + */ + return true; +} + +//-----------------------Npc Commands----------------------- +bool ChatHandler::HandleNpcAllowMovementCommand(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(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 = (Creature*)unit; + if (creature->UpdateEntry(newEntryNum)) + { + SendSysMessage(LANG_DONE); + } + else + { + SendSysMessage(LANG_ERROR); + } + return true; +} + +bool ChatHandler::HandleNpcInfoCommand(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(); + + time_t curRespawnDelay = target->GetRespawnTimeEx() - time(NULL); + if (curRespawnDelay < 0) + { + curRespawnDelay = 0; + } + std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay, true); + std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(), true); + + // Send information dependend on difficulty mode + CreatureInfo const* baseInfo = ObjectMgr::GetCreatureTemplate(Entry); + if (baseInfo->HeroicEntry == target->GetCreatureInfo()->Entry) + PSendSysMessage(LANG_NPCINFO_CHAR_DIFFICULTY, target->GetGuidStr().c_str(), faction, npcflags, + Entry, target->GetCreatureInfo()->Entry, 1, + displayid, nativeid); + else + { + PSendSysMessage(LANG_NPCINFO_CHAR, target->GetGuidStr().c_str(), 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->SkinningLootId); + PSendSysMessage(LANG_NPCINFO_DUNGEON_ID, target->GetInstanceId()); + PSendSysMessage(LANG_NPCINFO_POSITION, float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ())); + + if ((npcflags & UNIT_NPC_FLAG_VENDOR)) + { + SendSysMessage(LANG_NPCINFO_VENDOR); + } + if ((npcflags & UNIT_NPC_FLAG_TRAINER)) + { + SendSysMessage(LANG_NPCINFO_TRAINER); + } + + ShowNpcOrGoSpawnInformation(target->GetGUIDLow()); + return true; +} + +// play npc emote +bool ChatHandler::HandleNpcPlayEmoteCommand(char* args) +{ + uint32 emote = atoi(args); + + Creature* target = getSelectedCreature(); + if (!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + target->HandleEmote(emote); + + return true; +} + +// TODO: NpcCommands that needs to be fixed : +bool ChatHandler::HandleNpcAddWeaponCommand(char* /*args*/) +{ + /*if (!*args) + return false; + + ObjectGuid guid = m_session->GetPlayer()->GetSelectionGuid(); + if (guid.IsEmpty()) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature *pCreature = sObjectAccessor.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 = ObjectMgr::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; +} +//---------------------------------------------------------- diff --git a/src/game/ChatCommands/debugcmds.cpp b/src/game/ChatCommands/DebugCommands.cpp similarity index 99% rename from src/game/ChatCommands/debugcmds.cpp rename to src/game/ChatCommands/DebugCommands.cpp index 2e4aff12bd7ce..fb35d90a8469c 100644 --- a/src/game/ChatCommands/debugcmds.cpp +++ b/src/game/ChatCommands/DebugCommands.cpp @@ -38,6 +38,10 @@ #include "ObjectGuid.h" #include "SpellMgr.h" +/********************************************************************** + CommandTable : debugCommandTable +/***********************************************************************/ + bool ChatHandler::HandleDebugSendSpellFailCommand(char* args) { if (!*args) diff --git a/src/game/ChatCommands/EventCommands.cpp b/src/game/ChatCommands/EventCommands.cpp new file mode 100644 index 0000000000000..7a392efb18efe --- /dev/null +++ b/src/game/ChatCommands/EventCommands.cpp @@ -0,0 +1,220 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "GameEventMgr.h" +#include "GameEventMgr.h" + + /********************************************************************** + CommandTable : eventCommandTable + /***********************************************************************/ + +bool ChatHandler::HandleEventListCommand(char* args) +{ + uint32 counter = 0; + bool all = false; + std::string arg = args; + if (arg == "all") + { + all = true; + } + + GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap(); + + char const* active = GetMangosString(LANG_ACTIVE); + char const* inactive = GetMangosString(LANG_FACTION_INACTIVE); + char const* state = ""; + + for (uint32 event_id = 0; event_id < events.size(); ++event_id) + { + if (!sGameEventMgr.IsValidEvent(event_id)) + { + continue; + } + + if (!sGameEventMgr.IsActiveEvent(event_id)) + { + if (!all) + { + continue; + } + state = inactive; + } + else + { + state = active; + } + + GameEventData const& eventData = events[event_id]; + + if (m_session) + { + PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT, event_id, event_id, eventData.description.c_str(), state); + } + else + { + PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE, event_id, eventData.description.c_str(), state); + } + + ++counter; + } + + if (counter == 0) + { + SendSysMessage(LANG_NOEVENTFOUND); + } + + return true; +} + +bool ChatHandler::HandleEventInfoCommand(char* args) +{ + if (!*args) + { + return false; + } + + // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r + uint32 event_id; + if (!ExtractUint32KeyFromLink(&args, "Hgameevent", event_id)) + { + return false; + } + + GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap(); + + if (!sGameEventMgr.IsValidEvent(event_id)) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventData const& eventData = events[event_id]; + + char const* activeStr = sGameEventMgr.IsActiveEvent(event_id) ? GetMangosString(LANG_ACTIVE) : ""; + + std::string startTimeStr = TimeToTimestampStr(eventData.start); + std::string endTimeStr = TimeToTimestampStr(eventData.end); + + uint32 delay = sGameEventMgr.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(char* args) +{ + if (!*args) + { + return false; + } + + // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r + uint32 event_id; + if (!ExtractUint32KeyFromLink(&args, "Hgameevent", event_id)) + { + return false; + } + + GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap(); + + if (!sGameEventMgr.IsValidEvent(event_id)) + { + 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; + } + + if (sGameEventMgr.IsActiveEvent(event_id)) + { + PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE, event_id); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_EVENT_STARTED, event_id, eventData.description.c_str()); + sGameEventMgr.StartEvent(event_id, true); + return true; +} + +bool ChatHandler::HandleEventStopCommand(char* args) +{ + if (!*args) + { + return false; + } + + // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r + uint32 event_id; + if (!ExtractUint32KeyFromLink(&args, "Hgameevent", event_id)) + { + return false; + } + + GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap(); + + if (!sGameEventMgr.IsValidEvent(event_id)) + { + 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; + } + + if (!sGameEventMgr.IsActiveEvent(event_id)) + { + PSendSysMessage(LANG_EVENT_NOT_ACTIVE, event_id); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_EVENT_STOPPED, event_id, eventData.description.c_str()); + sGameEventMgr.StopEvent(event_id, true); + return true; +} + diff --git a/src/game/ChatCommands/GMCommands.cpp b/src/game/ChatCommands/GMCommands.cpp new file mode 100644 index 0000000000000..8b93610e676d5 --- /dev/null +++ b/src/game/ChatCommands/GMCommands.cpp @@ -0,0 +1,427 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "World.h" +#include "Weather.h" +#include "SpellMgr.h" + + + /********************************************************************** + CommandTable : commandTable + /***********************************************************************/ + +// show info of player +bool ChatHandler::HandlePInfoCommand(char* args) +{ + Player* target; + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) + { + return false; + } + + uint32 accId = 0; + uint32 money = 0; + uint32 total_player_time = 0; + uint32 level = 0; + uint32 latency = 0; + + // get additional information from Player object + if (target) + { + // check online security + if (HasLowerSecurity(target)) + { + return false; + } + + accId = target->GetSession()->GetAccountId(); + money = target->GetMoney(); + total_player_time = target->GetTotalPlayedTime(); + level = target->getLevel(); + latency = target->GetSession()->GetLatency(); + } + // get additional information from DB + else + { + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + { + return false; + } + + // 0 1 2 3 + QueryResult* result = CharacterDatabase.PQuery("SELECT `totaltime`, `level`, `money`, `account` FROM `characters` WHERE `guid` = '%u'", target_guid.GetCounter()); + 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(); + delete result; + } + + std::string username = GetMangosString(LANG_ERROR); + std::string email = GetMangosString(LANG_ERROR); + std::string last_ip = GetMangosString(LANG_ERROR); + AccountTypes security = SEC_PLAYER; + std::string last_login = GetMangosString(LANG_ERROR); + + QueryResult* result = LoginDatabase.PQuery("SELECT `username`,`gmlevel`,`email`,`last_ip`,`last_login` FROM `account` WHERE `id` = '%u'", accId); + if (result) + { + Field* fields = result->Fetch(); + username = fields[0].GetCppString(); + security = (AccountTypes)fields[1].GetUInt32(); + + if (GetAccessLevel() >= security) + { + if (security == SEC_ADMINISTRATOR) + { + email = fields[2].GetCppString(); + } + else + { + email = "*hidden*"; + } + last_ip = fields[3].GetCppString(); + last_login = fields[4].GetCppString(); + } + else + { + email = "-"; + last_ip = "-"; + last_login = "-"; + } + + delete result; + } + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_PINFO_ACCOUNT, (target ? "" : GetMangosString(LANG_OFFLINE)), nameLink.c_str(), target_guid.GetCounter(), username.c_str(), accId, security, email.c_str(), last_ip.c_str(), last_login.c_str(), latency); + + 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, timeStr.c_str(), level, gold, silv, copp); + + return true; +} + +bool ChatHandler::HandleWaterwalkCommand(char* args) +{ + bool value; + if (!ExtractOnOff(&args, value)) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + Player* player = getSelectedPlayer(); + + if (!player) + { + PSendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(player)) + { + return false; + } + + if (value) + { + player->SetWaterWalk(true); // ON + } + else + { + player->SetWaterWalk(false); // OFF + } + + 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; +} + +// Enable\Dissable GM Mode +bool ChatHandler::HandleGMCommand(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); +#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); +#ifdef _DEBUG_VMAPS + VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); + vMapManager->processCommand("startlog"); +#endif + + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +// Enable\Dissable Invisible mode +bool ChatHandler::HandleGMVisibleCommand(char* args) +{ + if (!*args) + { + PSendSysMessage(LANG_YOU_ARE, m_session->GetPlayer()->isGMVisible() ? GetMangosString(LANG_VISIBLE) : GetMangosString(LANG_INVISIBLE)); + return true; + } + + bool value; + if (!ExtractOnOff(&args, value)) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + Player* player = m_session->GetPlayer(); + SpellEntry const* invisibleAuraInfo = sSpellStore.LookupEntry(sWorld.getConfig(CONFIG_UINT32_GM_INVISIBLE_AURA)); + if (!invisibleAuraInfo || !IsSpellAppliesAura(invisibleAuraInfo)) + { + invisibleAuraInfo = NULL; + } + + if (value) + { + player->SetGMVisible(true); + m_session->SendNotification(LANG_INVISIBLE_VISIBLE); + if (invisibleAuraInfo) + { + player->RemoveAurasDueToSpell(invisibleAuraInfo->Id); + } + } + else + { + m_session->SendNotification(LANG_INVISIBLE_INVISIBLE); + player->SetGMVisible(false); + if (invisibleAuraInfo) + { + player->CastSpell(player, invisibleAuraInfo, true); + } + } + + return true; +} + +bool ChatHandler::HandleGMFlyCommand(char* args) +{ + bool value; + if (!ExtractOnOff(&args, value)) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + Player* target = getSelectedPlayer(); + if (!target) + { + target = m_session->GetPlayer(); + } + + target->SetCanFly(value); + PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, GetNameLink(target).c_str(), args); + return true; +} + +bool ChatHandler::HandleGMListIngameCommand(char* /*args*/) +{ + std::list< std::pair > names; + sObjectAccessor.DoForAllPlayers([&names, this](Player *player) + { + AccountTypes security = player->GetSession()->GetSecurity(); + if ((player->isGameMaster() || (security > SEC_PLAYER && security <= (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_GM_LIST))) && + (!m_session || player->IsVisibleGloballyFor(m_session->GetPlayer()))) + { + names.push_back(std::make_pair(GetNameLink(player), player->isAcceptWhispers())); + } + }); + + if (!names.empty()) + { + SendSysMessage(LANG_GMS_ON_SRV); + + char const* accepts = GetMangosString(LANG_GM_ACCEPTS_WHISPER); + char const* not_accept = GetMangosString(LANG_GM_NO_WHISPER); + for (std::list >::const_iterator iter = names.begin(); iter != names.end(); ++iter) + { + PSendSysMessage("%s - %s", iter->first.c_str(), iter->second ? accepts : not_accept); + } + } + else + { + SendSysMessage(LANG_GMS_NOT_LOGGED); + } + + return true; +} + +/// Display the list of GMs +bool ChatHandler::HandleGMListFullCommand(char* /*args*/) +{ + ///- Get the accounts with GM Level >0 + QueryResult* result = LoginDatabase.Query("SELECT `username`,`gmlevel` FROM `account` WHERE `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("========================"); + delete result; + } + else + { + PSendSysMessage(LANG_GMLIST_EMPTY); + } + return true; +} + +// change standstate +bool ChatHandler::HandleModifyStandStateCommand(char* args) +{ + uint32 anim_id; + if (!ExtractUInt32(&args, anim_id)) + { + return false; + } + + if (!sEmotesStore.LookupEntry(anim_id)) + { + return false; + } + + m_session->GetPlayer()->HandleEmoteState(anim_id); + + return true; +} + + +bool ChatHandler::HandleChangeWeatherCommand(char* args) +{ + // Weather is OFF + if (!sWorld.getConfig(CONFIG_BOOL_WEATHER)) + { + SendSysMessage(LANG_WEATHER_DISABLED); + SetSentErrorMessage(true); + return false; + } + + uint32 type; + if (!ExtractUInt32(&args, type)) + { + return false; + } + + // see enum WeatherType + if (!Weather::IsValidWeatherType(type)) + { + return false; + } + + float grade; + if (!ExtractFloat(&args, grade)) + { + return false; + } + + // clamp grade from 0 to 1 + if (grade < 0.0f) + { + grade = 0.0f; + } + else if (grade > 1.0f) + { + grade = 1.0f; + } + + Player* player = m_session->GetPlayer(); + uint32 zoneId = player->GetZoneId(); + if (!sWeatherMgr.GetWeatherChances(zoneId)) + { + SendSysMessage(LANG_NO_WEATHER); + SetSentErrorMessage(true); + } + player->GetMap()->SetWeather(zoneId, (WeatherType)type, grade, false); + + return true; +} diff --git a/src/game/ChatCommands/GMTicketCommands.cpp b/src/game/ChatCommands/GMTicketCommands.cpp new file mode 100644 index 0000000000000..e2f8fb4e1274c --- /dev/null +++ b/src/game/ChatCommands/GMTicketCommands.cpp @@ -0,0 +1,485 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "World.h" +#include "GMTicketMgr.h" +#include "Mail.h" + + +// show ticket (helper) +void ChatHandler::ShowTicket(GMTicket const* ticket) +{ + std::string lastupdated = TimeToTimestampStr(ticket->GetLastUpdate()); + + std::string name; + if (!sObjectMgr.GetPlayerNameByGUID(ticket->GetPlayerGuid(), name)) + { + name = GetMangosString(LANG_UNKNOWN); + } + + std::string nameLink = playerLink(name); + + char const* response = ticket->GetResponse(); + + PSendSysMessage(LANG_COMMAND_TICKETVIEW, nameLink.c_str(), lastupdated.c_str(), ticket->GetText()); + if (strlen(response)) + { + PSendSysMessage(LANG_COMMAND_TICKETRESPONSE, ticket->GetResponse()); + } +} + +// ticket commands +bool ChatHandler::HandleTicketAcceptCommand(char* args) +{ + char* px = ExtractLiteralArg(&args); + + // ticket + if (!px) + { + return false; + } + + // ticket accept on + if (strncmp(px, "on", 3) == 0) + { + sTicketMgr.SetAcceptTickets(true); + SendSysMessage(LANG_COMMAND_TICKETS_SYSTEM_ON); + } + // ticket accept off + else if (strncmp(px, "off", 4) == 0) + { + sTicketMgr.SetAcceptTickets(false); + SendSysMessage(LANG_COMMAND_TICKETS_SYSTEM_OFF); + } + else + { + return false; + } + + return true; +} + +bool ChatHandler::HandleTicketCloseCommand(char* args) +{ + GMTicket* ticket = NULL; + + uint32 num; + if (ExtractUInt32(&args, num)) + { + if (num == 0) + { + return false; + } + + ticket = sTicketMgr.GetGMTicket(num); + + if (!ticket) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); + SetSentErrorMessage(true); + return false; + } + } + else + { + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&args, NULL, &target_guid, &target_name)) + { + return false; + } + + // ticket respond $char_name + ticket = sTicketMgr.GetGMTicket(target_guid); + + if (!ticket) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST_NAME, target_name.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + Player* pPlayer = sObjectMgr.GetPlayer(ticket->GetPlayerGuid()); + + if (!pPlayer && !sWorld.getConfig(CONFIG_BOOL_GM_TICKET_OFFLINE_CLOSING)) + { + SendSysMessage(LANG_COMMAND_TICKET_CANT_CLOSE); + return false; + } + + ticket->Close(); + + //This logic feels misplaced, but you can't have it in GMTicket? + sTicketMgr.Delete(ticket->GetPlayerGuid()); // here, ticket become invalidated and should not be used below + + PSendSysMessage(LANG_COMMAND_TICKETCLOSED_NAME, pPlayer ? pPlayer->GetName() : "an offline player"); + + return true; +} + +// del tickets +bool ChatHandler::HandleTicketDeleteCommand(char* args) +{ + char* px = ExtractLiteralArg(&args); + if (!px) + { + return false; + } + + // ticket delete all + if (strncmp(px, "all", 4) == 0) + { + sTicketMgr.DeleteAll(); + SendSysMessage(LANG_COMMAND_ALLTICKETDELETED); + return true; + } + + uint32 num; + + // ticket delete #num + if (ExtractUInt32(&px, num)) + { + if (num == 0) + { + return false; + } + + // mgr numbering tickets start from 0 + GMTicket* ticket = sTicketMgr.GetGMTicket(num); + + if (!ticket) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); + SetSentErrorMessage(true); + return false; + } + + ObjectGuid guid = ticket->GetPlayerGuid(); + + sTicketMgr.Delete(guid); + + // notify player + if (Player* pl = sObjectMgr.GetPlayer(guid)) + { + pl->GetSession()->SendGMTicketGetTicket(0x0A); + PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, GetNameLink(pl).c_str()); + } + else + { + PSendSysMessage(LANG_COMMAND_TICKETDEL); + } + + return true; + } + + // ticket delete $charName + Player* target; + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&px, &target, &target_guid, &target_name)) + { + return false; + } + + // ticket delete $charName + sTicketMgr.Delete(target_guid); + + // notify players about ticket deleting + if (target) + { + target->GetSession()->SendGMTicketGetTicket(0x0A); + } + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, nameLink.c_str()); + return true; +} + +bool ChatHandler::HandleTicketInfoCommand(char* args) +{ + size_t count = sTicketMgr.GetTicketCount(); + + if (m_session) + { + PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, GetOnOffStr(m_session->GetPlayer()->isAcceptTickets())); + } + else + { + PSendSysMessage(LANG_COMMAND_TICKETCOUNT_CONSOLE, count); + } + + return true; +} + +bool ChatHandler::HandleTicketListCommand(char* args) +{ + uint16 numToShow = std::min(uint16(sTicketMgr.GetTicketCount()), uint16(sWorld.getConfig(CONFIG_UINT32_GM_TICKET_LIST_SIZE))); + for (uint16 i = 0; i < numToShow; ++i) + { + GMTicket* ticket = sTicketMgr.GetGMTicketByOrderPos(i); + time_t lastChanged = time_t(ticket->GetLastUpdate()); + PSendSysMessage(LANG_COMMAND_TICKET_OFFLINE_INFO, ticket->GetId(), ticket->GetPlayerGuid().GetCounter(), ticket->HasResponse() ? "+" : "-", ctime(&lastChanged)); + } + + PSendSysMessage(LANG_COMMAND_TICKET_COUNT_ALL, numToShow, sTicketMgr.GetTicketCount()); + return true; +} + +bool ChatHandler::HandleTicketOnlineListCommand(char* args) +{ + uint16 count = 0; + for (uint16 i = 0; i < sTicketMgr.GetTicketCount(); ++i) + { + GMTicket* ticket = sTicketMgr.GetGMTicketByOrderPos(i); + if (Player* player = sObjectMgr.GetPlayer(ticket->GetPlayerGuid(), true)) + { + ++count; + if (i < sWorld.getConfig(CONFIG_UINT32_GM_TICKET_LIST_SIZE)) + { + time_t lastChanged = time_t(ticket->GetLastUpdate()); + PSendSysMessage(LANG_COMMAND_TICKET_BRIEF_INFO, ticket->GetId(), player->GetName(), ticket->HasResponse() ? "+" : "-", ctime(&lastChanged)); + } + } + } + + PSendSysMessage(LANG_COMMAND_TICKET_COUNT_ONLINE, std::min(count, uint16(sWorld.getConfig(CONFIG_UINT32_GM_TICKET_LIST_SIZE))), count); + return true; +} + +bool ChatHandler::HandleTicketMeAcceptCommand(char* args) +{ + char* px = ExtractLiteralArg(&args); + if (!px) + { + PSendSysMessage(LANG_COMMAND_TICKET_ACCEPT_STATE, m_session->GetPlayer()->isAcceptTickets() ? "on" : "off"); + return true; + } + + if (!m_session) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // ticket on + if (strncmp(px, "on", 3) == 0) + { + m_session->GetPlayer()->SetAcceptTicket(true); + SendSysMessage(LANG_COMMAND_TICKETON); + } + // ticket off + else if (strncmp(px, "off", 4) == 0) + { + m_session->GetPlayer()->SetAcceptTicket(false); + SendSysMessage(LANG_COMMAND_TICKETOFF); + } + else + { + return false; + } + + return true; +} + +bool ChatHandler::HandleTicketRespondCommand(char* args) +{ + GMTicket* ticket = NULL; + + // ticket respond #num + uint32 num; + if (ExtractUInt32(&args, num)) + { + if (num == 0) + { + return false; + } + + // mgr numbering tickets start from 0 + ticket = sTicketMgr.GetGMTicket(num); + + if (!ticket) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); + SetSentErrorMessage(true); + return false; + } + } + else + { + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&args, NULL, &target_guid, &target_name)) + { + return false; + } + + // ticket respond $char_name + ticket = sTicketMgr.GetGMTicket(target_guid); + + if (!ticket) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST_NAME, target_name.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + // no response text? + if (!*args) + { + return false; + } + + ticket->SetResponseText(args); + + if (Player* pl = sObjectMgr.GetPlayer(ticket->GetPlayerGuid())) + { + pl->GetSession()->SendGMTicketGetTicket(0x06, ticket); + //How should we error here? + if (m_session) + { + m_session->GetPlayer()->Whisper(args, LANG_UNIVERSAL, pl->GetObjectGuid()); + } + } + + return true; +} + +bool ChatHandler::HandleTicketShowCommand(char* args) +{ + // ticket #num + char* px = ExtractLiteralArg(&args); + if (!px) + { + return false; + } + + uint32 num; + if (ExtractUInt32(&px, num)) + { + if (num == 0) + { + return false; + } + + // mgr numbering tickets start from 0 + GMTicket* ticket = sTicketMgr.GetGMTicket(num); + if (!ticket) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); + SetSentErrorMessage(true); + return false; + } + + ShowTicket(ticket); + return true; + } + + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&px, NULL, &target_guid, &target_name)) + { + return false; + } + + // ticket $char_name + GMTicket* ticket = sTicketMgr.GetGMTicket(target_guid); + if (!ticket) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST_NAME, target_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + ShowTicket(ticket); + + return true; +} + +bool ChatHandler::HandleTickerSurveyClose(char* args) +{ + GMTicket* ticket = NULL; + + uint32 num; + if (ExtractUInt32(&args, num)) + { + if (num == 0) + { + return false; + } + + ticket = sTicketMgr.GetGMTicket(num); + + if (!ticket) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); + SetSentErrorMessage(true); + return false; + } + } + else + { + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&args, NULL, &target_guid, &target_name)) + { + return false; + } + + // ticket respond $char_name + ticket = sTicketMgr.GetGMTicket(target_guid); + + if (!ticket) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST_NAME, target_name.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + ticket->CloseWithSurvey(); + + //This needs to be before we delete the ticket + Player* pPlayer = sObjectMgr.GetPlayer(ticket->GetPlayerGuid()); + + //For now we can't close tickets for offline players, TODO + if (!pPlayer) + { + SendSysMessage(LANG_COMMAND_TICKET_CANT_CLOSE); + return false; + } + + //This logic feels misplaced, but you can't have it in GMTicket? + sTicketMgr.Delete(ticket->GetPlayerGuid()); + ticket = NULL; + + PSendSysMessage(LANG_COMMAND_TICKETCLOSED_NAME, pPlayer->GetName()); + + return true; +} \ No newline at end of file diff --git a/src/game/ChatCommands/GameObjectCommands.cpp b/src/game/ChatCommands/GameObjectCommands.cpp new file mode 100644 index 0000000000000..4a8fa672d7db3 --- /dev/null +++ b/src/game/ChatCommands/GameObjectCommands.cpp @@ -0,0 +1,615 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "G3D/Quat.h" +#include "MapManager.h" +#include "GameEventMgr.h" + + /********************************************************************** + CommandTable : gobjectCommandTable + /***********************************************************************/ + + // delete object by selection or guid +bool ChatHandler::HandleGameObjectDeleteCommand(char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + uint32 lowguid; + if (!ExtractUint32KeyFromLink(&args, "Hgameobject", lowguid)) + { + return false; + } + + if (!lowguid) + { + return false; + } + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid)) + { + obj = GetGameObjectWithGuid(lowguid, go_data->id); + } + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + if (ObjectGuid ownerGuid = obj->GetOwnerGuid()) + { + Unit* owner = sObjectAccessor.GetUnit(*m_session->GetPlayer(), ownerGuid); + if (!owner || !ownerGuid.IsPlayer()) + { + PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, obj->GetGUIDLow(), ownerGuid.GetString().c_str()); + 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(char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r + uint32 lowguid; + if (!ExtractUint32KeyFromLink(&args, "Hgameobject", lowguid)) + { + return false; + } + + if (!lowguid) + { + return false; + } + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid)) + { + obj = GetGameObjectWithGuid(lowguid, go_data->id); + } + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + float o; + if (!ExtractOptFloat(&args, o, m_session->GetPlayer()->GetOrientation())) + { + return false; + } + + // ok, let's rotate the GO around Z axis + // we first get the original rotation quaternion + // then we'll create a rotation quat describing the rotation around Z + G3D::Quat original_rot; + obj->GetQuaternion(original_rot); + + // the rotation amount around Z-axis + float deltaO = o - obj->GetOrientationFromQuat(original_rot); + + // multiplying 2 quaternions gives the final rotation + // quaternion multiplication is not commutative! + G3D::Quat final_rot = G3D::Quat(0.0f, 0.0f, sin(deltaO / 2), cos(deltaO / 2)) * original_rot; + + // quaternion multiplication gives a non-unit quat + final_rot.unitize(); + + Map* map = obj->GetMap(); + map->Remove(obj, false); //mandatory to remove GO model from m_dyn_tree + + obj->SetQuaternion(final_rot); // this will update internal model rotation matrices + obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientationFromQuat(final_rot)); + + map->Add(obj); + + obj->SaveToDB(); + obj->Refresh(); + + PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow()); + + return true; +} + +// move selected object +bool ChatHandler::HandleGameObjectMoveCommand(char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + uint32 lowguid; + if (!ExtractUint32KeyFromLink(&args, "Hgameobject", lowguid)) + { + return false; + } + + if (!lowguid) + { + return false; + } + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid)) + { + obj = GetGameObjectWithGuid(lowguid, go_data->id); + } + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + if (!*args) + { + Player* chr = m_session->GetPlayer(); + + Map* map = obj->GetMap(); + map->Remove(obj, false); + + obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation()); + obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX()); + obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY()); + obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ()); + + map->Add(obj); + } + else + { + float x; + if (!ExtractFloat(&args, x)) + { + return false; + } + + float y; + if (!ExtractFloat(&args, y)) + { + return false; + } + + float z; + if (!ExtractFloat(&args, z)) + { + return false; + } + + if (!MapManager::IsValidMapCoord(obj->GetMapId(), x, y, z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, obj->GetMapId()); + SetSentErrorMessage(true); + return false; + } + + Map* map = obj->GetMap(); + map->Remove(obj, false); + + obj->Relocate(x, y, z, obj->GetOrientation()); + obj->SetFloatValue(GAMEOBJECT_POS_X, x); + obj->SetFloatValue(GAMEOBJECT_POS_Y, y); + obj->SetFloatValue(GAMEOBJECT_POS_Z, z); + + map->Add(obj); + } + + obj->SaveToDB(); + obj->Refresh(); + + PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow()); + + return true; +} + +// spawn go +bool ChatHandler::HandleGameObjectAddCommand(char* args) +{ + // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r + uint32 id; + if (!ExtractUint32KeyFromLink(&args, "Hgameobject_entry", id)) + { + return false; + } + + if (!id) + { + return false; + } + + int32 spawntimeSecs; + if (!ExtractOptInt32(&args, spawntimeSecs, 0)) + { + return false; + } + + const GameObjectInfo* gInfo = ObjectMgr::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* plr = m_session->GetPlayer(); + float x = float(plr->GetPositionX()); + float y = float(plr->GetPositionY()); + float z = float(plr->GetPositionZ()); + float o = float(plr->GetOrientation()); + Map* map = plr->GetMap(); + + // used guids from specially reserved range (can be 0 if no free values) + uint32 db_lowGUID = sObjectMgr.GenerateStaticGameObjectLowGuid(); + if (!db_lowGUID) + { + SendSysMessage(LANG_NO_FREE_STATIC_GUID_FOR_SPAWN); + SetSentErrorMessage(true); + return false; + } + + GameObject* pGameObj = new GameObject; + if (!pGameObj->Create(db_lowGUID, gInfo->id, map, x, y, z, o)) + { + delete pGameObj; + return false; + } + + if (spawntimeSecs) + { + pGameObj->SetRespawnTime(spawntimeSecs); + } + + // fill the gameobject data and save to the db + pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + + // this will generate a new guid if the object is in an instance + if (!pGameObj->LoadFromDB(db_lowGUID, map)) + { + delete pGameObj; + return false; + } + + DEBUG_LOG(GetMangosString(LANG_GAMEOBJECT_CURRENT), gInfo->name, db_lowGUID, x, y, z, o); + + map->Add(pGameObj); + + sObjectMgr.AddGameobjectToGrid(db_lowGUID, sObjectMgr.GetGOData(db_lowGUID)); + + PSendSysMessage(LANG_GAMEOBJECT_ADD, id, gInfo->name, db_lowGUID, x, y, z); + return true; +} + +bool ChatHandler::HandleGameObjectAnimationCommand(char* args) +{ + uint32 lowguid; + if (!ExtractUInt32(&args, lowguid)) + { + return false; + } + + int type; + if (!ExtractInt32(&args, type)) + { + return false; + } + + GameObjectData const* goData = sObjectMgr.GetGOData(lowguid); + if (!goData) + { + return false; + } + + if (GameObject* go = GetGameObjectWithGuid(lowguid, goData->id)) + { + if (type < 0) + go->SendObjectDeSpawnAnim(); + else + { + go->SendGameObjectCustomAnim(uint32(type)); + } + return true; + } + return false; +} + +bool ChatHandler::HandleGameObjectLootstateCommand(char* args) +{ + uint32 lowguid; + if (!ExtractUInt32(&args, lowguid)) + { + return false; + } + + int32 type; + if (!ExtractInt32(&args, type)) + type = -1; + + GameObjectData const* goData = sObjectMgr.GetGOData(lowguid); + if (!goData) + { + return false; + } + + if (GameObject* go = GetGameObjectWithGuid(lowguid, goData->id)) + { + if (type < 0) + PSendSysMessage(LANG_GET_GAMEOBJECT_LOOTSTATE, lowguid, go->getLootState()); + else + go->SetLootState(LootState(type)); // no check for max value of "type" is intended here + return true; + } + return false; +} + +bool ChatHandler::HandleGameObjectStateCommand(char* args) +{ + uint32 lowguid; + if (!ExtractUInt32(&args, lowguid)) + { + return false; + } + + int32 type; + if (!ExtractInt32(&args, type)) + { + type = -1; + } + + GameObjectData const* goData = sObjectMgr.GetGOData(lowguid); + if (!goData) + { + return false; + } + + if (GameObject* go = GetGameObjectWithGuid(lowguid, goData->id)) + { + if (type < 0) + { + PSendSysMessage(LANG_GET_GAMEOBJECT_STATE, lowguid, go->GetGoState()); + } + else + { + go->SetGoState(GOState(type)); // no check for max value of "type" is intended here + } + return true; + } + return false; +} + +bool ChatHandler::HandleGameObjectNearCommand(char* args) +{ + float distance; + if (!ExtractOptFloat(&args, distance, 10.0f)) + { + return false; + } + + uint32 count = 0; + + Player* pl = m_session->GetPlayer(); + QueryResult* 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 = ObjectMgr::GetGameObjectInfo(entry); + + if (!gInfo) + { + continue; + } + + PSendSysMessage(LANG_GO_MIXED_LIST_CHAT, guid, PrepareStringNpcOrGoSpawnInformation(guid).c_str(), entry, guid, gInfo->name, x, y, z, mapid); + + ++count; + } + while (result->NextRow()); + + delete result; + } + + PSendSysMessage(LANG_COMMAND_NEAROBJMESSAGE, distance, count); + return true; +} + +bool ChatHandler::HandleGameObjectTargetCommand(char* args) +{ + Player* pl = m_session->GetPlayer(); + QueryResult* result; + GameEventMgr::ActiveEvents const& activeEventsList = sGameEventMgr.GetActiveEventList(); + if (*args) + { + // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r + char* cId = ExtractKeyFromLink(&args, "Hgameobject_entry"); + if (!cId) + { + return false; + } + + uint32 id; + if (ExtractUInt32(&cId, id)) + { + result = WorldDatabase.PQuery("SELECT `guid`, `id`, `position_x`, `position_y`, `position_z`, `orientation`, `map`, (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`, (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`, " + "(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", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->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; + + 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(); + pool_id = sPoolMgr.IsPartOfAPool(lowguid); + if (!pool_id || pl->GetMap()->GetPersistentState()->IsSpawnedPoolObject(lowguid)) + { + found = true; + } + } + while (result->NextRow() && (!found)); + + delete result; + + if (!found) + { + PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST, id); + return false; + } + + GameObjectInfo const* goI = ObjectMgr::GetGameObjectInfo(id); + + if (!goI) + { + PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST, id); + return false; + } + + GameObject* target = m_session->GetPlayer()->GetMap()->GetGameObject(ObjectGuid(HIGHGUID_GAMEOBJECT, id, lowguid)); + + PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o); + + if (target) + { + time_t 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()); + + ShowNpcOrGoSpawnInformation(target->GetGUIDLow()); + + if (target->GetGoType() == GAMEOBJECT_TYPE_DOOR) + { + PSendSysMessage(LANG_COMMAND_GO_STATUS_DOOR, target->GetGoState(), target->getLootState(), GetOnOffStr(target->IsCollisionEnabled()), goI->door.startOpen ? "open" : "closed"); + } + else + { + PSendSysMessage(LANG_COMMAND_GO_STATUS, target->GetGoState(), target->getLootState(), GetOnOffStr(target->IsCollisionEnabled())); + } + } + return true; +} diff --git a/src/game/ChatCommands/GuildCommands.cpp b/src/game/ChatCommands/GuildCommands.cpp new file mode 100644 index 0000000000000..5133a6dcbc569 --- /dev/null +++ b/src/game/ChatCommands/GuildCommands.cpp @@ -0,0 +1,214 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "GuildMgr.h" +#include "Guild.h" + + /********************************************************************** + CommandTable : guildCommandTable + /***********************************************************************/ + + /** \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(char* args) +{ + // guildmaster name optional + char* guildMasterStr = ExtractOptNotLastArg(&args); + + Player* target; + if (!ExtractPlayerTarget(&guildMasterStr, &target)) + { + return false; + } + + char* guildStr = ExtractQuotedArg(&args); + 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; + } + + sGuildMgr.AddGuild(guild); + return true; +} + +bool ChatHandler::HandleGuildInviteCommand(char* args) +{ + // player name optional + char* nameStr = ExtractOptNotLastArg(&args); + + // if not guild name only (in "") then player name + ObjectGuid target_guid; + if (!ExtractPlayerTarget(&nameStr, NULL, &target_guid)) + { + return false; + } + + char* guildStr = ExtractQuotedArg(&args); + if (!guildStr) + { + return false; + } + + std::string glName = guildStr; + Guild* targetGuild = sGuildMgr.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(char* args) +{ + Player* target; + ObjectGuid target_guid; + if (!ExtractPlayerTarget(&args, &target, &target_guid)) + { + return false; + } + + uint32 glId = target ? target->GetGuildId() : Player::GetGuildIdFromDB(target_guid); + if (!glId) + { + return false; + } + + Guild* targetGuild = sGuildMgr.GetGuildById(glId); + if (!targetGuild) + { + return false; + } + + if (targetGuild->DelMember(target_guid)) + { + targetGuild->Disband(); + delete targetGuild; + } + + return true; +} + +bool ChatHandler::HandleGuildRankCommand(char* args) +{ + char* nameStr = ExtractOptNotLastArg(&args); + + Player* target; + ObjectGuid 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 = sGuildMgr.GetGuildById(glId); + if (!targetGuild) + { + return false; + } + + uint32 newrank; + if (!ExtractUInt32(&args, newrank)) + { + return false; + } + + if (newrank > targetGuild->GetLowestRank()) + { + return false; + } + + MemberSlot* slot = targetGuild->GetMemberSlot(target_guid); + if (!slot) + { + return false; + } + + slot->ChangeRank(newrank); + return true; +} + +bool ChatHandler::HandleGuildDeleteCommand(char* args) +{ + if (!*args) + { + return false; + } + + char* guildStr = ExtractQuotedArg(&args); + if (!guildStr) + { + return false; + } + + std::string gld = guildStr; + + Guild* targetGuild = sGuildMgr.GetGuildByName(gld); + if (!targetGuild) + { + return false; + } + + targetGuild->Disband(); + delete targetGuild; + + return true; +} diff --git a/src/game/ChatCommands/InstanceCommands.cpp b/src/game/ChatCommands/InstanceCommands.cpp new file mode 100644 index 0000000000000..36abe3cbfff30 --- /dev/null +++ b/src/game/ChatCommands/InstanceCommands.cpp @@ -0,0 +1,185 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "MapManager.h" +#include "InstanceData.h" + + /********************************************************************** + CommandTable : instanceCommandTable + /***********************************************************************/ + +bool ChatHandler::HandleInstanceListBindsCommand(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) + { + DungeonPersistentState* state = itr->second.state; + std::string timeleft = secsToTimeString(state->GetResetTime() - time(NULL), true); + if (const MapEntry* entry = sMapStore.LookupEntry(itr->first)) + { + PSendSysMessage("map: %d (%s) inst: %d perm: %s diff: %s canReset: %s TTR: %s", + itr->first, entry->name[GetSessionDbcLocale()], state->GetInstanceId(), itr->second.perm ? "yes" : "no", + state->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? "normal" : "heroic", state->CanReset() ? "yes" : "no", timeleft.c_str()); + } + else + PSendSysMessage("bound for a nonexistent map %u", itr->first); + ++counter; + } + } + PSendSysMessage("player binds: %d", counter); + counter = 0; + + if (Group* group = player->GetGroup()) + { + 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) + { + DungeonPersistentState* state = itr->second.state; + std::string timeleft = secsToTimeString(state->GetResetTime() - time(NULL), true); + if (const MapEntry* entry = sMapStore.LookupEntry(itr->first)) + { + PSendSysMessage("map: %d (%s) inst: %d perm: %s diff: %s canReset: %s TTR: %s", + itr->first, entry->name[GetSessionDbcLocale()], state->GetInstanceId(), itr->second.perm ? "yes" : "no", + state->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? "normal" : "heroic", state->CanReset() ? "yes" : "no", timeleft.c_str()); + } + else + PSendSysMessage("bound for a nonexistent map %u", itr->first); + ++counter; + } + } + } + PSendSysMessage("group binds: %d", counter); + + return true; +} + +bool ChatHandler::HandleInstanceUnbindCommand(char* args) +{ + if (!*args) + { + return false; + } + + Player* player = getSelectedPlayer(); + if (!player) + { + player = m_session->GetPlayer(); + } + uint32 counter = 0; + uint32 mapid = 0; + bool got_map = false; + + if (strncmp(args, "all", strlen(args)) != 0) + { + if (!isNumeric(args[0])) + { + return false; + } + + got_map = true; + mapid = atoi(args); + } + + 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 (got_map && mapid != itr->first) + { + ++itr; + continue; + } + if (itr->first != player->GetMapId()) + { + DungeonPersistentState* save = itr->second.state; + std::string timeleft = secsToTimeString(save->GetResetTime() - time(NULL), true); + + if (const MapEntry* entry = sMapStore.LookupEntry(itr->first)) + { + PSendSysMessage("unbinding map: %d (%s) inst: %d perm: %s diff: %s canReset: %s TTR: %s", + itr->first, entry->name[GetSessionDbcLocale()], save->GetInstanceId(), itr->second.perm ? "yes" : "no", + save->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str()); + } + else + { + PSendSysMessage("bound for a nonexistent map %u", itr->first); + } + player->UnbindInstance(itr, Difficulty(i)); + ++counter; + } + else + { + ++itr; + } + } + } + PSendSysMessage("instances unbound: %d", counter); + + return true; +} + +bool ChatHandler::HandleInstanceStatsCommand(char* /*args*/) +{ + PSendSysMessage("instances loaded: %d", sMapMgr.GetNumInstances()); + PSendSysMessage("players in instances: %d", sMapMgr.GetNumPlayersInInstances()); + + uint32 numSaves, numBoundPlayers, numBoundGroups; + sMapPersistentStateMgr.GetStatistics(numSaves, numBoundPlayers, numBoundGroups); + PSendSysMessage("instance saves: %d", numSaves); + PSendSysMessage("players bound: %d", numBoundPlayers); + PSendSysMessage("groups bound: %d", numBoundGroups); + return true; +} + +bool ChatHandler::HandleInstanceSaveDataCommand(char* /*args*/) +{ + Player* pl = m_session->GetPlayer(); + + Map* map = pl->GetMap(); + + InstanceData* iData = map->GetInstanceData(); + if (!iData) + { + PSendSysMessage("Map has no instance data."); + SetSentErrorMessage(true); + return false; + } + + iData->SaveToDB(); + return true; +} + diff --git a/src/game/ChatCommands/Level0.cpp b/src/game/ChatCommands/Level0.cpp deleted file mode 100644 index 3d7a76d0aea18..0000000000000 --- a/src/game/ChatCommands/Level0.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/** - * MaNGOS is a full featured server for World of Warcraft, supporting - * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 - * - * Copyright (C) 2005-2020 MaNGOS - * - * 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 - * - * World of Warcraft, and all World of Warcraft or Warcraft art, images, - * and lore are copyrighted by Blizzard Entertainment, Inc. - */ - -#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 "ScriptMgr.h" -#include "SystemConfig.h" -#include "revision.h" -#include "Util.h" - -bool ChatHandler::HandleHelpCommand(char* args) -{ - if (!*args) - { - ShowHelpForCommand(getCommandTable(), "help"); - ShowHelpForCommand(getCommandTable(), ""); - } - else - { - if (!ShowHelpForCommand(getCommandTable(), args)) - { - SendSysMessage(LANG_NO_CMD); - } - } - - return true; -} - -bool ChatHandler::HandleCommandsCommand(char* /*args*/) -{ - ShowHelpForCommand(getCommandTable(), ""); - return true; -} - -bool ChatHandler::HandleAccountCommand(char* args) -{ - // let show subcommands at unexpected data in args - if (*args) - { - return false; - } - - AccountTypes gmlevel = GetAccessLevel(); - PSendSysMessage(LANG_ACCOUNT_LEVEL, uint32(gmlevel)); - return true; -} - -bool ChatHandler::HandleStartCommand(char* /*args*/) -{ - Player* chr = m_session->GetPlayer(); - - if (chr->IsTaxiFlying()) - { - SendSysMessage(LANG_YOU_IN_FLIGHT); - SetSentErrorMessage(true); - return false; - } - - if (chr->IsInCombat()) - { - SendSysMessage(LANG_YOU_IN_COMBAT); - SetSentErrorMessage(true); - return false; - } - - // cast spell Stuck - chr->CastSpell(chr, 7355, false); - return true; -} - -bool ChatHandler::HandleServerInfoCommand(char* /*args*/) -{ - uint32 activeClientsNum = sWorld.GetActiveSessionCount(); - uint32 queuedClientsNum = sWorld.GetQueuedSessionCount(); - uint32 maxActiveClientsNum = sWorld.GetMaxActiveSessionCount(); - uint32 maxQueuedClientsNum = sWorld.GetMaxQueuedSessionCount(); - std::string str = secsToTimeString(sWorld.GetUptime()); - - char const* full; - full = REVISION_NR; - SendSysMessage(full); - - if (sScriptMgr.IsScriptLibraryLoaded()) - { - char const* ver = sScriptMgr.GetScriptLibraryVersion(); - if (ver && *ver) - { - PSendSysMessage(LANG_USING_SCRIPT_LIB, ver); - } - else - { - SendSysMessage(LANG_USING_SCRIPT_LIB_UNKNOWN); - } - } - else - { - SendSysMessage(LANG_USING_SCRIPT_LIB_NONE); - } - - PSendSysMessage(LANG_USING_WORLD_DB, sWorld.GetDBVersion()); - PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); - PSendSysMessage(LANG_UPTIME, str.c_str()); - - return true; -} - -bool ChatHandler::HandleDismountCommand(char* /*args*/) -{ - Player* player = m_session->GetPlayer(); - - // If player is not mounted, so go out :) - if (!player->IsMounted()) - { - SendSysMessage(LANG_CHAR_NON_MOUNTED); - SetSentErrorMessage(true); - return false; - } - - if (player->IsTaxiFlying()) - { - SendSysMessage(LANG_YOU_IN_FLIGHT); - SetSentErrorMessage(true); - return false; - } - - player->Unmount(); - player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); - return true; -} - -bool ChatHandler::HandleSaveCommand(char* /*args*/) -{ - Player* player = m_session->GetPlayer(); - - // save GM account without delay and output message (testing, etc) - if (GetAccessLevel() > 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_UINT32_INTERVAL_SAVE); - if (save_interval == 0 || (save_interval > 20 * IN_MILLISECONDS && player->GetSaveTimer() <= save_interval - 20 * IN_MILLISECONDS)) - { - player->SaveToDB(); - } - - return true; -} - -bool ChatHandler::HandleGMListIngameCommand(char* /*args*/) -{ - std::list< std::pair > names; - sObjectAccessor.DoForAllPlayers([&names, this](Player *player) - { - AccountTypes security = player->GetSession()->GetSecurity(); - if ((player->isGameMaster() || (security > SEC_PLAYER && security <= (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_GM_LIST))) && - (!m_session || player->IsVisibleGloballyFor(m_session->GetPlayer()))) - { - names.push_back(std::make_pair(GetNameLink(player), player->isAcceptWhispers())); - } - }); - - if (!names.empty()) - { - SendSysMessage(LANG_GMS_ON_SRV); - - char const* accepts = GetMangosString(LANG_GM_ACCEPTS_WHISPER); - char const* not_accept = GetMangosString(LANG_GM_NO_WHISPER); - for (std::list >::const_iterator iter = names.begin(); iter != names.end(); ++iter) - { - PSendSysMessage("%s - %s", iter->first.c_str(), iter->second ? accepts : not_accept); - } - } - else - { - SendSysMessage(LANG_GMS_NOT_LOGGED); - } - - return true; -} - -bool ChatHandler::HandleAccountPasswordCommand(char* args) -{ - // allow use from RA, but not from console (not have associated account id) - if (!GetAccountId()) - { - SendSysMessage(LANG_RA_ONLY_COMMAND); - SetSentErrorMessage(true); - return false; - } - - // allow or quoted string with possible spaces or literal without spaces - char* old_pass = ExtractQuotedOrLiteralArg(&args); - char* new_pass = ExtractQuotedOrLiteralArg(&args); - char* new_pass_c = ExtractQuotedOrLiteralArg(&args); - - 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 (password_new != password_new_c) - { - SendSysMessage(LANG_NEW_PASSWORDS_NOT_MATCH); - SetSentErrorMessage(true); - return false; - } - - if (!sAccountMgr.CheckPassword(GetAccountId(), password_old)) - { - SendSysMessage(LANG_COMMAND_WRONGOLDPASSWORD); - SetSentErrorMessage(true); - return false; - } - - AccountOpResult result = sAccountMgr.ChangePassword(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; - } - - // OK, but avoid normal report for hide passwords, but log use command for anyone - LogCommand(".account password *** *** ***"); - SetSentErrorMessage(true); - return false; -} - -bool ChatHandler::HandleAccountLockCommand(char* args) -{ - // allow use from RA, but not from console (not have associated account id) - if (!GetAccountId()) - { - SendSysMessage(LANG_RA_ONLY_COMMAND); - SetSentErrorMessage(true); - return false; - } - - bool value; - if (!ExtractOnOff(&args, value)) - { - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; - } - - if (value) - { - LoginDatabase.PExecute("UPDATE `account` SET `locked` = '1' WHERE `id` = '%u'", GetAccountId()); - PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED); - } - else - { - LoginDatabase.PExecute("UPDATE `account` SET `locked` = '0' WHERE `id` = '%u'", GetAccountId()); - PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED); - } - - return true; -} - -/// Display the 'Message of the day' for the realm -bool ChatHandler::HandleServerMotdCommand(char* /*args*/) -{ - PSendSysMessage(LANG_MOTD_CURRENT, sWorld.GetMotd()); - return true; -} diff --git a/src/game/ChatCommands/Level2.cpp b/src/game/ChatCommands/Level2.cpp deleted file mode 100644 index aca9650dd4394..0000000000000 --- a/src/game/ChatCommands/Level2.cpp +++ /dev/null @@ -1,5967 +0,0 @@ -/** - * MaNGOS is a full featured server for World of Warcraft, supporting - * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 - * - * Copyright (C) 2005-2020 MaNGOS - * - * 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 - * - * World of Warcraft, and all World of Warcraft or Warcraft art, images, - * and lore are copyrighted by Blizzard Entertainment, Inc. - */ - -#include "Common.h" -#include "Database/DatabaseEnv.h" - -#include "DBCStores.h" - -#include "ObjectMgr.h" -#include "ObjectGuid.h" -#include "Item.h" -#include "Player.h" -#include "TemporarySummon.h" -#include "Totem.h" -#include "Pet.h" -#include "CreatureAI.h" -#include "GameObject.h" -#include "Opcodes.h" -#include "Chat.h" -#include "ObjectAccessor.h" -#include "MapManager.h" -#include "Language.h" -#include "World.h" -#include "GameEventMgr.h" -#include "SpellMgr.h" -#include "MapPersistentStateMgr.h" -#include "AccountMgr.h" -#include "GMTicketMgr.h" -#include "WaypointManager.h" -#include "DBCStores.h" -#include "Util.h" -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "CellImpl.h" -#include "WaypointMovementGenerator.h" -#include "Formulas.h" -#include "G3D/Quat.h" // for turning GO's -#include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand -#include "MoveMap.h" // for mmap manager -#include "PathFinder.h" // for mmap commands -#include "movement/MoveSplineInit.h" - -#include -#include -#include - -static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] = -{ - LANG_REP_HATED, LANG_REP_HOSTILE, LANG_REP_UNFRIENDLY, LANG_REP_NEUTRAL, - LANG_REP_FRIENDLY, LANG_REP_HONORED, LANG_REP_REVERED, LANG_REP_EXALTED -}; - -// mute player for some times -bool ChatHandler::HandleMuteCommand(char* args) -{ - char* nameStr = ExtractOptNotLastArg(&args); - - Player* target; - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&nameStr, &target, &target_guid, &target_name)) - { - return false; - } - - uint32 notspeaktime; - if (!ExtractUInt32(&args, notspeaktime)) - { - return false; - } - - uint32 account_id = target ? target->GetSession()->GetAccountId() : sObjectMgr.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; - } - - 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); - } - - std::string nameLink = playerLink(target_name); - - PSendSysMessage(LANG_YOU_DISABLE_CHAT, nameLink.c_str(), notspeaktime); - return true; -} - -// unmute player -bool ChatHandler::HandleUnmuteCommand(char* args) -{ - Player* target; - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) - { - return false; - } - - uint32 account_id = target ? target->GetSession()->GetAccountId() : sObjectMgr.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; -} - -void ChatHandler::ShowTriggerTargetListHelper(uint32 id, AreaTrigger const* at, bool subpart /*= false*/) -{ - if (m_session) - { - char dist_buf[50]; - if (!subpart) - { - float dist = m_session->GetPlayer()->GetDistance2d(at->target_X, at->target_Y); - snprintf(dist_buf, 50, GetMangosString(LANG_TRIGGER_DIST), dist); - } - else - { - dist_buf[0] = '\0'; - } - - PSendSysMessage(LANG_TRIGGER_TARGET_LIST_CHAT, - subpart ? " -> " : "", id, id, at->target_mapId, at->target_X, at->target_Y, at->target_Z, dist_buf); - } - else - PSendSysMessage(LANG_TRIGGER_TARGET_LIST_CONSOLE, - subpart ? " -> " : "", id, at->target_mapId, at->target_X, at->target_Y, at->target_Z); -} - -void ChatHandler::ShowTriggerListHelper(AreaTriggerEntry const* atEntry) -{ - - char const* tavern = sObjectMgr.IsTavernAreaTrigger(atEntry->id) ? GetMangosString(LANG_TRIGGER_TAVERN) : ""; - char const* quest = sObjectMgr.GetQuestForAreaTrigger(atEntry->id) ? GetMangosString(LANG_TRIGGER_QUEST) : ""; - - if (m_session) - { - float dist = m_session->GetPlayer()->GetDistance2d(atEntry->x, atEntry->y); - char dist_buf[50]; - snprintf(dist_buf, 50, GetMangosString(LANG_TRIGGER_DIST), dist); - - PSendSysMessage(LANG_TRIGGER_LIST_CHAT, - atEntry->id, atEntry->id, atEntry->mapid, atEntry->x, atEntry->y, atEntry->z, dist_buf, tavern, quest); - } - else - PSendSysMessage(LANG_TRIGGER_LIST_CONSOLE, - atEntry->id, atEntry->mapid, atEntry->x, atEntry->y, atEntry->z, tavern, quest); - - if (AreaTrigger const* at = sObjectMgr.GetAreaTrigger(atEntry->id)) - { - ShowTriggerTargetListHelper(atEntry->id, at, true); - } -} - -bool ChatHandler::HandleTriggerCommand(char* args) -{ - AreaTriggerEntry const* atEntry = NULL; - - Player* pl = m_session ? m_session->GetPlayer() : NULL; - - // select by args - if (*args) - { - uint32 atId; - if (!ExtractUint32KeyFromLink(&args, "Hareatrigger", atId)) - { - return false; - } - - if (!atId) - { - return false; - } - - atEntry = sAreaTriggerStore.LookupEntry(atId); - - if (!atEntry) - { - PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND, atId); - SetSentErrorMessage(true); - return false; - } - } - // find nearest - else - { - if (!m_session) - { - return false; - } - - float dist2 = MAP_SIZE * MAP_SIZE; - - // Search triggers - for (uint32 id = 0; id < sAreaTriggerStore.GetNumRows(); ++id) - { - AreaTriggerEntry const* atTestEntry = sAreaTriggerStore.LookupEntry(id); - if (!atTestEntry) - { - continue; - } - - if (atTestEntry->mapid != m_session->GetPlayer()->GetMapId()) - { - continue; - } - - float dx = atTestEntry->x - pl->GetPositionX(); - float dy = atTestEntry->y - pl->GetPositionY(); - - float test_dist2 = dx * dx + dy * dy; - - if (test_dist2 >= dist2) - { - continue; - } - - dist2 = test_dist2; - atEntry = atTestEntry; - } - - if (!atEntry) - { - SendSysMessage(LANG_COMMAND_NOTRIGGERFOUND); - SetSentErrorMessage(true); - return false; - } - } - - ShowTriggerListHelper(atEntry); - - int loc_idx = GetSessionDbLocaleIndex(); - - AreaTrigger const* at = sObjectMgr.GetAreaTrigger(atEntry->id); - if (at) - { - PSendSysMessage(LANG_TRIGGER_REQ_LEVEL, at->requiredLevel); - } - - if (uint32 quest_id = sObjectMgr.GetQuestForAreaTrigger(atEntry->id)) - { - SendSysMessage(LANG_TRIGGER_EXPLORE_QUEST); - ShowQuestListHelper(quest_id, loc_idx, pl); - } - - if (at) - { - if (at->requiredItem || at->requiredItem2) - { - SendSysMessage(LANG_TRIGGER_REQ_ITEMS); - - if (at->requiredItem) - { - ShowItemListHelper(at->requiredItem, loc_idx, pl); - } - if (at->requiredItem2) - { - ShowItemListHelper(at->requiredItem2, loc_idx, pl); - } - } - - if (at->requiredQuest) - { - SendSysMessage(LANG_TRIGGER_REQ_QUEST); - ShowQuestListHelper(at->requiredQuest, loc_idx, pl); - } - - if (at->heroicKey || at->heroicKey2) - { - SendSysMessage(LANG_TRIGGER_REQ_KEYS_HEROIC); - - if (at->heroicKey) - { - ShowItemListHelper(at->heroicKey, loc_idx, pl); - } - if (at->heroicKey2) - { - ShowItemListHelper(at->heroicKey2, loc_idx, pl); - } - } - } - - return true; -} - -bool ChatHandler::HandleTriggerActiveCommand(char* /*args*/) -{ - uint32 counter = 0; // Counter for figure out that we found smth. - - Player* pl = m_session->GetPlayer(); - - // Search in AreaTable.dbc - for (uint32 id = 0; id < sAreaTriggerStore.GetNumRows(); ++id) - { - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(id); - if (!atEntry) - { - continue; - } - - if (!IsPointInAreaTriggerZone(atEntry, pl->GetMapId(), pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ())) - { - continue; - } - - ShowTriggerListHelper(atEntry); - - ++counter; - } - - if (counter == 0) // if counter == 0 then we found nth - { - SendSysMessage(LANG_COMMAND_NOTRIGGERFOUND); - } - - return true; -} - -bool ChatHandler::HandleTriggerNearCommand(char* args) -{ - float distance = (!*args) ? 10.0f : (float)atof(args); - float dist2 = distance * distance; - uint32 counter = 0; // Counter for figure out that we found smth. - - Player* pl = m_session->GetPlayer(); - - // Search triggers - for (uint32 id = 0; id < sAreaTriggerStore.GetNumRows(); ++id) - { - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(id); - if (!atEntry) - { - continue; - } - - if (atEntry->mapid != m_session->GetPlayer()->GetMapId()) - { - continue; - } - - float dx = atEntry->x - pl->GetPositionX(); - float dy = atEntry->y - pl->GetPositionY(); - - if (dx * dx + dy * dy > dist2) - { - continue; - } - - ShowTriggerListHelper(atEntry); - - ++counter; - } - - // Search trigger targets - for (uint32 id = 0; id < sAreaTriggerStore.GetNumRows(); ++id) - { - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(id); - if (!atEntry) - { - continue; - } - - AreaTrigger const* at = sObjectMgr.GetAreaTrigger(atEntry->id); - if (!at) - { - continue; - } - - if (at->target_mapId != m_session->GetPlayer()->GetMapId()) - { - continue; - } - - float dx = at->target_X - pl->GetPositionX(); - float dy = at->target_Y - pl->GetPositionY(); - - if (dx * dx + dy * dy > dist2) - { - continue; - } - - ShowTriggerTargetListHelper(atEntry->id, at); - - ++counter; - } - - if (counter == 0) // if counter == 0 then we found nth - { - SendSysMessage(LANG_COMMAND_NOTRIGGERFOUND); - } - - return true; -} - -static char const* const areatriggerKeys[] = -{ - "Hareatrigger", - "Hareatrigger_target", - NULL -}; - -bool ChatHandler::HandleGoTriggerCommand(char* args) -{ - Player* _player = m_session->GetPlayer(); - - if (!*args) - { - return false; - } - - char* atIdStr = ExtractKeyFromLink(&args, areatriggerKeys); - if (!atIdStr) - { - return false; - } - - uint32 atId; - if (!ExtractUInt32(&atIdStr, atId)) - { - return false; - } - - if (!atId) - { - return false; - } - - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(atId); - if (!atEntry) - { - PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND, atId); - SetSentErrorMessage(true); - return false; - } - - bool to_target = ExtractLiteralArg(&args, "target"); - if (!to_target && *args) // can be fail also at syntax error - { - return false; - } - - if (to_target) - { - AreaTrigger const* at = sObjectMgr.GetAreaTrigger(atId); - if (!at) - { - PSendSysMessage(LANG_AREATRIGER_NOT_HAS_TARGET, atId); - SetSentErrorMessage(true); - return false; - } - - return HandleGoHelper(_player, at->target_mapId, at->target_X, at->target_Y, &at->target_Z); - } - else - { - return HandleGoHelper(_player, atEntry->mapid, atEntry->x, atEntry->y, &atEntry->z); - } -} - -bool ChatHandler::HandleGoGraveyardCommand(char* args) -{ - Player* _player = m_session->GetPlayer(); - - uint32 gyId; - if (!ExtractUInt32(&args, gyId)) - { - return false; - } - - WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(gyId); - if (!gy) - { - PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST, gyId); - SetSentErrorMessage(true); - return false; - } - - return HandleGoHelper(_player, gy->map_id, gy->x, gy->y, &gy->z); -} - -enum CreatureLinkType -{ - CREATURE_LINK_RAW = -1, // non-link case - CREATURE_LINK_GUID = 0, - CREATURE_LINK_ENTRY = 1, -}; - -static char const* const creatureKeys[] = -{ - "Hcreature", - "Hcreature_entry", - NULL -}; - -/** \brief Teleport the GM to the specified creature -* -* .go creature --> TP using creature.guid -* .go creature 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. -* .go creature 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(char* args) -{ - if (!*args) - { - return false; - } - - Player* _player = m_session->GetPlayer(); - - // "id" or number or [name] Shift-click form |color|Hcreature:creature_id|h[name]|h|r - int crType; - char* pParam1 = ExtractKeyFromLink(&args, creatureKeys, &crType); - if (!pParam1) - { - return false; - } - - // User wants to teleport to the NPC's template entry - if (crType == CREATURE_LINK_RAW && strcmp(pParam1, "id") == 0) - { - // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r - pParam1 = ExtractKeyFromLink(&args, "Hcreature_entry"); - if (!pParam1) - { - return false; - } - - crType = CREATURE_LINK_ENTRY; - } - - CreatureData const* data = NULL; - - switch (crType) - { - case CREATURE_LINK_ENTRY: - { - uint32 tEntry; - if (!ExtractUInt32(&pParam1, tEntry)) - { - return false; - } - - if (!tEntry) - { - return false; - } - - if (!ObjectMgr::GetCreatureTemplate(tEntry)) - { - SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); - SetSentErrorMessage(true); - return false; - } - - FindCreatureData worker(tEntry, m_session ? m_session->GetPlayer() : NULL); - - sObjectMgr.DoCreatureData(worker); - - CreatureDataPair const* dataPair = worker.GetResult(); - if (!dataPair) - { - SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); - SetSentErrorMessage(true); - return false; - } - - data = &dataPair->second; - break; - } - case CREATURE_LINK_GUID: - { - uint32 lowguid; - if (!ExtractUInt32(&pParam1, lowguid)) - { - return false; - } - - data = sObjectMgr.GetCreatureData(lowguid); - if (!data) - { - SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); - SetSentErrorMessage(true); - return false; - } - break; - } - case CREATURE_LINK_RAW: - { - uint32 lowguid; - if (ExtractUInt32(&pParam1, lowguid)) - { - data = sObjectMgr.GetCreatureData(lowguid); - if (!data) - { - SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); - SetSentErrorMessage(true); - return false; - } - } - // Number is invalid - maybe the user specified the mob's name - else - { - std::string name = pParam1; - WorldDatabase.escape_string(name); - QueryResult* result = WorldDatabase.PQuery("SELECT `guid` FROM `creature`, `creature_template` WHERE `creature`.`id` = `creature_template`.`entry` AND `creature_template`.`name` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), name.c_str()); - if (!result) - { - SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); - SetSentErrorMessage(true); - return false; - } - - FindCreatureData worker(0, m_session ? m_session->GetPlayer() : NULL); - - do - { - Field* fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - - CreatureDataPair const* cr_data = sObjectMgr.GetCreatureDataPair(guid); - if (!cr_data) - { - continue; - } - - worker(*cr_data); - } - while (result->NextRow()); - - delete result; - - CreatureDataPair const* dataPair = worker.GetResult(); - if (!dataPair) - { - SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); - SetSentErrorMessage(true); - return false; - } - - data = &dataPair->second; - } - break; - } - } - - return HandleGoHelper(_player, data->mapid, data->posX, data->posY, &data->posZ); -} - -enum GameobjectLinkType -{ - GAMEOBJECT_LINK_RAW = -1, // non-link case - GAMEOBJECT_LINK_GUID = 0, - GAMEOBJECT_LINK_ENTRY = 1, -}; - -static char const* const gameobjectKeys[] = -{ - "Hgameobject", - "Hgameobject_entry", - NULL -}; - -// teleport to gameobject -bool ChatHandler::HandleGoObjectCommand(char* args) -{ - Player* _player = m_session->GetPlayer(); - - // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r - int goType; - char* pParam1 = ExtractKeyFromLink(&args, gameobjectKeys, &goType); - if (!pParam1) - { - return false; - } - - // User wants to teleport to the GO's template entry - if (goType == GAMEOBJECT_LINK_RAW && strcmp(pParam1, "id") == 0) - { - // number or [name] Shift-click form |color|Hgameobject_entry:creature_id|h[name]|h|r - pParam1 = ExtractKeyFromLink(&args, "Hgameobject_entry"); - if (!pParam1) - { - return false; - } - - goType = GAMEOBJECT_LINK_ENTRY; - } - - GameObjectData const* data = NULL; - - switch (goType) - { - case CREATURE_LINK_ENTRY: - { - uint32 tEntry; - if (!ExtractUInt32(&pParam1, tEntry)) - { - return false; - } - - if (!tEntry) - { - return false; - } - - if (!ObjectMgr::GetGameObjectInfo(tEntry)) - { - SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); - SetSentErrorMessage(true); - return false; - } - - FindGOData worker(tEntry, m_session ? m_session->GetPlayer() : NULL); - - sObjectMgr.DoGOData(worker); - - GameObjectDataPair const* dataPair = worker.GetResult(); - - if (!dataPair) - { - SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); - SetSentErrorMessage(true); - return false; - } - - data = &dataPair->second; - break; - } - case GAMEOBJECT_LINK_GUID: - { - uint32 lowguid; - if (!ExtractUInt32(&pParam1, lowguid)) - { - return false; - } - - // by DB guid - data = sObjectMgr.GetGOData(lowguid); - if (!data) - { - SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); - SetSentErrorMessage(true); - return false; - } - break; - } - case GAMEOBJECT_LINK_RAW: - { - uint32 lowguid; - if (ExtractUInt32(&pParam1, lowguid)) - { - // by DB guid - data = sObjectMgr.GetGOData(lowguid); - if (!data) - { - SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); - SetSentErrorMessage(true); - return false; - } - } - else - { - std::string name = pParam1; - WorldDatabase.escape_string(name); - QueryResult* result = WorldDatabase.PQuery("SELECT `guid` FROM `gameobject`, `gameobject_template` WHERE `gameobject`.`id` = `gameobject_template`.`entry` AND `gameobject_template`.`name `" _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), name.c_str()); - if (!result) - { - SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); - SetSentErrorMessage(true); - return false; - } - - FindGOData worker(0, m_session ? m_session->GetPlayer() : NULL); - - do - { - Field* fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - - GameObjectDataPair const* go_data = sObjectMgr.GetGODataPair(guid); - if (!go_data) - { - continue; - } - - worker(*go_data); - } - while (result->NextRow()); - - delete result; - - GameObjectDataPair const* dataPair = worker.GetResult(); - if (!dataPair) - { - SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); - SetSentErrorMessage(true); - return false; - } - - data = &dataPair->second; - } - break; - } - } - - return HandleGoHelper(_player, data->mapid, data->posX, data->posY, &data->posZ); -} - -bool ChatHandler::HandleGameObjectTargetCommand(char* args) -{ - Player* pl = m_session->GetPlayer(); - QueryResult* result; - GameEventMgr::ActiveEvents const& activeEventsList = sGameEventMgr.GetActiveEventList(); - if (*args) - { - // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r - char* cId = ExtractKeyFromLink(&args, "Hgameobject_entry"); - if (!cId) - { - return false; - } - - uint32 id; - if (ExtractUInt32(&cId, id)) - { - result = WorldDatabase.PQuery("SELECT `guid`, `id`, `position_x`, `position_y`, `position_z`, `orientation`, `map`, (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`, (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`, " - "(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", - pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->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; - - 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(); - pool_id = sPoolMgr.IsPartOfAPool(lowguid); - if (!pool_id || pl->GetMap()->GetPersistentState()->IsSpawnedPoolObject(lowguid)) - { - found = true; - } - } - while (result->NextRow() && (!found)); - - delete result; - - if (!found) - { - PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST, id); - return false; - } - - GameObjectInfo const* goI = ObjectMgr::GetGameObjectInfo(id); - - if (!goI) - { - PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST, id); - return false; - } - - GameObject* target = m_session->GetPlayer()->GetMap()->GetGameObject(ObjectGuid(HIGHGUID_GAMEOBJECT, id, lowguid)); - - PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o); - - if (target) - { - time_t 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()); - - ShowNpcOrGoSpawnInformation(target->GetGUIDLow()); - - if (target->GetGoType() == GAMEOBJECT_TYPE_DOOR) - { - PSendSysMessage(LANG_COMMAND_GO_STATUS_DOOR, target->GetGoState(), target->getLootState(), GetOnOffStr(target->IsCollisionEnabled()), goI->door.startOpen ? "open" : "closed"); - } - else - { - PSendSysMessage(LANG_COMMAND_GO_STATUS, target->GetGoState(), target->getLootState(), GetOnOffStr(target->IsCollisionEnabled())); - } - } - return true; -} - -// delete object by selection or guid -bool ChatHandler::HandleGameObjectDeleteCommand(char* args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r - uint32 lowguid; - if (!ExtractUint32KeyFromLink(&args, "Hgameobject", lowguid)) - { - return false; - } - - if (!lowguid) - { - return false; - } - - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid)) - { - obj = GetGameObjectWithGuid(lowguid, go_data->id); - } - - if (!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - if (ObjectGuid ownerGuid = obj->GetOwnerGuid()) - { - Unit* owner = sObjectAccessor.GetUnit(*m_session->GetPlayer(), ownerGuid); - if (!owner || !ownerGuid.IsPlayer()) - { - PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, obj->GetGUIDLow(), ownerGuid.GetString().c_str()); - 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(char* args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r - uint32 lowguid; - if (!ExtractUint32KeyFromLink(&args, "Hgameobject", lowguid)) - { - return false; - } - - if (!lowguid) - { - return false; - } - - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid)) - { - obj = GetGameObjectWithGuid(lowguid, go_data->id); - } - - if (!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - float o; - if (!ExtractOptFloat(&args, o, m_session->GetPlayer()->GetOrientation())) - { - return false; - } - - // ok, let's rotate the GO around Z axis - // we first get the original rotation quaternion - // then we'll create a rotation quat describing the rotation around Z - G3D::Quat original_rot; - obj->GetQuaternion(original_rot); - - // the rotation amount around Z-axis - float deltaO = o - obj->GetOrientationFromQuat(original_rot); - - // multiplying 2 quaternions gives the final rotation - // quaternion multiplication is not commutative! - G3D::Quat final_rot = G3D::Quat(0.0f, 0.0f, sin(deltaO/2), cos(deltaO/2)) * original_rot; - - // quaternion multiplication gives a non-unit quat - final_rot.unitize(); - - Map* map = obj->GetMap(); - map->Remove(obj, false); //mandatory to remove GO model from m_dyn_tree - - obj->SetQuaternion(final_rot); // this will update internal model rotation matrices - obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientationFromQuat(final_rot)); - - map->Add(obj); - - obj->SaveToDB(); - obj->Refresh(); - - PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow()); - - return true; -} - -// move selected object -bool ChatHandler::HandleGameObjectMoveCommand(char* args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r - uint32 lowguid; - if (!ExtractUint32KeyFromLink(&args, "Hgameobject", lowguid)) - { - return false; - } - - if (!lowguid) - { - return false; - } - - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid)) - { - obj = GetGameObjectWithGuid(lowguid, go_data->id); - } - - if (!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - if (!*args) - { - Player* chr = m_session->GetPlayer(); - - Map* map = obj->GetMap(); - map->Remove(obj, false); - - obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation()); - obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX()); - obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY()); - obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ()); - - map->Add(obj); - } - else - { - float x; - if (!ExtractFloat(&args, x)) - { - return false; - } - - float y; - if (!ExtractFloat(&args, y)) - { - return false; - } - - float z; - if (!ExtractFloat(&args, z)) - { - return false; - } - - if (!MapManager::IsValidMapCoord(obj->GetMapId(), x, y, z)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, obj->GetMapId()); - SetSentErrorMessage(true); - return false; - } - - Map* map = obj->GetMap(); - map->Remove(obj, false); - - obj->Relocate(x, y, z, obj->GetOrientation()); - obj->SetFloatValue(GAMEOBJECT_POS_X, x); - obj->SetFloatValue(GAMEOBJECT_POS_Y, y); - obj->SetFloatValue(GAMEOBJECT_POS_Z, z); - - map->Add(obj); - } - - obj->SaveToDB(); - obj->Refresh(); - - PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow()); - - return true; -} - -// spawn go -bool ChatHandler::HandleGameObjectAddCommand(char* args) -{ - // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r - uint32 id; - if (!ExtractUint32KeyFromLink(&args, "Hgameobject_entry", id)) - { - return false; - } - - if (!id) - { - return false; - } - - int32 spawntimeSecs; - if (!ExtractOptInt32(&args, spawntimeSecs, 0)) - { - return false; - } - - const GameObjectInfo* gInfo = ObjectMgr::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* plr = m_session->GetPlayer(); - float x = float(plr->GetPositionX()); - float y = float(plr->GetPositionY()); - float z = float(plr->GetPositionZ()); - float o = float(plr->GetOrientation()); - Map* map = plr->GetMap(); - - // used guids from specially reserved range (can be 0 if no free values) - uint32 db_lowGUID = sObjectMgr.GenerateStaticGameObjectLowGuid(); - if (!db_lowGUID) - { - SendSysMessage(LANG_NO_FREE_STATIC_GUID_FOR_SPAWN); - SetSentErrorMessage(true); - return false; - } - - GameObject* pGameObj = new GameObject; - if (!pGameObj->Create(db_lowGUID, gInfo->id, map, x, y, z, o)) - { - delete pGameObj; - return false; - } - - if (spawntimeSecs) - { - pGameObj->SetRespawnTime(spawntimeSecs); - } - - // fill the gameobject data and save to the db - pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); - - // this will generate a new guid if the object is in an instance - if (!pGameObj->LoadFromDB(db_lowGUID, map)) - { - delete pGameObj; - return false; - } - - DEBUG_LOG(GetMangosString(LANG_GAMEOBJECT_CURRENT), gInfo->name, db_lowGUID, x, y, z, o); - - map->Add(pGameObj); - - sObjectMgr.AddGameobjectToGrid(db_lowGUID, sObjectMgr.GetGOData(db_lowGUID)); - - PSendSysMessage(LANG_GAMEOBJECT_ADD, id, gInfo->name, db_lowGUID, x, y, z); - return true; -} - -bool ChatHandler::HandleGameObjectAnimationCommand(char* args) -{ - uint32 lowguid; - if (!ExtractUInt32(&args, lowguid)) - { - return false; - } - - int type; - if (!ExtractInt32(&args, type)) - { - return false; - } - - GameObjectData const *goData = sObjectMgr.GetGOData(lowguid); - if (!goData) - { - return false; - } - - if (GameObject *go = GetGameObjectWithGuid(lowguid, goData->id)) - { - if (type < 0) - go->SendObjectDeSpawnAnim(); - else - { - go->SendGameObjectCustomAnim(uint32(type)); - } - return true; - } - return false; -} - -bool ChatHandler::HandleGameObjectLootstateCommand(char* args) -{ - uint32 lowguid; - if (!ExtractUInt32(&args, lowguid)) - { - return false; - } - - int32 type; - if (!ExtractInt32(&args, type)) - { - type = -1; - } - - GameObjectData const *goData = sObjectMgr.GetGOData(lowguid); - if (!goData) - { - return false; - } - - if (GameObject *go = GetGameObjectWithGuid(lowguid, goData->id)) - { - if (type < 0) - { - PSendSysMessage(LANG_GET_GAMEOBJECT_LOOTSTATE, lowguid, go->getLootState()); - } - else - go->SetLootState(LootState(type)); // no check for max value of "type" is intended here - return true; - } - return false; -} - -bool ChatHandler::HandleGameObjectStateCommand(char* args) -{ - uint32 lowguid; - if (!ExtractUInt32(&args, lowguid)) - { - return false; - } - - int32 type; - if (!ExtractInt32(&args, type)) - { - type = -1; - } - - GameObjectData const *goData = sObjectMgr.GetGOData(lowguid); - if (!goData) - { - return false; - } - - if (GameObject *go = GetGameObjectWithGuid(lowguid, goData->id)) - { - if (type < 0) - { - PSendSysMessage(LANG_GET_GAMEOBJECT_STATE, lowguid, go->GetGoState()); - } - else - { - go->SetGoState(GOState(type)); // no check for max value of "type" is intended here - } - return true; - } - return false; -} - -bool ChatHandler::HandleGameObjectNearCommand(char* args) -{ - float distance; - if (!ExtractOptFloat(&args, distance, 10.0f)) - { - return false; - } - - uint32 count = 0; - - Player* pl = m_session->GetPlayer(); - QueryResult* 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 = ObjectMgr::GetGameObjectInfo(entry); - - if (!gInfo) - { - continue; - } - - PSendSysMessage(LANG_GO_MIXED_LIST_CHAT, guid, PrepareStringNpcOrGoSpawnInformation(guid).c_str(), entry, guid, gInfo->name, x, y, z, mapid); - - ++count; - } - while (result->NextRow()); - - delete result; - } - - PSendSysMessage(LANG_COMMAND_NEAROBJMESSAGE, distance, count); - return true; -} - -bool ChatHandler::HandleGUIDCommand(char* /*args*/) -{ - ObjectGuid guid = m_session->GetPlayer()->GetSelectionGuid(); - - if (!guid) - { - SendSysMessage(LANG_NO_SELECTION); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_OBJECT_GUID, guid.GetString().c_str()); - return true; -} - -void ChatHandler::ShowFactionListHelper(FactionEntry const* factionEntry, LocaleConstant loc, FactionState const* repState /*= NULL*/, Player* target /*= NULL */) -{ - std::string name = factionEntry->name[loc]; - // 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 << factionEntry->ID << " - |cffffffff|Hfaction:" << factionEntry->ID << "|h[" << name << " " << localeNames[loc] << "]|h|r"; - } - else - { - ss << factionEntry->ID << " - " << name << " " << localeNames[loc]; - } - - if (repState) // and then target!=NULL also - { - ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); - std::string rankName = GetMangosString(ReputationRankStrIndex[rank]); - - ss << " " << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ")"; - - if (repState->Flags & FACTION_FLAG_VISIBLE) - { - ss << GetMangosString(LANG_FACTION_VISIBLE); - } - if (repState->Flags & FACTION_FLAG_AT_WAR) - { - ss << GetMangosString(LANG_FACTION_ATWAR); - } - if (repState->Flags & FACTION_FLAG_PEACE_FORCED) - { - ss << GetMangosString(LANG_FACTION_PEACE_FORCED); - } - if (repState->Flags & FACTION_FLAG_HIDDEN) - { - ss << GetMangosString(LANG_FACTION_HIDDEN); - } - if (repState->Flags & FACTION_FLAG_INVISIBLE_FORCED) - { - ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED); - } - if (repState->Flags & FACTION_FLAG_INACTIVE) - { - ss << GetMangosString(LANG_FACTION_INACTIVE); - } - } - else if (target) - { - ss << GetMangosString(LANG_FACTION_NOREPUTATION); - } - - SendSysMessage(ss.str().c_str()); -} - -bool ChatHandler::HandleLookupFactionCommand(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); - - uint32 counter = 0; // Counter for figure out that we found smth. - - for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id) - { - FactionEntry const* factionEntry = sFactionStore.LookupEntry(id); - if (factionEntry) - { - 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) - { - FactionState const* repState = target ? target->GetReputationMgr().GetState(factionEntry) : NULL; - ShowFactionListHelper(factionEntry, LocaleConstant(loc), repState, target); - ++counter; - } - } - } - - if (counter == 0) // if counter == 0 then we found nth - { - SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND); - } - return true; -} - -bool ChatHandler::HandleModifyRepCommand(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)) - { - return false; - } - - uint32 factionId; - if (!ExtractUint32KeyFromLink(&args, "Hfaction", factionId)) - { - return false; - } - - if (!factionId) - { - return false; - } - - int32 amount = 0; - if (!ExtractInt32(&args, amount)) - { - char* rankTxt = ExtractLiteralArg(&args); - if (!rankTxt) - { - return false; - } - - 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 = GetMangosString(ReputationRankStrIndex[r]); - if (rank.empty()) - { - continue; - } - - std::wstring wrank; - if (!Utf8toWStr(rank, wrank)) - { - continue; - } - - wstrToLower(wrank); - - if (wrank.substr(0, wrankStr.size()) == wrankStr) - { - int32 delta; - if (!ExtractOptInt32(&args, delta, 0) || (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(char* args) -{ - if (!*args) - { - return false; - } - - uint32 id; - if (!ExtractUint32KeyFromLink(&args, "Hcreature_entry", id)) - { - return false; - } - - CreatureInfo const* cinfo = ObjectMgr::GetCreatureTemplate(id); - if (!cinfo) - { - PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, id); - SetSentErrorMessage(true); - return false; - } - - Player* chr = m_session->GetPlayer(); - CreatureCreatePos pos(chr, chr->GetOrientation()); - Map* map = chr->GetMap(); - - Creature* pCreature = new Creature; - - // used guids from specially reserved range (can be 0 if no free values) - uint32 lowguid = sObjectMgr.GenerateStaticCreatureLowGuid(); - if (!lowguid) - { - SendSysMessage(LANG_NO_FREE_STATIC_GUID_FOR_SPAWN); - SetSentErrorMessage(true); - return false; - } - - if (!pCreature->Create(lowguid, pos, cinfo)) - { - delete pCreature; - return false; - } - - pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); - - uint32 db_guid = pCreature->GetGUIDLow(); - - // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); - pCreature->LoadFromDB(db_guid, map); - - return true; -} - -// add item in vendorlist -bool ChatHandler::HandleNpcAddVendorItemCommand(char* args) -{ - uint32 itemId; - if (!ExtractUint32KeyFromLink(&args, "Hitem", itemId)) - { - SendSysMessage(LANG_COMMAND_NEEDITEMSEND); - SetSentErrorMessage(true); - return false; - } - - uint32 maxcount; - if (!ExtractOptUInt32(&args, maxcount, 0)) - { - return false; - } - - uint32 incrtime; - if (!ExtractOptUInt32(&args, incrtime, 0)) - { - return false; - } - - uint32 extendedcost; - if (!ExtractOptUInt32(&args, extendedcost, 0)) - { - return false; - } - - Creature* vendor = getSelectedCreature(); - - uint32 vendor_entry = vendor ? vendor->GetEntry() : 0; - - if (!sObjectMgr.IsVendorItemValid(false, "npc_vendor", vendor_entry, itemId, maxcount, incrtime, extendedcost, 0, m_session->GetPlayer())) - { - SetSentErrorMessage(true); - return false; - } - - sObjectMgr.AddVendorItem(vendor_entry, itemId, maxcount, incrtime, extendedcost); - - ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(itemId); - - PSendSysMessage(LANG_ITEM_ADDED_TO_LIST, itemId, pProto->Name1, maxcount, incrtime, extendedcost); - return true; -} - -// del item from vendor list -bool ChatHandler::HandleNpcDelVendorItemCommand(char* args) -{ - if (!*args) - { - return false; - } - - Creature* vendor = getSelectedCreature(); - if (!vendor || !vendor->IsVendor()) - { - SendSysMessage(LANG_COMMAND_VENDORSELECTION); - SetSentErrorMessage(true); - return false; - } - - uint32 itemId; - if (!ExtractUint32KeyFromLink(&args, "Hitem", itemId)) - { - SendSysMessage(LANG_COMMAND_NEEDITEMSEND); - SetSentErrorMessage(true); - return false; - } - - if (!sObjectMgr.RemoveVendorItem(vendor->GetEntry(), itemId)) - { - PSendSysMessage(LANG_ITEM_NOT_IN_LIST, itemId); - SetSentErrorMessage(true); - return false; - } - - ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(itemId); - - PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST, itemId, pProto->Name1); - return true; -} - -// show info about AI -bool ChatHandler::HandleNpcAIInfoCommand(char* /*args*/) -{ - Creature* pTarget = getSelectedCreature(); - - if (!pTarget) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_NPC_AI_HEADER, pTarget->GetEntry()); - - std::string strScript = pTarget->GetScriptName(); - std::string strAI = pTarget->GetAIName(); - char const* cstrAIClass = pTarget->AI() ? typeid(*pTarget->AI()).name() : " - "; - - PSendSysMessage(LANG_NPC_AI_NAMES, - strAI.empty() ? " - " : strAI.c_str(), - cstrAIClass ? cstrAIClass : " - ", - strScript.empty() ? " - " : strScript.c_str()); - - if (pTarget->AI()) - { - pTarget->AI()->GetAIInformation(*this); - } - - return true; -} - -// change level of creature or pet -bool ChatHandler::HandleNpcChangeLevelCommand(char* args) -{ - if (!*args) - { - return false; - } - - uint8 lvl = (uint8) atoi(args); - if (lvl < 1 || lvl > sWorld.getConfig(CONFIG_UINT32_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()) - { - ((Pet*)pCreature)->GivePetLevel(lvl); - } - else - { - pCreature->SetMaxHealth(100 + 30 * lvl); - pCreature->SetHealth(100 + 30 * lvl); - pCreature->SetLevel(lvl); - - if (pCreature->HasStaticDBSpawnData()) - { - pCreature->SaveToDB(); - } - } - - return true; -} - -// set npcflag of creature -bool ChatHandler::HandleNpcFlagCommand(char* args) -{ - if (!*args) - { - return false; - } - - uint32 npcFlags = (uint32) atoi(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 `NpcFlags` = '%u' WHERE `entry` = '%u'", npcFlags, pCreature->GetEntry()); - - SendSysMessage(LANG_VALUE_SAVED_REJOIN); - - return true; -} - -bool ChatHandler::HandleNpcDeleteCommand(char* args) -{ - Creature* unit = NULL; - - if (*args) - { - // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r - uint32 lowguid; - if (!ExtractUint32KeyFromLink(&args, "Hcreature", lowguid)) - { - return false; - } - - if (!lowguid) - { - return false; - } - - if (CreatureData const* data = sObjectMgr.GetCreatureData(lowguid)) - { - unit = m_session->GetPlayer()->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); - } - } - else - { - unit = getSelectedCreature(); - } - - if (!unit) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - switch (unit->GetSubtype()) - { - case CREATURE_SUBTYPE_GENERIC: - { - unit->CombatStop(); - if (CreatureData const* data = sObjectMgr.GetCreatureData(unit->GetGUIDLow())) - { - Creature::AddToRemoveListInMaps(unit->GetGUIDLow(), data); - Creature::DeleteFromDB(unit->GetGUIDLow(), data); - } - else - { - unit->AddObjectToRemoveList(); - } - break; - } - case CREATURE_SUBTYPE_PET: - ((Pet*)unit)->Unsummon(PET_SAVE_AS_CURRENT); - break; - case CREATURE_SUBTYPE_TOTEM: - ((Totem*)unit)->UnSummon(); - break; - case CREATURE_SUBTYPE_TEMPORARY_SUMMON: - ((TemporarySummon*)unit)->UnSummon(); - break; - default: - return false; - } - - SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); - - return true; -} - -// move selected creature -bool ChatHandler::HandleNpcMoveCommand(char* args) -{ - uint32 lowguid = 0; - Player* player = m_session->GetPlayer(); - - Creature* pCreature = getSelectedCreature(); - if (!pCreature) - { - // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r - if (!ExtractUint32KeyFromLink(&args, "Hcreature", lowguid)) - { - return false; - } - - CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); - if (!data) - { - PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - if (player->GetMapId() != data->mapid) - { - PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); - SetSentErrorMessage(true); - return false; - } - - pCreature = player->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); - } - else - { - lowguid = pCreature->GetGUIDLow(); - } - - float x = player->GetPositionX(); - float y = player->GetPositionY(); - float z = player->GetPositionZ(); - float o = player->GetOrientation(); - - if (pCreature) - { - if (CreatureData const* data = sObjectMgr.GetCreatureData(pCreature->GetGUIDLow())) - { - const_cast(data)->posX = x; - const_cast(data)->posY = y; - const_cast(data)->posZ = z; - const_cast(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.
- *
- * Valid movement types are: - *
    - *
  • stay - NPC wont move
  • - *
  • random - NPC will move randomly according to the spawndist
  • - *
  • way - NPC will move with given waypoints set
  • - *
- * additional parameter: NODEL - so no waypoints are deleted, if you - * change the movement type - */ -bool ChatHandler::HandleNpcSetMoveTypeCommand(char* args) -{ - // 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) - - uint32 lowguid; - Creature* pCreature; - if (!ExtractUInt32(&args, lowguid)) // case .setmovetype $move_type (with selected creature) - { - pCreature = getSelectedCreature(); - if (!pCreature || !pCreature->HasStaticDBSpawnData()) - { - return false; - } - lowguid = pCreature->GetGUIDLow(); - } - else // case .setmovetype #creature_guid $move_type (with guid) - { - CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); - if (!data) - { - PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - Player* player = m_session->GetPlayer(); - - if (player->GetMapId() != data->mapid) - { - PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); - SetSentErrorMessage(true); - return false; - } - - pCreature = player->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); - } - - MovementGeneratorType move_type; - char* type_str = ExtractLiteralArg(&args); - if (!type_str) - { - return false; - } - - if (strncmp(type_str, "stay", strlen(type_str)) == 0) - { - move_type = IDLE_MOTION_TYPE; - } - else if (strncmp(type_str, "random", strlen(type_str)) == 0) - { - move_type = RANDOM_MOTION_TYPE; - } - else if (strncmp(type_str, "way", strlen(type_str)) == 0) - { - move_type = WAYPOINT_MOTION_TYPE; - } - else - { - return false; - } - - bool doNotDelete = ExtractLiteralArg(&args, "NODEL") != NULL; - if (!doNotDelete && *args) // need fail if false in result wrong literal - { - return false; - } - - // now lowguid is low guid really existing creature - // and pCreature point (maybe) to this creature or NULL - - // update movement type - if (!doNotDelete) - { - sWaypointMgr.DeletePath(lowguid); - } - - if (pCreature) - { - 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) - { - PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL, type_str); - } - else - { - PSendSysMessage(LANG_MOVE_TYPE_SET, type_str); - } - - return true; -} - -// set model of creature -bool ChatHandler::HandleNpcSetModelCommand(char* args) -{ - if (!*args) - { - return false; - } - - uint32 displayId = (uint32) atoi(args); - - Creature* pCreature = getSelectedCreature(); - - if (!pCreature || pCreature->IsPet()) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->SetDisplayId(displayId); - pCreature->SetNativeDisplayId(displayId); - - if (pCreature->HasStaticDBSpawnData()) - { - pCreature->SaveToDB(); - } - - return true; -} -// set faction of creature -bool ChatHandler::HandleNpcFactionIdCommand(char* args) -{ - if (!*args) - { - return false; - } - - uint32 factionId = (uint32) atoi(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(cinfo)->FactionAlliance = factionId; - const_cast(cinfo)->FactionHorde = factionId; - } - - // and DB - WorldDatabase.PExecuteLog("UPDATE `creature_template` SET `FactionAlliance` = '%u', `FactionHorde` = '%u' WHERE `entry` = '%u'", factionId, factionId, pCreature->GetEntry()); - - return true; -} -// set spawn dist of creature -bool ChatHandler::HandleNpcSpawnDistCommand(char* args) -{ - if (!*args) - { - return false; - } - - float option = (float)atof(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->GetGUIDLow(); - } - 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(char* args) -{ - uint32 stime; - if (!ExtractUInt32(&args, stime)) - { - return false; - } - - Creature* pCreature = getSelectedCreature(); - if (!pCreature) - { - PSendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - uint32 u_guidlow = pCreature->GetGUIDLow(); - - WorldDatabase.PExecuteLog("UPDATE `creature` SET `spawntimesecs`=%i WHERE `guid`=%u", stime, u_guidlow); - pCreature->SetRespawnDelay(stime); - PSendSysMessage(LANG_COMMAND_SPAWNTIME, stime); - - return true; -} -// npc follow handling -bool ChatHandler::HandleNpcFollowCommand(char* /*args*/) -{ - Player* player = m_session->GetPlayer(); - Creature* creature = getSelectedCreature(); - - if (!creature) - { - PSendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // Follow player - Using pet's default dist and angle - creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - - PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName()); - return true; -} -// npc unfollow handling -bool ChatHandler::HandleNpcUnFollowCommand(char* /*args*/) -{ - Player* player = m_session->GetPlayer(); - Creature* creature = getSelectedCreature(); - - if (!creature) - { - PSendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - MotionMaster* creatureMotion = creature->GetMotionMaster(); - if (creatureMotion->empty() || - creatureMotion->GetCurrentMovementGeneratorType() != FOLLOW_MOTION_TYPE) - { - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName()); - SetSentErrorMessage(true); - return false; - } - - FollowMovementGenerator const* mgen = static_cast const*>(creatureMotion->top()); - - if (mgen->GetTarget() != player) - { - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName()); - SetSentErrorMessage(true); - return false; - } - - // reset movement - creatureMotion->MovementExpired(true); - - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName()); - return true; -} -// npc tame handling -bool ChatHandler::HandleNpcTameCommand(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; - } - - player->CastSpell(creatureTarget, 13481, true); // Tame Beast, triggered effect - return true; -} - -// npc deathstate handling -bool ChatHandler::HandleNpcSetDeathStateCommand(char* args) -{ - bool value; - if (!ExtractOnOff(&args, value)) - { - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; - } - - Creature* pCreature = getSelectedCreature(); - if (!pCreature || !pCreature->HasStaticDBSpawnData()) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (value) - { - pCreature->SetDeadByDefault(true); - } - else - { - pCreature->SetDeadByDefault(false); - } - - pCreature->SaveToDB(); - pCreature->Respawn(); - - return true; -} - -// TODO: NpcCommands that need to be fixed : - -bool ChatHandler::HandleNpcNameCommand(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; - } - } - - ObjectGuid guid = m_session->GetPlayer()->GetSelectionGuid(); - if (guid.IsEmpty()) - { - SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature* pCreature = sObjectAccessor.GetCreature(*m_session->GetPlayer(), guid); - - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - pCreature->SetName(args); - uint32 idname = sObjectMgr.AddCreatureTemplate(pCreature->GetName()); - pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); - - pCreature->SaveToDB(); - */ - - return true; -} - -bool ChatHandler::HandleNpcSubNameCommand(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; - } - } - - ObjectGuid guid = m_session->GetPlayer()->GetSelectionGuid(); - if (guid.IsEmpty()) - { - SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature* pCreature = sObjectAccessor.GetCreature(*m_session->GetPlayer(), guid); - - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - uint32 idname = sObjectMgr.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(char* args) -{ - if (!*args) - { - return false; - } - uint8 srcslot, dstslot; - - char* pParam1 = strtok(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; - } - - Player* player = m_session->GetPlayer(); - if (!player->IsValidPos(INVENTORY_SLOT_BAG_0, srcslot, true)) - { - return false; - } - - // can be autostore pos - if (!player->IsValidPos(INVENTORY_SLOT_BAG_0, dstslot, false)) - { - return false; - } - - uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); - uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); - - player->SwapItem(src, dst); - - return true; -} - -// demorph player or unit -bool ChatHandler::HandleDeMorphCommand(char* /*args*/) -{ - Unit* target = getSelectedUnit(); - if (!target) - { - target = m_session->GetPlayer(); - } - - - // check online security - else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target)) - { - return false; - } - - target->DeMorph(); - - return true; -} - -// morph creature or player -bool ChatHandler::HandleModifyMorphCommand(char* args) -{ - if (!*args) - { - return false; - } - - uint32 display_id = (uint32)atoi(args); - - CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(display_id); - if (!displayEntry) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Unit* target = getSelectedUnit(); - if (!target) - { - target = m_session->GetPlayer(); - } - - // check online security - else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target)) - { - return false; - } - - target->SetDisplayId(display_id); - - return true; -} - -// kick player -bool ChatHandler::HandleKickPlayerCommand(char* args) -{ - Player* target; - if (!ExtractPlayerTarget(&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)) - { - return false; - } - - // send before target pointer invalidate - PSendSysMessage(LANG_COMMAND_KICKMESSAGE, GetNameLink(target).c_str()); - target->GetSession()->KickPlayer(); - return true; -} - -// show info of player -bool ChatHandler::HandlePInfoCommand(char* args) -{ - Player* target; - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) - { - return false; - } - - uint32 accId = 0; - uint32 money = 0; - uint32 total_player_time = 0; - uint32 level = 0; - uint32 latency = 0; - - // get additional information from Player object - if (target) - { - // check online security - if (HasLowerSecurity(target)) - { - return false; - } - - accId = target->GetSession()->GetAccountId(); - money = target->GetMoney(); - total_player_time = target->GetTotalPlayedTime(); - level = target->getLevel(); - latency = target->GetSession()->GetLatency(); - } - // get additional information from DB - else - { - // check offline security - if (HasLowerSecurity(NULL, target_guid)) - { - return false; - } - - // 0 1 2 3 - QueryResult* result = CharacterDatabase.PQuery("SELECT `totaltime`, `level`, `money`, `account` FROM `characters` WHERE `guid` = '%u'", target_guid.GetCounter()); - 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(); - delete result; - } - - std::string username = GetMangosString(LANG_ERROR); - std::string email = GetMangosString(LANG_ERROR); - std::string last_ip = GetMangosString(LANG_ERROR); - AccountTypes security = SEC_PLAYER; - std::string last_login = GetMangosString(LANG_ERROR); - - QueryResult* result = LoginDatabase.PQuery("SELECT `username`,`gmlevel`,`email`,`last_ip`,`last_login` FROM `account` WHERE `id` = '%u'", accId); - if (result) - { - Field* fields = result->Fetch(); - username = fields[0].GetCppString(); - security = (AccountTypes)fields[1].GetUInt32(); - - if (GetAccessLevel() >= security) - { - if (security == SEC_ADMINISTRATOR) - { - email = fields[2].GetCppString(); - } - else - { - email = "*hidden*"; - } - last_ip = fields[3].GetCppString(); - last_login = fields[4].GetCppString(); - } - else - { - email = "-"; - last_ip = "-"; - last_login = "-"; - } - - delete result; - } - - std::string nameLink = playerLink(target_name); - - PSendSysMessage(LANG_PINFO_ACCOUNT, (target ? "" : GetMangosString(LANG_OFFLINE)), nameLink.c_str(), target_guid.GetCounter(), username.c_str(), accId, security, email.c_str(), last_ip.c_str(), last_login.c_str(), latency); - - 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, timeStr.c_str(), level, gold, silv, copp); - - return true; -} - -// show ticket (helper) -void ChatHandler::ShowTicket(GMTicket const* ticket) -{ - std::string lastupdated = TimeToTimestampStr(ticket->GetLastUpdate()); - - std::string name; - if (!sObjectMgr.GetPlayerNameByGUID(ticket->GetPlayerGuid(), name)) - { - name = GetMangosString(LANG_UNKNOWN); - } - - std::string nameLink = playerLink(name); - - char const* response = ticket->GetResponse(); - - PSendSysMessage(LANG_COMMAND_TICKETVIEW, nameLink.c_str(), lastupdated.c_str(), ticket->GetText()); - if (strlen(response)) - { - PSendSysMessage(LANG_COMMAND_TICKETRESPONSE, ticket->GetResponse()); - } -} - -// ticket commands -bool ChatHandler::HandleTicketAcceptCommand(char* args) -{ - char* px = ExtractLiteralArg(&args); - - // ticket - if (!px) - { - return false; - } - - // ticket accept on - if (strncmp(px, "on", 3) == 0) - { - sTicketMgr.SetAcceptTickets(true); - SendSysMessage(LANG_COMMAND_TICKETS_SYSTEM_ON); - } - // ticket accept off - else if (strncmp(px, "off", 4) == 0) - { - sTicketMgr.SetAcceptTickets(false); - SendSysMessage(LANG_COMMAND_TICKETS_SYSTEM_OFF); - } - else - { - return false; - } - - return true; -} - -bool ChatHandler::HandleTicketCloseCommand(char* args) -{ - GMTicket* ticket = NULL; - - uint32 num; - if (ExtractUInt32(&args, num)) - { - if (num == 0) - { - return false; - } - - ticket = sTicketMgr.GetGMTicket(num); - - if (!ticket) - { - PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); - SetSentErrorMessage(true); - return false; - } - } - else - { - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&args, NULL, &target_guid, &target_name)) - { - return false; - } - - // ticket respond $char_name - ticket = sTicketMgr.GetGMTicket(target_guid); - - if (!ticket) - { - PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST_NAME, target_name.c_str()); - SetSentErrorMessage(true); - return false; - } - } - - Player* pPlayer = sObjectMgr.GetPlayer(ticket->GetPlayerGuid()); - - if (!pPlayer && !sWorld.getConfig(CONFIG_BOOL_GM_TICKET_OFFLINE_CLOSING)) - { - SendSysMessage(LANG_COMMAND_TICKET_CANT_CLOSE); - return false; - } - - ticket->Close(); - - //This logic feels misplaced, but you can't have it in GMTicket? - sTicketMgr.Delete(ticket->GetPlayerGuid()); // here, ticket become invalidated and should not be used below - - PSendSysMessage(LANG_COMMAND_TICKETCLOSED_NAME, pPlayer ? pPlayer->GetName() : "an offline player"); - - return true; -} - -// del tickets -bool ChatHandler::HandleTicketDeleteCommand(char* args) -{ - char* px = ExtractLiteralArg(&args); - if (!px) - { - return false; - } - - // ticket delete all - if (strncmp(px, "all", 4) == 0) - { - sTicketMgr.DeleteAll(); - SendSysMessage(LANG_COMMAND_ALLTICKETDELETED); - return true; - } - - uint32 num; - - // ticket delete #num - if (ExtractUInt32(&px, num)) - { - if (num == 0) - { - return false; - } - - // mgr numbering tickets start from 0 - GMTicket* ticket = sTicketMgr.GetGMTicket(num); - - if (!ticket) - { - PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); - SetSentErrorMessage(true); - return false; - } - - ObjectGuid guid = ticket->GetPlayerGuid(); - - sTicketMgr.Delete(guid); - - // notify player - if (Player* pl = sObjectMgr.GetPlayer(guid)) - { - pl->GetSession()->SendGMTicketGetTicket(0x0A); - PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, GetNameLink(pl).c_str()); - } - else - { - PSendSysMessage(LANG_COMMAND_TICKETDEL); - } - - return true; - } - - // ticket delete $charName - Player* target; - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&px, &target, &target_guid, &target_name)) - { - return false; - } - - // ticket delete $charName - sTicketMgr.Delete(target_guid); - - // notify players about ticket deleting - if (target) - { - target->GetSession()->SendGMTicketGetTicket(0x0A); - } - - std::string nameLink = playerLink(target_name); - - PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, nameLink.c_str()); - return true; -} - -bool ChatHandler::HandleTicketInfoCommand(char *args) -{ - size_t count = sTicketMgr.GetTicketCount(); - - if (m_session) - { - PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, GetOnOffStr(m_session->GetPlayer()->isAcceptTickets())); - } - else - { - PSendSysMessage(LANG_COMMAND_TICKETCOUNT_CONSOLE, count); - } - - return true; -} - -bool ChatHandler::HandleTicketListCommand(char* args) -{ - uint16 numToShow = std::min(uint16(sTicketMgr.GetTicketCount()), uint16(sWorld.getConfig(CONFIG_UINT32_GM_TICKET_LIST_SIZE))); - for (uint16 i = 0; i < numToShow; ++i) - { - GMTicket* ticket = sTicketMgr.GetGMTicketByOrderPos(i); - time_t lastChanged = time_t(ticket->GetLastUpdate()); - PSendSysMessage(LANG_COMMAND_TICKET_OFFLINE_INFO, ticket->GetId(), ticket->GetPlayerGuid().GetCounter(), ticket->HasResponse() ? "+" : "-", ctime(&lastChanged)); - } - - PSendSysMessage(LANG_COMMAND_TICKET_COUNT_ALL, numToShow, sTicketMgr.GetTicketCount()); - return true; -} - -bool ChatHandler::HandleTicketOnlineListCommand(char* args) -{ - uint16 count = 0; - for (uint16 i = 0; i < sTicketMgr.GetTicketCount(); ++i) - { - GMTicket* ticket = sTicketMgr.GetGMTicketByOrderPos(i); - if (Player* player = sObjectMgr.GetPlayer(ticket->GetPlayerGuid(), true)) - { - ++count; - if (i < sWorld.getConfig(CONFIG_UINT32_GM_TICKET_LIST_SIZE)) - { - time_t lastChanged = time_t(ticket->GetLastUpdate()); - PSendSysMessage(LANG_COMMAND_TICKET_BRIEF_INFO, ticket->GetId(), player->GetName(), ticket->HasResponse() ? "+" : "-", ctime(&lastChanged)); - } - } - } - - PSendSysMessage(LANG_COMMAND_TICKET_COUNT_ONLINE, std::min(count, uint16(sWorld.getConfig(CONFIG_UINT32_GM_TICKET_LIST_SIZE))), count); - return true; -} - -bool ChatHandler::HandleTicketMeAcceptCommand(char* args) -{ - char* px = ExtractLiteralArg(&args); - if (!px) - { - PSendSysMessage(LANG_COMMAND_TICKET_ACCEPT_STATE, m_session->GetPlayer()->isAcceptTickets() ? "on" : "off"); - return true; - } - - if (!m_session) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - // ticket on - if (strncmp(px, "on", 3) == 0) - { - m_session->GetPlayer()->SetAcceptTicket(true); - SendSysMessage(LANG_COMMAND_TICKETON); - } - // ticket off - else if (strncmp(px, "off", 4) == 0) - { - m_session->GetPlayer()->SetAcceptTicket(false); - SendSysMessage(LANG_COMMAND_TICKETOFF); - } - else - { - return false; - } - - return true; -} - -bool ChatHandler::HandleTicketRespondCommand(char* args) -{ - GMTicket* ticket = NULL; - - // ticket respond #num - uint32 num; - if (ExtractUInt32(&args, num)) - { - if (num == 0) - { - return false; - } - - // mgr numbering tickets start from 0 - ticket = sTicketMgr.GetGMTicket(num); - - if (!ticket) - { - PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); - SetSentErrorMessage(true); - return false; - } - } - else - { - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&args, NULL, &target_guid, &target_name)) - { - return false; - } - - // ticket respond $char_name - ticket = sTicketMgr.GetGMTicket(target_guid); - - if (!ticket) - { - PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST_NAME, target_name.c_str()); - SetSentErrorMessage(true); - return false; - } - } - - // no response text? - if (!*args) - { - return false; - } - - ticket->SetResponseText(args); - - if (Player* pl = sObjectMgr.GetPlayer(ticket->GetPlayerGuid())) - { - pl->GetSession()->SendGMTicketGetTicket(0x06, ticket); - //How should we error here? - if (m_session) - { - m_session->GetPlayer()->Whisper(args, LANG_UNIVERSAL, pl->GetObjectGuid()); - } - } - - return true; -} - -bool ChatHandler::HandleTicketShowCommand(char *args) -{ - // ticket #num - char* px = ExtractLiteralArg(&args); - if (!px) - { - return false; - } - - uint32 num; - if (ExtractUInt32(&px, num)) - { - if (num == 0) - { - return false; - } - - // mgr numbering tickets start from 0 - GMTicket* ticket = sTicketMgr.GetGMTicket(num); - if (!ticket) - { - PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); - SetSentErrorMessage(true); - return false; - } - - ShowTicket(ticket); - return true; - } - - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&px, NULL, &target_guid, &target_name)) - { - return false; - } - - // ticket $char_name - GMTicket* ticket = sTicketMgr.GetGMTicket(target_guid); - if (!ticket) - { - PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST_NAME, target_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - ShowTicket(ticket); - - return true; -} - -bool ChatHandler::HandleTickerSurveyClose(char *args) -{ - GMTicket* ticket = NULL; - - uint32 num; - if (ExtractUInt32(&args, num)) - { - if (num == 0) - { - return false; - } - - ticket = sTicketMgr.GetGMTicket(num); - - if (!ticket) - { - PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); - SetSentErrorMessage(true); - return false; - } - } - else - { - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&args, NULL, &target_guid, &target_name)) - { - return false; - } - - // ticket respond $char_name - ticket = sTicketMgr.GetGMTicket(target_guid); - - if (!ticket) - { - PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST_NAME, target_name.c_str()); - SetSentErrorMessage(true); - return false; - } - } - - ticket->CloseWithSurvey(); - - //This needs to be before we delete the ticket - Player* pPlayer = sObjectMgr.GetPlayer(ticket->GetPlayerGuid()); - - //For now we can't close tickets for offline players, TODO - if (!pPlayer) - { - SendSysMessage(LANG_COMMAND_TICKET_CANT_CLOSE); - return false; - } - - //This logic feels misplaced, but you can't have it in GMTicket? - sTicketMgr.Delete(ticket->GetPlayerGuid()); - ticket = NULL; - - PSendSysMessage(LANG_COMMAND_TICKETCLOSED_NAME, pPlayer->GetName()); - - return true; -} - -/// Helper function -inline Creature* Helper_CreateWaypointFor(Creature* wpOwner, WaypointPathOrigin wpOrigin, int32 pathId, uint32 wpId, WaypointNode const* wpNode, CreatureInfo const* waypointInfo) -{ - TemporarySummonWaypoint* wpCreature = new TemporarySummonWaypoint(wpOwner->GetObjectGuid(), wpId, pathId, (uint32)wpOrigin); - - CreatureCreatePos pos(wpOwner->GetMap(), wpNode->x, wpNode->y, wpNode->z, wpNode->orientation); - - if (!wpCreature->Create(wpOwner->GetMap()->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, waypointInfo)) - { - delete wpCreature; - return NULL; - } - - wpCreature->SetVisibility(VISIBILITY_OFF); - wpCreature->SetRespawnCoord(pos); - - wpCreature->SetActiveObjectState(true); - - wpCreature->Summon(TEMPSUMMON_TIMED_DESPAWN, 5 * MINUTE * IN_MILLISECONDS); // Also initializes the AI and MMGen - return wpCreature; -} -inline void UnsummonVisualWaypoints(Player const* player, ObjectGuid ownerGuid) -{ - std::list waypoints; - MaNGOS::AllCreaturesOfEntryInRangeCheck checkerForWaypoint(player, VISUAL_WAYPOINT, SIZE_OF_GRIDS); - MaNGOS::CreatureListSearcher searcher(waypoints, checkerForWaypoint); - Cell::VisitGridObjects(player, searcher, SIZE_OF_GRIDS); - - for (std::list::iterator itr = waypoints.begin(); itr != waypoints.end(); ++itr) - { - if ((*itr)->GetSubtype() != CREATURE_SUBTYPE_TEMPORARY_SUMMON) - { - continue; - } - - TemporarySummonWaypoint* wpTarget = dynamic_cast(*itr); - if (!wpTarget) - { - continue; - } - - if (wpTarget->GetSummonerGuid() == ownerGuid) - { - wpTarget->UnSummon(); - } - } -} - -/** Add a waypoint to a creature - * .wp add [dbGuid] [pathId] [source] - * - * The user can either select an npc or provide its dbGuid. - * Also the user can specify pathId and source if wanted. - * - * 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. - * - * .wp add [pathId] [source] - * -> adds a waypoint to the currently selected creature, to path pathId in source-storage - * - * .wp add guid [pathId] [source] - * -> if no npc is selected, expect the creature provided with guid argument - * - * @return true - command did succeed, false - something went wrong - */ -bool ChatHandler::HandleWpAddCommand(char* args) -{ - DEBUG_LOG("DEBUG: HandleWpAddCommand"); - - CreatureInfo const* waypointInfo = ObjectMgr::GetCreatureTemplate(VISUAL_WAYPOINT); - if (!waypointInfo || waypointInfo->GetHighGuid() != HIGHGUID_UNIT) - { - return false; // must exist as normal creature in mangos.sql 'creature_template' - } - - Creature* targetCreature = getSelectedCreature(); - WaypointPathOrigin wpDestination = PATH_NO_PATH; ///< into which storage - int32 wpPathId = 0; ///< along which path - uint32 wpPointId = 0; ///< pointId if a waypoint was selected, in this case insert after - Creature* wpOwner = NULL; - - if (targetCreature) - { - // Check if the user did specify a visual waypoint - if (targetCreature->GetEntry() == VISUAL_WAYPOINT && targetCreature->GetSubtype() == CREATURE_SUBTYPE_TEMPORARY_SUMMON) - { - TemporarySummonWaypoint* wpTarget = dynamic_cast(targetCreature); - if (!wpTarget) - { - PSendSysMessage(LANG_WAYPOINT_VP_SELECT); - SetSentErrorMessage(true); - return false; - } - - // Who moves along this waypoint? - wpOwner = targetCreature->GetMap()->GetAnyTypeCreature(wpTarget->GetSummonerGuid()); - if (!wpOwner) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUND_NPC, wpTarget->GetSummonerGuid().GetString().c_str()); - SetSentErrorMessage(true); - return false; - } - wpDestination = (WaypointPathOrigin)wpTarget->GetPathOrigin(); - wpPathId = wpTarget->GetPathId(); - wpPointId = wpTarget->GetWaypointId() + 1; // Insert as next waypoint - } - else // normal creature selected - { - wpOwner = targetCreature; - } - } - else //!targetCreature - first argument must be dbGuid - { - uint32 dbGuid; - if (!ExtractUInt32(&args, dbGuid)) - { - PSendSysMessage(LANG_WAYPOINT_NOGUID); - SetSentErrorMessage(true); - return false; - } - - CreatureData const* data = sObjectMgr.GetCreatureData(dbGuid); - if (!data) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); - SetSentErrorMessage(true); - return false; - } - - if (m_session->GetPlayer()->GetMapId() != data->mapid) - { - PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, dbGuid); - SetSentErrorMessage(true); - return false; - } - - wpOwner = m_session->GetPlayer()->GetMap()->GetAnyTypeCreature(data->GetObjectGuid(dbGuid)); - if (!wpOwner) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); - SetSentErrorMessage(true); - return false; - } - } - - if (wpDestination == PATH_NO_PATH) // No Waypoint selected, parse additional params - { - if (ExtractOptInt32(&args, wpPathId, 0)) // Fill path-id and source - { - uint32 src = (uint32)PATH_NO_PATH; - if (ExtractOptUInt32(&args, src, src)) - { - wpDestination = (WaypointPathOrigin)src; - } - else // pathId provided but no destination - { - if (wpPathId != 0) - { - wpDestination = PATH_FROM_ENTRY; // Multiple Paths must only be assigned by entry - } - } - } - - if (wpDestination == PATH_NO_PATH) // No overwrite params. Do best estimate - { - if (wpOwner->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) - { - if (WaypointMovementGenerator const* wpMMGen = dynamic_cast const*>(wpOwner->GetMotionMaster()->GetCurrent())) - { - wpMMGen->GetPathInformation(wpPathId, wpDestination); - } - } - // Get information about default path if no current path. If no default path, prepare data dependendy on uniqueness - if (wpDestination == PATH_NO_PATH && !sWaypointMgr.GetDefaultPath(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), &wpDestination)) - { - wpDestination = PATH_FROM_ENTRY; // Default place to store paths - if (wpOwner->HasStaticDBSpawnData()) - { - QueryResult* result = WorldDatabase.PQuery("SELECT COUNT(`id`) FROM `creature` WHERE `id` = %u", wpOwner->GetEntry()); - if (result && result->Fetch()[0].GetUInt32() != 1) - { - wpDestination = PATH_FROM_GUID; - } - delete result; - } - } - } - } - - // All arguments parsed - // wpOwner will get a new waypoint inserted into wpPath = GetPathFromOrigin(wpOwner, wpDestination, wpPathId) at wpPointId - - float x, y, z; - m_session->GetPlayer()->GetPosition(x, y, z); - if (!sWaypointMgr.AddNode(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPointId, wpDestination, x, y, z)) - { - PSendSysMessage(LANG_WAYPOINT_NOTCREATED, wpPointId, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpDestination).c_str()); - SetSentErrorMessage(true); - return false; - } - - // Unsummon old visuals, summon new ones - UnsummonVisualWaypoints(m_session->GetPlayer(), wpOwner->GetObjectGuid()); - WaypointPath const* wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpDestination); - for (WaypointPath::const_iterator itr = wpPath->begin(); itr != wpPath->end(); ++itr) - { - if (!Helper_CreateWaypointFor(wpOwner, wpDestination, wpPathId, itr->first, &itr->second, waypointInfo)) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); - SetSentErrorMessage(true); - return false; - } - } - - PSendSysMessage(LANG_WAYPOINT_ADDED, wpPointId, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpDestination).c_str()); - - return true; -} // HandleWpAddCommand - -/** - * .wp modify waittime | scriptid | orientation | del | move [dbGuid, id] [value] - * - * waittime - * User has selected a visual waypoint before. - * Delay is added to this waypoint. Everytime the - * NPC comes to this waypoint, it will wait Delay millieseconds. - * - * waittime - * User has not selected visual waypoint before. - * For the waypoint for the NPC with - * an delay Delay is added to this waypoint - * Everytime the NPC comes to this waypoint, it will wait Delay millieseconds. - * - * scriptid - * User has selected a visual waypoint before. - * is added to this waypoint. Everytime the - * NPC comes to this waypoint, the DBScript scriptId is executed. - * - * scriptid - * User has not selected visual waypoint before. - * For the waypoint for the NPC with - * an emote is added. - * Everytime the NPC comes to this waypoint, the DBScript scriptId is executed. - * - * orientation [DBGuid, WpNum] - * Set the orientation of the selected waypoint or waypoint given with DbGuid/ WpId - * to the value of . - * - * del [DBGuid, WpId] - * Remove the selected waypoint or waypoint given with DbGuid/ WpId. - * - * move [DBGuid, WpId] - * Move the selected waypoint or waypoint given with DbGuid/ WpId to player's current positiion. - */ -bool ChatHandler::HandleWpModifyCommand(char* args) -{ - DEBUG_LOG("DEBUG: HandleWpModifyCommand"); - - if (!*args) - { - return false; - } - - CreatureInfo const* waypointInfo = ObjectMgr::GetCreatureTemplate(VISUAL_WAYPOINT); - if (!waypointInfo || waypointInfo->GetHighGuid() != HIGHGUID_UNIT) - { - return false; // must exist as normal creature in mangos.sql 'creature_template' - } - - // first arg: add del text emote spell waittime move - char* subCmd_str = ExtractLiteralArg(&args); - if (!subCmd_str) - { - return false; - } - - std::string subCmd = subCmd_str; - // Check - // Remember: "show" must also be the name of a column! - if ((subCmd != "waittime") && (subCmd != "scriptid") && (subCmd != "orientation") && (subCmd != "del") && (subCmd != "move")) - { - return false; - } - - // Next arg is: - - // Did user provide a GUID or did the user select a creature? - Creature* targetCreature = getSelectedCreature(); // Expect a visual waypoint to be selected - Creature* wpOwner = NULL; // Who moves along the waypoint - uint32 wpId = 0; - WaypointPathOrigin wpSource = PATH_NO_PATH; - int32 wpPathId = 0; - - if (targetCreature) - { - DEBUG_LOG("DEBUG: HandleWpModifyCommand - User did select an NPC"); - - // Check if the user did specify a visual waypoint - if (targetCreature->GetEntry() != VISUAL_WAYPOINT || targetCreature->GetSubtype() != CREATURE_SUBTYPE_TEMPORARY_SUMMON) - { - PSendSysMessage(LANG_WAYPOINT_VP_SELECT); - SetSentErrorMessage(true); - return false; - } - TemporarySummonWaypoint* wpTarget = dynamic_cast(targetCreature); - if (!wpTarget) - { - PSendSysMessage(LANG_WAYPOINT_VP_SELECT); - SetSentErrorMessage(true); - return false; - } - - // Who moves along this waypoint? - wpOwner = targetCreature->GetMap()->GetAnyTypeCreature(wpTarget->GetSummonerGuid()); - if (!wpOwner) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUND_NPC, wpTarget->GetSummonerGuid().GetString().c_str()); - SetSentErrorMessage(true); - return false; - } - wpId = wpTarget->GetWaypointId(); - - wpPathId = wpTarget->GetPathId(); - wpSource = (WaypointPathOrigin)wpTarget->GetPathOrigin(); - } - else - { - uint32 dbGuid = 0; - // User did provide - if (!ExtractUInt32(&args, dbGuid)) - { - SendSysMessage(LANG_WAYPOINT_NOGUID); - SetSentErrorMessage(true); - return false; - } - - if (!ExtractUInt32(&args, wpId)) - { - SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN); - SetSentErrorMessage(true); - return false; - } - - CreatureData const* data = sObjectMgr.GetCreatureData(dbGuid); - if (!data) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); - SetSentErrorMessage(true); - return false; - } - - wpOwner = m_session->GetPlayer()->GetMap()->GetAnyTypeCreature(data->GetObjectGuid(dbGuid)); - if (!wpOwner) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); - SetSentErrorMessage(true); - return false; - } - } - - if (wpSource == PATH_NO_PATH) // No waypoint selected - { - if (wpOwner->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) - { - if (WaypointMovementGenerator const* wpMMGen = dynamic_cast const*>(wpOwner->GetMotionMaster()->GetCurrent())) - { - wpMMGen->GetPathInformation(wpPathId, wpSource); - } - } - if (wpSource == PATH_NO_PATH) - { - sWaypointMgr.GetDefaultPath(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), &wpSource); - } - } - - WaypointPath const* wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpSource); - if (!wpPath) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDPATH, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpSource).c_str()); - SetSentErrorMessage(true); - return false; - } - - WaypointPath::const_iterator point = wpPath->find(wpId); - if (point == wpPath->end()) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUND, wpId, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpSource).c_str()); - SetSentErrorMessage(true); - return false; - } - - // If no visual WP was selected, but we are not going to remove it - if (!targetCreature && subCmd != "del") - { - targetCreature = Helper_CreateWaypointFor(wpOwner, wpSource, wpPathId, wpId, &(point->second), waypointInfo); - if (!targetCreature) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); - SetSentErrorMessage(true); - return false; - } - } - - if (subCmd == "del") // Remove WP, no additional command required - { - sWaypointMgr.DeleteNode(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource); - - if (TemporarySummonWaypoint* wpCreature = dynamic_cast(targetCreature)) - { - wpCreature->UnSummon(); - } - - if (wpPath->empty()) - { - wpOwner->SetDefaultMovementType(RANDOM_MOTION_TYPE); - wpOwner->GetMotionMaster()->Initialize(); - if (wpOwner->IsAlive()) // Dead creature will reset movement generator at respawn - { - wpOwner->SetDeathState(JUST_DIED); - wpOwner->Respawn(); - } - wpOwner->SaveToDB(); - } - - PSendSysMessage(LANG_WAYPOINT_REMOVED); - return true; - } - else if (subCmd == "move") // Move to player position, no additional command required - { - float x, y, z; - m_session->GetPlayer()->GetPosition(x, y, z); - - // Move visual waypoint - targetCreature->NearTeleportTo(x, y, z, targetCreature->GetOrientation()); - - sWaypointMgr.SetNodePosition(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource, x, y, z); - - PSendSysMessage(LANG_WAYPOINT_CHANGED); - return true; - } - else if (subCmd == "waittime") - { - uint32 waittime; - if (!ExtractUInt32(&args, waittime)) - { - return false; - } - - sWaypointMgr.SetNodeWaittime(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource, waittime); - } - else if (subCmd == "scriptid") - { - uint32 scriptId; - if (!ExtractUInt32(&args, scriptId)) - { - return false; - } - - if (!sWaypointMgr.SetNodeScriptId(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource, scriptId)) - { - PSendSysMessage(LANG_WAYPOINT_INFO_UNK_SCRIPTID, scriptId); - } - } - else if (subCmd == "orientation") - { - float ori; - if (!ExtractFloat(&args, ori)) - { - return false; - } - - sWaypointMgr.SetNodeOrientation(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource, ori); - } - - PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, subCmd_str); - return true; -} - -/** - * .wp show info | on | off | first | last [dbGuid] [pathId [wpOrigin] ] - * - * info -> User has selected a visual waypoint before - * - * on -> User has selected an NPC; all visual waypoints for this - * NPC are added to the world - * - * on -> User did not select an NPC - instead the dbGuid of the - * NPC is provided. All visual waypoints for this NPC - * are added from the world. - * - * off -> User has selected an NPC; all visual waypoints for this - * NPC are removed from the world. - */ -bool ChatHandler::HandleWpShowCommand(char* args) -{ - DEBUG_LOG("DEBUG: HandleWpShowCommand"); - - if (!*args) - { - return false; - } - - CreatureInfo const* waypointInfo = ObjectMgr::GetCreatureTemplate(VISUAL_WAYPOINT); - if (!waypointInfo || waypointInfo->GetHighGuid() != HIGHGUID_UNIT) - { - return false; // must exist as normal creature in mangos.sql 'creature_template' - } - - // first arg: info, on, off, first, last - - char* subCmd_str = ExtractLiteralArg(&args); - if (!subCmd_str) - { - return false; - } - std::string subCmd = subCmd_str; ///< info, on, off, first, last - - uint32 dbGuid = 0; - int32 wpPathId = 0; - WaypointPathOrigin wpOrigin = PATH_NO_PATH; - - // User selected an npc? - Creature* targetCreature = getSelectedCreature(); - if (targetCreature) - { - if (ExtractOptInt32(&args, wpPathId, 0)) // Fill path-id and source - { - uint32 src; - if (ExtractOptUInt32(&args, src, (uint32)PATH_NO_PATH)) - { - wpOrigin = (WaypointPathOrigin)src; - } - } - } - else // Guid must be provided - { - if (!ExtractUInt32(&args, dbGuid)) // No creature selected and no dbGuid provided - { - return false; - } - - if (ExtractOptInt32(&args, wpPathId, 0)) // Fill path-id and source - { - uint32 src = (uint32)PATH_NO_PATH; - if (ExtractOptUInt32(&args, src, src)) - { - wpOrigin = (WaypointPathOrigin)src; - } - } - - // Params now parsed, check them - CreatureData const* data = sObjectMgr.GetCreatureData(dbGuid); - if (!data) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); - SetSentErrorMessage(true); - return false; - } - - targetCreature = m_session->GetPlayer()->GetMap()->GetCreature(data->GetObjectGuid(dbGuid)); - if (!targetCreature) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); - SetSentErrorMessage(true); - return false; - } - } - - Creature* wpOwner = NULL; ///< Npc that is moving - TemporarySummonWaypoint* wpTarget = NULL; // Define here for wp-info command - - // Show info for the selected waypoint (Step one: get moving npc) - if (subCmd == "info") - { - // Check if the user did specify a visual waypoint - if (targetCreature->GetEntry() != VISUAL_WAYPOINT || targetCreature->GetSubtype() != CREATURE_SUBTYPE_TEMPORARY_SUMMON) - { - PSendSysMessage(LANG_WAYPOINT_VP_SELECT); - SetSentErrorMessage(true); - return false; - } - wpTarget = dynamic_cast(targetCreature); - if (!wpTarget) - { - PSendSysMessage(LANG_WAYPOINT_VP_SELECT); - SetSentErrorMessage(true); - return false; - } - - // Who moves along this waypoint? - wpOwner = targetCreature->GetMap()->GetAnyTypeCreature(wpTarget->GetSummonerGuid()); - if (!wpOwner) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUND_NPC, wpTarget->GetSummonerGuid().GetString().c_str()); - SetSentErrorMessage(true); - return false; - } - - // Ignore params, use information of selected waypoint! - wpOrigin = (WaypointPathOrigin)wpTarget->GetPathOrigin(); - wpPathId = wpTarget->GetPathId(); - } - else - { - wpOwner = targetCreature; - } - - // Get the path - WaypointPath* wpPath = NULL; - if (wpOrigin != PATH_NO_PATH) // Might have been provided by param - { - wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpOrigin); - } - else - { - if (wpOwner->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) - { - if (WaypointMovementGenerator const* wpMMGen = dynamic_cast const*>(wpOwner->GetMotionMaster()->GetCurrent())) - { - wpMMGen->GetPathInformation(wpPathId, wpOrigin); - wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpOrigin); - } - } - if (wpOrigin == PATH_NO_PATH) - { - wpPath = sWaypointMgr.GetDefaultPath(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), &wpOrigin); - } - } - - if (!wpPath || wpPath->empty()) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDPATH, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpOrigin).c_str()); - SetSentErrorMessage(true); - return false; - } - - // Show info for the selected waypoint (Step two: Show actual info) - if (subCmd == "info") - { - // Find the waypoint - WaypointPath::const_iterator point = wpPath->find(wpTarget->GetWaypointId()); - if (point == wpPath->end()) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUND, wpTarget->GetWaypointId(), wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpOrigin).c_str()); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, wpTarget->GetWaypointId(), wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpOrigin).c_str()); - PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, point->second.delay); - PSendSysMessage(LANG_WAYPOINT_INFO_ORI, point->second.orientation); - PSendSysMessage(LANG_WAYPOINT_INFO_SCRIPTID, point->second.script_id); - if (wpOrigin == PATH_FROM_EXTERNAL) - { - PSendSysMessage(LANG_WAYPOINT_INFO_AISCRIPT, wpOwner->GetScriptName().c_str()); - } - if (WaypointBehavior* behaviour = point->second.behavior) - { - PSendSysMessage(" ModelId1: %u", behaviour->model1); - PSendSysMessage(" ModelId2: %u", behaviour->model2); - PSendSysMessage(" Emote: %u", behaviour->emote); - PSendSysMessage(" Spell: %u", behaviour->spell); - for (int i = 0; i < MAX_WAYPOINT_TEXT; ++i) - { - PSendSysMessage(" TextId%i: %i \'%s\'", i + 1, behaviour->textid[i], (behaviour->textid[i] ? GetMangosString(behaviour->textid[i]) : "")); - } - } - - return true; - } - - if (subCmd == "on") - { - UnsummonVisualWaypoints(m_session->GetPlayer(), wpOwner->GetObjectGuid()); - - for (WaypointPath::const_iterator pItr = wpPath->begin(); pItr != wpPath->end(); ++pItr) - { - if (!Helper_CreateWaypointFor(wpOwner, wpOrigin, wpPathId, pItr->first, &(pItr->second), waypointInfo)) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); - SetSentErrorMessage(true); - return false; - } - } - - return true; - } - - if (subCmd == "first") - { - if (!Helper_CreateWaypointFor(wpOwner, wpOrigin, wpPathId, wpPath->begin()->first, &(wpPath->begin()->second), waypointInfo)) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); - SetSentErrorMessage(true); - return false; - } - - // player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint"); - return true; - } - - if (subCmd == "last") - { - if (!Helper_CreateWaypointFor(wpOwner, wpOrigin, wpPathId, wpPath->rbegin()->first, &(wpPath->rbegin()->second), waypointInfo)) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); - SetSentErrorMessage(true); - return false; - } - - // player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint"); - return true; - } - - if (subCmd == "off") - { - UnsummonVisualWaypoints(m_session->GetPlayer(), wpOwner->GetObjectGuid()); - PSendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED); - return true; - } - - return false; -} // HandleWpShowCommand - -/// [Guid if no selected unit] [pathId [wpOrigin] ] -bool ChatHandler::HandleWpExportCommand(char* args) -{ - if (!*args) - { - return false; - } - - Creature* wpOwner = NULL; - WaypointPathOrigin wpOrigin = PATH_NO_PATH; - int32 wpPathId = 0; - - if (Creature* targetCreature = getSelectedCreature()) - { - // Check if the user did specify a visual waypoint - if (targetCreature->GetEntry() == VISUAL_WAYPOINT && targetCreature->GetSubtype() == CREATURE_SUBTYPE_TEMPORARY_SUMMON) - { - TemporarySummonWaypoint* wpTarget = dynamic_cast(targetCreature); - if (!wpTarget) - { - PSendSysMessage(LANG_WAYPOINT_VP_SELECT); - SetSentErrorMessage(true); - return false; - } - - // Who moves along this waypoint? - wpOwner = targetCreature->GetMap()->GetAnyTypeCreature(wpTarget->GetSummonerGuid()); - if (!wpOwner) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUND_NPC, wpTarget->GetSummonerGuid().GetString().c_str()); - SetSentErrorMessage(true); - return false; - } - wpOrigin = (WaypointPathOrigin)wpTarget->GetPathOrigin(); - wpPathId = wpTarget->GetPathId(); - } - else // normal creature selected - { - wpOwner = targetCreature; - } - } - else - { - uint32 dbGuid; - if (!ExtractUInt32(&args, dbGuid)) - { - PSendSysMessage(LANG_WAYPOINT_NOGUID); - SetSentErrorMessage(true); - return false; - } - - CreatureData const* data = sObjectMgr.GetCreatureData(dbGuid); - if (!data) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); - SetSentErrorMessage(true); - return false; - } - - if (m_session->GetPlayer()->GetMapId() != data->mapid) - { - PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, dbGuid); - SetSentErrorMessage(true); - return false; - } - - wpOwner = m_session->GetPlayer()->GetMap()->GetAnyTypeCreature(data->GetObjectGuid(dbGuid)); - if (!wpOwner) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); - SetSentErrorMessage(true); - return false; - } - } - - // wpOwner is now known, in case of export by visual waypoint also the to be exported path - char* export_str = ExtractLiteralArg(&args); - if (!export_str) - { - PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export"); - SetSentErrorMessage(true); - return false; - } - - if (wpOrigin == PATH_NO_PATH) // No WP selected, Extract optional arguments - { - if (ExtractOptInt32(&args, wpPathId, 0)) // Fill path-id and source - { - uint32 src = (uint32)PATH_NO_PATH; - if (ExtractOptUInt32(&args, src, src)) - { - wpOrigin = (WaypointPathOrigin)src; - } - else // pathId provided but no destination - { - if (wpPathId != 0) - { - wpOrigin = PATH_FROM_ENTRY; // Multiple Paths must only be assigned by entry - } - } - } - - if (wpOrigin == PATH_NO_PATH) - { - if (wpOwner->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) - if (WaypointMovementGenerator const* wpMMGen = dynamic_cast const*>(wpOwner->GetMotionMaster()->GetCurrent())) - { - wpMMGen->GetPathInformation(wpPathId, wpOrigin); - } - if (wpOrigin == PATH_NO_PATH) - { - sWaypointMgr.GetDefaultPath(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), &wpOrigin); - } - } - } - - WaypointPath const* wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpOrigin); - if (!wpPath || wpPath->empty()) - { - PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT); - SetSentErrorMessage(true); - return false; - } - - std::ofstream outfile; - outfile.open(export_str); - - std::string table; - char const* key_field; - uint32 key; - switch (wpOrigin) - { - case PATH_FROM_ENTRY: key = wpOwner->GetEntry(); key_field = "entry"; table = "creature_movement_template"; break; - case PATH_FROM_GUID: key = wpOwner->GetGUIDLow(); key_field = "id"; table = "creature_movement"; break; - case PATH_FROM_EXTERNAL: key = wpOwner->GetEntry(); key_field = "entry"; table = sWaypointMgr.GetExternalWPTable(); break; - case PATH_NO_PATH: - return false; - } - - outfile << "DELETE FROM `" << table << "` WHERE `" << key_field << "`=" << key << ";\n"; - if (wpOrigin != PATH_FROM_EXTERNAL) - { - outfile << "INSERT INTO `" << table << "` (`" << key_field << "`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `waittime`, `script_id`) VALUES\n"; - } - else - { - outfile << "INSERT INTO `" << table << "` (`" << key_field << "`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `waittime`) VALUES\n"; - } - - WaypointPath::const_iterator itr = wpPath->begin(); - uint32 countDown = wpPath->size(); - for (; itr != wpPath->end(); ++itr, --countDown) - { - outfile << "(" << key << ","; - outfile << itr->first << ","; - outfile << itr->second.x << ","; - outfile << itr->second.y << ","; - outfile << itr->second.z << ","; - outfile << itr->second.orientation << ","; - outfile << itr->second.delay << ","; - if (wpOrigin != PATH_FROM_EXTERNAL) // Only for normal waypoints - { - outfile << itr->second.script_id << ")"; - } - if (countDown > 1) - { - outfile << ",\n"; - } - else - { - outfile << ";\n"; - } - } - - PSendSysMessage(LANG_WAYPOINT_EXPORTED); - outfile.close(); - - return true; -} - -// rename characters -bool ChatHandler::HandleCharacterRenameCommand(char* args) -{ - Player* target; - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) - { - return false; - } - - if (target) - { - // check online security - if (HasLowerSecurity(target)) - { - return false; - } - - PSendSysMessage(LANG_RENAME_PLAYER, GetNameLink(target).c_str()); - target->SetAtLoginFlag(AT_LOGIN_RENAME); - CharacterDatabase.PExecute("UPDATE `characters` SET `at_login` = `at_login` | '1' WHERE `guid` = '%u'", target->GetGUIDLow()); - } - 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(), target_guid.GetCounter()); - CharacterDatabase.PExecute("UPDATE `characters` SET `at_login` = `at_login` | '1' WHERE `guid` = '%u'", target_guid.GetCounter()); - } - - return true; -} - -bool ChatHandler::HandleCharacterReputationCommand(char* args) -{ - Player* target; - if (!ExtractPlayerTarget(&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); - - ShowFactionListHelper(factionEntry, loc, &itr->second, target); - } - return true; -} - -// change standstate -bool ChatHandler::HandleModifyStandStateCommand(char* args) -{ - uint32 anim_id; - if (!ExtractUInt32(&args, anim_id)) - { - return false; - } - - if (!sEmotesStore.LookupEntry(anim_id)) - { - return false; - } - - m_session->GetPlayer()->HandleEmoteState(anim_id); - - return true; -} - -bool ChatHandler::HandleHonorAddCommand(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)) - { - return false; - } - - float amount = (float)atof(args); - target->RewardHonor(NULL, 1, amount); - return true; -} - -bool ChatHandler::HandleHonorAddKillCommand(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)) - { - return false; - } - - m_session->GetPlayer()->RewardHonor(target, 1); - return true; -} - -bool ChatHandler::HandleHonorUpdateCommand(char* /*args*/) -{ - Player* target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target)) - { - return false; - } - - target->UpdateHonorFields(); - return true; -} - -bool ChatHandler::HandleLookupEventCommand(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); - - uint32 counter = 0; - - GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap(); - - for (uint32 id = 1; id < events.size(); ++id) - { - if (!sGameEventMgr.IsValidEvent(id)) - { - continue; - } - - GameEventData const& eventData = events[id]; - - std::string descr = eventData.description; - if (descr.empty()) - { - continue; - } - - if (Utf8FitTo(descr, wnamepart)) - { - char const* active = sGameEventMgr.IsActiveEvent(id) ? GetMangosString(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); - } - - ++counter; - } - } - - if (counter == 0) - { - SendSysMessage(LANG_NOEVENTFOUND); - } - - return true; -} - -bool ChatHandler::HandleEventListCommand(char* args) -{ - uint32 counter = 0; - bool all = false; - std::string arg = args; - if (arg == "all") - { - all = true; - } - - GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap(); - - char const* active = GetMangosString(LANG_ACTIVE); - char const* inactive = GetMangosString(LANG_FACTION_INACTIVE); - char const* state = ""; - - for (uint32 event_id = 0; event_id < events.size(); ++event_id) - { - if (!sGameEventMgr.IsValidEvent(event_id)) - { - continue; - } - - if (!sGameEventMgr.IsActiveEvent(event_id)) - { - if (!all) - { - continue; - } - state = inactive; - } - else - { - state = active; - } - - GameEventData const& eventData = events[event_id]; - - if (m_session) - { - PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT, event_id, event_id, eventData.description.c_str(), state); - } - else - { - PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE, event_id, eventData.description.c_str(), state); - } - - ++counter; - } - - if (counter == 0) - { - SendSysMessage(LANG_NOEVENTFOUND); - } - - return true; -} - -bool ChatHandler::HandleEventInfoCommand(char* args) -{ - if (!*args) - { - return false; - } - - // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r - uint32 event_id; - if (!ExtractUint32KeyFromLink(&args, "Hgameevent", event_id)) - { - return false; - } - - GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap(); - - if (!sGameEventMgr.IsValidEvent(event_id)) - { - SendSysMessage(LANG_EVENT_NOT_EXIST); - SetSentErrorMessage(true); - return false; - } - - GameEventData const& eventData = events[event_id]; - - char const* activeStr = sGameEventMgr.IsActiveEvent(event_id) ? GetMangosString(LANG_ACTIVE) : ""; - - std::string startTimeStr = TimeToTimestampStr(eventData.start); - std::string endTimeStr = TimeToTimestampStr(eventData.end); - - uint32 delay = sGameEventMgr.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(char* args) -{ - if (!*args) - { - return false; - } - - // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r - uint32 event_id; - if (!ExtractUint32KeyFromLink(&args, "Hgameevent", event_id)) - { - return false; - } - - GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap(); - - if (!sGameEventMgr.IsValidEvent(event_id)) - { - 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; - } - - if (sGameEventMgr.IsActiveEvent(event_id)) - { - PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE, event_id); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_EVENT_STARTED, event_id, eventData.description.c_str()); - sGameEventMgr.StartEvent(event_id, true); - return true; -} - -bool ChatHandler::HandleEventStopCommand(char* args) -{ - if (!*args) - { - return false; - } - - // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r - uint32 event_id; - if (!ExtractUint32KeyFromLink(&args, "Hgameevent", event_id)) - { - return false; - } - - GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap(); - - if (!sGameEventMgr.IsValidEvent(event_id)) - { - 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; - } - - if (!sGameEventMgr.IsActiveEvent(event_id)) - { - PSendSysMessage(LANG_EVENT_NOT_ACTIVE, event_id); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_EVENT_STOPPED, event_id, eventData.description.c_str()); - sGameEventMgr.StopEvent(event_id, true); - return true; -} - -bool ChatHandler::HandleCombatStopCommand(char* args) -{ - Player* target; - if (!ExtractPlayerTarget(&args, &target)) - { - return false; - } - - // check online security - if (HasLowerSecurity(target)) - { - 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(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) - { - HandleLearnSkillRecipesHelper(m_session->GetPlayer(), skillInfo->id); - } - } - - SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT); - return true; -} - -bool ChatHandler::HandleLearnAllRecipesCommand(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) - { - 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, maxLevel, maxLevel); - PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str()); - return true; -} - -bool ChatHandler::HandleLookupAccountEmailCommand(char* args) -{ - char* emailStr = ExtractQuotedOrLiteralArg(&args); - if (!emailStr) - { - return false; - } - - uint32 limit; - if (!ExtractOptUInt32(&args, limit, 100)) - { - return false; - } - - std::string email = emailStr; - LoginDatabase.escape_string(email); - // 0 1 2 3 4 - QueryResult* result = LoginDatabase.PQuery("SELECT `id`, `username`, `last_ip`, `gmlevel`, `expansion` FROM `account` WHERE `email` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), email.c_str()); - - return ShowAccountListHelper(result, &limit); -} - -bool ChatHandler::HandleLookupAccountIpCommand(char* args) -{ - char* ipStr = ExtractQuotedOrLiteralArg(&args); - if (!ipStr) - { - return false; - } - - uint32 limit; - if (!ExtractOptUInt32(&args, limit, 100)) - { - return false; - } - - std::string ip = ipStr; - LoginDatabase.escape_string(ip); - - // 0 1 2 3 4 - QueryResult* result = LoginDatabase.PQuery("SELECT `id`, `username`, `last_ip`, `gmlevel`, `expansion` FROM `account` WHERE `last_ip` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), ip.c_str()); - - return ShowAccountListHelper(result, &limit); -} - -bool ChatHandler::HandleLookupAccountNameCommand(char* args) -{ - char* accountStr = ExtractQuotedOrLiteralArg(&args); - if (!accountStr) - { - return false; - } - - uint32 limit; - if (!ExtractOptUInt32(&args, limit, 100)) - { - return false; - } - - std::string account = accountStr; - if (!AccountMgr::normalizeString(account)) - { - return false; - } - - LoginDatabase.escape_string(account); - // 0 1 2 3 4 - QueryResult* result = LoginDatabase.PQuery("SELECT `id`, `username`, `last_ip`, `gmlevel`, `expansion` FROM `account` WHERE `username` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), account.c_str()); - - return ShowAccountListHelper(result, &limit); -} - -bool ChatHandler::ShowAccountListHelper(QueryResult* result, uint32* limit, bool title, bool error) -{ - if (!result) - { - if (error) - { - SendSysMessage(LANG_ACCOUNT_LIST_EMPTY); - } - return true; - } - - ///- Display the list of account/characters online - if (!m_session && title) // not output header for online case - { - SendSysMessage(LANG_ACCOUNT_LIST_BAR); - SendSysMessage(LANG_ACCOUNT_LIST_HEADER); - SendSysMessage(LANG_ACCOUNT_LIST_BAR); - } - - ///- Circle through accounts - do - { - // check limit - if (limit) - { - if (*limit == 0) - { - break; - } - --*limit; - } - - Field* fields = result->Fetch(); - uint32 account = fields[0].GetUInt32(); - - WorldSession* session = sWorld.FindSession(account); - Player* player = session ? session->GetPlayer() : NULL; - char const* char_name = player ? player->GetName() : " - "; - - if (m_session) - PSendSysMessage(LANG_ACCOUNT_LIST_LINE_CHAT, - account, fields[1].GetString(), char_name, fields[2].GetString(), fields[3].GetUInt32(), fields[4].GetUInt32()); - else - PSendSysMessage(LANG_ACCOUNT_LIST_LINE_CONSOLE, - account, fields[1].GetString(), char_name, fields[2].GetString(), fields[3].GetUInt32(), fields[4].GetUInt32()); - } - while (result->NextRow()); - - delete result; - - if (!m_session) // not output header for online case - { - SendSysMessage(LANG_ACCOUNT_LIST_BAR); - } - - return true; -} - -bool ChatHandler::HandleLookupPlayerIpCommand(char* args) -{ - char* ipStr = ExtractQuotedOrLiteralArg(&args); - if (!ipStr) - { - return false; - } - - uint32 limit; - if (!ExtractOptUInt32(&args, limit, 100)) - { - return false; - } - - std::string ip = ipStr; - LoginDatabase.escape_string(ip); - - QueryResult* result = LoginDatabase.PQuery("SELECT `id`,`username` FROM `account` WHERE `last_ip` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), ip.c_str()); - - return LookupPlayerSearchCommand(result, &limit); -} - -bool ChatHandler::HandleLookupPlayerAccountCommand(char* args) -{ - char* accountStr = ExtractQuotedOrLiteralArg(&args); - if (!accountStr) - { - return false; - } - - uint32 limit; - if (!ExtractOptUInt32(&args, limit, 100)) - { - return false; - } - - std::string account = accountStr; - if (!AccountMgr::normalizeString(account)) - { - return false; - } - - LoginDatabase.escape_string(account); - - QueryResult* result = LoginDatabase.PQuery("SELECT `id`,`username` FROM `account` WHERE `username` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), account.c_str()); - - return LookupPlayerSearchCommand(result, &limit); -} - -bool ChatHandler::HandleLookupPlayerEmailCommand(char* args) -{ - char* emailStr = ExtractQuotedOrLiteralArg(&args); - if (!emailStr) - { - return false; - } - - uint32 limit; - if (!ExtractOptUInt32(&args, limit, 100)) - { - return false; - } - - std::string email = emailStr; - LoginDatabase.escape_string(email); - - QueryResult* result = LoginDatabase.PQuery("SELECT `id`,`username` FROM `account` WHERE `email` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), email.c_str()); - - return LookupPlayerSearchCommand(result, &limit); -} - -bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, uint32* limit) -{ - if (!result) - { - PSendSysMessage(LANG_NO_PLAYERS_FOUND); - SetSentErrorMessage(true); - return false; - } - - uint32 limit_original = limit ? *limit : 100; - - uint32 limit_local = limit_original; - - if (!limit) - { - limit = &limit_local; - } - - do - { - if (limit && *limit == 0) - { - break; - } - - Field* fields = result->Fetch(); - uint32 acc_id = fields[0].GetUInt32(); - std::string acc_name = fields[1].GetCppString(); - - ///- Get the characters for account id - QueryResult* chars = CharacterDatabase.PQuery("SELECT `guid`, `name`, `race`, `class`, `level` FROM `characters` WHERE `account` = %u", acc_id); - if (chars) - { - if (chars->GetRowCount()) - { - PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT, acc_name.c_str(), acc_id); - ShowPlayerListHelper(chars, limit, true, false); - } - else - { - delete chars; - } - } - } - while (result->NextRow()); - - delete result; - - if (*limit == limit_original) // empty accounts only - { - PSendSysMessage(LANG_NO_PLAYERS_FOUND); - SetSentErrorMessage(true); - return false; - } - - return true; -} - -void ChatHandler::ShowPoolListHelper(uint16 pool_id) -{ - PoolTemplateData const& pool_template = sPoolMgr.GetPoolTemplate(pool_id); - if (m_session) - PSendSysMessage(LANG_POOL_ENTRY_LIST_CHAT, - pool_id, pool_id, pool_template.description.c_str(), pool_template.AutoSpawn ? 1 : 0, pool_template.MaxLimit, - sPoolMgr.GetPoolCreatures(pool_id).size(), sPoolMgr.GetPoolGameObjects(pool_id).size(), sPoolMgr.GetPoolPools(pool_id).size()); - else - PSendSysMessage(LANG_POOL_ENTRY_LIST_CONSOLE, - pool_id, pool_template.description.c_str(), pool_template.AutoSpawn ? 1 : 0, pool_template.MaxLimit, - sPoolMgr.GetPoolCreatures(pool_id).size(), sPoolMgr.GetPoolGameObjects(pool_id).size(), sPoolMgr.GetPoolPools(pool_id).size()); -} - -bool ChatHandler::HandleLookupPoolCommand(char* args) -{ - if (!*args) - { - return false; - } - - std::string namepart = args; - strToLower(namepart); - - uint32 counter = 0; - - // spawn pools for expected map or for not initialized shared pools state for non-instanceable maps - for (uint16 pool_id = 0; pool_id < sPoolMgr.GetMaxPoolId(); ++pool_id) - { - PoolTemplateData const& pool_template = sPoolMgr.GetPoolTemplate(pool_id); - - std::string desc = pool_template.description; - strToLower(desc); - - if (desc.find(namepart) == std::wstring::npos) - { - continue; - } - - ShowPoolListHelper(pool_id); - ++counter; - } - - if (counter == 0) - { - SendSysMessage(LANG_NO_POOL); - } - - return true; -} - -bool ChatHandler::HandlePoolListCommand(char* /*args*/) -{ - Player* player = m_session->GetPlayer(); - - MapPersistentState* mapState = player->GetMap()->GetPersistentState(); - - if (!mapState->GetMapEntry()->Instanceable()) - { - PSendSysMessage(LANG_POOL_LIST_NON_INSTANCE, mapState->GetMapEntry()->name[GetSessionDbcLocale()], mapState->GetMapId()); - SetSentErrorMessage(false); - return false; - } - - uint32 counter = 0; - - // spawn pools for expected map or for not initialized shared pools state for non-instanceable maps - for (uint16 pool_id = 0; pool_id < sPoolMgr.GetMaxPoolId(); ++pool_id) - { - if (sPoolMgr.GetPoolTemplate(pool_id).CanBeSpawnedAtMap(mapState->GetMapEntry())) - { - ShowPoolListHelper(pool_id); - ++counter; - } - } - - if (counter == 0) - { - PSendSysMessage(LANG_NO_POOL_FOR_MAP, mapState->GetMapEntry()->name[GetSessionDbcLocale()], mapState->GetMapId()); - } - - return true; -} - -bool ChatHandler::HandlePoolSpawnsCommand(char* args) -{ - Player* player = m_session->GetPlayer(); - - MapPersistentState* mapState = player->GetMap()->GetPersistentState(); - - // shared continent pools data expected too big for show - uint32 pool_id = 0; - if (!ExtractUint32KeyFromLink(&args, "Hpool", pool_id) && !mapState->GetMapEntry()->Instanceable()) - { - PSendSysMessage(LANG_POOL_SPAWNS_NON_INSTANCE, mapState->GetMapEntry()->name[GetSessionDbcLocale()], mapState->GetMapId()); - SetSentErrorMessage(false); - return false; - } - - SpawnedPoolData const& spawns = mapState->GetSpawnedPoolData(); - - SpawnedPoolObjects const& crSpawns = spawns.GetSpawnedCreatures(); - for (SpawnedPoolObjects::const_iterator itr = crSpawns.begin(); itr != crSpawns.end(); ++itr) - if (!pool_id || pool_id == sPoolMgr.IsPartOfAPool(*itr)) - if (CreatureData const* data = sObjectMgr.GetCreatureData(*itr)) - if (CreatureInfo const* info = ObjectMgr::GetCreatureTemplate(data->id)) - PSendSysMessage(LANG_CREATURE_LIST_CHAT, *itr, PrepareStringNpcOrGoSpawnInformation(*itr).c_str(), - *itr, info->Name, data->posX, data->posY, data->posZ, data->mapid); - - SpawnedPoolObjects const& goSpawns = spawns.GetSpawnedGameobjects(); - for (SpawnedPoolObjects::const_iterator itr = goSpawns.begin(); itr != goSpawns.end(); ++itr) - if (!pool_id || pool_id == sPoolMgr.IsPartOfAPool(*itr)) - if (GameObjectData const* data = sObjectMgr.GetGOData(*itr)) - if (GameObjectInfo const* info = ObjectMgr::GetGameObjectInfo(data->id)) - PSendSysMessage(LANG_GO_LIST_CHAT, *itr, PrepareStringNpcOrGoSpawnInformation(*itr).c_str(), - *itr, info->name, data->posX, data->posY, data->posZ, data->mapid); - - return true; -} - -bool ChatHandler::HandlePoolInfoCommand(char* args) -{ - // id or [name] Shift-click form |color|Hpool:id|h[name]|h|r - uint32 pool_id; - if (!ExtractUint32KeyFromLink(&args, "Hpool", pool_id)) - { - return false; - } - - if (pool_id > sPoolMgr.GetMaxPoolId()) - { - PSendSysMessage(LANG_POOL_ENTRY_LOWER_MAX_POOL, pool_id, sPoolMgr.GetMaxPoolId()); - return true; - } - - Player* player = m_session ? m_session->GetPlayer() : NULL; - - MapPersistentState* mapState = player ? player->GetMap()->GetPersistentState() : NULL; - SpawnedPoolData const* spawns = mapState ? &mapState->GetSpawnedPoolData() : NULL; - - std::string active_str = GetMangosString(LANG_ACTIVE); - - PoolTemplateData const& pool_template = sPoolMgr.GetPoolTemplate(pool_id); - uint32 mother_pool_id = sPoolMgr.IsPartOfAPool(pool_id); - if (!mother_pool_id) - { - PSendSysMessage(LANG_POOL_INFO_HEADER, pool_id, pool_template.AutoSpawn, pool_template.MaxLimit); - } - else - { - PoolTemplateData const& mother_template = sPoolMgr.GetPoolTemplate(mother_pool_id); - if (m_session) - PSendSysMessage(LANG_POOL_INFO_HEADER_CHAT, pool_id, mother_pool_id, mother_pool_id, mother_template.description.c_str(), - pool_template.AutoSpawn, pool_template.MaxLimit); - else - PSendSysMessage(LANG_POOL_INFO_HEADER_CONSOLE, pool_id, mother_pool_id, mother_template.description.c_str(), - pool_template.AutoSpawn, pool_template.MaxLimit); - } - - PoolGroup const& poolCreatures = sPoolMgr.GetPoolCreatures(pool_id); - SpawnedPoolObjects const* crSpawns = spawns ? &spawns->GetSpawnedCreatures() : NULL; - - PoolObjectList const& poolCreaturesEx = poolCreatures.GetExplicitlyChanced(); - if (!poolCreaturesEx.empty()) - { - SendSysMessage(LANG_POOL_CHANCE_CREATURE_LIST_HEADER); - for (PoolObjectList::const_iterator itr = poolCreaturesEx.begin(); itr != poolCreaturesEx.end(); ++itr) - { - if (CreatureData const* data = sObjectMgr.GetCreatureData(itr->guid)) - { - if (CreatureInfo const* info = ObjectMgr::GetCreatureTemplate(data->id)) - { - char const* active = crSpawns && crSpawns->find(itr->guid) != crSpawns->end() ? active_str.c_str() : ""; - if (m_session) - PSendSysMessage(LANG_POOL_CHANCE_CREATURE_LIST_CHAT, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), - itr->guid, info->Name, data->posX, data->posY, data->posZ, data->mapid, itr->chance, active); - else - PSendSysMessage(LANG_POOL_CHANCE_CREATURE_LIST_CONSOLE, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), - info->Name, data->posX, data->posY, data->posZ, data->mapid, itr->chance, active); - } - } - } - } - - PoolObjectList const& poolCreaturesEq = poolCreatures.GetEqualChanced(); - if (!poolCreaturesEq.empty()) - { - SendSysMessage(LANG_POOL_CREATURE_LIST_HEADER); - for (PoolObjectList::const_iterator itr = poolCreaturesEq.begin(); itr != poolCreaturesEq.end(); ++itr) - { - if (CreatureData const* data = sObjectMgr.GetCreatureData(itr->guid)) - { - if (CreatureInfo const* info = ObjectMgr::GetCreatureTemplate(data->id)) - { - char const* active = crSpawns && crSpawns->find(itr->guid) != crSpawns->end() ? active_str.c_str() : ""; - if (m_session) - PSendSysMessage(LANG_POOL_CREATURE_LIST_CHAT, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), - itr->guid, info->Name, data->posX, data->posY, data->posZ, data->mapid, active); - else - PSendSysMessage(LANG_POOL_CREATURE_LIST_CONSOLE, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), - info->Name, data->posX, data->posY, data->posZ, data->mapid, active); - } - } - } - } - - PoolGroup const& poolGameObjects = sPoolMgr.GetPoolGameObjects(pool_id); - SpawnedPoolObjects const* goSpawns = spawns ? &spawns->GetSpawnedGameobjects() : NULL; - - PoolObjectList const& poolGameObjectsEx = poolGameObjects.GetExplicitlyChanced(); - if (!poolGameObjectsEx.empty()) - { - SendSysMessage(LANG_POOL_CHANCE_GO_LIST_HEADER); - for (PoolObjectList::const_iterator itr = poolGameObjectsEx.begin(); itr != poolGameObjectsEx.end(); ++itr) - { - if (GameObjectData const* data = sObjectMgr.GetGOData(itr->guid)) - { - if (GameObjectInfo const* info = ObjectMgr::GetGameObjectInfo(data->id)) - { - char const* active = goSpawns && goSpawns->find(itr->guid) != goSpawns->end() ? active_str.c_str() : ""; - if (m_session) - PSendSysMessage(LANG_POOL_CHANCE_GO_LIST_CHAT, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), - itr->guid, info->name, data->posX, data->posY, data->posZ, data->mapid, itr->chance, active); - else - PSendSysMessage(LANG_POOL_CHANCE_GO_LIST_CONSOLE, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), - info->name, data->posX, data->posY, data->posZ, data->mapid, itr->chance, active); - } - } - } - } - - PoolObjectList const& poolGameObjectsEq = poolGameObjects.GetEqualChanced(); - if (!poolGameObjectsEq.empty()) - { - SendSysMessage(LANG_POOL_GO_LIST_HEADER); - for (PoolObjectList::const_iterator itr = poolGameObjectsEq.begin(); itr != poolGameObjectsEq.end(); ++itr) - { - if (GameObjectData const* data = sObjectMgr.GetGOData(itr->guid)) - { - if (GameObjectInfo const* info = ObjectMgr::GetGameObjectInfo(data->id)) - { - char const* active = goSpawns && goSpawns->find(itr->guid) != goSpawns->end() ? active_str.c_str() : ""; - if (m_session) - PSendSysMessage(LANG_POOL_GO_LIST_CHAT, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), - itr->guid, info->name, data->posX, data->posY, data->posZ, data->mapid, active); - else - PSendSysMessage(LANG_POOL_GO_LIST_CONSOLE, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), - info->name, data->posX, data->posY, data->posZ, data->mapid, active); - } - } - } - } - - PoolGroup const& poolPools = sPoolMgr.GetPoolPools(pool_id); - SpawnedPoolPools const* poolSpawns = spawns ? &spawns->GetSpawnedPools() : NULL; - - PoolObjectList const& poolPoolsEx = poolPools.GetExplicitlyChanced(); - if (!poolPoolsEx.empty()) - { - SendSysMessage(LANG_POOL_CHANCE_POOL_LIST_HEADER); - for (PoolObjectList::const_iterator itr = poolPoolsEx.begin(); itr != poolPoolsEx.end(); ++itr) - { - PoolTemplateData const& itr_template = sPoolMgr.GetPoolTemplate(itr->guid); - char const* active = poolSpawns && poolSpawns->find(itr->guid) != poolSpawns->end() ? active_str.c_str() : ""; - if (m_session) - PSendSysMessage(LANG_POOL_CHANCE_POOL_LIST_CHAT, itr->guid, - itr->guid, itr_template.description.c_str(), itr_template.AutoSpawn ? 1 : 0, itr_template.MaxLimit, - sPoolMgr.GetPoolCreatures(itr->guid).size(), sPoolMgr.GetPoolGameObjects(itr->guid).size(), sPoolMgr.GetPoolPools(itr->guid).size(), - itr->chance, active); - else - PSendSysMessage(LANG_POOL_CHANCE_POOL_LIST_CONSOLE, itr->guid, - itr_template.description.c_str(), itr_template.AutoSpawn ? 1 : 0, itr_template.MaxLimit, - sPoolMgr.GetPoolCreatures(itr->guid).size(), sPoolMgr.GetPoolGameObjects(itr->guid).size(), sPoolMgr.GetPoolPools(itr->guid).size(), - itr->chance, active); - } - } - - PoolObjectList const& poolPoolsEq = poolPools.GetEqualChanced(); - if (!poolPoolsEq.empty()) - { - SendSysMessage(LANG_POOL_POOL_LIST_HEADER); - for (PoolObjectList::const_iterator itr = poolPoolsEq.begin(); itr != poolPoolsEq.end(); ++itr) - { - PoolTemplateData const& itr_template = sPoolMgr.GetPoolTemplate(itr->guid); - char const* active = poolSpawns && poolSpawns->find(itr->guid) != poolSpawns->end() ? active_str.c_str() : ""; - if (m_session) - PSendSysMessage(LANG_POOL_POOL_LIST_CHAT, itr->guid, - itr->guid, itr_template.description.c_str(), itr_template.AutoSpawn ? 1 : 0, itr_template.MaxLimit, - sPoolMgr.GetPoolCreatures(itr->guid).size(), sPoolMgr.GetPoolGameObjects(itr->guid).size(), sPoolMgr.GetPoolPools(itr->guid).size(), - active); - else - PSendSysMessage(LANG_POOL_POOL_LIST_CONSOLE, itr->guid, - itr_template.description.c_str(), itr_template.AutoSpawn ? 1 : 0, itr_template.MaxLimit, - sPoolMgr.GetPoolCreatures(itr->guid).size(), sPoolMgr.GetPoolGameObjects(itr->guid).size(), sPoolMgr.GetPoolPools(itr->guid).size(), - active); - } - } - return true; -} - -/// Triggering corpses expire check in world -bool ChatHandler::HandleServerCorpsesCommand(char* /*args*/) -{ - sObjectAccessor.RemoveOldCorpses(); - return true; -} - -bool ChatHandler::HandleRepairitemsCommand(char* args) -{ - Player* target; - if (!ExtractPlayerTarget(&args, &target)) - { - return false; - } - - // check online security - if (HasLowerSecurity(target)) - { - 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(char* args) -{ - bool value; - if (!ExtractOnOff(&args, value)) - { - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; - } - - Player* player = getSelectedPlayer(); - - if (!player) - { - PSendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(player)) - { - return false; - } - - if (value) - { - player->SetWaterWalk(true); // ON - } - else - { - player->SetWaterWalk(false); // OFF - } - - 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::HandleLookupTitleCommand(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) ? GetMangosString(LANG_KNOWN) : ""; - - char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index - ? GetMangosString(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(char* args) -{ - // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r - uint32 id; - if (!ExtractUint32KeyFromLink(&args, "Htitle", id)) - { - return false; - } - - 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)) - { - 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(char* args) -{ - // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r - uint32 id; - if (!ExtractUint32KeyFromLink(&args, "Htitle", id)) - { - return false; - } - - 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)) - { - 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(char* args) -{ - if (!*args) - { - return false; - } - - uint64 titles = 0; - - sscanf(args, UI64FMTD, &titles); - - Player* target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target)) - { - 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 nonexistent 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(char* args) -{ - Player* target; - if (!ExtractPlayerTarget(&args, &target)) - { - return false; - } - - LocaleConstant loc = GetSessionDbcLocale(); - char const* targetName = target->GetName(); - char const* knownStr = GetMangosString(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 - ? GetMangosString(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(char* args) -{ - // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r - uint32 id; - if (!ExtractUint32KeyFromLink(&args, "Htitle", id)) - { - return false; - } - - 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)) - { - 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; -} - -bool ChatHandler::HandleMmapPathCommand(char* args) -{ - if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(m_session->GetPlayer()->GetMapId())) - { - PSendSysMessage("NavMesh not loaded for current map."); - return true; - } - - PSendSysMessage("mmap path:"); - - // units - Player* player = m_session->GetPlayer(); - Unit* target = getSelectedUnit(); - if (!player || !target) - { - PSendSysMessage("Invalid target/source selection."); - return true; - } - - char* para = strtok(args, " "); - - bool useStraightPath = false; - bool followPath = false; - bool unitToPlayer = false; - if (para) - { - if (strcmp(para, "go") == 0) - { - followPath = true; - para = strtok(NULL, " "); - if (para && strcmp(para, "straight") == 0) - { - useStraightPath = true; - } - } - else if (strcmp(para, "straight") == 0) - { - useStraightPath = true; - } - else if (strcmp(para, "to_me") == 0) - { - unitToPlayer = true; - } - else - { - PSendSysMessage("Use '.mmap path go' to move on target."); - PSendSysMessage("Use '.mmap path straight' to generate straight path."); - PSendSysMessage("Use '.mmap path to_me' to generate path from the target to you."); - } - } - - Unit* destinationUnit; - Unit* originUnit; - if (unitToPlayer) - { - destinationUnit = player; - originUnit = target; - } - else - { - destinationUnit = target; - originUnit = player; - } - - // unit locations - float x, y, z; - destinationUnit->GetPosition(x, y, z); - - // path - PathFinder path(originUnit); - path.setUseStrightPath(useStraightPath); - path.calculate(x, y, z); - - PointsArray pointPath = path.getPath(); - PSendSysMessage("%s's path to %s:", originUnit->GetName(), destinationUnit->GetName()); - PSendSysMessage("Building %s", useStraightPath ? "StraightPath" : "SmoothPath"); - PSendSysMessage("length " SIZEFMTD " type %u", pointPath.size(), path.getPathType()); - - Vector3 start = path.getStartPosition(); - Vector3 end = path.getEndPosition(); - Vector3 actualEnd = path.getActualEndPosition(); - - PSendSysMessage("start (%.3f, %.3f, %.3f)", start.x, start.y, start.z); - PSendSysMessage("end (%.3f, %.3f, %.3f)", end.x, end.y, end.z); - PSendSysMessage("actual end (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z); - - if (!player->isGameMaster()) - { - PSendSysMessage("Enable GM mode to see the path points."); - } - - for (uint32 i = 0; i < pointPath.size(); ++i) - { - player->SummonCreature(VISUAL_WAYPOINT, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000); - } - - if (followPath) - { - Movement::MoveSplineInit init(*player); - init.MovebyPath(pointPath); - init.SetWalk(false); - init.Launch(); - } - - return true; -} - -bool ChatHandler::HandleMmapLocCommand(char* /*args*/) -{ - PSendSysMessage("mmap tileloc:"); - - // grid tile location - Player* player = m_session->GetPlayer(); - - int32 gx = 32 - player->GetPositionX() / SIZE_OF_GRIDS; - int32 gy = 32 - player->GetPositionY() / SIZE_OF_GRIDS; - - PSendSysMessage("%03u%02i%02i.mmtile", player->GetMapId(), gy, gx); - PSendSysMessage("gridloc [%i,%i]", gx, gy); - - // calculate navmesh tile location - const dtNavMesh* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(player->GetMapId()); - const dtNavMeshQuery* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(player->GetMapId(), player->GetInstanceId()); - if (!navmesh || !navmeshquery) - { - PSendSysMessage("NavMesh not loaded for current map."); - return true; - } - - const float* min = navmesh->getParams()->orig; - - float x, y, z; - player->GetPosition(x, y, z); - float location[VERTEX_SIZE] = {y, z, x}; - float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; - - int32 tilex = int32((y - min[0]) / SIZE_OF_GRIDS); - int32 tiley = int32((x - min[2]) / SIZE_OF_GRIDS); - - PSendSysMessage("Calc [%02i,%02i]", tilex, tiley); - - // navmesh poly -> navmesh tile location - dtQueryFilter filter = dtQueryFilter(); - dtPolyRef polyRef = INVALID_POLYREF; - navmeshquery->findNearestPoly(location, extents, &filter, &polyRef, NULL); - - if (polyRef == INVALID_POLYREF) - { - PSendSysMessage("Dt [??,??] (invalid poly, probably no tile loaded)"); - } - else - { - const dtMeshTile* tile; - const dtPoly* poly; - dtStatus dtResult = navmesh->getTileAndPolyByRef(polyRef, &tile, &poly); - if ((dtStatusSucceed(dtResult)) && tile) - { - PSendSysMessage("Dt [%02i,%02i]", tile->header->x, tile->header->y); - } - else - { - PSendSysMessage("Dt [??,??] (no tile loaded)"); - } - } - - return true; -} - -bool ChatHandler::HandleMmapLoadedTilesCommand(char* /*args*/) -{ - uint32 mapid = m_session->GetPlayer()->GetMapId(); - - const dtNavMesh* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid); - const dtNavMeshQuery* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, m_session->GetPlayer()->GetInstanceId()); - if (!navmesh || !navmeshquery) - { - PSendSysMessage("NavMesh not loaded for current map."); - return true; - } - - PSendSysMessage("mmap loadedtiles:"); - - for (int32 i = 0; i < navmesh->getMaxTiles(); ++i) - { - const dtMeshTile* tile = navmesh->getTile(i); - if (!tile || !tile->header) - { - continue; - } - - PSendSysMessage("[%02i,%02i]", tile->header->x, tile->header->y); - } - - return true; -} - -bool ChatHandler::HandleMmapStatsCommand(char* /*args*/) -{ - PSendSysMessage("mmap stats:"); - PSendSysMessage(" global mmap pathfinding is %sabled", sWorld.getConfig(CONFIG_BOOL_MMAP_ENABLED) ? "en" : "dis"); - - MMAP::MMapManager* manager = MMAP::MMapFactory::createOrGetMMapManager(); - PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount()); - - const dtNavMesh* navmesh = manager->GetNavMesh(m_session->GetPlayer()->GetMapId()); - if (!navmesh) - { - PSendSysMessage("NavMesh not loaded for current map."); - return true; - } - - uint32 tileCount = 0; - uint32 nodeCount = 0; - uint32 polyCount = 0; - uint32 vertCount = 0; - uint32 triCount = 0; - uint32 triVertCount = 0; - uint32 dataSize = 0; - for (int32 i = 0; i < navmesh->getMaxTiles(); ++i) - { - const dtMeshTile* tile = navmesh->getTile(i); - if (!tile || !tile->header) - { - continue; - } - - tileCount ++; - nodeCount += tile->header->bvNodeCount; - polyCount += tile->header->polyCount; - vertCount += tile->header->vertCount; - triCount += tile->header->detailTriCount; - triVertCount += tile->header->detailVertCount; - dataSize += tile->dataSize; - } - - PSendSysMessage("Navmesh stats on current map:"); - PSendSysMessage(" %u tiles loaded", tileCount); - PSendSysMessage(" %u BVTree nodes", nodeCount); - PSendSysMessage(" %u polygons (%u vertices)", polyCount, vertCount); - PSendSysMessage(" %u triangles (%u vertices)", triCount, triVertCount); - PSendSysMessage(" %.2f MB of data (not including pointers)", ((float)dataSize / sizeof(unsigned char)) / 1048576); - - return true; -} diff --git a/src/game/ChatCommands/Level3.cpp b/src/game/ChatCommands/Level3.cpp deleted file mode 100644 index 5e6048e667d33..0000000000000 --- a/src/game/ChatCommands/Level3.cpp +++ /dev/null @@ -1,7697 +0,0 @@ -/** - * MaNGOS is a full featured server for World of Warcraft, supporting - * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 - * - * Copyright (C) 2005-2020 MaNGOS - * - * 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 - * - * World of Warcraft, and all World of Warcraft or Warcraft art, images, - * and lore are copyrighted by Blizzard Entertainment, Inc. - */ - -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "WorldSession.h" -#include "World.h" -#include "ObjectMgr.h" -#include "AccountMgr.h" -#include "PlayerDump.h" -#include "SpellMgr.h" -#include "Player.h" -#include "GameObject.h" -#include "Chat.h" -#include "Log.h" -#include "Guild.h" -#include "GuildMgr.h" -#include "ObjectAccessor.h" -#include "MapManager.h" -#include "MassMailMgr.h" -#include "ScriptMgr.h" -#include "Language.h" -#include "GridNotifiersImpl.h" -#include "CellImpl.h" -#include "Weather.h" -#include "PointMovementGenerator.h" -#include "PathFinder.h" -#include "TargetedMovementGenerator.h" -#include "SkillDiscovery.h" -#include "SkillExtraItems.h" -#include "SystemConfig.h" -#include "Config/Config.h" -#include "Mail.h" -#include "Util.h" -#include "ItemEnchantmentMgr.h" -#include "BattleGround/BattleGroundMgr.h" -#include "MapPersistentStateMgr.h" -#include "InstanceData.h" -#include "DBCStores.h" -#include "CreatureEventAIMgr.h" -#include "AuctionHouseBot/AuctionHouseBot.h" -#include "SQLStorages.h" -#include "DisableMgr.h" - -static uint32 ahbotQualityIds[MAX_AUCTION_QUALITY] = -{ - LANG_AHBOT_QUALITY_GREY, LANG_AHBOT_QUALITY_WHITE, - LANG_AHBOT_QUALITY_GREEN, LANG_AHBOT_QUALITY_BLUE, - LANG_AHBOT_QUALITY_PURPLE, LANG_AHBOT_QUALITY_ORANGE, - LANG_AHBOT_QUALITY_YELLOW -}; - -bool ChatHandler::HandleAHBotItemsAmountCommand(char* args) -{ - uint32 qVals[MAX_AUCTION_QUALITY]; - for (int i = 0; i < MAX_AUCTION_QUALITY; ++i) - if (!ExtractUInt32(&args, qVals[i])) - { - return false; - } - - sAuctionBot.SetItemsAmount(qVals); - - for (int i = 0; i < MAX_AUCTION_QUALITY; ++i) - { - PSendSysMessage(LANG_AHBOT_ITEMS_AMOUNT, GetMangosString(ahbotQualityIds[i]), sAuctionBotConfig.getConfigItemQualityAmount(AuctionQuality(i))); - } - - return true; -} - -template -bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char* args) -{ - uint32 qVal; - if (!ExtractUInt32(&args, qVal)) - { - return false; - } - sAuctionBot.SetItemsAmountForQuality(AuctionQuality(Q), qVal); - PSendSysMessage(LANG_AHBOT_ITEMS_AMOUNT, GetMangosString(ahbotQualityIds[Q]), - sAuctionBotConfig.getConfigItemQualityAmount(AuctionQuality(Q))); - return true; -} - -template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); -template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); -template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); -template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); -template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); -template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); -template bool ChatHandler::HandleAHBotItemsAmountQualityCommand(char*); - -bool ChatHandler::HandleAHBotItemsRatioCommand(char* args) -{ - uint32 rVal[MAX_AUCTION_HOUSE_TYPE]; - for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i) - if (!ExtractUInt32(&args, rVal[i])) - { - return false; - } - - sAuctionBot.SetItemsRatio(rVal[0], rVal[1], rVal[2]); - - for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i) - { - PSendSysMessage(LANG_AHBOT_ITEMS_RATIO, AuctionBotConfig::GetHouseTypeName(AuctionHouseType(i)), sAuctionBotConfig.getConfigItemAmountRatio(AuctionHouseType(i))); - } - return true; -} - -template -bool ChatHandler::HandleAHBotItemsRatioHouseCommand(char* args) -{ - uint32 rVal; - if (!ExtractUInt32(&args, rVal)) - { - return false; - } - sAuctionBot.SetItemsRatioForHouse(AuctionHouseType(H), rVal); - PSendSysMessage(LANG_AHBOT_ITEMS_RATIO, AuctionBotConfig::GetHouseTypeName(AuctionHouseType(H)), sAuctionBotConfig.getConfigItemAmountRatio(AuctionHouseType(H))); - return true; -} - -template bool ChatHandler::HandleAHBotItemsRatioHouseCommand(char*); -template bool ChatHandler::HandleAHBotItemsRatioHouseCommand(char*); -template bool ChatHandler::HandleAHBotItemsRatioHouseCommand(char*); - -bool ChatHandler::HandleAHBotRebuildCommand(char* args) -{ - bool all = false; - if (*args) - { - if (!ExtractLiteralArg(&args, "all")) - { - return false; - } - all = true; - } - - sAuctionBot.Rebuild(all); - return true; -} - -bool ChatHandler::HandleAHBotReloadCommand(char* /*args*/) -{ - if (sAuctionBot.ReloadAllConfig()) - { - SendSysMessage(LANG_AHBOT_RELOAD_OK); - return true; - } - else - { - SendSysMessage(LANG_AHBOT_RELOAD_FAIL); - SetSentErrorMessage(true); - return false; - } -} - -bool ChatHandler::HandleAHBotStatusCommand(char* args) -{ - bool all = false; - if (*args) - { - if (!ExtractLiteralArg(&args, "all")) - { - return false; - } - all = true; - } - - AuctionHouseBotStatusInfo statusInfo; - sAuctionBot.PrepareStatusInfos(statusInfo); - - if (!m_session) - { - SendSysMessage(LANG_AHBOT_STATUS_BAR_CONSOLE); - SendSysMessage(LANG_AHBOT_STATUS_TITLE1_CONSOLE); - SendSysMessage(LANG_AHBOT_STATUS_MIDBAR_CONSOLE); - } - else - { - SendSysMessage(LANG_AHBOT_STATUS_TITLE1_CHAT); - } - - uint32 fmtId = m_session ? LANG_AHBOT_STATUS_FORMAT_CHAT : LANG_AHBOT_STATUS_FORMAT_CONSOLE; - - PSendSysMessage(fmtId, GetMangosString(LANG_AHBOT_STATUS_ITEM_COUNT), - statusInfo[AUCTION_HOUSE_ALLIANCE].ItemsCount, - statusInfo[AUCTION_HOUSE_HORDE].ItemsCount, - statusInfo[AUCTION_HOUSE_NEUTRAL].ItemsCount, - statusInfo[AUCTION_HOUSE_ALLIANCE].ItemsCount + - statusInfo[AUCTION_HOUSE_HORDE].ItemsCount + - statusInfo[AUCTION_HOUSE_NEUTRAL].ItemsCount); - - if (all) - { - PSendSysMessage(fmtId, GetMangosString(LANG_AHBOT_STATUS_ITEM_RATIO), - sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO), - sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_HORDE_ITEM_AMOUNT_RATIO), - sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO), - sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO) + - sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_HORDE_ITEM_AMOUNT_RATIO) + - sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO)); - - if (!m_session) - { - SendSysMessage(LANG_AHBOT_STATUS_BAR_CONSOLE); - SendSysMessage(LANG_AHBOT_STATUS_TITLE2_CONSOLE); - SendSysMessage(LANG_AHBOT_STATUS_MIDBAR_CONSOLE); - } - else - { - SendSysMessage(LANG_AHBOT_STATUS_TITLE2_CHAT); - } - - for (int i = 0; i < MAX_AUCTION_QUALITY; ++i) - PSendSysMessage(fmtId, GetMangosString(ahbotQualityIds[i]), - statusInfo[AUCTION_HOUSE_ALLIANCE].QualityInfo[i], - statusInfo[AUCTION_HOUSE_HORDE].QualityInfo[i], - statusInfo[AUCTION_HOUSE_NEUTRAL].QualityInfo[i], - sAuctionBotConfig.getConfigItemQualityAmount(AuctionQuality(i))); - } - - if (!m_session) - { - SendSysMessage(LANG_AHBOT_STATUS_BAR_CONSOLE); - } - - return true; -} - -// reload commands -bool ChatHandler::HandleReloadAllCommand(char* /*args*/) -{ - HandleReloadSkillFishingBaseLevelCommand((char*)""); - - HandleReloadAllAreaCommand((char*)""); - HandleReloadAutoBroadcastCommand((char*)""); - HandleReloadAllEventAICommand((char*)""); - HandleReloadAllLootCommand((char*)""); - HandleReloadAllNpcCommand((char*)""); - HandleReloadAllQuestCommand((char*)""); - HandleReloadAllSpellCommand((char*)""); - HandleReloadAllItemCommand((char*)""); - HandleReloadAllGossipsCommand((char*)""); - HandleReloadAllLocalesCommand((char*)""); - - HandleReloadMailLevelRewardCommand((char*)""); - HandleReloadCommandCommand((char*)""); - HandleReloadReservedNameCommand((char*)""); - HandleReloadMangosStringCommand((char*)""); - HandleReloadGameTeleCommand((char*)""); - HandleReloadBattleEventCommand((char*)""); - return true; -} - -bool ChatHandler::HandleReloadAllAreaCommand(char* /*args*/) -{ - // HandleReloadQuestAreaTriggersCommand((char*)""); -- reloaded in HandleReloadAllQuestCommand - HandleReloadAreaTriggerTeleportCommand((char*)""); - HandleReloadAreaTriggerTavernCommand((char*)""); - HandleReloadGameGraveyardZoneCommand((char*)""); - return true; -} - -bool ChatHandler::HandleReloadAllLootCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Loot Tables..."); - LoadLootTables(); - SendGlobalSysMessage("DB tables `*_loot_template` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadAllNpcCommand(char* args) -{ - HandleReloadNpcTrainerCommand((char*)"a"); - HandleReloadNpcVendorCommand((char*)"a"); - HandleReloadPointsOfInterestCommand((char*)"a"); - return true; -} - -bool ChatHandler::HandleReloadAllQuestCommand(char* /*args*/) -{ - HandleReloadQuestAreaTriggersCommand((char*)"a"); - HandleReloadQuestTemplateCommand((char*)"a"); - - sLog.outString("Re-Loading Quests Relations..."); - sObjectMgr.LoadQuestRelations(); - SendGlobalSysMessage("DB table `quest_relations` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadAllScriptsCommand(char* /*args*/) -{ - if (sScriptMgr.IsScriptScheduled()) - { - PSendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - sLog.outString("Re-Loading Scripts..."); - HandleReloadDBScriptsOnCreatureDeathCommand((char*)"a"); - HandleReloadDBScriptsOnGoUseCommand((char*)"a"); - HandleReloadDBScriptsOnGossipCommand((char*)"a"); - HandleReloadDBScriptsOnEventCommand((char*)"a"); - HandleReloadDBScriptsOnQuestEndCommand((char*)"a"); - HandleReloadDBScriptsOnQuestStartCommand((char*)"a"); - HandleReloadDBScriptsOnSpellCommand((char*)"a"); - SendGlobalSysMessage("DB tables `*_scripts` reloaded.", SEC_MODERATOR); - HandleReloadDbScriptStringCommand((char*)"a"); - return true; -} - -bool ChatHandler::HandleReloadAllEventAICommand(char* /*args*/) -{ - HandleReloadEventAITextsCommand((char*)"a"); - HandleReloadEventAISummonsCommand((char*)"a"); - HandleReloadEventAIScriptsCommand((char*)"a"); - return true; -} - -bool ChatHandler::HandleReloadAllSpellCommand(char* /*args*/) -{ - HandleReloadSkillDiscoveryTemplateCommand((char*)"a"); - HandleReloadSkillExtraItemTemplateCommand((char*)"a"); - HandleReloadSpellAffectCommand((char*)"a"); - HandleReloadSpellAreaCommand((char*)"a"); - HandleReloadSpellChainCommand((char*)"a"); - HandleReloadSpellElixirCommand((char*)"a"); - HandleReloadSpellLearnSpellCommand((char*)"a"); - HandleReloadSpellProcEventCommand((char*)"a"); - HandleReloadSpellBonusesCommand((char*)"a"); - HandleReloadSpellProcItemEnchantCommand((char*)"a"); - HandleReloadSpellScriptTargetCommand((char*)"a"); - HandleReloadSpellTargetPositionCommand((char*)"a"); - HandleReloadSpellThreatsCommand((char*)"a"); - HandleReloadSpellPetAurasCommand((char*)"a"); - HandleReloadSpellLinkedCommand((char*)"a"); - return true; -} - -bool ChatHandler::HandleReloadAllGossipsCommand(char* args) -{ - if (*args != 'a') // already reload from all_scripts - { - HandleReloadDBScriptsOnGossipCommand((char*)"a"); - } - HandleReloadGossipMenuCommand((char*)"a"); - HandleReloadPointsOfInterestCommand((char*)"a"); - return true; -} - -bool ChatHandler::HandleReloadAllItemCommand(char* /*args*/) -{ - HandleReloadPageTextsCommand((char*)"a"); - HandleReloadItemEnchantementsCommand((char*)"a"); - HandleReloadItemRequiredTragetCommand((char*)"a"); - return true; -} - -bool ChatHandler::HandleReloadAllLocalesCommand(char* /*args*/) -{ - HandleReloadLocalesCreatureCommand((char*)"a"); - HandleReloadLocalesGameobjectCommand((char*)"a"); - HandleReloadLocalesGossipMenuOptionCommand((char*)"a"); - HandleReloadLocalesItemCommand((char*)"a"); - HandleReloadLocalesNpcTextCommand((char*)"a"); - HandleReloadLocalesPageTextCommand((char*)"a"); - HandleReloadLocalesPointsOfInterestCommand((char*)"a"); - HandleReloadLocalesQuestCommand((char*)"a"); - return true; -} - -bool ChatHandler::HandleReloadConfigCommand(char* /*args*/) -{ - sLog.outString("Re-Loading config settings..."); - sWorld.LoadConfigSettings(true); - sMapMgr.InitializeVisibilityDistanceInfo(); - SendGlobalSysMessage("World config settings reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadAreaTriggerTavernCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Tavern Area Triggers..."); - sObjectMgr.LoadTavernAreaTriggers(); - SendGlobalSysMessage("DB table `areatrigger_tavern` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadAreaTriggerTeleportCommand(char* /*args*/) -{ - sLog.outString("Re-Loading AreaTrigger teleport definitions..."); - sObjectMgr.LoadAreaTriggerTeleports(); - SendGlobalSysMessage("DB table `areatrigger_teleport` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadAutoBroadcastCommand(char* /*args*/) -{ - sLog.outString("Re-Loading broadcast strings..."); - sWorld.LoadBroadcastStrings(); - SendGlobalSysMessage("Broadcast strings reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadCommandCommand(char* /*args*/) -{ - load_command_table = true; - SendGlobalSysMessage("DB table `command` will be reloaded at next chat command use.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadCreatureQuestRelationsCommand(char* /*args*/) -{ - sLog.outString("Loading creature quest givers..."); - sObjectMgr.LoadCreatureQuestRelations(); - SendGlobalSysMessage("DB table `quest_relations` (creature quest givers) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadCreatureQuestInvRelationsCommand(char* /*args*/) -{ - sLog.outString("Loading creature quest takers..."); - sObjectMgr.LoadCreatureInvolvedRelations(); - SendGlobalSysMessage("DB table `quest_relations` (creature quest takers) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadConditionsCommand(char* /*args*/) -{ - sLog.outString("Re-Loading `conditions`... "); - sObjectMgr.LoadConditions(); - SendGlobalSysMessage("DB table `conditions` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadCreaturesStatsCommand(char* /*args*/) -{ - sLog.outString("Re-Loading stats data..."); - sObjectMgr.LoadCreatureClassLvlStats(); - SendGlobalSysMessage("DB table `creature_template_classlevelstats` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadGossipMenuCommand(char* /*args*/) -{ - sObjectMgr.LoadGossipMenus(); - SendGlobalSysMessage("DB tables `gossip_menu` and `gossip_menu_option` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadGOQuestRelationsCommand(char* /*args*/) -{ - sLog.outString("Loading gameobject quest givers..."); - sObjectMgr.LoadGameobjectQuestRelations(); - SendGlobalSysMessage("DB table `quest_relations` (gameobject quest givers) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadGOQuestInvRelationsCommand(char* /*args*/) -{ - sLog.outString("Loading gameobject quest takers..."); - sObjectMgr.LoadGameobjectInvolvedRelations(); - SendGlobalSysMessage("DB table `quest_relations` (gameobject quest takers) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadQuestAreaTriggersCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Quest Area Triggers..."); - sObjectMgr.LoadQuestAreaTriggers(); - SendGlobalSysMessage("DB table `quest_relations` (quest area triggers) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadQuestTemplateCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Quest Templates..."); - sObjectMgr.LoadQuests(); - SendGlobalSysMessage("DB table `quest_template` (quest definitions) reloaded.", SEC_MODERATOR); - - /// dependent also from `gameobject` but this table not reloaded anyway - sLog.outString("Re-Loading GameObjects for quests..."); - sObjectMgr.LoadGameObjectForQuests(); - SendGlobalSysMessage("Data GameObjects for quests reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesCreatureCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Loot Tables... (`creature_loot_template`)"); - LoadLootTemplates_Creature(); - LootTemplates_Creature.CheckLootRefs(); - SendGlobalSysMessage("DB table `creature_loot_template` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesDisenchantCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Loot Tables... (`disenchant_loot_template`)"); - LoadLootTemplates_Disenchant(); - LootTemplates_Disenchant.CheckLootRefs(); - SendGlobalSysMessage("DB table `disenchant_loot_template` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesFishingCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Loot Tables... (`fishing_loot_template`)"); - LoadLootTemplates_Fishing(); - LootTemplates_Fishing.CheckLootRefs(); - SendGlobalSysMessage("DB table `fishing_loot_template` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesGameobjectCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Loot Tables... (`gameobject_loot_template`)"); - LoadLootTemplates_Gameobject(); - LootTemplates_Gameobject.CheckLootRefs(); - SendGlobalSysMessage("DB table `gameobject_loot_template` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesItemCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Loot Tables... (`item_loot_template`)"); - LoadLootTemplates_Item(); - LootTemplates_Item.CheckLootRefs(); - SendGlobalSysMessage("DB table `item_loot_template` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesPickpocketingCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Loot Tables... (`pickpocketing_loot_template`)"); - LoadLootTemplates_Pickpocketing(); - LootTemplates_Pickpocketing.CheckLootRefs(); - SendGlobalSysMessage("DB table `pickpocketing_loot_template` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesProspectingCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Loot Tables... (`prospecting_loot_template`)"); - LoadLootTemplates_Prospecting(); - LootTemplates_Prospecting.CheckLootRefs(); - SendGlobalSysMessage("DB table `prospecting_loot_template` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesMailCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Loot Tables... (`mail_loot_template`)"); - LoadLootTemplates_Mail(); - LootTemplates_Mail.CheckLootRefs(); - SendGlobalSysMessage("DB table `mail_loot_template` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesReferenceCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Loot Tables... (`reference_loot_template`)"); - LoadLootTemplates_Reference(); - SendGlobalSysMessage("DB table `reference_loot_template` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesSkinningCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Loot Tables... (`skinning_loot_template`)"); - LoadLootTemplates_Skinning(); - LootTemplates_Skinning.CheckLootRefs(); - SendGlobalSysMessage("DB table `skinning_loot_template` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadMangosStringCommand(char* /*args*/) -{ - sLog.outString("Re-Loading mangos_string Table!"); - sObjectMgr.LoadMangosStrings(); - SendGlobalSysMessage("DB table `mangos_string` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadNpcTextCommand(char* /*args*/) -{ - sLog.outString("Re-Loading `npc_text` Table!"); - sObjectMgr.LoadGossipText(); - SendGlobalSysMessage("DB table `npc_text` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadNpcTrainerCommand(char* /*args*/) -{ - sLog.outString("Re-Loading `npc_trainer_template` Table!"); - sObjectMgr.LoadTrainerTemplates(); - SendGlobalSysMessage("DB table `npc_trainer_template` reloaded.", SEC_MODERATOR); - - sLog.outString("Re-Loading `npc_trainer` Table!"); - sObjectMgr.LoadTrainers(); - SendGlobalSysMessage("DB table `npc_trainer` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadNpcVendorCommand(char* /*args*/) -{ - // not safe reload vendor template tables independent... - sLog.outString("Re-Loading `npc_vendor_template` Table!"); - sObjectMgr.LoadVendorTemplates(); - SendGlobalSysMessage("DB table `npc_vendor_template` reloaded.", SEC_MODERATOR); - - sLog.outString("Re-Loading `npc_vendor` Table!"); - sObjectMgr.LoadVendors(); - SendGlobalSysMessage("DB table `npc_vendor` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadPointsOfInterestCommand(char* /*args*/) -{ - sLog.outString("Re-Loading `points_of_interest` Table!"); - sObjectMgr.LoadPointsOfInterest(); - SendGlobalSysMessage("DB table `points_of_interest` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadReservedNameCommand(char* /*args*/) -{ - sLog.outString("Loading ReservedNames... (`reserved_name`)"); - sObjectMgr.LoadReservedPlayersNames(); - SendGlobalSysMessage("DB table `reserved_name` (player reserved names) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadReputationRewardRateCommand(char* /*args*/) -{ - sLog.outString("Re-Loading `reputation_reward_rate` Table!"); - sObjectMgr.LoadReputationRewardRate(); - SendGlobalSysMessage("DB table `reputation_reward_rate` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadReputationSpilloverTemplateCommand(char* /*args*/) -{ - sLog.outString("Re-Loading `reputation_spillover_template` Table!"); - sObjectMgr.LoadReputationSpilloverTemplate(); - SendGlobalSysMessage("DB table `reputation_spillover_template` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSkillDiscoveryTemplateCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Skill Discovery Table..."); - LoadSkillDiscoveryTable(); - SendGlobalSysMessage("DB table `skill_discovery_template` (recipes discovered at crafting) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSkillExtraItemTemplateCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Skill Extra Item Table..."); - LoadSkillExtraItemTable(); - SendGlobalSysMessage("DB table `skill_extra_item_template` (extra item creation when crafting) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadScriptBindingCommand(char* /*args*/) -{ - sLog.outString("Trying to re-load `script_binding` Table!"); - if (sScriptMgr.ReloadScriptBinding()) - { - SendGlobalSysMessage("DB table `script_binding` reloaded.", SEC_MODERATOR); - } - else - { - SendSysMessage("DENIED: DB table `script_binding` is reloadable only in Debug build."); - } - return true; -} - -bool ChatHandler::HandleReloadSkillFishingBaseLevelCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Skill Fishing base level requirements..."); - sObjectMgr.LoadFishingBaseSkillLevel(); - SendGlobalSysMessage("DB table `skill_fishing_base_level` (fishing base level for zone/subzone) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellAffectCommand(char* /*args*/) -{ - sLog.outString("Re-Loading SpellAffect definitions..."); - sSpellMgr.LoadSpellAffects(); - SendGlobalSysMessage("DB table `spell_affect` (spell mods apply requirements) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellAreaCommand(char* /*args*/) -{ - sLog.outString("Re-Loading SpellArea Data..."); - sSpellMgr.LoadSpellAreas(); - SendGlobalSysMessage("DB table `spell_area` (spell dependences from area/quest/auras state) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellBonusesCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Spell Bonus Data..."); - sSpellMgr.LoadSpellBonuses(); - SendGlobalSysMessage("DB table `spell_bonus_data` (spell damage/healing coefficients) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellChainCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Spell Chain Data... "); - sSpellMgr.LoadSpellChains(); - SendGlobalSysMessage("DB table `spell_chain` (spell ranks) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellElixirCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Spell Elixir types..."); - sSpellMgr.LoadSpellElixirs(); - SendGlobalSysMessage("DB table `spell_elixir` (spell elixir types) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellLearnSpellCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Spell Learn Spells..."); - sSpellMgr.LoadSpellLearnSpells(); - SendGlobalSysMessage("DB table `spell_learn_spell` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellProcEventCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Spell Proc Event conditions..."); - sSpellMgr.LoadSpellProcEvents(); - SendGlobalSysMessage("DB table `spell_proc_event` (spell proc trigger requirements) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellProcItemEnchantCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Spell Proc Item Enchant..."); - sSpellMgr.LoadSpellProcItemEnchant(); - SendGlobalSysMessage("DB table `spell_proc_item_enchant` (item enchantment ppm) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellScriptTargetCommand(char* /*args*/) -{ - sLog.outString("Re-Loading SpellsScriptTarget..."); - sSpellMgr.LoadSpellScriptTarget(); - SendGlobalSysMessage("DB table `spell_script_target` (spell targets selection in case specific creature/GO requirements) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellTargetPositionCommand(char* /*args*/) -{ - sLog.outString("Re-Loading spell target destination coordinates..."); - sSpellMgr.LoadSpellTargetPositions(); - SendGlobalSysMessage("DB table `spell_target_position` (destination coordinates for spell targets) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellThreatsCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Aggro Spells Definitions..."); - sSpellMgr.LoadSpellThreats(); - SendGlobalSysMessage("DB table `spell_threat` (spell aggro definitions) reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellPetAurasCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Spell pet auras..."); - sSpellMgr.LoadSpellPetAuras(); - SendGlobalSysMessage("DB table `spell_pet_auras` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadSpellLinkedCommand(char* /*arg*/) -{ - sLog.outString("Re-Loading spell linked table..."); - sSpellMgr.LoadSpellLinked(); - SendGlobalSysMessage("DB table `spell_linked` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadPageTextsCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Page Texts..."); - sObjectMgr.LoadPageTexts(); - SendGlobalSysMessage("DB table `page_texts` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadItemEnchantementsCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Item Random Enchantments Table..."); - LoadRandomEnchantmentsTable(); - SendGlobalSysMessage("DB table `item_enchantment_template` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadItemRequiredTragetCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Item Required Targets Table..."); - sObjectMgr.LoadItemRequiredTarget(); - SendGlobalSysMessage("DB table `item_required_target` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadBattleEventCommand(char* /*args*/) -{ - sLog.outString("Re-Loading BattleGround Eventindexes..."); - sBattleGroundMgr.LoadBattleEventIndexes(); - SendGlobalSysMessage("DB table `gameobject_battleground` and `creature_battleground` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadEventAITextsCommand(char* /*args*/) -{ - - sLog.outString("Re-Loading Texts from `creature_ai_texts`..."); - sEventAIMgr.LoadCreatureEventAI_Texts(true); - SendGlobalSysMessage("DB table `creature_ai_texts` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadEventAISummonsCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Summons from `creature_ai_summons`..."); - sEventAIMgr.LoadCreatureEventAI_Summons(true); - SendGlobalSysMessage("DB table `creature_ai_summons` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadEventAIScriptsCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Scripts from `creature_ai_scripts`..."); - sEventAIMgr.LoadCreatureEventAI_Scripts(); - SendGlobalSysMessage("DB table `creature_ai_scripts` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadDbScriptStringCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Script strings from `db_script_string`..."); - sScriptMgr.LoadDbScriptStrings(); - SendGlobalSysMessage("DB table `db_script_string` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadDBScriptsOnGossipCommand(char* args) -{ - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*args != 'a') - { - sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_GOSSIP]`..."); - } - - sScriptMgr.LoadDbScripts(DBS_ON_GOSSIP); - - if (*args != 'a') - { - SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_GOSSIP]` reloaded.", SEC_MODERATOR); - } - - return true; -} - -bool ChatHandler::HandleReloadDBScriptsOnSpellCommand(char* args) -{ - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*args != 'a') - { - sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_SPELL]`..."); - } - - sScriptMgr.LoadDbScripts(DBS_ON_SPELL); - - if (*args != 'a') - { - SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_SPELL]` reloaded.", SEC_MODERATOR); - } - - return true; -} - -bool ChatHandler::HandleReloadDBScriptsOnQuestStartCommand(char* args) -{ - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*args != 'a') - { - sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_QUEST_START]`..."); - } - - sScriptMgr.LoadDbScripts(DBS_ON_QUEST_START); - - if (*args != 'a') - { - SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_QUEST_START]` reloaded.", SEC_MODERATOR); - } - - return true; -} - -bool ChatHandler::HandleReloadDBScriptsOnQuestEndCommand(char* args) -{ - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*args != 'a') - { - sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_QUEST_END]`..."); - } - - sScriptMgr.LoadDbScripts(DBS_ON_QUEST_END); - - if (*args != 'a') - { - SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_QUEST_END]` reloaded.", SEC_MODERATOR); - } - - return true; -} - -bool ChatHandler::HandleReloadDBScriptsOnEventCommand(char* args) -{ - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*args != 'a') - { - sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_EVENT]`..."); - } - - sScriptMgr.LoadDbScripts(DBS_ON_EVENT); - - if (*args != 'a') - { - SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_EVENT]` reloaded.", SEC_MODERATOR); - } - - return true; -} - -bool ChatHandler::HandleReloadDBScriptsOnGoUseCommand(char* args) -{ - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*args != 'a') - { - sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_GO[_TEMPLATE]_USE]`..."); - } - - sScriptMgr.LoadDbScripts(DBS_ON_GO_USE); - sScriptMgr.LoadDbScripts(DBS_ON_GOT_USE); - - if (*args != 'a') - { - SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_GO[_TEMPLATE]_USE]` reloaded.", SEC_MODERATOR); - } - - return true; -} - -bool ChatHandler::HandleReloadDBScriptsOnCreatureDeathCommand(char* args) -{ - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*args != 'a') - { - sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_CREATURE_DEATH]`..."); - } - - sScriptMgr.LoadDbScripts(DBS_ON_CREATURE_DEATH); - - if (*args != 'a') - { - SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_CREATURE_DEATH]` reloaded.", SEC_MODERATOR); - } - - return true; -} - -bool ChatHandler::HandleReloadGameGraveyardZoneCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Graveyard-zone links..."); - - sObjectMgr.LoadGraveyardZones(); - - SendGlobalSysMessage("DB table `game_graveyard_zone` reloaded.", SEC_MODERATOR); - - return true; -} - -bool ChatHandler::HandleReloadGameTeleCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Game Tele coordinates..."); - - sObjectMgr.LoadGameTele(); - - SendGlobalSysMessage("DB table `game_tele` reloaded.", SEC_MODERATOR); - - return true; -} - -bool ChatHandler::HandleReloadLocalesCreatureCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Locales Creature ..."); - sObjectMgr.LoadCreatureLocales(); - SendGlobalSysMessage("DB table `locales_creature` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLocalesGameobjectCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Locales Gameobject ... "); - sObjectMgr.LoadGameObjectLocales(); - SendGlobalSysMessage("DB table `locales_gameobject` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLocalesGossipMenuOptionCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Locales Gossip Menu Option ... "); - sObjectMgr.LoadGossipMenuItemsLocales(); - SendGlobalSysMessage("DB table `locales_gossip_menu_option` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLocalesItemCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Locales Item ... "); - sObjectMgr.LoadItemLocales(); - SendGlobalSysMessage("DB table `locales_item` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLocalesNpcTextCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Locales NPC Text ... "); - sObjectMgr.LoadGossipTextLocales(); - SendGlobalSysMessage("DB table `locales_npc_text` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLocalesPageTextCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Locales Page Text ... "); - sObjectMgr.LoadPageTextLocales(); - SendGlobalSysMessage("DB table `locales_page_text` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLocalesPointsOfInterestCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Locales Points Of Interest ... "); - sObjectMgr.LoadPointOfInterestLocales(); - SendGlobalSysMessage("DB table `locales_points_of_interest` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadLocalesQuestCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Locales Quest ... "); - sObjectMgr.LoadQuestLocales(); - SendGlobalSysMessage("DB table `locales_quest` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleReloadMailLevelRewardCommand(char* /*args*/) -{ - sLog.outString("Re-Loading Player level dependent mail rewards..."); - sObjectMgr.LoadMailLevelRewards(); - SendGlobalSysMessage("DB table `mail_level_reward` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadDisablesCommand(char * /*args*/) -{ - sLog.outString("Re-loading Disables..."); - DisableMgr::LoadDisables(); - DisableMgr::CheckQuestDisables(); - SendGlobalSysMessage("DB table `disables` reloaded.", SEC_MODERATOR); - return true; -} - -bool ChatHandler::HandleLoadScriptsCommand(char* args) -{ - if (!*args) - { - return false; - } - - switch (sScriptMgr.LoadScriptLibrary(args)) - { - case SCRIPT_LOAD_OK: - sWorld.SendWorldText(LANG_SCRIPTS_RELOADED_ANNOUNCE); - SendSysMessage(LANG_SCRIPTS_RELOADED_OK); - break; - case SCRIPT_LOAD_ERR_NOT_FOUND: - SendSysMessage(LANG_SCRIPTS_NOT_FOUND); - break; - case SCRIPT_LOAD_ERR_WRONG_API: - SendSysMessage(LANG_SCRIPTS_WRONG_API); - break; - case SCRIPT_LOAD_ERR_OUTDATED: - SendSysMessage(LANG_SCRIPTS_OUTDATED); - break; - } - - return true; -} - -bool ChatHandler::HandleAccountSetGmLevelCommand(char* args) -{ - char* accountStr = ExtractOptNotLastArg(&args); - - std::string targetAccountName; - Player* targetPlayer = NULL; - uint32 targetAccountId = ExtractAccountId(&accountStr, &targetAccountName, &targetPlayer); - if (!targetAccountId) - { - return false; - } - - /// only target player different from self allowed - if (GetAccountId() == targetAccountId) - { - return false; - } - - int32 gm; - if (!ExtractInt32(&args, gm)) - { - return false; - } - - if (gm < SEC_PLAYER || gm > SEC_ADMINISTRATOR) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - /// can set security level only for target with less security and to less security that we have - /// This will reject self apply by specify account name - if (HasLowerSecurityAccount(NULL, targetAccountId, true)) - { - return false; - } - - /// account can't set security to same or grater level, need more power GM or console - AccountTypes plSecurity = GetAccessLevel(); - if (AccountTypes(gm) >= plSecurity) - { - SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); - SetSentErrorMessage(true); - return false; - } - - if (targetPlayer) - { - ChatHandler(targetPlayer).PSendSysMessage(LANG_YOURS_SECURITY_CHANGED, GetNameLink().c_str(), gm); - targetPlayer->GetSession()->SetSecurity(AccountTypes(gm)); - } - - PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm); - LoginDatabase.PExecute("UPDATE `account` SET `gmlevel` = '%i' WHERE `id` = '%u'", gm, targetAccountId); - - return true; -} - -/// Set password for account -bool ChatHandler::HandleAccountSetPasswordCommand(char* args) -{ - ///- Get the command line arguments - std::string account_name; - uint32 targetAccountId = ExtractAccountId(&args, &account_name); - if (!targetAccountId) - { - return false; - } - - // allow or quoted string with possible spaces or literal without spaces - char* szPassword1 = ExtractQuotedOrLiteralArg(&args); - char* szPassword2 = ExtractQuotedOrLiteralArg(&args); - if (!szPassword1 || !szPassword2) - { - 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 = sAccountMgr.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; - } - - // OK, but avoid normal report for hide passwords, but log use command for anyone - char msg[100]; - snprintf(msg, 100, ".account set password %s *** ***", account_name.c_str()); - LogCommand(msg); - SetSentErrorMessage(true); - return false; -} - -bool ChatHandler::HandleMaxSkillCommand(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(char* args) -{ - Player* target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // number or [name] Shift-click form |color|Hskill:skill_id|h[name]|h|r - char* skill_p = ExtractKeyFromLink(&args, "Hskill"); - if (!skill_p) - { - return false; - } - - int32 skill; - if (!ExtractInt32(&skill_p, skill)) - { - return false; - } - - int32 level; - if (!ExtractInt32(&args, level)) - { - return false; - } - - int32 maxskill; - if (!ExtractOptInt32(&args, maxskill, target->GetPureMaxSkillValue(skill))) - { - return false; - } - - if (skill <= 0) - { - PSendSysMessage(LANG_INVALID_SKILL_ID, skill); - 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; - } - - if (level <= 0 || level > maxskill || maxskill <= 0) - { - return false; - } - - target->SetSkill(skill, level, maxskill); - PSendSysMessage(LANG_SET_SKILL, skill, sl->name[GetSessionDbcLocale()], tNameLink.c_str(), level, maxskill); - - return true; -} - -bool ChatHandler::HandleUnLearnCommand(char* args) -{ - if (!*args) - { - return false; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r - uint32 spell_id = ExtractSpellIdFromLink(&args); - if (!spell_id) - { - return false; - } - - bool allRanks = ExtractLiteralArg(&args, "all") != NULL; - if (!allRanks && *args) // can be fail also at syntax error - { - return false; - } - - Player* target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - if (allRanks) - { - spell_id = sSpellMgr.GetFirstSpellInChain(spell_id); - } - - if (target->HasSpell(spell_id)) - { - target->removeSpell(spell_id, false, !allRanks); - } - else - { - SendSysMessage(LANG_FORGET_SPELL); - } - - return true; -} - -bool ChatHandler::HandleCooldownCommand(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(&args); - if (!spell_id) - { - return false; - } - - if (!sSpellStore.LookupEntry(spell_id)) - { - PSendSysMessage(LANG_UNKNOWN_SPELL, target == m_session->GetPlayer() ? GetMangosString(LANG_YOU) : tNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - target->RemoveSpellCooldown(spell_id, true); - PSendSysMessage(LANG_REMOVE_COOLDOWN, spell_id, target == m_session->GetPlayer() ? GetMangosString(LANG_YOU) : tNameLink.c_str()); - } - return true; -} - -bool ChatHandler::HandleLearnAllCommand(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", - "12842", - "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", - "15053", - "12580", - "12475", - "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(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(char* /*args*/) -{ - HandleLearnAllMySpellsCommand((char*)""); - HandleLearnAllMyTalentsCommand((char*)""); - return true; -} - -bool ChatHandler::HandleLearnAllMySpellsCommand(char* /*args*/) -{ - Player* player = m_session->GetPlayer(); - ChrClassesEntry const* clsEntry = sChrClassesStore.LookupEntry(player->getClass()); - if (!clsEntry) - { - return true; - } - uint32 family = clsEntry->spellfamily; - - for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); ++i) - { - SkillLineAbilityEntry const* entry = sSkillLineAbilityStore.LookupEntry(i); - if (!entry) - { - continue; - } - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(entry->spellId); - if (!spellInfo) - { - continue; - } - - // skip server-side/triggered spells - if (spellInfo->spellLevel == 0) - { - continue; - } - - // skip wrong class/race skills - if (!player->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 = sSpellMgr.GetFirstSpellInChain(spellInfo->Id); - if (GetTalentSpellCost(first_rank) > 0) - { - continue; - } - - // skip broken spells - if (!SpellMgr::IsSpellValid(spellInfo, player, false)) - { - continue; - } - - player->learnSpell(spellInfo->Id, false); - } - - SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS); - return true; -} - -bool ChatHandler::HandleLearnAllMyTalentsCommand(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 (int 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, player, false)) - { - continue; - } - - // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) - player->learnSpellHighRank(spellid); - } - - SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); - return true; -} - -bool ChatHandler::HandleLearnAllLangCommand(char* /*args*/) -{ - Player* player = m_session->GetPlayer(); - - // skipping UNIVERSAL language (0) - for (int i = 1; i < LANGUAGES_COUNT; ++i) - { - player->learnSpell(lang_description[i].spell_id, false); - } - - SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG); - return true; -} - -bool ChatHandler::HandleLearnAllDefaultCommand(char* args) -{ - Player* target; - if (!ExtractPlayerTarget(&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(char* args) -{ - Player* player = m_session->GetPlayer(); - 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(&args); - if (!spell || !sSpellStore.LookupEntry(spell)) - { - return false; - } - - bool allRanks = ExtractLiteralArg(&args, "all") != NULL; - if (!allRanks && *args) // can be fail also at syntax error - { - return false; - } - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); - if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, player)) - { - PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spell); - SetSentErrorMessage(true); - return false; - } - - if (!allRanks && targetPlayer->HasSpell(spell)) - { - if (targetPlayer == player) - { - SendSysMessage(LANG_YOU_KNOWN_SPELL); - } - else - { - PSendSysMessage(LANG_TARGET_KNOWN_SPELL, targetPlayer->GetName()); - } - SetSentErrorMessage(true); - return false; - } - - if (allRanks) - { - targetPlayer->learnSpellHighRank(spell); - } - else - { - targetPlayer->learnSpell(spell, false); - } - - return true; -} - -bool ChatHandler::HandleAddItemCommand(char* args) -{ - char* cId = ExtractKeyFromLink(&args, "Hitem"); - if (!cId) - { - return false; - } - - uint32 itemId = 0; - if (!ExtractUInt32(&cId, itemId)) // [name] manual form - { - std::string itemName = cId; - WorldDatabase.escape_string(itemName); - QueryResult* result = WorldDatabase.PQuery("SELECT `entry` FROM `item_template` WHERE `name` = '%s'", itemName.c_str()); - if (!result) - { - PSendSysMessage(LANG_COMMAND_COULDNOTFIND, cId); - SetSentErrorMessage(true); - return false; - } - itemId = result->Fetch()->GetUInt16(); - delete result; - } - - int32 count; - if (!ExtractOptInt32(&args, count, 1)) - { - return false; - } - - Player* pl = m_session->GetPlayer(); - Player* plTarget = getSelectedPlayer(); - if (!plTarget) - { - plTarget = pl; - } - - DETAIL_LOG(GetMangosString(LANG_ADDITEM), itemId, count); - - ItemPrototype const* pProto = ObjectMgr::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(char* args) -{ - uint32 itemsetId; - if (!ExtractUint32KeyFromLink(&args, "Hitemset", itemsetId)) - { - return false; - } - - // 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; - } - - DETAIL_LOG(GetMangosString(LANG_ADDITEMSET), itemsetId); - - bool found = false; - for (uint32 id = 0; id < sItemStorage.GetMaxEntry(); ++id) - { - ItemPrototype const* pProto = sItemStorage.LookupEntry(id); - if (!pProto) - { - continue; - } - - if (pProto->ItemSet == itemsetId) - { - found = true; - ItemPosCountVec dest; - InventoryResult 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, pProto->ItemId); - 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(char* args) -{ - uint32 item_id; - if (!ExtractUint32KeyFromLink(&args, "Hitem", item_id)) - { - return false; - } - - if (!item_id) - { - PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); - SetSentErrorMessage(true); - return false; - } - - ItemPrototype const* itemProto = ObjectMgr::GetItemPrototype(item_id); - if (!itemProto) - { - PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); - SetSentErrorMessage(true); - return false; - } - - uint32 count; - if (!ExtractOptUInt32(&args, count, 10)) - { - return false; - } - - QueryResult* 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(); - delete result; - } - - 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()); - - uint32 res_count = uint32(result->GetRowCount()); - - delete result; - - 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(); - delete result; - } - - 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 = 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()); - - uint32 res_count = uint32(result->GetRowCount()); - - delete result; - - 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 `auction` WHERE `item_template`='%u'", item_id); - if (result) - { - auc_count = (*result)[0].GetUInt32(); - delete result; - } - - if (count > 0) - { - result = CharacterDatabase.PQuery( - // 0 1 2 3 - "SELECT `auction`.`itemguid`, `auction`.`itemowner`, `characters`.`account`, `characters`.`name` " - "FROM `auction`,`characters` WHERE `auction`.`item_template`='%u' AND `characters`.`guid` = `auction`.`itemowner` LIMIT %u", - item_id, uint32(count)); - } - else - { - result = 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()); - - delete result; - } - - // 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(); - delete result; - } - - 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()); - - uint32 res_count = uint32(result->GetRowCount()); - - delete result; - - 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(char* args) -{ - // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r - uint32 go_id; - if (!ExtractUint32KeyFromLink(&args, "Hgameobject_entry", go_id)) - { - return false; - } - - if (!go_id) - { - PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); - SetSentErrorMessage(true); - return false; - } - - GameObjectInfo const* gInfo = ObjectMgr::GetGameObjectInfo(go_id); - if (!gInfo) - { - PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); - SetSentErrorMessage(true); - return false; - } - - uint32 count; - if (!ExtractOptUInt32(&args, count, 10)) - { - return false; - } - - QueryResult* 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(); - delete result; - } - - 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, PrepareStringNpcOrGoSpawnInformation(guid).c_str(), guid, gInfo->name, x, y, z, mapid); - } - else - { - PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, PrepareStringNpcOrGoSpawnInformation(guid).c_str(), gInfo->name, x, y, z, mapid); - } - } - while (result->NextRow()); - - delete result; - } - - PSendSysMessage(LANG_COMMAND_LISTOBJMESSAGE, go_id, obj_count); - return true; -} - -bool ChatHandler::HandleListCreatureCommand(char* args) -{ - // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r - uint32 cr_id; - if (!ExtractUint32KeyFromLink(&args, "Hcreature_entry", cr_id)) - { - return false; - } - - if (!cr_id) - { - PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); - SetSentErrorMessage(true); - return false; - } - - CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(cr_id); - if (!cInfo) - { - PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); - SetSentErrorMessage(true); - return false; - } - - uint32 count; - if (!ExtractOptUInt32(&args, count, 10)) - { - return false; - } - - QueryResult* 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(); - delete result; - } - - 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, PrepareStringNpcOrGoSpawnInformation(guid).c_str(), guid, cInfo->Name, x, y, z, mapid); - } - else - { - PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, PrepareStringNpcOrGoSpawnInformation(guid).c_str(), cInfo->Name, x, y, z, mapid); - } - } - while (result->NextRow()); - - delete result; - } - - PSendSysMessage(LANG_COMMAND_LISTCREATUREMESSAGE, cr_id, cr_count); - return true; -} - - -void ChatHandler::ShowItemListHelper(uint32 itemId, int loc_idx, Player* target /*=NULL*/) -{ - ItemPrototype const* itemProto = sItemStorage.LookupEntry(itemId); - if (!itemProto) - { - return; - } - - std::string name = itemProto->Name1; - sObjectMgr.GetItemLocaleStrings(itemProto->ItemId, loc_idx, &name); - - char const* usableStr = ""; - - if (target) - { - if (target->CanUseItem(itemProto)) - { - usableStr = GetMangosString(LANG_COMMAND_ITEM_USABLE); - } - } - - if (m_session) - { - PSendSysMessage(LANG_ITEM_LIST_CHAT, itemId, itemId, name.c_str(), usableStr); - } - else - { - PSendSysMessage(LANG_ITEM_LIST_CONSOLE, itemId, name.c_str(), usableStr); - } -} - -bool ChatHandler::HandleLookupItemCommand(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); - - Player* pl = m_session ? m_session->GetPlayer() : NULL; - - uint32 counter = 0; - - // Search in `item_template` - for (uint32 id = 0; id < sItemStorage.GetMaxEntry(); ++id) - { - ItemPrototype const* pProto = sItemStorage.LookupEntry(id); - if (!pProto) - { - continue; - } - - int loc_idx = GetSessionDbLocaleIndex(); - - std::string name; // "" for let later only single time check default locale name directly - sObjectMgr.GetItemLocaleStrings(id, loc_idx, &name); - if ((name.empty() || !Utf8FitTo(name, wnamepart)) && !Utf8FitTo(pProto->Name1, wnamepart)) - { - continue; - } - - ShowItemListHelper(id, loc_idx, pl); - ++counter; - } - - if (counter == 0) - { - SendSysMessage(LANG_COMMAND_NOITEMFOUND); - } - - return true; -} - -bool ChatHandler::HandleLookupItemSetCommand(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); - - uint32 counter = 0; // Counter for figure out that we found smth. - - // 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]); - } - ++counter; - } - } - } - if (counter == 0) // if counter == 0 then we found nth - { - SendSysMessage(LANG_COMMAND_NOITEMSETFOUND); - } - return true; -} - -bool ChatHandler::HandleLookupSkillCommand(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); - - uint32 counter = 0; // Counter for figure out that we found smth. - - // 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 = GetMangosString(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 = GetMangosString(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); - } - - ++counter; - } - } - } - if (counter == 0) // if counter == 0 then we found nth - { - SendSysMessage(LANG_COMMAND_NOSKILLFOUND); - } - return true; -} - -void ChatHandler::ShowSpellListHelper(Player* target, SpellEntry const* spellInfo, LocaleConstant loc) -{ - uint32 id = spellInfo->Id; - - bool known = target && target->HasSpell(id); - bool learn = (spellInfo->Effect[EFFECT_INDEX_0] == SPELL_EFFECT_LEARN_SPELL); - - uint32 talentCost = GetTalentSpellCost(id); - - bool talent = (talentCost > 0); - bool passive = IsPassiveSpell(spellInfo); - 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 : sSpellMgr.GetSpellRank(learn ? spellInfo->EffectTriggerSpell[EFFECT_INDEX_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[" << spellInfo->SpellName[loc]; - } - else - { - ss << id << " - " << spellInfo->SpellName[loc]; - } - - // include rank in link name - if (rank) - { - ss << GetMangosString(LANG_SPELL_RANK) << rank; - } - - if (m_session) - { - ss << " " << localeNames[loc] << "]|h|r"; - } - else - { - ss << " " << localeNames[loc]; - } - - if (talent) - { - ss << GetMangosString(LANG_TALENT); - } - if (passive) - { - ss << GetMangosString(LANG_PASSIVE); - } - if (learn) - { - ss << GetMangosString(LANG_LEARN); - } - if (known) - { - ss << GetMangosString(LANG_KNOWN); - } - if (active) - { - ss << GetMangosString(LANG_ACTIVE); - } - - SendSysMessage(ss.str().c_str()); -} - -bool ChatHandler::HandleLookupSpellCommand(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); - - uint32 counter = 0; // Counter for figure out that we found smth. - - // 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) - { - ShowSpellListHelper(target, spellInfo, LocaleConstant(loc)); - ++counter; - } - } - } - if (counter == 0) // if counter == 0 then we found nth - { - SendSysMessage(LANG_COMMAND_NOSPELLFOUND); - } - return true; -} - - -void ChatHandler::ShowQuestListHelper(uint32 questId, int32 loc_idx, Player* target /*= NULL*/) -{ - Quest const* qinfo = sObjectMgr.GetQuestTemplate(questId); - if (!qinfo) - { - return; - } - - std::string title = qinfo->GetTitle(); - sObjectMgr.GetQuestLocaleStrings(questId, loc_idx, &title); - - char const* statusStr = ""; - - if (target) - { - QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); - - if (status == QUEST_STATUS_COMPLETE) - { - if (target->GetQuestRewardStatus(qinfo->GetQuestId())) - { - statusStr = GetMangosString(LANG_COMMAND_QUEST_REWARDED); - } - else - { - statusStr = GetMangosString(LANG_COMMAND_QUEST_COMPLETE); - } - } - else if (status == QUEST_STATUS_INCOMPLETE) - { - statusStr = GetMangosString(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); - } -} - -bool ChatHandler::HandleLookupQuestCommand(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); - - uint32 counter = 0 ; - - int loc_idx = GetSessionDbLocaleIndex(); - - ObjectMgr::QuestMap const& qTemplates = sObjectMgr.GetQuestTemplates(); - for (ObjectMgr::QuestMap::const_iterator iter = qTemplates.begin(); iter != qTemplates.end(); ++iter) - { - Quest* qinfo = iter->second; - - std::string title; // "" for avoid repeating check default locale - sObjectMgr.GetQuestLocaleStrings(qinfo->GetQuestId(), loc_idx, &title); - - if ((title.empty() || !Utf8FitTo(title, wnamepart)) && !Utf8FitTo(qinfo->GetTitle(), wnamepart)) - { - continue; - } - - ShowQuestListHelper(qinfo->GetQuestId(), loc_idx, target); - ++counter; - } - - if (counter == 0) - { - SendSysMessage(LANG_COMMAND_NOQUESTFOUND); - } - - return true; -} - -bool ChatHandler::HandleLookupCreatureCommand(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); - - uint32 counter = 0; - - for (uint32 id = 0; id < sCreatureStorage.GetMaxEntry(); ++id) - { - CreatureInfo const* cInfo = sCreatureStorage.LookupEntry (id); - if (!cInfo) - { - continue; - } - - int loc_idx = GetSessionDbLocaleIndex(); - - char const* name = ""; // "" for avoid repeating check for default locale - sObjectMgr.GetCreatureLocaleStrings(id, loc_idx, &name); - if (!*name || !Utf8FitTo(name, wnamepart)) - { - name = cInfo->Name; - if (!Utf8FitTo(name, wnamepart)) - { - continue; - } - } - - if (m_session) - { - PSendSysMessage(LANG_CREATURE_ENTRY_LIST_CHAT, id, id, name); - } - else - { - PSendSysMessage(LANG_CREATURE_ENTRY_LIST_CONSOLE, id, name); - } - - ++counter; - } - - if (counter == 0) - { - SendSysMessage(LANG_COMMAND_NOCREATUREFOUND); - } - - return true; -} - -bool ChatHandler::HandleLookupObjectCommand(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); - - uint32 counter = 0; - - for (SQLStorageBase::SQLSIterator itr = sGOStorage.getDataBegin(); itr < sGOStorage.getDataEnd(); ++itr) - { - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - GameObjectLocale const* gl = sObjectMgr.GetGameObjectLocale(itr->id); - if (gl) - { - if ((int32)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, itr->id, itr->id, name.c_str()); - } - else - { - PSendSysMessage(LANG_GO_ENTRY_LIST_CONSOLE, itr->id, name.c_str()); - } - ++counter; - continue; - } - } - } - } - - std::string name = itr->name; - if (name.empty()) - { - continue; - } - - if (Utf8FitTo(name, wnamepart)) - { - if (m_session) - { - PSendSysMessage(LANG_GO_ENTRY_LIST_CHAT, itr->id, itr->id, name.c_str()); - } - else - { - PSendSysMessage(LANG_GO_ENTRY_LIST_CONSOLE, itr->id, name.c_str()); - } - ++counter; - } - } - - if (counter == 0) - { - SendSysMessage(LANG_COMMAND_NOGAMEOBJECTFOUND); - } - - return true; -} - -bool ChatHandler::HandleLookupTaxiNodeCommand(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); - - uint32 counter = 0; // Counter for figure out that we found smth. - - // 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); - ++counter; - } - } - } - if (counter == 0) // if counter == 0 then we found nth - { - SendSysMessage(LANG_COMMAND_NOTAXINODEFOUND); - } - 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(char* args) -{ - // guildmaster name optional - char* guildMasterStr = ExtractOptNotLastArg(&args); - - Player* target; - if (!ExtractPlayerTarget(&guildMasterStr, &target)) - { - return false; - } - - char* guildStr = ExtractQuotedArg(&args); - 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; - } - - sGuildMgr.AddGuild(guild); - return true; -} - -bool ChatHandler::HandleGuildInviteCommand(char* args) -{ - // player name optional - char* nameStr = ExtractOptNotLastArg(&args); - - // if not guild name only (in "") then player name - ObjectGuid target_guid; - if (!ExtractPlayerTarget(&nameStr, NULL, &target_guid)) - { - return false; - } - - char* guildStr = ExtractQuotedArg(&args); - if (!guildStr) - { - return false; - } - - std::string glName = guildStr; - Guild* targetGuild = sGuildMgr.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(char* args) -{ - Player* target; - ObjectGuid target_guid; - if (!ExtractPlayerTarget(&args, &target, &target_guid)) - { - return false; - } - - uint32 glId = target ? target->GetGuildId() : Player::GetGuildIdFromDB(target_guid); - if (!glId) - { - return false; - } - - Guild* targetGuild = sGuildMgr.GetGuildById(glId); - if (!targetGuild) - { - return false; - } - - if (targetGuild->DelMember(target_guid)) - { - targetGuild->Disband(); - delete targetGuild; - } - - return true; -} - -bool ChatHandler::HandleGuildRankCommand(char* args) -{ - char* nameStr = ExtractOptNotLastArg(&args); - - Player* target; - ObjectGuid 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 = sGuildMgr.GetGuildById(glId); - if (!targetGuild) - { - return false; - } - - uint32 newrank; - if (!ExtractUInt32(&args, newrank)) - { - return false; - } - - if (newrank > targetGuild->GetLowestRank()) - { - return false; - } - - MemberSlot* slot = targetGuild->GetMemberSlot(target_guid); - if (!slot) - { - return false; - } - - slot->ChangeRank(newrank); - return true; -} - -bool ChatHandler::HandleGuildDeleteCommand(char* args) -{ - if (!*args) - { - return false; - } - - char* guildStr = ExtractQuotedArg(&args); - if (!guildStr) - { - return false; - } - - std::string gld = guildStr; - - Guild* targetGuild = sGuildMgr.GetGuildByName(gld); - if (!targetGuild) - { - return false; - } - - targetGuild->Disband(); - delete targetGuild; - - return true; -} - -bool ChatHandler::HandleGetDistanceCommand(char* args) -{ - WorldObject* obj = NULL; - - if (*args) - { - if (ObjectGuid guid = ExtractGuidFromLink(&args)) - { - obj = (WorldObject*)m_session->GetPlayer()->GetObjectByTypeMask(guid, TYPEMASK_CREATURE_OR_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; - } - } - - Player* player = m_session->GetPlayer(); - // Calculate point-to-point distance - float dx, dy, dz; - dx = player->GetPositionX() - obj->GetPositionX(); - dy = player->GetPositionY() - obj->GetPositionY(); - dz = player->GetPositionZ() - obj->GetPositionZ(); - - PSendSysMessage(LANG_DISTANCE, player->GetDistance(obj), player->GetDistance2d(obj), sqrt(dx * dx + dy * dy + dz * dz)); - - return true; -} - -bool ChatHandler::HandleDieCommand(char* /*args*/) -{ - Player* player = m_session->GetPlayer(); - Unit* target = getSelectedUnit(); - - if (!target || !player->GetSelectionGuid()) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (target->GetTypeId() == TYPEID_PLAYER) - { - if (HasLowerSecurity((Player*)target, ObjectGuid(), false)) - { - return false; - } - } - - if (target->IsAlive()) - { - player->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - return true; -} - -bool ChatHandler::HandleDamageCommand(char* args) -{ - if (!*args) - { - return false; - } - - Unit* target = getSelectedUnit(); - Player* player = m_session->GetPlayer(); - - if (!target || !player->GetSelectionGuid()) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (!target->IsAlive()) - { - return true; - } - - int32 damage_int; - if (!ExtractInt32(&args, damage_int)) - { - return false; - } - - if (damage_int <= 0) - { - return true; - } - - uint32 damage = damage_int; - - // flat melee damage without resistance/etc reduction - if (!*args) - { - player->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - if (target != player) - { - player->SendAttackStateUpdate(HITINFO_NORMALSWING2, target, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); - } - return true; - } - - uint32 school; - if (!ExtractUInt32(&args, school)) - { - return false; - } - - if (school >= MAX_SPELL_SCHOOL) - { - return false; - } - - SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); - - if (schoolmask & SPELL_SCHOOL_MASK_NORMAL) - { - damage = player->CalcArmorReducedDamage(target, damage); - } - - // melee damage by specific school - if (!*args) - { - uint32 absorb = 0; - uint32 resist = 0; - - target->CalculateDamageAbsorbAndResist(player, schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); - - if (damage <= absorb + resist) - { - return true; - } - - damage -= absorb + resist; - - player->DealDamageMods(target, damage, &absorb); - player->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); - player->SendAttackStateUpdate(HITINFO_NORMALSWING2, target, 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(&args); - if (!spellid || !sSpellStore.LookupEntry(spellid)) - { - return false; - } - - player->SpellNonMeleeDamageLog(target, spellid, damage); - return true; -} - -bool ChatHandler::HandleModifyArenaCommand(char* args) -{ - if (!*args) - { - return false; - } - - Player* target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - int32 amount = (int32)atoi(args); - - target->ModifyArenaPoints(amount); - - PSendSysMessage(LANG_COMMAND_MODIFY_ARENA, GetNameLink(target).c_str(), target->GetArenaPoints()); - - return true; -} - -bool ChatHandler::HandleReviveCommand(char* args) -{ - Player* target; - ObjectGuid target_guid; - if (!ExtractPlayerTarget(&args, &target, &target_guid)) - { - return false; - } - - if (target) - { - target->ResurrectPlayer(0.5f); - target->SpawnCorpseBones(); - } - else // will resurrected at login without corpse - { - sObjectAccessor.ConvertCorpseForPlayer(target_guid); - } - - return true; -} - -bool ChatHandler::HandleAuraCommand(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(&args); - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellID); - if (!spellInfo) - { - return false; - } - - if (!IsSpellAppliesAura(spellInfo, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) && - !IsSpellHaveEffect(spellInfo, SPELL_EFFECT_PERSISTENT_AREA_AURA)) - { - PSendSysMessage(LANG_SPELL_NO_HAVE_AURAS, spellID); - SetSentErrorMessage(true); - return false; - } - - SpellAuraHolder* holder = CreateSpellAuraHolder(spellInfo, target, m_session->GetPlayer()); - - for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) - { - uint8 eff = spellInfo->Effect[i]; - if (eff >= TOTAL_SPELL_EFFECTS) - { - continue; - } - if (IsAreaAuraEffect(eff) || - eff == SPELL_EFFECT_APPLY_AURA || - eff == SPELL_EFFECT_PERSISTENT_AREA_AURA) - { - Aura* aur = CreateAura(spellInfo, SpellEffectIndex(i), NULL, holder, target); - holder->AddAura(aur, SpellEffectIndex(i)); - } - } - target->AddSpellAuraHolder(holder); - - return true; -} - -bool ChatHandler::HandleUnAuraCommand(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(&args); - if (!spellID) - { - return false; - } - - target->RemoveAurasDueToSpell(spellID); - - return true; -} - -bool ChatHandler::HandleLinkGraveCommand(char* args) -{ - uint32 g_id; - if (!ExtractUInt32(&args, g_id)) - { - return false; - } - - char* teamStr = ExtractLiteralArg(&args); - - Team g_team; - if (!teamStr) - { - g_team = TEAM_BOTH_ALLOWED; - } - else if (strncmp(teamStr, "horde", strlen(teamStr)) == 0) - { - g_team = HORDE; - } - else if (strncmp(teamStr, "alliance", strlen(teamStr)) == 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 (sObjectMgr.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(char* args) -{ - Team g_team; - - size_t argslen = strlen(args); - - if (!*args) - { - g_team = TEAM_BOTH_ALLOWED; - } - else if (strncmp(args, "horde", argslen) == 0) - { - g_team = HORDE; - } - else if (strncmp(args, "alliance", argslen) == 0) - { - g_team = ALLIANCE; - } - else - { - return false; - } - - Player* player = m_session->GetPlayer(); - uint32 zone_id = player->GetZoneId(); - - WorldSafeLocsEntry const* graveyard = sObjectMgr.GetClosestGraveYard(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), g_team); - - if (graveyard) - { - uint32 g_id = graveyard->ID; - - GraveYardData const* data = sObjectMgr.FindGraveYardData(g_id, zone_id); - if (!data) - { - PSendSysMessage(LANG_COMMAND_GRAVEYARDERROR, g_id); - SetSentErrorMessage(true); - return false; - } - - std::string team_name; - - if (data->team == TEAM_BOTH_ALLOWED) - { - team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ANY); - } - else if (data->team == HORDE) - { - team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_HORDE); - } - else if (data->team == ALLIANCE) - { - team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ALLIANCE); - } - else // Actually, this case can not happen - { - team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_NOTEAM); - } - - PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, g_id, team_name.c_str(), zone_id); - } - else - { - std::string team_name; - - if (g_team == TEAM_BOTH_ALLOWED) - { - team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ANY); - } - else if (g_team == HORDE) - { - team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_HORDE); - } - else if (g_team == ALLIANCE) - { - team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ALLIANCE); - } - - if (g_team == TEAM_BOTH_ALLOWED) - { - PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, zone_id); - } - else - { - PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, zone_id, team_name.c_str()); - } - } - - return true; -} - -//-----------------------Npc Commands----------------------- -bool ChatHandler::HandleNpcAllowMovementCommand(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(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 = (Creature*)unit; - if (creature->UpdateEntry(newEntryNum)) - { - SendSysMessage(LANG_DONE); - } - else - { - SendSysMessage(LANG_ERROR); - } - return true; -} - -bool ChatHandler::HandleNpcInfoCommand(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(); - - time_t curRespawnDelay = target->GetRespawnTimeEx() - time(NULL); - if (curRespawnDelay < 0) - { - curRespawnDelay = 0; - } - std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay, true); - std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(), true); - - // Send information dependend on difficulty mode - CreatureInfo const* baseInfo = ObjectMgr::GetCreatureTemplate(Entry); - if (baseInfo->HeroicEntry == target->GetCreatureInfo()->Entry) - PSendSysMessage(LANG_NPCINFO_CHAR_DIFFICULTY, target->GetGuidStr().c_str(), faction, npcflags, - Entry, target->GetCreatureInfo()->Entry, 1, - displayid, nativeid); - else - { - PSendSysMessage(LANG_NPCINFO_CHAR, target->GetGuidStr().c_str(), 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->SkinningLootId); - PSendSysMessage(LANG_NPCINFO_DUNGEON_ID, target->GetInstanceId()); - PSendSysMessage(LANG_NPCINFO_POSITION, float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ())); - - if ((npcflags & UNIT_NPC_FLAG_VENDOR)) - { - SendSysMessage(LANG_NPCINFO_VENDOR); - } - if ((npcflags & UNIT_NPC_FLAG_TRAINER)) - { - SendSysMessage(LANG_NPCINFO_TRAINER); - } - - ShowNpcOrGoSpawnInformation(target->GetGUIDLow()); - return true; -} - -// play npc emote -bool ChatHandler::HandleNpcPlayEmoteCommand(char* args) -{ - uint32 emote = atoi(args); - - Creature* target = getSelectedCreature(); - if (!target) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - target->HandleEmote(emote); - - return true; -} - -// TODO: NpcCommands that needs to be fixed : - -bool ChatHandler::HandleNpcAddWeaponCommand(char* /*args*/) -{ - /*if (!*args) - return false; - - ObjectGuid guid = m_session->GetPlayer()->GetSelectionGuid(); - if (guid.IsEmpty()) - { - SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature *pCreature = sObjectAccessor.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 = ObjectMgr::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(char* args) -{ - if (!*args) - { - return false; - } - - int flag = atoi(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; -} - -void ChatHandler::HandleCharacterLevel(Player* player, ObjectGuid 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, player_guid.GetCounter()); - } -} - -bool ChatHandler::HandleCharacterLevelCommand(char* args) -{ - char* nameStr = ExtractOptNotLastArg(&args); - - int32 newlevel; - bool nolevel = false; - // exception opt second arg: .character level $name - if (!ExtractInt32(&args, newlevel)) - { - if (!nameStr) - { - nameStr = ExtractArg(&args); - if (!nameStr) - { - return false; - } - - nolevel = true; - } - else - { - return false; - } - } - - Player* target; - ObjectGuid 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); - if (nolevel) - { - newlevel = 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(char* args) -{ - int32 addlevel = 1; - char* nameStr = NULL; - - if (*args) - { - nameStr = ExtractOptNotLastArg(&args); - - // exception opt second arg: .levelup $name - if (!ExtractInt32(&args, addlevel)) - { - if (!nameStr) - { - nameStr = ExtractArg(&args); - } - else - { - return false; - } - } - } - - Player* target; - ObjectGuid 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 = 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(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(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(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(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::HandleAuctionAllianceCommand(char* /*args*/) -{ - m_session->GetPlayer()->SetAuctionAccessMode(m_session->GetPlayer()->GetTeam() != ALLIANCE ? -1 : 0); - m_session->SendAuctionHello(m_session->GetPlayer()); - return true; -} - -bool ChatHandler::HandleAuctionHordeCommand(char* /*args*/) -{ - m_session->GetPlayer()->SetAuctionAccessMode(m_session->GetPlayer()->GetTeam() != HORDE ? -1 : 0); - m_session->SendAuctionHello(m_session->GetPlayer()); - return true; -} - -bool ChatHandler::HandleAuctionGoblinCommand(char* /*args*/) -{ - m_session->GetPlayer()->SetAuctionAccessMode(1); - m_session->SendAuctionHello(m_session->GetPlayer()); - return true; -} - -bool ChatHandler::HandleAuctionCommand(char* /*args*/) -{ - m_session->GetPlayer()->SetAuctionAccessMode(0); - m_session->SendAuctionHello(m_session->GetPlayer()); - - return true; -} - -bool ChatHandler::HandleAuctionItemCommand(char* args) -{ - // format: (alliance|horde|goblin) item[:count] price [buyout] [short|long|verylong] - char* typeStr = ExtractLiteralArg(&args); - if (!typeStr) - { - return false; - } - - uint32 houseid; - if (strncmp(typeStr, "alliance", strlen(typeStr)) == 0) - { - houseid = 1; - } - else if (strncmp(typeStr, "horde", strlen(typeStr)) == 0) - { - houseid = 6; - } - else if (strncmp(typeStr, "goblin", strlen(typeStr)) == 0) - { - houseid = 7; - } - else - { - return false; - } - - // parse item str - char* itemStr = ExtractArg(&args); - if (!itemStr) - { - return false; - } - - uint32 item_id = 0; - uint32 item_count = 1; - if (sscanf(itemStr, "%u:%u", &item_id, &item_count) != 2) - if (sscanf(itemStr, "%u", &item_id) != 1) - { - return false; - } - - uint32 price; - if (!ExtractUInt32(&args, price)) - { - return false; - } - - uint32 buyout; - if (!ExtractOptUInt32(&args, buyout, 0)) - { - return false; - } - - uint32 etime = 4 * MIN_AUCTION_TIME; - if (char* timeStr = ExtractLiteralArg(&args)) - { - if (strncmp(timeStr, "short", strlen(timeStr)) == 0) - { - etime = 1 * MIN_AUCTION_TIME; - } - else if (strncmp(timeStr, "long", strlen(timeStr)) == 0) - { - etime = 2 * MIN_AUCTION_TIME; - } - else if (strncmp(timeStr, "verylong", strlen(timeStr)) == 0) - { - etime = 4 * MIN_AUCTION_TIME; - } - else - { - return false; - } - } - - AuctionHouseEntry const* auctionHouseEntry = sAuctionHouseStore.LookupEntry(houseid); - AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(auctionHouseEntry); - - if (!item_id) - { - PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); - SetSentErrorMessage(true); - return false; - } - - ItemPrototype const* item_proto = ObjectMgr::GetItemPrototype(item_id); - if (!item_proto) - { - PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); - SetSentErrorMessage(true); - return false; - } - - 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; - } - - do - { - uint32 item_stack = item_count > item_proto->GetMaxStackSize() ? item_proto->GetMaxStackSize() : item_count; - item_count -= item_stack; - - Item* newItem = Item::CreateItem(item_id, item_stack); - MANGOS_ASSERT(newItem); - - auctionHouse->AddAuction(auctionHouseEntry, newItem, etime, price, buyout); - } - while (item_count); - - return true; -} - -bool ChatHandler::HandleBankCommand(char* /*args*/) -{ - m_session->SendShowBank(m_session->GetPlayer()->GetObjectGuid()); - - return true; -} - -bool ChatHandler::HandleStableCommand(char* /*args*/) -{ - m_session->SendStablePet(m_session->GetPlayer()->GetObjectGuid()); - - return true; -} - -bool ChatHandler::HandleChangeWeatherCommand(char* args) -{ - // Weather is OFF - if (!sWorld.getConfig(CONFIG_BOOL_WEATHER)) - { - SendSysMessage(LANG_WEATHER_DISABLED); - SetSentErrorMessage(true); - return false; - } - - uint32 type; - if (!ExtractUInt32(&args, type)) - { - return false; - } - - // see enum WeatherType - if (!Weather::IsValidWeatherType(type)) - { - return false; - } - - float grade; - if (!ExtractFloat(&args, grade)) - { - return false; - } - - // clamp grade from 0 to 1 - if (grade < 0.0f) - { - grade = 0.0f; - } - else if (grade > 1.0f) - { - grade = 1.0f; - } - - Player* player = m_session->GetPlayer(); - uint32 zoneId = player->GetZoneId(); - if (!sWeatherMgr.GetWeatherChances(zoneId)) - { - SendSysMessage(LANG_NO_WEATHER); - SetSentErrorMessage(true); - } - player->GetMap()->SetWeather(zoneId, (WeatherType)type, grade, false); - - return true; -} - -bool ChatHandler::HandleTeleAddCommand(char* args) -{ - if (!*args) - { - return false; - } - - Player* player = m_session->GetPlayer(); - if (!player) - { - return false; - } - - std::string name = args; - - if (sObjectMgr.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 (sObjectMgr.AddGameTele(tele)) - { - SendSysMessage(LANG_COMMAND_TP_ADDED); - } - else - { - SendSysMessage(LANG_COMMAND_TP_ADDEDERR); - SetSentErrorMessage(true); - return false; - } - - return true; -} - -bool ChatHandler::HandleTeleDelCommand(char* args) -{ - if (!*args) - { - return false; - } - - std::string name = args; - - if (!sObjectMgr.DeleteGameTele(name)) - { - SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); - SetSentErrorMessage(true); - return false; - } - - SendSysMessage(LANG_COMMAND_TP_DELETED); - return true; -} - -bool ChatHandler::HandleListAurasCommand(char* /*args*/) -{ - Unit* unit = getSelectedUnit(); - if (!unit) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - char const* talentStr = GetMangosString(LANG_TALENT); - char const* passiveStr = GetMangosString(LANG_PASSIVE); - - Unit::SpellAuraHolderMap const& uAuras = unit->GetSpellAuraHolderMap(); - PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, uAuras.size()); - for (Unit::SpellAuraHolderMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr) - { - bool talent = GetTalentSpellCost(itr->second->GetId()) > 0; - - SpellAuraHolder* holder = itr->second; - char const* name = holder->GetSpellProto()->SpellName[GetSessionDbcLocale()]; - - for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) - { - Aura* aur = holder->GetAuraByEffectIndex(SpellEffectIndex(i)); - if (!aur) - { - continue; - } - - if (m_session) - { - std::ostringstream ss_name; - ss_name << "|cffffffff|Hspell:" << itr->second->GetId() << "|h[" << name << "]|h|r"; - - PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, holder->GetId(), aur->GetEffIndex(), - aur->GetModifier()->m_auraname, aur->GetAuraDuration(), aur->GetAuraMaxDuration(), - ss_name.str().c_str(), - (holder->IsPassive() ? passiveStr : ""), (talent ? talentStr : ""), - holder->GetCasterGuid().GetString().c_str()); - } - else - { - PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, holder->GetId(), aur->GetEffIndex(), - aur->GetModifier()->m_auraname, aur->GetAuraDuration(), aur->GetAuraMaxDuration(), - name, - (holder->IsPassive() ? passiveStr : ""), (talent ? talentStr : ""), - holder->GetCasterGuid().GetString().c_str()); - } - } - } - for (int i = 0; i < TOTAL_AURAS; ++i) - { - Unit::AuraList const& uAuraList = unit->GetAurasByType(AuraType(i)); - if (uAuraList.empty()) - { - continue; - } - PSendSysMessage(LANG_COMMAND_TARGET_LISTAURATYPE, uAuraList.size(), i); - for (Unit::AuraList::const_iterator itr = uAuraList.begin(); itr != uAuraList.end(); ++itr) - { - bool talent = GetTalentSpellCost((*itr)->GetId()) > 0; - - char const* name = (*itr)->GetSpellProto()->SpellName[GetSessionDbcLocale()]; - - if (m_session) - { - std::ostringstream ss_name; - ss_name << "|cffffffff|Hspell:" << (*itr)->GetId() << "|h[" << name << "]|h|r"; - - PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), - ss_name.str().c_str(), ((*itr)->GetHolder()->IsPassive() ? passiveStr : ""), (talent ? talentStr : ""), - (*itr)->GetCasterGuid().GetString().c_str()); - } - else - { - PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), - name, ((*itr)->GetHolder()->IsPassive() ? passiveStr : ""), (talent ? talentStr : ""), - (*itr)->GetCasterGuid().GetString().c_str()); - } - } - } - return true; -} - -bool ChatHandler::HandleListTalentsCommand(char* /*args*/) -{ - Player* player = getSelectedPlayer(); - if (!player) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - SendSysMessage(LANG_LIST_TALENTS_TITLE); - uint32 count = 0; - uint32 cost = 0; - PlayerSpellMap const& uSpells = player->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = uSpells.begin(); itr != uSpells.end(); ++itr) - { - if (itr->second.state == PLAYERSPELL_REMOVED || itr->second.disabled) - { - continue; - } - - uint32 cost_itr = GetTalentSpellCost(itr->first); - - if (cost_itr == 0) - { - continue; - } - - SpellEntry const* spellEntry = sSpellStore.LookupEntry(itr->first); - if (!spellEntry) - { - continue; - } - - ShowSpellListHelper(player, spellEntry, GetSessionDbcLocale()); - ++count; - cost += cost_itr; - } - PSendSysMessage(LANG_LIST_TALENTS_COUNT, count, cost); - - return true; -} - -bool ChatHandler::HandleResetHonorCommand(char* args) -{ - Player* target; - if (!ExtractPlayerTarget(&args, &target)) - { - return false; - } - - target->SetHonorPoints(0); - target->SetUInt32Value(PLAYER_FIELD_KILLS, 0); - target->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0); - target->SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); - target->SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); - 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->SetShapeshiftForm(FORM_NONE); - } - - player->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); - player->SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f); - - player->setFactionForRace(player->getRace()); - - player->SetByteValue(UNIT_FIELD_BYTES_0, 3, powertype); - - // reset only if player not in some form; - if (player->GetShapeshiftForm() == FORM_NONE) - { - player->InitDisplayIds(); - } - - player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_UNK5); - - player->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); - - //-1 is default value - player->SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, -1); - - // player->SetUInt32Value(PLAYER_FIELD_BYTES, 0xEEE00000 ); - return true; -} - -bool ChatHandler::HandleResetLevelCommand(char* args) -{ - Player* target; - if (!ExtractPlayerTarget(&args, &target)) - { - return false; - } - - if (!HandleResetStatsOrLevelHelper(target)) - { - return false; - } - - // set starting level - uint32 start_level = sWorld.getConfig(CONFIG_UINT32_START_PLAYER_LEVEL); - - target->SetLevel(start_level); - target->InitStatsForLevel(true); - target->InitTaxiNodesForLevel(); - target->InitTalentForLevel(); - target->SetUInt32Value(PLAYER_XP, 0); - - // reset level for pet - if (Pet* pet = target->GetPet()) - { - pet->SynchronizeLevelWithOwner(); - } - - return true; -} - -bool ChatHandler::HandleResetStatsCommand(char* args) -{ - Player* target; - if (!ExtractPlayerTarget(&args, &target)) - { - return false; - } - - if (!HandleResetStatsOrLevelHelper(target)) - { - return false; - } - - target->InitStatsForLevel(true); - target->InitTaxiNodesForLevel(); - target->InitTalentForLevel(); - - return true; -} - -bool ChatHandler::HandleResetSpellsCommand(char* args) -{ - Player* target; - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) - { - return false; - } - - if (target) - { - target->resetSpells(); - - 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), target_guid.GetCounter()); - PSendSysMessage(LANG_RESET_SPELLS_OFFLINE, target_name.c_str()); - } - - return true; -} - -bool ChatHandler::HandleResetTalentsCommand(char* args) -{ - Player* target; - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) - { - return false; - } - - if (target) - { - target->resetTalents(true); - - ChatHandler(target).SendSysMessage(LANG_RESET_TALENTS); - if (!m_session || m_session->GetPlayer() != target) - { - PSendSysMessage(LANG_RESET_TALENTS_ONLINE, GetNameLink(target).c_str()); - } - return true; - } - else if (target_guid) - { - uint32 at_flags = AT_LOGIN_RESET_TALENTS; - CharacterDatabase.PExecute("UPDATE `characters` SET `at_login` = `at_login` | '%u' WHERE `guid` = '%u'", at_flags, target_guid.GetCounter()); - 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(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 = AT_LOGIN_RESET_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); - sObjectAccessor.DoForAllPlayers([&atLogin](Player* plr){ plr->SetAtLoginFlag(atLogin); }); - return true; -} - -bool ChatHandler::HandleServerShutDownCancelCommand(char* /*args*/) -{ - sWorld.ShutdownCancel(); - return true; -} - -bool ChatHandler::HandleServerShutDownCommand(char* args) -{ - if (!*args) - { - return false; - } - - char* timeStr = strtok((char*)args, " "); - char* exitCodeStr = strtok(NULL, ""); - - int32 time = atoi(timeStr); - - // Prevent interpret wrong arg value as 0 secs shutdown time - if ((time == 0 && (timeStr[0] != '0' || timeStr[1] != '\0')) || time < 0) - { - return false; - } - - if (exitCodeStr) - { - int32 exitCode = atoi(exitCodeStr); - - // Handle atoi() errors - if (exitCode == 0 && (exitCodeStr[0] != '0' || exitCodeStr[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_STOP, exitCode); - } - else - { - sWorld.ShutdownServ(time, SHUTDOWN_MASK_STOP, SHUTDOWN_EXIT_CODE); - } - - return true; -} - -bool ChatHandler::HandleServerRestartCommand(char* args) -{ - if (!*args) - { - return false; - } - - char* timeStr = strtok((char*)args, " "); - char* exitCodeStr = strtok(NULL, ""); - - int32 time = atoi(timeStr); - - // Prevent interpret wrong arg value as 0 secs shutdown time - if ((time == 0 && (timeStr[0] != '0' || timeStr[1] != '\0')) || time < 0) - { - return false; - } - - if (exitCodeStr) - { - int32 exitCode = atoi(exitCodeStr); - - // Handle atoi() errors - if (exitCode == 0 && (exitCodeStr[0] != '0' || exitCodeStr[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(char* args) -{ - if (!*args) - { - return false; - } - - char* timeStr = strtok((char*)args, " "); - char* exitCodeStr = strtok(NULL, ""); - - int32 time = atoi(timeStr); - - // Prevent interpret wrong arg value as 0 secs shutdown time - if ((time == 0 && (timeStr[0] != '0' || timeStr[1] != '\0')) || time < 0) - { - return false; - } - - if (exitCodeStr) - { - int32 exitCode = atoi(exitCodeStr); - - // Handle atoi() errors - if (exitCode == 0 && (exitCodeStr[0] != '0' || exitCodeStr[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::HandleServerIdleShutDownCommand(char* args) -{ - if (!*args) - { - return false; - } - - char* timeStr = strtok((char*)args, " "); - char* exitCodeStr = strtok(NULL, ""); - - int32 time = atoi(timeStr); - - // Prevent interpret wrong arg value as 0 secs shutdown time - if ((time == 0 && (timeStr[0] != '0' || timeStr[1] != '\0')) || time < 0) - { - return false; - } - - if (exitCodeStr) - { - int32 exitCode = atoi(exitCodeStr); - - // Handle atoi() errors - if (exitCode == 0 && (exitCodeStr[0] != '0' || exitCodeStr[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, RESTART_EXIT_CODE); - } - - return true; -} - -bool ChatHandler::HandleQuestAddCommand(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 - uint32 entry; - if (!ExtractUint32KeyFromLink(&args, "Hquest", entry)) - { - return false; - } - - Quest const* pQuest = sObjectMgr.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.GetMaxEntry(); ++id) - { - ItemPrototype const* pProto = sItemStorage.LookupEntry(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::HandleQuestRemoveCommand(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 - uint32 entry; - if (!ExtractUint32KeyFromLink(&args, "Hquest", entry)) - { - return false; - } - - Quest const* pQuest = sObjectMgr.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::HandleQuestCompleteCommand(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 - uint32 entry; - if (!ExtractUint32KeyFromLink(&args, "Hquest", entry)) - { - return false; - } - - Quest const* pQuest = sObjectMgr.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) - { - int32 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, ObjectGuid(), spell_id); - } - } - else if (creature > 0) - { - if (CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(creature)) - for (uint16 z = 0; z < creaturecount; ++z) - { - player->KilledMonster(cInfo, ObjectGuid()); - } - } - else if (creature < 0) - { - for (uint16 z = 0; z < creaturecount; ++z) - { - player->CastedCreatureOrGO(-creature, ObjectGuid(), 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 money - int32 ReqOrRewMoney = pQuest->GetRewOrReqMoney(); - if (ReqOrRewMoney < 0) - { - player->ModifyMoney(-ReqOrRewMoney); - } - - player->CompleteQuest(entry, QUEST_STATUS_FORCE_COMPLETE); - return true; -} - -bool ChatHandler::HandleBanAccountCommand(char* args) -{ - return HandleBanHelper(BAN_ACCOUNT, args); -} - -bool ChatHandler::HandleBanCharacterCommand(char* args) -{ - return HandleBanHelper(BAN_CHARACTER, args); -} - -bool ChatHandler::HandleBanIPCommand(char* args) -{ - return HandleBanHelper(BAN_IP, args); -} - -bool ChatHandler::HandleBanHelper(BanMode mode, char* args) -{ - if (!*args) - { - return false; - } - - char* cnameOrIP = ExtractArg(&args); - if (!cnameOrIP) - { - return false; - } - - std::string nameOrIP = cnameOrIP; - - char* duration = ExtractArg(&args); // time string - if (!duration) - { - return false; - } - - uint32 duration_secs = TimeStringToSecs(duration); - - char* reason = ExtractArg(&args); - 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_secs, reason, m_session ? m_session->GetPlayerName() : "")) - { - case BAN_SUCCESS: - if (duration_secs > 0) - { - PSendSysMessage(LANG_BAN_YOUBANNED, nameOrIP.c_str(), secsToTimeString(duration_secs, 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(char* args) -{ - return HandleUnBanHelper(BAN_ACCOUNT, args); -} - -bool ChatHandler::HandleUnBanCharacterCommand(char* args) -{ - return HandleUnBanHelper(BAN_CHARACTER, args); -} - -bool ChatHandler::HandleUnBanIPCommand(char* args) -{ - return HandleUnBanHelper(BAN_IP, args); -} - -bool ChatHandler::HandleUnBanHelper(BanMode mode, char* args) -{ - if (!*args) - { - return false; - } - - char* cnameOrIP = ExtractArg(&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(char* args) -{ - if (!*args) - { - return false; - } - - std::string account_name; - uint32 accountid = ExtractAccountId(&args, &account_name); - if (!accountid) - { - return false; - } - - return HandleBanInfoHelper(accountid, account_name.c_str()); -} - -bool ChatHandler::HandleBanInfoCharacterCommand(char* args) -{ - Player* target; - ObjectGuid target_guid; - if (!ExtractPlayerTarget(&args, &target, &target_guid)) - { - return false; - } - - uint32 accountid = target ? target->GetSession()->GetAccountId() : sObjectMgr.GetPlayerAccountIdByGUID(target_guid); - - std::string accountname; - if (!sAccountMgr.GetName(accountid, accountname)) - { - PSendSysMessage(LANG_BANINFO_NOCHARACTER); - return true; - } - - return HandleBanInfoHelper(accountid, accountname.c_str()); -} - -bool ChatHandler::HandleBanInfoHelper(uint32 accountid, char const* accountname) -{ - QueryResult* 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 ? GetMangosString(LANG_BANINFO_INFINITE) : secsToTimeString(fields[1].GetUInt64(), true); - PSendSysMessage(LANG_BANINFO_HISTORYENTRY, - fields[0].GetString(), bantime.c_str(), active ? GetMangosString(LANG_BANINFO_YES) : GetMangosString(LANG_BANINFO_NO), fields[4].GetString(), fields[5].GetString()); - } - while (result->NextRow()); - - delete result; - return true; -} - -bool ChatHandler::HandleBanInfoIPCommand(char* args) -{ - if (!*args) - { - return false; - } - - char* cIP = ExtractQuotedOrLiteralArg(&args); - if (!cIP) - { - return false; - } - - if (!IsIPAddress(cIP)) - { - return false; - } - - std::string IP = cIP; - - LoginDatabase.escape_string(IP); - QueryResult* 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 ? GetMangosString(LANG_BANINFO_NEVER) : fields[2].GetString(), - permanent ? GetMangosString(LANG_BANINFO_INFINITE) : secsToTimeString(fields[3].GetUInt64(), true).c_str(), fields[4].GetString(), fields[5].GetString()); - delete result; - return true; -} - -bool ChatHandler::HandleBanListCharacterCommand(char* args) -{ - LoginDatabase.Execute("DELETE FROM `ip_banned` WHERE `unbandate`<=UNIX_TIMESTAMP() AND `unbandate`<>`bandate`"); - - char* cFilter = ExtractLiteralArg(&args); - if (!cFilter) - { - return false; - } - - std::string filter = cFilter; - LoginDatabase.escape_string(filter); - QueryResult* 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(char* args) -{ - LoginDatabase.Execute("DELETE FROM `ip_banned` WHERE `unbandate`<=UNIX_TIMESTAMP() AND `unbandate`<>`bandate`"); - - char* cFilter = ExtractLiteralArg(&args); - std::string filter = cFilter ? cFilter : ""; - LoginDatabase.escape_string(filter); - - QueryResult* 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* result) -{ - PSendSysMessage(LANG_BANLIST_MATCHINGACCOUNT); - - // Chat short output - if (m_session) - { - do - { - Field* fields = result->Fetch(); - uint32 accountid = fields[0].GetUInt32(); - - QueryResult* 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()); - delete banresult; - } - } - 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 - { - sAccountMgr.GetName(account_id, account_name); - } - - // No SQL injection. id is uint32. - QueryResult* 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()); - delete banInfo; - } - } - while (result->NextRow()); - SendSysMessage("==============================================================================="); - } - - delete result; - return true; -} - -bool ChatHandler::HandleBanListIPCommand(char* args) -{ - LoginDatabase.Execute("DELETE FROM `ip_banned` WHERE `unbandate`<=UNIX_TIMESTAMP() AND `unbandate`<>`bandate`"); - - char* cFilter = ExtractLiteralArg(&args); - std::string filter = cFilter ? cFilter : ""; - LoginDatabase.escape_string(filter); - - QueryResult* 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("==============================================================================="); - } - - delete result; - return true; -} - -bool ChatHandler::HandleRespawnCommand(char* /*args*/) -{ - Player* pl = m_session->GetPlayer(); - - // accept only explicitly selected target (not implicitly self targeting case) - Unit* target = getSelectedUnit(); - if (pl->GetSelectionGuid() && target) - { - if (target->GetTypeId() != TYPEID_UNIT) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (target->IsDead()) - { - ((Creature*)target)->Respawn(); - } - return true; - } - - MaNGOS::RespawnDo u_do; - MaNGOS::WorldObjectWorker worker(u_do); - Cell::VisitGridObjects(pl, worker, pl->GetMap()->GetVisibilityDistance()); - return true; -} - -bool ChatHandler::HandleGMFlyCommand(char* args) -{ - bool value; - if (!ExtractOnOff(&args, value)) - { - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; - } - - Player* target = getSelectedPlayer(); - if (!target) - { - target = m_session->GetPlayer(); - } - - target->SetCanFly(value); - PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, GetNameLink(target).c_str(), args); - return true; -} - -bool ChatHandler::HandlePDumpLoadCommand(char* args) -{ - char* file = ExtractQuotedOrLiteralArg(&args); - if (!file) - { - return false; - } - - std::string account_name; - uint32 account_id = ExtractAccountId(&args, &account_name); - if (!account_id) - { - return false; - } - - char* name_str = ExtractLiteralArg(&args); - - uint32 lowguid = 0; - 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; - } - - if (*args) - { - if (!ExtractUInt32(&args, lowguid)) - { - return false; - } - - if (!lowguid) - { - PSendSysMessage(LANG_INVALID_CHARACTER_GUID); - SetSentErrorMessage(true); - return false; - } - - ObjectGuid guid = ObjectGuid(HIGHGUID_PLAYER, lowguid); - - if (sObjectMgr.GetPlayerAccountIdByGUID(guid)) - { - PSendSysMessage(LANG_CHARACTER_GUID_IN_USE, lowguid); - SetSentErrorMessage(true); - return false; - } - } - } - - switch (PlayerDumpReader().LoadDump(file, account_id, name, lowguid)) - { - 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(char* args) -{ - if (!*args) - { - return false; - } - - char* file = ExtractQuotedOrLiteralArg(&args); - if (!file) - { - return false; - } - - char* p2 = ExtractLiteralArg(&args); - - uint32 lowguid; - ObjectGuid guid; - // character name can't start from number - if (!ExtractUInt32(&p2, lowguid)) - { - std::string name = ExtractPlayerNameFromLink(&p2); - if (name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - guid = sObjectMgr.GetPlayerGuidByName(name); - if (!guid) - { - PSendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - lowguid = guid.GetCounter(); - } - else - { - guid = ObjectGuid(HIGHGUID_PLAYER, lowguid); - } - - if (!sObjectMgr.GetPlayerAccountIdByGUID(guid)) - { - PSendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - switch (PlayerDumpWriter().WriteDump(file, lowguid)) - { - 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(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(); - float x, y, z; - mm->GetDestination(x, y, z); - for (MotionMaster::const_iterator itr = mm->begin(); itr != mm->end(); ++itr) - { - switch ((*itr)->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 CONFUSED_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_CONFUSED); break; - - case CHASE_MOTION_TYPE: - { - Unit* target = NULL; - if (unit->GetTypeId() == TYPEID_PLAYER) - { - target = static_cast const*>(*itr)->GetTarget(); - } - else - { - target = static_cast const*>(*itr)->GetTarget(); - } - - if (!target) - { - SendSysMessage(LANG_MOVEGENS_CHASE_NULL); - } - else if (target->GetTypeId() == TYPEID_PLAYER) - { - PSendSysMessage(LANG_MOVEGENS_CHASE_PLAYER, target->GetName(), target->GetGUIDLow()); - } - else - { - PSendSysMessage(LANG_MOVEGENS_CHASE_CREATURE, target->GetName(), target->GetGUIDLow()); - } - break; - } - case FOLLOW_MOTION_TYPE: - { - Unit* target = NULL; - if (unit->GetTypeId() == TYPEID_PLAYER) - { - target = static_cast const*>(*itr)->GetTarget(); - } - else - { - target = static_cast const*>(*itr)->GetTarget(); - } - - if (!target) - { - SendSysMessage(LANG_MOVEGENS_FOLLOW_NULL); - } - else if (target->GetTypeId() == TYPEID_PLAYER) - { - PSendSysMessage(LANG_MOVEGENS_FOLLOW_PLAYER, target->GetName(), target->GetGUIDLow()); - } - else - { - PSendSysMessage(LANG_MOVEGENS_FOLLOW_CREATURE, target->GetName(), target->GetGUIDLow()); - } - break; - } - case HOME_MOTION_TYPE: - if (unit->GetTypeId() == TYPEID_UNIT) - { - 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: - { - 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; - case EFFECT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_EFFECT); break; - default: - PSendSysMessage(LANG_MOVEGENS_UNKNOWN, (*itr)->GetMovementGeneratorType()); - break; - } - } - return true; -} - -bool ChatHandler::HandleServerPLimitCommand(char* args) -{ - if (*args) - { - char* param = ExtractLiteralArg(&args); - if (!param) - { - return false; - } - - int l = strlen(param); - - int val; - if (strncmp(param, "player", l) == 0) - { - sWorld.SetPlayerLimit(-SEC_PLAYER); - } - else if (strncmp(param, "moderator", l) == 0) - { - sWorld.SetPlayerLimit(-SEC_MODERATOR); - } - else if (strncmp(param, "gamemaster", l) == 0) - { - sWorld.SetPlayerLimit(-SEC_GAMEMASTER); - } - else if (strncmp(param, "administrator", l) == 0) - { - sWorld.SetPlayerLimit(-SEC_ADMINISTRATOR); - } - else if (strncmp(param, "reset", l) == 0) - { - sWorld.SetPlayerLimit(sConfig.GetIntDefault("PlayerLimit", DEFAULT_PLAYER_LIMIT)); - } - else if (ExtractInt32(¶m, val)) - { - if (val < -SEC_ADMINISTRATOR) - { - val = -SEC_ADMINISTRATOR; - } - - sWorld.SetPlayerLimit(val); - } - else - { - return false; - } - - // kick all low security level players - if (sWorld.GetPlayerAmountLimit() > 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 = ""; break; - } - - PSendSysMessage("Player limits: amount %u, min. security level %s.", pLimit, secName); - - return true; -} - -bool ChatHandler::HandleCastCommand(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(&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; - } - - bool triggered = ExtractLiteralArg(&args, "triggered") != NULL; - if (!triggered && *args) // can be fail also at syntax error - { - return false; - } - - m_session->GetPlayer()->CastSpell(target, spell, triggered); - - return true; -} - -bool ChatHandler::HandleCastBackCommand(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(&args); - if (!spell || !sSpellStore.LookupEntry(spell)) - { - return false; - } - - bool triggered = ExtractLiteralArg(&args, "triggered") != NULL; - if (!triggered && *args) // can be fail also at syntax error - { - return false; - } - - caster->SetFacingToObject(m_session->GetPlayer()); - - caster->CastSpell(m_session->GetPlayer(), spell, triggered); - - return true; -} - -bool ChatHandler::HandleCastDistCommand(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(&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; - } - - float dist; - if (!ExtractFloat(&args, dist)) - { - return false; - } - - bool triggered = ExtractLiteralArg(&args, "triggered") != NULL; - if (!triggered && *args) // can be fail also at syntax error - { - return false; - } - - 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(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(&args); - if (!spell || !sSpellStore.LookupEntry(spell)) - { - return false; - } - - bool triggered = ExtractLiteralArg(&args, "triggered") != NULL; - if (!triggered && *args) // can be fail also at syntax error - { - return false; - } - - 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(char* /*args*/) -{ - Creature* caster = getSelectedCreature(); - - if (!caster) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - Player* pl = m_session->GetPlayer(); - - caster->GetMotionMaster()->MovePoint(0, pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ()); - return true; -} - -bool ChatHandler::HandleCastSelfCommand(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(&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; - } - - bool triggered = ExtractLiteralArg(&args, "triggered") != NULL; - if (!triggered && *args) // can be fail also at syntax error - { - return false; - } - - target->CastSpell(target, spell, triggered); - - return true; -} - -bool ChatHandler::HandleInstanceListBindsCommand(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) - { - DungeonPersistentState* state = itr->second.state; - std::string timeleft = secsToTimeString(state->GetResetTime() - time(NULL), true); - if (const MapEntry* entry = sMapStore.LookupEntry(itr->first)) - { - PSendSysMessage("map: %d (%s) inst: %d perm: %s diff: %s canReset: %s TTR: %s", - itr->first, entry->name[GetSessionDbcLocale()], state->GetInstanceId(), itr->second.perm ? "yes" : "no", - state->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? "normal" : "heroic", state->CanReset() ? "yes" : "no", timeleft.c_str()); - } - else - PSendSysMessage("bound for a nonexistent map %u", itr->first); - ++counter; - } - } - PSendSysMessage("player binds: %d", counter); - counter = 0; - - if (Group* group = player->GetGroup()) - { - 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) - { - DungeonPersistentState* state = itr->second.state; - std::string timeleft = secsToTimeString(state->GetResetTime() - time(NULL), true); - if (const MapEntry* entry = sMapStore.LookupEntry(itr->first)) - { - PSendSysMessage("map: %d (%s) inst: %d perm: %s diff: %s canReset: %s TTR: %s", - itr->first, entry->name[GetSessionDbcLocale()], state->GetInstanceId(), itr->second.perm ? "yes" : "no", - state->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? "normal" : "heroic", state->CanReset() ? "yes" : "no", timeleft.c_str()); - } - else - PSendSysMessage("bound for a nonexistent map %u", itr->first); - ++counter; - } - } - } - PSendSysMessage("group binds: %d", counter); - - return true; -} - -bool ChatHandler::HandleInstanceUnbindCommand(char* args) -{ - if (!*args) - { - return false; - } - - Player* player = getSelectedPlayer(); - if (!player) - { - player = m_session->GetPlayer(); - } - uint32 counter = 0; - uint32 mapid = 0; - bool got_map = false; - - if (strncmp(args, "all", strlen(args)) != 0) - { - if (!isNumeric(args[0])) - { - return false; - } - - got_map = true; - mapid = atoi(args); - } - - 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 (got_map && mapid != itr->first) - { - ++itr; - continue; - } - if (itr->first != player->GetMapId()) - { - DungeonPersistentState* save = itr->second.state; - std::string timeleft = secsToTimeString(save->GetResetTime() - time(NULL), true); - - if (const MapEntry* entry = sMapStore.LookupEntry(itr->first)) - { - PSendSysMessage("unbinding map: %d (%s) inst: %d perm: %s diff: %s canReset: %s TTR: %s", - itr->first, entry->name[GetSessionDbcLocale()], save->GetInstanceId(), itr->second.perm ? "yes" : "no", - save->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str()); - } - else - { - PSendSysMessage("bound for a nonexistent map %u", itr->first); - } - player->UnbindInstance(itr, Difficulty(i)); - ++counter; - } - else - { - ++itr; - } - } - } - PSendSysMessage("instances unbound: %d", counter); - - return true; -} - -bool ChatHandler::HandleInstanceStatsCommand(char* /*args*/) -{ - PSendSysMessage("instances loaded: %d", sMapMgr.GetNumInstances()); - PSendSysMessage("players in instances: %d", sMapMgr.GetNumPlayersInInstances()); - - uint32 numSaves, numBoundPlayers, numBoundGroups; - sMapPersistentStateMgr.GetStatistics(numSaves, numBoundPlayers, numBoundGroups); - PSendSysMessage("instance saves: %d", numSaves); - PSendSysMessage("players bound: %d", numBoundPlayers); - PSendSysMessage("groups bound: %d", numBoundGroups); - return true; -} - -bool ChatHandler::HandleInstanceSaveDataCommand(char* /*args*/) -{ - Player* pl = m_session->GetPlayer(); - - Map* map = pl->GetMap(); - - InstanceData* iData = map->GetInstanceData(); - if (!iData) - { - PSendSysMessage("Map has no instance data."); - SetSentErrorMessage(true); - return false; - } - - iData->SaveToDB(); - return true; -} - -/// Display the list of GMs -bool ChatHandler::HandleGMListFullCommand(char* /*args*/) -{ - ///- Get the accounts with GM Level >0 - QueryResult* result = LoginDatabase.Query("SELECT `username`,`gmlevel` FROM `account` WHERE `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("========================"); - delete result; - } - else - { - PSendSysMessage(LANG_GMLIST_EMPTY); - } - return true; -} - -/// Define the 'Message of the day' for the realm -bool ChatHandler::HandleServerSetMotdCommand(char* args) -{ - sWorld.SetMotd(args); - PSendSysMessage(LANG_MOTD_NEW, args); - return true; -} - -bool ChatHandler::ShowPlayerListHelper(QueryResult* result, uint32* limit, bool title, bool error) -{ - if (!result) - { - if (error) - { - PSendSysMessage(LANG_NO_PLAYERS_FOUND); - SetSentErrorMessage(true); - } - return false; - } - - if (!m_session && title) - { - SendSysMessage(LANG_CHARACTERS_LIST_BAR); - SendSysMessage(LANG_CHARACTERS_LIST_HEADER); - SendSysMessage(LANG_CHARACTERS_LIST_BAR); - } - - if (result) - { - ///- Circle through them. Display username and GM level - do - { - // check limit - if (limit) - { - if (*limit == 0) - { - break; - } - --*limit; - } - - Field* fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - std::string name = fields[1].GetCppString(); - uint8 race = fields[2].GetUInt8(); - uint8 class_ = fields[3].GetUInt8(); - uint32 level = fields[4].GetUInt32(); - - ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race); - ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); - - char const* race_name = raceEntry ? raceEntry->name[GetSessionDbcLocale()] : ""; - char const* class_name = classEntry ? classEntry->name[GetSessionDbcLocale()] : ""; - - if (!m_session) - { - PSendSysMessage(LANG_CHARACTERS_LIST_LINE_CONSOLE, guid, name.c_str(), race_name, class_name, level); - } - else - { - PSendSysMessage(LANG_CHARACTERS_LIST_LINE_CHAT, guid, name.c_str(), name.c_str(), race_name, class_name, level); - } - } - while (result->NextRow()); - - delete result; - } - - if (!m_session) - { - SendSysMessage(LANG_CHARACTERS_LIST_BAR); - } - - return true; -} - - -/// Output list of character for account -bool ChatHandler::HandleAccountCharactersCommand(char* args) -{ - ///- Get the command line arguments - std::string account_name; - Player* target = NULL; // only for triggering use targeted player account - uint32 account_id = ExtractAccountId(&args, &account_name, &target); - if (!account_id) - { - return false; - } - - ///- Get the characters for account id - QueryResult* result = CharacterDatabase.PQuery("SELECT `guid`, `name`, `race`, `class`, `level` FROM `characters` WHERE `account` = %u", account_id); - - return ShowPlayerListHelper(result); -} - -/// Set/Unset the expansion level for an account -bool ChatHandler::HandleAccountSetAddonCommand(char* args) -{ - ///- Get the command line arguments - char* accountStr = ExtractOptNotLastArg(&args); - - std::string account_name; - uint32 account_id = ExtractAccountId(&accountStr, &account_name); - if (!account_id) - { - return false; - } - - // Let set addon state only for lesser (strong) security level - // or to self account - if (GetAccountId() && GetAccountId() != account_id && HasLowerSecurityAccount(NULL, account_id, true)) - { - return false; - } - - uint32 lev; - if (!ExtractUInt32(&args, lev)) - { - return false; - } - - // No SQL injection - LoginDatabase.PExecute("UPDATE `account` SET `expansion` = '%u' WHERE `id` = '%u'", lev, account_id); - PSendSysMessage(LANG_ACCOUNT_SETADDON, account_name.c_str(), account_id, lev); - return true; -} - -bool ChatHandler::HandleSendMailHelper(MailDraft& draft, char* args) -{ - // format: "subject text" "mail text" - std::string msgSubject = ExtractQuotedArg(&args); - if (msgSubject.empty()) - { - return false; - } - - std::string msgText = ExtractQuotedArg(&args); - if (msgText.empty()) - { - return false; - } - - // msgSubject, msgText isn't NUL after prev. check - draft.SetSubjectAndBody(msgSubject, msgText); - - return true; -} - -bool ChatHandler::HandleSendMassMailCommand(char* args) -{ - // format: raceMask "subject text" "mail text" - uint32 raceMask = 0; - char const* name = NULL; - - if (!ExtractRaceMask(&args, raceMask, &name)) - { - return false; - } - - // need dynamic object because it trasfered to mass mailer - MailDraft* draft = new MailDraft; - - // fill mail - if (!HandleSendMailHelper(*draft, args)) - { - delete draft; - return false; - } - - // from console show nonexistent sender - MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM); - - sMassMailMgr.AddMassMailTask(draft, sender, raceMask); - - PSendSysMessage(LANG_MAIL_SENT, name); - return true; -} - - - -bool ChatHandler::HandleSendItemsHelper(MailDraft& draft, char* args) -{ - // format: "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] - std::string msgSubject = ExtractQuotedArg(&args); - if (msgSubject.empty()) - { - return false; - } - - std::string msgText = ExtractQuotedArg(&args); - if (msgText.empty()) - { - return false; - } - - // extract items - typedef std::pair ItemPair; - typedef std::list< ItemPair > ItemPairs; - ItemPairs items; - - // get from tail next item str - while (char* itemStr = ExtractArg(&args)) - { - // parse item str - uint32 item_id = 0; - uint32 item_count = 1; - if (sscanf(itemStr, "%u:%u", &item_id, &item_count) != 2) - { - if (sscanf(itemStr, "%u", &item_id) != 1) - { - return false; - } - } - if (!item_id) - { - PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); - SetSentErrorMessage(true); - return false; - } - - ItemPrototype const* item_proto = ObjectMgr::GetItemPrototype(item_id); - if (!item_proto) - { - PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); - SetSentErrorMessage(true); - return false; - } - - 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; - } - } - - // fill mail - draft.SetSubjectAndBody(msgSubject, msgText); - - 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); - } - } - - return true; -} - -bool ChatHandler::HandleSendItemsCommand(char* args) -{ - // format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] - Player* receiver; - ObjectGuid receiver_guid; - std::string receiver_name; - if (!ExtractPlayerTarget(&args, &receiver, &receiver_guid, &receiver_name)) - { - return false; - } - - MailDraft draft; - - // fill mail - if (!HandleSendItemsHelper(draft, args)) - { - return false; - } - - // from console show nonexistent sender - MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM); - - draft.SendMailTo(MailReceiver(receiver, receiver_guid), sender); - - std::string nameLink = playerLink(receiver_name); - PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); - return true; -} - -bool ChatHandler::HandleSendMassItemsCommand(char* args) -{ - // format: racemask "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] - - uint32 raceMask = 0; - char const* name = NULL; - - if (!ExtractRaceMask(&args, raceMask, &name)) - { - return false; - } - - // need dynamic object because it trasfered to mass mailer - MailDraft* draft = new MailDraft; - - - // fill mail - if (!HandleSendItemsHelper(*draft, args)) - { - delete draft; - return false; - } - - // from console show nonexistent sender - MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM); - - sMassMailMgr.AddMassMailTask(draft, sender, raceMask); - - PSendSysMessage(LANG_MAIL_SENT, name); - return true; -} - -bool ChatHandler::HandleSendMoneyHelper(MailDraft& draft, char* args) -{ - /// format: "subject text" "mail text" money - - std::string msgSubject = ExtractQuotedArg(&args); - if (msgSubject.empty()) - { - return false; - } - - char* msgText = ExtractQuotedArg(&args); - if (!msgText) - { - return false; - } - - uint32 money; - if (!ExtractUInt32(&args, money)) - { - return false; - } - - if (money <= 0) - { - return false; - } - - // msgSubject, msgText isn't NUL after prev. check - draft.SetSubjectAndBody(msgSubject, msgText).SetMoney(money); - - return true; -} - -bool ChatHandler::HandleSendMoneyCommand(char* args) -{ - /// format: name "subject text" "mail text" money - - Player* receiver; - ObjectGuid receiver_guid; - std::string receiver_name; - if (!ExtractPlayerTarget(&args, &receiver, &receiver_guid, &receiver_name)) - { - return false; - } - - MailDraft draft; - - // fill mail - if (!HandleSendMoneyHelper(draft, args)) - { - return false; - } - - // from console show nonexistent sender - MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM); - - draft.SendMailTo(MailReceiver(receiver, receiver_guid), sender); - - std::string nameLink = playerLink(receiver_name); - PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); - return true; -} - -bool ChatHandler::HandleSendMassMoneyCommand(char* args) -{ - /// format: raceMask "subject text" "mail text" money - - uint32 raceMask = 0; - char const* name = NULL; - - if (!ExtractRaceMask(&args, raceMask, &name)) - { - return false; - } - - // need dynamic object because it trasfered to mass mailer - MailDraft* draft = new MailDraft; - - // fill mail - if (!HandleSendMoneyHelper(*draft, args)) - { - delete draft; - return false; - } - - // from console show nonexistent sender - MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM); - - sMassMailMgr.AddMassMailTask(draft, sender, raceMask); - - PSendSysMessage(LANG_MAIL_SENT, name); - return true; -} - -/// Send a message to a player in game -bool ChatHandler::HandleSendMessageCommand(char* args) -{ - ///- Find the player - Player* rPlayer; - if (!ExtractPlayerTarget(&args, &rPlayer)) - { - return false; - } - - ///- message - if (!*args) - { - return false; - } - - WorldSession* rPlayerSession = rPlayer->GetSession(); - - ///- Check that he is not logging out. - if (rPlayerSession->isLogingOut()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - ///- Send the message - // Use SendAreaTriggerMessage for fastest delivery. - rPlayerSession->SendAreaTriggerMessage("%s", args); - rPlayerSession->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); - - // Confirmation message - std::string nameLink = GetNameLink(rPlayer); - PSendSysMessage(LANG_SENDMESSAGE, nameLink.c_str(), args); - return true; -} - -bool ChatHandler::HandleFlushArenaPointsCommand(char* /*args*/) -{ - sBattleGroundMgr.DistributeArenaPoints(); - return true; -} - -bool ChatHandler::HandleModifyGenderCommand(char* args) -{ - if (!*args) - { - return false; - } - - Player* player = getSelectedPlayer(); - - if (!player) - { - PSendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - PlayerInfo const* info = sObjectMgr.GetPlayerInfo(player->getRace(), player->getClass()); - if (!info) - { - return false; - } - - char* gender_str = 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->SetUInt16Value(PLAYER_BYTES_3, 0, uint16(gender) | (player->GetDrunkValue() & 0xFFFE)); - - // Change display ID - player->InitDisplayIds(); - - char const* gender_full = gender ? "female" : "male"; - - PSendSysMessage(LANG_YOU_CHANGE_GENDER, player->GetName(), gender_full); - - if (needReportToTarget(player)) - { - ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full, GetNameLink().c_str()); - } - - return true; -} - -bool ChatHandler::HandleMmap(char* args) -{ - bool on; - if (ExtractOnOff(&args, on)) - { - if (on) - { - sWorld.setConfig(CONFIG_BOOL_MMAP_ENABLED, true); - SendSysMessage("WORLD: mmaps are now ENABLED (individual map settings still in effect)"); - } - else - { - sWorld.setConfig(CONFIG_BOOL_MMAP_ENABLED, false); - SendSysMessage("WORLD: mmaps are now DISABLED"); - } - return true; - } - - on = sWorld.getConfig(CONFIG_BOOL_MMAP_ENABLED); - PSendSysMessage("mmaps are %sabled", on ? "en" : "dis"); - - return true; -} - -bool ChatHandler::HandleMmapTestArea(char* args) -{ - float radius = 40.0f; - ExtractFloat(&args, radius); - - std::list creatureList; - MaNGOS::AnyUnitInObjectRangeCheck go_check(m_session->GetPlayer(), radius); - MaNGOS::CreatureListSearcher go_search(creatureList, go_check); - // Get Creatures - Cell::VisitGridObjects(m_session->GetPlayer(), go_search, radius); - - if (!creatureList.empty()) - { - PSendSysMessage("Found " SIZEFMTD " Creatures.", creatureList.size()); - - uint32 paths = 0; - uint32 uStartTime = WorldTimer::getMSTime(); - - float gx, gy, gz; - m_session->GetPlayer()->GetPosition(gx, gy, gz); - for (std::list::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) - { - PathFinder path(*itr); - path.calculate(gx, gy, gz); - ++paths; - } - - uint32 uPathLoadTime = WorldTimer::getMSTimeDiff(uStartTime, WorldTimer::getMSTime()); - PSendSysMessage("Generated %i paths in %i ms", paths, uPathLoadTime); - } - else - { - PSendSysMessage("No creatures in %f yard range.", radius); - } - - return true; -} - -// use ".mmap testheight 10" selecting any creature/player -bool ChatHandler::HandleMmapTestHeight(char* args) -{ - float radius = 0.0f; - ExtractFloat(&args, radius); - if (radius > 40.0f) - { - radius = 40.0f; - } - - Unit* unit = getSelectedUnit(); - - Player* player = m_session->GetPlayer(); - if (!unit) - { - unit = player; - } - - if (unit->GetTypeId() == TYPEID_UNIT) - { - if (radius < 0.1f) - { - radius = static_cast(unit)->GetRespawnRadius(); - } - } - else - { - if (unit->GetTypeId() != TYPEID_PLAYER) - { - PSendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - return false; - } - } - - if (radius < 0.1f) - { - PSendSysMessage("Provided spawn radius for %s is too small. Using 5.0f instead.", unit->GetGuidStr().c_str()); - radius = 5.0f; - } - - float gx, gy, gz; - unit->GetPosition(gx, gy, gz); - - Creature* summoned = unit->SummonCreature(VISUAL_WAYPOINT, gx, gy, gz + 0.5f, 0, TEMPSUMMON_TIMED_DESPAWN, 20000); - summoned->CastSpell(summoned, 8599, false); - uint32 tries = 1; - uint32 successes = 0; - uint32 startTime = WorldTimer::getMSTime(); - for (; tries < 500; ++tries) - { - unit->GetPosition(gx, gy, gz); - if (unit->GetMap()->GetReachableRandomPosition(unit, gx, gy, gz, radius)) - { - unit->SummonCreature(VISUAL_WAYPOINT, gx, gy, gz, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); - ++successes; - if (successes >= 100) - { - break; - } - } - } - uint32 genTime = WorldTimer::getMSTimeDiff(startTime, WorldTimer::getMSTime()); - PSendSysMessage("Generated %u valid points for %u try in %ums.", successes, tries, genTime); - return true; -} - -bool ChatHandler::HandleServerResetAllRaidCommand(char* args) -{ - PSendSysMessage("Global raid instances reset, all players in raid instances will be teleported to homebind!"); - sMapPersistentStateMgr.GetScheduler().ResetAllRaid(); - return true; -} - diff --git a/src/game/ChatCommands/Level4.cpp b/src/game/ChatCommands/Level4.cpp deleted file mode 100644 index 574ccb1cda55e..0000000000000 --- a/src/game/ChatCommands/Level4.cpp +++ /dev/null @@ -1,613 +0,0 @@ -/** - * MaNGOS is a full featured server for World of Warcraft, supporting - * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 - * - * Copyright (C) 2005-2020 MaNGOS - * - * 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 - * - * World of Warcraft, and all World of Warcraft or Warcraft art, images, - * and lore are copyrighted by Blizzard Entertainment, Inc. - */ - -/// \addtogroup mangosd -/// @{ -/// \file - -#include "Common.h" -#include "Language.h" -#include "Log.h" -#include "World.h" -#include "ObjectMgr.h" -#include "WorldSession.h" -#include "Config/Config.h" -#include "Util.h" -#include "AccountMgr.h" -#include "MapManager.h" -#include "Player.h" -#include "Chat.h" - -/// Delete a user account and all associated characters in this realm -/// \todo This function has to be enhanced to respect the login/realm split (delete char, delete account chars in realm, delete account chars in realm then delete account -bool ChatHandler::HandleAccountDeleteCommand(char* args) -{ - if (!*args) - { - return false; - } - - std::string account_name; - uint32 account_id = ExtractAccountId(&args, &account_name); - if (!account_id) - { - return false; - } - - /// Commands not recommended call from chat, but support anyway - /// can delete only for account with less security - /// This is also reject self apply in fact - if (HasLowerSecurityAccount(NULL, account_id, true)) - { - return false; - } - - AccountOpResult result = sAccountMgr.DeleteAccount(account_id); - switch (result) - { - case AOR_OK: - PSendSysMessage(LANG_ACCOUNT_DELETED, account_name.c_str()); - break; - case AOR_NAME_NOT_EXIST: - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, account_name.c_str()); - SetSentErrorMessage(true); - return false; - case AOR_DB_INTERNAL_ERROR: - PSendSysMessage(LANG_ACCOUNT_NOT_DELETED_SQL_ERROR, account_name.c_str()); - SetSentErrorMessage(true); - return false; - default: - PSendSysMessage(LANG_ACCOUNT_NOT_DELETED, account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - return true; -} - -/** - * Collects all GUIDs (and related info) from deleted characters which are still in the database. - * - * @param foundList a reference to an std::list which will be filled with info data - * @param searchString the search string which either contains a player GUID (low part) or a part of the character-name - * @return returns false if there was a problem while selecting the characters (e.g. player name not normalizeable) - */ -bool ChatHandler::GetDeletedCharacterInfoList(DeletedInfoList& foundList, std::string searchString) -{ - QueryResult* resultChar; - if (!searchString.empty()) - { - // search by GUID - if (isNumeric(searchString)) - { - resultChar = CharacterDatabase.PQuery("SELECT `guid`, `deleteInfos_Name`, `deleteInfos_Account`, `deleteDate` FROM `characters` WHERE `deleteDate` IS NOT NULL AND `guid` = %u", uint32(atoi(searchString.c_str()))); - } - // search by name - else - { - if (!normalizePlayerName(searchString)) - { - return false; - } - - resultChar = CharacterDatabase.PQuery("SELECT `guid`, `deleteInfos_Name`, `deleteInfos_Account`, `deleteDate` FROM `characters` WHERE `deleteDate` IS NOT NULL AND `deleteInfos_Name` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), searchString.c_str()); - } - } - else - { - resultChar = CharacterDatabase.Query("SELECT `guid`, `deleteInfos_Name`, `deleteInfos_Account`, `deleteDate` FROM `characters` WHERE `deleteDate` IS NOT NULL"); - } - - if (resultChar) - { - do - { - Field* fields = resultChar->Fetch(); - - DeletedInfo info; - - info.lowguid = fields[0].GetUInt32(); - info.name = fields[1].GetCppString(); - info.accountId = fields[2].GetUInt32(); - - // account name will be empty for nonexistent account - sAccountMgr.GetName(info.accountId, info.accountName); - - info.deleteDate = time_t(fields[3].GetUInt64()); - - foundList.push_back(info); - } - while (resultChar->NextRow()); - - delete resultChar; - } - - return true; -} - -/** - * Generate WHERE guids list by deleted info in way preventing return too long where list for existed query string length limit. - * - * @param itr a reference to an deleted info list iterator, it updated in function for possible next function call if list to long - * @param itr_end a reference to an deleted info list iterator end() - * @return returns generated where list string in form: 'guid IN (gui1, guid2, ...)' - */ -std::string ChatHandler::GenerateDeletedCharacterGUIDsWhereStr(DeletedInfoList::const_iterator& itr, DeletedInfoList::const_iterator const& itr_end) -{ - std::ostringstream wherestr; - wherestr << "guid IN ('"; - for (; itr != itr_end; ++itr) - { - wherestr << itr->lowguid; - - if (wherestr.str().size() > MAX_QUERY_LEN - 50) // near to max query - { - ++itr; - break; - } - - DeletedInfoList::const_iterator itr2 = itr; - if (++itr2 != itr_end) - { - wherestr << "','"; - } - } - wherestr << "')"; - return wherestr.str(); -} - -/** - * Shows all deleted characters which matches the given search string, expected non empty list - * - * @see ChatHandler::HandleCharacterDeletedListCommand - * @see ChatHandler::HandleCharacterDeletedRestoreCommand - * @see ChatHandler::HandleCharacterDeletedDeleteCommand - * @see ChatHandler::DeletedInfoList - * - * @param foundList contains a list with all found deleted characters - */ -void ChatHandler::HandleCharacterDeletedListHelper(DeletedInfoList const& foundList) -{ - if (!m_session) - { - SendSysMessage(LANG_CHARACTER_DELETED_LIST_BAR); - SendSysMessage(LANG_CHARACTER_DELETED_LIST_HEADER); - SendSysMessage(LANG_CHARACTER_DELETED_LIST_BAR); - } - - for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr) - { - std::string dateStr = TimeToTimestampStr(itr->deleteDate); - - if (!m_session) - PSendSysMessage(LANG_CHARACTER_DELETED_LIST_LINE_CONSOLE, - itr->lowguid, itr->name.c_str(), itr->accountName.empty() ? "" : itr->accountName.c_str(), - itr->accountId, dateStr.c_str()); - else - PSendSysMessage(LANG_CHARACTER_DELETED_LIST_LINE_CHAT, - itr->lowguid, itr->name.c_str(), itr->accountName.empty() ? "" : itr->accountName.c_str(), - itr->accountId, dateStr.c_str()); - } - - if (!m_session) - { - SendSysMessage(LANG_CHARACTER_DELETED_LIST_BAR); - } -} - -/** - * Handles the '.character deleted list' command, which shows all deleted characters which matches the given search string - * - * @see ChatHandler::HandleCharacterDeletedListHelper - * @see ChatHandler::HandleCharacterDeletedRestoreCommand - * @see ChatHandler::HandleCharacterDeletedDeleteCommand - * @see ChatHandler::DeletedInfoList - * - * @param args the search string which either contains a player GUID or a part of the character-name - */ -bool ChatHandler::HandleCharacterDeletedListCommand(char* args) -{ - DeletedInfoList foundList; - if (!GetDeletedCharacterInfoList(foundList, args)) - { - return false; - } - - // if no characters have been found, output a warning - if (foundList.empty()) - { - SendSysMessage(LANG_CHARACTER_DELETED_LIST_EMPTY); - return false; - } - - HandleCharacterDeletedListHelper(foundList); - return true; -} - -/** - * Restore a previously deleted character - * - * @see ChatHandler::HandleCharacterDeletedListHelper - * @see ChatHandler::HandleCharacterDeletedRestoreCommand - * @see ChatHandler::HandleCharacterDeletedDeleteCommand - * @see ChatHandler::DeletedInfoList - * - * @param delInfo the informations about the character which will be restored - */ -void ChatHandler::HandleCharacterDeletedRestoreHelper(DeletedInfo const& delInfo) -{ - if (delInfo.accountName.empty()) // account not exist - { - PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_ACCOUNT, delInfo.name.c_str(), delInfo.lowguid, delInfo.accountId); - return; - } - - // check character count - uint32 charcount = sAccountMgr.GetCharactersCount(delInfo.accountId); - if (charcount >= 10) - { - PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_FULL, delInfo.name.c_str(), delInfo.lowguid, delInfo.accountId); - return; - } - - if (sObjectMgr.GetPlayerGuidByName(delInfo.name)) - { - PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_NAME, delInfo.name.c_str(), delInfo.lowguid, delInfo.accountId); - return; - } - - CharacterDatabase.PExecute("UPDATE `characters` SET `name`='%s', `account`='%u', `deleteDate`=NULL, `deleteInfos_Name`=NULL, `deleteInfos_Account`=NULL WHERE `deleteDate` IS NOT NULL AND `guid` = %u", - delInfo.name.c_str(), delInfo.accountId, delInfo.lowguid); -} - -/** - * Handles the '.character deleted restore' command, which restores all deleted characters which matches the given search string - * - * The command automatically calls '.character deleted list' command with the search string to show all restored characters. - * - * @see ChatHandler::HandleCharacterDeletedRestoreHelper - * @see ChatHandler::HandleCharacterDeletedListCommand - * @see ChatHandler::HandleCharacterDeletedDeleteCommand - * - * @param args the search string which either contains a player GUID or a part of the character-name - */ -bool ChatHandler::HandleCharacterDeletedRestoreCommand(char* args) -{ - // It is required to submit at least one argument - if (!*args) - { - return false; - } - - std::string searchString; - std::string newCharName; - uint32 newAccount = 0; - - // GCC by some strange reason fail build code without temporary variable - std::istringstream params(args); - params >> searchString >> newCharName >> newAccount; - - DeletedInfoList foundList; - if (!GetDeletedCharacterInfoList(foundList, searchString)) - { - return false; - } - - if (foundList.empty()) - { - SendSysMessage(LANG_CHARACTER_DELETED_LIST_EMPTY); - return false; - } - - SendSysMessage(LANG_CHARACTER_DELETED_RESTORE); - HandleCharacterDeletedListHelper(foundList); - - if (newCharName.empty()) - { - // Drop nonexistent account cases - for (DeletedInfoList::iterator itr = foundList.begin(); itr != foundList.end(); ++itr) - { - HandleCharacterDeletedRestoreHelper(*itr); - } - } - else if (foundList.size() == 1 && normalizePlayerName(newCharName)) - { - DeletedInfo delInfo = foundList.front(); - - // update name - delInfo.name = newCharName; - - // if new account provided update deleted info - if (newAccount && newAccount != delInfo.accountId) - { - delInfo.accountId = newAccount; - sAccountMgr.GetName(newAccount, delInfo.accountName); - } - - HandleCharacterDeletedRestoreHelper(delInfo); - } - else - { - SendSysMessage(LANG_CHARACTER_DELETED_ERR_RENAME); - } - - return true; -} - -/** - * Handles the '.character deleted delete' command, which completely deletes all deleted characters which matches the given search string - * - * @see Player::GetDeletedCharacterGUIDs - * @see Player::DeleteFromDB - * @see ChatHandler::HandleCharacterDeletedListCommand - * @see ChatHandler::HandleCharacterDeletedRestoreCommand - * - * @param args the search string which either contains a player GUID or a part of the character-name - */ -bool ChatHandler::HandleCharacterDeletedDeleteCommand(char* args) -{ - // It is required to submit at least one argument - if (!*args) - { - return false; - } - - DeletedInfoList foundList; - if (!GetDeletedCharacterInfoList(foundList, args)) - { - return false; - } - - if (foundList.empty()) - { - SendSysMessage(LANG_CHARACTER_DELETED_LIST_EMPTY); - return false; - } - - SendSysMessage(LANG_CHARACTER_DELETED_DELETE); - HandleCharacterDeletedListHelper(foundList); - - // Call the appropriate function to delete them (current account for deleted characters is 0) - for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr) - { - Player::DeleteFromDB(ObjectGuid(HIGHGUID_PLAYER, itr->lowguid), 0, false, true); - } - - return true; -} - -/** - * Handles the '.character deleted old' command, which completely deletes all deleted characters deleted with some days ago - * - * @see Player::DeleteOldCharacters - * @see Player::DeleteFromDB - * @see ChatHandler::HandleCharacterDeletedDeleteCommand - * @see ChatHandler::HandleCharacterDeletedListCommand - * @see ChatHandler::HandleCharacterDeletedRestoreCommand - * - * @param args the search string which either contains a player GUID or a part of the character-name - */ -bool ChatHandler::HandleCharacterDeletedOldCommand(char* args) -{ - int32 keepDays = sWorld.getConfig(CONFIG_UINT32_CHARDELETE_KEEP_DAYS); - - if (!ExtractOptInt32(&args, keepDays, sWorld.getConfig(CONFIG_UINT32_CHARDELETE_KEEP_DAYS))) - { - return false; - } - - if (keepDays < 0) - { - return false; - } - - Player::DeleteOldCharacters((uint32)keepDays); - return true; -} - -bool ChatHandler::HandleCharacterEraseCommand(char* args) -{ - char* nameStr = ExtractLiteralArg(&args); - if (!nameStr) - { - return false; - } - - Player* target; - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&nameStr, &target, &target_guid, &target_name)) - { - return false; - } - - uint32 account_id; - - if (target) - { - account_id = target->GetSession()->GetAccountId(); - target->GetSession()->KickPlayer(); - } - else - { - account_id = sObjectMgr.GetPlayerAccountIdByGUID(target_guid); - } - - std::string account_name; - sAccountMgr.GetName(account_id, account_name); - - Player::DeleteFromDB(target_guid, account_id, true, true); - PSendSysMessage(LANG_CHARACTER_DELETED, target_name.c_str(), target_guid.GetCounter(), account_name.c_str(), account_id); - return true; -} - -/// Close RA connection -bool ChatHandler::HandleQuitCommand(char* /*args*/) -{ - // processed in RASocket - SendSysMessage(LANG_QUIT_WRONG_USE_ERROR); - return true; -} - -/// Exit the realm -bool ChatHandler::HandleServerExitCommand(char* /*args*/) -{ - SendSysMessage(LANG_COMMAND_EXIT); - World::StopNow(SHUTDOWN_EXIT_CODE); - return true; -} - -/// Display info on users currently in the realm -bool ChatHandler::HandleAccountOnlineListCommand(char* args) -{ - uint32 limit; - if (!ExtractOptUInt32(&args, limit, 100)) - { - return false; - } - - ///- Get the list of accounts ID logged to the realm - // 0 1 2 3 4 - QueryResult* result = LoginDatabase.PQuery("SELECT `id`, `username`, `last_ip`, `gmlevel`, `expansion` FROM `account` WHERE `active_realm_id` = %u", realmID); - - return ShowAccountListHelper(result, &limit); -} - -/// Create an account -bool ChatHandler::HandleAccountCreateCommand(char* args) -{ - ///- %Parse the command line arguments - char* szAcc = ExtractQuotedOrLiteralArg(&args); - char* szPassword = ExtractQuotedOrLiteralArg(&args); - if (!szAcc || !szPassword) - { - return false; - } - - // normalized in accmgr.CreateAccount - std::string account_name = szAcc; - std::string password = szPassword; - - AccountOpResult result; - uint32 expansion = 0; - if(ExtractUInt32(&args, expansion)) - { - result = sAccountMgr.CreateAccount(account_name, password, expansion); - } - else - - result = sAccountMgr.CreateAccount(account_name, password); - switch (result) - { - case AOR_OK: - PSendSysMessage(LANG_ACCOUNT_CREATED, account_name.c_str()); - break; - case AOR_NAME_TOO_LONG: - SendSysMessage(LANG_ACCOUNT_TOO_LONG); - SetSentErrorMessage(true); - return false; - case AOR_NAME_ALREADY_EXIST: - SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST); - SetSentErrorMessage(true); - return false; - case AOR_DB_INTERNAL_ERROR: - PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR, account_name.c_str()); - SetSentErrorMessage(true); - return false; - default: - PSendSysMessage(LANG_ACCOUNT_NOT_CREATED, account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - return true; -} - -/// Set the filters of logging -bool ChatHandler::HandleServerLogFilterCommand(char* args) -{ - if (!*args) - { - SendSysMessage(LANG_LOG_FILTERS_STATE_HEADER); - for (int i = 0; i < LOG_FILTER_COUNT; ++i) - if (*logFilterData[i].name) - { - PSendSysMessage(" %-20s = %s", logFilterData[i].name, GetOnOffStr(sLog.HasLogFilter(1 << i))); - } - return true; - } - - char* filtername = ExtractLiteralArg(&args); - if (!filtername) - { - return false; - } - - bool value; - if (!ExtractOnOff(&args, value)) - { - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; - } - - if (strncmp(filtername, "all", 4) == 0) - { - sLog.SetLogFilter(LogFilters(0xFFFFFFFF), value); - PSendSysMessage(LANG_ALL_LOG_FILTERS_SET_TO_S, GetOnOffStr(value)); - return true; - } - - for (int i = 0; i < LOG_FILTER_COUNT; ++i) - { - if (!*logFilterData[i].name) - { - continue; - } - - if (!strncmp(filtername, logFilterData[i].name, strlen(filtername))) - { - sLog.SetLogFilter(LogFilters(1 << i), value); - PSendSysMessage(" %-20s = %s", logFilterData[i].name, GetOnOffStr(value)); - return true; - } - } - - return false; -} - -/// Set the level of logging -bool ChatHandler::HandleServerLogLevelCommand(char* args) -{ - if (!*args) - { - PSendSysMessage("Log level: %u", sLog.GetLogLevel()); - return true; - } - - sLog.SetLogLevel(args); - return true; -} - -/// @} diff --git a/src/game/ChatCommands/ListCommands.cpp b/src/game/ChatCommands/ListCommands.cpp new file mode 100644 index 0000000000000..25c64afc6a20b --- /dev/null +++ b/src/game/ChatCommands/ListCommands.cpp @@ -0,0 +1,567 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "SpellAuras.h" + + /********************************************************************** + CommandTable : listCommandTable + /***********************************************************************/ + +bool ChatHandler::HandleListAurasCommand(char* /*args*/) +{ + Unit* unit = getSelectedUnit(); + if (!unit) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + char const* talentStr = GetMangosString(LANG_TALENT); + char const* passiveStr = GetMangosString(LANG_PASSIVE); + + Unit::SpellAuraHolderMap const& uAuras = unit->GetSpellAuraHolderMap(); + PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, uAuras.size()); + for (Unit::SpellAuraHolderMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr) + { + bool talent = GetTalentSpellCost(itr->second->GetId()) > 0; + + SpellAuraHolder* holder = itr->second; + char const* name = holder->GetSpellProto()->SpellName[GetSessionDbcLocale()]; + + for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) + { + Aura* aur = holder->GetAuraByEffectIndex(SpellEffectIndex(i)); + if (!aur) + { + continue; + } + + if (m_session) + { + std::ostringstream ss_name; + ss_name << "|cffffffff|Hspell:" << itr->second->GetId() << "|h[" << name << "]|h|r"; + + PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, holder->GetId(), aur->GetEffIndex(), + aur->GetModifier()->m_auraname, aur->GetAuraDuration(), aur->GetAuraMaxDuration(), + ss_name.str().c_str(), + (holder->IsPassive() ? passiveStr : ""), (talent ? talentStr : ""), + holder->GetCasterGuid().GetString().c_str()); + } + else + { + PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, holder->GetId(), aur->GetEffIndex(), + aur->GetModifier()->m_auraname, aur->GetAuraDuration(), aur->GetAuraMaxDuration(), + name, + (holder->IsPassive() ? passiveStr : ""), (talent ? talentStr : ""), + holder->GetCasterGuid().GetString().c_str()); + } + } + } + for (int i = 0; i < TOTAL_AURAS; ++i) + { + Unit::AuraList const& uAuraList = unit->GetAurasByType(AuraType(i)); + if (uAuraList.empty()) + { + continue; + } + PSendSysMessage(LANG_COMMAND_TARGET_LISTAURATYPE, uAuraList.size(), i); + for (Unit::AuraList::const_iterator itr = uAuraList.begin(); itr != uAuraList.end(); ++itr) + { + bool talent = GetTalentSpellCost((*itr)->GetId()) > 0; + + char const* name = (*itr)->GetSpellProto()->SpellName[GetSessionDbcLocale()]; + + if (m_session) + { + std::ostringstream ss_name; + ss_name << "|cffffffff|Hspell:" << (*itr)->GetId() << "|h[" << name << "]|h|r"; + + PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), + ss_name.str().c_str(), ((*itr)->GetHolder()->IsPassive() ? passiveStr : ""), (talent ? talentStr : ""), + (*itr)->GetCasterGuid().GetString().c_str()); + } + else + { + PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), + name, ((*itr)->GetHolder()->IsPassive() ? passiveStr : ""), (talent ? talentStr : ""), + (*itr)->GetCasterGuid().GetString().c_str()); + } + } + } + return true; +} + +bool ChatHandler::HandleListTalentsCommand(char* /*args*/) +{ + Player* player = getSelectedPlayer(); + if (!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + SendSysMessage(LANG_LIST_TALENTS_TITLE); + uint32 count = 0; + uint32 cost = 0; + PlayerSpellMap const& uSpells = player->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = uSpells.begin(); itr != uSpells.end(); ++itr) + { + if (itr->second.state == PLAYERSPELL_REMOVED || itr->second.disabled) + { + continue; + } + + uint32 cost_itr = GetTalentSpellCost(itr->first); + + if (cost_itr == 0) + { + continue; + } + + SpellEntry const* spellEntry = sSpellStore.LookupEntry(itr->first); + if (!spellEntry) + { + continue; + } + + ShowSpellListHelper(player, spellEntry, GetSessionDbcLocale()); + ++count; + cost += cost_itr; + } + PSendSysMessage(LANG_LIST_TALENTS_COUNT, count, cost); + + return true; +} + +bool ChatHandler::HandleListItemCommand(char* args) +{ + uint32 item_id; + if (!ExtractUint32KeyFromLink(&args, "Hitem", item_id)) + { + return false; + } + + if (!item_id) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + ItemPrototype const* itemProto = ObjectMgr::GetItemPrototype(item_id); + if (!itemProto) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + uint32 count; + if (!ExtractOptUInt32(&args, count, 10)) + { + return false; + } + + QueryResult* 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(); + delete result; + } + + 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()); + + uint32 res_count = uint32(result->GetRowCount()); + + delete result; + + 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(); + delete result; + } + + 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 = 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()); + + uint32 res_count = uint32(result->GetRowCount()); + + delete result; + + 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 `auction` WHERE `item_template`='%u'", item_id); + if (result) + { + auc_count = (*result)[0].GetUInt32(); + delete result; + } + + if (count > 0) + { + result = CharacterDatabase.PQuery( + // 0 1 2 3 + "SELECT `auction`.`itemguid`, `auction`.`itemowner`, `characters`.`account`, `characters`.`name` " + "FROM `auction`,`characters` WHERE `auction`.`item_template`='%u' AND `characters`.`guid` = `auction`.`itemowner` LIMIT %u", + item_id, uint32(count)); + } + else + { + result = 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()); + + delete result; + } + + // 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(); + delete result; + } + + 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()); + + uint32 res_count = uint32(result->GetRowCount()); + + delete result; + + 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(char* args) +{ + // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r + uint32 go_id; + if (!ExtractUint32KeyFromLink(&args, "Hgameobject_entry", go_id)) + { + return false; + } + + if (!go_id) + { + PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); + SetSentErrorMessage(true); + return false; + } + + GameObjectInfo const* gInfo = ObjectMgr::GetGameObjectInfo(go_id); + if (!gInfo) + { + PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); + SetSentErrorMessage(true); + return false; + } + + uint32 count; + if (!ExtractOptUInt32(&args, count, 10)) + { + return false; + } + + QueryResult* 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(); + delete result; + } + + 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, PrepareStringNpcOrGoSpawnInformation(guid).c_str(), guid, gInfo->name, x, y, z, mapid); + } + else + { + PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, PrepareStringNpcOrGoSpawnInformation(guid).c_str(), gInfo->name, x, y, z, mapid); + } + } + while (result->NextRow()); + + delete result; + } + + PSendSysMessage(LANG_COMMAND_LISTOBJMESSAGE, go_id, obj_count); + return true; +} + +bool ChatHandler::HandleListCreatureCommand(char* args) +{ + // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + uint32 cr_id; + if (!ExtractUint32KeyFromLink(&args, "Hcreature_entry", cr_id)) + { + return false; + } + + if (!cr_id) + { + PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); + SetSentErrorMessage(true); + return false; + } + + CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(cr_id); + if (!cInfo) + { + PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); + SetSentErrorMessage(true); + return false; + } + + uint32 count; + if (!ExtractOptUInt32(&args, count, 10)) + { + return false; + } + + QueryResult* 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(); + delete result; + } + + 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, PrepareStringNpcOrGoSpawnInformation(guid).c_str(), guid, cInfo->Name, x, y, z, mapid); + } + else + { + PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, PrepareStringNpcOrGoSpawnInformation(guid).c_str(), cInfo->Name, x, y, z, mapid); + } + } + while (result->NextRow()); + + delete result; + } + + PSendSysMessage(LANG_COMMAND_LISTCREATUREMESSAGE, cr_id, cr_count); + return true; +} \ No newline at end of file diff --git a/src/game/ChatCommands/LookupCommands.cpp b/src/game/ChatCommands/LookupCommands.cpp new file mode 100644 index 0000000000000..da2e2cf5fb779 --- /dev/null +++ b/src/game/ChatCommands/LookupCommands.cpp @@ -0,0 +1,1246 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "AccountMgr.h" +#include "GameEventMgr.h" +#include "World.h" +#include "ObjectMgr.h" +#include "SQLStorages.h" + + /********************************************************************** + CommandTable : lookupCommandTable + /***********************************************************************/ + + +bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, uint32* limit) +{ + if (!result) + { + PSendSysMessage(LANG_NO_PLAYERS_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint32 limit_original = limit ? *limit : 100; + + uint32 limit_local = limit_original; + + if (!limit) + { + limit = &limit_local; + } + + do + { + if (limit && *limit == 0) + { + break; + } + + Field* fields = result->Fetch(); + uint32 acc_id = fields[0].GetUInt32(); + std::string acc_name = fields[1].GetCppString(); + + ///- Get the characters for account id + QueryResult* chars = CharacterDatabase.PQuery("SELECT `guid`, `name`, `race`, `class`, `level` FROM `characters` WHERE `account` = %u", acc_id); + if (chars) + { + if (chars->GetRowCount()) + { + PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT, acc_name.c_str(), acc_id); + ShowPlayerListHelper(chars, limit, true, false); + } + else + { + delete chars; + } + } + } + while (result->NextRow()); + + delete result; + + if (*limit == limit_original) // empty accounts only + { + PSendSysMessage(LANG_NO_PLAYERS_FOUND); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +void ChatHandler::ShowQuestListHelper(uint32 questId, int32 loc_idx, Player* target /*= NULL*/) +{ + Quest const* qinfo = sObjectMgr.GetQuestTemplate(questId); + if (!qinfo) + { + return; + } + + std::string title = qinfo->GetTitle(); + sObjectMgr.GetQuestLocaleStrings(questId, loc_idx, &title); + + char const* statusStr = ""; + + if (target) + { + QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); + + if (status == QUEST_STATUS_COMPLETE) + { + if (target->GetQuestRewardStatus(qinfo->GetQuestId())) + { + statusStr = GetMangosString(LANG_COMMAND_QUEST_REWARDED); + } + else + { + statusStr = GetMangosString(LANG_COMMAND_QUEST_COMPLETE); + } + } + else if (status == QUEST_STATUS_INCOMPLETE) + { + statusStr = GetMangosString(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); + } +} + +void ChatHandler::ShowItemListHelper(uint32 itemId, int loc_idx, Player* target /*=NULL*/) +{ + ItemPrototype const* itemProto = sItemStorage.LookupEntry(itemId); + if (!itemProto) + { + return; + } + + std::string name = itemProto->Name1; + sObjectMgr.GetItemLocaleStrings(itemProto->ItemId, loc_idx, &name); + + char const* usableStr = ""; + + if (target) + { + if (target->CanUseItem(itemProto)) + { + usableStr = GetMangosString(LANG_COMMAND_ITEM_USABLE); + } + } + + if (m_session) + { + PSendSysMessage(LANG_ITEM_LIST_CHAT, itemId, itemId, name.c_str(), usableStr); + } + else + { + PSendSysMessage(LANG_ITEM_LIST_CONSOLE, itemId, name.c_str(), usableStr); + } +} + +bool ChatHandler::HandleLookupAreaCommand(char* args) +{ + if (!*args) + { + return false; + } + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart, wnamepart)) + { + return false; + } + + uint32 counter = 0; // Counter for figure out that we found smth. + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + // Search in AreaTable.dbc + for (uint32 areaid = 0; areaid <= sAreaStore.GetNumRows(); ++areaid) + { + AreaTableEntry const* areaEntry = sAreaStore.LookupEntry(areaid); + 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()); + + ++counter; + } + } + } + + if (counter == 0) // if counter == 0 then we found nth + { + SendSysMessage(LANG_COMMAND_NOAREAFOUND); + } + + return true; +} + +// Find tele in game_tele order by name +bool ChatHandler::HandleLookupTeleCommand(char* args) +{ + if (!*args) + { + SendSysMessage(LANG_COMMAND_TELE_PARAMETER); + SetSentErrorMessage(true); + 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); + + std::ostringstream reply; + + GameTeleMap const& teleMap = sObjectMgr.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; +} + +bool ChatHandler::HandleLookupFactionCommand(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); + + uint32 counter = 0; // Counter for figure out that we found smth. + + for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id) + { + FactionEntry const* factionEntry = sFactionStore.LookupEntry(id); + if (factionEntry) + { + 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) + { + FactionState const* repState = target ? target->GetReputationMgr().GetState(factionEntry) : NULL; + ShowFactionListHelper(factionEntry, LocaleConstant(loc), repState, target); + ++counter; + } + } + } + + if (counter == 0) // if counter == 0 then we found nth + { + SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND); + } + return true; +} + +bool ChatHandler::HandleLookupEventCommand(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); + + uint32 counter = 0; + + GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap(); + + for (uint32 id = 1; id < events.size(); ++id) + { + if (!sGameEventMgr.IsValidEvent(id)) + { + continue; + } + + GameEventData const& eventData = events[id]; + + std::string descr = eventData.description; + if (descr.empty()) + { + continue; + } + + if (Utf8FitTo(descr, wnamepart)) + { + char const* active = sGameEventMgr.IsActiveEvent(id) ? GetMangosString(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); + } + + ++counter; + } + } + + if (counter == 0) + { + SendSysMessage(LANG_NOEVENTFOUND); + } + + return true; +} + +bool ChatHandler::HandleLookupAccountEmailCommand(char* args) +{ + char* emailStr = ExtractQuotedOrLiteralArg(&args); + if (!emailStr) + { + return false; + } + + uint32 limit; + if (!ExtractOptUInt32(&args, limit, 100)) + { + return false; + } + + std::string email = emailStr; + LoginDatabase.escape_string(email); + // 0 1 2 3 4 + QueryResult* result = LoginDatabase.PQuery("SELECT `id`, `username`, `last_ip`, `gmlevel`, `expansion` FROM `account` WHERE `email` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), email.c_str()); + + return ShowAccountListHelper(result, &limit); +} + +bool ChatHandler::HandleLookupAccountIpCommand(char* args) +{ + char* ipStr = ExtractQuotedOrLiteralArg(&args); + if (!ipStr) + { + return false; + } + + uint32 limit; + if (!ExtractOptUInt32(&args, limit, 100)) + { + return false; + } + + std::string ip = ipStr; + LoginDatabase.escape_string(ip); + + // 0 1 2 3 4 + QueryResult* result = LoginDatabase.PQuery("SELECT `id`, `username`, `last_ip`, `gmlevel`, `expansion` FROM `account` WHERE `last_ip` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), ip.c_str()); + + return ShowAccountListHelper(result, &limit); +} + +bool ChatHandler::HandleLookupAccountNameCommand(char* args) +{ + char* accountStr = ExtractQuotedOrLiteralArg(&args); + if (!accountStr) + { + return false; + } + + uint32 limit; + if (!ExtractOptUInt32(&args, limit, 100)) + { + return false; + } + + std::string account = accountStr; + if (!AccountMgr::normalizeString(account)) + { + return false; + } + + LoginDatabase.escape_string(account); + // 0 1 2 3 4 + QueryResult* result = LoginDatabase.PQuery("SELECT `id`, `username`, `last_ip`, `gmlevel`, `expansion` FROM `account` WHERE `username` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), account.c_str()); + + return ShowAccountListHelper(result, &limit); +} + +bool ChatHandler::ShowAccountListHelper(QueryResult* result, uint32* limit, bool title, bool error) +{ + if (!result) + { + if (error) + { + SendSysMessage(LANG_ACCOUNT_LIST_EMPTY); + } + return true; + } + + ///- Display the list of account/characters online + if (!m_session && title) // not output header for online case + { + SendSysMessage(LANG_ACCOUNT_LIST_BAR); + SendSysMessage(LANG_ACCOUNT_LIST_HEADER); + SendSysMessage(LANG_ACCOUNT_LIST_BAR); + } + + ///- Circle through accounts + do + { + // check limit + if (limit) + { + if (*limit == 0) + { + break; + } + --* limit; + } + + Field* fields = result->Fetch(); + uint32 account = fields[0].GetUInt32(); + + WorldSession* session = sWorld.FindSession(account); + Player* player = session ? session->GetPlayer() : NULL; + char const* char_name = player ? player->GetName() : " - "; + + if (m_session) + PSendSysMessage(LANG_ACCOUNT_LIST_LINE_CHAT, + account, fields[1].GetString(), char_name, fields[2].GetString(), fields[3].GetUInt32(), fields[4].GetUInt32()); + else + PSendSysMessage(LANG_ACCOUNT_LIST_LINE_CONSOLE, + account, fields[1].GetString(), char_name, fields[2].GetString(), fields[3].GetUInt32(), fields[4].GetUInt32()); + } + while (result->NextRow()); + + delete result; + + if (!m_session) // not output header for online case + { + SendSysMessage(LANG_ACCOUNT_LIST_BAR); + } + + return true; +} + +bool ChatHandler::HandleLookupPlayerIpCommand(char* args) +{ + char* ipStr = ExtractQuotedOrLiteralArg(&args); + if (!ipStr) + { + return false; + } + + uint32 limit; + if (!ExtractOptUInt32(&args, limit, 100)) + { + return false; + } + + std::string ip = ipStr; + LoginDatabase.escape_string(ip); + + QueryResult* result = LoginDatabase.PQuery("SELECT `id`,`username` FROM `account` WHERE `last_ip` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), ip.c_str()); + + return LookupPlayerSearchCommand(result, &limit); +} + +bool ChatHandler::HandleLookupPlayerAccountCommand(char* args) +{ + char* accountStr = ExtractQuotedOrLiteralArg(&args); + if (!accountStr) + { + return false; + } + + uint32 limit; + if (!ExtractOptUInt32(&args, limit, 100)) + { + return false; + } + + std::string account = accountStr; + if (!AccountMgr::normalizeString(account)) + { + return false; + } + + LoginDatabase.escape_string(account); + + QueryResult* result = LoginDatabase.PQuery("SELECT `id`,`username` FROM `account` WHERE `username` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), account.c_str()); + + return LookupPlayerSearchCommand(result, &limit); +} + +bool ChatHandler::HandleLookupPlayerEmailCommand(char* args) +{ + char* emailStr = ExtractQuotedOrLiteralArg(&args); + if (!emailStr) + { + return false; + } + + uint32 limit; + if (!ExtractOptUInt32(&args, limit, 100)) + { + return false; + } + + std::string email = emailStr; + LoginDatabase.escape_string(email); + + QueryResult* result = LoginDatabase.PQuery("SELECT `id`,`username` FROM `account` WHERE `email` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), email.c_str()); + + return LookupPlayerSearchCommand(result, &limit); +} + +bool ChatHandler::HandleLookupPoolCommand(char* args) +{ + if (!*args) + { + return false; + } + + std::string namepart = args; + strToLower(namepart); + + uint32 counter = 0; + + // spawn pools for expected map or for not initialized shared pools state for non-instanceable maps + for (uint16 pool_id = 0; pool_id < sPoolMgr.GetMaxPoolId(); ++pool_id) + { + PoolTemplateData const& pool_template = sPoolMgr.GetPoolTemplate(pool_id); + + std::string desc = pool_template.description; + strToLower(desc); + + if (desc.find(namepart) == std::wstring::npos) + { + continue; + } + + ShowPoolListHelper(pool_id); + ++counter; + } + + if (counter == 0) + { + SendSysMessage(LANG_NO_POOL); + } + + return true; +} + +bool ChatHandler::HandleLookupItemCommand(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); + + Player* pl = m_session ? m_session->GetPlayer() : NULL; + + uint32 counter = 0; + + // Search in `item_template` + for (uint32 id = 0; id < sItemStorage.GetMaxEntry(); ++id) + { + ItemPrototype const* pProto = sItemStorage.LookupEntry(id); + if (!pProto) + { + continue; + } + + int loc_idx = GetSessionDbLocaleIndex(); + + std::string name; // "" for let later only single time check default locale name directly + sObjectMgr.GetItemLocaleStrings(id, loc_idx, &name); + if ((name.empty() || !Utf8FitTo(name, wnamepart)) && !Utf8FitTo(pProto->Name1, wnamepart)) + { + continue; + } + + ShowItemListHelper(id, loc_idx, pl); + ++counter; + } + + if (counter == 0) + { + SendSysMessage(LANG_COMMAND_NOITEMFOUND); + } + + return true; +} + +bool ChatHandler::HandleLookupItemSetCommand(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); + + uint32 counter = 0; // Counter for figure out that we found smth. + + // 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]); + } + ++counter; + } + } + } + if (counter == 0) // if counter == 0 then we found nth + { + SendSysMessage(LANG_COMMAND_NOITEMSETFOUND); + } + return true; +} + +bool ChatHandler::HandleLookupSkillCommand(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); + + uint32 counter = 0; // Counter for figure out that we found smth. + + // 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 = GetMangosString(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 = GetMangosString(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); + } + + ++counter; + } + } + } + if (counter == 0) // if counter == 0 then we found nth + { + SendSysMessage(LANG_COMMAND_NOSKILLFOUND); + } + return true; +} + + +bool ChatHandler::HandleLookupSpellCommand(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); + + uint32 counter = 0; // Counter for figure out that we found smth. + + // 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) + { + ShowSpellListHelper(target, spellInfo, LocaleConstant(loc)); + ++counter; + } + } + } + if (counter == 0) // if counter == 0 then we found nth + { + SendSysMessage(LANG_COMMAND_NOSPELLFOUND); + } + return true; +} + +bool ChatHandler::HandleLookupQuestCommand(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); + + uint32 counter = 0; + + int loc_idx = GetSessionDbLocaleIndex(); + + ObjectMgr::QuestMap const& qTemplates = sObjectMgr.GetQuestTemplates(); + for (ObjectMgr::QuestMap::const_iterator iter = qTemplates.begin(); iter != qTemplates.end(); ++iter) + { + Quest* qinfo = iter->second; + + std::string title; // "" for avoid repeating check default locale + sObjectMgr.GetQuestLocaleStrings(qinfo->GetQuestId(), loc_idx, &title); + + if ((title.empty() || !Utf8FitTo(title, wnamepart)) && !Utf8FitTo(qinfo->GetTitle(), wnamepart)) + { + continue; + } + + ShowQuestListHelper(qinfo->GetQuestId(), loc_idx, target); + ++counter; + } + + if (counter == 0) + { + SendSysMessage(LANG_COMMAND_NOQUESTFOUND); + } + + return true; +} + +bool ChatHandler::HandleLookupCreatureCommand(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); + + uint32 counter = 0; + + for (uint32 id = 0; id < sCreatureStorage.GetMaxEntry(); ++id) + { + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(id); + if (!cInfo) + { + continue; + } + + int loc_idx = GetSessionDbLocaleIndex(); + + char const* name = ""; // "" for avoid repeating check for default locale + sObjectMgr.GetCreatureLocaleStrings(id, loc_idx, &name); + if (!*name || !Utf8FitTo(name, wnamepart)) + { + name = cInfo->Name; + if (!Utf8FitTo(name, wnamepart)) + { + continue; + } + } + + if (m_session) + { + PSendSysMessage(LANG_CREATURE_ENTRY_LIST_CHAT, id, id, name); + } + else + { + PSendSysMessage(LANG_CREATURE_ENTRY_LIST_CONSOLE, id, name); + } + + ++counter; + } + + if (counter == 0) + { + SendSysMessage(LANG_COMMAND_NOCREATUREFOUND); + } + + return true; +} + +bool ChatHandler::HandleLookupObjectCommand(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); + + uint32 counter = 0; + + for (SQLStorageBase::SQLSIterator itr = sGOStorage.getDataBegin(); itr < sGOStorage.getDataEnd(); ++itr) + { + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + GameObjectLocale const* gl = sObjectMgr.GetGameObjectLocale(itr->id); + if (gl) + { + if ((int32)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, itr->id, itr->id, name.c_str()); + } + else + { + PSendSysMessage(LANG_GO_ENTRY_LIST_CONSOLE, itr->id, name.c_str()); + } + ++counter; + continue; + } + } + } + } + + std::string name = itr->name; + if (name.empty()) + { + continue; + } + + if (Utf8FitTo(name, wnamepart)) + { + if (m_session) + { + PSendSysMessage(LANG_GO_ENTRY_LIST_CHAT, itr->id, itr->id, name.c_str()); + } + else + { + PSendSysMessage(LANG_GO_ENTRY_LIST_CONSOLE, itr->id, name.c_str()); + } + ++counter; + } + } + + if (counter == 0) + { + SendSysMessage(LANG_COMMAND_NOGAMEOBJECTFOUND); + } + + return true; +} + +bool ChatHandler::HandleLookupTaxiNodeCommand(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); + + uint32 counter = 0; // Counter for figure out that we found smth. + + // 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); + ++counter; + } + } + } + if (counter == 0) // if counter == 0 then we found nth + { + SendSysMessage(LANG_COMMAND_NOTAXINODEFOUND); + } + return true; +} diff --git a/src/game/ChatCommands/MMapCommands.cpp b/src/game/ChatCommands/MMapCommands.cpp new file mode 100644 index 0000000000000..609f0bddc138c --- /dev/null +++ b/src/game/ChatCommands/MMapCommands.cpp @@ -0,0 +1,409 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "World.h" +#include "MoveMap.h" +#include "PathFinder.h" // for mmap manager +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" // for mmap manager +#include "CellImpl.h" +#include "movement/MoveSplineInit.h" +#include +#include +#include + +bool ChatHandler::HandleMmapPathCommand(char* args) +{ + if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(m_session->GetPlayer()->GetMapId())) + { + PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + PSendSysMessage("mmap path:"); + + // units + Player* player = m_session->GetPlayer(); + Unit* target = getSelectedUnit(); + if (!player || !target) + { + PSendSysMessage("Invalid target/source selection."); + return true; + } + + char* para = strtok(args, " "); + + bool useStraightPath = false; + bool followPath = false; + bool unitToPlayer = false; + if (para) + { + if (strcmp(para, "go") == 0) + { + followPath = true; + para = strtok(NULL, " "); + if (para && strcmp(para, "straight") == 0) + { + useStraightPath = true; + } + } + else if (strcmp(para, "straight") == 0) + { + useStraightPath = true; + } + else if (strcmp(para, "to_me") == 0) + { + unitToPlayer = true; + } + else + { + PSendSysMessage("Use '.mmap path go' to move on target."); + PSendSysMessage("Use '.mmap path straight' to generate straight path."); + PSendSysMessage("Use '.mmap path to_me' to generate path from the target to you."); + } + } + + Unit* destinationUnit; + Unit* originUnit; + if (unitToPlayer) + { + destinationUnit = player; + originUnit = target; + } + else + { + destinationUnit = target; + originUnit = player; + } + + // unit locations + float x, y, z; + destinationUnit->GetPosition(x, y, z); + + // path + PathFinder path(originUnit); + path.setUseStrightPath(useStraightPath); + path.calculate(x, y, z); + + PointsArray pointPath = path.getPath(); + PSendSysMessage("%s's path to %s:", originUnit->GetName(), destinationUnit->GetName()); + PSendSysMessage("Building %s", useStraightPath ? "StraightPath" : "SmoothPath"); + PSendSysMessage("length " SIZEFMTD " type %u", pointPath.size(), path.getPathType()); + + Vector3 start = path.getStartPosition(); + Vector3 end = path.getEndPosition(); + Vector3 actualEnd = path.getActualEndPosition(); + + PSendSysMessage("start (%.3f, %.3f, %.3f)", start.x, start.y, start.z); + PSendSysMessage("end (%.3f, %.3f, %.3f)", end.x, end.y, end.z); + PSendSysMessage("actual end (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z); + + if (!player->isGameMaster()) + { + PSendSysMessage("Enable GM mode to see the path points."); + } + + for (uint32 i = 0; i < pointPath.size(); ++i) + { + player->SummonCreature(VISUAL_WAYPOINT, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000); + } + + if (followPath) + { + Movement::MoveSplineInit init(*player); + init.MovebyPath(pointPath); + init.SetWalk(false); + init.Launch(); + } + + return true; +} + +bool ChatHandler::HandleMmapLocCommand(char* /*args*/) +{ + PSendSysMessage("mmap tileloc:"); + + // grid tile location + Player* player = m_session->GetPlayer(); + + int32 gx = 32 - player->GetPositionX() / SIZE_OF_GRIDS; + int32 gy = 32 - player->GetPositionY() / SIZE_OF_GRIDS; + + PSendSysMessage("%03u%02i%02i.mmtile", player->GetMapId(), gy, gx); + PSendSysMessage("gridloc [%i,%i]", gx, gy); + + // calculate navmesh tile location + const dtNavMesh* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(player->GetMapId()); + const dtNavMeshQuery* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(player->GetMapId(), player->GetInstanceId()); + if (!navmesh || !navmeshquery) + { + PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + const float* min = navmesh->getParams()->orig; + + float x, y, z; + player->GetPosition(x, y, z); + float location[VERTEX_SIZE] = {y, z, x}; + float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; + + int32 tilex = int32((y - min[0]) / SIZE_OF_GRIDS); + int32 tiley = int32((x - min[2]) / SIZE_OF_GRIDS); + + PSendSysMessage("Calc [%02i,%02i]", tilex, tiley); + + // navmesh poly -> navmesh tile location + dtQueryFilter filter = dtQueryFilter(); + dtPolyRef polyRef = INVALID_POLYREF; + navmeshquery->findNearestPoly(location, extents, &filter, &polyRef, NULL); + + if (polyRef == INVALID_POLYREF) + { + PSendSysMessage("Dt [??,??] (invalid poly, probably no tile loaded)"); + } + else + { + const dtMeshTile* tile; + const dtPoly* poly; + dtStatus dtResult = navmesh->getTileAndPolyByRef(polyRef, &tile, &poly); + if ((dtStatusSucceed(dtResult)) && tile) + { + PSendSysMessage("Dt [%02i,%02i]", tile->header->x, tile->header->y); + } + else + { + PSendSysMessage("Dt [??,??] (no tile loaded)"); + } + } + + return true; +} + +bool ChatHandler::HandleMmapLoadedTilesCommand(char* /*args*/) +{ + uint32 mapid = m_session->GetPlayer()->GetMapId(); + + const dtNavMesh* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid); + const dtNavMeshQuery* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, m_session->GetPlayer()->GetInstanceId()); + if (!navmesh || !navmeshquery) + { + PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + PSendSysMessage("mmap loadedtiles:"); + + for (int32 i = 0; i < navmesh->getMaxTiles(); ++i) + { + const dtMeshTile* tile = navmesh->getTile(i); + if (!tile || !tile->header) + { + continue; + } + + PSendSysMessage("[%02i,%02i]", tile->header->x, tile->header->y); + } + + return true; +} + +bool ChatHandler::HandleMmapStatsCommand(char* /*args*/) +{ + PSendSysMessage("mmap stats:"); + PSendSysMessage(" global mmap pathfinding is %sabled", sWorld.getConfig(CONFIG_BOOL_MMAP_ENABLED) ? "en" : "dis"); + + MMAP::MMapManager* manager = MMAP::MMapFactory::createOrGetMMapManager(); + PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount()); + + const dtNavMesh* navmesh = manager->GetNavMesh(m_session->GetPlayer()->GetMapId()); + if (!navmesh) + { + PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + uint32 tileCount = 0; + uint32 nodeCount = 0; + uint32 polyCount = 0; + uint32 vertCount = 0; + uint32 triCount = 0; + uint32 triVertCount = 0; + uint32 dataSize = 0; + for (int32 i = 0; i < navmesh->getMaxTiles(); ++i) + { + const dtMeshTile* tile = navmesh->getTile(i); + if (!tile || !tile->header) + { + continue; + } + + tileCount++; + nodeCount += tile->header->bvNodeCount; + polyCount += tile->header->polyCount; + vertCount += tile->header->vertCount; + triCount += tile->header->detailTriCount; + triVertCount += tile->header->detailVertCount; + dataSize += tile->dataSize; + } + + PSendSysMessage("Navmesh stats on current map:"); + PSendSysMessage(" %u tiles loaded", tileCount); + PSendSysMessage(" %u BVTree nodes", nodeCount); + PSendSysMessage(" %u polygons (%u vertices)", polyCount, vertCount); + PSendSysMessage(" %u triangles (%u vertices)", triCount, triVertCount); + PSendSysMessage(" %.2f MB of data (not including pointers)", ((float)dataSize / sizeof(unsigned char)) / 1048576); + + return true; +} + +bool ChatHandler::HandleMmap(char* args) +{ + bool on; + if (ExtractOnOff(&args, on)) + { + if (on) + { + sWorld.setConfig(CONFIG_BOOL_MMAP_ENABLED, true); + SendSysMessage("WORLD: mmaps are now ENABLED (individual map settings still in effect)"); + } + else + { + sWorld.setConfig(CONFIG_BOOL_MMAP_ENABLED, false); + SendSysMessage("WORLD: mmaps are now DISABLED"); + } + return true; + } + + on = sWorld.getConfig(CONFIG_BOOL_MMAP_ENABLED); + PSendSysMessage("mmaps are %sabled", on ? "en" : "dis"); + + return true; +} + +bool ChatHandler::HandleMmapTestArea(char* args) +{ + float radius = 40.0f; + ExtractFloat(&args, radius); + + std::list creatureList; + MaNGOS::AnyUnitInObjectRangeCheck go_check(m_session->GetPlayer(), radius); + MaNGOS::CreatureListSearcher go_search(creatureList, go_check); + // Get Creatures + Cell::VisitGridObjects(m_session->GetPlayer(), go_search, radius); + + if (!creatureList.empty()) + { + PSendSysMessage("Found " SIZEFMTD " Creatures.", creatureList.size()); + + uint32 paths = 0; + uint32 uStartTime = WorldTimer::getMSTime(); + + float gx, gy, gz; + m_session->GetPlayer()->GetPosition(gx, gy, gz); + for (std::list::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) + { + PathFinder path(*itr); + path.calculate(gx, gy, gz); + ++paths; + } + + uint32 uPathLoadTime = WorldTimer::getMSTimeDiff(uStartTime, WorldTimer::getMSTime()); + PSendSysMessage("Generated %i paths in %i ms", paths, uPathLoadTime); + } + else + { + PSendSysMessage("No creatures in %f yard range.", radius); + } + + return true; +} + +// use ".mmap testheight 10" selecting any creature/player +bool ChatHandler::HandleMmapTestHeight(char* args) +{ + float radius = 0.0f; + ExtractFloat(&args, radius); + if (radius > 40.0f) + { + radius = 40.0f; + } + + Unit* unit = getSelectedUnit(); + + Player* player = m_session->GetPlayer(); + if (!unit) + { + unit = player; + } + + if (unit->GetTypeId() == TYPEID_UNIT) + { + if (radius < 0.1f) + { + radius = static_cast(unit)->GetRespawnRadius(); + } + } + else + { + if (unit->GetTypeId() != TYPEID_PLAYER) + { + PSendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + return false; + } + } + + if (radius < 0.1f) + { + PSendSysMessage("Provided spawn radius for %s is too small. Using 5.0f instead.", unit->GetGuidStr().c_str()); + radius = 5.0f; + } + + float gx, gy, gz; + unit->GetPosition(gx, gy, gz); + + Creature* summoned = unit->SummonCreature(VISUAL_WAYPOINT, gx, gy, gz + 0.5f, 0, TEMPSUMMON_TIMED_DESPAWN, 20000); + summoned->CastSpell(summoned, 8599, false); + uint32 tries = 1; + uint32 successes = 0; + uint32 startTime = WorldTimer::getMSTime(); + for (; tries < 500; ++tries) + { + unit->GetPosition(gx, gy, gz); + if (unit->GetMap()->GetReachableRandomPosition(unit, gx, gy, gz, radius)) + { + unit->SummonCreature(VISUAL_WAYPOINT, gx, gy, gz, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); + ++successes; + if (successes >= 100) + { + break; + } + } + } + uint32 genTime = WorldTimer::getMSTimeDiff(startTime, WorldTimer::getMSTime()); + PSendSysMessage("Generated %u valid points for %u try in %ums.", successes, tries, genTime); + return true; +} diff --git a/src/game/ChatCommands/MailCommands.cpp b/src/game/ChatCommands/MailCommands.cpp new file mode 100644 index 0000000000000..5bce511b0ffbe --- /dev/null +++ b/src/game/ChatCommands/MailCommands.cpp @@ -0,0 +1,354 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "Mail.h" +#include "MassMailMgr.h" + + /********************************************************************** + CommandTable : mailCommandTable + /***********************************************************************/ + // Send mail by command +bool ChatHandler::HandleSendMailCommand(char* args) +{ + // format: name "subject text" "mail text" + Player* target; + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) + { + return false; + } + + MailDraft draft; + + // fill draft + if (!HandleSendMailHelper(draft, args)) + { + return false; + } + + // from console show nonexistent sender + MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM); + + draft.SendMailTo(MailReceiver(target, target_guid), sender); + + std::string nameLink = playerLink(target_name); + PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); + return true; +} + +bool ChatHandler::HandleSendMailHelper(MailDraft& draft, char* args) +{ + // format: "subject text" "mail text" + std::string msgSubject = ExtractQuotedArg(&args); + if (msgSubject.empty()) + { + return false; + } + + std::string msgText = ExtractQuotedArg(&args); + if (msgText.empty()) + { + return false; + } + + // msgSubject, msgText isn't NUL after prev. check + draft.SetSubjectAndBody(msgSubject, msgText); + + return true; +} + +bool ChatHandler::HandleSendMassMailCommand(char* args) +{ + // format: raceMask "subject text" "mail text" + uint32 raceMask = 0; + char const* name = NULL; + + if (!ExtractRaceMask(&args, raceMask, &name)) + { + return false; + } + + // need dynamic object because it trasfered to mass mailer + MailDraft* draft = new MailDraft; + + // fill mail + if (!HandleSendMailHelper(*draft, args)) + { + delete draft; + return false; + } + + // from console show nonexistent sender + MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM); + + sMassMailMgr.AddMassMailTask(draft, sender, raceMask); + + PSendSysMessage(LANG_MAIL_SENT, name); + return true; +} + +bool ChatHandler::HandleSendItemsHelper(MailDraft& draft, char* args) +{ + // format: "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] + std::string msgSubject = ExtractQuotedArg(&args); + if (msgSubject.empty()) + { + return false; + } + + std::string msgText = ExtractQuotedArg(&args); + if (msgText.empty()) + { + return false; + } + + // extract items + typedef std::pair ItemPair; + typedef std::list< ItemPair > ItemPairs; + ItemPairs items; + + // get from tail next item str + while (char* itemStr = ExtractArg(&args)) + { + // parse item str + uint32 item_id = 0; + uint32 item_count = 1; + if (sscanf(itemStr, "%u:%u", &item_id, &item_count) != 2) + { + if (sscanf(itemStr, "%u", &item_id) != 1) + { + return false; + } + } + if (!item_id) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + ItemPrototype const* item_proto = ObjectMgr::GetItemPrototype(item_id); + if (!item_proto) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + 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; + } + } + + // fill mail + draft.SetSubjectAndBody(msgSubject, msgText); + + 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); + } + } + + return true; +} + +bool ChatHandler::HandleSendItemsCommand(char* args) +{ + // format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] + Player* receiver; + ObjectGuid receiver_guid; + std::string receiver_name; + if (!ExtractPlayerTarget(&args, &receiver, &receiver_guid, &receiver_name)) + { + return false; + } + + MailDraft draft; + + // fill mail + if (!HandleSendItemsHelper(draft, args)) + { + return false; + } + + // from console show nonexistent sender + MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM); + + draft.SendMailTo(MailReceiver(receiver, receiver_guid), sender); + + std::string nameLink = playerLink(receiver_name); + PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); + return true; +} + +bool ChatHandler::HandleSendMassItemsCommand(char* args) +{ + // format: racemask "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] + + uint32 raceMask = 0; + char const* name = NULL; + + if (!ExtractRaceMask(&args, raceMask, &name)) + { + return false; + } + + // need dynamic object because it trasfered to mass mailer + MailDraft* draft = new MailDraft; + + + // fill mail + if (!HandleSendItemsHelper(*draft, args)) + { + delete draft; + return false; + } + + // from console show nonexistent sender + MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM); + + sMassMailMgr.AddMassMailTask(draft, sender, raceMask); + + PSendSysMessage(LANG_MAIL_SENT, name); + return true; +} + +bool ChatHandler::HandleSendMoneyHelper(MailDraft& draft, char* args) +{ + /// format: "subject text" "mail text" money + + std::string msgSubject = ExtractQuotedArg(&args); + if (msgSubject.empty()) + { + return false; + } + + char* msgText = ExtractQuotedArg(&args); + if (!msgText) + { + return false; + } + + uint32 money; + if (!ExtractUInt32(&args, money)) + { + return false; + } + + if (money <= 0) + { + return false; + } + + // msgSubject, msgText isn't NUL after prev. check + draft.SetSubjectAndBody(msgSubject, msgText).SetMoney(money); + + return true; +} + +bool ChatHandler::HandleSendMoneyCommand(char* args) +{ + /// format: name "subject text" "mail text" money + + Player* receiver; + ObjectGuid receiver_guid; + std::string receiver_name; + if (!ExtractPlayerTarget(&args, &receiver, &receiver_guid, &receiver_name)) + { + return false; + } + + MailDraft draft; + + // fill mail + if (!HandleSendMoneyHelper(draft, args)) + { + return false; + } + + // from console show nonexistent sender + MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM); + + draft.SendMailTo(MailReceiver(receiver, receiver_guid), sender); + + std::string nameLink = playerLink(receiver_name); + PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); + return true; +} + +bool ChatHandler::HandleSendMassMoneyCommand(char* args) +{ + /// format: raceMask "subject text" "mail text" money + + uint32 raceMask = 0; + char const* name = NULL; + + if (!ExtractRaceMask(&args, raceMask, &name)) + { + return false; + } + + // need dynamic object because it trasfered to mass mailer + MailDraft* draft = new MailDraft; + + // fill mail + if (!HandleSendMoneyHelper(*draft, args)) + { + delete draft; + return false; + } + + // from console show nonexistent sender + MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM); + + sMassMailMgr.AddMassMailTask(draft, sender, raceMask); + + PSendSysMessage(LANG_MAIL_SENT, name); + return true; +} + diff --git a/src/game/ChatCommands/MiscellanousCommands.cpp b/src/game/ChatCommands/MiscellanousCommands.cpp new file mode 100644 index 0000000000000..b63f40086f689 --- /dev/null +++ b/src/game/ChatCommands/MiscellanousCommands.cpp @@ -0,0 +1,265 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "World.h" +#include "BattleGroundMgr.h" +#include "PlayerDump.h" + + /********************************************************************** + CommandTable : commandTable + /***********************************************************************/ + +bool ChatHandler::HandleHelpCommand(char* args) +{ + if (!*args) + { + ShowHelpForCommand(getCommandTable(), "help"); + ShowHelpForCommand(getCommandTable(), ""); + } + else + { + if (!ShowHelpForCommand(getCommandTable(), args)) + { + SendSysMessage(LANG_NO_CMD); + } + } + + return true; +} + +bool ChatHandler::HandleCommandsCommand(char* /*args*/) +{ + ShowHelpForCommand(getCommandTable(), ""); + return true; +} + +bool ChatHandler::HandleGUIDCommand(char* /*args*/) +{ + ObjectGuid guid = m_session->GetPlayer()->GetSelectionGuid(); + + if (!guid) + { + SendSysMessage(LANG_NO_SELECTION); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_OBJECT_GUID, guid.GetString().c_str()); + return true; +} + +bool ChatHandler::HandleLoadScriptsCommand(char* args) +{ + if (!*args) + { + return false; + } + + switch (sScriptMgr.LoadScriptLibrary(args)) + { + case SCRIPT_LOAD_OK: + sWorld.SendWorldText(LANG_SCRIPTS_RELOADED_ANNOUNCE); + SendSysMessage(LANG_SCRIPTS_RELOADED_OK); + break; + case SCRIPT_LOAD_ERR_NOT_FOUND: + SendSysMessage(LANG_SCRIPTS_NOT_FOUND); + break; + case SCRIPT_LOAD_ERR_WRONG_API: + SendSysMessage(LANG_SCRIPTS_WRONG_API); + break; + case SCRIPT_LOAD_ERR_OUTDATED: + SendSysMessage(LANG_SCRIPTS_OUTDATED); + break; + } + + return true; +} + +bool ChatHandler::HandlePDumpLoadCommand(char* args) +{ + char* file = ExtractQuotedOrLiteralArg(&args); + if (!file) + { + return false; + } + + std::string account_name; + uint32 account_id = ExtractAccountId(&args, &account_name); + if (!account_id) + { + return false; + } + + char* name_str = ExtractLiteralArg(&args); + + uint32 lowguid = 0; + 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; + } + + if (*args) + { + if (!ExtractUInt32(&args, lowguid)) + { + return false; + } + + if (!lowguid) + { + PSendSysMessage(LANG_INVALID_CHARACTER_GUID); + SetSentErrorMessage(true); + return false; + } + + ObjectGuid guid = ObjectGuid(HIGHGUID_PLAYER, lowguid); + + if (sObjectMgr.GetPlayerAccountIdByGUID(guid)) + { + PSendSysMessage(LANG_CHARACTER_GUID_IN_USE, lowguid); + SetSentErrorMessage(true); + return false; + } + } + } + + switch (PlayerDumpReader().LoadDump(file, account_id, name, lowguid)) + { + 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(char* args) +{ + if (!*args) + { + return false; + } + + char* file = ExtractQuotedOrLiteralArg(&args); + if (!file) + { + return false; + } + + char* p2 = ExtractLiteralArg(&args); + + uint32 lowguid; + ObjectGuid guid; + // character name can't start from number + if (!ExtractUInt32(&p2, lowguid)) + { + std::string name = ExtractPlayerNameFromLink(&p2); + if (name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + guid = sObjectMgr.GetPlayerGuidByName(name); + if (!guid) + { + PSendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + lowguid = guid.GetCounter(); + } + else + { + guid = ObjectGuid(HIGHGUID_PLAYER, lowguid); + } + + if (!sObjectMgr.GetPlayerAccountIdByGUID(guid)) + { + PSendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + switch (PlayerDumpWriter().WriteDump(file, lowguid)) + { + 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; +} + +// Misc COmmands + +bool ChatHandler::HandleFlushArenaPointsCommand(char* /*args*/) +{ + sBattleGroundMgr.DistributeArenaPoints(); + return true; +} + diff --git a/src/game/ChatCommands/PlayerAndCreatureCommands.cpp b/src/game/ChatCommands/PlayerAndCreatureCommands.cpp new file mode 100644 index 0000000000000..aba370a63c447 --- /dev/null +++ b/src/game/ChatCommands/PlayerAndCreatureCommands.cpp @@ -0,0 +1,336 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "PathFinder.h" +#include "TargetedMovementGenerator.h" +#include "MovementGenerator.h" +#include "FollowerReference.h" +#include "G3D/Vector3.h" + + /********************************************************************** + CommandTable : commandTable + /***********************************************************************/ + +// demorph player or unit +bool ChatHandler::HandleDeMorphCommand(char* /*args*/) +{ + Unit* target = getSelectedUnit(); + if (!target) + { + target = m_session->GetPlayer(); + } + + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target)) + { + return false; + } + + target->DeMorph(); + + return true; +} + +// morph creature or player +bool ChatHandler::HandleModifyMorphCommand(char* args) +{ + if (!*args) + { + return false; + } + + uint32 display_id = (uint32)atoi(args); + + CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(display_id); + if (!displayEntry) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Unit* target = getSelectedUnit(); + if (!target) + { + target = m_session->GetPlayer(); + } + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target)) + { + return false; + } + + target->SetDisplayId(display_id); + + return true; +} + +bool ChatHandler::HandleDamageCommand(char* args) +{ + if (!*args) + { + return false; + } + + Unit* target = getSelectedUnit(); + Player* player = m_session->GetPlayer(); + + if (!target || !player->GetSelectionGuid()) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (!target->IsAlive()) + { + return true; + } + + int32 damage_int; + if (!ExtractInt32(&args, damage_int)) + { + return false; + } + + if (damage_int <= 0) + { + return true; + } + + uint32 damage = damage_int; + + // flat melee damage without resistance/etc reduction + if (!*args) + { + player->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + if (target != player) + { + player->SendAttackStateUpdate(HITINFO_NORMALSWING2, target, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); + } + return true; + } + + uint32 school; + if (!ExtractUInt32(&args, school)) + { + return false; + } + + if (school >= MAX_SPELL_SCHOOL) + { + return false; + } + + SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); + + if (schoolmask & SPELL_SCHOOL_MASK_NORMAL) + { + damage = player->CalcArmorReducedDamage(target, damage); + } + + // melee damage by specific school + if (!*args) + { + uint32 absorb = 0; + uint32 resist = 0; + + target->CalculateDamageAbsorbAndResist(player, schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + + if (damage <= absorb + resist) + { + return true; + } + + damage -= absorb + resist; + + player->DealDamageMods(target, damage, &absorb); + player->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); + player->SendAttackStateUpdate(HITINFO_NORMALSWING2, target, 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(&args); + if (!spellid || !sSpellStore.LookupEntry(spellid)) + { + return false; + } + + player->SpellNonMeleeDamageLog(target, spellid, damage); + return true; +} + +bool ChatHandler::HandleDieCommand(char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + Unit* target = getSelectedUnit(); + + if (!target || !player->GetSelectionGuid()) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (target->GetTypeId() == TYPEID_PLAYER) + { + if (HasLowerSecurity((Player*)target, ObjectGuid(), false)) + { + return false; + } + } + + if (target->IsAlive()) + { + player->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + return true; +} + +bool ChatHandler::HandleMovegensCommand(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(); + float x, y, z; + mm->GetDestination(x, y, z); + for (MotionMaster::const_iterator itr = mm->begin(); itr != mm->end(); ++itr) + { + switch ((*itr)->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 CONFUSED_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_CONFUSED); break; + + case CHASE_MOTION_TYPE: + { + Unit* target = NULL; + if (unit->GetTypeId() == TYPEID_PLAYER) + { + target = static_cast const*>(*itr)->GetTarget(); + } + else + { + target = static_cast const*>(*itr)->GetTarget(); + } + + if (!target) + { + SendSysMessage(LANG_MOVEGENS_CHASE_NULL); + } + else if (target->GetTypeId() == TYPEID_PLAYER) + { + PSendSysMessage(LANG_MOVEGENS_CHASE_PLAYER, target->GetName(), target->GetGUIDLow()); + } + else + { + PSendSysMessage(LANG_MOVEGENS_CHASE_CREATURE, target->GetName(), target->GetGUIDLow()); + } + break; + } + case FOLLOW_MOTION_TYPE: + { + Unit* target = NULL; + if (unit->GetTypeId() == TYPEID_PLAYER) + { + target = static_cast const*>(*itr)->GetTarget(); + } + else + { + target = static_cast const*>(*itr)->GetTarget(); + } + + if (!target) + { + SendSysMessage(LANG_MOVEGENS_FOLLOW_NULL); + } + else if (target->GetTypeId() == TYPEID_PLAYER) + { + PSendSysMessage(LANG_MOVEGENS_FOLLOW_PLAYER, target->GetName(), target->GetGUIDLow()); + } + else + { + PSendSysMessage(LANG_MOVEGENS_FOLLOW_CREATURE, target->GetName(), target->GetGUIDLow()); + } + break; + } + case HOME_MOTION_TYPE: + if (unit->GetTypeId() == TYPEID_UNIT) + { + 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: + { + 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; + case EFFECT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_EFFECT); break; + default: + PSendSysMessage(LANG_MOVEGENS_UNKNOWN, (*itr)->GetMovementGeneratorType()); + break; + } + } + return true; +} + +bool ChatHandler::HandleSetViewCommand(char* /*args*/) +{ + if (Unit* unit = getSelectedUnit()) + { + m_session->GetPlayer()->GetCamera().SetView(unit); + } + else + { + PSendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + return true; +} diff --git a/src/game/ChatCommands/PlayerCommands.cpp b/src/game/ChatCommands/PlayerCommands.cpp new file mode 100644 index 0000000000000..085aa55512cf6 --- /dev/null +++ b/src/game/ChatCommands/PlayerCommands.cpp @@ -0,0 +1,2412 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "World.h" +#include "AccountMgr.h" +#include "ObjectMgr.h" +#include "SQLStorages.h" + + + + /********************************************************************** + CommandTable : characterCommandTable + /***********************************************************************/ + +bool ChatHandler::HandleCharacterEraseCommand(char* args) +{ + char* nameStr = ExtractLiteralArg(&args); + if (!nameStr) + { + return false; + } + + Player* target; + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&nameStr, &target, &target_guid, &target_name)) + { + return false; + } + + uint32 account_id; + + if (target) + { + account_id = target->GetSession()->GetAccountId(); + target->GetSession()->KickPlayer(); + } + else + { + account_id = sObjectMgr.GetPlayerAccountIdByGUID(target_guid); + } + + std::string account_name; + sAccountMgr.GetName(account_id, account_name); + + Player::DeleteFromDB(target_guid, account_id, true, true); + PSendSysMessage(LANG_CHARACTER_DELETED, target_name.c_str(), target_guid.GetCounter(), account_name.c_str(), account_id); + return true; +} + +bool ChatHandler::HandleCharacterLevelCommand(char* args) +{ + char* nameStr = ExtractOptNotLastArg(&args); + + int32 newlevel; + bool nolevel = false; + // exception opt second arg: .character level $name + if (!ExtractInt32(&args, newlevel)) + { + if (!nameStr) + { + nameStr = ExtractArg(&args); + if (!nameStr) + { + return false; + } + + nolevel = true; + } + else + { + return false; + } + } + + Player* target; + ObjectGuid 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); + if (nolevel) + { + newlevel = 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; +} + +// rename characters +bool ChatHandler::HandleCharacterRenameCommand(char* args) +{ + Player* target; + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) + { + return false; + } + + if (target) + { + // check online security + if (HasLowerSecurity(target)) + { + return false; + } + + PSendSysMessage(LANG_RENAME_PLAYER, GetNameLink(target).c_str()); + target->SetAtLoginFlag(AT_LOGIN_RENAME); + CharacterDatabase.PExecute("UPDATE `characters` SET `at_login` = `at_login` | '1' WHERE `guid` = '%u'", target->GetGUIDLow()); + } + 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(), target_guid.GetCounter()); + CharacterDatabase.PExecute("UPDATE `characters` SET `at_login` = `at_login` | '1' WHERE `guid` = '%u'", target_guid.GetCounter()); + } + + return true; +} + +bool ChatHandler::HandleCharacterReputationCommand(char* args) +{ + Player* target; + if (!ExtractPlayerTarget(&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); + + ShowFactionListHelper(factionEntry, loc, &itr->second, target); + } + return true; +} + +/********************************************************************** + CommandTable : characterDeletedCommandTable +/***********************************************************************/ + +/** + * Collects all GUIDs (and related info) from deleted characters which are still in the database. + * + * @param foundList a reference to an std::list which will be filled with info data + * @param searchString the search string which either contains a player GUID (low part) or a part of the character-name + * @return returns false if there was a problem while selecting the characters (e.g. player name not normalizeable) + */ + +bool ChatHandler::GetDeletedCharacterInfoList(DeletedInfoList& foundList, std::string searchString) +{ + QueryResult* resultChar; + if (!searchString.empty()) + { + // search by GUID + if (isNumeric(searchString)) + { + resultChar = CharacterDatabase.PQuery("SELECT `guid`, `deleteInfos_Name`, `deleteInfos_Account`, `deleteDate` FROM `characters` WHERE `deleteDate` IS NOT NULL AND `guid` = %u", uint32(atoi(searchString.c_str()))); + } + // search by name + else + { + if (!normalizePlayerName(searchString)) + { + return false; + } + + resultChar = CharacterDatabase.PQuery("SELECT `guid`, `deleteInfos_Name`, `deleteInfos_Account`, `deleteDate` FROM `characters` WHERE `deleteDate` IS NOT NULL AND `deleteInfos_Name` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), searchString.c_str()); + } + } + else + { + resultChar = CharacterDatabase.Query("SELECT `guid`, `deleteInfos_Name`, `deleteInfos_Account`, `deleteDate` FROM `characters` WHERE `deleteDate` IS NOT NULL"); + } + + if (resultChar) + { + do + { + Field* fields = resultChar->Fetch(); + + DeletedInfo info; + + info.lowguid = fields[0].GetUInt32(); + info.name = fields[1].GetCppString(); + info.accountId = fields[2].GetUInt32(); + + // account name will be empty for nonexistent account + sAccountMgr.GetName(info.accountId, info.accountName); + + info.deleteDate = time_t(fields[3].GetUInt64()); + + foundList.push_back(info); + } + while (resultChar->NextRow()); + + delete resultChar; + } + + return true; +} + +/** + * Generate WHERE guids list by deleted info in way preventing return too long where list for existed query string length limit. + * + * @param itr a reference to an deleted info list iterator, it updated in function for possible next function call if list to long + * @param itr_end a reference to an deleted info list iterator end() + * @return returns generated where list string in form: 'guid IN (gui1, guid2, ...)' + */ +std::string ChatHandler::GenerateDeletedCharacterGUIDsWhereStr(DeletedInfoList::const_iterator& itr, DeletedInfoList::const_iterator const& itr_end) +{ + std::ostringstream wherestr; + wherestr << "guid IN ('"; + for (; itr != itr_end; ++itr) + { + wherestr << itr->lowguid; + + if (wherestr.str().size() > MAX_QUERY_LEN - 50) // near to max query + { + ++itr; + break; + } + + DeletedInfoList::const_iterator itr2 = itr; + if (++itr2 != itr_end) + { + wherestr << "','"; + } + } + wherestr << "')"; + return wherestr.str(); +} + +/** + * Shows all deleted characters which matches the given search string, expected non empty list + * + * @see ChatHandler::HandleCharacterDeletedListCommand + * @see ChatHandler::HandleCharacterDeletedRestoreCommand + * @see ChatHandler::HandleCharacterDeletedDeleteCommand + * @see ChatHandler::DeletedInfoList + * + * @param foundList contains a list with all found deleted characters + */ +void ChatHandler::HandleCharacterDeletedListHelper(DeletedInfoList const& foundList) +{ + if (!m_session) + { + SendSysMessage(LANG_CHARACTER_DELETED_LIST_BAR); + SendSysMessage(LANG_CHARACTER_DELETED_LIST_HEADER); + SendSysMessage(LANG_CHARACTER_DELETED_LIST_BAR); + } + + for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr) + { + std::string dateStr = TimeToTimestampStr(itr->deleteDate); + + if (!m_session) + PSendSysMessage(LANG_CHARACTER_DELETED_LIST_LINE_CONSOLE, + itr->lowguid, itr->name.c_str(), itr->accountName.empty() ? "" : itr->accountName.c_str(), + itr->accountId, dateStr.c_str()); + else + PSendSysMessage(LANG_CHARACTER_DELETED_LIST_LINE_CHAT, + itr->lowguid, itr->name.c_str(), itr->accountName.empty() ? "" : itr->accountName.c_str(), + itr->accountId, dateStr.c_str()); + } + + if (!m_session) + { + SendSysMessage(LANG_CHARACTER_DELETED_LIST_BAR); + } +} + +/** + * Restore a previously deleted character + * + * @see ChatHandler::HandleCharacterDeletedListHelper + * @see ChatHandler::HandleCharacterDeletedRestoreCommand + * @see ChatHandler::HandleCharacterDeletedDeleteCommand + * @see ChatHandler::DeletedInfoList + * + * @param delInfo the informations about the character which will be restored + */ + +void ChatHandler::HandleCharacterDeletedRestoreHelper(DeletedInfo const& delInfo) +{ + if (delInfo.accountName.empty()) // account not exist + { + PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_ACCOUNT, delInfo.name.c_str(), delInfo.lowguid, delInfo.accountId); + return; + } + + // check character count + uint32 charcount = sAccountMgr.GetCharactersCount(delInfo.accountId); + if (charcount >= 10) + { + PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_FULL, delInfo.name.c_str(), delInfo.lowguid, delInfo.accountId); + return; + } + + if (sObjectMgr.GetPlayerGuidByName(delInfo.name)) + { + PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_NAME, delInfo.name.c_str(), delInfo.lowguid, delInfo.accountId); + return; + } + + CharacterDatabase.PExecute("UPDATE `characters` SET `name`='%s', `account`='%u', `deleteDate`=NULL, `deleteInfos_Name`=NULL, `deleteInfos_Account`=NULL WHERE `deleteDate` IS NOT NULL AND `guid` = %u", + delInfo.name.c_str(), delInfo.accountId, delInfo.lowguid); +} + +/** + * Handles the '.character deleted delete' command, which completely deletes all deleted characters which matches the given search string + * + * @see Player::GetDeletedCharacterGUIDs + * @see Player::DeleteFromDB + * @see ChatHandler::HandleCharacterDeletedListCommand + * @see ChatHandler::HandleCharacterDeletedRestoreCommand + * + * @param args the search string which either contains a player GUID or a part of the character-name + */ +bool ChatHandler::HandleCharacterDeletedDeleteCommand(char* args) +{ + // It is required to submit at least one argument + if (!*args) + { + return false; + } + + DeletedInfoList foundList; + if (!GetDeletedCharacterInfoList(foundList, args)) + { + return false; + } + + if (foundList.empty()) + { + SendSysMessage(LANG_CHARACTER_DELETED_LIST_EMPTY); + return false; + } + + SendSysMessage(LANG_CHARACTER_DELETED_DELETE); + HandleCharacterDeletedListHelper(foundList); + + // Call the appropriate function to delete them (current account for deleted characters is 0) + for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr) + { + Player::DeleteFromDB(ObjectGuid(HIGHGUID_PLAYER, itr->lowguid), 0, false, true); + } + + return true; +} + +/** + * Handles the '.character deleted list' command, which shows all deleted characters which matches the given search string + * + * @see ChatHandler::HandleCharacterDeletedListHelper + * @see ChatHandler::HandleCharacterDeletedRestoreCommand + * @see ChatHandler::HandleCharacterDeletedDeleteCommand + * @see ChatHandler::DeletedInfoList + * + * @param args the search string which either contains a player GUID or a part of the character-name + */ +bool ChatHandler::HandleCharacterDeletedListCommand(char* args) +{ + DeletedInfoList foundList; + if (!GetDeletedCharacterInfoList(foundList, args)) + { + return false; + } + + // if no characters have been found, output a warning + if (foundList.empty()) + { + SendSysMessage(LANG_CHARACTER_DELETED_LIST_EMPTY); + return false; + } + + HandleCharacterDeletedListHelper(foundList); + return true; +} + +/** + * Handles the '.character deleted restore' command, which restores all deleted characters which matches the given search string + * + * The command automatically calls '.character deleted list' command with the search string to show all restored characters. + * + * @see ChatHandler::HandleCharacterDeletedRestoreHelper + * @see ChatHandler::HandleCharacterDeletedListCommand + * @see ChatHandler::HandleCharacterDeletedDeleteCommand + * + * @param args the search string which either contains a player GUID or a part of the character-name + */ +bool ChatHandler::HandleCharacterDeletedRestoreCommand(char* args) +{ + // It is required to submit at least one argument + if (!*args) + { + return false; + } + + std::string searchString; + std::string newCharName; + uint32 newAccount = 0; + + // GCC by some strange reason fail build code without temporary variable + std::istringstream params(args); + params >> searchString >> newCharName >> newAccount; + + DeletedInfoList foundList; + if (!GetDeletedCharacterInfoList(foundList, searchString)) + { + return false; + } + + if (foundList.empty()) + { + SendSysMessage(LANG_CHARACTER_DELETED_LIST_EMPTY); + return false; + } + + SendSysMessage(LANG_CHARACTER_DELETED_RESTORE); + HandleCharacterDeletedListHelper(foundList); + + if (newCharName.empty()) + { + // Drop nonexistent account cases + for (DeletedInfoList::iterator itr = foundList.begin(); itr != foundList.end(); ++itr) + { + HandleCharacterDeletedRestoreHelper(*itr); + } + } + else if (foundList.size() == 1 && normalizePlayerName(newCharName)) + { + DeletedInfo delInfo = foundList.front(); + + // update name + delInfo.name = newCharName; + + // if new account provided update deleted info + if (newAccount && newAccount != delInfo.accountId) + { + delInfo.accountId = newAccount; + sAccountMgr.GetName(newAccount, delInfo.accountName); + } + + HandleCharacterDeletedRestoreHelper(delInfo); + } + else + { + SendSysMessage(LANG_CHARACTER_DELETED_ERR_RENAME); + } + + return true; +} + +/** + * Handles the '.character deleted old' command, which completely deletes all deleted characters deleted with some days ago + * + * @see Player::DeleteOldCharacters + * @see Player::DeleteFromDB + * @see ChatHandler::HandleCharacterDeletedDeleteCommand + * @see ChatHandler::HandleCharacterDeletedListCommand + * @see ChatHandler::HandleCharacterDeletedRestoreCommand + * + * @param args the search string which either contains a player GUID or a part of the character-name + */ +bool ChatHandler::HandleCharacterDeletedOldCommand(char* args) +{ + int32 keepDays = sWorld.getConfig(CONFIG_UINT32_CHARDELETE_KEEP_DAYS); + + if (!ExtractOptInt32(&args, keepDays, sWorld.getConfig(CONFIG_UINT32_CHARDELETE_KEEP_DAYS))) + { + return false; + } + + if (keepDays < 0) + { + return false; + } + + Player::DeleteOldCharacters((uint32)keepDays); + return true; +} + +/********************************************************************** + CommandTable : commandTable +/***********************************************************************/ + +void ChatHandler::HandleCharacterLevel(Player* player, ObjectGuid 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, player_guid.GetCounter()); + } +} + +bool ChatHandler::HandleReviveCommand(char* args) +{ + Player* target; + ObjectGuid target_guid; + if (!ExtractPlayerTarget(&args, &target, &target_guid)) + { + return false; + } + + if (target) + { + target->ResurrectPlayer(0.5f); + target->SpawnCorpseBones(); + } + else // will resurrected at login without corpse + { + sObjectAccessor.ConvertCorpseForPlayer(target_guid); + } + + return true; +} + +bool ChatHandler::HandleDismountCommand(char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + + // If player is not mounted, so go out :) + if (!player->IsMounted()) + { + SendSysMessage(LANG_CHAR_NON_MOUNTED); + SetSentErrorMessage(true); + return false; + } + + if (player->IsTaxiFlying()) + { + SendSysMessage(LANG_YOU_IN_FLIGHT); + SetSentErrorMessage(true); + return false; + } + + player->Unmount(); + player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + return true; +} + +bool ChatHandler::HandleLinkGraveCommand(char* args) +{ + uint32 g_id; + if (!ExtractUInt32(&args, g_id)) + { + return false; + } + + char* teamStr = ExtractLiteralArg(&args); + + Team g_team; + if (!teamStr) + { + g_team = TEAM_BOTH_ALLOWED; + } + else if (strncmp(teamStr, "horde", strlen(teamStr)) == 0) + { + g_team = HORDE; + } + else if (strncmp(teamStr, "alliance", strlen(teamStr)) == 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 (sObjectMgr.AddGraveYardLink(g_id, zoneId, g_team)) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDLINKED, g_id, zoneId); + } + else + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDALRLINKED, g_id, zoneId); + } + + return true; +} + +// move item to other slot +bool ChatHandler::HandleItemMoveCommand(char* args) +{ + if (!*args) + { + return false; + } + uint8 srcslot, dstslot; + + char* pParam1 = strtok(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; + } + + Player* player = m_session->GetPlayer(); + if (!player->IsValidPos(INVENTORY_SLOT_BAG_0, srcslot, true)) + { + return false; + } + + // can be autostore pos + if (!player->IsValidPos(INVENTORY_SLOT_BAG_0, dstslot, false)) + { + return false; + } + + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); + uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); + + player->SwapItem(src, dst); + + return true; +} + +bool ChatHandler::HandleCooldownCommand(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(&args); + if (!spell_id) + { + return false; + } + + if (!sSpellStore.LookupEntry(spell_id)) + { + PSendSysMessage(LANG_UNKNOWN_SPELL, target == m_session->GetPlayer() ? GetMangosString(LANG_YOU) : tNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + target->RemoveSpellCooldown(spell_id, true); + PSendSysMessage(LANG_REMOVE_COOLDOWN, spell_id, target == m_session->GetPlayer() ? GetMangosString(LANG_YOU) : tNameLink.c_str()); + } + return true; +} + +bool ChatHandler::HandleSaveCommand(char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + + // save GM account without delay and output message (testing, etc) + if (GetAccessLevel() > 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_UINT32_INTERVAL_SAVE); + if (save_interval == 0 || (save_interval > 20 * IN_MILLISECONDS && player->GetSaveTimer() <= save_interval - 20 * IN_MILLISECONDS)) + { + player->SaveToDB(); + } + + return true; +} + +// Save all players in the world +bool ChatHandler::HandleSaveAllCommand(char* /*args*/) +{ + sObjectAccessor.SaveAllPlayers(); + SendSysMessage(LANG_PLAYERS_SAVED); + return true; +} + +bool ChatHandler::HandleStartCommand(char* /*args*/) +{ + Player* chr = m_session->GetPlayer(); + + if (chr->IsTaxiFlying()) + { + SendSysMessage(LANG_YOU_IN_FLIGHT); + SetSentErrorMessage(true); + return false; + } + + if (chr->IsInCombat()) + { + SendSysMessage(LANG_YOU_IN_COMBAT); + SetSentErrorMessage(true); + return false; + } + + // cast spell Stuck + chr->CastSpell(chr, 7355, false); + return true; +} + +// Enable On\OFF all taxi paths +bool ChatHandler::HandleTaxiCheatCommand(char* args) +{ + bool value; + if (!ExtractOnOff(&args, value)) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + Player* chr = getSelectedPlayer(); + if (!chr) + { + chr = m_session->GetPlayer(); + } + // check online security + else if (HasLowerSecurity(chr)) + { + return false; + } + + if (value) + { + 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()); + } + } + else + { + 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; +} + +bool ChatHandler::HandleExploreCheatCommand(char* args) +{ + if (!*args) + { + return false; + } + + int flag = atoi(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::HandleLevelUpCommand(char* args) +{ + int32 addlevel = 1; + char* nameStr = NULL; + + if (*args) + { + nameStr = ExtractOptNotLastArg(&args); + + // exception opt second arg: .levelup $name + if (!ExtractInt32(&args, addlevel)) + { + if (!nameStr) + { + nameStr = ExtractArg(&args); + } + else + { + return false; + } + } + } + + Player* target; + ObjectGuid 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 = 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(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(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(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(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::HandleAddItemCommand(char* args) +{ + char* cId = ExtractKeyFromLink(&args, "Hitem"); + if (!cId) + { + return false; + } + + uint32 itemId = 0; + if (!ExtractUInt32(&cId, itemId)) // [name] manual form + { + std::string itemName = cId; + WorldDatabase.escape_string(itemName); + QueryResult* result = WorldDatabase.PQuery("SELECT `entry` FROM `item_template` WHERE `name` = '%s'", itemName.c_str()); + if (!result) + { + PSendSysMessage(LANG_COMMAND_COULDNOTFIND, cId); + SetSentErrorMessage(true); + return false; + } + itemId = result->Fetch()->GetUInt16(); + delete result; + } + + int32 count; + if (!ExtractOptInt32(&args, count, 1)) + { + return false; + } + + Player* pl = m_session->GetPlayer(); + Player* plTarget = getSelectedPlayer(); + if (!plTarget) + { + plTarget = pl; + } + + DETAIL_LOG(GetMangosString(LANG_ADDITEM), itemId, count); + + ItemPrototype const* pProto = ObjectMgr::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(char* args) +{ + uint32 itemsetId; + if (!ExtractUint32KeyFromLink(&args, "Hitemset", itemsetId)) + { + return false; + } + + // 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; + } + + DETAIL_LOG(GetMangosString(LANG_ADDITEMSET), itemsetId); + + bool found = false; + for (uint32 id = 0; id < sItemStorage.GetMaxEntry(); ++id) + { + ItemPrototype const* pProto = sItemStorage.LookupEntry(id); + if (!pProto) + { + continue; + } + + if (pProto->ItemSet == itemsetId) + { + found = true; + ItemPosCountVec dest; + InventoryResult 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, pProto->ItemId); + 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::HandleMaxSkillCommand(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(char* args) +{ + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hskill:skill_id|h[name]|h|r + char* skill_p = ExtractKeyFromLink(&args, "Hskill"); + if (!skill_p) + { + return false; + } + + int32 skill; + if (!ExtractInt32(&skill_p, skill)) + { + return false; + } + + int32 level; + if (!ExtractInt32(&args, level)) + { + return false; + } + + int32 maxskill; + if (!ExtractOptInt32(&args, maxskill, target->GetPureMaxSkillValue(skill))) + { + return false; + } + + if (skill <= 0) + { + PSendSysMessage(LANG_INVALID_SKILL_ID, skill); + 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; + } + + if (level <= 0 || level > maxskill || maxskill <= 0) + { + return false; + } + + target->SetSkill(skill, level, maxskill); + PSendSysMessage(LANG_SET_SKILL, skill, sl->name[GetSessionDbcLocale()], tNameLink.c_str(), level, maxskill); + + return true; +} + +bool ChatHandler::HandleCombatStopCommand(char* args) +{ + Player* target; + if (!ExtractPlayerTarget(&args, &target)) + { + return false; + } + + // check online security + if (HasLowerSecurity(target)) + { + return false; + } + + target->CombatStop(); + target->GetHostileRefManager().deleteReferences(); + return true; +} + +bool ChatHandler::HandleRepairitemsCommand(char* args) +{ + Player* target; + if (!ExtractPlayerTarget(&args, &target)) + { + return false; + } + + // check online security + if (HasLowerSecurity(target)) + { + 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; +} + +// Edit Player HP +bool ChatHandler::HandleModifyHPCommand(char* args) +{ + if (!*args) + { + return false; + } + + int32 hp = atoi(args); + int32 hpm = atoi(args); + + if (hp <= 0 || hpm <= 0 || 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; + } + + // check online security + if (HasLowerSecurity(chr)) + { + 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(char* args) +{ + if (!*args) + { + return false; + } + + int32 mana = atoi(args); + int32 manam = atoi(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)) + { + 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(char* args) +{ + if (!*args) + { + return false; + } + + int32 energy = atoi(args) * 10; + int32 energym = atoi(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)) + { + 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); + + DETAIL_LOG(GetMangosString(LANG_CURRENT_ENERGY), chr->GetMaxPower(POWER_ENERGY)); + + return true; +} + +// Edit Player Rage +bool ChatHandler::HandleModifyRageCommand(char* args) +{ + if (!*args) + { + return false; + } + + int32 rage = atoi(args) * 10; + int32 ragem = atoi(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)) + { + 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 TP +bool ChatHandler::HandleModifyTalentCommand(char* args) +{ + if (!*args) + { + return false; + } + + int tp = atoi(args); + if (tp < 0) + { + return false; + } + + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target)) + { + return false; + } + + target->SetFreeTalentPoints(tp); + return true; +} + +// Edit Player Aspeed +bool ChatHandler::HandleModifyASpeedCommand(char* args) +{ + if (!*args) + { + return false; + } + + float modSpeed = (float)atof(args); + + if (modSpeed > sWorld.getConfig(CONFIG_UINT32_GM_MAX_SPEED_FACTOR) || modSpeed < 0.1) + { + 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)) + { + return false; + } + + std::string chrNameLink = GetNameLink(chr); + + if (chr->IsTaxiFlying()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT, chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_ASPEED, modSpeed, chrNameLink.c_str()); + if (needReportToTarget(chr)) + { + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, GetNameLink().c_str(), modSpeed); + } + + chr->UpdateSpeed(MOVE_WALK, true, modSpeed); + chr->UpdateSpeed(MOVE_RUN, true, modSpeed); + chr->UpdateSpeed(MOVE_SWIM, true, modSpeed); + // chr->UpdateSpeed(MOVE_TURN, true, modSpeed); + chr->UpdateSpeed(MOVE_FLIGHT, true, modSpeed); + return true; +} + +// Edit Player Speed +bool ChatHandler::HandleModifySpeedCommand(char* args) +{ + if (!*args) + { + return false; + } + + float modSpeed = (float)atof(args); + + if (modSpeed > sWorld.getConfig(CONFIG_UINT32_GM_MAX_SPEED_FACTOR) || modSpeed < 0.1) + { + 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)) + { + return false; + } + + std::string chrNameLink = GetNameLink(chr); + + if (chr->IsTaxiFlying()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT, chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_SPEED, modSpeed, chrNameLink.c_str()); + if (needReportToTarget(chr)) + { + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, GetNameLink().c_str(), modSpeed); + } + + chr->UpdateSpeed(MOVE_RUN, true, modSpeed); + + return true; +} + +// Edit Player Swim Speed +bool ChatHandler::HandleModifySwimCommand(char* args) +{ + if (!*args) + { + return false; + } + + float modSpeed = (float)atof(args); + + if (modSpeed > sWorld.getConfig(CONFIG_UINT32_GM_MAX_SPEED_FACTOR) || modSpeed < 0.01f) + { + 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)) + { + return false; + } + + std::string chrNameLink = GetNameLink(chr); + + if (chr->IsTaxiFlying()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT, chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, modSpeed, chrNameLink.c_str()); + if (needReportToTarget(chr)) + { + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, GetNameLink().c_str(), modSpeed); + } + + chr->UpdateSpeed(MOVE_SWIM, true, modSpeed); + + return true; +} + +//Edit Player Fly command +bool ChatHandler::HandleModifyFlyCommand(char* args) +{ + if (!*args) + { + return false; + } + + float modSpeed = (float)atof(args); + + if (modSpeed > 10.0f || modSpeed < 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)) + { + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, modSpeed, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + { + ChatHandler(chr).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, GetNameLink().c_str(), modSpeed); + } + + chr->UpdateSpeed(MOVE_FLIGHT, true, modSpeed); + + return true; +} + +// Edit Player Walk Speed +bool ChatHandler::HandleModifyBWalkCommand(char* args) +{ + if (!*args) + { + return false; + } + + float modSpeed = (float)atof(args); + + if (modSpeed > sWorld.getConfig(CONFIG_UINT32_GM_MAX_SPEED_FACTOR) || modSpeed < 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)) + { + return false; + } + + std::string chrNameLink = GetNameLink(chr); + + if (chr->IsTaxiFlying()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT, chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, modSpeed, chrNameLink.c_str()); + if (needReportToTarget(chr)) + { + ChatHandler(chr).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, GetNameLink().c_str(), modSpeed); + } + + chr->UpdateSpeed(MOVE_RUN_BACK, true, modSpeed); + + return true; +} + +// Edit Player Scale +bool ChatHandler::HandleModifyScaleCommand(char* args) +{ + if (!*args) + { + return false; + } + + float Scale = (float)atof(args); + if (Scale > 10.0f || Scale <= 0.0f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Unit* target = getSelectedUnit(); + if (target == NULL) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (target->GetTypeId() == TYPEID_PLAYER) + { + // check online security + if (HasLowerSecurity((Player*)target)) + { + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, GetNameLink((Player*)target).c_str()); + if (needReportToTarget((Player*)target)) + { + ChatHandler((Player*)target).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, GetNameLink().c_str(), Scale); + } + } + + target->SetObjectScale(Scale); + target->UpdateModelData(); + + return true; +} + +// Enable Player mount +bool ChatHandler::HandleModifyMountCommand(char* args) +{ + if (!*args) + { + return false; + } + + uint16 mId = 1147; + float speed = (float)15; + uint32 num = atoi(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) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr)) + { + 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 << 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 << chr->GetPackGUID(); + data << (uint32)0; + data << float(speed); + chr->SendMessageToSet(&data, true); + + return true; +} + +// Edit Player money +bool ChatHandler::HandleModifyMoneyCommand(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)) + { + return false; + } + + int32 addmoney = atoi(args); + + uint32 moneyuser = chr->GetMoney(); + + if (addmoney < 0) + { + int32 newmoney = int32(moneyuser) + addmoney; + + DETAIL_LOG(GetMangosString(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); + } + } + + DETAIL_LOG(GetMangosString(LANG_NEW_MONEY), moneyuser, addmoney, chr->GetMoney()); + + return true; +} + +bool ChatHandler::HandleModifyDrunkCommand(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; +} + +bool ChatHandler::HandleModifyRepCommand(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)) + { + return false; + } + + uint32 factionId; + if (!ExtractUint32KeyFromLink(&args, "Hfaction", factionId)) + { + return false; + } + + if (!factionId) + { + return false; + } + + int32 amount = 0; + if (!ExtractInt32(&args, amount)) + { + char* rankTxt = ExtractLiteralArg(&args); + if (!rankTxt) + { + return false; + } + + 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 = GetMangosString(ReputationRankStrIndex[r]); + if (rank.empty()) + { + continue; + } + + std::wstring wrank; + if (!Utf8toWStr(rank, wrank)) + { + continue; + } + + wstrToLower(wrank); + + if (wrank.substr(0, wrankStr.size()) == wrankStr) + { + int32 delta; + if (!ExtractOptInt32(&args, delta, 0) || (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; +} + +bool ChatHandler::HandleModifyGenderCommand(char* args) +{ + if (!*args) + { + return false; + } + + Player* player = getSelectedPlayer(); + + if (!player) + { + PSendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + PlayerInfo const* info = sObjectMgr.GetPlayerInfo(player->getRace(), player->getClass()); + if (!info) + { + return false; + } + + char* gender_str = 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->SetUInt16Value(PLAYER_BYTES_3, 0, uint16(gender) | (player->GetDrunkValue() & 0xFFFE)); + + // Change display ID + player->InitDisplayIds(); + + char const* gender_full = gender ? "female" : "male"; + + PSendSysMessage(LANG_YOU_CHANGE_GENDER, player->GetName(), gender_full); + + if (needReportToTarget(player)) + { + ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full, GetNameLink().c_str()); + } + + return true; +} + +bool ChatHandler::HandleModifyArenaCommand(char* args) +{ + if (!*args) + { + return false; + } + + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + int32 amount = (int32)atoi(args); + + target->ModifyArenaPoints(amount); + + PSendSysMessage(LANG_COMMAND_MODIFY_ARENA, GetNameLink(target).c_str(), target->GetArenaPoints()); + + return true; +} diff --git a/src/game/ChatCommands/PlayerHonorCommands.cpp b/src/game/ChatCommands/PlayerHonorCommands.cpp new file mode 100644 index 0000000000000..bfac4972da4b7 --- /dev/null +++ b/src/game/ChatCommands/PlayerHonorCommands.cpp @@ -0,0 +1,152 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" + + /********************************************************************** + CommandTable : honorCommandTable + /***********************************************************************/ + + +bool ChatHandler::HandleHonorAddCommand(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)) + { + return false; + } + + float amount = (float)atof(args); + target->RewardHonor(NULL, 1, amount); + return true; +} + +bool ChatHandler::HandleHonorAddKillCommand(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)) + { + return false; + } + + m_session->GetPlayer()->RewardHonor(target, 1); + return true; +} + +bool ChatHandler::HandleHonorUpdateCommand(char* /*args*/) +{ + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target)) + { + return false; + } + + target->UpdateHonorFields(); + return true; +} + +/********************************************************************** + CommandTable : modifyCommandTable +/***********************************************************************/ + +bool ChatHandler::HandleModifyHonorCommand(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)) + { + return false; + } + + int32 amount = (int32)atoi(args); + + target->ModifyHonorPoints(amount); + + PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, GetNameLink(target).c_str(), target->GetHonorPoints()); + + return true; +} + +/********************************************************************** + CommandTable : resetCommandTable +/***********************************************************************/ + +bool ChatHandler::HandleResetHonorCommand(char* args) +{ + Player* target; + if (!ExtractPlayerTarget(&args, &target)) + { + return false; + } + + target->SetHonorPoints(0); + target->SetUInt32Value(PLAYER_FIELD_KILLS, 0); + target->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0); + target->SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); + target->SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); + return true; +} + diff --git a/src/game/ChatCommands/PlayerLearnCommands.cpp b/src/game/ChatCommands/PlayerLearnCommands.cpp new file mode 100644 index 0000000000000..35a942910af49 --- /dev/null +++ b/src/game/ChatCommands/PlayerLearnCommands.cpp @@ -0,0 +1,1118 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "SpellMgr.h" + + /********************************************************************** + CommandTable : learnCommandTable + /***********************************************************************/ + +bool ChatHandler::HandleUnLearnCommand(char* args) +{ + if (!*args) + { + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r + uint32 spell_id = ExtractSpellIdFromLink(&args); + if (!spell_id) + { + return false; + } + + bool allRanks = ExtractLiteralArg(&args, "all") != NULL; + if (!allRanks && *args) // can be fail also at syntax error + { + return false; + } + + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (allRanks) + { + spell_id = sSpellMgr.GetFirstSpellInChain(spell_id); + } + + if (target->HasSpell(spell_id)) + { + target->removeSpell(spell_id, false, !allRanks); + } + else + { + SendSysMessage(LANG_FORGET_SPELL); + } + + return true; +} + +bool ChatHandler::HandleLearnAllCommand(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", + "12842", + "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", + "15053", + "12580", + "12475", + "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(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(char* /*args*/) +{ + HandleLearnAllMySpellsCommand((char*)""); + HandleLearnAllMyTalentsCommand((char*)""); + return true; +} + +bool ChatHandler::HandleLearnAllMySpellsCommand(char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + ChrClassesEntry const* clsEntry = sChrClassesStore.LookupEntry(player->getClass()); + if (!clsEntry) + { + return true; + } + uint32 family = clsEntry->spellfamily; + + for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); ++i) + { + SkillLineAbilityEntry const* entry = sSkillLineAbilityStore.LookupEntry(i); + if (!entry) + { + continue; + } + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(entry->spellId); + if (!spellInfo) + { + continue; + } + + // skip server-side/triggered spells + if (spellInfo->spellLevel == 0) + { + continue; + } + + // skip wrong class/race skills + if (!player->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 = sSpellMgr.GetFirstSpellInChain(spellInfo->Id); + if (GetTalentSpellCost(first_rank) > 0) + { + continue; + } + + // skip broken spells + if (!SpellMgr::IsSpellValid(spellInfo, player, false)) + { + continue; + } + + player->learnSpell(spellInfo->Id, false); + } + + SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS); + return true; +} + +bool ChatHandler::HandleLearnAllMyTalentsCommand(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 (int 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, player, false)) + { + continue; + } + + // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) + player->learnSpellHighRank(spellid); + } + + SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); + return true; +} + +bool ChatHandler::HandleLearnAllLangCommand(char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + + // skipping UNIVERSAL language (0) + for (int i = 1; i < LANGUAGES_COUNT; ++i) + { + player->learnSpell(lang_description[i].spell_id, false); + } + + SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG); + return true; +} + +bool ChatHandler::HandleLearnAllDefaultCommand(char* args) +{ + Player* target; + if (!ExtractPlayerTarget(&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(char* args) +{ + Player* player = m_session->GetPlayer(); + 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(&args); + if (!spell || !sSpellStore.LookupEntry(spell)) + { + return false; + } + + bool allRanks = ExtractLiteralArg(&args, "all") != NULL; + if (!allRanks && *args) // can be fail also at syntax error + { + return false; + } + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, player)) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spell); + SetSentErrorMessage(true); + return false; + } + + if (!allRanks && targetPlayer->HasSpell(spell)) + { + if (targetPlayer == player) + { + SendSysMessage(LANG_YOU_KNOWN_SPELL); + } + else + { + PSendSysMessage(LANG_TARGET_KNOWN_SPELL, targetPlayer->GetName()); + } + SetSentErrorMessage(true); + return false; + } + + if (allRanks) + { + targetPlayer->learnSpellHighRank(spell); + } + else + { + targetPlayer->learnSpell(spell, false); + } + + 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(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) + { + HandleLearnSkillRecipesHelper(m_session->GetPlayer(), skillInfo->id); + } + } + + SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT); + return true; +} + +bool ChatHandler::HandleLearnAllRecipesCommand(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) + { + 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, maxLevel, maxLevel); + PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str()); + return true; +} diff --git a/src/game/ChatCommands/PlayerMiscCommands.cpp b/src/game/ChatCommands/PlayerMiscCommands.cpp new file mode 100644 index 0000000000000..a83cd8dc30e53 --- /dev/null +++ b/src/game/ChatCommands/PlayerMiscCommands.cpp @@ -0,0 +1,247 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "World.h" + + /********************************************************************** + CommandTable : commandTable + /***********************************************************************/ + +bool ChatHandler::HandleBankCommand(char* /*args*/) +{ + m_session->SendShowBank(m_session->GetPlayer()->GetObjectGuid()); + + return true; +} + +bool ChatHandler::HandleStableCommand(char* /*args*/) +{ + m_session->SendStablePet(m_session->GetPlayer()->GetObjectGuid()); + + return true; +} + +/********************************************************************** + CommandTable : resetCommandTable +/***********************************************************************/ + +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->SetShapeshiftForm(FORM_NONE); + } + + player->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); + player->SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f); + + player->setFactionForRace(player->getRace()); + + player->SetByteValue(UNIT_FIELD_BYTES_0, 3, powertype); + + // reset only if player not in some form; + if (player->GetShapeshiftForm() == FORM_NONE) + { + player->InitDisplayIds(); + } + + player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_UNK5); + + player->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + + //-1 is default value + player->SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, -1); + + // player->SetUInt32Value(PLAYER_FIELD_BYTES, 0xEEE00000 ); + return true; +} + +bool ChatHandler::HandleResetLevelCommand(char* args) +{ + Player* target; + if (!ExtractPlayerTarget(&args, &target)) + { + return false; + } + + if (!HandleResetStatsOrLevelHelper(target)) + { + return false; + } + + // set starting level + uint32 start_level = sWorld.getConfig(CONFIG_UINT32_START_PLAYER_LEVEL); + + target->SetLevel(start_level); + target->InitStatsForLevel(true); + target->InitTaxiNodesForLevel(); + target->InitTalentForLevel(); + target->SetUInt32Value(PLAYER_XP, 0); + + // reset level for pet + if (Pet* pet = target->GetPet()) + { + pet->SynchronizeLevelWithOwner(); + } + + return true; +} + +bool ChatHandler::HandleResetStatsCommand(char* args) +{ + Player* target; + if (!ExtractPlayerTarget(&args, &target)) + { + return false; + } + + if (!HandleResetStatsOrLevelHelper(target)) + { + return false; + } + + target->InitStatsForLevel(true); + target->InitTaxiNodesForLevel(); + target->InitTalentForLevel(); + + return true; +} + +bool ChatHandler::HandleResetSpellsCommand(char* args) +{ + Player* target; + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) + { + return false; + } + + if (target) + { + target->resetSpells(); + + 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), target_guid.GetCounter()); + PSendSysMessage(LANG_RESET_SPELLS_OFFLINE, target_name.c_str()); + } + + return true; +} + +bool ChatHandler::HandleResetTalentsCommand(char* args) +{ + Player* target; + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) + { + return false; + } + + if (target) + { + target->resetTalents(true); + + ChatHandler(target).SendSysMessage(LANG_RESET_TALENTS); + if (!m_session || m_session->GetPlayer() != target) + { + PSendSysMessage(LANG_RESET_TALENTS_ONLINE, GetNameLink(target).c_str()); + } + return true; + } + else if (target_guid) + { + uint32 at_flags = AT_LOGIN_RESET_TALENTS; + CharacterDatabase.PExecute("UPDATE `characters` SET `at_login` = `at_login` | '%u' WHERE `guid` = '%u'", at_flags, target_guid.GetCounter()); + 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(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 = AT_LOGIN_RESET_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); + sObjectAccessor.DoForAllPlayers([&atLogin](Player* plr) { plr->SetAtLoginFlag(atLogin); }); + return true; +} diff --git a/src/game/ChatCommands/PlayerTitleCommands.cpp b/src/game/ChatCommands/PlayerTitleCommands.cpp new file mode 100644 index 0000000000000..98987ab214c4e --- /dev/null +++ b/src/game/ChatCommands/PlayerTitleCommands.cpp @@ -0,0 +1,372 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "World.h" + + +bool ChatHandler::HandleLookupTitleCommand(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) ? GetMangosString(LANG_KNOWN) : ""; + + char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index + ? GetMangosString(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(char* args) +{ + // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r + uint32 id; + if (!ExtractUint32KeyFromLink(&args, "Htitle", id)) + { + return false; + } + + 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)) + { + 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(char* args) +{ + // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r + uint32 id; + if (!ExtractUint32KeyFromLink(&args, "Htitle", id)) + { + return false; + } + + 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)) + { + 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(char* args) +{ + if (!*args) + { + return false; + } + + uint64 titles = 0; + + sscanf(args, UI64FMTD, &titles); + + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target)) + { + 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 nonexistent 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(char* args) +{ + Player* target; + if (!ExtractPlayerTarget(&args, &target)) + { + return false; + } + + LocaleConstant loc = GetSessionDbcLocale(); + char const* targetName = target->GetName(); + char const* knownStr = GetMangosString(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 + ? GetMangosString(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(char* args) +{ + // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r + uint32 id; + if (!ExtractUint32KeyFromLink(&args, "Htitle", id)) + { + return false; + } + + 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)) + { + 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/game/ChatCommands/PoolCommands.cpp b/src/game/ChatCommands/PoolCommands.cpp new file mode 100644 index 0000000000000..35b256c330fb4 --- /dev/null +++ b/src/game/ChatCommands/PoolCommands.cpp @@ -0,0 +1,289 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" + + +void ChatHandler::ShowPoolListHelper(uint16 pool_id) +{ + PoolTemplateData const& pool_template = sPoolMgr.GetPoolTemplate(pool_id); + if (m_session) + PSendSysMessage(LANG_POOL_ENTRY_LIST_CHAT, + pool_id, pool_id, pool_template.description.c_str(), pool_template.AutoSpawn ? 1 : 0, pool_template.MaxLimit, + sPoolMgr.GetPoolCreatures(pool_id).size(), sPoolMgr.GetPoolGameObjects(pool_id).size(), sPoolMgr.GetPoolPools(pool_id).size()); + else + PSendSysMessage(LANG_POOL_ENTRY_LIST_CONSOLE, + pool_id, pool_template.description.c_str(), pool_template.AutoSpawn ? 1 : 0, pool_template.MaxLimit, + sPoolMgr.GetPoolCreatures(pool_id).size(), sPoolMgr.GetPoolGameObjects(pool_id).size(), sPoolMgr.GetPoolPools(pool_id).size()); +} + +bool ChatHandler::HandlePoolListCommand(char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + + MapPersistentState* mapState = player->GetMap()->GetPersistentState(); + + if (!mapState->GetMapEntry()->Instanceable()) + { + PSendSysMessage(LANG_POOL_LIST_NON_INSTANCE, mapState->GetMapEntry()->name[GetSessionDbcLocale()], mapState->GetMapId()); + SetSentErrorMessage(false); + return false; + } + + uint32 counter = 0; + + // spawn pools for expected map or for not initialized shared pools state for non-instanceable maps + for (uint16 pool_id = 0; pool_id < sPoolMgr.GetMaxPoolId(); ++pool_id) + { + if (sPoolMgr.GetPoolTemplate(pool_id).CanBeSpawnedAtMap(mapState->GetMapEntry())) + { + ShowPoolListHelper(pool_id); + ++counter; + } + } + + if (counter == 0) + { + PSendSysMessage(LANG_NO_POOL_FOR_MAP, mapState->GetMapEntry()->name[GetSessionDbcLocale()], mapState->GetMapId()); + } + + return true; +} + +bool ChatHandler::HandlePoolSpawnsCommand(char* args) +{ + Player* player = m_session->GetPlayer(); + + MapPersistentState* mapState = player->GetMap()->GetPersistentState(); + + // shared continent pools data expected too big for show + uint32 pool_id = 0; + if (!ExtractUint32KeyFromLink(&args, "Hpool", pool_id) && !mapState->GetMapEntry()->Instanceable()) + { + PSendSysMessage(LANG_POOL_SPAWNS_NON_INSTANCE, mapState->GetMapEntry()->name[GetSessionDbcLocale()], mapState->GetMapId()); + SetSentErrorMessage(false); + return false; + } + + SpawnedPoolData const& spawns = mapState->GetSpawnedPoolData(); + + SpawnedPoolObjects const& crSpawns = spawns.GetSpawnedCreatures(); + for (SpawnedPoolObjects::const_iterator itr = crSpawns.begin(); itr != crSpawns.end(); ++itr) + if (!pool_id || pool_id == sPoolMgr.IsPartOfAPool(*itr)) + if (CreatureData const* data = sObjectMgr.GetCreatureData(*itr)) + if (CreatureInfo const* info = ObjectMgr::GetCreatureTemplate(data->id)) + PSendSysMessage(LANG_CREATURE_LIST_CHAT, *itr, PrepareStringNpcOrGoSpawnInformation(*itr).c_str(), + *itr, info->Name, data->posX, data->posY, data->posZ, data->mapid); + + SpawnedPoolObjects const& goSpawns = spawns.GetSpawnedGameobjects(); + for (SpawnedPoolObjects::const_iterator itr = goSpawns.begin(); itr != goSpawns.end(); ++itr) + if (!pool_id || pool_id == sPoolMgr.IsPartOfAPool(*itr)) + if (GameObjectData const* data = sObjectMgr.GetGOData(*itr)) + if (GameObjectInfo const* info = ObjectMgr::GetGameObjectInfo(data->id)) + PSendSysMessage(LANG_GO_LIST_CHAT, *itr, PrepareStringNpcOrGoSpawnInformation(*itr).c_str(), + *itr, info->name, data->posX, data->posY, data->posZ, data->mapid); + + return true; +} + +bool ChatHandler::HandlePoolInfoCommand(char* args) +{ + // id or [name] Shift-click form |color|Hpool:id|h[name]|h|r + uint32 pool_id; + if (!ExtractUint32KeyFromLink(&args, "Hpool", pool_id)) + { + return false; + } + + if (pool_id > sPoolMgr.GetMaxPoolId()) + { + PSendSysMessage(LANG_POOL_ENTRY_LOWER_MAX_POOL, pool_id, sPoolMgr.GetMaxPoolId()); + return true; + } + + Player* player = m_session ? m_session->GetPlayer() : NULL; + + MapPersistentState* mapState = player ? player->GetMap()->GetPersistentState() : NULL; + SpawnedPoolData const* spawns = mapState ? &mapState->GetSpawnedPoolData() : NULL; + + std::string active_str = GetMangosString(LANG_ACTIVE); + + PoolTemplateData const& pool_template = sPoolMgr.GetPoolTemplate(pool_id); + uint32 mother_pool_id = sPoolMgr.IsPartOfAPool(pool_id); + if (!mother_pool_id) + { + PSendSysMessage(LANG_POOL_INFO_HEADER, pool_id, pool_template.AutoSpawn, pool_template.MaxLimit); + } + else + { + PoolTemplateData const& mother_template = sPoolMgr.GetPoolTemplate(mother_pool_id); + if (m_session) + PSendSysMessage(LANG_POOL_INFO_HEADER_CHAT, pool_id, mother_pool_id, mother_pool_id, mother_template.description.c_str(), + pool_template.AutoSpawn, pool_template.MaxLimit); + else + PSendSysMessage(LANG_POOL_INFO_HEADER_CONSOLE, pool_id, mother_pool_id, mother_template.description.c_str(), + pool_template.AutoSpawn, pool_template.MaxLimit); + } + + PoolGroup const& poolCreatures = sPoolMgr.GetPoolCreatures(pool_id); + SpawnedPoolObjects const* crSpawns = spawns ? &spawns->GetSpawnedCreatures() : NULL; + + PoolObjectList const& poolCreaturesEx = poolCreatures.GetExplicitlyChanced(); + if (!poolCreaturesEx.empty()) + { + SendSysMessage(LANG_POOL_CHANCE_CREATURE_LIST_HEADER); + for (PoolObjectList::const_iterator itr = poolCreaturesEx.begin(); itr != poolCreaturesEx.end(); ++itr) + { + if (CreatureData const* data = sObjectMgr.GetCreatureData(itr->guid)) + { + if (CreatureInfo const* info = ObjectMgr::GetCreatureTemplate(data->id)) + { + char const* active = crSpawns && crSpawns->find(itr->guid) != crSpawns->end() ? active_str.c_str() : ""; + if (m_session) + PSendSysMessage(LANG_POOL_CHANCE_CREATURE_LIST_CHAT, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), + itr->guid, info->Name, data->posX, data->posY, data->posZ, data->mapid, itr->chance, active); + else + PSendSysMessage(LANG_POOL_CHANCE_CREATURE_LIST_CONSOLE, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), + info->Name, data->posX, data->posY, data->posZ, data->mapid, itr->chance, active); + } + } + } + } + + PoolObjectList const& poolCreaturesEq = poolCreatures.GetEqualChanced(); + if (!poolCreaturesEq.empty()) + { + SendSysMessage(LANG_POOL_CREATURE_LIST_HEADER); + for (PoolObjectList::const_iterator itr = poolCreaturesEq.begin(); itr != poolCreaturesEq.end(); ++itr) + { + if (CreatureData const* data = sObjectMgr.GetCreatureData(itr->guid)) + { + if (CreatureInfo const* info = ObjectMgr::GetCreatureTemplate(data->id)) + { + char const* active = crSpawns && crSpawns->find(itr->guid) != crSpawns->end() ? active_str.c_str() : ""; + if (m_session) + PSendSysMessage(LANG_POOL_CREATURE_LIST_CHAT, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), + itr->guid, info->Name, data->posX, data->posY, data->posZ, data->mapid, active); + else + PSendSysMessage(LANG_POOL_CREATURE_LIST_CONSOLE, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), + info->Name, data->posX, data->posY, data->posZ, data->mapid, active); + } + } + } + } + + PoolGroup const& poolGameObjects = sPoolMgr.GetPoolGameObjects(pool_id); + SpawnedPoolObjects const* goSpawns = spawns ? &spawns->GetSpawnedGameobjects() : NULL; + + PoolObjectList const& poolGameObjectsEx = poolGameObjects.GetExplicitlyChanced(); + if (!poolGameObjectsEx.empty()) + { + SendSysMessage(LANG_POOL_CHANCE_GO_LIST_HEADER); + for (PoolObjectList::const_iterator itr = poolGameObjectsEx.begin(); itr != poolGameObjectsEx.end(); ++itr) + { + if (GameObjectData const* data = sObjectMgr.GetGOData(itr->guid)) + { + if (GameObjectInfo const* info = ObjectMgr::GetGameObjectInfo(data->id)) + { + char const* active = goSpawns && goSpawns->find(itr->guid) != goSpawns->end() ? active_str.c_str() : ""; + if (m_session) + PSendSysMessage(LANG_POOL_CHANCE_GO_LIST_CHAT, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), + itr->guid, info->name, data->posX, data->posY, data->posZ, data->mapid, itr->chance, active); + else + PSendSysMessage(LANG_POOL_CHANCE_GO_LIST_CONSOLE, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), + info->name, data->posX, data->posY, data->posZ, data->mapid, itr->chance, active); + } + } + } + } + + PoolObjectList const& poolGameObjectsEq = poolGameObjects.GetEqualChanced(); + if (!poolGameObjectsEq.empty()) + { + SendSysMessage(LANG_POOL_GO_LIST_HEADER); + for (PoolObjectList::const_iterator itr = poolGameObjectsEq.begin(); itr != poolGameObjectsEq.end(); ++itr) + { + if (GameObjectData const* data = sObjectMgr.GetGOData(itr->guid)) + { + if (GameObjectInfo const* info = ObjectMgr::GetGameObjectInfo(data->id)) + { + char const* active = goSpawns && goSpawns->find(itr->guid) != goSpawns->end() ? active_str.c_str() : ""; + if (m_session) + PSendSysMessage(LANG_POOL_GO_LIST_CHAT, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), + itr->guid, info->name, data->posX, data->posY, data->posZ, data->mapid, active); + else + PSendSysMessage(LANG_POOL_GO_LIST_CONSOLE, itr->guid, PrepareStringNpcOrGoSpawnInformation(itr->guid).c_str(), + info->name, data->posX, data->posY, data->posZ, data->mapid, active); + } + } + } + } + + PoolGroup const& poolPools = sPoolMgr.GetPoolPools(pool_id); + SpawnedPoolPools const* poolSpawns = spawns ? &spawns->GetSpawnedPools() : NULL; + + PoolObjectList const& poolPoolsEx = poolPools.GetExplicitlyChanced(); + if (!poolPoolsEx.empty()) + { + SendSysMessage(LANG_POOL_CHANCE_POOL_LIST_HEADER); + for (PoolObjectList::const_iterator itr = poolPoolsEx.begin(); itr != poolPoolsEx.end(); ++itr) + { + PoolTemplateData const& itr_template = sPoolMgr.GetPoolTemplate(itr->guid); + char const* active = poolSpawns && poolSpawns->find(itr->guid) != poolSpawns->end() ? active_str.c_str() : ""; + if (m_session) + PSendSysMessage(LANG_POOL_CHANCE_POOL_LIST_CHAT, itr->guid, + itr->guid, itr_template.description.c_str(), itr_template.AutoSpawn ? 1 : 0, itr_template.MaxLimit, + sPoolMgr.GetPoolCreatures(itr->guid).size(), sPoolMgr.GetPoolGameObjects(itr->guid).size(), sPoolMgr.GetPoolPools(itr->guid).size(), + itr->chance, active); + else + PSendSysMessage(LANG_POOL_CHANCE_POOL_LIST_CONSOLE, itr->guid, + itr_template.description.c_str(), itr_template.AutoSpawn ? 1 : 0, itr_template.MaxLimit, + sPoolMgr.GetPoolCreatures(itr->guid).size(), sPoolMgr.GetPoolGameObjects(itr->guid).size(), sPoolMgr.GetPoolPools(itr->guid).size(), + itr->chance, active); + } + } + + PoolObjectList const& poolPoolsEq = poolPools.GetEqualChanced(); + if (!poolPoolsEq.empty()) + { + SendSysMessage(LANG_POOL_POOL_LIST_HEADER); + for (PoolObjectList::const_iterator itr = poolPoolsEq.begin(); itr != poolPoolsEq.end(); ++itr) + { + PoolTemplateData const& itr_template = sPoolMgr.GetPoolTemplate(itr->guid); + char const* active = poolSpawns && poolSpawns->find(itr->guid) != poolSpawns->end() ? active_str.c_str() : ""; + if (m_session) + PSendSysMessage(LANG_POOL_POOL_LIST_CHAT, itr->guid, + itr->guid, itr_template.description.c_str(), itr_template.AutoSpawn ? 1 : 0, itr_template.MaxLimit, + sPoolMgr.GetPoolCreatures(itr->guid).size(), sPoolMgr.GetPoolGameObjects(itr->guid).size(), sPoolMgr.GetPoolPools(itr->guid).size(), + active); + else + PSendSysMessage(LANG_POOL_POOL_LIST_CONSOLE, itr->guid, + itr_template.description.c_str(), itr_template.AutoSpawn ? 1 : 0, itr_template.MaxLimit, + sPoolMgr.GetPoolCreatures(itr->guid).size(), sPoolMgr.GetPoolGameObjects(itr->guid).size(), sPoolMgr.GetPoolPools(itr->guid).size(), + active); + } + } + return true; +} diff --git a/src/game/ChatCommands/QuestCommands.cpp b/src/game/ChatCommands/QuestCommands.cpp new file mode 100644 index 0000000000000..801453dc1a0d7 --- /dev/null +++ b/src/game/ChatCommands/QuestCommands.cpp @@ -0,0 +1,237 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "ObjectMgr.h" +#include "SQLStorages.h" + +bool ChatHandler::HandleQuestAddCommand(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 + uint32 entry; + if (!ExtractUint32KeyFromLink(&args, "Hquest", entry)) + { + return false; + } + + Quest const* pQuest = sObjectMgr.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.GetMaxEntry(); ++id) + { + ItemPrototype const* pProto = sItemStorage.LookupEntry(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::HandleQuestRemoveCommand(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 + uint32 entry; + if (!ExtractUint32KeyFromLink(&args, "Hquest", entry)) + { + return false; + } + + Quest const* pQuest = sObjectMgr.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::HandleQuestCompleteCommand(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 + uint32 entry; + if (!ExtractUint32KeyFromLink(&args, "Hquest", entry)) + { + return false; + } + + Quest const* pQuest = sObjectMgr.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) + { + int32 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, ObjectGuid(), spell_id); + } + } + else if (creature > 0) + { + if (CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(creature)) + for (uint16 z = 0; z < creaturecount; ++z) + { + player->KilledMonster(cInfo, ObjectGuid()); + } + } + else if (creature < 0) + { + for (uint16 z = 0; z < creaturecount; ++z) + { + player->CastedCreatureOrGO(-creature, ObjectGuid(), 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 money + int32 ReqOrRewMoney = pQuest->GetRewOrReqMoney(); + if (ReqOrRewMoney < 0) + { + player->ModifyMoney(-ReqOrRewMoney); + } + + player->CompleteQuest(entry, QUEST_STATUS_FORCE_COMPLETE); + return true; +} diff --git a/src/game/ChatCommands/RACommands.cpp b/src/game/ChatCommands/RACommands.cpp new file mode 100644 index 0000000000000..91e128420d1ef --- /dev/null +++ b/src/game/ChatCommands/RACommands.cpp @@ -0,0 +1,38 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" + + /********************************************************************** + CommandTable : commandTable + /***********************************************************************/ + +/// Close RA connection +bool ChatHandler::HandleQuitCommand(char* /*args*/) +{ + // processed in RASocket + SendSysMessage(LANG_QUIT_WRONG_USE_ERROR); + return true; +} \ No newline at end of file diff --git a/src/game/ChatCommands/ReloadCommands.cpp b/src/game/ChatCommands/ReloadCommands.cpp new file mode 100644 index 0000000000000..2501111b356f7 --- /dev/null +++ b/src/game/ChatCommands/ReloadCommands.cpp @@ -0,0 +1,938 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "SpellMgr.h" +#include "DisableMgr.h" +#include "World.h" +#include "MapManager.h" +#include "CreatureEventAIMgr.h" +#include "BattleGroundMgr.h" +#include "SkillExtraItems.h" +#include "SkillDiscovery.h" +#include "ItemEnchantmentMgr.h" + + /********************************************************************** + CommandTable : commandTable + /***********************************************************************/ +bool ChatHandler::HandleReloadSpellLinkedCommand(char* /*arg*/) +{ + sLog.outString("Re-Loading spell linked table..."); + sSpellMgr.LoadSpellLinked(); + SendGlobalSysMessage("DB table `spell_linked` reloaded.", SEC_MODERATOR); + return true; +} + + + +/********************************************************************** + CommandTable : reloadCommandTable +/***********************************************************************/ + +bool ChatHandler::HandleReloadAllSpellCommand(char* /*args*/) +{ + HandleReloadSkillDiscoveryTemplateCommand((char*)"a"); + HandleReloadSkillExtraItemTemplateCommand((char*)"a"); + HandleReloadSpellAffectCommand((char*)"a"); + HandleReloadSpellAreaCommand((char*)"a"); + HandleReloadSpellChainCommand((char*)"a"); + HandleReloadSpellElixirCommand((char*)"a"); + HandleReloadSpellLearnSpellCommand((char*)"a"); + HandleReloadSpellProcEventCommand((char*)"a"); + HandleReloadSpellBonusesCommand((char*)"a"); + HandleReloadSpellProcItemEnchantCommand((char*)"a"); + HandleReloadSpellScriptTargetCommand((char*)"a"); + HandleReloadSpellTargetPositionCommand((char*)"a"); + HandleReloadSpellThreatsCommand((char*)"a"); + HandleReloadSpellPetAurasCommand((char*)"a"); + HandleReloadSpellLinkedCommand((char*)"a"); + return true; +} + +// reload commands +bool ChatHandler::HandleReloadAllCommand(char* /*args*/) +{ + HandleReloadSkillFishingBaseLevelCommand((char*)""); + + HandleReloadAllAreaCommand((char*)""); + HandleReloadAutoBroadcastCommand((char*)""); + HandleReloadAllEventAICommand((char*)""); + HandleReloadAllLootCommand((char*)""); + HandleReloadAllNpcCommand((char*)""); + HandleReloadAllQuestCommand((char*)""); + HandleReloadAllSpellCommand((char*)""); + HandleReloadAllItemCommand((char*)""); + HandleReloadAllGossipsCommand((char*)""); + HandleReloadAllLocalesCommand((char*)""); + + HandleReloadMailLevelRewardCommand((char*)""); + HandleReloadCommandCommand((char*)""); + HandleReloadReservedNameCommand((char*)""); + HandleReloadMangosStringCommand((char*)""); + HandleReloadGameTeleCommand((char*)""); + HandleReloadBattleEventCommand((char*)""); + return true; +} + +bool ChatHandler::HandleReloadAllAreaCommand(char* /*args*/) +{ + // HandleReloadQuestAreaTriggersCommand((char*)""); -- reloaded in HandleReloadAllQuestCommand + HandleReloadAreaTriggerTeleportCommand((char*)""); + HandleReloadAreaTriggerTavernCommand((char*)""); + HandleReloadGameGraveyardZoneCommand((char*)""); + return true; +} + +bool ChatHandler::HandleReloadAllLootCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Loot Tables..."); + LoadLootTables(); + SendGlobalSysMessage("DB tables `*_loot_template` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadAllNpcCommand(char* args) +{ + HandleReloadNpcTrainerCommand((char*)"a"); + HandleReloadNpcVendorCommand((char*)"a"); + HandleReloadPointsOfInterestCommand((char*)"a"); + return true; +} + +bool ChatHandler::HandleReloadAllQuestCommand(char* /*args*/) +{ + HandleReloadQuestAreaTriggersCommand((char*)"a"); + HandleReloadQuestTemplateCommand((char*)"a"); + + sLog.outString("Re-Loading Quests Relations..."); + sObjectMgr.LoadQuestRelations(); + SendGlobalSysMessage("DB table `quest_relations` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadAllScriptsCommand(char* /*args*/) +{ + if (sScriptMgr.IsScriptScheduled()) + { + PSendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + sLog.outString("Re-Loading Scripts..."); + HandleReloadDBScriptsOnCreatureDeathCommand((char*)"a"); + HandleReloadDBScriptsOnGoUseCommand((char*)"a"); + HandleReloadDBScriptsOnGossipCommand((char*)"a"); + HandleReloadDBScriptsOnEventCommand((char*)"a"); + HandleReloadDBScriptsOnQuestEndCommand((char*)"a"); + HandleReloadDBScriptsOnQuestStartCommand((char*)"a"); + HandleReloadDBScriptsOnSpellCommand((char*)"a"); + SendGlobalSysMessage("DB tables `*_scripts` reloaded.", SEC_MODERATOR); + HandleReloadDbScriptStringCommand((char*)"a"); + return true; +} + +bool ChatHandler::HandleReloadAllEventAICommand(char* /*args*/) +{ + HandleReloadEventAITextsCommand((char*)"a"); + HandleReloadEventAISummonsCommand((char*)"a"); + HandleReloadEventAIScriptsCommand((char*)"a"); + return true; +} + +bool ChatHandler::HandleReloadAllGossipsCommand(char* args) +{ + if (*args != 'a') // already reload from all_scripts + { + HandleReloadDBScriptsOnGossipCommand((char*)"a"); + } + HandleReloadGossipMenuCommand((char*)"a"); + HandleReloadPointsOfInterestCommand((char*)"a"); + return true; +} + +bool ChatHandler::HandleReloadAllItemCommand(char* /*args*/) +{ + HandleReloadPageTextsCommand((char*)"a"); + HandleReloadItemEnchantementsCommand((char*)"a"); + HandleReloadItemRequiredTragetCommand((char*)"a"); + return true; +} + +bool ChatHandler::HandleReloadAllLocalesCommand(char* /*args*/) +{ + HandleReloadLocalesCreatureCommand((char*)"a"); + HandleReloadLocalesGameobjectCommand((char*)"a"); + HandleReloadLocalesGossipMenuOptionCommand((char*)"a"); + HandleReloadLocalesItemCommand((char*)"a"); + HandleReloadLocalesNpcTextCommand((char*)"a"); + HandleReloadLocalesPageTextCommand((char*)"a"); + HandleReloadLocalesPointsOfInterestCommand((char*)"a"); + HandleReloadLocalesQuestCommand((char*)"a"); + return true; +} + +bool ChatHandler::HandleReloadConfigCommand(char* /*args*/) +{ + sLog.outString("Re-Loading config settings..."); + sWorld.LoadConfigSettings(true); + sMapMgr.InitializeVisibilityDistanceInfo(); + SendGlobalSysMessage("World config settings reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadAreaTriggerTavernCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Tavern Area Triggers..."); + sObjectMgr.LoadTavernAreaTriggers(); + SendGlobalSysMessage("DB table `areatrigger_tavern` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadAreaTriggerTeleportCommand(char* /*args*/) +{ + sLog.outString("Re-Loading AreaTrigger teleport definitions..."); + sObjectMgr.LoadAreaTriggerTeleports(); + SendGlobalSysMessage("DB table `areatrigger_teleport` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadAutoBroadcastCommand(char* /*args*/) +{ + sLog.outString("Re-Loading broadcast strings..."); + sWorld.LoadBroadcastStrings(); + SendGlobalSysMessage("Broadcast strings reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadCommandCommand(char* /*args*/) +{ + load_command_table = true; + SendGlobalSysMessage("DB table `command` will be reloaded at next chat command use.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadCreatureQuestRelationsCommand(char* /*args*/) +{ + sLog.outString("Loading creature quest givers..."); + sObjectMgr.LoadCreatureQuestRelations(); + SendGlobalSysMessage("DB table `quest_relations` (creature quest givers) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadCreatureQuestInvRelationsCommand(char* /*args*/) +{ + sLog.outString("Loading creature quest takers..."); + sObjectMgr.LoadCreatureInvolvedRelations(); + SendGlobalSysMessage("DB table `quest_relations` (creature quest takers) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadConditionsCommand(char* /*args*/) +{ + sLog.outString("Re-Loading `conditions`... "); + sObjectMgr.LoadConditions(); + SendGlobalSysMessage("DB table `conditions` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadCreaturesStatsCommand(char* /*args*/) +{ + sLog.outString("Re-Loading stats data..."); + sObjectMgr.LoadCreatureClassLvlStats(); + SendGlobalSysMessage("DB table `creature_template_classlevelstats` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadGossipMenuCommand(char* /*args*/) +{ + sObjectMgr.LoadGossipMenus(); + SendGlobalSysMessage("DB tables `gossip_menu` and `gossip_menu_option` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadGOQuestRelationsCommand(char* /*args*/) +{ + sLog.outString("Loading gameobject quest givers..."); + sObjectMgr.LoadGameobjectQuestRelations(); + SendGlobalSysMessage("DB table `quest_relations` (gameobject quest givers) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadGOQuestInvRelationsCommand(char* /*args*/) +{ + sLog.outString("Loading gameobject quest takers..."); + sObjectMgr.LoadGameobjectInvolvedRelations(); + SendGlobalSysMessage("DB table `quest_relations` (gameobject quest takers) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadQuestAreaTriggersCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Quest Area Triggers..."); + sObjectMgr.LoadQuestAreaTriggers(); + SendGlobalSysMessage("DB table `quest_relations` (quest area triggers) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadQuestTemplateCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Quest Templates..."); + sObjectMgr.LoadQuests(); + SendGlobalSysMessage("DB table `quest_template` (quest definitions) reloaded.", SEC_MODERATOR); + + /// dependent also from `gameobject` but this table not reloaded anyway + sLog.outString("Re-Loading GameObjects for quests..."); + sObjectMgr.LoadGameObjectForQuests(); + SendGlobalSysMessage("Data GameObjects for quests reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesCreatureCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Loot Tables... (`creature_loot_template`)"); + LoadLootTemplates_Creature(); + LootTemplates_Creature.CheckLootRefs(); + SendGlobalSysMessage("DB table `creature_loot_template` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesDisenchantCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Loot Tables... (`disenchant_loot_template`)"); + LoadLootTemplates_Disenchant(); + LootTemplates_Disenchant.CheckLootRefs(); + SendGlobalSysMessage("DB table `disenchant_loot_template` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesFishingCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Loot Tables... (`fishing_loot_template`)"); + LoadLootTemplates_Fishing(); + LootTemplates_Fishing.CheckLootRefs(); + SendGlobalSysMessage("DB table `fishing_loot_template` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesGameobjectCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Loot Tables... (`gameobject_loot_template`)"); + LoadLootTemplates_Gameobject(); + LootTemplates_Gameobject.CheckLootRefs(); + SendGlobalSysMessage("DB table `gameobject_loot_template` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesItemCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Loot Tables... (`item_loot_template`)"); + LoadLootTemplates_Item(); + LootTemplates_Item.CheckLootRefs(); + SendGlobalSysMessage("DB table `item_loot_template` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesPickpocketingCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Loot Tables... (`pickpocketing_loot_template`)"); + LoadLootTemplates_Pickpocketing(); + LootTemplates_Pickpocketing.CheckLootRefs(); + SendGlobalSysMessage("DB table `pickpocketing_loot_template` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesProspectingCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Loot Tables... (`prospecting_loot_template`)"); + LoadLootTemplates_Prospecting(); + LootTemplates_Prospecting.CheckLootRefs(); + SendGlobalSysMessage("DB table `prospecting_loot_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesMailCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Loot Tables... (`mail_loot_template`)"); + LoadLootTemplates_Mail(); + LootTemplates_Mail.CheckLootRefs(); + SendGlobalSysMessage("DB table `mail_loot_template` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesReferenceCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Loot Tables... (`reference_loot_template`)"); + LoadLootTemplates_Reference(); + SendGlobalSysMessage("DB table `reference_loot_template` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesSkinningCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Loot Tables... (`skinning_loot_template`)"); + LoadLootTemplates_Skinning(); + LootTemplates_Skinning.CheckLootRefs(); + SendGlobalSysMessage("DB table `skinning_loot_template` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadMangosStringCommand(char* /*args*/) +{ + sLog.outString("Re-Loading mangos_string Table!"); + sObjectMgr.LoadMangosStrings(); + SendGlobalSysMessage("DB table `mangos_string` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadNpcTextCommand(char* /*args*/) +{ + sLog.outString("Re-Loading `npc_text` Table!"); + sObjectMgr.LoadGossipText(); + SendGlobalSysMessage("DB table `npc_text` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadNpcTrainerCommand(char* /*args*/) +{ + sLog.outString("Re-Loading `npc_trainer_template` Table!"); + sObjectMgr.LoadTrainerTemplates(); + SendGlobalSysMessage("DB table `npc_trainer_template` reloaded.", SEC_MODERATOR); + + sLog.outString("Re-Loading `npc_trainer` Table!"); + sObjectMgr.LoadTrainers(); + SendGlobalSysMessage("DB table `npc_trainer` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadNpcVendorCommand(char* /*args*/) +{ + // not safe reload vendor template tables independent... + sLog.outString("Re-Loading `npc_vendor_template` Table!"); + sObjectMgr.LoadVendorTemplates(); + SendGlobalSysMessage("DB table `npc_vendor_template` reloaded.", SEC_MODERATOR); + + sLog.outString("Re-Loading `npc_vendor` Table!"); + sObjectMgr.LoadVendors(); + SendGlobalSysMessage("DB table `npc_vendor` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadPointsOfInterestCommand(char* /*args*/) +{ + sLog.outString("Re-Loading `points_of_interest` Table!"); + sObjectMgr.LoadPointsOfInterest(); + SendGlobalSysMessage("DB table `points_of_interest` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadReservedNameCommand(char* /*args*/) +{ + sLog.outString("Loading ReservedNames... (`reserved_name`)"); + sObjectMgr.LoadReservedPlayersNames(); + SendGlobalSysMessage("DB table `reserved_name` (player reserved names) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadReputationRewardRateCommand(char* /*args*/) +{ + sLog.outString("Re-Loading `reputation_reward_rate` Table!"); + sObjectMgr.LoadReputationRewardRate(); + SendGlobalSysMessage("DB table `reputation_reward_rate` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadReputationSpilloverTemplateCommand(char* /*args*/) +{ + sLog.outString("Re-Loading `reputation_spillover_template` Table!"); + sObjectMgr.LoadReputationSpilloverTemplate(); + SendGlobalSysMessage("DB table `reputation_spillover_template` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSkillDiscoveryTemplateCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Skill Discovery Table..."); + LoadSkillDiscoveryTable(); + SendGlobalSysMessage("DB table `skill_discovery_template` (recipes discovered at crafting) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSkillExtraItemTemplateCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Skill Extra Item Table..."); + LoadSkillExtraItemTable(); + SendGlobalSysMessage("DB table `skill_extra_item_template` (extra item creation when crafting) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadScriptBindingCommand(char* /*args*/) +{ + sLog.outString("Trying to re-load `script_binding` Table!"); + if (sScriptMgr.ReloadScriptBinding()) + { + SendGlobalSysMessage("DB table `script_binding` reloaded.", SEC_MODERATOR); + } + else + { + SendSysMessage("DENIED: DB table `script_binding` is reloadable only in Debug build."); + } + return true; +} + +bool ChatHandler::HandleReloadSkillFishingBaseLevelCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Skill Fishing base level requirements..."); + sObjectMgr.LoadFishingBaseSkillLevel(); + SendGlobalSysMessage("DB table `skill_fishing_base_level` (fishing base level for zone/subzone) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSpellAffectCommand(char* /*args*/) +{ + sLog.outString("Re-Loading SpellAffect definitions..."); + sSpellMgr.LoadSpellAffects(); + SendGlobalSysMessage("DB table `spell_affect` (spell mods apply requirements) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSpellAreaCommand(char* /*args*/) +{ + sLog.outString("Re-Loading SpellArea Data..."); + sSpellMgr.LoadSpellAreas(); + SendGlobalSysMessage("DB table `spell_area` (spell dependences from area/quest/auras state) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSpellBonusesCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Spell Bonus Data..."); + sSpellMgr.LoadSpellBonuses(); + SendGlobalSysMessage("DB table `spell_bonus_data` (spell damage/healing coefficients) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSpellChainCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Spell Chain Data... "); + sSpellMgr.LoadSpellChains(); + SendGlobalSysMessage("DB table `spell_chain` (spell ranks) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSpellElixirCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Spell Elixir types..."); + sSpellMgr.LoadSpellElixirs(); + SendGlobalSysMessage("DB table `spell_elixir` (spell elixir types) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSpellLearnSpellCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Spell Learn Spells..."); + sSpellMgr.LoadSpellLearnSpells(); + SendGlobalSysMessage("DB table `spell_learn_spell` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSpellProcEventCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Spell Proc Event conditions..."); + sSpellMgr.LoadSpellProcEvents(); + SendGlobalSysMessage("DB table `spell_proc_event` (spell proc trigger requirements) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSpellProcItemEnchantCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Spell Proc Item Enchant..."); + sSpellMgr.LoadSpellProcItemEnchant(); + SendGlobalSysMessage("DB table `spell_proc_item_enchant` (item enchantment ppm) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSpellScriptTargetCommand(char* /*args*/) +{ + sLog.outString("Re-Loading SpellsScriptTarget..."); + sSpellMgr.LoadSpellScriptTarget(); + SendGlobalSysMessage("DB table `spell_script_target` (spell targets selection in case specific creature/GO requirements) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSpellTargetPositionCommand(char* /*args*/) +{ + sLog.outString("Re-Loading spell target destination coordinates..."); + sSpellMgr.LoadSpellTargetPositions(); + SendGlobalSysMessage("DB table `spell_target_position` (destination coordinates for spell targets) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSpellThreatsCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Aggro Spells Definitions..."); + sSpellMgr.LoadSpellThreats(); + SendGlobalSysMessage("DB table `spell_threat` (spell aggro definitions) reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadSpellPetAurasCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Spell pet auras..."); + sSpellMgr.LoadSpellPetAuras(); + SendGlobalSysMessage("DB table `spell_pet_auras` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadPageTextsCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Page Texts..."); + sObjectMgr.LoadPageTexts(); + SendGlobalSysMessage("DB table `page_texts` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadItemEnchantementsCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Item Random Enchantments Table..."); + LoadRandomEnchantmentsTable(); + SendGlobalSysMessage("DB table `item_enchantment_template` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadItemRequiredTragetCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Item Required Targets Table..."); + sObjectMgr.LoadItemRequiredTarget(); + SendGlobalSysMessage("DB table `item_required_target` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadBattleEventCommand(char* /*args*/) +{ + sLog.outString("Re-Loading BattleGround Eventindexes..."); + sBattleGroundMgr.LoadBattleEventIndexes(); + SendGlobalSysMessage("DB table `gameobject_battleground` and `creature_battleground` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadEventAITextsCommand(char* /*args*/) +{ + + sLog.outString("Re-Loading Texts from `creature_ai_texts`..."); + sEventAIMgr.LoadCreatureEventAI_Texts(true); + SendGlobalSysMessage("DB table `creature_ai_texts` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadEventAISummonsCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Summons from `creature_ai_summons`..."); + sEventAIMgr.LoadCreatureEventAI_Summons(true); + SendGlobalSysMessage("DB table `creature_ai_summons` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadEventAIScriptsCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Scripts from `creature_ai_scripts`..."); + sEventAIMgr.LoadCreatureEventAI_Scripts(); + SendGlobalSysMessage("DB table `creature_ai_scripts` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadDbScriptStringCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Script strings from `db_script_string`..."); + sScriptMgr.LoadDbScriptStrings(); + SendGlobalSysMessage("DB table `db_script_string` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadDBScriptsOnGossipCommand(char* args) +{ + if (sScriptMgr.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*args != 'a') + { + sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_GOSSIP]`..."); + } + + sScriptMgr.LoadDbScripts(DBS_ON_GOSSIP); + + if (*args != 'a') + { + SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_GOSSIP]` reloaded.", SEC_MODERATOR); + } + + return true; +} + +bool ChatHandler::HandleReloadDBScriptsOnSpellCommand(char* args) +{ + if (sScriptMgr.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*args != 'a') + { + sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_SPELL]`..."); + } + + sScriptMgr.LoadDbScripts(DBS_ON_SPELL); + + if (*args != 'a') + { + SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_SPELL]` reloaded.", SEC_MODERATOR); + } + + return true; +} + +bool ChatHandler::HandleReloadDBScriptsOnQuestStartCommand(char* args) +{ + if (sScriptMgr.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*args != 'a') + { + sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_QUEST_START]`..."); + } + + sScriptMgr.LoadDbScripts(DBS_ON_QUEST_START); + + if (*args != 'a') + { + SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_QUEST_START]` reloaded.", SEC_MODERATOR); + } + + return true; +} + +bool ChatHandler::HandleReloadDBScriptsOnQuestEndCommand(char* args) +{ + if (sScriptMgr.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*args != 'a') + { + sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_QUEST_END]`..."); + } + + sScriptMgr.LoadDbScripts(DBS_ON_QUEST_END); + + if (*args != 'a') + { + SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_QUEST_END]` reloaded.", SEC_MODERATOR); + } + + return true; +} + +bool ChatHandler::HandleReloadDBScriptsOnEventCommand(char* args) +{ + if (sScriptMgr.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*args != 'a') + { + sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_EVENT]`..."); + } + + sScriptMgr.LoadDbScripts(DBS_ON_EVENT); + + if (*args != 'a') + { + SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_EVENT]` reloaded.", SEC_MODERATOR); + } + + return true; +} + +bool ChatHandler::HandleReloadDBScriptsOnGoUseCommand(char* args) +{ + if (sScriptMgr.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*args != 'a') + { + sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_GO[_TEMPLATE]_USE]`..."); + } + + sScriptMgr.LoadDbScripts(DBS_ON_GO_USE); + sScriptMgr.LoadDbScripts(DBS_ON_GOT_USE); + + if (*args != 'a') + { + SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_GO[_TEMPLATE]_USE]` reloaded.", SEC_MODERATOR); + } + + return true; +} + +bool ChatHandler::HandleReloadDBScriptsOnCreatureDeathCommand(char* args) +{ + if (sScriptMgr.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*args != 'a') + { + sLog.outString("Re-Loading Scripts from `db_scripts [type = DBS_ON_CREATURE_DEATH]`..."); + } + + sScriptMgr.LoadDbScripts(DBS_ON_CREATURE_DEATH); + + if (*args != 'a') + { + SendGlobalSysMessage("DB table `db_scripts [type = DBS_ON_CREATURE_DEATH]` reloaded.", SEC_MODERATOR); + } + + return true; +} + +bool ChatHandler::HandleReloadGameGraveyardZoneCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Graveyard-zone links..."); + sObjectMgr.LoadGraveyardZones(); + SendGlobalSysMessage("DB table `game_graveyard_zone` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadGameTeleCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Game Tele coordinates..."); + sObjectMgr.LoadGameTele(); + SendGlobalSysMessage("DB table `game_tele` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLocalesCreatureCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Locales Creature ..."); + sObjectMgr.LoadCreatureLocales(); + SendGlobalSysMessage("DB table `locales_creature` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLocalesGameobjectCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Locales Gameobject ... "); + sObjectMgr.LoadGameObjectLocales(); + SendGlobalSysMessage("DB table `locales_gameobject` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLocalesGossipMenuOptionCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Locales Gossip Menu Option ... "); + sObjectMgr.LoadGossipMenuItemsLocales(); + SendGlobalSysMessage("DB table `locales_gossip_menu_option` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLocalesItemCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Locales Item ... "); + sObjectMgr.LoadItemLocales(); + SendGlobalSysMessage("DB table `locales_item` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLocalesNpcTextCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Locales NPC Text ... "); + sObjectMgr.LoadGossipTextLocales(); + SendGlobalSysMessage("DB table `locales_npc_text` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLocalesPageTextCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Locales Page Text ... "); + sObjectMgr.LoadPageTextLocales(); + SendGlobalSysMessage("DB table `locales_page_text` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLocalesPointsOfInterestCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Locales Points Of Interest ... "); + sObjectMgr.LoadPointOfInterestLocales(); + SendGlobalSysMessage("DB table `locales_points_of_interest` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadLocalesQuestCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Locales Quest ... "); + sObjectMgr.LoadQuestLocales(); + SendGlobalSysMessage("DB table `locales_quest` reloaded.", SEC_MODERATOR); + return true; +} + +bool ChatHandler::HandleReloadMailLevelRewardCommand(char* /*args*/) +{ + sLog.outString("Re-Loading Player level dependent mail rewards..."); + sObjectMgr.LoadMailLevelRewards(); + SendGlobalSysMessage("DB table `mail_level_reward` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadDisablesCommand(char* /*args*/) +{ + sLog.outString("Re-loading Disables..."); + DisableMgr::LoadDisables(); + DisableMgr::CheckQuestDisables(); + SendGlobalSysMessage("DB table `disables` reloaded.", SEC_MODERATOR); + return true; +} diff --git a/src/game/ChatCommands/ServerCommands.cpp b/src/game/ChatCommands/ServerCommands.cpp new file mode 100644 index 0000000000000..609931c02b0c0 --- /dev/null +++ b/src/game/ChatCommands/ServerCommands.cpp @@ -0,0 +1,436 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "World.h" +#include "Config.h" +#include "SystemConfig.h" +#include "BattleGroundMgr.h" +#include "revision.h" + + /********************************************************************** + CommandTable : serverCommandTable + /***********************************************************************/ + + +bool ChatHandler::HandleServerInfoCommand(char* /*args*/) +{ + uint32 activeClientsNum = sWorld.GetActiveSessionCount(); + uint32 queuedClientsNum = sWorld.GetQueuedSessionCount(); + uint32 maxActiveClientsNum = sWorld.GetMaxActiveSessionCount(); + uint32 maxQueuedClientsNum = sWorld.GetMaxQueuedSessionCount(); + std::string str = secsToTimeString(sWorld.GetUptime()); + + char const* full; + full = REVISION_NR; + SendSysMessage(full); + + if (sScriptMgr.IsScriptLibraryLoaded()) + { + char const* ver = sScriptMgr.GetScriptLibraryVersion(); + if (ver && *ver) + { + PSendSysMessage(LANG_USING_SCRIPT_LIB, ver); + } + else + { + SendSysMessage(LANG_USING_SCRIPT_LIB_UNKNOWN); + } + } + else + { + SendSysMessage(LANG_USING_SCRIPT_LIB_NONE); + } + + PSendSysMessage(LANG_USING_WORLD_DB, sWorld.GetDBVersion()); + PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); + PSendSysMessage(LANG_UPTIME, str.c_str()); + + return true; +} + +/// Display the 'Message of the day' for the realm +bool ChatHandler::HandleServerMotdCommand(char* /*args*/) +{ + PSendSysMessage(LANG_MOTD_CURRENT, sWorld.GetMotd()); + return true; +} + +bool ChatHandler::HandleServerShutDownCancelCommand(char* /*args*/) +{ + sWorld.ShutdownCancel(); + return true; +} + +bool ChatHandler::HandleServerShutDownCommand(char* args) +{ + if (!*args) + { + return false; + } + + char* timeStr = strtok((char*)args, " "); + char* exitCodeStr = strtok(NULL, ""); + + int32 time = atoi(timeStr); + + // Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (timeStr[0] != '0' || timeStr[1] != '\0')) || time < 0) + { + return false; + } + + if (exitCodeStr) + { + int32 exitCode = atoi(exitCodeStr); + + // Handle atoi() errors + if (exitCode == 0 && (exitCodeStr[0] != '0' || exitCodeStr[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_STOP, exitCode); + } + else + { + sWorld.ShutdownServ(time, SHUTDOWN_MASK_STOP, SHUTDOWN_EXIT_CODE); + } + + return true; +} + +bool ChatHandler::HandleServerRestartCommand(char* args) +{ + if (!*args) + { + return false; + } + + char* timeStr = strtok((char*)args, " "); + char* exitCodeStr = strtok(NULL, ""); + + int32 time = atoi(timeStr); + + // Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (timeStr[0] != '0' || timeStr[1] != '\0')) || time < 0) + { + return false; + } + + if (exitCodeStr) + { + int32 exitCode = atoi(exitCodeStr); + + // Handle atoi() errors + if (exitCode == 0 && (exitCodeStr[0] != '0' || exitCodeStr[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(char* args) +{ + if (!*args) + { + return false; + } + + char* timeStr = strtok((char*)args, " "); + char* exitCodeStr = strtok(NULL, ""); + + int32 time = atoi(timeStr); + + // Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (timeStr[0] != '0' || timeStr[1] != '\0')) || time < 0) + { + return false; + } + + if (exitCodeStr) + { + int32 exitCode = atoi(exitCodeStr); + + // Handle atoi() errors + if (exitCode == 0 && (exitCodeStr[0] != '0' || exitCodeStr[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::HandleServerIdleShutDownCommand(char* args) +{ + if (!*args) + { + return false; + } + + char* timeStr = strtok((char*)args, " "); + char* exitCodeStr = strtok(NULL, ""); + + int32 time = atoi(timeStr); + + // Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (timeStr[0] != '0' || timeStr[1] != '\0')) || time < 0) + { + return false; + } + + if (exitCodeStr) + { + int32 exitCode = atoi(exitCodeStr); + + // Handle atoi() errors + if (exitCode == 0 && (exitCodeStr[0] != '0' || exitCodeStr[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, RESTART_EXIT_CODE); + } + + return true; +} + +/// Exit the realm +bool ChatHandler::HandleServerExitCommand(char* /*args*/) +{ + SendSysMessage(LANG_COMMAND_EXIT); + World::StopNow(SHUTDOWN_EXIT_CODE); + return true; +} + +/// Set the filters of logging +bool ChatHandler::HandleServerLogFilterCommand(char* args) +{ + if (!*args) + { + SendSysMessage(LANG_LOG_FILTERS_STATE_HEADER); + for (int i = 0; i < LOG_FILTER_COUNT; ++i) + if (*logFilterData[i].name) + { + PSendSysMessage(" %-20s = %s", logFilterData[i].name, GetOnOffStr(sLog.HasLogFilter(1 << i))); + } + return true; + } + + char* filtername = ExtractLiteralArg(&args); + if (!filtername) + { + return false; + } + + bool value; + if (!ExtractOnOff(&args, value)) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + if (strncmp(filtername, "all", 4) == 0) + { + sLog.SetLogFilter(LogFilters(0xFFFFFFFF), value); + PSendSysMessage(LANG_ALL_LOG_FILTERS_SET_TO_S, GetOnOffStr(value)); + return true; + } + + for (int i = 0; i < LOG_FILTER_COUNT; ++i) + { + if (!*logFilterData[i].name) + { + continue; + } + + if (!strncmp(filtername, logFilterData[i].name, strlen(filtername))) + { + sLog.SetLogFilter(LogFilters(1 << i), value); + PSendSysMessage(" %-20s = %s", logFilterData[i].name, GetOnOffStr(value)); + return true; + } + } + + return false; +} + +/// Set the level of logging +bool ChatHandler::HandleServerLogLevelCommand(char* args) +{ + if (!*args) + { + PSendSysMessage("Log level: %u", sLog.GetLogLevel()); + return true; + } + + sLog.SetLogLevel(args); + return true; +} + +/// Triggering corpses expire check in world +bool ChatHandler::HandleServerCorpsesCommand(char* /*args*/) +{ + sObjectAccessor.RemoveOldCorpses(); + return true; +} + +bool ChatHandler::HandleServerResetAllRaidCommand(char* args) +{ + PSendSysMessage("Global raid instances reset, all players in raid instances will be teleported to homebind!"); + sMapPersistentStateMgr.GetScheduler().ResetAllRaid(); + return true; +} + +/// Define the 'Message of the day' for the realm +bool ChatHandler::HandleServerSetMotdCommand(char* args) +{ + sWorld.SetMotd(args); + PSendSysMessage(LANG_MOTD_NEW, args); + return true; +} + +bool ChatHandler::HandleServerPLimitCommand(char* args) +{ + if (*args) + { + char* param = ExtractLiteralArg(&args); + if (!param) + { + return false; + } + + int l = strlen(param); + + int val; + if (strncmp(param, "player", l) == 0) + { + sWorld.SetPlayerLimit(-SEC_PLAYER); + } + else if (strncmp(param, "moderator", l) == 0) + { + sWorld.SetPlayerLimit(-SEC_MODERATOR); + } + else if (strncmp(param, "gamemaster", l) == 0) + { + sWorld.SetPlayerLimit(-SEC_GAMEMASTER); + } + else if (strncmp(param, "administrator", l) == 0) + { + sWorld.SetPlayerLimit(-SEC_ADMINISTRATOR); + } + else if (strncmp(param, "reset", l) == 0) + { + sWorld.SetPlayerLimit(sConfig.GetIntDefault("PlayerLimit", DEFAULT_PLAYER_LIMIT)); + } + else if (ExtractInt32(¶m, val)) + { + if (val < -SEC_ADMINISTRATOR) + { + val = -SEC_ADMINISTRATOR; + } + + sWorld.SetPlayerLimit(val); + } + else + { + return false; + } + + // kick all low security level players + if (sWorld.GetPlayerAmountLimit() > 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 = ""; break; + } + + PSendSysMessage("Player limits: amount %u, min. security level %s.", pLimit, secName); + + return true; +} diff --git a/src/game/ChatCommands/Level1.cpp b/src/game/ChatCommands/TeleportationAndPositionCommands.cpp similarity index 50% rename from src/game/ChatCommands/Level1.cpp rename to src/game/ChatCommands/TeleportationAndPositionCommands.cpp index d49f0f56374ac..6fbf56e0937c7 100644 --- a/src/game/ChatCommands/Level1.cpp +++ b/src/game/ChatCommands/TeleportationAndPositionCommands.cpp @@ -22,514 +22,381 @@ * and lore are copyrighted by Blizzard Entertainment, Inc. */ -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "DBCStores.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "World.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "Opcodes.h" #include "Chat.h" -#include "Log.h" -#include "MapManager.h" -#include "ObjectAccessor.h" #include "Language.h" +#include "World.h" +#include "MapManager.h" #include "CellImpl.h" -#include "MapPersistentStateMgr.h" -#include "Mail.h" -#include "Util.h" -#include "SpellMgr.h" + + #ifdef _DEBUG_VMAPS #include "VMapFactory.h" #endif + /* + All commands related to Teleportation + */ -//-----------------------Npc Commands----------------------- -bool ChatHandler::HandleNpcSayCommand(char* args) -{ - if (!*args) - { - return false; - } - - Creature* pCreature = getSelectedCreature(); - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->MonsterSay(args, LANG_UNIVERSAL, m_session->GetPlayer()); - - return true; -} +/* + Utilities methods an enums +*/ -bool ChatHandler::HandleNpcYellCommand(char* args) +enum CreatureLinkType { - if (!*args) - { - return false; - } + CREATURE_LINK_RAW = -1, // non-link case + CREATURE_LINK_GUID = 0, + CREATURE_LINK_ENTRY = 1, +}; - Creature* pCreature = getSelectedCreature(); - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } +static char const* const creatureKeys[] = +{ + "Hcreature", + "Hcreature_entry", + NULL +}; - pCreature->MonsterYell(args, LANG_UNIVERSAL, m_session->GetPlayer()); +enum GameobjectLinkType +{ + GAMEOBJECT_LINK_RAW = -1, // non-link case + GAMEOBJECT_LINK_GUID = 0, + GAMEOBJECT_LINK_ENTRY = 1, +}; - return true; -} +static char const* const gameobjectKeys[] = +{ + "Hgameobject", + "Hgameobject_entry", + NULL +}; -// show text emote by creature in chat -bool ChatHandler::HandleNpcTextEmoteCommand(char* args) +static char const* const areatriggerKeys[] = { - if (!*args) - { - return false; - } + "Hareatrigger", + "Hareatrigger_target", + NULL +}; - Creature* pCreature = getSelectedCreature(); +bool ChatHandler::HandleGoHelper(Player* player, uint32 mapid, float x, float y, float const* zPtr, float const* ortPtr) +{ + float z; + float ort = player->GetOrientation(); - if (!pCreature) + if (zPtr) { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->MonsterTextEmote(args, m_session->GetPlayer()); + z = *zPtr; - return true; -} + if (ortPtr) + { + ort = *ortPtr; + } -// make npc whisper to player -bool ChatHandler::HandleNpcWhisperCommand(char* args) -{ - Player* target; - if (!ExtractPlayerTarget(&args, &target)) - { - return false; + // check full provided coordinates + if (!MapManager::IsValidMapCoord(mapid, x, y, z, ort)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapid); + SetSentErrorMessage(true); + return false; + } } - - ObjectGuid guid = m_session->GetPlayer()->GetSelectionGuid(); - if (!guid) + else { - return false; - } + // we need check x,y before ask Z or can crash at invalide coordinates + if (!MapManager::IsValidMapCoord(mapid, x, y)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapid); + SetSentErrorMessage(true); + return false; + } - Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(guid); + TerrainInfo const* map = sTerrainMgr.LoadTerrain(mapid); + z = map->GetWaterOrGroundLevel(x, y, MAX_HEIGHT); + } - if (!pCreature || !target || !*args) + // stop flight if need + if (player->IsTaxiFlying()) { - return false; + player->GetMotionMaster()->MovementExpired(); + player->m_taxi.ClearTaxiDestinations(); } - - // check online security - if (HasLowerSecurity(target)) + // save only in non-flight case + else { - return false; + player->SaveRecallPosition(); } - pCreature->MonsterWhisper(args, target); + player->TeleportTo(mapid, x, y, z, ort); return true; } -//---------------------------------------------------------- -// global announce -bool ChatHandler::HandleAnnounceCommand(char* args) + /********************************************************************** + CommandTable : commandTable + /***********************************************************************/ + + // Summon Player +bool ChatHandler::HandleSummonCommand(char* args) { - if (!*args) + Player* target; + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) { return false; } - sWorld.SendWorldText(LANG_SYSTEMMESSAGE, args); - return true; -} - -// notification player at the screen -bool ChatHandler::HandleNotifyCommand(char* args) -{ - if (!*args) + Player* player = m_session->GetPlayer(); + if (target == player || target_guid == player->GetObjectGuid()) { + PSendSysMessage(LANG_CANT_TELEPORT_SELF); + SetSentErrorMessage(true); return false; } - std::string str = GetMangosString(LANG_GLOBAL_NOTIFY); - str += args; - - WorldPacket data(SMSG_NOTIFICATION, (str.size() + 1)); - data << str; - sWorld.SendGlobalMessage(&data); - - return true; -} - -// Enable\Dissable GM Mode -bool ChatHandler::HandleGMCommand(char* args) -{ - if (!*args) + if (target) { - if (m_session->GetPlayer()->isGameMaster()) + std::string nameLink = playerLink(target_name); + // check online security + if (HasLowerSecurity(target)) { - m_session->SendNotification(LANG_GM_ON); + return false; } - else + + if (target->IsBeingTeleported()) { - m_session->SendNotification(LANG_GM_OFF); + PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str()); + SetSentErrorMessage(true); + return false; } - return true; - } - std::string argstr = (char*)args; - - if (argstr == "on") - { - m_session->GetPlayer()->SetGameMaster(true); - m_session->SendNotification(LANG_GM_ON); -#ifdef _DEBUG_VMAPS - VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); - vMapManager->processCommand("stoplog"); -#endif - - return true; - } + Map* pMap = player->GetMap(); - if (argstr == "off") - { - m_session->GetPlayer()->SetGameMaster(false); - m_session->SendNotification(LANG_GM_OFF); -#ifdef _DEBUG_VMAPS - VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); - vMapManager->processCommand("startlog"); -#endif + 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() && player->GetBattleGroundId() != target->GetBattleGroundId()) + { + 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(player->GetBattleGroundId(), player->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()) + { + // can not summon from instance to instance + PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, nameLink.c_str()); + SetSentErrorMessage(true); + return false; + } - return true; - } + // we are in instance, and can summon only player in our group with us as lead + if (!player->GetGroup() || !target->GetGroup() || + (target->GetGroup()->GetLeaderGuid() != player->GetObjectGuid()) || + (player->GetGroup()->GetLeaderGuid() != player->GetObjectGuid())) + // 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; + } + } - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; -} + PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), ""); + if (needReportToTarget(target)) + { + ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, playerLink(player->GetName()).c_str()); + } -// Enables or disables hiding of the staff badge -bool ChatHandler::HandleGMChatCommand(char* args) -{ - if (!*args) - { - if (m_session->GetPlayer()->isGMChat()) + // stop flight if need + if (target->IsTaxiFlying()) { - m_session->SendNotification(LANG_GM_CHAT_ON); + target->GetMotionMaster()->MovementExpired(); + target->m_taxi.ClearTaxiDestinations(); } + // save only in non-flight case else { - m_session->SendNotification(LANG_GM_CHAT_OFF); + target->SaveRecallPosition(); } - return true; - } - - bool value; - if (!ExtractOnOff(&args, value)) - { - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; - } - if (value) - { - m_session->GetPlayer()->SetGMChat(true); - m_session->SendNotification(LANG_GM_CHAT_ON); + // before GM + float x, y, z; + player->GetClosePoint(x, y, z, target->GetObjectBoundingRadius()); + target->TeleportTo(player->GetMapId(), x, y, z, target->GetOrientation()); } else { - m_session->GetPlayer()->SetGMChat(false); - m_session->SendNotification(LANG_GM_CHAT_OFF); + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + { + return false; + } + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), GetMangosString(LANG_OFFLINE)); + + // in point where GM stay + Player::SavePositionInDB(target_guid, player->GetMapId(), + player->GetPositionX(), + player->GetPositionY(), + player->GetPositionZ(), + player->GetOrientation(), + player->GetZoneId()); } return true; } -// Enable\Dissable Invisible mode -bool ChatHandler::HandleGMVisibleCommand(char* args) +// Teleport to Player +bool ChatHandler::HandleAppearCommand(char* args) { - if (!*args) + Player* target; + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) { - PSendSysMessage(LANG_YOU_ARE, m_session->GetPlayer()->isGMVisible() ? GetMangosString(LANG_VISIBLE) : GetMangosString(LANG_INVISIBLE)); - return true; + return false; } - bool value; - if (!ExtractOnOff(&args, value)) + Player* _player = m_session->GetPlayer(); + if (target == _player || target_guid == _player->GetObjectGuid()) { - SendSysMessage(LANG_USE_BOL); + SendSysMessage(LANG_CANT_TELEPORT_SELF); SetSentErrorMessage(true); return false; } - Player* player = m_session->GetPlayer(); - SpellEntry const* invisibleAuraInfo = sSpellStore.LookupEntry(sWorld.getConfig(CONFIG_UINT32_GM_INVISIBLE_AURA)); - if (!invisibleAuraInfo || !IsSpellAppliesAura(invisibleAuraInfo)) - { - invisibleAuraInfo = NULL; - } - if (value) - { - player->SetGMVisible(true); - m_session->SendNotification(LANG_INVISIBLE_VISIBLE); - if (invisibleAuraInfo) - { - player->RemoveAurasDueToSpell(invisibleAuraInfo->Id); - } - } - else + if (target) { - m_session->SendNotification(LANG_INVISIBLE_INVISIBLE); - player->SetGMVisible(false); - if (invisibleAuraInfo) + // check online security + if (HasLowerSecurity(target)) { - player->CastSpell(player, invisibleAuraInfo, true); + return false; } - } - return true; -} + std::string chrNameLink = playerLink(target_name); -bool ChatHandler::HandleGPSCommand(char* args) -{ - WorldObject* obj = NULL; - if (*args) - { - if (ObjectGuid guid = ExtractGuidFromLink(&args)) - { - obj = (WorldObject*)m_session->GetPlayer()->GetObjectByTypeMask(guid, TYPEMASK_CREATURE_OR_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 = MaNGOS::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(); - - if (!Map2ZoneCoordinates(zone_x, zone_y, zone_id)) - { - zone_x = 0; - zone_y = 0; - } - - 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 = MaNGOS::ComputeGridPair(obj->GetPositionX(), obj->GetPositionY()); - - int gx = 63 - p.x_coord; - int gy = 63 - p.y_coord; - - uint32 have_map = GridMap::ExistMap(obj->GetMapId(), gx, gy) ? 1 : 0; - uint32 have_vmap = GridMap::ExistVMap(obj->GetMapId(), gx, gy) ? 1 : 0; - - TerrainInfo const* terrain = obj->GetTerrain(); - - if (have_vmap) - { - if (terrain->IsOutdoors(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ())) - { - PSendSysMessage("You are OUTdoor"); - } - else - { - PSendSysMessage("You are INdoor"); - } - } - else - { - PSendSysMessage("no VMAP available for area info"); - } - - PSendSysMessage(LANG_MAP_POSITION, - obj->GetMapId(), (mapEntry ? mapEntry->name[GetSessionDbcLocale()] : ""), - zone_id, (zoneEntry ? zoneEntry->area_name[GetSessionDbcLocale()] : ""), - area_id, (areaEntry ? areaEntry->area_name[GetSessionDbcLocale()] : ""), - 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); - - DEBUG_LOG("Player %s GPS call for %s '%s' (%s: %u):", - m_session ? GetNameLink().c_str() : GetMangosString(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())); - - DEBUG_LOG(GetMangosString(LANG_MAP_POSITION), - obj->GetMapId(), (mapEntry ? mapEntry->name[sWorld.GetDefaultDbcLocale()] : ""), - zone_id, (zoneEntry ? zoneEntry->area_name[sWorld.GetDefaultDbcLocale()] : ""), - area_id, (areaEntry ? areaEntry->area_name[sWorld.GetDefaultDbcLocale()] : ""), - 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); - - GridMapLiquidData liquid_status; - GridMapLiquidStatus res = terrain->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_flags, res); - } - - // Additional vmap debugging help -#ifdef _DEBUG_VMAPS - PSendSysMessage("Static terrain height (maps only): %f", obj->GetTerrain()->GetHeightStatic(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), false)); - - if (VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager()) - { - PSendSysMessage("Vmap Terrain Height %f", vmgr->getHeight(obj->GetMapId(), obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ() + 2.0f, 10000.0f)); - } - - PSendSysMessage("Static map height (maps and vmaps): %f", obj->GetTerrain()->GetHeightStatic(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ())); -#endif - - return true; -} - -// Summon Player -bool ChatHandler::HandleSummonCommand(char* args) -{ - Player* target; - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) - { - return false; - } - - Player* player = m_session->GetPlayer(); - if (target == player || target_guid == player->GetObjectGuid()) - { - PSendSysMessage(LANG_CANT_TELEPORT_SELF); - SetSentErrorMessage(true); - return false; - } - - if (target) - { - std::string nameLink = playerLink(target_name); - // check online security - if (HasLowerSecurity(target)) - { - return false; - } - - if (target->IsBeingTeleported()) - { - PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - Map* pMap = player->GetMap(); - - if (pMap->IsBattleGroundOrArena()) + Map* cMap = target->GetMap(); + if (cMap->IsBattleGroundOrArena()) { // only allow if gm mode is on - if (!target->isGameMaster()) + if (!_player->isGameMaster()) { - PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM, nameLink.c_str()); + PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM, chrNameLink.c_str()); SetSentErrorMessage(true); return false; } // if both players are in different bgs - else if (target->GetBattleGroundId() && player->GetBattleGroundId() != target->GetBattleGroundId()) + else if (_player->GetBattleGroundId() && _player->GetBattleGroundId() != target->GetBattleGroundId()) { - PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG, nameLink.c_str()); + 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 - target->SetBattleGroundId(player->GetBattleGroundId(), player->GetBattleGroundTypeId()); + _player->SetBattleGroundId(target->GetBattleGroundId(), target->GetBattleGroundTypeId()); // remember current position as entry point for return at bg end teleportation - if (!target->GetMap()->IsBattleGroundOrArena()) + if (!_player->GetMap()->IsBattleGroundOrArena()) { - target->SetBattleGroundEntryPoint(); + _player->SetBattleGroundEntryPoint(); } } - else if (pMap->IsDungeon()) + else if (cMap->IsDungeon()) { - Map* cMap = target->GetMap(); - if (cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId()) + // 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()) { - // can not summon from instance to instance - PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, nameLink.c_str()); - SetSentErrorMessage(true); - return false; + // 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; + } } - // we are in instance, and can summon only player in our group with us as lead - if (!player->GetGroup() || !target->GetGroup() || - (target->GetGroup()->GetLeaderGuid() != player->GetObjectGuid()) || - (player->GetGroup()->GetLeaderGuid() != player->GetObjectGuid())) - // the last check is a bit excessive, but let it be, just in case + // 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()); + if (!pBind) { - PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, nameLink.c_str()); - SetSentErrorMessage(true); - return false; + Group* group = _player->GetGroup(); + // if no bind exists, create a solo bind + InstanceGroupBind* gBind = group ? group->GetBoundInstance(target->GetMapId(), target) : NULL; + // if no bind exists, create a solo bind + if (!gBind) + { + DungeonPersistentState* save = ((DungeonMap*)target->GetMap())->GetPersistanceState(); + + // if player is group leader then we need add group bind + if (group && group->IsLeader(_player->GetObjectGuid())) + { + group->BindToInstance(save, !save->CanReset()); + } + else + { + _player->BindToInstance(save, !save->CanReset()); + } + } } + + _player->SetDifficulty(target->GetDifficulty()); } - PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), ""); + PSendSysMessage(LANG_APPEARING_AT, chrNameLink.c_str()); if (needReportToTarget(target)) { - ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, playerLink(player->GetName()).c_str()); + ChatHandler(target).PSendSysMessage(LANG_APPEARING_TO, GetNameLink().c_str()); } // stop flight if need - if (target->IsTaxiFlying()) + if (_player->IsTaxiFlying()) { - target->GetMotionMaster()->MovementExpired(); - target->m_taxi.ClearTaxiDestinations(); + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); } // save only in non-flight case else { - target->SaveRecallPosition(); + _player->SaveRecallPosition(); } - // before GM + // to point to see at target with same orientation float x, y, z; - player->GetClosePoint(x, y, z, target->GetObjectBoundingRadius()); - target->TeleportTo(player->GetMapId(), x, y, z, target->GetOrientation()); + target->GetContactPoint(_player, x, y, z); + + _player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE); } else { @@ -541,165 +408,7 @@ bool ChatHandler::HandleSummonCommand(char* args) std::string nameLink = playerLink(target_name); - PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), GetMangosString(LANG_OFFLINE)); - - // in point where GM stay - Player::SavePositionInDB(target_guid, player->GetMapId(), - player->GetPositionX(), - player->GetPositionY(), - player->GetPositionZ(), - player->GetOrientation(), - player->GetZoneId()); - } - - return true; -} - -// Teleport to Player -bool ChatHandler::HandleAppearCommand(char* args) -{ - Player* target; - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) - { - return false; - } - - Player* _player = m_session->GetPlayer(); - if (target == _player || target_guid == _player->GetObjectGuid()) - { - SendSysMessage(LANG_CANT_TELEPORT_SELF); - SetSentErrorMessage(true); - return false; - } - - - if (target) - { - // check online security - if (HasLowerSecurity(target)) - { - 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()) - { - 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()) - { - // 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()); - if (!pBind) - { - Group* group = _player->GetGroup(); - // if no bind exists, create a solo bind - InstanceGroupBind* gBind = group ? group->GetBoundInstance(target->GetMapId(), target) : NULL; - // if no bind exists, create a solo bind - if (!gBind) - { - DungeonPersistentState* save = ((DungeonMap*)target->GetMap())->GetPersistanceState(); - - // if player is group leader then we need add group bind - if (group && group->IsLeader(_player->GetObjectGuid())) - { - group->BindToInstance(save, !save->CanReset()); - } - else - { - _player->BindToInstance(save, !save->CanReset()); - } - } - } - - _player->SetDifficulty(target->GetDifficulty()); - } - - 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->IsTaxiFlying()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->m_taxi.ClearTaxiDestinations(); - } - // 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); - } - else - { - // check offline security - if (HasLowerSecurity(NULL, target_guid)) - { - return false; - } - - std::string nameLink = playerLink(target_name); - - PSendSysMessage(LANG_APPEARING_AT, nameLink.c_str()); + PSendSysMessage(LANG_APPEARING_AT, nameLink.c_str()); // to point where player stay (if loaded) float x, y, z, o; @@ -716,8 +425,8 @@ bool ChatHandler::HandleAppearCommand(char* args) return true; } -// Teleport player to last position -bool ChatHandler::HandleRecallCommand(char* args) +// Summon group of player +bool ChatHandler::HandleGroupgoCommand(char* args) { Player* target; if (!ExtractPlayerTarget(&args, &target)) @@ -731,1805 +440,1216 @@ bool ChatHandler::HandleRecallCommand(char* args) return false; } - if (target->IsBeingTeleported()) - { - PSendSysMessage(LANG_IS_TELEPORTED, GetNameLink(target).c_str()); - SetSentErrorMessage(true); - return false; - } - - return HandleGoHelper(target, target->m_recallMap, target->m_recallX, target->m_recallY, &target->m_recallZ, &target->m_recallO); -} - -// Edit Player HP -bool ChatHandler::HandleModifyHPCommand(char* args) -{ - if (!*args) - { - return false; - } - - int32 hp = atoi(args); - int32 hpm = atoi(args); - - if (hp <= 0 || hpm <= 0 || 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; - } - - // check online security - if (HasLowerSecurity(chr)) - { - 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(char* args) -{ - if (!*args) - { - return false; - } - - int32 mana = atoi(args); - int32 manam = atoi(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)) - { - 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(char* args) -{ - if (!*args) - { - return false; - } - - int32 energy = atoi(args) * 10; - int32 energym = atoi(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)) - { - return false; - } + Group* grp = target->GetGroup(); - 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); - } + std::string nameLink = GetNameLink(target); - chr->SetMaxPower(POWER_ENERGY, energym); - chr->SetPower(POWER_ENERGY, energy); - - DETAIL_LOG(GetMangosString(LANG_CURRENT_ENERGY), chr->GetMaxPower(POWER_ENERGY)); - - return true; -} - -// Edit Player Rage -bool ChatHandler::HandleModifyRageCommand(char* args) -{ - if (!*args) - { - return false; - } - - int32 rage = atoi(args) * 10; - int32 ragem = atoi(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)) - { - 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 Faction -bool ChatHandler::HandleModifyFactionCommand(char* args) -{ - Creature* chr = getSelectedCreature(); - if (!chr) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (!*args) - { - 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; - if (!ExtractUint32KeyFromLink(&args, "Hfaction", factionid)) - { - return false; - } - - if (!sFactionTemplateStore.LookupEntry(factionid)) - { - PSendSysMessage(LANG_WRONG_FACTION, factionid); - SetSentErrorMessage(true); - return false; - } - - uint32 flag; - if (!ExtractOptUInt32(&args, flag, chr->GetUInt32Value(UNIT_FIELD_FLAGS))) - { - return false; - } - - uint32 npcflag; - if (!ExtractOptUInt32(&args, npcflag, chr->GetUInt32Value(UNIT_NPC_FLAGS))) - { - return false; - } - - uint32 dyflag; - if (!ExtractOptUInt32(&args, dyflag, chr->GetUInt32Value(UNIT_DYNAMIC_FLAGS))) - { - 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 TP -bool ChatHandler::HandleModifyTalentCommand(char* args) -{ - if (!*args) - { - return false; - } - - int tp = atoi(args); - if (tp < 0) - { - return false; - } - - Player* target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target)) - { - return false; - } - - target->SetFreeTalentPoints(tp); - return true; -} - -// Enable On\OFF all taxi paths -bool ChatHandler::HandleTaxiCheatCommand(char* args) -{ - bool value; - if (!ExtractOnOff(&args, value)) - { - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; - } - - Player* chr = getSelectedPlayer(); - if (!chr) - { - chr = m_session->GetPlayer(); - } - // check online security - else if (HasLowerSecurity(chr)) - { - return false; - } - - if (value) - { - 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()); - } - } - else - { - 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; -} - -// Edit Player Aspeed -bool ChatHandler::HandleModifyASpeedCommand(char* args) -{ - if (!*args) - { - return false; - } - - float modSpeed = (float)atof(args); - - if (modSpeed > sWorld.getConfig(CONFIG_UINT32_GM_MAX_SPEED_FACTOR) || modSpeed < 0.1) - { - 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)) - { - return false; - } - - std::string chrNameLink = GetNameLink(chr); - - if (chr->IsTaxiFlying()) - { - PSendSysMessage(LANG_CHAR_IN_FLIGHT, chrNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_YOU_CHANGE_ASPEED, modSpeed, chrNameLink.c_str()); - if (needReportToTarget(chr)) - { - ChatHandler(chr).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, GetNameLink().c_str(), modSpeed); - } - - chr->UpdateSpeed(MOVE_WALK, true, modSpeed); - chr->UpdateSpeed(MOVE_RUN, true, modSpeed); - chr->UpdateSpeed(MOVE_SWIM, true, modSpeed); - // chr->UpdateSpeed(MOVE_TURN, true, modSpeed); - chr->UpdateSpeed(MOVE_FLIGHT, true, modSpeed); - return true; -} - -// Edit Player Speed -bool ChatHandler::HandleModifySpeedCommand(char* args) -{ - if (!*args) - { - return false; - } - - float modSpeed = (float)atof(args); - - if (modSpeed > sWorld.getConfig(CONFIG_UINT32_GM_MAX_SPEED_FACTOR) || modSpeed < 0.1) - { - 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)) - { - return false; - } - - std::string chrNameLink = GetNameLink(chr); - - if (chr->IsTaxiFlying()) - { - PSendSysMessage(LANG_CHAR_IN_FLIGHT, chrNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_YOU_CHANGE_SPEED, modSpeed, chrNameLink.c_str()); - if (needReportToTarget(chr)) - { - ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, GetNameLink().c_str(), modSpeed); - } - - chr->UpdateSpeed(MOVE_RUN, true, modSpeed); - - return true; -} - -// Edit Player Swim Speed -bool ChatHandler::HandleModifySwimCommand(char* args) -{ - if (!*args) - { - return false; - } - - float modSpeed = (float)atof(args); - - if (modSpeed > sWorld.getConfig(CONFIG_UINT32_GM_MAX_SPEED_FACTOR) || modSpeed < 0.01f) - { - 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)) - { - return false; - } - - std::string chrNameLink = GetNameLink(chr); - - if (chr->IsTaxiFlying()) - { - PSendSysMessage(LANG_CHAR_IN_FLIGHT, chrNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, modSpeed, chrNameLink.c_str()); - if (needReportToTarget(chr)) - { - ChatHandler(chr).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, GetNameLink().c_str(), modSpeed); - } - - chr->UpdateSpeed(MOVE_SWIM, true, modSpeed); - - return true; -} - -// Edit Player Walk Speed -bool ChatHandler::HandleModifyBWalkCommand(char* args) -{ - if (!*args) - { - return false; - } - - float modSpeed = (float)atof(args); - - if (modSpeed > sWorld.getConfig(CONFIG_UINT32_GM_MAX_SPEED_FACTOR) || modSpeed < 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)) - { - return false; - } - - std::string chrNameLink = GetNameLink(chr); - - if (chr->IsTaxiFlying()) - { - PSendSysMessage(LANG_CHAR_IN_FLIGHT, chrNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, modSpeed, chrNameLink.c_str()); - if (needReportToTarget(chr)) - { - ChatHandler(chr).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, GetNameLink().c_str(), modSpeed); - } - - chr->UpdateSpeed(MOVE_RUN_BACK, true, modSpeed); - - return true; -} - -// Edit Player Fly -bool ChatHandler::HandleModifyFlyCommand(char* args) -{ - if (!*args) - { - return false; - } - - float modSpeed = (float)atof(args); - - if (modSpeed > 10.0f || modSpeed < 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)) - { - return false; - } - - PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, modSpeed, GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) - { - ChatHandler(chr).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, GetNameLink().c_str(), modSpeed); - } - - chr->UpdateSpeed(MOVE_FLIGHT, true, modSpeed); - - return true; -} - -// Edit Player Scale -bool ChatHandler::HandleModifyScaleCommand(char* args) -{ - if (!*args) - { - return false; - } - - float Scale = (float)atof(args); - if (Scale > 10.0f || Scale <= 0.0f) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Unit* target = getSelectedUnit(); - if (target == NULL) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (target->GetTypeId() == TYPEID_PLAYER) - { - // check online security - if (HasLowerSecurity((Player*)target)) - { - return false; - } - - PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, GetNameLink((Player*)target).c_str()); - if (needReportToTarget((Player*)target)) - { - ChatHandler((Player*)target).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, GetNameLink().c_str(), Scale); - } - } - - target->SetObjectScale(Scale); - target->UpdateModelData(); - - return true; -} - -// Enable Player mount -bool ChatHandler::HandleModifyMountCommand(char* args) -{ - if (!*args) - { - return false; - } - - uint16 mId = 1147; - float speed = (float)15; - uint32 num = atoi(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) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr)) - { - 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 << 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 << chr->GetPackGUID(); - data << (uint32)0; - data << float(speed); - chr->SendMessageToSet(&data, true); - - return true; -} - -// Edit Player money -bool ChatHandler::HandleModifyMoneyCommand(char* args) -{ - if (!*args) + if (!grp) { + PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); + SetSentErrorMessage(true); return false; } - Player* chr = getSelectedPlayer(); - if (chr == NULL) + Player* player = m_session->GetPlayer(); + Map* gmMap = player->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 && ( + !player->GetGroup() || (grp->GetLeaderGuid() != player->GetObjectGuid()) || + (player->GetGroup()->GetLeaderGuid() != player->GetObjectGuid()))) + // the last check is a bit excessive, but let it be, just in case { - SendSysMessage(LANG_NO_CHAR_SELECTED); + SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); SetSentErrorMessage(true); return false; } - // check online security - if (HasLowerSecurity(chr)) + for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { - return false; - } + Player* pl = itr->getSource(); - int32 addmoney = atoi(args); + if (!pl || pl == m_session->GetPlayer() || !pl->GetSession()) + { + continue; + } - uint32 moneyuser = chr->GetMoney(); + // check online security + if (HasLowerSecurity(pl)) + { + return false; + } - if (addmoney < 0) - { - int32 newmoney = int32(moneyuser) + addmoney; + std::string plNameLink = GetNameLink(pl); - DETAIL_LOG(GetMangosString(LANG_CURRENT_MONEY), moneyuser, addmoney, newmoney); - if (newmoney <= 0) + if (pl->IsBeingTeleported() == true) { - 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); + PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); + SetSentErrorMessage(true); + return false; } - else + + if (to_instance) { - if (newmoney > MAX_MONEY_AMOUNT) - { - newmoney = MAX_MONEY_AMOUNT; - } + Map* plMap = pl->GetMap(); - PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) + if (plMap->Instanceable() && plMap->GetInstanceId() != gmMap->GetInstanceId()) { - ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, GetNameLink().c_str(), abs(addmoney)); + // can not summon from instance to instance + PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, plNameLink.c_str()); + SetSentErrorMessage(true); + return false; } - chr->SetMoney(newmoney); } - } - else - { - PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) + + PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(), ""); + if (needReportToTarget(pl)) { - ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, GetNameLink().c_str(), addmoney); + ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, nameLink.c_str()); } - if (addmoney >= MAX_MONEY_AMOUNT) + // stop flight if need + if (pl->IsTaxiFlying()) { - chr->SetMoney(MAX_MONEY_AMOUNT); + pl->GetMotionMaster()->MovementExpired(); + pl->m_taxi.ClearTaxiDestinations(); } + // save only in non-flight case else { - chr->ModifyMoney(addmoney); + pl->SaveRecallPosition(); } - } - DETAIL_LOG(GetMangosString(LANG_NEW_MONEY), moneyuser, addmoney, chr->GetMoney()); + // before GM + float x, y, z; + m_session->GetPlayer()->GetClosePoint(x, y, z, pl->GetObjectBoundingRadius()); + pl->TeleportTo(m_session->GetPlayer()->GetMapId(), x, y, z, pl->GetOrientation()); + } return true; } -bool ChatHandler::HandleModifyHonorCommand(char* args) +// Teleport player to last position +bool ChatHandler::HandleRecallCommand(char* args) { - if (!*args) + Player* target; + if (!ExtractPlayerTarget(&args, &target)) { return false; } - Player* target = getSelectedPlayer(); - if (!target) + // check online security + if (HasLowerSecurity(target)) { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); return false; } - // check online security - if (HasLowerSecurity(target)) + if (target->IsBeingTeleported()) { + PSendSysMessage(LANG_IS_TELEPORTED, GetNameLink(target).c_str()); + SetSentErrorMessage(true); return false; } - int32 amount = (int32)atoi(args); - - target->ModifyHonorPoints(amount); - - PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, GetNameLink(target).c_str(), target->GetHonorPoints()); - - return true; + return HandleGoHelper(target, target->m_recallMap, target->m_recallX, target->m_recallY, &target->m_recallZ, &target->m_recallO); } -bool ChatHandler::HandleTeleCommand(char* args) +bool ChatHandler::HandleGPSCommand(char* args) { - if (!*args) + WorldObject* obj = NULL; + if (*args) { - return false; + if (ObjectGuid guid = ExtractGuidFromLink(&args)) + { + obj = (WorldObject*)m_session->GetPlayer()->GetObjectByTypeMask(guid, TYPEMASK_CREATURE_OR_GAMEOBJECT); + } + + if (!obj) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } } + else + { + obj = getSelectedUnit(); - Player* _player = m_session->GetPlayer(); + if (!obj) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + } + CellPair cell_val = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + Cell cell(cell_val); - // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r - GameTele const* tele = ExtractGameTeleFromLink(&args); + uint32 zone_id, area_id; + obj->GetZoneAndAreaId(zone_id, area_id); - if (!tele) - { - SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); - SetSentErrorMessage(true); - return false; - } + MapEntry const* mapEntry = sMapStore.LookupEntry(obj->GetMapId()); + AreaTableEntry const* zoneEntry = GetAreaEntryByAreaID(zone_id); + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(area_id); - return HandleGoHelper(_player, tele->mapId, tele->position_x, tele->position_y, &tele->position_z, &tele->orientation); -} + float zone_x = obj->GetPositionX(); + float zone_y = obj->GetPositionY(); -bool ChatHandler::HandleLookupAreaCommand(char* args) -{ - if (!*args) + if (!Map2ZoneCoordinates(zone_x, zone_y, zone_id)) { - return false; + zone_x = 0; + zone_y = 0; } - std::string namepart = args; - std::wstring wnamepart; + 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 = MaNGOS::ComputeGridPair(obj->GetPositionX(), obj->GetPositionY()); + + int gx = 63 - p.x_coord; + int gy = 63 - p.y_coord; + + uint32 have_map = GridMap::ExistMap(obj->GetMapId(), gx, gy) ? 1 : 0; + uint32 have_vmap = GridMap::ExistVMap(obj->GetMapId(), gx, gy) ? 1 : 0; + + TerrainInfo const* terrain = obj->GetTerrain(); - if (!Utf8toWStr(namepart, wnamepart)) + if (have_vmap) { - return false; + if (terrain->IsOutdoors(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ())) + { + PSendSysMessage("You are OUTdoor"); + } + else + { + PSendSysMessage("You are INdoor"); + } + } + else + { + PSendSysMessage("no VMAP available for area info"); } - uint32 counter = 0; // Counter for figure out that we found smth. + PSendSysMessage(LANG_MAP_POSITION, + obj->GetMapId(), (mapEntry ? mapEntry->name[GetSessionDbcLocale()] : ""), + zone_id, (zoneEntry ? zoneEntry->area_name[GetSessionDbcLocale()] : ""), + area_id, (areaEntry ? areaEntry->area_name[GetSessionDbcLocale()] : ""), + 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); + + DEBUG_LOG("Player %s GPS call for %s '%s' (%s: %u):", + m_session ? GetNameLink().c_str() : GetMangosString(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())); - // converting string that we try to find to lower case - wstrToLower(wnamepart); + DEBUG_LOG(GetMangosString(LANG_MAP_POSITION), + obj->GetMapId(), (mapEntry ? mapEntry->name[sWorld.GetDefaultDbcLocale()] : ""), + zone_id, (zoneEntry ? zoneEntry->area_name[sWorld.GetDefaultDbcLocale()] : ""), + area_id, (areaEntry ? areaEntry->area_name[sWorld.GetDefaultDbcLocale()] : ""), + 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); - // Search in AreaTable.dbc - for (uint32 areaid = 0; areaid <= sAreaStore.GetNumRows(); ++areaid) + GridMapLiquidData liquid_status; + GridMapLiquidStatus res = terrain->getLiquidStatus(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), MAP_ALL_LIQUIDS, &liquid_status); + if (res) { - AreaTableEntry const* areaEntry = sAreaStore.LookupEntry(areaid); - if (areaEntry) - { - int loc = GetSessionDbcLocale(); - std::string name = areaEntry->area_name[loc]; - if (name.empty()) - { - continue; - } + PSendSysMessage(LANG_LIQUID_STATUS, liquid_status.level, liquid_status.depth_level, liquid_status.type_flags, res); + } - if (!Utf8FitTo(name, wnamepart)) - { - loc = 0; - for (; loc < MAX_LOCALE; ++loc) - { - if (loc == GetSessionDbcLocale()) - { - continue; - } + // Additional vmap debugging help +#ifdef _DEBUG_VMAPS + PSendSysMessage("Static terrain height (maps only): %f", obj->GetTerrain()->GetHeightStatic(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), false)); - name = areaEntry->area_name[loc]; - if (name.empty()) - { - continue; - } + if (VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager()) + { + PSendSysMessage("Vmap Terrain Height %f", vmgr->getHeight(obj->GetMapId(), obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ() + 2.0f, 10000.0f)); + } - if (Utf8FitTo(name, wnamepart)) - { - break; - } - } - } + PSendSysMessage("Static map height (maps and vmaps): %f", obj->GetTerrain()->GetHeightStatic(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ())); +#endif - 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]; - } + return true; +} - SendSysMessage(ss.str().c_str()); +bool ChatHandler::HandleGetDistanceCommand(char* args) +{ + WorldObject* obj = NULL; - ++counter; - } + if (*args) + { + if (ObjectGuid guid = ExtractGuidFromLink(&args)) + { + obj = (WorldObject*)m_session->GetPlayer()->GetObjectByTypeMask(guid, TYPEMASK_CREATURE_OR_GAMEOBJECT); } - } - if (counter == 0) // if counter == 0 then we found nth + if (!obj) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + } + else { - SendSysMessage(LANG_COMMAND_NOAREAFOUND); + obj = getSelectedUnit(); + + if (!obj) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } } + Player* player = m_session->GetPlayer(); + // Calculate point-to-point distance + float dx, dy, dz; + dx = player->GetPositionX() - obj->GetPositionX(); + dy = player->GetPositionY() - obj->GetPositionY(); + dz = player->GetPositionZ() - obj->GetPositionZ(); + + PSendSysMessage(LANG_DISTANCE, player->GetDistance(obj), player->GetDistance2d(obj), sqrt(dx * dx + dy * dy + dz * dz)); + return true; } -// Find tele in game_tele order by name -bool ChatHandler::HandleLookupTeleCommand(char* args) +bool ChatHandler::HandleNearGraveCommand(char* args) { + Team g_team; + + size_t argslen = strlen(args); + if (!*args) { - SendSysMessage(LANG_COMMAND_TELE_PARAMETER); - SetSentErrorMessage(true); - return false; + g_team = TEAM_BOTH_ALLOWED; } - - std::string namepart = args; - std::wstring wnamepart; - - if (!Utf8toWStr(namepart, wnamepart)) + else if (strncmp(args, "horde", argslen) == 0) + { + g_team = HORDE; + } + else if (strncmp(args, "alliance", argslen) == 0) + { + g_team = ALLIANCE; + } + else { return false; } - // converting string that we try to find to lower case - wstrToLower(wnamepart); + Player* player = m_session->GetPlayer(); + uint32 zone_id = player->GetZoneId(); - std::ostringstream reply; + WorldSafeLocsEntry const* graveyard = sObjectMgr.GetClosestGraveYard(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), g_team); - GameTeleMap const& teleMap = sObjectMgr.GetGameTeleMap(); - for (GameTeleMap::const_iterator itr = teleMap.begin(); itr != teleMap.end(); ++itr) + if (graveyard) { - GameTele const* tele = &itr->second; + uint32 g_id = graveyard->ID; - if (tele->wnameLow.find(wnamepart) == std::wstring::npos) + GraveYardData const* data = sObjectMgr.FindGraveYardData(g_id, zone_id); + if (!data) { - continue; + PSendSysMessage(LANG_COMMAND_GRAVEYARDERROR, g_id); + SetSentErrorMessage(true); + return false; } - if (m_session) + std::string team_name; + + if (data->team == TEAM_BOTH_ALLOWED) { - reply << " |cffffffff|Htele:" << itr->first << "|h[" << tele->name << "]|h|r\n"; + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ANY); } - else + else if (data->team == HORDE) { - reply << " " << itr->first << " " << tele->name << "\n"; + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_HORDE); + } + else if (data->team == ALLIANCE) + { + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ALLIANCE); + } + else // Actually, this case can not happen + { + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_NOTEAM); } - } - if (reply.str().empty()) - { - SendSysMessage(LANG_COMMAND_TELE_NOLOCATION); + PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, g_id, team_name.c_str(), zone_id); } else { - PSendSysMessage(LANG_COMMAND_TELE_LOCATION, reply.str().c_str()); + std::string team_name; + + if (g_team == TEAM_BOTH_ALLOWED) + { + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ANY); + } + else if (g_team == HORDE) + { + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_HORDE); + } + else if (g_team == ALLIANCE) + { + team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ALLIANCE); + } + + if (g_team == TEAM_BOTH_ALLOWED) + { + PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, zone_id); + } + else + { + PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, zone_id, team_name.c_str()); + } } return true; } -// Enable\Dissable accept whispers (for GM) -bool ChatHandler::HandleWhispersCommand(char* args) +/********************************************************************** + CommandTable : goCommandTable +/***********************************************************************/ + +bool ChatHandler::HandleGoTaxinodeCommand(char* args) { - if (!*args) - { - PSendSysMessage(LANG_COMMAND_WHISPERACCEPTING, GetOnOffStr(m_session->GetPlayer()->isAcceptWhispers())); - return true; - } + Player* _player = m_session->GetPlayer(); - bool value; - if (!ExtractOnOff(&args, value)) + uint32 nodeId; + if (!ExtractUint32KeyFromLink(&args, "Htaxinode", nodeId)) { - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); return false; } - // whisper on - if (value) - { - m_session->GetPlayer()->SetAcceptWhispers(true); - SendSysMessage(LANG_COMMAND_WHISPERON); - } - // whisper off - else - { - m_session->GetPlayer()->SetAcceptWhispers(false); - SendSysMessage(LANG_COMMAND_WHISPEROFF); - } - - return true; -} - -// Save all players in the world -bool ChatHandler::HandleSaveAllCommand(char* /*args*/) -{ - sObjectAccessor.SaveAllPlayers(); - SendSysMessage(LANG_PLAYERS_SAVED); - return true; -} - -// Send mail by command -bool ChatHandler::HandleSendMailCommand(char* args) -{ - // format: name "subject text" "mail text" - Player* target; - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) + TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(nodeId); + if (!node) { + PSendSysMessage(LANG_COMMAND_GOTAXINODENOTFOUND, nodeId); + SetSentErrorMessage(true); return false; } - MailDraft draft; - - // fill draft - if (!HandleSendMailHelper(draft, args)) + if (node->x == 0.0f && node->y == 0.0f && node->z == 0.0f) { + PSendSysMessage(LANG_INVALID_TARGET_COORD, node->x, node->y, node->map_id); + SetSentErrorMessage(true); return false; } - // from console show nonexistent sender - MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM); - - draft.SendMailTo(MailReceiver(target, target_guid), sender); - - std::string nameLink = playerLink(target_name); - PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); - return true; + return HandleGoHelper(_player, node->map_id, node->x, node->y, &node->z); } -// teleport player to given game_tele.entry -bool ChatHandler::HandleTeleNameCommand(char* args) +bool ChatHandler::HandleGoCommand(char* args) { - char* nameStr = ExtractOptNotLastArg(&args); - - Player* target; - ObjectGuid target_guid; - std::string target_name; - if (!ExtractPlayerTarget(&nameStr, &target, &target_guid, &target_name)) + if (!*args) { return false; } - // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r - GameTele const* tele = ExtractGameTeleFromLink(&args); - if (!tele) - { - SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); - SetSentErrorMessage(true); - return false; - } + Player* _player = m_session->GetPlayer(); - if (target) + uint32 mapid; + float x, y, z; + + // raw coordinates case + if (ExtractFloat(&args, x)) { - // check online security - if (HasLowerSecurity(target)) + if (!ExtractFloat(&args, y)) { return false; } - std::string chrNameLink = playerLink(target_name); - - if (target->IsBeingTeleported() == true) + if (!ExtractFloat(&args, z)) { - 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)) + if (!ExtractOptUInt32(&args, mapid, _player->GetMapId())) { - ChatHandler(target).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetNameLink().c_str()); + return false; } - - return HandleGoHelper(target, tele->mapId, tele->position_x, tele->position_y, &tele->position_z, &tele->orientation); } - else + // link case + else if (!ExtractLocationFromLink(&args, mapid, x, y, z)) { - // check offline security - if (HasLowerSecurity(NULL, target_guid)) - { - return false; - } + return false; + } - std::string nameLink = playerLink(target_name); + return HandleGoHelper(_player, mapid, x, y, &z); +} - PSendSysMessage(LANG_TELEPORTING_TO, nameLink.c_str(), GetMangosString(LANG_OFFLINE), tele->name.c_str()); - Player::SavePositionInDB(target_guid, tele->mapId, - tele->position_x, tele->position_y, tele->position_z, tele->orientation, - sTerrainMgr.GetZoneId(tele->mapId, tele->position_x, tele->position_y, tele->position_z)); +// teleport at coordinates +bool ChatHandler::HandleGoXYCommand(char* args) +{ + Player* _player = m_session->GetPlayer(); + + float x; + if (!ExtractFloat(&args, x)) + { + return false; } - return true; + float y; + if (!ExtractFloat(&args, y)) + { + return false; + } + + uint32 mapid; + if (!ExtractOptUInt32(&args, mapid, _player->GetMapId())) + { + return false; + } + + return HandleGoHelper(_player, mapid, x, y); } -// Teleport group to given game_tele.entry -bool ChatHandler::HandleTeleGroupCommand(char* args) +// teleport at coordinates, including Z +bool ChatHandler::HandleGoXYZCommand(char* args) { - if (!*args) + Player* _player = m_session->GetPlayer(); + + float x; + if (!ExtractFloat(&args, x)) { return false; } - Player* player = getSelectedPlayer(); - if (!player) + float y; + if (!ExtractFloat(&args, y)) { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); return false; } - // check online security - if (HasLowerSecurity(player)) + float z; + if (!ExtractFloat(&args, z)) { return false; } - // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r - GameTele const* tele = ExtractGameTeleFromLink(&args); - if (!tele) + uint32 mapid; + if (!ExtractOptUInt32(&args, mapid, _player->GetMapId())) { - SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); - SetSentErrorMessage(true); return false; } - std::string nameLink = GetNameLink(player); + return HandleGoHelper(_player, mapid, x, y, &z); +} - Group* grp = player->GetGroup(); - if (!grp) +// teleport at coordinates +bool ChatHandler::HandleGoZoneXYCommand(char* args) +{ + Player* _player = m_session->GetPlayer(); + + float x; + if (!ExtractFloat(&args, x)) { - PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); - SetSentErrorMessage(true); return false; } - for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + float y; + if (!ExtractFloat(&args, y)) { - Player* pl = itr->getSource(); - - if (!pl || !pl->GetSession()) - { - continue; - } + return false; + } - // check online security - if (HasLowerSecurity(pl)) + uint32 areaid; + if (*args) + { + if (!ExtractUint32KeyFromLink(&args, "Harea", areaid)) { return false; } + } + else + { + areaid = _player->GetZoneId(); + } - std::string plNameLink = GetNameLink(pl); + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaid); - if (pl->IsBeingTeleported()) - { - PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); - continue; - } + if (x < 0 || x > 100 || y < 0 || y > 100 || !areaEntry) + { + PSendSysMessage(LANG_INVALID_ZONE_COORD, x, y, areaid); + SetSentErrorMessage(true); + return false; + } - PSendSysMessage(LANG_TELEPORTING_TO, plNameLink.c_str(), "", tele->name.c_str()); - if (needReportToTarget(pl)) - { - ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, nameLink.c_str()); - } + // update to parent zone if exist (client map show only zones without parents) + AreaTableEntry const* zoneEntry = areaEntry->zone ? GetAreaEntryByAreaID(areaEntry->zone) : areaEntry; - // stop flight if need - if (pl->IsTaxiFlying()) - { - pl->GetMotionMaster()->MovementExpired(); - pl->m_taxi.ClearTaxiDestinations(); - } - // save only in non-flight case - else - { - pl->SaveRecallPosition(); - } + MapEntry const* mapEntry = sMapStore.LookupEntry(zoneEntry->mapid); - pl->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); + if (mapEntry->Instanceable()) + { + PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->area_name[GetSessionDbcLocale()], + mapEntry->MapID, mapEntry->name[GetSessionDbcLocale()]); + SetSentErrorMessage(true); + return false; } - return true; + if (!Zone2MapCoordinates(x, y, zoneEntry->ID)) + { + PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->area_name[GetSessionDbcLocale()], + mapEntry->MapID, mapEntry->name[GetSessionDbcLocale()]); + SetSentErrorMessage(true); + return false; + } + + return HandleGoHelper(_player, mapEntry->MapID, x, y); } -// Summon group of player -bool ChatHandler::HandleGroupgoCommand(char* args) +// teleport to grid +bool ChatHandler::HandleGoGridCommand(char* args) { - Player* target; - if (!ExtractPlayerTarget(&args, &target)) + Player* _player = m_session->GetPlayer(); + + float grid_x; + if (!ExtractFloat(&args, grid_x)) { return false; } - // check online security - if (HasLowerSecurity(target)) + float grid_y; + if (!ExtractFloat(&args, grid_y)) { return false; } - Group* grp = target->GetGroup(); + uint32 mapid; + if (!ExtractOptUInt32(&args, mapid, _player->GetMapId())) + { + return false; + } - std::string nameLink = GetNameLink(target); + // 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 (!grp) + return HandleGoHelper(_player, mapid, x, y); +} + +/** \brief Teleport the GM to the specified creature +* +* .go creature --> TP using creature.guid +* .go creature 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. +* .go creature 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(char* args) +{ + if (!*args) { - PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); - SetSentErrorMessage(true); return false; } - Player* player = m_session->GetPlayer(); - Map* gmMap = player->GetMap(); - bool to_instance = gmMap->Instanceable(); + Player* _player = m_session->GetPlayer(); - // we are in instance, and can summon only player in our group with us as lead - if (to_instance && ( - !player->GetGroup() || (grp->GetLeaderGuid() != player->GetObjectGuid()) || - (player->GetGroup()->GetLeaderGuid() != player->GetObjectGuid()))) - // the last check is a bit excessive, but let it be, just in case + // "id" or number or [name] Shift-click form |color|Hcreature:creature_id|h[name]|h|r + int crType; + char* pParam1 = ExtractKeyFromLink(&args, creatureKeys, &crType); + if (!pParam1) { - SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); - SetSentErrorMessage(true); return false; } - for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + // User wants to teleport to the NPC's template entry + if (crType == CREATURE_LINK_RAW && strcmp(pParam1, "id") == 0) { - Player* pl = itr->getSource(); - - if (!pl || pl == m_session->GetPlayer() || !pl->GetSession()) - { - continue; - } - - // check online security - if (HasLowerSecurity(pl)) + // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + pParam1 = ExtractKeyFromLink(&args, "Hcreature_entry"); + if (!pParam1) { return false; } - std::string plNameLink = GetNameLink(pl); + crType = CREATURE_LINK_ENTRY; + } - if (pl->IsBeingTeleported() == true) - { - PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } + CreatureData const* data = NULL; - if (to_instance) + switch (crType) + { + case CREATURE_LINK_ENTRY: { - Map* plMap = pl->GetMap(); + uint32 tEntry; + if (!ExtractUInt32(&pParam1, tEntry)) + { + return false; + } - if (plMap->Instanceable() && plMap->GetInstanceId() != gmMap->GetInstanceId()) + if (!tEntry) { - // can not summon from instance to instance - PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, plNameLink.c_str()); + return false; + } + + if (!ObjectMgr::GetCreatureTemplate(tEntry)) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); SetSentErrorMessage(true); return false; } - } - PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(), ""); - if (needReportToTarget(pl)) - { - ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, nameLink.c_str()); - } + FindCreatureData worker(tEntry, m_session ? m_session->GetPlayer() : NULL); - // stop flight if need - if (pl->IsTaxiFlying()) - { - pl->GetMotionMaster()->MovementExpired(); - pl->m_taxi.ClearTaxiDestinations(); + sObjectMgr.DoCreatureData(worker); + + CreatureDataPair const* dataPair = worker.GetResult(); + if (!dataPair) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + data = &dataPair->second; + break; } - // save only in non-flight case - else + case CREATURE_LINK_GUID: { - pl->SaveRecallPosition(); + uint32 lowguid; + if (!ExtractUInt32(&pParam1, lowguid)) + { + return false; + } + + data = sObjectMgr.GetCreatureData(lowguid); + if (!data) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } + break; } + case CREATURE_LINK_RAW: + { + uint32 lowguid; + if (ExtractUInt32(&pParam1, lowguid)) + { + data = sObjectMgr.GetCreatureData(lowguid); + if (!data) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } + } + // Number is invalid - maybe the user specified the mob's name + else + { + std::string name = pParam1; + WorldDatabase.escape_string(name); + QueryResult* result = WorldDatabase.PQuery("SELECT `guid` FROM `creature`, `creature_template` WHERE `creature`.`id` = `creature_template`.`entry` AND `creature_template`.`name` " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), name.c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } - // before GM - float x, y, z; - m_session->GetPlayer()->GetClosePoint(x, y, z, pl->GetObjectBoundingRadius()); - pl->TeleportTo(m_session->GetPlayer()->GetMapId(), x, y, z, pl->GetOrientation()); + FindCreatureData worker(0, m_session ? m_session->GetPlayer() : NULL); + + do + { + Field* fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + + CreatureDataPair const* cr_data = sObjectMgr.GetCreatureDataPair(guid); + if (!cr_data) + { + continue; + } + + worker(*cr_data); + } + while (result->NextRow()); + + delete result; + + CreatureDataPair const* dataPair = worker.GetResult(); + if (!dataPair) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + data = &dataPair->second; + } + break; + } } - return true; + return HandleGoHelper(_player, data->mapid, data->posX, data->posY, &data->posZ); } -bool ChatHandler::HandleGoHelper(Player* player, uint32 mapid, float x, float y, float const* zPtr, float const* ortPtr) +// teleport to gameobject +bool ChatHandler::HandleGoObjectCommand(char* args) { - float z; - float ort = player->GetOrientation(); + Player* _player = m_session->GetPlayer(); - if (zPtr) + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + int goType; + char* pParam1 = ExtractKeyFromLink(&args, gameobjectKeys, &goType); + if (!pParam1) { - z = *zPtr; - - if (ortPtr) - { - ort = *ortPtr; - } + return false; + } - // check full provided coordinates - if (!MapManager::IsValidMapCoord(mapid, x, y, z, ort)) + // User wants to teleport to the GO's template entry + if (goType == GAMEOBJECT_LINK_RAW && strcmp(pParam1, "id") == 0) + { + // number or [name] Shift-click form |color|Hgameobject_entry:creature_id|h[name]|h|r + pParam1 = ExtractKeyFromLink(&args, "Hgameobject_entry"); + if (!pParam1) { - PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapid); - SetSentErrorMessage(true); return false; } + + goType = GAMEOBJECT_LINK_ENTRY; } - else + + GameObjectData const* data = NULL; + + switch (goType) { - // we need check x,y before ask Z or can crash at invalide coordinates - if (!MapManager::IsValidMapCoord(mapid, x, y)) + case CREATURE_LINK_ENTRY: { - PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapid); - SetSentErrorMessage(true); - return false; + uint32 tEntry; + if (!ExtractUInt32(&pParam1, tEntry)) + { + return false; + } + + if (!tEntry) + { + return false; + } + + if (!ObjectMgr::GetGameObjectInfo(tEntry)) + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + FindGOData worker(tEntry, m_session ? m_session->GetPlayer() : NULL); + + sObjectMgr.DoGOData(worker); + + GameObjectDataPair const* dataPair = worker.GetResult(); + + if (!dataPair) + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + data = &dataPair->second; + break; + } + case GAMEOBJECT_LINK_GUID: + { + uint32 lowguid; + if (!ExtractUInt32(&pParam1, lowguid)) + { + return false; + } + + // by DB guid + data = sObjectMgr.GetGOData(lowguid); + if (!data) + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + break; } + case GAMEOBJECT_LINK_RAW: + { + uint32 lowguid; + if (ExtractUInt32(&pParam1, lowguid)) + { + // by DB guid + data = sObjectMgr.GetGOData(lowguid); + if (!data) + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + } + else + { + std::string name = pParam1; + WorldDatabase.escape_string(name); + QueryResult* result = WorldDatabase.PQuery("SELECT `guid` FROM `gameobject`, `gameobject_template` WHERE `gameobject`.`id` = `gameobject_template`.`entry` AND `gameobject_template`.`name `" _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), name.c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } - TerrainInfo const* map = sTerrainMgr.LoadTerrain(mapid); - z = map->GetWaterOrGroundLevel(x, y, MAX_HEIGHT); + FindGOData worker(0, m_session ? m_session->GetPlayer() : NULL); + + do + { + Field* fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + + GameObjectDataPair const* go_data = sObjectMgr.GetGODataPair(guid); + if (!go_data) + { + continue; + } + + worker(*go_data); + } + while (result->NextRow()); + + delete result; + + GameObjectDataPair const* dataPair = worker.GetResult(); + if (!dataPair) + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + data = &dataPair->second; + } + break; + } } - // stop flight if need - if (player->IsTaxiFlying()) + return HandleGoHelper(_player, data->mapid, data->posX, data->posY, &data->posZ); +} + +bool ChatHandler::HandleGoGraveyardCommand(char* args) +{ + Player* _player = m_session->GetPlayer(); + + uint32 gyId; + if (!ExtractUInt32(&args, gyId)) { - player->GetMotionMaster()->MovementExpired(); - player->m_taxi.ClearTaxiDestinations(); + return false; } - // save only in non-flight case - else + + WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(gyId); + if (!gy) { - player->SaveRecallPosition(); + PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST, gyId); + SetSentErrorMessage(true); + return false; } - player->TeleportTo(mapid, x, y, z, ort); - - return true; + return HandleGoHelper(_player, gy->map_id, gy->x, gy->y, &gy->z); } -bool ChatHandler::HandleGoTaxinodeCommand(char* args) +bool ChatHandler::HandleGoTriggerCommand(char* args) { Player* _player = m_session->GetPlayer(); - uint32 nodeId; - if (!ExtractUint32KeyFromLink(&args, "Htaxinode", nodeId)) + if (!*args) { return false; } - TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(nodeId); - if (!node) + char* atIdStr = ExtractKeyFromLink(&args, areatriggerKeys); + if (!atIdStr) { - PSendSysMessage(LANG_COMMAND_GOTAXINODENOTFOUND, nodeId); - SetSentErrorMessage(true); return false; } - if (node->x == 0.0f && node->y == 0.0f && node->z == 0.0f) + uint32 atId; + if (!ExtractUInt32(&atIdStr, atId)) { - PSendSysMessage(LANG_INVALID_TARGET_COORD, node->x, node->y, node->map_id); - SetSentErrorMessage(true); return false; } - return HandleGoHelper(_player, node->map_id, node->x, node->y, &node->z); -} - -bool ChatHandler::HandleGoCommand(char* args) -{ - if (!*args) + if (!atId) { return false; } - Player* _player = m_session->GetPlayer(); - - uint32 mapid; - float x, y, z; + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(atId); + if (!atEntry) + { + PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND, atId); + SetSentErrorMessage(true); + return false; + } - // raw coordinates case - if (ExtractFloat(&args, x)) + bool to_target = ExtractLiteralArg(&args, "target"); + if (!to_target && *args) // can be fail also at syntax error { - if (!ExtractFloat(&args, y)) - { - return false; - } + return false; + } - if (!ExtractFloat(&args, z)) + if (to_target) + { + AreaTrigger const* at = sObjectMgr.GetAreaTrigger(atId); + if (!at) { + PSendSysMessage(LANG_AREATRIGER_NOT_HAS_TARGET, atId); + SetSentErrorMessage(true); return false; } - if (!ExtractOptUInt32(&args, mapid, _player->GetMapId())) - { - return false; - } + return HandleGoHelper(_player, at->target_mapId, at->target_X, at->target_Y, &at->target_Z); } - // link case - else if (!ExtractLocationFromLink(&args, mapid, x, y, z)) + else { - return false; + return HandleGoHelper(_player, atEntry->mapid, atEntry->x, atEntry->y, &atEntry->z); } - - return HandleGoHelper(_player, mapid, x, y, &z); } - - -// teleport at coordinates -bool ChatHandler::HandleGoXYCommand(char* args) +bool ChatHandler::HandleTeleDelCommand(char* args) { - Player* _player = m_session->GetPlayer(); - - float x; - if (!ExtractFloat(&args, x)) + if (!*args) { return false; } - float y; - if (!ExtractFloat(&args, y)) - { - return false; - } + std::string name = args; - uint32 mapid; - if (!ExtractOptUInt32(&args, mapid, _player->GetMapId())) + if (!sObjectMgr.DeleteGameTele(name)) { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); return false; } - return HandleGoHelper(_player, mapid, x, y); + SendSysMessage(LANG_COMMAND_TP_DELETED); + return true; } -// teleport at coordinates, including Z -bool ChatHandler::HandleGoXYZCommand(char* args) +bool ChatHandler::HandleTeleAddCommand(char* args) { - Player* _player = m_session->GetPlayer(); - - float x; - if (!ExtractFloat(&args, x)) + if (!*args) { return false; } - float y; - if (!ExtractFloat(&args, y)) + Player* player = m_session->GetPlayer(); + if (!player) { return false; } - float z; - if (!ExtractFloat(&args, z)) + std::string name = args; + + if (sObjectMgr.GetGameTele(name)) { + SendSysMessage(LANG_COMMAND_TP_ALREADYEXIST); + SetSentErrorMessage(true); return false; } - uint32 mapid; - if (!ExtractOptUInt32(&args, mapid, _player->GetMapId())) + 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 (sObjectMgr.AddGameTele(tele)) { + SendSysMessage(LANG_COMMAND_TP_ADDED); + } + else + { + SendSysMessage(LANG_COMMAND_TP_ADDEDERR); + SetSentErrorMessage(true); return false; } - return HandleGoHelper(_player, mapid, x, y, &z); + return true; } -// teleport at coordinates -bool ChatHandler::HandleGoZoneXYCommand(char* args) +// teleport player to given game_tele.entry +bool ChatHandler::HandleTeleNameCommand(char* args) { - Player* _player = m_session->GetPlayer(); + char* nameStr = ExtractOptNotLastArg(&args); - float x; - if (!ExtractFloat(&args, x)) + Player* target; + ObjectGuid target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&nameStr, &target, &target_guid, &target_name)) { return false; } - float y; - if (!ExtractFloat(&args, y)) + // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r + GameTele const* tele = ExtractGameTeleFromLink(&args); + if (!tele) { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); return false; } - uint32 areaid; - if (*args) + if (target) { - if (!ExtractUint32KeyFromLink(&args, "Harea", areaid)) + // check online security + if (HasLowerSecurity(target)) + { + 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()); + } + + return HandleGoHelper(target, tele->mapId, tele->position_x, tele->position_y, &tele->position_z, &tele->orientation); } else { - areaid = _player->GetZoneId(); - } + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + { + return false; + } - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaid); + std::string nameLink = playerLink(target_name); - if (x < 0 || x > 100 || y < 0 || y > 100 || !areaEntry) - { - PSendSysMessage(LANG_INVALID_ZONE_COORD, x, y, areaid); - SetSentErrorMessage(true); - return false; + PSendSysMessage(LANG_TELEPORTING_TO, nameLink.c_str(), GetMangosString(LANG_OFFLINE), tele->name.c_str()); + Player::SavePositionInDB(target_guid, tele->mapId, + tele->position_x, tele->position_y, tele->position_z, tele->orientation, + sTerrainMgr.GetZoneId(tele->mapId, tele->position_x, tele->position_y, tele->position_z)); } - // update to parent zone if exist (client map show only zones without parents) - AreaTableEntry const* zoneEntry = areaEntry->zone ? GetAreaEntryByAreaID(areaEntry->zone) : areaEntry; + return true; +} - MapEntry const* mapEntry = sMapStore.LookupEntry(zoneEntry->mapid); - if (mapEntry->Instanceable()) +bool ChatHandler::HandleTeleCommand(char* args) +{ + if (!*args) { - PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->area_name[GetSessionDbcLocale()], - mapEntry->MapID, mapEntry->name[GetSessionDbcLocale()]); - SetSentErrorMessage(true); return false; } - if (!Zone2MapCoordinates(x, y, zoneEntry->ID)) + Player* _player = m_session->GetPlayer(); + + // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r + GameTele const* tele = ExtractGameTeleFromLink(&args); + + if (!tele) { - PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->area_name[GetSessionDbcLocale()], - mapEntry->MapID, mapEntry->name[GetSessionDbcLocale()]); + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); SetSentErrorMessage(true); return false; } - return HandleGoHelper(_player, mapEntry->MapID, x, y); + return HandleGoHelper(_player, tele->mapId, tele->position_x, tele->position_y, &tele->position_z, &tele->orientation); } -// teleport to grid -bool ChatHandler::HandleGoGridCommand(char* args) +// Teleport group to given game_tele.entry +bool ChatHandler::HandleTeleGroupCommand(char* args) { - Player* _player = m_session->GetPlayer(); - - float grid_x; - if (!ExtractFloat(&args, grid_x)) + if (!*args) { return false; } - float grid_y; - if (!ExtractFloat(&args, grid_y)) + Player* player = getSelectedPlayer(); + if (!player) { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); return false; } - uint32 mapid; - if (!ExtractOptUInt32(&args, mapid, _player->GetMapId())) + // check online security + if (HasLowerSecurity(player)) { return false; } - // 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; + // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r + GameTele const* tele = ExtractGameTeleFromLink(&args); + if (!tele) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } - return HandleGoHelper(_player, mapid, x, y); -} + std::string nameLink = GetNameLink(player); -bool ChatHandler::HandleModifyDrunkCommand(char* args) -{ - if (!*args) + Group* grp = player->GetGroup(); + if (!grp) { + PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); + SetSentErrorMessage(true); return false; } - uint32 drunklevel = (uint32)atoi(args); - if (drunklevel > 100) + for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { - drunklevel = 100; - } + Player* pl = itr->getSource(); - uint16 drunkMod = drunklevel * 0xFFFF / 100; + if (!pl || !pl->GetSession()) + { + continue; + } - m_session->GetPlayer()->SetDrunkValue(drunkMod); + // check online security + if (HasLowerSecurity(pl)) + { + return false; + } - return true; -} + std::string plNameLink = GetNameLink(pl); -bool ChatHandler::HandleSetViewCommand(char* /*args*/) -{ - if (Unit* unit = getSelectedUnit()) - { - m_session->GetPlayer()->GetCamera().SetView(unit); - } - else - { - PSendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; + 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->IsTaxiFlying()) + { + pl->GetMotionMaster()->MovementExpired(); + pl->m_taxi.ClearTaxiDestinations(); + } + // 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; diff --git a/src/game/ChatCommands/TriggerCommands.cpp b/src/game/ChatCommands/TriggerCommands.cpp new file mode 100644 index 0000000000000..348445d396961 --- /dev/null +++ b/src/game/ChatCommands/TriggerCommands.cpp @@ -0,0 +1,314 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" + + +void ChatHandler::ShowTriggerTargetListHelper(uint32 id, AreaTrigger const* at, bool subpart /*= false*/) +{ + if (m_session) + { + char dist_buf[50]; + if (!subpart) + { + float dist = m_session->GetPlayer()->GetDistance2d(at->target_X, at->target_Y); + snprintf(dist_buf, 50, GetMangosString(LANG_TRIGGER_DIST), dist); + } + else + { + dist_buf[0] = '\0'; + } + + PSendSysMessage(LANG_TRIGGER_TARGET_LIST_CHAT, + subpart ? " -> " : "", id, id, at->target_mapId, at->target_X, at->target_Y, at->target_Z, dist_buf); + } + else + PSendSysMessage(LANG_TRIGGER_TARGET_LIST_CONSOLE, + subpart ? " -> " : "", id, at->target_mapId, at->target_X, at->target_Y, at->target_Z); +} + +void ChatHandler::ShowTriggerListHelper(AreaTriggerEntry const* atEntry) +{ + char const* tavern = sObjectMgr.IsTavernAreaTrigger(atEntry->id) ? GetMangosString(LANG_TRIGGER_TAVERN) : ""; + char const* quest = sObjectMgr.GetQuestForAreaTrigger(atEntry->id) ? GetMangosString(LANG_TRIGGER_QUEST) : ""; + + if (m_session) + { + float dist = m_session->GetPlayer()->GetDistance2d(atEntry->x, atEntry->y); + char dist_buf[50]; + snprintf(dist_buf, 50, GetMangosString(LANG_TRIGGER_DIST), dist); + + PSendSysMessage(LANG_TRIGGER_LIST_CHAT, + atEntry->id, atEntry->id, atEntry->mapid, atEntry->x, atEntry->y, atEntry->z, dist_buf, tavern, quest); + } + else + PSendSysMessage(LANG_TRIGGER_LIST_CONSOLE, + atEntry->id, atEntry->mapid, atEntry->x, atEntry->y, atEntry->z, tavern, quest); + + if (AreaTrigger const* at = sObjectMgr.GetAreaTrigger(atEntry->id)) + { + ShowTriggerTargetListHelper(atEntry->id, at, true); + } +} + +bool ChatHandler::HandleTriggerCommand(char* args) +{ + AreaTriggerEntry const* atEntry = NULL; + + Player* pl = m_session ? m_session->GetPlayer() : NULL; + + // select by args + if (*args) + { + uint32 atId; + if (!ExtractUint32KeyFromLink(&args, "Hareatrigger", atId)) + { + return false; + } + + if (!atId) + { + return false; + } + + atEntry = sAreaTriggerStore.LookupEntry(atId); + + if (!atEntry) + { + PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND, atId); + SetSentErrorMessage(true); + return false; + } + } + // find nearest + else + { + if (!m_session) + { + return false; + } + + float dist2 = MAP_SIZE * MAP_SIZE; + + // Search triggers + for (uint32 id = 0; id < sAreaTriggerStore.GetNumRows(); ++id) + { + AreaTriggerEntry const* atTestEntry = sAreaTriggerStore.LookupEntry(id); + if (!atTestEntry) + { + continue; + } + + if (atTestEntry->mapid != m_session->GetPlayer()->GetMapId()) + { + continue; + } + + float dx = atTestEntry->x - pl->GetPositionX(); + float dy = atTestEntry->y - pl->GetPositionY(); + + float test_dist2 = dx * dx + dy * dy; + + if (test_dist2 >= dist2) + { + continue; + } + + dist2 = test_dist2; + atEntry = atTestEntry; + } + + if (!atEntry) + { + SendSysMessage(LANG_COMMAND_NOTRIGGERFOUND); + SetSentErrorMessage(true); + return false; + } + } + + ShowTriggerListHelper(atEntry); + + int loc_idx = GetSessionDbLocaleIndex(); + + AreaTrigger const* at = sObjectMgr.GetAreaTrigger(atEntry->id); + if (at) + { + PSendSysMessage(LANG_TRIGGER_REQ_LEVEL, at->requiredLevel); + } + + if (uint32 quest_id = sObjectMgr.GetQuestForAreaTrigger(atEntry->id)) + { + SendSysMessage(LANG_TRIGGER_EXPLORE_QUEST); + ShowQuestListHelper(quest_id, loc_idx, pl); + } + + if (at) + { + if (at->requiredItem || at->requiredItem2) + { + SendSysMessage(LANG_TRIGGER_REQ_ITEMS); + + if (at->requiredItem) + { + ShowItemListHelper(at->requiredItem, loc_idx, pl); + } + if (at->requiredItem2) + { + ShowItemListHelper(at->requiredItem2, loc_idx, pl); + } + } + + if (at->requiredQuest) + { + SendSysMessage(LANG_TRIGGER_REQ_QUEST); + ShowQuestListHelper(at->requiredQuest, loc_idx, pl); + } + + if (at->heroicKey || at->heroicKey2) + { + SendSysMessage(LANG_TRIGGER_REQ_KEYS_HEROIC); + + if (at->heroicKey) + { + ShowItemListHelper(at->heroicKey, loc_idx, pl); + } + if (at->heroicKey2) + { + ShowItemListHelper(at->heroicKey2, loc_idx, pl); + } + } + } + + return true; +} + +bool ChatHandler::HandleTriggerActiveCommand(char* /*args*/) +{ + uint32 counter = 0; // Counter for figure out that we found smth. + + Player* pl = m_session->GetPlayer(); + + // Search in AreaTable.dbc + for (uint32 id = 0; id < sAreaTriggerStore.GetNumRows(); ++id) + { + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(id); + if (!atEntry) + { + continue; + } + + if (!IsPointInAreaTriggerZone(atEntry, pl->GetMapId(), pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ())) + { + continue; + } + + ShowTriggerListHelper(atEntry); + + ++counter; + } + + if (counter == 0) // if counter == 0 then we found nth + { + SendSysMessage(LANG_COMMAND_NOTRIGGERFOUND); + } + + return true; +} + +bool ChatHandler::HandleTriggerNearCommand(char* args) +{ + float distance = (!*args) ? 10.0f : (float)atof(args); + float dist2 = distance * distance; + uint32 counter = 0; // Counter for figure out that we found smth. + + Player* pl = m_session->GetPlayer(); + + // Search triggers + for (uint32 id = 0; id < sAreaTriggerStore.GetNumRows(); ++id) + { + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(id); + if (!atEntry) + { + continue; + } + + if (atEntry->mapid != m_session->GetPlayer()->GetMapId()) + { + continue; + } + + float dx = atEntry->x - pl->GetPositionX(); + float dy = atEntry->y - pl->GetPositionY(); + + if (dx * dx + dy * dy > dist2) + { + continue; + } + + ShowTriggerListHelper(atEntry); + + ++counter; + } + + // Search trigger targets + for (uint32 id = 0; id < sAreaTriggerStore.GetNumRows(); ++id) + { + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(id); + if (!atEntry) + { + continue; + } + + AreaTrigger const* at = sObjectMgr.GetAreaTrigger(atEntry->id); + if (!at) + { + continue; + } + + if (at->target_mapId != m_session->GetPlayer()->GetMapId()) + { + continue; + } + + float dx = at->target_X - pl->GetPositionX(); + float dy = at->target_Y - pl->GetPositionY(); + + if (dx * dx + dy * dy > dist2) + { + continue; + } + + ShowTriggerTargetListHelper(atEntry->id, at); + + ++counter; + } + + if (counter == 0) // if counter == 0 then we found nth + { + SendSysMessage(LANG_COMMAND_NOTRIGGERFOUND); + } + + return true; +} diff --git a/src/game/ChatCommands/WaypointCommands.cpp b/src/game/ChatCommands/WaypointCommands.cpp new file mode 100644 index 0000000000000..fbdc86eb3a560 --- /dev/null +++ b/src/game/ChatCommands/WaypointCommands.cpp @@ -0,0 +1,944 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + +#include "Chat.h" +#include "Language.h" +#include "PointMovementGenerator.h" +#include "WaypointMovementGenerator.h" +#include "TemporarySummon.h" +#include "MoveMap.h" +#include "PathFinder.h" // for mmap manager +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" +#include "movement/MoveSplineInit.h" +#include +#include +#include + +/// Helper function +inline Creature* Helper_CreateWaypointFor(Creature* wpOwner, WaypointPathOrigin wpOrigin, int32 pathId, uint32 wpId, WaypointNode const* wpNode, CreatureInfo const* waypointInfo) +{ + TemporarySummonWaypoint* wpCreature = new TemporarySummonWaypoint(wpOwner->GetObjectGuid(), wpId, pathId, (uint32)wpOrigin); + + CreatureCreatePos pos(wpOwner->GetMap(), wpNode->x, wpNode->y, wpNode->z, wpNode->orientation); + + if (!wpCreature->Create(wpOwner->GetMap()->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, waypointInfo)) + { + delete wpCreature; + return NULL; + } + + wpCreature->SetVisibility(VISIBILITY_OFF); + wpCreature->SetRespawnCoord(pos); + + wpCreature->SetActiveObjectState(true); + + wpCreature->Summon(TEMPSUMMON_TIMED_DESPAWN, 5 * MINUTE * IN_MILLISECONDS); // Also initializes the AI and MMGen + return wpCreature; +} + +inline void UnsummonVisualWaypoints(Player const* player, ObjectGuid ownerGuid) +{ + std::list waypoints; + MaNGOS::AllCreaturesOfEntryInRangeCheck checkerForWaypoint(player, VISUAL_WAYPOINT, SIZE_OF_GRIDS); + MaNGOS::CreatureListSearcher searcher(waypoints, checkerForWaypoint); + Cell::VisitGridObjects(player, searcher, SIZE_OF_GRIDS); + + for (std::list::iterator itr = waypoints.begin(); itr != waypoints.end(); ++itr) + { + if ((*itr)->GetSubtype() != CREATURE_SUBTYPE_TEMPORARY_SUMMON) + { + continue; + } + + TemporarySummonWaypoint* wpTarget = dynamic_cast(*itr); + if (!wpTarget) + { + continue; + } + + if (wpTarget->GetSummonerGuid() == ownerGuid) + { + wpTarget->UnSummon(); + } + } +} + +/** Add a waypoint to a creature + * .wp add [dbGuid] [pathId] [source] + * + * The user can either select an npc or provide its dbGuid. + * Also the user can specify pathId and source if wanted. + * + * 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. + * + * .wp add [pathId] [source] + * -> adds a waypoint to the currently selected creature, to path pathId in source-storage + * + * .wp add guid [pathId] [source] + * -> if no npc is selected, expect the creature provided with guid argument + * + * @return true - command did succeed, false - something went wrong + */ +bool ChatHandler::HandleWpAddCommand(char* args) +{ + DEBUG_LOG("DEBUG: HandleWpAddCommand"); + + CreatureInfo const* waypointInfo = ObjectMgr::GetCreatureTemplate(VISUAL_WAYPOINT); + if (!waypointInfo || waypointInfo->GetHighGuid() != HIGHGUID_UNIT) + { + return false; // must exist as normal creature in mangos.sql 'creature_template' + } + + Creature* targetCreature = getSelectedCreature(); + WaypointPathOrigin wpDestination = PATH_NO_PATH; ///< into which storage + int32 wpPathId = 0; ///< along which path + uint32 wpPointId = 0; ///< pointId if a waypoint was selected, in this case insert after + Creature* wpOwner = NULL; + + if (targetCreature) + { + // Check if the user did specify a visual waypoint + if (targetCreature->GetEntry() == VISUAL_WAYPOINT && targetCreature->GetSubtype() == CREATURE_SUBTYPE_TEMPORARY_SUMMON) + { + TemporarySummonWaypoint* wpTarget = dynamic_cast(targetCreature); + if (!wpTarget) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + + // Who moves along this waypoint? + wpOwner = targetCreature->GetMap()->GetAnyTypeCreature(wpTarget->GetSummonerGuid()); + if (!wpOwner) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND_NPC, wpTarget->GetSummonerGuid().GetString().c_str()); + SetSentErrorMessage(true); + return false; + } + wpDestination = (WaypointPathOrigin)wpTarget->GetPathOrigin(); + wpPathId = wpTarget->GetPathId(); + wpPointId = wpTarget->GetWaypointId() + 1; // Insert as next waypoint + } + else // normal creature selected + { + wpOwner = targetCreature; + } + } + else //!targetCreature - first argument must be dbGuid + { + uint32 dbGuid; + if (!ExtractUInt32(&args, dbGuid)) + { + PSendSysMessage(LANG_WAYPOINT_NOGUID); + SetSentErrorMessage(true); + return false; + } + + CreatureData const* data = sObjectMgr.GetCreatureData(dbGuid); + if (!data) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); + SetSentErrorMessage(true); + return false; + } + + if (m_session->GetPlayer()->GetMapId() != data->mapid) + { + PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, dbGuid); + SetSentErrorMessage(true); + return false; + } + + wpOwner = m_session->GetPlayer()->GetMap()->GetAnyTypeCreature(data->GetObjectGuid(dbGuid)); + if (!wpOwner) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); + SetSentErrorMessage(true); + return false; + } + } + + if (wpDestination == PATH_NO_PATH) // No Waypoint selected, parse additional params + { + if (ExtractOptInt32(&args, wpPathId, 0)) // Fill path-id and source + { + uint32 src = (uint32)PATH_NO_PATH; + if (ExtractOptUInt32(&args, src, src)) + { + wpDestination = (WaypointPathOrigin)src; + } + else // pathId provided but no destination + { + if (wpPathId != 0) + { + wpDestination = PATH_FROM_ENTRY; // Multiple Paths must only be assigned by entry + } + } + } + + if (wpDestination == PATH_NO_PATH) // No overwrite params. Do best estimate + { + if (wpOwner->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) + { + if (WaypointMovementGenerator const* wpMMGen = dynamic_cast const*>(wpOwner->GetMotionMaster()->GetCurrent())) + { + wpMMGen->GetPathInformation(wpPathId, wpDestination); + } + } + // Get information about default path if no current path. If no default path, prepare data dependendy on uniqueness + if (wpDestination == PATH_NO_PATH && !sWaypointMgr.GetDefaultPath(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), &wpDestination)) + { + wpDestination = PATH_FROM_ENTRY; // Default place to store paths + if (wpOwner->HasStaticDBSpawnData()) + { + QueryResult* result = WorldDatabase.PQuery("SELECT COUNT(`id`) FROM `creature` WHERE `id` = %u", wpOwner->GetEntry()); + if (result && result->Fetch()[0].GetUInt32() != 1) + { + wpDestination = PATH_FROM_GUID; + } + delete result; + } + } + } + } + + // All arguments parsed + // wpOwner will get a new waypoint inserted into wpPath = GetPathFromOrigin(wpOwner, wpDestination, wpPathId) at wpPointId + + float x, y, z; + m_session->GetPlayer()->GetPosition(x, y, z); + if (!sWaypointMgr.AddNode(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPointId, wpDestination, x, y, z)) + { + PSendSysMessage(LANG_WAYPOINT_NOTCREATED, wpPointId, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpDestination).c_str()); + SetSentErrorMessage(true); + return false; + } + + // Unsummon old visuals, summon new ones + UnsummonVisualWaypoints(m_session->GetPlayer(), wpOwner->GetObjectGuid()); + WaypointPath const* wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpDestination); + for (WaypointPath::const_iterator itr = wpPath->begin(); itr != wpPath->end(); ++itr) + { + if (!Helper_CreateWaypointFor(wpOwner, wpDestination, wpPathId, itr->first, &itr->second, waypointInfo)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + SetSentErrorMessage(true); + return false; + } + } + + PSendSysMessage(LANG_WAYPOINT_ADDED, wpPointId, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpDestination).c_str()); + + return true; +} // HandleWpAddCommand + +/** + * .wp modify waittime | scriptid | orientation | del | move [dbGuid, id] [value] + * + * waittime + * User has selected a visual waypoint before. + * Delay is added to this waypoint. Everytime the + * NPC comes to this waypoint, it will wait Delay millieseconds. + * + * waittime + * User has not selected visual waypoint before. + * For the waypoint for the NPC with + * an delay Delay is added to this waypoint + * Everytime the NPC comes to this waypoint, it will wait Delay millieseconds. + * + * scriptid + * User has selected a visual waypoint before. + * is added to this waypoint. Everytime the + * NPC comes to this waypoint, the DBScript scriptId is executed. + * + * scriptid + * User has not selected visual waypoint before. + * For the waypoint for the NPC with + * an emote is added. + * Everytime the NPC comes to this waypoint, the DBScript scriptId is executed. + * + * orientation [DBGuid, WpNum] + * Set the orientation of the selected waypoint or waypoint given with DbGuid/ WpId + * to the value of . + * + * del [DBGuid, WpId] + * Remove the selected waypoint or waypoint given with DbGuid/ WpId. + * + * move [DBGuid, WpId] + * Move the selected waypoint or waypoint given with DbGuid/ WpId to player's current positiion. + */ +bool ChatHandler::HandleWpModifyCommand(char* args) +{ + DEBUG_LOG("DEBUG: HandleWpModifyCommand"); + + if (!*args) + { + return false; + } + + CreatureInfo const* waypointInfo = ObjectMgr::GetCreatureTemplate(VISUAL_WAYPOINT); + if (!waypointInfo || waypointInfo->GetHighGuid() != HIGHGUID_UNIT) + { + return false; // must exist as normal creature in mangos.sql 'creature_template' + } + + // first arg: add del text emote spell waittime move + char* subCmd_str = ExtractLiteralArg(&args); + if (!subCmd_str) + { + return false; + } + + std::string subCmd = subCmd_str; + // Check + // Remember: "show" must also be the name of a column! + if ((subCmd != "waittime") && (subCmd != "scriptid") && (subCmd != "orientation") && (subCmd != "del") && (subCmd != "move")) + { + return false; + } + + // Next arg is: + + // Did user provide a GUID or did the user select a creature? + Creature* targetCreature = getSelectedCreature(); // Expect a visual waypoint to be selected + Creature* wpOwner = NULL; // Who moves along the waypoint + uint32 wpId = 0; + WaypointPathOrigin wpSource = PATH_NO_PATH; + int32 wpPathId = 0; + + if (targetCreature) + { + DEBUG_LOG("DEBUG: HandleWpModifyCommand - User did select an NPC"); + + // Check if the user did specify a visual waypoint + if (targetCreature->GetEntry() != VISUAL_WAYPOINT || targetCreature->GetSubtype() != CREATURE_SUBTYPE_TEMPORARY_SUMMON) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + TemporarySummonWaypoint* wpTarget = dynamic_cast(targetCreature); + if (!wpTarget) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + + // Who moves along this waypoint? + wpOwner = targetCreature->GetMap()->GetAnyTypeCreature(wpTarget->GetSummonerGuid()); + if (!wpOwner) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND_NPC, wpTarget->GetSummonerGuid().GetString().c_str()); + SetSentErrorMessage(true); + return false; + } + wpId = wpTarget->GetWaypointId(); + + wpPathId = wpTarget->GetPathId(); + wpSource = (WaypointPathOrigin)wpTarget->GetPathOrigin(); + } + else + { + uint32 dbGuid = 0; + // User did provide + if (!ExtractUInt32(&args, dbGuid)) + { + SendSysMessage(LANG_WAYPOINT_NOGUID); + SetSentErrorMessage(true); + return false; + } + + if (!ExtractUInt32(&args, wpId)) + { + SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN); + SetSentErrorMessage(true); + return false; + } + + CreatureData const* data = sObjectMgr.GetCreatureData(dbGuid); + if (!data) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); + SetSentErrorMessage(true); + return false; + } + + wpOwner = m_session->GetPlayer()->GetMap()->GetAnyTypeCreature(data->GetObjectGuid(dbGuid)); + if (!wpOwner) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); + SetSentErrorMessage(true); + return false; + } + } + + if (wpSource == PATH_NO_PATH) // No waypoint selected + { + if (wpOwner->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) + { + if (WaypointMovementGenerator const* wpMMGen = dynamic_cast const*>(wpOwner->GetMotionMaster()->GetCurrent())) + { + wpMMGen->GetPathInformation(wpPathId, wpSource); + } + } + if (wpSource == PATH_NO_PATH) + { + sWaypointMgr.GetDefaultPath(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), &wpSource); + } + } + + WaypointPath const* wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpSource); + if (!wpPath) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDPATH, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpSource).c_str()); + SetSentErrorMessage(true); + return false; + } + + WaypointPath::const_iterator point = wpPath->find(wpId); + if (point == wpPath->end()) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND, wpId, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpSource).c_str()); + SetSentErrorMessage(true); + return false; + } + + // If no visual WP was selected, but we are not going to remove it + if (!targetCreature && subCmd != "del") + { + targetCreature = Helper_CreateWaypointFor(wpOwner, wpSource, wpPathId, wpId, &(point->second), waypointInfo); + if (!targetCreature) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + SetSentErrorMessage(true); + return false; + } + } + + if (subCmd == "del") // Remove WP, no additional command required + { + sWaypointMgr.DeleteNode(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource); + + if (TemporarySummonWaypoint* wpCreature = dynamic_cast(targetCreature)) + { + wpCreature->UnSummon(); + } + + if (wpPath->empty()) + { + wpOwner->SetDefaultMovementType(RANDOM_MOTION_TYPE); + wpOwner->GetMotionMaster()->Initialize(); + if (wpOwner->IsAlive()) // Dead creature will reset movement generator at respawn + { + wpOwner->SetDeathState(JUST_DIED); + wpOwner->Respawn(); + } + wpOwner->SaveToDB(); + } + + PSendSysMessage(LANG_WAYPOINT_REMOVED); + return true; + } + else if (subCmd == "move") // Move to player position, no additional command required + { + float x, y, z; + m_session->GetPlayer()->GetPosition(x, y, z); + + // Move visual waypoint + targetCreature->NearTeleportTo(x, y, z, targetCreature->GetOrientation()); + + sWaypointMgr.SetNodePosition(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource, x, y, z); + + PSendSysMessage(LANG_WAYPOINT_CHANGED); + return true; + } + else if (subCmd == "waittime") + { + uint32 waittime; + if (!ExtractUInt32(&args, waittime)) + { + return false; + } + + sWaypointMgr.SetNodeWaittime(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource, waittime); + } + else if (subCmd == "scriptid") + { + uint32 scriptId; + if (!ExtractUInt32(&args, scriptId)) + { + return false; + } + + if (!sWaypointMgr.SetNodeScriptId(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource, scriptId)) + { + PSendSysMessage(LANG_WAYPOINT_INFO_UNK_SCRIPTID, scriptId); + } + } + else if (subCmd == "orientation") + { + float ori; + if (!ExtractFloat(&args, ori)) + { + return false; + } + + sWaypointMgr.SetNodeOrientation(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource, ori); + } + + PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, subCmd_str); + return true; +} + +/** + * .wp show info | on | off | first | last [dbGuid] [pathId [wpOrigin] ] + * + * info -> User has selected a visual waypoint before + * + * on -> User has selected an NPC; all visual waypoints for this + * NPC are added to the world + * + * on -> User did not select an NPC - instead the dbGuid of the + * NPC is provided. All visual waypoints for this NPC + * are added from the world. + * + * off -> User has selected an NPC; all visual waypoints for this + * NPC are removed from the world. + */ +bool ChatHandler::HandleWpShowCommand(char* args) +{ + DEBUG_LOG("DEBUG: HandleWpShowCommand"); + + if (!*args) + { + return false; + } + + CreatureInfo const* waypointInfo = ObjectMgr::GetCreatureTemplate(VISUAL_WAYPOINT); + if (!waypointInfo || waypointInfo->GetHighGuid() != HIGHGUID_UNIT) + { + return false; // must exist as normal creature in mangos.sql 'creature_template' + } + + // first arg: info, on, off, first, last + + char* subCmd_str = ExtractLiteralArg(&args); + if (!subCmd_str) + { + return false; + } + std::string subCmd = subCmd_str; ///< info, on, off, first, last + + uint32 dbGuid = 0; + int32 wpPathId = 0; + WaypointPathOrigin wpOrigin = PATH_NO_PATH; + + // User selected an npc? + Creature* targetCreature = getSelectedCreature(); + if (targetCreature) + { + if (ExtractOptInt32(&args, wpPathId, 0)) // Fill path-id and source + { + uint32 src; + if (ExtractOptUInt32(&args, src, (uint32)PATH_NO_PATH)) + { + wpOrigin = (WaypointPathOrigin)src; + } + } + } + else // Guid must be provided + { + if (!ExtractUInt32(&args, dbGuid)) // No creature selected and no dbGuid provided + { + return false; + } + + if (ExtractOptInt32(&args, wpPathId, 0)) // Fill path-id and source + { + uint32 src = (uint32)PATH_NO_PATH; + if (ExtractOptUInt32(&args, src, src)) + { + wpOrigin = (WaypointPathOrigin)src; + } + } + + // Params now parsed, check them + CreatureData const* data = sObjectMgr.GetCreatureData(dbGuid); + if (!data) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); + SetSentErrorMessage(true); + return false; + } + + targetCreature = m_session->GetPlayer()->GetMap()->GetCreature(data->GetObjectGuid(dbGuid)); + if (!targetCreature) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); + SetSentErrorMessage(true); + return false; + } + } + + Creature* wpOwner = NULL; ///< Npc that is moving + TemporarySummonWaypoint* wpTarget = NULL; // Define here for wp-info command + + // Show info for the selected waypoint (Step one: get moving npc) + if (subCmd == "info") + { + // Check if the user did specify a visual waypoint + if (targetCreature->GetEntry() != VISUAL_WAYPOINT || targetCreature->GetSubtype() != CREATURE_SUBTYPE_TEMPORARY_SUMMON) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + wpTarget = dynamic_cast(targetCreature); + if (!wpTarget) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + + // Who moves along this waypoint? + wpOwner = targetCreature->GetMap()->GetAnyTypeCreature(wpTarget->GetSummonerGuid()); + if (!wpOwner) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND_NPC, wpTarget->GetSummonerGuid().GetString().c_str()); + SetSentErrorMessage(true); + return false; + } + + // Ignore params, use information of selected waypoint! + wpOrigin = (WaypointPathOrigin)wpTarget->GetPathOrigin(); + wpPathId = wpTarget->GetPathId(); + } + else + { + wpOwner = targetCreature; + } + + // Get the path + WaypointPath* wpPath = NULL; + if (wpOrigin != PATH_NO_PATH) // Might have been provided by param + { + wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpOrigin); + } + else + { + if (wpOwner->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) + { + if (WaypointMovementGenerator const* wpMMGen = dynamic_cast const*>(wpOwner->GetMotionMaster()->GetCurrent())) + { + wpMMGen->GetPathInformation(wpPathId, wpOrigin); + wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpOrigin); + } + } + if (wpOrigin == PATH_NO_PATH) + { + wpPath = sWaypointMgr.GetDefaultPath(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), &wpOrigin); + } + } + + if (!wpPath || wpPath->empty()) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDPATH, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpOrigin).c_str()); + SetSentErrorMessage(true); + return false; + } + + // Show info for the selected waypoint (Step two: Show actual info) + if (subCmd == "info") + { + // Find the waypoint + WaypointPath::const_iterator point = wpPath->find(wpTarget->GetWaypointId()); + if (point == wpPath->end()) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND, wpTarget->GetWaypointId(), wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpOrigin).c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, wpTarget->GetWaypointId(), wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpOrigin).c_str()); + PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, point->second.delay); + PSendSysMessage(LANG_WAYPOINT_INFO_ORI, point->second.orientation); + PSendSysMessage(LANG_WAYPOINT_INFO_SCRIPTID, point->second.script_id); + if (wpOrigin == PATH_FROM_EXTERNAL) + { + PSendSysMessage(LANG_WAYPOINT_INFO_AISCRIPT, wpOwner->GetScriptName().c_str()); + } + if (WaypointBehavior* behaviour = point->second.behavior) + { + PSendSysMessage(" ModelId1: %u", behaviour->model1); + PSendSysMessage(" ModelId2: %u", behaviour->model2); + PSendSysMessage(" Emote: %u", behaviour->emote); + PSendSysMessage(" Spell: %u", behaviour->spell); + for (int i = 0; i < MAX_WAYPOINT_TEXT; ++i) + { + PSendSysMessage(" TextId%i: %i \'%s\'", i + 1, behaviour->textid[i], (behaviour->textid[i] ? GetMangosString(behaviour->textid[i]) : "")); + } + } + + return true; + } + + if (subCmd == "on") + { + UnsummonVisualWaypoints(m_session->GetPlayer(), wpOwner->GetObjectGuid()); + + for (WaypointPath::const_iterator pItr = wpPath->begin(); pItr != wpPath->end(); ++pItr) + { + if (!Helper_CreateWaypointFor(wpOwner, wpOrigin, wpPathId, pItr->first, &(pItr->second), waypointInfo)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + SetSentErrorMessage(true); + return false; + } + } + + return true; + } + + if (subCmd == "first") + { + if (!Helper_CreateWaypointFor(wpOwner, wpOrigin, wpPathId, wpPath->begin()->first, &(wpPath->begin()->second), waypointInfo)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + SetSentErrorMessage(true); + return false; + } + + // player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint"); + return true; + } + + if (subCmd == "last") + { + if (!Helper_CreateWaypointFor(wpOwner, wpOrigin, wpPathId, wpPath->rbegin()->first, &(wpPath->rbegin()->second), waypointInfo)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + SetSentErrorMessage(true); + return false; + } + + // player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint"); + return true; + } + + if (subCmd == "off") + { + UnsummonVisualWaypoints(m_session->GetPlayer(), wpOwner->GetObjectGuid()); + PSendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED); + return true; + } + + return false; +} // HandleWpShowCommand + +/// [Guid if no selected unit] [pathId [wpOrigin] ] +bool ChatHandler::HandleWpExportCommand(char* args) +{ + if (!*args) + { + return false; + } + + Creature* wpOwner = NULL; + WaypointPathOrigin wpOrigin = PATH_NO_PATH; + int32 wpPathId = 0; + + if (Creature* targetCreature = getSelectedCreature()) + { + // Check if the user did specify a visual waypoint + if (targetCreature->GetEntry() == VISUAL_WAYPOINT && targetCreature->GetSubtype() == CREATURE_SUBTYPE_TEMPORARY_SUMMON) + { + TemporarySummonWaypoint* wpTarget = dynamic_cast(targetCreature); + if (!wpTarget) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + + // Who moves along this waypoint? + wpOwner = targetCreature->GetMap()->GetAnyTypeCreature(wpTarget->GetSummonerGuid()); + if (!wpOwner) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND_NPC, wpTarget->GetSummonerGuid().GetString().c_str()); + SetSentErrorMessage(true); + return false; + } + wpOrigin = (WaypointPathOrigin)wpTarget->GetPathOrigin(); + wpPathId = wpTarget->GetPathId(); + } + else // normal creature selected + { + wpOwner = targetCreature; + } + } + else + { + uint32 dbGuid; + if (!ExtractUInt32(&args, dbGuid)) + { + PSendSysMessage(LANG_WAYPOINT_NOGUID); + SetSentErrorMessage(true); + return false; + } + + CreatureData const* data = sObjectMgr.GetCreatureData(dbGuid); + if (!data) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); + SetSentErrorMessage(true); + return false; + } + + if (m_session->GetPlayer()->GetMapId() != data->mapid) + { + PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, dbGuid); + SetSentErrorMessage(true); + return false; + } + + wpOwner = m_session->GetPlayer()->GetMap()->GetAnyTypeCreature(data->GetObjectGuid(dbGuid)); + if (!wpOwner) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); + SetSentErrorMessage(true); + return false; + } + } + + // wpOwner is now known, in case of export by visual waypoint also the to be exported path + char* export_str = ExtractLiteralArg(&args); + if (!export_str) + { + PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export"); + SetSentErrorMessage(true); + return false; + } + + if (wpOrigin == PATH_NO_PATH) // No WP selected, Extract optional arguments + { + if (ExtractOptInt32(&args, wpPathId, 0)) // Fill path-id and source + { + uint32 src = (uint32)PATH_NO_PATH; + if (ExtractOptUInt32(&args, src, src)) + { + wpOrigin = (WaypointPathOrigin)src; + } + else // pathId provided but no destination + { + if (wpPathId != 0) + { + wpOrigin = PATH_FROM_ENTRY; // Multiple Paths must only be assigned by entry + } + } + } + + if (wpOrigin == PATH_NO_PATH) + { + if (wpOwner->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) + if (WaypointMovementGenerator const* wpMMGen = dynamic_cast const*>(wpOwner->GetMotionMaster()->GetCurrent())) + { + wpMMGen->GetPathInformation(wpPathId, wpOrigin); + } + if (wpOrigin == PATH_NO_PATH) + { + sWaypointMgr.GetDefaultPath(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), &wpOrigin); + } + } + } + + WaypointPath const* wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpOrigin); + if (!wpPath || wpPath->empty()) + { + PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT); + SetSentErrorMessage(true); + return false; + } + + std::ofstream outfile; + outfile.open(export_str); + + std::string table; + char const* key_field; + uint32 key; + switch (wpOrigin) + { + case PATH_FROM_ENTRY: key = wpOwner->GetEntry(); key_field = "entry"; table = "creature_movement_template"; break; + case PATH_FROM_GUID: key = wpOwner->GetGUIDLow(); key_field = "id"; table = "creature_movement"; break; + case PATH_FROM_EXTERNAL: key = wpOwner->GetEntry(); key_field = "entry"; table = sWaypointMgr.GetExternalWPTable(); break; + case PATH_NO_PATH: + return false; + } + + outfile << "DELETE FROM `" << table << "` WHERE `" << key_field << "`=" << key << ";\n"; + if (wpOrigin != PATH_FROM_EXTERNAL) + { + outfile << "INSERT INTO `" << table << "` (`" << key_field << "`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `waittime`, `script_id`) VALUES\n"; + } + else + { + outfile << "INSERT INTO `" << table << "` (`" << key_field << "`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `waittime`) VALUES\n"; + } + + WaypointPath::const_iterator itr = wpPath->begin(); + uint32 countDown = wpPath->size(); + for (; itr != wpPath->end(); ++itr, --countDown) + { + outfile << "(" << key << ","; + outfile << itr->first << ","; + outfile << itr->second.x << ","; + outfile << itr->second.y << ","; + outfile << itr->second.z << ","; + outfile << itr->second.orientation << ","; + outfile << itr->second.delay << ","; + if (wpOrigin != PATH_FROM_EXTERNAL) // Only for normal waypoints + { + outfile << itr->second.script_id << ")"; + } + if (countDown > 1) + { + outfile << ",\n"; + } + else + { + outfile << ";\n"; + } + } + + PSendSysMessage(LANG_WAYPOINT_EXPORTED); + outfile.close(); + + return true; +} diff --git a/src/game/ChatCommands/ZZZ_CustomCommands.cpp b/src/game/ChatCommands/ZZZ_CustomCommands.cpp new file mode 100644 index 0000000000000..98b2d09edef5f --- /dev/null +++ b/src/game/ChatCommands/ZZZ_CustomCommands.cpp @@ -0,0 +1,67 @@ +/** + * MaNGOS is a full featured server for World of Warcraft, supporting + * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 + * + * Copyright (C) 2005-2020 MaNGOS + * + * 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 + * + * World of Warcraft, and all World of Warcraft or Warcraft art, images, + * and lore are copyrighted by Blizzard Entertainment, Inc. + */ + + /* + CUSTOM COMMANDS HANDLERS + Code your custom command handlers here ! + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "AccountMgr.h" +#include "PlayerDump.h" +#include "SpellMgr.h" +#include "Player.h" +#include "GameObject.h" +#include "Chat.h" +#include "Log.h" +#include "Guild.h" +#include "GuildMgr.h" +#include "ObjectAccessor.h" +#include "MapManager.h" +#include "MassMailMgr.h" +#include "ScriptMgr.h" +#include "Language.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" +#include "Weather.h" +#include "PointMovementGenerator.h" +#include "PathFinder.h" +#include "TargetedMovementGenerator.h" +#include "SystemConfig.h" +#include "Config/Config.h" +#include "Mail.h" +#include "Util.h" +#include "ItemEnchantmentMgr.h" +#include "BattleGround/BattleGroundMgr.h" +#include "MapPersistentStateMgr.h" +#include "InstanceData.h" +#include "DBCStores.h" +#include "CreatureEventAIMgr.h" +#include "AuctionHouseBot/AuctionHouseBot.h" +#include "SQLStorages.h" +#include "DisableMgr.h" \ No newline at end of file diff --git a/src/game/WorldHandlers/Chat.cpp b/src/game/WorldHandlers/Chat.cpp index 67ceb32ea6a12..407f855ea7b70 100644 --- a/src/game/WorldHandlers/Chat.cpp +++ b/src/game/WorldHandlers/Chat.cpp @@ -3841,6 +3841,199 @@ void ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg msgtype, char const } } +// Shared Helpers between command implementation files + +void ChatHandler::ShowFactionListHelper(FactionEntry const* factionEntry, LocaleConstant loc, FactionState const* repState /*= NULL*/, Player* target /*= NULL */) +{ + std::string name = factionEntry->name[loc]; + // 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 << factionEntry->ID << " - |cffffffff|Hfaction:" << factionEntry->ID << "|h[" << name << " " << localeNames[loc] << "]|h|r"; + } + else + { + ss << factionEntry->ID << " - " << name << " " << localeNames[loc]; + } + + if (repState) // and then target!=NULL also + { + ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); + std::string rankName = GetMangosString(ReputationRankStrIndex[rank]); + + ss << " " << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ")"; + + if (repState->Flags & FACTION_FLAG_VISIBLE) + { + ss << GetMangosString(LANG_FACTION_VISIBLE); + } + if (repState->Flags & FACTION_FLAG_AT_WAR) + { + ss << GetMangosString(LANG_FACTION_ATWAR); + } + if (repState->Flags & FACTION_FLAG_PEACE_FORCED) + { + ss << GetMangosString(LANG_FACTION_PEACE_FORCED); + } + if (repState->Flags & FACTION_FLAG_HIDDEN) + { + ss << GetMangosString(LANG_FACTION_HIDDEN); + } + if (repState->Flags & FACTION_FLAG_INVISIBLE_FORCED) + { + ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED); + } + if (repState->Flags & FACTION_FLAG_INACTIVE) + { + ss << GetMangosString(LANG_FACTION_INACTIVE); + } + } + else if (target) + { + ss << GetMangosString(LANG_FACTION_NOREPUTATION); + } + + SendSysMessage(ss.str().c_str()); +} +void ChatHandler::ShowSpellListHelper(Player* target, SpellEntry const* spellInfo, LocaleConstant loc) +{ + uint32 id = spellInfo->Id; + + bool known = target && target->HasSpell(id); + bool learn = (spellInfo->Effect[EFFECT_INDEX_0] == SPELL_EFFECT_LEARN_SPELL); + + uint32 talentCost = GetTalentSpellCost(id); + + bool talent = (talentCost > 0); + bool passive = IsPassiveSpell(spellInfo); + 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 : sSpellMgr.GetSpellRank(learn ? spellInfo->EffectTriggerSpell[EFFECT_INDEX_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[" << spellInfo->SpellName[loc]; + } + else + { + ss << id << " - " << spellInfo->SpellName[loc]; + } + + // include rank in link name + if (rank) + { + ss << GetMangosString(LANG_SPELL_RANK) << rank; + } + + if (m_session) + { + ss << " " << localeNames[loc] << "]|h|r"; + } + else + { + ss << " " << localeNames[loc]; + } + + if (talent) + { + ss << GetMangosString(LANG_TALENT); + } + if (passive) + { + ss << GetMangosString(LANG_PASSIVE); + } + if (learn) + { + ss << GetMangosString(LANG_LEARN); + } + if (known) + { + ss << GetMangosString(LANG_KNOWN); + } + if (active) + { + ss << GetMangosString(LANG_ACTIVE); + } + + SendSysMessage(ss.str().c_str()); +} + +bool ChatHandler::ShowPlayerListHelper(QueryResult* result, uint32* limit, bool title, bool error) +{ + if (!result) + { + if (error) + { + PSendSysMessage(LANG_NO_PLAYERS_FOUND); + SetSentErrorMessage(true); + } + return false; + } + + if (!m_session && title) + { + SendSysMessage(LANG_CHARACTERS_LIST_BAR); + SendSysMessage(LANG_CHARACTERS_LIST_HEADER); + SendSysMessage(LANG_CHARACTERS_LIST_BAR); + } + + if (result) + { + ///- Circle through them. Display username and GM level + do + { + // check limit + if (limit) + { + if (*limit == 0) + { + break; + } + --* limit; + } + + Field* fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + std::string name = fields[1].GetCppString(); + uint8 race = fields[2].GetUInt8(); + uint8 class_ = fields[3].GetUInt8(); + uint32 level = fields[4].GetUInt32(); + + ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race); + ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); + + char const* race_name = raceEntry ? raceEntry->name[GetSessionDbcLocale()] : ""; + char const* class_name = classEntry ? classEntry->name[GetSessionDbcLocale()] : ""; + + if (!m_session) + { + PSendSysMessage(LANG_CHARACTERS_LIST_LINE_CONSOLE, guid, name.c_str(), race_name, class_name, level); + } + else + { + PSendSysMessage(LANG_CHARACTERS_LIST_LINE_CHAT, guid, name.c_str(), name.c_str(), race_name, class_name, level); + } + } while (result->NextRow()); + + delete result; + } + + if (!m_session) + { + SendSysMessage(LANG_CHARACTERS_LIST_BAR); + } + + return true; +} + + + // Instantiate template for helper function template void ChatHandler::ShowNpcOrGoSpawnInformation(uint32 guid); template void ChatHandler::ShowNpcOrGoSpawnInformation(uint32 guid); diff --git a/src/game/WorldHandlers/Chat.h b/src/game/WorldHandlers/Chat.h index b6f708352282d..d31d48fad3fcf 100644 --- a/src/game/WorldHandlers/Chat.h +++ b/src/game/WorldHandlers/Chat.h @@ -28,6 +28,7 @@ #include "Common.h" #include "SharedDefines.h" #include "ObjectGuid.h" +#include "Language.h" struct AreaTrigger; struct AreaTriggerEntry; @@ -75,6 +76,12 @@ enum PlayerChatTag }; typedef uint32 ChatTagFlags; +static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] = +{ + LANG_REP_HATED, LANG_REP_HOSTILE, LANG_REP_UNFRIENDLY, LANG_REP_NEUTRAL, + LANG_REP_FRIENDLY, LANG_REP_HONORED, LANG_REP_REVERED, LANG_REP_EXALTED +}; + class ChatHandler { public: