From 8a3490332636a5f97bf46434040a851e14c3017e Mon Sep 17 00:00:00 2001
From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com>
Date: Wed, 8 Apr 2026 11:42:46 -0600
Subject: [PATCH] feat: Consolidates staff gump layouts (#2404)
## Summary
- Creates `PropsLayoutExtensions.cs` with reusable extension methods for both legacy `Gump` and `DynamicGumpBuilder` that encapsulate the repeating PropsConfig-style layout patterns (frame, header navigation, entry rows)
- Converts all 12 standardized staff gumps to use the new extensions, reducing ~570 lines of duplicated layout code
- Adds Type and Serial display to PropsGump and SkillsGump headers (e.g. `PlayerMobile (0x1)`)
### Extension methods provided
| Method | Pattern |
|--------|---------|
| `AddPropsFrame` | Background + offset region + origin coordinates |
| `AddPropsHeader` | 3-column: [Prev] [Title] [Next] |
| `AddPropsHeaderWithBack` | 4-column: [Back] [Title] [Prev] [Next] |
| `AddPropsEntryButton` | Label + action button |
| `AddPropsEntryNameValue` | Name + Value + action button |
| `AddPropsEntryTextInput` | Text input + action button |
| `AddPropsEntryLabel` | Label only (no button) |
| `AddPropsEntryType` | Full-width type label |
| `AddPropsEntryBlank` | Separator row |
### Gumps converted
PropsGump, GoGump, WhoGump, SkillsGump (frame+header), EditSkillGump, SetGump, SetObjectGump, SetPoint2DGump, SetPoint3DGump, SetTimeSpanGump (frame), SetListOptionGump (frame+header), CategorizedAddGump (frame+header)
## Test plan
- [x] Verify `[props` gump displays correctly with type + serial in header
- [x] Verify `[skills` gump displays correctly with type + serial in header
- [x] Verify `[go` navigation gump works (prev/next/back)
- [x] Verify property editing gumps (Set, SetObject, SetPoint2D, SetPoint3D, SetTimeSpan, SetListOption)
- [x] Verify `[categorizedadd` gump works
- [x] Verify `[who` gump works with pagination
---
.../Object Creation/CategorizedAddGump.cs | 63 +-
.../Engines/Spawners/SpawnPropsGump.cs | 28 +-
Projects/UOContent/Gumps/Go/GoGump.cs | 64 +-
Projects/UOContent/Gumps/Props/PropsGump.cs | 85 +--
.../Gumps/Props/PropsLayoutExtensions.cs | 677 ++++++++++++++++++
Projects/UOContent/Gumps/Props/SetGump.cs | 80 +--
.../Gumps/Props/SetListOptionGump.cs | 55 +-
.../UOContent/Gumps/Props/SetObjectGump.cs | 84 +--
.../UOContent/Gumps/Props/SetPoint2DGump.cs | 56 +-
.../UOContent/Gumps/Props/SetPoint3DGump.cs | 56 +-
.../UOContent/Gumps/Props/SetTimeSpanGump.cs | 7 +-
Projects/UOContent/Gumps/SkillsGump.cs | 60 +-
Projects/UOContent/Gumps/WhoGump.cs | 41 +-
13 files changed, 786 insertions(+), 570 deletions(-)
create mode 100644 Projects/UOContent/Gumps/Props/PropsLayoutExtensions.cs
diff --git a/Projects/UOContent/Commands/Object Creation/CategorizedAddGump.cs b/Projects/UOContent/Commands/Object Creation/CategorizedAddGump.cs
index 76b4b50af..57bb5d837 100644
--- a/Projects/UOContent/Commands/Object Creation/CategorizedAddGump.cs
+++ b/Projects/UOContent/Commands/Object Creation/CategorizedAddGump.cs
@@ -21,8 +21,6 @@ namespace Server.Gumps
private const int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize;
- private const int BackWidth = BorderSize + TotalWidth + BorderSize;
-
private readonly CAGCategory m_Category;
private readonly Mobile m_Owner;
@@ -50,64 +48,21 @@ namespace Server.Gumps
var count = Math.Clamp(nodes.Length - page * EntryCount, 0, EntryCount);
- var totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1);
-
AddPage(0);
- AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID);
- AddImageTiled(
- BorderSize,
- BorderSize,
- TotalWidth,
- totalHeight,
- OffsetGumpID
+ this.AddPropsFrame(TotalWidth, count + 1, out var x, out var y, EntryHeight);
+ this.AddPropsHeaderWithBack(
+ TotalWidth, ref x, ref y, m_Category.Title,
+ m_Category.Parent != null, 1,
+ page > 0, 2,
+ (page + 1) * EntryCount < nodes.Length, 3,
+ nextType: GumpButtonType.Reply, nextParam: 1,
+ entryHeight: EntryHeight
);
- var x = BorderSize + OffsetSize;
- var y = BorderSize + OffsetSize;
-
- AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID);
-
- if (m_Category.Parent != null)
- {
- AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1);
- }
-
- x += PrevWidth + OffsetSize;
-
- const int emptyWidth = TotalWidth - PrevWidth * 2 - NextWidth - OffsetSize * 5;
- AddImageTiled(x, y, emptyWidth, EntryHeight, EntryGumpID);
-
- AddHtml(
- x + TextOffsetX,
- y + (EntryHeight - 20) / 2,
- emptyWidth - TextOffsetX,
- EntryHeight,
- $"
{m_Category.Title}"
- );
-
- x += emptyWidth + OffsetSize;
-
- AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID);
-
- if (page > 0)
- {
- AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 2);
- }
-
- x += PrevWidth + OffsetSize;
-
- AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID);
-
- if ((page + 1) * EntryCount < nodes.Length)
- {
- AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 3, GumpButtonType.Reply, 1);
- }
-
for (int i = 0, index = page * EntryCount; i < EntryCount && index < nodes.Length; ++i, ++index)
{
- x = BorderSize + OffsetSize;
- y += EntryHeight + OffsetSize;
+ PropsLayout.NextRow(ref x, ref y, EntryHeight);
var node = nodes[index];
diff --git a/Projects/UOContent/Engines/Spawners/SpawnPropsGump.cs b/Projects/UOContent/Engines/Spawners/SpawnPropsGump.cs
index ac06bf61f..4a6732ec9 100644
--- a/Projects/UOContent/Engines/Spawners/SpawnPropsGump.cs
+++ b/Projects/UOContent/Engines/Spawners/SpawnPropsGump.cs
@@ -41,24 +41,14 @@ public class SpawnPropsGump : PropertiesGump
private List