AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
PetAI Class Reference

#include "PetAI.h"

Inheritance diagram for PetAI:
CreatureAI UnitAI

Public Member Functions

 PetAI (Creature *c)
 
void UpdateAI (uint32) override
 Use to start attacking a target. Called just before JustEngagedWith()
 
void KilledUnit (Unit *) override
 
void AttackStart (Unit *target) override
 
void MovementInform (uint32 moveType, uint32 data) override
 
void OwnerAttackedBy (Unit *attacker) override
 
void OwnerAttacked (Unit *target) override
 
void AttackedBy (Unit *attacker) override
 
void ReceiveEmote (Player *player, uint32 textEmote) override
 
void MoveInLineOfSight (Unit *) override
 
void MoveInLineOfSight_Safe (Unit *)
 
void EnterEvadeMode (EvadeReason) override
 
void SpellHit (Unit *caster, SpellInfo const *spellInfo) override
 
void PetStopAttack () override
 
- Public Member Functions inherited from CreatureAI
void Talk (uint8 id, WorldObject const *whisperTarget=nullptr, Milliseconds delay=0ms)
 Causes the creature to talk/say the text assigned to their entry in the creature_text database table.
 
void Talk (uint8 id, Milliseconds delay)
 
WorldObjectGetSummoner () const
 Returns the summoner creature/object, if the creature is a temporary summon.
 
 CreatureAI (Creature *creature)
 
 ~CreatureAI () override
 
bool IsEngaged () const
 Check if creature is currently engaged in combat.
 
void MoveCircleChecks ()
 
void MoveBackwardsChecks ()
 
void MoveInLineOfSight_Safe (Unit *who)
 == Reactions At =================================
 
void TriggerAlert (Unit const *who) const
 
virtual bool CanRespawn ()
 
virtual bool IsEscortNPC (bool=true) const
 
void JustEnteredCombat (Unit *who) override
 Called when the unit enters combat.
 
virtual void JustStartedThreateningMe (Unit *who)
 
virtual void JustEngagedWith (Unit *)
 Called for reaction when initially engaged - this happens after JustEnteredCombat.
 
void EngagementStart (Unit *who)
 
void EngagementOver ()
 
void JustExitedCombat () override
 Called when the unit leaves combat.
 
virtual void JustDied (Unit *)
 
virtual void JustSummoned (Creature *)
 
virtual void IsSummonedBy (WorldObject *)
 
virtual void SummonedCreatureDespawn (Creature *)
 
virtual void SummonedCreatureDies (Creature *, Unit *)
 
virtual void SummonedCreatureDespawnAll ()
 
virtual void SummonedCreatureEvade (Creature *)
 
virtual void SpellHitTarget (Unit *, SpellInfo const *)
 
virtual void OnSpellStart (SpellInfo const *)
 
virtual void OnSpellCast (SpellInfo const *)
 
virtual void OnSpellFailed (SpellInfo const *)
 
virtual void OnChannelFinished (SpellInfo const *)
 
virtual bool IsEscorted ()
 
virtual void JustRespawned ()
 
virtual void PathEndReached (uint32)
 
virtual void WaypointPathStarted (uint32)
 == Waypoints system =============================
 
virtual void WaypointStarted (uint32, uint32)
 
virtual void WaypointReached (uint32, uint32)
 
virtual void WaypointPathEnded (uint32, uint32)
 
void OnCharmed (bool apply) override
 Called when unit is charmed.
 
virtual void JustReachedHome ()
 
void DoZoneInCombat (Creature *creature=nullptr, float maxRangeToNearestTarget=250.0f)
 
void OnOwnerCombatInteraction (Unit *target)
 
virtual void CorpseRemoved (uint32 &)
 == Triggered Actions Requested ==================
 
virtual void PassengerBoarded (Unit *, int8, bool)
 == Fields =======================================
 
virtual bool BeforeSpellClick (Unit *)
 
virtual void OnSpellClick (Unit *, bool &)
 
virtual bool CanSeeAlways (WorldObject const *)
 
virtual bool CanBeSeen (Player const *)
 
virtual bool CanAlwaysBeDetectable (WorldObject const *)
 
int32 VisualizeBoundary (uint32 duration, Unit *owner=nullptr, bool fill=false, bool checkZ=false) const
 
virtual bool CheckInRoom ()
 
CreatureBoundary const * GetBoundary () const
 
void SetBoundary (CreatureBoundary const *boundary, bool negativeBoundaries=false)
 
bool IsInBoundary (Position const *who=nullptr) const
 
virtual void CalculateThreat (Unit *, float &, SpellInfo const *)
 
virtual bool OnTeleportUnreacheablePlayer (Player *)
 
virtual void OnAuraRemove (AuraApplication *, AuraRemoveMode)
 
virtual void DistancingStarted ()
 
virtual void DistancingEnded ()
 
- Public Member Functions inherited from UnitAI
 UnitAI (Unit *unit)
 
virtual ~UnitAI ()
 
virtual bool CanAIAttack (Unit const *) const
 
virtual void InitializeAI ()
 
virtual void Reset ()
 
virtual void DoAction (int32)
 
virtual uint32 GetData (uint32) const
 
virtual void SetData (uint32, uint32)
 
virtual void SetGUID (ObjectGuid const &, int32=0)
 
virtual ObjectGuid GetGUID (int32=0) const
 
