/*
   usaar33 is a wiener

   now watch as I turn this trash fire into a better weapon
*/
Class OLSMPAmmo : Ammo
{
	override bool TryPickup( in out Actor toucher )
	{
		if ( !sting_olsmp ) return false;	// not allowed
		return Super.TryPickup(toucher);
	}
	override void Tick()
	{
		Super.Tick();
		if ( sting_olsmp ) return;
		if ( !Owner )
		{
			let r = Spawn("CellPack",pos,ALLOW_REPLACE);
			r.spawnangle = spawnangle;
			r.spawnpoint = spawnpoint;
			r.angle = angle;
			r.pitch = pitch;
			r.roll = roll;
			r.special = special;
			r.args[0] = args[0];
			r.args[1] = args[1];
			r.args[2] = args[2];
			r.args[3] = args[3];
			r.args[4] = args[4];
			r.ChangeTid(tid);
			r.SpawnFlags = SpawnFlags&~MTF_SECRET;
			r.HandleSpawnFlags();
			r.SpawnFlags = SpawnFlags;
			r.bCountSecret = SpawnFlags&MTF_SECRET;
			r.vel = vel;
			r.master = master;
			r.target = target;
			r.tracer = tracer;
			r.bDropped = bDropped;
			r.bNeverRespawn = bNeverRespawn;
		}
		else Owner.RemoveInventory(self);
		Destroy();
	}
	Default
	{
		Tag "$T_OLSMPAMMO";
		Inventory.Icon "I_OLSMP";
		Inventory.PickupMessage "$I_OLSMPAMMO";
		Inventory.Amount 100;
		Inventory.MaxAmount 300;
		Ammo.BackpackAmount 0;
		Ammo.BackpackMaxAmount 900;
		Ammo.DropAmount 100;
	}
	States
	{
	Spawn:
		UCLP A -1;
		Stop;
	}
}

Class OLSMPMag : EnforcerMag
{
}

