OregonCore  revision 3611e8a-git
Your Favourite TBC server
Pet.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore 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 "Common.h"
19 #include "Database/DatabaseEnv.h"
20 #include "Log.h"
21 #include "WorldSession.h"
22 #include "WorldPacket.h"
23 #include "ObjectMgr.h"
24 #include "SpellMgr.h"
25 #include "Pet.h"
26 #include "MapManager.h"
27 #include "Formulas.h"
28 #include "SpellAuras.h"
29 #include "Unit.h"
30 #include "Util.h"
31 
32 
33 //numbers represent minutes * 100 while happy (you get 100 loyalty points per min while happy)
35 {
36  5500,
37  11500,
38  17000,
39  23500,
40  31000,
41  39500,
42 };
43 
45 {
46  2000,
47  4500,
48  7000,
49  10000,
50  13500,
51  17500,
52 };
53 
54 Pet::Pet(Player* owner, PetType type) : Guardian(NULL, owner, true),
55  m_resetTalentsCost(0), m_resetTalentsTime(0),
56  m_removed(false), m_owner(owner), m_happinessTimer(7500),
57  m_petType(type), m_duration(0), m_declinedname(NULL),
58  m_petModeFlags(PET_MODE_DEFAULT)
59 {
61  if (type == HUNTER_PET)
63 
65  {
67  InitCharmInfo();
68  }
69 
70  if (type == CLASS_PET)
72 
73  m_name = "Pet";
74 
75  m_regenTimer = 4000;
76  m_loyaltyTimer = 12000;
77 
78  m_loyaltyPoints = 0;
79  m_TrainingPoints = 0;
80 
81  m_auraUpdateMask = 0;
82 
83  m_spells.clear();
84  m_Auras.clear();
87  m_autospells.clear();
88 
89  m_wasOutdoors = false;
91 }
92 
94 {
95  delete m_declinedname;
96 }
97 
99 {
100  // Register the pet for guid lookup
101  if (!IsInWorld())
102  {
105  AIM_Initialize();
106  }
107 
108  // Prevent stuck pets when zoning. Pets default to "follow" when added to world
109  // so we'll reset flags and let the AI handle things
110  if (GetCharmInfo() && GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
111  {
114  GetCharmInfo()->SetIsAtStay(false);
115  GetCharmInfo()->SetIsFollowing(false);
116  GetCharmInfo()->SetIsReturning(false);
117  }
118 }
119 
121 {
122  // Remove the pet from the accessor
123  if (IsInWorld())
124  {
125  // Don't call the function for Creature, normal mobs + totems go in a different storage
128  }
129 }
130 
131 bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool current)
132 {
133  uint32 ownerid = owner->GetGUIDLow();
134 
135  QueryResult_AutoPtr result;
136 
137  if (petnumber)
138  // known petnumber entry 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
139  result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'", ownerid, petnumber);
140  else if (current)
141  // current pet (slot 0) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
142  result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'", ownerid);
143  else if (petentry)
144  // known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets)
145  // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
146  result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ", ownerid, petentry);
147  else
148  // any current or other non-stabled pet (for hunter "call pet")
149  // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
150  result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ", ownerid);
151 
152  if (!result)
153  return false;
154 
155  Field* fields = result->Fetch();
156 
157  // update for case of current pet "slot = 0"
158  petentry = fields[1].GetUInt32();
159  if (!petentry)
160  return false;
161 
162  uint32 summon_spell_id = fields[21].GetUInt32();
163  SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id);
164 
165  bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0;
166 
167  // check temporary summoned pets like mage water elemental
168  if (current && is_temporary_summoned)
169  return false;
170 
171  Map* map = owner->GetMap();
172  uint32 guid = sObjectMgr.GenerateLowGuid(HIGHGUID_PET);
173  uint32 pet_number = fields[0].GetUInt32();
174  if (!Create(guid, map, petentry, pet_number))
175  return false;
176 
177  float px, py, pz;
179 
180  Relocate(px, py, pz, owner->GetOrientation());
181 
182  if (!IsPositionValid())
183  {
184  sLog.outError("Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)",
186  return false;
187  }
188 
189  setPetType(PetType(fields[22].GetUInt8()));
191  SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id);
192 
193  CreatureInfo const* cinfo = GetCreatureTemplate();
194  if (cinfo->type == CREATURE_TYPE_CRITTER)
195  {
196  map->AddToMap(ToCreature());
197  return true;
198  }
199 
200  m_charmInfo->SetPetNumber(pet_number, IsPermanentPetFor(owner));
201 
202  SetDisplayId(fields[3].GetUInt32());
203  SetNativeDisplayId(fields[3].GetUInt32());
204  uint32 petlevel = fields[4].GetUInt32();
206  SetName(fields[11].GetString());
207 
208  switch (getPetType())
209  {
210  case SUMMON_PET:
211  petlevel = owner->getLevel();
212 
215  // this enables popup window (pet dismiss, cancel)
216  break;
217  case HUNTER_PET:
218  SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100);
219  SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[8].GetUInt32());
222 
223  if (fields[12].GetBool())
225  else
227 
229  // this enables popup window (pet abandon, cancel)
230  SetTP(fields[9].GetInt32());
232  SetPower( POWER_HAPPINESS, fields[15].GetUInt32());
234  break;
235  default:
236  sLog.outError("Pet has incorrect type (%u) for pet loading.", getPetType());
237  }
238 
240  SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32());
242 
243  SetReactState(ReactStates(fields[6].GetUInt8()));
244  m_loyaltyPoints = fields[7].GetInt32();
245 
246  SetCanModifyStats(true);
247  InitStatsForLevel(petlevel);
248 
249  if (getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current
250  {
253  }
254  else
255  {
256  uint32 savedhealth = fields[13].GetUInt32();
257  uint32 savedmana = fields[14].GetUInt32();
258  if (!savedhealth && getPetType() == HUNTER_PET)
260  else
261  {
262  SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : (!savedhealth ? 1 : savedhealth));
263  SetPower(POWER_MANA, savedmana > GetMaxPower(POWER_MANA) ? GetMaxPower(POWER_MANA) : savedmana);
264  }
265  }
266 
267  // set current pet as current
268  if (fields[10].GetUInt32() != 0)
269  {
271  CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'", ownerid, m_charmInfo->GetPetNumber());
272  CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'", ownerid, m_charmInfo->GetPetNumber());
274  }
275 
276  if (!is_temporary_summoned)
277  {
278  // permanent controlled pets store state in DB
279  Tokens tokens = StrSplit(fields[16].GetString(), " ");
280 
281  if (tokens.size() != 20)
282  return false;
283 
284  int index;
285  Tokens::iterator iter;
286  for (iter = tokens.begin(), index = 0; index < 10; ++iter, ++index)
287  {
288  m_charmInfo->GetActionBarEntry(index)->Type = atol((*iter).c_str());
289  ++iter;
290  m_charmInfo->GetActionBarEntry(index)->SpellOrAction = atol((*iter).c_str());
293  }
294 
295  //init teach spells
296  tokens = StrSplit(fields[17].GetString(), " ");
297  for (iter = tokens.begin(), index = 0; index < 4; ++iter, ++index)
298  {
299  uint32 tmp = atol((*iter).c_str());
300 
301  ++iter;
302 
303  if (tmp)
304  AddTeachSpell(tmp, atol((*iter).c_str()));
305  else
306  break;
307  }
308  }
309 
310  owner->SetMinion(this, true);
311  map->AddToMap(ToCreature());
312 
313  uint32 timediff = (time(NULL) - fields[18].GetUInt32());
314  _LoadAuras(timediff);
315 
316  if (!is_temporary_summoned)
317  {
318  _LoadSpells();
321  if (map->IsBattleArena())
323 
324  CastPetAuras(current);
325  }
326 
327  sLog.outDebug("New Pet has guid %u", GetGUIDLow());
328 
329  owner->PetSpellInitialize();
330 
331  if (owner->GetGroup())
333 
334  if (getPetType() == HUNTER_PET)
335  {
336  result = CharacterDatabase.PQuery("SELECT genitive, dative, accusative, instrumental, prepositional FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", owner->GetGUIDLow(), GetCharmInfo()->GetPetNumber());
337 
338  if (result)
339  {
340  delete m_declinedname;
341 
343  Field* fields = result->Fetch();
344  for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i)
345  m_declinedname->name[i] = fields[i].GetCppString();
346  }
347 
348  // set speed to be at least the base character speed.
349  // pet shoudln't sync its speed with master because some of its
350  // talents wouldn't be useful at all i.e. speed boosts, but the pet
351  // should be also able to follow its master at normal speed levels
352  for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
354  SetSpeed(UnitMoveType(i), baseMoveSpeed[i], true);
355  }
356 
357  //set last used pet number (for use in BG's)
359  owner->ToPlayer()->SetLastPetNumber(pet_number);
360 
361  return true;
362 }
363 
365 {
366  if (!GetEntry() || !m_charmInfo)
367  return;
368 
369  // save only fully controlled creature
370  if (!isControlled())
371  return;
372 
373  uint32 curhealth = GetHealth();
374  uint32 curmana = GetPower(POWER_MANA);
375 
376  switch (mode)
377  {
381  {
382  RemoveAllAuras();
383 
384  //only alive hunter pets get auras saved, the others don't
385  if (!(getPetType() == HUNTER_PET && IsAlive()))
386  m_Auras.clear();
387  }
388  default:
389  break;
390  }
391 
392  _SaveSpells();
394  _SaveAuras();
395 
396  switch (mode)
397  {
398  case PET_SAVE_AS_CURRENT:
402  {
403  uint32 owner = GUID_LOPART(GetOwnerGUID());
404  std::string name = m_name;
407  // remove current data
408  CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND id = '%u'", owner, m_charmInfo->GetPetNumber());
409 
410  // prevent duplicate using slot (except PET_SAVE_NOT_IN_SLOT)
411  if (mode != PET_SAVE_NOT_IN_SLOT)
412  CharacterDatabase.PExecute("UPDATE character_pet SET slot = 3 WHERE owner = '%u' AND slot = '%u'", owner, uint32(mode));
413 
414  // prevent existence another hunter pet in PET_SAVE_AS_CURRENT and PET_SAVE_NOT_IN_SLOT
415  if (getPetType() == HUNTER_PET && (mode == PET_SAVE_AS_CURRENT || mode == PET_SAVE_NOT_IN_SLOT))
416  CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3')", owner);
417  // save pet
418  std::ostringstream ss;
419  ss << "INSERT INTO character_pet (id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata,TeachSpelldata,savetime,resettalents_cost,resettalents_time,CreatedBySpell,PetType) "
420  << "VALUES ("
421  << m_charmInfo->GetPetNumber() << ", "
422  << GetEntry() << ", "
423  << owner << ", "
424  << GetNativeDisplayId() << ", "
425  << getLevel() << ", "
427  << uint32(GetReactState()) << ", "
428  << m_loyaltyPoints << ", "
429  << GetLoyaltyLevel() << ", "
430  << m_TrainingPoints << ", "
431  << uint32(mode) << ", '"
432  << name.c_str() << "', "
433  << uint32((GetByteValue(UNIT_FIELD_BYTES_2, 2) == UNIT_RENAME_ALLOWED) ? 0 : 1) << ", "
434  << curhealth << ", "
435  << curmana << ", "
436  << GetPower(POWER_HAPPINESS) << ", '";
437 
438  for (uint32 i = 0; i < 10; i++)
440  ss << "', '";
441 
442  //save spells the pet can teach to it's Master
443  {
444  int i = 0;
445  for (TeachSpellMap::iterator itr = m_teachspells.begin(); i < 4 && itr != m_teachspells.end(); ++i, ++itr)
446  ss << itr->first << " " << itr->second << " ";
447  for (; i < 4; ++i)
448  ss << uint32(0) << " " << uint32(0) << " ";
449  }
450 
451  ss << "', "
452  << time(NULL) << ", "
453  << uint32(m_resetTalentsCost) << ", "
454  << uint64(m_resetTalentsTime) << ", "
456  << uint32(getPetType()) << ")";
457 
458  CharacterDatabase.Execute(ss.str().c_str());
459 
461  break;
462  }
463  case PET_SAVE_AS_DELETED:
464  {
465  RemoveAllAuras();
467  break;
468  }
469  default:
470  sLog.outError("Unknown pet save/remove mode: %d", mode);
471  }
472 }
473 
475 {
476  CharacterDatabase.PExecute("DELETE FROM character_pet WHERE id = '%u'", guidlow);
477  CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE id = '%u'", guidlow);
478  CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'", guidlow);
479  CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u'", guidlow);
480  CharacterDatabase.PExecute("DELETE FROM pet_spell_cooldown WHERE guid = '%u'", guidlow);
481 }
482 
483 void Pet::setDeathState(DeathState s) // overwrite virtual Creature::setDeathState and Unit::setDeathState
484 {
486  if (getDeathState() == CORPSE)
487  {
488  if (getPetType() == HUNTER_PET)
489  {
490  // Pet has just died, update it's status
491  if (Player* owner = GetOwner())
492  owner->SetPetStatus(PET_STATUS_DEAD);
493 
494  // pet corpse non lootable and non skinnable
497 
498  // lose happiness when died and not in BG/Arena
499  MapEntry const* mapEntry = sMapStore.LookupEntry(GetMapId());
500  if (!mapEntry || !mapEntry->IsBattlegroundOrArena())
502 
504  }
505  }
506  else if (getDeathState() == ALIVE)
507  {
509  CastPetAuras(true);
510  }
511 }
512 
513 void Pet::Update(uint32 diff)
514 {
515  if (m_removed) // pet already removed, just wait in remove queue, no updates
516  return;
517 
518  switch (m_deathState)
519  {
520  case CORPSE:
521  {
522  if (getPetType() != HUNTER_PET || m_corpseRemoveTime <= uint32(time(NULL)))
523  {
524  Remove(PET_SAVE_NOT_IN_SLOT); //hunters' pets never get removed because of death, NEVER!
525  return;
526  }
527  break;
528  }
529  case ALIVE:
530  {
531  // unsummon pet that lost owner
532  Player* owner = GetOwner();
533  if (!owner || (!IsWithinDistInMap(owner, GetMap()->GetVisibilityRange()) && !isPossessed()) || (isControlled() && !owner->GetPetGUID()))
534  {
535  sLog.outError("Pet %u is not pet of owner %u, removed", GetEntry(), m_owner->GetGUIDLow());
537  return;
538  }
539 
540  if (isControlled())
541  {
542  if (owner->GetPetGUID() != GetGUID())
543  {
545  return;
546  }
547  }
548 
549  if (m_duration > 0)
550  {
551  if (m_duration > int32(diff))
552  m_duration -= diff;
553  else
554  {
556  return;
557  }
558  }
559 
560  if (getPetType() != HUNTER_PET)
561  break;
562 
563  //regenerate Focus
564  if (m_regenTimer <= diff)
565  {
566  RegenerateFocus();
567  m_regenTimer = 4000;
568  }
569  else
570  m_regenTimer -= diff;
571 
572  if (m_happinessTimer <= diff)
573  {
574  LoseHappiness();
575  m_happinessTimer = 7500;
576  }
577  else
578  m_happinessTimer -= diff;
579 
580  if (m_loyaltyTimer <= diff)
581  {
583  m_loyaltyTimer = 12000;
584  }
585  else
586  m_loyaltyTimer -= diff;
587 
588  break;
589  }
590  default:
591  break;
592  }
593 
594  // Handle outdoor movements speed bonuses (every 1sec check for change)
595  if (m_owner)
596  {
597  if (m_outdoorBonusCheckTimer <= diff)
598  {
599  bool isOutdoor = GetMap()->IsOutdoors(GetPositionX(), GetPositionY(), GetPositionZ());
600  if ((isOutdoor && !m_wasOutdoors) || (!isOutdoor && m_wasOutdoors))
601  {
603  for (AuraList::const_iterator it = auras.begin(); it != auras.end(); it++)
604  (*it)->ApplyModifier(isOutdoor);
605  m_wasOutdoors = isOutdoor;
606  }
608  }
609  else
610  m_outdoorBonusCheckTimer -= diff;
611  }
612 
613  Creature::Update(diff);
614 }
615 
617 {
618  uint32 curValue = GetPower(POWER_FOCUS);
619  uint32 maxValue = GetMaxPower(POWER_FOCUS);
620 
621  if (curValue >= maxValue)
622  return;
623 
624  float addvalue = 24 * sWorld.getRate(RATE_POWER_FOCUS);
625 
626  AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT);
627  for (AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i)
628  if ((*i)->GetModifier()->m_miscvalue == POWER_FOCUS)
629  addvalue *= ((*i)->GetModifierValue() + 100) / 100.0f;
630 
631  ModifyPower(POWER_FOCUS, (int32)addvalue);
632 }
633 
635 {
636  uint32 curValue = GetPower(POWER_HAPPINESS);
637  if (curValue <= 0)
638  return;
639  int32 addvalue = (140 >> GetLoyaltyLevel()) * 125; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs)
640  if (IsInCombat()) //we know in combat happiness fades faster, multiplier guess
641  addvalue = int32(addvalue * 1.5);
642  ModifyPower(POWER_HAPPINESS, -addvalue);
643 }
644 
645 void Pet::ModifyLoyalty(int32 addvalue)
646 {
647  uint32 loyaltylevel = GetLoyaltyLevel();
648 
649  if (addvalue > 0) //only gain influenced, not loss
650  addvalue = int32((float)addvalue * sWorld.getRate(RATE_LOYALTY));
651 
652  if (loyaltylevel >= BEST_FRIEND && (addvalue + m_loyaltyPoints) > int32(GetMaxLoyaltyPoints(loyaltylevel)))
653  return;
654 
655  m_loyaltyPoints += addvalue;
656 
657  if (m_loyaltyPoints < 0)
658  {
659  if (loyaltylevel > REBELLIOUS)
660  {
661  //level down
662  --loyaltylevel;
663  SetLoyaltyLevel(LoyaltyLevel(loyaltylevel));
664  m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel);
666  }
667  else
668  {
669  m_loyaltyPoints = 0;
670  Unit* owner = GetOwner();
671  if (owner && owner->GetTypeId() == TYPEID_PLAYER)
672  {
673  WorldPacket data(SMSG_PET_BROKEN, 0);
674  owner->ToPlayer()->GetSession()->SendPacket(&data);
675 
676  //run away
677  owner->ToPlayer()->RemovePet(this, PET_SAVE_AS_DELETED);
678  }
679  }
680  }
681  //level up
682  else if (m_loyaltyPoints > int32(GetMaxLoyaltyPoints(loyaltylevel)))
683  {
684  ++loyaltylevel;
685  SetLoyaltyLevel(LoyaltyLevel(loyaltylevel));
686  m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel);
688  }
689 }
690 
692 {
693  int32 addvalue;
694 
695  switch (GetHappinessState())
696  {
697  case HAPPY:
698  addvalue = 20;
699  break;
700  case CONTENT:
701  addvalue = 10;
702  break;
703  case UNHAPPY:
704  addvalue = -20;
705  break;
706  default:
707  return;
708  }
709  ModifyLoyalty(addvalue);
710 }
711 
713 {
714  if (level > 100)
715  return;
716 
717  //at lower levels gain is faster | the lower loyalty the more loyalty is gained
718  uint32 bonus = uint32(((100 - level) / 10) + (6 - GetLoyaltyLevel()));
719  ModifyLoyalty(bonus);
720 }
721 
723 {
725  return UNHAPPY;
727  return HAPPY;
728  else
729  return CONTENT;
730 }
731 
733 {
734  SetByteValue(UNIT_FIELD_BYTES_1, 1, level);
735 }
736 
738 {
739  uint8 activecount = 1;
740  uint32 chainstartstore[ACTIVE_SPELLS_MAX];
741 
742  if (IsPassiveSpell(spellid))
743  return true;
744 
745  chainstartstore[0] = sSpellMgr.GetFirstSpellInChain(spellid);
746 
747  for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
748  {
749  if (IsPassiveSpell(itr->first))
750  continue;
751 
752  uint32 chainstart = sSpellMgr.GetFirstSpellInChain(itr->first);
753 
754  uint8 x;
755 
756  for (x = 0; x < activecount; x++)
757  {
758  if (chainstart == chainstartstore[x])
759  break;
760  }
761 
762  if (x == activecount) //spellchain not yet saved -> add active count
763  {
764  ++activecount;
765  if (activecount > ACTIVE_SPELLS_MAX)
766  return false;
767  chainstartstore[x] = chainstart;
768  }
769  }
770  return true;
771 }
772 
774 {
775  int32 neededtrainp = GetTPForSpell(spellid);
776  if ((m_TrainingPoints - neededtrainp < 0 || neededtrainp < 0) && neededtrainp != 0)
777  return false;
778  return true;
779 }
780 
782 {
783  uint32 basetrainp = 0;
784 
785  SkillLineAbilityMap::const_iterator lower = sSpellMgr.GetBeginSkillLineAbilityMap(spellid);
786  SkillLineAbilityMap::const_iterator upper = sSpellMgr.GetEndSkillLineAbilityMap(spellid);
787  for (SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
788  {
789  if (!_spell_idx->second->reqtrainpoints)
790  return 0;
791 
792  basetrainp = _spell_idx->second->reqtrainpoints;
793  break;
794  }
795 
796  uint32 spenttrainp = 0;
797  uint32 chainstart = sSpellMgr.GetFirstSpellInChain(spellid);
798 
799  for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
800  {
801  if (itr->second.state == PETSPELL_REMOVED)
802  continue;
803 
804  if (sSpellMgr.GetFirstSpellInChain(itr->first) == chainstart)
805  {
806  SkillLineAbilityMap::const_iterator _lower = sSpellMgr.GetBeginSkillLineAbilityMap(itr->first);
807  SkillLineAbilityMap::const_iterator _upper = sSpellMgr.GetEndSkillLineAbilityMap(itr->first);
808 
809  for (SkillLineAbilityMap::const_iterator _spell_idx2 = _lower; _spell_idx2 != _upper; ++_spell_idx2)
810  {
811  if (_spell_idx2->second->reqtrainpoints > spenttrainp)
812  {
813  spenttrainp = _spell_idx2->second->reqtrainpoints;
814  break;
815  }
816  }
817  }
818  }
819 
820  return int32(basetrainp) - int32(spenttrainp);
821 }
822 
824 {
825  if (level < 1) level = 1; // prevent SIGSEGV (out of range)
826  if (level > 7) level = 7; // prevent SIGSEGV (out of range)
827  return LevelUpLoyalty[level - 1];
828 }
829 
831 {
832  if (level < 1) level = 1; // prevent SIGSEGV (out of range)
833  if (level > 7) level = 7; // prevent SIGSEGV (out of range)
834  return LevelStartLoyalty[level - 1];
835 }
836 
838 {
839  m_TrainingPoints = TP;
841 }
842 
844 {
845  if (getPetType() != HUNTER_PET)
846  return (0);
847  if (m_TrainingPoints < 0)
848  return -m_TrainingPoints;
849  else
850  return -(m_TrainingPoints + 1);
851 }
852 
853 void Pet::Remove(PetSaveMode mode, bool returnreagent)
854 {
855  m_owner->RemovePet(this, mode, returnreagent);
856 }
857 
859 {
860  if (getPetType() != HUNTER_PET)
861  return;
862 
863  if (xp < 1)
864  return;
865 
866  if (!IsAlive())
867  return;
868 
869  uint32 level = getLevel();
870  uint32 maxlevel = std::min(sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL), GetOwner()->getLevel());
871 
874  uint32 newXP = curXP + xp;
875 
876  // Don't give pet next level if current pet level = player level.
877  if(newXP >= nextLvlXP && level >= maxlevel)
878  return;
879 
880  while (newXP >= nextLvlXP && level < maxlevel)
881  {
882  newXP -= nextLvlXP;
883  ++level;
884 
885  GivePetLevel(level); // also update UNIT_FIELD_PETNEXTLEVELEXP and UNIT_FIELD_PETEXPERIENCE to level start
886 
888  }
889 
890  SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, level <= maxlevel ? newXP : 0);
891 
892  if (getPetType() == HUNTER_PET)
893  KillLoyaltyBonus(level);
894 }
895 
897 {
898  if (!level || level == getLevel())
899  return;
900 
901  InitStatsForLevel(level);
903 }
904 
906 {
907  if (!creature)
908  {
909  sLog.outError("CRITICAL ERROR: NULL pointer parsed into CreateBaseAtCreature()");
910  return false;
911  }
912  uint32 guid = sObjectMgr.GenerateLowGuid(HIGHGUID_PET);
913 
914  sLog.outDebug("Create pet");
915  uint32 pet_number = sObjectMgr.GeneratePetNumber();
916  if (!Create(guid, creature->GetMap(), creature->GetEntry(), pet_number))
917  return false;
918 
919  Relocate(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation());
920 
921  if (!IsPositionValid())
922  {
923  sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
925  return false;
926  }
927 
928  CreatureInfo const* cinfo = GetCreatureTemplate();
929  if (!cinfo)
930  {
931  sLog.outError("CreateBaseAtCreature() failed, creatureInfo is missing!");
932  return false;
933  }
934 
935  SetDisplayId(creature->GetDisplayId());
938  SetPower(POWER_HAPPINESS, 166500);
945 
946  CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(creature->GetCreatureTemplate()->family);
947  if (char* familyname = cFamily->Name[sWorld.GetDefaultDbcLocale()])
948  SetName(familyname);
949  else
950  SetName(creature->GetName());
951 
952  m_loyaltyPoints = 1000;
953  if (cinfo->type == CREATURE_TYPE_BEAST)
954  {
955  SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100);
959 
962  }
963  return true;
964 }
965 
967 {
968  CreatureInfo const* cinfo = GetCreatureTemplate();
969  ASSERT(cinfo);
970 
971  SetLevel(petlevel);
972 
973  //Determine pet type
974  PetType petType = MAX_PET_TYPE;
975  if (IsPet() && m_owner->GetTypeId() == TYPEID_PLAYER)
976  {
977  if ((m_owner->getClass() == CLASS_WARLOCK)
978  || (m_owner->getClass() == CLASS_SHAMAN) // Fire Elemental
979  || (m_owner->getClass() == CLASS_MAGE) // Water Elemental
980  || (m_owner->getClass() == CLASS_PRIEST)) // Shadowfiend
981  petType = SUMMON_PET;
982  else if (m_owner->getClass() == CLASS_HUNTER)
983  {
984  petType = HUNTER_PET;
986  }
987  else
988  sLog.outError("Unknown type pet %u is summoned by player class %u", GetEntry(), m_owner->getClass());
989  }
990 
991  uint32 creature_ID = (petType == HUNTER_PET) ? 1 : cinfo->Entry;
992 
994 
995  SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
996 
1000 
1002 
1003  //scale
1004  CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family);
1005  if (cFamily && cFamily->minScale > 0.0f && petType == HUNTER_PET)
1006  {
1007  float scale;
1008  if (getLevel() >= cFamily->maxScaleLevel)
1009  scale = cFamily->maxScale;
1010  else if (getLevel() <= cFamily->minScaleLevel)
1011  scale = cFamily->minScale;
1012  else
1013  scale = cFamily->minScale + float(getLevel() - (float)cFamily->minScaleLevel) / (float)cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale);
1014 
1015  SetObjectScale(scale);
1016  }
1017 
1018  //resistance
1019  int32 createResistance[MAX_SPELL_SCHOOL] = {0, 0, 0, 0, 0, 0, 0};
1020  if (petType != HUNTER_PET)
1021  {
1022  createResistance[SPELL_SCHOOL_HOLY] = cinfo->resistance1;
1023  createResistance[SPELL_SCHOOL_FIRE] = cinfo->resistance2;
1024  createResistance[SPELL_SCHOOL_NATURE] = cinfo->resistance3;
1025  createResistance[SPELL_SCHOOL_FROST] = cinfo->resistance4;
1026  createResistance[SPELL_SCHOOL_SHADOW] = cinfo->resistance5;
1027  createResistance[SPELL_SCHOOL_ARCANE] = cinfo->resistance6;
1028  }
1029  for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
1030  SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i]));
1031 
1032  //health, mana, armor and resistance
1033  PetLevelInfo const* pInfo = sObjectMgr.GetPetLevelInfo(creature_ID, petlevel);
1034  if (pInfo) // exist in DB
1035  {
1036  SetCreateHealth(pInfo->health);
1037  if (petType != HUNTER_PET) //hunter pet use focus
1038  SetCreateMana(pInfo->mana);
1039 
1040  if (pInfo->armor > 0)
1042 
1043  for (uint8 stat = 0; stat < MAX_STATS; ++stat)
1044  SetCreateStat(Stats(stat), float(pInfo->stats[stat]));
1045  }
1046  else // not exist in DB, use some default fake data
1047  {
1048  // remove elite bonuses included in DB values
1049  //SetCreateHealth(uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel));
1050  //SetCreateMana(uint32(((float(cinfo->maxmana) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel));
1051 
1057  }
1058 
1059  m_bonusdamage = 0;
1060  switch (petType)
1061  {
1062  case SUMMON_PET:
1063  {
1064  if (m_owner->GetTypeId() == TYPEID_PLAYER)
1065  {
1066  switch (m_owner->getClass())
1067  {
1068  case CLASS_WARLOCK:
1069  {
1070 
1071  //the damage bonus used for pets is either fire or shadow damage, whatever is higher
1074  uint32 val = (fire > shadow) ? fire : shadow;
1075 
1076  SetBonusDamage(int32 (val * 0.15f));
1077  //bonusAP += val * 0.57;
1078  break;
1079  }
1080  case CLASS_MAGE:
1081  {
1083 
1084  //40% damage bonus of mage's frost damage
1086  if (val < 0)
1087  val = 0;
1088  SetBonusDamage(int32(val));
1089  break;
1090  }
1091  default:
1092  break;
1093  }
1094  }
1095 
1096  SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
1097  SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
1098 
1099  //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower));
1100  break;
1101  }
1102  case HUNTER_PET:
1103  {
1105 
1106  //these formula may not be correct; however, it is designed to be close to what it should be
1107  //this makes dps 0.5 of pets level
1108  SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
1109  //damage range is then petlevel / 2
1110  SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
1111  //damage is increased afterwards as strength and pet scaling modify attack power
1112  break;
1113  }
1114  default:
1115  {
1116  switch (GetEntry())
1117  {
1118  case 1964: //force of nature
1119  {
1120  if (!pInfo)
1121  SetCreateHealth(30 + 30 * petlevel);
1122  SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 2.5f - (petlevel / 2)));
1123  SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 2.5f + (petlevel / 2)));
1124  break;
1125  }
1126  case 15352: //earth elemental 36213
1127  {
1129 
1130  if (!pInfo)
1131  SetCreateHealth(100 + 120 * petlevel);
1132  SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
1133  SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
1134  break;
1135  }
1136  case 15438: //fire elemental
1137  {
1139 
1140  if (!pInfo)
1141  {
1142  SetCreateHealth(40 * petlevel);
1143  SetCreateMana(28 + 10 * petlevel);
1144  }
1145  SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 4 - petlevel));
1146  SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 4 + petlevel));
1147  break;
1148  }
1149  case 19668: // Shadowfiend
1150  {
1151  if (!pInfo)
1152  {
1153  SetCreateMana(28 + 10 * petlevel);
1154  SetCreateHealth(28 + 30 * petlevel);
1155  }
1157  SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel) + bonus_dmg));
1158  SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel) + bonus_dmg));
1159 
1160  break;
1161  }
1162  case 19833: //Snake Trap - Venomous Snake
1163  {
1164  SetCreateHealth(uint32(107 * (petlevel - 40) * 0.025f));
1165  SetCreateMana(0);
1166  SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel / 2) - 25));
1167  SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel / 2) - 18));
1168  break;
1169  }
1170  case 19921: //Snake Trap - Viper
1171  {
1172  SetCreateHealth(uint32(107 * (petlevel - 40) * 0.025f));
1173  SetCreateMana(0);
1174  SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel / 2 - 10));
1175  SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel / 2));
1176  break;
1177  }
1178  default:
1179  {
1180  if (!pInfo)
1181  {
1182  SetCreateMana(28 + 10 * petlevel);
1183  SetCreateHealth(28 + 30 * petlevel);
1184  }
1185  // FIXME: this is wrong formula, possible each guardian pet have own damage formula
1186  //these formula may not be correct; however, it is designed to be close to what it should be
1187  //this makes dps 0.5 of pets level
1188  SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
1189  //damage range is then petlevel / 2
1190  SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
1191  break;
1192  }
1193  }
1194  break;
1195  }
1196  }
1197 
1198  UpdateAllStats();
1199 
1202  return true;
1203 }
1204 
1205 bool Pet::HaveInDiet(ItemTemplate const* item) const
1206 {
1207  if (!item || !item->FoodType)
1208  return false;
1209 
1210  CreatureInfo const* cInfo = GetCreatureTemplate();
1211  if (!cInfo)
1212  return false;
1213 
1214  CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->family);
1215  if (!cFamily)
1216  return false;
1217 
1218  uint32 diet = cFamily->petFoodMask;
1219  uint32 FoodMask = 1 << (item->FoodType - 1);
1220  return diet & FoodMask;
1221 }
1222 
1224 {
1225  // -5 or greater food level
1226  if (getLevel() <= itemlevel + 5) //possible to feed level 60 pet with level 55 level food for full effect
1227  return 35000;
1228  // -10..-6
1229  else if (getLevel() <= itemlevel + 10) //pure guess, but sounds good
1230  return 17000;
1231  // -14..-11
1232  else if (getLevel() <= itemlevel + 14) //level 55 food gets green on 70, makes sense to me
1233  return 8000;
1234  // -15 or less
1235  else
1236  return 0; //food too low level
1237 }
1238 
1240 {
1241  m_CreatureSpellCooldowns.clear();
1243 
1244  QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT spell,time FROM pet_spell_cooldown WHERE guid = '%u'", m_charmInfo->GetPetNumber());
1245 
1246  if (result)
1247  {
1248  time_t curTime = time(NULL);
1249 
1250  WorldPacket data(SMSG_SPELL_COOLDOWN, (8 + 1 + result->GetRowCount() * 8));
1251  data << GetGUID();
1252  data << uint8(0x0); // flags (0x1, 0x2)
1253 
1254  do
1255  {
1256  Field* fields = result->Fetch();
1257 
1258  uint32 spell_id = fields[0].GetUInt32();
1259  time_t db_time = (time_t)fields[1].GetUInt64();
1260 
1261  if (!sSpellStore.LookupEntry(spell_id))
1262  {
1263  sLog.outError("Pet %u has unknown spell %u in pet_spell_cooldown, skipping.", m_charmInfo->GetPetNumber(), spell_id);
1264  continue;
1265  }
1266 
1267  // skip outdated cooldown
1268  if (db_time <= curTime)
1269  continue;
1270 
1271  data << uint32(spell_id);
1272  data << uint32(uint32(db_time - curTime)*IN_MILLISECONDS); // in m.secs
1273 
1274  _AddCreatureSpellCooldown(spell_id, db_time);
1275 
1276  sLog.outDebug("Pet (Number: %u) spell %u cooldown loaded (%u secs).", m_charmInfo->GetPetNumber(), spell_id, uint32(db_time - curTime));
1277  }
1278  while (result->NextRow());
1279 
1280  if (!m_CreatureSpellCooldowns.empty() && GetOwner())
1281  GetOwner()->ToPlayer()->GetSession()->SendPacket(&data);
1282  }
1283 }
1284 
1286 {
1287  if (getPetType() == SUMMON_PET) //don't save cooldowns for temp pets, thats senseless
1288  return;
1289 
1290  CharacterDatabase.PExecute("DELETE FROM pet_spell_cooldown WHERE guid = '%u'", m_charmInfo->GetPetNumber());
1291 
1292  time_t curTime = time(NULL);
1293 
1294  // remove oudated and save active
1295  for (CreatureSpellCooldowns::iterator itr = m_CreatureSpellCooldowns.begin(); itr != m_CreatureSpellCooldowns.end();)
1296  {
1297  if (itr->second <= curTime)
1298  m_CreatureSpellCooldowns.erase(itr++);
1299  else
1300  {
1301  CharacterDatabase.PExecute("INSERT INTO pet_spell_cooldown (guid,spell,time) VALUES ('%u', '%u', '" UI64FMTD "')", m_charmInfo->GetPetNumber(), itr->first, uint64(itr->second));
1302  ++itr;
1303  }
1304  }
1305 }
1306 
1308 {
1309  QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT spell,active FROM pet_spell WHERE guid = '%u'", m_charmInfo->GetPetNumber());
1310 
1311  if (result)
1312  {
1313  do
1314  {
1315  Field* fields = result->Fetch();
1316 
1317  addSpell(fields[0].GetUInt32(), fields[1].GetUInt16(), PETSPELL_UNCHANGED);
1318  }
1319  while (result->NextRow());
1320  }
1321 }
1322 
1324 {
1325  for (PetSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next)
1326  {
1327  ++next;
1328 
1329  // prevent saving family passives to DB
1330  if (itr->second.type == PETSPELL_FAMILY)
1331  continue;
1332 
1333  switch (itr->second.state)
1334  {
1335  case PETSPELL_REMOVED:
1336  CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first);
1337  m_spells.erase(itr);
1338  continue;
1339  case PETSPELL_CHANGED:
1340  CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first);
1341  CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second.active);
1342  break;
1343  case PETSPELL_NEW:
1344  CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second.active);
1345  break;
1346  case PETSPELL_UNCHANGED:
1347  continue;
1348  }
1349 
1350  itr->second.state = PETSPELL_UNCHANGED;
1351  }
1352 }
1353 
1354 void Pet::_LoadAuras(uint32 timediff)
1355 {
1356  m_Auras.clear();
1357  for (int i = 0; i < TOTAL_AURAS; i++)
1358  m_modAuras[i].clear();
1359 
1360  // all aura related fields
1361  for (int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i)
1362  SetUInt32Value(i, 0);
1363 
1364  QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT caster_guid,item_caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'", m_charmInfo->GetPetNumber());
1365 
1366  if (result)
1367  {
1368  do
1369  {
1370  Field* fields = result->Fetch();
1371  uint64 caster_guid = fields[0].GetUInt64();
1372  uint64 item_caster_guid = fields[1].GetUInt64();
1373  uint32 spellid = fields[2].GetUInt32();
1374  uint32 effindex = fields[3].GetUInt32();
1375  uint32 stackcount = fields[4].GetUInt32();
1376  int32 damage = fields[5].GetUInt32();
1377  int32 maxduration = fields[6].GetUInt32();
1378  int32 remaintime = fields[7].GetUInt32();
1379  int32 remaincharges = fields[8].GetUInt32();
1380 
1381  SpellEntry const* spellproto = sSpellStore.LookupEntry(spellid);
1382  if (!spellproto)
1383  {
1384  sLog.outError("Unknown aura (spellid %u, effindex %u), ignore.", spellid, effindex);
1385  continue;
1386  }
1387 
1388  if (effindex >= 3)
1389  {
1390  sLog.outError("Invalid effect index (spellid %u, effindex %u), ignore.", spellid, effindex);
1391  continue;
1392  }
1393 
1394  // negative effects should continue counting down after logout
1395  if (remaintime != -1 && !IsPositiveEffect(spellid, effindex))
1396  {
1397  if (remaintime / IN_MILLISECONDS <= int32(timediff))
1398  continue;
1399 
1400  remaintime -= timediff * IN_MILLISECONDS;
1401  }
1402 
1403  // prevent wrong values of remaincharges
1404  if (spellproto->procCharges)
1405  {
1406  if (remaincharges <= 0 || uint32(remaincharges) > spellproto->procCharges)
1407  remaincharges = spellproto->procCharges;
1408  }
1409  else
1410  remaincharges = -1;
1411 
1412  // do not load single target auras (unless they were cast by the player)
1413  if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto))
1414  continue;
1415 
1416  for (uint32 i = 0; i < stackcount; ++i)
1417  {
1418  Aura* aura = CreateAura(spellproto, effindex, NULL, this, NULL);
1419 
1420  if (!damage)
1421  damage = aura->GetModifier()->m_amount;
1422  aura->SetLoadedState(caster_guid, item_caster_guid, damage, maxduration, remaintime, remaincharges);
1423  AddAura(aura);
1424  }
1425  }
1426  while (result->NextRow());
1427  }
1428 }
1429 
1431 {
1432  CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'", m_charmInfo->GetPetNumber());
1433 
1434  AuraMap const& auras = GetAuras();
1435  if (auras.empty())
1436  return;
1437 
1438  spellEffectPair lastEffectPair = auras.begin()->first;
1439  uint32 stackCounter = 1;
1440 
1441  for (AuraMap::const_iterator itr = auras.begin(); ; ++itr)
1442  {
1443  if (itr == auras.end() || lastEffectPair != itr->first)
1444  {
1445  AuraMap::const_iterator itr2 = itr;
1446  // save previous spellEffectPair to db
1447  itr2--;
1448  SpellEntry const* spellInfo = itr2->second->GetSpellProto();
1449  // do not save single target auras (unless they were cast by the player)
1450  if (!(itr2->second->GetCasterGUID() != GetGUID() && IsSingleTargetSpell(spellInfo)))
1451  {
1452  if (!itr2->second->IsPassive())
1453  {
1454  // skip all auras from spell that apply at cast SPELL_AURA_MOD_SHAPESHIFT or pet area auras.
1455  uint8 i;
1456  for (i = 0; i < 3; i++)
1457  if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH ||
1458  spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_CHARM ||
1459  spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_POSSESS ||
1461  spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_OWNER ||
1462  spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PET)
1463  break;
1464 
1465  if (i == 3)
1466  {
1467  CharacterDatabase.PExecute("INSERT INTO pet_aura (guid,caster_guid,item_caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges) "
1468  "VALUES ('%u', '" UI64FMTD "', '" UI64FMTD "', '%u', '%u', '%u', '%d', '%d', '%d', '%d')",
1469  m_charmInfo->GetPetNumber(), itr2->second->GetCasterGUID(), itr2->second->GetCastItemGUID(), (uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), (uint32)itr2->second->GetStackAmount(), itr2->second->GetModifier()->m_amount, int(itr2->second->GetAuraMaxDuration()), int(itr2->second->GetAuraDuration()), int(itr2->second->m_procCharges));
1470  }
1471  }
1472  }
1473  if (itr == auras.end())
1474  break;
1475  }
1476 
1477  if (lastEffectPair == itr->first)
1478  stackCounter++;
1479  else
1480  {
1481  lastEffectPair = itr->first;
1482  stackCounter = 1;
1483  }
1484  }
1485 }
1486 
1487 bool Pet::addSpell(uint16 spell_id, uint16 active /*= ACT_DECIDE*/, PetSpellState state /*= PETSPELL_NEW*/, PetSpellType type /*= PETSPELL_NORMAL*/)
1488 {
1489  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
1490  if (!spellInfo)
1491  {
1492  // do pet spell book cleanup
1493  if (state == PETSPELL_UNCHANGED) // spell load case
1494  {
1495  sLog.outError("Pet::addSpell: Invalid SpellStore spell #%u request, deleting for all pets in pet_spell.", spell_id);
1496  CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE spell = '%u'", spell_id);
1497  }
1498  else
1499  sLog.outError("Pet::addSpell: Invalid SpellStore spell #%u request.", spell_id);
1500 
1501  return false;
1502  }
1503 
1504  PetSpellMap::iterator itr = m_spells.find(spell_id);
1505  if (itr != m_spells.end())
1506  {
1507  if (itr->second.state == PETSPELL_REMOVED)
1508  {
1509  m_spells.erase(itr);
1510  state = PETSPELL_CHANGED;
1511  }
1512  else if (state == PETSPELL_UNCHANGED && itr->second.state != PETSPELL_UNCHANGED)
1513  {
1514  // can be in case spell loading but learned at some previous spell loading
1515  itr->second.state = PETSPELL_UNCHANGED;
1516 
1517  if (active == ACT_ENABLED)
1518  ToggleAutocast(spell_id, true);
1519  else if (active == ACT_DISABLED)
1520  ToggleAutocast(spell_id, false);
1521 
1522  return false;
1523  }
1524  else
1525  return false;
1526  }
1527 
1528  uint32 oldspell_id = 0;
1529 
1530  PetSpell newspell;
1531  newspell.state = state;
1532  newspell.type = type;
1533 
1534  if (active == ACT_DECIDE) // active was not used before, so we save it's autocast/passive state here
1535  {
1536  if (IsAutocastableSpell(spell_id))
1537  newspell.active = ACT_DISABLED;
1538  else
1539  newspell.active = ACT_PASSIVE;
1540  }
1541  else
1542  newspell.active = active;
1543 
1544  uint32 chainstart = sSpellMgr.GetFirstSpellInChain(spell_id);
1545 
1546  for (PetSpellMap::iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2)
1547  {
1548  if (itr2->second.state == PETSPELL_REMOVED) continue;
1549 
1550  if (sSpellMgr.GetFirstSpellInChain(itr2->first) == chainstart)
1551  {
1552  newspell.active = itr2->second.active;
1553 
1554  if (newspell.active == ACT_ENABLED)
1555  ToggleAutocast(itr2->first, false);
1556 
1557  oldspell_id = itr2->first;
1558  removeSpell(itr2->first);
1559  break;
1560  }
1561  }
1562 
1563  m_spells[spell_id] = newspell;
1564 
1565  if (IsPassiveSpell(spell_id))
1566  CastSpell(this, spell_id, true);
1567  else if (state == PETSPELL_NEW)
1568  m_charmInfo->AddSpellToActionBar(oldspell_id, spell_id, (ActiveStates)active);
1569 
1570  if (newspell.active == ACT_ENABLED)
1571  ToggleAutocast(spell_id, true);
1572 
1573  return true;
1574 }
1575 
1576 bool Pet::learnSpell(uint16 spell_id)
1577 {
1578  // prevent duplicated entires in spell book
1579  if (!addSpell(spell_id))
1580  return false;
1581 
1582  Unit* owner = GetOwner();
1583  if (owner->GetTypeId() == TYPEID_PLAYER)
1584  owner->ToPlayer()->PetSpellInitialize();
1585  return true;
1586 }
1587 
1588 void Pet::removeSpell(uint16 spell_id)
1589 {
1590  PetSpellMap::iterator itr = m_spells.find(spell_id);
1591  if (itr == m_spells.end())
1592  return;
1593 
1594  if (itr->second.state == PETSPELL_REMOVED)
1595  return;
1596 
1597  if (itr->second.state == PETSPELL_NEW)
1598  m_spells.erase(itr);
1599  else
1600  itr->second.state = PETSPELL_REMOVED;
1601 
1602  RemoveAurasDueToSpell(spell_id);
1603 }
1604 
1606 {
1608  m_spells.clear();
1609 
1610  int32 usedtrainpoints = 0, petspellid;
1611  PetCreateSpellEntry const* CreateSpells = sObjectMgr.GetPetCreateSpellEntry(GetEntry());
1612  if (CreateSpells)
1613  {
1614  Unit* owner = GetOwner();
1615  Player* p_owner = owner && owner->GetTypeId() == TYPEID_PLAYER ? owner->ToPlayer() : NULL;
1616 
1617  for (uint8 i = 0; i < 4; ++i)
1618  {
1619  if (!CreateSpells->spellid[i])
1620  break;
1621 
1622  SpellEntry const* learn_spellproto = sSpellStore.LookupEntry(CreateSpells->spellid[i]);
1623  if (!learn_spellproto)
1624  continue;
1625 
1626  if (learn_spellproto->Effect[0] == SPELL_EFFECT_LEARN_SPELL || learn_spellproto->Effect[0] == SPELL_EFFECT_LEARN_PET_SPELL)
1627  {
1628  petspellid = learn_spellproto->EffectTriggerSpell[0];
1629  if (p_owner && !p_owner->HasSpell(learn_spellproto->Id))
1630  {
1631  if (IsPassiveSpell(petspellid)) //learn passive skills when tamed, not sure if thats right
1632  p_owner->LearnSpell(learn_spellproto->Id);
1633  else
1634  AddTeachSpell(learn_spellproto->EffectTriggerSpell[0], learn_spellproto->Id);
1635  }
1636  }
1637  else
1638  petspellid = learn_spellproto->Id;
1639 
1640  addSpell(petspellid);
1641 
1642  if (petspellid)
1643  ToggleAutocast(petspellid, true);
1644 
1645  SkillLineAbilityMap::const_iterator lower = sSpellMgr.GetBeginSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]);
1646  SkillLineAbilityMap::const_iterator upper = sSpellMgr.GetEndSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]);
1647 
1648  for (SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
1649  {
1650  usedtrainpoints += _spell_idx->second->reqtrainpoints;
1651  break;
1652  }
1653  }
1654  }
1655 
1656  LearnPetPassives();
1657 
1658  CastPetAuras(false);
1659 
1660  SetTP(-usedtrainpoints);
1661 }
1662 
1664 {
1665  //charmed case -> prevent crash
1666  if (GetTypeId() == TYPEID_PLAYER || getPetType() != HUNTER_PET)
1667  return;
1668 
1669  Unit* owner = GetOwner();
1670 
1671  if (m_teachspells.empty() || !owner || owner->GetTypeId() != TYPEID_PLAYER)
1672  return;
1673 
1674  TeachSpellMap::iterator itr = m_teachspells.find(spellid);
1675  if (itr == m_teachspells.end())
1676  return;
1677 
1678  if (urand(0, 100) < 10)
1679  {
1680  owner->ToPlayer()->LearnSpell(itr->second);
1681  m_teachspells.erase(itr);
1682  }
1683 }
1684 
1686 {
1687  uint32 days = (sWorld.GetGameTime() - m_resetTalentsTime) / DAY;
1688 
1689  // The first time reset costs 10 silver; after 1 day cost is reset to 10 silver
1690  if (m_resetTalentsCost < 10 * SILVER || days > 0)
1691  return 10 * SILVER;
1692  // then 50 silver
1693  else if (m_resetTalentsCost < 50 * SILVER)
1694  return 50 * SILVER;
1695  // then 1 gold
1696  else if (m_resetTalentsCost < 1 * GOLD)
1697  return 1 * GOLD;
1698  // then increasing at a rate of 1 gold; cap 10 gold
1699  else
1700  return (m_resetTalentsCost + 1 * GOLD > 10 * GOLD ? 10 * GOLD : m_resetTalentsCost + 1 * GOLD);
1701 }
1702 
1703 void Pet::ToggleAutocast(uint32 spellid, bool apply)
1704 {
1705  if (!IsAutocastableSpell(spellid))
1706  return;
1707 
1708  PetSpellMap::iterator itr = m_spells.find(spellid);
1709  if (itr == m_spells.end())
1710  return;
1711 
1712  uint32 i;
1713 
1714  if (apply)
1715  {
1716  for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; ++i)
1717  ; // just search
1718 
1719  if (i == m_autospells.size())
1720  {
1721  m_autospells.push_back(spellid);
1722 
1723  if (itr->second.active != ACT_ENABLED)
1724  {
1725  itr->second.active = ACT_ENABLED;
1726  if (itr->second.state != PETSPELL_NEW)
1727  itr->second.state = PETSPELL_CHANGED;
1728  }
1729  }
1730  }
1731  else
1732  {
1733  AutoSpellList::iterator itr2 = m_autospells.begin();
1734  for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; ++i, ++itr2)
1735  ; // just search
1736 
1737  if (i < m_autospells.size())
1738  {
1739  m_autospells.erase(itr2);
1740  if (itr->second.active != ACT_DISABLED)
1741  {
1742  itr->second.active = ACT_DISABLED;
1743  if (itr->second.state != PETSPELL_NEW)
1744  itr->second.state = PETSPELL_CHANGED;
1745  }
1746  }
1747  }
1748 }
1749 
1751 {
1752  switch (getPetType())
1753  {
1754  case SUMMON_PET:
1755  switch (owner->getClass())
1756  {
1757  case CLASS_WARLOCK:
1759  default:
1760  return false;
1761  }
1762  case HUNTER_PET:
1763  return true;
1764  default:
1765  return false;
1766  }
1767 }
1768 
1769 bool Pet::Create(uint32 guidlow, Map* map, uint32 Entry, uint32 pet_number)
1770 {
1771  ASSERT(map);
1772  SetMap(map);
1773 
1774  Object::_Create(guidlow, pet_number, HIGHGUID_PET);
1775 
1776  m_DBTableGuid = guidlow;
1777  m_originalEntry = Entry;
1778 
1779  if (!InitEntry(Entry))
1780  return false;
1781 
1784 
1785  InitPetAuras(Entry);
1786 
1787  return true;
1788 }
1789 
1790 void Pet::InitPetAuras(const uint32 Entry)
1791 {
1792  CreatureInfo const* cInfo = sObjectMgr.GetCreatureTemplate(Entry);
1793  if (!cInfo)
1794  return;
1795 
1796  uint32 aura1 = 0, aura2 = 0, aura3 = 0;
1797 
1798  switch (cInfo->family)
1799  {
1800  // WARLOCK PETS:
1801  case CREATURE_FAMILY_IMP:
1802  aura1 = 18728;
1803  aura2 = 18737;
1804  aura3 = 18740;
1805  break;
1807  aura1 = 18730;
1808  aura2 = 18738;
1809  aura3 = 18739;
1810  break;
1812  aura1 = 18727;
1813  aura2 = 18735;
1814  aura3 = 18742;
1815  break;
1817  aura1 = 18729;
1818  aura2 = 18736;
1819  aura3 = 18741;
1820  break;
1822  aura1 = 30147;
1823  aura2 = 30148;
1824  aura3 = 30149;
1825  break;
1826 
1827  // HUNTER PETS:
1828  case CREATURE_FAMILY_HYENA:
1829  aura1 = 17215;
1830  break;
1831  case CREATURE_FAMILY_BEAR:
1832  aura1 = 17208;
1833  break;
1835  aura1 = 35386;
1836  break;
1837  case CREATURE_FAMILY_WOLF:
1838  aura1 = 17223;
1839  break;
1841  aura1 = 35254;
1842  break;
1844  aura1 = 35258;
1845  break;
1847  aura1 = 34887;
1848  break;
1850  aura1 = 35253;
1851  break;
1853  aura1 = 35257;
1854  break;
1855  case CREATURE_FAMILY_BOAR:
1856  aura1 = 7000;
1857  break;
1858  case CREATURE_FAMILY_BAT:
1859  aura1 = 17206;
1860  break;
1862  aura1 = 17209;
1863  break;
1864  case CREATURE_FAMILY_CAT:
1865  aura1 = 17210;
1866  break;
1868  aura1 = 17219;
1869  break;
1871  aura1 = 17212;
1872  break;
1873  case CREATURE_FAMILY_CRAB:
1874  aura1 = 17211;
1875  break;
1877  aura1 = 17214;
1878  break;
1880  aura1 = 17217;
1881  break;
1883  aura1 = 17220;
1884  break;
1886  aura1 = 17218;
1887  break;
1889  aura1 = 17221;
1890  break;
1891  case CREATURE_FAMILY_OWL:
1892  aura1 = 17216;
1893  break;
1895  aura1 = 17222;
1896  break;
1900  default:
1901  return;
1902  }
1903 
1904  if (aura1)
1905  CastSpell(this, aura1, true);
1906  if (aura2)
1907  CastSpell(this, aura2, true);
1908  if (aura3)
1909  CastSpell(this, aura3, true);
1910 
1911  // Hunter Pets have multiple auras
1912  if (getPetType() == HUNTER_PET)
1913  {
1914  CastSpell(this, 8875, true); // Damage
1915  CastSpell(this, 19580, true); // Armor
1916  CastSpell(this, 19581, true); // HP
1917  CastSpell(this, 19582, true); // Speed
1918  CastSpell(this, 19589, true); // Power Regen
1919  CastSpell(this, 19591, true); // Critical Chance
1920  CastSpell(this, 20784, true); // Frenzy Chance
1921  CastSpell(this, 34666, true); // Hit Chance
1922  CastSpell(this, 34667, true); // Dodge Chance
1923  CastSpell(this, 34675, true); // Attack Speed
1924  }
1925 }
1926 
1927 bool Pet::HasSpell(uint32 spell) const
1928 {
1929  return (m_spells.find(spell) != m_spells.end());
1930 }
1931 
1932 // Get all passive spells in our skill line
1934 {
1935  CreatureInfo const* cInfo = GetCreatureTemplate();
1936  if (!cInfo)
1937  return;
1938 
1939  CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->family);
1940  if (!cFamily)
1941  return;
1942 
1943  PetFamilySpellsStore::const_iterator petStore = sPetFamilySpellsStore.find(cFamily->ID);
1944  if (petStore != sPetFamilySpellsStore.end())
1945  {
1946  // For general hunter pets skill 270
1947  // Passive 01~10, Passive 00 (20782, not used), Ferocious Inspiration (34457)
1948  // Scale 01~03 (34902~34904, bonus from owner, not used)
1949  for (PetFamilySpellsSet::const_iterator petSet = petStore->second.begin(); petSet != petStore->second.end(); ++petSet)
1951  }
1952 }
1953 
1954 void Pet::CastPetAuras(bool current)
1955 {
1956  Unit* owner = GetOwner();
1957  if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
1958  return;
1959 
1960  if (!IsPermanentPetFor(owner->ToPlayer()))
1961  return;
1962 
1963  for (PetAuraSet::iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end();)
1964  {
1965  PetAura const* pa = *itr;
1966  ++itr;
1967 
1968  if (!current && pa->IsRemovedOnChangePet())
1969  owner->RemovePetAura(pa);
1970  else
1971  CastPetAura(pa);
1972  }
1973 }
1974 
1975 void Pet::CastPetAura(PetAura const* aura)
1976 {
1977  uint32 auraId = aura->GetAura(GetEntry());
1978  if (!auraId)
1979  return;
1980 
1981  if (auraId == 35696) // Demonic Knowledge
1982  {
1984  CastCustomSpell(this, auraId, &basePoints, NULL, NULL, true);
1985  }
1986  else
1987  CastSpell(this, auraId, true);
1988 }
1989 
1991 {
1992  if (apply)
1994  else
1996 
1997  Unit* owner = GetOwner();
1998  if(!owner || owner->GetTypeId()!=TYPEID_PLAYER)
1999  return;
2000 
2001  WorldPacket data(SMSG_PET_MODE, 12);
2002  data << uint64(GetGUID());
2003  data << uint32(m_petModeFlags);
2004  ((Player*)owner)->GetSession()->SendPacket(&data);
2005 }
void RemoveFromWorld() override
Definition: Unit.cpp:11056
UnitMoveType
Definition: Unit.h:458
PetSaveMode
Definition: Pet.h:33
uint32 SpellOrAction
Definition: Unit.h:701
uint16 mana
Definition: ObjectMgr.h:398
void LoseHappiness()
Definition: Pet.cpp:634
TeachSpellMap m_teachspells
Definition: Pet.h:254
int32 ModifyPower(Powers power, int32 val)
Definition: Unit.cpp:9725
PetSpellType type
Definition: Pet.h:99
bool AddToMap(T *)
Definition: Map.cpp:424
void RemoveAllAuras()
Definition: Unit.cpp:4522
#define BASE_ATTACK_TIME
Definition: Unit.h:159
Group * GetGroup()
Definition: Player.h:2589
int32 resistance3
Definition: Creature.h:180
PetType
Definition: Pet.h:25
bool HasSpell(uint32 spell) const override
Definition: Pet.cpp:1927
void DeleteFromDB() override
Definition: Pet.h:322
void SetLastPetNumber(uint32 petnumber)
Definition: Player.h:2575
void AddToWorld() override
Definition: Pet.cpp:98
const uint32 & GetUInt32Value(uint16 index) const
Definition: Object.h:228
void CastCustomSpell(Unit *Victim, uint32 spellId, int32 const *bp0, int32 const *bp1, int32 const *bp2, bool triggered, Item *castItem=NULL, Aura *triggeredByAura=NULL, uint64 originalCaster=0)
Definition: Unit.cpp:1248
bool AddSpellToActionBar(uint32 oldid, uint32 newid, ActiveStates newstate=ACT_DECIDE)
Definition: Unit.cpp:11283
#define MAX_MOVE_TYPE
Definition: Unit.h:470
#define GUID_LOPART(x)
Definition: ObjectGuid.h:110
void SetPetNumber(uint32 petnumber, bool statwindow)
Definition: Unit.cpp:11314
uint32 GetMaxHealth() const
Definition: Unit.h:1052
uint32 EffectTriggerSpell[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:741
Definition: Pet.h:67
bool IsSingleTargetSpell(SpellEntry const *spellInfo)
Definition: SpellMgr.cpp:783
void ToggleAutocast(uint32 spellid, bool apply)
Definition: Pet.cpp:1703
Map * GetMap() const
Definition: Object.h:829
time_t m_resetTalentsTime
Definition: Pet.h:266
std::vector< std::string > Tokens
Definition: Util.h:26
bool IsPassiveSpell(uint32 spellId)
Definition: SpellMgr.cpp:278
int32 resistance6
Definition: Creature.h:183
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData *data=NULL)
Definition: Creature.cpp:260
void InitPetAuras(const uint32 Entry)
Definition: Pet.cpp:1790
bool BeginTransaction()
Definition: Database.cpp:533
UnitMods
Definition: Unit.h:360
void SetIsFollowing(bool val)
Definition: Unit.cpp:13473
uint32 getFaction() const
Definition: Unit.h:1111
void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value)
Definition: Unit.h:1750
uint16 stats[MAX_STATS]
Definition: ObjectMgr.h:396
void AddTeachSpell(uint32 learned_id, uint32 source_id)
Definition: Pet.h:233
QueryResult_AutoPtr PQuery(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:400
void _LoadSpells()
Definition: Pet.cpp:1307
void SetAttackTime(WeaponAttackType att, uint32 val)
Definition: Unit.h:1094
SpellSchools
PetSpellType
Definition: Pet.h:88
AuraMap & GetAuras()
Definition: Unit.h:1848
uint16 armor
Definition: ObjectMgr.h:399
Definition: Field.h:24
void SetObjectScale(float scale)
Definition: Object.h:199
Player * m_owner
Definition: Pet.h:297
uint32 GetAura(uint32 petEntry) const
Definition: SpellMgr.h:739
std::string m_name
Definition: Object.h:919
AutoSpellList m_autospells
Definition: Pet.h:255
int32 GetTPForSpell(uint32 spellid)
Definition: Pet.cpp:781
#define PET_FOLLOW_ANGLE
bool Execute(const char *sql)
Definition: Database.cpp:420
bool IsInCombat() const
Definition: Unit.h:1318
uint32 m_regenTimer
Definition: Pet.h:298
CharmInfo * m_charmInfo
Definition: Unit.h:2161
virtual void SetMap(Map *map)
Definition: Object.cpp:1951
uint32 procCharges
Definition: DBCStructure.h:704
UnitActionBarEntry * GetActionBarEntry(uint8 index)
Definition: Unit.h:809
std::pair< uint32, uint8 > spellEffectPair
Definition: Unit.h:891
void SetCreateHealth(uint32 val)
Definition: Unit.h:1655
Definition: Unit.h:413
void setPetType(PetType type)
Definition: Pet.h:159
void AddObject(T *object)
#define sLog
Log class singleton.
Definition: Log.h:187
uint32 m_happinessTimer
Definition: Pet.h:299
float GetVisibilityRange() const
Definition: Object.cpp:1549
void SetCanModifyStats(bool modifyStats)
Definition: Unit.h:1764
#define PET_FOLLOW_DIST
void AddToWorld() override
Definition: Unit.cpp:11050
Tokens StrSplit(const std::string &src, const std::string &sep)
Definition: Util.cpp:97
void SetUInt32Value(uint16 index, uint32 value)
Definition: Object.cpp:779
ACE_INT32 int32
Definition: Define.h:67
uint32 GetNativeDisplayId()
Definition: Unit.h:1896
unsigned long escape_string(char *to, const char *from, unsigned long length)
Definition: Database.cpp:212
void _LoadSpellCooldowns()
Definition: Pet.cpp:1239
std::list< Aura * > AuraList
Definition: Unit.h:893
uint32 const LevelStartLoyalty[6]
Definition: Pet.cpp:44
NULL Dbg ErrDB Arena Chat Char Map MMap false
Definition: Log.cpp:556
bool Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number)
Definition: Pet.cpp:1769
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply)
Definition: Unit.cpp:9133
void SetNativeDisplayId(uint32 modelId)
Definition: Unit.h:1900
#define HAPPINESS_LEVEL_SIZE
Definition: Pet.h:137
int32 m_duration
Definition: Pet.h:302
~Pet() override
Definition: Pet.cpp:93
bool CreateBaseAtCreature(Creature *creature)
Definition: Pet.cpp:905
uint32 GetGUIDLow() const
Definition: Object.h:160
uint32 Effect[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:724
Definition: Pet.h:28
Definition: Unit.h:415
#define MAX_DECLINED_NAME_CASES
Definition: Unit.h:704
void AddAura(uint32 spellId, Unit *target)
Definition: Unit.cpp:13382
Aura * CreateAura(SpellEntry const *spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item *castItem)
Definition: SpellAuras.cpp:502
void SetFlag(uint16 index, uint32 newFlag)
Definition: Object.cpp:985
void SetMinion(Minion *minion, bool apply)
Definition: Unit.cpp:7629
bool AIM_Initialize(CreatureAI *ai=NULL)
Definition: Creature.cpp:741
void _AddCreatureSpellCooldown(uint32 spell_id, time_t end_time)
Definition: Creature.cpp:2223
void apply(T *val)
Definition: ByteConverter.h:41
uint32 const LevelUpLoyalty[6]
Definition: Pet.cpp:34
#define sObjectMgr
Definition: ObjectMgr.h:1285
void SendPacket(WorldPacket const *packet)
PetModeFlags m_petModeFlags
Definition: Pet.h:311
CharmInfo * GetCharmInfo()
Definition: Unit.h:1567
#define MAX_SPELL_SCHOOL
bool CommitTransaction()
Definition: Database.cpp:551
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
int32 SpellBaseDamageBonus(SpellSchoolMask schoolMask)
Definition: Unit.cpp:8323
void setPowerType(Powers power)
Definition: Unit.cpp:7089
bool UpdateAllStats() override
Definition: StatSystem.cpp:963
DBCStorage< SpellEntry > sSpellStore(SpellEntryfmt)
void setDeathState(DeathState s) override
Definition: Pet.cpp:483
uint32 EffectApplyAuraName[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:734
PetSpellState
Definition: Pet.h:80
Definition: Pet.h:94
void GivePetXP(uint32 xp)
Definition: Pet.cpp:858
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true) const
Definition: Object.h:762
Player * ToPlayer()
Definition: Object.h:386
Definition: Common.h:181
uint32 GetPower(Powers power) const
Definition: Unit.h:1076
int32 GetDispTP()
Definition: Pet.cpp:843
bool HasSpell(uint32 spell) const override
Definition: Player.cpp:3813
void ModifyLoyalty(int32 addvalue)
Definition: Pet.cpp:645
uint32 GetCreatePowers(Powers power) const
Definition: Unit.cpp:11032
bool HasTPForSpell(uint32 spellid)
Definition: Pet.cpp:773
#define MAX_STATS
void RemoveAurasDueToSpell(uint32 spellId, Aura *except=NULL)
Definition: Unit.cpp:4316
void _SaveAuras()
Definition: Pet.cpp:1430
void RemovePetAura(PetAura const *petSpell)
Definition: Unit.cpp:12258
void CastPetAura(PetAura const *aura)
Definition: Pet.cpp:1975
bool IsRemovedOnChangePet() const
Definition: SpellMgr.h:759
void ApplyModeFlags(PetModeFlags mode, bool apply)
Definition: Pet.cpp:1990
Definition: Pet.h:65
uint8 GetTypeId() const
Definition: Object.h:204
void SavePetToDB(PetSaveMode mode)
Definition: Pet.cpp:364
uint32 GetStartLoyaltyPoints(uint32 level)
Definition: Pet.cpp:830
void _Create(uint32 guidlow, uint32 entry, HighGuid guidhigh)
Definition: Object.cpp:125
Definition: Pet.h:27
void SetMeleeDamageSchool(SpellSchools school)
Definition: Creature.h:562
bool InitStatsForLevel(uint32 level)
Definition: Pet.cpp:966
uint32 m_corpseRemoveTime
Definition: Creature.h:899
ACE_UINT8 uint8
Definition: Define.h:73
uint32 GetMaxPower(Powers power) const
Definition: Unit.h:1080
float GetOrientation() const
Definition: Position.h:100
void setDeathState(DeathState s) override
Definition: Creature.cpp:1558
uint32 GetDisplayId()
Definition: Unit.h:1891
#define UI64FMTD
Definition: Common.h:149
int32 resistance4
Definition: Creature.h:181
void Relocate(float x, float y)
Definition: Position.h:65
std::string GetCppString() const
Definition: Field.h:52
bool learnSpell(uint16 spell_id)
Definition: Pet.cpp:1576
const bool & IsInWorld() const
Definition: Object.h:129
bool IsPermanentPetFor(Player *owner)
Definition: Pet.cpp:1750
void PetSpellInitialize()
Definition: Player.cpp:17319
void InitPetActionBar()
Definition: Unit.cpp:11180
int32 m_amount
Definition: SpellAuras.h:35
uint32 m_DBTableGuid
Definition: Creature.h:914
bool isTemporarySummoned() const
Definition: Pet.h:167
void SetDisplayId(uint32 modelId)
Definition: Unit.cpp:11896
uint32 GetPetNumber() const
Definition: Unit.h:779
void SetIsReturning(bool val)
Definition: Unit.cpp:13483
void Update(uint32 diff) override
Definition: Pet.cpp:513
bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
Definition: SpellMgr.cpp:561
uint32 type
Definition: Creature.h:173
void CastPetAuras(bool current)
Definition: Pet.cpp:1954
uint32 xp_to_level(uint32 lvl)
Definition: Formulas.h:157
Stats
bool IsAlive() const
Definition: Unit.h:1433
void SetCreateMana(uint32 val)
Definition: Unit.h:1663
float GetPositionY() const
Definition: Position.h:98
int32 resistance5
Definition: Creature.h:182
void SetByteValue(uint16 index, uint8 offset, uint8 value)
Definition: Object.cpp:878
DeathState m_deathState
Definition: Unit.h:2133
LoyaltyLevel
Definition: Pet.h:70
void CastSpell(Unit *Victim, uint32 spellId, bool triggered, Item *castItem=NULL, Aura *triggeredByAura=NULL, uint64 originalCaster=0)
Definition: Unit.cpp:1174
bool isControlled() const
Definition: Pet.h:163
void _LoadAuras(uint32 timediff)
Definition: Pet.cpp:1354
bool m_wasOutdoors
Definition: Pet.h:308
#define sSpellMgr
Definition: SpellMgr.h:1239
void SetCreateStat(Stats stat, float val)
Definition: Unit.h:1651
Player * GetOwner()
Definition: Pet.h:292
float GetPositionZ() const
Definition: Position.h:99
std::multimap< spellEffectPair, Aura * > AuraMap
Definition: Unit.h:892
Modifier * GetModifier()
Definition: SpellAuras.h:220
int32 m_TrainingPoints
Definition: Pet.h:264
void LearnPetPassives()
Definition: Pet.cpp:1933
void RemovePet(Pet *pet, PetSaveMode mode, bool returnreagent=false)
Definition: Player.cpp:17122
uint32 GetMaxLoyaltyPoints(uint32 level)
Definition: Pet.cpp:823
bool isPossessed() const
Definition: Unit.h:1547
#define ACTIVE_SPELLS_MAX
Definition: Pet.h:142
uint32 GetMapId() const
Definition: Object.h:585
void _SaveSpells()
Definition: Pet.cpp:1323
uint32 GetLoyaltyLevel()
Definition: Pet.h:204
bool IsAutocastableSpell(uint32 spellId)
Definition: SpellMgr.cpp:291
bool addSpell(uint16 spell_id, uint16 active=ACT_DECIDE, PetSpellState state=PETSPELL_NEW, PetSpellType type=PETSPELL_NORMAL)
Definition: Pet.cpp:1487
uint32 m_originalEntry
Definition: Creature.h:923
void SetTP(int32 TP)
Definition: Pet.cpp:837
DBCStorage< CreatureFamilyEntry > sCreatureFamilyStore(CreatureFamilyfmt)
bool PExecute(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:441
virtual void SetSheath(SheathState sheathed)
Definition: Unit.h:1105
Definition: Map.h:266
AuraList m_modAuras[TOTAL_AURAS]
Definition: Unit.h:2147
ReactStates
Pet&#39;s behavior.
Definition: Unit.h:734
void SetIsAtStay(bool val)
Definition: Unit.cpp:13463
T CalculatePct(T base, U pct)
Definition: Util.h:103
CreatureSpellCooldowns m_CreatureSpellCooldowns
Definition: Creature.h:680
void KillLoyaltyBonus(uint32 level)
Definition: Pet.cpp:712
void SetUInt64Value(uint16 index, const uint64 &value)
Definition: Object.cpp:798
uint64 GetOwnerGUID() const
Definition: Unit.h:1451
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value)
Definition: Unit.h:1779
uint32 m_outdoorBonusCheckTimer
Definition: Pet.h:309
void InitPetCreateSpells()
Definition: Pet.cpp:1605
bool IsPet() const
Definition: Unit.h:1020
Pet(Player *owner, PetType type=MAX_PET_TYPE)
Definition: Pet.cpp:54
void SetIsCommandAttack(bool val)
Definition: Unit.cpp:13431
const char * GetName() const
Definition: Object.h:692
void RemoveObject(T *object)
PetSpellMap m_spells
Definition: Pet.h:253
uint32 m_loyaltyTimer
Definition: Pet.h:300
bool CanTakeMoreActiveSpells(uint32 SpellIconID)
Definition: Pet.cpp:737
DeathState
Definition: Unit.h:411
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition: Object.cpp:1006
bool m_removed
Definition: Pet.h:290
ACE_UINT64 uint64
Definition: Define.h:70
void TickLoyaltyChange()
Definition: Pet.cpp:691
ActiveStates
Definition: Unit.h:722
uint64 GetPetGUID() const
Definition: Unit.h:1487
HappinessState GetHappinessState()
Definition: Pet.cpp:722
void SetLoyaltyLevel(LoyaltyLevel level)
Definition: Pet.cpp:732
ReactStates GetReactState() const
Definition: Creature.h:526
CreatureInfo const * GetCreatureTemplate() const
Definition: Creature.h:598
orders pet to follow
Definition: Unit.h:745
uint64 m_auraUpdateMask
Definition: Pet.h:304
bool HaveInDiet(ItemTemplate const *item) const
Definition: Pet.cpp:1205
bool IsBattlegroundOrArena() const
Definition: DBCStructure.h:570
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
Definition: QueryResult.h:113
bool LoadPetFromDB(Player *owner, uint32 petentry=0, uint32 petnumber=0, bool current=false)
Definition: Pet.cpp:131
int32 resistance1
Definition: Creature.h:178
Creature * ToCreature()
Definition: Object.h:389
uint32 Entry
Definition: Creature.h:131
int32 m_bonusdamage
uint32 m_unitTypeMask
Definition: Unit.h:2160
uint16 active
Definition: Pet.h:96
uint32 GetCurrentFoodBenefitLevel(uint32 itemlevel)
Definition: Pet.cpp:1223
void SetFloatValue(uint16 index, float value)
Definition: Object.cpp:859
void RemoveArenaAuras()
Definition: Unit.cpp:4531
uint8 getClass() const
Definition: Unit.h:1039
float baseMoveSpeed[MAX_MOVE_TYPE]
Definition: Unit.cpp:58
CharmInfo * InitCharmInfo()
Definition: Unit.cpp:11142
void SetName(const std::string &newname)
Definition: Object.h:696
void SetPower(Powers power, uint32 val)
Definition: Unit.cpp:10918
int32 GetDamage() const
Definition: SpellMgr.h:764
#define ASSERT
Definition: Errors.h:33
bool IsBattleArena() const
Definition: Map.h:443
void SetMaxPower(Powers power, uint32 val)
Definition: Unit.cpp:10951
void SetSpeed(UnitMoveType mtype, float rate, bool forced=false)
Definition: Unit.cpp:9935
void Update(uint32 time) override
Definition: Creature.cpp:467
PetAuraSet m_petAuras
Definition: Unit.h:2065
void SetGroupUpdateFlag(uint32 flag)
Definition: Player.h:2610
void SetLevel(uint32 lvl)
Definition: Unit.cpp:10817
uint32 GetEntry() const
Definition: Object.h:186
bool IsOutdoors(float x, float y, float z) const
Definition: Map.cpp:1650
bool IsPositionValid() const
Definition: Position.cpp:40
WorldSession * GetSession() const
Definition: Player.h:1959
uint32 resetTalentsCost() const
Definition: Pet.cpp:1685
#define sWorld
Definition: World.h:860
AuraList const & GetAurasByType(AuraType type) const
Definition: Unit.h:1856
DatabaseType CharacterDatabase
Accessor to the character database.
Definition: Main.cpp:54
void SetHealth(uint32 val)
Definition: Unit.cpp:10826
ACE_UINT16 uint16
Definition: Define.h:72
PetFamilySpellsStore sPetFamilySpellsStore
Definition: DBCStores.cpp:120
uint32 dmgschool
Definition: Creature.h:158
void SetBonusDamage(int32 damage)
CreatureSpellCooldowns m_CreatureCategoryCooldowns
Definition: Creature.h:681
ACE_UINT32 uint32
Definition: Define.h:71
Definition: Pet.h:29
uint16 health
Definition: ObjectMgr.h:397
float GetPositionX() const
Definition: Position.h:97
uint32 Type
Definition: Unit.h:700
PetModeFlags
Definition: Pet.h:53
void RegenerateFocus()
Definition: Pet.cpp:616
Definition: Pet.h:72
uint32 GetHealth() const
Definition: Unit.h:1051
uint32 m_resetTalentsCost
Definition: Pet.h:265
void removeSpell(uint16 spell_id)
Definition: Pet.cpp:1588
true
Definition: Log.cpp:534
CreatureFamily family
Definition: Creature.h:165
void RemoveFromWorld() override
Definition: Pet.cpp:120
Definition: Unit.h:884
void SetIsCommandFollow(bool val)
Definition: Unit.cpp:13441
float GetObjectSize() const
Definition: Object.h:663
void SetLoadedState(uint64 caster_guid, uint64 item_caster_guid, int32 damage, int32 maxduration, int32 duration, int32 charges)
Definition: SpellAuras.h:316
uint32 getLevel() const
Definition: Unit.h:1029
void GivePetLevel(uint32 level)
Definition: Pet.cpp:896
Definition: Pet.h:66
void SetReactState(ReactStates st)
Definition: Creature.h:525
std::string name[MAX_DECLINED_NAME_CASES]
Definition: Unit.h:708
Definition: Player.h:922
int32 resistance2
Definition: Creature.h:179
AuraMap m_Auras
Definition: Unit.h:2135
DeathState getDeathState()
Definition: Unit.h:1445
void _SaveSpellCooldowns()
Definition: Pet.cpp:1285
float GetStat(Stats stat) const
Definition: Unit.h:1043
uint32 spellid[4]
Definition: ObjectMgr.h:457
int32 GetSpellDuration(SpellEntry const *spellInfo)
Definition: SpellMgr.cpp:228
uint8 GetByteValue(uint16 index, uint8 offset) const
Definition: Object.h:246
void Remove(PetSaveMode mode, bool returnreagent=false)
Definition: Pet.cpp:853
void LearnSpell(uint32 spell_id)
Definition: Player.cpp:3198
PetType getPetType() const
Definition: Pet.h:155
#define atol(a)
Definition: Common.h:162
uint32 urand(uint32 min, uint32 max)
Definition: Util.cpp:71
void GetClosePoint(float &x, float &y, float &z, float size, float distance2d=0, float angle=0) const
Definition: Object.h:640
const uint64 & GetGUID() const
Definition: Object.h:156
PetSpellState state
Definition: Pet.h:98
HappinessState
Definition: Pet.h:63
DeclinedName * m_declinedname
Definition: Pet.h:306
void CheckLearning(uint32 spellid)
Definition: Pet.cpp:1663
int32 m_loyaltyPoints
Definition: Pet.h:303
float GetSpeedRate(UnitMoveType mtype) const
Definition: Unit.h:1969