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=0s)
 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
 
void MoveCircleChecks ()
 
void MoveBackwardsChecks ()
 
void MoveInLineOfSight_Safe (Unit *who)
 == Reactions At =================================
 
void TriggerAlert (Unit const *who) const
 
virtual bool CanRespawn ()
 
virtual void JustEngagedWith (Unit *)
 Called for reaction when initially engaged.
 
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 bool IsEscorted ()
 
virtual void JustRespawned ()
 
virtual void PathEndReached (uint32)
 
void OnCharmed (bool apply) override
 Called when unit is charmed.
 
virtual void JustReachedHome ()
 
void DoZoneInCombat (Creature *creature=nullptr, float maxRangeToNearestTarget=250.0f)
 
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 *)
 
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)
 
- 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, 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 JustEnteredCombat (Unit *)
 Called when the unit enters combat.
 
virtual void JustExitedCombat ()
 Called when the unit leaves combat.
 
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
 
- 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:35
Definition CreatureAI.h:70
void UpdateAllies()
Definition PetAI.cpp:353
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:269
#define sSpellMgr
Definition SpellMgr.h:825
Creature *const me
Definition CreatureAI.h:72
virtual uint8 GetPetAutoSpellSize() const
Definition Creature.h:324
virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const
Definition Creature.h:325
uint32 GetEntry() const
Definition Object.h:115
float combatRange
Definition PetAI.h:85
Definition SpellInfo.h:316
SpellSchoolMask GetSchoolMask() const
Definition SpellInfo.cpp:1987
float GetMaxRange(bool positive=false, Unit *caster=nullptr, Spell *spell=nullptr) const
Definition SpellInfo.cpp:2323
int32 CalcPowerCost(Unit const *caster, SpellSchoolMask schoolMask, Spell *spell=nullptr) const
Definition SpellInfo.cpp:2401
uint32 GetPower(Powers power) const
Definition Unit.h:1065

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

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:2630
Definition Unit.h:636
bool IsCharmed() const
Definition Unit.h:1244
Unit * GetCharmer() const
Definition Unit.cpp:10653
Unit * GetCharmerOrOwner() const
Definition Unit.h:1220
Unit * GetVictim() const
Definition Unit.h:862
float GetVisibilityRange() const
Definition Object.cpp:1656
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:169
void deleteReferences(bool removeFromMap=false)
Definition HostileRefMgr.cpp:125
void MoveIdle()
Definition MotionMaster.cpp:232
void Clear(bool reset=true)
Definition MotionMaster.h:167
std::string ToString() const
Definition ObjectGuid.cpp:47
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:112
void ClearCharmInfoFlags()
Definition PetAI.cpp:780
void HandleReturnMovement()
Definition PetAI.cpp:538
void CombatStop(bool includingCast=false)
Definition Unit.cpp:10481
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true, bool bySelf=false)
Definition Unit.cpp:4161
MotionMaster * GetMotionMaster()
Definition Unit.h:1673
bool IsAlive() const
Definition Unit.h:1707
CharmInfo * GetCharmInfo()
Definition Unit.h:1215
HostileRefMgr & getHostileRefMgr()
Definition Unit.h:916
bool AttackStop()
Force the unit to stop attacking. This will clear UNIT_STATE_MELEE_ATTACKING, Interrupt current spell...
Definition Unit.cpp:10448
void SetIsCommandAttack(bool val)
Definition CharmInfo.cpp:303

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

Referenced by PetStopAttack(), and UpdateAI().

◆ AttackedBy()

void PetAI::AttackedBy ( Unit attacker)
overridevirtual

Reimplemented from CreatureAI.

797{
798 // Called when pet takes damage. This function helps keep pets from running off
799 // simply due to gaining aggro.
800
801 if (!attacker)
802 return;
803
804 // Passive pets don't do anything
806 return;
807
808 // Prevent pet from disengaging from current target
809 if (me->GetVictim() && me->GetVictim()->IsAlive())
810 return;
811
812 // Continue to evaluate and attack if necessary
813 AttackStart(attacker);
814}
@ REACT_PASSIVE
Definition Unit.h:548
bool HasReactState(ReactStates state) const
Definition Creature.h:97
void AttackStart(Unit *target) override
Definition PetAI.cpp:417

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

◆ AttackStart()

void PetAI::AttackStart ( Unit target)
overridevirtual

Reimplemented from UnitAI.

