Class Tier1Weapon : RandomSpawner2 replaces Chainsaw
{
	Default
	{
		DropItem "UTChainsaw", 255, 1;
		DropItem "Enforcer", 255, 1;
	}
}

Class SawImpact : Actor
{
	Default
	{
		Radius 0.1;
		Height 0;
		+NOGRAVITY;
		+NOCLIP;
		+DONTSPLASH;
	}
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		A_SprayDecal("WallCrack",20);
		int numpt = Random[Chainsaw](5,10);
		Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
		for ( int i=0; i<numpt; i++ )
		{
			Vector3 pvel = (-x+(FRandom[Chainsaw](-.8,.8),FRandom[Chainsaw](-.8,.8),FRandom[Chainsaw](-.8,.8))).unit()*FRandom[Chainsaw](0.1,1.2);
			let s = Spawn("UTSmoke",pos);
			s.vel = pvel;
			s.SetShade(Color(1,1,1)*Random[Chainsaw](128,192));
		}
		numpt = Random[Chainsaw](4,12);
		for ( int i=0; i<numpt; i++ )
		{
			Vector3 pvel = (FRandom[Chainsaw](-1,1),FRandom[Chainsaw](-1,1),FRandom[Chainsaw](-1,1)).unit()*FRandom[Chainsaw](2,8);
			let s = Spawn("UTSpark",pos);
			s.vel = pvel;
		}
		numpt = Random[Chainsaw](4,8);
		for ( int i=0; i<numpt; i++ )
		{
			Vector3 pvel = (FRandom[Chainsaw](-1,1),FRandom[Chainsaw](-1,1),FRandom[Chainsaw](-1,1)).unit()*FRandom[Chainsaw](2,8);
			let s = Spawn("UTChip",pos);
			s.vel = pvel;
		}
		Destroy();
	}
}