Class OLSMP : UnrealWeapon
{
	int ClipCount;
	double AltAccuracy;
	bool ClipOut;

	property ClipCount : ClipCount;

	override int, int, bool, bool GetClipAmount()
	{
		return ClipOut?-1:ClipCount, -1, (ClipCount<35), false;
	}
	override bool TryPickup( in out Actor toucher )
	{
		if ( !sting_olsmp ) return false;	// not allowed
		return Super.TryPickup(toucher);
	}
	override void Tick()
	{
		Super.Tick();
		if ( sting_olsmp ) return;
		if ( !Owner )
		{
			let r = Spawn("BFG9000",pos,ALLOW_REPLACE);
			r.spawnangle = spawnangle;
			r.spawnpoint = spawnpoint;
			r.angle = angle;
			r.pitch = pitch;
			r.roll = roll;
			r.special = special;
			r.args[0] = args[0];
			r.args[1] = args[1];
			r.args[2] = args[2];
			r.args[3] = args[3];
			r.args[4] = args[4];
			r.ChangeTid(tid);
			r.SpawnFlags = SpawnFlags&~MTF_SECRET;
			r.HandleSpawnFlags();
			r.SpawnFlags = SpawnFlags;
			r.bCountSecret = SpawnFlags&MTF_SECRET;
			r.vel = vel;
			r.master = master;
			r.target = target;
			r.tracer = tracer;
			r.bDropped = bDropped;
			r.bNeverRespawn = bNeverRespawn;
		}
		else Owner.RemoveInventory(self);
		Destroy();
	}
	override void PlayUpSound( Actor origin )
	{
		origin.A_StartSound(upsound,CHAN_WEAPON,volume:Dampener.Active(origin)?.1:1.,pitch:0.8);
	}
	action void A_OLSMPRefire( statelabel flash = null, bool slave = false )
	{
		Weapon weap = Weapon(invoker);
		if ( !weap || !player ) return;
		if ( invoker.altaccuracy < 0.2 ) invoker.altaccuracy += 0.01;
		if ( invoker.clipcount < 35 ) A_StartSound("automag/click",CHAN_WEAPONMISC,CHANF_OVERLAP,!Dampener.Active(self)?1.:.35,pitch:1.6);
		if ( invoker.clipcount <= 0 )
		{
			A_ClearRefire();
			return;
		}
		A_Refire(flash);
	}
	action void A_OLSMPFire( bool alt = false )
	{
		Weapon weap = Weapon(invoker);
		if ( !weap ) return;
		if ( invoker.clipcount <= 0 ) return;
		invoker.clipcount--;
		invoker.FireEffect();
		UTMainHandler.DoFlash(self,Color(32,255,128,0),1);
		A_StartSound("automag/fire",CHAN_WEAPON,CHANF_OVERLAP,!Dampener.Active(self)?1.:.2,pitch:FRandom[Automag](1.2,1.8)*(alt?2.5:1.));
		if ( !Dampener.Active(self) ) A_AlertMonsters();
		A_QuakeEx(1,1,1,8,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.15);
		A_Overlay(-2,"MuzzleFlash");
		A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
		A_OverlayRenderstyle(-2,STYLE_Add);
		Vector3 x, y, z, x2, y2, z2;
		[x, y, z] = dt_Utility.GetAxes(angle,pitch,roll);
		if ( alt )
		{
			vel -= x*(player.onground?2.:0.8);
			vel.z += (player.onground?.3:.08);
		}
		else
		{
			vel -= x*(player.onground?2.2:1.);
			vel.z += (player.onground?.5:.15);
		}
		Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x);
		origin = level.Vec3Offset(origin,-z-y*4);
		double a = FRandom[Automag](0,360), s = FRandom[Automag](0,alt?(0.05+invoker.altaccuracy):0.05);
		[x2, y2, z2] = dt_Utility.GetAxes(angle,BulletSlope(),roll);
		Vector3 dir = dt_Utility.ConeSpread(x2,y2,z2,a,s);
		FLineTraceData d;
		LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
		UTBulletTrail.DoTrail(self,origin,dir,10000,alt?6:4);
		if ( d.HitType == TRACE_HitActor )
		{
			int dmg = 17;
			dmg = d.HitActor.DamageMobj(invoker,self,dmg,'shot',DMG_USEANGLE|DMG_THRUSTLESS,atan2(d.HitDir.y,d.HitDir.x));
			double mm = 3000;
			if ( FRandom[Automag](0,1) < 0.2 ) mm *= 5;
			UTMainHandler.DoKnockback(d.HitActor,d.HitDir,mm);
			if ( d.HitActor.bNOBLOOD )
			{
				let p = Spawn("BulletImpact",d.HitLocation);
				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 )
			{
				if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal;
				else hitnormal = d.HitSector.floorplane.Normal;
			}
			else if ( d.HitType == TRACE_HitCeiling )
			{
				if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal;
				else 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.angle = atan2(hitnormal.y,hitnormal.x);
			p.pitch = asin(-hitnormal.z);
			if ( d.HitLine ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation);
		}
		for ( int i=0; i<3; i++ )
		{
			let s = Spawn("UTViewSmoke",origin);
			UTViewSmoke(s).ofs = (10,-4,-1);
			s.target = self;
			s.alpha *= 0.5;
		}
		origin = level.Vec3Offset(origin,x*8-y*6-z*2);
		let c = Spawn("UCasing",origin);
		c.angle = angle;
		c.pitch = pitch;
		c.vel = x*FRandom[Junk](-1.5,1.5)-y*FRandom[Junk](2,4)+z*FRandom[Junk](2,3);
	}
	override bool CheckAmmo( int fireMode, bool autoSwitch, bool requireAmmo, int ammocount )
	{
		if ( ClipCount > 0 ) return true;
		return Super.CheckAmmo(firemode,autoswitch,requireammo,ammocount);
	}
	Default
	{
		Tag "$T_OLSMP";
		Inventory.PickupMessage "$I_OLSMP";
		Weapon.UpSound "automag/select";
		Weapon.SlotNumber 0;
		Weapon.SelectionOrder 800;
		Weapon.SlotPriority 0.95;
		Weapon.AmmoType "OLSMPAmmo";
		Weapon.AmmoUse 1;
		Weapon.AmmoType2 "OLSMPAmmo";
		Weapon.AmmoUse2 1;
		Weapon.AmmoGive 100;
		Weapon.Kickback 320;
		UTWeapon.DropAmmo 50;
		OLSMP.ClipCount 100;
		+UNREALWEAPON.NOFIRSTGIVE;
		+INVENTORY.ALWAYSPICKUP;
	}
	States
	{
	Spawn:
		AUTP A -1;
		Stop;
		AUTP B -1;
		Stop;
	Select:
		AUTS A 1 A_Raise(int.max);
	Ready:
		AUTS ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 A_WeaponReady(WRF_NOFIRE);
		AUS2 ABCD 1 A_WeaponReady(WRF_NOFIRE);
	Idle:
		AUTI A 0 A_Overlay(-9999,"Dummy");
		AUTI AB 30;
		AUTI A 0 A_Jump(50,"Twiddle");
		Goto Idle+1;
	Twiddle:
		AUTT ABCDEFGHIJKLMNOPQRSTUVWXY 2;
		Goto Idle+1;
	Dummy:
		TNT1 A 1
		{
			A_CheckReload();
			if ( (invoker.clipcount <= 0) && (invoker.Ammo1.Amount > 0) ) A_Overlay(PSP_WEAPON,"Reload");
			else if ( invoker.clipcount < min(invoker.default.clipcount,invoker.Ammo1.Amount) ) A_WeaponReady(WRF_ALLOWRELOAD);
			else A_WeaponReady();
		}
		Wait;
	Fire:
		AUTF A 1 A_Overlay(-9999,null);
		AUTF BCD 1;
	Hold:
		AUTF E 1 A_OLSMPFire();
		AUTF F 1;
		AUTF G 0 A_OLSMPRefire(1);
		Goto Release1;
		AUTF G 1;
		AUTF H 1 A_OLSMPFire();
		AUTF I 1;
		AUTF J 0 A_OLSMPRefire(1);
		Goto Release2;
		AUTF J 1;
		AUTF K 1 A_OLSMPFire();
		AUTF L 1;
		AUTF M 0 A_OLSMPRefire(1);
		Goto Release3;
		AUTF M 1;
		Goto Hold;
	Release1:
		AUTF G 1;
		Goto Release;
	Release2:
		AUTF J 1;
		Goto Release;
	Release3:
		AUTF M 1;
		Goto Release;
	Release:
		AUTF NOPQRST 1;
		AUTI A 0;
		Goto Idle;
	AltFire:
		AUTF A 1 A_Overlay(-9999,null);
		AUTF BCD 1;
	AltHold:
		AUTF E 1 A_OLSMPFire(true);
		AUTF H 0 A_OLSMPRefire(1);
		Goto AltRelease1;
		AUTF H 1 A_OLSMPFire(true);
		AUTF K 0 A_OLSMPRefire(1);
		Goto AltRelease2;
		AUTF K 1 A_OLSMPFire(true);
		AUTF E 0 A_OLSMPRefire("AltHold");
		Goto AltRelease3;
	AltRelease1:
		AUTF FG 1;
		Goto Release;
	AltRelease2:
		AUTF IJ 1;
		Goto Release;
	AltRelease3:
		AUTF LM 1;
		Goto Release;
	Reload:
		AUTR A 0 A_JumpIf(invoker.clipcount>=min(invoker.default.clipcount,invoker.Ammo1.Amount),"Idle");
		AUTR A 0
		{
			invoker.clipout = true;
			A_Overlay(-9999,null);
			A_WeaponOffset(0,32);	// fix sudden psprite lowering
			A_StartSound("automag/click",CHAN_WEAPONMISC,volume:!Dampener.Active(self)?1.:.1,pitch:0.8);
		}
		AUTR ABCDEFGHIJKLMNOPQRSTUVWXY 1;
		AUTD ABCD 1;
		AUTD E 30
		{
			invoker.clipout = false;
			let aadd = min(invoker.Ammo1.Amount,invoker.default.clipcount-invoker.clipcount);
			invoker.clipcount += aadd;
			if ( !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true) )
				invoker.Ammo1.Amount -= aadd;
			A_StartSound("automag/reload",CHAN_WEAPONMISC,volume:!Dampener.Active(self)?1.:.1,pitch:0.8);
			if ( self is 'UTPlayer' )
				UTPlayer(self).PlayReloading();
			Vector3 x, y, z, origin;
			[x,y,z] = dt_Utility.GetAxes(angle,pitch,roll);
			origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),x*4.-y*4.-z*18.);
			let c = Spawn("OLSMPMag",origin);
			c.angle = angle;
			c.pitch = pitch;
			c.vel = vel*.5+x*FRandom[Junk](-.5,.5)+y*FRandom[Junk](-.5,.5)-z*FRandom[Junk](1,2);
		}
		AUTS A 0 A_StartSound("automag/select",CHAN_WEAPON,volume:!Dampener.Active(self)?1.:.1,pitch:0.8);
		Goto Ready;
	Deselect:
		AUTD A 1 A_Overlay(-9999,null);
		AUTD BCD 1;
		AUTD E 1 A_Lower(int.max);
		Wait;
	MuzzleFlash:
		TNT1 A 0 A_Jump(256,1,2,3,4,5,6,7,8,9);
		AMUZ A 2 Bright
		{
			let l = Spawn("EnforcerLight",pos);
			l.target = self;
		}
		Stop;
		AMUZ B 2 Bright
		{
			let l = Spawn("EnforcerLight",pos);
			l.target = self;
		}
		Stop;
		AMUZ C 2 Bright
		{
			let l = Spawn("EnforcerLight",pos);
			l.target = self;
		}
		Stop;
		AMUZ D 2 Bright
		{
			let l = Spawn("EnforcerLight",pos);
			l.target = self;
		}
		Stop;
		AMUZ E 2 Bright
		{
			let l = Spawn("EnforcerLight",pos);
			l.target = self;
		}
		Stop;
		AMUZ F 2 Bright
		{
			let l = Spawn("EnforcerLight",pos);
			l.target = self;
		}
		Stop;
		AMUZ G 2 Bright
		{
			let l = Spawn("EnforcerLight",pos);
			l.target = self;
		}
		Stop;
		AMUZ H 2 Bright
		{
			let l = Spawn("EnforcerLight",pos);
			l.target = self;
		}
		Stop;
		AMUZ I 2 Bright
		{
			let l = Spawn("EnforcerLight",pos);
			l.target = self;
		}
		Stop;
	}
}
