All pastes #70908 Raw Edit

PvPEvent.cs

public text v1 · immutable
#70908 ·published 2006-06-24 23:49 UTC
rendered paste body
using System;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using Server;
using Server.Commands;
using Server.Network;
using Server.Gumps;
using Server.Mobiles;
using Server.Accounting;
using Server.Items;
using Server.Engines.CannedEvil;
using Server.Regions;
using Server.Targeting;

namespace Server.Engines.Event
{

	public enum PvpEventStyle
	{
		Normal,
		Caveman,
		Savage,
		Wrestling,
		ArtiWhore,
		RandomMonster,
		TeamMonster,
		PureMage,
		DexxerDuel
	}

	public enum PvpEventStatus
	{
		Idle,
		MatchStarting,
		MatchInProgress,
		MatchEnding
	}

	public enum PvpEventType
	{
		Normal,
		FFA,
		TeamFFA
	}

	public class PvpEvent : Event
	{

		private PvpEventStyle m_EventStyle;
		public PvpEventStyle EventStyle{get{return m_EventStyle;} set{m_EventStyle = value;} }

		private PvpEventType m_EventType;
		public PvpEventType EventType{get{return m_EventType;} set{m_EventType = value;} }

		private int m_TeamSize;
		public int TeamSize{get{return m_TeamSize;} set{m_TeamSize = value < 1 ? 1 : value; MinPlayers = m_TeamSize * m_TeamCount;} }

		private int m_TeamCount;
		public int TeamCount{get{return m_TeamCount;} set{m_TeamCount = value < 2 ? 2 : value;} }

		private bool m_TeamColors;
		public bool TeamColors{get{return m_TeamColors;} set{m_TeamColors = value;} }

		private Mobile m_Announcer;
		public Mobile Announcer{get{return m_Announcer;} set{m_Announcer=value;} }

		private Point3D m_LoseLocation;
		public Point3D LoseLocation{get{return m_LoseLocation;} set{m_LoseLocation=value;} }

		private string m_RewardItem;
		private int m_RewardItemAmount;
		private int m_WinnerCount;

		public string RewardItem{get{return m_RewardItem;} set{m_RewardItem = value;} }
		public int RewardItemAmount{get{return m_RewardItemAmount;} set{m_RewardItemAmount = value;} }
		public int WinnerCount{get{return m_WinnerCount;} set{m_WinnerCount = value;} }

		private bool m_CustomReward;
		private Layer m_CustomRewardLayer;
		private int m_CustomRewardID;
		private bool m_CustomRewardHued;

		public bool CustomReward{get{return m_CustomReward;} set{m_CustomReward = value;} }
		public Layer CustomRewardLayer{get{return m_CustomRewardLayer;} set{m_CustomRewardLayer = value;} }
		public int CustomRewardID{get{return m_CustomRewardID;} set{m_CustomRewardID = value;} }
		public bool CustomRewardHued{get{return m_CustomRewardHued;} set{m_CustomRewardHued = value;} }

		//Requirements
		private bool m_AllowArtifacts;
		private bool m_AllowPotions;
		private bool m_AllowHealing;

		public bool AllowArtifacts{get{return m_AllowArtifacts;} set{m_AllowArtifacts = value;} }
		public bool AllowPotions{get{return m_AllowPotions;} set{m_AllowPotions = value;} }
		public bool AllowHealing{get{return m_AllowHealing;} set{m_AllowHealing = value;} }


		//PvpEvent variables only
		private int m_Round;
		public int Round{get{return m_Round;} set{m_Round = value;} }
		private PvpEventStatus m_Status;
		public PvpEventStatus Status{get{return m_Status;} set{m_Status = value;} }
		private PvpFighterRegion m_FightRegion;
		private PvpSpectatorRegion m_SpectateRegion;
		private ArrayList m_FightingTeams;
		private ArrayList m_Eliminated;
		private ArrayList m_EliminatedTeams;
		private ArrayList m_Winners;
		private Team[] m_WinnerList;
		private PvpEventStone m_Stone;
		private ArrayList astr,adex,aint;
		private PvpTemplate pvpt;

		public ArrayList FightingTeams{get{return m_FightingTeams;} }

