diff --git a/code/datums/supply_packs/explosives.dm b/code/datums/supply_packs/explosives.dm index f032d0f891b0..f3b59c709d20 100644 --- a/code/datums/supply_packs/explosives.dm +++ b/code/datums/supply_packs/explosives.dm @@ -31,6 +31,17 @@ containername = "\improper explosive mine boxes crate (WARNING)" group = "Explosives" +/datum/supply_packs/explosives_satchel_charges + name = "M17 satchel charges crate (x3)" + contains = list( + /obj/item/storage/box/explosive_mines/satchel_charges, + /obj/item/storage/box/explosive_mines/satchel_charges, + /obj/item/storage/box/explosive_mines/satchel_charges, + ) + cost = 30 + containertype = /obj/structure/closet/crate/explosives + containername = "\improper explosive M17 charges crate (WARNING)" + group = "Explosives" /datum/supply_packs/explosives_m15 name = "M15 fragmentation grenades crate (x6)" contains = list( diff --git a/code/game/machinery/vending/vendor_types/requisitions.dm b/code/game/machinery/vending/vendor_types/requisitions.dm index 569a042da81d..bf7b5bc6d67f 100644 --- a/code/game/machinery/vending/vendor_types/requisitions.dm +++ b/code/game/machinery/vending/vendor_types/requisitions.dm @@ -60,6 +60,9 @@ list("M40 MFHS Metal Foam Grenade", floor(scale * 6), /obj/item/explosive/grenade/metal_foam, VENDOR_ITEM_REGULAR), list("Plastic Explosives", floor(scale * 3), /obj/item/explosive/plastic, VENDOR_ITEM_REGULAR), list("Breaching Charge", floor(scale * 2), /obj/item/explosive/plastic/breaching_charge, VENDOR_ITEM_REGULAR), + list("Satchel Charges", floor(scale*3), /obj/item/explosive/satchel_charge, VENDOR_ITEM_REGULAR), + list("Satchel Charge Detonator", floor(scale*5), /obj/item/satchel_charge_detonator, VENDOR_ITEM_REGULAR), + list("Satchel Charge Box (x3 charges)", floor(scale*3), /obj/item/storage/box/explosive_mines/satchel_charges/req, VENDOR_ITEM_REGULAR), list("WEBBINGS", -1, null, null), list("Black Webbing Vest", floor(scale * 2), /obj/item/clothing/accessory/storage/black_vest, VENDOR_ITEM_REGULAR), diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm index f59f9543592a..6708c65469d0 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm @@ -20,6 +20,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_engi, list( list("Plasteel x10", 7, /obj/item/stack/sheet/plasteel/small_stack, null, VENDOR_ITEM_RECOMMENDED), list("Plastic Explosive", 3, /obj/item/explosive/plastic, null, VENDOR_ITEM_REGULAR), list("Breaching Charge", 5, /obj/item/explosive/plastic/breaching_charge, null, VENDOR_ITEM_RECOMMENDED), + list("Satchel Charge Box (x5 charges, 1x detonator)", 15, /obj/item/storage/box/explosive_mines/satchel_charges, null, VENDOR_ITEM_RECOMMENDED), list("Sandbags x25", 10, /obj/item/stack/sandbags_empty/half, null, VENDOR_ITEM_RECOMMENDED), list("Super-Capacity Power Cell", 10, /obj/item/cell/super, null, VENDOR_ITEM_REGULAR), list("ES-11 Mobile Fuel Canister", 4, /obj/item/tool/weldpack/minitank, null, VENDOR_ITEM_REGULAR), diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm index 8cb71a57872f..9af53a97faed 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm @@ -45,6 +45,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_leader, list( list("Plasteel x10", 7, /obj/item/stack/sheet/plasteel/small_stack, null, VENDOR_ITEM_RECOMMENDED), list("Plastic explosive", 5, /obj/item/explosive/plastic, null, VENDOR_ITEM_RECOMMENDED), list("Breaching Charge", 7, /obj/item/explosive/plastic/breaching_charge, null, VENDOR_ITEM_RECOMMENDED), + list("Satchel Charge Box (x5 charges, 1x detonator)", 20, /obj/item/storage/box/explosive_mines/satchel_charges, null, VENDOR_ITEM_RECOMMENDED), list("Sandbags x25", 10, /obj/item/stack/sandbags_empty/half, null, VENDOR_ITEM_RECOMMENDED), list("Signal Flare Pack", 7, /obj/item/storage/box/m94/signal, null, VENDOR_ITEM_REGULAR), list("Tools Pouch (Full)", 5, /obj/item/storage/pouch/tools/full, null, VENDOR_ITEM_REGULAR), diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm index 430a673c5cb7..9d64b88a5287 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm @@ -51,6 +51,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_tl, list( list("Plastic Explosive", 10, /obj/item/explosive/plastic, null, VENDOR_ITEM_REGULAR), list("Signal Flare Pack", 5, /obj/item/storage/box/m94/signal, null, VENDOR_ITEM_REGULAR), list("Breaching Charge", 10, /obj/item/explosive/plastic/breaching_charge, null, VENDOR_ITEM_REGULAR), + list("Satchel Charge Box (x5 charges, 1x detonator)", 30, /obj/item/storage/box/explosive_mines/satchel_charges, null, VENDOR_ITEM_RECOMMENDED), list("ES-11 Mobile Fuel Canister", 5, /obj/item/tool/weldpack/minitank, null, VENDOR_ITEM_REGULAR), list("ME3 Hand Welder", 5, /obj/item/tool/weldingtool/simple, null, VENDOR_ITEM_REGULAR), diff --git a/code/game/objects/items/explosives/explosive.dm b/code/game/objects/items/explosives/explosive.dm index 0be81ba8a0ed..dedfe97bd2db 100644 --- a/code/game/objects/items/explosives/explosive.dm +++ b/code/game/objects/items/explosives/explosive.dm @@ -270,3 +270,163 @@ falloff_mode = EXPLOSION_FALLOFF_SHAPE_LINEAR to_chat(usr, SPAN_NOTICE("You disable [src]'s blast wave dampener, restoring the blast radius to full.")) playsound(loc, 'sound/items/Screwdriver2.ogg', 25, 0, 6) + +/obj/item/satchel_charge_detonator + name = "M38-D Multipurpose Detonator" + desc = "An ergonomic detonator capable of detonating multiple types of command explosives, notable being satchel charges, detcords and plastic explosives." + icon = 'icons/obj/items/weapons/grenade.dmi' + icon_state = "detonator" + w_class = SIZE_TINY + + /// list of linked explosives to handle + var/list/linked_charges = list() + var/pressed = FALSE + +/obj/item/satchel_charge_detonator/attack_self(mob/user, parameters) // when attackl_self, detonate charges + . = ..() + to_chat(user, SPAN_BOLDWARNING("You hold down the detonator button.")) + if(pressed) + return + pressed = TRUE + flick("detonator_active", src) + playsound(src.loc, 'sound/handling/charge-detonator.ogg', 25, 1) + sleep(40) + pressed = FALSE + var/detonation_count = 0 + for(var/obj/item/explosive/satchel_charge/charges in linked_charges) + if(charges.detonate(src)) + detonation_count++ + to_chat(user, SPAN_NOTICE("[src] reported [detonation_count] charge[detonation_count > 1 ? "s" : ""] detonated.")) + +/obj/item/satchel_charge_detonator/clicked(mob/user, list/mods) // kill me + if (isobserver(user) || isxeno(user)) + return + + if (mods["alt"]) // alt+click to ping charges? + to_chat(user, SPAN_NOTICE("You ping the detonator's [length(linked_charges)] linked charges.")) + for(var/obj/item/explosive/satchel_charge/charges in linked_charges) + flick("satchel_primed", charges) + charges.beep(TRUE) + return TRUE + return + +/obj/item/satchel_charge_detonator/Destroy() + for(var/obj/item/explosive/satchel_charge/charges in linked_charges) + charges.linked_detonator = null + linked_charges = null + return ..() + +/obj/item/explosive/satchel_charge + name = "M17 Satchel Charge" + desc = "After linked to a detonator, and thrown, will become primed and able to be detonated." + desc_lore = "The M17 is a simple satchel charge system used by Marines in situations where their usual fire support can't reach, designed to be thrown at or into structures before exploding. This one is set to automatically disarm after a short period, to reduce the chances of civilian injuries from abandoned UXO.\nTo detonate it, link the satchel charge with the included M38-D universal detonator beforehand, then throw it. The detonator's safety mechanism takes four seconds to deactivate after being thrown." + gender = PLURAL + icon = 'icons/obj/items/weapons/grenade.dmi' + icon_state = "satchel" + flags_item = NOBLUDGEON + w_class = SIZE_SMALL + antigrief_protection = TRUE + max_container_volume = 180 + reaction_limits = list( "max_ex_power" = 260, "base_ex_falloff" = 90, "max_ex_shards" = 64, + "max_fire_rad" = 6, "max_fire_int" = 26, "max_fire_dur" = 30, + "min_fire_rad" = 2, "min_fire_int" = 4, "min_fire_dur" = 5 + ) + + var/prime_time = 3 SECONDS + var/prime_timer = null + var/obj/item/satchel_charge_detonator/linked_detonator = null + var/activated = FALSE + var/armed = FALSE + +/obj/item/explosive/satchel_charge/attack_self(mob/user) + . = ..() + if(antigrief_protection && user.faction == FACTION_MARINE && explosive_antigrief_check(src, user)) + to_chat(user, SPAN_WARNING("[name]'s safe-area accident inhibitor prevents you from planting it!")) + msg_admin_niche("[key_name(user)] attempted to prime \a [name] in [get_area(src)] [ADMIN_JMP(src.loc)]") + return + if(!linked_detonator) + to_chat(user, SPAN_NOTICE("This Charge is not linked to any detonator")) + return + icon_state = "satchel_primed" + playsound(src.loc, 'sound/handling/charge-primed.ogg', 25, 1) + var/mob/living/carbon/living_carbon = user + if(istype(living_carbon) && !living_carbon.throw_mode) + living_carbon.toggle_throw_mode(THROW_MODE_NORMAL) + to_chat(user, SPAN_NOTICE("You activate the M17 Satchel Charge, it will now arm itself after a short time once thrown.")) + w_class = SIZE_MASSIVE + activated = TRUE + addtimer(CALLBACK(src, PROC_REF(un_activate)), 10 SECONDS, TIMER_UNIQUE) + +/obj/item/explosive/satchel_charge/attackby(obj/item/weapon_thing, mob/user) + . = ..() + if(armed) + to_chat(user, SPAN_WARNING("This charge is armed, its linking cannot be altered unless disarmed.")) + return + if(!istype(weapon_thing, /obj/item/satchel_charge_detonator)) + return + var/obj/item/satchel_charge_detonator/detonator = weapon_thing + if(linked_detonator == detonator) + detonator.linked_charges -= src + linked_detonator = null + to_chat(user, SPAN_NOTICE("You unlink the charge from [detonator].")) + icon_state = "satchel" + else + linked_detonator?.linked_charges -= src + detonator.linked_charges |= src + linked_detonator = detonator + to_chat(user, SPAN_NOTICE("[detonator] indicates a new charge has been linked.")) + playsound(src.loc, 'sound/handling/charge-connection.ogg', 25, 1) + icon_state = "satchel_linked" + +/obj/item/explosive/satchel_charge/proc/un_activate() + if(activated) + activated = FALSE + w_class = SIZE_SMALL + if(linked_detonator) + icon_state = "satchel_linked" + else + icon_state = "satchel" + +/obj/item/explosive/satchel_charge/throw_atom(atom/target, range, speed, atom/thrower, spin, launch_type, pass_flags) + . = ..() + dir = get_dir(src, thrower) + if(activated && linked_detonator) + icon_state = "satchel_primed" + prime_timer = addtimer(CALLBACK(src, PROC_REF(arm)), prime_time, TIMER_UNIQUE) + beep() + +/obj/item/explosive/satchel_charge/proc/beep(beep_once) + playsound(src.loc, 'sound/weapons/mine_tripped.ogg', 10, 1) + if(!armed && beep_once != TRUE) + addtimer(CALLBACK(src, PROC_REF(beep)), 1 SECONDS, TIMER_UNIQUE) + + +/obj/item/explosive/satchel_charge/proc/arm() + activated = FALSE + if(!linked_detonator || armed) + return + icon_state = "satchel_armed" + armed = TRUE + +/obj/item/explosive/satchel_charge/pickup(mob/user) + if(armed) + if(linked_detonator) + icon_state = "satchel_linked" + else + icon_state = "satchel" + armed = FALSE + w_class = SIZE_SMALL + return ..() + +/obj/item/explosive/satchel_charge/proc/detonate(triggerer) + if(!armed || linked_detonator != triggerer) + return FALSE + cell_explosion(loc, 120, 30, EXPLOSION_FALLOFF_SHAPE_LINEAR, null, cause_data) + qdel(src) + return TRUE + +/obj/item/explosive/satchel_charge/Destroy() + linked_detonator?.linked_charges -= src + linked_detonator = null + return ..() + diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm index 0647d214be97..6421893861d5 100644 --- a/code/game/objects/items/storage/boxes.dm +++ b/code/game/objects/items/storage/boxes.dm @@ -601,6 +601,31 @@ for(var/i in 1 to 5) new /obj/item/explosive/mine/pmc(src) +/obj/item/storage/box/explosive_mines/satchel_charges + name = "\improper M17 satchel charge box (x5)" + desc = "A secure box holding five M17 satchel charges and a detonator, don't lose it!" + icon_state = "satchelbox" + max_storage_space = 16 + can_hold = list( + /obj/item/explosive/satchel_charge, + /obj/item/satchel_charge_detonator, + ) + +/obj/item/storage/box/explosive_mines/satchel_charges/fill_preset_inventory() + new /obj/item/satchel_charge_detonator(src) + for(var/i in 1 to 5) + new /obj/item/explosive/satchel_charge(src) + +/obj/item/storage/box/explosive_mines/satchel_charges/req + name = "\improper M17 satchel charge box (x3)" + max_storage_space = 10 + desc = "A secure box holding three M17 satchel charges." + +/obj/item/storage/box/explosive_mines/satchel_charges/req/fill_preset_inventory() + new /obj/item/satchel_charge_detonator(src) + for(var/i in 1 to 3) + new /obj/item/explosive/satchel_charge(src) + /obj/item/storage/box/m94 name = "\improper M94 marking flare pack" desc = "A packet of eight M94 Marking Flares. Carried by USCM soldiers to light dark areas that cannot be reached with the usual TNR Shoulder Lamp." diff --git a/code/game/objects/items/storage/pouch.dm b/code/game/objects/items/storage/pouch.dm index 5993aa6b6f67..82b4be8b35cb 100644 --- a/code/game/objects/items/storage/pouch.dm +++ b/code/game/objects/items/storage/pouch.dm @@ -594,6 +594,8 @@ /obj/item/explosive/plastic, /obj/item/explosive/mine, /obj/item/explosive/grenade, + /obj/item/explosive/satchel_charge, + /obj/item/satchel_charge_detonator, ) /obj/item/storage/pouch/explosive/attackby(obj/item/W, mob/user) diff --git a/icons/obj/items/storage/packets.dmi b/icons/obj/items/storage/packets.dmi index ac900a18aafa..bd7ad38fc2b4 100644 Binary files a/icons/obj/items/storage/packets.dmi and b/icons/obj/items/storage/packets.dmi differ diff --git a/icons/obj/items/weapons/grenade.dmi b/icons/obj/items/weapons/grenade.dmi index 61c9707e43df..b173798cadaf 100644 Binary files a/icons/obj/items/weapons/grenade.dmi and b/icons/obj/items/weapons/grenade.dmi differ diff --git a/sound/handling/charge-connection.ogg b/sound/handling/charge-connection.ogg new file mode 100644 index 000000000000..8b92f2f42d02 Binary files /dev/null and b/sound/handling/charge-connection.ogg differ diff --git a/sound/handling/charge-detonator.ogg b/sound/handling/charge-detonator.ogg new file mode 100644 index 000000000000..8bb228ab76c6 Binary files /dev/null and b/sound/handling/charge-detonator.ogg differ diff --git a/sound/handling/charge-primed.ogg b/sound/handling/charge-primed.ogg new file mode 100644 index 000000000000..bdfeabf64fdb Binary files /dev/null and b/sound/handling/charge-primed.ogg differ