context: using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Xml;
  using Server;
  using Server.Commands;
  using Server.Mobiles;
  using Server.Spells;
  using Server.Events;
  
  namespace Server.Regions
  {
  	public class GuardedRegion : BaseRegion
  	{
  		private static object[] m_GuardParams = new object[1];
  		private Type m_GuardType;
  		private bool m_Disabled;
  
  		public bool Disabled { get { return m_Disabled; } set { m_Disabled = value; } }
  
  		public virtual bool IsDisabled()
  		{
  			return m_Disabled;
  		}
  
  		public static void Initialize()
  		{
  			CommandSystem.Register( "CheckGuarded", AccessLevel.GameMaster, new CommandEventHandler( CheckGuarded_OnCommand ) );
  			CommandSystem.Register( "SetGuarded", AccessLevel.Administrator, new CommandEventHandler( SetGuarded_OnCommand ) );
  			CommandSystem.Register( "ToggleGuarded", AccessLevel.Administrator, new CommandEventHandler( ToggleGuarded_OnCommand ) );
  		}
  
  		[Usage( "CheckGuarded" )]
  		[Description( "Returns a value indicating if the current region is guarded or not." )]
  		private static void CheckGuarded_OnCommand( CommandEventArgs e )
  		{
  			Mobile from = e.Mobile;
  			GuardedRegion reg = (GuardedRegion) from.Region.GetRegion( typeof( GuardedRegion ) );
  
  			if ( reg == null )
  				from.SendMessage( "You are not in a guardable region." );
  			else if ( reg.Disabled )
  				from.SendMessage( "The guards in this region have been disabled." );
  			else
  				from.SendMessage( "This region is actively guarded." );
  		}
  
  		[Usage( "SetGuarded <true|false>" )]
  		[Description( "Enables or disables guards for the current region." )]
  		private static void SetGuarded_OnCommand( CommandEventArgs e )
  		{
  			Mobile from = e.Mobile;
  
  			if ( e.Length == 1 )
  			{
  				GuardedRegion reg = (GuardedRegion) from.Region.GetRegion( typeof( GuardedRegion ) );
  
  				if ( reg == null )
  				{
  					from.SendMessage( "You are not in a guardable region." );
  				}
  				else
  				{
  					reg.Disabled = !e.GetBoolean( 0 );
  
  					if ( reg.Disabled )
  						from.SendMessage( "The guards in this region have been disabled." );
  					else
  						from.SendMessage( "The guards in this region have been enabled." );
  				}
  			}
  			else
  			{
  				from.SendMessage( "Format: SetGuarded <true|false>" );
  			}
  		}
  
  		[Usage( "ToggleGuarded" )]
  		[Description( "Toggles the state of guards for the current region." )]
  		private static void ToggleGuarded_OnCommand( CommandEventArgs e )
  		{
  			Mobile from = e.Mobile;
  			GuardedRegion reg = (GuardedRegion) from.Region.GetRegion( typeof( GuardedRegion ) );
  
  			if ( reg == null )
  			{
  				from.SendMessage( "You are not in a guardable region." );
  			}
  			else
  			{
  				reg.Disabled = !reg.Disabled;
  
  				if ( reg.Disabled )
  					from.SendMessage( "The guards in this region have been disabled." );
  				else
  					from.SendMessage( "The guards in this region have been enabled." );
  			}
  		}
  
  		public static GuardedRegion Disable( GuardedRegion reg )
  		{
  			reg.Disabled = true;
  			return reg;
  		}
  
  		public virtual bool AllowReds { get { return true; } }
  
  		public virtual bool CheckVendorAccess( BaseVendor vendor, Mobile from )
  		{
  			if ( from.AccessLevel >= AccessLevel.GameMaster || IsDisabled() )
  				return true;
  
  			return ( from.Kills < 5 );
  		}
  
  		public virtual Type DefaultGuardType
  		{
  			get
  			{
  				if ( this.Map == Map.Ilshenar || this.Map == Map.Malas )
  					return typeof( ArcherGuard );
  				else
  					return typeof( WarriorGuard );
  			}
  		}
  
  		public GuardedRegion( string name, Map map, int priority, params Rectangle3D[] area )
  			: base( name, map, priority, area )
  		{
  			m_GuardType = DefaultGuardType;
  		}
  
  		public GuardedRegion( string name, Map map, int priority, params Rectangle2D[] area )
  			: base( name, map, priority, area )
  		{
  			m_GuardType = DefaultGuardType;
  		}
  
  		public GuardedRegion( XmlElement xml, Map map, Region parent )
  			: base( xml, map, parent )
  		{
  			XmlElement el = xml["guards"];
  
  			if ( ReadType( el, "type", ref m_GuardType, false ) )
  			{
  				if ( !typeof( Mobile ).IsAssignableFrom( m_GuardType ) )
  				{
  					Console.WriteLine( "Invalid guard type for region '{0}'", this );
  					m_GuardType = DefaultGuardType;
  				}
  			}
  			else
  			{
  				m_GuardType = DefaultGuardType;
  			}
  
  			bool disabled = false;
  			if ( ReadBoolean( el, "disabled", ref disabled, false ) )
  				this.Disabled = disabled;
  		}
  
  		public override bool OnBeginSpellCast( Mobile m, ISpell s )
  		{
  			if ( !IsDisabled() && !s.OnCastInTown( this ) )
  			{
  				m.SendLocalizedMessage( 500946 ); // You cannot cast this in town!
  				return false;
  			}
  
  			return base.OnBeginSpellCast( m, s );
  		}
  
  		public override bool AllowHousing( Mobile from, Point3D p )
  		{
  			return false;
  		}
  
  		public override void MakeGuard( Mobile focus )
  		{
  			BaseGuard useGuard = null;
  
  			foreach ( Mobile m in focus.GetMobilesInRange( 8 ) )
  			{
  				if ( m is BaseGuard )
  				{
  					BaseGuard g = (BaseGuard) m;
  
  					if ( g.Focus == null ) // idling
  					{
  						useGuard = g;
  						break;
  					}
  				}
  			}
  
  			if ( useGuard == null )
  			{
  				m_GuardParams[0] = focus;
  
  				try { Activator.CreateInstance( m_GuardType, m_GuardParams ); }
  				catch { }
  			}
  			else
  				useGuard.Focus = focus;
  		}
  
  		public override void OnEnter( Mobile m )
  		{
  			if ( IsDisabled() )
  				return;
  
  			if ( !AllowReds && m.Murderer )
  				CheckGuardCandidate( m );
  		}
  
  		public override void OnExit( Mobile m )
  		{
  			if ( IsDisabled() )
  				return;
  		}
  
  		public override void OnSpeech( SpeechEventArgs args )
  		{
  			base.OnSpeech( args );
  
  			if ( IsDisabled() )
  				return;
  
  			if ( args.Mobile.Alive && args.HasKeyword( 0x0007 ) ) // *guards*
  				CallGuards( args.Mobile.Location );
  		}
  
  		public override void OnAggressed( Mobile aggressor, Mobile aggressed, bool criminal )
  		{
  			base.OnAggressed( aggressor, aggressed, criminal );
  
  			if ( !IsDisabled() && aggressor != aggressed && criminal )
  				CheckGuardCandidate( aggressor );
  		}
  
  		public override void OnGotBeneficialAction( Mobile helper, Mobile helped )
  		{
  			base.OnGotBeneficialAction( helper, helped );
  
  			if ( IsDisabled() )
  				return;
  
  			int noto = Notoriety.Compute( helper, helped );
  
  			if ( helper != helped && ( noto == Notoriety.Criminal || noto == Notoriety.Murderer ) )
  				CheckGuardCandidate( helper );
  		}
  
  		public override void OnCriminalAction( Mobile m, bool message )
  		{
  			base.OnCriminalAction( m, message );
  
  			if ( !IsDisabled() )
  				CheckGuardCandidate( m );
  		}
  
  		private Dictionary<Mobile, GuardTimer> m_GuardCandidates = new Dictionary<Mobile, GuardTimer>();
  
  		public void CheckGuardCandidate( Mobile m )
  		{
  			if ( IsDisabled() )
  				return;
  
  			if ( IsGuardCandidate( m ) )
  			{
  				GuardTimer timer = null;
  				m_GuardCandidates.TryGetValue( m, out timer );
  
  				if ( timer == null )
  				{
  
gt: 					timer = new GuardTimer( m, m_GuardCandidates );