UnitSelectTarget (SelectTargetMethod targetType, uint32 position=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
 
template<class PREDICATE >
UnitSelectTarget (SelectTargetMethod targetType, uint32 position, PREDICATE const &predicate)
 
void SelectTargetList (std::list< Unit * > &targetList, uint32 num, SelectTargetMethod targetType, uint32 position=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
 Select the best (up to) <num> targets (in <targetType> order) from the threat list that fulfill the following:
 
template<class PREDICATE >
void SelectTargetList (std::list< Unit * > &targetList, uint32 num, SelectTargetMethod targetType, uint32 position, PREDICATE const &predicate)
 
virtual void OnDespawn ()
 Called when the unit is about to be removed from the world (despawn, grid unload, corpse disappearing, player logging out etc.)
 
virtual void EvadeTimerExpired ()
 Called when evade timer expires (target unreachable for too long)
 
virtual void DamageDealt (Unit *, uint32 &, DamageEffectType, SpellSchoolMask)
 Called at any Damage to any victim (before damage apply)
 
virtual void DamageTaken (Unit *, uint32 &, DamageEffectType, SpellSchoolMask)
 Called at any Damage from any attacker (before damage apply)
 
virtual void HealReceived (Unit *, uint32 &)
 Called when the creature receives heal.
 
virtual void OnPowerUpdate (Powers, int32, int32, uint32)
 Called when the creature power updates.
 
virtual void HealDone (Unit *, uint32 &)
 Called when the unit heals.
 
virtual void OnCalculateMeleeDamageReceived (uint32 &, Unit *)
 Called during damage calculations.
 
virtual void OnCalculateSpellDamageReceived (int32 &, Unit *)
 
virtual void OnCalculatePeriodicTickReceived (uint32 &, Unit *)
 Called during calculation when receiving periodic healing or damage (DoT or HoT)
 
void AttackStartCaster (Unit *victim, float dist)
 
SpellCastResult DoAddAuraToAllHostilePlayers (uint32 spellid)
 
SpellCastResult DoCast (uint32 spellId)
 
SpellCastResult DoCast (Unit *victim, uint32 spellId, bool triggered=false)
 
SpellCastResult DoCastSelf (uint32 spellId, bool triggered=false)
 
SpellCastResult DoCastToAllHostilePlayers (uint32 spellid, bool triggered=false)
 To specify the caster as target if the spell is self-cast.
 
SpellCastResult DoCastVictim (uint32 spellId, bool triggered=false)
 
SpellCastResult DoCastAOE (uint32 spellId, bool triggered=false)
 
SpellCastResult DoCastRandomTarget (uint32 spellId, uint32 threatTablePosition=0, float dist=0.0f, bool playerOnly=true, bool triggered=false, bool withTank=true, int32 aura=0)
 Cast the spell on a random unit from the threat list.
 
SpellCastResult DoCastMaxThreat (uint32 spellId, uint32 threatTablePosition=0, float dist=0.0f, bool playerOnly=true, bool triggered=false)
 Cast spell on the top threat target, which may not be the current victim.
 
float DoGetSpellMaxRange (uint32 spellId, bool positive=false)
 
void DoMeleeAttackIfReady ()
 
bool DoSpellAttackIfReady (uint32 spell)
 
void DoSpellAttackToRandomTargetIfReady (uint32 spell, uint32 threatTablePosition=0, float dist=0.f, bool playerOnly=true)
 
virtual void SummonMovementInform (Creature *, uint32, uint32)
 Called when a summon reaches a waypoint or point movement finished.
 
virtual void sGossipHello (Player *)
 
virtual void sGossipSelect (Player *, uint32, uint32)
 
virtual void sGossipSelectCode (Player *, uint32, uint32, char const *)
 
virtual void sQuestAccept (Player *, Quest const *)
 
virtual void sQuestSelect (Player *, Quest const *)
 
virtual void sQuestComplete (Player *, Quest const *)
 
virtual void sQuestReward (Player *, Quest const *, uint32)
 
virtual void sOnGameEvent (bool, uint16)
 
virtual std::string GetDebugInfo () const
 

Static Public Member Functions

static int32 Permissible (Creature const *creature)
 
- Static Public Member Functions inherited from CreatureAI
static bool IsInBounds (CreatureBoundary const &boundary, Position const *who)
 
- Static Public Member Functions inherited from UnitAI
static void FillAISpellInfo ()
 

Private Member Functions

bool _isVisible (Unit *) const
 
bool _needToStop (void)
 
void _stopAttack (void)
 
void _doMeleeAttack ()
 
bool _canMeleeAttack ()
 
void UpdateAllies ()
 
UnitSelectNextTarget (bool allowAutoSelect) const
 
void HandleReturnMovement ()
 
void DoAttack (Unit *target, bool chase)
 
bool StartChase (Unit *target)
 
bool CanAttack (Unit *target, SpellInfo const *spellInfo=nullptr)
 
void ClearCharmInfoFlags ()
 

Private Attributes

TimeTracker i_tracker
 
GuidSet m_AllySet
 
uint32 m_updateAlliesTimer
 
float combatRange
 

Additional Inherited Members

- Public Types inherited from CreatureAI
enum  EvadeReason {
  EVADE_REASON_NO_HOSTILES ,
  EVADE_REASON_BOUNDARY ,
  EVADE_REASON_SEQUENCE_BREAK ,
  EVADE_REASON_NO_PATH ,
  EVADE_REASON_OTHER
}
 
- Static Public Attributes inherited from UnitAI
static AISpellInfoTypeAISpellInfo
 
- Protected Member Functions inherited from CreatureAI
bool UpdateVictim ()
 
bool UpdateVictimWithGaze ()
 
void SetGazeOn (Unit *target)
 
CreatureDoSummon (uint32 entry, Position const &pos, uint32 despawnTime=30000, TempSummonType summonType=TEMPSUMMON_CORPSE_TIMED_DESPAWN)
 
CreatureDoSummon (uint32 entry, WorldObject *obj, float radius=5.0f, uint32 despawnTime=30000, TempSummonType summonType=TEMPSUMMON_CORPSE_TIMED_DESPAWN)
 
CreatureDoSummonFlyer (uint32 entry, WorldObject *obj, float flightZ, float radius=5.0f, uint32 despawnTime=30000, TempSummonType summonType=TEMPSUMMON_CORPSE_TIMED_DESPAWN)
 
bool _EnterEvadeMode (EvadeReason why=EVADE_REASON_OTHER)
 
- Protected Attributes inherited from CreatureAI
Creature *const me
 
EventMap events
 
TaskScheduler scheduler
 
CreatureBoundary const * _boundary
 
bool _negateBoundary
 
bool _isEngaged
 
- Protected Attributes inherited from UnitAI
Unit *const me
 

Detailed Description

Constructor & Destructor Documentation

◆ PetAI()

PetAI::PetAI ( Creature c)
explicit
45{
47}
#define TIME_INTERVAL_LOOK
Definition CreatureAI.h:34
Definition CreatureAI.h:69
void UpdateAllies()
Definition PetAI.cpp:376
TimeTracker i_tracker
Definition PetAI.h:82

References UpdateAllies().

Member Function Documentation

◆ _canMeleeAttack()

bool PetAI::_canMeleeAttack ( )
private
101{
102 combatRange = 0.f;
103 switch (me->GetEntry())
104 {
105 case ENTRY_IMP:
108 {
109 for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
110 {
111 uint32 spellID = me->GetPetAutoSpellOnPos(i);
112 switch (spellID)
113 {
125 {
126 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
127 int32 mana = me->GetPower(POWER_MANA);
128
129 if (mana >= spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask()))
130 {
131 combatRange = spellInfo->GetMaxRange();
132 return true;
133 }
134 }
135 default:
136 break;
137 }
138 }
139 return false;
140 }
141 default:
142 break;
143 }
144
145 return true;
146}
std::int32_t int32
Definition Define.h:103
std::uint8_t uint8
Definition Define.h:109
std::uint32_t uint32
Definition Define.h:107
@ WATER_ELEMENTAL_WATERBOLT_1
Definition PetAI.h:42
@ ENTRY_WATER_ELEMENTAL_PERM
Definition PetAI.h:31
@ WATER_ELEMENTAL_WATERBOLT_2
Definition PetAI.h:43
@ IMP_FIREBOLT_RANK_2
Definition PetAI.h:34
@ IMP_FIREBOLT_RANK_6
Definition PetAI.h:38
@ IMP_FIREBOLT_RANK_7
Definition PetAI.h:39
@ IMP_FIREBOLT_RANK_4
Definition PetAI.h:36
@ ENTRY_WATER_ELEMENTAL
Definition PetAI.h:30
@ IMP_FIREBOLT_RANK_1
Definition PetAI.h:33
@ IMP_FIREBOLT_RANK_9
Definition PetAI.h:41
@ ENTRY_IMP
Definition PetAI.h:29
@ IMP_FIREBOLT_RANK_3
Definition PetAI.h:35
@ IMP_FIREBOLT_RANK_8
Definition PetAI.h:40
@ IMP_FIREBOLT_RANK_5
Definition PetAI.h:37
@ POWER_MANA
Definition SharedDefines.h:257
#define sSpellMgr
Definition SpellMgr.h:847
Creature *const me
Definition CreatureAI.h:71
virtual uint8 GetPetAutoSpellSize() const
Definition Creature.h:330
virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const
Definition Creature.h:331
uint32 GetEntry() const
Definition Object.h:123
float combatRange
Definition PetAI.h:85
Definition SpellInfo.h:340
float GetMaxRange(bool positive=false, WorldObject *caster=nullptr, Spell *spell=nullptr) const
Definition SpellInfo.cpp:2750
SpellSchoolMask GetSchoolMask() const
Definition SpellInfo.cpp:1921
int32 CalcPowerCost(WorldObject const *caster, SpellSchoolMask schoolMask, Spell *spell=nullptr) const
Definition SpellInfo.cpp:2829
uint32 GetPower(Powers power) const
Definition Unit.h:1141

References SpellInfo::CalcPowerCost(), combatRange, ENTRY_IMP, ENTRY_WATER_ELEMENTAL, ENTRY_WATER_ELEMENTAL_PERM, Object::GetEntry(), SpellInfo::GetMaxRange(), Creature::GetPetAutoSpellOnPos(), Creature::GetPetAutoSpellSize(), Unit::GetPower(), SpellInfo::GetSchoolMask(), IMP_FIREBOLT_RANK_1, IMP_FIREBOLT_RANK_2, IMP_FIREBOLT_RANK_3, IMP_FIREBOLT_RANK_4, IMP_FIREBOLT_RANK_5, IMP_FIREBOLT_RANK_6, IMP_FIREBOLT_RANK_7, IMP_FIREBOLT_RANK_8, IMP_FIREBOLT_RANK_9, CreatureAI::me, POWER_MANA, sSpellMgr, WATER_ELEMENTAL_WATERBOLT_1, and WATER_ELEMENTAL_WATERBOLT_2.

Referenced by _doMeleeAttack(), and StartChase().

◆ _doMeleeAttack()

void PetAI::_doMeleeAttack ( )
private
92{
93 // Xinef: Imps cannot attack with melee
94 if (!_canMeleeAttack())
95 return;
96
98}
bool _canMeleeAttack()
Definition PetAI.cpp:100
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:41

References _canMeleeAttack(), and UnitAI::DoMeleeAttackIfReady().

Referenced by UpdateAI().

◆ _isVisible()

bool PetAI::_isVisible ( Unit ) const
private

◆ _needToStop()

bool PetAI::_needToStop ( void  )
private
50{
51 // This is needed for charmed creatures, as once their target was reset other effects can trigger threat
52 if (me->IsCharmed() && me->GetVictim() == me->GetCharmer())
53 return true;
54
55 // xinef: dont allow to follow targets out of visibility range
56 if (me->GetExactDist(me->GetVictim()) > me->GetVisibilityRange() - 5.0f)
57 return true;
58
59 // dont allow pets to follow targets far away from owner
60 if (Unit* owner = me->GetCharmerOrOwner())
61 if (owner->GetExactDist(me) >= (owner->GetVisibilityRange() - 10.0f))
62 return true;
63
64 return !me->CanCreatureAttack(me->GetVictim());
65}
bool CanCreatureAttack(Unit const *victim, bool skipDistCheck=false) const
Definition Creature.cpp:2668
Definition Unit.h:665
bool IsCharmed() const
Definition Unit.h:1315
Unit * GetCharmer() const
Definition Unit.cpp:7451
Unit * GetCharmerOrOwner() const
Definition Unit.h:1291
Unit * GetVictim() const
Definition Unit.h:904
float GetVisibilityRange() const
Definition Object.cpp:1710
float GetExactDist(float x, float y, float z) const
Definition Position.h:182

References Creature::CanCreatureAttack(), Unit::GetCharmer(), Unit::GetCharmerOrOwner(), Position::GetExactDist(), Unit::GetVictim(), WorldObject::GetVisibilityRange(), Unit::IsCharmed(), and CreatureAI::me.

Referenced by UpdateAI().

◆ _stopAttack()

void PetAI::_stopAttack ( void  )
private
73{
74 if (!me->IsAlive())
75 {
76 LOG_DEBUG("entities.unit.ai", "Creature stoped attacking cuz his dead [{}]", me->GetGUID().ToString());
79 me->CombatStop();
81 return;
82 }
83
84 me->AttackStop();
89}
#define LOG_DEBUG(filterType__,...)
Definition Log.h:157
void MoveIdle()
Definition MotionMaster.cpp:235
void Clear(bool reset=true)
Definition MotionMaster.h:194
std::string ToString() const
Definition ObjectGuid.cpp:48
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:120
void ClearCharmInfoFlags()
Definition PetAI.cpp:816
void HandleReturnMovement()
Definition PetAI.cpp:561
void RemoveMeFromThreatLists()
Definition ThreatManager.cpp:798
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true, bool bySelf=false)
Definition Unit.cpp:4023
MotionMaster * GetMotionMaster()
Definition Unit.h:1761
bool IsAlive() const
Definition Unit.h:1796
CharmInfo * GetCharmInfo()
Definition Unit.h:1286
ThreatManager & GetThreatMgr()
Definition Unit.h:957
void CombatStop(bool includingCast=false, bool mutualPvP=true)
Definition Unit.cpp:7229
bool AttackStop()
Force the unit to stop attacking. This will clear UNIT_STATE_MELEE_ATTACKING, Interrupt current spell...
Definition Unit.cpp:7196
void SetIsCommandAttack(bool val)
Definition CharmInfo.cpp:303

