Many of these practices carry significant health risks.

This commit is contained in:
Mari the Deer 2020-06-03 01:26:34 +02:00
commit 4bc05fed38
21 changed files with 776 additions and 65 deletions

View file

@ -179,7 +179,8 @@ better as a list:
you can take your time, but in coop you better have someone to cover you
while you micromanage this beast.
- While loading shells, you can cancel by holding the reload button.
- For a skilled combat robot like you, reloading this should be very fast.
- For a skilled combat robot like you, reloading this should be very fast. 10
seconds tops, for all 25 barrels.
People like to nickname it the "Ballbuster". You'll see why.

View file

@ -1,11 +1,12 @@
Fundamental things:
- Wallbuster
- Wallbuster breaching feature
- Silver Bullet
- Ynykron
Not so fundamental things:
- Chanceboxes
- Extra Demolitionist animations (swim, weapon melee/reload/idle)
- Adjust Demolitionist crouch height to match anims
Extra things:
- Art for custom intermission

View file

@ -32,3 +32,4 @@ Most of the work here is original, but there are some notable exceptions:
- Intermission fanart:
* Substance20 (@S20TBL)
* Captain J (@Jho7835)
- A certain hidden easter egg / meme uses crappified/bassboosted edits of Old Days and the CBT Wikipedia article.

View file

@ -53,4 +53,5 @@ user int swwm_numscale = 0; // damnum scaling (0 = use GZDoom scaling)
server bool swwm_blood = false; // custom blood/gibbing
user bool swwm_fuzz = true; // allows toggling the fuzz shader on the demolitionist menus, useful if you're streaming/recording since it destroys the encoding quality
user bool swwm_cbtpause = true; // wallbuster menu pauses the game
user noarchive int swwm_cbtmeme = 0; // easter egg, hidden cvar
user noarchive bool swwm_cbttime = false; // debug: times how long a reload takes

View file

@ -1,2 +1,2 @@
[default]
SWWM_MODVER="\cxSWWM GZ\c- r278 (Sat 30 May 22:29:59 CEST 2020)";
SWWM_MODVER="\cxSWWM GZ\c- r279 (Wed 3 Jun 01:26:34 CEST 2020)";

View file

@ -114,7 +114,8 @@ Model "CandyGun"
Model 2 "Flat_d.3d"
Scale 0.15 0.15 0.15
Offset 16 -60 -12
PitchOffset 90
RollOffset 90
AngleOffset 90
Skin 2 "CandyMuz0.png"
FrameIndex XZWZ A 2 0

View file

@ -44,7 +44,8 @@ Model "Eviscerator"
Model 2 "Flat_d.3d"
Offset 18 -60 -22
PitchOffset 90
RollOffset 90
AngleOffset 90
Scale 0.3 0.3 0.3
Skin 2 "EvisceratorMuz0.png"

View file

@ -71,7 +71,8 @@ Model "ExplodiumGun"
Model 2 "Flat_d.3d"
Scale 0.1 0.1 0.1
Offset 16 -60 -12
PitchOffset 90
RollOffset 90
AngleOffset 90
Skin 2 "ExploMuz0.png"
FrameIndex XZWZ A 2 0

View file

@ -174,7 +174,8 @@ Model "Spreadgun"
Model 2 "Flat_d.3d"
Offset 16 -60 -15
PitchOffset 90
RollOffset 90
AngleOffset 90
// buckshot
Scale 0.13 0.13 0.13

View file

