Class ASMDAmmo : Ammo
{
	Default
	{
		Tag "$T_ASMDAMMO";
		Inventory.Icon "I_ASMD";
		Inventory.PickupMessage "$I_ASMDAMMO";
		Inventory.Amount 10;
		Inventory.MaxAmount 50;
		Ammo.BackpackAmount 5;
		Ammo.BackpackMaxAmount 100;
		Ammo.DropAmount 5;
	}
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		tracer = Spawn("ASMDAmmoX",pos);
		tracer.angle = angle;
		tracer.target = self;
		tracer = Spawn("ASMDAmmoXX",pos);
		tracer.angle = angle;
		tracer.target = self;
	}
	States
	{
	Spawn:
		SHOA A -1;
		Stop;
	}
}

Class ASMDAmmoX : Actor
{
	Default
	{
		RenderStyle "Add";
		+NOGRAVITY;
		+NOCLIP;
		+DONTSPLASH;
		Radius 0.1;
		Height 0;
	}
	override void Tick()
	{
		Super.Tick();
		if ( !target )
		{
			Destroy();
			return;
		}
		Warp(target,flags:WARPF_COPYINTERPOLATION|WARPF_NOCHECKPOSITION);
		bInvisible = target.bInvisible||!target.InStateSequence(target.CurState,target.FindState("Spawn"));
	}
	States
	{
	Spawn:
		SHOA A -1 Bright;
		Stop;
	}
}

Class ASMDAmmoXX : ASMDAmmoX
{
	States
	{
	Spawn:
		SHOA A -1;
		Stop;
	}
}

Class ASMDAmmo2X : ASMDAmmoX
{
	States
	{
	Spawn:
		SHOA B -1 Bright;
		Stop;
	}
}

Class ASMDAmmo2 : ASMDAmmo
{
	Default
	{
		Tag "$T_ASMDAMMO2";
		Inventory.Icon "I_ASMD";
		Inventory.PickupMessage "$I_ASMDAMMO2";
		Inventory.Amount 5;
		Ammo.DropAmount 3;
	}
	override void PostBeginPlay()
	{
		Ammo.PostBeginPlay();
		tracer = Spawn("ASMDAmmo2X",pos);
		tracer.angle = angle;
		tracer.target = self;
	}
	States
	{
	Spawn:
		SHOA B -1;
		Stop;
	}
}

Class ASMDLight : EnforcerLight
{
	Default
	{
		Args 64,32,255,70;
	}
}

Class ASMDBeamRing : Actor
{
	Default
	{
		RenderStyle "Add";
		+NOGRAVITY;
		+NOCLIP;
		+DONTSPLASH;
		Radius 0.1;
		Height 0;
	}
	override void Tick()
	{
		Super.Tick();
		if ( isFrozen() ) return;
		A_FadeOut(0.05,0);
	}
	States
	{
	Spawn:
		RNGX ABCDEF 4 Bright;
		Stop;
	}
}
Class ASMDSBeamRing : ASMDBeamRing {}
Class ASMDBlastRing : ASMDBeamRing
{
	override void Tick()
	{
		Actor.Tick();
		if ( isFrozen() ) return;
		A_FadeOut(0.028,0);
	}
	States
	{
	Spawn:
		RNGX ABCDEF 7 Bright;
		Stop;
	}
}

Class ASMDRingTrail : Actor
{
	Default
	{
		RenderStyle "Add";
		+NOGRAVITY;
		+NOCLIP;
		+DONTSPLASH;
		+INTERPOLATEANGLES;
		Radius 0.1;
		Height 0;
	}
	override void Tick()
	{
		Super.Tick();
		if ( isFrozen() ) return;
		A_FadeOut(0.05,0);
	}
	States
	{
	Spawn:
		RNGX ABCDEF 4 Bright;
		Stop;
	}
}

Class ASMDBeamLight : PaletteLight
{
	Default
	{
		Tag "Blue2";
		Args 0,0,0,50;
		ReactionTime 30;
	}
}

Class ASMDSBeamLight : PaletteLight
{
	Default
	{
		Tag "Ampd";
		Args 0,0,0,50;
		ReactionTime 30;
	}
}

Class ASMDBlastLight : PaletteLight
{
	Default
	{
		Tag "Purple";
		ReactionTime 40;
		Args 0,0,0,300;
	}
}

