diff --git a/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm b/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm index 4511f8bd5a7..865490aef28 100644 --- a/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm @@ -381,6 +381,8 @@ if(!welded) if(open) for(var/obj/item/W in src) + if(istype(W, /obj/item/pipe)) + continue W.forceMove(get_turf(src)) diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 6f14b75b2ec..967749a55a7 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -17,7 +17,8 @@ // /datum signals #define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (/datum/component) #define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (/datum/component) -#define COMSIG_PARENT_QDELETED "parent_qdeleted" //before a datum's Destroy() is called: () +#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation +#define COMSIG_PARENT_QDELETED "parent_qdeleted" //after a datum's Destroy() is called: (force, qdel_hint), at this point none of the other components chose to interrupt qdel and Destroy has been called // /atom signals #define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params) diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm index 8d504edaf41..6adb876da8d 100644 --- a/code/__DEFINES/qdel.dm +++ b/code/__DEFINES/qdel.dm @@ -11,14 +11,12 @@ #define QDEL_HINT_IFFAIL_FINDREFERENCE 6 //Above but only if gc fails. //defines for the gc_destroyed var -#define GC_QUEUE_PREQUEUE 1 -#define GC_QUEUE_CHECK 2 -#define GC_QUEUE_HARDDELETE 3 -#define GC_QUEUE_COUNT 3 //increase this when adding more steps. +#define GC_QUEUE_CHECK 1 +#define GC_QUEUE_HARDDELETE 2 +#define GC_QUEUE_COUNT 2 //increase this when adding more steps. #define GC_QUEUED_FOR_QUEUING -1 -#define GC_QUEUED_FOR_HARD_DEL -2 -#define GC_CURRENTLY_BEING_QDELETED -3 +#define GC_CURRENTLY_BEING_QDELETED -2 #define QDELING(X) (X.gc_destroyed) #define QDELETED(X) (!X || QDELING(X)) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 7c38ee1072a..623d1bb5dd6 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -175,66 +175,111 @@ icon_state = "zone_sel" screen_loc = ui_zonesel var/selecting = "chest" + var/static/list/hover_overlays_cache = list() + var/hovering /obj/screen/zone_sel/Click(location, control,params) + if(isobserver(usr)) + return + var/list/PL = params2list(params) var/icon_x = text2num(PL["icon-x"]) var/icon_y = text2num(PL["icon-y"]) - var/old_selecting = selecting //We're only going to update_icon() if there's been a change + var/choice = get_zone_at(icon_x, icon_y) + if(!choice) + return 1 + return set_selected_zone(choice, usr) + +/obj/screen/zone_sel/MouseEntered(location, control, params) + MouseMove(location, control, params) + +/obj/screen/zone_sel/MouseMove(location, control, params) + if(isobserver(usr)) + return + + var/list/PL = params2list(params) + var/icon_x = text2num(PL["icon-x"]) + var/icon_y = text2num(PL["icon-y"]) + var/choice = get_zone_at(icon_x, icon_y) + + if(hovering == choice) + return + cut_overlay(hover_overlays_cache[hovering]) + hovering = choice + + var/obj/effect/overlay/zone_sel/overlay_object = hover_overlays_cache[choice] + if(!overlay_object) + overlay_object = new + overlay_object.icon_state = "[choice]" + hover_overlays_cache[choice] = overlay_object + add_overlay(overlay_object) + + +/obj/effect/overlay/zone_sel + icon = 'icons/mob/zone_sel.dmi' + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + alpha = 128 + anchored = TRUE + layer = ABOVE_HUD_LAYER + plane = ABOVE_HUD_PLANE + +/obj/screen/zone_sel/MouseExited(location, control, params) + if(!isobserver(usr) && hovering) + cut_overlay(hover_overlays_cache[hovering]) + hovering = null + +/obj/screen/zone_sel/proc/get_zone_at(icon_x, icon_y) switch(icon_y) if(1 to 3) //Feet switch(icon_x) if(10 to 15) - selecting = "r_foot" + return "r_foot" if(17 to 22) - selecting = "l_foot" - else - return 1 + return "l_foot" if(4 to 9) //Legs switch(icon_x) if(10 to 15) - selecting = "r_leg" + return "r_leg" if(17 to 22) - selecting = "l_leg" - else - return 1 + return "l_leg" if(10 to 13) //Hands and groin switch(icon_x) if(8 to 11) - selecting = "r_hand" + return "r_hand" if(12 to 20) - selecting = "groin" + return "groin" if(21 to 24) - selecting = "l_hand" - else - return 1 + return "l_hand" if(14 to 22) //Chest and arms to shoulders switch(icon_x) if(8 to 11) - selecting = "r_arm" + return "r_arm" if(12 to 20) - selecting = "chest" + return "chest" if(21 to 24) - selecting = "l_arm" - else - return 1 + return "l_arm" if(23 to 30) //Head, but we need to check for eye or mouth if(icon_x in 12 to 20) - selecting = "head" switch(icon_y) if(23 to 24) if(icon_x in 15 to 17) - selecting = "mouth" + return "mouth" if(26) //Eyeline, eyes are on 15 and 17 if(icon_x in 14 to 18) - selecting = "eyes" + return "eyes" if(25 to 27) if(icon_x in 15 to 17) - selecting = "eyes" + return "eyes" + return "head" - if(old_selecting != selecting) - update_icon() +/obj/screen/zone_sel/proc/set_selected_zone(choice, mob/user) + if(isobserver(user)) + return + + if(choice != selecting) + selecting = choice + update_icon(usr) return 1 /obj/screen/zone_sel/update_icon() diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 97dd02838d0..c1cb90919f5 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -59,7 +59,6 @@ SUBSYSTEM_DEF(garbage) msg += " | Fail:[fail_counts.Join(",")]" ..(msg) - /datum/controller/subsystem/garbage/Shutdown() //Adds the del() log to the qdel log file var/list/dellog = list() @@ -86,41 +85,21 @@ SUBSYSTEM_DEF(garbage) /datum/controller/subsystem/garbage/fire() //the fact that this resets its processing each fire (rather then resume where it left off) is intentional. - var/queue = GC_QUEUE_PREQUEUE + var/queue = GC_QUEUE_CHECK while(state == SS_RUNNING) switch(queue) - if(GC_QUEUE_PREQUEUE) - HandlePreQueue() - queue = GC_QUEUE_PREQUEUE + 1 if(GC_QUEUE_CHECK) HandleQueue(GC_QUEUE_CHECK) queue = GC_QUEUE_CHECK + 1 if(GC_QUEUE_HARDDELETE) HandleQueue(GC_QUEUE_HARDDELETE) + if(state == SS_PAUSED) //make us wait again before the next run. + state = SS_RUNNING break - if(state == SS_PAUSED) //make us wait again before the next run. - state = SS_RUNNING -//If you see this proc high on the profile, what you are really seeing is the garbage collection/soft delete overhead in byond. -//Don't attempt to optimize, not worth the effort. -/datum/controller/subsystem/garbage/proc/HandlePreQueue() - var/list/tobequeued = queues[GC_QUEUE_PREQUEUE] - var/static/count = 0 - if(count) - var/c = count - count = 0 //so if we runtime on the Cut, we don't try again. - tobequeued.Cut(1, c + 1) - for(var/ref in tobequeued) - count++ - Queue(ref, GC_QUEUE_PREQUEUE + 1) - if(MC_TICK_CHECK) - break - if(count) - tobequeued.Cut(1, count + 1) - count = 0 /datum/controller/subsystem/garbage/proc/HandleQueue(level = GC_QUEUE_CHECK) if(level == GC_QUEUE_CHECK) @@ -142,7 +121,7 @@ SUBSYSTEM_DEF(garbage) if(!refID) count++ if(MC_TICK_CHECK) - break + return continue var/GCd_at_time = queue[refID] @@ -161,7 +140,7 @@ SUBSYSTEM_DEF(garbage) reference_find_on_fail -= refID //It's deleted we don't care anymore. #endif if(MC_TICK_CHECK) - break + return continue // Something's still referring to the qdel'd object. @@ -184,27 +163,20 @@ SUBSYSTEM_DEF(garbage) if(GC_QUEUE_HARDDELETE) HardDelete(D) if(MC_TICK_CHECK) - break + return continue Queue(D, level + 1) if(MC_TICK_CHECK) - break + return if(count) queue.Cut(1, count + 1) count = 0 -/datum/controller/subsystem/garbage/proc/PreQueue(datum/D) - if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED) - queues[GC_QUEUE_PREQUEUE] += D - D.gc_destroyed = GC_QUEUED_FOR_QUEUING - /datum/controller/subsystem/garbage/proc/Queue(datum/D, level = GC_QUEUE_CHECK) if(isnull(D)) return - if(D.gc_destroyed == GC_QUEUED_FOR_HARD_DEL) - level = GC_QUEUE_HARDDELETE if(level > GC_QUEUE_COUNT) HardDelete(D) return @@ -250,11 +222,6 @@ SUBSYSTEM_DEF(garbage) message_admins("Error: [type]([refID]) took longer than 1 second to delete (took [time / 10] seconds to delete).") postpone(time) -/datum/controller/subsystem/garbage/proc/HardQueue(datum/D) - if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED) - queues[GC_QUEUE_PREQUEUE] += D - D.gc_destroyed = GC_QUEUED_FOR_HARD_DEL - /datum/controller/subsystem/garbage/Recover() if(istype(SSgarbage.queues)) for(var/i in 1 to SSgarbage.queues.len) @@ -294,11 +261,13 @@ SUBSYSTEM_DEF(garbage) if(isnull(D.gc_destroyed)) - D.SendSignal(COMSIG_PARENT_QDELETED) + if(D.SendSignal(COMSIG_PARENT_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted + return D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED var/start_time = world.time var/start_tick = world.tick_usage var/hint = D.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up. + D.SendSignal(COMSIG_PARENT_QDELETED, force, hint) // Let the (remaining) components know about the result of Destroy if(world.time != start_time) I.slept_destroy++ else @@ -307,7 +276,7 @@ SUBSYSTEM_DEF(garbage) return switch(hint) if(QDEL_HINT_QUEUE) //qdel should queue the object for deletion. - SSgarbage.PreQueue(D) + SSgarbage.Queue(D) if(QDEL_HINT_IWILLGC) D.gc_destroyed = world.time return @@ -327,18 +296,18 @@ SUBSYSTEM_DEF(garbage) #endif I.no_respect_force++ - SSgarbage.PreQueue(D) - if(QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete using a hard reference to save time from the locate() - SSgarbage.HardQueue(D) + SSgarbage.Queue(D) + if(QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete + SSgarbage.Queue(D, GC_QUEUE_HARDDELETE) if(QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste. SSgarbage.HardDelete(D) if(QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion. - SSgarbage.PreQueue(D) + SSgarbage.Queue(D) #ifdef TESTING D.find_references() #endif if(QDEL_HINT_IFFAIL_FINDREFERENCE) - SSgarbage.PreQueue(D) + SSgarbage.Queue(D) #ifdef TESTING SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE #endif @@ -348,7 +317,7 @@ SUBSYSTEM_DEF(garbage) testing("WARNING: [D.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.") #endif I.no_hint++ - SSgarbage.PreQueue(D) + SSgarbage.Queue(D) else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED) CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic") @@ -463,4 +432,4 @@ SUBSYSTEM_DEF(garbage) CHECK_TICK #endif -#endif +#endif \ No newline at end of file diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 05eaae1a9d9..d0abd774e6f 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -391,6 +391,9 @@ Class Procs: return ..() +/obj/machinery/proc/is_operational() + return !(stat & (NOPOWER|BROKEN|MAINT)) + /obj/machinery/CheckParts(list/parts_list) ..() RefreshParts() diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 370cef73559..2d395da0dd0 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -1,128 +1,353 @@ -////////////////////////////////////// // SUIT STORAGE UNIT ///////////////// -////////////////////////////////////// - - /obj/machinery/suit_storage_unit - name = "Suit Storage Unit" + name = "suit storage unit" desc = "An industrial U-Stor-It Storage unit designed to accomodate all kinds of space suits. Its on-board equipment also allows the user to decontaminate the contents through a UV-ray purging cycle. There's a warning label dangling from the control pad, reading \"STRICTLY NO BIOLOGICALS IN THE CONFINES OF THE UNIT\"." - icon = 'icons/obj/suitstorage.dmi' - icon_state = "suitstorage000000100" //order is: [has helmet][has suit][has human][is open][is locked][is UV cycling][is powered][is dirty/broken] [is superUVcycling] - anchored = 1 - density = 1 - var/mob/living/carbon/human/OCCUPANT = null - var/obj/item/clothing/suit/space/SUIT = null - var/SUIT_TYPE = null - var/obj/item/clothing/head/helmet/space/HELMET = null - var/HELMET_TYPE = null - var/obj/item/clothing/mask/MASK = null //All the stuff that's gonna be stored insiiiiiiiiiiiiiiiiiiide, nyoro~n - var/MASK_TYPE = null //Erro's idea on standarising SSUs whle keeping creation of other SSU types easy: Make a child SSU, name it something then set the TYPE vars to your desired suit output. New() should take it from there by itself. - var/isopen = 0 - var/islocked = 0 - var/isUV = 0 - var/ispowered = 1 //starts powered - var/isbroken = 0 - var/issuperUV = 0 - var/panelopen = 0 - var/safetieson = 1 - var/cycletime_left = 0 + icon = 'icons/obj/machines/suit_storage.dmi' + icon_state = "close" + anchored = TRUE + density = TRUE + max_integrity = 250 + var/obj/item/clothing/suit/space/suit = null + var/obj/item/clothing/head/helmet/space/helmet = null + var/obj/item/clothing/mask/mask = null + var/obj/item/storage = null + + var/helmet_type = null + var/suit_type = null + var/mask_type = null + var/storage_type = null + + var/locked = FALSE + var/safeties = TRUE + var/broken = FALSE + + var/uv = FALSE + var/uv_super = FALSE + var/uv_cycles = 6 + var/message_cooldown + var/breakout_time = 300 + + //abstract these onto machinery eventually + var/state_open = FALSE + var/list/occupant_typecache //if set, turned into typecache in Initialize, other wise, defaults to mob/living typecache + var/atom/movable/occupant = null -//The units themselves///////////////// /obj/machinery/suit_storage_unit/standard_unit - SUIT_TYPE = /obj/item/clothing/suit/space/eva - HELMET_TYPE = /obj/item/clothing/head/helmet/space/eva - MASK_TYPE = /obj/item/clothing/mask/breath + suit_type = /obj/item/clothing/suit/space/eva + helmet_type = /obj/item/clothing/head/helmet/space/eva + mask_type = /obj/item/clothing/mask/breath /obj/machinery/suit_storage_unit/captain - SUIT_TYPE = /obj/item/clothing/suit/space/captain - HELMET_TYPE = /obj/item/clothing/head/helmet/space/capspace - MASK_TYPE = /obj/item/clothing/mask/gas + suit_type = /obj/item/clothing/suit/space/captain + helmet_type = /obj/item/clothing/head/helmet/space/capspace + mask_type = /obj/item/clothing/mask/gas + storage_type = /obj/item/tank/jetpack/oxygen/captain /obj/machinery/suit_storage_unit/engine - SUIT_TYPE = /obj/item/clothing/suit/space/hardsuit/engineering - HELMET_TYPE = /obj/item/clothing/head/helmet/space/hardsuit/engineering - MASK_TYPE = /obj/item/clothing/mask/breath + suit_type = /obj/item/clothing/suit/space/hardsuit/engineering + helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/engineering + mask_type = /obj/item/clothing/mask/breath + storage_type = /obj/item/clothing/shoes/magboots /obj/machinery/suit_storage_unit/ce - SUIT_TYPE = /obj/item/clothing/suit/space/hardsuit/elite - HELMET_TYPE = /obj/item/clothing/head/helmet/space/hardsuit/elite - MASK_TYPE = /obj/item/clothing/mask/breath + suit_type = /obj/item/clothing/suit/space/hardsuit/elite + helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/elite + mask_type = /obj/item/clothing/mask/gas + storage_type = /obj/item/clothing/shoes/magboots/advance /obj/machinery/suit_storage_unit/security - SUIT_TYPE = /obj/item/clothing/suit/space/hardsuit/security - HELMET_TYPE = /obj/item/clothing/head/helmet/space/hardsuit/security - MASK_TYPE = /obj/item/clothing/mask/gas/sechailer + suit_type = /obj/item/clothing/suit/space/hardsuit/security + helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/security + mask_type = /obj/item/clothing/mask/gas/sechailer /obj/machinery/suit_storage_unit/atmos - SUIT_TYPE = /obj/item/clothing/suit/space/hardsuit/atmos - HELMET_TYPE = /obj/item/clothing/head/helmet/space/hardsuit/atmos - MASK_TYPE = /obj/item/clothing/mask/gas + suit_type = /obj/item/clothing/suit/space/hardsuit/atmos + helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/atmos + mask_type = /obj/item/clothing/mask/gas + storage_type = /obj/item/clothing/shoes/magboots /obj/machinery/suit_storage_unit/mining - SUIT_TYPE = /obj/item/clothing/suit/space/hardsuit/mining - HELMET_TYPE = /obj/item/clothing/head/helmet/space/hardsuit/mining - MASK_TYPE = /obj/item/clothing/mask/breath + suit_type = /obj/item/clothing/suit/space/hardsuit/mining + helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/mining + mask_type = /obj/item/clothing/mask/breath /obj/machinery/suit_storage_unit/cmo - SUIT_TYPE = /obj/item/clothing/suit/space/hardsuit/medical - HELMET_TYPE = /obj/item/clothing/head/helmet/space/hardsuit/medical - MASK_TYPE = /obj/item/clothing/mask/breath + suit_type = /obj/item/clothing/suit/space/hardsuit/medical + helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/medical + mask_type = /obj/item/clothing/mask/breath -/obj/machinery/suit_storage_unit/New() - src.update_icon() - if(SUIT_TYPE) - SUIT = new SUIT_TYPE(src) - if(HELMET_TYPE) - HELMET = new HELMET_TYPE(src) - if(MASK_TYPE) - MASK = new MASK_TYPE(src) +/obj/machinery/suit_storage_unit/syndicate + suit_type = /obj/item/clothing/suit/space/hardsuit/syndi + helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/syndi + mask_type = /obj/item/clothing/mask/gas/syndicate + storage_type = /obj/item/tank/jetpack/oxygen/harness + +/obj/machinery/suit_storage_unit/ert/command + suit_type = /obj/item/clothing/suit/space/hardsuit/ert/commander + helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/ert/commander + mask_type = /obj/item/clothing/mask/breath + storage_type = /obj/item/tank/emergency_oxygen/double + +/obj/machinery/suit_storage_unit/ert/security + suit_type = /obj/item/clothing/suit/space/hardsuit/ert/security + helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/ert/security + mask_type = /obj/item/clothing/mask/breath + storage_type = /obj/item/tank/emergency_oxygen/double + +/obj/machinery/suit_storage_unit/ert/engineer + suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engineer + helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/ert/engineer + mask_type = /obj/item/clothing/mask/breath + storage_type = /obj/item/tank/emergency_oxygen/double + +/obj/machinery/suit_storage_unit/ert/medical + suit_type = /obj/item/clothing/suit/space/hardsuit/ert/medical + helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/ert/medical + mask_type = /obj/item/clothing/mask/breath + storage_type = /obj/item/tank/emergency_oxygen/double + + + +/obj/machinery/suit_storage_unit/Initialize() + . = ..() + if(suit_type) + suit = new suit_type(src) + if(helmet_type) + helmet = new helmet_type(src) + if(mask_type) + mask = new mask_type(src) + if(storage_type) + storage = new storage_type(src) + update_icon() + + //move this into machinery eventually... + if(occupant_typecache) + occupant_typecache = typecacheof(occupant_typecache) + +/obj/machinery/suit_storage_unit/Destroy() + QDEL_NULL(suit) + QDEL_NULL(helmet) + QDEL_NULL(mask) + QDEL_NULL(storage) + return ..() /obj/machinery/suit_storage_unit/update_icon() - var/hashelmet = 0 - var/hassuit = 0 - var/hashuman = 0 - if(HELMET) - hashelmet = 1 - if(SUIT) - hassuit = 1 - if(OCCUPANT) - hashuman = 1 - icon_state = text("suitstorage[][][][][][][][][]",hashelmet,hassuit,hashuman,src.isopen,src.islocked,src.isUV,src.ispowered,src.isbroken,src.issuperUV) + cut_overlays() + if(uv) + if(uv_super) + add_overlay("super") + else if(occupant) + add_overlay("uvhuman") + else + add_overlay("uv") + else if(state_open) + if(stat & BROKEN) + add_overlay("broken") + else + add_overlay("open") + if(suit) + add_overlay("suit") + if(helmet) + add_overlay("helm") + if(storage) + add_overlay("storage") + else if(occupant) + add_overlay("human") + +/obj/machinery/suit_storage_unit/attackby(obj/item/I as obj, mob/user as mob, params) + if(!is_operational()) + return + if(isscrewdriver(I)) + panel_open = !panel_open + playsound(loc, I.usesound, 100, 1) + to_chat(user, text("You [panel_open ? "open up" : "close"] the unit's maintenance panel.")) + updateUsrDialog() /obj/machinery/suit_storage_unit/power_change() - if( powered() ) - src.ispowered = 1 - stat &= ~NOPOWER - src.update_icon() + ..() + if(!is_operational() && state_open) + open_machine() + dump_contents() + update_icon() + + +/obj/machinery/suit_storage_unit/proc/dump_contents() + dropContents() + helmet = null + suit = null + mask = null + storage = null + occupant = null + +/obj/machinery/suit_storage_unit/deconstruct(disassembled = TRUE) + open_machine() + dump_contents() + new /obj/item/stack/sheet/metal (loc, 2) + qdel(src) + +/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/user) + if(user.stat || user.lying || !Adjacent(user) || !Adjacent(A) || !isliving(A)) + return + var/mob/living/target = A + if(!state_open) + to_chat(user, "The [src]'s doors are shut!") + return + if(!is_operational()) + to_chat(user, "The [src] is not operational!") + return + if(occupant || helmet || suit || storage) + to_chat(user, "It's too cluttered inside to fit in!") + return + + if(target == user) + user.visible_message("[user] starts squeezing into [src]!", "You start working your way into [src]...") else - spawn(rand(0, 15)) - src.ispowered = 0 - stat |= NOPOWER - src.islocked = 0 - src.isopen = 1 - src.dump_everything() - src.update_icon() + target.visible_message("[user] starts shoving [target] into [src]!", "[user] starts shoving you into [src]!") - -/obj/machinery/suit_storage_unit/ex_act(severity) - switch(severity) - if(1.0) - if(prob(50)) - src.dump_everything() //So suits dont survive all the time - qdel(src) - return - if(2.0) - if(prob(50)) - src.dump_everything() - qdel(src) + if(do_mob(user, target, 30)) + if(occupant || helmet || suit || storage) return + if(target == user) + user.visible_message("[user] slips into [src] and closes the door behind [user.p_them()]!", "You slip into [src]'s cramped space and shut its door.") else - return - return + target.visible_message("[user] pushes [target] into [src] and shuts its door!", "[user] shoves you into [src] and shuts the door!") + close_machine(target) + add_fingerprint(user) +/obj/machinery/suit_storage_unit/proc/cook() + if(uv_cycles) + uv_cycles-- + uv = TRUE + locked = TRUE + update_icon() + if(occupant) + var/mob/living/mob_occupant = occupant + if(uv_super) + mob_occupant.adjustFireLoss(rand(20, 36)) + else + mob_occupant.adjustFireLoss(rand(10, 16)) + mob_occupant.emote("scream") + addtimer(CALLBACK(src, .proc/cook), 50) + else + uv_cycles = initial(uv_cycles) + uv = FALSE + locked = FALSE + if(uv_super) + visible_message("[src]'s door creaks open with a loud whining noise. A cloud of foul black smoke escapes from its chamber.") + playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, 1) + helmet = null + qdel(helmet) + suit = null + qdel(suit) // Delete everything but the occupant. + mask = null + qdel(mask) + storage = null + qdel(storage) + else + if(!occupant) + visible_message("[src]'s door slides open. The glowing yellow lights dim to a gentle green.") + else + visible_message("[src]'s door slides open, barraging you with the nauseating smell of charred flesh.") + playsound(src, 'sound/machines/airlock_close.ogg', 25, 1) + open_machine(FALSE) + if(occupant) + dump_contents() + +/obj/machinery/suit_storage_unit/shock(mob/user, prb) + if(!prob(prb)) + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread + s.set_up(5, 1, src) + s.start() + if(electrocute_mob(user, src, src, 1, TRUE)) + return 1 + +/obj/machinery/suit_storage_unit/relaymove(mob/user) + if(locked) + if(message_cooldown <= world.time) + message_cooldown = world.time + 50 + to_chat(user, "[src]'s door won't budge!") + return + open_machine() + dump_contents() + +/obj/machinery/suit_storage_unit/container_resist(mob/living/user) + if(!locked) + open_machine() + dump_contents() + return + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + user.visible_message("You see [user] kicking against the doors of [src]!", \ + "You start kicking against the doors... (this will take about [DisplayTimeText(breakout_time)].)", \ + "You hear a thump from [src].") + if(do_after(user,(breakout_time), target = src)) + if(!user || user.stat != CONSCIOUS || user.loc != src ) + return + user.visible_message("[user] successfully broke out of [src]!", \ + "You successfully break out of [src]!") + open_machine() + dump_contents() + + add_fingerprint(user) + if(locked) + visible_message("You see [user] kicking against the doors of [src]!", \ + "You start kicking against the doors...") + addtimer(CALLBACK(src, .proc/resist_open, user), 300) + else + open_machine() + dump_contents() + +/obj/machinery/suit_storage_unit/proc/resist_open(mob/user) + if(!state_open && occupant && (user in src) && !user.stat) // Check they're still here. + visible_message("You see [user] burst out of [src]!", \ + "You escape the cramped confines of [src]!") + open_machine() + +//eventually move these onto the parent.... + +/obj/machinery/suit_storage_unit/proc/open_machine(drop = TRUE) + state_open = TRUE + if(drop) + dropContents() + update_icon() + updateUsrDialog() + +/obj/machinery/suit_storage_unit/dropContents() + var/turf/T = get_turf(src) + for(var/atom/movable/A in contents) + A.forceMove(T) + if(isliving(A)) + var/mob/living/L = A + L.update_canmove() + occupant = null + +/obj/machinery/suit_storage_unit/proc/close_machine(atom/movable/target = null) + state_open = FALSE + if(!target) + for(var/am in loc) + if(!(occupant_typecache ? is_type_in_typecache(am, occupant_typecache) : isliving(am))) + continue + var/atom/movable/AM = am + if(AM.has_buckled_mobs()) + continue + if(isliving(AM)) + var/mob/living/L = am + if(L.buckled || L.mob_size >= MOB_SIZE_LARGE) + continue + target = am + + var/mob/living/mobtarget = target + if(target && !target.has_buckled_mobs() && (!isliving(target) || !mobtarget.buckled)) + occupant = target + target.forceMove(src) + updateUsrDialog() + update_icon() + + +//////// /obj/machinery/suit_storage_unit/attack_hand(mob/user as mob) var/dat @@ -131,54 +356,49 @@ if(stat & NOPOWER) return if(!user.IsAdvancedToolUser()) - return 0 - if(src.panelopen) //The maintenance panel is open. Time for some shady stuff + return FALSE + if(panel_open) //The maintenance panel is open. Time for some shady stuff dat+= "Suit storage unit: Maintenance panel" dat+= "Maintenance panel controls
" dat+= "The panel is ridden with controls, button and meters, labeled in strange signs and symbols that
you cannot understand. Probably the manufactoring world's language.
Among other things, a few controls catch your eye.