@ -18,46 +18,225 @@ Model "Wallbuster"
Path "models/extra"
Model 3 "Flat_d.3d"
PitchOffset 90
RollOffset 90
AngleOffset 90
// Base 12 -60 -24
// Radius1 10
// Radius2 3
// Buckshot
Scale 0.13 0.13 0.13
Skin 3 "ShotgMuz.png"
Offset 16 -60 -16
Offset 12 -60 -11
FrameIndex XZWW A 3 0
Offset 14.8532 -60 -13.0729
FrameIndex XZWW B 3 0
Offset 13.7634 -60 -16.4271
FrameIndex XZWW C 3 0
Offset 10.2366 -60 -16.4271
FrameIndex XZWW D 3 0
Offset 9.14683 -60 -13.0729
FrameIndex XZWW E 3 0
Offset 24.3637 -60 -19.9828
FrameIndex XZWW F 3 0
Offset 23.2739 -60 -23.3369
FrameIndex XZWW G 3 0
Offset 19.7472 -60 -23.3369
FrameIndex XZWW H 3 0
Offset 18.6574 -60 -19.9828
FrameIndex XZWW I 3 0
Offset 21.5106 -60 -17.9098
FrameIndex XZWW J 3 0
Offset 19.6412 -60 -34.5172
FrameIndex XZWW K 3 0
Offset 16.1145 -60 -34.5172
FrameIndex XZWW L 3 0
Offset 15.0247 -60 -31.1631
FrameIndex XZWW M 3 0
Offset 17.8779 -60 -29.0902
FrameIndex XZWW N 3 0
Offset 20.731 -60 -31.1631
FrameIndex XZWW O 3 0
Offset 4.35879 -60 -34.5172
FrameIndex XZWW P 3 0
Offset 3.26898 -60 -31.1631
FrameIndex XZWW Q 3 0
Offset 6.12215 -60 -29.0902
FrameIndex XZWW R 3 0
Offset 8.97532 -60 -31.1631
FrameIndex XZWW S 3 0
Offset 7.8855 -60 -34.5172
FrameIndex XZWW T 3 0
Offset -0.363735 -60 -19.9828
FrameIndex XZWW U 3 0
Offset 2.48943 -60 -17.9098
FrameIndex XZWW V 3 0
Offset 5.3426 -60 -19.9828
FrameIndex XZWW W 3 0
Offset 4.25279 -60 -23.3369
FrameIndex XZWW X 3 0
Offset 0.726079 -60 -23.3369
FrameIndex XZWW Y 3 0
// Slug
Scale 0.08 0.08 0.08
Skin 3 "ShotgMuz.png"
Offset 12 -60 -11
FrameIndex XZWX A 3 0
Offset 14.8532 -60 -13.0729
FrameIndex XZWX B 3 0
Offset 13.7634 -60 -16.4271
FrameIndex XZWX C 3 0
Offset 10.2366 -60 -16.4271
FrameIndex XZWX D 3 0
Offset 9.14683 -60 -13.0729
FrameIndex XZWX E 3 0
Offset 24.3637 -60 -19.9828
FrameIndex XZWX F 3 0
Offset 23.2739 -60 -23.3369
FrameIndex XZWX G 3 0
Offset 19.7472 -60 -23.3369
FrameIndex XZWX H 3 0
Offset 18.6574 -60 -19.9828
FrameIndex XZWX I 3 0
Offset 21.5106 -60 -17.9098
FrameIndex XZWX J 3 0
Offset 19.6412 -60 -34.5172
FrameIndex XZWX K 3 0
Offset 16.1145 -60 -34.5172
FrameIndex XZWX L 3 0
Offset 15.0247 -60 -31.1631
FrameIndex XZWX M 3 0
Offset 17.8779 -60 -29.0902
FrameIndex XZWX N 3 0
Offset 20.731 -60 -31.1631
FrameIndex XZWX O 3 0
Offset 4.35879 -60 -34.5172
FrameIndex XZWX P 3 0
Offset 3.26898 -60 -31.1631
FrameIndex XZWX Q 3 0
Offset 6.12215 -60 -29.0902
FrameIndex XZWX R 3 0
Offset 8.97532 -60 -31.1631
FrameIndex XZWX S 3 0
Offset 7.8855 -60 -34.5172
FrameIndex XZWX T 3 0
Offset -0.363735 -60 -19.9828
FrameIndex XZWX U 3 0
Offset 2.48943 -60 -17.9098
FrameIndex XZWX V 3 0
Offset 5.3426 -60 -19.9828
FrameIndex XZWX W 3 0
Offset 4.25279 -60 -23.3369
FrameIndex XZWX X 3 0
Offset 0.726079 -60 -23.3369
FrameIndex XZWX Y 3 0
// Kinylum
Scale 0.13 0.13 0.13
Skin 2 "ShotgMuzSalt.png"
Skin 3 "ShotgMuzSalt.png"
Offset 12 -60 -11
FrameIndex XZWY A 3 0
Offset 14.8532 -60 -13.0729
FrameIndex XZWY B 3 0
Offset 13.7634 -60 -16.4271
FrameIndex XZWY C 3 0
Offset 10.2366 -60 -16.4271
FrameIndex XZWY D 3 0
Offset 9.14683 -60 -13.0729
FrameIndex XZWY E 3 0
Offset 24.3637 -60 -19.9828
FrameIndex XZWY F 3 0
Offset 23.2739 -60 -23.3369
FrameIndex XZWY G 3 0
Offset 19.7472 -60 -23.3369
FrameIndex XZWY H 3 0
Offset 18.6574 -60 -19.9828
FrameIndex XZWY I 3 0
Offset 21.5106 -60 -17.9098
FrameIndex XZWY J 3 0
Offset 19.6412 -60 -34.5172
FrameIndex XZWY K 3 0
Offset 16.1145 -60 -34.5172
FrameIndex XZWY L 3 0
Offset 15.0247 -60 -31.1631
FrameIndex XZWY M 3 0
Offset 17.8779 -60 -29.0902
FrameIndex XZWY N 3 0
Offset 20.731 -60 -31.1631
FrameIndex XZWY O 3 0
Offset 4.35879 -60 -34.5172
FrameIndex XZWY P 3 0
Offset 3.26898 -60 -31.1631
FrameIndex XZWY Q 3 0
Offset 6.12215 -60 -29.0902
FrameIndex XZWY R 3 0
Offset 8.97532 -60 -31.1631
FrameIndex XZWY S 3 0
Offset 7.8855 -60 -34.5172
FrameIndex XZWY T 3 0
Offset -0.363735 -60 -19.9828
FrameIndex XZWY U 3 0
Offset 2.48943 -60 -17.9098
FrameIndex XZWY V 3 0
Offset 5.3426 -60 -19.9828
FrameIndex XZWY W 3 0
Offset 4.25279 -60 -23.3369
FrameIndex XZWY X 3 0
Offset 0.726079 -60 -23.3369
FrameIndex XZWY Y 3 0
// Ball
Scale 0.06 0.06 0.06
Skin 2 "ShotgMuz.png"
Skin 3 "ShotgMuz.png"
Offset 12 -60 -11
FrameIndex XZWZ A 3 0
Offset 14.8532 -60 -13.0729
FrameIndex XZWZ B 3 0
Offset 13.7634 -60 -16.4271
FrameIndex XZWZ C 3 0
Offset 10.2366 -60 -16.4271
FrameIndex XZWZ D 3 0
Offset 9.14683 -60 -13.0729
FrameIndex XZWZ E 3 0
Offset 24.3637 -60 -19.9828
FrameIndex XZWZ F 3 0
Offset 23.2739 -60 -23.3369
FrameIndex XZWZ G 3 0
Offset 19.7472 -60 -23.3369
FrameIndex XZWZ H 3 0
Offset 18.6574 -60 -19.9828
FrameIndex XZWZ I 3 0
Offset 21.5106 -60 -17.9098
FrameIndex XZWZ J 3 0
Offset 19.6412 -60 -34.5172
FrameIndex XZWZ K 3 0
Offset 16.1145 -60 -34.5172
FrameIndex XZWZ L 3 0
Offset 15.0247 -60 -31.1631
FrameIndex XZWZ M 3 0
Offset 17.8779 -60 -29.0902
FrameIndex XZWZ N 3 0
Offset 20.731 -60 -31.1631
FrameIndex XZWZ O 3 0
Offset 4.35879 -60 -34.5172
FrameIndex XZWZ P 3 0
Offset 3.26898 -60 -31.1631
FrameIndex XZWZ Q 3 0
Offset 6.12215 -60 -29.0902
FrameIndex XZWZ R 3 0
Offset 8.97532 -60 -31.1631
FrameIndex XZWZ S 3 0
Offset 7.8855 -60 -34.5172
FrameIndex XZWZ T 3 0
Offset -0.363735 -60 -19.9828
FrameIndex XZWZ U 3 0
Offset 2.48943 -60 -17.9098
FrameIndex XZWZ V 3 0
Offset 5.3426 -60 -19.9828
FrameIndex XZWZ W 3 0
Offset 4.25279 -60 -23.3369
FrameIndex XZWZ X 3 0
Offset 0.726079 -60 -23.3369
FrameIndex XZWZ Y 3 0
}
Model "Wallbuster"
@ -67,11 +246,12 @@ Model "Wallbuster"
Model 2 "Wallbuster1st_d.3d"
AngleOffset -93
PitchOffset 0.4
Offset 0 2 0
Scale -0.005 0.0025 0.005
//// Shell0
SurfaceSkin 2 5 "Shell_Normal.png"
SurfaceSkin 2 4 "Shell_Normal.png"
// Detach
FrameIndex XZWA E 2 91
FrameIndex XZWA F 2 92
@ -99,8 +279,8 @@ Model "Wallbuster"
FrameIndex XZWB A 2 128
FrameIndex XZWB B 2 129
//// Shell1
SurfaceSkin 2 5 ""
SurfaceSkin 2 6 "Shell_Normal.png"
SurfaceSkin 2 4 ""
SurfaceSkin 2 5 "Shell_Normal.png"
// Detach
FrameIndex XZWB C 2 91
FrameIndex XZWB D 2 92
@ -128,8 +308,8 @@ Model "Wallbuster"
FrameIndex XZWB Y 2 128
FrameIndex XZWB Z 2 129
//// Shell2
SurfaceSkin 2 6 ""
SurfaceSkin 2 7 "Shell_Normal.png"
SurfaceSkin 2 5 ""
SurfaceSkin 2 6 "Shell_Normal.png"
// Detach
FrameIndex XZWC A 2 91
FrameIndex XZWC B 2 92
@ -157,8 +337,8 @@ Model "Wallbuster"
FrameIndex XZWC W 2 128
FrameIndex XZWC X 2 129
//// Shell3
SurfaceSkin 2 7 ""
SurfaceSkin 2 8 "Shell_Normal.png"
SurfaceSkin 2 6 ""
SurfaceSkin 2 7 "Shell_Normal.png"
// Detach
FrameIndex XZWC Y 2 91
FrameIndex XZWC Z 2 92
@ -186,8 +366,8 @@ Model "Wallbuster"
FrameIndex XZWD U 2 128
FrameIndex XZWD V 2 129
//// Shell4
SurfaceSkin 2 8 ""
SurfaceSkin 2 9 "Shell_Normal.png"
SurfaceSkin 2 7 ""
SurfaceSkin 2 8 "Shell_Normal.png"
// Detach
FrameIndex XZWD W 2 91
FrameIndex XZWD X 2 92
@ -214,6 +394,8 @@ Model "Wallbuster"
FrameIndex XZWE R 2 127
FrameIndex XZWE S 2 128
FrameIndex XZWE T 2 129
// TODO difference between spent/unspent if I actually
// decide to make the textures visually different
}
Model "Wallbuster"
@ -227,6 +409,7 @@ Model "Wallbuster"
SurfaceSkin 1 2 "DemoSoft.png"
SurfaceSkin 1 3 "Wallbuster.png"
AngleOffset -93
PitchOffset 0.4
Offset 0 2 0
Scale -0.005 0.0025 0.005
@ -312,7 +495,7 @@ Model "Wallbuster"
FrameIndex XZW4 U 1 78
FrameIndex XZW4 V 1 79
FrameIndex XZW4 W 1 80 // StillFrm
// Detach
// PreDetach
FrameIndex XZW4 X 1 81
FrameIndex XZW4 Y 1 82
FrameIndex XZW4 Z 1 83
@ -323,6 +506,7 @@ Model "Wallbuster"
FrameIndex XZW5 E 1 88
FrameIndex XZW5 F 1 89
FrameIndex XZW5 G 1 90 // DetachSnd
// Detach
FrameIndex XZW5 H 1 91 // StartDetachOverlays
FrameIndex XZW5 I 1 92
FrameIndex XZW5 J 1 93
@ -408,9 +592,9 @@ Model "Wallbuster"
FrameIndex XZW8 J 1 171
FrameIndex XZW8 K 1 172
FrameIndex XZW8 L 1 173
FrameIndex XZW8 M 1 174 // DetachSnd
FrameIndex XZW8 N 1 175 // duplicate of frame 91, but with spin applied
// Lock
FrameIndex XZW8 M 1 174 // StillFrm
FrameIndex XZW8 N 1 175
FrameIndex XZW8 O 1 176
FrameIndex XZW8 P 1 177
FrameIndex XZW8 Q 1 178

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
models/extra/DebugFlat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

