//=============================================================================
// KFWeap_LMG_Stoner63A
//=============================================================================
// The Stoner63A rifle
//=============================================================================
// Killing Floor 2
// Copyright (C) 2017 Tripwire Interactive LLC
// - Matt "Squirrlz" Farber
//=============================================================================
class KFWeap_LMG_Stoner63A extends KFWeap_RifleBase;

/** Alternate reload anims (when below the bullet belt threshold */
const ReloadLowAmmoAnim = 'Reload_Empty_Half';
const ReloadLowAmmoEliteAnim = 'Reload_Empty_Half_Elite';

/** Array of bone names corresponding to bullets in the ammo belt */
var protected const string AmmoBeltBulletBonePrefix;

/** Number of bullets in the ammo belt */
var protected const int NumAmmoBeltBullets;

/** How much ammo we had the last time we updated the ammo belt */
var transient protected int LastAmmoCount;

/** TRUE when set for the first time */
var transient protected bool bAmmoBeltInitialized;

/** Just in case we spawned in with an ammo count that's lower than the threshold */
simulated event ReplicatedEvent( name VarName )
{
	super.ReplicatedEvent( VarName );

	if( !bAmmoBeltInitialized )
	{
		UpdateAmmoBeltBullets();
	}
}

/** Just in case we spawned in with an ammo count that's lower than the threshold */
simulated event PostBeginPlay()
{
	super.PostBeginPlay();

	if( !bAmmoBeltInitialized && Role == ROLE_Authority )
	{
		UpdateAmmoBeltBullets();
	}
}

/** Update ammo belt */
simulated function ConsumeAmmo( byte FireModeNum )
{
	super.ConsumeAmmo( FireModeNum );

	UpdateAmmoBeltBullets();
}

/** Update ammo belt */
simulated function PerformReload( optional byte FireModeNum )
{
	super.PerformReload( FireModeNum );

	UpdateAmmoBeltBullets();
}

/** Notify triggered by reload animations, when ammo belt is grabbed offscreen */
simulated function ANIMNOTIFY_RestoreAmmoBelt()
{
	local int AmmoType, PendingAmmoCount;

	AmmoType = GetAmmoType(0);

	// This value will sync with the amount actually reloaded in PerformReload()
	PendingAmmoCount = Min( AmmoCount[AmmoType] + SpareAmmoCount[AmmoType], MagazineCapacity[AmmoType] );
	if( PendingAmmoCount < NumAmmoBeltBullets )
	{
		UpdateAmmoBeltBullets( PendingAmmoCount );
	}
	else
	{
		UpdateAmmoBeltBullets( , true );
	}
}

/** Hides/shows bones on the weapon to simulate reaching the end of the ammo belt */
simulated function UpdateAmmoBeltBullets( optional int ForcedBulletCount=INDEX_NONE, optional bool bShowAll=false )
{
	local Name BulletBoneName;
	local int NumAmmo, i;

	if( WorldInfo.NetMode == NM_DedicatedServer )
	{
		return;
	}

	// Don't do any bone alterations until the bone array has been filled out
	if( MySkelMesh.LocalAtoms.Length == 0 )
	{
		// Check on the next frame to see if we can init our ammo belt
		if( !IsTimerActive(nameOf(Timer_AttemptAmmoBeltUpdate)) )
		{
			SetTimer( 0.01f, false, nameOf(Timer_AttemptAmmoBeltUpdate) );
		}
		return;
	}

	// So we don't do this in PostInitAnimTree() or again in Timer_AttemptAmmoBeltUpdate() if we don't have to
	bAmmoBeltInitialized = true;

	// Don't do anything if ammo hasn't changed
	NumAmmo = ForcedBulletCount != INDEX_NONE ? ForcedBulletCount : AmmoCount[GetAmmoType(0)];
	if( !bShowAll && (LastAmmoCount == NumAmmo || (LastAmmoCount >= NumAmmoBeltBullets && NumAmmo >= NumAmmoBeltBullets)) )
	{
		return;
	}

	// Hide or unhide depending on place in array
	for( i = 0; i < NumAmmoBeltBullets; ++i )
	{
		BulletBoneName = Name( AmmoBeltBulletBonePrefix $ (i+1) );

		// Unhide all bullets if our ammo count is higher than the number of bullets
		if( bShowAll || NumAmmo >= NumAmmoBeltBullets )
		{
			MySkelMesh.UnHideBoneByName( BulletBoneName );
			continue;
		}

		if( i > NumAmmo-1 )
		{
			MySkelMesh.HideBoneByName( BulletBoneName, PBO_None );
		}
		else
		{
			MySkelMesh.UnHideBoneByName( BulletBoneName );
		}
	}

	LastAmmoCount = NumAmmo;
}

simulated function Timer_AttemptAmmoBeltUpdate()
{
	if( !bAmmoBeltInitialized )
	{
		UpdateAmmoBeltBullets();
	}
}

/** Returns animation to play based on reload type and status */
simulated function name GetReloadAnimName( bool bTacticalReload )
{
	if( AmmoCount[0] > 0 && AmmoCount[0] < NumAmmoBeltBullets )
	{
		// If we are below the threshold, play our low ammo reload
		return bTacticalReload ? ReloadLowAmmoEliteAnim : ReloadLowAmmoAnim;
	}
	else
	{
		return super.GetReloadAnimName( bTacticalReload );
	}
}

