44std::unordered_map<
uint32 , std::unordered_set<
uint8 >> _availableBreedsPerSpecies;
45std::unordered_map<
uint32 ,
uint8 > _defaultQualityPerSpecies;
52 if (breedState == _battlePetBreedStates.end())
61 if (speciesState != _battlePetSpeciesStates.end())
73 health *= battlePetBreedQuality->StateMultiplier;
74 power *= battlePetBreedQuality->StateMultiplier;
75 speed *= battlePetBreedQuality->StateMultiplier;
99 if (
uint32 creatureId = battlePetSpecies->CreatureID)
100 _battlePetSpeciesByCreature[creatureId] = battlePetSpecies;
103 _battlePetBreedStates[battlePetBreedState->BattlePetBreedID][
BattlePetState(battlePetBreedState->BattlePetStateID)] = battlePetBreedState->Value;
106 _battlePetSpeciesStates[battlePetSpeciesState->BattlePetSpeciesID][
BattlePetState(battlePetSpeciesState->BattlePetStateID)] = battlePetSpeciesState->Value;
117 TC_LOG_INFO(
"server.loading",
">> Loaded 0 battle pet breeds. DB table `battle_pet_breeds` is empty.");
124 Field* fields = result->Fetch();
130 TC_LOG_ERROR(
"sql.sql",
"Non-existing BattlePetSpecies.db2 entry {} was referenced in `battle_pet_breeds` by row ({}, {}).", speciesId, speciesId, breedId);
136 _availableBreedsPerSpecies[speciesId].insert(breedId);
138 }
while (result->NextRow());
140 TC_LOG_INFO(
"server.loading",
">> Loaded {} battle pet breeds.", count);
148 TC_LOG_INFO(
"server.loading",
">> Loaded 0 battle pet qualities. DB table `battle_pet_quality` is empty.");
154 Field* fields = result->Fetch();
159 if (!battlePetSpecies)
161 TC_LOG_ERROR(
"sql.sql",
"Non-existing BattlePetSpecies.db2 entry {} was referenced in `battle_pet_quality` by row ({}, {}).", speciesId, speciesId, quality);
167 TC_LOG_ERROR(
"sql.sql",
"BattlePetSpecies.db2 entry {} was referenced in `battle_pet_quality` with non-existing quality {}).", speciesId, quality);
173 TC_LOG_ERROR(
"sql.sql",
"Learnable BattlePetSpecies.db2 entry {} was referenced in `battle_pet_quality` with invalid quality {}. Maximum allowed quality is BattlePetBreedQuality::Rare.", speciesId, quality);
177 _defaultQualityPerSpecies[speciesId] = quality;
178 }
while (result->NextRow());
180 TC_LOG_INFO(
"server.loading",
">> Loaded {} battle pet qualities.",
uint32(_defaultQualityPerSpecies.size()));
185 _battlePetSpeciesBySpell[spellId] = speciesEntry;
200 auto itr = _availableBreedsPerSpecies.find(species);
201 if (itr == _availableBreedsPerSpecies.end())
209 auto itr = _defaultQualityPerSpecies.find(species);
210 if (itr == _defaultQualityPerSpecies.end())
220 if (
CreatureModel const* creatureModel = creatureTemplate->GetRandomValidModel())
221 return creatureModel->CreatureDisplayID;
243 Field* fields = pets->Fetch();
277 pet.
PacketInfo.
Guid = ObjectGuid::Create<HighGuid::BattlePet>(fields[0].GetUInt64());
290 if (!fields[13].IsNull())
301 if (std::shared_ptr<Realm const> ownerRealm =
sRealmList->GetRealm(fields[12].
GetInt32()))
309 }
while (pets->NextRow());
318 Field* fields = slots->Fetch();
320 auto itr =
_pets.find(fields[1].GetUInt64());
321 if (itr !=
_pets.end())
322 _slots[i].Pet = itr->second.PacketInfo;
325 }
while (slots->NextRow());
333 for (
auto itr =
_pets.begin(); itr !=
_pets.end();)
335 switch (itr->second.SaveInfo)
341 stmt->
setUInt32(2, itr->second.PacketInfo.Species);
342 stmt->
setUInt16(3, itr->second.PacketInfo.Breed);
343 stmt->
setUInt32(4, itr->second.PacketInfo.DisplayID);
344 stmt->
setUInt16(5, itr->second.PacketInfo.Level);
345 stmt->
setUInt16(6, itr->second.PacketInfo.Exp);
346 stmt->
setUInt32(7, itr->second.PacketInfo.Health);
347 stmt->
setUInt8(8, itr->second.PacketInfo.Quality);
348 stmt->
setUInt16(9, itr->second.PacketInfo.Flags);
349 stmt->
setString(10, itr->second.PacketInfo.Name);
350 stmt->
setInt64(11, itr->second.NameTimestamp);
351 if (itr->second.PacketInfo.OwnerInfo)
353 stmt->
setInt64(12, itr->second.PacketInfo.OwnerInfo->Guid.GetCounter());
364 if (itr->second.DeclinedName)
370 stmt->
setString(i + 1, itr->second.DeclinedName->name[i]);
380 stmt->
setUInt16(0, itr->second.PacketInfo.Level);
381 stmt->
setUInt16(1, itr->second.PacketInfo.Exp);
382 stmt->
setUInt32(2, itr->second.PacketInfo.Health);
383 stmt->
setUInt8(3, itr->second.PacketInfo.Quality);
384 stmt->
setUInt16(4, itr->second.PacketInfo.Flags);
385 stmt->
setString(5, itr->second.PacketInfo.Name);
386 stmt->
setInt64(6, itr->second.NameTimestamp);
395 if (itr->second.DeclinedName)
401 stmt->
setString(i + 1, itr->second.DeclinedName->name[i]);
419 itr =
_pets.erase(itr);
436 stmt->
setUInt64(2, slot.Pet.Guid.GetCounter());
450 if (!battlePetSpecies)
479 std::array<std::reference_wrapper<BattlePet const>, 1> updates = { pet };
529 if (summonedBattlePet->GetBattlePetCompanionGUID() == guid)
530 summonedBattlePet->SetBattlePetCompanionNameTimestamp(pet->
NameTimestamp);
536 if (slot.Pet.Guid == guid)
544 return uint8(std::ranges::count_if(
_pets, [battlePetSpecies, ownerGuid](
BattlePet const& pet)
565 return GetPetCount(battlePetSpecies, ownerGuid) >= maxPetsPerSpecies;
570 std::set<uint32> speciesIds;
571 std::ranges::transform(
_pets, std::inserter(speciesIds, speciesIds.end()), [](
BattlePet const& pet)
573 return pet.PacketInfo.Species;
575 return speciesIds.size();
587 _slots[slotIndex].Locked =
false;
599 for (
auto& pet :
_pets)
601 level = std::max(level, pet.second.PacketInfo.Level);
651 if (summonedBattlePet->GetBattlePetCompanionGUID() == guid)
653 summonedBattlePet->DespawnOrUnsummon();
686 std::array<std::reference_wrapper<BattlePet const>, 1> updates = { *pet };
748 std::array<std::reference_wrapper<BattlePet const>, 1> updates = { *pet };
786 std::array<std::reference_wrapper<BattlePet const>, 1> updates = { *pet };
794 std::vector<std::reference_wrapper<BattlePet const>> updates;
796 for (
auto& [_, pet] :
_pets)
798 if (pet.PacketInfo.Health == pet.PacketInfo.MaxHealth)
801 pet.PacketInfo.Health +=
CalculatePct(pet.PacketInfo.MaxHealth, pct);
803 pet.PacketInfo.Health = std::min(pet.PacketInfo.Health, pet.PacketInfo.MaxHealth);
807 updates.push_back(pet);
824 if (summonedBattlePet->GetBattlePetCompanionGUID() == guid)
860 summonedBattlePet->DespawnOrUnsummon();
874 for (
auto& pet :
_pets)
876 if (!pet.second.PacketInfo.OwnerInfo || pet.second.PacketInfo.OwnerInfo->Guid ==
_owner->
GetPlayer()->
GetGUID())
877 battlePetJournal.
Pets.push_back(std::ref(pet.second.PacketInfo));
DB2Storage< BattlePetBreedQualityEntry > sBattlePetBreedQualityStore("BattlePetBreedQuality.db2", &BattlePetBreedQualityLoadInfo::Instance)
DB2Storage< BattlePetBreedStateEntry > sBattlePetBreedStateStore("BattlePetBreedState.db2", &BattlePetBreedStateLoadInfo::Instance)
DB2Storage< BattlePetSpeciesStateEntry > sBattlePetSpeciesStateStore("BattlePetSpeciesState.db2", &BattlePetSpeciesStateLoadInfo::Instance)
DB2Storage< BattlePetSpeciesEntry > sBattlePetSpeciesStore("BattlePetSpecies.db2", &BattlePetSpeciesLoadInfo::Instance)
SQLTransaction< LoginDatabaseConnection > LoginDatabaseTransaction
std::shared_ptr< ResultSet > QueryResult
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< LoginDatabaseConnection > LoginDatabase
Accessor to the realm/login database.
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
@ ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID
@ ITEM_MODIFIER_BATTLE_PET_BREED_DATA
@ ITEM_MODIFIER_BATTLE_PET_SPECIES_ID
@ ITEM_MODIFIER_BATTLE_PET_LEVEL
#define TC_LOG_ERROR(filterType__, message__,...)
#define TC_LOG_INFO(filterType__, message__,...)
@ LOGIN_INS_BATTLE_PET_SLOTS
@ LOGIN_DEL_BATTLE_PET_DECLINED_NAME
@ LOGIN_INS_BATTLE_PET_DECLINED_NAME
@ LOGIN_DEL_BATTLE_PET_SLOTS
std::vector< ItemPosCount > ItemPosCountVec
@ SPELL_AURA_MOD_BATTLE_PET_XP_PCT
#define MAX_DECLINED_NAME_CASES
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
T CalculatePct(T base, U pct)
ObjectGuid const & GetGUID() const
std::vector< WorldPackets::BattlePet::BattlePetSlot > _slots
void GrantBattlePetExperience(ObjectGuid guid, uint16 xp, BattlePetXpSource xpSource)
void HealBattlePetsPct(uint8 pct)
static uint16 RollPetBreed(uint32 species)
void RemovePet(ObjectGuid guid)
uint32 GetPetUniqueSpeciesCount() const
void ToggleJournalLock(bool lock)
static void LoadAvailablePetBreeds()
bool IsJournalLockAcquired() const
static void AddBattlePetSpeciesBySpell(uint32 spellId, BattlePetSpeciesEntry const *speciesEntry)
uint16 GetMaxPetLevel() const
void ClearFanfare(ObjectGuid guid)
static BattlePetSpeciesEntry const * GetBattlePetSpeciesByCreature(uint32 creatureId)
void SummonPet(ObjectGuid guid)
BattlePetMgr(WorldSession *owner)
void ModifyName(ObjectGuid guid, std::string const &name, std::unique_ptr< DeclinedName > declinedName)
static uint32 SelectPetDisplay(BattlePetSpeciesEntry const *speciesEntry)
void UnlockSlot(BattlePetSlot slot)
uint8 GetPetCount(BattlePetSpeciesEntry const *battlePetSpecies, ObjectGuid ownerGuid) const
void SendUpdates(std::span< std::reference_wrapper< BattlePet const > const > pets, bool petAdded)
static BattlePetSpeciesEntry const * GetBattlePetSpeciesBySpell(uint32 spellId)
void AddPet(uint32 species, uint32 display, uint16 breed, BattlePetBreedQuality quality, uint16 level=1)
std::unordered_map< uint64, BattlePet > _pets
void UpdateBattlePetData(ObjectGuid guid)
BattlePet * GetPet(ObjectGuid guid)
bool IsPetInSlot(ObjectGuid guid) const
static void LoadDefaultPetQualities()
bool HasJournalLock() const
void CageBattlePet(ObjectGuid guid)
void GrantBattlePetLevel(ObjectGuid guid, uint16 grantedLevels)
bool HasMaxPetCount(BattlePetSpeciesEntry const *battlePetSpecies, ObjectGuid ownerGuid) const
void SendError(BattlePetError error, uint32 creatureId)
void SendJournalLockStatus()
void ChangeBattlePetQuality(ObjectGuid guid, BattlePetBreedQuality quality)
static BattlePetBreedQuality GetDefaultPetQuality(uint32 species)
void LoadFromDB(PreparedQueryResult pets, PreparedQueryResult slots)
void SaveToDB(LoginDatabaseTransaction trans)
Class used to access individual fields of database query result.
bool GetBool() const noexcept
uint32 GetUInt32() const noexcept
uint16 GetUInt16() const noexcept
bool IsNull() const noexcept
uint8 GetUInt8() const noexcept
int32 GetInt32() const noexcept
std::string GetString() const noexcept
int64 GetInt64() const noexcept
void SetModifier(ItemModifier modifier, uint32 value)
LowType GetCounter() const
static ObjectGuid const Empty
std::string ToString() const
UF::UpdateField< UF::PlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_PLAYER > m_playerData
Item * StoreNewItem(ItemPosCountVec const &pos, uint32 itemId, bool update, ItemRandomBonusListId randomBonusListId=0, GuidSet const &allowedLooters=GuidSet(), ItemContext context=ItemContext::NONE, std::vector< int32 > const *bonusListIDs=nullptr, bool addToCollection=true)
void UpdateCriteria(CriteriaType type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, WorldObject *ref=nullptr)
void SetBattlePetData(BattlePets::BattlePet const *pet=nullptr)
Creature * GetSummonedBattlePet() const
InventoryResult CanStoreNewItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, uint32 item, uint32 count, uint32 *no_space_count=nullptr) const
void SendNewItem(Item *item, uint32 quantity, bool received, bool created, bool broadcast=false, uint32 dungeonEncounterId=0)
void setUInt16(uint8 index, uint16 value)
void setString(uint8 index, std::string &&value)
void setUInt32(uint8 index, uint32 value)
void setInt64(uint8 index, int64 value)
void setBool(uint8 index, bool value)
void setUInt64(uint8 index, uint64 value)
void setInt32(uint8 index, int32 value)
void setUInt8(uint8 index, uint8 value)
void setNull(uint8 index)
float GetTotalAuraMultiplier(AuraType auraType) const
void SetWildBattlePetLevel(uint32 wildBattlePetLevel)
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
std::vector< std::reference_wrapper< BattlePet > > Pets
std::vector< std::reference_wrapper< BattlePetSlot > > Slots
std::vector< std::reference_wrapper< BattlePet const > > Pets
WorldPacket const * Write() override
WorldPacket const * Write() override
std::vector< BattlePetSlot > Slots
Player session in the World.
ObjectGuid GetBattlenetAccountGUID() const
Player * GetPlayer() const
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
uint32 GetBattlenetAccountId() const
@ SPELL_SUMMON_BATTLE_PET
@ DEFAULT_MAX_BATTLE_PETS_PER_SPECIES
@ BATTLE_PET_CAGE_ITEM_ID
static constexpr uint16 MAX_BATTLE_PET_LEVEL
auto SelectRandomContainerElement(C const &container) -> std::add_const_t< decltype(*std::ranges::begin(container))> &
auto MapGetValuePtr(M &map, typename M::key_type const &key)
EnumFlag< BattlePetSpeciesFlags > GetFlags() const
WorldPackets::BattlePet::BattlePet PacketInfo
std::unique_ptr<::DeclinedName > DeclinedName
BattlePetSaveInfo SaveInfo
Optional< BattlePetOwnerInfo > OwnerInfo