
class BattleRoyaleUT extends DeathMatchPlus;

#exec AUDIO IMPORT NAME=uWon FILE=Sounds\uWon.wav Group=Announcer

var config bool bHighDetailGhosts;
var() int Lives;
var int TotalKills, NumGhosts;
var localized string AltStartupMessage;
var PlayerPawn LocalPlayer;
var bool bSlowTime;
var Pawn LastKilled;  
var MediaLoader ML;
var BRUTGameReplicationInfo GRI;

function PreBeginPlay()
{
	Super.PreBeginPlay();
   //Added it's own mutator class to allow easy changes
   Level.Game.BaseMutator.AddMutator(Level.Spawn(class'BRUT')); 
   
    //Spawn the media loader for the end game announcer
	ML=spawn(class'MediaLoader');
	ML.LoadSounds();
}

//Convert the standard pickups to CSWeapons
function PostBeginPlay()
{
	local Actor Other, W, NewW;	local Bandages 		BB;	local HealthVial 		HV;	local BladeHopper 	BH;
	local RazorAmmo 		RA;		local Clip 				CL;	local EClip 			EC;	local Shells 			SH;
	local RifleRound 		RR;		local RifleShell 		RS;	local ASMDAmmo 		AS;	local ShockCore 		SC;
	local StingerAmmo 	SA;		local PAmmo       	PA;	local ShellBox			SB;	local MiniAmmo			MA;
	local RocketCan		RC;		local RocketPack		RP;	local FlakBox  		FB;	local FlakAmmo			FA;
	local RifleAmmo 		RF;		local BulletBox		BU;	local Sludge			SL;	local BioAmmo			BI;
	local HealthPack		HP;		local SuperHealth		SU;	local Nalifruit 		NA;	local MedBox			MB;

	foreach AllActors(Class'Actor', Other)
	{
		ActorTweaking(Other);
	}

	ForEach AllActors(Class'Actor', W)
	{
		if ((W.Class == Class'Unrealshare.DispersionPistol' || W.Class == Class'Botpack.Chainsaw' || W.Class == Class'Botpack.ImpactHammer') && Pawn(W.Owner)==None)
		{
			NewW = Spawn(Class'Melee_Knife',,, W.Location, W.Rotation);
			W.Destroy();
		}
		//WEAPONS A REPLACEMENT -Split in two because of the 16 item array limit
		else if ((W.Class == Class'Unrealshare.Automag' || W.Class == Class'Botpack.Enforcer' 			|| W.Class == Class'UnrealI.GESBioRifle'
			|| W.Class == Class'Botpack.ShockRifle' 		|| W.Class == Class'Unrealshare.Stinger' 		|| W.Class == Class'Botpack.Pulsegun'
			|| W.Class == Class'Botpack.Ripper' 			|| W.Class == Class'UnrealI.Minigun' 			|| W.Class == Class'Botpack.Minigun2'
			|| W.Class == Class'Botpack.SniperRifle')	&& Pawn(W.Owner)==None)
		{
			NewW = Spawn(Class'RandWeaponsAReplacer',,, W.Location, W.Rotation);
			W.Destroy();
		}
		//WEAPONS B REPLACEMENT
		else if ((W.Class == Class'Botpack.UT_BioRifle' 	|| W.Class == Class'UnrealI.Quadshot' 			|| W.Class == Class'Unrealshare.ASMD'
			||	W.Class == Class'UnrealI.FlakCannon' 			|| W.Class == Class'Botpack.UT_FlakCannon' 	|| W.Class == Class'UnrealI.Razorjack'
			|| W.Class == Class'Unrealshare.Eightball' 		|| W.Class == Class'Botpack.UT_Eightball' 	|| W.Class == Class'UnrealI.Rifle')	
			&& Pawn(W.Owner)==None)
		{
			NewW = Spawn(Class'RandWeaponsBReplacer',,, W.Location, W.Rotation);
			W.Destroy();
		}
		//AMMO REPLACEMENT
		else if (W.Class == Class'UnrealI.RazorAmmo' 	|| W.Class == Class'Botpack.BladeHopper' 		|| W.Class == Class'Unrealshare.Clip'
			|| W.Class == Class'Botpack.EClip' 				|| W.Class == Class'Unrealshare.Shells' 		|| W.Class == Class'UnrealI.RifleRound'
			|| W.Class == Class'Botpack.RifleShell' 		|| W.Class == Class'Unrealshare.ASMDAmmo' 	|| W.Class == Class'Botpack.ShockCore'
         || W.Class == Class'Unrealshare.StingerAmmo' || W.Class == Class'Botpack.PAmmo' 				|| W.Class == Class'Unrealshare.ShellBox'
			|| W.Class == Class'Botpack.MiniAmmo' 			|| W.Class == Class'Unrealshare.RocketCan' 	|| W.Class == Class'Botpack.RocketPack'
  			|| W.Class == Class'UnrealI.FlakBox' 			|| W.Class == Class'Botpack.FlakAmmo' 			|| W.Class == Class'UnrealI.RifleAmmo'
			|| W.Class == Class'Botpack.BulletBox' 		|| W.Class == Class'Botpack.SuperShockCore' 	|| W.Class == Class'UnrealI.Sludge'
			|| W.Class == Class'Botpack.BioAmmo')
		{
			NewW = Spawn(Class'RandAmmoReplacer',,, W.Location, W.Rotation);
			W.Destroy();
			//Radius checks are used to keep number of pickups low and force movement of players
			foreach RadiusActors(class'BladeHopper', BH, 200, NewW.Location)
				BH.Destroy();
			foreach RadiusActors(class'RazorAmmo', RA, 200, NewW.Location)
				RA.Destroy();
			foreach RadiusActors(class'Clip', CL, 200, NewW.Location)
				CL.Destroy();
			foreach RadiusActors(class'EClip', EC, 200, NewW.Location)
				EC.Destroy();
			foreach RadiusActors(class'Shells', SH, 200, NewW.Location)
				SH.Destroy();
			foreach RadiusActors(class'RifleRound', RR, 200, NewW.Location)
				RR.Destroy();
			foreach RadiusActors(class'RifleShell', RS, 200, NewW.Location)
				RS.Destroy();
			foreach RadiusActors(class'ASMDAmmo', AS, 200, NewW.Location)
				AS.Destroy();
			foreach RadiusActors(class'ShockCore', SC, 200, NewW.Location)
				SC.Destroy();
			foreach RadiusActors(class'StingerAmmo', SA, 200, NewW.Location)
				SA.Destroy();
			foreach RadiusActors(class'PAmmo', PA, 200, NewW.Location)
				PA.Destroy();
			foreach RadiusActors(class'ShellBox', SB, 200, NewW.Location)
				SB.Destroy();
			foreach RadiusActors(class'MiniAmmo', MA, 200, NewW.Location)
				MA.Destroy();
			foreach RadiusActors(class'RocketCan', RC, 200, NewW.Location)
				RC.Destroy();
			foreach RadiusActors(class'RocketPack', RP, 200, NewW.Location)
				RP.Destroy();
			foreach RadiusActors(class'FlakBox', FB, 200, NewW.Location)
				FB.Destroy();
			foreach RadiusActors(class'FlakAmmo', FA, 200, NewW.Location)
				FA.Destroy();
			foreach RadiusActors(class'RifleAmmo', RF, 200, NewW.Location)
				RF.Destroy();
			foreach RadiusActors(class'BulletBox', BU, 200, NewW.Location)
				BU.Destroy();
			foreach RadiusActors(class'Sludge', SL, 200, NewW.Location)
				SL.Destroy();
			foreach RadiusActors(class'BioAmmo', BI, 200, NewW.Location)
				BI.Destroy();
		}
		//HEALTH,ARMOR,GRENADES
		else if (W.Class == Class'Botpack.UT_ShieldBelt' 	|| W.Class == Class'UnrealI.PowerShield'		|| W.Class == Class'Botpack.MedBox'
			|| W.Class == Class'UnrealShare.ShieldBelt' 		|| W.Class == Class'Botpack.UDamage' 			|| W.Class == Class'Botpack.Armor2'
			|| W.Class == Class'UnrealShare.Armor' 			|| W.Class == Class'UnrealShare.Amplifier' 	|| W.Class == Class'Botpack.ThighPads'
			|| W.Class == Class'UnrealI.Dampener' 				|| W.Class == Class'UnrealI.AsbestosSuit' 	|| W.Class == Class'UnrealShare.KevlarSuit'
			|| W.Class == Class'UnrealI.ToxinSuit' 			|| W.Class == Class'Botpack.UT_JumpBoots' 	|| W.Class == Class'UnrealI.JumpBoots'
			|| W.Class == Class'Botpack.HealthPack' 			|| W.Class == Class'UnrealShare.SuperHealth' ||W.Class == Class'UnrealShare.Bandages'
			|| W.Class == Class'Botpack.HealthVial' 			|| W.Class == Class'UnrealI.Seeds' 				|| W.Class == Class'UnrealShare.NaliFruit')
		{
			NewW = Spawn(Class'RandItemReplacer',,, W.Location, W.Rotation);
			W.Destroy();
			foreach RadiusActors(class'HealthPack', HP, 200, NewW.Location)
				HP.Destroy();
			foreach RadiusActors(class'SuperHealth', SU, 200, NewW.Location)
				SU.Destroy();
			foreach RadiusActors(class'Bandages', BB, 200, NewW.Location)
				BB.Destroy();
			foreach RadiusActors(class'HealthVial', HV, 200, NewW.Location)
				HV.Destroy();
			foreach RadiusActors(class'NaliFruit', NA, 200, NewW.Location)
				NA.Destroy();
			foreach RadiusActors(class'MedBox', MB, 200, NewW.Location)
				MB.Destroy();
		}
		//SUPERWEAPON
		else 	if (W.Class == Class'Botpack.WarHeadLauncher' || W.Class == Class'Botpack.SuperShockRifle')
		{
			NewW = Spawn(Class'Sniper_AWM',,, W.Location, W.Rotation);
			W.Destroy();
		}
		else 	if (W.Class == Class'Botpack.WarheadAmmo')
			W.Destroy();
	}
	Super.PostBeginPlay();
}

