context: using System;
  using Server;
  using Server.Gumps;
  using Server.Network;
  using Server.Mobiles;
  using System.Collections;
  using Server.Targeting;
  using Server.Engines.XmlSpawner2;
  
  /*
  ** LastManStandingGauntlet
  ** ArteGordon
  ** updated 12/05/04
  **
  ** used to set up a last man standing pvp challenge game through the XmlPoints system.
  */
  
  namespace Server.Items
  {
      public class LastManStandingGauntlet : BaseChallengeGame
      {
  
  
  		public class ChallengeEntry : BaseChallengeEntry
  		{
  
              public ChallengeEntry(Mobile m) : base (m)
              {
              }
  
              public ChallengeEntry() : base ()
              {
              }
  		}
  
  		
  		private static TimeSpan MaximumOutOfBoundsDuration = TimeSpan.FromSeconds(15);    // maximum time allowed out of bounds before disqualification
  
          private static TimeSpan MaximumOfflineDuration = TimeSpan.FromSeconds(60);    // maximum time allowed offline before disqualification
  
          private static TimeSpan MaximumHiddenDuration = TimeSpan.FromSeconds(10);    // maximum time allowed hidden before disqualification
          
          private static TimeSpan RespawnTime = TimeSpan.FromSeconds(6);    // delay until autores if autores is enabled
  
          public static bool OnlyInChallengeGameRegion = false;           // if this is true, then the game can only be set up in a challenge game region
  
          private Mobile m_Challenger;
  
          private ArrayList m_Organizers = new ArrayList();
  
          private ArrayList m_Participants = new ArrayList();
  
          private bool m_GameLocked;
  
          private bool m_GameInProgress;
  
          private int m_TotalPurse;
  
          private int m_EntryFee;
          
          private int m_ArenaSize = 0;        // maximum distance from the challenge gauntlet allowed before disqualification.  Zero is unlimited range
  
          private Mobile m_Winner;
  
          // how long before the gauntlet decays if a gauntlet is dropped but never started
          public override TimeSpan DecayTime { get{ return TimeSpan.FromMinutes( 15 ); } }  // this will apply to the setup
  
          public override ArrayList Organizers { get { return m_Organizers; } }
  
          public override bool AllowPoints { get{ return false; } }   // determines whether kills during the game will award points.  If this is false, UseKillDelay is ignored
  
          public override bool UseKillDelay { get{ return true; } }   // determines whether the normal delay between kills of the same player for points is enforced
  
          public bool AutoRes { get { return true; } }            // determines whether players auto res after being killed
  
          [CommandProperty( AccessLevel.GameMaster )]
          public override Mobile Challenger { get{ return m_Challenger; } set { m_Challenger = value; } }
  
          public override bool GameInProgress { get{ return m_GameInProgress; } set {m_GameInProgress = value; } }
  
          [CommandProperty( AccessLevel.GameMaster )]
          public override bool GameCompleted { get{ return !m_GameInProgress && m_GameLocked; } }
  
          public override bool GameLocked { get{ return m_GameLocked; } set {m_GameLocked = value; } }
  
          [CommandProperty( AccessLevel.GameMaster )]
          public Mobile Winner { get{ return m_Winner; } set { m_Winner = value; } }
  
          public override ArrayList Participants { get{ return m_Participants; } set { m_Participants = value; } }
  
          public override int TotalPurse { get { return m_TotalPurse; } set { m_TotalPurse = value; } }
  
          public override int EntryFee { get { return m_EntryFee; } set { m_EntryFee = value; } }
  
          [CommandProperty( AccessLevel.GameMaster )]
          public override int ArenaSize { get { return m_ArenaSize; } set { m_ArenaSize = value; } }
  
          public override bool InsuranceIsFree(Mobile from, Mobile awardto)
          {
              return true;
          }
                  
          public override void OnTick()
  		{
              CheckForDisqualification();
  		}
  
  		public void CheckForDisqualification()
  		{
  		
              if(Participants == null || !GameInProgress) return;
  
              bool statuschange = false;
  
              foreach(ChallengeEntry entry in Participants)
              {
                  if(entry.Participant == null || entry.Status == ChallengeStatus.Forfeit || entry.Status == ChallengeStatus.Disqualified) continue;
  
                  bool hadcaution = (entry.Caution != ChallengeStatus.None);
  
                  // and a map check
                  if(entry.Participant.Map != Map)
                  {
                      // check to see if they are offline
                      if(entry.Participant.Map == Map.Internal)
                      {
                          // then give them a little time to return before disqualification
                          if(entry.Caution == ChallengeStatus.Offline)
                          {
                              // were previously out of bounds so check for disqualification
                              // check to see how long they have been out of bounds
                              if(DateTime.UtcNow - entry.LastCaution > MaximumOfflineDuration)
                              {
                                  entry.Status = ChallengeStatus.Disqualified;
                                  GameBroadcast(100308, entry.Participant.Name);  // "{0} has been disqualified"
                                  RefreshSymmetricNoto(entry.Participant);
                                  statuschange = true;
                              }
                          } else
                          {
                              entry.LastCaution  = DateTime.UtcNow;
                              statuschange = true;
                          }
      
                          entry.Caution = ChallengeStatus.Offline;
                      } else
                      {
                          // changing to any other map is instant disqualification
                          entry.Status = ChallengeStatus.Disqualified;
                          GameBroadcast(100308, entry.Participant.Name);  // "{0} has been disqualified"
                          RefreshSymmetricNoto(entry.Participant);
                          statuschange = true;
                      }
                      
  
                  } else
                  // make a range check
                  if(m_ArenaSize > 0 && !Utility.InRange(entry.Participant.Location, Location, m_ArenaSize)
                  || (IsInChallengeGameRegion && !(Region.Find(entry.Participant.Location, entry.Participant.Map) is ChallengeGameRegion)))
                  {
                      if(entry.Caution == ChallengeStatus.OutOfBounds)
                      {
                          // were previously out of bounds so check for disqualification
                          // check to see how long they have been out of bounds
                          if(DateTime.UtcNow - entry.LastCaution > MaximumOutOfBoundsDuration)
                          {
                              entry.Status = ChallengeStatus.Disqualified;
                              GameBroadcast(100308, entry.Participant.Name);  // "{0} has been disqualified"
                              RefreshSymmetricNoto(entry.Participant);
                              statuschange = true;
                          }
                      } else
                      {
                          entry.LastCaution  = DateTime.UtcNow;
                          // inform the player
                          XmlPoints.SendText(entry.Participant, 100309, MaximumOutOfBoundsDuration.TotalSeconds);  // "You are out of bounds!  You have {0} seconds to return"
                          statuschange = true;
                      }
  
                      entry.Caution = ChallengeStatus.OutOfBounds;
                      
  
                  } else
                  // make a hiding check
                  if(entry.Participant.Hidden)
                  {
                      if(entry.Caution == ChallengeStatus.Hidden)
                      {
                          // were previously hidden so check for disqualification
                          // check to see how long they have hidden
                          if(DateTime.UtcNow - entry.LastCaution > MaximumHiddenDuration)
                          {
                              entry.Status = ChallengeStatus.Disqualified;
                              GameBroadcast(100308, entry.Participant.Name);  // "{0} has been disqualified"
                              RefreshSymmetricNoto(entry.Participant);
                              statuschange = true;
                          }
                      } else
                      {
                          entry.LastCaution  = DateTime.UtcNow;
                          // inform the player
                          XmlPoints.SendText(entry.Participant, 100310, MaximumHiddenDuration.TotalSeconds); // "You have {0} seconds become unhidden"
                          statuschange = true;
                      }
  
                      entry.Caution = ChallengeStatus.Hidden;
                      
  
                  } else
                  {
                      entry.Caution = ChallengeStatus.None;
                  }
                  
                  if(hadcaution && entry.Caution == ChallengeStatus.None)
                      statuschange = true;
  
              }
  
              if(statuschange)
              {
                  // update gumps with the new status
                  LastManStandingGump.RefreshAllGumps(this, false);
              }
  
              // it is possible that the game could end like this so check
              CheckForGameEnd();
  		}
  
  		public override void CheckForGameEnd()
  		{
  
              if(Participants == null || !GameInProgress) return;
  
              int leftstanding = 0;
              Mobile winner = null;
  
              foreach(ChallengeEntry entry in Participants)
              {
  
gt:                 if(entry.Status == ChallengeStatus.Active)