		public PvpEvent(PvpEventStone stone, Mobile host) : base(stone, host)
		{
			m_Stone = stone;
			m_EventStyle = stone.EventStyle;
			m_EventType = stone.EventTypeFlag;
			m_TeamSize = stone.TeamSize;
			m_TeamCount = stone.TeamCount;
			m_AllowArtifacts = stone.AllowArtifacts;
			m_AllowPotions = stone.AllowPotions;
			m_AllowHealing = stone.AllowHealing;
			m_TeamColors = stone.TeamColors;
			m_Announcer = stone.Announcer;
			m_RewardItem = stone.RewardItem;
			m_RewardItemAmount = stone.RewardItemAmount;
			m_WinnerCount = stone.WinnerCount;
			m_LoseLocation = stone.LoseLocation;

			m_CustomReward = stone.CustomReward;
			m_CustomRewardLayer = stone.CustomRewardLayer;
			m_CustomRewardID = stone.CustomRewardID;
			m_CustomRewardHued = stone.CustomRewardHued;

			m_Round = 0;
			m_Status = PvpEventStatus.Idle;
			m_SpectateRegion = new PvpSpectatorRegion( this, this.Map, stone.SpectateRegion);
			m_FightRegion = new PvpFighterRegion( this, this.Map, stone.FightRegion);
			m_Winners = new ArrayList();
			m_WinnerList = new Team[m_WinnerCount];
            pvpt= new PvpTemplate();
		}



		//For caveman / savage / any other theme
		public override void OnJoin(Mobile from)
		{
			bool UseTemplate=true;
			base.OnJoin(from);
			switch((int)m_EventStyle)
			{
				case (int)PvpEventStyle.ArtiWhore:
					pvpt = new ArtiWhore();
					break;
				case (int)PvpEventStyle.Savage:
					from.HueMod = 0;
					pvpt = new Savage();
					break;
				case (int)PvpEventStyle.Caveman:
					pvpt = new Caveman();
					break;
				case (int)PvpEventStyle.Wrestling:
					pvpt = new Wrestling();
					break;
				case (int) PvpEventStyle.PureMage:
					pvpt = new PureMage();
					break;
				case (int) PvpEventStyle.DexxerDuel:
					pvpt = new Dexxer();
					break;
				default : UseTemplate=false;
                	break;
				}
				if(UseTemplate) pvpt.Apply(from);
		}


