//=============================================================================
// KFWeap_HRG_EMP_ArcGenerator 
//=============================================================================
// A gun that zaps zeds
//=============================================================================
// Killing Floor 2
// Copyright (C) 2015 Tripwire Interactive LLC
// FFerrando @ saber3d
//=============================================================================
/*
	Default firemode:
	-max number of secondary arcs
	-secondary arcs max range
	-main beam max range
	-aiming speed reduction

	Alt firemode:
	-projectile speed
	-projectile max range
	-zapTick (time between zaps)
	-max number of Zeds zapped
	-zap max range
 */
class KFWeap_HRG_EMP_ArcGenerator extends KFWeap_FlameBase;

Replication
{
	if(role == role_authority && bNetDirty)
		oZedCurrentlyBeingSprayed, MaxNumberOfZedsZapped, MaxDistanceToBeZapped, ZapInterval, ChainDamage;
}
/** Shoot animation to play when shooting secondary fire */
var(Animations) const editconst	name	FireHeavyAnim;

/** Shoot animation to play when shooting secondary fire last shot */
var(Animations) const editconst	name	FireLastHeavyAnim;

/** Shoot animation to play when shooting secondary fire last shot when aiming */
var(Animations) const editconst	name	FireLastHeavySightedAnim;

/** Alt-fire explosion template */
var() GameExplosion 		ExplosionTemplate;



/**************************** HRG SPRAY STUFF*/ 


struct BeamAttachedToActor
{
	var ParticleSystemComponent oBeam;
	var KFPawn_Monster oAttachedZed;
};

var array<DamagedActorInfo> vRecentlyZappedActors;
var array<DamagedActorInfo> vAuxDeletionArrayChainedActors;

var array<BeamAttachedToActor> vActiveBeamEffects;
var array<BeamAttachedToActor> vAuxDeletionArray;


var repnotify KFPawn_Monster oZedCurrentlyBeingSprayed;


var ParticleSystem BeamPSCTemplate;

var string EmitterPoolClassPath;
var EmitterPool vBeamEffects;

var int 	MaxNumberOfZedsZapped;
var int 	MaxDistanceToBeZapped;
var float 	ZapInterval;
var int 	ChainDamage;


/*********************** */

/** Handle one-hand fire anims */
simulated function name GetWeaponFireAnim(byte FireModeNum)
{
	local bool bPlayFireLast;

    bPlayFireLast = ShouldPlayFireLast(FireModeNum);

	if ( bUsingSights )
	{
		if( bPlayFireLast )
        {
        	if ( FireModeNum == ALTFIRE_FIREMODE )
        	{
                return FireLastHeavySightedAnim;
        	}
        	else
        	{
                return FireLastSightedAnim;
            }
        }
        else
        {
            return FireSightedAnims[FireModeNum];
        }

	}
	else
	{
		if( bPlayFireLast )
        {
        	if ( FireModeNum == ALTFIRE_FIREMODE )
        	{
                return FireLastHeavyAnim;
        	}
        	else
        	{
                return FireLastAnim;
            }
        }
        else
        {
        	if ( FireModeNum == ALTFIRE_FIREMODE )
        	{
                return FireHeavyAnim;
        	}
        	else
        	{
                return FireAnim;
            }
        }
	}
}



/**
 * Instead of a toggle, just immediately fire alternate fire.
 */
simulated function AltFireMode()
{
	// LocalPlayer Only
	if ( !Instigator.IsLocallyControlled()  )
	{
		return;
	}

	StartFire(ALTFIRE_FIREMODE);
}

/** Disable auto-reload for alt-fire */
simulated function bool ShouldAutoReload(byte FireModeNum)
{
	local bool bRequestReload;

    bRequestReload = Super.ShouldAutoReload(FireModeNum);

    // Must be completely empty for auto-reload or auto-switch
    if ( FireModeNum == ALTFIRE_FIREMODE && AmmoCount[0] > 0 )
    {
   		bPendingAutoSwitchOnDryFire = false;
   		return false;
    }

    return bRequestReload;
}