//Replace contents of any decorations
simulated function ActorTweaking(Actor Other)
{
	if(Decoration(Other) != None)
	{
		Switch(Decoration(Other).Contents)
		{
			case class'Clip':
				Decoration(Other).Contents = Class'BRUT.AmmoPistols';
				break;
			case class'Sludge':
				Decoration(Other).Contents = Class'BRUT.AmmoShotgun';
				break;
			case class'ASMDAmmo':
				Decoration(Other).Contents = Class'BRUT.AmmoSMG';
				break;
			case class'StingerAmmo':
				Decoration(Other).Contents = Class'BRUT.AmmoRifles';
				break;
			case class'RazorAmmo':
				Decoration(Other).Contents = Class'BRUT.AmmoGrenade_Frag';
				break;
			case class'ShellBox':
				Decoration(Other).Contents = Class'BRUT.AmmoRifles';
				break;
			case class'FlakBox':
				Decoration(Other).Contents = Class'BRUT.AmmoMachine';
				break;
			case class'RocketCan':
				Decoration(Other).Contents = Class'BRUT.AmmoRifles';
				break;
			case class'RifleAmmo':
				Decoration(Other).Contents = Class'BRUT.AmmoSniper';
				break;
			case class'Armor':
				Decoration(Other).Contents = Class'BRUT.KevlarOne';
				break;
			case class'Suits':
				Decoration(Other).Contents = Class'BRUT.KevlarOne';
				break;
			case class'EClip':
				Decoration(Other).Contents = Class'BRUT.AmmoPistols';
				break;
			case class'BioAmmo':
				Decoration(Other).Contents = Class'BRUT.AmmoShotgun';
				break;
			case class'ShockCore':
				Decoration(Other).Contents = Class'BRUT.AmmoSMG';
				break;
			case class'PAmmo':
				Decoration(Other).Contents = Class'BRUT.AmmoRifles';
				break;
			case class'BladeHopper':
				Decoration(Other).Contents = Class'BRUT.AmmoGrenade_Frag';
				break;
			case class'MiniAmmo':
				Decoration(Other).Contents = Class'BRUT.AmmoRifles';
				break;
			case class'FlakAmmo':
				Decoration(Other).Contents = Class'BRUT.AmmoMachine';
				break;
			case class'RocketPack':
				Decoration(Other).Contents = Class'BRUT.AmmoRifles';
				break;
			case class'BulletBox':
				Decoration(Other).Contents = Class'BRUT.AmmoSniper';
				break;
			case class'Armor2':
				Decoration(Other).Contents = Class'BRUT.KevlarOne';
				break;
			case class'ThighPads':
				Decoration(Other).Contents = Class'BRUT.KevlarOne';
				break;
			case class'DispersionPistol':
				Decoration(Other).Contents = Class'BRUT.Melee_Knife';
				break;
			case class'AutoMag':
				Decoration(Other).Contents = Class'BRUT.Pistol_Deagle';
				break;
			case class'GESBioRifle':
				Decoration(Other).Contents = Class'BRUT.Shotgun_M3';
				break;
			case class'ASMD':
				Decoration(Other).Contents = Class'BRUT.SMG_MP5';
				break;
			case class'Stinger':
				Decoration(Other).Contents = Class'BRUT.Rifle_M4A1';
				break;
			case class'Razorjack':
				Decoration(Other).Contents = Class'BRUT.Grenade_Frag';
				break;
			case class'Minigun':
				Decoration(Other).Contents = Class'BRUT.Rifle_Aug';
				break;
			case class'FlakCannon':
				Decoration(Other).Contents = Class'BRUT.HeavyRifle_M249';
				break;
			case class'Rifle':
				Decoration(Other).Contents = Class'BRUT.Sniper_AWM';
				break;
			case class'ImpactHammer':
				Decoration(Other).Contents = Class'BRUT.Melee_Knife';
				break;
			case class'Enforcer':
				Decoration(Other).Contents = Class'BRUT.Pistol_Deagle';
				break;
			case class'UT_BioRifle':
				Decoration(Other).Contents = Class'BRUT.Shotgun_M3';
				break;
			case class'ShockRifle':
				Decoration(Other).Contents = Class'BRUT.SMG_MP5';
				break;
			case class'Pulsegun':
				Decoration(Other).Contents = Class'BRUT.Rifle_AK47';
				break;
			case class'Ripper':
				Decoration(Other).Contents = Class'BRUT.Grenade_Frag';
				break;
			case class'minigun2':
				Decoration(Other).Contents = Class'BRUT.Rifle_SG550';
				break;
			case class'UT_FlakCannon':
				Decoration(Other).Contents = Class'BRUT.HeavyRifle_M249';
				break;
			case class'UT_Eightball':
				Decoration(Other).Contents = Class'BRUT.Rifle_M4A1';
				break;
			case class'SniperRifle':
				Decoration(Other).Contents = Class'BRUT.Sniper_AWM';
				break;
			case class'WarHeadLauncher':
				Decoration(Other).Contents = Class'BRUT.Sniper_AWM';
				break;
			case class'SuperShockRifle':
				Decoration(Other).Contents = Class'BRUT.Sniper_AWM';
				break;
		}
	}
}

