fix: Stages faction code for serialization conversion (#1835)

This commit is contained in:
Kamron Batman 2024-06-16 11:53:15 -07:00 • committed by GitHub
parent 20596e52fa
commit 221312be4c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 6234 additions and 6364 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,154 +1,153 @@
using System; using System;
namespace Server.Factions namespace Server.Factions;
public interface IFactionItem
{ {
public interface IFactionItem FactionItem FactionItemState { get; set; }
}
public class FactionItem
{
public static readonly TimeSpan ExpirationPeriod = TimeSpan.FromDays(21.0);
public FactionItem(Item item, Faction faction)
{ {
FactionItem FactionItemState { get; set; } Item = item;
Faction = faction;
} }
public class FactionItem public FactionItem(IGenericReader reader, Faction faction)
{ {
public static readonly TimeSpan ExpirationPeriod = TimeSpan.FromDays(21.0); var version = reader.ReadEncodedInt();
public FactionItem(Item item, Faction faction) switch (version)
{ {
Item = item; case 0:
Faction = faction;
}
public FactionItem(IGenericReader reader, Faction faction)
{
var version = reader.ReadEncodedInt();
switch (version)
{
case 0:
{
Item = reader.ReadEntity<Item>();
Expiration = reader.ReadDateTime();
break;
}
}
Faction = faction;
}
public Item Item { get; }
public Faction Faction { get; }
public DateTime Expiration { get; private set; }
public bool HasExpired
{
get
{
if (Item?.Deleted != false)
{ {
return true; Item = reader.ReadEntity<Item>();
Expiration = reader.ReadDateTime();
break;
} }
return Expiration != DateTime.MinValue && Core.Now >= Expiration;
}
} }
public void StartExpiration() Faction = faction;
}
public Item Item { get; }
public Faction Faction { get; }
public DateTime Expiration { get; private set; }
public bool HasExpired
{
get
{ {
Expiration = Core.Now + ExpirationPeriod; if (Item?.Deleted != false)
{
return true;
}
return Expiration != DateTime.MinValue && Core.Now >= Expiration;
}
}
public void StartExpiration()
{
Expiration = Core.Now + ExpirationPeriod;
}
public void CheckAttach()
{
if (!HasExpired)
{
Attach();
}
else
{
Detach();
}
}
public void Attach()
{
if (Item is IFactionItem item)
{
item.FactionItemState = this;
} }
public void CheckAttach() Faction?.State.FactionItems.Add(this);
}
public void Detach()
{
if (Item is IFactionItem item)
{ {
if (!HasExpired) item.FactionItemState = null;
{
Attach();
}
else
{
Detach();
}
} }
public void Attach() if (Faction?.State.FactionItems.Contains(this) == true)
{ {
if (Item is IFactionItem item) Faction.State.FactionItems.Remove(this);
}
}
public void Serialize(IGenericWriter writer)
{
writer.WriteEncodedInt(0);
writer.Write(Item);
writer.Write(Expiration);
}
public static int GetMaxWearables(Mobile mob)
{
var pl = PlayerState.Find(mob);
return pl == null ? 0 :
pl.Faction.IsCommander(mob) ? 9 : pl.Rank.MaxWearables;
}
public static FactionItem Find(Item item)
{
if (item is IFactionItem factionItem)
{
var state = factionItem.FactionItemState;
if (state?.HasExpired == true)
{ {
item.FactionItemState = this; state.Detach();
state = null;
} }
Faction?.State.FactionItems.Add(this); return state;
} }
public void Detach() return null;
}
public static Item Imbue(Item item, Faction faction, bool expire, int hue)
{
if (item is not IFactionItem)
{ {
if (Item is IFactionItem item)
{
item.FactionItemState = null;
}
if (Faction?.State.FactionItems.Contains(this) == true)
{
Faction.State.FactionItems.Remove(this);
}
}
public void Serialize(IGenericWriter writer)
{
writer.WriteEncodedInt(0);
writer.Write(Item);
writer.Write(Expiration);
}
public static int GetMaxWearables(Mobile mob)
{
var pl = PlayerState.Find(mob);
return pl == null ? 0 :
pl.Faction.IsCommander(mob) ? 9 : pl.Rank.MaxWearables;
}
public static FactionItem Find(Item item)
{
if (item is IFactionItem factionItem)
{
var state = factionItem.FactionItemState;
if (state?.HasExpired == true)
{
state.Detach();
state = null;
}
return state;
}
return null;
}
public static Item Imbue(Item item, Faction faction, bool expire, int hue)
{
if (item is not IFactionItem)
{
return item;
}
var state = Find(item);
if (state == null)
{
state = new FactionItem(item, faction);
state.Attach();
}
if (expire)
{
state.StartExpiration();
}
item.Hue = hue;
return item; return item;
} }
var state = Find(item);
if (state == null)
{
state = new FactionItem(item, faction);
state.Attach();
}
if (expire)
{
state.StartExpiration();
}
item.Hue = hue;
return item;
} }
} }

View file

@ -1,309 +1,308 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Server.Factions namespace Server.Factions;
public class FactionState
{ {
public class FactionState private const int BroadcastsPerPeriod = 2;
private static readonly TimeSpan BroadcastPeriod = TimeSpan.FromHours(1.0);
private readonly Faction m_Faction;
private readonly DateTime[] m_LastBroadcasts = new DateTime[BroadcastsPerPeriod];
private Mobile m_Commander;
public FactionState(Faction faction)
{ {
private const int BroadcastsPerPeriod = 2; m_Faction = faction;
private static readonly TimeSpan BroadcastPeriod = TimeSpan.FromHours(1.0); Tithe = 50;
private readonly Faction m_Faction; Members = [];
Election = new Election(faction);
FactionItems = [];
Traps = [];
}
private readonly DateTime[] m_LastBroadcasts = new DateTime[BroadcastsPerPeriod]; public FactionState(IGenericReader reader)
private Mobile m_Commander; {
var version = reader.ReadEncodedInt();
public FactionState(Faction faction) switch (version)
{ {
m_Faction = faction; case 5:
Tithe = 50;
Members = new List<PlayerState>();
Election = new Election(faction);
FactionItems = new List<FactionItem>();
Traps = new List<BaseFactionTrap>();
}
public FactionState(IGenericReader reader)
{
var version = reader.ReadEncodedInt();
switch (version)
{
case 5:
{
LastAtrophy = reader.ReadDateTime();
goto case 4;
}
case 4:
{
var count = reader.ReadEncodedInt();
for (var i = 0; i < count; ++i)
{
var time = reader.ReadDateTime();
if (i < m_LastBroadcasts.Length)
{
m_LastBroadcasts[i] = time;
}
}
goto case 3;
}
case 3:
case 2:
case 1:
{
Election = new Election(reader);
goto case 0;
}
case 0:
{
m_Faction = Faction.ReadReference(reader);
m_Commander = reader.ReadEntity<Mobile>();
if (version < 5)
{
LastAtrophy = Core.Now;
}
if (version < 4)
{
var time = reader.ReadDateTime();
if (m_LastBroadcasts.Length > 0)
{
m_LastBroadcasts[0] = time;
}
}
Tithe = reader.ReadEncodedInt();
Silver = reader.ReadEncodedInt();
var memberCount = reader.ReadEncodedInt();
Members = new List<PlayerState>();
for (var i = 0; i < memberCount; ++i)
{
var pl = new PlayerState(reader, m_Faction, Members);
if (pl.Mobile != null)
{
Members.Add(pl);
}
}
m_Faction.State = this;
m_Faction.ZeroRankOffset = Members.Count;
Members.Sort();
for (var i = Members.Count - 1; i >= 0; i--)
{
var player = Members[i];
if (player.KillPoints <= 0)
{
m_Faction.ZeroRankOffset = i;
}
else
{
player.RankIndex = i;
}
}
FactionItems = new List<FactionItem>();
if (version >= 2)
{
var factionItemCount = reader.ReadEncodedInt();
for (var i = 0; i < factionItemCount; ++i)
{
var factionItem = new FactionItem(reader, m_Faction);
Timer.StartTimer(factionItem.CheckAttach); // sandbox attachment
}
}
Traps = new List<BaseFactionTrap>();
if (version >= 3)
{
var factionTrapCount = reader.ReadEncodedInt();
for (var i = 0; i < factionTrapCount; ++i)
{
if (reader.ReadEntity<Item>() is BaseFactionTrap trap && !trap.CheckDecay())
{
Traps.Add(trap);
}
}
}
break;
}
}
if (version < 1)
{
Election = new Election(m_Faction);
}
}
public DateTime LastAtrophy { get; set; }
public bool FactionMessageReady
{
get
{
for (var i = 0; i < m_LastBroadcasts.Length; ++i)
{ {
if (Core.Now >= m_LastBroadcasts[i] + BroadcastPeriod) LastAtrophy = reader.ReadDateTime();
{ goto case 4;
return true;
}
} }
case 4:
{
var count = reader.ReadEncodedInt();
return false; for (var i = 0; i < count; ++i)
} {
var time = reader.ReadDateTime();
if (i < m_LastBroadcasts.Length)
{
m_LastBroadcasts[i] = time;
}
}
goto case 3;
}
case 3:
case 2:
case 1:
{
Election = new Election(reader);
goto case 0;
}
case 0:
{
m_Faction = Faction.ReadReference(reader);
m_Commander = reader.ReadEntity<Mobile>();
if (version < 5)
{
LastAtrophy = Core.Now;
}
if (version < 4)
{
var time = reader.ReadDateTime();
if (m_LastBroadcasts.Length > 0)
{
m_LastBroadcasts[0] = time;
}
}
Tithe = reader.ReadEncodedInt();
Silver = reader.ReadEncodedInt();
var memberCount = reader.ReadEncodedInt();
Members = [];
for (var i = 0; i < memberCount; ++i)
{
var pl = new PlayerState(reader, m_Faction, Members);
if (pl.Mobile != null)
{
Members.Add(pl);
}
}
m_Faction.State = this;
m_Faction.ZeroRankOffset = Members.Count;
Members.Sort();
for (var i = Members.Count - 1; i >= 0; i--)
{
var player = Members[i];
if (player.KillPoints <= 0)
{
m_Faction.ZeroRankOffset = i;
}
else
{
player.RankIndex = i;
}
}
FactionItems = [];
if (version >= 2)
{
var factionItemCount = reader.ReadEncodedInt();
for (var i = 0; i < factionItemCount; ++i)
{
var factionItem = new FactionItem(reader, m_Faction);
Timer.StartTimer(factionItem.CheckAttach); // sandbox attachment
}
}
Traps = [];
if (version >= 3)
{
var factionTrapCount = reader.ReadEncodedInt();
for (var i = 0; i < factionTrapCount; ++i)
{
if (reader.ReadEntity<Item>() is BaseFactionTrap trap && !trap.CheckDecay())
{
Traps.Add(trap);
}
}
}
break;
}
} }
public bool IsAtrophyReady => Core.Now >= LastAtrophy + TimeSpan.FromHours(47.0); if (version < 1)
public List<FactionItem> FactionItems { get; set; }
public List<BaseFactionTrap> Traps { get; set; }
public Election Election { get; set; }
public Mobile Commander
{ {
get => m_Commander; Election = new Election(m_Faction);
set
{
m_Commander?.InvalidateProperties();
m_Commander = value;
if (m_Commander != null)
{
m_Commander.SendLocalizedMessage(1042227); // You have been elected Commander of your faction
m_Commander.InvalidateProperties();
var pl = PlayerState.Find(m_Commander);
if (pl?.Finance != null)
{
pl.Finance.Finance = null;
}
if (pl?.Sheriff != null)
{
pl.Sheriff.Sheriff = null;
}
}
}
} }
}
public int Tithe { get; set; } public DateTime LastAtrophy { get; set; }
public int Silver { get; set; } public bool FactionMessageReady
{
public List<PlayerState> Members { get; set; } get
public int CheckAtrophy()
{
if (Core.Now < LastAtrophy + TimeSpan.FromHours(47.0))
{
return 0;
}
var distrib = 0;
LastAtrophy = Core.Now;
var members = new List<PlayerState>(Members);
for (var i = 0; i < members.Count; ++i)
{
var ps = members[i];
if (ps.IsActive)
{
ps.IsActive = false;
continue;
}
if (ps.KillPoints > 0)
{
var atrophy = (ps.KillPoints + 9) / 10;
ps.KillPoints -= atrophy;
distrib += atrophy;
}
}
return distrib;
}
public void RegisterBroadcast()
{ {
for (var i = 0; i < m_LastBroadcasts.Length; ++i) for (var i = 0; i < m_LastBroadcasts.Length; ++i)
{ {
if (Core.Now >= m_LastBroadcasts[i] + BroadcastPeriod) if (Core.Now >= m_LastBroadcasts[i] + BroadcastPeriod)
{ {
m_LastBroadcasts[i] = Core.Now; return true;
break; }
}
return false;
}
}
public bool IsAtrophyReady => Core.Now >= LastAtrophy + TimeSpan.FromHours(47.0);
public List<FactionItem> FactionItems { get; set; }
public List<BaseFactionTrap> Traps { get; set; }
public Election Election { get; set; }
public Mobile Commander
{
get => m_Commander;
set
{
m_Commander?.InvalidateProperties();
m_Commander = value;
if (m_Commander != null)
{
m_Commander.SendLocalizedMessage(1042227); // You have been elected Commander of your faction
m_Commander.InvalidateProperties();
var pl = PlayerState.Find(m_Commander);
if (pl?.Finance != null)
{
pl.Finance.Finance = null;
}
if (pl?.Sheriff != null)
{
pl.Sheriff.Sheriff = null;
} }
} }
} }
}
public void Serialize(IGenericWriter writer) public int Tithe { get; set; }
public int Silver { get; set; }
public List<PlayerState> Members { get; set; }
public int CheckAtrophy()
{
if (Core.Now < LastAtrophy + TimeSpan.FromHours(47.0))
{ {
writer.WriteEncodedInt(5); // version return 0;
}
writer.Write(LastAtrophy); var distrib = 0;
LastAtrophy = Core.Now;
writer.WriteEncodedInt(m_LastBroadcasts.Length); var members = new List<PlayerState>(Members);
for (var i = 0; i < m_LastBroadcasts.Length; ++i) for (var i = 0; i < members.Count; ++i)
{
var ps = members[i];
if (ps.IsActive)
{ {
writer.Write(m_LastBroadcasts[i]); ps.IsActive = false;
continue;
} }
Election.Serialize(writer); if (ps.KillPoints > 0)
Faction.WriteReference(writer, m_Faction);
writer.Write(m_Commander);
writer.WriteEncodedInt(Tithe);
writer.WriteEncodedInt(Silver);
writer.WriteEncodedInt(Members.Count);
for (var i = 0; i < Members.Count; ++i)
{ {
var pl = Members[i]; var atrophy = (ps.KillPoints + 9) / 10;
ps.KillPoints -= atrophy;
pl.Serialize(writer); distrib += atrophy;
} }
}
writer.WriteEncodedInt(FactionItems.Count); return distrib;
}
for (var i = 0; i < FactionItems.Count; ++i) public void RegisterBroadcast()
{
for (var i = 0; i < m_LastBroadcasts.Length; ++i)
{
if (Core.Now >= m_LastBroadcasts[i] + BroadcastPeriod)
{ {
FactionItems[i].Serialize(writer); m_LastBroadcasts[i] = Core.Now;
} break;
writer.WriteEncodedInt(Traps.Count);
for (var i = 0; i < Traps.Count; ++i)
{
writer.Write(Traps[i]);
} }
} }
} }
public void Serialize(IGenericWriter writer)
{
writer.WriteEncodedInt(5); // version
writer.Write(LastAtrophy);
writer.WriteEncodedInt(m_LastBroadcasts.Length);
for (var i = 0; i < m_LastBroadcasts.Length; ++i)
{
writer.Write(m_LastBroadcasts[i]);
}
Election.Serialize(writer);
Faction.WriteReference(writer, m_Faction);
writer.Write(m_Commander);
writer.WriteEncodedInt(Tithe);
writer.WriteEncodedInt(Silver);
writer.WriteEncodedInt(Members.Count);
for (var i = 0; i < Members.Count; ++i)
{
var pl = Members[i];
pl.Serialize(writer);
}
writer.WriteEncodedInt(FactionItems.Count);
for (var i = 0; i < FactionItems.Count; ++i)
{
FactionItems[i].Serialize(writer);
}
writer.WriteEncodedInt(Traps.Count);
for (var i = 0; i < Traps.Count; ++i)
{
writer.Write(Traps[i]);
}
}
} }

View file

@ -1,100 +1,99 @@
using System; using System;
namespace Server.Factions namespace Server.Factions;
public static class Generator
{ {
public static class Generator public static void Configure()
{ {
public static void Configure() CommandSystem.Register("GenerateFactions", AccessLevel.Developer, GenerateFactions_OnCommand);
}
[Usage("GenerateFactions")]
[Aliases("FactionGen", "GenFactions")]
[Description("Enables and generates factions.")]
public static void GenerateFactions_OnCommand(CommandEventArgs e)
{
var from = e.Mobile;
FactionSystem.Enable();
var factions = Faction.Factions;
foreach (var faction in factions)
{ {
CommandSystem.Register("GenerateFactions", AccessLevel.Developer, GenerateFactions_OnCommand); Generate(faction);
from.SendMessage($"Generated {faction}");
} }
[Usage("GenerateFactions")] var towns = Town.Towns;
[Aliases("FactionGen", "GenFactions")]
[Description("Enables and generates factions.")] foreach (var town in towns)
public static void GenerateFactions_OnCommand(CommandEventArgs e)
{ {
var from = e.Mobile; Generate(town);
FactionSystem.Enable(); from.SendMessage($"Generated {town}");
var factions = Faction.Factions;
foreach (var faction in factions)
{
Generate(faction);
from.SendMessage($"Generated {faction}");
}
var towns = Town.Towns;
foreach (var town in towns)
{
Generate(town);
from.SendMessage($"Generated {town}");
}
from.SendMessage("Faction generation completed.");
} }
public static void Generate(Town town) from.SendMessage("Faction generation completed.");
}
public static void Generate(Town town)
{
var facet = Faction.Facet;
var def = town.Definition;
if (!CheckExistence(def.Monolith, facet, typeof(TownMonolith)))
{ {
var facet = Faction.Facet; var mono = new TownMonolith(town);
mono.MoveToWorld(def.Monolith, facet);
var def = town.Definition; mono.Sigil = new Sigil(town);
if (!CheckExistence(def.Monolith, facet, typeof(TownMonolith)))
{
var mono = new TownMonolith(town);
mono.MoveToWorld(def.Monolith, facet);
mono.Sigil = new Sigil(town);
}
if (!CheckExistence(def.TownStone, facet, typeof(TownStone)))
{
new TownStone(town).MoveToWorld(def.TownStone, facet);
}
} }
public static void Generate(Faction faction) if (!CheckExistence(def.TownStone, facet, typeof(TownStone)))
{ {
var facet = Faction.Facet; new TownStone(town).MoveToWorld(def.TownStone, facet);
var towns = Town.Towns;
var stronghold = faction.Definition.Stronghold;
if (!CheckExistence(stronghold.JoinStone, facet, typeof(JoinStone)))
{
new JoinStone(faction).MoveToWorld(stronghold.JoinStone, facet);
}
if (!CheckExistence(stronghold.FactionStone, facet, typeof(FactionStone)))
{
new FactionStone(faction).MoveToWorld(stronghold.FactionStone, facet);
}
for (var i = 0; i < stronghold.Monoliths.Length; ++i)
{
var monolith = stronghold.Monoliths[i];
if (!CheckExistence(monolith, facet, typeof(StrongholdMonolith)))
{
new StrongholdMonolith(towns[i], faction).MoveToWorld(monolith, facet);
}
}
}
private static bool CheckExistence(Point3D loc, Map facet, Type type)
{
foreach (var item in facet.GetItemsAt(loc))
{
if (type.IsInstanceOfType(item))
{
return true;
}
}
return false;
} }
} }
}
public static void Generate(Faction faction)
{
var facet = Faction.Facet;
var towns = Town.Towns;
var stronghold = faction.Definition.Stronghold;
if (!CheckExistence(stronghold.JoinStone, facet, typeof(JoinStone)))
{
new JoinStone(faction).MoveToWorld(stronghold.JoinStone, facet);
}
if (!CheckExistence(stronghold.FactionStone, facet, typeof(FactionStone)))
{
new FactionStone(faction).MoveToWorld(stronghold.FactionStone, facet);
}
for (var i = 0; i < stronghold.Monoliths.Length; ++i)
{
var monolith = stronghold.Monoliths[i];
if (!CheckExistence(monolith, facet, typeof(StrongholdMonolith)))
{
new StrongholdMonolith(towns[i], faction).MoveToWorld(monolith, facet);
}
}
}
private static bool CheckExistence(Point3D loc, Map facet, Type type)
{
foreach (var item in facet.GetItemsAt(loc))
{
if (type.IsInstanceOfType(item))
{
return true;
}
}
return false;
}
}

View file

@ -1,29 +1,28 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace Server.Factions namespace Server.Factions;
public class GuardList
{ {
public class GuardList public GuardList(GuardDefinition definition)
{ {
public GuardList(GuardDefinition definition) Definition = definition;
Guards = [];
}
public GuardDefinition Definition { get; }
public List<BaseFactionGuard> Guards { get; }
public BaseFactionGuard Construct()
{
try
{ {
Definition = definition; return Definition.Type.CreateInstance<BaseFactionGuard>();
Guards = new List<BaseFactionGuard>();
} }
catch
public GuardDefinition Definition { get; }
public List<BaseFactionGuard> Guards { get; }
public BaseFactionGuard Construct()
{ {
try return null;
{
return Definition.Type.CreateInstance<BaseFactionGuard>();
}
catch
{
return null;
}
} }
} }
} }

View file

@ -1,189 +1,188 @@
using Server.Mobiles; using Server.Mobiles;
namespace Server.Factions namespace Server.Factions;
public static class Keywords
{ {
public static class Keywords public static void Initialize()
{ {
public static void Initialize() EventSink.Speech += EventSink_Speech;
{ }
EventSink.Speech += EventSink_Speech;
}
private static void ShowScore_Sandbox(PlayerState pl) private static void ShowScore_Sandbox(PlayerState pl)
{ {
pl?.Mobile.PublicOverheadMessage( pl?.Mobile.PublicOverheadMessage(
MessageType.Regular, MessageType.Regular,
pl.Mobile.SpeechHue, pl.Mobile.SpeechHue,
true, true,
pl.KillPoints.ToString("N0") pl.KillPoints.ToString("N0")
); );
} }
private static void EventSink_Speech(SpeechEventArgs e) private static void EventSink_Speech(SpeechEventArgs e)
{ {
var from = e.Mobile; var from = e.Mobile;
var keywords = e.Keywords; var keywords = e.Keywords;
for (var i = 0; i < keywords.Length; ++i) for (var i = 0; i < keywords.Length; ++i)
{
switch (keywords[i])
{ {
switch (keywords[i]) case 0x00E4: // *i wish to access the city treasury*
{ {
case 0x00E4: // *i wish to access the city treasury* var town = Town.FromRegion(from.Region);
{
var town = Town.FromRegion(from.Region);
if (town?.IsFinance(from) != true || !from.Alive) if (town?.IsFinance(from) != true || !from.Alive)
{
break;
}
if (FactionGump.Exists(from))
{
from.SendLocalizedMessage(1042160); // You already have a faction menu open.
}
else if (town.Owner != null && from is PlayerMobile mobile)
{
mobile.SendGump(new FinanceGump(mobile, town.Owner, town));
}
break;
}
case 0x0ED: // *i am sheriff*
{
var town = Town.FromRegion(from.Region);
if (town?.IsSheriff(from) != true || !from.Alive)
{
break;
}
if (FactionGump.Exists(from))
{
from.SendLocalizedMessage(1042160); // You already have a faction menu open.
}
else if (town.Owner != null)
{
from.SendGump(new SheriffGump((PlayerMobile)from, town.Owner, town));
}
break;
}
case 0x00EF: // *you are fired*
{
var town = Town.FromRegion(from.Region);
if (town == null)
{
break;
}
if (town.IsFinance(from) || town.IsSheriff(from))
{
town.BeginOrderFiring(from);
}
break;
}
case 0x00E5: // *i wish to resign as finance minister*
{
var pl = PlayerState.Find(from);
if (pl?.Finance != null)
{
pl.Finance.Finance = null;
from.SendLocalizedMessage(1005081); // You have been fired as Finance Minister
}
break;
}
case 0x00EE: // *i wish to resign as sheriff*
{
var pl = PlayerState.Find(from);
if (pl?.Sheriff != null)
{
pl.Sheriff.Sheriff = null;
from.SendLocalizedMessage(1010270); // You have been fired as Sheriff
}
break;
}
case 0x00E9: // *what is my faction term status*
{
var pl = PlayerState.Find(from);
if (pl?.IsLeaving == true)
{
if (Faction.CheckLeaveTimer(from))
{ {
break; break;
} }
if (FactionGump.Exists(from)) var remaining = pl.Leaving + Faction.LeavePeriod - Core.Now;
if (remaining.TotalDays >= 1)
{ {
from.SendLocalizedMessage(1042160); // You already have a faction menu open. // Your term of service will come to an end in ~1_DAYS~ days.
from.SendLocalizedMessage(1042743, remaining.TotalDays.ToString("N0"));
} }
else if (town.Owner != null && from is PlayerMobile mobile) else if (remaining.TotalHours >= 1)
{ {
mobile.SendGump(new FinanceGump(mobile, town.Owner, town)); // Your term of service will come to an end in ~1_HOURS~ hours.
} from.SendLocalizedMessage(1042741, remaining.TotalHours.ToString("N0"));
break;
}
case 0x0ED: // *i am sheriff*
{
var town = Town.FromRegion(from.Region);
if (town?.IsSheriff(from) != true || !from.Alive)
{
break;
}
if (FactionGump.Exists(from))
{
from.SendLocalizedMessage(1042160); // You already have a faction menu open.
}
else if (town.Owner != null)
{
from.SendGump(new SheriffGump((PlayerMobile)from, town.Owner, town));
}
break;
}
case 0x00EF: // *you are fired*
{
var town = Town.FromRegion(from.Region);
if (town == null)
{
break;
}
if (town.IsFinance(from) || town.IsSheriff(from))
{
town.BeginOrderFiring(from);
}
break;
}
case 0x00E5: // *i wish to resign as finance minister*
{
var pl = PlayerState.Find(from);
if (pl?.Finance != null)
{
pl.Finance.Finance = null;
from.SendLocalizedMessage(1005081); // You have been fired as Finance Minister
}
break;
}
case 0x00EE: // *i wish to resign as sheriff*
{
var pl = PlayerState.Find(from);
if (pl?.Sheriff != null)
{
pl.Sheriff.Sheriff = null;
from.SendLocalizedMessage(1010270); // You have been fired as Sheriff
}
break;
}
case 0x00E9: // *what is my faction term status*
{
var pl = PlayerState.Find(from);
if (pl?.IsLeaving == true)
{
if (Faction.CheckLeaveTimer(from))
{
break;
}
var remaining = pl.Leaving + Faction.LeavePeriod - Core.Now;
if (remaining.TotalDays >= 1)
{
// Your term of service will come to an end in ~1_DAYS~ days.
from.SendLocalizedMessage(1042743, remaining.TotalDays.ToString("N0"));
}
else if (remaining.TotalHours >= 1)
{
// Your term of service will come to an end in ~1_HOURS~ hours.
from.SendLocalizedMessage(1042741, remaining.TotalHours.ToString("N0"));
}
else
{
// Your term of service will come to an end in less than one hour.
from.SendLocalizedMessage(1042742);
}
}
else if (pl != null)
{
// You are not in the process of quitting the faction.
from.SendLocalizedMessage(1042233);
}
break;
}
case 0x00EA: // *message faction*
{
var faction = Faction.Find(from);
if (faction?.IsCommander(from) != true)
{
break;
}
if (from.AccessLevel == AccessLevel.Player && !faction.FactionMessageReady)
{
// The required time has not yet passed since the last message was sent
from.SendLocalizedMessage(1010264);
} }
else else
{ {
faction.BeginBroadcast(from); // Your term of service will come to an end in less than one hour.
from.SendLocalizedMessage(1042742);
} }
break;
} }
case 0x00EC: // *showscore* else if (pl != null)
{ {
var pl = PlayerState.Find(from); // You are not in the process of quitting the faction.
from.SendLocalizedMessage(1042233);
if (pl != null)
{
Timer.StartTimer(() => ShowScore_Sandbox(pl));
}
break;
} }
case 0x0178: // i honor your leadership
break;
}
case 0x00EA: // *message faction*
{
var faction = Faction.Find(from);
if (faction?.IsCommander(from) != true)
{ {
Faction.Find(from)?.BeginHonorLeadership(from);
break; break;
} }
}
if (from.AccessLevel == AccessLevel.Player && !faction.FactionMessageReady)
{
// The required time has not yet passed since the last message was sent
from.SendLocalizedMessage(1010264);
}
else
{
faction.BeginBroadcast(from);
}
break;
}
case 0x00EC: // *showscore*
{
var pl = PlayerState.Find(from);
if (pl != null)
{
Timer.StartTimer(() => ShowScore_Sandbox(pl));
}
break;
}
case 0x0178: // i honor your leadership
{
Faction.Find(from)?.BeginHonorLeadership(from);
break;
}
} }
} }
} }
} }

View file

@ -1,123 +1,118 @@
namespace Server.Factions using System.Runtime.CompilerServices;
namespace Server.Factions;
public enum MerchantTitle
{ {
public enum MerchantTitle None,
{ Scribe,
None, Carpenter,
Scribe, Blacksmith,
Carpenter, Bowyer,
Blacksmith, Tailor
Bowyer, }
Tailor
} public class MerchantTitleInfo
{
public class MerchantTitleInfo public MerchantTitleInfo(
{ SkillName skill, double requirement, TextDefinition title, TextDefinition label,
public MerchantTitleInfo( TextDefinition assigned
SkillName skill, double requirement, TextDefinition title, TextDefinition label, )
TextDefinition assigned {
) Skill = skill;
{ Requirement = requirement;
Skill = skill; Title = title;
Requirement = requirement; Label = label;
Title = title; Assigned = assigned;
Label = label; }
Assigned = assigned;
} public SkillName Skill { get; }
public SkillName Skill { get; } public double Requirement { get; }
public double Requirement { get; } public TextDefinition Title { get; }
public TextDefinition Title { get; } public TextDefinition Label { get; }
public TextDefinition Label { get; } public TextDefinition Assigned { get; }
}
public TextDefinition Assigned { get; }
} public static class MerchantTitles
{
public static class MerchantTitles public static MerchantTitleInfo[] Info { get; } =
{ [
public static MerchantTitleInfo[] Info { get; } = new MerchantTitleInfo(
{ SkillName.Inscribe,
new( 90.0,
SkillName.Inscribe, 1060773, // Scribe
90.0, 1011468, // SCRIBE
1060773, // Scribe 1010121 // You now have the faction title of scribe
1011468, // SCRIBE ),
1010121 // You now have the faction title of scribe new MerchantTitleInfo(
), SkillName.Carpentry,
new( 90.0,
SkillName.Carpentry, 1060774, // Carpenter
90.0, 1011469, // CARPENTER
1060774, // Carpenter 1010122 // You now have the faction title of carpenter
1011469, // CARPENTER ),
1010122 // You now have the faction title of carpenter new MerchantTitleInfo(
), SkillName.Tinkering,
new( 90.0,
SkillName.Tinkering, 1022984, // Tinker
90.0, 1011470, // TINKER
1022984, // Tinker 1010123 // You now have the faction title of tinker
1011470, // TINKER ),
1010123 // You now have the faction title of tinker new MerchantTitleInfo(
), SkillName.Blacksmith,
new( 90.0,
SkillName.Blacksmith, 1023016, // Blacksmith
90.0, 1011471, // BLACKSMITH
1023016, // Blacksmith 1010124 // You now have the faction title of blacksmith
1011471, // BLACKSMITH ),
1010124 // You now have the faction title of blacksmith new MerchantTitleInfo(
), SkillName.Fletching,
new( 90.0,
SkillName.Fletching, 1023022, // Bowyer
90.0, 1011472, // BOWYER
1023022, // Bowyer 1010125 // You now have the faction title of Bowyer
1011472, // BOWYER ),
1010125 // You now have the faction title of Bowyer new MerchantTitleInfo(
), SkillName.Tailoring,
new( 90.0,
SkillName.Tailoring, 1022982, // Tailor
90.0, 1018300, // TAILOR
1022982, // Tailor 1042162 // You now have the faction title of Tailor
1018300, // TAILOR )
1042162 // You now have the faction title of Tailor ];
)
}; public static MerchantTitleInfo GetInfo(MerchantTitle title)
{
public static MerchantTitleInfo GetInfo(MerchantTitle title) var idx = (int)title - 1;
{
var idx = (int)title - 1; if (idx >= 0 && idx < Info.Length)
{
if (idx >= 0 && idx < Info.Length) return Info[idx];
{ }
return Info[idx];
} return null;
}
return null;
} public static bool HasMerchantQualifications(Mobile mob)
{
public static bool HasMerchantQualifications(Mobile mob) for (var i = 0; i < Info.Length; ++i)
{ {
for (var i = 0; i < Info.Length; ++i) if (IsQualified(mob, Info[i]))
{ {
if (IsQualified(mob, Info[i])) return true;
{ }
return true; }
}
} return false;
}
return false;
} [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsQualified(Mobile mob, MerchantTitle title) => IsQualified(mob, GetInfo(title));
public static bool IsQualified(Mobile mob, MerchantTitle title) => IsQualified(mob, GetInfo(title));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsQualified(Mobile mob, MerchantTitleInfo info) public static bool IsQualified(Mobile mob, MerchantTitleInfo info) => mob?.Skills[info.Skill].Value >= info?.Requirement;
{
if (mob == null || info == null)
{
return false;
}
return mob.Skills[info.Skill].Value >= info.Requirement;
}
}
} }

View file

@ -2,133 +2,174 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Server.Mobiles; using Server.Mobiles;
namespace Server.Factions namespace Server.Factions;
public class PlayerState : IComparable<PlayerState>
{ {
public class PlayerState : IComparable<PlayerState> private Town m_Finance;
private bool m_InvalidateRank = true;
private int m_KillPoints;
private MerchantTitle m_MerchantTitle;
private RankDefinition m_Rank;
private int m_RankIndex = -1;
private Town m_Sheriff;
public PlayerState(Mobile mob, Faction faction, List<PlayerState> owner)
{ {
private Town m_Finance; Mobile = mob;
Faction = faction;
Owner = owner;
private bool m_InvalidateRank = true; Attach();
private int m_KillPoints; Invalidate();
private MerchantTitle m_MerchantTitle; }
private RankDefinition m_Rank;
private int m_RankIndex = -1;
private Town m_Sheriff; public PlayerState(IGenericReader reader, Faction faction, List<PlayerState> owner)
{
Faction = faction;
Owner = owner;
public PlayerState(Mobile mob, Faction faction, List<PlayerState> owner) var version = reader.ReadEncodedInt();
switch (version)
{ {
Mobile = mob; case 1:
Faction = faction; {
Owner = owner; IsActive = reader.ReadBool();
LastHonorTime = reader.ReadDateTime();
goto case 0;
}
case 0:
{
Mobile = reader.ReadEntity<Mobile>();
Attach(); m_KillPoints = reader.ReadEncodedInt();
m_MerchantTitle = (MerchantTitle)reader.ReadEncodedInt();
Leaving = reader.ReadDateTime();
break;
}
}
Attach();
}
public Mobile Mobile { get; }
public Faction Faction { get; }
public List<PlayerState> Owner { get; }
public MerchantTitle MerchantTitle
{
get => m_MerchantTitle;
set
{
m_MerchantTitle = value;
Invalidate(); Invalidate();
} }
}
public PlayerState(IGenericReader reader, Faction faction, List<PlayerState> owner) public Town Sheriff
{
get => m_Sheriff;
set
{ {
Faction = faction; m_Sheriff = value;
Owner = owner; Invalidate();
var version = reader.ReadEncodedInt();
switch (version)
{
case 1:
{
IsActive = reader.ReadBool();
LastHonorTime = reader.ReadDateTime();
goto case 0;
}
case 0:
{
Mobile = reader.ReadEntity<Mobile>();
m_KillPoints = reader.ReadEncodedInt();
m_MerchantTitle = (MerchantTitle)reader.ReadEncodedInt();
Leaving = reader.ReadDateTime();
break;
}
}
Attach();
} }
}
public Mobile Mobile { get; } public Town Finance
{
public Faction Faction { get; } get => m_Finance;
set
public List<PlayerState> Owner { get; }
public MerchantTitle MerchantTitle
{ {
get => m_MerchantTitle; m_Finance = value;
set Invalidate();
{
m_MerchantTitle = value;
Invalidate();
}
} }
}
public Town Sheriff public List<SilverGivenEntry> SilverGiven { get; private set; }
public int KillPoints
{
get => m_KillPoints;
set
{ {
get => m_Sheriff; if (m_KillPoints != value)
set
{ {
m_Sheriff = value; if (value > m_KillPoints)
Invalidate();
}
}
public Town Finance
{
get => m_Finance;
set
{
m_Finance = value;
Invalidate();
}
}
public List<SilverGivenEntry> SilverGiven { get; private set; }
public int KillPoints
{
get => m_KillPoints;
set
{
if (m_KillPoints != value)
{ {
if (value > m_KillPoints) if (m_KillPoints <= 0)
{
if (value <= 0)
{
m_KillPoints = value;
Invalidate();
return;
}
Owner.Remove(this);
Owner.Insert(Faction.ZeroRankOffset, this);
m_RankIndex = Faction.ZeroRankOffset;
Faction.ZeroRankOffset++;
}
while (m_RankIndex - 1 >= 0)
{
var p = Owner[m_RankIndex - 1];
if (value > p.KillPoints)
{
Owner[m_RankIndex] = p;
Owner[m_RankIndex - 1] = this;
RankIndex--;
p.RankIndex++;
}
else
{
break;
}
}
}
else
{
if (value <= 0)
{ {
if (m_KillPoints <= 0) if (m_KillPoints <= 0)
{ {
if (value <= 0) m_KillPoints = value;
{ Invalidate();
m_KillPoints = value; return;
Invalidate();
return;
}
Owner.Remove(this);
Owner.Insert(Faction.ZeroRankOffset, this);
m_RankIndex = Faction.ZeroRankOffset;
Faction.ZeroRankOffset++;
} }
while (m_RankIndex - 1 >= 0) while (m_RankIndex + 1 < Faction.ZeroRankOffset)
{ {
var p = Owner[m_RankIndex - 1]; var p = Owner[m_RankIndex + 1];
if (value > p.KillPoints) Owner[m_RankIndex + 1] = this;
Owner[m_RankIndex] = p;
RankIndex++;
p.RankIndex--;
}
m_RankIndex = -1;
Faction.ZeroRankOffset--;
}
else
{
while (m_RankIndex + 1 < Faction.ZeroRankOffset)
{
var p = Owner[m_RankIndex + 1];
if (value < p.KillPoints)
{ {
Owner[m_RankIndex + 1] = this;
Owner[m_RankIndex] = p; Owner[m_RankIndex] = p;
Owner[m_RankIndex - 1] = this; RankIndex++;
RankIndex--; p.RankIndex--;
p.RankIndex++;
} }
else else
{ {
@ -136,173 +177,131 @@ namespace Server.Factions
} }
} }
} }
else
{
if (value <= 0)
{
if (m_KillPoints <= 0)
{
m_KillPoints = value;
Invalidate();
return;
}
while (m_RankIndex + 1 < Faction.ZeroRankOffset)
{
var p = Owner[m_RankIndex + 1];
Owner[m_RankIndex + 1] = this;
Owner[m_RankIndex] = p;
RankIndex++;
p.RankIndex--;
}
m_RankIndex = -1;
Faction.ZeroRankOffset--;
}
else
{
while (m_RankIndex + 1 < Faction.ZeroRankOffset)
{
var p = Owner[m_RankIndex + 1];
if (value < p.KillPoints)
{
Owner[m_RankIndex + 1] = this;
Owner[m_RankIndex] = p;
RankIndex++;
p.RankIndex--;
}
else
{
break;
}
}
}
}
m_KillPoints = value;
Invalidate();
}
}
}
public int RankIndex
{
get => m_RankIndex;
set
{
if (m_RankIndex != value)
{
m_RankIndex = value;
m_InvalidateRank = true;
}
}
}
public RankDefinition Rank
{
get
{
if (m_InvalidateRank)
{
var ranks = Faction.Definition.Ranks;
int percent;
if (Owner.Count == 1)
{
percent = 1000;
}
else if (m_RankIndex == -1)
{
percent = 0;
}
else
{
percent = (Faction.ZeroRankOffset - m_RankIndex) * 1000 / Faction.ZeroRankOffset;
}
for (var i = 0; i < ranks.Length; i++)
{
var check = ranks[i];
if (percent >= check.Required)
{
m_Rank = check;
m_InvalidateRank = false;
break;
}
}
Invalidate();
} }
return m_Rank; m_KillPoints = value;
Invalidate();
} }
} }
public DateTime LastHonorTime { get; set; }
public DateTime Leaving { get; set; }
public bool IsLeaving => Leaving > DateTime.MinValue;
public bool IsActive { get; set; }
public int CompareTo(PlayerState ps) => (ps?.m_KillPoints ?? 0) - m_KillPoints;
public bool CanGiveSilverTo(Mobile mob)
{
for (var i = 0; i < SilverGiven?.Count; ++i)
{
var sge = SilverGiven[i];
if (sge.IsExpired)
{
SilverGiven.RemoveAt(i--);
}
else if (sge.GivenTo == mob)
{
return false;
}
}
return true;
}
public void OnGivenSilverTo(Mobile mob)
{
SilverGiven ??= new List<SilverGivenEntry>();
SilverGiven.Add(new SilverGivenEntry(mob));
}
public void Invalidate()
{
(Mobile as PlayerMobile)?.InvalidateProperties();
}
public void Attach()
{
if (Mobile is PlayerMobile mobile)
{
mobile.FactionPlayerState = this;
}
}
public void Serialize(IGenericWriter writer)
{
writer.WriteEncodedInt(1); // version
writer.Write(IsActive);
writer.Write(LastHonorTime);
writer.Write(Mobile);
writer.WriteEncodedInt(m_KillPoints);
writer.WriteEncodedInt((int)m_MerchantTitle);
writer.Write(Leaving);
}
public static PlayerState Find(Mobile mob) => mob is PlayerMobile mobile ? mobile.FactionPlayerState : null;
} }
}
public int RankIndex
{
get => m_RankIndex;
set
{
if (m_RankIndex != value)
{
m_RankIndex = value;
m_InvalidateRank = true;
}
}
}
public RankDefinition Rank
{
get
{
if (m_InvalidateRank)
{
var ranks = Faction.Definition.Ranks;
int percent;
if (Owner.Count == 1)
{
percent = 1000;
}
else if (m_RankIndex == -1)
{
percent = 0;
}
else
{
percent = (Faction.ZeroRankOffset - m_RankIndex) * 1000 / Faction.ZeroRankOffset;
}
for (var i = 0; i < ranks.Length; i++)
{
var check = ranks[i];
if (percent >= check.Required)
{
m_Rank = check;
m_InvalidateRank = false;
break;
}
}
Invalidate();
}
return m_Rank;
}
}
public DateTime LastHonorTime { get; set; }
public DateTime Leaving { get; set; }
public bool IsLeaving => Leaving > DateTime.MinValue;
public bool IsActive { get; set; }
public int CompareTo(PlayerState ps) => (ps?.m_KillPoints ?? 0) - m_KillPoints;
public bool CanGiveSilverTo(Mobile mob)
{
for (var i = 0; i < SilverGiven?.Count; ++i)
{
var sge = SilverGiven[i];
if (sge.IsExpired)
{
SilverGiven.RemoveAt(i--);
}
else if (sge.GivenTo == mob)
{
return false;
}
}
return true;
}
public void OnGivenSilverTo(Mobile mob)
{
SilverGiven ??= [];
SilverGiven.Add(new SilverGivenEntry(mob));
}
public void Invalidate()
{
(Mobile as PlayerMobile)?.InvalidateProperties();
}
public void Attach()
{
if (Mobile is PlayerMobile mobile)
{
mobile.FactionPlayerState = this;
}
}
public void Serialize(IGenericWriter writer)
{
writer.WriteEncodedInt(1); // version
writer.Write(IsActive);
writer.Write(LastHonorTime);
writer.Write(Mobile);
writer.WriteEncodedInt(m_KillPoints);
writer.WriteEncodedInt((int)m_MerchantTitle);
writer.Write(Leaving);
}
public static PlayerState Find(Mobile mob) => mob is PlayerMobile mobile ? mobile.FactionPlayerState : null;
}

View file

@ -1,85 +1,84 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Server.Factions namespace Server.Factions;
public static class Reflector
{ {
public static class Reflector private static List<Town> m_Towns;
private static List<Faction> m_Factions;
public static List<Town> Towns
{ {
private static List<Town> m_Towns; get
private static List<Faction> m_Factions;
public static List<Town> Towns
{ {
get if (m_Towns == null)
{ {
if (m_Towns == null) ProcessTypes();
{
ProcessTypes();
}
return m_Towns;
} }
return m_Towns;
} }
}
public static List<Faction> Factions public static List<Faction> Factions
{
get
{ {
get if (m_Factions == null)
{ {
if (m_Factions == null) ProcessTypes();
{
ProcessTypes();
}
return m_Factions;
} }
return m_Factions;
} }
}
private static object Construct(Type type) private static object Construct(Type type)
{
try
{ {
try return type.CreateInstance<object>();
{
return type.CreateInstance<object>();
}
catch
{
return null;
}
} }
catch
private static void ProcessTypes()
{ {
m_Factions = new List<Faction>(); return null;
m_Towns = new List<Town>(); }
}
var asms = AssemblyHandler.Assemblies; private static void ProcessTypes()
{
m_Factions = [];
m_Towns = [];
for (var i = 0; i < asms.Length; ++i) var asms = AssemblyHandler.Assemblies;
for (var i = 0; i < asms.Length; ++i)
{
var asm = asms[i];
var tc = AssemblyHandler.GetTypeCache(asm);
var types = tc.Types;
for (var j = 0; j < types.Length; ++j)
{ {
var asm = asms[i]; var type = types[j];
var tc = AssemblyHandler.GetTypeCache(asm);
var types = tc.Types;
for (var j = 0; j < types.Length; ++j) if (type.IsSubclassOf(typeof(Faction)))
{ {
var type = types[j]; if (Construct(type) is Faction faction)
if (type.IsSubclassOf(typeof(Faction)))
{ {
if (Construct(type) is Faction faction) Faction.Factions.Add(faction);
{
Faction.Factions.Add(faction);
}
} }
else if (type.IsSubclassOf(typeof(Town))) }
else if (type.IsSubclassOf(typeof(Town)))
{
if (Construct(type) is Town town)
{ {
if (Construct(type) is Town town) Town.Towns.Add(town);
{
Town.Towns.Add(town);
}
} }
} }
} }
} }
} }
} }

View file

@ -1,21 +1,20 @@
using System; using System;
namespace Server.Factions namespace Server.Factions;
public class SilverGivenEntry
{ {
public class SilverGivenEntry public static readonly TimeSpan ExpirePeriod = TimeSpan.FromHours(3.0);
public SilverGivenEntry(Mobile givenTo)
{ {
public static readonly TimeSpan ExpirePeriod = TimeSpan.FromHours(3.0); GivenTo = givenTo;
TimeOfGift = Core.Now;
public SilverGivenEntry(Mobile givenTo)
{
GivenTo = givenTo;
TimeOfGift = Core.Now;
}
public Mobile GivenTo { get; }
public DateTime TimeOfGift { get; }
public bool IsExpired => TimeOfGift + ExpirePeriod < Core.Now;
} }
}
public Mobile GivenTo { get; }
public DateTime TimeOfGift { get; }
public bool IsExpired => TimeOfGift + ExpirePeriod < Core.Now;
}

View file

@ -1,45 +1,44 @@
using Server.Mobiles; using Server.Mobiles;
using Server.Regions; using Server.Regions;
namespace Server.Factions namespace Server.Factions;
public class StrongholdRegion : BaseRegion
{ {
public class StrongholdRegion : BaseRegion public StrongholdRegion(Faction faction) : base(
faction.Definition.FriendlyName,
Faction.Facet,
DefaultPriority,
faction.Definition.Stronghold.Area
)
{ {
public StrongholdRegion(Faction faction) : base( Faction = faction;
faction.Definition.FriendlyName,
Faction.Facet,
DefaultPriority,
faction.Definition.Stronghold.Area
)
{
Faction = faction;
Register(); Register();
}
public Faction Faction { get; set; }
public override bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation)
{
if (!base.OnMoveInto(m, d, newLocation, oldLocation))
{
return false;
}
if (m.AccessLevel >= AccessLevel.Counselor || Contains(oldLocation))
{
return true;
}
if (m is PlayerMobile pm && pm.DuelContext != null)
{
pm.SendMessage("You may not enter this area while participating in a duel or a tournament.");
return false;
}
return Faction.Find(m, true, true) != null;
}
public override bool AllowHousing(Mobile from, Point3D p) => false;
} }
}
public Faction Faction { get; set; }
public override bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation)
{
if (!base.OnMoveInto(m, d, newLocation, oldLocation))
{
return false;
}
if (m.AccessLevel >= AccessLevel.Counselor || Contains(oldLocation))
{
return true;
}
if (m is PlayerMobile pm && pm.DuelContext != null)
{
pm.SendMessage("You may not enter this area while participating in a duel or a tournament.");
return false;
}
return Faction.Find(m, true, true) != null;
}
public override bool AllowHousing(Mobile from, Point3D p) => false;
}

File diff suppressed because it is too large Load diff

View file

@ -1,140 +1,139 @@
using System; using System;
namespace Server.Factions namespace Server.Factions;
public class TownState
{ {
public class TownState private Mobile m_Finance;
private Mobile m_Sheriff;
public TownState(Town town) => Town = town;
public TownState(IGenericReader reader)
{ {
private Mobile m_Finance; var version = reader.ReadEncodedInt();
private Mobile m_Sheriff;
public TownState(Town town) => Town = town; switch (version)
public TownState(IGenericReader reader)
{ {
var version = reader.ReadEncodedInt(); case 3:
switch (version)
{
case 3:
{
LastIncome = reader.ReadDateTime();
goto case 2;
}
case 2:
{
Tax = reader.ReadEncodedInt();
LastTaxChange = reader.ReadDateTime();
goto case 1;
}
case 1:
{
Silver = reader.ReadEncodedInt();
goto case 0;
}
case 0:
{
Town = Town.ReadReference(reader);
Owner = Faction.ReadReference(reader);
m_Sheriff = reader.ReadEntity<Mobile>();
m_Finance = reader.ReadEntity<Mobile>();
Town.State = this;
break;
}
}
}
public Town Town { get; set; }
public Faction Owner { get; set; }
public Mobile Sheriff
{
get => m_Sheriff;
set
{
if (m_Sheriff != null)
{ {
var pl = PlayerState.Find(m_Sheriff); LastIncome = reader.ReadDateTime();
if (pl != null) goto case 2;
{
pl.Sheriff = null;
}
} }
case 2:
m_Sheriff = value;
if (m_Sheriff != null)
{ {
var pl = PlayerState.Find(m_Sheriff); Tax = reader.ReadEncodedInt();
LastTaxChange = reader.ReadDateTime();
if (pl != null) goto case 1;
{
pl.Sheriff = Town;
}
} }
} case 1:
}
public Mobile Finance
{
get => m_Finance;
set
{
if (m_Finance != null)
{ {
var pl = PlayerState.Find(m_Finance); Silver = reader.ReadEncodedInt();
if (pl != null) goto case 0;
{
pl.Finance = null;
}
} }
case 0:
m_Finance = value;
if (m_Finance != null)
{ {
var pl = PlayerState.Find(m_Finance); Town = Town.ReadReference(reader);
Owner = Faction.ReadReference(reader);
if (pl != null) m_Sheriff = reader.ReadEntity<Mobile>();
{ m_Finance = reader.ReadEntity<Mobile>();
pl.Finance = Town;
} Town.State = this;
break;
} }
}
}
public int Silver { get; set; }
public int Tax { get; set; }
public DateTime LastTaxChange { get; set; }
public DateTime LastIncome { get; set; }
public void Serialize(IGenericWriter writer)
{
writer.WriteEncodedInt(3); // version
writer.Write(LastIncome);
writer.WriteEncodedInt(Tax);
writer.Write(LastTaxChange);
writer.WriteEncodedInt(Silver);
Town.WriteReference(writer, Town);
Faction.WriteReference(writer, Owner);
writer.Write(m_Sheriff);
writer.Write(m_Finance);
} }
} }
}
public Town Town { get; set; }
public Faction Owner { get; set; }
public Mobile Sheriff
{
get => m_Sheriff;
set
{
if (m_Sheriff != null)
{
var pl = PlayerState.Find(m_Sheriff);
if (pl != null)
{
pl.Sheriff = null;
}
}
m_Sheriff = value;
if (m_Sheriff != null)
{
var pl = PlayerState.Find(m_Sheriff);
if (pl != null)
{
pl.Sheriff = Town;
}
}
}
}
public Mobile Finance
{
get => m_Finance;
set
{
if (m_Finance != null)
{
var pl = PlayerState.Find(m_Finance);
if (pl != null)
{
pl.Finance = null;
}
}
m_Finance = value;
if (m_Finance != null)
{
var pl = PlayerState.Find(m_Finance);
if (pl != null)
{
pl.Finance = Town;
}
}
}
}
public int Silver { get; set; }
public int Tax { get; set; }
public DateTime LastTaxChange { get; set; }
public DateTime LastIncome { get; set; }
public void Serialize(IGenericWriter writer)
{
writer.WriteEncodedInt(3); // version
writer.Write(LastIncome);
writer.WriteEncodedInt(Tax);
writer.Write(LastTaxChange);
writer.WriteEncodedInt(Silver);
Town.WriteReference(writer, Town);
Faction.WriteReference(writer, Owner);
writer.Write(m_Sheriff);
writer.Write(m_Finance);
}
}

View file

@ -1,29 +1,28 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace Server.Factions namespace Server.Factions;
public class VendorList
{ {
public class VendorList public VendorList(VendorDefinition definition)
{ {
public VendorList(VendorDefinition definition) Definition = definition;
Vendors = [];
}
public VendorDefinition Definition { get; }
public List<BaseFactionVendor> Vendors { get; }
public BaseFactionVendor Construct(Town town, Faction faction)
{
try
{ {
Definition = definition; return Definition.Type.CreateInstance<BaseFactionVendor>(town, faction);
Vendors = new List<BaseFactionVendor>();
} }
catch
public VendorDefinition Definition { get; }
public List<BaseFactionVendor> Vendors { get; }
public BaseFactionVendor Construct(Town town, Faction faction)
{ {
try return null;
{
return Definition.Type.CreateInstance<BaseFactionVendor>(town, faction);
}
catch
{
return null;
}
} }
} }
} }

View file

@ -25,37 +25,17 @@ namespace Server.Factions
public static FactionItemDefinition Identify(Item item) public static FactionItemDefinition Identify(Item item)
{ {
if (item is BaseArmor armor) return item switch
{ {
if (CraftResources.GetType(armor.Resource) == CraftResourceType.Leather) BaseArmor armor => CraftResources.GetType(armor.Resource) == CraftResourceType.Leather
{ ? m_LeatherArmor
return m_LeatherArmor; : m_MetalArmor,
} BaseRanged => m_RangedWeapon,
BaseWeapon => m_Weapon,
return m_MetalArmor; BaseClothing => m_Clothing,
} SpellScroll => m_Scroll,
_ => null
if (item is BaseRanged) };
{
return m_RangedWeapon;
}
if (item is BaseWeapon)
{
return m_Weapon;
}
if (item is BaseClothing)
{
return m_Clothing;
}
if (item is SpellScroll)
{
return m_Scroll;
}
return null;
} }
} }
} }

