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
 
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)
 
 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 EnterEvadeMode (EvadeReason why=EVADE_REASON_OTHER)
 
virtual void JustEngagedWith (Unit *)
 Called for reaction when initially engaged.
 
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 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
 
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 ==================
 
virtual void PassengerBoarded (Unit *, int8, bool)
 == Fields =======================================
 
virtual bool BeforeSpellClick (Unit *)
 
virtual void OnSpellClick (Unit *, bool &)
 
virtual bool CanSeeAlways (WorldObject const *)
 
virtual bool CanBeSeen (Player const *)
 
virtual bool CanAlwaysBeDetectable (WorldObject const *)
 
virtual 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 *)
 
- 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
 
virtual void InitializeAI ()
 
virtual void Reset ()
 
virtual void OnCharmed (bool apply)=0
 
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)
 
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 (NOTE: Creature engage logic should NOT be here, but in JustEngagedWith, which happens once threat is established!)
 
virtual void JustExitedCombat ()
 Called when the unit leaves combat.
 
virtual void DamageDealt (Unit *, uint32 &, DamageEffectType)
 
virtual void DamageTaken (Unit *, uint32 &, DamageEffectType, SpellSchoolMask)
 
virtual void HealReceived (Unit *, uint32 &)
 
virtual void HealDone (Unit *, uint32 &)
 
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)
 
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)
 
SpellCastResult DoCastMaxThreat (uint32 spellId, uint32 threatTablePosition=0, float dist=0.0f, bool playerOnly=true, bool triggered=false)
 Cast spell on the max threat target, which may not always 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)
 
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
 
CreatureBoundary const * _boundary
 
bool _negateBoundary
 
- Protected Attributes inherited from UnitAI
Unit *const me
 

Detailed Description

Constructor & Destructor Documentation

◆ PetAI()

PetAI::PetAI ( Creature c)
explicit
44{
46}
#define TIME_INTERVAL_LOOK
Definition: CreatureAI.h:35
void UpdateAllies()
Definition: PetAI.cpp:352
TimeTracker i_tracker
Definition: PetAI.h:82
Definition: CreatureAI.h:70

References UpdateAllies().

Member Function Documentation

◆ _canMeleeAttack()

bool PetAI::_canMeleeAttack ( )
private
100{
101 combatRange = 0.f;
102 switch (me->GetEntry())
103 {
104 case ENTRY_IMP:
107 {
108 for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
109 {
110 uint32 spellID = me->GetPetAutoSpellOnPos(i);
111 switch (spellID)
112 {
124 {
125 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
126 int32 mana = me->GetPower(POWER_MANA);
127
128 if (mana >= spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask()))
129 {
130 combatRange = spellInfo->GetMaxRange();
131 return true;
132 }
133 }
134 default:
135 break;
136 }
137 }
138 return false;
139 }
140 default:
141 break;
142 }
143
144 return true;
145}
std::int32_t int32
Definition: Define.h:104
std::uint8_t uint8
Definition: Define.h:110
std::uint32_t uint32
Definition: Define.h:108
@ 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
#define sSpellMgr
Definition: SpellMgr.h:818
@ POWER_MANA
Definition: SharedDefines.h:241
float combatRange
Definition: PetAI.h:85
Creature *const me
Definition: CreatureAI.h:72
virtual uint8 GetPetAutoSpellSize() const
Definition: Creature.h:312
virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const
Definition: Creature.h:313
uint32 GetEntry() const
Definition: Object.h:109
uint32 GetPower(Powers power) const
Definition: Unit.h:1461
Definition: SpellInfo.h:314
SpellSchoolMask GetSchoolMask() const
Definition: SpellInfo.cpp:1972
float GetMaxRange(bool positive=false, Unit *caster=nullptr, Spell *spell=nullptr) const
Definition: SpellInfo.cpp:2306
int32 CalcPowerCost(Unit const *caster, SpellSchoolMask schoolMask, Spell *spell=nullptr) const
Definition: SpellInfo.cpp:2384

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
91{
92 // Xinef: Imps cannot attack with melee
93 if (!_canMeleeAttack())
94 return;
95
97}
bool _canMeleeAttack()
Definition: PetAI.cpp:99
void DoMeleeAttackIfReady()
Definition: UnitAI.cpp:40

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

Referenced by UpdateAI().

◆ _isVisible()

bool PetAI::_isVisible ( Unit ) const
private