//Need to clean up the gamegoal message
function PlayStartUpMessage(PlayerPawn NewPlayer)
{
   local int i;

   NewPlayer.ClearProgressMessages();
   NewPlayer.SetProgressMessage(GameName, i++);

   if (fraglimit > 0)
      NewPlayer.SetProgressMessage(GameGoal, i++);

   if (Level.NetMode == NM_Standalone)
      NewPlayer.SetProgressMessage(SingleWaitingMessage, i++);
   else if (bRequireReady)
      NewPlayer.SetProgressMessage(TourneyMessage, i++);
}

event InitGame(string Options, out string Error)
{
   local string InOpt;

   Super.InitGame(Options, Error);

   RemainingTime = 60 * TimeLimit;
   SetGameSpeed(GameSpeed);
   FragLimit = 1;
   TimeLimit = GetIntOption(Options, "TimeLimit", TimeLimit);
   MaxCommanders = GetIntOption(Options, "MaxCommanders", MaxCommanders);

   InOpt = ParseOption(Options, "CoopWeaponMode");
   if (InOpt != "")
      bCoopWeaponMode = bool(InOpt);

   IDnum = -1;
   IDnum = GetIntOption(Options, "Tournament", IDnum);
   if (IDnum > 0)
   {
      bRatedGame = true;
      TimeLimit = 0;
      RemainingTime = 0;
   }
   if (bTournament)
   {
      bRequireReady = true;
      CheckReady();
   }
   if (Level.NetMode == NM_StandAlone)
   {
      bRequireReady = true;
      CountDown = 1;
   }
   if (!bRequireReady && (Level.NetMode != NM_Standalone))
   {
      bRequireReady = true;
      bNetReady = true;
   }

   Lives = Fraglimit;
}

function float GameThreatAdd(Bot aBot, Pawn Other)
{
   if (!Other.bIsPlayer)
      return 0;
   else
      return 0.1 * Other.PlayerReplicationInfo.Score;
}

event playerpawn Login(string Portal,string Options,out string Error,class<playerpawn> SpawnClass)
{
   local playerpawn NewPlayer;
   local Pawn P;

   // if more than 15% of the game is over, must join as spectator
   if (TotalKills > 0.15 * (NumPlayers + NumBots) * Lives)
   {
      bDisallowOverride = true;
      SpawnClass = class'CHSpectator';
      if ((NumSpectators >= MaxSpectators) && ((Level.NetMode != NM_ListenServer) || (NumPlayers > 0)))
      {
         MaxSpectators++;
      }
   }
   NewPlayer = Super.Login(Portal, Options, Error, SpawnClass);

   if ((NewPlayer != None) && !NewPlayer.IsA('Spectator') && !NewPlayer.IsA('Commander'))
      NewPlayer.PlayerReplicationInfo.Score = Lives;

   return NewPlayer;
}

event PostLogin(playerpawn NewPlayer)
{
   if(NewPlayer.Player != None && Viewport(NewPlayer.Player) != None)
      LocalPlayer = NewPlayer;

   if ((TotalKills > 0.15 * (NumPlayers + NumBots) * Lives) && NewPlayer.IsA('CHSpectator'))
      GameName = AltStartupMessage;
   Super.PostLogin(NewPlayer);
   GameName = Default.GameName;
}

