context: using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.IO;
  using Server.Gumps;
  using Server.Commands;
  using System.Xml;
  
  namespace Server.Engines.CannedEvil
  {
  	public class ChampionSystem
  	{
  		private static bool m_Enabled = false;
  		private static bool m_Initialized = false;
  		private static readonly string m_Path = Path.Combine("Saves", "Champions", "ChampionSystem.bin");
  		private static readonly string m_ConfigPath = Path.Combine("Config", "ChampionSpawns.xml");
  		private static DateTime m_LastRotate;
  		private static TimeSpan m_RotateDelay;
  		private static List<ChampionSpawn> m_AllSpawns = new List<ChampionSpawn>();
  		private static InternalTimer m_Timer;
  		private static int m_GoldShowerPiles;
  		private static int m_GoldShowerMinAmount;
  		private static int m_GoldShowerMaxAmount;
  		private static int m_HarrowerGoldPiles;
  		private static int m_HarrowerGoldMinAmount;
  		private static int m_HarrowerGoldMaxAmount;
  		private static int m_PowerScrollAmount;
  		private static int m_StatScrollAmount;
  		private static int[] m_Rank = new int[16];
  		private static int[] m_MaxKill = new int[4];
  		private static double m_TranscendenceChance;
  		private static double m_ScrollChance;
  		private static bool m_ForceGenerate = false;
  
  		public static int GoldShowerPiles { get { return m_GoldShowerPiles; } }
  		public static int GoldShowerMinAmount { get { return m_GoldShowerMinAmount; } }
  		public static int GoldShowerMaxAmount { get { return m_GoldShowerMaxAmount; } }
  		public static int HarrowerGoldShowerPiles { get { return m_HarrowerGoldPiles; } }
  		public static int HarrowerGoldShowerMinAmount { get { return m_HarrowerGoldMinAmount; } }
  		public static int HarrowerGoldShowerMaxAmount { get { return m_HarrowerGoldMaxAmount; } }
  		public static int PowerScrollAmount { get { return m_PowerScrollAmount; } }
  		public static int StatScrollAmount { get { return m_StatScrollAmount; } }
  
          public static List<ChampionSpawn> AllSpawns { get { return m_AllSpawns; } }
  
  		public static int RankForLevel(int l)
  		{
  			if (l < 0)
  				return 0;
  			if (l >= m_Rank.Length)
  				return 3;
  			return m_Rank[l];
  		}
  		public static int MaxKillsForLevel(int l)
  		{
  			return m_MaxKill[RankForLevel(l)];
  		}
  		public static double SpawnRadiusModForLevel(int l)
  		{
  			switch (RankForLevel(l))
  			{
  				case 0: return 1.0d;
  				case 1: return 0.75d;
  				case 2: return 0.5d;
  				default: return 0.25d;
  			}
  		}
  		public static double TranscendenceChance { get { return m_TranscendenceChance; } }
  		public static double ScrollChance { get { return m_ScrollChance; } }
  
  		public static void Configure()
  		{
  			m_Enabled = Config.Get("Champions.Enabled", true);
  			m_RotateDelay = Config.Get("Champions.RotateDelay", TimeSpan.FromDays(1.0d));
  			m_GoldShowerPiles = Config.Get("Champions.GoldPiles", 50);
  			m_GoldShowerMinAmount = Config.Get("Champions.GoldMin", 4000);
  			m_GoldShowerMaxAmount = Config.Get("Champions.GoldMax", 5500);
  			m_HarrowerGoldPiles = Config.Get("Champions.HarrowerGoldPiles", 75);
  			m_HarrowerGoldMinAmount = Config.Get("Champions.HarrowerGoldMin", 5000);
  			m_HarrowerGoldMaxAmount = Config.Get("Champions.HarrowerGoldMax", 10000);
  			m_PowerScrollAmount = Config.Get("Champions.PowerScrolls", 6);
  			m_StatScrollAmount = Config.Get("Champions.StatScrolls", 16);
  			m_ScrollChance = Config.Get("Champions.ScrollChance", 0.1d) / 100.0d;
  			m_TranscendenceChance = Config.Get("Champions.TranscendenceChance", 50.0d) / 100.0d;
  			int rank2 = Config.Get("Champions.Rank2RedSkulls", 5);
  			int rank3 = Config.Get("Champions.Rank3RedSkulls", 10);
  			int rank4 = Config.Get("Champions.Rank4RedSkulls", 10);
  			for (int i = 0; i < m_Rank.Length; ++i)
  			{
  				if (i < rank2)
  					m_Rank[i] = 0;
  				else if (i < rank3)
  					m_Rank[i] = 1;
  				else if (i < rank4)
  					m_Rank[i] = 2;
  				else
  					m_Rank[i] = 3;
  			}
  			m_MaxKill[0] = Config.Get("Champions.Rank1MaxKills", 256);
  			m_MaxKill[1] = Config.Get("Champions.Rank2MaxKills", 128);
  			m_MaxKill[2] = Config.Get("Champions.Rank3MaxKills", 64);
  			m_MaxKill[3] = Config.Get("Champions.Rank4MaxKills", 32);
  			EventSink.WorldLoad += EventSink_WorldLoad;
  			EventSink.WorldSave += EventSink_WorldSave;
  		}
  		private static void EventSink_WorldSave(WorldSaveEventArgs e)
  		{
  			Persistence.Serialize(
  				m_Path,
  				writer =>
  				{
  					writer.Write(1); // Version
  					writer.Write(m_Initialized);
  					writer.Write(m_LastRotate);
  					writer.WriteItemList(m_AllSpawns, true);
  				});
  		}
  
  		private static void EventSink_WorldLoad()
  		{
  			Persistence.Deserialize(
  				m_Path,
  				reader =>
  				{
  					int version = reader.ReadInt();
  
  					m_Initialized = reader.ReadBool();
  					m_LastRotate = reader.ReadDateTime();
  					m_AllSpawns.AddRange(reader.ReadItemList().Cast<ChampionSpawn>());
  
  					if(version == 0)
  					{
  						//m_ForceGenerate = true;
  					}
  				});
  		}
  
  		public static void Initialize()
          {
              CommandSystem.Register("GenChampSpawns", AccessLevel.GameMaster, GenSpawns_OnCommand);
              CommandSystem.Register("DelChampSpawns", AccessLevel.GameMaster, DelSpawns_OnCommand);
  
  			CommandSystem.Register("ChampionInfo", AccessLevel.GameMaster, new CommandEventHandler(ChampionInfo_OnCommand));
  
  			if (!m_Enabled || m_ForceGenerate)
  			{
  				m_Initialized = false;
  
                  if (m_Enabled)
                  {
                      LoadSpawns();
                  }
                  else
                  {
                      RemoveSpawns();
                  }
  			}
  
              if (m_Enabled)
              {
                  m_Timer = new InternalTimer();
              }
  		}
  
          public static void GenSpawns_OnCommand(CommandEventArgs e)
          {
              LoadSpawns();
              e.Mobile.SendMessage("Champ Spawns Generated!");
          }
  
          public static void DelSpawns_OnCommand(CommandEventArgs e)
          {
              RemoveSpawns();
              e.Mobile.SendMessage("Champ Spawns Removed!");
          }
  
          public static void LoadSpawns()
          {
              if (m_Initialized)
                  return;
  
              RemoveSpawns();
  
              Utility.PushColor(ConsoleColor.White);
              Console.WriteLine("Generating Champion Spawns");
              Utility.PopColor();
  
              ChampionSpawn spawn;
  
              XmlDocument doc = new XmlDocument();
              doc.Load(m_ConfigPath);
              foreach (XmlNode node in doc.GetElementsByTagName("championSystem")[0].ChildNodes)
              {
                  if (node.Name.Equals("spawn"))
                  {
                      spawn = new ChampionSpawn();
                      spawn.SpawnName = GetAttr(node, "name", "Unamed Spawner");
                      string value = GetAttr(node, "type", null);
  
                      if (value == null)
                          spawn.RandomizeType = true;
                      else
                          spawn.Type = (ChampionSpawnType)Enum.Parse(typeof(ChampionSpawnType), value);
  
                      value = GetAttr(node, "spawnMod", "1.0");
                      spawn.SpawnMod = XmlConvert.ToDouble(value);
                      value = GetAttr(node, "killsMod", "1.0");
                      spawn.KillsMod = XmlConvert.ToDouble(value);
  
                      foreach (XmlNode child in node.ChildNodes)
                      {
                          if (child.Name.Equals("location"))
                          {
                              int x = XmlConvert.ToInt32(GetAttr(child, "x", "0"));
                              int y = XmlConvert.ToInt32(GetAttr(child, "y", "0"));
                              int z = XmlConvert.ToInt32(GetAttr(child, "z", "0"));
                              int r = XmlConvert.ToInt32(GetAttr(child, "radius", "0"));
                              string mapName = GetAttr(child, "map", "Felucca");
                              Map map = Map.Parse(mapName);
  
                              spawn.SpawnRadius = r;
                              spawn.MoveToWorld(new Point3D(x, y, z), map);
                          }
                      }
  
                      spawn.GroupName = GetAttr(node, "group", null);
                      m_AllSpawns.Add(spawn);
  
                      if (spawn.Type == ChampionSpawnType.Infuse)
                      {
                          PrimevalLichPuzzle.GenLichPuzzle(null);
                      }
                  }
              }
  
              Rotate();
  
              m_Initialized = true;
          }
  
          public static void RemoveSpawns()
          {
  
gt:             if (m_AllSpawns != null && m_AllSpawns.Count > 0)