static simulated event EFilterTypeUI GetTraderFilter()
{
	return FT_Electric;
}


simulated function StartPilotSound()
{
	if( Instigator != none && Instigator.IsLocallyControlled() && Instigator.IsFirstPerson() )
	{
        //PostAkEventOnBone(PilotLightPlayEvent, PilotLightSocketName, true, true);
    }
}

/**
 * Stops playing looping Pilot light sound
 */
simulated function StopPilotSound()
{
    //PostAkEventOnBone(PilotLightStopEvent, PilotLightSocketName, true, true);
}

/**********************************************************************




*********************************************************************** */


simulated function ReplicatedEvent(name VarName)
{
	if(VarName == nameof(oZedCurrentlyBeingSprayed))
	{
		if(role != role_authority || WorldInfo.NetMode == NM_ListenServer || WorldInfo.NetMode == NM_StandAlone)
		{
			if(oZedCurrentlyBeingSprayed == none)
			{
				SprayEnded();
			}
		}
	}
}

simulated function ChangeMaterial()
{
	// Removed from base class
	/*local int i, Idx;
    if( BarrelHeat != LastBarrelHeat )
    {
    	for( i = 0; i < WeaponMICs.Length; ++i )
    	{
    		if( WeaponMICs[i] != none )
    		{
				WeaponMICs[i].SetScalarParameterValue('Glow_Intensity', BarrelHeat);
			}
		}
    }*/
}

simulated protected function TurnOnPilot()
{
	Super.TurnOnPilot();

	if( FlamePool[0] != None )
	{
		KFSprayActor_ArcGenerator(FlamePool[0]).OwnerWeapon = self;
		MaxNumberOfZedsZapped=KFSprayActor_ArcGenerator(FlamePool[0]).MaxNumberOfZedsZapped;
		MaxDistanceToBeZapped=KFSprayActor_ArcGenerator(FlamePool[0]).MaxDistanceToBeZapped;
		ZapInterval=KFSprayActor_ArcGenerator(FlamePool[0]).ZapInterval;
		ChainDamage=KFSprayActor_ArcGenerator(FlamePool[0]).ChainDamage;
	}
	if( FlamePool[1] != None )
	{
		KFSprayActor_ArcGenerator(FlamePool[1]).OwnerWeapon = self;
	}
}

simulated function float FlameHeatCalc()
{
	//hack in order to make the arc gen always glow
	LastBarrelHeat = 1.0f;
	return 1.0f;
}

simulated event PostBeginPlay()
{
	local class<EmitterPool> PoolClass;
	super.PostBeginPlay();

	PoolClass = class<EmitterPool>(DynamicLoadObject(EmitterPoolClassPath, class'Class'));
	if (PoolClass != None)
	{
		vBeamEffects = Spawn(PoolClass, self,, vect(0,0,0), rot(0,0,0));
	}
}


/***************************************

	PARTICLE SYSTEM POOL AND ATTACHMENT MANAGEMENT

 ***************************************/

/** We so we detach the Component once we are done playing it **/
simulated function OnBeamEffectFinished( ParticleSystemComponent PSC )
{
	PSC.DeactivateSystem();
	EndPSC(PSC);
}

