Class Tier6Ammo : RandomSpawner2 replaces Cell
{
	Default
	{
		DropItem "EClip", 255, 1;
		DropItem "RifleAmmo2", 255, 1;
	}
}
Class Tier6Ammo2 : RandomSpawner2 replaces CellPack
{
	Default
	{
		DropItem "MiniAmmo", 255, 1;
		DropItem "RifleAmmo", 255, 1;
	}
}

Class Tier6Weapon : RandomSpawner2 replaces PlasmaRifle
{
	Default
	{
		DropItem "Minigun", 255, 1;
		DropItem "SniperRifle", 255, 1;
	}
}

Class MiniAmmo : Ammo
{
	Default
	{
		Tag "Large Bullets";
		Inventory.PickupMessage "You picked up 50 bullets.";
		Inventory.Amount 50;
		Inventory.MaxAmount 199;
		Ammo.BackpackAmount 100;
		Ammo.BackpackMaxAmount 199;
		Ammo.DropAmount 20;
	}
	States
	{
	Spawn:
		MAMO A -1;
		Stop;
	}
}

Class MinigunLight : EnforcerLight
{
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		args[LIGHT_INTENSITY] = Random[Minigun](120,180);
	}
}

Class MinigunTracer : Actor
{
	Vector3 dest;
	Default
	{
		RenderStyle "Add";
		Radius 0.1;
		Height 0;
		+NOCLIP;
		+NOGRAVITY;
		+DONTSPLASH;
	}
	override void Tick()
	{
		Super.Tick();
		Vector3 dir = level.Vec3Diff(pos,dest);
		if ( dir.length() < 200 )
		{
			Destroy();
			return;
		}
		dir = dir.unit();
		SetOrigin(Vec3Offset(dir.x*200,dir.y*200,dir.z*200),true);
		A_SetAngle(atan2(dir.y,dir.x),SPF_INTERPOLATE);
		A_SetPitch(asin(-dir.z),SPF_INTERPOLATE);
		A_SetRoll(roll+60,SPF_INTERPOLATE);
	}
	States
	{
	Spawn:
		TRAC A -1 Bright;
		Stop;
	}
}

