Formats UO Content (#201)

This commit is contained in:
Kamron Batman 2020-08-27 18:30:38 -07:00 • committed by GitHub
parent 86b7b3aed1
commit ad3775c4d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3249 changed files with 431083 additions and 440981 deletions

View file

@ -1,274 +1,289 @@
using System;
using System.Collections.Generic;
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class AcceptDuelGump : Gump
{
private const int LabelColor32 = 0xFFFFFF;
private const int BlackColor32 = 0x000008;
private static readonly Dictionary<Mobile, List<IgnoreEntry>> m_IgnoreLists = new Dictionary<Mobile, List<IgnoreEntry>>();
private bool m_Active = true;
private readonly Mobile m_Challenger;
private readonly Mobile m_Challenged;
private readonly DuelContext m_Context;
private readonly Participant m_Participant;
private readonly int m_Slot;
public AcceptDuelGump(Mobile challenger, Mobile challenged, DuelContext context, Participant p, int slot) : base(50,
50)
{
m_Challenger = challenger;
m_Challenged = challenged;
m_Context = context;
m_Participant = p;
m_Slot = slot;
challenged.CloseGump<AcceptDuelGump>();
Closable = false;
AddPage(0);
// AddBackground( 0, 0, 400, 220, 9150 );
AddBackground(1, 1, 398, 218, 3600);
// AddBackground( 16, 15, 369, 189, 9100 );
AddImageTiled(16, 15, 369, 189, 3604);
AddAlphaRegion(16, 15, 369, 189);
AddImage(215, -43, 0xEE40);
// AddImage( 330, 141, 0x8BA );
AddHtml(22 - 1, 22, 294, 20, Color(Center("Duel Challenge"), BlackColor32));
AddHtml(22 + 1, 22, 294, 20, Color(Center("Duel Challenge"), BlackColor32));
AddHtml(22, 22 - 1, 294, 20, Color(Center("Duel Challenge"), BlackColor32));
AddHtml(22, 22 + 1, 294, 20, Color(Center("Duel Challenge"), BlackColor32));
AddHtml(22, 22, 294, 20, Color(Center("Duel Challenge"), LabelColor32));
string fmt;
if (p.Contains(challenger))
fmt = "You have been asked to join sides with {0} in a duel. Do you accept?";
else
fmt = "You have been challenged to a duel from {0}. Do you accept?";
AddHtml(22 - 1, 50, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32));
AddHtml(22 + 1, 50, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32));
AddHtml(22, 50 - 1, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32));
AddHtml(22, 50 + 1, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32));
AddHtml(22, 50, 294, 40, Color(string.Format(fmt, challenger.Name), 0xB0C868));
AddImageTiled(32, 88, 264, 1, 9107);
AddImageTiled(42, 90, 264, 1, 9157);
AddRadio(24, 100, 9727, 9730, true, 1);
AddHtml(60 - 1, 105, 250, 20, Color("Yes, I will fight this duel.", BlackColor32));
AddHtml(60 + 1, 105, 250, 20, Color("Yes, I will fight this duel.", BlackColor32));
AddHtml(60, 105 - 1, 250, 20, Color("Yes, I will fight this duel.", BlackColor32));
AddHtml(60, 105 + 1, 250, 20, Color("Yes, I will fight this duel.", BlackColor32));
AddHtml(60, 105, 250, 20, Color("Yes, I will fight this duel.", LabelColor32));
AddRadio(24, 135, 9727, 9730, false, 2);
AddHtml(60 - 1, 140, 250, 20, Color("No, I do not wish to fight.", BlackColor32));
AddHtml(60 + 1, 140, 250, 20, Color("No, I do not wish to fight.", BlackColor32));
AddHtml(60, 140 - 1, 250, 20, Color("No, I do not wish to fight.", BlackColor32));
AddHtml(60, 140 + 1, 250, 20, Color("No, I do not wish to fight.", BlackColor32));
AddHtml(60, 140, 250, 20, Color("No, I do not wish to fight.", LabelColor32));
AddRadio(24, 170, 9727, 9730, false, 3);
AddHtml(60 - 1, 175, 250, 20, Color("No, knave. Do not ask again.", BlackColor32));
AddHtml(60 + 1, 175, 250, 20, Color("No, knave. Do not ask again.", BlackColor32));
AddHtml(60, 175 - 1, 250, 20, Color("No, knave. Do not ask again.", BlackColor32));
AddHtml(60, 175 + 1, 250, 20, Color("No, knave. Do not ask again.", BlackColor32));
AddHtml(60, 175, 250, 20, Color("No, knave. Do not ask again.", LabelColor32));
AddButton(314, 173, 247, 248, 1);
Timer.DelayCall(TimeSpan.FromSeconds(15.0), AutoReject);
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public string Color(string text, int color) => $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
public void AutoReject()
{
if (!m_Active)
return;
m_Active = false;
m_Challenged.CloseGump<AcceptDuelGump>();
m_Challenger.SendMessage("{0} seems unresponsive.", m_Challenged.Name);
m_Challenged.SendMessage("You decline the challenge.");
}
public static void BeginIgnore(Mobile source, Mobile toIgnore)
{
if (!m_IgnoreLists.TryGetValue(source, out List<IgnoreEntry> list))
m_IgnoreLists[source] = list = new List<IgnoreEntry>();
for (int i = 0; i < list.Count; ++i)
{
IgnoreEntry ie = list[i];
if (ie.Ignored == toIgnore)
{
ie.Refresh();
return;
}
if (ie.Expired)
list.RemoveAt(i--);
}
list.Add(new IgnoreEntry(toIgnore));
}
public static bool IsIgnored(Mobile source, Mobile check)
{
if (!m_IgnoreLists.TryGetValue(source, out List<IgnoreEntry> list))
return false;
for (int i = 0; i < list.Count; ++i)
{
IgnoreEntry ie = list[i];
if (ie.Expired)
list.RemoveAt(i--);
else if (ie.Ignored == check)
return true;
}
return false;
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID != 1 || !m_Active || !m_Context.Registered)
return;
m_Active = false;
if (!m_Context.Participants.Contains(m_Participant))
return;
if (info.IsSwitched(1))
{
if (!(m_Challenged is PlayerMobile pm))
return;
if (pm.DuelContext != null)
{
if (pm.DuelContext.Initiator == pm)
pm.SendMessage(0x22, "You have already started a duel.");
else
pm.SendMessage(0x22, "You have already been challenged in a duel.");
m_Challenger.SendMessage("{0} cannot fight because they are already assigned to another duel.", pm.Name);
}
else if (DuelContext.CheckCombat(pm))
{
pm.SendMessage(0x22,
"You have recently been in combat with another player and must wait before starting a duel.");
m_Challenger.SendMessage(
"{0} cannot fight because they have recently been in combat with another player.", pm.Name);
}
else if (TournamentController.IsActive)
{
pm.SendMessage(0x22, "A tournament is currently active and you may not duel.");
m_Challenger.SendMessage(0x22, "A tournament is currently active and you may not duel.");
}
else
{
bool added = false;
if (m_Slot >= 0 && m_Slot < m_Participant.Players.Length && m_Participant.Players[m_Slot] == null)
{
added = true;
m_Participant.Players[m_Slot] = new DuelPlayer(m_Challenged, m_Participant);
}
else
{
for (int i = 0; i < m_Participant.Players.Length; ++i)
if (m_Participant.Players[i] == null)
{
added = true;
m_Participant.Players[i] = new DuelPlayer(m_Challenged, m_Participant);
break;
}
}
if (added)
{
m_Challenger.SendMessage("{0} has accepted the request.", m_Challenged.Name);
m_Challenged.SendMessage("You have accepted the request from {0}.", m_Challenger.Name);
NetState ns = m_Challenger.NetState;
if (ns != null)
foreach (Gump g in ns.Gumps)
{
if (g is ParticipantGump pg && pg.Participant == m_Participant)
{
m_Challenger.SendGump(new ParticipantGump(m_Challenger, m_Context, m_Participant));
break;
}
if (g is DuelContextGump dcg && dcg.Context == m_Context)
{
m_Challenger.SendGump(new DuelContextGump(m_Challenger, m_Context));
break;
}
}
}
else
{
m_Challenger.SendMessage("The participant list was full and so {0} could not join.",
m_Challenged.Name);
m_Challenged.SendMessage(
"The participant list was full and so you could not join the fight {1} {0}.", m_Challenger.Name,
m_Participant.Contains(m_Challenger) ? "with" : "against");
}
}
}
else
{
if (info.IsSwitched(3))
BeginIgnore(m_Challenged, m_Challenger);
m_Challenger.SendMessage("{0} does not wish to fight.", m_Challenged.Name);
m_Challenged.SendMessage("You chose not to fight {1} {0}.", m_Challenger.Name,
m_Participant.Contains(m_Challenger) ? "with" : "against");
}
}
private class IgnoreEntry
{
private static readonly TimeSpan ExpireDelay = TimeSpan.FromMinutes(15.0);
public DateTime m_Expire;
public readonly Mobile m_Ignored;
public IgnoreEntry(Mobile ignored)
{
m_Ignored = ignored;
Refresh();
}
public Mobile Ignored => m_Ignored;
public bool Expired => DateTime.UtcNow >= m_Expire;
public void Refresh()
{
m_Expire = DateTime.UtcNow + ExpireDelay;
}
}
}
}
using System;
using System.Collections.Generic;
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class AcceptDuelGump : Gump
{
private const int LabelColor32 = 0xFFFFFF;
private const int BlackColor32 = 0x000008;
private static readonly Dictionary<Mobile, List<IgnoreEntry>> m_IgnoreLists =
new Dictionary<Mobile, List<IgnoreEntry>>();
private readonly Mobile m_Challenged;
private readonly Mobile m_Challenger;
private readonly DuelContext m_Context;
private readonly Participant m_Participant;
private readonly int m_Slot;
private bool m_Active = true;
public AcceptDuelGump(Mobile challenger, Mobile challenged, DuelContext context, Participant p, int slot) : base(
50,
50
)
{
m_Challenger = challenger;
m_Challenged = challenged;
m_Context = context;
m_Participant = p;
m_Slot = slot;
challenged.CloseGump<AcceptDuelGump>();
Closable = false;
AddPage(0);
// AddBackground( 0, 0, 400, 220, 9150 );
AddBackground(1, 1, 398, 218, 3600);
// AddBackground( 16, 15, 369, 189, 9100 );
AddImageTiled(16, 15, 369, 189, 3604);
AddAlphaRegion(16, 15, 369, 189);
AddImage(215, -43, 0xEE40);
// AddImage( 330, 141, 0x8BA );
AddHtml(22 - 1, 22, 294, 20, Color(Center("Duel Challenge"), BlackColor32));
AddHtml(22 + 1, 22, 294, 20, Color(Center("Duel Challenge"), BlackColor32));
AddHtml(22, 22 - 1, 294, 20, Color(Center("Duel Challenge"), BlackColor32));
AddHtml(22, 22 + 1, 294, 20, Color(Center("Duel Challenge"), BlackColor32));
AddHtml(22, 22, 294, 20, Color(Center("Duel Challenge"), LabelColor32));
string fmt;
if (p.Contains(challenger))
fmt = "You have been asked to join sides with {0} in a duel. Do you accept?";
else
fmt = "You have been challenged to a duel from {0}. Do you accept?";
AddHtml(22 - 1, 50, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32));
AddHtml(22 + 1, 50, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32));
AddHtml(22, 50 - 1, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32));
AddHtml(22, 50 + 1, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32));
AddHtml(22, 50, 294, 40, Color(string.Format(fmt, challenger.Name), 0xB0C868));
AddImageTiled(32, 88, 264, 1, 9107);
AddImageTiled(42, 90, 264, 1, 9157);
AddRadio(24, 100, 9727, 9730, true, 1);
AddHtml(60 - 1, 105, 250, 20, Color("Yes, I will fight this duel.", BlackColor32));
AddHtml(60 + 1, 105, 250, 20, Color("Yes, I will fight this duel.", BlackColor32));
AddHtml(60, 105 - 1, 250, 20, Color("Yes, I will fight this duel.", BlackColor32));
AddHtml(60, 105 + 1, 250, 20, Color("Yes, I will fight this duel.", BlackColor32));
AddHtml(60, 105, 250, 20, Color("Yes, I will fight this duel.", LabelColor32));
AddRadio(24, 135, 9727, 9730, false, 2);
AddHtml(60 - 1, 140, 250, 20, Color("No, I do not wish to fight.", BlackColor32));
AddHtml(60 + 1, 140, 250, 20, Color("No, I do not wish to fight.", BlackColor32));
AddHtml(60, 140 - 1, 250, 20, Color("No, I do not wish to fight.", BlackColor32));
AddHtml(60, 140 + 1, 250, 20, Color("No, I do not wish to fight.", BlackColor32));
AddHtml(60, 140, 250, 20, Color("No, I do not wish to fight.", LabelColor32));
AddRadio(24, 170, 9727, 9730, false, 3);
AddHtml(60 - 1, 175, 250, 20, Color("No, knave. Do not ask again.", BlackColor32));
AddHtml(60 + 1, 175, 250, 20, Color("No, knave. Do not ask again.", BlackColor32));
AddHtml(60, 175 - 1, 250, 20, Color("No, knave. Do not ask again.", BlackColor32));
AddHtml(60, 175 + 1, 250, 20, Color("No, knave. Do not ask again.", BlackColor32));
AddHtml(60, 175, 250, 20, Color("No, knave. Do not ask again.", LabelColor32));
AddButton(314, 173, 247, 248, 1);
Timer.DelayCall(TimeSpan.FromSeconds(15.0), AutoReject);
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public string Color(string text, int color) => $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
public void AutoReject()
{
if (!m_Active)
return;
m_Active = false;
m_Challenged.CloseGump<AcceptDuelGump>();
m_Challenger.SendMessage("{0} seems unresponsive.", m_Challenged.Name);
m_Challenged.SendMessage("You decline the challenge.");
}
public static void BeginIgnore(Mobile source, Mobile toIgnore)
{
if (!m_IgnoreLists.TryGetValue(source, out var list))
m_IgnoreLists[source] = list = new List<IgnoreEntry>();
for (var i = 0; i < list.Count; ++i)
{
var ie = list[i];
if (ie.Ignored == toIgnore)
{
ie.Refresh();
return;
}
if (ie.Expired)
list.RemoveAt(i--);
}
list.Add(new IgnoreEntry(toIgnore));
}
public static bool IsIgnored(Mobile source, Mobile check)
{
if (!m_IgnoreLists.TryGetValue(source, out var list))
return false;
for (var i = 0; i < list.Count; ++i)
{
var ie = list[i];
if (ie.Expired)
list.RemoveAt(i--);
else if (ie.Ignored == check)
return true;
}
return false;
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID != 1 || !m_Active || !m_Context.Registered)
return;
m_Active = false;
if (!m_Context.Participants.Contains(m_Participant))
return;
if (info.IsSwitched(1))
{
if (!(m_Challenged is PlayerMobile pm))
return;
if (pm.DuelContext != null)
{
if (pm.DuelContext.Initiator == pm)
pm.SendMessage(0x22, "You have already started a duel.");
else
pm.SendMessage(0x22, "You have already been challenged in a duel.");
m_Challenger.SendMessage("{0} cannot fight because they are already assigned to another duel.", pm.Name);
}
else if (DuelContext.CheckCombat(pm))
{
pm.SendMessage(
0x22,
"You have recently been in combat with another player and must wait before starting a duel."
);
m_Challenger.SendMessage(
"{0} cannot fight because they have recently been in combat with another player.",
pm.Name
);
}
else if (TournamentController.IsActive)
{
pm.SendMessage(0x22, "A tournament is currently active and you may not duel.");
m_Challenger.SendMessage(0x22, "A tournament is currently active and you may not duel.");
}
else
{
var added = false;
if (m_Slot >= 0 && m_Slot < m_Participant.Players.Length && m_Participant.Players[m_Slot] == null)
{
added = true;
m_Participant.Players[m_Slot] = new DuelPlayer(m_Challenged, m_Participant);
}
else
{
for (var i = 0; i < m_Participant.Players.Length; ++i)
if (m_Participant.Players[i] == null)
{
added = true;
m_Participant.Players[i] = new DuelPlayer(m_Challenged, m_Participant);
break;
}
}
if (added)
{
m_Challenger.SendMessage("{0} has accepted the request.", m_Challenged.Name);
m_Challenged.SendMessage("You have accepted the request from {0}.", m_Challenger.Name);
var ns = m_Challenger.NetState;
if (ns != null)
foreach (var g in ns.Gumps)
{
if (g is ParticipantGump pg && pg.Participant == m_Participant)
{
m_Challenger.SendGump(new ParticipantGump(m_Challenger, m_Context, m_Participant));
break;
}
if (g is DuelContextGump dcg && dcg.Context == m_Context)
{
m_Challenger.SendGump(new DuelContextGump(m_Challenger, m_Context));
break;
}
}
}
else
{
m_Challenger.SendMessage(
"The participant list was full and so {0} could not join.",
m_Challenged.Name
);
m_Challenged.SendMessage(
"The participant list was full and so you could not join the fight {1} {0}.",
m_Challenger.Name,
m_Participant.Contains(m_Challenger) ? "with" : "against"
);
}
}
}
else
{
if (info.IsSwitched(3))
BeginIgnore(m_Challenged, m_Challenger);
m_Challenger.SendMessage("{0} does not wish to fight.", m_Challenged.Name);
m_Challenged.SendMessage(
"You chose not to fight {1} {0}.",
m_Challenger.Name,
m_Participant.Contains(m_Challenger) ? "with" : "against"
);
}
}
private class IgnoreEntry
{
private static readonly TimeSpan ExpireDelay = TimeSpan.FromMinutes(15.0);
public readonly Mobile m_Ignored;
public DateTime m_Expire;
public IgnoreEntry(Mobile ignored)
{
m_Ignored = ignored;
Refresh();
}
public Mobile Ignored => m_Ignored;
public bool Expired => DateTime.UtcNow >= m_Expire;
public void Refresh()
{
m_Expire = DateTime.UtcNow + ExpireDelay;
}
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,89 +1,89 @@
using Server.Items;
namespace Server.Engines.ConPVP
{
public enum DuelTeleporterType
{
Squares = 6095,
Buds = 6104,
Flowers = 6113,
Spikes = 6122,
Arrows = 6140,
Links = 6149
}
public class DuelTeleporterAddon : BaseAddon
{
[Constructible]
public DuelTeleporterAddon(DuelTeleporterType type = DuelTeleporterType.Squares)
{
int itemID = (int)type;
AddComponent(new AddonComponent(itemID + 0), -1, -1, 5);
AddComponent(new AddonComponent(itemID + 1), -1, 0, 5);
AddComponent(new AddonComponent(itemID + 2), 0, -1, 5);
AddComponent(new AddonComponent(itemID + 3), -1, +1, 5);
AddComponent(new AddonComponent(itemID + 4), 0, 0, 5);
AddComponent(new AddonComponent(itemID + 5), +1, -1, 5);
AddComponent(new AddonComponent(itemID + 6), 0, +1, 5);
AddComponent(new AddonComponent(itemID + 7), +1, 0, 5);
AddComponent(new AddonComponent(itemID + 8), +1, +1, 5);
AddComponent(new AddonComponent(0x759), -2, -2, 0);
AddComponent(new AddonComponent(0x75A), +2, +2, 0);
AddComponent(new AddonComponent(0x75B), -2, +2, 0);
AddComponent(new AddonComponent(0x75C), +2, -2, 0);
AddComponent(new AddonComponent(0x751), -1, +2, 0);
AddComponent(new AddonComponent(0x751), 0, +2, 0);
AddComponent(new AddonComponent(0x751), +1, +2, 0);
AddComponent(new AddonComponent(0x752), +2, -1, 0);
AddComponent(new AddonComponent(0x752), +2, 0, 0);
AddComponent(new AddonComponent(0x752), +2, +1, 0);
AddComponent(new AddonComponent(0x753), -1, -2, 0);
AddComponent(new AddonComponent(0x753), 0, -2, 0);
AddComponent(new AddonComponent(0x753), +1, -2, 0);
AddComponent(new AddonComponent(0x754), -2, -1, 0);
AddComponent(new AddonComponent(0x754), -2, 0, 0);
AddComponent(new AddonComponent(0x754), -2, +1, 0);
}
public DuelTeleporterAddon(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public DuelTeleporterType Type
{
get
{
if (Components.Count > 0)
return (DuelTeleporterType)Components[0].ItemID;
return DuelTeleporterType.Squares;
}
set
{
for (int i = 0; i < Components.Count && i < 9; ++i)
Components[i].ItemID = i + (int)value;
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}
using Server.Items;
namespace Server.Engines.ConPVP
{
public enum DuelTeleporterType
{
Squares = 6095,
Buds = 6104,
Flowers = 6113,
Spikes = 6122,
Arrows = 6140,
Links = 6149
}
public class DuelTeleporterAddon : BaseAddon
{
[Constructible]
public DuelTeleporterAddon(DuelTeleporterType type = DuelTeleporterType.Squares)
{
var itemID = (int)type;
AddComponent(new AddonComponent(itemID + 0), -1, -1, 5);
AddComponent(new AddonComponent(itemID + 1), -1, 0, 5);
AddComponent(new AddonComponent(itemID + 2), 0, -1, 5);
AddComponent(new AddonComponent(itemID + 3), -1, +1, 5);
AddComponent(new AddonComponent(itemID + 4), 0, 0, 5);
AddComponent(new AddonComponent(itemID + 5), +1, -1, 5);
AddComponent(new AddonComponent(itemID + 6), 0, +1, 5);
AddComponent(new AddonComponent(itemID + 7), +1, 0, 5);
AddComponent(new AddonComponent(itemID + 8), +1, +1, 5);
AddComponent(new AddonComponent(0x759), -2, -2, 0);
AddComponent(new AddonComponent(0x75A), +2, +2, 0);
AddComponent(new AddonComponent(0x75B), -2, +2, 0);
AddComponent(new AddonComponent(0x75C), +2, -2, 0);
AddComponent(new AddonComponent(0x751), -1, +2, 0);
AddComponent(new AddonComponent(0x751), 0, +2, 0);
AddComponent(new AddonComponent(0x751), +1, +2, 0);
AddComponent(new AddonComponent(0x752), +2, -1, 0);
AddComponent(new AddonComponent(0x752), +2, 0, 0);
AddComponent(new AddonComponent(0x752), +2, +1, 0);
AddComponent(new AddonComponent(0x753), -1, -2, 0);
AddComponent(new AddonComponent(0x753), 0, -2, 0);
AddComponent(new AddonComponent(0x753), +1, -2, 0);
AddComponent(new AddonComponent(0x754), -2, -1, 0);
AddComponent(new AddonComponent(0x754), -2, 0, 0);
AddComponent(new AddonComponent(0x754), -2, +1, 0);
}
public DuelTeleporterAddon(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public DuelTeleporterType Type
{
get
{
if (Components.Count > 0)
return (DuelTeleporterType)Components[0].ItemID;
return DuelTeleporterType.Squares;
}
set
{
for (var i = 0; i < Components.Count && i < 9; ++i)
Components[i].ItemID = i + (int)value;
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,68 +1,68 @@
using Server.Gumps;
using Server.Items;
namespace Server.Engines.ConPVP
{
public abstract class EventController : Item
{
public EventController()
: base(0x1B7A)
{
Visible = false;
Movable = false;
}
public EventController(Serial serial)
: base(serial)
{
}
public abstract string Title { get; }
public abstract EventGame Construct(DuelContext dc);
public abstract string GetTeamName(int teamID);
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void OnDoubleClick(Mobile from)
{
if (from.AccessLevel >= AccessLevel.GameMaster)
from.SendGump(new PropertiesGump(from, this));
}
}
public abstract class EventGame
{
protected DuelContext m_Context;
public EventGame(DuelContext context) => m_Context = context;
public DuelContext Context => m_Context;
public virtual bool FreeConsume => true;
public virtual bool OnDeath(Mobile mob, Container corpse) => true;
public virtual bool CantDoAnything(Mobile mob) => false;
public virtual void OnStart()
{
}
public virtual void OnStop()
{
}
}
}
using Server.Gumps;
using Server.Items;
namespace Server.Engines.ConPVP
{
public abstract class EventController : Item
{
public EventController()
: base(0x1B7A)
{
Visible = false;
Movable = false;
}
public EventController(Serial serial)
: base(serial)
{
}
public abstract string Title { get; }
public abstract EventGame Construct(DuelContext dc);
public abstract string GetTeamName(int teamID);
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
}
public override void OnDoubleClick(Mobile from)
{
if (from.AccessLevel >= AccessLevel.GameMaster)
from.SendGump(new PropertiesGump(from, this));
}
}
public abstract class EventGame
{
protected DuelContext m_Context;
public EventGame(DuelContext context) => m_Context = context;
public DuelContext Context => m_Context;
public virtual bool FreeConsume => true;
public virtual bool OnDeath(Mobile mob, Container corpse) => true;
public virtual bool CantDoAnything(Mobile mob) => false;
public virtual void OnStart()
{
}
public virtual void OnStop()
{
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,122 +1,129 @@
using System;
using System.Collections.Generic;
using System.Text;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class TourneyMatch
{
public TourneyMatch(List<TourneyParticipant> participants)
{
Participants = participants;
for (int i = 0; i < participants.Count; ++i)
{
TourneyParticipant part = participants[i];
StringBuilder sb = new StringBuilder();
sb.Append("Matched in a duel against ");
if (participants.Count > 2)
sb.AppendFormat("{0} other {1}: ", participants.Count - 1,
part.Players.Count == 1 ? "players" : "teams");
bool hasAppended = false;
for (int j = 0; j < participants.Count; ++j)
{
if (i == j)
continue;
if (hasAppended)
sb.Append(", ");
sb.Append(participants[j].NameList);
hasAppended = true;
}
sb.Append(".");
part.AddLog(sb.ToString());
}
}
public List<TourneyParticipant> Participants { get; set; }
public TourneyParticipant Winner { get; set; }
public DuelContext Context { get; set; }
public bool InProgress => Context?.Registered == true;
public void Start(Arena arena, Tournament tourney)
{
TourneyParticipant first = Participants[0];
DuelContext dc = new DuelContext(first.Players[0], tourney.Ruleset.Layout, false);
dc.Ruleset.Options.SetAll(false);
dc.Ruleset.Options.Or(tourney.Ruleset.Options);
for (int i = 0; i < Participants.Count; ++i)
{
TourneyParticipant tourneyPart = Participants[i];
Participant duelPart = new Participant(dc, tourneyPart.Players.Count)
{
TourneyPart = tourneyPart
};
for (int j = 0; j < tourneyPart.Players.Count; ++j)
duelPart.Add(tourneyPart.Players[j]);
for (int j = 0; j < duelPart.Players.Length; ++j)
if (duelPart.Players[j] != null)
duelPart.Players[j].Ready = true;
dc.Participants.Add(duelPart);
}
if (tourney.EventController != null)
dc.m_EventGame = tourney.EventController.Construct(dc);
dc.m_Tournament = tourney;
dc.m_Match = this;
dc.m_OverrideArena = arena;
if (tourney.SuddenDeath > TimeSpan.Zero &&
(tourney.SuddenDeathRounds == 0 || tourney.Pyramid.Levels.Count <= tourney.SuddenDeathRounds))
dc.StartSuddenDeath(tourney.SuddenDeath);
dc.SendReadyGump(0);
if (dc.StartedBeginCountdown)
{
Context = dc;
for (int i = 0; i < Participants.Count; ++i)
{
TourneyParticipant p = Participants[i];
for (int j = 0; j < p.Players.Count; ++j)
{
Mobile mob = p.Players[j];
foreach (Mobile view in mob.GetMobilesInRange(18))
if (!mob.CanSee(view))
mob.Send(view.RemovePacket);
mob.LocalOverheadMessage(MessageType.Emote, 0x3B2, false,
"* Your mind focuses intently on the fight and all other distractions fade away *");
}
}
}
else
{
dc.Unregister();
dc.StopCountdown();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class TourneyMatch
{
public TourneyMatch(List<TourneyParticipant> participants)
{
Participants = participants;
for (var i = 0; i < participants.Count; ++i)
{
var part = participants[i];
var sb = new StringBuilder();
sb.Append("Matched in a duel against ");
if (participants.Count > 2)
sb.AppendFormat(
"{0} other {1}: ",
participants.Count - 1,
part.Players.Count == 1 ? "players" : "teams"
);
var hasAppended = false;
for (var j = 0; j < participants.Count; ++j)
{
if (i == j)
continue;
if (hasAppended)
sb.Append(", ");
sb.Append(participants[j].NameList);
hasAppended = true;
}
sb.Append(".");
part.AddLog(sb.ToString());
}
}
public List<TourneyParticipant> Participants { get; set; }
public TourneyParticipant Winner { get; set; }
public DuelContext Context { get; set; }
public bool InProgress => Context?.Registered == true;
public void Start(Arena arena, Tournament tourney)
{
var first = Participants[0];
var dc = new DuelContext(first.Players[0], tourney.Ruleset.Layout, false);
dc.Ruleset.Options.SetAll(false);
dc.Ruleset.Options.Or(tourney.Ruleset.Options);
for (var i = 0; i < Participants.Count; ++i)
{
var tourneyPart = Participants[i];
var duelPart = new Participant(dc, tourneyPart.Players.Count)
{
TourneyPart = tourneyPart
};
for (var j = 0; j < tourneyPart.Players.Count; ++j)
duelPart.Add(tourneyPart.Players[j]);
for (var j = 0; j < duelPart.Players.Length; ++j)
if (duelPart.Players[j] != null)
duelPart.Players[j].Ready = true;
dc.Participants.Add(duelPart);
}
if (tourney.EventController != null)
dc.m_EventGame = tourney.EventController.Construct(dc);
dc.m_Tournament = tourney;
dc.m_Match = this;
dc.m_OverrideArena = arena;
if (tourney.SuddenDeath > TimeSpan.Zero &&
(tourney.SuddenDeathRounds == 0 || tourney.Pyramid.Levels.Count <= tourney.SuddenDeathRounds))
dc.StartSuddenDeath(tourney.SuddenDeath);
dc.SendReadyGump(0);
if (dc.StartedBeginCountdown)
{
Context = dc;
for (var i = 0; i < Participants.Count; ++i)
{
var p = Participants[i];
for (var j = 0; j < p.Players.Count; ++j)
{
var mob = p.Players[j];
foreach (var view in mob.GetMobilesInRange(18))
if (!mob.CanSee(view))
mob.Send(view.RemovePacket);
mob.LocalOverheadMessage(
MessageType.Emote,
0x3B2,
false,
"* Your mind focuses intently on the fight and all other distractions fade away *"
);
}
}
}
else
{
dc.Unregister();
dc.StopCountdown();
}
}
}
}

View file

@ -1,349 +1,412 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class AcceptTeamGump : Gump
{
private const int BlackColor32 = 0x000008;
private const int LabelColor32 = 0xFFFFFF;
private bool m_Active;
private readonly Mobile m_From;
private readonly List<Mobile> m_Players;
private readonly Mobile m_Registrar;
private readonly Mobile m_Requested;
private readonly Tournament m_Tournament;
public AcceptTeamGump(Mobile from, Mobile requested, Tournament tourney, Mobile registrar, List<Mobile> players) : base(50, 50)
{
m_From = from;
m_Requested = requested;
m_Tournament = tourney;
m_Registrar = registrar;
m_Players = players;
m_Active = true;
Ruleset ruleset = tourney.Ruleset;
Ruleset basedef = ruleset.Base;
int height = 185 + 35 + 60 + 12;
int changes = 0;
BitArray defs;
if (ruleset.Flavors.Count > 0)
{
defs = new BitArray(basedef.Options);
for (int i = 0; i < ruleset.Flavors.Count; ++i)
defs.Or(ruleset.Flavors[i].Options);
height += ruleset.Flavors.Count * 18;
}
else
{
defs = basedef.Options;
}
BitArray opts = ruleset.Options;
for (int i = 0; i < opts.Length; ++i)
if (defs[i] != opts[i])
++changes;
height += changes * 22;
height += 10 + 22 + 25 + 25;
Closable = false;
AddPage(0);
AddBackground(1, 1, 398, height, 3600);
AddImageTiled(16, 15, 369, height - 29, 3604);
AddAlphaRegion(16, 15, 369, height - 29);
AddImage(215, -43, 0xEE40);
StringBuilder sb = new StringBuilder();
if (tourney.TourneyType == TourneyType.FreeForAll)
{
sb.Append("FFA");
}
else if (tourney.TourneyType == TourneyType.RandomTeam)
{
sb.Append(tourney.ParticipantsPerMatch);
sb.Append("-Team");
}
else if (tourney.TourneyType == TourneyType.Faction)
{
sb.Append(tourney.ParticipantsPerMatch);
sb.Append("-Team Faction");
}
else if (tourney.TourneyType == TourneyType.RedVsBlue)
{
sb.Append("Red v Blue");
}
else
{
for (int i = 0; i < tourney.ParticipantsPerMatch; ++i)
{
if (sb.Length > 0)
sb.Append('v');
sb.Append(tourney.PlayersPerParticipant);
}
}
if (tourney.EventController != null)
sb.Append(' ').Append(tourney.EventController.Title);
sb.Append(" Tournament Invitation");
AddBorderedText(22, 22, 294, 20, Center(sb.ToString()), LabelColor32, BlackColor32);
AddBorderedText(22, 50, 294, 40,
$"You have been asked to partner with {from.Name} in a tournament. Do you accept?",
0xB0C868, BlackColor32);
AddImageTiled(32, 88, 264, 1, 9107);
AddImageTiled(42, 90, 264, 1, 9157);
int y = 100;
var groupText = tourney.GroupType switch
{
GroupingType.HighVsLow => "High vs Low",
GroupingType.Nearest => "Closest opponent",
GroupingType.Random => "Random",
_ => null
};
AddBorderedText(35, y, 190, 20, $"Grouping: {groupText}", LabelColor32, BlackColor32);
y += 20;
var tieText = tourney.TieType switch
{
TieType.Random => "Random",
TieType.Highest => "Highest advances",
TieType.Lowest => "Lowest advances",
TieType.FullAdvancement => tourney.ParticipantsPerMatch == 2 ? "Both advance" : "Everyone advances",
TieType.FullElimination => tourney.ParticipantsPerMatch == 2 ? "Both eliminated" : "Everyone eliminated",
_ => null
};
AddBorderedText(35, y, 190, 20, $"Tiebreaker: {tieText}", LabelColor32, BlackColor32);
y += 20;
string sdText = "Off";
if (tourney.SuddenDeath > TimeSpan.Zero)
{
sdText = $"{(int)tourney.SuddenDeath.TotalMinutes}:{tourney.SuddenDeath.Seconds:D2}";
if (tourney.SuddenDeathRounds > 0)
sdText = $"{sdText} (first {tourney.SuddenDeathRounds} rounds)";
else
sdText = $"{sdText} (all rounds)";
}
AddBorderedText(35, y, 240, 20, $"Sudden Death: {sdText}", LabelColor32, BlackColor32);
y += 20;
y += 6;
AddImageTiled(32, y - 1, 264, 1, 9107);
AddImageTiled(42, y + 1, 264, 1, 9157);
y += 6;
AddBorderedText(35, y, 190, 20, $"Ruleset: {basedef.Title}", LabelColor32, BlackColor32);
y += 20;
for (int i = 0; i < ruleset.Flavors.Count; ++i, y += 18)
AddBorderedText(35, y, 190, 20, $" + {ruleset.Flavors[i].Title}", LabelColor32, BlackColor32);
y += 4;
if (changes > 0)
{
AddBorderedText(35, y, 190, 20, "Modifications:", LabelColor32, BlackColor32);
y += 20;
for (int i = 0; i < opts.Length; ++i)
if (defs[i] != opts[i])
{
string name = ruleset.Layout.FindByIndex(i);
if (name != null) // sanity
{
AddImage(35, y, opts[i] ? 0xD3 : 0xD2);
AddBorderedText(60, y, 165, 22, name, LabelColor32, BlackColor32);
}
y += 22;
}
}
else
{
AddBorderedText(35, y, 190, 20, "Modifications: None", LabelColor32, BlackColor32);
y += 20;
}
y += 8;
AddImageTiled(32, y - 1, 264, 1, 9107);
AddImageTiled(42, y + 1, 264, 1, 9157);
y += 8;
AddRadio(24, y, 9727, 9730, true, 1);
AddBorderedText(60, y + 5, 250, 20, "Yes, I will join them.", LabelColor32, BlackColor32);
y += 35;
AddRadio(24, y, 9727, 9730, false, 2);
AddBorderedText(60, y + 5, 250, 20, "No, I do not wish to fight.", LabelColor32, BlackColor32);
y += 35;
AddRadio(24, y, 9727, 9730, false, 3);
AddBorderedText(60, y + 5, 270, 20, "No, most certainly not. Do not ask again.", LabelColor32, BlackColor32);
y += 35;
y -= 3;
AddButton(314, y, 247, 248, 1);
Timer.DelayCall(TimeSpan.FromSeconds(15.0), AutoReject);
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public string Color(string text, int color) => $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor)
{
AddColoredText(x - 1, y - 1, width, height, text, borderColor);
AddColoredText(x - 1, y + 1, width, height, text, borderColor);
AddColoredText(x + 1, y - 1, width, height, text, borderColor);
AddColoredText(x + 1, y + 1, width, height, text, borderColor);
AddColoredText(x, y, width, height, text, color);
}
private void AddColoredText(int x, int y, int width, int height, string text, int color)
{
if (color == 0)
AddHtml(x, y, width, height, text);
else
AddHtml(x, y, width, height, Color(text, color));
}
public void AutoReject()
{
if (!m_Active)
return;
m_Active = false;
m_Requested.CloseGump<AcceptTeamGump>();
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
if (m_Registrar != null)
{
m_Registrar.PrivateOverheadMessage(MessageType.Regular,
0x22, false, $"{m_Requested.Name} seems unresponsive.", m_From.NetState);
m_Registrar.PrivateOverheadMessage(MessageType.Regular,
0x22, false, $"You have declined the partnership with {m_From.Name}.", m_Requested.NetState);
}
}
public override void OnResponse(NetState sender, RelayInfo info)
{
Mobile from = m_From;
Mobile mob = m_Requested;
if (info.ButtonID != 1 || !m_Active)
return;
m_Active = false;
if (info.IsSwitched(1))
{
if (!(mob is PlayerMobile pm))
return;
if (AcceptDuelGump.IsIgnored(mob, from) || mob.Blessed)
{
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
m_Registrar?.PrivateOverheadMessage(MessageType.Regular,
0x22, false, "They ignore your invitation.", from.NetState);
}
else if (pm.DuelContext != null)
{
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
m_Registrar?.PrivateOverheadMessage(MessageType.Regular,
0x22, false, "They are already assigned to another duel.", from.NetState);
}
else if (m_Players.Contains(mob))
{
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
m_Registrar?.PrivateOverheadMessage(MessageType.Regular,
0x22, false, "You have already named them as a team member.", from.NetState);
}
else if (m_Tournament.HasParticipant(mob))
{
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
m_Registrar?.PrivateOverheadMessage(MessageType.Regular,
0x22, false, "They have already entered this tournament.", from.NetState);
}
else if (m_Players.Count >= m_Tournament.PlayersPerParticipant)
{
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
m_Registrar?.PrivateOverheadMessage(MessageType.Regular,
0x22, false, "Your team is full.", from.NetState);
}
else
{
m_Players.Add(mob);
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
if (m_Registrar != null)
{
m_Registrar.PrivateOverheadMessage(MessageType.Regular,
0x59, false, $"{mob.Name} has accepted your offer of partnership.", from.NetState);
m_Registrar.PrivateOverheadMessage(MessageType.Regular,
0x59, false, $"You have accepted the partnership with {from.Name}.", mob.NetState);
}
}
}
else
{
if (info.IsSwitched(3))
AcceptDuelGump.BeginIgnore(m_Requested, m_From);
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
if (m_Registrar != null)
{
m_Registrar.PrivateOverheadMessage(MessageType.Regular,
0x22, false, $"{mob.Name} has declined your offer of partnership.", from.NetState);
m_Registrar.PrivateOverheadMessage(MessageType.Regular,
0x22, false, $"You have declined the partnership with {from.Name}.", mob.NetState);
}
}
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class AcceptTeamGump : Gump
{
private const int BlackColor32 = 0x000008;
private const int LabelColor32 = 0xFFFFFF;
private readonly Mobile m_From;
private readonly List<Mobile> m_Players;
private readonly Mobile m_Registrar;
private readonly Mobile m_Requested;
private readonly Tournament m_Tournament;
private bool m_Active;
public AcceptTeamGump(
Mobile from, Mobile requested, Tournament tourney, Mobile registrar, List<Mobile> players
) : base(50, 50)
{
m_From = from;
m_Requested = requested;
m_Tournament = tourney;
m_Registrar = registrar;
m_Players = players;
m_Active = true;
var ruleset = tourney.Ruleset;
var basedef = ruleset.Base;
var height = 185 + 35 + 60 + 12;
var changes = 0;
BitArray defs;
if (ruleset.Flavors.Count > 0)
{
defs = new BitArray(basedef.Options);
for (var i = 0; i < ruleset.Flavors.Count; ++i)
defs.Or(ruleset.Flavors[i].Options);
height += ruleset.Flavors.Count * 18;
}
else
{
defs = basedef.Options;
}
var opts = ruleset.Options;
for (var i = 0; i < opts.Length; ++i)
if (defs[i] != opts[i])
++changes;
height += changes * 22;
height += 10 + 22 + 25 + 25;
Closable = false;
AddPage(0);
AddBackground(1, 1, 398, height, 3600);
AddImageTiled(16, 15, 369, height - 29, 3604);
AddAlphaRegion(16, 15, 369, height - 29);
AddImage(215, -43, 0xEE40);
var sb = new StringBuilder();
if (tourney.TourneyType == TourneyType.FreeForAll)
{
sb.Append("FFA");
}
else if (tourney.TourneyType == TourneyType.RandomTeam)
{
sb.Append(tourney.ParticipantsPerMatch);
sb.Append("-Team");
}
else if (tourney.TourneyType == TourneyType.Faction)
{
sb.Append(tourney.ParticipantsPerMatch);
sb.Append("-Team Faction");
}
else if (tourney.TourneyType == TourneyType.RedVsBlue)
{
sb.Append("Red v Blue");
}
else
{
for (var i = 0; i < tourney.ParticipantsPerMatch; ++i)
{
if (sb.Length > 0)
sb.Append('v');
sb.Append(tourney.PlayersPerParticipant);
}
}
if (tourney.EventController != null)
sb.Append(' ').Append(tourney.EventController.Title);
sb.Append(" Tournament Invitation");
AddBorderedText(22, 22, 294, 20, Center(sb.ToString()), LabelColor32, BlackColor32);
AddBorderedText(
22,
50,
294,
40,
$"You have been asked to partner with {from.Name} in a tournament. Do you accept?",
0xB0C868,
BlackColor32
);
AddImageTiled(32, 88, 264, 1, 9107);
AddImageTiled(42, 90, 264, 1, 9157);
var y = 100;
var groupText = tourney.GroupType switch
{
GroupingType.HighVsLow => "High vs Low",
GroupingType.Nearest => "Closest opponent",
GroupingType.Random => "Random",
_ => null
};
AddBorderedText(35, y, 190, 20, $"Grouping: {groupText}", LabelColor32, BlackColor32);
y += 20;
var tieText = tourney.TieType switch
{
TieType.Random => "Random",
TieType.Highest => "Highest advances",
TieType.Lowest => "Lowest advances",
TieType.FullAdvancement => tourney.ParticipantsPerMatch == 2 ? "Both advance" : "Everyone advances",
TieType.FullElimination => tourney.ParticipantsPerMatch == 2 ? "Both eliminated" : "Everyone eliminated",
_ => null
};
AddBorderedText(35, y, 190, 20, $"Tiebreaker: {tieText}", LabelColor32, BlackColor32);
y += 20;
var sdText = "Off";
if (tourney.SuddenDeath > TimeSpan.Zero)
{
sdText = $"{(int)tourney.SuddenDeath.TotalMinutes}:{tourney.SuddenDeath.Seconds:D2}";
if (tourney.SuddenDeathRounds > 0)
sdText = $"{sdText} (first {tourney.SuddenDeathRounds} rounds)";
else
sdText = $"{sdText} (all rounds)";
}
AddBorderedText(35, y, 240, 20, $"Sudden Death: {sdText}", LabelColor32, BlackColor32);
y += 20;
y += 6;
AddImageTiled(32, y - 1, 264, 1, 9107);
AddImageTiled(42, y + 1, 264, 1, 9157);
y += 6;
AddBorderedText(35, y, 190, 20, $"Ruleset: {basedef.Title}", LabelColor32, BlackColor32);
y += 20;
for (var i = 0; i < ruleset.Flavors.Count; ++i, y += 18)
AddBorderedText(35, y, 190, 20, $" + {ruleset.Flavors[i].Title}", LabelColor32, BlackColor32);
y += 4;
if (changes > 0)
{
AddBorderedText(35, y, 190, 20, "Modifications:", LabelColor32, BlackColor32);
y += 20;
for (var i = 0; i < opts.Length; ++i)
if (defs[i] != opts[i])
{
var name = ruleset.Layout.FindByIndex(i);
if (name != null) // sanity
{
AddImage(35, y, opts[i] ? 0xD3 : 0xD2);
AddBorderedText(60, y, 165, 22, name, LabelColor32, BlackColor32);
}
y += 22;
}
}
else
{
AddBorderedText(35, y, 190, 20, "Modifications: None", LabelColor32, BlackColor32);
y += 20;
}
y += 8;
AddImageTiled(32, y - 1, 264, 1, 9107);
AddImageTiled(42, y + 1, 264, 1, 9157);
y += 8;
AddRadio(24, y, 9727, 9730, true, 1);
AddBorderedText(60, y + 5, 250, 20, "Yes, I will join them.", LabelColor32, BlackColor32);
y += 35;
AddRadio(24, y, 9727, 9730, false, 2);
AddBorderedText(60, y + 5, 250, 20, "No, I do not wish to fight.", LabelColor32, BlackColor32);
y += 35;
AddRadio(24, y, 9727, 9730, false, 3);
AddBorderedText(60, y + 5, 270, 20, "No, most certainly not. Do not ask again.", LabelColor32, BlackColor32);
y += 35;
y -= 3;
AddButton(314, y, 247, 248, 1);
Timer.DelayCall(TimeSpan.FromSeconds(15.0), AutoReject);
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public string Color(string text, int color) => $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor)
{
AddColoredText(x - 1, y - 1, width, height, text, borderColor);
AddColoredText(x - 1, y + 1, width, height, text, borderColor);
AddColoredText(x + 1, y - 1, width, height, text, borderColor);
AddColoredText(x + 1, y + 1, width, height, text, borderColor);
AddColoredText(x, y, width, height, text, color);
}
private void AddColoredText(int x, int y, int width, int height, string text, int color)
{
if (color == 0)
AddHtml(x, y, width, height, text);
else
AddHtml(x, y, width, height, Color(text, color));
}
public void AutoReject()
{
if (!m_Active)
return;
m_Active = false;
m_Requested.CloseGump<AcceptTeamGump>();
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
if (m_Registrar != null)
{
m_Registrar.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
$"{m_Requested.Name} seems unresponsive.",
m_From.NetState
);
m_Registrar.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
$"You have declined the partnership with {m_From.Name}.",
m_Requested.NetState
);
}
}
public override void OnResponse(NetState sender, RelayInfo info)
{
var from = m_From;
var mob = m_Requested;
if (info.ButtonID != 1 || !m_Active)
return;
m_Active = false;
if (info.IsSwitched(1))
{
if (!(mob is PlayerMobile pm))
return;
if (AcceptDuelGump.IsIgnored(mob, from) || mob.Blessed)
{
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
m_Registrar?.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
"They ignore your invitation.",
from.NetState
);
}
else if (pm.DuelContext != null)
{
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
m_Registrar?.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
"They are already assigned to another duel.",
from.NetState
);
}
else if (m_Players.Contains(mob))
{
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
m_Registrar?.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
"You have already named them as a team member.",
from.NetState
);
}
else if (m_Tournament.HasParticipant(mob))
{
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
m_Registrar?.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
"They have already entered this tournament.",
from.NetState
);
}
else if (m_Players.Count >= m_Tournament.PlayersPerParticipant)
{
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
m_Registrar?.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
"Your team is full.",
from.NetState
);
}
else
{
m_Players.Add(mob);
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
if (m_Registrar != null)
{
m_Registrar.PrivateOverheadMessage(
MessageType.Regular,
0x59,
false,
$"{mob.Name} has accepted your offer of partnership.",
from.NetState
);
m_Registrar.PrivateOverheadMessage(
MessageType.Regular,
0x59,
false,
$"You have accepted the partnership with {from.Name}.",
mob.NetState
);
}
}
}
else
{
if (info.IsSwitched(3))
AcceptDuelGump.BeginIgnore(m_Requested, m_From);
m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players));
if (m_Registrar != null)
{
m_Registrar.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
$"{mob.Name} has declined your offer of partnership.",
from.NetState
);
m_Registrar.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
$"You have declined the partnership with {from.Name}.",
mob.NetState
);
}
}
}
}
}

View file

@ -1,276 +1,278 @@
using System.Collections.Generic;
using System.Text;
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class ArenasMoongate : Item
{
[Constructible]
public ArenasMoongate() : base(0x1FD4)
{
Movable = false;
Light = LightType.Circle300;
}
public ArenasMoongate(Serial serial) : base(serial)
{
}
public override string DefaultName => "arena moongate";
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
Light = LightType.Circle300;
}
public bool UseGate(Mobile from)
{
if (DuelContext.CheckCombat(from))
{
from.SendMessage(0x22, "You have recently been in combat with another player and cannot use this moongate.");
return false;
}
if (from.Spell != null)
{
from.SendLocalizedMessage(1049616); // You are too busy to do that at the moment.
return false;
}
from.CloseGump<ArenaGump>();
from.SendGump(new ArenaGump(from, this));
if (!from.Hidden || from.AccessLevel == AccessLevel.Player)
Effects.PlaySound(from.Location, from.Map, 0x20E);
return true;
}
public override void OnDoubleClick(Mobile from)
{
if (from.InRange(GetWorldLocation(), 1))
UseGate(from);
else
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that
}
public override bool OnMoveOver(Mobile m) => !m.Player || UseGate(m);
}
public class ArenaGump : Gump
{
private readonly List<Arena> m_Arenas;
private int m_ColumnX = 12;
private readonly Mobile m_From;
private readonly ArenasMoongate m_Gate;
public ArenaGump(Mobile from, ArenasMoongate gate) : base(50, 50)
{
m_From = from;
m_Gate = gate;
m_Arenas = Arena.Arenas;
AddPage(0);
int height = 12 + 20 + m_Arenas.Count * 31 + 24 + 12;
AddBackground(0, 0, 499 + 40, height, 0x2436);
List<Arena> list = m_Arenas;
for (int i = 1; i < list.Count; i += 2)
AddImageTiled(12, 32 + i * 31, 475 + 40, 30, 0x2430);
AddAlphaRegion(10, 10, 479 + 40, height - 20);
AddColumnHeader(35, null);
AddColumnHeader(115, "Arena");
AddColumnHeader(325, "Participants");
AddColumnHeader(40, "Obs");
AddButton(499 + 40 - 12 - 63 - 4 - 63, height - 12 - 24, 247, 248, 1);
AddButton(499 + 40 - 12 - 63, height - 12 - 24, 241, 242, 2);
for (int i = 0; i < list.Count; ++i)
{
Arena ar = list[i];
int x = 12;
int y = 32 + i * 31;
int color = ar.Players.Count > 0 ? 0xCCFFCC : 0xCCCCCC;
AddRadio(x + 3, y + 1, 9727, 9730, false, i);
x += 35;
AddBorderedText(x + 5, y + 5, 115 - 5, ar.Name ?? "(no name)", color, 0);
x += 115;
StringBuilder sb = new StringBuilder();
if (ar.Players.Count > 0)
{
Ladder ladder = Ladder.Instance;
if (ladder == null)
continue;
LadderEntry p1 = null, p2 = null, p3 = null, p4 = null;
for (int j = 0; j < ar.Players.Count; ++j)
{
Mobile mob = ar.Players[j];
LadderEntry c = ladder.Find(mob);
if (p1 == null || c.Index < p1.Index)
{
p4 = p3;
p3 = p2;
p2 = p1;
p1 = c;
}
else if (p2 == null || c.Index < p2.Index)
{
p4 = p3;
p3 = p2;
p2 = c;
}
else if (p3 == null || c.Index < p3.Index)
{
p4 = p3;
p3 = c;
}
else if (p4 == null || c.Index < p4.Index)
{
p4 = c;
}
}
Append(sb, p1);
Append(sb, p2);
Append(sb, p3);
Append(sb, p4);
if (ar.Players.Count > 4)
sb.Append(", ...");
}
else
{
sb.Append("Empty");
}
AddBorderedText(x + 5, y + 5, 325 - 5, sb.ToString(), color, 0);
x += 325;
AddBorderedText(x, y + 5, 40, Center(ar.Spectators.ToString()), color, 0);
}
}
private void Append(StringBuilder sb, LadderEntry le)
{
if (le == null)
return;
if (sb.Length > 0)
sb.Append(", ");
sb.Append(le.Mobile.Name);
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID != 1)
return;
int[] switches = info.Switches;
if (switches.Length == 0)
return;
int opt = switches[0];
if (opt < 0 || opt >= m_Arenas.Count)
return;
Arena arena = m_Arenas[opt];
if (!m_From.InRange(m_Gate.GetWorldLocation(), 1) || m_From.Map != m_Gate.Map)
{
m_From.SendLocalizedMessage(1019002); // You are too far away to use the gate.
}
else if (DuelContext.CheckCombat(m_From))
{
m_From.SendMessage(0x22,
"You have recently been in combat with another player and cannot use this moongate.");
}
else if (m_From.Spell != null)
{
m_From.SendLocalizedMessage(1049616); // You are too busy to do that at the moment.
}
else if (m_From.Map == arena.Facet && arena.Zone.Contains(m_From))
{
m_From.SendLocalizedMessage(1019003); // You are already there.
}
else
{
BaseCreature.TeleportPets(m_From, arena.GateIn, arena.Facet);
m_From.Combatant = null;
m_From.Warmode = false;
m_From.Hidden = true;
m_From.MoveToWorld(arena.GateIn, arena.Facet);
Effects.PlaySound(arena.GateIn, arena.Facet, 0x1FE);
}
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public string Color(string text, int color) => $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
private void AddBorderedText(int x, int y, int width, string text, int color, int borderColor)
{
/*AddColoredText( x - 1, y, width, text, borderColor );
AddColoredText( x + 1, y, width, text, borderColor );
AddColoredText( x, y - 1, width, text, borderColor );
AddColoredText( x, y + 1, width, text, borderColor );*/
/*AddColoredText( x - 1, y - 1, width, text, borderColor );
AddColoredText( x + 1, y + 1, width, text, borderColor );*/
AddColoredText(x, y, width, text, color);
}
private void AddColoredText(int x, int y, int width, string text, int color)
{
if (color == 0)
AddHtml(x, y, width, 20, text);
else
AddHtml(x, y, width, 20, Color(text, color));
}
private void AddColumnHeader(int width, string name)
{
AddBackground(m_ColumnX, 12, width, 20, 0x242C);
AddImageTiled(m_ColumnX + 2, 14, width - 4, 16, 0x2430);
if (name != null)
AddBorderedText(m_ColumnX, 13, width, Center(name), 0xFFFFFF, 0);
m_ColumnX += width;
}
}
}
using System.Collections.Generic;
using System.Text;
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class ArenasMoongate : Item
{
[Constructible]
public ArenasMoongate() : base(0x1FD4)
{
Movable = false;
Light = LightType.Circle300;
}
public ArenasMoongate(Serial serial) : base(serial)
{
}
public override string DefaultName => "arena moongate";
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
Light = LightType.Circle300;
}
public bool UseGate(Mobile from)
{
if (DuelContext.CheckCombat(from))
{
from.SendMessage(0x22, "You have recently been in combat with another player and cannot use this moongate.");
return false;
}
if (from.Spell != null)
{
from.SendLocalizedMessage(1049616); // You are too busy to do that at the moment.
return false;
}
from.CloseGump<ArenaGump>();
from.SendGump(new ArenaGump(from, this));
if (!from.Hidden || from.AccessLevel == AccessLevel.Player)
Effects.PlaySound(from.Location, from.Map, 0x20E);
return true;
}
public override void OnDoubleClick(Mobile from)
{
if (from.InRange(GetWorldLocation(), 1))
UseGate(from);
else
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that
}
public override bool OnMoveOver(Mobile m) => !m.Player || UseGate(m);
}
public class ArenaGump : Gump
{
private readonly List<Arena> m_Arenas;
private readonly Mobile m_From;
private readonly ArenasMoongate m_Gate;
private int m_ColumnX = 12;
public ArenaGump(Mobile from, ArenasMoongate gate) : base(50, 50)
{
m_From = from;
m_Gate = gate;
m_Arenas = Arena.Arenas;
AddPage(0);
var height = 12 + 20 + m_Arenas.Count * 31 + 24 + 12;
AddBackground(0, 0, 499 + 40, height, 0x2436);
var list = m_Arenas;
for (var i = 1; i < list.Count; i += 2)
AddImageTiled(12, 32 + i * 31, 475 + 40, 30, 0x2430);
AddAlphaRegion(10, 10, 479 + 40, height - 20);
AddColumnHeader(35, null);
AddColumnHeader(115, "Arena");
AddColumnHeader(325, "Participants");
AddColumnHeader(40, "Obs");
AddButton(499 + 40 - 12 - 63 - 4 - 63, height - 12 - 24, 247, 248, 1);
AddButton(499 + 40 - 12 - 63, height - 12 - 24, 241, 242, 2);
for (var i = 0; i < list.Count; ++i)
{
var ar = list[i];
var x = 12;
var y = 32 + i * 31;
var color = ar.Players.Count > 0 ? 0xCCFFCC : 0xCCCCCC;
AddRadio(x + 3, y + 1, 9727, 9730, false, i);
x += 35;
AddBorderedText(x + 5, y + 5, 115 - 5, ar.Name ?? "(no name)", color, 0);
x += 115;
var sb = new StringBuilder();
if (ar.Players.Count > 0)
{
var ladder = Ladder.Instance;
if (ladder == null)
continue;
LadderEntry p1 = null, p2 = null, p3 = null, p4 = null;
for (var j = 0; j < ar.Players.Count; ++j)
{
var mob = ar.Players[j];
var c = ladder.Find(mob);
if (p1 == null || c.Index < p1.Index)
{
p4 = p3;
p3 = p2;
p2 = p1;
p1 = c;
}
else if (p2 == null || c.Index < p2.Index)
{
p4 = p3;
p3 = p2;
p2 = c;
}
else if (p3 == null || c.Index < p3.Index)
{
p4 = p3;
p3 = c;
}
else if (p4 == null || c.Index < p4.Index)
{
p4 = c;
}
}
Append(sb, p1);
Append(sb, p2);
Append(sb, p3);
Append(sb, p4);
if (ar.Players.Count > 4)
sb.Append(", ...");
}
else
{
sb.Append("Empty");
}
AddBorderedText(x + 5, y + 5, 325 - 5, sb.ToString(), color, 0);
x += 325;
AddBorderedText(x, y + 5, 40, Center(ar.Spectators.ToString()), color, 0);
}
}
private void Append(StringBuilder sb, LadderEntry le)
{
if (le == null)
return;
if (sb.Length > 0)
sb.Append(", ");
sb.Append(le.Mobile.Name);
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID != 1)
return;
var switches = info.Switches;
if (switches.Length == 0)
return;
var opt = switches[0];
if (opt < 0 || opt >= m_Arenas.Count)
return;
var arena = m_Arenas[opt];
if (!m_From.InRange(m_Gate.GetWorldLocation(), 1) || m_From.Map != m_Gate.Map)
{
m_From.SendLocalizedMessage(1019002); // You are too far away to use the gate.
}
else if (DuelContext.CheckCombat(m_From))
{
m_From.SendMessage(
0x22,
"You have recently been in combat with another player and cannot use this moongate."
);
}
else if (m_From.Spell != null)
{
m_From.SendLocalizedMessage(1049616); // You are too busy to do that at the moment.
}
else if (m_From.Map == arena.Facet && arena.Zone.Contains(m_From))
{
m_From.SendLocalizedMessage(1019003); // You are already there.
}
else
{
BaseCreature.TeleportPets(m_From, arena.GateIn, arena.Facet);
m_From.Combatant = null;
m_From.Warmode = false;
m_From.Hidden = true;
m_From.MoveToWorld(arena.GateIn, arena.Facet);
Effects.PlaySound(arena.GateIn, arena.Facet, 0x1FE);
}
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public string Color(string text, int color) => $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
private void AddBorderedText(int x, int y, int width, string text, int color, int borderColor)
{
/*AddColoredText( x - 1, y, width, text, borderColor );
AddColoredText( x + 1, y, width, text, borderColor );
AddColoredText( x, y - 1, width, text, borderColor );
AddColoredText( x, y + 1, width, text, borderColor );*/
/*AddColoredText( x - 1, y - 1, width, text, borderColor );
AddColoredText( x + 1, y + 1, width, text, borderColor );*/
AddColoredText(x, y, width, text, color);
}
private void AddColoredText(int x, int y, int width, string text, int color)
{
if (color == 0)
AddHtml(x, y, width, 20, text);
else
AddHtml(x, y, width, 20, Color(text, color));
}
private void AddColumnHeader(int width, string name)
{
AddBackground(m_ColumnX, 12, width, 20, 0x242C);
AddImageTiled(m_ColumnX + 2, 14, width - 4, 16, 0x2430);
if (name != null)
AddBorderedText(m_ColumnX, 13, width, Center(name), 0xFFFFFF, 0);
m_ColumnX += width;
}
}
}

