context: #region Header
  // **********
  // ServUO - Skills.cs
  // **********
  #endregion
  
  #region References
  using System;
  using System.Collections;
  
  using Server.Network;
  #endregion
  
  namespace Server
  {
  	public delegate TimeSpan SkillUseCallback(Mobile user);
  
  	public enum SkillLock : byte
  	{
  		Up = 0,
  		Down = 1,
  		Locked = 2
  	}
  
  	public enum SkillName
  	{
  		Alchemy = 0,
  		Anatomy = 1,
  		AnimalLore = 2,
  		ItemID = 3,
  		ArmsLore = 4,
  		Parry = 5,
  		Begging = 6,
  		Blacksmith = 7,
  		Fletching = 8,
  		Peacemaking = 9,
  		Camping = 10,
  		Carpentry = 11,
  		Cartography = 12,
  		Cooking = 13,
  		DetectHidden = 14,
  		Discordance = 15,
  		EvalInt = 16,
  		Healing = 17,
  		Fishing = 18,
  		Forensics = 19,
  		Herding = 20,
  		Hiding = 21,
  		Provocation = 22,
  		Inscribe = 23,
  		Lockpicking = 24,
  		Magery = 25,
  		MagicResist = 26,
  		Tactics = 27,
  		Snooping = 28,
  		Musicianship = 29,
  		Poisoning = 30,
  		Archery = 31,
  		SpiritSpeak = 32,
  		Stealing = 33,
  		Tailoring = 34,
  		AnimalTaming = 35,
  		TasteID = 36,
  		Tinkering = 37,
  		Tracking = 38,
  		Veterinary = 39,
  		Swords = 40,
  		Macing = 41,
  		Fencing = 42,
  		Wrestling = 43,
  		Lumberjacking = 44,
  		Mining = 45,
  		Meditation = 46,
  		Stealth = 47,
  		RemoveTrap = 48,
  		Necromancy = 49,
  		Focus = 50,
  		Chivalry = 51,
  		Bushido = 52,
  		Ninjitsu = 53,
  		Spellweaving = 54,
  		Mysticism = 55,
  		Imbuing = 56,
  		Throwing = 57
  	}
  
  	[PropertyObject]
  	public class Skill
  	{
  		private readonly Skills m_Owner;
  		private readonly SkillInfo m_Info;
  		private ushort m_Base;
  		private ushort m_Cap;
  		private SkillLock m_Lock;
  
  		public override string ToString()
  		{
  			return String.Format("[{0}: {1}]", Name, Base);
  		}
  
  		public Skill(Skills owner, SkillInfo info, GenericReader reader)
  		{
  			m_Owner = owner;
  			m_Info = info;
  
  			int version = reader.ReadByte();
  
  			switch (version)
  			{
  				case 0:
  					{
  						m_Base = reader.ReadUShort();
  						m_Cap = reader.ReadUShort();
  						m_Lock = (SkillLock)reader.ReadByte();
  
  						break;
  					}
  				case 0xFF:
  					{
  						m_Base = 0;
  						m_Cap = 1000;
  						m_Lock = SkillLock.Up;
  
  						break;
  					}
  				default:
  					{
  						if ((version & 0xC0) == 0x00)
  						{
  							if ((version & 0x1) != 0)
  							{
  								m_Base = reader.ReadUShort();
  							}
  
  							if ((version & 0x2) != 0)
  							{
  								m_Cap = reader.ReadUShort();
  							}
  							else
  							{
  								m_Cap = 1000;
  							}
  
  							if ((version & 0x4) != 0)
  							{
  								m_Lock = (SkillLock)reader.ReadByte();
  							}
  						}
  
  						break;
  					}
  			}
  
  			if (m_Lock < SkillLock.Up || m_Lock > SkillLock.Locked)
  			{
  				Console.WriteLine("Bad skill lock -> {0}.{1}", owner.Owner, m_Lock);
  				m_Lock = SkillLock.Up;
  			}
  		}
  
  		public Skill(Skills owner, SkillInfo info, int baseValue, int cap, SkillLock skillLock)
  		{
  			m_Owner = owner;
  			m_Info = info;
  			m_Base = (ushort)baseValue;
  			m_Cap = (ushort)cap;
  			m_Lock = skillLock;
  		}
  
  		public void SetLockNoRelay(SkillLock skillLock)
  		{
  			if (skillLock < SkillLock.Up || skillLock > SkillLock.Locked)
  			{
  				return;
  			}
  
  			m_Lock = skillLock;
  		}
  
  		public void Serialize(GenericWriter writer)
  		{
  			if (m_Base == 0 && m_Cap == 1000 && m_Lock == SkillLock.Up)
  			{
  				writer.Write((byte)0xFF); // default
  			}
  			else
  			{
  				int flags = 0x0;
  
  				if (m_Base != 0)
  				{
  					flags |= 0x1;
  				}
  
  				if (m_Cap != 1000)
  				{
  					flags |= 0x2;
  				}
  
  				if (m_Lock != SkillLock.Up)
  				{
  					flags |= 0x4;
  				}
  
  				writer.Write((byte)flags); // version
  
  				if (m_Base != 0)
  				{
  					writer.Write((short)m_Base);
  				}
  
  				if (m_Cap != 1000)
  				{
  					writer.Write((short)m_Cap);
  				}
  
  				if (m_Lock != SkillLock.Up)
  				{
  					writer.Write((byte)m_Lock);
  				}
  			}
  		}
  
  		public Skills Owner { get { return m_Owner; } }
  
  		public SkillName SkillName { get { return (SkillName)m_Info.SkillID; } }
  
  		public int SkillID { get { return m_Info.SkillID; } }
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public string Name { get { return m_Info.Name; } }
  
  		public SkillInfo Info { get { return m_Info; } }
  
  		[CommandProperty(AccessLevel.Counselor)]
  		public SkillLock Lock { get { return m_Lock; } }
  
  		public int BaseFixedPoint
  		{
  			get { return m_Base; }
  			set
  			{
  				if (value < 0)
  				{
  					value = 0;
  				}
  				else if (value >= 0x10000)
  				{
  					value = 0xFFFF;
  				}
  
  				ushort sv = (ushort)value;
  
  				int oldBase = m_Base;
  
  				if (m_Base != sv)
  				{
  					m_Owner.Total = (m_Owner.Total - m_Base) + sv;
  
  					m_Base = sv;
  
  					m_Owner.OnSkillChange(this);
  
  					Mobile m = m_Owner.Owner;
  
  					if (m != null)
  					{
  						m.OnSkillChange(SkillName, (double)oldBase / 10);
  					}
  				}
  			}
  		}
  
  		[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
  		public double Base { get { return (m_Base / 10.0); } set { BaseFixedPoint = (int)(value * 10.0); } }
  
  		public int CapFixedPoint
  		{
  			get { return m_Cap; }
  			set
  			{
  				if (value < 0)
  				{
  					value = 0;
  				}
  				else if (value >= 0x10000)
  				{
  					value = 0xFFFF;
  				}
  
  				ushort sv = (ushort)value;
  
  
gt: 				if (m_Cap != sv)