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= (d.HitActor.pos.z+d.HitActor.height*0.8) ) dmg = d.HitActor.DamageMobj(invoker,self,dmg*2,'Decapitated',DMG_USEANGLE,atan2(d.HitDir.y,d.HitDir.x)); else dmg = d.HitActor.DamageMobj(invoker,self,dmg,'slashed',DMG_USEANGLE,atan2(d.HitDir.y,d.HitDir.x)); 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); } invoker.sawcnt += 0.1; } override void DetachFromOwner() { if ( Owner ) Owner.A_StopSound(CHAN_6); A_PlaySound("chainsaw/lower",CHAN_6); Super.DetachFromOwner(); } action void A_Vibrate( bool bAlt = false ) { invoker.sawcnt = 0; A_AlertMonsters(); if ( bAlt ) A_QuakeEx(1,1,1,3,0,1,"",QF_RELATIVE,rollIntensity:0.4); else A_QuakeEx(0,0,0,2,0,1,"",QF_RELATIVE,rollIntensity:0.2); UTMainHandler.DoSwing(self,(FRandom[Chainsaw](-1,1),FRandom[Chainsaw](-1,1)),0.25,-0.1,2,SWING_Spring); if ( bAlt || Random[Chainsaw](0,2) ) return; Vector3 x, y, z; [x, y, z] = Matrix4.GetAxes(pitch,angle,roll); Vector3 origin = (pos.x,pos.y,player.viewz)+5.0*x+1.0*y-3.0*z; for ( int i=0; i<5; i++ ) { let s = Spawn("UTViewSmoke",origin); UTViewSmoke(s).ofs = (5,1,-3); s.scale *= 1.2; s.alpha *= 0.2; s.SetShade("202020"); s.target = self; UTViewSmoke(s).vvel += (0,-0.2,0); } } 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_Vibrate(); A_WeaponReady(WRF_NOFIRE); } Idle: CSWI A 0 A_PlaySound("chainsaw/idle",CHAN_6,looping:true); CSWI ABCDEFGHIJ 1 { A_Vibrate(); A_WeaponReady(); } Goto Idle+1; Fire: CSWJ A 1 A_PlaySound("chainsaw/fire",CHAN_6,looping:true); CSWJ BCDEF 1 A_Vibrate(); 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_Vibrate(); Goto Idle; AltFire: CSWA A 0 { A_PlaySound("chainsaw/fire",CHAN_6); UTMainHandler.DoSwing(self,(FRandom[Chainsaw](-0.8,-1.2),FRandom[Chainsaw](-0.4,-0.7)),0,1,5,SWING_Spring,6,3); } CSWA ABCDE 2 A_Vibrate(true); CSWA F 2 { A_Overlay(PSP_WEAPON+1,"AltFireSwipes"); UTMainHandler.DoSwing(self,(FRandom[Chainsaw](0.8,1.2),0),0,2,6,SWING_Spring,1,3); } CSWA GHIJ 2; CSWA K 2 A_Vibrate(true); CSWA K 0 A_PlaySound("chainsaw/idle",CHAN_6,looping:true); Goto Ready; AltFireSwipes: TNT1 A 1 A_SawSwipe(true); TNT1 AAAAAAAAA 1 A_SawSwipe(); Stop; Deselect: CSWD A 0 A_PlaySound("chainsaw/lower",CHAN_6); CSWD ABCDEF 1; CSWD F 1 A_Lower(int.max); Wait; } }