View file

@ -1,66 +1,96 @@
using Server.Gumps;
namespace Server.Engines.ConPVP
{
public class BeginGump : Gump
{
private const int LabelColor32 = 0xFFFFFF;
private const int BlackColor32 = 0x000008;
public BeginGump(int count) : base(50, 50)
{
AddPage(0);
const int offset = 50;
AddBackground(1, 1, 398, 202 - offset, 3600);
AddImageTiled(16, 15, 369, 173 - offset, 3604);
AddAlphaRegion(16, 15, 369, 173 - offset);
AddImage(215, -43, 0xEE40);
AddHtml(22 - 1, 22, 294, 20, Color(Center("Duel Countdown"), BlackColor32));
AddHtml(22 + 1, 22, 294, 20, Color(Center("Duel Countdown"), BlackColor32));
AddHtml(22, 22 - 1, 294, 20, Color(Center("Duel Countdown"), BlackColor32));
AddHtml(22, 22 + 1, 294, 20, Color(Center("Duel Countdown"), BlackColor32));
AddHtml(22, 22, 294, 20, Color(Center("Duel Countdown"), LabelColor32));
AddHtml(22 - 1, 50, 294, 80,
Color(
"The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.",
BlackColor32));
AddHtml(22 + 1, 50, 294, 80,
Color(
"The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.",
BlackColor32));
AddHtml(22, 50 - 1, 294, 80,
Color(
"The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.",
BlackColor32));
AddHtml(22, 50 + 1, 294, 80,
Color(
"The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.",
BlackColor32));
AddHtml(22, 50, 294, 80,
Color(
"The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.",
0xFFCC66));
/*AddImageTiled( 32, 128, 264, 1, 9107 );
AddImageTiled( 42, 130, 264, 1, 9157 );
AddHtml( 60-1, 140, 250, 20, Color( String.Format( "Duel will begin in <BASEFONT COLOR=#{2:X6}>{0} <BASEFONT COLOR=#{2:X6}>second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false );
AddHtml( 60+1, 140, 250, 20, Color( String.Format( "Duel will begin in <BASEFONT COLOR=#{2:X6}>{0} <BASEFONT COLOR=#{2:X6}>second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false );
AddHtml( 60, 140-1, 250, 20, Color( String.Format( "Duel will begin in <BASEFONT COLOR=#{2:X6}>{0} <BASEFONT COLOR=#{2:X6}>second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false );
AddHtml( 60, 140+1, 250, 20, Color( String.Format( "Duel will begin in <BASEFONT COLOR=#{2:X6}>{0} <BASEFONT COLOR=#{2:X6}>second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false );
AddHtml( 60, 140, 250, 20, Color( String.Format( "Duel will begin in <BASEFONT COLOR=#FF6666>{0} <BASEFONT COLOR=#{2:X6}>second{1}.", count, count==1?"":"s", 0x66AACC ), 0x66AACC ), false, false );*/
AddButton(314 - 50, 157 - offset, 247, 248, 1);
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public string Color(string text, int color) => $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
}
}
using Server.Gumps;
namespace Server.Engines.ConPVP
{
public class BeginGump : Gump
{
private const int LabelColor32 = 0xFFFFFF;
private const int BlackColor32 = 0x000008;
public BeginGump(int count) : base(50, 50)
{
AddPage(0);
const int offset = 50;
AddBackground(1, 1, 398, 202 - offset, 3600);
AddImageTiled(16, 15, 369, 173 - offset, 3604);
AddAlphaRegion(16, 15, 369, 173 - offset);
AddImage(215, -43, 0xEE40);
AddHtml(22 - 1, 22, 294, 20, Color(Center("Duel Countdown"), BlackColor32));
AddHtml(22 + 1, 22, 294, 20, Color(Center("Duel Countdown"), BlackColor32));
AddHtml(22, 22 - 1, 294, 20, Color(Center("Duel Countdown"), BlackColor32));
AddHtml(22, 22 + 1, 294, 20, Color(Center("Duel Countdown"), BlackColor32));
AddHtml(22, 22, 294, 20, Color(Center("Duel Countdown"), LabelColor32));
AddHtml(
22 - 1,
50,
294,
80,
Color(
"The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.",
BlackColor32
)
);
AddHtml(
22 + 1,
50,
294,
80,
Color(
"The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.",
BlackColor32
)
);
AddHtml(
22,
50 - 1,
294,
80,
Color(
"The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.",
BlackColor32
)
);
AddHtml(
22,
50 + 1,
294,
80,
Color(
"The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.",
BlackColor32
)
);
AddHtml(
22,
50,
294,
80,
Color(
"The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.",
0xFFCC66
)
);
/*AddImageTiled( 32, 128, 264, 1, 9107 );
AddImageTiled( 42, 130, 264, 1, 9157 );
AddHtml( 60-1, 140, 250, 20, Color( String.Format( "Duel will begin in <BASEFONT COLOR=#{2:X6}>{0} <BASEFONT COLOR=#{2:X6}>second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false );
AddHtml( 60+1, 140, 250, 20, Color( String.Format( "Duel will begin in <BASEFONT COLOR=#{2:X6}>{0} <BASEFONT COLOR=#{2:X6}>second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false );
AddHtml( 60, 140-1, 250, 20, Color( String.Format( "Duel will begin in <BASEFONT COLOR=#{2:X6}>{0} <BASEFONT COLOR=#{2:X6}>second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false );
AddHtml( 60, 140+1, 250, 20, Color( String.Format( "Duel will begin in <BASEFONT COLOR=#{2:X6}>{0} <BASEFONT COLOR=#{2:X6}>second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false );
AddHtml( 60, 140, 250, 20, Color( String.Format( "Duel will begin in <BASEFONT COLOR=#FF6666>{0} <BASEFONT COLOR=#{2:X6}>second{1}.", count, count==1?"":"s", 0x66AACC ), 0x66AACC ), false, false );*/
AddButton(314 - 50, 157 - offset, 247, 248, 1);
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public string Color(string text, int color) => $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,136 +1,147 @@
using Server.Gumps;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class DuelContextGump : Gump
{
public DuelContextGump(Mobile from, DuelContext context) : base(50, 50)
{
From = from;
Context = context;
from.CloseGump<RulesetGump>();
from.CloseGump<DuelContextGump>();
from.CloseGump<ParticipantGump>();
int count = context.Participants.Count;
if (count < 3)
count = 3;
int height = 35 + 10 + 22 + 30 + 22 + 22 + 2 + count * 22 + 2 + 30;
AddPage(0);
AddBackground(0, 0, 300, height, 9250);
AddBackground(10, 10, 280, height - 20, 0xDAC);
AddHtml(35, 25, 230, 20, Center("Duel Setup"));
int x = 35;
int y = 47;
AddGoldenButtonLabeled(x, y, 1, "Rules");
y += 22;
AddGoldenButtonLabeled(x, y, 2, "Start");
y += 22;
AddGoldenButtonLabeled(x, y, 3, "Add Participant");
y += 30;
AddHtml(35, y, 230, 20, Center("Participants"));
y += 22;
for (int i = 0; i < context.Participants.Count; ++i)
{
Participant p = context.Participants[i];
AddGoldenButtonLabeled(x, y, 4 + i,
string.Format(p.Count == 1 ? "Player {0}: {3}" : "Team {0}: {1}/{2}: {3}", 1 + i, p.FilledSlots, p.Count,
p.NameList));
y += 22;
}
}
public Mobile From { get; }
public DuelContext Context { get; }
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public void AddGoldenButton(int x, int y, int bid)
{
AddButton(x, y, 0xD2, 0xD2, bid);
AddButton(x + 3, y + 3, 0xD8, 0xD8, bid);
}
public void AddGoldenButtonLabeled(int x, int y, int bid, string text)
{
AddGoldenButton(x, y, bid);
AddHtml(x + 25, y, 200, 20, text);
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (!Context.Registered)
return;
int index = info.ButtonID;
switch (index)
{
case -1: // CloseGump
{
break;
}
case 0: // closed
{
Context.Unregister();
break;
}
case 1: // Rules
{
// m_From.SendGump( new RulesetGump( m_From, m_Context.Ruleset, m_Context.Ruleset.Layout, m_Context ) );
From.SendGump(new PickRulesetGump(From, Context, Context.Ruleset));
break;
}
case 2: // Start
{
if (Context.CheckFull())
{
Context.CloseAllGumps();
Context.SendReadyUpGump();
// m_Context.SendReadyGump();
}
else
{
From.SendMessage("You cannot start the duel before all participating players have been assigned.");
From.SendGump(new DuelContextGump(From, Context));
}
break;
}
case 3: // New Participant
{
if (Context.Participants.Count < 10)
Context.Participants.Add(new Participant(Context, 1));
else
From.SendMessage("The number of participating parties may not be increased further.");
From.SendGump(new DuelContextGump(From, Context));
break;
}
default: // Participant
{
index -= 4;
if (index >= 0 && index < Context.Participants.Count)
From.SendGump(new ParticipantGump(From, Context, Context.Participants[index]));
break;
}
}
}
}
}
using Server.Gumps;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class DuelContextGump : Gump
{
public DuelContextGump(Mobile from, DuelContext context) : base(50, 50)
{
From = from;
Context = context;
from.CloseGump<RulesetGump>();
from.CloseGump<DuelContextGump>();
from.CloseGump<ParticipantGump>();
var count = context.Participants.Count;
if (count < 3)
count = 3;
var height = 35 + 10 + 22 + 30 + 22 + 22 + 2 + count * 22 + 2 + 30;
AddPage(0);
AddBackground(0, 0, 300, height, 9250);
AddBackground(10, 10, 280, height - 20, 0xDAC);
AddHtml(35, 25, 230, 20, Center("Duel Setup"));
var x = 35;
var y = 47;
AddGoldenButtonLabeled(x, y, 1, "Rules");
y += 22;
AddGoldenButtonLabeled(x, y, 2, "Start");
y += 22;
AddGoldenButtonLabeled(x, y, 3, "Add Participant");
y += 30;
AddHtml(35, y, 230, 20, Center("Participants"));
y += 22;
for (var i = 0; i < context.Participants.Count; ++i)
{
var p = context.Participants[i];
AddGoldenButtonLabeled(
x,
y,
4 + i,
string.Format(
p.Count == 1 ? "Player {0}: {3}" : "Team {0}: {1}/{2}: {3}",
1 + i,
p.FilledSlots,
p.Count,
p.NameList
)
);
y += 22;
}
}
public Mobile From { get; }
public DuelContext Context { get; }
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public void AddGoldenButton(int x, int y, int bid)
{
AddButton(x, y, 0xD2, 0xD2, bid);
AddButton(x + 3, y + 3, 0xD8, 0xD8, bid);
}
public void AddGoldenButtonLabeled(int x, int y, int bid, string text)
{
AddGoldenButton(x, y, bid);
AddHtml(x + 25, y, 200, 20, text);
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (!Context.Registered)
return;
var index = info.ButtonID;
switch (index)
{
case -1: // CloseGump
{
break;
}
case 0: // closed
{
Context.Unregister();
break;
}
case 1: // Rules
{
// m_From.SendGump( new RulesetGump( m_From, m_Context.Ruleset, m_Context.Ruleset.Layout, m_Context ) );
From.SendGump(new PickRulesetGump(From, Context, Context.Ruleset));
break;
}
case 2: // Start
{
if (Context.CheckFull())
{
Context.CloseAllGumps();
Context.SendReadyUpGump();
// m_Context.SendReadyGump();
}
else
{
From.SendMessage(
"You cannot start the duel before all participating players have been assigned."
);
From.SendGump(new DuelContextGump(From, Context));
}
break;
}
case 3: // New Participant
{
if (Context.Participants.Count < 10)
Context.Participants.Add(new Participant(Context, 1));
else
From.SendMessage("The number of participating parties may not be increased further.");
From.SendGump(new DuelContextGump(From, Context));
break;
}
default: // Participant
{
index -= 4;
if (index >= 0 && index < Context.Participants.Count)
From.SendGump(new ParticipantGump(From, Context, Context.Participants[index]));
break;
}
}
}
}
}

View file

@ -1,239 +1,246 @@
using System;
using System.Collections.Generic;
using Server.Gumps;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class LadderItem : Item
{
[Constructible]
public LadderItem() : base(0x117F) => Movable = false;
public LadderItem(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public LadderController Ladder { get; set; }
public override string DefaultName => "1v1 leaderboard";
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(1);
writer.Write(Ladder);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
{
Ladder = reader.ReadItem<LadderController>();
break;
}
}
}
public override void OnDoubleClick(Mobile from)
{
if (from.InRange(GetWorldLocation(), 2))
{
Ladder ladder = ConPVP.Ladder.Instance ?? Ladder.Ladder;
if (ladder != null)
{
from.CloseGump<LadderGump>();
from.SendGump(new LadderGump(ladder));
}
}
else
{
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that
}
}
}
public class LadderGump : Gump
{
private int m_ColumnX = 12;
private readonly Ladder m_Ladder;
private readonly List<LadderEntry> m_List;
private readonly int m_Page;
public LadderGump(Ladder ladder, int page = 0) : base(50, 50)
{
m_Ladder = ladder;
m_Page = page;
AddPage(0);
m_List = new List<LadderEntry>(ladder.Entries);
int lc = Math.Min(m_List.Count, 150);
int start = page * 15;
int end = start + 15;
if (end > lc)
end = lc;
int ct = end - start;
int height = 12 + 20 + ct * 20 + 23 + 12;
AddBackground(0, 0, 499, height, 0x2436);
for (int i = start + 1; i < end; i += 2)
AddImageTiled(12, 32 + (i - start) * 20, 475, 20, 0x2430);
AddAlphaRegion(10, 10, 479, height - 20);
if (page > 0)
AddButton(446, height - 12 - 2 - 16, 0x15E3, 0x15E7, 1);
else
AddImage(446, height - 12 - 2 - 16, 0x2626);
if ((page + 1) * 15 < lc)
AddButton(466, height - 12 - 2 - 16, 0x15E1, 0x15E5, 2);
else
AddImage(466, height - 12 - 2 - 16, 0x2622);
AddHtml(16, height - 12 - 2 - 18, 400, 20,
Color(string.Format("Top {3} of {0:N0} duelists, page {1} of {2}", m_List.Count, page + 1, (lc + 14) / 15, lc),
0xFFC000));
AddColumnHeader(75, "Rank");
AddColumnHeader(115, "Level");
AddColumnHeader(50, "Guild");
AddColumnHeader(115, "Name");
AddColumnHeader(60, "Wins");
AddColumnHeader(60, "Losses");
for (int i = start; i < end && i < lc; ++i)
{
LadderEntry entry = m_List[i];
int y = 32 + (i - start) * 20;
int x = 12;
AddBorderedText(x, y, 75, Center(Rank(i + 1)), 0xFFFFFF, 0);
x += 75;
/*AddImage( 20, y + 5, 0x2616, 0x96C );
AddImage( 22, y + 5, 0x2616, 0x96C );
AddImage( 20, y + 7, 0x2616, 0x96C );
AddImage( 22, y + 7, 0x2616, 0x96C );
AddImage( 21, y + 6, 0x2616, 0x454 );*/
AddImage(x + 3, y + 4, 0x805);
int xp = entry.Experience;
int level = Ladder.GetLevel(xp);
Ladder.GetLevelInfo(level, out int xpBase, out int xpAdvance);
int width;
int xpOffset = xp - xpBase;
if (xpOffset >= xpAdvance)
width = 109; // level 50
else
width = (109 * xpOffset + xpAdvance / 2) / (xpAdvance - 1);
// AddImageTiled( 21, y + 6, width, 8, 0x2617 );
AddImageTiled(x + 3, y + 4, width, 11, 0x806);
AddBorderedText(x, y, 115, Center(level.ToString()), 0xFFFFFF, 0);
x += 115;
Mobile mob = entry.Mobile;
if (mob.Guild != null)
AddBorderedText(x, y, 50, Center(mob.Guild.Abbreviation), 0xFFFFFF, 0);
x += 50;
AddBorderedText(x + 5, y, 115 - 5, mob.Name, 0xFFFFFF, 0);
x += 115;
AddBorderedText(x, y, 60, Center(entry.Wins.ToString()), 0xFFFFFF, 0);
x += 60;
AddBorderedText(x, y, 60, Center(entry.Losses.ToString()), 0xFFFFFF, 0);
x += 60;
// AddBorderedText( 292 + 15, y, 115 - 30, String.Format( "{0} <DIV ALIGN=CENTER>/</DIV> <DIV ALIGN=RIGHT>{1}</DIV>", entry.Wins, entry.Losses ), 0xFFC000, 0 );
}
}
public static string Rank(int num)
{
string numStr = num.ToString("N0");
if (num % 100 > 10 && num % 100 < 20)
return $"{numStr}th";
return (num % 10) switch
{
1 => $"{numStr}st",
2 => $"{numStr}nd",
3 => $"{numStr}rd",
_ => $"{numStr}th"
};
}
public override void OnResponse(NetState sender, RelayInfo info)
{
Mobile from = sender.Mobile;
if (info.ButtonID == 1 && m_Page > 0)
from.SendGump(new LadderGump(m_Ladder, m_Page - 1));
else if (info.ButtonID == 2 && (m_Page + 1) * 15 < Math.Min(m_List.Count, 150))
from.SendGump(new LadderGump(m_Ladder, m_Page + 1));
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public string Color(string text, int color) => $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
private void AddBorderedText(int x, int y, int width, string text, int color, int borderColor)
{
/*AddColoredText( x - 1, y, width, text, borderColor );
AddColoredText( x + 1, y, width, text, borderColor );
AddColoredText( x, y - 1, width, text, borderColor );
AddColoredText( x, y + 1, width, text, borderColor );*/
/*AddColoredText( x - 1, y - 1, width, text, borderColor );
AddColoredText( x + 1, y + 1, width, text, borderColor );*/
AddColoredText(x, y, width, text, color);
}
private void AddColoredText(int x, int y, int width, string text, int color)
{
if (color == 0)
AddHtml(x, y, width, 20, text);
else
AddHtml(x, y, width, 20, Color(text, color));
}
private void AddColumnHeader(int width, string name)
{
AddBackground(m_ColumnX, 12, width, 20, 0x242C);
AddImageTiled(m_ColumnX + 2, 14, width - 4, 16, 0x2430);
AddBorderedText(m_ColumnX, 13, width, Center(name), 0xFFFFFF, 0);
m_ColumnX += width;
}
}
}
using System;
using System.Collections.Generic;
using Server.Gumps;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class LadderItem : Item
{
[Constructible]
public LadderItem() : base(0x117F) => Movable = false;
public LadderItem(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public LadderController Ladder { get; set; }
public override string DefaultName => "1v1 leaderboard";
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(1);
writer.Write(Ladder);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 1:
{
Ladder = reader.ReadItem<LadderController>();
break;
}
}
}
public override void OnDoubleClick(Mobile from)
{
if (from.InRange(GetWorldLocation(), 2))
{
var ladder = ConPVP.Ladder.Instance ?? Ladder.Ladder;
if (ladder != null)
{
from.CloseGump<LadderGump>();
from.SendGump(new LadderGump(ladder));
}
}
else
{
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that
}
}
}
public class LadderGump : Gump
{
private readonly Ladder m_Ladder;
private readonly List<LadderEntry> m_List;
private readonly int m_Page;
private int m_ColumnX = 12;
public LadderGump(Ladder ladder, int page = 0) : base(50, 50)
{
m_Ladder = ladder;
m_Page = page;
AddPage(0);
m_List = new List<LadderEntry>(ladder.Entries);
var lc = Math.Min(m_List.Count, 150);
var start = page * 15;
var end = start + 15;
if (end > lc)
end = lc;
var ct = end - start;
var height = 12 + 20 + ct * 20 + 23 + 12;
AddBackground(0, 0, 499, height, 0x2436);
for (var i = start + 1; i < end; i += 2)
AddImageTiled(12, 32 + (i - start) * 20, 475, 20, 0x2430);
AddAlphaRegion(10, 10, 479, height - 20);
if (page > 0)
AddButton(446, height - 12 - 2 - 16, 0x15E3, 0x15E7, 1);
else
AddImage(446, height - 12 - 2 - 16, 0x2626);
if ((page + 1) * 15 < lc)
AddButton(466, height - 12 - 2 - 16, 0x15E1, 0x15E5, 2);
else
AddImage(466, height - 12 - 2 - 16, 0x2622);
AddHtml(
16,
height - 12 - 2 - 18,
400,
20,
Color(
string.Format("Top {3} of {0:N0} duelists, page {1} of {2}", m_List.Count, page + 1, (lc + 14) / 15, lc),
0xFFC000
)
);
AddColumnHeader(75, "Rank");
AddColumnHeader(115, "Level");
AddColumnHeader(50, "Guild");
AddColumnHeader(115, "Name");
AddColumnHeader(60, "Wins");
AddColumnHeader(60, "Losses");
for (var i = start; i < end && i < lc; ++i)
{
var entry = m_List[i];
var y = 32 + (i - start) * 20;
var x = 12;
AddBorderedText(x, y, 75, Center(Rank(i + 1)), 0xFFFFFF, 0);
x += 75;
/*AddImage( 20, y + 5, 0x2616, 0x96C );
AddImage( 22, y + 5, 0x2616, 0x96C );
AddImage( 20, y + 7, 0x2616, 0x96C );
AddImage( 22, y + 7, 0x2616, 0x96C );
AddImage( 21, y + 6, 0x2616, 0x454 );*/
AddImage(x + 3, y + 4, 0x805);
var xp = entry.Experience;
var level = Ladder.GetLevel(xp);
Ladder.GetLevelInfo(level, out var xpBase, out var xpAdvance);
int width;
var xpOffset = xp - xpBase;
if (xpOffset >= xpAdvance)
width = 109; // level 50
else
width = (109 * xpOffset + xpAdvance / 2) / (xpAdvance - 1);
// AddImageTiled( 21, y + 6, width, 8, 0x2617 );
AddImageTiled(x + 3, y + 4, width, 11, 0x806);
AddBorderedText(x, y, 115, Center(level.ToString()), 0xFFFFFF, 0);
x += 115;
var mob = entry.Mobile;
if (mob.Guild != null)
AddBorderedText(x, y, 50, Center(mob.Guild.Abbreviation), 0xFFFFFF, 0);
x += 50;
AddBorderedText(x + 5, y, 115 - 5, mob.Name, 0xFFFFFF, 0);
x += 115;
AddBorderedText(x, y, 60, Center(entry.Wins.ToString()), 0xFFFFFF, 0);
x += 60;
AddBorderedText(x, y, 60, Center(entry.Losses.ToString()), 0xFFFFFF, 0);
x += 60;
// AddBorderedText( 292 + 15, y, 115 - 30, String.Format( "{0} <DIV ALIGN=CENTER>/</DIV> <DIV ALIGN=RIGHT>{1}</DIV>", entry.Wins, entry.Losses ), 0xFFC000, 0 );
}
}
public static string Rank(int num)
{
var numStr = num.ToString("N0");
if (num % 100 > 10 && num % 100 < 20)
return $"{numStr}th";
return (num % 10) switch
{
1 => $"{numStr}st",
2 => $"{numStr}nd",
3 => $"{numStr}rd",
_ => $"{numStr}th"
};
}
public override void OnResponse(NetState sender, RelayInfo info)
{
var from = sender.Mobile;
if (info.ButtonID == 1 && m_Page > 0)
from.SendGump(new LadderGump(m_Ladder, m_Page - 1));
else if (info.ButtonID == 2 && (m_Page + 1) * 15 < Math.Min(m_List.Count, 150))
from.SendGump(new LadderGump(m_Ladder, m_Page + 1));
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public string Color(string text, int color) => $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
private void AddBorderedText(int x, int y, int width, string text, int color, int borderColor)
{
/*AddColoredText( x - 1, y, width, text, borderColor );
AddColoredText( x + 1, y, width, text, borderColor );
AddColoredText( x, y - 1, width, text, borderColor );
AddColoredText( x, y + 1, width, text, borderColor );*/
/*AddColoredText( x - 1, y - 1, width, text, borderColor );
AddColoredText( x + 1, y + 1, width, text, borderColor );*/
AddColoredText(x, y, width, text, color);
}
private void AddColoredText(int x, int y, int width, string text, int color)
{
if (color == 0)
AddHtml(x, y, width, 20, text);
else
AddHtml(x, y, width, 20, Color(text, color));
}
private void AddColumnHeader(int width, string name)
{
AddBackground(m_ColumnX, 12, width, 20, 0x242C);
AddImageTiled(m_ColumnX + 2, 14, width - 4, 16, 0x2430);
AddBorderedText(m_ColumnX, 13, width, Center(name), 0xFFFFFF, 0);
m_ColumnX += width;
}
}
}