References Unit::AttackStop(), MotionMaster::Clear(), ClearCharmInfoFlags(), Unit::CombatStop(), Unit::GetCharmInfo(), Object::GetGUID(), Unit::GetMotionMaster(), Unit::GetThreatMgr(), HandleReturnMovement(), Unit::InterruptNonMeleeSpells(), Unit::IsAlive(), LOG_DEBUG, CreatureAI::me, MotionMaster::MoveIdle(), ThreatManager::RemoveMeFromThreatLists(), CharmInfo::SetIsCommandAttack(), and ObjectGuid::ToString().

Referenced by PetStopAttack(), and UpdateAI().

◆ AttackedBy()

void PetAI::AttackedBy ( Unit attacker)
overridevirtual

Reimplemented from CreatureAI.

833{
834 // Called when pet takes damage. This function helps keep pets from running off
835 // simply due to gaining aggro.
836
837 if (!attacker)
838 return;
839
840 // Passive pets don't do anything
842 return;
843
844 // Prevent pet from disengaging from current target
845 if (me->GetVictim() && me->GetVictim()->IsAlive())
846 return;
847
848 // Continue to evaluate and attack if necessary
849 AttackStart(attacker);
850}
@ REACT_PASSIVE
Definition Unit.h:567
bool HasReactState(ReactStates state) const
Definition Creature.h:102
void AttackStart(Unit *target) override
Definition PetAI.cpp:440

References AttackStart(), Unit::GetVictim(), Creature::HasReactState(), Unit::IsAlive(), CreatureAI::me, and REACT_PASSIVE.

◆ AttackStart()

void PetAI::AttackStart ( Unit target)
overridevirtual

Reimplemented from UnitAI.

441{
442 // Overrides Unit::AttackStart to correctly evaluate Pet states
443
444 // Check all pet states to decide if we can attack this target
445 if (!CanAttack(target))
446 return;
447
448 // Only chase if not commanded to stay or if stay but commanded to attack
450}
@ COMMAND_STAY
Definition Unit.h:574
void DoAttack(Unit *target, bool chase)
Definition PetAI.cpp:627
bool CanAttack(Unit *target, SpellInfo const *spellInfo=nullptr)
Definition PetAI.cpp:710
bool IsCommandAttack()
Definition CharmInfo.cpp:308
bool HasCommandState(CommandStates state) const
Definition CharmInfo.h:137

References CanAttack(), COMMAND_STAY, DoAttack(), Unit::GetCharmInfo(), CharmInfo::HasCommandState(), CharmInfo::IsCommandAttack(), and CreatureAI::me.

Referenced by AttackedBy(), KilledUnit(), OwnerAttacked(), OwnerAttackedBy(), and UpdateAI().

◆ CanAttack()

