Class StingerAmmo : Ammo
{
	Default
	{
		Tag "$T_STINGERAMMO";
		Inventory.Icon "I_Stingr";
		Inventory.PickupMessage "";
		Inventory.Amount 5;
		Inventory.MaxAmount 200;
		Ammo.BackpackAmount 20;
		Ammo.BackpackMaxAmount 400;
		Ammo.DropAmount 2;
	}
	override String PickupMessage()
	{
		return String.Format("%s%d%s",StringTable.Localize("$I_STINGERAMMOL"),Amount,StringTable.Localize("$I_STINGERAMMOR"));
	}
	States
	{
	Spawn:
		SAMO A -1;
		Stop;
	}
}

Class StingerAmmo2 : StingerAmmo
{
	Default
	{
		Tag "$T_STINGERAMMO2";
		Inventory.Amount 40;
		Ammo.DropAmount 15;
	}
	States
	{
	Spawn:
		SAMO B -1;
		Stop;
	}
}

Class StingerBurstLight : PaletteLight
{
	Default
	{
		Tag "Blue4";
		Args 0,0,0,30;
		ReactionTime 12;
	}
}

Class StingerChunk : Actor
{
	int deadtimer;
	double rollvel, anglevel, pitchvel;

	Default
	{
		Radius 2;
		Height 2;
		+NOBLOCKMAP;
		+MISSILE;
		+MOVEWITHSECTOR;
		+THRUACTORS;
		+NOTELEPORT;
		+DONTSPLASH;
		+INTERPOLATEANGLES;
		BounceType "Doom";
		BounceFactor 0.4;
		Gravity 0.35;
	}
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		deadtimer = 0;
		anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
		pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
		rollvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
		frame = Random[Junk](0,8);
		scale *= Frandom[Junk](0.4,0.8);
	}
	override void Tick()
	{
		Super.Tick();
		if ( isFrozen() ) return;
		if ( InStateSequence(CurState,ResolveState("Death")) )
		{
			deadtimer++;
			if ( deadtimer > 60 ) A_FadeOut(0.05);
			return;
		}
	}
	States
	{
	Spawn:
		CHIP # 1
		{
			angle += anglevel;
			pitch += pitchvel;
			roll += rollvel;
		}
		Loop;
	Bounce:
		CHIP # 0
		{
			anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
			pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
			rollvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
		}
		Goto Spawn;
	Death:
		CHIP # -1;
		Stop;
	Dummy:
		CHIP ABCDEFGHI -1;
		Stop;
	}
}

