mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-19 20:15:47 +01:00
Secure safe, secure briefcase, and vaults improvements (#93085)
Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
This commit is contained in:
@@ -18,7 +18,14 @@ FLOOR SAFES
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
obj_flags = CONDUCTS_ELECTRICITY
|
||||
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT
|
||||
custom_materials = list(
|
||||
/datum/material/metalhydrogen = SHEET_MATERIAL_AMOUNT*10,
|
||||
/datum/material/alloy/plastitanium = SHEET_MATERIAL_AMOUNT*5,
|
||||
)
|
||||
material_flags = MATERIAL_EFFECTS
|
||||
|
||||
/// The maximum combined w_class of stuff in the safe
|
||||
var/maxspace = 24
|
||||
/// The amount of tumblers that will be generated
|
||||
@@ -41,14 +48,26 @@ FLOOR SAFES
|
||||
/obj/structure/safe/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
update_appearance(UPDATE_ICON)
|
||||
var/static/list/tool_behaviors = list(
|
||||
TOOL_WRENCH = list(
|
||||
SCREENTIP_CONTEXT_LMB = "Reset lock",
|
||||
),
|
||||
)
|
||||
AddElement(/datum/element/contextual_screentip_tools, tool_behaviors)
|
||||
|
||||
// Combination generation
|
||||
for(var/iterating in 1 to number_of_tumblers)
|
||||
tumblers.Add(rand(0, 99))
|
||||
|
||||
if(!mapload)
|
||||
if(density)
|
||||
AddElement(/datum/element/climbable)
|
||||
AddElement(/datum/element/elevation, pixel_shift = 22)
|
||||
|
||||
if(open && !locked)
|
||||
return
|
||||
|
||||
update_appearance(UPDATE_ICON)
|
||||
|
||||
// Put as many items on our turf inside as possible
|
||||
for(var/obj/item/inserting_item in loc)
|
||||
if(space >= maxspace)
|
||||
@@ -57,11 +76,46 @@ FLOOR SAFES
|
||||
space += inserting_item.w_class
|
||||
inserting_item.forceMove(src)
|
||||
|
||||
/obj/structure/safe/examine(mob/user)
|
||||
. = ..()
|
||||
. += span_notice("The locking mechanism gears are <b>wrenched</b> in place.")
|
||||
|
||||
/obj/structure/safe/update_icon_state()
|
||||
//uses the same icon as the captain's spare safe (therefore lockable storage) so keep it in line with that
|
||||
icon_state = "[initial(icon_state)][open ? null : "_locked"]"
|
||||
return ..()
|
||||
|
||||
/obj/structure/safe/wrench_act(mob/living/user, obj/item/tool)
|
||||
if(!open)
|
||||
balloon_alert(user, "must be open!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
balloon_alert(user, "resetting lock...")
|
||||
to_chat(user, span_notice("You begin resetting the lock for [src]. You'll need to set [number_of_tumblers] numbers."))
|
||||
|
||||
var/list/new_tumblers = list()
|
||||
for(var/tumbler_index in 1 to number_of_tumblers)
|
||||
var/input_value = tgui_input_number(user, "Set tumbler #[tumbler_index] (0-99):", "Set Lock", 0, 99, 0)
|
||||
if(isnull(input_value))
|
||||
balloon_alert(user, "reset cancelled!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!user.can_perform_action(src))
|
||||
balloon_alert(user, "reset interrupted!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
new_tumblers.Add(input_value)
|
||||
|
||||
tool.play_tool_sound(src)
|
||||
if(!do_after(user, 10 SECONDS, target = src))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
tumblers = new_tumblers
|
||||
current_tumbler_index = 1
|
||||
dial = 0
|
||||
tool.play_tool_sound(src)
|
||||
to_chat(user, span_notice("You successfully reset the lock for [src]. The new combination is: [tumblers.Join("-")]."))
|
||||
balloon_alert(user, "lock set!")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/structure/safe/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers)
|
||||
if(open)
|
||||
. = TRUE //no afterattack
|
||||
@@ -238,6 +292,10 @@ FLOOR SAFES
|
||||
if(total_ticks == 1 || prob(SOUND_CHANCE))
|
||||
balloon_alert(user, pick(sounds))
|
||||
|
||||
/obj/structure/safe/open
|
||||
open = TRUE
|
||||
locked = FALSE
|
||||
|
||||
//FLOOR SAFES
|
||||
/obj/structure/safe/floor
|
||||
name = "floor safe"
|
||||
@@ -249,6 +307,10 @@ FLOOR SAFES
|
||||
. = ..()
|
||||
AddElement(/datum/element/undertile)
|
||||
|
||||
/obj/structure/safe/floor/open
|
||||
open = TRUE
|
||||
locked = FALSE
|
||||
|
||||
///Special safe for the station's vault. Not explicitly required, but the piggy bank inside it is.
|
||||
/obj/structure/safe/vault
|
||||
|
||||
|
||||
@@ -6,6 +6,16 @@
|
||||
base_icon_state = "wall_safe"
|
||||
result_path = /obj/structure/secure_safe
|
||||
pixel_shift = 32
|
||||
w_class = WEIGHT_CLASS_GIGANTIC
|
||||
obj_flags = CONDUCTS_ELECTRICITY
|
||||
resistance_flags = FIRE_PROOF
|
||||
custom_materials = list(
|
||||
/datum/material/alloy/plasteel = SHEET_MATERIAL_AMOUNT*5,
|
||||
/datum/material/titanium = SHEET_MATERIAL_AMOUNT*3,
|
||||
)
|
||||
material_flags = MATERIAL_EFFECTS
|
||||
/// The lock code transferred from the structure
|
||||
var/stored_lock_code
|
||||
|
||||
/obj/item/wallframe/secure_safe/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -13,12 +23,55 @@
|
||||
max_specific_storage = WEIGHT_CLASS_GIGANTIC,
|
||||
max_total_storage = 20,
|
||||
)
|
||||
atom_storage.set_locked(STORAGE_FULLY_LOCKED)
|
||||
if(stored_lock_code && !(obj_flags & EMAGGED))
|
||||
atom_storage.set_locked(STORAGE_FULLY_LOCKED)
|
||||
update_appearance()
|
||||
|
||||
/obj/item/wallframe/secure_safe/after_attach(obj/attached_to)
|
||||
/obj/item/wallframe/secure_safe/update_icon_state()
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
icon_state = "[base_icon_state]_broken"
|
||||
else
|
||||
icon_state = "[base_icon_state][stored_lock_code ? "_locked" : null]"
|
||||
|
||||
/obj/item/wallframe/secure_safe/emag_act(mob/user, obj/item/card/emag/emag_card)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return FALSE
|
||||
|
||||
obj_flags |= EMAGGED
|
||||
visible_message(span_warning("Sparks fly from [src]!"), blind_message = span_hear("You hear a faint electrical spark."))
|
||||
balloon_alert(user, "lock destroyed")
|
||||
playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
stored_lock_code = null
|
||||
atom_storage.locked = STORAGE_NOT_LOCKED
|
||||
update_appearance()
|
||||
return TRUE
|
||||
|
||||
/obj/item/wallframe/secure_safe/after_attach(obj/structure/secure_safe/safe)
|
||||
if(!istype(safe))
|
||||
return ..()
|
||||
|
||||
for(var/obj/item in contents)
|
||||
item.forceMove(attached_to)
|
||||
item.forceMove(safe)
|
||||
|
||||
var/datum/component/lockable_storage/storage_component = safe.GetComponent(/datum/component/lockable_storage)
|
||||
if(stored_lock_code)
|
||||
storage_component?.set_lock_code(stored_lock_code)
|
||||
|
||||
if(obj_flags & EMAGGED)
|
||||
storage_component?.break_lock()
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/armor/secure_safe
|
||||
melee = 30
|
||||
bullet = 30
|
||||
laser = 20
|
||||
energy = 20
|
||||
bomb = 30
|
||||
fire = 95
|
||||
acid = 30
|
||||
|
||||
/**
|
||||
* Wall safes
|
||||
@@ -33,21 +86,47 @@
|
||||
base_icon_state = "wall_safe"
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
resistance_flags = FIRE_PROOF
|
||||
obj_flags = CONDUCTS_ELECTRICITY
|
||||
armor_type = /datum/armor/secure_safe
|
||||
max_integrity = 300
|
||||
damage_deflection = 21
|
||||
custom_materials = list(
|
||||
/datum/material/alloy/plasteel = SHEET_MATERIAL_AMOUNT*5,
|
||||
/datum/material/titanium = SHEET_MATERIAL_AMOUNT*3,
|
||||
)
|
||||
material_flags = MATERIAL_EFFECTS
|
||||
/// The lock code used to open the safe
|
||||
var/stored_lock_code
|
||||
|
||||
MAPPING_DIRECTIONAL_HELPERS(/obj/structure/secure_safe, 32)
|
||||
|
||||
/obj/structure/secure_safe/Initialize(mapload)
|
||||
. = ..()
|
||||
//this will create the storage for us.
|
||||
AddComponent(/datum/component/lockable_storage)
|
||||
AddComponent(/datum/component/lockable_storage, stored_lock_code)
|
||||
|
||||
if(!density)
|
||||
find_and_hang_on_wall()
|
||||
if(mapload)
|
||||
PopulateContents()
|
||||
|
||||
RegisterSignal(src, COMSIG_LOCKABLE_STORAGE_SET_CODE, PROC_REF(update_lock_code))
|
||||
|
||||
/obj/structure/secure_safe/atom_deconstruct(disassembled)
|
||||
if(!density) //if we're a wall item, we'll drop a wall frame.
|
||||
var/obj/item/wallframe/secure_safe/new_safe = new(get_turf(src))
|
||||
|
||||
// Transfer lock code to the wallframe
|
||||
var/datum/component/lockable_storage/storage_component = GetComponent(/datum/component/lockable_storage)
|
||||
if(storage_component)
|
||||
new_safe.stored_lock_code = storage_component.lock_code
|
||||
|
||||
if(obj_flags & EMAGGED)
|
||||
new_safe.obj_flags |= EMAGGED
|
||||
|
||||
new_safe.update_appearance()
|
||||
|
||||
for(var/obj/item in contents)
|
||||
item.forceMove(new_safe)
|
||||
|
||||
@@ -55,6 +134,16 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/secure_safe, 32)
|
||||
new /obj/item/paper(src)
|
||||
new /obj/item/pen(src)
|
||||
|
||||
/obj/structure/secure_safe/proc/update_lock_code(obj/structure/secure_safe/safe, new_code)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
stored_lock_code = new_code
|
||||
|
||||
/obj/structure/secure_safe/ex_act(severity, target)
|
||||
if(severity <= EXPLODE_LIGHT)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/structure/secure_safe/hos
|
||||
name = "head of security's safe"
|
||||
|
||||
@@ -77,11 +166,13 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/secure_safe, 32)
|
||||
icon_state = "spare_safe"
|
||||
base_icon_state = "spare_safe"
|
||||
armor_type = /datum/armor/safe_caps_spare
|
||||
max_integrity = 300
|
||||
damage_deflection = 30 // prevents stealing the captain's spare using null rods/lavaland monsters/AP projectiles
|
||||
density = TRUE
|
||||
anchored_tabletop_offset = 6
|
||||
custom_materials = list(/datum/material/gold = SMALL_MATERIAL_AMOUNT)
|
||||
custom_materials = list(
|
||||
/datum/material/alloy/plasteel = SHEET_MATERIAL_AMOUNT*5,
|
||||
/datum/material/gold = SHEET_MATERIAL_AMOUNT*3,
|
||||
)
|
||||
material_flags = MATERIAL_EFFECTS
|
||||
|
||||
/datum/armor/safe_caps_spare
|
||||
|
||||
Reference in New Issue
Block a user