context: using Server.Commands;
  using Server.Engines.Craft;
  using Server.Gumps;
  using Server.Items;
  using Server.Mobiles;
  using Server.Network;
  using Server.Targeting;
  using System;
  using System.Collections.Generic;
  using System.Linq;
  
  namespace Server.SkillHandlers
  {
      public class Imbuing
      {
          public static void Initialize()
          {
              SkillInfo.Table[(int)SkillName.Imbuing].Callback = new SkillUseCallback(OnUse);
  
              CommandSystem.Register("GetTotalWeight", AccessLevel.GameMaster, new CommandEventHandler(GetTotalWeight_OnCommand));
              CommandSystem.Register("GetTotalMods", AccessLevel.GameMaster, new CommandEventHandler(GetTotalMods_OnCommand));
          }
  
          private static void OnLogin(LoginEventArgs e)
          {
              if (!e.Mobile.CanBeginAction(typeof(Imbuing)))
                  e.Mobile.EndAction(typeof(Imbuing));
          }
  
          private static readonly Dictionary<Mobile, ImbuingContext> m_ContextTable = new Dictionary<Mobile, ImbuingContext>();
          public static Dictionary<Mobile, ImbuingContext> ContextTable => m_ContextTable;
  
          public static TimeSpan OnUse(Mobile from)
          {
              if (!from.Alive)
              {
                  from.SendLocalizedMessage(500949); //You can't do that when you're dead.
              }
              else if (from is PlayerMobile)
              {
                  from.CloseGump(typeof(ImbuingGump));
                  BaseGump.SendGump(new ImbuingGump((PlayerMobile)from));
                  from.BeginAction(typeof(Imbuing));
              }
  
              return TimeSpan.FromSeconds(1.0);
          }
  
          public static ImbuingContext GetContext(Mobile m)
          {
              if (!m_ContextTable.ContainsKey(m))
              {
                  ImbuingContext context = new ImbuingContext(m);
                  m_ContextTable[m] = context;
                  return context;
              }
  
              return m_ContextTable[m];
          }
  
          public static void AddContext(Mobile from, ImbuingContext context)
          {
              m_ContextTable[from] = context;
          }
  
          public static bool CanImbueItem(Mobile from, Item item)
          {
              if (!CheckSoulForge(from, 2))
              {
                  return false;
              }
              if (item == null || !item.IsChildOf(from.Backpack))
              {
                  from.SendLocalizedMessage(1079575);  // The item must be in your backpack to imbue it.
              }
              else if (item.LootType == LootType.Blessed || item.LootType == LootType.Newbied)
              {
                  from.SendLocalizedMessage(1080438);  // You cannot imbue a blessed item.
              }
              else if (item is BaseWeapon && Spells.Mysticism.EnchantSpell.IsUnderSpellEffects(from, (BaseWeapon)item))
              {
                  from.SendLocalizedMessage(1080130);  // You cannot imbue an item that is currently enchanted.
              }
              else if (item is BaseWeapon && ((BaseWeapon)item).FocusWeilder != null)
              {
                  from.SendLocalizedMessage(1080444);  //You cannot imbue an item that is under the effects of the ninjitsu focus attack ability.
              }
              else if (IsSpecialItem(item))
              {
                  from.SendLocalizedMessage(1079576); // You cannot imbue this item.
              }
              else if (item.GetType() == typeof(JukaBow))
              {
                  if (((JukaBow)item).IsModified)
                      from.SendLocalizedMessage(1079576); // You cannot imbue this item.
                  else
                      return true;
              }
              else if (item is BaseJewel && !(item is BaseRing) && !(item is BaseBracelet))
              {
                  from.SendLocalizedMessage(1079576); // You cannot imbue this item.
              }
              else if (IsInNonImbueList(item.GetType()))
              {
                  from.SendLocalizedMessage(1079576); // You cannot imbue this item.
              }
              else
              {
                  return true;
              }
  
              return false;
          }
  
          public static bool OnBeforeImbue(Mobile from, Item item, int id, int value)
          {
              return OnBeforeImbue(from, item, id, value, GetTotalMods(item, id), GetMaxProps(item), GetTotalWeight(item, id, false, true), Imbuing.GetMaxWeight(item));
          }
  
          public static bool OnBeforeImbue(Mobile from, Item item, int id, int value, int totalprops, int maxprops, int totalitemweight, int maxweight)
          {
              if (totalprops >= maxprops || totalitemweight > maxweight)
              {
                  from.SendLocalizedMessage(1079772); // You cannot imbue this item with any more item properties.
                  from.CloseGump(typeof(ImbueGump));
                  from.EndAction(typeof(Imbuing));
                  return false;
              }
  
              return true;
          }
  
          public static bool CanUnravelItem(Mobile from, Item item, bool message = true)
          {
              if (!CheckSoulForge(from, 2, false, false))
              {
                  from.SendLocalizedMessage(1080433); // You must be near a soulforge to magically unravel an item.
              }
              else if (!item.IsChildOf(from.Backpack))
              {
                  if (message)
                      from.SendLocalizedMessage(1080424);  // The item must be in your backpack to magically unravel it.
              }
              else if (item.LootType == LootType.Blessed || item.LootType == LootType.Newbied)
              {
                  if (message)
                      from.SendLocalizedMessage(1080421);  // You cannot unravel the magic of a blessed item.
              }
              else if (!(item is BaseWeapon || item is BaseArmor || item is BaseJewel || item is BaseHat))
              {
                  if (message)
                      from.SendLocalizedMessage(1080425); // You cannot magically unravel this item.
              }
              else if (item is BaseWeapon && Spells.Mysticism.EnchantSpell.IsUnderSpellEffects(from, (BaseWeapon)item))
              {
                  if (message)
                      from.SendLocalizedMessage(1080427);  // You cannot magically unravel an item that is currently enchanted.
              }
              else if (item is BaseWeapon && ((BaseWeapon)item).FocusWeilder != null)
              {
                  if (message)
                      from.SendLocalizedMessage(1080445); //You cannot magically unravel an item that is under the effects of the ninjitsu focus attack ability.
              }
              else
              {
                  return true;
              }
  
              return false;
          }
  
          public static bool IsSpecialItem(Item item)
          {
              if (item == null)
                  return true;
  
              if (IsSpecialImbuable(item))
                  return false;
  
              if (item.IsArtifact)
                  return true;
  
              if (RunicReforging.GetArtifactRarity(item) > 0)
                  return true;
  
              if (NonCraftableImbuable(item))
                  return false;
  
              foreach (CraftSystem system in CraftSystem.Systems)
              {
                  CraftItem crItem = null;
  
                  if (system != null && system.CraftItems != null)
                      crItem = system.CraftItems.SearchFor(item.GetType());
  
                  if (crItem != null)
                      return false;
              }
  
              return true;
          }
  
          private static bool IsSpecialImbuable(Item item)
          {
              return IsSpecialImbuable(item.GetType());
          }
  
          private static bool IsSpecialImbuable(Type type)
          {
              if (_SpecialImbuable.Any(i => i == type))
                  return true;
  
              if (type.IsSubclassOf(typeof(BaseGlovesOfMining)) || typeof(IFishingAttire).IsAssignableFrom(type))
                  return true;
  
              return false;
          }
  
          private static readonly Type[] _SpecialImbuable =
         {
              typeof(ClockworkLeggings), typeof(GargishClockworkLeggings), typeof(OrcishKinMask), typeof(SavageMask), typeof(VirtuososArmbands),
              typeof(VirtuososCap), typeof(VirtuososCollar), typeof(VirtuososEarpieces), typeof(VirtuososKidGloves), typeof(VirtuososKilt),
              typeof(VirtuososNecklace), typeof(VirtuososTunic), typeof(BestialArms), typeof(BestialEarrings), typeof(BestialGloves), typeof(BestialGorget),
              typeof(BestialHelm), typeof(BestialKilt), typeof(BestialLegs), typeof(BestialNecklace), typeof(BarbedWhip), typeof(BladedWhip),
              typeof(SpikedWhip), typeof(SkullGnarledStaff), typeof(GargishSkullGnarledStaff), typeof(SkullLongsword), typeof(GargishSkullLongsword), typeof(JukaBow)
          };
  
          private static readonly Type[] _NonCraftables =
          {
              typeof(SilverRing), typeof(SilverBracelet)
          };
  
          public static bool NonCraftableImbuable(Item item)
          {
              if (item is BaseWand)
                  return true;
  
              Type type = item.GetType();
  
              foreach (Type t in _NonCraftables)
              {
                  if (t == type)
                      return true;
              }
  
              return false;
          }
  
          public static double GetSuccessChance(Mobile from, Item item, int totalItemIntensity, int propintensity, double bonus)
          {
              double skill = from.Skills[SkillName.Imbuing].Value;
              double resultWeight = totalItemIntensity + propintensity;
  
              double e = Math.E;
              double a, b, c, w;
              double i = item is BaseJewel ? 0.9162 : 1.0;
  
              // - Racial Bonus - SA ONLY -
              if (from.Race == Race.Gargoyle)
              {
                  a = 1362.281555;
                  b = 66.32801518;
                  c = 235.2223147;
                  w = -1481.037561;
              }
              else
              {
                  a = 1554.96118;
                  b = 53.81743328;
                  c = 230.0038452;
                  w = -1664.857794;
              }
  
              // Royal City Bonus, Fluctuation - Removed as EA doesn't seem to fluctuate despite stratics posts
              /*if (bonus == 0.02)
              {
                  if (totalItemIntensity < 295)
                  {
                      bonus = (double)Utility.RandomMinMax(190, 210) / 100.0;
                  }
              }*/
  
              return Math.Max(0, Math.Round(Math.Floor(20 * skill + 10 * a * Math.Pow(e, (b / (resultWeight + c))) + 10 * w - 2400) / 1000 * (i) + bonus, 3) * 100);
          }
  
          public static int GetQualityBonus(Item item)
          {
              IQuality quality = item as IQuality;
  
              if (quality != null)
              {
                  if (quality.Quality == ItemQuality.Exceptional)
                      return 20;
  
                  if (quality.PlayerConstructed)
                      return 10;
              }
  
              return 0;
          }
  
          /// <summary>
          /// Imbues Item with selected id
          /// </summary>
          /// <param name="from">Player Imbuing</param>
          /// <param name="i">Item to be imbued</param>
          /// <param name="id">id to be imbued, see m_Table</param>
          /// <param name="value">value for id</param>
          public static void TryImbueItem(Mobile from, Item i, int id, int value)
          {
              double bonus = 0.0;
  
              if (!CheckSoulForge(from, 2, out bonus))
                  return;
  
              ImbuingContext context = Imbuing.GetContext(from);
  
              context.LastImbued = i;
              context.Imbue_Mod = id;
              context.Imbue_ModInt = value;
  
              ItemPropertyInfo def = ItemPropertyInfo.GetInfo(id);
  
              if (def == null)
                  return;
  
              Type gem = def.GemRes;
              Type primary = def.PrimaryRes;
              Type special = def.SpecialRes;
  
              context.Imbue_ModVal = def.Weight;
  
              int gemAmount = GetGemAmount(i, id, value);
              int primResAmount = GetPrimaryAmount(i, id, value);
              int specResAmount = GetSpecialAmount(i, id, value);
  
              if (from.AccessLevel == AccessLevel.Player &&
                  (from.Backpack == null || from.Backpack.GetAmount(gem) < gemAmount ||
                  from.Backpack.GetAmount(primary) < primResAmount ||
                  from.Backpack.GetAmount(special) < specResAmount))
                  from.SendLocalizedMessage(1079773); //You do not have enough resources to imbue this item.     
              else
              {
                  int maxWeight = GetMaxWeight(i);
                  context.Imbue_IWmax = maxWeight;
  
                  int trueWeight = GetTotalWeight(i, id, true, true);
                  int imbuingWeight = GetTotalWeight(i, id, false, true);
                  int totalItemMods = GetTotalMods(i, id);
                  int maxint = ItemPropertyInfo.GetMaxIntensity(i, id, true);
  
                  int propImbuingweight = (int)((def.Weight / (double)maxint) * value);
                  int propTrueWeight = (int)((propImbuingweight / (double)def.Weight) * 100);
  
                  if ((imbuingWeight + propImbuingweight) > maxWeight)
                  {
                      from.SendLocalizedMessage(1079772); // You cannot imbue this item with any more item properties.
                      from.CloseGump(typeof(ImbueGump));
                      return;
                  }
  
                  double skill = from.Skills[SkillName.Imbuing].Value;
                  double success = GetSuccessChance(from, i, trueWeight, propTrueWeight, bonus);
  
                  if (TimesImbued(i) < 20 && skill < from.Skills[SkillName.Imbuing].Cap)
                  {
                      double s = Math.Min(100, success);
                      double mins = 120 - (s * 1.2);
                      double maxs = Math.Max(120 / (s / 100), skill);
  
                      from.CheckSkill(SkillName.Imbuing, mins, maxs);
                  }
  
                  success /= 100;
  
                  Effects.SendPacket(from, from.Map, new GraphicalEffect(EffectType.FixedFrom, from.Serial, Server.Serial.Zero, 0x375A, from.Location, from.Location, 1, 17, true, false));
                  Effects.SendTargetParticles(from, 0, 1, 0, 0x1593, EffectLayer.Waist);
  
                  if (success >= Utility.RandomDouble() || id < 0 || id > 180)
                  {
                      if (from.AccessLevel == AccessLevel.Player)
                      {
                          from.Backpack.ConsumeTotal(gem, gemAmount);
                          from.Backpack.ConsumeTotal(primary, primResAmount);
  
                          if (specResAmount > 0)
                              from.Backpack.ConsumeTotal(special, specResAmount);
                      }
  
  
                      ImbueItem(from, i, id, value);
                  }
                  else
                  {
                      // This is consumed regardless of success/fail
                      if (from.AccessLevel == AccessLevel.Player)
                      {
                          from.Backpack.ConsumeTotal(primary, primResAmount);
                      }
  
                      from.SendLocalizedMessage(1079774); // You attempt to imbue the item, but fail.
                      from.PlaySound(0x1E4);
                  }
              }
  
              from.EndAction(typeof(Imbuing));
          }
  
          public static void ImbueItem(Mobile from, Item item, int id, int value)
          {
              from.SendLocalizedMessage(1079775); // You successfully imbue the item!
              from.PlaySound(0x1EB);
  
              if (item is BaseWeapon)
              {
                  BaseWeapon wep = (BaseWeapon)item;
  
                  // New property replaces the old one, so lets set them all to 0
                  if (id >= 30 && id <= 34)
                  {
                      wep.WeaponAttributes.HitPhysicalArea = 0;
                      wep.WeaponAttributes.HitFireArea = 0;
                      wep.WeaponAttributes.HitColdArea = 0;
                      wep.WeaponAttributes.HitPoisonArea = 0;
                      wep.WeaponAttributes.HitEnergyArea = 0;
                  }
                  else if (id >= 35 && id <= 39)
                  {
                      wep.WeaponAttributes.HitMagicArrow = 0;
                      wep.WeaponAttributes.HitHarm = 0;
                      wep.WeaponAttributes.HitFireball = 0;
                      wep.WeaponAttributes.HitLightning = 0;
                      wep.WeaponAttributes.HitDispel = 0;
                  }
              }
  
              if (item is BaseJewel && id >= 151 && id <= 183)
              {
                  BaseJewel jewel = (BaseJewel)item;
                  SkillName[] group = GetSkillGroup((SkillName)ItemPropertyInfo.GetAttribute(id));
  
                  //Removes skill bonus if that group already exists on the item
                  for (int j = 0; j < 5; j++)
                  {
                      if (jewel.SkillBonuses.GetBonus(j) > 0 && group.Any(sk => sk == jewel.SkillBonuses.GetSkill(j)))
                      {
                          jewel.SkillBonuses.SetBonus(j, 0.0);
                          jewel.SkillBonuses.SetSkill(j, SkillName.Alchemy);
                      }
                  }
              }
  
              SetProperty(item, id, value);
  
              // Sets DImodded, which is used in BaseWeapon
              if (item is BaseWeapon && id == 12 && !((BaseWeapon)item).DImodded)
              {
                  ((BaseWeapon)item).DImodded = true;
              }
  
              // removes nom-imbued Imbuing value, which changes the way the items total weight is calculated
              if (id >= 51 && id <= 55)
              {
                  if (item is BaseArmor)
                  {
                      BaseArmor arm = (BaseArmor)item;
  
                      switch (id)
                      {
                          case 51: arm.PhysNonImbuing = 0; break;
                          case 52: arm.FireNonImbuing = 0; break;
                          case 53: arm.ColdNonImbuing = 0; break;
                          case 54: arm.PoisonNonImbuing = 0; break;
                          case 55: arm.EnergyNonImbuing = 0; break;
                      }
                  }
                  else if (item is BaseClothing)
                  {
                      BaseClothing hat = (BaseClothing)item;
  
                      switch (id)
                      {
                          case 51: hat.PhysNonImbuing = 0; break;
                          case 52: hat.FireNonImbuing = 0; break;
                          case 53: hat.ColdNonImbuing = 0; break;
                          case 54: hat.PoisonNonImbuing = 0; break;
                          case 55: hat.EnergyNonImbuing = 0; break;
                      }
                  }
              }
  
              if (item is IImbuableEquipement)
              {
                  IImbuableEquipement imbuable = (IImbuableEquipement)item;
  
                  imbuable.OnAfterImbued(from, id, value);
                  imbuable.TimesImbued++;
              }
  
              // jewels get hits set to 255
              if (item is BaseJewel && ((BaseJewel)item).MaxHitPoints <= 0)
              {
                  ((BaseJewel)item).MaxHitPoints = 255;
                  ((BaseJewel)item).HitPoints = 255;
              }
  
              // Removes self repair
              AosArmorAttributes armorAttrs = RunicReforging.GetAosArmorAttributes(item);
  
              if (armorAttrs != null)
              {
                  armorAttrs.SelfRepair = 0;
              }
              else
              {
                  AosWeaponAttributes wepAttrs = RunicReforging.GetAosWeaponAttributes(item);
  
                  if (wepAttrs != null)
                  {
                      wepAttrs.SelfRepair = 0;
                  }
              }
          }
  
          public static void SetProperty(Item item, int id, int value)
          {
              object prop = ItemPropertyInfo.GetAttribute(id);
  
              if (item is BaseWeapon)
              {
                  BaseWeapon wep = item as BaseWeapon;
  
                  if (prop is AosAttribute)
                  {
                      AosAttribute attr = (AosAttribute)prop;
  
                      if (attr == AosAttribute.SpellChanneling)
                      {
                          wep.Attributes.SpellChanneling = value;
  
                          if (value > 0 && wep.Attributes.CastSpeed >= 0)
                              wep.Attributes.CastSpeed -= 1;
                      }
                      else if (attr == AosAttribute.CastSpeed)
                      {
                          wep.Attributes.CastSpeed += value;
                      }
                      else
                      {
                          wep.Attributes[attr] = value;
                      }
                  }
                  else if (prop is AosWeaponAttribute)
                  {
                      wep.WeaponAttributes[(AosWeaponAttribute)prop] = value;
                  }
  
                  else if (prop is SlayerName)
                  {
                      wep.Slayer = (SlayerName)prop;
                  }
                  else if (prop is SAAbsorptionAttribute)
                  {
                      wep.AbsorptionAttributes[(SAAbsorptionAttribute)prop] = value;
                  }
                  else if (prop is AosElementAttribute)
                  {
                      int fire, phys, cold, nrgy, pois, chaos, direct;
  
                      wep.GetDamageTypes(null, out phys, out fire, out cold, out pois, out nrgy, out chaos, out direct);
  
                      value = Math.Min(phys, value);
  
                      wep.AosElementDamages[(AosElementAttribute)prop] = value;
                      wep.Hue = wep.GetElementalDamageHue();
                  }
                  else if (prop is string && wep is BaseRanged && (string)prop == "WeaponVelocity")
                  {
                      ((BaseRanged)wep).Velocity = value;
                  }
              }
              else if (item is BaseShield)
              {
                  BaseShield shield = item as BaseShield;
  
                  if (prop is AosWeaponAttribute && (AosWeaponAttribute)prop == AosWeaponAttribute.DurabilityBonus)
                  {
                      prop = AosArmorAttribute.DurabilityBonus;
                  }
  
                  if (prop is AosAttribute)
                  {
                      AosAttribute attr = (AosAttribute)prop;
  
                      if (attr == AosAttribute.SpellChanneling)
                      {
                          shield.Attributes.SpellChanneling = value;
  
                          if (value > 0 && shield.Attributes.CastSpeed >= 0)
                              shield.Attributes.CastSpeed -= 1;
                      }
                      else if (attr == AosAttribute.CastSpeed)
                      {
                          shield.Attributes.CastSpeed += value;
                      }
                      else
                      {
                          shield.Attributes[attr] = value;
                      }
                  }
                  else if (prop is AosElementAttribute)
                  {
                      AosElementAttribute attr = (AosElementAttribute)prop;
  
                      switch (attr)
                      {
                          case AosElementAttribute.Physical: shield.PhysicalBonus = value; break;
                          case AosElementAttribute.Fire: shield.FireBonus = value; break;
                          case AosElementAttribute.Cold: shield.ColdBonus = value; break;
                          case AosElementAttribute.Poison: shield.PoisonBonus = value; break;
                          case AosElementAttribute.Energy: shield.EnergyBonus = value; break;
                      }
                  }
                  else if (prop is SAAbsorptionAttribute)
                  {
                      shield.AbsorptionAttributes[(SAAbsorptionAttribute)prop] = value;
                  }
                  else if (prop is AosArmorAttribute)
                  {
                      shield.ArmorAttributes[(AosArmorAttribute)prop] = value;
                  }
              }
              else if (item is BaseArmor)
              {
                  BaseArmor arm = item as BaseArmor;
  
                  if (prop is AosWeaponAttribute && (AosWeaponAttribute)prop == AosWeaponAttribute.DurabilityBonus)
                  {
                      prop = AosArmorAttribute.DurabilityBonus;
                  }
  
                  if (prop is AosAttribute)
                  {
                      arm.Attributes[(AosAttribute)prop] = value;
                  }
                  else if (prop is AosElementAttribute)
                  {
                      AosElementAttribute attr = (AosElementAttribute)prop;
  
                      switch (attr)
                      {
                          case AosElementAttribute.Physical: arm.PhysicalBonus = value; break;
                          case AosElementAttribute.Fire: arm.FireBonus = value; break;
                          case AosElementAttribute.Cold: arm.ColdBonus = value; break;
                          case AosElementAttribute.Poison: arm.PoisonBonus = value; break;
                          case AosElementAttribute.Energy: arm.EnergyBonus = value; break;
                      }
                  }
                  else if (prop is SAAbsorptionAttribute)
                  {
                      arm.AbsorptionAttributes[(SAAbsorptionAttribute)prop] = value;
                  }
                  else if (prop is AosArmorAttribute)
                  {
                      arm.ArmorAttributes[(AosArmorAttribute)prop] = value;
                  }
              }
              else if (item is BaseClothing)
              {
                  BaseClothing clothing = item as BaseClothing;
  
                  if (prop is AosAttribute)
                  {
                      clothing.Attributes[(AosAttribute)prop] = value;
                  }
                  else if (prop is SAAbsorptionAttribute)
                  {
                      clothing.SAAbsorptionAttributes[(SAAbsorptionAttribute)prop] = value;
                  }
                  else if (prop is AosElementAttribute)
                  {
                      AosElementAttribute attr = (AosElementAttribute)prop;
  
                      switch (attr)
                      {
                          case AosElementAttribute.Physical: clothing.Resistances.Physical = value; break;
                          case AosElementAttribute.Fire: clothing.Resistances.Fire = value; break;
                          case AosElementAttribute.Cold: clothing.Resistances.Cold = value; break;
                          case AosElementAttribute.Poison: clothing.Resistances.Poison = value; break;
                          case AosElementAttribute.Energy: clothing.Resistances.Energy = value; break;
                      }
                  }
              }
              else if (item is BaseJewel)
              {
                  BaseJewel jewel = item as BaseJewel;
  
                  if (prop is AosAttribute)
                  {
                      jewel.Attributes[(AosAttribute)prop] = value;
                  }
                  else if (prop is SAAbsorptionAttribute)
                  {
                      jewel.AbsorptionAttributes[(SAAbsorptionAttribute)prop] = value;
                  }
                  else if (prop is AosElementAttribute)
                  {
                      AosElementAttribute attr = (AosElementAttribute)prop;
  
                      switch (attr)
                      {
                          case AosElementAttribute.Physical: jewel.Resistances.Physical = value; break;
                          case AosElementAttribute.Fire: jewel.Resistances.Fire = value; break;
                          case AosElementAttribute.Cold: jewel.Resistances.Cold = value; break;
                          case AosElementAttribute.Poison: jewel.Resistances.Poison = value; break;
                          case AosElementAttribute.Energy: jewel.Resistances.Energy = value; break;
                      }
                  }
                  else if (prop is SkillName)
                  {
                      SkillName skill = (SkillName)prop;
                      AosSkillBonuses bonuses = jewel.SkillBonuses;
  
                      int index = GetAvailableSkillIndex(bonuses);
  
                      if (index >= 0 && index <= 4)
                      {
                          bonuses.SetValues(index, skill, value);
                      }
                  }
              }
  
              item.InvalidateProperties();
          }
  
          public static bool UnravelItem(Mobile from, Item item, bool message = true)
          {
              double bonus = 0.0;
  
              if (!CheckSoulForge(from, 2, out bonus))
                  return false;
  
              int weight = GetTotalWeight(item, -1, false, true);
  
              if (weight <= 0)
              {
                  if (message)
                  {
                      // You cannot magically unravel this item. It appears to possess little or no magic.
                      from.SendLocalizedMessage(1080437);
                  }
  
                  return false;
              }
  
              ImbuingContext context = GetContext(from);
  
              Type resType = null;
              int resAmount = Math.Max(1, weight / 100);
  
              bool success = false;
  
              if (weight >= 480 - bonus)
              {
                  if (from.Skills[SkillName.Imbuing].Value < 95.0)
                  {
                      if (message)
                      {
                          // Your Imbuing skill is not high enough to magically unravel this item.
                          from.SendLocalizedMessage(1080434);
                      }
  
                      return false;
                  }
  
                  if (from.CheckSkill(SkillName.Imbuing, 90.1, 120.0))
                  {
                      success = true;
                      resType = typeof(RelicFragment);
                      resAmount = 1;
                  }
  
gt:                 else if (from.CheckSkill(SkillName.Imbuing, 45.0, 95.0))