Class ViewStingerChunk : StingerChunk
{
	Vector3 ofs, vvel;
	Default
	{
		+NOCLIP;
		+NOGRAVITY;
		-MISSILE;
		BounceType "None";
	}
	override void Tick()
	{
		Actor.Tick();
		if ( !target || !target.player )
		{
			Destroy();
			return;
		}
		Vector3 x, y, z;
		[x, y, z] = dt_CoordUtil.GetAxes(target.pitch,target.angle,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;
		scale *= 0.75;
		if ( scale.x <= 0.01 ) Destroy();
	}
}

Class TarydiumExLight : PaletteLight
{
	Default
	{
		Tag "Blue2";
		Args 0,0,0,60;
		ReactionTime 30;
	}
}

Class TarydiumExplosion : Actor
{
	Default
	{
		RenderStyle "Add";
		+NOGRAVITY;
		+NOBLOCKMAP;
		+FORCEXYBILLBOARD;
		+FORCERADIUSDMG;
		+NODAMAGETHRUST;
		DamageType 'TarydiumCharge';
		Obituary "$O_STINGERX";
	}
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		A_Explode(max(10,special1),90+special1);
		UTMainHandler.DoBlast(self,90+special1,900*special1);
		UTMainHandler.DoBlast(self,200+special1,200*special1);	// hurtless secondary blast, so stuff that's pretty close by gets pushed away
										// (just going off the novels here, it's supposed to be pretty strong)
		A_QuakeEx(clamp(special1/6,2,9),clamp(special1/6,2,9),clamp(special1/6,2,9),10,0,300+special1*2,"",QF_RELATIVE|QF_SCALEDOWN,falloff:200+special1*2,rollIntensity:0.12);
		SetOrigin(Vec3Offset(0,0,16),false);
		A_PlaySound("stinger/explode",CHAN_VOICE,pitch:FRandom[Stinger](0.8,1.5));
		A_PlaySound("stinger/explode",CHAN_ITEM,pitch:FRandom[Stinger](0.8,1.5));
		let l = Spawn("TarydiumExLight",pos);
		l.args[3] = int(60*scale.x);
		scale.x *= RandomPick[Stinger](-1,1);
		scale.y *= RandomPick[Stinger](-1,1);
		double ang, pt;
		int numpt = Random[Stinger](10,15)*min(3,special1/60);
		for ( int i=0; i<numpt; i++ )
		{
			ang = FRandom[Stinger](0,360);
			pt = FRandom[Stinger](-90,90);
			let c = Spawn("UTSmoke",pos);
			c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](2,7);
			c.SetShade(Color(1,3,4)*Random[Stinger](24,63));
			c.scale *= 3.;
		}
		numpt = Random[Stinger](4,8)*min(8,special1/25);
		for ( int i=0; i<numpt; i++ )
		{
			ang = FRandom[Stinger](0,360);
			pt = FRandom[Stinger](-90,90);
			let c = Spawn("StingerChunk",pos);
			c.angle = ang;
			c.pitch = pt;
			c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](6,12);
		}
		numpt = Random[Stinger](10,20)*min(4,special1/40);
		for ( int i=0; i<numpt; i++ )
		{
			ang = FRandom[Stinger](0,360);
			pt = FRandom[Stinger](-90,90);
			let c = Spawn("UTChip",pos);
			c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](6,12);
			c.scale *= FRandom[Stinger](0.9,1.5);
		}
	}
	States
	{
	Spawn:
		TNT1 A 0 NoDelay A_Jump(128,"Explo2");
	Explo1:
		TEX1 ABCDEFGHI 3 Bright;
		Stop;
	Explo2:
		TEX2 ABCDEFGHIJK 3 Bright;
		Stop;
	}
}

Class TDebuffLight : PointLightAttenuated
{
	TarydiumDebuff dbf;

	override void Tick()
	{
		Super.Tick();
		if ( !dbf || !dbf.victim )
		{
			Destroy();
			return;
		}
		Args[0] = int(min(dbf.Amount,64));
		Args[1] = int(min(dbf.Amount*3,192));
		Args[2] = int(min(dbf.Amount*4,255));
		Args[3] = int(max(dbf.victim.radius,dbf.victim.height)+60+min(dbf.amount/4,40));
		SetOrigin(dbf.Victim.Vec3Offset(0,0,dbf.Victim.Height/2),true);
	}
}