function bool NeedPlayers()
{
   if (bGameEnded || (TotalKills > 0.15 * (NumPlayers + NumBots) * Lives))
      return false;
   return (NumPlayers + NumBots < MinPlayers);
}

function bool RestartPlayer(pawn aPlayer)
{
   local NavigationPoint startSpot;
   local bool foundStart;
   local Pawn P;

   if(bRestartLevel && Level.NetMode!=NM_DedicatedServer && Level.NetMode!=NM_ListenServer)
      return true;

   if (aPlayer.PlayerReplicationInfo.Score < 1)
   {
      BroadcastLocalizedMessage(class'BRUTOutMessage', 0, aPlayer.PlayerReplicationInfo);
      For (P=Level.PawnList; P!=None; P=P.NextPawn)
         if (P.bIsPlayer && (P.PlayerReplicationInfo.Score >= 1))
            P.PlayerReplicationInfo.Score += 0.00001;
      if (aPlayer.IsA('Bot'))
      {
         aPlayer.PlayerReplicationInfo.bIsSpectator = true;
         aPlayer.PlayerReplicationInfo.bWaitingPlayer = true;
         aPlayer.GotoState('GameEnded');
         return false; // bots don't respawn when ghosts
      }
   }
   startSpot = FindPlayerStart(None, 255);
   if(startSpot == None)
      return false;
   foundStart = aPlayer.SetLocation(startSpot.Location);
   if(foundStart)
   {
      startSpot.PlayTeleportEffect(aPlayer, true);
      aPlayer.SetRotation(startSpot.Rotation);
      aPlayer.ViewRotation = aPlayer.Rotation;
      aPlayer.Acceleration = vect(0,0,0);
      aPlayer.Velocity = vect(0,0,0);
      aPlayer.Health = aPlayer.Default.Health;
      aPlayer.ClientSetRotation(startSpot.Rotation);
      aPlayer.bHidden = false;
      aPlayer.SoundDampening = aPlayer.Default.SoundDampening;
      if (aPlayer.PlayerReplicationInfo.Score < 1)
      {
         // This guy is a ghost.  Add a visual effect.
         if (bHighDetailGhosts)
         {
            aPlayer.Style = STY_Translucent;
            aPlayer.ScaleGlow = 0.5;
         }
         else
            aPlayer.bHidden = true;
         aPlayer.PlayerRestartState = 'PlayerSpectating';
      }
      else
      {
         aPlayer.SetCollision(true, true, true);
         AddDefaultInventory(aPlayer);
      }
   }
   return foundStart;
}

