/* * Copyright (C) 2005-2012 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 */ #include "Common.h" #include "Database/DatabaseEnv.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 "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, 5); data << uint8(0); data << uint32(133); 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::HandleDebugSendOpcodeCommand(char* /*args*/) { Unit* unit = getSelectedUnit(); if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) unit = m_session->GetPlayer(); std::ifstream ifs("opcode.txt"); if (ifs.bad()) return false; uint32 opcode; ifs >> opcode; WorldPacket data(opcode, 0); while (!ifs.eof()) { std::string type; ifs >> type; if (type == "") break; if (type == "uint8") { uint16 val1; ifs >> val1; data << uint8(val1); } else if (type == "uint16") { uint16 val2; ifs >> val2; data << val2; } else if (type == "uint32") { uint32 val3; ifs >> val3; data << val3; } else if (type == "uint64") { uint64 val4; ifs >> val4; data << val4; } else if (type == "float") { float val5; ifs >> val5; data << val5; } else if (type == "string") { std::string val6; ifs >> val6; data << val6; } else if (type == "pguid") { data << unit->GetPackGUID(); } else { DEBUG_LOG("Sending opcode: unknown type '%s'", type.c_str()); break; } } ifs.close(); DEBUG_LOG("Sending opcode %u", data.GetOpcode()); data.hexlike(); ((Player*)unit)->GetSession()->SendPacket(&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; } bool ChatHandler::HandleDebugPlayMovieCommand(char* args) { // USAGE: .debug play movie #movieid // #movieid - ID decimal number from Movie.dbc (1st column) uint32 dwId; if (!ExtractUInt32(&args, dwId)) return false; if (!sMovieStore.LookupEntry(dwId)) { PSendSysMessage(LANG_MOVIE_NOT_EXIST, dwId); SetSentErrorMessage(true); return false; } m_session->GetPlayer()->SendMovieStart(dwId); return true; } // Play sound bool ChatHandler::HandleDebugPlaySoundCommand(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 = "testtest"; uint32 type; if (!ExtractUInt32(&args, type) || type > 255) return false; WorldPacket data; ChatHandler::FillMessageData(&data, m_session, type, 0, "chan", m_session->GetPlayer()->GetObjectGuid(), msg, m_session->GetPlayer()); m_session->SendPacket(&data); return true; } bool ChatHandler::HandleDebugSendQuestPartyMsgCommand(char* args) { uint32 msg; if (!ExtractUInt32(&args, msg)) return false; m_session->GetPlayer()->SendPushToPartyResponse(m_session->GetPlayer(), 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::HandleDebugArenaCommand(char* /*args*/) { sBattleGroundMgr.ToggleArenaTesting(); 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; } bool ChatHandler::HandleDebugSendLargePacketCommand(char* /*args*/) { const char* stuffingString = "This is a dummy string to push the packet's size beyond 128000 bytes. "; std::ostringstream ss; while (ss.str().size() < 128000) ss << stuffingString; SendSysMessage(ss.str().c_str()); return true; } bool ChatHandler::HandleDebugSendSetPhaseShiftCommand(char* args) { if (!*args) return false; uint32 PhaseShift = atoi(args); m_session->SendSetPhaseShift(PhaseShift); 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); switch (type) { default: case 1: // int + value = uint32(int32(value) + int32(iValue)); DEBUG_LOG(GetMangosString(LANG_CHANGE_INT32), guid.GetString().c_str(), field, iValue, value, value); PSendSysMessage(LANG_CHANGE_INT32_FIELD, guid.GetString().c_str(), field, iValue, value, value); break; case 2: // |= bit or value |= iValue; DEBUG_LOG(GetMangosString(LANG_CHANGE_HEX), guid.GetString().c_str(), field, typeStr, iValue, value); PSendSysMessage(LANG_CHANGE_HEX_FIELD, guid.GetString().c_str(), field, typeStr, iValue, value); break; case 3: // &= bit and value &= iValue; DEBUG_LOG(GetMangosString(LANG_CHANGE_HEX), guid.GetString().c_str(), field, typeStr, iValue, value); PSendSysMessage(LANG_CHANGE_HEX_FIELD, guid.GetString().c_str(), field, typeStr, iValue, value); break; case 4: // &=~ bit and not value &= ~iValue; DEBUG_LOG(GetMangosString(LANG_CHANGE_HEX), guid.GetString().c_str(), field, typeStr, iValue, value); PSendSysMessage(LANG_CHANGE_HEX_FIELD, guid.GetString().c_str(), 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) { SpellEffectEntry const* spellEffect = spellEntry->GetSpellEffect(SpellEffectIndex(i)); if(!spellEffect) continue; // Heals (Also count Mana Shield and Absorb effects as heals) if (spellEffect->Effect == SPELL_EFFECT_HEAL || spellEffect->Effect == SPELL_EFFECT_HEAL_MAX_HEALTH || (spellEffect->Effect == SPELL_EFFECT_APPLY_AURA && (spellEffect->EffectApplyAuraName == SPELL_AURA_SCHOOL_ABSORB || spellEffect->EffectApplyAuraName == SPELL_AURA_PERIODIC_HEAL))) { isDirectHeal = true; break; } } bool isDotHeal = false; for (int i = 0; i < 3; ++i) { SpellEffectEntry const* spellEffect = spellEntry->GetSpellEffect(SpellEffectIndex(i)); if(!spellEffect) continue; // Periodic Heals if (spellEffect->Effect == SPELL_EFFECT_APPLY_AURA && spellEffect->EffectApplyAuraName == 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 + 32) 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; }