diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 1dc8336ae6..e3b9b18840 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -9,18 +9,26 @@ var/icon_closed = "closed" var/icon_opened = "open" var/opened = 0 - var/welded = 0 + var/sealed = 0 + var/seal_tool = /obj/item/weapon/weldingtool //Tool used to seal the closet, defaults to welder var/wall_mounted = 0 //never solid (You can always pass over it) var/health = 100 + var/breakout = 0 //if someone is currently breaking out. mutex + var/breakout_time = 2 //2 minutes by default + var/breakout_sound = 'sound/effects/grillehit.ogg' //Sound that plays while breaking out + var/storage_capacity = 2 * MOB_MEDIUM //This is so that someone can't pack hundreds of items in a locker/crate //then open it in a populated area to crash clients. + var/storage_cost = 40 //How much space this closet takes up if it's stuffed in another closet + var/open_sound = 'sound/machines/click.ogg' var/close_sound = 'sound/machines/click.ogg' - var/store_misc = 1 - var/store_items = 1 - var/store_mobs = 1 + var/store_misc = 1 //Chameleon item check + var/store_items = 1 //Will the closet store items? + var/store_mobs = 1 //Will the closet store mobs? + var/max_closets = 0 //Number of other closets allowed on tile before it won't close. var/list/starts_with @@ -41,7 +49,7 @@ content_size += Ceiling(I.w_class/2) if(content_size > storage_capacity-5) storage_capacity = content_size + 5 - + update_icon() /obj/structure/closet/examine(mob/user) if(..(user, 1) && !opened) @@ -50,29 +58,33 @@ if(!I.anchored) content_size += Ceiling(I.w_class/2) if(!content_size) - user << "It is empty." + to_chat(user, "It is empty.") else if(storage_capacity > content_size*4) - user << "It is barely filled." + to_chat(user, "It is barely filled.") else if(storage_capacity > content_size*2) - user << "It is less than half full." + to_chat(user, "It is less than half full.") else if(storage_capacity > content_size) - user << "There is still some free space." + to_chat(user, "There is still some free space.") else - user << "It is full." + to_chat(user, "It is full.") /obj/structure/closet/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) if(air_group || (height==0 || wall_mounted)) return 1 return (!density) /obj/structure/closet/proc/can_open() - if(src.welded) + if(src.sealed) return 0 return 1 /obj/structure/closet/proc/can_close() + var/closet_count = 0 for(var/obj/structure/closet/closet in get_turf(src)) if(closet != src) - return 0 + if(!closet.anchored) + closet_count ++ + if(closet_count > max_closets) + return 0 return 1 /obj/structure/closet/proc/dump_contents() @@ -101,7 +113,7 @@ src.icon_state = src.icon_opened src.opened = 1 playsound(src.loc, open_sound, 15, 1, -3) - density = 0 + density = !density return 1 /obj/structure/closet/proc/close() @@ -118,12 +130,14 @@ stored_units += store_items(stored_units) if(store_mobs) stored_units += store_mobs(stored_units) + if(max_closets) + stored_units += store_closets(stored_units) src.icon_state = src.icon_closed src.opened = 0 playsound(src.loc, close_sound, 15, 1, -3) - density = 1 + density = !density return 1 //Cham Projector Exception @@ -161,9 +175,25 @@ added_units += M.mob_size return added_units +/obj/structure/closet/proc/store_closets(var/stored_units) + var/added_units = 0 + for(var/obj/structure/closet/C in src.loc) + if(C == src) //Don't store ourself + continue + if(C.anchored) //Don't worry about anchored things on the same tile + continue + if(C.max_closets) //Prevents recursive storage + continue + if(stored_units + added_units + storage_cost > storage_capacity) + break + C.forceMove(src) + added_units += storage_cost + return added_units + + /obj/structure/closet/proc/toggle(mob/user as mob) if(!(src.opened ? src.close() : src.open())) - user << "It won't budge!" + to_chat(user, "It won't budge!") return update_icon() @@ -221,7 +251,7 @@ if(!WT.isOn()) return else - user << "You need more welding fuel to complete this task." + to_chat(user, "You need more welding fuel to complete this task.") return playsound(src, WT.usesound, 50) new /obj/item/stack/material/steel(src.loc) @@ -247,21 +277,25 @@ W.forceMove(src.loc) else if(istype(W, /obj/item/weapon/packageWrap)) return - else if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(!WT.remove_fuel(0,user)) - if(!WT.isOn()) - return - else - user << "You need more welding fuel to complete this task." - return - playsound(src, WT.usesound, 50) - src.welded = !src.welded - src.update_icon() - for(var/mob/M in viewers(src)) - M.show_message("[src] has been [welded?"welded shut":"unwelded"] by [user.name].", 3, "You hear welding.", 2) + else if(seal_tool) + if(istype(W, seal_tool)) + var/obj/item/weapon/S = W + if(istype(S, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = S + if(!WT.remove_fuel(0,user)) + if(!WT.isOn()) + return + else + to_chat(user, "You need more welding fuel to complete this task.") + return + if(do_after(user, 20 * S.toolspeed)) + playsound(src, S.usesound, 50) + src.sealed = !src.sealed + src.update_icon() + for(var/mob/M in viewers(src)) + M.show_message("[src] has been [sealed?"sealed":"unsealed"] by [user.name].", 3) else if(W.is_wrench()) - if(welded) + if(sealed) if(anchored) user.visible_message("\The [user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.") else @@ -269,7 +303,7 @@ playsound(src, W.usesound, 50) if(do_after(user, 20 * W.toolspeed)) if(!src) return - user << "You [anchored? "un" : ""]secured \the [src]!" + to_chat(user, "You [anchored? "un" : ""]secured \the [src]!") anchored = !anchored else src.attack_hand(user) @@ -305,7 +339,7 @@ return if(!src.open()) - user << "It won't budge!" + to_chat(user, "It won't budge!") /obj/structure/closet/attack_hand(mob/user as mob) src.add_fingerprint(user) @@ -315,7 +349,7 @@ /obj/structure/closet/attack_self_tk(mob/user as mob) src.add_fingerprint(user) if(!src.toggle()) - usr << "It won't budge!" + to_chat(usr, "It won't budge!") /obj/structure/closet/attack_ghost(mob/ghost) if(ghost.client && ghost.client.inquisitive_ghost) @@ -335,14 +369,14 @@ src.add_fingerprint(usr) src.toggle(usr) else - usr << "This mob type can't use this verb." + to_chat(usr, "This mob type can't use this verb.") -/obj/structure/closet/update_icon()//Putting the welded stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot) +/obj/structure/closet/update_icon()//Putting the sealed stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot) overlays.Cut() if(!opened) icon_state = icon_closed - if(welded) - overlays += "welded" + if(sealed) + overlays += "sealed" else icon_state = icon_opened @@ -358,20 +392,19 @@ /obj/structure/closet/proc/req_breakout() if(opened) return 0 //Door's open... wait, why are you in it's contents then? - if(!welded) - return 0 //closed but not welded... + if(!sealed) + return 0 //closed but not sealed... return 1 /obj/structure/closet/proc/mob_breakout(var/mob/living/escapee) - var/breakout_time = 2 //2 minutes by default if(breakout || !req_breakout()) return escapee.setClickCooldown(100) - //okay, so the closet is either welded or locked... resist!!! - escapee << "You lean on the back of \the [src] and start pushing the door open. (this will take about [breakout_time] minutes)" + //okay, so the closet is either sealed or locked... resist!!! + to_chat(escapee, "You lean on the back of \the [src] and start pushing the door open. (this will take about [breakout_time] minutes)") visible_message("\The [src] begins to shake violently!") @@ -388,20 +421,20 @@ breakout = 0 return - playsound(src.loc, 'sound/effects/grillehit.ogg', 100, 1) + playsound(src.loc, breakout_sound, 100, 1) animate_shake() add_fingerprint(escapee) //Well then break it! breakout = 0 - escapee << "You successfully break out!" + to_chat(escapee, "You successfully break out!") visible_message("\The [escapee] successfully broke out of \the [src]!") - playsound(src.loc, 'sound/effects/grillehit.ogg', 100, 1) + playsound(src.loc, breakout_sound, 100, 1) break_open() animate_shake() /obj/structure/closet/proc/break_open() - welded = 0 + sealed = 0 update_icon() //Do this to prevent contents from being opened into nullspace (read: bluespace) if(istype(loc, /obj/structure/bigDelivery)) @@ -420,3 +453,9 @@ /obj/structure/closet/AllowDrop() return TRUE + +/obj/structure/closet/return_air_for_internal_lifeform(var/mob/living/L) + if(src.loc) + if(istype(src.loc, /obj/structure/closet)) + return (loc.return_air_for_internal_lifeform(L)) + return return_air() \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/coffin.dm b/code/game/objects/structures/crates_lockers/closets/coffin.dm index 67de5d38b9..6d5df80ed8 100644 --- a/code/game/objects/structures/crates_lockers/closets/coffin.dm +++ b/code/game/objects/structures/crates_lockers/closets/coffin.dm @@ -4,9 +4,161 @@ icon_state = "coffin" icon_closed = "coffin" icon_opened = "coffin_open" + seal_tool = /obj/item/weapon/tool/screwdriver + breakout_sound = 'sound/weapons/tablehit1.ogg' /obj/structure/closet/coffin/update_icon() if(!opened) icon_state = icon_closed else icon_state = icon_opened + +/* Graves */ +/obj/structure/closet/grave + name = "grave" + desc = "Dirt." + icon_state = "grave" + icon_closed = "grave" + icon_opened = "grave_open" + seal_tool = null + breakout_sound = 'sound/weapons/thudswoosh.ogg' + anchored = 1 + max_closets = 1 + opened = 1 + +/obj/structure/closet/grave/attack_hand(mob/user as mob) + if(opened) + visible_message("[user] starts to climb into \the [src.name].", \ + "You start to lower yourself into \the [src.name].") + if(do_after(user, 50)) + user.forceMove(src.loc) + visible_message("[user] climbs into \the [src.name].", \ + "You climb into \the [src.name].") + else + visible_message("[user] decides not to climb into \the [src.name].", \ + "You stop climbing into \the [src.name].") + return + +/obj/structure/closet/grave/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(opened && ismob(mover)) + var/mob/M = mover + add_fingerprint(M) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.m_intent == "walk") + to_chat(H, "You stop at the edge of \the [src.name].") + return FALSE + else + to_chat(H, "You fall into \the [src.name]!") + fall_in(H) + return TRUE + if(isrobot(M)) + var/mob/living/silicon/robot/R = M + if(R.a_intent == I_HELP) + to_chat(R, "You stop at the edge of \the [src.name].") + return FALSE + else + to_chat(R, "You enter \the [src.name].") + return TRUE + return TRUE //Everything else can move over the graves + +/obj/structure/closet/grave/proc/fall_in(mob/living/L) //Only called on humans for now, but still + L.Weaken(5) + if(ishuman(L)) + var/mob/living/carbon/human/H = L + var/limb_damage = rand(5,25) + H.adjustBruteLoss(limb_damage) + +/obj/structure/closet/grave/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(src.opened) + if(istype(W, /obj/item/weapon/shovel)) + user.visible_message("[user] piles dirt into \the [src.name].", \ + "You start to pile dirt into \the [src.name].", \ + "You hear dirt being moved.") + if(do_after(user, 40 * W.toolspeed)) + user.visible_message("[user] pats down the dirt on top of \the [src.name].", \ + "You finish filling in \the [src.name].") + close() + return + else + user.visible_message("[user] stops filling in \the [src.name].", \ + "You change your mind and stop filling in \the [src.name].") + return + if(istype(W, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = W + src.MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet + return 0 + if(istype(W,/obj/item/tk_grab)) + return 0 + if(istype(W, /obj/item/weapon/storage/laundry_basket) && W.contents.len) + var/obj/item/weapon/storage/laundry_basket/LB = W + var/turf/T = get_turf(src) + for(var/obj/item/I in LB.contents) + LB.remove_from_storage(I, T) + user.visible_message("[user] empties \the [LB] into \the [src].", \ + "You empty \the [LB] into \the [src].", \ + "You hear rustling of clothes.") + return + if(isrobot(user)) + return + if(W.loc != user) // This should stop mounted modules ending up outside the module. + return + usr.drop_item() + if(W) + W.forceMove(src.loc) + else + if(istype(W, /obj/item/weapon/shovel)) + if(user.a_intent == I_HURT) // Hurt intent means you're trying to kill someone, or just get rid of the grave + user.visible_message("[user] begins to smoothe out the dirt of \the [src.name].", \ + "You start to smoothe out the dirt of \the [src.name].", \ + "You hear dirt being moved.") + if(do_after(user, 40 * W.toolspeed)) + user.visible_message("[user] finishes smoothing out \the [src.name].", \ + "You finish smoothing out \the [src.name].") + if(LAZYLEN(contents)) + alpha = 40 // If we've got stuff inside, like maybe a person, just make it hard to see us + else + qdel(src) // Else, go away + return + else + user.visible_message("[user] stops concealing \the [src.name].", \ + "You stop concealing \the [src.name].") + return + else + user.visible_message("[user] begins to unearth \the [src.name].", \ + "You start to unearth \the [src.name].", \ + "You hear dirt being moved.") + if(do_after(user, 40 * W.toolspeed)) + user.visible_message("[user] reaches the bottom of \the [src.name].", \ + "You finish digging out \the [src.name].") + break_open() + return + else + user.visible_message("[user] stops digging out \the [src.name].", \ + "You stop digging out \the [src.name].") + return + return + +/obj/structure/closet/grave/close() + ..() + if(!opened) + sealed = TRUE + +/obj/structure/closet/grave/open() + .=..() + alpha = 255 // Needed because of grave hiding + +/obj/structure/closet/grave/bullet_act(var/obj/item/projectile/P) + return PROJECTILE_CONTINUE // It's a hole in the ground, doesn't usually stop or even care about bullets + +/obj/structure/closet/grave/return_air_for_internal_lifeform(var/mob/living/L) + var/gasid = "carbon_dioxide" + if(ishuman(L)) + var/mob/living/carbon/human/H = L + if(H.species && H.species.exhale_type) + gasid = H.species.exhale_type + var/datum/gas_mixture/grave_breath = new() + var/datum/gas_mixture/above_air = return_air() + grave_breath.adjust_gas(gasid, BREATH_MOLES) + grave_breath.temperature = (above_air.temperature) - 30 //Underground + return grave_breath \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm b/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm index c606151550..62497919fc 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm @@ -43,8 +43,8 @@ overlays += icon(src.icon, "door") - if(welded) - overlays += icon(src.icon,"welded") + if(sealed) + overlays += icon(src.icon,"sealed") if(broken) overlays += icon(src.icon,"broken") diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm index 994fe0eca1..af07ceb9e5 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm @@ -46,23 +46,23 @@ /obj/structure/closet/secure_closet/proc/togglelock(mob/user as mob) if(src.opened) - user << "Close the locker first." + to_chat(user, "Close the locker first.") return if(src.broken) - user << "The locker appears to be broken." + to_chat(user, "The locker appears to be broken.") return if(user.loc == src) - user << "You can't reach the lock from inside." + to_chat(user, "You can't reach the lock from inside.") return if(src.allowed(user)) src.locked = !src.locked playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) for(var/mob/O in viewers(user, 3)) if((O.client && !( O.blinded ))) - O << "The locker has been [locked ? null : "un"]locked by [user]." + to_chat(O, "The locker has been [locked ? null : "un"]locked by [user].") update_icon() else - user << "Access Denied" + to_chat(user, "Access Denied") /obj/structure/closet/secure_closet/attackby(obj/item/weapon/W as obj, mob/user as mob) if(src.opened) @@ -73,7 +73,7 @@ if(src.large) src.MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet else - user << "The locker is too small to stuff [G.affecting] into!" + to_chat(user, "The locker is too small to stuff [G.affecting] into!") if(isrobot(user)) return if(W.loc != user) // This should stop mounted modules ending up outside the module. @@ -89,14 +89,14 @@ playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) playsound(src.loc, "sparks", 50, 1) else if(W.is_wrench()) - if(welded) + if(sealed) if(anchored) user.visible_message("\The [user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.") else user.visible_message("\The [user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.") if(do_after(user, 20 * W.toolspeed)) if(!src) return - user << "You [anchored? "un" : ""]secured \the [src]!" + to_chat(user, "You [anchored? "un" : ""]secured \the [src]!") anchored = !anchored return else if(istype(W,/obj/item/weapon/packageWrap) || istype(W,/obj/item/weapon/weldingtool)) @@ -143,9 +143,9 @@ src.add_fingerprint(usr) src.togglelock(usr) else - usr << "This mob type can't use this verb." + to_chat(usr, "This mob type can't use this verb.") -/obj/structure/closet/secure_closet/update_icon()//Putting the welded stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot) +/obj/structure/closet/secure_closet/update_icon()//Putting the sealed stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot) overlays.Cut() if(!opened) @@ -155,8 +155,8 @@ icon_state = icon_locked else icon_state = icon_closed - if(welded) - overlays += "welded" + if(sealed) + overlays += "sealed" else icon_state = icon_opened diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index ddedd18b18..389209e52c 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -380,7 +380,7 @@ //Resisting out of closets if(istype(loc,/obj/structure/closet)) var/obj/structure/closet/C = loc - if(C.welded) + if(C.sealed) handle_resist() else C.open() diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index 64f5b923ab..59b690f31a 100755 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -284,7 +284,7 @@ if (src.amount > 3 && !O.opened) var/obj/structure/bigDelivery/P = new /obj/structure/bigDelivery(get_turf(O.loc)) P.wrapped = O - O.welded = 1 + O.sealed = 1 O.loc = P src.amount -= 3 user.visible_message("\The [user] wraps \a [target] with \a [src].",\ @@ -311,7 +311,7 @@ wrapped.forceMove(get_turf(src)) if(istype(wrapped, /obj/structure/closet)) var/obj/structure/closet/O = wrapped - O.welded = 0 + O.sealed = 0 wrapped = null var/turf/T = get_turf(src) for(var/atom/movable/AM in contents) diff --git a/html/changelogs/Anewbe - Graves.yml b/html/changelogs/Anewbe - Graves.yml new file mode 100644 index 0000000000..fd7b71a680 --- /dev/null +++ b/html/changelogs/Anewbe - Graves.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Anewbe + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Graves are now a thing in the code, will need some testing and probably more work before they get more common." \ No newline at end of file diff --git a/icons/obj/closet.dmi b/icons/obj/closet.dmi index 5fd95e85d7..80fb1712be 100644 Binary files a/icons/obj/closet.dmi and b/icons/obj/closet.dmi differ