View file

@ -3,131 +3,130 @@ using Server.Gumps;
using Server.Mobiles; using Server.Mobiles;
using Server.Network; using Server.Network;
namespace Server.Factions namespace Server.Factions;
public class ElectionGump : FactionGump
{ {
public class ElectionGump : FactionGump private readonly Election m_Election;
private readonly PlayerMobile m_From;
public ElectionGump(PlayerMobile from, Election election) : base(50, 50)
{ {
private readonly Election m_Election; m_From = from;
private readonly PlayerMobile m_From; m_Election = election;
public ElectionGump(PlayerMobile from, Election election) : base(50, 50) AddPage(0);
AddBackground(0, 0, 420, 180, 5054);
AddBackground(10, 10, 400, 160, 3000);
AddHtmlText(20, 20, 380, 20, election.Faction.Definition.Header, false, false);
// NOTE: Gump not entirely OSI-accurate, intentionally so
switch (election.State)
{ {
m_From = from; case ElectionState.Pending:
m_Election = election; {
var toGo = election.LastStateTime + Election.PendingPeriod - Core.Now;
var days = (int)(toGo.TotalDays + 0.5);
AddPage(0); AddHtmlLocalized(20, 40, 380, 20, 1038034); // A new election campaign is pending
AddBackground(0, 0, 420, 180, 5054); if (days > 0)
AddBackground(10, 10, 400, 160, 3000);
AddHtmlText(20, 20, 380, 20, election.Faction.Definition.Header, false, false);
// NOTE: Gump not entirely OSI-accurate, intentionally so
switch (election.State)
{
case ElectionState.Pending:
{ {
var toGo = election.LastStateTime + Election.PendingPeriod - Core.Now; AddHtmlLocalized(20, 60, 280, 20, 1018062); // Days until next election :
var days = (int)(toGo.TotalDays + 0.5);
AddHtmlLocalized(20, 40, 380, 20, 1038034); // A new election campaign is pending
if (days > 0)
{
AddHtmlLocalized(20, 60, 280, 20, 1018062); // Days until next election :
AddLabel(300, 60, 0, days.ToString());
}
else
{
AddHtmlLocalized(20, 60, 280, 20, 1018059); // Election campaigning begins tonight.
}
break;
}
case ElectionState.Campaign:
{
var toGo = election.LastStateTime + Election.CampaignPeriod - Core.Now;
var days = (int)(toGo.TotalDays + 0.5);
AddHtmlLocalized(20, 40, 380, 20, 1018058); // There is an election campaign in progress.
if (days > 0)
{
AddHtmlLocalized(20, 60, 280, 20, 1038033); // Days to go:
AddLabel(300, 60, 0, days.ToString());
}
else
{
AddHtmlLocalized(20, 60, 280, 20, 1018061); // Campaign in progress. Voting begins tonight.
}
if (m_Election.CanBeCandidate(m_From))
{
AddButton(20, 110, 4005, 4007, 2);
AddHtmlLocalized(55, 110, 350, 20, 1011427); // CAMPAIGN FOR LEADERSHIP
}
else
{
var pl = PlayerState.Find(m_From);
if (pl == null || pl.Rank.Rank < Election.CandidateRank)
{
AddHtmlLocalized(20, 100, 380, 20, 1010118); // You must have a higher rank to run for office
}
}
break;
}
case ElectionState.Election:
{
var toGo = election.LastStateTime + Election.VotingPeriod - Core.Now;
var days = (int)Math.Ceiling(toGo.TotalDays);
AddHtmlLocalized(20, 40, 380, 20, 1018060); // There is an election vote in progress.
AddHtmlLocalized(20, 60, 280, 20, 1038033);
AddLabel(300, 60, 0, days.ToString()); AddLabel(300, 60, 0, days.ToString());
AddHtmlLocalized(55, 100, 380, 20, 1011428); // VOTE FOR LEADERSHIP
AddButton(20, 100, 4005, 4007, 1);
break;
} }
} else
{
AddHtmlLocalized(20, 60, 280, 20, 1018059); // Election campaigning begins tonight.
}
AddButton(20, 140, 4005, 4007, 0); break;
AddHtmlLocalized(55, 140, 350, 20, 1011012); // CANCEL }
case ElectionState.Campaign:
{
var toGo = election.LastStateTime + Election.CampaignPeriod - Core.Now;
var days = (int)(toGo.TotalDays + 0.5);
AddHtmlLocalized(20, 40, 380, 20, 1018058); // There is an election campaign in progress.
if (days > 0)
{
AddHtmlLocalized(20, 60, 280, 20, 1038033); // Days to go:
AddLabel(300, 60, 0, days.ToString());
}
else
{
AddHtmlLocalized(20, 60, 280, 20, 1018061); // Campaign in progress. Voting begins tonight.
}
if (m_Election.CanBeCandidate(m_From))
{
AddButton(20, 110, 4005, 4007, 2);
AddHtmlLocalized(55, 110, 350, 20, 1011427); // CAMPAIGN FOR LEADERSHIP
}
else
{
var pl = PlayerState.Find(m_From);
if (pl == null || pl.Rank.Rank < Election.CandidateRank)
{
AddHtmlLocalized(20, 100, 380, 20, 1010118); // You must have a higher rank to run for office
}
}
break;
}
case ElectionState.Election:
{
var toGo = election.LastStateTime + Election.VotingPeriod - Core.Now;
var days = (int)Math.Ceiling(toGo.TotalDays);
AddHtmlLocalized(20, 40, 380, 20, 1018060); // There is an election vote in progress.
AddHtmlLocalized(20, 60, 280, 20, 1038033);
AddLabel(300, 60, 0, days.ToString());
AddHtmlLocalized(55, 100, 380, 20, 1011428); // VOTE FOR LEADERSHIP
AddButton(20, 100, 4005, 4007, 1);
break;
}
} }
public override void OnResponse(NetState sender, in RelayInfo info) AddButton(20, 140, 4005, 4007, 0);
AddHtmlLocalized(55, 140, 350, 20, 1011012); // CANCEL
}
public override void OnResponse(NetState sender, in RelayInfo info)
{
switch (info.ButtonID)
{ {
switch (info.ButtonID) case 0: // back
{ {
case 0: // back m_From.SendGump(new FactionStoneGump(m_From, m_Election.Faction));
break;
}
case 1: // vote
{
if (m_Election.State == ElectionState.Election)
{ {
m_From.SendGump(new FactionStoneGump(m_From, m_Election.Faction)); m_From.SendGump(new VoteGump(m_From, m_Election));
break;
} }
case 1: // vote
{
if (m_Election.State == ElectionState.Election)
{
m_From.SendGump(new VoteGump(m_From, m_Election));
}
break; break;
} }
case 2: // campaign case 2: // campaign
{
if (m_Election.CanBeCandidate(m_From))
{ {
if (m_Election.CanBeCandidate(m_From)) m_Election.AddCandidate(m_From);
{
m_Election.AddCandidate(m_From);
}
break;
} }
}
break;
}
} }
} }
} }

View file

@ -3,202 +3,201 @@ using System.Net;
using Server.Gumps; using Server.Gumps;
using Server.Network; using Server.Network;
namespace Server.Factions namespace Server.Factions;
public class ElectionManagementGump : Gump
{ {
public class ElectionManagementGump : Gump public const int LabelColor = 0xFFFFFF;
private readonly Candidate m_Candidate;
private readonly Election m_Election;
private readonly int m_Page;
public ElectionManagementGump(Election election, Candidate candidate = null, int page = 0) : base(40, 40)
{ {
public const int LabelColor = 0xFFFFFF; m_Election = election;
private readonly Candidate m_Candidate; m_Candidate = candidate;
m_Page = page;
private readonly Election m_Election; AddPage(0);
private readonly int m_Page;
public ElectionManagementGump(Election election, Candidate candidate = null, int page = 0) : base(40, 40) if (candidate != null)
{ {
m_Election = election; AddBackground(0, 0, 448, 354, 9270);
m_Candidate = candidate; AddAlphaRegion(10, 10, 428, 334);
m_Page = page;
AddPage(0); AddHtml(10, 10, 428, 20, "Candidate Management".Center(LabelColor));
if (candidate != null) AddHtml(45, 35, 100, 20, "Player Name:".Color(LabelColor));
AddHtml(145, 35, 100, 20, (candidate.Mobile == null ? "null" : candidate.Mobile.Name).Color(LabelColor));
AddHtml(45, 55, 100, 20, "Vote Count:".Color(LabelColor));
AddHtml(145, 55, 100, 20, candidate.Votes.ToString().Color(LabelColor));
AddButton(12, 73, 4005, 4007, 1);
AddHtml(45, 75, 100, 20, "Drop Candidate".Color(LabelColor));
AddImageTiled(13, 99, 422, 242, 9264);
AddImageTiled(14, 100, 420, 240, 9274);
AddAlphaRegion(14, 100, 420, 240);
AddHtml(14, 100, 420, 20, "Voters".Center(LabelColor));
if (page > 0)
{ {
AddBackground(0, 0, 448, 354, 9270); AddButton(397, 104, 0x15E3, 0x15E7, 2);
AddAlphaRegion(10, 10, 428, 334);
AddHtml(10, 10, 428, 20, "Candidate Management".Center(LabelColor));
AddHtml(45, 35, 100, 20, "Player Name:".Color(LabelColor));
AddHtml(145, 35, 100, 20, (candidate.Mobile == null ? "null" : candidate.Mobile.Name).Color(LabelColor));
AddHtml(45, 55, 100, 20, "Vote Count:".Color(LabelColor));
AddHtml(145, 55, 100, 20, candidate.Votes.ToString().Color(LabelColor));
AddButton(12, 73, 4005, 4007, 1);
AddHtml(45, 75, 100, 20, "Drop Candidate".Color(LabelColor));
AddImageTiled(13, 99, 422, 242, 9264);
AddImageTiled(14, 100, 420, 240, 9274);
AddAlphaRegion(14, 100, 420, 240);
AddHtml(14, 100, 420, 20, "Voters".Center(LabelColor));
if (page > 0)
{
AddButton(397, 104, 0x15E3, 0x15E7, 2);
}
else
{
AddImage(397, 104, 0x25EA);
}
if ((page + 1) * 10 < candidate.Voters.Count)
{
AddButton(414, 104, 0x15E1, 0x15E5, 3);
}
else
{
AddImage(414, 104, 0x25E6);
}
AddHtml(14, 120, 30, 20, "DEL".Center(LabelColor));
AddHtml(47, 120, 150, 20, "Name".Color(LabelColor));
AddHtml(195, 120, 100, 20, "Address".Center(LabelColor));
AddHtml(295, 120, 80, 20, "Time".Center(LabelColor));
AddHtml(355, 120, 60, 20, "Legit".Center(LabelColor));
var idx = 0;
for (var i = page * 10; i >= 0 && i < candidate.Voters.Count && i < (page + 1) * 10; ++i, ++idx)
{
var voter = candidate.Voters[i];
AddButton(13, 138 + idx * 20, 4002, 4004, 4 + i);
var fields = voter.AcquireFields();
var x = 45;
for (var j = 0; j < fields.Length; ++j)
{
var obj = fields[j];
if (obj is Mobile mobile)
{
AddHtml(x + 2, 140 + idx * 20, 150, 20, mobile.Name.Color(LabelColor));
x += 150;
}
else if (obj is IPAddress)
{
AddHtml(x, 140 + idx * 20, 100, 20, obj.ToString().Center(LabelColor));
x += 100;
}
else if (obj is DateTime time)
{
AddHtml(
x,
140 + idx * 20,
80,
20,
FormatTimeSpan(time - election.LastStateTime).Center(LabelColor)
);
x += 80;
}
else if (obj is int i1)
{
AddHtml(x, 140 + idx * 20, 60, 20, $"{i1}%".Center(LabelColor));
x += 60;
}
}
}
} }
else else
{ {
AddBackground(0, 0, 288, 334, 9270); AddImage(397, 104, 0x25EA);
AddAlphaRegion(10, 10, 268, 314); }
AddHtml(10, 10, 268, 20, "Election Management".Center(LabelColor)); if ((page + 1) * 10 < candidate.Voters.Count)
{
AddButton(414, 104, 0x15E1, 0x15E5, 3);
}
else
{
AddImage(414, 104, 0x25E6);
}
AddHtml(45, 35, 100, 20, "Current State:".Color(LabelColor)); AddHtml(14, 120, 30, 20, "DEL".Center(LabelColor));
AddHtml(145, 35, 100, 20, election.State.ToString().Color(LabelColor)); AddHtml(47, 120, 150, 20, "Name".Color(LabelColor));
AddHtml(195, 120, 100, 20, "Address".Center(LabelColor));
AddHtml(295, 120, 80, 20, "Time".Center(LabelColor));
AddHtml(355, 120, 60, 20, "Legit".Center(LabelColor));
AddButton(12, 53, 4005, 4007, 1); var idx = 0;
AddHtml(45, 55, 100, 20, "Transition Time:".Color(LabelColor));
AddHtml(145, 55, 100, 20, FormatTimeSpan(election.NextStateTime).Color(LabelColor));
AddImageTiled(13, 79, 262, 242, 9264); for (var i = page * 10; i >= 0 && i < candidate.Voters.Count && i < (page + 1) * 10; ++i, ++idx)
AddImageTiled(14, 80, 260, 240, 9274); {
AddAlphaRegion(14, 80, 260, 240); var voter = candidate.Voters[i];
AddHtml(14, 80, 260, 20, "Candidates".Center(LabelColor)); AddButton(13, 138 + idx * 20, 4002, 4004, 4 + i);
AddHtml(14, 100, 30, 20, "-->".Center(LabelColor));
AddHtml(47, 100, 150, 20, "Name".Color(LabelColor));
AddHtml(195, 100, 80, 20, "Votes".Center(LabelColor));
for (var i = 0; i < election.Candidates.Count; ++i) var fields = voter.AcquireFields();
var x = 45;
for (var j = 0; j < fields.Length; ++j)
{ {
var cd = election.Candidates[i]; var obj = fields[j];
var mob = cd.Mobile;
if (mob == null) if (obj is Mobile mobile)
{ {
continue; AddHtml(x + 2, 140 + idx * 20, 150, 20, mobile.Name.Color(LabelColor));
x += 150;
}
else if (obj is IPAddress)
{
AddHtml(x, 140 + idx * 20, 100, 20, obj.ToString().Center(LabelColor));
x += 100;
}
else if (obj is DateTime time)
{
AddHtml(
x,
140 + idx * 20,
80,
20,
FormatTimeSpan(time - election.LastStateTime).Center(LabelColor)
);
x += 80;
}
else if (obj is int i1)
{
AddHtml(x, 140 + idx * 20, 60, 20, $"{i1}%".Center(LabelColor));
x += 60;
} }
AddButton(13, 118 + i * 20, 4005, 4007, 2 + i);
AddHtml(47, 120 + i * 20, 150, 20, mob.Name.Color(LabelColor));
AddHtml(195, 120 + i * 20, 80, 20, cd.Votes.ToString().Center(LabelColor));
} }
} }
} }
else
public static string FormatTimeSpan(TimeSpan ts) =>
$"{ts.Days:D2}:{ts.Hours % 24:D2}:{ts.Minutes % 60:D2}:{ts.Seconds % 60:D2}";
public override void OnResponse(NetState sender, in RelayInfo info)
{ {
var from = sender.Mobile; AddBackground(0, 0, 288, 334, 9270);
var bid = info.ButtonID; AddAlphaRegion(10, 10, 268, 314);
if (m_Candidate == null) AddHtml(10, 10, 268, 20, "Election Management".Center(LabelColor));
AddHtml(45, 35, 100, 20, "Current State:".Color(LabelColor));
AddHtml(145, 35, 100, 20, election.State.ToString().Color(LabelColor));
AddButton(12, 53, 4005, 4007, 1);
AddHtml(45, 55, 100, 20, "Transition Time:".Color(LabelColor));
AddHtml(145, 55, 100, 20, FormatTimeSpan(election.NextStateTime).Color(LabelColor));
AddImageTiled(13, 79, 262, 242, 9264);
AddImageTiled(14, 80, 260, 240, 9274);
AddAlphaRegion(14, 80, 260, 240);
AddHtml(14, 80, 260, 20, "Candidates".Center(LabelColor));
AddHtml(14, 100, 30, 20, "-->".Center(LabelColor));
AddHtml(47, 100, 150, 20, "Name".Color(LabelColor));
AddHtml(195, 100, 80, 20, "Votes".Center(LabelColor));
for (var i = 0; i < election.Candidates.Count; ++i)
{ {
if (bid > 1) var cd = election.Candidates[i];
var mob = cd.Mobile;
if (mob == null)
{ {
bid -= 2; continue;
if (bid < m_Election.Candidates.Count)
{
from.SendGump(new ElectionManagementGump(m_Election, m_Election.Candidates[bid]));
}
} }
}
else if (bid == 0)
{
from.SendGump(new ElectionManagementGump(m_Election));
}
else if (bid == 1)
{
m_Election.RemoveCandidate(m_Candidate.Mobile);
from.SendGump(new ElectionManagementGump(m_Election));
}
else if (bid == 2 && m_Page > 0)
{
from.SendGump(new ElectionManagementGump(m_Election, m_Candidate, m_Page - 1));
}
else if (bid == 3 && (m_Page + 1) * 10 < m_Candidate.Voters.Count)
{
from.SendGump(new ElectionManagementGump(m_Election, m_Candidate, m_Page + 1));
}
else
{
bid -= 4;
if (bid >= 0 && bid < m_Candidate.Voters.Count) AddButton(13, 118 + i * 20, 4005, 4007, 2 + i);
{ AddHtml(47, 120 + i * 20, 150, 20, mob.Name.Color(LabelColor));
m_Candidate.Voters.RemoveAt(bid); AddHtml(195, 120 + i * 20, 80, 20, cd.Votes.ToString().Center(LabelColor));
from.SendGump(new ElectionManagementGump(m_Election, m_Candidate, m_Page));
}
} }
} }
} }
}
public static string FormatTimeSpan(TimeSpan ts) =>
$"{ts.Days:D2}:{ts.Hours % 24:D2}:{ts.Minutes % 60:D2}:{ts.Seconds % 60:D2}";
public override void OnResponse(NetState sender, in RelayInfo info)
{
var from = sender.Mobile;
var bid = info.ButtonID;
if (m_Candidate == null)
{
if (bid > 1)
{
bid -= 2;
if (bid < m_Election.Candidates.Count)
{
from.SendGump(new ElectionManagementGump(m_Election, m_Election.Candidates[bid]));
}
}
}
else if (bid == 0)
{
from.SendGump(new ElectionManagementGump(m_Election));
}
else if (bid == 1)
{
m_Election.RemoveCandidate(m_Candidate.Mobile);
from.SendGump(new ElectionManagementGump(m_Election));
}
else if (bid == 2 && m_Page > 0)
{
from.SendGump(new ElectionManagementGump(m_Election, m_Candidate, m_Page - 1));
}
else if (bid == 3 && (m_Page + 1) * 10 < m_Candidate.Voters.Count)
{
from.SendGump(new ElectionManagementGump(m_Election, m_Candidate, m_Page + 1));
}
else
{
bid -= 4;
if (bid >= 0 && bid < m_Candidate.Voters.Count)
{
m_Candidate.Voters.RemoveAt(bid);
from.SendGump(new ElectionManagementGump(m_Election, m_Candidate, m_Page));
}
}
}
}

View file

@ -1,44 +1,43 @@
using Server.Gumps; using Server.Gumps;
namespace Server.Factions namespace Server.Factions;
public abstract class FactionGump : Gump
{ {
public abstract class FactionGump : Gump public FactionGump(int x, int y) : base(x, y)
{ {
public FactionGump(int x, int y) : base(x, y) }
public virtual int ButtonTypes => 10;
public int ToButtonID(int type, int index) => 1 + index * ButtonTypes + type;
public bool FromButtonID(int buttonID, out int type, out int index)
{
var offset = buttonID - 1;
if (offset >= 0)
{ {
type = offset % ButtonTypes;
index = offset / ButtonTypes;
return true;
} }
public virtual int ButtonTypes => 10; type = index = 0;
return false;
}
public int ToButtonID(int type, int index) => 1 + index * ButtonTypes + type; public static bool Exists(Mobile mob) => mob.HasGump<FactionGump>();
public bool FromButtonID(int buttonID, out int type, out int index) public void AddHtmlText(int x, int y, int width, int height, TextDefinition text, bool back, bool scroll)
{
if (text?.Number > 0)
{ {
var offset = buttonID - 1; AddHtmlLocalized(x, y, width, height, text.Number, back, scroll);
if (offset >= 0)
{
type = offset % ButtonTypes;
index = offset / ButtonTypes;
return true;
}
type = index = 0;
return false;
} }
else if (text?.String != null)
public static bool Exists(Mobile mob) => mob.HasGump<FactionGump>();
public void AddHtmlText(int x, int y, int width, int height, TextDefinition text, bool back, bool scroll)
{ {
if (text?.Number > 0) AddHtml(x, y, width, height, text.String, back, scroll);
{
AddHtmlLocalized(x, y, width, height, text.Number, back, scroll);
}
else if (text?.String != null)
{
AddHtml(x, y, width, height, text.String, back, scroll);
}
} }
} }
} }

View file

@ -3,112 +3,111 @@ using Server.Gumps;
using Server.Items; using Server.Items;
using Server.Network; using Server.Network;
namespace Server.Factions namespace Server.Factions;
public class FactionImbueGump : FactionGump
{ {
public class FactionImbueGump : FactionGump private readonly CraftSystem m_CraftSystem;
private readonly FactionItemDefinition m_Definition;
private readonly Faction m_Faction;
private readonly Item m_Item;
private readonly Mobile m_Mobile;
private readonly TextDefinition m_Notice;
private readonly BaseTool m_Tool;
public FactionImbueGump(
int quality, Item item, Mobile from, CraftSystem craftSystem, BaseTool tool, TextDefinition notice,
int availableSilver, Faction faction, FactionItemDefinition def
) : base(100, 200)
{ {
private readonly CraftSystem m_CraftSystem; m_Item = item;
m_Mobile = from;
m_Faction = faction;
m_CraftSystem = craftSystem;
m_Tool = tool;
m_Notice = notice;
m_Definition = def;
private readonly FactionItemDefinition m_Definition; AddPage(0);
private readonly Faction m_Faction;
private readonly Item m_Item;
private readonly Mobile m_Mobile;
private readonly TextDefinition m_Notice;
private readonly BaseTool m_Tool;
public FactionImbueGump( AddBackground(0, 0, 320, 270, 5054);
int quality, Item item, Mobile from, CraftSystem craftSystem, BaseTool tool, TextDefinition notice, AddBackground(10, 10, 300, 250, 3000);
int availableSilver, Faction faction, FactionItemDefinition def
) : base(100, 200) AddHtmlLocalized(20, 20, 210, 25, 1011569); // Imbue with Faction properties?
AddHtmlLocalized(20, 60, 170, 25, 1018302); // Item quality:
AddHtmlLocalized(175, 60, 100, 25, 1018305 - quality); // Exceptional, Average, Low
AddHtmlLocalized(20, 80, 170, 25, 1011572); // Item Cost :
AddLabel(175, 80, 0x34, def.SilverCost.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 100, 170, 25, 1011573); // Your Silver :
AddLabel(175, 100, 0x34, availableSilver.ToString("N0")); // NOTE: Added 'N0'
AddRadio(20, 140, 210, 211, true, 1);
AddLabel(55, 140, m_Faction.Definition.HuePrimary - 1, "*****");
AddHtmlLocalized(150, 140, 150, 25, 1011570); // Primary Color
AddRadio(20, 160, 210, 211, false, 2);
AddLabel(55, 160, m_Faction.Definition.HueSecondary - 1, "*****");
AddHtmlLocalized(150, 160, 150, 25, 1011571); // Secondary Color
AddHtmlLocalized(55, 200, 200, 25, 1011011); // CONTINUE
AddButton(20, 200, 4005, 4007, 1);
AddHtmlLocalized(55, 230, 200, 25, 1011012); // CANCEL
AddButton(20, 230, 4005, 4007, 0);
}
public override void OnResponse(NetState sender, in RelayInfo info)
{
if (info.ButtonID == 1)
{ {
m_Item = item; var pack = m_Mobile.Backpack;
m_Mobile = from;
m_Faction = faction;
m_CraftSystem = craftSystem;
m_Tool = tool;
m_Notice = notice;
m_Definition = def;
AddPage(0); if (pack != null && m_Item.IsChildOf(pack))
AddBackground(0, 0, 320, 270, 5054);
AddBackground(10, 10, 300, 250, 3000);
AddHtmlLocalized(20, 20, 210, 25, 1011569); // Imbue with Faction properties?
AddHtmlLocalized(20, 60, 170, 25, 1018302); // Item quality:
AddHtmlLocalized(175, 60, 100, 25, 1018305 - quality); // Exceptional, Average, Low
AddHtmlLocalized(20, 80, 170, 25, 1011572); // Item Cost :
AddLabel(175, 80, 0x34, def.SilverCost.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 100, 170, 25, 1011573); // Your Silver :
AddLabel(175, 100, 0x34, availableSilver.ToString("N0")); // NOTE: Added 'N0'
AddRadio(20, 140, 210, 211, true, 1);
AddLabel(55, 140, m_Faction.Definition.HuePrimary - 1, "*****");
AddHtmlLocalized(150, 140, 150, 25, 1011570); // Primary Color
AddRadio(20, 160, 210, 211, false, 2);
AddLabel(55, 160, m_Faction.Definition.HueSecondary - 1, "*****");
AddHtmlLocalized(150, 160, 150, 25, 1011571); // Secondary Color
AddHtmlLocalized(55, 200, 200, 25, 1011011); // CONTINUE
AddButton(20, 200, 4005, 4007, 1);
AddHtmlLocalized(55, 230, 200, 25, 1011012); // CANCEL
AddButton(20, 230, 4005, 4007, 0);
}
public override void OnResponse(NetState sender, in RelayInfo info)
{
if (info.ButtonID == 1)
{ {
var pack = m_Mobile.Backpack; if (pack.ConsumeTotal(typeof(Silver), m_Definition.SilverCost))
if (pack != null && m_Item.IsChildOf(pack))
{ {
if (pack.ConsumeTotal(typeof(Silver), m_Definition.SilverCost)) int hue;
if (m_Item is SpellScroll)
{ {
int hue; hue = 0;
}
if (m_Item is SpellScroll) else if (info.IsSwitched(1))
{ {
hue = 0; hue = m_Faction.Definition.HuePrimary;
}
else if (info.IsSwitched(1))
{
hue = m_Faction.Definition.HuePrimary;
}
else
{
hue = m_Faction.Definition.HueSecondary;
}
FactionItem.Imbue(m_Item, m_Faction, true, hue);
} }
else else
{ {
m_Mobile.SendLocalizedMessage(1042204); // You do not have enough silver. hue = m_Faction.Definition.HueSecondary;
} }
}
}
if (m_Tool?.Deleted == false && m_Tool.UsesRemaining > 0) FactionItem.Imbue(m_Item, m_Faction, true, hue);
{
m_Mobile.SendGump(new CraftGump(m_Mobile, m_CraftSystem, m_Tool, m_Notice));
}
else if (m_Notice != null)
{
if (m_Notice.Number > 0)
{
m_Mobile.SendLocalizedMessage(m_Notice.Number);
} }
else else
{ {
m_Mobile.SendMessage(m_Notice.String); m_Mobile.SendLocalizedMessage(1042204); // You do not have enough silver.
} }
} }
} }
if (m_Tool?.Deleted == false && m_Tool.UsesRemaining > 0)
{
m_Mobile.SendGump(new CraftGump(m_Mobile, m_CraftSystem, m_Tool, m_Notice));
}
else if (m_Notice != null)
{
if (m_Notice.Number > 0)
{
m_Mobile.SendLocalizedMessage(m_Notice.Number);
}
else
{
m_Mobile.SendMessage(m_Notice.String);
}
}
} }
} }

View file

@ -2,364 +2,363 @@ using Server.Gumps;
using Server.Mobiles; using Server.Mobiles;
using Server.Network; using Server.Network;
namespace Server.Factions namespace Server.Factions;
public class FactionStoneGump : FactionGump
{ {
public class FactionStoneGump : FactionGump private readonly Faction m_Faction;
private readonly PlayerMobile m_From;
public FactionStoneGump(PlayerMobile from, Faction faction) : base(20, 30)
{ {
private readonly Faction m_Faction; m_From = from;
private readonly PlayerMobile m_From; m_Faction = faction;
public FactionStoneGump(PlayerMobile from, Faction faction) : base(20, 30) AddPage(0);
AddBackground(0, 0, 550, 440, 5054);
AddBackground(10, 10, 530, 420, 3000);
AddPage(1);
AddHtmlText(20, 30, 510, 20, faction.Definition.Header, false, false);
AddHtmlLocalized(20, 60, 100, 20, 1011429); // Led By :
AddHtml(125, 60, 200, 20, faction.Commander != null ? faction.Commander.Name : "Nobody");
AddHtmlLocalized(20, 80, 100, 20, 1011457); // Tithe rate :
if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0)
{ {
m_From = from; AddHtmlLocalized(125, 80, 350, 20, 1011480 + faction.Tithe / 10);
m_Faction = faction; }
else
{
AddHtml(125, 80, 350, 20, $"{faction.Tithe}%");
}
AddPage(0); AddHtmlLocalized(20, 100, 100, 20, 1011458); // Traps placed :
AddHtml(125, 100, 50, 20, faction.Traps.Count.ToString());
AddBackground(0, 0, 550, 440, 5054); AddHtmlLocalized(55, 225, 200, 20, 1011428); // VOTE FOR LEADERSHIP
AddBackground(10, 10, 530, 420, 3000); AddButton(20, 225, 4005, 4007, ToButtonID(0, 0));
AddPage(1); AddHtmlLocalized(55, 150, 100, 20, 1011430); // CITY STATUS
AddButton(20, 150, 4005, 4007, 0, GumpButtonType.Page, 2);
AddHtmlText(20, 30, 510, 20, faction.Definition.Header, false, false); AddHtmlLocalized(55, 175, 100, 20, 1011444); // STATISTICS
AddButton(20, 175, 4005, 4007, 0, GumpButtonType.Page, 4);
AddHtmlLocalized(20, 60, 100, 20, 1011429); // Led By : var isMerchantQualified = MerchantTitles.HasMerchantQualifications(from);
AddHtml(125, 60, 200, 20, faction.Commander != null ? faction.Commander.Name : "Nobody");
AddHtmlLocalized(20, 80, 100, 20, 1011457); // Tithe rate : var pl = PlayerState.Find(from);
if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0)
if (pl != null && pl.MerchantTitle != MerchantTitle.None)
{
AddHtmlLocalized(55, 200, 250, 20, 1011460); // UNDECLARE FACTION MERCHANT
AddButton(20, 200, 4005, 4007, ToButtonID(1, 0));
}
else if (isMerchantQualified)
{
AddHtmlLocalized(55, 200, 250, 20, 1011459); // DECLARE FACTION MERCHANT
AddButton(20, 200, 4005, 4007, 0, GumpButtonType.Page, 5);
}
else
{
AddHtmlLocalized(55, 200, 250, 20, 1011467); // MERCHANT OPTIONS
AddImage(20, 200, 4020);
}
AddHtmlLocalized(55, 250, 300, 20, 1011461); // COMMANDER OPTIONS
if (faction.IsCommander(from))
{
AddButton(20, 250, 4005, 4007, 0, GumpButtonType.Page, 6);
}
else
{
AddImage(20, 250, 4020);
}
AddHtmlLocalized(55, 275, 300, 20, 1011426); // LEAVE THIS FACTION
AddButton(20, 275, 4005, 4007, ToButtonID(0, 1));
AddHtmlLocalized(55, 300, 200, 20, 1011441); // EXIT
AddButton(20, 300, 4005, 4007, 0);
AddPage(2);
AddHtmlLocalized(20, 30, 250, 20, 1011430); // CITY STATUS
var towns = Town.Towns;
for (var i = 0; i < towns.Count; ++i)
{
var town = towns[i];
AddHtmlText(40, 55 + i * 30, 150, 20, town.Definition.TownName, false, false);
if (town.Owner == null)
{ {
AddHtmlLocalized(125, 80, 350, 20, 1011480 + faction.Tithe / 10); AddHtmlLocalized(200, 55 + i * 30, 150, 20, 1011462); // : Neutral
} }
else else
{ {
AddHtml(125, 80, 350, 20, $"{faction.Tithe}%"); AddHtmlLocalized(200, 55 + i * 30, 150, 20, town.Owner.Definition.OwnerLabel);
BaseMonolith monolith = town.Monolith;
AddImage(20, 60 + i * 30, monolith?.Sigil?.IsPurifying == true ? 0x938 : 0x939);
} }
}
AddHtmlLocalized(20, 100, 100, 20, 1011458); // Traps placed : AddImage(20, 300, 2361);
AddHtml(125, 100, 50, 20, faction.Traps.Count.ToString()); AddHtmlLocalized(45, 295, 300, 20, 1011491); // sigil may be recaptured
AddHtmlLocalized(55, 225, 200, 20, 1011428); // VOTE FOR LEADERSHIP AddImage(20, 320, 2360);
AddButton(20, 225, 4005, 4007, ToButtonID(0, 0)); AddHtmlLocalized(45, 315, 300, 20, 1011492); // sigil may not be recaptured
AddHtmlLocalized(55, 150, 100, 20, 1011430); // CITY STATUS AddHtmlLocalized(55, 350, 100, 20, 1011447); // BACK
AddButton(20, 150, 4005, 4007, 0, GumpButtonType.Page, 2); AddButton(20, 350, 4005, 4007, 0, GumpButtonType.Page, 1);
AddHtmlLocalized(55, 175, 100, 20, 1011444); // STATISTICS AddPage(4);
AddButton(20, 175, 4005, 4007, 0, GumpButtonType.Page, 4);
var isMerchantQualified = MerchantTitles.HasMerchantQualifications(from); AddHtmlLocalized(20, 30, 150, 20, 1011444); // STATISTICS
var pl = PlayerState.Find(from); AddHtmlLocalized(20, 100, 100, 20, 1011445); // Name :
AddHtml(120, 100, 150, 20, from.Name);
if (pl != null && pl.MerchantTitle != MerchantTitle.None) AddHtmlLocalized(20, 130, 100, 20, 1018064); // score :
AddHtml(120, 130, 100, 20, (pl?.KillPoints ?? 0).ToString());
AddHtmlLocalized(20, 160, 100, 20, 1011446); // Rank :
AddHtml(120, 160, 100, 20, (pl?.Rank.Rank ?? 0).ToString());
AddHtmlLocalized(55, 250, 100, 20, 1011447); // BACK
AddButton(20, 250, 4005, 4007, 0, GumpButtonType.Page, 1);
if ((pl == null || pl.MerchantTitle == MerchantTitle.None) && isMerchantQualified)
{
AddPage(5);
AddHtmlLocalized(20, 30, 250, 20, 1011467); // MERCHANT OPTIONS
AddHtmlLocalized(20, 80, 300, 20, 1011473); // Select the title you wish to display
var infos = MerchantTitles.Info;
for (var i = 0; i < infos.Length; ++i)
{ {
AddHtmlLocalized(55, 200, 250, 20, 1011460); // UNDECLARE FACTION MERCHANT var info = infos[i];
AddButton(20, 200, 4005, 4007, ToButtonID(1, 0));
}
else if (isMerchantQualified)
{
AddHtmlLocalized(55, 200, 250, 20, 1011459); // DECLARE FACTION MERCHANT
AddButton(20, 200, 4005, 4007, 0, GumpButtonType.Page, 5);
}
else
{
AddHtmlLocalized(55, 200, 250, 20, 1011467); // MERCHANT OPTIONS
AddImage(20, 200, 4020);
}
AddHtmlLocalized(55, 250, 300, 20, 1011461); // COMMANDER OPTIONS if (MerchantTitles.IsQualified(from, info))
if (faction.IsCommander(from))
{
AddButton(20, 250, 4005, 4007, 0, GumpButtonType.Page, 6);
}
else
{
AddImage(20, 250, 4020);
}
AddHtmlLocalized(55, 275, 300, 20, 1011426); // LEAVE THIS FACTION
AddButton(20, 275, 4005, 4007, ToButtonID(0, 1));
AddHtmlLocalized(55, 300, 200, 20, 1011441); // EXIT
AddButton(20, 300, 4005, 4007, 0);
AddPage(2);
AddHtmlLocalized(20, 30, 250, 20, 1011430); // CITY STATUS
var towns = Town.Towns;
for (var i = 0; i < towns.Count; ++i)
{
var town = towns[i];
AddHtmlText(40, 55 + i * 30, 150, 20, town.Definition.TownName, false, false);
if (town.Owner == null)
{ {
AddHtmlLocalized(200, 55 + i * 30, 150, 20, 1011462); // : Neutral AddButton(20, 100 + i * 30, 4005, 4007, ToButtonID(1, i + 1));
} }
else else
{ {
AddHtmlLocalized(200, 55 + i * 30, 150, 20, town.Owner.Definition.OwnerLabel); AddImage(20, 100 + i * 30, 4020);
BaseMonolith monolith = town.Monolith;
AddImage(20, 60 + i * 30, monolith?.Sigil?.IsPurifying == true ? 0x938 : 0x939);
} }
AddHtmlText(55, 100 + i * 30, 200, 20, info.Label, false, false);
} }
AddImage(20, 300, 2361); AddHtmlLocalized(55, 340, 100, 20, 1011447); // BACK
AddHtmlLocalized(45, 295, 300, 20, 1011491); // sigil may be recaptured AddButton(20, 340, 4005, 4007, 0, GumpButtonType.Page, 1);
}
AddImage(20, 320, 2360); if (faction.IsCommander(from))
AddHtmlLocalized(45, 315, 300, 20, 1011492); // sigil may not be recaptured {
AddPage(6);
AddHtmlLocalized(55, 350, 100, 20, 1011447); // BACK AddHtmlLocalized(20, 30, 200, 20, 1011461); // COMMANDER OPTIONS
AddButton(20, 350, 4005, 4007, 0, GumpButtonType.Page, 1);
AddPage(4); AddHtmlLocalized(20, 70, 120, 20, 1011457); // Tithe rate :
if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0)
AddHtmlLocalized(20, 30, 150, 20, 1011444); // STATISTICS
AddHtmlLocalized(20, 100, 100, 20, 1011445); // Name :
AddHtml(120, 100, 150, 20, from.Name);
AddHtmlLocalized(20, 130, 100, 20, 1018064); // score :
AddHtml(120, 130, 100, 20, (pl?.KillPoints ?? 0).ToString());
AddHtmlLocalized(20, 160, 100, 20, 1011446); // Rank :
AddHtml(120, 160, 100, 20, (pl?.Rank.Rank ?? 0).ToString());
AddHtmlLocalized(55, 250, 100, 20, 1011447); // BACK
AddButton(20, 250, 4005, 4007, 0, GumpButtonType.Page, 1);
if ((pl == null || pl.MerchantTitle == MerchantTitle.None) && isMerchantQualified)
{ {
AddPage(5); AddHtmlLocalized(140, 70, 250, 20, 1011480 + faction.Tithe / 10);
}
else
{
AddHtml(140, 70, 250, 20, $"{faction.Tithe}%");
}
AddHtmlLocalized(20, 30, 250, 20, 1011467); // MERCHANT OPTIONS AddHtmlLocalized(20, 100, 120, 20, 1011474); // Silver available :
AddHtml(140, 100, 50, 20, faction.Silver.ToString("N0")); // NOTE: Added 'N0' formatting
AddHtmlLocalized(20, 80, 300, 20, 1011473); // Select the title you wish to display AddHtmlLocalized(55, 130, 200, 20, 1011478); // CHANGE TITHE RATE
AddButton(20, 130, 4005, 4007, 0, GumpButtonType.Page, 8);
var infos = MerchantTitles.Info; AddHtmlLocalized(55, 160, 200, 20, 1018301); // TRANSFER SILVER
if (faction.Silver >= 10000)
{
AddButton(20, 160, 4005, 4007, 0, GumpButtonType.Page, 7);
}
else
{
AddImage(20, 160, 4020);
}
for (var i = 0; i < infos.Length; ++i) AddHtmlLocalized(55, 310, 100, 20, 1011447); // BACK
AddButton(20, 310, 4005, 4007, 0, GumpButtonType.Page, 1);
if (faction.Silver >= 10000)
{
AddPage(7);
AddHtmlLocalized(20, 30, 250, 20, 1011476); // TOWN FINANCE
AddHtmlLocalized(20, 50, 400, 20, 1011477); // Select a town to transfer 10000 silver to
for (var i = 0; i < towns.Count; ++i)
{ {
var info = infos[i]; var town = towns[i];
if (MerchantTitles.IsQualified(from, info)) AddHtmlText(55, 75 + i * 30, 200, 20, town.Definition.TownName, false, false);
if (town.Owner == faction)
{ {
AddButton(20, 100 + i * 30, 4005, 4007, ToButtonID(1, i + 1)); AddButton(20, 75 + i * 30, 4005, 4007, ToButtonID(2, i));
} }
else else
{ {
AddImage(20, 100 + i * 30, 4020); AddImage(20, 75 + i * 30, 4020);
} }
AddHtmlText(55, 100 + i * 30, 200, 20, info.Label, false, false);
}
AddHtmlLocalized(55, 340, 100, 20, 1011447); // BACK
AddButton(20, 340, 4005, 4007, 0, GumpButtonType.Page, 1);
}
if (faction.IsCommander(from))
{
AddPage(6);
AddHtmlLocalized(20, 30, 200, 20, 1011461); // COMMANDER OPTIONS
AddHtmlLocalized(20, 70, 120, 20, 1011457); // Tithe rate :
if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0)
{
AddHtmlLocalized(140, 70, 250, 20, 1011480 + faction.Tithe / 10);
}
else
{
AddHtml(140, 70, 250, 20, $"{faction.Tithe}%");
}
AddHtmlLocalized(20, 100, 120, 20, 1011474); // Silver available :
AddHtml(140, 100, 50, 20, faction.Silver.ToString("N0")); // NOTE: Added 'N0' formatting
AddHtmlLocalized(55, 130, 200, 20, 1011478); // CHANGE TITHE RATE
AddButton(20, 130, 4005, 4007, 0, GumpButtonType.Page, 8);
AddHtmlLocalized(55, 160, 200, 20, 1018301); // TRANSFER SILVER
if (faction.Silver >= 10000)
{
AddButton(20, 160, 4005, 4007, 0, GumpButtonType.Page, 7);
}
else
{
AddImage(20, 160, 4020);
} }
AddHtmlLocalized(55, 310, 100, 20, 1011447); // BACK AddHtmlLocalized(55, 310, 100, 20, 1011447); // BACK
AddButton(20, 310, 4005, 4007, 0, GumpButtonType.Page, 1); AddButton(20, 310, 4005, 4007, 0, GumpButtonType.Page, 1);
}
if (faction.Silver >= 10000) AddPage(8);
AddHtmlLocalized(20, 30, 400, 20, 1011479); // Select the % for the new tithe rate
var y = 55;
for (var i = 0; i <= 10; ++i)
{
if (i == 5)
{ {
AddPage(7); y += 5;
AddHtmlLocalized(20, 30, 250, 20, 1011476); // TOWN FINANCE
AddHtmlLocalized(20, 50, 400, 20, 1011477); // Select a town to transfer 10000 silver to
for (var i = 0; i < towns.Count; ++i)
{
var town = towns[i];
AddHtmlText(55, 75 + i * 30, 200, 20, town.Definition.TownName, false, false);
if (town.Owner == faction)
{
AddButton(20, 75 + i * 30, 4005, 4007, ToButtonID(2, i));
}
else
{
AddImage(20, 75 + i * 30, 4020);
}
}
AddHtmlLocalized(55, 310, 100, 20, 1011447); // BACK
AddButton(20, 310, 4005, 4007, 0, GumpButtonType.Page, 1);
} }
AddPage(8); AddHtmlLocalized(55, y, 300, 20, 1011480 + i);
AddButton(20, y, 4005, 4007, ToButtonID(3, i));
AddHtmlLocalized(20, 30, 400, 20, 1011479); // Select the % for the new tithe rate y += 20;
var y = 55; if (i == 5)
for (var i = 0; i <= 10; ++i)
{ {
if (i == 5) y += 5;
{
y += 5;
}
AddHtmlLocalized(55, y, 300, 20, 1011480 + i);
AddButton(20, y, 4005, 4007, ToButtonID(3, i));
y += 20;
if (i == 5)
{
y += 5;
}
} }
AddHtmlLocalized(55, 310, 300, 20, 1011447); // BACK
AddButton(20, 310, 4005, 4007, 0, GumpButtonType.Page, 1);
}
}
public override int ButtonTypes => 4;
public override void OnResponse(NetState sender, in RelayInfo info)
{
if (!FromButtonID(info.ButtonID, out var type, out var index))
{
return;
} }
switch (type) AddHtmlLocalized(55, 310, 300, 20, 1011447); // BACK
{ AddButton(20, 310, 4005, 4007, 0, GumpButtonType.Page, 1);
case 0: // general
{
switch (index)
{
case 0: // vote
{
m_From.SendGump(new ElectionGump(m_From, m_Faction.Election));
break;
}
case 1: // leave
{
m_From.SendGump(new LeaveFactionGump(m_From, m_Faction));
break;
}
}
break;
}
case 1: // merchant title
{
if (index >= 0 && index <= MerchantTitles.Info.Length)
{
var pl = PlayerState.Find(m_From);
var newTitle = (MerchantTitle)index;
var mti = MerchantTitles.GetInfo(newTitle);
if (mti == null)
{
m_From.SendLocalizedMessage(1010120); // Your merchant title has been removed
if (pl != null)
{
pl.MerchantTitle = newTitle;
}
}
else if (MerchantTitles.IsQualified(m_From, mti))
{
m_From.SendLocalizedMessage(mti.Assigned);
if (pl != null)
{
pl.MerchantTitle = newTitle;
}
}
}
break;
}
case 2: // transfer silver
{
if (!m_Faction.IsCommander(m_From))
{
return;
}
var towns = Town.Towns;
if (index >= 0 && index < towns.Count)
{
var town = towns[index];
if (town.Owner == m_Faction)
{
if (m_Faction.Silver >= 10000)
{
m_Faction.Silver -= 10000;
town.Silver += 10000;
// 10k in silver has been received by:
m_From.SendLocalizedMessage(1042726, true, $" {town.Definition.FriendlyName}");
}
}
}
break;
}
case 3: // change tithe
{
if (!m_Faction.IsCommander(m_From))
{
return;
}
if (index >= 0 && index <= 10)
{
m_Faction.Tithe = index * 10;
}
break;
}
}
} }
} }
}
public override int ButtonTypes => 4;
public override void OnResponse(NetState sender, in RelayInfo info)
{
if (!FromButtonID(info.ButtonID, out var type, out var index))
{
return;
}
switch (type)
{
case 0: // general
{
switch (index)
{
case 0: // vote
{
m_From.SendGump(new ElectionGump(m_From, m_Faction.Election));
break;
}
case 1: // leave
{
m_From.SendGump(new LeaveFactionGump(m_From, m_Faction));
break;
}
}
break;
}
case 1: // merchant title
{
if (index >= 0 && index <= MerchantTitles.Info.Length)
{
var pl = PlayerState.Find(m_From);
var newTitle = (MerchantTitle)index;
var mti = MerchantTitles.GetInfo(newTitle);
if (mti == null)
{
m_From.SendLocalizedMessage(1010120); // Your merchant title has been removed
if (pl != null)
{
pl.MerchantTitle = newTitle;
}
}
else if (MerchantTitles.IsQualified(m_From, mti))
{
m_From.SendLocalizedMessage(mti.Assigned);
if (pl != null)
{
pl.MerchantTitle = newTitle;
}
}
}
break;
}
case 2: // transfer silver
{
if (!m_Faction.IsCommander(m_From))
{
return;
}
var towns = Town.Towns;
if (index >= 0 && index < towns.Count)
{
var town = towns[index];
if (town.Owner == m_Faction)
{
if (m_Faction.Silver >= 10000)
{
m_Faction.Silver -= 10000;
town.Silver += 10000;
// 10k in silver has been received by:
m_From.SendLocalizedMessage(1042726, true, $" {town.Definition.FriendlyName}");
}
}
}
break;
}
case 3: // change tithe
{
if (!m_Faction.IsCommander(m_From))
{
return;
}
if (index >= 0 && index <= 10)
{
m_Faction.Tithe = index * 10;
}
break;
}
}
}
}