" - dat+= text("A small dial with a \"�\" symbol embroidded on it. It's pointing towards a gauge that reads [].
Turn towards []
",(src.issuperUV ? "15nm" : "185nm"),(src.issuperUV ? "185nm" : "15nm") ) - dat+= text("A thick old-style button, with 2 grimy LED lights next to it. The [] LED is on.
Press button",(src.safetieson? "GREEN" : "RED")) + dat+= text("A small dial with a arrow embroidered on it. It's pointing towards a gauge that reads [].
Turn towards []
",(uv_super ? "15nm" : "185nm"),(uv_super ? "185nm" : "15nm") ) + dat+= text("A thick old-style button, with 2 grimy LED lights next to it. The [] LED is on.
Press button",(safeties ? "GREEN" : "RED")) dat+= "

Close panel" - //user << browse(dat, "window=ssu_m_panel;size=400x500") - //onclose(user, "ssu_m_panel") - else if(src.isUV) //The thing is running its cauterisation cycle. You have to wait. + else if(uv) //The thing is running its cauterisation cycle. You have to wait. dat += "Suit storage unit" dat+= "Unit is cauterising contents with selected UV ray intensity. Please wait.
" - //dat+= "Cycle end in: [src.cycletimeleft()] seconds. " - //user << browse(dat, "window=ssu_cycling_panel;size=400x500") - //onclose(user, "ssu_cycling_panel") else - if(!src.isbroken) + if(!broken) dat+= "Welcome to the Unit control panel.
" - dat+= text("Helmet storage compartment: []
",(src.HELMET ? HELMET.name : "
No helmet detected.") ) - if(HELMET && src.isopen) + dat+= text("Helmet storage compartment: []
",(helmet ? helmet.name : "
No helmet detected.") ) + if(helmet && state_open) dat+="Dispense helmet
" - dat+= text("Suit storage compartment: []
",(src.SUIT ? SUIT.name : "
No exosuit detected.") ) - if(SUIT && src.isopen) + dat+= text("Suit storage compartment: []
",(suit ? suit.name : "
No exosuit detected.") ) + if(suit && state_open) dat+="Dispense suit
" - dat+= text("Breathmask storage compartment: []
",(src.MASK ? MASK.name : "
No breathmask detected.") ) - if(MASK && src.isopen) + dat+= text("Breathmask storage compartment: []
",(mask ? mask.name : "
No breathmask detected.") ) + if(mask && state_open) dat+="Dispense mask
" - if(src.OCCUPANT) + dat+= text("Breathmask storage compartment: []
",(storage ? storage.name : "
No storage item detected.") ) + if(storage && state_open) + dat+="Dispense storage item
" + if(occupant) dat+= "
WARNING: Biological entity detected inside the Unit's storage. Please remove.
" dat+= "Eject extra load" - dat+= text("
Unit is: [] - [] Unit ",(src.isopen ? "Open" : "Closed"),(src.isopen ? "Close" : "Open")) - if(src.isopen) + dat+= text("
Unit is: [] - [] Unit ",(state_open ? "Open" : "Closed"),(state_open ? "Close" : "Open")) + if(state_open) dat+="
" else - dat+= text(" - *[] Unit*
",(src.islocked ? "Unlock" : "Lock") ) - dat+= text("Unit status: []",(src.islocked? "**LOCKED**
" : "**UNLOCKED**
") ) - dat+= "Start Disinfection cycle
" + dat+= text(" - *[] Unit*
",(locked ? "Unlock" : "Lock") ) + dat+= text("Unit status: []",(locked? "**LOCKED**
" : "**UNLOCKED**
") ) + dat+= "Start Disinfection cycle
" dat += "

