
enum eFlakAnims
{
	anim_Flak_Fire    = anim_weaponFire,
	anim_Flak_AltFire = anim_weaponFireCharged,
	anim_Flak_Load1   = anim_weaponAttack1, // primary, fast load
	anim_Flak_Load2   = anim_weaponAttack2  // secondary, slower load
}

enum eFlakFrames
{
	Flak_SwapIn1    =   0, Flak_SwapIn2    =  23,
	Flak_SwapOut1_1 = 111, Flak_SwapOut1_2 = 124, // loaded swap-out
	Flak_SwapOut2_1 = 125, Flak_SwapOut2_2 = 138, // empty swap-out
	Flak_Fire1      =  65, Flak_Fire2      =  85,
	Flak_AltFire1   =  86, Flak_AltFire2   = 110,
	Flak_Load1      =  23, Flak_Load2      =  65,
	Flak_Idle       =  65
}

final class TurokAutoShotgun : TurokWeapon
{
	float recoilRoll;

	TurokAutoShotgun( kWeapon @a )
	{
		super( a );
		BobDamping = 0.972f;
	}

	void AnimProperties( int&out first, int&out last, float&out rate, bool&out bLoop )
	{
		rate = 60; bLoop = false;
		switch ( PlayingID() )
		{
			case anim_weaponSwapIn:  first = Flak_SwapIn1;    last = HasAmmo()
			                                                       ? Flak_Load2
			                                                       : Flak_SwapIn2;      break;
			case anim_weaponSwapOut:
			      if ( HasAmmo() ) { first = Flak_SwapOut1_1; last = Flak_SwapOut1_2; }
			      else             { first = Flak_SwapOut2_1; last = Flak_SwapOut2_2; } break;
			case anim_Flak_Fire:     first = Flak_Fire1;      last = Flak_Fire2;        break;
			case anim_Flak_AltFire:  first = Flak_AltFire1;   last = Flak_AltFire2;     break;
			case anim_Flak_Load1:    rate = 75; // rate  = 90;
			case anim_Flak_Load2:    first = Flak_Load1;      last = Flak_Load2;        break;
			default: /* idle */      first =                  last = HasAmmo()
			                                                       ? Flak_Idle
			                                                       : Flak_SwapIn2;
			                         bLoop = true; break;
		}
	}

	int ModFrame( int v )
	{
		// play load anim at 2x speed during swap-in
		if ( IsPlaying(anim_weaponSwapIn) && v > Flak_SwapIn2 )
			return Flak_SwapIn2 + (v - Flak_SwapIn2) * 2;
		return v;
	}

	void AnimEnd()
	{
		switch ( PlayingID() )
		{
			case anim_Flak_Fire:
				if ( HasAmmo() )
				{
					PlayAnim( anim_Flak_Load1 );
					self.PlaySound( "U1/sounds/Flak/Reload.ksnd" );
					return;
				}
				break;
			case anim_Flak_AltFire:
				if ( HasAmmo() )
				{
					PlayAnim( anim_Flak_Load2 );
					self.PlaySound( "U1/sounds/Flak/Reload.ksnd" );
					return;
				}
		}
		TurokWeapon::AnimEnd();
	}

	bool Refire()
	{
		switch ( PlayingID() )
		{
			case anim_Flak_Load1: case anim_Flak_Load2:
				return true;
		}
		return false;
	}

	void OnTick()
	{
		TurokWeapon::OnTick();
		AmmoLED();
		switch ( PlayingID() )
		{
			case anim_weaponSwapIn:
				if ( self.ModelVariation() == Flak_Load1 && HasAmmo() )
					self.PlaySound( "U1/sounds/Flak/SwapIn_Load.ksnd" );
				break;
			case anim_Flak_Fire:
			case anim_Flak_AltFire:
				Recoil();
		}
	}

	void Recoil()
	{
		float f = (Flak_Fire2 - Flak_Fire1) / 60.0f;
		if ( PlayTime() > f ) return;
		f = 1 - PlayTime() / f;
		f *= f;
		OwnerP().RecoilPitch() = Math::Sin(   Math::pi * f ) * f * -0.05f;
		OwnerP().Roll()        = Math::Sin( 2*Math::pi * f ) * f * -0.03f * recoilRoll;
	}

	void OnBeginFire()
	{
		// primary takes precedence if both are pressed
		if ( bFire1 )
		{
			self.FireProjectile( "UT/fx/Flak/Flash.kfx", 6.656f-0.5f, 29.69f, -1.9456f-0.75f );
			array<kStr> chunks(2);
			chunks[0] = chunks[1] = "UT/fx/Flak/Chunk";
			chunks[0] += '1';
			chunks[1] += '2';
			if ( UDamage() )
			{
				chunks[0] += "_Amp";
				chunks[1] += "_Amp";
			}
			chunks[0] += ".kfx";
			chunks[1] += ".kfx";
			for ( int i=0; i<8; ++i )
			{
				kVec3 dir = kVec3( 0,1,0 );
				if ( i < 3 ) dir.Randomize( FlakSpread / 2 );
				else         dir.Randomize( FlakSpread );
				kVec3 offset = kVec3( 9, 25, -7 );
				float speedRand = Math::RandFloat();
				offset += dir * kVec3( 30, 4 * speedRand - 2, 30 );
				dir = dir * OwnerP().Rotation();
				SpawnProj( i < 4 ? chunks[0] : chunks[1], offset, dir,
					dir * (3000 + 100*speedRand) * GAME_DELTA_TIME );
			}
			self.PlaySound( "U1/sounds/Flak/Shot.ksnd" );
			PlayAnim( anim_Flak_Fire );
		}
		else
		{
			self.FireProjectile( "UT/fx/Flak/Flash_Alt.kfx", 6.656f-0.5f, 29.69f, -1.9456f-0.75f );
			kVec3 dir = kVec3( 0,1,0 ) * OwnerP().Rotation();
			dir.z += 0.1f;
			kStr slug = "UT/fx/Flak/Slug";
			if ( UDamage() ) slug += "_Amp";
			SpawnProj( slug + ".kfx", 9, 25, -9, ToQuat(dir) );
			self.PlaySound( "U1/sounds/Flak/Shot_Alt.ksnd" );
			PlayAnim( anim_Flak_AltFire );
		}

		self.RunFxEvent( "GunFire" );
		OwnerP().LoudNoiseAlert();
		recoilRoll = 0.5f + 0.5f * Math::RandFloat();
		UseAmmo( 1 );
	}
}
