/* * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef BattlePetMgr_h__ #define BattlePetMgr_h__ #include "BattlePetPackets.h" #include "DatabaseEnvFwd.h" #include "EnumFlag.h" #include struct BattlePetSpeciesEntry; namespace BattlePets { enum BattlePetMisc { DEFAULT_MAX_BATTLE_PETS_PER_SPECIES = 3, BATTLE_PET_CAGE_ITEM_ID = 82800, SPELL_VISUAL_UNCAGE_PET = 222, SPELL_BATTLE_PET_TRAINING = 125610, SPELL_REVIVE_BATTLE_PETS = 125439, SPELL_SUMMON_BATTLE_PET = 118301 }; static constexpr uint16 MAX_BATTLE_PET_LEVEL = 25; enum class BattlePetBreedQuality : uint8 { Poor = 0, Common = 1, Uncommon = 2, Rare = 3, Epic = 4, Legendary = 5, Count }; 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); enum class BattlePetError : uint8 { CantHaveMorePetsOfType = 3, // You can't have any more pets of that type. CantHaveMorePets = 4, // You can't have any more pets. TooHighLevelToUncage = 7 // This pet is too high level for you to uncage. }; enum class BattlePetSlot : uint8 { Slot0 = 0, Slot1 = 1, Slot2 = 2, Count }; enum class BattlePetXpSource : uint8 { PetBattle = 0, SpellEffect = 1, Count }; // 6.2.4 enum FlagsControlType { FLAGS_CONTROL_TYPE_APPLY = 1, FLAGS_CONTROL_TYPE_REMOVE = 2 }; // taken from BattlePetState.db2 - it seems to store some initial values for battle pets // there are only values used in BattlePetSpeciesState.db2 and BattlePetBreedState.db2 // TODO: expand this enum if needed enum BattlePetState { STATE_MAX_HEALTH_BONUS = 2, STATE_INTERNAL_INITIAL_LEVEL = 17, STATE_STAT_POWER = 18, STATE_STAT_STAMINA = 19, STATE_STAT_SPEED = 20, STATE_MOD_DAMAGE_DEALT_PERCENT = 23, STATE_GENDER = 78, // 1 - male, 2 - female STATE_COSMETIC_WATER_BUBBLED = 85, STATE_SPECIAL_IS_COCKROACH = 93, STATE_COSMETIC_FLY_TIER = 128, STATE_COSMETIC_BIGGLESWORTH = 144, STATE_PASSIVE_ELITE = 153, STATE_PASSIVE_BOSS = 162, STATE_COSMETIC_TREASURE_GOBLIN = 176, // these are not in BattlePetState.db2 but are used in BattlePetSpeciesState.db2 STATE_START_WITH_BUFF = 183, STATE_START_WITH_BUFF_2 = 184, // STATE_COSMETIC_SPECTRAL_BLUE = 196 }; enum BattlePetSaveInfo { BATTLE_PET_UNCHANGED = 0, BATTLE_PET_CHANGED = 1, BATTLE_PET_NEW = 2, BATTLE_PET_REMOVED = 3 }; struct BattlePet { void CalculateStats(); WorldPackets::BattlePet::BattlePet PacketInfo; time_t NameTimestamp = time_t(0); std::unique_ptr<::DeclinedName> DeclinedName; BattlePetSaveInfo SaveInfo = BATTLE_PET_UNCHANGED; }; class TC_GAME_API BattlePetMgr { public: explicit BattlePetMgr(WorldSession* owner); BattlePetMgr(BattlePetMgr const& right) = delete; BattlePetMgr(BattlePetMgr&& right) = delete; static void Initialize(); static void AddBattlePetSpeciesBySpell(uint32 spellId, BattlePetSpeciesEntry const* speciesEntry); static BattlePetSpeciesEntry const* GetBattlePetSpeciesByCreature(uint32 creatureId); static BattlePetSpeciesEntry const* GetBattlePetSpeciesBySpell(uint32 spellId); static uint16 RollPetBreed(uint32 species); static BattlePetBreedQuality GetDefaultPetQuality(uint32 species); static uint32 SelectPetDisplay(BattlePetSpeciesEntry const* speciesEntry); void LoadFromDB(PreparedQueryResult pets, PreparedQueryResult slots); void SaveToDB(LoginDatabaseTransaction trans); BattlePet* GetPet(ObjectGuid guid); void AddPet(uint32 species, uint32 display, uint16 breed, BattlePetBreedQuality quality, uint16 level = 1); void RemovePet(ObjectGuid guid); void ClearFanfare(ObjectGuid guid); void ModifyName(ObjectGuid guid, std::string const& name, std::unique_ptr declinedName); bool IsPetInSlot(ObjectGuid guid) const; uint8 GetPetCount(BattlePetSpeciesEntry const* battlePetSpecies, ObjectGuid ownerGuid) const; bool HasMaxPetCount(BattlePetSpeciesEntry const* battlePetSpecies, ObjectGuid ownerGuid) const; uint32 GetPetUniqueSpeciesCount() const; WorldPackets::BattlePet::BattlePetSlot* GetSlot(BattlePetSlot slot) { return slot < BattlePetSlot::Count ? &_slots[size_t(slot)] : nullptr; } void UnlockSlot(BattlePetSlot slot); WorldSession* GetOwner() const { return _owner; } uint16 GetTrapLevel() const { return _trapLevel; } uint16 GetMaxPetLevel() const; std::vector const& GetSlots() const { return _slots; } void CageBattlePet(ObjectGuid guid); void ChangeBattlePetQuality(ObjectGuid guid, BattlePetBreedQuality quality); void GrantBattlePetExperience(ObjectGuid guid, uint16 xp, BattlePetXpSource xpSource); void GrantBattlePetLevel(ObjectGuid guid, uint16 grantedLevels); void HealBattlePetsPct(uint8 pct); void UpdateBattlePetData(ObjectGuid guid); void SummonPet(ObjectGuid guid); void DismissPet(); void SendJournal(); void SendUpdates(std::span const> pets, bool petAdded); void SendError(BattlePetError error, uint32 creatureId); void SendJournalLockStatus(); bool IsJournalLockAcquired() const; bool HasJournalLock() const { return _hasJournalLock; } void ToggleJournalLock(bool lock) { _hasJournalLock = lock; } bool IsBattlePetSystemEnabled() { return GetSlot(BattlePetSlot::Slot0)->Locked != true; } private: WorldSession* _owner; bool _hasJournalLock = false; uint16 _trapLevel = 0; std::unordered_map _pets; std::vector _slots; static void LoadAvailablePetBreeds(); static void LoadDefaultPetQualities(); }; } #endif // BattlePetMgr_h__