42#define PET_XP_FACTOR 0.05f
45 Guardian(nullptr, owner, true), m_usedTalentCount(0), m_removed(false),
46 m_happinessTimer(7500), m_petType(type), m_duration(0), m_auraRaidUpdateMask(0), m_loading(false)
76 zoneScript->OnCreatureCreate(
this);
110 for (std::size_t stableSlot = 0; stableSlot < stable.
StabledPets.size(); ++stableSlot)
115 if (pet.PetNumber == petnumber)
131 if (pet.CreatureId == petEntry)
192 std::pair<PetStable::PetInfo const*, PetSaveMode> info =
GetLoadPetInfo(*petStable, petEntry, petnumber, current);
207 bool isTemporarySummon = spellInfo && spellInfo->
GetDuration() > 0;
208 if (current && isTemporarySummon)
240 TC_LOG_ERROR(
"entities.pet",
"Pet{} not loaded. Suggested coordinates isn't valid (X: {} Y: {})",
293 TC_LOG_ERROR(
"entities.pet",
"Pet {} not loaded. Suggested coordinates isn't valid (X: {} Y: {})",
328 return unslottedPet.PetNumber == petInfoNumber;
333 petStable->
CurrentPet = std::move(*unslottedPetItr);
343 return pet && pet->PetNumber == petnumber;
347 std::swap(*stabledPet, petStable->
CurrentPet);
369 if (!isTemporarySummon)
381 if (session->GetPlayer() != owner || owner->GetPet() != this)
388 InitTalentForLevel();
390 uint32 timediff = uint32(GameTime::GetGameTime() - lastSaveTime);
391 _LoadAuras(holder.GetPreparedResult(PetLoadQueryHolder::AURAS), timediff);
394 if (!isTemporarySummon)
396 _LoadSpells(holder.GetPreparedResult(PetLoadQueryHolder::SPELLS));
397 InitTalentForLevel();
398 GetSpellHistory()->LoadFromDB<Pet>(holder.GetPreparedResult(PetLoadQueryHolder::COOLDOWNS));
400 InitLevelupSpellsForLevel();
401 if (GetMap()->IsBattleArena())
404 CastPetAuras(current);
423 Field* fields = result->Fetch();
594 if (!
GetMap()->IsBattlegroundOrArena())
716 int32 addvalue = 670;
718 addvalue =
int32(addvalue * 1.5f);
752 if (petlevel >= maxlevel)
757 uint32 newXP = curXP + xp;
760 while (newXP >= nextLvlXP && petlevel < maxlevel)
801 TC_LOG_ERROR(
"entities.pet",
"Pet {} not created base at creature. Suggested coordinates isn't valid (X: {} Y: {})",
809 TC_LOG_ERROR(
"entities.pet",
"CreateBaseAtCreature() failed, creatureInfo is missing!");
838 TC_LOG_DEBUG(
"entities.pet",
"Pet::CreateBaseForTamed");
885 TC_LOG_ERROR(
"entities.pet",
"Unknown type pet {} is summoned by player class {}",
918 if (pInfo->
armor > 0)
962 int32 val = (fire > shadow) ? fire : shadow;
1113 float weaponBaseMinDamage = basedamage;
1114 float weaponBaseMaxDamage = basedamage * 1.5f;
1147 return (diet & FoodMask) != 0;
1156 else if (
GetLevel() <= itemlevel + 10)
1159 else if (
GetLevel() <= itemlevel + 14)
1172 Field* fields = result->Fetch();
1176 while (result->NextRow());
1192 switch (itr->second.state)
1198 trans->Append(stmt);
1206 trans->Append(stmt);
1211 stmt->
setUInt8(2, itr->second.active);
1212 trans->Append(stmt);
1219 stmt->
setUInt8(2, itr->second.active);
1220 trans->Append(stmt);
1239 int32 baseDamage[3];
1240 Field* fields = result->Fetch();
1252 baseDamage[0] = fields[8].
GetInt32();
1253 baseDamage[1] = fields[9].
GetInt32();
1254 baseDamage[2] = fields[10].
GetInt32();
1258 float critChance = fields[14].
GetFloat();
1259 bool applyResilience = fields[15].
GetBool();
1264 TC_LOG_ERROR(
"entities.pet",
"Unknown aura (spellid {}), ignore.", spellid);
1280 if (remaincharges <= 0 || remaincharges > spellInfo->
ProcCharges)
1293 if (!aura->CanBeSaved())
1298 aura->SetLoadedState(maxduration, remaintime, remaincharges, stackcount, recalculatemask, critChance, applyResilience, &damage[0]);
1299 aura->ApplyForTargets();
1300 TC_LOG_DEBUG(
"entities.pet",
"Added aura spellid {}, effectmask {}", spellInfo->
Id, effmask);
1303 while (result->NextRow());
1311 trans->Append(stmt);
1316 if (!itr->second->CanBeSaved() ||
IsPetAura(itr->second))
1319 Aura* aura = itr->second;
1324 uint8 recalculateMask = 0;
1333 recalculateMask |= (1<<i);
1350 stmt->
setUInt32(index++, itr->second->GetId());
1352 stmt->
setUInt8(index++, recalculateMask);
1353 stmt->
setUInt8(index++, itr->second->GetStackAmount());
1354 stmt->
setInt32(index++, damage[0]);
1355 stmt->
setInt32(index++, damage[1]);
1356 stmt->
setInt32(index++, damage[2]);
1357 stmt->
setInt32(index++, baseDamage[0]);
1358 stmt->
setInt32(index++, baseDamage[1]);
1359 stmt->
setInt32(index++, baseDamage[2]);
1360 stmt->
setInt32(index++, itr->second->GetMaxDuration());
1361 stmt->
setInt32(index++, itr->second->GetDuration());
1362 stmt->
setUInt8(index++, itr->second->GetCharges());
1363 stmt->
setFloat(index++, itr->second->GetCritChance());
1364 stmt->
setBool (index++, itr->second->CanApplyResilience());
1366 trans->Append(stmt);
1378 TC_LOG_ERROR(
"entities.pet",
"Pet::addSpell: Non-existed in SpellStore spell #{} request, deleting for all pets in `pet_spell`.", spellId);
1387 TC_LOG_ERROR(
"entities.pet",
"Pet::addSpell: Non-existed in SpellStore spell #{} request.", spellId);
1392 PetSpellMap::iterator itr =
m_spells.find(spellId);
1415 newspell.
state = state;
1416 newspell.
type = type;
1426 newspell.
active = active;
1433 for (
uint32 rankSpellId : talentInfo->SpellRank)
1436 if (!rankSpellId || rankSpellId == spellId)
1448 for (PetSpellMap::const_iterator itr2 =
m_spells.begin(); itr2 !=
m_spells.end(); ++itr2)
1455 if (!oldRankSpellInfo)
1463 newspell.
active = itr2->second.active;
1523 for (PetLevelupSpellSet::const_reverse_iterator itr = levelupSpells->rbegin(); itr != levelupSpells->rend(); ++itr)
1526 if (itr->first > level)
1539 for (
uint32 spellId : defSpells->spellid)
1572 PetSpellMap::iterator itr =
m_spells.find(spell_id);
1620 if (ab->GetAction() && ab->IsActionBarForSpell())
1686 for (PetSpellMap::const_iterator itr =
m_spells.begin(); itr !=
m_spells.end();)
1697 if (itrFirstId == talentSpellId ||
sSpellMgr->IsSpellLearnToSpell(talentSpellId, itrFirstId))
1734 std::unordered_set<uint32> petIds;
1736 petIds.insert(petStable->
CurrentPet->PetNumber);
1740 petIds.insert(stabledPet->PetNumber);
1743 petIds.insert(unslottedPet.PetNumber);
1756 bool need_comma =
false;
1757 std::ostringstream ss;
1758 ss <<
"DELETE FROM pet_spell WHERE guid IN (";
1770 ss <<
") AND spell IN (";
1804 uint8 points = (level >= 20) ? ((level - 16) / 4) : 0;
1817 PetSpellMap::iterator itr =
m_spells.find(spellInfo->
Id);
1898 PetSpellMap::const_iterator itr =
m_spells.find(spell);
1919 for (
uint32 spellId : petStore->second)
1952 if (auraId == 35696)
2037 std::ostringstream oss;
2050 std::stringstream sstr;
2053 <<
"PetType: " << std::to_string(
getPetType()) <<
" "
@ CHAR_DEL_CHAR_PET_BY_SLOT
@ CHAR_DEL_INVALID_PET_SPELL
@ CHAR_DEL_CHAR_PET_BY_ID
@ CHAR_SEL_PET_DECLINED_NAME
@ CHAR_DEL_PET_SPELL_BY_SPELL
@ CHAR_DEL_PET_SPELL_COOLDOWNS
@ CHAR_SEL_PET_SPELL_COOLDOWN
@ CHAR_DEL_CHAR_PET_DECLINEDNAME
static const uint32 PET_FOCUS_REGEN_INTERVAL
#define MAX_SPELL_EFFECTS
DBCStorage< TalentTabEntry > sTalentTabStore(TalentTabEntryfmt)
TalentSpellPos const * GetTalentSpellPos(uint32 spellId)
uint32 GetTalentSpellCost(uint32 spellId)
std::unordered_set< uint32 > sPetTalentSpells
DBCStorage< CreatureFamilyEntry > sCreatureFamilyStore(CreatureFamilyfmt)
DBCStorage< TalentEntry > sTalentStore(TalentEntryfmt)
PetFamilySpellsStore sPetFamilySpellsStore
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
#define ASSERT_NOTNULL(pointer)
@ GROUP_UPDATE_FLAG_PET_MODEL_ID
#define TC_LOG_DEBUG(filterType__,...)
#define TC_LOG_ERROR(filterType__,...)
std::optional< T > Optional
Optional helper class to wrap optional values within.
@ PET_SAVE_FIRST_STABLE_SLOT
@ PET_SAVE_LAST_STABLE_SLOT
#define HAPPINESS_LEVEL_SIZE
@ AT_LOGIN_RESET_PET_TALENTS
@ SPELL_SCHOOL_MASK_SHADOW
@ SPELL_SCHOOL_MASK_NATURE
@ SPELL_SCHOOL_MASK_FROST
@ SPELL_ATTR4_FADES_WHILE_LOGGED_OUT
@ SPELL_AURA_MOD_PET_TALENT_POINTS
@ TRIGGERED_FULL_MASK
Will return SPELL_FAILED_DONT_REPORT in CheckCast functions.
std::multimap< uint32, uint32 > PetLevelupSpellSet
@ UNIT_FLAG2_REGENERATE_POWER
@ UNIT_PET_FLAG_CAN_BE_ABANDONED
@ UNIT_PET_FLAG_CAN_BE_RENAMED
#define MAX_DECLINED_NAME_CASES
@ UNIT_FLAG_PLAYER_CONTROLLED
@ UNIT_MASK_CONTROLABLE_GUARDIAN
#define MAX_UNIT_ACTION_BAR_INDEX
@ UNIT_MOD_RESISTANCE_START
@ PLAYER_FIELD_MOD_DAMAGE_DONE_POS
@ UNIT_FIELD_PETEXPERIENCE
@ UNIT_FIELD_PETNEXTLEVELEXP
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
T CalculatePct(T base, U pct)
bool CanBeRecalculated() const
int32 GetBaseAmount() const
static Aura * TryCreate(AuraCreateInfo &createInfo)
AuraEffect * GetEffect(uint8 effIndex) const
void SetPhaseMask(uint32 newPhaseMask, bool update) override
void setDeathState(DeathState s) override
void SetDisplayId(uint32 modelId) override
void Update(uint32 time) override
void SetObjectScale(float scale) override
bool AIM_Initialize(CreatureAI *ai=nullptr)
void LoadTemplateImmunities()
void SetReactState(ReactStates st)
std::string const & GetNameForLocaleIdx(LocaleConstant locale_idx) const override
time_t m_corpseRemoveTime
static float _GetHealthMod(int32 Rank)
CreatureTemplate const * GetCreatureTemplate() const
float GetNativeObjectScale() const override
ReactStates GetReactState() const
bool InitEntry(uint32 entry, CreatureData const *data=nullptr)
void SetMeleeDamageSchool(SpellSchools school)
void Regenerate(Powers power)
Class used to access individual fields of database query result.
std::string GetString() const
void SetBonusDamage(int32 damage)
bool InitStatsForLevel(uint8 level)
std::string GetDebugInfo() const override
bool UpdateAllStats() override
MapStoredObjectTypesContainer & GetObjectsStore()
ObjectGuid::LowType GenerateLowGuid()
float GetFollowAngle() const override
LowType GetCounter() const
static ObjectGuid const Empty
void SetRawValue(uint64 guid)
uint64 GetRawValue() const
uint32 GetUInt32Value(uint16 index) const
void _Create(ObjectGuid const &guid)
static ObjectGuid GetGUID(Object const *o)
void SetUInt32Value(uint16 index, uint32 value)
ObjectGuid GetGUID() const
static Player * ToPlayer(Object *o)
uint32 GetAura(uint32 petEntry) const
bool IsRemovedOnChangePet() const
PetLoadQueryHolder(ObjectGuid::LowType ownerGuid, uint32 petNumber)
std::array< Optional< PetInfo >, MAX_PET_STABLES > StabledPets
Optional< PetInfo > CurrentPet
std::vector< PetInfo > UnslottedPets
Pet(Player *owner, PetType type=MAX_PET_TYPE)
void GivePetLevel(uint8 level)
void RemoveFromWorld() override
Player * GetOwner() const
bool IsPetAura(Aura const *aura)
bool unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab=true)
void FillPetInfo(PetStable::PetInfo *petInfo) const
bool Create(ObjectGuid::LowType guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number)
void SetDisplayId(uint32 modelId) override
void ToggleAutocast(SpellInfo const *spellInfo, bool apply)
static void resetTalentsForAllPetsOf(Player *owner, Pet *online_pet=nullptr, bool involuntarily=false)
void AddToWorld() override
void InitTalentForLevel()
void CastPetAuras(bool current)
void setPetType(PetType type)
void SavePetToDB(PetSaveMode mode)
float GetNativeObjectScale() const override
void _SaveAuras(CharacterDatabaseTransaction trans)
PetType getPetType() const
void SynchronizeLevelWithOwner()
std::unique_ptr< DeclinedName > m_declinedname
uint8 GetMaxTalentPointsForLevel(uint8 level) const
void _SaveSpells(CharacterDatabaseTransaction trans)
void learnSpellHighRank(uint32 spellid)
bool IsPermanentPetFor(Player *owner) const
bool HaveInDiet(ItemTemplate const *item) const
bool addSpell(uint32 spellId, ActiveStates active=ACT_DECIDE, PetSpellState state=PETSPELL_NEW, PetSpellType type=PETSPELL_NORMAL)
AutoSpellList m_autospells
void SetPetExperience(uint32 xp)
std::string GetDebugInfo() const override
static void DeleteFromDB(ObjectGuid::LowType guidlow)
bool CreateBaseAtTamed(CreatureTemplate const *cinfo, Map *map, uint32 phaseMask)
bool CreateBaseAtCreatureInfo(CreatureTemplate const *cinfo, Unit *owner)
HappinessState GetHappinessState()
bool removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab=true)
bool CreateBaseAtCreature(Creature *creature)
bool isTemporarySummoned() const
void CastPetAura(PetAura const *aura)
void _LoadSpells(PreparedQueryResult result)
bool isControlled() const
void SetPetNextLevelExperience(uint32 xp)
void setDeathState(DeathState s) override
void SetFreeTalentPoints(uint8 points)
void Remove(PetSaveMode mode, bool returnreagent=false)
void Update(uint32 diff) override
void InitPetCreateSpells()
void _LoadAuras(PreparedQueryResult result, uint32 timediff)
bool HasSpell(uint32 spell) const override
bool resetTalents(bool involuntarily=false)
uint32 GetCurrentFoodBenefitLevel(uint32 itemlevel) const
static std::pair< PetStable::PetInfo const *, PetSaveMode > GetLoadPetInfo(PetStable const &stable, uint32 petEntry, uint32 petnumber, bool current)
bool LoadPetFromDB(Player *owner, uint32 petEntry, uint32 petnumber, bool current)
void GivePetXP(uint32 xp)
std::string GenerateActionBarData() const
bool learnSpell(uint32 spell_id)
void InitLevelupSpellsForLevel()
void RemoveAtLoginFlag(AtLoginFlags flags, bool persist=false)
void SendTalentsInfoData(bool pet)
void SetGroupUpdateFlag(uint32 flag)
uint32 GetTemporaryUnsummonedPetNumber() const
void SendDirectMessage(WorldPacket const *data) const
bool CanTameExoticPets() const
void SetTemporaryUnsummonedPetNumber(uint32 petnumber)
bool IsPetNeedBeTemporaryUnsummoned() const
PetStable * GetPetStable()
void PetSpellInitialize()
WorldSession * GetSession() const
void RemovePet(Pet *pet, PetSaveMode mode, bool returnreagent=false)
std::unordered_set< PetAura const * > m_petAuras
bool HasAtLoginFlag(AtLoginFlags f) const
void RemovePetAura(PetAura const *petSpell)
void SendMessageToSet(WorldPacket const *data, bool self) const override
void SetLastPetNumber(uint32 petnumber)
void setUInt32(uint8 index, uint32 value)
void setBool(uint8 index, bool value)
void setFloat(uint8 index, float value)
void setUInt64(uint8 index, uint64 value)
void setInt32(uint8 index, int32 value)
void setUInt8(uint8 index, uint8 value)
void setString(uint8 index, std::string const &value)
void SetSize(size_t size)
PreparedQueryResult GetPreparedResult(size_t index) const
void AfterComplete(std::function< void(SQLQueryHolderBase const &)> callback) &
bool SetPreparedQuery(size_t index, PreparedStatement< T > *stmt)
void SaveToDB(CharacterDatabaseTransaction trans)
bool IsAutocastable() const
bool IsHighRankOf(SpellInfo const *spellInfo) const
bool HasAttribute(SpellAttr0 attribute) const
int32 GetDuration() const
bool IsDifferentRankOf(SpellInfo const *spellInfo) const
bool Remove(KEY_TYPE const &handle)
bool Insert(KEY_TYPE const &handle, SPECIFIC_TYPE *obj)
void ReplaceAllDynamicFlags(uint32 flag) override
void SetMinion(Minion *minion, bool apply)
int32 ModifyPower(Powers power, int32 val, bool withPowerUpdate=true)
bool HasPetFlag(UnitPetFlag flags) const
void SetCreateStat(Stats stat, float val)
void SetGender(Gender gender)
ThreatManager & GetThreatManager()
void AddToWorld() override
void SetCreateHealth(uint32 val)
void SetFaction(uint32 faction) override
ObjectGuid GetOwnerGUID() const override
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value, uint8 damageIndex=0)
void ReplaceAllUnitFlags(UnitFlags flags)
Powers GetPowerType() const
void SetCreatedBySpell(int32 spellId)
uint32 GetMaxHealth() const
Aura * AddAura(uint32 spellId, Unit *target)
void SetUnitFlag2(UnitFlags2 flags)
void ReplaceAllPetFlags(UnitPetFlag flags)
void SetPetNameTimestamp(uint32 timestamp)
float GetCombatReach() const override
void SetHealth(uint32 val)
void SetMaxPower(Powers power, uint32 val)
CharmInfo * GetCharmInfo()
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
void SetNativeDisplayId(uint32 displayId)
void SetCreateMana(uint32 val)
virtual void SetSheath(SheathState sheathed)
uint32 GetDisplayId() const
uint32 GetNativeDisplayId() const
uint32 GetMaxPower(Powers power) const
uint32 GetFaction() const override
void SetPower(Powers power, uint32 val, bool withPowerUpdate=true, bool force=false)
bool HasAuraState(AuraStateType flag, SpellInfo const *spellProto=nullptr, Unit const *Caster=nullptr) const
int32 GetTotalAuraModifier(AuraType auraType) const
void SetFullPower(Powers power)
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
void SetPowerType(Powers power, bool sendUpdate=true)
DeathState getDeathState() const
void SetLevel(uint8 lvl, bool sendUpdate=true)
void SetCanModifyStats(bool modifyStats)
CharmInfo * InitCharmInfo()
void SetClass(uint8 classId)
void RemoveFromWorld() override
float GetStat(Stats stat) const
SpellHistory * GetSpellHistory()
void SetCreatorGUID(ObjectGuid creator)
uint32 GetPower(Powers power) const
void SetAttackTime(WeaponAttackType att, uint32 val)
void SetModCastingSpeed(float castingSpeed)
void ReplaceAllNpcFlags(NPCFlags flags)
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
void SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val)
uint32 GetCreatePowerValue(Powers power) const
float GetTotalAttackPowerValue(WeaponAttackType attType) const
void RemoveUnitFlag(UnitFlags flags)
ObjectGuid GetPetGUID() const
uint32 GetPhaseMask() const
InstanceScript * GetInstanceScript() const
void GetClosePoint(float &x, float &y, float &z, float size, float distance2d=0, float relAngle=0) const
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
ZoneScript * GetZoneScript() const
std::string const & GetName() const
virtual void SetMap(Map *map)
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
void SetName(std::string newname)
float GetVisibilityRange() const
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
std::string GetPlayerInfo() const
SQLQueryHolderCallback & AddQueryHolderCallback(SQLQueryHolderCallback &&callback)
@ CONFIG_MAX_PLAYER_LEVEL
AuraCreateInfo & SetBaseAmount(int32 const *bp)
AuraCreateInfo & SetCasterGUID(ObjectGuid const &guid)
void SetIsCommandFollow(bool val)
uint32 GetPetNumber() const
void LoadPetActionBar(const std::string &data)
void SetActionBar(uint8 index, uint32 spellOrAction, ActiveStates type)
bool AddSpellToActionBar(SpellInfo const *spellInfo, ActiveStates newstate=ACT_DECIDE, uint8 preferredSlot=0)
void SetIsAtStay(bool val)
void SetPetNumber(uint32 petnumber, bool statwindow)
void SetIsFollowing(bool val)
void SetIsReturning(bool val)
bool RemoveSpellFromActionBar(uint32 spell_id)
UnitActionBarEntry const * GetActionBarEntry(uint8 index) const
bool HasCommandState(CommandStates state) const
void SetIsCommandAttack(bool val)
float GenerateBaseDamage(CreatureTemplate const *info) const
uint32 GenerateMana(CreatureTemplate const *info) const
uint32 GenerateHealth(CreatureTemplate const *info) const
int32 resistance[MAX_SPELL_SCHOOL]
bool IsTameable(bool canTameExotic) const
std::string ToString() const
float GetPositionZ() const
float GetOrientation() const
bool IsPositionValid() const
float GetPositionX() const
float GetPositionY() const
void Relocate(float x, float y)
std::array< uint32, MAX_TALENT_RANK > SpellRank
ActiveStates GetType() const