diff --git a/code/datums/uplink_items/uplink_traitor.dm b/code/datums/uplink_items/uplink_traitor.dm index 545ec96e3bc..ff2cdec2b6d 100644 --- a/code/datums/uplink_items/uplink_traitor.dm +++ b/code/datums/uplink_items/uplink_traitor.dm @@ -77,6 +77,7 @@ cost = 25 //A chef can get a knife that sharp easily, though it won't block. While you can get endless boomerang, they are less deadly than a stech, and slower / more predictable. job = list("Mime", "Chef") +// Shaft miner /datum/uplink_item/jobspecific/pressure_mod name = "Kinetic Accelerator Pressure Mod" desc = "A modification kit which allows Kinetic Accelerators to do greatly increased damage while indoors. Occupies 35% mod capacity." @@ -86,6 +87,15 @@ job = list("Shaft Miner") surplus = 0 // Requires a KA to even be used. +/datum/uplink_item/jobspecific/mining_charge_hacker + name = "Mining Charge Hacker" + desc = "Looks and functions like an advanced mining scanner, but allows mining charges to be placed anywhere and destroy more than rocks. \ + Use it on a mining charge to override its safeties. Reduces explosive power of mining charges due to the modification of their internals." + reference = "MCH" + item = /obj/item/t_scanner/adv_mining_scanner/syndicate + cost = 25 + job = list("Shaft Miner") + //Chef /datum/uplink_item/jobspecific/specialsauce name = "Chef Excellence's Special Sauce" diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index ab458dc8c36..dd5df9c4122 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -12,6 +12,7 @@ var/image_overlay = null var/obj/item/assembly/nadeassembly = null var/assemblyattacher + var/notify_admins = TRUE /obj/item/grenade/plastic/Initialize(mapload) . = ..() @@ -79,8 +80,9 @@ target = AM loc = null - message_admins("[key_name_admin(user)]([ADMIN_QUE(user,"?")]) ([ADMIN_FLW(user,"FLW")]) planted [src.name] on [target.name] at ([target.x],[target.y],[target.z] - JMP) with [det_time] second fuse",0,1) - log_game("[key_name(user)] planted [name] on [target.name] at ([target.x],[target.y],[target.z]) with [det_time] second fuse") + if(notify_admins) + message_admins("[ADMIN_LOOKUPFLW(user)] planted [src.name] on [target.name] at ([target.x],[target.y],[target.z] - JMP) with [det_time] second fuse", 0, 1) + log_game("[key_name(user)] planted [name] on [target.name] at ([target.x],[target.y],[target.z]) with [det_time] second fuse") AddComponent(/datum/component/persistent_overlay, image_overlay, target) if(!nadeassembly) diff --git a/code/modules/mining/equipment/mining_charges.dm b/code/modules/mining/equipment/mining_charges.dm new file mode 100644 index 00000000000..25c7e0252a3 --- /dev/null +++ b/code/modules/mining/equipment/mining_charges.dm @@ -0,0 +1,215 @@ +/obj/item/grenade/plastic/miningcharge + name = "industrial mining charge" + desc = "Used to make big holes in rocks. Only works on rocks!" + icon = 'icons/obj/mining.dmi' + icon_state = "mining-charge-2" + item_state = "charge_indust" + det_time = 5 + notify_admins = FALSE // no need to make adminlogs on lavaland, while they are "safe" to use + /// When TRUE, charges won't detonate on it's own. Used for mining detonator + var/timer_off = FALSE + var/installed = FALSE + var/smoke_amount = 3 + /// list of sizes for explosion. Third number is used for actual rock explosion size, second number is radius for Weaken() effects, first is used for hacked charges + var/boom_sizes = list(2, 3, 5) + var/hacked = FALSE + +/obj/item/grenade/plastic/miningcharge/Initialize() + . = ..() + image_overlay = mutable_appearance(icon, "[icon_state]_active", ON_EDGED_TURF_LAYER) + +/obj/item/grenade/plastic/miningcharge/examine(mob/user) + . = ..() + if(hacked) + . += "Its wiring is haphazardly changed." + if(timer_off) + . += "The mining charge is connected to a detonator." + +/obj/item/grenade/plastic/miningcharge/attack_self(mob/user) + if(nadeassembly) + nadeassembly.attack_self(user) + +/obj/item/grenade/plastic/miningcharge/afterattack(atom/movable/AM, mob/user, flag) + if(!ismineralturf(AM) && !hacked) + return + if(is_ancient_rock(AM) && !hacked) + to_chat(user, "This rock appears to be resistant to all mining tools except pickaxes!") + return + if(!timer_off) //override original proc for plastic explosions + return ..() + if(!flag) + return + if(iscarbon(AM)) + return + to_chat(user, "You start planting [src].") + if(!do_after(user, (2.5 SECONDS) * toolspeed, target = AM)) + return + if(!user.unEquip(src)) + return + target = AM + forceMove(AM) + if(hacked) + message_admins("[ADMIN_LOOKUPFLW(user)] planted [name] on [target.name] at [ADMIN_COORDJMP(target)]") + log_game("planted [name] on [target.name] at [COORD(target)]", user) + installed = TRUE + target.overlays += image_overlay + +/obj/item/grenade/plastic/miningcharge/attackby(obj/item/I, mob/user, params) + if(!istype(I, /obj/item/detonator)) + return + var/obj/item/detonator/detonator = I + if((src in detonator.bombs) || timer_off) + to_chat(user, "[src] was already synchronized to a existing detonator!") + return + detonator.bombs += src + timer_off = TRUE + to_chat(user, "You synchronize [src] to [I].") + playsound(src, 'sound/machines/twobeep.ogg', 50) + detonator.update_icon() + +/obj/item/grenade/plastic/miningcharge/proc/detonate() + addtimer(CALLBACK(src, PROC_REF(prime)), 3 SECONDS) + +/obj/item/grenade/plastic/miningcharge/prime() + if(hacked) //try not to blow your fingers off + explode() + return + var/turf/simulated/mineral/location = get_turf(target) + var/datum/effect_system/smoke_spread/S = new + S.set_up(smoke_amount, 0, location, null) + S.start() + for(var/turf/simulated/mineral/rock in circlerangeturfs(location, boom_sizes[3])) + var/distance = get_dist_euclidian(location, rock) + if(distance <= boom_sizes[3]) + rock.mineralAmt += 3 // if rock is going to get drilled, add bonus mineral amount + rock.gets_drilled() + for(var/mob/living/carbon/C in circlerange(location, boom_sizes[3])) + var/distance = get_dist_euclidian(location, C) + C.flash_eyes() + C.Weaken((boom_sizes[2] - distance) * 1 SECONDS) //1 second for how close you are to center if you're in range + C.AdjustDeaf((boom_sizes[3] - distance) * 5 SECONDS) //guaranteed deafness + var/obj/item/organ/internal/ears/ears = C.get_int_organ(/obj/item/organ/internal/ears) + if(istype(ears) && C.check_ear_prot() < HEARING_PROTECTION_MINOR) //headsets should be enough to avoid taking damage + ears.receive_damage((boom_sizes[3] - distance) * 2) //something like that i guess. Mega charge makes 12 damage to ears if nearby + to_chat(C, "You are knocked down by the power of the mining charge!") + qdel(src) + +/obj/item/grenade/plastic/miningcharge/proc/explode() + var/turf/location + if(target) + if(!QDELETED(target)) + if(isturf(target)) + location = get_turf(target) + else + location = get_atom_on_turf(target) + target.overlays -= image_overlay + else + location = get_atom_on_turf(src) + if(location) + explosion(location, boom_sizes[1], boom_sizes[2], boom_sizes[3], cause = src) + location.ex_act(2, target) + qdel(src) + +/obj/item/grenade/plastic/miningcharge/proc/override_safety() + hacked = TRUE + notify_admins = TRUE + boom_sizes[1] = round(boom_sizes[1] / 3) //lesser - 0, normal - 0, mega - 1; c4 - 0 + boom_sizes[2] = round(boom_sizes[2] / 3) //lesser - 0, normal - 1, mega - 2; c4 - 0 + boom_sizes[3] = round(boom_sizes[3] / 1.5) //lesser - 2, normal - 3, mega - 5; c4 - 3 + +/// Overriding to avoid the chargers from exploding because of received damage +/obj/item/grenade/plastic/miningcharge/deconstruct(disassembled = TRUE) + if(!QDELETED(src)) + qdel(src) + +/obj/item/grenade/plastic/miningcharge/lesser + name = "mining charge" + desc = "A mining charge. This one seems less powerful than industrial. Only works on rocks!" + icon_state = "mining-charge-1" + item_state = "charge_lesser" + smoke_amount = 1 + boom_sizes = list(1, 2, 3) + +/obj/item/grenade/plastic/miningcharge/mega + name = "experimental mining charge" + desc = "A mining charge. This one seems much more powerful than normal!" + icon_state = "mining-charge-3" + item_state = "charge_mega" + smoke_amount = 5 + boom_sizes = list(4, 6, 8) + +/obj/item/storage/backpack/duffel/miningcharges/populate_contents() + for(var/i in 1 to 5) + new /obj/item/grenade/plastic/miningcharge/lesser(src) + for(var/i in 1 to 3) + new /obj/item/grenade/plastic/miningcharge(src) + new /obj/item/detonator(src) + +//MINING CHARGE HACKER + +/obj/item/t_scanner/adv_mining_scanner/syndicate + var/charges = 6 + +/obj/item/t_scanner/adv_mining_scanner/syndicate/examine(mob/user) + . = ..() + . += "This scanner has an extra port for overriding mining charge safeties." + +/obj/item/t_scanner/adv_mining_scanner/syndicate/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + if(!istype(target, /obj/item/grenade/plastic/miningcharge)) + return + var/obj/item/grenade/plastic/miningcharge/charge = target + if(charge.hacked) + to_chat(user, "[src] is already overridden!") + return + if(charges <= 0) + to_chat(user, "Its overriding function is depleted.") + return + charge.override_safety() + visible_message("Sparks fly out of [src]!") + playsound(src, "sparks", 50, TRUE) + charges-- + if(charges <= 0) + to_chat(user, "[src]'s internal battery for overriding mining charges has run dry!") + +// MINING CHARGES DETONATOR + +/obj/item/detonator + name = "mining charge detonator" + desc = "A specialized mining device designed for controlled demolition operations using mining explosives." + w_class = WEIGHT_CLASS_SMALL + icon = 'icons/obj/mining.dmi' + icon_state = "Detonator-0" + + /// list of all bombs connected to a detonator for a moment + var/list/bombs = list() + +/obj/item/detonator/examine(mob/user) + . = ..() + if(length(bombs)) + . += "List of synched bombs:" + for(var/obj/item/grenade/plastic/miningcharge/charge in bombs) + . += "[bicon(charge)] [charge]. Current status: [charge.installed ? "ready to detonate" : "ready to deploy"]." + +/obj/item/detonator/update_icon() + . = ..() + if(length(bombs)) + icon_state = "Detonator-1" + else + icon_state = initial(icon_state) + +/obj/item/detonator/attack_self(mob/user) + playsound(src, 'sound/items/detonator.ogg', 40) + if(length(bombs)) + to_chat(user, "Activating explosives...") + for(var/obj/item/grenade/plastic/miningcharge/charge in bombs) + if(QDELETED(charge)) + bombs -= charge + update_icon() //if the last bomb was qdeleted, detonator icon should change after activating + continue + if(charge.installed) + bombs -= charge + charge.detonate() + update_icon() + else + to_chat(user, "There are no charges linked to a detonator!") + return ..() diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index 80e0b252ade..ba69109c473 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -42,6 +42,7 @@ EQUIPMENT("Mining MODsuit", /obj/item/mod/control/pre_equipped/mining/vendor, 3500), EQUIPMENT("Asteroid MODsuit Skin", /obj/item/mod/skin_applier/asteroid, 1000), EQUIPMENT("Tracking Bio-chip Kit", /obj/item/storage/box/minertracker, 600), + EQUIPMENT("Mining Charge Detonator", /obj/item/detonator, 150) ) prize_list["Consumables"] = list( EQUIPMENT("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 100), @@ -50,6 +51,8 @@ EQUIPMENT("Jaunter", /obj/item/wormhole_jaunter, 750), EQUIPMENT("Chasm Jaunter Recovery Grenade", /obj/item/grenade/jaunter_grenade, 1500), EQUIPMENT("Lazarus Injector", /obj/item/lazarus_injector, 1000), + EQUIPMENT("Mining Charge", /obj/item/grenade/plastic/miningcharge/lesser, 150), + EQUIPMENT("Industrial Mining Charge", /obj/item/grenade/plastic/miningcharge, 500), EQUIPMENT("Point Transfer Card", /obj/item/card/mining_point_card, 500), EQUIPMENT("Shelter Capsule", /obj/item/survivalcapsule, 400), EQUIPMENT("Stabilizing Serum", /obj/item/hivelordstabilizer, 400), @@ -248,7 +251,7 @@ * * redeemer - The person holding it */ /obj/machinery/mineral/equipment_vendor/proc/redeem_voucher(obj/item/mining_voucher/voucher, mob/redeemer) - var/items = list("Survival Capsule and Explorer's Webbing", "Resonator Kit", "Minebot Kit", "Extraction and Rescue Kit", "Crusher Kit", "Plasma Cutter", "Jaunter Kit", "Mining Conscription Kit") + var/items = list("Survival Capsule and Explorer's Webbing", "Resonator Kit", "Minebot Kit", "Extraction and Rescue Kit", "Crusher Kit", "Plasma Cutter", "Mining Explosives Kit", "Jaunter Kit", "Mining Conscription Kit") var/selection = tgui_input_list(redeemer, "Pick your equipment", "Mining Voucher Redemption", items) if(!selection || !Adjacent(redeemer) || QDELETED(voucher) || voucher.loc != redeemer) @@ -274,6 +277,8 @@ new /obj/item/kinetic_crusher(drop_location) if("Plasma Cutter") new /obj/item/gun/energy/plasmacutter(drop_location) + if("Mining Explosives Kit") + new /obj/item/storage/backpack/duffel/miningcharges(drop_location) if("Jaunter Kit") new /obj/item/wormhole_jaunter(drop_location) new /obj/item/stack/medical/bruise_pack/advanced(drop_location) diff --git a/code/modules/research/designs/mining_designs.dm b/code/modules/research/designs/mining_designs.dm index 3b4e5a1c1cb..831092befaa 100644 --- a/code/modules/research/designs/mining_designs.dm +++ b/code/modules/research/designs/mining_designs.dm @@ -111,6 +111,16 @@ build_path = /obj/item/borg/upgrade/modkit/aoe/turfs category = list("Mining", "Cyborg Upgrade Modules") +/datum/design/mining_charges + name = "Experimental Mining Charge" + desc = "An experimental mining charge used to make big holes in rocks." + id = "megacharge" + req_tech = list("materials" = 5, "engineering" = 5, "plasmatech" = 6) + build_type = PROTOLATHE + materials = list(MAT_METAL = 4000, MAT_PLASMA = 6000, MAT_URANIUM = 1000) + build_path = /obj/item/grenade/plastic/miningcharge/mega + category = list("Mining") + /datum/design/lavarods name = "Lava-Resistant Iron Rods" desc = "Treated, specialized iron rods. When exposed to the vacuum of space their coating breaks off, but they can hold up against the extreme heat of molten liquids." diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 33942e4a03c..556989be5d2 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 01cee2e989d..5350e346160 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi index 4a74f194c51..4ca486bcfb7 100644 Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ diff --git a/paradise.dme b/paradise.dme index 522424f7148..9c97b387faa 100644 --- a/paradise.dme +++ b/paradise.dme @@ -2053,6 +2053,7 @@ #include "code\modules\mining\equipment\lazarus_injector.dm" #include "code\modules\mining\equipment\marker_beacons.dm" #include "code\modules\mining\equipment\mineral_scanner.dm" +#include "code\modules\mining\equipment\mining_charges.dm" #include "code\modules\mining\equipment\mining_tools.dm" #include "code\modules\mining\equipment\regenerative_core.dm" #include "code\modules\mining\equipment\resonator.dm" diff --git a/sound/items/detonator.ogg b/sound/items/detonator.ogg new file mode 100644 index 00000000000..b607bdc3607 Binary files /dev/null and b/sound/items/detonator.ogg differ