context: #region Header
  // **********
  // ServUO - DefBlacksmithy.cs
  // **********
  #endregion
  
  #region References
  using System;
  
  using Server.Items;
  #endregion
  
  namespace Server.Engines.Craft
  {
  
      public class DefBlacksmithy : CraftSystem
      {
          public override SkillName MainSkill { get { return SkillName.Blacksmith; } }
  
          public override int GumpTitleNumber
          {
              get { return 1044002; } // <CENTER>BLACKSMITHY MENU</CENTER>
          }
  
          private static CraftSystem m_CraftSystem;
  
          public static CraftSystem CraftSystem { get { return m_CraftSystem ?? (m_CraftSystem = new DefBlacksmithy()); } }
  
          public override CraftECA ECA { get { return CraftECA.ChanceMinusSixtyToFourtyFive; } }
  
          public override double GetChanceAtMin(CraftItem item)
          {
              return 0.0; // 0%
          }
  
          private DefBlacksmithy()
              : base(1, 1, 1.25) // base( 1, 2, 1.7 )
          {
              /*
              base( MinCraftEffect, MaxCraftEffect, Delay )
              MinCraftEffect	: The minimum number of time the mobile will play the craft effect
              MaxCraftEffect	: The maximum number of time the mobile will play the craft effect
              Delay			: The delay between each craft effect
              Example: (3, 6, 1.7) would make the mobile do the PlayCraftEffect override
              function between 3 and 6 time, with a 1.7 second delay each time.
              */
          }
  
          private static readonly Type typeofAnvil = typeof(AnvilAttribute);
          private static readonly Type typeofForge = typeof(ForgeAttribute);
  
          public static void CheckAnvilAndForge(Mobile from, int range, out bool anvil, out bool forge)
          {
              anvil = false;
              forge = false;
  
              Map map = from.Map;
  
              if (map == null)
              {
                  return;
              }
  
              IPooledEnumerable eable = map.GetItemsInRange(from.Location, range);
  
              foreach (Item item in eable)
              {
                  Type type = item.GetType();
  
                  bool isAnvil = (type.IsDefined(typeofAnvil, false) || item.ItemID == 4015 || item.ItemID == 4016 ||
                                  item.ItemID == 0x2DD5 || item.ItemID == 0x2DD6);
                  bool isForge = (type.IsDefined(typeofForge, false) || item.ItemID == 4017 ||
                                  (item.ItemID >= 6522 && item.ItemID <= 6569) || item.ItemID == 0x2DD8);
  
                  if (!isAnvil && !isForge)
                  {
                      continue;
                  }
  
                  if ((from.Z + 16) < item.Z || (item.Z + 16) < from.Z || !from.InLOS(item))
                  {
                      continue;
                  }
  
                  anvil = anvil || isAnvil;
                  forge = forge || isForge;
  
                  if (anvil && forge)
                  {
                      break;
                  }
              }
  
              eable.Free();
  
              for (int x = -range; (!anvil || !forge) && x <= range; ++x)
              {
                  for (int y = -range; (!anvil || !forge) && y <= range; ++y)
                  {
                      var tiles = map.Tiles.GetStaticTiles(from.X + x, from.Y + y, true);
  
                      for (int i = 0; (!anvil || !forge) && i < tiles.Length; ++i)
                      {
                          int id = tiles[i].ID;
  
                          bool isAnvil = (id == 4015 || id == 4016 || id == 0x2DD5 || id == 0x2DD6);
                          bool isForge = (id == 4017 || (id >= 6522 && id <= 6569) || id == 0x2DD8);
  
                          if (!isAnvil && !isForge)
                          {
                              continue;
                          }
  
                          if ((from.Z + 16) < tiles[i].Z || (tiles[i].Z + 16) < from.Z ||
                              !from.InLOS(new Point3D(from.X + x, from.Y + y, tiles[i].Z + (tiles[i].Height / 2) + 1)))
                          {
                              continue;
                          }
  
                          anvil = anvil || isAnvil;
                          forge = forge || isForge;
                      }
                  }
              }
          }
  
          public override int CanCraft(Mobile from, BaseTool tool, Type itemType)
          {
              if (tool == null || tool.Deleted || tool.UsesRemaining < 0)
              {
                  return 1044038; // You have worn out your tool!
              }
  
              if (!BaseTool.CheckTool(tool, from))
              {
                  return 1048146; // If you have a tool equipped, you must use that tool.
              }
  
              if (!BaseTool.CheckAccessible(tool, from))
              {
                  return 1044263; // The tool must be on your person to use.
              }
  
              bool anvil, forge;
              CheckAnvilAndForge(from, 2, out anvil, out forge);
  
              if (anvil && forge)
              {
                  return 0;
              }
  
              return 1044267; // You must be near an anvil and a forge to smith items.
          }
  
          public override void PlayCraftEffect(Mobile from)
          {
              // no animation, instant sound
              //if ( from.Body.Type == BodyType.Human && !from.Mounted )
              //	from.Animate( 9, 5, 1, true, false, 0 );
              //new InternalTimer( from ).Start();
              from.PlaySound(0x2A);
          }
  
          // Delay to synchronize the sound with the hit on the anvil
          private class InternalTimer : Timer
          {
              private readonly Mobile m_From;
  
              public InternalTimer(Mobile from)
                  : base(TimeSpan.FromSeconds(0.7))
              {
                  m_From = from;
              }
  
              protected override void OnTick()
              {
                  m_From.PlaySound(0x2A);
              }
          }
  
          public override int PlayEndingEffect(
              Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, bool makersMark, CraftItem item)
          {
              if (toolBroken)
              {
                  from.SendLocalizedMessage(1044038); // You have worn out your tool
              }
  
              if (failed)
              {
                  if (lostMaterial)
                  {
                      return 1044043; // You failed to create the item, and some of your materials are lost.
                  }
  
                  return 1044157; // You failed to create the item, but no materials were lost.
              }
  
              if (quality == 0)
              {
                  return 502785; // You were barely able to make this item.  It's quality is below average.
              }
  
  
gt:             if (makersMark && quality == 2)