/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
/* ScriptData
Name: list_commandscript
%Complete: 100
Comment: All list related commands
Category: commandscripts
EndScriptData */
#include "Chat.h"
#include "CommandScript.h"
#include "Creature.h"
#include "DBCStores.h"
#include "DatabaseEnv.h"
#include "GameObject.h"
#include "Language.h"
#include "MapMgr.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "Random.h"
#include "SpellAuraEffects.h"
using namespace Acore::ChatCommands;
class list_commandscript : public CommandScript
{
public:
list_commandscript() : CommandScript("list_commandscript") { }
ChatCommandTable GetCommands() const override
{
static ChatCommandTable listAurasCommandTable =
{
{ "", HandleListAllAurasCommand, SEC_MODERATOR, Console::No },
{ "id", HandleListAurasByIdCommand, SEC_MODERATOR, Console::No },
{ "name", HandleListAurasByNameCommand, SEC_MODERATOR, Console::No },
};
static ChatCommandTable listCommandTable =
{
{ "creature", HandleListCreatureCommand, SEC_MODERATOR, Console::Yes },
{ "item", HandleListItemCommand, SEC_MODERATOR, Console::Yes },
{ "object", HandleListObjectCommand, SEC_MODERATOR, Console::Yes },
{ "auras", listAurasCommandTable },
};
static ChatCommandTable commandTable =
{
{ "list", listCommandTable }
};
return commandTable;
}
static bool HandleListCreatureCommand(ChatHandler* handler, Variant, uint32> creatureId, Optional countArg)
{
CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creatureId);
if (!cInfo)
{
handler->SendErrorMessage(LANG_COMMAND_INVALIDCREATUREID, uint32(creatureId));
return false;
}
uint32 count = countArg.value_or(10);
if (count == 0)
return false;
QueryResult result;
uint32 creatureCount = 0;
result = WorldDatabase.Query("SELECT COUNT(guid) FROM creature WHERE id1='{}' OR id2='{}' OR id3='{}'", uint32(creatureId), uint32(creatureId), uint32(creatureId));
if (result)
creatureCount = (*result)[0].Get();
if (handler->GetSession())
{
Player* player = handler->GetSession()->GetPlayer();
result = WorldDatabase.Query("SELECT guid, position_x, position_y, position_z, map, (POW(position_x - '{}', 2) + POW(position_y - '{}', 2) + POW(position_z - '{}', 2)) AS order_ FROM creature WHERE id1='{}' OR id2='{}' OR id3='{}' ORDER BY order_ ASC LIMIT {}",
player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), uint32(creatureId), uint32(creatureId), uint32(creatureId), count);
}
else
result = WorldDatabase.Query("SELECT guid, position_x, position_y, position_z, map FROM creature WHERE id1='{}' OR id2='{}' OR id3='{}' LIMIT {}",
uint32(creatureId), uint32(creatureId), uint32(creatureId), count);
if (result)
{
do
{
Field* fields = result->Fetch();
ObjectGuid::LowType guid = fields[0].Get();
float x = fields[1].Get();
float y = fields[2].Get();
float z = fields[3].Get();
uint16 mapId = fields[4].Get();
bool liveFound = false;
// Get map (only support base map from console)
Map* thisMap;
if (handler->GetSession())
thisMap = handler->GetSession()->GetPlayer()->GetMap();
else
thisMap = sMapMgr->FindBaseNonInstanceMap(mapId);
// If map found, try to find active version of this creature
if (thisMap)
{
auto const creBounds = thisMap->GetCreatureBySpawnIdStore().equal_range(guid);
if (creBounds.first != creBounds.second)
{
for (std::unordered_multimap::const_iterator itr = creBounds.first; itr != creBounds.second;)
{
if (handler->GetSession())
handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, cInfo->Entry, guid, cInfo->Name, x, y, z, mapId, itr->second->GetGUID().ToString(), itr->second->IsAlive() ? "*" : " ");
else
handler->PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name, x, y, z, mapId, itr->second->GetGUID().ToString(), itr->second->IsAlive() ? "*" : " ");
++itr;
}
liveFound = true;
}
}
if (!liveFound)
{
if (handler->GetSession())
handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, cInfo->Entry, guid, cInfo->Name, x, y, z, mapId, "", "");
else
handler->PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name, x, y, z, mapId, "", "");
}
}
while (result->NextRow());
}
handler->PSendSysMessage(LANG_COMMAND_LISTCREATUREMESSAGE, uint32(creatureId), creatureCount);
return true;
}
static bool HandleListItemCommand(ChatHandler* handler, Variant, uint32> itemArg, Optional countArg)
{
uint32 itemId = 0;
uint32 count = countArg.value_or(10);
if (itemArg.holds_alternative>())
{
itemId = itemArg.get>()->Item->ItemId;
}
else
{
itemId = itemArg.get();
}
if (!count || !itemId)
return false;
PreparedQueryResult result;
// inventory case
uint32 inventoryCount = 0;
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM);
stmt->SetData(0, itemId);
result = CharacterDatabase.Query(stmt);
if (result)
inventoryCount = (*result)[0].Get();
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY);
stmt->SetData(0, itemId);
stmt->SetData(1, count);
result = CharacterDatabase.Query(stmt);
if (result)
{
do
{
Field* fields = result->Fetch();
uint32 itemGuid = fields[0].Get();
uint32 itemBag = fields[1].Get();
uint8 itemSlot = fields[2].Get();
uint32 ownerGuid = fields[3].Get();
uint32 ownerAccountId = fields[4].Get();
std::string ownerName = fields[5].Get();
char const* itemPos = nullptr;
if (Player::IsEquipmentPos(itemBag, itemSlot))
itemPos = "[equipped]";
else if (Player::IsInventoryPos(itemBag, itemSlot))
itemPos = "[in inventory]";
else if (Player::IsBankPos(itemBag, itemSlot))
itemPos = "[in bank]";
else
itemPos = "";
handler->PSendSysMessage(LANG_ITEMLIST_SLOT, itemGuid, ownerName, ownerGuid, ownerAccountId, itemPos);
}
while (result->NextRow());
uint32 resultCount = uint32(result->GetRowCount());
if (count > resultCount)
count -= resultCount;
else
count = 0;
}
// mail case
uint32 mailCount = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_COUNT_ITEM);
stmt->SetData(0, itemId);
result = CharacterDatabase.Query(stmt);
if (result)
mailCount = (*result)[0].Get();
if (count > 0)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_ITEMS_BY_ENTRY);
stmt->SetData(0, itemId);
stmt->SetData(1, count);
result = CharacterDatabase.Query(stmt);
}
else
result = PreparedQueryResult(nullptr);
if (result)
{
do
{
Field* fields = result->Fetch();
ObjectGuid::LowType itemGuid = fields[0].Get();
ObjectGuid::LowType itemSender = fields[1].Get();
uint32 itemReceiver = fields[2].Get();
uint32 itemSenderAccountId = fields[3].Get();
std::string itemSenderName = fields[4].Get();
uint32 itemReceiverAccount = fields[5].Get();
std::string itemReceiverName = fields[6].Get();
char const* itemPos = "[in mail]";
handler->PSendSysMessage(LANG_ITEMLIST_MAIL, itemGuid, itemSenderName, itemSender, itemSenderAccountId, itemReceiverName, itemReceiver, itemReceiverAccount, itemPos);
}
while (result->NextRow());
uint32 resultCount = uint32(result->GetRowCount());
if (count > resultCount)
count -= resultCount;
else
count = 0;
}
// auction case
uint32 auctionCount = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_AUCTIONHOUSE_COUNT_ITEM);
stmt->SetData(0, itemId);
result = CharacterDatabase.Query(stmt);
if (result)
auctionCount = (*result)[0].Get();
if (count > 0)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_AUCTIONHOUSE_ITEM_BY_ENTRY);
stmt->SetData(0, itemId);
stmt->SetData(1, count);
result = CharacterDatabase.Query(stmt);
}
else
result = PreparedQueryResult(nullptr);
if (result)
{
do
{
Field* fields = result->Fetch();
uint32 itemGuid = fields[0].Get();
uint32 owner = fields[1].Get();
uint32 ownerAccountId = fields[2].Get();
std::string ownerName = fields[3].Get();
char const* itemPos = "[in auction]";
handler->PSendSysMessage(LANG_ITEMLIST_AUCTION, itemGuid, ownerName, owner, ownerAccountId, itemPos);
}
while (result->NextRow());
}
// guild bank case
uint32 guildCount = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_BANK_COUNT_ITEM);
stmt->SetData(0, itemId);
result = CharacterDatabase.Query(stmt);
if (result)
guildCount = (*result)[0].Get();
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_BANK_ITEM_BY_ENTRY);
stmt->SetData(0, itemId);
stmt->SetData(1, count);
result = CharacterDatabase.Query(stmt);
if (result)
{
do
{
Field* fields = result->Fetch();
uint32 itemGuid = fields[0].Get();
uint32 guildGuid = fields[1].Get();
std::string guildName = fields[2].Get();
char const* itemPos = "[in guild bank]";
handler->PSendSysMessage(LANG_ITEMLIST_GUILD, itemGuid, guildName, guildGuid, itemPos);
}
while (result->NextRow());
uint32 resultCount = uint32(result->GetRowCount());
if (count > resultCount)
count -= resultCount;
else
count = 0;
}
if (inventoryCount + mailCount + auctionCount + guildCount == 0)
{
handler->SendErrorMessage(LANG_COMMAND_NOITEMFOUND);
return false;
}
handler->PSendSysMessage(LANG_COMMAND_LISTITEMMESSAGE, itemId, inventoryCount + mailCount + auctionCount + guildCount, inventoryCount, mailCount, auctionCount, guildCount);
return true;
}
static bool HandleListObjectCommand(ChatHandler* handler, Variant, uint32> gameObjectId, Optional countArg)
{
GameObjectTemplate const* gInfo = sObjectMgr->GetGameObjectTemplate(gameObjectId);
if (!gInfo)
{
handler->SendErrorMessage(LANG_COMMAND_LISTOBJINVALIDID, uint32(gameObjectId));
return false;
}
uint32 count = countArg.value_or(10);
if (count == 0)
return false;
QueryResult result;
uint32 objectCount = 0;
result = WorldDatabase.Query("SELECT COUNT(guid) FROM gameobject WHERE id='{}'", uint32(gameObjectId));
if (result)
objectCount = (*result)[0].Get();
if (handler->GetSession())
{
Player* player = handler->GetSession()->GetPlayer();
result = WorldDatabase.Query("SELECT guid, position_x, position_y, position_z, map, id, (POW(position_x - '{}', 2) + POW(position_y - '{}', 2) + POW(position_z - '{}', 2)) AS order_ FROM gameobject WHERE id = '{}' ORDER BY order_ ASC LIMIT {}",
player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), uint32(gameObjectId), count);
}
else
result = WorldDatabase.Query("SELECT guid, position_x, position_y, position_z, map, id FROM gameobject WHERE id = '{}' LIMIT {}",
uint32(gameObjectId), count);
if (result)
{
do
{
Field* fields = result->Fetch();
ObjectGuid::LowType guid = fields[0].Get();
float x = fields[1].Get();
float y = fields[2].Get();
float z = fields[3].Get();
uint16 mapId = fields[4].Get();
uint32 entry = fields[5].Get();
bool liveFound = false;
// Get map (only support base map from console)
Map* thisMap;
if (handler->GetSession())
thisMap = handler->GetSession()->GetPlayer()->GetMap();
else
thisMap = sMapMgr->FindBaseNonInstanceMap(mapId);
// If map found, try to find active version of this object
if (thisMap)
{
auto const goBounds = thisMap->GetGameObjectBySpawnIdStore().equal_range(guid);
if (goBounds.first != goBounds.second)
{
for (std::unordered_multimap::const_iterator itr = goBounds.first; itr != goBounds.second;)
{
if (handler->GetSession())
handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gInfo->name, x, y, z, mapId, itr->second->GetGUID().ToString(), itr->second->isSpawned() ? "*" : " ");
else
handler->PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name, x, y, z, mapId, itr->second->GetGUID().ToString(), itr->second->isSpawned() ? "*" : " ");
++itr;
}
liveFound = true;
}
}
if (!liveFound)
{
if (handler->GetSession())
handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gInfo->name, x, y, z, mapId, "", "");
else
handler->PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name, x, y, z, mapId, "", "");
}
}
while (result->NextRow());
}
handler->PSendSysMessage(LANG_COMMAND_LISTOBJMESSAGE, uint32(gameObjectId), objectCount);
return true;
}
static bool HandleListAllAurasCommand(ChatHandler* handler)
{
return ListAurasCommand(handler, {}, {});
}
static bool HandleListAurasByIdCommand(ChatHandler* handler, uint32 spellId)
{
return ListAurasCommand(handler, spellId, {});
}
static bool HandleListAurasByNameCommand(ChatHandler* handler, WTail namePart)
{
return ListAurasCommand(handler, {}, namePart);
}
static bool ListAurasCommand(ChatHandler* handler, Optional spellId, std::wstring namePart)
{
Unit* unit = handler->getSelectedUnit();
if (!unit)
{
handler->SendErrorMessage(LANG_SELECT_CHAR_OR_CREATURE);
return false;
}
wstrToLower(namePart);
char const* talentStr = handler->GetAcoreString(LANG_TALENT);
char const* passiveStr = handler->GetAcoreString(LANG_PASSIVE);
Unit::AuraApplicationMap const& auras = unit->GetAppliedAuras();
handler->PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, auras.size());
for (auto const& [aurId, aurApp] : auras)
{
bool talent = GetTalentSpellCost(aurApp->GetBase()->GetId()) > 0;
Aura const* aura = aurApp->GetBase();
char const* name = aura->GetSpellInfo()->SpellName[handler->GetSessionDbcLocale()];
if (!ShouldListAura(aura->GetSpellInfo(), spellId, namePart, handler->GetSessionDbcLocale()))
continue;
std::ostringstream ss_name;
ss_name << "|cffffffff|Hspell:" << aura->GetId() << "|h[" << name << "]|h|r";
handler->PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, aura->GetId(), (handler->GetSession() ? ss_name.str() : name),
aurApp->GetEffectMask(), aura->GetCharges(), aura->GetStackAmount(), aurApp->GetSlot(),
aura->GetDuration(), aura->GetMaxDuration(), (aura->IsPassive() ? passiveStr : ""),
(talent ? talentStr : ""), aura->GetCasterGUID().IsPlayer() ? "player" : "creature",
aura->GetCasterGUID().ToString());
}
for (uint16 i = 0; i < TOTAL_AURAS; ++i)
{
Unit::AuraEffectList const& auraList = unit->GetAuraEffectsByType(AuraType(i));
if (auraList.empty())
continue;
bool sizeLogged = false;
for (AuraEffect const* effect : auraList)
{
if (!ShouldListAura(effect->GetSpellInfo(), spellId, namePart, handler->GetSessionDbcLocale()))
continue;
if (!sizeLogged)
{
sizeLogged = true;
handler->PSendSysMessage(LANG_COMMAND_TARGET_LISTAURATYPE, auraList.size(), i);
}
handler->PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, effect->GetId(), effect->GetEffIndex(), effect->GetAmount());
}
}
return true;
}
static bool ShouldListAura(SpellInfo const* spellInfo, Optional spellId, std::wstring namePart, uint8 locale)
{
if (spellId)
return spellInfo->Id == spellId;
if (!namePart.empty())
{
std::string name = spellInfo->SpellName[locale];
return Utf8FitTo(name, namePart);
}
return true;
}
};
void AddSC_list_commandscript()
{
new list_commandscript();
}