TrinityCore
Loading...
Searching...
No Matches
PetAI.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "PetAI.h"
19#include "AIException.h"
20#include "Creature.h"
21#include "Errors.h"
22#include "Group.h"
23#include "Log.h"
24#include "MotionMaster.h"
25#include "ObjectAccessor.h"
26#include "Pet.h"
27#include "Player.h"
28#include "Spell.h"
29#include "SpellHistory.h"
30#include "SpellInfo.h"
31#include "SpellMgr.h"
32#include "Util.h"
33
35{
37 {
38 if (reinterpret_cast<Guardian const*>(creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)
41 }
42
43 return PERMIT_BASE_NO;
44}
45
46PetAI::PetAI(Creature* creature) : CreatureAI(creature), _tracker(TIME_INTERVAL_LOOK)
47{
48 if (!me->GetCharmInfo())
49 throw InvalidAIException("Creature doesn't have a valid charm info");
50
52}
53
55{
56 if (!me->IsAlive() || !me->GetCharmInfo())
57 return;
58
59 Unit* owner = me->GetCharmerOrOwner();
60
61 if (_updateAlliesTimer <= diff)
62 // UpdateAllies self set update timer
64 else
65 _updateAlliesTimer -= diff;
66
67 if (me->GetVictim() && me->EnsureVictim()->IsAlive())
68 {
69 // is only necessary to stop casting, the pet must not exit combat
70 if (!me->GetCurrentSpell(CURRENT_CHANNELED_SPELL) && // ignore channeled spells (Pin, Seduction)
72 {
74 return;
75 }
76
77 if (NeedToStop())
78 {
79 TC_LOG_TRACE("scripts.ai.petai", "PetAI::UpdateAI: AI stopped attacking {}", me->GetGUID().ToString());
80 StopAttack();
81 return;
82 }
83
84 // Check before attacking to prevent pets from leaving stay position
86 {
89 }
90 else
92 }
93 else
94 {
96 {
97 // Every update we need to check targets only in certain cases
98 // Aggressive - Allow auto select if owner or pet don't have a target
99 // Stay - Only pick from pet or owner targets / attackers so targets won't run by
100 // while chasing our owner. Don't do auto select.
101 // All other cases (ie: defensive) - Targets are assigned by DamageTaken(), OwnerAttackedBy(), OwnerAttacked(), etc.
103
104 if (nextTarget)
105 AttackStart(nextTarget);
106 else
108 }
109 else
111 }
112
113 // Autocast (cast only in combat or persistent spells in any state)
115 {
116 TargetSpellList targetSpellStore;
117
118 for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
119 {
120 uint32 spellID = me->GetPetAutoSpellOnPos(i);
121 if (!spellID)
122 continue;
123
124 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
125 if (!spellInfo)
126 continue;
127
128 if (me->GetSpellHistory()->HasGlobalCooldown(spellInfo))
129 continue;
130
131 // check spell cooldown
132 if (!me->GetSpellHistory()->IsReady(spellInfo))
133 continue;
134
135 if (spellInfo->IsPositive())
136 {
137 if (spellInfo->CanBeUsedInCombat())
138 {
139 // Check if we're in combat or commanded to attack
140 if (!me->IsInCombat() && !me->GetCharmInfo()->IsCommandAttack())
141 continue;
142 }
143
144 Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE);
145 bool spellUsed = false;
146
147 // Some spells can target enemy or friendly (DK Ghoul's Leap)
148 // Check for enemy first (pet then owner)
149 Unit* target = me->getAttackerForHelper();
150 if (!target && owner)
151 target = owner->getAttackerForHelper();
152
153 if (target)
154 {
155 if (CanAttack(target) && spell->CanAutoCast(target))
156 {
157 targetSpellStore.push_back(std::make_pair(target, spell));
158 spellUsed = true;
159 }
160 }
161
162 if (spellInfo->HasEffect(SPELL_EFFECT_JUMP_DEST))
163 {
164 if (!spellUsed)
165 delete spell;
166 continue; // Pets must only jump to target
167 }
168
169 // No enemy, check friendly
170 if (!spellUsed)
171 {
172 for (ObjectGuid target : _allySet)
173 {
174 Unit* ally = ObjectAccessor::GetUnit(*me, target);
175
176 //only buff targets that are in combat, unless the spell can only be cast while out of combat
177 if (!ally)
178 continue;
179
180 if (spell->CanAutoCast(ally))
181 {
182 targetSpellStore.push_back(std::make_pair(ally, spell));
183 spellUsed = true;
184 break;
185 }
186 }
187 }
188
189 // No valid targets at all
190 if (!spellUsed)
191 delete spell;
192 }
193 else if (me->GetVictim() && CanAttack(me->GetVictim()) && spellInfo->CanBeUsedInCombat())
194 {
195 Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE);
196 if (spell->CanAutoCast(me->GetVictim()))
197 targetSpellStore.push_back(std::make_pair(me->GetVictim(), spell));
198 else
199 delete spell;
200 }
201 }
202
203 // found units to cast on to
204 if (!targetSpellStore.empty())
205 {
206 TargetSpellList::iterator it = targetSpellStore.begin();
207 std::advance(it, urand(0, targetSpellStore.size() - 1));
208
209 Spell* spell = (*it).second;
210 Unit* target = (*it).first;
211
212 targetSpellStore.erase(it);
213
214 SpellCastTargets targets;
215 targets.SetUnitTarget(target);
216
217 spell->prepare(targets);
218 }
219
220 // deleted cached Spell objects
221 for (std::pair<Unit*, Spell*> const& unitspellpair : targetSpellStore)
222 delete unitspellpair.second;
223 }
224
225 // Update speed as needed to prevent dropping too far behind and despawning
229
230}
231
233{
234 // Called from Unit::Kill() in case where pet or owner kills something
235 // if owner killed this victim, pet may still be attacking something else
236 if (me->GetVictim() && me->GetVictim() != victim)
237 return;
238
239 // Clear target just in case. May help problem where health / focus / mana
240 // regen gets stuck. Also resets attack command.
241 // Can't use StopAttack() because that activates movement handlers and ignores
242 // next target selection
243 me->AttackStop();
245
246 // Before returning to owner, see if there are more things to attack
247 if (Unit* nextTarget = SelectNextTarget(false))
248 AttackStart(nextTarget);
249 else
250 HandleReturnMovement(); // Return
251}
252
254{
255 // Overrides Unit::AttackStart to prevent pet from switching off its assigned target
256 if (!target || target == me)
257 return;
258
259 if (me->GetVictim() && me->EnsureVictim()->IsAlive())
260 return;
261
262 _AttackStart(target);
263}
264
266{
267 // Check all pet states to decide if we can attack this target
268 if (!CanAttack(target))
269 return;
270
271 // Only chase if not commanded to stay or if stay but commanded to attack
273}
274
276{
277 // Called when owner takes damage. This function helps keep pets from running off
278 // simply due to owner gaining aggro.
279
280 if (!attacker || !me->IsAlive())
281 return;
282
283 // Passive pets don't do anything
285 return;
286
287 // Prevent pet from disengaging from current target
288 if (me->GetVictim() && me->EnsureVictim()->IsAlive())
289 return;
290
291 // Continue to evaluate and attack if necessary
292 AttackStart(attacker);
293}
294
296{
297 // Called when owner attacks something. Allows defensive pets to know
298 // that they need to assist
299
300 // Target might be NULL if called from spell with invalid cast targets
301 if (!target || !me->IsAlive())
302 return;
303
304 // Passive pets don't do anything
306 return;
307
308 // Prevent pet from disengaging from current target
309 if (me->GetVictim() && me->EnsureVictim()->IsAlive())
310 return;
311
312 // Continue to evaluate and attack if necessary
313 AttackStart(target);
314}
315
316Unit* PetAI::SelectNextTarget(bool allowAutoSelect) const
317{
318 // Provides next target selection after current target death.
319 // This function should only be called internally by the AI
320 // Targets are not evaluated here for being valid targets, that is done in _CanAttack()
321 // The parameter: allowAutoSelect lets us disable aggressive pet auto targeting for certain situations
322
323 // Passive pets don't do next target selection
325 return nullptr;
326
327 // Check pet attackers first so we don't drag a bunch of targets to the owner
328 if (Unit* myAttacker = me->getAttackerForHelper())
329 if (!myAttacker->HasBreakableByDamageCrowdControlAura())
330 return myAttacker;
331
332 // Not sure why we wouldn't have an owner but just in case...
333 if (!me->GetCharmerOrOwner())
334 return nullptr;
335
336 // Check owner attackers
337 if (Unit* ownerAttacker = me->GetCharmerOrOwner()->getAttackerForHelper())
338 if (!ownerAttacker->HasBreakableByDamageCrowdControlAura())
339 return ownerAttacker;
340
341 // Check owner victim
342 // 3.0.2 - Pets now start attacking their owners victim in defensive mode as soon as the hunter does
343 if (Unit* ownerVictim = me->GetCharmerOrOwner()->GetVictim())
344 return ownerVictim;
345
346 // Neither pet or owner had a target and aggressive pets can pick any target
347 // To prevent aggressive pets from chain selecting targets and running off, we
348 // only select a random target if certain conditions are met.
349 if (me->HasReactState(REACT_AGGRESSIVE) && allowAutoSelect)
350 {
352 if (Unit* nearTarget = me->SelectNearestHostileUnitInAggroRange(true, true))
353 return nearTarget;
354 }
355
356 // Default - no valid targets
357 return nullptr;
358}
359
361{
362 // Handles moving the pet back to stay or owner
363
364 // Prevent activating movement when under control of spells
365 // such as "Eyes of the Beast"
366 if (me->isPossessed())
367 return;
368
369 if (!me->GetCharmInfo())
370 {
371 TC_LOG_WARN("scripts.ai.petai", "me->GetCharmInfo() is NULL in PetAI::HandleReturnMovement(). Debug info: {}", GetDebugInfo());
372 return;
373 }
374
376 {
377 if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning())
378 {
379 // Return to previous position where stay was clicked
380 float x, y, z;
381
382 me->GetCharmInfo()->GetStayPosition(x, y, z);
385
388
389 me->GetMotionMaster()->MovePoint(me->GetGUID().GetCounter(), x, y, z);
390 }
391 }
392 else // COMMAND_FOLLOW
393 {
395 {
398
401
403 }
404 }
405 me->RemoveUnitFlag(UNIT_FLAG_PET_IN_COMBAT); // on player pets, this flag indicates that we're actively going after a target - we're returning, so remove it
406}
407
408void PetAI::DoAttack(Unit* target, bool chase)
409{
410 // Handles attack with or without chase and also resets flags
411 // for next update / creature kill
412
413 if (me->Attack(target, true))
414 {
415 me->SetUnitFlag(UNIT_FLAG_PET_IN_COMBAT); // on player pets, this flag indicates we're actively going after a target - that's what we're doing, so set it
416 // Play sound to let the player know the pet is attacking something it picked on its own
419
420 if (chase)
421 {
422 bool oldCmdAttack = me->GetCharmInfo()->IsCommandAttack(); // This needs to be reset after other flags are cleared
424 me->GetCharmInfo()->SetIsCommandAttack(oldCmdAttack); // For passive pets commanded to attack so they will use spells
425
428
429 // Pets with ranged attacks should not care about the chase angle at all.
430 float chaseDistance = me->GetPetChaseDistance();
431 float angle = chaseDistance == 0.f ? float(M_PI) : 0.f;
432 float tolerance = chaseDistance == 0.f ? float(M_PI_4) : float(M_PI * 2);
433 me->GetMotionMaster()->MoveChase(target, ChaseRange(0.f, chaseDistance), ChaseAngle(angle, tolerance));
434 }
435 else // (Stay && ((Aggressive || Defensive) && In Melee Range)))
436 {
438 me->GetCharmInfo()->SetIsAtStay(true);
439
442
444 }
445 }
446}
447
449{
450 // Receives notification when pet reaches stay or follow owner
451 switch (type)
452 {
454 {
455 // Pet is returning to where stay was clicked. data should be
456 // pet's GUIDLow since we set that as the waypoint ID
457 if (id == me->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning())
458 {
460 me->GetCharmInfo()->SetIsAtStay(true);
462 }
463 break;
464 }
466 {
467 // If data is owner's GUIDLow then we've reached follow point,
468 // otherwise we're probably chasing a creature
470 {
473 }
474 break;
475 }
476 default:
477 break;
478 }
479}
480
482{
483 // Evaluates wether a pet can attack a specific target based on CommandState, ReactState and other flags
484 // IMPORTANT: The order in which things are checked is important, be careful if you add or remove checks
485
486 // Hmmm...
487 if (!target)
488 return false;
489
490 if (!target->IsAlive())
491 {
492 // if target is invalid, pet should evade automaticly
493 // Clear target to prevent getting stuck on dead targets
494 //me->AttackStop();
495 //me->InterruptNonMeleeSpells(false);
496 return false;
497 }
498
499 if (!me->GetCharmInfo())
500 {
501 TC_LOG_WARN("scripts.ai.petai", "me->GetCharmInfo() is NULL in PetAI::CanAttack(). Debug info: {}", GetDebugInfo());
502 return false;
503 }
504
505 // Passive - passive pets can attack if told to
507 return me->GetCharmInfo()->IsCommandAttack();
508
509 // CC - mobs under crowd control can be attacked if owner commanded
511 return me->GetCharmInfo()->IsCommandAttack();
512
513 // Returning - pets ignore attacks only if owner clicked follow
514 if (me->GetCharmInfo()->IsReturning())
515 return !me->GetCharmInfo()->IsCommandFollow();
516
517 // Stay - can attack if target is within range or commanded to
519 return (me->IsWithinMeleeRange(target) || me->GetCharmInfo()->IsCommandAttack());
520
521 // Pets attacking something (or chasing) should only switch targets if owner tells them to
522 if (me->GetVictim() && me->GetVictim() != target)
523 {
524 // Check if our owner selected this target and clicked "attack"
525 Unit* ownerTarget = nullptr;
526 if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
527 ownerTarget = owner->GetSelectedUnit();
528 else
529 ownerTarget = me->GetCharmerOrOwner()->GetVictim();
530
531 if (ownerTarget && me->GetCharmInfo()->IsCommandAttack())
532 return (target->GetGUID() == ownerTarget->GetGUID());
533 }
534
535 // Follow
537 return !me->GetCharmInfo()->IsReturning();
538
539 // default, though we shouldn't ever get here
540 return false;
541}
542
544{
545 if (me->GetOwnerGUID() != player->GetGUID())
546 return;
547
548 switch (emote)
549 {
550 case TEXT_EMOTE_COWER:
551 if (me->IsPet() && me->ToPet()->IsPetGhoul())
552 me->HandleEmoteCommand(/*EMOTE_ONESHOT_ROAR*/EMOTE_ONESHOT_OMNICAST_GHOUL);
553 break;
554 case TEXT_EMOTE_ANGRY:
555 if (me->IsPet() && me->ToPet()->IsPetGhoul())
556 me->HandleEmoteCommand(/*EMOTE_ONESHOT_COWER*/EMOTE_STATE_STUN);
557 break;
558 case TEXT_EMOTE_GLARE:
559 if (me->IsPet() && me->ToPet()->IsPetGhoul())
561 break;
563 if (me->IsPet() && me->ToPet()->IsPetGhoul())
565 break;
566 }
567}
568
570{
571 // This is needed for charmed creatures, as once their target was reset other effects can trigger threat
572 if (me->IsCharmed() && me->GetVictim() == me->GetCharmer())
573 return true;
574
575 // dont allow pets to follow targets far away from owner
576 if (Unit* owner = me->GetCharmerOrOwner())
577 if (owner->GetExactDist(me) >= (owner->GetVisibilityRange() - 10.0f))
578 return true;
579
580 return !me->IsValidAttackTarget(me->GetVictim());
581}
582
584{
585 if (!me->IsAlive())
586 {
589 me->CombatStop();
590 return;
591 }
592
593 me->AttackStop();
598}
599
601{
602 _updateAlliesTimer = 10 * IN_MILLISECONDS; // update friendly targets every 10 seconds, lesser checks increase performance
603
604 Unit* owner = me->GetCharmerOrOwner();
605 if (!owner)
606 return;
607
608 Group* group = nullptr;
609 if (Player* player = owner->ToPlayer())
610 group = player->GetGroup();
611
612 // only pet and owner/not in group->ok
613 if (_allySet.size() == 2 && !group)
614 return;
615
616 // owner is in group; group members filled in already (no raid -> subgroupcount = whole count)
617 if (group && !group->isRaidGroup() && _allySet.size() == (group->GetMembersCount() + 2))
618 return;
619
620 _allySet.clear();
621 _allySet.insert(me->GetGUID());
622 if (group) // add group
623 {
624 for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
625 {
626 Player* Target = itr->GetSource();
627 if (!Target || !Target->IsInMap(owner) || !group->SameSubGroup(owner->ToPlayer(), Target))
628 continue;
629
630 if (Target->GetGUID() == owner->GetGUID())
631 continue;
632
633 _allySet.insert(Target->GetGUID());
634 }
635 }
636 else // remove group
637 _allySet.insert(owner->GetGUID());
638}
639
647
649{
650 CharmInfo* ci = me->GetCharmInfo();
651 if (ci)
652 {
653 ci->SetIsAtStay(false);
654 ci->SetIsCommandAttack(false);
655 ci->SetIsCommandFollow(false);
656 ci->SetIsFollowing(false);
657 ci->SetIsReturning(false);
658 }
659}
@ IN_MILLISECONDS
Definition Common.h:35
#define M_PI
Definition Common.h:72
#define M_PI_4
Definition Common.h:76
#define TIME_INTERVAL_LOOK
Definition CreatureAI.h:38
@ PERMIT_BASE_PROACTIVE
Definition CreatureAI.h:46
@ PERMIT_BASE_NO
Definition CreatureAI.h:43
@ PERMIT_BASE_REACTIVE
Definition CreatureAI.h:45
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
#define TC_LOG_WARN(filterType__,...)
Definition Log.h:162
#define TC_LOG_TRACE(filterType__,...)
Definition Log.h:153
@ CHASE_MOTION_TYPE
@ POINT_MOTION_TYPE
@ FOLLOW_MOTION_TYPE
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
std::vector< std::pair< Unit *, Spell * > > TargetSpellList
Definition PetAI.h:27
#define PET_FOLLOW_DIST
Definition PetDefines.h:85
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
@ SPELL_EFFECT_JUMP_DEST
@ EMOTE_ONESHOT_OMNICAST_GHOUL
@ EMOTE_STATE_STUN
@ TEXT_EMOTE_ANGRY
@ TEXT_EMOTE_SOOTHE
@ TEXT_EMOTE_COWER
@ TEXT_EMOTE_GLARE
@ TRIGGERED_NONE
#define sSpellMgr
Definition SpellMgr.h:738
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ COMMAND_STAY
@ COMMAND_FOLLOW
@ MOVE_FLIGHT
@ MOVE_RUN
@ MOVE_WALK
@ UNIT_FLAG_PET_IN_COMBAT
@ UNIT_MASK_CONTROLABLE_GUARDIAN
Definition Unit.h:372
@ CURRENT_CHANNELED_SPELL
Definition Unit.h:608
@ UNIT_STATE_CHASE
Definition Unit.h:225
@ UNIT_STATE_FOLLOW
Definition Unit.h:229
@ UNIT_STATE_CASTING
Definition Unit.h:235
void OnCharmed(bool isNew) override
Creature *const me
Definition CreatureAI.h:82
virtual uint8 GetPetAutoSpellSize() const
Definition Creature.h:286
bool HasReactState(ReactStates state) const
Definition Creature.h:121
Unit * SelectNearestHostileUnitInAggroRange(bool useLOS=false, bool ignoreCivilians=false) const
float GetPetChaseDistance() const
virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const
Definition Group.h:165
uint32 GetMembersCount() const
Definition Group.h:249
GroupReference * GetFirstMember()
Definition Group.h:247
bool SameSubGroup(ObjectGuid guid1, ObjectGuid guid2) const
Definition Group.cpp:2531
bool isRaidGroup() const
Definition Group.cpp:2448
bool IsPetGhoul() const
void MoveChase(Unit *target, Optional< ChaseRange > dist={}, Optional< ChaseAngle > angle={})
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
void MoveFollow(Unit *target, float dist, ChaseAngle angle, MovementSlot slot=MOTION_SLOT_ACTIVE)
void Remove(MovementGenerator *movement, MovementSlot slot=MOTION_SLOT_ACTIVE)
LowType GetCounter() const
Definition ObjectGuid.h:156
std::string ToString() const
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
static Player * ToPlayer(Object *o)
Definition Object.h:180
void ReceiveEmote(Player *player, uint32 textEmote) override
Definition PetAI.cpp:543
uint32 _updateAlliesTimer
Definition PetAI.h:72
void OwnerAttackedBy(Unit *attacker) override
Definition PetAI.cpp:275
void AttackStart(Unit *target) override
Definition PetAI.cpp:253
void OwnerAttacked(Unit *target) override
Definition PetAI.cpp:295
void MovementInform(uint32 type, uint32 id) override
Definition PetAI.cpp:448
bool NeedToStop()
Definition PetAI.cpp:569
bool CanAttack(Unit *target)
Definition PetAI.cpp:481
void OnCharmed(bool isNew) override
Definition PetAI.cpp:640
static int32 Permissible(Creature const *creature)
Definition PetAI.cpp:34
void UpdateAllies()
Definition PetAI.cpp:600
void DoAttack(Unit *target, bool chase)
Definition PetAI.cpp:408
void StopAttack()
Definition PetAI.cpp:583
void _AttackStart(Unit *target)
Definition PetAI.cpp:265
void ClearCharmInfoFlags()
Definition PetAI.cpp:648
void KilledUnit(Unit *) override
Definition PetAI.cpp:232
PetAI(Creature *creature)
Definition PetAI.cpp:46
GuidSet _allySet
Definition PetAI.h:71
Unit * SelectNextTarget(bool allowAutoSelect) const
Definition PetAI.cpp:316
void UpdateAI(uint32) override
Definition PetAI.cpp:54
void HandleReturnMovement()
Definition PetAI.cpp:360
void SetUnitTarget(Unit *target)
Definition Spell.cpp:237
bool IsReady(SpellInfo const *spellInfo, uint32 itemId=0, bool ignoreCategoryCooldown=false) const
bool HasGlobalCooldown(SpellInfo const *spellInfo) const
bool CanBeUsedInCombat() const
bool HasEffect(SpellEffects effect) const
bool IsPositive() const
Definition Spell.h:152
SpellCastResult prepare(SpellCastTargets const &targets, AuraEffect const *triggeredByAura=nullptr)
Definition Spell.cpp:3070
bool CanAutoCast(Unit *target)
Definition Spell.cpp:6470
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
virtual std::string GetDebugInfo() const
Definition UnitAI.cpp:322
Definition Unit.h:769
bool IsWithinMeleeRange(Unit const *obj) const
Definition Unit.h:844
bool IsCharmed() const
Definition Unit.h:1280
Pet * ToPet()
Definition Unit.h:1788
bool HasBreakableByDamageCrowdControlAura(Unit *excludeCasterChannel=nullptr) const
Definition Unit.cpp:693
void SendPetAIReaction(ObjectGuid guid) const
Definition Unit.cpp:10288
bool isPossessedByPlayer() const
Definition Unit.cpp:6280
void UpdateSpeed(UnitMoveType mtype)
Definition Unit.cpp:8523
ObjectGuid GetOwnerGUID() const override
Definition Unit.h:1241
Unit * GetCharmer() const
Definition Unit.h:1253
Unit * getAttackerForHelper() const
Definition Unit.cpp:5512
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3093
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
bool IsPet() const
Definition Unit.h:884
bool IsAlive() const
Definition Unit.h:1234
CharmInfo * GetCharmInfo()
Definition Unit.h:1287
Unit * EnsureVictim() const
Definition Unit.h:861
Unit * GetCharmerOrOwner() const
Definition Unit.h:1265
bool Attack(Unit *victim, bool meleeAttack)
Definition Unit.cpp:5535
bool isPossessed() const
Definition Unit.h:1282
virtual float GetFollowAngle() const
Definition Unit.h:1782
Unit * GetVictim() const
Definition Unit.h:859
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
void HandleEmoteCommand(Emote emoteId)
Definition Unit.cpp:1568
uint32 HasUnitTypeMask(uint32 mask) const
Definition Unit.h:880
SpellHistory * GetSpellHistory()
Definition Unit.h:1484
void CombatStop(bool includingCast=false, bool mutualPvP=true)
Definition Unit.cpp:5691
void SetUnitFlag(UnitFlags flags)
Definition Unit.h:954
bool AttackStop()
Definition Unit.cpp:5645
bool IsInCombat() const
Definition Unit.h:1144
void RemoveUnitFlag(UnitFlags flags)
Definition Unit.h:955
Spell * GetCurrentSpell(CurrentSpellTypes spellType) const
Definition Unit.h:1476
bool IsValidAttackTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition Object.cpp:2856
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:1160
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
void SetIsCommandFollow(bool val)
Definition Unit.cpp:13183
bool IsCommandAttack()
Definition Unit.cpp:13178
void SetIsAtStay(bool val)
Definition Unit.cpp:13214
bool IsFollowing()
Definition Unit.cpp:13229
bool IsReturning()
Definition Unit.cpp:13239
void SetIsFollowing(bool val)
Definition Unit.cpp:13224
void SetIsReturning(bool val)
Definition Unit.cpp:13234
bool IsAtStay()
Definition Unit.cpp:13219
bool HasCommandState(CommandStates state) const
Definition Unit.h:683
void GetStayPosition(float &x, float &y, float &z)
Definition Unit.cpp:13207
bool IsCommandFollow()
Definition Unit.cpp:13188
void SetIsCommandAttack(bool val)
Definition Unit.cpp:13173