context: using System;
  using System.Collections;
  using Server.Network;
  using Server.Engines.Craft;
  using Server.Factions;
  using AMA = Server.Items.ArmorMeditationAllowance;
  using AMT = Server.Items.ArmorMaterialType;
  using ABT = Server.Items.ArmorBodyType;
  
  namespace Server.Items
  {
  	public abstract class BaseArmor : Item, IScissorable, IFactionItem, ICraftable
  	{
  		#region Factions
  		private FactionItem m_FactionState;
  
  		public FactionItem FactionItemState
  		{
  			get{ return m_FactionState; }
  			set
  			{
  				m_FactionState = value;
  
  				if ( m_FactionState == null )
  					Hue = CraftResources.GetHue( Resource );
  
  				LootType = ( m_FactionState == null ? LootType.Regular : LootType.Blessed );
  			}
  		}
  		#endregion
  
  
  
  		/* Armor internals work differently now (Jun 19 2003)
  		 * 
  		 * The attributes defined below default to -1.
  		 * If the value is -1, the corresponding virtual 'Aos/Old' property is used.
  		 * If not, the attribute value itself is used. Here's the list:
  		 *  - ArmorBase
  		 *  - StrBonus
  		 *  - DexBonus
  		 *  - IntBonus
  		 *  - StrReq
  		 *  - DexReq
  		 *  - IntReq
  		 *  - MeditationAllowance
  		 */
  
  		// Instance values. These values must are unique to each armor piece.
  		private int m_MaxHitPoints;
  		private int m_HitPoints;
  		private Mobile m_Crafter;
  		private ArmorQuality m_Quality;
  		private ArmorDurabilityLevel m_Durability;
  		private ArmorProtectionLevel m_Protection;
  		private CraftResource m_Resource;
  		private bool m_Identified, m_PlayerConstructed;
  		private int m_PhysicalBonus, m_FireBonus, m_ColdBonus, m_PoisonBonus, m_EnergyBonus;
  
  		private AosAttributes m_AosAttributes;
  		private AosArmorAttributes m_AosArmorAttributes;
  		private AosSkillBonuses m_AosSkillBonuses;
  
  		// Overridable values. These values are provided to override the defaults which get defined in the individual armor scripts.
  		private int m_ArmorBase = -1;
  		private int m_StrBonus = -1, m_DexBonus = -1, m_IntBonus = -1;
  		private int m_StrReq = -1, m_DexReq = -1, m_IntReq = -1;
  		private AMA m_Meditate = (AMA)(-1);
  
  
  		public virtual bool AllowMaleWearer{ get{ return true; } }
  		public virtual bool AllowFemaleWearer{ get{ return true; } }
  
  		public abstract AMT MaterialType{ get; }
  
  		public virtual int RevertArmorBase{ get{ return ArmorBase; } }
  		public virtual int ArmorBase{ get{ return 0; } }
  
  		public virtual AMA DefMedAllowance{ get{ return AMA.None; } }
  		public virtual AMA AosMedAllowance{ get{ return DefMedAllowance; } }
  		public virtual AMA OldMedAllowance{ get{ return DefMedAllowance; } }
  
  
  		public virtual int AosStrBonus{ get{ return 0; } }
  		public virtual int AosDexBonus{ get{ return 0; } }
  		public virtual int AosIntBonus{ get{ return 0; } }
  		public virtual int AosStrReq{ get{ return 0; } }
  		public virtual int AosDexReq{ get{ return 0; } }
  		public virtual int AosIntReq{ get{ return 0; } }
  
  
  		public virtual int OldStrBonus{ get{ return 0; } }
  		public virtual int OldDexBonus{ get{ return 0; } }
  		public virtual int OldIntBonus{ get{ return 0; } }
  		public virtual int OldStrReq{ get{ return 0; } }
  		public virtual int OldDexReq{ get{ return 0; } }
  		public virtual int OldIntReq{ get{ return 0; } }
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public AMA MeditationAllowance
  		{
  			get{ return ( m_Meditate == (AMA)(-1) ? Core.AOS ? AosMedAllowance : OldMedAllowance : m_Meditate ); }
  			set{ m_Meditate = value; }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int BaseArmorRating
  		{
  			get
  			{
  				if ( m_ArmorBase == -1 )
  					return ArmorBase;
  				else
  					return m_ArmorBase;
  			}
  			set
  			{ 
  				m_ArmorBase = value; Invalidate(); 
  			}
  		}
  
  		public double BaseArmorRatingScaled
  		{
  			get
  			{
  				return ( BaseArmorRating * ArmorScalar );
  			}
  		}
  
  		public virtual double ArmorRating
  		{
  			get
  			{
  				int ar = BaseArmorRating;
  
  				if ( m_Protection != ArmorProtectionLevel.Regular )
  					ar += 10 + (5 * (int)m_Protection);
  
  				switch ( m_Resource )
  				{
  					case CraftResource.DullCopper:		ar += 2; break;
  					case CraftResource.ShadowIron:		ar += 4; break;
  					case CraftResource.Copper:			ar += 6; break;
  					case CraftResource.Bronze:			ar += 8; break;
  					case CraftResource.Gold:			ar += 10; break;
  					case CraftResource.Agapite:			ar += 12; break;
  					case CraftResource.Verite:			ar += 14; break;
  					case CraftResource.Valorite:		ar += 16; break;
  					case CraftResource.SpinedLeather:	ar += 10; break;
  					case CraftResource.HornedLeather:	ar += 13; break;
  					case CraftResource.BarbedLeather:	ar += 16; break;
  				}
  
  				ar += -8 + (8 * (int)m_Quality);
  				return ScaleArmorByDurability( ar );
  			}
  		}
  
  		public double ArmorRatingScaled
  		{
  			get
  			{
  				return ( ArmorRating * ArmorScalar );
  			}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int StrBonus
  		{
  			get{ return ( m_StrBonus == -1 ? Core.AOS ? AosStrBonus : OldStrBonus : m_StrBonus ); }
  			set{ m_StrBonus = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int DexBonus
  		{
  			get{ return ( m_DexBonus == -1 ? Core.AOS ? AosDexBonus : OldDexBonus : m_DexBonus ); }
  			set{ m_DexBonus = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int IntBonus
  		{
  			get{ return ( m_IntBonus == -1 ? Core.AOS ? AosIntBonus : OldIntBonus : m_IntBonus ); }
  			set{ m_IntBonus = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int StrRequirement
  		{
  			get{ return ( m_StrReq == -1 ? Core.AOS ? AosStrReq : OldStrReq : m_StrReq ); }
  			set{ m_StrReq = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int DexRequirement
  		{
  			get{ return ( m_DexReq == -1 ? Core.AOS ? AosDexReq : OldDexReq : m_DexReq ); }
  			set{ m_DexReq = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int IntRequirement
  		{
  			get{ return ( m_IntReq == -1 ? Core.AOS ? AosIntReq : OldIntReq : m_IntReq ); }
  			set{ m_IntReq = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public bool Identified
  		{
  			get{ return m_Identified; }
  			set{ m_Identified = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public bool PlayerConstructed
  		{
  			get{ return m_PlayerConstructed; }
  			set{ m_PlayerConstructed = value; }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public CraftResource Resource
  		{
  			get
  			{
  				return m_Resource;
  			}
  			set
  			{
  				if ( m_Resource != value )
  				{
  					UnscaleDurability();
  
  					m_Resource = value;
  					Hue = CraftResources.GetHue( m_Resource );
  
  					Invalidate();
  					InvalidateProperties();
  
  					if ( Parent is Mobile )
  						((Mobile)Parent).UpdateResistances();
  
  					ScaleDurability();
  				}
  			}
  		}
  
  		public virtual double ArmorScalar
  		{
  			get
  			{
  				int pos = (int)BodyPosition;
  
  				if ( pos >= 0 && pos < m_ArmorScalars.Length )
  					return m_ArmorScalars[pos];
  
  				return 1.0;
  			}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int MaxHitPoints
  		{
  			get{ return m_MaxHitPoints; }
  			set{ m_MaxHitPoints = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int HitPoints
  		{
  			get 
  			{
  				return m_HitPoints;
  			}
  			set 
  			{
  				if ( value != m_HitPoints && MaxHitPoints > 0 )
  				{
  					m_HitPoints = value;
  
  					if ( m_HitPoints < 0 )
  						Delete();
  					else if ( m_HitPoints > MaxHitPoints )
  						m_HitPoints = MaxHitPoints;
  
  					InvalidateProperties();
  				}
  			}
  		}
  
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public Mobile Crafter
  		{
  			get{ return m_Crafter; }
  			set{ m_Crafter = value; InvalidateProperties(); }
  		}
  
  		
  		[CommandProperty( AccessLevel.GameMaster )]
  		public ArmorQuality Quality
  		{
  			get{ return m_Quality; }
  			set{ UnscaleDurability(); m_Quality = value; Invalidate(); InvalidateProperties(); ScaleDurability(); }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public ArmorDurabilityLevel Durability
  		{
  			get{ return m_Durability; }
  			set{ UnscaleDurability(); m_Durability = value; ScaleDurability(); InvalidateProperties(); }
  		}
  
  		public virtual int ArtifactRarity
  		{
  			get{ return 0; }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public ArmorProtectionLevel ProtectionLevel
  		{
  			get
  			{
  				return m_Protection;
  			}
  			set
  			{
  				if ( m_Protection != value )
  				{
  					m_Protection = value;
  
  					Invalidate();
  					InvalidateProperties();
  
  					if ( Parent is Mobile )
  						((Mobile)Parent).UpdateResistances();
  				}
  			}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public AosAttributes Attributes
  		{
  			get {
  				if (m_AosAttributes == null)
  					m_AosAttributes = new AosAttributes(this);
  				return m_AosAttributes;
  			}
  			set{}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public AosArmorAttributes ArmorAttributes
  		{
  			get {
  				if (m_AosArmorAttributes == null)
  					m_AosArmorAttributes = new AosArmorAttributes(this);
  				return m_AosArmorAttributes;
  			}
  			set{}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public AosSkillBonuses SkillBonuses
  		{
  			get {
  				if (m_AosSkillBonuses == null)
  					m_AosSkillBonuses = new AosSkillBonuses(this);
  				return m_AosSkillBonuses;
  			}
  			set{}
  		}
  
  		public int ComputeStatReq( StatType type )
  		{
  			int v;
  
  			if ( type == StatType.Str )
  				v = StrRequirement;
  			else if ( type == StatType.Dex )
  				v = DexRequirement;
  			else
  				v = IntRequirement;
  
  			return AOS.Scale( v, 100 - GetLowerStatReq() );
  		}
  
  		public int ComputeStatBonus( StatType type )
  		{
  			if ( type == StatType.Str )
  				return StrBonus + Attributes.BonusStr;
  			else if ( type == StatType.Dex )
  				return DexBonus + Attributes.BonusDex;
  			else
  				return IntBonus + Attributes.BonusInt;
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int PhysicalBonus{ get{ return m_PhysicalBonus; } set{ m_PhysicalBonus = value; InvalidateProperties(); } }
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int FireBonus{ get{ return m_FireBonus; } set{ m_FireBonus = value; InvalidateProperties(); } }
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int ColdBonus{ get{ return m_ColdBonus; } set{ m_ColdBonus = value; InvalidateProperties(); } }
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int PoisonBonus{ get{ return m_PoisonBonus; } set{ m_PoisonBonus = value; InvalidateProperties(); } }
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int EnergyBonus{ get{ return m_EnergyBonus; } set{ m_EnergyBonus = value; InvalidateProperties(); } }
  
  		public virtual int BasePhysicalResistance{ get{ return 0; } }
  		public virtual int BaseFireResistance{ get{ return 0; } }
  		public virtual int BaseColdResistance{ get{ return 0; } }
  		public virtual int BasePoisonResistance{ get{ return 0; } }
  		public virtual int BaseEnergyResistance{ get{ return 0; } }
  
  		public override int PhysicalResistance{ get{ return BasePhysicalResistance + GetProtOffset() + GetResourceAttrs().ArmorPhysicalResist + m_PhysicalBonus; } }
  		public override int FireResistance{ get{ return BaseFireResistance + GetProtOffset() + GetResourceAttrs().ArmorFireResist + m_FireBonus; } }
  		public override int ColdResistance{ get{ return BaseColdResistance + GetProtOffset() + GetResourceAttrs().ArmorColdResist + m_ColdBonus; } }
  		public override int PoisonResistance{ get{ return BasePoisonResistance + GetProtOffset() + GetResourceAttrs().ArmorPoisonResist + m_PoisonBonus; } }
  		public override int EnergyResistance{ get{ return BaseEnergyResistance + GetProtOffset() + GetResourceAttrs().ArmorEnergyResist + m_EnergyBonus; } }
  
  		public virtual int InitMinHits{ get{ return 0; } }
  		public virtual int InitMaxHits{ get{ return 0; } }
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public ArmorBodyType BodyPosition
  		{
  			get
  			{
  				switch ( this.Layer )
  				{
  					default:
  					case Layer.Neck:		return ArmorBodyType.Gorget;
  					case Layer.TwoHanded:	return ArmorBodyType.Shield;
  					case Layer.Gloves:		return ArmorBodyType.Gloves;
  					case Layer.Helm:		return ArmorBodyType.Helmet;
  					case Layer.Arms:		return ArmorBodyType.Arms;
  
  					case Layer.InnerLegs:
  					case Layer.OuterLegs:
  					case Layer.Pants:		return ArmorBodyType.Legs;
  
  					case Layer.InnerTorso:
  					case Layer.OuterTorso:
  					case Layer.Shirt:		return ArmorBodyType.Chest;
  				}
  			}
  		}
  
  		public void DistributeBonuses( int amount )
  		{
  			for ( int i = 0; i < amount; ++i )
  			{
  				switch ( Utility.Random( 5 ) )
  				{
  					case 0: ++m_PhysicalBonus; break;
  					case 1: ++m_FireBonus; break;
  					case 2: ++m_ColdBonus; break;
  					case 3: ++m_PoisonBonus; break;
  					case 4: ++m_EnergyBonus; break;
  				}
  			}
  
  			InvalidateProperties();
  		}
  
  		public CraftAttributeInfo GetResourceAttrs()
  		{
  			CraftResourceInfo info = CraftResources.GetInfo( m_Resource );
  
  			if ( info == null )
  				return CraftAttributeInfo.Blank;
  
  			return info.AttributeInfo;
  		}
  
  		public int GetProtOffset()
  		{
  			switch ( m_Protection )
  			{
  				case ArmorProtectionLevel.Guarding: return 1;
  				case ArmorProtectionLevel.Hardening: return 2;
  				case ArmorProtectionLevel.Fortification: return 3;
  				case ArmorProtectionLevel.Invulnerability: return 4;
  			}
  
  			return 0;
  		}
  
  		public void UnscaleDurability()
  		{
  			int scale = 100 + GetDurabilityBonus();
  
  			m_HitPoints = ((m_HitPoints * 100) + (scale - 1)) / scale;
  			m_MaxHitPoints = ((m_MaxHitPoints * 100) + (scale - 1)) / scale;
  			InvalidateProperties();
  		}
  
  		public void ScaleDurability()
  		{
  			int scale = 100 + GetDurabilityBonus();
  
  			m_HitPoints = ((m_HitPoints * scale) + 99) / 100;
  			m_MaxHitPoints = ((m_MaxHitPoints * scale) + 99) / 100;
  			InvalidateProperties();
  		}
  
  		public int GetDurabilityBonus()
  		{
  			int bonus = 0;
  
  			if ( m_Quality == ArmorQuality.Exceptional )
  				bonus += 20;
  
  			switch ( m_Durability )
  			{
  				case ArmorDurabilityLevel.Durable: bonus += 20; break;
  				case ArmorDurabilityLevel.Substantial: bonus += 50; break;
  				case ArmorDurabilityLevel.Massive: bonus += 70; break;
  				case ArmorDurabilityLevel.Fortified: bonus += 100; break;
  				case ArmorDurabilityLevel.Indestructible: bonus += 120; break;
  			}
  
  			if ( Core.AOS )
  			{
  				if (m_AosArmorAttributes != null)
  					bonus += m_AosArmorAttributes.DurabilityBonus;
  
  				CraftResourceInfo resInfo = CraftResources.GetInfo( m_Resource );
  				CraftAttributeInfo attrInfo = null;
  
  				if ( resInfo != null )
  					attrInfo = resInfo.AttributeInfo;
  
  				if ( attrInfo != null )
  					bonus += attrInfo.ArmorDurability;
  			}
  
  			return bonus;
  		}
  
  		public bool Scissor( Mobile from, Scissors scissors )
  		{
  			if ( !IsChildOf( from.Backpack ) )
  			{
  				from.SendLocalizedMessage( 502437 ); // Items you wish to cut must be in your backpack.
  				return false;
  			}
  
  			CraftSystem system = DefTailoring.CraftSystem;
  
  			CraftItem item = system.CraftItems.SearchFor( GetType() );
  
  			if ( item != null && item.Ressources.Count == 1 && item.Ressources.GetAt( 0 ).Amount >= 2 )
  			{
  				try
  				{
  					Item res = (Item)Activator.CreateInstance( CraftResources.GetInfo( m_Resource ).ResourceTypes[0] );
  
  					ScissorHelper( from, res, m_PlayerConstructed ? (item.Ressources.GetAt( 0 ).Amount / 2) : 1 );
  					return true;
  				}
  				catch
  				{
  				}
  			}
  
  			from.SendLocalizedMessage( 502440 ); // Scissors can not be used on that to produce anything.
  			return false;
  		}
  
  		private static double[] m_ArmorScalars = { 0.07, 0.07, 0.14, 0.15, 0.22, 0.35 };
  
  		public static double[] ArmorScalars
  		{
  			get
  			{
  				return m_ArmorScalars;
  			}
  			set
  			{
  				m_ArmorScalars = value;
  			}
  		}
  
  		public static void ValidateMobile( Mobile m )
  		{
  			for ( int i = m.Items.Count - 1; i >= 0; --i )
  			{
  				if ( i >= m.Items.Count )
  					continue;
  
  				Item item = (Item)m.Items[i];
  
  				if ( item is BaseArmor )
  				{
  					BaseArmor armor = (BaseArmor)item;
  
  					if ( !armor.AllowMaleWearer && m.Body.IsMale && m.AccessLevel < AccessLevel.GameMaster )
  					{
  						if ( armor.AllowFemaleWearer )
  							m.SendLocalizedMessage( 1010388 ); // Only females can wear this.
  						else
  							m.SendMessage( "You may not wear this." );
  
  						m.AddToBackpack( armor );
  					}
  					else if ( !armor.AllowFemaleWearer && m.Body.IsFemale && m.AccessLevel < AccessLevel.GameMaster )
  					{
  						if ( armor.AllowMaleWearer )
  							m.SendMessage( "Only males can wear this." );
  						else
  							m.SendMessage( "You may not wear this." );
  
  						m.AddToBackpack( armor );
  					}
  				}
  			}
  		}
  
  		public int GetLowerStatReq()
  		{
  			if ( !Core.AOS )
  				return 0;
  
  			int v = 0;
  			if (m_AosArmorAttributes != null)
  				v += m_AosArmorAttributes.LowerStatReq;
  
  			CraftResourceInfo info = CraftResources.GetInfo( m_Resource );
  
  			if ( info != null )
  			{
  				CraftAttributeInfo attrInfo = info.AttributeInfo;
  
  				if ( attrInfo != null )
  					v += attrInfo.ArmorLowerRequirements;
  			}
  
  			if ( v > 100 )
  				v = 100;
  
  			return v;
  		}
  
  		public override void OnAdded( object parent )
  		{
  			if ( parent is Mobile )
  			{
  				Mobile from = (Mobile)parent;
  
  				if ( Core.AOS )
  					this.SkillBonuses.AddTo( from );
  
  				from.Delta( MobileDelta.Armor ); // Tell them armor rating has changed
  			}
  		}
  
  		public virtual double ScaleArmorByDurability( double armor )
  		{
  			int scale = 100;
  
  			if ( m_MaxHitPoints > 0 && m_HitPoints < m_MaxHitPoints )
  				scale = 50 + ((50 * m_HitPoints) / m_MaxHitPoints);
  
  			return ( armor * scale ) / 100;
  		}
  
  		protected void Invalidate()
  		{
  			if ( Parent is Mobile )
  				((Mobile)Parent).Delta( MobileDelta.Armor ); // Tell them armor rating has changed
  		}
  
  		public BaseArmor( Serial serial ) :  base( serial )
  		{
  		}
  
  		private static void SetSaveFlag( ref SaveFlag flags, SaveFlag toSet, bool setIf )
  		{
  			if ( setIf )
  				flags |= toSet;
  		}
  
  		private static bool GetSaveFlag( SaveFlag flags, SaveFlag toGet )
  		{
  			return ( (flags & toGet) != 0 );
  		}
  
  		[Flags]
  		private enum SaveFlag
  		{
  			None				= 0x00000000,
  			Attributes			= 0x00000001,
  			ArmorAttributes		= 0x00000002,
  			PhysicalBonus		= 0x00000004,
  			FireBonus			= 0x00000008,
  			ColdBonus			= 0x00000010,
  			PoisonBonus			= 0x00000020,
  			EnergyBonus			= 0x00000040,
  			Identified			= 0x00000080,
  			MaxHitPoints		= 0x00000100,
  			HitPoints			= 0x00000200,
  			Crafter				= 0x00000400,
  			Quality				= 0x00000800,
  			Durability			= 0x00001000,
  			Protection			= 0x00002000,
  			Resource			= 0x00004000,
  			BaseArmor			= 0x00008000,
  			StrBonus			= 0x00010000,
  			DexBonus			= 0x00020000,
  			IntBonus			= 0x00040000,
  			StrReq				= 0x00080000,
  			DexReq				= 0x00100000,
  			IntReq				= 0x00200000,
  			MedAllowance		= 0x00400000,
  			SkillBonuses		= 0x00800000,
  			PlayerConstructed	= 0x01000000
  		}
  
  		public override void Serialize( GenericWriter writer )
  		{
  			base.Serialize( writer );
  
  			writer.Write( (int) 7 ); // version
  
  			SaveFlag flags = SaveFlag.None;
  
  			SetSaveFlag(ref flags, SaveFlag.Attributes,
  						m_AosAttributes != null && !m_AosAttributes.IsEmpty );
  			SetSaveFlag(ref flags, SaveFlag.ArmorAttributes,
  						m_AosArmorAttributes != null && !m_AosArmorAttributes.IsEmpty );
  			SetSaveFlag( ref flags, SaveFlag.PhysicalBonus,		m_PhysicalBonus != 0 );
  			SetSaveFlag( ref flags, SaveFlag.FireBonus,			m_FireBonus != 0 );
  			SetSaveFlag( ref flags, SaveFlag.ColdBonus,			m_ColdBonus != 0 );
  			SetSaveFlag( ref flags, SaveFlag.PoisonBonus,		m_PoisonBonus != 0 );
  			SetSaveFlag( ref flags, SaveFlag.EnergyBonus,		m_EnergyBonus != 0 );
  			SetSaveFlag( ref flags, SaveFlag.Identified,		m_Identified != false );
  			SetSaveFlag( ref flags, SaveFlag.MaxHitPoints,		m_MaxHitPoints != 0 );
  			SetSaveFlag( ref flags, SaveFlag.HitPoints,			m_HitPoints != 0 );
  			SetSaveFlag( ref flags, SaveFlag.Crafter,			m_Crafter != null );
  			SetSaveFlag( ref flags, SaveFlag.Quality,			m_Quality != ArmorQuality.Regular );
  			SetSaveFlag( ref flags, SaveFlag.Durability,		m_Durability != ArmorDurabilityLevel.Regular );
  			SetSaveFlag( ref flags, SaveFlag.Protection,		m_Protection != ArmorProtectionLevel.Regular );
  			SetSaveFlag( ref flags, SaveFlag.Resource,			m_Resource != DefaultResource );
  			SetSaveFlag( ref flags, SaveFlag.BaseArmor,			m_ArmorBase != -1 );
  			SetSaveFlag( ref flags, SaveFlag.StrBonus,			m_StrBonus != -1 );
  			SetSaveFlag( ref flags, SaveFlag.DexBonus,			m_DexBonus != -1 );
  			SetSaveFlag( ref flags, SaveFlag.IntBonus,			m_IntBonus != -1 );
  			SetSaveFlag( ref flags, SaveFlag.StrReq,			m_StrReq != -1 );
  			SetSaveFlag( ref flags, SaveFlag.DexReq,			m_DexReq != -1 );
  			SetSaveFlag( ref flags, SaveFlag.IntReq,			m_IntReq != -1 );
  			SetSaveFlag( ref flags, SaveFlag.MedAllowance,		m_Meditate != (AMA)(-1) );
  			SetSaveFlag(ref flags, SaveFlag.SkillBonuses,
  						m_AosSkillBonuses != null && !m_AosSkillBonuses.IsEmpty );
  			SetSaveFlag( ref flags, SaveFlag.PlayerConstructed,	m_PlayerConstructed != false );
  
  			writer.WriteEncodedInt( (int) flags );
  
  			if ( GetSaveFlag( flags, SaveFlag.Attributes ) )
  				m_AosAttributes.Serialize( writer );
  
  			if ( GetSaveFlag( flags, SaveFlag.ArmorAttributes ) )
  				m_AosArmorAttributes.Serialize( writer );
  
  			if ( GetSaveFlag( flags, SaveFlag.PhysicalBonus ) )
  				writer.WriteEncodedInt( (int) m_PhysicalBonus );
  
  			if ( GetSaveFlag( flags, SaveFlag.FireBonus ) )
  				writer.WriteEncodedInt( (int) m_FireBonus );
  
  			if ( GetSaveFlag( flags, SaveFlag.ColdBonus ) )
  				writer.WriteEncodedInt( (int) m_ColdBonus );
  
  			if ( GetSaveFlag( flags, SaveFlag.PoisonBonus ) )
  				writer.WriteEncodedInt( (int) m_PoisonBonus );
  
  			if ( GetSaveFlag( flags, SaveFlag.EnergyBonus ) )
  				writer.WriteEncodedInt( (int) m_EnergyBonus );
  
  			if ( GetSaveFlag( flags, SaveFlag.MaxHitPoints ) )
  				writer.WriteEncodedInt( (int) m_MaxHitPoints );
  
  			if ( GetSaveFlag( flags, SaveFlag.HitPoints ) )
  				writer.WriteEncodedInt( (int) m_HitPoints );
  
  			if ( GetSaveFlag( flags, SaveFlag.Crafter ) )
  				writer.Write( (Mobile) m_Crafter );
  
  			if ( GetSaveFlag( flags, SaveFlag.Quality ) )
  				writer.WriteEncodedInt( (int) m_Quality );
  
  			if ( GetSaveFlag( flags, SaveFlag.Durability ) )
  				writer.WriteEncodedInt( (int) m_Durability );
  
  			if ( GetSaveFlag( flags, SaveFlag.Protection ) )
  				writer.WriteEncodedInt( (int) m_Protection );
  
  			if ( GetSaveFlag( flags, SaveFlag.Resource ) )
  				writer.WriteEncodedInt( (int) m_Resource );
  
  			if ( GetSaveFlag( flags, SaveFlag.BaseArmor ) )
  				writer.WriteEncodedInt( (int) m_ArmorBase );
  
  			if ( GetSaveFlag( flags, SaveFlag.StrBonus ) )
  				writer.WriteEncodedInt( (int) m_StrBonus );
  
  			if ( GetSaveFlag( flags, SaveFlag.DexBonus ) )
  				writer.WriteEncodedInt( (int) m_DexBonus );
  
  			if ( GetSaveFlag( flags, SaveFlag.IntBonus ) )
  				writer.WriteEncodedInt( (int) m_IntBonus );
  
  			if ( GetSaveFlag( flags, SaveFlag.StrReq ) )
  				writer.WriteEncodedInt( (int) m_StrReq );
  
  			if ( GetSaveFlag( flags, SaveFlag.DexReq ) )
  				writer.WriteEncodedInt( (int) m_DexReq );
  
  			if ( GetSaveFlag( flags, SaveFlag.IntReq ) )
  				writer.WriteEncodedInt( (int) m_IntReq );
  
  			if ( GetSaveFlag( flags, SaveFlag.MedAllowance ) )
  				writer.WriteEncodedInt( (int) m_Meditate );
  
  			if ( GetSaveFlag( flags, SaveFlag.SkillBonuses ) )
  				m_AosSkillBonuses.Serialize( writer );
  		}
  
  		public override void Deserialize( GenericReader reader )
  		{
  			base.Deserialize( reader );
  
  			int version = reader.ReadInt();
  
  			switch ( version )
  			{
  				case 7:
  				case 6:
  				case 5:
  				{
  					SaveFlag flags = (SaveFlag)reader.ReadEncodedInt();
  
  					if ( GetSaveFlag( flags, SaveFlag.Attributes ) )
  						m_AosAttributes = new AosAttributes( this, reader );
  
  					if ( GetSaveFlag( flags, SaveFlag.ArmorAttributes ) )
  						m_AosArmorAttributes = new AosArmorAttributes( this, reader );
  
  					if ( GetSaveFlag( flags, SaveFlag.PhysicalBonus ) )
  						m_PhysicalBonus = reader.ReadEncodedInt();
  
  					if ( GetSaveFlag( flags, SaveFlag.FireBonus ) )
  						m_FireBonus = reader.ReadEncodedInt();
  
  					if ( GetSaveFlag( flags, SaveFlag.ColdBonus ) )
  						m_ColdBonus = reader.ReadEncodedInt();
  
  					if ( GetSaveFlag( flags, SaveFlag.PoisonBonus ) )
  						m_PoisonBonus = reader.ReadEncodedInt();
  
  					if ( GetSaveFlag( flags, SaveFlag.EnergyBonus ) )
  						m_EnergyBonus = reader.ReadEncodedInt();
  
  					if ( GetSaveFlag( flags, SaveFlag.Identified ) )
  						m_Identified = ( version >= 7 || reader.ReadBool() );
  
  					if ( GetSaveFlag( flags, SaveFlag.MaxHitPoints ) )
  						m_MaxHitPoints = reader.ReadEncodedInt();
  
  					if ( GetSaveFlag( flags, SaveFlag.HitPoints ) )
  						m_HitPoints = reader.ReadEncodedInt();
  
  					if ( GetSaveFlag( flags, SaveFlag.Crafter ) )
  						m_Crafter = reader.ReadMobile();
  
  					if ( GetSaveFlag( flags, SaveFlag.Quality ) )
  						m_Quality = (ArmorQuality)reader.ReadEncodedInt();
  					else
  						m_Quality = ArmorQuality.Regular;
  
  					if ( version == 5 && m_Quality == ArmorQuality.Low )
  						m_Quality = ArmorQuality.Regular;
  
  					if ( GetSaveFlag( flags, SaveFlag.Durability ) )
  					{
  						m_Durability = (ArmorDurabilityLevel)reader.ReadEncodedInt();
  
  						if ( m_Durability > ArmorDurabilityLevel.Indestructible )
  							m_Durability = ArmorDurabilityLevel.Durable;
  					}
  
  					if ( GetSaveFlag( flags, SaveFlag.Protection ) )
  					{
  						m_Protection = (ArmorProtectionLevel)reader.ReadEncodedInt();
  
  						if ( m_Protection > ArmorProtectionLevel.Invulnerability )
  							m_Protection = ArmorProtectionLevel.Defense;
  					}
  
  					if ( GetSaveFlag( flags, SaveFlag.Resource ) )
  						m_Resource = (CraftResource)reader.ReadEncodedInt();
  					else
  						m_Resource = DefaultResource;
  
  					if ( m_Resource == CraftResource.None )
  						m_Resource = DefaultResource;
  
  					if ( GetSaveFlag( flags, SaveFlag.BaseArmor ) )
  						m_ArmorBase = reader.ReadEncodedInt();
  					else
  						m_ArmorBase = -1;
  
  					if ( GetSaveFlag( flags, SaveFlag.StrBonus ) )
  						m_StrBonus = reader.ReadEncodedInt();
  					else
  						m_StrBonus = -1;
  
  					if ( GetSaveFlag( flags, SaveFlag.DexBonus ) )
  						m_DexBonus = reader.ReadEncodedInt();
  					else
  						m_DexBonus = -1;
  
  					if ( GetSaveFlag( flags, SaveFlag.IntBonus ) )
  						m_IntBonus = reader.ReadEncodedInt();
  					else
  						m_IntBonus = -1;
  
  					if ( GetSaveFlag( flags, SaveFlag.StrReq ) )
  						m_StrReq = reader.ReadEncodedInt();
  					else
  						m_StrReq = -1;
  
  					if ( GetSaveFlag( flags, SaveFlag.DexReq ) )
  						m_DexReq = reader.ReadEncodedInt();
  					else
  						m_DexReq = -1;
  
  					if ( GetSaveFlag( flags, SaveFlag.IntReq ) )
  						m_IntReq = reader.ReadEncodedInt();
  					else
  						m_IntReq = -1;
  
  					if ( GetSaveFlag( flags, SaveFlag.MedAllowance ) )
  						m_Meditate = (AMA)reader.ReadEncodedInt();
  					else
  						m_Meditate = (AMA)(-1);
  
  					if ( GetSaveFlag( flags, SaveFlag.SkillBonuses ) )
  						m_AosSkillBonuses = new AosSkillBonuses( this, reader );
  
  					if ( GetSaveFlag( flags, SaveFlag.PlayerConstructed ) )
  						m_PlayerConstructed = true;
  
  					break;
  				}
  				case 4:
  				{
  					m_AosAttributes = new AosAttributes( this, reader );
  					m_AosArmorAttributes = new AosArmorAttributes( this, reader );
  					goto case 3;
  				}
  				case 3:
  				{
  					m_PhysicalBonus = reader.ReadInt();
  					m_FireBonus = reader.ReadInt();
  					m_ColdBonus = reader.ReadInt();
  					m_PoisonBonus = reader.ReadInt();
  					m_EnergyBonus = reader.ReadInt();
  					goto case 2;
  				}
  				case 2:
  				case 1:
  				{
  					m_Identified = reader.ReadBool();
  					goto case 0;
  				}
  				case 0:
  				{
  					m_ArmorBase = reader.ReadInt();
  					m_MaxHitPoints = reader.ReadInt();
  					m_HitPoints = reader.ReadInt();
  					m_Crafter = reader.ReadMobile();
  					m_Quality = (ArmorQuality)reader.ReadInt();
  
gt: 					m_Durability = (ArmorDurabilityLevel)reader.ReadInt();