//=============================================================================
// KFProj_HuskCannon_Fireball
//=============================================================================
// Player version for the Husk Cannon of the Husk fire ball.
//=============================================================================
// Killing Floor 2
// Copyright (C) 2017 Tripwire Interactive LLC
//=============================================================================
class KFProj_HuskCannon_Fireball extends KFProj_BallisticExplosive
    implements(KFInterface_DamageCauser);

var float DamageScale;
var float AOEScale;
var float IncapScale;
var repnotify int ChargeLevel;

var const ParticleSystem ExplosionEffectL1;
var const ParticleSystem ExplosionEffectL2;
var const ParticleSystem ExplosionEffectL3;

var const ParticleSystem ProjFlightTemplateL1;
var const ParticleSystem ProjFlightTemplateL2;
var const ParticleSystem ProjFlightTemplateL3;

var const AkBaseSoundObject ExplosionSoundL1;
var const AkBaseSoundObject ExplosionSoundL2;
var const AkBaseSoundObject ExplosionSoundL3;

var const ParticleSystem ConcussiveForceEffectL1;
var const ParticleSystem ConcussiveForceEffectL2;
var const ParticleSystem ConcussiveForceEffectL3;

/** Explosion actor class to use for ground fire */
var const protected class<KFExplosionActorLingering> GroundFireExplosionActorClass;
/** Explosion template to use for ground fire */
var KFGameExplosion GroundFireExplosionTemplate;

/** How long the ground fire should stick around */
var const protected float BurnDuration;

/** How often, in seconds, we should apply burn */
var const protected float BurnDamageInterval;

var bool bSpawnGroundFire;

var bool bAltGroundFire;
var KFImpactEffectInfo AltGroundFire;

replication
{
	if (bNetInitial)
		bSpawnGroundFire, ChargeLevel;
}

simulated event ReplicatedEvent(name VarName)
{
	if (VarName == nameof(ChargeLevel))
	{
		bSpawnGroundFire = ChargeLevel == 3;
		SpawnFlightEffects();
	}

	Super.ReplicatedEvent(VarName);
}

simulated function PostBeginPlay()
{
	local KFWeap_HuskCannon HuskCannon;
	local KFPlayerReplicationInfo InstigatorPRI;

	if(Role == ROLE_Authority)
	{
		HuskCannon = KFWeap_HuskCannon(Owner);
		if (HuskCannon != none)
		{
			ChargeLevel = HuskCannon.GetChargeFXLevel();
			bSpawnGroundFire = ChargeLevel == 3;
		}
	}

	if(Instigator != none)
	{
		if (AltGroundFire != none)
		{
			InstigatorPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo);
			if (InstigatorPRI != none)
			{
				bAltGroundFire = InstigatorPRI.bSplashActive;
			}
		}
		else
		{
			bAltGroundFire = false;
		}
	}

	Super.PostBeginPlay();
}

simulated protected function PrepareExplosionActor(GameExplosionActor GEA)
{
    local KFExplosionActor_HuskCannon HuskExplode;

    HuskExplode = KFExplosionActor_HuskCannon(GEA);
    if (HuskExplode != None)
    {
        HuskExplode.DamageScale = DamageScale;
    }
}

simulated function TriggerExplosion(Vector HitLocation, Vector HitNormal, Actor HitActor)
{
	local KFExplosionActorLingering GFExplosionActor;
	local vector GroundExplosionHitNormal;

	if (bHasDisintegrated)
	{
		return;
	}

	if (!bHasExploded && bSpawnGroundFire)
	{
		if (bAltGroundFire && AltGroundFire != none)
		{
			GroundFireExplosionTemplate.ExplosionEffects = AltGroundFire;
		}

		GroundExplosionHitNormal = HitNormal;

		// Spawn our explosion and set up its parameters
		GFExplosionActor = Spawn(GroundFireExplosionActorClass, self, , HitLocation + (HitNormal * 32.f), rotator(HitNormal));
		if (GFExplosionActor != None)
		{
			GFExplosionActor.Instigator = Instigator;
			GFExplosionActor.InstigatorController = InstigatorController;

			// These are needed for the decal tracing later in GameExplosionActor.Explode()
			GroundFireExplosionTemplate.HitLocation = HitLocation;
			GroundFireExplosionTemplate.HitNormal = GroundExplosionHitNormal;

			// Apply explosion direction
			if (GroundFireExplosionTemplate.bDirectionalExplosion)
			{
				GroundExplosionHitNormal = GetExplosionDirection(GroundExplosionHitNormal);
			}

			// Set our duration
			GFExplosionActor.MaxTime = BurnDuration;

			// Set our burn interval
			GFExplosionActor.Interval = BurnDamageInterval;

			// Boom
			GFExplosionActor.Explode(GroundFireExplosionTemplate, GroundExplosionHitNormal);
		}
	}

	super.TriggerExplosion(HitLocation, HitNormal, HitActor);
}

