mirror of
https://gitcode.com/GitHub_Trending/az/azerothcore-wotlk.git
synced 2026-07-11 03:13:10 +00:00
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:
@@ -0,0 +1,10 @@
|
||||
-- RBAC permissions for .pet list (sec 1+, Mod role 198) and .pet delete (sec 3+, Admin role 196).
|
||||
DELETE FROM `rbac_permissions` WHERE `id` IN (914, 915);
|
||||
INSERT INTO `rbac_permissions` (`id`, `name`) VALUES
|
||||
(914, 'Command: pet list'),
|
||||
(915, 'Command: pet delete');
|
||||
|
||||
DELETE FROM `rbac_linked_permissions` WHERE `linkedId` IN (914, 915);
|
||||
INSERT INTO `rbac_linked_permissions` (`id`, `linkedId`) VALUES
|
||||
(198, 914),
|
||||
(196, 915);
|
||||
@@ -0,0 +1,8 @@
|
||||
-- acore_string entries for .pet list and .pet delete commands.
|
||||
DELETE FROM `acore_string` WHERE `entry` BETWEEN 35435 AND 35439;
|
||||
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
|
||||
(35435, 'Pets owned by {} ({}):', '{}({})이(가) 소유한 펫:', 'Familiers de {} ({}) :', 'Begleiter von {} ({}):', '{} ({}) 拥有的宠物:', '{} ({}) 擁有的寵物:', 'Mascotas de {} ({}):', 'Mascotas de {} ({}):', 'Питомцы игрока {} ({}):'),
|
||||
(35436, ' PetNumber: {} | Slot: {} | Entry: {} ({}) | Name: {} | Level: {} | Type: {}', ' 펫번호: {} | 슬롯: {} | Entry: {} ({}) | 이름: {} | 레벨: {} | 종류: {}', ' N° Familier : {} | Emplacement : {} | Entrée : {} ({}) | Nom : {} | Niveau : {} | Type : {}', ' Begleiter-Nr.: {} | Slot: {} | Eintrag: {} ({}) | Name: {} | Stufe: {} | Typ: {}', ' 宠物编号: {} | 槽位: {} | 条目: {} ({}) | 名称: {} | 等级: {} | 类型: {}', ' 寵物編號: {} | 槽位: {} | 條目: {} ({}) | 名稱: {} | 等級: {} | 類型: {}', ' N.º mascota: {} | Ranura: {} | Entrada: {} ({}) | Nombre: {} | Nivel: {} | Tipo: {}', ' N.º mascota: {} | Ranura: {} | Entrada: {} ({}) | Nombre: {} | Nivel: {} | Tipo: {}', ' Номер: {} | Слот: {} | Entry: {} ({}) | Имя: {} | Уровень: {} | Тип: {}'),
|
||||
(35437, 'Player {} ({}) has no pets.', '플레이어 {}({})에게 펫이 없습니다.', "Le joueur {} ({}) n'a aucun familier.", 'Spieler {} ({}) besitzt keine Begleiter.', '玩家 {} ({}) 没有任何宠物。', '玩家 {} ({}) 沒有任何寵物。', 'El jugador {} ({}) no tiene mascotas.', 'El jugador {} ({}) no tiene mascotas.', 'У игрока {} ({}) нет питомцев.'),
|
||||
(35438, 'No pet with PetNumber {0} found for player {1} ({2}).', '플레이어 {1} ({2})의 펫번호 {0}을(를) 찾을 수 없습니다.', "Aucun familier avec le N° {0} trouvé pour le joueur {1} ({2}).", 'Kein Begleiter mit Nummer {0} für Spieler {1} ({2}) gefunden.', '未找到玩家 {1} ({2}) 的宠物编号 {0}。', '找不到玩家 {1} ({2}) 的寵物編號 {0}。', 'No se encontró ninguna mascota con N.º {0} para el jugador {1} ({2}).', 'No se encontró ninguna mascota con N.º {0} para el jugador {1} ({2}).', 'У игрока {1} ({2}) не найден питомец с номером {0}.'),
|
||||
(35439, 'Deleted pet {0} ({1}, entry {2} - {3}) from player {4} ({5}).', '플레이어 {4} ({5})로부터 펫 {0} ({1}, entry {2} - {3})을(를) 삭제했습니다.', "Familier {0} ({1}, entrée {2} - {3}) supprimé du joueur {4} ({5}).", 'Begleiter {0} ({1}, Eintrag {2} - {3}) von Spieler {4} ({5}) gelöscht.', '已从玩家 {4} ({5}) 删除宠物 {0} ({1}, 条目 {2} - {3})。', '已從玩家 {4} ({5}) 刪除寵物 {0} ({1}, 條目 {2} - {3})。', 'Eliminada la mascota {0} ({1}, entrada {2} - {3}) del jugador {4} ({5}).', 'Eliminada la mascota {0} ({1}, entrada {2} - {3}) del jugador {4} ({5}).', 'Питомец {0} ({1}, entry {2} - {3}) удалён у игрока {4} ({5}).');
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user