
class CSSFlashBlindEffect extends Inventory;

#exec AUDIO IMPORT NAME="FlashBangRing" FILE=Sounds\Grenades\GrenadeFlash\FlashBangRing.wav GROUP="GrenadeFlash"

var float BlindLength, BlindStrength, curScale, curLength, curStrength, ServerBlindScale, Distance;
var bool bBlinding, bInitLater;
var config int BlindScale;

replication
{
	unreliable if (Role == ROLE_Authority)
		ServerBlindScale, BlindLength, BlindStrength;
	
	reliable if (Role == ROLE_Authority)
		SetBlinding;
}

// no relevancy checking
function PreBeginPlay()
{
	ServerBlindScale = BlindScale;
	ServerBlindScale /= 3;
}

function PostBeginPlay()
{
	local CSSFlashBlinding L;
	
	ForEach AllActors(class'CSSFlashBlinding', L)
		return;
	Spawn(class'CSSFlashBlinding');
}

// blind player
simulated function SetBlinding(float Direction, float BlinderDistance)
{
	Distance = BlinderDistance;
	BlindStrength = FClamp(Direction + 1, 0, 1.2);
	if (Distance > 7000 || BlindStrength == 0) 
	{
		Destroy();
		return;
	}

	BlindLength = FMin(1000 / Distance, 5);
	if (Distance > 500)
		BlindStrength *= Sqrt(500 / Distance);
	
	if (Level.NetMode == NM_Client && Owner == None)
		bInitLater = True;
	else
		InitBlinding();
}

simulated function InitBlinding()
{
	local Inventory Inv;
	local int numBlinders;
	
	For (Inv = Owner.Inventory; Inv != None; Inv = Inv.Inventory)
		if (Inv.IsA('CSSFlashBlindEffect'))
			numBlinders++;
	
	BlindStrength *= (10 + 5 * numBlinders) / Sqrt(Distance * 0.1);
	curLength = 0;
	bBlinding = True;
	PlayOwnedSound(sound'FlashBangRing', SLOT_None,4.0*Pawn(Owner).SoundDampening);
	Tick(0.0);
}

simulated function bool IsStrongestBlinding()
{
	local float Blinding;
	local Inventory Inv;
	local CSSFlashBlindEffect FBE;
	
	for (Inv = Owner.Inventory; Inv != None; Inv = Inv.Inventory)
		if (Inv.IsA('CSSFlashBlindEffect') && Inv != Self) 
		{
			FBE = CSSFlashBlindEffect(Inv);
			Blinding = ServerBlindScale * CalcStrength(FBE.BlindLength, FBE.curLength, FBE.BlindStrength);
			if (Blinding > curStrength)
				return false;
		}
	return true;
}

simulated function float CalcStrength(float FullLength, float CurLength, float FullStrength)
{
	return FullStrength * Sqrt((FullLength - CurLength) / FullLength);
}

simulated function Tick(float DeltaTime)
{
	local vector NewFog;
	
	if (bInitLater && Owner != None)
		InitBlinding();
	
	if (ServerBlindScale == 0) 
	{
		Destroy();
		return;
	}
	
	if (!bBlinding || Pawn(Owner) == None || BlindLength == 0)
		return;
	
	curLength += DeltaTime / ServerBlindScale;
	if (curLength > BlindLength || Owner.IsInState('GameEnded') || Pawn(Owner).Health <= 0) 
	{
		if (PlayerPawn(Owner) != None && Level.NetMode != NM_StandAlone) 
		{
			curLength = BlindLength;
			curStrength = 0;
			Disable('Tick');
			LifeSpan = 0.5;
		}
		else
			Destroy();
		return;
	}
	curStrength = ServerBlindScale * CalcStrength(BlindLength, curLength, BlindStrength);
	
	if (Role == ROLE_Authority && !Owner.IsInState('GameEnded') && IsStrongestBlinding()) 
	{
		if (Owner.IsA('Bot')) 
		{
			Bot(Owner).SetPeripheralVision();
			Bot(Owner).SightRadius -= FMax(Bot(Owner).SightRadius * curStrength, 0);
			Bot(Owner).SetAlertness(-2 * curStrength);
			if (DeltaTime > 0 && curStrength > 0.8) 
			{
				Bot(Owner).Enemy = None;
				Bot(Owner).OldEnemy = None;
				Bot(Owner).NextState = '';
				Bot(Owner).MoveTimer = -1.0;
				Bot(Owner).MoveTarget = None;
				Bot(Owner).WhatToDoNext('','');
			}
		}
		else if (Owner.IsA('ScriptedPawn')) 
		{
			ScriptedPawn(Owner).SightRadius -= FMax(ScriptedPawn(Owner).Default.SightRadius * curStrength, 0);
			ScriptedPawn(Owner).SetAlertness(-2 * curStrength);
			if (DeltaTime > 0 && curStrength > 0.8) 
			{
				ScriptedPawn(Owner).Enemy = None;
				ScriptedPawn(Owner).OldEnemy = None;
				ScriptedPawn(Owner).NextState = '';
				ScriptedPawn(Owner).MoveTimer = -1.0;
				ScriptedPawn(Owner).MoveTarget = None;
				ScriptedPawn(Owner).WhatToDoNext('','');
			}
		}
	}
}

simulated function Destroyed()
{
	if (Role == ROLE_Authority) 
	{
		if (Bot(Owner) != None && Bot(Owner).Health > 0 && !Owner.IsInState('GameEnded')) 
		{
			Bot(Owner).SetPeripheralVision();
			Bot(Owner).SetAlertness(Bot(Owner).BaseAlertness);
		}
		if (ScriptedPawn(Owner) != None && ScriptedPawn(Owner).Health > 0 && !Owner.IsInState('GameEnded'))
		{
			ScriptedPawn(Owner).SightRadius = ScriptedPawn(Owner).Default.SightRadius;
			ScriptedPawn(Owner).SetAlertness(0.0);
		}
	}
	bBlinding = False;
	curStrength = 0;
	Super.Destroyed();
}

defaultproperties
{
   BlindScale=2
   bHidden=True
   NetUpdateFrequency=0.20
}
