Class GHAGPistolOverlay : Inventory
{
	Default
	{
		Inventory.MaxAmount 4;
		Inventory.pickupMessage "Found an extra pistol!";
	}
	
	override void beginplay()
	{
		super.beginPlay();
		
		if (GameInfo.GameType == 2) Self.MaxAmount = 2;
	}
}
Class GHAGPistol : GHAGWeapon
{
	Default
	{
		Weapon.AmmoUse1 1;
		Weapon.SlotNumber 2;
		Weapon.AmmoType1 "Clip";
		Weapon.AmmoType2 "Clip";
		Tag "9mm Pistol";
	}
	
	Array<Actor> targets;
	
	override void DoEffect()
	{
		players[consoleplayer].WeaponState |= WF_WEAPONBOBBING;
		super.DoEffect();
	}
	
	override void BeginPlay()
	{
		Super.BeginPlay();
	}
	
	override void tick()
	{
		Super.Tick();
		
		setTag(Cvar.findCvar("GHAGPistolName").getString());
	}
	
	int getPistolCount()
	{
		return owner.countInv('GHAGPistolOverlay') * (owner.CountInv("PowerWeaponLevel2") >= 1 ? 2 : 1);
	}

	states
	{
		Ready:
			HAND A 1 {
				Invoker.AmmoUse2 = invoker.getPistolCount();
				A_WeaponReady(WRF_ALLOWUSER1);
				A_NullTargets();
			}
			Loop;
		Deselect:
			HAND A 1 {
				A_NullTargets();
				A_GHAGLower();
				A_OverlayPistols();
			}
			Loop;
		Select:
			HAND A 1 {
				A_GHAGRaise();
				A_OverlayPistols();
			}
			Loop;
		Fire:
			HAND AB 3 {
				A_SetTics(GHAGGardevoir(self).GetTicModifier(3, true));
			}
			HAND C 3 {
				A_SetTics(GHAGGardevoir(self).GetTicModifier(3));
			}
			HAND D 3 {
				A_FireBullets(GHAGGardevoir(self).GetAccuracyModifier(4.3), GHAGGardevoir(self).GetAccuracyModifier(4.3), 1, 8, "BulletPuff");
				A_StartSound("weapons/pistol", CHAN_WEAPON);
				A_SetTics(GHAGGardevoir(self).GetTicModifier(3));
				A_OverlayPistols(true);
			}
			HAND EF 1 A_SetTics(GHAGGardevoir(self).GetTicModifier(1, true));
			HAND G 5
			{
				A_SetTics(GHAGGardevoir(self).GetTicModifier(5, true));
				A_ReFire();
			}
			Goto Ready;
		AltFire:
			HAND A 1 {
				if(A_AutoTarget()) return resolveState('AltFire.Shoot'); //A_Jump wouldn't work?
				return resolveState(null);
			}
			HAND A 3 A_StartSound("weapons/dryfire", CHAN_AUTO);
			goto Ready;
		AltFire.Shoot:
			HAND BC 3 A_SetTics(GHAGGardevoir(self).GetTicModifier(3) * 2);
			HAND D 3
			{
				A_SetTics(GHAGGardevoir(self).GetTicModifier(3) * 2);
				A_FireTargets();
			}
			TNT1 A 0
			{
				A_Refire();
			}
			HAND EFG 1;
			TNT1 A 0 A_NullTargets();
			Goto Ready;
		Fire.Overlay:
			PIST B 2 Bright A_SetTics(GHAGGardevoir(self).GetTicModifier(2));
			PIST A 100;
			stop;
		AltFire.Overlay:
			PIST B 2 Bright;
		Select.Overlay:
			PIST A 1;
			loop;
		Deselect.Overlay:
			PIST A 1;
			loop;
		Ready.Overlay:
			PIST A 1;
			loop;
	}
	
	Action void A_OverlayPistols(bool RollForFire = false, bool AltFire = false)
	{
		int rng = random(0, (Min(invoker.getPistolCount() - 1, 3)));
		if (invoker.getPistolCount() > 1 && rng == invoker.lastRNG) 
		{
			while (rng == invoker.lastRNG)
			{
				rng = random(0, (invoker.getPistolCount() - 1));
			}
		}
		
		invoker.lastRNG = rng;
		
		let gardie = GHAGGardevoir(invoker.owner);
		if (gardie.FloatGuns.Size())
		{
			if (RollForFire)
			{
				gardie.FloatGuns[rng].SetStateLabel('PistolFire');
			}
		}
	}
	
	Action bool A_AutoTarget()
	{
		let gardie = GHAGGardevoir(self);
		invoker.targets.clear();
		
		if (!countInv("Clip"))
		{
			if (!GetCVar("sv_infiniteammo")) return false;
		}
		
		ThinkerIterator it = ThinkerIterator.Create("Actor");
		Actor mo;
		
		while ( (mo = Actor(it.Next ())) )
		{
			if (!mo.bIsMonster) continue;
			if (mo.health <= 0)continue;
			if (!mo.isVisible(self, true)) continue;
			if (invoker.targets.find(mo) != invoker.targets.size()) continue;
			
			double difference = AbsAngle(self.angle, angleTo(mo));
			
			if (difference >= 45 + (135 * GHAGGardevoir(self).getRageModifier())) continue;
			
			if (invoker.targets.size() != 0)
			{
				for (int i = 0; i < invoker.getPistolCount(); ++i)
				{
					if (i >= invoker.targets.size()) 
					{
						invoker.targets.push(mo);
						break;
					}
					
					double distA = distance3D(invoker.targets[i]);
					double distB = distance3D(mo);
					
					if (distB <= distA)
					{
						invoker.targets.insert(i, mo);
						break;
					}
				}
			} 
			else 
			{
				invoker.targets.push(mo);
			}
			
			if (invoker.targets.Size() > 4) invoker.targets.resize(4);
		}
		
		if (invoker.targets.size() == 0) 
		{	
			A_NullTargets();
			return false;
		}
		
		return true;
	}
	
	Action void A_FireTargets()
	{
		let gardie = GHAGGardevoir(self);
	
		int prevIndex = 0;
		for (int i = 0; i < invoker.getPistolCount(); ++i)
		{
			let gun = GHAGFloatingGun(gardie.floatGuns[i]);
			if (i < invoker.targets.size()) {
				prevIndex = i;
			}
			gun.targetOverride = invoker.targets[prevIndex];
			gun.SetStateLabel('PistolFire');
			double pitch = GHAGFloatingGun.PitchTo(self, invoker.targets[prevIndex], 0.75);
			double accuracy = GHAGGardevoir(self).GetAccuracyModifier(4.3);
			LineAttack(angleTo(invoker.targets[prevIndex]) + random(Int(-accuracy), Int(accuracy)), 4096, pitch + random(Int(-accuracy), Int(accuracy)), 8, 'Melee', 'BulletPuff', LAF_ISMELEEATTACK);
			if (!GetCVar("sv_infiniteammo")) A_TakeInventory('Clip', 1);
			A_StartSound("weapons/pistol", CHAN_WEAPON);
		}
	}
	
	Action void A_NullTargets()
	{
		let gardie = GHAGGardevoir(self);
		
		if (!gardie.floatGuns.size()) return;
	
		for (int i = 0; i < invoker.getPistolCount(); ++i)
		{
			let gun = GHAGFloatingGun(gardie.floatGuns[i]);
			gun.A_NullTarget();
		}
	}
}