Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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()));
        }
Ejemplo n.º 3
0
        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);
        }