//returns the position of the effect in the array, otherwise, -1
simulated function int SpawnBeam(Actor _OriginActor, Actor _DestinationActor)
{	
	local ParticleSystemComponent BeamPSC;

	local BeamAttachedToActor BeamAttachedInfo;
	local int i;

	//if actor is dupped in active beams, not chain again this to another beam

	for(i = 0; i < vActiveBeamEffects.Length; i++)
	{
		if(vActiveBeamEffects[i].oAttachedZed == _DestinationActor)
		{
			return -1;
		}
	}
	BeamPSC = vBeamEffects.SpawnEmitterCustomLifetime(BeamPSCTemplate);
	if(BeamPSC != none)
	{
		BeamPSC.SetBeamSourcePoint(0, _OriginActor.Location, 0);
		BeamPSC.SetBeamTargetPoint(0, _DestinationActor.Location, 0);
		BeamPSC.SetKillOnDeactivate(0, true);
		BeamPSC.SetAbsolute(false, false, false);
		BeamPSC.bUpdateComponentInTick = true;

		BeamAttachedInfo.oBeam = BeamPSC;
		BeamAttachedInfo.oAttachedZed = KFPawn_Monster(_DestinationActor);

		if(role != role_authority || WorldInfo.NetMode == NM_ListenServer || WorldInfo.NetMode == NM_StandAlone)
		{
			BeamPSC.SetActive(true);
			AttachComponent(BeamPSC);
		}

		BeamAttachedInfo.oBeam.SetActive(true);
		vActiveBeamEffects.AddItem(BeamAttachedInfo);
		return vActiveBeamEffects.Length - 1;
	}
	else
	{
	}
	return -1;
}

simulated function MarkBeamToDeactivate(BeamAttachedToActor _BeamData)
{
	vAuxDeletionArray.AddItem(_BeamData);
}

simulated function MarkZedToUnchain(DamagedActorInfo _DamageActorInfo)
{
	vAuxDeletionArrayChainedActors.AddItem(_DamageActorInfo);
}

simulated function BeamAttachedToActor GetBeamFromActor(Actor _Actor)
{
	local int i;

	for(i = 0; i < vActiveBeamEffects.Length; i++)
	{
		if(vActiveBeamEffects[i].oAttachedZed == _Actor)
		{
			return vActiveBeamEffects[i];
		}
	}
}

simulated function DeactivateBeam(Actor _ChainedActor)
{
	local int i;
	for(i = 0; i < vActiveBeamEffects.Length; i++)
	{
		if(vActiveBeamEffects[i].oAttachedZed == _ChainedActor)
		{
			OnBeamEffectFinished(vActiveBeamEffects[i].oBeam);
			vActiveBeamEffects.RemoveItem(vActiveBeamEffects[i]);
			break;
		}
	}

}

simulated function EndPSC(ParticleSystemComponent _Value)
{
	/*if(vCachedBeamEffects.Length < MaxNumberOfZedsZapped)
	{
		vCachedBeamEffects.AddItem(_Value);
	}*/
	_Value.KillParticlesForced();
	vBeamEffects.OnParticleSystemFinished(_Value);
	DetachComponent(_Value);
}


/***************************************

	END PARTICLE SYSTEM POOL AND ATTACHMENT MANAGEMENT

 ***************************************/



/***************************************

	CHAIN LOGIC FUNCTIONS

 ***************************************/
 
simulated function SetCurrentSprayedZed(KFPawn_Monster _Monster)
{
	if(role == role_authority || WorldInfo.NetMode == NM_ListenServer || WorldInfo.NetMode == NM_StandAlone)
	{
		oZedCurrentlyBeingSprayed = _Monster;
		bNetDirty=true;
	}
}

 //returns true if it has successfully chained the zed, false otherwise (ex: dupe zed in the array)
function bool ChainZed(Actor _ZedToChain)
{
	local DamagedActorInfo NewActorInfo;
	local int i;
	
	for (i = vRecentlyZappedActors.Length - 1; i >= 0; i--)
	{
		//remove everything if pawn died or interval is greater than the time its supposed to be in here; 
		if(vRecentlyZappedActors[i].HitActor == _ZedToChain)
		{
			return false;
		}
	}

	NewActorInfo.HitActor = _ZedToChain;
	NewActorInfo.HitTime = WorldInfo.TimeSeconds;
	vRecentlyZappedActors.AddItem(NewActorInfo);
	return true;
}

function UnchainZed(DamagedActorInfo _ZedToUnchain)
{
	vRecentlyZappedActors.RemoveItem(_ZedToUnchain);
}

