From ac3e4fcc97807a53501b014ec726b83ad17aecf2 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Wed, 3 Jul 2024 18:04:03 -0700 Subject: [PATCH] Fixes more potion throwing edge cases (#1852) --- Projects/UOContent/Items/Misc/Firebomb.cs | 28 +++++++------ .../Skill Items/Magical/Potions/BasePotion.cs | 16 ++++---- .../BaseConflagrationPotion.cs | 41 ++++++++++++------- .../BaseConfusionBlastPotion.cs | 20 ++++++--- .../Explosion Potions/BaseExplosionPotion.cs | 16 ++++++-- 5 files changed, 78 insertions(+), 43 deletions(-) diff --git a/Projects/UOContent/Items/Misc/Firebomb.cs b/Projects/UOContent/Items/Misc/Firebomb.cs index de846f3ca..89545a8ad 100644 --- a/Projects/UOContent/Items/Misc/Firebomb.cs +++ b/Projects/UOContent/Items/Misc/Firebomb.cs @@ -15,12 +15,11 @@ public partial class Firebomb : Item private Point3D _thrownFromLocation; private int _ticks; private TimerExecutionToken _timerToken; - private List _users; + private HashSet _users; [Constructible] public Firebomb(int itemID = 0x99B) : base(itemID) { - // Name = "a firebomb"; Weight = 2.0; Hue = 1260; } @@ -51,12 +50,8 @@ public partial class Firebomb : Item from.SendLocalizedMessage(1060582); // You light the firebomb. Throw it now! } - _users ??= new List(); - - if (!_users.Contains(from)) - { - _users.Add(from); - } + _users ??= []; + _users.Add(from); from.Target = new ThrowTarget(this); } @@ -101,18 +96,23 @@ public partial class Firebomb : Item { HeldBy?.DropHolding(); - if (_users != null) + if (_users is { Count: > 0 }) { - foreach (var m in _users) + using var usersQueue = PooledRefQueue.Create(); + foreach (var user in _users) { - if (m.Target is ThrowTarget targ && targ.Bomb == this) + if ((user.Target as ThrowTarget)?.Bomb == this) { - Target.Cancel(m); + usersQueue.Enqueue(user); } } _users.Clear(); - _users = null; + + while (usersQueue.Count > 0) + { + Target.Cancel(usersQueue.Dequeue()); + } } if (RootParent is Mobile parent) @@ -201,5 +201,7 @@ public partial class Firebomb : Item public Firebomb Bomb { get; } protected override void OnTarget(Mobile from, object targeted) => Bomb.OnFirebombTarget(from, targeted); + + protected override void OnTargetFinish(Mobile from) => Bomb._users.Remove(from); } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/BasePotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/BasePotion.cs index b395d41e1..54b6bfa6a 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/BasePotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/BasePotion.cs @@ -57,6 +57,8 @@ public abstract partial class BasePotion : Item, ICraftable, ICommodity public virtual bool RequireFreeHand => true; + public virtual bool IsThrowablePotion => false; + int ICommodity.DescriptionNumber => LabelNumber; bool ICommodity.IsDeedable => Core.ML; @@ -144,9 +146,11 @@ public abstract partial class BasePotion : Item, ICraftable, ICommodity return; } - if (this is BaseExplosionPotion && Amount > 1) + var pot = this; + + if (IsThrowablePotion && Amount > 1) { - var pot = GetType().CreateInstance(); + pot = GetType().CreateInstance(); Amount--; @@ -158,13 +162,9 @@ public abstract partial class BasePotion : Item, ICraftable, ICommodity { pot.MoveToWorld(from.Location, from.Map); } + } - pot.Drink(from); - } - else - { - Drink(from); - } + pot.Drink(from); } private void Deserialize(IGenericReader reader, int version) diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/BaseConflagrationPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/BaseConflagrationPotion.cs index 3004c9e56..2927e795e 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/BaseConflagrationPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/BaseConflagrationPotion.cs @@ -10,8 +10,8 @@ namespace Server.Items; [SerializationGenerator(0, false)] public abstract partial class BaseConflagrationPotion : BasePotion { - private static readonly Dictionary m_Delay = new(); - private readonly List m_Users = new(); + private static readonly Dictionary _delay = []; + private HashSet _users; public BaseConflagrationPotion(PotionEffect effect) : base(0xF06, effect) => Hue = 0x489; @@ -20,6 +20,8 @@ public abstract partial class BaseConflagrationPotion : BasePotion public override bool RequireFreeHand => false; + public override bool IsThrowablePotion => true; + public override void Drink(Mobile from) { if (Core.AOS && (from.Paralyzed || from.Frozen || from.Spell?.IsCasting == true)) @@ -37,17 +39,15 @@ public abstract partial class BaseConflagrationPotion : BasePotion return; } - if (from.Target is ThrowTarget targ && targ.Potion == this) + if ((from.Target as ThrowTarget)?.Potion == this) { return; } from.RevealingAction(); - if (!m_Users.Contains(from)) - { - m_Users.Add(from); - } + _users ??= []; + _users.Add(from); from.Target = new ThrowTarget(this); } @@ -62,11 +62,22 @@ public abstract partial class BaseConflagrationPotion : BasePotion Consume(); // Check if any other players are using this potion - for (var i = 0; i < m_Users.Count; i++) + if (_users is { Count: > 0 }) { - if (m_Users[i].Target is ThrowTarget targ && targ.Potion == this) + using var usersQueue = PooledRefQueue.Create(); + foreach (var user in _users) { - Target.Cancel(from); + if ((user.Target as ThrowTarget)?.Potion == this) + { + usersQueue.Enqueue(user); + } + } + + _users.Clear(); + + while (usersQueue.Count > 0) + { + Target.Cancel(usersQueue.Dequeue()); } } @@ -89,16 +100,16 @@ public abstract partial class BaseConflagrationPotion : BasePotion public static void AddDelay(Mobile m) { - m_Delay.TryGetValue(m, out var timer); + _delay.TryGetValue(m, out var timer); timer.Cancel(); Timer.StartTimer(TimeSpan.FromSeconds(30), () => EndDelay(m), out timer); - m_Delay[m] = timer; + _delay[m] = timer; } public static int GetDelay(Mobile m) { - if (m_Delay.TryGetValue(m, out var timer) && timer.Next > Core.Now) + if (_delay.TryGetValue(m, out var timer) && timer.Next > Core.Now) { return (int)Math.Round((timer.Next - Core.Now).TotalSeconds); } @@ -108,7 +119,7 @@ public abstract partial class BaseConflagrationPotion : BasePotion public static void EndDelay(Mobile m) { - if (m_Delay.Remove(m, out var timer)) + if (_delay.Remove(m, out var timer)) { timer.Cancel(); } @@ -155,6 +166,8 @@ public abstract partial class BaseConflagrationPotion : BasePotion Effects.SendMovingEffect(from, to, 0xF0D, 7, 0, false, false, Potion.Hue); Timer.StartTimer(TimeSpan.FromSeconds(1.5), () => Potion.Explode(from, loc, map)); } + + protected override void OnTargetFinish(Mobile from) => Potion._users.Remove(from); } [SerializationGenerator(0, false)] diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/BaseConfusionBlastPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/BaseConfusionBlastPotion.cs index 77d812fcb..ff556019c 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/BaseConfusionBlastPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/BaseConfusionBlastPotion.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using ModernUO.Serialization; +using Server.Collections; using Server.Misc; using Server.Mobiles; using Server.Spells; @@ -20,6 +21,8 @@ public abstract partial class BaseConfusionBlastPotion : BasePotion public override bool RequireFreeHand => false; + public override bool IsThrowablePotion => true; + public override void Drink(Mobile from) { if (Core.AOS && (from.Paralyzed || from.Frozen || from.Spell?.IsCasting == true)) @@ -37,14 +40,14 @@ public abstract partial class BaseConfusionBlastPotion : BasePotion return; } - if (from.Target is ThrowTarget targ && targ.Potion == this) + if ((from.Target as ThrowTarget)?.Potion == this) { return; } from.RevealingAction(); - _users ??= new HashSet(); + _users ??= []; _users.Add(from); from.Target = new ThrowTarget(this); @@ -59,18 +62,23 @@ public abstract partial class BaseConfusionBlastPotion : BasePotion Consume(); - if (_users != null) + if (_users is { Count: > 0 }) { - // Check if any other players are using this potion + using var usersQueue = PooledRefQueue.Create(); foreach (var user in _users) { if ((user.Target as ThrowTarget)?.Potion == this) { - Target.Cancel(from); + usersQueue.Enqueue(user); } } _users.Clear(); + + while (usersQueue.Count > 0) + { + Target.Cancel(usersQueue.Dequeue()); + } } // Effects @@ -170,5 +178,7 @@ public abstract partial class BaseConfusionBlastPotion : BasePotion Effects.SendMovingEffect(from, to, 0xF0D, 7, 0, false, false, Potion.Hue); Timer.StartTimer(TimeSpan.FromSeconds(1.0), () => Potion.Explode(from, loc, map)); } + + protected override void OnTargetFinish(Mobile from) => Potion._users.Remove(from); } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs index 055248b2d..bed396f2c 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs @@ -27,6 +27,8 @@ public abstract partial class BaseExplosionPotion : BasePotion public override bool RequireFreeHand => false; + public override bool IsThrowablePotion => true; + private HashSet _users; public virtual IEntity FindParent(Mobile from) @@ -67,7 +69,7 @@ public abstract partial class BaseExplosionPotion : BasePotion from.RevealingAction(); - _users ??= new HashSet(); + _users ??= []; _users.Add(from); from.Target = new ThrowTarget(this); @@ -115,17 +117,23 @@ public abstract partial class BaseExplosionPotion : BasePotion Consume(); - if (_users != null) + if (_users is { Count: > 0 }) { + using var usersQueue = PooledRefQueue.Create(); foreach (var user in _users) { if ((user.Target as ThrowTarget)?.Potion == this) { - Target.Cancel(user); + usersQueue.Enqueue(user); } } _users.Clear(); + + while (usersQueue.Count > 0) + { + Target.Cancel(usersQueue.Dequeue()); + } } if (map == null) @@ -259,6 +267,8 @@ public abstract partial class BaseExplosionPotion : BasePotion Timer.StartTimer(delay, () => Potion.Reposition_OnTick(from, loc, map)); } + + protected override void OnTargetFinish(Mobile from) => Potion._users.Remove(from); } private class DetonateTimer : Timer