TrinityCore
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
84 if (GetCharmInfo() && GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
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].GetInt32();
1203 info.BaseAmounts[effectIndex] = fields[5].GetInt32();
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
1274 if (Aura* aura = Aura::TryCreate(createInfo))
1275 {
1276 if (!aura->CanBeSaved())
1277 {
1278 aura->Remove();
1279 continue;
1280 }
1281
1282 aura->SetLoadedState(maxDuration, remainTime, remainCharges, stackCount, recalculateMask, info.Amounts.data());
1283 aura->ApplyForTargets();
1284 TC_LOG_DEBUG("entities.pet", "Added aura spellid {}, effectmask {}", spellInfo->Id, key.EffectMask);
1285 }
1286 }
1287 while (auraResult->NextRow());
1288 }
1289}
1290
1292{
1294 stmt->setUInt32(0, m_charmInfo->GetPetNumber());
1295 trans->Append(stmt);
1296
1297 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_AURAS);
1298 stmt->setUInt32(0, m_charmInfo->GetPetNumber());
1299 trans->Append(stmt);
1300
1301 uint8 index;
1302 for (AuraMap::const_iterator itr = m_ownedAuras.begin(); itr != m_ownedAuras.end(); ++itr)
1303 {
1304 // check if the aura has to be saved
1305 if (!itr->second->CanBeSaved() || IsPetAura(itr->second))
1306 continue;
1307
1308 Aura* aura = itr->second;
1309 uint32 recalculateMask = 0;
1310 AuraKey key = aura->GenerateKey(recalculateMask);
1311
1312 // 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
1313 if (key.Caster == GetGUID())
1314 key.Caster.Clear();
1315
1316 index = 0;
1317 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PET_AURA);
1318 stmt->setUInt32(index++, m_charmInfo->GetPetNumber());
1319 stmt->setBinary(index++, key.Caster.GetRawValue());
1320 stmt->setUInt32(index++, key.SpellId);
1321 stmt->setUInt32(index++, key.EffectMask);
1322 stmt->setUInt32(index++, recalculateMask);
1323 stmt->setUInt8(index++, aura->GetCastDifficulty());
1324 stmt->setUInt8(index++, aura->GetStackAmount());
1325 stmt->setInt32(index++, aura->GetMaxDuration());
1326 stmt->setInt32(index++, aura->GetDuration());
1327 stmt->setUInt8(index++, aura->GetCharges());
1328 trans->Append(stmt);
1329
1330 for (AuraEffect const* effect : aura->GetAuraEffects())
1331 {
1332 index = 0;
1333 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PET_AURA_EFFECT);
1334 stmt->setUInt32(index++, m_charmInfo->GetPetNumber());
1335 stmt->setBinary(index++, key.Caster.GetRawValue());
1336 stmt->setUInt32(index++, key.SpellId);
1337 stmt->setUInt32(index++, key.EffectMask);
1338 stmt->setUInt8(index++, effect->GetEffIndex());
1339 stmt->setInt32(index++, effect->GetAmount());
1340 stmt->setInt32(index++, effect->GetBaseAmount());
1341 trans->Append(stmt);
1342 }
1343 }
1344}
1345
1346bool Pet::addSpell(uint32 spellId, ActiveStates active /*= ACT_DECIDE*/, PetSpellState state /*= PETSPELL_NEW*/, PetSpellType type /*= PETSPELL_NORMAL*/)
1347{
1348 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
1349 if (!spellInfo)
1350 {
1351 // do pet spell book cleanup
1352 if (state == PETSPELL_UNCHANGED) // spell load case
1353 {
1354 TC_LOG_ERROR("entities.pet", "Pet::addSpell: Non-existed in SpellStore spell #{} request, deleting for all pets in `pet_spell`.", spellId);
1355
1357
1358 stmt->setUInt32(0, spellId);
1359
1360 CharacterDatabase.Execute(stmt);
1361 }
1362 else
1363 TC_LOG_ERROR("entities.pet", "Pet::addSpell: Non-existed in SpellStore spell #{} request.", spellId);
1364
1365 return false;
1366 }
1367
1368 PetSpellMap::iterator itr = m_spells.find(spellId);
1369 if (itr != m_spells.end())
1370 {
1371 if (itr->second.state == PETSPELL_REMOVED)
1372 state = PETSPELL_CHANGED;
1373 else
1374 {
1375 if (state == PETSPELL_UNCHANGED && itr->second.state != PETSPELL_UNCHANGED)
1376 {
1377 // can be in case spell loading but learned at some previous spell loading
1378 itr->second.state = PETSPELL_UNCHANGED;
1379
1380 if (active == ACT_ENABLED)
1381 ToggleAutocast(spellInfo, true);
1382 else if (active == ACT_DISABLED)
1383 ToggleAutocast(spellInfo, false);
1384 }
1385
1386 return false;
1387 }
1388 }
1389
1390 PetSpell newspell;
1391 newspell.state = state;
1392 newspell.type = type;
1393
1394 if (active == ACT_DECIDE) // active was not used before, so we save it's autocast/passive state here
1395 {
1396 if (!spellInfo->IsAutocastable())
1397 newspell.active = ACT_PASSIVE;
1398 else if (spellInfo->IsAutocastEnabledByDefault())
1399 newspell.active = ACT_ENABLED;
1400 else
1401 newspell.active = ACT_DISABLED;
1402 }
1403 else
1404 newspell.active = active;
1405
1406 // talent: unlearn all other talent ranks (high and low)
1407 if (spellInfo->IsRanked())
1408 {
1409 for (PetSpellMap::const_iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2)
1410 {
1411 if (itr2->second.state == PETSPELL_REMOVED)
1412 continue;
1413
1414 SpellInfo const* oldRankSpellInfo = sSpellMgr->GetSpellInfo(itr2->first, DIFFICULTY_NONE);
1415
1416 if (!oldRankSpellInfo)
1417 continue;
1418
1419 if (spellInfo->IsDifferentRankOf(oldRankSpellInfo))
1420 {
1421 // replace by new high rank
1422 if (spellInfo->IsHighRankOf(oldRankSpellInfo))
1423 {
1424 newspell.active = itr2->second.active;
1425
1426 if (newspell.active == ACT_ENABLED)
1427 ToggleAutocast(oldRankSpellInfo, false);
1428
1429 unlearnSpell(itr2->first, false, false);
1430 break;
1431 }
1432 // ignore new lesser rank
1433 else
1434 return false;
1435 }
1436 }
1437 }
1438
1439 m_spells[spellId] = newspell;
1440
1441 if (spellInfo->IsPassive() && (!spellInfo->CasterAuraState || HasAuraState(AuraStateType(spellInfo->CasterAuraState))))
1442 CastSpell(this, spellId, true);
1443 else
1444 m_charmInfo->AddSpellToActionBar(spellInfo);
1445
1446 if (newspell.active == ACT_ENABLED)
1447 ToggleAutocast(spellInfo, true);
1448
1449 return true;
1450}
1451
1453{
1454 // prevent duplicated entires in spell book
1455 if (!addSpell(spell_id))
1456 return false;
1457
1458 if (!m_loading)
1459 {
1461 packet.Spells.push_back(spell_id);
1462 GetOwner()->SendDirectMessage(packet.Write());
1464 }
1465 return true;
1466}
1467
1468void Pet::learnSpells(std::vector<uint32> const& spellIds)
1469{
1471
1472 for (uint32 spell : spellIds)
1473 {
1474 if (!addSpell(spell))
1475 continue;
1476
1477 packet.Spells.push_back(spell);
1478 }
1479
1480 if (!m_loading)
1481 GetOwner()->GetSession()->SendPacket(packet.Write());
1482}
1483
1485{
1486 uint8 level = GetLevel();
1487
1488 if (PetLevelupSpellSet const* levelupSpells = GetCreatureTemplate()->family ? sSpellMgr->GetPetLevelupSpellList(GetCreatureTemplate()->family) : nullptr)
1489 {
1490 // PetLevelupSpellSet ordered by levels, process in reversed order
1491 for (PetLevelupSpellSet::const_reverse_iterator itr = levelupSpells->rbegin(); itr != levelupSpells->rend(); ++itr)
1492 {
1493 // will called first if level down
1494 if (itr->first > level)
1495 unlearnSpell(itr->second, true); // will learn prev rank if any
1496 // will called if level up
1497 else
1498 learnSpell(itr->second); // will unlearn prev rank if any
1499 }
1500 }
1501
1502 // default spells (can be not learned if pet level (as owner level decrease result for example) less first possible in normal game)
1503 if (PetDefaultSpellsEntry const* defSpells = sSpellMgr->GetPetDefaultSpellsEntry(int32(GetEntry())))
1504 {
1505 for (uint32 spellId : defSpells->spellid)
1506 {
1507 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
1508 if (!spellInfo)
1509 continue;
1510
1511 // will called first if level down
1512 if (spellInfo->SpellLevel > level)
1513 unlearnSpell(spellInfo->Id, true);
1514 // will called if level up
1515 else
1516 learnSpell(spellInfo->Id);
1517 }
1518 }
1519}
1520
1521bool Pet::unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab)
1522{
1523 if (removeSpell(spell_id, learn_prev, clear_ab))
1524 {
1525 if (!m_loading)
1526 {
1528 packet.Spells.push_back(spell_id);
1529 GetOwner()->SendDirectMessage(packet.Write());
1530 }
1531 return true;
1532 }
1533 return false;
1534}
1535
1536void Pet::unlearnSpells(std::vector<uint32> const& spellIds, bool learn_prev, bool clear_ab)
1537{
1539
1540 for (uint32 spell : spellIds)
1541 {
1542 if (!removeSpell(spell, learn_prev, clear_ab))
1543 continue;
1544
1545 packet.Spells.push_back(spell);
1546 }
1547
1548 if (!m_loading)
1549 GetOwner()->GetSession()->SendPacket(packet.Write());
1550}
1551
1552bool Pet::removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab)
1553{
1554 PetSpellMap::iterator itr = m_spells.find(spell_id);
1555 if (itr == m_spells.end())
1556 return false;
1557
1558 if (itr->second.state == PETSPELL_REMOVED)
1559 return false;
1560
1561 if (itr->second.state == PETSPELL_NEW)
1562 m_spells.erase(itr);
1563 else
1564 itr->second.state = PETSPELL_REMOVED;
1565
1566 RemoveAurasDueToSpell(spell_id);
1567
1568 if (learn_prev)
1569 {
1570 if (uint32 prev_id = sSpellMgr->GetPrevSpellInChain (spell_id))
1571 learnSpell(prev_id);
1572 else
1573 learn_prev = false;
1574 }
1575
1576 // if remove last rank or non-ranked then update action bar at server and client if need
1577 if (clear_ab && !learn_prev && m_charmInfo->RemoveSpellFromActionBar(spell_id))
1578 {
1579 if (!m_loading)
1580 GetOwner()->PetSpellInitialize(); // need update action bar for last removed rank
1581 }
1582
1583 return true;
1584}
1585
1587{
1588 for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
1589 if (UnitActionBarEntry const* ab = m_charmInfo->GetActionBarEntry(i))
1590 if (ab->GetAction() && ab->IsActionBarForSpell())
1591 {
1592 if (!HasSpell(ab->GetAction()))
1593 m_charmInfo->SetActionBar(i, 0, ACT_PASSIVE);
1594 else if (ab->GetType() == ACT_ENABLED)
1595 {
1596 if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(ab->GetAction(), DIFFICULTY_NONE))
1597 ToggleAutocast(spellInfo, true);
1598 }
1599 }
1600}
1601
1603{
1604 m_charmInfo->InitPetActionBar();
1605 m_spells.clear();
1606
1609
1610 CastPetAuras(false);
1611}
1612
1613void Pet::ToggleAutocast(SpellInfo const* spellInfo, bool apply)
1614{
1615 ASSERT(spellInfo);
1616
1617 if (!spellInfo->IsAutocastable())
1618 return;
1619
1620 PetSpellMap::iterator itr = m_spells.find(spellInfo->Id);
1621 if (itr == m_spells.end())
1622 return;
1623
1624 auto autospellItr = std::find(m_autospells.begin(), m_autospells.end(), spellInfo->Id);
1625
1626 if (apply)
1627 {
1628 if (autospellItr == m_autospells.end())
1629 {
1630 m_autospells.push_back(spellInfo->Id);
1631
1632 if (itr->second.active != ACT_ENABLED)
1633 {
1634 itr->second.active = ACT_ENABLED;
1635 if (itr->second.state != PETSPELL_NEW)
1636 itr->second.state = PETSPELL_CHANGED;
1637 }
1638 }
1639 }
1640 else
1641 {
1642 if (autospellItr != m_autospells.end())
1643 {
1644 m_autospells.erase(autospellItr);
1645
1646 if (itr->second.active != ACT_DISABLED)
1647 {
1648 itr->second.active = ACT_DISABLED;
1649 if (itr->second.state != PETSPELL_NEW)
1650 itr->second.state = PETSPELL_CHANGED;
1651 }
1652 }
1653 }
1654}
1655
1657{
1658 switch (getPetType())
1659 {
1660 case SUMMON_PET:
1661 switch (owner->GetClass())
1662 {
1663 case CLASS_WARLOCK:
1665 case CLASS_DEATH_KNIGHT:
1667 case CLASS_MAGE:
1669 default:
1670 return false;
1671 }
1672 case HUNTER_PET:
1673 return true;
1674 default:
1675 return false;
1676 }
1677}
1678
1679bool Pet::Create(ObjectGuid::LowType guidlow, Map* map, uint32 Entry, uint32 /*petId*/)
1680{
1681 ASSERT(map);
1682 SetMap(map);
1683
1684 // TODO: counter should be constructed as (summon_count << 32) | petNumber
1685 Object::_Create(ObjectGuid::Create<HighGuid::Pet>(map->GetId(), Entry, guidlow));
1686
1687 m_spawnId = guidlow;
1689
1690 if (!InitEntry(Entry))
1691 return false;
1692
1693 // Force regen flag for player pets, just like we do for players themselves
1696
1698
1699 return true;
1700}
1701
1702bool Pet::HasSpell(uint32 spell) const
1703{
1704 PetSpellMap::const_iterator itr = m_spells.find(spell);
1705 return itr != m_spells.end() && itr->second.state != PETSPELL_REMOVED;
1706}
1707
1708// Get all passive spells in our skill line
1710{
1711 CreatureTemplate const* cInfo = GetCreatureTemplate();
1712 if (!cInfo)
1713 return;
1714
1715 CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->family);
1716 if (!cFamily)
1717 return;
1718
1719 PetFamilySpellsStore::const_iterator petStore = sPetFamilySpellsStore.find(cInfo->family);
1720 if (petStore != sPetFamilySpellsStore.end())
1721 {
1722 // For general hunter pets skill 270
1723 // Passive 01~10, Passive 00 (20782, not used), Ferocious Inspiration (34457)
1724 // Scale 01~03 (34902~34904, bonus from owner, not used)
1725 for (uint32 spellId : petStore->second)
1727 }
1728}
1729
1730void Pet::CastPetAuras(bool current)
1731{
1732 Player* owner = GetOwner();
1733
1734 if (!IsPermanentPetFor(owner))
1735 return;
1736
1737 for (auto itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end();)
1738 {
1739 PetAura const* pa = *itr;
1740 ++itr;
1741
1742 if (!current && pa->IsRemovedOnChangePet())
1743 owner->RemovePetAura(pa);
1744 else
1745 CastPetAura(pa);
1746 }
1747}
1748
1749void Pet::CastPetAura(PetAura const* aura)
1750{
1751 uint32 auraId = aura->GetAura(GetEntry());
1752 if (!auraId)
1753 return;
1754
1755 CastSpellExtraArgs args;
1757
1758 if (auraId == 35696) // Demonic Knowledge
1760
1761 CastSpell(this, auraId, args);
1762}
1763
1764bool Pet::IsPetAura(Aura const* aura)
1765{
1766 Player* owner = GetOwner();
1767
1768 // if the owner has that pet aura, return true
1769 for (PetAura const* petAura : owner->m_petAuras)
1770 if (petAura->GetAura(GetEntry()) == aura->GetId())
1771 return true;
1772
1773 return false;
1774}
1775
1777{
1778 learnSpell(spellid);
1779
1780 if (uint32 next = sSpellMgr->GetNextSpellInChain(spellid))
1781 learnSpellHighRank(next);
1782}
1783
1785{
1786 Player* owner = GetOwner();
1787
1788 switch (getPetType())
1789 {
1790 // always same level
1791 case SUMMON_PET:
1792 case HUNTER_PET:
1793 GivePetLevel(owner->GetLevel());
1794 break;
1795 default:
1796 break;
1797 }
1798}
1799
1801{
1802 return Minion::GetOwner()->ToPlayer();
1803}
1804
1806{
1807 CreatureFamilyEntry const* creatureFamily = sCreatureFamilyStore.LookupEntry(GetCreatureTemplate()->family);
1808 if (creatureFamily && creatureFamily->MinScale > 0.0f && getPetType() == HUNTER_PET)
1809 {
1810 float scale;
1811 if (GetLevel() >= creatureFamily->MaxScaleLevel)
1812 scale = creatureFamily->MaxScale;
1813 else if (GetLevel() <= creatureFamily->MinScaleLevel)
1814 scale = creatureFamily->MinScale;
1815 else
1816 scale = creatureFamily->MinScale + float(GetLevel() - creatureFamily->MinScaleLevel) / creatureFamily->MaxScaleLevel * (creatureFamily->MaxScale - creatureFamily->MinScale);
1817
1818 return scale;
1819 }
1820
1822}
1823
1824void Pet::SetDisplayId(uint32 modelId, bool setNative /*= false*/)
1825{
1826 Guardian::SetDisplayId(modelId, setNative);
1827
1828 if (!isControlled())
1829 return;
1830
1832}
1833
1835{
1836 if (GetOwner()->GetGroup())
1837 {
1838 m_groupUpdateMask |= flag;
1840 }
1841}
1842
1844{
1846 if (GetOwner()->GetGroup())
1848}
1849
1851{
1852 std::vector<uint32> learnedSpells;
1853
1854 if (std::vector<SpecializationSpellsEntry const*> const* specSpells = sDB2Manager.GetSpecializationSpells(m_petSpecialization))
1855 {
1856 for (size_t j = 0; j < specSpells->size(); ++j)
1857 {
1858 SpecializationSpellsEntry const* specSpell = specSpells->at(j);
1859 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(specSpell->SpellID, DIFFICULTY_NONE);
1860 if (!spellInfo || spellInfo->SpellLevel > GetLevel())
1861 continue;
1862
1863 learnedSpells.push_back(specSpell->SpellID);
1864 }
1865 }
1866
1867 learnSpells(learnedSpells);
1868}
1869
1870void Pet::RemoveSpecializationSpells(bool clearActionBar)
1871{
1872 std::vector<uint32> unlearnedSpells;
1873
1874 for (uint32 i = 0; i < MAX_SPECIALIZATIONS; ++i)
1875 {
1876 if (ChrSpecializationEntry const* specialization = sDB2Manager.GetChrSpecializationByIndex(0, i))
1877 {
1878 if (std::vector<SpecializationSpellsEntry const*> const* specSpells = sDB2Manager.GetSpecializationSpells(specialization->ID))
1879 {
1880 for (size_t j = 0; j < specSpells->size(); ++j)
1881 {
1882 SpecializationSpellsEntry const* specSpell = specSpells->at(j);
1883 unlearnedSpells.push_back(specSpell->SpellID);
1884 }
1885 }
1886 }
1887
1888 if (ChrSpecializationEntry const* specialization = sDB2Manager.GetChrSpecializationByIndex(PET_SPEC_OVERRIDE_CLASS_INDEX, i))
1889 {
1890 if (std::vector<SpecializationSpellsEntry const*> const* specSpells = sDB2Manager.GetSpecializationSpells(specialization->ID))
1891 {
1892 for (size_t j = 0; j < specSpells->size(); ++j)
1893 {
1894 SpecializationSpellsEntry const* specSpell = specSpells->at(j);
1895 unlearnedSpells.push_back(specSpell->SpellID);
1896 }
1897 }
1898 }
1899 }
1900
1901 unlearnSpells(unlearnedSpells, true, clearActionBar);
1902}
1903
1905{
1906 if (m_petSpecialization == spec)
1907 return;
1908
1909 // remove all the old spec's specalization spells, set the new spec, then add the new spec's spells
1910 // clearActionBars is false because we'll be updating the pet actionbar later so we don't have to do it now
1912 if (!sChrSpecializationStore.LookupEntry(spec))
1913 {
1915 return;
1916 }
1917
1918 m_petSpecialization = spec;
1920
1921 // resend SMSG_PET_SPELLS_MESSAGE to remove old specialization spells from the pet action bar
1924
1925 WorldPackets::Pet::SetPetSpecialization setPetSpecialization;
1926 setPetSpecialization.SpecID = m_petSpecialization;
1927 GetOwner()->GetSession()->SendPacket(setPetSpecialization.Write());
1928}
1929
1931{
1932 std::ostringstream ss;
1933
1935 {
1936 ss << uint32(m_charmInfo->GetActionBarEntry(i)->GetType()) << ' '
1937 << uint32(m_charmInfo->GetActionBarEntry(i)->GetAction()) << ' ';
1938 }
1939
1940 return ss.str();
1941}
1942
1943std::string Pet::GetDebugInfo() const
1944{
1945 std::stringstream sstr;
1946 sstr << Guardian::GetDebugInfo() << "\n"
1947 << std::boolalpha
1948 << "PetType: " << std::to_string(getPetType()) << " "
1949 << "PetNumber: " << m_charmInfo->GetPetNumber();
1950 return sstr.str();
1951}
@ 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:86
@ ACTION_BAR_INDEX_END
Definition: CharmInfo.h:83
@ ACTION_BAR_INDEX_START
Definition: CharmInfo.h:80
@ IN_MILLISECONDS
Definition: Common.h:35
const uint32 PET_FOCUS_REGEN_INTERVAL
Definition: CreatureData.h:422
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:554
Difficulty
Definition: DBCEnums.h:918
@ DIFFICULTY_NONE
Definition: DBCEnums.h:919
#define MAX_SPELL_EFFECTS
Definition: DBCEnums.h:2121
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint16_t uint16
Definition: Define.h:143
uint32_t uint32
Definition: Define.h:142
#define ASSERT_NOTNULL(pointer)
Definition: Errors.h:84
#define ASSERT
Definition: Errors.h:68
@ 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:179
#define TC_LOG_ERROR(filterType__, message__,...)
Definition: Log.h:188
@ TYPEID_PLAYER
Definition: ObjectGuid.h:43
#define sObjectMgr
Definition: ObjectMgr.h:1986
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
@ SPELLVALUE_BASE_POINT0
Definition: SpellDefines.h:199
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
Definition: SpellDefines.h:277
PetFamilySpellsStore sPetFamilySpellsStore
Definition: SpellMgr.cpp:104
#define sSpellMgr
Definition: SpellMgr.h:855
std::multimap< uint32, uint32 > PetLevelupSpellSet
Definition: SpellMgr.h:627
@ SPELL_CAST_SOURCE_NORMAL
Definition: Spell.h:153
@ UNIT_FLAG2_REGENERATE_POWER
Definition: UnitDefines.h:228
@ UNIT_PET_FLAG_CAN_BE_ABANDONED
Definition: UnitDefines.h:110
@ UNIT_PET_FLAG_CAN_BE_RENAMED
Definition: UnitDefines.h:109
@ REACT_PASSIVE
Definition: UnitDefines.h:540
#define BASE_ATTACK_TIME
Definition: UnitDefines.h:35
#define MAX_DECLINED_NAME_CASES
Definition: UnitDefines.h:518
ActiveStates
Definition: UnitDefines.h:529
@ ACT_DECIDE
Definition: UnitDefines.h:535
@ ACT_ENABLED
Definition: UnitDefines.h:532
@ ACT_PASSIVE
Definition: UnitDefines.h:530
@ ACT_DISABLED
Definition: UnitDefines.h:531
@ UNIT_NPC_FLAG_NONE
Definition: UnitDefines.h:319
@ SHEATH_STATE_MELEE
Definition: UnitDefines.h:83
@ UNIT_NPC_FLAG_2_NONE
Definition: UnitDefines.h:362
@ COMMAND_FOLLOW
Definition: UnitDefines.h:561
@ UNIT_FLAG_PLAYER_CONTROLLED
Definition: UnitDefines.h:170
@ UNIT_FLAG_SKINNABLE
Definition: UnitDefines.h:193
@ BASE_VALUE
Definition: Unit.h:155
@ UNIT_MASK_CONTROLABLE_GUARDIAN
Definition: Unit.h:361
@ UNIT_MASK_HUNTER_PET
Definition: Unit.h:360
@ UNIT_MASK_PET
Definition: Unit.h:357
@ MINDAMAGE
Definition: Unit.h:170
@ MAXDAMAGE
Definition: Unit.h:171
UnitMods
Definition: Unit.h:175
@ UNIT_MOD_ARMOR
Definition: Unit.h:207
@ UNIT_MOD_RESISTANCE_START
Definition: Unit.h:223
@ UNIT_MOD_POWER_START
Definition: Unit.h:225
@ UNIT_MOD_STAT_STAMINA
Definition: Unit.h:178
DeathState
Definition: Unit.h:248
@ CORPSE
Definition: Unit.h:251
@ ALIVE
Definition: Unit.h:249
@ JUST_DIED
Definition: Unit.h:250
@ BASE_PCT
Definition: Unit.h:163
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition: Util.h:528
T CalculatePct(T base, U pct)
Definition: Util.h:72
uint32 const Entry[5]
int32 GetMaxDuration() const
Definition: SpellAuras.h:171
static Aura * TryCreate(AuraCreateInfo &createInfo)
Definition: SpellAuras.cpp:389
Trinity::IteratorPair< DBStorageIterator< AuraEffect * > > GetAuraEffects()
Definition: SpellAuras.h:316
uint32 GetId() const
Definition: SpellAuras.h:138
int32 GetDuration() const
Definition: SpellAuras.h:176
uint8 GetStackAmount() const
Definition: SpellAuras.h:192
uint8 GetCharges() const
Definition: SpellAuras.h:183
Difficulty GetCastDifficulty() const
Definition: SpellAuras.h:139
AuraKey GenerateKey(uint32 &recalculateMask) const
Fills a helper structure containing aura primary key for character_aura, character_aura_effect,...
void setDeathState(DeathState s) override
Definition: Creature.cpp:2194
ObjectGuid::LowType m_spawnId
For new or temporary creatures is 0 for saved it is lowguid.
Definition: Creature.h:542
void Update(uint32 time) override
Definition: Creature.cpp:745
CreatureDifficulty const * GetCreatureDifficulty() const
Definition: Creature.h:268
void SetObjectScale(float scale) override
Definition: Creature.cpp:3483
std::string GetNameForLocaleIdx(LocaleConstant locale) const override
Definition: Creature.cpp:3342
bool AIM_Initialize(CreatureAI *ai=nullptr)
Definition: Creature.cpp:1071
void LoadTemplateImmunities(int32 creatureImmunitiesId)
Definition: Creature.cpp:2428
void SetReactState(ReactStates st)
Definition: Creature.h:174
void ApplyLevelScaling()
Definition: Creature.cpp:3041
time_t m_corpseRemoveTime
Definition: Creature.h:530
CreatureTemplate const * GetCreatureTemplate() const
Definition: Creature.h:266
float GetBaseDamageForLevel(uint8 level) const
Definition: Creature.cpp:3079
uint32 m_originalEntry
Definition: Creature.h:552
float GetNativeObjectScale() const override
Definition: Creature.cpp:3478
void SetDisplayId(uint32 displayId, bool setNative=false) override
Definition: Creature.cpp:3494
ReactStates GetReactState() const
Definition: Creature.h:175
bool InitEntry(uint32 entry, CreatureData const *data=nullptr)
Definition: Creature.cpp:496
void SetMeleeDamageSchool(SpellSchools school)
Definition: Creature.h:231
static float GetHealthMod(CreatureClassifications classification)
Definition: Creature.cpp:1674
void Regenerate(Powers power)
Definition: Creature.cpp:945
Class used to access individual fields of database query result.
Definition: Field.h:93
uint8 GetUInt8() const
Definition: Field.cpp:29
std::string GetString() const
Definition: Field.cpp:125
std::span< uint8 const > GetBinaryView() const
Definition: Field.cpp:154
uint32 GetUInt32() const
Definition: Field.cpp:61
int32 GetInt32() const
Definition: Field.cpp:69
void SetBonusDamage(int32 damage)
bool InitStatsForLevel(uint8 level)
Definition: Pet.cpp:839
std::string GetDebugInfo() const override
bool UpdateAllStats() override
Definition: Map.h:223
MapStoredObjectTypesContainer & GetObjectsStore()
Definition: Map.h:456
bool AddToMap(T *)
Definition: Map.cpp:522
ObjectGuid::LowType GenerateLowGuid()
Definition: Map.h:553
Difficulty GetDifficultyID() const
Definition: Map.h:358
uint32 GetId() const
Definition: Map.cpp:3206
Unit * GetOwner() const
float GetFollowAngle() const override
bool IsPetGhoul() const
LowType GetCounter() const
Definition: ObjectGuid.h:296
bool IsEmpty() const
Definition: ObjectGuid.h:322
uint64 GetRawValue(std::size_t i) const
Definition: ObjectGuid.h:285
void SetRawValue(std::span< uint8 const > rawBytes)
Definition: ObjectGuid.cpp:787
static constexpr std::size_t BytesSize
Definition: ObjectGuid.h:279
uint64 LowType
Definition: ObjectGuid.h:281
void Clear()
Definition: ObjectGuid.h:289
bool IsPlayer() const
Definition: Object.h:248
ObjectGuid const & GetGUID() const
Definition: Object.h:196
bool IsInWorld() const
Definition: Object.h:190
TypeID GetTypeId() const
Definition: Object.h:209
void ReplaceAllDynamicFlags(uint32 flag)
Definition: Object.h:207
uint32 GetEntry() const
Definition: Object.h:197
Creature * ToCreature()
Definition: Object.h:257
void _Create(ObjectGuid const &guid)
Definition: Object.cpp:104
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:195
static Player * ToPlayer(Object *o)
Definition: Object.h:249
int32 GetDamage() const
Definition: SpellMgr.h:512
uint32 GetAura(uint32 petEntry) const
Definition: SpellMgr.h:491
bool IsRemovedOnChangePet() const
Definition: SpellMgr.h:507
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:1709
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:1904
uint16 m_petSpecialization
Definition: Pet.h:158
Player * GetOwner() const
Definition: Pet.cpp:1800
bool IsPetAura(Aura const *aura)
Definition: Pet.cpp:1764
bool unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab=true)
Definition: Pet.cpp:1521
bool Create(ObjectGuid::LowType guidlow, Map *map, uint32 Entry, uint32 pet_number)
Definition: Pet.cpp:1679
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:1613
void learnSpells(std::vector< uint32 > const &spellIds)
Definition: Pet.cpp:1468
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:1834
void CastPetAuras(bool current)
Definition: Pet.cpp:1730
void setPetType(PetType type)
Definition: Pet.h:52
void SavePetToDB(PetSaveMode mode)
Definition: Pet.cpp:451
float GetNativeObjectScale() const override
Definition: Pet.cpp:1805
void _SaveAuras(CharacterDatabaseTransaction trans)
Definition: Pet.cpp:1291
PetType getPetType() const
Definition: Pet.h:51
void SynchronizeLevelWithOwner()
Definition: Pet.cpp:1784
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:1776
bool IsPermanentPetFor(Player *owner) const
Definition: Pet.cpp:1656
bool HaveInDiet(ItemTemplate const *item) const
Definition: Pet.cpp:1092
void RemoveSpecializationSpells(bool clearActionBar)
Definition: Pet.cpp:1870
bool addSpell(uint32 spellId, ActiveStates active=ACT_DECIDE, PetSpellState state=PETSPELL_NEW, PetSpellType type=PETSPELL_NORMAL)
Definition: Pet.cpp:1346
AutoSpellList m_autospells
Definition: Pet.h:128
void SetPetExperience(uint32 xp)
Definition: Pet.h:84
std::string GetDebugInfo() const override
Definition: Pet.cpp:1943
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:1824
bool removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab=true)
Definition: Pet.cpp:1552
bool CreateBaseAtCreature(Creature *creature)
Definition: Pet.cpp:768
void CleanupActionBar()
Definition: Pet.cpp:1586
bool isTemporarySummoned() const
Definition: Pet.h:54
void CastPetAura(PetAura const *aura)
Definition: Pet.cpp:1749
void unlearnSpells(std::vector< uint32 > const &spellIds, bool learn_prev, bool clear_ab=true)
Definition: Pet.cpp:1536
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:1843
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:1602
bool HasSpell(uint32 spell) const override
Definition: Pet.cpp:1702
void LearnSpecializationSpells()
Definition: Pet.cpp:1850
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:1930
bool learnSpell(uint32 spell_id)
Definition: Pet.cpp:1452
int32 m_duration
Definition: Pet.h:151
void InitLevelupSpellsForLevel()
Definition: Pet.cpp:1484
static void InheritPhaseShift(WorldObject *target, WorldObject const *source)
void SetGroupUpdateFlag(uint32 flag)
Definition: Player.h:2716
uint32 GetTemporaryUnsummonedPetNumber() const
Definition: Player.h:2645
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6322
UF::UpdateField< UF::ActivePlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_ACTIVE_PLAYER > m_activePlayerData
Definition: Player.h:2968
bool CanTameExoticPets() const
Definition: Player.h:2407
void SetTemporaryUnsummonedPetNumber(uint32 petnumber)
Definition: Player.h:2646
void DisablePetControlsOnMount(ReactStates reactState, CommandStates commandState)
Definition: Player.cpp:27582
void RemoveGroupUpdateFlag(uint32 flag)
Definition: Player.h:2717
bool IsPetNeedBeTemporaryUnsummoned() const
Definition: Player.cpp:27688
PetStable * GetPetStable()
Definition: Player.h:1291
void PetSpellInitialize()
Definition: Player.cpp:22247
Pet * GetPet() const
Definition: Player.cpp:21839
WorldSession * GetSession() const
Definition: Player.h:2195
void RemovePet(Pet *pet, PetSaveMode mode, bool returnreagent=false)
Definition: Player.cpp:21863
Optional< ReactStates > GetTemporaryPetReactState() const
Definition: Player.h:2647
std::unordered_set< PetAura const * > m_petAuras
Definition: Player.h:1306
void RemovePetAura(PetAura const *petSpell)
Definition: Player.cpp:22011
void SetLastPetNumber(uint32 petnumber)
Definition: Player.h:2699
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 SetSize(size_t size)
Definition: QueryHolder.cpp:69
PreparedQueryResult GetPreparedResult(size_t index) const
Definition: QueryHolder.cpp:37
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:382
bool IsAutocastEnabledByDefault() const
Definition: SpellInfo.cpp:1673
bool IsAutocastable() const
Definition: SpellInfo.cpp:1664
uint32 const Id
Definition: SpellInfo.h:322
bool IsPassive() const
Definition: SpellInfo.cpp:1659
uint32 ProcCharges
Definition: SpellInfo.h:376
bool IsRanked() const
Definition: SpellInfo.cpp:4327
bool IsHighRankOf(SpellInfo const *spellInfo) const
Definition: SpellInfo.cpp:4420
uint32 CasterAuraState
Definition: SpellInfo.h:351
bool HasAttribute(SpellAttr0 attribute) const
Definition: SpellInfo.h:449
int32 GetDuration() const
Definition: SpellInfo.cpp:3858
bool IsDifferentRankOf(SpellInfo const *spellInfo) const
Definition: SpellInfo.cpp:4413
bool IsPositive() const
Definition: SpellInfo.cpp:1781
Definition: Unit.h:631
void SetMinion(Minion *minion, bool apply)
Definition: Unit.cpp:6153
bool HasPetFlag(UnitPetFlag flags) const
Definition: Unit.h:887
bool IsHunterPet() const
Definition: Unit.h:748
void SetCreateStat(Stats stat, float val)
Definition: Unit.h:1404
void SetHealth(uint64 val)
Definition: Unit.cpp:9727
Pet * ToPet()
Definition: Unit.h:1794
void SetGender(Gender gender)
Definition: Unit.h:764
void SetFullHealth()
Definition: Unit.h:798
void ReplaceAllNpcFlags2(NPCFlags2 flags)
Definition: Unit.h:1000
ThreatManager & GetThreatManager()
Definition: Unit.h:1073
void AddToWorld() override
Definition: Unit.cpp:9987
uint8 GetClass() const
Definition: Unit.h:760
void SetCreateHealth(uint32 val)
Definition: Unit.h:1405
std::unique_ptr< CharmInfo > m_charmInfo
Definition: Unit.h:1928
void SetFaction(uint32 faction) override
Definition: Unit.h:868
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value)
Definition: Unit.h:1563
ObjectGuid GetOwnerGUID() const override
Definition: Unit.h:1182
void SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val)
Definition: Unit.cpp:9400
void SetPower(Powers power, int32 val, bool withPowerUpdate=true)
Definition: Unit.cpp:9800
void ReplaceAllUnitFlags(UnitFlags flags)
Definition: Unit.h:844
bool IsPet() const
Definition: Unit.h:747
Powers GetPowerType() const
Definition: Unit.h:807
void SetCreatedBySpell(int32 spellId)
Definition: Unit.h:856
Aura * AddAura(uint32 spellId, Unit *target)
Definition: Unit.cpp:12002
void SetUnitFlag2(UnitFlags2 flags)
Definition: Unit.h:847
void ReplaceAllPetFlags(UnitPetFlag flags)
Definition: Unit.h:890
void SetPetNameTimestamp(uint32 timestamp)
Definition: Unit.h:1237
bool IsAlive() const
Definition: Unit.h:1176
float GetCombatReach() const override
Definition: Unit.h:701
DeathState m_deathState
Definition: Unit.h:1882
uint32 m_unitTypeMask
Definition: Unit.h:1939
CharmInfo * GetCharmInfo()
Definition: Unit.h:1233
void SetBaseAttackTime(WeaponAttackType att, uint32 val)
Definition: Unit.cpp:10692
void SetSheath(SheathState sheathed)
Definition: Unit.cpp:5721
void SetCreateMana(uint32 val)
Definition: Unit.h:1407
uint32 GetDisplayId() const
Definition: Unit.h:1600
uint32 GetNativeDisplayId() const
Definition: Unit.h:1603
bool isPossessed() const
Definition: Unit.h:1228
uint64 GetHealth() const
Definition: Unit.h:784
uint32 GetFaction() const override
Definition: Unit.h:867
bool HasAuraState(AuraStateType flag, SpellInfo const *spellProto=nullptr, Unit const *Caster=nullptr) const
Definition: Unit.cpp:6052
bool HasAuraType(AuraType auraType) const
Definition: Unit.cpp:4743
uint32 GetArmor() const
Definition: Unit.h:770
void SetFullPower(Powers power)
Definition: Unit.h:821
bool IsMounted() const
Definition: Unit.h:907
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition: Unit.h:1858
int32 GetPower(Powers power) const
Definition: Unit.cpp:9782
float GetTotalAttackPowerValue(WeaponAttackType attType, bool includeWeapon=true) const
Definition: Unit.cpp:9666
DeathState getDeathState() const
Definition: Unit.h:1179
bool IsCritter() const
Definition: Unit.h:1020
AuraMap m_ownedAuras
Definition: Unit.h:1900
void SetLevel(uint8 lvl, bool sendUpdate=true)
Definition: Unit.cpp:9710
void SetCanModifyStats(bool modifyStats)
Definition: Unit.h:1539
CharmInfo * InitCharmInfo()
Definition: Unit.cpp:10132
void SetClass(uint8 classId)
Definition: Unit.h:761
void RemoveFromWorld() override
Definition: Unit.cpp:9995
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4733
Powers CalculateDisplayPowerType() const
Definition: Unit.cpp:5670
float GetStat(Stats stat) const
Definition: Unit.h:768
void RemoveAllAuras()
Definition: Unit.cpp:4311
SpellHistory * GetSpellHistory()
Definition: Unit.h:1488
void SetCreatorGUID(ObjectGuid creator)
Definition: Unit.h:1185
void ReplaceAllNpcFlags(NPCFlags flags)
Definition: Unit.h:994
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
Definition: Unit.cpp:6990
void SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val)
Definition: Unit.cpp:9391
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3897
void SetPowerType(Powers power, bool sendUpdate=true, bool onInit=false)
Definition: Unit.cpp:5605
uint8 GetLevel() const
Definition: Unit.h:753
void RemoveUnitFlag(UnitFlags flags)
Definition: Unit.h:843
ObjectGuid GetPetGUID() const
Definition: Unit.h:1188
constexpr uint32 GetMapId() const
Definition: Position.h:215
Map * GetMap() const
Definition: Object.h:762
std::string m_name
Definition: Object.h:935
InstanceScript * GetInstanceScript() const
Definition: Object.cpp:1107
void GetClosePoint(float &x, float &y, float &z, float size, float distance2d=0, float relAngle=0) const
Definition: Object.cpp:3517
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2993
ZoneScript * GetZoneScript() const
Definition: Object.h:768
std::string const & GetName() const
Definition: Object.h:693
virtual void SetMap(Map *map)
Definition: Object.cpp:1865
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition: Object.cpp:1212
void SetName(std::string newname)
Definition: Object.h:694
float GetVisibilityRange() const
Definition: Object.cpp:1512
WorldPacket const * Write() override
Definition: PetPackets.cpp:64
std::vector< uint32 > Spells
Definition: PetPackets.h:149
WorldPacket const * Write() override
Definition: PetPackets.cpp:72
WorldPacket const * Write() override
Definition: PetPackets.cpp:175
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:927
@ CONFIG_MAX_PLAYER_LEVEL
Definition: World.h:258
void apply(T *val)
Definition: ByteConverter.h:41
time_t GetGameTime()
Definition: GameTime.cpp:44
AuraCreateInfo & SetBaseAmount(int32 const *bp)
AuraCreateInfo & SetCasterGUID(ObjectGuid const &guid)
uint32 SpellId
Definition: SpellAuras.h:109
ObjectGuid Caster
Definition: SpellAuras.h:107
uint32 EffectMask
Definition: SpellAuras.h:110
std::array< int32, MAX_SPELL_EFFECTS > BaseAmounts
Definition: SpellAuras.h:118
std::array< int32, MAX_SPELL_EFFECTS > Amounts
Definition: SpellAuras.h:117
TriggerCastFlags TriggerFlags
Definition: SpellDefines.h:465
CastSpellExtraArgs & AddSpellMod(SpellValueMod mod, int32 val)
Definition: SpellDefines.h:519
void SetIsCommandFollow(bool val)
Definition: Unit.cpp:12986
void SetIsAtStay(bool val)
Definition: Unit.cpp:13017
void SetIsFollowing(bool val)
Definition: Unit.cpp:13027
void SetIsReturning(bool val)
Definition: Unit.cpp:13037
void SetIsCommandAttack(bool val)
Definition: Unit.cpp:12976
int32 GetHealthScalingExpansion() const
Definition: CreatureData.h:468
CreatureDifficulty const * GetDifficulty(Difficulty difficulty) const
Definition: Creature.cpp:244
CreatureClassifications Classification
Definition: CreatureData.h:506
CreatureFamily family
Definition: CreatureData.h:516
int32 resistance[MAX_SPELL_SCHOOL]
Definition: CreatureData.h:519
bool IsTameable(bool canTameExotic, CreatureDifficulty const *creatureDifficulty) const
Definition: CreatureData.h:550
uint32 FoodType
Definition: ItemTemplate.h:873
uint16 health
Definition: ObjectMgr.h:685
uint16 armor
Definition: ObjectMgr.h:687
uint16 stats[MAX_STATS]
Definition: ObjectMgr.h:684
uint16 mana
Definition: ObjectMgr.h:686
Definition: Pet.h:27
PetSpellState state
Definition: Pet.h:29
PetSpellType type
Definition: Pet.h:30
ActiveStates active
Definition: Pet.h:28
uint32 CreatedBySpellId
Definition: PetDefines.h:160
ReactStates ReactState
Definition: PetDefines.h:163
std::string Name
Definition: PetDefines.h:151
uint16 SpecializationId
Definition: PetDefines.h:161
std::string ActionBar
Definition: PetDefines.h:152
constexpr float GetPositionX() const
Definition: Position.h:86
constexpr float GetPositionY() const
Definition: Position.h:87
std::string ToString() const
Definition: Position.cpp:199
bool IsPositionValid() const
Definition: Position.cpp:42
constexpr void Relocate(float x, float y)
Definition: Position.h:73
constexpr float GetOrientation() const
Definition: Position.h:89
constexpr float GetPositionZ() const
Definition: Position.h:88
bool Remove(ObjectType *object)
Definition: TypeContainer.h:75
bool Insert(ObjectType *object)
Definition: TypeContainer.h:69