View file

@ -585,6 +585,8 @@ wallbuster/load2 sounds/wallbuster/cbt_shellin2.ogg
wallbuster/load3 sounds/wallbuster/cbt_shellin3.ogg
wallbuster/load4 sounds/wallbuster/cbt_shellin4.ogg
$random wallbuster/load { wallbuster/load1 wallbuster/load2 wallbuster/load3 wallbuster/load4 }
wallbuster/cbt sounds/wallbuster/cbt_cbt.ogg
wallbuster/olddays sounds/wallbuster/cbt_olddays.ogg
eviscerator/select sounds/eviscerator/visc_select.ogg
eviscerator/deselect sounds/eviscerator/visc_deselect.ogg

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,6 +1,6 @@
GameInfo
{
AddEventHandlers = "SWWMCrashHandler", "SWWMBrutalHandler", "SWWMHDoomHandler", "SWWMVanillaBossHandler", "SWWMHandler", "SWWMGoreHandler"
AddEventHandlers = "SWWMCrashHandler", "SWWMBrutalHandler", "SWWMHDoomHandler", "SWWMVanillaBossHandler", "SWWMHandler", "SWWMGoreHandler", "CBTHandler"
PlayerClasses = "Demolitionist"
StatusBarClass = "SWWMStatusBar"
BackpackType = "HammerspaceEmbiggener"
@ -30,6 +30,9 @@ GameInfo
"SilverBullet",
"CandyGun",
"YnykronArtifact"
// make easter egg not stutter
PrecacheSounds = "wallbuster/olddays",
"wallbuster/cbt"
}
Map TITLEMAP "SWWM GZ - Title Map"

