diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm index 44c9da74b20..7cee3769888 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -6,29 +6,44 @@ FLOOR SAFES //SAFES /obj/structure/safe - name = "safe" + name = "\improper Safe" desc = "A huge chunk of metal with a dial embedded in it. Fine print on the dial reads \"Scarborough Arms - 2 tumbler safe, guaranteed thermite resistant, explosion resistant, and assistant resistant.\"" icon = 'icons/obj/structures.dmi' icon_state = "safe" anchored = 1 density = 1 - var/open = 0 //is the safe open? + var/open = FALSE //is the safe open? + var/unlocked = FALSE 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 var/tumbler_2_open + var/open_pos var/dial = 0 //where is the dial pointing? 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 /obj/structure/safe/New() - tumbler_1_pos = rand(0, 71) - tumbler_1_open = rand(0, 71) + tumbler_2_pos = rand(0, 99) // first value in the combination set first + tumbler_2_open = rand(0, 99) - tumbler_2_pos = rand(0, 71) - tumbler_2_open = rand(0, 71) + tumbler_1_pos = rand(0, 99) + do + tumbler_1_open = rand(0, 99) + while(tumbler_1_open > Wrap(tumbler_2_open +48, 0, 100) && tumbler_1_open < Wrap(tumbler_2_open + 53, 0, 100)) // prevents a combination that wont open + do + open_pos = rand(0,99) + while(open_pos > Wrap(tumbler_1_open - 2, 0, 100) && open_pos < Wrap(tumbler_1_open + 2, 0, 100)) // prevents a combination that wont open + var/num1 = tumbler_2_open + 54 + if(num1 > 99) + num1 = num1 - 100 + var/num2 = tumbler_1_open + 98 + 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." /obj/structure/safe/Initialize() ..() @@ -40,31 +55,28 @@ FLOOR SAFES I.loc = src -/obj/structure/safe/proc/check_unlocked(mob/user, canhear) +/obj/structure/safe/proc/check_unlocked() + if(tumbler_1_pos == tumbler_1_open && tumbler_2_pos == tumbler_2_open && dial == open_pos) + unlocked = TRUE + return TRUE + unlocked = FALSE + return FALSE + +/obj/structure/safe/proc/make_noise(turns, turns_total, tum1 = 0, tum2 = 0, mob/user, canhear) if(user && canhear) - if(tumbler_1_pos == tumbler_1_open) + if(turns == 2) + to_chat(user, "The sounds from [src] are too fast and blend together.") + if(tum1 && (turns_total == 1 || prob(10))) // So multi turns dont super spam the chat + to_chat(user, "You hear a [pick("clack", "scrape", "clank")] from [src].") + if(tum2 && (turns_total == 1 || prob(10))) // So multi turns dont super spam the chat + to_chat(user, "You hear a [pick("click", "chink", "clink")] from [src].") + if(tumbler_1_pos == tumbler_1_open && turns_total == 1) // You cant hear tumblers if you spin fast! to_chat(user, "You hear a [pick("tonk", "krunk", "plunk")] from [src].") - if(tumbler_2_pos == tumbler_2_open) + 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(tumbler_1_pos == tumbler_1_open && tumbler_2_pos == tumbler_2_open) - if(user) visible_message("[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!") - return 1 - return 0 - - -/obj/structure/safe/proc/decrement(num) - num -= 1 - if(num < 0) - num = 71 - return num - - -/obj/structure/safe/proc/increment(num) - num += 1 - if(num > 71) - num = 0 - return num - + if(unlocked) + if(user) + visible_message("[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!") /obj/structure/safe/update_icon() if(open) @@ -72,75 +84,112 @@ FLOOR SAFES else icon_state = initial(icon_state) - /obj/structure/safe/attack_hand(mob/user) - user.set_machine(src) - var/dat = "
" - dat += "[open ? "Close" : "Open"] [src] | - [dial * 5] +" + if(..()) + return TRUE + ui_interact(user) + return + +/obj/structure/safe/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "safe.tmpl", name, 600, 750) + ui.open() + ui.set_auto_update(1) + +/obj/structure/safe/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) + var/data[0] + var/list/contents_names = list() if(open) - dat += "" - for(var/i = contents.len, i>=1, i--) - var/obj/item/P = contents[i] - dat += "" - dat += "
[P.name]
" - user << browse("[name][dat]", "window=safe;size=350x300") + for(var/obj/O in contents) + contents_names[++contents_names.len] = list("name" = O.name, "index" = contents.Find(O), "sprite" = O.icon_state) + user << browse_rsc(icon(O.icon, O.icon_state), "[O.icon_state].png") + else + contents_names = list(list("name" = "you're"), list("name" = "a"), list("name" = "cheater")) + + data["dial"] = dial + data["open"] = open + data["unlocked"] = unlocked + data["rotation"] = "[-dial*3.6]deg" + data["contents"] = contents_names + + return data /obj/structure/safe/Topic(href, href_list) - if(!ishuman(usr)) return - var/mob/living/carbon/human/user = usr + if(..()) + return TRUE var/canhear = 0 + if(!ishuman(usr)) + to_chat(usr, "You don't have hands to operate the safe!") + return FALSE + + var/mob/living/carbon/human/user = usr if(istype(user.l_hand, /obj/item/clothing/accessory/stethoscope) || istype(user.r_hand, /obj/item/clothing/accessory/stethoscope)) canhear = 1 if(href_list["open"]) - if(check_unlocked()) + if(check_unlocked() || open) to_chat(user, "You [open ? "close" : "open"] [src].") open = !open update_icon() - updateUsrDialog() - return else - to_chat(user, "You can't [open ? "close" : "open"] [src], the lock is engaged!") - return + to_chat(user, "You can't open [src], the lock is engaged!") + .= TRUE + SSnanoui.update_uis(src) if(href_list["decrement"]) - dial = decrement(dial) - if(dial == tumbler_1_pos + 1 || dial == tumbler_1_pos - 71) - tumbler_1_pos = decrement(tumbler_1_pos) - if(canhear) - to_chat(user, "You hear a [pick("clack", "scrape", "clank")] from [src].") - if(tumbler_1_pos == tumbler_2_pos + 37 || tumbler_1_pos == tumbler_2_pos - 35) - tumbler_2_pos = decrement(tumbler_2_pos) - if(canhear) - to_chat(user, "You hear a [pick("click", "chink", "clink")] from [src].") - check_unlocked(user, canhear) - updateUsrDialog() - return + var/ticks = text2num(href_list["decrement"]) + if(open) + return + for(var/i=1 to ticks) + if(!check_unlocked()) + dial = Wrap(dial - 1, 0 ,100) + if(dial == tumbler_1_pos + 1 || dial == tumbler_1_pos - 99) + tumbler_1_pos = Wrap(tumbler_1_pos - 1, 0, 100) + make_noise(i, ticks, 1, 0, user, canhear) + if(tumbler_1_pos == tumbler_2_pos + 51 || tumbler_1_pos == tumbler_2_pos - 49) + tumbler_2_pos = Wrap(tumbler_2_pos - 1, 0, 100) + make_noise(0, ticks, 0, 1, user, canhear) + sleep(1) + check_unlocked() + SSnanoui.update_uis(src) + make_noise(0, 0, 0, 0, user, canhear) + .= TRUE if(href_list["increment"]) - dial = increment(dial) - if(dial == tumbler_1_pos - 1 || dial == tumbler_1_pos + 71) - tumbler_1_pos = increment(tumbler_1_pos) - if(canhear) - to_chat(user, "You hear a [pick("clack", "scrape", "clank")] from [src].") - if(tumbler_1_pos == tumbler_2_pos - 37 || tumbler_1_pos == tumbler_2_pos + 35) - tumbler_2_pos = increment(tumbler_2_pos) - if(canhear) - to_chat(user, "You hear a [pick("click", "chink", "clink")] from [src].") - check_unlocked(user, canhear) - updateUsrDialog() - return + var/ticks = text2num(href_list["increment"]) + if(open) + return + for(var/i=1 to ticks) + check_unlocked() + dial = Wrap(dial + 1, 0, 100) + if(dial == tumbler_1_pos - 1 || dial == tumbler_1_pos + 99) + tumbler_1_pos = Wrap(tumbler_1_pos + 1, 0, 100) + make_noise(i, ticks, 1, 0, user, canhear) + if(tumbler_1_pos == tumbler_2_pos - 51 || tumbler_1_pos == tumbler_2_pos + 49) + tumbler_2_pos = Wrap(tumbler_2_pos + 1, 0, 100) + make_noise(0, ticks, 0, 1, user, canhear) + sleep(1) + SSnanoui.update_uis(src) + make_noise(0, 0, 0, 0, user, canhear) + .= TRUE if(href_list["retrieve"]) - user << browse("", "window=safe") // Close the menu + var/index = text2num(href_list["retrieve"]) + if(index > 0 && index <= contents.len) + var/obj/item/P = contents[index] + if(open) + if(P && in_range(src, user)) + user.put_in_hands(P) + space -= P.w_class + SSnanoui.update_uis(src) + .= TRUE - var/obj/item/P = locate(href_list["retrieve"]) in src - if(open) - if(P && in_range(src, user)) - user.put_in_hands(P) - updateUsrDialog() + + updateUsrDialog() + return /obj/structure/safe/attackby(obj/item/I, mob/user, params) @@ -161,14 +210,19 @@ 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 + to_chat(user, "You can't put [I] in into the safe while it is closed!") + return -obj/structure/safe/blob_act() +/obj/structure/safe/blob_act() return -obj/structure/safe/ex_act(severity) +/obj/structure/safe/ex_act(severity) return +/obj/structure/safe/examine_status(mob/user) + return //FLOOR SAFES /obj/structure/safe/floor diff --git a/nano/images/Scarborough Arms.svg b/nano/images/Scarborough Arms.svg new file mode 100644 index 00000000000..cf164903bdf --- /dev/null +++ b/nano/images/Scarborough Arms.svg @@ -0,0 +1,75 @@ + + + + + + + + + + image/svg+xml + + + + + + + SA + + diff --git a/nano/images/safe_dial.png b/nano/images/safe_dial.png new file mode 100644 index 00000000000..de24f16b670 Binary files /dev/null and b/nano/images/safe_dial.png differ diff --git a/nano/templates/safe.tmpl b/nano/templates/safe.tmpl new file mode 100644 index 00000000000..e0c98215737 --- /dev/null +++ b/nano/templates/safe.tmpl @@ -0,0 +1,62 @@ + + + +{{if data.open}} +
+
+
{{:helper.link('Close', 'caret-square-o-up', {'open': 1})}}
+
+
+
+ {{for data.contents}} +
+ {{:helper.link(value.name, 'arrow-left', {'retrieve': value.index})}} +
+ {{/for}} +
+{{else}} +
+
+
{{:helper.link('Open', 'caret-square-o-down', {'open': 1})}}
+
+
+
+
+
{{:helper.link('Left 50', 'arrow-left', {'increment': 50})}}
+
{{:helper.link('Left 10', 'arrow-left', {'increment': 10})}}
+
{{:helper.link('Left 1', 'arrow-left', {'increment': 1})}}
+
+ {{if data.unlocked}} +
{{:helper.link('Right 1', 'arrow-right', null, 'disabled')}}
+
{{:helper.link('Right 10', 'arrow-right', null, 'disabled')}}
+
{{:helper.link('Right 100', 'arrow-right', null, 'disabled')}}
+ {{else}} +
{{:helper.link('Right 1', 'arrow-right', {'decrement': 1})}}
+
{{:helper.link('Right 10', 'arrow-right', {'decrement': 10})}}
+
{{:helper.link('Right 50', 'arrow-right', {'decrement': 50})}}
+ {{/if}} +
+
+
+ +
+
+
+
+
+
How to open your Scarborough Arms - 2 tumbler safe
+
+
1. Turn the dial to the right past the first number twice
+
2. Stop at the first number
+
3. Turn the dial to the left past the second number once
+
4. Stop at the second number
+
5. Turn to the right until the dial stops
+
6. Open the safe
+
+
To lock fully, turn the dial to the left for three rotations
+
+{{/if}} \ No newline at end of file