View file

@ -1,250 +1,255 @@
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
using Server.Targeting;
namespace Server.Engines.ConPVP
{
public class ParticipantGump : Gump
{
public ParticipantGump(Mobile from, DuelContext context, Participant p) : base(50, 50)
{
From = from;
Context = context;
Participant = p;
from.CloseGump<RulesetGump>();
from.CloseGump<DuelContextGump>();
from.CloseGump<ParticipantGump>();
int count = p.Players.Length;
if (count < 4)
count = 4;
AddPage(0);
int height = 35 + 10 + 22 + 22 + 30 + 22 + 2 + count * 22 + 2 + 30;
AddBackground(0, 0, 300, height, 9250);
AddBackground(10, 10, 280, height - 20, 0xDAC);
AddButton(240, 25, 0xFB1, 0xFB3, 3);
// AddButton( 223, 54, 0x265A, 0x265A, 4, );
AddHtml(35, 25, 230, 20, Center("Participant Setup"));
int x = 35;
int y = 47;
AddHtml(x, y, 200, 20, $"Team Size: {p.Players.Length}");
y += 22;
AddGoldenButtonLabeled(x + 20, y, 1, "Increase");
y += 22;
AddGoldenButtonLabeled(x + 20, y, 2, "Decrease");
y += 30;
AddHtml(35, y, 230, 20, Center("Players"));
y += 22;
for (int i = 0; i < p.Players.Length; ++i)
{
DuelPlayer pl = p.Players[i];
AddGoldenButtonLabeled(x, y, 5 + i, $"{1 + i}: {(pl == null ? "Empty" : pl.Mobile.Name)}");
y += 22;
}
}
public Mobile From { get; }
public DuelContext Context { get; }
public Participant Participant { get; }
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public void AddGoldenButton(int x, int y, int bid)
{
AddButton(x, y, 0xD2, 0xD2, bid);
AddButton(x + 3, y + 3, 0xD8, 0xD8, bid);
}
public void AddGoldenButtonLabeled(int x, int y, int bid, string text)
{
AddGoldenButton(x, y, bid);
AddHtml(x + 25, y, 200, 20, text);
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (!Context.Registered)
return;
int bid = info.ButtonID;
if (bid == 0)
{
From.SendGump(new DuelContextGump(From, Context));
}
else if (bid == 1)
{
if (Participant.Count < 8)
Participant.Resize(Participant.Count + 1);
else
From.SendMessage("You may not raise the team size any further.");
From.SendGump(new ParticipantGump(From, Context, Participant));
}
else if (bid == 2)
{
if (Participant.Count > 1 && Participant.Count > Participant.FilledSlots)
Participant.Resize(Participant.Count - 1);
else
From.SendMessage("You may not lower the team size any further.");
From.SendGump(new ParticipantGump(From, Context, Participant));
}
else if (bid == 3)
{
if (Participant.FilledSlots > 0)
{
From.SendMessage("There is at least one currently active player. You must remove them first.");
From.SendGump(new ParticipantGump(From, Context, Participant));
}
else if (Context.Participants.Count > 2)
{
/*Container cont = m_Participant.Stakes;
if (cont != null)
cont.Delete();*/
Context.Participants.Remove(Participant);
From.SendGump(new DuelContextGump(From, Context));
}
else
{
From.SendMessage("Duels must have at least two participating parties.");
From.SendGump(new ParticipantGump(From, Context, Participant));
}
}
/*else if (bid == 4)
{
m_From.SendGump( new ParticipantGump( m_From, m_Context, m_Participant ) );
Container cont = m_Participant.Stakes;
if (cont != null && !cont.Deleted)
{
cont.DisplayTo( m_From );
Item[] checks = cont.FindItemsByType( typeof( BankCheck ) );
int gold = cont.TotalGold;
for ( int i = 0; i < checks.Length; ++i )
gold += ((BankCheck)checks[i]).Worth;
m_From.SendMessage( "This container has {0} item{1} and {2} stone{3}. In gold or check form there is a total of {4:D}gp.", cont.TotalItems, cont.TotalItems==1?"":"s", cont.TotalWeight, cont.TotalWeight==1?"":"s", gold );
}
}*/
else
{
bid -= 5;
if (bid >= 0 && bid < Participant.Players.Length)
{
if (Participant.Players[bid] == null)
{
From.Target = new ParticipantTarget(Context, Participant, bid);
From.SendMessage("Target a player.");
}
else
{
Participant.Players[bid].Mobile.SendMessage("You have been removed from the duel.");
if (Participant.Players[bid].Mobile is PlayerMobile)
((PlayerMobile)Participant.Players[bid].Mobile).DuelPlayer = null;
Participant.Players[bid] = null;
From.SendMessage("They have been removed from the duel.");
From.SendGump(new ParticipantGump(From, Context, Participant));
}
}
}
}
private class ParticipantTarget : Target
{
private readonly DuelContext m_Context;
private readonly int m_Index;
private readonly Participant m_Participant;
public ParticipantTarget(DuelContext context, Participant p, int index) : base(12, false, TargetFlags.None)
{
m_Context = context;
m_Participant = p;
m_Index = index;
}
protected override void OnTarget(Mobile from, object targeted)
{
if (!m_Context.Registered)
return;
int index = m_Index;
if (index < 0 || index >= m_Participant.Players.Length)
return;
if (!(targeted is Mobile mob))
{
from.SendMessage("That is not a player.");
}
else if (!mob.Player)
{
if (mob.Body.IsHuman)
mob.SayTo(from, 1005443); // Nay, I would rather stay here and watch a nail rust.
else
mob.SayTo(from, 1005444); // The creature ignores your offer.
}
else if (AcceptDuelGump.IsIgnored(mob, from) || mob.Blessed)
{
from.SendMessage("They ignore your offer.");
}
else
{
if (!(mob is PlayerMobile pm))
return;
if (pm.DuelContext != null)
{
from.SendMessage("{0} cannot fight because they are already assigned to another duel.", pm.Name);
}
else if (DuelContext.CheckCombat(pm))
{
from.SendMessage("{0} cannot fight because they have recently been in combat with another player.",
pm.Name);
}
else if (mob.HasGump<AcceptDuelGump>())
{
from.SendMessage("{0} has already been offered a duel.");
}
else
{
from.SendMessage("You send {0} to {1}.",
m_Participant.Find(from) == null ? "a challenge" : "an invitation", mob.Name);
mob.SendGump(new AcceptDuelGump(from, mob, m_Context, m_Participant, m_Index));
}
}
}
protected override void OnTargetFinish(Mobile from)
{
from.SendGump(new ParticipantGump(from, m_Context, m_Participant));
}
}
}
}
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
using Server.Targeting;
namespace Server.Engines.ConPVP
{
public class ParticipantGump : Gump
{
public ParticipantGump(Mobile from, DuelContext context, Participant p) : base(50, 50)
{
From = from;
Context = context;
Participant = p;
from.CloseGump<RulesetGump>();
from.CloseGump<DuelContextGump>();
from.CloseGump<ParticipantGump>();
var count = p.Players.Length;
if (count < 4)
count = 4;
AddPage(0);
var height = 35 + 10 + 22 + 22 + 30 + 22 + 2 + count * 22 + 2 + 30;
AddBackground(0, 0, 300, height, 9250);
AddBackground(10, 10, 280, height - 20, 0xDAC);
AddButton(240, 25, 0xFB1, 0xFB3, 3);
// AddButton( 223, 54, 0x265A, 0x265A, 4, );
AddHtml(35, 25, 230, 20, Center("Participant Setup"));
var x = 35;
var y = 47;
AddHtml(x, y, 200, 20, $"Team Size: {p.Players.Length}");
y += 22;
AddGoldenButtonLabeled(x + 20, y, 1, "Increase");
y += 22;
AddGoldenButtonLabeled(x + 20, y, 2, "Decrease");
y += 30;
AddHtml(35, y, 230, 20, Center("Players"));
y += 22;
for (var i = 0; i < p.Players.Length; ++i)
{
var pl = p.Players[i];
AddGoldenButtonLabeled(x, y, 5 + i, $"{1 + i}: {(pl == null ? "Empty" : pl.Mobile.Name)}");
y += 22;
}
}
public Mobile From { get; }
public DuelContext Context { get; }
public Participant Participant { get; }
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public void AddGoldenButton(int x, int y, int bid)
{
AddButton(x, y, 0xD2, 0xD2, bid);
AddButton(x + 3, y + 3, 0xD8, 0xD8, bid);
}
public void AddGoldenButtonLabeled(int x, int y, int bid, string text)
{
AddGoldenButton(x, y, bid);
AddHtml(x + 25, y, 200, 20, text);
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (!Context.Registered)
return;
var bid = info.ButtonID;
if (bid == 0)
{
From.SendGump(new DuelContextGump(From, Context));
}
else if (bid == 1)
{
if (Participant.Count < 8)
Participant.Resize(Participant.Count + 1);
else
From.SendMessage("You may not raise the team size any further.");
From.SendGump(new ParticipantGump(From, Context, Participant));
}
else if (bid == 2)
{
if (Participant.Count > 1 && Participant.Count > Participant.FilledSlots)
Participant.Resize(Participant.Count - 1);
else
From.SendMessage("You may not lower the team size any further.");
From.SendGump(new ParticipantGump(From, Context, Participant));
}
else if (bid == 3)
{
if (Participant.FilledSlots > 0)
{
From.SendMessage("There is at least one currently active player. You must remove them first.");
From.SendGump(new ParticipantGump(From, Context, Participant));
}
else if (Context.Participants.Count > 2)
{
/*Container cont = m_Participant.Stakes;
if (cont != null)
cont.Delete();*/
Context.Participants.Remove(Participant);
From.SendGump(new DuelContextGump(From, Context));
}
else
{
From.SendMessage("Duels must have at least two participating parties.");
From.SendGump(new ParticipantGump(From, Context, Participant));
}
}
/*else if (bid == 4)
{
m_From.SendGump( new ParticipantGump( m_From, m_Context, m_Participant ) );
Container cont = m_Participant.Stakes;
if (cont != null && !cont.Deleted)
{
cont.DisplayTo( m_From );
Item[] checks = cont.FindItemsByType( typeof( BankCheck ) );
int gold = cont.TotalGold;
for ( int i = 0; i < checks.Length; ++i )
gold += ((BankCheck)checks[i]).Worth;
m_From.SendMessage( "This container has {0} item{1} and {2} stone{3}. In gold or check form there is a total of {4:D}gp.", cont.TotalItems, cont.TotalItems==1?"":"s", cont.TotalWeight, cont.TotalWeight==1?"":"s", gold );
}
}*/
else
{
bid -= 5;
if (bid >= 0 && bid < Participant.Players.Length)
{
if (Participant.Players[bid] == null)
{
From.Target = new ParticipantTarget(Context, Participant, bid);
From.SendMessage("Target a player.");
}
else
{
Participant.Players[bid].Mobile.SendMessage("You have been removed from the duel.");
if (Participant.Players[bid].Mobile is PlayerMobile)
((PlayerMobile)Participant.Players[bid].Mobile).DuelPlayer = null;
Participant.Players[bid] = null;
From.SendMessage("They have been removed from the duel.");
From.SendGump(new ParticipantGump(From, Context, Participant));
}
}
}
}
private class ParticipantTarget : Target
{
private readonly DuelContext m_Context;
private readonly int m_Index;
private readonly Participant m_Participant;
public ParticipantTarget(DuelContext context, Participant p, int index) : base(12, false, TargetFlags.None)
{
m_Context = context;
m_Participant = p;
m_Index = index;
}
protected override void OnTarget(Mobile from, object targeted)
{
if (!m_Context.Registered)
return;
var index = m_Index;
if (index < 0 || index >= m_Participant.Players.Length)
return;
if (!(targeted is Mobile mob))
{
from.SendMessage("That is not a player.");
}
else if (!mob.Player)
{
if (mob.Body.IsHuman)
mob.SayTo(from, 1005443); // Nay, I would rather stay here and watch a nail rust.
else
mob.SayTo(from, 1005444); // The creature ignores your offer.
}
else if (AcceptDuelGump.IsIgnored(mob, from) || mob.Blessed)
{
from.SendMessage("They ignore your offer.");
}
else
{
if (!(mob is PlayerMobile pm))
return;
if (pm.DuelContext != null)
{
from.SendMessage("{0} cannot fight because they are already assigned to another duel.", pm.Name);
}
else if (DuelContext.CheckCombat(pm))
{
from.SendMessage(
"{0} cannot fight because they have recently been in combat with another player.",
pm.Name
);
}
else if (mob.HasGump<AcceptDuelGump>())
{
from.SendMessage("{0} has already been offered a duel.");
}
else
{
from.SendMessage(
"You send {0} to {1}.",
m_Participant.Find(from) == null ? "a challenge" : "an invitation",
mob.Name
);
mob.SendGump(new AcceptDuelGump(from, mob, m_Context, m_Participant, m_Index));
}
}
}
protected override void OnTargetFinish(Mobile from)
{
from.SendGump(new ParticipantGump(from, m_Context, m_Participant));
}
}
}
}

