diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index 110f249c99d..cd41d9393b4 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -19,6 +19,10 @@ var/det_time = 30 var/fake = FALSE var/activation_sound = 'sound/weapons/armbomb.ogg' + /// If TRUE, grenade launchers defer projectile processing and post-fire handling to this ammunition. + var/special_launcher_handling = FALSE + /// If TRUE, firing this ammunition from a grenade launcher sends a live notification to admins. + var/notify_admins_on_launcher_fire = TRUE pickup_sound = 'sound/items/pickup/grenade.ogg' drop_sound = 'sound/items/drop/grenade.ogg' @@ -89,6 +93,14 @@ // Nor do we want people to instantly know when to throw a perfectly timed grenade. animate(src, det_time + rand(-5, 5), -1, LINEAR_EASING, color = COLOR_RED) +/// Handles firing behavior for ammunition with special_launcher_handling. +/obj/item/grenade/proc/process_launcher_projectile(obj/item/gun/launcher/grenade/launcher, mob/user, atom/target, target_zone, params) + return FALSE + +/// Handles cleanup after special launcher ammunition has been successfully fired. +/obj/item/grenade/proc/handle_launcher_post_fire(obj/item/gun/launcher/grenade/launcher) + return + /obj/item/grenade/proc/prime() var/turf/T = get_turf(src) if(T) diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index f777a7c8f3a..984706b416c 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -416,6 +416,12 @@ illustration = "stinger" starts_with = list(/obj/item/grenade/stinger = 7) +/obj/item/storage/box/tactical/beanbags + name = "box of beanbag rounds" + desc = "A box containing 7 less-lethal beanbag rounds for grenade launchers." + illustration = "stinger" + starts_with = list(/obj/item/grenade/beanbag = 7) + /obj/item/storage/box/tactical/teargas name = "box of pepperspray grenades" desc = "A box containing 7 tear gas grenades. A gas mask is printed on the label.
WARNING: Exposure carries risk of serious injury or death. Keep away from persons with lung conditions." diff --git a/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm b/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm index c5fdf3265fc..7667165a6d8 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm @@ -67,6 +67,8 @@ new /obj/item/ammo_magazine/mc9mmt/rubber(src) for(var/i = 1 to 4) new /obj/item/storage/box/shells/beanbags(src) + for(var/i = 1 to 2) + new /obj/item/storage/box/tactical/beanbags(src) new /obj/item/storage/box/shells/flashshells(src) new /obj/item/storage/box/shells/stunshells(src) new /obj/item/storage/box/shells/trackingslugs(src) diff --git a/code/modules/cargo/items/security.dm b/code/modules/cargo/items/security.dm index 23a59356544..24218504f68 100644 --- a/code/modules/cargo/items/security.dm +++ b/code/modules/cargo/items/security.dm @@ -168,6 +168,20 @@ groupable = TRUE spawn_amount = 1 +/singleton/cargo_item/grenade_launcher_beanbags_box + category = "security" + name = "box of beanbag rounds" + supplier = "zavodskoi" + description = "A box containing 7 less-lethal beanbag rounds. These rounds can only be fired from a grenade launcher." + price = 400 + items = list( + /obj/item/storage/box/tactical/beanbags + ) + access = ACCESS_SECURITY + container_type = "crate" + groupable = TRUE + spawn_amount = 1 + /singleton/cargo_item/empgrenades_box category = "security" name = "box of EMP grenades" diff --git a/code/modules/projectiles/guns/launcher/grenade_launcher.dm b/code/modules/projectiles/guns/launcher/grenade_launcher.dm index 70e588cac74..c258106663f 100644 --- a/code/modules/projectiles/guns/launcher/grenade_launcher.dm +++ b/code/modules/projectiles/guns/launcher/grenade_launcher.dm @@ -100,15 +100,63 @@ chambered.activate(null) return chambered +/obj/item/gun/launcher/grenade/process_projectile(obj/item/projectile, mob/user, atom/target, target_zone, params, pointblank, reflex) + var/obj/item/grenade/grenade = projectile + if(grenade.special_launcher_handling) + return grenade.process_launcher_projectile(src, user, target, target_zone, params) + return ..() + /obj/item/gun/launcher/grenade/handle_post_fire(mob/user) - message_admins("[key_name_admin(user)] fired a grenade ([chambered.name]) from a grenade launcher ([src.name]).") + if(chambered.notify_admins_on_launcher_fire) + message_admins("[key_name_admin(user)] fired a grenade ([chambered.name]) from a grenade launcher ([src.name]).") log_game("[key_name_admin(user)] used a grenade ([chambered.name]).") + if(chambered.special_launcher_handling) + chambered.handle_launcher_post_fire(src) chambered = null update_maptext() /obj/item/gun/launcher/grenade/get_ammo() return grenades.len + (chambered? 1 : 0) +/** + * A less-lethal round which the grenade launcher converts into a conventional + * beanbag projectile when fired. The inert item cannot be activated by hand + * or produce the beanbag effect when thrown by other means. + */ +/obj/projectile/bullet/shotgun/beanbag/grenade_launcher + icon_state = "beanbag" + damage = 20 + agony = 70 + +/obj/item/grenade/beanbag + name = "beanbag round" + desc = "A less-than-lethal round intended to be fired by a standard grenade launcher." + icon_state = "beanbag" + item_state = "grenade" + throwforce = 0 + special_launcher_handling = TRUE + notify_admins_on_launcher_fire = FALSE + +/obj/item/grenade/beanbag/attack_self(mob/user) + to_chat(user, SPAN_WARNING("\The [src] has no hand-operated firing mechanism. It must be loaded into a grenade launcher.")) + +/obj/item/grenade/beanbag/activate(atom/user) + return + +/obj/item/grenade/beanbag/process_launcher_projectile(obj/item/gun/launcher/grenade/launcher, mob/user, atom/target, target_zone, params) + var/obj/projectile/bullet/shotgun/beanbag/grenade_launcher/beanbag = new(get_turf(user)) + if(!beanbag.preparePixelProjectile(target, launcher, params)) + qdel(beanbag) + return FALSE + beanbag.firer = user + beanbag.fired_from = launcher + beanbag.def_zone = target_zone + return !beanbag.fire() + +/obj/item/grenade/beanbag/handle_launcher_post_fire(obj/item/gun/launcher/grenade/launcher) + launcher.play_fire_sound() + qdel(src) + //Underslung grenade launcher to be used with the Z8 /obj/item/gun/launcher/grenade/underslung name = "underslung grenade launcher" diff --git a/html/changelogs/geeves-beanbag-rounds.yml b/html/changelogs/geeves-beanbag-rounds.yml new file mode 100644 index 00000000000..09292fc71b2 --- /dev/null +++ b/html/changelogs/geeves-beanbag-rounds.yml @@ -0,0 +1,6 @@ +author: Geeves + +delete-after: True + +changes: + - rscadd: "Added less-than-lethal beanbag rounds for grenade launchers. These have been mapped in to the armory, alongside a single grenade launcher. More ammo can be ordered from cargo." diff --git a/icons/obj/grenade.dmi b/icons/obj/grenade.dmi index 099a8d2ec83..549d5b71e4f 100644 Binary files a/icons/obj/grenade.dmi and b/icons/obj/grenade.dmi differ diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi index d36f9006e48..dd5796f84e3 100644 Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ diff --git a/maps/runtime/runtime.dmm b/maps/runtime/runtime.dmm index 40d105feaa4..edabea7cd9e 100644 --- a/maps/runtime/runtime.dmm +++ b/maps/runtime/runtime.dmm @@ -311,6 +311,7 @@ /obj/structure/railing/mapped/no_density/low{ dir = 8 }, +/obj/item/gun/launcher/grenade, /turf/unsimulated/floor/dark_monotile, /area/runtime/floor_one/main) "ba" = ( @@ -5654,6 +5655,7 @@ /obj/item/storage/box/shells/beanbags, /obj/item/storage/box/shells/buckshot, /obj/item/storage/box/shells/buckshot, +/obj/item/storage/box/tactical/beanbags, /turf/simulated/floor/tiled/dark, /area/runtime/floor_one/main) "Db" = ( diff --git a/maps/sccv_horizon/sccv_horizon.dmm b/maps/sccv_horizon/sccv_horizon.dmm index 761bfde7274..8f974fe69c2 100644 --- a/maps/sccv_horizon/sccv_horizon.dmm +++ b/maps/sccv_horizon/sccv_horizon.dmm @@ -81889,6 +81889,7 @@ /obj/effect/floor_decal/industrial/outline/yellow, /obj/item/gun/projectile/shotgun/pump/unloaded, /obj/item/gun/projectile/shotgun/pump/unloaded, +/obj/item/gun/launcher/grenade, /turf/simulated/floor/tiled/dark/full, /area/horizon/security/armoury) "kDV" = (