Class WeaponPowerUp : Inventory
{
	Default
	{
		Tag "$T_WPOWERUP";
		Inventory.PickupMessage "$I_WPOWERUP";
		Inventory.PickupSound "misc/p_pkup";
		+COUNTITEM;
		+INVENTORY.BIGPOWERUP;
	}
	override bool TryPickup( in out Actor toucher )
	{
		if ( !toucher.FindInventory("DispersionPistol") ) return false;
		let damo = DefaultAmmo(toucher.FindInventory("DefaultAmmo"));
		if ( damo )
		{
			damo.BackpackMaxAmount = damo.MaxAmount = min(90,damo.MaxAmount+10);
			damo.Amount = min(damo.MaxAmount,damo.Amount+10);
		}
		let dpis = DispersionPistol(toucher.FindInventory("DispersionPistol"));
		if ( dpis && (dpis.pendingupgrade < 4) )
		{
			dpis.pendingupgrade++;
			if ( toucher.player && ((toucher.player.ReadyWeapon != dpis) || (toucher.player.PendingWeapon != WP_NOCHANGE)) )
				ScriptUtil.SetWeapon(toucher,"DispersionPistol");
		}
		GoAwayAndDie();
		return true;
	}
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		tracer = Spawn("WeaponPowerUpX",pos);
		tracer.angle = angle;
		tracer.target = self;
	}
	States
	{
	Spawn:
		WPOW A -1;
		Stop;
	}
}

Class WeaponPowerUpX : ASMDAmmoX
{
	States
	{
	Spawn:
		WPOW ABCDEFGHIJKLMNOPQRST 3 Bright;
		Loop;
	}
}

Class DefaultAmmo : Ammo
{
	double rechargephase, rechargespeed;

	Default
	{
		Inventory.Icon "I_Disper";
		Inventory.Amount 10;
		Inventory.MaxAmount 50;
		Ammo.BackpackAmount 0;
		Ammo.BackpackMaxAmount 50;
	}
	override void DoEffect()
	{
		Super.DoEffect();
		if ( rechargespeed <= 0. ) rechargespeed = 1.1;
		rechargephase += 1./rechargespeed;
		if ( rechargephase < 35 ) return;
		rechargespeed = max(1.1,0.11*Amount);
		rechargephase = 0;
		Amount = min(Amount+1,MaxAmount);
	}
}

Class DispExLight1 : PaletteLight
{
	Default
	{
		Tag "DBlue";
		Args 0,0,0,80;
		ReactionTime 25;
	}
}
Class DispExLight2 : PaletteLight
{
	Default
	{
		Tag "DGreen";
		Args 0,0,0,80;
		ReactionTime 25;
	}
}
Class DispExLight3 : PaletteLight
{
	Default
	{
		Tag "DYellow";
		Args 0,0,0,80;
		ReactionTime 25;
	}
}
Class DispExLight4 : PaletteLight
{
	Default
	{
		Tag "DOrange";
		Args 0,0,0,80;
		ReactionTime 25;
	}
}
Class DispExLight5 : PaletteLight
{
	Default
	{
		Tag "DRed";
		Args 0,0,0,80;
		ReactionTime 25;
	}
}

