//=============================================================================
// KFSM_ScreamBase
//=============================================================================
// Base class for sonic scream special moves
//=============================================================================
// Killing Floor 2
// Copyright (C) 2019 Tripwire Interactive LLC
//=============================================================================
class KFSM_ScreamBase extends KFSM_PlaySingleAnim;

/** The frequency to do scream damage at */
var float			ScreamDamageFrequency;

/** The number of times damage has been dealt by a single scream */
var byte 			ScreamCount;

/** Last time a scream was executed */
var float 			LastScreamTime;

/** Maximum number of times a scream can deal damage */
const DAMAGE_COUNT_PER_SCREAM = 4;

/** How much base damage a scream does */
var protected const int ScreamDamage;

/** Temp reference to the explosion template, used for delayed damage */
var GameExplosion ExplosionTemplate;

var const class<GameExplosionActor> ExplosionActorClass;

/** Set to TRUE when the scream ends on its own (not interrupted) */
var bool bEndedNormally;

/** Stop event played when this scream was interrupted too early */
var AkEvent ScreamInterruptSound;

/** The explosion actor to store when this projectile is created */
var GameExplosionActor ExplosionActor;

/** Debugging Siren Sonic Wave */
var bool            bDrawWaveRadius;
var bool			bDrawProjectileShield;

var KFTrigger_SirenProjectileShield ProjectileShield;
var const	float	ProjectileShieldLifetime;

///**
// * Can a new special move override this one before it is finished?
// * This is only if CanDoSpecialMove() == TRUE && !bForce when starting it.
// */
//function bool CanOverrideMoveWith(Name NewMove)
//{
//	if (bCanBeInterrupted &&
//		(NewMove == 'KFSM_Stunned' ||
//		 NewMove == 'KFSM_Stumble' ||
//		 NewMove == 'KFSM_Knockdown' ||
//		 NewMove == 'KFSM_Frozen'))
//	{
//		return TRUE;
//	}
//	return FALSE;
//}
//
///**
// * Can the special move be chained after the current one finishes?
// */
//function bool CanChainMove( Name NextMove )
//{
//	if (NextMove == 'KFSM_MeleeAttack')
//	{
//		return true;
//	}
//
//	return super.CanChainMove(NextMove);
//}