Class TarydiumDebuff : Thinker
{
	Actor victim, instigator, lite;
	double amount;	// accumulated damage for the explosion
	Vector3 oldvel;
	bool wasonair, exploding;
	int explodetimer;

	void UpdateEffect()
	{
		if ( !victim ) return;
		if ( !lite )
		{
			lite = Actor.Spawn("TDebuffLight",victim.pos);
			TDebuffLight(lite).dbf = self;
			lite.Args[0] = int(min(Amount,64));
			lite.Args[1] = int(min(Amount*3,192));
			lite.Args[2] = int(min(Amount*4,255));
			lite.Args[3] = int(max(victim.radius,victim.height)+60+min(amount/4,40));
		}
	}

	void BlowUp()
	{
		let b = victim.Spawn("TarydiumExplosion",victim.Vec3Offset(FRandom[Stinger](-victim.radius,victim.radius),FRandom[Stinger](-victim.radius,victim.radius),FRandom[Stinger](0,victim.height)));
		b.target = instigator;
		b.special1 = int(min(amount,100));	// in Unreal this was capped to 10, which would make it deal barely any damage
		b.scale *= .8+min(1.,amount*0.01);
		amount = amount*0.9-10;	// in Unreal this falls off linearly 10 points at a time, which can take very long at full charge
	}

	override void OnDestroy()
	{
		if ( lite ) lite.Destroy();
		Super.OnDestroy();
	}

	override void Tick()
	{
		if ( !sting_stinger || !victim || (amount <= .4) )
		{
			Destroy();
			return;
		}
		if ( exploding )
		{
			explodetimer--;
			if ( explodetimer > 0 ) return;
			explodetimer = Random[Stinger](3,6);
			BlowUp();
			return;
		}
		if ( victim.Health <= 0 )
		{
			exploding = true;
			return;
		}
		if ( victim.pos.z > victim.floorz ) wasonair = true;
		else
		{
			if ( wasonair && (oldvel.z < -20) )
			{
				Amount += min(int(-oldvel.z),100);
				exploding = true;
				return;
			}
			wasonair = false;
		}
		oldvel = victim.vel;
		amount *= 1.-.04/TICRATE;
		UpdateEffect();
		if ( amount <= .4 )
		{
			Destroy();
			return;
		}
		if ( level.maptime%3 ) return;
		int numpt = clamp(int(Random[Stinger](1,3)*amount*0.02),1,8);
		for ( int i=0; i<numpt; i++ )
		{
			Vector3 pos = victim.Vec3Offset(FRandom[Stinger](-victim.radius,victim.radius),FRandom[Stinger](-victim.radius,victim.radius),FRandom[Stinger](0,victim.height));
			let l = victim.Spawn("StingerBurstLight",pos);
			l.Args[3] /= 2;
			double ang, pt;
			int numpt2 = Random[Stinger](2,5);
			for ( int i=0; i<numpt; i++ )
			{
				ang = FRandom[Stinger](0,360);
				pt = FRandom[Stinger](-90,90);
				let c = victim.Spawn("UTSmoke",pos);
				c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](0.3,0.8);
				c.SetShade(Color(1,3,4)*Random[Stinger](24,63));
				c.scale *= 3.;
				c.alpha *= 0.35;
			}
		}
	}

	static void Apply( Actor victim, Actor instigator, double amount )
	{
		if ( !victim || (victim.Health <= 0) || !victim.bISMONSTER ) return;
		if ( !sting_stinger ) return;
		let ti = ThinkerIterator.Create("TarydiumDebuff",STAT_USER);
		TarydiumDebuff t;
		while ( t = TarydiumDebuff(ti.Next()) )
		{
			if ( t.victim != victim ) continue;
			if ( instigator ) t.instigator = instigator;
			t.amount += amount;
			t.UpdateEffect();
			return;
		}
		t = new("TarydiumDebuff");
		t.ChangeStatNum(STAT_USER);
		t.victim = victim;
		t.instigator = instigator;
		t.amount = amount;
		t.oldvel = victim.vel;
		t.wasonair = (victim.pos.z>victim.floorz);
		t.UpdateEffect();
	}
}

