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 *)
 
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)
 
- 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: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: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:116
float combatRange
Definition PetAI.h:85
Definition SpellInfo.h:316
SpellSchoolMask GetSchoolMask() const
Definition SpellInfo.cpp:1998
float GetMaxRange(bool positive=false, Unit *caster=nullptr, Spell *spell=nullptr) const
Definition SpellInfo.cpp:2335
int32 CalcPowerCost(Unit const *caster, SpellSchoolMask schoolMask, Spell *spell=nullptr) const
Definition SpellInfo.cpp:2413
uint32 GetPower(Powers power) const
Definition Unit.h:1058

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:2632
Definition Unit.h:620
bool IsCharmed() const
Definition Unit.h:1237
Unit * GetCharmer() const
Definition Unit.cpp:10694
Unit * GetCharmerOrOwner() const
Definition Unit.h:1213
Unit * GetVictim() const
Definition Unit.h:848
float GetVisibilityRange() const
Definition Object.cpp:1638
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 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:113
void ClearCharmInfoFlags()
Definition PetAI.cpp:788
void HandleReturnMovement()
Definition PetAI.cpp:546
void CombatStop(bool includingCast=false)
Definition Unit.cpp:10522
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true, bool bySelf=false)
Definition Unit.cpp:4176
MotionMaster * GetMotionMaster()
Definition Unit.h:1673
bool IsAlive() const
Definition Unit.h:1707
CharmInfo * GetCharmInfo()
Definition Unit.h:1208
HostileRefMgr & getHostileRefMgr()
Definition Unit.h:902
bool AttackStop()
Force the unit to stop attacking. This will clear UNIT_STATE_MELEE_ATTACKING, Interrupt current spell...
Definition Unit.cpp:10489
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.