Class UTChainsaw : UTWeapon
{
	double sawcnt;

	action void A_SawHit()
	{
		A_QuakeEx(2,2,2,2,0,1,"",QF_RELATIVE,rollIntensity:0.15);
		invoker.sawcnt += 1./TICRATE;
		if ( invoker.sawcnt < 0.15 ) return;
		invoker.sawcnt = 0;
		invoker.FireEffect();
		A_AlertMonsters();
		Vector3 x, y, z;
		[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
		Vector3 origin = (pos.x,pos.y,player.viewz)+10.0*x-4.0*z;
		FLineTraceData d;
		LineTrace(angle,90,BulletSlope(),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
		if ( d.HitType == TRACE_HitActor )
		{
			int dmg = Random[Chainsaw](16,22);
			dmg = d.HitActor.DamageMobj(invoker,self,dmg,'slashed');
			d.HitActor.vel -= x*(500/d.HitActor.mass);
			vel += x*(100/mass);
			if ( d.HitActor.player ) d.HitActor.A_QuakeEx(5,5,5,6,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.25);
			if ( d.HitActor.bNOBLOOD )
			{
				let p = Spawn("SawImpact",d.HitLocation-d.HitDir*4);
				p.angle = atan2(d.HitDir.y,d.HitDir.x);
				p.pitch = asin(-d.HitDir.z);
			}
			else
			{
				d.HitActor.TraceBleed(dmg,invoker);
				d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
			}
		}
		else if ( d.HitType != TRACE_HitNone )
		{
			let p = Spawn("SawImpact",d.HitLocation-d.HitDir*4);
			p.angle = atan2(d.HitDir.y,d.HitDir.x);
			p.pitch = asin(-d.HitDir.z);
			if ( d.HitType == TRACE_HitWall ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation-d.HitDir*4);
		}
	}
	action void A_SawSwipe()
	{
		A_QuakeEx(2,2,2,3,0,1,"",QF_RELATIVE,rollIntensity:0.15);
		invoker.FireEffect();
		A_AlertMonsters();
		Vector3 x, y, z;
		[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
		Vector3 origin = (pos.x,pos.y,player.viewz)+10.0*x-2.0*z;
		FLineTraceData d;
		LineTrace(angle,90,BulletSlope(),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
		if ( d.HitType == TRACE_HitActor )
		{
			int dmg = Random[Chainsaw](50,55);
			if ( d.HitLocation.z >= (d.HitActor.pos.z+d.HitActor.height*0.8) )
				dmg = d.HitActor.DamageMobj(invoker,self,dmg*2,'Decapitated');
			else dmg = d.HitActor.DamageMobj(invoker,self,dmg,'slashed');
			d.HitActor.vel = -y*(1200/d.HitActor.mass);
			vel += x*(100/mass);
			if ( d.HitActor.player ) d.HitActor.A_QuakeEx(5,5,5,6,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.25);
			if ( d.HitActor.bNOBLOOD )
			{
				let p = Spawn("SawImpact",d.HitLocation-d.HitDir*4);
				p.angle = atan2(d.HitDir.y,d.HitDir.x);
				p.pitch = asin(-d.HitDir.z);
			}
			else
			{
				d.HitActor.TraceBleed(dmg,invoker);
				d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
			}
		}
		else if ( d.HitType != TRACE_HitNone )
		{
			let p = Spawn("SawImpact",d.HitLocation-d.HitDir*4);
			p.angle = atan2(d.HitDir.y,d.HitDir.x);
			p.pitch = asin(-d.HitDir.z);
			if ( d.HitType == TRACE_HitWall ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation-d.HitDir*4);
		}
	}
	Default
	{
		Tag "Chainsaw";
		Obituary "%k ripped into %o with a blood soaked Chainsaw.";
		Inventory.PickupMessage "It's been twenty five years since I've seen one of these.";	// was five years in UT99
		Weapon.UpSound "chainsaw/select";
		Weapon.SlotNumber 1;
		Weapon.SelectionOrder 9;
		+WEAPON.MELEEWEAPON;
		+FORCEPAIN;
	}
	States
	{
	Spawn:
		CSWP A -1;
		Stop;
		CSWP B -1;
		Stop;
	Select:
		CSWS A 1 A_Raise(int.max);
		Wait;
	Ready:
		CSWS ABCDEFGHIJLMNO 1
		{
			A_AlertMonsters();
			A_QuakeEx(1,1,1,2,0,1,"",QF_RELATIVE,rollIntensity:0.1);
		}
	Idle:
		CSWI A 0 A_PlaySound("chainsaw/idle",CHAN_6,looping:true);
		CSWI ABCDEFGHIJ 1
		{
			A_AlertMonsters();
			A_WeaponReady();
			A_QuakeEx(1,1,1,2,0,1,"",QF_RELATIVE,rollIntensity:0.1);
		}
		Goto Idle+1;
	Fire:
		CSWJ A 1 A_PlaySound("chainsaw/fire",CHAN_6,looping:true);
		CSWJ BCDEF 1
		{
			A_AlertMonsters();
			A_QuakeEx(1,1,1,2,0,1,"",QF_RELATIVE,rollIntensity:0.1);
		}
	Hold:
		CSWJ G 1 A_SawHit();
		CSWJ H 0 A_Refire(1);
		Goto Release;
		CSWJ H 1 A_SawHit();
		CSWJ I 0 A_Refire(1);
		Goto Release;
		CSWJ I 1 A_SawHit();
		CSWJ J 0 A_Refire(1);
		Goto Release;
		CSWJ J 1 A_SawHit();
		CSWJ K 0 A_Refire(1);
		Goto Release;
		CSWJ K 1 A_SawHit();
		CSWJ L 0 A_Refire(1);
		Goto Release;
		CSWJ L 1 A_SawHit();
		CSWJ M 0 A_Refire(1);
		Goto Release;
		CSWJ M 1 A_SawHit();
		CSWJ N 0 A_Refire(1);
		Goto Release;
		CSWJ N 1 A_SawHit();
		CSWJ O 0 A_Refire(1);
		Goto Release;
		CSWJ O 1 A_SawHit();
		CSWJ P 0 A_Refire(1);
		Goto Release;
		CSWJ P 1 A_SawHit();
		CSWJ Q 0 A_Refire(1);
		Goto Release;
		CSWJ Q 1 A_SawHit();
		CSWJ R 0 A_Refire(1);
		Goto Release;
		CSWJ R 1 A_SawHit();
		CSWJ S 0 A_Refire(1);
		Goto Release;
		CSWJ S 1 A_SawHit();
		CSWJ G 0 A_Refire("Hold");
	Release:
		CSWJ FEDCBA 1
		{
			A_AlertMonsters();
			A_QuakeEx(1,1,1,2,0,1,"",QF_RELATIVE,rollIntensity:0.1);
		}
		Goto Idle;
	AltFire:
		CSWA A 0 A_PlaySound("chainsaw/fire",CHAN_6);
		CSWA ABCDEFG 2
		{
			A_AlertMonsters();
			A_QuakeEx(2,2,2,3,0,1,"",QF_RELATIVE,rollIntensity:0.15);
		}
		CSWA H 2 A_SawSwipe();
		CSWA IJK 2
		{
			A_AlertMonsters();
			A_QuakeEx(2,2,2,3,0,1,"",QF_RELATIVE,rollIntensity:0.15);
		}
		CSWA K 0 A_PlaySound("chainsaw/idle",CHAN_6,looping:true);
		Goto Ready;
	Deselect:
		CSWD A 0 A_PlaySound("chainsaw/lower",CHAN_6);
		CSWD ABCDEF 2;
		CSWD F 1 A_Lower(int.max);
		Wait;
	}
}
