stinger_m/zscript/razorjack.zsc
Marisa Kirisame 6984c2819d Rifle implemented.
Misc. adjustments to Biorifle and Razorjack.
2019-09-11 23:19:55 +02:00

315 lines
7.8 KiB
Text

Class RazorAmmo : Ammo
{
Default
{
Tag "$T_RIPPERAMMO";
Inventory.Icon "I_RazorA";
Inventory.PickupMessage "$I_RIPPERAMMO";
Inventory.Amount 25;
Inventory.MaxAmount 75;
Ammo.BackpackAmount 20;
Ammo.BackpackMaxAmount 150;
Ammo.DropAmount 15;
}
States
{
Spawn:
BHOP A 8 A_CheckProximity(1,"PlayerPawn",80,1,CPXF_ANCESTOR|CPXF_CHECKSIGHT);
Wait;
BHOP AA 16;
BHOP B 8 A_CheckProximity(1,"PlayerPawn",80,0,CPXF_ANCESTOR|CPXF_CHECKSIGHT|CPXF_EXACT);
Goto Spawn+3;
BHOP BB 16;
Goto Spawn;
}
}
Class RazorBlade : Actor
{
Vector3 gvel, accel;
double oldgangle, gangle, oldgpitch, gpitch;
Default
{
Radius 2;
Height 2;
Speed 25;
DamageFunction (int((30+special1*5)*((DamageType=='Decapitated')?3.5:1.0)));
DamageType 'Shredded';
Obituary "$O_RAZORJACK";
BounceType "Hexen";
ReactionTime 5;
BounceFactor 1.0;
WallBounceFactor 1.0;
PROJECTILE;
+USEBOUNCESTATE;
+SKYEXPLODE;
+CANBOUNCEWATER;
+NODAMAGETHRUST;
+DONTBOUNCEONSHOOTABLES;
+ROLLSPRITE;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
let t = Spawn("RazorBladeTrail",pos);
t.target = self;
frame = special1;
if ( special1 > 0 )
{
vel *= 1.+.06+special1;
A_PlaySound("ripper/hum",CHAN_VOICE,1.0,true,3.0,pitch:3.125+special1*.2);
}
else A_PlaySound("ripper/hum",CHAN_VOICE,1.0,true,3.0,pitch:3.125);
Vector3 dir = vel.unit();
A_SetAngle(atan2(dir.y,dir.x));
A_SetPitch(asin(-dir.z));
frame = 0;
gvel = vel;
oldgangle = gangle = angle;
oldgpitch = gpitch = pitch;
}
override int SpecialMissileHit( Actor victim )
{
if ( pos.z > victim.pos.z+victim.height*0.81 ) DamageType = 'Decapitated';
return -1;
}
override int DoSpecialDamage( Actor target, int damage, Name damagetype )
{
if ( !target.bNOBLOOD )
{
target.SpawnBlood(pos,AngleTo(target),damage);
A_PlaySound("ripper/flesh");
A_AlertMonsters();
}
UTMainHandler.DoKnockback(target,vel.unit(),15000);
return damage;
}
void A_RazorAltOrient()
{
if ( !bAMBUSH || !target || !target.player || (target.Health <= 0) ) return;
if ( sting_razoraim )
{
FLineTraceData d;
target.LineTrace(target.angle,10000,target.pitch,0,target.player.viewheight,data:d);
Vector3 SeekingDir = level.Vec3Diff(pos,d.HitLocation).unit();
double MagnitudeVel = Vel.length();
SeekingDir = (SeekingDir*0.1*MagnitudeVel+Vel).unit();
vel = MagnitudeVel * SeekingDir;
accel = SeekingDir * 25.;
vel += accel/TICRATE;
vel = vel.unit()*clamp(MagnitudeVel,10,15);
}
else
{
double dangle, dpitch;
dangle = deltaangle(oldgangle,target.angle);
dpitch = deltaangle(oldgpitch,target.pitch);
gangle += dangle;
gpitch += dpitch;
vel += (cos(gangle)*cos(gpitch),sin(gangle)*cos(gpitch),-sin(gpitch))*15./TICRATE;
double spd = vel.length();
vel = vel*clamp(spd,10,15)/spd;
gvel = vel;
oldgangle = target.angle;
oldgpitch = target.pitch;
}
Vector3 dir = vel.unit();
A_SetAngle(atan2(dir.y,dir.x));
A_SetPitch(asin(-dir.z));
}
action void A_RazorHit()
{
A_PlaySound("ripper/hit");
A_AlertMonsters();
A_SprayDecal("WallCrack",-20);
int numpt = Random[Ripper](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[Ripper](-.8,.8),FRandom[Ripper](-.8,.8),FRandom[Ripper](-.8,.8))).unit()*FRandom[Ripper](0.1,1.2);
let s = Spawn("UTSmoke",pos);
s.vel = pvel;
s.SetShade(Color(1,1,1)*Random[Ripper](128,192));
}
numpt = Random[Ripper](4,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Ripper](-1,1),FRandom[Ripper](-1,1),FRandom[Ripper](-1,1)).unit()*FRandom[Ripper](2,8);
let s = Spawn("UTSpark",pos);
s.vel = pvel;
}
numpt = Random[Ripper](4,8);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Ripper](-1,1),FRandom[Ripper](-1,1),FRandom[Ripper](-1,1)).unit()*FRandom[Ripper](2,8);
let s = Spawn("UTChip",pos);
s.vel = pvel;
}
}
States
{
Spawn:
RAZB # 1 A_RazorAltOrient();
Wait;
Bounce:
RAZB # 0
{
bHITOWNER = true; // technically the Unreal version sets this 0.2 seconds after being fired, but this works better
Vector3 dir = vel.unit();
A_SetAngle(atan2(dir.y,dir.x));
A_SetPitch(asin(-dir.z));
A_RazorHit();
A_CountDown();
}
Goto Spawn;
Death:
TNT1 A 1 A_StopSound(CHAN_VOICE);
Stop;
}
}
Class RazorBladeTrail : Actor
{
Default
{
RenderStyle "Add";
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
+NOTELEPORT;
Radius 0.1;
Height 0;
}
override void Tick()
{
if ( !target || target.InStateSequence(target.CurState,target.ResolveState("Death")) )
{
A_RemoveLight('RazorLight');
Destroy();
return;
}
SetOrigin(target.pos,true);
angle = target.angle;
pitch = target.pitch;
roll = target.roll;
alpha = min(target.vel.length()/target.speed,1.);
A_AttachLight('RazorLight',DynamicLight.PointLight,Color(2,0,3)*int(80*alpha),80,80);
}
States
{
Spawn:
RAZB A -1 Bright;
Stop;
}
}
Class Razorjack : UnrealWeapon
{
action void A_RazorFire( bool bAlt = false )
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
if ( self is 'UTPlayer' )
UTPlayer(self).PlayAttacking3();
A_PlaySound("ripper/fire",CHAN_WEAPON,pitch:bAlt?1.:(1.+invoker.special1*.1));
invoker.FireEffect();
UTMainHandler.DoFlash(self,Color(16,255,0,255),1);
A_AlertMonsters();
A_QuakeEx(1,1,1,5,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.08);
if ( bAlt ) UTMainHandler.DoSwing(self,(FRandom[Ripper](-0.6,-0.3),FRandom[Ripper](0.2,0.4)),1,-0.3,2,SWING_Spring,2,2);
else UTMainHandler.DoSwing(self,(FRandom[Ripper](-0.3,0.3),FRandom[Ripper](0.2,0.6)),1,-0.3,2,SWING_Spring,2,2);
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = Vec2OffsetZ(0,0,player.viewz);
if ( bAlt ) origin = level.Vec3Offset(origin,x*10-y*4-z*5);
else origin = level.Vec3Offset(origin,x*10-z*9);
Actor p;
p = Spawn("RazorBlade",origin);
if ( bAlt )
{
p.roll = 70;
p.bAMBUSH = true;
}
else p.special1 = invoker.special1;
p.angle = angle;
p.pitch = BulletSlope();
p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed;
p.target = self;
}
Default
{
Tag "$T_RAZORJACK";
Inventory.PickupMessage "$I_RAZORJACK";
Weapon.UpSound "ripper/select";
Weapon.SlotNumber 7;
Weapon.SelectionOrder 7;
Weapon.AmmoType "RazorAmmo";
Weapon.AmmoUse 1;
Weapon.AmmoType2 "RazorAmmo";
Weapon.AmmoUse2 1;
Weapon.AmmoGive 15;
UTWeapon.DropAmmo 10;
}
States
{
Spawn:
RZRP A -1;
Stop;
RZRP B -1;
Stop;
Select:
RZRS A 1 A_Raise(int.max);
Wait;
Ready:
RZRS ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 A_WeaponReady(WRF_NOFIRE);
RZS2 ABCD 1 A_WeaponReady(WRF_NOFIRE);
Idle:
RZRI ABCDEFGHIJKLMNOPQRSUVWXYZ 2
{
A_CheckReload();
A_WeaponReady();
}
RZI2 ABCDE 2
{
A_CheckReload();
A_WeaponReady();
}
Loop;
Fire:
RZRI A 0
{
invoker.special1 = 0;
return A_JumpIf(sting_razor,"ChargeUp");
}
Release:
RZRF A 0 A_RazorFire();
RZRF ABCDEFGH 2;
Goto Idle;
ChargeUp:
RZRI ABCDEFGHIJKLMNOPQRSUVWXYZ 1 A_JumpIf(!(player.cmd.buttons&BT_ATTACK),"Release");
RZI2 ABCDE 1 A_JumpIf(!(player.cmd.buttons&BT_ATTACK),"Release");
RZRI A 0 { invoker.special1 = 1; }
RZRI ACEGIKMOQSVXZ 1 A_JumpIf(!(player.cmd.buttons&BT_ATTACK),"Release");
RZI2 BD 1 A_JumpIf(!(player.cmd.buttons&BT_ATTACK),"Release");
RZRI A 0 { invoker.special1 = 2; }
RZRI ADGJMPSWZ 1 A_JumpIf(!(player.cmd.buttons&BT_ATTACK),"Release");
RZI2 C 1 A_JumpIf(!(player.cmd.buttons&BT_ATTACK),"Release");
RZRI A 0 { invoker.special1 = 3; }
Goto Release;
AltFire:
RZRA ABCDEFGHIJKL 1;
AltHold:
RZRA M 0 A_RazorFire(true);
RZRA MNOP 4;
RZRA Q 0 A_ReFire("AltHold");
RZRA QRSTU 2;
Goto Idle;
Deselect:
RZRD ABCDEF 1;
RZRD F 1 A_Lower(int.max);
Wait;
}
}