◆ _needToStop()

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

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
72{
73 if (!me->IsAlive())
74 {
75 LOG_DEBUG("entities.unit.ai", "Creature stoped attacking cuz his dead [{}]", me->GetGUID().ToString());
78 me->CombatStop();
80 return;
81 }
82
83 me->AttackStop();
88}
#define LOG_DEBUG(filterType__,...)
Definition: Log.h:171
void ClearCharmInfoFlags()
Definition: PetAI.cpp:766
void HandleReturnMovement()
Definition: PetAI.cpp:524
void deleteReferences(bool removeFromMap=false)
Definition: HostileRefMgr.cpp:125
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:106
std::string ToString() const
Definition: ObjectGuid.cpp:47
void SetIsCommandAttack(bool val)
Definition: Unit.cpp:20497
void CombatStop(bool includingCast=false)
Definition: Unit.cpp:10401
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true, bool bySelf=false)
Definition: Unit.cpp:4069
MotionMaster * GetMotionMaster()
Definition: Unit.h:2262
bool IsAlive() const
Definition: Unit.h:1808
CharmInfo * GetCharmInfo()
Definition: Unit.h:1883
HostileRefMgr & getHostileRefMgr()
Definition: Unit.h:2149
bool AttackStop()
Definition: Unit.cpp:10368
void MoveIdle()
Definition: MotionMaster.cpp:231
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.

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

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

◆ AttackStart()

void PetAI::AttackStart ( Unit target)
overridevirtual

Reimplemented from UnitAI.

417{
418 // Overrides Unit::AttackStart to correctly evaluate Pet states
419
420 // Check all pet states to decide if we can attack this target
421 if (!CanAttack(target))
422 return;
423
424 // Only chase if not commanded to stay or if stay but commanded to attack
426}
@ COMMAND_STAY
Definition: Unit.h:1030
void DoAttack(Unit *target, bool chase)
Definition: PetAI.cpp:590
bool CanAttack(Unit *target, SpellInfo const *spellInfo=nullptr)
Definition: PetAI.cpp:665
bool IsCommandAttack()
Definition: Unit.cpp:20502
bool HasCommandState(CommandStates state) const
Definition: Unit.h:1104

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

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

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
591{
592 // Handles attack with or without chase and also resets flags
593 // for next update / creature kill
594
595 if (me->Attack(target, true))
596 {
597 // xinef: properly fix fake combat after pet is sent to attack
598 if (Unit* owner = me->GetOwner())
599 owner->SetUnitFlag(UNIT_FLAG_PET_IN_COMBAT);
600
602
603 // Play sound to let the player know the pet is attacking something it picked on its own
606
607 if (chase)
608 {
609 bool oldCmdAttack = me->GetCharmInfo()->IsCommandAttack(); // This needs to be reset after other flags are cleared
611 me->GetCharmInfo()->SetIsCommandAttack(oldCmdAttack); // For passive pets commanded to attack so they will use spells
612
613 if (_canMeleeAttack())
614 {
615 float angle = combatRange == 0.f && target->GetTypeId() != TYPEID_PLAYER && !target->IsPet() ? float(M_PI) : 0.f;
616 float tolerance = combatRange == 0.f ? float(M_PI_4) : float(M_PI * 2);
617 me->GetMotionMaster()->MoveChase(target, ChaseRange(0.f, combatRange), ChaseAngle(angle, tolerance));
618 }
619 }
620 else // (Stay && ((Aggressive || Defensive) && In Melee Range)))
621 {
623
624 me->GetCharmInfo()->SetIsAtStay(true);
627 }
628 }
629}
@ TYPEID_PLAYER
Definition: ObjectGuid.h:38
@ REACT_AGGRESSIVE
Definition: Unit.h:1025
@ UNIT_FLAG_PET_IN_COMBAT
Definition: Unit.h:459
@ MOTION_SLOT_ACTIVE
Definition: MotionMaster.h:62
TypeID GetTypeId() const
Definition: Object.h:121
Unit * GetOwner() const
Definition: Unit.cpp:10560
bool IsPet() const
Definition: Unit.h:1413
bool Attack(Unit *victim, bool meleeAttack)
Definition: Unit.cpp:10245
void SendPetAIReaction(ObjectGuid guid)
Definition: Unit.cpp:16805
void SetUnitFlag(UnitFlags flags)
Definition: Unit.h:1481
Definition: MotionMaster.h:82
Definition: MotionMaster.h:95
void MoveChase(Unit *target, std::optional< ChaseRange > dist={}, std::optional< ChaseAngle > angle={})
Definition: MotionMaster.cpp:299
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(), Object::GetTypeId(), Creature::HasReactState(), CharmInfo::IsCommandAttack(), Unit::IsPet(), CreatureAI::me, MOTION_SLOT_ACTIVE, MotionMaster::MoveChase(), MotionMaster::MoveIdle(), MotionMaster::MovementExpiredOnSlot(), REACT_AGGRESSIVE, Unit::SendPetAIReaction(), CharmInfo::SetIsAtStay(), CharmInfo::SetIsCommandAttack(), Unit::SetUnitFlag(), TYPEID_PLAYER, 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
525{
526 // Handles moving the pet back to stay or owner
527
528 // Prevent activating movement when under control of spells
529 // such as "Eyes of the Beast"
530 if (me->isPossessed())
531 return;
532
534 {
535 if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning())
536 {
538 {
539 // Return to previous position where stay was clicked
541 {
542 float x, y, z;
543 me->GetCharmInfo()->GetStayPosition(x, y, z);
547 me->GetMotionMaster()->MovePoint(me->GetGUID().GetCounter(), x, y, z);
548 }
549 }
550 }
551 }
552 else // COMMAND_FOLLOW
553 {
555 {
557 {
562 }
563 }
564 }
565
568
569 // xinef: remember that npcs summoned by npcs can also be pets
572}
#define PET_FOLLOW_DIST
Definition: PetDefines.h:193
@ MOTION_SLOT_CONTROLLED
Definition: MotionMaster.h:63
@ NULL_MOTION_TYPE
Definition: MotionMaster.h:56
void ClearAllThreat()
Definition: ThreatMgr.cpp:418
LowType GetCounter() const
Definition: ObjectGuid.h:147
bool IsFollowing()
Definition: Unit.cpp:20574
void SetForcedSpell(uint32 id)
Definition: Unit.h:1144
bool IsAtStay()
Definition: Unit.cpp:20564
void GetStayPosition(float &x, float &y, float &z)
Definition: Unit.cpp:20540
void SetForcedTargetGUID(ObjectGuid guid=ObjectGuid::Empty)
Definition: Unit.h:1146
bool HasStayPosition()
Definition: Unit.cpp:20554
void ClearInPetCombat()
Definition: Unit.cpp:13749
bool isPossessed() const
Definition: Unit.h:1872
virtual float GetFollowAngle() const
Definition: Unit.h:2392
ThreatMgr & GetThreatMgr()
Definition: Unit.h:2145
MovementGeneratorType GetMotionSlotType(int slot) const
Definition: MotionMaster.cpp:825
void MoveFollow(Unit *target, float dist, float angle, MovementSlot slot=MOTION_SLOT_ACTIVE)
Definition: MotionMaster.cpp:367
void MovePoint(uint32 id, const Position &pos, bool generatePath=true, bool forceDestination=true)
Definition: MotionMaster.h:210

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.

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

632{
633 // Receives notification when pet reaches stay or follow owner
634 switch (moveType)
635 {
637 {
638 // Pet is returning to where stay was clicked. data should be
639 // pet's GUIDLow since we set that as the waypoint ID
640 if (data == me->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning())
641 {
643 me->GetCharmInfo()->SetIsAtStay(true);
646 }
647 break;
648 }
650 {
651 // If data is owner's GUIDLow then we've reached follow point,
652 // otherwise we're probably chasing a creature
654 {
657 }
658 break;
659 }
660 default:
661 break;
662 }
663}
@ 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.

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

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

◆ OwnerAttackedBy()

void PetAI::OwnerAttackedBy ( Unit attacker)
overridevirtual

Reimplemented from CreatureAI.

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

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

◆ Permissible()

int32 PetAI::Permissible ( Creature const *  creature)
static
32{
33 if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
34 {
35 if (reinterpret_cast<Guardian const*>(creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)
38 }
39
40 return PERMIT_BASE_NO;
41}
@ PERMIT_BASE_PROACTIVE
Definition: CreatureAI.h:236
@ PERMIT_BASE_NO
Definition: CreatureAI.h:233
@ PERMIT_BASE_REACTIVE
Definition: CreatureAI.h:235
@ UNIT_MASK_CONTROLABLE_GUARDIAN
Definition: Unit.h:683
Definition: TemporarySummon.h:95

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

◆ PetStopAttack()

void PetAI::PetStopAttack ( )
overridevirtual

Reimplemented from CreatureAI.

67{
69}
void _stopAttack(void)
Definition: PetAI.cpp:71

References _stopAttack().

◆ ReceiveEmote()

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

Reimplemented from CreatureAI.

743{
744 if (me->GetOwnerGUID() && me->GetOwnerGUID() == player->GetGUID())
745 switch (emote)
746 {
747 case TEXT_EMOTE_COWER:
748 if (me->IsPet() && me->ToPet()->IsPetGhoul())
749 me->HandleEmoteCommand(/*EMOTE_ONESHOT_ROAR*/EMOTE_ONESHOT_OMNICAST_GHOUL);
750 break;
751 case TEXT_EMOTE_ANGRY:
752 if (me->IsPet() && me->ToPet()->IsPetGhoul())
753 me->HandleEmoteCommand(/*EMOTE_ONESHOT_COWER*/EMOTE_STATE_STUN);
754 break;
755 case TEXT_EMOTE_GLARE:
756 if (me->IsPet() && me->ToPet()->IsPetGhoul())
758 break;
760 if (me->IsPet() && me->ToPet()->IsPetGhoul())
762 break;
763 }
764}
@ EMOTE_ONESHOT_OMNICAST_GHOUL
Definition: SharedDefines.h:2000
@ EMOTE_STATE_STUN
Definition: SharedDefines.h:1912
@ TEXT_EMOTE_ANGRY
Definition: SharedDefines.h:1610
@ TEXT_EMOTE_SOOTHE
Definition: SharedDefines.h:1741
@ TEXT_EMOTE_COWER
Definition: SharedDefines.h:1635
@ TEXT_EMOTE_GLARE
Definition: SharedDefines.h:1653
bool IsPetGhoul() const
Definition: TemporarySummon.h:84
Pet * ToPet()
Definition: Unit.h:2398
void HandleEmoteCommand(uint32 emoteId)
Definition: Unit.cpp:1970

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
470{
471 // Provides next target selection after current target death.
472 // This function should only be called internally by the AI
473 // Targets are not evaluated here for being valid targets, that is done in _CanAttack()
474 // The parameter: allowAutoSelect lets us disable aggressive pet auto targeting for certain situations
475
476 // Passive pets don't do next target selection
478 return nullptr;
479
480 // Check pet attackers first so we don't drag a bunch of targets to the owner
481 if (Unit* myAttacker = me->getAttackerForHelper())
482 if (!myAttacker->HasBreakableByDamageCrowdControlAura() && me->CanCreatureAttack(myAttacker))
483 return myAttacker;
484
485 // Check pet's attackers first to prevent dragging mobs back to owner
487 {
489 if (!tauntAuras.empty())
490 for (Unit::AuraEffectList::const_reverse_iterator itr = tauntAuras.rbegin(); itr != tauntAuras.rend(); ++itr)
491 if (Unit* caster = (*itr)->GetCaster())
492 if (me->CanCreatureAttack(caster) && !caster->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, me->GetGUID()))
493 return caster;
494 }
495
496 // Not sure why we wouldn't have an owner but just in case...
497 Unit* owner = me->GetCharmerOrOwner();
498 if (!owner)
499 return nullptr;
500
501 // Check owner attackers
502 if (Unit* ownerAttacker = owner->getAttackerForHelper())
503 if (!ownerAttacker->HasBreakableByDamageCrowdControlAura() && me->CanCreatureAttack(ownerAttacker))
504 return ownerAttacker;
505
506 // Check owner victim
507 // 3.0.2 - Pets now start attacking their owners victim in defensive mode as soon as the hunter does
508 if (Unit* ownerVictim = owner->GetVictim())
509 if (me->CanCreatureAttack(ownerVictim))
510 return ownerVictim;
511
512 // Neither pet or owner had a target and aggressive pets can pick any target
513 // To prevent aggressive pets from chain selecting targets and running off, we
514 // only select a random target if certain conditions are met.
515 if (allowAutoSelect)
518 return nearTarget;
519
520 // Default - no valid targets
521 return nullptr;
522}
#define MAX_AGGRO_RADIUS
Definition: Unit.h:162
@ SPELL_AURA_IGNORED
Definition: SpellAuraDefines.h:284
Unit * SelectNearestTargetInAttackDistance(float dist) const
Definition: Creature.cpp:2330
Creature * ToCreature()
Definition: Object.h:197
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition: Unit.h:1967
Unit * getAttackerForHelper() const
Definition: Unit.h:1366
bool HasAuraType(AuraType auraType) const
Definition: Unit.cpp:5617
std::list< AuraEffect * > AuraEffectList
Definition: Unit.h:1306

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.

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

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  diff)
overridevirtual

Implements UnitAI.

148{
149 if (!me->IsAlive() || !me->GetCharmInfo())
150 return;
151
152 Unit* owner = me->GetCharmerOrOwner();
153
154 if (m_updateAlliesTimer <= diff)
155 // UpdateAllies self set update timer
156 UpdateAllies();
157 else
158 m_updateAlliesTimer -= diff;
159
160 if (me->GetVictim() && me->GetVictim()->IsAlive())
161 {
162 // is only necessary to stop casting, the pet must not exit combat
164 {
166 return;
167 }
168
169 if (_needToStop())
170 {
171 LOG_DEBUG("entities.unit.ai", "Pet AI stopped attacking [{}]", me->GetGUID().ToString());
172 _stopAttack();
173 return;
174 }
175
176 // Check before attacking to prevent pets from leaving stay position
178 {
181 }
182 else
184 }
185 else if (!me->GetCharmInfo() || (!me->GetCharmInfo()->GetForcedSpell() && !(me->IsPet() && me->ToPet()->HasTempSpell()) && !me->HasUnitState(UNIT_STATE_CASTING)))
186 {
188 {
189 // Every update we need to check targets only in certain cases
190 // Aggressive - Allow auto select if owner or pet don't have a target
191 // Stay - Only pick from pet or owner targets / attackers so targets won't run by
192 // while chasing our owner. Don't do auto select.
193 // All other cases (ie: defensive) - Targets are assigned by AttackedBy(), OwnerAttackedBy(), OwnerAttacked(), etc.
195
196 if (nextTarget)
197 AttackStart(nextTarget);
198 else
200 }
201 else
203 }
204
205 // xinef: charm info must be always available
206 if (!me->GetCharmInfo())
207 return;
208
209 // Autocast (casted only in combat or persistent spells in any state)
211 {
212 if (owner && owner->GetTypeId() == TYPEID_PLAYER && me->GetCharmInfo()->GetForcedSpell() && me->GetCharmInfo()->GetForcedTarget())
213 {
215
216 // xinef: if spell was casted properly and we are in passive mode, handle return
218 {
220 {
221 me->GetMotionMaster()->Clear(false);
222 me->StopMoving();
223 }
224 else
225 _stopAttack();
226 }
227 return;
228 }
229
230 // xinef: dont allow ghouls to cast spells below 75 energy
231 if (me->IsPet() && me->ToPet()->IsPetGhoul() && me->GetPower(POWER_ENERGY) < 75)
232 return;
233
234 typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
235 TargetSpellList targetSpellStore;
236
237 for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
238 {
239 uint32 spellID = me->GetPetAutoSpellOnPos(i);
240 if (!spellID)
241 continue;
242
243 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
244 if (!spellInfo)
245 continue;
246
248 continue;
249
250 // check spell cooldown, this should be checked in CheckCast...
251 if (me->HasSpellCooldown(spellInfo->Id))
252 continue;
253
254 if (spellInfo->IsPositive())
255 {
256 if (spellInfo->CanBeUsedInCombat())
257 {
258 // Check if we're in combat or commanded to attack (exlude auras with infinity duration)
259 if (!me->IsInCombat() && spellInfo->GetMaxDuration() != -1 && !me->IsPetInCombat())
260 {
261 continue;
262 }
263 }
264
265 Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE);
266 spell->LoadScripts(); // xinef: load for CanAutoCast (calling CheckPetCast)
267 bool spellUsed = false;
268
269 // Some spells can target enemy or friendly (DK Ghoul's Leap)
270 // Check for enemy first (pet then owner)
271 Unit* target = me->getAttackerForHelper();
272 if (!target && owner)
273 target = owner->getAttackerForHelper();
274
275 if (target)
276 {
277 if (CanAttack(target) && spell->CanAutoCast(target))
278 {
279 targetSpellStore.push_back(std::make_pair(target, spell));
280 spellUsed = true;
281 }
282 }
283
284 // No enemy, check friendly
285 if (!spellUsed)
286 {
287 for (ObjectGuid const& guid : m_AllySet)
288 {
289 Unit* ally = ObjectAccessor::GetUnit(*me, guid);
290
291 //only buff targets that are in combat, unless the spell can only be cast while out of combat
292 if (!ally)
293 continue;
294
295 if (spell->CanAutoCast(ally))
296 {
297 targetSpellStore.push_back(std::make_pair(ally, spell));
298 spellUsed = true;
299 break;
300 }
301 }
302 }
303
304 // No valid targets at all
305 if (!spellUsed)
306 delete spell;
307 }
308 else if (me->GetVictim() && CanAttack(me->GetVictim(), spellInfo) && spellInfo->CanBeUsedInCombat())
309 {
310 Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE);
311 if (spell->CanAutoCast(me->GetVictim()))
312 targetSpellStore.push_back(std::make_pair(me->GetVictim(), spell));
313 else
314 delete spell;
315 }
316 }
317
318 //found units to cast on to
319 if (!targetSpellStore.empty())
320 {
321 uint32 index = urand(0, targetSpellStore.size() - 1);
322
323 Spell* spell = targetSpellStore[index].second;
324 Unit* target = targetSpellStore[index].first;
325
326 targetSpellStore.erase(targetSpellStore.begin() + index);
327
328 SpellCastTargets targets;
329 targets.SetUnitTarget(target);
330
331 if (!me->HasInArc(M_PI, target))
332 {
333 me->SetInFront(target);
334 if (target && target->GetTypeId() == TYPEID_PLAYER)
335 me->SendUpdateToPlayer(target->ToPlayer());
336
337 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
338 me->SendUpdateToPlayer(owner->ToPlayer());
339 }
340
341 me->AddSpellCooldown(spell->m_spellInfo->Id, 0, 0);
342
343 spell->prepare(&targets);
344 }
345
346 // deleted cached Spell objects
347 for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
348 delete itr->second;
349 }
350}
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:44
@ ACT_ENABLED
Definition: Unit.h:1015
@ TRIGGERED_NONE
Definition: SpellDefines.h:131
@ POWER_ENERGY
Definition: SharedDefines.h:244
Unit * GetUnit(WorldObject const &, ObjectGuid const guid)
Definition: ObjectAccessor.cpp:204
bool _needToStop(void)
Definition: PetAI.cpp:48
GuidSet m_AllySet
Definition: PetAI.h:83
void _doMeleeAttack()
Definition: PetAI.cpp:90
uint32 m_updateAlliesTimer
Definition: PetAI.h:84
bool HasSpellCooldown(uint32 spell_id) const override
Definition: Creature.cpp:2819
void AddSpellCooldown(uint32 spell_id, uint32, uint32 end_time, bool needSendToClient=false, bool forceSendToSpectator=false) override
Definition: Creature.cpp:2764
void SendUpdateToPlayer(Player *player)
Definition: Object.cpp:246
Definition: ObjectGuid.h:120
bool HasInArc(float arcangle, const Position *pos, float targetRadius=0.0f) const
Definition: Position.cpp:140
bool HasTempSpell() const
Definition: Pet.h:146
WorldSession * GetSession() const
Definition: Player.h:1948
bool HasGlobalCooldown(SpellInfo const *spellInfo) const
Definition: Unit.cpp:341
int32 GetForcedSpell()
Definition: Unit.h:1145
ObjectGuid GetForcedTarget()
Definition: Unit.h:1147
GlobalCooldownMgr & GetGlobalCooldownMgr()
Definition: Unit.h:1127
void StopMoving()
Definition: Unit.cpp:16824
bool IsPetInCombat() const
Definition: Unit.h:1691
void SetInFront(WorldObject const *target)
Definition: Unit.cpp:20776
bool IsInCombat() const
Definition: Unit.h:1688
void HandlePetActionHelper(Unit *pet, ObjectGuid guid1, uint32 spellid, uint16 flag, ObjectGuid guid2)
Definition: PetHandler.cpp:150
Definition: Spell.h:109
void SetUnitTarget(Unit *target)
Definition: Spell.cpp:233
Definition: Spell.h:284
void LoadScripts()
Definition: Spell.cpp:8456
SpellCastResult prepare(SpellCastTargets const *targets, AuraEffect const *triggeredByAura=nullptr)
Definition: Spell.cpp:3450
SpellInfo const *const m_spellInfo
Definition: Spell.h:520
bool CanAutoCast(Unit *target)
Definition: Spell.cpp:6976
uint32 Id
Definition: SpellInfo.h:318
int32 GetMaxDuration() const
Definition: SpellInfo.cpp:2328
bool CanBeUsedInCombat() const
Definition: SpellInfo.cpp:1216
bool IsPositive() const
Definition: SpellInfo.cpp:1221

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(), Object::GetTypeId(), 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(), 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, TYPEID_PLAYER, UNIT_STATE_CASTING, UpdateAllies(), and urand().

◆ UpdateAllies()

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

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

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