aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/BattlePets/BattlePetMgr.cpp27
-rw-r--r--src/server/game/BattlePets/BattlePetMgr.h17
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp16
-rw-r--r--src/server/game/Entities/Creature/Creature.h3
-rw-r--r--src/server/game/Entities/Player/Player.h1
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp9
-rw-r--r--src/server/game/Entities/Unit/Unit.h32
-rw-r--r--src/server/game/Spells/SpellEffects.cpp2
8 files changed, 82 insertions, 25 deletions
diff --git a/src/server/game/BattlePets/BattlePetMgr.cpp b/src/server/game/BattlePets/BattlePetMgr.cpp
index 5938595fb50..9a22df4ee08 100644
--- a/src/server/game/BattlePets/BattlePetMgr.cpp
+++ b/src/server/game/BattlePets/BattlePetMgr.cpp
@@ -142,13 +142,24 @@ void BattlePetMgr::LoadDefaultPetQualities()
uint32 speciesId = fields[0].GetUInt32();
uint8 quality = fields[1].GetUInt8();
- if (!sBattlePetSpeciesStore.LookupEntry(speciesId))
+ BattlePetSpeciesEntry const* battlePetSpecies = sBattlePetSpeciesStore.LookupEntry(speciesId);
+ if (!battlePetSpecies)
{
TC_LOG_ERROR("sql.sql", "Non-existing BattlePetSpecies.db2 entry %u was referenced in `battle_pet_quality` by row (%u, %u).", speciesId, speciesId, quality);
continue;
}
- // TODO: verify quality (0 - 3 for player pets or 0 - 5 for both player and tamer pets) if needed
+ if (quality >= AsUnderlyingType(BattlePetBreedQuality::Count))
+ {
+ TC_LOG_ERROR("sql.sql", "BattlePetSpecies.db2 entry %u was referenced in `battle_pet_quality` with non-existing quality %u).", speciesId, quality);
+ continue;
+ }
+
+ if (battlePetSpecies->GetFlags().HasFlag(BattlePetSpeciesFlags::WellKnown) && quality > AsUnderlyingType(BattlePetBreedQuality::Rare))
+ {
+ TC_LOG_ERROR("sql.sql", "Learnable BattlePetSpecies.db2 entry %u was referenced in `battle_pet_quality` with invalid quality %u. Maximum allowed quality is BattlePetBreedQuality::Rare.", speciesId, quality);
+ continue;
+ }
_defaultQualityPerSpecies[speciesId] = quality;
} while (result->NextRow());
@@ -165,13 +176,13 @@ uint16 BattlePetMgr::RollPetBreed(uint32 species)
return Trinity::Containers::SelectRandomContainerElement(itr->second);
}
-uint8 BattlePetMgr::GetDefaultPetQuality(uint32 species)
+BattlePetBreedQuality BattlePetMgr::GetDefaultPetQuality(uint32 species)
{
auto itr = _defaultQualityPerSpecies.find(species);
if (itr == _defaultQualityPerSpecies.end())
- return 0; // default poor
+ return BattlePetBreedQuality::Poor; // Default
- return itr->second;
+ return BattlePetBreedQuality(itr->second);
}
BattlePetMgr::BattlePetMgr(WorldSession* owner)
@@ -308,7 +319,7 @@ BattlePetMgr::BattlePet* BattlePetMgr::GetPet(ObjectGuid guid)
return Trinity::Containers::MapGetValuePtr(_pets, guid.GetCounter());
}
-void BattlePetMgr::AddPet(uint32 species, uint32 creatureId, uint16 breed, uint8 quality, uint16 level /*= 1*/)
+void BattlePetMgr::AddPet(uint32 species, uint32 creatureId, uint16 breed, BattlePetBreedQuality quality, uint16 level /*= 1*/)
{
BattlePetSpeciesEntry const* battlePetSpecies = sBattlePetSpeciesStore.LookupEntry(species);
if (!battlePetSpecies) // should never happen
@@ -325,7 +336,7 @@ void BattlePetMgr::AddPet(uint32 species, uint32 creatureId, uint16 breed, uint8
pet.PacketInfo.Exp = 0;
pet.PacketInfo.Flags = 0;
pet.PacketInfo.Breed = breed;
- pet.PacketInfo.Quality = quality;
+ pet.PacketInfo.Quality = AsUnderlyingType(quality);
pet.PacketInfo.Name = "";
pet.CalculateStats();
pet.PacketInfo.Health = pet.PacketInfo.MaxHealth;
@@ -495,6 +506,7 @@ void BattlePetMgr::SummonPet(ObjectGuid guid)
// TODO: set proper CreatureID for spell DEFAULT_SUMMON_BATTLE_PET_SPELL (default EffectMiscValueA is 40721 - Murkimus the Gladiator)
_owner->GetPlayer()->SetSummonedBattlePetGUID(guid);
+ _owner->GetPlayer()->SetCurrentBattlePetBreedQuality(pet->PacketInfo.Quality);
_owner->GetPlayer()->CastSpell(_owner->GetPlayer(), speciesEntry->SummonSpellID ? speciesEntry->SummonSpellID : uint32(DEFAULT_SUMMON_BATTLE_PET_SPELL));
// TODO: set pet level, quality... update fields
@@ -508,6 +520,7 @@ void BattlePetMgr::DismissPet()
{
pet->DespawnOrUnsummon();
ownerPlayer->SetSummonedBattlePetGUID(ObjectGuid::Empty);
+ ownerPlayer->SetCurrentBattlePetBreedQuality(AsUnderlyingType(BattlePetBreedQuality::Poor));
}
}
diff --git a/src/server/game/BattlePets/BattlePetMgr.h b/src/server/game/BattlePets/BattlePetMgr.h
index 721c1aafa3d..d1da973dc00 100644
--- a/src/server/game/BattlePets/BattlePetMgr.h
+++ b/src/server/game/BattlePets/BattlePetMgr.h
@@ -20,6 +20,7 @@
#include "BattlePetPackets.h"
#include "DatabaseEnvFwd.h"
+#include "EnumFlag.h"
#include <unordered_map>
struct BattlePetSpeciesEntry;
@@ -32,6 +33,18 @@ enum BattlePetMisc
DEFAULT_SUMMON_BATTLE_PET_SPELL = 118301
};
+enum class BattlePetBreedQuality : uint8
+{
+ Poor = 0,
+ Common = 1,
+ Uncommon = 2,
+ Rare = 3,
+ Epic = 4,
+ Legendary = 5,
+
+ Count
+};
+
enum class BattlePetDbFlags : uint16
{
None = 0x000,
@@ -122,13 +135,13 @@ public:
static void Initialize();
static uint16 RollPetBreed(uint32 species);
- static uint8 GetDefaultPetQuality(uint32 species);
+ static BattlePetBreedQuality GetDefaultPetQuality(uint32 species);
void LoadFromDB(PreparedQueryResult pets, PreparedQueryResult slots);
void SaveToDB(LoginDatabaseTransaction& trans);
BattlePet* GetPet(ObjectGuid guid);
- void AddPet(uint32 species, uint32 creatureId, uint16 breed, uint8 quality, uint16 level = 1);
+ void AddPet(uint32 species, uint32 creatureId, uint16 breed, BattlePetBreedQuality quality, uint16 level = 1);
void RemovePet(ObjectGuid guid);
void ClearFanfare(ObjectGuid guid);
bool IsPetInSlot(ObjectGuid guid);
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 162fd6fc1f0..ef6c5385fda 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -1620,6 +1620,20 @@ void Creature::UpdateLevelDependantStats()
SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, armor);
}
+void Creature::SelectWildBattlePetLevel()
+{
+ if (IsWildBattlePet())
+ {
+ uint8 wildBattlePetLevel = WILD_BATTLE_PET_DEFAULT_LEVEL;
+
+ if (AreaTableEntry const* areaTable = sAreaTableStore.LookupEntry(GetZoneId()))
+ if (areaTable->WildBattlePetLevelMin > 0)
+ wildBattlePetLevel = urand(areaTable->WildBattlePetLevelMin, areaTable->WildBattlePetLevelMax);
+
+ SetWildBattlePetLevel(wildBattlePetLevel);
+ }
+}
+
float Creature::_GetHealthMod(int32 Rank)
{
switch (Rank) // define rates for each elite rank
@@ -1804,6 +1818,8 @@ bool Creature::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap,
SetSpawnHealth();
+ SelectWildBattlePetLevel();
+
// checked at creature_template loading
m_defaultMovementType = MovementGeneratorType(data->movementType);
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index cab9b45e783..2aa3fa395c3 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -54,6 +54,8 @@ typedef std::list<VendorItemCount> VendorItemCounts;
#define MAX_VENDOR_ITEMS 150 // Limitation in 4.x.x item count in SMSG_LIST_INVENTORY
+static constexpr uint8 WILD_BATTLE_PET_DEFAULT_LEVEL = 1;
+
//used for handling non-repeatable random texts
typedef std::vector<uint8> CreatureTextRepeatIds;
typedef std::unordered_map<uint8, CreatureTextRepeatIds> CreatureTextRepeatGroup;
@@ -81,6 +83,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool LoadCreaturesAddon();
void SelectLevel();
void UpdateLevelDependantStats();
+ void SelectWildBattlePetLevel();
void LoadEquipment(int8 id = 1, bool force = false);
void SetSpawnHealth();
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 17818b4c33c..99660ed918c 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2622,6 +2622,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void SetArenaFaction(uint8 arenaFaction) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::ArenaFaction), arenaFaction); }
void ApplyModFakeInebriation(int32 mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::FakeInebriation), mod, apply); }
void SetVirtualPlayerRealm(uint32 virtualRealmAddress) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::VirtualPlayerRealm), virtualRealmAddress); }
+ void SetCurrentBattlePetBreedQuality(uint8 battlePetBreedQuality) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::CurrentBattlePetBreedQuality), battlePetBreedQuality); }
void AddHeirloom(int32 itemId, uint32 flags)
{
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index e86156cc3bf..86db8294fcb 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -22,6 +22,7 @@
#include "Battleground.h"
#include "BattlegroundPackets.h"
#include "BattlegroundScore.h"
+#include "BattlePetMgr.h"
#include "CellImpl.h"
#include "CharacterCache.h"
#include "ChatPackets.h"
@@ -5823,7 +5824,13 @@ void Unit::SetMinion(Minion *minion, bool apply)
{
SetCritterGUID(minion->GetGUID());
if (Player const* thisPlayer = ToPlayer())
- minion->SetBattlePetCompanionGUID(thisPlayer->m_activePlayerData->SummonedBattlePetGUID);
+ {
+ if (BattlePetMgr::BattlePet const* pet = thisPlayer->GetSession()->GetBattlePetMgr()->GetPet(thisPlayer->m_activePlayerData->SummonedBattlePetGUID))
+ {
+ minion->SetBattlePetCompanionGUID(thisPlayer->m_activePlayerData->SummonedBattlePetGUID);
+ minion->SetWildBattlePetLevel(pet->PacketInfo.Level);
+ }
+ }
}
// PvP, FFAPvP
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 67746b97bc9..810f1de1413 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1065,20 +1065,21 @@ class TC_GAME_API Unit : public WorldObject
void AddNpcFlag2(NPCFlags2 flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::NpcFlags, 1), flags); }
void RemoveNpcFlag2(NPCFlags2 flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::NpcFlags, 1), flags); }
void SetNpcFlags2(NPCFlags2 flags) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::NpcFlags, 1), flags); }
- bool IsVendor() const { return HasNpcFlag(UNIT_NPC_FLAG_VENDOR); }
- bool IsTrainer() const { return HasNpcFlag(UNIT_NPC_FLAG_TRAINER); }
- bool IsQuestGiver() const { return HasNpcFlag(UNIT_NPC_FLAG_QUESTGIVER); }
- bool IsGossip() const { return HasNpcFlag(UNIT_NPC_FLAG_GOSSIP); }
- bool IsTaxi() const { return HasNpcFlag(UNIT_NPC_FLAG_FLIGHTMASTER); }
- bool IsGuildMaster() const { return HasNpcFlag(UNIT_NPC_FLAG_PETITIONER); }
- bool IsBattleMaster() const { return HasNpcFlag(UNIT_NPC_FLAG_BATTLEMASTER); }
- bool IsBanker() const { return HasNpcFlag(UNIT_NPC_FLAG_BANKER); }
- bool IsInnkeeper() const { return HasNpcFlag(UNIT_NPC_FLAG_INNKEEPER); }
- bool IsSpiritHealer() const { return HasNpcFlag(UNIT_NPC_FLAG_SPIRITHEALER); }
- bool IsSpiritGuide() const { return HasNpcFlag(UNIT_NPC_FLAG_SPIRITGUIDE); }
- bool IsTabardDesigner()const{ return HasNpcFlag(UNIT_NPC_FLAG_TABARDDESIGNER); }
- bool IsAuctioner() const { return HasNpcFlag(UNIT_NPC_FLAG_AUCTIONEER); }
- bool IsArmorer() const { return HasNpcFlag(UNIT_NPC_FLAG_REPAIR); }
+ bool IsVendor() const { return HasNpcFlag(UNIT_NPC_FLAG_VENDOR); }
+ bool IsTrainer() const { return HasNpcFlag(UNIT_NPC_FLAG_TRAINER); }
+ bool IsQuestGiver() const { return HasNpcFlag(UNIT_NPC_FLAG_QUESTGIVER); }
+ bool IsGossip() const { return HasNpcFlag(UNIT_NPC_FLAG_GOSSIP); }
+ bool IsTaxi() const { return HasNpcFlag(UNIT_NPC_FLAG_FLIGHTMASTER); }
+ bool IsGuildMaster() const { return HasNpcFlag(UNIT_NPC_FLAG_PETITIONER); }
+ bool IsBattleMaster() const { return HasNpcFlag(UNIT_NPC_FLAG_BATTLEMASTER); }
+ bool IsBanker() const { return HasNpcFlag(UNIT_NPC_FLAG_BANKER); }
+ bool IsInnkeeper() const { return HasNpcFlag(UNIT_NPC_FLAG_INNKEEPER); }
+ bool IsSpiritHealer() const { return HasNpcFlag(UNIT_NPC_FLAG_SPIRITHEALER); }
+ bool IsSpiritGuide() const { return HasNpcFlag(UNIT_NPC_FLAG_SPIRITGUIDE); }
+ bool IsTabardDesigner() const { return HasNpcFlag(UNIT_NPC_FLAG_TABARDDESIGNER); }
+ bool IsAuctioner() const { return HasNpcFlag(UNIT_NPC_FLAG_AUCTIONEER); }
+ bool IsArmorer() const { return HasNpcFlag(UNIT_NPC_FLAG_REPAIR); }
+ bool IsWildBattlePet() const { return HasNpcFlag(UNIT_NPC_FLAG_WILD_BATTLE_PET); }
bool IsServiceProvider() const;
bool IsSpiritService() const { return HasNpcFlag(NPCFlags(UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE)); }
bool IsCritter() const { return GetCreatureType() == CREATURE_TYPE_CRITTER; }
@@ -1296,6 +1297,9 @@ class TC_GAME_API Unit : public WorldObject
Pet* CreateTamedPetFrom(uint32 creatureEntry, uint32 spell_id = 0);
bool InitTamedPet(Pet* pet, uint8 level, uint32 spell_id);
+ void SetWildBattlePetLevel(uint32 wildBattlePetLevel) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::WildBattlePetLevel), wildBattlePetLevel); }
+ uint32 GetWildBattlePetLevel() const { return m_unitData->WildBattlePetLevel; }
+
// aura apply/remove helpers - you should better not use these
Aura* _TryStackingOrRefreshingExistingAura(AuraCreateInfo& createInfo);
void _AddAura(UnitAura* aura, Unit* caster);
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 0c12f8f8243..49936e0ed15 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -5670,7 +5670,7 @@ void Spell::EffectUncageBattlePet()
return;
}
- battlePetMgr->AddPet(speciesId, creatureId, breed, quality, level);
+ battlePetMgr->AddPet(speciesId, creatureId, breed, BattlePetBreedQuality(quality), level);
if (!plr->HasSpell(speciesEntry->SummonSpellID))
plr->LearnSpell(speciesEntry->SummonSpellID, false);