context: using System;
  using Server.Engines.Craft;
  using Server.Mobiles;
  using Server.Targeting;
  
  namespace Server.Items
  {
      public abstract class BaseOre : Item
      {
          protected virtual CraftResource DefaultResource { get { return CraftResource.Iron; } }
  
          private CraftResource m_Resource;
  
          [CommandProperty(AccessLevel.GameMaster)]
          public CraftResource Resource
          {
              get
              {
                  return this.m_Resource;
              }
              set
              {
                  this.m_Resource = value;
                  this.InvalidateProperties();
              }
          }
  
          public abstract BaseIngot GetIngot();
  
          public override void Serialize(GenericWriter writer)
          {
              base.Serialize(writer);
  
              writer.Write((int)1); // version
  
              writer.Write((int)this.m_Resource);
          }
  
          public override void Deserialize(GenericReader reader)
          {
              base.Deserialize(reader);
  
              int version = reader.ReadInt();
  
              switch ( version )
              {
                  case 2: // Reset from Resource System
                      this.m_Resource = this.DefaultResource;
                      reader.ReadString();
                      break;
                  case 1:
                      {
                          this.m_Resource = (CraftResource)reader.ReadInt();
                          break;
                      }
                  case 0:
                      {
                          OreInfo info;
  
                          switch ( reader.ReadInt() )
                          {
                              case 0:
                                  info = OreInfo.Iron;
                                  break;
                              case 1:
                                  info = OreInfo.DullCopper;
                                  break;
                              case 2:
                                  info = OreInfo.ShadowIron;
                                  break;
                              case 3:
                                  info = OreInfo.Copper;
                                  break;
                              case 4:
                                  info = OreInfo.Bronze;
                                  break;
                              case 5:
                                  info = OreInfo.Gold;
                                  break;
                              case 6:
                                  info = OreInfo.Agapite;
                                  break;
                              case 7:
                                  info = OreInfo.Verite;
                                  break;
                              case 8:
                                  info = OreInfo.Valorite;
                                  break;
                              default:
                                  info = null;
                                  break;
                          }
  
                          this.m_Resource = CraftResources.GetFromOreInfo(info);
                          break;
                      }
              }
          }
  
          private static int RandomSize()
          {
              double rand = Utility.RandomDouble();
  
              if (rand < 0.12)
                  return 0x19B7;
              else if (rand < 0.18)
                  return 0x19B8;
              else if (rand < 0.25)
                  return 0x19BA;
              else
                  return 0x19B9;
          }
  
          public BaseOre(CraftResource resource)
              : this(resource, 1)
          {
          }
  
          public BaseOre(CraftResource resource, int amount)
              : base(RandomSize())
          {
              this.Stackable = true;
              this.Amount = amount;
              this.Hue = CraftResources.GetHue(resource);
  
              this.m_Resource = resource;
          }
  
          public BaseOre(Serial serial)
              : base(serial)
          {
          }
  
          public override void AddNameProperty(ObjectPropertyList list)
          {
              if (this.Amount > 1)
                  list.Add(1050039, "{0}\t#{1}", this.Amount, 1026583); // ~1_NUMBER~ ~2_ITEMNAME~
              else
                  list.Add(1026583); // ore
          }
  
          public override void GetProperties(ObjectPropertyList list)
          {
              base.GetProperties(list);
  
              if (!CraftResources.IsStandard(this.m_Resource))
              {
                  int num = CraftResources.GetLocalizationNumber(this.m_Resource);
  
                  if (num > 0)
                      list.Add(num);
                  else
                      list.Add(CraftResources.GetName(this.m_Resource));
              }
          }
  
          public override int LabelNumber
          {
              get
              {
                  if (this.m_Resource >= CraftResource.DullCopper && this.m_Resource <= CraftResource.Valorite)
                      return 1042845 + (int)(this.m_Resource - CraftResource.DullCopper);
  
                  return 1042853; // iron ore;
              }
          }
  
          public override void OnDoubleClick(Mobile from)
          {
              if (!this.Movable)
                  return;
  
              if (this.RootParent is BaseCreature)
              {
                  from.SendLocalizedMessage(500447); // That is not accessible
              }
              else if (from.InRange(this.GetWorldLocation(), 2))
              {
                  from.SendLocalizedMessage(501971); // Select the forge on which to smelt the ore, or another pile of ore with which to combine it.
                  from.Target = new InternalTarget(this);
              }
              else
              {
                  from.SendLocalizedMessage(501976); // The ore is too far away.
              }
          }
  
          private class InternalTarget : Target
          {
              private readonly BaseOre m_Ore;
  
              public InternalTarget(BaseOre ore)
                  : base(2, false, TargetFlags.None)
              {
                  this.m_Ore = ore;
              }
  
              private bool IsForge(object obj)
              {
                  if (Core.ML && obj is Mobile && ((Mobile)obj).IsDeadBondedPet)
                      return false;
  
                  if (obj.GetType().IsDefined(typeof(ForgeAttribute), false))
                      return true;
  
                  int itemID = 0;
  
                  if (obj is Item)
                      itemID = ((Item)obj).ItemID;
                  else if (obj is StaticTarget)
                      itemID = ((StaticTarget)obj).ItemID;
  
                  return (itemID == 4017 || (itemID >= 6522 && itemID <= 6569));
              }
  
              protected override void OnTarget(Mobile from, object targeted)
              {
                  if (this.m_Ore.Deleted)
                      return;
  
                  if (!from.InRange(this.m_Ore.GetWorldLocation(), 2))
                  {
                      from.SendLocalizedMessage(501976); // The ore is too far away.
                      return;
                  }
  
                  #region Combine Ore
                  if (targeted is BaseOre)
                  {
                      BaseOre ore = (BaseOre)targeted;
  
                      if (!ore.Movable)
                      {
                          return;
                      }
                      else if (this.m_Ore == ore)
                      {
                          from.SendLocalizedMessage(501972); // Select another pile or ore with which to combine this.
                          from.Target = new InternalTarget(ore);
                          return;
                      }
                      else if (ore.Resource != this.m_Ore.Resource)
                      {
                          from.SendLocalizedMessage(501979); // You cannot combine ores of different metals.
                          return;
                      }
  
                      int worth = ore.Amount;
  
                      if (ore.ItemID == 0x19B9)
                          worth *= 8;
                      else if (ore.ItemID == 0x19B7)
                          worth *= 2;
                      else
                          worth *= 4;
  
                      int sourceWorth = this.m_Ore.Amount;
  
  
gt:                     if (this.m_Ore.ItemID == 0x19B9)