- Spent mags for Automag, Flak Cannon and Demolisher (needs updated DT). - Betamag defaults to both having the 0.83 skin, other options put on add-ons. - Adjustments to bullet casings. - Fixed flames producing water splashes. - Fixed female models having male gibs. - Corrected ASMD ball hit behavior to match Unreal. - Added bubble trail to Stinger when underwater.
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 = level.Vec3Offset(target.Vec2OffsetZ(0,0,target.player.viewz),x*ofs.x+y*ofs.y+z*ofs.z);
|
|
SetOrigin(origin,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 int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
|
|
{
|
|
if ( mod == 'jolted' )
|
|
return 0;
|
|
if ( !bAMBUSH )
|
|
{
|
|
bAMBUSH = true;
|
|
if ( target && target.InStateSequence(target.CurState,target.FindState("Spawn")) )
|
|
target.ExplodeMissile();
|
|
}
|
|
return 0;
|
|
}
|
|
override bool CanCollideWith( Actor other, bool passive )
|
|
{
|
|
return true;
|
|
}
|
|
Default
|
|
{
|
|
Radius 6;
|
|
Height 12;
|
|
+SHOOTABLE;
|
|
}
|
|
}
|
|
|
|
Class ASMDBall : Actor
|
|
{
|
|
Actor b;
|
|
double mult;
|
|
double startangle, startpitch;
|
|
|
|
override int SpecialMissileHit( Actor victim )
|
|
{
|
|
if ( victim is 'ASMDHitbox' ) 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.ShootThroughList.Clear();
|
|
t.Trace(pos,cursector,tracedir,1000,0);
|
|
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
|
|
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
|
|
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 = level.Vec3Offset(Vec2OffsetZ(0,0,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 = level.Vec3Offset(Vec2OffsetZ(0,0,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 2000;
|
|
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;
|
|
}
|
|
}
|