diff --git a/code/datums/looping_sounds/thermal_drill.dm b/code/datums/looping_sounds/thermal_drill.dm new file mode 100644 index 00000000000..d4a20647f2b --- /dev/null +++ b/code/datums/looping_sounds/thermal_drill.dm @@ -0,0 +1,4 @@ +/datum/looping_sound/thermal_drill + mid_sounds = list('sound/items/thermal_drill.ogg' = 1) + mid_length = 19 + volume = 30 \ No newline at end of file diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index ef439049611..15438fdf64c 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -1002,6 +1002,22 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) cost = 3 excludefrom = list(/datum/game_mode/nuclear) +/datum/uplink_item/device_tools/thermal_drill + name = "Thermal Drill" + desc = "A tungsten carbide thermal drill with magnetic clamps for the purpose of drilling hardened objects. Guaranteed 100% jam proof." + reference = "DRL" + item = /obj/item/thermal_drill + cost = 3 + excludefrom = list(/datum/game_mode/nuclear) + +/datum/uplink_item/device_tools/diamond_drill + name = "Diamond Tipped Thermal Drill" + desc = "A diamond tipped thermal drill with magnetic clamps for the purpose of quickly drilling hardened objects. Guaranteed 100% jam proof." + reference = "DDRL" + item = /obj/item/thermal_drill/diamond_drill + cost = 1 + gamemodes = list(/datum/game_mode/nuclear) + /datum/uplink_item/device_tools/medkit name = "Syndicate Combat Medic Kit" desc = "The syndicate medkit is a suspicious black and red. Included is a combat stimulant injector for rapid healing, a medical HUD for quick identification of injured comrades, \ diff --git a/code/game/objects/items/devices/thermal_drill.dm b/code/game/objects/items/devices/thermal_drill.dm index ca8732f49b6..bb377b2692b 100644 --- a/code/game/objects/items/devices/thermal_drill.dm +++ b/code/game/objects/items/devices/thermal_drill.dm @@ -1,4 +1,10 @@ /obj/item/thermal_drill name = "thermal drill" - desc = "A tungsten carbide thermal drill with magnetic clamps for the purpose of drilling hardened objects." + desc = "A tungsten carbide thermal drill with magnetic clamps for the purpose of drilling hardened objects. Guaranteed 100% jam proof." icon = 'icons/obj/items.dmi' + icon_state = "hardened_drill" + +/obj/item/thermal_drill/diamond_drill + name = "diamond tipped thermal drill" + desc = "A diamond tipped thermal drill with magnetic clamps for the purpose of quickly drilling hardened objects. Guaranteed 100% jam proof." + icon_state = "diamond_drill" \ No newline at end of file diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm index 7cee3769888..7b5db776165 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -2,8 +2,12 @@ CONTAINS: SAFES FLOOR SAFES +Safe Codes +Safe Internals */ +var/list/global_safes = list() + //SAFES /obj/structure/safe name = "\improper Safe" @@ -13,7 +17,7 @@ FLOOR SAFES anchored = 1 density = 1 var/open = FALSE //is the safe open? - var/unlocked = FALSE + var/locked = TRUE var/tumbler_1_pos //the tumbler position- from 0 to 72 var/tumbler_1_open //the tumbler position to open at- 0 to 72 var/tumbler_2_pos @@ -23,9 +27,20 @@ FLOOR SAFES var/space = 0 //the combined w_class of everything in the safe var/maxspace = 24 //the maximum combined w_class of stuff in the safe var/combo_to_open //so admins know the code + var/obj/item/thermal_drill/drill = null + var/drill_timer + var/time_to_drill + var/image/bar + var/drill_start_time + var/datum/looping_sound/thermal_drill/soundloop + var/datum/effect_system/spark_spread/spark_system + var/drill_x_offset = -13 + var/drill_y_offset = -3 + var/knownby = list() /obj/structure/safe/New() + global_safes += src tumbler_2_pos = rand(0, 99) // first value in the combination set first tumbler_2_open = rand(0, 99) @@ -43,7 +58,12 @@ FLOOR SAFES if(num2 > 99) num2 = num2 - 100 - combo_to_open = "Go right past [num1] twice then stop at [num1]. Go left past [num2] once then stop at [num2]. Turn right till it stops and its open." + combo_to_open = "[num1] - [num2]" + + soundloop = new(list(src), FALSE) + spark_system = new /datum/effect_system/spark_spread() + spark_system.set_up(1, 0, src) + spark_system.attach(src) /obj/structure/safe/Initialize() ..() @@ -57,9 +77,9 @@ FLOOR SAFES /obj/structure/safe/proc/check_unlocked() if(tumbler_1_pos == tumbler_1_open && tumbler_2_pos == tumbler_2_open && dial == open_pos) - unlocked = TRUE + locked = FALSE return TRUE - unlocked = FALSE + locked = TRUE return FALSE /obj/structure/safe/proc/make_noise(turns, turns_total, tum1 = 0, tum2 = 0, mob/user, canhear) @@ -74,20 +94,63 @@ FLOOR SAFES to_chat(user, "You hear a [pick("tonk", "krunk", "plunk")] from [src].") if(tumbler_2_pos == tumbler_2_open && turns_total == 1 ) // You cant hear tumblers if you spin fast! to_chat(user, "You hear a [pick("tink", "krink", "plink")] from [src].") - if(unlocked) + if(!locked) if(user) visible_message("[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!") /obj/structure/safe/update_icon() if(open) - icon_state = "[initial(icon_state)]-open" + if(broken) + icon_state = "[initial(icon_state)]-open-broken" + else + icon_state = "[initial(icon_state)]-open" else - icon_state = initial(icon_state) + if(broken) + icon_state = "[initial(icon_state)]-broken" + else + icon_state = initial(icon_state) + overlays.Cut() + if(istype(drill, /obj/item/thermal_drill/diamond_drill)) + if(drill_timer) + overlays += image(icon = 'icons/effects/drill.dmi', icon_state = "[initial(icon_state)]_d-drill-on", pixel_x = drill_x_offset, pixel_y = drill_y_offset) + else + overlays += image(icon = 'icons/effects/drill.dmi', icon_state = "[initial(icon_state)]_d-drill-off", pixel_x = drill_x_offset, pixel_y = drill_y_offset) + else if(istype(drill, /obj/item/thermal_drill)) + if(drill_timer) + overlays += image(icon = 'icons/effects/drill.dmi', icon_state = "[initial(icon_state)]_h-drill-on", pixel_x = drill_x_offset, pixel_y = drill_y_offset) + else + overlays += image(icon = 'icons/effects/drill.dmi', icon_state = "[initial(icon_state)]_h-drill-off", pixel_x = drill_x_offset, pixel_y = drill_y_offset) /obj/structure/safe/attack_hand(mob/user) if(..()) return TRUE - ui_interact(user) + if(drill) + switch(alert("What would you like to do?", "Thermal Drill", "Turn [drill_timer ? "Off" : "On"]", "Remove Drill", "Cancel")) + if("Turn On") + if(do_after(user, 2 SECONDS, target = src)) + drill_timer = addtimer(CALLBACK(src, .proc/drill_open), time_to_drill) + drill_start_time = world.time + soundloop.start() + update_icon() + processing_objects.Add(src) + if("Turn Off") + if(do_after(user, 2 SECONDS, target = src)) + deltimer(drill_timer) + drill_timer = null + soundloop.stop() + update_icon() + processing_objects.Remove(src) + if("Remove Drill") + if(drill_timer) + to_chat(user, "You cant remove the drill while it's running!") + else if(do_after(user, 2 SECONDS, target = src)) + user.put_in_hands(drill) + drill = null + update_icon() + if("Cancel") + return + else + ui_interact(user) return /obj/structure/safe/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) @@ -109,7 +172,7 @@ FLOOR SAFES data["dial"] = dial data["open"] = open - data["unlocked"] = unlocked + data["locked"] = locked data["rotation"] = "[-dial*3.6]deg" data["contents"] = contents_names @@ -130,7 +193,7 @@ FLOOR SAFES canhear = 1 if(href_list["open"]) - if(check_unlocked() || open) + if(check_unlocked() || open || broken) to_chat(user, "You [open ? "close" : "open"] [src].") open = !open update_icon() @@ -143,6 +206,9 @@ FLOOR SAFES var/ticks = text2num(href_list["decrement"]) if(open) return + if(broken) + to_chat(user, "The dial will not turn, the mechanism is destroyed.") + return for(var/i=1 to ticks) if(!check_unlocked()) dial = Wrap(dial - 1, 0 ,100) @@ -162,6 +228,9 @@ FLOOR SAFES var/ticks = text2num(href_list["increment"]) if(open) return + if(broken) + to_chat(user, "The dial will not turn, the mechanism is destroyed.") + return for(var/i=1 to ticks) check_unlocked() dial = Wrap(dial + 1, 0, 100) @@ -194,7 +263,12 @@ FLOOR SAFES /obj/structure/safe/attackby(obj/item/I, mob/user, params) if(open) - if(I.w_class + space <= maxspace) + if(broken && istype(I, /obj/item/safe_internals) && do_after(user, 2 SECONDS, target = src)) + to_chat(user, "You replace the broken mechanism.") + qdel(I) + broken = !broken + update_icon() + else if(I.w_class + space <= maxspace) space += I.w_class if(!user.drop_item()) to_chat(user, "\The [I] is stuck to your hand, you cannot put it in the safe!") @@ -210,10 +284,31 @@ FLOOR SAFES if(istype(I, /obj/item/clothing/accessory/stethoscope)) to_chat(user, "Hold [I] in one of your hands while you manipulate the dial!") return + else if(istype(I, /obj/item/thermal_drill)) + if(drill) + to_chat(user, "There is already a drill attached!") + else if(do_after(user, 2 SECONDS, target = src)) + if(!user.drop_item()) + to_chat(user, "\The [I] is stuck to your hand, you cannot put it in the safe!") + return + I.loc = src + drill = I + if(istype(drill, /obj/item/thermal_drill/diamond_drill)) + time_to_drill = 150 SECONDS + else + time_to_drill = 300 SECONDS + update_icon() else to_chat(user, "You can't put [I] in into the safe while it is closed!") return +/obj/structure/safe/proc/drill_open() + broken = TRUE + drill_timer = null + soundloop.stop() + update_icon() + processing_objects.Remove(src) + return /obj/structure/safe/blob_act() return @@ -224,6 +319,24 @@ FLOOR SAFES /obj/structure/safe/examine_status(mob/user) return +/obj/structure/safe/Destroy() + global_safes -= src + QDEL_NULL(soundloop) + QDEL_NULL(spark_system) + return ..() + +/obj/structure/safe/process() + if(drill_timer) + overlays -= bar + bar = image('icons/effects/progessbar.dmi', src, "prog_bar_[round((((world.time - drill_start_time) / time_to_drill) * 100), 5)]", HUD_LAYER) + overlays += bar + if(prob(15)) + spark_system.start() + +/obj/structure/safe/examine(mob/user) + ..() + to_chat(user, "On the inside of the the door is [combo_to_open]") + //FLOOR SAFES /obj/structure/safe/floor name = "floor safe" @@ -231,13 +344,35 @@ FLOOR SAFES density = 0 level = 1 //underfloor layer = 2.5 - + drill_x_offset = -1 + drill_y_offset = 20 /obj/structure/safe/floor/Initialize() ..() var/turf/T = loc hide(T.intact) - /obj/structure/safe/floor/hide(var/intact) - invisibility = intact ? 101 : 0 \ No newline at end of file + invisibility = intact ? 101 : 0 + +/obj/item/safe_internals + name = "safe internals" + desc = "The mechanism and locking bolts for a Scarborough Arms - 2 tumbler safe" + icon_state = "safe_internals" + +/obj/item/paper/safe_code + name = "safe codes" + var/owner + info = "