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 ()
 
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 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)
 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 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:361
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:836
Creature *const me
Definition CreatureAI.h:71
virtual uint8 GetPetAutoSpellSize() const
Definition Creature.h:328
virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const
Definition Creature.h:329
uint32 GetEntry() const
Definition Object.h:117
float combatRange
Definition PetAI.h:85
Definition SpellInfo.h:340
SpellSchoolMask GetSchoolMask() const
Definition SpellInfo.cpp:1894
float GetMaxRange(bool positive=false, Unit *caster=nullptr, Spell *spell=nullptr) const
Definition SpellInfo.cpp:2723
int32 CalcPowerCost(Unit const *caster, SpellSchoolMask schoolMask, Spell *spell=nullptr) const
Definition SpellInfo.cpp:2803
uint32 GetPower(Powers power) const
Definition Unit.h:1135

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 DoAttack().

◆ _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:40

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:2595
Definition Unit.h:664
bool IsCharmed() const
Definition Unit.h:1310
Unit * GetCharmer() const
Definition Unit.cpp:7690
Unit * GetCharmerOrOwner() const
Definition Unit.h:1286
Unit * GetVictim() const
Definition Unit.h:903
float GetVisibilityRange() const
Definition Object.cpp:1701
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:170
void MoveIdle()
Definition MotionMaster.cpp:234
void Clear(bool reset=true)
Definition MotionMaster.h:193
std::string ToString() const
Definition ObjectGuid.cpp:47
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:114
void ClearCharmInfoFlags()
Definition PetAI.cpp:795
void HandleReturnMovement()
Definition PetAI.cpp:546
void RemoveMeFromThreatLists()
Definition ThreatManager.cpp:794
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true, bool bySelf=false)
Definition Unit.cpp:4302
MotionMaster * GetMotionMaster()
Definition Unit.h:1758
bool IsAlive() const
Definition Unit.h:1793
CharmInfo * GetCharmInfo()
Definition Unit.h:1281
ThreatManager & GetThreatMgr()
Definition Unit.h:951
void CombatStop(bool includingCast=false, bool mutualPvP=true)
Definition Unit.cpp:7469
bool AttackStop()
Force the unit to stop attacking. This will clear UNIT_STATE_MELEE_ATTACKING, Interrupt current spell...
Definition Unit.cpp:7436
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.

812{
813 // Called when pet takes damage. This function helps keep pets from running off
814 // simply due to gaining aggro.
815
816 if (!attacker)
817 return;
818
819 // Passive pets don't do anything
821 return;
822
823 // Prevent pet from disengaging from current target
824 if (me->GetVictim() && me->GetVictim()->IsAlive())
825 return;
826
827 // Continue to evaluate and attack if necessary
828 AttackStart(attacker);
829}
@ REACT_PASSIVE
Definition Unit.h:566
bool HasReactState(ReactStates state) const
Definition Creature.h:101
void AttackStart(Unit *target) override
Definition PetAI.cpp:425

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

◆ AttackStart()

void PetAI::AttackStart ( Unit target)
overridevirtual

Reimplemented from UnitAI.