Close control panel" - //user << browse(dat, "window=Suit Storage Unit;size=400x500") - //onclose(user, "Suit Storage Unit") else //Ohhhh shit it's dirty or broken! Let's inform the guy. dat+= "Suit storage unit" dat+= "Unit chamber is too contaminated to continue usage. Please call for a qualified individual to perform maintenance.

" dat+= "
Close control panel" - //user << browse(dat, "window=suit_storage_unit;size=400x500") - //onclose(user, "suit_storage_unit") + var/datum/browser/popup = new(user, "suit_storage_unit", name, 400, 500) popup.set_content(dat) @@ -187,263 +407,134 @@ return -/obj/machinery/suit_storage_unit/Topic(href, href_list) //I fucking HATE this proc +/obj/machinery/suit_storage_unit/Topic(href, href_list) if(..()) return 1 if((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon/ai))) usr.set_machine(src) if(href_list["toggleUV"]) - src.toggleUV(usr) - src.updateUsrDialog() - src.update_icon() + toggleUV(usr) + updateUsrDialog() + update_icon() if(href_list["togglesafeties"]) - src.togglesafeties(usr) - src.updateUsrDialog() - src.update_icon() + togglesafeties(usr) + updateUsrDialog() + update_icon() if(href_list["dispense_helmet"]) - src.dispense_helmet(usr) - src.updateUsrDialog() - src.update_icon() + dispense_helmet(usr) + updateUsrDialog() + update_icon() if(href_list["dispense_suit"]) - src.dispense_suit(usr) - src.updateUsrDialog() - src.update_icon() + dispense_suit(usr) + updateUsrDialog() + update_icon() if(href_list["dispense_mask"]) - src.dispense_mask(usr) - src.updateUsrDialog() - src.update_icon() + dispense_mask(usr) + updateUsrDialog() + update_icon() + if(href_list["dispense_storage"]) + dispense_storage(usr) + updateUsrDialog() + update_icon() if(href_list["toggle_open"]) - src.toggle_open(usr) - src.updateUsrDialog() - src.update_icon() + toggle_open(usr) + updateUsrDialog() + update_icon() if(href_list["toggle_lock"]) - src.toggle_lock(usr) - src.updateUsrDialog() - src.update_icon() - if(href_list["start_UV"]) - src.start_UV(usr) - src.updateUsrDialog() - src.update_icon() + toggle_lock(usr) + updateUsrDialog() + update_icon() + if(href_list["cook"]) + cook(usr) + updateUsrDialog() + update_icon() if(href_list["eject_guy"]) - src.eject_occupant(usr) - src.updateUsrDialog() - src.update_icon() - /*if(href_list["refresh"]) - src.updateUsrDialog()*/ - src.add_fingerprint(usr) + eject_occupant(usr) + updateUsrDialog() + update_icon() + add_fingerprint(usr) return /obj/machinery/suit_storage_unit/proc/toggleUV(mob/user as mob) -// var/protected = 0 -// var/mob/living/carbon/human/H = user - if(!src.panelopen) + + if(!panel_open) return - - /*if(istype(H)) //Let's check if the guy's wearing electrically insulated gloves - if(H.gloves) - var/obj/item/clothing/gloves/G = H.gloves - if(istype(G,/obj/item/clothing/gloves/color/yellow)) - protected = 1 - - if(!protected) - playsound(src.loc, "sparks", 75, 1, -1) - to_chat(user, "You try to touch the controls but you get zapped. There must be a short circuit somewhere.") - return*/ - else //welp, the guy is protected, we can continue - if(src.issuperUV) - to_chat(user, "You slide the dial back towards \"185nm\".") - src.issuperUV = 0 + else + if(uv_super) + to_chat(user, "You slide the dial back towards \"185nm\".") + uv_super = FALSE else - to_chat(user, "You crank the dial all the way up to \"15nm\".") - src.issuperUV = 1 - return - + to_chat(user, "You crank the dial all the way up to \"15nm\".") + uv_super = TRUE /obj/machinery/suit_storage_unit/proc/togglesafeties(mob/user as mob) -// var/protected = 0 -// var/mob/living/carbon/human/H = user - if(!src.panelopen) //Needed check due to bugs + if(!panel_open) return - - /*if(istype(H)) //Let's check if the guy's wearing electrically insulated gloves - if(H.gloves) - var/obj/item/clothing/gloves/G = H.gloves - if(istype(G,/obj/item/clothing/gloves/color/yellow) ) - protected = 1 - - if(!protected) - playsound(src.loc, "sparks", 75, 1, -1) - to_chat(user, "You try to touch the controls but you get zapped. There must be a short circuit somewhere.") - return*/ else - to_chat(user, "You push the button. The coloured LED next to it changes.") - src.safetieson = !src.safetieson - + to_chat(user, "You push the button. The coloured LED next to it changes.") + safeties = !safeties /obj/machinery/suit_storage_unit/proc/dispense_helmet(mob/user as mob) - if(!src.HELMET) - return //Do I even need this sanity check? Nyoro~n - else - src.HELMET.loc = src.loc - src.HELMET = null + if(!helmet) return - + else + helmet.forceMove(loc) + helmet = null /obj/machinery/suit_storage_unit/proc/dispense_suit(mob/user as mob) - if(!src.SUIT) + if(!suit) return else - src.SUIT.loc = src.loc - src.SUIT = null - return - + suit.forceMove(loc) + suit = null /obj/machinery/suit_storage_unit/proc/dispense_mask(mob/user as mob) - if(!src.MASK) + if(!mask) return else - src.MASK.loc = src.loc - src.MASK = null + mask.forceMove(loc) + mask = null + +/obj/machinery/suit_storage_unit/proc/dispense_storage(mob/user as mob) + if(!storage) return - - -/obj/machinery/suit_storage_unit/proc/dump_everything() - src.islocked = 0 //locks go free - if(src.SUIT) - src.SUIT.loc = src.loc - src.SUIT = null - if(src.HELMET) - src.HELMET.loc = src.loc - src.HELMET = null - if(src.MASK) - src.MASK.loc = src.loc - src.MASK = null - if(src.OCCUPANT) - src.eject_occupant(OCCUPANT) - return - + else + storage.forceMove(loc) + storage = null /obj/machinery/suit_storage_unit/proc/toggle_open(mob/user as mob) - if(src.islocked || src.isUV) - to_chat(user, "Unable to open unit.") + if(locked || uv) + to_chat(user, "Unable to open unit.") return - if(src.OCCUPANT) - src.eject_occupant(user) - return // eject_occupant opens the door, so we need to return - src.isopen = !src.isopen - return - + if(occupant) + eject_occupant(user) + return + state_open = !state_open /obj/machinery/suit_storage_unit/proc/toggle_lock(mob/user as mob) - if(src.OCCUPANT && src.safetieson) - to_chat(user, "The Unit's safety protocols disallow locking when a biological form is detected inside its compartments.") + if(occupant && safeties) + to_chat(user, "The unit's safety protocols disallow locking when a biological form is detected inside its compartments.") return - if(src.isopen) + if(state_open) return - src.islocked = !src.islocked - return - - -/obj/machinery/suit_storage_unit/proc/start_UV(mob/user as mob) - if(src.isUV || src.isopen) //I'm bored of all these sanity checks - return - if(src.OCCUPANT && src.safetieson) - to_chat(user, "WARNING: Biological entity detected in the confines of the Unit's storage. Cannot initiate cycle.") - return - if(!src.HELMET && !src.MASK && !src.SUIT && !src.OCCUPANT ) //shit's empty yo - to_chat(user, "Unit storage bays empty. Nothing to disinfect -- Aborting.") - return - to_chat(user, "You start the Unit's cauterisation cycle.") - src.cycletime_left = 20 - src.isUV = 1 - if(src.OCCUPANT && !src.islocked) - src.islocked = 1 //Let's lock it for good measure - src.update_icon() - src.updateUsrDialog() - - var/i //our counter - for(i=0,i<4,i++) - sleep(50) - if(src.OCCUPANT) - if(src.issuperUV) - var/burndamage = rand(35,45) - OCCUPANT.take_organ_damage(0,burndamage) - OCCUPANT.emote("scream") - else - var/burndamage = rand(10,15) - OCCUPANT.take_organ_damage(0,burndamage) - OCCUPANT.emote("scream") - if(i==3) //End of the cycle - if(!src.issuperUV) - if(src.HELMET) - HELMET.clean_blood() - if(src.SUIT) - SUIT.clean_blood() - if(src.MASK) - MASK.clean_blood() - else //It was supercycling, destroy everything - if(src.HELMET) - src.HELMET = null - if(src.SUIT) - src.SUIT = null - if(src.MASK) - src.MASK = null - visible_message("With a loud whining noise, the Suit Storage Unit's door grinds open. Puffs of ashen smoke come out of its chamber.") - src.isbroken = 1 - src.isopen = 1 - src.islocked = 0 - src.eject_occupant(OCCUPANT) //Mixing up these two lines causes bug. DO NOT DO IT. - src.isUV = 0 //Cycle ends - src.update_icon() - src.updateUsrDialog() - return - -/* spawn(200) //Let's clean dat shit after 20 secs //Eh, this doesn't work - if(src.HELMET) - HELMET.clean_blood() - if(src.SUIT) - SUIT.clean_blood() - if(src.MASK) - MASK.clean_blood() - src.isUV = 0 //Cycle ends - src.update_icon() - src.updateUsrDialog() - - var/i - for(i=0,i<4,i++) //Gradually give the guy inside some damaged based on the intensity - spawn(50) - if(OCCUPANT) - if(issuperUV) - OCCUPANT.take_organ_damage(0,40) - to_chat(user, "Test. You gave [OCCUPANT.p_them()] 40 damage") - else - OCCUPANT.take_organ_damage(0,8) - to_chat(user, "Test. You gave [OCCUPANT.p_them()] 8 damage") - return*/ - - -/obj/machinery/suit_storage_unit/proc/cycletimeleft() - if(src.cycletime_left >= 1) - src.cycletime_left-- - return src.cycletime_left - + locked = !locked /obj/machinery/suit_storage_unit/proc/eject_occupant(mob/user as mob) - if(islocked) + if(locked) return - if(!OCCUPANT) + if(!occupant) return - if(user != OCCUPANT) - to_chat(OCCUPANT, "The machine kicks you out!") + if(user != occupant) + to_chat(occupant, "The machine kicks you out!") if(user.loc != loc) - to_chat(OCCUPANT, "You leave the not-so-cozy confines of the SSU.") - OCCUPANT.forceMove(loc) - OCCUPANT = null - if(!isopen) - isopen = 1 + to_chat(occupant, "You leave the not-so-cozy confines of the SSU.") + occupant.forceMove(loc) + occupant = null + if(!state_open) + state_open = 1 update_icon() return @@ -455,13 +546,12 @@ if(usr.stat != 0) return - src.eject_occupant(usr) + eject_occupant(usr) add_fingerprint(usr) - src.updateUsrDialog() - src.update_icon() + updateUsrDialog() + update_icon() return - /obj/machinery/suit_storage_unit/verb/move_inside() set name = "Hide in Suit Storage Unit" set category = "Object" @@ -469,640 +559,28 @@ if(usr.stat != 0) return - if(!src.isopen) - to_chat(usr, "The unit's doors are shut.") + if(!state_open) + to_chat(usr, "The unit's doors are shut.") return - if(!src.ispowered || src.isbroken) - to_chat(usr, "The unit is not operational.") + if(broken) + to_chat(usr, "The unit is not operational.") return - if( (src.OCCUPANT) || (src.HELMET) || (src.SUIT) ) - to_chat(usr, "It's too cluttered inside for you to fit in!") + if((occupant) || (helmet) || (suit) || (storage)) + to_chat(usr, "It's too cluttered inside for you to fit in!") return visible_message("[usr] starts squeezing into the suit storage unit!") if(do_after(usr, 10, target = usr)) usr.stop_pulling() usr.forceMove(src) -// usr.metabslow = 1 - src.OCCUPANT = usr - src.isopen = 0 //Close the thing after the guy gets inside - src.update_icon() + occupant = usr + state_open = FALSE //Close the thing after the guy gets inside + update_icon() -// for(var/obj/O in src) -// qdel(O) - - src.add_fingerprint(usr) - src.updateUsrDialog() + add_fingerprint(usr) + updateUsrDialog() return else - src.OCCUPANT = null //Testing this as a backup sanity test - return - - -/obj/machinery/suit_storage_unit/attackby(obj/item/I as obj, mob/user as mob, params) - if(!src.ispowered) - return - if(istype(I, /obj/item/screwdriver)) - src.panelopen = !src.panelopen - playsound(src.loc, I.usesound, 100, 1) - to_chat(user, text("You [] the unit's maintenance panel.",(src.panelopen ? "open up" : "close") )) - src.updateUsrDialog() - return - if( istype(I, /obj/item/grab) ) - var/obj/item/grab/G = I - if( !(ismob(G.affecting)) ) - return - if(!src.isopen) - to_chat(usr, "The unit's doors are shut.") - return - if(!src.ispowered || src.isbroken) - to_chat(usr, "The unit is not operational.") - return - if( (src.OCCUPANT) || (src.HELMET) || (src.SUIT) ) //Unit needs to be absolutely empty - to_chat(user, "The unit's storage area is too cluttered.") - return - visible_message("[user] starts putting [G.affecting.name] into the Suit Storage Unit.") - if(do_after(user, 20, target = G:affecting)) - if(!G || !G.affecting) return //derpcheck - var/mob/M = G.affecting - M.forceMove(src) - src.OCCUPANT = M - src.isopen = 0 //close ittt - - //for(var/obj/O in src) - // O.loc = src.loc - src.add_fingerprint(user) - qdel(G) - src.updateUsrDialog() - src.update_icon() - return - return - if( istype(I,/obj/item/clothing/suit/space) ) - if(!src.isopen) - return - var/obj/item/clothing/suit/space/S = I - if(src.SUIT) - to_chat(user, "The unit already contains a suit.") - return - to_chat(user, "You load the [S.name] into the storage compartment.") - user.drop_item() - S.loc = src - src.SUIT = S - src.update_icon() - src.updateUsrDialog() - return - if( istype(I,/obj/item/clothing/head/helmet) ) - if(!src.isopen) - return - var/obj/item/clothing/head/helmet/H = I - if(src.HELMET) - to_chat(user, "The unit already contains a helmet.") - return - to_chat(user, "You load the [H.name] into the storage compartment.") - user.drop_item() - H.loc = src - src.HELMET = H - src.update_icon() - src.updateUsrDialog() - return - if( istype(I,/obj/item/clothing/mask) ) - if(!src.isopen) - return - var/obj/item/clothing/mask/M = I - if(src.MASK) - to_chat(user, "The unit already contains a mask.") - return - to_chat(user, "You load the [M.name] into the storage compartment.") - user.drop_item() - M.loc = src - src.MASK = M - src.update_icon() - src.updateUsrDialog() - return - src.update_icon() - src.updateUsrDialog() - return - + occupant = null /obj/machinery/suit_storage_unit/attack_ai(mob/user as mob) - return src.attack_hand(user) - - - -//////////////////////////////REMINDER: Make it lock once you place some fucker inside. - -//God this entire file is fucking awful -//Suit painter for Bay's special snowflake aliums. - -/obj/machinery/suit_cycler - - name = "suit cycler" - desc = "An industrial machine for repairing, painting and equipping hardsuits." - anchored = 1 - density = 1 - - icon = 'icons/obj/suitstorage.dmi' - icon_state = "suitstorage000000100" - - req_access = list(access_captain,access_heads) - - var/active = 0 // PLEASE HOLD. - var/safeties = 1 // The cycler won't start with a living thing inside it unless safeties are off. - var/irradiating = 0 // If this is > 0, the cycler is decontaminating whatever is inside it. - var/radiation_level = 2 // 1 is removing germs, 2 is removing blood, 3 is removing plasma. - var/model_text = "" // Some flavour text for the topic box. - var/locked = 1 // If locked, nothing can be taken from or added to the cycler. - - // Wiring bollocks. - var/wires = 15 - var/electrified = 0 - var/const/WIRE_EXTEND = 1 // Safeties - var/const/WIRE_SCANID = 2 // Locked status - var/const/WIRE_SHOCK = 3 // What it says on the tin. - - //Departments that the cycler can paint suits to look like. - var/list/departments = list("Engineering","Mining","Medical","Security","Atmos") - //Species that the suits can be configured to fit. - var/list/species = list("Human","Skrell","Unathi","Tajaran") - - var/target_department = "Engineering" - var/target_species = "Human" - - var/mob/living/carbon/human/occupant = null - var/obj/item/clothing/suit/space/hardsuit/suit = null - var/obj/item/clothing/head/helmet/space/helmet = null - -/obj/machinery/suit_cycler/engineering - name = "Engineering suit cycler" - model_text = "Engineering" - req_access = list(access_construction) - departments = list("Engineering","Atmos") - species = list("Human","Unathi","Tajaran") - -/obj/machinery/suit_cycler/mining - name = "Mining suit cycler" - model_text = "Mining" - req_access = list(access_mining) - departments = list("Mining") - species = list("Human","Unathi","Tajaran") - -/obj/machinery/suit_cycler/attack_ai(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/suit_cycler/attackby(obj/item/I as obj, mob/user as mob, params) - - if(electrified != 0) - if(src.shock(user, 100)) - return - - //Hacking init. - if(istype(I, /obj/item/multitool) || istype(I, /obj/item/wirecutters)) - if(panel_open) - attack_hand(user) - return - //Other interface stuff. - if(istype(I, /obj/item/grab)) - var/obj/item/grab/G = I - - if(!(ismob(G.affecting))) - return - - if(locked) - to_chat(user, "The suit cycler is locked.") - return - - if(src.contents.len > 0) - to_chat(user, "There is no room inside the cycler for [G.affecting.name].") - return - - visible_message("[user] starts putting [G.affecting.name] into the suit cycler.") - - if(do_after(user, 20, target = G:affecting)) - if(!G || !G.affecting) return - var/mob/M = G.affecting - M.forceMove(src) - src.occupant = M - - src.add_fingerprint(user) - qdel(G) - - src.updateUsrDialog() - - return - else if(istype(I,/obj/item/screwdriver)) - - panel_open = !panel_open - to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.") - src.updateUsrDialog() - return - - else if(istype(I,/obj/item/clothing/head/helmet/space)) - - if(locked) - to_chat(user, "The suit cycler is locked.") - return - - if(helmet) - to_chat(user, "The cycler already contains a helmet.") - return - - to_chat(user, "You fit \the [I] into the suit cycler.") - user.drop_item() - I.loc = src - helmet = I - - src.update_icon() - src.updateUsrDialog() - return - - else if(istype(I,/obj/item/clothing/suit/space/hardsuit)) - - if(locked) - to_chat(user, "The suit cycler is locked.") - return - - if(suit) - to_chat(user, "The cycler already contains a hardsuit.") - return - - var/obj/item/clothing/suit/space/hardsuit/S = I - - if(S.helmet) - to_chat(user, "\The [S] will not fit into the cycler with a helmet attached.") - return - - if(S.boots) - to_chat(user, "\The [S] will not fit into the cycler with boots attached.") - return - - to_chat(user, "You fit \the [I] into the suit cycler.") - user.drop_item() - I.loc = src - suit = I - - src.update_icon() - src.updateUsrDialog() - return - - ..() - -/obj/machinery/suit_cycler/emag_act(user as mob) - if(emagged) - to_chat(user, "The cycler has already been subverted.") - return - - //Clear the access reqs, disable the safeties, and open up all paintjobs. - to_chat(user, "You run the sequencer across the interface, corrupting the operating protocols.") - departments = list("Engineering","Mining","Medical","Security","Atmos","^%###^%$") - emagged = 1 - safeties = 0 - req_access = list() - return - -/obj/machinery/suit_cycler/attack_hand(mob/user as mob) - - add_fingerprint(user) - - if(..() || stat & (BROKEN|NOPOWER)) - return - - if(!user.IsAdvancedToolUser()) - return 0 - - if(electrified != 0) - if(src.shock(user, 100)) - return - - usr.set_machine(src) - - var/dat = "Suit Cycler Interface" - - if(src.active) - dat+= "
The [model_text ? "[model_text] " : ""]suit cycler is currently in use. Please wait..." - - else if(locked) - dat += "
The [model_text ? "[model_text] " : ""]suit cycler is currently locked. Please contact your system administrator." - if(src.allowed(usr)) - dat += "
\[unlock unit\]" - else - dat += "

