Silver Bullet JET fully implemented.

Ammo rebalancing.
Damage boost to Candy Gun.
Various small adjustments.
Grilled Cheese Sandwich now gives 3 seconds of invulnerability on activation.
This commit is contained in:
Mari the Deer 2020-06-13 21:32:28 +02:00
commit fb078b7232
65 changed files with 1095 additions and 69 deletions

View file

@ -196,7 +196,7 @@ Class RedShell : Ammo
Tag "$T_REDSHELLS";
Stamina 500;
Inventory.Amount 1;
Inventory.MaxAmount 48;
Inventory.MaxAmount 40;
Ammo.BackpackAmount 8;
Ammo.DropAmount 3;
+FLOATBOB;
@ -255,7 +255,7 @@ Class GreenShell : Ammo
Tag "$T_GREENSHELLS";
Stamina 800;
Inventory.Amount 1;
Inventory.MaxAmount 40;
Inventory.MaxAmount 32;
Ammo.BackpackAmount 4;
Ammo.DropAmount 2;
+FLOATBOB;
@ -540,7 +540,7 @@ Class EvisceratorShell : Ammo
Inventory.PickupMessage "$T_EVISHELL";
Stamina 2500;
Inventory.Amount 1;
Inventory.MaxAmount 30;
Inventory.MaxAmount 24;
Ammo.BackpackAmount 3;
Ammo.DropAmount 2;
+FLOATBOB;
@ -577,7 +577,7 @@ Class HellblazerMissiles : Ammo
Inventory.PickupMessage "$T_HELLMISSILE";
Stamina 6000;
Inventory.Amount 1;
Inventory.MaxAmount 60;
Inventory.MaxAmount 30;
Ammo.BackpackAmount 3;
Ammo.DropAmount 1;
+FLOATBOB;
@ -609,7 +609,7 @@ Class HellblazerCrackshots : Ammo
Inventory.PickupMessage "$T_HELLCLUSTER";
Stamina 8000;
Inventory.Amount 1;
Inventory.MaxAmount 24;
Inventory.MaxAmount 18;
Ammo.BackpackAmount 2;
Ammo.DropAmount 1;
+FLOATBOB;
@ -707,7 +707,7 @@ Class SparkUnit : Ammo
Inventory.PickupMessage "$T_SPARKUNIT";
Stamina 50000;
Inventory.Amount 1;
Inventory.MaxAmount 8;
Inventory.MaxAmount 4;
Ammo.BackpackAmount 1;
Ammo.DropAmount 1;
+FLOATBOB;
@ -733,8 +733,8 @@ Class SilverBulletAmmo : Ammo
Inventory.PickupMessage "$T_XSBMAG";
Stamina 70000;
Inventory.Amount 1;
Inventory.MaxAmount 5;
Ammo.BackpackAmount 1;
Inventory.MaxAmount 3;
Ammo.BackpackAmount 0;
Ammo.DropAmount 1;
+FLOATBOB;
FloatBobStrength 0.25;
@ -759,7 +759,7 @@ Class CandyGunAmmo : Ammo
Inventory.PickupMessage "$T_CANDYMAG";
Stamina 100000;
Inventory.Amount 1;
Inventory.MaxAmount 4;
Inventory.MaxAmount 2;
Ammo.BackpackAmount 0;
Ammo.DropAmount 1;
+FLOATBOB;

View file

@ -1841,7 +1841,7 @@ Class Hellblazer : SWWMWeapon
XZWQ KLM 2;
XZWQ N 2 A_Parry(9);
XZWQ OP 1;
XZWQ Q 1 A_Melee(75,"demolitionist/whitl");
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;

View file

@ -636,8 +636,8 @@ Class Wallbuster : SWWMWeapon
{
t.HitList[i].HitActor.TraceBleed(realdmg,self);
t.HitList[i].HitActor.SpawnBlood(t.HitList[i].HitLocation,atan2(t.HitList[i].x.y,t.HitList[i].x.x)+180,realdmg);
if ( large ) t.HitList[i].HitActor.A_StartSound("spreadgun/slugf",CHAN_BODY,CHANF_OVERLAP,1.,2.);
else t.HitList[i].HitActor.A_StartSound("spreadgun/pelletf",CHAN_BODY,CHANF_OVERLAP,.4,4.);
if ( large ) t.HitList[i].HitActor.A_StartSound("spreadgun/slugf",CHAN_FOOTSTEP,CHANF_OVERLAP,1.,2.);
else t.HitList[i].HitActor.A_StartSound("spreadgun/pelletf",CHAN_FOOTSTEP,CHANF_OVERLAP,.4,4.);
}
}
if ( (t.Results.HitType != TRACE_HitNone) && (t.Results.HitType != TRACE_HasHitSky) )
@ -746,7 +746,7 @@ Class Wallbuster : SWWMWeapon
int qk = min(9,1+howmany/5);
int ql = min(25,6+howmany/2);
A_QuakeEx(qk,qk,qk,ql,0,8,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:qk*.15);
A_ZoomFactor(1.+qk*.04,ZOOM_INSTANT);
A_ZoomFactor(1.-qk*.04,ZOOM_INSTANT);
A_ZoomFactor(1.);
A_AlertMonsters(alertness);
A_PlayerFire();
@ -1390,7 +1390,7 @@ Class Wallbuster : SWWMWeapon
XZW9 GHI 2;
XZW9 J 2 A_Parry(9);
XZW9 KLM 1;
XZW9 N 1 A_Melee(70,"demolitionist/whitl");
XZW9 N 1 A_Melee(70,"demolitionist/whitl",1.2);
XZW9 OPQRS 2;
XZW9 T 2 A_StartSound("wallbuster/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
XZW9 UVW 2;

View file

@ -2811,22 +2811,22 @@ Class SWWMHandler : EventHandler
case 1:
case 2:
case 3:
if ( Random[Replacements](0,1) ) e.Replacement = 'HellblazerMissiles';
if ( Random[Replacements](0,2) ) e.Replacement = 'HellblazerMissiles';
else e.Replacement = 'HellblazerMissileMag';
break;
case 4:
case 5:
case 6:
if ( Random[Replacements](0,2) ) e.Replacement = 'HellblazerCrackshots';
if ( Random[Replacements](0,3) ) e.Replacement = 'HellblazerCrackshots';
else e.Replacement = 'HellblazerCrackshotMag';
break;
case 7:
case 8:
if ( Random[Replacements](0,3) ) e.Replacement = 'HellblazerRavagers';
if ( Random[Replacements](0,4) ) e.Replacement = 'HellblazerRavagers';
else e.Replacement = 'HellblazerRavagerMag';
break;
case 9:
if ( Random[Replacements](0,4) ) e.Replacement = 'HellblazerWarheads';
if ( Random[Replacements](0,5) ) e.Replacement = 'HellblazerWarheads';
else e.Replacement = 'HellblazerWarheadMag';
break;
}
@ -3088,6 +3088,9 @@ Class SWWMHandler : EventHandler
Screen.Dim(Color(96,255,64),.1875*fstr,0,0,Screen.GetWidth(),Screen.GetHeight());
}
}
// weapon underlays
if ( players[consoleplayer].ReadyWeapon is 'SWWMWeapon' )
SWWMWeapon(players[consoleplayer].ReadyWeapon).RenderUnderlay(e);
if ( !statusbar || !(statusbar is 'SWWMStatusBar') ) return;
SWWMStatusBar(statusbar).viewpos = e.viewpos;
SWWMStatusBar(statusbar).viewrot = (e.viewangle,e.viewpitch,e.viewroll);