View file

@ -1,123 +1,123 @@
using Server.Gumps;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class PickRulesetGump : Gump
{
private readonly DuelContext m_Context;
private readonly Ruleset[] m_Defaults;
private readonly Ruleset[] m_Flavors;
private readonly Mobile m_From;
private readonly Ruleset m_Ruleset;
public PickRulesetGump(Mobile from, DuelContext context, Ruleset ruleset) : base(50, 50)
{
m_From = from;
m_Context = context;
m_Ruleset = ruleset;
m_Defaults = ruleset.Layout.Defaults;
m_Flavors = ruleset.Layout.Flavors;
int height = 25 + 20 + (m_Defaults.Length + 1) * 22 + 6 + 20 + m_Flavors.Length * 22 + 25;
AddPage(0);
AddBackground(0, 0, 260, height, 9250);
AddBackground(10, 10, 240, height - 20, 0xDAC);
AddHtml(35, 25, 190, 20, Center("Rules"));
int y = 25 + 20;
for (int i = 0; i < m_Defaults.Length; ++i)
{
Ruleset cur = m_Defaults[i];
AddHtml(35 + 14, y, 176, 20, cur.Title);
if (ruleset.Base == cur && !ruleset.Changed)
AddImage(35, y + 4, 0x939);
else if (ruleset.Base == cur)
AddButton(35, y + 4, 0x93A, 0x939, 2 + i);
else
AddButton(35, y + 4, 0x938, 0x939, 2 + i);
y += 22;
}
AddHtml(35 + 14, y, 176, 20, "Custom");
AddButton(35, y + 4, ruleset.Changed ? 0x939 : 0x938, 0x939, 1);
y += 22;
y += 6;
AddHtml(35, y, 190, 20, Center("Flavors"));
y += 20;
for (int i = 0; i < m_Flavors.Length; ++i)
{
Ruleset cur = m_Flavors[i];
AddHtml(35 + 14, y, 176, 20, cur.Title);
if (ruleset.Flavors.Contains(cur))
AddButton(35, y + 4, 0x939, 0x938, 2 + m_Defaults.Length + i);
else
AddButton(35, y + 4, 0x938, 0x939, 2 + m_Defaults.Length + i);
y += 22;
}
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public override void OnResponse(NetState sender, RelayInfo info)
{
if (m_Context?.Registered == false)
return;
switch (info.ButtonID)
{
case 0: // closed
{
if (m_Context != null)
m_From.SendGump(new DuelContextGump(m_From, m_Context));
break;
}
case 1: // customize
{
m_From.SendGump(new RulesetGump(m_From, m_Ruleset, m_Ruleset.Layout, m_Context));
break;
}
default:
{
int idx = info.ButtonID - 2;
if (idx >= 0 && idx < m_Defaults.Length)
{
m_Ruleset.ApplyDefault(m_Defaults[idx]);
m_From.SendGump(new PickRulesetGump(m_From, m_Context, m_Ruleset));
}
else
{
idx -= m_Defaults.Length;
if (idx >= 0 && idx < m_Flavors.Length)
{
if (m_Ruleset.Flavors.Contains(m_Flavors[idx]))
m_Ruleset.RemoveFlavor(m_Flavors[idx]);
else
m_Ruleset.AddFlavor(m_Flavors[idx]);
m_From.SendGump(new PickRulesetGump(m_From, m_Context, m_Ruleset));
}
}
break;
}
}
}
}
}
using Server.Gumps;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class PickRulesetGump : Gump
{
private readonly DuelContext m_Context;
private readonly Ruleset[] m_Defaults;
private readonly Ruleset[] m_Flavors;
private readonly Mobile m_From;
private readonly Ruleset m_Ruleset;
public PickRulesetGump(Mobile from, DuelContext context, Ruleset ruleset) : base(50, 50)
{
m_From = from;
m_Context = context;
m_Ruleset = ruleset;
m_Defaults = ruleset.Layout.Defaults;
m_Flavors = ruleset.Layout.Flavors;
var height = 25 + 20 + (m_Defaults.Length + 1) * 22 + 6 + 20 + m_Flavors.Length * 22 + 25;
AddPage(0);
AddBackground(0, 0, 260, height, 9250);
AddBackground(10, 10, 240, height - 20, 0xDAC);
AddHtml(35, 25, 190, 20, Center("Rules"));
var y = 25 + 20;
for (var i = 0; i < m_Defaults.Length; ++i)
{
var cur = m_Defaults[i];
AddHtml(35 + 14, y, 176, 20, cur.Title);
if (ruleset.Base == cur && !ruleset.Changed)
AddImage(35, y + 4, 0x939);
else if (ruleset.Base == cur)
AddButton(35, y + 4, 0x93A, 0x939, 2 + i);
else
AddButton(35, y + 4, 0x938, 0x939, 2 + i);
y += 22;
}
AddHtml(35 + 14, y, 176, 20, "Custom");
AddButton(35, y + 4, ruleset.Changed ? 0x939 : 0x938, 0x939, 1);
y += 22;
y += 6;
AddHtml(35, y, 190, 20, Center("Flavors"));
y += 20;
for (var i = 0; i < m_Flavors.Length; ++i)
{
var cur = m_Flavors[i];
AddHtml(35 + 14, y, 176, 20, cur.Title);
if (ruleset.Flavors.Contains(cur))
AddButton(35, y + 4, 0x939, 0x938, 2 + m_Defaults.Length + i);
else
AddButton(35, y + 4, 0x938, 0x939, 2 + m_Defaults.Length + i);
y += 22;
}
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public override void OnResponse(NetState sender, RelayInfo info)
{
if (m_Context?.Registered == false)
return;
switch (info.ButtonID)
{
case 0: // closed
{
if (m_Context != null)
m_From.SendGump(new DuelContextGump(m_From, m_Context));
break;
}
case 1: // customize
{
m_From.SendGump(new RulesetGump(m_From, m_Ruleset, m_Ruleset.Layout, m_Context));
break;
}
default:
{
var idx = info.ButtonID - 2;
if (idx >= 0 && idx < m_Defaults.Length)
{
m_Ruleset.ApplyDefault(m_Defaults[idx]);
m_From.SendGump(new PickRulesetGump(m_From, m_Context, m_Ruleset));
}
else
{
idx -= m_Defaults.Length;
if (idx >= 0 && idx < m_Flavors.Length)
{
if (m_Ruleset.Flavors.Contains(m_Flavors[idx]))
m_Ruleset.RemoveFlavor(m_Flavors[idx]);
else
m_Ruleset.AddFlavor(m_Flavors[idx]);
m_From.SendGump(new PickRulesetGump(m_From, m_Context, m_Ruleset));
}
}
break;
}
}
}
}
}

