- Various fixes for the Combined Patch. - Some safeguards for force field and sentries so they don't bug the hell out if receiving crushing or ice damage.
849 lines
19 KiB
Text
849 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("asmd/hit",CHAN_VOICE);
|
|
A_PlaySound("asmd/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 )
|
|
{
|
|
if ( !sv_infiniteammo && !target.FindInventory('PowerInfiniteAmmo',true) )
|
|
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("asmd/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("asmd/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("asmd/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("asmd/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 "asmd/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;
|
|
}
|
|
}
|