function Logout(pawn Exiting)
{
   Super.Logout(Exiting);

   if(LocalPlayer == None || Exiting != LocalPlayer)
   	CheckEndGame();
}

function Killed(pawn killer, pawn Other, name damageType)
{
   local int OldFragLimit;

   OldFragLimit = FragLimit;
   FragLimit = 0;

   if (Other.bIsPlayer)
      TotalKills++;

	//Keep track of last person killed
   LastKilled = Other;

   Super.Killed(Killer, Other, damageType);
   FragLimit = OldFragLimit;
   CheckEndGame();
}

function CheckEndGame()
{
   local Pawn PawnLink;
   local int StillPlaying;
   local bool bStillHuman;
   local bot B, D, BB;
   local actor A;

   if (bGameEnded)
      return;

   // Check to see if everyone is a ghost.
   NumGhosts = 0;
   for (PawnLink=Level.PawnList; PawnLink!=None; PawnLink=PawnLink.nextPawn)
      if (PawnLink.bIsPlayer)
      {
         if (PawnLink.PlayerReplicationInfo.Score < 1)
            NumGhosts++;
         else
         {
            if (PawnLink.IsA('PlayerPawn'))
               bStillHuman = true;
            StillPlaying++;
         }
      }

   // End the game if there is only one man standing.
   if (StillPlaying < 2)
   {
   	if (FRand() < 0.65)
   	{
			BRUTGameReplicationInfo(GameReplicationInfo).bSlowTime=True;
   		SetKillCam();
   	}
   	else
   	{
      	EndGame("BRUT");
      	foreach AllActors(class'Bot',BB) //added check to stop bots respawning
        		BB.GotoState('GameEnded');
      }
   }
   else if (!bStillHuman)
   {
      // no humans left - get bots to be more aggressive and finish up
      for (PawnLink=Level.PawnList; PawnLink!=None; PawnLink=PawnLink.NextPawn)
      {
         B = Bot(PawnLink);
         if (B != None)
         {
            B.CampingRate = 0;
            B.Aggressiveness += 5.0;
            if (D == None)
               D = B;
            else if (B.Enemy == None)
               B.SetEnemy(D);
         }
      }
   }
}

function SetKillCam()
{
   local pawn P;
   local PlayerPawn Player;

   for (P=Level.PawnList; P!=None; P=P.nextPawn)
   {
      Player = PlayerPawn(P);
      if (Player != None)
      {
         Player.bBehindView = true;
         Player.ViewTarget = LastKilled;
      }
   }
}

function ScoreKill(pawn Killer, pawn Other)
{
   Other.DieCount++;
   if (Other.PlayerReplicationInfo.Score > 0)
      Other.PlayerReplicationInfo.Score -= 1;
   if((killer != Other) && (killer != None))
      killer.killCount++;
   BaseMutator.ScoreKill(Killer, Other);
}

