Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
PetAI.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Creature.h"
7#include "DBCStores.h"
8#include "Errors.h"
9#include "Group.h"
10#include "ObjectAccessor.h"
11#include "Pet.h"
12#include "PetAI.h"
13#include "Player.h"
14#include "Spell.h"
15#include "SpellInfo.h"
16#include "SpellMgr.h"
17#include "Util.h"
18#include "World.h"
19
20int PetAI::Permissible(const Creature* creature)
21{
22 if (creature->IsPet())
24
25 return PERMIT_BASE_NO;
26}
27
32
34{
35 // This is needed for charmed creatures, as once their target was reset other effects can trigger threat
36 if (me->IsCharmed() && me->GetVictim() == me->GetCharmer())
37 return true;
38
39 return !me->IsValidAttackTarget(me->GetVictim());
40}
41
43{
44 if (!me->IsAlive())
45 {
46 SF_LOG_DEBUG("misc", "Creature stoped attacking cuz his dead [guid=%u]", me->GetGUIDLow());
47 me->GetMotionMaster()->Clear();
48 me->GetMotionMaster()->MoveIdle();
49 me->CombatStop();
50 me->getHostileRefManager().deleteReferences();
51
52 return;
53 }
54
55 me->AttackStop();
56 me->InterruptNonMeleeSpells(false);
57 me->SendMeleeAttackStop(); // Should stop pet's attack button from flashing
58 me->GetCharmInfo()->SetIsCommandAttack(false);
61}
62
64{
65 if (!me->IsAlive() || !me->GetCharmInfo())
66 return;
67
68 Unit* owner = me->GetCharmerOrOwner();
69
70 if (m_updateAlliesTimer <= diff)
71 // UpdateAllies self set update timer
73 else
74 m_updateAlliesTimer -= diff;
75
76 if (me->GetVictim() && me->GetVictim()->IsAlive())
77 {
78 // is only necessary to stop casting, the pet must not exit combat
79 if (me->GetVictim()->HasBreakableByDamageCrowdControlAura(me))
80 {
81 me->InterruptNonMeleeSpells(false);
82 return;
83 }
84
85 if (_needToStop())
86 {
87 SF_LOG_DEBUG("misc", "Pet AI stopped attacking [guid=%u]", me->GetGUIDLow());
89 return;
90 }
91
92 // Check before attacking to prevent pets from leaving stay position
93 if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY))
94 {
95 if (me->GetCharmInfo()->IsCommandAttack() || (me->GetCharmInfo()->IsAtStay() && me->IsWithinMeleeRange(me->GetVictim())))
97 }
98 else
100 }
101 else
102 {
103 if (me->HasReactState(REACT_AGGRESSIVE) || me->GetCharmInfo()->IsAtStay())
104 {
105 // Every update we need to check targets only in certain cases
106 // Aggressive - Allow auto select if owner or pet don't have a target
107 // Stay - Only pick from pet or owner targets / attackers so targets won't run by
108 // while chasing our owner. Don't do auto select.
109 // All other cases (ie: defensive) - Targets are assigned by AttackedBy(), OwnerAttackedBy(), OwnerAttacked(), etc.
110 Unit* nextTarget = SelectNextTarget(me->HasReactState(REACT_AGGRESSIVE));
111
112 if (nextTarget)
113 AttackStart(nextTarget);
114 else
116 }
117 else
119 }
120
121 // Autocast (casted only in combat or persistent spells in any state)
122 if (!me->HasUnitState(UNIT_STATE_CASTING))
123 {
124 typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
125 TargetSpellList targetSpellStore;
126
127 for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
128 {
129 uint32 spellID = me->GetPetAutoSpellOnPos(i);
130 if (!spellID)
131 continue;
132
133 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
134 if (!spellInfo)
135 continue;
136
137 if (me->GetCharmInfo() && me->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
138 continue;
139
140 if (spellInfo->IsPositive())
141 {
142 if (spellInfo->CanBeUsedInCombat())
143 {
144 // check spell cooldown
145 if (me->HasSpellCooldown(spellInfo->Id))
146 continue;
147
148 // Check if we're in combat or commanded to attack
149 if (!me->IsInCombat() && !me->GetCharmInfo()->IsCommandAttack())
150 continue;
151 }
152
153 Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);
154 bool spellUsed = false;
155
156 // Some spells can target enemy or friendly (DK Ghoul's Leap)
157 // Check for enemy first (pet then owner)
158 Unit* target = me->getAttackerForHelper();
159 if (!target && owner)
160 target = owner->getAttackerForHelper();
161
162 if (target)
163 {
164 if (CanAttack(target) && spell->CanAutoCast(target))
165 {
166 targetSpellStore.push_back(std::make_pair(target, spell));
167 spellUsed = true;
168 }
169 }
170
171 if (spellInfo->HasEffect(SPELL_EFFECT_JUMP_DEST))
172 continue; // Pets must only jump to target
173
174 // No enemy, check friendly
175 if (!spellUsed)
176 {
177 for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
178 {
179 Unit* ally = ObjectAccessor::GetUnit(*me, *tar);
180
181 //only buff targets that are in combat, unless the spell can only be cast while out of combat
182 if (!ally)
183 continue;
184
185 if (spell->CanAutoCast(ally))
186 {
187 targetSpellStore.push_back(std::make_pair(ally, spell));
188 spellUsed = true;
189 break;
190 }
191 }
192 }
193
194 // No valid targets at all
195 if (!spellUsed)
196 delete spell;
197 }
198 else if (me->GetVictim() && CanAttack(me->GetVictim()) && spellInfo->CanBeUsedInCombat())
199 {
200 Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);
201 if (spell->CanAutoCast(me->GetVictim()))
202 targetSpellStore.push_back(std::make_pair(me->GetVictim(), spell));
203 else
204 delete spell;
205 }
206 }
207
208 //found units to cast on to
209 if (!targetSpellStore.empty())
210 {
211 uint32 index = std::rand() % targetSpellStore.size();
212
213 Spell* spell = targetSpellStore[index].second;
214 Unit* target = targetSpellStore[index].first;
215
216 targetSpellStore.erase(targetSpellStore.begin() + index);
217
218 SpellCastTargets targets;
219 targets.SetUnitTarget(target);
220
221 if (!me->HasInArc(M_PI, target))
222 {
223 me->SetInFront(target);
224 if (target && target->GetTypeId() == TypeID::TYPEID_PLAYER)
225 me->SendUpdateToPlayer(target->ToPlayer());
226
227 if (owner && owner->GetTypeId() == TypeID::TYPEID_PLAYER)
228 me->SendUpdateToPlayer(owner->ToPlayer());
229 }
230
231 me->AddCreatureSpellCooldown(spell->m_spellInfo->Id);
232
233 spell->prepare(&targets);
234 }
235
236 // deleted cached Spell objects
237 for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
238 delete itr->second;
239 }
240
241 // Update speed as needed to prevent dropping too far behind and despawning
242 me->UpdateSpeed(MOVE_RUN, true);
243 me->UpdateSpeed(MOVE_WALK, true);
244 me->UpdateSpeed(MOVE_FLIGHT, true);
245}
246
248{
249 m_updateAlliesTimer = 10 * IN_MILLISECONDS; // update friendly targets every 10 seconds, lesser checks increase performance
250
251 Unit* owner = me->GetCharmerOrOwner();
252 if (!owner)
253 return;
254
255 Group* group = NULL;
256 if (Player* player = owner->ToPlayer())
257 group = player->GetGroup();
258
259 //only pet and owner/not in group->ok
260 if (m_AllySet.size() == 2 && !group)
261 return;
262
263 //owner is in group; group members filled in already (no raid -> subgroupcount = whole count)
264 if (group && !group->isRaidGroup() && m_AllySet.size() == (group->GetMembersCount() + 2))
265 return;
266
267 m_AllySet.clear();
268 m_AllySet.insert(me->GetGUID());
269 if (group) //add group
270 {
271 for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
272 {
273 Player* Target = itr->GetSource();
274 if (!Target || !group->SameSubGroup(owner->ToPlayer(), Target))
275 continue;
276
277 if (Target->GetGUID() == owner->GetGUID())
278 continue;
279
280 m_AllySet.insert(Target->GetGUID());
281 }
282 }
283 else //remove group
284 m_AllySet.insert(owner->GetGUID());
285}
286
288{
289 // Called from Unit::Kill() in case where pet or owner kills something
290 // if owner killed this victim, pet may still be attacking something else
291 if (me->GetVictim() && me->GetVictim() != victim)
292 return;
293
294 // Clear target just in case. May help problem where health / focus / mana
295 // regen gets stuck. Also resets attack command.
296 // Can't use _stopAttack() because that activates movement handlers and ignores
297 // next target selection
298 me->AttackStop();
299 me->InterruptNonMeleeSpells(false);
300 me->SendMeleeAttackStop(); // Stops the pet's 'Attack' button from flashing
301
302 // Before returning to owner, see if there are more things to attack
303 if (Unit* nextTarget = SelectNextTarget(false))
304 AttackStart(nextTarget);
305 else
306 HandleReturnMovement(); // Return
307}
308
310{
311 // Overrides Unit::AttackStart to correctly evaluate Pet states
312
313 // Check all pet states to decide if we can attack this target
314 if (!CanAttack(target))
315 return;
316
317 // Only chase if not commanded to stay or if stay but commanded to attack
318 DoAttack(target, (!me->GetCharmInfo()->HasCommandState(COMMAND_STAY) || me->GetCharmInfo()->IsCommandAttack()));
319}
320
322{
323 // Called when owner takes damage. This function helps keep pets from running off
324 // simply due to owner gaining aggro.
325
326 if (!attacker)
327 return;
328
329 // Passive pets don't do anything
330 if (me->HasReactState(REACT_PASSIVE))
331 return;
332
333 // Prevent pet from disengaging from current target
334 if (me->GetVictim() && me->GetVictim()->IsAlive())
335 return;
336
337 // Continue to evaluate and attack if necessary
338 AttackStart(attacker);
339}
340
342{
343 // Called when owner attacks something. Allows defensive pets to know
344 // that they need to assist
345
346 // Target might be NULL if called from spell with invalid cast targets
347 if (!target)
348 return;
349
350 // Passive pets don't do anything
351 if (me->HasReactState(REACT_PASSIVE))
352 return;
353
354 // Prevent pet from disengaging from current target
355 if (me->GetVictim() && me->GetVictim()->IsAlive())
356 return;
357
358 // Continue to evaluate and attack if necessary
359 AttackStart(target);
360}
361
362Unit* PetAI::SelectNextTarget(bool allowAutoSelect) const
363{
364 // Provides next target selection after current target death.
365 // This function should only be called internally by the AI
366 // Targets are not evaluated here for being valid targets, that is done in _CanAttack()
367 // The parameter: allowAutoSelect lets us disable aggressive pet auto targeting for certain situations
368
369 // Passive pets don't do next target selection
370 if (me->HasReactState(REACT_PASSIVE))
371 return NULL;
372
373 // Check pet attackers first so we don't drag a bunch of targets to the owner
374 if (Unit* myAttacker = me->getAttackerForHelper())
375 if (!myAttacker->HasBreakableByDamageCrowdControlAura())
376 return myAttacker;
377
378 // Not sure why we wouldn't have an owner but just in case...
379 if (!me->GetCharmerOrOwner())
380 return NULL;
381
382 // Check owner attackers
383 if (Unit* ownerAttacker = me->GetCharmerOrOwner()->getAttackerForHelper())
384 if (!ownerAttacker->HasBreakableByDamageCrowdControlAura())
385 return ownerAttacker;
386
387 // Check owner victim
388 // 3.0.2 - Pets now start attacking their owners victim in defensive mode as soon as the hunter does
389 if (Unit* ownerVictim = me->GetCharmerOrOwner()->GetVictim())
390 return ownerVictim;
391
392 // Neither pet or owner had a target and aggressive pets can pick any target
393 // To prevent aggressive pets from chain selecting targets and running off, we
394 // only select a random target if certain conditions are met.
395 if (me->HasReactState(REACT_AGGRESSIVE) && allowAutoSelect)
396 {
397 if (!me->GetCharmInfo()->IsReturning() || me->GetCharmInfo()->IsFollowing() || me->GetCharmInfo()->IsAtStay())
398 if (Unit* nearTarget = me->ToCreature()->SelectNearestHostileUnitInAggroRange(true))
399 return nearTarget;
400 }
401
402 // Default - no valid targets
403 return NULL;
404}
405
407{
408 // Handles moving the pet back to stay or owner
409
410 // Prevent activating movement when under control of spells
411 // such as "Eyes of the Beast"
412 if (me->IsCharmed())
413 return;
414
415 if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY))
416 {
417 if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning())
418 {
419 // Return to previous position where stay was clicked
420 float x, y, z;
421
422 me->GetCharmInfo()->GetStayPosition(x, y, z);
424 me->GetCharmInfo()->SetIsReturning(true);
425 me->GetMotionMaster()->Clear();
426 me->GetMotionMaster()->MovePoint(me->GetGUIDLow(), x, y, z);
427 }
428 }
429 else // COMMAND_FOLLOW
430 {
431 if (!me->GetCharmInfo()->IsFollowing() && !me->GetCharmInfo()->IsReturning())
432 {
434 me->GetCharmInfo()->SetIsReturning(true);
435 me->GetMotionMaster()->Clear();
436 me->GetMotionMaster()->MoveFollow(me->GetCharmerOrOwner(), PET_FOLLOW_DIST, me->GetFollowAngle());
437 }
438 }
439}
440
441void PetAI::DoAttack(Unit* target, bool chase)
442{
443 // Handles attack with or without chase and also resets flags
444 // for next update / creature kill
445
446 if (me->Attack(target, true))
447 {
448 if (Unit* owner = me->GetOwner())
449 owner->SetInCombatWith(target);
450
451 // Play sound to let the player know the pet is attacking something it picked on its own
452 if (me->HasReactState(REACT_AGGRESSIVE) && !me->GetCharmInfo()->IsCommandAttack())
453 me->SendPetAIReaction(me->GetGUID());
454
455 if (chase)
456 {
457 bool oldCmdAttack = me->GetCharmInfo()->IsCommandAttack(); // This needs to be reset after other flags are cleared
459 me->GetCharmInfo()->SetIsCommandAttack(oldCmdAttack); // For passive pets commanded to attack so they will use spells
460 me->GetMotionMaster()->Clear();
461 me->GetMotionMaster()->MoveChase(target);
462 }
463 else // (Stay && ((Aggressive || Defensive) && In Melee Range)))
464 {
466 me->GetCharmInfo()->SetIsAtStay(true);
467 me->GetMotionMaster()->Clear();
468 me->GetMotionMaster()->MoveIdle();
469 }
470 }
471}
472
474{
475 // Receives notification when pet reaches stay or follow owner
476 switch (moveType)
477 {
479 {
480 // Pet is returning to where stay was clicked. data should be
481 // pet's GUIDLow since we set that as the waypoint ID
482 if (data == me->GetGUIDLow() && me->GetCharmInfo()->IsReturning())
483 {
485 me->GetCharmInfo()->SetIsAtStay(true);
486 me->GetMotionMaster()->Clear();
487 me->GetMotionMaster()->MoveIdle();
488 }
489 break;
490 }
492 {
493 // If data is owner's GUIDLow then we've reached follow point,
494 // otherwise we're probably chasing a creature
495 if (me->GetCharmerOrOwner() && me->GetCharmInfo() && data == me->GetCharmerOrOwner()->GetGUIDLow() && me->GetCharmInfo()->IsReturning())
496 {
498 me->GetCharmInfo()->SetIsFollowing(true);
499 }
500 break;
501 }
502 default:
503 break;
504 }
505}
506
508{
509 // Evaluates wether a pet can attack a specific target based on CommandState, ReactState and other flags
510 // IMPORTANT: The order in which things are checked is important, be careful if you add or remove checks
511
512 // Hmmm...
513 if (!target)
514 return false;
515
516 if (!target->IsAlive())
517 {
518 // Clear target to prevent getting stuck on dead targets
519 me->AttackStop();
520 me->InterruptNonMeleeSpells(false);
521 me->SendMeleeAttackStop();
522 return false;
523 }
524
525 // Passive - passive pets can attack if told to
526 if (me->HasReactState(REACT_PASSIVE))
527 return me->GetCharmInfo()->IsCommandAttack();
528
529 // CC - mobs under crowd control can be attacked if owner commanded
531 return me->GetCharmInfo()->IsCommandAttack();
532
533 // Returning - pets ignore attacks only if owner clicked follow
534 if (me->GetCharmInfo()->IsReturning())
535 return !me->GetCharmInfo()->IsCommandFollow();
536
537 // Stay - can attack if target is within range or commanded to
538 if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY))
539 return (me->IsWithinMeleeRange(target) || me->GetCharmInfo()->IsCommandAttack());
540
541 // Pets attacking something (or chasing) should only switch targets if owner tells them to
542 if (me->GetVictim() && me->GetVictim() != target)
543 {
544 // Check if our owner selected this target and clicked "attack"
545 Unit* ownerTarget = NULL;
546 if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
547 ownerTarget = owner->GetSelectedUnit();
548 else
549 ownerTarget = me->GetCharmerOrOwner()->GetVictim();
550
551 if (ownerTarget && me->GetCharmInfo()->IsCommandAttack())
552 return (target->GetGUID() == ownerTarget->GetGUID());
553 }
554
555 // Follow
556 if (me->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
557 return !me->GetCharmInfo()->IsReturning();
558
559 // default, though we shouldn't ever get here
560 return false;
561}
562
564{
565 if (me->GetOwnerGUID() && me->GetOwnerGUID() == player->GetGUID())
566 switch (emote)
567 {
568 case TEXT_EMOTE_COWER:
569 if (me->IsPet() && me->ToPet()->IsPetGhoul())
570 me->HandleEmoteCommand(/*EMOTE_ONESHOT_ROAR*/EMOTE_ONESHOT_OMNICAST_GHOUL);
571 break;
572 case TEXT_EMOTE_ANGRY:
573 if (me->IsPet() && me->ToPet()->IsPetGhoul())
574 me->HandleEmoteCommand(/*EMOTE_ONESHOT_COWER*/EMOTE_STATE_STUN);
575 break;
576 case TEXT_EMOTE_GLARE:
577 if (me->IsPet() && me->ToPet()->IsPetGhoul())
578 me->HandleEmoteCommand(EMOTE_STATE_STUN);
579 break;
581 if (me->IsPet() && me->ToPet()->IsPetGhoul())
582 me->HandleEmoteCommand(EMOTE_ONESHOT_OMNICAST_GHOUL);
583 break;
584 }
585}
586
588{
589 // Quick access to set all flags to FALSE
590
591 CharmInfo* ci = me->GetCharmInfo();
592
593 if (ci)
594 {
595 ci->SetIsAtStay(false);
596 ci->SetIsCommandAttack(false);
597 ci->SetIsCommandFollow(false);
598 ci->SetIsFollowing(false);
599 ci->SetIsReturning(false);
600 }
601}
602
603void PetAI::AttackedBy(Unit* attacker)
604{
605 // Called when pet takes damage. This function helps keep pets from running off
606 // simply due to gaining aggro.
607
608 if (!attacker)
609 return;
610
611 // Passive pets don't do anything
612 if (me->HasReactState(REACT_PASSIVE))
613 return;
614
615 // Prevent pet from disengaging from current target
616 if (me->GetVictim() && me->GetVictim()->IsAlive())
617 return;
618
619 // Continue to evaluate and attack if necessary
620 AttackStart(attacker);
621}
@ IN_MILLISECONDS
Definition Common.h:125
#define M_PI
Definition Common.h:192
#define TIME_INTERVAL_LOOK
Definition CreatureAI.h:19
@ PERMIT_BASE_SPECIAL
Definition CreatureAI.h:185
@ PERMIT_BASE_NO
Definition CreatureAI.h:180
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
@ POINT_MOTION_TYPE
@ FOLLOW_MOTION_TYPE
@ TYPEID_PLAYER
Definition Object.h:55
#define PET_FOLLOW_DIST
Definition PetDefines.h:57
@ EMOTE_ONESHOT_OMNICAST_GHOUL
@ EMOTE_STATE_STUN
@ SPELL_EFFECT_JUMP_DEST
@ TEXT_EMOTE_ANGRY
@ TEXT_EMOTE_SOOTHE
@ TEXT_EMOTE_COWER
@ TEXT_EMOTE_GLARE
#define sSpellMgr
Definition SpellMgr.h:744
@ COMMAND_STAY
Definition Unit.h:1164
@ COMMAND_FOLLOW
Definition Unit.h:1165
@ TRIGGERED_NONE
Definition Unit.h:416
@ UNIT_STATE_CASTING
Definition Unit.h:527
@ MOVE_FLIGHT
Definition Unit.h:561
@ MOVE_RUN
Definition Unit.h:556
@ MOVE_WALK
Definition Unit.h:555
@ REACT_PASSIVE
Definition Unit.h:1156
@ REACT_AGGRESSIVE
Definition Unit.h:1158
CreatureAI(Creature *creature)
Definition CreatureAI.h:69
Creature *const me
Definition CreatureAI.h:56
Definition Group.h:147
uint32 GetMembersCount() const
Definition Group.h:227
GroupReference * GetFirstMember()
Definition Group.h:225
bool SameSubGroup(uint64 guid1, uint64 guid2) const
Definition Group.cpp:2629
bool isRaidGroup() const
Definition Group.cpp:2548
GroupReference * next()
static Unit * GetUnit(WorldObject const &, uint64 guid)
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
TypeID GetTypeId() const
Definition Object.h:131
void OwnerAttacked(Unit *target) OVERRIDE
Definition PetAI.cpp:341
bool _needToStop(void)
Definition PetAI.cpp:33
bool CanAttack(Unit *target)
Definition PetAI.cpp:507
static int Permissible(const Creature *)
Definition PetAI.cpp:20
void UpdateAllies()
Definition PetAI.cpp:247
void AttackedBy(Unit *attacker) OVERRIDE
Definition PetAI.cpp:603
bool inCombat
Definition PetAI.h:46
void KilledUnit(Unit *) OVERRIDE
Definition PetAI.cpp:287
void DoAttack(Unit *target, bool chase)
Definition PetAI.cpp:441
PetAI(Creature *c)
Definition PetAI.cpp:28
void MovementInform(uint32 moveType, uint32 data) OVERRIDE
Definition PetAI.cpp:473
TimeTracker i_tracker
Definition PetAI.h:45
void OwnerAttackedBy(Unit *attacker) OVERRIDE
Definition PetAI.cpp:321
void ClearCharmInfoFlags()
Definition PetAI.cpp:587
uint32 m_updateAlliesTimer
Definition PetAI.h:48
void AttackStart(Unit *target) OVERRIDE
Definition PetAI.cpp:309
void _stopAttack(void)
Definition PetAI.cpp:42
Unit * SelectNextTarget(bool allowAutoSelect) const
Definition PetAI.cpp:362
void ReceiveEmote(Player *player, uint32 textEmote) OVERRIDE
Definition PetAI.cpp:563
void HandleReturnMovement()
Definition PetAI.cpp:406
std::set< uint64 > m_AllySet
Definition PetAI.h:47
void UpdateAI(uint32) OVERRIDE
== Triggered Actions Requested ==================
Definition PetAI.cpp:63
void SetUnitTarget(Unit *target)
Definition Spell.cpp:228
Definition Spell.h:289
void prepare(SpellCastTargets const *targets, AuraEffect const *triggeredByAura=NULL)
Definition Spell.cpp:2939
SpellInfo const *const m_spellInfo
Definition Spell.h:530
bool CanAutoCast(Unit *target)
Definition Spell.cpp:6559
uint32 Id
Definition SpellInfo.h:160
bool CanBeUsedInCombat() const
bool HasEffect(SpellEffects effect) const
bool IsPositive() const
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
Definition Unit.h:1367
Unit * getAttackerForHelper() const
bool IsPet() const
Definition Unit.h:1511
bool IsAlive() const
Definition Unit.h:2032
bool HasBreakableByDamageCrowdControlAura(Unit *excludeCasterChannel=NULL) const
Definition Unit.cpp:589
void SetIsCommandFollow(bool val)
Definition Unit.cpp:9072
void SetIsAtStay(bool val)
Definition Unit.cpp:9093
void SetIsFollowing(bool val)
Definition Unit.cpp:9098
void SetIsReturning(bool val)
Definition Unit.cpp:9103
void SetIsCommandAttack(bool val)
Definition Unit.cpp:9067