		public void StartNextMatch()
		{
			ArrayList AbleTeams = new ArrayList();
			foreach(Team team in Teams)
			{
				if(team.Round == m_Round)
					AbleTeams.Add(team);
			}
			string message = "The next match will be ";
			m_Status = PvpEventStatus.MatchStarting;
			m_Eliminated = new ArrayList();
			m_EliminatedTeams = new ArrayList();
			ArrayList startingPositions = new ArrayList();
			Rectangle2D rect = (Rectangle2D) m_FightRegion.Coords[0];
			bool wide = rect.Width > rect.Height;
			int width = rect.Width - 1;
			int height = rect.Height - 1;

			//providing the fighting area is all a flat surface
			int z = JoinLocation.Z;
			int x = rect.X;
			int y = rect.Y;

			int North = 0;
			startingPositions.Add(new Point3D(x + (width / 2), y , z));

			int South = 1;
			startingPositions.Add(new Point3D(x + (width / 2), y + height , z));

			int East = 2;
			startingPositions.Add(new Point3D(x + width, y + (height / 2) , z));

			int West = 3;
			startingPositions.Add(new Point3D(x, y + (height / 2) , z));

			int NW = 4;
			startingPositions.Add(new Point3D(x, y , z));

			int NE = 5;
			startingPositions.Add(new Point3D(x + width, y , z));

			int SW = 6;
			startingPositions.Add(new Point3D(x, y + height , z));

			int SE = 7;
			startingPositions.Add(new Point3D(x + width, y + height , z));

			try
			{
				switch(m_TeamCount)
				{
					case 2:
						if(wide)
						{
							((Team)AbleTeams[0]).MoveTo(startingPositions[West]);
							((Team)AbleTeams[1]).MoveTo(startingPositions[East]);
						}
						else
						{
							((Team)AbleTeams[0]).MoveTo(startingPositions[North]);
							((Team)AbleTeams[1]).MoveTo(startingPositions[South]);
						}
						break;
					case 3:
						if(wide)
						{
							((Team)AbleTeams[0]).MoveTo(startingPositions[NW]);
							((Team)AbleTeams[1]).MoveTo(startingPositions[NE]);
							((Team)AbleTeams[2]).MoveTo(startingPositions[South]);
						}
						else
						{
							((Team)AbleTeams[0]).MoveTo(startingPositions[NW]);
							((Team)AbleTeams[1]).MoveTo(startingPositions[East]);
							((Team)AbleTeams[2]).MoveTo(startingPositions[SW]);
						}
						break;
					case 4:
						((Team)AbleTeams[0]).MoveTo(startingPositions[NW]);
						((Team)AbleTeams[1]).MoveTo(startingPositions[NE]);
						((Team)AbleTeams[2]).MoveTo(startingPositions[SW]);
						((Team)AbleTeams[3]).MoveTo(startingPositions[SE]);
						break;
					default:
						for(int i=0;i<m_TeamCount;i++)
						{
							((Team)AbleTeams[i]).MoveTo(new Point3D(Utility.Random(rect.X, width), Utility.Random(rect.Y, height),z));
						}
						break;
				}
				if(m_TeamCount == 2)
					message += ((Team)AbleTeams[0]).TeamName + " vs " + ((Team)AbleTeams[1]).TeamName;
				else
				{
					for(int i=0;i<m_TeamCount;i++)
					{
						if(i == m_TeamCount - 1)
						{
							message += "and " + ((Team)AbleTeams[i]).TeamName;
						}
						else
						{
							message += ((Team)AbleTeams[i]).TeamName + ", ";
						}
					}
				}

				m_FightingTeams = new ArrayList();
				for(int i=0;i<m_TeamCount;i++)
				{
					m_FightingTeams.Add(AbleTeams[i]);
					foreach(Mobile m in ((Team)AbleTeams[i]).Members)
					{
						if(m.Target != null)
							m.Target.Cancel(m, TargetCancelType.Canceled);
					}
				}

				DeltaNoto();

				message += " in a ";
				if(m_TeamCount == 2)
					message += m_TeamSize.ToString() + " vs " + m_TeamSize.ToString();
				else
					message += m_TeamSize > 1 ? "team" : "" + "free for all with " + m_TeamCount.ToString() + (m_TeamSize == 1 ? " players" : " teams");

				EventMessage(message);
				FreezeFighters(true);
				Timer.DelayCall(TimeSpan.FromSeconds(5),new TimerStateCallback(InitCurrentMatch), new object[]{false, 10});
			}
			catch(Exception e)
			{
				EventMessage("Error: StartNextMatch(Mobile from) - moving teams to start locations");
				Console.WriteLine(e.Message);
				Console.WriteLine(e.StackTrace);
				Console.WriteLine(e.TargetSite);
			}
		}

		public void DeltaNoto()
		{
			foreach(Team team in Teams)
			{
				foreach(Mobile mob in team.Members)
				{
					mob.Delta( MobileDelta.Noto );
				}
			}
		}

		public void BeginCurrentMatch()
		{
			FreezeFighters(false);
			m_Status = PvpEventStatus.MatchInProgress;
			new MatchTimer(this).Start();
		}

		private class MatchTimer : Timer
		{
			private PvpEvent E;
			public MatchTimer(PvpEvent e) : base(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1))
			{
				Priority = TimerPriority.OneSecond;
				E = e;
			}

			protected override void OnTick()
			{
				if(E.Status != PvpEventStatus.MatchInProgress || !EventSystem.EventList.Contains(E))
					Stop();

				foreach(Team t in E.FightingTeams)
				{
					foreach(Mobile m in t.Members)
					{
						if(m.NetState == null && m is PlayerMobile)
							m.Kill();
					}
				}
			}
		}

		public void InitCurrentMatch(object state)
		{
			object[] objects = (object[]) state;
			bool countdown = (bool)objects[0];
			int seconds = (int)objects[1];

			if(countdown)
			{
				if(seconds == 0)
				{
					EventMessage("FIGHT!");
					BeginCurrentMatch();
				}
				else
				{
					if(seconds == 5)
						EventMessage("The match will begin in 5 seconds");
					Timer.DelayCall(TimeSpan.FromSeconds(1),new TimerStateCallback(InitCurrentMatch), new object[]{true, --seconds});
				}
			}
			else
			{
				EventMessage("The match will begin in 10 seconds");
				Timer.DelayCall(TimeSpan.FromSeconds(1),new TimerStateCallback(InitCurrentMatch), new object[]{true, 9});
			}
		}

		public void FreezeFighters(bool frozen)
		{
			try
			{
				foreach(Team team in m_FightingTeams)
				{
					foreach(Mobile m in team.Members)
					{
						m.Frozen = frozen;
					}
				}
			}
			catch{}
		}

