Class GHAGPlasmaOverlay : Inventory
{
	Default
	{
		Inventory.MaxAmount 4;
		Inventory.pickupMessage "Found an extra plasma rifle!";
	}
	
	override void beginplay()
	{
		super.beginPlay();
		
		if (GameInfo.GameType == 2) Self.MaxAmount = 2;
	}
}

Class GHAGPlasmaRifle : GHAGWeapon
{
	default {
		Weapon.SlotNumber 6;
		Tag "Generic Energy Weapon";
		Weapon.AmmoType1 "Cell";
		Weapon.AmmoType2 "Cell";
		Weapon.AmmoUse1 1;
	}
	
	override void DoEffect()
	{
		players[consoleplayer].WeaponState |= WF_WEAPONBOBBING;
		super.DoEffect();
	}
	
	override void Tick()
	{
		Super.tick();
		
		setTag(Cvar.findCvar("GHAGPlasmaName").getString());
	}	
	
	int getPlasmaCount()
	{
		return owner.countInv('GHAGPlasmaOverlay') * (owner.CountInv("PowerWeaponLevel2") >= 1 ? 2 : 1);
	}
	
	States
	{
		Select:
			HAND A 1 {	
				A_GHAGRaise();
			}
			loop;
		Deselect:
			HAND A 1 {
				A_GHAGLower();
			}
			loop;
		Ready:
			HAND A 1 {
				A_WeaponReady(WRF_ALLOWUSER1);
				return resolveState(null);
			}
			loop;
		Fire:
			TNT1 A 0
			{
				for (int i = 0; i < invoker.getPlasmaCount(); ++i)
				{
					GHAGGardevoir(Invoker.owner).FloatGuns[i].SetStateLabel('PlasmaFire');
				}
			}
		FireLoop:
			HAND A 1 Bright {
				A_PsychicPlasma();
			}
			HAND BC 1 Bright;
			HAND DE 1 A_Refire('FireLoop');
			TNT1 A 0
			{
				for (int i = 0; i < invoker.getPlasmaCount(); ++i)
				{
					GHAGGardevoir(Invoker.owner).FloatGuns[i].SetStateLabel('PlasmaCooldown');
				}
			}
			Goto Ready;
		AltFire:
			TNT1 A 0
			{
				for (int i = 0; i < invoker.getPlasmaCount(); ++i)
				{
					GHAGGardevoir(Invoker.owner).FloatGuns[i].SetStateLabel('PlasmaFire');
				}
			}
			HAND A 20 {
				A_BFGSound();
				Invoker.AmmoUse2 = int(40 / invoker.getPlasmaCount());
				A_SetTics(int(20 / invoker.getPlasmaCount()));
			}
			HAND A 10;
			TNT1 A 0 A_FireBFG();
			HAND BCDE 2;
			HAND A 12;
			HAND A 20 A_Refire();
			TNT1 A 0
			{
				for (int i = 0; i < invoker.getPlasmaCount(); ++i)
				{
					GHAGGardevoir(Invoker.owner).FloatGuns[i].SetStateLabel('PlasmaCooldown');
				}
			}
			goto Ready;
	}
	
	Action void A_PsychicPlasma() 
	{
	
		bool consume = true;
		double odds = Min(0.75 * GHAGGardevoir(self).getRageModifier(), 0.75);
		double rng = random(0, 100) / 100.0;
		if (rng < odds) consume = false;
	
		for (int i = 0; i < invoker.getPlasmaCount(); ++i)
		{
			if (player == null)
			{
				return;
			}
			
			A_FirePlasmaBall(i, consume);
		}
	}
	
	Action Void A_FirePlasmaBall(int layer, bool _consume)
	{
		Vector2 pos = (0, 0);
	
		switch (layer)
		{
			Default:
			case 0:
				pos.x = 15;
				pos.y = 5;
				break;
			case 1:
				pos.x = -15;
				pos.y = 5;
				break;
			case 2:
				pos.x = -15;
				pos.y = 12;
				break;
			case 3:
				pos.x = 15;
				pos.y = 12;
				break;
		}
	
		A_FireAimedProjectile(layer > 0 ? "GHAGSilentPlasmaBall" : "PlasmaBall", _consume, pos.x, pos.y);
	}
	
	action Actor A_FireAimedProjectile(class<Actor> missiletype, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0)
	{
		let misl = A_FireProjectile(missiletype, 0, useammo, spawnofs_xy, spawnheight, flags, 0);
		if (misl)
		{
			FLineTraceData data;
			Vector3 end;
			bool hit = player.mo.LineTrace(angle, PLAYERMISSILERANGE, pitch, TRF_SOLIDACTORS|TRF_THRUHITSCAN, player.viewz-pos.z, data: data);
			if (hit && data.hitType != TRACE_CrossingPortal)
				end = (pos.xy, player.viewz) + (AngleToVector(angle,cos(pitch)), -sin(pitch)) * data.distance;
			else
				end = (pos.xy, player.viewz) + (AngleToVector(angle,cos(pitch)), -sin(pitch)) * PLAYERMISSILERANGE;
        
			Vector3 spawnPos = (pos.xy, misl.pos.z);
			if (spawnofs_xy)
				spawnPos.xy = pos.xy + AngleToVector(angle-90)*spawnofs_xy;
        
			Vector3 diff = end - spawnPos;
			double l = diff.Length();
			if (l > 0)
			{
				diff /= l;
				misl.angle = atan2(diff.y, diff.x);
				misl.pitch = -asin(diff.z);
				misl.vel = diff * misl.vel.Length();
			}
		}
    
		return misl;
	}
}

Class GHAGSilentPlasmaBall : PlasmaBall
{
	Default
	{
		SeeSound "";
	}
}