Class DispBurst1 : ASMDSpark
{
	States
	{
	Spawn:
		DEFB ABCDEFG 1 Bright
		{
			A_FadeOut(FRandom[ASMD](0.0,0.3));
			vel *= 0.95;
		}
		Loop;
	}
}
Class DispBurst2 : DispBurst1
{
	States
	{
	Spawn:
		DEFG ABCDEFG 1 Bright
		{
			A_FadeOut(FRandom[ASMD](0.0,0.3));
			vel *= 0.95;
		}
		Loop;
	}
}
Class DispBurst3 : DispBurst1
{
	States
	{
	Spawn:
		DEFY ABCDEFG 1 Bright
		{
			A_FadeOut(FRandom[ASMD](0.0,0.3));
			vel *= 0.95;
		}
		Loop;
	}
}
Class DispBurst4 : DispBurst1
{
	States
	{
	Spawn:
		DEFO ABCDEFG 1 Bright
		{
			A_FadeOut(FRandom[ASMD](0.0,0.3));
			vel *= 0.95;
		}
		Loop;
	}
}
Class DispBurst5 : DispBurst1
{
	States
	{
	Spawn:
		DEFR ABCDEFG 1 Bright
		{
			A_FadeOut(FRandom[ASMD](0.0,0.3));
			vel *= 0.95;
		}
		Loop;
	}
}
Class ViewDispBurst1 : ViewASMDSpark
{
	States
	{
	Spawn:
		DEFB ABCDEFG 1 Bright A_FadeOut(FRandom[ASMD](0.0,0.3));
		Loop;
	}
}
Class ViewDispBurst2 : ViewDispBurst1
{
	States
	{
	Spawn:
		DEFG ABCDEFG 1 Bright A_FadeOut(FRandom[ASMD](0.0,0.3));
		Loop;
	}
}
Class ViewDispBurst3 : ViewDispBurst1
{
	States
	{
	Spawn:
		DEFY ABCDEFG 1 Bright A_FadeOut(FRandom[ASMD](0.0,0.3));
		Loop;
	}
}
Class ViewDispBurst4 : ViewDispBurst1
{
	States
	{
	Spawn:
		DEFO ABCDEFG 1 Bright A_FadeOut(FRandom[ASMD](0.0,0.3));
		Loop;
	}
}
Class ViewDispBurst5 : ViewDispBurst1
{
	States
	{
	Spawn:
		DEFR ABCDEFG 1 Bright A_FadeOut(FRandom[ASMD](0.0,0.3));
		Loop;
	}
}

Class DispExplo1 : Actor
{
	Default
	{
		RenderStyle "Add";
		Scale 0.4;
		+NOGRAVITY;
		+NOBLOCKMAP;
		Radius 0.1;
		Height 0;
	}
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		Scale.x *= RandomPick[DPistol](-1,1);
		Scale.y *= RandomPick[DPistol](-1,1);
	}
	States
	{
	Spawn:
		DSEB ABCDEFGHIJ 2 Bright;
		Stop;
	}
}
Class DispExplo2 : DispExplo1
{
	States
	{
	Spawn:
		DISE ABCDEFGHIJ 2 Bright;
		Stop;
	}
}
Class DispExplo3 : DispExplo1
{
	States
	{
	Spawn:
		DSEY ABCDEFGHIJ 2 Bright;
		Stop;
	}
}
Class DispExplo4 : DispExplo1
{
	States
	{
	Spawn:
		DSEO ABCDEFGHIJ 2 Bright;
		Stop;
	}
}
Class DispExplo5 : DispExplo1
{
	States
	{
	Spawn:
		DSER ABCDEFGHIJ 2 Bright;
		Stop;
	}
}

