## Summary Migrates the eight concrete New Guild System gumps (CreateGuild, GuildInfo, GuildMemberInfo, GuildRoster, GuildDiplomacy, WarDeclaration, GuildAdvancedSearch, GuildInvitationRequest) and three abstract bases (BaseGuildGump, BaseGuildListGump, OtherGuildInfo) from the legacy `Gump` class to `DynamicGump`. Layout work moves from constructor-side `AddX(...)` calls into `BuildLayout(ref DynamicGumpBuilder builder)` — the abstract `BaseGuildGump` now provides a `BuildContent` callout for shared tab-strip chrome, and `BaseGuildListGump<T>` adds another `BuildListExtras` hook so subclasses can paint highlighted titles after the filter/sort/pagination chrome. The headline win is the **self-refresh pattern** on the list gumps and diplomacy advanced search. Previously each filter/sort/back/forward click allocated a brand new gump via `GetResentGump`. After migration, those handlers mutate `_filter`, `_startNumber`, `_comparer`, `_ascending`, or `_display` on the existing gump and call `from.SendGump(this)`, letting the singleton path in `NetStateGumps.Send` swap in the same instance with the new layout. The original list is preserved separately from the per-render filtered/sorted `_displayList`, so refreshes pick up the latest state without losing the source list. All guild gumps deal with per-instance dynamic strings (guild names, member names, war declarations, alliance names), which would defeat `StaticGump<T>` caching per the cliloc rule, so every concrete subclass migrates to `DynamicGump`. `AllianceRosterGump` (in `Misc/Guild.cs`) is a `GuildDiplomacyGump` subclass and inherits the new behavior; its unused override and stored alliance reference were dropped along with the now-obsolete `GetResentGump` abstract.
297 lines
9.4 KiB
C#
297 lines
9.4 KiB
C#
using System.Collections.Generic;
|
|
using Server.Factions;
|
|
using Server.Gumps;
|
|
using Server.Mobiles;
|
|
using Server.Network;
|
|
using Server.Targeting;
|
|
|
|
namespace Server.Guilds
|
|
{
|
|
public class GuildRosterGump : BaseGuildListGump<PlayerMobile>
|
|
{
|
|
private static readonly InfoField<PlayerMobile>[] _fields =
|
|
[
|
|
new(1062955, 130, NameComparer.Instance), // Name
|
|
new(1062956, 80, RankComparer.Instance), // Rank
|
|
new(1062952, 80, LastOnComparer.Instance), // Last On
|
|
new(1062953, 150, TitleComparer.Instance) // Guild Title
|
|
];
|
|
|
|
public GuildRosterGump(PlayerMobile pm, Guild g) : this(pm, g, LastOnComparer.Instance)
|
|
{
|
|
}
|
|
|
|
public GuildRosterGump(
|
|
PlayerMobile pm, Guild g, IComparer<PlayerMobile> currentComparer, bool ascending = false,
|
|
string filter = "", int startNumber = 0
|
|
)
|
|
: base(
|
|
pm,
|
|
g,
|
|
g.Members.SafeConvertList<Mobile, PlayerMobile>(),
|
|
currentComparer,
|
|
ascending,
|
|
filter,
|
|
startNumber,
|
|
_fields
|
|
)
|
|
{
|
|
}
|
|
|
|
protected override void BuildListExtras(ref DynamicGumpBuilder builder)
|
|
{
|
|
builder.AddHtmlLocalized(266, 43, 110, 26, 1062974, 0xF); // Guild Roster
|
|
}
|
|
|
|
protected override void DrawEndingEntry(ref DynamicGumpBuilder builder, int itemNumber)
|
|
{
|
|
builder.AddBackground(225, 148 + itemNumber * 28, 150, 26, 0x2486);
|
|
builder.AddButton(230, 153 + itemNumber * 28, 0x845, 0x846, 8);
|
|
builder.AddHtmlLocalized(255, 151 + itemNumber * 28, 110, 26, 1062992, 0x0); // Invite Player
|
|
}
|
|
|
|
protected override TextDefinition[] GetValuesFor(PlayerMobile pm, int aryLength)
|
|
{
|
|
var defs = new TextDefinition[aryLength];
|
|
|
|
var name = $"{pm.Name}{(Player.GuildFealty == pm && Player.GuildFealty != Guild.Leader ? " *" : "")}";
|
|
|
|
if (pm == Player)
|
|
{
|
|
name = name.Color(0x006600);
|
|
}
|
|
else if (pm.NetState != null)
|
|
{
|
|
name = name.Color(0x000066);
|
|
}
|
|
|
|
defs[0] = name;
|
|
defs[1] = pm.GuildRank.Name;
|
|
defs[2] = pm.NetState != null ? 1063015 : pm.LastOnline.ToString("yyyy-MM-dd");
|
|
defs[3] = pm.GuildTitle ?? "";
|
|
|
|
return defs;
|
|
}
|
|
|
|
protected override bool IsFiltered(PlayerMobile pm, string filter)
|
|
{
|
|
if (pm == null)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return !pm.Name.InsensitiveContains(filter);
|
|
}
|
|
|
|
public override BaseGump GetObjectInfoGump(PlayerMobile pm, Guild g, PlayerMobile o) =>
|
|
new GuildMemberInfoGump(pm, g, o, false, false);
|
|
|
|
public override void OnResponse(NetState sender, in RelayInfo info)
|
|
{
|
|
base.OnResponse(sender, info);
|
|
|
|
if (sender.Mobile is not PlayerMobile pm || !IsMember(pm, Guild))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (info.ButtonID == 8)
|
|
{
|
|
if (pm.GuildRank.GetFlag(RankFlags.CanInvitePlayer))
|
|
{
|
|
pm.SendLocalizedMessage(1063048); // Whom do you wish to invite into your guild?
|
|
pm.BeginTarget(-1, false, TargetFlags.None, InvitePlayer_Callback, Guild);
|
|
}
|
|
else
|
|
{
|
|
pm.SendLocalizedMessage(503301); // You don't have permission to do that.
|
|
}
|
|
}
|
|
}
|
|
|
|
public void InvitePlayer_Callback(Mobile from, object targeted, Guild g)
|
|
{
|
|
var pm = from as PlayerMobile;
|
|
var targ = targeted as PlayerMobile;
|
|
|
|
var guildState = PlayerState.Find(g.Leader);
|
|
var targetState = PlayerState.Find(targ);
|
|
|
|
var guildFaction = guildState?.Faction;
|
|
var targetFaction = targetState?.Faction;
|
|
|
|
if (pm == null || !IsMember(pm, Guild) || !pm.GuildRank.GetFlag(RankFlags.CanInvitePlayer))
|
|
{
|
|
from.SendLocalizedMessage(503301); // You don't have permission to do that.
|
|
}
|
|
else if (targ == null)
|
|
{
|
|
pm.SendLocalizedMessage(1063334); // That isn't a valid player.
|
|
}
|
|
else if (!targ.AcceptGuildInvites)
|
|
{
|
|
pm.SendLocalizedMessage(1063049, targ.Name); // ~1_val~ is not accepting guild invitations.
|
|
}
|
|
else if (g.IsMember(targ))
|
|
{
|
|
pm.SendLocalizedMessage(1063050, targ.Name); // ~1_val~ is already a member of your guild!
|
|
}
|
|
else if (targ.Guild != null)
|
|
{
|
|
pm.SendLocalizedMessage(1063051, targ.Name); // ~1_val~ is already a member of a guild.
|
|
}
|
|
// TODO: Check message if CreateGuildGump Open
|
|
else if (targ.HasGump<BaseGuildGump>() || targ.HasGump<CreateGuildGump>())
|
|
{
|
|
pm.SendLocalizedMessage(1063052, targ.Name); // ~1_val~ is currently considering another guild invitation.
|
|
}
|
|
else if (targ.Young && guildFaction != null)
|
|
{
|
|
pm.SendLocalizedMessage(1070766); // You cannot invite a young player to your faction-aligned guild.
|
|
}
|
|
else if (guildFaction != targetFaction)
|
|
{
|
|
if (guildFaction == null)
|
|
{
|
|
pm.SendLocalizedMessage(1013027); // That player cannot join a non-faction guild.
|
|
}
|
|
else if (targetFaction == null)
|
|
{
|
|
pm.SendLocalizedMessage(1013026); // That player must be in a faction before joining this guild.
|
|
}
|
|
else
|
|
{
|
|
pm.SendLocalizedMessage(1013028); // That person has a different faction affiliation.
|
|
}
|
|
}
|
|
else if (targetState?.IsLeaving == true)
|
|
{
|
|
// OSI does this quite strangely, so we'll just do it this way
|
|
pm.SendMessage("That person is quitting their faction and so you may not recruit them.");
|
|
}
|
|
else
|
|
{
|
|
pm.SendLocalizedMessage(1063053, targ.Name); // You invite ~1_val~ to join your guild.
|
|
targ.SendGump(new GuildInvitationRequest(targ, Guild, pm));
|
|
}
|
|
}
|
|
|
|
private class NameComparer : IComparer<PlayerMobile>
|
|
{
|
|
public static readonly IComparer<PlayerMobile> Instance = new NameComparer();
|
|
|
|
public int Compare(PlayerMobile x, PlayerMobile y)
|
|
{
|
|
if (x == null && y == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (x == null)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (y == null)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return x.Name.InsensitiveCompare(y.Name);
|
|
}
|
|
}
|
|
|
|
private class LastOnComparer : IComparer<PlayerMobile>
|
|
{
|
|
public static readonly IComparer<PlayerMobile> Instance = new LastOnComparer();
|
|
|
|
public int Compare(PlayerMobile x, PlayerMobile y)
|
|
{
|
|
if (x == null && y == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (x == null)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (y == null)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
var aState = x.NetState;
|
|
var bState = y.NetState;
|
|
|
|
if (aState == null && bState == null)
|
|
{
|
|
return x.LastOnline.CompareTo(y.LastOnline);
|
|
}
|
|
|
|
if (aState == null)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (bState == null)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
private class TitleComparer : IComparer<PlayerMobile>
|
|
{
|
|
public static readonly IComparer<PlayerMobile> Instance = new TitleComparer();
|
|
|
|
public int Compare(PlayerMobile x, PlayerMobile y)
|
|
{
|
|
if (x == null && y == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (x == null)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (y == null)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return x.GuildTitle.InsensitiveCompare(y.GuildTitle);
|
|
}
|
|
}
|
|
|
|
private class RankComparer : IComparer<PlayerMobile>
|
|
{
|
|
public static readonly IComparer<PlayerMobile> Instance = new RankComparer();
|
|
|
|
public int Compare(PlayerMobile x, PlayerMobile y)
|
|
{
|
|
if (x == null && y == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (x == null)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (y == null)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return x.GuildRank.Rank.CompareTo(y.GuildRank.Rank);
|
|
}
|
|
}
|
|
}
|
|
}
|