using System; using System.Collections; using Server; using Server.Targeting; using Server.Mobiles; using Server.Commands; using System.Collections.Generic; namespace Server.Factions { [CustomEnum( new string[]{ "Britain", "Magincia", "Minoc", "Moonglow", "Skara Brae", "Trinsic", "Vesper", "Yew" } )] public abstract class Town : IComparable { private TownDefinition m_Definition; private TownState m_State; public TownDefinition Definition { get{ return m_Definition; } set{ m_Definition = value; } } public TownState State { get{ return m_State; } set{ m_State = value; ConstructGuardLists(); } } public int Silver { get{ return m_State.Silver; } set{ m_State.Silver = value; } } public Faction Owner { get{ return m_State.Owner; } set{ Capture( value ); } } public Mobile Sheriff { get{ return m_State.Sheriff; } set{ m_State.Sheriff = value; } } public Mobile Finance { get{ return m_State.Finance; } set{ m_State.Finance = value; } } public int Tax { get{ return m_State.Tax; } set{ m_State.Tax = value; } } public DateTime LastTaxChange { get{ return m_State.LastTaxChange; } set{ m_State.LastTaxChange = value; } } public static readonly TimeSpan TaxChangePeriod = TimeSpan.FromHours( 12.0 ); public static readonly TimeSpan IncomePeriod = TimeSpan.FromDays( 1.0 ); public bool TaxChangeReady { get{ return ( m_State.LastTaxChange + TaxChangePeriod ) < DateTime.Now; } } 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 int FinanceUpkeep { get { List vendorLists = 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 = 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 + m_State.Tax)) / 100; } } public int NetCashFlow { get{ return DailyIncome - FinanceUpkeep - 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 m_State.LastIncome; } set{ m_State.LastIncome = value; } } public void BeginOrderFiring( Mobile from ) { bool isFinance = IsFinance( from ); bool 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 {0} you wish to dismiss.", type ); from.BeginTarget( 12, false, TargetFlags.None, new TargetCallback( EndOrderFiring ) ); } public void EndOrderFiring( Mobile from, object obj ) { bool isFinance = IsFinance( from ); bool isSheriff = 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 ); } } private Timer m_IncomeTimer; public void StartIncomeTimer() { if ( m_IncomeTimer != null ) m_IncomeTimer.Stop(); m_IncomeTimer = Timer.DelayCall( TimeSpan.FromMinutes( 1.0 ), TimeSpan.FromMinutes( 1.0 ), new TimerCallback( CheckIncome ) ); } public void StopIncomeTimer() { if ( m_IncomeTimer != null ) m_IncomeTimer.Stop(); m_IncomeTimer = null; } public void CheckIncome() { if ( (LastIncome + IncomePeriod) > DateTime.Now || Owner == null ) return; ProcessIncome(); } public void ProcessIncome() { LastIncome = DateTime.Now; int flow = NetCashFlow; if ( (Silver + flow) < 0 ) { ArrayList toDelete = BuildFinanceList(); while ( (Silver + flow) < 0 && toDelete.Count > 0 ) { int index = Utility.Random( toDelete.Count ); Mobile mob = (Mobile)toDelete[index]; mob.Delete(); toDelete.RemoveAt( index ); flow = NetCashFlow; } } Silver += flow; } public ArrayList BuildFinanceList() { ArrayList list = new ArrayList(); List vendorLists = VendorLists; for ( int i = 0; i < vendorLists.Count; ++i ) list.AddRange( vendorLists[i].Vendors ); List guardLists = GuardLists; for ( int i = 0; i < guardLists.Count; ++i ) list.AddRange( guardLists[i].Guards ); return list; } private List m_VendorLists; private List m_GuardLists; public List VendorLists { get{ return m_VendorLists; } set{ m_VendorLists = value; } } public List GuardLists { get{ return m_GuardLists; } set{ m_GuardLists = value; } } public void ConstructGuardLists() { GuardDefinition[] defs = ( Owner == null ? new GuardDefinition[0] : Owner.Definition.Guards ); m_GuardLists = new List(); for ( int i = 0; i < defs.Length; ++i ) m_GuardLists.Add( new GuardList( defs[i] ) ); } public GuardList FindGuardList( Type type ) { List guardLists = 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; m_VendorLists = new List(); for ( int i = 0; i < defs.Length; ++i ) m_VendorLists.Add( new VendorList( defs[i] ) ); } public VendorList FindVendorList( Type type ) { List vendorLists = 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 = 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 = 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 = 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 = FindVendorList( vendor.GetType() ); if ( vendorList == null ) return false; if ( !vendorList.Vendors.Contains( vendor ) ) return false; vendorList.Vendors.Remove( vendor ); return true; } 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 Town() { m_State = new TownState( this ); ConstructVendorLists(); ConstructGuardLists(); StartIncomeTimer(); } public bool IsSheriff( Mobile mob ) { if ( mob == null || mob.Deleted ) return false; return ( mob.AccessLevel >= AccessLevel.GameMaster || mob == Sheriff ); } public bool IsFinance( Mobile mob ) { if ( mob == null || mob.Deleted ) return false; return ( mob.AccessLevel >= AccessLevel.GameMaster || mob == Finance ); } public static List Towns { get { return Reflector.Towns; } } public const int SilverCaptureBonus = 10000; public void Capture( Faction f ) { if ( m_State.Owner == f ) return; if ( m_State.Owner == null ) // going from unowned to owned { LastIncome = DateTime.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; TownMonolith monolith = this.Monolith; if ( monolith != null ) monolith.Faction = f; List vendorLists = 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 = 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(); } ConstructGuardLists(); } public int CompareTo( object obj ) { return m_Definition.Sort - ((Town)obj).m_Definition.Sort; } public override string ToString() { return m_Definition.FriendlyName; } 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 ); } } } }