1213 lines
39 KiB
C++
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;
|
|
}
|