Class Minigun : UTWeapon
{
	int bcnt;

	action void A_FireBullet( bool alt = false )
	{
		Weapon weap = Weapon(invoker);
		if ( !weap ) return;
		if ( weap.Ammo1.Amount <= 0 ) return;
		A_Overlay(-2,"MuzzleFlash",true);
		A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
		A_OverlayRenderstyle(-2,STYLE_Add);
		if ( alt ) invoker.bcnt = min(invoker.bcnt,3);
		if ( invoker.bcnt-- > 0 ) return;
		invoker.bcnt = alt?3:5;
		if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
		invoker.FireEffect();
		UTMainHandler.DoFlash(self,Color(32,255,255,0),1);
		A_AlertMonsters();
		if ( alt ) A_QuakeEx(3,3,3,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.12);
		else A_QuakeEx(2,2,2,5,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.08);
		let l = Spawn("MinigunLight",pos);
		l.target = self;
		if ( !alt ) MinigunLight(l).cnt--;
		Vector3 x, y, z, x2, y2, z2;
		[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
		Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+y*4.0-z*6.0;
		double a = FRandom[Minigun](0,360), s = FRandom[Minigun](0,alt?0.05:0.02);
		[x2, y2, z2] = Matrix4.GetAxes(BulletSlope(),angle,roll);
		Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
		FLineTraceData d;
		LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
		if ( d.HitType == TRACE_HitActor )
		{
			int dmg = Random[Minigun](9,15); // fun fact: the Minigun is one of the few weapons that has actual RNG damage in UT (and it's exactly this damage)
			dmg = d.HitActor.DamageMobj(invoker,self,dmg,'shot');
			if ( d.HitActor.bNOBLOOD )
			{
				let p = Spawn("BulletImpact",d.HitLocation);
				p.scale *= 0.75;
				p.angle = atan2(d.HitDir.y,d.HitDir.x)+180;
				p.pitch = asin(d.HitDir.z);
			}
			else
			{
				d.HitActor.TraceBleed(dmg,self);
				d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
			}
		}
		else if ( d.HitType != TRACE_HitNone )
		{
			Vector3 hitnormal = -d.HitDir;
			if ( d.HitType == TRACE_HitFloor ) hitnormal = d.HitSector.floorplane.Normal;
			else if ( d.HitType == TRACE_HitCeiling ) hitnormal = d.HitSector.ceilingplane.Normal;
			else if ( d.HitType == TRACE_HitWall )
			{
				hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
				if ( !d.LineSide ) hitnormal *= -1;
			}
			let p = Spawn("BulletImpact",d.HitLocation+hitnormal*0.01);
			p.scale *= 0.75;
			p.angle = atan2(hitnormal.y,hitnormal.x);
			p.pitch = asin(-hitnormal.z);
			if ( d.HitLine ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation);
		}
		if ( !Random[Minigun](0,1) )
		{
			let t = Spawn("MinigunTracer",origin+x*20.0);
			t.angle = atan2(dir.y,dir.x);
			t.pitch = asin(-dir.z);
			MinigunTracer(t).dest = d.HitLocation;
		}
		origin += x*8.0+y*4.0-z*2.0;
		let c = Spawn("UTCasing",origin);
		c.vel = x*FRandom[Junk](-2,2)+y*FRandom[Junk](3,6)+z*FRandom[Junk](3,5);
		c.Scale *= 0.5;
	}

	action void A_MinigunRefire( statelabel flash = null )
	{
		Weapon weap = Weapon(invoker);
		if ( !weap || !player ) return;
		if ( weap.Ammo1.Amount <= 0 )
		{
			A_ClearRefire();
			player.setpsprite(PSP_WEAPON,weap.FindState("Unwind"));
			return;
		}
		A_Refire(flash);
	}

	Default
	{
		Tag "Minigun";
		Obituary "%k's Minigun turned %o into a leaky piece of meat.";
		Inventory.PickupMessage "You got the Minigun.";
		Weapon.UpSound "minigun/select";
		Weapon.SlotNumber 7;
		Weapon.SelectionOrder 3;
		Weapon.AmmoType "MiniAmmo";
		Weapon.AmmoUse 1;
		Weapon.AmmoType2 "MiniAmmo";
		Weapon.AmmoUse2 1;
		Weapon.AmmoGive 50;
	}
	States
	{
	Spawn:
		MGNP A -1;
		Stop;
		MGNP B -1;
		Stop;
	Select:
		MGNS A 1 A_Raise(int.max);
		Wait;
	Ready:
		MGNS ABCDEFGHIJKLMNOPQRST 1;
	Idle:
		MGNI ABCDEFGHIJKLMNOPQRS 5
		{
			A_CheckReload();
			A_WeaponReady();
		}
		Loop;
	Fire:
	AltFire:
		MGNI A 3 { invoker.bcnt = 5; }
	Hold:
		MGNF A 1
		{
			A_PlaySound("minigun/fire",CHAN_WEAPON,1.0,true);
			A_FireBullet();
		}
		MGNF B 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF B 1 A_FireBullet();
		MGNF C 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF C 1 A_FireBullet();
		MGNF D 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF D 1 A_FireBullet();
		MGNF E 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF E 1 A_FireBullet();
		MGNF F 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF F 1 A_FireBullet();
		MGNF G 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF G 1 A_FireBullet();
		MGNF H 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF H 1 A_FireBullet();
		MGNF I 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF I 1 A_FireBullet();
		MGNF J 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF J 1 A_FireBullet();
		MGNF K 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF K 1 A_FireBullet();
		MGNF L 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF L 1 A_FireBullet();
		MGNF M 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF M 1 A_FireBullet();
		MGNF N 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF N 1 A_FireBullet();
		MGNF O 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF O 1 A_FireBullet();
		MGNF P 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF P 1 A_FireBullet();
		MGNF Q 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF Q 1 A_FireBullet();
		MGNF R 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF R 1 A_FireBullet();
		MGNF S 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF S 1 A_FireBullet();
		MGNF A 0
		{
			if ( invoker.bAltFire ) A_MinigunRefire(1);
			else A_MinigunRefire("Hold");
		}
		Goto Unwind;
	AltFire2:
		MGNF A 1 A_FireBullet();
		MGNF B 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF B 1 A_FireBullet();
		MGNF C 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF C 1 A_FireBullet();
		MGNF D 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF D 1 A_FireBullet();
		MGNF E 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF E 1 A_FireBullet();
		MGNF F 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF F 1 A_FireBullet();
		MGNF G 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF G 1 A_FireBullet();
		MGNF H 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF H 1 A_FireBullet();
		MGNF I 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF I 1 A_FireBullet();
		MGNF J 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF J 1 A_FireBullet();
		MGNF K 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF K 1 A_FireBullet();
		MGNF L 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF L 1 A_FireBullet();
		MGNF M 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF M 1 A_FireBullet();
		MGNF N 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF N 1 A_FireBullet();
		MGNF O 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF O 1 A_FireBullet();
		MGNF P 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF P 1 A_FireBullet();
		MGNF Q 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF Q 1 A_FireBullet();
		MGNF R 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF R 1 A_FireBullet();
		MGNF S 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF S 1 A_FireBullet();
		MGNF A 0 A_MinigunRefire(1);
		Goto Unwind;
	AltHold:
		MGNF A 1
		{
			A_PlaySound("minigun/altfire",CHAN_WEAPON,1.0,true);
			A_FireBullet(true);
		}
		MGNF D 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF D 1 A_FireBullet(true);
		MGNF G 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF G 1 A_FireBullet(true);
		MGNF J 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF J 1 A_FireBullet(true);
		MGNF M 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF M 1 A_FireBullet(true);
		MGNF P 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF P 1 A_FireBullet(true);
		MGNF S 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF S 1 A_FireBullet(true);
		MGNF C 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF C 1 A_FireBullet(true);
		MGNF F 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF F 1 A_FireBullet(true);
		MGNF I 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF I 1 A_FireBullet(true);
		MGNF L 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF L 1 A_FireBullet(true);
		MGNF O 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF O 1 A_FireBullet(true);
		MGNF R 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF R 1 A_FireBullet(true);
		MGNF B 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF B 1 A_FireBullet(true);
		MGNF E 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF E 1 A_FireBullet(true);
		MGNF H 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF H 1 A_FireBullet(true);
		MGNF K 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF K 1 A_FireBullet(true);
		MGNF N 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF N 1 A_FireBullet(true);
		MGNF Q 0 A_MinigunRefire(1);
		Goto Unwind;
		MGNF Q 1 A_FireBullet(true);
		MGNF A 0 A_MinigunRefire("AltHold");
		Goto Unwind;
	Unwind:
		MGNU A 0 A_PlaySound("minigun/unwind",CHAN_WEAPON);
		MGNU ABCDEFGHIJKLMNOPQRSTUVWXYZ 1;
		MGU2 ABCDEFGHIJKLM 1;
		Goto Idle;
	Deselect:
		MGND A 2 A_StopSound(CHAN_WEAPON);
		MGND BCDEFGHIJ 2;
		MGND J 1 A_Lower(int.max);
		Wait;
	MuzzleFlash:
		TNT1 A 0 A_Jump(256,1,2,3,4,5,6,7,8,9);
		Stop;
		MMUZ A 2 Bright;
		Stop;
		MMUZ B 2 Bright;
		Stop;
		MMUZ C 2 Bright;
		Stop;
		MMUZ D 2 Bright;
		Stop;
		MMUZ E 2 Bright;
		Stop;
		MMUZ F 2 Bright;
		Stop;
		MMUZ G 2 Bright;
		Stop;
		MMUZ H 2 Bright;
		Stop;
		MMUZ I 2 Bright;
		Stop;
	Dummy:
		MMUZ ABCDEFGHI -1;
		Stop;
	}
}
