flak_m/zscript/shockrifle.zsc

486 lines
10 KiB
Text

Class ShockAmmo : Ammo
{
Default
{
Tag "Flak Shells";
Inventory.Icon "I_ASMD";
Inventory.PickupMessage "You picked up a Shock Core.";
Inventory.PickupSound "ut/ammo";
Inventory.Amount 10;
Inventory.MaxAmount 50;
Ammo.BackpackAmount 50;
Ammo.BackpackMaxAmount 100;
Ammo.DropAmount 10;
}
States
{
Spawn:
SHOA A -1;
Stop;
}
}
Class ShockBeamTracer : LineTracer
{
Actor owner, ignore;
override ETraceStatus TraceCallback()
{
if ( Results.HitType == TRACE_HitActor )
{
if ( (Results.HitActor == owner) || (Results.HitActor == ignore) ) return TRACE_Skip;
if ( Results.HitActor.bSHOOTABLE || Results.HitActor is 'ShockHitbox' ) return TRACE_Stop;
return TRACE_Skip;
}
else if ( (Results.HitType == TRACE_HitWall) && (Results.Tier == TIER_Middle) )
{
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&Line.ML_BlockHitscan) )
return TRACE_Stop;
return TRACE_Skip;
}
return TRACE_Stop;
}
}
Class ShockRifleWave : Actor
{
Default
{
RenderStyle "Add";
Radius 0.1;
Height 0;
Scale 0.7;
+NOBLOCKMAP;
+NOGRAVITY;
+DONTSPLASH;
}
override void Tick()
{
Super.Tick();
alpha -= 1/50.;
}
States
{
Spawn:
SWAV A 50 Bright;
SWAV B 0 Bright;
Stop;
}
}
Class ShockBeamRing : Actor
{
Default
{
RenderStyle "Add";
Radius 0.1;
Height 0;
Scale 0.5;
ReactionTime 18;
+NOBLOCKMAP;
+NOGRAVITY;
+DONTSPLASH;
}
override void Tick()
{
Super.Tick();
alpha -= 1./ReactionTime;
}
States
{
Spawn:
SRNG ABCDEFGHI 2 Bright;
Stop;
}
}
Class ShockBlastRing : ShockBeamRing
{
Default
{
Scale 3.0;
ReactionTime 45;
}
States
{
Spawn:
SRNG ABCDEFGHI 5 Bright;
Stop;
}
}
Class ShockBeam : Actor
{
ShockBeamTracer t;
Vector3 tracedir;
bool moving;
double totaldist;
Default
{
Obituary "%k inflicted mortal damage upon %o with the Shock Rifle";
RenderStyle "Add";
Radius 0.1;
Height 0;
Scale 0.4;
DamageFunction Random[ASMD](30,45);
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
+FORCEXYBILLBOARD;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
t = new("ShockBeamTracer");
t.owner = target;
t.ignore = self;
moving = true;
}
override void Tick()
{
Super.Tick();
if ( !moving ) return;
// step trace
tracedir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
t.Trace(pos,cursector,tracedir,1000,0);
totaldist += t.Results.Distance;
// spawn particles
for ( int i=0; i<t.Results.Distance; i+=80 )
Spawn("ShockBeamLight",Vec3Offset(tracedir.x*i,tracedir.y*i,tracedir.z*i));
for ( int i=0; i<t.Results.Distance; i+=8 )
{
A_SpawnParticle("F0A0FF",SPF_FULLBRIGHT,15,2,0,tracedir.x*i,tracedir.y*i,tracedir.z*i,FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),startalphaf:1,sizestep:-.1);
A_SpawnParticle("A040FF",SPF_FULLBRIGHT,20,4,0,tracedir.x*i,tracedir.y*i,tracedir.z*i,FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),startalphaf:.75,sizestep:-.1);
A_SpawnParticle("8020FF",SPF_FULLBRIGHT,25,6,0,tracedir.x*i,tracedir.y*i,tracedir.z*i,FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),startalphaf:.5,sizestep:-.1);
A_SpawnParticle("602080",SPF_FULLBRIGHT,30,8,0,tracedir.x*i,tracedir.y*i,tracedir.z*i,FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),startalphaf:.25,sizestep:-.1);
}
if ( totaldist >= 10000.0 )
{
// reposition and explode on air
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,true);
A_SprayDecal("ShockMark",16);
ExplodeMissile(t.Results.HitLine,null);
moving = false;
let r = Spawn("ShockBeamRing",pos);
r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
r.pitch = asin(-t.Results.HitVector.z);
}
else if ( t.Results.HitType == TRACE_HitNone )
{
// reposition
SetOrigin(t.Results.HitPos+t.Results.HitVector,true);
angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
pitch = asin(-t.Results.HitVector.z);
}
else if ( t.Results.HitType == TRACE_HitActor )
{
// reposition and explode on actor
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,true);
ExplodeMissile(null,t.Results.HitActor);
if ( t.Results.HitActor is 'ShockHitbox' )
{
if ( target ) target.TakeInventory('ShockAmmo',2);
let b = t.Results.HitActor.target;
b.ExplodeMissile(null,self);
b.A_Explode(Random[ASMD](150,160),250);
b.A_QuakeEx(6,6,6,60,0,1200,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.2);
b.A_SprayDecal("BigShockMark1",100);
b.A_SprayDecal("BigShockMark2",100);
Spawn("ShockRifleWave",b.pos);
Spawn("ShockBlastLight",b.pos);
let r = Spawn("ShockBlastRing",b.pos);
r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
r.pitch = asin(-t.Results.HitVector.z);
A_PlaySound("shock/blast",CHAN_WEAPON,attenuation:0.5);
}
else
{
t.Results.HitActor.DamageMobj(self,target,Random[ASMD](35,50),'jolted');
let r = Spawn("ShockBeamRing",pos);
r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
r.pitch = asin(-t.Results.HitVector.z);
}
moving = false;
}
else
{
// reposition and explode on wall
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,true);
A_SprayDecal("ShockMark",16);
ExplodeMissile(t.Results.HitLine,null);
moving = false;
Vector3 HitNormal = t.Results.HitVector;
if ( t.Results.HitType == TRACE_HitWall )
{
t.Results.HitLine.RemoteActivate(target,t.Results.Side,SPAC_Impact,pos);
// calculate normal
HitNormal = (-t.Results.HitLine.delta.y,t.Results.HitLine.delta.x,0).unit();
if ( t.Results.Side == 1 ) HitNormal *= -1;
}
else if ( t.Results.HitType == TRACE_HitFloor )
HitNormal = t.Results.HitSector.floorplane.Normal;
else if ( t.Results.HitType == TRACE_HitCeiling )
HitNormal = t.Results.HitSector.ceilingplane.Normal;
let r = Spawn("ShockBeamRing",pos);
r.angle = atan2(HitNormal.y,HitNormal.x);
r.pitch = asin(-HitNormal.z);
}
}
action void A_BeamExplode()
{
Spawn("ShockBeamLight",pos);
A_QuakeEx(2,2,2,5,0,120,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
A_PlaySound("shock/hit",CHAN_VOICE);
}
States
{
Spawn:
TNT1 A 1;
Wait;
Death:
TNT1 A 0 A_BeamExplode();
AEXP ABCDEFGHIJKL 1 Bright;
TNT1 A 100;
Stop;
}
}
Class ShockBallLight : DynamicLight
{
Default
{
DynamicLight.Type "Point";
Args 160,128,255,120;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
}
override void Tick()
{
Super.Tick();
if ( !target || target.InStateSequence(target.CurState,target.ResolveState("Death")) )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
args[LIGHT_INTENSITY] = Random[ASMD](10,14)*10;
}
}
Class ShockBeamLight : ShockExplLight
{
Default
{
ReactionTime 15;
Args 0,0,0,80;
}
}
Class ShockBeamHitLight : ShockExplLight
{
Default
{
ReactionTime 24;
Args 0,0,0,120;
}
}
Class ShockBlastLight : ShockExplLight
{
Default
{
ReactionTime 50;
Args 0,0,0,300;
}
}
Class ShockExplLight : DynamicLight
{
double lifetime;
Default
{
DynamicLight.Type "Point";
ReactionTime 30;
Args 160,128,255,150;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
lifetime = 1.0;
}
override void Tick()
{
Super.Tick();
args[LIGHT_RED] = 160*lifetime;
args[LIGHT_GREEN] = 128*lifetime;
args[LIGHT_BLUE] = 255*lifetime;
lifetime -= 1./ReactionTime;
if ( lifetime <= 0 ) Destroy();
}
}
Class ShockHitbox : Actor
{
Default
{
Radius 16;
Height 16;
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
}
override void Tick()
{
Super.Tick();
if ( !target || target.InStateSequence(target.CurState,target.ResolveState("Death")) )
{
Destroy();
return;
}
SetOrigin(target.pos-(0,0,height*0.5),true);
}
}
Class ShockBall : Actor
{
Actor l, b;
override void PostBeginPlay()
{
Super.PostBeginPlay();
l = Spawn("ShockBallLight",pos);
l.target = self;
b = Spawn("ShockHitbox",pos);
b.target = self;
}
action void A_BallExplode()
{
A_Explode(Random[ASMD](50,60),70);
A_SprayDecal("ShockMarkBig",16);
Spawn("ShockExplLight",pos);
A_SetScale(1.0);
let r = Spawn("ShockBeamRing",pos);
r.angle = angle;
r.pitch = pitch;
r.scale *= 1.5;
A_PlaySound("shock/hit",CHAN_VOICE);
A_PlaySound("shock/ball",CHAN_WEAPON);
A_QuakeEx(4,4,4,30,0,200,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.15);
}
Default
{
Obituary "%k inflicted mortal damage upon %o with the Shock Rifle";
RenderStyle "Add";
DamageType 'jolted';
Radius 4;
Height 4;
Scale 0.4;
Speed 20;
PROJECTILE;
+FORCEXYBILLBOARD;
+SKYEXPLODE;
+FORCERADIUSDMG;
}
States
{
Spawn:
ABAL ABCD 2 Bright;
Loop;
Death:
TNT1 A 0 A_BallExplode();
AEXP ABCDEFGHIJKL 2 Bright;
TNT1 A 300;
Stop;
}
}
Class ShockRifle : UTWeapon
{
action void A_Selecting()
{
A_PlaySound("shock/select",CHAN_WEAPON);
}
action void A_ShockFire()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("shock/fire",CHAN_WEAPON);
A_QuakeEx(3,3,3,4,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
double a, s;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+3.0*y-4.0*z;
Actor p = Spawn("ShockBeam",origin);
p.angle = angle;
p.pitch = BulletSlope();
p.target = self;
}
action void A_ShockAlt()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("shock/altfire",CHAN_WEAPON);
A_QuakeEx(3,3,3,8,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
double a, s;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+3.0*y-4.0*z;
Actor p = Spawn("ShockBall",origin);
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 "Shock Rifle";
Inventory.PickupMessage "You got the ASMD Shock Rifle.";
Weapon.SlotNumber 4;
Weapon.AmmoType "ShockAmmo";
Weapon.AmmoUse 1;
Weapon.AmmoType2 "ShockAmmo";
Weapon.AmmoUse2 1;
Weapon.AmmoGive 20;
}
States
{
Spawn:
ASMP A -1;
Stop;
ASMP B -1;
Stop;
Ready:
ASMS A 1 A_Selecting();
ASMS BCDEFGHIJKLMNO 1;
Idle:
ASMI A 1
{
A_CheckReload();
A_WeaponReady();
}
Wait;
Fire:
ASMF A 1 A_ShockFire();
ASMF BCDEFGHIJ 2;
Goto Idle;
AltFire:
ASMA A 1 A_ShockAlt();
ASMA BCDEFGHIJ 2;
Goto Idle;
Deselect:
ASMD ABCDEFG 1;
ASMD G 1 A_Lower(int.max);
Wait;
Select:
ASMS A 1 A_Raise(int.max);
Wait;
}
}