Convert movement, actions (lift/use), combat, and spells to use Core.TickCount and avoid DateTime caveats (performance, system time dependency, etc) Refactor DateTime.Now to DateTime.UtcNow Add LOS check for Iron Maiden addon
554 lines
No EOL
12 KiB
C#
554 lines
No EOL
12 KiB
C#
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.UtcNow; }
|
|
}
|
|
|
|
public static Town FromRegion( Region reg )
|
|
{
|
|
if ( reg.Map != Faction.Facet )
|
|
return null;
|
|
|
|
List<Town> 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<VendorList> 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<GuardList> 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<BaseMonolith> 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.UtcNow || Owner == null )
|
|
return;
|
|
|
|
ProcessIncome();
|
|
}
|
|
|
|
public void ProcessIncome()
|
|
{
|
|
LastIncome = DateTime.UtcNow;
|
|
|
|
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<VendorList> vendorLists = VendorLists;
|
|
|
|
for ( int i = 0; i < vendorLists.Count; ++i )
|
|
list.AddRange( vendorLists[i].Vendors );
|
|
|
|
List<GuardList> guardLists = GuardLists;
|
|
|
|
for ( int i = 0; i < guardLists.Count; ++i )
|
|
list.AddRange( guardLists[i].Guards );
|
|
|
|
return list;
|
|
}
|
|
|
|
private List<VendorList> m_VendorLists;
|
|
private List<GuardList> m_GuardLists;
|
|
|
|
public List<VendorList> VendorLists
|
|
{
|
|
get{ return m_VendorLists; }
|
|
set{ m_VendorLists = value; }
|
|
}
|
|
|
|
public List<GuardList> 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<GuardList>();
|
|
|
|
for ( int i = 0; i < defs.Length; ++i )
|
|
m_GuardLists.Add( new GuardList( defs[i] ) );
|
|
}
|
|
|
|
public GuardList FindGuardList( Type type )
|
|
{
|
|
List<GuardList> 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<VendorList>();
|
|
|
|
for ( int i = 0; i < defs.Length; ++i )
|
|
m_VendorLists.Add( new VendorList( defs[i] ) );
|
|
}
|
|
|
|
public VendorList FindVendorList( Type type )
|
|
{
|
|
List<VendorList> 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<Town> 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<Town> 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.UtcNow;
|
|
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<VendorList> vendorLists = VendorLists;
|
|
|
|
for ( int i = 0; i < vendorLists.Count; ++i )
|
|
{
|
|
VendorList vendorList = vendorLists[i];
|
|
List<BaseFactionVendor> vendors = vendorList.Vendors;
|
|
|
|
for ( int j = vendors.Count - 1; j >= 0; --j )
|
|
vendors[j].Delete();
|
|
}
|
|
|
|
List<GuardList> guardLists = GuardLists;
|
|
|
|
for ( int i = 0; i < guardLists.Count; ++i )
|
|
{
|
|
GuardList guardList = guardLists[i];
|
|
List<BaseFactionGuard> 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<Town> 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 <amount>" );
|
|
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 );
|
|
}
|
|
}
|
|
}
|
|
} |