Suit cycler

" - dat += "Welcome to the [model_text ? "[model_text] " : ""]suit cycler control panel. \[lock unit\]
" - - dat += "

Maintenance

" - dat += "Helmet: [helmet ? "\the [helmet]" : "no helmet stored" ]. \[eject\]
" - dat += "Suit: [suit ? "\the [suit]" : "no suit stored" ]. \[eject\]" - - if(suit && istype(suit)) - dat += "[(suit.damage ? " \[repair\]" : "")]" - - dat += "
UV decontamination systems: SYSTEM ERROR" : "green'>READY"]
" - dat += "Output level: [radiation_level]
" - dat += "\[select power level\] \[begin decontamination cycle\]

" - - dat += "

Customisation

" - dat += "Target product: [target_department], [target_species]." - dat += "
\[apply customisation routine\]


" - -/* if(panel_open) - var/list/vendwires = list( - "Violet" = 1, - "Orange" = 2, - "Goldenrod" = 3, - ) - dat += "

Access Panel

" - for(var/wiredesc in vendwires) - var/is_uncut = src.wires & APCWireColorToFlag[vendwires[wiredesc]] - dat += "[wiredesc] wire: " - if(!is_uncut) - dat += "Mend" - else - dat += "Cut " - dat += "Pulse " - dat += "
" - - dat += "
" - dat += "The orange light is [(electrified == 0) ? "off" : "on"].
" - dat += "The red light is [safeties ? "blinking" : "off"].
" - dat += "The yellow light is [locked ? "on" : "off"].
" */ - - var/datum/browser/popup = new(user, "suit_cycler", name, 400, 400) - popup.set_content(dat) - popup.open(0) - onclose(user, "suit_cycler") - return - -/obj/machinery/suit_cycler/Topic(href, href_list) - if(href_list["eject_suit"]) - if(!suit) return - suit.loc = get_turf(src) - suit = null - else if(href_list["eject_helmet"]) - if(!helmet) return - helmet.loc = get_turf(src) - helmet = null - else if(href_list["select_department"]) - var/choice = input("Please select the target department paintjob.","Suit cycler",null) as null|anything in departments - if(choice) target_department = choice - else if(href_list["select_species"]) - var/choice = input("Please select the target species configuration.","Suit cycler",null) as null|anything in species - if(choice) target_species = choice - else if(href_list["select_rad_level"]) - var/choices = list(1,2,3) - if(emagged) - choices = list(1,2,3,4,5) - radiation_level = input("Please select the desired radiation level.","Suit cycler",null) as null|anything in choices - else if(href_list["repair_suit"]) - - if(!suit) return - active = 1 - spawn(100) - repair_suit() - finished_job() - - else if(href_list["apply_paintjob"]) - - if(!suit && !helmet) return - active = 1 - spawn(100) - apply_paintjob() - finished_job() - - else if(href_list["toggle_safties"]) - safeties = !safeties - - else if(href_list["toggle_lock"]) - - if(src.allowed(usr)) - locked = !locked - to_chat(usr, "You [locked ? "" : "un"]lock \the [src].") - else - to_chat(usr, "Access denied.") - - else if(href_list["begin_decontamination"]) - - if(safeties && occupant) - to_chat(usr, "The cycler has detected an occupant. Please remove the occupant before commencing the decontamination cycle.") - return - - active = 1 - irradiating = 10 - src.updateUsrDialog() - - sleep(10) - - if(helmet) - if(radiation_level > 1) - helmet.clean_blood() - - if(suit) - if(radiation_level > 1) - suit.clean_blood() - -/* else if((href_list["cutwire"]) && (src.panel_open)) - var/twire = text2num(href_list["cutwire"]) - if(!( istype(usr.get_active_hand(), /obj/item/wirecutters) )) - to_chat(usr, "You need wirecutters!") - return - if(src.isWireColorCut(twire)) - src.mend(twire) - else - src.cut(twire) - - else if((href_list["pulsewire"]) && (src.panel_open)) - var/twire = text2num(href_list["pulsewire"]) - if(!istype(usr.get_active_hand(), /obj/item/multitool)) - to_chat(usr, "You need a multitool!") - return - if(src.isWireColorCut(twire)) - to_chat(usr, "You can't pulse a cut wire.") - return - else - src.pulse(twire)*/ - - src.updateUsrDialog() - return - -/obj/machinery/suit_cycler/process() - - if(electrified > 0) - electrified-- - - if(!active) - return - - if(active && stat & (BROKEN|NOPOWER)) - active = 0 - irradiating = 0 - electrified = 0 - return - - if(irradiating == 1) - finished_job() - irradiating = 0 - return - - irradiating-- - - if(occupant) - if(prob(radiation_level*2)) occupant.emote("scream") - if(radiation_level > 2) - occupant.take_organ_damage(0,radiation_level*2 + rand(1,3)) - if(radiation_level > 1) - occupant.take_organ_damage(0,radiation_level + rand(1,3)) - occupant.apply_effect(radiation_level*10, IRRADIATE) - -/obj/machinery/suit_cycler/proc/finished_job() - var/turf/T = get_turf(src) - T.visible_message("\The [src] pings loudly.") - icon_state = initial(icon_state) - active = 0 - src.updateUsrDialog() - -/obj/machinery/suit_cycler/proc/repair_suit() - if(!suit || !suit.damage || !suit.can_breach) - return - - suit.breaches = list() - suit.calc_breach_damage() - - return - -/obj/machinery/suit_cycler/verb/leave() - set name = "Eject Cycler" - set category = "Object" - set src in oview(1) - - if(usr.stat != 0) - return - - eject_occupant(usr) - -/obj/machinery/suit_cycler/proc/eject_occupant(mob/user as mob) - - if(locked || active) - to_chat(user, "The cycler is locked.") - return - - if(!occupant) - return - - occupant.forceMove(loc) - occupant = null - - add_fingerprint(usr) - updateUsrDialog() - update_icon() - - return -/* -//HACKING PROCS, MOSTLY COPIED FROM VENDING MACHINES -/obj/machinery/suit_cycler/proc/isWireColorCut(var/wireColor) - var/wireFlag = APCWireColorToFlag[wireColor] - return ((src.wires & wireFlag) == 0) - -/obj/machinery/suit_cycler/proc/isWireCut(var/wireIndex) - var/wireFlag = APCIndexToFlag[wireIndex] - return ((src.wires & wireFlag) == 0) - -/obj/machinery/suit_cycler/proc/cut(var/wireColor) - var/wireFlag = APCWireColorToFlag[wireColor] - var/wireIndex = APCWireColorToIndex[wireColor] - src.wires &= ~wireFlag - switch(wireIndex) - - if(WIRE_EXTEND) - safeties = 0 - if(WIRE_SHOCK) - electrified = -1 - if(WIRE_SCANID) - locked = 0 - -/obj/machinery/suit_cycler/proc/mend(var/wireColor) - var/wireFlag = APCWireColorToFlag[wireColor] - var/wireIndex = APCWireColorToIndex[wireColor] //not used in this function - src.wires |= wireFlag - switch(wireIndex) - if(WIRE_SHOCK) - src.electrified = 0 - -/obj/machinery/suit_cycler/proc/pulse(var/wireColor) - var/wireIndex = APCWireColorToIndex[wireColor] - switch(wireIndex) - if(WIRE_EXTEND) - safeties = !locked - if(WIRE_SHOCK) - electrified = 30 - if(WIRE_SCANID) - locked = !locked -*/ - -//There HAS to be a less bloated way to do this. TODO: some kind of table/icon name coding? ~Z -/obj/machinery/suit_cycler/proc/apply_paintjob() - - if(!target_species || !target_department) - return - - if(target_species) - if(helmet) helmet.refit_for_species(target_species) - if(suit) suit.refit_for_species(target_species) - - switch(target_department) - if("Engineering") - if(helmet) - helmet.name = "engineering hardsuit helmet" - helmet.icon_state = "hardsuit0-engineering" - helmet.item_state = "eng_helm" - helmet.item_color = "engineering" - if(suit) - suit.name = "engineering hardsuit" - suit.icon_state = "hardsuit-engineering" - suit.item_state = "eng_hardsuit" - if("Mining") - if(helmet) - helmet.name = "mining hardsuit helmet" - helmet.icon_state = "hardsuit0-mining" - helmet.item_state = "mining_helm" - helmet.item_color = "mining" - if(suit) - suit.name = "mining hardsuit" - suit.icon_state = "hardsuit-mining" - suit.item_state = "mining_hardsuit" - if("Medical") - if(helmet) - helmet.name = "medical hardsuit helmet" - helmet.icon_state = "hardsuit0-medical" - helmet.item_state = "medical_helm" - helmet.item_color = "medical" - if(suit) - suit.name = "medical hardsuit" - suit.icon_state = "hardsuit-medical" - suit.item_state = "medical_hardsuit" - if("Security") - if(helmet) - helmet.name = "security hardsuit helmet" - helmet.icon_state = "hardsuit0-sec" - helmet.item_state = "sec_helm" - helmet.item_color = "sec" - if(suit) - suit.name = "security hardsuit" - suit.icon_state = "hardsuit-sec" - suit.item_state = "sec_hardsuit" - if("Atmos") - if(helmet) - helmet.name = "atmospherics hardsuit helmet" - helmet.icon_state = "hardsuit0-atmos" - helmet.item_state = "atmos_helm" - helmet.item_color = "atmos" - if(suit) - suit.name = "atmospherics hardsuit" - suit.icon_state = "hardsuit-atmos" - suit.item_state = "atmos_hardsuit" - if("^%###^%$") - if(helmet) - helmet.name = "blood-red hardsuit helmet" - helmet.icon_state = "hardsuit0-syndie" - helmet.item_state = "syndie_helm" - helmet.item_color = "syndie" - if(suit) - suit.name = "blood-red hardsuit" - suit.item_state = "syndie_hardsuit" - suit.icon_state = "hardsuit-syndie" + return attack_hand(user) diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 42d241404b1..d26a24b39a2 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -180,7 +180,6 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3"," var/turf/simulated/floor/plating/P = pry_tile(CB, user, TRUE) if(!istype(P)) return - update_icon() P.attackby(T, user, params) /turf/simulated/floor/proc/pry_tile(obj/item/C, mob/user, silent = FALSE) diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 4c6eee6311e..c6de130c81a 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -15,9 +15,6 @@ /turf/simulated/floor/plating/New() ..() icon_plating = icon_state - if(icon == 'icons/turf/floors/plating.dmi') - smooth = SMOOTH_MORE - canSmoothWith = list(/turf/simulated/floor/plating, /turf/space) update_icon() /turf/simulated/floor/plating/update_icon() @@ -25,7 +22,6 @@ return if(!broken && !burnt) icon_state = icon_plating //Because asteroids are 'platings' too. - underlays += image(icon, icon_state) /turf/simulated/floor/plating/attackby(obj/item/C, mob/user, params) if(..()) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 2e60537ce6f..4d6974f702f 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -226,8 +226,6 @@ for(var/obj/structure/cable/C in contents) qdel(C) - smooth_icon(src) - /turf/simulated/AfterChange(ignore_air, keep_cabling = FALSE) ..() RemoveLattice() diff --git a/code/modules/hydroponics/grown/kudzu.dm b/code/modules/hydroponics/grown/kudzu.dm index 855ca829bfa..ba67bf426fa 100644 --- a/code/modules/hydroponics/grown/kudzu.dm +++ b/code/modules/hydroponics/grown/kudzu.dm @@ -59,7 +59,7 @@ mutations.Remove(pick(temp_mut_list)) temp_mut_list.Cut() - if(S.has_reagent("welding_fuel", 5)) + if(S.has_reagent("fuel", 5)) for(var/datum/spacevine_mutation/SM in mutations) if(SM.quality == POSITIVE) temp_mut_list += SM @@ -94,4 +94,4 @@ desc = "Pueraria Virallis: An invasive species with vines that rapidly creep and wrap around whatever they contact." icon_state = "kudzupod" filling_color = "#6B8E23" - bitesize_mod = 2 \ No newline at end of file + bitesize_mod = 2 diff --git a/code/modules/hydroponics/sample.dm b/code/modules/hydroponics/sample.dm index 4478671b2fb..e2d5ea6eb97 100644 --- a/code/modules/hydroponics/sample.dm +++ b/code/modules/hydroponics/sample.dm @@ -12,7 +12,7 @@ var/list/chem_t2_reagents = list( var/list/chem_t3_reagents = list( "ethanol", "chlorine", "potassium", "aluminium", "radium", "fluorine", - "iron", "welding_fuel", "silver", + "iron", "fuel", "silver", "stable_plasma" ) @@ -41,4 +41,4 @@ var/list/chem_t4_reagents = list( /obj/item/seeds/sample/alienweed name = "alien weed sample" icon_state = "alienweed" - sample_color = null \ No newline at end of file + sample_color = null diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 303b34aed34..79cfc3ae9f8 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -462,10 +462,10 @@ var/global/list/rockTurfEdgeCache = list( /turf/simulated/floor/plating/airless/asteroid/New() var/proper_name = name + ..() name = proper_name if(prob(20)) icon_state = "asteroid[rand(0,12)]" - ..() /turf/simulated/floor/plating/airless/asteroid/ex_act(severity, target) switch(severity) diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm index 45e28a85ee4..1797fc8b4bd 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -38,6 +38,8 @@ var/datum/paiController/paiController // Global handler for pAI candidates var/obj/item/paicard/card = locate(href_list["device"]) if(card.pai) return + if(usr.incapacitated() || isobserver(usr) || !card.Adjacent(usr)) + return if(istype(card,/obj/item/paicard) && istype(candidate,/datum/paiCandidate)) var/mob/living/silicon/pai/pai = new(card) if(!candidate.name) diff --git a/code/modules/modular_computers/file_system/computer_file.dm b/code/modules/modular_computers/file_system/computer_file.dm index 25ca387a78e..f3b5a9659b2 100644 --- a/code/modules/modular_computers/file_system/computer_file.dm +++ b/code/modules/modular_computers/file_system/computer_file.dm @@ -4,10 +4,11 @@ var/global/file_uid = 0 var/filename = "NewFile" // Placeholder. No spacebars var/filetype = "XXX" // File full names are [filename].[filetype] so like NewFile.XXX in this case var/size = 1 // File size in GQ. Integers only! - var/obj/item/computer_hardware/hard_drive/holder // Holder that contains this file. + var/obj/item/computer_hardware/hard_drive/holder // Holder that contains this file. var/unsendable = 0 // Whether the file may be sent to someone via NTNet transfer or other means. var/undeletable = 0 // Whether the file may be deleted. Setting to 1 prevents deletion/renaming/etc. var/uid // UID of this file + var/password = "" // Placeholder for password. /datum/computer_file/New() ..() @@ -36,4 +37,14 @@ var/global/file_uid = 0 else temp.filename = filename temp.filetype = filetype - return temp \ No newline at end of file + temp.password = password + return temp + +/datum/computer_file/proc/can_access_file(mob/user, input_password = "") + if(!password) + return TRUE + if(!input_password) + input_password = sanitize(input(user, "Please enter a password to access file '[filename]':")) + if(input_password == password) + return TRUE + return FALSE \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/generic/file_browser.dm b/code/modules/modular_computers/file_system/programs/generic/file_browser.dm index 89fea156510..23b2cdab7ab 100644 --- a/code/modules/modular_computers/file_system/programs/generic/file_browser.dm +++ b/code/modules/modular_computers/file_system/programs/generic/file_browser.dm @@ -55,7 +55,8 @@ "name" = F.filename, "type" = F.filetype, "size" = F.size, - "undeletable" = F.undeletable + "undeletable" = F.undeletable, + "encrypted" = !!F.password ))) data["files"] = files if(RHDD) @@ -66,7 +67,8 @@ "name" = F.filename, "type" = F.filetype, "size" = F.size, - "undeletable" = F.undeletable + "undeletable" = F.undeletable, + "encrypted" = !!F.password ))) data["usbfiles"] = usbfiles @@ -83,6 +85,9 @@ switch(href_list["action"]) if("PRG_openfile") . = 1 + var/datum/computer_file/F = HDD.find_file_by_name(href_list["name"]) + if(!F.can_access_file(usr)) + return open_file = href_list["name"] if("PRG_newtextfile") . = 1 @@ -197,4 +202,27 @@ if(!F || !istype(F)) return 1 var/datum/computer_file/C = F.clone(0) - HDD.store_file(C) \ No newline at end of file + HDD.store_file(C) + if("PRG_encrypt") + . = 1 + if(!HDD) + return 1 + var/datum/computer_file/F = HDD.find_file_by_name(href_list["name"]) + if(!F || F.undeletable) + return 1 + if(F.password) + return + var/new_password = sanitize(input(usr, "Enter an encryption key:", "Encrypt File")) + if(!new_password) + to_chat(usr, "File not encrypted.") + return + F.password=new_password + if("PRG_decrypt") + . = 1 + if(!HDD) + return 1 + var/datum/computer_file/F = HDD.find_file_by_name(href_list["name"]) + if(!F || F.undeletable) + return 1 + if(F.can_access_file(usr)) + F.password = "" \ No newline at end of file diff --git a/html/changelog.html b/html/changelog.html index 735cb9d6cee..2b13f2dbd94 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,11 +56,38 @@ -->
+

