本文整理汇总了C++中UpdateAllies函数的典型用法代码示例。如果您正苦于以下问题:C++ UpdateAllies函数的具体用法?C++ UpdateAllies怎么用?C++ UpdateAllies使用的例子?那么, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了UpdateAllies函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: CreatureAI
PetAI::PetAI(Unit* unit) : CreatureAI(unit), i_tracker(TIME_INTERVAL_LOOK), inCombat(false)
{
m_AllySet.clear();
UpdateAllies();
}
示例2: UpdateAllies
void PetAI::UpdateAI(const uint32 diff)
{
if (!m_unit->isAlive())
return;
Creature* creature = (m_unit->GetTypeId() == TYPEID_UNIT) ? static_cast<Creature*>(m_unit) : nullptr;
Pet* pet = (creature && creature->IsPet()) ? static_cast<Pet*>(m_unit) : nullptr;
Unit* owner = m_unit->GetMaster();
if (!owner)
return;
Unit* victim = (pet && pet->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) ? nullptr : m_unit->getVictim();
if (m_updateAlliesTimer <= diff)
// UpdateAllies self set update timer
UpdateAllies();
else
m_updateAlliesTimer -= diff;
if (inCombat && !victim)
{
m_unit->AttackStop(true, true);
inCombat = false;
}
CharmInfo* charminfo = m_unit->GetCharmInfo();
MANGOS_ASSERT(charminfo);
if (charminfo->GetIsRetreating())
{
if (!owner->IsWithinDistInMap(m_unit, (PET_FOLLOW_DIST * 2)))
{
if (!m_unit->hasUnitState(UNIT_STAT_FOLLOW))
m_unit->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
return;
}
else
charminfo->SetIsRetreating();
}
else if (charminfo->GetSpellOpener() != 0) // have opener stored
{
uint32 minRange = charminfo->GetSpellOpenerMinRange();
if (!(victim = m_unit->getVictim())
|| (minRange != 0 && m_unit->IsWithinDistInMap(victim, minRange)))
charminfo->SetSpellOpener();
else if (m_unit->IsWithinDistInMap(victim, charminfo->GetSpellOpenerMaxRange())
&& m_unit->IsWithinLOSInMap(victim))
{
// stop moving
m_unit->clearUnitState(UNIT_STAT_MOVING);
// auto turn to target
m_unit->SetInFront(victim);
if (victim->GetTypeId() == TYPEID_PLAYER)
m_unit->SendCreateUpdateToPlayer((Player*)victim);
if (owner->GetTypeId() == TYPEID_PLAYER)
m_unit->SendCreateUpdateToPlayer((Player*)owner);
uint32 spell_id = charminfo->GetSpellOpener();
SpellEntry const* spellInfo = sSpellTemplate.LookupEntry<SpellEntry>(spell_id);
Spell* spell = new Spell(m_unit, spellInfo, false);
SpellCastResult result = spell->CheckPetCast(victim);
if (result == SPELL_CAST_OK)
spell->SpellStart(&(spell->m_targets));
else
delete spell;
charminfo->SetSpellOpener();
}
else
return;
}
// Auto cast (casted only in combat or persistent spells in any state)
else if (!m_unit->IsNonMeleeSpellCasted(false))
{
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
if (pet)
{
for (uint8 i = 0; i < pet->GetPetAutoSpellSize(); ++i)
{
uint32 spellID = pet->GetPetAutoSpellOnPos(i);
if (!spellID)
continue;
SpellEntry const* spellInfo = sSpellTemplate.LookupEntry<SpellEntry>(spellID);
if (!spellInfo)
continue;
if (!m_unit->IsSpellReady(*spellInfo))
continue;
// ignore some combinations of combat state and combat/non combat spells
//.........这里部分代码省略.........
示例3: UpdateAllies
void PetAI::UpdateAI(const uint32 diff)
{
m_owner = me->GetCharmerOrOwner();
// quest support - Razorthorn Ravager, switch to CreatureAI when charmed and not in combat
if (me->GetEntry() == 24922 && me->isCharmed() && !me->isInCombat())
me->NeedChangeAI = true;
updateAlliesTimer.Update(diff);
if (updateAlliesTimer.Passed())
UpdateAllies();
if (m_forceTimer)
{
if (m_forceTimer < diff)
m_forceTimer = 0;
else
m_forceTimer -= diff;
}
if (me->getVictim())
{
if (_needToStop())
{
_stopAttack();
return;
}
DoMeleeAttackIfReady();
}
else
{
if (me->isInCombat())
{
if (!me->GetOwner() || !me->GetOwner()->GetObjectGuid().IsPlayer())
_stopAttack();
}
else if (Unit* owner = me->GetOwner())
{
if (!me->HasReactState(REACT_PASSIVE) && !me->GetCharmInfo()->HasCommandState(COMMAND_STAY))
{
Unit* target = NULL;
if (owner->isInCombat())
target = owner->getAttackerForHelper();
else
target = me->getAttackerForHelper();
if (target)
AttackStart(target);
}
// we still do NOT have target, if follow command were appliend and we are NOT followin, reapply movegen :P
if (!me->getVictim() && me->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW) && !me->hasUnitState(UNIT_STAT_FOLLOW))
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
}
}
if (!me->GetCharmInfo())
return;
if (!me->hasUnitState(UNIT_STAT_CASTING))
{
//Autocast
for (uint8 i = 0; i < me->GetPetAutoSpellSize(); i++)
PrepareSpellForAutocast(me->GetPetAutoSpellOnPos(i));
AutocastPreparedSpells();
}
}
示例4: UpdateAllies
void PetAI::UpdateAI(const uint32 diff)
{
if (!me->isAlive())
return;
Unit* owner = me->GetCharmerOrOwner();
if (m_updateAlliesTimer <= diff)
// UpdateAllies self set update timer
UpdateAllies();
else
m_updateAlliesTimer -= 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;
}
DoMeleeAttackIfReady();
}
else if (owner && me->GetCharmInfo()) //no victim
{
Unit* nextTarget = SelectNextTarget();
if (me->HasReactState(REACT_PASSIVE))
_stopAttack();
else if (nextTarget)
AttackStart(nextTarget);
else
HandleReturnMovement();
}
else if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) // no charm info and no victim
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle());
if (!me->GetCharmInfo())
return;
// Autocast (casted only in combat or persistent spells in any state)
if (!me->HasUnitState(UNIT_STATE_CASTING))
{
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
{
uint32 spellID = me->GetPetAutoSpellOnPos(i);
if (!spellID)
continue;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
if (!spellInfo)
continue;
if (me->GetCharmInfo() && me->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
continue;
if (spellInfo->IsPositive())
{
// non combat spells allowed
// only pet spells have IsNonCombatSpell and not fit this reqs:
// Consume Shadows, Lesser Invisibility, so ignore checks for its
if (spellInfo->CanBeUsedInCombat())
{
// allow only spell without spell cost or with spell cost but not duration limit
int32 duration = spellInfo->GetDuration();
if ((spellInfo->ManaCost || spellInfo->ManaCostPercentage || spellInfo->ManaPerSecond) && duration > 0)
continue;
// allow only spell without cooldown > duration
int32 cooldown = spellInfo->GetRecoveryTime();
if (cooldown >= 0 && duration >= 0 && cooldown > duration)
continue;
}
Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);
bool spellUsed = false;
for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
{
Unit* target = ObjectAccessor::GetUnit(*me, *tar);
//only buff targets that are in combat, unless the spell can only be cast while out of combat
if (!target)
continue;
if (spell->CanAutoCast(target))
{
targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(target, spell));
//.........这里部分代码省略.........
示例5: UpdateAllies
void PetAI::Reset()
{
m_primaryTargetGuid.Clear();
m_savedTargetGuid.Clear();
m_attackDistanceRecheckTimer.SetInterval(TIME_INTERVAL_LOOK);
m_attackDistanceRecheckTimer.Reset();
m_updateAlliesTimer.SetInterval(ALLIES_UPDATE_TIME);
m_updateAlliesTimer.Reset();
UpdateAllies();
for (uint8 i = PET_SPELL_PASSIVE; i < PET_SPELL_MAX; ++i)
m_spellType[i].clear();
m_AIType = PET_AI_PASSIVE;
m_attackDistance = 0.0f;
float f_range = 0.0f;
if (!m_creature->GetCharmInfo())
return;
uint32 spellsSize = m_creature->IsPet() ? ((Pet*)m_creature)->GetPetAutoSpellSize() : m_creature->GetPetAutoSpellSize();
uint8 rangedDamageSpells = 0;
uint8 meleeDamageSpells = 0;
// classification for pet spells
for (uint32 i = 0; i < spellsSize; ++i)
{
uint32 spellID = m_creature->IsPet() ? ((Pet*)m_creature)->GetPetAutoSpellOnPos(i) : m_creature->GetPetAutoSpellOnPos(i);
if (!spellID)
continue;
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellID);
if (!spellInfo)
continue;
if (IsPassiveSpell(spellInfo))
{
m_spellType[PET_SPELL_PASSIVE].insert(spellID);
continue;
}
if (IsNonCombatSpell(spellInfo))
{
// Voidwalker Consume Shadows
if (IsChanneledSpell(spellInfo))
m_spellType[PET_SPELL_HEAL].insert(spellID);
else
m_spellType[PET_SPELL_NONCOMBAT].insert(spellID);
continue;
}
// need more correct define this type
if (IsSpellReduceThreat(spellInfo) || IsChanneledSpell(spellInfo))
{
m_spellType[PET_SPELL_DEFENCE].insert(spellID);
continue;
}
// Voracious Appetite && Cannibalize && Carrion Feeder
if (spellInfo->HasAttribute(SPELL_ATTR_ABILITY) && spellInfo->HasAttribute(SPELL_ATTR_EX2_ALLOW_DEAD_TARGET))
{
m_spellType[PET_SPELL_HEAL].insert(spellID);
continue;
}
if (IsPositiveSpell(spellInfo) && IsSpellAppliesAura(spellInfo))
{
m_spellType[PET_SPELL_BUFF].insert(spellID);
continue;
}
if (spellInfo->HasAttribute(SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY))
{
m_spellType[PET_SPELL_FREEACTION].insert(spellID);
continue;
}
// don't have SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY !
if (spellInfo->HasAttribute(SPELL_ATTR_EX_CANT_REFLECTED) ||
spellInfo->HasAttribute(SPELL_ATTR_EX7_HAS_CHARGE_EFFECT))
{
m_spellType[PET_SPELL_ATTACKSTART].insert(spellID);
continue;
}
if (IsSpellIncreaseThreat(spellInfo))
{
m_spellType[PET_SPELL_THREAT].insert(spellID);
continue;
}
// all non-combat spells classified.
switch (spellInfo->rangeIndex)
{
case SPELL_RANGE_IDX_COMBAT:
{
if (IsSpellCauseDamage(spellInfo))
{
m_spellType[PET_SPELL_MELEE].insert(spellID);
++meleeDamageSpells;
//.........这里部分代码省略.........
示例6: CreatureAI
PetAI::PetAI(Creature* c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK)
{
m_AllySet.clear();
UpdateAllies();
}
示例7: UpdateAllies
void PetAI::UpdateAI(uint32 diff)
{
if (!me->IsAlive() || !me->GetCharmInfo())
return;
Unit* owner = me->GetCharmerOrOwner();
if (m_updateAlliesTimer <= diff)
// UpdateAllies self set update timer
UpdateAllies();
else
m_updateAlliesTimer -= diff;
if (me->GetVictim() && me->GetVictim()->IsAlive())
{
// is only necessary to stop casting, the pet must not exit combat
if (me->GetVictim()->HasBreakableByDamageCrowdControlAura(me))
{
me->InterruptNonMeleeSpells(false);
return;
}
if (_needToStop())
{
;//sLog->outStaticDebug("Pet AI stopped attacking [guid=%u]", me->GetGUIDLow());
_stopAttack();
return;
}
// Check before attacking to prevent pets from leaving stay position
if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY))
{
if (me->GetCharmInfo()->IsCommandAttack() || (me->GetCharmInfo()->IsAtStay() && me->IsWithinMeleeRange(me->GetVictim())))
_doMeleeAttack();
}
else
_doMeleeAttack();
}
else if (!me->GetCharmInfo() || (!me->GetCharmInfo()->GetForcedSpell() && !me->HasUnitState(UNIT_STATE_CASTING)))
{
if (me->HasReactState(REACT_AGGRESSIVE) || me->GetCharmInfo()->IsAtStay())
{
// Every update we need to check targets only in certain cases
// Aggressive - Allow auto select if owner or pet don't have a target
// Stay - Only pick from pet or owner targets / attackers so targets won't run by
// while chasing our owner. Don't do auto select.
// All other cases (ie: defensive) - Targets are assigned by AttackedBy(), OwnerAttackedBy(), OwnerAttacked(), etc.
Unit* nextTarget = SelectNextTarget(me->HasReactState(REACT_AGGRESSIVE));
if (nextTarget)
AttackStart(nextTarget);
else
HandleReturnMovement();
}
else
HandleReturnMovement();
}
// xinef: charm info must be always available
if (!me->GetCharmInfo())
return;
// Autocast (casted only in combat or persistent spells in any state)
if (!me->HasUnitState(UNIT_STATE_CASTING))
{
if (owner && owner->GetTypeId() == TYPEID_PLAYER && me->GetCharmInfo()->GetForcedSpell() && me->GetCharmInfo()->GetForcedTarget())
{
owner->ToPlayer()->GetSession()->HandlePetActionHelper(me, me->GetGUID(), abs(me->GetCharmInfo()->GetForcedSpell()), ACT_ENABLED, me->GetCharmInfo()->GetForcedTarget());
// xinef: if spell was casted properly and we are in passive mode, handle return
if (!me->GetCharmInfo()->GetForcedSpell() && me->HasReactState(REACT_PASSIVE))
{
if (me->HasUnitState(UNIT_STATE_CASTING))
{
me->GetMotionMaster()->Clear(false);
me->StopMoving();
}
else
_stopAttack();
}
return;
}
// xinef: dont allow ghouls to cast spells below 75 energy
if (me->IsPet() && me->ToPet()->IsPetGhoul() && me->GetPower(POWER_ENERGY) < 75)
return;
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
{
uint32 spellID = me->GetPetAutoSpellOnPos(i);
if (!spellID)
continue;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
if (!spellInfo)
continue;
//.........这里部分代码省略.........
示例8: CreatureAI
PetAI::PetAI(Creature* c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK)
{
UpdateAllies();
}
示例9: UpdateAllies
void PetAI::UpdateAI(const uint32 diff)
{
if (!m_creature->isAlive())
return;
Unit* owner = m_creature->GetCharmerOrOwner();
Unit* victim = m_creature->getVictim();
if (m_updateAlliesTimer <= diff)
// UpdateAllies self set update timer
UpdateAllies();
else
m_updateAlliesTimer -= diff;
if (inCombat && (!victim || (m_creature->IsPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)))
_stopAttack();
if (((Pet*)m_creature)->GetIsRetreating())
{
if (!owner->_IsWithinDist(m_creature, (PET_FOLLOW_DIST * 2), true))
{
if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW))
m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
return;
}
else
((Pet*)m_creature)->SetIsRetreating();
}
else if (((Pet*)m_creature)->GetSpellOpener() != 0) // have opener stored
{
uint32 minRange = ((Pet*)m_creature)->GetSpellOpenerMinRange();
if (!(victim = m_creature->getVictim())
|| (minRange != 0 && m_creature->IsWithinDistInMap(victim, minRange)))
((Pet*)m_creature)->SetSpellOpener();
else if (m_creature->IsWithinDistInMap(victim, ((Pet*)m_creature)->GetSpellOpenerMaxRange()) && m_creature->IsWithinLOSInMap(victim))
{
// stop moving
m_creature->clearUnitState(UNIT_STAT_MOVING);
// auto turn to target
m_creature->SetInFront(victim);
if (victim->GetTypeId() == TYPEID_PLAYER)
m_creature->SendCreateUpdateToPlayer((Player*)victim);
if (owner->GetTypeId() == TYPEID_PLAYER)
m_creature->SendCreateUpdateToPlayer((Player*)owner);
uint32 spell_id = ((Pet*)m_creature)->GetSpellOpener();
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
Spell* spell = new Spell(m_creature, spellInfo, false);
SpellCastResult result = spell->CheckPetCast(victim);
if (result == SPELL_CAST_OK)
{
m_creature->AddCreatureSpellCooldown(spell_id);
spell->SpellStart(&(spell->m_targets));
}
else
delete spell;
((Pet*)m_creature)->SetSpellOpener();
}
else
return;
}
// Autocast (casted only in combat or persistent spells in any state)
else if (!m_creature->IsNonMeleeSpellCasted(false))
{
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); ++i)
{
uint32 spellID = m_creature->GetPetAutoSpellOnPos(i);
if (!spellID)
continue;
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellID);
if (!spellInfo)
continue;
if (m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
continue;
// ignore some combinations of combat state and combat/noncombat spells
if (!inCombat)
{
// ignore attacking spells, and allow only self/around spells
if (!IsPositiveSpell(spellInfo->Id))
continue;
// non combat spells allowed
// only pet spells have IsNonCombatSpell and not fit this reqs:
//.........这里部分代码省略.........
示例10: UpdateAllies
void PetAI::UpdateAI(const uint32 diff)
{
if (!m_creature->isAlive() || !m_creature->GetCharmInfo())
return;
Unit* owner = m_creature->GetCharmerOrOwner();
if (m_updateAlliesTimer <= diff)
// UpdateAllies self set update timer
UpdateAllies();
else
m_updateAlliesTimer -= diff;
// First checking if we have some taunt on us
Unit* tauntTarget = NULL;
const Unit::AuraList& tauntAuras = m_creature->GetAurasByType(SPELL_AURA_MOD_TAUNT);
if (!tauntAuras.empty())
{
Unit* caster = NULL;
// Auras are pushed_back, last caster will be on the end
Unit::AuraList::const_iterator aura = tauntAuras.end();
while (aura != tauntAuras.begin())
{
--aura;
caster = (*aura)->GetCaster();
if (caster && caster->isTargetableForAttack())
{
tauntTarget = caster;
break;
}
}
if (tauntTarget)
DoAttack(tauntTarget, true);
}
if (m_creature->getVictim() && m_creature->getVictim()->isAlive())
{
if (_needToStop())
{
_stopAttack();
return;
}
if (hasMelee)
{
// Check before attacking to prevent pets from leaving stay position
bool attacked = false;
if (m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY))
{
if (m_creature->GetCharmInfo()->IsCommandAttack() || (m_creature->GetCharmInfo()->IsAtStay() && m_creature->CanReachWithMeleeAttack(m_creature->getVictim())))
attacked = DoMeleeAttackIfReady();
}
else
attacked = DoMeleeAttackIfReady();
if (attacked && owner)
if (Unit* v = m_creature->getVictim()) // Victim may have died between
owner->SetInCombatWith(v);
}
}
else
{
if (m_creature->HasReactState(REACT_AGGRESSIVE) || m_creature->GetCharmInfo()->IsAtStay())
{
// Every update we need to check targets only in certain cases
// Aggressive - Allow auto select if owner or pet don't have a target
// Stay - Only pick from pet or owner targets / attackers so targets won't run by
// while chasing our owner. Don't do auto select.
// All other cases (ie: defensive) - Targets are assigned by AttackedBy(), OwnerAttackedBy(), OwnerAttacked(), etc.
Unit* nextTarget = SelectNextTarget(m_creature->HasReactState(REACT_AGGRESSIVE));
if (nextTarget)
AttackStart(nextTarget);
else
HandleReturnMovement();
}
else
HandleReturnMovement();
}
// Autocast (casted only in combat or persistent spells in any state)
if (!m_creature->IsNonMeleeSpellCasted(false))
{
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); ++i)
{
uint32 spellID = m_creature->GetPetAutoSpellOnPos(i);
if (!spellID)
continue;
SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(spellID);
if (!spellInfo)
continue;
if (m_creature->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
//.........这里部分代码省略.........
示例11: CreatureAI
PetAI::PetAI(Creature *c) : CreatureAI(c), inCombat(false)
{
UpdateAllies();
// Warlock imp has no melee attack
hasMelee = (c->GetEntry() != 416);
}
示例12: UpdateAllies
void PetAI::UpdateAI(uint32 diff)
{
if (!me->IsAlive() || !me->GetCharmInfo())
return;
Unit* owner = me->GetCharmerOrOwner();
if (m_updateAlliesTimer <= diff)
// UpdateAllies self set update timer
UpdateAllies();
else
m_updateAlliesTimer -= diff;
if (me->GetVictim() && me->EnsureVictim()->IsAlive())
{
// is only necessary to stop casting, the pet must not exit combat
if (!me->GetCurrentSpell(CURRENT_CHANNELED_SPELL) && // ignore channeled spells (Pin, Seduction)
me->EnsureVictim()->HasBreakableByDamageCrowdControlAura(me))
{
me->InterruptNonMeleeSpells(false);
return;
}
if (_needToStop())
{
TC_LOG_DEBUG("misc", "Pet AI stopped attacking [guid=%u]", me->GetGUIDLow());
_stopAttack();
return;
}
// Check before attacking to prevent pets from leaving stay position
if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY))
{
if (me->GetCharmInfo()->IsCommandAttack() || (me->GetCharmInfo()->IsAtStay() && me->IsWithinMeleeRange(me->GetVictim())))
DoMeleeAttackIfReady();
}
else
DoMeleeAttackIfReady();
}
else
{
if (me->HasReactState(REACT_AGGRESSIVE) || me->GetCharmInfo()->IsAtStay())
{
// Every update we need to check targets only in certain cases
// Aggressive - Allow auto select if owner or pet don't have a target
// Stay - Only pick from pet or owner targets / attackers so targets won't run by
// while chasing our owner. Don't do auto select.
// All other cases (ie: defensive) - Targets are assigned by AttackedBy(), OwnerAttackedBy(), OwnerAttacked(), etc.
Unit* nextTarget = SelectNextTarget(me->HasReactState(REACT_AGGRESSIVE));
if (nextTarget)
AttackStart(nextTarget);
else
HandleReturnMovement();
}
else
HandleReturnMovement();
}
// Autocast (cast only in combat or persistent spells in any state)
if (!me->HasUnitState(UNIT_STATE_CASTING))
{
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
{
uint32 spellID = me->GetPetAutoSpellOnPos(i);
if (!spellID)
continue;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
if (!spellInfo)
continue;
if (me->GetCharmInfo() && me->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
continue;
if (spellInfo->IsPositive())
{
if (spellInfo->CanBeUsedInCombat())
{
// check spell cooldown
if (me->HasSpellCooldown(spellInfo->Id))
continue;
// Check if we're in combat or commanded to attack
if (!me->IsInCombat() && !me->GetCharmInfo()->IsCommandAttack())
continue;
}
Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE);
bool spellUsed = false;
// Some spells can target enemy or friendly (DK Ghoul's Leap)
// Check for enemy first (pet then owner)
Unit* target = me->getAttackerForHelper();
if (!target && owner)
target = owner->getAttackerForHelper();
//.........这里部分代码省略.........
示例13: UpdateAllies
void PetAI::UpdateAI(const uint32 diff)
{
if (!me->isAlive())
return;
Unit* owner = me->GetCharmerOrOwner();
if (m_updateAlliesTimer <= diff)
// UpdateAllies self set update timer
UpdateAllies();
else
m_updateAlliesTimer -= 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))
{
me->InterruptNonMeleeSpells(false);
return;
}
if (_needToStop())
{
sLog->outStaticDebug("Pet AI stopped attacking [guid=%u]", me->GetGUIDLow());
_stopAttack();
return;
}
DoMeleeAttackIfReady();
}
else if (owner && me->GetCharmInfo()) //no victim
{
Unit* nextTarget = SelectNextTarget();
if (me->HasReactState(REACT_PASSIVE))
_stopAttack();
else if (nextTarget)
AttackStart(nextTarget);
else
HandleReturnMovement();
}
else if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) // no charm info and no victim
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle());
if (!me->GetCharmInfo())
return;
// Autocast (casted only in combat or persistent spells in any state)
if (!me->HasUnitState(UNIT_STATE_CASTING))
{
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
{
uint32 spellID = me->GetPetAutoSpellOnPos(i);
if (!spellID)
continue;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
if (!spellInfo)
continue;
// Check global cooldown
if (me->GetCharmInfo() && me->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
continue;
// Check spell cooldown
if (me->HasSpellCooldown(spellInfo->Id))
continue;
// Check if pet is in combat and if spell can be cast
if (me->isInCombat() && !spellInfo->CanBeUsedInCombat())
continue;
// Prevent spells like Furious Howl from constantly casting out of
// combat when the cooldown is up
if (!me->isInCombat() && !spellInfo->NeedsToBeTriggeredByCaster())
continue;
// We have a spell we can cast, let's pick a target
if (spellInfo->IsPositive())
{
// These would be buff spells like Furious Howl, Consume Shadows, etc.
Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);
bool spellUsed = false;
for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
{
Unit* target = ObjectAccessor::GetUnit(*me, *tar);
if (!target)
continue;
if (spell->CanAutoCast(target))
{
targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(target, spell));
spellUsed = true;
//.........这里部分代码省略.........
示例14: UpdateAllies
void PetAI::UpdateAI(const uint32 diff)
{
if (!m_creature->isAlive())
return;
Unit* owner = m_creature->GetCharmerOrOwner();
// chained, use original owner instead
if (owner && owner->GetTypeId() == TYPEID_UNIT && ((Creature*)owner)->GetEntry() == m_creature->GetEntry())
if (Unit *creator = m_creature->GetCreator())
owner = creator;
if (m_updateAlliesTimer <= diff)
// UpdateAllies self set update timer
UpdateAllies();
else
m_updateAlliesTimer -= diff;
if (inCombat && (!m_creature->getVictim() || m_creature->isPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS))
_stopAttack();
// i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
if (m_creature->getVictim())
{
if (_needToStop())
{
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "PetAI (guid = %u) is stopping attack.", m_creature->GetGUIDLow());
_stopAttack();
return;
}
else if (m_creature->IsStopped() || m_creature->IsTargetWithinAttackRange())
{
// required to be stopped cases
if (m_creature->IsStopped() && m_creature->IsNonMeleeSpellCasted(false))
{
if (m_creature->hasUnitState(UNIT_STAT_FOLLOW_MOVE))
m_creature->InterruptNonMeleeSpells(false);
else
return;
}
// not required to be stopped case
else if (m_creature->isAttackReady() && m_creature->canReachWithAttack(m_creature->getVictim()))
{
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();
if (!m_creature->getVictim())
return;
//if pet misses its target, it will also be the first in threat list
m_creature->getVictim()->AddThreat(m_creature);
if ( _needToStop() )
_stopAttack();
}
}
}
else if (owner && m_creature->GetCharmInfo())
{
if (owner->isInCombat() && !(m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE) || m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY)))
{
AttackStart(owner->getAttackerForHelper());
}
else if (m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
{
if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW) )
{
m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST, m_creature->isPet() ? ((Pet*)m_creature)->GetPetFollowAngle() : PET_DEFAULT_FOLLOW_ANGLE);
}
}
}
// Autocast (casted only in combat or persistent spells in any state)
if (!m_creature->IsNonMeleeSpellCasted(false))
{
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); ++i)
{
uint32 spellID = m_creature->GetPetAutoSpellOnPos(i);
if (!spellID)
continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID);
if (!spellInfo)
continue;
if (m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
continue;
// ignore some combinations of combat state and combat/noncombat spells
if (!inCombat)
{
// ignore attacking spells, and allow only self/around spells
if (!IsPositiveSpell(spellInfo->Id))
continue;
// non combat spells allowed
//.........这里部分代码省略.........
示例15: UpdateAllies
void PetAI::UpdateAI(const uint32 diff)
{
if (!m_creature->isAlive())
return;
Unit* owner = m_creature->GetCharmerOrOwner();
if(m_updateAlliesTimer <= diff)
// UpdateAllies self set update timer
UpdateAllies();
else
m_updateAlliesTimer -= diff;
if (inCombat && !m_creature->getVictim())
_stopAttack();
// i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
if (m_creature->getVictim())
{
if (_needToStop())
{
DEBUG_LOG("Pet AI stoped attacking [guid=%u]", m_creature->GetGUIDLow());
_stopAttack();
return;
}
else if (m_creature->IsStopped() || m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
{
// required to be stopped cases
if (m_creature->IsStopped() && m_creature->IsNonMeleeSpellCasted(false))
{
if (m_creature->hasUnitState(UNIT_STAT_FOLLOW))
m_creature->InterruptNonMeleeSpells(false);
else
return;
}
// not required to be stopped case
else if (m_creature->isAttackReady() && m_creature->canReachWithAttack(m_creature->getVictim()))
{
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();
if (!m_creature->getVictim())
return;
//if pet misses its target, it will also be the first in threat list
m_creature->getVictim()->AddThreat(m_creature,0.0f);
if( _needToStop() )
_stopAttack();
}
}
}
else if (owner && m_creature->GetCharmInfo())
{
if (owner->isInCombat() && !(m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE) || m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY)))
{
AttackStart(owner->getAttackerForHelper());
}
else if(m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
{
if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW) )
{
m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
}
}
}
if (m_creature->GetGlobalCooldown() == 0 && !m_creature->IsNonMeleeSpellCasted(false))
{
//Autocast
for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); i++)
{
uint32 spellID = m_creature->GetPetAutoSpellOnPos(i);
if (!spellID)
continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID);
if (!spellInfo)
continue;
// ignore some combinations of combat state and combat/noncombat spells
if (!inCombat)
{
if (!IsPositiveSpell(spellInfo->Id))
continue;
}
else
{
if (IsNonCombatSpell(spellInfo))
continue;
}
Spell *spell = new Spell(m_creature, spellInfo, false, 0);
if (inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(m_creature->getVictim()))
{
m_targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(m_creature->getVictim(), spell));
continue;
}
//.........这里部分代码省略.........