View file

@ -3,294 +3,293 @@ using Server.Mobiles;
using Server.Multis; using Server.Multis;
using Server.Network; using Server.Network;
namespace Server.Factions namespace Server.Factions;
public class FinanceGump : FactionGump
{ {
public class FinanceGump : FactionGump private static readonly int[] m_PriceOffsets =
{ {
private static readonly int[] m_PriceOffsets = -30, -25, -20, -15, -10, -5,
+50, +100, +150, +200, +250, +300
};
private readonly Faction m_Faction;
private readonly PlayerMobile m_From;
private readonly Town m_Town;
public FinanceGump(PlayerMobile from, Faction faction, Town town) : base(50, 50)
{
m_From = from;
m_Faction = faction;
m_Town = town;
AddPage(0);
AddBackground(0, 0, 320, 410, 5054);
AddBackground(10, 10, 300, 390, 3000);
AddPage(1);
AddHtmlLocalized(20, 30, 260, 25, 1011541); // FINANCE MINISTER
AddHtmlLocalized(55, 90, 200, 25, 1011539); // CHANGE PRICES
AddButton(20, 90, 4005, 4007, 0, GumpButtonType.Page, 2);
AddHtmlLocalized(55, 120, 200, 25, 1011540); // BUY SHOPKEEPERS
AddButton(20, 120, 4005, 4007, 0, GumpButtonType.Page, 3);
AddHtmlLocalized(55, 150, 200, 25, 1011495); // VIEW FINANCES
AddButton(20, 150, 4005, 4007, 0, GumpButtonType.Page, 4);
AddHtmlLocalized(55, 360, 200, 25, 1011441); // EXIT
AddButton(20, 360, 4005, 4007, 0);
AddPage(2);
AddHtmlLocalized(20, 30, 200, 25, 1011539); // CHANGE PRICES
for (var i = 0; i < m_PriceOffsets.Length; ++i)
{ {
-30, -25, -20, -15, -10, -5, var ofs = m_PriceOffsets[i];
+50, +100, +150, +200, +250, +300
};
private readonly Faction m_Faction; var x = 20 + i / 6 * 150;
private readonly PlayerMobile m_From; var y = 90 + i % 6 * 30;
private readonly Town m_Town;
public FinanceGump(PlayerMobile from, Faction faction, Town town) : base(50, 50) AddRadio(x, y, 208, 209, town.Tax == ofs, i + 1);
{
m_From = from;
m_Faction = faction;
m_Town = town;
AddPage(0); if (ofs < 0)
AddBackground(0, 0, 320, 410, 5054);
AddBackground(10, 10, 300, 390, 3000);
AddPage(1);
AddHtmlLocalized(20, 30, 260, 25, 1011541); // FINANCE MINISTER
AddHtmlLocalized(55, 90, 200, 25, 1011539); // CHANGE PRICES
AddButton(20, 90, 4005, 4007, 0, GumpButtonType.Page, 2);
AddHtmlLocalized(55, 120, 200, 25, 1011540); // BUY SHOPKEEPERS
AddButton(20, 120, 4005, 4007, 0, GumpButtonType.Page, 3);
AddHtmlLocalized(55, 150, 200, 25, 1011495); // VIEW FINANCES
AddButton(20, 150, 4005, 4007, 0, GumpButtonType.Page, 4);
AddHtmlLocalized(55, 360, 200, 25, 1011441); // EXIT
AddButton(20, 360, 4005, 4007, 0);
AddPage(2);
AddHtmlLocalized(20, 30, 200, 25, 1011539); // CHANGE PRICES
for (var i = 0; i < m_PriceOffsets.Length; ++i)
{ {
var ofs = m_PriceOffsets[i]; AddLabel(x + 35, y, 0x26, $"- {-ofs}%");
var x = 20 + i / 6 * 150;
var y = 90 + i % 6 * 30;
AddRadio(x, y, 208, 209, town.Tax == ofs, i + 1);
if (ofs < 0)
{
AddLabel(x + 35, y, 0x26, $"- {-ofs}%");
}
else
{
AddLabel(x + 35, y, 0x12A, $"+ {ofs}%");
}
} }
else
AddRadio(20, 270, 208, 209, town.Tax == 0, 0);
AddHtmlLocalized(55, 270, 90, 25, 1011542); // normal
AddHtmlLocalized(55, 330, 200, 25, 1011509); // Set Prices
AddButton(20, 330, 4005, 4007, ToButtonID(0, 0));
AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1);
AddPage(3);
AddHtmlLocalized(20, 30, 200, 25, 1011540); // BUY SHOPKEEPERS
var vendorLists = town.VendorLists;
for (var i = 0; i < vendorLists.Count; ++i)
{ {
var list = vendorLists[i]; AddLabel(x + 35, y, 0x12A, $"+ {ofs}%");
AddButton(20, 90 + i * 40, 4005, 4007, 0, GumpButtonType.Page, 5 + i);
AddItem(55, 90 + i * 40, list.Definition.ItemID);
AddHtmlText(100, 90 + i * 40, 200, 25, list.Definition.Label, false, false);
}
AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1);
AddPage(4);
var financeUpkeep = town.FinanceUpkeep;
var sheriffUpkeep = town.SheriffUpkeep;
var dailyIncome = town.DailyIncome;
var netCashFlow = town.NetCashFlow;
AddHtmlLocalized(20, 30, 300, 25, 1011524); // FINANCE STATEMENT
AddHtmlLocalized(20, 80, 300, 25, 1011538); // Current total money for town :
AddLabel(20, 100, 0x44, town.Silver.ToString());
AddHtmlLocalized(20, 130, 300, 25, 1011520); // Finance Minister Upkeep :
AddLabel(20, 150, 0x44, financeUpkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 180, 300, 25, 1011521); // Sheriff Upkeep :
AddLabel(20, 200, 0x44, sheriffUpkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 230, 300, 25, 1011522); // Town Income :
AddLabel(20, 250, 0x44, dailyIncome.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 280, 300, 25, 1011523); // Net Cash flow per day :
AddLabel(20, 300, 0x44, netCashFlow.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1);
for (var i = 0; i < vendorLists.Count; ++i)
{
var vendorList = vendorLists[i];
AddPage(5 + i);
AddHtmlText(60, 30, 300, 25, vendorList.Definition.Header, false, false);
AddItem(20, 30, vendorList.Definition.ItemID);
AddHtmlLocalized(20, 90, 200, 25, 1011514); // You have :
AddLabel(230, 90, 0x26, vendorList.Vendors.Count.ToString());
AddHtmlLocalized(20, 120, 200, 25, 1011515); // Maximum :
AddLabel(230, 120, 0x256, vendorList.Definition.Maximum.ToString());
AddHtmlLocalized(20, 150, 200, 25, 1011516); // Cost :
AddLabel(230, 150, 0x44, vendorList.Definition.Price.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 180, 200, 25, 1011517); // Daily Pay :
AddLabel(230, 180, 0x37, vendorList.Definition.Upkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 210, 200, 25, 1011518); // Current Silver :
AddLabel(230, 210, 0x44, town.Silver.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 240, 200, 25, 1011519); // Current Payroll :
AddLabel(230, 240, 0x44, financeUpkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlText(55, 300, 200, 25, vendorList.Definition.Label, false, false);
if (town.Silver >= vendorList.Definition.Price)
{
AddButton(20, 300, 4005, 4007, ToButtonID(1, i));
}
else
{
AddImage(20, 300, 4020);
}
AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 3);
} }
} }
public override int ButtonTypes => 2; AddRadio(20, 270, 208, 209, town.Tax == 0, 0);
AddHtmlLocalized(55, 270, 90, 25, 1011542); // normal
public override void OnResponse(NetState sender, in RelayInfo info) AddHtmlLocalized(55, 330, 200, 25, 1011509); // Set Prices
AddButton(20, 330, 4005, 4007, ToButtonID(0, 0));
AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1);
AddPage(3);
AddHtmlLocalized(20, 30, 200, 25, 1011540); // BUY SHOPKEEPERS
var vendorLists = town.VendorLists;
for (var i = 0; i < vendorLists.Count; ++i)
{ {
if (!m_Town.IsFinance(m_From) || m_Town.Owner != m_Faction) var list = vendorLists[i];
AddButton(20, 90 + i * 40, 4005, 4007, 0, GumpButtonType.Page, 5 + i);
AddItem(55, 90 + i * 40, list.Definition.ItemID);
AddHtmlText(100, 90 + i * 40, 200, 25, list.Definition.Label, false, false);
}
AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1);
AddPage(4);
var financeUpkeep = town.FinanceUpkeep;
var sheriffUpkeep = town.SheriffUpkeep;
var dailyIncome = town.DailyIncome;
var netCashFlow = town.NetCashFlow;
AddHtmlLocalized(20, 30, 300, 25, 1011524); // FINANCE STATEMENT
AddHtmlLocalized(20, 80, 300, 25, 1011538); // Current total money for town :
AddLabel(20, 100, 0x44, town.Silver.ToString());
AddHtmlLocalized(20, 130, 300, 25, 1011520); // Finance Minister Upkeep :
AddLabel(20, 150, 0x44, financeUpkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 180, 300, 25, 1011521); // Sheriff Upkeep :
AddLabel(20, 200, 0x44, sheriffUpkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 230, 300, 25, 1011522); // Town Income :
AddLabel(20, 250, 0x44, dailyIncome.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 280, 300, 25, 1011523); // Net Cash flow per day :
AddLabel(20, 300, 0x44, netCashFlow.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1);
for (var i = 0; i < vendorLists.Count; ++i)
{
var vendorList = vendorLists[i];
AddPage(5 + i);
AddHtmlText(60, 30, 300, 25, vendorList.Definition.Header, false, false);
AddItem(20, 30, vendorList.Definition.ItemID);
AddHtmlLocalized(20, 90, 200, 25, 1011514); // You have :
AddLabel(230, 90, 0x26, vendorList.Vendors.Count.ToString());
AddHtmlLocalized(20, 120, 200, 25, 1011515); // Maximum :
AddLabel(230, 120, 0x256, vendorList.Definition.Maximum.ToString());
AddHtmlLocalized(20, 150, 200, 25, 1011516); // Cost :
AddLabel(230, 150, 0x44, vendorList.Definition.Price.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 180, 200, 25, 1011517); // Daily Pay :
AddLabel(230, 180, 0x37, vendorList.Definition.Upkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 210, 200, 25, 1011518); // Current Silver :
AddLabel(230, 210, 0x44, town.Silver.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 240, 200, 25, 1011519); // Current Payroll :
AddLabel(230, 240, 0x44, financeUpkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlText(55, 300, 200, 25, vendorList.Definition.Label, false, false);
if (town.Silver >= vendorList.Definition.Price)
{ {
m_From.SendLocalizedMessage(1010339); // You no longer control this city AddButton(20, 300, 4005, 4007, ToButtonID(1, i));
return; }
else
{
AddImage(20, 300, 4020);
} }
if (!FromButtonID(info.ButtonID, out var type, out var index)) AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
{ AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 3);
return; }
} }
switch (type) public override int ButtonTypes => 2;
{
case 0: // general public override void OnResponse(NetState sender, in RelayInfo info)
{
if (!m_Town.IsFinance(m_From) || m_Town.Owner != m_Faction)
{
m_From.SendLocalizedMessage(1010339); // You no longer control this city
return;
}
if (!FromButtonID(info.ButtonID, out var type, out var index))
{
return;
}
switch (type)
{
case 0: // general
{
switch (index)
{ {
switch (index) case 0: // set price
{ {
case 0: // set price var switches = info.Switches;
if (switches.Length == 0)
{ {
var switches = info.Switches; break;
}
if (switches.Length == 0) var opt = switches[0];
var newTax = 0;
if (opt >= 1 && opt <= m_PriceOffsets.Length)
{
newTax = m_PriceOffsets[opt - 1];
}
if (m_Town.Tax == newTax)
{
break;
}
if (m_From.AccessLevel == AccessLevel.Player && !m_Town.TaxChangeReady)
{
var remaining = Core.Now - (m_Town.LastTaxChange + Town.TaxChangePeriod);
if (remaining.TotalMinutes < 4)
{ {
break; // You must wait a short while before changing prices again.
m_From.SendLocalizedMessage(1042165);
} }
else if (remaining.TotalMinutes < 10)
var opt = switches[0];
var newTax = 0;
if (opt >= 1 && opt <= m_PriceOffsets.Length)
{ {
newTax = m_PriceOffsets[opt - 1]; // You must wait several minutes before changing prices again.
m_From.SendLocalizedMessage(1042166);
} }
else if (remaining.TotalHours < 1)
if (m_Town.Tax == newTax)
{ {
break; // You must wait up to an hour before changing prices again.
m_From.SendLocalizedMessage(1042167);
} }
else if (remaining.TotalHours < 4)
if (m_From.AccessLevel == AccessLevel.Player && !m_Town.TaxChangeReady)
{ {
var remaining = Core.Now - (m_Town.LastTaxChange + Town.TaxChangePeriod); // You must wait a few hours before changing prices again.
m_From.SendLocalizedMessage(1042168);
if (remaining.TotalMinutes < 4)
{
// You must wait a short while before changing prices again.
m_From.SendLocalizedMessage(1042165);
}
else if (remaining.TotalMinutes < 10)
{
// You must wait several minutes before changing prices again.
m_From.SendLocalizedMessage(1042166);
}
else if (remaining.TotalHours < 1)
{
// You must wait up to an hour before changing prices again.
m_From.SendLocalizedMessage(1042167);
}
else if (remaining.TotalHours < 4)
{
// You must wait a few hours before changing prices again.
m_From.SendLocalizedMessage(1042168);
}
else
{
// You must wait several hours before changing prices again.
m_From.SendLocalizedMessage(1042169);
}
} }
else else
{ {
m_Town.Tax = newTax; // You must wait several hours before changing prices again.
m_From.SendLocalizedMessage(1042169);
if (m_From.AccessLevel == AccessLevel.Player)
{
m_Town.LastTaxChange = Core.Now;
}
} }
break;
} }
} else
break;
}
case 1: // make vendor
{
var vendorLists = m_Town.VendorLists;
if (index >= 0 && index < vendorLists.Count)
{
var vendorList = vendorLists[index];
if (Town.FromRegion(m_From.Region) != m_Town)
{
// You must be in your controlled city to buy Items
m_From.SendLocalizedMessage(1010305);
}
else if (vendorList.Vendors.Count >= vendorList.Definition.Maximum)
{
// You currently have too many of this enhancement type to place another
m_From.SendLocalizedMessage(1010306);
}
else if (BaseBoat.FindBoatAt(m_From.Location, m_From.Map) != null)
{
m_From.SendMessage("You cannot place a vendor here");
}
else if (m_Town.Silver >= vendorList.Definition.Price)
{
var vendor = vendorList.Construct(m_Town, m_Faction);
if (vendor != null)
{ {
m_Town.Silver -= vendorList.Definition.Price; m_Town.Tax = newTax;
vendor.MoveToWorld(m_From.Location, m_From.Map); if (m_From.AccessLevel == AccessLevel.Player)
vendor.Home = vendor.Location; {
m_Town.LastTaxChange = Core.Now;
}
} }
break;
}
}
break;
}
case 1: // make vendor
{
var vendorLists = m_Town.VendorLists;
if (index >= 0 && index < vendorLists.Count)
{
var vendorList = vendorLists[index];
if (Town.FromRegion(m_From.Region) != m_Town)
{
// You must be in your controlled city to buy Items
m_From.SendLocalizedMessage(1010305);
}
else if (vendorList.Vendors.Count >= vendorList.Definition.Maximum)
{
// You currently have too many of this enhancement type to place another
m_From.SendLocalizedMessage(1010306);
}
else if (BaseBoat.FindBoatAt(m_From.Location, m_From.Map) != null)
{
m_From.SendMessage("You cannot place a vendor here");
}
else if (m_Town.Silver >= vendorList.Definition.Price)
{
var vendor = vendorList.Construct(m_Town, m_Faction);
if (vendor != null)
{
m_Town.Silver -= vendorList.Definition.Price;
vendor.MoveToWorld(m_From.Location, m_From.Map);
vendor.Home = vendor.Location;
} }
} }
break;
} }
}
break;
}
} }
} }
} }

