Fix pet/guardian and other types of minion pet attack on targets with Crowd Controls.
This commit is contained in:
@@ -158,6 +158,12 @@ void CasterAI::UpdateAI(const uint32 diff)
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->getVictim()->HasBreakableByDamageCrowdControlAura())
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ PetAI::PetAI(Creature* c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK)
|
||||
{
|
||||
m_AllySet.clear();
|
||||
UpdateAllies();
|
||||
targetHasCC = false;
|
||||
}
|
||||
|
||||
void PetAI::EnterEvadeMode()
|
||||
@@ -55,9 +54,6 @@ bool PetAI::_needToStop()
|
||||
if (me->isCharmed() && me->getVictim() == me->GetCharmer())
|
||||
return true;
|
||||
|
||||
if (_CheckTargetCC(me->getVictim()) && !targetHasCC)
|
||||
return true;
|
||||
|
||||
return !me->IsValidAttackTarget(me->getVictim());
|
||||
}
|
||||
|
||||
@@ -95,13 +91,19 @@ void PetAI::UpdateAI(const uint32 diff)
|
||||
// me->getVictim() can't be used for check in case stop fighting, me->getVictim() clear at Unit death etc.
|
||||
if (me->getVictim())
|
||||
{
|
||||
// is only necessary to stop casting, the pet must not exit combat
|
||||
if (me->getVictim()->HasBreakableByDamageCrowdControlAura())
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_needToStop())
|
||||
{
|
||||
sLog->outStaticDebug("Pet AI stopped attacking [guid=%u]", me->GetGUIDLow());
|
||||
_stopAttack();
|
||||
return;
|
||||
}
|
||||
targetHasCC = _CheckTargetCC(me->getVictim());
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
@@ -293,8 +295,6 @@ void PetAI::AttackStart(Unit* target)
|
||||
if (!CanAttack(target))
|
||||
return;
|
||||
|
||||
targetHasCC = _CheckTargetCC(target);
|
||||
|
||||
if (Unit* owner = me->GetOwner())
|
||||
owner->SetInCombatWith(target);
|
||||
|
||||
@@ -310,22 +310,21 @@ Unit* PetAI::SelectNextTarget()
|
||||
return NULL;
|
||||
|
||||
Unit* target = me->getAttackerForHelper();
|
||||
targetHasCC = false;
|
||||
|
||||
// Check pet's attackers first to prevent dragging mobs back to owner
|
||||
if (target && !_CheckTargetCC(target))
|
||||
if (target && !target->HasBreakableByDamageCrowdControlAura())
|
||||
return target;
|
||||
|
||||
if (me->GetCharmerOrOwner())
|
||||
{
|
||||
// Check owner's attackers if pet didn't have any
|
||||
target = me->GetCharmerOrOwner()->getAttackerForHelper();
|
||||
if (target && !_CheckTargetCC(target))
|
||||
if (target && !target->HasBreakableByDamageCrowdControlAura())
|
||||
return target;
|
||||
|
||||
// 3.0.2 - Pets now start attacking their owners target in defensive mode as soon as the hunter does
|
||||
target = me->GetCharmerOrOwner()->getVictim();
|
||||
if (target && !_CheckTargetCC(target))
|
||||
if (target && !target->HasBreakableByDamageCrowdControlAura())
|
||||
return target;
|
||||
}
|
||||
|
||||
@@ -467,11 +466,3 @@ bool PetAI::CanAttack(Unit* target)
|
||||
// default, though we shouldn't ever get here
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PetAI::_CheckTargetCC(Unit* target)
|
||||
{
|
||||
if (me->GetCharmerOrOwnerGUID() && target->HasNegativeAuraWithAttribute(SPELL_ATTR0_BREAKABLE_BY_DAMAGE, me->GetCharmerOrOwnerGUID()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ class PetAI : public CreatureAI
|
||||
|
||||
TimeTracker i_tracker;
|
||||
bool inCombat;
|
||||
bool targetHasCC;
|
||||
std::set<uint64> m_AllySet;
|
||||
uint32 m_updateAlliesTimer;
|
||||
|
||||
@@ -58,7 +57,6 @@ class PetAI : public CreatureAI
|
||||
void HandleReturnMovement();
|
||||
void DoAttack(Unit* target, bool chase);
|
||||
bool CanAttack(Unit* target);
|
||||
bool _CheckTargetCC(Unit* target);
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -516,6 +516,24 @@ bool Unit::HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Unit::HasBreakableByDamageAuraType(AuraType type) const
|
||||
{
|
||||
AuraEffectList const& auras = GetAuraEffectsByType(type);
|
||||
for (AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
|
||||
if ((*itr)->GetSpellInfo()->Attributes & SPELL_ATTR0_BREAKABLE_BY_DAMAGE || (*itr)->GetSpellInfo()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_TAKE_DAMAGE)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Unit::HasBreakableByDamageCrowdControlAura() const
|
||||
{
|
||||
return ( HasBreakableByDamageAuraType(SPELL_AURA_MOD_CONFUSE)
|
||||
|| HasBreakableByDamageAuraType(SPELL_AURA_MOD_FEAR)
|
||||
|| HasBreakableByDamageAuraType(SPELL_AURA_MOD_STUN)
|
||||
|| HasBreakableByDamageAuraType(SPELL_AURA_MOD_ROOT)
|
||||
|| HasBreakableByDamageAuraType(SPELL_AURA_TRANSFORM));
|
||||
}
|
||||
|
||||
void Unit::DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb)
|
||||
{
|
||||
if (!victim || !victim->isAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()))
|
||||
|
||||
@@ -1536,6 +1536,8 @@ class Unit : public WorldObject
|
||||
|
||||
bool HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint32 familyFlags) const;
|
||||
bool virtual HasSpell(uint32 /*spellID*/) const { return false; }
|
||||
bool HasBreakableByDamageAuraType(AuraType type) const;
|
||||
bool HasBreakableByDamageCrowdControlAura() const;
|
||||
|
||||
bool HasStealthAura() const { return HasAuraType(SPELL_AURA_MOD_STEALTH); }
|
||||
bool HasInvisibilityAura() const { return HasAuraType(SPELL_AURA_MOD_INVISIBILITY); }
|
||||
|
||||
@@ -1738,6 +1738,12 @@ public:
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me->getVictim()->HasBreakableByDamageCrowdControlAura())
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SpellTimer <= diff)
|
||||
{
|
||||
if (IsViper) //Viper
|
||||
|
||||
Reference in New Issue
Block a user