function bool CheckRecentlyZapped(Actor _ActorToCheck)
{
	local int i;
	local bool bZapedRecently;
	bZapedRecently = false;

	for (i = vRecentlyZappedActors.Length - 1; i >= 0; i--)
	{
		if (vRecentlyZappedActors[i].HitActor == _ActorToCheck)
		{
			//`Warn("FOUND ACTOR. WorldInfo.TimeSeconds = " $(WorldInfo.TimeSeconds)$ "");
			//`Warn("FOUND ACTOR. vRecentlyZappedActors[i].HitTime = " $(vRecentlyZappedActors[i].HitTime)$ "");
			//`Warn("FOUND ACTOR. INTERVAL = " $(WorldInfo.TimeSeconds - vRecentlyZappedActors[i].HitTime)$ "");
			// Only damage at a specified rate, so return if it's too soon
			if ((WorldInfo.TimeSeconds - vRecentlyZappedActors[i].HitTime) < ZapInterval)
			{
				bZapedRecently = true;
			}
			break;
		}
	}

	return bZapedRecently;
}

function UpdateLastHitTimeForActor(Actor _ActorToCheck)
{
	local int i;
	for (i = vRecentlyZappedActors.Length - 1; i >= 0; i--)
	{
		if (vRecentlyZappedActors[i].HitActor == _ActorToCheck)
		{
			//`Warn("SETTING TIME: " $WorldInfo.TimeSeconds$ "");
			vRecentlyZappedActors[i].HitTime = WorldInfo.TimeSeconds;
			break;
		}
	}
}

simulated function ChainNearZeds(Actor _TouchActor)
{
	local KFPawn_Monster oMonsterPawn;

	//`Warn("ChainNearZeds(Actor _TouchActor)");
	//we get all pawns from the world to check them
	foreach WorldInfo.AllPawns( class'KFPawn_Monster', oMonsterPawn )
	{
		//if its alive and its not the main sprayed monster
		if( oMonsterPawn.IsAliveAndWell() && oMonsterPawn != _TouchActor)
		{
			//if its close enough to be zapped
			if( VSizeSQ(oMonsterPawn.Location - _TouchActor.Location) < Square(MaxDistanceToBeZapped) )
			{
				if(vActiveBeamEffects.Length < MaxNumberOfZedsZapped)
				{
					//if we have nothing in between
					if(FastTrace(_TouchActor.Location, oMonsterPawn.Location, vect(0,0,0)) == false)
					{
						continue;
					}
					if(_TouchActor.IsA('KFPawn_Monster'))
					{
						if(role == role_authority || WorldInfo.NetMode == NM_ListenServer || WorldInfo.NetMode == NM_StandAlone)
						{
							ChainZed(oMonsterPawn);
						}
						SpawnBeam(_TouchActor, oMonsterPawn);
					}
				}
				else
				{
					break;
				}
			}
		}
	}
}

/***************************************

	CHAIN LOGIC FUNCTIONS END

 ***************************************/

