From 221312be4c5f80f1592acac3f87bb2bb5edd042b Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sun, 16 Jun 2024 11:53:15 -0700 Subject: [PATCH] fix: Stages faction code for serialization conversion (#1835) --- .../Engines/Factions/Core/Election.cs | 943 +++--- .../Engines/Factions/Core/Faction.cs | 2616 ++++++++--------- .../Engines/Factions/Core/FactionItem.cs | 247 +- .../Engines/Factions/Core/FactionState.cs | 533 ++-- .../Engines/Factions/Core/Generator.cs | 167 +- .../Engines/Factions/Core/GuardList.cs | 39 +- .../Engines/Factions/Core/Keywords.cs | 319 +- .../Engines/Factions/Core/MerchantTitles.cs | 237 +- .../Engines/Factions/Core/PlayerState.cs | 529 ++-- .../Engines/Factions/Core/Reflector.cs | 107 +- .../Engines/Factions/Core/SilverGivenEntry.cs | 31 +- .../Engines/Factions/Core/StrongholdRegion.cs | 75 +- .../UOContent/Engines/Factions/Core/Town.cs | 942 +++--- .../Engines/Factions/Core/TownState.cs | 239 +- .../Engines/Factions/Core/VendorList.cs | 39 +- .../Definitions/FactionItemDefinition.cs | 40 +- .../Engines/Factions/Gumps/ElectionGump.cs | 213 +- .../Factions/Gumps/ElectionManagementGump.cs | 331 ++- .../Engines/Factions/Gumps/FactionGump.cs | 59 +- .../Factions/Gumps/FactionImbueGump.cs | 175 +- .../Factions/Gumps/FactionStoneGump.cs | 597 ++-- .../Engines/Factions/Gumps/FinanceGump.cs | 499 ++-- .../Factions/Gumps/HorseBreederGump.cs | 153 +- .../Engines/Factions/Gumps/JoinStoneGump.cs | 79 +- .../Factions/Gumps/LeaveFactionGump.cs | 167 +- .../Engines/Factions/Gumps/SheriffGump.cs | 285 +- .../Engines/Factions/Gumps/TownStoneGump.cs | 359 +-- .../Engines/Factions/Gumps/VoteGump.cs | 105 +- .../Instances/Factions/CouncilOfMages.cs | 20 +- .../Factions/Instances/Factions/Minax.cs | 20 +- .../Instances/Factions/Shadowlords.cs | 20 +- .../Instances/Factions/TrueBritannians.cs | 22 +- .../Engines/Factions/Items/BaseMonolith.cs | 243 +- .../Factions/Items/BaseSystemController.cs | 92 +- .../Engines/Factions/Items/FactionStone.cs | 153 +- .../Engines/Factions/Items/JoinStone.cs | 143 +- .../UOContent/Engines/Factions/Items/Sigil.cs | 797 +++-- .../Factions/Items/StrongholdMonolith.cs | 61 +- .../Engines/Factions/Items/TownMonolith.cs | 61 +- .../Engines/Factions/Items/TownStone.cs | 163 +- .../Factions/Items/Traps/BaseFactionTrap.cs | 481 ++- .../Items/Traps/BaseFactionTrapDeed.cs | 183 +- ...rver.Factions.BaseSystemController.v1.json | 14 + 43 files changed, 6234 insertions(+), 6364 deletions(-) create mode 100644 Projects/UOContent/Migrations/Server.Factions.BaseSystemController.v1.json diff --git a/Projects/UOContent/Engines/Factions/Core/Election.cs b/Projects/UOContent/Engines/Factions/Core/Election.cs index cedc23d12..bf07b081e 100644 --- a/Projects/UOContent/Engines/Factions/Core/Election.cs +++ b/Projects/UOContent/Engines/Factions/Core/Election.cs @@ -3,232 +3,146 @@ using System.Collections.Generic; using System.Net; using Server.Mobiles; -namespace Server.Factions +namespace Server.Factions; + +public class Election { - public class Election + public const int MaxCandidates = 10; + public const int CandidateRank = 5; + public static readonly TimeSpan PendingPeriod = TimeSpan.FromDays(5.0); + public static readonly TimeSpan CampaignPeriod = TimeSpan.FromDays(1.0); + public static readonly TimeSpan VotingPeriod = TimeSpan.FromDays(3.0); + + private Timer _timer; + + public Election(Faction faction) { - public const int MaxCandidates = 10; - public const int CandidateRank = 5; - public static readonly TimeSpan PendingPeriod = TimeSpan.FromDays(5.0); - public static readonly TimeSpan CampaignPeriod = TimeSpan.FromDays(1.0); - public static readonly TimeSpan VotingPeriod = TimeSpan.FromDays(3.0); + Faction = faction; + Candidates = []; - private Timer _timer; + StartTimer(); + } - public Election(Faction faction) + public Election(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) { - Faction = faction; - Candidates = new List(); + case 0: + { + Faction = Faction.ReadReference(reader); - StartTimer(); - } + LastStateTime = reader.ReadDateTime(); + CurrentState = (ElectionState)reader.ReadEncodedInt(); - public Election(IGenericReader reader) - { - var version = reader.ReadEncodedInt(); + Candidates = []; - switch (version) - { - case 0: + var count = reader.ReadEncodedInt(); + + for (var i = 0; i < count; ++i) { - Faction = Faction.ReadReference(reader); + var cd = new Candidate(reader); - LastStateTime = reader.ReadDateTime(); - CurrentState = (ElectionState)reader.ReadEncodedInt(); - - Candidates = new List(); - - var count = reader.ReadEncodedInt(); - - for (var i = 0; i < count; ++i) + if (cd.Mobile != null) { - var cd = new Candidate(reader); - - if (cd.Mobile != null) - { - Candidates.Add(cd); - } - } - - break; - } - } - - StartTimer(); - } - - public Faction Faction { get; } - - public List Candidates { get; } - - public ElectionState State - { - get => CurrentState; - set - { - CurrentState = value; - LastStateTime = Core.Now; - } - } - - public DateTime LastStateTime { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public ElectionState CurrentState { get; private set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public TimeSpan NextStateTime - { - get - { - var period = CurrentState switch - { - ElectionState.Pending => PendingPeriod, - ElectionState.Election => VotingPeriod, - ElectionState.Campaign => CampaignPeriod, - _ => PendingPeriod - }; - - var until = Utility.Max(LastStateTime + period - Core.Now, TimeSpan.Zero); - - return until; - } - set - { - var period = CurrentState switch - { - ElectionState.Pending => PendingPeriod, - ElectionState.Election => VotingPeriod, - ElectionState.Campaign => CampaignPeriod, - _ => PendingPeriod - }; - - LastStateTime = Core.Now - period + value; - } - } - - public void StartTimer() - { - _timer = Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), Slice); - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - Faction.WriteReference(writer, Faction); - - writer.Write(LastStateTime); - writer.WriteEncodedInt((int)CurrentState); - - writer.WriteEncodedInt(Candidates.Count); - - for (var i = 0; i < Candidates.Count; ++i) - { - Candidates[i].Serialize(writer); - } - } - - public void AddCandidate(Mobile mob) - { - if (IsCandidate(mob)) - { - return; - } - - Candidates.Add(new Candidate(mob)); - mob.SendLocalizedMessage(1010117); // You are now running for office. - } - - public void RemoveVoter(Mobile mob) - { - if (CurrentState == ElectionState.Election) - { - for (var i = 0; i < Candidates.Count; ++i) - { - var voters = Candidates[i].Voters; - - for (var j = 0; j < voters.Count; ++j) - { - var voter = voters[j]; - - if (voter.From == mob) - { - voters.RemoveAt(j--); + Candidates.Add(cd); } } + + break; } - } } - public void RemoveCandidate(Mobile mob) + StartTimer(); + } + + public Faction Faction { get; } + + public List Candidates { get; } + + public ElectionState State + { + get => CurrentState; + set { - var cd = FindCandidate(mob); - - if (cd == null) - { - return; - } - - Candidates.Remove(cd); - mob.SendLocalizedMessage(1038031); - - if (CurrentState == ElectionState.Election) - { - if (Candidates.Count == 1) - { - // There are no longer any valid candidates in the Faction Commander election. - Faction.Broadcast(1038031); - - var winner = Candidates[0]; - - var winMob = winner.Mobile; - var pl = PlayerState.Find(winMob); - - if (pl == null || pl.Faction != Faction || winMob == Faction.Commander) - { - Faction.Broadcast(1038026); // Faction leadership has not changed. - } - else - { - Faction.Broadcast(1038028); // The faction has a new commander. - Faction.Commander = winMob; - } - - Candidates.Clear(); - State = ElectionState.Pending; - } - else if (Candidates.Count == 0) // well, I guess this'll never happen - { - // There are no longer any valid candidates in the Faction Commander election. - Faction.Broadcast(1038031); - - Candidates.Clear(); - State = ElectionState.Pending; - } - } + CurrentState = value; + LastStateTime = Core.Now; } + } - public bool IsCandidate(Mobile mob) => FindCandidate(mob) != null; + public DateTime LastStateTime { get; private set; } - public bool CanVote(Mobile mob) => CurrentState == ElectionState.Election && !HasVoted(mob); + [CommandProperty(AccessLevel.GameMaster)] + public ElectionState CurrentState { get; private set; } - public bool HasVoted(Mobile mob) => FindVoter(mob) != null; - - public Candidate FindCandidate(Mobile mob) + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public TimeSpan NextStateTime + { + get { - for (var i = 0; i < Candidates.Count; ++i) + var period = CurrentState switch { - if (Candidates[i].Mobile == mob) - { - return Candidates[i]; - } - } + ElectionState.Pending => PendingPeriod, + ElectionState.Election => VotingPeriod, + ElectionState.Campaign => CampaignPeriod, + _ => PendingPeriod + }; - return null; + var until = Utility.Max(LastStateTime + period - Core.Now, TimeSpan.Zero); + + return until; + } + set + { + var period = CurrentState switch + { + ElectionState.Pending => PendingPeriod, + ElectionState.Election => VotingPeriod, + ElectionState.Campaign => CampaignPeriod, + _ => PendingPeriod + }; + + LastStateTime = Core.Now - period + value; + } + } + + public void StartTimer() + { + _timer = Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), Slice); + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + Faction.WriteReference(writer, Faction); + + writer.Write(LastStateTime); + writer.WriteEncodedInt((int)CurrentState); + + writer.WriteEncodedInt(Candidates.Count); + + for (var i = 0; i < Candidates.Count; ++i) + { + Candidates[i].Serialize(writer); + } + } + + public void AddCandidate(Mobile mob) + { + if (IsCandidate(mob)) + { + return; } - public Candidate FindVoter(Mobile mob) + Candidates.Add(new Candidate(mob)); + mob.SendLocalizedMessage(1010117); // You are now running for office. + } + + public void RemoveVoter(Mobile mob) + { + if (CurrentState == ElectionState.Election) { for (var i = 0; i < Candidates.Count; ++i) { @@ -240,322 +154,407 @@ namespace Server.Factions if (voter.From == mob) { - return Candidates[i]; + voters.RemoveAt(j--); } } } + } + } - return null; + public void RemoveCandidate(Mobile mob) + { + var cd = FindCandidate(mob); + + if (cd == null) + { + return; } - public bool CanBeCandidate(Mobile mob) + Candidates.Remove(cd); + mob.SendLocalizedMessage(1038031); + + if (CurrentState == ElectionState.Election) { - if (IsCandidate(mob)) + if (Candidates.Count == 1) { - return false; - } + // There are no longer any valid candidates in the Faction Commander election. + Faction.Broadcast(1038031); - if (Candidates.Count >= MaxCandidates) + var winner = Candidates[0]; + + var winMob = winner.Mobile; + var pl = PlayerState.Find(winMob); + + if (pl == null || pl.Faction != Faction || winMob == Faction.Commander) + { + Faction.Broadcast(1038026); // Faction leadership has not changed. + } + else + { + Faction.Broadcast(1038028); // The faction has a new commander. + Faction.Commander = winMob; + } + + Candidates.Clear(); + State = ElectionState.Pending; + } + else if (Candidates.Count == 0) // well, I guess this'll never happen { - return false; - } + // There are no longer any valid candidates in the Faction Commander election. + Faction.Broadcast(1038031); - if (CurrentState != ElectionState.Campaign) + Candidates.Clear(); + State = ElectionState.Pending; + } + } + } + + public bool IsCandidate(Mobile mob) => FindCandidate(mob) != null; + + public bool CanVote(Mobile mob) => CurrentState == ElectionState.Election && !HasVoted(mob); + + public bool HasVoted(Mobile mob) => FindVoter(mob) != null; + + public Candidate FindCandidate(Mobile mob) + { + for (var i = 0; i < Candidates.Count; ++i) + { + if (Candidates[i].Mobile == mob) { - return false; // sanity.. + return Candidates[i]; } - - var pl = PlayerState.Find(mob); - - return pl != null && pl.Faction == Faction && pl.Rank.Rank >= CandidateRank; } - public void Slice() + return null; + } + + public Candidate FindVoter(Mobile mob) + { + for (var i = 0; i < Candidates.Count; ++i) { - if (Faction.Election != this) + var voters = Candidates[i].Voters; + + for (var j = 0; j < voters.Count; ++j) { - _timer?.Stop(); - _timer = null; - return; + var voter = voters[j]; + + if (voter.From == mob) + { + return Candidates[i]; + } } + } - switch (CurrentState) - { - case ElectionState.Pending: + return null; + } + + public bool CanBeCandidate(Mobile mob) + { + if (IsCandidate(mob)) + { + return false; + } + + if (Candidates.Count >= MaxCandidates) + { + return false; + } + + if (CurrentState != ElectionState.Campaign) + { + return false; // sanity.. + } + + var pl = PlayerState.Find(mob); + + return pl != null && pl.Faction == Faction && pl.Rank.Rank >= CandidateRank; + } + + public void Slice() + { + if (Faction.Election != this) + { + _timer?.Stop(); + _timer = null; + return; + } + + switch (CurrentState) + { + case ElectionState.Pending: + { + if (LastStateTime + PendingPeriod > Core.Now) { - if (LastStateTime + PendingPeriod > Core.Now) - { - break; - } - - Faction.Broadcast(1038023); // Campaigning for the Faction Commander election has begun. - - Candidates.Clear(); - State = ElectionState.Campaign; - break; } - case ElectionState.Campaign: + + Faction.Broadcast(1038023); // Campaigning for the Faction Commander election has begun. + + Candidates.Clear(); + State = ElectionState.Campaign; + + break; + } + case ElectionState.Campaign: + { + if (LastStateTime + CampaignPeriod > Core.Now) { - if (LastStateTime + CampaignPeriod > Core.Now) - { - break; - } - - if (Candidates.Count == 0) - { - Faction.Broadcast(1038025); // Nobody ran for office. - State = ElectionState.Pending; - } - else if (Candidates.Count == 1) - { - Faction.Broadcast(1038029); // Only one member ran for office. - - var winner = Candidates[0]; - - var mob = winner.Mobile; - var pl = PlayerState.Find(mob); - - if (pl == null || pl.Faction != Faction || mob == Faction.Commander) - { - Faction.Broadcast(1038026); // Faction leadership has not changed. - } - else - { - Faction.Broadcast(1038028); // The faction has a new commander. - Faction.Commander = mob; - } - - Candidates.Clear(); - State = ElectionState.Pending; - } - else - { - Faction.Broadcast(1038030); - State = ElectionState.Election; - } - break; } - case ElectionState.Election: + + if (Candidates.Count == 0) { - if (LastStateTime + VotingPeriod > Core.Now) - { - break; - } + Faction.Broadcast(1038025); // Nobody ran for office. + State = ElectionState.Pending; + } + else if (Candidates.Count == 1) + { + Faction.Broadcast(1038029); // Only one member ran for office. - Faction.Broadcast(1038024); // The results for the Faction Commander election are in + var winner = Candidates[0]; - Candidate winner = null; + var mob = winner.Mobile; + var pl = PlayerState.Find(mob); - for (var i = 0; i < Candidates.Count; ++i) - { - var cd = Candidates[i]; - - var pl = PlayerState.Find(cd.Mobile); - - if (pl == null || pl.Faction != Faction) - { - continue; - } - - // cd.CleanMuleVotes(); - - if (winner == null || cd.Votes > winner.Votes) - { - winner = cd; - } - } - - if (winner == null) + if (pl == null || pl.Faction != Faction || mob == Faction.Commander) { Faction.Broadcast(1038026); // Faction leadership has not changed. } - else if (winner.Mobile == Faction.Commander) - { - Faction.Broadcast(1038027); // The incumbent won the election. - } else { Faction.Broadcast(1038028); // The faction has a new commander. - Faction.Commander = winner.Mobile; + Faction.Commander = mob; } Candidates.Clear(); State = ElectionState.Pending; - - break; } - } - } - } - - public class Voter - { - public Voter(Mobile from, Mobile candidate) - { - From = from; - Candidate = candidate; - - if (From.NetState != null) - { - Address = From.NetState.Address; - } - else - { - Address = IPAddress.None; - } - - Time = Core.Now; - } - - public Voter(IGenericReader reader, Mobile candidate) - { - Candidate = candidate; - - var version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: + else { - From = reader.ReadEntity(); - Address = Utility.Intern(reader.ReadIPAddress()); - Time = reader.ReadDateTime(); - - break; + Faction.Broadcast(1038030); + State = ElectionState.Election; } - } - } - public Mobile From { get; } - - public Mobile Candidate { get; } - - public IPAddress Address { get; } - - public DateTime Time { get; } - - public object[] AcquireFields() - { - var gameTime = TimeSpan.Zero; - - if (From is PlayerMobile mobile) - { - gameTime = mobile.GameTime; - } - - var kp = PlayerState.Find(From)?.KillPoints ?? 0; - - var sk = From.Skills.Total; - - var factorSkills = 50 + sk * 100 / 10000; - var factorKillPts = 100 + kp * 2; - var factorGameTime = 50 + (int)(gameTime.Ticks * 100 / TimeSpan.TicksPerDay); - - var totalFactor = Math.Clamp(factorSkills * factorKillPts * Math.Max(factorGameTime, 100) / 10000, 0, 100); - - return new object[] { From, Address, Time, totalFactor }; - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); - - writer.Write(From); - writer.Write(Address); - writer.Write(Time); - } - } - - public class Candidate - { - public Candidate(Mobile mob) - { - Mobile = mob; - Voters = new List(); - } - - public Candidate(IGenericReader reader) - { - var version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - Mobile = reader.ReadEntity(); - - var count = reader.ReadEncodedInt(); - Voters = new List(count); - - for (var i = 0; i < count; ++i) - { - var voter = new Voter(reader, Mobile); - - if (voter.From != null) - { - Voters.Add(voter); - } - } - - break; - } - case 0: - { - Mobile = reader.ReadEntity(); - - var mobs = reader.ReadEntityList(); - Voters = new List(mobs.Count); - - for (var i = 0; i < mobs.Count; ++i) - { - Voters.Add(new Voter(mobs[i], Mobile)); - } - - break; - } - } - } - - public Mobile Mobile { get; } - - public List Voters { get; } - - public int Votes => Voters.Count; - - public void CleanMuleVotes() - { - for (var i = 0; i < Voters.Count; ++i) - { - var voter = Voters[i]; - - if ((int)voter.AcquireFields()[3] < 90) - { - Voters.RemoveAt(i--); + break; + } + case ElectionState.Election: + { + if (LastStateTime + VotingPeriod > Core.Now) + { + break; + } + + Faction.Broadcast(1038024); // The results for the Faction Commander election are in + + Candidate winner = null; + + for (var i = 0; i < Candidates.Count; ++i) + { + var cd = Candidates[i]; + + var pl = PlayerState.Find(cd.Mobile); + + if (pl == null || pl.Faction != Faction) + { + continue; + } + + // cd.CleanMuleVotes(); + + if (winner == null || cd.Votes > winner.Votes) + { + winner = cd; + } + } + + if (winner == null) + { + Faction.Broadcast(1038026); // Faction leadership has not changed. + } + else if (winner.Mobile == Faction.Commander) + { + Faction.Broadcast(1038027); // The incumbent won the election. + } + else + { + Faction.Broadcast(1038028); // The faction has a new commander. + Faction.Commander = winner.Mobile; + } + + Candidates.Clear(); + State = ElectionState.Pending; + + break; } - } } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(1); // version - - writer.Write(Mobile); - - writer.WriteEncodedInt(Voters.Count); - - for (var i = 0; i < Voters.Count; ++i) - { - Voters[i].Serialize(writer); - } - } - } - - public enum ElectionState - { - Pending, - Campaign, - Election } } + +public class Voter +{ + public Voter(Mobile from, Mobile candidate) + { + From = from; + Candidate = candidate; + + if (From.NetState != null) + { + Address = From.NetState.Address; + } + else + { + Address = IPAddress.None; + } + + Time = Core.Now; + } + + public Voter(IGenericReader reader, Mobile candidate) + { + Candidate = candidate; + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + From = reader.ReadEntity(); + Address = Utility.Intern(reader.ReadIPAddress()); + Time = reader.ReadDateTime(); + + break; + } + } + } + + public Mobile From { get; } + + public Mobile Candidate { get; } + + public IPAddress Address { get; } + + public DateTime Time { get; } + + public object[] AcquireFields() + { + var gameTime = TimeSpan.Zero; + + if (From is PlayerMobile mobile) + { + gameTime = mobile.GameTime; + } + + var kp = PlayerState.Find(From)?.KillPoints ?? 0; + + var sk = From.Skills.Total; + + var factorSkills = 50 + sk * 100 / 10000; + var factorKillPts = 100 + kp * 2; + var factorGameTime = 50 + (int)(gameTime.Ticks * 100 / TimeSpan.TicksPerDay); + + var totalFactor = Math.Clamp(factorSkills * factorKillPts * Math.Max(factorGameTime, 100) / 10000, 0, 100); + + return [From, Address, Time, totalFactor]; + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); + + writer.Write(From); + writer.Write(Address); + writer.Write(Time); + } +} + +public class Candidate +{ + public Candidate(Mobile mob) + { + Mobile = mob; + Voters = []; + } + + public Candidate(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + { + Mobile = reader.ReadEntity(); + + var count = reader.ReadEncodedInt(); + Voters = new List(count); + + for (var i = 0; i < count; ++i) + { + var voter = new Voter(reader, Mobile); + + if (voter.From != null) + { + Voters.Add(voter); + } + } + + break; + } + case 0: + { + Mobile = reader.ReadEntity(); + + var mobs = reader.ReadEntityList(); + Voters = new List(mobs.Count); + + for (var i = 0; i < mobs.Count; ++i) + { + Voters.Add(new Voter(mobs[i], Mobile)); + } + + break; + } + } + } + + public Mobile Mobile { get; } + + public List Voters { get; } + + public int Votes => Voters.Count; + + public void CleanMuleVotes() + { + for (var i = 0; i < Voters.Count; ++i) + { + var voter = Voters[i]; + + if ((int)voter.AcquireFields()[3] < 90) + { + Voters.RemoveAt(i--); + } + } + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(1); // version + + writer.Write(Mobile); + + writer.WriteEncodedInt(Voters.Count); + + for (var i = 0; i < Voters.Count; ++i) + { + Voters[i].Serialize(writer); + } + } +} + +public enum ElectionState +{ + Pending, + Campaign, + Election +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Core/Faction.cs b/Projects/UOContent/Engines/Factions/Core/Faction.cs index 407bba8df..b5ae2d8f0 100644 --- a/Projects/UOContent/Engines/Factions/Core/Faction.cs +++ b/Projects/UOContent/Engines/Factions/Core/Faction.cs @@ -10,432 +10,353 @@ using Server.Mobiles; using Server.Prompts; using Server.Targeting; -namespace Server.Factions +namespace Server.Factions; + +[CustomEnum(["Minax", "Council of Mages", "True Britannians", "Shadowlords"])] +public abstract class Faction : IComparable { - [CustomEnum(new[] { "Minax", "Council of Mages", "True Britannians", "Shadowlords" })] - public abstract class Faction : IComparable + public const int StabilityFactor = 300; // 300% greater (3 times) than smallest faction + public const int StabilityActivation = 200; // Stability code goes into effect when largest faction has > 200 people + + public const double SkillLossFactor = 1.0 / 3; + + public static readonly TimeSpan LeavePeriod = TimeSpan.FromDays(3.0); + + public static readonly Map Facet = Map.Felucca; + public static readonly TimeSpan SkillLossPeriod = TimeSpan.FromMinutes(20.0); + + private static readonly Dictionary m_SkillLoss = new(); + + private FactionDefinition m_Definition; + public int ZeroRankOffset; + + public Faction() => State = new FactionState(this); + + public StrongholdRegion StrongholdRegion { get; set; } + + public FactionDefinition Definition { - public const int StabilityFactor = 300; // 300% greater (3 times) than smallest faction - public const int StabilityActivation = 200; // Stability code goes into effect when largest faction has > 200 people - - public const double SkillLossFactor = 1.0 / 3; - - public static readonly TimeSpan LeavePeriod = TimeSpan.FromDays(3.0); - - public static readonly Map Facet = Map.Felucca; - public static readonly TimeSpan SkillLossPeriod = TimeSpan.FromMinutes(20.0); - - private static readonly Dictionary - m_SkillLoss = new(); - - private FactionDefinition m_Definition; - public int ZeroRankOffset; - - public Faction() => State = new FactionState(this); - - public StrongholdRegion StrongholdRegion { get; set; } - - public FactionDefinition Definition + get => m_Definition; + set { - get => m_Definition; - set - { - m_Definition = value; - StrongholdRegion = new StrongholdRegion(this); - } + m_Definition = value; + StrongholdRegion = new StrongholdRegion(this); + } + } + + public FactionState State { get; set; } + + public Election Election + { + get => State.Election; + set => State.Election = value; + } + + public Mobile Commander + { + get => State.Commander; + set => State.Commander = value; + } + + public int Tithe + { + get => State.Tithe; + set => State.Tithe = value; + } + + public int Silver + { + get => State.Silver; + set => State.Silver = value; + } + + public List Members + { + get => State.Members; + set => State.Members = value; + } + + public bool FactionMessageReady => State.FactionMessageReady; + + public virtual int MaximumTraps => 15; + + public List Traps + { + get => State.Traps; + set => State.Traps = value; + } + + public static List Factions => Reflector.Factions; + + public int CompareTo(Faction f) => m_Definition.Sort - (f?.m_Definition.Sort ?? 0); + + public void Broadcast(string text) + { + Broadcast(0x3B2, text); + } + + public void Broadcast(int hue, string text) + { + var members = Members; + + for (var i = 0; i < members.Count; ++i) + { + members[i].Mobile.SendMessage(hue, text); + } + } + + public void Broadcast(int number) + { + var members = Members; + + for (var i = 0; i < members.Count; ++i) + { + members[i].Mobile.SendLocalizedMessage(number); + } + } + + public void BeginBroadcast(Mobile from) + { + from.SendLocalizedMessage(1010265); // Enter Faction Message + from.Prompt = new BroadcastPrompt(this); + } + + public void EndBroadcast(Mobile from, string text) + { + if (from.AccessLevel == AccessLevel.Player) + { + State.RegisterBroadcast(); } - public FactionState State { get; set; } + Broadcast(Definition.HueBroadcast, $"{from.Name} [Commander] {Definition.FriendlyName} : {text}"); + } - public Election Election + public static void HandleAtrophy() + { + foreach (var f in Factions) { - get => State.Election; - set => State.Election = value; - } - - public Mobile Commander - { - get => State.Commander; - set => State.Commander = value; - } - - public int Tithe - { - get => State.Tithe; - set => State.Tithe = value; - } - - public int Silver - { - get => State.Silver; - set => State.Silver = value; - } - - public List Members - { - get => State.Members; - set => State.Members = value; - } - - public bool FactionMessageReady => State.FactionMessageReady; - - public virtual int MaximumTraps => 15; - - public List Traps - { - get => State.Traps; - set => State.Traps = value; - } - - public static List Factions => Reflector.Factions; - - public int CompareTo(Faction f) => m_Definition.Sort - (f?.m_Definition.Sort ?? 0); - - public void Broadcast(string text) - { - Broadcast(0x3B2, text); - } - - public void Broadcast(int hue, string text) - { - var members = Members; - - for (var i = 0; i < members.Count; ++i) - { - members[i].Mobile.SendMessage(hue, text); - } - } - - public void Broadcast(int number) - { - var members = Members; - - for (var i = 0; i < members.Count; ++i) - { - members[i].Mobile.SendLocalizedMessage(number); - } - } - - public void BeginBroadcast(Mobile from) - { - from.SendLocalizedMessage(1010265); // Enter Faction Message - from.Prompt = new BroadcastPrompt(this); - } - - public void EndBroadcast(Mobile from, string text) - { - if (from.AccessLevel == AccessLevel.Player) - { - State.RegisterBroadcast(); - } - - Broadcast(Definition.HueBroadcast, $"{from.Name} [Commander] {Definition.FriendlyName} : {text}"); - } - - public static void HandleAtrophy() - { - foreach (var f in Factions) - { - if (!f.State.IsAtrophyReady) - { - return; - } - } - - var activePlayers = new List(); - - foreach (var f in Factions) - { - foreach (var ps in f.Members) - { - if (ps.KillPoints > 0 && ps.IsActive) - { - activePlayers.Add(ps); - } - } - } - - var distrib = 0; - - foreach (var f in Factions) - { - distrib += f.State.CheckAtrophy(); - } - - if (activePlayers.Count == 0) + if (!f.State.IsAtrophyReady) { return; } + } + var activePlayers = new List(); + + foreach (var f in Factions) + { + foreach (var ps in f.Members) + { + if (ps.KillPoints > 0 && ps.IsActive) + { + activePlayers.Add(ps); + } + } + } + + var distrib = 0; + + foreach (var f in Factions) + { + distrib += f.State.CheckAtrophy(); + } + + if (activePlayers.Count == 0) + { + return; + } + + for (var i = 0; i < distrib; ++i) + { + activePlayers.RandomElement().KillPoints++; + } + } + + public static void DistributePoints(int distrib) + { + var activePlayers = new List(); + + foreach (var f in Factions) + { + foreach (var ps in f.Members) + { + if (ps.KillPoints > 0 && ps.IsActive) + { + activePlayers.Add(ps); + } + } + } + + if (activePlayers.Count > 0) + { for (var i = 0; i < distrib; ++i) { activePlayers.RandomElement().KillPoints++; } } + } - public static void DistributePoints(int distrib) + public void BeginHonorLeadership(Mobile from) + { + from.SendLocalizedMessage(502090); // Click on the player whom you wish to honor. + from.BeginTarget(12, false, TargetFlags.None, HonorLeadership_OnTarget); + } + + private static void HonorLeadership_OnTarget(Mobile from, object obj) + { + if (obj is not Mobile recv) { - var activePlayers = new List(); + from.SendLocalizedMessage(1042496); // You may only honor another player. + return; + } - foreach (var f in Factions) - { - foreach (var ps in f.Members) - { - if (ps.KillPoints > 0 && ps.IsActive) - { - activePlayers.Add(ps); - } - } - } + var giveState = PlayerState.Find(from); + var recvState = PlayerState.Find(recv); - if (activePlayers.Count > 0) + if (giveState == null) + { + return; + } + + if (recvState == null || recvState.Faction != giveState.Faction) + { + from.SendLocalizedMessage(1042497); // Only faction mates can be honored this way. + } + else if (giveState.KillPoints < 5) + { + from.SendLocalizedMessage(1042499); // You must have at least five kill points to honor them. + } + else + { + recvState.LastHonorTime = Core.Now; + giveState.KillPoints -= 5; + recvState.KillPoints += 4; + + // TODO: Confirm no message sent to giver + recv.SendLocalizedMessage(1042500); // You have been honored with four kill points. + } + } + + public virtual void AddMember(Mobile mob) + { + Members.Insert(ZeroRankOffset, new PlayerState(mob, this, Members)); + + mob.AddToBackpack(FactionItem.Imbue(new Robe(), this, false, Definition.HuePrimary)); + mob.SendLocalizedMessage(1010374); // You have been granted a robe which signifies your faction + + mob.InvalidateProperties(); + mob.Delta(MobileDelta.Noto); + + mob.FixedEffect(0x373A, 10, 30); + mob.PlaySound(0x209); + } + + public static bool IsNearType(Mobile mob, Type type, int range) + { + if (type.IsAssignableTo(typeof(Mobile))) + { + foreach (var obj in mob.Map.GetMobilesInRange(mob.Location, range)) { - for (var i = 0; i < distrib; ++i) + if (type.IsInstanceOfType(obj)) { - activePlayers.RandomElement().KillPoints++; + return true; } } } - public void BeginHonorLeadership(Mobile from) + if (type.IsAssignableTo(typeof(Item))) { - from.SendLocalizedMessage(502090); // Click on the player whom you wish to honor. - from.BeginTarget(12, false, TargetFlags.None, HonorLeadership_OnTarget); - } - - public void HonorLeadership_OnTarget(Mobile from, object obj) - { - if (obj is Mobile recv) + foreach (var item in mob.Map.GetItemsInRange(mob.Location, range)) { - var giveState = PlayerState.Find(from); - var recvState = PlayerState.Find(recv); - - if (giveState == null) + if (type.IsInstanceOfType(item)) { - return; + return true; } - - if (recvState == null || recvState.Faction != giveState.Faction) - { - from.SendLocalizedMessage(1042497); // Only faction mates can be honored this way. - } - else if (giveState.KillPoints < 5) - { - from.SendLocalizedMessage(1042499); // You must have at least five kill points to honor them. - } - else - { - recvState.LastHonorTime = Core.Now; - giveState.KillPoints -= 5; - recvState.KillPoints += 4; - - // TODO: Confirm no message sent to giver - recv.SendLocalizedMessage(1042500); // You have been honored with four kill points. - } - } - else - { - from.SendLocalizedMessage(1042496); // You may only honor another player. } } - public virtual void AddMember(Mobile mob) - { - Members.Insert(ZeroRankOffset, new PlayerState(mob, this, Members)); - - mob.AddToBackpack(FactionItem.Imbue(new Robe(), this, false, Definition.HuePrimary)); - mob.SendLocalizedMessage(1010374); // You have been granted a robe which signifies your faction - - mob.InvalidateProperties(); - mob.Delta(MobileDelta.Noto); - - mob.FixedEffect(0x373A, 10, 30); - mob.PlaySound(0x209); - } - - public static bool IsNearType(Mobile mob, Type type, int range) + return false; + } + + public static bool IsNearType(Mobile mob, Type[] types, int range) + { + bool mobs = false; + bool items = false; + for (var i = 0; !(mobs && items) && i < types.Length; i++) { + var type = types[i]; if (type.IsAssignableTo(typeof(Mobile))) { - foreach (var obj in mob.Map.GetMobilesInRange(mob.Location, range)) - { - if (type.IsInstanceOfType(obj)) - { - return true; - } - } + mobs = true; } if (type.IsAssignableTo(typeof(Item))) { - foreach (var item in mob.Map.GetItemsInRange(mob.Location, range)) - { - if (type.IsInstanceOfType(item)) - { - return true; - } - } - } - - return false; - } - - public static bool IsNearType(Mobile mob, Type[] types, int range) - { - bool mobs = false; - bool items = false; - for (var i = 0; !(mobs && items) && i < types.Length; i++) - { - var type = types[i]; - if (type.IsAssignableTo(typeof(Mobile))) - { - mobs = true; - } - - if (type.IsAssignableTo(typeof(Item))) - { - items = true; - } - } - - if (mobs) - { - foreach (var m in mob.Map.GetMobilesInRange(mob.Location, range)) - { - if (m.InTypeList(types)) - { - return true; - } - } - } - - if (items) - { - foreach (var item in mob.Map.GetItemsInRange(mob.Location, range)) - { - if (item.InTypeList(types)) - { - return true; - } - } - } - - return false; - } - - public void RemovePlayerState(PlayerState pl) - { - if (pl == null || !Members.Contains(pl)) - { - return; - } - - var killPoints = pl.KillPoints; - - if (pl.RankIndex != -1) - { - while (pl.RankIndex + 1 < ZeroRankOffset) - { - var pNext = Members[pl.RankIndex + 1]; - Members[pl.RankIndex + 1] = pl; - Members[pl.RankIndex] = pNext; - pl.RankIndex++; - pNext.RankIndex--; - } - - ZeroRankOffset--; - } - - Members.Remove(pl); - - var pm = (PlayerMobile)pl.Mobile; - if (pm == null) - { - return; - } - - var mob = pl.Mobile; - if (pm.FactionPlayerState == pl) - { - pm.FactionPlayerState = null; - - mob.InvalidateProperties(); - mob.Delta(MobileDelta.Noto); - - if (Election.IsCandidate(mob)) - { - Election.RemoveCandidate(mob); - } - - if (pl.Finance != null) - { - pl.Finance.Finance = null; - } - - if (pl.Sheriff != null) - { - pl.Sheriff.Sheriff = null; - } - - Election.RemoveVoter(mob); - - if (Commander == mob) - { - Commander = null; - } - - pm.ValidateEquipment(); - } - - if (killPoints > 0) - { - DistributePoints(killPoints); + items = true; } } - public void RemoveMember(Mobile mob) + if (mobs) { - var pl = PlayerState.Find(mob); - - if (pl == null || !Members.Contains(pl)) + foreach (var m in mob.Map.GetMobilesInRange(mob.Location, range)) { - return; - } - - var killPoints = pl.KillPoints; - - // Ordinarily, through normal faction removal, this will never find any sigils. - // Only with a leave delay less than the ReturnPeriod or a Faction Kick/Ban, will this ever do anything - - if (mob.Backpack != null) - { - foreach (var sigil in mob.Backpack.EnumerateItemsByType()) + if (m.InTypeList(types)) { - sigil.ReturnHome(); + return true; } } + } - if (pl.RankIndex != -1) + if (items) + { + foreach (var item in mob.Map.GetItemsInRange(mob.Location, range)) { - while (pl.RankIndex + 1 < ZeroRankOffset) + if (item.InTypeList(types)) { - var pNext = Members[pl.RankIndex + 1]; - Members[pl.RankIndex + 1] = pl; - Members[pl.RankIndex] = pNext; - pl.RankIndex++; - pNext.RankIndex--; + return true; } - - ZeroRankOffset--; } + } - Members.Remove(pl); + return false; + } - if (mob is PlayerMobile mobile) + public void RemovePlayerState(PlayerState pl) + { + if (pl == null || !Members.Contains(pl)) + { + return; + } + + var killPoints = pl.KillPoints; + + if (pl.RankIndex != -1) + { + while (pl.RankIndex + 1 < ZeroRankOffset) { - mobile.FactionPlayerState = null; + var pNext = Members[pl.RankIndex + 1]; + Members[pl.RankIndex + 1] = pl; + Members[pl.RankIndex] = pNext; + pl.RankIndex++; + pNext.RankIndex--; } + ZeroRankOffset--; + } + + Members.Remove(pl); + + var pm = (PlayerMobile)pl.Mobile; + if (pm == null) + { + return; + } + + var mob = pl.Mobile; + if (pm.FactionPlayerState == pl) + { + pm.FactionPlayerState = null; + mob.InvalidateProperties(); mob.Delta(MobileDelta.Noto); @@ -444,8 +365,6 @@ namespace Server.Factions Election.RemoveCandidate(mob); } - Election.RemoveVoter(mob); - if (pl.Finance != null) { pl.Finance.Finance = null; @@ -456,154 +375,192 @@ namespace Server.Factions pl.Sheriff.Sheriff = null; } + Election.RemoveVoter(mob); + if (Commander == mob) { Commander = null; } - if (mob is PlayerMobile playerMobile) - { - playerMobile.ValidateEquipment(); - } - - if (killPoints > 0) - { - DistributePoints(killPoints); - } + pm.ValidateEquipment(); } - public void JoinGuilded(PlayerMobile mob, Guild guild) + if (killPoints > 0) { - if (mob.Young) + DistributePoints(killPoints); + } + } + + public void RemoveMember(Mobile mob) + { + var pl = PlayerState.Find(mob); + + if (pl == null || !Members.Contains(pl)) + { + return; + } + + var killPoints = pl.KillPoints; + + // Ordinarily, through normal faction removal, this will never find any sigils. + // Only with a leave delay less than the ReturnPeriod or a Faction Kick/Ban, will this ever do anything + + if (mob.Backpack != null) + { + foreach (var sigil in mob.Backpack.EnumerateItemsByType()) { - guild.RemoveMember(mob); - // You have been kicked out of your guild! - // Young players may not remain in a guild which is allied with a faction. - mob.SendLocalizedMessage(1042283); - } - else if (AlreadyHasCharInFaction(mob)) - { - guild.RemoveMember(mob); - mob.SendLocalizedMessage(1005281); // You have been kicked out of your guild due to factional overlap - } - else if (IsFactionBanned(mob)) - { - guild.RemoveMember(mob); - mob.SendLocalizedMessage(1005052); // You are currently banned from the faction system - } - else - { - AddMember(mob); - // You are now joining a faction: - mob.SendLocalizedMessage(1042756, true, $" {m_Definition.FriendlyName}"); + sigil.ReturnHome(); } } - public void JoinAlone(Mobile mob) + if (pl.RankIndex != -1) + { + while (pl.RankIndex + 1 < ZeroRankOffset) + { + var pNext = Members[pl.RankIndex + 1]; + Members[pl.RankIndex + 1] = pl; + Members[pl.RankIndex] = pNext; + pl.RankIndex++; + pNext.RankIndex--; + } + + ZeroRankOffset--; + } + + Members.Remove(pl); + + if (mob is PlayerMobile mobile) + { + mobile.FactionPlayerState = null; + } + + mob.InvalidateProperties(); + mob.Delta(MobileDelta.Noto); + + if (Election.IsCandidate(mob)) + { + Election.RemoveCandidate(mob); + } + + Election.RemoveVoter(mob); + + if (pl.Finance != null) + { + pl.Finance.Finance = null; + } + + if (pl.Sheriff != null) + { + pl.Sheriff.Sheriff = null; + } + + if (Commander == mob) + { + Commander = null; + } + + if (mob is PlayerMobile playerMobile) + { + playerMobile.ValidateEquipment(); + } + + if (killPoints > 0) + { + DistributePoints(killPoints); + } + } + + public void JoinGuilded(PlayerMobile mob, Guild guild) + { + if (mob.Young) + { + guild.RemoveMember(mob); + // You have been kicked out of your guild! + // Young players may not remain in a guild which is allied with a faction. + mob.SendLocalizedMessage(1042283); + } + else if (AlreadyHasCharInFaction(mob)) + { + guild.RemoveMember(mob); + mob.SendLocalizedMessage(1005281); // You have been kicked out of your guild due to factional overlap + } + else if (IsFactionBanned(mob)) + { + guild.RemoveMember(mob); + mob.SendLocalizedMessage(1005052); // You are currently banned from the faction system + } + else { AddMember(mob); - mob.SendLocalizedMessage(1005058); // You have joined the faction + // You are now joining a faction: + mob.SendLocalizedMessage(1042756, true, $" {m_Definition.FriendlyName}"); } + } - private bool AlreadyHasCharInFaction(Mobile mob) + public void JoinAlone(Mobile mob) + { + AddMember(mob); + mob.SendLocalizedMessage(1005058); // You have joined the faction + } + + private static bool AlreadyHasCharInFaction(Mobile mob) + { + if (mob.Account is Account acct) { - if (mob.Account is Account acct) + for (var i = 0; i < acct.Length; ++i) { - for (var i = 0; i < acct.Length; ++i) - { - var c = acct[i]; + var c = acct[i]; - if (Find(c) != null) - { - return true; - } + if (Find(c) != null) + { + return true; } } + } + return false; + } + + public static bool IsFactionBanned(Mobile mob) + { + if (mob.Account is not Account acct) + { return false; } - public static bool IsFactionBanned(Mobile mob) - { - if (mob.Account is not Account acct) - { - return false; - } + return acct.GetTag("FactionBanned") != null; + } - return acct.GetTag("FactionBanned") != null; + public void OnJoinAccepted(Mobile mob) + { + if (mob is not PlayerMobile pm) + { + return; // sanity } - public void OnJoinAccepted(Mobile mob) + var pl = PlayerState.Find(pm); + + if (pm.Young) { - if (mob is not PlayerMobile pm) - { - return; // sanity - } - - var pl = PlayerState.Find(pm); - - if (pm.Young) - { - pm.SendLocalizedMessage(1010104); // You cannot join a faction as a young player - } - else if (pl?.IsLeaving == true) - { - // You cannot use the faction stone until you have finished quitting your current faction - pm.SendLocalizedMessage(1005051); - } - else if (AlreadyHasCharInFaction(pm)) - { - // You cannot join a faction because you already declared your allegiance with another character - pm.SendLocalizedMessage(1005059); - } - else if (IsFactionBanned(mob)) - { - pm.SendLocalizedMessage(1005052); // You are currently banned from the faction system - } - else if (pm.Guild != null) - { - var guild = pm.Guild as Guild; - - if (guild?.Leader != pm) - { - // You cannot join a faction because you are in a guild and not the guildmaster - pm.SendLocalizedMessage(1005057); - } - else if (guild.Type != GuildType.Regular) - { - // You cannot join a faction because your guild is an Order or Chaos type. - pm.SendLocalizedMessage(1042161); - } - else if (!Guild.NewGuildSystem && guild.Enemies?.Count > 0) // CAN join w/wars in new system - { - pm.SendLocalizedMessage(1005056); // You cannot join a faction with active Wars - } - else if (Guild.NewGuildSystem && guild.Alliance != null) - { - // Your guild cannot join a faction while in alliance with non-factioned guilds. - pm.SendLocalizedMessage(1080454); - } - else if (!CanHandleInflux(guild.Members.Count)) - { - // In the interest of faction stability, this faction declines to accept new members for now. - pm.SendLocalizedMessage(1018031); - } - else - { - var members = new List(guild.Members); - - for (var i = 0; i < members.Count; ++i) - { - if (members[i] is not PlayerMobile member) - { - continue; - } - - JoinGuilded(member, guild); - } - } - } - else if (!CanHandleInflux(1)) + pm.SendLocalizedMessage(1010104); // You cannot join a faction as a young player + } + else if (pl?.IsLeaving == true) + { + // You cannot use the faction stone until you have finished quitting your current faction + pm.SendLocalizedMessage(1005051); + } + else if (AlreadyHasCharInFaction(pm)) + { + // You cannot join a faction because you already declared your allegiance with another character + pm.SendLocalizedMessage(1005059); + } + else if (IsFactionBanned(mob)) + { + pm.SendLocalizedMessage(1005052); // You are currently banned from the faction system + } + else if (pm.Guild is not Guild guild) + { + if (!CanHandleInflux(1)) { // In the interest of faction stability, this faction declines to accept new members for now. pm.SendLocalizedMessage(1018031); @@ -613,564 +570,655 @@ namespace Server.Factions JoinAlone(mob); } } - - public bool IsCommander(Mobile mob) => mob?.AccessLevel >= AccessLevel.GameMaster || mob == Commander; - - public override string ToString() => m_Definition.FriendlyName; - - public static bool CheckLeaveTimer(Mobile mob) + else if (guild?.Leader != pm) { - var pl = PlayerState.Find(mob); - - if (pl?.IsLeaving != true) - { - return false; - } - - if (pl.Leaving + LeavePeriod >= Core.Now) - { - return false; - } - - mob.SendLocalizedMessage(1005163); // You have now quit your faction - - pl.Faction.RemoveMember(mob); - - return true; + // You cannot join a faction because you are in a guild and not the guildmaster + pm.SendLocalizedMessage(1005057); } - - public static void Configure() + else if (guild.Type != GuildType.Regular) { - EventSink.Logout += EventSink_Logout; - - CommandSystem.Register("FactionElection", AccessLevel.GameMaster, FactionElection_OnCommand); - CommandSystem.Register("FactionCommander", AccessLevel.Administrator, FactionCommander_OnCommand); - CommandSystem.Register("FactionItemReset", AccessLevel.Administrator, FactionItemReset_OnCommand); - CommandSystem.Register("FactionReset", AccessLevel.Administrator, FactionReset_OnCommand); - CommandSystem.Register("FactionTownReset", AccessLevel.Administrator, FactionTownReset_OnCommand); + // You cannot join a faction because your guild is an Order or Chaos type. + pm.SendLocalizedMessage(1042161); } - - public static void Initialize() + else if (!Guild.NewGuildSystem && guild.Enemies?.Count > 0) // CAN join w/wars in new system { - Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(10.0), HandleAtrophy); - Timer.DelayCall(TimeSpan.FromSeconds(30.0), TimeSpan.FromSeconds(30.0), ProcessTick); + pm.SendLocalizedMessage(1005056); // You cannot join a faction with active Wars } - - [Usage("FactionTownReset")] - [Description("Resets all faction town data in the world.")] - public static void FactionTownReset_OnCommand(CommandEventArgs e) + else if (Guild.NewGuildSystem && guild.Alliance != null) { - var monoliths = BaseMonolith.Monoliths; - - for (var i = 0; i < monoliths.Count; ++i) - { - monoliths[i].Sigil = null; - } - - var towns = Town.Towns; - - for (var i = 0; i < towns.Count; ++i) - { - towns[i].Silver = 0; - towns[i].Sheriff = null; - towns[i].Finance = null; - towns[i].Tax = 0; - towns[i].Owner = null; - } - - var sigils = Sigil.Sigils; - - for (var i = 0; i < sigils.Count; ++i) - { - sigils[i].Corrupted = null; - sigils[i].Corrupting = null; - sigils[i].LastStolen = DateTime.MinValue; - sigils[i].GraceStart = DateTime.MinValue; - sigils[i].CorruptionStart = DateTime.MinValue; - sigils[i].PurificationStart = DateTime.MinValue; - sigils[i].LastMonolith = null; - sigils[i].ReturnHome(); - } - - var factions = Factions; - - for (var i = 0; i < factions.Count; ++i) - { - var f = factions[i]; - - var list = new List(f.State.FactionItems); - - for (var j = 0; j < list.Count; ++j) - { - var fi = list[j]; - - if (fi.Expiration == DateTime.MinValue) - { - fi.Item.Delete(); - } - else - { - fi.Detach(); - } - } - } + // Your guild cannot join a faction while in alliance with non-factioned guilds. + pm.SendLocalizedMessage(1080454); } - - [Usage("FactionReset")] - [Description("Resets all faction data in the world.")] - public static void FactionReset_OnCommand(CommandEventArgs e) + else if (!CanHandleInflux(guild.Members.Count)) { - var monoliths = BaseMonolith.Monoliths; - - for (var i = 0; i < monoliths.Count; ++i) - { - monoliths[i].Sigil = null; - } - - var towns = Town.Towns; - - for (var i = 0; i < towns.Count; ++i) - { - towns[i].Silver = 0; - towns[i].Sheriff = null; - towns[i].Finance = null; - towns[i].Tax = 0; - towns[i].Owner = null; - } - - var sigils = Sigil.Sigils; - - for (var i = 0; i < sigils.Count; ++i) - { - sigils[i].Corrupted = null; - sigils[i].Corrupting = null; - sigils[i].LastStolen = DateTime.MinValue; - sigils[i].GraceStart = DateTime.MinValue; - sigils[i].CorruptionStart = DateTime.MinValue; - sigils[i].PurificationStart = DateTime.MinValue; - sigils[i].LastMonolith = null; - sigils[i].ReturnHome(); - } - - var factions = Factions; - - for (var i = 0; i < factions.Count; ++i) - { - var f = factions[i]; - - var playerStateList = new List(f.Members); - - for (var j = 0; j < playerStateList.Count; ++j) - { - f.RemoveMember(playerStateList[j].Mobile); - } - - var factionItemList = new List(f.State.FactionItems); - - for (var j = 0; j < factionItemList.Count; ++j) - { - var fi = factionItemList[j]; - - if (fi.Expiration == DateTime.MinValue) - { - fi.Item.Delete(); - } - else - { - fi.Detach(); - } - } - - var factionTrapList = new List(f.Traps); - - for (var j = 0; j < factionTrapList.Count; ++j) - { - factionTrapList[j].Delete(); - } - } + // In the interest of faction stability, this faction declines to accept new members for now. + pm.SendLocalizedMessage(1018031); } - - [Usage("FactionItemReset")] - [Description("Resets all faction items in the world.")] - public static void FactionItemReset_OnCommand(CommandEventArgs e) + else { - var items = new List(); + var members = new List(guild.Members); - foreach (var item in World.Items.Values) + for (var i = 0; i < members.Count; ++i) { - if (item is IFactionItem && item is not HoodedShroudOfShadows) - { - items.Add(item); - } - } - - var hues = new int[Factions.Count * 2]; - - for (var i = 0; i < Factions.Count; ++i) - { - hues[0 + i * 2] = Factions[i].Definition.HuePrimary; - hues[1 + i * 2] = Factions[i].Definition.HueSecondary; - } - - var count = 0; - - for (var i = 0; i < items.Count; ++i) - { - var item = items[i]; - var fci = (IFactionItem)item; - - if (fci.FactionItemState != null || item.LootType != LootType.Blessed) + if (members[i] is not PlayerMobile member) { continue; } - var isHued = false; - - for (var j = 0; j < hues.Length; ++j) - { - if (item.Hue == hues[j]) - { - isHued = true; - break; - } - } - - if (isHued) - { - fci.FactionItemState = null; - ++count; - } - } - - e.Mobile.SendMessage($"{count} items reset"); - } - - [Usage("FactionCommander")] - [Description("Sets the targeted player as the faction commander.")] - public static void FactionCommander_OnCommand(CommandEventArgs e) - { - e.Mobile.SendMessage("Target a player to make them the faction commander."); - e.Mobile.BeginTarget(-1, false, TargetFlags.None, FactionCommander_OnTarget); - } - - public static void FactionCommander_OnTarget(Mobile from, object obj) - { - if (obj is PlayerMobile mobile) - { - Mobile targ = mobile; - var pl = PlayerState.Find(targ); - - if (pl != null) - { - pl.Faction.Commander = targ; - from.SendMessage("You have appointed them as the faction commander."); - } - else - { - from.SendMessage("They are not in a faction."); - } - } - else - { - from.SendMessage("That is not a player."); + JoinGuilded(member, guild); } } + } - [Usage("FactionElection")] - [Description("Opens the election properties for the targeted faction stone.")] - public static void FactionElection_OnCommand(CommandEventArgs e) + public bool IsCommander(Mobile mob) => mob?.AccessLevel >= AccessLevel.GameMaster || mob == Commander; + + public override string ToString() => m_Definition.FriendlyName; + + public static bool CheckLeaveTimer(Mobile mob) + { + var pl = PlayerState.Find(mob); + + if (pl?.IsLeaving != true) { - e.Mobile.SendMessage("Target a faction stone to open its election properties."); - e.Mobile.BeginTarget(-1, false, TargetFlags.None, FactionElection_OnTarget); - } - - public static void FactionElection_OnTarget(Mobile from, object obj) - { - if (obj is FactionStone stone) - { - var faction = stone.Faction; - - if (faction != null) - { - from.SendGump(new ElectionManagementGump(faction.Election)); - } - // from.SendGump( new Gumps.PropertiesGump( from, faction.Election ) ); - else - { - from.SendMessage("That stone has no faction assigned."); - } - } - else - { - from.SendMessage("That is not a faction stone."); - } - } - - public static void FactionKick_OnCommand(CommandEventArgs e) - { - e.Mobile.SendMessage("Target a player to remove them from their faction."); - e.Mobile.BeginTarget(-1, false, TargetFlags.None, FactionKick_OnTarget); - } - - public static void FactionKick_OnTarget(Mobile from, object obj) - { - if (obj is Mobile mob) - { - var pl = PlayerState.Find(mob); - - if (pl != null) - { - pl.Faction.RemoveMember(mob); - - mob.SendMessage("You have been kicked from your faction."); - from.SendMessage("They have been kicked from their faction."); - } - else - { - from.SendMessage("They are not in a faction."); - } - } - else - { - from.SendMessage("That is not a player."); - } - } - - public static void ProcessTick() - { - var sigils = Sigil.Sigils; - - for (var i = 0; i < sigils.Count; ++i) - { - var sigil = sigils[i]; - - if (!sigil.IsBeingCorrupted && sigil.GraceStart != DateTime.MinValue && - sigil.GraceStart + Sigil.CorruptionGrace < Core.Now) - { - if (sigil.LastMonolith is StrongholdMonolith && - (sigil.Corrupted == null || sigil.LastMonolith.Faction != sigil.Corrupted)) - { - sigil.Corrupting = sigil.LastMonolith.Faction; - sigil.CorruptionStart = Core.Now; - } - else - { - sigil.Corrupting = null; - sigil.CorruptionStart = DateTime.MinValue; - } - - sigil.GraceStart = DateTime.MinValue; - } - - if (sigil.LastMonolith?.Sigil == null) - { - if (sigil.LastStolen + Sigil.ReturnPeriod < Core.Now) - { - sigil.ReturnHome(); - } - } - else - { - if (sigil.IsBeingCorrupted && sigil.CorruptionStart + Sigil.CorruptionPeriod < Core.Now) - { - sigil.Corrupted = sigil.Corrupting; - sigil.Corrupting = null; - sigil.CorruptionStart = DateTime.MinValue; - sigil.GraceStart = DateTime.MinValue; - } - else if (sigil.IsPurifying && sigil.PurificationStart + Sigil.PurificationPeriod < Core.Now) - { - sigil.PurificationStart = DateTime.MinValue; - sigil.Corrupted = null; - sigil.Corrupting = null; - sigil.CorruptionStart = DateTime.MinValue; - sigil.GraceStart = DateTime.MinValue; - } - } - } - } - - public static void HandleDeath(Mobile mob) - { - HandleDeath(mob, null); - } - - public int AwardSilver(Mobile mob, int silver) - { - if (silver <= 0) - { - return 0; - } - - var tithed = silver * Tithe / 100; - - Silver += tithed; - - silver = silver - tithed; - - if (silver > 0) - { - mob.AddToBackpack(new Silver(silver)); - } - - return silver; - } - - public static Faction FindSmallestFaction() - { - var factions = Factions; - Faction smallest = null; - - for (var i = 0; i < factions.Count; ++i) - { - var faction = factions[i]; - - if (smallest == null || faction.Members.Count < smallest.Members.Count) - { - smallest = faction; - } - } - - return smallest; - } - - public static bool StabilityActive() - { - var factions = Factions; - - for (var i = 0; i < factions.Count; ++i) - { - var faction = factions[i]; - - if (faction.Members.Count > StabilityActivation) - { - return true; - } - } - return false; } - public bool CanHandleInflux(int influx) + if (pl.Leaving + LeavePeriod >= Core.Now) { - if (!StabilityActive()) + return false; + } + + mob.SendLocalizedMessage(1005163); // You have now quit your faction + + pl.Faction.RemoveMember(mob); + + return true; + } + + public static void Configure() + { + EventSink.Logout += EventSink_Logout; + + CommandSystem.Register("FactionElection", AccessLevel.GameMaster, FactionElection_OnCommand); + CommandSystem.Register("FactionCommander", AccessLevel.Administrator, FactionCommander_OnCommand); + CommandSystem.Register("FactionItemReset", AccessLevel.Administrator, FactionItemReset_OnCommand); + CommandSystem.Register("FactionReset", AccessLevel.Administrator, FactionReset_OnCommand); + CommandSystem.Register("FactionTownReset", AccessLevel.Administrator, FactionTownReset_OnCommand); + } + + public static void Initialize() + { + Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(10.0), HandleAtrophy); + Timer.DelayCall(TimeSpan.FromSeconds(30.0), TimeSpan.FromSeconds(30.0), ProcessTick); + } + + [Usage("FactionTownReset")] + [Description("Resets all faction town data in the world.")] + public static void FactionTownReset_OnCommand(CommandEventArgs e) + { + var monoliths = BaseMonolith.Monoliths; + + for (var i = 0; i < monoliths.Count; ++i) + { + monoliths[i].Sigil = null; + } + + var towns = Town.Towns; + + for (var i = 0; i < towns.Count; ++i) + { + var town = towns[i]; + town.Silver = 0; + town.Sheriff = null; + town.Finance = null; + town.Tax = 0; + town.Owner = null; + } + + var sigils = Sigil.Sigils; + + for (var i = 0; i < sigils.Count; ++i) + { + var sigil = sigils[i]; + sigil.Corrupted = null; + sigil.Corrupting = null; + sigil.LastStolen = DateTime.MinValue; + sigil.GraceStart = DateTime.MinValue; + sigil.CorruptionStart = DateTime.MinValue; + sigil.PurificationStart = DateTime.MinValue; + sigil.LastMonolith = null; + sigil.ReturnHome(); + } + + var factions = Factions; + + for (var i = 0; i < factions.Count; ++i) + { + var f = factions[i]; + + var list = new List(f.State.FactionItems); + + for (var j = 0; j < list.Count; ++j) + { + var fi = list[j]; + + if (fi.Expiration == DateTime.MinValue) + { + fi.Item.Delete(); + } + else + { + fi.Detach(); + } + } + } + } + + [Usage("FactionReset")] + [Description("Resets all faction data in the world.")] + public static void FactionReset_OnCommand(CommandEventArgs e) + { + var monoliths = BaseMonolith.Monoliths; + + for (var i = 0; i < monoliths.Count; ++i) + { + monoliths[i].Sigil = null; + } + + var towns = Town.Towns; + + for (var i = 0; i < towns.Count; ++i) + { + var town = towns[i]; + town.Silver = 0; + town.Sheriff = null; + town.Finance = null; + town.Tax = 0; + town.Owner = null; + } + + var sigils = Sigil.Sigils; + + for (var i = 0; i < sigils.Count; ++i) + { + var sigil = sigils[i]; + sigil.Corrupted = null; + sigil.Corrupting = null; + sigil.LastStolen = DateTime.MinValue; + sigil.GraceStart = DateTime.MinValue; + sigil.CorruptionStart = DateTime.MinValue; + sigil.PurificationStart = DateTime.MinValue; + sigil.LastMonolith = null; + sigil.ReturnHome(); + } + + var factions = Factions; + + for (var i = 0; i < factions.Count; ++i) + { + var f = factions[i]; + + var playerStateList = new List(f.Members); + + for (var j = 0; j < playerStateList.Count; ++j) + { + f.RemoveMember(playerStateList[j].Mobile); + } + + var factionItemList = new List(f.State.FactionItems); + + for (var j = 0; j < factionItemList.Count; ++j) + { + var fi = factionItemList[j]; + + if (fi.Expiration == DateTime.MinValue) + { + fi.Item.Delete(); + } + else + { + fi.Detach(); + } + } + + var factionTrapList = new List(f.Traps); + + for (var j = 0; j < factionTrapList.Count; ++j) + { + factionTrapList[j].Delete(); + } + } + } + + [Usage("FactionItemReset")] + [Description("Resets all faction items in the world.")] + public static void FactionItemReset_OnCommand(CommandEventArgs e) + { + var items = new List(); + + foreach (var item in World.Items.Values) + { + if (item is IFactionItem && item is not HoodedShroudOfShadows) + { + items.Add(item); + } + } + + var hues = new int[Factions.Count * 2]; + + for (var i = 0; i < Factions.Count; ++i) + { + var faction = Factions[i]; + hues[0 + i * 2] = faction.Definition.HuePrimary; + hues[1 + i * 2] = faction.Definition.HueSecondary; + } + + var count = 0; + + for (var i = 0; i < items.Count; ++i) + { + var item = items[i]; + var fci = (IFactionItem)item; + + if (fci.FactionItemState != null || item.LootType != LootType.Blessed) + { + continue; + } + + var isHued = false; + + for (var j = 0; j < hues.Length; ++j) + { + if (item.Hue == hues[j]) + { + isHued = true; + break; + } + } + + if (isHued) + { + fci.FactionItemState = null; + ++count; + } + } + + e.Mobile.SendMessage($"{count} items reset"); + } + + [Usage("FactionCommander")] + [Description("Sets the targeted player as the faction commander.")] + public static void FactionCommander_OnCommand(CommandEventArgs e) + { + e.Mobile.SendMessage("Target a player to make them the faction commander."); + e.Mobile.BeginTarget(-1, false, TargetFlags.None, FactionCommander_OnTarget); + } + + public static void FactionCommander_OnTarget(Mobile from, object obj) + { + if (obj is PlayerMobile mobile) + { + Mobile targ = mobile; + var pl = PlayerState.Find(targ); + + if (pl != null) + { + pl.Faction.Commander = targ; + from.SendMessage("You have appointed them as the faction commander."); + } + else + { + from.SendMessage("They are not in a faction."); + } + } + else + { + from.SendMessage("That is not a player."); + } + } + + [Usage("FactionElection")] + [Description("Opens the election properties for the targeted faction stone.")] + public static void FactionElection_OnCommand(CommandEventArgs e) + { + e.Mobile.SendMessage("Target a faction stone to open its election properties."); + e.Mobile.BeginTarget(-1, false, TargetFlags.None, FactionElection_OnTarget); + } + + public static void FactionElection_OnTarget(Mobile from, object obj) + { + if (obj is FactionStone stone) + { + var faction = stone.Faction; + + if (faction != null) + { + from.SendGump(new ElectionManagementGump(faction.Election)); + } + // from.SendGump( new Gumps.PropertiesGump( from, faction.Election ) ); + else + { + from.SendMessage("That stone has no faction assigned."); + } + } + else + { + from.SendMessage("That is not a faction stone."); + } + } + + public static void FactionKick_OnCommand(CommandEventArgs e) + { + e.Mobile.SendMessage("Target a player to remove them from their faction."); + e.Mobile.BeginTarget(-1, false, TargetFlags.None, FactionKick_OnTarget); + } + + public static void FactionKick_OnTarget(Mobile from, object obj) + { + if (obj is Mobile mob) + { + var pl = PlayerState.Find(mob); + + if (pl != null) + { + pl.Faction.RemoveMember(mob); + + mob.SendMessage("You have been kicked from your faction."); + from.SendMessage("They have been kicked from their faction."); + } + else + { + from.SendMessage("They are not in a faction."); + } + } + else + { + from.SendMessage("That is not a player."); + } + } + + public static void ProcessTick() + { + var sigils = Sigil.Sigils; + + for (var i = 0; i < sigils.Count; ++i) + { + var sigil = sigils[i]; + + if (!sigil.IsBeingCorrupted && sigil.GraceStart != DateTime.MinValue && + sigil.GraceStart + Sigil.CorruptionGrace < Core.Now) + { + if (sigil.LastMonolith is StrongholdMonolith && + (sigil.Corrupted == null || sigil.LastMonolith.Faction != sigil.Corrupted)) + { + sigil.Corrupting = sigil.LastMonolith.Faction; + sigil.CorruptionStart = Core.Now; + } + else + { + sigil.Corrupting = null; + sigil.CorruptionStart = DateTime.MinValue; + } + + sigil.GraceStart = DateTime.MinValue; + } + + if (sigil.LastMonolith?.Sigil == null) + { + if (sigil.LastStolen + Sigil.ReturnPeriod < Core.Now) + { + sigil.ReturnHome(); + } + + continue; + } + + if (sigil.IsBeingCorrupted && sigil.CorruptionStart + Sigil.CorruptionPeriod < Core.Now) + { + sigil.Corrupted = sigil.Corrupting; + } + else if (sigil.IsPurifying && sigil.PurificationStart + Sigil.PurificationPeriod < Core.Now) + { + sigil.PurificationStart = DateTime.MinValue; + } + + sigil.Corrupting = null; + sigil.CorruptionStart = DateTime.MinValue; + sigil.GraceStart = DateTime.MinValue; + } + } + + public static void HandleDeath(Mobile mob) + { + HandleDeath(mob, null); + } + + public int AwardSilver(Mobile mob, int silver) + { + if (silver <= 0) + { + return 0; + } + + var tithed = silver * Tithe / 100; + + Silver += tithed; + + silver = silver - tithed; + + if (silver > 0) + { + mob.AddToBackpack(new Silver(silver)); + } + + return silver; + } + + public static Faction FindSmallestFaction() + { + var factions = Factions; + Faction smallest = null; + + for (var i = 0; i < factions.Count; ++i) + { + var faction = factions[i]; + + if (smallest == null || faction.Members.Count < smallest.Members.Count) + { + smallest = faction; + } + } + + return smallest; + } + + public static bool StabilityActive() + { + var factions = Factions; + + for (var i = 0; i < factions.Count; ++i) + { + var faction = factions[i]; + + if (faction.Members.Count > StabilityActivation) { return true; } + } - var smallest = FindSmallestFaction(); - - if (smallest == null) - { - return true; // sanity - } - - if ((Members.Count + influx) * 100 / StabilityFactor > smallest.Members.Count) - { - return false; - } + return false; + } + public bool CanHandleInflux(int influx) + { + if (!StabilityActive()) + { return true; } - public static void HandleDeath(Mobile victim, Mobile killer) + var smallest = FindSmallestFaction(); + + return smallest == null || (Members.Count + influx) * 100 / StabilityFactor <= smallest.Members.Count; + } + + public static void HandleDeath(Mobile victim, Mobile killer) + { + killer ??= victim.FindMostRecentDamager(true); + + var killerState = PlayerState.Find(killer); + var killerPack = killer?.Backpack; + + if (victim.Backpack != null) { - killer ??= victim.FindMostRecentDamager(true); - - var killerState = PlayerState.Find(killer); - var killerPack = killer?.Backpack; - - if (victim.Backpack != null) + foreach (var sigil in victim.Backpack.EnumerateItemsByType()) { - foreach (var sigil in victim.Backpack.EnumerateItemsByType()) + if (killerState == null || killerPack == null) { - if (killerState == null || killerPack == null) - { - sigil.ReturnHome(); - continue; - } + sigil.ReturnHome(); + } + else if (killer?.GetDistanceToSqrt(victim) > 64) + { + sigil.ReturnHome(); + killer.SendLocalizedMessage(1042230); // The sigil has gone back to its home location. + } + else if (Sigil.ExistsOn(killer)) + { + sigil.ReturnHome(); + // The sigil has gone back to its home location because you already have a sigil. + killer?.SendLocalizedMessage(1010258); + } + else if (!killerPack.TryDropItem(killer, sigil, false)) + { + sigil.ReturnHome(); + // The sigil has gone home because your backpack is full. + killer?.SendLocalizedMessage(1010259); + } + } + } - if (killer?.GetDistanceToSqrt(victim) > 64) - { - sigil.ReturnHome(); - killer.SendLocalizedMessage(1042230); // The sigil has gone back to its home location. - } - else if (Sigil.ExistsOn(killer)) - { - sigil.ReturnHome(); - // The sigil has gone back to its home location because you already have a sigil. - killer?.SendLocalizedMessage(1010258); - } - else if (!killerPack.TryDropItem(killer, sigil, false)) - { - sigil.ReturnHome(); - // The sigil has gone home because your backpack is full. - killer?.SendLocalizedMessage(1010259); - } + if (killerState == null) + { + return; + } + + if (victim is BaseCreature bc) + { + var victimFaction = bc.FactionAllegiance; + + if (bc.Map == Facet && victimFaction != null && killerState.Faction != victimFaction) + { + var silver = killerState.Faction.AwardSilver(killer, bc.FactionSilverWorth); + + if (silver > 0) + { + // Thou hast earned ~1_AMOUNT~ silver for vanquishing the vile creature. + killer?.SendLocalizedMessage(1042748, silver.ToString("N0")); } } - if (killerState == null) + if (bc.Map == Facet && bc.GetEthicAllegiance(killer) == BaseCreature.Allegiance.Enemy) { - return; + var killerEPL = Player.Find(killer); + + if (killerEPL != null && 100 - killerEPL.Power > Utility.Random(100)) + { + ++killerEPL.Power; + ++killerEPL.History; + } } - if (victim is BaseCreature bc) + return; + } + + var victimState = PlayerState.Find(victim); + + if (victimState == null) + { + return; + } + + if (victim.Region.IsPartOf()) + { + return; + } + + if (killer == victim || killerState.Faction != victimState.Faction) + { + ApplySkillLoss(victim); + } + + if (killerState.Faction != victimState.Faction) + { + if (victimState.KillPoints <= -6) { - var victimFaction = bc.FactionAllegiance; + killer?.SendLocalizedMessage(501693); // This victim is not worth enough to get kill points from. - if (bc.Map == Facet && victimFaction != null && killerState.Faction != victimFaction) + var killerEPL = Player.Find(killer); + var victimEPL = Player.Find(victim); + + if (killerEPL != null && victimEPL?.Power > 0 && victimState.CanGiveSilverTo(killer)) { - var silver = killerState.Faction.AwardSilver(killer, bc.FactionSilverWorth); + // Not using Math.Clamp because min/max values could be reversed. + var powerTransfer = Math.Min(Math.Max(1, victimEPL.Power / 5), 100 - killerEPL.Power); - if (silver > 0) + if (powerTransfer > 0) { - // Thou hast earned ~1_AMOUNT~ silver for vanquishing the vile creature. - killer?.SendLocalizedMessage(1042748, silver.ToString("N0")); + victimEPL.Power -= (powerTransfer + 1) / 2; + killerEPL.Power += powerTransfer; + + killerEPL.History += powerTransfer; + victimState.OnGivenSilverTo(killer); } } + } + else + { + var award = Math.Max(victimState.KillPoints / 10, 1); - if (bc.Map == Facet && bc.GetEthicAllegiance(killer) == BaseCreature.Allegiance.Enemy) + if (award > 40) { - var killerEPL = Player.Find(killer); - - if (killerEPL != null && 100 - killerEPL.Power > Utility.Random(100)) - { - ++killerEPL.Power; - ++killerEPL.History; - } + award = 40; } - return; - } - - var victimState = PlayerState.Find(victim); - - if (victimState == null) - { - return; - } - - if (victim.Region.IsPartOf()) - { - return; - } - - if (killer == victim || killerState.Faction != victimState.Faction) - { - ApplySkillLoss(victim); - } - - if (killerState.Faction != victimState.Faction) - { - if (victimState.KillPoints <= -6) + if (victimState.CanGiveSilverTo(killer)) { - killer?.SendLocalizedMessage(501693); // This victim is not worth enough to get kill points from. + PowerFactionItem.CheckSpawn(killer, victim); + + if (victimState.KillPoints > 0) + { + victimState.IsActive = true; + + if (Utility.Random(3) < 1) + { + killerState.IsActive = true; + } + + var silver = killerState.Faction.AwardSilver(killer, award * 40); + + if (silver > 0) + { + // You have earned ~1_SILVER_AMOUNT~ pieces for vanquishing ~2_PLAYER_NAME~! + killer?.SendLocalizedMessage(1042736, $"{silver:N0} silver\t{victim.Name}"); + } + } + + victimState.KillPoints -= award; + killerState.KillPoints += award; + + var offset = award != 1 ? 0 : 2; // for pluralization + + var args = $"{award}\t{victim.Name}\t{killer?.Name}"; + + // Thou hast been honored with ~1_KILL_POINTS~ kill point(s) for vanquishing ~2_DEAD_PLAYER~! + killer?.SendLocalizedMessage(1042737 + offset, args); + + // Thou has lost ~1_KILL_POINTS~ kill point(s) to ~3_ATTACKER_NAME~ for being vanquished! + victim.SendLocalizedMessage(1042738 + offset, args); var killerEPL = Player.Find(killer); var victimEPL = Player.Find(victim); - if (killerEPL != null && victimEPL?.Power > 0 && victimState.CanGiveSilverTo(killer)) + if (killerEPL != null && victimEPL?.Power > 0) { var powerTransfer = Math.Max(1, victimEPL.Power / 5); @@ -1185,375 +1233,301 @@ namespace Server.Factions killerEPL.Power += powerTransfer; killerEPL.History += powerTransfer; - - victimState.OnGivenSilverTo(killer); } } + + victimState.OnGivenSilverTo(killer); } else { - var award = Math.Max(victimState.KillPoints / 10, 1); + // You have recently defeated this enemy and thus their death brings you no honor. + killer?.SendLocalizedMessage(1042231); + } + } + } + } - if (award > 40) + private static void EventSink_Logout(Mobile m) + { + if (m.Backpack != null) + { + foreach (var sigil in m.Backpack.EnumerateItemsByType()) + { + sigil.ReturnHome(); + } + } + } + + public static void OnLogin(Mobile m) => CheckLeaveTimer(m); + + public static void WriteReference(IGenericWriter writer, Faction fact) + { + var idx = Factions.IndexOf(fact); + + writer.WriteEncodedInt(idx + 1); + } + + public static Faction ReadReference(IGenericReader reader) + { + var idx = reader.ReadEncodedInt() - 1; + + return idx >= 0 && idx < Factions.Count ? Factions[idx] : null; + } + + public static Faction Find(Mobile mob, bool inherit = false, bool creatureAllegiances = false) + { + var pl = PlayerState.Find(mob); + + if (pl != null) + { + return pl.Faction; + } + + if (inherit && mob is BaseCreature bc) + { + var master = bc.GetMaster(); + if (master != null) + { + return Find(master); + } + + if (creatureAllegiances && bc is BaseFactionGuard guard) + { + return guard.Faction; + } + + if (creatureAllegiances) + { + return bc.FactionAllegiance; + } + } + + return null; + } + + public static Faction Parse(string name) + { + var factions = Factions; + + for (var i = 0; i < factions.Count; ++i) + { + var faction = factions[i]; + + if (faction.Definition.FriendlyName.InsensitiveEquals(name)) + { + return faction; + } + } + + return null; + } + + public static bool InSkillLoss(Mobile mob) => m_SkillLoss.ContainsKey(mob); + + public static void ApplySkillLoss(Mobile mob) + { + if (InSkillLoss(mob)) + { + return; + } + + var context = new SkillLossContext(); + m_SkillLoss[mob] = context; + + var mods = context.m_Mods = []; + + for (var i = 0; i < mob.Skills.Length; ++i) + { + var sk = mob.Skills[i]; + var baseValue = sk.Base; + + if (baseValue > 0) + { + SkillMod mod = new DefaultSkillMod( + sk.SkillName, + $"{sk.Name}FactionSkillLoss", + true, + -(baseValue * SkillLossFactor) + ); + + mods.Add(mod); + mob.AddSkillMod(mod); + } + } + + Timer.StartTimer(SkillLossPeriod, () => ClearSkillLoss_Event(mob), out context._timerToken); + } + + private static void ClearSkillLoss_Event(Mobile mob) => ClearSkillLoss(mob); + + public static bool ClearSkillLoss(Mobile mob) + { + if (!m_SkillLoss.Remove(mob, out var context)) + { + return false; + } + + var mods = context.m_Mods; + + foreach (var mod in mods) + { + mod.Remove(); + } + + context.m_Mods = null; + context._timerToken.Cancel(); + + return true; + } + + private class BroadcastPrompt : Prompt + { + private readonly Faction m_Faction; + + public BroadcastPrompt(Faction faction) => m_Faction = faction; + + public override void OnResponse(Mobile from, string text) + { + m_Faction.EndBroadcast(from, text); + } + } + + private class SkillLossContext + { + public HashSet m_Mods; + public TimerExecutionToken _timerToken; + } +} + +public enum FactionKickType +{ + Kick, + Ban, + Unban +} + +public class FactionKickCommand : BaseCommand +{ + private readonly FactionKickType m_KickType; + + public FactionKickCommand(FactionKickType kickType) + { + m_KickType = kickType; + + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.AllMobiles; + ObjectTypes = ObjectTypes.Mobiles; + + switch (m_KickType) + { + case FactionKickType.Kick: + { + Commands = ["FactionKick"]; + Usage = "FactionKick"; + Description = + "Kicks the targeted player out of his current faction. This does not prevent them from rejoining."; + break; + } + case FactionKickType.Ban: + { + Commands = ["FactionBan"]; + Usage = "FactionBan"; + Description = + "Bans the account of a targeted player from joining factions. All players on the account are removed from their current faction, if any."; + break; + } + case FactionKickType.Unban: + { + Commands = ["FactionUnban"]; + Usage = "FactionUnban"; + Description = "Unbans the account of a targeted player from joining factions."; + break; + } + } + } + + public override void Execute(CommandEventArgs e, object obj) + { + var mob = (Mobile)obj; + + switch (m_KickType) + { + case FactionKickType.Kick: + { + var pl = PlayerState.Find(mob); + + if (pl != null) { - award = 40; - } - - if (victimState.CanGiveSilverTo(killer)) - { - PowerFactionItem.CheckSpawn(killer, victim); - - if (victimState.KillPoints > 0) - { - victimState.IsActive = true; - - if (Utility.Random(3) < 1) - { - killerState.IsActive = true; - } - - var silver = killerState.Faction.AwardSilver(killer, award * 40); - - if (silver > 0) - { - // You have earned ~1_SILVER_AMOUNT~ pieces for vanquishing ~2_PLAYER_NAME~! - killer?.SendLocalizedMessage(1042736, $"{silver:N0} silver\t{victim.Name}"); - } - } - - victimState.KillPoints -= award; - killerState.KillPoints += award; - - var offset = award != 1 ? 0 : 2; // for pluralization - - var args = $"{award}\t{victim.Name}\t{killer?.Name}"; - - // Thou hast been honored with ~1_KILL_POINTS~ kill point(s) for vanquishing ~2_DEAD_PLAYER~! - killer?.SendLocalizedMessage(1042737 + offset, args); - - // Thou has lost ~1_KILL_POINTS~ kill point(s) to ~3_ATTACKER_NAME~ for being vanquished! - victim.SendLocalizedMessage(1042738 + offset, args); - - var killerEPL = Player.Find(killer); - var victimEPL = Player.Find(victim); - - if (killerEPL != null && victimEPL?.Power > 0) - { - var powerTransfer = Math.Max(1, victimEPL.Power / 5); - - if (powerTransfer > 100 - killerEPL.Power) - { - powerTransfer = 100 - killerEPL.Power; - } - - if (powerTransfer > 0) - { - victimEPL.Power -= (powerTransfer + 1) / 2; - killerEPL.Power += powerTransfer; - - killerEPL.History += powerTransfer; - } - } - - victimState.OnGivenSilverTo(killer); + pl.Faction.RemoveMember(mob); + mob.SendMessage("You have been kicked from your faction."); + AddResponse("They have been kicked from their faction."); } else { - // You have recently defeated this enemy and thus their death brings you no honor. - killer?.SendLocalizedMessage(1042231); + LogFailure("They are not in a faction."); } - } - } - } - private static void EventSink_Logout(Mobile m) - { - if (m.Backpack != null) - { - foreach (var sigil in m.Backpack.EnumerateItemsByType()) + break; + } + case FactionKickType.Ban: { - sigil.ReturnHome(); - } - } - } - - public static void OnLogin(Mobile m) => CheckLeaveTimer(m); - - public static void WriteReference(IGenericWriter writer, Faction fact) - { - var idx = Factions.IndexOf(fact); - - writer.WriteEncodedInt(idx + 1); - } - - public static Faction ReadReference(IGenericReader reader) - { - var idx = reader.ReadEncodedInt() - 1; - - return idx >= 0 && idx < Factions.Count ? Factions[idx] : null; - } - - public static Faction Find(Mobile mob, bool inherit = false, bool creatureAllegiances = false) - { - var pl = PlayerState.Find(mob); - - if (pl != null) - { - return pl.Faction; - } - - if (inherit && mob is BaseCreature bc) - { - if (bc.Controlled) - { - return Find(bc.ControlMaster); - } - - if (bc.Summoned) - { - return Find(bc.SummonMaster); - } - - if (creatureAllegiances && bc is BaseFactionGuard guard) - { - return guard.Faction; - } - - if (creatureAllegiances) - { - return bc.FactionAllegiance; - } - } - - return null; - } - - public static Faction Parse(string name) - { - var factions = Factions; - - for (var i = 0; i < factions.Count; ++i) - { - var faction = factions[i]; - - if (faction.Definition.FriendlyName.InsensitiveEquals(name)) - { - return faction; - } - } - - return null; - } - - public static bool InSkillLoss(Mobile mob) => m_SkillLoss.ContainsKey(mob); - - public static void ApplySkillLoss(Mobile mob) - { - if (InSkillLoss(mob)) - { - return; - } - - var context = new SkillLossContext(); - m_SkillLoss[mob] = context; - - var mods = context.m_Mods = new HashSet(); - - for (var i = 0; i < mob.Skills.Length; ++i) - { - var sk = mob.Skills[i]; - var baseValue = sk.Base; - - if (baseValue > 0) - { - SkillMod mod = new DefaultSkillMod( - sk.SkillName, - $"{sk.Name}FactionSkillLoss", - true, - -(baseValue * SkillLossFactor) - ); - - mods.Add(mod); - mob.AddSkillMod(mod); - } - } - - Timer.StartTimer(SkillLossPeriod, () => ClearSkillLoss_Event(mob), out context._timerToken); - } - - private static void ClearSkillLoss_Event(Mobile mob) => ClearSkillLoss(mob); - - public static bool ClearSkillLoss(Mobile mob) - { - if (!m_SkillLoss.TryGetValue(mob, out var context)) - { - return false; - } - - m_SkillLoss.Remove(mob); - - var mods = context.m_Mods; - - foreach (var mod in mods) - { - mod.Remove(); - } - - context.m_Mods = null; - context._timerToken.Cancel(); - - return true; - } - - private class BroadcastPrompt : Prompt - { - private readonly Faction m_Faction; - - public BroadcastPrompt(Faction faction) => m_Faction = faction; - - public override void OnResponse(Mobile from, string text) - { - m_Faction.EndBroadcast(from, text); - } - } - - private class SkillLossContext - { - public HashSet m_Mods; - public TimerExecutionToken _timerToken; - } - } - - public enum FactionKickType - { - Kick, - Ban, - Unban - } - - public class FactionKickCommand : BaseCommand - { - private readonly FactionKickType m_KickType; - - public FactionKickCommand(FactionKickType kickType) - { - m_KickType = kickType; - - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.AllMobiles; - ObjectTypes = ObjectTypes.Mobiles; - - switch (m_KickType) - { - case FactionKickType.Kick: + if (mob.Account is Account acct) { - Commands = new[] { "FactionKick" }; - Usage = "FactionKick"; - Description = - "Kicks the targeted player out of his current faction. This does not prevent them from rejoining."; - break; - } - case FactionKickType.Ban: - { - Commands = new[] { "FactionBan" }; - Usage = "FactionBan"; - Description = - "Bans the account of a targeted player from joining factions. All players on the account are removed from their current faction, if any."; - break; - } - case FactionKickType.Unban: - { - Commands = new[] { "FactionUnban" }; - Usage = "FactionUnban"; - Description = "Unbans the account of a targeted player from joining factions."; - break; - } - } - } - - public override void Execute(CommandEventArgs e, object obj) - { - var mob = (Mobile)obj; - - switch (m_KickType) - { - case FactionKickType.Kick: - { - var pl = PlayerState.Find(mob); - - if (pl != null) + if (acct.GetTag("FactionBanned") == null) { - pl.Faction.RemoveMember(mob); - mob.SendMessage("You have been kicked from your faction."); - AddResponse("They have been kicked from their faction."); + acct.SetTag("FactionBanned", "true"); + AddResponse("The account has been banned from joining factions."); } else { - LogFailure("They are not in a faction."); + AddResponse("The account is already banned from joining factions."); } - break; - } - case FactionKickType.Ban: - { - if (mob.Account is Account acct) + for (var i = 0; i < acct.Length; ++i) { - if (acct.GetTag("FactionBanned") == null) - { - acct.SetTag("FactionBanned", "true"); - AddResponse("The account has been banned from joining factions."); - } - else - { - AddResponse("The account is already banned from joining factions."); - } + mob = acct[i]; - for (var i = 0; i < acct.Length; ++i) + if (mob != null) { - mob = acct[i]; + var pl = PlayerState.Find(mob); - if (mob != null) + if (pl != null) { - var pl = PlayerState.Find(mob); - - if (pl != null) - { - pl.Faction.RemoveMember(mob); - mob.SendMessage("You have been kicked from your faction."); - AddResponse("They have been kicked from their faction."); - } + pl.Faction.RemoveMember(mob); + mob.SendMessage("You have been kicked from your faction."); + AddResponse("They have been kicked from their faction."); } } } - else - { - LogFailure("They have no assigned account."); - } - - break; } - case FactionKickType.Unban: + else { - if (mob.Account is Account acct) + LogFailure("They have no assigned account."); + } + + break; + } + case FactionKickType.Unban: + { + if (mob.Account is Account acct) + { + if (acct.GetTag("FactionBanned") == null) { - if (acct.GetTag("FactionBanned") == null) - { - AddResponse("The account is not already banned from joining factions."); - } - else - { - acct.RemoveTag("FactionBanned"); - AddResponse("The account may now freely join factions."); - } + AddResponse("The account is not already banned from joining factions."); } else { - LogFailure("They have no assigned account."); + acct.RemoveTag("FactionBanned"); + AddResponse("The account may now freely join factions."); } - - break; } - } + else + { + LogFailure("They have no assigned account."); + } + + break; + } } } } diff --git a/Projects/UOContent/Engines/Factions/Core/FactionItem.cs b/Projects/UOContent/Engines/Factions/Core/FactionItem.cs index 6d02f0948..ad874e936 100644 --- a/Projects/UOContent/Engines/Factions/Core/FactionItem.cs +++ b/Projects/UOContent/Engines/Factions/Core/FactionItem.cs @@ -1,154 +1,153 @@ 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; - Faction = faction; - } - - public FactionItem(IGenericReader reader, Faction faction) - { - var version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - Item = reader.ReadEntity(); - 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) + case 0: { - return true; + Item = reader.ReadEntity(); + 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) - { - Attach(); - } - else - { - Detach(); - } + item.FactionItemState = null; } - 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; } + + var state = Find(item); + + if (state == null) + { + state = new FactionItem(item, faction); + state.Attach(); + } + + if (expire) + { + state.StartExpiration(); + } + + item.Hue = hue; + return item; } } diff --git a/Projects/UOContent/Engines/Factions/Core/FactionState.cs b/Projects/UOContent/Engines/Factions/Core/FactionState.cs index d7b588b0b..0170c718c 100644 --- a/Projects/UOContent/Engines/Factions/Core/FactionState.cs +++ b/Projects/UOContent/Engines/Factions/Core/FactionState.cs @@ -1,309 +1,308 @@ using System; 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; - private static readonly TimeSpan BroadcastPeriod = TimeSpan.FromHours(1.0); - private readonly Faction m_Faction; + m_Faction = faction; + Tithe = 50; + Members = []; + Election = new Election(faction); + FactionItems = []; + Traps = []; + } - private readonly DateTime[] m_LastBroadcasts = new DateTime[BroadcastsPerPeriod]; - private Mobile m_Commander; + public FactionState(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); - public FactionState(Faction faction) + switch (version) { - m_Faction = faction; - Tithe = 50; - Members = new List(); - Election = new Election(faction); - FactionItems = new List(); - Traps = new List(); - } - - 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(); - - 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(); - - 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(); - - 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(); - - if (version >= 3) - { - var factionTrapCount = reader.ReadEncodedInt(); - - for (var i = 0; i < factionTrapCount; ++i) - { - if (reader.ReadEntity() 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) + case 5: { - if (Core.Now >= m_LastBroadcasts[i] + BroadcastPeriod) - { - return true; - } + LastAtrophy = reader.ReadDateTime(); + goto case 4; } + 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(); + + 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() is BaseFactionTrap trap && !trap.CheckDecay()) + { + Traps.Add(trap); + } + } + } + + break; + } } - public bool IsAtrophyReady => Core.Now >= LastAtrophy + TimeSpan.FromHours(47.0); - - public List FactionItems { get; set; } - - public List Traps { get; set; } - - public Election Election { get; set; } - - public Mobile Commander + if (version < 1) { - 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; - } - } - } + Election = new Election(m_Faction); } + } - public int Tithe { get; set; } + public DateTime LastAtrophy { get; set; } - public int Silver { get; set; } - - public List Members { get; set; } - - public int CheckAtrophy() - { - if (Core.Now < LastAtrophy + TimeSpan.FromHours(47.0)) - { - return 0; - } - - var distrib = 0; - LastAtrophy = Core.Now; - - var members = new List(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() + public bool FactionMessageReady + { + get { for (var i = 0; i < m_LastBroadcasts.Length; ++i) { if (Core.Now >= m_LastBroadcasts[i] + BroadcastPeriod) { - m_LastBroadcasts[i] = Core.Now; - break; + return true; + } + } + + return false; + } + } + + public bool IsAtrophyReady => Core.Now >= LastAtrophy + TimeSpan.FromHours(47.0); + + public List FactionItems { get; set; } + + public List 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 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(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); - - 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) + if (ps.KillPoints > 0) { - var pl = Members[i]; - - pl.Serialize(writer); + var atrophy = (ps.KillPoints + 9) / 10; + ps.KillPoints -= atrophy; + 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); - } - - writer.WriteEncodedInt(Traps.Count); - - for (var i = 0; i < Traps.Count; ++i) - { - writer.Write(Traps[i]); + m_LastBroadcasts[i] = Core.Now; + break; } } } + + 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]); + } + } } diff --git a/Projects/UOContent/Engines/Factions/Core/Generator.cs b/Projects/UOContent/Engines/Factions/Core/Generator.cs index 97f3a0e40..7e950ab95 100644 --- a/Projects/UOContent/Engines/Factions/Core/Generator.cs +++ b/Projects/UOContent/Engines/Factions/Core/Generator.cs @@ -1,100 +1,99 @@ 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")] - [Aliases("FactionGen", "GenFactions")] - [Description("Enables and generates factions.")] - public static void GenerateFactions_OnCommand(CommandEventArgs e) + var towns = Town.Towns; + + foreach (var town in towns) { - var from = e.Mobile; - FactionSystem.Enable(); - - 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."); + Generate(town); + from.SendMessage($"Generated {town}"); } - 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 def = town.Definition; - - 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); - } + var mono = new TownMonolith(town); + mono.MoveToWorld(def.Monolith, facet); + mono.Sigil = new Sigil(town); } - public static void Generate(Faction faction) + if (!CheckExistence(def.TownStone, facet, typeof(TownStone))) { - 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; + new TownStone(town).MoveToWorld(def.TownStone, facet); } } -} + + 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; + } +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Core/GuardList.cs b/Projects/UOContent/Engines/Factions/Core/GuardList.cs index 52333670a..e7d7df8d7 100644 --- a/Projects/UOContent/Engines/Factions/Core/GuardList.cs +++ b/Projects/UOContent/Engines/Factions/Core/GuardList.cs @@ -1,29 +1,28 @@ 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 Guards { get; } + + public BaseFactionGuard Construct() + { + try { - Definition = definition; - Guards = new List(); + return Definition.Type.CreateInstance(); } - - public GuardDefinition Definition { get; } - - public List Guards { get; } - - public BaseFactionGuard Construct() + catch { - try - { - return Definition.Type.CreateInstance(); - } - catch - { - return null; - } + return null; } } -} +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Core/Keywords.cs b/Projects/UOContent/Engines/Factions/Core/Keywords.cs index 3064e7432..c2c6e95d3 100644 --- a/Projects/UOContent/Engines/Factions/Core/Keywords.cs +++ b/Projects/UOContent/Engines/Factions/Core/Keywords.cs @@ -1,189 +1,188 @@ 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) - { - pl?.Mobile.PublicOverheadMessage( - MessageType.Regular, - pl.Mobile.SpeechHue, - true, - pl.KillPoints.ToString("N0") - ); - } + private static void ShowScore_Sandbox(PlayerState pl) + { + pl?.Mobile.PublicOverheadMessage( + MessageType.Regular, + pl.Mobile.SpeechHue, + true, + pl.KillPoints.ToString("N0") + ); + } - private static void EventSink_Speech(SpeechEventArgs e) - { - var from = e.Mobile; - var keywords = e.Keywords; + private static void EventSink_Speech(SpeechEventArgs e) + { + var from = e.Mobile; + 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* - { - var town = Town.FromRegion(from.Region); + case 0x00E4: // *i wish to access the city treasury* + { + 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; } - 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)); - } - - 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); + // Your term of service will come to an end in ~1_HOURS~ hours. + from.SendLocalizedMessage(1042741, remaining.TotalHours.ToString("N0")); } 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); - - if (pl != null) - { - Timer.StartTimer(() => ShowScore_Sandbox(pl)); - } - - break; + // You are not in the process of quitting the faction. + from.SendLocalizedMessage(1042233); } - 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; } - } + + 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; + } } } } -} +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Core/MerchantTitles.cs b/Projects/UOContent/Engines/Factions/Core/MerchantTitles.cs index ab17acf7f..92cefcc05 100644 --- a/Projects/UOContent/Engines/Factions/Core/MerchantTitles.cs +++ b/Projects/UOContent/Engines/Factions/Core/MerchantTitles.cs @@ -1,123 +1,118 @@ -namespace Server.Factions +using System.Runtime.CompilerServices; + +namespace Server.Factions; + +public enum MerchantTitle { - public enum MerchantTitle - { - None, - Scribe, - Carpenter, - Blacksmith, - Bowyer, - Tailor - } - - public class MerchantTitleInfo - { - public MerchantTitleInfo( - SkillName skill, double requirement, TextDefinition title, TextDefinition label, - TextDefinition assigned - ) - { - Skill = skill; - Requirement = requirement; - Title = title; - Label = label; - Assigned = assigned; - } - - public SkillName Skill { get; } - - public double Requirement { get; } - - public TextDefinition Title { get; } - - public TextDefinition Label { get; } - - public TextDefinition Assigned { get; } - } - - public static class MerchantTitles - { - public static MerchantTitleInfo[] Info { get; } = - { - new( - SkillName.Inscribe, - 90.0, - 1060773, // Scribe - 1011468, // SCRIBE - 1010121 // You now have the faction title of scribe - ), - new( - SkillName.Carpentry, - 90.0, - 1060774, // Carpenter - 1011469, // CARPENTER - 1010122 // You now have the faction title of carpenter - ), - new( - SkillName.Tinkering, - 90.0, - 1022984, // Tinker - 1011470, // TINKER - 1010123 // You now have the faction title of tinker - ), - new( - SkillName.Blacksmith, - 90.0, - 1023016, // Blacksmith - 1011471, // BLACKSMITH - 1010124 // You now have the faction title of blacksmith - ), - new( - SkillName.Fletching, - 90.0, - 1023022, // Bowyer - 1011472, // BOWYER - 1010125 // You now have the faction title of Bowyer - ), - new( - SkillName.Tailoring, - 90.0, - 1022982, // Tailor - 1018300, // TAILOR - 1042162 // You now have the faction title of Tailor - ) - }; - - public static MerchantTitleInfo GetInfo(MerchantTitle title) - { - var idx = (int)title - 1; - - if (idx >= 0 && idx < Info.Length) - { - return Info[idx]; - } - - return null; - } - - public static bool HasMerchantQualifications(Mobile mob) - { - for (var i = 0; i < Info.Length; ++i) - { - if (IsQualified(mob, Info[i])) - { - return true; - } - } - - return false; - } - - public static bool IsQualified(Mobile mob, MerchantTitle title) => IsQualified(mob, GetInfo(title)); - - public static bool IsQualified(Mobile mob, MerchantTitleInfo info) - { - if (mob == null || info == null) - { - return false; - } - - return mob.Skills[info.Skill].Value >= info.Requirement; - } - } + None, + Scribe, + Carpenter, + Blacksmith, + Bowyer, + Tailor +} + +public class MerchantTitleInfo +{ + public MerchantTitleInfo( + SkillName skill, double requirement, TextDefinition title, TextDefinition label, + TextDefinition assigned + ) + { + Skill = skill; + Requirement = requirement; + Title = title; + Label = label; + Assigned = assigned; + } + + public SkillName Skill { get; } + + public double Requirement { get; } + + public TextDefinition Title { get; } + + public TextDefinition Label { get; } + + public TextDefinition Assigned { get; } +} + +public static class MerchantTitles +{ + public static MerchantTitleInfo[] Info { get; } = + [ + new MerchantTitleInfo( + SkillName.Inscribe, + 90.0, + 1060773, // Scribe + 1011468, // SCRIBE + 1010121 // You now have the faction title of scribe + ), + new MerchantTitleInfo( + SkillName.Carpentry, + 90.0, + 1060774, // Carpenter + 1011469, // CARPENTER + 1010122 // You now have the faction title of carpenter + ), + new MerchantTitleInfo( + SkillName.Tinkering, + 90.0, + 1022984, // Tinker + 1011470, // TINKER + 1010123 // You now have the faction title of tinker + ), + new MerchantTitleInfo( + SkillName.Blacksmith, + 90.0, + 1023016, // Blacksmith + 1011471, // BLACKSMITH + 1010124 // You now have the faction title of blacksmith + ), + new MerchantTitleInfo( + SkillName.Fletching, + 90.0, + 1023022, // Bowyer + 1011472, // BOWYER + 1010125 // You now have the faction title of Bowyer + ), + new MerchantTitleInfo( + SkillName.Tailoring, + 90.0, + 1022982, // Tailor + 1018300, // TAILOR + 1042162 // You now have the faction title of Tailor + ) + ]; + + public static MerchantTitleInfo GetInfo(MerchantTitle title) + { + var idx = (int)title - 1; + + if (idx >= 0 && idx < Info.Length) + { + return Info[idx]; + } + + return null; + } + + public static bool HasMerchantQualifications(Mobile mob) + { + for (var i = 0; i < Info.Length; ++i) + { + if (IsQualified(mob, Info[i])) + { + return true; + } + } + + return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsQualified(Mobile mob, MerchantTitle title) => IsQualified(mob, GetInfo(title)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsQualified(Mobile mob, MerchantTitleInfo info) => mob?.Skills[info.Skill].Value >= info?.Requirement; } diff --git a/Projects/UOContent/Engines/Factions/Core/PlayerState.cs b/Projects/UOContent/Engines/Factions/Core/PlayerState.cs index d39f868df..792d2b4e3 100644 --- a/Projects/UOContent/Engines/Factions/Core/PlayerState.cs +++ b/Projects/UOContent/Engines/Factions/Core/PlayerState.cs @@ -2,133 +2,174 @@ using System; using System.Collections.Generic; using Server.Mobiles; -namespace Server.Factions +namespace Server.Factions; + +public class PlayerState : IComparable { - public class PlayerState : IComparable + 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 owner) { - private Town m_Finance; + Mobile = mob; + Faction = faction; + Owner = owner; - private bool m_InvalidateRank = true; - private int m_KillPoints; - private MerchantTitle m_MerchantTitle; - private RankDefinition m_Rank; - private int m_RankIndex = -1; + Attach(); + Invalidate(); + } - private Town m_Sheriff; + public PlayerState(IGenericReader reader, Faction faction, List owner) + { + Faction = faction; + Owner = owner; - public PlayerState(Mobile mob, Faction faction, List owner) + var version = reader.ReadEncodedInt(); + + switch (version) { - Mobile = mob; - Faction = faction; - Owner = owner; + case 1: + { + IsActive = reader.ReadBool(); + LastHonorTime = reader.ReadDateTime(); + goto case 0; + } + case 0: + { + Mobile = reader.ReadEntity(); - 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 Owner { get; } + + public MerchantTitle MerchantTitle + { + get => m_MerchantTitle; + set + { + m_MerchantTitle = value; Invalidate(); } + } - public PlayerState(IGenericReader reader, Faction faction, List owner) + public Town Sheriff + { + get => m_Sheriff; + set { - Faction = faction; - Owner = owner; - - var version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - IsActive = reader.ReadBool(); - LastHonorTime = reader.ReadDateTime(); - goto case 0; - } - case 0: - { - Mobile = reader.ReadEntity(); - - m_KillPoints = reader.ReadEncodedInt(); - m_MerchantTitle = (MerchantTitle)reader.ReadEncodedInt(); - - Leaving = reader.ReadDateTime(); - - break; - } - } - - Attach(); + m_Sheriff = value; + Invalidate(); } + } - public Mobile Mobile { get; } - - public Faction Faction { get; } - - public List Owner { get; } - - public MerchantTitle MerchantTitle + public Town Finance + { + get => m_Finance; + set { - get => m_MerchantTitle; - set - { - m_MerchantTitle = value; - Invalidate(); - } + m_Finance = value; + Invalidate(); } + } - public Town Sheriff + public List SilverGiven { get; private set; } + + public int KillPoints + { + get => m_KillPoints; + set { - get => m_Sheriff; - set + if (m_KillPoints != value) { - m_Sheriff = value; - Invalidate(); - } - } - - public Town Finance - { - get => m_Finance; - set - { - m_Finance = value; - Invalidate(); - } - } - - public List SilverGiven { get; private set; } - - public int KillPoints - { - get => m_KillPoints; - set - { - if (m_KillPoints != value) + if (value > m_KillPoints) { - 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 (value <= 0) - { - m_KillPoints = value; - Invalidate(); - return; - } - - Owner.Remove(this); - Owner.Insert(Faction.ZeroRankOffset, this); - - m_RankIndex = Faction.ZeroRankOffset; - Faction.ZeroRankOffset++; + m_KillPoints = value; + Invalidate(); + return; } - while (m_RankIndex - 1 >= 0) + while (m_RankIndex + 1 < Faction.ZeroRankOffset) { - var p = Owner[m_RankIndex - 1]; - if (value > p.KillPoints) + 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; - Owner[m_RankIndex - 1] = this; - RankIndex--; - p.RankIndex++; + RankIndex++; + p.RankIndex--; } 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(); - - 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; +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Core/Reflector.cs b/Projects/UOContent/Engines/Factions/Core/Reflector.cs index 196d45bbe..5d90c7dd6 100644 --- a/Projects/UOContent/Engines/Factions/Core/Reflector.cs +++ b/Projects/UOContent/Engines/Factions/Core/Reflector.cs @@ -1,85 +1,84 @@ using System; using System.Collections.Generic; -namespace Server.Factions +namespace Server.Factions; + +public static class Reflector { - public static class Reflector + private static List m_Towns; + + private static List m_Factions; + + public static List Towns { - private static List m_Towns; - - private static List m_Factions; - - public static List Towns + get { - get + if (m_Towns == null) { - if (m_Towns == null) - { - ProcessTypes(); - } - - return m_Towns; + ProcessTypes(); } + + return m_Towns; } + } - public static List Factions + public static List Factions + { + get { - get + if (m_Factions == null) { - if (m_Factions == null) - { - ProcessTypes(); - } - - return m_Factions; + ProcessTypes(); } + + return m_Factions; } + } - private static object Construct(Type type) + private static object Construct(Type type) + { + try { - try - { - return type.CreateInstance(); - } - catch - { - return null; - } + return type.CreateInstance(); } - - private static void ProcessTypes() + catch { - m_Factions = new List(); - m_Towns = new List(); + return null; + } + } - 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 tc = AssemblyHandler.GetTypeCache(asm); - var types = tc.Types; + var type = types[j]; - for (var j = 0; j < types.Length; ++j) + if (type.IsSubclassOf(typeof(Faction))) { - var type = types[j]; - - if (type.IsSubclassOf(typeof(Faction))) + if (Construct(type) is Faction 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); } } } } } -} +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Core/SilverGivenEntry.cs b/Projects/UOContent/Engines/Factions/Core/SilverGivenEntry.cs index 9e2423bcf..ad7e9f1dd 100644 --- a/Projects/UOContent/Engines/Factions/Core/SilverGivenEntry.cs +++ b/Projects/UOContent/Engines/Factions/Core/SilverGivenEntry.cs @@ -1,21 +1,20 @@ 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); - - public SilverGivenEntry(Mobile givenTo) - { - GivenTo = givenTo; - TimeOfGift = Core.Now; - } - - public Mobile GivenTo { get; } - - public DateTime TimeOfGift { get; } - - public bool IsExpired => TimeOfGift + ExpirePeriod < Core.Now; + GivenTo = givenTo; + TimeOfGift = Core.Now; } -} + + public Mobile GivenTo { get; } + + public DateTime TimeOfGift { get; } + + public bool IsExpired => TimeOfGift + ExpirePeriod < Core.Now; +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Core/StrongholdRegion.cs b/Projects/UOContent/Engines/Factions/Core/StrongholdRegion.cs index f6a7374b6..8397e9e0e 100644 --- a/Projects/UOContent/Engines/Factions/Core/StrongholdRegion.cs +++ b/Projects/UOContent/Engines/Factions/Core/StrongholdRegion.cs @@ -1,45 +1,44 @@ using Server.Mobiles; 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.Definition.FriendlyName, - Faction.Facet, - DefaultPriority, - faction.Definition.Stronghold.Area - ) - { - Faction = faction; + Faction = faction; - 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; + 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; +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Core/Town.cs b/Projects/UOContent/Engines/Factions/Core/Town.cs index 480b60f16..2dcca8c78 100644 --- a/Projects/UOContent/Engines/Factions/Core/Town.cs +++ b/Projects/UOContent/Engines/Factions/Core/Town.cs @@ -2,569 +2,543 @@ using System; using System.Collections.Generic; using Server.Targeting; -namespace Server.Factions +namespace Server.Factions; + +[CustomEnum(["Britain", "Magincia", "Minoc", "Moonglow", "Skara Brae", "Trinsic", "Vesper", "Yew"])] +public abstract class Town : IComparable { - [CustomEnum(new[] { "Britain", "Magincia", "Minoc", "Moonglow", "Skara Brae", "Trinsic", "Vesper", "Yew" })] - public abstract class Town : IComparable + public const int SilverCaptureBonus = 10000; + + public static readonly TimeSpan TaxChangePeriod = TimeSpan.FromHours(12.0); + public static readonly TimeSpan IncomePeriod = TimeSpan.FromDays(1.0); + + private Timer _incomeTimer; + private TownState m_State; + + public Town() { - public const int SilverCaptureBonus = 10000; + m_State = new TownState(this); + ConstructVendorLists(); + ConstructGuardLists(); + StartIncomeTimer(); + } - public static readonly TimeSpan TaxChangePeriod = TimeSpan.FromHours(12.0); - public static readonly TimeSpan IncomePeriod = TimeSpan.FromDays(1.0); + public TownDefinition Definition { get; set; } - private Timer _incomeTimer; - private TownState m_State; - - public Town() + public TownState State + { + get => m_State; + set { - m_State = new TownState(this); - ConstructVendorLists(); + m_State = value; ConstructGuardLists(); - StartIncomeTimer(); } + } - public TownDefinition Definition { get; set; } + public int Silver + { + get => m_State.Silver; + set => m_State.Silver = value; + } - public TownState State + public Faction Owner + { + get => m_State.Owner; + set => Capture(value); + } + + public Mobile Sheriff + { + get => m_State.Sheriff; + set => m_State.Sheriff = value; + } + + public Mobile Finance + { + get => m_State.Finance; + set => m_State.Finance = value; + } + + public int Tax + { + get => m_State.Tax; + set => m_State.Tax = value; + } + + public DateTime LastTaxChange + { + get => m_State.LastTaxChange; + set => m_State.LastTaxChange = value; + } + + public bool TaxChangeReady => m_State.LastTaxChange + TaxChangePeriod < Core.Now; + + public int FinanceUpkeep + { + get { - get => m_State; - set + var vendorLists = VendorLists; + var upkeep = 0; + + for (var i = 0; i < vendorLists.Count; ++i) { - m_State = value; - ConstructGuardLists(); + upkeep += vendorLists[i].Vendors.Count * vendorLists[i].Definition.Upkeep; } + + return upkeep; } + } - public int Silver + public int SheriffUpkeep + { + get { - get => m_State.Silver; - set => m_State.Silver = value; - } + var guardLists = GuardLists; + var upkeep = 0; - public Faction Owner - { - get => m_State.Owner; - set => Capture(value); - } - - public Mobile Sheriff - { - get => m_State.Sheriff; - set => m_State.Sheriff = value; - } - - public Mobile Finance - { - get => m_State.Finance; - set => m_State.Finance = value; - } - - public int Tax - { - get => m_State.Tax; - set => m_State.Tax = value; - } - - public DateTime LastTaxChange - { - get => m_State.LastTaxChange; - set => m_State.LastTaxChange = value; - } - - public bool TaxChangeReady => m_State.LastTaxChange + TaxChangePeriod < Core.Now; - - public int FinanceUpkeep - { - get + for (var i = 0; i < guardLists.Count; ++i) { - var vendorLists = VendorLists; - var upkeep = 0; + upkeep += guardLists[i].Guards.Count * guardLists[i].Definition.Upkeep; + } - for (var i = 0; i < vendorLists.Count; ++i) + return upkeep; + } + } + + public int DailyIncome => 10000 * (100 + m_State.Tax) / 100; + + public int NetCashFlow => DailyIncome - FinanceUpkeep - SheriffUpkeep; + + public TownMonolith Monolith + { + get + { + var monoliths = BaseMonolith.Monoliths; + + foreach (var monolith in monoliths) + { + if (monolith is TownMonolith townMonolith && townMonolith.Town == this) { - upkeep += vendorLists[i].Vendors.Count * vendorLists[i].Definition.Upkeep; - } - - return upkeep; - } - } - - public int SheriffUpkeep - { - get - { - var guardLists = GuardLists; - var upkeep = 0; - - for (var i = 0; i < guardLists.Count; ++i) - { - upkeep += guardLists[i].Guards.Count * guardLists[i].Definition.Upkeep; - } - - return upkeep; - } - } - - public int DailyIncome => 10000 * (100 + m_State.Tax) / 100; - - public int NetCashFlow => DailyIncome - FinanceUpkeep - SheriffUpkeep; - - public TownMonolith Monolith - { - get - { - var monoliths = BaseMonolith.Monoliths; - - foreach (var monolith in monoliths) - { - if (monolith is TownMonolith townMonolith && townMonolith.Town == this) - { - return townMonolith; - } - } - - return null; - } - } - - public DateTime LastIncome - { - get => m_State.LastIncome; - set => m_State.LastIncome = value; - } - - public List VendorLists { get; set; } - - public List GuardLists { get; set; } - - public static List Towns => Reflector.Towns; - - public int CompareTo(Town other) => Definition.Sort - (other?.Definition.Sort ?? 0); - - public static Town FromRegion(Region reg) - { - if (reg.Map != Faction.Facet) - { - return null; - } - - var towns = Towns; - - for (var i = 0; i < towns.Count; ++i) - { - var town = towns[i]; - - if (reg.IsPartOf(town.Definition.Region)) - { - return town; + return townMonolith; } } return null; } + } - public void BeginOrderFiring(Mobile from) + public DateTime LastIncome + { + get => m_State.LastIncome; + set => m_State.LastIncome = value; + } + + public List VendorLists { get; set; } + + public List GuardLists { get; set; } + + public static List Towns => Reflector.Towns; + + public int CompareTo(Town other) => Definition.Sort - (other?.Definition.Sort ?? 0); + + public static Town FromRegion(Region reg) + { + if (reg.Map != Faction.Facet) { - var isFinance = IsFinance(from); - var isSheriff = IsSheriff(from); - string type = null; - - // NOTE: Messages not OSI-accurate, intentional - if (isFinance && isSheriff) // GM only - { - type = "vendor or guard"; - } - else if (isFinance) - { - type = "vendor"; - } - else if (isSheriff) - { - type = "guard"; - } - - from.SendMessage($"Target the {type} you wish to dismiss."); - from.BeginTarget(12, false, TargetFlags.None, EndOrderFiring); + return null; } - public void EndOrderFiring(Mobile from, object obj) + var towns = Towns; + + for (var i = 0; i < towns.Count; ++i) { - var isFinance = IsFinance(from); - var isSheriff = IsSheriff(from); - string type = null; + var town = towns[i]; - if (isFinance && isSheriff) // GM only + if (reg.IsPartOf(town.Definition.Region)) { - type = "vendor or guard"; - } - else if (isFinance) - { - type = "vendor"; - } - else if (isSheriff) - { - type = "guard"; - } - - if (obj is BaseFactionVendor vendor && vendor.Town == this && isFinance) - { - vendor.Delete(); - } - else if (obj is BaseFactionGuard guard && guard.Town == this && isSheriff) - { - guard.Delete(); - } - else - { - from.SendMessage($"That is not a {type}!"); + return town; } } - public void StartIncomeTimer() + return null; + } + + public void BeginOrderFiring(Mobile from) + { + var isFinance = IsFinance(from); + var isSheriff = IsSheriff(from); + string type = null; + + // NOTE: Messages not OSI-accurate, intentional + if (isFinance && isSheriff) // GM only { - _incomeTimer ??= Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), CheckIncome); + type = "vendor or guard"; + } + else if (isFinance) + { + type = "vendor"; + } + else if (isSheriff) + { + type = "guard"; } - public void Delete() + from.SendMessage($"Target the {type} you wish to dismiss."); + from.BeginTarget(12, false, TargetFlags.None, EndOrderFiring); + } + + public void EndOrderFiring(Mobile from, object obj) + { + var isFinance = IsFinance(from); + var isSheriff = IsSheriff(from); + + if (obj is BaseFactionVendor vendor && vendor.Town == this && isFinance) { - _incomeTimer?.Stop(); + vendor.Delete(); + } + else if (obj is BaseFactionGuard guard && guard.Town == this && isSheriff) + { + guard.Delete(); + } + else if (isFinance && isSheriff) // GM only + { + from.SendMessage("That is not a vendor or guard!"); + } + else if (isFinance) + { + from.SendMessage("That is not a vendor!"); + } + else if (isSheriff) + { + from.SendMessage("That is not a guard!"); + } + } + + public void StartIncomeTimer() + { + _incomeTimer ??= Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), CheckIncome); + } + + public void Delete() + { + _incomeTimer?.Stop(); + } + + public void CheckIncome() + { + if (LastIncome + IncomePeriod > Core.Now || Owner == null) + { + return; } - public void CheckIncome() + ProcessIncome(); + } + + public void ProcessIncome() + { + LastIncome = Core.Now; + + var flow = NetCashFlow; + + if (Silver + flow < 0) { - if (LastIncome + IncomePeriod > Core.Now || Owner == null) + var toDelete = BuildFinanceList(); + + while (Silver + flow < 0 && toDelete.Count > 0) { - return; - } + var mob = toDelete.RandomElement(); + mob.Delete(); - ProcessIncome(); + toDelete.Remove(mob); + flow = NetCashFlow; + } } - public void ProcessIncome() + Silver += flow; + } + + public List BuildFinanceList() + { + var list = new List(); + + for (var i = 0; i < VendorLists.Count; ++i) + { + list.AddRange(VendorLists[i].Vendors); + } + + for (var i = 0; i < GuardLists.Count; ++i) + { + list.AddRange(GuardLists[i].Guards); + } + + return list; + } + + public void ConstructGuardLists() + { + var defs = Owner?.Definition.Guards ?? []; + + GuardLists = []; + + for (var i = 0; i < defs.Length; ++i) + { + GuardLists.Add(new GuardList(defs[i])); + } + } + + public GuardList FindGuardList(Type type) + { + var guardLists = GuardLists; + + for (var i = 0; i < guardLists.Count; ++i) + { + var guardList = guardLists[i]; + + if (guardList.Definition.Type == type) + { + return guardList; + } + } + + return null; + } + + public void ConstructVendorLists() + { + var defs = VendorDefinition.Definitions; + + VendorLists = []; + + for (var i = 0; i < defs.Length; ++i) + { + VendorLists.Add(new VendorList(defs[i])); + } + } + + public VendorList FindVendorList(Type type) + { + var vendorLists = VendorLists; + + for (var i = 0; i < vendorLists.Count; ++i) + { + var vendorList = vendorLists[i]; + + if (vendorList.Definition.Type == type) + { + return vendorList; + } + } + + return null; + } + + public bool RegisterGuard(BaseFactionGuard guard) + { + if (guard == null) + { + return false; + } + + var guardList = FindGuardList(guard.GetType()); + + if (guardList == null) + { + return false; + } + + guardList.Guards.Add(guard); + return true; + } + + public bool UnregisterGuard(BaseFactionGuard guard) + { + if (guard == null) + { + return false; + } + + var guardList = FindGuardList(guard.GetType()); + + if (guardList == null) + { + return false; + } + + if (!guardList.Guards.Contains(guard)) + { + return false; + } + + guardList.Guards.Remove(guard); + return true; + } + + public bool RegisterVendor(BaseFactionVendor vendor) + { + if (vendor == null) + { + return false; + } + + var vendorList = FindVendorList(vendor.GetType()); + + if (vendorList == null) + { + return false; + } + + vendorList.Vendors.Add(vendor); + return true; + } + + public bool UnregisterVendor(BaseFactionVendor vendor) => + vendor != null && (FindVendorList(vendor.GetType())?.Vendors.Remove(vendor) ?? false); + + public static void Configure() + { + CommandSystem.Register("GrantTownSilver", AccessLevel.Administrator, GrantTownSilver_OnCommand); + } + + public static void Initialize() + { + // Looks useless, but is used to set the PlayerState for these roles + // TODO: When this moves to a deserialization pattern, put it in AfterDeserialization + for (var i = 0; i < Towns.Count; ++i) + { + var town = Towns[i]; + town.Sheriff = town.Sheriff; + town.Finance = town.Finance; + } + } + + public bool IsSheriff(Mobile mob) => + mob?.Deleted == false && + (mob.AccessLevel >= AccessLevel.GameMaster || mob == Sheriff); + + public bool IsFinance(Mobile mob) => + mob?.Deleted == false && + (mob.AccessLevel >= AccessLevel.GameMaster || mob == Finance); + + public void Capture(Faction f) + { + if (m_State.Owner == f) + { + return; + } + + if (m_State.Owner == null) // going from unowned to owned { LastIncome = Core.Now; - - var flow = NetCashFlow; - - if (Silver + flow < 0) - { - var toDelete = BuildFinanceList(); - - while (Silver + flow < 0 && toDelete.Count > 0) - { - var mob = toDelete.RandomElement(); - mob.Delete(); - - toDelete.Remove(mob); - flow = NetCashFlow; - } - } - - Silver += flow; + f.Silver += SilverCaptureBonus; + } + else if (f == null) // going from owned to unowned + { + LastIncome = DateTime.MinValue; + } + else // otherwise changing hands, income timer doesn't change + { + f.Silver += SilverCaptureBonus; } - public List BuildFinanceList() + m_State.Owner = f; + + Sheriff = null; + Finance = null; + + var monolith = Monolith; + + if (monolith != null) { - var list = new List(); - - for (var i = 0; i < VendorLists.Count; ++i) - { - list.AddRange(VendorLists[i].Vendors); - } - - for (var i = 0; i < GuardLists.Count; ++i) - { - list.AddRange(GuardLists[i].Guards); - } - - return list; + monolith.Faction = f; } - public void ConstructGuardLists() + var vendorLists = VendorLists; + + for (var i = 0; i < vendorLists.Count; ++i) { - var defs = Owner?.Definition.Guards ?? Array.Empty(); + var vendorList = vendorLists[i]; + var vendors = vendorList.Vendors; - GuardLists = new List(); - - for (var i = 0; i < defs.Length; ++i) + for (var j = vendors.Count - 1; j >= 0; --j) { - GuardLists.Add(new GuardList(defs[i])); + vendors[j].Delete(); } } - public GuardList FindGuardList(Type type) + var guardLists = GuardLists; + + for (var i = 0; i < guardLists.Count; ++i) { - var guardLists = GuardLists; + var guardList = guardLists[i]; + var guards = guardList.Guards; - for (var i = 0; i < guardLists.Count; ++i) + for (var j = guards.Count - 1; j >= 0; --j) { - var guardList = guardLists[i]; - - if (guardList.Definition.Type == type) - { - return guardList; - } - } - - return null; - } - - public void ConstructVendorLists() - { - var defs = VendorDefinition.Definitions; - - VendorLists = new List(); - - for (var i = 0; i < defs.Length; ++i) - { - VendorLists.Add(new VendorList(defs[i])); + guards[j].Delete(); } } - public VendorList FindVendorList(Type type) + ConstructGuardLists(); + } + + public override string ToString() => Definition.FriendlyName; + + public static void WriteReference(IGenericWriter writer, Town town) + { + var idx = Towns.IndexOf(town); + + writer.WriteEncodedInt(idx + 1); + } + + public static Town ReadReference(IGenericReader reader) + { + var idx = reader.ReadEncodedInt() - 1; + + if (idx >= 0 && idx < Towns.Count) { - var vendorLists = VendorLists; - - for (var i = 0; i < vendorLists.Count; ++i) - { - var vendorList = vendorLists[i]; - - if (vendorList.Definition.Type == type) - { - return vendorList; - } - } - - return null; + return Towns[idx]; } - public bool RegisterGuard(BaseFactionGuard guard) + return null; + } + + public static Town Parse(string name) + { + var towns = Towns; + + for (var i = 0; i < towns.Count; ++i) { - if (guard == null) + var town = towns[i]; + + if (town.Definition.FriendlyName.InsensitiveEquals(name)) { - return false; - } - - var guardList = FindGuardList(guard.GetType()); - - if (guardList == null) - { - return false; - } - - guardList.Guards.Add(guard); - return true; - } - - public bool UnregisterGuard(BaseFactionGuard guard) - { - if (guard == null) - { - return false; - } - - var guardList = FindGuardList(guard.GetType()); - - if (guardList == null) - { - return false; - } - - if (!guardList.Guards.Contains(guard)) - { - return false; - } - - guardList.Guards.Remove(guard); - return true; - } - - public bool RegisterVendor(BaseFactionVendor vendor) - { - if (vendor == null) - { - return false; - } - - var vendorList = FindVendorList(vendor.GetType()); - - if (vendorList == null) - { - return false; - } - - vendorList.Vendors.Add(vendor); - return true; - } - - public bool UnregisterVendor(BaseFactionVendor vendor) - { - if (vendor == null) - { - return false; - } - - var vendorList = FindVendorList(vendor.GetType()); - - if (vendorList == null) - { - return false; - } - - if (!vendorList.Vendors.Contains(vendor)) - { - return false; - } - - vendorList.Vendors.Remove(vendor); - return true; - } - - public static void Configure() - { - CommandSystem.Register("GrantTownSilver", AccessLevel.Administrator, GrantTownSilver_OnCommand); - } - - public static void Initialize() - { - var towns = Towns; - - for (var i = 0; i < towns.Count; ++i) - { - towns[i].Sheriff = towns[i].Sheriff; - towns[i].Finance = towns[i].Finance; + return town; } } - public bool IsSheriff(Mobile mob) => - mob?.Deleted == false && - (mob.AccessLevel >= AccessLevel.GameMaster || mob == Sheriff); + return null; + } - public bool IsFinance(Mobile mob) => - mob?.Deleted == false && - (mob.AccessLevel >= AccessLevel.GameMaster || mob == Finance); + [Usage("GrantTownSilver ")] + [Description("Grants silver to the town of the current region.")] + public static void GrantTownSilver_OnCommand(CommandEventArgs e) + { + var town = FromRegion(e.Mobile.Region); - public void Capture(Faction f) + if (town == null) { - if (m_State.Owner == f) - { - return; - } - - if (m_State.Owner == null) // going from unowned to owned - { - LastIncome = Core.Now; - f.Silver += SilverCaptureBonus; - } - else if (f == null) // going from owned to unowned - { - LastIncome = DateTime.MinValue; - } - else // otherwise changing hands, income timer doesn't change - { - f.Silver += SilverCaptureBonus; - } - - m_State.Owner = f; - - Sheriff = null; - Finance = null; - - var monolith = Monolith; - - if (monolith != null) - { - monolith.Faction = f; - } - - var vendorLists = VendorLists; - - for (var i = 0; i < vendorLists.Count; ++i) - { - var vendorList = vendorLists[i]; - var vendors = vendorList.Vendors; - - for (var j = vendors.Count - 1; j >= 0; --j) - { - vendors[j].Delete(); - } - } - - var guardLists = GuardLists; - - for (var i = 0; i < guardLists.Count; ++i) - { - var guardList = guardLists[i]; - var guards = guardList.Guards; - - for (var j = guards.Count - 1; j >= 0; --j) - { - guards[j].Delete(); - } - } - - ConstructGuardLists(); + e.Mobile.SendMessage("You are not in a faction town."); } - - public override string ToString() => Definition.FriendlyName; - - public static void WriteReference(IGenericWriter writer, Town town) + else if (e.Length == 0) { - var idx = Towns.IndexOf(town); - - writer.WriteEncodedInt(idx + 1); + e.Mobile.SendMessage("Format: GrantTownSilver "); } - - public static Town ReadReference(IGenericReader reader) + else { - var idx = reader.ReadEncodedInt() - 1; - - if (idx >= 0 && idx < Towns.Count) - { - return Towns[idx]; - } - - return null; - } - - public static Town Parse(string name) - { - var towns = Towns; - - for (var i = 0; i < towns.Count; ++i) - { - var town = towns[i]; - - if (town.Definition.FriendlyName.InsensitiveEquals(name)) - { - return town; - } - } - - return null; - } - - [Usage("GrantTownSilver ")] - [Description("Grants silver to the town of the current region.")] - public static void GrantTownSilver_OnCommand(CommandEventArgs e) - { - var town = FromRegion(e.Mobile.Region); - - if (town == null) - { - e.Mobile.SendMessage("You are not in a faction town."); - } - else if (e.Length == 0) - { - e.Mobile.SendMessage("Format: GrantTownSilver "); - } - else - { - town.Silver += e.GetInt32(0); - e.Mobile.SendMessage( - $"You have granted {e.GetInt32(0):N0} silver to the town. It now has {town.Silver:N0} silver." - ); - } + town.Silver += e.GetInt32(0); + e.Mobile.SendMessage( + $"You have granted {e.GetInt32(0):N0} silver to the town. It now has {town.Silver:N0} silver." + ); } } } diff --git a/Projects/UOContent/Engines/Factions/Core/TownState.cs b/Projects/UOContent/Engines/Factions/Core/TownState.cs index 27523a7f4..0017555c5 100644 --- a/Projects/UOContent/Engines/Factions/Core/TownState.cs +++ b/Projects/UOContent/Engines/Factions/Core/TownState.cs @@ -1,140 +1,139 @@ 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; - private Mobile m_Sheriff; + var version = reader.ReadEncodedInt(); - public TownState(Town town) => Town = town; - - public TownState(IGenericReader reader) + switch (version) { - var version = reader.ReadEncodedInt(); - - 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(); - m_Finance = reader.ReadEntity(); - - 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) + case 3: { - var pl = PlayerState.Find(m_Sheriff); + LastIncome = reader.ReadDateTime(); - if (pl != null) - { - pl.Sheriff = null; - } + goto case 2; } - - m_Sheriff = value; - - if (m_Sheriff != null) + case 2: { - var pl = PlayerState.Find(m_Sheriff); + Tax = reader.ReadEncodedInt(); + LastTaxChange = reader.ReadDateTime(); - if (pl != null) - { - pl.Sheriff = Town; - } + goto case 1; } - } - } - - public Mobile Finance - { - get => m_Finance; - set - { - if (m_Finance != null) + case 1: { - var pl = PlayerState.Find(m_Finance); + Silver = reader.ReadEncodedInt(); - if (pl != null) - { - pl.Finance = null; - } + goto case 0; } - - m_Finance = value; - - if (m_Finance != null) + case 0: { - var pl = PlayerState.Find(m_Finance); + Town = Town.ReadReference(reader); + Owner = Faction.ReadReference(reader); - if (pl != null) - { - pl.Finance = Town; - } + m_Sheriff = reader.ReadEntity(); + m_Finance = reader.ReadEntity(); + + 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); + } +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Core/VendorList.cs b/Projects/UOContent/Engines/Factions/Core/VendorList.cs index e4550e95d..35d779032 100644 --- a/Projects/UOContent/Engines/Factions/Core/VendorList.cs +++ b/Projects/UOContent/Engines/Factions/Core/VendorList.cs @@ -1,29 +1,28 @@ 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 Vendors { get; } + + public BaseFactionVendor Construct(Town town, Faction faction) + { + try { - Definition = definition; - Vendors = new List(); + return Definition.Type.CreateInstance(town, faction); } - - public VendorDefinition Definition { get; } - - public List Vendors { get; } - - public BaseFactionVendor Construct(Town town, Faction faction) + catch { - try - { - return Definition.Type.CreateInstance(town, faction); - } - catch - { - return null; - } + return null; } } -} +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Definitions/FactionItemDefinition.cs b/Projects/UOContent/Engines/Factions/Definitions/FactionItemDefinition.cs index 14cee20b0..8e2f74f01 100644 --- a/Projects/UOContent/Engines/Factions/Definitions/FactionItemDefinition.cs +++ b/Projects/UOContent/Engines/Factions/Definitions/FactionItemDefinition.cs @@ -25,37 +25,17 @@ namespace Server.Factions public static FactionItemDefinition Identify(Item item) { - if (item is BaseArmor armor) + return item switch { - if (CraftResources.GetType(armor.Resource) == CraftResourceType.Leather) - { - return m_LeatherArmor; - } - - return m_MetalArmor; - } - - 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; + BaseArmor armor => CraftResources.GetType(armor.Resource) == CraftResourceType.Leather + ? m_LeatherArmor + : m_MetalArmor, + BaseRanged => m_RangedWeapon, + BaseWeapon => m_Weapon, + BaseClothing => m_Clothing, + SpellScroll => m_Scroll, + _ => null + }; } } } diff --git a/Projects/UOContent/Engines/Factions/Gumps/ElectionGump.cs b/Projects/UOContent/Engines/Factions/Gumps/ElectionGump.cs index 3305f1a60..d5c94ae96 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/ElectionGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/ElectionGump.cs @@ -3,131 +3,130 @@ using Server.Gumps; using Server.Mobiles; 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; - private readonly PlayerMobile m_From; + m_From = 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; - m_Election = election; + case ElectionState.Pending: + { + 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); - 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: + if (days > 0) { - var toGo = election.LastStateTime + Election.PendingPeriod - Core.Now; - 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); + AddHtmlLocalized(20, 60, 280, 20, 1018062); // Days until next election : 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); - AddHtmlLocalized(55, 140, 350, 20, 1011012); // CANCEL + 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()); + + 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)); - break; + m_From.SendGump(new VoteGump(m_From, m_Election)); } - case 1: // vote - { - if (m_Election.State == ElectionState.Election) - { - m_From.SendGump(new VoteGump(m_From, m_Election)); - } - break; - } - case 2: // campaign + break; + } + case 2: // campaign + { + if (m_Election.CanBeCandidate(m_From)) { - if (m_Election.CanBeCandidate(m_From)) - { - m_Election.AddCandidate(m_From); - } - - break; + m_Election.AddCandidate(m_From); } - } + + break; + } } } } diff --git a/Projects/UOContent/Engines/Factions/Gumps/ElectionManagementGump.cs b/Projects/UOContent/Engines/Factions/Gumps/ElectionManagementGump.cs index 4525af44f..5c9a6fad5 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/ElectionManagementGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/ElectionManagementGump.cs @@ -3,202 +3,201 @@ using System.Net; using Server.Gumps; 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; - private readonly Candidate m_Candidate; + m_Election = election; + m_Candidate = candidate; + m_Page = page; - private readonly Election m_Election; - private readonly int m_Page; + AddPage(0); - public ElectionManagementGump(Election election, Candidate candidate = null, int page = 0) : base(40, 40) + if (candidate != null) { - m_Election = election; - m_Candidate = candidate; - m_Page = page; + AddBackground(0, 0, 448, 354, 9270); + AddAlphaRegion(10, 10, 428, 334); - 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); - 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; - } - } - } + AddButton(397, 104, 0x15E3, 0x15E7, 2); } else { - AddBackground(0, 0, 288, 334, 9270); - AddAlphaRegion(10, 10, 268, 314); + AddImage(397, 104, 0x25EA); + } - 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(145, 35, 100, 20, election.State.ToString().Color(LabelColor)); + 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)); - 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)); + var idx = 0; - AddImageTiled(13, 79, 262, 242, 9264); - AddImageTiled(14, 80, 260, 240, 9274); - AddAlphaRegion(14, 80, 260, 240); + for (var i = page * 10; i >= 0 && i < candidate.Voters.Count && i < (page + 1) * 10; ++i, ++idx) + { + var voter = candidate.Voters[i]; - 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)); + AddButton(13, 138 + idx * 20, 4002, 4004, 4 + i); - 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 mob = cd.Mobile; + var obj = fields[j]; - 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)); } } } - - 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) + else { - var from = sender.Mobile; - var bid = info.ButtonID; + AddBackground(0, 0, 288, 334, 9270); + 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; - - if (bid < m_Election.Candidates.Count) - { - from.SendGump(new ElectionManagementGump(m_Election, m_Election.Candidates[bid])); - } + continue; } - } - 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)); - } + 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)); } } } -} + + 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)); + } + } + } +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Gumps/FactionGump.cs b/Projects/UOContent/Engines/Factions/Gumps/FactionGump.cs index f3e773b12..32a838d8a 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/FactionGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/FactionGump.cs @@ -1,44 +1,43 @@ 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(); - 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; - - if (offset >= 0) - { - type = offset % ButtonTypes; - index = offset / ButtonTypes; - return true; - } - - type = index = 0; - return false; + AddHtmlLocalized(x, y, width, height, text.Number, back, scroll); } - - public static bool Exists(Mobile mob) => mob.HasGump(); - - public void AddHtmlText(int x, int y, int width, int height, TextDefinition text, bool back, bool scroll) + else if (text?.String != null) { - if (text?.Number > 0) - { - AddHtmlLocalized(x, y, width, height, text.Number, back, scroll); - } - else if (text?.String != null) - { - AddHtml(x, y, width, height, text.String, back, scroll); - } + AddHtml(x, y, width, height, text.String, back, scroll); } } -} +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Gumps/FactionImbueGump.cs b/Projects/UOContent/Engines/Factions/Gumps/FactionImbueGump.cs index f8ac3742c..eec829a08 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/FactionImbueGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/FactionImbueGump.cs @@ -3,112 +3,111 @@ using Server.Gumps; using Server.Items; 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; - 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; + AddPage(0); - public FactionImbueGump( - int quality, Item item, Mobile from, CraftSystem craftSystem, BaseTool tool, TextDefinition notice, - int availableSilver, Faction faction, FactionItemDefinition def - ) : base(100, 200) + 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) { - m_Item = item; - m_Mobile = from; - m_Faction = faction; - m_CraftSystem = craftSystem; - m_Tool = tool; - m_Notice = notice; - m_Definition = def; + var pack = m_Mobile.Backpack; - AddPage(0); - - 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) + if (pack != null && m_Item.IsChildOf(pack)) { - var pack = m_Mobile.Backpack; - - if (pack != null && m_Item.IsChildOf(pack)) + if (pack.ConsumeTotal(typeof(Silver), m_Definition.SilverCost)) { - if (pack.ConsumeTotal(typeof(Silver), m_Definition.SilverCost)) + int hue; + + if (m_Item is SpellScroll) { - int hue; - - if (m_Item is SpellScroll) - { - hue = 0; - } - else if (info.IsSwitched(1)) - { - hue = m_Faction.Definition.HuePrimary; - } - else - { - hue = m_Faction.Definition.HueSecondary; - } - - FactionItem.Imbue(m_Item, m_Faction, true, hue); + hue = 0; + } + else if (info.IsSwitched(1)) + { + hue = m_Faction.Definition.HuePrimary; } 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) - { - 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); + FactionItem.Imbue(m_Item, m_Faction, true, hue); } 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); + } + } } -} +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Gumps/FactionStoneGump.cs b/Projects/UOContent/Engines/Factions/Gumps/FactionStoneGump.cs index 1d10b8d27..091e1df95 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/FactionStoneGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/FactionStoneGump.cs @@ -2,364 +2,363 @@ using Server.Gumps; using Server.Mobiles; 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; - private readonly PlayerMobile m_From; + m_From = 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; - m_Faction = faction; + AddHtmlLocalized(125, 80, 350, 20, 1011480 + faction.Tithe / 10); + } + 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); - AddBackground(10, 10, 530, 420, 3000); + AddHtmlLocalized(55, 225, 200, 20, 1011428); // VOTE FOR LEADERSHIP + 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 : - AddHtml(125, 60, 200, 20, faction.Commander != null ? faction.Commander.Name : "Nobody"); + var isMerchantQualified = MerchantTitles.HasMerchantQualifications(from); - AddHtmlLocalized(20, 80, 100, 20, 1011457); // Tithe rate : - if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0) + var pl = PlayerState.Find(from); + + 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 { - 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 : - AddHtml(125, 100, 50, 20, faction.Traps.Count.ToString()); + AddImage(20, 300, 2361); + AddHtmlLocalized(45, 295, 300, 20, 1011491); // sigil may be recaptured - AddHtmlLocalized(55, 225, 200, 20, 1011428); // VOTE FOR LEADERSHIP - AddButton(20, 225, 4005, 4007, ToButtonID(0, 0)); + AddImage(20, 320, 2360); + AddHtmlLocalized(45, 315, 300, 20, 1011492); // sigil may not be recaptured - AddHtmlLocalized(55, 150, 100, 20, 1011430); // CITY STATUS - AddButton(20, 150, 4005, 4007, 0, GumpButtonType.Page, 2); + AddHtmlLocalized(55, 350, 100, 20, 1011447); // BACK + AddButton(20, 350, 4005, 4007, 0, GumpButtonType.Page, 1); - AddHtmlLocalized(55, 175, 100, 20, 1011444); // STATISTICS - AddButton(20, 175, 4005, 4007, 0, GumpButtonType.Page, 4); + AddPage(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 - 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); - } + var info = infos[i]; - 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) + if (MerchantTitles.IsQualified(from, info)) { - AddHtmlLocalized(200, 55 + i * 30, 150, 20, 1011462); // : Neutral + AddButton(20, 100 + i * 30, 4005, 4007, ToButtonID(1, i + 1)); } else { - 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); + AddImage(20, 100 + i * 30, 4020); } + + AddHtmlText(55, 100 + i * 30, 200, 20, info.Label, false, false); } - AddImage(20, 300, 2361); - AddHtmlLocalized(45, 295, 300, 20, 1011491); // sigil may be recaptured + AddHtmlLocalized(55, 340, 100, 20, 1011447); // BACK + AddButton(20, 340, 4005, 4007, 0, GumpButtonType.Page, 1); + } - AddImage(20, 320, 2360); - AddHtmlLocalized(45, 315, 300, 20, 1011492); // sigil may not be recaptured + if (faction.IsCommander(from)) + { + AddPage(6); - AddHtmlLocalized(55, 350, 100, 20, 1011447); // BACK - AddButton(20, 350, 4005, 4007, 0, GumpButtonType.Page, 1); + AddHtmlLocalized(20, 30, 200, 20, 1011461); // COMMANDER OPTIONS - AddPage(4); - - 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) + AddHtmlLocalized(20, 70, 120, 20, 1011457); // Tithe rate : + if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0) { - 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 { - 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 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); - - 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); + y += 5; } - 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; - - for (var i = 0; i <= 10; ++i) + if (i == 5) { - if (i == 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; - } + 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) - { - 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; - } - } + 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) + { + 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; + } + } + } +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Gumps/FinanceGump.cs b/Projects/UOContent/Engines/Factions/Gumps/FinanceGump.cs index cf53e440f..5d0c0ec60 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/FinanceGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/FinanceGump.cs @@ -3,294 +3,293 @@ using Server.Mobiles; using Server.Multis; 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, - +50, +100, +150, +200, +250, +300 - }; + var ofs = m_PriceOffsets[i]; - private readonly Faction m_Faction; - private readonly PlayerMobile m_From; - private readonly Town m_Town; + var x = 20 + i / 6 * 150; + var y = 90 + i % 6 * 30; - public FinanceGump(PlayerMobile from, Faction faction, Town town) : base(50, 50) - { - m_From = from; - m_Faction = faction; - m_Town = town; + AddRadio(x, y, 208, 209, town.Tax == ofs, i + 1); - 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) + if (ofs < 0) { - var ofs = m_PriceOffsets[i]; - - 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}%"); - } + AddLabel(x + 35, y, 0x26, $"- {-ofs}%"); } - - 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) + else { - 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) - { - 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); + AddLabel(x + 35, y, 0x12A, $"+ {ofs}%"); } } - 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 - return; + AddButton(20, 300, 4005, 4007, ToButtonID(1, i)); + } + else + { + AddImage(20, 300, 4020); } - if (!FromButtonID(info.ButtonID, out var type, out var index)) - { - return; - } + AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page + AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 3); + } + } - switch (type) - { - case 0: // general + public override int ButtonTypes => 2; + + 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); } - - var opt = switches[0]; - var newTax = 0; - - if (opt >= 1 && opt <= m_PriceOffsets.Length) + else if (remaining.TotalMinutes < 10) { - newTax = m_PriceOffsets[opt - 1]; + // You must wait several minutes before changing prices again. + m_From.SendLocalizedMessage(1042166); } - - if (m_Town.Tax == newTax) + else if (remaining.TotalHours < 1) { - break; + // You must wait up to an hour before changing prices again. + m_From.SendLocalizedMessage(1042167); } - - if (m_From.AccessLevel == AccessLevel.Player && !m_Town.TaxChangeReady) + else if (remaining.TotalHours < 4) { - var remaining = Core.Now - (m_Town.LastTaxChange + Town.TaxChangePeriod); - - 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); - } + // You must wait a few hours before changing prices again. + m_From.SendLocalizedMessage(1042168); } else { - m_Town.Tax = newTax; - - if (m_From.AccessLevel == AccessLevel.Player) - { - m_Town.LastTaxChange = Core.Now; - } + // You must wait several hours before changing prices again. + m_From.SendLocalizedMessage(1042169); } - - 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) + else { - m_Town.Silver -= vendorList.Definition.Price; + m_Town.Tax = newTax; - vendor.MoveToWorld(m_From.Location, m_From.Map); - vendor.Home = vendor.Location; + if (m_From.AccessLevel == AccessLevel.Player) + { + 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; + } } } -} +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Gumps/HorseBreederGump.cs b/Projects/UOContent/Engines/Factions/Gumps/HorseBreederGump.cs index 130caa571..7cd4edc92 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/HorseBreederGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/HorseBreederGump.cs @@ -3,95 +3,94 @@ using Server.Items; using Server.Mobiles; 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; - private readonly PlayerMobile m_From; + m_From = 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; - 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); + return; } - 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; - } - - 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? + 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 { - if (pack.GetAmount(typeof(Silver)) < FactionWarHorse.SilverPrice) - { - 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(); - } + horse.Delete(); } } } -} +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Gumps/JoinStoneGump.cs b/Projects/UOContent/Engines/Factions/Gumps/JoinStoneGump.cs index 9e2b9a615..bafc3a78b 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/JoinStoneGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/JoinStoneGump.cs @@ -2,52 +2,51 @@ using Server.Gumps; using Server.Mobiles; 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; - private readonly PlayerMobile m_From; + m_From = 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; - m_Faction = faction; - - 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) - { - 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 + AddHtmlLocalized(125, 80, 350, 20, 1011480 + faction.Tithe / 10); + } + else + { + AddHtml(125, 80, 350, 20, $"{faction.Tithe}%"); } - 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); } } -} +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Gumps/LeaveFactionGump.cs b/Projects/UOContent/Engines/Factions/Gumps/LeaveFactionGump.cs index eacc61814..4db9ee982 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/LeaveFactionGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/LeaveFactionGump.cs @@ -4,55 +4,85 @@ using Server.Gumps; using Server.Mobiles; 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; - private Faction m_Faction; + m_From = from; + 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; - m_Faction = faction; - - AddBackground(0, 0, 270, 120, 5054); - AddBackground(10, 10, 250, 100, 3000); - - if (from.Guild is Guild guild && guild.Leader == from) - { - AddHtmlLocalized( - 20, - 15, - 230, - 60, - 1018057, // Are you sure you want your entire guild to leave this faction? - 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); + AddHtmlLocalized( + 20, + 15, + 230, + 60, + 1018057, // Are you sure you want your entire guild to leave this faction? + true, + true + ); + } + else + { + // Are you sure you want to leave this faction?s + AddHtmlLocalized(20, 15, 230, 60, 1018063, true, true); } - 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) { @@ -60,57 +90,26 @@ namespace Server.Factions 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 { - m_From.SendMessage( - $"You will be removed from the faction in {Faction.LeavePeriod.TotalDays} days." + mob.SendMessage( + $"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 - { - m_From.SendLocalizedMessage(500737); // Canceled resignation. - break; - } - } + + break; + } + case 2: // cancel + { + m_From.SendLocalizedMessage(500737); // Canceled resignation. + break; + } } } -} +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Gumps/SheriffGump.cs b/Projects/UOContent/Engines/Factions/Gumps/SheriffGump.cs index ea5c560a9..f5a466259 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/SheriffGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/SheriffGump.cs @@ -3,168 +3,167 @@ using Server.Mobiles; using Server.Multis; 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; - private readonly PlayerMobile m_From; - private readonly Town m_Town; + m_From = from; + m_Faction = faction; + 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; - m_Faction = faction; - m_Town = town; + var guardList = guardLists[i]; + var y = 90 + i * 60; - 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) - { - 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); - } + 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); } - 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]; - AddItem(x + (w - rc.Width) / 2 - rc.X, y + (h - rc.Height) / 2 - rc.Y, itemID); + 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) + { + 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 - return; + m_From.SendLocalizedMessage(1010305); // You must be in your controlled city to buy Items } - - var index = info.ButtonID - 1; - - if (index >= 0 && index < m_Town.GuardLists.Count) + else if (guardList.Guards.Count >= guardList.Definition.Maximum) { - 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 - } - 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(); + guard.Faction = m_Faction; + guard.Town = m_Town; - if (guard != null) - { - guard.Faction = m_Faction; - guard.Town = m_Town; + m_Town.Silver -= guardList.Definition.Price; - 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; } } } } -} +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Gumps/TownStoneGump.cs b/Projects/UOContent/Engines/Factions/Gumps/TownStoneGump.cs index 8eada407d..f225d2718 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/TownStoneGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/TownStoneGump.cs @@ -3,206 +3,209 @@ using Server.Mobiles; using Server.Network; 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; - private readonly PlayerMobile m_From; - private readonly Town m_Town; + m_From = from; + m_Faction = faction; + 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_Faction = faction; - 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); + m_From.SendLocalizedMessage(1010339); // You no longer control this city + return; } - public override void OnResponse(NetState sender, in RelayInfo info) + switch (info.ButtonID) { - if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(m_From)) - { - m_From.SendLocalizedMessage(1010339); // You no longer control this city - return; - } - - switch (info.ButtonID) - { - case 1: // hire sheriff + case 1: // hire sheriff + { + if (m_Town.Sheriff != null) { - if (m_Town.Sheriff != null) - { - // 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; + // You must fire your Sheriff before you can elect a new one + m_From.SendLocalizedMessage(1010342); } - case 2: // hire finance minister + else { - if (m_Town.Finance != null) - { - // 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; + m_From.SendLocalizedMessage(1010347); // Who shall be your new sheriff + m_From.BeginTarget(12, false, TargetFlags.None, HireSheriff_OnTarget); } - case 3: // fire sheriff + + break; + } + case 2: // hire finance minister + { + if (m_Town.Finance != null) { - 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; + // You must fire your finance minister before you can elect a new one + m_From.SendLocalizedMessage(1010345); } - case 4: // fire finance minister + else { - 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; + 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 + { + 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(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! - } + from.SendLocalizedMessage(1010342); // You must fire your Sheriff before you can elect a new one + return; } - 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(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); + from.SendLocalizedMessage(1010334); // You must select a player to hold a city position! + return; + } - 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.Finance = targ; - targ.SendLocalizedMessage(1010343); // You are now the Financial Minister - from.SendLocalizedMessage(1010344); // You have elected a Financial Minister - } - } - else - { - from.SendLocalizedMessage(1010334); // You must select a player to hold a city position! - } + 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.Sheriff = m; + m.SendLocalizedMessage(1010340); // You are now the Sheriff + from.SendLocalizedMessage(1010341); // You have elected a Sheriff + } + } + + 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 } } } diff --git a/Projects/UOContent/Engines/Factions/Gumps/VoteGump.cs b/Projects/UOContent/Engines/Factions/Gumps/VoteGump.cs index 7a0615457..a691f7417 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/VoteGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/VoteGump.cs @@ -2,75 +2,74 @@ using Server.Gumps; using Server.Mobiles; 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; - private readonly PlayerMobile m_From; + m_From = 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; - m_Election = election; + AddHtmlLocalized(20, 60, 380, 20, 1011428); // VOTE FOR LEADERSHIP + } + else + { + AddHtmlLocalized(20, 60, 380, 20, 1038032); // You have already voted in this election. + } - 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); + for (var i = 0; i < election.Candidates.Count; ++i) + { + var cd = election.Candidates[i]; if (canVote) { - AddHtmlLocalized(20, 60, 380, 20, 1011428); // VOTE FOR LEADERSHIP - } - else - { - AddHtmlLocalized(20, 60, 380, 20, 1038032); // You have already voted in this election. + AddButton(20, 100 + i * 20, 4005, 4007, i + 1); } - for (var i = 0; i < election.Candidates.Count; ++i) - { - 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 + AddLabel(55, 100 + i * 20, 0, cd.Mobile.Name); + AddLabel(300, 100 + i * 20, 0, cd.Votes.ToString()); } - 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)) - { - 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_Election.Candidates[index].Voters.Add(new Voter(m_From, m_Election.Candidates[index].Mobile)); } + + m_From.SendGump(new VoteGump(m_From, m_Election)); } } -} +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Instances/Factions/CouncilOfMages.cs b/Projects/UOContent/Engines/Factions/Instances/Factions/CouncilOfMages.cs index c10a70afd..6c95ed467 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Factions/CouncilOfMages.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Factions/CouncilOfMages.cs @@ -39,15 +39,13 @@ public class CouncilOfMages : Faction 1005189, // Members of the Council of Mages will now be beaten with a stick. // Moonglow new StrongholdDefinition( - new[] - { + [ new Rectangle2D(4463, 1487, 15, 35), new Rectangle2D(4450, 1522, 35, 48) - }, + ], new Point3D(4469, 1486, 0), new Point3D(4457, 1544, 0), - new[] - { + [ new Point3D(4464, 1534, 21), new Point3D(4470, 1536, 21), new Point3D(4468, 1534, 21), @@ -56,7 +54,7 @@ public class CouncilOfMages : Faction new Point3D(4466, 1534, 21), new Point3D(4466, 1536, 21), new Point3D(4464, 1536, 21) - } + ] ), // Magincia /* new StrongholdDefinition( @@ -80,8 +78,7 @@ public class CouncilOfMages : Faction new Point3D( 3797, 2249, 20 ), new Point3D( 3797, 2246, 20 ) } ), */ - new[] - { + [ new RankDefinition(10, 991, 8, 1060789), // Inquisitor of the Council new RankDefinition(9, 950, 7, 1060788), // Archon of Principle new RankDefinition(8, 900, 6, 1060787), // Luminary @@ -92,9 +89,8 @@ public class CouncilOfMages : Faction new RankDefinition(3, 400, 4, 1060785), // Mystic new RankDefinition(2, 200, 4, 1060785), // Mystic new RankDefinition(1, 0, 4, 1060785) // Mystic - }, - new[] - { + ], + [ new GuardDefinition( typeof(FactionHenchman), 0x1403, @@ -131,7 +127,7 @@ public class CouncilOfMages : Faction 1011508, // ELDER WIZARD 1011502 // Hire Elder Wizard ) - } + ] ); } diff --git a/Projects/UOContent/Engines/Factions/Instances/Factions/Minax.cs b/Projects/UOContent/Engines/Factions/Instances/Factions/Minax.cs index 55321911b..5ea59142e 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Factions/Minax.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Factions/Minax.cs @@ -39,14 +39,12 @@ public class Minax : Faction 1005191, // Followers of Minax will now be told to go away. 1005192, // Followers of Minax will now be hanged by their toes. new StrongholdDefinition( - new[] - { + [ new Rectangle2D(1097, 2570, 70, 50) - }, + ], new Point3D(1172, 2593, 0), new Point3D(1117, 2587, 18), - new[] - { + [ new Point3D(1113, 2601, 18), new Point3D(1113, 2598, 18), new Point3D(1113, 2595, 18), @@ -55,10 +53,9 @@ public class Minax : Faction new Point3D(1116, 2598, 18), new Point3D(1116, 2595, 18), new Point3D(1116, 2592, 18) - } + ] ), - new[] - { + [ new RankDefinition(10, 991, 8, 1060784), // Avenger of Mondain new RankDefinition(9, 950, 7, 1060783), // Dread Knight new RankDefinition(8, 900, 6, 1060782), // Warlord @@ -69,9 +66,8 @@ public class Minax : Faction new RankDefinition(3, 400, 4, 1060780), // Defiler new RankDefinition(2, 200, 4, 1060780), // Defiler new RankDefinition(1, 0, 4, 1060780) // Defiler - }, - new[] - { + ], + [ new GuardDefinition( typeof(FactionHenchman), 0x1403, @@ -108,7 +104,7 @@ public class Minax : Faction 1011506, // DRAGOON 1011500 // Hire Dragoon ) - } + ] ); } diff --git a/Projects/UOContent/Engines/Factions/Instances/Factions/Shadowlords.cs b/Projects/UOContent/Engines/Factions/Instances/Factions/Shadowlords.cs index 7c48cf88c..903d8fe48 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Factions/Shadowlords.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Factions/Shadowlords.cs @@ -38,15 +38,13 @@ public class Shadowlords : Faction 1005185, // Minions of the Shadowlords will now be warned of their impending deaths. 1005186, // Minions of the Shadowlords will now be attacked at will. new StrongholdDefinition( - new[] - { + [ new Rectangle2D(960, 688, 8, 9), new Rectangle2D(944, 697, 24, 23) - }, + ], new Point3D(969, 768, 0), new Point3D(947, 713, 0), - new[] - { + [ new Point3D(953, 713, 20), new Point3D(953, 709, 20), new Point3D(953, 705, 20), @@ -55,10 +53,9 @@ public class Shadowlords : Faction new Point3D(957, 709, 20), new Point3D(957, 705, 20), new Point3D(957, 701, 20) - } + ] ), - new[] - { + [ new RankDefinition(10, 991, 8, 1060799), // Purveyor of Darkness new RankDefinition(9, 950, 7, 1060798), // Agent of Evil 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(2, 200, 4, 1060795), // Servant new RankDefinition(1, 0, 4, 1060795) // Servant - }, - new[] - { + ], + [ new GuardDefinition( typeof(FactionHenchman), 0x1403, @@ -108,7 +104,7 @@ public class Shadowlords : Faction 1011513, // SHADOW MAGE 1011504 // Hire Shadow Mage ) - } + ] ); } diff --git a/Projects/UOContent/Engines/Factions/Instances/Factions/TrueBritannians.cs b/Projects/UOContent/Engines/Factions/Instances/Factions/TrueBritannians.cs index 9c7e6c35f..983d08f88 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Factions/TrueBritannians.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Factions/TrueBritannians.cs @@ -38,8 +38,7 @@ public class TrueBritannians : Faction 1005182, // Followers of Lord British will now be warned of their impending doom. 1005183, // Followers of Lord British will now be attacked on sight. new StrongholdDefinition( - new[] - { + [ new Rectangle2D(1292, 1556, 25, 25), new Rectangle2D(1292, 1676, 120, 25), new Rectangle2D(1388, 1556, 25, 25), @@ -47,11 +46,10 @@ public class TrueBritannians : Faction new Rectangle2D(1300, 1581, 105, 95), new Rectangle2D(1405, 1612, 12, 21), new Rectangle2D(1405, 1633, 11, 5) - }, + ], new Point3D(1419, 1622, 20), new Point3D(1330, 1621, 50), - new[] - { + [ new Point3D(1328, 1627, 50), new Point3D(1328, 1621, 50), new Point3D(1334, 1627, 50), @@ -60,10 +58,9 @@ public class TrueBritannians : Faction new Point3D(1340, 1621, 50), new Point3D(1345, 1621, 50), new Point3D(1345, 1627, 50) - } + ] ), - new[] - { + [ new RankDefinition(10, 991, 8, 1060794), // Knight of the Codex new RankDefinition(9, 950, 7, 1060793), // Knight of Virtue new RankDefinition(8, 900, 6, 1060792), // Crusader @@ -73,10 +70,9 @@ public class TrueBritannians : Faction new RankDefinition(4, 500, 5, 1060791), // Sentinel new RankDefinition(3, 400, 4, 1060790), // Defender new RankDefinition(2, 200, 4, 1060790), // Defender - new RankDefinition(1, 0, 4, 1060790), // Defender - }, - new[] - { + new RankDefinition(1, 0, 4, 1060790) // Defender + ], + [ new GuardDefinition( typeof(FactionHenchman), 0x1403, @@ -113,7 +109,7 @@ public class TrueBritannians : Faction 1011529, // PALADIN 1011498 // Hire Paladin ) - } + ] ); } diff --git a/Projects/UOContent/Engines/Factions/Items/BaseMonolith.cs b/Projects/UOContent/Engines/Factions/Items/BaseMonolith.cs index 2a2858c71..465798370 100644 --- a/Projects/UOContent/Engines/Factions/Items/BaseMonolith.cs +++ b/Projects/UOContent/Engines/Factions/Items/BaseMonolith.cs @@ -1,137 +1,136 @@ 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; - private Sigil m_Sigil; - private Town m_Town; + Movable = false; + Town = 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; - 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 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) + if (m_Sigil == value) { return; } - m_Sigil.MoveToWorld(new Point3D(X, Y, Z + 18), Map); - } + m_Sigil = value; - 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) + if (m_Sigil?.LastMonolith != null && m_Sigil.LastMonolith != this && m_Sigil.LastMonolith.Sigil == m_Sigil) { - case 0: - { - Town = Town.ReadReference(reader); - Faction = Faction.ReadReference(reader); - m_Sigil = reader.ReadEntity(); - break; - } + 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 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(); + break; + } + } + } +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Items/BaseSystemController.cs b/Projects/UOContent/Engines/Factions/Items/BaseSystemController.cs index 64c184485..632f6021f 100644 --- a/Projects/UOContent/Engines/Factions/Items/BaseSystemController.cs +++ b/Projects/UOContent/Engines/Factions/Items/BaseSystemController.cs @@ -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; - public new virtual string DefaultName => null; - - 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(); - } + private void Deserialize(IGenericReader reader, int version) + { + // Do nothing } } diff --git a/Projects/UOContent/Engines/Factions/Items/FactionStone.cs b/Projects/UOContent/Engines/Factions/Items/FactionStone.cs index 87dd49651..fbfce0845 100644 --- a/Projects/UOContent/Engines/Factions/Items/FactionStone.cs +++ b/Projects/UOContent/Engines/Factions/Items/FactionStone.cs @@ -1,104 +1,103 @@ 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(Faction faction = null) : base(0xEDC) + public FactionStone(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Faction Faction + { + get => m_Faction; + set { - Movable = false; - Faction = faction; + m_Faction = value; + + 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. } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Faction Faction + else if (FactionGump.Exists(from)) { - get => m_Faction; - set - { - m_Faction = value; - - AssignName(m_Faction?.Definition.FactionStoneName); - } + from.SendLocalizedMessage(1042160); // You already have a faction menu open. } - - public override string DefaultName => "faction stone"; - - public override void OnDoubleClick(Mobile from) + else if (from is PlayerMobile mobile) { - if (m_Faction == null) - { - return; - } + var existingFaction = Faction.Find(mobile); - if (!from.InRange(GetWorldLocation(), 2)) + if (existingFaction == m_Faction || mobile.AccessLevel >= AccessLevel.GameMaster) { - 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 (from is PlayerMobile mobile) - { - var existingFaction = Faction.Find(mobile); + var pl = PlayerState.Find(mobile); - if (existingFaction == m_Faction || mobile.AccessLevel >= AccessLevel.GameMaster) + if (pl?.IsLeaving == true) { - var pl = PlayerState.Find(mobile); - - 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! + // You cannot use the faction stone until you have finished quitting your current faction + mobile.SendLocalizedMessage(1005051); } else { - mobile.SendGump(new JoinStoneGump(mobile, m_Faction)); + mobile.SendGump(new FactionStoneGump(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) + else if (existingFaction != null) { - case 0: - { - Faction = Faction.ReadReference(reader); - break; - } + // TODO: Validate + mobile.SendLocalizedMessage(1005053); // This is not your faction stone! + } + 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; + } + } + } } diff --git a/Projects/UOContent/Engines/Factions/Items/JoinStone.cs b/Projects/UOContent/Engines/Factions/Items/JoinStone.cs index c98626ea6..92abdaa14 100644 --- a/Projects/UOContent/Engines/Factions/Items/JoinStone.cs +++ b/Projects/UOContent/Engines/Factions/Items/JoinStone.cs @@ -1,81 +1,80 @@ 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(Faction faction = null) : base(0xEDC) + public JoinStone(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Faction Faction + { + get => m_Faction; + set { - Movable = false; - Faction = faction; - } + m_Faction = value; - public JoinStone(Serial serial) : base(serial) - { - } - - [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; - } - } + 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; + } + } + } +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Items/Sigil.cs b/Projects/UOContent/Engines/Factions/Items/Sigil.cs index 997aae5d5..9f8034726 100644 --- a/Projects/UOContent/Engines/Factions/Items/Sigil.cs +++ b/Projects/UOContent/Engines/Factions/Items/Sigil.cs @@ -4,474 +4,473 @@ using Server.Mobiles; using Server.Network; 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 ? - public static readonly TimeSpan CorruptionGrace = TimeSpan.FromMinutes(Core.SE ? 30.0 : 15.0); + Sigils.Add(this); + } - // 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); + public Sigil(Serial serial) : base(serial) + { + Sigils.Add(this); + } - // 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); + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public DateTime LastStolen { get; set; } - // 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; + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public DateTime GraceStart { get; set; } - 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; - Town = town; + m_Town = value; + 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 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)] - 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 + if (IsCorrupting) { - get => m_Town; - set + list.Add(1042257); // This sigil is in the process of being corrupted. + } + 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; - Update(); + LabelTo(from, m_Corrupted.Definition.SigilControl.Number); + } + else if (m_Corrupted.Definition.SigilControl.String != null) + { + LabelTo(from, m_Corrupted.Definition.SigilControl.String); } } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Faction Corrupted + else { - get => m_Corrupted; - set - { - m_Corrupted = value; - Update(); - } + LabelTo(from, 1042256); // This sigil is not corrupted. } - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Faction Corrupting + if (IsCorrupting) { - get => m_Corrupting; - set - { - m_Corrupting = value; - Update(); - } + 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. + } + } + + 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)] - 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 Sigils { get; } = new(); - - public void Update() + if (parent is Mobile mobile) { - 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); - } - - InvalidateProperties(); + return mobile; } - 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) - { - m_Corrupted.Definition.SigilControl.AddTo(list); - } - else - { - list.Add(1042256); // This sigil is not corrupted. - } + public override void OnRemoved(IEntity parent) + { + base.OnRemoved(parent); - if (IsCorrupting) - { - list.Add(1042257); // This sigil is in the process of being corrupted. - } - 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. - } + 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() != 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 (IsCorrupted) + if (obj is PlayerMobile targ) { - 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 { - LabelTo(from, 1042256); // This sigil is not corrupted. - } - - 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. + from.SendLocalizedMessage(1005221); // You cannot give the sigil to them } } - - public override bool CheckLift(Mobile from, Item item, ref LRReason reject) + else if (obj is BaseMonolith) { - 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) + if (obj is StrongholdMonolith sm) { - return item.RootParent as Mobile; - } - - 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() != 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) + if (sm.Faction == null || sm.Faction != Faction.Find(from)) { - var toFaction = Faction.Find(targ); - var fromFaction = Faction.Find(from); - - if (toFaction == null) - { - 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); - } + 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 { - 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(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; - } + from.SendLocalizedMessage(1042245); // This is not the correct town sigil monolith } - else if (obj is TownMonolith tm) + else if (m_Corrupted == null || m_Corrupted != Faction.Find(from)) { - if (tm.Town == null || tm.Town != m_Town) - { - from.SendLocalizedMessage(1042245); // This is not the correct town sigil monolith - } - else if (m_Corrupted == null || m_Corrupted != Faction.Find(from)) - { - // Your faction did not corrupt this sigil. Take it to your stronghold. - from.SendLocalizedMessage(1042244); - } - else - { - 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; - PurificationStart = Core.Now; - CorruptionStart = DateTime.MinValue; + m_Corrupting = null; + PurificationStart = Core.Now; + CorruptionStart = DateTime.MinValue; - m_Town.Capture(m_Corrupted); - m_Corrupted = null; - } + m_Town.Capture(m_Corrupted); + m_Corrupted = null; } } - else - { - from.SendLocalizedMessage(1005224); // You can't use the sigil on that - } - - Update(); + } + else + { + from.SendLocalizedMessage(1005224); // You can't use the sigil on that } - 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(); - Town.WriteReference(writer, m_Town); - Faction.WriteReference(writer, m_Corrupted); - Faction.WriteReference(writer, m_Corrupting); + LastStolen = reader.ReadDateTime(); + GraceStart = reader.ReadDateTime(); + CorruptionStart = reader.ReadDateTime(); + PurificationStart = reader.ReadDateTime(); - writer.Write(LastMonolith); + Update(); - 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) - { - case 0: + if (RootParent is Mobile mob) { - m_Town = Town.ReadReference(reader); - m_Corrupted = Faction.ReadReference(reader); - m_Corrupting = Faction.ReadReference(reader); - - LastMonolith = reader.ReadEntity(); - - LastStolen = reader.ReadDateTime(); - GraceStart = reader.ReadDateTime(); - CorruptionStart = reader.ReadDateTime(); - PurificationStart = reader.ReadDateTime(); - - Update(); - - if (RootParent is Mobile mob) - { - mob.SolidHueOverride = OwnershipHue; - } - - break; + mob.SolidHueOverride = OwnershipHue; } - } - } - 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(); + break; + } } } -} + + 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(); + } +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Items/StrongholdMonolith.cs b/Projects/UOContent/Engines/Factions/Items/StrongholdMonolith.cs index 3eab01878..69d87ccd2 100644 --- a/Projects/UOContent/Engines/Factions/Items/StrongholdMonolith.cs +++ b/Projects/UOContent/Engines/Factions/Items/StrongholdMonolith.cs @@ -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(); + } +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Items/TownMonolith.cs b/Projects/UOContent/Engines/Factions/Items/TownMonolith.cs index 264184f48..24043e310 100644 --- a/Projects/UOContent/Engines/Factions/Items/TownMonolith.cs +++ b/Projects/UOContent/Engines/Factions/Items/TownMonolith.cs @@ -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(); + } +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Items/TownStone.cs b/Projects/UOContent/Engines/Factions/Items/TownStone.cs index efac59f72..7bf02bce8 100644 --- a/Projects/UOContent/Engines/Factions/Items/TownStone.cs +++ b/Projects/UOContent/Engines/Factions/Items/TownStone.cs @@ -1,91 +1,90 @@ 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(Town town = null) : base(0xEDE) + public TownStone(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Town Town + { + get => m_Town; + set { - Movable = false; - Town = town; - } + m_Town = value; - public TownStone(Serial serial) : base(serial) - { - } - - [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; - } - } + 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; + } + } + } +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrap.cs b/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrap.cs index 05ba279c4..17b77d69c 100644 --- a/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrap.cs +++ b/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrap.cs @@ -2,289 +2,288 @@ using System; using Server.Items; using Server.Network; -namespace Server.Factions -{ - public enum AllowedPlacing - { - Everywhere, +namespace Server.Factions; - AnyFactionTown, - ControlledFactionTown, - FactionStronghold +public enum AllowedPlacing +{ + 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; - - Faction = f; - TimeOfPlacement = Core.Now; - Placer = m; + return; } - 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)] - 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)) + if (victimState?.CanGiveSilverTo(Placer) == true && victimState.KillPoints > 0) { - return; - } + var silverGiven = Faction.AwardSilver(Placer, silverToAward); - 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); - - if (victimState?.CanGiveSilverTo(Placer) == true && victimState.KillPoints > 0) + if (silverGiven > 0) { - var silverGiven = Faction.AwardSilver(Placer, silverToAward); - - if (silverGiven > 0) + // TODO: Get real message + if (from.Alive) { - // TODO: Get real message - if (from.Alive) - { - 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}"); - } + Placer.SendMessage( + $"You have earned {silverGiven} silver pieces because {from.Name} fell for your trap." + ); } - - 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) + else { - 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(); - - 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) - { - base.OnMovement(m, oldLocation); + from.LocalOverheadMessage(MessageType.Regular, MessageHue, AttackMessage); + } - 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 && - (m.Skills.DetectHidden.Value - 80.0) / 20.0 > Utility.RandomDouble()) + if (item is BaseFactionTrap trap && trap.Faction == Faction) { - 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(); + + 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 (decayPeriod == TimeSpan.MaxValue) + if (Faction.Find(m) != null && + (m.Skills.DetectHidden.Value - 80.0) / 20.0 > Utility.RandomDouble()) { - return false; + PrivateOverheadLocalizedMessage(m, 1010154, MessageHue, "", ""); // [Faction Trap] } + } + } - if (TimeOfPlacement + decayPeriod < Core.Now) - { - Timer.StartTimer(Delete); - return true; - } + public void PrivateOverheadLocalizedMessage(Mobile to, int number, int hue, string name, string args) + { + to?.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, name, args); + } + public virtual bool CheckDecay() + { + var decayPeriod = DecayPeriod; + + if (decayPeriod == TimeSpan.MaxValue) + { return false; } - public virtual void BeginConceal() + if (TimeOfPlacement + decayPeriod < Core.Now) { - _concealingTimerToken.Cancel(); - Timer.StartTimer(ConcealPeriod, Conceal, out _concealingTimerToken); + Timer.StartTimer(Delete); + 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(); - - 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(); - 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; + 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(); + 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; + } +} \ No newline at end of file diff --git a/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrapDeed.cs b/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrapDeed.cs index f0d83b038..2104d2eb3 100644 --- a/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrapDeed.cs +++ b/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrapDeed.cs @@ -2,120 +2,119 @@ using System; using Server.Engines.Craft; 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; - LootType = LootType.Blessed; - } + m_Faction = value; - public BaseFactionTrapDeed(Serial serial) : base(serial) - { - } - - public abstract Type TrapType { get; } - - [CommandProperty(AccessLevel.GameMaster)] - public Faction Faction - { - get => m_Faction; - set + if (m_Faction != null) { - m_Faction = value; - - if (m_Faction != null) - { - Hue = m_Faction.Definition.HuePrimary; - } + Hue = m_Faction.Definition.HuePrimary; } } + } - public int OnCraft( - int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue - ) + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + ItemID = 0x14F0; + Faction = Faction.Find(from); + + return 1; + } + + public virtual BaseFactionTrap Construct(Mobile from) + { + try { - ItemID = 0x14F0; - Faction = Faction.Find(from); - - return 1; + return TrapType.CreateInstance(m_Faction, from); } - - public virtual BaseFactionTrap Construct(Mobile from) + catch { - try - { - return TrapType.CreateInstance(m_Faction, from); - } - catch - { - return null; - } + 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 - } - else if (faction.Traps.Count >= faction.MaximumTraps) - { - from.SendLocalizedMessage(1010358, "", 0x23); // Your faction already has the maximum number of traps placed + from.SendLocalizedMessage(message, "", 0x23); + trap.Delete(); } else { - var trap = Construct(from); - - if (trap == null) - { - 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(); - } + 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); + } +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Factions.BaseSystemController.v1.json b/Projects/UOContent/Migrations/Server.Factions.BaseSystemController.v1.json new file mode 100644 index 000000000..21c20798f --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Factions.BaseSystemController.v1.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "type": "Server.Factions.BaseSystemController", + "properties": [ + { + "name": "LabelNumber", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file