mangos/src/game/ChatCommands/debugcmds.cpp
2018-04-12 15:46:05 +01:00

1213 lines
39 KiB
C++

/**
* 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-2018 MaNGOS project <https://getmangos.eu>
*
* 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 <fstream>
#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<Item*>& updateQueue = player->GetItemUpdateQueue();
for (size_t i = 0; i < updateQueue.size(); ++i)
{
Item* item = updateQueue[i];
if (!item) { continue; }
Bag* container = item->GetContainer();
uint8 bag_slot = container ? container->GetSlot() : uint8(INVENTORY_SLOT_BAG_0);
std::string st;
switch (item->GetState())
{
case ITEM_UNCHANGED: st = "unchanged"; break;
case ITEM_CHANGED: st = "changed"; break;
case ITEM_NEW: st = "new"; break;
case ITEM_REMOVED: st = "removed"; break;
}
PSendSysMessage("%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<Item*>& updateQueue = player->GetItemUpdateQueue();
for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i)
{
if (i >= BUYBACK_SLOT_START && i < BUYBACK_SLOT_END)
{ continue; }
Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i);
if (!item) { continue; }
if (item->GetSlot() != i)
{
PSendSysMessage("%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;
}