diff --git a/Source/Framework/Constants/CreatureConst.cs b/Source/Framework/Constants/CreatureConst.cs index b43dc0c3d..a580bbeed 100644 --- a/Source/Framework/Constants/CreatureConst.cs +++ b/Source/Framework/Constants/CreatureConst.cs @@ -45,7 +45,7 @@ namespace Framework.Constants Unknown = 5 // found in 2.2.3 for 2 mobs } - [System.Flags] + [Flags] public enum UnitFlags : uint { ServerControlled = 0x01, diff --git a/Source/Framework/Constants/SharedConst.cs b/Source/Framework/Constants/SharedConst.cs index b8193a445..9db3e827f 100644 --- a/Source/Framework/Constants/SharedConst.cs +++ b/Source/Framework/Constants/SharedConst.cs @@ -189,6 +189,7 @@ namespace Framework.Constants public const int BoundaryVisualizeStepSize = 1; public const int BoundaryVisualizeFailsafeLimit = 750; public const int BoundaryVisualizeSpawnHeight = 5; + public const uint AIDefaultCooldown = 5000; /// /// GameObject Const diff --git a/Source/Game/AI/CoreAI/CombatAI.cs b/Source/Game/AI/CoreAI/CombatAI.cs index 684a89134..704e69679 100644 --- a/Source/Game/AI/CoreAI/CombatAI.cs +++ b/Source/Game/AI/CoreAI/CombatAI.cs @@ -46,7 +46,7 @@ namespace Game.AI foreach (var id in Spells) { AISpellInfoType info = GetAISpellInfo(id, me.GetMap().GetDifficultyID()); - if (info.condition == AICondition.Die) + if (info != null && info.condition == AICondition.Die) me.CastSpell(killer, id, true); } } @@ -56,10 +56,13 @@ namespace Game.AI 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); + if (info != null) + { + 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); + } } } @@ -78,7 +81,8 @@ namespace Game.AI { DoCast(spellId); AISpellInfoType info = GetAISpellInfo(spellId, me.GetMap().GetDifficultyID()); - _events.ScheduleEvent(spellId, info.cooldown + RandomHelper.Rand32() % info.cooldown); + if (info != null) + _events.ScheduleEvent(spellId, info.cooldown + RandomHelper.Rand32() % info.cooldown); } else DoMeleeAttackIfReady(); @@ -121,7 +125,7 @@ namespace Game.AI foreach (var id in Spells) { AISpellInfoType info = GetAISpellInfo(id, me.GetMap().GetDifficultyID()); - if (info.condition == AICondition.Combat && _attackDist > info.maxRange) + if (info != null && info.condition == AICondition.Combat && _attackDist > info.maxRange) _attackDist = info.maxRange; } @@ -144,17 +148,20 @@ namespace Game.AI 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) + if (info != null) { - uint cooldown = info.realCooldown; - if (count == spell) + if (info.condition == AICondition.Aggro) + me.CastSpell(victim, id, false); + else if (info.condition == AICondition.Combat) { - DoCast(Spells[spell]); - cooldown += (uint)me.GetCurrentSpellCastTime(id); + uint cooldown = info.realCooldown; + if (count == spell) + { + DoCast(Spells[spell]); + cooldown += (uint)me.GetCurrentSpellCastTime(id); + } + _events.ScheduleEvent(id, cooldown); } - _events.ScheduleEvent(id, cooldown); } } } @@ -181,7 +188,8 @@ namespace Game.AI DoCast(spellId); uint casttime = (uint)me.GetCurrentSpellCastTime(spellId); AISpellInfoType info = GetAISpellInfo(spellId, me.GetMap().GetDifficultyID()); - _events.ScheduleEvent(spellId, (casttime != 0 ? casttime : 500) + info.realCooldown); + if (info != null) + _events.ScheduleEvent(spellId, (casttime != 0 ? casttime : 500) + info.realCooldown); } } } diff --git a/Source/Game/AI/CoreAI/CreatureAI.cs b/Source/Game/AI/CoreAI/CreatureAI.cs index a8e0a6a0e..b56e4f101 100644 --- a/Source/Game/AI/CoreAI/CreatureAI.cs +++ b/Source/Game/AI/CoreAI/CreatureAI.cs @@ -491,8 +491,15 @@ namespace Game.AI public List GetBoundary() { return _boundary; } } - public struct AISpellInfoType + public class AISpellInfoType { + public AISpellInfoType() + { + target = AITarget.Self; + condition = AICondition.Combat; + cooldown = SharedConst.AIDefaultCooldown; + } + public AITarget target; public AICondition condition; public uint cooldown; diff --git a/Source/Game/AI/CoreAI/UnitAI.cs b/Source/Game/AI/CoreAI/UnitAI.cs index cd78ff941..2f64d5ef9 100644 --- a/Source/Game/AI/CoreAI/UnitAI.cs +++ b/Source/Game/AI/CoreAI/UnitAI.cs @@ -252,9 +252,13 @@ namespace Game.AI public void DoCast(uint spellId) { Unit target = null; + AITarget aiTargetType = AITarget.Self; AISpellInfoType info = GetAISpellInfo(spellId, me.GetMap().GetDifficultyID()); - switch (info.target) + if (info != null) + aiTargetType = info.target; + + switch (aiTargetType) { default: case AITarget.Self: @@ -321,8 +325,6 @@ namespace Game.AI public static void FillAISpellInfo() { - //AISpellInfo = new AISpellInfoType[spellStorage.Keys.Max() + 1]; - Global.SpellMgr.ForEachSpellInfo(spellInfo => { AISpellInfoType AIInfo = new(); diff --git a/Source/Game/AI/ScriptedAI/ScriptedAI.cs b/Source/Game/AI/ScriptedAI/ScriptedAI.cs index cce585c6d..458843aad 100644 --- a/Source/Game/AI/ScriptedAI/ScriptedAI.cs +++ b/Source/Game/AI/ScriptedAI/ScriptedAI.cs @@ -223,7 +223,7 @@ namespace Game.AI AISpellInfoType aiSpell = GetAISpellInfo(me.m_spells[i], me.GetMap().GetDifficultyID()); //This spell doesn't exist - if (tempSpell == null) + if (tempSpell == null || aiSpell == null) continue; // Targets and Effects checked first as most used restrictions