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 fb27581b0fa2..288892c95a1c 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 d9cd2c54681b..33c8ef8e5f26 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 bd9e57a108d8..c227bae555e0 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 791bb27d58a4..cee6ccb6f420 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