function bool PickupQuery(Pawn Other, Inventory item)
{
   if (Other.PlayerReplicationInfo.Score < 1)
      return false;

   return Super.PickupQuery(Other, item);
}
function byte AssessBotAttitude(Bot aBot, Pawn Other)
{
   local float Adjust;

   if (aBot.bNovice)
      Adjust = -0.2;
   else
      Adjust = -0.2 - 0.1 * aBot.Skill;
   if (Other.bIsPlayer && (Other.PlayerReplicationInfo.Score < 1))
      return 2; //bots ignore ghosts
   else if (aBot.bKamikaze)
      return 1;
   else if (Other.IsA('TeamCannon') || (aBot.RelativeStrength(Other) > aBot.Aggressiveness - Adjust))
      return 0;
   else
      return 1;
}

function ModifyBehaviour(Bot NewBot)
{
   // Set the Bot's Lives
   NewBot.PlayerReplicationInfo.Score = Lives;
   NewBot.CampingRate += FRand();
}

function bool OneOnOne()
{
   return (NumPlayers + NumBots - NumGhosts == 2);
}

function bool SetEndCams(string Reason)
{
   local pawn P, Best;
   local PlayerPawn Player;
   local Bot NonPlayer;
   local sound Announcement;
   local int numAnnounce;
   local Vector X;
	local	int hs;

   // find individual winner
   for (P=Level.PawnList; P!=None; P=P.nextPawn)
      if (P.bIsPlayer && !P.IsA('Spectator') && ((Best == None) || (P.PlayerReplicationInfo.Score > Best.PlayerReplicationInfo.Score)))
         Best = P;

   // check for tie
   for (P=Level.PawnList; P!=None; P=P.nextPawn)
      if (P.bIsPlayer && (Best != P) && (P.PlayerReplicationInfo.Score == Best.PlayerReplicationInfo.Score))
      {
         BroadcastLocalizedMessage(DMMessageClass, 0);
         return false;
      }

   EndTime = Level.TimeSeconds + 3.0;
   GameReplicationInfo.GameEndedComments = GameEndedMessage;

   for (P=Level.PawnList; P!=None; P=P.nextPawn)
   {
      NonPlayer = Bot(P);
      if (NonPlayer != None)
      {
			if (NonPlayer != Best)  //force gib the final loser for visual effect
         	NonPlayer.TakeDamage(1000, Pawn(Owner), Location, 60000 * X, 'jolted');
      }
   }

   for (P=Level.PawnList; P!=None; P=P.nextPawn)
   {
      Player = PlayerPawn(P);
      if (Player != None)
      {
      	if (!bTutorialGame)
         {
          	if(ML.sndAnnouncerSoundSize > 0) //grab a random announcer if configured
          	{
					hs=rand(ML.sndAnnouncerSoundSize);
         		Player.ClientPlaySound(ML.sndAnnouncerSound[hs], true, true);
         	}
         	else
				Player.ClientPlaySound(sound'uWon', true, true);
				
            Player.bBehindView = true;
            if (Player == Best)
                Player.ViewTarget = None;
            else      
                Player.ViewTarget = Best;

				Player.ClientGameEnded();
        	}
        	P.GotoState('GameEnded');
    	}
	}

	CalcEndStats();
   return true;
}

defaultproperties
{
	HUDType=Class'BRUTHUD'
	FragLimit=1
	gamegoal="Kill everyone to win"
   bAlwaysForceRespawn=True
   StartMessage="There can be only one!"
   GameEndedMessage="YOU ARE THE LAST PERSON STANDING!"
   ScoreBoardType=Class'BRUTScoreBoard'
   RulesMenuType="UTMenu.UTLMSRulesSC"
   BeaconName="DM"
   GameName="BattleRoyale UT"
	MutatorClass=Class'DMNoLogMutator'
	GameReplicationInfoClass=Class'BRUTGameReplicationInfo'
}