bool PetAI::CanAttack ( Unit target,
SpellInfo const *  spellInfo = nullptr 
)
private
711{
712 // Evaluates wether a pet can attack a specific target based on CommandState, ReactState and other flags
713 // IMPORTANT: The order in which things are checked is important, be careful if you add or remove checks
714
715 // Hmmm...
716 if (!target)
717 return false;
718
719 if (!target->IsAlive())
720 {
721 // xinef: if target is invalid, pet should evade automaticly
722 // Clear target to prevent getting stuck on dead targets
723 //me->AttackStop();
724 //me->InterruptNonMeleeSpells(false);
725 return false;
726 }
727
728 // xinef: check unit states of pet
730 return false;
731
732 // xinef: pets of mounted players have stunned flag only, check this also
734 return false;
735
736 // pussywizard: TEMP!
737 if (!me->GetCharmInfo())
738 {
739 LOG_INFO("misc", "PetAI::CanAttack (A1) - {}, {}", me->GetEntry(), me->GetOwnerGUID().ToString());
740 return false;
741 }
742
743 // Passive - passive pets can attack if told to
745 return me->GetCharmInfo()->IsCommandAttack();
746
747 // CC - mobs under crowd control can be attacked if owner commanded
748 if (target->HasBreakableByDamageCrowdControlAura() && (!spellInfo || !spellInfo->HasAttribute(SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS)))
749 return me->GetCharmInfo()->IsCommandAttack();
750
751 // Returning - pets ignore attacks only if owner clicked follow
752 if (me->GetCharmInfo()->IsReturning())
753 return !me->GetCharmInfo()->IsCommandFollow();
754
755 // Stay - can attack if target is within range or commanded to
757 return (me->IsWithinMeleeRange(target) || me->GetCharmInfo()->IsCommandAttack());
758
759 // Pets attacking something (or chasing) should only switch targets if owner tells them to
760 if (me->GetVictim() && me->GetVictim() != target)
761 {
762 // Forced change target if it's taunt
763 if (spellInfo && spellInfo->HasAura(SPELL_AURA_MOD_TAUNT))
764 {
765 return true;
766 }
767
768 // Check if our owner selected this target and clicked "attack"
769 Unit* ownerTarget = nullptr;
770 Unit* charmerOrOwner = me->GetCharmerOrOwner();
771
772 if (charmerOrOwner)
773 {
774 if (Player* owner = charmerOrOwner->ToPlayer())
775 ownerTarget = owner->GetSelectedUnit();
776 else
777 ownerTarget = charmerOrOwner->GetVictim();
778 }
779
780 if (ownerTarget && me->GetCharmInfo()->IsCommandAttack())
781 return (target->GetGUID() == ownerTarget->GetGUID());
782 }
783
784 // Follow
786 return !me->GetCharmInfo()->IsReturning();
787
788 // default, though we shouldn't ever get here
789 return false;
790}
#define LOG_INFO(filterType__,...)
Definition Log.h:153
@ SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS
Definition SharedDefines.h:532
@ SPELL_AURA_MOD_TAUNT
Definition SpellAuraDefines.h:74
@ UNIT_STATE_LOST_CONTROL
Definition UnitDefines.h:219
@ UNIT_FLAG_STUNNED
Definition UnitDefines.h:275
@ COMMAND_FOLLOW
Definition Unit.h:575
Player * ToPlayer()
Definition Object.h:208
Definition Player.h:1086
bool HasBreakableByDamageCrowdControlAura(Unit *excludeCasterChannel=nullptr) const
Definition Unit.cpp:959
ObjectGuid GetOwnerGUID() const override
Definition Unit.h:714
bool HasUnitFlag(UnitFlags flags) const
Definition Unit.h:748
bool IsWithinMeleeRange(Unit const *obj, float dist=0.f) const
Definition Unit.cpp:782
bool HasUnitState(const uint32 f) const
Definition Unit.h:737
bool IsReturning()
Definition CharmInfo.cpp:390
bool IsCommandFollow()
Definition CharmInfo.cpp:318

References COMMAND_FOLLOW, COMMAND_STAY, Unit::GetCharmerOrOwner(), Unit::GetCharmInfo(), Object::GetEntry(), Object::GetGUID(), Unit::GetOwnerGUID(), Unit::GetVictim(), SpellInfo::HasAttribute(), SpellInfo::HasAura(), Unit::HasBreakableByDamageCrowdControlAura(), CharmInfo::HasCommandState(), Creature::HasReactState(), Unit::HasUnitFlag(), Unit::HasUnitState(), Unit::IsAlive(), CharmInfo::IsCommandAttack(), CharmInfo::IsCommandFollow(), CharmInfo::IsReturning(), Unit::IsWithinMeleeRange(), LOG_INFO, CreatureAI::me, REACT_PASSIVE, SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS, SPELL_AURA_MOD_TAUNT, Object::ToPlayer(), ObjectGuid::ToString(), UNIT_FLAG_STUNNED, and UNIT_STATE_LOST_CONTROL.

Referenced by AttackStart(), SpellHit(), and UpdateAI().

◆ ClearCharmInfoFlags()

void PetAI::ClearCharmInfoFlags ( )
private
817{
818 // Quick access to set all flags to FALSE
819
820 CharmInfo* ci = me->GetCharmInfo();
821
822 if (ci)
823 {
824 ci->SetIsAtStay(false);
825 ci->SetIsCommandAttack(false);
826 ci->SetIsCommandFollow(false);
827 ci->SetIsFollowing(false);
828 ci->SetIsReturning(false);
829 }
830}
Definition CharmInfo.h:127
void SetIsCommandFollow(bool val)
Definition CharmInfo.cpp:313
void SetIsAtStay(bool val)
Definition CharmInfo.cpp:365
void SetIsFollowing(bool val)
Definition CharmInfo.cpp:375
void SetIsReturning(bool val)
Definition CharmInfo.cpp:385

References Unit::GetCharmInfo(), CreatureAI::me, CharmInfo::SetIsAtStay(), CharmInfo::SetIsCommandAttack(), CharmInfo::SetIsCommandFollow(), CharmInfo::SetIsFollowing(), and CharmInfo::SetIsReturning().

Referenced by _stopAttack(), DoAttack(), HandleReturnMovement(), and MovementInform().

◆ DoAttack()

void PetAI::DoAttack ( Unit target,
bool  chase 
)
private
628{
629 // Handles attack with or without chase and also resets flags
630 // for next update / creature kill
631
632 if (me->Attack(target, true))
633 {
634 // xinef: properly fix fake combat after pet is sent to attack
635 if (Unit* owner = me->GetOwner())
636 owner->SetUnitFlag(UNIT_FLAG_PET_IN_COMBAT);
637
639
640 // Play sound to let the player know the pet is attacking something it picked on its own
643
644 if (chase)
645 {
646 bool oldCmdAttack = me->GetCharmInfo()->IsCommandAttack(); // This needs to be reset after other flags are cleared
648 me->GetCharmInfo()->SetIsCommandAttack(oldCmdAttack); // For passive pets commanded to attack so they will use spells
649
650 StartChase(target);
651 }
652 else // (Stay && ((Aggressive || Defensive) && In Melee Range)))
653 {
655
656 me->GetCharmInfo()->SetIsAtStay(true);
659 }
660 }
661}
@ MOTION_SLOT_ACTIVE
Definition MotionMaster.h:65
@ UNIT_FLAG_PET_IN_COMBAT
Definition UnitDefines.h:268
@ REACT_AGGRESSIVE
Definition Unit.h:569
void MovementExpiredOnSlot(MovementSlot slot, bool reset=true)
Definition MotionMaster.h:221
bool StartChase(Unit *target)
Definition PetAI.cpp:663
Unit * GetOwner() const
Definition Unit.cpp:7443
void SendPetAIReaction(ObjectGuid guid) const
Definition Unit.cpp:12564
bool Attack(Unit *victim, bool meleeAttack)
Definition Unit.cpp:7030
void SetUnitFlag(UnitFlags flags)
UnitFlags available in UnitDefines.h.
Definition Unit.h:749

References Unit::Attack(), ClearCharmInfoFlags(), Unit::GetCharmInfo(), Object::GetGUID(), Unit::GetMotionMaster(), Unit::GetOwner(), Creature::HasReactState(), CharmInfo::IsCommandAttack(), CreatureAI::me, MOTION_SLOT_ACTIVE, MotionMaster::MoveIdle(), MotionMaster::MovementExpiredOnSlot(), REACT_AGGRESSIVE, Unit::SendPetAIReaction(), CharmInfo::SetIsAtStay(), CharmInfo::SetIsCommandAttack(), Unit::SetUnitFlag(), StartChase(), and UNIT_FLAG_PET_IN_COMBAT.

Referenced by AttackStart(), and SpellHit().

◆ EnterEvadeMode()

void PetAI::EnterEvadeMode ( EvadeReason  )
inlineoverridevirtual

Reimplemented from CreatureAI.

68{} // For fleeing, pets don't use this type of Evade mechanic

◆ HandleReturnMovement()

