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 += "| [P.name] |
"
- dat += "
"
- 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 @@
+
+
+
+
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