fix: Fixes crash when banker tries to consume checks & gold from bankbox (#1635)

Co-authored-by: Stefano Merotta <97297186+stefanomerotta@users.noreply.github.com>
Co-authored-by: Kamron Batman <3953314+kamronbatman@users.noreply.github.com>
This commit is contained in:
Eric Vintimilla 2023-12-15 12:13:21 -05:00 • committed by GitHub
parent c487aab3f9
commit 0d65464c9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using ModernUO.Serialization; using ModernUO.Serialization;
using Server.Accounting; using Server.Accounting;
using Server.Collections;
using Server.ContextMenus; using Server.ContextMenus;
using Server.Items; using Server.Items;
using Server.Network; using Server.Network;
@ -63,10 +64,11 @@ public partial class Banker : BaseVendor
return (int)Math.Clamp(balance, 0, int.MaxValue); return (int)Math.Clamp(balance, 0, int.MaxValue);
} }
public static int GetBalance(Mobile m, out List<Item> gold, out List<Item> checks) public static int GetBalance(Mobile m, out List<Gold> gold, out List<BankCheck> checks)
{ {
long balance = 0; long balance = 0;
gold = checks = new List<Item>(); gold = null;
checks = null;
if (AccountGold.Enabled && m.Account != null) if (AccountGold.Enabled && m.Account != null)
{ {
@ -82,6 +84,8 @@ public partial class Banker : BaseVendor
if (bank != null) if (bank != null)
{ {
gold = new List<Gold>();
foreach (var g in bank.FindItemsByType<Gold>()) foreach (var g in bank.FindItemsByType<Gold>())
{ {
balance += g.Amount; balance += g.Amount;
@ -93,6 +97,8 @@ public partial class Banker : BaseVendor
return int.MaxValue; return int.MaxValue;
} }
checks = new List<BankCheck>();
foreach (var bc in bank.FindItemsByType<BankCheck>()) foreach (var bc in bank.FindItemsByType<BankCheck>())
{ {
balance += bc.Worth; balance += bc.Worth;
@ -103,6 +109,52 @@ public partial class Banker : BaseVendor
return (int)Math.Clamp(balance, 0, int.MaxValue); return (int)Math.Clamp(balance, 0, int.MaxValue);
} }
private static bool HasRequiredBalance(int requiredBalance, Mobile m, out PooledRefList<Gold> gold, out PooledRefList<BankCheck> checks)
{
Container bank = m.FindBankNoCreate();
if (bank == null)
{
gold = default;
checks = default;
return false;
}
long balance = 0;
gold = PooledRefList<Gold>.Create();
foreach (var g in bank.FindItemsByType<Gold>())
{
balance += g.Amount;
gold.Add(g);
if (balance >= requiredBalance)
{
checks = default;
return true;
}
}
checks = PooledRefList<BankCheck>.Create();
foreach (var bc in bank.FindItemsByType<BankCheck>())
{
balance += bc.Worth;
checks.Add(bc);
if (balance >= requiredBalance)
{
return true;
}
}
gold.Dispose();
checks.Dispose();
return false;
}
public static bool Withdraw(Mobile from, int amount) public static bool Withdraw(Mobile from, int amount)
{ {
// If for whatever reason the TOL checks fail, we should still try old methods for withdrawing currency. // If for whatever reason the TOL checks fail, we should still try old methods for withdrawing currency.
@ -111,30 +163,30 @@ public partial class Banker : BaseVendor
return true; return true;
} }
var balance = GetBalance(from, out var gold, out var checks); if (!HasRequiredBalance(amount, from, out var gold, out var checks))
if (balance < amount)
{ {
return false; return false;
} }
for (var i = 0; amount > 0 && i < gold.Count; ++i) for (var i = 0; amount > 0 && i < gold.Count; ++i)
{ {
if (gold[i].Amount <= amount) var g = gold[i];
if (g.Amount <= amount)
{ {
amount -= gold[i].Amount; amount -= g.Amount;
gold[i].Delete(); g.Delete();
} }
else else
{ {
gold[i].Amount -= amount; g.Amount -= amount;
amount = 0; amount = 0;
} }
} }
for (var i = 0; amount > 0 && i < checks.Count; ++i) for (var i = 0; amount > 0 && i < checks.Count; ++i)
{ {
var check = (BankCheck)checks[i]; var check = checks[i];
if (check.Worth <= amount) if (check.Worth <= amount)
{ {
@ -148,6 +200,9 @@ public partial class Banker : BaseVendor
} }
} }
gold.Dispose();
checks.Dispose();
return true; return true;
} }