void PetAI::HandleReturnMovement ( )
private
562{
563 // Handles moving the pet back to stay or owner
564
565 // Prevent activating movement when under control of spells
566 // such as "Eyes of the Beast"
567 if (me->isPossessed())
568 return;
569
571 {
572 if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning())
573 {
575 {
576 // Return to previous position where stay was clicked
578 {
579 float x, y, z;
580 me->GetCharmInfo()->GetStayPosition(x, y, z);
584 me->GetMotionMaster()->MovePoint(me->GetGUID().GetCounter(), x, y, z);
585 }
586 }
587 }
588 }
589 else // COMMAND_FOLLOW
590 {
592 {
594 {
599 }
600 }
601 }
602
605
606 // xinef: remember that npcs summoned by npcs can also be pets
609}
@ MOTION_SLOT_CONTROLLED
Definition MotionMaster.h:66
@ NULL_MOTION_TYPE
Definition MotionMaster.h:59
constexpr float PET_FOLLOW_DIST
Definition PetDefines.h:206
void MovePoint(uint32 id, Position const &pos, ForcedMovement forcedMovement=FORCED_MOVEMENT_NONE, float speed=0.f, bool generatePath=true, bool forceDestination=true, std::optional< AnimTier > animTier=std::nullopt)
Definition MotionMaster.h:241
MovementGeneratorType GetMotionSlotType(int slot) const
Definition MotionMaster.cpp:989
void MoveFollow(Unit *target, float dist, float angle, MovementSlot slot=MOTION_SLOT_ACTIVE, bool inheritWalkState=true, bool inheritSpeed=true)
The unit will follow this target. Doesn't work with UNIT_FLAG_DISABLE_MOVE.
Definition MotionMaster.cpp:448
LowType GetCounter() const
Definition ObjectGuid.h:149
void ClearAllThreat()
Definition ThreatManager.cpp:584
void ClearInPetCombat()
Definition Unit.cpp:10410
bool isPossessed() const
Definition Unit.h:1316
virtual float GetFollowAngle() const
Definition Unit.h:1900
bool IsFollowing()
Definition CharmInfo.cpp:380
void SetForcedSpell(uint32 id)
Definition CharmInfo.h:177
bool IsAtStay()
Definition CharmInfo.cpp:370
void GetStayPosition(float &x, float &y, float &z)
Definition CharmInfo.cpp:346
void SetForcedTargetGUID(ObjectGuid guid=ObjectGuid::Empty)
Definition CharmInfo.h:179
bool HasStayPosition()
Definition CharmInfo.cpp:360

References MotionMaster::Clear(), ThreatManager::ClearAllThreat(), ClearCharmInfoFlags(), Unit::ClearInPetCombat(), COMMAND_STAY, Unit::GetCharmerOrOwner(), Unit::GetCharmInfo(), ObjectGuid::GetCounter(), Unit::GetFollowAngle(), Object::GetGUID(), Unit::GetMotionMaster(), MotionMaster::GetMotionSlotType(), CharmInfo::GetStayPosition(), Unit::GetThreatMgr(), CharmInfo::HasCommandState(), CharmInfo::HasStayPosition(), CharmInfo::IsAtStay(), CharmInfo::IsFollowing(), Unit::isPossessed(), CharmInfo::IsReturning(), CreatureAI::me, MOTION_SLOT_CONTROLLED, MotionMaster::MoveFollow(), MotionMaster::MovePoint(), NULL_MOTION_TYPE, PET_FOLLOW_DIST, CharmInfo::SetForcedSpell(), CharmInfo::SetForcedTargetGUID(), and CharmInfo::SetIsReturning().

Referenced by _stopAttack(), KilledUnit(), and UpdateAI().

◆ KilledUnit()

void PetAI::KilledUnit ( Unit victim)
overridevirtual

Reimplemented from CreatureAI.

416{
417 // Called from Unit::Kill() in case where pet or owner kills something
418 // if owner killed this victim, pet may still be attacking something else
419 if (me->GetVictim() && me->GetVictim() != victim)
420 return;
421
422 // Xinef: if pet is channeling a spell and owner killed something different, dont interrupt it
424 return;
425
426 // Clear target just in case. May help problem where health / focus / mana
427 // regen gets stuck. Also resets attack command.
428 // Can't use _stopAttack() because that activates movement handlers and ignores
429 // next target selection
430 me->AttackStop();
432
433 // Before returning to owner, see if there are more things to attack
434 if (Unit* nextTarget = SelectNextTarget(false))
435 AttackStart(nextTarget);
436 else
437 HandleReturnMovement(); // Return
438}
@ UNIT_STATE_CASTING
Definition UnitDefines.h:188
@ UNIT_FIELD_CHANNEL_OBJECT
Definition UpdateFields.h:93
ObjectGuid GetGuidValue(uint16 index) const
Definition Object.cpp:335
Unit * SelectNextTarget(bool allowAutoSelect) const
Definition PetAI.cpp:493

References AttackStart(), Unit::AttackStop(), Object::GetGUID(), Object::GetGuidValue(), Unit::GetVictim(), HandleReturnMovement(), Unit::HasUnitState(), Unit::InterruptNonMeleeSpells(), CreatureAI::me, SelectNextTarget(), UNIT_FIELD_CHANNEL_OBJECT, and UNIT_STATE_CASTING.

◆ MoveInLineOfSight()

void PetAI::MoveInLineOfSight ( Unit )
inlineoverridevirtual

Reimplemented from CreatureAI.

65{} // CreatureAI interferes with returning pets

◆ MoveInLineOfSight_Safe()

void PetAI::MoveInLineOfSight_Safe ( Unit )
inline
66{} // CreatureAI interferes with returning pets

◆ MovementInform()

void PetAI::MovementInform ( uint32  moveType,
uint32  data 
)
overridevirtual

Reimplemented from CreatureAI.

677{
678 // Receives notification when pet reaches stay or follow owner
679 switch (moveType)
680 {
682 {
683 // Pet is returning to where stay was clicked. data should be
684 // pet's GUIDLow since we set that as the waypoint ID
685 if (data == me->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning())
686 {
688 me->GetCharmInfo()->SetIsAtStay(true);
691 }
692 break;
693 }
695 {
696 // If data is owner's GUIDLow then we've reached follow point,
697 // otherwise we're probably chasing a creature
699 {
702 }
703 break;
704 }
705 default:
706 break;
707 }
708}
@ POINT_MOTION_TYPE
Definition MotionMaster.h:48
@ FOLLOW_MOTION_TYPE
Definition MotionMaster.h:54

References MotionMaster::Clear(), ClearCharmInfoFlags(), FOLLOW_MOTION_TYPE, Unit::GetCharmerOrOwner(), Unit::GetCharmInfo(), ObjectGuid::GetCounter(), Object::GetGUID(), Unit::GetMotionMaster(), CharmInfo::IsReturning(), CreatureAI::me, MotionMaster::MoveIdle(), POINT_MOTION_TYPE, CharmInfo::SetIsAtStay(), and CharmInfo::SetIsFollowing().

◆ OwnerAttacked()

void PetAI::OwnerAttacked ( Unit target)
overridevirtual

Reimplemented from CreatureAI.

473{
474 // Called when owner attacks something. Allows defensive pets to know
475 // that they need to assist
476
477 // Target might be nullptr if called from spell with invalid cast targets
478 if (!target)
479 return;
480
481 // Passive pets don't do anything
483 return;
484
485 // Prevent pet from disengaging from current target
486 if (me->GetVictim() && me->GetVictim()->IsAlive())
487 return;
488
489 // Continue to evaluate and attack if necessary
490 AttackStart(target);
491}

References AttackStart(), Unit::GetVictim(), Creature::HasReactState(), Unit::IsAlive(), CreatureAI::me, and REACT_PASSIVE.

◆ OwnerAttackedBy()

void PetAI::OwnerAttackedBy ( Unit attacker)
overridevirtual

Reimplemented from CreatureAI.

453{
454 // Called when owner takes damage. This function helps keep pets from running off
455 // simply due to owner gaining aggro.
456
457 if (!attacker)
458 return;
459
460 // Passive pets don't do anything
462 return;
463
464 // Prevent pet from disengaging from current target
465 if (me->GetVictim() && me->GetVictim()->IsAlive())
466 return;
467
468 // Continue to evaluate and attack if necessary
469 AttackStart(attacker);
470}

References AttackStart(), Unit::GetVictim(), Creature::HasReactState(), Unit::IsAlive(), CreatureAI::me, and REACT_PASSIVE.

◆ Permissible()

int32 PetAI::Permissible ( Creature const *  creature)
static
33{
34 if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLLABLE_GUARDIAN))
35 {
36 if (reinterpret_cast<Guardian const*>(creature)->GetOwner()->IsPlayer())
39 }
40
41 return PERMIT_BASE_NO;
42}
@ PERMIT_BASE_PROACTIVE
Definition CreatureAI.h:291
@ PERMIT_BASE_NO
Definition CreatureAI.h:288
@ PERMIT_BASE_REACTIVE
Definition CreatureAI.h:290
@ UNIT_MASK_CONTROLLABLE_GUARDIAN
Definition UnitDefines.h:167
Definition TemporarySummon.h:106

