diff --git a/Projects/UOContent/Engines/Virtues/HonorContext.cs b/Projects/UOContent/Engines/Virtues/HonorContext.cs index 8e2ba1a13..85ebfa8a2 100644 --- a/Projects/UOContent/Engines/Virtues/HonorContext.cs +++ b/Projects/UOContent/Engines/Virtues/HonorContext.cs @@ -1,4 +1,5 @@ using System; +using ModernUO.CodeGeneratedEvents; using Server.Mobiles; namespace Server.Engines.Virtues; diff --git a/Projects/UOContent/Mobiles/Abilities/MonsterAbility.cs b/Projects/UOContent/Mobiles/Abilities/MonsterAbility.cs index 72fb61ec3..fc227507e 100644 --- a/Projects/UOContent/Mobiles/Abilities/MonsterAbility.cs +++ b/Projects/UOContent/Mobiles/Abilities/MonsterAbility.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; +using ModernUO.CodeGeneratedEvents; namespace Server.Mobiles; /// /// Abstract class used to build singletons for managing a specific monster ability. /// -public abstract partial class MonsterAbility +public abstract class MonsterAbility { private Dictionary _nextTriggerTicks; @@ -18,39 +19,34 @@ public abstract partial class MonsterAbility public virtual TimeSpan MinTriggerCooldown => TimeSpan.Zero; public virtual TimeSpan MaxTriggerCooldown => TimeSpan.Zero; - public bool WillTrigger(MonsterAbilityTrigger trigger) => (AbilityTrigger & trigger) != 0; - /// /// Returns true if ability is not on cooldown, and the chance to trigger succeeds. /// /// Boolean indicating the ability can trigger. public virtual bool CanTrigger(BaseCreature source, MonsterAbilityTrigger trigger) { - if (source is not { Alive: true, Deleted: false }) + if ((AbilityTrigger & trigger) == 0 || source is not { Alive: true, Deleted: false }) { return false; } - if (_nextTriggerTicks?.TryGetValue(source, out var nextTrigger) == true && nextTrigger - Core.TickCount > 0) + if (_nextTriggerTicks?.TryGetValue(source, out var nextTrigger) == true) { - return false; + if (nextTrigger - Core.TickCount > 0) + { + return false; + } + + _nextTriggerTicks.Remove(source); + if (_nextTriggerTicks.Count == 0) + { + _nextTriggerTicks = null; + } } var c = ChanceToTrigger; - if (c >= 1) - { - return true; - } - - if (c <= 0) - { - return false; - } - - var rnd = Utility.RandomDouble(); - - return c > rnd; + return c >= 1 || c > 0 && c > Utility.RandomDouble(); } /// @@ -99,7 +95,23 @@ public abstract partial class MonsterAbility { } - public virtual void Move(BaseCreature creature, Direction d) + public virtual void Move(BaseCreature source, Direction d) { } + + [OnEvent(nameof(BaseCreature.CreatureDeathEvent))] + [OnEvent(nameof(BaseCreature.CreatureDeletedEvent))] + public static void InvalidateNextAbilityTriggers(BaseCreature source) + { + var abilities = source.GetMonsterAbilities(); + if (abilities == null || abilities.Length == 0) + { + return; + } + + for (var i = 0; i < abilities.Length; i++) + { + abilities[i]._nextTriggerTicks?.Remove(source); + } + } } diff --git a/Projects/UOContent/Mobiles/Abilities/MonsterAbilityGroup.cs b/Projects/UOContent/Mobiles/Abilities/MonsterAbilityGroup.cs index c431d4d35..6555a3682 100644 --- a/Projects/UOContent/Mobiles/Abilities/MonsterAbilityGroup.cs +++ b/Projects/UOContent/Mobiles/Abilities/MonsterAbilityGroup.cs @@ -1,15 +1,14 @@ using System; -using Server.Random; using WeightedMonsterAbility = Server.Random.WeightedValue; namespace Server.Mobiles; public class MonsterAbilityGroup : MonsterAbility { - private WeightedMonsterAbility[] _weightedAbilities; - private WeightedMonsterAbility[] _availableToTrigger; + private readonly WeightedMonsterAbility[] _weightedAbilities; + private readonly WeightedMonsterAbility[] _availableToTrigger; + private readonly MonsterAbilityTrigger _triggers; private int _availableToTriggerCount; - private MonsterAbilityTrigger _triggers; public MonsterAbilityGroup(params WeightedMonsterAbility[] weightedAbilities) { @@ -18,8 +17,7 @@ public class MonsterAbilityGroup : MonsterAbility for (var i = 0; i < _weightedAbilities.Length; i++) { - var weightedAbility = _weightedAbilities[i]; - _triggers |= weightedAbility.Value.AbilityTrigger; + _triggers |= _weightedAbilities[i].Value.AbilityTrigger; } } @@ -66,7 +64,7 @@ public class MonsterAbilityGroup : MonsterAbility for (var i = 0; i < _weightedAbilities.Length; i++) { var weightedAbility = _weightedAbilities[i]; - if (weightedAbility.Value.WillTrigger(trigger) && weightedAbility.Value.CanTrigger(source, trigger)) + if (weightedAbility.Value.CanTrigger(source, trigger)) { _availableToTrigger[_availableToTriggerCount++] = weightedAbility; } @@ -83,7 +81,7 @@ public class MonsterAbilityGroup : MonsterAbility return; } - var slice = new ReadOnlySpan>(_availableToTrigger, 0, _availableToTriggerCount); + var slice = new ReadOnlySpan(_availableToTrigger, 0, _availableToTriggerCount); var chosenAbility = slice.RandomWeightedElement().Value; // Just in case? diff --git a/Projects/UOContent/Mobiles/Abilities/ReflectPhysicalDamage.cs b/Projects/UOContent/Mobiles/Abilities/ReflectPhysicalDamage.cs index ae66734ba..3aa48960f 100644 --- a/Projects/UOContent/Mobiles/Abilities/ReflectPhysicalDamage.cs +++ b/Projects/UOContent/Mobiles/Abilities/ReflectPhysicalDamage.cs @@ -8,4 +8,8 @@ public class ReflectPhysicalDamage : MonsterAbility public override MonsterAbilityType AbilityType => MonsterAbilityType.ReflectPhysicalDamage; public virtual int PercentReflected => 10; + + public override void Trigger(MonsterAbilityTrigger trigger, BaseCreature source, Mobile target) + { + } } diff --git a/Projects/UOContent/Mobiles/BaseCreature.cs b/Projects/UOContent/Mobiles/BaseCreature.cs index ed37b7be1..22c43ebc4 100644 --- a/Projects/UOContent/Mobiles/BaseCreature.cs +++ b/Projects/UOContent/Mobiles/BaseCreature.cs @@ -1216,7 +1216,7 @@ namespace Server.Mobiles for (var i = 0; i < abilities.Length; i++) { var ability = abilities[i]; - if (ability.WillTrigger(trigger) && ability.CanTrigger(this, trigger)) + if (ability.CanTrigger(this, trigger)) { ability.Trigger(trigger, this, defender); triggered = true; @@ -1238,7 +1238,7 @@ namespace Server.Mobiles for (var i = 0; i < abilities.Length; i++) { var ability = abilities[i]; - if (ability.WillTrigger(trigger) && ability.CanTrigger(this, trigger)) + if (ability.CanTrigger(this, trigger)) { ability.Move(this, d); } @@ -1257,7 +1257,7 @@ namespace Server.Mobiles for (var i = 0; i < abilities.Length; i++) { var ability = abilities[i]; - if (ability.WillTrigger(trigger) && ability.CanTrigger(this, trigger)) + if (ability.CanTrigger(this, trigger)) { if ((trigger & MonsterAbilityTrigger.GiveMeleeDamage) != 0) { @@ -1298,7 +1298,7 @@ namespace Server.Mobiles for (var i = 0; i < abilities.Length; i++) { var ability = abilities[i]; - if (ability.WillTrigger(trigger) && ability.CanTrigger(this, trigger)) + if (ability.CanTrigger(this, trigger)) { if ((trigger & MonsterAbilityTrigger.GiveSpellDamage) != 0) { @@ -3263,7 +3263,7 @@ namespace Server.Mobiles } [GeneratedEvent(nameof(CreatureDeathEvent))] - public static partial void CreatureDeathEvent(Mobile m); + public static partial void CreatureDeathEvent(BaseCreature bc); public override void OnDeath(Container c) { @@ -3454,8 +3454,13 @@ namespace Server.Mobiles CreatureDeathEvent(this); } + [GeneratedEvent(nameof(CreatureDeletedEvent))] + public static partial void CreatureDeletedEvent(BaseCreature bc); + public override void OnDelete() { + CreatureDeletedEvent(this); + var m = m_ControlMaster; SetControlMaster(null);