418{
419 // Overrides Unit::AttackStart to correctly evaluate Pet states
420
421 // Check all pet states to decide if we can attack this target
422 if (!CanAttack(target))
423 return;
424
425 // Only chase if not commanded to stay or if stay but commanded to attack
427}
@ COMMAND_STAY
Definition Unit.h:555
void DoAttack(Unit *target, bool chase)
Definition PetAI.cpp:604
bool CanAttack(Unit *target, SpellInfo const *spellInfo=nullptr)
Definition PetAI.cpp:679
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
680{
681 // Evaluates wether a pet can attack a specific target based on CommandState, ReactState and other flags
682 // IMPORTANT: The order in which things are checked is important, be careful if you add or remove checks
683
684 // Hmmm...
685 if (!target)
686 return false;
687
688 if (!target->IsAlive())
689 {
690 // xinef: if target is invalid, pet should evade automaticly
691 // Clear target to prevent getting stuck on dead targets
692 //me->AttackStop();
693 //me->InterruptNonMeleeSpells(false);
694 return false;
695 }
696
697 // xinef: check unit states of pet
699 return false;
700
701 // xinef: pets of mounted players have stunned flag only, check this also
703 return false;
704
705 // pussywizard: TEMP!
706 if (!me->GetCharmInfo())
707 {
708 LOG_INFO("misc", "PetAI::CanAttack (A1) - {}, {}", me->GetEntry(), me->GetOwnerGUID().ToString());
709 return false;
710 }
711
712 // Passive - passive pets can attack if told to
714 return me->GetCharmInfo()->IsCommandAttack();
715
716 // CC - mobs under crowd control can be attacked if owner commanded
717 if (target->HasBreakableByDamageCrowdControlAura() && (!spellInfo || !spellInfo->HasAttribute(SPELL_ATTR4_REACTIVE_DAMAGE_PROC)))
718 return me->GetCharmInfo()->IsCommandAttack();
719
720 // Returning - pets ignore attacks only if owner clicked follow
721 if (me->GetCharmInfo()->IsReturning())
722 return !me->GetCharmInfo()->IsCommandFollow();
723
724 // Stay - can attack if target is within range or commanded to
726 return (me->IsWithinMeleeRange(target) || me->GetCharmInfo()->IsCommandAttack());
727
728 // Pets attacking something (or chasing) should only switch targets if owner tells them to
729 if (me->GetVictim() && me->GetVictim() != target)
730 {
731 // Forced change target if it's taunt
732 if (spellInfo && spellInfo->HasAura(SPELL_AURA_MOD_TAUNT))
733 {
734 return true;
735 }
736
737 // Check if our owner selected this target and clicked "attack"
738 Unit* ownerTarget = nullptr;
739 if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
740 ownerTarget = owner->GetSelectedUnit();
741 else
742 ownerTarget = me->GetCharmerOrOwner()->GetVictim();
743
744 if (ownerTarget && me->GetCharmInfo()->IsCommandAttack())
745 return (target->GetGUID() == ownerTarget->GetGUID());
746 }
747
748 // Follow
750 return !me->GetCharmInfo()->IsReturning();
751
752 // default, though we shouldn't ever get here
753 return false;
754}
#define LOG_INFO(filterType__,...)
Definition Log.h:165
@ SPELL_ATTR4_REACTIVE_DAMAGE_PROC
Definition SharedDefines.h:544
@ SPELL_AURA_MOD_TAUNT
Definition SpellAuraDefines.h:74
@ UNIT_STATE_LOST_CONTROL
Definition UnitDefines.h:212
@ UNIT_FLAG_STUNNED
Definition UnitDefines.h:268
@ COMMAND_FOLLOW
Definition Unit.h:556
Player * ToPlayer()
Definition Object.h:201
Definition Player.h:1081
bool HasBreakableByDamageCrowdControlAura(Unit *excludeCasterChannel=nullptr) const
Definition Unit.cpp:787
bool HasUnitFlag(UnitFlags flags) const
Definition Unit.h:718
bool IsWithinMeleeRange(Unit const *obj, float dist=0.f) const
Definition Unit.cpp:664
bool HasUnitState(const uint32 f) const
Definition Unit.h:707
ObjectGuid GetOwnerGUID() const
Definition Unit.h:684
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_REACTIVE_DAMAGE_PROC, 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
781{
782 // Quick access to set all flags to FALSE
783
784 CharmInfo* ci = me->GetCharmInfo();
785
786 if (ci)
787 {
788 ci->SetIsAtStay(false);
789 ci->SetIsCommandAttack(false);
790 ci->SetIsCommandFollow(false);
791 ci->SetIsFollowing(false);
792 ci->SetIsReturning(false);
793 }
794}
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
605{
606 // Handles attack with or without chase and also resets flags
607 // for next update / creature kill
608
609 if (me->Attack(target, true))
610 {
611 // xinef: properly fix fake combat after pet is sent to attack
612 if (Unit* owner = me->GetOwner())
613 owner->SetUnitFlag(UNIT_FLAG_PET_IN_COMBAT);
614
616
617 // Play sound to let the player know the pet is attacking something it picked on its own
620
621 if (chase)
622 {
623 bool oldCmdAttack = me->GetCharmInfo()->IsCommandAttack(); // This needs to be reset after other flags are cleared
625 me->GetCharmInfo()->SetIsCommandAttack(oldCmdAttack); // For passive pets commanded to attack so they will use spells
626
627 if (_canMeleeAttack())
628 {
629 float angle = combatRange == 0.f && !target->IsPlayer() && !target->IsPet() ? float(M_PI) : 0.f;
630 float tolerance = combatRange == 0.f ? float(M_PI_4) : float(M_PI * 2);
631 me->GetMotionMaster()->MoveChase(target, ChaseRange(0.f, combatRange), ChaseAngle(angle, tolerance));
632 }
633 }
634 else // (Stay && ((Aggressive || Defensive) && In Melee Range)))
635 {
637
638 me->GetCharmInfo()->SetIsAtStay(true);
641 }
642 }
643}
@ MOTION_SLOT_ACTIVE
Definition MotionMaster.h:64
@ UNIT_FLAG_PET_IN_COMBAT
Definition UnitDefines.h:261
@ REACT_AGGRESSIVE
Definition Unit.h:550
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:313
void MovementExpiredOnSlot(MovementSlot slot, bool reset=true)
Definition MotionMaster.h:194
bool IsPlayer() const
Definition Object.h:200
Unit * GetOwner() const
Definition Unit.cpp:10645
bool IsPet() const
Definition Unit.h:763
bool Attack(Unit *victim, bool meleeAttack)
Definition Unit.cpp:10313
void SendPetAIReaction(ObjectGuid guid)
Definition Unit.cpp:16683
void SetUnitFlag(UnitFlags flags)
UnitFlags available in UnitDefines.h.
Definition Unit.h:719
Definition MotionMaster.h:97
Definition MotionMaster.h:84

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
539{
540 // Handles moving the pet back to stay or owner
541
542 // Prevent activating movement when under control of spells
543 // such as "Eyes of the Beast"
544 if (me->isPossessed())
545 return;
546
548 {
549 if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning())
550 {
552 {
553 // Return to previous position where stay was clicked
555 {
556 float x, y, z;
557 me->GetCharmInfo()->GetStayPosition(x, y, z);
561 me->GetMotionMaster()->MovePoint(me->GetGUID().GetCounter(), x, y, z);
562 }
563 }
564 }
565 }
566 else // COMMAND_FOLLOW
567 {
569 {
571 {
576 }
577 }
578 }
579
582
583 // xinef: remember that npcs summoned by npcs can also be pets
586}
@ MOTION_SLOT_CONTROLLED
Definition MotionMaster.h:65
@ NULL_MOTION_TYPE
Definition MotionMaster.h:58
#define PET_FOLLOW_DIST
Definition PetDefines.h:202
MovementGeneratorType GetMotionSlotType(int slot) const
Definition MotionMaster.cpp:921
void MovePoint(uint32 id, const Position &pos, bool generatePath=true, bool forceDestination=true)
Definition MotionMaster.h:213
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:409
LowType GetCounter() const
Definition ObjectGuid.h:145
void ClearAllThreat()
Definition ThreatMgr.cpp:417
void ClearInPetCombat()
Definition Unit.cpp:13896
bool isPossessed() const
Definition Unit.h:1245
virtual float GetFollowAngle() const
Definition Unit.h:1809
ThreatMgr & GetThreatMgr()
Definition Unit.h:912
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(), ThreatMgr::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.

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

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.

