context: using System;
  using Server.Commands;
  using Server.Mobiles;
  using Server.Spells.Fifth;
  using Server.Spells.First;
  using Server.Spells.Fourth;
  using Server.Spells.Necromancy;
  using Server.Spells.Second;
  using Server.Targeting;
  
  namespace Server.Items
  {
  	public enum TalismanRemoval
  	{
  		None = 0,
  		Ward = 390,
  		Damage = 404,
  		Curse = 407,
  		Wildfire = 2843
  	}
  
  	public class BaseTalisman : Item
  	{
  		public static void Initialize()
  		{
  			CommandSystem.Register("RandomTalisman", AccessLevel.GameMaster, new CommandEventHandler(RandomTalisman_OnCommand));
  		}
  
  		[Usage("RandomTalisman <count>")]
  		[Description("Generates random talismans in your backback.")]
  		public static void RandomTalisman_OnCommand(CommandEventArgs e)
  		{
  			Mobile m = e.Mobile;
  			int count = e.GetInt32(0);
  
  			for (int i = 0; i < count; i++)
  			{
  				m.AddToBackpack(Loot.RandomTalisman());
  			}
  		}
  
  		public override int LabelNumber { get { return 1071023; } } // Talisman
  		public virtual bool ForceShowName { get { return false; } } // used to override default summoner/removal name
  
  		private int m_MaxCharges;
  		private int m_Charges;
  		private int m_MaxChargeTime;
  		private int m_ChargeTime;
  		private bool m_Blessed;
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public int MaxCharges
  		{
  			get { return m_MaxCharges; }
  			set { m_MaxCharges = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public int Charges
  		{
  			get { return m_Charges; }
  			set
  			{
  				m_Charges = value;
  
  				if (m_ChargeTime > 0)
  					StartTimer();
  
  				InvalidateProperties();
  			}
  		}
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public int MaxChargeTime
  		{
  			get { return m_MaxChargeTime; }
  			set { m_MaxChargeTime = value; InvalidateProperties(); }
  		}
  
  		public int ChargeTime
  		{
  			get { return m_ChargeTime; }
  			set { m_ChargeTime = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public bool Blessed
  		{
  			get { return m_Blessed; }
  			set { m_Blessed = value; InvalidateProperties(); }
  		}
  
  		#region Slayer
  		private TalismanSlayerName m_Slayer;
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public TalismanSlayerName Slayer
  		{
  			get { return m_Slayer; }
  			set { m_Slayer = value; InvalidateProperties(); }
  		}
  		#endregion
  
  		#region Summoner/Removal
  		private TalismanAttribute m_Summoner;
  		private TalismanRemoval m_Removal;
  		private Mobile m_Creature;
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public TalismanAttribute Summoner
  		{
  			get { return m_Summoner; }
  			set { m_Summoner = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public TalismanRemoval Removal
  		{
  			get { return m_Removal; }
  			set { m_Removal = value; InvalidateProperties(); }
  		}
  		#endregion
  
  		#region Protection/Killer
  		private TalismanAttribute m_Protection;
  		private TalismanAttribute m_Killer;
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public TalismanAttribute Protection
  		{
  			get { return m_Protection; }
  			set { m_Protection = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public TalismanAttribute Killer
  		{
  			get { return m_Killer; }
  			set { m_Killer = value; InvalidateProperties(); }
  		}
  		#endregion
  
  		#region Craft bonuses
  		private SkillName m_Skill;
  		private int m_SuccessBonus;
  		private int m_ExceptionalBonus;
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public SkillName Skill
  		{
  			get { return m_Skill; }
  			set { m_Skill = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public int SuccessBonus
  		{
  			get { return m_SuccessBonus; }
  			set { m_SuccessBonus = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public int ExceptionalBonus
  		{
  			get { return m_ExceptionalBonus; }
  			set { m_ExceptionalBonus = value; InvalidateProperties(); }
  		}
  		#endregion
  
  		#region AOS bonuses
  		private AosAttributes m_AosAttributes;
  		private AosSkillBonuses m_AosSkillBonuses;
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public AosAttributes Attributes
  		{
  			get { return m_AosAttributes; }
  			set { }
  		}
  
  		[CommandProperty(AccessLevel.GameMaster)]
  		public AosSkillBonuses SkillBonuses
  		{
  			get { return m_AosSkillBonuses; }
  			set { }
  		}
  		#endregion
  
  		public BaseTalisman()
  			: this(GetRandomItemID())
  		{
  		}
  
  		public BaseTalisman(int itemID)
  			: base(itemID)
  		{
  			Layer = Layer.Talisman;
  			Weight = 1.0;
  
  			m_Protection = new TalismanAttribute();
  			m_Killer = new TalismanAttribute();
  			m_Summoner = new TalismanAttribute();
  			m_AosAttributes = new AosAttributes(this);
  			m_AosSkillBonuses = new AosSkillBonuses(this);
  		}
  
  		public BaseTalisman(Serial serial)
  			: base(serial)
  		{
  		}
  
  		public override void OnAfterDuped(Item newItem)
  		{
  			BaseTalisman talisman = newItem as BaseTalisman;
  
  			if (talisman == null)
  				return;
  
  			talisman.m_Summoner = new TalismanAttribute(m_Summoner);
  			talisman.m_Protection = new TalismanAttribute(m_Protection);
  			talisman.m_Killer = new TalismanAttribute(m_Killer);
  			talisman.m_AosAttributes = new AosAttributes(newItem, m_AosAttributes);
  			talisman.m_AosSkillBonuses = new AosSkillBonuses(newItem, m_AosSkillBonuses);
  		}
  
  		public override bool CanEquip( Mobile from )
  		{
  			if ( BlessedFor != null && BlessedFor != from )
  			{
  				from.SendLocalizedMessage( 1010437 ); // You are not the owner.
  				return false;
  			}
  
  			return base.CanEquip( from );
  		}
  
  		public override void OnAdded(IEntity parent)
  		{
  			if (parent is Mobile)
  			{
  				Mobile from = (Mobile)parent;
  
  				m_AosSkillBonuses.AddTo(from);
  				m_AosAttributes.AddStatBonuses(from);
  
  				if (m_Blessed && BlessedFor == null)
  				{
  					BlessedFor = from;
  					LootType = LootType.Blessed;
  				}
  
  				if (m_ChargeTime > 0)
  				{
  					m_ChargeTime = m_MaxChargeTime;
  					StartTimer();
  				}
  			}
  
  			InvalidateProperties();
  		}
  
  		public override void OnRemoved(IEntity parent)
  		{
  			if (parent is Mobile)
  			{
  				Mobile from = (Mobile)parent;
  
  				m_AosSkillBonuses.Remove();
  				m_AosAttributes.RemoveStatBonuses(from);
  
  				if (m_Creature != null && !m_Creature.Deleted)
  				{
  					Effects.SendLocationParticles(EffectItem.Create(m_Creature.Location, m_Creature.Map, EffectItem.DefaultDuration), 0x3728, 8, 20, 5042);
  					Effects.PlaySound(m_Creature, m_Creature.Map, 0x201);
  
  					m_Creature.Delete();
  				}
  
  				StopTimer();
  			}
  
  			InvalidateProperties();
  		}
  
  		public override void OnDoubleClick(Mobile from)
  		{
  			if (from.Talisman != this)
  				from.SendLocalizedMessage(502641); // You must equip this item to use it.
  			else if (m_ChargeTime > 0)
  				from.SendLocalizedMessage(1074882, m_ChargeTime.ToString()); // You must wait ~1_val~ seconds for this to recharge.
  			else if (m_Charges == 0 && m_MaxCharges > 0)
  				from.SendLocalizedMessage(1042544); // This item is out of charges.
  			else
  			{
  				Type type = GetSummoner();
  
  				if (m_Summoner != null && !m_Summoner.IsEmpty)
  					type = m_Summoner.Type;
  
  				if (type != null)
  				{
  					object obj;
  
  					try { obj = Activator.CreateInstance(type); }
  					catch { obj = null; }
  
  					if (obj is Item)
  					{
  						Item item = (Item)obj;
  						int count = 1;
  
  						if (m_Summoner != null && m_Summoner.Amount > 1)
  						{
  							if (item.Stackable)
  								item.Amount = m_Summoner.Amount;
  							else
  								count = m_Summoner.Amount;
  						}
  
  						if (from.Backpack == null || count * item.Weight > from.Backpack.MaxWeight ||
  							 from.Backpack.Items.Count + count > from.Backpack.MaxItems)
  						{
  							from.SendLocalizedMessage(500720); // You don't have enough room in your backpack!
  							item.Delete();
  							item = null;
  							return;
  						}
  
  						for (int i = 0; i < count; i++)
  						{
  							from.PlaceInBackpack(item);
  
  							if (i + 1 < count)
  								item = Activator.CreateInstance(type) as Item;
  						}
  
  						if (item is Board)
  							from.SendLocalizedMessage(1075000); // You have been given some wooden boards.
  						else if (item is IronIngot)
  							from.SendLocalizedMessage(1075001); // You have been given some ingots.
  						else if (item is Bandage)
  							from.SendLocalizedMessage(1075002); // You have been given some clean bandages.
  						else if (m_Summoner != null && m_Summoner.Name != null)
  							from.SendLocalizedMessage(1074853, m_Summoner.Name.ToString()); // You have been given ~1_name~
  					}
  					else if (obj is BaseCreature)
  					{
  						BaseCreature mob = (BaseCreature)obj;
  
  						if ((m_Creature != null && !m_Creature.Deleted) || from.Followers + mob.ControlSlots > from.FollowersMax)
  						{
  							from.SendLocalizedMessage(1074270); // You have too many followers to summon another one.
  							mob.Delete();
  							return;
  						}
  
  						BaseCreature.Summon(mob, from, from.Location, mob.BaseSoundID, TimeSpan.FromMinutes(10));
  						Effects.SendLocationParticles(EffectItem.Create(mob.Location, mob.Map, EffectItem.DefaultDuration), 0x3728, 1, 10, 0x26B6);
  
  						mob.Summoned = false;
  						mob.ControlOrder = OrderType.Friend;
  
  						m_Creature = mob;
  					}
  
  					OnAfterUse(from);
  				}
  
  				if (m_Removal != TalismanRemoval.None)
  				{
  					from.Target = new TalismanTarget(this);
  				}
  			}
  		}
  
  		public override void AddNameProperty(ObjectPropertyList list)
  		{
  			if (ForceShowName)
  				base.AddNameProperty(list);
  			else if (m_Summoner != null && !m_Summoner.IsEmpty)
  				list.Add(1072400, m_Summoner.Name != null ? m_Summoner.Name.ToString() : "Unknown"); // Talisman of ~1_name~ Summoning
  			else if (m_Removal != TalismanRemoval.None)
  				list.Add(1072389, "#" + (1072000 + (int)m_Removal)); // Talisman of ~1_name~
  			else
  				base.AddNameProperty(list);
  		}
  
  		public override void GetProperties(ObjectPropertyList list)
  		{
  			base.GetProperties(list);
  
  			if (Blessed)
  			{
  				if (BlessedFor != null)
  					list.Add(1072304, !String.IsNullOrEmpty(BlessedFor.Name) ? BlessedFor.Name : "Unnamed Warrior"); // Owned by ~1_name~
  				else
  					list.Add(1072304, "Nobody"); // Owned by ~1_name~
  			}
  
  			if (Parent is Mobile && m_MaxChargeTime > 0)
  			{
  				if (m_ChargeTime > 0)
  					list.Add(1074884, m_ChargeTime.ToString()); // Charge time left: ~1_val~
  				else
  					list.Add(1074883); // Fully Charged
  			}
  
  			list.Add(1075085); // Requirement: Mondain's Legacy
  
  			if (m_Killer != null && !m_Killer.IsEmpty && m_Killer.Amount > 0)
  				list.Add(1072388, "{0}\t{1}", m_Killer.Name != null ? m_Killer.Name.ToString() : "Unknown", m_Killer.Amount); // ~1_NAME~ Killer: +~2_val~%
  
  			if (m_Protection != null && !m_Protection.IsEmpty && m_Protection.Amount > 0)
  				list.Add(1072387, "{0}\t{1}", m_Protection.Name != null ? m_Protection.Name.ToString() : "Unknown", m_Protection.Amount); // ~1_NAME~ Protection: +~2_val~%
  
  			if (m_ExceptionalBonus != 0)
  				list.Add(1072395, "#{0}\t{1}", AosSkillBonuses.GetLabel( m_Skill ), m_ExceptionalBonus); // ~1_NAME~ Exceptional Bonus: ~2_val~%
  
  			if (m_SuccessBonus != 0)
  				list.Add(1072394, "#{0}\t{1}", AosSkillBonuses.GetLabel( m_Skill ), m_SuccessBonus); // ~1_NAME~ Bonus: ~2_val~%
  
  			m_AosSkillBonuses.GetProperties(list);
  
  			int prop;
  
  			if ((prop = m_AosAttributes.WeaponDamage) != 0)
  				list.Add(1060401, prop.ToString()); // damage increase ~1_val~%
  
  			if ((prop = m_AosAttributes.DefendChance) != 0)
  				list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~%
  
  			if ((prop = m_AosAttributes.BonusDex) != 0)
  				list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~
  
  			if ((prop = m_AosAttributes.EnhancePotions) != 0)
  				list.Add(1060411, prop.ToString()); // enhance potions ~1_val~%
  
  			if ((prop = m_AosAttributes.CastRecovery) != 0)
  				list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~
  
  			if ((prop = m_AosAttributes.CastSpeed) != 0)
  				list.Add(1060413, prop.ToString()); // faster casting ~1_val~
  
  			if ((prop = m_AosAttributes.AttackChance) != 0)
  				list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~%
  
  			if ((prop = m_AosAttributes.BonusHits) != 0)
  				list.Add(1060431, prop.ToString()); // hit point increase ~1_val~
  
  			if ((prop = m_AosAttributes.BonusInt) != 0)
  				list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~
  
  			if ((prop = m_AosAttributes.LowerManaCost) != 0)
  				list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~%
  
  			if ((prop = m_AosAttributes.LowerRegCost) != 0)
  				list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~%
  
  			if ((prop = m_AosAttributes.Luck) != 0)
  				list.Add(1060436, prop.ToString()); // luck ~1_val~
  
  			if ((prop = m_AosAttributes.BonusMana) != 0)
  				list.Add(1060439, prop.ToString()); // mana increase ~1_val~
  
  			if ((prop = m_AosAttributes.RegenMana) != 0)
  				list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~
  
  			if ((prop = m_AosAttributes.NightSight) != 0)
  				list.Add(1060441); // night sight
  
  			if ((prop = m_AosAttributes.ReflectPhysical) != 0)
  				list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~%
  
  			if ((prop = m_AosAttributes.RegenStam) != 0)
  				list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~
  
  			if ((prop = m_AosAttributes.RegenHits) != 0)
  				list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~
  
  			if ((prop = m_AosAttributes.SpellChanneling) != 0)
  				list.Add(1060482); // spell channeling
  
  			if ((prop = m_AosAttributes.SpellDamage) != 0)
  				list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~%
  
  			if ((prop = m_AosAttributes.BonusStam) != 0)
  				list.Add(1060484, prop.ToString()); // stamina increase ~1_val~
  
  			if ((prop = m_AosAttributes.BonusStr) != 0)
  				list.Add(1060485, prop.ToString()); // strength bonus ~1_val~
  
  			if ((prop = m_AosAttributes.WeaponSpeed) != 0)
  				list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~%
  
  			if (Core.ML && (prop = m_AosAttributes.IncreasedKarmaLoss) != 0)
  				list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~%
  
  			if (m_MaxCharges > 0)
  				list.Add(1060741, m_Charges.ToString()); // charges: ~1_val~
  
  			if (m_Slayer != TalismanSlayerName.None)
  				list.Add(1072503 + (int)m_Slayer);
  		}
  
  		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,
  			SkillBonuses = 0x00000002,
  			Owner = 0x00000004,
  			Protection = 0x00000008,
  			Killer = 0x00000010,
  			Summoner = 0x00000020,
  			Removal = 0x00000040,
  			OldKarmaLoss = 0x00000080,
  			Skill = 0x00000100,
  			SuccessBonus = 0x00000200,
  			ExceptionalBonus = 0x00000400,
  			MaxCharges = 0x00000800,
  			Charges = 0x00001000,
  			MaxChargeTime = 0x00002000,
  			ChargeTime = 0x00004000,
  			Blessed = 0x00008000,
  			Slayer = 0x00010000,
  		}
  
  		public override void Serialize(GenericWriter writer)
  		{
  			base.Serialize(writer);
  
  			writer.Write((int)0); // version
  
  			SaveFlag flags = SaveFlag.None;
  
  			SetSaveFlag(ref flags, SaveFlag.Attributes, !m_AosAttributes.IsEmpty);
  			SetSaveFlag(ref flags, SaveFlag.SkillBonuses, !m_AosSkillBonuses.IsEmpty);
  			SetSaveFlag(ref flags, SaveFlag.Protection, m_Protection != null && !m_Protection.IsEmpty);
  			SetSaveFlag(ref flags, SaveFlag.Killer, m_Killer != null && !m_Killer.IsEmpty);
  			SetSaveFlag(ref flags, SaveFlag.Summoner, m_Summoner != null && !m_Summoner.IsEmpty);
  			SetSaveFlag(ref flags, SaveFlag.Removal, m_Removal != TalismanRemoval.None);
  			SetSaveFlag(ref flags, SaveFlag.Skill, (int)m_Skill != 0);
  			SetSaveFlag(ref flags, SaveFlag.SuccessBonus, m_SuccessBonus != 0);
  			SetSaveFlag(ref flags, SaveFlag.ExceptionalBonus, m_ExceptionalBonus != 0);
  			SetSaveFlag(ref flags, SaveFlag.MaxCharges, m_MaxCharges != 0);
  			SetSaveFlag(ref flags, SaveFlag.Charges, m_Charges != 0);
  			SetSaveFlag(ref flags, SaveFlag.MaxChargeTime, m_MaxChargeTime != 0);
  			SetSaveFlag(ref flags, SaveFlag.ChargeTime, m_ChargeTime != 0);
  			SetSaveFlag(ref flags, SaveFlag.Blessed, m_Blessed);
  			SetSaveFlag(ref flags, SaveFlag.Slayer, m_Slayer != TalismanSlayerName.None);
  
  			writer.WriteEncodedInt((int)flags);
  
  			if (GetSaveFlag(flags, SaveFlag.Attributes))
  				m_AosAttributes.Serialize(writer);
  
  			if (GetSaveFlag(flags, SaveFlag.SkillBonuses))
  				m_AosSkillBonuses.Serialize(writer);
  
  			if (GetSaveFlag(flags, SaveFlag.Protection))
  				m_Protection.Serialize(writer);
  
  			if (GetSaveFlag(flags, SaveFlag.Killer))
  				m_Killer.Serialize(writer);
  
  			if (GetSaveFlag(flags, SaveFlag.Summoner))
  				m_Summoner.Serialize(writer);
  
  			if (GetSaveFlag(flags, SaveFlag.Removal))
  				writer.WriteEncodedInt((int)m_Removal);
  
  			if (GetSaveFlag(flags, SaveFlag.Skill))
  				writer.WriteEncodedInt((int)m_Skill);
  
  			if (GetSaveFlag(flags, SaveFlag.SuccessBonus))
  				writer.WriteEncodedInt(m_SuccessBonus);
  
  			if (GetSaveFlag(flags, SaveFlag.ExceptionalBonus))
  				writer.WriteEncodedInt(m_ExceptionalBonus);
  
  			if (GetSaveFlag(flags, SaveFlag.MaxCharges))
  				writer.WriteEncodedInt(m_MaxCharges);
  
  			if (GetSaveFlag(flags, SaveFlag.Charges))
  				writer.WriteEncodedInt(m_Charges);
  
  			if (GetSaveFlag(flags, SaveFlag.MaxChargeTime))
  				writer.WriteEncodedInt(m_MaxChargeTime);
  
  			if (GetSaveFlag(flags, SaveFlag.ChargeTime))
  				writer.WriteEncodedInt(m_ChargeTime);
  
  			if (GetSaveFlag(flags, SaveFlag.Slayer))
  				writer.WriteEncodedInt((int)m_Slayer);
  		}
  
  		public override void Deserialize(GenericReader reader)
  		{
  			base.Deserialize(reader);
  
  			int version = reader.ReadInt();
  
  			switch (version)
  			{
  				case 0:
  					{
  						SaveFlag flags = (SaveFlag)reader.ReadEncodedInt();
  
  						if (GetSaveFlag(flags, SaveFlag.Attributes))
  							m_AosAttributes = new AosAttributes(this, reader);
  						else
  							m_AosAttributes = new AosAttributes(this);
  
  						if (GetSaveFlag(flags, SaveFlag.SkillBonuses))
  							m_AosSkillBonuses = new AosSkillBonuses(this, reader);
  						else
  							m_AosSkillBonuses = new AosSkillBonuses(this);
  
  						// Backward compatibility
  						if (GetSaveFlag(flags, SaveFlag.Owner))
  							BlessedFor = reader.ReadMobile();
  
  						if (GetSaveFlag(flags, SaveFlag.Protection))
  							m_Protection = new TalismanAttribute(reader);
  						else
  							m_Protection = new TalismanAttribute();
  
  						if (GetSaveFlag(flags, SaveFlag.Killer))
  							m_Killer = new TalismanAttribute(reader);
  						else
  							m_Killer = new TalismanAttribute();
  
  						if (GetSaveFlag(flags, SaveFlag.Summoner))
  							m_Summoner = new TalismanAttribute(reader);
  						else
  							m_Summoner = new TalismanAttribute();
  
  						if (GetSaveFlag(flags, SaveFlag.Removal))
  							m_Removal = (TalismanRemoval)reader.ReadEncodedInt();
  
  						if (GetSaveFlag(flags, SaveFlag.OldKarmaLoss))
  							m_AosAttributes.IncreasedKarmaLoss = reader.ReadEncodedInt();
  
  						if (GetSaveFlag(flags, SaveFlag.Skill))
  							m_Skill = (SkillName)reader.ReadEncodedInt();
  
  						if (GetSaveFlag(flags, SaveFlag.SuccessBonus))
  
gt: 							m_SuccessBonus = reader.ReadEncodedInt();