context: using Server.Engines.Points;
  using Server.Gumps;
  using Server.Items;
  using Server.Misc;
  using Server.Mobiles;
  using Server.Network;
  using System;
  using System.Collections;
  using System.Collections.Generic;
  
  namespace Server.Misc
  {
      public enum TreasuresOfTokunoEra
      {
          None,
          ToTOne,
          ToTTwo,
          ToTThree
      }
  
      public class TreasuresOfTokuno : PointsSystem
      {
          public override PointsType Loyalty => PointsType.TOT;
          public override TextDefinition Name => m_Name;
          public override bool AutoAdd => true;
          public override double MaxPoints => double.MaxValue;
          public override bool ShowOnLoyaltyGump => false;
  
          private readonly TextDefinition m_Name = new TextDefinition("Treasures of Tokuno");
  
          public const int ItemsPerReward = 10;
  
          private static readonly Type[] m_LesserArtifactsTotal = new Type[]
          {
              typeof(AncientFarmersKasa), typeof(AncientSamuraiDo), typeof(ArmsOfTacticalExcellence), typeof(BlackLotusHood),
              typeof(DaimyosHelm), typeof(DemonForks), typeof(DragonNunchaku), typeof(Exiler), typeof(GlovesOfTheSun),
              typeof(HanzosBow), typeof(LegsOfStability), typeof(PeasantsBokuto), typeof(PilferedDancerFans), typeof(TheDestroyer),
              typeof(TomeOfEnlightenment), typeof(AncientUrn), typeof(HonorableSwords), typeof(PigmentsOfTokuno), typeof(FluteOfRenewal),
              typeof(LeurociansMempoOfFortune), typeof(LesserPigmentsOfTokuno), typeof(MetalPigmentsOfTokuno), typeof(ChestOfHeirlooms)
          };
  
          public static Type[] LesserArtifactsTotal => m_LesserArtifactsTotal;
  
          private static TreasuresOfTokunoEra _DropEra = TreasuresOfTokunoEra.None;
          private static TreasuresOfTokunoEra _RewardEra = TreasuresOfTokunoEra.ToTOne;
  
          public static TreasuresOfTokunoEra DropEra
          {
              get
              {
                  return _DropEra;
              }
              set
              {
                  _DropEra = value;
              }
          }
  
          public static TreasuresOfTokunoEra RewardEra
          {
              get
              {
                  return _RewardEra;
              }
              set
              {
                  _RewardEra = value;
              }
          }
  
          private static readonly Type[][] m_LesserArtifacts = new Type[][]
          {
              // ToT One Rewards
              new Type[]
              {
                  typeof(AncientFarmersKasa), typeof(AncientSamuraiDo), typeof(ArmsOfTacticalExcellence), typeof(BlackLotusHood),
                  typeof(DaimyosHelm), typeof(DemonForks), typeof(DragonNunchaku), typeof(Exiler), typeof(GlovesOfTheSun),
                  typeof(HanzosBow), typeof(LegsOfStability), typeof(PeasantsBokuto), typeof(PilferedDancerFans), typeof(TheDestroyer),
                  typeof(TomeOfEnlightenment), typeof(AncientUrn), typeof(HonorableSwords), typeof(PigmentsOfTokuno),
                  typeof(FluteOfRenewal), typeof(ChestOfHeirlooms)
              },
              // ToT Two Rewards
              new Type[]
              {
                  typeof(MetalPigmentsOfTokuno), typeof(AncientFarmersKasa), typeof(AncientSamuraiDo), typeof(ArmsOfTacticalExcellence),
                  typeof(MetalPigmentsOfTokuno), typeof(BlackLotusHood), typeof(DaimyosHelm), typeof(DemonForks),
                  typeof(MetalPigmentsOfTokuno), typeof(DragonNunchaku), typeof(Exiler), typeof(GlovesOfTheSun), typeof(HanzosBow),
                  typeof(MetalPigmentsOfTokuno), typeof(LegsOfStability), typeof(PeasantsBokuto), typeof(PilferedDancerFans), typeof(TheDestroyer),
                  typeof(MetalPigmentsOfTokuno), typeof(TomeOfEnlightenment), typeof(AncientUrn), typeof(HonorableSwords),
                  typeof(MetalPigmentsOfTokuno), typeof(FluteOfRenewal), typeof(ChestOfHeirlooms)
              },
              // ToT Three Rewards
              new Type[]
              {
                  typeof(LesserPigmentsOfTokuno), typeof(AncientFarmersKasa), typeof(AncientSamuraiDo), typeof(ArmsOfTacticalExcellence),
                  typeof(LesserPigmentsOfTokuno), typeof(BlackLotusHood), typeof(DaimyosHelm), typeof(HanzosBow),
                  typeof(LesserPigmentsOfTokuno), typeof(DemonForks), typeof(DragonNunchaku), typeof(Exiler), typeof(GlovesOfTheSun),
                  typeof(LesserPigmentsOfTokuno), typeof(LegsOfStability), typeof(PeasantsBokuto), typeof(PilferedDancerFans), typeof(TheDestroyer),
                  typeof(LesserPigmentsOfTokuno), typeof(TomeOfEnlightenment), typeof(AncientUrn), typeof(HonorableSwords), typeof(FluteOfRenewal),
                  typeof(LesserPigmentsOfTokuno), typeof(LeurociansMempoOfFortune), typeof(ChestOfHeirlooms)
              }
          };
  
          public static Type[] LesserArtifacts => m_LesserArtifacts[(int)RewardEra - 1];
  
          private static Type[][] m_GreaterArtifacts = null;
  
          public static Type[] GreaterArtifacts
          {
              get
              {
                  if (m_GreaterArtifacts == null)
                  {
                      m_GreaterArtifacts = new Type[ToTRedeemGump.NormalRewards.Length][];
  
                      for (int i = 0; i < m_GreaterArtifacts.Length; i++)
                      {
                          m_GreaterArtifacts[i] = new Type[ToTRedeemGump.NormalRewards[i].Length];
  
                          for (int j = 0; j < m_GreaterArtifacts[i].Length; j++)
                          {
                              m_GreaterArtifacts[i][j] = ToTRedeemGump.NormalRewards[i][j].Type;
                          }
                      }
                  }
  
                  return m_GreaterArtifacts[(int)RewardEra - 1];
              }
          }
  
          private bool CheckLocation(Mobile m)
          {
              Region r = m.Region;
  
              if (r.IsPartOf<Regions.HouseRegion>() || Multis.BaseBoat.FindBoatAt(m, m.Map) != null)
                  return false;
  
              if (r.IsPartOf("Yomotsu Mines") || r.IsPartOf("Fan Dancer's Dojo"))
                  return true;
  
              return (m.Map == Map.Tokuno);
          }
  
          public override void SendMessage(PlayerMobile from, double old, double points, bool quest)
          {
          }
  
          public override TextDefinition GetTitle(PlayerMobile from)
          {
              return new TextDefinition("Treasures of Tokuno");
          }
  
          public override PointsEntry GetSystemEntry(PlayerMobile pm)
          {
              return new TOTEntry(pm);
          }
  
          public int GetTurnIns(PlayerMobile pm)
          {
              if (pm == null)
              {
                  return 0;
              }
  
              return GetPlayerEntry<TOTEntry>(pm).TurnIns;
          }
  
          public int TurnIn(PlayerMobile pm)
          {
              if (pm == null)
              {
                  return 0;
              }
  
              return GetPlayerEntry<TOTEntry>(pm).TurnIns++;
          }
  
          public void RemoveTurnIns(PlayerMobile pm, int amount)
          {
              TOTEntry entry = GetPlayerEntry<TOTEntry>(pm);
  
              entry.TurnIns = Math.Max(0, entry.TurnIns - amount);
          }
  
          public override void ProcessKill(Mobile victim, Mobile killer)
          {
              PlayerMobile pm = killer as PlayerMobile;
              BaseCreature bc = victim as BaseCreature;
  
              if (DropEra == TreasuresOfTokunoEra.None || pm == null || bc == null || !CheckLocation(bc) || !CheckLocation(pm) || !killer.InRange(victim, 18) || !pm.Alive || bc.GivenSpecialArtifact)
                  return;
  
              if (bc.Controlled || bc.Owners.Count > 0 || bc.Fame <= 0)
                  return;
  
              //25000 for 1/100 chance, 10 hyrus
              //1500, 1/1000 chance, 20 lizard men for that chance.
              int luck = Math.Max(0, pm.RealLuck);
              AwardPoints(pm, (int)Math.Max(0, (bc.Fame * (1 + Math.Sqrt(luck) / 100))));
  
              //This is the Exponentional regression with only 2 datapoints.
              //A log. func would also work, but it didn't make as much sense.
              //This function isn't OSI exact beign that I don't know OSI's func they used ;p
              double x = GetPoints(pm);
  
              //const double A = 8.63316841 * Math.Pow( 10, -4 );
              const double A = 0.000863316841;
              //const double B = 4.25531915 * Math.Pow( 10, -6 );
              const double B = 0.00000425531915;
  
              double chance = A * Math.Pow(10, B * x);
  
              if (chance > Utility.RandomDouble())
              {
                  Item i = null;
  
                  try
                  {
                      i = Activator.CreateInstance(m_LesserArtifacts[(int)DropEra - 1][Utility.Random(m_LesserArtifacts[(int)DropEra - 1].Length)]) as Item;
                  }
                  catch (Exception e)
                  {
                      Diagnostics.ExceptionLogging.LogException(e);
                  }
  
                  if (i != null)
                  {
                      killer.PlaySound(0x5B4);
                      pm.SendLocalizedMessage(1062317); // For your valor in combating the fallen beast, a special artifact has been bestowed on you.
  
                      if (!pm.PlaceInBackpack(i))
                      {
                          if (pm.BankBox != null && pm.BankBox.TryDropItem(killer, i, false))
                              pm.SendLocalizedMessage(1079730); // The item has been placed into your bank box.
                          else
                          {
                              pm.SendLocalizedMessage(1072523); // You find an artifact, but your backpack and bank are too full to hold it.
                              i.MoveToWorld(pm.Location, pm.Map);
                          }
                      }
  
                      bc.GivenSpecialArtifact = true;
                      SetPoints(pm, 0);
                  }
              }
          }
  
          /// <summary>
          /// PlayerMobile.cs version 40 deserializationn
          /// </summary>
          /// <param name="pm"></param>
          /// <param name="turnIns"></param>
          /// <param name="points"></param>
          public void Convert(PlayerMobile pm, int turnIns, int points)
          {
              TOTEntry entry = GetPlayerEntry<TOTEntry>(pm);
  
              entry.TurnIns = turnIns;
              entry.Points = points;
          }
  
          public override void Serialize(GenericWriter writer)
          {
              base.Serialize(writer);
  
              writer.Write(0);
          }
  
          public override void Deserialize(GenericReader reader)
          {
              base.Deserialize(reader);
  
              reader.ReadInt();
          }
  
          public class TOTEntry : PointsEntry
          {
              public int TurnIns { get; set; }
  
              public TOTEntry(PlayerMobile pm)
                  : base(pm)
              {
              }
  
              public override void Serialize(GenericWriter writer)
              {
                  writer.Write(1);
                  base.Serialize(writer);
  
                  writer.Write(TurnIns);
              }
  
              public override void Deserialize(GenericReader reader)
              {
                  int version = reader.ReadInt();
  
                  if (version > 0)
                  {
                      base.Deserialize(reader);
                  }
  
                  TurnIns = reader.ReadInt();
              }
          }
      }
  }
  
  namespace Server.Mobiles
  {
      public class IharaSoko : BaseVendor
      {
          public override bool IsActiveVendor => false;
          public override bool IsInvulnerable => true;
          public override bool DisallowAllMoves => true;
          public override bool ClickTitle => true;
          public override bool CanTeach => false;
  
          protected List<SBInfo> m_SBInfos = new List<SBInfo>();
          protected override List<SBInfo> SBInfos => m_SBInfos;
  
          public override void InitSBInfo()
          {
          }
  
          public override void InitOutfit()
          {
              AddItem(new Waraji(0x711));
              AddItem(new Backpack());
              AddItem(new Kamishimo(0x483));
  
              Item item = new LightPlateJingasa
              {
                  Hue = 0x711
              };
  
              AddItem(item);
          }
  
          [Constructable]
          public IharaSoko()
              : base("the Imperial Minister of Trade")
          {
              Name = "Ihara Soko";
              Female = false;
              Body = 0x190;
              Hue = 0x8403;
          }
  
          public IharaSoko(Serial serial)
              : base(serial)
          {
          }
  
          public override void Serialize(GenericWriter writer)
          {
              base.Serialize(writer);
  
              writer.Write(0);
          }
  
          public override void Deserialize(GenericReader reader)
          {
              base.Deserialize(reader);
  
              int version = reader.ReadInt();
          }
  
          public override bool CanBeDamaged()
          {
              return false;
          }
  
          public override void OnMovement(Mobile m, Point3D oldLocation)
          {
              if (m.Alive && m is PlayerMobile)
              {
                  PlayerMobile pm = (PlayerMobile)m;
  
                  int range = 3;
                  int turnIns = PointsSystem.TreasuresOfTokuno.GetTurnIns(pm);
  
                  if (m.Alive && Math.Abs(Z - m.Z) < 16 && InRange(m, range) && !InRange(oldLocation, range))
                  {
                      if (turnIns >= TreasuresOfTokuno.ItemsPerReward)
                      {
                          SayTo(pm, 1070980); // Congratulations! You have turned in enough minor treasures to earn a greater reward.
  
                          pm.CloseGump(typeof(ToTTurnInGump));    //Sanity
  
                          if (!pm.HasGump(typeof(ToTRedeemGump)))
  
gt:                             pm.SendGump(new ToTRedeemGump(this, false));