//=============================================================================
// sgPRI.
// * Revised by nOs*Badger
//
// HIGOR: Added tournament code and re-implemented spawn protection here
// HIGOR: Fingerprint and anti-supplier spam implemented
//=============================================================================
class sgPRI extends PlayerReplicationInfo;

var int choice;

var float	sgInfoCoreKiller, 
		sgInfoCoreRepair, 
		sgInfoBuildingHurt,
		sgInfoUpgradeRepair;
var int		sgInfoKiller,
		sgInfoBuildingMaker,
		sgInfoWarheadMaker,
		sgInfoWarheadKiller,
		sgInfoSpreeCount;

var string CountryPrefix;

var Actor IpToCountry;
var bool bIpToCountry;		

var float           RU,
                    MaxRU;
var sgBaseCore      Cores[4];
var WildcardsOrbs Orb;
var sg_XC_Orb XC_Orb;

Var bool bReadyToPlay;
var bool bGameStarted;
var bool bHideIdentify;

//Spawn protection
var float pTimer;
var int ProtectCount;
var Weapon WhosGun;
var int WhosAmmoCount;

var string VisibleMessage; //Always sHistory[0], for external mods
var int VisibleMessageNum;
var string sHistory[16];
var byte sColors[16];
var byte iHistory;

var pawn PushedBy;

//Remove protection
var int RemoveTimer;

//Supplier anti-spam
var bool bReachedSupplier;
var float SupplierTimer;

//Fingerprint
var bool bReceivedFingerPrint;
var string PlayerFingerPrint;
var float NoFingerPrintTimer;
var int iNoFP;
var bool bRequestedFPTime;

//For use in AI modes
var name Orders;
var actor OrderObject;
var sgAIqueuer AIQueuer;

replication
{
	reliable if ( Role == ROLE_Authority )
		RU, MaxRU, Cores, XC_Orb, Orb, sgInfoCoreKiller, sgInfoBuildingHurt, sgInfoCoreRepair, sgInfoUpgradeRepair, sgInfoKiller, sgInfoBuildingMaker,sgInfoWarheadMaker, sgInfoWarheadKiller, CountryPrefix, bReadyToPlay, bHideIdentify, Orders;
	reliable if ( Role == ROLE_Authority )
		ReceiveMessage, RequestFingerPrint;
	reliable if ( Role < ROLE_Authority )
		SendFingerPrint, RequestFPTime;
}

function SendFingerPrint( string aFingerPrint)
{
	local sgPRI aPRI;
	local sgBuilding sgB;
	
	if ( bReceivedFingerPrint )
		return; //Cheat attempt?

	if ( (SiegeGI(Level.Game) != none) && !SiegeGI(Level.Game).bShareFingerPrints )
		ForEach AllActors (class'sgPRI', aPRI)
			if ( aPRI.PlayerFingerPrint == aFingerPrint )
			{
				RequestFingerPrint( true);
				return;
			}

	PlayerFingerPrint = aFingerPrint;
	ForEach AllActors ( class'sgBuilding', sgB)
	{
		if ( (sgB.Owner == none) && (sgB.sPlayerIP == PlayerFingerPrint) )
			sgB.SetOwner( Owner);
	}
	if ( Spectator(Owner) == none )
		SiegeGI(Level.Game).RURecovery.RecoverRU(Pawn(Owner));
	bReceivedFingerPrint = true;
}

//sgClient is requesting more time to send the fingerprint
function RequestFPTime()
{
	if ( !bRequestedFPTime )
	{
		NoFingerPrintTimer += 5;
		bRequestedFPTime = True;
	}
}