View file

@ -3,95 +3,94 @@ using Server.Items;
using Server.Mobiles; using Server.Mobiles;
using Server.Network; using Server.Network;
namespace Server.Factions namespace Server.Factions;
public class HorseBreederGump : FactionGump
{ {
public class HorseBreederGump : FactionGump private readonly Faction m_Faction;
private readonly PlayerMobile m_From;
public HorseBreederGump(PlayerMobile from, Faction faction) : base(20, 30)
{ {
private readonly Faction m_Faction; m_From = from;
private readonly PlayerMobile m_From; m_Faction = faction;
public HorseBreederGump(PlayerMobile from, Faction faction) : base(20, 30) AddPage(0);
AddBackground(0, 0, 320, 280, 5054);
AddBackground(10, 10, 300, 260, 3000);
AddHtmlText(20, 30, 300, 25, faction.Definition.Header, false, false);
AddHtmlLocalized(20, 60, 300, 25, 1018306); // Purchase a Faction War Horse
AddItem(70, 120, 0x3FFE);
AddItem(150, 120, 0xEF2);
AddLabel(190, 122, 0x3E3, FactionWarHorse.SilverPrice.ToString("N0")); // NOTE: Added 'N0'
AddItem(150, 150, 0xEEF);
AddLabel(190, 152, 0x3E3, FactionWarHorse.GoldPrice.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(55, 210, 200, 25, 1011011); // CONTINUE
AddButton(20, 210, 4005, 4007, 1);
AddHtmlLocalized(55, 240, 200, 25, 1011012); // CANCEL
AddButton(20, 240, 4005, 4007, 0);
}
public override void OnResponse(NetState sender, in RelayInfo info)
{
if (info.ButtonID != 1)
{ {
m_From = from; return;
m_Faction = faction;
AddPage(0);
AddBackground(0, 0, 320, 280, 5054);
AddBackground(10, 10, 300, 260, 3000);
AddHtmlText(20, 30, 300, 25, faction.Definition.Header, false, false);
AddHtmlLocalized(20, 60, 300, 25, 1018306); // Purchase a Faction War Horse
AddItem(70, 120, 0x3FFE);
AddItem(150, 120, 0xEF2);
AddLabel(190, 122, 0x3E3, FactionWarHorse.SilverPrice.ToString("N0")); // NOTE: Added 'N0'
AddItem(150, 150, 0xEEF);
AddLabel(190, 152, 0x3E3, FactionWarHorse.GoldPrice.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(55, 210, 200, 25, 1011011); // CONTINUE
AddButton(20, 210, 4005, 4007, 1);
AddHtmlLocalized(55, 240, 200, 25, 1011012); // CANCEL
AddButton(20, 240, 4005, 4007, 0);
} }
public override void OnResponse(NetState sender, in RelayInfo info) if (Faction.Find(m_From) != m_Faction)
{ {
if (info.ButtonID != 1) return;
}
var pack = m_From.Backpack;
if (pack == null)
{
return;
}
var horse = new FactionWarHorse(m_Faction);
if (m_From.Followers + horse.ControlSlots > m_From.FollowersMax)
{
// TODO: Message?
horse.Delete();
}
else
{
if (pack.GetAmount(typeof(Silver)) < FactionWarHorse.SilverPrice)
{ {
return; sender.Mobile.SendLocalizedMessage(1042204); // You do not have enough silver.
}
if (Faction.Find(m_From) != m_Faction)
{
return;
}
var pack = m_From.Backpack;
if (pack == null)
{
return;
}
var horse = new FactionWarHorse(m_Faction);
if (m_From.Followers + horse.ControlSlots > m_From.FollowersMax)
{
// TODO: Message?
horse.Delete(); horse.Delete();
} }
else if (pack.GetAmount(typeof(Gold)) < FactionWarHorse.GoldPrice)
{
sender.Mobile.SendLocalizedMessage(1042205); // You do not have enough gold.
horse.Delete();
}
else if (pack.ConsumeTotal(typeof(Silver), FactionWarHorse.SilverPrice) &&
pack.ConsumeTotal(typeof(Gold), FactionWarHorse.GoldPrice))
{
horse.Controlled = true;
horse.ControlMaster = m_From;
horse.ControlOrder = OrderType.Follow;
horse.ControlTarget = m_From;
horse.MoveToWorld(m_From.Location, m_From.Map);
}
else else
{ {
if (pack.GetAmount(typeof(Silver)) < FactionWarHorse.SilverPrice) horse.Delete();
{
sender.Mobile.SendLocalizedMessage(1042204); // You do not have enough silver.
horse.Delete();
}
else if (pack.GetAmount(typeof(Gold)) < FactionWarHorse.GoldPrice)
{
sender.Mobile.SendLocalizedMessage(1042205); // You do not have enough gold.
horse.Delete();
}
else if (pack.ConsumeTotal(typeof(Silver), FactionWarHorse.SilverPrice) &&
pack.ConsumeTotal(typeof(Gold), FactionWarHorse.GoldPrice))
{
horse.Controlled = true;
horse.ControlMaster = m_From;
horse.ControlOrder = OrderType.Follow;
horse.ControlTarget = m_From;
horse.MoveToWorld(m_From.Location, m_From.Map);
}
else
{
horse.Delete();
}
} }
} }
} }
} }

View file

@ -2,52 +2,51 @@ using Server.Gumps;
using Server.Mobiles; using Server.Mobiles;
using Server.Network; using Server.Network;
namespace Server.Factions namespace Server.Factions;
public class JoinStoneGump : FactionGump
{ {
public class JoinStoneGump : FactionGump private readonly Faction m_Faction;
private readonly PlayerMobile m_From;
public JoinStoneGump(PlayerMobile from, Faction faction) : base(20, 30)
{ {
private readonly Faction m_Faction; m_From = from;
private readonly PlayerMobile m_From; m_Faction = faction;
public JoinStoneGump(PlayerMobile from, Faction faction) : base(20, 30) AddPage(0);
AddBackground(0, 0, 550, 440, 5054);
AddBackground(10, 10, 530, 420, 3000);
AddHtmlText(20, 30, 510, 20, faction.Definition.Header, false, false);
AddHtmlText(20, 130, 510, 100, faction.Definition.About, true, true);
AddHtmlLocalized(20, 60, 100, 20, 1011429); // Led By :
AddHtml(125, 60, 200, 20, faction.Commander != null ? faction.Commander.Name : "Nobody");
AddHtmlLocalized(20, 80, 100, 20, 1011457); // Tithe rate :
if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0)
{ {
m_From = from; AddHtmlLocalized(125, 80, 350, 20, 1011480 + faction.Tithe / 10);
m_Faction = faction; }
else
AddPage(0); {
AddHtml(125, 80, 350, 20, $"{faction.Tithe}%");
AddBackground(0, 0, 550, 440, 5054);
AddBackground(10, 10, 530, 420, 3000);
AddHtmlText(20, 30, 510, 20, faction.Definition.Header, false, false);
AddHtmlText(20, 130, 510, 100, faction.Definition.About, true, true);
AddHtmlLocalized(20, 60, 100, 20, 1011429); // Led By :
AddHtml(125, 60, 200, 20, faction.Commander != null ? faction.Commander.Name : "Nobody");
AddHtmlLocalized(20, 80, 100, 20, 1011457); // Tithe rate :
if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0)
{
AddHtmlLocalized(125, 80, 350, 20, 1011480 + faction.Tithe / 10);
}
else
{
AddHtml(125, 80, 350, 20, $"{faction.Tithe}%");
}
AddButton(20, 400, 4005, 4007, 1);
AddHtmlLocalized(55, 400, 200, 20, 1011425); // JOIN THIS FACTION
AddButton(300, 400, 4005, 4007, 0);
AddHtmlLocalized(335, 400, 200, 20, 1011012); // CANCEL
} }
public override void OnResponse(NetState sender, in RelayInfo info) AddButton(20, 400, 4005, 4007, 1);
AddHtmlLocalized(55, 400, 200, 20, 1011425); // JOIN THIS FACTION
AddButton(300, 400, 4005, 4007, 0);
AddHtmlLocalized(335, 400, 200, 20, 1011012); // CANCEL
}
public override void OnResponse(NetState sender, in RelayInfo info)
{
if (info.ButtonID == 1)
{ {
if (info.ButtonID == 1) m_Faction.OnJoinAccepted(m_From);
{
m_Faction.OnJoinAccepted(m_From);
}
} }
} }
} }

