diff --git a/Projects/UOContent/Mobiles/AI/AnimalAI.cs b/Projects/UOContent/Mobiles/AI/AnimalAI.cs index 73fd6c900..5f2a30590 100644 --- a/Projects/UOContent/Mobiles/AI/AnimalAI.cs +++ b/Projects/UOContent/Mobiles/AI/AnimalAI.cs @@ -60,7 +60,6 @@ public class AnimalAI : BaseAI } Action = ActionType.Wander; - return true; } @@ -74,7 +73,6 @@ public class AnimalAI : BaseAI } Action = ActionType.Wander; - return true; } @@ -96,6 +94,15 @@ public class AnimalAI : BaseAI } Action = ActionType.Flee; + return true; + } + } + + if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant)) + { + if (m_Mobile.Debug) + { + m_Mobile.DebugSay($"I used my abilities on {combatant.Name}!"); } } diff --git a/Projects/UOContent/Mobiles/AI/ArcherAI.cs b/Projects/UOContent/Mobiles/AI/ArcherAI.cs index 01faf9f5c..ad594ab08 100644 --- a/Projects/UOContent/Mobiles/AI/ArcherAI.cs +++ b/Projects/UOContent/Mobiles/AI/ArcherAI.cs @@ -80,6 +80,16 @@ public class ArcherAI : BaseAI } } + if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, m_Mobile.Combatant)) + { + if (m_Mobile.Debug) + { + m_Mobile.DebugSay($"I used my abilities on {m_Mobile.Combatant.Name}!"); + } + + return true; + } + // When we have no ammo, we flee var pack = m_Mobile.Backpack; @@ -123,4 +133,4 @@ public class ArcherAI : BaseAI return true; } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/AI/BaseAI.cs b/Projects/UOContent/Mobiles/AI/BaseAI.cs index cef4dbd47..1fcd3d50e 100644 --- a/Projects/UOContent/Mobiles/AI/BaseAI.cs +++ b/Projects/UOContent/Mobiles/AI/BaseAI.cs @@ -993,18 +993,24 @@ public abstract class BaseAI { m_Mobile.DebugSay("Praise the shepherd!"); } - } - else - { - var c = m_Mobile.Combatant; - if (c?.Deleted != false || c.Map != m_Mobile.Map || !c.Alive || c.IsDeadBondedPet) + return true; + } + + var c = m_Mobile.Combatant; + + if (c?.Deleted != false || c.Map != m_Mobile.Map || !c.Alive || c.IsDeadBondedPet) + { + Action = ActionType.Wander; + return true; + } + + m_Mobile.Direction = m_Mobile.GetDirectionTo(c); + if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, c)) + { + if (m_Mobile.Debug) { - Action = ActionType.Wander; - } - else - { - m_Mobile.Direction = m_Mobile.GetDirectionTo(c); + m_Mobile.DebugSay($"I used my abilities on {c.Name}!"); } } diff --git a/Projects/UOContent/Mobiles/AI/BerserkAI.cs b/Projects/UOContent/Mobiles/AI/BerserkAI.cs index d43449938..e356c6c33 100644 --- a/Projects/UOContent/Mobiles/AI/BerserkAI.cs +++ b/Projects/UOContent/Mobiles/AI/BerserkAI.cs @@ -72,6 +72,14 @@ public class BerserkAI : BaseAI } } + if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, m_Mobile.Combatant)) + { + if (m_Mobile.Debug) + { + m_Mobile.DebugSay($"I used my abilities on {m_Mobile.Combatant.Name}!"); + } + } + return true; } @@ -94,4 +102,4 @@ public class BerserkAI : BaseAI return true; } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/AI/HealerAI.cs b/Projects/UOContent/Mobiles/AI/HealerAI.cs index a44580f01..6cb49ff31 100644 --- a/Projects/UOContent/Mobiles/AI/HealerAI.cs +++ b/Projects/UOContent/Mobiles/AI/HealerAI.cs @@ -49,54 +49,65 @@ public class HealerAI : BaseAI { targ.Cancel(m_Mobile, TargetCancelType.Canceled); } + + return true; } - else + + var toHelp = Find(m_All); + + if (toHelp != null) { - var toHelp = Find(m_All); - - if (toHelp != null) + if (NeedCure(toHelp)) { - if (NeedCure(toHelp)) + if (m_Mobile.Debug) { - if (m_Mobile.Debug) - { - m_Mobile.DebugSay($"{toHelp.Name} needs a cure"); - } - - if (!new CureSpell(m_Mobile).Cast()) - { - new CureSpell(m_Mobile).Cast(); - } + m_Mobile.DebugSay($"{toHelp.Name} needs a cure"); } - else if (NeedGHeal(toHelp)) - { - if (m_Mobile.Debug) - { - m_Mobile.DebugSay("{toHelp.Name} needs a greater heal"); - } - if (!new GreaterHealSpell(m_Mobile).Cast()) - { - new HealSpell(m_Mobile).Cast(); - } + if (!new CureSpell(m_Mobile).Cast()) + { + new CureSpell(m_Mobile).Cast(); } - else if (NeedLHeal(toHelp)) + } + else if (NeedGHeal(toHelp)) + { + if (m_Mobile.Debug) { - if (m_Mobile.Debug) - { - m_Mobile.DebugSay("{toHelp.Name} needs a lesser heal"); - } + m_Mobile.DebugSay($"{toHelp.Name} needs a greater heal"); + } + if (!new GreaterHealSpell(m_Mobile).Cast()) + { new HealSpell(m_Mobile).Cast(); } } - else if (AcquireFocusMob(m_Mobile.RangePerception, FightMode.Weakest, false, true, false)) + else if (NeedLHeal(toHelp)) { - WalkMobileRange(m_Mobile.FocusMob, 1, false, 4, 7); + if (m_Mobile.Debug) + { + m_Mobile.DebugSay($"{toHelp.Name} needs a lesser heal"); + } + + new HealSpell(m_Mobile).Cast(); } - else + + return true; + } + + if (!AcquireFocusMob(m_Mobile.RangePerception, FightMode.Weakest, false, true, false)) + { + WalkRandomInHome(3, 2, 1); + return true; + } + + WalkMobileRange(m_Mobile.FocusMob, 1, false, 4, 7); + + // TODO: Should it be able to do this? + if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, m_Mobile.Combatant)) + { + if (m_Mobile.Debug) { - WalkRandomInHome(3, 2, 1); + m_Mobile.DebugSay($"I used my abilities on {m_Mobile.Combatant.Name}!"); } } diff --git a/Projects/UOContent/Mobiles/AI/MageAI.cs b/Projects/UOContent/Mobiles/AI/MageAI.cs index 4201729c9..fedf7d2ae 100644 --- a/Projects/UOContent/Mobiles/AI/MageAI.cs +++ b/Projects/UOContent/Mobiles/AI/MageAI.cs @@ -685,14 +685,15 @@ public class MageAI : BaseAI if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) { + m_Mobile.Combatant = c = m_Mobile.FocusMob!; + if (m_Mobile.Debug) { m_Mobile.DebugSay( - $"Something happened to my combatant, so I am going to fight {m_Mobile.FocusMob.Name}" + $"Something happened to my combatant, so I am going to fight {c.Name}" ); } - m_Mobile.Combatant = c = m_Mobile.FocusMob; m_Mobile.FocusMob = null; } else @@ -716,12 +717,13 @@ public class MageAI : BaseAI if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) { + m_Mobile.Combatant = c = m_Mobile.FocusMob!; + if (m_Mobile.Debug) { - m_Mobile.DebugSay($"I will switch to {m_Mobile.FocusMob.Name}"); + m_Mobile.DebugSay($"I will switch to {c.Name}"); } - m_Mobile.Combatant = c = m_Mobile.FocusMob; m_Mobile.FocusMob = null; } } @@ -778,7 +780,14 @@ public class MageAI : BaseAI } } - if (m_Mobile.Spell == null && Core.TickCount - m_NextCastTime >= 0 && m_Mobile.InRange(c, Core.ML ? 10 : 12)) + if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, c)) + { + if (m_Mobile.Debug) + { + m_Mobile.DebugSay("I used my abilities!"); + } + } + else if (m_Mobile.Spell == null && Core.TickCount - m_NextCastTime >= 0 && m_Mobile.InRange(c, Core.ML ? 10 : 12)) { // We are ready to cast a spell Spell spell; diff --git a/Projects/UOContent/Mobiles/AI/MeleeAI.cs b/Projects/UOContent/Mobiles/AI/MeleeAI.cs index e3ef2da4d..9f58a7c83 100644 --- a/Projects/UOContent/Mobiles/AI/MeleeAI.cs +++ b/Projects/UOContent/Mobiles/AI/MeleeAI.cs @@ -46,7 +46,6 @@ public class MeleeAI : BaseAI } Action = ActionType.Guard; - return true; } @@ -74,7 +73,6 @@ public class MeleeAI : BaseAI } Action = ActionType.Guard; - return true; } } @@ -90,7 +88,6 @@ public class MeleeAI : BaseAI m_Mobile.Combatant = m_Mobile.FocusMob; Action = ActionType.Combat; - return true; } @@ -102,7 +99,6 @@ public class MeleeAI : BaseAI } Action = ActionType.Guard; - return true; } @@ -127,10 +123,19 @@ public class MeleeAI : BaseAI } Action = ActionType.Flee; + return true; } } } + if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant)) + { + if (m_Mobile.Debug) + { + m_Mobile.DebugSay("I used my abilities!"); + } + } + return true; } @@ -173,4 +178,4 @@ public class MeleeAI : BaseAI return true; } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/AI/PredatorAI.cs b/Projects/UOContent/Mobiles/AI/PredatorAI.cs index bdfd5d890..e65c42cfc 100644 --- a/Projects/UOContent/Mobiles/AI/PredatorAI.cs +++ b/Projects/UOContent/Mobiles/AI/PredatorAI.cs @@ -68,6 +68,14 @@ public class PredatorAI : BaseAI } } + if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant)) + { + if (m_Mobile.Debug) + { + m_Mobile.DebugSay($"I used my abilities on {combatant.Name}!"); + } + } + return true; } @@ -101,4 +109,4 @@ public class PredatorAI : BaseAI return true; } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/AI/ThiefAI.cs b/Projects/UOContent/Mobiles/AI/ThiefAI.cs index 486e905f2..5d701e8c2 100644 --- a/Projects/UOContent/Mobiles/AI/ThiefAI.cs +++ b/Projects/UOContent/Mobiles/AI/ThiefAI.cs @@ -48,7 +48,6 @@ public class ThiefAI : BaseAI } Action = ActionType.Guard; - return true; } @@ -86,90 +85,69 @@ public class ThiefAI : BaseAI } else if (m_toDisarm == null && Core.TickCount - m_Mobile.NextSkillTime >= 0) { - var cpack = combatant.Backpack; - - if (cpack != null) + if (m_Mobile.Debug) { - Item steala = cpack.FindItemByType(); - if (steala != null) - { - if (m_Mobile.Debug) - { - m_Mobile.DebugSay("Trying to steal from combatant."); - } + m_Mobile.DebugSay($"Trying to steal from {combatant.Name}."); + } - m_Mobile.UseSkill(SkillName.Stealing); - m_Mobile.Target?.Invoke(m_Mobile, steala); + bool didSteal = TryStealFrom(combatant); + didSteal = TryStealFrom(combatant) || didSteal; + didSteal = TryStealFrom(combatant) || didSteal; + didSteal = TryStealFrom(combatant) || didSteal; + + if (!didSteal) + { + if (m_Mobile.Debug) + { + m_Mobile.DebugSay($"I am going to flee from {combatant.Name}"); } - Item stealb = cpack.FindItemByType(); - if (stealb != null) - { - if (m_Mobile.Debug) - { - m_Mobile.DebugSay("Trying to steal from combatant."); - } - - m_Mobile.UseSkill(SkillName.Stealing); - m_Mobile.Target?.Invoke(m_Mobile, stealb); - } - - Item stealc = cpack.FindItemByType(); - if (stealc != null) - { - if (m_Mobile.Debug) - { - m_Mobile.DebugSay("Trying to steal from combatant."); - } - - m_Mobile.UseSkill(SkillName.Stealing); - m_Mobile.Target?.Invoke(m_Mobile, stealc); - } - - Item steald = cpack.FindItemByType(); - if (steald != null) - { - if (m_Mobile.Debug) - { - m_Mobile.DebugSay("Trying to steal from combatant."); - } - - m_Mobile.UseSkill(SkillName.Stealing); - m_Mobile.Target?.Invoke(m_Mobile, steald); - } - else if (steala == null && stealb == null && stealc == null) - { - if (m_Mobile.Debug) - { - m_Mobile.DebugSay($"I am going to flee from {combatant.Name}"); - } - - Action = ActionType.Flee; - } + Action = ActionType.Flee; + return true; } } } - if (m_Mobile.Hits >= m_Mobile.HitsMax * 20 / 100 || !m_Mobile.CanFlee) + // We are low on health, should we flee? + // (10 + diff)% chance to flee + if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100 && m_Mobile.CanFlee) { + var fleeChance = 10 + Math.Max(0, combatant.Hits - m_Mobile.Hits); + + if (Utility.Random(0, 100) > fleeChance) + { + if (m_Mobile.Debug) + { + m_Mobile.DebugSay($"I am going to flee from {combatant.Name}"); + } + + Action = ActionType.Flee; + } + return true; } - // We are low on health, should we flee? - // (10 + diff)% chance to flee - var fleeChance = 10 + Math.Max(0, combatant.Hits - m_Mobile.Hits); - - if (Utility.Random(0, 100) > fleeChance) + if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, m_Mobile.Combatant)) { if (m_Mobile.Debug) { - m_Mobile.DebugSay($"I am going to flee from {combatant.Name}"); + m_Mobile.DebugSay($"I used my abilities on {m_Mobile.Combatant.Name}!"); } + } + return true; + } - Action = ActionType.Flee; + private bool TryStealFrom(Mobile combatant) where T : Item + { + Item steal = combatant.Backpack?.FindItemByType(); + if (steal != null) + { + m_Mobile.UseSkill(SkillName.Stealing); + m_Mobile.Target?.Invoke(m_Mobile, steal); + return true; } - return true; + return false; } public override bool DoActionGuard() @@ -211,4 +189,4 @@ public class ThiefAI : BaseAI return true; } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/BaseCreature.cs b/Projects/UOContent/Mobiles/BaseCreature.cs index a1799eeb9..092383d94 100644 --- a/Projects/UOContent/Mobiles/BaseCreature.cs +++ b/Projects/UOContent/Mobiles/BaseCreature.cs @@ -1159,23 +1159,27 @@ namespace Server.Mobiles return false; } - public virtual void TriggerAbility(MonsterAbilityTrigger trigger, Mobile defender) + public virtual bool TriggerAbility(MonsterAbilityTrigger trigger, Mobile defender) { var abilities = GetMonsterAbilities(); if (abilities == null) { - return; + return false; } + var triggered = false; for (var i = 0; i < abilities.Length; i++) { var ability = abilities[i]; if (ability.WillTrigger(trigger) && ability.CanTrigger(this, trigger)) { ability.Trigger(trigger, this, defender); + triggered = true; } } + + return triggered; } public virtual void TriggerAbilityMove(MonsterAbilityTrigger trigger, Mobile defender, Direction d)