function SpecialMoveStarted(bool bForced, name PrevMove)
{
	super.SpecialMoveStarted(bForced, PrevMove);

	bEndedNormally = false;
	LastScreamTime = KFPOwner.WorldInfo.TimeSeconds;
	KFPOwner.SetTimer(ProjectileShieldLifetime, false, nameof(Timer_DestroyProjectileShield), self);

	if (AIOwner != none)
	{
		`AILog_Ext(KFPOwner$" started for "$AIOwner, 'Siren', AIOwner);
	}
}

/** Triggers the start of the Siren's scream attack */
function ScreamBegan()
{
	if (bDrawWaveRadius || bDrawProjectileShield)
	{
	   KFPOwner.FlushPersistentDebugLines();
	}

	SpawnProjectileShield();
	InitializeSirenExplosion();
}

/** Create and initialize projectile shield */
function SpawnProjectileShield()
{
	local vector vExtent;

	if (KFPOwner.Role == ROLE_Authority && ProjectileShield == none)
	{
		// Spawn projectile shield, which can stop projectiles before hitting the Siren
		ProjectileShield = KFPOwner.Spawn(
			class'KFTrigger_SirenProjectileShield', KFPOwner,, KFPOwner.Location, KFPOwner.Rotation);
		ProjectileShield.SetBase( KFPOwner );
		ProjectileShield.SetRelativeLocation( vect(0,0,0) );

		// Renders the projectile shield's collision cylinder
		if (bDrawProjectileShield)
		{
			vExtent = vect(0,0,1) * ProjectileShield.CylinderComponent.CollisionHeight;
			KFPOwner.DrawDebugCylinder(
				ProjectileShield.Location - vExtent, ProjectileShield.Location + vExtent,
				ProjectileShield.CylinderComponent.CollisionRadius, 10, 255, 0, 0, true);
		}
	}
}

/** Destroys the projectile shield based on position in animation */
function Timer_DestroyProjectileShield()
{
	DestroyProjectileShield();
}

/** Destroy and clear proectile shield */
function DestroyProjectileShield()
{
	if (ProjectileShield != none)
	{
		ProjectileShield.Destroy();
		ProjectileShield = none;

		if (bDrawProjectileShield)
		{
			// Clear debug rendering of projectile shield
			KFPOwner.FlushPersistentDebugLines();
		}
	}
}

/** Set up the sirens ExplosionActor when she screams */
function InitializeSirenExplosion()
{
	if (KFPOwner.Role == ROLE_Authority && ExplosionTemplate != None)
	{
		ExplosionActor = KFPOwner.Spawn(
			ExplosionActorClass, KFPOwner,, KFPOwner.Location, KFPOwner.Rotation);
		if (ExplosionActor != None)
		{
			ExplosionActor.Instigator = KFPOwner;
			ExplosionActor.InstigatorController = KFPOwner.Controller;
			ExplosionActor.SetBase(KFPOwner);

			// Deal explosion damage instantly and over time
			ScreamExplosion();
    		KFPOwner.SetTimer(ScreamDamageFrequency, True, nameof(ScreamExplosion), self);
		}
	}
}

/** Called on a timer to deal damage in a radius */
function ScreamExplosion()
{
	if (!KFPOwner.IsCombatCapable())
	{
		KFPOwner.EndSpecialMove();
		return;
	}

	LastScreamTime = KFPOwner.WorldInfo.TimeSeconds;

	ExplosionTemplate.Damage = KFPawn_Monster(KFPOwner).GetRallyBoostDamage( ScreamDamage );
	ExplosionActor.Explode(ExplosionTemplate);

	ScreamCount++;
	if (ScreamCount >= DAMAGE_COUNT_PER_SCREAM)
	{
		bEndedNormally = true;
		KFPOwner.EndSpecialMove();
	}
}

function CheckIfScreamWasInterrupted()
{
	if (!bEndedNormally && LastScreamTime > 0.f && KFPOwner.WorldInfo.TimeSeconds - LastScreamTime < 1.0f)
	{
		KFPOwner.PlayAkevent(ScreamInterruptSound, false, true);
	}
}

function SpecialMoveEnded(Name PrevMove, Name NextMove)
{
	super.SpecialMoveEnded(PrevMove, NextMove);

	CheckIfScreamWasInterrupted();

	KFPOwner.ClearTimer(nameof(ScreamExplosion), self);
	ScreamCount = 0;

	DestroyProjectileShield();

	if (ExplosionActor != none)
	{
		ExplosionActor.Destroy();
		ExplosionActor = none;
	}

	if (AIOwner != none)
	{
		`AILog_Ext(KFPOwner$" ended for "$AIOwner, 'Siren', AIOwner );
	}
}

DefaultProperties
{
	// SpecialMove
	ProjectileShieldLifetime=2.2 // 0.52

	AnimName=Atk_Combo1_V1
	Handle=KFSM_Scream_Base
	bDisableSteering=false
	bDisableMovement=false
   	AnimStance=EAS_UpperBody
   	bCanBeInterrupted=true

	ScreamDamage=15
	ScreamDamageFrequency=0.5f //1.0
	ScreamInterruptSound=AkEvent'WW_ZED_Siren.Stop_Siren_Scream'

   	bDrawProjectileShield=false
	bDrawWaveRadius=false

	ExplosionActorClass=class'KFExplosion_SirenScream'

	// explosion
	Begin Object Class=KFGameExplosion Name=ExploTemplate0
		//Damage=15	@NOTE: This is now set using the ScreamDamage variable -MattF
		DamageRadius=600 //800
		DamageFalloffExponent=1f
		DamageDelay=0.f

		MomentumTransferScale=100//-100000 Reactivate this to add siren pull

		ActorClassToIgnoreForDamage=class'KFPawn_Monster'

		// Damage Effects
		MyDamageType=class'KFDT_Sonic'
		KnockDownStrength=0
		FractureMeshRadius=200.0
		FracturePartVel=500.0
		ExplosionEffects=none
		ExplosionSound=none

		// Camera Shake
		CamShake=CameraShake'FX_CameraShake_Arch.Misc_Explosions.SirenScream'
		CamShakeInnerRadius=450
		CamShakeOuterRadius=700 //900
		CamShakeFalloff=1.f
		bOrientCameraShakeTowardsEpicenter=true
	End Object
	ExplosionTemplate=ExploTemplate0
}