426{
427 // Overrides Unit::AttackStart to correctly evaluate Pet states
428
429 // Check all pet states to decide if we can attack this target
430 if (!CanAttack(target))
431 return;
432
433 // Only chase if not commanded to stay or if stay but commanded to attack
435}
@ COMMAND_STAY
Definition Unit.h:573
void DoAttack(Unit *target, bool chase)
Definition PetAI.cpp:612
bool CanAttack(Unit *target, SpellInfo const *spellInfo=nullptr)
Definition PetAI.cpp:689
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
690{
691 // Evaluates wether a pet can attack a specific target based on CommandState, ReactState and other flags
692 // IMPORTANT: The order in which things are checked is important, be careful if you add or remove checks
693
694 // Hmmm...
695 if (!target)
696 return false;
697
698 if (!target->IsAlive())
699 {
700 // xinef: if target is invalid, pet should evade automaticly
701 // Clear target to prevent getting stuck on dead targets
702 //me->AttackStop();
703 //me->InterruptNonMeleeSpells(false);
704 return false;
705 }
706
707 // xinef: check unit states of pet
709 return false;
710
711 // xinef: pets of mounted players have stunned flag only, check this also
713 return false;
714
715 // pussywizard: TEMP!
716 if (!me->GetCharmInfo())
717 {
718 LOG_INFO("misc", "PetAI::CanAttack (A1) - {}, {}", me->GetEntry(), me->GetOwnerGUID().ToString());
719 return false;
720 }
721
722 // Passive - passive pets can attack if told to
724 return me->GetCharmInfo()->IsCommandAttack();
725
726 // CC - mobs under crowd control can be attacked if owner commanded
727 if (target->HasBreakableByDamageCrowdControlAura() && (!spellInfo || !spellInfo->HasAttribute(SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS)))
728 return me->GetCharmInfo()->IsCommandAttack();
729
730 // Returning - pets ignore attacks only if owner clicked follow
731 if (me->GetCharmInfo()->IsReturning())
732 return !me->GetCharmInfo()->IsCommandFollow();
733
734 // Stay - can attack if target is within range or commanded to
736 return (me->IsWithinMeleeRange(target) || me->GetCharmInfo()->IsCommandAttack());
737
738 // Pets attacking something (or chasing) should only switch targets if owner tells them to
739 if (me->GetVictim() && me->GetVictim() != target)
740 {
741 // Forced change target if it's taunt
742 if (spellInfo && spellInfo->HasAura(SPELL_AURA_MOD_TAUNT))
743 {
744 return true;
745 }
746
747 // Check if our owner selected this target and clicked "attack"
748 Unit* ownerTarget = nullptr;
749 Unit* charmerOrOwner = me->GetCharmerOrOwner();
750
751 if (charmerOrOwner)
752 {
753 if (Player* owner = charmerOrOwner->ToPlayer())
754 ownerTarget = owner->GetSelectedUnit();
755 else
756 ownerTarget = charmerOrOwner->GetVictim();
757 }
758
759 if (ownerTarget && me->GetCharmInfo()->IsCommandAttack())
760 return (target->GetGUID() == ownerTarget->GetGUID());
761 }
762
763 // Follow
765 return !me->GetCharmInfo()->IsReturning();
766
767 // default, though we shouldn't ever get here
768 return false;
769}
#define LOG_INFO(filterType__,...)
Definition Log.h:166
@ 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:574
Player * ToPlayer()
Definition Object.h:202
Definition Player.h:1084
bool HasBreakableByDamageCrowdControlAura(Unit *excludeCasterChannel=nullptr) const
Definition Unit.cpp:960
bool HasUnitFlag(UnitFlags flags) const
Definition Unit.h:747
bool IsWithinMeleeRange(Unit const *obj, float dist=0.f) const
Definition Unit.cpp:782
bool HasUnitState(const uint32 f) const
Definition Unit.h:736
ObjectGuid GetOwnerGUID() const
Definition Unit.h:713
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
796{
797 // Quick access to set all flags to FALSE
798
799 CharmInfo* ci = me->GetCharmInfo();
800
801 if (ci)
802 {
803 ci->SetIsAtStay(false);
804 ci->SetIsCommandAttack(false);
805 ci->SetIsCommandFollow(false);
806 ci->SetIsFollowing(false);
807 ci->SetIsReturning(false);
808 }
809}
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
613{
614 // Handles attack with or without chase and also resets flags
615 // for next update / creature kill
616
617 if (me->Attack(target, true))
618 {
619 // xinef: properly fix fake combat after pet is sent to attack
620 if (Unit* owner = me->GetOwner())
621 owner->SetUnitFlag(UNIT_FLAG_PET_IN_COMBAT);
622
624
625 // Play sound to let the player know the pet is attacking something it picked on its own
628
629 if (chase)
630 {
631 bool oldCmdAttack = me->GetCharmInfo()->IsCommandAttack(); // This needs to be reset after other flags are cleared
633 me->GetCharmInfo()->SetIsCommandAttack(oldCmdAttack); // For passive pets commanded to attack so they will use spells
634
635 if (_canMeleeAttack())
636 {
637 std::optional<ChaseAngle> chaseAngle;
638 if (combatRange == 0.f && !target->IsPlayer() && !target->IsPet())
639 chaseAngle.emplace(float(M_PI), float(M_PI_4));
640
641 me->GetMotionMaster()->MoveChase(target, ChaseRange(0.f, combatRange), chaseAngle);
642 }
643 }
644 else // (Stay && ((Aggressive || Defensive) && In Melee Range)))
645 {
647
648 me->GetCharmInfo()->SetIsAtStay(true);
651 }
652 }
653}
@ MOTION_SLOT_ACTIVE
Definition MotionMaster.h:65
@ UNIT_FLAG_PET_IN_COMBAT
Definition UnitDefines.h:268
@ REACT_AGGRESSIVE
Definition Unit.h:568
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:315
void MovementExpiredOnSlot(MovementSlot slot, bool reset=true)
Definition MotionMaster.h:220
bool IsPlayer() const
Definition Object.h:201
Unit * GetOwner() const
Definition Unit.cpp:7682
void SendPetAIReaction(ObjectGuid guid) const
Definition Unit.cpp:12978
bool IsPet() const
Definition Unit.h:797
bool Attack(Unit *victim, bool meleeAttack)
Definition Unit.cpp:7272
void SetUnitFlag(UnitFlags flags)
UnitFlags available in UnitDefines.h.
Definition Unit.h:748
Definition MotionMaster.h:110

References _canMeleeAttack(), Unit::Attack(), ClearCharmInfoFlags(), combatRange, Unit::GetCharmInfo(), Object::GetGUID(), Unit::GetMotionMaster(), Unit::GetOwner(), Creature::HasReactState(), CharmInfo::IsCommandAttack(), Unit::IsPet(), Object::IsPlayer(), CreatureAI::me, MOTION_SLOT_ACTIVE, MotionMaster::MoveChase(), MotionMaster::MoveIdle(), MotionMaster::MovementExpiredOnSlot(), REACT_AGGRESSIVE, Unit::SendPetAIReaction(), CharmInfo::SetIsAtStay(), CharmInfo::SetIsCommandAttack(), Unit::SetUnitFlag(), 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
547{
548 // Handles moving the pet back to stay or owner
549
550 // Prevent activating movement when under control of spells
551 // such as "Eyes of the Beast"
552 if (me->isPossessed())
553 return;
554
556 {
557 if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning())
558 {
560 {
561 // Return to previous position where stay was clicked
563 {
564 float x, y, z;
565 me->GetCharmInfo()->GetStayPosition(x, y, z);
569 me->GetMotionMaster()->MovePoint(me->GetGUID().GetCounter(), x, y, z);
570 }
571 }
572 }
573 }
574 else // COMMAND_FOLLOW
575 {
577 {
579 {
584 }
585 }
586 }
587
590
591 // xinef: remember that npcs summoned by npcs can also be pets
594}
@ MOTION_SLOT_CONTROLLED
Definition MotionMaster.h:66
@ NULL_MOTION_TYPE
Definition MotionMaster.h:59
constexpr float PET_FOLLOW_DIST
Definition PetDefines.h:206
MovementGeneratorType GetMotionSlotType(int slot) const
Definition MotionMaster.cpp:969
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:447
void MovePoint(uint32 id, const Position &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:240
LowType GetCounter() const
Definition ObjectGuid.h:145
void ClearAllThreat()
Definition ThreatManager.cpp:580
void ClearInPetCombat()
Definition Unit.cpp:10678
bool isPossessed() const
Definition Unit.h:1311
virtual float GetFollowAngle() const
Definition Unit.h:1895
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.

401{
402 // Called from Unit::Kill() in case where pet or owner kills something
403 // if owner killed this victim, pet may still be attacking something else
404 if (me->GetVictim() && me->GetVictim() != victim)
405 return;
406
407 // Xinef: if pet is channeling a spell and owner killed something different, dont interrupt it
409 return;
410
411 // Clear target just in case. May help problem where health / focus / mana
412 // regen gets stuck. Also resets attack command.
413 // Can't use _stopAttack() because that activates movement handlers and ignores
414 // next target selection
415 me->AttackStop();
417
418 // Before returning to owner, see if there are more things to attack
419 if (Unit* nextTarget = SelectNextTarget(false))
420 AttackStart(nextTarget);
421 else
422 HandleReturnMovement(); // Return
423}
@ UNIT_STATE_CASTING
Definition UnitDefines.h:188
@ UNIT_FIELD_CHANNEL_OBJECT
Definition UpdateFields.h:93
ObjectGuid GetGuidValue(uint16 index) const
Definition Object.cpp:326
Unit * SelectNextTarget(bool allowAutoSelect) const
Definition PetAI.cpp:478

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.

656{
657 // Receives notification when pet reaches stay or follow owner
658 switch (moveType)
659 {
661 {
662 // Pet is returning to where stay was clicked. data should be
663 // pet's GUIDLow since we set that as the waypoint ID
664 if (data == me->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning())
665 {
667 me->GetCharmInfo()->SetIsAtStay(true);
670 }
671 break;
672 }
674 {
675 // If data is owner's GUIDLow then we've reached follow point,
676 // otherwise we're probably chasing a creature
678 {
681 }
682 break;
683 }
684 default:
685 break;
686 }
687}
@ 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.

458{
459 // Called when owner attacks something. Allows defensive pets to know
460 // that they need to assist
461
462 // Target might be nullptr if called from spell with invalid cast targets
463 if (!target)
464 return;
465
466 // Passive pets don't do anything
468 return;
469
470 // Prevent pet from disengaging from current target
471 if (me->GetVictim() && me->GetVictim()->IsAlive())
472 return;
473
474 // Continue to evaluate and attack if necessary
475 AttackStart(target);
476}

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

◆ OwnerAttackedBy()

void PetAI::OwnerAttackedBy ( Unit attacker)
overridevirtual

Reimplemented from CreatureAI.

438{
439 // Called when owner takes damage. This function helps keep pets from running off
440 // simply due to owner gaining aggro.
441
442 if (!attacker)
443 return;
444
445 // Passive pets don't do anything
447 return;
448
449 // Prevent pet from disengaging from current target
450 if (me->GetVictim() && me->GetVictim()->IsAlive())
451 return;
452
453 // Continue to evaluate and attack if necessary
454 AttackStart(attacker);
455}

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:288
@ PERMIT_BASE_NO
Definition CreatureAI.h:285
@ PERMIT_BASE_REACTIVE
Definition CreatureAI.h:287
@ 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.

772{
773 if (me->GetOwnerGUID() && me->GetOwnerGUID() == player->GetGUID())
774 switch (emote)
775 {
776 case TEXT_EMOTE_COWER:
777 if (me->IsPet() && me->ToPet()->IsPetGhoul())
778 me->HandleEmoteCommand(/*EMOTE_ONESHOT_ROAR*/EMOTE_ONESHOT_OMNICAST_GHOUL);
779 break;
780 case TEXT_EMOTE_ANGRY:
781 if (me->IsPet() && me->ToPet()->IsPetGhoul())
782 me->HandleEmoteCommand(/*EMOTE_ONESHOT_COWER*/EMOTE_STATE_STUN);
783 break;
784 case TEXT_EMOTE_GLARE:
785 if (me->IsPet() && me->ToPet()->IsPetGhoul())
787 break;
789 if (me->IsPet() && me->ToPet()->IsPetGhoul())
791 break;
792 }
793}
@ EMOTE_ONESHOT_OMNICAST_GHOUL
Definition SharedDefines.h:2034
@ EMOTE_STATE_STUN
Definition SharedDefines.h:1946
@ TEXT_EMOTE_ANGRY
Definition SharedDefines.h:1644
@ TEXT_EMOTE_SOOTHE
Definition SharedDefines.h:1775
@ TEXT_EMOTE_COWER
Definition SharedDefines.h:1669
@ TEXT_EMOTE_GLARE
Definition SharedDefines.h:1687
bool IsPetGhoul() const
Definition TemporarySummon.h:95
Pet * ToPet()
Definition Unit.h:729
void HandleEmoteCommand(uint32 emoteId)
Definition Unit.cpp:2172

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
479{
480 // Provides next target selection after current target death.
481 // This function should only be called internally by the AI
482 // Targets are not evaluated here for being valid targets, that is done in _CanAttack()
483 // The parameter: allowAutoSelect lets us disable aggressive pet auto targeting for certain situations
484
485 // Passive pets don't do next target selection
487 return nullptr;
488
489 // Check pet attackers first so we don't drag a bunch of targets to the owner
490 if (Unit* myAttacker = me->getAttackerForHelper())
491 if (!myAttacker->HasBreakableByDamageCrowdControlAura() && me->CanCreatureAttack(myAttacker))
492 return myAttacker;
493
494 // Check pet's attackers first to prevent dragging mobs back to owner
495 if (me->HasTauntAura())
496 {
498 if (!tauntAuras.empty())
499 for (Unit::AuraEffectList::const_reverse_iterator itr = tauntAuras.rbegin(); itr != tauntAuras.rend(); ++itr)
500 if (Unit* caster = (*itr)->GetCaster())
501 if (me->CanCreatureAttack(caster) && !caster->HasAuraTypeWithCaster(SPELL_AURA_MOD_DETAUNT, me->GetGUID()))
502 return caster;
503 }
504
505 // Not sure why we wouldn't have an owner but just in case...
506 Unit* owner = me->GetCharmerOrOwner();
507 if (!owner)
508 return nullptr;
509
510 // Check owner attackers
511 if (Unit* ownerAttacker = owner->getAttackerForHelper())
512 if (!ownerAttacker->HasBreakableByDamageCrowdControlAura() && me->CanCreatureAttack(ownerAttacker))
513 return ownerAttacker;
514
515 // Check owner victim
516 // 3.0.2 - Pets now start attacking their owners victim in defensive mode as soon as the hunter does
517 if (Unit* ownerVictim = owner->GetVictim())
518 if (me->CanCreatureAttack(ownerVictim))
519 return ownerVictim;
520
521 // Neither pet or owner had a target and aggressive pets can pick any target
522 // To prevent aggressive pets from chain selecting targets and running off, we
523 // only select a random target if certain conditions are met.
524 if (allowAutoSelect)
525 {
527 {
529 {
530 if (nearTarget->IsPlayer() && nearTarget->ToPlayer()->IsPvP() && !owner->IsPvP()) // If owner is not PvP flagged and target is PvP flagged, do not attack
531 {
532 return nullptr;
533 }
534 else
535 {
536 return nearTarget;
537 }
538 }
539 }
540 }
541
542 // Default - no valid targets
543 return nullptr;
544}
@ SPELL_AURA_MOD_DETAUNT
Definition SpellAuraDefines.h:284
#define MAX_AGGRO_RADIUS
Definition Unit.h:43
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:2372
Creature * ToCreature()
Definition Object.h:206
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1428
std::vector< AuraEffect * > AuraEffectList
Definition Unit.h:680
Unit * getAttackerForHelper() const
Definition Unit.cpp:871
bool IsPvP() const
Definition Unit.h:1044
bool HasTauntAura() const
Definition Unit.h:1840

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.

597{
598 // Xinef: taunt behavior code
599 if (spellInfo->HasAura(SPELL_AURA_MOD_TAUNT) && !me->HasReactState(REACT_PASSIVE))
600 {
603
604 if (CanAttack(caster, spellInfo))
605 {
606 // Only chase if not commanded to stay or if stay but commanded to attack
608 }
609 }
610}

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.

◆ 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 // Check before attacking to prevent pets from leaving stay position
179 {
182 }
183 else
185 }
186 else if (!me->GetCharmInfo() || (!me->GetCharmInfo()->GetForcedSpell() && !(me->IsPet() && me->ToPet()->HasTempSpell()) && !me->HasUnitState(UNIT_STATE_CASTING)))
187 {
189 {
190 // Every update we need to check targets only in certain cases
191 // Aggressive - Allow auto select if owner or pet don't have a target
192 // Stay - Only pick from pet or owner targets / attackers so targets won't run by
193 // while chasing our owner. Don't do auto select.
194 // All other cases (ie: defensive) - Targets are assigned by AttackedBy(), OwnerAttackedBy(), OwnerAttacked(), etc.
196
197 if (nextTarget)
198 AttackStart(nextTarget);
199 else
201 }
202 else
204 }
205
206 // xinef: charm info must be always available
207 if (!me->GetCharmInfo())
208 return;
209
210 // Autocast (casted only in combat or persistent spells in any state)
212 {
213 if (owner && owner->IsPlayer() && me->GetCharmInfo()->GetForcedSpell() && me->GetCharmInfo()->GetForcedTarget())
214 {
216
217 // xinef: if spell was casted properly and we are in passive mode, handle return
219 {
221 {
222 me->GetMotionMaster()->Clear(false);
223 me->StopMoving();
224 }
225 else
226 _stopAttack();
227 }
228 return;
229 }
230
231 // xinef: dont allow ghouls to cast spells below 75 energy
232 if (me->IsPet() && me->ToPet()->IsPetGhoul() && me->GetPower(POWER_ENERGY) < 75)
233 return;
234
235 typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
236 TargetSpellList targetSpellStore;
237
238 for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
239 {
240 uint32 spellID = me->GetPetAutoSpellOnPos(i);
241 if (!spellID)
242 continue;
243
244 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
245 if (!spellInfo)
246 continue;
247
249 continue;
250
251 // check spell cooldown, this should be checked in CheckCast...
252 if (me->HasSpellCooldown(spellInfo->Id))
253 continue;
254
255 if (spellInfo->IsPositive())
256 {
257 if (spellInfo->CanBeUsedInCombat())
258 {
259 // Check if we're in combat or commanded to attack (exlude auras with infinity duration)
260 if (!me->IsInCombat() && spellInfo->GetMaxDuration() != -1 && !me->IsPetInCombat())
261 {
262 continue;
263 }
264 }
265
266 Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE);
267 spell->LoadScripts(); // xinef: load for CanAutoCast (calling CheckPetCast)
268 bool spellUsed = false;
269
270 // Some spells can target enemy or friendly (DK Ghoul's Leap)
271 // Check for enemy first (pet then owner)
272 Unit* target = me->getAttackerForHelper();
273 if (!target && owner)
274 target = owner->getAttackerForHelper();
275
276 if (target)
277 {
278 if (CanAttack(target) && spell->CanAutoCast(target))
279 {
280 targetSpellStore.emplace_back(target, spell);
281 spellUsed = true;
282 }
283 }
284
285 if (spellInfo->HasEffect(SPELL_EFFECT_JUMP_DEST))
286 {
287 if (!spellUsed)
288 delete spell;
289
290 continue; // Pets must only jump to target
291 }
292
293 // No enemy, check friendly
294 if (!spellUsed)
295 {
296 for (ObjectGuid const& guid : m_AllySet)
297 {
298 Unit* ally = ObjectAccessor::GetUnit(*me, guid);
299
300 //only buff targets that are in combat, unless the spell can only be cast while out of combat
301 if (!ally)
302 continue;
303
304 if (spell->CanAutoCast(ally))
305 {
306 targetSpellStore.emplace_back(ally, spell);
307 spellUsed = true;
308 break;
309 }
310 }
311 }
312
313 // No valid targets at all
314 if (!spellUsed)
315 delete spell;
316 }
317 else if (me->GetVictim() && CanAttack(me->GetVictim(), spellInfo) && spellInfo->CanBeUsedInCombat())
318 {
319 Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE);
320 if (spell->CanAutoCast(me->GetVictim()))
321 targetSpellStore.emplace_back(me->GetVictim(), spell);
322 else
323 delete spell;
324 }
325 }
326
327 //found units to cast on to
328 if (!targetSpellStore.empty())
329 {
330 uint32 index = urand(0, targetSpellStore.size() - 1);
331
332 Spell* spell = targetSpellStore[index].second;
333 Unit* target = targetSpellStore[index].first;
334
335 targetSpellStore.erase(targetSpellStore.begin() + index);
336
337 SpellCastTargets targets;
338 targets.SetUnitTarget(target);
339
340 if (!me->HasInArc(M_PI, target))
341 {
342 me->SetInFront(target);
343 if (target && target->IsPlayer())
344 me->SendUpdateToPlayer(target->ToPlayer());
345
346 if (owner && owner->IsPlayer())
347 me->SendUpdateToPlayer(owner->ToPlayer());
348 }
349
350 me->AddSpellCooldown(spell->m_spellInfo->Id, 0, 0);
351
352 spell->prepare(&targets);
353 }
354
355 // deleted cached Spell objects
356 for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
357 delete itr->second;
358 }
359}
@ 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:133
bool HasSpellCooldown(uint32 spell_id) const override
Definition Creature.cpp:2963
void AddSpellCooldown(uint32 spell_id, uint32, uint32 end_time, bool needSendToClient=false, bool forceSendToSpectator=false) override
Definition Creature.cpp:2908
bool HasGlobalCooldown(SpellInfo const *spellInfo) const
Definition CharmInfo.cpp:397
Definition ObjectGuid.h:118
void SendUpdateToPlayer(Player *player)
Definition Object.cpp:235
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
bool HasTempSpell() const
Definition Pet.h:147
WorldSession * GetSession() const
Definition Player.h:2019
Definition Spell.h:121
void SetUnitTarget(Unit *target)
Definition Spell.cpp:238
uint32 Id
Definition SpellInfo.h:344
int32 GetMaxDuration() const
Definition SpellInfo.cpp:2745
bool CanBeUsedInCombat() const
Definition SpellInfo.cpp:1264
bool HasEffect(SpellEffects effect) const
Definition SpellInfo.cpp:885
bool IsPositive() const
Definition SpellInfo.cpp:1269
Definition Spell.h:298
void LoadScripts()
Definition Spell.cpp:8534
SpellCastResult prepare(SpellCastTargets const *targets, AuraEffect const *triggeredByAura=nullptr)
Definition Spell.cpp:3404
SpellInfo const *const m_spellInfo
Definition Spell.h:535
bool CanAutoCast(Unit *target)
Definition Spell.cpp:6981
void StopMoving()
Definition Unit.cpp:12997
bool IsPetInCombat() const
Definition Unit.h:938
void SetInFront(WorldObject const *target)
Definition Unit.cpp:16405
bool IsInCombat() const
Definition Unit.h:935
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:199
int32 GetForcedSpell()
Definition CharmInfo.h:178
ObjectGuid GetForcedTarget()
Definition CharmInfo.h:180
GlobalCooldownMgr & GetGlobalCooldownMgr()
Definition CharmInfo.h:160
bool HasInArc(float arcangle, const Position *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_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(), Unit::IsAlive(), CharmInfo::IsAtStay(), CharmInfo::IsCommandAttack(), Unit::IsInCombat(), 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(), SpellCastTargets::SetUnitTarget(), SPELL_EFFECT_JUMP_DEST, sSpellMgr, Unit::StopMoving(), Unit::ToPet(), Object::ToPlayer(), ObjectGuid::ToString(), TRIGGERED_NONE, UNIT_STATE_CASTING, UpdateAllies(), and urand().

◆ UpdateAllies()

void PetAI::UpdateAllies ( )
private
362{
363 Unit* owner = me->GetCharmerOrOwner();
364 Group* group = nullptr;
365
366 m_updateAlliesTimer = 10 * IN_MILLISECONDS; //update friendly targets every 10 seconds, lesser checks increase performance
367
368 if (!owner)
369 return;
370 else if (owner->IsPlayer())
371 group = owner->ToPlayer()->GetGroup();
372
373 //only pet and owner/not in group->ok
374 if (m_AllySet.size() == 2 && !group)
375 return;
376 //owner is in group; group members filled in already (no raid -> subgroupcount = whole count)
377 if (group && !group->isRaidGroup() && m_AllySet.size() == (group->GetMembersCount() + 2))
378 return;
379
380 m_AllySet.clear();
381 m_AllySet.insert(me->GetGUID());
382 if (group) //add group
383 {
384 for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
385 {
386 Player* Target = itr->GetSource();
387 if (!Target || !Target->IsInMap(owner) || !group->SameSubGroup(owner->ToPlayer(), Target))
388 continue;
389
390 if (Target->GetGUID() == owner->GetGUID())
391 continue;
392
393 m_AllySet.insert(Target->GetGUID());
394 }
395 }
396 else //remove group
397 m_AllySet.insert(owner->GetGUID());
398}
constexpr auto IN_MILLISECONDS
Definition Common.h:53
Definition GroupReference.h:27
Definition Group.h:169
uint32 GetMembersCount() const
Definition Group.h:245
GroupReference * GetFirstMember()
Definition Group.h:243
bool SameSubGroup(ObjectGuid guid1, ObjectGuid guid2) const
Definition Group.cpp:2373
bool isRaidGroup() const
Definition Group.cpp:2281
Group * GetGroup()
Definition Player.h:2504
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:1335

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 DoAttack().

◆ 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: