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

#include "PetAI.h"

Inheritance diagram for PetAI:
CreatureAI UnitAI npc_pet_pri_shadowfiend

Public Member Functions

 PetAI (Creature *c)
 
void UpdateAI (uint32) override
 Use to start attacking a target. Called just before JustEngagedWith() More...
 
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. More...
 
void Talk (uint8 id, Milliseconds delay)
 
 CreatureAI (Creature *creature)
 
 ~CreatureAI () override
 
void MoveCircleChecks ()
 
void MoveBackwardsChecks ()
 
void MoveInLineOfSight_Safe (Unit *who)
 == Reactions At ================================= More...
 
void TriggerAlert (Unit const *who) const
 
virtual bool CanRespawn ()
 
virtual void EnterEvadeMode (EvadeReason why=EVADE_REASON_OTHER)
 
virtual void JustEngagedWith (Unit *)
 Called for reaction when initially engaged. More...
 
virtual void JustDied (Unit *)
 
virtual void KilledUnit (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 SpellHit (Unit *, SpellInfo const *)
 
virtual void SpellHitTarget (Unit *, SpellInfo const *)
 
virtual void AttackedBy (Unit *)
 
virtual bool IsEscorted ()
 
virtual void JustRespawned ()
 
virtual void MovementInform (uint32, uint32)
 
virtual void PathEndReached (uint32)
 
void OnCharmed (bool apply) override
 Called when unit is charmed. More...
 
virtual void JustReachedHome ()
 
void DoZoneInCombat (Creature *creature=nullptr, float maxRangeToNearestTarget=250.0f)
 
virtual void ReceiveEmote (Player *, uint32)
 
virtual void OwnerAttackedBy (Unit *)
 
virtual void OwnerAttacked (Unit *)
 
virtual void CorpseRemoved (uint32 &)
 == Triggered Actions Requested ================== More...
 
virtual void PassengerBoarded (Unit *, int8, bool)
 == Fields ======================================= More...
 
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 void PetStopAttack ()
 
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 AttackStart (Unit *)
 
virtual void UpdateAI (uint32)=0
 Use to start attacking a target. Called just before JustEngagedWith() More...
 
virtual void InitializeAI ()
 
virtual void Reset ()
 
virtual void OnCharmed (bool apply)=0
 Called when unit is charmed. More...
 
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: More...
 
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. More...
 
virtual void JustExitedCombat ()
 Called when the unit leaves combat. More...
 
virtual void DamageDealt (Unit *, uint32 &, DamageEffectType)
 Called at any Damage to any victim (before damage apply) More...
 
virtual void DamageTaken (Unit *, uint32 &, DamageEffectType, SpellSchoolMask)
 Called at any Damage from any attacker (before damage apply) More...
 
virtual void HealReceived (Unit *, uint32 &)
 Called when the creature receives heal. More...
 
virtual void OnPowerUpdate (Powers, int32, int32, uint32)
 Called when the creature power updates. More...
 
virtual void HealDone (Unit *, uint32 &)
 Called when the unit heals. More...
 
virtual void OnCalculateMeleeDamageReceived (uint32 &, Unit *)
 Called during damage calculations. More...
 
virtual void OnCalculateSpellDamageReceived (int32 &, Unit *)
 
virtual void OnCalculatePeriodicTickReceived (uint32 &, Unit *)
 Called during calculation when receiving periodic healing or damage (DoT or HoT) More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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)
 
virtual void MoveInLineOfSight (Unit *)
 
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:36
void UpdateAllies()
Definition: PetAI.cpp:353
TimeTracker i_tracker
Definition: PetAI.h:82
Definition: CreatureAI.h:71

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}
#define sSpellMgr
Definition: SpellMgr.h:825
@ 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
std::int32_t int32
Definition: Define.h:103
std::uint8_t uint8
Definition: Define.h:109
std::uint32_t uint32
Definition: Define.h:107
float combatRange
Definition: PetAI.h:85
Creature *const me
Definition: CreatureAI.h:73
virtual uint8 GetPetAutoSpellSize() const
Definition: Creature.h:321
virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const
Definition: Creature.h:322
uint32 GetEntry() const
Definition: Object.h:112
uint32 GetPower(Powers power) const
Definition: Unit.h:804
Definition: SpellInfo.h:316
SpellSchoolMask GetSchoolMask() const
Definition: SpellInfo.cpp:1986
float GetMaxRange(bool positive=false, Unit *caster=nullptr, Spell *spell=nullptr) const
Definition: SpellInfo.cpp:2322
int32 CalcPowerCost(Unit const *caster, SpellSchoolMask schoolMask, Spell *spell=nullptr) const
Definition: SpellInfo.cpp:2400

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:2620
float GetVisibilityRange() const
Definition: Object.cpp:1645
float GetExactDist(float x, float y, float z) const
Definition: Position.h:178
Definition: Unit.h:630
bool IsCharmed() const
Definition: Unit.h:1214
Unit * GetCharmer() const
Definition: Unit.cpp:10553
Unit * GetCharmerOrOwner() const
Definition: Unit.h:1190
Unit * GetVictim() const
Definition: Unit.h:727

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:168
void ClearCharmInfoFlags()
Definition: PetAI.cpp:767
void HandleReturnMovement()
Definition: PetAI.cpp:525
void deleteReferences(bool removeFromMap=false)
Definition: HostileRefMgr.cpp:125
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:109
std::string ToString() const
Definition: ObjectGuid.cpp:47
void SetIsCommandAttack(bool val)
Definition: CharmInfo.cpp:310
void CombatStop(bool includingCast=false)
Definition: Unit.cpp:10381
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true, bool bySelf=false)
Definition: Unit.cpp:4094
MotionMaster * GetMotionMaster()
Definition: Unit.h:1605
bool IsAlive() const
Definition: Unit.h:1151
CharmInfo * GetCharmInfo()
Definition: Unit.h:1226
HostileRefMgr & getHostileRefMgr()
Definition: Unit.h:1492
bool AttackStop()
Force the unit to stop attacking. This will clear UNIT_STATE_MELEE_ATTACKING, Interrupt current spell...
Definition: Unit.cpp:10348
void MoveIdle()
Definition: MotionMaster.cpp:232
void Clear(bool reset=true)
Definition: MotionMaster.h:165

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.

784{
785 // Called when pet takes damage. This function helps keep pets from running off
786 // simply due to gaining aggro.
787
788 if (!attacker)
789 return;
790
791 // Passive pets don't do anything
793 return;
794
795 // Prevent pet from disengaging from current target
796 if (me->GetVictim() && me->GetVictim()->IsAlive())
797 return;
798
799 // Continue to evaluate and attack if necessary
800 AttackStart(attacker);
801}
@ REACT_PASSIVE
Definition: Unit.h:548
void AttackStart(Unit *target) override
Definition: PetAI.cpp:417
bool HasReactState(ReactStates state) const
Definition: Creature.h:99

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:591
bool CanAttack(Unit *target, SpellInfo const *spellInfo=nullptr)
Definition: PetAI.cpp:666
bool IsCommandAttack()
Definition: CharmInfo.cpp:315
bool HasCommandState(CommandStates state) const
Definition: CharmInfo.h:135

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

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

◆ CanAttack()

bool PetAI::CanAttack ( Unit target,
SpellInfo const *  spellInfo = nullptr 
)
private
667{
668 // Evaluates wether a pet can attack a specific target based on CommandState, ReactState and other flags
669 // IMPORTANT: The order in which things are checked is important, be careful if you add or remove checks
670
671 // Hmmm...
672 if (!target)
673 return false;
674
675 if (!target->IsAlive())
676 {
677 // xinef: if target is invalid, pet should evade automaticly
678 // Clear target to prevent getting stuck on dead targets
679 //me->AttackStop();
680 //me->InterruptNonMeleeSpells(false);
681 return false;
682 }
683
684 // xinef: check unit states of pet
686 return false;
687
688 // xinef: pets of mounted players have stunned flag only, check this also
690 return false;
691
692 // pussywizard: TEMP!
693 if (!me->GetCharmInfo())
694 {
695 LOG_INFO("misc", "PetAI::CanAttack (A1) - {}, {}", me->GetEntry(), me->GetOwnerGUID().ToString());
696 return false;
697 }
698
699 // Passive - passive pets can attack if told to
701 return me->GetCharmInfo()->IsCommandAttack();
702
703 // CC - mobs under crowd control can be attacked if owner commanded
704 if (target->HasBreakableByDamageCrowdControlAura() && (!spellInfo || !spellInfo->HasAttribute(SPELL_ATTR4_REACTIVE_DAMAGE_PROC)))
705 return me->GetCharmInfo()->IsCommandAttack();
706
707 // Returning - pets ignore attacks only if owner clicked follow
708 if (me->GetCharmInfo()->IsReturning())
709 return !me->GetCharmInfo()->IsCommandFollow();
710
711 // Stay - can attack if target is within range or commanded to
713 return (me->IsWithinMeleeRange(target) || me->GetCharmInfo()->IsCommandAttack());
714
715 // Pets attacking something (or chasing) should only switch targets if owner tells them to
716 if (me->GetVictim() && me->GetVictim() != target)
717 {
718 // Forced change target if it's taunt
719 if (spellInfo && spellInfo->HasAura(SPELL_AURA_MOD_TAUNT))
720 {
721 return true;
722 }
723
724 // Check if our owner selected this target and clicked "attack"
725 Unit* ownerTarget = nullptr;
726 if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
727 ownerTarget = owner->GetSelectedUnit();
728 else
729 ownerTarget = me->GetCharmerOrOwner()->GetVictim();
730
731 if (ownerTarget && me->GetCharmInfo()->IsCommandAttack())
732 return (target->GetGUID() == ownerTarget->GetGUID());
733 }
734
735 // Follow
737 return !me->GetCharmInfo()->IsReturning();
738
739 // default, though we shouldn't ever get here
740 return false;
741}
@ SPELL_AURA_MOD_TAUNT
Definition: SpellAuraDefines.h:74
@ COMMAND_FOLLOW
Definition: Unit.h:556
@ UNIT_STATE_LOST_CONTROL
Definition: UnitDefines.h:191
@ UNIT_FLAG_STUNNED
Definition: UnitDefines.h:247
@ SPELL_ATTR4_REACTIVE_DAMAGE_PROC
Definition: SharedDefines.h:544
#define LOG_INFO(filterType__,...)
Definition: Log.h:164
Player * ToPlayer()
Definition: Object.h:198
Definition: Player.h:1064
bool IsReturning()
Definition: CharmInfo.cpp:397
bool IsCommandFollow()
Definition: CharmInfo.cpp:325
bool HasBreakableByDamageCrowdControlAura(Unit *excludeCasterChannel=nullptr) const
Definition: Unit.cpp:774
bool HasUnitFlag(UnitFlags flags) const
Definition: Unit.h:825
bool IsWithinMeleeRange(Unit const *obj, float dist=0.f) const
Definition: Unit.cpp:665
bool HasUnitState(const uint32 f) const
Definition: Unit.h:739
ObjectGuid GetOwnerGUID() const
Definition: Unit.h:1157

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
768{
769 // Quick access to set all flags to FALSE
770
771 CharmInfo* ci = me->GetCharmInfo();
772
773 if (ci)
774 {
775 ci->SetIsAtStay(false);
776 ci->SetIsCommandAttack(false);
777 ci->SetIsCommandFollow(false);
778 ci->SetIsFollowing(false);
779 ci->SetIsReturning(false);
780 }
781}
Definition: CharmInfo.h:125
void SetIsCommandFollow(bool val)
Definition: CharmInfo.cpp:320
void SetIsAtStay(bool val)
Definition: CharmInfo.cpp:372
void SetIsFollowing(bool val)
Definition: CharmInfo.cpp:382
void SetIsReturning(bool val)
Definition: CharmInfo.cpp:392

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
592{
593 // Handles attack with or without chase and also resets flags
594 // for next update / creature kill
595
596 if (me->Attack(target, true))
597 {
598 // xinef: properly fix fake combat after pet is sent to attack
599 if (Unit* owner = me->GetOwner())
600 owner->SetUnitFlag(UNIT_FLAG_PET_IN_COMBAT);
601
603
604 // Play sound to let the player know the pet is attacking something it picked on its own
607
608 if (chase)
609 {
610 bool oldCmdAttack = me->GetCharmInfo()->IsCommandAttack(); // This needs to be reset after other flags are cleared
612 me->GetCharmInfo()->SetIsCommandAttack(oldCmdAttack); // For passive pets commanded to attack so they will use spells
613
614 if (_canMeleeAttack())
615 {
616 float angle = combatRange == 0.f && !target->IsPlayer() && !target->IsPet() ? float(M_PI) : 0.f;
617 float tolerance = combatRange == 0.f ? float(M_PI_4) : float(M_PI * 2);
618 me->GetMotionMaster()->MoveChase(target, ChaseRange(0.f, combatRange), ChaseAngle(angle, tolerance));
619 }
620 }
621 else // (Stay && ((Aggressive || Defensive) && In Melee Range)))
622 {
624
625 me->GetCharmInfo()->SetIsAtStay(true);
628 }
629 }
630}
@ REACT_AGGRESSIVE
Definition: Unit.h:550
@ UNIT_FLAG_PET_IN_COMBAT
Definition: UnitDefines.h:240
@ MOTION_SLOT_ACTIVE
Definition: MotionMaster.h:62
bool IsPlayer() const
Definition: Object.h:197
Unit * GetOwner() const
Definition: Unit.cpp:10545
bool IsPet() const
Definition: Unit.h:754
bool Attack(Unit *victim, bool meleeAttack)
Definition: Unit.cpp:10217
void SendPetAIReaction(ObjectGuid guid)
Definition: Unit.cpp:16570
void SetUnitFlag(UnitFlags flags)
UnitFlags available in UnitDefines.h.
Definition: Unit.h:826
Definition: MotionMaster.h:82
Definition: MotionMaster.h:95
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:192

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
526{
527 // Handles moving the pet back to stay or owner
528
529 // Prevent activating movement when under control of spells
530 // such as "Eyes of the Beast"
531 if (me->isPossessed())
532 return;
533
535 {
536 if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning())
537 {
539 {
540 // Return to previous position where stay was clicked
542 {
543 float x, y, z;
544 me->GetCharmInfo()->GetStayPosition(x, y, z);
548 me->GetMotionMaster()->MovePoint(me->GetGUID().GetCounter(), x, y, z);
549 }
550 }
551 }
552 }
553 else // COMMAND_FOLLOW
554 {
556 {
558 {
563 }
564 }
565 }
566
569
570 // xinef: remember that npcs summoned by npcs can also be pets
573}
#define PET_FOLLOW_DIST
Definition: PetDefines.h:198
@ MOTION_SLOT_CONTROLLED
Definition: MotionMaster.h:63
@ NULL_MOTION_TYPE
Definition: MotionMaster.h:56
void ClearAllThreat()
Definition: ThreatMgr.cpp:417
LowType GetCounter() const
Definition: ObjectGuid.h:145
bool IsFollowing()
Definition: CharmInfo.cpp:387
void SetForcedSpell(uint32 id)
Definition: CharmInfo.h:175
bool IsAtStay()
Definition: CharmInfo.cpp:377
void GetStayPosition(float &x, float &y, float &z)
Definition: CharmInfo.cpp:353
void SetForcedTargetGUID(ObjectGuid guid=ObjectGuid::Empty)
Definition: CharmInfo.h:177
bool HasStayPosition()
Definition: CharmInfo.cpp:367
void ClearInPetCombat()
Definition: Unit.cpp:13784
bool isPossessed() const
Definition: Unit.h:1215
virtual float GetFollowAngle() const
Definition: Unit.h:1735
ThreatMgr & GetThreatMgr()
Definition: Unit.h:1488
MovementGeneratorType GetMotionSlotType(int slot) const
Definition: MotionMaster.cpp:918
void MoveFollow(Unit *target, float dist, float angle, MovementSlot slot=MOTION_SLOT_ACTIVE, bool inheritWalkState=true)
The unit will follow this target. Doesn't work with UNIT_FLAG_DISABLE_MOVE.
Definition: MotionMaster.cpp:409
void MovePoint(uint32 id, const Position &pos, bool generatePath=true, bool forceDestination=true)
Definition: MotionMaster.h:211

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_FIELD_CHANNEL_OBJECT
Definition: UpdateFields.h:93
@ UNIT_STATE_CASTING
Definition: UnitDefines.h:164
Unit * SelectNextTarget(bool allowAutoSelect) const
Definition: PetAI.cpp:470
ObjectGuid GetGuidValue(uint16 index) const
Definition: Object.cpp:337

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.

633{
634 // Receives notification when pet reaches stay or follow owner
635 switch (moveType)
636 {
638 {
639 // Pet is returning to where stay was clicked. data should be
640 // pet's GUIDLow since we set that as the waypoint ID
641 if (data == me->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning())
642 {
644 me->GetCharmInfo()->SetIsAtStay(true);
647 }
648 break;
649 }
651 {
652 // If data is owner's GUIDLow then we've reached follow point,
653 // otherwise we're probably chasing a creature
655 {
658 }
659 break;
660 }
661 default:
662 break;
663 }
664}
@ POINT_MOTION_TYPE
Definition: MotionMaster.h:46
@ FOLLOW_MOTION_TYPE
Definition: MotionMaster.h:52

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}
@ UNIT_MASK_CONTROLABLE_GUARDIAN
Definition: UnitDefines.h:143
@ PERMIT_BASE_PROACTIVE
Definition: CreatureAI.h:243
@ PERMIT_BASE_NO
Definition: CreatureAI.h:240
@ PERMIT_BASE_REACTIVE
Definition: CreatureAI.h:242
Definition: TemporarySummon.h:95

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.

744{
745 if (me->GetOwnerGUID() && me->GetOwnerGUID() == player->GetGUID())
746 switch (emote)
747 {
748 case TEXT_EMOTE_COWER:
749 if (me->IsPet() && me->ToPet()->IsPetGhoul())
750 me->HandleEmoteCommand(/*EMOTE_ONESHOT_ROAR*/EMOTE_ONESHOT_OMNICAST_GHOUL);
751 break;
752 case TEXT_EMOTE_ANGRY:
753 if (me->IsPet() && me->ToPet()->IsPetGhoul())
754 me->HandleEmoteCommand(/*EMOTE_ONESHOT_COWER*/EMOTE_STATE_STUN);
755 break;
756 case TEXT_EMOTE_GLARE:
757 if (me->IsPet() && me->ToPet()->IsPetGhoul())
759 break;
761 if (me->IsPet() && me->ToPet()->IsPetGhoul())
763 break;
764 }
765}
@ 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:84
Pet * ToPet()
Definition: Unit.h:1741
void HandleEmoteCommand(uint32 emoteId)
Definition: Unit.cpp:1967

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
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
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)
519 return nearTarget;
520
521 // Default - no valid targets
522 return nullptr;
523}
@ 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:2401
Creature * ToCreature()
Definition: Object.h:202
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition: Unit.h:1310
Unit * getAttackerForHelper() const
Definition: Unit.h:706
bool HasAuraType(AuraType auraType) const
Definition: Unit.cpp:5659
std::list< AuraEffect * > AuraEffectList
Definition: Unit.h:646

References Creature::CanCreatureAttack(), Unit::getAttackerForHelper(), Unit::GetAuraEffectsByType(), Unit::GetCharmerOrOwner(), Unit::GetCharmInfo(), Object::GetGUID(), Unit::GetVictim(), Unit::HasAuraType(), Creature::HasReactState(), CharmInfo::IsAtStay(), CharmInfo::IsFollowing(), 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.

576{
577 // Xinef: taunt behavior code
578 if (spellInfo->HasAura(SPELL_AURA_MOD_TAUNT) && !me->HasReactState(REACT_PASSIVE))
579 {
582
583 if (CanAttack(caster, spellInfo))
584 {
585 // Only chase if not commanded to stay or if stay but commanded to attack
587 }
588 }
589}

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.push_back(std::make_pair(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.push_back(std::make_pair(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.push_back(std::make_pair(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}
@ TRIGGERED_NONE
Definition: SpellDefines.h:131
@ ACT_ENABLED
Definition: CharmInfo.h:62
@ POWER_ENERGY
Definition: SharedDefines.h:272
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:44
Unit * GetUnit(WorldObject const &, ObjectGuid const guid)
Definition: ObjectAccessor.cpp:202
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 HasSpellCooldown(uint32 spell_id) const override
Definition: Creature.cpp:2910
void AddSpellCooldown(uint32 spell_id, uint32, uint32 end_time, bool needSendToClient=false, bool forceSendToSpectator=false) override
Definition: Creature.cpp:2855
void SendUpdateToPlayer(Player *player)
Definition: Object.cpp:246
Definition: ObjectGuid.h:118
bool HasInArc(float arcangle, const Position *pos, float targetRadius=0.0f) const
Definition: Position.cpp:140
bool HasTempSpell() const
Definition: Pet.h:147
WorldSession * GetSession() const
Definition: Player.h:1975
bool HasGlobalCooldown(SpellInfo const *spellInfo) const
Definition: CharmInfo.cpp:404
int32 GetForcedSpell()
Definition: CharmInfo.h:176
ObjectGuid GetForcedTarget()
Definition: CharmInfo.h:178
GlobalCooldownMgr & GetGlobalCooldownMgr()
Definition: CharmInfo.h:158
void StopMoving()
Definition: Unit.cpp:16589
bool IsPetInCombat() const
Definition: Unit.h:1035
void SetInFront(WorldObject const *target)
Definition: Unit.cpp:20435
bool IsInCombat() const
Definition: Unit.h:1032
void HandlePetActionHelper(Unit *pet, ObjectGuid guid1, uint32 spellid, uint16 flag, ObjectGuid guid2)
Definition: PetHandler.cpp:151
Definition: Spell.h:109
void SetUnitTarget(Unit *target)
Definition: Spell.cpp:240
Definition: Spell.h:284
void LoadScripts()
Definition: Spell.cpp:8487
SpellCastResult prepare(SpellCastTargets const *targets, AuraEffect const *triggeredByAura=nullptr)
Definition: Spell.cpp:3468
SpellInfo const *const m_spellInfo
Definition: Spell.h:520
bool CanAutoCast(Unit *target)
Definition: Spell.cpp:6998
uint32 Id
Definition: SpellInfo.h:320
int32 GetMaxDuration() const
Definition: SpellInfo.cpp:2344
bool CanBeUsedInCombat() const
Definition: SpellInfo.cpp:1231
bool IsPositive() const
Definition: SpellInfo.cpp:1236

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
bool IsInMap(WorldObject const *obj) const
Definition: Object.cpp:1285
Group * GetGroup()
Definition: Player.h:2445
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:2363
bool isRaidGroup() const
Definition: Group.cpp:2271
Definition: GroupReference.h:27
GroupReference * next()
Definition: GroupReference.h:36

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, GroupReference::next(), 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().