		public override void End(bool message)
		{
			foreach(Mobile m in Participants)
			{
				m.BodyMod = new Body(0);
				m.HueMod = -1;
				m.SolidHueOverride = -1;
				if(m_EventStyle != PvpEventStyle.Normal)
					pvpt.Restore(m);
			}
			m_SpectateRegion.Clean();
			m_FightRegion.Clean();
			base.End(true, false);
		}

		public void StartNextRound(Mobile from)
		{
			if(IsOpen)
			{
				from.SendMessage("The event must be closed to start the round.");
			}
			else if(Teams == null || Teams.Count == 0)
			{
				from.SendMessage("The event must be closed to start the round.");
			}
			else
			{
				m_Round++;
				EventMessage("Starting round {0}", m_Round.ToString());
				StartNextMatch();
			}
		}

		public override bool Close()
		{
			Console.WriteLine("Participants % TeamSize: {0}", ((int)Participants.Count % m_TeamSize).ToString());
			if(Participants.Count % m_TeamSize > 0)
			{
				int playersNeeded = m_TeamSize - (Participants.Count % m_TeamSize);
				World.Broadcast(62, true, "{0} more players are needed to even the teams for this {1} event ({2}). Use [event to join.",playersNeeded.ToString(), EventType, Name);	
				Host.SendMessage("Can't close due to un-even teams.");
			}
			else if(base.Close())
			{
				if(m_EventType == PvpEventType.FFA)
				{
					m_TeamCount = Participants.Count;
					m_TeamSize = 1;
				}
				else if(m_EventType == PvpEventType.TeamFFA)
				{
					m_TeamSize = (int) (Participants.Count / m_TeamCount);
				}
				SortTeams();
				m_Winners = (ArrayList)Teams.Clone();
				return true;
			}
			return false;
		}

		public bool OpposingFighters(Mobile mob1, Mobile mob2)
		{
			if(m_FightingTeams == null)
				return false;

			bool check1 = false;
			bool check2 = false;
			foreach(Team team in m_FightingTeams)
			{
				//If the team has only ONE of the mobs
				if(team.Contains(mob1) && !team.Contains(mob2))
				{
					check1 = true;
				}
				if(team.Contains(mob2) && !team.Contains(mob1))
				{
					check2 = true;
				}
			}
			return (check1 && check2 && (m_Status == PvpEventStatus.MatchStarting || m_Status == PvpEventStatus.MatchInProgress));
		}