View file

@ -918,7 +918,7 @@ Class Eviscerator : SWWMWeapon
XZW9 AB 1;
XZW9 C 1 A_Parry(9);
XZW9 D 1;
XZW9 E 2 A_Melee(60,"demolitionist/whitm");
XZW9 E 2 A_Melee(60,"demolitionist/whitm",1.1);
XZW9 FGH 2;
XZW9 I 2 A_StartSound("eviscerator/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
XZW9 JKL 2;
@ -929,7 +929,7 @@ Class Eviscerator : SWWMWeapon
XZWA QRS 1;
XZWA T 1 A_Parry(9);
XZWA U 1;
XZWA V 2 A_Melee(60,"demolitionist/whitm");
XZWA V 2 A_Melee(60,"demolitionist/whitm",1.1);
XZWA WXY 2;
XZWA Z 2 A_StartSound("eviscerator/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
XZWB ABC 2;

View file

@ -976,6 +976,10 @@ Class SWWMWeapon : Weapon abstract
virtual ui void HudTick()
{
}
// extra drawing, usually scopes
virtual ui void RenderUnderlay( RenderEvent e )
{
}
// animations
action void A_PlayerFire()
{
@ -1048,12 +1052,12 @@ Class SWWMWeapon : Weapon abstract
if ( !FindInventory("ParryDamageChecker") )
GiveInventory("ParryDamageChecker",1); // need this so parried projectiles deal extra damage
}
private action bool TryMelee( double angle, int dmg, String hitsound = "" )
private action bool TryMelee( double angle, int dmg, String hitsound = "", double rangemul = 1. )
{
FTranslatedLineTarget t;
double slope = AimLineAttack(angle,1.5*DEFMELEERANGE,t,0.,ALF_CHECK3D);
double slope = AimLineAttack(angle,1.5*DEFMELEERANGE*rangemul,t,0.,ALF_CHECK3D);
FLineTraceData d;
LineTrace(angle,1.5*DEFMELEERANGE,slope,0,player.viewheight,data:d);
LineTrace(angle,1.5*DEFMELEERANGE*rangemul,slope,0,player.viewheight,data:d);
bool raging = CountInv("RagekitPower");
if ( d.HitType == TRACE_HitActor )
{
@ -1105,7 +1109,7 @@ Class SWWMWeapon : Weapon abstract
}
return false;
}
action void A_Melee( int dmg = 40, String hitsound = "" )
action void A_Melee( int dmg = 40, String hitsound = "", double rangemul = 1. )
{
// temporarily disable parry field so we can trace through
if ( invoker.pfield ) invoker.pfield.bSHOOTABLE = false;
@ -1113,7 +1117,7 @@ Class SWWMWeapon : Weapon abstract
let ut = new("UseLineTracer");
ut.uses.Clear();
ut.glass.Clear();
ut.Trace(Vec3Offset(0,0,player.viewheight),CurSector,(cos(angle)*cos(pitch),sin(angle)*cos(pitch),sin(-pitch)),DEFMELEERANGE,0);
ut.Trace(Vec3Offset(0,0,player.viewheight),CurSector,(cos(angle)*cos(pitch),sin(angle)*cos(pitch),sin(-pitch)),DEFMELEERANGE*rangemul,0);
for ( int i=0; i<ut.uses.Size(); i++ )
{
if ( ut.uses[i].hitactor )
@ -1138,7 +1142,7 @@ Class SWWMWeapon : Weapon abstract
int maxang = raging?18:12;
for ( int i=0; i<maxang; i++ )
{
if ( TryMelee(angle+i*(45./16),dmg,hitsound) || TryMelee(angle-i*(45./16),dmg,hitsound) )
if ( TryMelee(angle+i*(45./16),dmg,hitsound,rangemul) || TryMelee(angle-i*(45./16),dmg,hitsound,rangemul) )
{
if ( invoker.pfield ) invoker.pfield.bSHOOTABLE = true;
return;
@ -1147,9 +1151,9 @@ Class SWWMWeapon : Weapon abstract
if ( invoker.pfield ) invoker.pfield.bSHOOTABLE = true;
// check for walls instead
FTranslatedLineTarget t;
double slope = AimLineAttack(angle,DEFMELEERANGE,t,0.,ALF_CHECK3D);
double slope = AimLineAttack(angle,DEFMELEERANGE*rangemul,t,0.,ALF_CHECK3D);
FLineTraceData d;
LineTrace(angle,DEFMELEERANGE,slope,TRF_THRUACTORS,player.viewheight,data:d);
LineTrace(angle,DEFMELEERANGE*rangemul,slope,TRF_THRUACTORS,player.viewheight,data:d);
if ( d.HitType == TRACE_HitNone ) return;
Vector3 HitNormal = -d.HitDir;
if ( d.HitType == TRACE_HitFloor )

View file

@ -392,7 +392,7 @@ Class PusherWeapon : SWWMWeapon
{
d.HitActor.TraceBleed(dmg,invoker);
d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
d.HitActor.A_StartSound("pusher/meat",CHAN_ITEMEXTRA,CHANF_OVERLAP);
d.HitActor.A_StartSound("pusher/meat",CHAN_FOOTSTEP,CHANF_OVERLAP);
}
// move towards target
bJUSTATTACKED = true;
@ -477,7 +477,7 @@ Class PusherWeapon : SWWMWeapon
{
d.HitActor.TraceBleed(dmg,invoker);
d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
d.HitActor.A_StartSound("pusher/altmeat",CHAN_ITEMEXTRA,CHANF_OVERLAP);
d.HitActor.A_StartSound("pusher/altmeat",CHAN_FOOTSTEP,CHANF_OVERLAP);
}
}
else
@ -683,7 +683,7 @@ Class PusherWeapon : SWWMWeapon
XZW5 ABC 2;
XZW5 D 1 A_Parry(9);
XZW5 EFGH 1;
XZW5 I 0 A_Melee(70,"demolitionist/whitl");
XZW5 I 0 A_Melee(70,"demolitionist/whitl",1.1);
XZW5 IJ 2;
XZW5 K 2 { invoker.PlayUpSound(self); }
XZW5 LM 2;

View file

@ -1,4 +1,18 @@
// Powerups go here
Class GrilledCheeseSafeguard : Powerup
{
Default
{
Inventory.Icon "graphics/HUD/Icons/I_Sandwich.png";
Powerup.Duration -3;
}
override void ModifyDamage( int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags )
{
if ( passive ) newdamage = 0;
}
}
Class GrilledCheeseSandwich : Inventory
{
Mixin SWWMAutoUseFix;
@ -37,6 +51,9 @@ Class GrilledCheeseSandwich : Inventory
SWWMLoreLibrary.Add(Owner.player,"Nugget");
SWWMLoreLibrary.Add(Owner.player,"BlastSuit");
SWWMLoreLibrary.Add(Owner.player,"WarArmor");
let s = Owner.FindInventory("GrilledCheeseSafeguard");
if ( !s ) Owner.GiveInventory("GrilledCheeseSafeguard",1);
else Powerup(s).EffectTics = Powerup(s).default.EffectTics;
}
override bool Use( bool pickup )
{
@ -48,6 +65,8 @@ Class GrilledCheeseSandwich : Inventory
}
override void AbsorbDamage( int damage, Name damageType, out int newdamage, Actor inflictor, Actor source, int flags )
{
if ( Owner.FindInventory("GrilledCheeseSafeguard") )
return; // the safeguard absorbs all
if ( Owner.ApplyDamageFactor(damageType,damage) <= 0 )
return; // this damage type is ignored by the player, so it does not affect us
if ( damageType == 'EndLevel' )

View file

@ -150,7 +150,7 @@ Class SpreadgunTracer : LineTracer
// go right on through if dead
if ( Results.HitActor.health-amt <= 0 ) return TRACE_Skip;
// stap
return TRACE_Abort;
return TRACE_Stop;
}
return TRACE_Skip;
}
@ -198,7 +198,7 @@ Class SpreadSlugTracer : SpreadgunTracer
ent.hitdamage = min(Results.HitActor.health+int(Results.HitActor.GetSpawnHealth()*gameinfo.gibfactor),int(penetration));
hitlist.Push(ent);
penetration = max(0,penetration-ent.hitdamage);
if ( penetration <= 0 ) return TRACE_Abort;
if ( penetration <= 0 ) return TRACE_Stop;
return TRACE_Skip;
}
return TRACE_Skip;
@ -2056,11 +2056,11 @@ Class Spreadgun : SWWMWeapon
{
t.HitList[i].HitActor.TraceBleed(realdmg,self);
t.HitList[i].HitActor.SpawnBlood(t.HitList[i].HitLocation,atan2(t.HitList[i].x.y,t.HitList[i].x.x)+180,realdmg);
if ( large ) t.HitList[i].HitActor.A_StartSound("spreadgun/slugf",CHAN_BODY,CHANF_OVERLAP,1.,2.);
else t.HitList[i].HitActor.A_StartSound("spreadgun/pelletf",CHAN_BODY,CHANF_OVERLAP,.4,4.);
if ( large ) t.HitList[i].HitActor.A_StartSound("spreadgun/slugf",CHAN_FOOTSTEP,CHANF_OVERLAP,1.,2.);
else t.HitList[i].HitActor.A_StartSound("spreadgun/pelletf",CHAN_FOOTSTEP,CHANF_OVERLAP,.4,4.);
}
}
if ( (t.Results.HitType != TRACE_HitNone) && (t.Results.HitType != TRACE_HasHitSky) )
if ( (t.Results.HitType != TRACE_HitNone) && (t.Results.HitType != TRACE_HasHitSky) && (t.Results.HitType != TRACE_HitActor) )
{
Vector3 hitnormal = -t.Results.HitVector;
if ( t.Results.HitType == TRACE_HitFloor )
@ -2100,7 +2100,7 @@ Class Spreadgun : SWWMWeapon
A_StartSound(sounds[i],CHAN_WEAPON,CHANF_OVERLAP,attenuation:.6);
A_AlertMonsters(louds[i]);
A_QuakeEx(quakes[i],quakes[i],quakes[i],9,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:.2*quakes[i]);
A_ZoomFactor(1.+quakes[i]*.04,ZOOM_INSTANT);
A_ZoomFactor(1.-quakes[i]*.04,ZOOM_INSTANT);
A_ZoomFactor(1.);
A_PlayerFire();
SWWMHandler.DoFlash(self,cols[i],5);

View file

@ -177,7 +177,7 @@ Class CandyBeam : Actor
Obituary "$O_CANDYGUN";
RenderStyle "Add";
Alpha 0.4;
DamageFunction 20;
DamageFunction 25;
ReactionTime 12;
Radius 0.1;
Height 0;
@ -238,14 +238,13 @@ Class CandyPop : Actor
BLPF B 3 NoDelay
{
SWWMHandler.DoBlast(self,120,60000);
A_Explode(100,120);
A_Explode(200,120);
Scale *= FRandom[ExploS](0.6,1.8);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
roll = FRandom[Explos](0,360);
Spawn("CandyPLight",pos);
FlashPlayer(60,800);
A_StartSound("candygun/hit",CHAN_VOICE,CHANF_DEFAULT,.08,.6,1.3);
int numpt = Random[ExploS](-3,3);
for ( int i=0; i<numpt; i++ )
{
@ -279,7 +278,7 @@ Class TinyCandyBeam : CandyBeam
Default
{
ReactionTime 12;
DamageFunction 10;
DamageFunction 15;
}
States
{
@ -304,7 +303,7 @@ Class TinyCandyPop : CandyPop
BLPF B 3 NoDelay
{
SWWMHandler.DoBlast(self,80,32000);
A_Explode(40,80);
A_Explode(60,80);
Scale *= FRandom[ExploS](0.6,1.8);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
@ -364,7 +363,7 @@ Class CandyMagArm : Actor
SWWMHandler.DoBlast(self,50+6*reactiontime,3000+800*reactiontime);
double spd = vel.length();
vel = (vel*.1+(FRandom[ExploS](-.7,.7),FRandom[ExploS](-.7,.7),FRandom[ExploS](-.7,.7))).unit()*spd;
A_Explode(40+reactiontime*5,50+6*reactiontime);
A_Explode(80+reactiontime*7,50+6*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;
@ -440,7 +439,7 @@ Class CandyMagArmBig : CandyMagArm
SWWMHandler.DoBlast(self,100+8*reactiontime,3000+900*reactiontime);
double spd = vel.length();
vel = (vel*.1+(FRandom[ExploS](-.5,.5),FRandom[ExploS](-.5,.5),FRandom[ExploS](-.5,.5))).unit()*spd;
A_Explode(80+reactiontime*8,100+8*reactiontime);
A_Explode(120+reactiontime*10,100+8*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;
@ -473,7 +472,6 @@ Class CandyMagArmBig : CandyMagArm
s.pitch = pt;
s.ReactionTime += Random[ExploS](10,30);
}
A_StartSound("candygun/maghit",CHAN_VOICE,CHANF_DEFAULT,.5,.4,1.5);
Destroy();
}
}
@ -518,7 +516,7 @@ Class CandyGunProj : Actor
Scale *= 6.+.2*special1;
A_AlertMonsters(40000);
SWWMHandler.DoBlast(self,300+20*special1,80000+8000*special1);
A_Explode(3000+400*special1,300+20*special1);
A_Explode(3500+500*special1,300+20*special1);
A_QuakeEx(9,9,9,70,0,1500+100*special1,"",QF_RELATIVE|QF_SCALEDOWN,falloff:1200,rollintensity:2.);
A_StartSound("candygun/gunhit",CHAN_VOICE,attenuation:.24);
A_StartSound("candygun/gunhit",CHAN_WEAPON,attenuation:.12);
@ -628,7 +626,7 @@ Class CandyMagProj : Actor
Scale *= 3.+.2*special1;
A_AlertMonsters(20000);
SWWMHandler.DoBlast(self,250+25*special1,80000+8000*special1);
A_Explode(600+400*special1,250+25*special1);
A_Explode(700+600*special1,250+25*special1);
A_QuakeEx(9,9,9,30,0,500+80*special1,"",QF_RELATIVE|QF_SCALEDOWN,falloff:500,rollintensity:2.);
A_StartSound("candygun/maghit",CHAN_VOICE,attenuation:.24);
A_StartSound("candygun/maghit",CHAN_WEAPON,attenuation:.12);
@ -721,7 +719,7 @@ Class CandyBulletImpact : Actor
Super.PostBeginPlay();
A_AlertMonsters(9000);
SWWMHandler.DoBlast(self,200,48000);
A_Explode(350,200);
A_Explode(700,200);
A_QuakeEx(6,6,6,15,0,300,"",QF_RELATIVE|QF_SCALEDOWN,falloff:200,rollintensity:0.2);
A_StartSound("candygun/hit",CHAN_VOICE,attenuation:.25);
A_StartSound("candygun/hit",CHAN_WEAPON,attenuation:.5);
@ -916,7 +914,7 @@ Class CandyGun : SWWMWeapon
SWWMBulletTrail.DoTrail(self,origin,dir,10000,2);
if ( d.HitType == TRACE_HitActor )
{
int dmg = 500;
int dmg = 900;
SWWMHandler.DoKnockback(d.HitActor,d.HitDir,72000);
dmg = d.HitActor.DamageMobj(invoker,self,dmg,'Explodium',DMG_USEANGLE|DMG_THRUSTLESS,atan2(d.HitDir.y,d.HitDir.x));
if ( d.HitActor.bNOBLOOD || d.HitActor.bINVULNERABLE )

View file

@ -1,27 +1,382 @@
// Blackmann-Forx Silver Bullet JET (successor to Silver Bullet from Zanaveth Ultra Suite)
// Slot 8, replaces Plasma Rifle, Hellstaff, Quietus (hilt)
Class SilverBulletCasing : SWWMCasing
{
Default
{
BounceSound "silverbullet/casing";
}
}
Class SilverBulletMag : SWWMCasing
{
Default
{
Mass 10;
BounceFactor 0.4;
WallBounceFactor 0.4;
BounceSound "silverbullet/mag";
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
heat = 0;
}
States
{
Death:
#### # -1
{
pitch = 0;
angle = FRandom[Junk](0,360);
roll = RandomPick[Junk](-90,90);
}
Stop;
}
}
Class SilverBulletMagEmpty : SilverBulletMag
{
}
Class SilverAirRip : Actor
{
Default
{
Radius 0.1;
Height 0;
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
+NOTELEPORT;
+FORCERADIUSDMG;
+NODAMAGETHRUST;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
SWWMHandler.DoBlast(self,80,4000.,target);
A_Explode(20,80,0);
Destroy();
}
}
Class SilverImpact : Actor
{
Default
{
Radius 0.1;
Height 0;
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
+NOTELEPORT;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
if ( swwm_extraalert ) A_AlertMonsters(500);
A_QuakeEx(4,4,4,20,0,200,"",QF_RELATIVE|QF_SCALEDOWN,falloff:100,rollIntensity:.9);
A_StartSound("silverbullet/hit",CHAN_VOICE,CHANF_DEFAULT,1.,.7);
A_SprayDecal("BigBulletChip",-20);
A_SprayDecal("HugeWallCrack",-20);
int numpt = Random[Silverbullet](15,25);
Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Silverbullet](-.4,.4),FRandom[Silverbullet](-.4,.4),FRandom[Silverbullet](-.4,.4))).unit()*FRandom[Silverbullet](.4,2.);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.scale *= 1.8;
s.special1 = Random[Silverbullet](1,3);
s.SetShade(Color(1,1,1)*Random[Silverbullet](96,192));
}
numpt = Random[Silverbullet](6,9);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Silverbullet](-1,1),FRandom[Silverbullet](-1,1),FRandom[Silverbullet](-1,1)).unit()*FRandom[Silverbullet](2,8);
let s = Spawn("SWWMSpark",pos);
s.scale *= 1.3;
s.vel = pvel;
}
numpt = Random[Silverbullet](10,15);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Silverbullet](-.6,.6),FRandom[Silverbullet](-.6,.6),FRandom[Silverbullet](-.6,.6))).unit()*FRandom[Silverbullet](6,20);
let s = Spawn("SWWMChip",pos);
s.scale *= 1.6;
s.vel = pvel;
}
}
States
{
Spawn:
TNT1 A 20;
Stop;
}
}
Class SilverBullet : SWWMWeapon
{
bool chambered;
bool chambered, fired;
int clipcount;
transient ui TextureID WeaponBox[2], ZoomBar;
transient ui Font TewiFont;
transient ui DynamicValueInterpolator ZoomInter;
bool zoomed;
double zoomlevel;
ui TextureID reticle;
bool initialized;
State dezoomstate;
Property ClipCount : clipcount;
// leave these while it's still unimplemented
override void DrawWeapon( double TicFrac, double bx, double by, Vector2 hs, Vector2 ss )
{
if ( !WeaponBox[0] ) WeaponBox[0] = TexMan.CheckForTexture("graphics/HUD/SilverBulletDisplay.png",TexMan.Type_Any);
if ( !WeaponBox[1] ) WeaponBox[1] = TexMan.CheckForTexture("graphics/HUD/SilverBulletZoomDisplay.png",TexMan.Type_Any);
if ( !ZoomBar ) ZoomBar = TexMan.CheckForTexture("graphics/HUD/SilverBulletZoomBar.png",TexMan.Type_Any);
if ( !TewiFont ) TewiFont = Font.GetFont('TewiShaded');
int zl = clamp(ZoomInter?ZoomInter.GetValue():int(zoomlevel*10),0,160);
if ( zl >= 10 )
{
Screen.DrawTexture(WeaponBox[1],false,bx-56,by-34,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
Screen.DrawText(TewiFont,Font.CR_WHITE,bx-54,by-34,String.Format("%2dx",zl/10),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
int zw = int(zl*31./160.);
Screen.DrawTexture(ZoomBar,false,bx-33,by-32,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRight,zw);
}
Screen.DrawTexture(WeaponBox[0],false,bx-56,by-22,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
if ( chambered && !fired ) Screen.DrawText(TewiFont,Font.CR_FIRE,bx-19,by-21,"⁺¹",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Spacing,-1);
Screen.DrawText(TewiFont,Font.CR_FIRE,bx-16,by-14,String.Format("%d",max(clipcount,0)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
int cx = (Ammo1.Amount>9)?53:50;
Screen.DrawText(TewiFont,Font.CR_FIRE,bx-cx,by-18,String.Format("%d",Ammo1.Amount),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
override void HudTick()
{
if ( !ZoomInter ) ZoomInter = DynamicValueInterpolator.Create(int(zoomlevel*10),.5,1,20);
ZoomInter.Update(int(zoomlevel*10));
}
override bool ReportHUDAmmo()
{
return false;
if ( (chambered && !fired) || (clipcount > 0) ) return true;
if ( Ammo1.Amount <= 0 ) return false;
return Super.ReportHUDAmmo();
}
override bool CheckAmmo( int firemode, bool autoswitch, bool requireammo, int ammocount )
{
return false;
if ( sv_infiniteammo || Owner.FindInventory('PowerInfiniteAmmo',true) ) return true;
if ( fireMode == PrimaryFire ) return ((chambered && !fired) || (clipcount > 0) || (Ammo1.Amount > 0));
if ( fireMode == AltFire ) return true; // it's just a zoom
return Super.CheckAmmo(firemode,autoswitch,requireammo,ammocount);
}
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
if ( other.player == players[consoleplayer] )
Console.Printf("\cgSILVER BULLET JET NOT IMPLEMENTED\c-");
if ( !initialized )
{
initialized = true;
// first copy always has a bullet in the chamber
chambered = true;
fired = false;
}
}
override void DetachFromOwner()
{
// force disable zoom
zoomed = false;
if ( Owner.player == players[consoleplayer] )
Shader.SetEnabled(players[consoleplayer],"SilverScope",false);
Super.DetachFromOwner();
}
override void DoEffect()
{
Super.DoEffect();
if ( zoomed ) crosshair = 99;
else crosshair = 0;
}
override void RenderUnderlay( RenderEvent e )
{
if ( zoomed && (Owner.player == players[consoleplayer]) )
{
Vector2 ss = (Screen.GetWidth(),Screen.GetHeight());
ss *= (512./ss.y);
Shader.SetEnabled(players[consoleplayer],"SilverScope",true);
if ( !reticle ) reticle = TexMan.CheckForTexture("graphics/SBReticle.png",TexMan.Type_Any);
Screen.DrawTexture(reticle,false,ss.x*.5,ss.y*.5,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Stencil,DTA_FillColor,Color(0,0,0));
}
else Shader.SetEnabled(players[consoleplayer],"SilverScope",false);
}
action void ProcessTraceHit( SpreadgunTracer t, Vector3 origin, Vector3 dir )
{
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
{
t.ShootThroughList[i].Activate(self,0,SPAC_PCross);
if ( t.ShootThroughList[i].special == GlassBreak ) // fuck glass
t.ShootThroughList[i].Activate(target,0,SPAC_Impact);
}
for ( int i=0; i<t.WaterHitList.Size(); i++ )
{
let b = Spawn("InvisibleSplasher",t.WaterHitList[i].hitpos);
b.A_CheckTerrain();
}
for ( int i=8; i<t.Results.Distance; i+=16 )
{
let s = Spawn("SilverAirRip",level.Vec3Offset(origin,dir*i));
s.target = self;
if ( !Random[Boolet](0,1) ) continue;
let b = Spawn("SWWMSmoke",level.Vec3Offset(origin,dir*i));
b.Scale *= FRandom[Boolet](.9,1.6);
b.alpha *= .5;
b.special1 = Random[Boolet](0,2);
}
for ( int i=0; i<t.HitList.Size(); i++ )
{
int realdmg = t.HitList[i].HitDamage;
SWWMDamageAccumulator.Accumulate(t.HitList[i].HitActor,realdmg,invoker,self,'shot');
SWWMHandler.DoKnockback(t.HitList[i].HitActor,t.HitList[i].x+(0,0,0.025),realdmg*20.*FRandom[SilverBullet](.8,1.2));
if ( t.HitList[i].HitActor.bNOBLOOD || t.HitList[i].HitActor.bINVULNERABLE )
{
let p = Spawn("SilverImpact",t.HitList[i].HitLocation);
p.angle = atan2(t.HitList[i].x.y,t.HitList[i].x.x)+180;
p.pitch = asin(t.HitList[i].x.z);
}
else
{
t.HitList[i].HitActor.TraceBleed(realdmg,self);
t.HitList[i].HitActor.SpawnBlood(t.HitList[i].HitLocation,atan2(t.HitList[i].x.y,t.HitList[i].x.x)+180,realdmg);
t.HitList[i].HitActor.A_StartSound("silverbullet/flesh",CHAN_FOOTSTEP,CHANF_OVERLAP,1.,2.);
}
}
if ( (t.Results.HitType != TRACE_HitNone) && (t.Results.HitType != TRACE_HasHitSky) && (t.Results.HitType != TRACE_HitActor) )
{
Vector3 hitnormal = -t.Results.HitVector;
if ( t.Results.HitType == TRACE_HitFloor )
{
if ( t.Results.FFloor ) hitnormal = -t.Results.FFloor.top.Normal;
else hitnormal = t.Results.HitSector.floorplane.Normal;
}
else if ( t.Results.HitType == TRACE_HitCeiling )
{
if ( t.Results.FFloor ) hitnormal = -t.Results.FFloor.bottom.Normal;
else hitnormal = t.Results.HitSector.ceilingplane.Normal;
}
else if ( t.Results.HitType == TRACE_HitWall )
{
hitnormal = (-t.Results.HitLine.delta.y,t.Results.HitLine.delta.x,0).unit();
if ( !t.Results.Side ) hitnormal *= -1;
}
let p = Spawn("SilverImpact",t.Results.HitPos+hitnormal*4);
p.angle = atan2(hitnormal.y,hitnormal.x);
p.pitch = asin(-hitnormal.z);
if ( t.Results.HitLine ) t.Results.HitLine.RemoteActivate(self,t.Results.Side,SPAC_Impact,t.Results.HitPos);
}
}
action void A_SilverFire()
{
A_SWWMFlash();
A_StartSound("silverbullet/fire",CHAN_WEAPON,CHANF_OVERLAP,attenuation:.3);
A_AlertMonsters(16000);
A_QuakeEx(8,8,8,10,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:2.);
double basezoom = invoker.zoomed?clamp(invoker.zoomlevel,1.,16.):1.;
A_ZoomFactor(basezoom*.76,ZOOM_INSTANT);
A_ZoomFactor(basezoom);
A_PlayerFire();
SWWMHandler.DoFlash(self,Color(110,255,192,80),8);
A_Overlay(-9999,"Jet");
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+1*y-1*z);
Vector3 x2, y2, z2;
[x2, y2, z2] = swwm_CoordUtil.GetAxes(BulletSlope(),angle,roll);
SpreadSlugTracer sst = new("SpreadSlugTracer");
sst.ignoreme = self;
sst.penetration = 1500.;
sst.hitlist.Clear();
sst.shootthroughlist.Clear();
sst.waterhitlist.Clear();
sst.Trace(origin,level.PointInSector(origin.xy),x2,20000.,TRACE_HitSky);
ProcessTraceHit(sst,origin,x2);
for ( int i=0; i<10; i++ )
{
let s = Spawn("SWWMViewSmoke",origin);
SWWMViewSmoke(s).ofs = (10,1,-1);
s.target = self;
s.SetShade(Color(1,1,1)*Random[Silverbullet](96,192));
s.alpha *= .5;
}
for ( int i=0; i<16; i++ )
{
let s = Spawn("SWWMSmoke",origin);
s.scale *= 1.3;
s.alpha *= .5;
s.special1 = Random[Silverbullet](0,3);
s.SetShade(Color(1,1,1)*Random[Silverbullet](96,192));
s.vel += vel*.5+x*FRandom[Silverbullet](2.,7.)+y*FRandom[Silverbullet](-2.,2.)+z*FRandom[Silverbullet](-2.,2.);
}
for ( int i=0; i<34; i++ )
{
let s = Spawn("SWWMSmoke",origin);
s.scale *= 1.8;
s.alpha *= .8;
s.special1 = Random[Silverbullet](0,2);
s.SetShade(Color(1,1,1)*Random[Silverbullet](96,192));
s.vel += vel*.5+y*FRandom[Silverbullet](2.,8.)*RandomPick[SilverBullet](-1,1);
}
for ( int i=0; i<20; i++ )
{
let s = Spawn("SWWMSpark",origin);
s.scale *= .4;
s.alpha *= .4;
s.vel += vel*.5+x*FRandom[Silverbullet](4.,8.)+y*FRandom[Silverbullet](-1,1)+z*FRandom[Silverbullet](-1,1);
}
SWWMHandler.DoKnockback(self,-x,320000.);
}
action void A_DropCasing()
{
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+10*y-8*z);
let c = Spawn("SilverBulletCasing",origin);
c.angle = angle;
c.pitch = pitch;
c.vel = x*FRandom[Junk](-.5,.5)+y*FRandom[Junk](4,8)-(0,0,FRandom[Junk](1,3));
c.vel += vel*.5;
}
action void A_DropMag()
{
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),6*x-15*z);
let c = Spawn((invoker.clipcount>0)?"SilverBulletMag":"SilverBulletMagEmpty",origin);
c.angle = angle;
c.pitch = pitch;
c.vel = x*FRandom[Junk](-.5,.5)+y*FRandom[Junk](-.5,.5)-(0,0,FRandom[Junk](2,3));
c.vel += vel*.5;
}
action void A_JetCompensate()
{
invoker.specialf1 -= .06;
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
vel += x*min(1.,invoker.specialf1)*(600./Mass);
A_OverlayAlpha(PSP_WEAPON+2,clamp(invoker.specialf1*3.,0.,1.));
if ( Random[SilverBullet](0,int(invoker.specialf1*4)) )
self.DamageMobj(invoker,self,2,'jet');
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),-x*10-z*10);
for ( int i=0; i<4; i++ )
{
let s = Spawn("SWWMSmoke",origin);
s.scale *= 1.3;
s.alpha *= .5*invoker.specialf1;
s.special1 = Random[Silverbullet](0,3);
s.SetShade(Color(1,1,1)*Random[Silverbullet](224,255));
s.vel += vel*.5+x*FRandom[Silverbullet](-8.,-5.)+y*FRandom[Silverbullet](3.,6.)*RandomPick[Silverbullet](-1,1)+z*FRandom[Silverbullet](-3.,-2.);
}
}
Default
@ -31,6 +386,7 @@ Class SilverBullet : SWWMWeapon
Obituary "$O_SILVERBULLET";
Weapon.SlotNumber 8;
Weapon.SelectionOrder 1400;
Weapon.UpSound "silverbullet/select";
Stamina 400000;
Weapon.AmmoType1 "SilverBulletAmmo";
Weapon.AmmoGive1 1;
@ -44,20 +400,263 @@ Class SilverBullet : SWWMWeapon
XZW1 A -1;
Stop;
Select:
TNT1 A 1
{
Console.Printf("\cgSILVER BULLET JET NOT IMPLEMENTED\c-");
A_FullRaise();
}
XZW2 G 2 A_FullRaise();
XZW2 HIJKLMN 2;
Goto Ready;
Ready:
TNT1 A 1 A_WeaponReady();
XZW2 A 1
{
int flg = WRF_ALLOWZOOM|WRF_ALLOWUSER1;
if ( (invoker.clipcount < invoker.default.clipcount) && (sv_infiniteammo || FindInventory('PowerInfiniteAmmo',true) || (invoker.Ammo1.Amount > 0)) )
flg |= WRF_ALLOWRELOAD;
A_WeaponReady(flg);
if ( player.cmd.buttons&BT_ATTACK )
invoker.CheckAmmo(EitherFire,true);
}
Wait;
ZoomReady:
TNT1 A 1
{
int flg = WRF_ALLOWZOOM|WRF_ALLOWUSER1;
if ( (invoker.clipcount < invoker.default.clipcount) && (sv_infiniteammo || FindInventory('PowerInfiniteAmmo',true) || (invoker.Ammo1.Amount > 0)) )
flg |= WRF_ALLOWRELOAD;
A_WeaponReady(flg);
if ( player.cmd.buttons&BT_ATTACK )
invoker.CheckAmmo(EitherFire,true);
}
Wait;
Fire:
XZW2 A 1
{
if ( !invoker.chambered || invoker.fired )
{
if ( !invoker.fired && (invoker.clipcount <= 0) && (sv_infiniteammo || FindInventory('PowerInfiniteAmmo',true) || (invoker.Ammo1.Amount > 0)) )
return ResolveState("Reload");
return ResolveState("Cock");
}
A_SilverFire();
invoker.fired = true;
return A_JumpIf(invoker.zoomed,"ZoomFire");
}
XZW2 OPQR 2;
XZW2 STUVW 3;
XZW2 A 1 A_JumpIf(invoker.specialf1<=0.,"Ready");
Wait;
Jet:
TNT1 A 3
{
invoker.specialf1 = 1.5;
}
TNT1 A 0
{
A_StartSound("silverbullet/jet",CHAN_WEAPON,CHANF_OVERLAP);
A_Overlay(PSP_WEAPON+2,"JetSmoke");
A_OverlayFlags(PSP_WEAPON+2,PSPF_RENDERSTYLE|PSPF_ALPHA|PSPF_FORCESTYLE|PSPF_FORCEALPHA,true);
A_OverlayRenderStyle(PSP_WEAPON+2,STYLE_Add);
}
TNT1 A 1
{
A_JetCompensate();
return A_JumpIf(invoker.specialf1<=0.,1);
}
Wait;
TNT1 A 1;
Stop;
JetSmoke:
XZW7 PQR 2;
XZW7 STUVW 3;
XZW7 X 1 A_JumpIf(invoker.specialf1<=0.,1);
Wait;
TNT1 A 1;
Stop;
Cock:
XZW2 A 0
{
if ( invoker.zoomed )
{
invoker.dezoomstate = ResolveState("DoCock");
return ResolveState("AltFireZoom");
}
return ResolveState(null);
}
DoCock:
XZW2 A 2 A_StartSound("silverbullet/meleestart",CHAN_WEAPON,CHANF_OVERLAP);
XZW2 XYZ 2;
XZW3 AB 2;
XZW3 C 2
{
A_StartSound("silverbullet/boltopen",CHAN_WEAPON,CHANF_OVERLAP);
invoker.fired = false;
if ( invoker.chambered )
A_Overlay(PSP_WEAPON+1,"Casing");
invoker.chambered = (invoker.clipcount>0);
invoker.clipcount = max(0,invoker.clipcount-1);
}
XZW3 DEFG 2;
XZW3 H 2 A_StartSound("silverbullet/boltclose",CHAN_WEAPON,CHANF_OVERLAP);
XZW3 I 2 A_StartSound("silverbullet/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
XZW3 JKLMNOPQR 2;
Goto Ready;
Casing:
XZW7 DE 2;
XZW7 FGHIJKLMNO 1;
TNT1 A 0 A_DropCasing();
Stop;
ZoomFire:
TNT1 A 24;
TNT1 A 1 A_JumpIf(invoker.specialf1<=0.,"ZoomReady");
Wait;
AltFire:
XZW2 A 0 A_JumpIf(invoker.zoomed,"AltFireZoom");
XZW2 A 2
{
A_StartSound("silverbullet/zoomstart",CHAN_WEAPON,CHANF_OVERLAP);
invoker.zoomlevel = 0;
}
XZW3 STUVWX 1;
TNT1 A 1
{
invoker.zoomed = true;
invoker.zoomlevel = clamp(invoker.zoomlevel*1.1+.1,1.,16.);
A_ZoomFactor(invoker.zoomlevel);
if ( !(level.maptime%2) && (invoker.zoomlevel < 16.) ) A_StartSound("silverbullet/zooming",CHAN_WEAPON,CHANF_OVERLAP,.2);
if ( !(player.cmd.buttons&BT_ALTATTACK) )
return ResolveState("ZoomReady");
return ResolveState(null);
}
Wait;
AltFireZoom:
XZW3 X 1
{
A_StartSound("silverbullet/zoomend",CHAN_WEAPON,CHANF_OVERLAP);
invoker.zoomed = false;
invoker.zoomlevel = 0;
A_ZoomFactor(1.,ZOOM_INSTANT);
}
XZW3 YZ 1;
XZW4 ABC 1;
XZW2 A 0
{
if ( invoker.dezoomstate )
{
State tmp = invoker.dezoomstate;
invoker.dezoomstate = null;
return tmp;
}
return ResolveState(null);
}
Goto Ready;
Reload:
XZW2 A 0
{
if ( invoker.zoomed )
{
invoker.dezoomstate = ResolveState("Unload");
return ResolveState("AltFireZoom");
}
return ResolveState(null);
}
Unload:
XZW2 A 2
{
A_PlayerReload();
A_StartSound("silverbullet/meleestart",CHAN_WEAPON,CHANF_OVERLAP);
return A_JumpIf(invoker.clipcount<=0,"UnloadEmpty");
}
XZW4 DEFGHI 2;
XZW4 J 2 A_StartSound("silverbullet/magout",CHAN_WEAPON,CHANF_OVERLAP);
XZW4 KLMN 2;
Goto Load;
UnloadEmpty:
XZW2 A 2;
XZW4 OPQRST 2;
XZW4 U 2 A_StartSound("silverbullet/magout",CHAN_WEAPON,CHANF_OVERLAP);
XZW4 VWXY 2;
Goto Load;
Load:
XZW4 Z 2
{
A_DropMag();
invoker.clipcount = invoker.default.clipcount;
if ( !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true) )
invoker.Ammo1.Amount = max(0,invoker.Ammo1.Amount-1);
}
XZW5 ABC 2;
XZW5 D 2 A_StartSound("silverbullet/magin",CHAN_WEAPON,CHANF_OVERLAP);
XZW5 E 2 A_StartSound("silverbullet/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
XZW5 FGHIJKLMN 2;
Goto Ready;
Zoom:
XZW2 A 0
{
if ( invoker.zoomed )
{
invoker.dezoomstate = ResolveState("DoZoom");
return ResolveState("AltFireZoom");
}
return ResolveState(null);
}
DoZoom:
XZW2 A 2
{
A_StartSound("silverbullet/idle",CHAN_WEAPON,CHANF_OVERLAP);
A_PlayerCheckGun();
}
XZW5 OPQR 3;
XZW5 STUV 2;
XZW5 WXYZ 3;
XZW6 ABCD 4;
XZW6 EFGH 3;
Goto Ready;
User1:
XZW2 A 0
{
if ( invoker.zoomed )
{
invoker.dezoomstate = ResolveState("DoUser1");
return ResolveState("AltFireZoom");
}
return ResolveState(null);
}
DoUser1:
XZW2 A 2
{
A_StartSound("silverbullet/meleestart",CHAN_WEAPON,CHANF_OVERLAP);
A_StartSound("demolitionist/wswing",CHAN_WEAPON,CHANF_OVERLAP);
A_PlayerMelee();
}
XZW6 IJK 3;
XZW6 L 1 A_Parry(9);
XZW6 MN 1;
XZW6 O 1 A_Melee(90,"demolitionist/whitl",1.6);
XZW6 PQ 1;
XZW6 RST 2;
XZW6 U 3 A_StartSound("silverbullet/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
XZW6 VWXYZ 3;
XZW7 ABC 2;
Goto Ready;
Deselect:
TNT1 A -1 A_FullLower();
XZW2 A 0
{
if ( invoker.zoomed )
{
invoker.dezoomstate = ResolveState("DoDeselect");
return ResolveState("AltFireZoom");
}
return ResolveState(null);
}
DoDeselect:
XZW2 A 2 A_StartSound("silverbullet/deselect",CHAN_WEAPON,CHANF_OVERLAP);
XZW2 BCDEF 2;
XZW2 G -1 A_FullLower();
Stop;
Flash:
XZWZ A 2 Bright
{
let l = Spawn("SWWMWeaponLight",pos);
l.args[3] = 200;
l.target = self;
}
Stop;
}
}