20 October 2018

+

Dapocalypse updated:

+
    +
  • Adds password protected files to modular computer.
  • +
+

Purpose updated:

+
    +
  • Suit storage units now contain magboots for relevant roles.
  • +
  • Adds the captains jetpack to his suit storage unit, so it is now stealable again on Delta.
  • +
+

uc_guy updated:

+
    +
  • It is no longer possible to duplicate uvents.
  • +
+

variableundefined updated:

+
    +
  • Plating's icon is back to the old one once again.
  • +
+

19 October 2018

Fox McCloud updated:

  • Fixes round-start sparks being stuck in maintenance
+

Purpose updated:

+
    +
  • Fixed an issue with Space Vine mutations
  • +
+

SpaceManiac updated:

+
    +
  • The body zone selector now indicates which body part you are about to select when hovered over.
  • +

TDSSS updated:

  • New exosuit equipment: The rescue jaws for the Odysseus lets it open doors, firelocks and even force powered doors. It can also be added to firefighter ripleys.
  • diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 24edf7d9cf9..27ae375792b 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -7563,6 +7563,11 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. 2018-10-19: Fox McCloud: - bugfix: Fixes round-start sparks being stuck in maintenance + Purpose: + - bugfix: Fixed an issue with Space Vine mutations + SpaceManiac: + - rscadd: The body zone selector now indicates which body part you are about to + select when hovered over. TDSSS: - rscadd: 'New exosuit equipment: The rescue jaws for the Odysseus lets it open doors, firelocks and even force powered doors. It can also be added to firefighter @@ -7574,3 +7579,14 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - rscdel: Removed old UI from safe - tweak: Safe now is only Right - Left - Right. Safe is 0-99 rather than 0-71. - imageadd: Added safe dial for it's nanoui. +2018-10-20: + Dapocalypse: + - rscadd: Adds password protected files to modular computer. + Purpose: + - rscadd: Suit storage units now contain magboots for relevant roles. + - bugfix: Adds the captains jetpack to his suit storage unit, so it is now stealable + again on Delta. + uc_guy: + - bugfix: It is no longer possible to duplicate uvents. + variableundefined: + - tweak: Plating's icon is back to the old one once again. diff --git a/html/changelogs/AutoChangeLog-pr-9894.yml b/html/changelogs/AutoChangeLog-pr-9894.yml new file mode 100644 index 00000000000..07a4419b100 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9894.yml @@ -0,0 +1,4 @@ +author: "craftxbox" +delete-after: True +changes: + - bugfix: "added check to make sure person downloading pAI isnt dead." diff --git a/html/changelogs/AutoChangeLog-pr-9908.yml b/html/changelogs/AutoChangeLog-pr-9908.yml new file mode 100644 index 00000000000..f18a7bceab8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9908.yml @@ -0,0 +1,4 @@ +author: "Fox McCloud" +delete-after: True +changes: + - tweak: "Updates the Garbage SS so it's less likely to induce lag" diff --git a/icons/obj/machines/suit_storage.dmi b/icons/obj/machines/suit_storage.dmi new file mode 100644 index 00000000000..e61f9567c60 Binary files /dev/null and b/icons/obj/machines/suit_storage.dmi differ diff --git a/icons/obj/suitstorage.dmi b/icons/obj/suitstorage.dmi deleted file mode 100644 index 3fc3e4e7337..00000000000 Binary files a/icons/obj/suitstorage.dmi and /dev/null differ diff --git a/icons/turf/floors/plating.dmi b/icons/turf/floors/plating.dmi index c3c480bfc6a..fee52346e3c 100644 Binary files a/icons/turf/floors/plating.dmi and b/icons/turf/floors/plating.dmi differ diff --git a/nano/templates/file_manager.tmpl b/nano/templates/file_manager.tmpl index 1bdb0cd95c4..51d40b84475 100644 --- a/nano/templates/file_manager.tmpl +++ b/nano/templates/file_manager.tmpl @@ -32,6 +32,11 @@ {{:helper.link('DELETE', 'trash', {'action' : 'PRG_deletefile', 'name' : value.name}, value.undeletable ? 'disabled' : null)}} {{:helper.link('RENAME', 'pencil', {'action' : 'PRG_rename', 'name' : value.name}, value.undeletable ? 'disabled' : null)}} {{:helper.link('CLONE', 'files-o', {'action' : 'PRG_clone', 'name' : value.name}, value.undeletable ? 'disabled' : null)}} + {{if !value.encrypted}} + {{:helper.link('ENCRYPT', null, {'action' : 'PRG_encrypt', 'name' : value.name}, value.undeletable ? 'disabled' : null)}} + {{else}} + {{:helper.link('DECRYPT', null, {'action' : 'PRG_decrypt', 'name' : value.name}, value.undeletable ? 'disabled' : null)}} + {{/if}} {{if data.usbconnected}} {{:helper.link('EXPORT', 'upload', {'action' : 'PRG_copytousb', 'name' : value.name}, value.undeletable ? 'disabled' : null)}} {{/if}}