ModernUO/Projects/UOContent/Engines/ExileHunterBestiary/Gumps/HunterBestiaryGump.cs

238 lines
8.8 KiB
C#

using System;
using System.Collections.Generic;
using Server.Gumps;
using Server.Network;
namespace Server.Custom.ExileHunterBestiary.Gumps;
public sealed class HunterBestiaryGump : DynamicGump
{
private const int EntriesPerPage = 10;
private const int ButtonClose = 0;
private const int ButtonNext = 10;
private const int ButtonPrev = 11;
private const int ButtonToggleFilter = 12;
private const int ButtonSearch = 13;
private const int TextSearch = 1;
private const int ButtonCategoryBase = 100;
private const int ButtonCategoryLimit = 150;
private readonly Mobile _player;
private readonly BestiaryCategory _category;
private readonly int _page;
private readonly string _search;
private readonly bool _hideMastered;
public override bool Singleton => true;
private HunterBestiaryGump(Mobile player, BestiaryCategory category, int page, string search, bool hideMastered)
: base(100, 40)
{
_player = player;
_category = category;
_page = page;
_search = search ?? "";
_hideMastered = hideMastered;
}
public static void DisplayTo(
Mobile from, BestiaryCategory category = BestiaryCategory.Undead,
int page = 0, string search = "", bool hideMastered = false)
{
if (from is not { Deleted: false } || !HunterBestiaryEngine.Enabled)
{
return;
}
from.SendGump(new HunterBestiaryGump(from, category, page, search, hideMastered));
}
protected override void BuildLayout(ref DynamicGumpBuilder builder)
{
var profile = HunterBestiaryEngine.TryGetProfile(_player, out var p) ? p : null;
var totalMastered = profile?.TotalMastered ?? 0;
var grandTotal = BestiaryRegistry.TotalCount;
var grandPct = grandTotal > 0 ? totalMastered * 100.0 / grandTotal : 0;
builder.AddPage();
builder.AddBackground(0, 0, 660, 560, 9270);
builder.AddAlphaRegion(10, 10, 640, 540);
builder.AddBackground(14, 14, 632, 532, 9200);
builder.AddAlphaRegion(18, 18, 624, 524);
builder.AddItem(25, 20, 0x2252, 1153);
builder.AddHtml(85, 20, 310, 24, "<BASEFONT COLOR=#FFFFFF SIZE=5>The Grand Hunter's Bestiary</BASEFONT>");
builder.AddHtml(85, 46, 310, 20, "<BASEFONT COLOR=#D1C4E9 SIZE=3>Studied Treatises & Anatomical Lore</BASEFONT>");
builder.AddHtml(
400, 24, 240, 22,
$"<BASEFONT COLOR=#ECEFF1>Overall: <BASEFONT COLOR=#00FFCC>{totalMastered}/{grandTotal}</BASEFONT> ({grandPct:F0}%)</BASEFONT>"
);
builder.AddHtml(
400, 46, 240, 20,
$"<BASEFONT COLOR=#FFE082>Cap +{HunterBestiaryEngine.TotalBonusCap:P0}"
+ $" - {(HunterBestiaryEngine.DamageMode == DamageMode.Mark ? "Hunter's Mark" : "Multiplier")}</BASEFONT>"
);
builder.AddImageTiled(20, 72, 620, 2, 9354);
builder.AddImageTiled(195, 78, 2, 428, 9354);
var catY = 82;
foreach (var cat in Enum.GetValues<BestiaryCategory>())
{
var selected = cat == _category;
var catTotal = BestiaryRegistry.ByCategory[cat].Count;
var catMastered = profile?.GetCategoryMasteredCount(cat) ?? 0;
builder.AddButton(24, catY + 4, selected ? 4006 : 4005, 4007, ButtonCategoryBase + (int)cat);
var catColor = selected ? "#00FFCC" : catMastered == catTotal && catTotal > 0 ? "#69F0AE" : "#ECEFF1";
builder.AddHtml(
60, catY + 5, 130, 20,
$"<BASEFONT COLOR={catColor}>{cat}</BASEFONT> <BASEFONT COLOR=#90A4AE>({catMastered}/{catTotal})</BASEFONT>"
);
catY += 34;
}
builder.AddButton(24, catY + 8, _hideMastered ? 4006 : 4005, 4007, ButtonToggleFilter);
builder.AddHtml(
60, catY + 9, 130, 20,
$"<BASEFONT COLOR={(_hideMastered ? "#00FFCC" : "#ECEFF1")}>Hide mastered</BASEFONT>"
);
var catList = BestiaryRegistry.ByCategory[_category];
var catLearned = profile?.GetCategoryMasteredCount(_category) ?? 0;
var catPct = catList.Count > 0 ? catLearned * 100.0 / catList.Count : 0;
builder.AddHtml(205, 82, 430, 24, $"<BASEFONT COLOR=#FFFFFF SIZE=4>{_category} Studies</BASEFONT>");
builder.AddHtml(
205, 106, 430, 20,
$"<BASEFONT COLOR=#ECEFF1>Mastery: <BASEFONT COLOR=#00FFCC>{catLearned} / {catList.Count}</BASEFONT> ({catPct:F0}%)"
+ $" - milestone bonus up to +{HunterBestiaryEngine.CategoryMilestoneBonus:P0}</BASEFONT>"
);
builder.AddTextEntry(205, 132, 300, 22, 0x480, TextSearch, _search);
builder.AddButton(512, 132, 4005, 4007, ButtonSearch);
builder.AddHtml(548, 134, 80, 20, "<BASEFONT COLOR=#ECEFF1>Search</BASEFONT>");
builder.AddImageTiled(200, 160, 435, 2, 9354);
var filtered = new List<HunterCreatureEntry>(catList.Count);
foreach (var entry in catList)
{
var learned = profile != null && profile.HasLearned(entry.Id);
if (_hideMastered && learned)
{
continue;
}
if (_search.Length > 0 &&
entry.DisplayName.Contains(_search, StringComparison.OrdinalIgnoreCase) == false)
{
continue;
}
filtered.Add(entry);
}
filtered.Sort(static (a, b) => string.CompareOrdinal(a.DisplayName, b.DisplayName));
var maxPages = Math.Max(1, (filtered.Count + EntriesPerPage - 1) / EntriesPerPage);
var page = Math.Clamp(_page, 0, maxPages - 1);
var start = page * EntriesPerPage;
var end = Math.Min(start + EntriesPerPage, filtered.Count);
var categoryFraction = catList.Count > 0 ? (double)catLearned / catList.Count : 0;
var entryY = 170;
for (var i = start; i < end; i++)
{
var creature = filtered[i];
var learned = profile != null && profile.HasLearned(creature.Id);
var bonus = (learned ? HunterBestiaryEngine.PerCreatureBonus : 0.0)
+ HunterBestiaryEngine.CategoryMilestoneBonus * categoryFraction;
bonus = Math.Min(bonus, HunterBestiaryEngine.TotalBonusCap);
builder.AddBackground(200, entryY, 435, 32, learned ? 9200 : 9300);
builder.AddAlphaRegion(202, entryY + 2, 431, 28);
builder.AddImage(207, entryY + 5, learned ? 4017 : 4020);
var nameColor = learned ? "#FFFFFF" : "#B0BEC5";
builder.AddHtml(250, entryY + 6, 185, 20, $"<BASEFONT COLOR={nameColor}>{creature.DisplayName}</BASEFONT>");
builder.AddHtml(
440, entryY + 6, 190, 20,
learned
? $"<BASEFONT COLOR=#69F0AE>Mastered - +{HunterBestiaryEngine.PerCreatureBonus:P0} (+{bonus:P0} total)</BASEFONT>"
: $"<BASEFONT COLOR=#78909C>Pending Treatise - +{bonus:P0} milestone</BASEFONT>"
);
entryY += 36;
}
builder.AddImageTiled(20, 520, 620, 2, 9354);
builder.AddButton(30, 528, 4017, 4019, ButtonClose);
builder.AddHtml(65, 530, 50, 20, "<BASEFONT COLOR=#FFFFFF>Close</BASEFONT>");
if (page > 0)
{
builder.AddButton(200, 528, 4014, 4016, ButtonPrev);
builder.AddHtml(236, 530, 60, 20, "<BASEFONT COLOR=#ECEFF1>Previous</BASEFONT>");
}
builder.AddHtml(360, 530, 120, 20, $"<BASEFONT COLOR=#B0BEC5>Page {page + 1} of {maxPages}</BASEFONT>");
if (page < maxPages - 1)
{
builder.AddButton(560, 528, 4005, 4007, ButtonNext);
builder.AddHtml(590, 530, 40, 20, "<BASEFONT COLOR=#ECEFF1>Next</BASEFONT>");
}
}
public override void OnResponse(NetState sender, in RelayInfo info)
{
if (sender.Mobile is not { } from)
{
return;
}
var search = info.GetTextEntry(TextSearch)?.Trim() ?? _search;
switch (info.ButtonID)
{
case ButtonClose:
return;
case ButtonNext:
DisplayTo(from, _category, _page + 1, search, _hideMastered);
return;
case ButtonPrev:
DisplayTo(from, _category, Math.Max(0, _page - 1), search, _hideMastered);
return;
case ButtonToggleFilter:
DisplayTo(from, _category, 0, search, !_hideMastered);
return;
case ButtonSearch:
DisplayTo(from, _category, 0, search, _hideMastered);
return;
default:
{
if (info.ButtonID is >= ButtonCategoryBase and < ButtonCategoryLimit)
{
DisplayTo(from, (BestiaryCategory)(info.ButtonID - ButtonCategoryBase), 0, search, _hideMastered);
}
return;
}
}
}
}