805{
806 // Called when pet takes damage. This function helps keep pets from running off
807 // simply due to gaining aggro.
808
809 if (!attacker)
810 return;
811
812 // Passive pets don't do anything
814 return;
815
816 // Prevent pet from disengaging from current target
817 if (me->GetVictim() && me->GetVictim()->IsAlive())
818 return;
819
820 // Continue to evaluate and attack if necessary
821 AttackStart(attacker);
822}
@ REACT_PASSIVE
Definition Unit.h:549
bool HasReactState(ReactStates state) const
Definition Creature.h:97
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:556
void DoAttack(Unit *target, bool chase)
Definition PetAI.cpp:612
bool CanAttack(Unit *target, SpellInfo const *spellInfo=nullptr)
Definition PetAI.cpp:687
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
688{
689 // Evaluates wether a pet can attack a specific target based on CommandState, ReactState and other flags
690 // IMPORTANT: The order in which things are checked is important, be careful if you add or remove checks
691
692 // Hmmm...
693 if (!target)
694 return false;
695
696 if (!target->IsAlive())
697 {
698 // xinef: if target is invalid, pet should evade automaticly
699 // Clear target to prevent getting stuck on dead targets
700 //me->AttackStop();
701 //me->InterruptNonMeleeSpells(false);
702 return false;
703 }
704
705 // xinef: check unit states of pet
707 return false;
708
709 // xinef: pets of mounted players have stunned flag only, check this also
711 return false;
712
713 // pussywizard: TEMP!
714 if (!me->GetCharmInfo())
715 {
716 LOG_INFO("misc", "PetAI::CanAttack (A1) - {}, {}", me->GetEntry(), me->GetOwnerGUID().ToString());
717 return false;
718 }
719
720 // Passive - passive pets can attack if told to
722 return me->GetCharmInfo()->IsCommandAttack();
723
724 // CC - mobs under crowd control can be attacked if owner commanded
725 if (target->HasBreakableByDamageCrowdControlAura() && (!spellInfo || !spellInfo->HasAttribute(SPELL_ATTR4_REACTIVE_DAMAGE_PROC)))
726 return me->GetCharmInfo()->IsCommandAttack();
727
728 // Returning - pets ignore attacks only if owner clicked follow
729 if (me->GetCharmInfo()->IsReturning())
730 return !me->GetCharmInfo()->IsCommandFollow();
731
732 // Stay - can attack if target is within range or commanded to
734 return (me->IsWithinMeleeRange(target) || me->GetCharmInfo()->IsCommandAttack());
735
736 // Pets attacking something (or chasing) should only switch targets if owner tells them to
737 if (me->GetVictim() && me->GetVictim() != target)
738 {
739 // Forced change target if it's taunt
740 if (spellInfo && spellInfo->HasAura(SPELL_AURA_MOD_TAUNT))
741 {
742 return true;
743 }
744
745 // Check if our owner selected this target and clicked "attack"
746 Unit* ownerTarget = nullptr;
747 if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
748 ownerTarget = owner->GetSelectedUnit();
749 else
750 ownerTarget = me->GetCharmerOrOwner()->GetVictim();
751
752 if (ownerTarget && me->GetCharmInfo()->IsCommandAttack())
753 return (target->GetGUID() == ownerTarget->GetGUID());
754 }
755
756 // Follow
758 return !me->GetCharmInfo()->IsReturning();
759
760 // default, though we shouldn't ever get here
761 return false;
762}
#define LOG_INFO(filterType__,...)
Definition Log.h:166
@ 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:557
Player * ToPlayer()
Definition Object.h:202
Definition Player.h:1083
bool HasBreakableByDamageCrowdControlAura(Unit *excludeCasterChannel=nullptr) const
Definition Unit.cpp:801
bool HasUnitFlag(UnitFlags flags) const
Definition Unit.h:702
bool IsWithinMeleeRange(Unit const *obj, float dist=0.f) const
Definition Unit.cpp:665
bool HasUnitState(const uint32 f) const
Definition Unit.h:691
ObjectGuid GetOwnerGUID() const
Definition Unit.h:668
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
789{
790 // Quick access to set all flags to FALSE
791
792 CharmInfo* ci = me->GetCharmInfo();
793
794 if (ci)
795 {
796 ci->SetIsAtStay(false);
797 ci->SetIsCommandAttack(false);
798 ci->SetIsCommandFollow(false);
799 ci->SetIsFollowing(false);
800 ci->SetIsReturning(false);
801 }
802}
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 float angle = combatRange == 0.f && !target->IsPlayer() && !target->IsPet() ? float(M_PI) : 0.f;
638 float tolerance = combatRange == 0.f ? float(M_PI_4) : float(M_PI * 2);
639 me->GetMotionMaster()->MoveChase(target, ChaseRange(0.f, combatRange), ChaseAngle(angle, tolerance));
640 }
641 }
642 else // (Stay && ((Aggressive || Defensive) && In Melee Range)))
643 {
645
646 me->GetCharmInfo()->SetIsAtStay(true);
649 }
650 }
651}
@ MOTION_SLOT_ACTIVE
Definition MotionMaster.h:64
@ UNIT_FLAG_PET_IN_COMBAT
Definition UnitDefines.h:261
@ REACT_AGGRESSIVE
Definition Unit.h:551
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:201
Unit * GetOwner() const
Definition Unit.cpp:10686
bool IsPet() const
Definition Unit.h:747
bool Attack(Unit *victim, bool meleeAttack)
Definition Unit.cpp:10333
void SendPetAIReaction(ObjectGuid guid)
Definition Unit.cpp:16705
void SetUnitFlag(UnitFlags flags)
UnitFlags available in UnitDefines.h.
Definition Unit.h:703
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
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:65
@ NULL_MOTION_TYPE
Definition MotionMaster.h:58
#define PET_FOLLOW_DIST
Definition PetDefines.h:205
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:13936
bool isPossessed() const
Definition Unit.h:1238
virtual float GetFollowAngle() const
Definition Unit.h:1809
ThreatMgr & GetThreatMgr()
Definition Unit.h:898
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.

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