// yes this is the projectile class name, blame Epic
Class DispersionAmmo : Actor
{
	Class<Actor> LightClass, BurstClass, ExploClass;
	double mult;

	Property LightClass : LightClass;
	Property BurstClass : BurstClass;
	Property ExploClass : ExploClass;

	action void A_DispTrail()
	{
		Vector3 x, y, z, dir;
		double a, s;
		Actor p;
		[x,y,z] = dt_Utility.GetAxes(angle,pitch,roll);
		for ( int i=0; i<3; i++ )
		{
			a = FRandom[DPistol](0,360);
			s = FRandom[ASMD](0,0.35);
			dir = dt_Utility.ConeSpread(-x,y,z,a,s);
			p = Spawn(invoker.BurstClass,level.Vec3Offset(pos,scale.x*(dir*16.+x*32.)));
			p.A_SetScale(0.1*min(0.8+invoker.mult*0.75,1.5));
			p.vel = vel*0.5+dir*FRandom[DPistol](3,8);
		}
	}
	action void A_DispExpl()
	{
		UTMainHandler.DoKnockback(tracer,dt_Utility.Vec3FromAngle(angle,pitch),6000);
		A_AlertMonsters(gameinfo.gametype&GAME_Strife?100:0);
		A_SprayDecal("RazorBlast",20);
		Spawn(invoker.LightClass,pos);
		Actor a;
		double ang, pt;
		int numpt = int(Random[DPistol](12,18)*invoker.mult);
		for ( int i=0; i<numpt; i++ )
		{
			a = Spawn(invoker.BurstClass,pos);
			a.A_SetScale(0.2*min(0.8+invoker.mult*0.75,1.5));
			ang = FRandom[DPistol](0,360);
			pt = FRandom[DPistol](-90,90);
			a.vel = dt_Utility.Vec3FromAngle(ang,pt)*FRandom[DPistol](6,16);
			a.alpha *= 2.;
		}
		a = Spawn(invoker.ExploClass,pos);
		a.A_SetScale(min(0.8+invoker.mult*0.8,2.5));
		if ( !bAMBUSH ) return;
		UTMainHandler.DoBlast(self,80,6000);
		A_Explode(GetMissileDamage(0,0),80);
	}
	override int DoSpecialDamage( Actor target, int damage, Name damagetype )
	{
		if ( gameinfo.gametype&GAME_Strife )
			target.DaggerAlert(self.target);
		return damage;
	}
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		A_StartSound("dpistol/fly",CHAN_VOICE,CHANF_LOOPING,.9,2.);
		mult = max(1.,mult);
	}
	Default
	{
		Obituary "$O_DPISTOL";
		DamageFunction (15*mult);
		DamageType 'DAmmo1';
		Scale 0.8;
		Radius 4;
		Height 4;
		Speed 25;
		RenderStyle "Add";
		PROJECTILE;
		+FORCEXYBILLBOARD;
		+SKYEXPLODE;
		+EXPLODEONWATER;
		+FORCERADIUSDMG;
		+NODAMAGETHRUST;
		+INTERPOLATEANGLES;
		+HITTRACER;
		+NOFRICTION;
		DispersionAmmo.LightClass "DispExLight1";
		DispersionAmmo.BurstClass "DispBurst1";
		DispersionAmmo.ExploClass "DispExplo1";
	}
	States
	{
	Spawn:
		DISM AABBCCDDEEFFGGHH 1 Bright A_DispTrail();
		Loop;
	Death:
		TNT1 A 1
		{
			A_StartSound("dpistol/hit",CHAN_VOICE);
			A_DispExpl();
		}
		Stop;
	}
}
Class DAmmo2 : DispersionAmmo
{
	Default
	{
		DamageFunction (25*mult);
		DamageType 'DAmmo2';
		DispersionAmmo.LightClass "DispExLight2";
		DispersionAmmo.BurstClass "DispBurst2";
		DispersionAmmo.ExploClass "DispExplo2";
	}
}
Class DAmmo3 : DispersionAmmo
{
	Default
	{
		DamageFunction (40*mult);
		DamageType 'DAmmo3';
		DispersionAmmo.LightClass "DispExLight3";
		DispersionAmmo.BurstClass "DispBurst3";
		DispersionAmmo.ExploClass "DispExplo3";
	}
}
Class DAmmo4 : DispersionAmmo
{
	Default
	{
		DamageFunction (55*mult);
		DamageType 'DAmmo4';
		DispersionAmmo.LightClass "DispExLight4";
		DispersionAmmo.BurstClass "DispBurst4";
		DispersionAmmo.ExploClass "DispExplo4";
	}
}
Class DAmmo5 : DispersionAmmo
{
	Default
	{
		DamageFunction (75*mult);
		DamageType 'DAmmo5';
		DispersionAmmo.LightClass "DispExLight5";
		DispersionAmmo.BurstClass "DispBurst5";
		DispersionAmmo.ExploClass "DispExplo5";
	}
}

Class DispLight1 : EnforcerLight
{
	Default
	{
		args 96,64,255,80;
	}
}
Class DispLight2 : EnforcerLight
{
	Default
	{
		args 64,255,96,80;
	}
}
Class DispLight3 : EnforcerLight
{
	Default
	{
		args 255,255,96,80;
	}
}
Class DispLight4 : EnforcerLight
{
	Default
	{
		args 255,160,64,80;
	}
}
Class DispLight5 : EnforcerLight
{
	Default
	{
		args 255,96,64,80;
	}
}