/**
 * State WeaponEquipping
 * The Weapon is in this state while transitioning from Inactive to Active state.
 * Typically, the weapon will remain in this state while its selection animation is being played.
 * While in this state, the weapon cannot be fired.
 */
simulated state WeaponEquipping
{
	simulated event BeginState( Name PreviousStateName )
	{
		super.BeginState( PreviousStateName );

		// Just in case a reload was interrupted after ANIMNOTIFY_RestoreAmmoBelt() was called,
		// set the ammo belt to the current amount of bullets in the magazine on equip
		UpdateAmmoBeltBullets();
	}
}

defaultproperties
{
	// Shooting Animations
	FireSightedAnims[0]=Shoot_Iron
	FireSightedAnims[1]=Shoot_Iron2
	FireSightedAnims[2]=Shoot_Iron3

    // FOV
    MeshFOV=75
	MeshIronSightFOV=35
    PlayerIronSightFOV=70

	// Depth of field
	DOF_FG_FocalRadius=85
	DOF_FG_MaxNearBlurSize=2.5

	// Content
	PackageKey="Stoner63a"
	FirstPersonMeshName="WEP_1P_Stoner63A_MESH.Wep_1stP_Stoner63A_Rig"
	FirstPersonAnimSetNames(0)="WEP_1P_Stoner63A_ANIM.Wep_1stP_Stoner63A_Anim"
	PickupMeshName="WEP_3P_Stoner63A_MESH.Wep_Stoner63A_Pickup"
	AttachmentArchetypeName="WEP_Stoner63A_ARCH.Wep_Stoner63A_3P"
	MuzzleFlashTemplateName="WEP_Stoner63A_ARCH.Wep_Stoner63A_MuzzleFlash"

   	// Zooming/Position
	PlayerViewOffset=(X=4.0,Y=8,Z=-4)
	IronSightPosition=(X=8.5,Y=0,Z=0)

	// Ammo
	MagazineCapacity[0]=75
	SpareAmmoCapacity[0]=500
	InitialSpareMags[0]=1
	bCanBeReloaded=true
	bReloadFromMagazine=true

	// Recoil
	maxRecoilPitch=120
	minRecoilPitch=70
	maxRecoilYaw=130
	minRecoilYaw=-130
	RecoilRate=0.08
	RecoilMaxYawLimit=500
	RecoilMinYawLimit=65035
	RecoilMaxPitchLimit=900
	RecoilMinPitchLimit=65035
	RecoilISMaxYawLimit=75
	RecoilISMinYawLimit=65460
	RecoilISMaxPitchLimit=375
	RecoilISMinPitchLimit=65460
	RecoilViewRotationScale=0.25
	IronSightMeshFOVCompensationScale=2.3
    HippedRecoilModifier=1.5

    // Inventory / Grouping
	InventorySize=9
	GroupPriority=100
	WeaponSelectTexture=Texture2D'wep_ui_stoner63a_tex.UI_WeaponSelect_Stoner'
   	AssociatedPerkClasses(0)=class'KFPerk_Commando'

	// DEFAULT_FIREMODE
	FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletAuto'
	FiringStatesArray(DEFAULT_FIREMODE)=WeaponFiring
	WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_InstantHit
	WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_AssaultRifle'
	InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_Stoner63A'
	FireInterval(DEFAULT_FIREMODE)=+0.066 // 900 RPM
	Spread(DEFAULT_FIREMODE)=0.0085
	InstantHitDamage(DEFAULT_FIREMODE)=30.0 //25 //30
	FireOffset=(X=30,Y=4.5,Z=-5)

	// ALT_FIREMODE
	FireModeIconPaths(ALTFIRE_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletAuto'
	FiringStatesArray(ALTFIRE_FIREMODE)=WeaponFiring
	WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_None

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

	// Fire Effects
	WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Stoner.Play_WEP_Stoner_Fire_3P_Loop', FirstPersonCue=AkEvent'WW_WEP_Stoner.Play_WEP_Stoner_Fire_1P_Loop')
	WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Stoner.Play_WEP_Stoner_Fire_3P_Single', FirstPersonCue=AkEvent'WW_WEP_Stoner.Play_WEP_Stoner_Fire_1P_Single')
	WeaponFireLoopEndSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Stoner.Play_WEP_Stoner_Fire_3P_EndLoop', FirstPersonCue=AkEvent'WW_WEP_Stoner.Play_WEP_Stoner_Fire_1P_EndLoop')
	WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_SA_L85A2.Play_WEP_SA_L85A2_Handling_DryFire'
	WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_SA_L85A2.Play_WEP_SA_L85A2_Handling_DryFire'
	EjectedShellForegroundDuration=0.8f

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

	// Attachments
	bHasIronSights=true
	bHasFlashlight=false

	// Ammo belt
	AmmoBeltBulletBonePrefix="RW_Bullets"
	NumAmmoBeltBullets=14
	LastAmmoCount=-1

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

	WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.27f), (Stat=EWUS_Weight, Add=1)))
}
