flak_m/zscript/shockrifle.zsc
Marisa Kirisame 5248ac8fd6 A couple more things, including an ambient glow shader effect, some more item replacements, and menu options.
Damage Amplifier has been implemented. Armor items are being worked on. Powerups will come later, then I'll continue doing more weapons.
2018-05-20 02:10:30 +02:00

518 lines
13 KiB
Text

Class ShockAmmo : Ammo
{
Default
{
Tag "ShockCore";
Inventory.PickupMessage "You picked up a Shock Core.";
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();
if ( globalfreeze || level.frozen ) return;
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();
if ( globalfreeze || level.frozen ) return;
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";
DamageType 'jolted';
RenderStyle "Add";
Radius 0.1;
Height 0;
Scale 0.4;
+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 ( globalfreeze || level.frozen ) return;
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+=2 )
{
Vector3 pofs = Level.Vec3Diff(pos,pos+tracedir*FRandom[ASMD](0,2)+(FRandom[ASMD](-.5,.5),FRandom[ASMD](-.5,.5),FRandom[ASMD](-.5,.5)));
A_SpawnParticle("FFFFFF",SPF_FULLBRIGHT,30,2,0,tracedir.x*i+pofs.x,tracedir.y*i+pofs.y,tracedir.z*i+pofs.z,FRandom[ASMD](-.03,.03),FRandom[ASMD](-.03,.03),FRandom[ASMD](-.03,.03),startalphaf:1,sizestep:-.1);
A_SpawnParticle("5020FF",SPF_FULLBRIGHT,45,4,0,tracedir.x*i+pofs.x,tracedir.y*i+pofs.y,tracedir.z*i+pofs.z,FRandom[ASMD](-.03,.03),FRandom[ASMD](-.03,.03),FRandom[ASMD](-.03,.03),startalphaf:.5,sizestep:-.1);
A_SpawnParticle("402080",SPF_FULLBRIGHT,60,8,0,tracedir.x*i+pofs.x,tracedir.y*i+pofs.y,tracedir.z*i+pofs.z,FRandom[ASMD](-.03,.03),FRandom[ASMD](-.03,.03),FRandom[ASMD](-.03,.03),startalphaf:.25,sizestep:-.1);
}
if ( totaldist >= 10000.0 )
{
// reposition and explode on air
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,true);
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);
int numpt = Random[ASMD](200,300);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](2,8);
A_SpawnParticle("FFFFFF",SPF_FULLBRIGHT,Random[ASMD](20,80),FRandom[ASMD](1.6,4.8),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-.05);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("5020FF",SPF_FULLBRIGHT,Random[ASMD](40,120),FRandom[ASMD](4.8,11.2),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-.05);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("402080",SPF_FULLBRIGHT,Random[ASMD](50,140),FRandom[ASMD](5.6,12.8),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.25,-1,-.05);
}
}
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);
A_AlertMonsters();
int numpt = Random[ASMD](20,50);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("FFFFFF",SPF_FULLBRIGHT,Random[ASMD](20,40),FRandom[ASMD](1.6,2.4),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-.1);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("5020FF",SPF_FULLBRIGHT,Random[ASMD](40,60),FRandom[ASMD](4.8,5.6),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-.1);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("402080",SPF_FULLBRIGHT,Random[ASMD](50,70),FRandom[ASMD](5.6,6.4),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.25,-1,-.1);
}
}
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
{
+DYNAMICLIGHT.ATTENUATE;
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();
if ( globalfreeze || level.frozen ) return;
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);
A_AlertMonsters();
int numpt = Random[ASMD](50,100);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("FFFFFF",SPF_FULLBRIGHT,Random[ASMD](20,40),FRandom[ASMD](1.6,2.4),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-.1);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("5020FF",SPF_FULLBRIGHT,Random[ASMD](40,60),FRandom[ASMD](4.8,5.6),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-.1);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("402080",SPF_FULLBRIGHT,Random[ASMD](50,70),FRandom[ASMD](5.6,6.4),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.25,-1,-.1);
}
}
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_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);
invoker.FireEffect();
A_AlertMonsters();
A_QuakeEx(3,3,3,4,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = (pos.x,pos.y,player.viewz)+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);
invoker.FireEffect();
A_AlertMonsters();
A_QuakeEx(3,3,3,8,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = (pos.x,pos.y,player.viewz)+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.UpSound "shock/select";
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 ABCDEFGHIJKLMNO 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;
}
}