Class DispersionPistol : UnrealWeapon
{
	int upgradelevel, pendingupgrade;
	double chargesize, count;
	bool bCharging;
	int MainUse, ChargeUse;
	bool bOldSkin;

	override void Tick()
	{
		Super.Tick();
		if ( sting_olddpistol )
		{
			if ( !bOldSkin )
			{
				A_ChangeModel("",1,"","",1,"models/OldSkins","DPistol1_.png");
				A_ChangeModel("",0,"","",1,"models/OldSkins","DPistol1.png",CMDL_USESURFACESKIN);
			}
			bOldSkin = true;
		}
		else
		{
			if ( bOldSkin )
			{
				A_ChangeModel("",1,"","",1,"models","DPistol1_.png");
				A_ChangeModel("",0,"","",1,"models","DPistol1.png",CMDL_USESURFACESKIN);
			}
			bOldSkin = false;
		}
	}

	override int, int, bool, bool GetClipAmount()
	{
		return bCharging?min(5,int(chargesize+0.1)):-1, -1, false, false;
	}
	override void DoEffect()
	{
		Super.DoEffect();
		if ( MainUse < 1 ) MainUse = 1;
		if ( sting_dpistol ) ChargeUse = 1;
		else ChargeUse = max(1,MainUse/2);
	}
	action void A_DispFire()
	{
		Weapon weap = Weapon(invoker);
		if ( !weap ) return;
		if ( weap.Ammo1.Amount <= 0 ) return;
		A_StartSound("dpistol/fire",CHAN_WEAPON,CHANF_OVERLAP,Dampener.Active(self)?.4:1.,pitch:1.2);
		double mult = Amplifier.GetMult(self,80);
		invoker.FireEffect();
		Class<Actor> proj, part;
		int ulevel = invoker.upgradelevel;
		if ( !(sv_infiniteammo || FindInventory('PowerInfiniteAmmo',true)) )
		{
			if ( weap.Ammo1.Amount < max(10,invoker.MainUse) )
			{
				weap.Ammo1.Amount -= 1;
				ulevel = 0;
			}
			else weap.Ammo1.Amount -= invoker.MainUse;
		}
		DefaultAmmo(weap.Ammo1).rechargephase = (((weap.Ammo1.Amount>0)||!deathmatch)?0:30);
		DefaultAmmo(weap.Ammo1).rechargespeed = 1.1;
		switch ( ulevel )
		{
		case 0:
			proj = "DispersionAmmo";
			part = "ViewDispBurst1";
			UTMainHandler.DoFlash(self,Color(80,96,64,255),1);
			A_Overlay(PSP_FLASH,"Flash1");
			break;
		case 1:
			proj = "DAmmo2";
			part = "ViewDispBurst2";
			UTMainHandler.DoFlash(self,Color(80,64,255,96),1);
			A_Overlay(PSP_FLASH,"Flash2");
			break;
		case 2:
			proj = "DAmmo3";
			part = "ViewDispBurst3";
			UTMainHandler.DoFlash(self,Color(80,255,255,96),1);
			A_Overlay(PSP_FLASH,"Flash3");
			break;
		case 3:
			proj = "DAmmo4";
			part = "ViewDispBurst4";
			UTMainHandler.DoFlash(self,Color(80,255,160,64),1);
			A_Overlay(PSP_FLASH,"Flash4");
			break;
		default:
			proj = "DAmmo5";
			part = "ViewDispBurst5";
			UTMainHandler.DoFlash(self,Color(80,255,96,64),1);
			A_Overlay(PSP_FLASH,"Flash5");
			break;
		}
		A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
		A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
		if ( !Dampener.Active(self) ) A_AlertMonsters(gameinfo.gametype&GAME_Strife?120:0);
		A_QuakeEx(2,2,2,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-3*y-3*z);
		Actor p = Spawn(proj,origin);
		p.angle = angle;
		p.pitch = BulletSlope();
		p.vel = dt_Utility.Vec3FromAngle(p.angle,p.pitch)*p.speed;
		p.target = self;
		DispersionAmmo(p).mult = mult;
		int numpt = Random[DPistol](10,20);
		for ( int i=0; i<numpt; i++ )
		{
			let s = Spawn(part,origin);
			ViewASMDSpark(s).ofs = (10,-3,-3);
			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_DispAltFire()
	{
		Weapon weap = Weapon(invoker);
		if ( !weap ) return;
		A_WeaponOffset(0,32);
		invoker.bCharging = false;
		if ( self is 'UTPlayer' )
			UTPlayer(self).PlayAttacking3();
		DefaultAmmo(weap.Ammo1).rechargephase = (((weap.Ammo1.Amount>0)||!deathmatch)?0:30);
		DefaultAmmo(weap.Ammo1).rechargespeed = 1.1;
		A_StopSound(CHAN_WEAPONMISC);
		A_StartSound("dpistol/altfire",CHAN_WEAPON,CHANF_OVERLAP,Dampener.Active(self)?.4:1.);
		double mult = Amplifier.GetMult(self,int(invoker.ChargeSize*50)+50);
		invoker.FireEffect();
		int ulevel = sting_dpistol?0:invoker.upgradelevel;
		if ( weap.Ammo1.Amount < max(10,invoker.MainUse) ) ulevel = 0;
		Class<Actor> proj, part;
		switch ( ulevel )
		{
		case 0:
			proj = "DispersionAmmo";
			part = "ViewDispBurst1";
			UTMainHandler.DoFlash(self,Color(80,96,64,255),1);
			A_Overlay(PSP_FLASH,"Flash1");
			break;
		case 1:
			proj = "DAmmo2";
			part = "ViewDispBurst2";
			UTMainHandler.DoFlash(self,Color(80,64,255,96),1);
			A_Overlay(PSP_FLASH,"Flash2");
			break;
		case 2:
			proj = "DAmmo3";
			part = "ViewDispBurst3";
			UTMainHandler.DoFlash(self,Color(80,255,255,96),1);
			A_Overlay(PSP_FLASH,"Flash3");
			break;
		case 3:
			proj = "DAmmo4";
			part = "ViewDispBurst4";
			UTMainHandler.DoFlash(self,Color(80,255,160,64),1);
			A_Overlay(PSP_FLASH,"Flash4");
			break;
		default:
			proj = "DAmmo5";
			part = "ViewDispBurst5";
			UTMainHandler.DoFlash(self,Color(80,255,96,64),1);
			A_Overlay(PSP_FLASH,"Flash5");
			break;
		}
		A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
		A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
		double ss = 0.5+invoker.chargesize*0.3;
		if ( !Dampener.Active(self) ) A_AlertMonsters(gameinfo.gametype&GAME_Strife?120:0);
		int qs = int(1+invoker.chargesize*0.3);
		A_QuakeEx(qs,qs,qs,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-3*y-3*z);
		Actor p = Spawn(proj,origin);
		p.angle = angle;
		p.pitch = BulletSlope();
		p.vel = dt_Utility.Vec3FromAngle(p.angle,p.pitch)*p.speed;
		p.target = self;
		p.bAMBUSH = true;
		double scl = 0.5+invoker.chargesize*0.6;
		p.scale *= scl;
		DispersionAmmo(p).mult = scl*mult*1.1;
		int numpt = Random[DPistol](10,20);
		for ( int i=0; i<numpt; i++ )
		{
			let s = Spawn(part,origin);
			ViewASMDSpark(s).ofs = (10,-3,-3);
			s.target = self;
			ViewASMDSpark(s).vvel += (FRandom[ASMD](0.5,2.0),FRandom[ASMD](-1.5,1.5),FRandom[ASMD](-1.5,1.5));
		}
	}
	void UpdateSelectionOrder()
	{
		switch ( pendingupgrade )
		{
		case 0:
			SelectionOrder = default.SelectionOrder;
			break;
		case 1:
			SelectionOrder = 6400;
			break;
		case 2:
			SelectionOrder = 5000;
			break;
		case 3:
			SelectionOrder = 2700;
			break;
		case 4:
		default:
			SelectionOrder = 1800;
			break;
		}
	}
	action State A_DispCharge( statelabel next )
	{
		Weapon weap = Weapon(invoker);
		if ( !weap ) return ResolveState(null);
		if ( !(player.cmd.buttons&BT_ALTATTACK) ) return ResolveState(next);
		DefaultAmmo(weap.Ammo1).rechargephase = 0;
		A_WeaponOffset(FRandom[DPistol](-1,1)*1.2*invoker.chargesize,32+FRandom[DPistol](-1,1)*1.2*invoker.chargesize);
		A_SoundVolume(CHAN_WEAPONMISC,Dampener.Active(self)?.4:1.);
		if ( !Dampener.Active(self) ) A_AlertMonsters();
		invoker.chargesize += (2.-invoker.upgradelevel*0.15)/35.;
		invoker.count += 1./35.;
		if ( invoker.count < 0.3 ) return ResolveState(null);
		invoker.count = 0;
		if ( invoker.chargesize >= 5. ) return ResolveState(next);
		if ( !(sv_infiniteammo || (FindInventory('PowerInfiniteAmmo',true))) )
		{
			int use = invoker.ChargeUse;
			if ( weap.Ammo1.Amount < max(10,invoker.ChargeUse) ) use = 1;
			if ( weap.Ammo1.Amount < use ) return ResolveState(next);
			weap.Ammo1.Amount -= use;
		}
		return ResolveState(null);
	}
	Default
	{
		Tag "$T_DPISTOL";
		Inventory.PickupMessage "$I_DPISTOL";
		Weapon.UpSound "dpistol/select";
		Weapon.SlotNumber 1;
		Weapon.SelectionOrder 7700;
		Weapon.SlotPriority 1;
		Weapon.AmmoType "DefaultAmmo";
		Weapon.AmmoUse 1;
		Weapon.AmmoType2 "DefaultAmmo";
		Weapon.AmmoUse2 1;
		Weapon.AmmoGive 50;
		Weapon.MinSelectionAmmo1 10;
		Weapon.MinSelectionAmmo2 10;
		UTWeapon.DropAmmo 25;
		+WEAPON.WIMPY_WEAPON;
	}
	States
	{
	Spawn:
		DPIP A -1;
		Stop;
		DPIP B -1;
		Stop;
	Ready:
		DPS1 A 0
		{
			if ( invoker.upgradelevel == 0 ) return ResolveState("Ready1");
			else if ( invoker.upgradelevel == 1 ) return ResolveState("Ready2");
			else if ( invoker.upgradelevel == 2 ) return ResolveState("Ready3");
			else if ( invoker.upgradelevel == 3 ) return ResolveState("Ready4");
			return ResolveState("Ready5");
		}
	Ready1:
		DPS1 ABCDEFGHIJK 2 A_WeaponReady(WRF_NOFIRE);
		DPI1 A 5 A_WeaponReady(WRF_NOFIRE);
		Goto Idle;
	Ready2:
		DPS2 ABCDEFGHIJK 2 A_WeaponReady(WRF_NOFIRE);
		DPI2 A 5 A_WeaponReady(WRF_NOFIRE);
		Goto Idle;
	Ready3:
		DPS3 ABCDEFGHIJK 2 A_WeaponReady(WRF_NOFIRE);
		DPI3 A 5 A_WeaponReady(WRF_NOFIRE);
		Goto Idle;
	Ready4:
		DPS4 ABCDEFGHIJK 2 A_WeaponReady(WRF_NOFIRE);
		DPI4 A 5 A_WeaponReady(WRF_NOFIRE);
		Goto Idle;
	Ready5:
		DPS5 ABCDEFGHIJK 2 A_WeaponReady(WRF_NOFIRE);
		DPI5 A 5 A_WeaponReady(WRF_NOFIRE);
		Goto Idle;
	Dummy:
		TNT1 A 1
		{
			A_CheckReload();
			let weap = Weapon(invoker);
			if ( weap && (weap.Ammo1.Amount > 0) ) A_WeaponReady();
			else A_WeaponReady(WRF_NOFIRE);
		}
		TNT1 A 1
		{
			A_CheckReload();
			let weap = Weapon(invoker);
			// doing this on the first tic breaks the whole animation for some unexplainable reason
			if ( invoker.pendingupgrade > invoker.upgradelevel )
				player.SetPSprite(PSP_WEAPON,ResolveState("Upgrade"));
			else if ( weap && weap.Ammo1.Amount > 0 ) A_WeaponReady();
			else A_WeaponReady(WRF_NOFIRE);
		}
		Wait;
	Idle:
		#### # 0
		{
			A_Overlay(-9999,"Dummy");
			if ( invoker.upgradelevel == 0 ) return ResolveState("Idle1");
			else if ( invoker.upgradelevel == 1 ) return ResolveState("Idle2");
			else if ( invoker.upgradelevel == 2 ) return ResolveState("Idle3");
			else if ( invoker.upgradelevel == 3 ) return ResolveState("Idle4");
			return ResolveState("Idle5");
		}
	Idle1:
		DPI1 AB 30;
		Goto Idle1;
	Idle2:
		DPI2 AB 30;
		Goto Idle2;
	Idle3:
		DPI3 AB 30;
		Goto Idle3;
	Idle4:
		DPI4 AB 30;
		Goto Idle4;
	Idle5:
		DPI5 AB 30;
		Goto Idle5;
	Fire:
		#### # 0
		{
			A_Overlay(-9999,"Null");
			if ( invoker.upgradelevel == 0 ) return ResolveState("Fire1");
			else if ( invoker.upgradelevel == 1 ) return ResolveState("Fire2");
			else if ( invoker.upgradelevel == 2 ) return ResolveState("Fire3");
			else if ( invoker.upgradelevel == 3 ) return ResolveState("Fire4");
			return ResolveState("Fire5");
		}
	Fire1:
		#### # 3 A_DispFire();
		DPF1 ABC 3;
		DPI1 A 3 A_Refire("Fire1");
		Goto Idle;
	Fire2:
		#### # 3 A_DispFire();
		DPF2 ABC 4;
		DPI2 A 3 A_Refire("Fire2");
		Goto Idle;
	Fire3:
		#### # 3 A_DispFire();
		DPF3 ABC 6;
		DPI3 A 3 A_Refire("Fire3");
		Goto Idle;
	Fire4:
		#### # 3 A_DispFire();
		DPF4 ABC 8;
		DPI4 A 3 A_Refire("Fire4");
		Goto Idle;
	Fire5:
		#### # 3 A_DispFire();
		DPF5 ABC 10;
		DPI5 A 3 A_Refire("Fire5");
		Goto Idle;
	AltFire:
		#### # 0
		{
			invoker.chargesize = invoker.count = 0.;
			let weap = Weapon(invoker);
			if ( !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true) )
			{
				if ( weap.Ammo1.Amount < max(10,invoker.ChargeUse) )
					weap.Ammo1.Amount--;
				else weap.Ammo1.Amount -= invoker.ChargeUse;
			}
			invoker.bCharging = true;
			// need to make sure player does the repeat fire anim
			if ( self is 'UPlayer' )
				UPlayer(self).PlayAttacking();
			A_StartSound("dpistol/charge",CHAN_WEAPONMISC,CHANF_DEFAULT,Dampener.Active(self)?.4:1.);
			A_Overlay(-9999,"Null");
			if ( invoker.upgradelevel == 0 ) return ResolveState("AltFire1");
			else if ( invoker.upgradelevel == 1 ) return ResolveState("AltFire2");
			else if ( invoker.upgradelevel == 2 ) return ResolveState("AltFire3");
			else if ( invoker.upgradelevel == 3 ) return ResolveState("AltFire4");
			return ResolveState("AltFire5");
		}
	AltFire1:
		#### # 1 A_DispCharge(1);
		Wait;
	AltRelease1:
		#### # 3 A_DispAltFire();
		DPF1 ABC 6;
		DPI1 A 3;
		Goto Idle;
	AltFire2:
		#### # 1 A_DispCharge(1);
		Wait;
	AltRelease2:
		#### # 3 A_DispAltFire();
		DPF2 ABC 8;
		DPI2 A 3;
		Goto Idle;
	AltFire3:
		#### # 1 A_DispCharge(1);
		Wait;
	AltRelease3:
		#### # 3 A_DispAltFire();
		DPF3 ABC 9;
		DPI3 A 3;
		Goto Idle;
	AltFire4:
		#### # 1 A_DispCharge(1);
		Wait;
	AltRelease4:
		#### # 3 A_DispAltFire();
		DPF4 ABC 10;
		DPI4 A 3;
		Goto Idle;
	AltFire5:
		#### # 1 A_DispCharge(1);
		Wait;
	AltRelease5:
		#### # 3 A_DispAltFire();
		DPF5 ABC 12;
		DPI5 A 3;
		Goto Idle;
	Upgrade:
		#### # 1
		{
			A_Overlay(-9999,"Null");
			invoker.upgradelevel++;
			invoker.MainUse = invoker.upgradelevel+1;
			if ( invoker.upgradelevel > 1 ) invoker.MainUse++;
			invoker.UpdateSelectionOrder();
			if ( invoker.upgradelevel == 0 ) return ResolveState("Idle");
			else if ( invoker.upgradelevel == 1 ) return ResolveState("Upgrade1");
			else if ( invoker.upgradelevel == 2 ) return ResolveState("Upgrade2");
			else if ( invoker.upgradelevel == 3 ) return ResolveState("Upgrade3");
			return ResolveState("Upgrade4");
		}
	Upgrade1:
		#### # 0 A_StartSound("dpistol/up1",CHAN_WEAPONMISC,CHANF_DEFAULT,Dampener.Active(self)?.2:1.);
		DPU1 ABCD 9;
		DPI2 A 4 A_JumpIf(invoker.pendingupgrade>invoker.upgradelevel,"Upgrade");
		Goto Idle;
	Upgrade2:
		#### # 0 A_StartSound("dpistol/up2",CHAN_WEAPONMISC,CHANF_DEFAULT,Dampener.Active(self)?.2:1.);
		DPU2 ABCDEFGHI 9;
		DPI3 A 4 A_JumpIf(invoker.pendingupgrade>invoker.upgradelevel,"Upgrade");
		Goto Idle;
	Upgrade3:
		#### # 0 A_StartSound("dpistol/up3",CHAN_WEAPONMISC,CHANF_DEFAULT,Dampener.Active(self)?.2:1.);
		DPU3 ABCDEFGHI 9;
		DPI4 A 4 A_JumpIf(invoker.pendingupgrade>invoker.upgradelevel,"Upgrade");
		Goto Idle;
	Upgrade4:
		#### # 0 A_StartSound("dpistol/up4",CHAN_WEAPONMISC,CHANF_DEFAULT,Dampener.Active(self)?.2:1.);
		DPU4 ABCDEFGHI 9;
		DPI5 A 4 A_JumpIf(invoker.pendingupgrade>invoker.upgradelevel,"Upgrade");
		Goto Idle;
	Select:
		DPS1 A 1 A_Raise(int.max);
		Wait;
	Deselect:
		#### # 0
		{
			A_Overlay(-9999,"Null");
			if ( invoker.upgradelevel == 0 ) return ResolveState("Deselect1");
			else if ( invoker.upgradelevel == 1 ) return ResolveState("Deselect2");
			else if ( invoker.upgradelevel == 2 ) return ResolveState("Deselect3");
			else if ( invoker.upgradelevel == 3 ) return ResolveState("Deselect4");
			return ResolveState("Deselect5");
		}
	Deselect1:
		DPD1 ABCDE 2;
		DPD1 E 1 A_Lower(int.max);
		Wait;
	Deselect2:
		DPD2 ABCDE 2;
		DPD2 E 1 A_Lower(int.max);
		Wait;
	Deselect3:
		DPD3 ABCDE 2;
		DPD3 E 1 A_Lower(int.max);
		Wait;
	Deselect4:
		DPD4 ABCDE 2;
		DPD4 E 1 A_Lower(int.max);
		Wait;
	Deselect5:
		DPD5 ABCDE 2;
		DPD5 E 1 A_Lower(int.max);
		Wait;
	Flash1:
		DPFF A 2 Bright
		{
			let l = Spawn("DispLight1",pos);
			l.target = self;
		}
		Stop;
	Flash2:
		DPFF B 2 Bright
		{
			let l = Spawn("DispLight2",pos);
			l.target = self;
		}
		Stop;
	Flash3:
		DPFF C 2 Bright
		{
			let l = Spawn("DispLight3",pos);
			l.target = self;
		}
		Stop;
	Flash4:
		DPFF D 2 Bright
		{
			let l = Spawn("DispLight4",pos);
			l.target = self;
		}
		Stop;
	Flash5:
		DPFF E 2 Bright
		{
			let l = Spawn("DispLight5",pos);
			l.target = self;
		}
		Stop;
	}
}
