context: using System;
  using System.Collections.Generic;
  using Server;
  using Server.Items;
  using Server.Gumps;
  using Server.Prompts;
  using Server.Network;
  using Server.ContextMenus;
  using Server.Multis;
  
  namespace Server.Mobiles
  {
  
  	public class AnimalTrainerRumor
  	{
  		private string m_Message;
  		private string m_Keyword;
  
  		public string Message{ get{ return m_Message; } set{ m_Message = value; } }
  		public string Keyword{ get{ return m_Keyword; } set{ m_Keyword = value; } }
  
  		public AnimalTrainerRumor( string message, string keyword )
  		{
  			m_Message = message;
  			m_Keyword = keyword;
  		}
  
  		public static AnimalTrainerRumor Deserialize( GenericReader reader )
  		{
  			if ( !reader.ReadBool() )
  				return null;
  
  			return new AnimalTrainerRumor( reader.ReadString(), reader.ReadString() );
  		}
  
  		public static void Serialize( GenericWriter writer, AnimalTrainerRumor rumor )
  		{
  			if ( rumor == null )
  			{
  				writer.Write( false );
  			}
  			else
  			{
  				writer.Write( true );
  				writer.Write( rumor.m_Message );
  				writer.Write( rumor.m_Keyword );
  			}
  		}
  	}
  
  	public class ManageAnimalTrainerEntry : ContextMenuEntry
  	{
  		private Mobile m_From;
  		private PlayerAnimalTrainer m_AnimalTrainer;
  
  		public ManageAnimalTrainerEntry( Mobile from, PlayerAnimalTrainer trainer ) : base( 6151, 12 )
  		{
  			m_From = from;
  			m_AnimalTrainer = trainer;
  		}
  
  		public override void OnClick()
  		{
  			m_AnimalTrainer.BeginManagement( m_From );
  		}
  	}
  
  	public class PlayerAnimalTrainer : AnimalTrainer
  	{
  		private Mobile m_Owner;
  		private BaseHouse m_House;
  		private string m_TipMessage;
  
  		private AnimalTrainerRumor[] m_Rumors;
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public Mobile Owner
  		{
  			get{ return m_Owner; }
  			set{ m_Owner = value; }
  		}
  
  		public BaseHouse House
  		{
  			get{ return m_House; }
  			set
  			{
  				if ( m_House != null )
  					m_House.PlayerBarkeepers.Remove( this );
  
  				if ( value != null )
  					value.PlayerBarkeepers.Add( this );
  
  				m_House = value;
  			}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public string TipMessage
  		{
  			get{ return m_TipMessage; }
  			set{ m_TipMessage = value; }
  		}
  
  		public override bool IsActiveBuyer{ get{ return false; } }
  		public override bool IsActiveSeller{ get{ return ( m_SBInfos.Count > 0 ); } }
  
  		public override bool DisallowAllMoves{ get{ return true; } }
  		public override bool NoHouseRestrictions{ get{ return true; } }
  
  		public AnimalTrainerRumor[] Rumors{ get{ return m_Rumors; } }
  
  		public override VendorShoeType ShoeType{ get{ return Utility.RandomBool() ? VendorShoeType.ThighBoots : VendorShoeType.Boots; } }
  
  		public override bool GetGender()
  		{
  			return false; // always starts as male
  		}
  
  		public override void InitOutfit()
  		{
  			base.InitOutfit();
  
  			AddItem( new HalfApron( Utility.RandomBrightHue() ) );
  
  			Container pack = this.Backpack;
  
  			if ( pack != null )
  				pack.Delete();
  		}
  
  		public override void InitBody()
  		{
  			base.InitBody();
  
  			if ( BodyValue == 0x340 || BodyValue == 0x402 )
  				Hue = 0;
  			else
  				Hue = 0x83F4; // hue is not random
  
  			Container pack = this.Backpack;
  
  			if ( pack != null )
  				pack.Delete();
  		}
  
  		public PlayerAnimalTrainer( Mobile owner, BaseHouse house ) : base()
  		{
  			m_Owner = owner;
  			House = house;
  			m_Rumors = new AnimalTrainerRumor[3];
  
  			LoadSBInfo();
  		}
  
  		public override bool HandlesOnSpeech(Mobile from)
  		{
  			if ( InRange( from, 3 ) )
  				return true;
  
  			return base.HandlesOnSpeech (from);
  		}
  
  		private Timer m_NewsTimer;
  
  		private void ShoutNews_Callback( object state )
  		{
  			object[] states = (object[])state;
  			TownCrierEntry tce = (TownCrierEntry)states[0];
  			int index = (int)states[1];
  
  			if ( index < 0 || index >= tce.Lines.Length )
  			{
  				if ( m_NewsTimer != null )
  					m_NewsTimer.Stop();
  
  				m_NewsTimer = null;
  			}
  			else
  			{
  				PublicOverheadMessage( MessageType.Regular, 0x3B2, false, tce.Lines[index] );
  				states[1] = index + 1;
  			}
  		}
  
  		public override void OnAfterDelete()
  		{
  			base.OnAfterDelete();
  
  			House = null;
  		}
  
  		public override bool OnBeforeDeath()
  		{
  			if ( !base.OnBeforeDeath() )
  				return false;
  
  			Item shoes = this.FindItemOnLayer( Layer.Shoes );
  
  			if ( shoes is Sandals )
  				shoes.Hue = 0;
  
  			return true;
  		}
  
  		public override void OnSpeech( SpeechEventArgs e )
  		{
  			base.OnSpeech( e );
  
  			if ( !e.Handled && InRange( e.Mobile, 3 ) )
  			{
  				if ( m_NewsTimer == null && e.HasKeyword( 0x30 ) ) // *news*
  				{
  					TownCrierEntry tce = GlobalTownCrierEntryList.Instance.GetRandomEntry();
  
  					if ( tce == null )
  					{
  						PublicOverheadMessage( MessageType.Regular, 0x3B2, 1005643 ); // I have no news at this time.
  					}
  					else
  					{
  						m_NewsTimer = Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 3.0 ), new TimerStateCallback( ShoutNews_Callback ), new object[]{ tce, 0 } );
  
  						PublicOverheadMessage( MessageType.Regular, 0x3B2, 502978 ); // Some of the latest news!
  					}
  				}
  
  				for ( int i = 0; i < m_Rumors.Length; ++i )
  				{
  					AnimalTrainerRumor rumor = m_Rumors[i];
  
  					if ( rumor == null )
  						continue;
  
  					string keyword = rumor.Keyword;
  
  					if ( keyword == null || (keyword = keyword.Trim()).Length == 0 )
  						continue;
  
  					if ( Insensitive.Equals( keyword, e.Speech ) )
  					{
  						string message = rumor.Message;
  
  						if ( message == null || (message = message.Trim()).Length == 0 )
  							continue;
  
  						PublicOverheadMessage( MessageType.Regular, 0x3B2, false, message );
  					}
  				}
  			}
  		}
  
  		public override bool CheckGold( Mobile from, Item dropped )
  		{
  			if ( dropped is Gold )
  			{
  				Gold g = (Gold)dropped;
  
  				if ( g.Amount > 50 )
  				{
  					PrivateOverheadMessage( MessageType.Regular, 0x3B2, false, "I cannot accept so large a tip!", from.NetState );
  				}
  				else
  				{
  					string tip = m_TipMessage;
  
  					if ( tip == null || (tip = tip.Trim()).Length == 0 )
  					{
  						PrivateOverheadMessage( MessageType.Regular, 0x3B2, false, "It would not be fair of me to take your money and not offer you information in return.", from.NetState );
  					}
  					else
  					{
  						Direction = GetDirectionTo( from );
  						PrivateOverheadMessage( MessageType.Regular, 0x3B2, false, tip, from.NetState );
  
  						g.Delete();
  						return true;
  					}
  				}
  			}
  
  			return false;
  		}
  
  		public bool IsOwner( Mobile from )
  		{
  			if ( from == null || from.Deleted || this.Deleted )
  				return false;
  
  			if ( from.AccessLevel > AccessLevel.GameMaster )
  				return true;
  
  			return ( m_Owner == from );
  		}
  
  		public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
  		{
  			base.GetContextMenuEntries( from, list );
  
  			if ( IsOwner( from ) && from.InLOS( this ) )
  				list.Add( new ManageAnimalTrainerEntry( from, this ) );
  		}
  
  		public void BeginManagement( Mobile from )
  		{
  			if ( !IsOwner( from ) )
  				return;
  
  			from.SendGump( new AnimalTrainerGump( from, this ) );
  		}
  
  		public void Dismiss()
  		{
  			Delete();
  		}
  
  		public void BeginChangeTitle( Mobile from )
  		{
  			from.SendGump( new AnimalTrainerTitleGump( from, this ) );
  		}
  
  		public void EndChangeTitle( Mobile from, string title, bool vendor )
  		{
  			this.Title = title;
  
  			LoadSBInfo();
  		}
  
  		public void CancelChangeTitle( Mobile from )
  		{
  			from.SendGump( new AnimalTrainerGump( from, this ) );
  		}
  
  		public void BeginChangeAppearance( Mobile from )
  		{
  			from.CloseGump( typeof( PlayerVendorCustomizeGump ) );
  			from.SendGump( new PlayerVendorCustomizeGump( this, from ) );
  		}
  
  		public void ChangeGender( Mobile from )
  		{
  			Female = !Female;
  
  			if ( Female )
  			{
  				Body = 401;
  				Name = NameList.RandomName( "female" );
  
  				FacialHairItemID = 0;
  			}
  			else
  			{
  				Body = 400;
  				Name = NameList.RandomName( "male" );
  			}
  		}
  
  		private List<SBInfo> m_SBInfos = new List<SBInfo>(); 
  		protected override List<SBInfo> SBInfos{ get { return m_SBInfos; } } 
  
  		public override void InitSBInfo()
  		{
  			if ( Title == "the animal trainer" || Title == "the trainer" )
  			{
  				if ( m_SBInfos.Count == 0 )
  					m_SBInfos.Add( new SBAnimalTrainer() );
  			}
  			else
  			{
  				m_SBInfos.Clear();
  			}
  		}
  
  		public PlayerAnimalTrainer( Serial serial ) : base( serial )
  		{
  		}
  
  		public override void Serialize( GenericWriter writer )
  		{
  			base.Serialize( writer );
  
  			writer.Write( (int) 1 ); // version;
  
  			writer.Write( (Item) m_House );
  
  			writer.Write( (Mobile) m_Owner );
  
  			writer.WriteEncodedInt( (int) m_Rumors.Length );
  
  			for ( int i = 0; i < m_Rumors.Length; ++i )
  				AnimalTrainerRumor.Serialize( writer, m_Rumors[i] );
  
  			writer.Write( (string) m_TipMessage );
  		}
  
  		public override void Deserialize( GenericReader reader )
  		{
  			base.Deserialize( reader );
  
  
gt: 			int version = reader.ReadInt();