39std::unordered_map<
uint16 , std::unordered_map<
BattlePetState ,
int32 , std::hash<std::underlying_type<BattlePetState>::type> >> _battlePetBreedStates;
40std::unordered_map<
uint32 , std::unordered_map<
BattlePetState ,
int32 , std::hash<std::underlying_type<BattlePetState>::type> >> _battlePetSpeciesStates;
43std::unordered_map<
uint32 , std::unordered_set<
uint8 >> _availableBreedsPerSpecies;
44std::unordered_map<
uint32 ,
uint8 > _defaultQualityPerSpecies;
55 if (breedState == _battlePetBreedStates.end())
64 if (speciesState != _battlePetSpeciesStates.end())
76 health *= battlePetBreedQuality->StateMultiplier;
77 power *= battlePetBreedQuality->StateMultiplier;
78 speed *= battlePetBreedQuality->StateMultiplier;
102 if (
uint32 creatureId = battlePetSpecies->CreatureID)
103 _battlePetSpeciesByCreature[creatureId] = battlePetSpecies;
106 _battlePetBreedStates[battlePetBreedState->BattlePetBreedID][
BattlePetState(battlePetBreedState->BattlePetStateID)] = battlePetBreedState->Value;
109 _battlePetSpeciesStates[battlePetSpeciesState->BattlePetSpeciesID][
BattlePetState(battlePetSpeciesState->BattlePetStateID)] = battlePetSpeciesState->Value;
120 TC_LOG_INFO(
"server.loading",
">> Loaded 0 battle pet breeds. DB table `battle_pet_breeds` is empty.");
127 Field* fields = result->Fetch();
133 TC_LOG_ERROR(
"sql.sql",
"Non-existing BattlePetSpecies.db2 entry {} was referenced in `battle_pet_breeds` by row ({}, {}).", speciesId, speciesId, breedId);
139 _availableBreedsPerSpecies[speciesId].insert(breedId);
141 }
while (result->NextRow());
143 TC_LOG_INFO(
"server.loading",
">> Loaded {} battle pet breeds.", count);
151 TC_LOG_INFO(
"server.loading",
">> Loaded 0 battle pet qualities. DB table `battle_pet_quality` is empty.");
157 Field* fields = result->Fetch();
162 if (!battlePetSpecies)
164 TC_LOG_ERROR(
"sql.sql",
"Non-existing BattlePetSpecies.db2 entry {} was referenced in `battle_pet_quality` by row ({}, {}).", speciesId, speciesId, quality);
170 TC_LOG_ERROR(
"sql.sql",
"BattlePetSpecies.db2 entry {} was referenced in `battle_pet_quality` with non-existing quality {}).", speciesId, quality);
176 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);
180 _defaultQualityPerSpecies[speciesId] = quality;
181 }
while (result->NextRow());
183 TC_LOG_INFO(
"server.loading",
">> Loaded {} battle pet qualities.",
uint32(_defaultQualityPerSpecies.size()));
188 _battlePetSpeciesBySpell[spellId] = speciesEntry;
203 auto itr = _availableBreedsPerSpecies.find(species);
204 if (itr == _availableBreedsPerSpecies.end())
212 auto itr = _defaultQualityPerSpecies.find(species);
213 if (itr == _defaultQualityPerSpecies.end())
223 if (
CreatureModel const* creatureModel = creatureTemplate->GetRandomValidModel())
224 return creatureModel->CreatureDisplayID;
246 Field* fields = pets->Fetch();
280 pet.
PacketInfo.
Guid = ObjectGuid::Create<HighGuid::BattlePet>(fields[0].GetUInt64());
293 if (!fields[12].IsNull())
311 }
while (pets->NextRow());
320 Field* fields = slots->Fetch();
322 auto itr =
_pets.find(fields[1].GetUInt64());
323 if (itr !=
_pets.end())
324 _slots[i].Pet = itr->second.PacketInfo;
327 }
while (slots->NextRow());
335 for (
auto itr =
_pets.begin(); itr !=
_pets.end();)
337 switch (itr->second.SaveInfo)
343 stmt->
setUInt32(2, itr->second.PacketInfo.Species);
344 stmt->
setUInt16(3, itr->second.PacketInfo.Breed);
345 stmt->
setUInt32(4, itr->second.PacketInfo.DisplayID);
346 stmt->
setUInt16(5, itr->second.PacketInfo.Level);
347 stmt->
setUInt16(6, itr->second.PacketInfo.Exp);
348 stmt->
setUInt32(7, itr->second.PacketInfo.Health);
349 stmt->
setUInt8(8, itr->second.PacketInfo.Quality);
350 stmt->
setUInt16(9, itr->second.PacketInfo.Flags);
351 stmt->
setString(10, itr->second.PacketInfo.Name);
352 stmt->
setInt64(11, itr->second.NameTimestamp);
353 if (itr->second.PacketInfo.OwnerInfo)
355 stmt->
setInt64(12, itr->second.PacketInfo.OwnerInfo->Guid.GetCounter());
366 if (itr->second.DeclinedName)
372 stmt->
setString(i + 1, itr->second.DeclinedName->name[i]);
382 stmt->
setUInt16(0, itr->second.PacketInfo.Level);
383 stmt->
setUInt16(1, itr->second.PacketInfo.Exp);
384 stmt->
setUInt32(2, itr->second.PacketInfo.Health);
385 stmt->
setUInt8(3, itr->second.PacketInfo.Quality);
386 stmt->
setUInt16(4, itr->second.PacketInfo.Flags);
387 stmt->
setString(5, itr->second.PacketInfo.Name);
388 stmt->
setInt64(6, itr->second.NameTimestamp);
397 if (itr->second.DeclinedName)
403 stmt->
setString(i + 1, itr->second.DeclinedName->name[i]);
421 itr =
_pets.erase(itr);
438 stmt->
setUInt64(2, slot.Pet.Guid.GetCounter());
452 if (!battlePetSpecies)
484 std::vector<std::reference_wrapper<BattlePet>> updates;
485 updates.push_back(std::ref(pet));
535 if (summonedBattlePet->GetBattlePetCompanionGUID() == guid)
536 summonedBattlePet->SetBattlePetCompanionNameTimestamp(pet->
NameTimestamp);
542 if (slot.Pet.Guid == guid)
550 return uint8(std::count_if(
_pets.begin(),
_pets.end(), [battlePetSpecies, ownerGuid](std::pair<uint64 const, BattlePet>
const& pet)
552 if (pet.second.PacketInfo.Species != battlePetSpecies->ID)
555 if (pet.second.SaveInfo == BATTLE_PET_REMOVED)
558 if (battlePetSpecies->GetFlags().HasFlag(BattlePetSpeciesFlags::NotAccountWide))
559 if (!ownerGuid.IsEmpty() && pet.second.PacketInfo.OwnerInfo)
560 if (pet.second.PacketInfo.OwnerInfo->Guid != ownerGuid)
571 return GetPetCount(battlePetSpecies, ownerGuid) >= maxPetsPerSpecies;
576 std::set<uint32> speciesIds;
577 std::transform(
_pets.begin(),
_pets.end(), std::inserter(speciesIds, speciesIds.end()), [](std::pair<uint64 const, BattlePet>
const& pet)
579 return pet.second.PacketInfo.Species;
581 return speciesIds.size();
593 _slots[slotIndex].Locked =
false;
605 for (
auto& pet :
_pets)
607 level = std::max(level, pet.second.PacketInfo.Level);
657 if (summonedBattlePet->GetBattlePetCompanionGUID() == guid)
659 summonedBattlePet->DespawnOrUnsummon();
692 std::vector<std::reference_wrapper<BattlePet>> updates;
693 updates.push_back(std::ref(*pet));
755 std::vector<std::reference_wrapper<BattlePet>> updates;
756 updates.push_back(std::ref(*pet));
794 std::vector<std::reference_wrapper<BattlePet>> updates;
795 updates.push_back(std::ref(*pet));
803 std::vector<std::reference_wrapper<BattlePet>> updates;
805 for (
auto& pet :
_pets)
806 if (pet.second.PacketInfo.Health != pet.second.PacketInfo.MaxHealth)
808 pet.second.PacketInfo.Health +=
CalculatePct(pet.second.PacketInfo.MaxHealth, pct);
810 pet.second.PacketInfo.Health = std::min(pet.second.PacketInfo.Health, pet.second.PacketInfo.MaxHealth);
813 updates.push_back(std::ref(pet.second));
830 if (summonedBattlePet->GetBattlePetCompanionGUID() == guid)
866 summonedBattlePet->DespawnOrUnsummon();
880 for (
auto& pet :
_pets)
882 if (!pet.second.PacketInfo.OwnerInfo || pet.second.PacketInfo.OwnerInfo->Guid ==
_owner->
GetPlayer()->
GetGUID())
883 battlePetJournal.
Pets.push_back(std::ref(pet.second.PacketInfo));
894 updates.
Pets.push_back(std::ref(pet.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__,...)
#define TC_LOG_INFO(filterType__,...)
@ 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)
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
static BattlePetSpeciesEntry const * GetBattlePetSpeciesBySpell(uint32 spellId)
void AddPet(uint32 species, uint32 display, uint16 breed, BattlePetBreedQuality quality, uint16 level=1)
void SendUpdates(std::vector< std::reference_wrapper< BattlePet > > pets, bool petAdded)
std::unordered_map< uint64, BattlePet > _pets
void UpdateBattlePetData(ObjectGuid guid)
BattlePet * GetPet(ObjectGuid guid)
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)
bool IsPetInSlot(ObjectGuid guid)
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.
std::string GetString() const
void SetModifier(ItemModifier modifier, uint32 value)
LowType GetCounter() const
static ObjectGuid const Empty
std::string ToString() const
static ObjectGuid GetGUID(Object const *o)
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 setInt32(const uint8 index, const int32 value)
void setUInt8(const uint8 index, const uint8 value)
void setInt64(const uint8 index, const int64 value)
void setBool(const uint8 index, const bool value)
void setUInt32(const uint8 index, const uint32 value)
void setUInt16(const uint8 index, const uint16 value)
void setNull(const uint8 index)
void setString(const uint8 index, const std::string &value)
void setUInt64(const uint8 index, const uint64 value)
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
WorldPacket const * Write() override
std::vector< std::reference_wrapper< BattlePet > > Pets
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
uint32 GetVirtualRealmAddress()
@ 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) -> typename std::add_const< decltype(*std::begin(container))>::type &
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
Battlenet::RealmHandle Id
Optional< BattlePetOwnerInfo > OwnerInfo