simulated event Tick(float DeltaTime)
{
	local int i;
	local vector BeamStartPoint, BeamEndPoint;

	Super.Tick(DeltaTime);

	if(oZedCurrentlyBeingSprayed != none)
	{
			//if we have space for one more zed to chain, we try to chain one zed
			if(vActiveBeamEffects.Length < MaxNumberOfZedsZapped && !CheckRecentlyZapped(oZedCurrentlyBeingSprayed))
			{
				ChainNearZeds(oZedCurrentlyBeingSprayed);
			}
			//`Warn(vActiveBeamEffects.Length);
			//check current beams
			for (i = vActiveBeamEffects.Length - 1; i >= 0; i--)
			{
				//if a current beam has gone out of sight (we have a wall in between for example), remove the beam and continue to next beam
				if(FastTrace(vActiveBeamEffects[i].oAttachedZed.Location, oZedCurrentlyBeingSprayed.Location, vect(0,0,0)) == false)
				{
					//OnBeamEffectFinished(vActiveBeamEffects[i].oBeam);
					MarkBeamToDeactivate(GetBeamFromActor(vRecentlyZappedActors[i].HitActor));
					continue;
				}

				//if its not near enough to stay zapped, we break the chain
				if (VSizeSQ(vActiveBeamEffects[i].oAttachedZed.Location - oZedCurrentlyBeingSprayed.Location) < Square(MaxDistanceToBeZapped))
				{
					//if has been recently damaged, do not take damage again until the fire rate tells us
					if( !CheckRecentlyZapped(vActiveBeamEffects[i].oAttachedZed))
					{
						//take damage
						if(vActiveBeamEffects[i].oAttachedZed.IsAliveAndWell())
						{		
							if(role == role_authority || WorldInfo.NetMode == NM_ListenServer || WorldInfo.NetMode == NM_StandAlone)
							{ 
								ChainedZapDamageFunction(vActiveBeamEffects[i].oAttachedZed, oZedCurrentlyBeingSprayed);
								UpdateLastHitTimeForActor(vActiveBeamEffects[i].oAttachedZed);
							}
							 
							if(role != role_authority || WorldInfo.NetMode == NM_ListenServer || WorldInfo.NetMode == NM_StandAlone)
							{
								//`warn(vActiveBeamEffects[i].oAttachedZed.Location);
								BeamStartPoint = oZedCurrentlyBeingSprayed.Mesh.GetBoneLocation('Spine1');
								BeamEndPoint = vActiveBeamEffects[i].oAttachedZed.Mesh.GetBoneLocation('Spine1');

								if(BeamStartPoint == vect(0,0,0)) BeamStartPoint = oZedCurrentlyBeingSprayed.Location;
								if(BeamEndPoint == vect(0,0,0)) BeamEndPoint = vActiveBeamEffects[i].oAttachedZed.Location;

								vActiveBeamEffects[i].oBeam.SetBeamSourcePoint(0, BeamStartPoint, 0);
								vActiveBeamEffects[i].oBeam.SetBeamTargetPoint(0, BeamEndPoint, 0);
							}
							

							if(!vActiveBeamEffects[i].oAttachedZed.IsAliveAndWell())
							{
								//OnBeamEffectFinished(vActiveBeamEffects[i].oBeam);
								MarkBeamToDeactivate(GetBeamFromActor(vActiveBeamEffects[i].oAttachedZed));
							}
						}
					}
				}
				else
				{
					//OnBeamEffectFinished(vActiveBeamEffects[i].oBeam);
					if(role != role_authority || WorldInfo.NetMode == NM_ListenServer || WorldInfo.NetMode == NM_StandAlone)
						MarkBeamToDeactivate(GetBeamFromActor(vActiveBeamEffects[i].oAttachedZed));
				}
			}
	}


	if(oZedCurrentlyBeingSprayed == none && (role != role_authority || WorldInfo.NetMode == NM_ListenServer || WorldInfo.NetMode == NM_StandAlone))
	{
		for(i = 0; i < vActiveBeamEffects.Length; i++)
		{
			OnBeamEffectFinished(vActiveBeamEffects[i].oBeam);
		}
		vActiveBeamEffects.Remove(0, vActiveBeamEffects.Length);
	}
	else if(oZedCurrentlyBeingSprayed != none && (role != role_authority || WorldInfo.NetMode == NM_ListenServer || WorldInfo.NetMode == NM_StandAlone))
	{
		`log(vActiveBeamEffects.Length);
		for(i = 0; i < vActiveBeamEffects.Length; i++)
		{

			if(!vActiveBeamEffects[i].oAttachedZed.IsAliveAndWell())
			{
				//OnBeamEffectFinished(vActiveBeamEffects[i].oBeam);
				MarkBeamToDeactivate(GetBeamFromActor(vActiveBeamEffects[i].oAttachedZed));
			}
		}

		for(i = 0; i < vAuxDeletionArray.Length; i++)
		{
			OnBeamEffectFinished(vAuxDeletionArray[i].oBeam);
			vAuxDeletionArray.RemoveItem(vAuxDeletionArray[i]);

		}
	}

	if(role == role_authority || WorldInfo.NetMode == NM_ListenServer || WorldInfo.NetMode == NM_StandAlone)
	{
		for (i = vRecentlyZappedActors.Length - 1; i >= 0; i--)
		{
			//remove everything if pawn died 
			if(vRecentlyZappedActors[i].HitActor == none )
			{
				DeactivateBeam(vRecentlyZappedActors[i].HitActor);
				//UnchainZed(vRecentlyZappedActors[i]);
				MarkZedToUnchain(vRecentlyZappedActors[i]);
			}
			//remove everything if pawn died 
			if(!KFPawn_Monster(vRecentlyZappedActors[i].HitActor).IsAliveAndWell())
			{
				DeactivateBeam(vRecentlyZappedActors[i].HitActor);
				//UnchainZed(vRecentlyZappedActors[i]);
				MarkZedToUnchain(vRecentlyZappedActors[i]);
			}
			//remove if interval is greater than the time its supposed to be in here; 
			if(((WorldInfo.TimeSeconds - vRecentlyZappedActors[i].HitTime) > 1.f))
			{
				DeactivateBeam(vRecentlyZappedActors[i].HitActor);
				//UnchainZed(vRecentlyZappedActors[i]);
				MarkZedToUnchain(vRecentlyZappedActors[i]);
			}
		}
		for(i = 0; i < vAuxDeletionArrayChainedActors.Length; i++)
		{
			UnchainZed(vAuxDeletionArrayChainedActors[i]);
		}
		vAuxDeletionArrayChainedActors.Remove(0, vAuxDeletionArrayChainedActors.Length);

	}
	
	/*if(role != role_authority || WorldInfo.NetMode == NM_ListenServer || WorldInfo.NetMode == NM_StandAlone)
	{
		for (i = vRecentlyZappedActors.Length - 1; i >= 0; i--)
		{
			//remove everything if pawn died 
			if(vRecentlyZappedActors[i].HitActor == none )
			{
				DeactivateBeam(vRecentlyZappedActors[i].HitActor);
				MarkZedToUnchain(vRecentlyZappedActors[i]);

			}
			//remove everything if pawn died 
			if(!KFPawn_Monster(vRecentlyZappedActors[i].HitActor).IsAliveAndWell())
			{
				DeactivateBeam(vRecentlyZappedActors[i].HitActor);
				MarkZedToUnchain(vRecentlyZappedActors[i]);

			}
			//remove if interval is greater than the time its supposed to be in here; 
			if(((WorldInfo.TimeSeconds - vRecentlyZappedActors[i].HitTime) > 1.f))
			{
				DeactivateBeam(vRecentlyZappedActors[i].HitActor);
				MarkZedToUnchain(vRecentlyZappedActors[i]);
			}
		}	
	}*/

}


/** Notification that a direct impact has occurred. */
event ProcessDirectImpact()
{
    if( KFPlayer != none )
    {
        KFPlayer.AddShotsHit(1);
    }
}

function ChainedZapDamageFunction(Actor _TouchActor, Actor _OriginActor)
{
	local vector Momentum;
	local TraceHitInfo HitInfo;
	local Pawn TouchPawn;
	local int TotalDamage;
 
	if (_OriginActor != none)
	{
		Momentum = _TouchActor.Location - _OriginActor.Location;
	}

	//Momentum *= (MomentumScale / DistToHitActor);
	if (ChainDamage > 0)
	{
		TouchPawn = Pawn(_TouchActor);

		// Let script know that we hit something
		if (TouchPawn != none)
		{
			ProcessDirectImpact();
		}
		//`Warn("["$WorldInfo.TimeSeconds$"] Damaging "$_TouchActor.Name$" for "$ChainDamage$", Dist: "$VSize(_TouchActor.Location - _OriginActor.Location));
		
		TotalDamage = ChainDamage * GetUpgradeDamageMod();
		_TouchActor.TakeDamage(TotalDamage, KFPlayer, _TouchActor.Location, Momentum, class'KFDT_EMP_ArcGenerator_DefaultFiremodeZapDamage', HitInfo, self);
	}
}

