context: using System;
  using Server;
  using System.Collections.Generic;
  using Server.ContextMenus;
  using Server.Engines.Despise;
  using Server.Items;
  using Server.Gumps;
  using Server.Network;
  using Server.Engines.Quests;
  
  namespace Server.Mobiles
  {
      [CorpseName("a wisp corpse")]
      public class MysteriousWisp : BaseCreature
      {
          private int m_ItemCountMin;
          private int m_ItemCountMax;
          private int m_IntensityMin;
          private int m_IntensityMax;
          private int m_RestockMin;
          private int m_RestockMax;
          private double m_MutateChance;
  
          [CommandProperty(AccessLevel.GameMaster)]
          public int ItemCountMin { get { return m_ItemCountMin; } set { m_ItemCountMin = value; } }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public int ItemCountMax { get { return m_ItemCountMax; } set { m_ItemCountMax = value; } }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public int IntensityMin { get { return m_IntensityMin; } set { m_IntensityMin = value; } }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public int IntensityMax { get { return m_IntensityMax; } set { m_IntensityMax = value; } }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public int RestockMin { get { return m_RestockMin; } set { m_RestockMin = value; } }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public int RestockMax { get { return m_RestockMax; } set { m_RestockMax = value; } }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public double MutateChance { get { return m_MutateChance; } set { m_MutateChance = value; } }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public bool ForceRestock { get { return false; } set { if (value) DoRestock(); } }
  
          [Constructable]
          public MysteriousWisp()
              : base(AIType.AI_Mage, FightMode.None, 10, 1, 0.2, 0.4)
          {
              CantWalk = true;
              Blessed = true;
              SpeechHue = 52;
  
              Name = "a mysterious wisp";
              Body = 58;
              BaseSoundID = 466;
  
              SetStr(196, 225);
              SetDex(196, 225);
              SetInt(196, 225);
  
              SetHits(118, 135);
  
              SetDamage(17, 18);
  
              SetDamageType(ResistanceType.Physical, 50);
              SetDamageType(ResistanceType.Energy, 50);
  
              SetResistance(ResistanceType.Physical, 35, 45);
              SetResistance(ResistanceType.Fire, 20, 40);
              SetResistance(ResistanceType.Cold, 10, 30);
              SetResistance(ResistanceType.Poison, 5, 10);
              SetResistance(ResistanceType.Energy, 50, 70);
  
              SetSkill(SkillName.EvalInt, 80.0);
              SetSkill(SkillName.Magery, 80.0);
              SetSkill(SkillName.MagicResist, 80.0);
              SetSkill(SkillName.Tactics, 80.0);
              SetSkill(SkillName.Wrestling, 80.0);
  
              if (Backpack != null)
                  Backpack.Delete();
  
              m_ItemCountMin = 14;
              m_ItemCountMax = 20;
              m_IntensityMin = 40;
              m_IntensityMax = 100;
              m_RestockMin = 45;
              m_RestockMax = 65;
              m_MutateChance = 0.10;
  
              AddItem(new BuyBackpack());
              DoRestock();
          }
  
          public override bool HandlesOnSpeech(Mobile from)
          {
              return m_Conversation.ContainsKey(from);
          }
  
          private Dictionary<Mobile, int> m_Conversation = new Dictionary<Mobile, int>();
  
          public override void OnDoubleClick(Mobile from)
          {
              if (from.InRange(this.Location, 5))
              {
                  if (!m_Conversation.ContainsKey(from))
                  {
                      SayTo(from, m_Responses[0]);
                      m_Conversation[from] = 1;
                  }
              }
  
              if (from is PlayerMobile)
              {
                  var pm = from as PlayerMobile;
  
                  if (QuestHelper.CheckDoneOnce(pm, typeof(WishesOfTheWispQuest), null, false))
                  {
                      var q = QuestHelper.GetQuest<WhisperingWithWispsQuest>(pm);
  
                      if (q == null)
                      {
                          BaseQuest quest = QuestHelper.RandomQuest(pm, new Type[] { typeof(WhisperingWithWispsQuest) }, this);
  
                          if (quest != null)
                          {
                              pm.CloseGump(typeof(MondainQuestGump));
                              pm.SendGump(new MondainQuestGump(quest));
                          }
                      }
                      else if (q.Completed)
                      {
                          q.CompleteQuest();
                      }
                  }
              }
          }
  
          public override void OnMovement(Mobile m, Point3D oldLocation)
          {
              if (m is PlayerMobile && InRange(m.Location, 5) && !InRange(oldLocation, 5))
              {
                  WishesOfTheWispQuest quest = QuestHelper.GetQuest<WishesOfTheWispQuest>((PlayerMobile)m);
  
                  if (quest != null)
                  {
                      quest.CompleteQuest();
                  }
              }
          }
  
          public override void OnSpeech(SpeechEventArgs e)
          {
              if (!m_Conversation.ContainsKey(e.Mobile))
                  return;
  
              string speech = e.Speech.ToLower();
              int idx = m_Conversation[e.Mobile];
  
              if (idx < 0 || idx >= m_Keywords.Length)
              {
                  m_Conversation.Remove(e.Mobile);
                  return;
              }
  
              foreach (string str in m_Keywords[idx])
              {
                  if (speech.Contains(str))
                  {
                      SayTo(e.Mobile, m_Responses[idx]);
  
                      if (idx + 1 >= m_Keywords.Length)
                          m_Conversation.Remove(e.Mobile);
                      else
                          m_Conversation[e.Mobile]++;
  
                      break;
                  }
              }
          }
  
          private string[][] m_Keywords = new string[][]
          {
              new string[] { },
              new string[] { "corporeal" },
              new string[] { "sentient" },
              new string[] { "deal" },
              new string[] { "learn", "teach" },
              new string[] { "good and evil", "good", "evil" },
              new string[] { "guide" },
              new string[] { "follow" },
              new string[] { "fight" },
              new string[] { "resonate" },
              new string[] { "join" },
              new string[] { "command" },
              new string[] { "trade" },
          };
  
          private int[] m_Responses = new int[]
          {
              1153441,
              1153443,
              1153445,
              1153447,
              1153449,
              1153451,
              1153453,
              1153455,
              1153457,
              1153459,
              1153461,
              1153463,
              1153467
          };
  
          public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
          {
              base.GetContextMenuEntries(from, list);
  
              list.Add(new InternalEntry(this, from));
          }
  
          private Dictionary<Item, int> m_ItemTable = new Dictionary<Item, int>();
  
          public void CheckRestock()
          {
              if (m_NextRestock <= DateTime.UtcNow)
                  DoRestock();
          }
  
          private void DoRestock()
          {
              List<Item> list = new List<Item>(this.Backpack.Items);
              m_ItemTable.Clear();
  
              InternalGump.Clear();
  
              foreach (Item item in list)
                  item.Delete();
  
              int count = Utility.RandomMinMax(m_ItemCountMin, m_ItemCountMax);
  
              for (int i = 0; i < count; i++)
              {
                  Item item;
  
                  switch (Utility.Random(3))
                  {
                      default:
                      case 0: item = Loot.RandomArmorOrShieldOrWeaponOrJewelry(false, false, true); break;
                      case 1: item = Loot.RandomArmorOrShieldOrWeaponOrJewelry(false, true, false); break;
                      case 2: item = Loot.RandomArmorOrShieldOrWeaponOrJewelry(true, false, false); break;
                  }
  
                  int weight = 0;
  
                  if (0.10 > Utility.RandomDouble())
                  {
                      int budget = Utility.RandomMinMax(500, 860);
                      RunicReforging.GenerateRandomItem(item, null, Utility.RandomMinMax(500, 860), 0, ReforgedPrefix.None, ReforgedSuffix.None);
                      weight += budget / 3;
                  }
                  else
                  {
                      int props = Utility.RandomMinMax(3, 5);
  
                      if (props == 5 && 0.05 > Utility.RandomDouble())
                      {
                          props++;
                          weight += 100;
                      }
  
                      if (item is BaseWeapon)
                      {
                          BaseRunicTool.ApplyAttributesTo((BaseWeapon)item, false, 0, props, m_IntensityMin, m_IntensityMax);
                      }
                      else if (item is BaseArmor)
                      {
                          BaseRunicTool.ApplyAttributesTo((BaseArmor)item, false, 0, props, m_IntensityMin, m_IntensityMax);
                      }
                      else if (item is BaseJewel)
                      {
                          BaseRunicTool.ApplyAttributesTo((BaseJewel)item, false, 0, props, m_IntensityMin, m_IntensityMax);
                      }
                      else if (item is BaseHat)
                      {
                          BaseRunicTool.ApplyAttributesTo((BaseHat)item, false, 0, props, m_IntensityMin, m_IntensityMax);
                      }
                  }
  
                  m_ItemTable[item] = (int)((weight + Server.SkillHandlers.Imbuing.GetTotalWeight(item, -1, false, true)) * 31.5);
                  item.Movable = false;
                  this.Backpack.DropItem(item);
              }
  
              m_NextRestock = DateTime.UtcNow + TimeSpan.FromMinutes(Utility.RandomMinMax(m_RestockMin, m_RestockMax));
          }
  
          public int GetCostFor(Item item)
          {
              if (!m_ItemTable.ContainsKey(item))
                  return -1;
  
              return m_ItemTable[item];
          }
  
          public void TryBuyItem(Mobile from, Item item)
          {
              if (item.Deleted || !this.Backpack.Items.Contains(item) || !m_ItemTable.ContainsKey(item))
              {
                  from.SendMessage("This item is no longer available.");
                  return;
              }
  
              int points = (int)Server.Engines.Points.PointsSystem.DespiseCrystals.GetPoints(from);
              int cost = m_ItemTable[item];
  
              if (points >= cost)
              {
                  //DespiseController.Instance.DeductDespisePoints(from, cost);
                  Server.Engines.Points.PointsSystem.DespiseCrystals.DeductPoints(from, cost);
                  item.Movable = true;
  
                  if (from.Backpack == null || !from.Backpack.TryDropItem(from, item, false))
                      item.MoveToWorld(from.Location, from.Map);
  
                  from.SendLocalizedMessage(1153427, cost.ToString()); // You have spent ~1_AMT~ Dungeon Crystal Points of Despise.
  
                  InternalGump.Resend(this);
              }
              else
                  from.SendMessage("You need {0} more Despise dungeon crystal points for this.", cost - points);
          }
  
          private class InternalEntry : ContextMenuEntry
          {
              private Mobile m_Clicker;
              private MysteriousWisp m_Wisp;
  
              public InternalEntry(MysteriousWisp wisp, Mobile clicker)
                  : base(1150143, 3)
              {
                  m_Clicker = clicker;
                  m_Wisp = wisp;
              }
  
              public override void OnClick()
              {
                  if (m_Clicker.Alive && !m_Wisp.Deleted && m_Clicker.InRange(m_Wisp.Location, 3))
                  {
                      if (m_Wisp.Backpack == null)
                      {
  
gt:                         Console.WriteLine("Error, wisp backpack is null");