Class ASMDSpark : Actor
{
	Default
	{
		RenderStyle "Add";
		Radius 2;
		Height 2;
		+NOBLOCKMAP;
		+NOGRAVITY;
		+MISSILE;
		+FORCEXYBILLBOARD;
		+THRUACTORS;
		+ROLLSPRITE;
		+NOTELEPORT;
		+DONTSPLASH;
		+CANBOUNCEWATER;
		-BOUNCEAUTOOFF;
		+NOFRICTION;
		BounceType "Hexen";
		BounceFactor 1.0;
		WallBounceFactor 1.0;
		Scale 0.1;
	}
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		roll = FRandom[ASMD](0,360);
	}
	States
	{
	Spawn:
		AFLA A 1 Bright
		{
			A_FadeOut(FRandom[ASMD](0.0,0.1));
			vel *= 0.98;
		}
		Wait;
	}
}

Class ViewASMDSpark : ShockSpark
{
	Vector3 ofs, vvel;

	override void PostBeginPlay()
	{
		Actor.PostBeginPlay();
		scale *= FRandom[Puff](0.4,0.9);
		alpha *= FRandom[Puff](0.5,2.0);
		roll = FRandom[ASMD](0,360);
	}

	override void Tick()
	{
		Actor.Tick();
		if ( !target || !target.player )
		{
			Destroy();
			return;
		}
		Vector3 x, y, z;
		[x, y, z] = dt_Utility.GetAxes(target.angle,target.pitch,target.roll);
		Vector3 origin = level.Vec3Offset(target.Vec2OffsetZ(0,0,target.player.viewz),x*ofs.x+y*ofs.y+z*ofs.z);
		SetOrigin(origin,true);
		bInvisible = (players[consoleplayer].camera != target);
		if ( isFrozen() ) return;
		ofs += vvel;
		vvel *= 0.9;
		scale *= 0.8;
		if ( scale.x <= 0.01 ) Destroy();
	}

	States
	{
	Spawn:
		AFLA A 1 Bright A_FadeOut(FRandom[ASMD](0.0,0.1));
		Wait;
	}
}

Class ASMDHitbox : ShockHitbox
{
	Default
	{
		Radius 6;
		Height 12;
	}
}

