diff --git a/README.md b/README.md index f13e58bc9..93e5559b1 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/TODO.md b/TODO.md index 32047e8a8..f74035a90 100644 --- a/TODO.md +++ b/TODO.md @@ -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 diff --git a/credits.txt b/credits.txt index 7bbe53cbd..5292aa4b0 100644 --- a/credits.txt +++ b/credits.txt @@ -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. diff --git a/cvarinfo.txt b/cvarinfo.txt index 17bd2b984..06135ec31 100644 --- a/cvarinfo.txt +++ b/cvarinfo.txt @@ -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 \ No newline at end of file diff --git a/language.version b/language.version index 518541455..75b23074a 100644 --- a/language.version +++ b/language.version @@ -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)"; diff --git a/modeldef.candygun b/modeldef.candygun index 274cea452..a05a668af 100644 --- a/modeldef.candygun +++ b/modeldef.candygun @@ -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 diff --git a/modeldef.eviscerator b/modeldef.eviscerator index 5ccbc1735..52b3c383c 100644 --- a/modeldef.eviscerator +++ b/modeldef.eviscerator @@ -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" diff --git a/modeldef.explodiumgun b/modeldef.explodiumgun index a78063a75..9a4970ff5 100644 --- a/modeldef.explodiumgun +++ b/modeldef.explodiumgun @@ -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 diff --git a/modeldef.spreadgun b/modeldef.spreadgun index f5a084892..5cd246859 100644 --- a/modeldef.spreadgun +++ b/modeldef.spreadgun @@ -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 diff --git a/modeldef.wallbuster b/modeldef.wallbuster index b88d95795..8ac9cb3d4 100644 --- a/modeldef.wallbuster +++ b/modeldef.wallbuster @@ -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 diff --git a/models/Wallbuster1st.blend b/models/Wallbuster1st.blend index a4319d378..93f930ca3 100644 Binary files a/models/Wallbuster1st.blend and b/models/Wallbuster1st.blend differ diff --git a/models/Wallbuster1st_a.3d b/models/Wallbuster1st_a.3d index 244685e5f..795c718cc 100644 Binary files a/models/Wallbuster1st_a.3d and b/models/Wallbuster1st_a.3d differ diff --git a/models/Wallbuster1st_d.3d b/models/Wallbuster1st_d.3d index b6b71fce7..7fdbb9862 100644 Binary files a/models/Wallbuster1st_d.3d and b/models/Wallbuster1st_d.3d differ diff --git a/models/extra/DebugFlat.png b/models/extra/DebugFlat.png new file mode 100644 index 000000000..8c0adfebf Binary files /dev/null and b/models/extra/DebugFlat.png differ diff --git a/sndinfo.txt b/sndinfo.txt index dedacbb0c..c0f75dd46 100644 --- a/sndinfo.txt +++ b/sndinfo.txt @@ -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 diff --git a/sounds/wallbuster/cbt_cbt.ogg b/sounds/wallbuster/cbt_cbt.ogg new file mode 100644 index 000000000..b98b10e3c Binary files /dev/null and b/sounds/wallbuster/cbt_cbt.ogg differ diff --git a/sounds/wallbuster/cbt_load.ogg b/sounds/wallbuster/cbt_load.ogg index 61585abe9..d199dadef 100644 Binary files a/sounds/wallbuster/cbt_load.ogg and b/sounds/wallbuster/cbt_load.ogg differ diff --git a/sounds/wallbuster/cbt_olddays.ogg b/sounds/wallbuster/cbt_olddays.ogg new file mode 100644 index 000000000..c6921aec7 Binary files /dev/null and b/sounds/wallbuster/cbt_olddays.ogg differ diff --git a/zmapinfo.txt b/zmapinfo.txt index 505e48ca5..fd2bfaaf9 100644 --- a/zmapinfo.txt +++ b/zmapinfo.txt @@ -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" diff --git a/zscript/swwm_cbt.zsc b/zscript/swwm_cbt.zsc index 047cbd82f..05c7a3d4d 100644 --- a/zscript/swwm_cbt.zsc +++ b/zscript/swwm_cbt.zsc @@ -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 loaded[25]; @@ -319,7 +362,11 @@ Class Wallbuster : SWWMWeapon Array > 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 impact = "SpreadImpact", int bc = 1, bool large = false ) + { + // TODO wall busting + for ( int i=0; i 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 types[] = {"RedShell","GreenShell","BlueShell","PurpleShell"}; + static const Class casetypes[] = {"RedShellCasing","GreenShellCasing","BlueShellCasing","PurpleShellCasing"}; + for ( int i=0; i<5; i++ ) + { + Class 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 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: diff --git a/zscript/swwm_shot.zsc b/zscript/swwm_shot.zsc index cb7e378b0..73d3b554e 100644 --- a/zscript/swwm_shot.zsc +++ b/zscript/swwm_shot.zsc @@ -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