646{
647 // Receives notification when pet reaches stay or follow owner
648 switch (moveType)
649 {
651 {
652 // Pet is returning to where stay was clicked. data should be
653 // pet's GUIDLow since we set that as the waypoint ID
654 if (data == me->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning())
655 {
657 me->GetCharmInfo()->SetIsAtStay(true);
660 }
661 break;
662 }
664 {
665 // If data is owner's GUIDLow then we've reached follow point,
666 // otherwise we're probably chasing a creature
668 {
671 }
672 break;
673 }
674 default:
675 break;
676 }
677}
@ 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.

450{
451 // Called when owner attacks something. Allows defensive pets to know
452 // that they need to assist
453
454 // Target might be nullptr if called from spell with invalid cast targets
455 if (!target)
456 return;
457
458 // Passive pets don't do anything
460 return;
461
462 // Prevent pet from disengaging from current target
463 if (me->GetVictim() && me->GetVictim()->IsAlive())
464 return;
465
466 // Continue to evaluate and attack if necessary
467 AttackStart(target);
468}

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

◆ OwnerAttackedBy()

void PetAI::OwnerAttackedBy ( Unit attacker)
overridevirtual

Reimplemented from CreatureAI.

430{
431 // Called when owner takes damage. This function helps keep pets from running off
432 // simply due to owner gaining aggro.
433
434 if (!attacker)
435 return;
436
437 // Passive pets don't do anything
439 return;
440
441 // Prevent pet from disengaging from current target
442 if (me->GetVictim() && me->GetVictim()->IsAlive())
443 return;
444
445 // Continue to evaluate and attack if necessary
446 AttackStart(attacker);
447}

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_CONTROLABLE_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:244
@ PERMIT_BASE_NO
Definition CreatureAI.h:241
@ PERMIT_BASE_REACTIVE
Definition CreatureAI.h:243
@ UNIT_MASK_CONTROLABLE_GUARDIAN
Definition UnitDefines.h:164
Definition TemporarySummon.h:96