References Unit::HasUnitTypeMask(), PERMIT_BASE_NO, PERMIT_BASE_PROACTIVE, PERMIT_BASE_REACTIVE, and UNIT_MASK_CONTROLLABLE_GUARDIAN.

◆ PetStopAttack()

void PetAI::PetStopAttack ( )
overridevirtual

Reimplemented from CreatureAI.

68{
70}
void _stopAttack(void)
Definition PetAI.cpp:72

References _stopAttack().

◆ ReceiveEmote()

void PetAI::ReceiveEmote ( Player player,
uint32  textEmote 
)
overridevirtual

Reimplemented from CreatureAI.

793{
794 if (me->GetOwnerGUID() && me->GetOwnerGUID() == player->GetGUID())
795 switch (emote)
796 {
797 case TEXT_EMOTE_COWER:
798 if (me->IsPet() && me->ToPet()->IsPetGhoul())
799 me->HandleEmoteCommand(/*EMOTE_ONESHOT_ROAR*/EMOTE_ONESHOT_OMNICAST_GHOUL);
800 break;
801 case TEXT_EMOTE_ANGRY:
802 if (me->IsPet() && me->ToPet()->IsPetGhoul())
803 me->HandleEmoteCommand(/*EMOTE_ONESHOT_COWER*/EMOTE_STATE_STUN);
804 break;
805 case TEXT_EMOTE_GLARE:
806 if (me->IsPet() && me->ToPet()->IsPetGhoul())
808 break;
810 if (me->IsPet() && me->ToPet()->IsPetGhoul())
812 break;
813 }
814}
@ EMOTE_ONESHOT_OMNICAST_GHOUL
Definition SharedDefines.h:2032
@ EMOTE_STATE_STUN
Definition SharedDefines.h:1944
@ TEXT_EMOTE_ANGRY
Definition SharedDefines.h:1642
@ TEXT_EMOTE_SOOTHE
Definition SharedDefines.h:1773
@ TEXT_EMOTE_COWER
Definition SharedDefines.h:1667
@ TEXT_EMOTE_GLARE
Definition SharedDefines.h:1685
bool IsPetGhoul() const
Definition TemporarySummon.h:95
Pet * ToPet()
Definition Unit.h:730
bool IsPet() const
Definition Unit.h:798
void HandleEmoteCommand(uint32 emoteId)
Definition Unit.cpp:2185

References EMOTE_ONESHOT_OMNICAST_GHOUL, EMOTE_STATE_STUN, Object::GetGUID(), Unit::GetOwnerGUID(), Unit::HandleEmoteCommand(), Unit::IsPet(), Minion::IsPetGhoul(), CreatureAI::me, TEXT_EMOTE_ANGRY, TEXT_EMOTE_COWER, TEXT_EMOTE_GLARE, TEXT_EMOTE_SOOTHE, and Unit::ToPet().

◆ SelectNextTarget()

Unit * PetAI::SelectNextTarget ( bool  allowAutoSelect) const
private
Todo:
: try for another target
494{
495 // Provides next target selection after current target death.
496 // This function should only be called internally by the AI
497 // Targets are not evaluated here for being valid targets, that is done in _CanAttack()
498 // The parameter: allowAutoSelect lets us disable aggressive pet auto targeting for certain situations
499
500 // Passive pets don't do next target selection
502 return nullptr;
503
504 // Check pet attackers first so we don't drag a bunch of targets to the owner
505 if (Unit* myAttacker = me->getAttackerForHelper())
506 if (!myAttacker->HasBreakableByDamageCrowdControlAura() && me->CanCreatureAttack(myAttacker))
507 return myAttacker;
508
509 // Check pet's attackers first to prevent dragging mobs back to owner
510 if (me->HasTauntAura())
511 {
513 if (!tauntAuras.empty())
514 for (Unit::AuraEffectList::const_reverse_iterator itr = tauntAuras.rbegin(); itr != tauntAuras.rend(); ++itr)
515 if (Unit* caster = (*itr)->GetCaster())
516 if (me->CanCreatureAttack(caster) && !caster->HasAuraTypeWithCaster(SPELL_AURA_MOD_DETAUNT, me->GetGUID()))
517 return caster;
518 }
519
520 // Not sure why we wouldn't have an owner but just in case...
521 Unit* owner = me->GetCharmerOrOwner();
522 if (!owner)
523 return nullptr;
524
525 // Check owner attackers
526 if (Unit* ownerAttacker = owner->getAttackerForHelper())
527 if (!ownerAttacker->HasBreakableByDamageCrowdControlAura() && me->CanCreatureAttack(ownerAttacker))
528 return ownerAttacker;
529
530 // Check owner victim
531 // 3.0.2 - Pets now start attacking their owners victim in defensive mode as soon as the hunter does
532 if (Unit* ownerVictim = owner->GetVictim())
533 if (me->CanCreatureAttack(ownerVictim))
534 return ownerVictim;
535
536 // Neither pet or owner had a target and aggressive pets can pick any target
537 // To prevent aggressive pets from chain selecting targets and running off, we
538 // only select a random target if certain conditions are met.
539 if (allowAutoSelect)
540 {
542 {
544 {
545 if (nearTarget->IsPlayer() && nearTarget->ToPlayer()->IsPvP() && !owner->IsPvP()) // If owner is not PvP flagged and target is PvP flagged, do not attack
546 {
547 return nullptr;
548 }
549 else
550 {
551 return nearTarget;
552 }
553 }
554 }
555 }
556
557 // Default - no valid targets
558 return nullptr;
559}
@ SPELL_AURA_MOD_DETAUNT
Definition SpellAuraDefines.h:284
#define MAX_AGGRO_RADIUS
Definition Unit.h:44
Unit * SelectNearestTargetInAttackDistance(float dist) const
Select nearest hostile unit within the given attack distance (i.e. distance is ignored if > than ATTA...
Definition Creature.cpp:2445
Creature * ToCreature()
Definition Object.h:212
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1433
std::vector< AuraEffect * > AuraEffectList
Definition Unit.h:681
Unit * getAttackerForHelper() const
Definition Unit.cpp:870
bool IsPvP() const
Definition Unit.h:1050
bool HasTauntAura() const
Definition Unit.h:1843

References Creature::CanCreatureAttack(), Unit::getAttackerForHelper(), Unit::GetAuraEffectsByType(), Unit::GetCharmerOrOwner(), Unit::GetCharmInfo(), Object::GetGUID(), Unit::GetVictim(), Creature::HasReactState(), Unit::HasTauntAura(), CharmInfo::IsAtStay(), CharmInfo::IsFollowing(), Unit::IsPvP(), CharmInfo::IsReturning(), MAX_AGGRO_RADIUS, CreatureAI::me, REACT_PASSIVE, Creature::SelectNearestTargetInAttackDistance(), SPELL_AURA_MOD_DETAUNT, SPELL_AURA_MOD_TAUNT, and Object::ToCreature().

Referenced by KilledUnit(), and UpdateAI().

◆ SpellHit()

void PetAI::SpellHit ( Unit caster,
SpellInfo const *  spellInfo 
)
overridevirtual

Reimplemented from CreatureAI.

612{
613 // Xinef: taunt behavior code
614 if (spellInfo->HasAura(SPELL_AURA_MOD_TAUNT) && !me->HasReactState(REACT_PASSIVE))
615 {
618
619 if (CanAttack(caster, spellInfo))
620 {
621 // Only chase if not commanded to stay or if stay but commanded to attack
623 }
624 }
625}

References CanAttack(), COMMAND_STAY, DoAttack(), Unit::GetCharmInfo(), SpellInfo::HasAura(), CharmInfo::HasCommandState(), Creature::HasReactState(), CharmInfo::IsCommandAttack(), CreatureAI::me, REACT_PASSIVE, CharmInfo::SetForcedSpell(), CharmInfo::SetForcedTargetGUID(), and SPELL_AURA_MOD_TAUNT.

◆ StartChase()

bool PetAI::StartChase ( Unit target)
private
664{
665 if (!target || target == me || me->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE) || !_canMeleeAttack())
666 return false;
667
668 std::optional<ChaseAngle> chaseAngle;
669 if (combatRange == 0.f && !target->IsPlayer() && !target->IsPet())
670 chaseAngle.emplace(float(M_PI), float(M_PI_4));
671
672 me->GetMotionMaster()->MoveChase(target, ChaseRange(0.f, combatRange), chaseAngle);
673 return true;
674}
@ UNIT_FLAG_DISABLE_MOVE
Definition UnitDefines.h:259
void MoveChase(Unit *target, std::optional< ChaseRange > dist={}, std::optional< ChaseAngle > angle={})
Force the unit to chase this target. Doesn't work with UNIT_FLAG_DISABLE_MOVE.
Definition MotionMaster.cpp:316
bool IsPlayer() const
Definition Object.h:207
Definition MotionMaster.h:111