Class ASMDBall : Actor
{
	Actor b;
	double mult;
	double startangle, startpitch;

	override int SpecialMissileHit( Actor victim )
	{
		if ( victim is 'ASMDHitbox' ) return 1;
		return -1;
	}
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		b = Spawn("ASMDHitbox",pos);
		b.target = self;
		startpitch = pitch;
		startangle = angle;
	}
	action void A_BallExplode()
	{
		if ( bAMBUSH ) return;
		pitch = invoker.startpitch;
		angle = invoker.startangle;
		roll = 0;
		UTMainHandler.DoBlast(self,70,70000);
		int dmg = int(55*(1+invoker.mult));
		A_Explode(dmg,70);
		A_SprayDecal("ShockMarkBig",16);
		Actor r;
		if ( dmg > 60 )
		{
			SetStateLabel("AmpDeath");
			A_SetScale(0.7);
			let l = Spawn("ASMDSBeamLight",pos);
			l.Args[3] = 120;
			r = Spawn("ASMDSBeamRing",pos);
		}
		else
		{
			A_SetScale(1.3);
			let l = Spawn("ASMDBeamLight",pos);
			l.Args[3] = 120;
			r = Spawn("ASMDBeamRing",pos);
		}
		Vector3 HitNormal = dt_Utility.Vec3FromAngle(angle,pitch);
		if ( BlockingLine ) HitNormal = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit();
		else if ( BlockingFloor )
		{
			// find closest 3d floor for its normal
			F3DFloor ff = null;
			for ( int i=0; i<BlockingFloor.Get3DFloorCount(); i++ )
			{
				if ( !(BlockingFloor.Get3DFloor(i).top.ZAtPoint(pos.xy) ~== floorz) ) continue;
				ff = BlockingFloor.Get3DFloor(i);
				break;
			}
			if ( ff ) HitNormal = -ff.top.Normal;
			else HitNormal = BlockingFloor.floorplane.Normal;
			r.SetOrigin(r.Vec3Offset(0,0,2),false);
		}
		else if ( BlockingCeiling )
		{
			// find closest 3d floor for its normal
			F3DFloor ff = null;
			for ( int i=0; i<BlockingCeiling.Get3DFloorCount(); i++ )
			{
				if ( !(BlockingCeiling.Get3DFloor(i).bottom.ZAtPoint(pos.xy) ~== ceilingz) ) continue;
				ff = BlockingCeiling.Get3DFloor(i);
				break;
			}
			if ( ff ) HitNormal = -ff.bottom.Normal;
			else HitNormal = BlockingCeiling.ceilingplane.Normal;
		}
		r.angle = atan2(HitNormal.y,HitNormal.x);
		r.pitch = asin(-HitNormal.z);
		r.scale *= 1.5;
		A_StartSound("asmd/hit",CHAN_VOICE);
		A_StartSound("asmd/ball",CHAN_WEAPON,pitch:FRandom[ASMD](0.5,1.5));
		A_QuakeEx(4,4,4,30,0,200,"",QF_RELATIVE|QF_SCALEDOWN,falloff:70,rollIntensity:0.15);
		A_AlertMonsters();
		int numpt = Random[ASMD](50,100);
		for ( int i=0; i<numpt; i++ )
		{
			Vector3 pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](2,6);
			let s = Spawn("ASMDSpark",pos);
			s.vel = pvel;
		}
	}
	action void A_BallSpin()
	{
		for ( int i=0; i<6; i++ )
		{
			Vector3 x, y, z;
			[x,y,z] = dt_Utility.GetAxes(angle,pitch,roll);
			double a = FRandom[ASMD](0,360), s = FRandom[ASMD](0,0.15);
			Vector3 dir;
			switch (i)
			{
			case 0:
				dir = dt_Utility.ConeSpread(x,y,z,a,s);
				break;
			case 1:
				dir = dt_Utility.ConeSpread(y,x,z,a,s);
				break;
			case 2:
				dir = dt_Utility.ConeSpread(-x,y,z,a,s);
				break;
			case 3:
				dir = dt_Utility.ConeSpread(-y,x,z,a,s);
				break;
			case 4:
				dir = dt_Utility.ConeSpread(z,x,y,a,s);
				break;
			case 5:
				dir = dt_Utility.ConeSpread(-z,x,y,a,s);
				break;
			}
			let p = Spawn("ASMDSpark",level.Vec3Offset(pos,-vel));
			p.vel = vel*0.5+dir*FRandom[ASMD](1,3);
		}
		pitch += 7.12;
		angle += 5.25;
		roll += 9.96;
	}
	Default
	{
		Obituary "$O_ASMD";
		RenderStyle "Add";
		DamageType 'jolted';
		Radius 4;
		Height 4;
		Speed 20;
		PROJECTILE;
		+FORCEXYBILLBOARD;
		+SKYEXPLODE;
		+EXPLODEONWATER;
		+FORCERADIUSDMG;
		+NODAMAGETHRUST;
		+INTERPOLATEANGLES;
		+NOFRICTION;
	}
	States
	{
	Spawn:
		TAZB A 1 Bright A_BallSpin();
		Wait;
	Death:
		TNT1 A 0 A_BallExplode();
		AEXP ABCDEF 3 Bright;
		Stop;
	AmpDeath:
		SSMX ABCDEFGHIJ 2 Bright;
		Stop;
	SuperDeath:
		PSMX ABCDEFGHIJ 2 Bright;
		Stop;
	}
}

