1411 lines
40 KiB
Text
1411 lines
40 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 HellblazerX : GhostArtifactX
|
|
{
|
|
States
|
|
{
|
|
Spawn:
|
|
XZW1 A -1; // not fullbright
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class HellblazerXSub : GhostArtifactX
|
|
{
|
|
Hellblazer weap;
|
|
int ridx;
|
|
|
|
Default
|
|
{
|
|
RenderStyle "Normal";
|
|
}
|
|
void UpdateMe()
|
|
{
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
int curtype = -1;
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
if ( weap.loadammo != types[i] ) continue;
|
|
curtype = i;
|
|
break;
|
|
}
|
|
static const int sofs[] = {1,7,10,13}; // offsets from SpawnState for each ammo type state label
|
|
int idx;
|
|
switch ( curtype )
|
|
{
|
|
case 0:
|
|
idx = ridx-weap.magpos;
|
|
if ( idx > 5 ) idx -= 6;
|
|
else if ( idx < 0 ) idx += 6;
|
|
if ( weap.magstate[ridx] ) SetState(SpawnState);
|
|
else SetState(SpawnState+sofs[0]+idx);
|
|
break;
|
|
case 1:
|
|
idx = ridx-weap.magpos;
|
|
if ( idx > 2 ) idx -= 3;
|
|
else if ( idx < 0 ) idx += 3;
|
|
if ( (ridx > 2) || weap.magstate[ridx] ) SetState(SpawnState);
|
|
else SetState(SpawnState+sofs[1]+idx);
|
|
break;
|
|
case 2:
|
|
idx = ridx-weap.magpos;
|
|
if ( idx > 2 ) idx -= 3;
|
|
else if ( idx < 0 ) idx += 3;
|
|
if ( (ridx > 2) || weap.magstate[ridx] ) SetState(SpawnState);
|
|
else SetState(SpawnState+sofs[2]+idx);
|
|
break;
|
|
case 3:
|
|
idx = ridx-weap.magpos;
|
|
if ( idx > 1 ) idx -= 2;
|
|
else if ( idx < 0 ) idx += 2;
|
|
if ( (ridx > 1) || weap.magstate[ridx] ) SetState(SpawnState);
|
|
else SetState(SpawnState+sofs[3]+idx);
|
|
break;
|
|
default:
|
|
// uninitialized pickup (3 blazers)
|
|
idx = ridx;
|
|
if ( idx > 2 ) SetState(SpawnState);
|
|
else SetState(SpawnState+sofs[0]+idx);
|
|
break;
|
|
}
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A -1;
|
|
Missiles:
|
|
XZW1 ABCDEF -1;
|
|
Crackshots:
|
|
XZW2 ABC -1;
|
|
Ravagers:
|
|
XZW3 ABC -1;
|
|
Nukes:
|
|
XZW4 AB -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class Hellblazer : SWWMWeapon
|
|
{
|
|
int clipcount;
|
|
bool magstate[6]; // true: rocket was spent
|
|
int magpos; // current rotation
|
|
Class<Ammo> loadammo, nextammo;
|
|
ui Class<Ammo> lastammo;
|
|
int spinskipped;
|
|
HellblazerXSub pickuprockets[6];
|
|
int preload; // additional loaded missiles (up to 2)
|
|
Actor seektarget[3];
|
|
int seekcnt;
|
|
int preloadcnt;
|
|
|
|
Property ClipCount : clipcount;
|
|
|
|
transient ui TextureID WeaponBox, AmmoIcon[4], LoadedIcon[4], LockIcon[4];
|
|
transient ui SWWMProjectionData projdata;
|
|
|
|
override void RenderUnderlay( RenderEvent e )
|
|
{
|
|
Super.RenderUnderlay(e);
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
if ( !LockIcon[0] )
|
|
{
|
|
LockIcon[0] = TexMan.CheckForTexture("graphics/HUD/HellblazerMissileLock.png",TexMan.Type_Any);
|
|
LockIcon[1] = TexMan.CheckForTexture("graphics/HUD/HellblazerCrackshotLock.png",TexMan.Type_Any);
|
|
LockIcon[2] = TexMan.CheckForTexture("graphics/HUD/HellblazerRavagerLock.png",TexMan.Type_Any);
|
|
LockIcon[3] = TexMan.CheckForTexture("graphics/HUD/HellblazerWarheadLock.png",TexMan.Type_Any);
|
|
}
|
|
int curtype = 0;
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
if ( loadammo != types[i] ) continue;
|
|
curtype = i;
|
|
break;
|
|
}
|
|
SWWMUtility.PrepareProjData(projdata,e.ViewPos,e.ViewAngle,e.ViewPitch,e.ViewRoll,players[consoleplayer].fov);
|
|
int cliptop = projdata.viewy, clipbottom = projdata.viewy+projdata.viewh,
|
|
clipleft = projdata.viewx, clipright = projdata.viewx+projdata.vieww;
|
|
double hs;
|
|
if ( swwm_hudscale ) hs = CleanXFac_1;
|
|
else hs = max(floor(Screen.GetWidth()/640.),1.);
|
|
Vector2 ss = (Screen.GetWidth()/hs,Screen.GetHeight()/hs);
|
|
for ( int i=0; i<3; i++ )
|
|
{
|
|
if ( !seektarget[i] ) continue;
|
|
Vector3 tpos = seektarget[i].prev*(1.-e.FracTic)+seektarget[i].pos*e.FracTic;
|
|
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,e.viewpos+level.Vec3Diff(e.viewpos,tpos+(0,0,seektarget[i].Height/2)));
|
|
if ( ndc.z > 1. ) continue;
|
|
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc);
|
|
Screen.DrawTexture(LockIcon[curtype],false,vpos.x/hs,vpos.y/hs,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_CenterOffset,true,DTA_ClipTop,cliptop,DTA_ClipBottom,clipbottom,DTA_ClipLeft,clipleft,DTA_ClipRight,clipright);
|
|
}
|
|
}
|
|
|
|
override void DrawWeapon( double TicFrac, double bx, double by, double hs, Vector2 ss )
|
|
{
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
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 += 2;
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
int amt = Owner.CountInv(types[i]);
|
|
String amtstr = String.Format("%3d",amt);
|
|
Screen.DrawText(SWWMStatusBar(StatusBar).mSmallFont,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)&&(i>=(magpos-preload)))?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)&&(i>=(magpos-preload)))?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)&&(i>=(magpos-preload)))?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)&&(i>=(magpos-preload)))?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;
|
|
}
|
|
}
|
|
|
|
override void HudTick()
|
|
{
|
|
Super.HudTick();
|
|
if ( lastammo && (lastammo != nextammo) && (Owner.player == players[consoleplayer]) )
|
|
{
|
|
let bar = SWWMStatusBar(statusbar);
|
|
if ( bar )
|
|
{
|
|
bar.ntagstr = GetDefaultByType(nextammo).GetTag();
|
|
bar.ntagtic = level.totaltime;
|
|
bar.ntagcol = nametagcolor;
|
|
}
|
|
}
|
|
lastammo = nextammo;
|
|
}
|
|
|
|
override Vector3 GetTraceOffset()
|
|
{
|
|
return (10.,3.5,-5.);
|
|
}
|
|
|
|
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(swwm_uncapalert?0: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_BumpFOV(bAlt?.96:.93);
|
|
A_PlayerFire();
|
|
invoker.clipcount = max(0,invoker.clipcount-1);
|
|
invoker.magstate[invoker.magpos-invoker.preload] = true;
|
|
invoker.spinskipped++;
|
|
Vector3 x, y, z, x2, y2, z2, dir, origin;
|
|
double a, s;
|
|
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
|
|
SWWMUtility.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.5*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;
|
|
int tidx = max(0,invoker.seekcnt-(invoker.preload+1));
|
|
if ( invoker.seektarget[tidx] ) HellblazerMissile(p).seektarget = invoker.seektarget[tidx];
|
|
if ( invoker.preload <= 0 ) for ( int i=0; i<3; i++ ) invoker.seektarget[i] = null;
|
|
p.angle = atan2(dir.y,dir.x);
|
|
p.pitch = asin(-dir.z);
|
|
p.vel = dir*p.speed;
|
|
if ( bAlt )
|
|
{
|
|
if ( p.waterlevel <= 0 ) p.vel.z += 3.5;
|
|
return;
|
|
}
|
|
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 )
|
|
{
|
|
player.SetPSprite(PSP_WEAPON+1,invoker.FindState(g));
|
|
// we have to still use A_Overlay* functions for these
|
|
A_OverlayFlags(PSP_WEAPON+1,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
|
|
A_OverlayRenderStyle(PSP_WEAPON+1,STYLE_Add);
|
|
}
|
|
|
|
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 bool PickupForAmmoSWWM( SWWMWeapon ownedWeapon )
|
|
{
|
|
bool good = Super.PickupForAmmoSWWM(ownedWeapon);
|
|
let Owner = ownedWeapon.Owner;
|
|
if ( (AmmoGive1 == 0) && loadammo )
|
|
{
|
|
// let's get this bread
|
|
Inventory cur = Owner.FindInventory(loadammo);
|
|
if ( !cur )
|
|
{
|
|
cur = Inventory(Spawn(loadammo));
|
|
cur.Amount = 0;
|
|
cur.AttachToOwner(Owner);
|
|
}
|
|
int maxgiveamt = min(cur.MaxAmount-cur.Amount,clipcount);
|
|
int dropamt = clipcount-maxgiveamt;
|
|
if ( dropamt > 0 ) cur.CreateTossable(dropamt);
|
|
cur.Amount = min(cur.MaxAmount,cur.Amount+clipcount);
|
|
good = true;
|
|
}
|
|
return good;
|
|
}
|
|
|
|
override void AttachToOwner( Actor other )
|
|
{
|
|
if ( !loadammo )
|
|
{
|
|
// 3 hellblazer missiles loaded
|
|
loadammo = "HellblazerMissiles";
|
|
clipcount = 3;
|
|
magpos = 0;
|
|
for ( int i=0; i<6; i++ )
|
|
magstate[i] = (i>2);
|
|
}
|
|
nextammo = loadammo;
|
|
Super.AttachToOwner(other);
|
|
}
|
|
|
|
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|WRF_NOSWITCH);
|
|
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<3; i++ ) invoker.seektarget[i] = null;
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
if ( invoker.loadammo != types[i] ) continue;
|
|
// check preloaded rockets first (note, this theoretically would never go below zero)
|
|
invoker.magpos = max(0,invoker.magpos-invoker.preload);
|
|
invoker.preload = 0;
|
|
// do the spin
|
|
invoker.magpos = (invoker.magpos+invoker.spinskipped)%magcap[i];
|
|
invoker.spinskipped = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
action void A_UpdatePickup()
|
|
{
|
|
static const Class<Ammo> types[] = {"HellblazerMissiles","HellblazerCrackshots","HellblazerRavagers","HellblazerWarheads"};
|
|
for ( int i=0; i<6; i++ )
|
|
{
|
|
if ( !invoker.pickuprockets[i] )
|
|
{
|
|
invoker.pickuprockets[i] = HellblazerXSub(Spawn("HellblazerXSub",pos));
|
|
invoker.pickuprockets[i].angle = angle;
|
|
invoker.pickuprockets[i].target = invoker;
|
|
invoker.pickuprockets[i].weap = invoker;
|
|
invoker.pickuprockets[i].FloatBobPhase = FloatBobPhase;
|
|
invoker.pickuprockets[i].ridx = i;
|
|
}
|
|
invoker.pickuprockets[i].UpdateMe();
|
|
}
|
|
int curtype = 0;
|
|
for ( int i=0; i<4; i++ )
|
|
{
|
|
if ( invoker.loadammo != types[i] ) continue;
|
|
curtype = i;
|
|
break;
|
|
}
|
|
SetState(SpawnState+curtype+1);
|
|
}
|
|
|
|
action void A_CheckLockOn()
|
|
{
|
|
if ( invoker.seekcnt > invoker.preload ) return;
|
|
Vector3 x, y, z, x2, y2, z2, dir;
|
|
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
|
|
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x);
|
|
// try to catch target in cone of vision
|
|
[x2, y2, z2] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
|
|
Array<HHitList> hits;
|
|
hits.Clear();
|
|
int rings = 1;
|
|
FLineTraceData d;
|
|
for ( double i=0; i<.1; i+=.02 )
|
|
{
|
|
for ( int j=0; j<360; j+=(360/rings) )
|
|
{
|
|
dir = (x2+y2*cos(j)*i+z2*sin(j)*i).unit();
|
|
LineTrace(atan2(dir.y,dir.x),8000.,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
|
|
if ( d.HitType != TRACE_HitActor ) continue;
|
|
if ( (d.HitActor == invoker.seektarget[0])
|
|
|| (d.HitActor == invoker.seektarget[1])
|
|
|| (d.HitActor == invoker.seektarget[2]) ) continue;
|
|
if ( !d.HitActor.bISMONSTER && !(d.HitActor is 'BossBrain') && !d.HitActor.player )
|
|
continue;
|
|
if ( d.HitActor.IsFriend(self) ) continue;
|
|
bool addme = true;
|
|
for ( int k=0; k<hits.Size(); k++ )
|
|
{
|
|
if ( hits[k].a != d.HitActor ) continue;
|
|
if ( (hits[k].dir dot x2) < (dir dot x2) )
|
|
hits[k].dir = dir; // closer to centerpoint
|
|
addme = false;
|
|
break;
|
|
}
|
|
if ( !addme ) continue;
|
|
let nhit = new("HHitList");
|
|
nhit.a = d.HitActor;
|
|
nhit.dir = dir;
|
|
hits.Push(nhit);
|
|
}
|
|
rings += 5;
|
|
}
|
|
int closest = -1;
|
|
double closestdot = -1;
|
|
for ( int i=0; i<hits.Size(); i++ )
|
|
{
|
|
double thisdot = (hits[i].dir dot x2);
|
|
if ( thisdot < closestdot ) continue;
|
|
closest = i;
|
|
closestdot = thisdot;
|
|
}
|
|
if ( closest != -1 )
|
|
{
|
|
if ( invoker.seekcnt == 0 )
|
|
{
|
|
for ( int i=0; i<3; i++ )
|
|
invoker.seektarget[i] = hits[closest].a;
|
|
}
|
|
else invoker.seektarget[invoker.seekcnt] = hits[closest].a;
|
|
invoker.seekcnt++;
|
|
A_StartSound("hellblazer/lock",CHAN_WEAPON,CHANF_OVERLAP);
|
|
}
|
|
}
|
|
|
|
override void PreTravelled()
|
|
{
|
|
if ( tracer ) tracer.Destroy();
|
|
}
|
|
override void Travelled()
|
|
{
|
|
if ( tracer ) return;
|
|
tracer = Spawn("HellblazerX",pos);
|
|
tracer.angle = angle;
|
|
tracer.target = self;
|
|
tracer.FloatBobPhase = FloatBobPhase;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
tracer = Spawn("HellblazerX",pos);
|
|
tracer.angle = angle;
|
|
tracer.target = self;
|
|
tracer.FloatBobPhase = FloatBobPhase;
|
|
}
|
|
|
|
override void MarkPrecacheSounds()
|
|
{
|
|
Super.MarkPrecacheSounds();
|
|
MarkSound("hellblazer/select");
|
|
MarkSound("hellblazer/deselect");
|
|
MarkSound("hellblazer/fire");
|
|
MarkSound("hellblazer/altfire");
|
|
MarkSound("hellblazer/meleestart");
|
|
MarkSound("hellblazer/meleeend");
|
|
MarkSound("hellblazer/idle");
|
|
MarkSound("hellblazer/dustoff");
|
|
MarkSound("hellblazer/shift");
|
|
MarkSound("hellblazer/spin");
|
|
MarkSound("hellblazer/open");
|
|
MarkSound("hellblazer/magout");
|
|
MarkSound("hellblazer/magin");
|
|
MarkSound("hellblazer/close");
|
|
MarkSound("hellblazer/hitm1");
|
|
MarkSound("hellblazer/hitm2");
|
|
MarkSound("hellblazer/hitm3");
|
|
MarkSound("hellblazer/hitc1");
|
|
MarkSound("hellblazer/hitc2");
|
|
MarkSound("hellblazer/hitc3");
|
|
MarkSound("hellblazer/hitcs1");
|
|
MarkSound("hellblazer/hitcs2");
|
|
MarkSound("hellblazer/hitcs3");
|
|
MarkSound("hellblazer/hitr1");
|
|
MarkSound("hellblazer/hitr2");
|
|
MarkSound("hellblazer/hitr3");
|
|
MarkSound("hellblazer/hitw1");
|
|
MarkSound("hellblazer/hitw2");
|
|
MarkSound("hellblazer/bounce");
|
|
MarkSound("hellblazer/fly");
|
|
MarkSound("hellblazer/preload");
|
|
MarkSound("hellblazer/hold");
|
|
MarkSound("hellblazer/lock");
|
|
MarkSound("hellblazer/clear");
|
|
}
|
|
|
|
Default
|
|
{
|
|
//$Title Hellblazer
|
|
//$Group Weapons
|
|
//$Sprite graphics/HUD/Icons/W_Hellblazer.png
|
|
//$Icon weapon
|
|
Tag "$T_HELLBLAZER";
|
|
Inventory.PickupMessage "$I_HELLBLAZER";
|
|
Obituary "$O_HELLBLAZER";
|
|
SWWMWeapon.Tooltip "$TT_HELLBLAZER";
|
|
SWWMWeapon.GetLine "gethellblazer";
|
|
Inventory.Icon "graphics/HUD/Icons/W_Hellblazer.png";
|
|
Weapon.SlotNumber 6;
|
|
Weapon.SelectionOrder 700;
|
|
Weapon.UpSound "hellblazer/select";
|
|
Stamina 90000;
|
|
Weapon.AmmoType1 "HellblazerMissiles";
|
|
Weapon.AmmoGive1 3;
|
|
SWWMWeapon.DropAmmoType "RocketAmmo";
|
|
Hellblazer.ClipCount 6;
|
|
+SWWMWEAPON.NOFIRSTGIVE;
|
|
+WEAPON.EXPLOSIVE;
|
|
Radius 24;
|
|
Height 32;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
XZW1 A -1 NoDelay A_UpdatePickup();
|
|
XZW1 ABCD -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:
|
|
#### # 0
|
|
{
|
|
invoker.preloadcnt = 0;
|
|
invoker.preload = 0;
|
|
}
|
|
#### # 1
|
|
{
|
|
if ( invoker.clipcount <= 0 )
|
|
{
|
|
if ( CountInv(invoker.nextammo) <= 0 ) A_PickNextAmmo();
|
|
return A_JumpByAmmoType("Unload_1","Unload_2","Unload_3","Unload_4","Unload_G");
|
|
}
|
|
if ( player.cmd.buttons&BT_ATTACK )
|
|
{
|
|
invoker.preloadcnt++;
|
|
if ( (player.cmd.buttons&BT_ALTATTACK) || ((invoker.clipcount < 2) && (invoker.preloadcnt >= 10)) )
|
|
{
|
|
invoker.preloadcnt = 0;
|
|
return A_JumpByAmmoType("PreFire_1","PreFire_2","PreFire_3","PreFire_4","Ready_G");
|
|
}
|
|
if ( invoker.preloadcnt >= 10 )
|
|
{
|
|
invoker.preloadcnt = 0;
|
|
return A_JumpByAmmoType("PreLoad_1","PreLoad_2","PreFire_3","PreFire_4","Ready_G");
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
return A_JumpByAmmoType("Fire_1","Fire_2","Fire_3","Fire_4","Fire_G");
|
|
}
|
|
Wait;
|
|
Fire_1:
|
|
XZW2 A 1 A_HellblazerFire(0);
|
|
XZW2 QRSTUVW 2;
|
|
XZW2 A 0
|
|
{
|
|
// chain-fire
|
|
if ( invoker.preload > 0 )
|
|
{
|
|
invoker.preload--;
|
|
invoker.spinskipped--;
|
|
return A_JumpByAmmoType("Fire_1","Fire_2","Fire_3","Fire_4","Fire_G");
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
Goto Cycle_1;
|
|
Fire_2:
|
|
XZW6 V 1 A_HellblazerFire(1);
|
|
XZW7 LMNOPQR 2;
|
|
XZW6 V 0
|
|
{
|
|
// chain-fire
|
|
if ( invoker.preload > 0 )
|
|
{
|
|
invoker.preload--;
|
|
invoker.spinskipped--;
|
|
return A_JumpByAmmoType("Fire_1","Fire_2","Fire_3","Fire_4","Fire_G");
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
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:
|
|
#### # 0
|
|
{
|
|
invoker.preloadcnt = 0;
|
|
invoker.preload = 0;
|
|
}
|
|
#### # 1
|
|
{
|
|
if ( invoker.clipcount <= 0 )
|
|
{
|
|
if ( CountInv(invoker.nextammo) <= 0 ) A_PickNextAmmo();
|
|
return A_JumpByAmmoType("Unload_1","Unload_2","Unload_3","Unload_4","Unload_G");
|
|
}
|
|
if ( player.cmd.buttons&BT_ALTATTACK )
|
|
{
|
|
invoker.preloadcnt++;
|
|
if ( (player.cmd.buttons&BT_ATTACK) || ((invoker.clipcount < 2) && (invoker.preloadcnt >= 10)) )
|
|
{
|
|
invoker.preloadcnt = 0;
|
|
return A_JumpByAmmoType("PreAltFire_1","PreAltFire_2","PreAltFire_3","PreAltFire_4","Ready_G");
|
|
}
|
|
if ( invoker.preloadcnt >= 10 )
|
|
{
|
|
invoker.preloadcnt = 0;
|
|
return A_JumpByAmmoType("PreAltLoad_1","PreAltLoad_2","PreAltFire_3","PreAltFire_4","Ready_G");
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
return A_JumpByAmmoType("AltFire_1","AltFire_2","AltFire_3","AltFire_4","AltFire_G");
|
|
}
|
|
Wait;
|
|
AltFire_1:
|
|
XZW2 A 1 A_HellblazerFire(0,true);
|
|
XZW2 XYZ 2;
|
|
XZW3 ABCD 2;
|
|
XZW2 A 0
|
|
{
|
|
// chain-fire
|
|
if ( invoker.preload > 0 )
|
|
{
|
|
invoker.preload--;
|
|
invoker.spinskipped--;
|
|
return A_JumpByAmmoType("AltFire_1","AltFire_2","AltFire_3","AltFire_4","AltFire_G");
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
Goto Cycle_1;
|
|
AltFire_2:
|
|
XZW6 V 1 A_HellblazerFire(1,true);
|
|
XZW7 STUVWXY 2;
|
|
XZW6 V 0
|
|
{
|
|
// chain-fire
|
|
if ( invoker.preload > 0 )
|
|
{
|
|
invoker.preload--;
|
|
invoker.spinskipped--;
|
|
return A_JumpByAmmoType("AltFire_1","AltFire_2","AltFire_3","AltFire_4","AltFire_G");
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
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
|
|
PreLoad_1:
|
|
XZW2 A 10 A_StartSound("hellblazer/preload",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW2 A 2
|
|
{
|
|
invoker.magpos = (invoker.magpos+1)%6;
|
|
invoker.preload++;
|
|
A_GlassOverlay("Cycle_G1");
|
|
}
|
|
XZW3 E 2;
|
|
XZW3 FGHI 2;
|
|
XZW3 I 0;
|
|
XZW3 FE 2;
|
|
XZW2 A 1
|
|
{
|
|
if ( !(player.cmd.buttons&BT_ATTACK) )
|
|
return A_JumpByAmmoType("Fire_1","Fire_2","Fire_3","Fire_4","Fire_G");
|
|
if ( (player.cmd.buttons&BT_ALTATTACK) || (invoker.preload >= min(invoker.clipcount-1,2)) )
|
|
return A_JumpByAmmoType("PreFire_1","PreFire_2","PreFire_3","PreFire_4","Ready_G");
|
|
return ResolveState("PreLoad_1");
|
|
}
|
|
Wait;
|
|
PreLoad_2:
|
|
XZW6 V 10 A_StartSound("hellblazer/preload",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW6 V 2
|
|
{
|
|
invoker.magpos = (invoker.magpos+1)%3;
|
|
invoker.preload++;
|
|
A_GlassOverlay("Cycle_G2");
|
|
}
|
|
XZW7 Z 2;
|
|
XZW8 ABCDEFG 2;
|
|
XZW8 G 0;
|
|
XZW8 A 2;
|
|
XZW7 Z 2;
|
|
XZW6 V 1
|
|
{
|
|
if ( !(player.cmd.buttons&BT_ATTACK) )
|
|
return A_JumpByAmmoType("Fire_1","Fire_2","Fire_3","Fire_4","Fire_G");
|
|
if ( (player.cmd.buttons&BT_ALTATTACK) || (invoker.preload >= min(invoker.clipcount-1,2)) )
|
|
return A_JumpByAmmoType("PreFire_1","PreFire_2","PreFire_3","PreFire_4","Ready_G");
|
|
return ResolveState("PreLoad_2");
|
|
}
|
|
Wait;
|
|
PreAltLoad_1:
|
|
XZW2 A 10 A_StartSound("hellblazer/preload",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW2 A 2
|
|
{
|
|
invoker.magpos = (invoker.magpos+1)%6;
|
|
invoker.preload++;
|
|
A_GlassOverlay("Cycle_G1");
|
|
}
|
|
XZW3 E 2;
|
|
XZW3 FGHI 2;
|
|
XZW3 I 0;
|
|
XZW3 FE 2;
|
|
XZW2 A 1
|
|
{
|
|
if ( !(player.cmd.buttons&BT_ALTATTACK) )
|
|
return A_JumpByAmmoType("AltFire_1","AltFire_2","AltFire_3","AltFire_4","AltFire_G");
|
|
if ( (player.cmd.buttons&BT_ATTACK) || (invoker.preload >= min(invoker.clipcount-1,2)) )
|
|
return A_JumpByAmmoType("PreAltFire_1","PreAltFire_2","PreAltFire_3","PreAltFire_4","Ready_G");
|
|
return ResolveState("PreAltLoad_1");
|
|
}
|
|
Wait;
|
|
PreAltLoad_2:
|
|
XZW6 V 10 A_StartSound("hellblazer/preload",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZW6 V 2
|
|
{
|
|
invoker.magpos = (invoker.magpos+1)%3;
|
|
invoker.preload++;
|
|
A_GlassOverlay("Cycle_G2");
|
|
}
|
|
XZW7 Z 2;
|
|
XZW8 ABCDEFG 2;
|
|
XZW8 G 0;
|
|
XZW8 A 2;
|
|
XZW7 Z 2;
|
|
XZW6 V 1
|
|
{
|
|
if ( !(player.cmd.buttons&BT_ALTATTACK) )
|
|
return A_JumpByAmmoType("AltFire_1","AltFire_2","AltFire_3","AltFire_4","AltFire_G");
|
|
if ( (player.cmd.buttons&BT_ATTACK) || (invoker.preload >= min(invoker.clipcount-1,2)) )
|
|
return A_JumpByAmmoType("PreAltFire_1","PreAltFire_2","PreAltFire_3","PreAltFire_4","Ready_G");
|
|
return ResolveState("PreAltLoad_2");
|
|
}
|
|
Wait;
|
|
PreFire_1:
|
|
XZW2 A 0
|
|
{
|
|
invoker.seekcnt = 0;
|
|
A_StartSound("hellblazer/hold",CHAN_WEAPON,CHANF_OVERLAP);
|
|
}
|
|
XZW2 A 1
|
|
{
|
|
if ( !(player.cmd.buttons&BT_ATTACK) )
|
|
return A_JumpByAmmoType("Fire_1","Fire_2","Fire_3","Fire_4","Fire_G");
|
|
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
|
|
if ( (player.cmd.buttons&BT_ZOOM) && !(player.oldbuttons&BT_ZOOM) )
|
|
A_CheckLockOn();
|
|
if ( (player.cmd.buttons&BT_RELOAD) && !(player.oldbuttons&BT_RELOAD) )
|
|
{
|
|
for ( int i=0; i<3; i++ ) invoker.seektarget[i] = null;
|
|
if ( invoker.seekcnt > 0 ) A_StartSound("hellblazer/clear",CHAN_WEAPON,CHANF_OVERLAP);
|
|
invoker.seekcnt = 0;
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
Wait;
|
|
PreFire_2:
|
|
XZW6 V 0
|
|
{
|
|
invoker.seekcnt = 0;
|
|
A_StartSound("hellblazer/hold",CHAN_WEAPON,CHANF_OVERLAP);
|
|
}
|
|
XZW6 V 1
|
|
{
|
|
if ( !(player.cmd.buttons&BT_ATTACK) )
|
|
return A_JumpByAmmoType("Fire_1","Fire_2","Fire_3","Fire_4","Fire_G");
|
|
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
|
|
if ( (player.cmd.buttons&BT_ZOOM) && !(player.oldbuttons&BT_ZOOM) )
|
|
A_CheckLockOn();
|
|
if ( (player.cmd.buttons&BT_RELOAD) && !(player.oldbuttons&BT_RELOAD) )
|
|
{
|
|
for ( int i=0; i<3; i++ ) invoker.seektarget[i] = null;
|
|
if ( invoker.seekcnt > 0 ) A_StartSound("hellblazer/clear",CHAN_WEAPON,CHANF_OVERLAP);
|
|
invoker.seekcnt = 0;
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
Wait;
|
|
PreFire_3:
|
|
XZWB T 0
|
|
{
|
|
invoker.seekcnt = 0;
|
|
A_StartSound("hellblazer/hold",CHAN_WEAPON,CHANF_OVERLAP);
|
|
}
|
|
XZWB T 1
|
|
{
|
|
if ( !(player.cmd.buttons&BT_ATTACK) )
|
|
return A_JumpByAmmoType("Fire_1","Fire_2","Fire_3","Fire_4","Fire_G");
|
|
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
|
|
if ( (player.cmd.buttons&BT_ZOOM) && !(player.oldbuttons&BT_ZOOM) )
|
|
A_CheckLockOn();
|
|
if ( (player.cmd.buttons&BT_RELOAD) && !(player.oldbuttons&BT_RELOAD) )
|
|
{
|
|
for ( int i=0; i<3; i++ ) invoker.seektarget[i] = null;
|
|
if ( invoker.seekcnt > 0 ) A_StartSound("hellblazer/clear",CHAN_WEAPON,CHANF_OVERLAP);
|
|
invoker.seekcnt = 0;
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
Wait;
|
|
PreFire_4:
|
|
XZWG R 0
|
|
{
|
|
invoker.seekcnt = 0;
|
|
A_StartSound("hellblazer/hold",CHAN_WEAPON,CHANF_OVERLAP);
|
|
}
|
|
XZWG R 1
|
|
{
|
|
if ( !(player.cmd.buttons&BT_ATTACK) )
|
|
return A_JumpByAmmoType("Fire_1","Fire_2","Fire_3","Fire_4","Fire_G");
|
|
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
|
|
if ( (player.cmd.buttons&BT_ZOOM) && !(player.oldbuttons&BT_ZOOM) )
|
|
A_CheckLockOn();
|
|
if ( (player.cmd.buttons&BT_RELOAD) && !(player.oldbuttons&BT_RELOAD) )
|
|
{
|
|
for ( int i=0; i<3; i++ ) invoker.seektarget[i] = null;
|
|
if ( invoker.seekcnt > 0 ) A_StartSound("hellblazer/clear",CHAN_WEAPON,CHANF_OVERLAP);
|
|
invoker.seekcnt = 0;
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
Wait;
|
|
PreAltFire_1:
|
|
XZW2 A 0
|
|
{
|
|
invoker.seekcnt = 0;
|
|
A_StartSound("hellblazer/hold",CHAN_WEAPON,CHANF_OVERLAP);
|
|
}
|
|
XZW2 A 1
|
|
{
|
|
if ( !(player.cmd.buttons&BT_ALTATTACK) )
|
|
return A_JumpByAmmoType("AltFire_1","AltFire_2","AltFire_3","AltFire_4","AltFire_G");
|
|
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
|
|
if ( (player.cmd.buttons&BT_ZOOM) && !(player.oldbuttons&BT_ZOOM) )
|
|
A_CheckLockOn();
|
|
if ( (player.cmd.buttons&BT_RELOAD) && !(player.oldbuttons&BT_RELOAD) )
|
|
{
|
|
for ( int i=0; i<3; i++ ) invoker.seektarget[i] = null;
|
|
if ( invoker.seekcnt > 0 ) A_StartSound("hellblazer/clear",CHAN_WEAPON,CHANF_OVERLAP);
|
|
invoker.seekcnt = 0;
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
Wait;
|
|
PreAltFire_2:
|
|
XZW6 V 0
|
|
{
|
|
invoker.seekcnt = 0;
|
|
A_StartSound("hellblazer/hold",CHAN_WEAPON,CHANF_OVERLAP);
|
|
}
|
|
XZW6 V 1
|
|
{
|
|
if ( !(player.cmd.buttons&BT_ALTATTACK) )
|
|
return A_JumpByAmmoType("AltFire_1","AltFire_2","AltFire_3","AltFire_4","AltFire_G");
|
|
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
|
|
if ( (player.cmd.buttons&BT_ZOOM) && !(player.oldbuttons&BT_ZOOM) )
|
|
A_CheckLockOn();
|
|
if ( (player.cmd.buttons&BT_RELOAD) && !(player.oldbuttons&BT_RELOAD) )
|
|
{
|
|
for ( int i=0; i<3; i++ ) invoker.seektarget[i] = null;
|
|
if ( invoker.seekcnt > 0 ) A_StartSound("hellblazer/clear",CHAN_WEAPON,CHANF_OVERLAP);
|
|
invoker.seekcnt = 0;
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
Wait;
|
|
PreAltFire_3:
|
|
XZWB T 0
|
|
{
|
|
invoker.seekcnt = 0;
|
|
A_StartSound("hellblazer/hold",CHAN_WEAPON,CHANF_OVERLAP);
|
|
}
|
|
XZWB T 1
|
|
{
|
|
if ( !(player.cmd.buttons&BT_ALTATTACK) )
|
|
return A_JumpByAmmoType("AltFire_1","AltFire_2","AltFire_3","AltFire_4","AltFire_G");
|
|
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
|
|
if ( (player.cmd.buttons&BT_ZOOM) && !(player.oldbuttons&BT_ZOOM) )
|
|
A_CheckLockOn();
|
|
if ( (player.cmd.buttons&BT_RELOAD) && !(player.oldbuttons&BT_RELOAD) )
|
|
{
|
|
for ( int i=0; i<3; i++ ) invoker.seektarget[i] = null;
|
|
if ( invoker.seekcnt > 0 ) A_StartSound("hellblazer/clear",CHAN_WEAPON,CHANF_OVERLAP);
|
|
invoker.seekcnt = 0;
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
Wait;
|
|
PreAltFire_4:
|
|
XZWG R 0
|
|
{
|
|
invoker.seekcnt = 0;
|
|
A_StartSound("hellblazer/hold",CHAN_WEAPON,CHANF_OVERLAP);
|
|
}
|
|
XZWG R 1
|
|
{
|
|
if ( !(player.cmd.buttons&BT_ALTATTACK) )
|
|
return A_JumpByAmmoType("AltFire_1","AltFire_2","AltFire_3","AltFire_4","AltFire_G");
|
|
A_WeaponReady(WRF_NOFIRE|WRF_NOSWITCH);
|
|
if ( (player.cmd.buttons&BT_ZOOM) && !(player.oldbuttons&BT_ZOOM) )
|
|
A_CheckLockOn();
|
|
if ( (player.cmd.buttons&BT_RELOAD) && !(player.oldbuttons&BT_RELOAD) )
|
|
{
|
|
for ( int i=0; i<3; i++ ) invoker.seektarget[i] = null;
|
|
if ( invoker.seekcnt > 0 ) A_StartSound("hellblazer/clear",CHAN_WEAPON,CHANF_OVERLAP);
|
|
invoker.seekcnt = 0;
|
|
}
|
|
return ResolveState(null);
|
|
}
|
|
Wait;
|
|
Cycle_1:
|
|
XZW2 A 2
|
|
{
|
|
invoker.spinskipped--;
|
|
invoker.magpos = (invoker.magpos+1)%6;
|
|
A_GlassOverlay("Cycle_G1");
|
|
}
|
|
XZW3 E 2;
|
|
XZW3 FGHI 2;
|
|
XZW3 I 0;
|
|
XZW3 FE 2;
|
|
Goto Ready_1;
|
|
Cycle_2:
|
|
XZW6 V 2
|
|
{
|
|
invoker.spinskipped--;
|
|
invoker.magpos = (invoker.magpos+1)%3;
|
|
A_GlassOverlay("Cycle_G2");
|
|
}
|
|
XZW7 Z 2;
|
|
XZW8 ABCDEFG 2;
|
|
XZW8 G 0;
|
|
XZW8 A 2;
|
|
XZW7 Z 2;
|
|
Goto Ready_2;
|
|
Cycle_3:
|
|
XZWB T 2
|
|
{
|
|
invoker.spinskipped--;
|
|
invoker.magpos = (invoker.magpos+1)%3;
|
|
A_GlassOverlay("Cycle_G2");
|
|
}
|
|
XZWC X 2;
|
|
XZWC YZ 2;
|
|
XZWD ABCDE 2;
|
|
XZWD E 0;
|
|
XZWC YX 2;
|
|
Goto Ready_3;
|
|
Cycle_4:
|
|
XZWG R 2
|
|
{
|
|
invoker.spinskipped--;
|
|
invoker.magpos = (invoker.magpos+1)%2;
|
|
A_GlassOverlay("Cycle_G3");
|
|
}
|
|
XZWH V 2;
|
|
XZWH WXYZ 2;
|
|
XZWI ABCDEF 2;
|
|
XZWI F 0;
|
|
XZWH WV 2;
|
|
Goto Ready_4;
|
|
Cycle_G1:
|
|
XZWL S 2 A_StartSound("hellblazer/shift",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWM W 2;
|
|
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 2;
|
|
Goto Ready_G;
|
|
Cycle_G2:
|
|
XZWL S 2 A_StartSound("hellblazer/shift",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWM W 2;
|
|
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 2;
|
|
XZWM W 2;
|
|
Goto Ready_G;
|
|
Cycle_G3:
|
|
XZWL S 2 A_StartSound("hellblazer/shift",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWM W 2;
|
|
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 2;
|
|
XZWM W 2;
|
|
Goto Ready_G;
|
|
Reload:
|
|
XZW2 A 2
|
|
{
|
|
if ( (invoker.clipcount <= 0) && (CountInv(invoker.nextammo) <= 0) ) A_PickNextAmmo();
|
|
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 ABCDEFGHIJ 2;
|
|
XZWR JKLMN 3;
|
|
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 ABCDEFGH 2;
|
|
XZWR JKLMN 3;
|
|
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 ABCDEF 2;
|
|
XZWR JKLMN 3;
|
|
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 ABCDEFG 2;
|
|
XZWR JKLMN 3;
|
|
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;
|
|
XZWR EFGHI 3;
|
|
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|WRF_NOSWITCH);
|
|
}
|
|
#### # 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,1.2,1.2);
|
|
XZWQ RSTUV 2;
|
|
XZWQ W 2 A_StartSound("hellblazer/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
|
|
XZWQ XYZ 2;
|
|
XZWR ABCD 2;
|
|
Goto Ready_G;
|
|
}
|
|
}
|