Pusher autoswitches to the next weapon after it (skipping the Deep Impact if possible) when thrown, instead of switching to the best weapon, which may have undesirable consequences. Added icons for weapons and ammo, this doesn't have any actual use yet, but will in the future if I ever implement a custom alt hud.
1852 lines
48 KiB
Text
1852 lines
48 KiB
Text
// Imanaki Corp Hellfire Cannon Mk3, aka "Hellblazer" (from SWWM series, originally inspired by the Hellraiser from OMGWEAPONS)
|
|
// Slot 6, replaces Rocket Launcher, Phoenix Rod, Firestorm
|
|
|
|
Class HellblazerExplLight : PaletteLight
|
|
{
|
|
Default
|
|
{
|
|
Tag "HellExpl";
|
|
Args 0,0,0,200;
|
|
ReactionTime 25;
|
|
}
|
|
}
|
|
Class HellblazerExplLight2 : PaletteLight
|
|
{
|
|
Default
|
|
{
|
|
Tag "HellExpl";
|
|
Args 0,0,0,120;
|
|
ReactionTime 20;
|
|
}
|
|
}
|
|
Class HellblazerExplLight3 : PaletteLight
|
|
{
|
|
Default
|
|
{
|
|
Tag "HellExpl";
|
|
Args 0,0,0,900;
|
|
ReactionTime 60;
|
|
}
|
|
}
|
|
|
|
Class HellblazerSubExpl : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Scale 2.2;
|
|
Alpha .4;
|
|
Radius 0.1;
|
|
Height 0;
|
|
+NOGRAVITY;
|
|
+NOBLOCKMAP;
|
|
+FORCEXYBILLBOARD;
|
|
+NOTELEPORT;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
HEXP ABCDEFGHIJKLMNOPQR 1 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class HellblazerRing : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Scale 2.;
|
|
Radius 0.1;
|
|
Height 0;
|
|
+NOGRAVITY;
|
|
+NOBLOCKMAP;
|
|
+FORCEXYBILLBOARD;
|
|
+NOTELEPORT;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
XRG3 ACEGIKMOQSUW 1 Bright A_SetScale(scale.x*1.15);
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class HellblazerRing2 : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Scale 3.;
|
|
Radius 0.1;
|
|
Height 0;
|
|
+NOGRAVITY;
|
|
+NOBLOCKMAP;
|
|
+FORCEXYBILLBOARD;
|
|
+NOTELEPORT;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
XRG3 ABCDEFGHIJKLMNOPQRSTUVWX 1 Bright A_SetScale(scale.x*1.1);
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class HellblazerTrail : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Radius .1;
|
|
Height 0.;
|
|
Scale .2;
|
|
Alpha .3;
|
|
+NOGRAVITY;
|
|
+NOBLOCKMAP;
|
|
+DONTSPLASH;
|
|
+NOTELEPORT;
|
|
+FORCEXYBILLBOARD;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
SetState(FindState("Spawn")+Random[ExploS](0,7));
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
JFLR ABCDEFGH 1 Bright
|
|
{
|
|
A_FadeOut(.06);
|
|
A_SetScale(scale.x*.95);
|
|
if ( waterlevel > 0 )
|
|
{
|
|
let b = Spawn("SWWMBubble",pos);
|
|
b.vel = vel;
|
|
b.scale *= scale.x;
|
|
Destroy();
|
|
}
|
|
}
|
|
Loop;
|
|
}
|
|
}
|
|
|
|
Class HellblazerFlare : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Radius .1;
|
|
Height 0.;
|
|
+NOGRAVITY;
|
|
+NOBLOCKMAP;
|
|
+DONTSPLASH;
|
|
+NOTELEPORT;
|
|
+FORCEXYBILLBOARD;
|
|
}
|
|
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
if ( !master ) return;
|
|
State sp = FindState("Spawn");
|
|
if ( master is 'HellblazerCrackshot' ) SetState(sp+1);
|
|
else if ( master is 'HellblazerRavager' ) SetState(sp+2);
|
|
else if ( master is 'HellblazerWarhead' ) SetState(sp+3);
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !master || !master.bMISSILE )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
Vector3 traildir = -(cos(master.angle)*cos(master.pitch),sin(master.angle)*cos(master.pitch),sin(-master.pitch));
|
|
SetOrigin(level.Vec3Offset(master.pos,traildir*3),true);
|
|
}
|
|
|
|
States
|
|
{
|
|
Spawn:
|
|
HFLR ABCD -1 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
// rockets
|
|
Class HellblazerMissile : Actor
|
|
{
|
|
int deto;
|
|
|
|
Default
|
|
{
|
|
Obituary "$O_HELLBLAZER";
|
|
DamageType 'Exploded';
|
|
Radius 4;
|
|
Height 8;
|
|
Speed 50;
|
|
PROJECTILE;
|
|
+EXPLODEONWATER;
|
|
+FORCERADIUSDMG;
|
|
+NODAMAGETHRUST;
|
|
}
|
|
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
if ( bNOGRAVITY )
|
|
{
|
|
A_StartSound("hellblazer/fly",CHAN_BODY,CHANF_LOOPING,1.,2.);
|
|
let t = Spawn("HellblazerFlare",pos);
|
|
t.master = self;
|
|
}
|
|
}
|
|
|
|
void A_BlazerTick( Color smokecol )
|
|
{
|
|
Vector3 traildir = -(cos(angle)*cos(pitch),sin(angle)*cos(pitch),sin(-pitch));
|
|
for ( int i=0; i<3; i++ )
|
|
{
|
|
let s = Spawn("SWWMSmoke",level.Vec3Offset(pos,traildir*3));
|
|
s.SetShade(smokecol*Random[Hellblazer](48,63));
|
|
s.scale *= FRandom[Hellblazer](.8,1.2);
|
|
s.special1 = Random[Hellblazer](0,2);
|
|
s.alpha *= .5;
|
|
s.vel = .3*vel + (traildir+(FRandom[Hellblazer](-.4,.4),FRandom[Hellblazer](-.4,.4),FRandom[Hellblazer](-.4,.4))).unit()*FRandom[Hellblazer](1.,2.);
|
|
}
|
|
if ( bNOGRAVITY )
|
|
{
|
|
for ( double i=0.; i<vel.length(); i+= 5. )
|
|
{
|
|
let t = Spawn("HellblazerTrail",level.Vec3Offset(pos,-vel.unit()*i+traildir*3));
|
|
t.vel = traildir*4.;
|
|
}
|
|
}
|
|
if ( deto > 1 )
|
|
{
|
|
ExplodeMissile();
|
|
return;
|
|
}
|
|
// proximity check
|
|
let bt = BlockThingsIterator.Create(self,200);
|
|
while ( bt.Next() )
|
|
{
|
|
let t = bt.Thing;
|
|
if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),bNOGRAVITY?50:90) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
|
deto++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void A_BlazerMissileExplode()
|
|
{
|
|
bForceXYBillboard = true;
|
|
bRollSprite = false;
|
|
A_SetRenderStyle(1.0,STYLE_Add);
|
|
A_SprayDecal("BigScorch",50);
|
|
A_SetScale(4.5);
|
|
SWWMHandler.DoBlast(self,200,320000);
|
|
A_Explode(500,200);
|
|
A_NoGravity();
|
|
A_QuakeEx(5,5,5,15,0,1500,"",QF_RELATIVE|QF_SCALEDOWN,falloff:500,rollIntensity:.8);
|
|
A_StopSound(CHAN_BODY);
|
|
A_StartSound("hellblazer/hitm",CHAN_WEAPON,attenuation:.8);
|
|
A_StartSound("hellblazer/hitm",CHAN_VOICE,attenuation:.5);
|
|
A_AlertMonsters(2500);
|
|
Spawn("HellblazerExplLight",pos);
|
|
int numpt = Random[Hellblazer](12,24);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](2,8);
|
|
let s = Spawn("SWWMSmoke",pos);
|
|
s.vel = pvel;
|
|
s.SetShade(Color(4,3,2)*Random[Hellblazer](48,63));
|
|
s.special1 = Random[Hellblazer](1,4);
|
|
s.scale *= 2.8;
|
|
s.alpha *= .4;
|
|
}
|
|
numpt = Random[Hellblazer](8,12);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](4,12);
|
|
let s = Spawn("SWWMSpark",pos);
|
|
s.vel = pvel;
|
|
}
|
|
numpt = Random[Hellblazer](12,16);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](10,20);
|
|
let s = Spawn("SWWMChip",pos);
|
|
s.vel = pvel;
|
|
s.scale *= FRandom[Hellblazer](0.9,1.8);
|
|
}
|
|
Spawn("HellblazerRing",pos);
|
|
}
|
|
|
|
void A_SubExpl( double xscale = 1. )
|
|
{
|
|
special1++;
|
|
if ( (special1 > 8) || !(special1%2) ) return;
|
|
int numpt = Random[Hellblazer](0,8-special1);
|
|
double ang, pt;
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
ang = FRandom[Hellblazer](0,360);
|
|
pt = FRandom[Hellblazer](-90,90);
|
|
FLineTraceData d;
|
|
Vector3 HitNormal;
|
|
LineTrace(ang,FRandom[Hellblazer](10,20)+10*special1*xscale,pt,TRF_THRUACTORS,data:d);
|
|
hitnormal = -d.HitDir;
|
|
if ( d.HitType == TRACE_HitFloor )
|
|
{
|
|
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal;
|
|
else hitnormal = d.HitSector.floorplane.Normal;
|
|
}
|
|
else if ( d.HitType == TRACE_HitCeiling )
|
|
{
|
|
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal;
|
|
else hitnormal = d.HitSector.ceilingplane.Normal;
|
|
}
|
|
else if ( d.HitType == TRACE_HitWall )
|
|
{
|
|
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
|
|
if ( !d.LineSide ) hitnormal *= -1;
|
|
}
|
|
let p = Spawn("HellblazerSubExpl",d.HitLocation+hitnormal*4);
|
|
p.angle = atan2(hitnormal.y,hitnormal.x);
|
|
p.pitch = asin(-hitnormal.z);
|
|
p.target = target;
|
|
p.scale *= xscale*(2-special1*.1);
|
|
p.alpha *= 1-special1*.1;
|
|
}
|
|
}
|
|
|
|
States
|
|
{
|
|
Spawn:
|
|
XZW1 A 1 A_BlazerTick(Color(4,3,2));
|
|
Wait;
|
|
Death:
|
|
TNT1 A 0 A_BlazerMissileExplode();
|
|
HEXP ABCDEFGHIJKLMNOPQR 1 Bright A_SubExpl();
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class HellblazerCrackshot : HellblazerMissile
|
|
{
|
|
void A_BlazerCrackshotExplode()
|
|
{
|
|
bForceXYBillboard = true;
|
|
bRollSprite = false;
|
|
A_SetRenderStyle(1.0,STYLE_Add);
|
|
A_SprayDecal("BigScorch",50);
|
|
A_SetScale(6.);
|
|
SWWMHandler.DoBlast(self,250,320000);
|
|
A_Explode(500,250);
|
|
A_NoGravity();
|
|
A_QuakeEx(6,6,6,20,0,2000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:800,rollIntensity:1.);
|
|
A_StopSound(CHAN_BODY);
|
|
A_StartSound("hellblazer/hitc",CHAN_WEAPON,attenuation:.7);
|
|
A_StartSound("hellblazer/hitc",CHAN_VOICE,attenuation:.4);
|
|
A_AlertMonsters(3000);
|
|
Spawn("HellblazerExplLight",pos);
|
|
int numpt = Random[Hellblazer](12,24);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](2,8);
|
|
let s = Spawn("SWWMSmoke",pos);
|
|
s.vel = pvel;
|
|
s.SetShade(Color(2,4,2)*Random[Hellblazer](48,63));
|
|
s.special1 = Random[Hellblazer](1,4);
|
|
s.scale *= 2.8;
|
|
s.alpha *= .4;
|
|
}
|
|
numpt = Random[Hellblazer](8,12);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](4,12);
|
|
let s = Spawn("SWWMSpark",pos);
|
|
s.vel = pvel;
|
|
}
|
|
numpt = Random[Hellblazer](12,16);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](10,20);
|
|
let s = Spawn("SWWMChip",pos);
|
|
s.vel = pvel;
|
|
s.scale *= FRandom[Hellblazer](0.9,1.8);
|
|
}
|
|
Spawn("HellblazerRing",pos);
|
|
for ( int i=0; i<8; i++ )
|
|
{
|
|
double ang = FRandom[Hellblazer](0,360);
|
|
double pt = FRandom[Hellblazer](-90,90);
|
|
let c = Spawn("HellblazerClusterMini",pos);
|
|
c.angle = ang;
|
|
c.pitch = pt;
|
|
c.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),sin(-pt))*c.speed*FRandom[Hellblazer](.8,1.2);
|
|
c.target = target;
|
|
c.ReactionTime += Random[Hellblazer](-10,10);
|
|
}
|
|
}
|
|
|
|
States
|
|
{
|
|
Spawn:
|
|
XZW1 A 1 A_BlazerTick(Color(2,4,2));
|
|
Wait;
|
|
Death:
|
|
TNT1 A 0 A_BlazerCrackshotExplode();
|
|
HEXP ABCDEFGHIJKLMNOPQR 1 Bright A_SubExpl(1.25);
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class HellblazerRavager : HellblazerMissile
|
|
{
|
|
void A_BlazerRavagerExplode()
|
|
{
|
|
bForceXYBillboard = true;
|
|
bRollSprite = false;
|
|
A_SetRenderStyle(1.0,STYLE_Add);
|
|
A_SprayDecal("HugeScorch",50);
|
|
A_SetScale(8.);
|
|
SWWMHandler.DoBlast(self,300,320000);
|
|
A_Explode(800,300);
|
|
A_NoGravity();
|
|
A_QuakeEx(6,6,6,30,0,2000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:800,rollIntensity:1.);
|
|
A_StopSound(CHAN_BODY);
|
|
A_StartSound("hellblazer/hitr",CHAN_WEAPON,attenuation:.6);
|
|
A_StartSound("hellblazer/hitr",CHAN_VOICE,attenuation:.3);
|
|
A_AlertMonsters(4500);
|
|
Spawn("HellblazerExplLight",pos);
|
|
int numpt = Random[Hellblazer](16,28);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](4,12);
|
|
let s = Spawn("SWWMSmoke",pos);
|
|
s.vel = pvel;
|
|
s.SetShade(Color(4,2,2)*Random[Hellblazer](48,63));
|
|
s.special1 = Random[Hellblazer](2,5);
|
|
s.scale *= 3.2;
|
|
s.alpha *= .3;
|
|
}
|
|
numpt = Random[Hellblazer](8,12);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](4,12);
|
|
let s = Spawn("SWWMSpark",pos);
|
|
s.vel = pvel;
|
|
}
|
|
numpt = Random[Hellblazer](12,20);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](10,20);
|
|
let s = Spawn("SWWMChip",pos);
|
|
s.vel = pvel;
|
|
s.scale *= FRandom[Hellblazer](0.9,1.8);
|
|
}
|
|
Spawn("HellblazerRing",pos);
|
|
}
|
|
|
|
void A_RavagerSub()
|
|
{
|
|
special2++;
|
|
if ( (special2 > 10) || (special2%3) ) return;
|
|
int numpt = 6-special2/2;
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
double ang = FRandom[Hellblazer](0,360);
|
|
double pt = FRandom[Hellblazer](-90,90);
|
|
let c = Spawn("HellblazerRavagerArm",pos);
|
|
c.angle = ang;
|
|
c.pitch = pt;
|
|
c.target = target;
|
|
}
|
|
}
|
|
|
|
States
|
|
{
|
|
Spawn:
|
|
XZW1 A 1 A_BlazerTick(Color(4,2,2));
|
|
Wait;
|
|
Death:
|
|
TNT1 A 0 A_BlazerRavagerExplode();
|
|
HEXP ABCDEFGHIJKLMNOPQR 1 Bright
|
|
{
|
|
A_SubExpl(2.);
|
|
A_RavagerSub();
|
|
}
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class HellblazerWarhead : HellblazerMissile
|
|
{
|
|
void A_BlazerWarheadExplode()
|
|
{
|
|
bForceXYBillboard = true;
|
|
bRollSprite = false;
|
|
A_SetRenderStyle(1.0,STYLE_Add);
|
|
A_SprayDecal("WumboScorch",150);
|
|
A_SetScale(7.);
|
|
SWWMHandler.DoBlast(self,500,600000);
|
|
A_Explode(2500,500);
|
|
A_NoGravity();
|
|
A_QuakeEx(9,9,9,150,0,12000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:4000,rollIntensity:2.);
|
|
A_StopSound(CHAN_BODY);
|
|
A_StartSound("hellblazer/hitw",CHAN_WEAPON,attenuation:.4);
|
|
A_StartSound("hellblazer/hitw",CHAN_VOICE,attenuation:.1);
|
|
A_AlertMonsters(40000);
|
|
Spawn("HellblazerExplLight3",pos);
|
|
int numpt = Random[Hellblazer](20,30);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](4,20);
|
|
let s = Spawn("SWWMSmoke",pos);
|
|
s.vel = pvel;
|
|
s.SetShade(Color(3,2,4)*Random[Hellblazer](48,63));
|
|
s.special1 = Random[Hellblazer](3,8);
|
|
s.scale *= 4.;
|
|
s.alpha *= .4;
|
|
}
|
|
numpt = Random[Hellblazer](10,20);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](4,28);
|
|
let s = Spawn("SWWMSpark",pos);
|
|
s.vel = pvel;
|
|
}
|
|
numpt = Random[Hellblazer](20,25);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](10,40);
|
|
let s = Spawn("SWWMChip",pos);
|
|
s.vel = pvel;
|
|
s.scale *= FRandom[Hellblazer](0.9,1.8);
|
|
}
|
|
Spawn("HellblazerRing2",pos);
|
|
}
|
|
|
|
void A_WarheadSub()
|
|
{
|
|
if ( special1 < 40 )
|
|
{
|
|
SWWMHandler.DoBlast(self,300+special1*10,600000-special1*12000);
|
|
A_Explode(200-special1*5,300+special1*10);
|
|
}
|
|
special1++;
|
|
if ( (special1 <= 30) && !(special1%2) )
|
|
{
|
|
int numpt = Random[Hellblazer](0,30-special1);
|
|
double ang, pt;
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
ang = FRandom[Hellblazer](0,360);
|
|
pt = FRandom[Hellblazer](-90,90);
|
|
FLineTraceData d;
|
|
Vector3 HitNormal;
|
|
LineTrace(ang,FRandom[Hellblazer](30,40)+10*special1,pt,TRF_THRUACTORS,data:d);
|
|
hitnormal = -d.HitDir;
|
|
if ( d.HitType == TRACE_HitFloor )
|
|
{
|
|
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal;
|
|
else hitnormal = d.HitSector.floorplane.Normal;
|
|
}
|
|
else if ( d.HitType == TRACE_HitCeiling )
|
|
{
|
|
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal;
|
|
else hitnormal = d.HitSector.ceilingplane.Normal;
|
|
}
|
|
else if ( d.HitType == TRACE_HitWall )
|
|
{
|
|
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
|
|
if ( !d.LineSide ) hitnormal *= -1;
|
|
}
|
|
let p = Spawn("HellblazerSubExpl",d.HitLocation+hitnormal*4);
|
|
p.angle = atan2(hitnormal.y,hitnormal.x);
|
|
p.pitch = asin(-hitnormal.z);
|
|
p.target = target;
|
|
p.scale *= (3-special1*.02);
|
|
p.alpha *= 1-special1*.02;
|
|
}
|
|
}
|
|
special2++;
|
|
if ( (special2 <= 9) && !(special2%3) )
|
|
{
|
|
int numpt = 5-special2/2;
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
double ang = FRandom[Hellblazer](0,360);
|
|
double pt = FRandom[Hellblazer](-90,90);
|
|
let c = Spawn("HellblazerWarheadArm",pos);
|
|
c.angle = ang;
|
|
c.pitch = pt;
|
|
c.target = target;
|
|
}
|
|
}
|
|
}
|
|
|
|
States
|
|
{
|
|
Spawn:
|
|
XZW1 A 1 A_BlazerTick(Color(3,2,4));
|
|
Wait;
|
|
Death:
|
|
TNT1 A 0 A_BlazerWarheadExplode();
|
|
HEXP AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRR 1 Bright A_WarheadSub();
|
|
TNT1 A 1
|
|
{
|
|
A_WarheadSub();
|
|
A_FadeOut(.05);
|
|
}
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Mixin Class HellblazerGrenade
|
|
{
|
|
double rollvel, anglevel, pitchvel;
|
|
Vector3 oldvel;
|
|
|
|
Default
|
|
{
|
|
BounceFactor 1.;
|
|
WallBounceFactor 1.;
|
|
Gravity .35;
|
|
ReactionTime 85;
|
|
-NOGRAVITY;
|
|
+USEBOUNCESTATE;
|
|
+BOUNCEONWALLS;
|
|
+BOUNCEONFLOORS;
|
|
+BOUNCEONCEILINGS;
|
|
+ALLOWBOUNCEONACTORS;
|
|
+DONTBOUNCEONSKY;
|
|
+CANBOUNCEWATER;
|
|
+INTERPOLATEANGLES;
|
|
+ROLLSPRITE;
|
|
+ROLLCENTER;
|
|
}
|
|
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
rollvel = FRandom[Hellblazer](-4,4);
|
|
anglevel = FRandom[Hellblazer](-4,4);
|
|
pitchvel = FRandom[Hellblazer](-4,4);
|
|
oldvel = vel;
|
|
}
|
|
override void Tick()
|
|
{
|
|
oldvel = vel;
|
|
Super.Tick();
|
|
if ( isFrozen() || !InStateSequence(CurState,FindState("Spawn")) ) return;
|
|
roll += rollvel;
|
|
angle += anglevel;
|
|
pitch += pitchvel;
|
|
ReactionTime--;
|
|
if ( ReactionTime <= 0 ) ExplodeMissile();
|
|
}
|
|
void A_HandleBounce()
|
|
{
|
|
Vector3 HitNormal = -vel.unit();
|
|
F3DFloor ff;
|
|
if ( BlockingFloor )
|
|
{
|
|
// find closest 3d floor for its normal
|
|
for ( int i=0; i<CurSector.Get3DFloorCount(); i++ )
|
|
{
|
|
if ( !(CurSector.Get3DFloor(i).top.ZAtPoint(pos.xy) ~== floorz) ) continue;
|
|
ff = CurSector.Get3DFloor(i);
|
|
break;
|
|
}
|
|
if ( ff ) HitNormal = -ff.top.Normal;
|
|
else HitNormal = BlockingFloor.floorplane.Normal;
|
|
}
|
|
else if ( BlockingCeiling )
|
|
{
|
|
// find closest 3d floor for its normal
|
|
for ( int i=0; i<CurSector.Get3DFloorCount(); i++ )
|
|
{
|
|
if ( !(CurSector.Get3DFloor(i).bottom.ZAtPoint(pos.xy) ~== ceilingz) ) continue;
|
|
ff = CurSector.Get3DFloor(i);
|
|
break;
|
|
}
|
|
if ( ff ) HitNormal = -ff.bottom.Normal;
|
|
else HitNormal = BlockingCeiling.ceilingplane.Normal;
|
|
}
|
|
else if ( BlockingLine )
|
|
{
|
|
HitNormal = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit();
|
|
if ( !SWWMUtility.PointOnLineSide(pos.xy,BlockingLine) )
|
|
HitNormal *= -1;
|
|
}
|
|
else if ( BlockingMobj )
|
|
{
|
|
Vector3 diff = level.Vec3Diff(BlockingMobj.Vec3Offset(0,0,BlockingMobj.Height/2),pos);
|
|
HitNormal = diff.unit();
|
|
}
|
|
// undo the bounce, we need to hook in our own
|
|
vel = oldvel;
|
|
// re-do the bounce with our formula
|
|
Vector3 RealHitNormal = HitNormal;
|
|
HitNormal = (HitNormal+(FRandom[Hellblazer](-.1,.1),FRandom[Hellblazer](-.1,.1),FRandom[Hellblazer](-.1,.1))).unit();
|
|
if ( (HitNormal dot RealHitNormal) < 0 ) HitNormal *= -.5;
|
|
vel = FRandom[Hellblazer](.8,.9)*((vel dot HitNormal)*HitNormal*(FRandom[Hellblazer](-2.,-1.6))+vel);
|
|
if ( vel.z > 10 ) vel.z = 0.5*(10+vel.z);
|
|
bHITOWNER = true;
|
|
if ( vel.length() < 4. )
|
|
{
|
|
ClearBounce();
|
|
ExplodeMissile();
|
|
return;
|
|
}
|
|
if ( swwm_extraalert ) A_AlertMonsters(300);
|
|
A_StartSound("hellblazer/bounce",CHAN_ITEM);
|
|
rollvel = FRandom[Hellblazer](-16,16);
|
|
anglevel = FRandom[Hellblazer](-16,16);
|
|
pitchvel = FRandom[Hellblazer](-16,16);
|
|
}
|
|
States
|
|
{
|
|
Bounce:
|
|
XZW1 A 0 A_HandleBounce();
|
|
Goto Spawn;
|
|
}
|
|
}
|
|
|
|
// grenades
|
|
Class HellblazerMissile2 : HellblazerMissile
|
|
{
|
|
Mixin HellblazerGrenade;
|
|
}
|
|
|
|
Class HellblazerCrackshot2 : HellblazerCrackshot
|
|
{
|
|
Mixin HellblazerGrenade;
|
|
}
|
|
|
|
Class HellblazerRavager2 : HellblazerRavager
|
|
{
|
|
Mixin HellblazerGrenade;
|
|
}
|
|
|
|
Class HellblazerWarhead2 : HellblazerWarhead
|
|
{
|
|
Mixin HellblazerGrenade;
|
|
}
|
|
|
|
Class HellblazerClusterMini : HellblazerMissile2
|
|
{
|
|
Default
|
|
{
|
|
Radius 2;
|
|
Height 4;
|
|
Speed 20;
|
|
ReactionTime 30;
|
|
}
|
|
|
|
void A_ClusterTick( Color smokecol )
|
|
{
|
|
Vector3 traildir = -(cos(angle)*cos(pitch),sin(angle)*cos(pitch),sin(-pitch));
|
|
for ( int i=0; i<2; i++ )
|
|
{
|
|
let s = Spawn("SWWMSmoke",level.Vec3Offset(pos,traildir*3));
|
|
s.SetShade(smokecol*Random[Hellblazer](48,63));
|
|
s.scale *= FRandom[Hellblazer](.6,.8);
|
|
s.special1 = Random[Hellblazer](0,1);
|
|
s.alpha *= .4;
|
|
s.vel = .3*vel + (traildir+(FRandom[Hellblazer](-.4,.4),FRandom[Hellblazer](-.4,.4),FRandom[Hellblazer](-.4,.4))).unit()*FRandom[Hellblazer](1.,2.);
|
|
}
|
|
if ( (deto > 1) && (GetAge() > 2) )
|
|
{
|
|
ExplodeMissile();
|
|
return;
|
|
}
|
|
// proximity check
|
|
let bt = BlockThingsIterator.Create(self,200);
|
|
while ( bt.Next() )
|
|
{
|
|
let t = bt.Thing;
|
|
if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain')) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),80) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
|
|
deto++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void A_ClusterExplode()
|
|
{
|
|
bForceXYBillboard = true;
|
|
bRollSprite = false;
|
|
A_SetRenderStyle(1.0,STYLE_Add);
|
|
A_SprayDecal("BigScorch",50);
|
|
A_SetScale(2.5);
|
|
SWWMHandler.DoBlast(self,150,200000);
|
|
A_Explode(100,150);
|
|
A_NoGravity();
|
|
A_QuakeEx(4,4,4,12,0,1000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:400,rollIntensity:.6);
|
|
A_StopSound(CHAN_BODY);
|
|
A_StartSound("hellblazer/hitcs",CHAN_WEAPON,attenuation:.9);
|
|
A_StartSound("hellblazer/hitcs",CHAN_VOICE,attenuation:.5);
|
|
A_AlertMonsters(2000);
|
|
Spawn("HellblazerExplLight2",pos);
|
|
int numpt = Random[Hellblazer](4,8);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](1,5);
|
|
let s = Spawn("SWWMSmoke",pos);
|
|
s.vel = pvel;
|
|
s.SetShade(Color(2,4,2)*Random[Hellblazer](48,63));
|
|
s.special1 = Random[Hellblazer](1,3);
|
|
s.scale *= 1.5;
|
|
s.alpha *= .4;
|
|
}
|
|
numpt = Random[Hellblazer](4,6);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](2,5);
|
|
let s = Spawn("SWWMSpark",pos);
|
|
s.vel = pvel;
|
|
}
|
|
numpt = Random[Hellblazer](4,6);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](5,10);
|
|
let s = Spawn("SWWMChip",pos);
|
|
s.vel = pvel;
|
|
s.scale *= FRandom[Hellblazer](0.8,1.4);
|
|
}
|
|
let r = Spawn("HellblazerRing",pos);
|
|
r.scale *= .4;
|
|
}
|
|
void A_ClusterSubExpl()
|
|
{
|
|
special1++;
|
|
if ( (special1 > 5) || !(special1%2) ) return;
|
|
int numpt = Random[Hellblazer](0,5-special1);
|
|
double ang, pt;
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
ang = FRandom[Hellblazer](0,360);
|
|
pt = FRandom[Hellblazer](-90,90);
|
|
FLineTraceData d;
|
|
Vector3 HitNormal;
|
|
LineTrace(ang,FRandom[Hellblazer](6,12)+6*special1,pt,TRF_THRUACTORS,data:d);
|
|
hitnormal = -d.HitDir;
|
|
if ( d.HitType == TRACE_HitFloor )
|
|
{
|
|
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal;
|
|
else hitnormal = d.HitSector.floorplane.Normal;
|
|
}
|
|
else if ( d.HitType == TRACE_HitCeiling )
|
|
{
|
|
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal;
|
|
else hitnormal = d.HitSector.ceilingplane.Normal;
|
|
}
|
|
else if ( d.HitType == TRACE_HitWall )
|
|
{
|
|
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
|
|
if ( !d.LineSide ) hitnormal *= -1;
|
|
}
|
|
let p = Spawn("HellblazerSubExpl",d.HitLocation+hitnormal*4);
|
|
p.angle = atan2(hitnormal.y,hitnormal.x);
|
|
p.pitch = asin(-hitnormal.z);
|
|
p.target = target;
|
|
p.scale *= 1.5-special1*.1;
|
|
p.alpha *= 1-special1*.1;
|
|
}
|
|
}
|
|
|
|
States
|
|
{
|
|
Spawn:
|
|
XZW1 A 1 A_ClusterTick(Color(2,4,2));
|
|
Wait;
|
|
Bounce:
|
|
XZW1 A 0 A_HandleBounce();
|
|
Goto Spawn;
|
|
Death:
|
|
TNT1 A 0 A_ClusterExplode();
|
|
HEXP ABCDEFGHIJKLMNOPQR 1 Bright A_ClusterSubExpl();
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class RavagerLight : PaletteLight
|
|
{
|
|
Default
|
|
{
|
|
Tag "DRed";
|
|
Args 0,0,0,400;
|
|
}
|
|
}
|
|
|
|
Class RavagerPuff : Actor
|
|
{
|
|
Vector2 initsc;
|
|
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Scale .8;
|
|
Alpha .3;
|
|
+NOGRAVITY;
|
|
+NOBLOCKMAP;
|
|
+DONTSPLASH;
|
|
+NOINTERACTION;
|
|
+NOTELEPORT;
|
|
+ROLLSPRITE;
|
|
+ROLLCENTER;
|
|
+FORCEXYBILLBOARD;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
scale *= FRandom[Hellblazer](.8,1.);
|
|
alpha *= FRandom[Hellblazer](.8,1.);
|
|
roll = FRandom[Hellblazer](0,360);
|
|
SetState(FindState("Spawn")+Random[Hellblazer](0,19));
|
|
initsc = scale;
|
|
}
|
|
override void Tick()
|
|
{
|
|
if ( isFrozen() ) return;
|
|
A_FadeOut((waterlevel>0)?.1:.02);
|
|
scale += initsc*.2;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
RFLM ABCDEFGHIJKLMNOPQRST -1 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class HellblazerRavagerArm : Actor
|
|
{
|
|
Vector3 oldvel;
|
|
|
|
Default
|
|
{
|
|
Obituary "$O_HELLBLAZER";
|
|
DamageType 'Fire';
|
|
PROJECTILE;
|
|
+THRUACTORS;
|
|
+BOUNCEONWALLS;
|
|
+BOUNCEONFLOORS;
|
|
+BOUNCEONCEILINGS;
|
|
+USEBOUNCESTATE;
|
|
+NODAMAGETHRUST;
|
|
+FORCERADIUSDMG;
|
|
-NOGRAVITY;
|
|
Gravity 0.15;
|
|
BounceFactor 1.0;
|
|
Radius 2;
|
|
Height 2;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
reactiontime = Random[ExploS](18,24);
|
|
vel = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch))*FRandom[ExploS](10.,30.);
|
|
}
|
|
override void Tick()
|
|
{
|
|
oldvel = vel;
|
|
Super.Tick();
|
|
}
|
|
void A_HandleBounce()
|
|
{
|
|
Vector3 HitNormal = -vel.unit();
|
|
F3DFloor ff;
|
|
if ( BlockingFloor )
|
|
{
|
|
// find closest 3d floor for its normal
|
|
for ( int i=0; i<CurSector.Get3DFloorCount(); i++ )
|
|
{
|
|
if ( !(CurSector.Get3DFloor(i).top.ZAtPoint(pos.xy) ~== floorz) ) continue;
|
|
ff = CurSector.Get3DFloor(i);
|
|
break;
|
|
}
|
|
if ( ff ) HitNormal = -ff.top.Normal;
|
|
else HitNormal = BlockingFloor.floorplane.Normal;
|
|
}
|
|
else if ( BlockingCeiling )
|
|
{
|
|
// find closest 3d floor for its normal
|
|
for ( int i=0; i<CurSector.Get3DFloorCount(); i++ )
|
|
{
|
|
if ( !(CurSector.Get3DFloor(i).bottom.ZAtPoint(pos.xy) ~== ceilingz) ) continue;
|
|
ff = CurSector.Get3DFloor(i);
|
|
break;
|
|
}
|
|
if ( ff ) HitNormal = -ff.bottom.Normal;
|
|
else HitNormal = BlockingCeiling.ceilingplane.Normal;
|
|
}
|
|
else if ( BlockingLine )
|
|
{
|
|
HitNormal = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit();
|
|
if ( !SWWMUtility.PointOnLineSide(pos.xy,BlockingLine) )
|
|
HitNormal *= -1;
|
|
}
|
|
else if ( BlockingMobj )
|
|
{
|
|
Vector3 diff = level.Vec3Diff(pos,BlockingMobj.pos);
|
|
if ( (pos.x+radius) <= (BlockingMobj.pos.x-BlockingMobj.radius) )
|
|
HitNormal = (-1,0,0);
|
|
else if ( (pos.x-radius) >= (BlockingMobj.pos.x+BlockingMobj.radius) )
|
|
HitNormal = (1,0,0);
|
|
else if ( (pos.y+radius) <= (BlockingMobj.pos.y-BlockingMobj.radius) )
|
|
HitNormal = (0,-1,0);
|
|
else if ( (pos.y-radius) >= (BlockingMobj.pos.y+BlockingMobj.radius) )
|
|
HitNormal = (0,1,0);
|
|
else if ( pos.z >= (BlockingMobj.pos.z+BlockingMobj.height) )
|
|
HitNormal = (0,0,1);
|
|
else if ( (pos.z+height) <= BlockingMobj.pos.z )
|
|
HitNormal = (0,0,-1);
|
|
}
|
|
// undo the bounce, we need to hook in our own
|
|
vel = oldvel;
|
|
// re-do the bounce with our formula
|
|
vel = .8*((vel dot HitNormal)*HitNormal*FRandom[Hellblazer](-1.5,-1.)+vel);
|
|
bHITOWNER = true;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A 1
|
|
{
|
|
if ( waterlevel > 0 ) ReactionTime -= 2;
|
|
A_CountDown();
|
|
let p = Spawn("RavagerPuff",pos);
|
|
p.alpha *= .6+.4*(ReactionTime/20.);
|
|
p.scale *= 3.5-2.5*(ReactionTime/20.);
|
|
if ( !(ReactionTime%3) )
|
|
{
|
|
let l = Spawn("RavagerLight",pos);
|
|
l.Args[3] = int(90+50*(ReactionTime/20.));
|
|
l.ReactionTime = int(2+8*(ReactionTime/20.));
|
|
l.target = p;
|
|
}
|
|
if ( !(GetAge()%2) )
|
|
{
|
|
SWWMHandler.DoBlast(self,250-6*reactiontime,1000+200*reactiontime,bHITOWNER?null:target);
|
|
A_Explode(4+reactiontime*4,250-6*reactiontime,bHITOWNER?XF_HURTSOURCE:0);
|
|
}
|
|
double spd = vel.length();
|
|
vel = (vel*.4+(FRandom[ExploS](-.2,.2),FRandom[ExploS](-.2,.2),FRandom[ExploS](-.2,.2))).unit()*spd;
|
|
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,5);
|
|
if ( !(ReactionTime%2) )
|
|
{
|
|
let s = Spawn("SWWMSmoke",pos);
|
|
s.vel = pvel+vel*.2;
|
|
s.SetShade(Color(4,2,2)*Random[ExploS](48,63));
|
|
s.special1 = Random[ExploS](2,4);
|
|
s.scale *= 3.2;
|
|
s.alpha *= .1+.2*(ReactionTime/20.);
|
|
int numpt = Random[Hellblazer](-2,4);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = vel+(FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1),FRandom[Hellblazer](-1,1)).unit()*FRandom[Hellblazer](2,4);
|
|
let s2 = Spawn("SWWMSpark",pos);
|
|
s2.scale *= .4;
|
|
s2.vel = pvel;
|
|
}
|
|
}
|
|
}
|
|
Wait;
|
|
Bounce:
|
|
TNT1 A 0 A_HandleBounce();
|
|
Goto Spawn;
|
|
}
|
|
}
|
|
|
|
Class HellblazerWarheadTrail : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
+NOBLOCKMAP;
|
|
+NOGRAVITY;
|
|
+FORCEXYBILLBOARD;
|
|
+NOTELEPORT;
|
|
Scale 1.5;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
HEXP ABCDEFGHIJKLMNOPQR 1 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class HellblazerWarheadArm : Actor
|
|
{
|
|
Default
|
|
{
|
|
PROJECTILE;
|
|
+THRUACTORS;
|
|
+BOUNCEONWALLS;
|
|
+BOUNCEONFLOORS;
|
|
+BOUNCEONCEILINGS;
|
|
+NODAMAGETHRUST;
|
|
+FORCERADIUSDMG;
|
|
-NOGRAVITY;
|
|
Gravity 0.25;
|
|
BounceFactor 1.0;
|
|
Radius 4;
|
|
Height 4;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
reactiontime = Random[ExploS](20,25);
|
|
double ang, pt;
|
|
ang = FRandom[ExploS](0,360);
|
|
pt = FRandom[ExploS](-90,90);
|
|
vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[ExploS](10.,25.);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A 1
|
|
{
|
|
A_CountDown();
|
|
Spawn("HellblazerWarheadTrail",pos);
|
|
SWWMHandler.DoBlast(self,30+2*reactiontime,3000+500*reactiontime);
|
|
A_Explode(10+reactiontime*4,120+4*reactiontime);
|
|
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,5);
|
|
let s = Spawn("SWWMSmoke",pos);
|
|
s.vel = pvel+vel*.2;
|
|
s.SetShade(Color(4,3,2)*Random[ExploS](48,63));
|
|
s.special1 = Random[ExploS](1,3);
|
|
s.scale *= 4.;
|
|
s.alpha *= 0.1+.4*(ReactionTime/15.);
|
|
}
|
|
Wait;
|
|
}
|
|
}
|
|
|
|
Class Hellblazer : SWWMWeapon
|
|
{
|
|
int clipcount;
|
|
bool magstate[6]; // true: rocket was spent
|
|
int magpos; // current rotation
|
|
Class<Ammo> loadammo, nextammo;
|
|
int spinskipped;
|
|
|
|
Property ClipCount : clipcount;
|
|
|
|
transient ui TextureID WeaponBox, AmmoIcon[4], LoadedIcon[4];
|
|
transient ui Font TewiFont;
|
|
|
|
override void DrawWeapon( double TicFrac, double bx, double by, Vector2 hs, Vector2 ss )
|
|
{
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
if ( !TewiFont ) TewiFont = Font.GetFont('TewiShaded');
|
|
if ( !WeaponBox )
|
|
{
|
|
WeaponBox = TexMan.CheckForTexture("graphics/HUD/HellblazerDisplay.png",TexMan.Type_Any);
|
|
AmmoIcon[0] = TexMan.CheckForTexture("graphics/HUD/HellblazerMissile.png",TexMan.Type_Any);
|
|
AmmoIcon[1] = TexMan.CheckForTexture("graphics/HUD/HellblazerCrackshot.png",TexMan.Type_Any);
|
|
AmmoIcon[2] = TexMan.CheckForTexture("graphics/HUD/HellblazerRavager.png",TexMan.Type_Any);
|
|
AmmoIcon[3] = TexMan.CheckForTexture("graphics/HUD/HellblazerWarhead.png",TexMan.Type_Any);
|
|
LoadedIcon[0] = TexMan.CheckForTexture("graphics/HUD/HellblazerMissileLoaded.png",TexMan.Type_Any);
|
|
LoadedIcon[1] = TexMan.CheckForTexture("graphics/HUD/HellblazerCrackshotLoaded.png",TexMan.Type_Any);
|
|
LoadedIcon[2] = TexMan.CheckForTexture("graphics/HUD/HellblazerRavagerLoaded.png",TexMan.Type_Any);
|
|
LoadedIcon[3] = TexMan.CheckForTexture("graphics/HUD/HellblazerWarheadLoaded.png",TexMan.Type_Any);
|
|
}
|
|
double xx = -56, yy = -49;
|
|
Screen.DrawTexture(WeaponBox,false,bx+xx,by+yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
int curtype = 0;
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
if ( loadammo != types[i] ) continue;
|
|
curtype = i;
|
|
break;
|
|
}
|
|
xx += 2;
|
|
yy += 1;
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
int amt = Owner.CountInv(types[i]);
|
|
String amtstr = String.Format("%3d",amt);
|
|
Screen.DrawText(TewiFont,Font.CR_FIRE,bx+xx,by+yy,amtstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(types[i]==nextammo)?Color(0,0,0,0):Color(128,0,0,0));
|
|
Screen.DrawTexture(AmmoIcon[i],false,bx+xx+19,by+yy+1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(types[i]==nextammo)?Color(0,0,0,0):Color(128,0,0,0));
|
|
yy += 13;
|
|
if ( i%2 )
|
|
{
|
|
yy -= 26;
|
|
xx += 28;
|
|
}
|
|
}
|
|
yy = -18;
|
|
switch ( curtype )
|
|
{
|
|
case 0:
|
|
xx = -54;
|
|
for ( int i=0; i<6; i++ )
|
|
{
|
|
Screen.DrawTexture(LoadedIcon[0],false,bx+xx,by+yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i==magpos)?magstate[i]?Color(192,0,0,0):Color(0,0,0,0):magstate[i]?Color(224,0,0,0):Color(96,0,0,0),DTA_Desaturate,magstate[i]?192:0);
|
|
xx += 9;
|
|
}
|
|
break;
|
|
case 1:
|
|
xx = -49;
|
|
for ( int i=0; i<3; i++ )
|
|
{
|
|
Screen.DrawTexture(LoadedIcon[1],false,bx+xx,by+yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i==magpos)?magstate[i]?Color(192,0,0,0):Color(0,0,0,0):magstate[i]?Color(224,0,0,0):Color(96,0,0,0),DTA_Desaturate,magstate[i]?192:0);
|
|
xx += 18;
|
|
}
|
|
break;
|
|
case 2:
|
|
xx = -49;
|
|
for ( int i=0; i<3; i++ )
|
|
{
|
|
Screen.DrawTexture(LoadedIcon[2],false,bx+xx,by+yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i==magpos)?magstate[i]?Color(192,0,0,0):Color(0,0,0,0):magstate[i]?Color(224,0,0,0):Color(96,0,0,0),DTA_Desaturate,magstate[i]?192:0);
|
|
xx += 18;
|
|
}
|
|
break;
|
|
case 3:
|
|
xx = -45;
|
|
for ( int i=0; i<2; i++ )
|
|
{
|
|
Screen.DrawTexture(LoadedIcon[3],false,bx+xx,by+yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i==magpos)?magstate[i]?Color(192,0,0,0):Color(0,0,0,0):magstate[i]?Color(224,0,0,0):Color(96,0,0,0),DTA_Desaturate,magstate[i]?192:0);
|
|
xx += 27;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
action void A_HellblazerFire( int type = 0, bool bAlt = false )
|
|
{
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
static const Class<Actor> projs[] = {"HellblazerMissile","HellblazerCrackshot","HellblazerRavager","HellblazerWarhead",
|
|
"HellblazerMissile2","HellblazerCrackshot2","HellblazerRavager2","HellblazerWarhead2"};
|
|
static const Color cols[] = {Color(4,3,2),Color(2,4,2),Color(4,2,2),Color(3,2,4)};
|
|
A_StartSound(bAlt?"hellblazer/altfire":"hellblazer/fire",CHAN_WEAPON,CHANF_OVERLAP,attenuation:(bAlt?1.7:.8));
|
|
A_AlertMonsters(bAlt?400:1200);
|
|
int qstr = bAlt?4:5;
|
|
A_QuakeEx(qstr,qstr,qstr,bAlt?4:12,0,8,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:.12*qstr);
|
|
A_ZoomFactor(bAlt?.96:.93,ZOOM_INSTANT);
|
|
A_ZoomFactor(1.);
|
|
A_PlayerFire();
|
|
invoker.clipcount = max(0,invoker.clipcount-1);
|
|
invoker.magstate[invoker.magpos] = true;
|
|
invoker.spinskipped++;
|
|
Vector3 x, y, z, x2, y2, z2, dir, origin;
|
|
double a, s;
|
|
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
|
|
SWWMHandler.DoKnockback(self,-x,bAlt?22000.:32000.);
|
|
[x2, y2, z2] = swwm_CoordUtil.GetAxes(BulletSlope(),angle,roll);
|
|
origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+3*y-5*z);
|
|
a = FRandom[Hellblazer](0,360);
|
|
s = FRandom[Hellblazer](0,bAlt?.02:.005);
|
|
dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
|
|
let p = Spawn(projs[type+4*bAlt],origin);
|
|
p.target = self;
|
|
p.angle = atan2(dir.y,dir.x);
|
|
p.pitch = asin(-dir.z);
|
|
p.vel = dir*p.speed;
|
|
if ( bAlt )
|
|
{
|
|
p.vel.z += 3.5;
|
|
return;
|
|
}
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
let s = Spawn("SWWMViewSmoke",origin);
|
|
SWWMViewSmoke(s).ofs = (10,3,-5);
|
|
s.target = self;
|
|
s.SetShade(cols[type]*Random[Hellblazer](48,63));
|
|
s.alpha *= .2;
|
|
s.scale *= 2.;
|
|
}
|
|
for ( int i=0; i<5; i++ )
|
|
{
|
|
let s = Spawn("SWWMSmoke",origin);
|
|
s.special1 = 1;
|
|
s.scale *= 2.4;
|
|
s.alpha *= .4;
|
|
s.SetShade(cols[type]*Random[Hellblazer](48,63));
|
|
s.vel += vel*.5+x*FRandom[Hellblazer](6.,10.)+y*FRandom[Hellblazer](-2,2)+z*FRandom[Hellblazer](-2,2);
|
|
}
|
|
for ( int i=0; i<6; i++ )
|
|
{
|
|
let s = Spawn("SWWMSpark",origin);
|
|
s.scale *= .7;
|
|
s.alpha *= .4;
|
|
s.vel += vel*.5+x*FRandom[Hellblazer](4.,8.)+y*FRandom[Hellblazer](-2,2)+z*FRandom[Hellblazer](-2,2);
|
|
}
|
|
}
|
|
|
|
override bool ReportHUDAmmo()
|
|
{
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
for ( int i=0; i<4; i++ ) if ( Owner.CountInv(types[i]) > 0 ) return true;
|
|
return (clipcount>0);
|
|
}
|
|
|
|
override bool CheckAmmo( int firemode, bool autoswitch, bool requireammo, int ammocount )
|
|
{
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
if ( (firemode == PrimaryFire) || (firemode == AltFire) )
|
|
{
|
|
if ( clipcount > 0 ) return true;
|
|
for ( int i=0; i<4; i++ ) if ( Owner.CountInv(types[i]) > 0 ) return true;
|
|
return false;
|
|
}
|
|
return Super.CheckAmmo(firemode,autoswitch,requireammo,ammocount);
|
|
}
|
|
|
|
override bool UsesAmmo( Class<Ammo> kind )
|
|
{
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
for ( int i=0; i<4; i++ ) if ( kind is types[i] ) return true;
|
|
return false;
|
|
}
|
|
|
|
action void A_GlassOverlay( StateLabel g )
|
|
{
|
|
if ( !player.FindPSprite(PSP_WEAPON+1) )
|
|
{
|
|
A_Overlay(PSP_WEAPON+1,g);
|
|
A_OverlayFlags(PSP_WEAPON+1,PSPF_RENDERSTYLE,true);
|
|
A_OverlayRenderStyle(PSP_WEAPON+1,STYLE_Add);
|
|
}
|
|
else player.SetPSprite(PSP_WEAPON+1,invoker.FindState(g));
|
|
}
|
|
|
|
action state A_JumpByAmmoType( StateLabel a, StateLabel b, StateLabel c, StateLabel d, StateLabel g, StateLabel o = null )
|
|
{
|
|
A_Overlay(-9999,o);
|
|
A_GlassOverlay(g);
|
|
if ( invoker.loadammo is "HellblazerMissiles" ) return invoker.FindState(a);
|
|
if ( invoker.loadammo is "HellblazerCrackshots" ) return invoker.FindState(b);
|
|
if ( invoker.loadammo is "HellblazerRavagers" ) return invoker.FindState(c);
|
|
if ( invoker.loadammo is "HellblazerWarheads" ) return invoker.FindState(d);
|
|
return invoker.FindState(a);
|
|
}
|
|
|
|
override void AttachToOwner( Actor other )
|
|
{
|
|
Super.AttachToOwner(other);
|
|
if ( !loadammo ) loadammo = "HellblazerMissiles";
|
|
nextammo = loadammo;
|
|
}
|
|
|
|
clearscope int LoadedCapacity() const
|
|
{
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
static const int typeclipcount[] = {6,3,3,2};
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
if ( loadammo != types[i] ) continue;
|
|
let a = Owner.FindInventory(types[i]);
|
|
return min(a.Amount+clipcount,typeclipcount[i]);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
action void A_PickNextAmmo()
|
|
{
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
int curidx = 0;
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
if ( invoker.nextammo != types[i] ) continue;
|
|
curidx = (i+1)%4;
|
|
break;
|
|
}
|
|
Class<Ammo> oldammo = invoker.nextammo, newammo = invoker.loadammo;
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
int nidx = (i+curidx)%4;
|
|
if ( CountInv(types[nidx]) <= 0 ) continue;
|
|
newammo = types[nidx];
|
|
break;
|
|
}
|
|
if ( newammo != oldammo ) A_StartSound("misc/invchange",CHAN_WEAPONEXTRA,CHANF_UI|CHANF_LOCAL);
|
|
invoker.nextammo = newammo;
|
|
}
|
|
|
|
action void A_ZoomHold()
|
|
{
|
|
A_WeaponReady(WRF_NOFIRE);
|
|
if ( player.cmd.buttons&BT_ZOOM ) return;
|
|
player.SetPSPrite(PSP_WEAPON,invoker.FindState("Ready"));
|
|
}
|
|
|
|
action void A_SwapAmmo()
|
|
{
|
|
let amo = FindInventory(invoker.loadammo);
|
|
// if we're loading the same ammo type, we only need to remove the needed ammo
|
|
if ( invoker.loadammo == invoker.nextammo )
|
|
{
|
|
int takeamt = invoker.LoadedCapacity()-invoker.clipcount;
|
|
invoker.clipcount = invoker.LoadedCapacity();
|
|
if ( !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true) )
|
|
amo.Amount = max(0,amo.Amount-takeamt);
|
|
invoker.magpos = 0;
|
|
for ( int i=0; i<6; i++ )
|
|
invoker.magstate[i] = !(invoker.clipcount > i);
|
|
return;
|
|
}
|
|
// re-add/drop any still loaded
|
|
int maxgiveamt = min(amo.MaxAmount-amo.Amount,invoker.clipcount);
|
|
int dropamt = invoker.clipcount-maxgiveamt;
|
|
if ( (dropamt > 0) && !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true) ) amo.CreateTossable(dropamt);
|
|
amo.Amount = min(amo.MaxAmount,amo.Amount+invoker.clipcount);
|
|
// swap
|
|
invoker.clipcount = 0;
|
|
invoker.loadammo = invoker.nextammo;
|
|
invoker.clipcount = invoker.LoadedCapacity();
|
|
invoker.magpos = 0;
|
|
for ( int i=0; i<6; i++ )
|
|
invoker.magstate[i] = !(invoker.clipcount > i);
|
|
if ( !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true) )
|
|
{
|
|
let namo = FindInventory(invoker.loadammo);
|
|
namo.Amount = max(0,namo.Amount-invoker.clipcount);
|
|
}
|
|
}
|
|
|
|
action void A_HellblazerReady()
|
|
{
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
int flg = WRF_ALLOWRELOAD|WRF_ALLOWZOOM|WRF_ALLOWUSER1;
|
|
// can we fire?
|
|
bool canfire = (invoker.clipcount > 0);
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
if ( CountInv(types[i]) <= 0 ) continue;
|
|
canfire = true;
|
|
break;
|
|
}
|
|
if ( !canfire ) flg |= WRF_NOPRIMARY|WRF_NOSECONDARY;
|
|
A_WeaponReady(flg);
|
|
if ( player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK) )
|
|
invoker.CheckAmmo(EitherFire,true);
|
|
}
|
|
|
|
// check if weapon was dropped or interrupted in some way before the mag spin could be done
|
|
action void A_CheckSpinSkip()
|
|
{
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
static const int magcap[] = {6,3,3,2};
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
if ( invoker.loadammo != types[i] ) continue;
|
|
invoker.magpos = (invoker.magpos+invoker.spinskipped)%magcap[i];
|
|
invoker.spinskipped = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Default
|
|
{
|
|
Tag "$T_HELLBLAZER";
|
|
Inventory.PickupMessage "$I_HELLBLAZER";
|
|
Obituary "$O_HELLBLAZER";
|
|
Inventory.Icon "graphics/HUD/Icons/W_Hellblazer.png";
|
|
Weapon.SlotNumber 6;
|
|
Weapon.SelectionOrder 1800;
|
|
Weapon.UpSound "hellblazer/select";
|
|
Stamina 90000;
|
|
Weapon.AmmoType1 "HellblazerMissiles";
|
|
Weapon.AmmoGive1 6;
|
|
Hellblazer.ClipCount 6;
|
|
+SWWMWEAPON.NOFIRSTGIVE;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
XZW1 A -1;
|
|
Stop;
|
|
Select:
|
|
XZW2 I 0
|
|
{
|
|
A_CheckSpinSkip();
|
|
A_FullRaise();
|
|
return A_JumpByAmmoType("Select_1","Select_2","Select_3","Select_4","Select_G");
|
|
}
|
|
Select_1:
|
|
XZW2 IJKLMNOP 2;
|
|
Goto Ready_1;
|
|
Select_2:
|
|
XZW7 DEFGHIJK 2;
|
|
Goto Ready_2;
|
|
Select_3:
|
|
XZWC BCDEFGHI 2;
|
|
Goto Ready_3;
|
|
Select_4:
|
|
XZWG Z 2;
|
|
XZWH ABCDEFG 2;
|
|
Goto Ready_4;
|
|
Select_G:
|
|
XZWM ABCDEFGH 2;
|
|
Goto Ready_G;
|
|
Deselect:
|
|
XZW2 A 0
|
|
{
|
|
A_StartSound("hellblazer/deselect",CHAN_WEAPON,CHANF_OVERLAP);
|
|
return A_JumpByAmmoType("Deselect_1","Deselect_2","Deselect_3","Deselect_4","Deselect_G");
|
|
}
|
|
Deselect_1:
|
|
XZW2 ABCDEFGHI 2;
|
|
XZW2 I -1 A_FullLower();
|
|
Stop;
|
|
Deselect_2:
|
|
XZW6 VWXYZ 2;
|
|
XZW7 ABCD 2;
|
|
XZW7 D -1 A_FullLower();
|
|
Stop;
|
|
Deselect_3:
|
|
XZWB TUVWXYZ 2;
|
|
XZWC AB 2;
|
|
XZWC B -1 A_FullLower();
|
|
Stop;
|
|
Deselect_4:
|
|
XZWG RSTUVWXYZ 2;
|
|
XZWG Z -1 A_FullLower();
|
|
Stop;
|
|
Deselect_G:
|
|
XZWL STUVWXYZ 2;
|
|
XZWM A 2;
|
|
Stop;
|
|
Ready:
|
|
XZW2 A 0 A_JumpByAmmoType("Ready_1","Ready_2","Ready_3","Ready_4","Ready_G");
|
|
Ready_1:
|
|
XZW2 A 1 A_HellblazerReady();
|
|
Wait;
|
|
Ready_2:
|
|
XZW6 V 1 A_HellblazerReady();
|
|
Wait;
|
|
Ready_3:
|
|
XZWB T 1 A_HellblazerReady();
|
|
Wait;
|
|
Ready_4:
|
|
XZWG R 1 A_HellblazerReady();
|
|
Wait;
|
|
Ready_G:
|
|
XZWL S 1;
|
|
Wait;
|
|
Fire:
|
|
XZW2 A 0
|
|
{
|
|
if ( invoker.clipcount <= 0 )
|
|
{
|
|
if ( CountInv(invoker.nextammo) <= 0 ) A_PickNextAmmo();
|
|
return A_JumpByAmmoType("Unload_1","Unload_2","Unload_3","Unload_4","Unload_G");
|
|
}
|
|
return A_JumpByAmmoType("Fire_1","Fire_2","Fire_3","Fire_4","Fire_G");
|
|
}
|
|
Fire_1:
|
|
XZW2 A 1 A_HellblazerFire(0);
|
|
XZW2 QRSTUVW 2;
|
|
Goto Cycle_1;
|
|
Fire_2:
|
|
XZW6 V 1 A_HellblazerFire(1);
|
|
XZW7 LMNOPQR 2;
|
|
Goto Cycle_2;
|
|
Fire_3:
|
|
XZWB T 1 A_HellblazerFire(2);
|
|
XZWC JKLMNOP 2;
|
|
Goto Cycle_3;
|
|
Fire_4:
|
|
XZWG R 1 A_HellblazerFire(3);
|
|
XZWH HIJKLMN 2;
|
|
Goto Cycle_4;
|
|
Fire_G:
|
|
XZWL S 1;
|
|
XZWM IJKLMNO 2;
|
|
Goto Ready_G; // state jump to cycling is done elsewhere
|
|
AltFire:
|
|
XZW2 A 0
|
|
{
|
|
if ( invoker.clipcount <= 0 )
|
|
{
|
|
if ( CountInv(invoker.nextammo) <= 0 ) A_PickNextAmmo();
|
|
return A_JumpByAmmoType("Unload_1","Unload_2","Unload_3","Unload_4","Unload_G");
|
|
}
|
|
return A_JumpByAmmoType("AltFire_1","AltFire_2","AltFire_3","AltFire_4","AltFire_G");
|
|
}
|
|
AltFire_1:
|
|
XZW2 A 1 A_HellblazerFire(0,true);
|
|
XZW2 XYZ 2;
|
|
XZW3 ABCD 2;
|
|
Goto Cycle_1;
|
|
AltFire_2:
|
|
XZW6 V 1 A_HellblazerFire(1,true);
|
|
XZW7 STUVWXY 2;
|
|
Goto Cycle_2;
|
|
AltFire_3:
|
|
XZWB T 1 A_HellblazerFire(2,true);
|
|
XZWC QRSTUVW 2;
|
|
Goto Cycle_3;
|
|
AltFire_4:
|
|
XZWG R 1 A_HellblazerFire(3,true);
|
|
XZWH OPQRSTU 2;
|
|
Goto Cycle_4;
|
|
AltFire_G:
|
|
XZWL S 1;
|
|
XZWM PQRSTUV 2;
|
|
Goto Ready_G; // state jump to cycling is done elsewhere
|
|
Cycle_1:
|
|
XZW2 A 3
|
|
{
|
|
invoker.spinskipped--;
|
|
invoker.magpos = (invoker.magpos+1)%6;
|
|
A_GlassOverlay("Cycle_G1");
|
|
}
|
|
XZW3 E 3;
|
|
XZW3 FGHI 2;
|
|
XZW3 I 0;
|
|
XZW3 FE 3;
|
|
Goto Ready_1;
|
|
Cycle_2:
|
|
XZW6 V 3
|
|
{
|
|
invoker.spinskipped--;
|
|
invoker.magpos = (invoker.magpos+1)%3;
|
|
A_GlassOverlay("Cycle_G2");
|
|
}
|
|
XZW7 Z 3;
|
|
XZW8 ABCDEFG 2;
|
|
XZW8 G 0;
|
|
XZW8 A 3;
|
|
XZW7 Z 3;
|
|
Goto Ready_2;
|
|
Cycle_3:
|
|
XZWB T 3
|
|
{
|
|
invoker.spinskipped--;
|
|
invoker.magpos = (invoker.magpos+1)%3;
|
|
A_GlassOverlay("Cycle_G2");
|
|
}
|
|
XZWC X 3;
|
|
XZWC YZ 2;
|
|
XZWD ABCDE 2;
|
|
XZWD E 0;
|
|
XZWC YX 3;
|
|
Goto Ready_3;
|
|
Cycle_4:
|
|
XZWG R 3
|
|
{
|
|
invoker.spinskipped--;
|
|
invoker.magpos = (invoker.magpos+1)%2;
|
|
A_GlassOverlay("Cycle_G3");
|
|
}
|
|
XZWH V 3;
|
|
XZWH WXYZ 2;
|
|
XZWI ABCDEF 2;
|
|
XZWI F 0;
|
|
XZWH WV 3;
|
|
Goto Ready_4;
|
|
Cycle_G1:
|
|
XZWL S 3 A_StartSound("hellblazer/shift",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWM W 3;
|
|
XZWM X 2 A_StartSound("hellblazer/spin",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWM YZ 2;
|
|
XZWN A 2;
|
|
XZWN A 0 A_StartSound("hellblazer/shift",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWM XW 3;
|
|
Goto Ready_G;
|
|
Cycle_G2:
|
|
XZWL S 3 A_StartSound("hellblazer/shift",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWM W 3;
|
|
XZWN B 2 A_StartSound("hellblazer/spin",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWN CD 2;
|
|
XZWN E 2 A_StartSound("hellblazer/spin",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWN FGH 2;
|
|
XZWN H 0 A_StartSound("hellblazer/shift",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWN B 3;
|
|
XZWM W 3;
|
|
Goto Ready_G;
|
|
Cycle_G3:
|
|
XZWL S 3 A_StartSound("hellblazer/shift",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWM W 3;
|
|
XZWN I 2 A_StartSound("hellblazer/spin",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWN JK 2;
|
|
XZWN L 2 A_StartSound("hellblazer/spin",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWN MN 2;
|
|
XZWN O 2 A_StartSound("hellblazer/spin",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWN PQR 2;
|
|
XZWN R 0 A_StartSound("hellblazer/shift",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWN I 3;
|
|
XZWM W 3;
|
|
Goto Ready_G;
|
|
Reload:
|
|
XZW2 A 2
|
|
{
|
|
if ( (invoker.clipcount >= invoker.LoadedCapacity()) && (invoker.loadammo == invoker.nextammo) )
|
|
return A_JumpByAmmoType("Idle_1","Idle_2","Idle_3","Idle_4","Idle_G");
|
|
return A_JumpByAmmoType("Unload_1","Unload_2","Unload_3","Unload_4","Unload_G");
|
|
}
|
|
Goto Ready;
|
|
Unload_1:
|
|
XZW2 A 2;
|
|
XZW3 JKLMNOPQRSTUVWXYZ 2;
|
|
XZW4 ABCDEFGHI 2;
|
|
XZW4 J 2
|
|
{
|
|
A_SwapAmmo();
|
|
return A_JumpByAmmoType("Load_1","Load_2","Load_3","Load_4","Load_G");
|
|
}
|
|
Goto Load_1;
|
|
Unload_2:
|
|
XZW6 V 2;
|
|
XZW8 HIJKLMNOPQRSTUVWXYZ 2;
|
|
XZW9 ABCDEFG 2;
|
|
XZW9 H 2
|
|
{
|
|
A_SwapAmmo();
|
|
return A_JumpByAmmoType("Load_1","Load_2","Load_3","Load_4","Load_G");
|
|
}
|
|
Goto Load_2;
|
|
Unload_3:
|
|
XZWB T 2;
|
|
XZWD FGHIJKLMNOPQRSTUVWXYZ 2;
|
|
XZWE ABCDE 2;
|
|
XZWE F 2
|
|
{
|
|
A_SwapAmmo();
|
|
return A_JumpByAmmoType("Load_1","Load_2","Load_3","Load_4","Load_G");
|
|
}
|
|
Goto Load_3;
|
|
Unload_4:
|
|
XZWG R 2;
|
|
XZWI GHIJKLMNOPQRSTUVWXYZ 2;
|
|
XZWJ ABCDEF 2;
|
|
XZWJ G 2
|
|
{
|
|
A_SwapAmmo();
|
|
return A_JumpByAmmoType("Load_1","Load_2","Load_3","Load_4","Load_G");
|
|
}
|
|
Goto Load_4;
|
|
Unload_G:
|
|
XZWL S 2 A_StartSound("hellblazer/meleestart",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWN STU 2;
|
|
XZWN V 2 A_StartSound("hellblazer/open",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWN WXYZ 2;
|
|
XZWO ABCDEFGH 2;
|
|
XZWO I 2 A_StartSound("hellblazer/magout",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWO JKLMNOPQRS 2;
|
|
Goto Load_G;
|
|
Load_1:
|
|
XZW4 JKLMNOPQRSTUVWXYZ 2;
|
|
XZW5 ABCDEFGHIJ 2;
|
|
Goto Ready_1;
|
|
Load_2:
|
|
XZW9 HIJKLMNOPQRSTUVWXYZ 2;
|
|
XZWA ABCDEFGH 2;
|
|
Goto Ready_2;
|
|
Load_3:
|
|
XZWE FGHIJKLMNOPQRSTUVWXYZ 2;
|
|
XZWF ABCDEF 2;
|
|
Goto Ready_3;
|
|
Load_4:
|
|
XZWJ GHIJKLMNOPQRSTUVWXYZ 2;
|
|
XZWK ABCDEFG 2;
|
|
Goto Ready_4;
|
|
Load_G:
|
|
XZWO S 2 A_PlayerReload();
|
|
XZWO TUVWXY 2;
|
|
XZWO Z 2 A_StartSound("hellblazer/magin",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWP ABCDEFG 2;
|
|
XZWP H 2 A_StartSound("hellblazer/close",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWP IJKL 2;
|
|
XZWP M 2 A_StartSound("hellblazer/meleestop",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWP NOPQRS 2;
|
|
Goto Ready_G;
|
|
Idle_1:
|
|
XZW2 A 2;
|
|
XZW5 KLMNOPQRSTUVWXYZ 2;
|
|
XZW6 A 2;
|
|
Goto Ready_1;
|
|
Idle_2:
|
|
XZW6 V 2;
|
|
XZWA IJKLMNOPQRSTUVWXY 2;
|
|
Goto Ready_2;
|
|
Idle_3:
|
|
XZWB T 2;
|
|
XZWF GHIJKLMNOPQRSTUVW 2;
|
|
Goto Ready_3;
|
|
Idle_4:
|
|
XZWG R 2;
|
|
XZWK HIJKLMNOPQRSTUVWX 2;
|
|
Goto Ready_4;
|
|
Idle_G:
|
|
XZWL S 2
|
|
{
|
|
A_StartSound("hellblazer/idle",CHAN_WEAPON,CHANF_OVERLAP);
|
|
A_PlayerCheckGun();
|
|
}
|
|
XZWP TUVWX 2;
|
|
XZWP Y 2 A_StartSound("hellblazer/dustoff",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWP Z 2;
|
|
XZWQ ABCDEFGHIJ 2;
|
|
Goto Ready_G;
|
|
Zoom:
|
|
#### # 1
|
|
{
|
|
A_PickNextAmmo();
|
|
A_WeaponReady(WRF_NOFIRE);
|
|
}
|
|
#### # 1 A_ZoomHold();
|
|
Wait;
|
|
User1:
|
|
XZW2 A 0 A_JumpByAmmoType("User1_1","User1_2","User1_3","User1_4","User1_G");
|
|
User1_1:
|
|
XZW2 A 2;
|
|
XZW6 BCDE 2;
|
|
XZW6 FGH 1;
|
|
XZW6 IJK 2;
|
|
XZW6 LMNOPQRSTU 2;
|
|
Goto Ready_1;
|
|
User1_2:
|
|
XZW6 V 2;
|
|
XZWA Z 2;
|
|
XZWB ABC 2;
|
|
XZWB DEF 1;
|
|
XZWB GHI 2;
|
|
XZWB JKLMNOPQRS 2;
|
|
Goto Ready_2;
|
|
User1_3:
|
|
XZWB T 2;
|
|
XZWF XYZ 2;
|
|
XZWG A 2;
|
|
XZWG BCD 1;
|
|
XZWG EFG 2;
|
|
XZWG HIJKLMNOPQ 2;
|
|
Goto Ready_3;
|
|
User1_4:
|
|
XZWG R 2;
|
|
XZWK YZ 2;
|
|
XZWL AB 2;
|
|
XZWL CDE 1;
|
|
XZWL FGH 2;
|
|
XZWL IJKLMNOPQR 2;
|
|
Goto Ready_4;
|
|
User1_G:
|
|
XZWL S 2
|
|
{
|
|
A_StartSound("hellblazer/meleestart",CHAN_WEAPON,CHANF_OVERLAP);
|
|
A_StartSound("demolitionist/wswing",CHAN_WEAPON,CHANF_OVERLAP);
|
|
A_PlayerMelee();
|
|
}
|
|
XZWQ KLM 2;
|
|
XZWQ N 2 A_Parry(9);
|
|
XZWQ OP 1;
|
|
XZWQ Q 1 A_Melee(75,"demolitionist/whitl",1.05);
|
|
XZWQ RSTUV 2;
|
|
XZWQ W 2 A_StartSound("hellblazer/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWQ XYZ 2;
|
|
XZWR ABCD 2;
|
|
Goto Ready_G;
|
|
}
|
|
}
|