Class ASMDBeam : Actor
{
	ShockBeamTracer t;
	Vector3 tracedir;
	bool moving;
	double totaldist;

	Default
	{
		Obituary "$O_ASMD";
		DamageType 'jolted';
		RenderStyle "Add";
		Radius 0.1;
		Height 0;
		Scale 1.8;
		+NOGRAVITY;
		+NOCLIP;
		+DONTSPLASH;
		+FORCERADIUSDMG;
		+NODAMAGETHRUST;
		+NOTELEPORT;
		+FORCEXYBILLBOARD;
	}
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		t = new("ShockBeamTracer");
		t.owner = target;
		t.ignore = self;
		moving = true;
	}
	override void Tick()
	{
		Super.Tick();
		if ( isFrozen() || !moving ) return;
		// step trace
		tracedir = dt_Utility.Vec3FromAngle(angle,pitch);
		t.ShootThroughList.Clear();
		t.Trace(pos,cursector,tracedir,1000,0);
		for ( int i=0; i<t.ShootThroughList.Size(); i++ )
			t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
		totaldist += t.Results.Distance;
		// spawn particles
		for ( int i=10; i<t.Results.Distance; i+=80 )
			Spawn("ASMDBeamLight",Vec3Offset(tracedir.x*i,tracedir.y*i,tracedir.z*i));
		for ( int i=0; i<t.Results.Distance; i+=4 )
		{
			Vector3 pofs = tracedir*FRandom[ASMD](0,2)+(FRandom[ASMD](-.5,.5),FRandom[ASMD](-.5,.5),FRandom[ASMD](-.5,.5));
			let s = Spawn("ASMDSpark",Vec3Offset(tracedir.x*i+pofs.x,tracedir.y*i+pofs.y,tracedir.z*i+pofs.z));
			s.scale *= 0.2;
			s.vel = (FRandom[ASMD](-.3,.3),FRandom[ASMD](-.3,.3),FRandom[ASMD](-.3,.3));
		}
		for ( int i=10; i<t.Results.Distance; i+=20 )
		{
			let s = Spawn("ASMDRingTrail",Vec3Offset(tracedir.x*i,tracedir.y*i,tracedir.z*i));
			s.angle = angle;
			s.pitch = pitch;
		}
		if ( totaldist >= 10000.0 )
		{
			// reposition and explode on air
			SetOrigin(t.Results.HitPos-t.Results.HitVector*4,false);
			double mult = Amplifier.GetMult(target,100);
			BeamExplode(mult>1.5);
			Actor r;
			if ( mult > 1.5 ) r = Spawn("ASMDSBeamRing",pos);
			else r = Spawn("ASMDBeamRing",pos);
			r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
			r.pitch = asin(-t.Results.HitVector.z);
		}
		else if ( t.Results.HitType == TRACE_HitNone )
		{
			// reposition
			SetOrigin(t.Results.HitPos+t.Results.HitVector,false);
			angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
			pitch = asin(-t.Results.HitVector.z);
		}
		else if ( t.Results.HitType == TRACE_HitActor )
		{
			// reposition and explode on actor
			SetOrigin(t.Results.HitPos-t.Results.HitVector*4,false);
			double mult = Amplifier.GetMult(target,100);
			Actor r;
			if ( t.Results.HitActor is 'ASMDHitbox' )
			{
				BeamExplode(mult>1.5);
				if ( target && !sv_infiniteammo && !target.FindInventory('PowerInfiniteAmmo',true) )
					target.TakeInventory('ASMDAmmo',2);
				let b = t.Results.HitActor.target;
				b.bAMBUSH = true;
				b.ExplodeMissile();
				b.pitch = 90;
				b.angle = 0;
				b.roll = 0;
				UTMainHandler.DoBlast(b,240,140000);
				b.A_Explode(int(55*3.9*mult),240);
				b.A_SprayDecal("BigShockMark1",100);
				b.A_SprayDecal("SBigShockMark2",100);
				b.SetStateLabel("SuperDeath");
				b.A_SetScale(1.8);
				let l = Spawn("ASMDBlastLight",pos);
				let r = Spawn("ASMDBlastRing",b.pos);
				r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
				r.pitch = asin(-t.Results.HitVector.z);
				A_StartSound("asmd/blast",CHAN_WEAPON,attenuation:0.5,pitch:0.6);
				int numpt = Random[ASMD](200,300);
				for ( int i=0; i<numpt; i++ )
				{
					Vector3 pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](1,32);
					let s = Spawn("ASMDSpark",b.pos);
					s.vel = pvel;
				}
			}
			else
			{
				BeamExplode(mult>1.5);
				t.Results.HitActor.DamageMobj(self,target,int(35*mult),'jolted',DMG_USEANGLE,atan2(t.Results.HitVector.y,t.Results.HitVector.x));
				UTMainHandler.DoKnockback(t.Results.HitActor,t.Results.HitVector,60000);
				if ( mult > 1.5 ) r = Spawn("ASMDSBeamRing",pos);
				else r = Spawn("ASMDBeamRing",pos);
				r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
				r.pitch = asin(-t.Results.HitVector.z);
			}
		}
		else
		{
			// reposition and explode on wall
			SetOrigin(t.Results.HitPos-t.Results.HitVector*4,false);
			A_SprayDecal("ShockMark",16);
			moving = false;
			Vector3 HitNormal = t.Results.HitVector;
			if ( t.Results.HitType == TRACE_HitWall )
			{
				t.Results.HitLine.RemoteActivate(target,t.Results.Side,SPAC_Impact,pos);
				// calculate normal
				HitNormal = (-t.Results.HitLine.delta.y,t.Results.HitLine.delta.x,0).unit();
				if ( t.Results.Side == 0 ) HitNormal *= -1;
			}
			else if ( t.Results.HitType == TRACE_HitFloor )
			{
				if ( t.Results.ffloor ) HitNormal = -t.Results.ffloor.top.Normal;
				else HitNormal = t.Results.HitSector.floorplane.Normal;
			}
			else if ( t.Results.HitType == TRACE_HitCeiling )
			{
				if ( t.Results.ffloor ) HitNormal = -t.Results.ffloor.bottom.Normal;
				else HitNormal = t.Results.HitSector.ceilingplane.Normal;
			}
			double mult = Amplifier.GetMult(target,100);
			BeamExplode(mult>1.5);
			Actor r;
			if ( mult > 1.5 ) r = Spawn("ASMDSBeamRing",pos);
			else r = Spawn("ASMDBeamRing",pos);
			r.angle = atan2(HitNormal.y,HitNormal.x);
			r.pitch = asin(-HitNormal.z);
		}
	}
	void BeamExplode( bool amped = false )
	{
		moving = false;
		if ( amped )
		{
			Scale *= 0.3;
			SetStateLabel("AmpExplode");
			Spawn("ASMDSBeamLight",pos);
		}
		else
		{
			SetStateLabel("Explode");
			Spawn("ASMDBeamLight",pos);
		}
		A_QuakeEx(2,2,2,5,0,120,"",QF_RELATIVE|QF_SCALEDOWN,falloff:60,rollIntensity:0.1);
		A_StartSound("asmd/hit",CHAN_VOICE);
		A_AlertMonsters();
		int numpt = Random[ASMD](20,50);
		for ( int i=0; i<numpt; i++ )
		{
			Vector3 pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](2,6);
			let s = Spawn("ASMDSpark",pos);
			s.vel = pvel;
		}
	}
	States
	{
	Spawn:
		TNT1 A -1;
		Stop;
	Explode:
		AEXP ABCDEF 3 Bright;
		Stop;
	AmpExplode:
		SSMX ABCDEFGHIJ 2 Bright;
		Stop;
	}
}