View file

@ -1,106 +1,105 @@
using System.Collections.Generic;
using Server.Gumps;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class ReadyGump : Gump
{
private DuelContext m_Context;
private int m_Count;
private Mobile m_From;
public ReadyGump(Mobile from, DuelContext context, int count) : base(50, 50)
{
m_From = from;
m_Context = context;
m_Count = count;
List<Participant> parts = context.Participants;
int height = 25 + 20;
for (int i = 0; i < parts.Count; ++i)
{
Participant p = parts[i];
height += 4;
if (p.Players.Length > 1)
height += 22;
height += p.Players.Length * 22;
}
height += 25;
Closable = false;
Draggable = false;
AddPage(0);
AddBackground(0, 0, 260, height, 9250);
AddBackground(10, 10, 240, height - 20, 0xDAC);
if (count == -1)
{
AddHtml(35, 25, 190, 20, Center("Ready"));
}
else
{
AddHtml(35, 25, 190, 20, Center("Starting"));
AddHtml(35, 25, 190, 20, $"<DIV ALIGN=RIGHT>{count}");
}
int y = 25 + 20;
for (int i = 0; i < parts.Count; ++i)
{
Participant p = parts[i];
y += 4;
bool isAllReady = true;
int yStore = y;
int offset = 0;
if (p.Players.Length > 1)
{
AddHtml(35 + 14, y, 176, 20, $"Participant #{i + 1}");
y += 22;
offset = 10;
}
for (int j = 0; j < p.Players.Length; ++j)
{
DuelPlayer pl = p.Players[j];
if (pl?.Ready == true)
{
AddImage(35 + offset, y + 4, 0x939);
}
else
{
AddImage(35 + offset, y + 4, 0x938);
isAllReady = false;
}
string name = pl == null ? "(Empty)" : pl.Mobile.Name;
AddHtml(35 + offset + 14, y, 166, 20, name);
y += 22;
}
if (p.Players.Length > 1)
AddImage(35, yStore + 4, isAllReady ? 0x939 : 0x938);
}
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public override void OnResponse(NetState sender, RelayInfo info)
{
}
}
}
using Server.Gumps;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class ReadyGump : Gump
{
private DuelContext m_Context;
private int m_Count;
private Mobile m_From;
public ReadyGump(Mobile from, DuelContext context, int count) : base(50, 50)
{
m_From = from;
m_Context = context;
m_Count = count;
var parts = context.Participants;
var height = 25 + 20;
for (var i = 0; i < parts.Count; ++i)
{
var p = parts[i];
height += 4;
if (p.Players.Length > 1)
height += 22;
height += p.Players.Length * 22;
}
height += 25;
Closable = false;
Draggable = false;
AddPage(0);
AddBackground(0, 0, 260, height, 9250);
AddBackground(10, 10, 240, height - 20, 0xDAC);
if (count == -1)
{
AddHtml(35, 25, 190, 20, Center("Ready"));
}
else
{
AddHtml(35, 25, 190, 20, Center("Starting"));
AddHtml(35, 25, 190, 20, $"<DIV ALIGN=RIGHT>{count}");
}
var y = 25 + 20;
for (var i = 0; i < parts.Count; ++i)
{
var p = parts[i];
y += 4;
var isAllReady = true;
var yStore = y;
var offset = 0;
if (p.Players.Length > 1)
{
AddHtml(35 + 14, y, 176, 20, $"Participant #{i + 1}");
y += 22;
offset = 10;
}
for (var j = 0; j < p.Players.Length; ++j)
{
var pl = p.Players[j];
if (pl?.Ready == true)
{
AddImage(35 + offset, y + 4, 0x939);
}
else
{
AddImage(35 + offset, y + 4, 0x938);
isAllReady = false;
}
var name = pl == null ? "(Empty)" : pl.Mobile.Name;
AddHtml(35 + offset + 14, y, 166, 20, name);
y += 22;
}
if (p.Players.Length > 1)
AddImage(35, yStore + 4, isAllReady ? 0x939 : 0x938);
}
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public override void OnResponse(NetState sender, RelayInfo info)
{
}
}
}

View file

@ -1,222 +1,221 @@
using System.Collections;
using System.Collections.Generic;
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class ReadyUpGump : Gump
{
private readonly DuelContext m_Context;
private readonly Mobile m_From;
public ReadyUpGump(Mobile from, DuelContext context) : base(50, 50)
{
m_From = from;
m_Context = context;
Closable = false;
AddPage(0);
if (context.Rematch)
{
int height = 25 + 20 + 10 + 22 + 25;
AddBackground(0, 0, 210, height, 9250);
AddBackground(10, 10, 190, height - 20, 0xDAC);
AddHtml(35, 25, 140, 20, Center("Rematch?"));
AddButton(35, 55, 247, 248, 1);
AddButton(115, 55, 242, 241, 2);
}
else
{
AddPage(1);
List<Participant> parts = context.Participants;
int height = 25 + 20;
for (int i = 0; i < parts.Count; ++i)
{
Participant p = parts[i];
height += 4;
if (p.Players.Length > 1)
height += 22;
height += p.Players.Length * 22;
}
height += 10 + 22 + 25;
AddBackground(0, 0, 260, height, 9250);
AddBackground(10, 10, 240, height - 20, 0xDAC);
AddHtml(35, 25, 190, 20, Center("Participants"));
int y = 20 + 25;
for (int i = 0; i < parts.Count; ++i)
{
Participant p = parts[i];
y += 4;
int offset = 0;
if (p.Players.Length > 1)
{
AddHtml(35, y, 176, 20, $"Team #{i + 1}");
y += 22;
offset = 10;
}
for (int j = 0; j < p.Players.Length; ++j)
{
DuelPlayer pl = p.Players[j];
string name = pl == null ? "(Empty)" : pl.Mobile.Name;
AddHtml(35 + offset, y, 166, 20, name);
y += 22;
}
}
y += 8;
AddHtml(35, y, 176, 20, "Continue?");
y -= 2;
AddButton(102, y, 247, 248, 0, GumpButtonType.Page, 2);
AddButton(169, y, 242, 241, 2);
AddPage(2);
Ruleset ruleset = context.Ruleset;
Ruleset basedef = ruleset.Base;
height = 25 + 20 + 5 + 20 + 20 + 4;
int changes = 0;
BitArray defs;
if (ruleset.Flavors.Count > 0)
{
defs = new BitArray(basedef.Options);
for (int i = 0; i < ruleset.Flavors.Count; ++i)
defs.Or(ruleset.Flavors[i].Options);
height += ruleset.Flavors.Count * 18;
}
else
{
defs = basedef.Options;
}
BitArray opts = ruleset.Options;
for (int i = 0; i < opts.Length; ++i)
if (defs[i] != opts[i])
++changes;
height += changes * 22;
height += 10 + 22 + 25;
AddBackground(0, 0, 260, height, 9250);
AddBackground(10, 10, 240, height - 20, 0xDAC);
AddHtml(35, 25, 190, 20, Center("Rules"));
AddHtml(35, 50, 190, 20, $"Set: {basedef.Title}");
y = 70;
for (int i = 0; i < ruleset.Flavors.Count; ++i, y += 18)
AddHtml(35, y, 190, 20, $" + {ruleset.Flavors[i].Title}");
y += 4;
if (changes > 0)
{
AddHtml(35, y, 190, 20, "Modifications:");
y += 20;
for (int i = 0; i < opts.Length; ++i)
if (defs[i] != opts[i])
{
string name = ruleset.Layout.FindByIndex(i);
if (name != null) // sanity
{
AddImage(35, y, opts[i] ? 0xD3 : 0xD2);
AddHtml(60, y, 165, 22, name);
}
y += 22;
}
}
else
{
AddHtml(35, y, 190, 20, "Modifications: None");
y += 20;
}
y += 8;
AddHtml(35, y, 176, 20, "Continue?");
y -= 2;
AddButton(102, y, 247, 248, 1);
AddButton(169, y, 242, 241, 3);
}
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public void AddGoldenButton(int x, int y, int bid)
{
AddButton(x, y, 0xD2, 0xD2, bid);
AddButton(x + 3, y + 3, 0xD8, 0xD8, bid);
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (!m_Context.Registered || !m_Context.ReadyWait)
return;
switch (info.ButtonID)
{
case 1: // okay
{
if (!(m_From is PlayerMobile pm))
break;
pm.DuelPlayer.Ready = true;
m_Context.SendReadyGump();
break;
}
case 2: // reject participants
{
m_Context.RejectReady(m_From, "participants");
break;
}
case 3: // reject rules
{
m_Context.RejectReady(m_From, "rules");
break;
}
}
}
}
}
using System.Collections;
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class ReadyUpGump : Gump
{
private readonly DuelContext m_Context;
private readonly Mobile m_From;
public ReadyUpGump(Mobile from, DuelContext context) : base(50, 50)
{
m_From = from;
m_Context = context;
Closable = false;
AddPage(0);
if (context.Rematch)
{
var height = 25 + 20 + 10 + 22 + 25;
AddBackground(0, 0, 210, height, 9250);
AddBackground(10, 10, 190, height - 20, 0xDAC);
AddHtml(35, 25, 140, 20, Center("Rematch?"));
AddButton(35, 55, 247, 248, 1);
AddButton(115, 55, 242, 241, 2);
}
else
{
AddPage(1);
var parts = context.Participants;
var height = 25 + 20;
for (var i = 0; i < parts.Count; ++i)
{
var p = parts[i];
height += 4;
if (p.Players.Length > 1)
height += 22;
height += p.Players.Length * 22;
}
height += 10 + 22 + 25;
AddBackground(0, 0, 260, height, 9250);
AddBackground(10, 10, 240, height - 20, 0xDAC);
AddHtml(35, 25, 190, 20, Center("Participants"));
var y = 20 + 25;
for (var i = 0; i < parts.Count; ++i)
{
var p = parts[i];
y += 4;
var offset = 0;
if (p.Players.Length > 1)
{
AddHtml(35, y, 176, 20, $"Team #{i + 1}");
y += 22;
offset = 10;
}
for (var j = 0; j < p.Players.Length; ++j)
{
var pl = p.Players[j];
var name = pl == null ? "(Empty)" : pl.Mobile.Name;
AddHtml(35 + offset, y, 166, 20, name);
y += 22;
}
}
y += 8;
AddHtml(35, y, 176, 20, "Continue?");
y -= 2;
AddButton(102, y, 247, 248, 0, GumpButtonType.Page, 2);
AddButton(169, y, 242, 241, 2);
AddPage(2);
var ruleset = context.Ruleset;
var basedef = ruleset.Base;
height = 25 + 20 + 5 + 20 + 20 + 4;
var changes = 0;
BitArray defs;
if (ruleset.Flavors.Count > 0)
{
defs = new BitArray(basedef.Options);
for (var i = 0; i < ruleset.Flavors.Count; ++i)
defs.Or(ruleset.Flavors[i].Options);
height += ruleset.Flavors.Count * 18;
}
else
{
defs = basedef.Options;
}
var opts = ruleset.Options;
for (var i = 0; i < opts.Length; ++i)
if (defs[i] != opts[i])
++changes;
height += changes * 22;
height += 10 + 22 + 25;
AddBackground(0, 0, 260, height, 9250);
AddBackground(10, 10, 240, height - 20, 0xDAC);
AddHtml(35, 25, 190, 20, Center("Rules"));
AddHtml(35, 50, 190, 20, $"Set: {basedef.Title}");
y = 70;
for (var i = 0; i < ruleset.Flavors.Count; ++i, y += 18)
AddHtml(35, y, 190, 20, $" + {ruleset.Flavors[i].Title}");
y += 4;
if (changes > 0)
{
AddHtml(35, y, 190, 20, "Modifications:");
y += 20;
for (var i = 0; i < opts.Length; ++i)
if (defs[i] != opts[i])
{
var name = ruleset.Layout.FindByIndex(i);
if (name != null) // sanity
{
AddImage(35, y, opts[i] ? 0xD3 : 0xD2);
AddHtml(60, y, 165, 22, name);
}
y += 22;
}
}
else
{
AddHtml(35, y, 190, 20, "Modifications: None");
y += 20;
}
y += 8;
AddHtml(35, y, 176, 20, "Continue?");
y -= 2;
AddButton(102, y, 247, 248, 1);
AddButton(169, y, 242, 241, 3);
}
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public void AddGoldenButton(int x, int y, int bid)
{
AddButton(x, y, 0xD2, 0xD2, bid);
AddButton(x + 3, y + 3, 0xD8, 0xD8, bid);
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (!m_Context.Registered || !m_Context.ReadyWait)
return;
switch (info.ButtonID)
{
case 1: // okay
{
if (!(m_From is PlayerMobile pm))
break;
pm.DuelPlayer.Ready = true;
m_Context.SendReadyGump();
break;
}
case 2: // reject participants
{
m_Context.RejectReady(m_From, "participants");
break;
}
case 3: // reject rules
{
m_Context.RejectReady(m_From, "rules");
break;
}
}
}
}
}

View file

@ -1,123 +1,123 @@
using System.Collections;
using Server.Gumps;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class RulesetGump : Gump
{
private readonly DuelContext m_DuelContext;
private readonly Mobile m_From;
private readonly RulesetLayout m_Page;
private readonly bool m_ReadOnly;
private readonly Ruleset m_Ruleset;
public RulesetGump(Mobile from, Ruleset ruleset, RulesetLayout page, DuelContext duelContext, bool readOnly = false)
: base(readOnly ? 310 : 50, 50)
{
m_From = from;
m_Ruleset = ruleset;
m_Page = page;
m_DuelContext = duelContext;
m_ReadOnly = readOnly;
Draggable = !readOnly;
from.CloseGump<RulesetGump>();
from.CloseGump<DuelContextGump>();
from.CloseGump<ParticipantGump>();
RulesetLayout depthCounter = page;
while (depthCounter != null)
depthCounter = depthCounter.Parent;
int count = page.Children.Length + page.Options.Length;
AddPage(0);
int height = 35 + 10 + 2 + count * 22 + 2 + 30;
AddBackground(0, 0, 260, height, 9250);
AddBackground(10, 10, 240, height - 20, 0xDAC);
AddHtml(35, 25, 190, 20, Center(page.Title));
int x = 35;
int y = 47;
for (int i = 0; i < page.Children.Length; ++i)
{
AddGoldenButton(x, y, 1 + i);
AddHtml(x + 25, y, 250, 22, page.Children[i].Title);
y += 22;
}
for (int i = 0; i < page.Options.Length; ++i)
{
bool enabled = ruleset.Options[page.Offset + i];
if (readOnly)
AddImage(x, y, enabled ? 0xD3 : 0xD2);
else
AddCheck(x, y, 0xD2, 0xD3, enabled, i);
AddHtml(x + 25, y, 250, 22, page.Options[i]);
y += 22;
}
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public void AddGoldenButton(int x, int y, int bid)
{
AddButton(x, y, 0xD2, 0xD2, bid);
AddButton(x + 3, y + 3, 0xD8, 0xD8, bid);
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (m_DuelContext?.Registered == false)
return;
if (!m_ReadOnly)
{
BitArray opts = new BitArray(m_Page.Options.Length);
for (int i = 0; i < info.Switches.Length; ++i)
{
int sid = info.Switches[i];
if (sid >= 0 && sid < m_Page.Options.Length)
opts[sid] = true;
}
for (int i = 0; i < opts.Length; ++i)
if (m_Ruleset.Options[m_Page.Offset + i] != opts[i])
{
m_Ruleset.Options[m_Page.Offset + i] = opts[i];
m_Ruleset.Changed = true;
}
}
int bid = info.ButtonID;
if (bid == 0)
{
if (m_Page.Parent != null)
m_From.SendGump(new RulesetGump(m_From, m_Ruleset, m_Page.Parent, m_DuelContext, m_ReadOnly));
else if (!m_ReadOnly)
m_From.SendGump(new PickRulesetGump(m_From, m_DuelContext, m_Ruleset));
}
else
{
bid -= 1;
if (bid >= 0 && bid < m_Page.Children.Length)
m_From.SendGump(new RulesetGump(m_From, m_Ruleset, m_Page.Children[bid], m_DuelContext, m_ReadOnly));
}
}
}
}
using System.Collections;
using Server.Gumps;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class RulesetGump : Gump
{
private readonly DuelContext m_DuelContext;
private readonly Mobile m_From;
private readonly RulesetLayout m_Page;
private readonly bool m_ReadOnly;
private readonly Ruleset m_Ruleset;
public RulesetGump(Mobile from, Ruleset ruleset, RulesetLayout page, DuelContext duelContext, bool readOnly = false)
: base(readOnly ? 310 : 50, 50)
{
m_From = from;
m_Ruleset = ruleset;
m_Page = page;
m_DuelContext = duelContext;
m_ReadOnly = readOnly;
Draggable = !readOnly;
from.CloseGump<RulesetGump>();
from.CloseGump<DuelContextGump>();
from.CloseGump<ParticipantGump>();
var depthCounter = page;
while (depthCounter != null)
depthCounter = depthCounter.Parent;
var count = page.Children.Length + page.Options.Length;
AddPage(0);
var height = 35 + 10 + 2 + count * 22 + 2 + 30;
AddBackground(0, 0, 260, height, 9250);
AddBackground(10, 10, 240, height - 20, 0xDAC);
AddHtml(35, 25, 190, 20, Center(page.Title));
var x = 35;
var y = 47;
for (var i = 0; i < page.Children.Length; ++i)
{
AddGoldenButton(x, y, 1 + i);
AddHtml(x + 25, y, 250, 22, page.Children[i].Title);
y += 22;
}
for (var i = 0; i < page.Options.Length; ++i)
{
var enabled = ruleset.Options[page.Offset + i];
if (readOnly)
AddImage(x, y, enabled ? 0xD3 : 0xD2);
else
AddCheck(x, y, 0xD2, 0xD3, enabled, i);
AddHtml(x + 25, y, 250, 22, page.Options[i]);
y += 22;
}
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public void AddGoldenButton(int x, int y, int bid)
{
AddButton(x, y, 0xD2, 0xD2, bid);
AddButton(x + 3, y + 3, 0xD8, 0xD8, bid);
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (m_DuelContext?.Registered == false)
return;
if (!m_ReadOnly)
{
var opts = new BitArray(m_Page.Options.Length);
for (var i = 0; i < info.Switches.Length; ++i)
{
var sid = info.Switches[i];
if (sid >= 0 && sid < m_Page.Options.Length)
opts[sid] = true;
}
for (var i = 0; i < opts.Length; ++i)
if (m_Ruleset.Options[m_Page.Offset + i] != opts[i])
{
m_Ruleset.Options[m_Page.Offset + i] = opts[i];
m_Ruleset.Changed = true;
}
}
var bid = info.ButtonID;
if (bid == 0)
{
if (m_Page.Parent != null)
m_From.SendGump(new RulesetGump(m_From, m_Ruleset, m_Page.Parent, m_DuelContext, m_ReadOnly));
else if (!m_ReadOnly)
m_From.SendGump(new PickRulesetGump(m_From, m_DuelContext, m_Ruleset));
}
else
{
bid -= 1;
if (bid >= 0 && bid < m_Page.Children.Length)
m_From.SendGump(new RulesetGump(m_From, m_Ruleset, m_Page.Children[bid], m_DuelContext, m_ReadOnly));
}
}
}
}

