swwmgz_m/zscript/swwm_splode.zsc
Marisa Kirisame af1df2e18d Allow selling excess weapons/powerups.
Change of plans for one DLC weapon choice.
Various small fixes and tweaks.
Doubled price of Ynykron, since it was too cheap.
Fixed Candygun spares not being picked up in coop.
Add option to toggle menu fuzz, for streamers concerned about bitrate.
Add MAP07 enemies to the vanilla boss enhancer.
2020-05-19 14:30:35 +02:00

590 lines
16 KiB
Text

// Munch Innovations Explodium Gun (from SWWM series)
// Slot 2, replaces Pistol, Elven Wand, Hexen starting weapons
Class ExplodiumCasing : SWWMCasing {}
Class ExplodiumMag : SWWMCasing
{
Default
{
Mass 10;
BounceFactor 0.4;
WallBounceFactor 0.4;
BounceSound "explodium/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 ExplodiumMagEmpty : ExplodiumMag {}
Class ExplodiumMagArm : Actor
{
Default
{
+NOBLOCKMAP;
+THRUACTORS;
+BOUNCEONWALLS;
+BOUNCEONFLOORS;
+BOUNCEONCEILINGS;
+MISSILE;
+NODAMAGETHRUST;
+FORCERADIUSDMG;
+NOTELEPORT;
-NOGRAVITY;
Gravity 0.35;
BounceFactor 1.0;
Radius 4;
Height 4;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
reactiontime = Random[ExploS](10,15);
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](8.,20.);
}
States
{
Spawn:
TNT1 A 1
{
A_CountDown();
Spawn("ExplodiumMagTrail",pos);
SWWMHandler.DoBlast(self,30+2*reactiontime,3000+500*reactiontime);
A_Explode(2+reactiontime/3,30+2*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(1,1,1)*Random[ExploS](64,224));
s.special1 = Random[ExploS](1,3);
s.scale *= 2.4;
s.alpha *= 0.1+.4*(ReactionTime/15.);
}
Wait;
}
}
Class ExplodiumMagTrail : Actor
{
Default
{
RenderStyle "Add";
+NOBLOCKMAP;
+NOGRAVITY;
+FORCEXYBILLBOARD;
+NOTELEPORT;
Scale 1.1;
}
States
{
Spawn:
XEX1 ADGJMPSVY\ 1 Bright;
Stop;
}
}
Class ExplodiumMagProj : Actor
{
double pitchvel, anglevel;
Vector3 cvel;
Default
{
DamageType "Explodium";
Radius 6;
Height 6;
Gravity 0.5;
Speed 30;
PROJECTILE;
-NOGRAVITY;
+ROLLSPRITE;
+ROLLCENTER;
+INTERPOLATEANGLES;
+NODAMAGETHRUST;
+FORCERADIUSDMG;
+FORCEXYBILLBOARD;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
}
void A_BlowUp()
{
angle = atan2(cvel.y,cvel.x);
pitch = asin(-cvel.z);
bNOGRAVITY = true;
A_SetRenderStyle(1.,STYLE_Add);
Scale *= 2.+.2*special1;
A_AlertMonsters(6000);
SWWMHandler.DoBlast(self,120+30*special1,80000+8000*special1);
A_Explode(20+15*special1,120+30*special1);
A_QuakeEx(9,9,9,30,0,400+80*special1,"",QF_RELATIVE|QF_SCALEDOWN,falloff:300,rollintensity:2.);
A_StartSound("explodium/maghit",CHAN_VOICE,attenuation:.35);
A_StartSound("explodium/maghit",CHAN_WEAPON,attenuation:.2);
A_SprayDecal("BigScorch",172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
int numpt = Random[ExploS](16,32);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,6);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.SetShade(Color(1,1,1)*Random[ExploS](64,224));
s.special1 = Random[ExploS](1,4);
s.scale *= 2.8;
s.alpha *= .4;
}
numpt = Random[ExploS](10,20);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](2,12);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[ExploS](20,30);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](2,24);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
}
numpt = int(Random[ExploS](3,5)*(1.+.4*special1));
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("ExplodiumMagArm",pos);
s.target = target;
}
Spawn("ExploLight2",pos);
}
States
{
Spawn:
XZW1 A 1
{
pitch += pitchvel;
angle += anglevel;
if ( vel.length() > 0. ) cvel = vel.unit();
}
Wait;
Death:
TNT1 A 0 A_BlowUp();
XEX1 ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] 1 Bright;
Stop;
}
}
Class ExploLight : PaletteLight
{
Default
{
ReactionTime 15;
}
}
Class ExploLight2 : PaletteLight
{
Default
{
ReactionTime 30;
Args 0,0,0,120;
}
}
Class ExplodiumBulletImpact : Actor
{
Default
{
DamageType "Explodium";
RenderStyle "Add";
Scale 1.2;
+NOGRAVITY;
+NOBLOCKMAP;
+NODAMAGETHRUST;
+FORCERADIUSDMG;
+FORCEXYBILLBOARD;
+NOTELEPORT;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_AlertMonsters(3000);
SWWMHandler.DoBlast(self,120,80000);
A_Explode(25,120);
A_QuakeEx(4,4,4,10,0,250,"",QF_RELATIVE|QF_SCALEDOWN,falloff:150,rollintensity:0.2);
A_StartSound("explodium/hit",CHAN_VOICE,attenuation:.6);
A_StartSound("explodium/hit",CHAN_WEAPON,attenuation:.3);
A_SprayDecal("Scorch",-172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
int numpt = Random[ExploS](10,20);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,3);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.SetShade(Color(1,1,1)*Random[ExploS](64,224));
s.special1 = Random[ExploS](1,2);
s.scale *= 2.4;
s.alpha *= .4;
}
numpt = Random[ExploS](8,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](2,6);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[ExploS](6,16);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](2,12);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
}
Spawn("ExploLight",pos);
}
States
{
Spawn:
XEX1 ACEGIKMOQSUWY[] 1 Bright;
Stop;
}
}
Class ExplodiumGun : SWWMWeapon
{
int clipcount;
bool chambered;
transient ui TextureID WeaponBox;
transient ui Font TewiFont;
Property ClipCount : ClipCount;
override void DrawWeapon( double TicFrac, double bx, double by, Vector2 hs, Vector2 ss )
{
if ( !WeaponBox ) WeaponBox = TexMan.CheckForTexture("graphics/HUD/ExplodiumDisplay.png",TexMan.Type_Any);
if ( !TewiFont ) TewiFont = Font.GetFont('TewiShaded');
Screen.DrawTexture(WeaponBox,false,bx-24,by-22,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
if ( chambered ) Screen.DrawText(TewiFont,Font.CR_FIRE,bx-22,by-21,"⁺¹",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Spacing,-1);
Screen.DrawText(TewiFont,Font.CR_FIRE,bx-19,by-14,String.Format("%d",max(clipcount,0)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
action void A_Schutt()
{
let weap = Weapon(invoker);
if ( !weap ) return;
invoker.chambered = invoker.clipcount;
invoker.clipcount = max(invoker.clipcount-1,0);
A_StartSound("explodium/fire",CHAN_WEAPON,CHANF_OVERLAP);
A_QuakeEx(5,5,5,3,0,10,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:1.5);
A_ZoomFactor(.96,ZOOM_INSTANT);
A_ZoomFactor(1.);
A_SWWMFlash();
SWWMHandler.DoFlash(self,Color(64,255,224,64),3);
A_AlertMonsters(5000);
A_Recoil(1.2);
Vector3 x, y, z, x2, y2, z2;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+3*y-2*z);
double a = FRandom[Spread](0,360), s = FRandom[Spread](0,.002);
[x2, y2, z2] = swwm_CoordUtil.GetAxes(BulletSlope(),angle,roll);
Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
FLineTraceData d;
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION|TRF_NOSKY,origin.z,origin.x,origin.y,d);
SWWMBulletTrail.DoTrail(self,origin,dir,10000,2);
if ( d.HitType == TRACE_HitActor )
{
int dmg = 25;
SWWMHandler.DoKnockback(d.HitActor,d.HitDir,48000);
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 )
{
let p = Spawn("SWWMBulletImpact",d.HitLocation);
p.angle = atan2(d.HitDir.y,d.HitDir.x)+180;
p.pitch = asin(d.HitDir.z);
}
else
{
d.HitActor.TraceBleed(dmg,self);
d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
}
let b = Spawn("ExplodiumBulletImpact",d.HitLocation-d.HitDir*4.);
b.angle = atan2(d.HitDir.y,d.HitDir.x)+180;
b.pitch = asin(d.HitDir.z);
b.target = self;
}
else if ( d.HitType != TRACE_HitNone )
{
Vector3 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("SWWMBulletImpact",d.HitLocation+hitnormal*0.01);
p.angle = atan2(hitnormal.y,hitnormal.x);
p.pitch = asin(-hitnormal.z);
if ( d.HitLine ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation);
let b = Spawn("ExplodiumBulletImpact",d.HitLocation+hitnormal*4.);
b.angle = atan2(hitnormal.y,hitnormal.x);
b.pitch = asin(-hitnormal.z);
b.target = self;
}
for ( int i=0; i<6; i++ )
{
let s = Spawn("SWWMViewSmoke",origin);
SWWMViewSmoke(s).ofs = (15,4.5,-3);
s.target = self;
s.alpha *= 0.5;
}
}
action void A_ThrowMag()
{
let weap = Weapon(invoker);
if ( !weap ) return;
Vector3 x, y, z, x2, y2, z2;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x-2*y-3*z);
double a = FRandom[Spread](0,360), s = FRandom[Spread](0,.005);
[x2, y2, z2] = swwm_CoordUtil.GetAxes(BulletSlope(),angle,roll);
Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
let p = Spawn("ExplodiumMagProj",origin);
p.special1 = invoker.special1;
p.target = self;
p.angle = atan2(dir.y,dir.x);
p.pitch = asin(-dir.z);
p.vel = dir*p.speed;
p.vel.z += 5.;
p.vel += vel*.5;
}
action void A_DropMag( bool loaded = false )
{
Vector3 x, y, z;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x-2*y-10*z);
let c = Spawn(loaded?"ExplodiumMag":"ExplodiumMagEmpty",origin);
c.angle = angle;
c.pitch = pitch;
c.vel = x*FRandom[Junk](-.5,.5)+y*FRandom[Junk](-1.2,.3)-(0,0,FRandom[Junk](2,3));
c.vel += vel*.5;
}
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+8*y-10*z);
let c = Spawn("ExplodiumCasing",origin);
c.angle = angle;
c.pitch = pitch;
c.vel = x*FRandom[Junk](-.5,.5)+y*FRandom[Junk](2,4)-(0,0,FRandom[Junk](2,3));
c.vel += vel*.5;
}
override bool ReportHUDAmmo()
{
return true;
}
Default
{
Tag "$T_EXPLODIUM";
Inventory.PickupMessage "$T_EXPLODIUM";
Obituary "$O_EXPLODIUM";
Weapon.UpSound "explodium/select";
Weapon.SlotNumber 2;
Weapon.SelectionOrder 2600;
//Inventory.MaxAmount 2;
//Weapon.SisterWeapon "DualExplodiumGun";
Stamina 8000;
ExplodiumGun.ClipCount 7;
}
States
{
Spawn:
XZW1 A -1;
Stop;
Select:
XZW2 B 2 A_FullRaise();
XZW2 CDEFGH 2;
Goto Ready;
Ready:
XZW2 A 1
{
if ( (invoker.clipcount <= 0) && !invoker.chambered ) player.SetPSprite(PSP_WEAPON,ResolveState("Reload"));
else if ( (invoker.clipcount > 0) && !invoker.chambered ) player.SetPSprite(PSP_WEAPON,ResolveState("Slide"));
else A_WeaponReady(WRF_ALLOWZOOM|WRF_ALLOWUSER1|WRF_ALLOWRELOAD);
}
Wait;
Fire:
XZW2 A 1 A_Schutt();
XZW2 IJKLM 1;
XZW2 N 1 A_Recoil(-.7);
XZW2 OPQR 1;
XZW2 S 2 A_DropCasing();
Goto Ready;
AltFire:
XZW2 A 2 A_JumpIf(invoker.clipcount<=0,"Reload");
XZW5 NO 2;
XZW5 P 1 A_StartSound("explodium/magpin",CHAN_WEAPON,CHANF_OVERLAP);
XZW5 QRSTUVWXYZ 1;
XZW6 A 1 A_StartSound("explodium/slideback",CHAN_WEAPON,CHANF_OVERLAP);
XZW6 B 1;
XZW6 C 1
{
A_StartSound("explodium/magout",CHAN_WEAPON,CHANF_OVERLAP);
invoker.special1 = invoker.clipcount;
invoker.clipcount = 0;
}
XZW6 D 1 A_StartSound("explodium/throwmag",CHAN_WEAPON,CHANF_OVERLAP);
XZW6 EFGHIJKLMNOPRS 1;
XZW6 T 1 A_ThrowMag();
XZW6 UVWXY 2;
XZW6 Z 4;
Goto ReloadEnd;
Reload:
XZW2 A 1
{
if ( invoker.clipcount <= 0 ) return ResolveState("ReloadEmpty");
else if ( invoker.clipcount >= invoker.default.clipcount ) return ResolveState("CheckBullet");
return ResolveState(null);
}
XZW2 TUVWXYZ 1;
XZW3 A 1 A_StartSound("explodium/slideback",CHAN_WEAPON,CHANF_OVERLAP,.3);
XZW3 B 1 { invoker.clipcount = 0; }
XZW3 C 1;
XZW3 D 1 A_StartSound("explodium/magout",CHAN_WEAPON,CHANF_OVERLAP);
XZW3 EFGH 1;
XZW3 I 1 A_DropMag(true);
Goto ReloadEnd;
ReloadEmpty:
XZW2 A 1;
XZW3 JKLMNOP 1;
XZW3 Q 1 A_StartSound("explodium/slideback",CHAN_WEAPON,CHANF_OVERLAP,.3);
XZW3 RS 1;
XZW3 T 1 A_StartSound("explodium/magout",CHAN_WEAPON,CHANF_OVERLAP);
XZW3 UVWX 1;
XZW3 Y 1 A_DropMag();
Goto ReloadEnd;
ReloadEnd:
XZW3 Z 1;
XZW4 ABCDE 1;
XZW4 F 1 A_StartSound("explodium/magin",CHAN_WEAPON,CHANF_OVERLAP);
XZW4 GHIJKLMNOPQ 1;
XZW4 R 1 { A_StartSound("explodium/jamitin",CHAN_WEAPON,CHANF_OVERLAP); invoker.clipcount = invoker.default.clipcount; }
XZW4 STUV 1;
XZW2 A 1 A_JumpIf(!invoker.chambered,"Slide");
Goto Ready;
Slide:
XZW2 A 1;
XZW4 WXY 1;
XZW5 A 1 A_StartSound("explodium/slideback",CHAN_WEAPON,CHANF_OVERLAP,.3);
XZW5 BC 1;
XZW5 D 1 { invoker.chambered = true; invoker.clipcount--; }
XZW5 EFG 1;
XZW5 H 1 A_StartSound("explodium/slideforward",CHAN_WEAPON,CHANF_OVERLAP);
XZW5 IJKLM 1;
Goto Ready;
Zoom:
XZW2 A 1 A_Jump(256,"Zoom1","Zoom2","Zoom2");
Goto Ready;
CheckBullet:
XZW2 A 1;
XZW7 ABCDE 1;
XZW7 F 1 A_StartSound("explodium/slideback",CHAN_WEAPON,CHANF_OVERLAP);
XZW7 GHIJKLMNOP 1;
XZW7 Q 1 A_StartSound("explodium/slideforward",CHAN_WEAPON,CHANF_OVERLAP);
XZW7 RS 1;
Goto Ready;
User1:
XZW2 A 1;
XZW7 TU 1;
User1Hold:
XZW7 V 1
{
A_StartSound("demolitionist/swing",CHAN_WEAPON,CHANF_OVERLAP);
A_Parry(9);
}
XZW7 WX 1;
XZW7 Y 1 A_Melee();
XZW7 Z 2;
XZW8 ABCDE 2;
XZW8 F 1 A_JumpIf(player.cmd.buttons&BT_USER1,"User1Hold");
XZW2 B 0 { invoker.PlayUpSound(self); }
Goto Select;
Zoom1:
XZW2 A 2 A_StartSound("explodium/checkout",CHAN_WEAPON,CHANF_OVERLAP);
XZW8 GHIJKLMNOPQRSTUVWXYZ 2;
Goto Ready;
Zoom2:
XZW2 A 1 A_StartSound("explodium/speen",CHAN_WEAPON,CHANF_OVERLAP);
XZW9 ABCDEFGHIJKLMNOPQRSTUVW 1;
Goto Ready;
Deselect:
XZW2 A 2 A_StartSound("explodium/deselect",CHAN_WEAPON,CHANF_OVERLAP);
XZWA TUVW 2;
XZW2 B 2;
XZW2 B -1 A_FullLower();
Stop;
Flash:
XZWZ A 2
{
let psp = player.GetPSprite(PSP_FLASH);
psp.frame = Random[GunFlash](0,9);
let l = Spawn("SWWMWeaponLight",pos);
l.target = self;
}
Stop;
}
}
// TODO Dual Explodium Guns (eventually)
/*
Class DualExplodiumGun : ExplodiumGun
{
override bool CheckAmmo( int firemode, bool autoswitch, bool requireammo, int ammocount )
{
if ( (firemode == PrimaryFire) || (firemode == AltFire) )
return (SisterWeapon&&(SisterWeapon.Amount > 1));
return Super.CheckAmmo(firemode,autoswitch,requireammo,ammocount);
}
Default
{
Tag "$T_EXPLODIUM2";
Weapon.SisterWeapon "ExplodiumGun";
}
}*/