		public void SortTeams()
		{

			ArrayList bufferParticipants = new ArrayList(Participants);
			Participants.Clear();
			while(bufferParticipants.Count > 0)
			{
				Mobile randomMobile = (Mobile) bufferParticipants[Utility.Random(bufferParticipants.Count)];
				Participants.Add(randomMobile);
				bufferParticipants.Remove(randomMobile);
			}
			bufferParticipants.Clear();

			Hashtable teamnames = new Hashtable();
			teamnames.Add(38,	"Red");
			teamnames.Add(3,	"Blue");
			teamnames.Add(68,	"Green");
			teamnames.Add(1234,	"Purple");
			teamnames.Add(52,	"Yellow");
			teamnames.Add(1150,	"White");
			teamnames.Add(1161,	"Blaze");
			teamnames.Add(1283,	"Neon");
			teamnames.Add(1157,	"Blood");
			teamnames.Add(1,	"Black");
			teamnames.Add(1175,	"Gray");
			teamnames.Add(1194,	"Arcane");
			teamnames.Add(1165,	"Sky");
			teamnames.Add(1166,	"Pink");
			teamnames.Add(1168,	"Magenta");
			teamnames.Add(1152,	"Ice");
			teamnames.Add(1174,	"Gold");

			Hashtable monsterteamnames = new Hashtable();
			monsterteamnames.Add(1, "Ogres");
			monsterteamnames.Add(2, "Ettins");
			monsterteamnames.Add(3, "Zombies");
			monsterteamnames.Add(4, "Gargoyles");
			monsterteamnames.Add(7, "Orc Lords");
			monsterteamnames.Add(8, "Corpsers");
			monsterteamnames.Add(9, "Daemonlords");
			monsterteamnames.Add(10, "Daemons");
			monsterteamnames.Add(11, "Spiders");
			monsterteamnames.Add(12, "Dragons");
			monsterteamnames.Add(13, "Electric Vortices");
			monsterteamnames.Add(14, "Earth Elementals");
			monsterteamnames.Add(15, "Fire Elementals");
			monsterteamnames.Add(16, "Water Elementals");
			monsterteamnames.Add(17, "Orcs");
			monsterteamnames.Add(18, "Ettins");
			monsterteamnames.Add(20, "Frost Spiders");
			monsterteamnames.Add(21, "Serpents");
			monsterteamnames.Add(22, "Gazers");
			monsterteamnames.Add(102, "Old Daemons");
			monsterteamnames.Add(103, "Serpentine Dragons");
			monsterteamnames.Add(104, "Skeletal Dragons");
			

			Teams = new ArrayList();
			int totalTeamCount = (int) Math.Ceiling(Participants.Count / m_TeamSize);
			for(int i=0; i < totalTeamCount;i++)
			{
				Team team = new Team(this);
				int added = 0;
				int j = 0;
				int teamindex = Utility.Random(teamnames.Count);
				int teamhue = 0;
				string teamname = "Nameless";
				int index = 0;
				foreach(DictionaryEntry de in teamnames)
				{
					if(index< teamindex)
						index++;
					else
					{
						teamhue = Convert.ToInt32(de.Key);
						teamname = de.Value.ToString();
						break;
					}
				}

				int bodymod = 0;
				if(m_EventStyle == PvpEventStyle.TeamMonster)
				{
					int random = Utility.Random(monsterteamnames.Count);
					index = 0;
					foreach(DictionaryEntry de in monsterteamnames)
					{
						if(index == random)
						{
							bodymod = Convert.ToInt32(de.Key);
							if(m_TeamColors)
								teamname += " " + de.Value.ToString();
							else
								teamname = de.Value.ToString();
							break;
						}
						else
							index++;
					}
					
					monsterteamnames.Remove(bodymod);
				}


				//Basically, while you're still adding teammates
				//OR while you're still adding to the last team
				//to put every last person on a team
				while(added < m_TeamSize || i == (totalTeamCount - 1) )
				{
					if(Participants.Count - 1 < j)
						break;

					Mobile m = Participants[j] as Mobile;

					if(m != null && !IsTeammed(m))
					{
						team.Add(m);
						added++;

						if(m_TeamSize > 1)
						{
							if(m_TeamColors)
							{
								m.SolidHueOverride = teamhue;
								team.TeamName = teamname;
							}
							else if(m_EventStyle == PvpEventStyle.TeamMonster)
							{
								team.TeamName = teamname;
							}
							else
							{
								team.TeamName = i.ToString();
							}
							if(m_EventStyle == PvpEventStyle.TeamMonster)
							{
								m.BodyMod = new Body(bodymod);
							}
							m.SendMessage(35, "You are on team {0}", teamname);
						}
						else
						{
							if(m_EventStyle == PvpEventStyle.RandomMonster)
							{
								int random = Utility.Random(monsterteamnames.Count);
								index = 0;
								bodymod = 0;
								foreach(DictionaryEntry de in monsterteamnames)
								{
									if(index == random)
									{
										bodymod = Convert.ToInt32(de.Key);
										break;
									}
									else
										index++;
								}
								m.BodyMod = new Body(bodymod);
							}
						}
					}

					j++;
				}
				if(m_TeamColors)
					teamnames.Remove(teamhue);
				team.Round = 1;
				Teams.Add(team);
			}
			if(m_WinnerCount > Teams.Count)
			{
				m_WinnerCount = Teams.Count;
				m_WinnerList = new Team[m_WinnerCount];
			}
		}

		public void MobileDied(Mobile from)
		{
			if(m_Status != PvpEventStatus.MatchInProgress)
			{
				return;
			}
			
			if(m_TeamSize > 1 || m_TeamCount > 2)
			{

				EventMessage("{0} has been eliminated!", from.Name);
				m_Eliminated.Add(from);
				CheckEliminations();
				from.MoveToWorld(JoinLocation, this.Map);
				CheckForWinner();
			}
			else
			{
				try
				{
					foreach(Team team in m_FightingTeams)
					{
						if(!team.Contains(from))
						{
							WinMatch(team);
						}
					}
				}
				catch
				{
					EventMessage("Error: MobileDied(Mobile from)");
				}
			}
		}

		public void CheckEliminations()
		{
			//team just got eliminated
			foreach(Team team in m_FightingTeams)
			{
				if(Eliminated(team) && !m_EliminatedTeams.Contains(team))
				{
					EliminateTeam(team);
				}
			}
		}

