Prefixed mk_math classes for cross-compat with any other mods that use them. Fixed incorrect uses of gametic. Fixed crash caused by incorrect ordering of PendingWeapon checks.
821 lines
18 KiB
Text
821 lines
18 KiB
Text
Class PulseAmmo : Ammo
|
|
{
|
|
Default
|
|
{
|
|
Tag "Pulse Cell";
|
|
Inventory.PickupMessage "You picked up a Pulse Cell.";
|
|
Inventory.Amount 25;
|
|
Inventory.MaxAmount 200;
|
|
Ammo.BackpackAmount 40;
|
|
Ammo.BackpackMaxAmount 400;
|
|
Ammo.DropAmount 10;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
PAMO A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class PulseSpark : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Radius 2;
|
|
Height 2;
|
|
+NOBLOCKMAP;
|
|
+NOGRAVITY;
|
|
+MISSILE;
|
|
+FORCEXYBILLBOARD;
|
|
+THRUACTORS;
|
|
+ROLLSPRITE;
|
|
+ROLLCENTER;
|
|
+NOTELEPORT;
|
|
+DONTSPLASH;
|
|
+CANBOUNCEWATER;
|
|
-BOUNCEAUTOOFF;
|
|
BounceType "Doom";
|
|
BounceFactor 1.0;
|
|
WallBounceFactor 1.0;
|
|
Scale 0.03;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
if ( !bAMBUSH )
|
|
{
|
|
roll = FRandom[Pulse](0,360);
|
|
let s = Spawn(GetClass(),pos);
|
|
s.bAMBUSH = true;
|
|
s.vel = vel;
|
|
s.scale = scale;
|
|
s.roll = roll;
|
|
}
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
PSPK A 1 Bright
|
|
{
|
|
A_FadeOut(FRandom[Pulse](0.0,0.15));
|
|
vel *= 0.96;
|
|
}
|
|
Wait;
|
|
}
|
|
}
|
|
|
|
Class ViewPulseSpark : PulseSpark
|
|
{
|
|
Vector3 ofs, vvel;
|
|
|
|
override void PostBeginPlay()
|
|
{
|
|
Actor.PostBeginPlay();
|
|
scale *= FRandom[Puff](0.4,0.9);
|
|
alpha *= FRandom[Puff](0.5,2.0);
|
|
roll = FRandom[Pulse](0,360);
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
Actor.Tick();
|
|
if ( !target || !target.player )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
Vector3 x, y, z;
|
|
[x, y, z] = dt_Matrix4.GetAxes(target.pitch,target.angle,target.roll);
|
|
Vector3 origin = x*ofs.x+y*ofs.y+z*ofs.z+(0,0,target.player.viewz);
|
|
SetOrigin(target.Vec2OffsetZ(origin.x,origin.y,origin.z),true);
|
|
bInvisible = (players[consoleplayer].camera != target);
|
|
if ( level.frozen || globalfreeze ) return;
|
|
ofs += vvel;
|
|
vvel *= 0.9;
|
|
scale *= 0.8;
|
|
if ( scale.x <= 0.01 ) Destroy();
|
|
}
|
|
|
|
States
|
|
{
|
|
Spawn:
|
|
PSPK A 1 Bright A_FadeOut(FRandom[Pulse](0.0,0.15));
|
|
Wait;
|
|
}
|
|
}
|
|
|
|
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+int(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] = int(64*lifetime);
|
|
args[LIGHT_GREEN] = int(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](20,30);
|
|
PROJECTILE;
|
|
+EXPLODEONWATER;
|
|
+SKYEXPLODE;
|
|
+FORCEXYBILLBOARD;
|
|
Scale 0.19;
|
|
Speed 29;
|
|
Radius 2;
|
|
Height 2;
|
|
}
|
|
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);
|
|
let s = Spawn("PulseSpark",pos);
|
|
s.vel = pvel;
|
|
}
|
|
}
|
|
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);
|
|
let s = Spawn("PulseSpark",pos);
|
|
s.vel = pvel;
|
|
}
|
|
}
|
|
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 32,128,0,80;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !target )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
SetOrigin(target.pos,true);
|
|
args[LIGHT_INTENSITY] = Random[Pulse](60,100);
|
|
}
|
|
}
|
|
|
|
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 PulseBoltCap : Actor
|
|
{
|
|
override void OnDestroy()
|
|
{
|
|
Super.OnDestroy();
|
|
if ( tracer ) tracer.Destroy();
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( bAMBUSH ) return;
|
|
if ( !tracer )
|
|
{
|
|
tracer = Spawn(GetClass(),pos);
|
|
tracer.bAMBUSH = true;
|
|
}
|
|
tracer.SetOrigin(pos,true);
|
|
}
|
|
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Radius 0.1;
|
|
Height 0;
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
+FORCEXYBILLBOARD;
|
|
Scale 0.3;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
PCAP ABCD 1 Bright;
|
|
Loop;
|
|
}
|
|
}
|
|
|
|
Class PulseBoltHit : Actor
|
|
{
|
|
override void OnDestroy()
|
|
{
|
|
Super.OnDestroy();
|
|
if ( tracer ) tracer.Destroy();
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( bAMBUSH ) return;
|
|
if ( !tracer )
|
|
{
|
|
tracer = Spawn(GetClass(),pos);
|
|
tracer.bAMBUSH = true;
|
|
}
|
|
}
|
|
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Radius 0.1;
|
|
Height 0;
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
+FORCEXYBILLBOARD;
|
|
Scale 0.3;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
PHIT ABCD 1 Bright;
|
|
Loop;
|
|
}
|
|
}
|
|
|
|
Class PulseBolt : Actor
|
|
{
|
|
const beamsize = 81.0;
|
|
|
|
PulseBoltTracer t;
|
|
double accdamage;
|
|
int lasthit;
|
|
Actor damagedactor;
|
|
Actor weffect;
|
|
int position;
|
|
PulseBolt next;
|
|
|
|
override void OnDestroy()
|
|
{
|
|
Super.OnDestroy();
|
|
if ( next ) next.Destroy();
|
|
if ( weffect ) weffect.Destroy();
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
t = new("PulseBoltTracer");
|
|
t.ignore = target;
|
|
let l = Spawn("PulseBoltLight",pos);
|
|
l.target = self;
|
|
}
|
|
void CheckBeam( Vector3 x )
|
|
{
|
|
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,int(Random[Pulse](80,100)*accdamage),'zapped',DMG_USEANGLE,atan2(x.y,x.x));
|
|
accdamage = 0;
|
|
}
|
|
else if ( t.Results.HitActor != damagedactor )
|
|
{
|
|
t.Results.HitActor.DamageMobj(self,target,int(Random[Pulse](80,100)*accdamage),'zapped',DMG_USEANGLE,atan2(x.y,x.x));
|
|
accdamage = 0;
|
|
}
|
|
lasthit = level.time;
|
|
damagedactor = t.Results.HitActor;
|
|
accdamage += 1./TICRATE;
|
|
if ( accdamage > 0.17 )
|
|
{
|
|
t.Results.HitActor.DamageMobj(self,target,int(Random[Pulse](80,100)*accdamage),'zapped',DMG_USEANGLE,atan2(x.y,x.x));
|
|
accdamage = 0;
|
|
}
|
|
}
|
|
Vector3 norm = -x;
|
|
if ( t.Results.HitType == TRACE_HitWall )
|
|
{
|
|
norm = (t.Results.HitLine.delta.y,-t.Results.HitLine.delta.x,0).unit();
|
|
if ( t.Results.Side ) norm *= -1;
|
|
t.Results.HitLine.RemoteActivate(tracer,t.Results.Side,SPAC_Impact,t.Results.HitPos);
|
|
}
|
|
else if ( t.Results.HitType == TRACE_HitFloor ) norm = t.Results.HitSector.floorplane.Normal;
|
|
else if ( t.Results.HitType == TRACE_HitCeiling ) norm = t.Results.HitSector.ceilingplane.Normal;
|
|
int numpt = Random[Pulse](10,20)*!Random[Pulse](0,2);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (norm+(FRandom[Pulse](-.6,.6),FRandom[Pulse](-.6,.6),FRandom[Pulse](-.6,.6))).unit()*FRandom[Pulse](2,4);
|
|
let s = Spawn("PulseSpark",t.Results.HitPos-t.Results.HitVector*4);
|
|
s.vel = pvel;
|
|
}
|
|
if ( weffect && (weffect is 'PulseBoltCap') )
|
|
{
|
|
weffect.Destroy();
|
|
weffect = null;
|
|
}
|
|
if ( !weffect ) weffect = Spawn("PulseBoltHit",t.Results.HitPos-t.Results.HitVector*4);
|
|
else
|
|
{
|
|
weffect.SetOrigin(t.Results.HitPos-t.Results.HitVector*4,true);
|
|
if ( weffect.tracer ) weffect.tracer.SetOrigin(t.Results.HitPos-t.Results.HitVector*4,true);
|
|
}
|
|
A_SprayDecal("BoltScorch",beamsize+8);
|
|
if ( next )
|
|
{
|
|
accdamage += next.accdamage;
|
|
next.Destroy();
|
|
next = null;
|
|
}
|
|
return;
|
|
}
|
|
else if ( damagedactor )
|
|
{
|
|
damagedactor.DamageMobj(self,target,int(Random[Pulse](65,75)*accdamage),'zapped');
|
|
accdamage = 0;
|
|
damagedactor = null;
|
|
}
|
|
if ( position >= 9 )
|
|
{
|
|
int numpt = Random[Pulse](5,10)*!Random[Pulse](0,5);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (t.Results.HitVector+(FRandom[Pulse](-.6,.6),FRandom[Pulse](-.6,.6),FRandom[Pulse](-.6,.6))).unit()*FRandom[Pulse](2,4);
|
|
let s = Spawn("PulseSpark",t.Results.HitPos);
|
|
s.vel = pvel;
|
|
}
|
|
if ( weffect && (weffect is 'PulseBoltHit') )
|
|
{
|
|
weffect.Destroy();
|
|
weffect = null;
|
|
}
|
|
if ( !weffect ) weffect = Spawn("PulseBoltCap",t.Results.HitPos);
|
|
else
|
|
{
|
|
weffect.SetOrigin(t.Results.HitPos,true);
|
|
if ( weffect.tracer ) weffect.tracer.SetOrigin(t.Results.HitPos,true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( weffect )
|
|
{
|
|
weffect.Destroy();
|
|
weffect = null;
|
|
}
|
|
if ( !next )
|
|
{
|
|
next = PulseBolt(Spawn("PulseBolt",t.Results.HitPos));
|
|
next.angle = angle;
|
|
next.pitch = pitch;
|
|
next.target = target;
|
|
next.position = position+1;
|
|
}
|
|
else next.UpdateBeam(self,x);
|
|
}
|
|
}
|
|
void UpdateBeam( PulseBolt parent, Vector3 x )
|
|
{
|
|
frame = parent.frame;
|
|
SetOrigin(parent.Vec3Offset(x.x*beamsize,x.y*beamsize,x.z*beamsize),true);
|
|
A_SetAngle(parent.angle);
|
|
A_SetPitch(parent.pitch);
|
|
CheckBeam(x);
|
|
}
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Obituary "%o ate %k's burning plasma death.";
|
|
Radius 0.1;
|
|
Height 0;
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
+INTERPOLATEANGLES;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
PBLT # -1 Bright;
|
|
Stop;
|
|
Dummy:
|
|
PBLT ABCDE -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class StarterBolt : PulseBolt
|
|
{
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( globalfreeze || level.frozen ) return;
|
|
if ( !target )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
Vector3 x, y, z, origin;
|
|
if ( target.player )
|
|
{
|
|
[x, y, z] = dt_Matrix4.GetAxes(target.pitch,target.angle,target.roll);
|
|
origin = target.Vec2OffsetZ(0,0,target.player.viewz)+8.0*x+4.1*y-2.7*z;
|
|
}
|
|
else origin = target.Vec3Offset(0,0,target.missileheight);
|
|
SetOrigin(origin,true);
|
|
A_SetAngle(target.angle);
|
|
A_SetPitch(target.BulletSlope());
|
|
frame++;
|
|
if ( frame > 4 ) frame = 0;
|
|
CheckBeam((cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch)));
|
|
}
|
|
}
|
|
|
|
Class PulseGun : UTWeapon
|
|
{
|
|
int clipcount;
|
|
double sangle;
|
|
Actor beam;
|
|
|
|
Property ClipCount : clipcount;
|
|
|
|
override void PostRender( double lbottom )
|
|
{
|
|
if ( !flak_pulsereload ) return;
|
|
Screen.DrawText(confont,Font.CR_GREEN,Screen.GetWidth()*0.01,lbottom-Screen.GetHeight()*0.01-confont.GetHeight(),String.Format("Clip: %2d / 50",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 ( !flak_pulsereload && (invoker.clipcount <= 0) ) invoker.clipcount = (weap.Ammo1.Amount>0)?Min(50,weap.Ammo1.Amount):50;
|
|
invoker.FireEffect();
|
|
UTMainHandler.DoFlash(self,Color(32,128,255,128),1);
|
|
UTMainHandler.DoSwing(self,(FRandom[Pulse](-1,-1),FRandom[Pulse](-1,1)),0.1,-0.02,3,SWING_Spring,0,2);
|
|
A_AlertMonsters();
|
|
Vector3 x, y, z;
|
|
[x, y, z] = dt_Matrix4.GetAxes(pitch,angle,roll);
|
|
Vector3 origin = Vec2OffsetZ(0,0,player.viewz)+10.0*x+4.1*y-2.7*z;
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
let s = Spawn("UTViewSmoke",origin);
|
|
UTViewSmoke(s).ofs = (10,4.1,-2.7);
|
|
s.scale *= 1.8;
|
|
s.target = self;
|
|
s.SetShade("206010");
|
|
s.A_SetRenderStyle(0.4,STYLE_AddShaded);
|
|
UTViewSmoke(s).vvel += (FRandom[Pulse](0.2,0.6),FRandom[Pulse](-0.2,0.2),FRandom[Pulse](-0.2,0.2));
|
|
}
|
|
int numpt = Random[Pulse](8,16);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
let s = Spawn("ViewPulseSpark",origin);
|
|
ViewPulseSpark(s).ofs = (10,4.1,-2.7);
|
|
s.target = self;
|
|
ViewPulseSpark(s).vvel += (FRandom[Pulse](0.2,0.8),FRandom[Pulse](-0.5,0.5),FRandom[Pulse](-0.5,0.5));
|
|
}
|
|
}
|
|
action void A_PulseRefire( statelabel flash = null, bool noreload = false )
|
|
{
|
|
Weapon weap = Weapon(invoker);
|
|
if ( !weap || !player ) return;
|
|
if ( (invoker.clipcount <= 0) || (weap.Ammo1.Amount <= 0) )
|
|
{
|
|
if ( noreload ) return;
|
|
A_ClearRefire();
|
|
if ( weap.bAltFire ) player.setpsprite(PSP_WEAPON,weap.FindState("AltRelease"));
|
|
else player.setpsprite(PSP_WEAPON,weap.FindState("Release"));
|
|
return;
|
|
}
|
|
if ( noreload )
|
|
{
|
|
if ( player.cmd.buttons&BT_ALTATTACK )
|
|
{
|
|
weap.bAltFire = true;
|
|
flash = "AltFire";
|
|
}
|
|
else
|
|
{
|
|
weap.bAltFire = false;
|
|
flash = "Fire";
|
|
}
|
|
}
|
|
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 ( !flak_pulsereload && (invoker.clipcount <=0) ) invoker.clipcount = (weap.Ammo1.Amount>0)?Min(50,weap.Ammo1.Amount):50;
|
|
invoker.FireEffect();
|
|
UTMainHandler.DoFlash(self,Color(32,128,255,128),1);
|
|
UTMainHandler.DoSwing(self,(FRandom[Pulse](-1,-1),FRandom[Pulse](-1,1)),0.3,-0.1,2,SWING_Spring,0,3);
|
|
A_AlertMonsters();
|
|
A_QuakeEx(1,1,1,2,0,1,"",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] = dt_Matrix4.GetAxes(pitch,angle,roll);
|
|
Vector3 origin = Vec2OffsetZ(0,0,player.viewz)+10.0*x+3.0*y-1.8*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;
|
|
for ( int i=0; i<8; i++ )
|
|
{
|
|
let s = Spawn("UTViewSmoke",origin);
|
|
UTViewSmoke(s).ofs = (10,3.0,-1.8);
|
|
s.scale *= 1.8;
|
|
s.target = self;
|
|
s.SetShade("206010");
|
|
s.A_SetRenderStyle(0.4,STYLE_AddShaded);
|
|
UTViewSmoke(s).vvel += (FRandom[Pulse](0.4,0.8),FRandom[Pulse](-0.2,0.2),FRandom[Pulse](-0.2,0.2));
|
|
}
|
|
int numpt = Random[Pulse](8,16);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
let s = Spawn("ViewPulseSpark",origin);
|
|
ViewPulseSpark(s).ofs = (10,3.0,-1.8);
|
|
s.target = self;
|
|
ViewPulseSpark(s).vvel += (FRandom[Pulse](0.4,1.6),FRandom[Pulse](-1.2,1.2),FRandom[Pulse](-1.2,1.2));
|
|
}
|
|
}
|
|
action void A_StartBeam()
|
|
{
|
|
A_PlaySound("pulse/bolt",CHAN_WEAPON,1.0,true);
|
|
Vector3 x, y, z, origin;
|
|
[x, y, z] = dt_Matrix4.GetAxes(pitch,angle,roll);
|
|
origin = Vec2OffsetZ(0,0,player.viewz)+10.0*x+4.1*y-2.7*z;
|
|
invoker.beam = Spawn("StarterBolt",origin);
|
|
invoker.beam.angle = angle;
|
|
invoker.beam.pitch = BulletSlope();
|
|
invoker.beam.target = self;
|
|
}
|
|
action void A_StopBeam()
|
|
{
|
|
A_StopSound(CHAN_WEAPON);
|
|
if ( invoker.beam ) invoker.beam.Destroy();
|
|
}
|
|
override void OwnerDied()
|
|
{
|
|
Super.OwnerDied();
|
|
if ( beam ) beam.Destroy();
|
|
}
|
|
override void DetachFromOwner()
|
|
{
|
|
if ( beam ) beam.Destroy();
|
|
Super.DetachFromOwner();
|
|
}
|
|
override void OnDestroy()
|
|
{
|
|
Super.OnDestroy();
|
|
if ( beam ) 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;
|
|
UTWeapon.DropAmmo 15;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
PGNP A -1;
|
|
Stop;
|
|
PGNP B -1;
|
|
Stop;
|
|
Ready:
|
|
PGNS ABCDEFGHIJKLMNOPQRSTUVW 1 A_WeaponReady(WRF_NOFIRE);
|
|
Idle:
|
|
PGNI A 1
|
|
{
|
|
A_CheckReload();
|
|
if ( flak_pulsereload )
|
|
{
|
|
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 A_PulseRefire(null,true);
|
|
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 A_PulseRefire(null,true);
|
|
Goto Idle;
|
|
Reload:
|
|
PGNI A 1;
|
|
PGNI A 0 A_JumpIf(invoker.clipcount >= Min(50,invoker.Ammo1.Amount),"Idle");
|
|
PGNR A 1 A_Reloading();
|
|
PGNR BCDEFGHIJKLMNOPQRSTUVWXYZ 1;
|
|
PGR2 ABCDEFGHIJKLMNOPQRSTUVWX 1;
|
|
Goto Idle;
|
|
Deselect:
|
|
PGNS W 1 A_StopSound(CHAN_WEAPON);
|
|
PGNS VTSQPNMKJHGEDBA 1;
|
|
PGNS A 1 A_Lower(int.max);
|
|
Wait;
|
|
Select:
|
|
PGNS A 1 A_Raise(int.max);
|
|
Wait;
|
|
MuzzleFlash:
|
|
PMUZ A 2 Bright;
|
|
Stop;
|
|
}
|
|
}
|