References Unit::HasUnitTypeMask(), PERMIT_BASE_NO, PERMIT_BASE_PROACTIVE, PERMIT_BASE_REACTIVE, and UNIT_MASK_CONTROLABLE_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.

757{
758 if (me->GetOwnerGUID() && me->GetOwnerGUID() == player->GetGUID())
759 switch (emote)
760 {
761 case TEXT_EMOTE_COWER:
762 if (me->IsPet() && me->ToPet()->IsPetGhoul())
763 me->HandleEmoteCommand(/*EMOTE_ONESHOT_ROAR*/EMOTE_ONESHOT_OMNICAST_GHOUL);
764 break;
765 case TEXT_EMOTE_ANGRY:
766 if (me->IsPet() && me->ToPet()->IsPetGhoul())
767 me->HandleEmoteCommand(/*EMOTE_ONESHOT_COWER*/EMOTE_STATE_STUN);
768 break;
769 case TEXT_EMOTE_GLARE:
770 if (me->IsPet() && me->ToPet()->IsPetGhoul())
772 break;
774 if (me->IsPet() && me->ToPet()->IsPetGhoul())
776 break;
777 }
778}
@ EMOTE_ONESHOT_OMNICAST_GHOUL
Definition SharedDefines.h:2028
@ EMOTE_STATE_STUN
Definition SharedDefines.h:1940
@ TEXT_EMOTE_ANGRY
Definition SharedDefines.h:1638
@ TEXT_EMOTE_SOOTHE
Definition SharedDefines.h:1769
@ TEXT_EMOTE_COWER
Definition SharedDefines.h:1663
@ TEXT_EMOTE_GLARE
Definition SharedDefines.h:1681
bool IsPetGhoul() const
Definition TemporarySummon.h:85
Pet * ToPet()
Definition Unit.h:700
void HandleEmoteCommand(uint32 emoteId)
Definition Unit.cpp:2011

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

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_IGNORED, 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.