simulated function RequestFingerPrint( optional bool bRegen)
{
	local sgClient aClient;

	if ( (PlayerPawn(Owner) == none) || ViewPort(PlayerPawn(Owner).Player) == none )
		return;

	ForEach AllActors (class'sgClient', aClient )
		break;
	if ( aClient == none )
		return;
	if ( bRegen && aClient.bFPnoReplace )
	{
		PlayerPawn(Owner).ClientMessage("Your fingerprint is in use, if you timed out reconnect again in 5 seconds");
		PlayerPawn(Owner).ConsoleCommand("disconnect");
		return;
	}
	if ( bRegen )
	{
		PlayerPawn(Owner).ClientMessage("Your fingerprint is in use and will be regenerated");
		aClient.GenerateFingerPrint();
	}
	SendFingerPrint( aClient.FingerPrint);
}

simulated function ReceiveMessage( string sMsg, byte aTeam, bool bAnnounce)
{
	local int i, j;
	local PlayerPawn LocalPlayer;
	
	LocalPlayer = PlayerPawn(Owner);
	if ( (LocalPlayer == none) || (ViewPort(LocalPlayer.Player) == none) )
		return;

	//Duplicated messages merge now!
	i = Len( sMsg);
	if ( VisibleMessage == sMsg )
	{
		VisibleMessage = sMsg$" x2";
		sHistory[0] = VisibleMessage;
		VisibleMessageNum++;
	}
	else if ( (Left(VisibleMessage,i) == sMsg) && (Mid(VisibleMessage,i,2) == " x") )
	{
		j = int(Mid(VisibleMessage,i+2)) + 1;
		VisibleMessage = sMsg$" x"$ string(j);
		sHistory[0] = VisibleMessage;
		VisibleMessageNum++;
	}
	else
	{
		For ( i=ArrayCount(sHistory)-1 ; i>0 ; i-- )
		{
			sHistory[i] = sHistory[i-1]; //Push up
			sColors[i] = sColors[i-1];
		}
		sHistory[0] = sMsg;
		sColors[0] = aTeam;
		VisibleMessage = sMsg;
		VisibleMessageNum++;
		iHistory = Min(16,iHistory+1);
	}	
	if ( bAnnounce )
		LocalPlayer.ClientMessage("-== "$sMsg$" ==-");
}

function Timer()
{
	Super.Timer();
	RemoveTimer += 2;
}

event PostBeginPlay()
{
	Super.PostBeginPlay();
	if ( SiegeGI(Level.Game) != none )
		RU = SiegeGI(Level.Game).StartingRU;

	if ( Owner != none && !Owner.IsA('Spectator') )
		Owner.Spawn(class'sgPlayerData',Owner);

	foreach allActors(class'Actor', ipToCountry, 'IpToCountry')
	{
		bIpToCountry = true;
		break;
	}
	NoFingerPrintTimer = 10;
}

simulated event PostNetBeginPlay()
{
	local sgClient aClient;

	Super.PostNetBeginPlay();

	if ( Level.NetMode == NM_Client )
	{
		ForEach AllActors (class'sgClient', aClient)
			break;
		if ( aClient == none )
			Spawn(class'sgClient');
	}
}

simulated function AddRU( float Amount)
{
	if ( RU <= MaxRU )
		RU = fClamp(RU + Amount, 0, MaxRU);
	else
	{
		if ( Amount > 0 )
			return;
		RU = fMax(RU + Amount, 0);
	}
}

