//  Original mod done by spongebobut@yahoo.com | www.unrealriders.de code used with his permission
//  Also contains some work done by BobIsUnreal, thank you B
//  and from Nelsona, thank you Nels!
//  Code condensing and simplification for use in MH done by gopostal

class BRespawn extends Mutator;

var bool Initialized;
struct BTPlayers
{
	var PlayerPawn BTPP;
   var Checkpoint CP;
};
var BTPlayers BTP[32];
var PlayerPawn PlayerOwner;
var Pawn P;

replication 
{
  	reliable if (role == ROLE_Authority)
    	BTP;
}

function PreBeginPlay() 
{
	if (Initialized) return;
  	Initialized = True;

	Level.Game.BaseMutator.AddMutator(self);
}

function PostBeginPlay()
{
	SetTimer(10, True);

   if ( NextMutator != None )
      NextMutator.PostBeginPlay();
}

function Timer()
{
	local Pawn P;
	local Teleporter T;
  	local int i;
  	local rotator r;

  	if (Level.Game.bGameEnded) return;

  	searchForLeftPlayers();

   for (P = Level.PawnList; P != None; P = P.NextPawn)
   {
   	if (P.IsA('PlayerPawn'))
   	{
   		//Zone checks
   		if((P.Region.Zone != none) && (!P.Region.Zone.bWaterZone) && (!P.Region.Zone.bPainZone) &&
			(!P.Region.Zone.bKillZone) && (!P.Region.Zone.isA('WarpZone')) && (!P.Region.Zone.isA('TeleporterZone')) &&
			(!P.Region.Zone.isA('VacuumZone')) && (P.health >= 1) && (!P.PlayerReplicationInfo.bWaitingPlayer) &&
			(P.Physics != PHYS_Falling) && (P.Physics != PHYS_Swimming) && (P.Physics != PHYS_Flying) &&
			(P.Base != none) && (!P.Base.isA('Mover')) && !NearbyMonsters(P))
			{
    			foreach RadiusActors(class'Teleporter', T, 24.0, P.Location)   //too close to teleporter
      			return;

  				if(BTP[i].CP != none)  // Move old checkpoint
				{
					BTP[i].CP.setLocation(P.Location+vect(0,0,-38));
					r.Yaw = P.Rotation.Yaw;
					BTP[i].CP.setRotation(r);
					return;
  				}
  				else
  					BTP[i].CP = spawn(class'Checkpoint', P, , P.Location, P.Rotation);  //Add new one
			}
		}
	}
}

function ModifyPlayer(Pawn Other)   // Handles player respawn
{
  	local PlayerPawn PP;
  	local int i;

  	if(!Other.IsA('TournamentPlayer')) 
	{
    	if (NextMutator != None) 
		 	NextMutator.ModifyPlayer(Other);
    	return;
  	}

	PP = PlayerPawn(other);
  	i = GetPlayerIndex(PP);

  	if(BTP[i].CP != none && PP.PlayerReplicationInfo.deaths > 0) 
	{
    	Level.Game.PlayTeleportEffect(PP, false, true);
    	PP.SetLocation(BTP[i].CP.Location);
    	PP.ClientSetRotation(BTP[i].CP.Rotation);
    	PP.viewRotation = BTP[i].CP.Rotation;
  	}
  	
  	if(BTP[i].CP != none)  // Remove old checkpoint
	{
    	BTP[i].CP.destroy();
    	BTP[i].CP = none;
  	}

  	if (NextMutator != None)
	  	NextMutator.ModifyPlayer(Other);
}

function AddMutator(Mutator M)
{
  	if(M == none) return;
  
	if (M.Class != Class) 
		Super.AddMutator(M);
	else if(M != Self) 
		M.Destroy();
}

function searchForLeftPlayers()    // Removes old CPs and clears data
{
  	local int i;

  	for (i=0;i<ArrayCount(BTP);i++)
	{
    	if (BTP[i].BTPP == none || BTP[i].BTPP.Player == none) 
		{
      	if(BTP[i].CP != none) 
				BTP[i].CP.destroy();

      	BTP[i].CP = none;
    	}
  	}
}

simulated function int GetPlayerIndex(PlayerPawn Player) 
{
  	local int i, FirstEmptySlot;

  	FirstEmptySlot = -1;
  	for (i = 0; i < ArrayCount(BTP); i++)   // Search existing entries
	{
    	if (BTP[i].BTPP == Player) 
		 	break;
    	else if (BTP[i].BTPP == None && FirstEmptySlot == -1) 
		 	FirstEmptySlot = i;
  	}

  	if (i == ArrayCount(BTP))  // Not found, create new entry
	{
    	i = FirstEmptySlot;
    	BTP[i].BTPP = Player;
    	BTP[i].CP = none;
  	}
  	return i;
}

function Killed( pawn Killer, pawn Other, name damageType )
{
  	local int i;

	if ((Other != None) && ((Killer == None) || (Killer == Other)) && (DamageType == 'Suicided'))
	{
  		if(BTP[i].CP != none)
		{
    		BTP[i].CP.destroy();
    		BTP[i].CP = none;
  		}
  		Other.ClientMessage("Suicide detected, checkpoint removed");
	}
}

final function bool NearbyMonsters(Actor A)
{
	local bool bResult;
	local Pawn P1;

	if (A == None)
	{
		bResult = False;
		GoTo Resulting;
	}

	if (P == None || P.bDeleteMe)
	{
		bResult = False;
		GoTo Resulting;
	}

	foreach RadiusActors(class 'Pawn',P1,700,Location)
	{
		if (P1 != P && P.DrawType == DT_Mesh && P.Mesh != None && !P.bHidden)
		{
			if (P1.PlayerReplicationInfo == None && FastTrace(A.Location+vect(0,0,30),P1.Location))
			{
				bResult = True;
				break;
			}
		}
	}
Resulting:
	return bResult;
}

defaultproperties
{
  	bAlwaysTick=True
  	bAlwaysRelevant=True
  	RemoteRole=ROLE_SimulatedProxy
}