589{
590 // Xinef: taunt behavior code
591 if (spellInfo->HasAura(SPELL_AURA_MOD_TAUNT) && !me->HasReactState(REACT_PASSIVE))
592 {
595
596 if (CanAttack(caster, spellInfo))
597 {
598 // Only chase if not commanded to stay or if stay but commanded to attack
600 }
601 }
602}

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 // No enemy, check friendly
286 if (!spellUsed)
287 {
288 for (ObjectGuid const& guid : m_AllySet)
289 {
290 Unit* ally = ObjectAccessor::GetUnit(*me, guid);
291
292 //only buff targets that are in combat, unless the spell can only be cast while out of combat
293 if (!ally)
294 continue;
295
296 if (spell->CanAutoCast(ally))
297 {
298 targetSpellStore.emplace_back(ally, spell);
299 spellUsed = true;
300 break;
301 }
302 }
303 }
304
305 // No valid targets at all
306 if (!spellUsed)
307 delete spell;
308 }
309 else if (me->GetVictim() && CanAttack(me->GetVictim(), spellInfo) && spellInfo->CanBeUsedInCombat())
310 {
311 Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE);
312 if (spell->CanAutoCast(me->GetVictim()))
313 targetSpellStore.emplace_back(me->GetVictim(), spell);
314 else
315 delete spell;
316 }
317 }
318
319 //found units to cast on to
320 if (!targetSpellStore.empty())
321 {
322 uint32 index = urand(0, targetSpellStore.size() - 1);
323
324 Spell* spell = targetSpellStore[index].second;
325 Unit* target = targetSpellStore[index].first;
326
327 targetSpellStore.erase(targetSpellStore.begin() + index);
328
329 SpellCastTargets targets;
330 targets.SetUnitTarget(target);
331
332 if (!me->HasInArc(M_PI, target))
333 {
334 me->SetInFront(target);
335 if (target && target->IsPlayer())
336 me->SendUpdateToPlayer(target->ToPlayer());
337
338 if (owner && owner->IsPlayer())
339 me->SendUpdateToPlayer(owner->ToPlayer());
340 }
341
342 me->AddSpellCooldown(spell->m_spellInfo->Id, 0, 0);
343
344 spell->prepare(&targets);
345 }
346
347 // deleted cached Spell objects
348 for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
349 delete itr->second;
350 }
351}
@ ACT_ENABLED
Definition CharmInfo.h:63
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:44
@ POWER_ENERGY
Definition SharedDefines.h:272
@ TRIGGERED_NONE
Definition SpellDefines.h:133
bool HasSpellCooldown(uint32 spell_id) const override
Definition Creature.cpp:2932
void AddSpellCooldown(uint32 spell_id, uint32, uint32 end_time, bool needSendToClient=false, bool forceSendToSpectator=false) override
Definition Creature.cpp:2877
bool HasGlobalCooldown(SpellInfo const *spellInfo) const
Definition CharmInfo.cpp:397
Definition ObjectGuid.h:118
void SendUpdateToPlayer(Player *player)
Definition Object.cpp:246
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:2005
Definition Spell.h:111
void SetUnitTarget(Unit *target)
Definition Spell.cpp:239
uint32 Id
Definition SpellInfo.h:320
int32 GetMaxDuration() const
Definition SpellInfo.cpp:2345
bool CanBeUsedInCombat() const
Definition SpellInfo.cpp:1232
bool IsPositive() const
Definition SpellInfo.cpp:1237
Definition Spell.h:287
void LoadScripts()
Definition Spell.cpp:8537
SpellCastResult prepare(SpellCastTargets const *targets, AuraEffect const *triggeredByAura=nullptr)
Definition Spell.cpp:3485
SpellInfo const *const m_spellInfo
Definition Spell.h:523
bool CanAutoCast(Unit *target)
Definition Spell.cpp:7023
void StopMoving()
Definition Unit.cpp:16702
bool IsPetInCombat() const
Definition Unit.h:896
void SetInFront(WorldObject const *target)
Definition Unit.cpp:20575
bool IsInCombat() const
Definition Unit.h:893
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:141

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(), 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(), sSpellMgr, Unit::StopMoving(), Unit::ToPet(), Object::ToPlayer(), ObjectGuid::ToString(), TRIGGERED_NONE, UNIT_STATE_CASTING, UpdateAllies(), and urand().

◆ UpdateAllies()

void PetAI::UpdateAllies ( )
private
354{
355 Unit* owner = me->GetCharmerOrOwner();
356 Group* group = nullptr;
357
358 m_updateAlliesTimer = 10 * IN_MILLISECONDS; //update friendly targets every 10 seconds, lesser checks increase performance
359
360 if (!owner)
361 return;
362 else if (owner->IsPlayer())
363 group = owner->ToPlayer()->GetGroup();
364
365 //only pet and owner/not in group->ok
366 if (m_AllySet.size() == 2 && !group)
367 return;
368 //owner is in group; group members filled in already (no raid -> subgroupcount = whole count)
369 if (group && !group->isRaidGroup() && m_AllySet.size() == (group->GetMembersCount() + 2))
370 return;
371
372 m_AllySet.clear();
373 m_AllySet.insert(me->GetGUID());
374 if (group) //add group
375 {
376 for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
377 {
378 Player* Target = itr->GetSource();
379 if (!Target || !Target->IsInMap(owner) || !group->SameSubGroup(owner->ToPlayer(), Target))
380 continue;
381
382 if (Target->GetGUID() == owner->GetGUID())
383 continue;
384
385 m_AllySet.insert(Target->GetGUID());
386 }
387 }
388 else //remove group
389 m_AllySet.insert(owner->GetGUID());
390}
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:2361
bool isRaidGroup() const
Definition Group.cpp:2269
Group * GetGroup()
Definition Player.h:2476
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:1296

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: