Example #1
0
        public override void UpdateAI(uint diff)
        {
            if (!UpdateVictim())
            {
                return;
            }

            _events.Update(diff);

            if (me.HasUnitState(UnitState.Casting))
            {
                return;
            }

            uint spellId = _events.ExecuteEvent();

            if (spellId != 0)
            {
                DoCast(spellId);
                AISpellInfoType info = GetAISpellInfo(spellId, me.GetMap().GetDifficultyID());
                _events.ScheduleEvent(spellId, info.cooldown + RandomHelper.Rand32() % info.cooldown);
            }
            else
            {
                DoMeleeAttackIfReady();
            }
        }
Example #2
0
        public override void UpdateAI(uint diff)
        {
            if (!UpdateVictim())
            {
                return;
            }

            _events.Update(diff);

            if (me.GetVictim().HasBreakableByDamageCrowdControlAura(me))
            {
                me.InterruptNonMeleeSpells(false);
                return;
            }

            if (me.HasUnitState(UnitState.Casting))
            {
                return;
            }

            uint spellId = _events.ExecuteEvent();

            if (spellId != 0)
            {
                DoCast(spellId);
                uint            casttime = (uint)me.GetCurrentSpellCastTime(spellId);
                AISpellInfoType info     = GetAISpellInfo(spellId, me.GetMap().GetDifficultyID());
                _events.ScheduleEvent(spellId, (casttime != 0 ? casttime : 500) + info.realCooldown);
            }
        }
Example #3
0
        public override void EnterCombat(Unit victim)
        {
            if (spells.Empty())
            {
                return;
            }

            int  spell = (int)(RandomHelper.Rand32() % spells.Count);
            uint count = 0;

            foreach (var id in spells)
            {
                AISpellInfoType info = GetAISpellInfo(id, me.GetMap().GetDifficultyID());
                if (info.condition == AICondition.Aggro)
                {
                    me.CastSpell(victim, id, false);
                }
                else if (info.condition == AICondition.Combat)
                {
                    uint cooldown = info.realCooldown;
                    if (count == spell)
                    {
                        DoCast(spells[spell]);
                        cooldown += (uint)me.GetCurrentSpellCastTime(id);
                    }
                    _events.ScheduleEvent(id, cooldown);
                }
            }
        }
Example #4
0
 public override void JustDied(Unit killer)
 {
     foreach (var id in spells)
     {
         AISpellInfoType info = GetAISpellInfo(id, me.GetMap().GetDifficultyID());
         if (info.condition == AICondition.Die)
         {
             me.CastSpell(killer, id, true);
         }
     }
 }
Example #5
0
 public override void EnterCombat(Unit victim)
 {
     foreach (var id in spells)
     {
         AISpellInfoType info = GetAISpellInfo(id, me.GetMap().GetDifficultyID());
         if (info.condition == AICondition.Aggro)
         {
             me.CastSpell(victim, id, false);
         }
         else if (info.condition == AICondition.Combat)
         {
             _events.ScheduleEvent(id, info.cooldown + RandomHelper.Rand32() % info.cooldown);
         }
     }
 }
Example #6
0
        public override void InitializeAI()
        {
            base.InitializeAI();

            m_attackDist = 30.0f;
            foreach (var id in spells)
            {
                AISpellInfoType info = GetAISpellInfo(id, me.GetMap().GetDifficultyID());
                if (info.condition == AICondition.Combat && m_attackDist > info.maxRange)
                {
                    m_attackDist = info.maxRange;
                }
            }

            if (m_attackDist == 30.0f)
            {
                m_attackDist = SharedConst.MeleeRange;
            }
        }
