// SUIT STORAGE UNIT ///////////////// /obj/machinery/suit_storage_unit name = "suit storage unit" desc = "An industrial unit made to hold and decontaminate irradiated equipment. It comes with a built-in UV cauterization mechanism. A small warning label advises that organic matter should not be placed into the unit." icon = 'icons/obj/machines/suit_storage.dmi' icon_state = "close" 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/clothing/shoes/shoes = null var/obj/item/mod/control/mod = null var/obj/item/storage = null // if you add more storage slots, update cook() to clear their radiation too. /// What type of spacesuit the unit starts with when spawned. var/suit_type = null /// What type of space helmet the unit starts with when spawned. var/helmet_type = null /// What type of breathmask the unit starts with when spawned. var/mask_type = null /// What type of shoes the unit starts with when spawned. var/shoes_type = null /// What type of MOD the unit starts with when spawned. var/mod_type = null /// What type of additional item the unit starts with when spawned. var/storage_type = null state_open = FALSE /// If the SSU's doors are locked closed. Can be toggled manually via the UI, but is also locked automatically when the UV decontamination sequence is running. var/locked = FALSE panel_open = FALSE /// If the safety wire is cut/pulsed, the SSU can run the decontamination sequence while occupied by a mob. The mob will be burned during every cycle of cook(). var/safeties = TRUE /// If UV decontamination sequence is running. See cook() var/uv = FALSE /** * If the hack wire is cut/pulsed. * Modifies effects of cook() * * If FALSE, decontamination sequence will clear radiation for all atoms (and their contents) contained inside the unit, and burn any mobs inside. * * If TRUE, decontamination sequence will delete all items contained within, and if occupied by a mob, intensifies burn damage delt. All wires will be cut at the end. */ var/uv_super = FALSE /// How many cycles remain for the decontamination sequence. var/uv_cycles = 6 /// Cooldown for occupant breakout messages via relaymove() var/message_cooldown /// How long it takes to break out of the SSU. var/breakout_time = 300 /// How fast it charges cells in a suit var/charge_rate = 250 /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 /obj/machinery/suit_storage_unit/captain suit_type = /obj/item/clothing/suit/space/hardsuit/captain mask_type = /obj/item/clothing/mask/gas/sechailer storage_type = /obj/item/tank/jetpack/oxygen/captain /obj/machinery/suit_storage_unit/captainmod mask_type = /obj/item/clothing/mask/gas/sechailer storage_type = /obj/item/tank/jetpack/oxygen/captain mod_type = /obj/item/mod/control/pre_equipped/magnate /obj/machinery/suit_storage_unit/engine suit_type = /obj/item/clothing/suit/space/hardsuit/engine mask_type = /obj/item/clothing/mask/breath shoes_type = /obj/item/clothing/shoes/magboots /obj/machinery/suit_storage_unit/atmos suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos mask_type = /obj/item/clothing/mask/breath storage_type = /obj/item/watertank/atmos /obj/machinery/suit_storage_unit/enginemod mask_type = /obj/item/clothing/mask/breath mod_type = /obj/item/mod/control/pre_equipped/engineering /obj/machinery/suit_storage_unit/atmos suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos mask_type = /obj/item/clothing/mask/breath storage_type = /obj/item/watertank/atmos /obj/machinery/suit_storage_unit/atmosmod mask_type = /obj/item/clothing/mask/breath storage_type = /obj/item/watertank/atmos mod_type = /obj/item/mod/control/pre_equipped/atmospheric /obj/machinery/suit_storage_unit/ce suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite mask_type = /obj/item/clothing/mask/breath shoes_type = /obj/item/clothing/shoes/magboots/advance /obj/machinery/suit_storage_unit/cemod mask_type = /obj/item/clothing/mask/breath storage_type = /obj/item/clothing/shoes/magboots/advance mod_type = /obj/item/mod/control/pre_equipped/advanced /obj/machinery/suit_storage_unit/security suit_type = /obj/item/clothing/suit/space/hardsuit/security mask_type = /obj/item/clothing/mask/gas/sechailer storage_type = /obj/item/tank/jetpack/oxygen/security /obj/machinery/suit_storage_unit/securitymod mask_type = /obj/item/clothing/mask/gas/sechailer mod_type = /obj/item/mod/control/pre_equipped/security /obj/machinery/suit_storage_unit/hos suit_type = /obj/item/clothing/suit/space/hardsuit/security/hos mask_type = /obj/item/clothing/mask/gas/sechailer storage_type = /obj/item/tank/internals/oxygen /obj/machinery/suit_storage_unit/atmos suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos mask_type = /obj/item/clothing/mask/gas storage_type = /obj/item/watertank/atmos /obj/machinery/suit_storage_unit/hosmod mask_type = /obj/item/clothing/mask/gas/sechailer storage_type = /obj/item/tank/internals/oxygen mod_type = /obj/item/mod/control/pre_equipped/safeguard /obj/machinery/suit_storage_unit/mining suit_type = /obj/item/clothing/suit/hooded/explorer/standard mask_type = /obj/item/clothing/mask/gas/explorer /obj/machinery/suit_storage_unit/mining/eva suit_type = /obj/item/clothing/suit/space/hardsuit/mining mask_type = /obj/item/clothing/mask/breath /obj/machinery/suit_storage_unit/mining/evahos suit_type = null mask_type = /obj/item/clothing/mask/breath mod_type = /obj/item/mod/control/pre_equipped/mining /obj/machinery/suit_storage_unit/medicalmod mask_type = /obj/item/clothing/mask/breath/medical storage_type = /obj/item/tank/internals/oxygen mod_type = /obj/item/mod/control/pre_equipped/medical /obj/machinery/suit_storage_unit/cmo suit_type = /obj/item/clothing/suit/space/hardsuit/medical mask_type = /obj/item/clothing/mask/breath /obj/machinery/suit_storage_unit/paramedic name = "paramedic suit storage unit" suit_type = /obj/item/clothing/suit/space/eva/paramedic helmet_type = /obj/item/clothing/head/helmet/space/eva/paramedic mask_type = /obj/item/clothing/mask/breath /obj/machinery/suit_storage_unit/cmomod mask_type = /obj/item/clothing/mask/breath/medical storage_type = /obj/item/tank/internals/oxygen mod_type = /obj/item/mod/control/pre_equipped/rescue /obj/machinery/suit_storage_unit/rd suit_type = /obj/item/clothing/suit/space/hardsuit/rd mask_type = /obj/item/clothing/mask/breath /obj/machinery/suit_storage_unit/rdmod mask_type = /obj/item/clothing/mask/breath mod_type = /obj/item/mod/control/pre_equipped/research /obj/machinery/suit_storage_unit/syndicate suit_type = /obj/item/clothing/suit/space/hardsuit/syndi mask_type = /obj/item/clothing/mask/gas/syndicate storage_type = /obj/item/tank/jetpack/oxygen/harness /obj/machinery/suit_storage_unit/syndicatemod mask_type = /obj/item/clothing/mask/gas/syndicate storage_type = /obj/item/tank/jetpack/oxygen/harness mod_type = /obj/item/mod/control/pre_equipped/nuclear /obj/machinery/suit_storage_unit/ert/command suit_type = /obj/item/clothing/suit/space/hardsuit/ert mask_type = /obj/item/clothing/mask/breath storage_type = /obj/item/tank/internals/emergency_oxygen/double /obj/machinery/suit_storage_unit/ert/security suit_type = /obj/item/clothing/suit/space/hardsuit/ert/sec mask_type = /obj/item/clothing/mask/breath storage_type = /obj/item/tank/internals/emergency_oxygen/double /obj/machinery/suit_storage_unit/ert/engineer suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engi mask_type = /obj/item/clothing/mask/breath storage_type = /obj/item/tank/internals/emergency_oxygen/double /obj/machinery/suit_storage_unit/ert/medical suit_type = /obj/item/clothing/suit/space/hardsuit/ert/med mask_type = /obj/item/clothing/mask/breath storage_type = /obj/item/tank/internals/emergency_oxygen/double /obj/machinery/suit_storage_unit/radsuit name = "radiation suit storage unit" suit_type = /obj/item/clothing/suit/radiation helmet_type = /obj/item/clothing/head/radiation storage_type = /obj/item/geiger_counter /obj/machinery/suit_storage_unit/open state_open = TRUE density = FALSE /obj/machinery/suit_storage_unit/Initialize(mapload) . = ..() wires = new /datum/wires/suit_storage_unit(src) 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(shoes_type) shoes = new shoes_type(src) if(mod_type) mod = new mod_type(src) if(storage_type) storage = new storage_type(src) update_icon() /obj/machinery/suit_storage_unit/Destroy() QDEL_NULL(suit) QDEL_NULL(helmet) QDEL_NULL(mask) QDEL_NULL(shoes) QDEL_NULL(mod) QDEL_NULL(storage) return ..() /obj/machinery/suit_storage_unit/update_overlays() . = ..() if(uv) if(uv_super) . += "super" else if(occupant) . += "uvhuman" else . += "uv" else if(state_open) if(stat & BROKEN) . += "broken" else . += "open" if(suit || mod) . += "suit" if(helmet) . += "helm" if(shoes || storage) . += "storage" else if(occupant) . += "human" /obj/machinery/suit_storage_unit/power_change() . = ..() 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 mod = null storage = null occupant = null /obj/machinery/suit_storage_unit/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) 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 unit's doors are shut!") return if(!is_operational()) to_chat(user, "The unit is not operational!") return if(occupant || helmet || suit || shoes || 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 target.visible_message("[user] starts shoving [target] into [src]!", "[user] starts shoving you into [src]!") if(do_mob(user, target, 30)) if(occupant || helmet || suit || shoes || 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 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) /** * UV decontamination sequence. * Duration is determined by the uv_cycles var. * Effects determined by the uv_super var. * * If FALSE, all atoms (and their contents) contained are cleared of radiation. If a mob is inside, they are burned every cycle. * * If TRUE, all items contained are destroyed, and burn damage applied to the mob is increased. All wires will be cut at the end. * All atoms still inside at the end of all cycles are ejected from the unit. */ /obj/machinery/suit_storage_unit/proc/cook() var/mob/living/mob_occupant = occupant if(uv_cycles) uv_cycles-- uv = TRUE locked = TRUE update_icon() if(occupant) if(uv_super) mob_occupant.adjustFireLoss(rand(20, 36)) else mob_occupant.adjustFireLoss(rand(10, 16)) if(iscarbon(mob_occupant) && mob_occupant.stat < UNCONSCIOUS) //Awake, organic and screaming 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) shoes = null qdel(shoes) mod = null qdel(mod) storage = null qdel(storage) // The wires get damaged too. wires.cut_all() 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.") mob_occupant.radiation = 0 playsound(src, 'sound/machines/airlockclose.ogg', 25, TRUE) var/list/things_to_clear = list() //Done this way since using GetAllContents on the SSU itself would include circuitry and such. if(suit) things_to_clear += suit things_to_clear += suit.GetAllContents() if(helmet) things_to_clear += helmet things_to_clear += helmet.GetAllContents() if(mask) things_to_clear += mask things_to_clear += mask.GetAllContents() if(shoes) things_to_clear += shoes things_to_clear += shoes.GetAllContents() if(mod) things_to_clear += mod things_to_clear += mod.GetAllContents() if(storage) things_to_clear += storage things_to_clear += storage.GetAllContents() if(occupant) things_to_clear += occupant things_to_clear += occupant.GetAllContents() for(var/atom/movable/AM in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG) AM.clean_blood() AM.fingerprints = null var/datum/component/radioactive/contamination = AM.GetComponent(/datum/component/radioactive) if(contamination) qdel(contamination) open_machine(FALSE) if(occupant) dump_contents() /obj/machinery/suit_storage_unit/process(delta_time) var/obj/item/stock_parts/cell/cell if(mod) if(!istype(mod)) return if(!mod.cell) return cell = mod.cell else return use_power(charge_rate * delta_time) cell.give(charge_rate * delta_time) /obj/machinery/suit_storage_unit/proc/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.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 == 0) // Check they're still here. visible_message("You see [user] burst out of [src]!", \ "You escape the cramped confines of [src]!") open_machine() /obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params) if(state_open && is_operational()) if(istype(I, /obj/item/clothing/head/mob_holder)) to_chat(user, "You can't quite fit that in while you hold it!") return if(istype(I, /obj/item/clothing/suit)) if(suit) to_chat(user, "The unit already contains a suit!.") return if(!user.transferItemToLoc(I, src)) return suit = I else if(istype(I, /obj/item/clothing/head)) if(helmet) to_chat(user, "The unit already contains a helmet!") return if(!user.transferItemToLoc(I, src)) return helmet = I else if(istype(I, /obj/item/clothing/mask)) if(mask) to_chat(user, "The unit already contains a mask!") return if(!user.transferItemToLoc(I, src)) return mask = I else if(istype(I, /obj/item/clothing/shoes)) if(shoes) to_chat(user, "The unit already contains some shoes!") return if(!user.transferItemToLoc(I, src)) return shoes = I else if(istype(I, /obj/item/mod/control)) if(mod) to_chat(user, span_warning("The unit already contains a MOD!")) return if(!user.transferItemToLoc(I, src)) return mod = I else if(storage) to_chat(user, "The auxiliary storage compartment is full!") return if(!user.transferItemToLoc(I, src)) return storage = I visible_message("[user] inserts [I] into [src]", "You load [I] into [src].") update_icon() return if(panel_open && is_wire_tool(I)) wires.interact(user) return if(!state_open) if(default_deconstruction_screwdriver(user, "panel", "close", I)) return if(default_pry_open(I)) dump_contents() return return ..() /obj/machinery/suit_storage_unit/ui_state(mob/user) return GLOB.notcontained_state /obj/machinery/suit_storage_unit/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "SuitStorageUnit", name) ui.open() /obj/machinery/suit_storage_unit/ui_data() var/list/data = list() data["locked"] = locked data["open"] = state_open data["safeties"] = safeties data["uv_active"] = uv data["uv_super"] = uv_super if(helmet) data["helmet"] = helmet.name else data["helmet"] = null if(suit) data["suit"] = suit.name else data["suit"] = null if(mask) data["mask"] = mask.name else data["mask"] = null if(shoes) data["shoes"] = shoes.name else data["shoes"] = null if(mod) data["mod"] = mod.name else data["mod"] = null if(storage) data["storage"] = storage.name else data["storage"] = null if(occupant) data["occupied"] = TRUE else data["occupied"] = FALSE return data /obj/machinery/suit_storage_unit/ui_act(action, params) if(..() || uv) return switch(action) if("door") if(state_open) close_machine() else open_machine(0) if(occupant) dump_contents() // Dump out contents if someone is in there. . = TRUE if("lock") if(state_open) return locked = !locked . = TRUE if("uv") if(occupant && safeties) return else if(!helmet && !mask && !mod && !suit && !storage && !occupant) return else if(occupant) var/mob/living/mob_occupant = occupant to_chat(mob_occupant, "[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!") cook() . = TRUE if("dispense") if(!state_open) return var/static/list/valid_items = list("helmet", "suit", "mask", "shoes", "mod", "storage") var/item_name = params["item"] if(item_name in valid_items) var/obj/item/I = vars[item_name] vars[item_name] = null if(I) var/mob/living/living_person = usr if(!istype(living_person)) return if(!istype(living_person) || !Adjacent(living_person) || !living_person.put_in_active_hand(I)) I.forceMove(loc) . = TRUE update_icon() /obj/machinery/suit_storage_unit/default_pry_open(obj/item/I)//needs to check if the storage is locked. . = !(state_open || panel_open || is_operational() || locked || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR if(.) I.play_tool_sound(src, 50) visible_message("[usr] pries open \the [src].", "You pry open \the [src].") open_machine()