/** * 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 "DBCStores.h" #include "WorldPacket.h" #include "Player.h" #include "Opcodes.h" #include "Chat.h" #include "Log.h" #include "Unit.h" #include "GossipDef.h" #include "Language.h" #include "BattleGround/BattleGroundMgr.h" #include #include "ObjectMgr.h" #include "ObjectGuid.h" #include "SpellMgr.h" bool ChatHandler::HandleDebugSendSpellFailCommand(char* args) { if (!*args) { return false; } uint32 failnum; if (!ExtractUInt32(&args, failnum) || failnum > 255) { return false; } uint32 failarg1; if (!ExtractOptUInt32(&args, failarg1, 0)) { return false; } uint32 failarg2; if (!ExtractOptUInt32(&args, failarg2, 0)) { return false; } WorldPacket data(SMSG_CAST_FAILED, 4 + 1 + 1); data << uint32(133); data << uint8(2); data << uint8(failnum); if (failarg1 || failarg2) { data << uint32(failarg1); } if (failarg2) { data << uint32(failarg2); } m_session->SendPacket(&data); return true; } bool ChatHandler::HandleDebugSendPoiCommand(char* args) { Player* pPlayer = m_session->GetPlayer(); Unit* target = getSelectedUnit(); if (!target) { SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); return true; } uint32 icon; if (!ExtractUInt32(&args, icon)) { return false; } uint32 flags; if (!ExtractUInt32(&args, flags)) { return false; } DETAIL_LOG("Command : POI, NPC = %u, icon = %u flags = %u", target->GetGUIDLow(), icon, flags); pPlayer->PlayerTalkClass->SendPointOfInterest(target->GetPositionX(), target->GetPositionY(), Poi_Icon(icon), flags, 30, "Test POI"); return true; } bool ChatHandler::HandleDebugSendEquipErrorCommand(char* args) { if (!*args) { return false; } uint8 msg = atoi(args); m_session->GetPlayer()->SendEquipError(InventoryResult(msg), NULL, NULL); return true; } bool ChatHandler::HandleDebugSendSellErrorCommand(char* args) { if (!*args) { return false; } uint8 msg = atoi(args); m_session->GetPlayer()->SendSellError(SellResult(msg), 0, ObjectGuid(), 0); return true; } bool ChatHandler::HandleDebugSendBuyErrorCommand(char* args) { if (!*args) { return false; } uint8 msg = atoi(args); m_session->GetPlayer()->SendBuyError(BuyResult(msg), 0, 0, 0); return true; } bool ChatHandler::HandleDebugRecvOpcodeCommand(char* /*args*/) { Unit* unit = getSelectedUnit(); if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) { unit = m_session->GetPlayer(); } std::ifstream stream("ropcode.txt"); if (!stream.is_open()) { return false; } uint32 opcode = 0; if (!(stream >> opcode)) { stream.close(); return false; } WorldPacket *data = new WorldPacket(opcode, 10); std::string type; while (stream >> type) { if (type.empty()) { break; } if (type == "uint8") { uint16 value; stream >> value; *data << uint8(value); } else if (type == "uint16") { uint16 value; stream >> value; *data << value; } else if (type == "uint32") { uint32 value; stream >> value; *data << value; } else if (type == "uint64") { uint64 value; stream >> value; *data << value; } else if (type == "float") { float value; stream >> value; *data << value; } else if (type == "string") { std::string value; stream >> value; *data << value; } else if (type == "pguid") { *data << unit->GetPackGUID(); } else if (type == "guid") { *data << unit->GetObjectGuid(); } else if (type == "mypguid") { *data << m_session->GetPlayer()->GetPackGUID(); } else if (type == "myguid") { *data << m_session->GetPlayer()->GetObjectGuid(); } else if (type == "name") { *data << unit->GetName(); } else if (type == "myname") { *data << m_session->GetPlayerName(); } else { DEBUG_LOG("Sending opcode: unknown type '%s'", type.c_str()); break; } } stream.close(); DEBUG_LOG("Queued opcode %u, %s", data->GetOpcode(), data->GetOpcodeName()); m_session->QueuePacket(data); PSendSysMessage(LANG_COMMAND_OPCODEGOT, data->GetOpcode(), unit->GetName()); return true; } bool ChatHandler::HandleDebugSendOpcodeCommand(char* /*args*/) { Unit* unit = getSelectedUnit(); if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) { unit = m_session->GetPlayer(); } std::ifstream stream("opcode.txt"); if (!stream.is_open()) { return false; } uint32 opcode = 0; if (!(stream >> opcode)) { stream.close(); return false; } WorldPacket data(opcode, 0); std::string type; while (stream >> type) { if (type.empty()) { break; } if (type == "uint8") { uint16 value; stream >> value; data << uint8(value); } else if (type == "uint16") { uint16 value; stream >> value; data << value; } else if (type == "uint32") { uint32 value; stream >> value; data << value; } else if (type == "uint64") { uint64 value; stream >> value; data << value; } else if (type == "float") { float value; stream >> value; data << value; } else if (type == "string") { std::string value; stream >> value; data << value; } else if (type == "pguid") { data << unit->GetPackGUID(); } else if (type == "guid") { data << unit->GetObjectGuid(); } else if(type == "mypguid") { data << m_session->GetPlayer()->GetPackGUID(); } else if (type == "myguid") { data << m_session->GetPlayer()->GetObjectGuid(); } else if (type == "name") { data << unit->GetName(); } else if (type == "myname") { data << m_session->GetPlayerName(); } else { DEBUG_LOG("Sending opcode: unknown type '%s'", type.c_str()); break; } } stream.close(); DEBUG_LOG("Sending opcode %u, %s", data.GetOpcode(), data.GetOpcodeName()); data.hexlike(); unit->ToPlayer()->SendDirectMessage(&data); PSendSysMessage(LANG_COMMAND_OPCODESENT, data.GetOpcode(), unit->GetName()); return true; } bool ChatHandler::HandleDebugUpdateWorldStateCommand(char* args) { uint32 world; if (!ExtractUInt32(&args, world)) { return false; } uint32 state; if (!ExtractUInt32(&args, state)) { return false; } m_session->GetPlayer()->SendUpdateWorldState(world, state); return true; } bool ChatHandler::HandleDebugPlayCinematicCommand(char* args) { // USAGE: .debug play cinematic #cinematicid // #cinematicid - ID decimal number from CinemaicSequences.dbc (1st column) uint32 dwId; if (!ExtractUInt32(&args, dwId)) { return false; } if (!sCinematicSequencesStore.LookupEntry(dwId)) { PSendSysMessage(LANG_CINEMATIC_NOT_EXIST, dwId); SetSentErrorMessage(true); return false; } m_session->GetPlayer()->SendCinematicStart(dwId); return true; } // Play sound bool ChatHandler::HandleDebugPlaySoundCommand(char* args) { // USAGE: .debug playsound #soundid // #soundid - ID decimal number from SoundEntries.dbc (1st column) uint32 dwSoundId; if (!ExtractUInt32(&args, dwSoundId)) { return false; } if (!sSoundEntriesStore.LookupEntry(dwSoundId)) { PSendSysMessage(LANG_SOUND_NOT_EXIST, dwSoundId); SetSentErrorMessage(true); return false; } Unit* unit = getSelectedUnit(); if (!unit) { SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); SetSentErrorMessage(true); return false; } if (m_session->GetPlayer()->GetSelectionGuid()) { unit->PlayDistanceSound(dwSoundId, m_session->GetPlayer()); } else { unit->PlayDirectSound(dwSoundId, m_session->GetPlayer()); } PSendSysMessage(LANG_YOU_HEAR_SOUND, dwSoundId); return true; } // Send notification in channel bool ChatHandler::HandleDebugSendChannelNotifyCommand(char* args) { const char* name = "test"; uint32 code; if (!ExtractUInt32(&args, code) || code > 255) { return false; } WorldPacket data(SMSG_CHANNEL_NOTIFY, (1 + 10)); data << uint8(code); // notify type data << name; // channel name data << uint32(0); data << uint32(0); m_session->SendPacket(&data); return true; } // Send notification in chat bool ChatHandler::HandleDebugSendChatMsgCommand(char* args) { const char* msg = args; uint32 type; if (!ExtractUInt32(&args, type) || type > 255) { return false; } WorldPacket data; ChatHandler::BuildChatPacket(data, ChatMsg(type), msg, LANG_UNIVERSAL, CHAT_TAG_NONE, m_session->GetPlayer()->GetObjectGuid(), m_session->GetPlayerName()); m_session->SendPacket(&data); return true; } bool ChatHandler::HandleDebugSendQuestPartyMsgCommand(char* args) { uint32 msg; if (!ExtractUInt32(&args, msg)) { return false; } if (msg > 0xFF) { return false; } m_session->GetPlayer()->SendPushToPartyResponse(m_session->GetPlayer(), uint8(msg)); return true; } bool ChatHandler::HandleDebugGetLootRecipientCommand(char* /*args*/) { Creature* target = getSelectedCreature(); if (!target) { return false; } if (!target->HasLootRecipient()) { SendSysMessage("loot recipient: no loot recipient"); } else if (Player* recipient = target->GetLootRecipient()) PSendSysMessage("loot recipient: %s with raw data %s from group %u", recipient->GetGuidStr().c_str(), target->GetLootRecipientGuid().GetString().c_str(), target->GetLootGroupRecipientId()); else { SendSysMessage("loot recipient: offline "); } return true; } bool ChatHandler::HandleDebugSendQuestInvalidMsgCommand(char* args) { uint32 msg = atol(args); m_session->GetPlayer()->SendCanTakeQuestResponse(msg); return true; } bool ChatHandler::HandleDebugGetItemStateCommand(char* args) { if (!*args) { return false; } ItemUpdateState state = ITEM_UNCHANGED; bool list_queue = false, check_all = false; std::string state_str; if (strncmp(args, "unchanged", strlen(args)) == 0) { state = ITEM_UNCHANGED; state_str = "unchanged"; } else if (strncmp(args, "changed", strlen(args)) == 0) { state = ITEM_CHANGED; state_str = "changed"; } else if (strncmp(args, "new", strlen(args)) == 0) { state = ITEM_NEW; state_str = "new"; } else if (strncmp(args, "removed", strlen(args)) == 0) { state = ITEM_REMOVED; state_str = "removed"; } else if (strncmp(args, "queue", strlen(args)) == 0) { list_queue = true; } else if (strncmp(args, "all", strlen(args)) == 0) { check_all = true; } else { return false; } Player* player = getSelectedPlayer(); if (!player) { player = m_session->GetPlayer(); } if (!list_queue && !check_all) { state_str = "The player has the following " + state_str + " items: "; SendSysMessage(state_str.c_str()); for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i) { if (i >= BUYBACK_SLOT_START && i < BUYBACK_SLOT_END) { continue; } Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (!item) { continue; } if (!item->IsBag()) { if (item->GetState() == state) PSendSysMessage("%s bag: 255 slot: %u owner: %s", item->GetGuidStr().c_str(), item->GetSlot(), item->GetOwnerGuid().GetString().c_str()); } else { Bag* bag = (Bag*)item; for (uint8 j = 0; j < bag->GetBagSize(); ++j) { Item* item2 = bag->GetItemByPos(j); if (item2 && item2->GetState() == state) PSendSysMessage("%s bag: %u slot: %u owner: %s", item2->GetGuidStr().c_str(), item2->GetBagSlot(), item2->GetSlot(), item2->GetOwnerGuid().GetString().c_str()); } } } } if (list_queue) { std::vector& updateQueue = player->GetItemUpdateQueue(); for (size_t i = 0; i < updateQueue.size(); ++i) { Item* item = updateQueue[i]; if (!item) { continue; } Bag* container = item->GetContainer(); uint8 bag_slot = container ? container->GetSlot() : uint8(INVENTORY_SLOT_BAG_0); std::string st; switch (item->GetState()) { case ITEM_UNCHANGED: st = "unchanged"; break; case ITEM_CHANGED: st = "changed"; break; case ITEM_NEW: st = "new"; break; case ITEM_REMOVED: st = "removed"; break; } PSendSysMessage("%s bag: %u slot: %u - state: %s", item->GetGuidStr().c_str(), bag_slot, item->GetSlot(), st.c_str()); } if (updateQueue.empty()) { PSendSysMessage("updatequeue empty"); } } if (check_all) { bool error = false; std::vector& updateQueue = player->GetItemUpdateQueue(); for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i) { if (i >= BUYBACK_SLOT_START && i < BUYBACK_SLOT_END) { continue; } Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (!item) { continue; } if (item->GetSlot() != i) { PSendSysMessage("%s at slot %u has an incorrect slot value: %d", item->GetGuidStr().c_str(), i, item->GetSlot()); error = true; continue; } if (item->GetOwnerGuid() != player->GetObjectGuid()) { PSendSysMessage("%s at slot %u owner (%s) and inventory owner (%s) don't match!", item->GetGuidStr().c_str(), item->GetSlot(), item->GetOwnerGuid().GetString().c_str(), player->GetGuidStr().c_str()); error = true; continue; } if (Bag* container = item->GetContainer()) { PSendSysMessage("%s at slot %u has a container %s from slot %u but shouldnt!", item->GetGuidStr().c_str(), item->GetSlot(), container->GetGuidStr().c_str(), container->GetSlot()); error = true; continue; } if (item->IsInUpdateQueue()) { uint16 qp = item->GetQueuePos(); if (qp > updateQueue.size()) { PSendSysMessage("%s at slot %u has a queuepos (%d) larger than the update queue size! ", item->GetGuidStr().c_str(), item->GetSlot(), qp); error = true; continue; } if (updateQueue[qp] == NULL) { PSendSysMessage("%s at slot %u has a queuepos (%d) that points to NULL in the queue!", item->GetGuidStr().c_str(), item->GetSlot(), qp); error = true; continue; } if (updateQueue[qp] != item) { PSendSysMessage("%s at slot %u has a queuepos (%d) that points to %s in the queue (bag %u, slot %u)", item->GetGuidStr().c_str(), item->GetSlot(), qp, updateQueue[qp]->GetGuidStr().c_str(), updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot()); error = true; continue; } } else if (item->GetState() != ITEM_UNCHANGED) { PSendSysMessage("%s at slot %u is not in queue but should be (state: %d)!", item->GetGuidStr().c_str(), item->GetSlot(), item->GetState()); error = true; continue; } if (item->IsBag()) { Bag* bag = (Bag*)item; for (uint8 j = 0; j < bag->GetBagSize(); ++j) { Item* item2 = bag->GetItemByPos(j); if (!item2) { continue; } if (item2->GetSlot() != j) { PSendSysMessage("%s in bag %u at slot %u has an incorrect slot value: %u", item2->GetGuidStr().c_str(), bag->GetSlot(), j, item2->GetSlot()); error = true; continue; } if (item2->GetOwnerGuid() != player->GetObjectGuid()) { PSendSysMessage("%s in bag %u at slot %u owner (%s) and inventory owner (%s) don't match!", item2->GetGuidStr().c_str(), bag->GetSlot(), item2->GetSlot(), item2->GetOwnerGuid().GetString().c_str(), player->GetGuidStr().c_str()); error = true; continue; } Bag* container = item2->GetContainer(); if (!container) { PSendSysMessage("%s in bag %u at slot %u has no container!", item2->GetGuidStr().c_str(), bag->GetSlot(), item2->GetSlot()); error = true; continue; } if (container != bag) { PSendSysMessage("%s in bag %u at slot %u has a different container %s from slot %u!", item2->GetGuidStr().c_str(), bag->GetSlot(), item2->GetSlot(), container->GetGuidStr().c_str(), container->GetSlot()); error = true; continue; } if (item2->IsInUpdateQueue()) { uint16 qp = item2->GetQueuePos(); if (qp > updateQueue.size()) { PSendSysMessage("%s in bag %u at slot %u has a queuepos (%d) larger than the update queue size! ", item2->GetGuidStr().c_str(), bag->GetSlot(), item2->GetSlot(), qp); error = true; continue; } if (updateQueue[qp] == NULL) { PSendSysMessage("%s in bag %u at slot %u has a queuepos (%d) that points to NULL in the queue!", item2->GetGuidStr().c_str(), bag->GetSlot(), item2->GetSlot(), qp); error = true; continue; } if (updateQueue[qp] != item2) { PSendSysMessage("%s in bag %u at slot %u has a queuepos (%d) that points to %s in the queue (bag %u slot %u)", item2->GetGuidStr().c_str(), bag->GetSlot(), item2->GetSlot(), qp, updateQueue[qp]->GetGuidStr().c_str(), updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot()); error = true; continue; } } else if (item2->GetState() != ITEM_UNCHANGED) { PSendSysMessage("%s in bag %u at slot %u is not in queue but should be (state: %d)!", item2->GetGuidStr().c_str(), bag->GetSlot(), item2->GetSlot(), item2->GetState()); error = true; continue; } } } } for (size_t i = 0; i < updateQueue.size(); ++i) { Item* item = updateQueue[i]; if (!item) { continue; } if (item->GetOwnerGuid() != player->GetObjectGuid()) { PSendSysMessage("queue(" SIZEFMTD "): %s has the owner (%s) and inventory owner (%s) don't match!", i, item->GetGuidStr().c_str(), item->GetOwnerGuid().GetString().c_str(), player->GetGuidStr().c_str()); error = true; continue; } if (item->GetQueuePos() != i) { PSendSysMessage("queue(" SIZEFMTD "): %s has queuepos doesn't match it's position in the queue!", i, item->GetGuidStr().c_str()); error = true; continue; } if (item->GetState() == ITEM_REMOVED) { continue; } Item* test = player->GetItemByPos(item->GetBagSlot(), item->GetSlot()); if (test == NULL) { PSendSysMessage("queue(" SIZEFMTD "): %s has incorrect (bag %u slot %u) values, the player doesn't have an item at that position!", i, item->GetGuidStr().c_str(), item->GetBagSlot(), item->GetSlot()); error = true; continue; } if (test != item) { PSendSysMessage("queue(" SIZEFMTD "): %s has incorrect (bag %u slot %u) values, the %s is there instead!", i, item->GetGuidStr().c_str(), item->GetBagSlot(), item->GetSlot(), test->GetGuidStr().c_str()); error = true; continue; } } if (!error) { SendSysMessage("All OK!"); } } return true; } bool ChatHandler::HandleDebugBattlegroundCommand(char* /*args*/) { sBattleGroundMgr.ToggleTesting(); return true; } bool ChatHandler::HandleDebugSpellCheckCommand(char* /*args*/) { sLog.outString("Check expected in code spell properties base at table 'spell_check' content..."); sSpellMgr.CheckUsedSpells("spell_check"); return true; } // show animation bool ChatHandler::HandleDebugAnimCommand(char* args) { uint32 emote_id; if (!ExtractUInt32(&args, emote_id)) { return false; } m_session->GetPlayer()->HandleEmoteCommand(emote_id); return true; } bool ChatHandler::HandleDebugSetAuraStateCommand(char* args) { int32 state; if (!ExtractInt32(&args, state)) { return false; } Unit* unit = getSelectedUnit(); if (!unit) { SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); SetSentErrorMessage(true); return false; } if (!state) { // reset all states for (int i = 1; i <= 32; ++i) { unit->ModifyAuraState(AuraState(i), false); } return true; } unit->ModifyAuraState(AuraState(abs(state)), state > 0); return true; } bool ChatHandler::HandleSetValueHelper(Object* target, uint32 field, char* typeStr, char* valStr) { ObjectGuid guid = target->GetObjectGuid(); // not allow access to nonexistent or critical for work field if (field >= target->GetValuesCount() || field <= OBJECT_FIELD_ENTRY) { PSendSysMessage(LANG_TOO_BIG_INDEX, field, guid.GetString().c_str(), target->GetValuesCount()); return false; } uint32 base; // 0 -> float if (!typeStr) { base = 10; } else if (strncmp(typeStr, "int", strlen(typeStr)) == 0) { base = 10; } else if (strncmp(typeStr, "hex", strlen(typeStr)) == 0) { base = 16; } else if (strncmp(typeStr, "bit", strlen(typeStr)) == 0) { base = 2; } else if (strncmp(typeStr, "float", strlen(typeStr)) == 0) { base = 0; } else { return false; } if (base) { uint32 iValue; if (!ExtractUInt32Base(&valStr, iValue, base)) { return false; } DEBUG_LOG(GetMangosString(LANG_SET_UINT), guid.GetString().c_str(), field, iValue); target->SetUInt32Value(field , iValue); PSendSysMessage(LANG_SET_UINT_FIELD, guid.GetString().c_str(), field, iValue); } else { float fValue; if (!ExtractFloat(&valStr, fValue)) { return false; } DEBUG_LOG(GetMangosString(LANG_SET_FLOAT), guid.GetString().c_str(), field, fValue); target->SetFloatValue(field , fValue); PSendSysMessage(LANG_SET_FLOAT_FIELD, guid.GetString().c_str(), field, fValue); } return true; } bool ChatHandler::HandleDebugSetItemValueCommand(char* args) { uint32 guid; if (!ExtractUInt32(&args, guid)) { return false; } uint32 field; if (!ExtractUInt32(&args, field)) { return false; } char* typeStr = ExtractOptNotLastArg(&args); if (!typeStr) { return false; } char* valStr = ExtractLiteralArg(&args); if (!valStr) { return false; } Item* item = m_session->GetPlayer()->GetItemByGuid(ObjectGuid(HIGHGUID_ITEM, guid)); if (!item) { return false; } return HandleSetValueHelper(item, field, typeStr, valStr); } bool ChatHandler::HandleDebugSetValueCommand(char* args) { Unit* target = getSelectedUnit(); if (!target) { SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); SetSentErrorMessage(true); return false; } uint32 field; if (!ExtractUInt32(&args, field)) { return false; } char* typeStr = ExtractOptNotLastArg(&args); if (!typeStr) { return false; } char* valStr = ExtractLiteralArg(&args); if (!valStr) { return false; } return HandleSetValueHelper(target, field, typeStr, valStr); } bool ChatHandler::HandleGetValueHelper(Object* target, uint32 field, char* typeStr) { ObjectGuid guid = target->GetObjectGuid(); if (field >= target->GetValuesCount()) { PSendSysMessage(LANG_TOO_BIG_INDEX, field, guid.GetString().c_str(), target->GetValuesCount()); return false; } uint32 base; // 0 -> float if (!typeStr) { base = 10; } else if (strncmp(typeStr, "int", strlen(typeStr)) == 0) { base = 10; } else if (strncmp(typeStr, "hex", strlen(typeStr)) == 0) { base = 16; } else if (strncmp(typeStr, "bit", strlen(typeStr)) == 0) { base = 2; } else if (strncmp(typeStr, "float", strlen(typeStr)) == 0) { base = 0; } else { return false; } if (base) { uint32 iValue = target->GetUInt32Value(field); switch (base) { case 2: { // starting 0 if need as required bitstring format std::string res; res.reserve(1 + 32 + 1); res = (iValue & (1 << (32 - 1))) ? "0" : " "; for (int i = 32; i > 0; --i) { res += (iValue & (1 << (i - 1))) ? "1" : "0"; } DEBUG_LOG(GetMangosString(LANG_GET_BITSTR), guid.GetString().c_str(), field, res.c_str()); PSendSysMessage(LANG_GET_BITSTR_FIELD, guid.GetString().c_str(), field, res.c_str()); break; } case 16: DEBUG_LOG(GetMangosString(LANG_GET_HEX), guid.GetString().c_str(), field, iValue); PSendSysMessage(LANG_GET_HEX_FIELD, guid.GetString().c_str(), field, iValue); break; case 10: default: DEBUG_LOG(GetMangosString(LANG_GET_UINT), guid.GetString().c_str(), field, iValue); PSendSysMessage(LANG_GET_UINT_FIELD, guid.GetString().c_str(), field, iValue); } } else { float fValue = target->GetFloatValue(field); DEBUG_LOG(GetMangosString(LANG_GET_FLOAT), guid.GetString().c_str(), field, fValue); PSendSysMessage(LANG_GET_FLOAT_FIELD, guid.GetString().c_str(), field, fValue); } return true; } bool ChatHandler::HandleDebugGetItemValueCommand(char* args) { uint32 guid; if (!ExtractUInt32(&args, guid)) { return false; } uint32 field; if (!ExtractUInt32(&args, field)) { return false; } char* typeStr = ExtractLiteralArg(&args); if (!typeStr && *args) // optional arg but check format fail case { return false; } Item* item = m_session->GetPlayer()->GetItemByGuid(ObjectGuid(HIGHGUID_ITEM, guid)); if (!item) { return false; } return HandleGetValueHelper(item, field, typeStr); } bool ChatHandler::HandleDebugGetValueCommand(char* args) { Unit* target = getSelectedUnit(); if (!target) { SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); SetSentErrorMessage(true); return false; } uint32 field; if (!ExtractUInt32(&args, field)) { return false; } char* typeStr = ExtractLiteralArg(&args); if (!typeStr && *args) // optional arg but check format fail case { return false; } return HandleGetValueHelper(target, field, typeStr); } bool ChatHandler::HandlerDebugModValueHelper(Object* target, uint32 field, char* typeStr, char* valStr) { ObjectGuid guid = target->GetObjectGuid(); // not allow access to nonexistent or critical for work field if (field >= target->GetValuesCount() || field <= OBJECT_FIELD_ENTRY) { PSendSysMessage(LANG_TOO_BIG_INDEX, field, guid.GetString().c_str(), target->GetValuesCount()); return false; } uint32 type; // 0 -> float 1 -> int add 2-> bit or 3 -> bit and 4 -> bit and not if (strncmp(typeStr, "int", strlen(typeStr)) == 0) { type = 1; } else if (strncmp(typeStr, "float", strlen(typeStr)) == 0) { type = 0; } else if (strncmp(typeStr, "|=", strlen("|=") + 1) == 0) // exactly copy { type = 2; } else if (strncmp(typeStr, "&=", strlen("&=") + 1) == 0) // exactly copy { type = 3; } else if (strncmp(typeStr, "&=~", strlen("&=~") + 1) == 0) // exactly copy { type = 4; } else { return false; } if (type) { uint32 iValue; if (!ExtractUInt32Base(&valStr, iValue, type == 1 ? 10 : 16)) { return false; } uint32 value = target->GetUInt32Value(field); const char* guidString = guid.GetString().c_str(); switch (type) { default: case 1: // int + value = uint32(int32(value) + int32(iValue)); DEBUG_LOG(GetMangosString(LANG_CHANGE_INT32), guidString, field, iValue, value, value); PSendSysMessage(LANG_CHANGE_INT32_FIELD, guidString, field, iValue, value, value); break; case 2: // |= bit or value |= iValue; DEBUG_LOG(GetMangosString(LANG_CHANGE_HEX), guidString, field, typeStr, iValue, value); PSendSysMessage(LANG_CHANGE_HEX_FIELD, guidString, field, typeStr, iValue, value); break; case 3: // &= bit and value &= iValue; DEBUG_LOG(GetMangosString(LANG_CHANGE_HEX), guidString, field, typeStr, iValue, value); PSendSysMessage(LANG_CHANGE_HEX_FIELD, guidString, field, typeStr, iValue, value); break; case 4: // &=~ bit and not value &= ~iValue; DEBUG_LOG(GetMangosString(LANG_CHANGE_HEX), guidString, field, typeStr, iValue, value); PSendSysMessage(LANG_CHANGE_HEX_FIELD, guidString, field, typeStr, iValue, value); break; } target->SetUInt32Value(field, value); } else { float fValue; if (!ExtractFloat(&valStr, fValue)) { return false; } float value = target->GetFloatValue(field); value += fValue; DEBUG_LOG(GetMangosString(LANG_CHANGE_FLOAT), guid.GetString().c_str(), field, fValue, value); PSendSysMessage(LANG_CHANGE_FLOAT_FIELD, guid.GetString().c_str(), field, fValue, value); target->SetFloatValue(field, value); } return true; } bool ChatHandler::HandleDebugModItemValueCommand(char* args) { uint32 guid; if (!ExtractUInt32(&args, guid)) { return false; } uint32 field; if (!ExtractUInt32(&args, field)) { return false; } char* typeStr = ExtractLiteralArg(&args); if (!typeStr) { return false; } char* valStr = ExtractLiteralArg(&args); if (!valStr) { return false; } Item* item = m_session->GetPlayer()->GetItemByGuid(ObjectGuid(HIGHGUID_ITEM, guid)); if (!item) { return false; } return HandlerDebugModValueHelper(item, field, typeStr, valStr); } bool ChatHandler::HandleDebugModValueCommand(char* args) { Unit* target = getSelectedUnit(); if (!target) { SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); SetSentErrorMessage(true); return false; } uint32 field; if (!ExtractUInt32(&args, field)) { return false; } char* typeStr = ExtractLiteralArg(&args); if (!typeStr && *args) // optional arg but check format fail case { return false; } char* valStr = ExtractLiteralArg(&args); if (!valStr) { return false; } return HandlerDebugModValueHelper(target, field, typeStr, valStr); } bool ChatHandler::HandleDebugSpellCoefsCommand(char* args) { uint32 spellid = ExtractSpellIdFromLink(&args); if (!spellid) { return false; } SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellid); if (!spellEntry) { return false; } SpellBonusEntry const* bonus = sSpellMgr.GetSpellBonusData(spellid); float direct_calc = CalculateDefaultCoefficient(spellEntry, SPELL_DIRECT_DAMAGE); float dot_calc = CalculateDefaultCoefficient(spellEntry, DOT); bool isDirectHeal = false; for (int i = 0; i < 3; ++i) { // Heals (Also count Mana Shield and Absorb effects as heals) if (spellEntry->Effect[i] == SPELL_EFFECT_HEAL || spellEntry->Effect[i] == SPELL_EFFECT_HEAL_MAX_HEALTH || (spellEntry->Effect[i] == SPELL_EFFECT_APPLY_AURA && (spellEntry->EffectApplyAuraName[i] == SPELL_AURA_SCHOOL_ABSORB || spellEntry->EffectApplyAuraName[i] == SPELL_AURA_PERIODIC_HEAL))) { isDirectHeal = true; break; } } bool isDotHeal = false; for (int i = 0; i < 3; ++i) { // Periodic Heals if (spellEntry->Effect[i] == SPELL_EFFECT_APPLY_AURA && spellEntry->EffectApplyAuraName[i] == SPELL_AURA_PERIODIC_HEAL) { isDotHeal = true; break; } } char const* directHealStr = GetMangosString(LANG_DIRECT_HEAL); char const* directDamageStr = GetMangosString(LANG_DIRECT_DAMAGE); char const* dotHealStr = GetMangosString(LANG_DOT_HEAL); char const* dotDamageStr = GetMangosString(LANG_DOT_DAMAGE); PSendSysMessage(LANG_SPELLCOEFS, spellid, isDirectHeal ? directHealStr : directDamageStr, direct_calc, direct_calc * 1.88f, bonus ? bonus->direct_damage : 0.0f, bonus ? bonus->ap_bonus : 0.0f); PSendSysMessage(LANG_SPELLCOEFS, spellid, isDotHeal ? dotHealStr : dotDamageStr, dot_calc, dot_calc * 1.88f, bonus ? bonus->dot_damage : 0.0f, bonus ? bonus->ap_dot_bonus : 0.0f); return true; } bool ChatHandler::HandleDebugSpellModsCommand(char* args) { char* typeStr = ExtractLiteralArg(&args); if (!typeStr) { return false; } uint16 opcode; if (strncmp(typeStr, "flat", strlen(typeStr)) == 0) { opcode = SMSG_SET_FLAT_SPELL_MODIFIER; } else if (strncmp(typeStr, "pct", strlen(typeStr)) == 0) { opcode = SMSG_SET_PCT_SPELL_MODIFIER; } else { return false; } uint32 effidx; if (!ExtractUInt32(&args, effidx) || effidx >= 64) { return false; } uint32 spellmodop; if (!ExtractUInt32(&args, spellmodop) || spellmodop >= MAX_SPELLMOD) { return false; } int32 value; if (!ExtractInt32(&args, value)) { 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_SPELLMODS, opcode == SMSG_SET_FLAT_SPELL_MODIFIER ? "flat" : "pct", spellmodop, value, effidx, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLMODS_CHANGED, GetNameLink().c_str(), opcode == SMSG_SET_FLAT_SPELL_MODIFIER ? "flat" : "pct", spellmodop, value, effidx); WorldPacket data(opcode, (1 + 1 + 2 + 2)); data << uint8(effidx); data << uint8(spellmodop); data << int32(value); chr->GetSession()->SendPacket(&data); return true; }