simulated function SprayEnded()
{
	local int i;

	/*for (i = 0; i < vActiveBeamEffects.Length - 1; i++)
	{
		DeactivateBeam(vActiveBeamEffects[i].oAttachedZed);
	}*/
    //`Warn(vActiveBeamEffects.Length);
	for(i = 0; i < vActiveBeamEffects.Length; i++)
	{
		OnBeamEffectFinished(vActiveBeamEffects[i].oBeam);
	}

	vActiveBeamEffects.Remove(0, vActiveBeamEffects.Length);

}

/**********************************************************************************




 */


defaultproperties
{
	FlameSprayArchetype=KFSprayActor_ArcGenerator'WEP_HRG_ArcGenerator_ARCH.WEP_HRG_ArcGenerator_Spray'

	// Shooting Animations
	bHasFireLastAnims=true
	FireSightedAnims[0]=Shoot
	FireSightedAnims[1]=Shoot_Heavy_Iron
	FireLastHeavySightedAnim=Shoot_Heavy_Iron_Last
    FireHeavyAnim=Shoot_Heavy
    FireLastHeavyAnim=Shoot_Heavy_Last

    // FOV
	MeshIronSightFOV=52
    PlayerIronSightFOV=80

	// Zooming/Position
	IronSightPosition=(X=3,Y=0,Z=0)
	PlayerViewOffset=(X=5.0,Y=9,Z=-3)

	// Depth of field
	DOF_FG_FocalRadius=150
	DOF_FG_MaxNearBlurSize=1

	// Content
	PackageKey="HRG_ArcGenerator"
	FirstPersonMeshName="WEP_1P_HRG_ArcGenerator_MESH.Wep_1stP_HRG_ArcGenerator_Rig"
	FirstPersonAnimSetNames(0)="WEP_1p_HRG_ArcGenerator_ANIM.WEP_1p_HRG_ArcGenerator_ANIM"
	PickupMeshName="WEP_3P_HRG_ArcGenerator_MESH.Wep_HRG_ArcGenerator_Pickup"
	AttachmentArchetypeName="WEP_HRG_ArcGenerator_ARCH.HRG_ArcGenerator_3P"
	MuzzleFlashTemplateName="WEP_HRG_ArcGenerator_ARCH.Wep_HRG_ArcGenerator_MuzzleFlash"

	// Ammo
	MagazineCapacity[0]=90 //100
	SpareAmmoCapacity[0]=450 //500
	InitialSpareMags[0]=0
	AmmoPickupScale[0]=0.5
	bCanBeReloaded=true
	bReloadFromMagazine=true

	// Recoil
	maxRecoilPitch=150
	minRecoilPitch=115
	maxRecoilYaw=115
	minRecoilYaw=-115
	RecoilRate=0.085
	RecoilMaxYawLimit=500
	RecoilMinYawLimit=65034
	RecoilMaxPitchLimit=900
	RecoilMinPitchLimit=65035
	RecoilISMaxYawLimit=75
	RecoilISMinYawLimit=65460
	RecoilISMaxPitchLimit=375
	RecoilISMinPitchLimit=65460
	RecoilViewRotationScale=0.25
	IronSightMeshFOVCompensationScale=1.5
    HippedRecoilModifier=1.5

    // Inventory
	InventorySize=9 //10
	GroupPriority=100
	WeaponSelectTexture=Texture2D'WEP_UI_HRG_ArcGenerator_TEX.UI_WeaponSelect_HRG_ArcGenerator'

	// DEFAULT_FIREMODE
	FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Electricity'
	FiringStatesArray(DEFAULT_FIREMODE)=SprayingFire
	WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Custom
	FireInterval(DEFAULT_FIREMODE)=+0.1//+0.07 // 850 RPM
	MinAmmoConsumed=2 //3
	FireOffset=(X=30,Y=4.5,Z=-5)

	// ALT_FIREMODE
	WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Projectile
	Spread(ALTFIRE_FIREMODE) = 0.0085
	FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSingleFiring
    WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_ArcGeneratorSphereBlast'
	FireInterval(ALTFIRE_FIREMODE)=+1.0 //+0.223 //269 RPMs
	AmmoCost(ALTFIRE_FIREMODE)=15
	PenetrationPower(ALTFIRE_FIREMODE)=40.0 //10.0
	InstantHitDamage(ALTFIRE_FIREMODE)=220 //180 //185 //200
	InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_EMP_ArcGeneratorSphereImpact'


	// BASH_FIREMODE
	InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_ArcGenerator'
	InstantHitDamage(BASH_FIREMODE)=26

	// Fire Effects
	WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_HRG_ArcGenerator.Play_HRG_ArcGenerator_Fire_3P_Loop', FirstPersonCue=AkEvent'WW_WEP_HRG_ArcGenerator.Play_HRG_ArcGenerator_Fire_1P_Loop')
	WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_HRG_ArcGenerator.Play_HRG_ArcGenerator_AltFire_3P', FirstPersonCue=AkEvent'WW_WEP_HRG_ArcGenerator.Play_HRG_ArcGenerator_AltFire_1P')
    WeaponFireLoopEndSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_HRG_ArcGenerator.Play_HRG_ArcGenerator_Fire_3P_LoopEnd', FirstPersonCue=AkEvent'WW_WEP_HRG_ArcGenerator.Play_HRG_ArcGenerator_Fire_1P_LoopEnd')

	//@todo: add akevents when we have them
	WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_SA_Microwave_Gun.Play_SA_MicrowaveGun_DryFire'
	WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_SA_Microwave_Gun.Play_SA_MicrowaveGun_DryFire'
	PilotLightPlayEvent=AkEvent'WW_WEP_HRG_ArcGenerator.Play_HRG_ArcGenerator_PilotLight_Loop'
	PilotLightStopEvent=AkEvent'WW_WEP_HRG_ArcGenerator.Stop_HRG_ArcGenerator_PilotLight_Loop'

	// Advanced (High RPM) Fire Effects
	bLoopingFireAnim(DEFAULT_FIREMODE)=true
	bLoopingFireSnd(DEFAULT_FIREMODE)=true
	SingleFireSoundIndex=FIREMODE_NONE

	// Attachments
	bHasIronSights=true
	bHasFlashlight=false

   	AssociatedPerkClasses(0)=class'KFPerk_Survivalist'

   	BonesToLockOnEmpty=(RW_Handle1, RW_BatteryCylinder1, RW_BatteryCylinder2, RW_LeftArmSpinner, RW_RightArmSpinner, RW_LockEngager2, RW_LockEngager1)

 	// AI Warning
 	bWarnAIWhenFiring=true
    MaxAIWarningDistSQ=2250000

	// Weapon Upgrade stat boosts
	//WeaponUpgrades[1]=(IncrementDamage=1.15f,IncrementWeight=1)

	WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1)))

	BeamPSCTemplate = ParticleSystem'WEP_HRG_ArcGenerator_EMIT.FX_Beam_Test'
	EmitterPoolClassPath="Engine.EmitterPool"
	oZedCurrentlyBeingSprayed=none;

	MaxNumberOfZedsZapped=3
	MaxDistanceToBeZapped=2500
	ZapInterval=0.07
	ChainDamage=5;
	bAlwaysRelevant = true
	bOnlyRelevantToOwner = false
}