context: using System;
  using System.Collections;
  using Server.Engines.Housing.Regions;
  using Server.Misc;
  using Server.Mobiles;
  using Server.Network;
  using Server.Gumps;
  using Server.Regions;
  using Server.Spells;
  
  namespace Server.Items
  {
  	[DispellableFieldAttribute]
  	public class Moongate : Item
  	{
  		private Point3D m_Target;
  		private Map m_TargetMap;
  		private bool m_bDispellable;
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public Point3D Target
  		{
  			get
  			{
  				return m_Target;
  			}
  			set
  			{
  				m_Target = value;
  			}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public Map TargetMap
  		{
  			get
  			{
  				return m_TargetMap;
  			}
  			set
  			{
  				m_TargetMap = value;
  			}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public bool Dispellable
  		{
  			get
  			{
  				return m_bDispellable;
  			}
  			set
  			{
  				m_bDispellable = value;
  			}
  		}
  
  		public virtual bool ShowFeluccaWarning { get { return false; } }
  		public virtual bool TeleportPets { get { return true; } }
  
  		[Constructable]
  		public Moongate()
  			: this( Point3D.Zero, null )
  		{
  			m_bDispellable = true;
  		}
  
  		[Constructable]
  		public Moongate( bool bDispellable )
  			: this( Point3D.Zero, null )
  		{
  			m_bDispellable = bDispellable;
  		}
  
  		[Constructable]
  		public Moongate( Point3D target, Map targetMap )
  			: base( 0xF6C )
  		{
  			Movable = false;
  			Light = LightType.Circle300;
  
  			m_Target = target;
  			m_TargetMap = targetMap;
  		}
  
  		public Moongate( Serial serial )
  			: base( serial )
  		{
  		}
  
  		public override bool ForceShowProperties { get { return this.Name != null; } }
  
  		public override void OnDoubleClick( Mobile from )
  		{
  			if ( !from.Player )
  				return;
  
  			if ( from.InRange( GetWorldLocation(), 1 ) )
  				CheckGate( from, 1 );
  			else
  				from.SendLocalizedMessage( 500446 ); // That is too far away.
  		}
  
  		public override bool OnMoveOver( Mobile m )
  		{
  			if ( m.Player && Visible )
  				CheckGate( m, 0 );
  
  			return true;
  		}
  
  		public virtual void CheckGate( Mobile m, int range )
  		{
  			new DelayTimer( m, this, range ).Start();
  		}
  
  		public virtual void OnGateUsed( Mobile m )
  		{
  		}
  
  		public virtual void UseGate( Mobile m )
  		{
  			int flags = m.NetState == null ? 0 : m.NetState.Flags;
  			HouseRegion houseRegion = Region.Find( m_Target, m_TargetMap ) as HouseRegion;
  
  			if ( Factions.Sigil.ExistsOn( m ) )
  			{
  				m.SendLocalizedMessage( 1061632 ); // You can't do that while carrying the sigil.
  			}
  			else if ( m_TargetMap == Map.Felucca && m is PlayerMobile && ( (PlayerMobile) m ).Young )
  			{
  				m.SendLocalizedMessage( 1049543 ); // You decide against traveling to Felucca while you are still young.
  			}
  			else if ( ( m.Murderer && m_TargetMap != Map.Felucca ) || ( houseRegion != null && !houseRegion.House.HasAccess( m ) ) )
  			{
  				m.SendLocalizedMessage( 1019004 ); // You are not allowed to travel there.
  			}
  			else if ( m.Spell != null )
  			{
  				m.SendLocalizedMessage( 1049616 ); // You are too busy to do that at the moment.
  			}
  			else if ( m_TargetMap != null && m_TargetMap != Map.Internal )
  			{
  				if ( TeleportPets )
  					BaseCreature.TeleportPets( m, m_Target, m_TargetMap );
  
  				m.MoveToWorld( m_Target, m_TargetMap );
  
  				if ( m.AccessLevel == AccessLevel.Player )
  					m.PlaySound( 0x1FE );
  
  				OnGateUsed( m );
  			}
  			else
  			{
  				m.SendMessage( "This moongate does not seem to go anywhere." );
  			}
  		}
  
  		public override void Serialize( GenericWriter writer )
  		{
  			base.Serialize( writer );
  
  			writer.Write( (int) 1 ); // version
  
  			writer.Write( m_Target );
  			writer.Write( m_TargetMap );
  
  			// Version 1
  			writer.Write( m_bDispellable );
  		}
  
  		public override void Deserialize( GenericReader reader )
  		{
  			base.Deserialize( reader );
  
  			int version = reader.ReadInt();
  
  			m_Target = reader.ReadPoint3D();
  			m_TargetMap = reader.ReadMap();
  
  			if ( version >= 1 )
  				m_bDispellable = reader.ReadBool();
  		}
  
  		public virtual bool ValidateUse( Mobile from, bool message )
  		{
  			if ( from.Deleted || this.Deleted )
  				return false;
  
  			if ( from.Map != this.Map || !from.InRange( this, 1 ) )
  			{
  				if ( message )
  					from.SendLocalizedMessage( 500446 ); // That is too far away.
  
  				return false;
  			}
  
  			return true;
  		}
  
  		public virtual void BeginConfirmation( Mobile from )
  		{
  			if ( IsInTown( from.Location, from.Map ) && !IsInTown( m_Target, m_TargetMap ) || ( from.Map != Map.Felucca && TargetMap == Map.Felucca && ShowFeluccaWarning ) )
  			{
  				from.Send( GenericPackets.PlaySound( 0x20E, from.Location ) );
  				from.CloseGump<MoongateConfirmGump>();
  				from.SendGump( new MoongateConfirmGump( from, this ) );
  			}
  			else
  			{
  				EndConfirmation( from );
  			}
  		}
  
  		public virtual void EndConfirmation( Mobile from )
  		{
  			if ( !ValidateUse( from, true ) )
  				return;
  
  			UseGate( from );
  		}
  
  		public virtual void DelayCallback( Mobile from, int range )
  		{
  			if ( !ValidateUse( from, false ) || !from.InRange( this, range ) )
  				return;
  
  			if ( m_TargetMap != null )
  				BeginConfirmation( from );
  			else
  				from.SendMessage( "This moongate does not seem to go anywhere." );
  		}
  
  		public static bool IsInTown( Point3D p, Map map )
  		{
  			if ( map == null )
  				return false;
  
  			GuardedRegion reg = Region.Find( p, map ) as GuardedRegion;
  
  
gt: 			return ( reg != null && !reg.IsDisabled() );