//==============
// Touching
simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal)
{
	if (ClassIsChildOf(Other.class, class'KFPawn'))
	{
		bSpawnGroundFire = false;
	}

	super.ProcessTouch(Other, HitLocation, HitNormal);
}

simulated protected function PrepareExplosionTemplate()
{
	local bool bUseConcussiveForce;
	local Weapon OwnerWeapon;
	local Pawn OwnerPawn;
	local KFPlayerReplicationInfo PRI;

	super(KFProjectile).PrepareExplosionTemplate();

	bUseConcussiveForce = false;
	OwnerWeapon = Weapon(Owner);
	if (OwnerWeapon != none)
	{
		OwnerPawn = Pawn(OwnerWeapon.Owner);
		if (OwnerPawn != none)
		{
			PRI = KFPlayerReplicationInfo(OwnerPawn.PlayerReplicationInfo);
			if (PRI != none)
			{
				bUseConcussiveForce = PRI.bConcussiveActive;
			}
		}
	}

	switch (ChargeLevel)
	{
	case 1:
		if (bUseConcussiveForce)
		{
			ExplosionTemplate.ExplosionEffects.DefaultImpactEffect.ParticleTemplate = ConcussiveForceEffectL1;
			ExplosionTemplate.ExplosionSound = class'KFPerk_Demolitionist'.static.GetConcussiveExplosionSound();
		}
		else
		{
			ExplosionTemplate.ExplosionEffects.DefaultImpactEffect.ParticleTemplate = ExplosionEffectL1;
			ExplosionTemplate.ExplosionSound = ExplosionSoundL1;
		}
		break;
	case 2:
		if (bUseConcussiveForce)
		{
			ExplosionTemplate.ExplosionEffects.DefaultImpactEffect.ParticleTemplate = ConcussiveForceEffectL2;
			ExplosionTemplate.ExplosionSound = class'KFPerk_Demolitionist'.static.GetConcussiveExplosionSound();
		}
		else
		{
			ExplosionTemplate.ExplosionEffects.DefaultImpactEffect.ParticleTemplate = ExplosionEffectL2;
			ExplosionTemplate.ExplosionSound = ExplosionSoundL2;
		}
		break;
	case 3:
		if (bUseConcussiveForce)
		{
			ExplosionTemplate.ExplosionEffects.DefaultImpactEffect.ParticleTemplate = ConcussiveForceEffectL3;
			ExplosionTemplate.ExplosionSound = class'KFPerk_Demolitionist'.static.GetConcussiveExplosionSound();
		}
		else
		{
			ExplosionTemplate.ExplosionEffects.DefaultImpactEffect.ParticleTemplate = ExplosionEffectL3;
			ExplosionTemplate.ExplosionSound = ExplosionSoundL3;
		}
		break;
	}

	class'KFPerk_Demolitionist'.static.PrepareExplosive(Instigator, self, AOEScale, DamageScale);
}

simulated protected function SetExplosionActorClass()
{
	local KFPlayerReplicationInfo InstigatorPRI;

	if (bWasTimeDilated && Instigator != none)
	{
		InstigatorPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo);
		if (InstigatorPRI != none && InstigatorPRI.CurrentPerkClass == class'KFPerk_Demolitionist')
		{
			if (InstigatorPRI.bNukeActive && class'KFPerk_Demolitionist'.static.ProjectileShouldNuke(self))
			{
				ExplosionActorClass = class'KFPerk_Demolitionist'.static.GetNukeExplosionActorClass();
			}
		}
	}

	super.SetExplosionActorClass();
}

// KFInterface_DamageCauser
function float GetIncapMod()
{
    return IncapScale;
}

// Override ProjFlightTemplate to correct emitter.
simulated function SpawnFlightEffects()
{
	if (ChargeLevel == 0)
	{
		return; // Charge level will be set using replication.
	}

	switch (ChargeLevel)
	{
		case 1:
			ProjFlightTemplate = ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Projectile_L1';
			break;
		case 2:
			ProjFlightTemplate = ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Projectile_L2';
			break;
		case 3:
			ProjFlightTemplate = ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Projectile_L3';
			break;
	}

	Super.SpawnFlightEffects();
}

