From 402f3bc934b298c0176327c49d75b6a71aa152a4 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sun, 3 May 2026 10:19:12 -0700 Subject: [PATCH] perf: Migrate vendor management gumps to DynamicGump/StaticGump (#2431) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Converts `ReclaimVendorGump`, `VendorInventoryGump`, and the five gumps in `VendorRentalGumps.cs` from legacy `Gump` to `DynamicGump` / `StaticGump` with the static `DisplayTo` entry-point pattern. | Gump | Target | Reason | |---|---|---| | `ReclaimVendorGump` | DynamicGump | Variable vendor inventory list count. | | `VendorInventoryGump` | DynamicGump | Variable inventory list; keeps `from` (per-row button depends on owner check). | | `BaseVendorRentalGump` (abstract) → `VendorRentalContractGump`, `VendorRentalOfferGump`, `RenterVendorRentalGump`, `LandlordVendorRentalGump` | DynamicGump | Layout has many conditional sections driven by `GumpType` enum. | | `VendorRentalRefundGump` | StaticGump | Fixed layout; vendor name, shop name, refund amount in `BuildStrings` placeholders. | All builder labels and string slots use `$"{value}"` interpolated-string-handler form for zero-allocation text. Updates callers in `PlayerMobile`, `HouseSign`, `RentedVendor`, and `VendorRentalContract`. --- Projects/UOContent/Gumps/ReclaimVendorGump.cs | 127 +- .../UOContent/Gumps/VendorInventoryGump.cs | 237 +-- Projects/UOContent/Gumps/VendorRentalGumps.cs | 1276 +++++++++-------- .../Items/Deeds/VendorRentalContract.cs | 4 +- Projects/UOContent/Mobiles/PlayerMobile.cs | 2 +- .../UOContent/Mobiles/Vendors/RentedVendor.cs | 6 +- Projects/UOContent/Multis/Houses/HouseSign.cs | 2 +- 7 files changed, 864 insertions(+), 790 deletions(-) diff --git a/Projects/UOContent/Gumps/ReclaimVendorGump.cs b/Projects/UOContent/Gumps/ReclaimVendorGump.cs index 927dd1b70..af767f9cc 100644 --- a/Projects/UOContent/Gumps/ReclaimVendorGump.cs +++ b/Projects/UOContent/Gumps/ReclaimVendorGump.cs @@ -1,85 +1,94 @@ -using System.Collections.Generic; -using System.Linq; using Server.Multis; using Server.Network; -namespace Server.Gumps +namespace Server.Gumps; + +public class ReclaimVendorGump : DynamicGump { - public class ReclaimVendorGump : Gump + private readonly BaseHouse _house; + private readonly Mobile[] _vendors; + + public override bool Singleton => true; + + private ReclaimVendorGump(BaseHouse house) : base(50, 50) { - private readonly BaseHouse m_House; - private readonly List m_Vendors; + _house = house; + _vendors = house.InternalizedVendors.ToArray(); + } - public override bool Singleton => true; - - public ReclaimVendorGump(BaseHouse house) : base(50, 50) + public static void DisplayTo(Mobile from, BaseHouse house) + { + if (from?.NetState != null && house?.Deleted == false && house.InternalizedVendors.Count != 0) { - m_House = house; - m_Vendors = house.InternalizedVendors.ToList(); + from.SendGump(new ReclaimVendorGump(house)); + } + } - AddBackground(0, 0, 170, 50 + m_Vendors.Count * 20, 0x13BE); + protected override void BuildLayout(ref DynamicGumpBuilder builder) + { + builder.AddPage(); - AddImageTiled(10, 10, 150, 20, 0xA40); - AddHtmlLocalized(10, 10, 150, 20, 1061827, 0x7FFF); //
Reclaim Vendor
+ builder.AddBackground(0, 0, 170, 50 + _vendors.Length * 20, 0x13BE); - AddImageTiled(10, 40, 150, m_Vendors.Count * 20, 0xA40); + builder.AddImageTiled(10, 10, 150, 20, 0xA40); + builder.AddHtmlLocalized(10, 10, 150, 20, 1061827, 0x7FFF); //
Reclaim Vendor
- for (var i = 0; i < m_Vendors.Count; i++) - { - var m = m_Vendors[i]; + builder.AddImageTiled(10, 40, 150, _vendors.Length * 20, 0xA40); - var y = 40 + i * 20; + for (var i = 0; i < _vendors.Length; i++) + { + var m = _vendors[i]; - AddButton(10, y, 0xFA5, 0xFA7, i + 1); - AddLabel(45, y, 0x481, m.Name); - } + var y = 40 + i * 20; + + builder.AddButton(10, y, 0xFA5, 0xFA7, i + 1); + builder.AddLabel(45, y, 0x481, m.Name); + } + } + + public override void OnResponse(NetState sender, in RelayInfo info) + { + var from = sender.Mobile; + + if (info.ButtonID == 0 || !_house.IsActive || !_house.IsInside(from) || !_house.IsOwner(from) || !from.CheckAlive()) + { + return; } - public override void OnResponse(NetState sender, in RelayInfo info) + var index = info.ButtonID - 1; + + if (index < 0 || index >= _vendors.Length) { - var from = sender.Mobile; + return; + } - if (info.ButtonID == 0 || !m_House.IsActive || !m_House.IsInside(from) || !m_House.IsOwner(from) || - !from.CheckAlive()) + var mob = _vendors[index]; + + if (!_house.InternalizedVendors.Contains(mob)) + { + return; + } + + if (mob.Deleted) + { + _house.InternalizedVendors.Remove(mob); + } + else + { + BaseHouse.IsThereVendor(from.Location, from.Map, out var vendor, out var contract); + + if (vendor) { - return; + from.SendLocalizedMessage(1062677); // You cannot place a vendor or barkeep at this location. } - - var index = info.ButtonID - 1; - - if (index < 0 || index >= m_Vendors.Count) + else if (contract) { - return; - } - - var mob = m_Vendors[index]; - - if (!m_House.InternalizedVendors.Contains(mob)) - { - return; - } - - if (mob.Deleted) - { - m_House.InternalizedVendors.Remove(mob); + from.SendLocalizedMessage(1062678); // You cannot place a vendor or barkeep on top of a rental contract! } else { - BaseHouse.IsThereVendor(from.Location, from.Map, out var vendor, out var contract); - - if (vendor) - { - from.SendLocalizedMessage(1062677); // You cannot place a vendor or barkeep at this location. - } - else if (contract) - { - from.SendLocalizedMessage(1062678); // You cannot place a vendor or barkeep on top of a rental contract! - } - else - { - m_House.InternalizedVendors.Remove(mob); - mob.MoveToWorld(from.Location, from.Map); - } + _house.InternalizedVendors.Remove(mob); + mob.MoveToWorld(from.Location, from.Map); } } } diff --git a/Projects/UOContent/Gumps/VendorInventoryGump.cs b/Projects/UOContent/Gumps/VendorInventoryGump.cs index a8fb83a22..6b3728d0d 100644 --- a/Projects/UOContent/Gumps/VendorInventoryGump.cs +++ b/Projects/UOContent/Gumps/VendorInventoryGump.cs @@ -4,138 +4,147 @@ using Server.Mobiles; using Server.Multis; using Server.Network; -namespace Server.Gumps +namespace Server.Gumps; + +public class VendorInventoryGump : DynamicGump { - public class VendorInventoryGump : Gump + private readonly BaseHouse _house; + private readonly Mobile _from; + private readonly VendorInventory[] _inventories; + + public override bool Singleton => true; + + private VendorInventoryGump(BaseHouse house, Mobile from) : base(50, 50) { - private readonly BaseHouse m_House; - private readonly List m_Inventories; + _house = house; + _from = from; + _inventories = house.VendorInventories.ToArray(); + } - public override bool Singleton => true; - - public VendorInventoryGump(BaseHouse house, Mobile from) : base(50, 50) + public static void DisplayTo(Mobile from, BaseHouse house) + { + if (from?.NetState != null && house?.Deleted == false && house.VendorInventories.Count != 0) { - m_House = house; - m_Inventories = house.VendorInventories.ToList(); + from.SendGump(new VendorInventoryGump(house, from)); + } + } - AddBackground(0, 0, 420, 50 + 20 * m_Inventories.Count, 0x13BE); + protected override void BuildLayout(ref DynamicGumpBuilder builder) + { + builder.AddPage(); - AddImageTiled(10, 10, 400, 20, 0xA40); - AddHtmlLocalized(15, 10, 200, 20, 1062435, 0x7FFF); // Reclaim Vendor Inventory - AddHtmlLocalized(330, 10, 50, 20, 1062465, 0x7FFF); // Expires + builder.AddBackground(0, 0, 420, 50 + 20 * _inventories.Length, 0x13BE); - AddImageTiled(10, 40, 400, 20 * m_Inventories.Count, 0xA40); + builder.AddImageTiled(10, 10, 400, 20, 0xA40); + builder.AddHtmlLocalized(15, 10, 200, 20, 1062435, 0x7FFF); // Reclaim Vendor Inventory + builder.AddHtmlLocalized(330, 10, 50, 20, 1062465, 0x7FFF); // Expires - for (var i = 0; i < m_Inventories.Count; i++) + builder.AddImageTiled(10, 40, 400, 20 * _inventories.Length, 0xA40); + + for (var i = 0; i < _inventories.Length; i++) + { + var inventory = _inventories[i]; + + var y = 40 + 20 * i; + + if (inventory.Owner == _from) { - var inventory = m_Inventories[i]; + builder.AddButton(10, y, 0xFA5, 0xFA7, i + 1); + } - var y = 40 + 20 * i; + builder.AddLabel(45, y, 0x481, $"{inventory.ShopName} ({inventory.VendorName})"); - if (inventory.Owner == from) - { - AddButton(10, y, 0xFA5, 0xFA7, i + 1); - } + var expire = inventory.ExpireTime - Core.Now; + var hours = (int)expire.TotalHours; - AddLabel(45, y, 0x481, $"{inventory.ShopName} ({inventory.VendorName})"); + builder.AddLabel(320, y, 0x481, $"{hours}"); + builder.AddHtmlLocalized(350, y, 50, 20, 1062466, 0x7FFF); // hour(s) + } + } - var expire = inventory.ExpireTime - Core.Now; - var hours = (int)expire.TotalHours; + public override void OnResponse(NetState sender, in RelayInfo info) + { + if (info.ButtonID == 0) + { + return; + } - AddLabel(320, y, 0x481, hours.ToString()); - AddHtmlLocalized(350, y, 50, 20, 1062466, 0x7FFF); // hour(s) + var from = sender.Mobile; + var sign = _house.Sign; + + if (_house.Deleted || sign?.Deleted != false || !from.CheckAlive()) + { + return; + } + + if (from.Map != sign.Map || !from.InRange(sign, 5)) + { + from.SendLocalizedMessage(1062429); // You must be within five paces of the house sign to use this option. + return; + } + + var index = info.ButtonID - 1; + if (index < 0 || index >= _inventories.Length) + { + return; + } + + var inventory = _inventories[index]; + + if (inventory.Owner != from || !_house.VendorInventories.Contains(inventory)) + { + return; + } + + var totalItems = 0; + var givenToBackpack = 0; + var givenToBankBox = 0; + for (var i = inventory.Items.Count - 1; i >= 0; i--) + { + var item = inventory.Items[i]; + + if (item.Deleted) + { + inventory.Items.RemoveAt(i); + continue; + } + + totalItems += 1 + item.TotalItems; + + if (from.PlaceInBackpack(item)) + { + inventory.Items.RemoveAt(i); + givenToBackpack += 1 + item.TotalItems; + } + else if (from.BankBox.TryDropItem(from, item, false)) + { + inventory.Items.RemoveAt(i); + givenToBankBox += 1 + item.TotalItems; } } - public override void OnResponse(NetState sender, in RelayInfo info) + // The vendor you selected had ~1_COUNT~ items in its inventory, and ~2_AMOUNT~ gold in its account. + from.SendLocalizedMessage(1062436, $"{totalItems}\t{inventory.Gold}"); + + var givenGold = Banker.DepositUpTo(from, inventory.Gold); + inventory.Gold -= givenGold; + + // ~1_AMOUNT~ gold has been deposited into your bank box. + from.SendLocalizedMessage(1060397, givenGold.ToString()); + + // ~1_COUNT~ items have been removed from the shop inventory and placed in your backpack. + // ~2_BANKCOUNT~ items were removed from the shop inventory and placed in your bank box. + from.SendLocalizedMessage(1062437, $"{givenToBackpack}\t{givenToBankBox}"); + + if (inventory.Gold > 0 || inventory.Items.Count > 0) { - if (info.ButtonID == 0) - { - return; - } - - var from = sender.Mobile; - var sign = m_House.Sign; - - if (m_House.Deleted || sign?.Deleted != false || !from.CheckAlive()) - { - return; - } - - if (from.Map != sign.Map || !from.InRange(sign, 5)) - { - from.SendLocalizedMessage(1062429); // You must be within five paces of the house sign to use this option. - return; - } - - var index = info.ButtonID - 1; - if (index < 0 || index >= m_Inventories.Count) - { - return; - } - - var inventory = m_Inventories[index]; - - if (inventory.Owner != from || !m_House.VendorInventories.Contains(inventory)) - { - return; - } - - var totalItems = 0; - var givenToBackpack = 0; - var givenToBankBox = 0; - for (var i = inventory.Items.Count - 1; i >= 0; i--) - { - var item = inventory.Items[i]; - - if (item.Deleted) - { - inventory.Items.RemoveAt(i); - continue; - } - - totalItems += 1 + item.TotalItems; - - if (from.PlaceInBackpack(item)) - { - inventory.Items.RemoveAt(i); - givenToBackpack += 1 + item.TotalItems; - } - else if (from.BankBox.TryDropItem(from, item, false)) - { - inventory.Items.RemoveAt(i); - givenToBankBox += 1 + item.TotalItems; - } - } - - from.SendLocalizedMessage( - 1062436, - $"{totalItems}\t{inventory.Gold}" - ); // The vendor you selected had ~1_COUNT~ items in its inventory, and ~2_AMOUNT~ gold in its account. - - var givenGold = Banker.DepositUpTo(from, inventory.Gold); - inventory.Gold -= givenGold; - - from.SendLocalizedMessage( - 1060397, - givenGold.ToString() - ); // ~1_AMOUNT~ gold has been deposited into your bank box. - from.SendLocalizedMessage( - 1062437, - $"{givenToBackpack}\t{givenToBankBox}" - ); // ~1_COUNT~ items have been removed from the shop inventory and placed in your backpack. ~2_BANKCOUNT~ items were removed from the shop inventory and placed in your bank box. - - if (inventory.Gold > 0 || inventory.Items.Count > 0) - { - from.SendLocalizedMessage( - 1062440 - ); // Some of the shop inventory would not fit in your backpack or bank box. Please free up some room and try again. - } - else - { - inventory.Delete(); - from.SendLocalizedMessage(1062438); // The shop is now empty of inventory and funds, so it has been deleted. - } + // Some of the shop inventory would not fit in your backpack or bank box. Please free up some room and try again. + from.SendLocalizedMessage(1062440); + } + else + { + inventory.Delete(); + from.SendLocalizedMessage(1062438); // The shop is now empty of inventory and funds, so it has been deleted. } } } diff --git a/Projects/UOContent/Gumps/VendorRentalGumps.cs b/Projects/UOContent/Gumps/VendorRentalGumps.cs index 82710f662..4291cf7d3 100644 --- a/Projects/UOContent/Gumps/VendorRentalGumps.cs +++ b/Projects/UOContent/Gumps/VendorRentalGumps.cs @@ -1,3 +1,4 @@ +using System; using Server.Items; using Server.Mobiles; using Server.Multis; @@ -5,701 +6,756 @@ using Server.Network; using Server.Prompts; using Server.Targeting; -namespace Server.Gumps +namespace Server.Gumps; + +public abstract class BaseVendorRentalGump : DynamicGump { - public abstract class BaseVendorRentalGump : Gump + private readonly GumpType _type; + private readonly VendorRentalDuration _duration; + private readonly int _price; + private readonly int _renewalPrice; + private readonly Mobile _landlord; + private readonly Mobile _renter; + private readonly bool _landlordRenew; + private readonly bool _renterRenew; + private readonly bool _renew; + + protected BaseVendorRentalGump( + GumpType type, VendorRentalDuration duration, int price, int renewalPrice, + Mobile landlord, Mobile renter, bool landlordRenew, bool renterRenew, bool renew + ) : base(100, 100) { - protected BaseVendorRentalGump( - GumpType type, VendorRentalDuration duration, int price, int renewalPrice, - Mobile landlord, Mobile renter, bool landlordRenew, bool renterRenew, bool renew - ) : base(100, 100) + _type = type; + _duration = duration; + _price = price; + _renewalPrice = renewalPrice; + _landlord = landlord; + _renter = renter; + _landlordRenew = landlordRenew; + _renterRenew = renterRenew; + _renew = renew; + } + + protected override void BuildLayout(ref DynamicGumpBuilder builder) + { + if (_type == GumpType.Offer) { - if (type == GumpType.Offer) + builder.SetNoClose(); + } + + builder.AddPage(); + + builder.AddImage(0, 0, 0x1F40); + builder.AddImageTiled(20, 37, 300, 308, 0x1F42); + builder.AddImage(20, 325, 0x1F43); + + builder.AddImage(35, 8, 0x39); + builder.AddImageTiled(65, 8, 257, 10, 0x3A); + builder.AddImage(290, 8, 0x3B); + + builder.AddImageTiled(70, 55, 230, 2, 0x23C5); + + builder.AddImage(32, 33, 0x2635); + builder.AddHtmlLocalized(70, 35, 270, 20, 1062353, 0x1); // Vendor Rental Contract + + builder.AddPage(1); + + if (_type != GumpType.UnlockedContract) + { + builder.AddImage(65, 60, 0x827); + builder.AddHtmlLocalized(79, 58, 270, 20, 1062370, 0x1); // Landlord: + builder.AddLabel(150, 58, 0x64, _landlord?.Name ?? ""); + + builder.AddImageTiled(70, 80, 230, 2, 0x23C5); + } + + if (_type is GumpType.UnlockedContract or GumpType.LockedContract) + { + builder.AddButton(30, 96, 0x15E1, 0x15E5, 0, GumpButtonType.Page, 2); + } + + builder.AddHtmlLocalized(50, 95, 150, 20, 1062354, 0x1); // Contract Length + builder.AddHtmlLocalized(230, 95, 270, 20, _duration.Name, 0x1); + + if (_type is GumpType.UnlockedContract or GumpType.LockedContract) + { + builder.AddButton(30, 116, 0x15E1, 0x15E5, 1); + } + + builder.AddHtmlLocalized(50, 115, 150, 20, 1062356, 0x1); // Price Per Rental + if (_price > 0) + { + builder.AddLabel(230, 115, 0x64, $"{_price}"); + } + else + { + builder.AddLabel(230, 115, 0x64, "FREE"); + } + + builder.AddImageTiled(50, 160, 250, 2, 0x23BF); + + if (_type == GumpType.Offer) + { + builder.AddButton(67, 180, 0x482, 0x483, 2); + builder.AddHtmlLocalized(100, 180, 270, 20, 1049011, 0x28); // I accept! + + builder.AddButton(67, 210, 0x47F, 0x480, 0); + builder.AddHtmlLocalized(100, 210, 270, 20, 1049012, 0x28); // No thanks, I decline. + } + else + { + builder.AddImage(49, 170, 0x61); + builder.AddHtmlLocalized(60, 170, 250, 20, 1062355, 0x1); // Renew On Expiration? + + if (_type is GumpType.LockedContract or GumpType.UnlockedContract or GumpType.VendorLandlord) { - Closable = false; + builder.AddButton(30, 192, 0x15E1, 0x15E5, 3); } - AddPage(0); + builder.AddHtmlLocalized(85, 190, 250, 20, 1062359, 0x1); // Landlord: + builder.AddHtmlLocalized(230, 190, 270, 20, _landlordRenew ? 1049717 : 1049718, 0x1); // YES / NO - AddImage(0, 0, 0x1F40); - AddImageTiled(20, 37, 300, 308, 0x1F42); - AddImage(20, 325, 0x1F43); - - AddImage(35, 8, 0x39); - AddImageTiled(65, 8, 257, 10, 0x3A); - AddImage(290, 8, 0x3B); - - AddImageTiled(70, 55, 230, 2, 0x23C5); - - AddImage(32, 33, 0x2635); - AddHtmlLocalized(70, 35, 270, 20, 1062353, 0x1); // Vendor Rental Contract - - AddPage(1); - - if (type != GumpType.UnlockedContract) + if (_type == GumpType.VendorRenter) { - AddImage(65, 60, 0x827); - AddHtmlLocalized(79, 58, 270, 20, 1062370, 0x1); // Landlord: - AddLabel(150, 58, 0x64, landlord != null ? landlord.Name : ""); - - AddImageTiled(70, 80, 230, 2, 0x23C5); + builder.AddButton(30, 212, 0x15E1, 0x15E5, 4); } - if (type is GumpType.UnlockedContract or GumpType.LockedContract) + builder.AddHtmlLocalized(85, 210, 250, 20, 1062360, 0x1); // Renter: + builder.AddHtmlLocalized(230, 210, 270, 20, _renterRenew ? 1049717 : 1049718, 0x1); // YES / NO + + if (_renew) { - AddButton(30, 96, 0x15E1, 0x15E5, 0, GumpButtonType.Page, 2); - } - - AddHtmlLocalized(50, 95, 150, 20, 1062354, 0x1); // Contract Length - AddHtmlLocalized(230, 95, 270, 20, duration.Name, 0x1); - - if (type is GumpType.UnlockedContract or GumpType.LockedContract) - { - AddButton(30, 116, 0x15E1, 0x15E5, 1); - } - - AddHtmlLocalized(50, 115, 150, 20, 1062356, 0x1); // Price Per Rental - AddLabel(230, 115, 0x64, price > 0 ? price.ToString() : "FREE"); - - AddImageTiled(50, 160, 250, 2, 0x23BF); - - if (type == GumpType.Offer) - { - AddButton(67, 180, 0x482, 0x483, 2); - AddHtmlLocalized(100, 180, 270, 20, 1049011, 0x28); // I accept! - - AddButton(67, 210, 0x47F, 0x480, 0); - AddHtmlLocalized(100, 210, 270, 20, 1049012, 0x28); // No thanks, I decline. + builder.AddImage(49, 233, 0x939); + builder.AddHtmlLocalized(70, 230, 250, 20, 1062482, 0x1); // Contract WILL renew } else { - AddImage(49, 170, 0x61); - AddHtmlLocalized(60, 170, 250, 20, 1062355, 0x1); // Renew On Expiration? - - if (type is GumpType.LockedContract or GumpType.UnlockedContract or GumpType.VendorLandlord) - { - AddButton(30, 192, 0x15E1, 0x15E5, 3); - } - - AddHtmlLocalized(85, 190, 250, 20, 1062359, 0x1); // Landlord: - AddHtmlLocalized(230, 190, 270, 20, landlordRenew ? 1049717 : 1049718, 0x1); // YES / NO - - if (type == GumpType.VendorRenter) - { - AddButton(30, 212, 0x15E1, 0x15E5, 4); - } - - AddHtmlLocalized(85, 210, 250, 20, 1062360, 0x1); // Renter: - AddHtmlLocalized(230, 210, 270, 20, renterRenew ? 1049717 : 1049718, 0x1); // YES / NO - - if (renew) - { - AddImage(49, 233, 0x939); - AddHtmlLocalized(70, 230, 250, 20, 1062482, 0x1); // Contract WILL renew - } - else - { - AddImage(49, 233, 0x938); - AddHtmlLocalized(70, 230, 250, 20, 1062483, 0x1); // Contract WILL NOT renew - } - } - - AddImageTiled(30, 283, 257, 30, 0x5D); - AddImage(285, 283, 0x5E); - AddImage(20, 288, 0x232C); - - if (type == GumpType.LockedContract) - { - AddButton(67, 295, 0x15E1, 0x15E5, 5); - AddHtmlLocalized(85, 294, 270, 20, 1062358, 0x28); // Offer Contract To Someone - } - else if (type is GumpType.VendorLandlord or GumpType.VendorRenter) - { - if (type == GumpType.VendorLandlord) - { - AddButton(30, 250, 0x15E1, 0x15E1, 6); - } - - AddHtmlLocalized(85, 250, 250, 20, 1062499, 0x1); // Renewal Price - AddLabel(230, 250, 0x64, renewalPrice.ToString()); - - AddHtmlLocalized(60, 294, 270, 20, 1062369, 0x1); // Renter: - AddLabel(120, 293, 0x64, renter != null ? renter.Name : ""); - } - - if (type is GumpType.UnlockedContract or GumpType.LockedContract) - { - AddPage(2); - - for (var i = 0; i < VendorRentalDuration.Instances.Length; i++) - { - var durationItem = VendorRentalDuration.Instances[i]; - - AddButton(30, 76 + i * 20, 0x15E1, 0x15E5, 0x10 | i, GumpButtonType.Reply, 1); - AddHtmlLocalized(50, 75 + i * 20, 150, 20, durationItem.Name, 0x1); - } + builder.AddImage(49, 233, 0x938); + builder.AddHtmlLocalized(70, 230, 250, 20, 1062483, 0x1); // Contract WILL NOT renew } } - public override void OnResponse(NetState sender, in RelayInfo info) - { - var from = sender.Mobile; + builder.AddImageTiled(30, 283, 257, 30, 0x5D); + builder.AddImage(285, 283, 0x5E); + builder.AddImage(20, 288, 0x232C); - if (!IsValidResponse(from)) + if (_type == GumpType.LockedContract) + { + builder.AddButton(67, 295, 0x15E1, 0x15E5, 5); + builder.AddHtmlLocalized(85, 294, 270, 20, 1062358, 0x28); // Offer Contract To Someone + } + else if (_type is GumpType.VendorLandlord or GumpType.VendorRenter) + { + if (_type == GumpType.VendorLandlord) + { + builder.AddButton(30, 250, 0x15E1, 0x15E1, 6); + } + + builder.AddHtmlLocalized(85, 250, 250, 20, 1062499, 0x1); // Renewal Price + builder.AddLabel(230, 250, 0x64, $"{_renewalPrice}"); + + builder.AddHtmlLocalized(60, 294, 270, 20, 1062369, 0x1); // Renter: + builder.AddLabel(120, 293, 0x64, _renter != null ? _renter.Name : ""); + } + + if (_type is GumpType.UnlockedContract or GumpType.LockedContract) + { + builder.AddPage(2); + + for (var i = 0; i < VendorRentalDuration.Instances.Length; i++) + { + var durationItem = VendorRentalDuration.Instances[i]; + + builder.AddButton(30, 76 + i * 20, 0x15E1, 0x15E5, 0x10 | i, GumpButtonType.Reply, 1); + builder.AddHtmlLocalized(50, 75 + i * 20, 150, 20, durationItem.Name, 0x1); + } + } + } + + public override void OnResponse(NetState sender, in RelayInfo info) + { + var from = sender.Mobile; + + if (!IsValidResponse(from)) + { + return; + } + + if ((info.ButtonID & 0x10) != 0) // Contract duration + { + var index = info.ButtonID & 0xF; + + if (index < VendorRentalDuration.Instances.Length) + { + SetContractDuration(from, VendorRentalDuration.Instances[index]); + } + + return; + } + + switch (info.ButtonID) + { + case 1: // Price Per Rental + { + SetPricePerRental(from); + break; + } + + case 2: // Accept offer + { + AcceptOffer(from); + break; + } + + case 3: // Renew on expiration - landlord + { + LandlordRenewOnExpiration(from); + break; + } + + case 4: // Renew on expiration - renter + { + RenterRenewOnExpiration(from); + break; + } + + case 5: // Offer Contract To Someone + { + OfferContract(from); + break; + } + + case 6: // Renewal price + { + SetRenewalPrice(from); + break; + } + + default: + { + Cancel(from); + break; + } + } + } + + protected abstract bool IsValidResponse(Mobile from); + + protected virtual void SetContractDuration(Mobile from, VendorRentalDuration duration) + { + } + + protected virtual void SetPricePerRental(Mobile from) + { + } + + protected virtual void AcceptOffer(Mobile from) + { + } + + protected virtual void LandlordRenewOnExpiration(Mobile from) + { + } + + protected virtual void RenterRenewOnExpiration(Mobile from) + { + } + + protected virtual void OfferContract(Mobile from) + { + } + + protected virtual void SetRenewalPrice(Mobile from) + { + } + + protected virtual void Cancel(Mobile from) + { + } + + protected enum GumpType + { + UnlockedContract, + LockedContract, + Offer, + VendorLandlord, + VendorRenter + } +} + +public class VendorRentalContractGump : BaseVendorRentalGump +{ + private readonly VendorRentalContract _contract; + + private VendorRentalContractGump(VendorRentalContract contract, Mobile from) : base( + contract.IsLockedDown ? GumpType.LockedContract : GumpType.UnlockedContract, + contract.Duration, + contract.Price, + contract.Price, + from, + null, + contract.LandlordRenew, + false, + false + ) => _contract = contract; + + public static void DisplayTo(Mobile from, VendorRentalContract contract) + { + if (from?.NetState != null && contract?.Deleted == false) + { + from.SendGump(new VendorRentalContractGump(contract, from), true); + } + } + + protected override bool IsValidResponse(Mobile from) => _contract.IsUsableBy(from, true, true, true, true); + + protected override void SetContractDuration(Mobile from, VendorRentalDuration duration) + { + _contract.Duration = duration; + + DisplayTo(from, _contract); + } + + protected override void SetPricePerRental(Mobile from) + { + // Please enter the amount of gold that should be charged for this contract (ESC to cancel): + from.SendLocalizedMessage(1062365); + from.Prompt = new PricePerRentalPrompt(_contract); + } + + protected override void LandlordRenewOnExpiration(Mobile from) + { + _contract.LandlordRenew = !_contract.LandlordRenew; + + DisplayTo(from, _contract); + } + + protected override void OfferContract(Mobile from) + { + if (_contract.IsLandlord(from)) + { + from.SendLocalizedMessage(1062371); // Please target the person you wish to offer this contract to. + from.Target = new OfferContractTarget(_contract); + } + } + + private class PricePerRentalPrompt : Prompt + { + private readonly VendorRentalContract _contract; + + public PricePerRentalPrompt(VendorRentalContract contract) => _contract = contract; + + public override void OnResponse(Mobile from, string text) + { + if (!_contract.IsUsableBy(from, true, true, true, true)) { return; } - if ((info.ButtonID & 0x10) != 0) // Contract duration + if (!int.TryParse(text.AsSpan().Trim(), out var price)) { - var index = info.ButtonID & 0xF; + price = -1; + } - if (index < VendorRentalDuration.Instances.Length) - { - SetContractDuration(from, VendorRentalDuration.Instances[index]); - } + if (price < 0) + { + from.SendLocalizedMessage(1062485); // Invalid entry. Rental fee set to 0. + _contract.Price = 0; + } + else if (price > 5000000) + { + _contract.Price = 5000000; } else { - switch (info.ButtonID) - { - case 1: // Price Per Rental - { - SetPricePerRental(from); - break; - } - - case 2: // Accept offer - { - AcceptOffer(from); - break; - } - - case 3: // Renew on expiration - landlord - { - LandlordRenewOnExpiration(from); - break; - } - - case 4: // Renew on expiration - renter - { - RenterRenewOnExpiration(from); - break; - } - - case 5: // Offer Contract To Someone - { - OfferContract(from); - break; - } - - case 6: // Renewal price - { - SetRenewalPrice(from); - break; - } - - default: - { - Cancel(from); - break; - } - } - } - } - - protected abstract bool IsValidResponse(Mobile from); - - protected virtual void SetContractDuration(Mobile from, VendorRentalDuration duration) - { - } - - protected virtual void SetPricePerRental(Mobile from) - { - } - - protected virtual void AcceptOffer(Mobile from) - { - } - - protected virtual void LandlordRenewOnExpiration(Mobile from) - { - } - - protected virtual void RenterRenewOnExpiration(Mobile from) - { - } - - protected virtual void OfferContract(Mobile from) - { - } - - protected virtual void SetRenewalPrice(Mobile from) - { - } - - protected virtual void Cancel(Mobile from) - { - } - - protected enum GumpType - { - UnlockedContract, - LockedContract, - Offer, - VendorLandlord, - VendorRenter - } - } - - public class VendorRentalContractGump : BaseVendorRentalGump - { - private readonly VendorRentalContract m_Contract; - - public VendorRentalContractGump(VendorRentalContract contract, Mobile from) : base( - contract.IsLockedDown ? GumpType.LockedContract : GumpType.UnlockedContract, - contract.Duration, - contract.Price, - contract.Price, - from, - null, - contract.LandlordRenew, - false, - false - ) => - m_Contract = contract; - - protected override bool IsValidResponse(Mobile from) => m_Contract.IsUsableBy(from, true, true, true, true); - - protected override void SetContractDuration(Mobile from, VendorRentalDuration duration) - { - m_Contract.Duration = duration; - - from.SendGump(new VendorRentalContractGump(m_Contract, from)); - } - - protected override void SetPricePerRental(Mobile from) - { - from.SendLocalizedMessage( - 1062365 - ); // Please enter the amount of gold that should be charged for this contract (ESC to cancel): - from.Prompt = new PricePerRentalPrompt(m_Contract); - } - - protected override void LandlordRenewOnExpiration(Mobile from) - { - m_Contract.LandlordRenew = !m_Contract.LandlordRenew; - - from.SendGump(new VendorRentalContractGump(m_Contract, from)); - } - - protected override void OfferContract(Mobile from) - { - if (m_Contract.IsLandlord(from)) - { - from.SendLocalizedMessage(1062371); // Please target the person you wish to offer this contract to. - from.Target = new OfferContractTarget(m_Contract); - } - } - - private class PricePerRentalPrompt : Prompt - { - private readonly VendorRentalContract m_Contract; - - public PricePerRentalPrompt(VendorRentalContract contract) => m_Contract = contract; - - public override void OnResponse(Mobile from, string text) - { - if (!m_Contract.IsUsableBy(from, true, true, true, true)) - { - return; - } - - text = text.Trim(); - - if (!int.TryParse(text, out var price)) - { - price = -1; - } - - if (price < 0) - { - from.SendLocalizedMessage(1062485); // Invalid entry. Rental fee set to 0. - m_Contract.Price = 0; - } - else if (price > 5000000) - { - m_Contract.Price = 5000000; - } - else - { - m_Contract.Price = price; - } - - from.SendGump(new VendorRentalContractGump(m_Contract, from)); + _contract.Price = price; } - public override void OnCancel(Mobile from) - { - if (m_Contract.IsUsableBy(from, true, true, true, true)) - { - from.SendGump(new VendorRentalContractGump(m_Contract, from)); - } - } + DisplayTo(from, _contract); } - private class OfferContractTarget : Target + public override void OnCancel(Mobile from) { - private readonly VendorRentalContract m_Contract; - - public OfferContractTarget(VendorRentalContract contract) : base(-1, false, TargetFlags.None) => - m_Contract = contract; - - protected override void OnTarget(Mobile from, object targeted) + if (_contract.IsUsableBy(from, true, true, true, true)) { - if (!m_Contract.IsUsableBy(from, true, false, true, true)) - { - return; - } - - if (targeted is not Mobile mob || !mob.Player || !mob.Alive || mob == from) - { - from.SendLocalizedMessage(1071984); // That is not a valid target for a rental contract! - } - else if (!mob.InRange(m_Contract, 5)) - { - from.SendLocalizedMessage(501853); // Target is too far away. - } - else - { - from.SendLocalizedMessage(1062372); // Please wait while that person considers your offer. - - mob.SendLocalizedMessage( - 1062373, - from.Name - ); // ~1_NAME~ is offering you a vendor rental. If you choose to accept this offer, you have 30 seconds to do so. - mob.SendGump(new VendorRentalOfferGump(m_Contract, from)); - - m_Contract.Offeree = mob; - } - } - - protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) - { - from.SendLocalizedMessage(1062380); // You decide against offering the contract to anyone. + DisplayTo(from, _contract); } } } - public class VendorRentalOfferGump : BaseVendorRentalGump + private class OfferContractTarget : Target { - private readonly VendorRentalContract m_Contract; - private readonly Mobile m_Landlord; + private readonly VendorRentalContract _contract; - public VendorRentalOfferGump(VendorRentalContract contract, Mobile landlord) : base( - GumpType.Offer, - contract.Duration, - contract.Price, - contract.Price, - landlord, - null, - contract.LandlordRenew, - false, - false - ) + public OfferContractTarget(VendorRentalContract contract) : base(-1, false, TargetFlags.None) => + _contract = contract; + + protected override void OnTarget(Mobile from, object targeted) { - m_Contract = contract; - m_Landlord = landlord; - } - - protected override bool IsValidResponse(Mobile from) => - m_Contract.IsUsableBy(m_Landlord, true, false, false, false) && from.CheckAlive() && m_Contract.Offeree == from; - - protected override void AcceptOffer(Mobile from) - { - m_Contract.Offeree = null; - - if (!m_Contract.Map.CanFit(m_Contract.Location, 16, false, false)) - { - m_Landlord.SendLocalizedMessage(1062486); // A vendor cannot exist at that location. Please try again. - return; - } - - var house = BaseHouse.FindHouseAt(m_Contract); - if (house == null) + if (!_contract.IsUsableBy(from, true, false, true, true)) { return; } - var price = m_Contract.Price; - int goldToGive; - - if (price > 0) + if (targeted is not Mobile mob || !mob.Player || !mob.Alive || mob == from) { - if (Banker.Withdraw(from, price)) + from.SendLocalizedMessage(1071984); // That is not a valid target for a rental contract! + } + else if (!mob.InRange(_contract, 5)) + { + from.SendLocalizedMessage(501853); // Target is too far away. + } + else + { + from.SendLocalizedMessage(1062372); // Please wait while that person considers your offer. + + // ~1_NAME~ is offering you a vendor rental. If you choose to accept this offer, you have 30 seconds to do so. + mob.SendLocalizedMessage(1062373, from.Name); + VendorRentalOfferGump.DisplayTo(mob, _contract, from); + + _contract.Offeree = mob; + } + } + + protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) + { + from.SendLocalizedMessage(1062380); // You decide against offering the contract to anyone. + } + } +} + +public class VendorRentalOfferGump : BaseVendorRentalGump +{ + private readonly VendorRentalContract _contract; + private readonly Mobile _landlord; + + private VendorRentalOfferGump(VendorRentalContract contract, Mobile landlord) : base( + GumpType.Offer, + contract.Duration, + contract.Price, + contract.Price, + landlord, + null, + contract.LandlordRenew, + false, + false + ) + { + _contract = contract; + _landlord = landlord; + } + + public static void DisplayTo(Mobile to, VendorRentalContract contract, Mobile landlord) + { + if (to?.NetState != null && contract?.Deleted == false && landlord != null) + { + to.SendGump(new VendorRentalOfferGump(contract, landlord)); + } + } + + protected override bool IsValidResponse(Mobile from) => + _contract.IsUsableBy(_landlord, true, false, false, false) && from.CheckAlive() && _contract.Offeree == from; + + protected override void AcceptOffer(Mobile from) + { + _contract.Offeree = null; + + if (!_contract.Map.CanFit(_contract.Location, 16, false, false)) + { + _landlord.SendLocalizedMessage(1062486); // A vendor cannot exist at that location. Please try again. + return; + } + + var house = BaseHouse.FindHouseAt(_contract); + if (house == null) + { + return; + } + + var price = _contract.Price; + int goldToGive; + + if (price > 0) + { + if (Banker.Withdraw(from, price)) + { + // ~1_AMOUNT~ gold has been withdrawn from your bank box. + from.SendLocalizedMessage(1060398, price.ToString()); + + var depositedGold = Banker.DepositUpTo(_landlord, price); + goldToGive = price - depositedGold; + + if (depositedGold > 0) { - from.SendLocalizedMessage( - 1060398, - price.ToString() - ); // ~1_AMOUNT~ gold has been withdrawn from your bank box. - - var depositedGold = Banker.DepositUpTo(m_Landlord, price); - goldToGive = price - depositedGold; - - if (depositedGold > 0) - { - m_Landlord.SendLocalizedMessage( - 1060397, - price.ToString() - ); // ~1_AMOUNT~ gold has been deposited into your bank box. - } - - if (goldToGive > 0) - { - m_Landlord.SendLocalizedMessage(500390); // Your bank box is full. - } + // ~1_AMOUNT~ gold has been deposited into your bank box. + _landlord.SendLocalizedMessage(1060397, price.ToString()); } - else - { - from.SendLocalizedMessage( - 1062378 - ); // You do not have enough gold in your bank account to cover the cost of the contract. - m_Landlord.SendLocalizedMessage(1062374, from.Name); // ~1_NAME~ has declined your vendor rental offer. - return; + if (goldToGive > 0) + { + _landlord.SendLocalizedMessage(500390); // Your bank box is full. } } else { - goldToGive = 0; + // You do not have enough gold in your bank account to cover the cost of the contract. + from.SendLocalizedMessage(1062378); + _landlord.SendLocalizedMessage(1062374, from.Name); // ~1_NAME~ has declined your vendor rental offer. + + return; } - - var vendor = new RentedVendor( - from, - house, - m_Contract.Duration, - price, - m_Contract.LandlordRenew, - goldToGive - ); - vendor.MoveToWorld(m_Contract.Location, m_Contract.Map); - - m_Contract.Delete(); - - // You have accepted the offer and now own a vendor in this house. Rental contract options and details may be viewed on this vendor via the 'Contract Options' context menu. - from.SendLocalizedMessage(1062377); - - // ~1_NAME~ has accepted your vendor rental offer. Rental contract details and options may be viewed on this vendor via the 'Contract Options' context menu. - m_Landlord.SendLocalizedMessage(1062376, from.Name); + } + else + { + goldToGive = 0; } - protected override void Cancel(Mobile from) - { - m_Contract.Offeree = null; + var vendor = new RentedVendor(from, house, _contract.Duration, price, _contract.LandlordRenew, goldToGive); + vendor.MoveToWorld(_contract.Location, _contract.Map); - from.SendLocalizedMessage(1062375); // You decline the offer for a vendor space rental. - m_Landlord.SendLocalizedMessage(1062374, from.Name); // ~1_NAME~ has declined your vendor rental offer. + _contract.Delete(); + + // You have accepted the offer and now own a vendor in this house. Rental contract options and details may be viewed on this vendor via the 'Contract Options' context menu. + from.SendLocalizedMessage(1062377); + + // ~1_NAME~ has accepted your vendor rental offer. Rental contract details and options may be viewed on this vendor via the 'Contract Options' context menu. + _landlord.SendLocalizedMessage(1062376, from.Name); + } + + protected override void Cancel(Mobile from) + { + _contract.Offeree = null; + + from.SendLocalizedMessage(1062375); // You decline the offer for a vendor space rental. + _landlord.SendLocalizedMessage(1062374, from.Name); // ~1_NAME~ has declined your vendor rental offer. + } +} + +public class RenterVendorRentalGump : BaseVendorRentalGump +{ + private readonly RentedVendor _vendor; + + private RenterVendorRentalGump(RentedVendor vendor) : base( + GumpType.VendorRenter, + vendor.RentalDuration, + vendor.RentalPrice, + vendor.RenewalPrice, + vendor.Landlord, + vendor.Owner, + vendor.LandlordRenew, + vendor.RenterRenew, + vendor.Renew + ) => _vendor = vendor; + + public static void DisplayTo(Mobile from, RentedVendor vendor) + { + if (from?.NetState != null && vendor?.Deleted == false) + { + from.SendGump(new RenterVendorRentalGump(vendor), true); } } - public class RenterVendorRentalGump : BaseVendorRentalGump + protected override bool IsValidResponse(Mobile from) => _vendor.CanInteractWith(from, true); + + protected override void RenterRenewOnExpiration(Mobile from) { - private readonly RentedVendor m_Vendor; + _vendor.RenterRenew = !_vendor.RenterRenew; - public RenterVendorRentalGump(RentedVendor vendor) : base( - GumpType.VendorRenter, - vendor.RentalDuration, - vendor.RentalPrice, - vendor.RenewalPrice, - vendor.Landlord, - vendor.Owner, - vendor.LandlordRenew, - vendor.RenterRenew, - vendor.Renew - ) => - m_Vendor = vendor; + DisplayTo(from, _vendor); + } +} - protected override bool IsValidResponse(Mobile from) => m_Vendor.CanInteractWith(from, true); +public class LandlordVendorRentalGump : BaseVendorRentalGump +{ + private readonly RentedVendor _vendor; - protected override void RenterRenewOnExpiration(Mobile from) + private LandlordVendorRentalGump(RentedVendor vendor) : base( + GumpType.VendorLandlord, + vendor.RentalDuration, + vendor.RentalPrice, + vendor.RenewalPrice, + vendor.Landlord, + vendor.Owner, + vendor.LandlordRenew, + vendor.RenterRenew, + vendor.Renew + ) => _vendor = vendor; + + public static void DisplayTo(Mobile from, RentedVendor vendor) + { + if (from?.NetState != null && vendor?.Deleted == false) { - m_Vendor.RenterRenew = !m_Vendor.RenterRenew; - - from.SendGump(new RenterVendorRentalGump(m_Vendor)); + from.SendGump(new LandlordVendorRentalGump(vendor), true); } } - public class LandlordVendorRentalGump : BaseVendorRentalGump + protected override bool IsValidResponse(Mobile from) => + _vendor.CanInteractWith(from, false) && _vendor.IsLandlord(from); + + protected override void LandlordRenewOnExpiration(Mobile from) { - private readonly RentedVendor m_Vendor; + _vendor.LandlordRenew = !_vendor.LandlordRenew; - public LandlordVendorRentalGump(RentedVendor vendor) : base( - GumpType.VendorLandlord, - vendor.RentalDuration, - vendor.RentalPrice, - vendor.RenewalPrice, - vendor.Landlord, - vendor.Owner, - vendor.LandlordRenew, - vendor.RenterRenew, - vendor.Renew - ) => - m_Vendor = vendor; - - protected override bool IsValidResponse(Mobile from) => - m_Vendor.CanInteractWith(from, false) && m_Vendor.IsLandlord(from); - - protected override void LandlordRenewOnExpiration(Mobile from) - { - m_Vendor.LandlordRenew = !m_Vendor.LandlordRenew; - - from.SendGump(new LandlordVendorRentalGump(m_Vendor)); - } - - protected override void SetRenewalPrice(Mobile from) - { - from.SendLocalizedMessage(1062500); // Enter contract renewal price: - - from.Prompt = new ContractRenewalPricePrompt(m_Vendor); - } - - private class ContractRenewalPricePrompt : Prompt - { - private readonly RentedVendor m_Vendor; - - public ContractRenewalPricePrompt(RentedVendor vendor) => m_Vendor = vendor; - - public override void OnResponse(Mobile from, string text) - { - if (!m_Vendor.CanInteractWith(from, false) || !m_Vendor.IsLandlord(from)) - { - return; - } - - text = text.Trim(); - - if (!int.TryParse(text, out var price)) - { - price = -1; - } - - if (price < 0) - { - from.SendLocalizedMessage(1062485); // Invalid entry. Rental fee set to 0. - m_Vendor.RenewalPrice = 0; - } - else if (price > 5000000) - { - m_Vendor.RenewalPrice = 5000000; - } - else - { - m_Vendor.RenewalPrice = price; - } - - m_Vendor.RenterRenew = false; - - from.SendGump(new LandlordVendorRentalGump(m_Vendor)); - } - - public override void OnCancel(Mobile from) - { - if (m_Vendor.CanInteractWith(from, false) && m_Vendor.IsLandlord(from)) - { - from.SendGump(new LandlordVendorRentalGump(m_Vendor)); - } - } - } + DisplayTo(from, _vendor); } - public class VendorRentalRefundGump : Gump + protected override void SetRenewalPrice(Mobile from) { - private readonly Mobile m_Landlord; - private readonly int m_RefundAmount; - private readonly RentedVendor m_Vendor; + from.SendLocalizedMessage(1062500); // Enter contract renewal price: - public override bool Singleton => true; + from.Prompt = new ContractRenewalPricePrompt(_vendor); + } - public VendorRentalRefundGump(RentedVendor vendor, Mobile landlord, int refundAmount) : base(50, 50) + private class ContractRenewalPricePrompt : Prompt + { + private readonly RentedVendor _vendor; + + public ContractRenewalPricePrompt(RentedVendor vendor) => _vendor = vendor; + + public override void OnResponse(Mobile from, string text) { - m_Vendor = vendor; - m_Landlord = landlord; - m_RefundAmount = refundAmount; - - AddBackground(0, 0, 420, 320, 0x13BE); - - AddImageTiled(10, 10, 400, 300, 0xA40); - AddAlphaRegion(10, 10, 400, 300); - - /* The landlord for this vendor is offering you a partial refund of your rental fee - * in exchange for immediate termination of your rental contract.

- * - * If you accept this offer, the vendor will be immediately dismissed. You will then - * be able to claim the inventory and any funds the vendor may be holding for you via - * a context menu on the house sign for this house. - */ - AddHtmlLocalized(10, 10, 400, 150, 1062501, 0x7FFF, false, true); - - AddHtmlLocalized(10, 180, 150, 20, 1062508, 0x7FFF); // Vendor Name: - AddLabel(160, 180, 0x480, vendor.Name); - - AddHtmlLocalized(10, 200, 150, 20, 1062509, 0x7FFF); // Shop Name: - AddLabel(160, 200, 0x480, vendor.ShopName); - - AddHtmlLocalized(10, 220, 150, 20, 1062510, 0x7FFF); // Refund Amount: - AddLabel(160, 220, 0x480, refundAmount.ToString()); - - AddButton(10, 268, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(45, 268, 350, 20, 1062511, 0x7FFF); // Agree, and dismiss vendor - - AddButton(10, 288, 0xFA5, 0xFA7, 0); - AddHtmlLocalized(45, 288, 350, 20, 1062512, 0x7FFF); // No, I want to keep my vendor - } - - public override void OnResponse(NetState sender, in RelayInfo info) - { - var from = sender.Mobile; - - if (!m_Vendor.CanInteractWith(from, true) || !m_Vendor.CanInteractWith(m_Landlord, false) || - !m_Vendor.IsLandlord(m_Landlord)) + if (!_vendor.CanInteractWith(from, false) || !_vendor.IsLandlord(from)) { return; } - if (info.ButtonID == 1) + if (!int.TryParse(text.AsSpan().Trim(), out var price)) { - if (Banker.Withdraw(m_Landlord, m_RefundAmount)) - { - m_Landlord.SendLocalizedMessage( - 1060398, - m_RefundAmount.ToString() - ); // ~1_AMOUNT~ gold has been withdrawn from your bank box. + price = -1; + } - var depositedGold = Banker.DepositUpTo(from, m_RefundAmount); - - if (depositedGold > 0) - { - from.SendLocalizedMessage( - 1060397, - depositedGold.ToString() - ); // ~1_AMOUNT~ gold has been deposited into your bank box. - } - - m_Vendor.HoldGold += m_RefundAmount - depositedGold; - - m_Vendor.Destroy(false); - - from.SendLocalizedMessage(1071990); // Remember to claim your vendor's belongings from the house sign! - } - else - { - m_Landlord.SendLocalizedMessage(1062507); // You do not have that much money in your bank account. - } + if (price < 0) + { + from.SendLocalizedMessage(1062485); // Invalid entry. Rental fee set to 0. + _vendor.RenewalPrice = 0; + } + else if (price > 5000000) + { + _vendor.RenewalPrice = 5000000; } else { - m_Landlord.SendLocalizedMessage(1062513); // The renter declined your offer. + _vendor.RenewalPrice = price; + } + + _vendor.RenterRenew = false; + + DisplayTo(from, _vendor); + } + + public override void OnCancel(Mobile from) + { + if (_vendor.CanInteractWith(from, false) && _vendor.IsLandlord(from)) + { + DisplayTo(from, _vendor); } } } } + +public class VendorRentalRefundGump : StaticGump +{ + private readonly Mobile _landlord; + private readonly int _refundAmount; + private readonly RentedVendor _vendor; + + public override bool Singleton => true; + + private VendorRentalRefundGump(RentedVendor vendor, Mobile landlord, int refundAmount) : base(50, 50) + { + _vendor = vendor; + _landlord = landlord; + _refundAmount = refundAmount; + } + + public static void DisplayTo(Mobile to, RentedVendor vendor, Mobile landlord, int refundAmount) + { + if (to?.NetState == null || vendor?.Deleted != false || landlord == null) + { + return; + } + + to.SendGump(new VendorRentalRefundGump(vendor, landlord, refundAmount)); + } + + protected override void BuildLayout(ref StaticGumpBuilder builder) + { + builder.AddPage(); + + builder.AddBackground(0, 0, 420, 320, 0x13BE); + + builder.AddImageTiled(10, 10, 400, 300, 0xA40); + builder.AddAlphaRegion(10, 10, 400, 300); + + /* The landlord for this vendor is offering you a partial refund of your rental fee + * in exchange for immediate termination of your rental contract.

+ * + * If you accept this offer, the vendor will be immediately dismissed. You will then + * be able to claim the inventory and any funds the vendor may be holding for you via + * a context menu on the house sign for this house. + */ + builder.AddHtmlLocalized(10, 10, 400, 150, 1062501, 0x7FFF, false, true); + + builder.AddHtmlLocalized(10, 180, 150, 20, 1062508, 0x7FFF); // Vendor Name: + builder.AddLabelPlaceholder(160, 180, 0x480, "vendorName"); + + builder.AddHtmlLocalized(10, 200, 150, 20, 1062509, 0x7FFF); // Shop Name: + builder.AddLabelPlaceholder(160, 200, 0x480, "shopName"); + + builder.AddHtmlLocalized(10, 220, 150, 20, 1062510, 0x7FFF); // Refund Amount: + builder.AddLabelPlaceholder(160, 220, 0x480, "refundAmount"); + + builder.AddButton(10, 268, 0xFA5, 0xFA7, 1); + builder.AddHtmlLocalized(45, 268, 350, 20, 1062511, 0x7FFF); // Agree, and dismiss vendor + + builder.AddButton(10, 288, 0xFA5, 0xFA7, 0); + builder.AddHtmlLocalized(45, 288, 350, 20, 1062512, 0x7FFF); // No, I want to keep my vendor + } + + protected override void BuildStrings(ref GumpStringsBuilder builder) + { + builder.SetStringSlot("vendorName", _vendor.Name); + builder.SetStringSlot("shopName", _vendor.ShopName); + builder.SetStringSlot("refundAmount", $"{_refundAmount}"); + } + + public override void OnResponse(NetState sender, in RelayInfo info) + { + var from = sender.Mobile; + + if (!_vendor.CanInteractWith(from, true) || !_vendor.CanInteractWith(_landlord, false) || + !_vendor.IsLandlord(_landlord)) + { + return; + } + + if (info.ButtonID != 1) + { + _landlord.SendLocalizedMessage(1062513); // The renter declined your offer. + return; + } + + if (!Banker.Withdraw(_landlord, _refundAmount)) + { + _landlord.SendLocalizedMessage(1062507); // You do not have that much money in your bank account. + return; + } + + // ~1_AMOUNT~ gold has been withdrawn from your bank box. + _landlord.SendLocalizedMessage(1060398, _refundAmount.ToString()); + + var depositedGold = Banker.DepositUpTo(from, _refundAmount); + + if (depositedGold > 0) + { + // ~1_AMOUNT~ gold has been deposited into your bank box. + from.SendLocalizedMessage(1060397, depositedGold.ToString()); + } + + _vendor.HoldGold += _refundAmount - depositedGold; + + _vendor.Destroy(false); + + from.SendLocalizedMessage(1071990); // Remember to claim your vendor's belongings from the house sign! + } +} diff --git a/Projects/UOContent/Items/Deeds/VendorRentalContract.cs b/Projects/UOContent/Items/Deeds/VendorRentalContract.cs index d97d1f26a..3863cfe88 100644 --- a/Projects/UOContent/Items/Deeds/VendorRentalContract.cs +++ b/Projects/UOContent/Items/Deeds/VendorRentalContract.cs @@ -195,7 +195,7 @@ public partial class VendorRentalContract : Item { if (from.InRange(this, 5)) { - from.SendGump(new VendorRentalContractGump(this, from), true); + VendorRentalContractGump.DisplayTo(from, this); } else { @@ -231,7 +231,7 @@ public partial class VendorRentalContract : Item { if (target is VendorRentalContract contract && contract.IsUsableBy(from, true, true, true, true)) { - from.SendGump(new VendorRentalContractGump(contract, from), true); + VendorRentalContractGump.DisplayTo(from, contract); } } } diff --git a/Projects/UOContent/Mobiles/PlayerMobile.cs b/Projects/UOContent/Mobiles/PlayerMobile.cs index 529ebbf6e..bd83d1c71 100644 --- a/Projects/UOContent/Mobiles/PlayerMobile.cs +++ b/Projects/UOContent/Mobiles/PlayerMobile.cs @@ -2006,7 +2006,7 @@ namespace Server.Mobiles if (CheckAlive() && house?.IsOwner(this) == true && house.InternalizedVendors.Count > 0 && NetState is NetState { } ns) { - ns.SendGump(new ReclaimVendorGump(house)); + ReclaimVendorGump.DisplayTo(this, house); } } diff --git a/Projects/UOContent/Mobiles/Vendors/RentedVendor.cs b/Projects/UOContent/Mobiles/Vendors/RentedVendor.cs index 64977022a..99d818826 100644 --- a/Projects/UOContent/Mobiles/Vendors/RentedVendor.cs +++ b/Projects/UOContent/Mobiles/Vendors/RentedVendor.cs @@ -203,13 +203,13 @@ public partial class RentedVendor : PlayerVendor if (vendor.IsOwner(from)) { - from.SendGump(new RenterVendorRentalGump(vendor), true); + RenterVendorRentalGump.DisplayTo(from, vendor); vendor.SendRentalExpireMessage(from); } else if (vendor.IsLandlord(from)) { - from.SendGump(new LandlordVendorRentalGump(vendor), true); + LandlordVendorRentalGump.DisplayTo(from, vendor); vendor.SendRentalExpireMessage(from); } @@ -311,7 +311,7 @@ public partial class RentedVendor : PlayerVendor { from.SendLocalizedMessage(1062504); // Please wait while the renter considers your offer. - owner.SendGump(new VendorRentalRefundGump(m_Vendor, from, amount)); + VendorRentalRefundGump.DisplayTo(owner, m_Vendor, from, amount); } } } diff --git a/Projects/UOContent/Multis/Houses/HouseSign.cs b/Projects/UOContent/Multis/Houses/HouseSign.cs index 72237ca25..750651dbd 100644 --- a/Projects/UOContent/Multis/Houses/HouseSign.cs +++ b/Projects/UOContent/Multis/Houses/HouseSign.cs @@ -263,7 +263,7 @@ public partial class HouseSign : Item } else { - from.SendGump(new VendorInventoryGump(sign.Owner, from)); + VendorInventoryGump.DisplayTo(from, sign.Owner); } } }