View file

@ -4,55 +4,85 @@ using Server.Gumps;
using Server.Mobiles; using Server.Mobiles;
using Server.Network; using Server.Network;
namespace Server.Factions namespace Server.Factions;
public class LeaveFactionGump : FactionGump
{ {
public class LeaveFactionGump : FactionGump private readonly PlayerMobile m_From;
private Faction m_Faction;
public LeaveFactionGump(PlayerMobile from, Faction faction) : base(20, 30)
{ {
private readonly PlayerMobile m_From; m_From = from;
private Faction m_Faction; m_Faction = faction;
public LeaveFactionGump(PlayerMobile from, Faction faction) : base(20, 30) AddBackground(0, 0, 270, 120, 5054);
AddBackground(10, 10, 250, 100, 3000);
if (from.Guild is Guild guild && guild.Leader == from)
{ {
m_From = from; AddHtmlLocalized(
m_Faction = faction; 20,
15,
AddBackground(0, 0, 270, 120, 5054); 230,
AddBackground(10, 10, 250, 100, 3000); 60,
1018057, // Are you sure you want your entire guild to leave this faction?
if (from.Guild is Guild guild && guild.Leader == from) true,
{ true
AddHtmlLocalized( );
20, }
15, else
230, {
60, // Are you sure you want to leave this faction?s
1018057, // Are you sure you want your entire guild to leave this faction? AddHtmlLocalized(20, 15, 230, 60, 1018063, true, true);
true,
true
);
}
else
{
// Are you sure you want to leave this faction?s
AddHtmlLocalized(20, 15, 230, 60, 1018063, true, true);
}
AddHtmlLocalized(55, 80, 75, 20, 1011011); // CONTINUE
AddButton(20, 80, 4005, 4007, 1);
AddHtmlLocalized(170, 80, 75, 20, 1011012); // CANCEL
AddButton(135, 80, 4005, 4007, 2);
} }
public override void OnResponse(NetState sender, in RelayInfo info) AddHtmlLocalized(55, 80, 75, 20, 1011011); // CONTINUE
AddButton(20, 80, 4005, 4007, 1);
AddHtmlLocalized(170, 80, 75, 20, 1011012); // CANCEL
AddButton(135, 80, 4005, 4007, 2);
}
public override void OnResponse(NetState sender, in RelayInfo info)
{
switch (info.ButtonID)
{ {
switch (info.ButtonID) case 1: // continue
{ {
case 1: // continue if (m_From.Guild is not Guild guild)
{ {
if (m_From.Guild is not Guild guild) var pl = PlayerState.Find(m_From);
if (pl != null)
{ {
var pl = PlayerState.Find(m_From); pl.Leaving = Core.Now;
if (TimeSpan.FromDays(3.0) == Faction.LeavePeriod)
{
m_From.SendLocalizedMessage(1005065); // You will be removed from the faction in 3 days
}
else
{
m_From.SendMessage(
$"You will be removed from the faction in {Faction.LeavePeriod.TotalDays} days."
);
}
}
}
else if (guild.Leader != m_From)
{
// You cannot quit the faction because you are not the guild master
m_From.SendLocalizedMessage(1005061);
}
else
{
m_From.SendLocalizedMessage(1042285); // Your guild is now quitting the faction.
for (var i = 0; i < guild.Members.Count; ++i)
{
var mob = guild.Members[i];
var pl = PlayerState.Find(mob);
if (pl != null) if (pl != null)
{ {
@ -60,57 +90,26 @@ namespace Server.Factions
if (TimeSpan.FromDays(3.0) == Faction.LeavePeriod) if (TimeSpan.FromDays(3.0) == Faction.LeavePeriod)
{ {
m_From.SendLocalizedMessage(1005065); // You will be removed from the faction in 3 days // Your guild will quit the faction in 3 days
mob.SendLocalizedMessage(1005060);
} }
else else
{ {
m_From.SendMessage( mob.SendMessage(
$"You will be removed from the faction in {Faction.LeavePeriod.TotalDays} days." $"Your guild will quit the faction in {Faction.LeavePeriod.TotalDays} days."
); );
} }
} }
} }
else if (guild.Leader != m_From)
{
// You cannot quit the faction because you are not the guild master
m_From.SendLocalizedMessage(1005061);
}
else
{
m_From.SendLocalizedMessage(1042285); // Your guild is now quitting the faction.
for (var i = 0; i < guild.Members.Count; ++i)
{
var mob = guild.Members[i];
var pl = PlayerState.Find(mob);
if (pl != null)
{
pl.Leaving = Core.Now;
if (TimeSpan.FromDays(3.0) == Faction.LeavePeriod)
{
// Your guild will quit the faction in 3 days
mob.SendLocalizedMessage(1005060);
}
else
{
mob.SendMessage(
$"Your guild will quit the faction in {Faction.LeavePeriod.TotalDays} days."
);
}
}
}
}
break;
} }
case 2: // cancel
{ break;
m_From.SendLocalizedMessage(500737); // Canceled resignation. }
break; case 2: // cancel
} {
} m_From.SendLocalizedMessage(500737); // Canceled resignation.
break;
}
} }
} }
} }

View file

@ -3,168 +3,167 @@ using Server.Mobiles;
using Server.Multis; using Server.Multis;
using Server.Network; using Server.Network;
namespace Server.Factions namespace Server.Factions;
public class SheriffGump : FactionGump
{ {
public class SheriffGump : FactionGump private readonly Faction m_Faction;
private readonly PlayerMobile m_From;
private readonly Town m_Town;
public SheriffGump(PlayerMobile from, Faction faction, Town town) : base(50, 50)
{ {
private readonly Faction m_Faction; m_From = from;
private readonly PlayerMobile m_From; m_Faction = faction;
private readonly Town m_Town; m_Town = town;
public SheriffGump(PlayerMobile from, Faction faction, Town town) : base(50, 50) AddPage(0);
AddBackground(0, 0, 320, 410, 5054);
AddBackground(10, 10, 300, 390, 3000);
AddPage(1);
AddHtmlLocalized(20, 30, 260, 25, 1011431); // Sheriff
AddHtmlLocalized(55, 90, 200, 25, 1011494); // HIRE GUARDS
AddButton(20, 90, 4005, 4007, 0, GumpButtonType.Page, 3);
AddHtmlLocalized(55, 120, 200, 25, 1011495); // VIEW FINANCES
AddButton(20, 120, 4005, 4007, 0, GumpButtonType.Page, 2);
AddHtmlLocalized(55, 360, 200, 25, 1011441); // Exit
AddButton(20, 360, 4005, 4007, 0);
AddPage(2);
var financeUpkeep = town.FinanceUpkeep;
var sheriffUpkeep = town.SheriffUpkeep;
var dailyIncome = town.DailyIncome;
var netCashFlow = town.NetCashFlow;
AddHtmlLocalized(20, 30, 300, 25, 1011524); // FINANCE STATEMENT
AddHtmlLocalized(20, 80, 300, 25, 1011538); // Current total money for town :
AddLabel(20, 100, 0x44, town.Silver.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 130, 300, 25, 1011520); // Finance Minister Upkeep :
AddLabel(20, 150, 0x44, financeUpkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 180, 300, 25, 1011521); // Sheriff Upkeep :
AddLabel(20, 200, 0x44, sheriffUpkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 230, 300, 25, 1011522); // Town Income :
AddLabel(20, 250, 0x44, dailyIncome.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 280, 300, 25, 1011523); // Net Cash flow per day :
AddLabel(20, 300, 0x44, netCashFlow.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1);
AddPage(3);
AddHtmlLocalized(20, 30, 300, 25, 1011494); // HIRE GUARDS
var guardLists = town.GuardLists;
for (var i = 0; i < guardLists.Count; ++i)
{ {
m_From = from; var guardList = guardLists[i];
m_Faction = faction; var y = 90 + i * 60;
m_Town = town;
AddPage(0); AddButton(20, y, 4005, 4007, 0, GumpButtonType.Page, 4 + i);
CenterItem(guardList.Definition.ItemID, 50, y - 20, 70, 60);
AddBackground(0, 0, 320, 410, 5054); AddHtmlText(120, y, 200, 25, guardList.Definition.Header, false, false);
AddBackground(10, 10, 300, 390, 3000);
AddPage(1);
AddHtmlLocalized(20, 30, 260, 25, 1011431); // Sheriff
AddHtmlLocalized(55, 90, 200, 25, 1011494); // HIRE GUARDS
AddButton(20, 90, 4005, 4007, 0, GumpButtonType.Page, 3);
AddHtmlLocalized(55, 120, 200, 25, 1011495); // VIEW FINANCES
AddButton(20, 120, 4005, 4007, 0, GumpButtonType.Page, 2);
AddHtmlLocalized(55, 360, 200, 25, 1011441); // Exit
AddButton(20, 360, 4005, 4007, 0);
AddPage(2);
var financeUpkeep = town.FinanceUpkeep;
var sheriffUpkeep = town.SheriffUpkeep;
var dailyIncome = town.DailyIncome;
var netCashFlow = town.NetCashFlow;
AddHtmlLocalized(20, 30, 300, 25, 1011524); // FINANCE STATEMENT
AddHtmlLocalized(20, 80, 300, 25, 1011538); // Current total money for town :
AddLabel(20, 100, 0x44, town.Silver.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 130, 300, 25, 1011520); // Finance Minister Upkeep :
AddLabel(20, 150, 0x44, financeUpkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 180, 300, 25, 1011521); // Sheriff Upkeep :
AddLabel(20, 200, 0x44, sheriffUpkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 230, 300, 25, 1011522); // Town Income :
AddLabel(20, 250, 0x44, dailyIncome.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 280, 300, 25, 1011523); // Net Cash flow per day :
AddLabel(20, 300, 0x44, netCashFlow.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1);
AddPage(3);
AddHtmlLocalized(20, 30, 300, 25, 1011494); // HIRE GUARDS
var guardLists = town.GuardLists;
for (var i = 0; i < guardLists.Count; ++i)
{
var guardList = guardLists[i];
var y = 90 + i * 60;
AddButton(20, y, 4005, 4007, 0, GumpButtonType.Page, 4 + i);
CenterItem(guardList.Definition.ItemID, 50, y - 20, 70, 60);
AddHtmlText(120, y, 200, 25, guardList.Definition.Header, false, false);
}
AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1);
for (var i = 0; i < guardLists.Count; ++i)
{
var guardList = guardLists[i];
AddPage(4 + i);
AddHtmlText(90, 30, 300, 25, guardList.Definition.Header, false, false);
CenterItem(guardList.Definition.ItemID, 10, 10, 80, 80);
AddHtmlLocalized(20, 90, 200, 25, 1011514); // You have :
AddLabel(230, 90, 0x26, guardList.Guards.Count.ToString());
AddHtmlLocalized(20, 120, 200, 25, 1011515); // Maximum :
AddLabel(230, 120, 0x12A, guardList.Definition.Maximum.ToString());
AddHtmlLocalized(20, 150, 200, 25, 1011516); // Cost :
AddLabel(230, 150, 0x44, guardList.Definition.Price.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 180, 200, 25, 1011517); // Daily Pay :
AddLabel(230, 180, 0x37, guardList.Definition.Upkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 210, 200, 25, 1011518); // Current Silver :
AddLabel(230, 210, 0x44, town.Silver.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 240, 200, 25, 1011519); // Current Payroll :
AddLabel(230, 240, 0x44, sheriffUpkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlText(55, 300, 200, 25, guardList.Definition.Label, false, false);
AddButton(20, 300, 4005, 4007, 1 + i);
AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 3);
}
} }
private void CenterItem(int itemID, int x, int y, int w, int h) AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1);
for (var i = 0; i < guardLists.Count; ++i)
{ {
var rc = ItemBounds.Table[itemID]; var guardList = guardLists[i];
AddItem(x + (w - rc.Width) / 2 - rc.X, y + (h - rc.Height) / 2 - rc.Y, itemID);
AddPage(4 + i);
AddHtmlText(90, 30, 300, 25, guardList.Definition.Header, false, false);
CenterItem(guardList.Definition.ItemID, 10, 10, 80, 80);
AddHtmlLocalized(20, 90, 200, 25, 1011514); // You have :
AddLabel(230, 90, 0x26, guardList.Guards.Count.ToString());
AddHtmlLocalized(20, 120, 200, 25, 1011515); // Maximum :
AddLabel(230, 120, 0x12A, guardList.Definition.Maximum.ToString());
AddHtmlLocalized(20, 150, 200, 25, 1011516); // Cost :
AddLabel(230, 150, 0x44, guardList.Definition.Price.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 180, 200, 25, 1011517); // Daily Pay :
AddLabel(230, 180, 0x37, guardList.Definition.Upkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 210, 200, 25, 1011518); // Current Silver :
AddLabel(230, 210, 0x44, town.Silver.ToString("N0")); // NOTE: Added 'N0'
AddHtmlLocalized(20, 240, 200, 25, 1011519); // Current Payroll :
AddLabel(230, 240, 0x44, sheriffUpkeep.ToString("N0")); // NOTE: Added 'N0'
AddHtmlText(55, 300, 200, 25, guardList.Definition.Label, false, false);
AddButton(20, 300, 4005, 4007, 1 + i);
AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page
AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 3);
}
}
private void CenterItem(int itemID, int x, int y, int w, int h)
{
var rc = ItemBounds.Table[itemID];
AddItem(x + (w - rc.Width) / 2 - rc.X, y + (h - rc.Height) / 2 - rc.Y, itemID);
}
public override void OnResponse(NetState sender, in RelayInfo info)
{
if (!m_Town.IsSheriff(m_From) || m_Town.Owner != m_Faction)
{
m_From.SendLocalizedMessage(1010339); // You no longer control this city
return;
} }
public override void OnResponse(NetState sender, in RelayInfo info) var index = info.ButtonID - 1;
if (index >= 0 && index < m_Town.GuardLists.Count)
{ {
if (!m_Town.IsSheriff(m_From) || m_Town.Owner != m_Faction) var guardList = m_Town.GuardLists[index];
if (Town.FromRegion(m_From.Region) != m_Town)
{ {
m_From.SendLocalizedMessage(1010339); // You no longer control this city m_From.SendLocalizedMessage(1010305); // You must be in your controlled city to buy Items
return;
} }
else if (guardList.Guards.Count >= guardList.Definition.Maximum)
var index = info.ButtonID - 1;
if (index >= 0 && index < m_Town.GuardLists.Count)
{ {
var guardList = m_Town.GuardLists[index]; // You currently have too many of this enhancement type to place another
m_From.SendLocalizedMessage(1010306);
}
else if (BaseBoat.FindBoatAt(m_From.Location, m_From.Map) != null)
{
m_From.SendMessage("You cannot place a guard here");
}
else if (m_Town.Silver >= guardList.Definition.Price)
{
var guard = guardList.Construct();
if (Town.FromRegion(m_From.Region) != m_Town) if (guard != null)
{ {
m_From.SendLocalizedMessage(1010305); // You must be in your controlled city to buy Items guard.Faction = m_Faction;
} guard.Town = m_Town;
else if (guardList.Guards.Count >= guardList.Definition.Maximum)
{
// You currently have too many of this enhancement type to place another
m_From.SendLocalizedMessage(1010306);
}
else if (BaseBoat.FindBoatAt(m_From.Location, m_From.Map) != null)
{
m_From.SendMessage("You cannot place a guard here");
}
else if (m_Town.Silver >= guardList.Definition.Price)
{
var guard = guardList.Construct();
if (guard != null) m_Town.Silver -= guardList.Definition.Price;
{
guard.Faction = m_Faction;
guard.Town = m_Town;
m_Town.Silver -= guardList.Definition.Price; guard.MoveToWorld(m_From.Location, m_From.Map);
guard.Home = guard.Location;
guard.MoveToWorld(m_From.Location, m_From.Map);
guard.Home = guard.Location;
}
} }
} }
} }
} }
} }

View file

@ -3,206 +3,209 @@ using Server.Mobiles;
using Server.Network; using Server.Network;
using Server.Targeting; using Server.Targeting;
namespace Server.Factions namespace Server.Factions;
public class TownStoneGump : FactionGump
{ {
public class TownStoneGump : FactionGump private readonly Faction m_Faction;
private readonly PlayerMobile m_From;
private readonly Town m_Town;
public TownStoneGump(PlayerMobile from, Faction faction, Town town) : base(50, 50)
{ {
private readonly Faction m_Faction; m_From = from;
private readonly PlayerMobile m_From; m_Faction = faction;
private readonly Town m_Town; m_Town = town;
public TownStoneGump(PlayerMobile from, Faction faction, Town town) : base(50, 50) AddPage(0);
AddBackground(0, 0, 320, 250, 5054);
AddBackground(10, 10, 300, 230, 3000);
AddHtmlText(25, 30, 250, 25, town.Definition.TownStoneHeader, false, false);
AddHtmlLocalized(55, 60, 150, 25, 1011557); // Hire Sheriff
AddButton(20, 60, 4005, 4007, 1);
AddHtmlLocalized(55, 90, 150, 25, 1011559); // Hire Finance Minister
AddButton(20, 90, 4005, 4007, 2);
AddHtmlLocalized(55, 120, 150, 25, 1011558); // Fire Sheriff
AddButton(20, 120, 4005, 4007, 3);
AddHtmlLocalized(55, 150, 150, 25, 1011560); // Fire Finance Minister
AddButton(20, 150, 4005, 4007, 4);
AddHtmlLocalized(55, 210, 150, 25, 1011441); // EXIT
AddButton(20, 210, 4005, 4007, 0);
}
public override void OnResponse(NetState sender, in RelayInfo info)
{
if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(m_From))
{ {
m_From = from; m_From.SendLocalizedMessage(1010339); // You no longer control this city
m_Faction = faction; return;
m_Town = town;
AddPage(0);
AddBackground(0, 0, 320, 250, 5054);
AddBackground(10, 10, 300, 230, 3000);
AddHtmlText(25, 30, 250, 25, town.Definition.TownStoneHeader, false, false);
AddHtmlLocalized(55, 60, 150, 25, 1011557); // Hire Sheriff
AddButton(20, 60, 4005, 4007, 1);
AddHtmlLocalized(55, 90, 150, 25, 1011559); // Hire Finance Minister
AddButton(20, 90, 4005, 4007, 2);
AddHtmlLocalized(55, 120, 150, 25, 1011558); // Fire Sheriff
AddButton(20, 120, 4005, 4007, 3);
AddHtmlLocalized(55, 150, 150, 25, 1011560); // Fire Finance Minister
AddButton(20, 150, 4005, 4007, 4);
AddHtmlLocalized(55, 210, 150, 25, 1011441); // EXIT
AddButton(20, 210, 4005, 4007, 0);
} }
public override void OnResponse(NetState sender, in RelayInfo info) switch (info.ButtonID)
{ {
if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(m_From)) case 1: // hire sheriff
{ {
m_From.SendLocalizedMessage(1010339); // You no longer control this city if (m_Town.Sheriff != null)
return;
}
switch (info.ButtonID)
{
case 1: // hire sheriff
{ {
if (m_Town.Sheriff != null) // You must fire your Sheriff before you can elect a new one
{ m_From.SendLocalizedMessage(1010342);
// You must fire your Sheriff before you can elect a new one
m_From.SendLocalizedMessage(1010342);
}
else
{
m_From.SendLocalizedMessage(1010347); // Who shall be your new sheriff
m_From.BeginTarget(12, false, TargetFlags.None, HireSheriff_OnTarget);
}
break;
} }
case 2: // hire finance minister else
{ {
if (m_Town.Finance != null) m_From.SendLocalizedMessage(1010347); // Who shall be your new sheriff
{ m_From.BeginTarget(12, false, TargetFlags.None, HireSheriff_OnTarget);
// You must fire your finance minister before you can elect a new one
m_From.SendLocalizedMessage(1010345);
}
else
{
m_From.SendLocalizedMessage(1010348); // Who shall be your new Minister of Finances?
m_From.BeginTarget(12, false, TargetFlags.None, HireFinanceMinister_OnTarget);
}
break;
} }
case 3: // fire sheriff
break;
}
case 2: // hire finance minister
{
if (m_Town.Finance != null)
{ {
if (m_Town.Sheriff == null) // You must fire your finance minister before you can elect a new one
{ m_From.SendLocalizedMessage(1010345);
// You need to elect a sheriff before you can fire one
m_From.SendLocalizedMessage(1010350);
}
else
{
m_From.SendLocalizedMessage(1010349); // You have fired your sheriff
m_Town.Sheriff.SendLocalizedMessage(1010270); // You have been fired as Sheriff
m_Town.Sheriff = null;
}
break;
} }
case 4: // fire finance minister else
{ {
if (m_Town.Finance == null) m_From.SendLocalizedMessage(1010348); // Who shall be your new Minister of Finances?
{ m_From.BeginTarget(12, false, TargetFlags.None, HireFinanceMinister_OnTarget);
// You need to elect a financial minister before you can fire one
m_From.SendLocalizedMessage(1010352);
}
else
{
m_From.SendLocalizedMessage(1010351); // You have fired your financial Minister
m_Town.Finance.SendLocalizedMessage(1010151); // You have been fired as Finance Minister
m_Town.Finance = null;
}
break;
} }
}
break;
}
case 3: // fire sheriff
{
if (m_Town.Sheriff == null)
{
// You need to elect a sheriff before you can fire one
m_From.SendLocalizedMessage(1010350);
}
else
{
m_From.SendLocalizedMessage(1010349); // You have fired your sheriff
m_Town.Sheriff.SendLocalizedMessage(1010270); // You have been fired as Sheriff
m_Town.Sheriff = null;
}
break;
}
case 4: // fire finance minister
{
if (m_Town.Finance == null)
{
// You need to elect a financial minister before you can fire one
m_From.SendLocalizedMessage(1010352);
}
else
{
m_From.SendLocalizedMessage(1010351); // You have fired your financial Minister
m_Town.Finance.SendLocalizedMessage(1010151); // You have been fired as Finance Minister
m_Town.Finance = null;
}
break;
}
}
}
private void HireSheriff_OnTarget(Mobile from, object obj)
{
if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(from))
{
from.SendLocalizedMessage(1010339); // You no longer control this city
return;
} }
private void HireSheriff_OnTarget(Mobile from, object obj) if (m_Town.Sheriff != null)
{ {
if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(from)) from.SendLocalizedMessage(1010342); // You must fire your Sheriff before you can elect a new one
{ return;
from.SendLocalizedMessage(1010339); // You no longer control this city
return;
}
if (m_Town.Sheriff != null)
{
from.SendLocalizedMessage(1010342); // You must fire your Sheriff before you can elect a new one
}
else if (obj is Mobile targ)
{
var pl = PlayerState.Find(targ);
if (pl == null)
{
from.SendLocalizedMessage(1010337); // You must pick someone in a faction
}
else if (pl.Faction != m_Faction)
{
from.SendLocalizedMessage(1010338); // You must pick someone in the correct faction
}
else if (m_Faction.Commander == targ)
{
from.SendLocalizedMessage(1010335); // You cannot elect a commander to a town position
}
else if (pl.Sheriff != null || pl.Finance != null)
{
// You must pick someone who does not already hold a city post
from.SendLocalizedMessage(1005245);
}
else
{
m_Town.Sheriff = targ;
targ.SendLocalizedMessage(1010340); // You are now the Sheriff
from.SendLocalizedMessage(1010341); // You have elected a Sheriff
}
}
else
{
from.SendLocalizedMessage(1010334); // You must select a player to hold a city position!
}
} }
private void HireFinanceMinister_OnTarget(Mobile from, object obj) if (obj is not Mobile m)
{ {
if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(from)) from.SendLocalizedMessage(1010334); // You must select a player to hold a city position!
{ return;
from.SendLocalizedMessage(1010339); // You no longer control this city }
}
else if (m_Town.Finance != null)
{
from.SendLocalizedMessage(1010342); // You must fire your Sheriff before you can elect a new one
}
else if (obj is Mobile targ)
{
var pl = PlayerState.Find(targ);
if (pl == null) var pl = PlayerState.Find(m);
{
from.SendLocalizedMessage(1010337); // You must pick someone in a faction if (pl == null)
} {
else if (pl.Faction != m_Faction) from.SendLocalizedMessage(1010337); // You must pick someone in a faction
{ }
from.SendLocalizedMessage(1010338); // You must pick someone in the correct faction else if (pl.Faction != m_Faction)
} {
else if (m_Faction.Commander == targ) from.SendLocalizedMessage(1010338); // You must pick someone in the correct faction
{ }
from.SendLocalizedMessage(1010335); // You cannot elect a commander to a town position else if (m_Faction.Commander == m)
} {
else if (pl.Sheriff != null || pl.Finance != null) from.SendLocalizedMessage(1010335); // You cannot elect a commander to a town position
{ }
// You must pick someone who does not already hold a city post else if (pl.Sheriff != null || pl.Finance != null)
from.SendLocalizedMessage(1005245); {
} // You must pick someone who does not already hold a city post
else from.SendLocalizedMessage(1005245);
{ }
m_Town.Finance = targ; else
targ.SendLocalizedMessage(1010343); // You are now the Financial Minister {
from.SendLocalizedMessage(1010344); // You have elected a Financial Minister m_Town.Sheriff = m;
} m.SendLocalizedMessage(1010340); // You are now the Sheriff
} from.SendLocalizedMessage(1010341); // You have elected a Sheriff
else }
{ }
from.SendLocalizedMessage(1010334); // You must select a player to hold a city position!
} private void HireFinanceMinister_OnTarget(Mobile from, object obj)
{
if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(from))
{
from.SendLocalizedMessage(1010339); // You no longer control this city
return;
}
if (m_Town.Finance != null)
{
from.SendLocalizedMessage(1010342); // You must fire your Sheriff before you can elect a new one
return;
}
if (obj is not Mobile m)
{
from.SendLocalizedMessage(1010334); // You must select a player to hold a city position!
return;
}
var pl = PlayerState.Find(m);
if (pl == null)
{
from.SendLocalizedMessage(1010337); // You must pick someone in a faction
}
else if (pl.Faction != m_Faction)
{
from.SendLocalizedMessage(1010338); // You must pick someone in the correct faction
}
else if (m_Faction.Commander == m)
{
from.SendLocalizedMessage(1010335); // You cannot elect a commander to a town position
}
else if (pl.Sheriff != null || pl.Finance != null)
{
// You must pick someone who does not already hold a city post
from.SendLocalizedMessage(1005245);
}
else
{
m_Town.Finance = m;
m.SendLocalizedMessage(1010343); // You are now the Financial Minister
from.SendLocalizedMessage(1010344); // You have elected a Financial Minister
} }
} }
} }

View file

@ -2,75 +2,74 @@ using Server.Gumps;
using Server.Mobiles; using Server.Mobiles;
using Server.Network; using Server.Network;
namespace Server.Factions namespace Server.Factions;
public class VoteGump : FactionGump
{ {
public class VoteGump : FactionGump private readonly Election m_Election;
private readonly PlayerMobile m_From;
public VoteGump(PlayerMobile from, Election election) : base(50, 50)
{ {
private readonly Election m_Election; m_From = from;
private readonly PlayerMobile m_From; m_Election = election;
public VoteGump(PlayerMobile from, Election election) : base(50, 50) var canVote = election.CanVote(from);
AddPage(0);
AddBackground(0, 0, 420, 350, 5054);
AddBackground(10, 10, 400, 330, 3000);
AddHtmlText(20, 20, 380, 20, election.Faction.Definition.Header, false, false);
if (canVote)
{ {
m_From = from; AddHtmlLocalized(20, 60, 380, 20, 1011428); // VOTE FOR LEADERSHIP
m_Election = election; }
else
{
AddHtmlLocalized(20, 60, 380, 20, 1038032); // You have already voted in this election.
}
var canVote = election.CanVote(from); for (var i = 0; i < election.Candidates.Count; ++i)
{
AddPage(0); var cd = election.Candidates[i];
AddBackground(0, 0, 420, 350, 5054);
AddBackground(10, 10, 400, 330, 3000);
AddHtmlText(20, 20, 380, 20, election.Faction.Definition.Header, false, false);
if (canVote) if (canVote)
{ {
AddHtmlLocalized(20, 60, 380, 20, 1011428); // VOTE FOR LEADERSHIP AddButton(20, 100 + i * 20, 4005, 4007, i + 1);
}
else
{
AddHtmlLocalized(20, 60, 380, 20, 1038032); // You have already voted in this election.
} }
for (var i = 0; i < election.Candidates.Count; ++i) AddLabel(55, 100 + i * 20, 0, cd.Mobile.Name);
{ AddLabel(300, 100 + i * 20, 0, cd.Votes.ToString());
var cd = election.Candidates[i];
if (canVote)
{
AddButton(20, 100 + i * 20, 4005, 4007, i + 1);
}
AddLabel(55, 100 + i * 20, 0, cd.Mobile.Name);
AddLabel(300, 100 + i * 20, 0, cd.Votes.ToString());
}
AddButton(20, 310, 4005, 4007, 0);
AddHtmlLocalized(55, 310, 100, 20, 1011012); // CANCEL
} }
public override void OnResponse(NetState sender, in RelayInfo info) AddButton(20, 310, 4005, 4007, 0);
AddHtmlLocalized(55, 310, 100, 20, 1011012); // CANCEL
}
public override void OnResponse(NetState sender, in RelayInfo info)
{
if (info.ButtonID == 0)
{ {
if (info.ButtonID == 0) m_From.SendGump(new FactionStoneGump(m_From, m_Election.Faction));
}
else
{
if (!m_Election.CanVote(m_From))
{ {
m_From.SendGump(new FactionStoneGump(m_From, m_Election.Faction)); return;
} }
else
var index = info.ButtonID - 1;
if (index >= 0 && index < m_Election.Candidates.Count)
{ {
if (!m_Election.CanVote(m_From)) m_Election.Candidates[index].Voters.Add(new Voter(m_From, m_Election.Candidates[index].Mobile));
{
return;
}
var index = info.ButtonID - 1;
if (index >= 0 && index < m_Election.Candidates.Count)
{
m_Election.Candidates[index].Voters.Add(new Voter(m_From, m_Election.Candidates[index].Mobile));
}
m_From.SendGump(new VoteGump(m_From, m_Election));
} }
m_From.SendGump(new VoteGump(m_From, m_Election));
} }
} }
} }

View file

@ -39,15 +39,13 @@ public class CouncilOfMages : Faction
1005189, // Members of the Council of Mages will now be beaten with a stick. 1005189, // Members of the Council of Mages will now be beaten with a stick.
// Moonglow // Moonglow
new StrongholdDefinition( new StrongholdDefinition(
new[] [
{
new Rectangle2D(4463, 1487, 15, 35), new Rectangle2D(4463, 1487, 15, 35),
new Rectangle2D(4450, 1522, 35, 48) new Rectangle2D(4450, 1522, 35, 48)
}, ],
new Point3D(4469, 1486, 0), new Point3D(4469, 1486, 0),
new Point3D(4457, 1544, 0), new Point3D(4457, 1544, 0),
new[] [
{
new Point3D(4464, 1534, 21), new Point3D(4464, 1534, 21),
new Point3D(4470, 1536, 21), new Point3D(4470, 1536, 21),
new Point3D(4468, 1534, 21), new Point3D(4468, 1534, 21),
@ -56,7 +54,7 @@ public class CouncilOfMages : Faction
new Point3D(4466, 1534, 21), new Point3D(4466, 1534, 21),
new Point3D(4466, 1536, 21), new Point3D(4466, 1536, 21),
new Point3D(4464, 1536, 21) new Point3D(4464, 1536, 21)
} ]
), ),
// Magincia // Magincia
/* new StrongholdDefinition( /* new StrongholdDefinition(
@ -80,8 +78,7 @@ public class CouncilOfMages : Faction
new Point3D( 3797, 2249, 20 ), new Point3D( 3797, 2249, 20 ),
new Point3D( 3797, 2246, 20 ) new Point3D( 3797, 2246, 20 )
} ), */ } ), */
new[] [
{
new RankDefinition(10, 991, 8, 1060789), // Inquisitor of the Council new RankDefinition(10, 991, 8, 1060789), // Inquisitor of the Council
new RankDefinition(9, 950, 7, 1060788), // Archon of Principle new RankDefinition(9, 950, 7, 1060788), // Archon of Principle
new RankDefinition(8, 900, 6, 1060787), // Luminary new RankDefinition(8, 900, 6, 1060787), // Luminary
@ -92,9 +89,8 @@ public class CouncilOfMages : Faction
new RankDefinition(3, 400, 4, 1060785), // Mystic new RankDefinition(3, 400, 4, 1060785), // Mystic
new RankDefinition(2, 200, 4, 1060785), // Mystic new RankDefinition(2, 200, 4, 1060785), // Mystic
new RankDefinition(1, 0, 4, 1060785) // Mystic new RankDefinition(1, 0, 4, 1060785) // Mystic
}, ],
new[] [
{
new GuardDefinition( new GuardDefinition(
typeof(FactionHenchman), typeof(FactionHenchman),
0x1403, 0x1403,
@ -131,7 +127,7 @@ public class CouncilOfMages : Faction
1011508, // ELDER WIZARD 1011508, // ELDER WIZARD
1011502 // Hire Elder Wizard 1011502 // Hire Elder Wizard
) )
} ]
); );
} }

View file

@ -39,14 +39,12 @@ public class Minax : Faction
1005191, // Followers of Minax will now be told to go away. 1005191, // Followers of Minax will now be told to go away.
1005192, // Followers of Minax will now be hanged by their toes. 1005192, // Followers of Minax will now be hanged by their toes.
new StrongholdDefinition( new StrongholdDefinition(
new[] [
{
new Rectangle2D(1097, 2570, 70, 50) new Rectangle2D(1097, 2570, 70, 50)
}, ],
new Point3D(1172, 2593, 0), new Point3D(1172, 2593, 0),
new Point3D(1117, 2587, 18), new Point3D(1117, 2587, 18),
new[] [
{
new Point3D(1113, 2601, 18), new Point3D(1113, 2601, 18),
new Point3D(1113, 2598, 18), new Point3D(1113, 2598, 18),
new Point3D(1113, 2595, 18), new Point3D(1113, 2595, 18),
@ -55,10 +53,9 @@ public class Minax : Faction
new Point3D(1116, 2598, 18), new Point3D(1116, 2598, 18),
new Point3D(1116, 2595, 18), new Point3D(1116, 2595, 18),
new Point3D(1116, 2592, 18) new Point3D(1116, 2592, 18)
} ]
), ),
new[] [
{
new RankDefinition(10, 991, 8, 1060784), // Avenger of Mondain new RankDefinition(10, 991, 8, 1060784), // Avenger of Mondain
new RankDefinition(9, 950, 7, 1060783), // Dread Knight new RankDefinition(9, 950, 7, 1060783), // Dread Knight
new RankDefinition(8, 900, 6, 1060782), // Warlord new RankDefinition(8, 900, 6, 1060782), // Warlord
@ -69,9 +66,8 @@ public class Minax : Faction
new RankDefinition(3, 400, 4, 1060780), // Defiler new RankDefinition(3, 400, 4, 1060780), // Defiler
new RankDefinition(2, 200, 4, 1060780), // Defiler new RankDefinition(2, 200, 4, 1060780), // Defiler
new RankDefinition(1, 0, 4, 1060780) // Defiler new RankDefinition(1, 0, 4, 1060780) // Defiler
}, ],
new[] [
{
new GuardDefinition( new GuardDefinition(
typeof(FactionHenchman), typeof(FactionHenchman),
0x1403, 0x1403,
@ -108,7 +104,7 @@ public class Minax : Faction
1011506, // DRAGOON 1011506, // DRAGOON
1011500 // Hire Dragoon 1011500 // Hire Dragoon
) )
} ]
); );
} }

View file

@ -38,15 +38,13 @@ public class Shadowlords : Faction
1005185, // Minions of the Shadowlords will now be warned of their impending deaths. 1005185, // Minions of the Shadowlords will now be warned of their impending deaths.
1005186, // Minions of the Shadowlords will now be attacked at will. 1005186, // Minions of the Shadowlords will now be attacked at will.
new StrongholdDefinition( new StrongholdDefinition(
new[] [
{
new Rectangle2D(960, 688, 8, 9), new Rectangle2D(960, 688, 8, 9),
new Rectangle2D(944, 697, 24, 23) new Rectangle2D(944, 697, 24, 23)
}, ],
new Point3D(969, 768, 0), new Point3D(969, 768, 0),
new Point3D(947, 713, 0), new Point3D(947, 713, 0),
new[] [
{
new Point3D(953, 713, 20), new Point3D(953, 713, 20),
new Point3D(953, 709, 20), new Point3D(953, 709, 20),
new Point3D(953, 705, 20), new Point3D(953, 705, 20),
@ -55,10 +53,9 @@ public class Shadowlords : Faction
new Point3D(957, 709, 20), new Point3D(957, 709, 20),
new Point3D(957, 705, 20), new Point3D(957, 705, 20),
new Point3D(957, 701, 20) new Point3D(957, 701, 20)
} ]
), ),
new[] [
{
new RankDefinition(10, 991, 8, 1060799), // Purveyor of Darkness new RankDefinition(10, 991, 8, 1060799), // Purveyor of Darkness
new RankDefinition(9, 950, 7, 1060798), // Agent of Evil new RankDefinition(9, 950, 7, 1060798), // Agent of Evil
new RankDefinition(8, 900, 6, 1060797), // Bringer of Sorrow new RankDefinition(8, 900, 6, 1060797), // Bringer of Sorrow
@ -69,9 +66,8 @@ public class Shadowlords : Faction
new RankDefinition(3, 400, 4, 1060795), // Servant new RankDefinition(3, 400, 4, 1060795), // Servant
new RankDefinition(2, 200, 4, 1060795), // Servant new RankDefinition(2, 200, 4, 1060795), // Servant
new RankDefinition(1, 0, 4, 1060795) // Servant new RankDefinition(1, 0, 4, 1060795) // Servant
}, ],
new[] [
{
new GuardDefinition( new GuardDefinition(
typeof(FactionHenchman), typeof(FactionHenchman),
0x1403, 0x1403,
@ -108,7 +104,7 @@ public class Shadowlords : Faction
1011513, // SHADOW MAGE 1011513, // SHADOW MAGE
1011504 // Hire Shadow Mage 1011504 // Hire Shadow Mage
) )
} ]
); );
} }