Class StingerProjectile : Actor
{
	Vector3 oldvel;
	Default
	{
		Obituary "$O_STINGER";
		DamageType 'Stinger';
		DamageFunction 14;
		Speed 40;
		Radius 2;
		Height 2;
		PROJECTILE;
		+SKYEXPLODE;
	}
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		if ( sting_stingerb )
		{
			// set bounce stuff
			bBOUNCEONWALLS = true;
			bBOUNCEONFLOORS = true;
			bBOUNCEONCEILINGS = true;
			bALLOWBOUNCEONACTORS = true;
			bCANBOUNCEWATER = true;
			bUSEBOUNCESTATE = true;
			BounceCount = 4;
			BounceFactor = 1.;
			WallBounceFactor = 1.;
		}
	}
	override void Tick()
	{
		oldvel = vel;
		Super.Tick();
	}
	void A_HandleBounce()
	{
		// cancel bounce based on "incidence"
		if ( vel dot oldvel < 0.87 )
		{
			ClearBounce();
			ExplodeMissile();
			return;
		}
		if ( !Random[Stinger](0,2) ) A_PlaySound("stinger/hit2",CHAN_BODY,0.5,pitch:FRandom[Stinger](0.5,1.5));
		else A_PlaySound("stinger/hit",CHAN_BODY,0.6);
		A_SprayDecal("WallCrack",-20);
		A_AlertMonsters();
		let l = Spawn("StingerBurstLight",pos);
		l.Args[3] /= 2;
		double ang, pt;
		int numpt = Random[Stinger](1,3);
		for ( int i=0; i<numpt; i++ )
		{
			ang = FRandom[Stinger](0,360);
			pt = FRandom[Stinger](-90,90);
			let c = Spawn("StingerChunk",pos);
			c.scale *= 0.5;
			c.angle = ang;
			c.pitch = pt;
			c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](3,9);
		}
		numpt = Random[Stinger](2,5);
		for ( int i=0; i<numpt; i++ )
		{
			ang = FRandom[Stinger](0,360);
			pt = FRandom[Stinger](-90,90);
			let c = Spawn("UTSmoke",pos);
			c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](0.3,0.8);
			c.SetShade(Color(1,3,4)*Random[Stinger](48,63));
			c.alpha *= 0.35;
		}
	}
	override int DoSpecialDamage( Actor target, int damage, Name damagetype )
	{
		if ( !target.bNOBLOOD )
		{
			target.SpawnBlood(pos,AngleTo(target),damage);
			A_PlaySound("stinger/flesh");
			A_AlertMonsters();
			if ( sting_stinger )
			{
				TarydiumDebuff.Apply(target,self.target,10);
				damage = 2;
			}
		}
		return damage;
	}
	action void A_StingerHit()
	{
		if ( !Random[Stinger](0,2) ) A_PlaySound("stinger/hit2",CHAN_BODY,0.5,pitch:FRandom[Stinger](0.5,1.5));
		else A_PlaySound("stinger/hit",CHAN_BODY,0.6);
		A_SprayDecal("WallCrack",20);
		A_AlertMonsters();
		Spawn("StingerBurstLight",pos);
		double ang, pt;
		int numpt = Random[Stinger](4,8);
		for ( int i=0; i<numpt; i++ )
		{
			ang = FRandom[Stinger](0,360);
			pt = FRandom[Stinger](-90,90);
			let c = Spawn("StingerChunk",pos);
			c.angle = ang;
			c.pitch = pt;
			c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](3,9);
		}
		numpt = Random[Stinger](6,12);
		for ( int i=0; i<numpt; i++ )
		{
			ang = FRandom[Stinger](0,360);
			pt = FRandom[Stinger](-90,90);
			let c = Spawn("UTSmoke",pos);
			c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[Stinger](0.3,0.8);
			c.SetShade(Color(1,3,4)*Random[Stinger](48,63));
			c.alpha *= 0.5;
		}
	}
	States
	{
	Spawn:
		TPRJ A 1 Bright
		{
			if ( waterlevel > 0 )
				Spawn("UTBubble",pos);
		}
		Wait;
	Bounce:
		TPRJ A 0 Bright A_HandleBounce();
		Goto Spawn;
	Death:
	Crash:
		TNT1 A 1 A_StingerHit();
		Stop;
	XDeath:
		TNT1 A 1;
		Stop;
	}
}

Class StingerLight : EnforcerLight
{
	Default
	{
		args 64,128,255,80;
	}
}

