diff options
-rw-r--r-- | src/server/game/BattlePets/BattlePetMgr.cpp | 46 | ||||
-rw-r--r-- | src/server/game/BattlePets/BattlePetMgr.h | 29 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Structure.h | 2 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 22 | ||||
-rw-r--r-- | src/server/game/Handlers/BattlePetHandler.cpp | 5 | ||||
-rw-r--r-- | src/server/game/Server/Packets/BattlePetPackets.cpp | 5 | ||||
-rw-r--r-- | src/server/game/Server/Packets/BattlePetPackets.h | 10 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 2 |
10 files changed, 116 insertions, 9 deletions
diff --git a/src/server/game/BattlePets/BattlePetMgr.cpp b/src/server/game/BattlePets/BattlePetMgr.cpp index 55531bf20fa..5938595fb50 100644 --- a/src/server/game/BattlePets/BattlePetMgr.cpp +++ b/src/server/game/BattlePets/BattlePetMgr.cpp @@ -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); diff --git a/src/server/game/BattlePets/BattlePetMgr.h b/src/server/game/BattlePets/BattlePetMgr.h index 49ed9edc23f..721c1aafa3d 100644 --- a/src/server/game/BattlePets/BattlePetMgr.h +++ b/src/server/game/BattlePets/BattlePetMgr.h @@ -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; } diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index 941ecc72605..351f6e3d94e 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -479,6 +479,8 @@ struct BattlePetSpeciesEntry int32 CardUIModelSceneID; int32 LoadoutUIModelSceneID; int32 CovenantID; + + EnumFlag<BattlePetSpeciesFlags> GetFlags() const { return static_cast<BattlePetSpeciesFlags>(Flags); } }; struct BattlePetSpeciesStateEntry diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index babc2fde7a2..26dbebefc37 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -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, diff --git a/src/server/game/Handlers/BattlePetHandler.cpp b/src/server/game/Handlers/BattlePetHandler.cpp index 907c10ac24b..af088ba000f 100644 --- a/src/server/game/Handlers/BattlePetHandler.cpp +++ b/src/server/game/Handlers/BattlePetHandler.cpp @@ -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); diff --git a/src/server/game/Server/Packets/BattlePetPackets.cpp b/src/server/game/Server/Packets/BattlePetPackets.cpp index f664e92ea0f..e241e985367 100644 --- a/src/server/game/Server/Packets/BattlePetPackets.cpp +++ b/src/server/game/Server/Packets/BattlePetPackets.cpp @@ -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; diff --git a/src/server/game/Server/Packets/BattlePetPackets.h b/src/server/game/Server/Packets/BattlePetPackets.h index 2cc13908abc..9ad402a16fa 100644 --- a/src/server/game/Server/Packets/BattlePetPackets.h +++ b/src/server/game/Server/Packets/BattlePetPackets.h @@ -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: diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 21a7f023913..cad41a689a6 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -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); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index df4ebae873b..93c6ee84f66 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -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); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 5a48f16948b..cb330f5ca44 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -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); |