flak_m/zscript/chainsaw.zsc
Marisa Kirisame 07915ea7c2 Added first person visual effects to all weapons.
Added "instant rocket" mode to RL, toggleable with reload button.
Various adjustments to offsets and scales.
Fixed a bug where other armors wouldn't absorb damage if at least one of them is depleted.
Reduced armor bonus pickup amount to 1, and made it absorb more damage the more you have, up to a 75% cap at max amount.
Tweaked vibration on the Chainsaw.
More particles for rockets and flak slugs.
Reduced delay for rocket launcher refire.
Fixed Pulse balls having no XY billboarding.
Tweaked Pulse bolt visual effects.
Reduced shake of Shock Rifle and Enhanced Shock Rifle to more bearable levels.
Fixed clipping on the Ripper after offsets were changed.
2018-06-11 18:25:09 +02:00

253 lines
6.8 KiB
Text

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](20,30);
dmg = d.HitActor.DamageMobj(invoker,self,dmg,'slashed',DMG_USEANGLE,atan2(d.HitDir.y,d.HitDir.x));
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,60);
if ( d.HitLocation.z >= (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);
}
}
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 )
{
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);
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);
CSWA ABCDEFG 2 A_Vibrate(true);
CSWA H 2 A_SawSwipe();
CSWA IJK 2 A_Vibrate(true);
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 1;
CSWD F 1 A_Lower(int.max);
Wait;
}
}