Class GHAGSuperRailgun : GHAGWeapon
{
	Default
	{
		Weapon.SlotNumber 7;
		Weapon.AmmoType1 "Shell";
		Weapon.AmmoType2 "Shell";
		Weapon.AmmoUse1 2;
		Weapon.AmmoUse2 2;
		Tag "PSY-BP12";
	}
	
	int getSSRGCount()
	{
		return owner.countInv('GHAGSuperRailgunOverlay') * (owner.CountInv("PowerWeaponLevel2") >= 1 ? 2 : 1);
	}
	
	override void Tick()
	{
		Super.tick();
		
		setTag(Cvar.findCvar("GHAGRailgunName").getString());
	}
	
	States
	{
		Spawn:
			SHTG A 1;
			Loop;
		Select:
			HAND A 1 A_GHAGRaise();
			Loop;
		Deselect:
			HAND A 1 A_GHAGLower();
			Loop;
		Ready:
			HAND A 1 A_WeaponReady(WRF_ALLOWUSER1);
			Loop;
		Fire:
			HAND A 3;
			HAND A 2
			{
				A_StartSound("weapons/sshotf", CHAN_WEAPON);
				A_SuperRailgun(false);
			}
			HAND BCDE 2;
			HAND A 7;
			TNT1 A 0 A_CheckReload();
			HAND AAAA 1;
			goto ready;
		AltFire:
			HAND A 3;
			HAND A 2
			{
				for (int i = 0; i < invoker.getSSRGCount(); ++ i) A_StartSound("weapons/sshotf", CHAN_WEAPON, CHANF_OVERLAP);
				A_SuperRailgun(true);
			}
			HAND BCDE 2;
			HAND A 7;
			TNT1 A 0 A_CheckReload();
			HAND AAAA 1;
			goto Ready;
	}
	
	Action void A_SuperRailgun(bool _altFire)
	{
		int count = invoker.getSSRGCount();
		if (!_altFire)
		{
			int rng = random(0, count - 1);
			FireRailBeam(max(0, rng));
		}
		else
		{
			for (int i = 0; i < count; ++i)
			{
				FireRailBeam(i);
			}
		}
	}
	
	Action void FireRailBeam(int _selection)
	{
		int damage = int(random(25.0, 50.0) / 2.0);
		int depth = int(10 * GHAGGardevoir(self).getRageModifier()) + 1;
		
		let gun = GHAGGardevoir(self).FloatGuns[_selection];
		gun.SetStateLabel('RailgunFire');
		
		double distx = self.distance2D(gun) * (_selection % 2 == 0 ? 1 : -1);
		double disty = 7 + gun.pos.z - self.pos.z - 41 + (_selection >= 2 ? 3 : 0);
		
		FLineTraceData target;
		
		GHAGGardevoir(self).LineTrace(GHAGGardevoir(self).angle, 2048, GHAGGardevoir(self).pitch, 0, 41, 0, 0, target);
			
		FLineTraceData offset;
		GHAGGardevoir(self).LineTrace(GHAGGardevoir(self).angle, target.distance - 16, GHAGGardevoir(self).pitch, 0, 41, 0, 0, offset);
		
		for (int i = 0; i < 2; ++i)
		{
			let looker = GHAGChainRailMarker(Actor.spawn('GHAGChainRailMarker', offset.HitLocation));
			looker.depth = depth - 1;
			looker.chainDamage = damage;
		}
		
		int xModifier = (_selection % 2 == 0 ? 3 : -3);
		
		vector2 gunVector = AnglePitchBetween(target.hitlocation, gun.pos);
		if (gunVector.x < 0) gunVector.x += 360;
		double selfangle = self.angle;
		if (selfangle < 0) selfangle += 360;
		double offsetAngle = gunVector.x - selfangle;
		
		A_RailAttack(damage, Int(distx) - xModifier, true, "", "9933FF", RGF_EXPLICITANGLE | RGF_SILENT | RGF_NOPIERCING, 0, 'BulletPuff', offsetAngle, 0, 0, 0, 0, 1.0, "None", Int(disty));
		A_RailAttack(damage, Int(distx) + xModifier, false, "", "9933FF", RGF_EXPLICITANGLE | RGF_SILENT | RGF_NOPIERCING, 0, 'BulletPuff', offsetAngle, 0, 0, 0, 0, 1.0, "None", Int(disty));
	}
	
	static Vector2 AnglePitchBetween(Vector3 posA, Vector3 posB) {
		Vector3 delta = (posA.x - posB.x, posA.y - posB.y, posA.z - posB.z);
		double to_angle = atan2(delta.y, delta.x);
		double to_pitch = -(atan2(sqrt((delta.y * delta.y) + (delta.x * delta.x)), delta.z) - 90);
		return (to_angle, to_pitch);
	}
}

Class GHAGChainRailMarker : Actor
{
	Actor toIgnore;
	int depth;
	double chainDamage;
	
	Default
	{
		+SeekerMissile;
		+Friendly;
		+NoGravity;
		+NoBlockmap;
	}
	
	States
	{
		Spawn:
			TNT1 A 5 A_SetTics(random(5, 7));
		Attack:
			TNT1 A 1
			{
				if (invoker.depth > 0)
				{
					ThinkerIterator it = ThinkerIterator.Create("Actor");
					Actor mo;
					
					int limit = 2048;
					
					Array<Actor> targets;
					targets.clear();
		
					while ( (mo = Actor(it.Next ())) )
					{
						if (!mo.bIsMonster) continue;
						if (distance3D(mo) > 2048) continue;
						if (distance3D(mo) < 32) continue;
						if (!isVisible(mo, true)) continue;
						if (mo.bCorpse) continue;
						if (mo is 'GHAGGardevoir') continue;
						if (mo is 'GHAGChainRailMarker') continue;
						
						int distance = int(distance3D(mo));
						
						if (distance < limit)
						{
							limit = distance;
							targets.clear();
							targets.push(mo);
						} 
						else if (distance == limit)
						{
							targets.push(mo);
						}
						
					}
				
					if (targets.size() != 0)
					{
						self.target = targets[random(0, targets.size() - 1)];
						A_FaceTarget();
						FireRailBeam(invoker.depth, int(invoker.chainDamage), limit * 4);
					} 
				}
			}
			TNT1 A 0;
			stop;
	}
	
	Action void FireRailBeam(int _chain, int _damage, double _distance)
	{
		A_CustomRailgun(_damage, 0, "", "9933FF", RGF_EXPLICITANGLE | RGF_SILENT | RGF_NOPIERCING, 1, 0, 'BulletPuff', 0, 0, 0, 0, 0, 1.0, "None");
		
		let looker = GHAGChainRailMarker(Actor.spawn('GHAGChainRailMarker', self.target.pos));
		looker.depth = _chain - 1;
		looker.chainDamage = invoker.chainDamage;
	}
}

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