using System; using System.Collections; using System.Collections.Generic; using Server.Commands; using Server.Targeting; namespace Server.Factions { [CustomEnum(new string[] { "Britain", "Magincia", "Minoc", "Moonglow", "Skara Brae", "Trinsic", "Vesper", "Yew" })] public abstract class Town : IComparable { public static readonly TimeSpan TaxChangePeriod = TimeSpan.FromHours(12.0); public static readonly TimeSpan IncomePeriod = TimeSpan.FromDays(1.0); public const int SilverCaptureBonus = 10000; private TownDefinition m_Definition; private TownState m_State; private Timer m_IncomeTimer; private List m_VendorLists; private List m_GuardLists; public Town() { this.m_State = new TownState(this); this.ConstructVendorLists(); this.ConstructGuardLists(); this.StartIncomeTimer(); } public static List Towns { get { return Reflector.Towns; } } public TownDefinition Definition { get { return this.m_Definition; } set { this.m_Definition = value; } } public TownState State { get { return this.m_State; } set { this.m_State = value; this.ConstructGuardLists(); } } public int Silver { get { return this.m_State.Silver; } set { this.m_State.Silver = value; } } public Faction Owner { get { return this.m_State.Owner; } set { this.Capture(value); } } public Mobile Sheriff { get { return this.m_State.Sheriff; } set { this.m_State.Sheriff = value; } } public Mobile Finance { get { return this.m_State.Finance; } set { this.m_State.Finance = value; } } public int Tax { get { return this.m_State.Tax; } set { this.m_State.Tax = value; } } public DateTime LastTaxChange { get { return this.m_State.LastTaxChange; } set { this.m_State.LastTaxChange = value; } } public bool TaxChangeReady { get { return (this.m_State.LastTaxChange + TaxChangePeriod) < DateTime.UtcNow; } } public int FinanceUpkeep { get { List vendorLists = this.VendorLists; int upkeep = 0; for (int i = 0; i < vendorLists.Count; ++i) upkeep += vendorLists[i].Vendors.Count * vendorLists[i].Definition.Upkeep; return upkeep; } } public int SheriffUpkeep { get { List guardLists = this.GuardLists; int upkeep = 0; for (int i = 0; i < guardLists.Count; ++i) upkeep += guardLists[i].Guards.Count * guardLists[i].Definition.Upkeep; return upkeep; } } public int DailyIncome { get { return (10000 * (100 + this.m_State.Tax)) / 100; } } public int NetCashFlow { get { return this.DailyIncome - this.FinanceUpkeep - this.SheriffUpkeep; } } public TownMonolith Monolith { get { List monoliths = BaseMonolith.Monoliths; foreach (BaseMonolith monolith in monoliths) { if (monolith is TownMonolith) { TownMonolith townMonolith = (TownMonolith)monolith; if (townMonolith.Town == this) return townMonolith; } } return null; } } public DateTime LastIncome { get { return this.m_State.LastIncome; } set { this.m_State.LastIncome = value; } } public List VendorLists { get { return this.m_VendorLists; } set { this.m_VendorLists = value; } } public List GuardLists { get { return this.m_GuardLists; } set { this.m_GuardLists = value; } } public static Town FromRegion(Region reg) { if (reg.Map != Faction.Facet) return null; List towns = Towns; for (int i = 0; i < towns.Count; ++i) { Town town = towns[i]; if (reg.IsPartOf(town.Definition.Region)) return town; } return null; } public static void Initialize() { List towns = Towns; for (int i = 0; i < towns.Count; ++i) { towns[i].Sheriff = towns[i].Sheriff; towns[i].Finance = towns[i].Finance; } CommandSystem.Register("GrantTownSilver", AccessLevel.Administrator, new CommandEventHandler(GrantTownSilver_OnCommand)); } public static void WriteReference(GenericWriter writer, Town town) { int idx = Towns.IndexOf(town); writer.WriteEncodedInt((int)(idx + 1)); } public static Town ReadReference(GenericReader reader) { int idx = reader.ReadEncodedInt() - 1; if (idx >= 0 && idx < Towns.Count) return Towns[idx]; return null; } public static Town Parse(string name) { List towns = Towns; for (int i = 0; i < towns.Count; ++i) { Town town = towns[i]; if (Insensitive.Equals(town.Definition.FriendlyName, name)) return town; } return null; } public static void GrantTownSilver_OnCommand(CommandEventArgs e) { Town 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 {0:N0} silver to the town. It now has {1:N0} silver.", e.GetInt32(0), town.Silver); } } public void BeginOrderFiring(Mobile from) { bool isFinance = this.IsFinance(from); bool isSheriff = this.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 {0} you wish to dismiss.", type); from.BeginTarget(12, false, TargetFlags.None, new TargetCallback(EndOrderFiring)); } public void EndOrderFiring(Mobile from, object obj) { bool isFinance = this.IsFinance(from); bool isSheriff = this.IsSheriff(from); string type = null; if (isFinance && isSheriff) // GM only type = "vendor or guard"; else if (isFinance) type = "vendor"; else if (isSheriff) type = "guard"; if (obj is BaseFactionVendor) { BaseFactionVendor vendor = (BaseFactionVendor)obj; if (vendor.Town == this && isFinance) vendor.Delete(); } else if (obj is BaseFactionGuard) { BaseFactionGuard guard = (BaseFactionGuard)obj; if (guard.Town == this && isSheriff) guard.Delete(); } else { from.SendMessage("That is not a {0}!", type); } } public void StartIncomeTimer() { if (this.m_IncomeTimer != null) this.m_IncomeTimer.Stop(); this.m_IncomeTimer = Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), new TimerCallback(CheckIncome)); } public void StopIncomeTimer() { if (this.m_IncomeTimer != null) this.m_IncomeTimer.Stop(); this.m_IncomeTimer = null; } public void CheckIncome() { if ((this.LastIncome + IncomePeriod) > DateTime.UtcNow || this.Owner == null) return; this.ProcessIncome(); } public void ProcessIncome() { this.LastIncome = DateTime.UtcNow; int flow = this.NetCashFlow; if ((this.Silver + flow) < 0) { ArrayList toDelete = this.BuildFinanceList(); while ((this.Silver + flow) < 0 && toDelete.Count > 0) { int index = Utility.Random(toDelete.Count); Mobile mob = (Mobile)toDelete[index]; mob.Delete(); toDelete.RemoveAt(index); flow = this.NetCashFlow; } } this.Silver += flow; } public ArrayList BuildFinanceList() { ArrayList list = new ArrayList(); List vendorLists = this.VendorLists; for (int i = 0; i < vendorLists.Count; ++i) list.AddRange(vendorLists[i].Vendors); List guardLists = this.GuardLists; for (int i = 0; i < guardLists.Count; ++i) list.AddRange(guardLists[i].Guards); return list; } public void ConstructGuardLists() { GuardDefinition[] defs = (this.Owner == null ? new GuardDefinition[0] : this.Owner.Definition.Guards); this.m_GuardLists = new List(); for (int i = 0; i < defs.Length; ++i) this.m_GuardLists.Add(new GuardList(defs[i])); } public GuardList FindGuardList(Type type) { List guardLists = this.GuardLists; for (int i = 0; i < guardLists.Count; ++i) { GuardList guardList = guardLists[i]; if (guardList.Definition.Type == type) return guardList; } return null; } public void ConstructVendorLists() { VendorDefinition[] defs = VendorDefinition.Definitions; this.m_VendorLists = new List(); for (int i = 0; i < defs.Length; ++i) this.m_VendorLists.Add(new VendorList(defs[i])); } public VendorList FindVendorList(Type type) { List vendorLists = this.VendorLists; for (int i = 0; i < vendorLists.Count; ++i) { VendorList vendorList = vendorLists[i]; if (vendorList.Definition.Type == type) return vendorList; } return null; } public bool RegisterGuard(BaseFactionGuard guard) { if (guard == null) return false; GuardList guardList = this.FindGuardList(guard.GetType()); if (guardList == null) return false; guardList.Guards.Add(guard); return true; } public bool UnregisterGuard(BaseFactionGuard guard) { if (guard == null) return false; GuardList guardList = this.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; VendorList vendorList = this.FindVendorList(vendor.GetType()); if (vendorList == null) return false; vendorList.Vendors.Add(vendor); return true; } public bool UnregisterVendor(BaseFactionVendor vendor) { if (vendor == null) return false; VendorList vendorList = this.FindVendorList(vendor.GetType()); if (vendorList == null) return false; if (!vendorList.Vendors.Contains(vendor)) return false; vendorList.Vendors.Remove(vendor); return true; } public bool IsSheriff(Mobile mob) { if (mob == null || mob.Deleted) return false; return (mob.AccessLevel >= AccessLevel.GameMaster || mob == this.Sheriff); } public bool IsFinance(Mobile mob) { if (mob == null || mob.Deleted) return false; return (mob.AccessLevel >= AccessLevel.GameMaster || mob == this.Finance); } public void Capture(Faction f) { if (this.m_State.Owner == f) return; if (this.m_State.Owner == null) // going from unowned to owned { this.LastIncome = DateTime.UtcNow; f.Silver += SilverCaptureBonus; } else if (f == null) // going from owned to unowned { this.LastIncome = DateTime.MinValue; } else // otherwise changing hands, income timer doesn't change { f.Silver += SilverCaptureBonus; } this.m_State.Owner = f; this.Sheriff = null; this.Finance = null; TownMonolith monolith = this.Monolith; if (monolith != null) monolith.Faction = f; List vendorLists = this.VendorLists; for (int i = 0; i < vendorLists.Count; ++i) { VendorList vendorList = vendorLists[i]; List vendors = vendorList.Vendors; for (int j = vendors.Count - 1; j >= 0; --j) vendors[j].Delete(); } List guardLists = this.GuardLists; for (int i = 0; i < guardLists.Count; ++i) { GuardList guardList = guardLists[i]; List guards = guardList.Guards; for (int j = guards.Count - 1; j >= 0; --j) guards[j].Delete(); } this.ConstructGuardLists(); } public int CompareTo(object obj) { return this.m_Definition.Sort - ((Town)obj).m_Definition.Sort; } public override string ToString() { return this.m_Definition.FriendlyName; } } }