View file

@ -182,7 +182,7 @@ Class WallbusterReloadMenu : GenericMenu
override bool MouseEvent( int type, int mx, int my )
{
bool res = Super.MouseEvent(type,mx,my);
// TODO
// TODO mouse input?
return res;
}
@ -310,6 +310,49 @@ Class WallbusterReloadMenu : GenericMenu
}
}
Class CBTHandler : StaticEventHandler
{
bool initme;
double cbtvol;
transient CVar cbtme;
override void WorldTick()
{
if ( !cbtme ) cbtme = CVar.GetCVar('swwm_cbtmeme',players[consoleplayer]);
if ( !players[consoleplayer].mo ) return;
let cbt = players[consoleplayer].mo.FindInventory("Wallbuster");
if ( !cbt ) return;
if ( cbt == players[consoleplayer].ReadyWeapon )
{
if ( !initme && (cbtme.GetInt() > 0) )
{
initme = true;
cbtvol = 1.;
}
cbtvol = min(1.,cbtvol+.2);
if ( (cbtme.GetInt() >= 1) && !cbt.IsActorPlayingSound(CHAN_AMBEXTRA+1) )
cbt.A_StartSound("wallbuster/olddays",CHAN_AMBEXTRA+1,CHANF_UI|CHANF_LOOPING,cbtvol,0.);
else if ( (cbtme.GetInt() < 1) && cbt.IsActorPlayingSound(CHAN_AMBEXTRA+1) )
cbt.A_StopSound(CHAN_AMBEXTRA+1);
if ( (cbtme.GetInt() >= 2) && !cbt.IsActorPlayingSound(CHAN_AMBEXTRA+2) )
{
// restart the music
if ( cbt.IsActorPlayingSound(CHAN_AMBEXTRA+1) )
{
cbt.A_StopSound(CHAN_AMBEXTRA+1);
cbt.A_StartSound("wallbuster/olddays",CHAN_AMBEXTRA+1,CHANF_UI|CHANF_LOOPING,cbtvol,0.);
}
cbt.A_StartSound("wallbuster/cbt",CHAN_AMBEXTRA+2,CHANF_UI|CHANF_LOOPING,cbtvol,0.);
}
else if ( (cbtme.GetInt() < 2) && cbt.IsActorPlayingSound(CHAN_AMBEXTRA+2) )
cbt.A_StopSound(CHAN_AMBEXTRA+2);
}
else cbtvol = max(0.,cbtvol-.2);
cbt.A_SoundVolume(CHAN_AMBEXTRA+1,cbtvol);
cbt.A_SoundVolume(CHAN_AMBEXTRA+2,cbtvol);
}
}
Class Wallbuster : SWWMWeapon
{
Class<Ammo> loaded[25];
@ -319,7 +362,11 @@ Class Wallbuster : SWWMWeapon
Array<Class<Ammo> > reloadqueue;
transient bool waitreload;
int whichspin;
transient CVar cbtmuffler;
transient CVar cbtmuffler, timeme;
bool timing;
int reloadtime[2];
transient bool cancelreload;
double srecoil;
transient ui TextureID WeaponBox, AmmoIcon[4], LoadIcon[4], UsedIcon[4], EmptyIcon;
transient ui Font TewiFont;
@ -477,9 +524,74 @@ Class Wallbuster : SWWMWeapon
flashstate = weap.FindState('Flash');
}
else flashstate = weap.FindState(flashlabel);
player.SetPSprite(PSP_FLASH,flashstate+index);
A_OverlayFlags(PSP_FLASH,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
A_OverlayRenderStyle(PSP_FLASH,STYLE_Add);
player.SetPSprite(PSP_FLASH-index,flashstate+index);
A_OverlayFlags(PSP_FLASH-index,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
A_OverlayRenderStyle(PSP_FLASH-index,STYLE_Add);
}
action void ProcessTraceHit( SpreadgunTracer t, Vector3 origin, Vector3 dir, int dmg, double mm, Class<Actor> impact = "SpreadImpact", int bc = 1, bool large = false )
{
// TODO wall busting
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(large?"InvisibleSplasher":"SmolInvisibleSplasher",t.WaterHitList[i].hitpos);
b.A_CheckTerrain();
}
for ( int i=5; i<t.Results.Distance; i+=10 )
{
if ( !Random[Boolet](0,bc) ) continue;
let b = Actor.Spawn("SWWMBubble",level.Vec3Offset(origin,dir*i));
b.Scale *= FRandom[Boolet](.1,.3);
}
for ( int i=0; i<t.HitList.Size(); i++ )
{
int realdmg = dmg?dmg:t.HitList[i].HitDamage;
SWWMDamageAccumulator.Accumulate(t.HitList[i].HitActor,realdmg,invoker,self,'shot',!large);
SWWMHandler.DoKnockback(t.HitList[i].HitActor,t.HitList[i].x+(0,0,0.025),mm*FRandom[Wallbuster](0.4,1.2));
if ( t.HitList[i].HitActor.bNOBLOOD || t.HitList[i].HitActor.bINVULNERABLE )
{
let p = Spawn(impact,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);
p.special1 = max(0,(bc-5)/4);
}
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);
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 ( (t.Results.HitType != TRACE_HitNone) && (t.Results.HitType != TRACE_HasHitSky) )
{
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;
}
if ( t.Results.HitLine ) t.Results.HitLine.RemoteActivate(self,t.Results.Side,SPAC_Impact,t.Results.HitPos);
let p = Spawn(impact,t.Results.HitPos+hitnormal*4);
p.angle = atan2(hitnormal.y,hitnormal.x);
p.pitch = asin(-hitnormal.z);
p.special1 = max(0,(bc-5)/4);
}
}
action void A_FireShells( int num = 1 )
{
@ -497,6 +609,7 @@ Class Wallbuster : SWWMWeapon
int howmany = 0;
for ( int i=0; i<num; i++ )
{
// get physical index
int idx = i;
// shift based on full rotation
idx = (idx+invoker.rotation[5]*5);
@ -516,13 +629,15 @@ Class Wallbuster : SWWMWeapon
player.SetPsprite(PSP_WEAPON,ResolveState("DryFire"));
return;
}
Console.Printf("\cgFIRING NOT FULLY IMPLEMENTED\c-");
Vector3 x, y, z;
Vector3 x, y, z, origin, x2, y2, z2, dir;
double a, s;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
[x2, y2, z2] = swwm_CoordUtil.GetAxes(BulletSlope(),angle,roll);
if ( !invoker.cbtmuffler ) invoker.cbtmuffler = CVar.GetCVar('swwm_earbuster',players[consoleplayer]);
// second pass, actually fire them
// second pass, play the fire effects
for ( int i=0; i<num; i++ )
{
// get physical index
int idx = i;
// shift based on full rotation
idx = (idx+invoker.rotation[5]*5);
@ -541,13 +656,13 @@ Class Wallbuster : SWWMWeapon
which = j;
break;
}
double rfact = invoker.cbtmuffler.GetBool()?.85:.65;
double rfact = invoker.cbtmuffler.GetBool()?.85:.6;
A_StartSound(sounds[which],CHAN_WEAPON,CHANF_OVERLAP,1./(howmany**rfact),.6-howmany*.004,1.-howmany*.012);
if ( which == 0 ) redflashstr = max(120,redflashstr+10);
else if ( which == 1 ) redflashstr = max(90,redflashstr+8);
else if ( which == 2 ) blueflashstr = max(160,blueflashstr+10);
else if ( which == 3 ) redflashstr = max(60,redflashstr+6);
invoker.fired[idx] = true;
A_CBTFlash(flashes[which],i);
}
if ( howmany < 3 ) player.SetPsprite(PSP_WEAPON,ResolveState("FireOne"));
else if ( howmany < 15 ) player.SetPsprite(PSP_WEAPON,ResolveState("FireFive"));
@ -572,6 +687,204 @@ Class Wallbuster : SWWMWeapon
l.args[3] = blueflashstr;
l.target = self;
}
// third pass, actually fire them
A_Overlay(-9999,"InvRecoil");
invoker.srecoil = 0.;
Vector3 base = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+8*y-10*z);
SpreadgunTracer st;
SpreadSlugTracer sst;
for ( int i=0; i<num; i++ )
{
// get physical index
int idx = i;
// shift based on full rotation
idx = (idx+invoker.rotation[5]*5);
while ( idx > 24 ) idx -= 25;
int group = idx/5;
// shift based on group rotation
int gidx = i%5;
gidx = (gidx+invoker.rotation[group]);
while ( gidx > 4 ) gidx -= 5;
idx = gidx+group*5;
if ( !invoker.loaded[idx] || invoker.fired[idx] ) continue;
int which = 0;
for ( int j=0; j<4; j++ )
{
if ( !(invoker.loaded[idx] is types[j]) ) continue;
which = j;
break;
}
invoker.fired[idx] = true;
double t1 = int(i%5)*72+90;
double t2 = int(i/5)*72+90;
Vector2 b = (cos(t1),sin(t1))*2;
b.y += 8;
Vector2 n = (b.x*cos(t2)-b.y*sin(t2),b.x*sin(t2)+b.y*cos(t2));
origin = level.Vec3Offset(base,n.x*y+n.y*z);
switch ( which )
{
case 1:
// slug
if ( !sst ) sst = new("SpreadSlugTracer");
sst.ignoreme = self;
sst.penetration = 250.;
a = FRandom[Wallbuster](0,360);
s = FRandom[Wallbuster](0,.002);
dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
sst.hitlist.Clear();
sst.shootthroughlist.Clear();
sst.waterhitlist.Clear();
sst.Trace(origin,level.PointInSector(origin.xy),dir,8000.,TRACE_HitSky);
ProcessTraceHit(sst,origin,dir,0,12000,"SlugImpact",1+howmany/8,true);
for ( int i=0; i<(3-howmany/10); i++ )
{
let s = Spawn("SWWMViewSmoke",origin);
SWWMViewSmoke(s).ofs = (15,3,-3);
s.target = self;
s.SetShade(Color(1,1,1)*Random[Wallbuster](96,192));
s.alpha *= 0.5;
}
for ( int i=0; i<(6-howmany/4); i++ )
{
let s = Spawn("SWWMSmoke",origin);
s.scale *= .8;
s.alpha *= .3;
s.SetShade(Color(1,1,1)*Random[Wallbuster](96,192));
s.vel += vel*.5+x*FRandom[Wallbuster](3.,5.);
}
for ( int i=0; i<(10-howmany/3); i++ )
{
let s = Spawn("SWWMSpark",origin);
s.scale *= .2;
s.alpha *= .4;
s.vel += vel*.5+x*FRandom[Wallbuster](4.,8.)+y*FRandom[Wallbuster](-1,1)+z*FRandom[Wallbuster](-1,1);
}
SWWMHandler.DoKnockback(self,-x,6000.);
A_Recoil(2.);
invoker.srecoil += -.8;
break;
case 2:
// saltshot
for ( int j=0; j<(8-howmany/5); j++ )
{
a = FRandom[Wallbuster](0,360);
s = FRandom[Wallbuster](0,.3);
let b = Spawn("SaltBeam",level.Vec3Offset(origin,y*cos(a)*s+z*sin(a)*s));
b.target = self;
b.angle = atan2(x2.y,x2.x);
b.pitch = asin(-x2.z);
b.Stamina += howmany*16;
}
for ( int i=0; i<(9-howmany/3); i++ )
{
let s = Spawn("SWWMViewSmoke",origin);
SWWMViewSmoke(s).ofs = (15,3,-3);
s.target = self;
s.SetShade(Color(1,3,4)*Random[Wallbuster](32,63));
s.A_SetRenderStyle(.2,STYLE_AddShaded);
}
for ( int i=0; i<(16-howmany/2); i++ )
{
let s = Spawn("SWWMSmoke",origin);
s.special1 = 1;
s.scale *= .9;
s.SetShade(Color(1,3,4)*Random[Wallbuster](32,63));
s.A_SetRenderStyle(.3,STYLE_AddShaded);
s.vel += vel*.5+x*FRandom[Wallbuster](3.,5.)+y*FRandom[Wallbuster](-1,1)+z*FRandom[Wallbuster](-1,1);
}
for ( int i=0; i<(20-howmany/2); i++ )
{
let s = Spawn("SWWMSpark",origin);
s.scale *= .3;
s.alpha *= .4;
s.vel += vel*.5+x*FRandom[Wallbuster](4.,8.)+y*FRandom[Wallbuster](-2,2)+z*FRandom[Wallbuster](-2,2);
}
SWWMHandler.DoKnockback(self,-x,4000.);
A_Recoil(1.4);
invoker.srecoil += -.5;
break;
case 3:
// lead ball
a = FRandom[Wallbuster](0,360);
s = FRandom[Wallbuster](0,.006);
dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
let p = Spawn("TheBall",origin);
p.target = self;
p.angle = atan2(dir.y,dir.x);
p.pitch = asin(-dir.z);
p.vel = dir*p.speed;
for ( int i=0; i<(4-howmany/8); i++ )
{
let s = Spawn("SWWMViewSmoke",origin);
SWWMViewSmoke(s).ofs = (15,3,-3);
s.target = self;
s.SetShade(Color(1,1,1)*Random[Wallbuster](96,192));
s.alpha *= 0.4;
}
for ( int i=0; i<(8-howmany/4); i++ )
{
let s = Spawn("SWWMSmoke",origin);
s.scale *= .6;
s.alpha *= .25;
s.SetShade(Color(1,1,1)*Random[Wallbuster](96,192));
s.vel += vel*.5+x*FRandom[Wallbuster](3.,5.);
}
for ( int i=0; i<(8-howmany/4); i++ )
{
let s = Spawn("SWWMSpark",origin);
s.scale *= .2;
s.alpha *= .4;
s.vel += vel*.5+x*FRandom[Wallbuster](4.,8.)+y*FRandom[Wallbuster](-1,1)+z*FRandom[Wallbuster](-1,1);
}
SWWMHandler.DoKnockback(self,-x,2500.);
A_Recoil(1.);
invoker.srecoil += -.35;
break;
default:
// buckshot
if ( !st ) st = new("SpreadgunTracer");
st.ignoreme = self;
for ( int j=0; j<(30-howmany); j++ )
{
a = FRandom[Wallbuster](0,360);
s = FRandom[Wallbuster](0,.1);
dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
st.hitlist.Clear();
st.shootthroughlist.Clear();
st.waterhitlist.Clear();
st.Trace(origin,level.PointInSector(origin.xy),dir,8000.,TRACE_HitSky);
ProcessTraceHit(st,origin,dir,6,7000,bc:5+howmany/6);
}
for ( int i=0; i<(9-howmany/3); i++ )
{
let s = Spawn("SWWMViewSmoke",origin);
SWWMViewSmoke(s).ofs = (15,3,-3);
s.target = self;
s.SetShade(Color(1,1,1)*Random[Wallbuster](96,192));
s.alpha *= .2;
}
for ( int i=0; i<(16-howmany/2); i++ )
{
let s = Spawn("SWWMSmoke",origin);
s.special1 = 1;
s.scale *= .9;
s.alpha *= .3;
s.SetShade(Color(1,1,1)*Random[Wallbuster](96,192));
s.vel += vel*.5+x*FRandom[Wallbuster](3.,5.)+y*FRandom[Wallbuster](-1,1)+z*FRandom[Wallbuster](-1,1);
}
for ( int i=0; i<(20-howmany/2); i++ )
{
let s = Spawn("SWWMSpark",origin);
s.scale *= .3;
s.alpha *= .4;
s.vel += vel*.5+x*FRandom[Wallbuster](4.,8.)+y*FRandom[Wallbuster](-2,2)+z*FRandom[Wallbuster](-2,2);
}
SWWMHandler.DoKnockback(self,-x,4000.);
A_Recoil(1.4);
invoker.srecoil += -.5;
break;
}
}
}
action void A_SpinOne()
{
@ -604,6 +917,122 @@ Class Wallbuster : SWWMWeapon
if ( invoker.reloadqueue.Size() <= 0 ) player.SetPsprite(PSP_WEAPON,ResolveState("EndReload"));
else player.SetPsprite(PSP_WEAPON,ResolveState("Detach"));
}
action void A_StartDetachOverlays()
{
static const statelabel shells[] = {"DetachShell0","DetachShell1","DetachShell2","DetachShell3","DetachShell4"};
for ( int i=0; i<5; i++ )
{
// get physical index
int idx = i;
// shift based on full rotation
idx = (idx+invoker.rotation[5]*5);
while ( idx > 24 ) idx -= 25;
int group = idx/5;
// shift based on group rotation
int gidx = i%5;
gidx = (gidx+invoker.rotation[group]);
while ( gidx > 4 ) gidx -= 5;
idx = gidx+group*5;
if ( !invoker.loaded[idx] ) continue;
A_Overlay(PSP_WEAPON+1+i,shells[i]);
}
A_StartSound("wallbuster/meleestart",CHAN_WEAPON,CHANF_OVERLAP);
}
action void A_StartAttachOverlays()
{
static const statelabel shells[] = {"AttachShell0","AttachShell1","AttachShell2","AttachShell3","AttachShell4"};
for ( int i=0; i<5; i++ )
{
// get physical index
int idx = i;
// shift based on full rotation
idx = (idx+invoker.rotation[5]*5);
while ( idx > 24 ) idx -= 25;
int group = idx/5;
// shift based on group rotation
int gidx = i%5;
gidx = (gidx+invoker.rotation[group]);
while ( gidx > 4 ) gidx -= 5;
idx = gidx+group*5;
if ( !invoker.loaded[idx] ) continue;
A_Overlay(PSP_WEAPON+1+i,shells[i]);
}
A_StartSound("wallbuster/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
}
action void A_DropShells()
{
static const Class<Ammo> types[] = {"RedShell","GreenShell","BlueShell","PurpleShell"};
static const Class<Actor> casetypes[] = {"RedShellCasing","GreenShellCasing","BlueShellCasing","PurpleShellCasing"};
for ( int i=0; i<5; i++ )
{
Class<Ammo> loaded = invoker.loaded[invoker.rotation[5]*5+i];
int which = -1;
for ( int j=0; j<4; j++ )
{
if ( loaded != types[j] ) continue;
which = j;
break;
}
if ( which != -1 )
{
if ( invoker.fired[invoker.rotation[5]*5+i] )
{
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*z);
let c = Spawn(casetypes[which],origin);
c.angle = angle;
c.pitch = pitch;
c.vel = x*FRandom[Junk](-.2,.2)+y*FRandom[Junk](-.2,.2)-(0,0,FRandom[Junk](2,3));
c.vel += vel*.5;
}
else
{
let amo = FindInventory(types[which]);
if ( !amo )
{
amo = Inventory(Spawn(types[which]));
amo.AttachToOwner(self);
amo.Amount = 0;
}
if ( amo.Amount < amo.MaxAmount ) amo.Amount++;
else if ( !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true) )
Spawn(types[which],Vec3Angle(5,(angle-20)+i*10,height/2));
}
}
invoker.loaded[invoker.rotation[5]*5+i] = null;
invoker.fired[invoker.rotation[5]*5+i] = false;
}
invoker.rotation[invoker.rotation[5]] = 4;
}
action void A_LoadShell()
{
if ( invoker.reloadqueue.Size() <= 0 ) return;
Class<Ammo> toload = invoker.reloadqueue[invoker.reloadqueue.Size()-1];
invoker.reloadqueue.Pop();
invoker.loaded[invoker.rotation[5]*5+invoker.rotation[invoker.rotation[5]]] = toload;
if ( !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true) )
{
let am = FindInventory(toload);
if ( am && (am.Amount > 0) ) am.Amount--;
}
if ( (invoker.reloadqueue.Size() > 0) && (invoker.rotation[invoker.rotation[5]] > 0) )
invoker.rotation[invoker.rotation[5]]--;
A_StartSound("wallbuster/load",CHAN_WEAPON,CHANF_OVERLAP);
}
action void A_StartReloadTiming()
{
invoker.timing = true;
invoker.reloadtime[0] = level.time;
}
action void A_StopReloadTiming()
{
invoker.timing = false;
invoker.reloadtime[1] = level.time;
if ( !invoker.timeme ) invoker.timeme = CVar.GetCVar('swwm_cbttime',players[consoleplayer]);
if ( (player == players[consoleplayer]) && invoker.timeme.GetBool() )
Console.Printf("Total reload time: %gs",(invoker.reloadtime[1]-invoker.reloadtime[0])/35.);
}
Default
{
@ -624,11 +1053,7 @@ Class Wallbuster : SWWMWeapon
XZW1 A -1;
Stop;
Select:
XZW2 G 1
{
A_FullRaise();
Console.Printf("\cgWALLBUSTER NOT FULLY IMPLEMENTED\c-");
}
XZW2 G 1 A_FullRaise();
XZW2 HIJKLMNOP 2;
Goto Ready;
Ready:
@ -651,6 +1076,10 @@ Class Wallbuster : SWWMWeapon
Zoom:
XZW2 A 0 A_FireShells(25);
Goto FireTwentyFive;
InvRecoil:
TNT1 A 3;
TNT1 A 1 A_Recoil(invoker.srecoil);
Stop;
FireOne:
XZW2 AQRSTUVWX 1;
XZW2 A 0
@ -714,16 +1143,97 @@ Class Wallbuster : SWWMWeapon
XZW4 W 1 A_WaitMenu();
Wait;
Detach:
XZW4 W 1
XZW4 W 0
{
Console.Printf("\cgRELOADING NOT IMPLEMENTED\c-");
A_StartReloadTiming();
invoker.cancelreload = false;
A_Overlay(-9999,"CheckCancelReload");
}
Goto EndReload;
XZW4 WXYZ 1;
XZW5 ABCDEF 1;
XZW5 G 1 A_StartSound("wallbuster/detach",CHAN_WEAPON,CHANF_OVERLAP);
DetachHold:
XZW5 H 1 A_StartDetachOverlays();
XZW5 IJKLMNOPQ 1;
XZW5 R 2 A_DropShells();
XZW5 ST 2;
XZW5 V 2 A_LoadShell();
XZW5 X 2 A_LoadShell();
XZW5 Y 2 A_LoadShell();
XZW6 A 2 A_LoadShell();
XZW6 C 2 A_LoadShell();
XZW6 E 0
{
if ( invoker.cancelreload ) invoker.reloadqueue.Clear();
player.SetPSprite(-9999,null);
return A_JumpIf((invoker.reloadqueue.Size()>0),"AttachSpin");
}
Goto Attach;
CheckCancelReload:
TNT1 A 1
{
if ( player.cmd.buttons&BT_RELOAD )
invoker.cancelreload = true;
}
Wait;
DetachShell0:
XZWA EFGHIJKLMN 1;
Stop;
DetachShell1:
XZWB CDEFGHIJKL 1;
Stop;
DetachShell2:
XZWC ABCDEFGHIJ 1;
Stop;
DetachShell3:
XZWC YZ 1;
XZWD ABCDEFGH 1;
Stop;
DetachShell4:
XZWD WXYZ 1;
XZWE ABCDEF 1;
Stop;
Attach:
XZW2 W 1;
XZW6 EF 2;
XZW6 G 1 A_StartAttachOverlays();
XZW6 HIJKL 1;
XZW6 M 1 A_StartSound("wallbuster/attach",CHAN_WEAPON,CHANF_OVERLAP);
XZW6 NOPQ 1;
XZW6 RS 2;
XZW6 TUVWXYZ 1;
XZW7 ABC 1;
Goto EndReload;
AttachSpin:
XZW7 JK 2;
XZW7 L 1 A_StartAttachOverlays();
XZW7 MNOPQR 1;
XZW7 S 1 A_StartSound("wallbuster/attach",CHAN_WEAPON,CHANF_OVERLAP);
XZW7 TUVW 1;
XZW7 XYZ 1;
XZW8 ABC 1;
XZW8 D 2 A_HandSpin();
XZW8 EFGHIJKL 2;
XZW8 M 2 A_StartSound("wallbuster/detach",CHAN_WEAPON,CHANF_OVERLAP);
XZW8 N 0;
Goto DetachHold;
AttachShell0:
XZWA OPQRSTUVWXYZ 1;
XZWB AB 1;
Stop;
AttachShell1:
XZWB MNOPQRSTUVWXYZ 1;
Stop;
AttachShell2:
XZWC KLMNOPQRSTUVWX 1;
Stop;
AttachShell3:
XZWD IJKLMNOPQRSTUV 1;
Stop;
AttachShell4:
XZWE GHIJKLMNOPQRST 1;
Stop;
EndReload:
XZW4 W 2;
XZW4 W 2 A_StopReloadTiming();
XZW8 OPQRS 2;
XZW8 T 1 A_StartSound("wallbuster/lock",CHAN_WEAPON,CHANF_OVERLAP);
XZW8 UVWXY 1;
@ -736,13 +1246,14 @@ Class Wallbuster : SWWMWeapon
A_StartSound("wallbuster/meleestart",CHAN_WEAPON,CHANF_OVERLAP);
A_StartSound("demolitionist/wswing",CHAN_WEAPON,CHANF_OVERLAP);
}
XZW9 GHIJ 2;
XZW9 K 1 A_Parry(9);
XZW9 LMN 1;
XZW9 O 2 A_Melee(70,"demolitionist/whitl");
XZW9 PQRSTU 2;
XZW9 V 2 A_StartSound("wallbuster/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
XZW9 WXYZ 2;
XZW9 GHI 2;
XZW9 J 2 A_Parry(9);
XZW9 KLM 1;
XZW9 N 1 A_Melee(70,"demolitionist/whitl");
XZW9 OPQRS 2;
XZW9 T 2 A_StartSound("wallbuster/meleeend",CHAN_WEAPON,CHANF_OVERLAP);
XZW9 UVW 2;
XZW9 XYZ 1;
XZWA ABCD 2;
Goto Ready;
Deselect:

View file

@ -231,7 +231,7 @@ Class SpreadImpact : Actor
if ( swwm_extraalert ) A_AlertMonsters(200);
A_StartSound("spreadgun/pellet",CHAN_VOICE,CHANF_DEFAULT,.4,4.);
A_SprayDecal("TinyBulletChip",-20);
int numpt = Random[Spreadgun](2,4);
int numpt = Random[Spreadgun](2,4)-special1;
Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
for ( int i=0; i<numpt; i++ )
{
@ -242,14 +242,14 @@ Class SpreadImpact : Actor
s.special1 = Random[Spreadgun](0,1);
s.SetShade(Color(1,1,1)*Random[Spreadgun](96,192));
}
numpt = Random[Spreadgun](-1,3);
numpt = Random[Spreadgun](-1,3)-special1;
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Spreadgun](-1,1),FRandom[Spreadgun](-1,1),FRandom[Spreadgun](-1,1)).unit()*FRandom[Spreadgun](2,8);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[Spreadgun](2,4);
numpt = Random[Spreadgun](2,4)-special1;
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Spreadgun](-1,1),FRandom[Spreadgun](-1,1),FRandom[Spreadgun](-1,1)).unit()*FRandom[Spreadgun](1,4);
@ -277,7 +277,7 @@ Class SlugImpact : Actor
if ( swwm_extraalert ) A_AlertMonsters(500);
A_StartSound("spreadgun/slug",CHAN_VOICE,CHANF_DEFAULT,1.,2.);
A_SprayDecal("BulletChip",-20);
int numpt = Random[Spreadgun](5,10);
int numpt = Random[Spreadgun](5,10)-special1;
Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
for ( int i=0; i<numpt; i++ )
{
@ -288,14 +288,14 @@ Class SlugImpact : Actor
s.special1 = Random[Spreadgun](0,2);
s.SetShade(Color(1,1,1)*Random[Spreadgun](96,192));
}
numpt = Random[Spreadgun](2,5);
numpt = Random[Spreadgun](2,5)-special1;
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Spreadgun](-1,1),FRandom[Spreadgun](-1,1),FRandom[Spreadgun](-1,1)).unit()*FRandom[Spreadgun](2,8);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[Spreadgun](4,8);
numpt = Random[Spreadgun](4,8)-special1;
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Spreadgun](-1,1),FRandom[Spreadgun](-1,1),FRandom[Spreadgun](-1,1)).unit()*FRandom[Spreadgun](2,8);
@ -572,7 +572,7 @@ Class SaltImpact : Actor
A_SprayDecal("ShockMarkSmall",-172);
A_SprayDecal("SaltMark",-172);
Scale *= FRandom[ExploS](0.8,1.1);
int numpt = Random[ExploS](5,9);
int numpt = Random[ExploS](5,9)-special1;
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);
@ -583,14 +583,14 @@ Class SaltImpact : Actor
s.scale *= 2.4;
s.A_SetRenderStyle(.4,STYLE_AddShaded);
}
numpt = Random[ExploS](3,9);
numpt = Random[ExploS](3,9)-special1;
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](3,6);
numpt = Random[ExploS](3,6)-special1;
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);
@ -695,6 +695,7 @@ Class SaltBeam : Actor
i.angle = atan2(norm.y,norm.x);
i.pitch = asin(-norm.z);
i.target = target;
i.special1 = (Stamina-9)/4;
}
return;
}
@ -704,10 +705,11 @@ Class SaltBeam : Actor
i.angle = atan2(x.y,x.x);
i.pitch = asin(-x.z);
i.target = target;
i.special1 = (Stamina-9)/4;
return;
}
// next beam
if ( !(special2%4) && !Random[Spreadgun](0,4) )
if ( !(special2%4) && !Random[Spreadgun](0,Stamina/2) )
Spawn("SaltLight",level.Vec3Offset(pos,x*16));
let next = Spawn("SaltBeam",level.Vec3Offset(pos,x*32));
double a = FRandom[Spreadgun](0,360), s = FRandom[Spreadgun](0,.06);
@ -2262,11 +2264,12 @@ Class Spreadgun : SWWMWeapon
case 5:
a = FRandom[Spreadgun](0,360);
s = FRandom[Spreadgun](0,.03);
dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
let b = Spawn("TheBall",origin);
b.target = self;
b.angle = atan2(x2.y,x2.x);
b.pitch = asin(-x2.z);
b.vel = x2*b.speed;
b.angle = atan2(dir.y,dir.x);
b.pitch = asin(-dir.z);
b.vel = dir*b.speed;
for ( int i=0; i<4; i++ )
{
let s = Spawn("SWWMViewSmoke",origin);