//=============================================================================
// TeamGame.
//=============================================================================
class TeamGame expands DeathMatchGame
	config;

var() config bool   bSpawnInTeamArea;
var() config float  FriendlyFireScale; //scale friendly fire damage by this value
var() config int	MaxTeams; //Maximum number of teams allowed in (up to 16)
var	TeamInfo Teams[16]; 
var() config float  GoalTeamScore; //like fraglimit
var() config int	MaxTeamSize;

function PostBeginPlay()
{
	local int i;
	for (i=0;i<MaxTeams;i++)
	{
		Teams[i] = Spawn(class'TeamInfo');
		Teams[i].Size = 0;
		Teams[i].Score = 0;
	}
	
	CallParent.PostBeginPlay();
}

//------------------------------------------------------------------------------
// Player start functions


//FindPlayerStart
//- add teamnames as new teams enter
//- choose team spawn point if bSpawnInTeamArea

function playerpawn Login
(
	string[32]		Portal,
	string[120]     Options,
	out string[80 ] Error,
	class           SpawnClass
)
{
	local PlayerPawn newPlayer;
	local string[64]      InTeam;

	newPlayer = CallParent.Login(Portal, Options, Error, SpawnClass);
	if ( newPlayer == None)
		return None;

	InTeam     = ParseOption( Options, "Team"     );
	if ( !ChangeTeam(newPlayer, InTeam) )
		return None;
		
	return newPlayer;
}

function Logout(pawn Exiting)
{
	Teams[Exiting.Team].Size--;
	CallParent.Logout(Exiting);
}
	
function NavigationPoint FindPlayerStart(optional byte Team, optional string[32] incomingName)
{
	local PlayerStart Dest, Candidate[5], Best;
	local float Score[5], BestScore, NextDist;
	local pawn OtherPlayer;
	local int i, num;
	local Teleporter Tel;

	if( incomingName!="" )
		foreach AllActors( class 'Teleporter', Tel )
			if( string(Tel.Tag)~=incomingName )
				return Tel;
			
	num = 0;
	//choose candidates	
	foreach AllActors( class 'PlayerStart', Dest )
	{
		if ( !bSpawnInTeamArea || (Team == Dest.TeamNumber) )
		{  
			if (num<5)
				Candidate[num] = Dest;
			else if (Rand(num) < 5)
				Candidate[Rand(5)] = Dest;
			num++;
		}
	}
	
	if (num>5) num = 5;
	else if (num == 0)
		return None;
		
	//assess candidates
	for (i=0;i<num;i++)
		Score[i] = 4000 * FRand(); //randomize
		
	foreach AllActors( class 'Pawn', OtherPlayer )
	{
		if (OtherPlayer.bIsPlayer)
		{
			for (i=0;i<num;i++)
			{
				NextDist = Size(OtherPlayer.Location - Candidate[i].Location);
				Score[i] += NextDist;
				if (NextDist < CollisionRadius + CollisionHeight)
					Score[i] -= 1000000.0;
				else if (OtherPlayer.LineOfSightTo(Candidate[i]))
					Score[i] -= 2000.0;
			}
		}
	}
	
	BestScore = Score[0];
	Best = Candidate[0];
	for (i=1;i<num;i++)
	{
		if (Score[i] > BestScore)
		{
			BestScore = Score[i];
			Best = Candidate[i];
		}
	}			
	
	//if (BestScore < -500000.0) //then would telefrag - but then how to handle re-try?
	//	return None;
				
	return Best;
}


//-------------------------------------------------------------------------------------
// Level gameplay modification

//Use reduce damage for teamplay modifications, etc.
function int ReduceDamage(int Damage, name DamageType, pawn injured, pawn instigatedBy)
{
	local int reducedDamage;

	if (injured.Region.Zone.bNeutralZone)
		return 0;
	
	if ( instigatedBy == None )
		return Damage;

	Damage *= instigatedBy.DamageScaling;

	if ( (instigatedBy != injured) 
		&& (injured.Team ~= instigatedBy.Team) )
		return (Damage * FriendlyFireScale);
	else
		return Damage;
}

function Killed(pawn killer, pawn Other, name damageType)
{
	if ( (killer != Other) && (killer != None) )
		Teams[killer.Team].Score += 1.0;
				
	CallParent.Killed(killer, Other, damageType);
}

function bool ChangeTeam(Pawn Other, coerce string[32] PlayerTeam)
{
	local int i, s;
	local pawn APlayer;
	local teaminfo SmallestTeam;

	i = 0;
	SmallestTeam = None;

	while (i<MaxTeams)
	{
		if ( (Teams[i].Size < MaxTeamSize) 
				&& ((SmallestTeam == None) || (SmallestTeam.Size > Teams[i].Size)) )
		{
			s = i;
			SmallestTeam = Teams[i];
		}

		if ( (Teams[i].TeamName == PlayerTeam) || (Teams[i].Size == 0) )
		{
			if (Teams[i].Size < MaxTeamSize)
			{
				if ( PlayerTeam ~= "" )
					PlayerTeam = ("Team "$i);
				Teams[i].TeamName = PlayerTeam;
				Teams[i].Size++;
				Other.Team = i;
				BroadcastMessage(Other.PlayerName$" is now on "$PlayerTeam);
				return true;
			}
			if ( (PlayerTeam == "") && (SmallestTeam != None) )
			{
				SmallestTeam.Size++;
				Other.Team = s;
				BroadcastMessage(Other.PlayerName$" is now on "$SmallestTeam.TeamName);
				return true;
			}
			return false;
		}
		i++;
	}
	return false;
}

function bool CanSpectate( pawn Viewer, actor ViewTarget )
{
	return ( (Spectator(Viewer) != None) 
			|| ((Pawn(ViewTarget) != None) && (Pawn(ViewTarget).Team == Viewer.Team)) );
}

