context: using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Linq;
  using Server;
  using Server.Gumps;
  using Server.Mobiles;
  using Server.Network;
  using Server.Engines.PartySystem;
  
  namespace Server.Items
  {
      public abstract class PeerlessAltar : Container
      {
          public override bool IsPublicContainer { get { return true; } }
          public override bool IsDecoContainer { get { return false; } }
  
          public virtual TimeSpan TimeToSlay { get { return TimeSpan.FromMinutes(90); } }
          public virtual TimeSpan DelayAfterBossSlain { get { return TimeSpan.FromMinutes(15); } }
  
          public abstract int KeyCount { get; }
          public abstract MasterKey MasterKey { get; }
  
          public abstract Type[] Keys { get; }
          public abstract BasePeerless Boss { get; }
  
          public abstract Rectangle2D[] BossBounds { get; }
  
          private BasePeerless m_Peerless;
          private Point3D m_BossLocation;
          private Point3D m_TeleportDest;
          private Point3D m_ExitDest;
          private DateTime m_Deadline;
          private bool m_IsAvailable;
  
          [CommandProperty(AccessLevel.GameMaster)]
          public BasePeerless Peerless
          {
              get { return m_Peerless; }
              set { m_Peerless = value; }
          }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public Point3D BossLocation
          {
              get { return m_BossLocation; }
              set { m_BossLocation = value; }
          }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public Point3D TeleportDest
          {
              get { return m_TeleportDest; }
              set { m_TeleportDest = value; }
          }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public Point3D ExitDest
          {
              get { return m_ExitDest; }
              set { m_ExitDest = value; }
          }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public DateTime Deadline
          {
              get { return m_Deadline; }
              set { m_Deadline = value; }
          }
  
          [CommandProperty(AccessLevel.Counselor)]
          public bool ResetPeerless
          {
              get { return false; }
              set { if (value == true) FinishSequence(); }
          }
  
          [CommandProperty(AccessLevel.GameMaster)]
          public int FighterCount
          {
              get { return m_Fighters != null ? m_Fighters.Count : 0; }
          }
  
          private List<Mobile> m_Fighters;
          private List<Item> m_MasterKeys;
  
          public List<Mobile> Fighters
          {
              get { return m_Fighters; }
          }
  
          public List<Item> MasterKeys
          {
              get { return m_MasterKeys; }
          }
  
          public bool Activated
          {
              get { return (m_Fighters.Count > 0 || Items.Count == Keys.Length || !m_IsAvailable) ? true : false; }
          }
  
          [CommandProperty(AccessLevel.Counselor)]
          public bool IsAvailable
          {
              get { return m_IsAvailable; }
          }
  
          public Mobile Summoner
          {
              get
              {
                  if (m_Fighters == null || m_Fighters.Count == 0)
                      return null;
  
                  return m_Fighters[0];
              }
          }
  
          public PeerlessAltar(int itemID)
              : base(itemID)
          {
              Movable = false;
  
              m_Fighters = new List<Mobile>();
              //m_Pets = new Dictionary<Mobile, List<Mobile>>();
              m_MasterKeys = new List<Item>();
              m_IsAvailable = true;
          }
  
          public PeerlessAltar(Serial serial)
              : base(serial)
          {
          }
  
          public override bool OnDragDrop(Mobile from, Item dropped)
          {
              if (Activated)
              {
                  from.SendLocalizedMessage(1075213); // The master of this realm has already been summoned and is engaged in combat.  Your opportunity will come after he has squashed the current batch of intruders!
                  return false;
              }
  
              if (!IsKey(dropped))
              {
                  from.SendLocalizedMessage(1072682); // This is not the proper key.
                  return false;
              }
  
              if (Items.Count + 1 == Keys.Length)
              {
                  from.SendLocalizedMessage(1072680); // You have been given the key to the boss.
  
                  for (int i = 0; i < KeyCount; i++)
                  {
                      MasterKey key = MasterKey;
  
                      if (key != null)
                      {
                          key.Altar = this;
  
                          if (!from.AddToBackpack(key))
                              key.MoveToWorld(from.Location, from.Map);
  
                          m_MasterKeys.Add(key);
                      }
                  }
  
                  dropped.Delete();
                  ClearContainer();
                  StopKeyTimer();
              }
              else
                  StartTimer(from);
  
              return base.OnDragDrop(from, dropped);
          }
  
          public override void OnDoubleClick(Mobile from)
          {
              if ((int)from.AccessLevel > (int)AccessLevel.Player)
                  base.OnDoubleClick(from);
          }
  
          public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
          {
              if ((int)from.AccessLevel > (int)AccessLevel.Player)
                  return base.CheckLift(from, item, ref reject);
              else
                  reject = LRReason.CannotLift;
  
              return false;
          }
  
          public override void Serialize(GenericWriter writer)
          {
              base.Serialize(writer);
  
              writer.Write((int)4); // version
  
              // version 4 remove pet table
  
              // version 3
              writer.Write(m_IsAvailable);
  
              // version 1
              writer.Write((bool)(m_Helpers != null));
  
              if (m_Helpers != null)
                  writer.WriteMobileList<BaseCreature>(m_Helpers);
  
              // version 0			
              writer.Write(m_Peerless);
              writer.Write(m_BossLocation);
              writer.Write(m_TeleportDest);
              writer.Write(m_ExitDest);
  
              writer.Write(m_Deadline);
  
              // serialize master keys						
              writer.WriteItemList(m_MasterKeys);
  
              // serialize fighters							
              writer.WriteMobileList(m_Fighters);
          }
  
          public override void Deserialize(GenericReader reader)
          {
              base.Deserialize(reader);
  
              int version = reader.ReadInt();
  
              switch (version)
              {
                  case 4:
                  case 3:
                      m_IsAvailable = reader.ReadBool();
                      goto case 2;
                  case 2:
                  case 1:
                      if (reader.ReadBool())
                          m_Helpers = reader.ReadStrongMobileList<BaseCreature>();
                      goto case 0;
                  case 0:
                      m_Peerless = reader.ReadMobile() as BasePeerless;
                      m_BossLocation = reader.ReadPoint3D();
                      m_TeleportDest = reader.ReadPoint3D();
                      m_ExitDest = reader.ReadPoint3D();
  
                      m_Deadline = reader.ReadDateTime();
  
                      m_MasterKeys = reader.ReadStrongItemList();
                      m_Fighters = reader.ReadStrongMobileList();
  
                      if (version < 4)
                      {
                          int count = reader.ReadInt();
  
                          for (int i = 0; i < count; i++)
                          {
                              reader.ReadMobile();
                              reader.ReadStrongMobileList();
                          }
                      }
  
                      if (version < 2)
                          reader.ReadBool();
  
                      if (m_Peerless == null && m_Helpers.Count > 0)
                          Timer.DelayCall(TimeSpan.FromSeconds(30), new TimerCallback(CleanupHelpers));
  
                      break;
              }
  
  
gt:             if (version == 2)