feat(Scripts/Commands): Add .pet list and .pet delete commands (#25692)

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Andrew
2026-05-03 06:24:06 -03:00
committed by GitHub
parent 3a36c1ca8d
commit 685ef839f8
5 changed files with 134 additions and 4 deletions

View File

@@ -676,6 +676,8 @@ enum RBACPermissions
RBAC_PERM_COMMAND_CHARACTER_CHECK_PROFESSION = 911,
RBAC_PERM_COMMAND_GOBJECT_LOAD = 912,
RBAC_PERM_COMMAND_BF_QUEUE = 913,
RBAC_PERM_COMMAND_PET_LIST = 914,
RBAC_PERM_COMMAND_PET_DELETE = 915,
// custom permissions 1000+
RBAC_PERM_MAX
};

View File

@@ -1478,6 +1478,15 @@ enum AcoreStrings
LANG_POOL_LOOKUP_IN_POOL = 35431,
LANG_POOL_LOOKUP_NOT_IN_POOL = 35432,
LANG_POOL_LOOKUP_USE_INFO = 35433,
LANG_POOL_LOOKUP_NOTARGET = 35434
LANG_POOL_LOOKUP_NOTARGET = 35434,
// Pet list command
LANG_PET_LIST_HEADER = 35435,
LANG_PET_LIST_ENTRY = 35436,
LANG_PET_LIST_EMPTY = 35437,
// Pet delete command
LANG_PET_DELETE_NOT_FOUND = 35438,
LANG_PET_DELETE_SUCCESS = 35439
};
#endif

View File

@@ -17,6 +17,8 @@
#include "Chat.h"
#include "CommandScript.h"
#include "DatabaseEnv.h"
#include <algorithm>
#include "Language.h"
#include "Log.h"
#include "ObjectMgr.h"
@@ -37,9 +39,11 @@ public:
{
static ChatCommandTable petCommandTable =
{
{ "create", HandlePetCreateCommand, rbac::RBAC_PERM_COMMAND_PET_CREATE, Console::No },
{ "learn", HandlePetLearnCommand, rbac::RBAC_PERM_COMMAND_PET_LEARN, Console::No },
{ "unlearn", HandlePetUnlearnCommand, rbac::RBAC_PERM_COMMAND_PET_UNLEARN, Console::No }
{ "create", HandlePetCreateCommand, rbac::RBAC_PERM_COMMAND_PET_CREATE, Console::No },
{ "delete", HandlePetDeleteCommand, rbac::RBAC_PERM_COMMAND_PET_DELETE, Console::Yes },
{ "learn", HandlePetLearnCommand, rbac::RBAC_PERM_COMMAND_PET_LEARN, Console::No },
{ "list", HandlePetListCommand, rbac::RBAC_PERM_COMMAND_PET_LIST, Console::Yes },
{ "unlearn", HandlePetUnlearnCommand, rbac::RBAC_PERM_COMMAND_PET_UNLEARN, Console::No }
};
static ChatCommandTable commandTable =
@@ -126,6 +130,103 @@ public:
return true;
}
static bool HandlePetDeleteCommand(ChatHandler* handler, PlayerIdentifier owner, uint32 petNumber)
{
ObjectGuid ownerGuid = owner.GetGUID();
QueryResult result = CharacterDatabase.Query(
"SELECT entry, name FROM character_pet WHERE id = {} AND owner = {}",
petNumber, ownerGuid.GetCounter());
if (!result)
{
handler->SendErrorMessage(LANG_PET_DELETE_NOT_FOUND, petNumber, owner.GetName(),
ownerGuid.GetCounter());
return false;
}
if (Player* online = owner.GetConnectedPlayer())
{
if (Pet* activePet = online->GetPet())
{
if (activePet->GetCharmInfo() &&
activePet->GetCharmInfo()->GetPetNumber() == petNumber)
{
online->RemovePet(activePet, PET_SAVE_AS_DELETED);
}
}
// Drop the pet from the in-memory PetStable so the stable UI / call-pet
// logic does not reference a row that no longer exists in the database.
if (PetStable* stable = online->GetPetStable())
{
if (stable->CurrentPet && stable->CurrentPet->PetNumber == petNumber)
stable->CurrentPet.reset();
for (Optional<PetStable::PetInfo>& stabled : stable->StabledPets)
if (stabled && stabled->PetNumber == petNumber)
stabled.reset();
stable->UnslottedPets.erase(
std::remove_if(stable->UnslottedPets.begin(), stable->UnslottedPets.end(),
[petNumber](PetStable::PetInfo const& p) { return p.PetNumber == petNumber; }),
stable->UnslottedPets.end());
}
}
Field* fields = result->Fetch();
uint32 entry = fields[0].Get<uint32>();
std::string name = fields[1].Get<std::string>();
std::string creatureName = "<unknown>";
if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(entry))
creatureName = cInfo->Name;
Pet::DeleteFromDB(petNumber);
handler->PSendSysMessage(LANG_PET_DELETE_SUCCESS, petNumber, name, entry, creatureName,
owner.GetName(), ownerGuid.GetCounter());
return true;
}
static bool HandlePetListCommand(ChatHandler* handler, PlayerIdentifier owner)
{
ObjectGuid ownerGuid = owner.GetGUID();
QueryResult result = CharacterDatabase.Query(
"SELECT id, entry, level, slot, name, PetType FROM character_pet "
"WHERE owner = {} ORDER BY slot, id",
ownerGuid.GetCounter());
if (!result)
{
handler->PSendSysMessage(LANG_PET_LIST_EMPTY, owner.GetName(), ownerGuid.GetCounter());
return true;
}
handler->PSendSysMessage(LANG_PET_LIST_HEADER, owner.GetName(), ownerGuid.GetCounter());
do
{
Field* fields = result->Fetch();
uint32 petNumber = fields[0].Get<uint32>();
uint32 entry = fields[1].Get<uint32>();
uint8 level = fields[2].Get<uint8>();
uint8 slot = fields[3].Get<uint8>();
std::string name = fields[4].Get<std::string>();
uint8 petType = fields[5].Get<uint8>();
std::string creatureName = "<unknown>";
if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(entry))
creatureName = cInfo->Name;
handler->PSendSysMessage(LANG_PET_LIST_ENTRY, petNumber, uint32(slot), entry,
creatureName, name, uint32(level), uint32(petType));
} while (result->NextRow());
return true;
}
static bool HandlePetUnlearnCommand(ChatHandler* handler, SpellInfo const* spell)
{
if (!spell)