context: using Server.Engines.Craft;
  using Server.Gumps;
  using Server.Mobiles;
  using Server.SkillHandlers;
  using Server.Targeting;
  using System;
  using System.Collections.Generic;
  using System.Linq;
  
  namespace Server.Items
  {
      public enum ReforgedPrefix
      {
          None,
          Might,
          Mystic,
          Animated,
          Arcane,
          Exquisite,
          Vampiric,
          Invigorating,
          Fortified,
          Auspicious,
          Charmed,
          Vicious,
          Towering
      }
  
      public enum ReforgedSuffix
      {
          None,
          Vitality,
          Sorcery,
          Haste,
          Wizadry,
          Quality,
          Vampire,
          Restoration,
          Defense,
          Fortune,
          Alchemy,
          Slaughter,
          Aegis,
          Blackthorn,
          Minax,
          Kotl,
          Khaldun,
          Doom,
          EnchantedOrigin
      }
  
      public enum ItemPower
      {
          None,
          Minor,
          Lesser,
          Greater,
          Major,
          LesserArtifact,
          GreaterArtifact,
          MajorArtifact,
          LegendaryArtifact,
          ReforgedMinor,
          ReforgedLesser,
          ReforgedGreater,
          ReforgedMajor,
          ReforgedLegendary
      }
  
      public static class RunicReforging
      {
          public static bool CanReforge(Mobile from, Item item, CraftSystem crsystem)
          {
              CraftItem crItem = null;
              bool allowableSpecial = m_AllowableTable.ContainsKey(item.GetType());
  
              if (!allowableSpecial)
              {
                  foreach (CraftSystem system in CraftSystem.Systems)
                  {
                      if (system == crsystem && system != null && system.CraftItems != null)
                          crItem = system.CraftItems.SearchFor(item.GetType());
  
                      if (crItem != null)
                          break;
  
                  }
              }
  
              if (crItem == null && !allowableSpecial)
              {
                  from.SendLocalizedMessage(1152279); // You cannot re-forge that item with this tool.
                  return false;
              }
  
              bool goodtogo = true;
              int mods = GetTotalMods(item);
              int maxmods = item is JukaBow ||
                  (item is BaseWeapon && !((BaseWeapon)item).DImodded) ||
                  (item is BaseArmor && ((BaseArmor)item).ArmorAttributes.MageArmor > 0 && BaseArmor.IsMageArmorType((BaseArmor)item)) ? 1 : 0;
  
              if (item is BaseWeapon &&
                  (((BaseWeapon)item).AosElementDamages[AosElementAttribute.Fire] > 0 ||
                  ((BaseWeapon)item).AosElementDamages[AosElementAttribute.Cold] > 0 ||
                  ((BaseWeapon)item).AosElementDamages[AosElementAttribute.Poison] > 0 ||
                  ((BaseWeapon)item).AosElementDamages[AosElementAttribute.Energy] > 0))
              {
                  mods++;
              }
  
              if (mods > maxmods)
                  goodtogo = false;
              else if (m_AllowableTable.ContainsKey(item.GetType()) && m_AllowableTable[item.GetType()] != crsystem)
                  goodtogo = false;
              else if (item is IResource && !CraftResources.IsStandard(((IResource)item).Resource))
                  goodtogo = false;
              else if (item.LootType == LootType.Blessed || item.LootType == LootType.Newbied)
                  goodtogo = false;
              else if (item is BaseWeapon && Server.Spells.Mysticism.EnchantSpell.IsUnderSpellEffects(from, (BaseWeapon)item))
                  goodtogo = false;
              else if (item is BaseWeapon && ((BaseWeapon)item).FocusWeilder != null)
                  goodtogo = false;
              else if (!allowableSpecial && ((item is BaseWeapon && !((BaseWeapon)item).PlayerConstructed) || (item is BaseArmor && !((BaseArmor)item).PlayerConstructed)))
                  goodtogo = false;
              else if (!allowableSpecial && item is BaseClothing && !(item is BaseHat))
                  goodtogo = false;
              else if (Imbuing.IsInNonImbueList(item.GetType()))
                  goodtogo = false;
  
              if (!goodtogo)
                  from.SendLocalizedMessage(1152113); // You cannot reforge that item.
  
              return goodtogo;
          }
  
          public static void ApplyReforgedProperties(Item item, List<int> props, ReforgedPrefix prefix, ReforgedSuffix suffix, int budget, int perclow, int perchigh, int maxmods, int luckChance)
          {
              ApplyReforgedProperties(item, props, prefix, suffix, budget, perclow, perchigh, maxmods, luckChance, null, ReforgingOption.None);
          }
  
          public static void ApplyReforgedProperties(Item item, ReforgedPrefix prefix, ReforgedSuffix suffix, int budget, int perclow, int perchigh, int maxmods, int luckchance, BaseRunicTool tool, ReforgingOption option)
          {
              List<int> props = new List<int>(ItemPropertyInfo.LookupLootTable(item));
              ApplyReforgedProperties(item, props, prefix, suffix, budget, perclow, perchigh, maxmods, luckchance, tool, option);
              ColUtility.Free(props);
          }
  
          public static void ApplyReforgedProperties(Item item, List<int> props, ReforgedPrefix prefix, ReforgedSuffix suffix, int budget, int perclow, int perchigh, int maxmods, int luckchance, BaseRunicTool tool, ReforgingOption option)
          {
              bool reforged = tool != null;
              bool powerful = reforged ? (option & ReforgingOption.Powerful) != 0 : IsPowerful(budget);
  
              if (prefix == ReforgedPrefix.None && (suffix == ReforgedSuffix.None || suffix > ReforgedSuffix.Aegis))
              {
                  for (int i = 0; i < maxmods; i++)
                  {
                      ApplyRandomProperty(item, props, perclow, perchigh, ref budget, luckchance, reforged, powerful);
                  }
  
                  if (suffix != ReforgedSuffix.None)
                  {
                      ApplySuffixName(item, suffix);
                  }
              }
              else
              {
                  int prefixID = (int)prefix;
                  int suffixID = (int)suffix;
  
                  int index = GetCollectionIndex(item);
                  int resIndex = -1;
                  int preIndex = -1;
                  // resIndex & preIndex = -1 indicates is not reforged
  
                  if (reforged)
                  {
                      resIndex = GetResourceIndex(tool.Resource);
                      preIndex = GetPrerequisiteIndex(option);
                  }
  
                  if (index == -1)
                      return;
  
                  List<NamedInfoCol> prefixCol = null;
                  List<NamedInfoCol> suffixCol = null;
  
                  if (prefix != ReforgedPrefix.None)
                  {
                      try
                      {
                          prefixCol = new List<NamedInfoCol>();
                          prefixCol.AddRange(m_PrefixSuffixInfo[prefixID][index]);
                      }
                      catch
                      {
                          Console.WriteLine("Error: Prefix not in collection: {0}", prefixID);
                      }
                  }
  
                  if (suffix != ReforgedSuffix.None)
                  {
                      if (suffixCol == null)
                          suffixCol = new List<NamedInfoCol>();
  
                      try
                      {
                          suffixCol.AddRange(m_PrefixSuffixInfo[suffixID][index]);
                      }
                      catch
                      {
                          Console.WriteLine("Error: Suffix not in collection: {0}", suffixID);
                      }
                  }
  
                  //Removes things like blood drinking/balanced/splintering
                  ValidateAttributes(item, prefixCol, reforged);
                  ValidateAttributes(item, suffixCol, reforged);
  
                  int i = 0;
                  int mods = 0;
  
                  if (prefix != ReforgedPrefix.None && suffix == ReforgedSuffix.None && prefixCol != null)
                  {
                      int specialAdd = 0;
                      int nothing = 0;
                      GetNamedModCount(index, prefixID, 0, maxmods, prefixCol.Count, 0, ref specialAdd, ref nothing);
  
                      while (budget > 25 && mods < maxmods && i < 25)
                      {
                          if (prefixCol.Count > 0 && specialAdd > 0)
                          {
                              int random = Utility.Random(prefixCol.Count);
  
                              if (ApplyPrefixSuffixAttribute(item, prefixCol[random], resIndex, preIndex, perclow, perchigh, ref budget, luckchance, reforged, powerful))
                              {
                                  specialAdd--;
                                  mods++;
                              }
  
                              prefixCol.RemoveAt(random);
                          }
                          else if (ApplyRandomProperty(item, props, perclow, perchigh, ref budget, luckchance, reforged, powerful))
                          {
                              mods++;
                          }
  
                          i++;
                      }
  
                      if (prefix != ReforgedPrefix.None)
                      {
                          ApplyPrefixName(item, prefix);
                      }
                  }
                  else if (prefix == ReforgedPrefix.None && suffix != ReforgedSuffix.None && suffixCol != null)
                  {
                      int specialAdd = 0;
                      int nothing = 0;
                      GetNamedModCount(index, 0, suffixID, maxmods, 0, suffixCol.Count, ref nothing, ref specialAdd);
  
                      while (budget > 25 && mods < maxmods && i < 25)
                      {
                          if (suffixCol.Count > 0 && specialAdd > 0)
                          {
                              int random = Utility.Random(suffixCol.Count);
  
                              if (ApplyPrefixSuffixAttribute(item, suffixCol[random], resIndex, preIndex, perclow, perchigh, ref budget, luckchance, reforged, powerful))
                              {
                                  specialAdd--;
                                  mods++;
                              }
  
                              suffixCol.RemoveAt(random);
                          }
                          else if (ApplyRandomProperty(item, props, perclow, perchigh, ref budget, luckchance, reforged, powerful))
                          {
                              mods++;
                          }
  
                          i++;
                      }
  
                      if (suffix != ReforgedSuffix.None)
                          ApplySuffixName(item, suffix);
                  }
                  else if (prefix != ReforgedPrefix.None && suffix != ReforgedSuffix.None && prefixCol != null && suffixCol != null)
                  {
                      int specialAddPrefix = 0;
                      int specialAddSuffix = 0;
  
                      GetNamedModCount(index, prefixID, suffixID, maxmods, prefixCol.Count, suffixCol.Count, ref specialAddPrefix, ref specialAddSuffix);
  
                      while (budget > 25 && mods < maxmods && i < 25)
                      {
                          if (prefixCol.Count > 0 && specialAddPrefix > 0)
                          {
                              int random = Utility.Random(prefixCol.Count);
  
                              if (ApplyPrefixSuffixAttribute(item, prefixCol[random], resIndex, preIndex, perclow, perchigh, ref budget, luckchance, reforged, powerful))
                              {
                                  specialAddPrefix--;
                                  mods++;
                              }
  
                              prefixCol.RemoveAt(random);
                          }
                          else if (suffixCol.Count > 0 && specialAddSuffix > 0)
                          {
                              int random = Utility.Random(suffixCol.Count);
  
                              if (ApplyPrefixSuffixAttribute(item, suffixCol[random], resIndex, preIndex, perclow, perchigh, ref budget, luckchance, reforged, powerful))
                              {
                                  specialAddSuffix--;
                                  mods++;
                              }
  
                              suffixCol.RemoveAt(random);
                          }
                          else if (ApplyRandomProperty(item, props, perclow, perchigh, ref budget, luckchance, reforged, powerful))
                          {
                              mods++;
                          }
  
                          i++;
                      }
  
                      if (prefix != ReforgedPrefix.None)
                          ApplyPrefixName(item, prefix);
  
                      if (suffix != ReforgedSuffix.None)
                          ApplySuffixName(item, suffix);
                  }
  
                  if (_Elements.ContainsKey(item))
                      _Elements.Remove(item);
              }
          }
  
          public static bool HasSelection(int index, Item toreforge, BaseRunicTool tool, ReforgingOption options, int prefix, int suffix)
          {
              // No Vampire prefix/suffix for non-weapons
              if (index == 6 && !(toreforge is BaseWeapon))
                  return false;
  
              // Cannot choose same suffix/prefix
              //if (index != 0 && (index == prefix || index == suffix))
              //    return false;HasOption(options, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulAndFundamental)
  
              ItemType type = ItemPropertyInfo.GetItemType(toreforge);
  
              if (type == ItemType.Melee)
              {
                  switch (tool.Resource)
                  {
                      case CraftResource.DullCopper:
                          if (index == 8 && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.ShadowIron:
                          if (index == 8 && HasOption(options, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental))
                              return false;
                          else if (index >= 8 && index <= 10 && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Copper:
                          if (index == 8 && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental))
                              return false;
                          if (index >= 8 && index <= 10 && HasOption(options, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Bronze:
                          if (index == 8)
                              return false;
                          if (index == 9 && HasOption(options, ReforgingOption.Powerful))
                              return false;
                          if (index >= 8 && index <= 10 && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Gold:
                          if (index == 8)
                              return false;
                          if (index >= 8 && index <= 10 && HasOption(options, ReforgingOption.Powerful, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Agapite:
                      case CraftResource.Verite:
                          if (index >= 8 && index <= 10)
                              return false;
                          if (index == 12 && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Valorite:
                          if (index >= 8 && index <= 10)
                              return false;
                          if (index == 12 && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
  
                      case CraftResource.OakWood:
                          if (index == 8 && HasOption(options, ReforgingOption.StructuralAndFundamental))
                              return false;
                          if (index >= 8 && index <= 10 && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.AshWood:
                          if (index == 8)
                              return false;
                          if (index >= 8 && index <= 10 && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.YewWood:
                          if (index >= 8 && index <= 10)
                              return false;
                          if (index == 12 && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Heartwood:
                          if (index >= 8 && index <= 10)
                              return false;
                          if (index == 12 && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                  }
              }
              else if (type == ItemType.Ranged)
              {
                  switch (tool.Resource)
                  {
                      case CraftResource.OakWood:
                          if (index == 10 && HasOption(options, ReforgingOption.PowerfulAndStructural))
                              return false;
                          if ((index == 8 || index == 10) && HasOption(options, ReforgingOption.PowerfulAndFundamental))
                              return false;
                          if (index >= 8 && index <= 10 && (HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental) || HasOption(options, ReforgingOption.StructuralAndFundamental)))
                              return false;
                          break;
                      case CraftResource.AshWood:
                          if (index == 8 || index == 10)
                              return false;
                          if (index >= 8 && index <= 10 && HasOption(options, ReforgingOption.PowerfulAndStructural))
                              return false;
                          if (index >= 8 && index <= 11 && HasOption(options, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.YewWood:
                          if (index >= 8 && index <= 11)
                              return false;
                          break;
                      case CraftResource.Heartwood:
                          if (index >= 8 && index <= 11)
                              return false;
                          if (index == 12 && HasOption(options, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                  }
              }
              else if (type == ItemType.Shield)
              {
                  if (index == 10)
                      return false;
  
                  switch (tool.Resource)
                  {
                      case CraftResource.DullCopper:
                          if (index == 8 && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.ShadowIron:
                          if (index == 8 && HasOption(options, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental))
                              return false;
                          if ((index == 8 || index == 9) && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Copper:
                          if (index == 8 && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental))
                              return false;
                          else if ((index == 8 || index == 9) && HasOption(options, ReforgingOption.StructuralAndFundamental))
                              return false;
                          else if ((index == 5 || index == 8 || index == 9) && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Bronze:
                          if (index == 8)
                              return false;
                          else if (index == 9 && HasOption(options, ReforgingOption.PowerfulAndStructural))
                              return false;
                          else if ((index == 9 || index == 5) && HasOption(options, ReforgingOption.PowerfulAndFundamental))
                              return false;
                          else if ((index == 9 || index == 5 || index == 11) && HasOption(options, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Gold:
                          if (index == 8)
                              return false;
                          else if (index == 9 && HasOption(options, ReforgingOption.Powerful))
                              return false;
                          else if ((index == 5 || index == 9) && HasOption(options, ReforgingOption.PowerfulAndStructural))
                              return false;
                          else if ((index == 9 || index == 5 || index == 11) && HasOption(options, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Agapite:
                          if (index == 8 || index == 9)
                              return false;
                          else if ((index == 5 || index == 11) && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Verite:
                      case CraftResource.Valorite:
                          if (index == 8 || index == 9 || index == 11)
                              return false;
                          else if (index == 5 && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
  
                      case CraftResource.OakWood:
                          if (index == 8 && HasOption(options, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental))
                              return false;
                          if ((index == 8 || index == 9) && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.AshWood:
                          if (index == 8)
                              return false;
                          else if (index == 9 && HasOption(options, ReforgingOption.PowerfulAndStructural))
                              return false;
                          else if ((index == 9 || index == 5) && HasOption(options, ReforgingOption.PowerfulAndFundamental))
                              return false;
                          else if ((index == 9 || index == 5 || index == 11) && HasOption(options, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.YewWood:
                          if (index == 8 || index == 9)
                              return false;
                          else if ((index == 5 || index == 11) && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Heartwood:
                          if (index == 8 || index == 9 || index == 11)
                              return false;
                          else if (index == 5 && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                  }
              }
              else if (type == ItemType.Armor)
              {
                  switch (tool.Resource)
                  {
                      case CraftResource.DullCopper:
                          if ((index == 10 || index == 11) && HasOption(options, ReforgingOption.PowerfulAndFundamental))
                              return false;
                          else if ((index == 5 || index == 10 || index == 11) && HasOption(options, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.ShadowIron:
                          if ((index == 10 || index == 11) && HasOption(options, ReforgingOption.PowerfulAndStructural))
                              return false;
                          else if ((index == 5 || index == 10 || index == 11) && HasOption(options, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental))
                              return false;
                          else if ((index == 5 || index == 9 || index == 10 || index == 11) && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Copper:
                          if (index == 10 || index == 11)
                              return false;
                          else if (index == 5 && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental))
                              return false;
                          else if ((index == 5 || index == 9) && HasOption(options, ReforgingOption.StructuralAndFundamental))
                              return false;
                          else if ((index == 5 || index == 9 || index == 5) && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Bronze:
                          if (index == 10 || index == 11)
                              return false;
                          else if ((index == 5 || index == 9) && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental))
                              return false;
                          else if ((index == 5 || index == 9 || index == 12) && HasOption(options, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Gold:
                          if (index == 10 || index == 11)
                              return false;
                          else if (index == 9 && HasOption(options, ReforgingOption.Powerful))
                              return false;
                          else if ((index == 5 || index == 9 || index == 12) && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Agapite:
                          if (index >= 9 && index <= 11)
                              return false;
                          else if (index == 12 && HasOption(options, ReforgingOption.Powerful))
                              return false;
                          else if ((index == 12 || index == 5) && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Verite:
                      case CraftResource.Valorite:
                          if (index >= 9 && index <= 12)
                              return false;
                          else if (index == 5 && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
  
                      case CraftResource.SpinedLeather:
                          if ((index == 10 || index == 11) && HasOption(options, ReforgingOption.PowerfulAndStructural))
                              return false;
                          else if ((index == 10 || index == 11 || index == 5) && HasOption(options, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental))
                              return false;
                          else if ((index == 9 || index == 10 || index == 11 || index == 5) && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.HornedLeather:
                          if (index == 10 || index == 11)
                              return false;
                          else if (index == 9 && HasOption(options, ReforgingOption.Powerful))
                              return false;
                          else if ((index == 5 || index == 9 || index == 12) && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.BarbedLeather:
                          if (index >= 9 && index <= 12)
                              return false;
                          else if (index == 5 && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
  
                      case CraftResource.OakWood:
                          if ((index == 10 || index == 11) && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental))
                              return false;
                          else if (index == 9 && HasOption(options, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.AshWood:
                          if (index == 10 || index == 11)
                              return false;
                          else if ((index == 5 || index == 9) && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental))
                              return false;
                          else if ((index == 5 || index == 9 || index == 12) && HasOption(options, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.YewWood:
                          if (index == 9 || index == 10 || index == 11)
                              return false;
                          else if (index == 12 && HasOption(options, ReforgingOption.Powerful))
                              return false;
                          else if ((index == 5 || index == 12) && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                      case CraftResource.Heartwood:
                          if (index >= 9 && index <= 12)
                              return false;
                          else if (index == 5 && HasOption(options, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndStructural, ReforgingOption.PowerfulAndFundamental, ReforgingOption.StructuralAndFundamental, ReforgingOption.PowerfulStructuralAndFundamental))
                              return false;
                          break;
                  }
              }
  
              return true;
          }
  
          public static bool HasOption(ReforgingOption options, params ReforgingOption[] optionArray)
          {
              foreach (ReforgingOption option in optionArray)
              {
                  if ((options & option) == option)
                  {
                      return true;
                  }
              }
  
              return false;
          }
  
          private static void ValidateAttributes(Item item, List<NamedInfoCol> list, bool reforged)
          {
              if (list == null || list.Count == 0)
                  return;
  
              list.IterateReverse(col =>
              {
                  if (col != null && list.Contains(col) && !ItemPropertyInfo.ValidateProperty(item, col.Attribute, reforged))
                  {
                      list.Remove(col);
                  }
              });
          }
  
          private static void GetNamedModCount(int itemIndex, int prefixID, int suffixID, int maxmods, int precolcount, int suffixcolcount, ref int prefixCount, ref int suffixCount)
          {
              if (prefixID > 0 && suffixID > 0)
              {
                  if (0.5 > Utility.RandomDouble())
                  {
                      // Even Split
                      if (0.5 > Utility.RandomDouble())
                      {
                          prefixCount = maxmods / 2;
                          suffixCount = maxmods - prefixCount;
                      }
                      else
                      {
                          suffixCount = maxmods / 2;
                          prefixCount = maxmods - suffixCount;
                      }
                  }
                  else if (0.5 > Utility.RandomDouble())
                  {
                      prefixCount = (maxmods / 2) - 1;
                      suffixCount = maxmods - prefixCount;
                  }
                  else
                  {
                      suffixCount = (maxmods / 2) - 1;
                      prefixCount = maxmods - suffixCount;
                  }
              }
              else
              {
                  int mods = 0;
  
                  switch (maxmods)
                  {
                      default:
                      case 8:
                      case 7: mods = maxmods / 2; break;
                      case 6:
                      case 5:
                      case 4: mods = Utility.RandomBool() ? 2 : 3; break;
                      case 3: mods = Utility.RandomBool() ? 1 : 2; break;
                      case 2:
                      case 1: mods = 1; break;
                  }
  
                  if (prefixID > 0)
                      prefixCount = mods;
                  else
                      suffixCount = mods;
              }
  
              if (prefixCount > precolcount)
                  prefixCount = precolcount;
  
              if (suffixCount > suffixcolcount)
                  suffixCount = suffixcolcount;
          }
  
          public static int GetPropertyCount(BaseRunicTool tool)
          {
              switch (tool.Resource)
              {
                  case CraftResource.DullCopper:
                  case CraftResource.ShadowIron: return Utility.RandomMinMax(1, 2);
                  case CraftResource.Copper: return Utility.RandomMinMax(2, 3);
                  case CraftResource.Bronze:
                  case CraftResource.Gold: return 3;
                  case CraftResource.Agapite:
                  case CraftResource.Verite: return Utility.RandomMinMax(3, 4);
                  case CraftResource.Valorite: return 5;
  
                  case CraftResource.SpinedLeather: return Utility.RandomMinMax(1, 2);
                  case CraftResource.HornedLeather: return 3;
                  case CraftResource.BarbedLeather: return 5;
  
                  case CraftResource.OakWood: return Utility.RandomMinMax(1, 2);
                  case CraftResource.AshWood: return 2;
                  case CraftResource.YewWood: return 3;
                  case CraftResource.Heartwood: return 5;
              }
  
              return 1;
          }
  
          private static bool ApplyPrefixSuffixAttribute(Item item, NamedInfoCol col, int resIndex, int preIndex, int percLow, int percHigh, ref int budget, int luckchance, bool reforged, bool powerful)
          {
              int start = budget;
              object attribute = col.Attribute;
  
              // Converts Collection entry into actual attribute
              if (attribute is string)
              {
                  switch ((string)attribute)
                  {
                      case "RandomEater": attribute = GetRandomEater(); break;
                      case "HitSpell": attribute = GetRandomHitSpell(); break;
                      case "HitArea": attribute = GetRandomHitArea(); break;
                      case "Slayer": attribute = BaseRunicTool.GetRandomSlayer(); break;
                      case "WeaponVelocity": break;
                      case "ElementalDamage": attribute = GetRandomElemental(); break;
                  }
              }
  
              int id = ItemPropertyInfo.GetID(attribute);
  
              // prop is invalid, or the item already has a value for this prop
              if (id == -1 || Imbuing.GetValueForID(item, id) > 0 || !ItemPropertyInfo.ValidateProperty(item, id, reforged))
              {
                  return false;
              }
  
              if (reforged)
              {
                  ApplyReforgedNameProperty(item, id, col, resIndex, preIndex, 0, 100, ref budget, luckchance, reforged, powerful);
              }
              else
              {
                  ApplyProperty(item, id, percLow, percHigh, ref budget, luckchance, reforged, powerful); // TODO: powerful
              }
  
              return start != budget;
          }
  
          private static readonly Dictionary<Item, int[]> _Elements = new Dictionary<Item, int[]>();
  
          public static bool ApplyResistance(Item item, int value, AosElementAttribute attribute)
          {
              AosElementAttributes resists = GetElementalAttributes(item);
  
              if (!_Elements.ContainsKey(item))
              {
                  if (item is BaseArmor)
                  {
                      _Elements[item] = new int[] { ((BaseArmor)item).PhysicalBonus, ((BaseArmor)item).FireBonus, ((BaseArmor)item).ColdBonus, ((BaseArmor)item).PoisonBonus, ((BaseArmor)item).EnergyBonus };
                  }
                  else if (item is BaseWeapon)
                  {
                      _Elements[item] = new int[] { ((BaseWeapon)item).WeaponAttributes.ResistPhysicalBonus, ((BaseWeapon)item).WeaponAttributes.ResistFireBonus,
                              ((BaseWeapon)item).WeaponAttributes.ResistColdBonus, ((BaseWeapon)item).WeaponAttributes.ResistPoisonBonus, ((BaseWeapon)item).WeaponAttributes.ResistEnergyBonus };
                  }
                  else if (resists != null)
                  {
                      _Elements[item] = new int[] { resists[AosElementAttribute.Physical], resists[AosElementAttribute.Fire], resists[AosElementAttribute.Cold],
                          resists[AosElementAttribute.Poison], resists[AosElementAttribute.Energy] };
                  }
                  else
                  {
                      return false;
                  }
              }
  
              switch (attribute)
              {
                  default:
                  case AosElementAttribute.Physical:
                      if (item is BaseArmor && (!_Elements.ContainsKey(item) || ((BaseArmor)item).PhysicalBonus == _Elements[item][0]))
                      {
                          ((BaseArmor)item).PhysicalBonus = value;
                          return true;
                      }
                      else if (item is BaseWeapon && (!_Elements.ContainsKey(item) || ((BaseWeapon)item).WeaponAttributes.ResistPhysicalBonus == _Elements[item][0]))
                      {
                          ((BaseWeapon)item).WeaponAttributes.ResistPhysicalBonus = value;
                          return true;
                      }
                      else if (resists != null && (!_Elements.ContainsKey(item) || resists[attribute] == _Elements[item][0]))
                      {
                          resists[attribute] = value;
                          return true;
                      }
                      break;
                  case AosElementAttribute.Fire:
                      if (item is BaseArmor && (!_Elements.ContainsKey(item) || ((BaseArmor)item).FireBonus == _Elements[item][1]))
                      {
                          ((BaseArmor)item).FireBonus = value;
                          return true;
                      }
                      else if (item is BaseWeapon && (!_Elements.ContainsKey(item) || ((BaseWeapon)item).WeaponAttributes.ResistFireBonus == _Elements[item][1]))
                      {
                          ((BaseWeapon)item).WeaponAttributes.ResistFireBonus = value;
                          return true;
                      }
                      else if (resists != null && (!_Elements.ContainsKey(item) || resists[attribute] == _Elements[item][1]))
                      {
                          resists[attribute] = value;
                          return true;
                      }
                      break;
                  case AosElementAttribute.Cold:
                      if (item is BaseArmor && (!_Elements.ContainsKey(item) || ((BaseArmor)item).ColdBonus == _Elements[item][2]))
                      {
                          ((BaseArmor)item).ColdBonus = value;
                          return true;
                      }
                      else if (item is BaseWeapon && (!_Elements.ContainsKey(item) || ((BaseWeapon)item).WeaponAttributes.ResistColdBonus == _Elements[item][2]))
                      {
                          ((BaseWeapon)item).WeaponAttributes.ResistColdBonus = value;
                          return true;
                      }
                      else if (resists != null && (!_Elements.ContainsKey(item) || resists[attribute] == _Elements[item][2]))
                      {
                          resists[attribute] = value;
                          return true;
                      }
                      break;
                  case AosElementAttribute.Poison:
                      if (item is BaseArmor && (!_Elements.ContainsKey(item) || ((BaseArmor)item).PoisonBonus == _Elements[item][3]))
                      {
                          ((BaseArmor)item).PoisonBonus = value;
                          return true;
                      }
                      else if (item is BaseWeapon && (!_Elements.ContainsKey(item) || ((BaseWeapon)item).WeaponAttributes.ResistPoisonBonus == _Elements[item][3]))
                      {
                          ((BaseWeapon)item).WeaponAttributes.ResistPoisonBonus = value;
                          return true;
                      }
                      else if (resists != null && (!_Elements.ContainsKey(item) || resists[attribute] == _Elements[item][3]))
                      {
                          resists[attribute] = value;
                          return true;
                      }
                      break;
                  case AosElementAttribute.Energy:
                      if (item is BaseArmor && (!_Elements.ContainsKey(item) || ((BaseArmor)item).EnergyBonus == _Elements[item][4]))
                      {
                          ((BaseArmor)item).EnergyBonus = value;
                          return true;
                      }
                      else if (item is BaseWeapon && (!_Elements.ContainsKey(item) || ((BaseWeapon)item).WeaponAttributes.ResistEnergyBonus == _Elements[item][4]))
                      {
                          ((BaseWeapon)item).WeaponAttributes.ResistEnergyBonus = value;
                          return true;
                      }
                      else if (resists != null && (!_Elements.ContainsKey(item) || resists[attribute] == _Elements[item][4]))
                      {
                          resists[attribute] = value;
                          return true;
                      }
                      break;
              }
  
              return false;
          }
  
          public static int Scale(int min, int max, int perclow, int perchigh, int luckchance, bool reforged)
          {
              int percent;
  
              if (reforged)
              {
                  percent = Utility.RandomMinMax(perclow, perchigh);
              }
              else
              {
                  percent = Utility.RandomMinMax(0, perchigh);
              }
  
              if (LootPack.CheckLuck(luckchance))
                  percent += 10;
  
              if (percent < perclow) percent = perclow;
              if (percent > perchigh) percent = perchigh;
  
              int scaledBy = Math.Abs(min - max) + 1;
  
              if (scaledBy != 0)
                  scaledBy = 10000 / scaledBy;
  
              percent *= (10000 + scaledBy);
  
              return min + (((max - min) * percent) / 1000001);
          }
  
          private static int CalculateValue(Item item, object attribute, int min, int max, int perclow, int perchigh, ref int budget, int luckchance)
          {
              return CalculateValue(item, attribute, min, max, perclow, perchigh, ref budget, luckchance, false);
          }
  
          private static int CalculateValue(Item item, object attribute, int min, int max, int perclow, int perchigh, ref int budget, int luckchance, bool reforged)
          {
              int scale = Math.Max(1, ItemPropertyInfo.GetScale(item, attribute));
  
              if (scale > 0 && min < scale)
              {
                  min = scale;
              }
  
              int value = Scale(min, max, perclow, perchigh, luckchance, reforged);
  
              if (scale > 1 && value > scale)
              {
                  value = (value / scale) * scale;
              }
  
              int totalweight = ItemPropertyInfo.GetTotalWeight(item, attribute, value);
  
              while (budget <= totalweight)
              {
                  value -= scale;
  
                  if (value <= 0)
                  {
                      if (ItemPropertyInfo.GetTotalWeight(item, attribute, 3) > budget)
                          budget = 0;
  
                      return 0;
                  }
  
                  totalweight = ItemPropertyInfo.GetTotalWeight(item, attribute, value);
              }
  
              return value;
          }
  
          private static int GetTotalMods(Item item)
          {
              return Imbuing.GetTotalMods(item);
          }
  
          private static ItemPropertyInfo GetItemProps(object attr)
          {
              int id = -1;
  
              if (attr is AosAttribute)
                  id = ItemPropertyInfo.GetIDForAttribute((AosAttribute)attr);
  
              else if (attr is AosWeaponAttribute)
                  id = ItemPropertyInfo.GetIDForAttribute((AosWeaponAttribute)attr);
  
              else if (attr is SkillName)
                  id = ItemPropertyInfo.GetIDForAttribute((SkillName)attr);
  
              else if (attr is SlayerName)
                  id = ItemPropertyInfo.GetIDForAttribute((SlayerName)attr);
  
              else if (attr is SAAbsorptionAttribute)
                  id = ItemPropertyInfo.GetIDForAttribute((SAAbsorptionAttribute)attr);
  
              else if (attr is AosArmorAttribute)
                  id = ItemPropertyInfo.GetIDForAttribute((AosArmorAttribute)attr);
  
              else if (attr is AosElementAttribute)
                  id = ItemPropertyInfo.GetIDForAttribute((AosElementAttribute)attr);
  
              if (ItemPropertyInfo.Table.ContainsKey(id))
                  return ItemPropertyInfo.Table[id];
  
              return null;
          }
  
          private static int GetCollectionIndex(Item item)
          {
              if (item is BaseWeapon)
                  return 0;
              if (item is BaseShield)
                  return 2;
              if (item is BaseArmor || item is BaseClothing)
                  return 1;
              if (item is BaseJewel)
                  return 3;
  
              return -1;
          }
  
          private static int GetResourceIndex(CraftResource resource)
          {
              // RunicIndex 0 - dullcopper; 1 - shadow; 2 - copper; 3 - spined; 4 - Oak; 5 - ash
              switch (resource)
              {
                  default:
                  case CraftResource.DullCopper: return 0;
                  case CraftResource.ShadowIron: return 1;
                  case CraftResource.Bronze:
                  case CraftResource.Gold:
                  case CraftResource.Agapite:
                  case CraftResource.Verite:
                  case CraftResource.Valorite:
                  case CraftResource.Copper: return 2;
                  case CraftResource.SpinedLeather: return 3;
                  case CraftResource.OakWood: return 4;
                  case CraftResource.YewWood:
                  case CraftResource.Heartwood:
                  case CraftResource.Bloodwood:
                  case CraftResource.Frostwood:
                  case CraftResource.HornedLeather:
                  case CraftResource.BarbedLeather:
                  case CraftResource.AshWood: return 5;
              }
          }
  
          private static int GetPrerequisiteIndex(ReforgingOption option)
          {
              if ((option & ReforgingOption.Powerful) != 0 &&
                  (option & ReforgingOption.Structural) != 0 &&
                  (option & ReforgingOption.Fundamental) != 0)
                  return 6;
  
              if ((option & ReforgingOption.Structural) != 0 &&
                  (option & ReforgingOption.Fundamental) != 0)
                  return 5;
  
              if ((option & ReforgingOption.Powerful) != 0 &&
                  (option & ReforgingOption.Structural) != 0)
                  return 4;
  
              if ((option & ReforgingOption.Fundamental) != 0)
                  return 3;
  
              if ((option & ReforgingOption.Structural) != 0)
                  return 2;
  
              if ((option & ReforgingOption.Powerful) != 0)
                  return 1;
  
              return 0;
          }
  
          private static int CalculateMinIntensity(int perclow, int perchi, ReforgingOption option)
          {
              if (option == ReforgingOption.None)
                  return perclow;
  
              return perclow + (int)((perchi - perclow) * (GetPrerequisiteIndex(option) * 5.0 / 100.0));
          }
  
          private static readonly Dictionary<Type, CraftSystem> m_AllowableTable = new Dictionary<Type, CraftSystem>();
          private static readonly Dictionary<int, NamedInfoCol[][]> m_PrefixSuffixInfo = new Dictionary<int, NamedInfoCol[][]>();
  
          public static Dictionary<int, NamedInfoCol[][]> PrefixSuffixInfo => m_PrefixSuffixInfo;
  
          public static void Initialize()
          {
              m_AllowableTable[typeof(LeatherGlovesOfMining)] = DefTailoring.CraftSystem;
              m_AllowableTable[typeof(RingmailGlovesOfMining)] = DefBlacksmithy.CraftSystem;
              m_AllowableTable[typeof(StuddedGlovesOfMining)] = DefTailoring.CraftSystem;
              m_AllowableTable[typeof(JukaBow)] = DefBowFletching.CraftSystem;
              m_AllowableTable[typeof(TribalSpear)] = DefBlacksmithy.CraftSystem;
              m_AllowableTable[typeof(Pickaxe)] = DefBlacksmithy.CraftSystem;
              m_AllowableTable[typeof(Cleaver)] = DefBlacksmithy.CraftSystem;
              m_AllowableTable[typeof(SkinningKnife)] = DefBlacksmithy.CraftSystem;
              m_AllowableTable[typeof(ButcherKnife)] = DefBlacksmithy.CraftSystem;
              m_AllowableTable[typeof(GargishNecklace)] = DefBlacksmithy.CraftSystem;
              m_AllowableTable[typeof(GargishEarrings)] = DefBlacksmithy.CraftSystem;
              m_AllowableTable[typeof(GargishAmulet)] = DefBlacksmithy.CraftSystem;
              m_AllowableTable[typeof(GargishStoneAmulet)] = DefMasonry.CraftSystem;
              m_AllowableTable[typeof(BarbedWhip)] = DefTailoring.CraftSystem;
              m_AllowableTable[typeof(SpikedWhip)] = DefTailoring.CraftSystem;
              m_AllowableTable[typeof(BladedWhip)] = DefTailoring.CraftSystem;
          }
  
          public static void Configure()
          {
              Server.Commands.CommandSystem.Register("GetCreatureScore", AccessLevel.GameMaster, e =>
                  {
                      e.Mobile.BeginTarget(12, false, Server.Targeting.TargetFlags.None, (from, targeted) =>
                          {
                              if (targeted is BaseCreature)
                              {
                                  ((BaseCreature)targeted).PrivateOverheadMessage(Server.Network.MessageType.Regular, 0x25, false, GetDifficultyFor((BaseCreature)targeted).ToString(), e.Mobile.NetState);
                              }
                          });
                  });
  
              // TypeIndex 0 - Weapon; 1 - Armor; 2 - Shield; 3 - Jewels
              // RunicIndex 0 - dullcopper; 1 - shadow; 2 - copper; 3 - spined; 4 - Oak; 5 - ash
              m_PrefixSuffixInfo[0] = null;
              m_PrefixSuffixInfo[1] = new NamedInfoCol[][] 	//Might
  				{
                      new NamedInfoCol[] // Weapon
                      {
                          new NamedInfoCol(AosWeaponAttribute.HitLeechHits, HitsAndManaLeechTable),
                          new NamedInfoCol(AosAttribute.BonusHits, WeaponHitsTable),
                          new NamedInfoCol(AosAttribute.BonusStr, WeaponStrTable),
                          new NamedInfoCol(AosAttribute.RegenHits, WeaponRegenTable),
                      },
  
                      new NamedInfoCol[] // armor
                      {
                          new NamedInfoCol("RandomEater", EaterTable),
                          new NamedInfoCol(AosAttribute.BonusHits, ArmorHitsTable),
                          new NamedInfoCol(AosAttribute.BonusStr, ArmorStrTable),
                          new NamedInfoCol(AosAttribute.RegenHits, ArmorRegenTable),
                      },
  
                      new NamedInfoCol[] // shield
                      {
                          new NamedInfoCol("RandomEater", EaterTable),
                          new NamedInfoCol(AosAttribute.BonusHits, ArmorHitsTable),
                          new NamedInfoCol(AosAttribute.BonusStr, ArmorStrTable),
                          new NamedInfoCol(AosAttribute.RegenHits, ArmorRegenTable),
                      },
  
                      new NamedInfoCol[] // jewels
                      {
                          new NamedInfoCol(AosAttribute.BonusHits, ArmorHitsTable),
                          new NamedInfoCol(AosAttribute.BonusStr, ArmorStrTable),
                      }
                  };
  
  
gt:             m_PrefixSuffixInfo[2] = new NamedInfoCol[][] 	//Mystic