View file

@ -38,8 +38,7 @@ public class TrueBritannians : Faction
1005182, // Followers of Lord British will now be warned of their impending doom. 1005182, // Followers of Lord British will now be warned of their impending doom.
1005183, // Followers of Lord British will now be attacked on sight. 1005183, // Followers of Lord British will now be attacked on sight.
new StrongholdDefinition( new StrongholdDefinition(
new[] [
{
new Rectangle2D(1292, 1556, 25, 25), new Rectangle2D(1292, 1556, 25, 25),
new Rectangle2D(1292, 1676, 120, 25), new Rectangle2D(1292, 1676, 120, 25),
new Rectangle2D(1388, 1556, 25, 25), new Rectangle2D(1388, 1556, 25, 25),
@ -47,11 +46,10 @@ public class TrueBritannians : Faction
new Rectangle2D(1300, 1581, 105, 95), new Rectangle2D(1300, 1581, 105, 95),
new Rectangle2D(1405, 1612, 12, 21), new Rectangle2D(1405, 1612, 12, 21),
new Rectangle2D(1405, 1633, 11, 5) new Rectangle2D(1405, 1633, 11, 5)
}, ],
new Point3D(1419, 1622, 20), new Point3D(1419, 1622, 20),
new Point3D(1330, 1621, 50), new Point3D(1330, 1621, 50),
new[] [
{
new Point3D(1328, 1627, 50), new Point3D(1328, 1627, 50),
new Point3D(1328, 1621, 50), new Point3D(1328, 1621, 50),
new Point3D(1334, 1627, 50), new Point3D(1334, 1627, 50),
@ -60,10 +58,9 @@ public class TrueBritannians : Faction
new Point3D(1340, 1621, 50), new Point3D(1340, 1621, 50),
new Point3D(1345, 1621, 50), new Point3D(1345, 1621, 50),
new Point3D(1345, 1627, 50) new Point3D(1345, 1627, 50)
} ]
), ),
new[] [
{
new RankDefinition(10, 991, 8, 1060794), // Knight of the Codex new RankDefinition(10, 991, 8, 1060794), // Knight of the Codex
new RankDefinition(9, 950, 7, 1060793), // Knight of Virtue new RankDefinition(9, 950, 7, 1060793), // Knight of Virtue
new RankDefinition(8, 900, 6, 1060792), // Crusader new RankDefinition(8, 900, 6, 1060792), // Crusader
@ -73,10 +70,9 @@ public class TrueBritannians : Faction
new RankDefinition(4, 500, 5, 1060791), // Sentinel new RankDefinition(4, 500, 5, 1060791), // Sentinel
new RankDefinition(3, 400, 4, 1060790), // Defender new RankDefinition(3, 400, 4, 1060790), // Defender
new RankDefinition(2, 200, 4, 1060790), // Defender new RankDefinition(2, 200, 4, 1060790), // Defender
new RankDefinition(1, 0, 4, 1060790), // Defender new RankDefinition(1, 0, 4, 1060790) // Defender
}, ],
new[] [
{
new GuardDefinition( new GuardDefinition(
typeof(FactionHenchman), typeof(FactionHenchman),
0x1403, 0x1403,
@ -113,7 +109,7 @@ public class TrueBritannians : Faction
1011529, // PALADIN 1011529, // PALADIN
1011498 // Hire Paladin 1011498 // Hire Paladin
) )
} ]
); );
} }

View file