function Tick(float deltaTime)
{
    local sgBaseCore core;
    local int I;
    local PlayerPawn P;
    local string temp;

	if ( Spectator(Owner) != none )
	{
		Disable('Tick');
		return;
	}

	//Fingerprint requests
	if ( (PlayerFingerPrint == "") && (NoFingerPrintTimer > 0) )
	{
		NoFingerPrintTimer -= DeltaTime / Level.TimeDilation;
		if ( NoFingerPrintTimer <= 0 )
		{
			if ( (iNoFP == 0) && (PlayerPawn(Owner) != none) && (ViewPort(PlayerPawn(Owner).Player) == none) )
			{
				Pawn(Owner).ClientMessage("Fingerprint not received by server, disconnecting");
				Owner.Destroy();
			}
			else if ( !Owner.IsA('PlayerPawn') )
			{
				SendFingerPrint("ARTIFICIAL_"$PlayerName);
				AIQueuer = Spawn(class'sgAIqueuer',Owner,'sgAIqueuer');
			}
			else
			{
				RequestFingerPrint();
				iNoFP--;
			}
			NoFingerPrintTimer = 10;
		}
	}

	if ( PushedBy != none )
	{
		if ( PushedBy.bDeleteMe || (Owner.Physics == PHYS_Walking) )
			PushedBy = none;
	}
	if ( bReachedSupplier && SupplierTimer > 0 )
		SupplierTimer -= deltaTime;

	if ( !bGameStarted && (Pawn(Owner).Weapon != none) )
		bGameStarted = true;
	if ( !bGameStarted && !bReadyToPlay )
	{
		if ( PlayerPawn(Owner) == none )
			bReadyToPlay = true;
		else if ( DeathMatchPlus(Level.Game).bTournament && (PlayerPawn(Owner) != none) )
			bReadyToPlay = PlayerPawn(Owner).bReadyToPlay;
	}
	else if ( bReadyToPlay && bGameStarted )
		bReadyToPlay = false;

	if ( SiegeGI(Level.Game) != None )
	{
		RU = FMax(FMin(RU, SiegeGI(Level.Game).MaxRUs[Team]), 0);
		MaxRU = SiegeGI(Level.Game).MaxRUs[Team];
		for (I=0;I<4;I++)
			Cores[I] = SiegeGI(Level.Game).Cores[I];
	}

	if ( ProtectCount > 0 )
	{
		PTimer -= DeltaTime;
		if ( PTimer <= 0 )
		{
			PTimer += 1;
			ProtTimer();
		}
	}

    if(bIpToCountry)
  {
     if(CountryPrefix == "")
     {       
        
	   /*if(Owner.Owner.IsA('PlayerPawn'))
	   {*/
          CountryPrefix = "*2";  
          P=PlayerPawn(Owner);
	      if(NetConnection(P.Player) != None)
	      {
             temp=P.GetPlayerNetworkAddress();
             temp=Left(temp, InStr(temp, ":"));
             
             temp=IpToCountry.GetItemName(temp);
             
             if(temp == "!Disabled") /* after this return, iptocountry won't resolve anything anyway */
                bIpToCountry=False;
             else if(Left(temp, 1) != "!") /* good response */
             {
                CountryPrefix=SelElem(temp, 5);
                if(CountryPrefix=="") /* the country is probably unknown(maybe LAN), so as the prefix */
                  bIpToCountry=False;
             }
	      }
	      else
	         bIpToCountry=False;
	    /*}
	    else
	       bIpToCountry=False;*/
      }
      else
         bIpToCountry=False;
    
  }

}

function ProtTimer()
{
	if (Pawn(Owner)==None)
		return;
	if ( --ProtectCount <= 0 )
	{
		ClearProt();
		return;
	}
	if (WhosGun == None)
	{
		WhosGun = Pawn(Owner).Weapon;
		if ( (WhosGun != none) && (WhosGun.AmmoType != none) )
			WhosAmmoCount = Pawn(Owner).Weapon.AmmoType.AmmoAmount;
	}
	if ( (WhosGun != None) && (Pawn(Owner).Weapon != none) )
		if (Pawn(Owner).Weapon != WhosGun || Pawn(Owner).Weapon.AmmoType.AmmoAmount != WhosAmmoCount)
			ClearProt();
}

function ClearProt()
{
	WhosGun = none;
	WhosAmmoCount = 0;
	ProtectCount = 0;
	PTimer = 1;
	Pawn(Owner).ClientMessage("Siege spawn protection off");
}

static final function string SelElem(string Str, int Elem)
{
	local int pos;
	while(Elem-->1)
		Str=Mid(Str, InStr(Str,":")+1);
	pos=InStr(Str, ":");
	if(pos != -1)
    	Str=Left(Str, pos);
    return Str;
}

simulated final function float GetEff()
{
	return float(sgInfoKiller) / (sgInfoKiller + Deaths) * 100;
}

defaultproperties
{
     iNoFP=3
}
