Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes more potion throwing edge cases #1852

Merged
merged 1 commit into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions Projects/UOContent/Items/Misc/Firebomb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ public partial class Firebomb : Item
private Point3D _thrownFromLocation;
private int _ticks;
private TimerExecutionToken _timerToken;
private List<Mobile> _users;
private HashSet<Mobile> _users;

[Constructible]
public Firebomb(int itemID = 0x99B) : base(itemID)
{
// Name = "a firebomb";
Weight = 2.0;
Hue = 1260;
}
Expand Down Expand Up @@ -51,12 +50,8 @@ public override void OnDoubleClick(Mobile from)
from.SendLocalizedMessage(1060582); // You light the firebomb. Throw it now!
}

_users ??= new List<Mobile>();

if (!_users.Contains(from))
{
_users.Add(from);
}
_users ??= [];
_users.Add(from);

from.Target = new ThrowTarget(this);
}
Expand Down Expand Up @@ -101,18 +96,23 @@ private void OnFirebombTimerTick()
{
HeldBy?.DropHolding();

if (_users != null)
if (_users is { Count: > 0 })
{
foreach (var m in _users)
using var usersQueue = PooledRefQueue<Mobile>.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)
Expand Down Expand Up @@ -201,5 +201,7 @@ private class ThrowTarget : Target
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public BasePotion(int itemID, PotionEffect effect) : base(itemID)

public virtual bool RequireFreeHand => true;

public virtual bool IsThrowablePotion => false;

int ICommodity.DescriptionNumber => LabelNumber;
bool ICommodity.IsDeedable => Core.ML;

Expand Down Expand Up @@ -144,9 +146,11 @@ public override void OnDoubleClick(Mobile from)
return;
}

if (this is BaseExplosionPotion && Amount > 1)
var pot = this;

if (IsThrowablePotion && Amount > 1)
{
var pot = GetType().CreateInstance<BaseExplosionPotion>();
pot = GetType().CreateInstance<BasePotion>();

Amount--;

Expand All @@ -158,13 +162,9 @@ public override void OnDoubleClick(Mobile from)
{
pot.MoveToWorld(from.Location, from.Map);
}

pot.Drink(from);
}
else
{
Drink(from);
}

pot.Drink(from);
}

private void Deserialize(IGenericReader reader, int version)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ namespace Server.Items;
[SerializationGenerator(0, false)]
public abstract partial class BaseConflagrationPotion : BasePotion
{
private static readonly Dictionary<Mobile, TimerExecutionToken> m_Delay = new();
private readonly List<Mobile> m_Users = new();
private static readonly Dictionary<Mobile, TimerExecutionToken> _delay = [];
private HashSet<Mobile> _users;

public BaseConflagrationPotion(PotionEffect effect) : base(0xF06, effect) => Hue = 0x489;

Expand All @@ -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))
Expand All @@ -37,17 +39,15 @@ public override void Drink(Mobile from)
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);
}
Expand All @@ -62,11 +62,22 @@ public virtual void Explode(Mobile from, Point3D loc, Map map)
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<Mobile>.Create();
foreach (var user in _users)
{
if ((user.Target as ThrowTarget)?.Potion == this)
{
usersQueue.Enqueue(user);
}
}

_users.Clear();

while (usersQueue.Count > 0)
{
Target.Cancel(from);
Target.Cancel(usersQueue.Dequeue());
}
}

Expand All @@ -89,16 +100,16 @@ public virtual void Explode(Mobile from, Point3D loc, Map map)

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);
}
Expand All @@ -108,7 +119,7 @@ public static int GetDelay(Mobile m)

public static void EndDelay(Mobile m)
{
if (m_Delay.Remove(m, out var timer))
if (_delay.Remove(m, out var timer))
{
timer.Cancel();
}
Expand Down Expand Up @@ -155,6 +166,8 @@ protected override void OnTarget(Mobile from, object targeted)
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)]
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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))
Expand All @@ -37,14 +40,14 @@ public override void Drink(Mobile from)
return;
}

if (from.Target is ThrowTarget targ && targ.Potion == this)
if ((from.Target as ThrowTarget)?.Potion == this)
{
return;
}

from.RevealingAction();

_users ??= new HashSet<Mobile>();
_users ??= [];
_users.Add(from);

from.Target = new ThrowTarget(this);
Expand All @@ -59,18 +62,23 @@ public virtual void Explode(Mobile from, Point3D loc, Map map)

Consume();

if (_users != null)
if (_users is { Count: > 0 })
{
// Check if any other players are using this potion
using var usersQueue = PooledRefQueue<Mobile>.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
Expand Down Expand Up @@ -170,5 +178,7 @@ protected override void OnTarget(Mobile from, object targeted)
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public BaseExplosionPotion(PotionEffect effect) : base(0xF0D, effect)

public override bool RequireFreeHand => false;

public override bool IsThrowablePotion => true;

private HashSet<Mobile> _users;

public virtual IEntity FindParent(Mobile from)
Expand Down Expand Up @@ -67,7 +69,7 @@ public override void Drink(Mobile from)

from.RevealingAction();

_users ??= new HashSet<Mobile>();
_users ??= [];
_users.Add(from);

from.Target = new ThrowTarget(this);
Expand Down Expand Up @@ -115,17 +117,23 @@ public void Explode(Mobile from, bool direct, Point3D loc, Map map)

Consume();

if (_users != null)
if (_users is { Count: > 0 })
{
using var usersQueue = PooledRefQueue<Mobile>.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)
Expand Down Expand Up @@ -259,6 +267,8 @@ protected override void OnTarget(Mobile from, object targeted)

Timer.StartTimer(delay, () => Potion.Reposition_OnTick(from, loc, map));
}

protected override void OnTargetFinish(Mobile from) => Potion._users.Remove(from);
}

private class DetonateTimer : Timer
Expand Down
Loading