Class ASMD : UnrealWeapon
{
	action void A_ShockFire()
	{
		Weapon weap = Weapon(invoker);
		if ( !weap ) return;
		if ( weap.Ammo1.Amount <= 0 ) return;
		if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
		A_StartSound("asmd/fire",CHAN_WEAPON,CHANF_OVERLAP,Dampener.Active(self)?.2:1.);
		invoker.FireEffect();
		A_Overlay(PSP_FLASH,"Flash");
		A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
		A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
		UTMainHandler.DoFlash(self,Color(80,64,32,255),1);
		if ( !Dampener.Active(self) ) A_AlertMonsters();
		A_QuakeEx(1,1,1,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
		Vector3 x, y, z;
		[x, y, z] = dt_Utility.GetAxes(angle,pitch,roll);
		Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x-2.9*y-2.5*z);
		Actor p = Spawn("ASMDBeam",origin);
		p.angle = angle;
		p.pitch = BulletSlope();
		p.target = self;
		int numpt = Random[ASMD](20,40);
		for ( int i=0; i<numpt; i++ )
		{
			let s = Spawn("ViewASMDSpark",origin);
			ViewASMDSpark(s).ofs = (10,-2.9,-2.5);
			s.target = self;
			ViewASMDSpark(s).vvel += (FRandom[ASMD](0.5,2.0),FRandom[ASMD](-1.5,1.5),FRandom[ASMD](-1.5,1.5));
		}
	}
	action void A_ShockAlt()
	{
		Weapon weap = Weapon(invoker);
		if ( !weap ) return;
		if ( weap.Ammo1.Amount <= 0 ) return;
		if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
		A_StartSound("asmd/altfire",CHAN_WEAPON,CHANF_OVERLAP,Dampener.Active(self)?.2:1.);
		double mult = Amplifier.GetMult(self,80);
		invoker.FireEffect();
		A_Overlay(PSP_FLASH,"Flash");
		A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
		A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
		UTMainHandler.DoFlash(self,Color(80,64,32,255),1);
		if ( !Dampener.Active(self) ) A_AlertMonsters();
		A_QuakeEx(1,1,1,8,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
		Vector3 x, y, z;
		[x, y, z] = dt_Utility.GetAxes(angle,pitch,roll);
		Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x-2.9*y-2.5*z);
		Actor p = Spawn("ASMDBall",origin);
		p.angle = angle;
		p.pitch = BulletSlope();
		p.vel = dt_Utility.Vec3FromAngle(p.angle,p.pitch)*p.speed;
		p.target = self;
		ASMDBall(p).mult = mult-1;
		int numpt = Random[ASMD](20,40);
		for ( int i=0; i<numpt; i++ )
		{
			let s = Spawn("ViewASMDSpark",origin);
			ViewASMDSpark(s).ofs = (10,-2.9,-2.5);
			s.target = self;
			ViewASMDSpark(s).vvel += (FRandom[ASMD](0.5,2.0),FRandom[ASMD](-1.5,1.5),FRandom[ASMD](-1.5,1.5));
		}
	}
	Default
	{
		Tag "$T_ASMD";
		Inventory.PickupMessage "$I_ASMD";
		Weapon.UpSound "asmd/select";
		Weapon.SlotNumber 4;
		Weapon.SelectionOrder 2000;
		Weapon.SlotPriority 1;
		Weapon.AmmoType "ASMDAmmo";
		Weapon.AmmoUse 1;
		Weapon.AmmoType2 "ASMDAmmo";
		Weapon.AmmoUse2 1;
		Weapon.AmmoGive 20;
		UTWeapon.DropAmmo 10;
	}
	States
	{
	Spawn:
		ASMP A -1;
		Stop;
		ASMP B -1;
		Stop;
	Ready:
		ASMS ABCDEFGHIJKLMN 1 A_WeaponReady(WRF_NOFIRE);
	Idle:
		#### # 8 A_Overlay(-9999,"Dummy");	// little hackeroo to make this more responsive
		ASMI AB 30;
		Goto Idle+1;
	Dummy:
		TNT1 A 1
		{
			A_CheckReload();
			A_WeaponReady();
			// that's a long-ass if
			if ( player.FindPSprite(PSP_WEAPON).CurState.InStateSequence(invoker.FindState("Idle")) && (player.cmd.forwardmove || player.cmd.sidemove) && (player.vel.length() > 0.5) )
				player.SetPSPrite(PSP_WEAPON,invoker.FindState("Sway"));
		}
		Wait;
	Vapour:
		#### # 8 A_Overlay(-9999,"Dummy");
		ASMI A 6
		{
			A_StartSound("asmd/vapour",CHAN_WEAPONMISC,CHANF_DEFAULT,.5);
			A_Overlay(PSP_FLASH,"VapourFlash");
			A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
			A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
		}
		ASMV ABCDEFGHIJ 4;
		Goto Idle;
	VapourFlash:
		ASVI A 6;
		ASVF ABCDEFGHIJ 4;
		Stop;
	Sway:
		#### # 4;
		ASMI C 10 A_JumpIf((!player.cmd.forwardmove && !player.cmd.sidemove) || (player.vel.length() < 0.5),4);
		ASMI D 10 A_JumpIf((!player.cmd.forwardmove && !player.cmd.sidemove) || (player.vel.length() < 0.5),5);
		ASMI E 10 A_JumpIf((!player.cmd.forwardmove && !player.cmd.sidemove) || (player.vel.length() < 0.5),6);
		ASMI F 10 A_JumpIf((!player.cmd.forwardmove && !player.cmd.sidemove) || (player.vel.length() < 0.5),7);
		Goto Sway+1;
		ASMI C 4;
		ASMI A 0 A_Jump(32,"Vapour");
		Goto Idle;
		ASMI D 4;
		ASMI A 0 A_Jump(32,"Vapour");
		Goto Idle;
		ASMI E 4;
		ASMI A 0 A_Jump(32,"Vapour");
		Goto Idle;
		ASMI F 4;
		ASMI A 0 A_Jump(32,"Vapour");
		Goto Idle;
	Fire:
		#### # 1
		{
			A_ShockFire();
			A_Overlay(-9999,"Null");
		}
		ASMF ABCDEFGH 3;
		ASMF H 0 A_Jump(48,"Vapour");
		Goto Idle;
	AltFire:
		#### # 1
		{
			A_ShockAlt();
			A_Overlay(-9999,"Null");
		}
		ASMA ABCDFGHIJ 2;
		ASMA J 0 A_Jump(48,"Vapour");
		Goto Idle;
	Deselect:
		ASMD A 1 A_Overlay(-9999,"Null");
		ASMD BCDEFGHIJ 1;
		ASMD J 1 A_Lower(int.max);
		Wait;
	Select:
		ASMS A 1 A_Raise(int.max);
		Wait;
	Flash:
		ASFF A 2 Bright
		{
			let l = Spawn("ASMDLight",pos);
			l.target = self;
		}
		Stop;
	}
}
