flak_m/zscript/pulsegun.zsc

550 lines
14 KiB
Text

Class Tier4Ammo : RandomSpawner2 replaces ClipBox
{
Default
{
DropItem "PulseAmmo", 255, 1;
DropItem "RipperAmmo", 255, 1;
}
}
Class Tier4Weapon : RandomSpawner2 replaces Chaingun
{
Default
{
DropItem "PulseGun", 255, 1;
DropItem "Ripper2", 255, 1;
}
}
Class PulseAmmo : UTAmmo
{
Default
{
Tag "Pulse Cell";
Inventory.PickupMessage "You picked up a Pulse Cell.";
Inventory.Amount 25;
Inventory.MaxAmount 199;
Ammo.BackpackAmount 50;
Ammo.BackpackMaxAmount 199;
Ammo.DropAmount 25;
UTAmmo.UsedInSlot AMMO_SLOT5;
}
States
{
Spawn:
PAMO A -1;
Stop;
}
}
Class PulseBallLight : DynamicLight
{
double pulseofs;
Default
{
DynamicLight.Type "Point";
Args 64,255,0,10;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
pulseofs = FRandom[Pulse](0,360);
}
override void Tick()
{
Super.Tick();
if ( !target || target.InStateSequence(target.CurState,target.ResolveState("Death")) )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
args[LIGHT_INTENSITY] = 10+sin(gametic*80+pulseofs)*5;
}
}
Class PulseExplLight : DynamicLight
{
double lifetime;
Default
{
DynamicLight.Type "Point";
ReactionTime 20;
Args 64,255,0,30;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
lifetime = 1.0;
}
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
args[LIGHT_RED] = 64*lifetime;
args[LIGHT_GREEN] = 255*lifetime;
lifetime -= 1./ReactionTime;
if ( lifetime <= 0 ) Destroy();
}
}
Class PulseBall : Actor
{
Default
{
Obituary "%o ate %k's burning plasma death.";
DamageType 'Pulsed';
RenderStyle "Add";
DamageFunction Random[Pulse](15,25);
PROJECTILE;
Scale 0.2;
Speed 30;
Radius 4;
Height 4;
}
override void PostBeginPlay()
{
A_PlaySound("pulse/fly",CHAN_BODY,0.8,true,8.0);
let l = Spawn("PulseBallLight",pos);
l.target = self;
}
action void A_BallExp()
{
A_SetScale(0.45);
A_PlaySound("pulse/hit",CHAN_BODY);
A_SprayDecal("BoltScorch");
Spawn("PulseExplLight",pos);
int numpt = Random[Pulse](20,40);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Pulse](-1,1),FRandom[Pulse](-1,1),FRandom[Pulse](-1,1)).unit()*FRandom[Pulse](2,4);
A_SpawnParticle("FFFFFF",SPF_FULLBRIGHT,Random[Pulse](20,40),FRandom[Pulse](2.4,4.8),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-0.1);
A_SpawnParticle("40FF00",SPF_FULLBRIGHT,Random[Pulse](30,50),FRandom[Pulse](4.8,7.2),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-0.1);
}
}
action void A_Trail()
{
if ( Random[Pulse](0,4) ) return;
int numpt = Random[Pulse](2,5);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Pulse](-1,1),FRandom[Pulse](-1,1),FRandom[Pulse](-1,1)).unit()*FRandom[Pulse](2,4);
A_SpawnParticle("FFFFFF",SPF_FULLBRIGHT,Random[Pulse](10,20),FRandom[Pulse](1.2,2.4),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-0.1);
A_SpawnParticle("40FF00",SPF_FULLBRIGHT,Random[Pulse](15,25),FRandom[Pulse](2.4,3.6),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-0.1);
}
}
States
{
Spawn:
PBAL ABCDE 1 Bright A_Trail();
Loop;
Death:
TNT1 A 0 A_BallExp();
PBAL ABCDE 3 Bright;
Stop;
}
}
Class PulseBoltLight : DynamicLight
{
bool lived;
Default
{
DynamicLight.Type "Point";
Args 64,255,0,50;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
args[LIGHT_INTENSITY] = Random[Pulse](50,60);
}
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
if ( lived ) Destroy();
lived = true;
}
}
Class PulseBoltTracer : LineTracer
{
Actor ignore;
override ETraceStatus TraceCallback()
{
if ( Results.HitType == TRACE_HitActor )
{
if ( Results.HitActor == ignore ) return TRACE_Skip;
if ( Results.HitActor.bSHOOTABLE ) 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 PulseBolt : Actor
{
PulseBoltTracer t;
double accdamage;
int lasthit;
Actor damagedactor;
double beamsize;
Actor weffect;
double phase;
override void OnDestroy()
{
Super.OnDestroy();
if ( weffect ) weffect.Destroy();
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
t = new("PulseBoltTracer");
t.ignore = target;
beamsize = 40;
}
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
if ( !target )
{
Destroy();
return;
}
phase += 10;
// update beam
int numpt;
Vector3 x, y, z;
Vector3 origin;
if ( target.player )
{
[x, y, z] = Matrix4.GetAxes(target.pitch,target.angle,target.roll);
origin = (0,0,target.player.viewz-target.pos.z)+5.0*x+3.0*y-1.5*z;
}
else origin = (0,0,target.missileheight);
SetOrigin(target.Vec3Offset(origin.x,origin.y,origin.z),true);
A_SetAngle(target.angle,SPF_INTERPOLATE);
A_SetPitch(target.BulletSlope(),SPF_INTERPOLATE);
// draw beam
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
for ( double i=0; i<=beamsize; i+=0.5 )
{
origin = Level.Vec3Diff(pos,pos+x*i
+sin(i*0.834-phase)*y*0.1435*min(1,(i*0.1)**.5)
+sin(i*0.836-phase)*y*0.1342*min(1,(i*0.1)**.5)
+sin(i*0.843-phase)*z*0.1463*min(1,(i*0.1)**.5)
+sin(i*0.863-phase)*z*0.1345*min(1,(i*0.1)**.5));
A_SpawnParticle("FFFFFF",SPF_FULLBRIGHT,1,FRandom[Pulse](0.6,1.2),0,origin.x,origin.y,origin.z,0,0,0,0,0,0,2);
A_SpawnParticle("40FF00",SPF_FULLBRIGHT,1,FRandom[Pulse](2.4,4.8),0,origin.x,origin.y,origin.z,0,0,0,0,0,0,.1);
}
for ( int i=50; i<beamsize; i+=100 )
{
origin = Vec3Offset(x.x*i,x.y*i,x.z*i);
Spawn("PulseBoltLight",origin);
}
// check beam
t.Trace(pos,cursector,x,beamsize,0);
if ( t.Results.HitType != TRACE_HitNone )
{
if ( t.Results.HitType == TRACE_HitActor )
{
if ( !damagedactor )
{
accdamage = min(0.5*(level.time-lasthit),0.1);
t.Results.HitActor.DamageMobj(self,target,Random[Pulse](65,75)*accdamage,'zapped');
accdamage = 0;
}
else if ( t.Results.HitActor != damagedactor )
{
t.Results.HitActor.DamageMobj(self,target,Random[Pulse](65,75)*accdamage,'zapped');
accdamage = 0;
}
lasthit = level.time;
damagedactor = t.Results.HitActor;
accdamage += 1./TICRATE;
if ( accdamage > 0.22 )
{
t.Results.HitActor.DamageMobj(self,target,Random[Pulse](65,75)*accdamage,'zapped');
accdamage = 0;
}
}
origin = Level.Vec3Diff(pos,t.Results.HitPos);
numpt = Random[Pulse](10,20)*!Random[Pulse](0,2);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = ((FRandom[Pulse](-.4,.5),FRandom[Pulse](-.4,.4),FRandom[Pulse](-.4,.4))-x).unit()*FRandom[Pulse](2,4);
A_SpawnParticle("FFFFFF",SPF_FULLBRIGHT,Random[Pulse](20,40),FRandom[Pulse](2.4,4.8),0,origin.x,origin.y,origin.z,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-0.1);
A_SpawnParticle("40FF00",SPF_FULLBRIGHT,Random[Pulse](30,50),FRandom[Pulse](4.8,7.2),0,origin.x,origin.y,origin.z,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-0.1);
}
beamsize = t.Results.Distance;
A_SprayDecal("BoltScorch",beamsize+8);
return;
}
else if ( damagedactor )
{
damagedactor.DamageMobj(self,target,Random[Pulse](65,75)*accdamage,'zapped');
accdamage = 0;
damagedactor = null;
}
origin = Level.Vec3Diff(pos,t.Results.HitPos);
numpt = Random[Pulse](5,10)*!Random[Pulse](0,5);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (t.Results.HitVector+(FRandom[Pulse](-.5,.5),FRandom[Pulse](-.5,.5),FRandom[Pulse](-.5,.5))).unit()*FRandom[Pulse](2,4);
A_SpawnParticle("FFFFFF",SPF_FULLBRIGHT,Random[Pulse](20,40),FRandom[Pulse](2.4,4.8),0,origin.x,origin.y,origin.z,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-0.1);
A_SpawnParticle("40FF00",SPF_FULLBRIGHT,Random[Pulse](30,50),FRandom[Pulse](4.8,7.2),0,origin.x,origin.y,origin.z,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-0.1);
}
beamsize = min(400,beamsize+40);
}
Default
{
Obituary "%o ate %k's burning plasma death.";
RenderStyle "Add";
Radius 0.1;
Height 0;
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
}
States
{
Spawn:
PBLT A 1 Bright;
Loop;
}
}
Class PulseGun : UTWeapon
{
int clipcount;
double sangle;
Actor beam;
Property ClipCount : clipcount;
action void A_Reloading()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
invoker.clipcount = Min(50,weap.Ammo1.Amount);
A_PlaySound("pulse/reload",CHAN_WEAPON);
}
action void A_DrainAmmo()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
invoker.clipcount--;
if ( !CVar.GetCVar('flak_pulsereload').GetBool() && (invoker.clipcount <= 0) ) invoker.clipcount = Min(50,weap.Ammo1.Amount);
invoker.FireEffect();
UTMainHandler.DoFlash(self,Color(32,128,255,128),1);
A_AlertMonsters();
Vector3 x, y, z;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+4.5*y-2.4*z;
int numpt = Random[Pulse](2,5);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Pulse](-.5,.5),FRandom[Pulse](-.5,.5),FRandom[Pulse](-.5,.5))).unit()*FRandom[Pulse](2,4);
A_SpawnParticle("FFFFFF",SPF_FULLBRIGHT,Random[Pulse](10,20),FRandom[Pulse](1.2,2.4),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-0.1);
A_SpawnParticle("40FF00",SPF_FULLBRIGHT,Random[Pulse](15,25),FRandom[Pulse](2.4,3.6),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-0.1);
}
}
action void A_PulseRefire( statelabel flash = null )
{
Weapon weap = Weapon(invoker);
if ( !weap || !player ) return;
if ( (invoker.clipcount <= 0) || (weap.Ammo1.Amount <= 0) )
{
A_ClearRefire();
if ( weap.bAltFire ) player.setpsprite(PSP_WEAPON,weap.FindState("AltRelease"));
else player.setpsprite(PSP_WEAPON,weap.FindState("Release"));
return;
}
A_Refire(flash);
}
action void A_PulseFire()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
invoker.clipcount--;
if ( !CVar.GetCVar('flak_pulsereload').GetBool() && (invoker.clipcount <=0) ) invoker.clipcount = Min(50,weap.Ammo1.Amount);
invoker.FireEffect();
UTMainHandler.DoFlash(self,Color(32,128,255,128),1);
A_AlertMonsters();
A_QuakeEx(1,1,1,2,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.05);
A_Overlay(-2,"MuzzleFlash");
A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
A_OverlayRenderstyle(-2,STYLE_Add);
Vector3 x, y, z;
double a;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+4.0*y-2.0*z;
origin += y*cos(invoker.sangle)*2.0+z*sin(invoker.sangle)*2.0;
invoker.sangle += 100;
Actor p = Spawn("PulseBall",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;
int numpt = Random[Pulse](2,5);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Pulse](-.5,.5),FRandom[Pulse](-.5,.5),FRandom[Pulse](-.5,.5))).unit()*FRandom[Pulse](2,4);
A_SpawnParticle("FFFFFF",SPF_FULLBRIGHT,Random[Pulse](10,20),FRandom[Pulse](1.2,2.4),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-0.1);
A_SpawnParticle("40FF00",SPF_FULLBRIGHT,Random[Pulse](15,25),FRandom[Pulse](2.4,3.6),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-0.1);
}
}
action void A_StartBeam()
{
A_PlaySound("pulse/bolt",CHAN_WEAPON,1.0,true);
invoker.beam = Spawn("PulseBolt",pos);
invoker.beam.target = self;
}
action void A_StopBeam()
{
A_StopSound(CHAN_WEAPON);
if ( invoker.beam ) invoker.beam.Destroy();
}
Default
{
Tag "Pulse Gun";
Inventory.PickupMessage "You got a Pulse Gun";
Weapon.UpSound "pulse/select";
Weapon.SlotNumber 5;
Weapon.SelectionOrder 5;
Weapon.AmmoType "PulseAmmo";
Weapon.AmmoUse 1;
Weapon.AmmoType2 "PulseAmmo";
Weapon.AmmoUse2 1;
Weapon.AmmoGive 60;
PulseGun.ClipCount 50;
}
States
{
Spawn:
PGNP A -1;
Stop;
PGNP B -1;
Stop;
Ready:
PGNS ABCDEFGHIJKLMNOPQRSTUVW 1;
Idle:
PGNI A 1
{
A_CheckReload();
if ( CVar.GetCVar('flak_pulsereload').GetBool() )
{
if ( (invoker.clipcount <= 0) && (invoker.Ammo1.Amount > 0) ) return A_Jump(255,"Reload");
A_WeaponReady(WRF_ALLOWRELOAD);
}
else A_WeaponReady();
return A_JumpIf(!Random[Pulse](0,300),1);
}
Wait;
PGNI ABCDEFGHIJKLMNOPQRSTUVWXYZ 1
{
A_CheckReload();
A_WeaponReady(WRF_ALLOWRELOAD);
}
Goto Idle;
Fire:
PGNI A 0 A_PlaySound("pulse/fire",CHAN_WEAPON,1.0,true);
Hold:
PGNF A 1 A_PulseFire();
PGNF BCDEF 1;
PNGF G 0 A_PulseRefire(1);
Goto Release;
PGNF G 1 A_PulseFire();
PGNF HIJKL 1;
PNGF M 0 A_PulseRefire(1);
Goto Release;
PGNF N 1 A_PulseFire();
PGNF OPQRS 1;
PNGF T 0 A_PulseRefire(1);
Goto Release;
PGNF U 1 A_PulseFire();
PGNF VWXYZ 1;
PGF2 A 0 A_PulseRefire(1);
Goto Release;
PGF2 A 1 A_PulseFire();
PGF2 BCDEF 1;
PGF2 G 0 A_PulseRefire(1);
Goto Release;
PGF2 H 1 A_PulseFire();
PGF2 IJKLM 1;
PGF2 N 0 A_PulseRefire();
Goto Release;
Release:
PGNC A 0 A_PlaySound("pulse/down",CHAN_WEAPON);
PGNC ABCDEFGHIJKLMNOPQRSTUVWXY 1;
PGNC Y 0;
Goto Idle;
AltFire:
PGBS ABCDE 1;
PGBL A 0 A_StartBeam();
AltHold:
PGBL A 1 A_DrainAmmo();
PGBL B 0 A_PulseRefire(1);
Goto AltRelease;
PGBL B 1;
PGBL C 0 A_PulseRefire(1);
Goto AltRelease;
PGBL C 1;
PGBL D 0 A_PulseRefire(1);
Goto AltRelease;
PGBL D 1;
PGBL E 0 A_PulseRefire(1);
Goto AltRelease;
PGBL E 1;
PGBL F 0 A_PulseRefire(1);
Goto AltRelease;
PGBL F 1;
PGBL G 0 A_PulseRefire(1);
Goto AltRelease;
PGBL G 1;
PGBL H 0 A_PulseRefire(1);
Goto AltRelease;
PGBL H 1;
PGBL I 0 A_PulseRefire(1);
Goto AltRelease;
PGBL I 1;
PGBL J 0 A_PulseRefire(1);
Goto AltRelease;
PGBL J 1;
PGBL A 0 A_PulseRefire();
AltRelease:
PGBE A 0 A_StopBeam();
PGBE ABCDE 1;
Goto Idle;
Reload:
PGNI A 1;
PGNI A 0 A_JumpIf(invoker.clipcount >= 50,"Idle");
PGNR A 1 A_Reloading();
PGNR BCDEFGHIJKLMNOPQRSTUVWXYZ 1;
PGR2 ABCDEFGHIJKLMNOPQRSTUVWX 1;
Goto Idle;
Deselect:
PGNS WVUTSRQPONMLKJIHGFEDCBA 1;
PGNS A 1 A_Lower(int.max);
Wait;
Select:
PGNS A 1 A_Raise(int.max);
Wait;
MuzzleFlash:
PMUZ A 2 Bright;
Stop;
}
}