Fix pet/guardian and other types of minion pet attack on targets with Crowd Controls.

This commit is contained in:
Giuseppe Montesanto
2012-02-04 14:59:17 +01:00
parent 1ca8c63e4c
commit 14bc551862
6 changed files with 42 additions and 21 deletions
+6
View File
@@ -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;
+10 -19
View File
@@ -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;
}
-2
View File
@@ -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
+18
View File
@@ -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()))
+2
View File
@@ -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