Addition to HUD for showing clip counts (kinda cheap-looking, but still better than what Oldskool did). Charge for some weapons and loaded rockets for eightball also use the clipcount display, like in Doom Tournament. Small fixups for dual wielding logic.
848 lines
19 KiB
Text
848 lines
19 KiB
Text
Class ASMDAmmo : Ammo
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_ASMDAMMO";
|
|
Inventory.Icon "I_ASMD";
|
|
Inventory.PickupMessage "$I_ASMDAMMO";
|
|
Inventory.Amount 10;
|
|
Inventory.MaxAmount 50;
|
|
Ammo.BackpackAmount 5;
|
|
Ammo.BackpackMaxAmount 100;
|
|
Ammo.DropAmount 5;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
tracer = Spawn("ASMDAmmoX",pos);
|
|
tracer.angle = angle;
|
|
tracer.target = self;
|
|
tracer = Spawn("ASMDAmmoXX",pos);
|
|
tracer.angle = angle;
|
|
tracer.target = self;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
SHOA A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class ASMDAmmoX : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
Radius 0.1;
|
|
Height 0;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !target )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
Warp(target,flags:WARPF_COPYINTERPOLATION|WARPF_NOCHECKPOSITION);
|
|
bInvisible = target.bInvisible||!target.InStateSequence(target.CurState,target.FindState("Spawn"));
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
SHOA A -1 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class ASMDAmmoXX : ASMDAmmoX
|
|
{
|
|
States
|
|
{
|
|
Spawn:
|
|
SHOA A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class ASMDAmmo2X : ASMDAmmoX
|
|
{
|
|
States
|
|
{
|
|
Spawn:
|
|
SHOA B -1 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class ASMDAmmo2 : ASMDAmmo
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_ASMDAMMO2";
|
|
Inventory.Icon "I_ASMD";
|
|
Inventory.PickupMessage "$I_ASMDAMMO2";
|
|
Inventory.Amount 5;
|
|
Ammo.DropAmount 3;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Ammo.PostBeginPlay();
|
|
tracer = Spawn("ASMDAmmo2X",pos);
|
|
tracer.angle = angle;
|
|
tracer.target = self;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
SHOA B -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class ASMDLight : EnforcerLight
|
|
{
|
|
Default
|
|
{
|
|
Args 64,32,255,70;
|
|
}
|
|
}
|
|
|
|
Class ASMDBeamRing : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
Radius 0.1;
|
|
Height 0;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( isFrozen() ) return;
|
|
A_FadeOut(0.05,0);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
RNGX ABCDEF 4 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
Class ASMDSBeamRing : ASMDBeamRing {}
|
|
Class ASMDBlastRing : ASMDBeamRing
|
|
{
|
|
override void Tick()
|
|
{
|
|
Actor.Tick();
|
|
if ( isFrozen() ) return;
|
|
A_FadeOut(0.028,0);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
RNGX ABCDEF 7 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class ASMDRingTrail : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
+INTERPOLATEANGLES;
|
|
Radius 0.1;
|
|
Height 0;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( isFrozen() ) return;
|
|
A_FadeOut(0.05,0);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
RNGX ABCDEF 4 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class ASMDBeamLight : PaletteLight
|
|
{
|
|
Default
|
|
{
|
|
Tag "Blue2";
|
|
Args 0,0,0,50;
|
|
ReactionTime 30;
|
|
}
|
|
}
|
|
|
|
Class ASMDSBeamLight : PaletteLight
|
|
{
|
|
Default
|
|
{
|
|
Tag "Ampd";
|
|
Args 0,0,0,50;
|
|
ReactionTime 30;
|
|
}
|
|
}
|
|
|
|
Class ASMDBlastLight : PaletteLight
|
|
{
|
|
Default
|
|
{
|
|
Tag "Purple";
|
|
ReactionTime 40;
|
|
Args 0,0,0,300;
|
|
}
|
|
}
|
|
|
|
Class ASMDSpark : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Radius 2;
|
|
Height 2;
|
|
+NOBLOCKMAP;
|
|
+NOGRAVITY;
|
|
+MISSILE;
|
|
+FORCEXYBILLBOARD;
|
|
+THRUACTORS;
|
|
+ROLLSPRITE;
|
|
+NOTELEPORT;
|
|
+DONTSPLASH;
|
|
+CANBOUNCEWATER;
|
|
-BOUNCEAUTOOFF;
|
|
BounceType "Hexen";
|
|
BounceFactor 1.0;
|
|
WallBounceFactor 1.0;
|
|
Scale 0.1;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
roll = FRandom[ASMD](0,360);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
AFLA A 1 Bright
|
|
{
|
|
A_FadeOut(FRandom[ASMD](0.0,0.1));
|
|
vel *= 0.98;
|
|
}
|
|
Wait;
|
|
}
|
|
}
|
|
|
|
Class ViewASMDSpark : ShockSpark
|
|
{
|
|
Vector3 ofs, vvel;
|
|
|
|
override void PostBeginPlay()
|
|
{
|
|
Actor.PostBeginPlay();
|
|
scale *= FRandom[Puff](0.4,0.9);
|
|
alpha *= FRandom[Puff](0.5,2.0);
|
|
roll = FRandom[ASMD](0,360);
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
Actor.Tick();
|
|
if ( !target || !target.player )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
Vector3 x, y, z;
|
|
[x, y, z] = dt_CoordUtil.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 ( isFrozen() ) return;
|
|
ofs += vvel;
|
|
vvel *= 0.9;
|
|
scale *= 0.8;
|
|
if ( scale.x <= 0.01 ) Destroy();
|
|
}
|
|
|
|
States
|
|
{
|
|
Spawn:
|
|
AFLA A 1 Bright A_FadeOut(FRandom[ASMD](0.0,0.1));
|
|
Wait;
|
|
}
|
|
}
|
|
|
|
Class ASMDHitbox : ShockHitbox
|
|
{
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !target ) return;
|
|
let t = ThinkerIterator.Create("ASMDHitbox");
|
|
Actor a;
|
|
while ( a = Actor(t.Next()) )
|
|
{
|
|
if ( (a == self) || !(a is 'ASMDHitbox') || a.bAMBUSH || (Distance3D(a) > radius*2) ) continue;
|
|
a.bAMBUSH = true;
|
|
if ( a.target && a.target.InStateSequence(a.target.CurState,a.target.FindState("Spawn")) )
|
|
a.target.ExplodeMissile();
|
|
if ( !bAMBUSH )
|
|
{
|
|
bAMBUSH = true;
|
|
if ( target && target.InStateSequence(target.CurState,target.FindState("Spawn")) )
|
|
target.ExplodeMissile();
|
|
}
|
|
}
|
|
}
|
|
Default
|
|
{
|
|
Radius 6;
|
|
Height 12;
|
|
}
|
|
}
|
|
|
|
Class ASMDBall : Actor
|
|
{
|
|
Actor b;
|
|
double mult;
|
|
double startangle, startpitch;
|
|
|
|
override int SpecialMissileHit( Actor victim )
|
|
{
|
|
if ( victim == b ) return 1;
|
|
return -1;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
b = Spawn("ASMDHitbox",pos);
|
|
b.target = self;
|
|
startpitch = pitch;
|
|
startangle = angle;
|
|
}
|
|
action void A_BallExplode()
|
|
{
|
|
if ( bAMBUSH ) return;
|
|
pitch = invoker.startpitch;
|
|
angle = invoker.startangle;
|
|
roll = 0;
|
|
UTMainHandler.DoBlast(self,70,70000);
|
|
int dmg = int(55*(1+invoker.mult));
|
|
A_Explode(dmg,70);
|
|
A_SprayDecal("ShockMarkBig",16);
|
|
Actor r;
|
|
if ( dmg > 60 )
|
|
{
|
|
SetStateLabel("AmpDeath");
|
|
A_SetScale(0.7);
|
|
let l = Spawn("ASMDSBeamLight",pos);
|
|
l.Args[3] = 120;
|
|
r = Spawn("ASMDSBeamRing",pos);
|
|
}
|
|
else
|
|
{
|
|
A_SetScale(1.3);
|
|
let l = Spawn("ASMDBeamLight",pos);
|
|
l.Args[3] = 120;
|
|
r = Spawn("ASMDBeamRing",pos);
|
|
}
|
|
Vector3 HitNormal = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
|
|
if ( BlockingLine ) HitNormal = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit();
|
|
else if ( BlockingFloor )
|
|
{
|
|
// find closest 3d floor for its normal
|
|
F3DFloor ff = null;
|
|
for ( int i=0; i<BlockingFloor.Get3DFloorCount(); i++ )
|
|
{
|
|
if ( !(BlockingFloor.Get3DFloor(i).top.ZAtPoint(pos.xy) ~== floorz) ) continue;
|
|
ff = BlockingFloor.Get3DFloor(i);
|
|
break;
|
|
}
|
|
if ( ff ) HitNormal = -ff.top.Normal;
|
|
else HitNormal = BlockingFloor.floorplane.Normal;
|
|
r.SetOrigin(r.Vec3Offset(0,0,2),false);
|
|
}
|
|
else if ( BlockingCeiling )
|
|
{
|
|
// find closest 3d floor for its normal
|
|
F3DFloor ff = null;
|
|
for ( int i=0; i<BlockingCeiling.Get3DFloorCount(); i++ )
|
|
{
|
|
if ( !(BlockingCeiling.Get3DFloor(i).bottom.ZAtPoint(pos.xy) ~== ceilingz) ) continue;
|
|
ff = BlockingCeiling.Get3DFloor(i);
|
|
break;
|
|
}
|
|
if ( ff ) HitNormal = -ff.bottom.Normal;
|
|
else HitNormal = BlockingCeiling.ceilingplane.Normal;
|
|
}
|
|
r.angle = atan2(HitNormal.y,HitNormal.x);
|
|
r.pitch = asin(-HitNormal.z);
|
|
r.scale *= 1.5;
|
|
A_PlaySound("shock/hit",CHAN_VOICE);
|
|
A_PlaySound("shock/ball",CHAN_WEAPON,pitch:FRandom[ASMD](0.5,1.5));
|
|
A_QuakeEx(4,4,4,30,0,200,"",QF_RELATIVE|QF_SCALEDOWN,falloff:70,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](2,6);
|
|
let s = Spawn("ASMDSpark",pos);
|
|
s.vel = pvel;
|
|
}
|
|
}
|
|
action void A_BallSpin()
|
|
{
|
|
for ( int i=0; i<6; i++ )
|
|
{
|
|
Vector3 x, y, z;
|
|
[x,y,z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
|
|
double a = FRandom[ASMD](0,360), s = FRandom[ASMD](0,0.15);
|
|
Vector3 dir;
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
dir = (x+y*cos(a)*s+z*sin(a)*s).unit();
|
|
break;
|
|
case 1:
|
|
dir = (y+x*cos(a)*s+z*sin(a)*s).unit();
|
|
break;
|
|
case 2:
|
|
dir = (-x+y*cos(a)*s+z*sin(a)*s).unit();
|
|
break;
|
|
case 3:
|
|
dir = (-y+x*cos(a)*s+z*sin(a)*s).unit();
|
|
break;
|
|
case 4:
|
|
dir = (z+x*cos(a)*s+y*sin(a)*s).unit();
|
|
break;
|
|
case 5:
|
|
dir = (-z+x*cos(a)*s+y*sin(a)*s).unit();
|
|
break;
|
|
}
|
|
let p = Spawn("ASMDSpark",level.Vec3Offset(pos,-vel));
|
|
p.vel = vel*0.5+dir*FRandom[ASMD](1,3);
|
|
}
|
|
pitch += 7.12;
|
|
angle += 5.25;
|
|
roll += 9.96;
|
|
}
|
|
Default
|
|
{
|
|
Obituary "$O_ASMD";
|
|
RenderStyle "Add";
|
|
DamageType 'jolted';
|
|
Radius 4;
|
|
Height 4;
|
|
Speed 20;
|
|
PROJECTILE;
|
|
+FORCEXYBILLBOARD;
|
|
+SKYEXPLODE;
|
|
+EXPLODEONWATER;
|
|
+FORCERADIUSDMG;
|
|
+NODAMAGETHRUST;
|
|
+INTERPOLATEANGLES;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TAZB A 1 Bright A_BallSpin();
|
|
Wait;
|
|
Death:
|
|
TNT1 A 0 A_BallExplode();
|
|
AEXP ABCDEF 3 Bright;
|
|
Stop;
|
|
AmpDeath:
|
|
SSMX ABCDEFGHIJ 2 Bright;
|
|
Stop;
|
|
SuperDeath:
|
|
PSMX ABCDEFGHIJ 2 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class ASMDBeam : Actor
|
|
{
|
|
ShockBeamTracer t;
|
|
Vector3 tracedir;
|
|
bool moving;
|
|
double totaldist;
|
|
|
|
Default
|
|
{
|
|
Obituary "$O_ASMD";
|
|
DamageType 'jolted';
|
|
RenderStyle "Add";
|
|
Radius 0.1;
|
|
Height 0;
|
|
Scale 1.8;
|
|
+NOGRAVITY;
|
|
+NOCLIP;
|
|
+DONTSPLASH;
|
|
+FORCERADIUSDMG;
|
|
+NODAMAGETHRUST;
|
|
+NOTELEPORT;
|
|
+FORCEXYBILLBOARD;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
t = new("ShockBeamTracer");
|
|
t.owner = target;
|
|
t.ignore = self;
|
|
moving = true;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( isFrozen() || !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=10; i<t.Results.Distance; i+=80 )
|
|
Spawn("ASMDBeamLight",Vec3Offset(tracedir.x*i,tracedir.y*i,tracedir.z*i));
|
|
for ( int i=0; i<t.Results.Distance; i+=4 )
|
|
{
|
|
Vector3 pofs = tracedir*FRandom[ASMD](0,2)+(FRandom[ASMD](-.5,.5),FRandom[ASMD](-.5,.5),FRandom[ASMD](-.5,.5));
|
|
let s = Spawn("ASMDSpark",Vec3Offset(tracedir.x*i+pofs.x,tracedir.y*i+pofs.y,tracedir.z*i+pofs.z));
|
|
s.scale *= 0.2;
|
|
s.vel = (FRandom[ASMD](-.3,.3),FRandom[ASMD](-.3,.3),FRandom[ASMD](-.3,.3));
|
|
}
|
|
for ( int i=10; i<t.Results.Distance; i+=20 )
|
|
{
|
|
let s = Spawn("ASMDRingTrail",Vec3Offset(tracedir.x*i,tracedir.y*i,tracedir.z*i));
|
|
s.angle = angle;
|
|
s.pitch = pitch;
|
|
}
|
|
if ( totaldist >= 10000.0 )
|
|
{
|
|
// reposition and explode on air
|
|
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,false);
|
|
double mult = Amplifier.GetMult(target,100);
|
|
BeamExplode(mult>1.5);
|
|
Actor r;
|
|
if ( mult > 1.5 ) r = Spawn("ASMDSBeamRing",pos);
|
|
else r = Spawn("ASMDBeamRing",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,false);
|
|
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,false);
|
|
double mult = Amplifier.GetMult(target,100);
|
|
Actor r;
|
|
if ( t.Results.HitActor is 'ASMDHitbox' )
|
|
{
|
|
BeamExplode(mult>1.5);
|
|
if ( target )
|
|
{
|
|
target.TakeInventory('ASMDAmmo',2);
|
|
UTMainHandler.DoSwing(target,(FRandom[ASMD](-0.1,-0.6),FRandom[ASMD](-0.1,0.5)),10,-2,3,SWING_Spring,3,6);
|
|
}
|
|
let b = t.Results.HitActor.target;
|
|
b.bAMBUSH = true;
|
|
b.ExplodeMissile();
|
|
b.pitch = 90;
|
|
b.angle = 0;
|
|
b.roll = 0;
|
|
UTMainHandler.DoBlast(b,240,140000);
|
|
b.A_Explode(int(55*3.9*mult),240);
|
|
b.A_SprayDecal("BigShockMark1",100);
|
|
b.A_SprayDecal("SBigShockMark2",100);
|
|
b.SetStateLabel("SuperDeath");
|
|
b.A_SetScale(1.8);
|
|
let l = Spawn("ASMDBlastLight",pos);
|
|
let r = Spawn("ASMDBlastRing",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,pitch:0.6);
|
|
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](1,32);
|
|
let s = Spawn("ASMDSpark",b.pos);
|
|
s.vel = pvel;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BeamExplode(mult>1.5);
|
|
t.Results.HitActor.DamageMobj(self,target,int(35*mult),'jolted',DMG_USEANGLE,atan2(t.Results.HitVector.y,t.Results.HitVector.x));
|
|
UTMainHandler.DoKnockback(t.Results.HitActor,t.Results.HitVector,60000);
|
|
if ( mult > 1.5 ) r = Spawn("ASMDSBeamRing",pos);
|
|
else r = Spawn("ASMDBeamRing",pos);
|
|
r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
|
|
r.pitch = asin(-t.Results.HitVector.z);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// reposition and explode on wall
|
|
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,false);
|
|
A_SprayDecal("ShockMark",16);
|
|
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 == 0 ) HitNormal *= -1;
|
|
}
|
|
else if ( t.Results.HitType == TRACE_HitFloor )
|
|
{
|
|
if ( t.Results.ffloor ) HitNormal = -t.Results.ffloor.top.Normal;
|
|
else HitNormal = t.Results.HitSector.floorplane.Normal;
|
|
}
|
|
else if ( t.Results.HitType == TRACE_HitCeiling )
|
|
{
|
|
if ( t.Results.ffloor ) HitNormal = -t.Results.ffloor.bottom.Normal;
|
|
else HitNormal = t.Results.HitSector.ceilingplane.Normal;
|
|
}
|
|
double mult = Amplifier.GetMult(target,100);
|
|
BeamExplode(mult>1.5);
|
|
Actor r;
|
|
if ( mult > 1.5 ) r = Spawn("ASMDSBeamRing",pos);
|
|
else r = Spawn("ASMDBeamRing",pos);
|
|
r.angle = atan2(HitNormal.y,HitNormal.x);
|
|
r.pitch = asin(-HitNormal.z);
|
|
}
|
|
}
|
|
void BeamExplode( bool amped = false )
|
|
{
|
|
moving = false;
|
|
if ( amped )
|
|
{
|
|
Scale *= 0.3;
|
|
SetStateLabel("AmpExplode");
|
|
Spawn("ASMDSBeamLight",pos);
|
|
}
|
|
else
|
|
{
|
|
SetStateLabel("Explode");
|
|
Spawn("ASMDBeamLight",pos);
|
|
}
|
|
A_QuakeEx(2,2,2,5,0,120,"",QF_RELATIVE|QF_SCALEDOWN,falloff:60,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](2,6);
|
|
let s = Spawn("ASMDSpark",pos);
|
|
s.vel = pvel;
|
|
}
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A -1;
|
|
Stop;
|
|
Explode:
|
|
AEXP ABCDEF 3 Bright;
|
|
Stop;
|
|
AmpExplode:
|
|
SSMX ABCDEFGHIJ 2 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class ASMD : UnrealWeapon
|
|
{
|
|
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,Dampener.Active(self)?.2:1.);
|
|
invoker.FireEffect();
|
|
A_Overlay(PSP_FLASH,"Flash");
|
|
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
|
|
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
|
|
UTMainHandler.DoFlash(self,Color(80,64,32,255),1);
|
|
UTMainHandler.DoSwing(self,(FRandom[ASMD](-0.1,-0.6),FRandom[ASMD](-0.1,0.5)),2,-0.3,3,SWING_Spring,0,4);
|
|
if ( !Dampener.Active(self) ) A_AlertMonsters();
|
|
A_QuakeEx(1,1,1,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
|
|
Vector3 x, y, z;
|
|
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
|
|
Vector3 origin = (pos.x,pos.y,player.viewz)+10*x+2.9*y-2.5*z;
|
|
Actor p = Spawn("ASMDBeam",origin);
|
|
p.angle = angle;
|
|
p.pitch = BulletSlope();
|
|
p.target = self;
|
|
int numpt = Random[ASMD](20,40);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
let s = Spawn("ViewASMDSpark",origin);
|
|
ViewASMDSpark(s).ofs = (10,2.9,-2.5);
|
|
s.target = self;
|
|
ViewASMDSpark(s).vvel += (FRandom[ASMD](0.5,2.0),FRandom[ASMD](-1.5,1.5),FRandom[ASMD](-1.5,1.5));
|
|
}
|
|
}
|
|
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,Dampener.Active(self)?.2:1.);
|
|
double mult = Amplifier.GetMult(self,80);
|
|
invoker.FireEffect();
|
|
A_Overlay(PSP_FLASH,"Flash");
|
|
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
|
|
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
|
|
UTMainHandler.DoFlash(self,Color(80,64,32,255),1);
|
|
UTMainHandler.DoSwing(self,(FRandom[ASMD](-0.1,-0.6),FRandom[ASMD](-0.1,0.5)),3,-0.4,3,SWING_Spring,0,4);
|
|
if ( !Dampener.Active(self) ) A_AlertMonsters();
|
|
A_QuakeEx(1,1,1,8,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
|
|
Vector3 x, y, z;
|
|
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
|
|
Vector3 origin = (pos.x,pos.y,player.viewz)+10*x+2.9*y-2.5*z;
|
|
Actor p = Spawn("ASMDBall",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;
|
|
ASMDBall(p).mult = mult-1;
|
|
int numpt = Random[ASMD](20,40);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
let s = Spawn("ViewASMDSpark",origin);
|
|
ViewASMDSpark(s).ofs = (10,2.9,-2.5);
|
|
s.target = self;
|
|
ViewASMDSpark(s).vvel += (FRandom[ASMD](0.5,2.0),FRandom[ASMD](-1.5,1.5),FRandom[ASMD](-1.5,1.5));
|
|
}
|
|
}
|
|
Default
|
|
{
|
|
Tag "$T_ASMD";
|
|
Inventory.PickupMessage "$I_ASMD";
|
|
Weapon.UpSound "shock/select";
|
|
Weapon.SlotNumber 4;
|
|
Weapon.SelectionOrder 4;
|
|
Weapon.SlotPriority 1;
|
|
Weapon.AmmoType "ASMDAmmo";
|
|
Weapon.AmmoUse 1;
|
|
Weapon.AmmoType2 "ASMDAmmo";
|
|
Weapon.AmmoUse2 1;
|
|
Weapon.AmmoGive 20;
|
|
UTWeapon.DropAmmo 10;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
ASMP A -1;
|
|
Stop;
|
|
ASMP B -1;
|
|
Stop;
|
|
Ready:
|
|
ASMS ABCDEFGHIJKLMN 1 A_WeaponReady(WRF_NOFIRE);
|
|
Idle:
|
|
#### # 8 A_Overlay(-9999,"Dummy"); // little hackeroo to make this more responsive
|
|
ASMI AB 30;
|
|
Goto Idle+1;
|
|
Dummy:
|
|
TNT1 A 1
|
|
{
|
|
A_CheckReload();
|
|
A_WeaponReady();
|
|
// that's a long-ass if
|
|
if ( player.FindPSprite(PSP_WEAPON).CurState.InStateSequence(invoker.FindState("Idle")) && (player.cmd.forwardmove || player.cmd.sidemove) && (player.vel.length() > 0.5) )
|
|
player.SetPSPrite(PSP_WEAPON,invoker.FindState("Sway"));
|
|
}
|
|
Wait;
|
|
Vapour:
|
|
#### # 8 A_Overlay(-9999,"Dummy");
|
|
ASMI A 6
|
|
{
|
|
A_PlaySound("asmd/vapour",CHAN_6,0.5);
|
|
A_Overlay(PSP_FLASH,"VapourFlash");
|
|
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
|
|
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
|
|
}
|
|
ASMV ABCDEFGHIJ 4;
|
|
Goto Idle;
|
|
VapourFlash:
|
|
ASVI A 6;
|
|
ASVF ABCDEFGHIJ 4;
|
|
Stop;
|
|
Sway:
|
|
#### # 4;
|
|
ASMI C 10 A_JumpIf((!player.cmd.forwardmove && !player.cmd.sidemove) || (player.vel.length() < 0.5),4);
|
|
ASMI D 10 A_JumpIf((!player.cmd.forwardmove && !player.cmd.sidemove) || (player.vel.length() < 0.5),5);
|
|
ASMI E 10 A_JumpIf((!player.cmd.forwardmove && !player.cmd.sidemove) || (player.vel.length() < 0.5),6);
|
|
ASMI F 10 A_JumpIf((!player.cmd.forwardmove && !player.cmd.sidemove) || (player.vel.length() < 0.5),7);
|
|
Goto Sway+1;
|
|
ASMI C 4;
|
|
ASMI A 0 A_Jump(32,"Vapour");
|
|
Goto Idle;
|
|
ASMI D 4;
|
|
ASMI A 0 A_Jump(32,"Vapour");
|
|
Goto Idle;
|
|
ASMI E 4;
|
|
ASMI A 0 A_Jump(32,"Vapour");
|
|
Goto Idle;
|
|
ASMI F 4;
|
|
ASMI A 0 A_Jump(32,"Vapour");
|
|
Goto Idle;
|
|
Fire:
|
|
#### # 1
|
|
{
|
|
A_ShockFire();
|
|
A_Overlay(-9999,"Null");
|
|
}
|
|
ASMF ABCDEFGH 3;
|
|
ASMF H 0 A_Jump(48,"Vapour");
|
|
Goto Idle;
|
|
AltFire:
|
|
#### # 1
|
|
{
|
|
A_ShockAlt();
|
|
A_Overlay(-9999,"Null");
|
|
}
|
|
ASMA ABCDFGHIJ 2;
|
|
ASMA J 0 A_Jump(48,"Vapour");
|
|
Goto Idle;
|
|
Deselect:
|
|
ASMD A 1 A_Overlay(-9999,"Null");
|
|
ASMD BCDEFGHIJ 1;
|
|
ASMD J 1 A_Lower(int.max);
|
|
Wait;
|
|
Select:
|
|
ASMS A 1 A_Raise(int.max);
|
|
Wait;
|
|
Flash:
|
|
ASFF A 2 Bright
|
|
{
|
|
let l = Spawn("ASMDLight",pos);
|
|
l.target = self;
|
|
}
|
|
Stop;
|
|
}
|
|
}
|