/*

struct tker
{
	var string PlayerName;
	var string PlayerIP;
	var int pain;  
	var int nbtk;     
};

var tker tkers[32];
var int nbtker;

/////////////////////////////////////////////////////////

// cache for victims of pushing attacks
var Pawn LastVictim[32], LastInstigator[32];
var int KilledHealth[32];
var name KilledDamage[32];

var bool bPushKill;	// set to true when WhoPushedMe wants to make a delayed kill
var bool bFirstTick;	// used to move WhoPushedMe to start of mutator list

function PreBeginPlay()
{
	Super.PreBeginPlay();
	Level.Game.RegisterDamageMutator(Self);
	EIDMM = Self;
	nbtker=0;
}

function bool PreventDeath(Pawn Killed, Pawn Killer, name damageType, vector HitLocation)
{
	local int i;
	
	if ( !bPushKill && NextMutator != None && NextMutator.PreventDeath(Killed, Killer, damageType, HitLocation) )
		return true;
	
	if ( (DamageType != 'Suicided' || Killed.IsA('PlayerPawn')) && DamageActor[0] == None
			&& ((Killer == None && damageType != 'Drowned') || (Killed == Killer
			&& (damageType == 'Burned' || damageType == 'SpecialDamage' || damageType == 'Suicided'
			|| damageType == 'Corroded' || damageType == 'Fell' || damageType == 'None'))) ) {
		// was a push kill; death will be delayed till next Tick()
		for (i = 0; i < ArrayCount(LastVictim); i++)
			if ( Killed == LastVictim[i] ) {
				KilledHealth[i] = Killed.Health;
				KilledDamage[i] = damageType;
				return true;
			}
	}
	else	// remove from victim cache (was regular suicide)
		for (i = 0; i < ArrayCount(LastVictim); i++)
			if ( Killed == LastVictim[i] ) {
				LastVictim[i] = None;
				KilledHealth[i] = 1;
			}
	
	return false;
}

function MutatorTakeDamage(out int ActualDamage, Pawn Victim, Pawn InstigatedBy, out Vector HitLocation, out Vector Momentum, name DamageType)
{
	// add player to victim cache
	if ( Victim.bIsPlayer
			&& Victim.IsA('PlayerPawn')
			&& InstigatedBy != None 
			&& InstigatedBy.bIsPlayer
			&& InstigatedBy.IsA('PlayerPawn')
			&& Victim != InstigatedBy 
		&& VSize(Momentum) > 0 )
		AddHit(Victim, InstigatedBy);
	
	if ( NextDamageMutator != None )
		NextDamageMutator.MutatorTakeDamage(ActualDamage, Victim, InstigatedBy, HitLocation, Momentum, DamageType);
}

// adds or updates an entry in the victim cache
function AddHit(Pawn Victim, Pawn InstigatedBy)
{
	local int i;
	
	for (i = 0; i < ArrayCount(LastVictim); i++)
		if ( LastVictim[i] == Victim ) {
			LastInstigator[i] = InstigatedBy;
			KilledHealth[i] = 1;
			return;
		}
	
	for (i = 0; i < ArrayCount(LastVictim); i++)
		if ( LastVictim[i] == None ) {
			LastVictim[i] = Victim;
			LastInstigator[i] = InstigatedBy;
			KilledHealth[i] = 1;
			return;
		}
}

// moves WhoPushedMe to the start of the mutator list (behind BaseMutator)
function SendToListStart()
{
	local Mutator M, PrevMutator;
	
	For (M = Level.Game.BaseMutator; M != None; M = M.NextMutator) {
		if ( M == Self && PrevMutator == None )
			break;	// already first regular mutator
		else if ( M == Self ) {	// insert self after BaseMutator
			PrevMutator.NextMutator = NextMutator;
			NextMutator = Level.Game.BaseMutator.NextMutator;
			Level.Game.BaseMutator.NextMutator = Self;
			break;
		}
	}
}

function Tick(float DeltaTime)
{
	local int i;
	local Pawn P;
	local bool bPrevPushKill;
	
	// move to start of mutator list to prevent problems with other mutator's PreventDeath()
	if ( !bFirstTick ) {
		SendToListStart();
		bFirstTick = True;
	}
	
	// check victim cache for push kills
	for (i = 0; i < ArrayCount(LastVictim); i++)
		if ( LastVictim[i] != None && KilledHealth[i] <= 0 && LastInstigator[i] != None ) {
			//ATH
			if(LastVictim[i].PlayerReplicationInfo.Team == LastInstigator[i].PlayerReplicationInfo.Team)
				tk(LastVictim[i],LastInstigator[i]);
			bPrevPushKill = bPushKill;
			bPushKill = True;
			LastVictim[i].Health = Min(KilledHealth[i], 0);
	
			LastVictim[i].Died(LastInstigator[i], 'Pushed', LastVictim[i].Location);
			LastVictim[i] = None;
			RemoveDamageActor();
			bPushKill = bPrevPushKill;
		}
	
	// remove players from the cache who already landed
	for (i = 0; i < ArrayCount(LastVictim); i++)
		if ( LastVictim[i] != None && (LastVictim[i].Physics == PHYS_Walking
				|| LastVictim[i].Health <= 0 || LastInstigator[i] == None) ) {
			LastVictim[i] = None;
			LastInstigator[i] = None;
		}
	
	// kill bots with negative health who aren't already dead
	for (P = Level.PawnList; P != None; P = P.NextPawn)
		if ( P.IsA('Bot') && P.Health <= 0 && !P.IsInState('Dying') )
			P.Died(P, 'Suicided', P.Location);
}
//==================================================================================================
//tk punisher
function bool tk(Pawn Killed, Pawn Killer)
{
	local string strkiller,strkilled,ipkiller;
	local int i,j;
	local int flagpain;
	local ath_sa AAS;
	ipkiller=Left(PlayerPawn(Killer).GetPlayerNetworkAddress(), InStr(PlayerPawn(Killer).GetPlayerNetworkAddress(), ":"));

		for (i = 0; i < nbtker; i++)
			if(tkers[i].PlayerIP == ipkiller)
				break;
		if(tkers[i].PlayerIP=="")
		{
			 tkers[i].PlayerIP=ipkiller;	
			 tkers[i].pain=1;
			 tkers[i].nbtk=0;
			nbtker++;
		}
		tkers[i].PlayerName=PlayerPawn(Killer).PlayerReplicationInfo.PlayerName;
		tkers[i].nbtk++;				
		if (PlayerPawn(Killed).PlayerReplicationInfo.hasFlag != none) flagpain=3; else flagpain=0;

		PlayerPawn(Killed).PlayerReplicationInfo.Score=PlayerPawn(Killed).PlayerReplicationInfo.Score + tkers[i].pain + flagpain;
		PlayerPawn(Killer).PlayerReplicationInfo.Score=PlayerPawn(Killer).PlayerReplicationInfo.Score - tkers[i].pain - flagpain;
		
		strkiller="-"$string(tkers[i].pain + flagpain);
		strkilled="+"$string(tkers[i].pain + flagpain);

		if(tkers[i].pain>5)
		{ 
			strkiller="kicked"; 
			BroadcastMessage("[:][TK][ "$PlayerPawn(Killer).PlayerReplicationInfo.PlayerName@"has been kicked ]", true);
			//banip
			foreach AllActors(Class'ath_sa',AAS){
				AAS.ban_ip(tkers[i].PlayerIP);
				AAS.tk_kick(Killer);
			}

		}

		BroadcastMessage("[:][TK][ "$PlayerPawn(Killer).PlayerReplicationInfo.PlayerName$"("$strkiller$") has teamkilled "$PlayerPawn(Killed).PlayerReplicationInfo.PlayerName$"("$strkilled$") ]", false, 'Event');
		tkers[i].pain++;
	return true;
}
//==================================================================================================
//pawntoac
function ath_controller get_ac(Pawn P)
{
	local ath_controller AC;
	foreach AllActors(Class'ath_controller',AC)
	{
		if(P==Pawn(AC.owner))return AC;
	}
	log("[ATH][ failed to locate the pawn ]");	
	return none;
}
//==================================================================================================
// !tk && mutate tk
function Mutate(string MutateString, PlayerPawn Sender)
{
   local int i;
   Super.Mutate(MutateString, Sender);
   if(Caps(MutateString) == "TK")
   {
//		get_ac(Sender).ac_oc();
		for (i = 0; i < nbtker; i++)
			Sender.ClientMessage("[:][TK][ "$tkers[i].PlayerName$" ][ "$tkers[i].nbtk@"Team-kill(s) ]",'athclient');
		if(nbtker==0)
			Sender.ClientMessage("[:][TK][ List empty, no team-killer here :) ]",'athclient');		
   }
}
*/