Class Stinger : UnrealWeapon
{
	int flashnum;

	Default
	{
		Tag "$T_STINGER";
		Inventory.PickupMessage "$I_STINGER";
		Weapon.UpSound "stinger/select";
		Weapon.SlotNumber 3;
		Weapon.SelectionOrder 2500;
		Weapon.SlotPriority 1;
		Weapon.AmmoType "StingerAmmo";
		Weapon.AmmoUse 1;
		Weapon.AmmoType2 "StingerAmmo";
		Weapon.AmmoUse2 1;
		Weapon.AmmoGive 40;
		UTWeapon.DropAmmo 20;
	}
	action void A_StingerFire( bool hold = false )
	{
		Weapon weap = Weapon(invoker);
		if ( !weap ) return;
		if ( weap.Ammo1.Amount <= 0 ) return;
		if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
		if ( hold )
		{
			A_SoundVolume(CHAN_WEAPON,Dampener.Active(self)?.1:1.);
			A_Overlay(PSP_FLASH,"MFlashHold");
		}
		else
		{
			A_PlaySound("stinger/fire",CHAN_WEAPON,Dampener.Active(self)?.1:1.);
			A_Overlay(PSP_FLASH,"MFlash");
		}
		A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
		A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
		invoker.FireEffect();
		UTMainHandler.DoFlash(self,Color(16,0,64,255),1);
		UTMainHandler.DoSwing(self,(FRandom[Stinger](-0.1,-0.2),FRandom[Stinger](-0.1,0.1)),4,-1.5,2,SWING_Spring,2,2);
		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_CoordUtil.GetAxes(pitch,angle,roll);
		Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),5*x+8*y-8*z);
		Actor p = Spawn("StingerProjectile",origin);
		p.angle = angle;
		p.pitch = BulletSlope();
		p.roll = FRandom[Stinger](0,360);
		p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed;
		p.target = self;
		int numpt = Random[Stinger](5,9);
		double ang;
		for ( int i=0; i<numpt; i++ )
		{
			let s = Spawn("ViewStingerChunk",origin);
			ViewStingerChunk(s).ofs = (8,2,-2);
			ang = FRandom[Stinger](0,360);
			ViewStingerChunk(s).vvel = (FRandom[Stinger](0.2,1.2),0,0)+(0,cos(ang),sin(ang))*FRandom[Stinger](0.3,0.9);
			s.target = self;
		}
		for ( int i=0; i<12; i++ )
		{
			let s = Spawn("UTViewSmoke",origin);
			UTViewSmoke(s).ofs = (16,4,-4);
			ang = FRandom[Stinger](0,360);
			UTViewSmoke(s).vvel = (FRandom[Stinger](0,0.4),0,0)+(0,cos(ang),sin(ang))*FRandom[Stinger](0.2,0.5);
			s.target = self;
			s.scale *= 1.5;
			s.alpha *= 0.3;
			s.SetShade(Color(1,3,4)*Random[Stinger](31,63));
		}
	}
	action void A_StingerAltFire()
	{
		Weapon weap = Weapon(invoker);
		if ( !weap ) return;
		if ( weap.Ammo1.Amount <= 0 ) return;
		A_PlaySound("stinger/altfire",CHAN_WEAPON,Dampener.Active(self)?.1:1.);
		A_Overlay(PSP_FLASH,"MFlash");
		A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
		A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
		invoker.FireEffect();
		UTMainHandler.DoFlash(self,Color(16,0,64,255),1);
		UTMainHandler.DoSwing(self,(FRandom[Stinger](-0.3,-0.8),FRandom[Stinger](-0.4,0.4)),4,-1,3,SWING_Spring,3,5);
		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_CoordUtil.GetAxes(pitch,angle,roll);
		Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),5*x+8*y-8*z);
		[x, y, z] = dt_CoordUtil.GetAxes(BulletSlope(),angle,roll);
		Actor p;
		double a, s;
		Vector3 dir;
		for ( int i=0; i<5; i++ )
		{
			if ( weap.Ammo1.Amount <= 0 ) return;
			if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
			a = FRandom[Stinger](0,360);
			s = FRandom[Stinger](0,(i>0)?.08:0.);	// first shot always accurate
			dir = (x+y*cos(a)*s+z*sin(a)*s).unit();
			p = Spawn("StingerProjectile",origin);
			p.angle = atan2(dir.y,dir.x);
			p.pitch = asin(-dir.z);
			p.roll = FRandom[Stinger](0,360);
			p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed;
			p.target = self;
			int numpt = Random[Stinger](5,9);
			double ang;
			for ( int i=0; i<numpt; i++ )
			{
				let s = Spawn("ViewStingerChunk",origin);
				ViewStingerChunk(s).ofs = (8,2,-2);
				ang = FRandom[Stinger](0,360);
				ViewStingerChunk(s).vvel = (FRandom[Stinger](0.2,1.2),0,0)+(0,cos(ang),sin(ang))*FRandom[Stinger](0.3,0.9);
				s.target = self;
			}
			for ( int i=0; i<12; i++ )
			{
				let s = Spawn("UTViewSmoke",origin);
				UTViewSmoke(s).ofs = (16,4,-4);
				ang = FRandom[Stinger](0,360);
				UTViewSmoke(s).vvel = (FRandom[Stinger](0,0.4),0,0)+(0,cos(ang),sin(ang))*FRandom[Stinger](0.2,0.5);
				s.target = self;
				s.scale *= 1.5;
				s.alpha *= 0.3;
				s.SetShade(Color(1,3,4)*Random[Stinger](48,63));
			}
		}
	}
	States
	{
	Spawn:
		STNP A -1;
		Stop;
		STNP B -1;
		Stop;
	Select:
		STNS A 1 A_Raise(int.max);
		Wait;
	Ready:
		STNS ABCDEFGHIJKLMNOPQRSTU 1 A_WeaponReady(WRF_NOFIRE);
	Idle:
		STNI A 1
		{
			A_CheckReload();
			A_WeaponReady();
		}
		Wait;
	Fire:
		STNF A 2 A_StingerFire();
		STNF BC 2;
		STNI A 3;
		STNI A 0 A_Refire(1);
		Goto Idle;
		STNI A 0
		{
			A_PlaySound("stinger/hold",CHAN_WEAPON,Dampener.Active(self)?.1:1.,true);
			invoker.flashnum = Random[Stinger](0,3);
		}
	Hold:
		STNH A 1
		{
			// need to make sure player does the repeat fire anim
			if ( self is 'UPlayer' )
				UPlayer(self).PlayAttacking();
			A_StingerFire(true);
			invoker.flashnum = (invoker.flashnum+1)%4;
		}
		STNH BCDEFG 1;
		STNH A 0 A_JumpIfNoAmmo(1);
		STNH A 0 A_Refire();
		STNH A 2 A_PlaySound("stinger/release",CHAN_WEAPON,Dampener.Active(self)?.1:1.);
		Goto Idle;
	AltFire:
		STNF A 2 A_StingerAltFire();
		STNF BC 2;
		STNI A 35;	// yes, 1 second cooldown
		Goto Idle;
	Deselect:
		STND ACEGIK 1;
		STND K 1 A_Lower(int.max);
		Wait;
	MFlash:
		STFF A 2 Bright
		{
			let l = Spawn("StingerLight",pos);
			l.target = self;
		}
		Stop;
	MFlashHold:
		TNT1 A 0 A_JumpIf(invoker.flashnum==0,7);
		TNT1 A 0 A_JumpIf(invoker.flashnum==1,4);
		TNT1 A 0 A_JumpIf(invoker.flashnum==2,4);
		TNT1 A 0 A_JumpIf(invoker.flashnum==3,1);
		Stop;
		STFF A 2 Bright
		{
			let l = Spawn("StingerLight",pos);
			l.target = self;
		}
		Stop;
		STFF B 2 Bright
		{
			let l = Spawn("StingerLight",pos);
			l.target = self;
		}
		Stop;
		STFF C 2 Bright
		{
			let l = Spawn("StingerLight",pos);
			l.target = self;
		}
		Stop;
		STFF D 2 Bright
		{
			let l = Spawn("StingerLight",pos);
			l.target = self;
		}
		Stop;
	/*MFlash:
		STFF ABC 2 Bright;
		Stop;
	MFlashHold:
		STFH ABCDEFG 1 Bright;
		Stop;*/
	}
}
