mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 15:40:45 +01:00
Core/BattlePets: Misc fixes (#26964)
* Define BattlePetSpeciesFlags enum class. * Define BattlePetDbFlags enum class. * Added check to prevent the pet from being caged if its species has flag BattlePetSpeciesFlags::NotTradable. * Added check to prevent the pet from being caged if it's in battle pet slots. * Added check to prevent the pet from being caged if its health is below maximum health. * Only add pet if the species has flag BattlePetSpeciesFlags::WellKnown. * Added function to check flag BattlePetSpeciesFlags::LegacyAccountUnique to avoid learning copies of unique pets. * Implemented CMSG_BATTLE_PET_CLEAR_FANFARE.
This commit is contained in:
@@ -196,9 +196,9 @@ void BattlePetMgr::LoadFromDB(PreparedQueryResult pets, PreparedQueryResult slot
|
||||
|
||||
if (BattlePetSpeciesEntry const* speciesEntry = sBattlePetSpeciesStore.LookupEntry(species))
|
||||
{
|
||||
if (GetPetCount(species) >= MAX_BATTLE_PETS_PER_SPECIES)
|
||||
if (HasMaxPetCount(speciesEntry))
|
||||
{
|
||||
TC_LOG_ERROR("misc", "Battlenet account with id %u has more than 3 battle pets of species %u", _owner->GetBattlenetAccountId(), species);
|
||||
TC_LOG_ERROR("misc", "Battlenet account with id %u has more than maximum battle pets of species %u", _owner->GetBattlenetAccountId(), species);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -314,6 +314,9 @@ void BattlePetMgr::AddPet(uint32 species, uint32 creatureId, uint16 breed, uint8
|
||||
if (!battlePetSpecies) // should never happen
|
||||
return;
|
||||
|
||||
if (!battlePetSpecies->GetFlags().HasFlag(BattlePetSpeciesFlags::WellKnown)) // Not learnable
|
||||
return;
|
||||
|
||||
BattlePet pet;
|
||||
pet.PacketInfo.Guid = ObjectGuid::Create<HighGuid::BattlePet>(sObjectMgr->GetGenerator<HighGuid::BattlePet>().Generate());
|
||||
pet.PacketInfo.Species = species;
|
||||
@@ -351,6 +354,27 @@ void BattlePetMgr::RemovePet(ObjectGuid guid)
|
||||
_owner->GetPlayer()->RemoveSpell(speciesEntry->SummonSpellID);*/
|
||||
}
|
||||
|
||||
void BattlePetMgr::ClearFanfare(ObjectGuid guid)
|
||||
{
|
||||
BattlePet* pet = GetPet(guid);
|
||||
if (!pet)
|
||||
return;
|
||||
|
||||
pet->PacketInfo.Flags &= ~uint16(BattlePetDbFlags::FanfareNeeded);
|
||||
|
||||
if (pet->SaveInfo != BATTLE_PET_NEW)
|
||||
pet->SaveInfo = BATTLE_PET_CHANGED;
|
||||
}
|
||||
|
||||
bool BattlePetMgr::IsPetInSlot(ObjectGuid guid)
|
||||
{
|
||||
for (WorldPackets::BattlePet::BattlePetSlot const& slot : _slots)
|
||||
if (slot.Pet.Guid == guid)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8 BattlePetMgr::GetPetCount(uint32 species) const
|
||||
{
|
||||
return uint8(std::count_if(_pets.begin(), _pets.end(), [species](std::pair<uint64 const, BattlePet> const& pet)
|
||||
@@ -359,6 +383,13 @@ uint8 BattlePetMgr::GetPetCount(uint32 species) const
|
||||
}));
|
||||
}
|
||||
|
||||
bool BattlePetMgr::HasMaxPetCount(BattlePetSpeciesEntry const* speciesEntry) const
|
||||
{
|
||||
uint8 maxPetsPerSpecies = speciesEntry->GetFlags().HasFlag(BattlePetSpeciesFlags::LegacyAccountUnique) ? 1 : DEFAULT_MAX_BATTLE_PETS_PER_SPECIES;
|
||||
|
||||
return GetPetCount(speciesEntry->ID) >= maxPetsPerSpecies;
|
||||
}
|
||||
|
||||
uint32 BattlePetMgr::GetPetUniqueSpeciesCount() const
|
||||
{
|
||||
std::set<uint32> speciesIds;
|
||||
@@ -399,6 +430,16 @@ void BattlePetMgr::CageBattlePet(ObjectGuid guid)
|
||||
if (!pet)
|
||||
return;
|
||||
|
||||
if (BattlePetSpeciesEntry const* battlePetSpecies = sBattlePetSpeciesStore.LookupEntry(pet->PacketInfo.Species))
|
||||
if (battlePetSpecies->GetFlags().HasFlag(BattlePetSpeciesFlags::NotTradable))
|
||||
return;
|
||||
|
||||
if (IsPetInSlot(guid))
|
||||
return;
|
||||
|
||||
if (pet->PacketInfo.Health < pet->PacketInfo.MaxHealth)
|
||||
return;
|
||||
|
||||
ItemPosCountVec dest;
|
||||
|
||||
if (_owner->GetPlayer()->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, BATTLE_PET_CAGE_ITEM_ID, 1) != EQUIP_ERR_OK)
|
||||
@@ -413,7 +454,6 @@ void BattlePetMgr::CageBattlePet(ObjectGuid guid)
|
||||
item->SetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL, pet->PacketInfo.Level);
|
||||
item->SetModifier(ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID, pet->PacketInfo.CreatureID);
|
||||
|
||||
// FIXME: "You create: ." - item name missing in chat
|
||||
_owner->GetPlayer()->SendNewItem(item, 1, true, false);
|
||||
|
||||
RemovePet(guid);
|
||||
|
||||
@@ -22,14 +22,32 @@
|
||||
#include "DatabaseEnvFwd.h"
|
||||
#include <unordered_map>
|
||||
|
||||
struct BattlePetSpeciesEntry;
|
||||
|
||||
enum BattlePetMisc
|
||||
{
|
||||
MAX_PET_BATTLE_SLOTS = 3,
|
||||
MAX_BATTLE_PETS_PER_SPECIES = 3,
|
||||
BATTLE_PET_CAGE_ITEM_ID = 82800,
|
||||
DEFAULT_SUMMON_BATTLE_PET_SPELL = 118301
|
||||
MAX_PET_BATTLE_SLOTS = 3,
|
||||
DEFAULT_MAX_BATTLE_PETS_PER_SPECIES = 3,
|
||||
BATTLE_PET_CAGE_ITEM_ID = 82800,
|
||||
DEFAULT_SUMMON_BATTLE_PET_SPELL = 118301
|
||||
};
|
||||
|
||||
enum class BattlePetDbFlags : uint16
|
||||
{
|
||||
None = 0x000,
|
||||
Favorite = 0x001,
|
||||
Converted = 0x002,
|
||||
Revoked = 0x004,
|
||||
LockedForConvert = 0x008,
|
||||
Ability0Selection = 0x010,
|
||||
Ability1Selection = 0x020,
|
||||
Ability2Selection = 0x040,
|
||||
FanfareNeeded = 0x080,
|
||||
DisplayOverridden = 0x100
|
||||
};
|
||||
|
||||
DEFINE_ENUM_FLAG(BattlePetDbFlags);
|
||||
|
||||
// 6.2.4
|
||||
enum FlagsControlType
|
||||
{
|
||||
@@ -112,8 +130,11 @@ public:
|
||||
BattlePet* GetPet(ObjectGuid guid);
|
||||
void AddPet(uint32 species, uint32 creatureId, uint16 breed, uint8 quality, uint16 level = 1);
|
||||
void RemovePet(ObjectGuid guid);
|
||||
void ClearFanfare(ObjectGuid guid);
|
||||
bool IsPetInSlot(ObjectGuid guid);
|
||||
|
||||
uint8 GetPetCount(uint32 species) const;
|
||||
bool HasMaxPetCount(BattlePetSpeciesEntry const* speciesEntry) const;
|
||||
uint32 GetPetUniqueSpeciesCount() const;
|
||||
|
||||
WorldPackets::BattlePet::BattlePetSlot* GetSlot(uint8 slot) { return slot < _slots.size() ? &_slots[slot] : nullptr; }
|
||||
|
||||
@@ -479,6 +479,8 @@ struct BattlePetSpeciesEntry
|
||||
int32 CardUIModelSceneID;
|
||||
int32 LoadoutUIModelSceneID;
|
||||
int32 CovenantID;
|
||||
|
||||
EnumFlag<BattlePetSpeciesFlags> GetFlags() const { return static_cast<BattlePetSpeciesFlags>(Flags); }
|
||||
};
|
||||
|
||||
struct BattlePetSpeciesStateEntry
|
||||
|
||||
@@ -193,6 +193,28 @@ enum AzeriteTierUnlockSetFlags
|
||||
|
||||
#define BATTLE_PET_SPECIES_MAX_ID 3159
|
||||
|
||||
enum class BattlePetSpeciesFlags : uint16
|
||||
{
|
||||
NoRename = 0x0001,
|
||||
WellKnown = 0x0002,
|
||||
NotAccountWide = 0x0004,
|
||||
Capturable = 0x0008,
|
||||
NotTradable = 0x0010,
|
||||
HideFromJournal = 0x0020,
|
||||
LegacyAccountUnique = 0x0040,
|
||||
CantBattle = 0x0080,
|
||||
HordeOnly = 0x0100,
|
||||
AllianceOnly = 0x0200,
|
||||
Boss = 0x0400,
|
||||
RandomDisplay = 0x0800,
|
||||
NoLicenseRequired = 0x1000,
|
||||
AddsAllowedWithBoss = 0x2000,
|
||||
HideUntilLearned = 0x4000,
|
||||
MatchPlayerHighPetLevel = 0x8000
|
||||
};
|
||||
|
||||
DEFINE_ENUM_FLAG(BattlePetSpeciesFlags);
|
||||
|
||||
enum class BattlemasterListFlags : uint32
|
||||
{
|
||||
InternalOnly = 0x01,
|
||||
|
||||
@@ -62,6 +62,11 @@ void WorldSession::HandleBattlePetSetFlags(WorldPackets::BattlePet::BattlePetSet
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleBattlePetClearFanfare(WorldPackets::BattlePet::BattlePetClearFanfare& battlePetClearFanfare)
|
||||
{
|
||||
GetBattlePetMgr()->ClearFanfare(battlePetClearFanfare.PetGuid);
|
||||
}
|
||||
|
||||
void WorldSession::HandleCageBattlePet(WorldPackets::BattlePet::CageBattlePet& cageBattlePet)
|
||||
{
|
||||
GetBattlePetMgr()->CageBattlePet(cageBattlePet.PetGuid);
|
||||
|
||||
@@ -140,6 +140,11 @@ void WorldPackets::BattlePet::BattlePetSetFlags::Read()
|
||||
ControlType = _worldPacket.ReadBits(2);
|
||||
}
|
||||
|
||||
void WorldPackets::BattlePet::BattlePetClearFanfare::Read()
|
||||
{
|
||||
_worldPacket >> PetGuid;
|
||||
}
|
||||
|
||||
void WorldPackets::BattlePet::CageBattlePet::Read()
|
||||
{
|
||||
_worldPacket >> PetGuid;
|
||||
|
||||
@@ -158,6 +158,16 @@ namespace WorldPackets
|
||||
uint8 ControlType = 0;
|
||||
};
|
||||
|
||||
class BattlePetClearFanfare final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
BattlePetClearFanfare(WorldPacket&& packet) : ClientPacket(CMSG_BATTLE_PET_CLEAR_FANFARE, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
ObjectGuid PetGuid;
|
||||
};
|
||||
|
||||
class CageBattlePet final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -206,7 +206,7 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_HANDLER(CMSG_BATTLE_PAY_REQUEST_PRICE_INFO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_BATTLE_PAY_START_PURCHASE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_BATTLE_PAY_START_VAS_PURCHASE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_BATTLE_PET_CLEAR_FANFARE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_BATTLE_PET_CLEAR_FANFARE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetClearFanfare);
|
||||
DEFINE_HANDLER(CMSG_BATTLE_PET_DELETE_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetDeletePet);
|
||||
DEFINE_HANDLER(CMSG_BATTLE_PET_DELETE_PET_CHEAT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||
DEFINE_HANDLER(CMSG_BATTLE_PET_MODIFY_NAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetModifyName);
|
||||
|
||||
@@ -194,6 +194,7 @@ namespace WorldPackets
|
||||
class BattlePetModifyName;
|
||||
class BattlePetDeletePet;
|
||||
class BattlePetSetFlags;
|
||||
class BattlePetClearFanfare;
|
||||
class BattlePetSummon;
|
||||
class CageBattlePet;
|
||||
}
|
||||
@@ -1756,6 +1757,7 @@ class TC_GAME_API WorldSession
|
||||
void HandleBattlePetModifyName(WorldPackets::BattlePet::BattlePetModifyName& battlePetModifyName);
|
||||
void HandleBattlePetDeletePet(WorldPackets::BattlePet::BattlePetDeletePet& battlePetDeletePet);
|
||||
void HandleBattlePetSetFlags(WorldPackets::BattlePet::BattlePetSetFlags& battlePetSetFlags);
|
||||
void HandleBattlePetClearFanfare(WorldPackets::BattlePet::BattlePetClearFanfare& battlePetClearFanfare);
|
||||
void HandleBattlePetSummon(WorldPackets::BattlePet::BattlePetSummon& battlePetSummon);
|
||||
void HandleCageBattlePet(WorldPackets::BattlePet::CageBattlePet& cageBattlePet);
|
||||
|
||||
|
||||
@@ -5607,7 +5607,7 @@ void Spell::EffectUncageBattlePet()
|
||||
return;
|
||||
}
|
||||
|
||||
if (battlePetMgr->GetPetCount(speciesId) >= MAX_BATTLE_PETS_PER_SPECIES)
|
||||
if (battlePetMgr->HasMaxPetCount(speciesEntry))
|
||||
{
|
||||
battlePetMgr->SendError(BATTLEPETRESULT_CANT_HAVE_MORE_PETS_OF_THAT_TYPE, creatureId); // or speciesEntry.CreatureID
|
||||
SendCastResult(SPELL_FAILED_CANT_ADD_BATTLE_PET);
|
||||
|
||||
Reference in New Issue
Block a user