654{
655 // Receives notification when pet reaches stay or follow owner
656 switch (moveType)
657 {
659 {
660 // Pet is returning to where stay was clicked. data should be
661 // pet's GUIDLow since we set that as the waypoint ID
662 if (data == me->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning())
663 {
665 me->GetCharmInfo()->SetIsAtStay(true);
668 }
669 break;
670 }
672 {
673 // If data is owner's GUIDLow then we've reached follow point,
674 // otherwise we're probably chasing a creature
676 {
679 }
680 break;
681 }
682 default:
683 break;
684 }
685}
@ 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:247
@ PERMIT_BASE_NO
Definition CreatureAI.h:244
@ PERMIT_BASE_REACTIVE
Definition CreatureAI.h:246
@ UNIT_MASK_CONTROLLABLE_GUARDIAN
Definition UnitDefines.h:164
Definition TemporarySummon.h:96

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.

765{
766 if (me->GetOwnerGUID() && me->GetOwnerGUID() == player->GetGUID())
767 switch (emote)
768 {
769 case TEXT_EMOTE_COWER:
770 if (me->IsPet() && me->ToPet()->IsPetGhoul())
771 me->HandleEmoteCommand(/*EMOTE_ONESHOT_ROAR*/EMOTE_ONESHOT_OMNICAST_GHOUL);
772 break;
773 case TEXT_EMOTE_ANGRY:
774 if (me->IsPet() && me->ToPet()->IsPetGhoul())
775 me->HandleEmoteCommand(/*EMOTE_ONESHOT_COWER*/EMOTE_STATE_STUN);
776 break;
777 case TEXT_EMOTE_GLARE:
778 if (me->IsPet() && me->ToPet()->IsPetGhoul())
780 break;
782 if (me->IsPet() && me->ToPet()->IsPetGhoul())
784 break;
785 }
786}
@ 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:684
void HandleEmoteCommand(uint32 emoteId)
Definition Unit.cpp:2026

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_IGNORED, 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_IGNORED
Definition SpellAuraDefines.h:284
#define MAX_AGGRO_RADIUS
Definition Unit.h:44
Unit * SelectNearestTargetInAttackDistance(float dist) const
Select nearest hostile unit within the given attack distance (i.e. distance is ignored if > than ATTA...
Definition Creature.cpp:2410
Creature * ToCreature()
Definition Object.h:206
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1351
std::vector< AuraEffect * > AuraEffectList
Definition Unit.h:636
Unit * getAttackerForHelper() const
Definition Unit.cpp:754
bool IsPvP() const
Definition Unit.h:983
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.

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:272
@ SPELL_EFFECT_JUMP_DEST
Definition SharedDefines.h:820
@ TRIGGERED_NONE
Definition SpellDefines.h:133
bool HasSpellCooldown(uint32 spell_id) const override
Definition Creature.cpp:2930
void AddSpellCooldown(uint32 spell_id, uint32, uint32 end_time, bool needSendToClient=false, bool forceSendToSpectator=false) override
Definition Creature.cpp:2875
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:2016
Definition Spell.h:111
void SetUnitTarget(Unit *target)
Definition Spell.cpp:239
uint32 Id
Definition SpellInfo.h:320
int32 GetMaxDuration() const
Definition SpellInfo.cpp:2357
bool CanBeUsedInCombat() const
Definition SpellInfo.cpp:1232
bool HasEffect(SpellEffects effect) const
Definition SpellInfo.cpp:876
bool IsPositive() const
Definition SpellInfo.cpp:1237
Definition Spell.h:287
void LoadScripts()
Definition Spell.cpp:8545
SpellCastResult prepare(SpellCastTargets const *targets, AuraEffect const *triggeredByAura=nullptr)
Definition Spell.cpp:3488
SpellInfo const *const m_spellInfo
Definition Spell.h:523
bool CanAutoCast(Unit *target)
Definition Spell.cpp:7031
void StopMoving()
Definition Unit.cpp:16724
bool IsPetInCombat() const
Definition Unit.h:882
void SetInFront(WorldObject const *target)
Definition Unit.cpp:20362
bool IsInCombat() const
Definition Unit.h:879
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(), 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:2362
bool isRaidGroup() const
Definition Group.cpp:2270
Group * GetGroup()
Definition Player.h:2487
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:1278

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: