void HandleEffectDummy(uint effIndex) { Position destPos = GetHitDest().GetPosition(); SpellCastTargets targets = new SpellCastTargets(); targets.SetDst(destPos); targets.SetUnitTarget(GetCaster()); GetHitUnit().CastSpell(targets, Global.SpellMgr.GetSpellInfo((uint)GetEffectValue()), null); }
void HandleEffectDummy(uint effIndex) { Position destPos = GetHitDest().GetPosition(); SpellCastTargets targets = new SpellCastTargets(); targets.SetDst(destPos); targets.SetUnitTarget(GetCaster()); GetHitUnit().CastSpell(targets, (uint)GetEffectValue(), new CastSpellExtraArgs(GetCastDifficulty())); }
public override void UpdateAI(uint diff) { if (!me.IsAlive() || me.GetCharmInfo() == null) { 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.GetCurrentSpell(CurrentSpellTypes.Channeled) && // ignore channeled spells (Pin, Seduction) (me.GetVictim() && me.GetVictim().HasBreakableByDamageCrowdControlAura(me))) { me.InterruptNonMeleeSpells(false); return; } if (_needToStop()) { Log.outDebug(LogFilter.Server, "Pet AI stopped attacking [{0}]", me.GetGUID().ToString()); _stopAttack(); return; } // Check before attacking to prevent pets from leaving stay position if (me.GetCharmInfo().HasCommandState(CommandStates.Stay)) { if (me.GetCharmInfo().IsCommandAttack() || (me.GetCharmInfo().IsAtStay() && me.IsWithinMeleeRange(me.GetVictim()))) { DoMeleeAttackIfReady(); } } else { DoMeleeAttackIfReady(); } } else { if (me.HasReactState(ReactStates.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(ReactStates.Aggressive)); if (nextTarget) { AttackStart(nextTarget); } else { HandleReturnMovement(); } } else { HandleReturnMovement(); } } // Autocast (casted only in combat or persistent spells in any state) if (!me.HasUnitState(UnitState.Casting)) { List <Tuple <Unit, Spell> > targetSpellStore = new List <Tuple <Unit, Spell> >(); for (byte i = 0; i < me.GetPetAutoSpellSize(); ++i) { uint spellID = me.GetPetAutoSpellOnPos(i); if (spellID == 0) { continue; } SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellID); if (spellInfo == null) { continue; } if (me.GetCharmInfo() != null && me.GetSpellHistory().HasGlobalCooldown(spellInfo)) { continue; } // check spell cooldown if (!me.GetSpellHistory().IsReady(spellInfo)) { continue; } if (spellInfo.IsPositive()) { if (spellInfo.CanBeUsedInCombat()) { // Check if we're in combat or commanded to attack if (!me.IsInCombat() && !me.GetCharmInfo().IsCommandAttack()) { continue; } } Spell spell = new Spell(me, spellInfo, TriggerCastFlags.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(); } if (target) { if (CanAIAttack(target) && spell.CanAutoCast(target)) { targetSpellStore.Add(Tuple.Create(target, spell)); spellUsed = true; } } if (spellInfo.HasEffect(SpellEffectName.JumpDest)) { if (!spellUsed) { spell.Dispose(); } continue; // Pets must only jump to target } // No enemy, check friendly if (!spellUsed) { foreach (var tar in m_AllySet) { Unit ally = Global.ObjAccessor.GetUnit(me, tar); //only buff targets that are in combat, unless the spell can only be cast while out of combat if (!ally) { continue; } if (spell.CanAutoCast(ally)) { targetSpellStore.Add(Tuple.Create(ally, spell)); spellUsed = true; break; } } } // No valid targets at all if (!spellUsed) { spell.Dispose(); } } else if (me.GetVictim() && CanAIAttack(me.GetVictim()) && spellInfo.CanBeUsedInCombat()) { Spell spell = new Spell(me, spellInfo, TriggerCastFlags.None); if (spell.CanAutoCast(me.GetVictim())) { targetSpellStore.Add(Tuple.Create(me.GetVictim(), spell)); } else { spell.Dispose(); } } } //found units to cast on to if (!targetSpellStore.Empty()) { int index = RandomHelper.IRand(0, targetSpellStore.Count - 1); var tss = targetSpellStore[index]; (Unit target, Spell spell) = tss; targetSpellStore.RemoveAt(index); SpellCastTargets targets = new SpellCastTargets(); targets.SetUnitTarget(target); spell.Prepare(targets); } // deleted cached Spell objects foreach (var pair in targetSpellStore) { pair.Item2.Dispose(); } } // Update speed as needed to prevent dropping too far behind and despawning me.UpdateSpeed(UnitMoveType.Run); me.UpdateSpeed(UnitMoveType.Walk); me.UpdateSpeed(UnitMoveType.Flight); }