Example #7
0
        public static void FillAISpellInfo()
        {
            //AISpellInfo = new AISpellInfoType[spellStorage.Keys.Max() + 1];

            Global.SpellMgr.ForEachSpellInfo(spellInfo =>
            {
                AISpellInfoType AIInfo = new AISpellInfoType();
                if (spellInfo.HasAttribute(SpellAttr0.CastableWhileDead))
                {
                    AIInfo.condition = AICondition.Die;
                }
                else if (spellInfo.IsPassive() || spellInfo.GetDuration() == -1)
                {
                    AIInfo.condition = AICondition.Aggro;
                }
                else
                {
                    AIInfo.condition = AICondition.Combat;
                }

                if (AIInfo.cooldown < spellInfo.RecoveryTime)
                {
                    AIInfo.cooldown = spellInfo.RecoveryTime;
                }

                if (spellInfo.GetMaxRange(false) == 0)
                {
                    if (AIInfo.target < AITarget.Self)
                    {
                        AIInfo.target = AITarget.Self;
                    }
                }
                else
                {
                    foreach (SpellEffectInfo effect in spellInfo.GetEffects())
                    {
                        if (effect == null)
                        {
                            continue;
                        }

                        var targetType = effect.TargetA.GetTarget();

                        if (targetType == Targets.UnitTargetEnemy || targetType == Targets.DestTargetEnemy)
                        {
                            if (AIInfo.target < AITarget.Victim)
                            {
                                AIInfo.target = AITarget.Victim;
                            }
                        }
                        else if (targetType == Targets.UnitDestAreaEnemy)
                        {
                            if (AIInfo.target < AITarget.Enemy)
                            {
                                AIInfo.target = AITarget.Enemy;
                            }
                        }

                        if (effect.Effect == SpellEffectName.ApplyAura)
                        {
                            if (targetType == Targets.UnitTargetEnemy)
                            {
                                if (AIInfo.target < AITarget.Debuff)
                                {
                                    AIInfo.target = AITarget.Debuff;
                                }
                            }
                            else if (spellInfo.IsPositive())
                            {
                                if (AIInfo.target < AITarget.Buff)
                                {
                                    AIInfo.target = AITarget.Buff;
                                }
                            }
                        }
                    }
                }
                AIInfo.realCooldown = spellInfo.RecoveryTime + spellInfo.StartRecoveryTime;
                AIInfo.maxRange     = spellInfo.GetMaxRange(false) * 3 / 4;

                AIInfo.Effects = 0;
                AIInfo.Targets = 0;

                foreach (SpellEffectInfo effect in spellInfo.GetEffects())
                {
                    if (effect == null)
                    {
                        continue;
                    }

                    // Spell targets self.
                    if (effect.TargetA.GetTarget() == Targets.UnitCaster)
                    {
                        AIInfo.Targets |= 1 << ((int)SelectTargetType.Self - 1);
                    }

                    // Spell targets a single enemy.
                    if (effect.TargetA.GetTarget() == Targets.UnitTargetEnemy ||
                        effect.TargetA.GetTarget() == Targets.DestTargetEnemy)
                    {
                        AIInfo.Targets |= 1 << ((int)SelectTargetType.SingleEnemy - 1);
                    }

                    // Spell targets AoE at enemy.
                    if (effect.TargetA.GetTarget() == Targets.UnitSrcAreaEnemy ||
                        effect.TargetA.GetTarget() == Targets.UnitDestAreaEnemy ||
                        effect.TargetA.GetTarget() == Targets.SrcCaster ||
                        effect.TargetA.GetTarget() == Targets.DestDynobjEnemy)
                    {
                        AIInfo.Targets |= 1 << ((int)SelectTargetType.AoeEnemy - 1);
                    }

                    // Spell targets an enemy.
                    if (effect.TargetA.GetTarget() == Targets.UnitTargetEnemy ||
                        effect.TargetA.GetTarget() == Targets.DestTargetEnemy ||
                        effect.TargetA.GetTarget() == Targets.UnitSrcAreaEnemy ||
                        effect.TargetA.GetTarget() == Targets.UnitDestAreaEnemy ||
                        effect.TargetA.GetTarget() == Targets.SrcCaster ||
                        effect.TargetA.GetTarget() == Targets.DestDynobjEnemy)
                    {
                        AIInfo.Targets |= 1 << ((int)SelectTargetType.AnyEnemy - 1);
                    }

                    // Spell targets a single friend (or self).
                    if (effect.TargetA.GetTarget() == Targets.UnitCaster ||
                        effect.TargetA.GetTarget() == Targets.UnitTargetAlly ||
                        effect.TargetA.GetTarget() == Targets.UnitTargetParty)
                    {
                        AIInfo.Targets |= 1 << ((int)SelectTargetType.SingleFriend - 1);
                    }

                    // Spell targets AoE friends.
                    if (effect.TargetA.GetTarget() == Targets.UnitCasterAreaParty ||
                        effect.TargetA.GetTarget() == Targets.UnitLastTargetAreaParty ||
                        effect.TargetA.GetTarget() == Targets.SrcCaster)
                    {
                        AIInfo.Targets |= 1 << ((int)SelectTargetType.AoeFriend - 1);
                    }

                    // Spell targets any friend (or self).
                    if (effect.TargetA.GetTarget() == Targets.UnitCaster ||
                        effect.TargetA.GetTarget() == Targets.UnitTargetAlly ||
                        effect.TargetA.GetTarget() == Targets.UnitTargetParty ||
                        effect.TargetA.GetTarget() == Targets.UnitCasterAreaParty ||
                        effect.TargetA.GetTarget() == Targets.UnitLastTargetAreaParty ||
                        effect.TargetA.GetTarget() == Targets.SrcCaster)
                    {
                        AIInfo.Targets |= 1 << ((int)SelectTargetType.AnyFriend - 1);
                    }

                    // Make sure that this spell includes a damage effect.
                    if (effect.Effect == SpellEffectName.SchoolDamage ||
                        effect.Effect == SpellEffectName.Instakill ||
                        effect.Effect == SpellEffectName.EnvironmentalDamage ||
                        effect.Effect == SpellEffectName.HealthLeech)
                    {
                        AIInfo.Effects |= 1 << ((int)SelectEffect.Damage - 1);
                    }

                    // Make sure that this spell includes a healing effect (or an apply aura with a periodic heal).
                    if (effect.Effect == SpellEffectName.Heal ||
                        effect.Effect == SpellEffectName.HealMaxHealth ||
                        effect.Effect == SpellEffectName.HealMechanical ||
                        (effect.Effect == SpellEffectName.ApplyAura && effect.ApplyAuraName == AuraType.PeriodicHeal))
                    {
                        AIInfo.Effects |= 1 << ((int)SelectEffect.Healing - 1);
                    }

                    // Make sure that this spell applies an aura.
                    if (effect.Effect == SpellEffectName.ApplyAura)
                    {
                        AIInfo.Effects |= 1 << ((int)SelectEffect.Aura - 1);
                    }
                }

                AISpellInfo[(spellInfo.Id, spellInfo.Difficulty)] = AIInfo;
            });
Example #8
0
        public void DoCast(uint spellId)
        {
            Unit target = null;

            AISpellInfoType info = GetAISpellInfo(spellId, me.GetMap().GetDifficultyID());

            switch (info.target)
            {
            default:
            case AITarget.Self:
                target = me;
                break;

            case AITarget.Victim:
                target = me.GetVictim();
                break;

            case AITarget.Enemy:
            {
                var spellInfo = Global.SpellMgr.GetSpellInfo(spellId, me.GetMap().GetDifficultyID());
                if (spellInfo != null)
                {
                    bool playerOnly = spellInfo.HasAttribute(SpellAttr3.OnlyTargetPlayers);
                    target = SelectTarget(SelectAggroTarget.Random, 0, spellInfo.GetMaxRange(false), playerOnly);
                }
                break;
            }

            case AITarget.Ally:
            case AITarget.Buff:
                target = me;
                break;

            case AITarget.Debuff:
            {
                var spellInfo = Global.SpellMgr.GetSpellInfo(spellId, me.GetMap().GetDifficultyID());
                if (spellInfo != null)
                {
                    bool  playerOnly = spellInfo.HasAttribute(SpellAttr3.OnlyTargetPlayers);
                    float range      = spellInfo.GetMaxRange(false);

                    DefaultTargetSelector targetSelector = new DefaultTargetSelector(me, range, playerOnly, true, -(int)spellId);
                    if (!spellInfo.HasAuraInterruptFlag(SpellAuraInterruptFlags.NotVictim) &&
                        targetSelector.Check(me.GetVictim()))
                    {
                        target = me.GetVictim();
                    }
                    else
                    {
                        target = SelectTarget(SelectAggroTarget.Random, 0, targetSelector);
                    }
                }
                break;
            }
            }

            if (target != null)
            {
                me.CastSpell(target, spellId, false);
            }
        }
Example #9
0
        //Returns spells that meet the specified criteria from the creatures spell list
        public SpellInfo SelectSpell(Unit target, SpellSchoolMask school, Mechanics mechanic, SelectTargetType targets, float rangeMin, float rangeMax, SelectEffect effect)
        {
            //No target so we can't cast
            if (target == null)
            {
                return(null);
            }

            //Silenced so we can't cast
            if (me.HasUnitFlag(UnitFlags.Silenced))
            {
                return(null);
            }

            //Using the extended script system we first create a list of viable spells
            SpellInfo[] apSpell = new SpellInfo[SharedConst.MaxCreatureSpells];

            uint spellCount = 0;

            //Check if each spell is viable(set it to null if not)
            for (uint i = 0; i < SharedConst.MaxCreatureSpells; i++)
            {
                SpellInfo       tempSpell = Global.SpellMgr.GetSpellInfo(me.m_spells[i], me.GetMap().GetDifficultyID());
                AISpellInfoType aiSpell   = GetAISpellInfo(me.m_spells[i], me.GetMap().GetDifficultyID());

                //This spell doesn't exist
                if (tempSpell == null)
                {
                    continue;
                }

                // Targets and Effects checked first as most used restrictions
                //Check the spell targets if specified
                if (targets != 0 && !Convert.ToBoolean(aiSpell.Targets & (1 << ((int)targets - 1))))
                {
                    continue;
                }

                //Check the type of spell if we are looking for a specific spell type
                if (effect != 0 && !Convert.ToBoolean(aiSpell.Effects & (1 << ((int)effect - 1))))
                {
                    continue;
                }

                //Check for school if specified
                if (school != 0 && (tempSpell.SchoolMask & school) == 0)
                {
                    continue;
                }

                //Check for spell mechanic if specified
                if (mechanic != 0 && tempSpell.Mechanic != mechanic)
                {
                    continue;
                }

                //Check if the spell meets our range requirements
                if (rangeMin != 0 && me.GetSpellMinRangeForTarget(target, tempSpell) < rangeMin)
                {
                    continue;
                }
                if (rangeMax != 0 && me.GetSpellMaxRangeForTarget(target, tempSpell) > rangeMax)
                {
                    continue;
                }

                //Check if our target is in range
                if (me.IsWithinDistInMap(target, me.GetSpellMinRangeForTarget(target, tempSpell)) || !me.IsWithinDistInMap(target, me.GetSpellMaxRangeForTarget(target, tempSpell)))
                {
                    continue;
                }

                //All good so lets add it to the spell list
                apSpell[spellCount] = tempSpell;
                ++spellCount;
            }

            //We got our usable spells so now lets randomly pick one
            if (spellCount == 0)
            {
                return(null);
            }

            return(apSpell[RandomHelper.IRand(0, (int)(spellCount - 1))]);
        }
Example #10
0
        public static void FillAISpellInfo()
        {
            var spellStorage = Global.SpellMgr.GetSpellInfoStorage();

            AISpellInfo = new AISpellInfoType[spellStorage.Keys.Max() + 1];

            foreach (var spellInfo in spellStorage.Values)
            {
                AISpellInfoType AIInfo = AISpellInfo[spellInfo.Id];
                if (spellInfo.HasAttribute(SpellAttr0.CastableWhileDead))
                {
                    AIInfo.condition = AICondition.Die;
                }
                else if (spellInfo.IsPassive() || spellInfo.GetDuration() == -1)
                {
                    AIInfo.condition = AICondition.Aggro;
                }
                else
                {
                    AIInfo.condition = AICondition.Combat;
                }

                if (AIInfo.cooldown < spellInfo.RecoveryTime)
                {
                    AIInfo.cooldown = spellInfo.RecoveryTime;
                }

                if (spellInfo.GetMaxRange(false) == 0)
                {
                    if (AIInfo.target < AITarget.Self)
                    {
                        AIInfo.target = AITarget.Self;
                    }
                }
                else
                {
                    foreach (SpellEffectInfo effect in spellInfo.GetEffectsForDifficulty(Difficulty.None))
                    {
                        if (effect == null)
                        {
                            continue;
                        }

                        var targetType = effect.TargetA.GetTarget();

                        if (targetType == Targets.UnitEnemy || targetType == Targets.DestEnemy)
                        {
                            if (AIInfo.target < AITarget.Victim)
                            {
                                AIInfo.target = AITarget.Victim;
                            }
                        }
                        else if (targetType == Targets.UnitDestAreaEnemy)
                        {
                            if (AIInfo.target < AITarget.Enemy)
                            {
                                AIInfo.target = AITarget.Enemy;
                            }
                        }

                        if (effect.Effect == SpellEffectName.ApplyAura)
                        {
                            if (targetType == Targets.UnitEnemy)
                            {
                                if (AIInfo.target < AITarget.Debuff)
                                {
                                    AIInfo.target = AITarget.Debuff;
                                }
                            }
                            else if (spellInfo.IsPositive())
                            {
                                if (AIInfo.target < AITarget.Buff)
                                {
                                    AIInfo.target = AITarget.Buff;
                                }
                            }
                        }
                    }
                }
                AIInfo.realCooldown = spellInfo.RecoveryTime + spellInfo.StartRecoveryTime;
                AIInfo.maxRange     = spellInfo.GetMaxRange(false) * 3 / 4;
            }
        }