341 lines
7.9 KiB
Text
341 lines
7.9 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 15;
|
|
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*10)*((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;
|
|
+NOFRICTION;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
let t = Spawn("RazorBladeTrail",pos);
|
|
t.target = self;
|
|
frame = special1;
|
|
if ( special1 > 0 )
|
|
{
|
|
vel *= 1.+.06+special1;
|
|
A_StartSound("razorjack/hum",CHAN_VOICE,CHANF_LOOPING,1.,3.,3.125+special1*.2);
|
|
}
|
|
else A_StartSound("razorjack/hum",CHAN_VOICE,CHANF_LOOPING,1.,3.,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_StartSound("razorjack/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 += dt_Utility.Vec3FromAngle(gangle,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_StartSound("razorjack/hit");
|
|
A_AlertMonsters();
|
|
A_SprayDecal("WallCrack",-20);
|
|
int numpt = Random[Ripper](5,10);
|
|
Vector3 x = dt_Utility.Vec3FromAngle(angle,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 0 A_RazorHit();
|
|
XDeath:
|
|
TNT1 A 1 A_StopSound(CHAN_VOICE);
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class RazorLight : DynamicLight
|
|
{
|
|
Default
|
|
{
|
|
Args 160, 0, 240, 40;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !target )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
Args[0] = int(160*target.alpha);
|
|
Args[2] = int(240*target.alpha);
|
|
SetOrigin(target.pos,true);
|
|
}
|
|
}
|
|
|
|
Class RazorBladeTrail : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
+NOTELEPORT;
|
|
Radius 0.1;
|
|
Height 0;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
let l = Spawn("RazorLight",pos);
|
|
l.target = self;
|
|
}
|
|
override void Tick()
|
|
{
|
|
if ( !target || target.InStateSequence(target.CurState,target.ResolveState("Death")) )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
SetOrigin(target.pos,true);
|
|
angle = target.angle;
|
|
pitch = target.pitch;
|
|
roll = target.roll;
|
|
alpha = min(target.vel.length()/target.speed,1.);
|
|
}
|
|
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_StartSound("razorjack/fire",CHAN_WEAPON,CHANF_OVERLAP,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);
|
|
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 = dt_Utility.Vec3FromAngle(p.angle,p.pitch)*p.speed;
|
|
p.target = self;
|
|
}
|
|
Default
|
|
{
|
|
Tag "$T_RAZORJACK";
|
|
Inventory.PickupMessage "$I_RAZORJACK";
|
|
Weapon.UpSound "razorjack/select";
|
|
Weapon.SlotNumber 7;
|
|
Weapon.SelectionOrder 1500;
|
|
Weapon.SlotPriority 1;
|
|
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;
|
|
}
|
|
}
|