		public void CheckForWinner()
		{
			int remainingTeams = 0;
			Team winningTeam = null;
			foreach(Team team in m_FightingTeams)
			{
				if(!m_EliminatedTeams.Contains(team))
				{
					remainingTeams++;
					winningTeam = team;
				}

				if(remainingTeams > 1)
					return;
			}
			
			WinMatch(winningTeam);

		}

		public void WinMatch(Team team)
		{
			m_Status = PvpEventStatus.MatchEnding;
			ArrayList m_Losers = new ArrayList();
			Team[] losers = new Team[m_FightingTeams.Count - 1];
			Team bestLoser = null;
			DateTime timeLost = DateTime.Now.Subtract(TimeSpan.FromDays(1));
			
			ArrayList m_LosingTeams = (ArrayList) m_FightingTeams.Clone();
			m_LosingTeams.Remove(team);

			team.Peace();

			foreach(Team t in m_FightingTeams)
			{
				foreach(Mobile m in t.Members)
				{
					m.Hits = m.HitsMax;
					m.Mana = m.ManaMax;
					m.Stam = m.StamMax;
					m.CurePoison( m );
				}
			}

			for(int loserIndex = 0; loserIndex < losers.Length; loserIndex++)
			{
				
				foreach(Team loser in m_LosingTeams)
				{
					loser.Peace();
					if(loser.LastDeathTime.CompareTo(timeLost) > 0)
					{
						timeLost = loser.LastDeathTime;
						bestLoser = loser;
					}

				}

				losers[loserIndex] = bestLoser;
				m_LosingTeams.Remove(bestLoser);
				bestLoser = null;
				
				timeLost = DateTime.Now.Subtract(TimeSpan.FromDays(1));
			}


			for(int loserIndex = losers.Length - 1; loserIndex >= 0; loserIndex--)
			{
				Team l = losers[loserIndex];
				Lose(losers[loserIndex]);
			}
			

			//Move winning team members to winning spots
			Rectangle2D rect = (Rectangle2D)m_FightRegion.Coords[0];
			int startY = rect.Y + ((rect.Height-1) / 2);
			int startX = rect.X + ((rect.Width-1) / 2);
			bool wide = rect.Width > rect.Height;
			startX -= wide ? (team.Members.Count / 2) : 0;
			startY -= wide ? 0 : (team.Members.Count / 2);

			for(int i=0;i<team.Members.Count;i++)
			{
				int x = startX + ( wide ? i : 0 );
				int y = startY + ( wide ? 0 : i );
				((Mobile)team.Members[i]).MoveToWorld(new Point3D(x, y, JoinLocation.Z), this.Map);
				((Mobile)team.Members[i]).Frozen = true;
			}

			team.Round++;

			DeltaNoto();
			Timer.DelayCall(TimeSpan.FromSeconds(3), new TimerStateCallback(AnnounceWinner), team);
		}

		public void Lose(Team loser)
		{
			if(loser.Members.Count == 1)
			{
				loser.Deaths++;
				loser.LastDeathTime = DateTime.Now;
			}

			if(Teams.Contains(loser))
				Teams.Remove(loser);
			
			if(m_Winners.Count > m_WinnerCount)
			{
				if(m_Winners.Contains(loser))
					m_Winners.Remove(loser);
			}
			else if(m_Winners.Contains(loser))
			{
				loser.MoveTo(JoinLocation);
				EventMessage("{0} has lost their match but has still won a place in the event", loser.TeamName);
				return;
			}

			loser.MoveTo(m_LoseLocation);

			foreach(Mobile m in loser.Members)
			{
				m.BodyMod = new Body(0);
				m.HueMod = -1;
				m.SolidHueOverride = -1;
				if(m_EventStyle != PvpEventStyle.Normal)
					pvpt.Restore(m);
				m.SendMessage("You lost the match");
			}
		}

		public void AnnounceWinner(object state)
		{
			Team team = (Team) state;
			EventMessage("Congratulations to {0} for winning the match!", team.TeamName);
			Timer.DelayCall(TimeSpan.FromSeconds(8), new TimerCallback(FinishRound));
		}

		public void FinishRound()
		{
			ArrayList mobs = new ArrayList();
			foreach(Mobile mob in m_FightRegion.Mobiles)
				mobs.Add(mob);

			foreach(Mobile mob in mobs)
				if(mob.AccessLevel == AccessLevel.Player)
					mob.MoveToWorld(JoinLocation, this.Map);

			FreezeFighters(false);
			m_FightingTeams.Clear();
			Timer.DelayCall(TimeSpan.FromSeconds(5), new TimerCallback(TryNewMatch));
		}