References _canMeleeAttack(), combatRange, Unit::GetMotionMaster(), Unit::HasUnitFlag(), Unit::IsPet(), Object::IsPlayer(), CreatureAI::me, MotionMaster::MoveChase(), and UNIT_FLAG_DISABLE_MOVE.

Referenced by DoAttack(), and UpdateAI().

◆ UpdateAI()

void PetAI::UpdateAI ( uint32  )
overridevirtual

Use to start attacking a target. Called just before JustEngagedWith()

Implements UnitAI.

149{
150 if (!me->IsAlive() || !me->GetCharmInfo())
151 return;
152
153 Unit* owner = me->GetCharmerOrOwner();
154
155 if (m_updateAlliesTimer <= diff)
156 // UpdateAllies self set update timer
157 UpdateAllies();
158 else
159 m_updateAlliesTimer -= diff;
160
161 if (me->GetVictim() && me->GetVictim()->IsAlive())
162 {
163 // is only necessary to stop casting, the pet must not exit combat
165 {
167 return;
168 }
169
170 if (_needToStop())
171 {
172 LOG_DEBUG("entities.unit.ai", "Pet AI stopped attacking [{}]", me->GetGUID().ToString());
173 _stopAttack();
174 return;
175 }
176
177 CharmInfo* charmInfo = me->GetCharmInfo();
178 // Deferred hostile casts pause their chase at cast range. Resume once movement cannot interrupt the cast.
180 charmInfo->IsCommandAttack() && charmInfo->IsAtStay() && !me->IsMovementPreventedByCasting())
181 {
182 if (StartChase(me->GetVictim()))
183 charmInfo->SetIsAtStay(false);
184 }
185
186 // Check before attacking to prevent pets from leaving stay position
187 if (charmInfo->HasCommandState(COMMAND_STAY))
188 {
189 if (charmInfo->IsCommandAttack() || (charmInfo->IsAtStay() && me->IsWithinMeleeRange(me->GetVictim())))
191 }
192 else
194 }
195 else if (!me->GetCharmInfo() || (!me->GetCharmInfo()->GetForcedSpell() && !(me->IsPet() && me->ToPet()->HasTempSpell()) && !me->HasUnitState(UNIT_STATE_CASTING)))
196 {
198 {
199 // Every update we need to check targets only in certain cases
200 // Aggressive - Allow auto select if owner or pet don't have a target
201 // Stay - Only pick from pet or owner targets / attackers so targets won't run by
202 // while chasing our owner. Don't do auto select.
203 // All other cases (ie: defensive) - Targets are assigned by AttackedBy(), OwnerAttackedBy(), OwnerAttacked(), etc.
205
206 if (nextTarget)
207 AttackStart(nextTarget);
208 else
210 }
211 else
213 }
214
215 // xinef: charm info must be always available
216 if (!me->GetCharmInfo())
217 return;
218
219 // Autocast (casted only in combat or persistent spells in any state)
221 {
222 if (owner && owner->IsPlayer() && me->GetCharmInfo()->GetForcedSpell() && me->GetCharmInfo()->GetForcedTarget())
223 {
225
226 // xinef: if spell was casted properly and we are in passive mode, handle return
228 {
230 {
231 me->GetMotionMaster()->Clear(false);
232 me->StopMoving();
233 }
234 else
235 _stopAttack();
236 }
237 return;
238 }
239
240 // xinef: dont allow ghouls to cast spells below 75 energy
241 if (me->IsPet() && me->ToPet()->IsPetGhoul() && me->GetPower(POWER_ENERGY) < 75)
242 return;
243
244 typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
245 TargetSpellList targetSpellStore;
246
247 for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
248 {
249 uint32 spellID = me->GetPetAutoSpellOnPos(i);
250 if (!spellID)
251 continue;
252
253 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
254 if (!spellInfo)
255 continue;
256
258 continue;
259
260 // check spell cooldown, this should be checked in CheckCast...
261 if (me->HasSpellCooldown(spellInfo->Id))
262 continue;
263
264 if (spellInfo->IsPositive())
265 {
266 if (spellInfo->CanBeUsedInCombat())
267 {
268 // Check if we're in combat or commanded to attack (exlude auras with infinity duration)
269 if (!me->IsInCombat() && spellInfo->GetMaxDuration() != -1 && !me->IsPetInCombat())
270 {
271 continue;
272 }
273 }
274
275 Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE);
276 spell->LoadScripts(); // xinef: load for CanAutoCast (calling CheckPetCast)
277 bool spellUsed = false;
278
279 // Some spells can target enemy or friendly (DK Ghoul's Leap)
280 // Check for enemy first (pet then owner)
281 Unit* target = me->getAttackerForHelper();
282 if (!target && owner)
283 target = owner->getAttackerForHelper();
284
285 if (target)
286 {
287 if (CanAttack(target) && spell->CanAutoCast(target))
288 {
289 targetSpellStore.emplace_back(target, spell);
290 spellUsed = true;
291 }
292 }
293
294 if (spellInfo->HasEffect(SPELL_EFFECT_JUMP_DEST))
295 {
296 if (!spellUsed)
297 delete spell;
298
299 continue; // Pets must only jump to target
300 }
301
302 // No enemy, check friendly
303 if (!spellUsed)
304 {
305 for (ObjectGuid const& guid : m_AllySet)
306 {
307 Unit* ally = ObjectAccessor::GetUnit(*me, guid);
308
309 //only buff targets that are in combat, unless the spell can only be cast while out of combat
310 if (!ally)
311 continue;
312
313 if (spell->CanAutoCast(ally))
314 {
315 targetSpellStore.emplace_back(ally, spell);
316 spellUsed = true;
317 break;
318 }
319 }
320 }
321
322 // No valid targets at all
323 if (!spellUsed)
324 delete spell;
325 }
326 else if (me->GetVictim() && CanAttack(me->GetVictim(), spellInfo) && spellInfo->CanBeUsedInCombat())
327 {
328 Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE);
329 if (spell->CanAutoCast(me->GetVictim()))
330 targetSpellStore.emplace_back(me->GetVictim(), spell);
331 else
332 delete spell;
333 }
334 }
335
336 //found units to cast on to
337 if (!targetSpellStore.empty())
338 {
339 uint32 index = urand(0, targetSpellStore.size() - 1);
340
341 Spell* spell = targetSpellStore[index].second;
342 Unit* target = targetSpellStore[index].first;
343
344 targetSpellStore.erase(targetSpellStore.begin() + index);
345
346 SpellCastTargets targets;
347 targets.SetUnitTarget(target);
348
349 if (!me->HasInArc(M_PI, target))
350 {
351 me->SetInFront(target);
352 if (target && target->IsPlayer())
353 me->SendUpdateToPlayer(target->ToPlayer());
354
355 if (owner && owner->IsPlayer())
356 me->SendUpdateToPlayer(owner->ToPlayer());
357 }
358
359 me->AddSpellCooldown(spell->m_spellInfo->Id, 0, 0);
360
361 spell->prepare(&targets);
362
363 // Stop the current spline before the next movement update can interrupt a stationary channel.
364 if (Pet* controlledPet = me->ToPet())
366 && controlledPet->IsMovementPreventedByCasting())
367 controlledPet->StopMoving();
368 }
369
370 // deleted cached Spell objects
371 for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
372 delete itr->second;
373 }
374}
@ ACT_ENABLED
Definition CharmInfo.h:63
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:44
@ POWER_ENERGY
Definition SharedDefines.h:260
@ SPELL_EFFECT_JUMP_DEST
Definition SharedDefines.h:808
@ TRIGGERED_NONE
Definition SpellDefines.h:141
bool HasSpellCooldown(uint32 spell_id) const override
Definition Creature.cpp:3064
void AddSpellCooldown(uint32 spell_id, uint32, uint32 end_time, bool needSendToClient=false, bool forceSendToSpectator=false) override
Definition Creature.cpp:2989
bool IsMovementPreventedByCasting() const override
Definition Creature.cpp:3674
bool HasGlobalCooldown(SpellInfo const *spellInfo) const
Definition CharmInfo.cpp:397
Definition ObjectGuid.h:121
void SendUpdateToPlayer(Player *player)
Definition Object.cpp:244
bool _needToStop(void)
Definition PetAI.cpp:49
GuidSet m_AllySet
Definition PetAI.h:83
void _doMeleeAttack()
Definition PetAI.cpp:91
uint32 m_updateAlliesTimer
Definition PetAI.h:84
Definition Pet.h:41
bool HasTempSpell() const
Definition Pet.h:147
WorldSession * GetSession() const
Definition Player.h:2031
Definition Spell.h:121
void SetUnitTarget(Unit *target)
Definition Spell.cpp:276
uint32 Id
Definition SpellInfo.h:344
bool IsActionAllowedChannel() const
Definition SpellInfo.cpp:1306
int32 GetMaxDuration() const
Definition SpellInfo.cpp:2771
bool CanBeUsedInCombat() const
Definition SpellInfo.cpp:1277
bool IsChanneled() const
Definition SpellInfo.cpp:1301
bool HasEffect(SpellEffects effect) const
Definition SpellInfo.cpp:889
bool IsPositive() const
Definition SpellInfo.cpp:1282
Definition Spell.h:298
void LoadScripts()
Definition Spell.cpp:8855
SpellCastResult prepare(SpellCastTargets const *targets, AuraEffect const *triggeredByAura=nullptr)
Definition Spell.cpp:3556
SpellInfo const *const m_spellInfo
Definition Spell.h:535
bool CanAutoCast(Unit *target)
Definition Spell.cpp:7261
void StopMoving()
Definition Unit.cpp:12583
bool IsPetInCombat() const
Definition Unit.h:944
void SetInFront(WorldObject const *target)
Definition Unit.cpp:16003
bool IsInCombat() const
Definition Unit.h:941
void HandlePetActionHelper(Unit *pet, ObjectGuid guid1, uint32 spellid, uint16 flag, ObjectGuid guid2)
Definition PetHandler.cpp:150
Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
Definition ObjectAccessor.cpp:223
int32 GetForcedSpell()
Definition CharmInfo.h:178
ObjectGuid GetForcedTarget()
Definition CharmInfo.h:180
GlobalCooldownMgr & GetGlobalCooldownMgr()
Definition CharmInfo.h:160
bool HasInArc(float arcangle, Position const *pos, float targetRadius=0.0f) const
Definition Position.cpp:148

