diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 2c4463928c..cf5b9ce197 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -34,7 +34,8 @@ var/delivery_icon = "deliverycloset" //which icon to use when packagewrapped. null to be unwrappable. var/anchorable = TRUE var/icon_welded = "welded" - + var/obj/item/electronics/airlock/lockerelectronics //Installed electronics + var/lock_in_use = FALSE //Someone is doing some stuff with the lock here, better not proceed further /obj/structure/closet/Initialize(mapload) . = ..() @@ -42,47 +43,56 @@ PopulateContents() if(mapload && !opened) // if closed, any item at the crate's loc is put in the contents take_contents() + if(secure) + lockerelectronics = new(src) + lockerelectronics.accesses = req_access //USE THIS TO FILL IT, NOT INITIALIZE OR NEW /obj/structure/closet/proc/PopulateContents() return /obj/structure/closet/Destroy() - dump_contents() + dump_contents(override = FALSE) return ..() /obj/structure/closet/update_icon() cut_overlays() - if(!opened) + if(opened & icon_door_override) + add_overlay("[icon_door]_open") layer = OBJ_LAYER - if(icon_door) - add_overlay("[icon_door]_door") - else - add_overlay("[icon_state]_door") - if(welded) - add_overlay(icon_welded) - if(secure && !broken) - if(locked) - add_overlay("locked") - else - add_overlay("unlocked") - + return + else if(opened) + add_overlay("[icon_state]_open") + return + if(icon_door) + add_overlay("[icon_door]_door") else layer = BELOW_OBJ_LAYER - if(icon_door_override) - add_overlay("[icon_door]_open") - else - add_overlay("[icon_state]_open") + add_overlay("[icon_state]_door") + if(welded) + add_overlay("welded") + if(!secure) + return + if(broken) + add_overlay("off") + add_overlay("sparking") + else if(locked) + add_overlay("locked") + else + add_overlay("unlocked") /obj/structure/closet/examine(mob/user) ..() if(welded) - to_chat(user, "It's welded shut.") + to_chat(user, "It's welded shut.") if(anchored) to_chat(user, "It is bolted to the ground.") if(opened) to_chat(user, "The parts are welded together.") else if(secure && !opened) + else if(broken) + to_chat(user, "The lock is screwed in.") + else if(secure) to_chat(user, "Alt-click to [locked ? "unlock" : "lock"].") if(isliving(user)) var/mob/living/L = user @@ -117,9 +127,37 @@ return FALSE return TRUE -/obj/structure/closet/proc/dump_contents() +/obj/structure/closet/proc/can_lock(mob/living/user, var/check_access = TRUE) //set check_access to FALSE if you only need to check if a locker has a functional lock rather than access + if(!secure) + return FALSE + if(broken) + to_chat(user, "[src] is broken!") + return FALSE + if(QDELETED(lockerelectronics) && !locked) //We want to be able to unlock it regardless of electronics, but only lockable with electronics + to_chat(user, "[src] is missing locker electronics!") + return FALSE + if(!check_access) + return TRUE + if(allowed(user)) + return TRUE + to_chat(user, "Access denied.") + +/obj/structure/closet/proc/togglelock(mob/living/user) + add_fingerprint(user) + if(opened) + return + if(!can_lock(user)) + return + locked = !locked + user.visible_message("[user] [locked ? null : "un"]locks [src].", + "You [locked ? null : "un"]lock [src].") + update_icon() + +/obj/structure/closet/proc/dump_contents(var/override = TRUE) //Override is for not revealing the locker electronics when you open the locker, for example var/atom/L = drop_location() for(var/atom/movable/AM in src) + if(AM == lockerelectronics && override) + continue AM.forceMove(L) if(throwing) // you keep some momentum when getting out of a thrown closet step(AM, dir) @@ -207,6 +245,73 @@ else return open(user) +/obj/structure/closet/proc/bust_open() + welded = FALSE //applies to all lockers + locked = FALSE //applies to critter crates and secure lockers only + broken = TRUE //applies to secure lockers only + open() + +/obj/structure/closet/proc/handle_lock_addition(mob/user, obj/item/electronics/airlock/E) + add_fingerprint(user) + if(lock_in_use) + to_chat(user, "Wait for work on [src] to be done first!") + return + if(secure) + to_chat(user, "This locker already has a lock!") + return + if(broken) + to_chat(user, "Unscrew the broken lock first!") + return + if(!istype(E)) + return + user.visible_message("[user] begins installing a lock on [src]...","You begin installing a lock on [src]...") + lock_in_use = TRUE + playsound(loc, 'sound/items/screwdriver.ogg', 50, 1) + if(!do_after(user, 60, target = src)) + lock_in_use = FALSE + return + lock_in_use = FALSE + to_chat(user, "You finish the lock on [src]!") + E.forceMove(src) + lockerelectronics = E + req_access = E.accesses + secure = TRUE + update_icon() + return TRUE + +/obj/structure/closet/proc/handle_lock_removal(mob/user, obj/item/screwdriver/S) + if(lock_in_use) + to_chat(user, "Wait for work on [src] to be done first!") + return + if(locked) + to_chat(user, "Unlock it first!") + return + if(!secure) + to_chat(user, "[src] doesn't have a lock that you can remove!") + return + if(!istype(S)) + return + var/brokenword = broken ? "broken " : null + user.visible_message("You begin removing the [brokenword]lock on [src]...", "[user] begins removing the [brokenword]lock on [src]...") + playsound(loc, S.usesound, 50, 1) + lock_in_use = TRUE + if(!do_after(user, 100 * S.toolspeed, target = src)) + lock_in_use = FALSE + return + to_chat(user, "You remove the [brokenword]lock from [src]!") + if(!QDELETED(lockerelectronics)) + lockerelectronics.add_fingerprint(user) + lockerelectronics.forceMove(user.loc) + lockerelectronics = null + req_access = null + secure = FALSE + broken = FALSE + locked = FALSE + lock_in_use = FALSE + update_icon() + return TRUE + + /obj/structure/closet/deconstruct(disassembled = TRUE) if(ispath(material_drop) && material_drop_amount && !(flags_1 & NODECONSTRUCT_1)) new material_drop(loc, material_drop_amount) @@ -247,7 +352,11 @@ deconstruct(TRUE) return if(user.transferItemToLoc(W, drop_location())) // so we put in unlit welder too - return + return TRUE + else if(istype(W, /obj/item/electronics/airlock)) + handle_lock_addition(user, W) + else if(istype(W, /obj/item/screwdriver)) + handle_lock_removal(user, W) else if(istype(W, /obj/item/weldingtool) && can_weld_shut) if(!W.tool_start_check(user, amount=0)) return @@ -258,7 +367,7 @@ return welded = !welded after_weld(welded) - user.visible_message("[user] [welded ? "welds shut" : "unwelded"] \the [src].", + user.visible_message("[user] [welded ? "welds shut" : "unwelds"] \the [src].", "You [welded ? "weld" : "unwelded"] \the [src] with \the [W].", "You hear welding.") update_icon() @@ -401,20 +510,12 @@ if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded. to_chat(user, "You fail to break out of [src]!") -/obj/structure/closet/proc/bust_open() - welded = FALSE //applies to all lockers - locked = FALSE //applies to critter crates and secure lockers only - broken = TRUE //applies to secure lockers only - open() - /obj/structure/closet/AltClick(mob/user) ..() - if(!user.canUseTopic(src, BE_CLOSE) || !isturf(loc)) + if(!user.canUseTopic(src, be_close=TRUE) || !isturf(loc)) + to_chat(user, "You can't do that right now!") return - if(opened || !secure) - return - else - togglelock(user) + togglelock(user) /obj/structure/closet/CtrlShiftClick(mob/living/user) if(!HAS_TRAIT(user, TRAIT_SKITTISH)) @@ -423,20 +524,6 @@ return dive_into(user) -/obj/structure/closet/proc/togglelock(mob/living/user, silent) - if(secure && !broken) - if(allowed(user)) - if(iscarbon(user)) - add_fingerprint(user) - locked = !locked - user.visible_message("[user] [locked ? null : "un"]locks [src].", - "You [locked ? null : "un"]lock [src].") - update_icon() - else if(!silent) - to_chat(user, "Access Denied") - else if(secure && broken) - to_chat(user, "\The [src] is broken!") - /obj/structure/closet/emag_act(mob/user) if(secure && !broken) user.visible_message("Sparks fly from [src]!", @@ -445,6 +532,9 @@ playsound(src, "sparks", 50, 1) broken = TRUE locked = FALSE + if(!QDELETED(lockerelectronics)) + qdel(lockerelectronics) + lockerelectronics = null update_icon() /obj/structure/closet/get_remote_view_fullscreens(mob/user) @@ -458,16 +548,19 @@ if (!(. & EMP_PROTECT_CONTENTS)) for(var/obj/O in src) O.emp_act(severity) - if(secure && !broken && !(. & EMP_PROTECT_SELF)) - if(prob(50 / severity)) - locked = !locked - update_icon() - if(prob(20 / severity) && !opened) - if(!locked) - open() - else - req_access = list() - req_access += pick(get_all_accesses()) + if(!secure || broken) + return ..() + if(prob(50 / severity)) + locked = !locked + update_icon() + if(prob(20 / severity) && !opened) + if(!locked) + open() + else + req_access = list() + req_access += pick(get_all_accesses()) + if(!QDELETED(lockerelectronics)) + lockerelectronics.accesses = req_access /obj/structure/closet/contents_explosion(severity, target) for(var/atom/A in contents) diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm index 502b23354c..1c34850274 100644 --- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm +++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm @@ -49,6 +49,12 @@ return 1 return 0 +/obj/structure/closet/body_bag/handle_lock_addition() + return + +/obj/structure/closet/body_bag/handle_lock_removal() + return + /obj/structure/closet/body_bag/MouseDrop(over_object, src_location, over_location) . = ..() if(over_object == usr && Adjacent(usr) && (in_range(src, usr) || usr.contents.Find(src))) diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm index 82b0d1a441..aad68b2166 100644 --- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm +++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm @@ -57,6 +57,11 @@ I.alpha = 0 animate(I, pixel_z = 32, alpha = 255, time = 5, easing = ELASTIC_EASING) +/obj/structure/closet/cardboard/handle_lock_addition() //Whoever heard of a lockable cardboard box anyway + return + +/obj/structure/closet/cardboard/handle_lock_removal() + return /obj/structure/closet/cardboard/metal name = "large metal box" diff --git a/code/game/objects/structures/crates_lockers/closets/job_closets.dm b/code/game/objects/structures/crates_lockers/closets/job_closets.dm index d6d2f18e5a..d2ab9ea6fb 100644 --- a/code/game/objects/structures/crates_lockers/closets/job_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/job_closets.dm @@ -358,3 +358,8 @@ new /obj/item/clothing/shoes/workboots/mining(src) new /obj/item/storage/backpack/satchel/explorer(src) +/obj/structure/closet/coffin/handle_lock_addition() + return + +/obj/structure/closet/coffin/handle_lock_removal() + return diff --git a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm index eb764fc230..e44d3c9079 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm @@ -4,6 +4,18 @@ req_access = list(ACCESS_ALL_PERSONAL_LOCKERS) var/registered_name = null +/obj/structure/closet/secure_closet/personal/examine(mob/user) + ..() + if(registered_name) + to_chat(user, "The display reads, \"Owned by [registered_name]\".") + +/obj/structure/closet/secure_closet/personal/check_access(obj/item/card/id/I) + . = ..() + if(!I || !istype(I)) + return + if(registered_name == I.registered_name) + return TRUE + /obj/structure/closet/secure_closet/personal/PopulateContents() ..() if(prob(50)) @@ -33,21 +45,21 @@ /obj/structure/closet/secure_closet/personal/attackby(obj/item/W, mob/user, params) var/obj/item/card/id/I = W.GetID() - if(istype(I)) - if(broken) - to_chat(user, "It appears to be broken.") - return - if(!I || !I.registered_name) - return - if(allowed(user) || !registered_name || (istype(I) && (registered_name == I.registered_name))) - //they can open all lockers, or nobody owns this, or they own this locker - locked = !locked - update_icon() - - if(!registered_name) - registered_name = I.registered_name - desc = "Owned by [I.registered_name]." - else - to_chat(user, "Access Denied.") - else + if(!I || !istype(I)) return ..() + if(!can_lock(user, FALSE)) //Can't do anything if there isn't a lock! + return + if(I.registered_name && !registered_name) + to_chat(user, "You claim [src].") + registered_name = I.registered_name + else + ..() + +/obj/structure/closet/secure_closet/personal/handle_lock_addition() //If lock construction is successful we don't care what access the electronics had, so we override it + if(..()) + req_access = list(ACCESS_ALL_PERSONAL_LOCKERS) + lockerelectronics.accesses = req_access + +/obj/structure/closet/secure_closet/personal/handle_lock_removal() + if(..()) + registered_name = null diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 067b1b0eb1..6caa7d834b 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -54,6 +54,12 @@ manifest = null update_icon() +/obj/structure/closet/crate/handle_lock_addition() + return + +/obj/structure/closet/crate/handle_lock_removal() + return + /obj/structure/closet/crate/proc/tear_manifest(mob/user) to_chat(user, "You tear the manifest off of [src].") playsound(src, 'sound/items/poster_ripped.ogg', 75, 1) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 7cf8defc0f..b529d826c9 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -747,6 +747,12 @@ Difficulty: Very Hard /obj/structure/closet/stasis/ex_act() return +/obj/structure/closet/stasis/handle_lock_addition() + return + +/obj/structure/closet/stasis/handle_lock_removal() + return + /obj/effect/proc_holder/spell/targeted/exit_possession name = "Exit Possession" desc = "Exits the body you are possessing."