		public bool CanMoveIntoArena(Mobile m)
		{
			if(m_FightingTeams.Contains(m))
				return true;
			m.SendMessage( "Only the fighters can be in this area." );
			return false;
		}

		public void TryNewMatch()
		{
			ArrayList AbleTeams = new ArrayList();
			foreach(Team team in Teams)
			{
				if(team.Round == m_Round)
					AbleTeams.Add(team);
			}
			if(AbleTeams.Count >= m_TeamCount)
			{
				StartNextMatch();
			}
			else
			{
				foreach(Team team in AbleTeams)
					team.Round++;
				EndRound(AbleTeams.Count, AbleTeams);
			}
		}

		public void EndRound(int i, ArrayList advanced)
		{
			m_Status = PvpEventStatus.Idle;
			if(m_EventType == PvpEventType.Normal)
			{
				if(i > 0)
					EventMessage("Round {0} has ended. {1} {2}s were automatically advanced due to an uneven number of participants", m_Round.ToString(), i.ToString(), m_TeamSize == 1 ? "player" : "team");
				else
					EventMessage("Round {0} has ended.", m_Round.ToString());
			}
			else
			{
				EventMessage("The {0} match has ended.", m_EventType.ToString());
			}

			ArrayList AbleTeams = new ArrayList();
			foreach(Team team in Teams)
			{
				if(team.Round == m_Round + 1)
					AbleTeams.Add(team);
			}

			if((AbleTeams.Count < m_TeamCount) || m_EventType != PvpEventType.Normal)
			{
				EventMessage("That was the final round");
				foreach(Team team in advanced)
				{
					team.Round--;
				}
				SortWinners();
			}
		}

		public void SortWinners()
		{
			m_WinnerCount = m_Winners.Count;
			m_WinnerList = new Team[m_WinnerCount];
			Team highRoundTeam = null;
			int highRound = 0;
			int highDeaths = 100;
			DateTime highDeathTime = DateTime.Now.Subtract(TimeSpan.FromHours(10));
			for(int i=0;i<m_WinnerCount;i++)
			{
				foreach(Team team in m_Winners)
				{
					if(team.Round > highRound)
					{
						highRoundTeam = team;
						highRound = team.Round;
						highDeaths = team.Deaths;
						highDeathTime = team.LastDeathTime;
					}
					else if(team.Round == highRound)
					{
						if(team.Deaths < highDeaths)
						{
							highRoundTeam = team;
							highRound = team.Round;
							highDeaths = team.Deaths;
							highDeathTime = team.LastDeathTime;
						}
						else if(team.LastDeathTime.CompareTo(highDeathTime) > 0)
						{
							highRoundTeam = team;
							highRound = team.Round;
							highDeaths = team.Deaths;
							highDeathTime = team.LastDeathTime;
						}
					}
				}
				if(highRoundTeam != null)
				{
					m_WinnerList[i] = highRoundTeam;
					m_Winners.Remove(highRoundTeam);
					highRound = 0;
					highDeaths = 100;
					highDeathTime = DateTime.Now.Subtract(TimeSpan.FromHours(10));
				}
			}
			Timer.DelayCall(TimeSpan.FromSeconds(10), new TimerCallback(AnnounceWinners));
		}

		public void AnnounceWinners()
		{
			EventMessage("Congratulations to the winners!");
			for(int i=m_WinnerList.Length-1;i>=0;i--)
			{
				
				int reverseIndex = m_WinnerList.Length - 1 - i;
				Timer.DelayCall(TimeSpan.FromSeconds(reverseIndex * 12), new TimerStateCallback(RewardWinner), i);
				Timer.DelayCall(TimeSpan.FromSeconds((reverseIndex * 12) + 10), new TimerStateCallback(FinishReward), i);
			}
		}

