diff --git a/LANGUAGE.de b/LANGUAGE.de index fcdfd45..38dda60 100644 --- a/LANGUAGE.de +++ b/LANGUAGE.de @@ -8,6 +8,11 @@ TAG_SMG = "Machinenpistole"; GOTSMG = "Machinenpistole genommen."; OB_MPSMG = "%o wurde mit Blei aus %ks Machinenpistole vollgepumpt."; +TAG_BLASTER = "TODO: Blaster"; +GOTBLASTER = "TODO: You got a Blaster!"; +OB_MPBLASTER = "TODO: %o got tased by %k's blaster."; + + // Menu RWMENU_DOOMABLOSETTINGS = "DOOMablo anpassen"; RWMENU_CUSTOMIZEDOOMABLO = "DOOMablo Einstellungen"; diff --git a/LANGUAGE.default b/LANGUAGE.default index 88804bd..f4b0b78 100644 --- a/LANGUAGE.default +++ b/LANGUAGE.default @@ -8,6 +8,10 @@ TAG_SMG = "Sub-Machine Gun"; GOTSMG = "You got a Sub-Machine Gun!"; OB_MPSMG = "%o was rattled by %k's little friend."; +TAG_BLASTER = "Blaster"; +GOTBLASTER = "You got a Blaster!"; +OB_MPBLASTER = "%o got tased by %k's blaster."; + // Menu RWMENU_DOOMABLOSETTINGS = "DOOMablo settings"; RWMENU_CUSTOMIZEDOOMABLO = "Customize DOOMablo"; diff --git a/TEXTURES.txt b/TEXTURES.txt new file mode 100644 index 0000000..822af98 --- /dev/null +++ b/TEXTURES.txt @@ -0,0 +1,30 @@ +// Texture definitions generated by SLADE3 +// on Sat May 10 17:08:32 2025 + +Sprite "BLSGA0", 79, 73 +{ + Offset -136, -95 + Patch "sprites/weapons/blaster/breadbagfly-scrapyard-pistols.png", -196, -71 +} + +Sprite "BLSGB0", 79, 82 +{ + Offset -136, -86 + Patch "PLSEA0", 13, 0 + Patch "sprites/weapons/blaster/breadbagfly-scrapyard-pistols.png", -196, -62 +} + +Sprite "BLSGC0", 79, 82 +{ + Offset -136, -86 + Patch "PLSED0", 9, 0 + Patch "sprites/weapons/blaster/breadbagfly-scrapyard-pistols.png", -196, -62 +} + +Sprite "BLASA0", 18, 13 +{ + Offset 9, 13 + Patch "sprites/weapons/blaster/breadbagfly-scrapyard-pistols.png", -212, -36 +} + +// End of texture definitions diff --git a/credits.txt b/credits.txt index 547d888..0199609 100644 --- a/credits.txt +++ b/credits.txt @@ -14,6 +14,8 @@ Resources: Uses ZForms by Gutawer Additional graphics and mods's base: Id Software, Raven Software Armor and backpack sprites: cybermonday https://forum.zdoom.org/viewtopic.php?t=78536 + Blaster graphics from Breadbagfly's Scrapyard https://forum.zdoom.org/viewtopic.php?p=921224 + Blaster projectile graphics from Realm667, "Plasma Bolter" (Sprites from id Software and 3D Realms, edited by Daniel) https://www.realm667.com/component/docman/?task=doc_download&gid=313&Itemid= Other sprites: Realm667 - per-resource credits are inside credits folder diff --git a/sprites/weapons/blaster/BOLTA0 b/sprites/weapons/blaster/BOLTA0 new file mode 100644 index 0000000..da02f29 Binary files /dev/null and b/sprites/weapons/blaster/BOLTA0 differ diff --git a/sprites/weapons/blaster/BOLTB0 b/sprites/weapons/blaster/BOLTB0 new file mode 100644 index 0000000..de9dc48 Binary files /dev/null and b/sprites/weapons/blaster/BOLTB0 differ diff --git a/sprites/weapons/blaster/BOLTC0 b/sprites/weapons/blaster/BOLTC0 new file mode 100644 index 0000000..81bb35c Binary files /dev/null and b/sprites/weapons/blaster/BOLTC0 differ diff --git a/sprites/weapons/blaster/BOLTD0 b/sprites/weapons/blaster/BOLTD0 new file mode 100644 index 0000000..aca108d Binary files /dev/null and b/sprites/weapons/blaster/BOLTD0 differ diff --git a/sprites/weapons/blaster/BOLTE0 b/sprites/weapons/blaster/BOLTE0 new file mode 100644 index 0000000..ffe2a40 Binary files /dev/null and b/sprites/weapons/blaster/BOLTE0 differ diff --git a/sprites/weapons/blaster/BOLTF0 b/sprites/weapons/blaster/BOLTF0 new file mode 100644 index 0000000..14c3956 Binary files /dev/null and b/sprites/weapons/blaster/BOLTF0 differ diff --git a/sprites/weapons/blaster/breadbagfly-scrapyard-pistols.png b/sprites/weapons/blaster/breadbagfly-scrapyard-pistols.png new file mode 100644 index 0000000..f953af4 Binary files /dev/null and b/sprites/weapons/blaster/breadbagfly-scrapyard-pistols.png differ diff --git a/zscript.zsc b/zscript.zsc index 6ddfdbc..5ce9b68 100644 --- a/zscript.zsc +++ b/zscript.zsc @@ -130,6 +130,7 @@ version "4.10.0" #include "zscript/rweapons/w1fist.zs" #include "zscript/rweapons/w1chainsaw.zs" #include "zscript/rweapons/w2pistol.zs" +#include "zscript/rweapons/w2blaster.zs" #include "zscript/rweapons/w3shotgun.zs" #include "zscript/rweapons/w3ssg.zs" #include "zscript/rweapons/w4chaingun.zs" @@ -145,6 +146,7 @@ version "4.10.0" #include "zscript/rweapons/projectiles/rwbfgball.zs" #include "zscript/rweapons/projectiles/rwflechette.zs" #include "zscript/rweapons/projectiles/rwplasmaball.zs" +#include "zscript/rweapons/projectiles/rwblasterball.zs" #include "zscript/rweapons/projectiles/rwminirocket.zs" #include "zscript/rweapons/projectiles/rwrocket.zs" diff --git a/zscript/drops/drops_database.zs b/zscript/drops/drops_database.zs index 9c51593..0425933 100644 --- a/zscript/drops/drops_database.zs +++ b/zscript/drops/drops_database.zs @@ -30,7 +30,6 @@ class DropDatabaseHandler : StaticEventHandler { // Good thing this isn't SQL, l AmmoItems.insert("Shell",5); AmmoItems.insert("RocketAmmo",1); AmmoItems.insert("Cell",2); - debug.print("=== All artifacts' weights: ==="); // And now, iterate the whole class list... // I might be able to make this even more flexible later. @@ -74,6 +73,7 @@ class DropDatabaseHandler : StaticEventHandler { // Good thing this isn't SQL, l } // 2. When something asks for a random drop, give it to them. + String PickFromWeightList(Map items) { MapIterator it; Array weights; @@ -85,6 +85,7 @@ class DropDatabaseHandler : StaticEventHandler { // Good thing this isn't SQL, l } // Now we have a list of weights, so we can just do WeightedRand. + int selected = rnd.WeightedRandArr(weights); if (selected < 0 || selected > results.Size()) { String err = String.format("Invalid result %d from WeightedRand",selected); diff --git a/zscript/drops/map_placed_items_replacements_handler.zs b/zscript/drops/map_placed_items_replacements_handler.zs index a2a2c84..512bca1 100644 --- a/zscript/drops/map_placed_items_replacements_handler.zs +++ b/zscript/drops/map_placed_items_replacements_handler.zs @@ -15,7 +15,11 @@ class MapPlacedItemsToRWCounterpartsReplacementHandler : EventHandler e.Replacement = 'rwChainsaw'; break; case 'Pistol': - e.Replacement = 'rwPistol'; + if (rnd.OneChanceFrom(2)) { + e.Replacement = "rwBlaster"; + } else { + e.Replacement = 'rwPistol'; + } break; case 'Shotgun': e.Replacement = 'rwShotgun'; diff --git a/zscript/rweapons/projectiles/rwblasterball.zs b/zscript/rweapons/projectiles/rwblasterball.zs new file mode 100644 index 0000000..a581dc0 --- /dev/null +++ b/zscript/rweapons/projectiles/rwblasterball.zs @@ -0,0 +1,24 @@ +class RwBlasterBall : RwProjectile { + Default { + Radius 8; + Height 6; + Speed 30; + Projectile; + +RANDOMIZE; + +ZDOOMTRANS; + RenderStyle "Add"; + Alpha 0.6; + SeeSound "weapons/plasmaf"; + DeathSound "weapons/plasmax"; + Obituary "$OB_MPBLASTER"; + } + + states { + Spawn: + BOLT A 4 Bright RWA_SeekerMissile(); + Loop; + Death: + BOLT BCDEF 3 Bright; + Stop; + } +} \ No newline at end of file diff --git a/zscript/rweapons/w2blaster.zs b/zscript/rweapons/w2blaster.zs new file mode 100644 index 0000000..50e40a1 --- /dev/null +++ b/zscript/rweapons/w2blaster.zs @@ -0,0 +1,127 @@ +class RwBlaster : RandomizedWeapon { + // A pistol alternative that runs off an internal battery. + // Instead of ammo, its firerate drops off dramatically as it heats up. + // The idea is that this is a weapon you want to use in between other weapons; it works best in short bursts and 'cools down' while in your pocket. + // Partly inspired by the Treasure Tech pistol's altfire--again, high burst damage, but it's at its best when you have other weapons on hand. + + int chargeAcc; + int chargeTimer; + + default { + Weapon.SlotNumber 2; + Weapon.SelectionOrder 3600; // Backup weapon + + Inventory.PickupMessage "$GOTBLASTER"; + Obituary "$OB_MPBLASTER"; + Tag "$TAG_BLASTER"; + // I'd like to set this thing up so that it doesn't autoswitch away + // when the clip is depleted (since the clip recharges over time), + // but it looks like I can't do that without making the recharge completely irrelevant, + // esp. if this thing gets firerate affixes. + } + + override void DoEffect() { + super.DoEffect(); + chargeTimer++; + chargeAcc += stats.reloadSpeedModifier; + // Charge speed up from reload speed. + while (chargeAcc > 100) { + chargeTimer++; + chargeAcc -= 100; + } + // Charge speed down from reload speed penalties. + if (chargeAcc < -100) { + chargeTimer--; // can only happen once a frame--you can't go backwards! + chargeAcc += 100; + } + if (chargeTimer >= 3 && currentClipAmmo < stats.clipSize) { + currentClipAmmo++; // Reloads slowly over time. + // Base clip size takes ~9 seconds to recharge from empty. + chargeTimer = 0; + } + } + + action state PickBlasterStage() { + double magfill = double(invoker.CurrentClipAmmo) / double(invoker.stats.clipSize); + if (magfill > 0.7) { + return ResolveState("Stage1"); + } else if (magfill > 0.4) { + return ResolveState("Stage2"); + } else { + return ResolveState("Stage3"); + } + } + + states { + Spawn: + BLAS A -1; + + Select: + BLSG A 1 A_Raise; + Loop; + DeSelect: + BLSG A 1 A_Lower; + Loop; + + Ready: + BLSG A 1 A_WeaponReady; // Does not manually reload! + Loop; + + Fire: + BLSG A 0 PickBlasterStage; + + Stage1: + BLSG B 1 Bright { + RWA_ApplyRateOfFire(); + RWA_DoFire(); + } + BLSG C 1 Bright RWA_ApplyRateOfFire; + Goto Ready; + Stage2: + BLSG B 2 Bright { + RWA_ApplyRateOfFire(); + RWA_DoFire(); + } + BLSG C 2 Bright RWA_ApplyRateOfFire; + Goto Ready; + Stage3: + BLSG B 2 Bright { + RWA_ApplyRateOfFire(); + RWA_DoFire(); + } + BLSG C 2 Bright RWA_ApplyRateOfFire; + BLSG A 2 RWA_ApplyRateOfFire; + Goto Ready; + } + + override void setBaseStats() { + stats = RWStatsClass.NewWeaponStats( + 10, 20, + 1, + 10, + 5.0, + 1.0 + ); + stats.clipSize = 100; + stats.firesProjectiles = true; + stats.projClass = 'RwBlasterBall'; + rwBaseName = "Blaster"; + } + + override string GetRandomFluffName() { + static const string specialNames[] = + { + "Reserve Shooter", + "Taser", + "Zapper", + "Zapgun", + "Bolt Thrower", + "Backup Plan", + "Phaser", + "Beamer", + "Sprayer", + "Cricket" + }; + return specialNames[rnd.randn(specialNames.Size())]; + } +} \ No newline at end of file