ModernUO/Projects/UOContent/Holiday Stuff/Valentine/2011/Items/StValentinesBears.cs
Kamron Batman ec85d97482
perf: Migrate Holiday and Decorative gumps to DynamicGump/StaticGump (#2413)
## Summary

Migrates 10 player-facing legacy `Gump` subclasses for holiday and decorative items to the modern `DynamicGump` / `StaticGump<T>` system. All migrated gumps are `Singleton`, use private constructors gated by static `DisplayTo(...)` entry points (empty-gump rule, CLAUDE.md §13), and replace legacy `m_X` fields with `_x` per coding standards.

Per-gump base type and rationale:

- **Mistletoe.cs** — `MistletoeAddonGump` -> `StaticGump<MistletoeAddonGump>`. Fixed re-deed confirmation layout.
- **StValentinesBears.cs** — Renamed `InternalGump` -> `StValentinesBearsGump`, base `StaticGump<T>`. Fixed sign-bear layout with three text entries; legacy `m_Bear` -> `_bear`. Switched legacy `AddTextEntry(..., size)` -> `AddTextEntryLimited(...)` (modern API split).
- **Wreath.cs** — `WreathAddonGump` -> `StaticGump<WreathAddonGump>`. Fixed re-deed confirmation layout.
- **HolidayPottedPlant.cs** — Renamed `InternalGump` -> `HolidayPottedPlantGump`, base `StaticGump<T>`. Fixed plant-picker layout.
- **SnowStatue.cs** — Renamed `InternalGump` -> `SnowStatueGump`, base `StaticGump<T>`. Fixed statue-picker layout. Dropped unused `Mobile from` ctor arg.
- **TapestryOfSosaria.cs** — Renamed `InternalGump` -> `TapestryOfSosariaGump`, base `StaticGump<T>`. Single image, fixed.
- **HouseRaffleDeed.cs** — `WritOfLeaseGump` -> `DynamicGump`. Description HTML is computed per-instance from deed expiration / days-left, so layout text varies per instance. Added `Singleton => true` (was missing implicitly via legacy default).
- **SpecialScroll.cs** — Renamed `InternalGump` -> `SpecialScrollGump`, base `DynamicGump`. **Cliloc rule**: `_scroll.Message`, `_scroll.Title`, `_scroll.SkillLabel` are dynamic cliloc numbers per scroll type — `AddHtmlLocalized` bakes the cliloc number into the cached layout, so `StaticGump<T>` cannot cache it.
- **BallotBox.cs** — Renamed `InternalGump` -> `BallotBoxGump`, base `DynamicGump`. Layout shape varies: variable topic-line count, owner-vs-voter buttons, and vote-tally bars all add/remove elements. Legacy `m_Box` -> `_box`. Updated the `TopicPrompt` callbacks to call `BallotBoxGump.DisplayTo(...)` instead of allocating a new gump directly.
- **AquariumGump.cs** — `AquariumGump` -> `DynamicGump`. Per-page layout depends on each item's `LabelNumber` and (for `BaseFish`) `GetDescription()` cliloc — those vary per fish/decoration. Two `DisplayTo` overloads (auto-detect access vs explicit edit flag) to mirror the original two call sites in `Aquarium.cs`. Legacy `m_Aquarium` -> `_aquarium`.

### Skipped

- **HouseRaffleManagementGump.cs** — Skipped as **staff-only**. Only invoked via `ManagementEntry` context entry inside `HouseRaffleStone.cs`, gated by `from.AccessLevel >= AccessLevel.Seer`. Per task instructions, staff-only gumps are out of scope for this PR.

### External callers updated

- `Aquarium.cs` — Two `new AquariumGump(...)` sites swapped to `AquariumGump.DisplayTo(...)`.

All other migrated inner classes were nested in the same file and only had local references, which were updated to call the new `DisplayTo(...)` static entry point.
2026-04-25 17:22:41 -07:00

220 lines
7.1 KiB
C#

using System;
using ModernUO.Serialization;
using Server.Gumps;
using Server.Network;
namespace Server.Items
{
[SerializationGenerator(0, false)]
public abstract partial class StValentinesBear : Item
{
[InternString]
[InvalidateProperties]
[SerializableField(0)]
[SerializedCommandProperty(AccessLevel.GameMaster)]
private string _owner;
[InternString]
[InvalidateProperties]
[SerializableField(1)]
[SerializedCommandProperty(AccessLevel.GameMaster)]
private string _line1;
[InternString]
[InvalidateProperties]
[SerializableField(2)]
[SerializedCommandProperty(AccessLevel.GameMaster)]
private string _line2;
[InternString]
[InvalidateProperties]
[SerializableField(3)]
[SerializedCommandProperty(AccessLevel.GameMaster)]
private string _line3;
public StValentinesBear(int itemid, string name) : base(itemid)
{
Owner = name;
LootType = LootType.Blessed;
}
public override string DefaultName => _owner != null ? $"{_owner}'s St. Valentine Bear" : "St. Valentine Bear";
[CommandProperty(AccessLevel.GameMaster)]
public DateTime EditLimit { get; set; }
public bool IsSigned => _line1 != null || _line2 != null || _line3 != null;
public bool CanSign => !IsSigned || Core.Now <= EditLimit;
public override void AddNameProperty(IPropertyList list)
{
if (_owner != null)
{
list.Add(1150295, _owner); // ~1_NAME~'s St. Valentine Bear
}
else
{
list.Add(1150294); // St. Valentine Bear
}
AddLine(list, 1150301, _line1); // [ ~1_LINE0~ ]
AddLine(list, 1150302, _line2); // [ ~1_LINE1~ ]
AddLine(list, 1150303, _line3); // [ ~1_LINE2~ ]
}
private static void AddLine(IPropertyList list, int cliloc, string line)
{
if (line != null)
{
list.Add(cliloc, line);
}
}
public override void OnSingleClick(Mobile from)
{
base.OnSingleClick(from);
ShowLine(from, 1150301, _line1); // [ ~1_LINE0~ ]
ShowLine(from, 1150302, _line2); // [ ~1_LINE1~ ]
ShowLine(from, 1150303, _line3); // [ ~1_LINE2~ ]
}
private void ShowLine(Mobile from, int cliloc, string line)
{
if (line != null)
{
LabelTo(from, cliloc, line);
}
}
public override void OnDoubleClick(Mobile from)
{
if (!CupidsArrow.CheckSeason(from) || !CanSign)
{
return;
}
if (!IsChildOf(from.Backpack))
{
from.SendLocalizedMessage(1080063); // This must be in your backpack to use it.
return;
}
StValentinesBearsGump.DisplayTo(from, this);
}
private class StValentinesBearsGump : StaticGump<StValentinesBearsGump>
{
private readonly StValentinesBear _bear;
public override bool Singleton => true;
protected override bool Cached => false;
private StValentinesBearsGump(StValentinesBear bear) : base(50, 50)
{
_bear = bear;
}
public static void DisplayTo(Mobile from, StValentinesBear bear)
{
if (from?.NetState == null || bear?.Deleted != false)
{
return;
}
from.SendGump(new StValentinesBearsGump(bear));
}
protected override void BuildLayout(ref StaticGumpBuilder builder)
{
builder.AddPage();
builder.AddBackground(0, 0, 420, 320, 9300);
// St. Valentine Bear
builder.AddHtmlLocalized(10, 10, 400, 21, 1154645, "#1150294", 0);
// Enter up to three lines of personalized greeting for your St. Valentine Bear. You many enter up to 25 characters per line. Once you enter text, you will only be able to correct mistakes for 10 minutes.
builder.AddHtmlLocalized(10, 40, 400, 75, 1150293, 0);
builder.AddHtmlLocalized(10, 129, 400, 21, 1150296, 0); // Line 1:
builder.AddBackground(10, 150, 400, 24, 9350);
builder.AddTextEntryLimited(15, 152, 390, 20, 0, 0, "", 25);
builder.AddHtmlLocalized(10, 179, 400, 21, 1150297, 0); // Line 2:
builder.AddBackground(10, 200, 400, 24, 9350);
builder.AddTextEntryLimited(15, 202, 390, 20, 0, 1, "", 25);
builder.AddHtmlLocalized(10, 229, 400, 21, 1150298, 0); // Line 3:
builder.AddBackground(10, 250, 400, 24, 9350);
builder.AddTextEntryLimited(15, 252, 390, 20, 0, 2, "", 25);
builder.AddButton(15, 285, 242, 241, 0);
builder.AddButton(335, 285, 247, 248, 1);
}
public override void OnResponse(NetState sender, in RelayInfo info)
{
var from = sender.Mobile;
if (_bear.Deleted || !_bear.IsChildOf(from.Backpack) || !_bear.CanSign || info.ButtonID != 1)
{
return;
}
var line1 = GetLine(info, 0);
var line2 = GetLine(info, 1);
var line3 = GetLine(info, 2);
if (string.IsNullOrEmpty(line1)
|| string.IsNullOrEmpty(line2)
|| string.IsNullOrEmpty(line3))
{
from.SendMessage("Lines cannot be left blank.");
return;
}
if (line1.Length > 25
|| line2.Length > 25
|| line3.Length > 25)
{
from.SendMessage("Lines may not exceed 25 characters.");
return;
}
if (!_bear.IsSigned)
{
_bear.EditLimit = Core.Now + TimeSpan.FromMinutes(10);
}
_bear.Line1 = line1.FixHtml();
_bear.Line2 = line2.FixHtml();
_bear.Line3 = line3.FixHtml();
from.SendMessage("You add the personalized greeting to your St. Valentine Bear.");
}
private static string GetLine(RelayInfo info, int idx) => info.GetTextEntry(idx);
}
}
[SerializationGenerator(0, false)]
[Flippable(0x48E0, 0x48E1)]
public partial class StValentinesPanda : StValentinesBear
{
[Constructible]
public StValentinesPanda(string name = null) : base(0x48E0, name)
{
}
}
[SerializationGenerator(0, false)]
[Flippable(0x48E2, 0x48E3)]
public partial class StValentinesPolarBear : StValentinesBear
{
[Constructible]
public StValentinesPolarBear(string name = null) : base(0x48E2, name)
{
}
}
}