defaultproperties
{
    ExplosionActorClass=class'KFExplosionActor_HuskCannon'
	// Ground fire
	BurnDuration = 4.f
	BurnDamageInterval = 0.5f
	GroundFireExplosionActorClass=class'KFExplosion_HuskCannonFireballGroundFire'
	ProjFlightTemplate=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Projectile_L3'

	// Fire light
	Begin Object Class=PointLightComponent Name=FlamePointLight
		LightColor = (R = 245,G = 190,B = 140,A = 255)
		Brightness = 4.f
		Radius = 500.f
		FalloffExponent = 10.f
		CastShadows = False
		CastStaticShadows = FALSE
		CastDynamicShadows = TRUE
		bCastPerObjectShadows = false
		bEnabled = FALSE
		LightingChannels = (Indoor = TRUE,Outdoor = TRUE,bInitialized = TRUE)
	End Object

	// Grenade explosion light
	Begin Object Class=PointLightComponent Name=ExplosionPointLight
		LightColor = (R = 245,G = 190,B = 140,A = 255)
		Brightness = 4.f
		Radius = 2000.f
		FalloffExponent = 10.f
		CastShadows = False
		CastStaticShadows = FALSE
		CastDynamicShadows = False
		bCastPerObjectShadows = false
		bEnabled = FALSE
		LightingChannels = (Indoor = TRUE,Outdoor = TRUE,bInitialized = TRUE)
	End Object

	Begin Object Class=KFGameExplosion Name=ExploTemplate1
		Damage=3
		DamageRadius=150
		DamageFalloffExponent=1.f
		DamageDelay=0.f
		// Don't burn the guy that tossed it, it's just too much damage with multiple fires, its almost guaranteed to kill the guy that tossed it
        bIgnoreInstigator=true

		MomentumTransferScale=1

		// Damage Effects
		MyDamageType=class'KFDT_Fire_Ground_HuskCannon'
		KnockDownStrength=0
		FractureMeshRadius=0
		ExplosionEffects=KFImpactEffectInfo'wep_molotov_arch.Molotov_GroundFire'

		bDirectionalExplosion=true

		// Camera Shake
		CamShake=none

		// Dynamic Light
        ExploLight=FlamePointLight
        ExploLightStartFadeOutTime=1.5f
        ExploLightFadeOutTime=0.3
	End Object
	GroundFireExplosionTemplate=ExploTemplate1

	Begin Object Class=KFGameExplosion Name=ExploTemplate2
		Damage=60 //100
		DamageRadius=100 //450 //550
		DamageFalloffExponent=1.f //1.0
		DamageDelay=0.f
		bUseOverlapCheck = true

		// Damage Effects
		MyDamageType=class'KFDT_Explosive_HuskCannon'
		bCausesFracture=true
		MomentumTransferScale=6000.f
		KnockDownStrength=100
		FractureMeshRadius=200.0
		FracturePartVel=100.0
		ExplosionEffects=KFImpactEffectInfo'FX_Impacts_ARCH.Explosions.HuskProjectile_Explosion'
		ExplosionSound=AkEvent'WW_ZED_Husk.ZED_Husk_SFX_Ranged_Shot_Impact'
		ExplosionEmitterScale=2.f

		// Dynamic Light
		ExploLight=ExplosionPointLight
		ExploLightStartFadeOutTime = 0.0
		ExploLightFadeOutTime = 0.5

		// Camera Shake
		// Camera Shake
		CamShake = none
		bOrientCameraShakeTowardsEpicenter=true

		bIgnoreInstigator=false
    End Object
	ExplosionTemplate=ExploTemplate2

	//AltExploEffects=KFImpactEffectInfo'WEP_Flamethrower_ARCH.GroundFire_Splash_Impacts'
	AltGroundFire=KFImpactEffectInfo'WEP_Flamethrower_ARCH.GroundFire_Splash_Impacts'

	Begin Object Name=CollisionCylinder
		CollisionRadius=4 //6
		CollisionHeight=4  //2
	End Object

	ExtraLineCollisionOffsets.Add((Y = -8))
	ExtraLineCollisionOffsets.Add((Y = 8))
	// Since we're still using an extent cylinder, we need a line at 0
	ExtraLineCollisionOffsets.Add(())

    MomentumTransfer=0

	ConcussiveForceEffectL1=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Impact_L1_CF'
	ConcussiveForceEffectL2=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Impact_L2_CF'
	ConcussiveForceEffectL3=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Impact_L3_CF'

	ExplosionEffectL1=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Impact_L1'
	ExplosionEffectL2=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Impact_L2'
	ExplosionEffectL3=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Impact_L3'

	ProjFlightTemplateL1=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Projectile_L1'
	ProjFlightTemplateL2=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Projectile_L2'
	ProjFlightTemplateL3=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Projectile_L3'

	ExplosionSoundL1=AkEvent'WW_ZED_Husk.ZED_Husk_SFX_Ranged_Shot_Impact';
	ExplosionSoundL2=AkEvent'WW_ZED_Husk.ZED_Husk_SFX_Ranged_Shot_Impact';
	ExplosionSoundL3=AkEvent'WW_ZED_Husk.ZED_Husk_SFX_Ranged_Shot_Impact';

	AmbientSoundPlayEvent=none
    AmbientSoundStopEvent=none

    MaxSpeed=4000.0
	Speed=4000.0

	bNetTemporary = False
	bBlockedByInstigator=false
	bAlwaysReplicateExplosion = true
	bUseClientSideHitDetection = true
	bNoReplicationToInstigator = false
	bReplicateLocationOnExplosion = true
	bValidateExplosionNormalOnClient = true
	TouchTimeThreshhold = 0.15
}