TrinityCore
Loading...
Searching...
No Matches
Pet.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Pet.h"
19#include "CharmInfo.h"
20#include "Common.h"
21#include "DatabaseEnv.h"
22#include "DB2Stores.h"
23#include "Group.h"
24#include "InstanceScript.h"
25#include "Log.h"
26#include "Map.h"
27#include "ObjectMgr.h"
28#include "PetPackets.h"
29#include "PhasingHandler.h"
30#include "Player.h"
31#include "QueryHolder.h"
32#include "Spell.h"
33#include "SpellAuraEffects.h"
34#include "SpellAuras.h"
35#include "SpellHistory.h"
36#include "SpellMgr.h"
37#include "SpellPackets.h"
38#include "Unit.h"
39#include "Util.h"
40#include "World.h"
41#include "WorldSession.h"
42#include <sstream>
43
44#define PET_XP_FACTOR 0.05f
45
46Pet::Pet(Player* owner, PetType type) :
47 Guardian(nullptr, owner, true), m_removed(false),
48 m_petType(type), m_duration(0), m_loading(false), m_groupUpdateMask(0),
49 m_petSpecialization(0)
50{
52
54 if (type == HUNTER_PET)
56
58 {
61 }
62
63 m_name = "Pet";
65}
66
67Pet::~Pet() = default;
68
70{
72 if (!IsInWorld())
73 {
75 GetMap()->GetObjectsStore().Insert<Pet>(this);
78 if (ZoneScript* zoneScript = GetZoneScript() ? GetZoneScript() : GetInstanceScript())
79 zoneScript->OnCreatureCreate(this);
80 }
81
82 // Prevent stuck pets when zoning. Pets default to "follow" when added to world
83 // so we'll reset flags and let the AI handle things
85 {
88 GetCharmInfo()->SetIsAtStay(false);
91 }
92}
93
95{
97 if (IsInWorld())
98 {
101 GetMap()->GetObjectsStore().Remove<Pet>(this);
102 }
103}
104
105std::pair<PetStable::PetInfo const*, PetSaveMode> Pet::GetLoadPetInfo(PetStable const& stable, uint32 petEntry, uint32 petnumber, Optional<PetSaveMode> slot)
106{
107 if (petnumber)
108 {
109 // Known petnumber entry
110 for (std::size_t activeSlot = 0; activeSlot < stable.ActivePets.size(); ++activeSlot)
111 if (stable.ActivePets[activeSlot] && stable.ActivePets[activeSlot]->PetNumber == petnumber)
112 return { &stable.ActivePets[activeSlot].value(), PetSaveMode(PET_SAVE_FIRST_ACTIVE_SLOT + activeSlot) };
113
114 for (std::size_t stableSlot = 0; stableSlot < stable.StabledPets.size(); ++stableSlot)
115 if (stable.StabledPets[stableSlot] && stable.StabledPets[stableSlot]->PetNumber == petnumber)
116 return { &stable.StabledPets[stableSlot].value(), PetSaveMode(PET_SAVE_FIRST_STABLE_SLOT + stableSlot) };
117
118 for (PetStable::PetInfo const& pet : stable.UnslottedPets)
119 if (pet.PetNumber == petnumber)
120 return { &pet, PET_SAVE_NOT_IN_SLOT };
121 }
122 else if (slot)
123 {
124 // Current pet
125 if (slot == PET_SAVE_AS_CURRENT)
126 if (stable.GetCurrentActivePetIndex() && stable.ActivePets[*stable.GetCurrentActivePetIndex()])
127 return { &stable.ActivePets[*stable.GetCurrentActivePetIndex()].value(), PetSaveMode(*stable.GetCurrentActivePetIndex()) };
128
130 if (stable.ActivePets[*slot])
131 return { &stable.ActivePets[*slot].value(), *slot };
132
134 if (stable.StabledPets[*slot])
135 return { &stable.StabledPets[*slot].value(), *slot };
136 }
137 else if (petEntry)
138 {
139 // known petEntry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets)
140 for (PetStable::PetInfo const& pet : stable.UnslottedPets)
141 if (pet.CreatureId == petEntry)
142 return { &pet, PET_SAVE_NOT_IN_SLOT };
143 }
144 else
145 {
146 // Any current or other non-stabled pet (for hunter "call pet")
147 if (stable.ActivePets[0])
148 return { &stable.ActivePets[0].value(), PET_SAVE_FIRST_ACTIVE_SLOT };
149
150 if (!stable.UnslottedPets.empty())
151 return { &stable.UnslottedPets.front(), PET_SAVE_NOT_IN_SLOT };
152 }
153
154 return { nullptr, PET_SAVE_AS_DELETED };
155}
156
158{
159public:
160 enum
161 {
168
169 MAX
170 };
171
173 {
174 SetSize(MAX);
175
177
178 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_DECLINED_NAME);
179 stmt->setUInt64(0, ownerGuid);
180 stmt->setUInt32(1, petNumber);
182
183 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_AURA);
184 stmt->setUInt32(0, petNumber);
185 SetPreparedQuery(AURAS, stmt);
186
187 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_AURA_EFFECT);
188 stmt->setUInt32(0, petNumber);
190
191 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SPELL);
192 stmt->setUInt32(0, petNumber);
194
195 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SPELL_COOLDOWN);
196 stmt->setUInt32(0, petNumber);
198
199 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SPELL_CHARGES);
200 stmt->setUInt32(0, petNumber);
202 }
203};
204
205bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool current, Optional<PetSaveMode> forcedSlot /*= {}*/)
206{
207 m_loading = true;
208
209 PetStable* petStable = ASSERT_NOTNULL(owner->GetPetStable());
210
211 ObjectGuid::LowType ownerid = owner->GetGUID().GetCounter();
212 std::pair<PetStable::PetInfo const*, PetSaveMode> info = GetLoadPetInfo(*petStable, petEntry, petnumber, forcedSlot);
213 PetStable::PetInfo const* petInfo = info.first;
214 PetSaveMode slot = info.second;
215 if (!petInfo || (slot >= PET_SAVE_FIRST_STABLE_SLOT && slot < PET_SAVE_LAST_STABLE_SLOT))
216 {
217 m_loading = false;
218 return false;
219 }
220
221 // Don't try to reload the current pet
222 if (petStable->GetCurrentPet() && owner->GetPet() && petStable->GetCurrentPet()->PetNumber == petInfo->PetNumber)
223 return false;
224
225 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(petInfo->CreatedBySpellId, owner->GetMap()->GetDifficultyID());
226
227 bool isTemporarySummon = spellInfo && spellInfo->GetDuration() > 0;
228 if (current && isTemporarySummon)
229 return false;
230
231 if (petInfo->Type == HUNTER_PET)
232 {
233 CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petInfo->CreatureId);
234 if (!creatureInfo)
235 return false;
236
237 CreatureDifficulty const* creatureDifficulty = creatureInfo->GetDifficulty(DIFFICULTY_NONE);
238 if (!creatureDifficulty || !creatureInfo->IsTameable(owner->CanTameExoticPets(), creatureDifficulty))
239 return false;
240 }
241
242 if (current && owner->IsPetNeedBeTemporaryUnsummoned())
243 {
245 return false;
246 }
247
249
250 Map* map = owner->GetMap();
252
253 if (!Create(guid, map, petInfo->CreatureId, petInfo->PetNumber))
254 return false;
255
257
258 setPetType(petInfo->Type);
259 SetFaction(owner->GetFaction());
261
262 if (IsCritter())
263 {
264 float px, py, pz;
266 Relocate(px, py, pz, owner->GetOrientation());
267
268 if (!IsPositionValid())
269 {
270 TC_LOG_ERROR("entities.pet", "Pet{} not loaded. Suggested coordinates isn't valid (X: {} Y: {})",
272 return false;
273 }
274
275 map->AddToMap(ToCreature());
276 return true;
277 }
278
279 m_charmInfo->SetPetNumber(petInfo->PetNumber, IsPermanentPetFor(owner));
280
281 SetDisplayId(petInfo->DisplayId, true);
282 uint8 petlevel = petInfo->Level;
285 SetName(petInfo->Name);
286
287 switch (getPetType())
288 {
289 case SUMMON_PET:
290 petlevel = owner->GetLevel();
291 ReplaceAllUnitFlags(UNIT_FLAG_PLAYER_CONTROLLED); // this enables popup window (pet dismiss, cancel)
292 break;
293 case HUNTER_PET:
298 ReplaceAllUnitFlags(UNIT_FLAG_PLAYER_CONTROLLED); // this enables popup window (pet abandon, cancel)
299 break;
300 default:
301 if (!IsPetGhoul())
302 TC_LOG_ERROR("entities.pet", "Pet have incorrect type ({}) for pet loading.", getPetType());
303 break;
304 }
305
307 SetCreatorGUID(owner->GetGUID());
308
309 InitStatsForLevel(petlevel);
311
313
314 // Set pet's position after setting level, its size depends on it
315 float px, py, pz;
317 Relocate(px, py, pz, owner->GetOrientation());
318 if (!IsPositionValid())
319 {
320 TC_LOG_ERROR("entities.pet", "Pet {} not loaded. Suggested coordinates isn't valid (X: {} Y: {})",
322 return false;
323 }
324
325 SetReactState(petInfo->ReactState);
326 SetCanModifyStats(true);
327
328 if (getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current
330 else
331 {
332 uint32 savedhealth = petInfo->Health;
333 uint32 savedmana = petInfo->Mana;
334 if (!savedhealth && getPetType() == HUNTER_PET)
336 else
337 {
338 SetHealth(savedhealth);
339 SetPower(POWER_MANA, savedmana);
340 }
341 }
342
343 // set current pet as current
344 // 0-4=current
345 // PET_SAVE_NOT_IN_SLOT(-1) = not stable slot (summoning))
346 if (slot == PET_SAVE_NOT_IN_SLOT)
347 {
348 uint32 petInfoNumber = petInfo->PetNumber;
349 if (petStable->CurrentPetIndex)
350 owner->RemovePet(nullptr, PET_SAVE_NOT_IN_SLOT);
351
352 auto unslottedPetItr = std::find_if(petStable->UnslottedPets.begin(), petStable->UnslottedPets.end(), [&](PetStable::PetInfo const& unslottedPet)
353 {
354 return unslottedPet.PetNumber == petInfoNumber;
355 });
356 ASSERT(!petStable->CurrentPetIndex);
357 ASSERT(unslottedPetItr != petStable->UnslottedPets.end());
358
359 petStable->SetCurrentUnslottedPetIndex(std::distance(petStable->UnslottedPets.begin(), unslottedPetItr));
360 }
361 else if (PET_SAVE_FIRST_ACTIVE_SLOT <= slot && slot <= PET_SAVE_LAST_ACTIVE_SLOT)
362 {
363 auto activePetItr = std::find_if(petStable->ActivePets.begin(), petStable->ActivePets.end(), [&](Optional<PetStable::PetInfo> const& pet)
364 {
365 return pet && pet->PetNumber == petInfo->PetNumber;
366 });
367 ASSERT(activePetItr != petStable->ActivePets.end());
368
369 uint32 newPetIndex = std::distance(petStable->ActivePets.begin(), activePetItr);
370
371 petStable->SetCurrentActivePetIndex(newPetIndex);
372 }
373
374 owner->SetMinion(this, true);
375
376 if (!isTemporarySummon)
377 m_charmInfo->LoadPetActionBar(petInfo->ActionBar);
378
379 map->AddToMap(ToCreature());
380
381 //set last used pet number (for use in BG's)
383 owner->ToPlayer()->SetLastPetNumber(petInfo->PetNumber);
384
385 owner->GetSession()->AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(std::make_shared<PetLoadQueryHolder>(ownerid, petInfo->PetNumber)))
386 .AfterComplete([this, owner, session = owner->GetSession(), isTemporarySummon, current, lastSaveTime = petInfo->LastSaveTime, specializationId = petInfo->SpecializationId](SQLQueryHolderBase const& holder)
387 {
388 if (session->GetPlayer() != owner || owner->GetPet() != this)
389 return;
390
391 // passing previous checks ensure that 'this' is still valid
392 if (m_removed)
393 return;
394
395 uint32 timediff = uint32(GameTime::GetGameTime() - lastSaveTime);
396 _LoadAuras(holder.GetPreparedResult(PetLoadQueryHolder::AURAS), holder.GetPreparedResult(PetLoadQueryHolder::AURA_EFFECTS), timediff);
397
398 // load action bar, if data broken will fill later by default spells.
399 if (!isTemporarySummon)
400 {
401 _LoadSpells(holder.GetPreparedResult(PetLoadQueryHolder::SPELLS));
402 GetSpellHistory()->LoadFromDB<Pet>(holder.GetPreparedResult(PetLoadQueryHolder::COOLDOWNS), holder.GetPreparedResult(PetLoadQueryHolder::CHARGES));
403 LearnPetPassives();
404 InitLevelupSpellsForLevel();
405 if (GetMap()->IsBattleArena())
406 RemoveArenaAuras();
407
408 CastPetAuras(current);
409 }
410
411 TC_LOG_DEBUG("entities.pet", "New Pet has {}", GetGUID().ToString());
412
413 uint16 specId = specializationId;
414 if (ChrSpecializationEntry const* petSpec = sChrSpecializationStore.LookupEntry(specId))
415 specId = sDB2Manager.GetChrSpecializationByIndex(owner->HasAuraType(SPELL_AURA_OVERRIDE_PET_SPECS) ? PET_SPEC_OVERRIDE_CLASS_INDEX : 0, petSpec->OrderIndex)->ID;
416
417 SetSpecialization(specId);
418
419 // The SetSpecialization function will run these functions if the pet's spec is not 0
420 if (!GetSpecialization())
421 {
422 CleanupActionBar(); // remove unknown spells from action bar after load
423
424 owner->PetSpellInitialize();
425 }
426
428
429 if (getPetType() == HUNTER_PET)
430 {
432 {
433 m_declinedname = std::make_unique<DeclinedName>();
434 Field* fields = result->Fetch();
435 for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i)
436 m_declinedname->name[i] = fields[i].GetString();
437 }
438 }
439
440 if (owner->IsMounted())
442
443 // must be after SetMinion (owner guid check)
445 m_loading = false;
446 });
447
448 return true;
449}
450
452{
453 if (!GetEntry())
454 return;
455
456 // save only fully controlled creature
457 if (!isControlled())
458 return;
459
460 // not save not player pets
461 if (!GetOwnerGUID().IsPlayer())
462 return;
463
464 Player* owner = GetOwner();
465
466 // not save pet as current if another pet temporary unsummoned
468 owner->GetTemporaryUnsummonedPetNumber() != m_charmInfo->GetPetNumber())
469 {
470 // pet will lost anyway at restore temporary unsummoned
471 if (getPetType() == HUNTER_PET)
472 return;
473
474 // for warlock case
476 }
477
478 uint32 curhealth = GetHealth();
479 uint32 curmana = GetPower(POWER_MANA);
480
481 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
482 // save auras before possibly removing them
483 _SaveAuras(trans);
484
485 if (mode == PET_SAVE_AS_CURRENT)
486 if (Optional<uint32> activeSlot = owner->GetPetStable()->GetCurrentActivePetIndex())
487 mode = PetSaveMode(*activeSlot);
488
489 // stable and not in slot saves
490 if (mode < PET_SAVE_FIRST_ACTIVE_SLOT || mode >= PET_SAVE_LAST_ACTIVE_SLOT)
492
493 _SaveSpells(trans);
494 GetSpellHistory()->SaveToDB<Pet>(trans);
495 CharacterDatabase.CommitTransaction(trans);
496
497 // current/stable/not_in_slot
498 if (mode != PET_SAVE_AS_DELETED)
499 {
501 trans = CharacterDatabase.BeginTransaction();
502 // remove current data
503
505 stmt->setUInt32(0, m_charmInfo->GetPetNumber());
506 trans->Append(stmt);
507
508 // save pet
509 std::string actionBar = GenerateActionBarData();
510
511 ASSERT(owner->GetPetStable()->GetCurrentPet() && owner->GetPetStable()->GetCurrentPet()->PetNumber == m_charmInfo->GetPetNumber());
513
514 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PET);
515 stmt->setUInt32(0, m_charmInfo->GetPetNumber());
516 stmt->setUInt32(1, GetEntry());
517 stmt->setUInt64(2, ownerLowGUID);
518 stmt->setUInt32(3, GetNativeDisplayId());
519 stmt->setUInt8(4, GetLevel());
520 stmt->setUInt32(5, m_unitData->PetExperience);
521 stmt->setUInt8(6, owner->GetTemporaryPetReactState().value_or(GetReactState()));
523 stmt->setString(8, m_name);
525 stmt->setUInt32(10, curhealth);
526 stmt->setUInt32(11, curmana);
527 stmt->setString(12, actionBar);
528 stmt->setUInt32(13, GameTime::GetGameTime());
529 stmt->setUInt32(14, m_unitData->CreatedBySpell);
530 stmt->setUInt8(15, getPetType());
531 stmt->setUInt16(16, GetSpecialization());
532 trans->Append(stmt);
533
534 CharacterDatabase.CommitTransaction(trans);
535 }
536 // delete
537 else
538 {
540 DeleteFromDB(m_charmInfo->GetPetNumber());
541 }
542}
543
544void Pet::FillPetInfo(PetStable::PetInfo* petInfo, Optional<ReactStates> forcedReactState /*= {}*/) const
545{
546 petInfo->PetNumber = m_charmInfo->GetPetNumber();
547 petInfo->CreatureId = GetEntry();
548 petInfo->DisplayId = GetNativeDisplayId();
549 petInfo->Level = GetLevel();
550 petInfo->Experience = m_unitData->PetExperience;
551 petInfo->ReactState = forcedReactState.value_or(GetReactState());
552 petInfo->Name = GetName();
554 petInfo->Health = GetHealth();
555 petInfo->Mana = GetPower(POWER_MANA);
556 petInfo->ActionBar = GenerateActionBarData();
558 petInfo->CreatedBySpellId = m_unitData->CreatedBySpell;
559 petInfo->Type = getPetType();
561}
562
564{
565 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
566
568 stmt->setUInt32(0, petNumber);
569 trans->Append(stmt);
570
571 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME);
572 stmt->setUInt32(0, petNumber);
573 trans->Append(stmt);
574
575 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_AURA_EFFECTS);
576 stmt->setUInt32(0, petNumber);
577 trans->Append(stmt);
578
579 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_AURAS);
580 stmt->setUInt32(0, petNumber);
581 trans->Append(stmt);
582
583 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_SPELLS);
584 stmt->setUInt32(0, petNumber);
585 trans->Append(stmt);
586
587 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_SPELL_COOLDOWNS);
588 stmt->setUInt32(0, petNumber);
589 trans->Append(stmt);
590
591 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_SPELL_CHARGES);
592 stmt->setUInt32(0, petNumber);
593 trans->Append(stmt);
594
595 CharacterDatabase.CommitTransaction(trans);
596}
597
598void Pet::setDeathState(DeathState s) // overwrite virtual Creature::setDeathState and Unit::setDeathState
599{
601 if (getDeathState() == CORPSE)
602 {
603 if (getPetType() == HUNTER_PET)
604 {
605 // pet corpse non lootable and non skinnable
608
609 //SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
610 }
611 }
612 else if (getDeathState() == ALIVE)
613 {
614 //RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
615 CastPetAuras(true);
616 }
617}
618
620{
621 if (m_removed) // pet already removed, just wait in remove queue, no updates
622 return;
623
624 if (m_loading)
625 return;
626
627 switch (m_deathState)
628 {
629 case CORPSE:
630 {
632 {
633 Remove(PET_SAVE_NOT_IN_SLOT); //hunters' pets never get removed because of death, NEVER!
634 return;
635 }
636 break;
637 }
638 case ALIVE:
639 {
640 // unsummon pet that lost owner
641 Player* owner = GetOwner();
642 if ((!IsWithinDistInMap(owner, GetMap()->GetVisibilityRange()) && !isPossessed()) || (isControlled() && !owner->GetPetGUID()))
643 //if (!owner || (!IsWithinDistInMap(owner, GetMap()->GetVisibilityDistance()) && (owner->GetCharmGUID() && (owner->GetCharmGUID() != GetGUID()))) || (isControlled() && !owner->GetPetGUID()))
644 {
646 return;
647 }
648
649 if (isControlled())
650 {
651 if (owner->GetPetGUID() != GetGUID())
652 {
653 TC_LOG_ERROR("entities.pet", "Pet {} is not pet of owner {}, removed", GetEntry(), GetOwner()->GetName());
654 ASSERT(getPetType() != HUNTER_PET, "Unexpected unlinked pet found for owner %s", owner->GetSession()->GetPlayerInfo().c_str());
656 return;
657 }
658 }
659
660 if (m_duration > 0)
661 {
662 if (uint32(m_duration) > diff)
663 m_duration -= diff;
664 else
665 {
667 return;
668 }
669 }
670
671 //regenerate focus for hunter pets or energy for deathknight's ghoul
673 {
674 if (m_focusRegenTimer > diff)
675 m_focusRegenTimer -= diff;
676 else
677 {
678 switch (GetPowerType())
679 {
680 case POWER_FOCUS:
684
685 // Reset if large diff (lag) causes focus to get 'stuck'
688
689 break;
690
691 // in creature::update
692 //case POWER_ENERGY:
693 // Regenerate(POWER_ENERGY);
694 // m_regenTimer += CREATURE_REGEN_INTERVAL - diff;
695 // if (!m_regenTimer) ++m_regenTimer;
696 // break;
697 default:
699 break;
700 }
701 }
702 }
703 break;
704 }
705 default:
706 break;
707 }
708 Creature::Update(diff);
709}
710
711void Pet::Remove(PetSaveMode mode, bool returnreagent)
712{
713 GetOwner()->RemovePet(this, mode, returnreagent);
714}
715
717{
718 if (getPetType() != HUNTER_PET)
719 return;
720
721 if (xp < 1)
722 return;
723
724 if (!IsAlive())
725 return;
726
727 uint8 maxlevel = std::min((uint8)sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL), GetOwner()->GetLevel());
728 uint8 petlevel = GetLevel();
729
730 // If pet is detected to be at, or above(?) the players level, don't hand out XP
731 if (petlevel >= maxlevel)
732 return;
733
734 uint32 nextLvlXP = m_unitData->PetNextLevelExperience;
735 uint32 curXP = m_unitData->PetExperience;
736 uint32 newXP = curXP + xp;
737
738 // Check how much XP the pet should receive, and hand off have any left from previous levelups
739 while (newXP >= nextLvlXP && petlevel < maxlevel)
740 {
741 // Subtract newXP from amount needed for nextlevel, and give pet the level
742 newXP -= nextLvlXP;
743 ++petlevel;
744
745 GivePetLevel(petlevel);
746
747 nextLvlXP = m_unitData->PetNextLevelExperience;
748 }
749 // Not affected by special conditions - give it new XP
750 SetPetExperience(petlevel < maxlevel ? newXP : 0);
751}
752
754{
755 if (!level || level == GetLevel())
756 return;
757
758 if (getPetType() == HUNTER_PET)
759 {
762 }
763
764 InitStatsForLevel(level);
766}
767
769{
770 ASSERT(creature);
771
772 if (!CreateBaseAtTamed(creature->GetCreatureTemplate(), creature->GetMap()))
773 return false;
774
775 Relocate(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation());
776
777 if (!IsPositionValid())
778 {
779 TC_LOG_ERROR("entities.pet", "Pet {} not created base at creature. Suggested coordinates isn't valid (X: {} Y: {})",
781 return false;
782 }
783
784 CreatureTemplate const* cinfo = GetCreatureTemplate();
785 if (!cinfo)
786 {
787 TC_LOG_ERROR("entities.pet", "CreateBaseAtCreature() failed, creatureInfo is missing!");
788 return false;
789 }
790
791 SetDisplayId(creature->GetDisplayId());
792
793 if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family))
794 SetName(cFamily->Name[GetOwner()->GetSession()->GetSessionDbcLocale()]);
795 else
796 SetName(creature->GetNameForLocaleIdx(sObjectMgr->GetDBCLocaleIndex()));
797
798 return true;
799}
800
802{
803 if (!CreateBaseAtTamed(cinfo, owner->GetMap()))
804 return false;
805
806 if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family))
807 SetName(cFamily->Name[GetOwner()->GetSession()->GetSessionDbcLocale()]);
808
809 Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation());
810
811 return true;
812}
813
815{
816 TC_LOG_DEBUG("entities.pet", "Pet::CreateBaseForTamed");
817 if (!Create(map->GenerateLowGuid<HighGuid::Pet>(), map, cinfo->Entry, sObjectMgr->GeneratePetNumber()))
818 return false;
819
825
826 if (cinfo->type == CREATURE_TYPE_BEAST)
827 {
833 }
834
835 return true;
836}
837
840{
841 CreatureTemplate const* cinfo = GetCreatureTemplate();
842 ASSERT(cinfo);
843
844 SetLevel(petlevel);
845
846 //Determine pet type
847 PetType petType = MAX_PET_TYPE;
848 if (IsPet() && GetOwner()->GetTypeId() == TYPEID_PLAYER)
849 {
851 || GetOwner()->GetClass() == CLASS_SHAMAN // Fire Elemental
852 || GetOwner()->GetClass() == CLASS_DEATH_KNIGHT) // Risen Ghoul
853 {
854 petType = SUMMON_PET;
855 }
856 else if (GetOwner()->GetClass() == CLASS_HUNTER)
857 {
858 petType = HUNTER_PET;
860 }
861 else
862 {
863 TC_LOG_ERROR("entities.pet", "Unknown type pet {} is summoned by player class {}",
864 GetEntry(), GetOwner()->GetClass());
865 }
866 }
867
868 uint32 creature_ID = (petType == HUNTER_PET) ? 1 : cinfo->Entry;
869
871
872 SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
873
877
878 //scale
880
881 // Resistance
882 // Hunters pet should not inherit resistances from creature_template, they have separate auras for that
883 if (!IsHunterPet())
884 for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
886
887 Powers powerType = CalculateDisplayPowerType();
888
889 // Health, Mana or Power, Armor
890 PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(creature_ID, petlevel);
891 if (pInfo) // exist in DB
892 {
893 SetCreateHealth(pInfo->health);
894 SetCreateMana(pInfo->mana);
895
897
898 if (pInfo->armor > 0)
900
901 for (uint8 stat = 0; stat < MAX_STATS; ++stat)
902 SetCreateStat(Stats(stat), float(pInfo->stats[stat]));
903 }
904 else // not exist in DB, use some default fake data
905 {
906 // remove elite bonuses included in DB values
907 CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(petlevel, cinfo->unit_class);
909
910 CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
911 SetCreateHealth(std::max(sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, petlevel, creatureDifficulty->GetHealthScalingExpansion(), m_unitData->ContentTuningID, Classes(cinfo->unit_class), 0) * creatureDifficulty->HealthModifier * GetHealthMod(cinfo->Classification), 1.0f));
912 SetCreateMana(stats->BaseMana);
917 }
918
919 // Power
920 SetPowerType(powerType, true, true);
921
922 // Damage
924 switch (petType)
925 {
926 case SUMMON_PET:
927 {
928 // the damage bonus used for pets is either fire or shadow damage, whatever is higher
929 int32 fire = GetOwner()->ToPlayer()->m_activePlayerData->ModDamageDonePos[SPELL_SCHOOL_FIRE];
930 int32 shadow = GetOwner()->ToPlayer()->m_activePlayerData->ModDamageDonePos[SPELL_SCHOOL_SHADOW];
931 int32 val = (fire > shadow) ? fire : shadow;
932 if (val < 0)
933 val = 0;
934
935 SetBonusDamage(val * 0.15f);
936
937 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
938 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
939
940 //SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower));
941 break;
942 }
943 case HUNTER_PET:
944 {
945 ToPet()->SetPetNextLevelExperience(uint32(sObjectMgr->GetXPForLevel(petlevel)*PET_XP_FACTOR));
946 //these formula may not be correct; however, it is designed to be close to what it should be
947 //this makes dps 0.5 of pets level
948 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
949 //damage range is then petlevel / 2
950 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
951 //damage is increased afterwards as strength and pet scaling modify attack power
952 break;
953 }
954 default:
955 {
956 switch (GetEntry())
957 {
958 case 510: // mage Water Elemental
959 {
961 break;
962 }
963 case 1964: //force of nature
964 {
965 if (!pInfo)
966 SetCreateHealth(30 + 30*petlevel);
968 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 2.5f - (petlevel / 2) + bonusDmg));
969 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 2.5f + (petlevel / 2) + bonusDmg));
970 break;
971 }
972 case 15352: //earth elemental 36213
973 {
974 if (!pInfo)
975 SetCreateHealth(100 + 120*petlevel);
976 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
977 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
978 break;
979 }
980 case 15438: //fire elemental
981 {
982 if (!pInfo)
983 {
984 SetCreateHealth(40*petlevel);
985 SetCreateMana(28 + 10*petlevel);
986 }
988 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 4 - petlevel));
989 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 4 + petlevel));
990 break;
991 }
992 case 19668: // Shadowfiend
993 {
994 if (!pInfo)
995 {
996 SetCreateMana(28 + 10*petlevel);
997 SetCreateHealth(28 + 30*petlevel);
998 }
1000 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel) + bonus_dmg));
1001 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel) + bonus_dmg));
1002
1003 break;
1004 }
1005 case 19833: //Snake Trap - Venomous Snake
1006 {
1007 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel / 2) - 25));
1008 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel / 2) - 18));
1009 break;
1010 }
1011 case 19921: //Snake Trap - Viper
1012 {
1013 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel / 2 - 10));
1014 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel / 2));
1015 break;
1016 }
1017 case 29264: // Feral Spirit
1018 {
1019 if (!pInfo)
1020 SetCreateHealth(30*petlevel);
1021
1022 // wolf attack speed is 1.5s
1024
1025 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel)));
1026 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel)));
1027
1028 SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(GetOwner()->GetArmor()) * 0.35f); // Bonus Armor (35% of player armor)
1029 SetStatFlatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(GetOwner()->GetStat(STAT_STAMINA)) * 0.3f); // Bonus Stamina (30% of player stamina)
1030 if (!HasAura(58877))//prevent apply twice for the 2 wolves
1031 AddAura(58877, this);//Spirit Hunt, passive, Spirit Wolves' attacks heal them and their master for 150% of damage done.
1032 break;
1033 }
1034 case 31216: // Mirror Image
1035 {
1038 if (!pInfo)
1039 {
1040 SetCreateMana(28 + 30*petlevel);
1041 SetCreateHealth(28 + 10*petlevel);
1042 }
1043 break;
1044 }
1045 case 27829: // Ebon Gargoyle
1046 {
1047 if (!pInfo)
1048 {
1049 SetCreateMana(28 + 10*petlevel);
1050 SetCreateHealth(28 + 30*petlevel);
1051 }
1053 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
1054 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
1055 break;
1056 }
1057 case 28017: // Bloodworms
1058 {
1059 SetCreateHealth(4 * petlevel);
1061 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - 30 - (petlevel / 4)));
1062 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel - 30 + (petlevel / 4)));
1063 break;
1064 }
1065 default:
1066 {
1067 /* ToDo: Check what 5f5d2028 broke/fixed and how much of Creature::UpdateLevelDependantStats()
1068 * should be copied here (or moved to another method or if that function should be called here
1069 * or not just for this default case)
1070 */
1071 float basedamage = GetBaseDamageForLevel(petlevel);
1072
1073 float weaponBaseMinDamage = basedamage;
1074 float weaponBaseMaxDamage = basedamage * 1.5f;
1075
1076 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, weaponBaseMinDamage);
1077 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
1078 break;
1079 }
1080 }
1081 break;
1082 }
1083 }
1084
1086
1087 SetFullHealth();
1089 return true;
1090}
1091
1092bool Pet::HaveInDiet(ItemTemplate const* item) const
1093{
1094 if (!item->FoodType)
1095 return false;
1096
1097 CreatureTemplate const* cInfo = GetCreatureTemplate();
1098 if (!cInfo)
1099 return false;
1100
1101 CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->family);
1102 if (!cFamily)
1103 return false;
1104
1105 uint32 diet = cFamily->PetFoodMask;
1106 uint32 FoodMask = 1 << (item->FoodType-1);
1107 return (diet & FoodMask) != 0;
1108}
1109
1111{
1112 if (result)
1113 {
1114 do
1115 {
1116 Field* fields = result->Fetch();
1117
1118 addSpell(fields[0].GetUInt32(), ActiveStates(fields[1].GetUInt8()), PETSPELL_UNCHANGED);
1119 }
1120 while (result->NextRow());
1121 }
1122}
1123
1125{
1126 for (PetSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next)
1127 {
1128 ++next;
1129
1130 // prevent saving family passives to DB
1131 if (itr->second.type == PETSPELL_FAMILY)
1132 continue;
1133
1135
1136 switch (itr->second.state)
1137 {
1138 case PETSPELL_REMOVED:
1139 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_SPELL_BY_SPELL);
1140 stmt->setUInt32(0, m_charmInfo->GetPetNumber());
1141 stmt->setUInt32(1, itr->first);
1142 trans->Append(stmt);
1143
1144 m_spells.erase(itr);
1145 continue;
1146 case PETSPELL_CHANGED:
1147 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_SPELL_BY_SPELL);
1148 stmt->setUInt32(0, m_charmInfo->GetPetNumber());
1149 stmt->setUInt32(1, itr->first);
1150 trans->Append(stmt);
1151
1152 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PET_SPELL);
1153 stmt->setUInt32(0, m_charmInfo->GetPetNumber());
1154 stmt->setUInt32(1, itr->first);
1155 stmt->setUInt8(2, itr->second.active);
1156 trans->Append(stmt);
1157
1158 break;
1159 case PETSPELL_NEW:
1160 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PET_SPELL);
1161 stmt->setUInt32(0, m_charmInfo->GetPetNumber());
1162 stmt->setUInt32(1, itr->first);
1163 stmt->setUInt8(2, itr->second.active);
1164 trans->Append(stmt);
1165 break;
1166 case PETSPELL_UNCHANGED:
1167 continue;
1168 }
1169 itr->second.state = PETSPELL_UNCHANGED;
1170 }
1171}
1172
1173void Pet::_LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effectResult, uint32 timediff)
1174{
1175 TC_LOG_DEBUG("entities.pet", "Loading auras for pet {}", GetGUID().ToString());
1176
1177 ObjectGuid casterGuid, itemGuid;
1178 std::map<AuraKey, AuraLoadEffectInfo> effectInfo;
1179
1180 /*
1181 0 1 2 3 4 5
1182 SELECT casterGuid, spell, effectMask, effectIndex, amount, baseAmount FROM pet_aura_effect WHERE guid = ?
1183 */
1184 if (effectResult)
1185 {
1186 do
1187 {
1188 Field* fields = effectResult->Fetch();
1189 uint32 effectIndex = fields[3].GetUInt8();
1190 if (effectIndex < MAX_SPELL_EFFECTS)
1191 {
1192 std::span<uint8 const> rawGuidBytes = fields[0].GetBinaryView();
1193 if (rawGuidBytes.size() != ObjectGuid::BytesSize)
1194 continue;
1195
1196 casterGuid.SetRawValue(rawGuidBytes);
1197 if (casterGuid.IsEmpty())
1198 casterGuid = GetGUID();
1199
1200 AuraKey key{ casterGuid, itemGuid, fields[1].GetUInt32(), fields[2].GetUInt32() };
1201 AuraLoadEffectInfo& info = effectInfo[key];
1202 info.Amounts[effectIndex] = fields[4].GetDouble();
1203 info.BaseAmounts[effectIndex] = fields[5].GetDouble();
1204 }
1205 } while (effectResult->NextRow());
1206 }
1207
1208 /*
1209 0 1 2 3 4 5 6 7 8
1210 SELECT casterGuid, spell, effectMask, recalculateMask, difficulty, stackCount, maxDuration, remainTime, remainCharges FROM pet_aura WHERE guid = ?
1211 */
1212 if (auraResult)
1213 {
1214 do
1215 {
1216 Field* fields = auraResult->Fetch();
1217 // NULL guid stored - pet is the caster of the spell - see Pet::_SaveAuras
1218 std::span<uint8 const> rawGuidBytes = fields[0].GetBinaryView();
1219 if (rawGuidBytes.size() != ObjectGuid::BytesSize)
1220 continue;
1221
1222 casterGuid.SetRawValue(rawGuidBytes);
1223 if (casterGuid.IsEmpty())
1224 casterGuid = GetGUID();
1225
1226 AuraKey key{ casterGuid, itemGuid, fields[1].GetUInt32(), fields[2].GetUInt32() };
1227 uint32 recalculateMask = fields[3].GetUInt32();
1228 Difficulty difficulty = Difficulty(fields[4].GetUInt8());
1229 uint8 stackCount = fields[5].GetUInt8();
1230 int32 maxDuration = fields[6].GetInt32();
1231 int32 remainTime = fields[7].GetInt32();
1232 uint8 remainCharges = fields[8].GetUInt8();
1233
1234 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(key.SpellId, difficulty);
1235 if (!spellInfo)
1236 {
1237 TC_LOG_ERROR("entities.pet", "Pet::_LoadAuras: Unknown aura (spellid {}), ignore.", key.SpellId);
1238 continue;
1239 }
1240
1241 if (difficulty != DIFFICULTY_NONE && !sDifficultyStore.LookupEntry(difficulty))
1242 {
1243 TC_LOG_ERROR("entities.pet", "Pet::_LoadAuras: Unknown difficulty {} (spellid {}), ignore.", uint32(difficulty), key.SpellId);
1244 continue;
1245 }
1246
1247 // negative effects should continue counting down after logout
1248 if (remainTime != -1 && (!spellInfo->IsPositive() || spellInfo->HasAttribute(SPELL_ATTR4_AURA_EXPIRES_OFFLINE)))
1249 {
1250 if (remainTime/IN_MILLISECONDS <= int32(timediff))
1251 continue;
1252
1253 remainTime -= timediff*IN_MILLISECONDS;
1254 }
1255
1256 // prevent wrong values of remainCharges
1257 if (spellInfo->ProcCharges)
1258 {
1259 // we have no control over the order of applying auras and modifiers allow auras
1260 // to have more charges than value in SpellInfo
1261 if (remainCharges <= 0/* || remainCharges > spellproto->procCharges*/)
1262 remainCharges = spellInfo->ProcCharges;
1263 }
1264 else
1265 remainCharges = 0;
1266
1267 AuraLoadEffectInfo& info = effectInfo[key];
1268 ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellInfo->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>());
1269 AuraCreateInfo createInfo(castId, spellInfo, difficulty, key.EffectMask, this);
1270 createInfo
1271 .SetCasterGUID(casterGuid)
1272 .SetBaseAmount(info.BaseAmounts.data())
1273 .SetStackAmount(stackCount);
1274
1275 if (Aura* aura = Aura::TryCreate(createInfo))
1276 {
1277 if (!aura->CanBeSaved())
1278 {
1279 aura->Remove();
1280 continue;
1281 }
1282
1283 aura->SetLoadedState(maxDuration, remainTime, remainCharges, recalculateMask, info.Amounts.data());
1284 aura->ApplyForTargets();
1285 TC_LOG_DEBUG("entities.pet", "Added aura spellid {}, effectmask {}", spellInfo->Id, key.EffectMask);
1286 }
1287 }
1288 while (auraResult->NextRow());
1289 }
1290}
1291
1293{
1295 stmt->setUInt32(0, m_charmInfo->GetPetNumber());
1296 trans->Append(stmt);
1297
1298 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_AURAS);
1299 stmt->setUInt32(0, m_charmInfo->GetPetNumber());
1300 trans->Append(stmt);
1301
1302 uint8 index;
1303 for (AuraMap::const_iterator itr = m_ownedAuras.begin(); itr != m_ownedAuras.end(); ++itr)
1304 {
1305 // check if the aura has to be saved
1306 if (!itr->second->CanBeSaved() || IsPetAura(itr->second))
1307 continue;
1308
1309 Aura* aura = itr->second;
1310 uint32 recalculateMask = 0;
1311 AuraKey key = aura->GenerateKey(recalculateMask);
1312
1313 // don't save guid of caster in case we are caster of the spell - guid for pet is generated every pet load, so it won't match saved guid anyways
1314 if (key.Caster == GetGUID())
1315 key.Caster.Clear();
1316
1317 index = 0;
1318 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PET_AURA);
1319 stmt->setUInt32(index++, m_charmInfo->GetPetNumber());
1320 stmt->setBinary(index++, key.Caster.GetRawValue());
1321 stmt->setUInt32(index++, key.SpellId);
1322 stmt->setUInt32(index++, key.EffectMask);
1323 stmt->setUInt32(index++, recalculateMask);
1324 stmt->setUInt8(index++, aura->GetCastDifficulty());
1325 stmt->setUInt8(index++, aura->GetStackAmount());
1326 stmt->setInt32(index++, aura->GetMaxDuration());
1327 stmt->setInt32(index++, aura->GetDuration());
1328 stmt->setUInt8(index++, aura->GetCharges());
1329 trans->Append(stmt);
1330
1331 for (AuraEffect const* effect : aura->GetAuraEffects())
1332 {
1333 index = 0;
1334 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PET_AURA_EFFECT);
1335 stmt->setUInt32(index++, m_charmInfo->GetPetNumber());
1336 stmt->setBinary(index++, key.Caster.GetRawValue());
1337 stmt->setUInt32(index++, key.SpellId);
1338 stmt->setUInt32(index++, key.EffectMask);
1339 stmt->setUInt8(index++, effect->GetEffIndex());
1340 stmt->setDouble(index++, effect->GetAmount());
1341 stmt->setDouble(index++, effect->GetBaseAmount());
1342 trans->Append(stmt);
1343 }
1344 }
1345}
1346
1347bool Pet::addSpell(uint32 spellId, ActiveStates active /*= ACT_DECIDE*/, PetSpellState state /*= PETSPELL_NEW*/, PetSpellType type /*= PETSPELL_NORMAL*/)
1348{
1349 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
1350 if (!spellInfo)
1351 {
1352 // do pet spell book cleanup
1353 if (state == PETSPELL_UNCHANGED) // spell load case
1354 {
1355 TC_LOG_ERROR("entities.pet", "Pet::addSpell: Non-existed in SpellStore spell #{} request, deleting for all pets in `pet_spell`.", spellId);
1356
1358
1359 stmt->setUInt32(0, spellId);
1360
1361 CharacterDatabase.Execute(stmt);
1362 }
1363 else
1364 TC_LOG_ERROR("entities.pet", "Pet::addSpell: Non-existed in SpellStore spell #{} request.", spellId);
1365
1366 return false;
1367 }
1368
1369 PetSpellMap::iterator itr = m_spells.find(spellId);
1370 if (itr != m_spells.end())
1371 {
1372 if (itr->second.state == PETSPELL_REMOVED)
1373 state = PETSPELL_CHANGED;
1374 else
1375 {
1376 if (state == PETSPELL_UNCHANGED && itr->second.state != PETSPELL_UNCHANGED)
1377 {
1378 // can be in case spell loading but learned at some previous spell loading
1379 itr->second.state = PETSPELL_UNCHANGED;
1380
1381 if (active == ACT_ENABLED)
1382 ToggleAutocast(spellInfo, true);
1383 else if (active == ACT_DISABLED)
1384 ToggleAutocast(spellInfo, false);
1385 }
1386
1387 return false;
1388 }
1389 }
1390
1391 PetSpell newspell;
1392 newspell.state = state;
1393 newspell.type = type;
1394
1395 if (active == ACT_DECIDE) // active was not used before, so we save it's autocast/passive state here
1396 {
1397 if (!spellInfo->IsAutocastable())
1398 newspell.active = ACT_PASSIVE;
1399 else if (spellInfo->IsAutocastEnabledByDefault())
1400 newspell.active = ACT_ENABLED;
1401 else
1402 newspell.active = ACT_DISABLED;
1403 }
1404 else
1405 newspell.active = active;
1406
1407 // talent: unlearn all other talent ranks (high and low)
1408 if (spellInfo->IsRanked())
1409 {
1410 for (PetSpellMap::const_iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2)
1411 {
1412 if (itr2->second.state == PETSPELL_REMOVED)
1413 continue;
1414
1415 SpellInfo const* oldRankSpellInfo = sSpellMgr->GetSpellInfo(itr2->first, DIFFICULTY_NONE);
1416
1417 if (!oldRankSpellInfo)
1418 continue;
1419
1420 if (spellInfo->IsDifferentRankOf(oldRankSpellInfo))
1421 {
1422 // replace by new high rank
1423 if (spellInfo->IsHighRankOf(oldRankSpellInfo))
1424 {
1425 newspell.active = itr2->second.active;
1426
1427 if (newspell.active == ACT_ENABLED)
1428 ToggleAutocast(oldRankSpellInfo, false);
1429
1430 unlearnSpell(itr2->first, false, false);
1431 break;
1432 }
1433 // ignore new lesser rank
1434 else
1435 return false;
1436 }
1437 }
1438 }
1439
1440 m_spells[spellId] = newspell;
1441
1442 if (spellInfo->IsPassive() && (!spellInfo->CasterAuraState || HasAuraState(AuraStateType(spellInfo->CasterAuraState))))
1443 CastSpell(this, spellId, true);
1444 else
1445 m_charmInfo->AddSpellToActionBar(spellInfo);
1446
1447 if (newspell.active == ACT_ENABLED)
1448 ToggleAutocast(spellInfo, true);
1449
1450 return true;
1451}
1452
1454{
1455 // prevent duplicated entires in spell book
1456 if (!addSpell(spell_id))
1457 return false;
1458
1459 if (!m_loading)
1460 {
1462 packet.Spells.push_back(spell_id);
1463 GetOwner()->SendDirectMessage(packet.Write());
1465 }
1466 return true;
1467}
1468
1469void Pet::learnSpells(std::vector<uint32> const& spellIds)
1470{
1472
1473 for (uint32 spell : spellIds)
1474 {
1475 if (!addSpell(spell))
1476 continue;
1477
1478 packet.Spells.push_back(spell);
1479 }
1480
1481 if (!m_loading)
1482 GetOwner()->GetSession()->SendPacket(packet.Write());
1483}
1484
1486{
1487 uint8 level = GetLevel();
1488
1489 if (PetLevelupSpellSet const* levelupSpells = GetCreatureTemplate()->family ? sSpellMgr->GetPetLevelupSpellList(GetCreatureTemplate()->family) : nullptr)
1490 {
1491 // PetLevelupSpellSet ordered by levels, process in reversed order
1492 for (PetLevelupSpellSet::const_reverse_iterator itr = levelupSpells->rbegin(); itr != levelupSpells->rend(); ++itr)
1493 {
1494 // will called first if level down
1495 if (itr->first > level)
1496 unlearnSpell(itr->second, true); // will learn prev rank if any
1497 // will called if level up
1498 else
1499 learnSpell(itr->second); // will unlearn prev rank if any
1500 }
1501 }
1502
1503 // default spells (can be not learned if pet level (as owner level decrease result for example) less first possible in normal game)
1504 if (PetDefaultSpellsEntry const* defSpells = sSpellMgr->GetPetDefaultSpellsEntry(int32(GetEntry())))
1505 {
1506 for (uint32 spellId : defSpells->spellid)
1507 {
1508 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
1509 if (!spellInfo)
1510 continue;
1511
1512 // will called first if level down
1513 if (spellInfo->SpellLevel > level)
1514 unlearnSpell(spellInfo->Id, true);
1515 // will called if level up
1516 else
1517 learnSpell(spellInfo->Id);
1518 }
1519 }
1520}
1521
1522bool Pet::unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab)
1523{
1524 if (removeSpell(spell_id, learn_prev, clear_ab))
1525 {
1526 if (!m_loading)
1527 {
1529 packet.Spells.push_back(spell_id);
1530 GetOwner()->SendDirectMessage(packet.Write());
1531 }
1532 return true;
1533 }
1534 return false;
1535}
1536
1537void Pet::unlearnSpells(std::vector<uint32> const& spellIds, bool learn_prev, bool clear_ab)
1538{
1540
1541 for (uint32 spell : spellIds)
1542 {
1543 if (!removeSpell(spell, learn_prev, clear_ab))
1544 continue;
1545
1546 packet.Spells.push_back(spell);
1547 }
1548
1549 if (!m_loading)
1550 GetOwner()->GetSession()->SendPacket(packet.Write());
1551}
1552
1553bool Pet::removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab)
1554{
1555 PetSpellMap::iterator itr = m_spells.find(spell_id);
1556 if (itr == m_spells.end())
1557 return false;
1558
1559 if (itr->second.state == PETSPELL_REMOVED)
1560 return false;
1561
1562 if (itr->second.state == PETSPELL_NEW)
1563 m_spells.erase(itr);
1564 else
1565 itr->second.state = PETSPELL_REMOVED;
1566
1567 RemoveAurasDueToSpell(spell_id);
1568
1569 if (learn_prev)
1570 {
1571 if (uint32 prev_id = sSpellMgr->GetPrevSpellInChain (spell_id))
1572 learnSpell(prev_id);
1573 else
1574 learn_prev = false;
1575 }
1576
1577 // if remove last rank or non-ranked then update action bar at server and client if need
1578 if (clear_ab && !learn_prev && m_charmInfo->RemoveSpellFromActionBar(spell_id))
1579 {
1580 if (!m_loading)
1581 GetOwner()->PetSpellInitialize(); // need update action bar for last removed rank
1582 }
1583
1584 return true;
1585}
1586
1588{
1589 for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
1590 if (UnitActionBarEntry const* ab = m_charmInfo->GetActionBarEntry(i))
1591 if (ab->GetAction() && ab->IsActionBarForSpell())
1592 {
1593 if (!HasSpell(ab->GetAction()))
1594 m_charmInfo->SetActionBar(i, 0, ACT_PASSIVE);
1595 else if (ab->GetType() == ACT_ENABLED)
1596 {
1597 if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(ab->GetAction(), DIFFICULTY_NONE))
1598 ToggleAutocast(spellInfo, true);
1599 }
1600 }
1601}
1602
1604{
1605 m_charmInfo->InitPetActionBar();
1606 m_spells.clear();
1607
1610
1611 CastPetAuras(false);
1612}
1613
1614void Pet::ToggleAutocast(SpellInfo const* spellInfo, bool apply)
1615{
1616 ASSERT(spellInfo);
1617
1618 if (!spellInfo->IsAutocastable())
1619 return;
1620
1621 PetSpellMap::iterator itr = m_spells.find(spellInfo->Id);
1622 if (itr == m_spells.end())
1623 return;
1624
1625 auto autospellItr = std::find(m_autospells.begin(), m_autospells.end(), spellInfo->Id);
1626
1627 if (apply)
1628 {
1629 if (autospellItr == m_autospells.end())
1630 {
1631 m_autospells.push_back(spellInfo->Id);
1632
1633 if (itr->second.active != ACT_ENABLED)
1634 {
1635 itr->second.active = ACT_ENABLED;
1636 if (itr->second.state != PETSPELL_NEW)
1637 itr->second.state = PETSPELL_CHANGED;
1638 }
1639 }
1640 }
1641 else
1642 {
1643 if (autospellItr != m_autospells.end())
1644 {
1645 m_autospells.erase(autospellItr);
1646
1647 if (itr->second.active != ACT_DISABLED)
1648 {
1649 itr->second.active = ACT_DISABLED;
1650 if (itr->second.state != PETSPELL_NEW)
1651 itr->second.state = PETSPELL_CHANGED;
1652 }
1653 }
1654 }
1655}
1656
1658{
1659 switch (getPetType())
1660 {
1661 case SUMMON_PET:
1662 switch (owner->GetClass())
1663 {
1664 case CLASS_WARLOCK:
1666 case CLASS_DEATH_KNIGHT:
1668 case CLASS_MAGE:
1670 default:
1671 return false;
1672 }
1673 case HUNTER_PET:
1674 return true;
1675 default:
1676 return false;
1677 }
1678}
1679
1680bool Pet::Create(ObjectGuid::LowType guidlow, Map* map, uint32 Entry, uint32 /*petId*/)
1681{
1682 ASSERT(map);
1683 SetMap(map);
1684
1685 // TODO: counter should be constructed as (summon_count << 32) | petNumber
1686 _Create(ObjectGuid::Create<HighGuid::Pet>(map->GetId(), Entry, guidlow));
1687
1688 m_spawnId = guidlow;
1690
1691 if (!InitEntry(Entry))
1692 return false;
1693
1694 // Force regen flag for player pets, just like we do for players themselves
1697
1699
1700 return true;
1701}
1702
1703bool Pet::HasSpell(uint32 spell) const
1704{
1705 PetSpellMap::const_iterator itr = m_spells.find(spell);
1706 return itr != m_spells.end() && itr->second.state != PETSPELL_REMOVED;
1707}
1708
1709// Get all passive spells in our skill line
1711{
1712 CreatureTemplate const* cInfo = GetCreatureTemplate();
1713 if (!cInfo)
1714 return;
1715
1716 CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->family);
1717 if (!cFamily)
1718 return;
1719
1720 PetFamilySpellsStore::const_iterator petStore = sPetFamilySpellsStore.find(cInfo->family);
1721 if (petStore != sPetFamilySpellsStore.end())
1722 {
1723 // For general hunter pets skill 270
1724 // Passive 01~10, Passive 00 (20782, not used), Ferocious Inspiration (34457)
1725 // Scale 01~03 (34902~34904, bonus from owner, not used)
1726 for (uint32 spellId : petStore->second)
1728 }
1729}
1730
1731void Pet::CastPetAuras(bool current)
1732{
1733 Player* owner = GetOwner();
1734
1735 if (!IsPermanentPetFor(owner))
1736 return;
1737
1738 for (auto itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end();)
1739 {
1740 PetAura const* pa = *itr;
1741 ++itr;
1742
1743 if (!current && pa->IsRemovedOnChangePet())
1744 owner->RemovePetAura(pa);
1745 else
1746 CastPetAura(pa);
1747 }
1748}
1749
1750void Pet::CastPetAura(PetAura const* aura)
1751{
1752 uint32 auraId = aura->GetAura(GetEntry());
1753 if (!auraId)
1754 return;
1755
1756 CastSpellExtraArgs args;
1758
1759 if (auraId == 35696) // Demonic Knowledge
1761
1762 CastSpell(this, auraId, args);
1763}
1764
1765bool Pet::IsPetAura(Aura const* aura)
1766{
1767 Player* owner = GetOwner();
1768
1769 // if the owner has that pet aura, return true
1770 for (PetAura const* petAura : owner->m_petAuras)
1771 if (petAura->GetAura(GetEntry()) == aura->GetId())
1772 return true;
1773
1774 return false;
1775}
1776
1778{
1779 learnSpell(spellid);
1780
1781 if (uint32 next = sSpellMgr->GetNextSpellInChain(spellid))
1782 learnSpellHighRank(next);
1783}
1784
1786{
1787 Player* owner = GetOwner();
1788
1789 switch (getPetType())
1790 {
1791 // always same level
1792 case SUMMON_PET:
1793 case HUNTER_PET:
1794 GivePetLevel(owner->GetLevel());
1795 break;
1796 default:
1797 break;
1798 }
1799}
1800
1802{
1803 return Minion::GetOwner()->ToPlayer();
1804}
1805
1807{
1808 CreatureFamilyEntry const* creatureFamily = sCreatureFamilyStore.LookupEntry(GetCreatureTemplate()->family);
1809 if (creatureFamily && creatureFamily->MinScale > 0.0f && getPetType() == HUNTER_PET)
1810 {
1811 float scale;
1812 if (GetLevel() >= creatureFamily->MaxScaleLevel)
1813 scale = creatureFamily->MaxScale;
1814 else if (GetLevel() <= creatureFamily->MinScaleLevel)
1815 scale = creatureFamily->MinScale;
1816 else
1817 scale = creatureFamily->MinScale + float(GetLevel() - creatureFamily->MinScaleLevel) / creatureFamily->MaxScaleLevel * (creatureFamily->MaxScale - creatureFamily->MinScale);
1818
1819 return scale;
1820 }
1821
1823}
1824
1825void Pet::SetDisplayId(uint32 modelId, bool setNative /*= false*/)
1826{
1827 Guardian::SetDisplayId(modelId, setNative);
1828
1829 if (!isControlled())
1830 return;
1831
1833}
1834
1836{
1837 if (GetOwner()->GetGroup())
1838 {
1839 m_groupUpdateMask |= flag;
1841 }
1842}
1843
1850
1852{
1853 std::vector<uint32> learnedSpells;
1854
1855 if (std::vector<SpecializationSpellsEntry const*> const* specSpells = sDB2Manager.GetSpecializationSpells(m_petSpecialization))
1856 {
1857 for (size_t j = 0; j < specSpells->size(); ++j)
1858 {
1859 SpecializationSpellsEntry const* specSpell = specSpells->at(j);
1860 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(specSpell->SpellID, DIFFICULTY_NONE);
1861 if (!spellInfo || spellInfo->SpellLevel > GetLevel())
1862 continue;
1863
1864 learnedSpells.push_back(specSpell->SpellID);
1865 }
1866 }
1867
1868 learnSpells(learnedSpells);
1869}
1870
1871void Pet::RemoveSpecializationSpells(bool clearActionBar)
1872{
1873 std::vector<uint32> unlearnedSpells;
1874
1875 for (uint32 i = 0; i < MAX_SPECIALIZATIONS; ++i)
1876 {
1877 if (ChrSpecializationEntry const* specialization = sDB2Manager.GetChrSpecializationByIndex(0, i))
1878 {
1879 if (std::vector<SpecializationSpellsEntry const*> const* specSpells = sDB2Manager.GetSpecializationSpells(specialization->ID))
1880 {
1881 for (size_t j = 0; j < specSpells->size(); ++j)
1882 {
1883 SpecializationSpellsEntry const* specSpell = specSpells->at(j);
1884 unlearnedSpells.push_back(specSpell->SpellID);
1885 }
1886 }
1887 }
1888
1889 if (ChrSpecializationEntry const* specialization = sDB2Manager.GetChrSpecializationByIndex(PET_SPEC_OVERRIDE_CLASS_INDEX, i))
1890 {
1891 if (std::vector<SpecializationSpellsEntry const*> const* specSpells = sDB2Manager.GetSpecializationSpells(specialization->ID))
1892 {
1893 for (size_t j = 0; j < specSpells->size(); ++j)
1894 {
1895 SpecializationSpellsEntry const* specSpell = specSpells->at(j);
1896 unlearnedSpells.push_back(specSpell->SpellID);
1897 }
1898 }
1899 }
1900 }
1901
1902 unlearnSpells(unlearnedSpells, true, clearActionBar);
1903}
1904
1906{
1907 if (m_petSpecialization == spec)
1908 return;
1909
1910 // remove all the old spec's specalization spells, set the new spec, then add the new spec's spells
1911 // clearActionBars is false because we'll be updating the pet actionbar later so we don't have to do it now
1913 if (!sChrSpecializationStore.LookupEntry(spec))
1914 {
1916 return;
1917 }
1918
1919 m_petSpecialization = spec;
1921
1922 // resend SMSG_PET_SPELLS_MESSAGE to remove old specialization spells from the pet action bar
1925
1926 WorldPackets::Pet::SetPetSpecialization setPetSpecialization;
1927 setPetSpecialization.SpecID = m_petSpecialization;
1928 GetOwner()->GetSession()->SendPacket(setPetSpecialization.Write());
1929}
1930
1932{
1933 std::ostringstream ss;
1934
1936 {
1937 ss << uint32(m_charmInfo->GetActionBarEntry(i)->GetType()) << ' '
1938 << uint32(m_charmInfo->GetActionBarEntry(i)->GetAction()) << ' ';
1939 }
1940
1941 return ss.str();
1942}
1943
1944std::string Pet::GetDebugInfo() const
1945{
1946 std::stringstream sstr;
1947 sstr << Guardian::GetDebugInfo() << "\n"
1948 << std::boolalpha
1949 << "PetType: " << std::to_string(getPetType()) << " "
1950 << "PetNumber: " << m_charmInfo->GetPetNumber();
1951 return sstr.str();
1952}
@ CHAR_SEL_PET_AURA
@ CHAR_DEL_PET_SPELL_CHARGES
@ CHAR_INS_PET_AURA_EFFECT
@ CHAR_DEL_INVALID_PET_SPELL
@ CHAR_DEL_PET_SPELLS
@ CHAR_INS_PET
@ CHAR_INS_PET_SPELL
@ CHAR_DEL_CHAR_PET_BY_ID
@ CHAR_DEL_PET_AURAS
@ CHAR_SEL_PET_DECLINED_NAME
@ CHAR_SEL_PET_AURA_EFFECT
@ CHAR_DEL_PET_SPELL_BY_SPELL
@ CHAR_DEL_PET_SPELL_COOLDOWNS
@ CHAR_SEL_PET_SPELL
@ CHAR_SEL_PET_SPELL_COOLDOWN
@ CHAR_SEL_PET_SPELL_CHARGES
@ CHAR_DEL_PET_AURA_EFFECTS
@ CHAR_INS_PET_AURA
@ CHAR_DEL_CHAR_PET_DECLINEDNAME
#define MAX_UNIT_ACTION_BAR_INDEX
Definition CharmInfo.h:85
@ ACTION_BAR_INDEX_END
Definition CharmInfo.h:82
@ ACTION_BAR_INDEX_START
Definition CharmInfo.h:79
@ IN_MILLISECONDS
Definition Common.h:38
const uint32 PET_FOCUS_REGEN_INTERVAL
DB2Storage< DifficultyEntry > sDifficultyStore("Difficulty.db2", &DifficultyLoadInfo::Instance)
DB2Storage< CreatureFamilyEntry > sCreatureFamilyStore("CreatureFamily.db2", &CreatureFamilyLoadInfo::Instance)
DB2Storage< ChrSpecializationEntry > sChrSpecializationStore("ChrSpecialization.db2", &ChrSpecializationLoadInfo::Instance)
#define sDB2Manager
Definition DB2Stores.h:569
Difficulty
Definition DBCEnums.h:932
@ DIFFICULTY_NONE
Definition DBCEnums.h:933
#define MAX_SPELL_EFFECTS
Definition DBCEnums.h:2430
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:82
#define ASSERT
Definition Errors.h:80
@ GROUP_UPDATE_FLAG_PET
Definition Group.h:138
@ GROUP_UPDATE_PET_FULL
Definition Group.h:159
@ GROUP_UPDATE_FLAG_PET_MODEL_ID
Definition Group.h:154
@ GROUP_UPDATE_FLAG_PET_NONE
Definition Group.h:151
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:181
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
#define sObjectMgr
Definition ObjectMgr.h:1885
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
PetSpellState
Definition PetDefines.h:69
@ PETSPELL_NEW
Definition PetDefines.h:72
@ PETSPELL_UNCHANGED
Definition PetDefines.h:70
@ PETSPELL_CHANGED
Definition PetDefines.h:71
@ PETSPELL_REMOVED
Definition PetDefines.h:73
#define PET_FOLLOW_DIST
Definition PetDefines.h:98
PetType
Definition PetDefines.h:30
@ SUMMON_PET
Definition PetDefines.h:31
@ HUNTER_PET
Definition PetDefines.h:32
@ MAX_PET_TYPE
Definition PetDefines.h:33
PetSpellType
Definition PetDefines.h:77
@ PETSPELL_FAMILY
Definition PetDefines.h:79
PetSaveMode
Definition PetDefines.h:41
@ PET_SAVE_FIRST_STABLE_SLOT
Definition PetDefines.h:46
@ PET_SAVE_LAST_STABLE_SLOT
Definition PetDefines.h:47
@ PET_SAVE_LAST_ACTIVE_SLOT
Definition PetDefines.h:45
@ PET_SAVE_FIRST_ACTIVE_SLOT
Definition PetDefines.h:44
@ PET_SAVE_AS_DELETED
Definition PetDefines.h:42
@ PET_SAVE_NOT_IN_SLOT
Definition PetDefines.h:48
@ PET_SAVE_AS_CURRENT
Definition PetDefines.h:43
#define PET_XP_FACTOR
Definition Pet.cpp:44
#define MAX_STATS
Classes
@ CLASS_HUNTER
@ CLASS_SHAMAN
@ CLASS_WARRIOR
@ CLASS_WARLOCK
@ CLASS_MAGE
@ CLASS_DEATH_KNIGHT
@ GENDER_NONE
@ SPELL_SCHOOL_MASK_SHADOW
@ SPELL_SCHOOL_MASK_NATURE
@ SPELL_SCHOOL_MASK_FIRE
@ SPELL_SCHOOL_MASK_FROST
@ CREATURE_TYPE_UNDEAD
@ CREATURE_TYPE_DEMON
@ CREATURE_TYPE_ELEMENTAL
@ CREATURE_TYPE_BEAST
#define MAX_SPECIALIZATIONS
@ UNIT_DYNFLAG_NONE
@ OFF_ATTACK
@ BASE_ATTACK
@ RANGED_ATTACK
#define PET_SPEC_OVERRIDE_CLASS_INDEX
Powers
@ POWER_MANA
@ POWER_FOCUS
Stats
@ STAT_INTELLECT
@ STAT_AGILITY
@ STAT_STRENGTH
@ STAT_STAMINA
AuraStateType
SpellSchools
@ SPELL_SCHOOL_SHADOW
@ SPELL_SCHOOL_FIRE
@ SPELL_SCHOOL_HOLY
@ MAX_SPELL_SCHOOL
@ SPELL_ATTR4_AURA_EXPIRES_OFFLINE
@ SPELL_AURA_OVERRIDE_PET_SPECS
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
@ SPELLVALUE_BASE_POINT0
PetFamilySpellsStore sPetFamilySpellsStore
Definition SpellMgr.cpp:105
#define sSpellMgr
Definition SpellMgr.h:812
std::multimap< uint32, uint32 > PetLevelupSpellSet
Definition SpellMgr.h:584
@ SPELL_CAST_SOURCE_NORMAL
Definition Spell.h:168
@ UNIT_FLAG2_REGENERATE_POWER
@ UNIT_PET_FLAG_CAN_BE_ABANDONED
@ UNIT_PET_FLAG_CAN_BE_RENAMED
@ REACT_PASSIVE
#define BASE_ATTACK_TIME
Definition UnitDefines.h:35
#define MAX_DECLINED_NAME_CASES
ActiveStates
@ ACT_DECIDE
@ ACT_ENABLED
@ ACT_PASSIVE
@ ACT_DISABLED
@ UNIT_NPC_FLAG_NONE
@ SHEATH_STATE_MELEE
Definition UnitDefines.h:83
@ UNIT_NPC_FLAG_2_NONE
@ COMMAND_FOLLOW
@ UNIT_FLAG_PLAYER_CONTROLLED
@ UNIT_FLAG_SKINNABLE
@ BASE_VALUE
Definition Unit.h:156
@ UNIT_MASK_CONTROLABLE_GUARDIAN
Definition Unit.h:364
@ UNIT_MASK_HUNTER_PET
Definition Unit.h:363
@ UNIT_MASK_PET
Definition Unit.h:360
@ MINDAMAGE
Definition Unit.h:171
@ MAXDAMAGE
Definition Unit.h:172
UnitMods
Definition Unit.h:176
@ UNIT_MOD_ARMOR
Definition Unit.h:209
@ UNIT_MOD_RESISTANCE_START
Definition Unit.h:225
@ UNIT_MOD_POWER_START
Definition Unit.h:227
@ UNIT_MOD_STAT_STAMINA
Definition Unit.h:179
DeathState
Definition Unit.h:251
@ CORPSE
Definition Unit.h:254
@ ALIVE
Definition Unit.h:252
@ JUST_DIED
Definition Unit.h:253
@ BASE_PCT
Definition Unit.h:164
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:565
T CalculatePct(T base, U pct)
Definition Util.h:72
uint32 const Entry[5]
int32 GetMaxDuration() const
Definition SpellAuras.h:217
static Aura * TryCreate(AuraCreateInfo &createInfo)
Trinity::IteratorPair< DBStorageIterator< AuraEffect * > > GetAuraEffects()
Definition SpellAuras.h:362
uint32 GetId() const
Definition SpellAuras.h:183
int32 GetDuration() const
Definition SpellAuras.h:222
uint8 GetStackAmount() const
Definition SpellAuras.h:238
uint8 GetCharges() const
Definition SpellAuras.h:229
Difficulty GetCastDifficulty() const
Definition SpellAuras.h:184
AuraKey GenerateKey(uint32 &recalculateMask) const
Fills a helper structure containing aura primary key for character_aura, character_aura_effect,...
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
bool IsInWorld() const
Definition BaseEntity.h:158
void _Create(ObjectGuid const &guid)
Definition BaseEntity.h:218
TypeID GetTypeId() const
Definition BaseEntity.h:166
void setDeathState(DeathState s) override
ObjectGuid::LowType m_spawnId
For new or temporary creatures is 0 for saved it is lowguid.
Definition Creature.h:541
void Update(uint32 time) override
Definition Creature.cpp:752
CreatureDifficulty const * GetCreatureDifficulty() const
Definition Creature.h:268
void SetObjectScale(float scale) override
std::string GetNameForLocaleIdx(LocaleConstant locale) const override
bool AIM_Initialize(CreatureAI *ai=nullptr)
void LoadTemplateImmunities(int32 creatureImmunitiesId)
void SetReactState(ReactStates st)
Definition Creature.h:174
void ApplyLevelScaling()
time_t m_corpseRemoveTime
Definition Creature.h:529
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:266
float GetBaseDamageForLevel(uint8 level) const
uint32 m_originalEntry
Definition Creature.h:551
float GetNativeObjectScale() const override
void SetDisplayId(uint32 displayId, bool setNative=false) override
ReactStates GetReactState() const
Definition Creature.h:175
bool InitEntry(uint32 entry, CreatureData const *data=nullptr)
Definition Creature.cpp:500
void SetMeleeDamageSchool(SpellSchools school)
Definition Creature.h:231
static float GetHealthMod(CreatureClassifications classification)
void Regenerate(Powers power)
Definition Creature.cpp:952
Class used to access individual fields of database query result.
Definition Field.h:94
double GetDouble() const noexcept
Definition Field.cpp:92
std::span< uint8 const > GetBinaryView() const noexcept
Definition Field.cpp:131
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
uint8 GetUInt8() const noexcept
Definition Field.cpp:29
int32 GetInt32() const noexcept
Definition Field.cpp:64
std::string GetString() const noexcept
Definition Field.cpp:113
void SetBonusDamage(int32 damage)
bool InitStatsForLevel(uint8 level)
Definition Pet.cpp:839
std::string GetDebugInfo() const override
bool UpdateAllStats() override
Definition Map.h:225
MapStoredObjectTypesContainer & GetObjectsStore()
Definition Map.h:458
bool AddToMap(T *)
Definition Map.cpp:517
ObjectGuid::LowType GenerateLowGuid()
Definition Map.h:558
Difficulty GetDifficultyID() const
Definition Map.h:360
uint32 GetId() const
Definition Map.cpp:3257
Unit * GetOwner() const
float GetFollowAngle() const override
bool IsPetGhoul() const
LowType GetCounter() const
Definition ObjectGuid.h:336
bool IsEmpty() const
Definition ObjectGuid.h:362
uint64 GetRawValue(std::size_t i) const
Definition ObjectGuid.h:325
void SetRawValue(std::span< uint8 const > rawBytes)
static constexpr std::size_t BytesSize
Definition ObjectGuid.h:319
uint64 LowType
Definition ObjectGuid.h:321
void Clear()
Definition ObjectGuid.h:329
Player * ToPlayer()
Definition Object.h:126
void ReplaceAllDynamicFlags(uint32 flag)
Definition Object.h:99
uint32 GetEntry() const
Definition Object.h:89
Creature * ToCreature()
Definition Object.h:121
uint32 GetAura(uint32 petEntry) const
Definition SpellMgr.h:448
bool IsRemovedOnChangePet() const
Definition SpellMgr.h:464
SpellEffectValue GetDamage() const
Definition SpellMgr.h:469
PetLoadQueryHolder(ObjectGuid::LowType ownerGuid, uint32 petNumber)
Definition Pet.cpp:172
Optional< uint32 > GetCurrentActivePetIndex() const
Definition PetDefines.h:188
std::array< Optional< PetInfo >, MAX_ACTIVE_PETS > ActivePets
Definition PetDefines.h:169
void SetCurrentUnslottedPetIndex(uint32 index)
Definition PetDefines.h:191
std::array< Optional< PetInfo >, MAX_PET_STABLES > StabledPets
Definition PetDefines.h:170
std::vector< PetInfo > UnslottedPets
Definition PetDefines.h:171
PetInfo * GetCurrentPet()
Definition PetDefines.h:173
Optional< uint32 > CurrentPetIndex
Definition PetDefines.h:168
void SetCurrentActivePetIndex(uint32 index)
Definition PetDefines.h:189
Definition Pet.h:40
uint16 GetSpecialization() const
Definition Pet.h:132
void LearnPetPassives()
Definition Pet.cpp:1710
Pet(Player *owner, PetType type=MAX_PET_TYPE)
Definition Pet.cpp:46
void GivePetLevel(uint8 level)
Definition Pet.cpp:753
void RemoveFromWorld() override
Definition Pet.cpp:94
bool m_loading
Definition Pet.h:152
void SetSpecialization(uint16 spec)
Definition Pet.cpp:1905
uint16 m_petSpecialization
Definition Pet.h:158
Player * GetOwner() const
Definition Pet.cpp:1801
bool IsPetAura(Aura const *aura)
Definition Pet.cpp:1765
bool unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab=true)
Definition Pet.cpp:1522
bool Create(ObjectGuid::LowType guidlow, Map *map, uint32 Entry, uint32 pet_number)
Definition Pet.cpp:1680
uint32 m_focusRegenTimer
Definition Pet.h:153
static void DeleteFromDB(uint32 petNumber)
Definition Pet.cpp:563
void FillPetInfo(PetStable::PetInfo *petInfo, Optional< ReactStates > forcedReactState={}) const
Definition Pet.cpp:544
void ToggleAutocast(SpellInfo const *spellInfo, bool apply)
Definition Pet.cpp:1614
void learnSpells(std::vector< uint32 > const &spellIds)
Definition Pet.cpp:1469
void AddToWorld() override
Definition Pet.cpp:69
static std::pair< PetStable::PetInfo const *, PetSaveMode > GetLoadPetInfo(PetStable const &stable, uint32 petEntry, uint32 petnumber, Optional< PetSaveMode > slot)
Definition Pet.cpp:105
void SetGroupUpdateFlag(uint32 flag)
Definition Pet.cpp:1835
void CastPetAuras(bool current)
Definition Pet.cpp:1731
void setPetType(PetType type)
Definition Pet.h:52
void SavePetToDB(PetSaveMode mode)
Definition Pet.cpp:451
float GetNativeObjectScale() const override
Definition Pet.cpp:1806
void _SaveAuras(CharacterDatabaseTransaction trans)
Definition Pet.cpp:1292
PetType getPetType() const
Definition Pet.h:51
void SynchronizeLevelWithOwner()
Definition Pet.cpp:1785
std::unique_ptr< DeclinedName > m_declinedname
Definition Pet.h:156
bool LoadPetFromDB(Player *owner, uint32 petEntry, uint32 petnumber, bool current, Optional< PetSaveMode > forcedSlot={})
Definition Pet.cpp:205
void _SaveSpells(CharacterDatabaseTransaction trans)
Definition Pet.cpp:1124
void learnSpellHighRank(uint32 spellid)
Definition Pet.cpp:1777
bool IsPermanentPetFor(Player *owner) const
Definition Pet.cpp:1657
bool HaveInDiet(ItemTemplate const *item) const
Definition Pet.cpp:1092
void RemoveSpecializationSpells(bool clearActionBar)
Definition Pet.cpp:1871
bool addSpell(uint32 spellId, ActiveStates active=ACT_DECIDE, PetSpellState state=PETSPELL_NEW, PetSpellType type=PETSPELL_NORMAL)
Definition Pet.cpp:1347
AutoSpellList m_autospells
Definition Pet.h:128
void SetPetExperience(uint32 xp)
Definition Pet.h:84
std::string GetDebugInfo() const override
Definition Pet.cpp:1944
bool CreateBaseAtTamed(CreatureTemplate const *cinfo, Map *map)
Definition Pet.cpp:814
bool CreateBaseAtCreatureInfo(CreatureTemplate const *cinfo, Unit *owner)
Definition Pet.cpp:801
void SetDisplayId(uint32 modelId, bool setNative=false) override
Definition Pet.cpp:1825
bool removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab=true)
Definition Pet.cpp:1553
bool CreateBaseAtCreature(Creature *creature)
Definition Pet.cpp:768
void CleanupActionBar()
Definition Pet.cpp:1587
bool isTemporarySummoned() const
Definition Pet.h:54
void CastPetAura(PetAura const *aura)
Definition Pet.cpp:1750
void unlearnSpells(std::vector< uint32 > const &spellIds, bool learn_prev, bool clear_ab=true)
Definition Pet.cpp:1537
void _LoadSpells(PreparedQueryResult result)
Definition Pet.cpp:1110
bool isControlled() const
Definition Pet.h:53
virtual ~Pet()
void SetPetNextLevelExperience(uint32 xp)
Definition Pet.h:85
void setDeathState(DeathState s) override
Definition Pet.cpp:598
void ResetGroupUpdateFlag()
Definition Pet.cpp:1844
bool m_removed
Definition Pet.h:143
void Remove(PetSaveMode mode, bool returnreagent=false)
Definition Pet.cpp:711
void _LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effectResult, uint32 timediff)
Definition Pet.cpp:1173
void Update(uint32 diff) override
Definition Pet.cpp:619
void InitPetCreateSpells()
Definition Pet.cpp:1603
bool HasSpell(uint32 spell) const override
Definition Pet.cpp:1703
void LearnSpecializationSpells()
Definition Pet.cpp:1851
uint32 m_groupUpdateMask
Definition Pet.h:154
PetSpellMap m_spells
Definition Pet.h:127
void GivePetXP(uint32 xp)
Definition Pet.cpp:716
std::string GenerateActionBarData() const
Definition Pet.cpp:1931
bool learnSpell(uint32 spell_id)
Definition Pet.cpp:1453
int32 m_duration
Definition Pet.h:151
void InitLevelupSpellsForLevel()
Definition Pet.cpp:1485
static void InheritPhaseShift(WorldObject *target, WorldObject const *source)
void SetGroupUpdateFlag(uint32 flag)
Definition Player.h:2804
uint32 GetTemporaryUnsummonedPetNumber() const
Definition Player.h:2733
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6283
UF::UpdateField< UF::ActivePlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_ACTIVE_PLAYER > m_activePlayerData
Definition Player.h:3062
bool CanTameExoticPets() const
Definition Player.h:2496
void SetTemporaryUnsummonedPetNumber(uint32 petnumber)
Definition Player.h:2734
void DisablePetControlsOnMount(ReactStates reactState, CommandStates commandState)
Definition Player.cpp:27942
void RemoveGroupUpdateFlag(uint32 flag)
Definition Player.h:2805
bool IsPetNeedBeTemporaryUnsummoned() const
Definition Player.cpp:28048
PetStable * GetPetStable()
Definition Player.h:1355
void PetSpellInitialize()
Definition Player.cpp:22471
Pet * GetPet() const
Definition Player.cpp:22060
WorldSession * GetSession() const
Definition Player.h:2272
void RemovePet(Pet *pet, PetSaveMode mode, bool returnreagent=false)
Definition Player.cpp:22084
Optional< ReactStates > GetTemporaryPetReactState() const
Definition Player.h:2735
std::unordered_set< PetAura const * > m_petAuras
Definition Player.h:1370
void RemovePetAura(PetAura const *petSpell)
Definition Player.cpp:22235
void SetLastPetNumber(uint32 petnumber)
Definition Player.h:2787
void setBinary(uint8 index, std::vector< uint8 > &&value)
void setInt16(uint8 index, int16 value)
void setUInt16(uint8 index, uint16 value)
void setString(uint8 index, std::string &&value)
void setUInt32(uint8 index, uint32 value)
void setUInt64(uint8 index, uint64 value)
void setInt32(uint8 index, int32 value)
void setUInt8(uint8 index, uint8 value)
void setDouble(uint8 index, double value)
void SetSize(size_t size)
PreparedQueryResult GetPreparedResult(size_t index) const
void AfterComplete(std::function< void(SQLQueryHolderBase const &)> callback) &
Definition QueryHolder.h:70
bool SetPreparedQuery(size_t index, PreparedStatement< T > *stmt)
Definition QueryHolder.h:48
void SaveToDB(CharacterDatabaseTransaction trans)
uint32 SpellLevel
Definition SpellInfo.h:389
bool IsAutocastEnabledByDefault() const
bool IsAutocastable() const
uint32 const Id
Definition SpellInfo.h:328
bool IsPassive() const
uint32 ProcCharges
Definition SpellInfo.h:383
bool IsRanked() const
bool IsHighRankOf(SpellInfo const *spellInfo) const
uint32 CasterAuraState
Definition SpellInfo.h:358
bool HasAttribute(SpellAttr0 attribute) const
Definition SpellInfo.h:456
int32 GetDuration() const
bool IsDifferentRankOf(SpellInfo const *spellInfo) const
bool IsPositive() const
Definition Unit.h:635
void SetMinion(Minion *minion, bool apply)
Definition Unit.cpp:6247
bool HasPetFlag(UnitPetFlag flags) const
Definition Unit.h:891
bool IsHunterPet() const
Definition Unit.h:752
void SetCreateStat(Stats stat, float val)
Definition Unit.h:1413
void SetHealth(uint64 val)
Definition Unit.cpp:9973
Pet * ToPet()
Definition Unit.h:1822
void SetGender(Gender gender)
Definition Unit.h:768
void SetFullHealth()
Definition Unit.h:802
void ReplaceAllNpcFlags2(NPCFlags2 flags)
Definition Unit.h:1005
ThreatManager & GetThreatManager()
Definition Unit.h:1078
void AddToWorld() override
Definition Unit.cpp:10233
uint8 GetClass() const
Definition Unit.h:764
void SetCreateHealth(uint32 val)
Definition Unit.h:1414
std::unique_ptr< CharmInfo > m_charmInfo
Definition Unit.h:1952
void SetFaction(uint32 faction) override
Definition Unit.h:872
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value)
Definition Unit.h:1573
ObjectGuid GetOwnerGUID() const override
Definition Unit.h:1191
void SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val)
Definition Unit.cpp:9644
void SetPower(Powers power, int32 val, bool withPowerUpdate=true)
Definition Unit.cpp:10046
void ReplaceAllUnitFlags(UnitFlags flags)
Definition Unit.h:848
bool IsPet() const
Definition Unit.h:751
Powers GetPowerType() const
Definition Unit.h:811
void SetCreatedBySpell(int32 spellId)
Definition Unit.h:860
Aura * AddAura(uint32 spellId, Unit *target)
Definition Unit.cpp:12249
void SetUnitFlag2(UnitFlags2 flags)
Definition Unit.h:851
void ReplaceAllPetFlags(UnitPetFlag flags)
Definition Unit.h:894
void SetPetNameTimestamp(uint32 timestamp)
Definition Unit.h:1246
bool IsAlive() const
Definition Unit.h:1185
float GetCombatReach() const override
Definition Unit.h:705
DeathState m_deathState
Definition Unit.h:1905
uint32 m_unitTypeMask
Definition Unit.h:1963
CharmInfo * GetCharmInfo()
Definition Unit.h:1242
void SetBaseAttackTime(WeaponAttackType att, uint32 val)
Definition Unit.cpp:10939
void SetSheath(SheathState sheathed)
Definition Unit.cpp:5813
void SetCreateMana(uint32 val)
Definition Unit.h:1416
uint32 GetDisplayId() const
Definition Unit.h:1610
uint32 GetNativeDisplayId() const
Definition Unit.h:1613
bool isPossessed() const
Definition Unit.h:1237
uint64 GetHealth() const
Definition Unit.h:788
uint32 GetFaction() const override
Definition Unit.h:871
bool HasAuraState(AuraStateType flag, SpellInfo const *spellProto=nullptr, Unit const *Caster=nullptr) const
Definition Unit.cpp:6146
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4814
uint32 GetArmor() const
Definition Unit.h:774
void SetFullPower(Powers power)
Definition Unit.h:825
bool IsMounted() const
Definition Unit.h:912
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition Unit.h:1881
int32 GetPower(Powers power) const
Definition Unit.cpp:10028
float GetTotalAttackPowerValue(WeaponAttackType attType, bool includeWeapon=true) const
Definition Unit.cpp:9912
DeathState getDeathState() const
Definition Unit.h:1188
bool IsCritter() const
Definition Unit.h:1025
AuraMap m_ownedAuras
Definition Unit.h:1924
void SetLevel(uint8 lvl, bool sendUpdate=true)
Definition Unit.cpp:9956
void SetCanModifyStats(bool modifyStats)
Definition Unit.h:1549
CharmInfo * InitCharmInfo()
Definition Unit.cpp:10379
void SetClass(uint8 classId)
Definition Unit.h:765
void RemoveFromWorld() override
Definition Unit.cpp:10241
Powers CalculateDisplayPowerType() const
Definition Unit.cpp:5762
float GetStat(Stats stat) const
Definition Unit.h:772
void RemoveAllAuras()
Definition Unit.cpp:4382
SpellHistory * GetSpellHistory()
Definition Unit.h:1498
void SetCreatorGUID(ObjectGuid creator)
Definition Unit.h:1194
void ReplaceAllNpcFlags(NPCFlags flags)
Definition Unit.h:999
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
Definition Unit.cpp:7084
void SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val)
Definition Unit.cpp:9635
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3974
void SetPowerType(Powers power, bool sendUpdate=true, bool onInit=false)
Definition Unit.cpp:5697
uint8 GetLevel() const
Definition Unit.h:757
void RemoveUnitFlag(UnitFlags flags)
Definition Unit.h:847
ObjectGuid GetPetGUID() const
Definition Unit.h:1197
constexpr uint32 GetMapId() const
Definition Position.h:216
Map * GetMap() const
Definition Object.h:411
std::string m_name
Definition Object.h:579
InstanceScript * GetInstanceScript() const
Definition Object.cpp:396
void GetClosePoint(float &x, float &y, float &z, float size, float distance2d=0, float relAngle=0) const
Definition Object.cpp:2749
ZoneScript * GetZoneScript() const
Definition Object.h:417
std::string const & GetName() const
Definition Object.h:342
virtual void SetMap(Map *map)
Definition Object.cpp:1144
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:501
void SetName(std::string newname)
Definition Object.h:343
float GetVisibilityRange() const
Definition Object.cpp:787
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
std::string GetPlayerInfo() const
SQLQueryHolderCallback & AddQueryHolderCallback(SQLQueryHolderCallback &&callback)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
#define sWorld
Definition World.h:916
@ CONFIG_MAX_PLAYER_LEVEL
Definition World.h:262
time_t GetGameTime()
Definition GameTime.cpp:52
AuraCreateInfo & SetCasterGUID(ObjectGuid const &guid)
Definition SpellAuras.h:114
AuraCreateInfo & SetBaseAmount(SpellEffectValue const *bp)
Definition SpellAuras.h:116
AuraCreateInfo & SetStackAmount(int32 stackAmount)
Definition SpellAuras.h:120
uint32 SpellId
Definition SpellAuras.h:155
ObjectGuid Caster
Definition SpellAuras.h:153
uint32 EffectMask
Definition SpellAuras.h:156
std::array< SpellEffectValue, MAX_SPELL_EFFECTS > Amounts
Definition SpellAuras.h:163
std::array< SpellEffectValue, MAX_SPELL_EFFECTS > BaseAmounts
Definition SpellAuras.h:164
TriggerCastFlags TriggerFlags
CastSpellExtraArgs & AddSpellMod(SpellValueMod mod, int32 val)
void SetIsCommandFollow(bool val)
Definition Unit.cpp:13222
void SetIsAtStay(bool val)
Definition Unit.cpp:13253
void SetIsFollowing(bool val)
Definition Unit.cpp:13263
void SetIsReturning(bool val)
Definition Unit.cpp:13273
bool HasCommandState(CommandStates state) const
Definition CharmInfo.h:98
void SetIsCommandAttack(bool val)
Definition Unit.cpp:13212
int32 GetHealthScalingExpansion() const
CreatureDifficulty const * GetDifficulty(Difficulty difficulty) const
Definition Creature.cpp:252
CreatureClassifications Classification
CreatureFamily family
int32 resistance[MAX_SPELL_SCHOOL]
bool IsTameable(bool canTameExotic, CreatureDifficulty const *creatureDifficulty) const
uint16 health
Definition ObjectMgr.h:680
uint16 armor
Definition ObjectMgr.h:682
uint16 stats[MAX_STATS]
Definition ObjectMgr.h:679
uint16 mana
Definition ObjectMgr.h:681
Definition Pet.h:27
PetSpellState state
Definition Pet.h:29
PetSpellType type
Definition Pet.h:30
ActiveStates active
Definition Pet.h:28
ReactStates ReactState
Definition PetDefines.h:163
std::string Name
Definition PetDefines.h:151
std::string ActionBar
Definition PetDefines.h:152
constexpr float GetPositionX() const
Definition Position.h:87
constexpr float GetPositionY() const
Definition Position.h:88
std::string ToString() const
Definition Position.cpp:202
bool IsPositionValid() const
Definition Position.cpp:42
constexpr void Relocate(float x, float y)
Definition Position.h:74
constexpr float GetOrientation() const
Definition Position.h:90
constexpr float GetPositionZ() const
Definition Position.h:89
bool Insert(ValueType< ObjectType > object)
bool Remove(ValueType< ObjectType > object)