		public void RewardWinner(object state)
		{
			int i = (int) state;
			string[] place = new string[]{"1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th", "11th", "12th", "13th", "14th", "15th"};

			
			Team team = m_WinnerList[i];

			//Move winning team members to winning spots
			Rectangle2D rect = (Rectangle2D)m_FightRegion.Coords[0];
			int startY = rect.Y + ((rect.Height-1) / 2);
			int startX = rect.X + ((rect.Width-1) / 2);
			bool wide = rect.Width > rect.Height;
			startX -= wide ? (team.Members.Count / 2) : 0;
			startY -= wide ? 0 : (team.Members.Count / 2);

			for(int j=0;j<team.Members.Count;j++)
			{
				int x = startX + ( wide ? j : 0 );
				int y = startY + ( wide ? 0 : j );
				((Mobile)team.Members[j]).MoveToWorld(new Point3D(x, y, JoinLocation.Z), this.Map);
				((Mobile)team.Members[j]).Frozen = true;
			}

			string teamname = team.TeamName;
			if(m_TeamSize > 1)
			{
				teamname += ", which consisted of ";
				for(int j=0;j<team.Members.Count;j++)
				{
					if(j == team.Members.Count - 1)
					{
						teamname += "and " + ((Mobile)team.Members[j]).Name;
					}
					else
					{
						teamname += ((Mobile)team.Members[j]).Name + ", ";
					}
				}
			}

			if(i <= 15)
				EventMessage("In {0} place came {1}.", place[i], teamname);
			else
				EventMessage("In {0} place came {1}.", i.ToString(), teamname);

			if(i == 0)
				EventMessage("Congratulations!!!");


			int amount = (m_RewardItemAmount / m_WinnerCount) * (m_WinnerCount - i);
			if(amount < 1)
				amount = 1;

			if(m_RewardItem == "" || m_RewardItem == null)
				return;

			Type type = ScriptCompiler.FindTypeByName(m_RewardItem);

			if(type != null)
			{
				try
				{
					foreach(Mobile m in team.Members)
					{
						if(m.BankBox != null)
						{
							Item item = Activator.CreateInstance(type) as Item;
							if(item == null)
								continue;
							if(m_RewardItemAmount > 0)
								item.Amount = amount;
							m.BankBox.DropItem(item);
							m.SendMessage(68, "Your reward has been dropped in your bank box.");
						}

						if(i==0 && m.Backpack != null && m_CustomReward)
						{
							string date = String.Format("{0}/{1}/{2}", DateTime.Now.Month.ToString(), DateTime.Now.Day.ToString(), DateTime.Now.Year.ToString());
							string teaminfo = m_TeamSize > 1 ? String.Format("winning team member ({0})", team.TeamName) : "winner";
							string CustomRewardName = String.Format("{4}: {0} ({1}) {2} - {3}", this.Name, this.EventType, teaminfo, date, m.Name);
							m.SendMessage(68, "You have received a custom reward, it has been dropped in your bank box.");
							Item item = new Item(m_CustomRewardID);
							item.Layer = m_CustomRewardLayer;
							item.LootType = LootType.Blessed;
							item.Name = CustomRewardName;
							m.BankBox.DropItem(item);
							if(m_CustomRewardHued)
								m.SendGump(new RewardColorGump(item));
						}
					}
				}
				catch(Exception e)
				{
					Console.WriteLine(e.Message);
					Console.WriteLine(e.StackTrace);
				}

			}
			
		}

		public void FinishReward(object state)
		{
			int i = (int) state;
			Team team = m_WinnerList[i];
			foreach(Mobile m in team.Members)
			{
				m.Frozen = false;
				m.MoveToWorld(m_LoseLocation, this.Map);
				m.SolidHueOverride = -1;
			}
		}

		public bool Eliminated(Team team)
		{
			if(!m_FightingTeams.Contains(team))
				return true;
			foreach(Mobile m in team.Members)
			{
				if(!Eliminated(m))
					return false;
			}
			return true;
		}

		public bool Eliminated(Mobile mob)
		{
			return m_Eliminated.Contains(mob);
		}

		public void EliminateTeam(Team loser)
		{

			if(loser.Members.Count > 1)
				EventMessage("{0} has been eliminated!", loser.TeamName);

			loser.Deaths++;
			loser.LastDeathTime = DateTime.Now;
			m_EliminatedTeams.Add(loser);
		}

		public override void Start()
		{
		}

		public override void CleanUp()
		{
			base.CleanUp();
			m_Stone = null;
		}

		public override void EventMessage(string message)
		{
			m_Announcer.Say(message);
		}

		public override void EventMessage(string message, params object[] args)
		{
			message = String.Format(message, args);
			m_Announcer.Say(message);
		}

		/*
		private class InternalTimer : Timer
		{
			Event m_Event;

			public InternalTimer(PvpEvent e): base(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1))
			{
				m_Event = e;
			}

			protected override void OnTick()
			{
			}
		}*/


	}
}