View file

@ -1,357 +1,357 @@
using System;
using System.Collections.Generic;
namespace Server.Engines.ConPVP
{
public class LadderController : Item
{
[Constructible]
public LadderController() : base(0x1B7A)
{
Visible = false;
Movable = false;
Ladder = new Ladder();
Ladder.Instance ??= Ladder;
}
public LadderController(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.Administrator)]
public Ladder Ladder { get; private set; }
public override string DefaultName => "ladder controller";
public override void Delete()
{
if (Ladder.Instance == Ladder)
Ladder.Instance = null;
base.Delete();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(1);
Ladder.Serialize(writer);
writer.Write(Ladder.Instance == Ladder);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
case 0:
{
Ladder = new Ladder(reader);
if (version < 1 || reader.ReadBool())
Ladder.Instance = Ladder;
break;
}
}
}
}
public class Ladder
{
private static readonly int[] m_ShortLevels =
{
1,
2,
3, 3,
4, 4,
5, 5, 5,
6, 6, 6,
7, 7, 7, 7,
8, 8, 8, 8,
9, 9, 9, 9, 9
};
private static readonly int[] m_BaseXP =
{
0, 100, 200, 400, 600, 900, 1200, 1600, 2000, 2500
};
private static readonly int[] m_LossFactors =
{
10,
11, 11,
25, 25,
43, 43,
67, 67
};
private static readonly int[,] m_OffsetScalar =
{
/* { win, los } */
/* -6 */ { 175, 25 },
/* -5 */ { 165, 35 },
/* -4 */ { 155, 45 },
/* -3 */ { 145, 55 },
/* -2 */ { 130, 70 },
/* -1 */ { 115, 85 },
/* 0 */ { 100, 100 },
/* +1 */ { 90, 110 },
/* +2 */ { 80, 120 },
/* +3 */ { 70, 130 },
/* +4 */ { 60, 140 },
/* +5 */ { 50, 150 },
/* +6 */ { 40, 160 }
};
public List<LadderEntry> Entries { get; } = new List<LadderEntry>();
private readonly Dictionary<Mobile, LadderEntry> m_Table;
public Ladder() => m_Table = new Dictionary<Mobile, LadderEntry>();
public Ladder(IGenericReader reader)
{
int version = reader.ReadEncodedInt();
switch (version)
{
case 1:
case 0:
{
int count = reader.ReadEncodedInt();
m_Table = new Dictionary<Mobile, LadderEntry>(count);
Entries = new List<LadderEntry>(count);
for (int i = 0; i < count; ++i)
{
LadderEntry entry = new LadderEntry(reader, this, version);
if (entry.Mobile != null)
{
m_Table[entry.Mobile] = entry;
entry.Index = Entries.Count;
Entries.Add(entry);
}
}
if (version == 0)
{
Entries.Sort();
for (int i = 0; i < Entries.Count; ++i)
{
LadderEntry entry = Entries[i];
entry.Index = i;
}
}
break;
}
}
}
public static Ladder Instance { get; set; }
public static int GetLevel(int xp)
{
if (xp >= 22500)
return 50;
if (xp >= 2500)
return 10 + (xp - 2500) / 500;
return m_ShortLevels[Math.Max(xp, 0) / 100];
}
public static void GetLevelInfo(int level, out int xpBase, out int xpAdvance)
{
if (level >= 10)
{
xpBase = 2500 + (level - 10) * 500;
xpAdvance = 500;
}
else
{
xpBase = m_BaseXP[level - 1];
xpAdvance = m_BaseXP[level] - xpBase;
}
}
public static int GetLossFactor(int level)
{
if (level >= 10)
return 100;
return m_LossFactors[level - 1];
}
public static int GetOffsetScalar(int ourLevel, int theirLevel, bool win)
{
int x = ourLevel - theirLevel;
if (x < -6 || x > +6)
return 0;
int y = win ? 0 : 1;
return m_OffsetScalar[x + 6, y];
}
public static int GetExperienceGain(LadderEntry us, LadderEntry them, bool weWon)
{
if (us == null || them == null)
return 0;
int ourLevel = GetLevel(us.Experience);
int theirLevel = GetLevel(them.Experience);
int scalar = GetOffsetScalar(ourLevel, theirLevel, weWon);
if (scalar == 0)
return 0;
int xp = 25 * scalar;
if (!weWon)
xp = xp * GetLossFactor(ourLevel) / 100;
xp /= 100;
if (xp <= 0)
xp = 1;
return xp * (weWon ? 1 : -1);
}
private int Swap(int idx, int newIdx)
{
LadderEntry hold = Entries[idx];
Entries[idx] = Entries[newIdx];
Entries[newIdx] = hold;
Entries[idx].Index = idx;
Entries[newIdx].Index = newIdx;
return newIdx;
}
public void UpdateEntry(LadderEntry entry)
{
int index = entry.Index;
if (index >= 0 && index < Entries.Count)
{
while (index - 1 >= 0 && entry.CompareTo(Entries[index - 1]) < 0)
index = Swap(index, index - 1);
while (index + 1 < Entries.Count && entry.CompareTo(Entries[index + 1]) > 0)
index = Swap(index, index + 1);
}
}
public LadderEntry Find(Mobile mob)
{
if (m_Table.TryGetValue(mob, out LadderEntry entry))
{
m_Table[mob] = entry = new LadderEntry(mob, this);
entry.Index = Entries.Count;
Entries.Add(entry);
}
return entry;
}
public LadderEntry FindNoCreate(Mobile mob)
{
m_Table.TryGetValue(mob, out LadderEntry entry);
return entry;
}
public void Serialize(IGenericWriter writer)
{
writer.WriteEncodedInt(1); // version;
writer.WriteEncodedInt(Entries.Count);
for (int i = 0; i < Entries.Count; ++i)
Entries[i].Serialize(writer);
}
}
public class LadderEntry : IComparable<LadderEntry>
{
private int m_Experience;
private readonly Ladder m_Ladder;
public LadderEntry(Mobile mob, Ladder ladder)
{
m_Ladder = ladder;
Mobile = mob;
}
public LadderEntry(IGenericReader reader, Ladder ladder, int version)
{
m_Ladder = ladder;
switch (version)
{
case 1:
case 0:
{
Mobile = reader.ReadMobile();
m_Experience = reader.ReadEncodedInt();
Wins = reader.ReadEncodedInt();
Losses = reader.ReadEncodedInt();
break;
}
}
}
public Mobile Mobile { get; }
[CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)]
public int Experience
{
get => m_Experience;
set
{
m_Experience = value;
m_Ladder.UpdateEntry(this);
}
}
[CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)]
public int Wins { get; set; }
[CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)]
public int Losses { get; set; }
public int Index { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int Rank => Index;
public int CompareTo(LadderEntry l) => (l?.m_Experience ?? 0) - m_Experience;
public void Serialize(IGenericWriter writer)
{
writer.Write(Mobile);
writer.WriteEncodedInt(m_Experience);
writer.WriteEncodedInt(Wins);
writer.WriteEncodedInt(Losses);
}
}
}
using System;
using System.Collections.Generic;
namespace Server.Engines.ConPVP
{
public class LadderController : Item
{
[Constructible]
public LadderController() : base(0x1B7A)
{
Visible = false;
Movable = false;
Ladder = new Ladder();
Ladder.Instance ??= Ladder;
}
public LadderController(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.Administrator)]
public Ladder Ladder { get; private set; }
public override string DefaultName => "ladder controller";
public override void Delete()
{
if (Ladder.Instance == Ladder)
Ladder.Instance = null;
base.Delete();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(1);
Ladder.Serialize(writer);
writer.Write(Ladder.Instance == Ladder);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 1:
case 0:
{
Ladder = new Ladder(reader);
if (version < 1 || reader.ReadBool())
Ladder.Instance = Ladder;
break;
}
}
}
}
public class Ladder
{
private static readonly int[] m_ShortLevels =
{
1,
2,
3, 3,
4, 4,
5, 5, 5,
6, 6, 6,
7, 7, 7, 7,
8, 8, 8, 8,
9, 9, 9, 9, 9
};
private static readonly int[] m_BaseXP =
{
0, 100, 200, 400, 600, 900, 1200, 1600, 2000, 2500
};
private static readonly int[] m_LossFactors =
{
10,
11, 11,
25, 25,
43, 43,
67, 67
};
private static readonly int[,] m_OffsetScalar =
{
/* { win, los } */
/* -6 */ { 175, 25 },
/* -5 */ { 165, 35 },
/* -4 */ { 155, 45 },
/* -3 */ { 145, 55 },
/* -2 */ { 130, 70 },
/* -1 */ { 115, 85 },
/* 0 */ { 100, 100 },
/* +1 */ { 90, 110 },
/* +2 */ { 80, 120 },
/* +3 */ { 70, 130 },
/* +4 */ { 60, 140 },
/* +5 */ { 50, 150 },
/* +6 */ { 40, 160 }
};
private readonly Dictionary<Mobile, LadderEntry> m_Table;
public Ladder() => m_Table = new Dictionary<Mobile, LadderEntry>();
public Ladder(IGenericReader reader)
{
var version = reader.ReadEncodedInt();
switch (version)
{
case 1:
case 0:
{
var count = reader.ReadEncodedInt();
m_Table = new Dictionary<Mobile, LadderEntry>(count);
Entries = new List<LadderEntry>(count);
for (var i = 0; i < count; ++i)
{
var entry = new LadderEntry(reader, this, version);
if (entry.Mobile != null)
{
m_Table[entry.Mobile] = entry;
entry.Index = Entries.Count;
Entries.Add(entry);
}
}
if (version == 0)
{
Entries.Sort();
for (var i = 0; i < Entries.Count; ++i)
{
var entry = Entries[i];
entry.Index = i;
}
}
break;
}
}
}
public List<LadderEntry> Entries { get; } = new List<LadderEntry>();
public static Ladder Instance { get; set; }
public static int GetLevel(int xp)
{
if (xp >= 22500)
return 50;
if (xp >= 2500)
return 10 + (xp - 2500) / 500;
return m_ShortLevels[Math.Max(xp, 0) / 100];
}
public static void GetLevelInfo(int level, out int xpBase, out int xpAdvance)
{
if (level >= 10)
{
xpBase = 2500 + (level - 10) * 500;
xpAdvance = 500;
}
else
{
xpBase = m_BaseXP[level - 1];
xpAdvance = m_BaseXP[level] - xpBase;
}
}
public static int GetLossFactor(int level)
{
if (level >= 10)
return 100;
return m_LossFactors[level - 1];
}
public static int GetOffsetScalar(int ourLevel, int theirLevel, bool win)
{
var x = ourLevel - theirLevel;
if (x < -6 || x > +6)
return 0;
var y = win ? 0 : 1;
return m_OffsetScalar[x + 6, y];
}
public static int GetExperienceGain(LadderEntry us, LadderEntry them, bool weWon)
{
if (us == null || them == null)
return 0;
var ourLevel = GetLevel(us.Experience);
var theirLevel = GetLevel(them.Experience);
var scalar = GetOffsetScalar(ourLevel, theirLevel, weWon);
if (scalar == 0)
return 0;
var xp = 25 * scalar;
if (!weWon)
xp = xp * GetLossFactor(ourLevel) / 100;
xp /= 100;
if (xp <= 0)
xp = 1;
return xp * (weWon ? 1 : -1);
}
private int Swap(int idx, int newIdx)
{
var hold = Entries[idx];
Entries[idx] = Entries[newIdx];
Entries[newIdx] = hold;
Entries[idx].Index = idx;
Entries[newIdx].Index = newIdx;
return newIdx;
}
public void UpdateEntry(LadderEntry entry)
{
var index = entry.Index;
if (index >= 0 && index < Entries.Count)
{
while (index - 1 >= 0 && entry.CompareTo(Entries[index - 1]) < 0)
index = Swap(index, index - 1);
while (index + 1 < Entries.Count && entry.CompareTo(Entries[index + 1]) > 0)
index = Swap(index, index + 1);
}
}
public LadderEntry Find(Mobile mob)
{
if (m_Table.TryGetValue(mob, out var entry))
{
m_Table[mob] = entry = new LadderEntry(mob, this);
entry.Index = Entries.Count;
Entries.Add(entry);
}
return entry;
}
public LadderEntry FindNoCreate(Mobile mob)
{
m_Table.TryGetValue(mob, out var entry);
return entry;
}
public void Serialize(IGenericWriter writer)
{
writer.WriteEncodedInt(1); // version;
writer.WriteEncodedInt(Entries.Count);
for (var i = 0; i < Entries.Count; ++i)
Entries[i].Serialize(writer);
}
}
public class LadderEntry : IComparable<LadderEntry>
{
private readonly Ladder m_Ladder;
private int m_Experience;
public LadderEntry(Mobile mob, Ladder ladder)
{
m_Ladder = ladder;
Mobile = mob;
}
public LadderEntry(IGenericReader reader, Ladder ladder, int version)
{
m_Ladder = ladder;
switch (version)
{
case 1:
case 0:
{
Mobile = reader.ReadMobile();
m_Experience = reader.ReadEncodedInt();
Wins = reader.ReadEncodedInt();
Losses = reader.ReadEncodedInt();
break;
}
}
}
public Mobile Mobile { get; }
[CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)]
public int Experience
{
get => m_Experience;
set
{
m_Experience = value;
m_Ladder.UpdateEntry(this);
}
}
[CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)]
public int Wins { get; set; }
[CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)]
public int Losses { get; set; }
public int Index { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int Rank => Index;
public int CompareTo(LadderEntry l) => (l?.m_Experience ?? 0) - m_Experience;
public void Serialize(IGenericWriter writer)
{
writer.Write(Mobile);
writer.WriteEncodedInt(m_Experience);
writer.WriteEncodedInt(Wins);
writer.WriteEncodedInt(Losses);
}
}
}

View file

@ -1,225 +1,233 @@
using System;
using System.Text;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class Participant
{
public Participant(DuelContext context, int count)
{
Context = context;
// m_Stakes = new StakesContainer( context, this );
Resize(count);
}
public int Count => Players.Length;
public DuelPlayer[] Players { get; private set; }
public DuelContext Context { get; }
public TourneyParticipant TourneyPart { get; set; }
public int FilledSlots
{
get
{
int count = 0;
for (int i = 0; i < Players.Length; ++i)
if (Players[i] != null)
++count;
return count;
}
}
public bool HasOpenSlot
{
get
{
for (int i = 0; i < Players.Length; ++i)
if (Players[i] == null)
return true;
return false;
}
}
public bool Eliminated
{
get
{
for (int i = 0; i < Players.Length; ++i)
if (Players[i]?.Eliminated == false)
return false;
return true;
}
}
public string NameList
{
get
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < Players.Length; ++i)
{
if (Players[i] == null)
continue;
Mobile mob = Players[i].Mobile;
if (sb.Length > 0)
sb.Append(", ");
sb.Append(mob.Name);
}
return sb.Length == 0 ? "Empty" : sb.ToString();
}
}
public DuelPlayer Find(Mobile mob)
{
if (mob is PlayerMobile pm)
{
if (pm.DuelContext == Context && pm.DuelPlayer.Participant == this)
return pm.DuelPlayer;
return null;
}
for (int i = 0; i < Players.Length; ++i)
if (Players[i]?.Mobile == mob)
return Players[i];
return null;
}
public bool Contains(Mobile mob) => Find(mob) != null;
public void Broadcast(int hue, string message, string nonLocalOverhead, string localOverhead)
{
for (int i = 0; i < Players.Length; ++i)
if (Players[i] != null)
{
if (message != null)
Players[i].Mobile.SendMessage(hue, message);
if (nonLocalOverhead != null)
Players[i].Mobile.NonlocalOverheadMessage(MessageType.Regular, hue, false,
string.Format(nonLocalOverhead, Players[i].Mobile.Name,
Players[i].Mobile.Female ? "her" : "his"));
if (localOverhead != null)
Players[i].Mobile.LocalOverheadMessage(MessageType.Regular, hue, false, localOverhead);
}
}
public void Nullify(DuelPlayer player)
{
if (player == null)
return;
int index = Array.IndexOf(Players, player);
if (index == -1)
return;
Players[index] = null;
}
public void Remove(DuelPlayer player)
{
if (player == null)
return;
int index = Array.IndexOf(Players, player);
if (index == -1)
return;
DuelPlayer[] old = Players;
Players = new DuelPlayer[old.Length - 1];
for (int i = 0; i < index; ++i)
Players[i] = old[i];
for (int i = index + 1; i < old.Length; ++i)
Players[i - 1] = old[i];
}
public void Remove(Mobile player)
{
Remove(Find(player));
}
public void Add(Mobile player)
{
if (Contains(player))
return;
for (int i = 0; i < Players.Length; ++i)
if (Players[i] == null)
{
Players[i] = new DuelPlayer(player, this);
return;
}
Resize(Players.Length + 1);
Players[^1] = new DuelPlayer(player, this);
}
public void Resize(int count)
{
DuelPlayer[] old = Players;
Players = new DuelPlayer[count];
if (old != null)
{
int ct = 0;
for (int i = 0; i < old.Length; ++i)
if (old[i] != null && ct < count)
Players[ct++] = old[i];
}
}
}
public class DuelPlayer
{
private bool m_Eliminated;
public DuelPlayer(Mobile mob, Participant p)
{
Mobile = mob;
Participant = p;
if (mob is PlayerMobile mobile)
mobile.DuelPlayer = this;
}
public Mobile Mobile { get; }
public bool Ready { get; set; }
public bool Eliminated
{
get => m_Eliminated;
set
{
m_Eliminated = value;
if (Participant.Context.m_Tournament != null && m_Eliminated)
{
Participant.Context.m_Tournament.OnEliminated(this);
Mobile.SendEverything();
}
}
}
public Participant Participant { get; set; }
}
}
using System;
using System.Text;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class Participant
{
public Participant(DuelContext context, int count)
{
Context = context;
// m_Stakes = new StakesContainer( context, this );
Resize(count);
}
public int Count => Players.Length;
public DuelPlayer[] Players { get; private set; }
public DuelContext Context { get; }
public TourneyParticipant TourneyPart { get; set; }
public int FilledSlots
{
get
{
var count = 0;
for (var i = 0; i < Players.Length; ++i)
if (Players[i] != null)
++count;
return count;
}
}
public bool HasOpenSlot
{
get
{
for (var i = 0; i < Players.Length; ++i)
if (Players[i] == null)
return true;
return false;
}
}
public bool Eliminated
{
get
{
for (var i = 0; i < Players.Length; ++i)
if (Players[i]?.Eliminated == false)
return false;
return true;
}
}
public string NameList
{
get
{
var sb = new StringBuilder();
for (var i = 0; i < Players.Length; ++i)
{
if (Players[i] == null)
continue;
var mob = Players[i].Mobile;
if (sb.Length > 0)
sb.Append(", ");
sb.Append(mob.Name);
}
return sb.Length == 0 ? "Empty" : sb.ToString();
}
}
public DuelPlayer Find(Mobile mob)
{
if (mob is PlayerMobile pm)
{
if (pm.DuelContext == Context && pm.DuelPlayer.Participant == this)
return pm.DuelPlayer;
return null;
}
for (var i = 0; i < Players.Length; ++i)
if (Players[i]?.Mobile == mob)
return Players[i];
return null;
}
public bool Contains(Mobile mob) => Find(mob) != null;
public void Broadcast(int hue, string message, string nonLocalOverhead, string localOverhead)
{
for (var i = 0; i < Players.Length; ++i)
if (Players[i] != null)
{
if (message != null)
Players[i].Mobile.SendMessage(hue, message);
if (nonLocalOverhead != null)
Players[i]
.Mobile.NonlocalOverheadMessage(
MessageType.Regular,
hue,
false,
string.Format(
nonLocalOverhead,
Players[i].Mobile.Name,
Players[i].Mobile.Female ? "her" : "his"
)
);
if (localOverhead != null)
Players[i].Mobile.LocalOverheadMessage(MessageType.Regular, hue, false, localOverhead);
}
}
public void Nullify(DuelPlayer player)
{
if (player == null)
return;
var index = Array.IndexOf(Players, player);
if (index == -1)
return;
Players[index] = null;
}
public void Remove(DuelPlayer player)
{
if (player == null)
return;
var index = Array.IndexOf(Players, player);
if (index == -1)
return;
var old = Players;
Players = new DuelPlayer[old.Length - 1];
for (var i = 0; i < index; ++i)
Players[i] = old[i];
for (var i = index + 1; i < old.Length; ++i)
Players[i - 1] = old[i];
}
public void Remove(Mobile player)
{
Remove(Find(player));
}
public void Add(Mobile player)
{
if (Contains(player))
return;
for (var i = 0; i < Players.Length; ++i)
if (Players[i] == null)
{
Players[i] = new DuelPlayer(player, this);
return;
}
Resize(Players.Length + 1);
Players[^1] = new DuelPlayer(player, this);
}
public void Resize(int count)
{
var old = Players;
Players = new DuelPlayer[count];
if (old != null)
{
var ct = 0;
for (var i = 0; i < old.Length; ++i)
if (old[i] != null && ct < count)
Players[ct++] = old[i];
}
}
}
public class DuelPlayer
{
private bool m_Eliminated;
public DuelPlayer(Mobile mob, Participant p)
{
Mobile = mob;
Participant = p;
if (mob is PlayerMobile mobile)
mobile.DuelPlayer = this;
}
public Mobile Mobile { get; }
public bool Ready { get; set; }
public bool Eliminated
{
get => m_Eliminated;
set
{
m_Eliminated = value;
if (Participant.Context.m_Tournament != null && m_Eliminated)
{
Participant.Context.m_Tournament.OnEliminated(this);
Mobile.SendEverything();
}
}
}
public Participant Participant { get; set; }
}
}

View file

@ -1,271 +1,271 @@
using System.Collections.Generic;
using Server.Gumps;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class PreferencesController : Item
{
[Constructible]
public PreferencesController() : base(0x1B7A)
{
Visible = false;
Movable = false;
Preferences = new Preferences();
if (Preferences.Instance == null)
Preferences.Instance = Preferences;
else
Delete();
}
public PreferencesController(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.Administrator)]
public Preferences Preferences { get; private set; }
public override string DefaultName => "preferences controller";
public override void Delete()
{
if (Preferences.Instance != Preferences)
base.Delete();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
Preferences.Serialize(writer);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
Preferences = new Preferences(reader);
Preferences.Instance = Preferences;
break;
}
}
}
}
public class Preferences
{
private readonly Dictionary<Mobile, PreferencesEntry> m_Table;
public Preferences()
{
m_Table = new Dictionary<Mobile, PreferencesEntry>();
Entries = new List<PreferencesEntry>();
}
public Preferences(IGenericReader reader)
{
int version = reader.ReadEncodedInt();
switch (version)
{
case 0:
{
int count = reader.ReadEncodedInt();
m_Table = new Dictionary<Mobile, PreferencesEntry>(count);
Entries = new List<PreferencesEntry>(count);
for (int i = 0; i < count; ++i)
{
PreferencesEntry entry = new PreferencesEntry(reader, version);
if (entry.Mobile != null)
{
m_Table[entry.Mobile] = entry;
Entries.Add(entry);
}
}
break;
}
}
}
public List<PreferencesEntry> Entries { get; }
public static Preferences Instance { get; set; }
public PreferencesEntry Find(Mobile mob)
{
if (m_Table.TryGetValue(mob, out PreferencesEntry entry))
{
m_Table[mob] = entry = new PreferencesEntry(mob);
Entries.Add(entry);
}
return entry;
}
public void Serialize(IGenericWriter writer)
{
writer.WriteEncodedInt(0); // version;
writer.WriteEncodedInt(Entries.Count);
for (int i = 0; i < Entries.Count; ++i)
Entries[i].Serialize(writer);
}
}
public class PreferencesEntry
{
public PreferencesEntry(Mobile mob)
{
Mobile = mob;
Disliked = new List<string>();
}
public PreferencesEntry(IGenericReader reader, int version)
{
switch (version)
{
case 0:
{
Mobile = reader.ReadMobile();
int count = reader.ReadEncodedInt();
Disliked = new List<string>(count);
for (int i = 0; i < count; ++i)
Disliked.Add(reader.ReadString());
break;
}
}
}
public Mobile Mobile { get; }
public List<string> Disliked { get; }
public void Serialize(IGenericWriter writer)
{
writer.Write(Mobile);
writer.WriteEncodedInt(Disliked.Count);
for (int i = 0; i < Disliked.Count; ++i)
writer.Write(Disliked[i]);
}
}
public class PreferencesGump : Gump
{
private int m_ColumnX = 12;
private readonly PreferencesEntry m_Entry;
public PreferencesGump(Mobile from, Preferences prefs) : base(50, 50)
{
m_Entry = prefs.Find(from);
if (m_Entry == null)
return;
List<Arena> arenas = Arena.Arenas;
AddPage(0);
int height = 12 + 20 + arenas.Count * 31 + 24 + 12;
AddBackground(0, 0, 499 + 40 - 365, height, 0x2436);
for (int i = 1; i < arenas.Count; i += 2)
AddImageTiled(12, 32 + i * 31, 475 + 40 - 365, 30, 0x2430);
AddAlphaRegion(10, 10, 479 + 40 - 365, height - 20);
AddColumnHeader(35, null);
AddColumnHeader(115, "Arena");
AddButton(499 + 40 - 365 - 12 - 63 - 4 - 63, height - 12 - 24, 247, 248, 1);
AddButton(499 + 40 - 365 - 12 - 63, height - 12 - 24, 241, 242, 2);
for (int i = 0; i < arenas.Count; ++i)
{
Arena ar = arenas[i];
string name = ar.Name ?? "(no name)";
int x = 12;
int y = 32 + i * 31;
int color = 0xCCFFCC;
AddCheck(x + 3, y + 1, 9730, 9727, m_Entry.Disliked.Contains(name), i);
x += 35;
AddBorderedText(x + 5, y + 5, 115 - 5, name, color, 0);
}
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (m_Entry == null)
return;
if (info.ButtonID != 1)
return;
m_Entry.Disliked.Clear();
List<Arena> arenas = Arena.Arenas;
for (int i = 0; i < info.Switches.Length; ++i)
{
int idx = info.Switches[i];
if (idx >= 0 && idx < arenas.Count)
m_Entry.Disliked.Add(arenas[idx].Name);
}
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public string Color(string text, int color) => $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
private void AddBorderedText(int x, int y, int width, string text, int color, int borderColor)
{
AddColoredText(x, y, width, text, color);
}
private void AddColoredText(int x, int y, int width, string text, int color)
{
if (color == 0)
AddHtml(x, y, width, 20, text);
else
AddHtml(x, y, width, 20, Color(text, color));
}
private void AddColumnHeader(int width, string name)
{
AddBackground(m_ColumnX, 12, width, 20, 0x242C);
AddImageTiled(m_ColumnX + 2, 14, width - 4, 16, 0x2430);
if (name != null)
AddBorderedText(m_ColumnX, 13, width, Center(name), 0xFFFFFF, 0);
m_ColumnX += width;
}
}
}
using System.Collections.Generic;
using Server.Gumps;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class PreferencesController : Item
{
[Constructible]
public PreferencesController() : base(0x1B7A)
{
Visible = false;
Movable = false;
Preferences = new Preferences();
if (Preferences.Instance == null)
Preferences.Instance = Preferences;
else
Delete();
}
public PreferencesController(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.Administrator)]
public Preferences Preferences { get; private set; }
public override string DefaultName => "preferences controller";
public override void Delete()
{
if (Preferences.Instance != Preferences)
base.Delete();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
Preferences.Serialize(writer);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Preferences = new Preferences(reader);
Preferences.Instance = Preferences;
break;
}
}
}
}
public class Preferences
{
private readonly Dictionary<Mobile, PreferencesEntry> m_Table;
public Preferences()
{
m_Table = new Dictionary<Mobile, PreferencesEntry>();
Entries = new List<PreferencesEntry>();
}
public Preferences(IGenericReader reader)
{
var version = reader.ReadEncodedInt();
switch (version)
{
case 0:
{
var count = reader.ReadEncodedInt();
m_Table = new Dictionary<Mobile, PreferencesEntry>(count);
Entries = new List<PreferencesEntry>(count);
for (var i = 0; i < count; ++i)
{
var entry = new PreferencesEntry(reader, version);
if (entry.Mobile != null)
{
m_Table[entry.Mobile] = entry;
Entries.Add(entry);
}
}
break;
}
}
}
public List<PreferencesEntry> Entries { get; }
public static Preferences Instance { get; set; }
public PreferencesEntry Find(Mobile mob)
{
if (m_Table.TryGetValue(mob, out var entry))
{
m_Table[mob] = entry = new PreferencesEntry(mob);
Entries.Add(entry);
}
return entry;
}
public void Serialize(IGenericWriter writer)
{
writer.WriteEncodedInt(0); // version;
writer.WriteEncodedInt(Entries.Count);
for (var i = 0; i < Entries.Count; ++i)
Entries[i].Serialize(writer);
}
}
public class PreferencesEntry
{
public PreferencesEntry(Mobile mob)
{
Mobile = mob;
Disliked = new List<string>();
}
public PreferencesEntry(IGenericReader reader, int version)
{
switch (version)
{
case 0:
{
Mobile = reader.ReadMobile();
var count = reader.ReadEncodedInt();
Disliked = new List<string>(count);
for (var i = 0; i < count; ++i)
Disliked.Add(reader.ReadString());
break;
}
}
}
public Mobile Mobile { get; }
public List<string> Disliked { get; }
public void Serialize(IGenericWriter writer)
{
writer.Write(Mobile);
writer.WriteEncodedInt(Disliked.Count);
for (var i = 0; i < Disliked.Count; ++i)
writer.Write(Disliked[i]);
}
}
public class PreferencesGump : Gump
{
private readonly PreferencesEntry m_Entry;
private int m_ColumnX = 12;
public PreferencesGump(Mobile from, Preferences prefs) : base(50, 50)
{
m_Entry = prefs.Find(from);
if (m_Entry == null)
return;
var arenas = Arena.Arenas;
AddPage(0);
var height = 12 + 20 + arenas.Count * 31 + 24 + 12;
AddBackground(0, 0, 499 + 40 - 365, height, 0x2436);
for (var i = 1; i < arenas.Count; i += 2)
AddImageTiled(12, 32 + i * 31, 475 + 40 - 365, 30, 0x2430);
AddAlphaRegion(10, 10, 479 + 40 - 365, height - 20);
AddColumnHeader(35, null);
AddColumnHeader(115, "Arena");
AddButton(499 + 40 - 365 - 12 - 63 - 4 - 63, height - 12 - 24, 247, 248, 1);
AddButton(499 + 40 - 365 - 12 - 63, height - 12 - 24, 241, 242, 2);
for (var i = 0; i < arenas.Count; ++i)
{
var ar = arenas[i];
var name = ar.Name ?? "(no name)";
var x = 12;
var y = 32 + i * 31;
var color = 0xCCFFCC;
AddCheck(x + 3, y + 1, 9730, 9727, m_Entry.Disliked.Contains(name), i);
x += 35;
AddBorderedText(x + 5, y + 5, 115 - 5, name, color, 0);
}
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (m_Entry == null)
return;
if (info.ButtonID != 1)
return;
m_Entry.Disliked.Clear();
var arenas = Arena.Arenas;
for (var i = 0; i < info.Switches.Length; ++i)
{
var idx = info.Switches[i];
if (idx >= 0 && idx < arenas.Count)
m_Entry.Disliked.Add(arenas[idx].Name);
}
}
public string Center(string text) => $"<CENTER>{text}</CENTER>";
public string Color(string text, int color) => $"<BASEFONT COLOR=#{color:X6}>{text}</BASEFONT>";
private void AddBorderedText(int x, int y, int width, string text, int color, int borderColor)
{
AddColoredText(x, y, width, text, color);
}
private void AddColoredText(int x, int y, int width, string text, int color)
{
if (color == 0)
AddHtml(x, y, width, 20, text);
else
AddHtml(x, y, width, 20, Color(text, color));
}
private void AddColumnHeader(int width, string name)
{
AddBackground(m_ColumnX, 12, width, 20, 0x242C);
AddImageTiled(m_ColumnX + 2, 14, width - 4, 16, 0x2430);
if (name != null)
AddBorderedText(m_ColumnX, 13, width, Center(name), 0xFFFFFF, 0);
m_ColumnX += width;
}
}
}

View file

@ -1,102 +1,102 @@
using System.Collections;
using System.Collections.Generic;
namespace Server.Engines.ConPVP
{
public class Ruleset
{
public Ruleset(RulesetLayout layout)
{
Layout = layout;
Options = new BitArray(layout.TotalLength);
}
public RulesetLayout Layout { get; }
public BitArray Options { get; private set; }
public string Title { get; set; }
public Ruleset Base { get; private set; }
public List<Ruleset> Flavors { get; } = new List<Ruleset>();
public bool Changed { get; set; }
public void ApplyDefault(Ruleset newDefault)
{
Base = newDefault;
Changed = false;
Options = new BitArray(newDefault.Options);
ApplyFlavorsTo(this);
}
public void ApplyFlavorsTo(Ruleset ruleset)
{
for (int i = 0; i < Flavors.Count; ++i)
{
Ruleset flavor = Flavors[i];
Options.Or(flavor.Options);
}
}
public void AddFlavor(Ruleset flavor)
{
if (Flavors.Contains(flavor))
return;
Flavors.Add(flavor);
Options.Or(flavor.Options);
}
public void RemoveFlavor(Ruleset flavor)
{
if (!Flavors.Contains(flavor))
return;
Flavors.Remove(flavor);
Options.And(flavor.Options.Not());
flavor.Options.Not();
}
public void SetOptionRange(string title, bool value)
{
RulesetLayout layout = Layout.FindByTitle(title);
if (layout == null)
return;
for (int i = 0; i < layout.TotalLength; ++i)
Options[i + layout.Offset] = value;
Changed = true;
}
public bool GetOption(string title, string option)
{
int index = 0;
RulesetLayout layout = Layout.FindByOption(title, option, ref index);
if (layout == null)
return true;
return Options[layout.Offset + index];
}
public void SetOption(string title, string option, bool value)
{
int index = 0;
RulesetLayout layout = Layout.FindByOption(title, option, ref index);
if (layout == null)
return;
Options[layout.Offset + index] = value;
Changed = true;
}
}
}
using System.Collections;
using System.Collections.Generic;
namespace Server.Engines.ConPVP
{
public class Ruleset
{
public Ruleset(RulesetLayout layout)
{
Layout = layout;
Options = new BitArray(layout.TotalLength);
}
public RulesetLayout Layout { get; }
public BitArray Options { get; private set; }
public string Title { get; set; }
public Ruleset Base { get; private set; }
public List<Ruleset> Flavors { get; } = new List<Ruleset>();
public bool Changed { get; set; }
public void ApplyDefault(Ruleset newDefault)
{
Base = newDefault;
Changed = false;
Options = new BitArray(newDefault.Options);
ApplyFlavorsTo(this);
}
public void ApplyFlavorsTo(Ruleset ruleset)
{
for (var i = 0; i < Flavors.Count; ++i)
{
var flavor = Flavors[i];
Options.Or(flavor.Options);
}
}
public void AddFlavor(Ruleset flavor)
{
if (Flavors.Contains(flavor))
return;
Flavors.Add(flavor);
Options.Or(flavor.Options);
}
public void RemoveFlavor(Ruleset flavor)
{
if (!Flavors.Contains(flavor))
return;
Flavors.Remove(flavor);
Options.And(flavor.Options.Not());
flavor.Options.Not();
}
public void SetOptionRange(string title, bool value)
{
var layout = Layout.FindByTitle(title);
if (layout == null)
return;
for (var i = 0; i < layout.TotalLength; ++i)
Options[i + layout.Offset] = value;
Changed = true;
}
public bool GetOption(string title, string option)
{
var index = 0;
var layout = Layout.FindByOption(title, option, ref index);
if (layout == null)
return true;
return Options[layout.Offset + index];
}
public void SetOption(string title, string option, bool value)
{
var index = 0;
var layout = Layout.FindByOption(title, option, ref index);
if (layout == null)
return;
Options[layout.Offset + index] = value;
Changed = true;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,60 +1,60 @@
using Server.Factions;
using Server.Mobiles;
using Server.Regions;
namespace Server.Engines.ConPVP
{
public class SafeZone : GuardedRegion
{
public static readonly int SafeZonePriority = HouseRegion.HousePriority + 1;
/*public override bool AllowReds => true;*/
public SafeZone(Rectangle2D area, Point3D goloc, Map map, bool isGuarded) : base(null, map, SafeZonePriority, area)
{
GoLocation = goloc;
Disabled = !isGuarded;
Register();
}
public override bool AllowHousing(Mobile from, Point3D p) => from.AccessLevel >= AccessLevel.GameMaster && base.AllowHousing(from, p);
public override bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation)
{
if (m.Player && Sigil.ExistsOn(m))
{
m.SendMessage(0x22, "You are holding a sigil and cannot enter this zone.");
return false;
}
PlayerMobile pm = m as PlayerMobile ??
(m is BaseCreature bc && bc.Summoned ?
bc.SummonMaster as PlayerMobile : null);
if (pm?.DuelContext?.StartedBeginCountdown == true)
return true;
if (DuelContext.CheckCombat(m))
{
m.SendMessage(0x22, "You have recently been in combat and cannot enter this zone.");
return false;
}
return base.OnMoveInto(m, d, newLocation, oldLocation);
}
public override void OnEnter(Mobile m)
{
m.SendMessage("You have entered a dueling safezone. No combat other than duels are allowed in this zone.");
}
public override void OnExit(Mobile m)
{
m.SendMessage("You have left a dueling safezone. Combat is now unrestricted.");
}
public override bool CanUseStuckMenu(Mobile m) => false;
}
}
using Server.Factions;
using Server.Mobiles;
using Server.Regions;
namespace Server.Engines.ConPVP
{
public class SafeZone : GuardedRegion
{
public static readonly int SafeZonePriority = HouseRegion.HousePriority + 1;
/*public override bool AllowReds => true;*/
public SafeZone(Rectangle2D area, Point3D goloc, Map map, bool isGuarded) : base(null, map, SafeZonePriority, area)
{
GoLocation = goloc;
Disabled = !isGuarded;
Register();
}
public override bool AllowHousing(Mobile from, Point3D p) =>
from.AccessLevel >= AccessLevel.GameMaster && base.AllowHousing(from, p);
public override bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation)
{
if (m.Player && Sigil.ExistsOn(m))
{
m.SendMessage(0x22, "You are holding a sigil and cannot enter this zone.");
return false;
}
var pm = m as PlayerMobile ??
(m is BaseCreature bc && bc.Summoned ? bc.SummonMaster as PlayerMobile : null);
if (pm?.DuelContext?.StartedBeginCountdown == true)
return true;
if (DuelContext.CheckCombat(m))
{
m.SendMessage(0x22, "You have recently been in combat and cannot enter this zone.");
return false;
}
return base.OnMoveInto(m, d, newLocation, oldLocation);
}
public override void OnEnter(Mobile m)
{
m.SendMessage("You have entered a dueling safezone. No combat other than duels are allowed in this zone.");
}
public override void OnExit(Mobile m)
{
m.SendMessage("You have left a dueling safezone. Combat is now unrestricted.");
}
public override bool CanUseStuckMenu(Mobile m) => false;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,62 +1,62 @@
using Server.Network;
namespace Server.Engines.ConPVP
{
public class TournamentBracketItem : Item
{
[Constructible]
public TournamentBracketItem() : base(3774) => Movable = false;
public TournamentBracketItem(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public TournamentController Tournament { get; set; }
public override string DefaultName => "tournament bracket";
public override void OnDoubleClick(Mobile from)
{
if (!from.InRange(GetWorldLocation(), 2))
{
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that
}
else
{
Tournament tourney = Tournament?.Tournament;
if (tourney != null)
{
from.CloseGump<TournamentBracketGump>();
from.SendGump(new TournamentBracketGump(from, tourney, TourneyBracketGumpType.Index));
}
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(Tournament);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
Tournament = reader.ReadItem() as TournamentController;
break;
}
}
}
}
}
using Server.Network;
namespace Server.Engines.ConPVP
{
public class TournamentBracketItem : Item
{
[Constructible]
public TournamentBracketItem() : base(3774) => Movable = false;
public TournamentBracketItem(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public TournamentController Tournament { get; set; }
public override string DefaultName => "tournament bracket";
public override void OnDoubleClick(Mobile from)
{
if (!from.InRange(GetWorldLocation(), 2))
{
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that
}
else
{
var tourney = Tournament?.Tournament;
if (tourney != null)
{
from.CloseGump<TournamentBracketGump>();
from.SendGump(new TournamentBracketGump(from, tourney, TourneyBracketGumpType.Index));
}
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(Tournament);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Tournament = reader.ReadItem() as TournamentController;
break;
}
}
}
}
}

View file

@ -1,137 +1,139 @@
using System;
using System.Collections.Generic;
using Server.ContextMenus;
using Server.Gumps;
namespace Server.Engines.ConPVP
{
public class TournamentController : Item
{
private static readonly List<TournamentController> m_Instances = new List<TournamentController>();
[Constructible]
public TournamentController() : base(0x1B7A)
{
Visible = false;
Movable = false;
Tournament = new Tournament();
m_Instances.Add(this);
}
public TournamentController(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public Tournament Tournament { get; private set; }
public static bool IsActive
{
get
{
for (int i = 0; i < m_Instances.Count; ++i)
{
TournamentController controller = m_Instances[i];
if (controller?.Deleted == false && controller.Tournament != null &&
controller.Tournament.Stage != TournamentStage.Inactive)
return true;
}
return false;
}
}
public override string DefaultName => "tournament controller";
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
if (from.AccessLevel >= AccessLevel.GameMaster && Tournament != null)
{
list.Add(new EditEntry(Tournament));
if (Tournament.CurrentStage == TournamentStage.Inactive)
list.Add(new StartEntry(Tournament));
}
}
public override void OnDoubleClick(Mobile from)
{
if (from.AccessLevel >= AccessLevel.GameMaster && Tournament != null)
{
from.CloseGump<PickRulesetGump>();
from.CloseGump<RulesetGump>();
from.SendGump(new PickRulesetGump(from, null, Tournament.Ruleset));
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
Tournament.Serialize(writer);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
Tournament = new Tournament(reader);
break;
}
}
m_Instances.Add(this);
}
public override void OnDelete()
{
base.OnDelete();
m_Instances.Remove(this);
}
private class EditEntry : ContextMenuEntry
{
private readonly Tournament m_Tournament;
public EditEntry(Tournament tourney) : base(5101) => m_Tournament = tourney;
public override void OnClick()
{
Owner.From.SendGump(new PropertiesGump(Owner.From, m_Tournament));
}
}
private class StartEntry : ContextMenuEntry
{
private readonly Tournament m_Tournament;
public StartEntry(Tournament tourney) : base(5113) => m_Tournament = tourney;
public override void OnClick()
{
if (m_Tournament.Stage == TournamentStage.Inactive)
{
m_Tournament.SignupStart = DateTime.UtcNow;
m_Tournament.Stage = TournamentStage.Signup;
m_Tournament.Participants.Clear();
m_Tournament.Pyramid.Levels.Clear();
m_Tournament.Alert("Hear ye! Hear ye!",
"Tournament signup has opened. You can enter by signing up with the registrar.");
}
}
}
}
}
using System;
using System.Collections.Generic;
using Server.ContextMenus;
using Server.Gumps;
namespace Server.Engines.ConPVP
{
public class TournamentController : Item
{
private static readonly List<TournamentController> m_Instances = new List<TournamentController>();
[Constructible]
public TournamentController() : base(0x1B7A)
{
Visible = false;
Movable = false;
Tournament = new Tournament();
m_Instances.Add(this);
}
public TournamentController(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public Tournament Tournament { get; private set; }
public static bool IsActive
{
get
{
for (var i = 0; i < m_Instances.Count; ++i)
{
var controller = m_Instances[i];
if (controller?.Deleted == false && controller.Tournament != null &&
controller.Tournament.Stage != TournamentStage.Inactive)
return true;
}
return false;
}
}
public override string DefaultName => "tournament controller";
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
if (from.AccessLevel >= AccessLevel.GameMaster && Tournament != null)
{
list.Add(new EditEntry(Tournament));
if (Tournament.CurrentStage == TournamentStage.Inactive)
list.Add(new StartEntry(Tournament));
}
}
public override void OnDoubleClick(Mobile from)
{
if (from.AccessLevel >= AccessLevel.GameMaster && Tournament != null)
{
from.CloseGump<PickRulesetGump>();
from.CloseGump<RulesetGump>();
from.SendGump(new PickRulesetGump(from, null, Tournament.Ruleset));
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
Tournament.Serialize(writer);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Tournament = new Tournament(reader);
break;
}
}
m_Instances.Add(this);
}
public override void OnDelete()
{
base.OnDelete();
m_Instances.Remove(this);
}
private class EditEntry : ContextMenuEntry
{
private readonly Tournament m_Tournament;
public EditEntry(Tournament tourney) : base(5101) => m_Tournament = tourney;
public override void OnClick()
{
Owner.From.SendGump(new PropertiesGump(Owner.From, m_Tournament));
}
}
private class StartEntry : ContextMenuEntry
{
private readonly Tournament m_Tournament;
public StartEntry(Tournament tourney) : base(5113) => m_Tournament = tourney;
public override void OnClick()
{
if (m_Tournament.Stage == TournamentStage.Inactive)
{
m_Tournament.SignupStart = DateTime.UtcNow;
m_Tournament.Stage = TournamentStage.Signup;
m_Tournament.Participants.Clear();
m_Tournament.Pyramid.Levels.Clear();
m_Tournament.Alert(
"Hear ye! Hear ye!",
"Tournament signup has opened. You can enter by signing up with the registrar."
);
}
}
}
}
}

View file

@ -1,180 +1,183 @@
using System.Collections.Generic;
using Server.Ethics;
using Server.Factions;
namespace Server.Engines.ConPVP
{
public class TourneyPyramid
{
public TourneyPyramid() => Levels = new List<PyramidLevel>();
public List<PyramidLevel> Levels { get; set; }
public void AddLevel(int partsPerMatch, List<TourneyParticipant> participants, GroupingType groupType, TourneyType tourneyType)
{
List<TourneyParticipant> copy = new List<TourneyParticipant>(participants);
if (groupType == GroupingType.Nearest || groupType == GroupingType.HighVsLow)
copy.Sort();
PyramidLevel level = new PyramidLevel();
switch (tourneyType)
{
case TourneyType.RedVsBlue:
{
TourneyParticipant[] parts = new TourneyParticipant[2];
for (int i = 0; i < parts.Length; ++i)
parts[i] = new TourneyParticipant(new List<Mobile>());
for (int i = 0; i < copy.Count; ++i)
{
List<Mobile> players = copy[i].Players;
for (int j = 0; j < players.Count; ++j)
{
Mobile mob = players[j];
if (mob.Kills >= 5)
parts[0].Players.Add(mob);
else
parts[1].Players.Add(mob);
}
}
level.Matches.Add(new TourneyMatch(new List<TourneyParticipant>(parts)));
break;
}
case TourneyType.Faction:
{
TourneyParticipant[] parts = new TourneyParticipant[partsPerMatch];
for (int i = 0; i < parts.Length; ++i)
parts[i] = new TourneyParticipant(new List<Mobile>());
for (int i = 0; i < copy.Count; ++i)
{
List<Mobile> players = copy[i].Players;
for (int j = 0; j < players.Count; ++j)
{
Mobile mob = players[j];
int index = -1;
if (partsPerMatch == 4)
{
Faction fac = Faction.Find(mob);
if (fac != null)
index = fac.Definition.Sort;
}
else if (partsPerMatch == 2)
{
if (Ethic.Evil.IsEligible(mob))
index = 0;
else if (Ethic.Hero.IsEligible(mob)) index = 1;
}
if (index < 0 || index >= partsPerMatch) index = i % partsPerMatch;
parts[index].Players.Add(mob);
}
}
level.Matches.Add(new TourneyMatch(new List<TourneyParticipant>(parts)));
break;
}
case TourneyType.RandomTeam:
{
TourneyParticipant[] parts = new TourneyParticipant[partsPerMatch];
for (int i = 0; i < partsPerMatch; ++i)
parts[i] = new TourneyParticipant(new List<Mobile>());
for (int i = 0; i < copy.Count; ++i)
parts[i % parts.Length].Players.AddRange(copy[i].Players);
level.Matches.Add(new TourneyMatch(new List<TourneyParticipant>(parts)));
break;
}
case TourneyType.FreeForAll:
{
level.Matches.Add(new TourneyMatch(copy));
break;
}
case TourneyType.Standard:
{
if (partsPerMatch >= 2 && participants.Count % partsPerMatch == 1)
{
int lowAdvances = int.MaxValue;
for (int i = 0; i < participants.Count; ++i)
{
TourneyParticipant p = participants[i];
if (p.FreeAdvances < lowAdvances)
lowAdvances = p.FreeAdvances;
}
List<TourneyParticipant> toAdvance = new List<TourneyParticipant>();
for (int i = 0; i < participants.Count; ++i)
{
TourneyParticipant p = participants[i];
if (p.FreeAdvances == lowAdvances)
toAdvance.Add(p);
}
if (toAdvance.Count == 0)
toAdvance = copy; // sanity
var random = toAdvance.RandomElement();
random.AddLog(
"Advanced automatically due to an odd number of challengers.");
level.FreeAdvance = random;
++level.FreeAdvance.FreeAdvances;
copy.Remove(random);
}
while (copy.Count >= partsPerMatch)
{
List<TourneyParticipant> thisMatch = new List<TourneyParticipant>();
for (int i = 0; i < partsPerMatch; ++i)
{
var idx = groupType switch
{
GroupingType.HighVsLow => i * (copy.Count - 1) / (partsPerMatch - 1),
GroupingType.Nearest => 0,
GroupingType.Random => Utility.Random(copy.Count),
_ => 0
};
thisMatch.Add(copy[idx]);
copy.RemoveAt(idx);
}
level.Matches.Add(new TourneyMatch(thisMatch));
}
if (copy.Count > 1)
level.Matches.Add(new TourneyMatch(copy));
break;
}
}
Levels.Add(level);
}
}
public class PyramidLevel
{
public List<TourneyMatch> Matches { get; set; } = new List<TourneyMatch>();
public TourneyParticipant FreeAdvance { get; set; }
}
}
using System.Collections.Generic;
using Server.Ethics;
using Server.Factions;
namespace Server.Engines.ConPVP
{
public class TourneyPyramid
{
public TourneyPyramid() => Levels = new List<PyramidLevel>();
public List<PyramidLevel> Levels { get; set; }
public void AddLevel(
int partsPerMatch, List<TourneyParticipant> participants, GroupingType groupType, TourneyType tourneyType
)
{
var copy = new List<TourneyParticipant>(participants);
if (groupType == GroupingType.Nearest || groupType == GroupingType.HighVsLow)
copy.Sort();
var level = new PyramidLevel();
switch (tourneyType)
{
case TourneyType.RedVsBlue:
{
var parts = new TourneyParticipant[2];
for (var i = 0; i < parts.Length; ++i)
parts[i] = new TourneyParticipant(new List<Mobile>());
for (var i = 0; i < copy.Count; ++i)
{
var players = copy[i].Players;
for (var j = 0; j < players.Count; ++j)
{
var mob = players[j];
if (mob.Kills >= 5)
parts[0].Players.Add(mob);
else
parts[1].Players.Add(mob);
}
}
level.Matches.Add(new TourneyMatch(new List<TourneyParticipant>(parts)));
break;
}
case TourneyType.Faction:
{
var parts = new TourneyParticipant[partsPerMatch];
for (var i = 0; i < parts.Length; ++i)
parts[i] = new TourneyParticipant(new List<Mobile>());
for (var i = 0; i < copy.Count; ++i)
{
var players = copy[i].Players;
for (var j = 0; j < players.Count; ++j)
{
var mob = players[j];
var index = -1;
if (partsPerMatch == 4)
{
var fac = Faction.Find(mob);
if (fac != null)
index = fac.Definition.Sort;
}
else if (partsPerMatch == 2)
{
if (Ethic.Evil.IsEligible(mob))
index = 0;
else if (Ethic.Hero.IsEligible(mob)) index = 1;
}
if (index < 0 || index >= partsPerMatch) index = i % partsPerMatch;
parts[index].Players.Add(mob);
}
}
level.Matches.Add(new TourneyMatch(new List<TourneyParticipant>(parts)));
break;
}
case TourneyType.RandomTeam:
{
var parts = new TourneyParticipant[partsPerMatch];
for (var i = 0; i < partsPerMatch; ++i)
parts[i] = new TourneyParticipant(new List<Mobile>());
for (var i = 0; i < copy.Count; ++i)
parts[i % parts.Length].Players.AddRange(copy[i].Players);
level.Matches.Add(new TourneyMatch(new List<TourneyParticipant>(parts)));
break;
}
case TourneyType.FreeForAll:
{
level.Matches.Add(new TourneyMatch(copy));
break;
}
case TourneyType.Standard:
{
if (partsPerMatch >= 2 && participants.Count % partsPerMatch == 1)
{
var lowAdvances = int.MaxValue;
for (var i = 0; i < participants.Count; ++i)
{
var p = participants[i];
if (p.FreeAdvances < lowAdvances)
lowAdvances = p.FreeAdvances;
}
var toAdvance = new List<TourneyParticipant>();
for (var i = 0; i < participants.Count; ++i)
{
var p = participants[i];
if (p.FreeAdvances == lowAdvances)
toAdvance.Add(p);
}
if (toAdvance.Count == 0)
toAdvance = copy; // sanity
var random = toAdvance.RandomElement();
random.AddLog(
"Advanced automatically due to an odd number of challengers."
);
level.FreeAdvance = random;
++level.FreeAdvance.FreeAdvances;
copy.Remove(random);
}
while (copy.Count >= partsPerMatch)
{
var thisMatch = new List<TourneyParticipant>();
for (var i = 0; i < partsPerMatch; ++i)
{
var idx = groupType switch
{
GroupingType.HighVsLow => i * (copy.Count - 1) / (partsPerMatch - 1),
GroupingType.Nearest => 0,
GroupingType.Random => Utility.Random(copy.Count),
_ => 0
};
thisMatch.Add(copy[idx]);
copy.RemoveAt(idx);
}
level.Matches.Add(new TourneyMatch(thisMatch));
}
if (copy.Count > 1)
level.Matches.Add(new TourneyMatch(copy));
break;
}
}
Levels.Add(level);
}
}
public class PyramidLevel
{
public List<TourneyMatch> Matches { get; set; } = new List<TourneyMatch>();
public TourneyParticipant FreeAdvance { get; set; }
}
}

View file

@ -1,93 +1,101 @@
using System;
using Server.Factions;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class TournamentRegistrar : Banker
{
[Constructible]
public TournamentRegistrar()
{
Timer.DelayCall(TimeSpan.FromSeconds(30.0), TimeSpan.FromSeconds(30.0), Announce_Callback);
}
public TournamentRegistrar(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public TournamentController Tournament { get; set; }
private void Announce_Callback()
{
Tournament tourney = Tournament?.Tournament;
if (tourney?.Stage == TournamentStage.Signup)
PublicOverheadMessage(MessageType.Regular, 0x35, false,
"Come one, come all! Do you aspire to be a fighter of great renown? Join this tournament and show the world your abilities.");
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
base.OnMovement(m, oldLocation);
Tournament tourney = Tournament?.Tournament;
if (InRange(m, 4) && !InRange(oldLocation, 4) && tourney != null && tourney.Stage == TournamentStage.Signup &&
m.CanBeginAction(this))
{
Ladder ladder = Ladder.Instance;
LadderEntry entry = ladder?.Find(m);
if (entry != null && Ladder.GetLevel(entry.Experience) < tourney.LevelRequirement)
return;
if (tourney.IsFactionRestricted && Faction.Find(m) == null) return;
if (tourney.HasParticipant(m))
return;
PrivateOverheadMessage(MessageType.Regular, 0x35, false,
$"Hello m'{(m.Female ? "Lady" : "Lord")}. Dost thou wish to enter this tournament? You need only to write your name in this book.",
m.NetState);
m.BeginAction(this);
Timer.DelayCall(TimeSpan.FromSeconds(10.0), ReleaseLock_Callback, m);
}
}
public void ReleaseLock_Callback(Mobile m)
{
m.EndAction(this);
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(Tournament);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
Tournament = reader.ReadItem() as TournamentController;
break;
}
}
Timer.DelayCall(TimeSpan.FromSeconds(30.0), TimeSpan.FromSeconds(30.0), Announce_Callback);
}
}
}
using System;
using Server.Factions;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class TournamentRegistrar : Banker
{
[Constructible]
public TournamentRegistrar()
{
Timer.DelayCall(TimeSpan.FromSeconds(30.0), TimeSpan.FromSeconds(30.0), Announce_Callback);
}
public TournamentRegistrar(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public TournamentController Tournament { get; set; }
private void Announce_Callback()
{
var tourney = Tournament?.Tournament;
if (tourney?.Stage == TournamentStage.Signup)
PublicOverheadMessage(
MessageType.Regular,
0x35,
false,
"Come one, come all! Do you aspire to be a fighter of great renown? Join this tournament and show the world your abilities."
);
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
base.OnMovement(m, oldLocation);
var tourney = Tournament?.Tournament;
if (InRange(m, 4) && !InRange(oldLocation, 4) && tourney != null && tourney.Stage == TournamentStage.Signup &&
m.CanBeginAction(this))
{
var ladder = Ladder.Instance;
var entry = ladder?.Find(m);
if (entry != null && Ladder.GetLevel(entry.Experience) < tourney.LevelRequirement)
return;
if (tourney.IsFactionRestricted && Faction.Find(m) == null) return;
if (tourney.HasParticipant(m))
return;
PrivateOverheadMessage(
MessageType.Regular,
0x35,
false,
$"Hello m'{(m.Female ? "Lady" : "Lord")}. Dost thou wish to enter this tournament? You need only to write your name in this book.",
m.NetState
);
m.BeginAction(this);
Timer.DelayCall(TimeSpan.FromSeconds(10.0), ReleaseLock_Callback, m);
}
}
public void ReleaseLock_Callback(Mobile m)
{
m.EndAction(this);
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(Tournament);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Tournament = reader.ReadItem() as TournamentController;
break;
}
}
Timer.DelayCall(TimeSpan.FromSeconds(30.0), TimeSpan.FromSeconds(30.0), Announce_Callback);
}
}
}

View file

@ -1,146 +1,189 @@
using System.Collections.Generic;
using Server.Factions;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class TournamentSignupItem : Item
{
[Constructible]
public TournamentSignupItem() : base(4029) => Movable = false;
public TournamentSignupItem(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public TournamentController Tournament { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public Mobile Registrar { get; set; }
public override string DefaultName => "tournament signup book";
public override void OnDoubleClick(Mobile from)
{
if (!from.InRange(GetWorldLocation(), 2))
{
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that
}
else
{
Tournament tourney = Tournament?.Tournament;
if (tourney == null)
return;
if (Registrar != null)
Registrar.Direction = Registrar.GetDirectionTo(this);
switch (tourney.Stage)
{
case TournamentStage.Fighting:
{
if (Registrar != null)
{
if (tourney.HasParticipant(from))
Registrar.PrivateOverheadMessage(MessageType.Regular,
0x35, false, "Excuse me? You are already signed up.", from.NetState);
else
Registrar.PrivateOverheadMessage(MessageType.Regular,
0x22, false, "The tournament has already begun. You are too late to signup now.",
from.NetState);
}
break;
}
case TournamentStage.Inactive:
{
Registrar?.PrivateOverheadMessage(MessageType.Regular,
0x35, false, "The tournament is closed.", from.NetState);
break;
}
case TournamentStage.Signup:
{
Ladder ladder = Ladder.Instance;
LadderEntry entry = ladder?.Find(from);
if (entry != null && Ladder.GetLevel(entry.Experience) < tourney.LevelRequirement)
{
Registrar?.PrivateOverheadMessage(MessageType.Regular,
0x35, false, "You have not yet proven yourself a worthy dueler.", from.NetState);
break;
}
if (tourney.IsFactionRestricted && Faction.Find(from) == null)
{
Registrar?.PrivateOverheadMessage(MessageType.Regular,
0x35, false, "Only those who have declared their faction allegiance may participate.",
from.NetState);
break;
}
if (from.HasGump<AcceptTeamGump>())
{
Registrar?.PrivateOverheadMessage(MessageType.Regular,
0x22, false, "You must first respond to the offer I've given you.", from.NetState);
}
else if (from.HasGump<AcceptDuelGump>())
{
Registrar?.PrivateOverheadMessage(MessageType.Regular,
0x22, false, "You must first cancel your duel offer.", from.NetState);
}
else if (from is PlayerMobile mobile && mobile.DuelContext != null)
{
Registrar?.PrivateOverheadMessage(MessageType.Regular,
0x22, false, "You are already participating in a duel.", mobile.NetState);
}
else if (!tourney.HasParticipant(from))
{
from.CloseGump<ConfirmSignupGump>();
from.SendGump(new ConfirmSignupGump(from, Registrar, tourney, new List<Mobile> { from }));
}
else
{
Registrar?.PrivateOverheadMessage(MessageType.Regular,
0x35, false, "You have already entered this tournament.", from.NetState);
}
break;
}
}
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(Tournament);
writer.Write(Registrar);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
Tournament = reader.ReadItem() as TournamentController;
Registrar = reader.ReadMobile();
break;
}
}
}
}
}
using System.Collections.Generic;
using Server.Factions;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.ConPVP
{
public class TournamentSignupItem : Item
{
[Constructible]
public TournamentSignupItem() : base(4029) => Movable = false;
public TournamentSignupItem(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public TournamentController Tournament { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public Mobile Registrar { get; set; }
public override string DefaultName => "tournament signup book";
public override void OnDoubleClick(Mobile from)
{
if (!from.InRange(GetWorldLocation(), 2))
{
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that
}
else
{
var tourney = Tournament?.Tournament;
if (tourney == null)
return;
if (Registrar != null)
Registrar.Direction = Registrar.GetDirectionTo(this);
switch (tourney.Stage)
{
case TournamentStage.Fighting:
{
if (Registrar != null)
{
if (tourney.HasParticipant(from))
Registrar.PrivateOverheadMessage(
MessageType.Regular,
0x35,
false,
"Excuse me? You are already signed up.",
from.NetState
);
else
Registrar.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
"The tournament has already begun. You are too late to signup now.",
from.NetState
);
}
break;
}
case TournamentStage.Inactive:
{
Registrar?.PrivateOverheadMessage(
MessageType.Regular,
0x35,
false,
"The tournament is closed.",
from.NetState
);
break;
}
case TournamentStage.Signup:
{
var ladder = Ladder.Instance;
var entry = ladder?.Find(from);
if (entry != null && Ladder.GetLevel(entry.Experience) < tourney.LevelRequirement)
{
Registrar?.PrivateOverheadMessage(
MessageType.Regular,
0x35,
false,
"You have not yet proven yourself a worthy dueler.",
from.NetState
);
break;
}
if (tourney.IsFactionRestricted && Faction.Find(from) == null)
{
Registrar?.PrivateOverheadMessage(
MessageType.Regular,
0x35,
false,
"Only those who have declared their faction allegiance may participate.",
from.NetState
);
break;
}
if (from.HasGump<AcceptTeamGump>())
{
Registrar?.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
"You must first respond to the offer I've given you.",
from.NetState
);
}
else if (from.HasGump<AcceptDuelGump>())
{
Registrar?.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
"You must first cancel your duel offer.",
from.NetState
);
}
else if (from is PlayerMobile mobile && mobile.DuelContext != null)
{
Registrar?.PrivateOverheadMessage(
MessageType.Regular,
0x22,
false,
"You are already participating in a duel.",
mobile.NetState
);
}
else if (!tourney.HasParticipant(from))
{
from.CloseGump<ConfirmSignupGump>();
from.SendGump(new ConfirmSignupGump(from, Registrar, tourney, new List<Mobile> { from }));
}
else
{
Registrar?.PrivateOverheadMessage(
MessageType.Regular,
0x35,
false,
"You have already entered this tournament.",
from.NetState
);
}
break;
}
}
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(Tournament);
writer.Write(Registrar);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Tournament = reader.ReadItem() as TournamentController;
Registrar = reader.ReadMobile();
break;
}
}
}
}
}

View file

@ -1,103 +1,103 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Server.Engines.ConPVP
{
public class TourneyParticipant : IComparable<TourneyParticipant>
{
public TourneyParticipant(Mobile owner)
{
Log = new List<string>();
Players = new List<Mobile> { owner };
}
public TourneyParticipant(List<Mobile> players)
{
Log = new List<string>();
Players = players;
}
public List<Mobile> Players { get; set; }
public List<string> Log { get; set; }
public int FreeAdvances { get; set; }
public int TotalLadderXP
{
get
{
Ladder ladder = Ladder.Instance;
if (ladder == null)
return 0;
int total = 0;
for (int i = 0; i < Players.Count; ++i)
{
Mobile mob = Players[i];
LadderEntry entry = ladder.Find(mob);
if (entry != null)
total += entry.Experience;
}
return total;
}
}
public string NameList
{
get
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < Players.Count; ++i)
{
if (Players[i] == null)
continue;
Mobile mob = Players[i];
if (sb.Length > 0)
{
if (Players.Count == 2)
sb.Append(" and ");
else if (i + 1 < Players.Count)
sb.Append(", ");
else
sb.Append(", and ");
}
sb.Append(mob.Name);
}
return sb.Length == 0 ? "Empty" : sb.ToString();
}
}
public int CompareTo(TourneyParticipant p) => p.TotalLadderXP - TotalLadderXP;
public void AddLog(string text)
{
Log.Add(text);
}
public void AddLog(string format, params object[] args)
{
AddLog(string.Format(format, args));
}
public void WonMatch(TourneyMatch match)
{
AddLog("Match won.");
}
public void LostMatch(TourneyMatch match)
{
AddLog("Match lost.");
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Server.Engines.ConPVP
{
public class TourneyParticipant : IComparable<TourneyParticipant>
{
public TourneyParticipant(Mobile owner)
{
Log = new List<string>();
Players = new List<Mobile> { owner };
}
public TourneyParticipant(List<Mobile> players)
{
Log = new List<string>();
Players = players;
}
public List<Mobile> Players { get; set; }
public List<string> Log { get; set; }
public int FreeAdvances { get; set; }
public int TotalLadderXP
{
get
{
var ladder = Ladder.Instance;
if (ladder == null)
return 0;
var total = 0;
for (var i = 0; i < Players.Count; ++i)
{
var mob = Players[i];
var entry = ladder.Find(mob);
if (entry != null)
total += entry.Experience;
}
return total;
}
}
public string NameList
{
get
{
var sb = new StringBuilder();
for (var i = 0; i < Players.Count; ++i)
{
if (Players[i] == null)
continue;
var mob = Players[i];
if (sb.Length > 0)
{
if (Players.Count == 2)
sb.Append(" and ");
else if (i + 1 < Players.Count)
sb.Append(", ");
else
sb.Append(", and ");
}
sb.Append(mob.Name);
}
return sb.Length == 0 ? "Empty" : sb.ToString();
}
}
public int CompareTo(TourneyParticipant p) => p.TotalLadderXP - TotalLadderXP;
public void AddLog(string text)
{
Log.Add(text);
}
public void AddLog(string format, params object[] args)
{
AddLog(string.Format(format, args));
}
public void WonMatch(TourneyMatch match)
{
AddLog("Match won.");
}
public void LostMatch(TourneyMatch match)
{
AddLog("Match lost.");
}
}
}

View file

@ -1,113 +1,113 @@
using System;
namespace Server.Items
{
public enum TrophyRank
{
Bronze,
Silver,
Gold
}
[Flippable(5020, 4647)]
public class Trophy : Item
{
private TrophyRank m_Rank;
[Constructible]
public Trophy(string title, TrophyRank rank) : base(5020)
{
Title = title;
m_Rank = rank;
Date = DateTime.UtcNow;
LootType = LootType.Blessed;
UpdateStyle();
}
public Trophy(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public string Title { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public TrophyRank Rank
{
get => m_Rank;
set
{
m_Rank = value;
UpdateStyle();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public Mobile Owner { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime Date { get; private set; }
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
writer.Write(Title);
writer.Write((int)m_Rank);
writer.Write(Owner);
writer.Write(Date);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
Title = reader.ReadString();
m_Rank = (TrophyRank)reader.ReadInt();
Owner = reader.ReadMobile();
Date = reader.ReadDateTime();
if (version == 0)
LootType = LootType.Blessed;
}
public override void OnAdded(IEntity parent)
{
base.OnAdded(parent);
Owner ??= RootParent as Mobile;
}
public override void OnSingleClick(Mobile from)
{
base.OnSingleClick(from);
if (Owner != null)
LabelTo(from, "{0} -- {1}", Title, Owner.RawName);
else if (Title != null)
LabelTo(from, Title);
if (Date != DateTime.MinValue)
LabelTo(from, Date.ToString("d"));
}
public void UpdateStyle()
{
Name = $"{m_Rank.ToString().ToLower()} trophy";
Hue = m_Rank switch
{
TrophyRank.Gold => 2213,
TrophyRank.Silver => 0,
TrophyRank.Bronze => 2206,
_ => Hue
};
}
}
}
using System;
namespace Server.Items
{
public enum TrophyRank
{
Bronze,
Silver,
Gold
}
[Flippable(5020, 4647)]
public class Trophy : Item
{
private TrophyRank m_Rank;
[Constructible]
public Trophy(string title, TrophyRank rank) : base(5020)
{
Title = title;
m_Rank = rank;
Date = DateTime.UtcNow;
LootType = LootType.Blessed;
UpdateStyle();
}
public Trophy(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public string Title { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public TrophyRank Rank
{
get => m_Rank;
set
{
m_Rank = value;
UpdateStyle();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public Mobile Owner { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime Date { get; private set; }
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
writer.Write(Title);
writer.Write((int)m_Rank);
writer.Write(Owner);
writer.Write(Date);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
Title = reader.ReadString();
m_Rank = (TrophyRank)reader.ReadInt();
Owner = reader.ReadMobile();
Date = reader.ReadDateTime();
if (version == 0)
LootType = LootType.Blessed;
}
public override void OnAdded(IEntity parent)
{
base.OnAdded(parent);
Owner ??= RootParent as Mobile;
}
public override void OnSingleClick(Mobile from)
{
base.OnSingleClick(from);
if (Owner != null)
LabelTo(from, "{0} -- {1}", Title, Owner.RawName);
else if (Title != null)
LabelTo(from, Title);
if (Date != DateTime.MinValue)
LabelTo(from, Date.ToString("d"));
}
public void UpdateStyle()
{
Name = $"{m_Rank.ToString().ToLower()} trophy";
Hue = m_Rank switch
{
TrophyRank.Gold => 2213,
TrophyRank.Silver => 0,
TrophyRank.Bronze => 2206,
_ => Hue
};
}
}
}