@ -1,137 +1,136 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace Server.Factions namespace Server.Factions;
public abstract class BaseMonolith : BaseSystemController
{ {
public abstract class BaseMonolith : BaseSystemController private Faction m_Faction;
private Sigil m_Sigil;
private Town m_Town;
public BaseMonolith(Town town = null, Faction faction = null) : base(0x1183)
{ {
private Faction m_Faction; Movable = false;
private Sigil m_Sigil; Town = town;
private Town m_Town; Faction = faction;
Monoliths.Add(this);
}
public BaseMonolith(Town town = null, Faction faction = null) : base(0x1183) public BaseMonolith(Serial serial) : base(serial)
{
Monoliths.Add(this);
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Sigil Sigil
{
get => m_Sigil;
set
{ {
Movable = false; if (m_Sigil == value)
Town = town;
Faction = faction;
Monoliths.Add(this);
}
public BaseMonolith(Serial serial) : base(serial)
{
Monoliths.Add(this);
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Sigil Sigil
{
get => m_Sigil;
set
{
if (m_Sigil == value)
{
return;
}
m_Sigil = value;
if (m_Sigil?.LastMonolith != null && m_Sigil.LastMonolith != this && m_Sigil.LastMonolith.Sigil == m_Sigil)
{
m_Sigil.LastMonolith.Sigil = null;
}
if (m_Sigil != null)
{
m_Sigil.LastMonolith = this;
}
UpdateSigil();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Town Town
{
get => m_Town;
set
{
m_Town = value;
OnTownChanged();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Faction Faction
{
get => m_Faction;
set
{
m_Faction = value;
Hue = m_Faction?.Definition.HuePrimary ?? 0;
}
}
public static List<BaseMonolith> Monoliths { get; set; } = new();
public override void OnLocationChange(Point3D oldLocation)
{
base.OnLocationChange(oldLocation);
UpdateSigil();
}
public override void OnMapChange()
{
base.OnMapChange();
UpdateSigil();
}
public virtual void UpdateSigil()
{
if (m_Sigil?.Deleted != false)
{ {
return; return;
} }
m_Sigil.MoveToWorld(new Point3D(X, Y, Z + 18), Map); m_Sigil = value;
}
public virtual void OnTownChanged() if (m_Sigil?.LastMonolith != null && m_Sigil.LastMonolith != this && m_Sigil.LastMonolith.Sigil == m_Sigil)
{
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
Monoliths.Remove(this);
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Town.WriteReference(writer, m_Town);
Faction.WriteReference(writer, m_Faction);
writer.Write(m_Sigil);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{ {
case 0: m_Sigil.LastMonolith.Sigil = null;
{
Town = Town.ReadReference(reader);
Faction = Faction.ReadReference(reader);
m_Sigil = reader.ReadEntity<Sigil>();
break;
}
} }
if (m_Sigil != null)
{
m_Sigil.LastMonolith = this;
}
UpdateSigil();
} }
} }
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Town Town
{
get => m_Town;
set
{
m_Town = value;
OnTownChanged();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Faction Faction
{
get => m_Faction;
set
{
m_Faction = value;
Hue = m_Faction?.Definition.HuePrimary ?? 0;
}
}
public static List<BaseMonolith> Monoliths { get; set; } = new();
public override void OnLocationChange(Point3D oldLocation)
{
base.OnLocationChange(oldLocation);
UpdateSigil();
}
public override void OnMapChange()
{
base.OnMapChange();
UpdateSigil();
}
public virtual void UpdateSigil()
{
if (m_Sigil?.Deleted != false)
{
return;
}
m_Sigil.MoveToWorld(new Point3D(X, Y, Z + 18), Map);
}
public virtual void OnTownChanged()
{
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
Monoliths.Remove(this);
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Town.WriteReference(writer, m_Town);
Faction.WriteReference(writer, m_Faction);
writer.Write(m_Sigil);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Town = Town.ReadReference(reader);
Faction = Faction.ReadReference(reader);
m_Sigil = reader.ReadEntity<Sigil>();
break;
}
}
}
}

View file

@ -1,66 +1,44 @@
namespace Server.Factions using ModernUO.Serialization;
namespace Server.Factions;
[SerializationGenerator(1, false)]
public abstract partial class BaseSystemController : Item
{ {
public abstract class BaseSystemController : Item private int _labelNumber;
public BaseSystemController(int itemID) : base(itemID)
{ {
private int m_LabelNumber; }
public BaseSystemController(int itemID) : base(itemID) public virtual int DefaultLabelNumber => 0;
[SerializableProperty(0, useField: nameof(_labelNumber))]
public override int LabelNumber => _labelNumber > 0 ? _labelNumber : DefaultLabelNumber;
public virtual void AssignName(TextDefinition name)
{
if (name?.Number > 0)
{ {
_labelNumber = name.Number;
Name = null;
}
else if (name?.String != null)
{
_labelNumber = 0;
Name = name.String;
}
else
{
_labelNumber = 0;
Name = null;
} }
public BaseSystemController(Serial serial) : base(serial) InvalidateProperties();
{ }
}
public virtual int DefaultLabelNumber => base.LabelNumber; private void Deserialize(IGenericReader reader, int version)
public new virtual string DefaultName => null; {
// Do nothing
public override int LabelNumber
{
get
{
if (m_LabelNumber > 0)
{
return m_LabelNumber;
}
return DefaultLabelNumber;
}
}
public virtual void AssignName(TextDefinition name)
{
if (name?.Number > 0)
{
m_LabelNumber = name.Number;
Name = null;
}
else if (name?.String != null)
{
m_LabelNumber = 0;
Name = name.String;
}
else
{
m_LabelNumber = 0;
Name = DefaultName;
}
InvalidateProperties();
}
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();
}
} }
} }

View file

@ -1,104 +1,103 @@
using Server.Mobiles; using Server.Mobiles;
namespace Server.Factions namespace Server.Factions;
public class FactionStone : BaseSystemController
{ {
public class FactionStone : BaseSystemController private Faction m_Faction;
[Constructible]
public FactionStone(Faction faction = null) : base(0xEDC)
{ {
private Faction m_Faction; Movable = false;
Faction = faction;
}
[Constructible] public FactionStone(Serial serial) : base(serial)
public FactionStone(Faction faction = null) : base(0xEDC) {
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Faction Faction
{
get => m_Faction;
set
{ {
Movable = false; m_Faction = value;
Faction = faction;
AssignName(m_Faction?.Definition.FactionStoneName);
}
}
public override string DefaultName => "faction stone";
public override void OnDoubleClick(Mobile from)
{
if (m_Faction == null)
{
return;
} }
public FactionStone(Serial serial) : base(serial) if (!from.InRange(GetWorldLocation(), 2))
{ {
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
} }
else if (FactionGump.Exists(from))
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Faction Faction
{ {
get => m_Faction; from.SendLocalizedMessage(1042160); // You already have a faction menu open.
set
{
m_Faction = value;
AssignName(m_Faction?.Definition.FactionStoneName);
}
} }
else if (from is PlayerMobile mobile)
public override string DefaultName => "faction stone";
public override void OnDoubleClick(Mobile from)
{ {
if (m_Faction == null) var existingFaction = Faction.Find(mobile);
{
return;
}
if (!from.InRange(GetWorldLocation(), 2)) if (existingFaction == m_Faction || mobile.AccessLevel >= AccessLevel.GameMaster)
{ {
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. var pl = PlayerState.Find(mobile);
}
else if (FactionGump.Exists(from))
{
from.SendLocalizedMessage(1042160); // You already have a faction menu open.
}
else if (from is PlayerMobile mobile)
{
var existingFaction = Faction.Find(mobile);
if (existingFaction == m_Faction || mobile.AccessLevel >= AccessLevel.GameMaster) if (pl?.IsLeaving == true)
{ {
var pl = PlayerState.Find(mobile); // You cannot use the faction stone until you have finished quitting your current faction
mobile.SendLocalizedMessage(1005051);
if (pl?.IsLeaving == true)
{
// You cannot use the faction stone until you have finished quitting your current faction
mobile.SendLocalizedMessage(1005051);
}
else
{
mobile.SendGump(new FactionStoneGump(mobile, m_Faction));
}
}
else if (existingFaction != null)
{
// TODO: Validate
mobile.SendLocalizedMessage(1005053); // This is not your faction stone!
} }
else else
{ {
mobile.SendGump(new JoinStoneGump(mobile, m_Faction)); mobile.SendGump(new FactionStoneGump(mobile, m_Faction));
} }
} }
} else if (existingFaction != null)
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Faction.WriteReference(writer, m_Faction);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{ {
case 0: // TODO: Validate
{ mobile.SendLocalizedMessage(1005053); // This is not your faction stone!
Faction = Faction.ReadReference(reader); }
break; else
} {
mobile.SendGump(new JoinStoneGump(mobile, m_Faction));
} }
} }
} }
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Faction.WriteReference(writer, m_Faction);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Faction = Faction.ReadReference(reader);
break;
}
}
}
} }

View file

@ -1,81 +1,80 @@
using Server.Mobiles; using Server.Mobiles;
namespace Server.Factions namespace Server.Factions;
public class JoinStone : BaseSystemController
{ {
public class JoinStone : BaseSystemController private Faction m_Faction;
[Constructible]
public JoinStone(Faction faction = null) : base(0xEDC)
{ {
private Faction m_Faction; Movable = false;
Faction = faction;
}
[Constructible] public JoinStone(Serial serial) : base(serial)
public JoinStone(Faction faction = null) : base(0xEDC) {
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Faction Faction
{
get => m_Faction;
set
{ {
Movable = false; m_Faction = value;
Faction = faction;
}
public JoinStone(Serial serial) : base(serial) Hue = m_Faction?.Definition.HueJoin ?? 0;
{ AssignName(m_Faction?.Definition.SignupName);
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Faction Faction
{
get => m_Faction;
set
{
m_Faction = value;
Hue = m_Faction?.Definition.HueJoin ?? 0;
AssignName(m_Faction?.Definition.SignupName);
}
}
public override string DefaultName => "faction signup stone";
public override void OnDoubleClick(Mobile from)
{
if (m_Faction == null)
{
return;
}
if (!from.InRange(GetWorldLocation(), 2))
{
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
}
else if (FactionGump.Exists(from))
{
from.SendLocalizedMessage(1042160); // You already have a faction menu open.
}
else if (Faction.Find(from) == null && from is PlayerMobile mobile)
{
mobile.SendGump(new JoinStoneGump(mobile, m_Faction));
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Faction.WriteReference(writer, m_Faction);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Faction = Faction.ReadReference(reader);
break;
}
}
} }
} }
}
public override string DefaultName => "faction signup stone";
public override void OnDoubleClick(Mobile from)
{
if (m_Faction == null)
{
return;
}
if (!from.InRange(GetWorldLocation(), 2))
{
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
}
else if (FactionGump.Exists(from))
{
from.SendLocalizedMessage(1042160); // You already have a faction menu open.
}
else if (Faction.Find(from) == null && from is PlayerMobile mobile)
{
mobile.SendGump(new JoinStoneGump(mobile, m_Faction));
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Faction.WriteReference(writer, m_Faction);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Faction = Faction.ReadReference(reader);
break;
}
}
}
}

View file

@ -4,474 +4,473 @@ using Server.Mobiles;
using Server.Network; using Server.Network;
using Server.Targeting; using Server.Targeting;
namespace Server.Factions namespace Server.Factions;
public class Sigil : BaseSystemController
{ {
public class Sigil : BaseSystemController public const int OwnershipHue = 0xB;
// ?? time corrupting faction has to return the sigil before corruption time resets ?
public static readonly TimeSpan CorruptionGrace = TimeSpan.FromMinutes(Core.SE ? 30.0 : 15.0);
// Sigil must be held at a stronghold for this amount of time in order to become corrupted
public static readonly TimeSpan CorruptionPeriod = Core.SE ? TimeSpan.FromHours(10.0) : TimeSpan.FromHours(24.0);
// After a sigil has been corrupted it must be returned to the town within this period of time
public static readonly TimeSpan ReturnPeriod = TimeSpan.FromHours(1.0);
// Once it's been returned the corrupting faction owns the town for this period of time
public static readonly TimeSpan PurificationPeriod = TimeSpan.FromDays(3.0);
private Faction m_Corrupted;
private Faction m_Corrupting;
private Town m_Town;
public Sigil(Town town) : base(0x1869)
{ {
public const int OwnershipHue = 0xB; Movable = false;
Town = town;
// ?? time corrupting faction has to return the sigil before corruption time resets ? Sigils.Add(this);
public static readonly TimeSpan CorruptionGrace = TimeSpan.FromMinutes(Core.SE ? 30.0 : 15.0); }
// Sigil must be held at a stronghold for this amount of time in order to become corrupted public Sigil(Serial serial) : base(serial)
public static readonly TimeSpan CorruptionPeriod = Core.SE ? TimeSpan.FromHours(10.0) : TimeSpan.FromHours(24.0); {
Sigils.Add(this);
}
// After a sigil has been corrupted it must be returned to the town within this period of time [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public static readonly TimeSpan ReturnPeriod = TimeSpan.FromHours(1.0); public DateTime LastStolen { get; set; }
// Once it's been returned the corrupting faction owns the town for this period of time [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public static readonly TimeSpan PurificationPeriod = TimeSpan.FromDays(3.0); public DateTime GraceStart { get; set; }
private Faction m_Corrupted;
private Faction m_Corrupting;
private Town m_Town; [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public DateTime CorruptionStart { get; set; }
public Sigil(Town town) : base(0x1869) [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public DateTime PurificationStart { get; set; }
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Town Town
{
get => m_Town;
set
{ {
Movable = false; m_Town = value;
Town = town; Update();
}
}
Sigils.Add(this); [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Faction Corrupted
{
get => m_Corrupted;
set
{
m_Corrupted = value;
Update();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Faction Corrupting
{
get => m_Corrupting;
set
{
m_Corrupting = value;
Update();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public BaseMonolith LastMonolith { get; set; }
[CommandProperty(AccessLevel.Counselor)]
public bool IsBeingCorrupted => LastMonolith is StrongholdMonolith && LastMonolith.Faction == m_Corrupting &&
m_Corrupting != null;
[CommandProperty(AccessLevel.Counselor)]
public bool IsCorrupted => m_Corrupted != null;
[CommandProperty(AccessLevel.Counselor)]
public bool IsPurifying => PurificationStart != DateTime.MinValue;
[CommandProperty(AccessLevel.Counselor)]
public bool IsCorrupting => m_Corrupting != null && m_Corrupting != m_Corrupted;
[CommandProperty(AccessLevel.GameMaster)]
public TimeSpan TimeUntilCorruption =>
!IsBeingCorrupted ?
TimeSpan.Zero :
Utility.Max(CorruptionStart + CorruptionPeriod - Core.Now, TimeSpan.Zero);
public static List<Sigil> Sigils { get; } = new();
public void Update()
{
ItemID = m_Town?.Definition.SigilID ?? 0x1869;
if (m_Town == null)
{
AssignName(null);
}
else if (IsCorrupted || IsPurifying)
{
AssignName(m_Town.Definition.CorruptedSigilName);
}
else
{
AssignName(m_Town.Definition.SigilName);
} }
public Sigil(Serial serial) : base(serial) InvalidateProperties();
}
public override void GetProperties(IPropertyList list)
{
base.GetProperties(list);
if (IsCorrupted)
{ {
Sigils.Add(this); m_Corrupted.Definition.SigilControl.AddTo(list);
}
else
{
list.Add(1042256); // This sigil is not corrupted.
} }
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] if (IsCorrupting)
public DateTime LastStolen { get; set; }
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public DateTime GraceStart { get; set; }
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public DateTime CorruptionStart { get; set; }
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public DateTime PurificationStart { get; set; }
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Town Town
{ {
get => m_Town; list.Add(1042257); // This sigil is in the process of being corrupted.
set }
else if (IsPurifying)
{
list.Add(1042258); // This sigil has recently been corrupted, and is undergoing purification.
}
else
{
list.Add(1042259); // This sigil is not in the process of being corrupted.
}
}
public override void OnSingleClick(Mobile from)
{
base.OnSingleClick(from);
if (IsCorrupted)
{
if (m_Corrupted.Definition.SigilControl.Number > 0)
{ {
m_Town = value; LabelTo(from, m_Corrupted.Definition.SigilControl.Number);
Update(); }
else if (m_Corrupted.Definition.SigilControl.String != null)
{
LabelTo(from, m_Corrupted.Definition.SigilControl.String);
} }
} }
else
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Faction Corrupted
{ {
get => m_Corrupted; LabelTo(from, 1042256); // This sigil is not corrupted.
set
{
m_Corrupted = value;
Update();
}
} }
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] if (IsCorrupting)
public Faction Corrupting
{ {
get => m_Corrupting; LabelTo(from, 1042257); // This sigil is in the process of being corrupted.
set }
{ else if (IsPurifying)
m_Corrupting = value; {
Update(); LabelTo(from, 1042258); // This sigil has been recently corrupted, and is undergoing purification.
} }
else
{
LabelTo(from, 1042259); // This sigil is not in the process of being corrupted.
}
}
public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
{
from.SendLocalizedMessage(1005225); // You must use the stealing skill to pick up the sigil
return false;
}
private Mobile FindOwner(IEntity parent)
{
if (parent is Item item)
{
return item.RootParent as Mobile;
} }
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] if (parent is Mobile mobile)
public BaseMonolith LastMonolith { get; set; }
[CommandProperty(AccessLevel.Counselor)]
public bool IsBeingCorrupted => LastMonolith is StrongholdMonolith && LastMonolith.Faction == m_Corrupting &&
m_Corrupting != null;
[CommandProperty(AccessLevel.Counselor)]
public bool IsCorrupted => m_Corrupted != null;
[CommandProperty(AccessLevel.Counselor)]
public bool IsPurifying => PurificationStart != DateTime.MinValue;
[CommandProperty(AccessLevel.Counselor)]
public bool IsCorrupting => m_Corrupting != null && m_Corrupting != m_Corrupted;
[CommandProperty(AccessLevel.GameMaster)]
public TimeSpan TimeUntilCorruption =>
!IsBeingCorrupted ?
TimeSpan.Zero :
Utility.Max(CorruptionStart + CorruptionPeriod - Core.Now, TimeSpan.Zero);
public static List<Sigil> Sigils { get; } = new();
public void Update()
{ {
ItemID = m_Town?.Definition.SigilID ?? 0x1869; return mobile;
if (m_Town == null)
{
AssignName(null);
}
else if (IsCorrupted || IsPurifying)
{
AssignName(m_Town.Definition.CorruptedSigilName);
}
else
{
AssignName(m_Town.Definition.SigilName);
}
InvalidateProperties();
} }
public override void GetProperties(IPropertyList list) return null;
}
public override void OnAdded(IEntity parent)
{
base.OnAdded(parent);
var mob = FindOwner(parent);
if (mob != null)
{ {
base.GetProperties(list); mob.SolidHueOverride = OwnershipHue;
}
}
if (IsCorrupted) public override void OnRemoved(IEntity parent)
{ {
m_Corrupted.Definition.SigilControl.AddTo(list); base.OnRemoved(parent);
}
else
{
list.Add(1042256); // This sigil is not corrupted.
}
if (IsCorrupting) var mob = FindOwner(parent);
{
list.Add(1042257); // This sigil is in the process of being corrupted. if (mob != null)
} {
else if (IsPurifying) mob.SolidHueOverride = -1;
{ }
list.Add(1042258); // This sigil has recently been corrupted, and is undergoing purification. }
}
else public override void OnDoubleClick(Mobile from)
{ {
list.Add(1042259); // This sigil is not in the process of being corrupted. if (IsChildOf(from.Backpack))
} {
from.BeginTarget(1, false, TargetFlags.None, Sigil_OnTarget);
from.SendLocalizedMessage(1042251); // Click on a sigil monolith or player
}
}
public static bool ExistsOn(Mobile mob) => mob.Backpack?.FindItemByType<Sigil>() != null;
private void BeginCorrupting(Faction faction)
{
m_Corrupting = faction;
CorruptionStart = Core.Now;
}
private void ClearCorrupting()
{
m_Corrupting = null;
CorruptionStart = DateTime.MinValue;
}
private void Sigil_OnTarget(Mobile from, object obj)
{
if (Deleted || !IsChildOf(from.Backpack))
{
return;
} }
public override void OnSingleClick(Mobile from) if (obj is Mobile)
{ {
base.OnSingleClick(from); if (obj is PlayerMobile targ)
if (IsCorrupted)
{ {
if (m_Corrupted.Definition.SigilControl.Number > 0) var toFaction = Faction.Find(targ);
var fromFaction = Faction.Find(from);
if (toFaction == null)
{ {
LabelTo(from, m_Corrupted.Definition.SigilControl.Number); from.SendLocalizedMessage(1005223); // You cannot give the sigil to someone not in a faction
} }
else if (m_Corrupted.Definition.SigilControl.String != null) else if (fromFaction != toFaction)
{ {
LabelTo(from, m_Corrupted.Definition.SigilControl.String); from.SendLocalizedMessage(1005222); // You cannot give the sigil to someone not in your faction
}
else if (ExistsOn(targ))
{
from.SendLocalizedMessage(1005220); // You cannot give this sigil to someone who already has a sigil
}
else if (!targ.Alive)
{
from.SendLocalizedMessage(1042248); // You cannot give a sigil to a dead person.
}
else if (from.NetState != null && targ.NetState != null)
{
var pack = targ.Backpack;
pack?.DropItem(this);
} }
} }
else else
{ {
LabelTo(from, 1042256); // This sigil is not corrupted. from.SendLocalizedMessage(1005221); // You cannot give the sigil to them
}
if (IsCorrupting)
{
LabelTo(from, 1042257); // This sigil is in the process of being corrupted.
}
else if (IsPurifying)
{
LabelTo(from, 1042258); // This sigil has been recently corrupted, and is undergoing purification.
}
else
{
LabelTo(from, 1042259); // This sigil is not in the process of being corrupted.
} }
} }
else if (obj is BaseMonolith)
public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
{ {
from.SendLocalizedMessage(1005225); // You must use the stealing skill to pick up the sigil if (obj is StrongholdMonolith sm)
return false;
}
private Mobile FindOwner(IEntity parent)
{
if (parent is Item item)
{ {
return item.RootParent as Mobile; if (sm.Faction == null || sm.Faction != Faction.Find(from))
}
if (parent is Mobile mobile)
{
return mobile;
}
return null;
}
public override void OnAdded(IEntity parent)
{
base.OnAdded(parent);
var mob = FindOwner(parent);
if (mob != null)
{
mob.SolidHueOverride = OwnershipHue;
}
}
public override void OnRemoved(IEntity parent)
{
base.OnRemoved(parent);
var mob = FindOwner(parent);
if (mob != null)
{
mob.SolidHueOverride = -1;
}
}
public override void OnDoubleClick(Mobile from)
{
if (IsChildOf(from.Backpack))
{
from.BeginTarget(1, false, TargetFlags.None, Sigil_OnTarget);
from.SendLocalizedMessage(1042251); // Click on a sigil monolith or player
}
}
public static bool ExistsOn(Mobile mob) => mob.Backpack?.FindItemByType<Sigil>() != null;
private void BeginCorrupting(Faction faction)
{
m_Corrupting = faction;
CorruptionStart = Core.Now;
}
private void ClearCorrupting()
{
m_Corrupting = null;
CorruptionStart = DateTime.MinValue;
}
private void Sigil_OnTarget(Mobile from, object obj)
{
if (Deleted || !IsChildOf(from.Backpack))
{
return;
}
if (obj is Mobile)
{
if (obj is PlayerMobile targ)
{ {
var toFaction = Faction.Find(targ); from.SendLocalizedMessage(1042246); // You can't place that on an enemy monolith
var fromFaction = Faction.Find(from); }
else if (sm.Town == null || sm.Town != m_Town)
if (toFaction == null) {
{ from.SendLocalizedMessage(1042247); // That is not the correct faction monolith
from.SendLocalizedMessage(1005223); // You cannot give the sigil to someone not in a faction
}
else if (fromFaction != toFaction)
{
from.SendLocalizedMessage(1005222); // You cannot give the sigil to someone not in your faction
}
else if (ExistsOn(targ))
{
from.SendLocalizedMessage(1005220); // You cannot give this sigil to someone who already has a sigil
}
else if (!targ.Alive)
{
from.SendLocalizedMessage(1042248); // You cannot give a sigil to a dead person.
}
else if (from.NetState != null && targ.NetState != null)
{
var pack = targ.Backpack;
pack?.DropItem(this);
}
} }
else else
{ {
from.SendLocalizedMessage(1005221); // You cannot give the sigil to them sm.Sigil = this;
var newController = sm.Faction;
var oldController = m_Corrupting;
if (oldController == null)
{
if (m_Corrupted != newController)
{
BeginCorrupting(newController);
}
}
else if (GraceStart > DateTime.MinValue && GraceStart + CorruptionGrace < Core.Now)
{
if (m_Corrupted != newController)
{
BeginCorrupting(newController); // grace time over, reset period
}
else
{
ClearCorrupting();
}
GraceStart = DateTime.MinValue;
}
else if (newController == oldController)
{
GraceStart = DateTime.MinValue; // returned within grace period
}
else if (GraceStart == DateTime.MinValue)
{
GraceStart = Core.Now;
}
PurificationStart = DateTime.MinValue;
} }
} }
else if (obj is BaseMonolith) else if (obj is TownMonolith tm)
{ {
if (obj is StrongholdMonolith sm) if (tm.Town == null || tm.Town != m_Town)
{ {
if (sm.Faction == null || sm.Faction != Faction.Find(from)) from.SendLocalizedMessage(1042245); // This is not the correct town sigil monolith
{
from.SendLocalizedMessage(1042246); // You can't place that on an enemy monolith
}
else if (sm.Town == null || sm.Town != m_Town)
{
from.SendLocalizedMessage(1042247); // That is not the correct faction monolith
}
else
{
sm.Sigil = this;
var newController = sm.Faction;
var oldController = m_Corrupting;
if (oldController == null)
{
if (m_Corrupted != newController)
{
BeginCorrupting(newController);
}
}
else if (GraceStart > DateTime.MinValue && GraceStart + CorruptionGrace < Core.Now)
{
if (m_Corrupted != newController)
{
BeginCorrupting(newController); // grace time over, reset period
}
else
{
ClearCorrupting();
}
GraceStart = DateTime.MinValue;
}
else if (newController == oldController)
{
GraceStart = DateTime.MinValue; // returned within grace period
}
else if (GraceStart == DateTime.MinValue)
{
GraceStart = Core.Now;
}
PurificationStart = DateTime.MinValue;
}
} }
else if (obj is TownMonolith tm) else if (m_Corrupted == null || m_Corrupted != Faction.Find(from))
{ {
if (tm.Town == null || tm.Town != m_Town) // Your faction did not corrupt this sigil. Take it to your stronghold.
{ from.SendLocalizedMessage(1042244);
from.SendLocalizedMessage(1042245); // This is not the correct town sigil monolith }
} else
else if (m_Corrupted == null || m_Corrupted != Faction.Find(from)) {
{ tm.Sigil = this;
// Your faction did not corrupt this sigil. Take it to your stronghold.
from.SendLocalizedMessage(1042244);
}
else
{
tm.Sigil = this;
m_Corrupting = null; m_Corrupting = null;
PurificationStart = Core.Now; PurificationStart = Core.Now;
CorruptionStart = DateTime.MinValue; CorruptionStart = DateTime.MinValue;
m_Town.Capture(m_Corrupted); m_Town.Capture(m_Corrupted);
m_Corrupted = null; m_Corrupted = null;
}
} }
} }
else }
{ else
from.SendLocalizedMessage(1005224); // You can't use the sigil on that {
} from.SendLocalizedMessage(1005224); // You can't use the sigil on that
Update();
} }
public override void Serialize(IGenericWriter writer) Update();
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Town.WriteReference(writer, m_Town);
Faction.WriteReference(writer, m_Corrupted);
Faction.WriteReference(writer, m_Corrupting);
writer.Write(LastMonolith);
writer.Write(LastStolen);
writer.Write(GraceStart);
writer.Write(CorruptionStart);
writer.Write(PurificationStart);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{ {
base.Serialize(writer); case 0:
{
m_Town = Town.ReadReference(reader);
m_Corrupted = Faction.ReadReference(reader);
m_Corrupting = Faction.ReadReference(reader);
writer.Write(0); // version LastMonolith = reader.ReadEntity<BaseMonolith>();
Town.WriteReference(writer, m_Town); LastStolen = reader.ReadDateTime();
Faction.WriteReference(writer, m_Corrupted); GraceStart = reader.ReadDateTime();
Faction.WriteReference(writer, m_Corrupting); CorruptionStart = reader.ReadDateTime();
PurificationStart = reader.ReadDateTime();
writer.Write(LastMonolith); Update();
writer.Write(LastStolen); if (RootParent is Mobile mob)
writer.Write(GraceStart);
writer.Write(CorruptionStart);
writer.Write(PurificationStart);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{ {
m_Town = Town.ReadReference(reader); mob.SolidHueOverride = OwnershipHue;
m_Corrupted = Faction.ReadReference(reader);
m_Corrupting = Faction.ReadReference(reader);
LastMonolith = reader.ReadEntity<BaseMonolith>();
LastStolen = reader.ReadDateTime();
GraceStart = reader.ReadDateTime();
CorruptionStart = reader.ReadDateTime();
PurificationStart = reader.ReadDateTime();
Update();
if (RootParent is Mobile mob)
{
mob.SolidHueOverride = OwnershipHue;
}
break;
} }
}
}
public bool ReturnHome() break;
{ }
var monolith = LastMonolith;
if (monolith == null && m_Town != null)
{
monolith = m_Town.Monolith;
}
if (monolith?.Deleted == false)
{
monolith.Sigil = this;
}
return monolith?.Deleted == false;
}
public override void OnParentDeleted(IEntity parent)
{
base.OnParentDeleted(parent);
ReturnHome();
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
Sigils.Remove(this);
}
public override void Delete()
{
if (ReturnHome())
{
return;
}
base.Delete();
} }
} }
}
public bool ReturnHome()
{
var monolith = LastMonolith;
if (monolith == null && m_Town != null)
{
monolith = m_Town.Monolith;
}
if (monolith?.Deleted == false)
{
monolith.Sigil = this;
}
return monolith?.Deleted == false;
}
public override void OnParentDeleted(IEntity parent)
{
base.OnParentDeleted(parent);
ReturnHome();
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
Sigils.Remove(this);
}
public override void Delete()
{
if (ReturnHome())
{
return;
}
base.Delete();
}
}

View file

@ -1,34 +1,33 @@
namespace Server.Factions namespace Server.Factions;
public class StrongholdMonolith : BaseMonolith
{ {
public class StrongholdMonolith : BaseMonolith public StrongholdMonolith(Town town = null, Faction faction = null) : base(town, faction)
{ {
public StrongholdMonolith(Town town = null, Faction faction = null) : base(town, faction)
{
}
public StrongholdMonolith(Serial serial) : base(serial)
{
}
public override int DefaultLabelNumber => 1041042; // A Faction Sigil Monolith
public override void OnTownChanged()
{
AssignName(Town?.Definition.StrongholdMonolithName);
}
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();
}
} }
}
public StrongholdMonolith(Serial serial) : base(serial)
{
}
public override int DefaultLabelNumber => 1041042; // A Faction Sigil Monolith
public override void OnTownChanged()
{
AssignName(Town?.Definition.StrongholdMonolithName);
}
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();
}
}

View file

@ -1,34 +1,33 @@
namespace Server.Factions namespace Server.Factions;
public class TownMonolith : BaseMonolith
{ {
public class TownMonolith : BaseMonolith public TownMonolith(Town town = null) : base(town)
{ {
public TownMonolith(Town town = null) : base(town)
{
}
public TownMonolith(Serial serial) : base(serial)
{
}
public override int DefaultLabelNumber => 1041403; // A Faction Town Sigil Monolith
public override void OnTownChanged()
{
AssignName(Town?.Definition.TownMonolithName);
}
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();
}
} }
}
public TownMonolith(Serial serial) : base(serial)
{
}
public override int DefaultLabelNumber => 1041403; // A Faction Town Sigil Monolith
public override void OnTownChanged()
{
AssignName(Town?.Definition.TownMonolithName);
}
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();
}
}

View file

@ -1,91 +1,90 @@
using Server.Mobiles; using Server.Mobiles;
namespace Server.Factions namespace Server.Factions;
public class TownStone : BaseSystemController
{ {
public class TownStone : BaseSystemController private Town m_Town;
[Constructible]
public TownStone(Town town = null) : base(0xEDE)
{ {
private Town m_Town; Movable = false;
Town = town;
}
[Constructible] public TownStone(Serial serial) : base(serial)
public TownStone(Town town = null) : base(0xEDE) {
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Town Town
{
get => m_Town;
set
{ {
Movable = false; m_Town = value;
Town = town;
}
public TownStone(Serial serial) : base(serial) AssignName(m_Town?.Definition.TownStoneName);
{
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)]
public Town Town
{
get => m_Town;
set
{
m_Town = value;
AssignName(m_Town?.Definition.TownStoneName);
}
}
public override string DefaultName => "faction town stone";
public override void OnDoubleClick(Mobile from)
{
if (m_Town == null)
{
return;
}
var faction = Faction.Find(from);
if (faction == null && from.AccessLevel < AccessLevel.GameMaster)
{
return; // TODO: Message?
}
if (m_Town.Owner == null || from.AccessLevel < AccessLevel.GameMaster && faction != m_Town.Owner)
{
from.SendLocalizedMessage(1010332); // Your faction does not control this town
}
else if (!m_Town.Owner.IsCommander(from))
{
from.SendLocalizedMessage(1005242); // Only faction Leaders can use townstones
}
else if (FactionGump.Exists(from))
{
from.SendLocalizedMessage(1042160); // You already have a faction menu open.
}
else if (from is PlayerMobile mobile)
{
mobile.SendGump(new TownStoneGump(mobile, m_Town.Owner, m_Town));
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Town.WriteReference(writer, m_Town);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Town = Town.ReadReference(reader);
break;
}
}
} }
} }
}
public override string DefaultName => "faction town stone";
public override void OnDoubleClick(Mobile from)
{
if (m_Town == null)
{
return;
}
var faction = Faction.Find(from);
if (faction == null && from.AccessLevel < AccessLevel.GameMaster)
{
return; // TODO: Message?
}
if (m_Town.Owner == null || from.AccessLevel < AccessLevel.GameMaster && faction != m_Town.Owner)
{
from.SendLocalizedMessage(1010332); // Your faction does not control this town
}
else if (!m_Town.Owner.IsCommander(from))
{
from.SendLocalizedMessage(1005242); // Only faction Leaders can use townstones
}
else if (FactionGump.Exists(from))
{
from.SendLocalizedMessage(1042160); // You already have a faction menu open.
}
else if (from is PlayerMobile mobile)
{
mobile.SendGump(new TownStoneGump(mobile, m_Town.Owner, m_Town));
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Town.WriteReference(writer, m_Town);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Town = Town.ReadReference(reader);
break;
}
}
}
}

View file

@ -2,289 +2,288 @@ using System;
using Server.Items; using Server.Items;
using Server.Network; using Server.Network;
namespace Server.Factions namespace Server.Factions;
{
public enum AllowedPlacing
{
Everywhere,
AnyFactionTown, public enum AllowedPlacing
ControlledFactionTown, {
FactionStronghold Everywhere,
AnyFactionTown,
ControlledFactionTown,
FactionStronghold
}
public abstract class BaseFactionTrap : BaseTrap
{
private TimerExecutionToken _concealingTimerToken;
public BaseFactionTrap(Faction f, Mobile m, int itemID) : base(itemID)
{
Visible = false;
Faction = f;
TimeOfPlacement = Core.Now;
Placer = m;
} }
public abstract class BaseFactionTrap : BaseTrap public BaseFactionTrap(Serial serial) : base(serial)
{ {
private TimerExecutionToken _concealingTimerToken; }
public BaseFactionTrap(Faction f, Mobile m, int itemID) : base(itemID) [CommandProperty(AccessLevel.GameMaster)]
public Faction Faction { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public Mobile Placer { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime TimeOfPlacement { get; set; }
public virtual int EffectSound => 0;
public virtual int SilverFromDisarm => 100;
public virtual int MessageHue => 0;
public virtual int AttackMessage => 0;
public virtual int DisarmMessage => 0;
public virtual AllowedPlacing AllowedPlacing => AllowedPlacing.Everywhere;
public virtual TimeSpan ConcealPeriod => TimeSpan.FromMinutes(1.0);
public virtual TimeSpan DecayPeriod => Core.AOS ? TimeSpan.FromDays(1.0) : TimeSpan.MaxValue;
public override void OnTrigger(Mobile from)
{
if (!IsEnemy(from))
{ {
Visible = false; return;
Faction = f;
TimeOfPlacement = Core.Now;
Placer = m;
} }
public BaseFactionTrap(Serial serial) : base(serial) Conceal();
DoVisibleEffect();
Effects.PlaySound(Location, Map, EffectSound);
DoAttackEffect(from);
var silverToAward = from.Alive ? 20 : 40;
if (Placer != null && Faction != null)
{ {
} var victimState = PlayerState.Find(from);
[CommandProperty(AccessLevel.GameMaster)] if (victimState?.CanGiveSilverTo(Placer) == true && victimState.KillPoints > 0)
public Faction Faction { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public Mobile Placer { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime TimeOfPlacement { get; set; }
public virtual int EffectSound => 0;
public virtual int SilverFromDisarm => 100;
public virtual int MessageHue => 0;
public virtual int AttackMessage => 0;
public virtual int DisarmMessage => 0;
public virtual AllowedPlacing AllowedPlacing => AllowedPlacing.Everywhere;
public virtual TimeSpan ConcealPeriod => TimeSpan.FromMinutes(1.0);
public virtual TimeSpan DecayPeriod => Core.AOS ? TimeSpan.FromDays(1.0) : TimeSpan.MaxValue;
public override void OnTrigger(Mobile from)
{
if (!IsEnemy(from))
{ {
return; var silverGiven = Faction.AwardSilver(Placer, silverToAward);
}
Conceal(); if (silverGiven > 0)
DoVisibleEffect();
Effects.PlaySound(Location, Map, EffectSound);
DoAttackEffect(from);
var silverToAward = from.Alive ? 20 : 40;
if (Placer != null && Faction != null)
{
var victimState = PlayerState.Find(from);
if (victimState?.CanGiveSilverTo(Placer) == true && victimState.KillPoints > 0)
{ {
var silverGiven = Faction.AwardSilver(Placer, silverToAward); // TODO: Get real message
if (from.Alive)
if (silverGiven > 0)
{ {
// TODO: Get real message Placer.SendMessage(
if (from.Alive) $"You have earned {silverGiven} silver pieces because {from.Name} fell for your trap."
{ );
Placer.SendMessage(
$"You have earned {silverGiven} silver pieces because {from.Name} fell for your trap."
);
}
else
{
// You have earned ~1_SILVER_AMOUNT~ pieces for vanquishing ~2_PLAYER_NAME~!
Placer.SendLocalizedMessage(1042736, $"{silverGiven} silver\t{from.Name}");
}
} }
else
victimState.OnGivenSilverTo(Placer);
}
}
from.LocalOverheadMessage(MessageType.Regular, MessageHue, AttackMessage);
}
public abstract void DoVisibleEffect();
public abstract void DoAttackEffect(Mobile m);
public virtual int IsValidLocation() => IsValidLocation(GetWorldLocation(), Map);
public virtual int IsValidLocation(Point3D p, Map m)
{
if (m == null)
{
return 502956; // You cannot place a trap on that.
}
if (Core.ML)
{
foreach (var item in m.GetItemsAt(p))
{
if (item is BaseFactionTrap trap && trap.Faction == Faction)
{ {
return 1075263; // There is already a trap belonging to your faction at this location.; // You have earned ~1_SILVER_AMOUNT~ pieces for vanquishing ~2_PLAYER_NAME~!
Placer.SendLocalizedMessage(1042736, $"{silverGiven} silver\t{from.Name}");
} }
} }
victimState.OnGivenSilverTo(Placer);
} }
switch (AllowedPlacing)
{
case AllowedPlacing.FactionStronghold:
{
var region = Region.Find(p, m).GetRegion<StrongholdRegion>();
if (region != null && region.Faction == Faction)
{
return 0;
}
return 1010355; // This trap can only be placed in your stronghold
}
case AllowedPlacing.AnyFactionTown:
{
var town = Town.FromRegion(Region.Find(p, m));
if (town != null)
{
return 0;
}
return 1010356; // This trap can only be placed in a faction town
}
case AllowedPlacing.ControlledFactionTown:
{
var town = Town.FromRegion(Region.Find(p, m));
if (town != null && town.Owner == Faction)
{
return 0;
}
return 1010357; // This trap can only be placed in a town your faction controls
}
}
return 0;
} }
public override void OnMovement(Mobile m, Point3D oldLocation) from.LocalOverheadMessage(MessageType.Regular, MessageHue, AttackMessage);
{ }
base.OnMovement(m, oldLocation);
if (!CheckDecay() && CheckRange(m.Location, oldLocation, 6)) public abstract void DoVisibleEffect();
public abstract void DoAttackEffect(Mobile m);
public virtual int IsValidLocation() => IsValidLocation(GetWorldLocation(), Map);
public virtual int IsValidLocation(Point3D p, Map m)
{
if (m == null)
{
return 502956; // You cannot place a trap on that.
}
if (Core.ML)
{
foreach (var item in m.GetItemsAt(p))
{ {
if (Faction.Find(m) != null && if (item is BaseFactionTrap trap && trap.Faction == Faction)
(m.Skills.DetectHidden.Value - 80.0) / 20.0 > Utility.RandomDouble())
{ {
PrivateOverheadLocalizedMessage(m, 1010154, MessageHue, "", ""); // [Faction Trap] return 1075263; // There is already a trap belonging to your faction at this location.;
} }
} }
} }
public void PrivateOverheadLocalizedMessage(Mobile to, int number, int hue, string name, string args) switch (AllowedPlacing)
{ {
to?.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, name, args); case AllowedPlacing.FactionStronghold:
{
var region = Region.Find(p, m).GetRegion<StrongholdRegion>();
if (region != null && region.Faction == Faction)
{
return 0;
}
return 1010355; // This trap can only be placed in your stronghold
}
case AllowedPlacing.AnyFactionTown:
{
var town = Town.FromRegion(Region.Find(p, m));
if (town != null)
{
return 0;
}
return 1010356; // This trap can only be placed in a faction town
}
case AllowedPlacing.ControlledFactionTown:
{
var town = Town.FromRegion(Region.Find(p, m));
if (town != null && town.Owner == Faction)
{
return 0;
}
return 1010357; // This trap can only be placed in a town your faction controls
}
} }
public virtual bool CheckDecay() return 0;
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
base.OnMovement(m, oldLocation);
if (!CheckDecay() && CheckRange(m.Location, oldLocation, 6))
{ {
var decayPeriod = DecayPeriod; if (Faction.Find(m) != null &&
(m.Skills.DetectHidden.Value - 80.0) / 20.0 > Utility.RandomDouble())
if (decayPeriod == TimeSpan.MaxValue)
{ {
return false; PrivateOverheadLocalizedMessage(m, 1010154, MessageHue, "", ""); // [Faction Trap]
} }
}
}
if (TimeOfPlacement + decayPeriod < Core.Now) public void PrivateOverheadLocalizedMessage(Mobile to, int number, int hue, string name, string args)
{ {
Timer.StartTimer(Delete); to?.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, name, args);
return true; }
}
public virtual bool CheckDecay()
{
var decayPeriod = DecayPeriod;
if (decayPeriod == TimeSpan.MaxValue)
{
return false; return false;
} }
public virtual void BeginConceal() if (TimeOfPlacement + decayPeriod < Core.Now)
{ {
_concealingTimerToken.Cancel(); Timer.StartTimer(Delete);
Timer.StartTimer(ConcealPeriod, Conceal, out _concealingTimerToken); return true;
} }
public virtual void Conceal() return false;
}
public virtual void BeginConceal()
{
_concealingTimerToken.Cancel();
Timer.StartTimer(ConcealPeriod, Conceal, out _concealingTimerToken);
}
public virtual void Conceal()
{
_concealingTimerToken.Cancel();
if (!Deleted)
{ {
_concealingTimerToken.Cancel(); Visible = false;
if (!Deleted)
{
Visible = false;
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Faction.WriteReference(writer, Faction);
writer.Write(Placer);
writer.Write(TimeOfPlacement);
if (Visible)
{
BeginConceal();
}
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
Faction = Faction.ReadReference(reader);
Placer = reader.ReadEntity<Mobile>();
TimeOfPlacement = reader.ReadDateTime();
if (Visible)
{
BeginConceal();
}
CheckDecay();
}
public override void OnDelete()
{
if (Faction?.Traps.Contains(this) == true)
{
Faction.Traps.Remove(this);
}
base.OnDelete();
}
public virtual bool IsEnemy(Mobile mob)
{
if (mob.Hidden && mob.AccessLevel > AccessLevel.Player)
{
return false;
}
if (!mob.Alive || mob.IsDeadBondedPet)
{
return false;
}
var faction = Faction.Find(mob, true);
if (faction == null && mob is BaseFactionGuard guard)
{
faction = guard.Faction;
}
if (faction == null)
{
return false;
}
return faction != Faction;
} }
} }
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Faction.WriteReference(writer, Faction);
writer.Write(Placer);
writer.Write(TimeOfPlacement);
if (Visible)
{
BeginConceal();
}
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
Faction = Faction.ReadReference(reader);
Placer = reader.ReadEntity<Mobile>();
TimeOfPlacement = reader.ReadDateTime();
if (Visible)
{
BeginConceal();
}
CheckDecay();
}
public override void OnDelete()
{
if (Faction?.Traps.Contains(this) == true)
{
Faction.Traps.Remove(this);
}
base.OnDelete();
}
public virtual bool IsEnemy(Mobile mob)
{
if (mob.Hidden && mob.AccessLevel > AccessLevel.Player)
{
return false;
}
if (!mob.Alive || mob.IsDeadBondedPet)
{
return false;
}
var faction = Faction.Find(mob, true);
if (faction == null && mob is BaseFactionGuard guard)
{
faction = guard.Faction;
}
if (faction == null)
{
return false;
}
return faction != Faction;
}
}

View file

@ -2,120 +2,119 @@ using System;
using Server.Engines.Craft; using Server.Engines.Craft;
using Server.Items; using Server.Items;
namespace Server.Factions namespace Server.Factions;
public abstract class BaseFactionTrapDeed : Item, ICraftable
{ {
public abstract class BaseFactionTrapDeed : Item, ICraftable private Faction m_Faction;
public BaseFactionTrapDeed(int itemID = 0x14F0) : base(itemID)
{ {
private Faction m_Faction; Weight = 1.0;
LootType = LootType.Blessed;
}
public BaseFactionTrapDeed(int itemID = 0x14F0) : base(itemID) public BaseFactionTrapDeed(Serial serial) : base(serial)
{
}
public abstract Type TrapType { get; }
[CommandProperty(AccessLevel.GameMaster)]
public Faction Faction
{
get => m_Faction;
set
{ {
Weight = 1.0; m_Faction = value;
LootType = LootType.Blessed;
}
public BaseFactionTrapDeed(Serial serial) : base(serial) if (m_Faction != null)
{
}
public abstract Type TrapType { get; }
[CommandProperty(AccessLevel.GameMaster)]
public Faction Faction
{
get => m_Faction;
set
{ {
m_Faction = value; Hue = m_Faction.Definition.HuePrimary;
if (m_Faction != null)
{
Hue = m_Faction.Definition.HuePrimary;
}
} }
} }
}
public int OnCraft( public int OnCraft(
int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool,
CraftItem craftItem, int resHue CraftItem craftItem, int resHue
) )
{
ItemID = 0x14F0;
Faction = Faction.Find(from);
return 1;
}
public virtual BaseFactionTrap Construct(Mobile from)
{
try
{ {
ItemID = 0x14F0; return TrapType.CreateInstance<BaseFactionTrap>(m_Faction, from);
Faction = Faction.Find(from);
return 1;
} }
catch
public virtual BaseFactionTrap Construct(Mobile from)
{ {
try return null;
{
return TrapType.CreateInstance<BaseFactionTrap>(m_Faction, from);
}
catch
{
return null;
}
} }
}
public override void OnDoubleClick(Mobile from) public override void OnDoubleClick(Mobile from)
{
var faction = Faction.Find(from);
if (faction == null)
{ {
var faction = Faction.Find(from); from.SendLocalizedMessage(1010353, "", 0x23); // Only faction members may place faction traps
}
else if (faction != m_Faction)
{
from.SendLocalizedMessage(1010354, "", 0x23); // You may only place faction traps created by your faction
}
else if (faction.Traps.Count >= faction.MaximumTraps)
{
from.SendLocalizedMessage(1010358, "", 0x23); // Your faction already has the maximum number of traps placed
}
else
{
var trap = Construct(from);
if (faction == null) if (trap == null)
{ {
from.SendLocalizedMessage(1010353, "", 0x23); // Only faction members may place faction traps return;
} }
else if (faction != m_Faction)
var message = trap.IsValidLocation(from.Location, from.Map);
if (message > 0)
{ {
from.SendLocalizedMessage(1010354, "", 0x23); // You may only place faction traps created by your faction from.SendLocalizedMessage(message, "", 0x23);
} trap.Delete();
else if (faction.Traps.Count >= faction.MaximumTraps)
{
from.SendLocalizedMessage(1010358, "", 0x23); // Your faction already has the maximum number of traps placed
} }
else else
{ {
var trap = Construct(from); from.SendLocalizedMessage(1010360); // You arm the trap and carefully hide it from view
trap.MoveToWorld(from.Location, from.Map);
if (trap == null) faction.Traps.Add(trap);
{ Delete();
return;
}
var message = trap.IsValidLocation(from.Location, from.Map);
if (message > 0)
{
from.SendLocalizedMessage(message, "", 0x23);
trap.Delete();
}
else
{
from.SendLocalizedMessage(1010360); // You arm the trap and carefully hide it from view
trap.MoveToWorld(from.Location, from.Map);
faction.Traps.Add(trap);
Delete();
}
} }
} }
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Faction.WriteReference(writer, m_Faction);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
m_Faction = Faction.ReadReference(reader);
}
} }
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
Faction.WriteReference(writer, m_Faction);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
m_Faction = Faction.ReadReference(reader);
}
}

View file

@ -0,0 +1,14 @@
{
"version": 1,
"type": "Server.Factions.BaseSystemController",
"properties": [
{
"name": "LabelNumber",
"type": "int",
"rule": "PrimitiveTypeMigrationRule",
"ruleArguments": [
""
]
}
]
}