References _doMeleeAttack(), _needToStop(), _stopAttack(), ACT_ENABLED, Creature::AddSpellCooldown(), AttackStart(), CanAttack(), Spell::CanAutoCast(), SpellInfo::CanBeUsedInCombat(), MotionMaster::Clear(), COMMAND_FOLLOW, COMMAND_STAY, Unit::getAttackerForHelper(), Unit::GetCharmerOrOwner(), Unit::GetCharmInfo(), CharmInfo::GetForcedSpell(), CharmInfo::GetForcedTarget(), CharmInfo::GetGlobalCooldownMgr(), Object::GetGUID(), SpellInfo::GetMaxDuration(), Unit::GetMotionMaster(), Creature::GetPetAutoSpellOnPos(), Creature::GetPetAutoSpellSize(), Unit::GetPower(), Player::GetSession(), ObjectAccessor::GetUnit(), Unit::GetVictim(), WorldSession::HandlePetActionHelper(), HandleReturnMovement(), Unit::HasBreakableByDamageCrowdControlAura(), CharmInfo::HasCommandState(), SpellInfo::HasEffect(), GlobalCooldownMgr::HasGlobalCooldown(), Position::HasInArc(), Creature::HasReactState(), Creature::HasSpellCooldown(), Pet::HasTempSpell(), Unit::HasUnitState(), SpellInfo::Id, Unit::InterruptNonMeleeSpells(), SpellInfo::IsActionAllowedChannel(), Unit::IsAlive(), CharmInfo::IsAtStay(), SpellInfo::IsChanneled(), CharmInfo::IsCommandAttack(), Unit::IsInCombat(), Creature::IsMovementPreventedByCasting(), Unit::IsPet(), Minion::IsPetGhoul(), Unit::IsPetInCombat(), Object::IsPlayer(), SpellInfo::IsPositive(), Unit::IsWithinMeleeRange(), Spell::LoadScripts(), LOG_DEBUG, m_AllySet, Spell::m_spellInfo, m_updateAlliesTimer, CreatureAI::me, POWER_ENERGY, Spell::prepare(), REACT_AGGRESSIVE, REACT_PASSIVE, SelectNextTarget(), Object::SendUpdateToPlayer(), Unit::SetInFront(), CharmInfo::SetIsAtStay(), SpellCastTargets::SetUnitTarget(), SPELL_EFFECT_JUMP_DEST, sSpellMgr, StartChase(), Unit::StopMoving(), Unit::ToPet(), Object::ToPlayer(), ObjectGuid::ToString(), TRIGGERED_NONE, UNIT_STATE_CASTING, UpdateAllies(), and urand().

◆ UpdateAllies()

void PetAI::UpdateAllies ( )
private
377{
378 Unit* owner = me->GetCharmerOrOwner();
379 Group* group = nullptr;
380
381 m_updateAlliesTimer = 10 * IN_MILLISECONDS; //update friendly targets every 10 seconds, lesser checks increase performance
382
383 if (!owner)
384 return;
385 else if (owner->IsPlayer())
386 group = owner->ToPlayer()->GetGroup();
387
388 //only pet and owner/not in group->ok
389 if (m_AllySet.size() == 2 && !group)
390 return;
391 //owner is in group; group members filled in already (no raid -> subgroupcount = whole count)
392 if (group && !group->isRaidGroup() && m_AllySet.size() == (group->GetMembersCount() + 2))
393 return;
394
395 m_AllySet.clear();
396 m_AllySet.insert(me->GetGUID());
397 if (group) //add group
398 {
399 for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
400 {
401 Player* Target = itr->GetSource();
402 if (!Target || !Target->IsInMap(owner) || !group->SameSubGroup(owner->ToPlayer(), Target))
403 continue;
404
405 if (Target->GetGUID() == owner->GetGUID())
406 continue;
407
408 m_AllySet.insert(Target->GetGUID());
409 }
410 }
411 else //remove group
412 m_AllySet.insert(owner->GetGUID());
413}
constexpr auto IN_MILLISECONDS
Definition Common.h:53
Definition GroupReference.h:27
Definition Group.h:177
uint32 GetMembersCount() const
Definition Group.h:254
GroupReference * GetFirstMember()
Definition Group.h:252
bool SameSubGroup(ObjectGuid guid1, ObjectGuid guid2) const
Definition Group.cpp:2582
bool isRaidGroup() const
Definition Group.cpp:2490
Group * GetGroup()
Definition Player.h:2517
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:1344

References Unit::GetCharmerOrOwner(), Group::GetFirstMember(), Player::GetGroup(), Object::GetGUID(), Group::GetMembersCount(), IN_MILLISECONDS, WorldObject::IsInMap(), Object::IsPlayer(), Group::isRaidGroup(), m_AllySet, m_updateAlliesTimer, CreatureAI::me, Group::SameSubGroup(), and Object::ToPlayer().

Referenced by PetAI(), and UpdateAI().

Member Data Documentation

◆ combatRange

float PetAI::combatRange
private

Referenced by _canMeleeAttack(), and StartChase().

◆ i_tracker

TimeTracker PetAI::i_tracker
private

◆ m_AllySet

GuidSet PetAI::m_AllySet
private

Referenced by UpdateAI(), and UpdateAllies().

◆ m_updateAlliesTimer

uint32 PetAI::m_updateAlliesTimer
private

Referenced by UpdateAI(), and UpdateAllies().


The documentation for this class was generated from the following files: