From cfce12f0230d7180f9f50dbc5416ddc3c418b67d Mon Sep 17 00:00:00 2001 From: Heroman3003 <31296024+Heroman3003@users.noreply.github.com> Date: Sat, 10 Jun 2023 14:05:52 +1000 Subject: [PATCH] Store your suits and borgs more properly --- .../machinery/suit_storage/suit_cycler.dm | 547 ++++++++ .../{ => suit_storage}/suit_cycler_datums.dm | 0 .../suit_storage/suit_cycler_units.dm | 112 ++ .../suit_cycler_units_vr.dm} | 9 + .../machinery/suit_storage/suit_storage.dm | 476 +++++++ .../suit_storage/suit_storage_units.dm | 54 + code/game/machinery/suit_storage_unit.dm | 1131 ----------------- icons/obj/robot_storage.dmi | Bin 5948 -> 1459 bytes icons/obj/suit_cycler.dmi | Bin 0 -> 2175 bytes icons/obj/suit_storage.dmi | Bin 0 -> 4070 bytes icons/obj/suitstorage.dmi | Bin 28189 -> 0 bytes vorestation.dme | 9 + 12 files changed, 1207 insertions(+), 1131 deletions(-) create mode 100644 code/game/machinery/suit_storage/suit_cycler.dm rename code/game/machinery/{ => suit_storage}/suit_cycler_datums.dm (100%) create mode 100644 code/game/machinery/suit_storage/suit_cycler_units.dm rename code/game/machinery/{suit_storage_unit_vr.dm => suit_storage/suit_cycler_units_vr.dm} (89%) create mode 100644 code/game/machinery/suit_storage/suit_storage.dm create mode 100644 code/game/machinery/suit_storage/suit_storage_units.dm delete mode 100644 code/game/machinery/suit_storage_unit.dm create mode 100644 icons/obj/suit_cycler.dmi create mode 100644 icons/obj/suit_storage.dmi delete mode 100644 icons/obj/suitstorage.dmi diff --git a/code/game/machinery/suit_storage/suit_cycler.dm b/code/game/machinery/suit_storage/suit_cycler.dm new file mode 100644 index 0000000000..56a081737f --- /dev/null +++ b/code/game/machinery/suit_storage/suit_cycler.dm @@ -0,0 +1,547 @@ +GLOBAL_LIST_EMPTY(suit_cycler_typecache) + +/obj/machinery/suit_cycler + name = "suit cycler" + desc = "An industrial machine for painting and refitting voidsuits." + anchored = TRUE + density = TRUE + + icon = 'icons/obj/suit_cycler.dmi' + icon_state = "suit_cycler" + + 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 phoron. + 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. + var/can_repair // If set, the cycler can repair voidsuits. + var/electrified = 0 + + /// Departments that the cycler can paint suits to look like. Null assumes all except specially excluded ones. + /// No idea why these particular suits are the default cycler's options. + var/list/limit_departments = list( + /datum/suit_cycler_choice/department/eng/standard, + /datum/suit_cycler_choice/department/crg/mining, + /datum/suit_cycler_choice/department/med/standard, + /datum/suit_cycler_choice/department/sec/standard, + /datum/suit_cycler_choice/department/eng/atmospherics, + /datum/suit_cycler_choice/department/eng/hazmat, + /datum/suit_cycler_choice/department/eng/construction, + /datum/suit_cycler_choice/department/med/biohazard, + /datum/suit_cycler_choice/department/med/emt, + /datum/suit_cycler_choice/department/sec/riot, + /datum/suit_cycler_choice/department/sec/eva + ) + + /// Species that the cycler can refit suits for. Null assumes all except specially excluded ones. + var/list/limit_species + + var/list/departments + var/list/species + var/list/emagged_departments + + var/datum/suit_cycler_choice/department/target_department + var/datum/suit_cycler_choice/species/target_species + + var/mob/living/carbon/human/occupant = null + var/obj/item/clothing/suit/space/void/suit = null + var/obj/item/clothing/head/helmet/space/helmet = null + + var/datum/wires/suit_storage_unit/wires = null + +/obj/machinery/suit_cycler/Initialize() + . = ..() + + departments = load_departments() + species = load_species() + emagged_departments = load_emagged() + limit_departments = null // just for mem + + target_department = departments["No Change"] + target_species = species["No Change"] + + if(!target_department || !target_species) + stat |= BROKEN + + wires = new(src) + +/obj/machinery/suit_cycler/Destroy() + qdel(wires) + wires = null + return ..() + +/obj/machinery/suit_cycler/proc/load_departments() + var/list/typecache = GLOB.suit_cycler_typecache[type] + // First of our type + if(!typecache) + typecache = list() + GLOB.suit_cycler_typecache[type] = typecache + var/list/loaded = typecache["departments"] + // No departments loaded + if(!loaded) + loaded = list() + typecache["departments"] = loaded + for(var/datum/suit_cycler_choice/department/thing as anything in GLOB.suit_cycler_departments) + if(istype(thing, /datum/suit_cycler_choice/department/noop)) + loaded[thing.name] = thing + continue + if(limit_departments && !is_type_in_list(thing, limit_departments)) + continue + loaded[thing.name] = thing + + return loaded + +/obj/machinery/suit_cycler/proc/load_species() + var/list/typecache = GLOB.suit_cycler_typecache[type] + // First of our type + if(!typecache) + typecache = list() + GLOB.suit_cycler_typecache[type] = typecache + var/list/loaded = typecache["species"] + // No species loaded + if(!loaded) + loaded = list() + typecache["species"] = loaded + for(var/datum/suit_cycler_choice/species/thing as anything in GLOB.suit_cycler_species) + if(istype(thing, /datum/suit_cycler_choice/species/noop)) + loaded[thing.name] = thing + continue + if(limit_species && !is_type_in_list(thing, limit_species)) + continue + loaded[thing.name] = thing + + return loaded + +/obj/machinery/suit_cycler/proc/load_emagged() + var/list/typecache = GLOB.suit_cycler_typecache[type] + // First of our type + if(!typecache) + typecache = list() + GLOB.suit_cycler_typecache[type] = typecache + var/list/loaded = typecache["emagged"] + // No emagged loaded + if(!loaded) + loaded = list() + typecache["emagged"] = loaded + for(var/datum/suit_cycler_choice/department/thing as anything in GLOB.suit_cycler_emagged) + loaded[thing.name] = thing + + return loaded + +/obj/machinery/suit_cycler/attack_ai(mob/user as mob) + return attack_hand(user) + +/obj/machinery/suit_cycler/attackby(obj/item/I as obj, mob/user as mob) + + if(electrified != 0) + if(shock(user, 100)) + return + + //Hacking init. + if(istype(I, /obj/item/device/multitool) || I.is_wirecutter()) + if(panel_open) + attack_hand(user) + return + //Other interface stuff. + if(istype(I, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = I + + if(!(ismob(G.affecting))) + return + + if(locked) + to_chat(user, "The suit cycler is locked.") + return + + if(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.", 3) + + if(do_after(user, 20)) + if(!G || !G.affecting) return + var/mob/M = G.affecting + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + M.loc = src + occupant = M + + add_fingerprint(user) + qdel(G) + + updateUsrDialog() + + return + else if(I.is_screwdriver()) + + panel_open = !panel_open + playsound(src, I.usesound, 50, 1) + to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.") + updateUsrDialog() + return + + else if(istype(I,/obj/item/clothing/head/helmet/space/void) && !istype(I, /obj/item/clothing/head/helmet/space/rig)) + var/obj/item/clothing/head/helmet/space/void/IH = I + + if(locked) + to_chat(user, "The suit cycler is locked.") + return + + if(helmet) + to_chat(user, "The cycler already contains a helmet.") + return + + if(IH.no_cycle) + to_chat(user, "That item is not compatible with the cycler's protocols.") + return + + if(I.icon_override == CUSTOM_ITEM_MOB) + to_chat(user, "You cannot refit a customised voidsuit.") + return + + //VOREStation Edit BEGINS + //Make it so autolok suits can't be refitted in a cycler + if(istype(I,/obj/item/clothing/head/helmet/space/void/autolok)) + to_chat(user, "You cannot refit an autolok helmet. In fact you shouldn't even be able to remove it in the first place. Inform an admin!") + return + + //Ditto the Mk7 + if(istype(I,/obj/item/clothing/head/helmet/space/void/responseteam)) + to_chat(user, "The cycler indicates that the Mark VII Emergency Response Helmet is not compatible with the refitting system. How did you manage to detach it anyway? Inform an admin!") + return + //VOREStation Edit ENDS + + to_chat(user, "You fit \the [I] into the suit cycler.") + user.drop_item() + I.loc = src + helmet = I + + update_icon() + updateUsrDialog() + return + + else if(istype(I,/obj/item/clothing/suit/space/void)) + var/obj/item/clothing/suit/space/void/IS = I + + if(locked) + to_chat(user, "The suit cycler is locked.") + return + + if(suit) + to_chat(user, "The cycler already contains a voidsuit.") + return + + if(IS.no_cycle) + to_chat(user, "That item is not compatible with the cycler's protocols.") + return + + if(I.icon_override == CUSTOM_ITEM_MOB) + to_chat(user, "You cannot refit a customised voidsuit.") + return + + //VOREStation Edit BEGINS + //Make it so autolok suits can't be refitted in a cycler + if(istype(I,/obj/item/clothing/suit/space/void/autolok)) + to_chat(user, "You cannot refit an autolok suit.") + return + + //Ditto the Mk7 + if(istype(I,/obj/item/clothing/suit/space/void/responseteam)) + to_chat(user, "The cycler indicates that the Mark VII Emergency Response Suit is not compatible with the refitting system.") + return + //VOREStation Edit ENDS + + to_chat(user, "You fit \the [I] into the suit cycler.") + user.drop_item() + I.loc = src + suit = I + + update_icon() + updateUsrDialog() + return + + ..() + +/obj/machinery/suit_cycler/emag_act(var/remaining_charges, var/mob/user) + 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.") + + emagged = 1 + safeties = 0 + req_access = list() + updateUsrDialog() + return 1 + +/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(shock(user, 100)) + return + + tgui_interact(user) + +/obj/machinery/suit_cycler/tgui_state(mob/user) + return GLOB.tgui_notcontained_state + +/obj/machinery/suit_cycler/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "SuitCycler", name) + ui.open() + +/obj/machinery/suit_cycler/tgui_data(mob/user) + var/list/data = list() + + data["model_text"] = model_text + data["can_repair"] = can_repair + data["userHasAccess"] = allowed(user) + + data["locked"] = locked + data["active"] = active + data["safeties"] = safeties + data["uv_active"] = (active && irradiating > 0) + data["uv_level"] = radiation_level + data["max_uv_level"] = emagged ? 5 : 3 + if(helmet) + data["helmet"] = helmet.name + else + data["helmet"] = null + if(suit) + data["suit"] = suit.name + if(istype(suit) && can_repair) + data["damage"] = suit.damage + else + data["suit"] = null + data["damage"] = null + if(occupant) + data["occupied"] = TRUE + else + data["occupied"] = FALSE + + return data + +/obj/machinery/suit_cycler/tgui_static_data(mob/user) + var/list/data = list() + + // tgui gets angy if you pass values too + var/list/department_keys = list() + for(var/key in departments) + department_keys += key + + // emagged at the bottom + if(emagged) + for(var/key in emagged_departments) + department_keys += key + + var/list/species_keys = list() + for(var/key in species) + species_keys += key + + data["departments"] = department_keys + data["species"] = species_keys + + return data + +/obj/machinery/suit_cycler/tgui_act(action, params) + if(..()) + return TRUE + + switch(action) + if("dispense") + switch(params["item"]) + if("helmet") + helmet.forceMove(get_turf(src)) + helmet = null + if("suit") + suit.forceMove(get_turf(src)) + suit = null + . = TRUE + + if("department") + var/choice = params["department"] + if(choice in departments) + target_department = departments[choice] + else if(emagged && (choice in emagged_departments)) + target_department = emagged_departments[choice] + . = TRUE + + if("species") + var/choice = params["species"] + if(choice in species) + target_species = species[choice] + . = TRUE + + if("radlevel") + radiation_level = clamp(params["radlevel"], 1, emagged ? 5 : 3) + . = TRUE + + if("repair_suit") + if(!suit || !can_repair) + return + active = 1 + spawn(100) + repair_suit() + finished_job() + . = TRUE + + if("apply_paintjob") + if(!suit && !helmet) + return + active = 1 + spawn(100) + apply_paintjob() + finished_job() + . = TRUE + + if("lock") + if(allowed(usr)) + locked = !locked + to_chat(usr, "You [locked ? "" : "un"]lock \the [src].") + else + to_chat(usr, "Access denied.") + . = TRUE + + if("eject_guy") + eject_occupant(usr) + . = TRUE + + if("uv") + 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 + + sleep(10) + + if(helmet) + if(radiation_level > 2) + helmet.decontaminate() + if(radiation_level > 1) + helmet.clean_blood() + + if(suit) + if(radiation_level > 2) + suit.decontaminate() + if(radiation_level > 1) + suit.clean_blood() + + . = TRUE + +/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) + add_overlay("decon") + finished_job() + irradiating = 0 + cut_overlays() + 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("\icon[src][bicon(src)]The [src] beeps several times.") + icon_state = initial(icon_state) + active = 0 + playsound(src, 'sound/machines/boobeebeep.ogg', 50) + 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 + + if(occupant.client) + occupant.client.eye = occupant.client.mob + occupant.client.perspective = MOB_PERSPECTIVE + + occupant.loc = get_turf(occupant) + occupant = null + + add_fingerprint(user) + updateUsrDialog() + update_icon() + + return + +// "Streamlined" before? Ok. -Aro +/obj/machinery/suit_cycler/proc/apply_paintjob() + if(!target_species || !target_department) + return + + // Helmet to new paint + if(target_department.can_refit_helmet(helmet)) + target_department.do_refit_helmet(helmet) + // Suit to new paint + if(target_department.can_refit_suit(suit)) + target_department.do_refit_suit(suit) + // Attached voidsuit helmet to new paint + if(target_department.can_refit_helmet(suit?.helmet)) + target_department.do_refit_helmet(suit.helmet) + + // Species fitting for all 3 potential changes + if(target_species.can_refit_to(helmet, suit, suit?.helmet)) + target_species.do_refit_to(helmet, suit, suit?.helmet) + else + visible_message("\icon[src][bicon(src)]Unable to apply specified cosmetics with specified species. Please try again with a different species or cosmetic option selected.") + return diff --git a/code/game/machinery/suit_cycler_datums.dm b/code/game/machinery/suit_storage/suit_cycler_datums.dm similarity index 100% rename from code/game/machinery/suit_cycler_datums.dm rename to code/game/machinery/suit_storage/suit_cycler_datums.dm diff --git a/code/game/machinery/suit_storage/suit_cycler_units.dm b/code/game/machinery/suit_storage/suit_cycler_units.dm new file mode 100644 index 0000000000..82134bc94b --- /dev/null +++ b/code/game/machinery/suit_storage/suit_cycler_units.dm @@ -0,0 +1,112 @@ +/obj/machinery/suit_cycler/refit_only + name = "Suit cycler" + desc = "A dedicated industrial machine that can refit voidsuits for \ + different species, but not change the suit's overall appearance or \ + departmental scheme." + model_text = "General Access" + req_access = null + limit_departments = list() + +/obj/machinery/suit_cycler/engineering + name = "Engineering suit cycler" + model_text = "Engineering" + icon_state = "engi_cycler" + req_access = list(access_construction) + limit_departments = list( + /datum/suit_cycler_choice/department/eng + ) + +/obj/machinery/suit_cycler/mining + name = "Mining suit cycler" + model_text = "Mining" + icon_state = "industrial_cycler" + req_access = list(access_mining) + limit_departments = list( + /datum/suit_cycler_choice/department/crg + ) + +/obj/machinery/suit_cycler/security + name = "Security suit cycler" + model_text = "Security" + icon_state = "sec_cycler" + req_access = list(access_security) + limit_departments = list( + /datum/suit_cycler_choice/department/sec + ) + +/obj/machinery/suit_cycler/medical + name = "Medical suit cycler" + model_text = "Medical" + icon_state = "med_cycler" + req_access = list(access_medical) + limit_departments = list( + /datum/suit_cycler_choice/department/med + ) + +/obj/machinery/suit_cycler/syndicate + name = "Nonstandard suit cycler" + model_text = "Nonstandard" + icon_state = "red_cycler" + req_access = list(access_syndicate) + limit_departments = list( + /datum/suit_cycler_choice/department/emag + ) + can_repair = 1 + +/obj/machinery/suit_cycler/exploration + name = "Explorer suit cycler" + model_text = "Exploration" + icon_state = "explo_cycler" + limit_departments = list( + /datum/suit_cycler_choice/department/exp + ) + +/obj/machinery/suit_cycler/pilot + name = "Pilot suit cycler" + model_text = "Pilot" + icon_state = "pilot_cycler" + limit_departments = list( + /datum/suit_cycler_choice/department/pil + ) + +/obj/machinery/suit_cycler/vintage + name = "Vintage Crew suit cycler" + model_text = "Vintage" + icon_state = "industrial_cycler" + limit_departments = list( + /datum/suit_cycler_choice/department/vintage/crew + ) + req_access = null + +/obj/machinery/suit_cycler/vintage/pilot + name = "Vintage Pilot suit cycler" + model_text = "Vintage Pilot" + limit_departments = list( + /datum/suit_cycler_choice/department/vintage/pilot + ) + +/obj/machinery/suit_cycler/vintage/medsci + name = "Vintage MedSci suit cycler" + model_text = "Vintage MedSci" + limit_departments = list( + /datum/suit_cycler_choice/department/vintage/research, + /datum/suit_cycler_choice/department/vintage/med + ) + +/obj/machinery/suit_cycler/vintage/rugged + name = "Vintage Ruggedized suit cycler" + model_text = "Vintage Ruggedized" + + limit_departments = list( + /datum/suit_cycler_choice/department/vintage/eng, + /datum/suit_cycler_choice/department/vintage/marine, + /datum/suit_cycler_choice/department/vintage/officer, + /datum/suit_cycler_choice/department/vintage/merc + ) + +/obj/machinery/suit_cycler/vintage/omni + name = "Vintage Master suit cycler" + model_text = "Vintage Master" + limit_departments = list( + /datum/suit_cycler_choice/department/vintage + ) \ No newline at end of file diff --git a/code/game/machinery/suit_storage_unit_vr.dm b/code/game/machinery/suit_storage/suit_cycler_units_vr.dm similarity index 89% rename from code/game/machinery/suit_storage_unit_vr.dm rename to code/game/machinery/suit_storage/suit_cycler_units_vr.dm index 5dda239b93..604d6320bd 100644 --- a/code/game/machinery/suit_storage_unit_vr.dm +++ b/code/game/machinery/suit_storage/suit_cycler_units_vr.dm @@ -9,53 +9,62 @@ /obj/machinery/suit_cycler/captain name = "Manager suit cycler" model_text = "Manager" + icon_state = "cap_cycler" req_access = list(access_captain) departments = list(/datum/suit_cycler_choice/department/captain) /obj/machinery/suit_cycler/prototype name = "Prototype suit cycler" model_text = "Prototype" + icon_state = "industrial_cycler" req_access = list(access_hos) departments = list(/datum/suit_cycler_choice/department/prototype) /obj/machinery/suit_cycler/vintage/tcrew name = "Talon crew suit cycler" model_text = "Talon crew" + icon_state = "dark_cycler" req_access = list(access_talon) departments = list(/datum/suit_cycler_choice/department/talon/crew) /obj/machinery/suit_cycler/vintage/tpilot name = "Talon pilot suit cycler" model_text = "Talon pilot" + icon_state = "dark_cycler" req_access = list(access_talon) departments = list(/datum/suit_cycler_choice/department/talon/pilot) /obj/machinery/suit_cycler/vintage/tengi name = "Talon engineer suit cycler" model_text = "Talon engineer" + icon_state = "dark_cycler" req_access = list(access_talon) departments = list(/datum/suit_cycler_choice/department/talon/eng) /obj/machinery/suit_cycler/vintage/tguard name = "Talon guard suit cycler" model_text = "Talon guard" + icon_state = "dark_cycler" req_access = list(access_talon) departments = list(/datum/suit_cycler_choice/department/talon/marine) /obj/machinery/suit_cycler/vintage/tmedic name = "Talon doctor suit cycler" model_text = "Talon doctor" + icon_state = "dark_cycler" req_access = list(access_talon) departments = list(/datum/suit_cycler_choice/department/talon/med) /obj/machinery/suit_cycler/vintage/tcaptain name = "Talon captain suit cycler" model_text = "Talon captain" + icon_state = "dark_cycler" req_access = list(access_talon) departments = list(/datum/suit_cycler_choice/department/talon/officer) /obj/machinery/suit_cycler/vintage/tminer name = "Talon miner suit cycler" model_text = "Talon miner" + icon_state = "dark_cycler" req_access = list(access_talon) departments = list(/datum/suit_cycler_choice/department/talon/miner) diff --git a/code/game/machinery/suit_storage/suit_storage.dm b/code/game/machinery/suit_storage/suit_storage.dm new file mode 100644 index 0000000000..334f5227d8 --- /dev/null +++ b/code/game/machinery/suit_storage/suit_storage.dm @@ -0,0 +1,476 @@ +////////////////////////////////////// +// SUIT STORAGE UNIT ///////////////// +////////////////////////////////////// + +/obj/machinery/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/suit_storage.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 = TRUE + density = TRUE + 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 + +/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) + update_icon() + +/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, isopen, islocked, isUV, ispowered, isbroken, issuperUV) + +/obj/machinery/suit_storage_unit/power_change() + ..() + if(!(stat & NOPOWER)) + ispowered = 1 + update_icon() + else + spawn(rand(0, 15)) + ispowered = 0 + islocked = 0 + isopen = 1 + dump_everything() + update_icon() + +/obj/machinery/suit_storage_unit/ex_act(severity) + switch(severity) + if(1.0) + if(prob(50)) + dump_everything() //So suits dont survive all the time + qdel(src) + if(2.0) + if(prob(50)) + dump_everything() + qdel(src) + +/obj/machinery/suit_storage_unit/attack_hand(mob/user) + if(..()) + return + if(stat & NOPOWER) + return + if(!user.IsAdvancedToolUser()) + return 0 + tgui_interact(user) + +/obj/machinery/suit_storage_unit/tgui_state(mob/user) + return GLOB.tgui_notcontained_state + +/obj/machinery/suit_storage_unit/tgui_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/tgui_data() + var/list/data = list() + + data["broken"] = isbroken + data["panelopen"] = panelopen + + data["locked"] = islocked + data["open"] = isopen + data["safeties"] = safetieson + data["uv_active"] = isUV + data["uv_super"] = issuperUV + 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 + data["storage"] = null + if(OCCUPANT) + data["occupied"] = TRUE + else + data["occupied"] = FALSE + return data + +/obj/machinery/suit_storage_unit/tgui_act(action, params) //I fucking HATE this proc + if(..() || isUV || isbroken) + return TRUE + + switch(action) + if("door") + toggle_open(usr) + . = TRUE + if("dispense") + switch(params["item"]) + if("helmet") + dispense_helmet(usr) + if("mask") + dispense_mask(usr) + if("suit") + dispense_suit(usr) + . = TRUE + if("uv") + start_UV(usr) + . = TRUE + if("lock") + toggle_lock(usr) + . = TRUE + if("eject_guy") + eject_occupant(usr) + . = TRUE + + // Panel Open stuff + if(!. && panelopen) + switch(action) + if("toggleUV") + toggleUV(usr) + . = TRUE + if("togglesafeties") + togglesafeties(usr) + . = TRUE + + update_icon() + add_fingerprint(usr) + + +/obj/machinery/suit_storage_unit/proc/toggleUV(mob/user as mob) + if(!panelopen) + return + + else //welp, the guy is protected, we can continue + if(issuperUV) + to_chat(user, "You slide the dial back towards \"185nm\".") + issuperUV = 0 + else + to_chat(user, "You crank the dial all the way up to \"15nm\".") + issuperUV = 1 + return + + +/obj/machinery/suit_storage_unit/proc/togglesafeties(mob/user as mob) + if(!panelopen) //Needed check due to bugs + return + + else + to_chat(user, "You push the button. The coloured LED next to it changes.") + safetieson = !safetieson + + +/obj/machinery/suit_storage_unit/proc/dispense_helmet(mob/user as mob) + if(!HELMET) + return //Do I even need this sanity check? Nyoro~n + else + HELMET.loc = src.loc + HELMET = null + return + + +/obj/machinery/suit_storage_unit/proc/dispense_suit(mob/user as mob) + if(!SUIT) + return + else + SUIT.loc = src.loc + SUIT = null + return + + +/obj/machinery/suit_storage_unit/proc/dispense_mask(mob/user as mob) + if(!MASK) + return + else + MASK.loc = src.loc + MASK = null + return + + +/obj/machinery/suit_storage_unit/proc/dump_everything() + islocked = 0 //locks go free + if(SUIT) + SUIT.loc = src.loc + SUIT = null + if(HELMET) + HELMET.loc = src.loc + HELMET = null + if(MASK) + MASK.loc = src.loc + MASK = null + if(OCCUPANT) + eject_occupant(OCCUPANT) + return + + +/obj/machinery/suit_storage_unit/proc/toggle_open(mob/user as mob) + if(islocked || isUV) + to_chat(user, "Unable to open unit.") + return + if(OCCUPANT) + eject_occupant(user) + return // eject_occupant opens the door, so we need to return + isopen = !isopen + return + + +/obj/machinery/suit_storage_unit/proc/toggle_lock(mob/user as mob) + if(OCCUPANT && safetieson) + to_chat(user, "The Unit's safety protocols disallow locking when a biological form is detected inside its compartments.") + return + if(isopen) + return + islocked = !islocked + return + + +/obj/machinery/suit_storage_unit/proc/start_UV(mob/user as mob) + if(isUV || isopen) //I'm bored of all these sanity checks + return + if(OCCUPANT && safetieson) + to_chat(user, "WARNING: Biological entity detected in the confines of the Unit's storage. Cannot initiate cycle.") + return + if(!HELMET && !MASK && !SUIT && !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.") + cycletime_left = 20 + isUV = 1 + if(OCCUPANT && !islocked) + islocked = 1 //Let's lock it for good measure + update_icon() + updateUsrDialog() + + var/i //our counter + for(i=0,i<4,i++) + sleep(50) + if(OCCUPANT) + OCCUPANT.apply_effect(50, IRRADIATE) + var/obj/item/organ/internal/diona/nutrients/rad_organ = locate() in OCCUPANT.internal_organs + if(!rad_organ) + if(OCCUPANT.can_feel_pain()) + OCCUPANT.emote("scream") + if(issuperUV) + var/burndamage = rand(28,35) + OCCUPANT.take_organ_damage(0,burndamage) + else + var/burndamage = rand(6,10) + OCCUPANT.take_organ_damage(0,burndamage) + if(i==3) //End of the cycle + if(!issuperUV) + if(HELMET) + HELMET.clean_blood() + if(SUIT) + SUIT.clean_blood() + if(MASK) + MASK.clean_blood() + else //It was supercycling, destroy everything + if(HELMET) + HELMET = null + if(SUIT) + SUIT = null + if(MASK) + 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.", 3) + isbroken = 1 + isopen = 1 + islocked = 0 + eject_occupant(OCCUPANT) //Mixing up these two lines causes bug. DO NOT DO IT. + isUV = 0 //Cycle ends + update_icon() + updateUsrDialog() + return + +/obj/machinery/suit_storage_unit/proc/cycletimeleft() + if(cycletime_left >= 1) + cycletime_left-- + return cycletime_left + + +/obj/machinery/suit_storage_unit/proc/eject_occupant(mob/user as mob) + if(islocked) + return + + if(!OCCUPANT) + return + + if(OCCUPANT.client) + if(user != OCCUPANT) + to_chat(OCCUPANT, "The machine kicks you out!") + if(user.loc != src.loc) + to_chat(OCCUPANT, "You leave the not-so-cozy confines of the SSU.") + + OCCUPANT.client.eye = OCCUPANT.client.mob + OCCUPANT.client.perspective = MOB_PERSPECTIVE + OCCUPANT.loc = src.loc + OCCUPANT = null + if(!isopen) + isopen = 1 + update_icon() + return + + +/obj/machinery/suit_storage_unit/verb/get_out() + set name = "Eject Suit Storage Unit" + set category = "Object" + set src in oview(1) + + if(usr.stat != 0) + return + eject_occupant(usr) + add_fingerprint(usr) + updateUsrDialog() + update_icon() + return + + +/obj/machinery/suit_storage_unit/verb/move_inside() + set name = "Hide in Suit Storage Unit" + set category = "Object" + set src in oview(1) + + if(usr.stat != 0) + return + if(!isopen) + to_chat(usr, "The unit's doors are shut.") + return + if(!ispowered || isbroken) + to_chat(usr, "The unit is not operational.") + return + if((OCCUPANT) || (HELMET) || (SUIT)) + to_chat(usr, "It's too cluttered inside for you to fit in!") + return + visible_message("[usr] starts squeezing into the suit storage unit!", 3) + if(do_after(usr, 10)) + usr.stop_pulling() + usr.client.perspective = EYE_PERSPECTIVE + usr.client.eye = src + usr.loc = src + OCCUPANT = usr + isopen = 0 //Close the thing after the guy gets inside + update_icon() + + add_fingerprint(usr) + updateUsrDialog() + return + else + 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) + if(!ispowered) + return + if(I.is_screwdriver()) + panelopen = !panelopen + playsound(src, I.usesound, 100, 1) + to_chat(user, "You [panelopen ? "open up" : "close"] the unit's maintenance panel.") + updateUsrDialog() + return + if(istype(I, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = I + if(!(ismob(G.affecting))) + return + if(!isopen) + to_chat(user, "The unit's doors are shut.") + return + if(!ispowered || isbroken) + to_chat(user, "The unit is not operational.") + return + if((OCCUPANT) || (HELMET) || (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.", 3) + if(do_after(user, 20)) + if(!G || !G.affecting) return //derpcheck + var/mob/M = G.affecting + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + M.loc = src + OCCUPANT = M + isopen = 0 //close ittt + + add_fingerprint(user) + qdel(G) + updateUsrDialog() + update_icon() + return + return + if(istype(I,/obj/item/clothing/suit/space)) + if(!isopen) + return + var/obj/item/clothing/suit/space/S = I + if(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 + SUIT = S + update_icon() + updateUsrDialog() + return + if(istype(I,/obj/item/clothing/head/helmet)) + if(!isopen) + return + var/obj/item/clothing/head/helmet/H = I + if(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 + HELMET = H + update_icon() + updateUsrDialog() + return + if(istype(I,/obj/item/clothing/mask)) + if(!isopen) + return + var/obj/item/clothing/mask/M = I + if(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 + MASK = M + update_icon() + updateUsrDialog() + return + update_icon() + updateUsrDialog() + return + + +/obj/machinery/suit_storage_unit/attack_ai(mob/user as mob) + return attack_hand(user) + +//////////////////////////////REMINDER: Make it lock once you place some fucker inside. + +//God this entire file is fucking awful //Yes \ No newline at end of file diff --git a/code/game/machinery/suit_storage/suit_storage_units.dm b/code/game/machinery/suit_storage/suit_storage_units.dm new file mode 100644 index 0000000000..740d067776 --- /dev/null +++ b/code/game/machinery/suit_storage/suit_storage_units.dm @@ -0,0 +1,54 @@ +//Standard +/obj/machinery/suit_storage_unit/empty + suit_type = null + helmet_type = null + mask_type = null + +/obj/machinery/suit_storage_unit/standard_unit + suit_type = /obj/item/clothing/suit/space + helmet_type = /obj/item/clothing/head/helmet/space + mask_type = /obj/item/clothing/mask/breath + +//Engineering +/obj/machinery/suit_storage_unit/engineering + suit_type = /obj/item/clothing/head/helmet/space/void/engineering + helmet_type = /obj/item/clothing/suit/space/void/engineering + mask_type = /obj/item/clothing/mask/breath + +/obj/machinery/suit_storage_unit/hazmat + suit_type = /obj/item/clothing/head/helmet/space/void/engineering/hazmat + helmet_type = /obj/item/clothing/suit/space/void/engineering/hazmat + mask_type = /obj/item/clothing/mask/breath + +//Mining +/obj/machinery/suit_storage_unit/mining + suit_type = /obj/item/clothing/head/helmet/space/void/mining + helmet_type = /obj/item/clothing/suit/space/void/mining + mask_type = /obj/item/clothing/mask/breath + +/obj/machinery/suit_storage_unit/mining_alt + suit_type = /obj/item/clothing/head/helmet/space/void/mining/alt + helmet_type = /obj/item/clothing/suit/space/void/mining/alt + mask_type = /obj/item/clothing/mask/breath + +//Medical +/obj/machinery/suit_storage_unit/medical + suit_type = /obj/item/clothing/head/helmet/space/void/medical + helmet_type = /obj/item/clothing/suit/space/void/medical + mask_type = /obj/item/clothing/mask/breath + +/obj/machinery/suit_storage_unit/emt + suit_type = /obj/item/clothing/head/helmet/space/void/medical/emt + helmet_type = /obj/item/clothing/suit/space/void/medical/emt + mask_type = /obj/item/clothing/mask/breath + +//Security +/obj/machinery/suit_storage_unit/security + suit_type = /obj/item/clothing/head/helmet/space/void/security + helmet_type = /obj/item/clothing/suit/space/void/security + mask_type = /obj/item/clothing/mask/breath + +/obj/machinery/suit_storage_unit/riot + suit_type = /obj/item/clothing/head/helmet/space/void/security/riot + helmet_type = /obj/item/clothing/suit/space/void/security/riot + mask_type = /obj/item/clothing/mask/breath \ No newline at end of file diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm deleted file mode 100644 index c8a980c2ce..0000000000 --- a/code/game/machinery/suit_storage_unit.dm +++ /dev/null @@ -1,1131 +0,0 @@ -////////////////////////////////////// -// SUIT STORAGE UNIT ///////////////// -////////////////////////////////////// - -/obj/machinery/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 = TRUE - density = TRUE - 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 - -//The units themselves///////////////// - -/obj/machinery/suit_storage_unit/standard_unit - suit_type = /obj/item/clothing/suit/space - helmet_type = /obj/item/clothing/head/helmet/space - mask_type = /obj/item/clothing/mask/breath - -/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) - update_icon() - -/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, isopen, islocked, isUV, ispowered, isbroken, issuperUV) - -/obj/machinery/suit_storage_unit/power_change() - ..() - if(!(stat & NOPOWER)) - ispowered = 1 - update_icon() - else - spawn(rand(0, 15)) - ispowered = 0 - islocked = 0 - isopen = 1 - dump_everything() - update_icon() - -/obj/machinery/suit_storage_unit/ex_act(severity) - switch(severity) - if(1.0) - if(prob(50)) - dump_everything() //So suits dont survive all the time - qdel(src) - if(2.0) - if(prob(50)) - dump_everything() - qdel(src) - -/obj/machinery/suit_storage_unit/attack_hand(mob/user) - if(..()) - return - if(stat & NOPOWER) - return - if(!user.IsAdvancedToolUser()) - return 0 - tgui_interact(user) - -/obj/machinery/suit_storage_unit/tgui_state(mob/user) - return GLOB.tgui_notcontained_state - -/obj/machinery/suit_storage_unit/tgui_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/tgui_data() - var/list/data = list() - - data["broken"] = isbroken - data["panelopen"] = panelopen - - data["locked"] = islocked - data["open"] = isopen - data["safeties"] = safetieson - data["uv_active"] = isUV - data["uv_super"] = issuperUV - 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 - data["storage"] = null - if(OCCUPANT) - data["occupied"] = TRUE - else - data["occupied"] = FALSE - return data - -/obj/machinery/suit_storage_unit/tgui_act(action, params) //I fucking HATE this proc - if(..() || isUV || isbroken) - return TRUE - - switch(action) - if("door") - toggle_open(usr) - . = TRUE - if("dispense") - switch(params["item"]) - if("helmet") - dispense_helmet(usr) - if("mask") - dispense_mask(usr) - if("suit") - dispense_suit(usr) - . = TRUE - if("uv") - start_UV(usr) - . = TRUE - if("lock") - toggle_lock(usr) - . = TRUE - if("eject_guy") - eject_occupant(usr) - . = TRUE - - // Panel Open stuff - if(!. && panelopen) - switch(action) - if("toggleUV") - toggleUV(usr) - . = TRUE - if("togglesafeties") - togglesafeties(usr) - . = TRUE - - update_icon() - add_fingerprint(usr) - - -/obj/machinery/suit_storage_unit/proc/toggleUV(mob/user as mob) - if(!panelopen) - return - - else //welp, the guy is protected, we can continue - if(issuperUV) - to_chat(user, "You slide the dial back towards \"185nm\".") - issuperUV = 0 - else - to_chat(user, "You crank the dial all the way up to \"15nm\".") - issuperUV = 1 - return - - -/obj/machinery/suit_storage_unit/proc/togglesafeties(mob/user as mob) - if(!panelopen) //Needed check due to bugs - return - - else - to_chat(user, "You push the button. The coloured LED next to it changes.") - safetieson = !safetieson - - -/obj/machinery/suit_storage_unit/proc/dispense_helmet(mob/user as mob) - if(!HELMET) - return //Do I even need this sanity check? Nyoro~n - else - HELMET.loc = src.loc - HELMET = null - return - - -/obj/machinery/suit_storage_unit/proc/dispense_suit(mob/user as mob) - if(!SUIT) - return - else - SUIT.loc = src.loc - SUIT = null - return - - -/obj/machinery/suit_storage_unit/proc/dispense_mask(mob/user as mob) - if(!MASK) - return - else - MASK.loc = src.loc - MASK = null - return - - -/obj/machinery/suit_storage_unit/proc/dump_everything() - islocked = 0 //locks go free - if(SUIT) - SUIT.loc = src.loc - SUIT = null - if(HELMET) - HELMET.loc = src.loc - HELMET = null - if(MASK) - MASK.loc = src.loc - MASK = null - if(OCCUPANT) - eject_occupant(OCCUPANT) - return - - -/obj/machinery/suit_storage_unit/proc/toggle_open(mob/user as mob) - if(islocked || isUV) - to_chat(user, "Unable to open unit.") - return - if(OCCUPANT) - eject_occupant(user) - return // eject_occupant opens the door, so we need to return - isopen = !isopen - return - - -/obj/machinery/suit_storage_unit/proc/toggle_lock(mob/user as mob) - if(OCCUPANT && safetieson) - to_chat(user, "The Unit's safety protocols disallow locking when a biological form is detected inside its compartments.") - return - if(isopen) - return - islocked = !islocked - return - - -/obj/machinery/suit_storage_unit/proc/start_UV(mob/user as mob) - if(isUV || isopen) //I'm bored of all these sanity checks - return - if(OCCUPANT && safetieson) - to_chat(user, "WARNING: Biological entity detected in the confines of the Unit's storage. Cannot initiate cycle.") - return - if(!HELMET && !MASK && !SUIT && !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.") - cycletime_left = 20 - isUV = 1 - if(OCCUPANT && !islocked) - islocked = 1 //Let's lock it for good measure - update_icon() - updateUsrDialog() - - var/i //our counter - for(i=0,i<4,i++) - sleep(50) - if(OCCUPANT) - OCCUPANT.apply_effect(50, IRRADIATE) - var/obj/item/organ/internal/diona/nutrients/rad_organ = locate() in OCCUPANT.internal_organs - if(!rad_organ) - if(OCCUPANT.can_feel_pain()) - OCCUPANT.emote("scream") - if(issuperUV) - var/burndamage = rand(28,35) - OCCUPANT.take_organ_damage(0,burndamage) - else - var/burndamage = rand(6,10) - OCCUPANT.take_organ_damage(0,burndamage) - if(i==3) //End of the cycle - if(!issuperUV) - if(HELMET) - HELMET.clean_blood() - if(SUIT) - SUIT.clean_blood() - if(MASK) - MASK.clean_blood() - else //It was supercycling, destroy everything - if(HELMET) - HELMET = null - if(SUIT) - SUIT = null - if(MASK) - 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.", 3) - isbroken = 1 - isopen = 1 - islocked = 0 - eject_occupant(OCCUPANT) //Mixing up these two lines causes bug. DO NOT DO IT. - isUV = 0 //Cycle ends - update_icon() - updateUsrDialog() - return - -/obj/machinery/suit_storage_unit/proc/cycletimeleft() - if(cycletime_left >= 1) - cycletime_left-- - return cycletime_left - - -/obj/machinery/suit_storage_unit/proc/eject_occupant(mob/user as mob) - if(islocked) - return - - if(!OCCUPANT) - return - - if(OCCUPANT.client) - if(user != OCCUPANT) - to_chat(OCCUPANT, "The machine kicks you out!") - if(user.loc != src.loc) - to_chat(OCCUPANT, "You leave the not-so-cozy confines of the SSU.") - - OCCUPANT.client.eye = OCCUPANT.client.mob - OCCUPANT.client.perspective = MOB_PERSPECTIVE - OCCUPANT.loc = src.loc - OCCUPANT = null - if(!isopen) - isopen = 1 - update_icon() - return - - -/obj/machinery/suit_storage_unit/verb/get_out() - set name = "Eject Suit Storage Unit" - set category = "Object" - set src in oview(1) - - if(usr.stat != 0) - return - eject_occupant(usr) - add_fingerprint(usr) - updateUsrDialog() - update_icon() - return - - -/obj/machinery/suit_storage_unit/verb/move_inside() - set name = "Hide in Suit Storage Unit" - set category = "Object" - set src in oview(1) - - if(usr.stat != 0) - return - if(!isopen) - to_chat(usr, "The unit's doors are shut.") - return - if(!ispowered || isbroken) - to_chat(usr, "The unit is not operational.") - return - if((OCCUPANT) || (HELMET) || (SUIT)) - to_chat(usr, "It's too cluttered inside for you to fit in!") - return - visible_message("[usr] starts squeezing into the suit storage unit!", 3) - if(do_after(usr, 10)) - usr.stop_pulling() - usr.client.perspective = EYE_PERSPECTIVE - usr.client.eye = src - usr.loc = src - OCCUPANT = usr - isopen = 0 //Close the thing after the guy gets inside - update_icon() - - add_fingerprint(usr) - updateUsrDialog() - return - else - 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) - if(!ispowered) - return - if(I.is_screwdriver()) - panelopen = !panelopen - playsound(src, I.usesound, 100, 1) - to_chat(user, "You [panelopen ? "open up" : "close"] the unit's maintenance panel.") - updateUsrDialog() - return - if(istype(I, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = I - if(!(ismob(G.affecting))) - return - if(!isopen) - to_chat(user, "The unit's doors are shut.") - return - if(!ispowered || isbroken) - to_chat(user, "The unit is not operational.") - return - if((OCCUPANT) || (HELMET) || (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.", 3) - if(do_after(user, 20)) - if(!G || !G.affecting) return //derpcheck - var/mob/M = G.affecting - if(M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - M.loc = src - OCCUPANT = M - isopen = 0 //close ittt - - add_fingerprint(user) - qdel(G) - updateUsrDialog() - update_icon() - return - return - if(istype(I,/obj/item/clothing/suit/space)) - if(!isopen) - return - var/obj/item/clothing/suit/space/S = I - if(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 - SUIT = S - update_icon() - updateUsrDialog() - return - if(istype(I,/obj/item/clothing/head/helmet)) - if(!isopen) - return - var/obj/item/clothing/head/helmet/H = I - if(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 - HELMET = H - update_icon() - updateUsrDialog() - return - if(istype(I,/obj/item/clothing/mask)) - if(!isopen) - return - var/obj/item/clothing/mask/M = I - if(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 - MASK = M - update_icon() - updateUsrDialog() - return - update_icon() - updateUsrDialog() - return - - -/obj/machinery/suit_storage_unit/attack_ai(mob/user as mob) - return attack_hand(user) - -//////////////////////////////REMINDER: Make it lock once you place some fucker inside. - -//God this entire file is fucking awful //Yes -//Suit painter for Bay's special snowflake aliums. - -GLOBAL_LIST_EMPTY(suit_cycler_typecache) -/obj/machinery/suit_cycler - - name = "suit cycler" - desc = "An industrial machine for painting and refitting voidsuits." - anchored = TRUE - density = TRUE - - 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 phoron. - 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. - var/can_repair // If set, the cycler can repair voidsuits. - var/electrified = 0 - - /// Departments that the cycler can paint suits to look like. Null assumes all except specially excluded ones. - /// No idea why these particular suits are the default cycler's options. - var/list/limit_departments = list( - /datum/suit_cycler_choice/department/eng/standard, - /datum/suit_cycler_choice/department/crg/mining, - /datum/suit_cycler_choice/department/med/standard, - /datum/suit_cycler_choice/department/sec/standard, - /datum/suit_cycler_choice/department/eng/atmospherics, - /datum/suit_cycler_choice/department/eng/hazmat, - /datum/suit_cycler_choice/department/eng/construction, - /datum/suit_cycler_choice/department/med/biohazard, - /datum/suit_cycler_choice/department/med/emt, - /datum/suit_cycler_choice/department/sec/riot, - /datum/suit_cycler_choice/department/sec/eva - ) - - /// Species that the cycler can refit suits for. Null assumes all except specially excluded ones. - var/list/limit_species - - var/list/departments - var/list/species - var/list/emagged_departments - - var/datum/suit_cycler_choice/department/target_department - var/datum/suit_cycler_choice/species/target_species - - var/mob/living/carbon/human/occupant = null - var/obj/item/clothing/suit/space/void/suit = null - var/obj/item/clothing/head/helmet/space/helmet = null - - var/datum/wires/suit_storage_unit/wires = null - -/obj/machinery/suit_cycler/Initialize() - . = ..() - - departments = load_departments() - species = load_species() - emagged_departments = load_emagged() - limit_departments = null // just for mem - - target_department = departments["No Change"] - target_species = species["No Change"] - - if(!target_department || !target_species) - stat |= BROKEN - - wires = new(src) - -/obj/machinery/suit_cycler/Destroy() - qdel(wires) - wires = null - return ..() - -/obj/machinery/suit_cycler/proc/load_departments() - var/list/typecache = GLOB.suit_cycler_typecache[type] - // First of our type - if(!typecache) - typecache = list() - GLOB.suit_cycler_typecache[type] = typecache - var/list/loaded = typecache["departments"] - // No departments loaded - if(!loaded) - loaded = list() - typecache["departments"] = loaded - for(var/datum/suit_cycler_choice/department/thing as anything in GLOB.suit_cycler_departments) - if(istype(thing, /datum/suit_cycler_choice/department/noop)) - loaded[thing.name] = thing - continue - if(limit_departments && !is_type_in_list(thing, limit_departments)) - continue - loaded[thing.name] = thing - - return loaded - -/obj/machinery/suit_cycler/proc/load_species() - var/list/typecache = GLOB.suit_cycler_typecache[type] - // First of our type - if(!typecache) - typecache = list() - GLOB.suit_cycler_typecache[type] = typecache - var/list/loaded = typecache["species"] - // No species loaded - if(!loaded) - loaded = list() - typecache["species"] = loaded - for(var/datum/suit_cycler_choice/species/thing as anything in GLOB.suit_cycler_species) - if(istype(thing, /datum/suit_cycler_choice/species/noop)) - loaded[thing.name] = thing - continue - if(limit_species && !is_type_in_list(thing, limit_species)) - continue - loaded[thing.name] = thing - - return loaded - -/obj/machinery/suit_cycler/proc/load_emagged() - var/list/typecache = GLOB.suit_cycler_typecache[type] - // First of our type - if(!typecache) - typecache = list() - GLOB.suit_cycler_typecache[type] = typecache - var/list/loaded = typecache["emagged"] - // No emagged loaded - if(!loaded) - loaded = list() - typecache["emagged"] = loaded - for(var/datum/suit_cycler_choice/department/thing as anything in GLOB.suit_cycler_emagged) - loaded[thing.name] = thing - - return loaded - -/obj/machinery/suit_cycler/refit_only - name = "Suit cycler" - desc = "A dedicated industrial machine that can refit voidsuits for different species, but not change the suit's overall appearance or departmental scheme." - model_text = "General Access" - req_access = null - limit_departments = list() - -/obj/machinery/suit_cycler/engineering - name = "Engineering suit cycler" - model_text = "Engineering" - req_access = list(access_construction) - limit_departments = list( - /datum/suit_cycler_choice/department/eng - ) - -/obj/machinery/suit_cycler/mining - name = "Mining suit cycler" - model_text = "Mining" - req_access = list(access_mining) - limit_departments = list( - /datum/suit_cycler_choice/department/crg - ) - -/obj/machinery/suit_cycler/security - name = "Security suit cycler" - model_text = "Security" - req_access = list(access_security) - limit_departments = list( - /datum/suit_cycler_choice/department/sec - ) - -/obj/machinery/suit_cycler/medical - name = "Medical suit cycler" - model_text = "Medical" - req_access = list(access_medical) - limit_departments = list( - /datum/suit_cycler_choice/department/med - ) - -/obj/machinery/suit_cycler/syndicate - name = "Nonstandard suit cycler" - model_text = "Nonstandard" - req_access = list(access_syndicate) - limit_departments = list( - /datum/suit_cycler_choice/department/emag - ) - can_repair = 1 -/obj/machinery/suit_cycler/exploration - name = "Explorer suit cycler" - model_text = "Exploration" - limit_departments = list( - /datum/suit_cycler_choice/department/exp - ) -/obj/machinery/suit_cycler/pilot - name = "Pilot suit cycler" - model_text = "Pilot" - limit_departments = list( - /datum/suit_cycler_choice/department/pil - ) - -/obj/machinery/suit_cycler/vintage - name = "Vintage Crew suit cycler" - model_text = "Vintage" - limit_departments = list( - /datum/suit_cycler_choice/department/vintage/crew - ) - req_access = null - -/obj/machinery/suit_cycler/vintage/pilot - name = "Vintage Pilot suit cycler" - model_text = "Vintage Pilot" - limit_departments = list( - /datum/suit_cycler_choice/department/vintage/pilot - ) - -/obj/machinery/suit_cycler/vintage/medsci - name = "Vintage MedSci suit cycler" - model_text = "Vintage MedSci" - limit_departments = list( - /datum/suit_cycler_choice/department/vintage/research, - /datum/suit_cycler_choice/department/vintage/med - ) - -/obj/machinery/suit_cycler/vintage/rugged - name = "Vintage Ruggedized suit cycler" - model_text = "Vintage Ruggedized" - - limit_departments = list( - /datum/suit_cycler_choice/department/vintage/eng, - /datum/suit_cycler_choice/department/vintage/marine, - /datum/suit_cycler_choice/department/vintage/officer, - /datum/suit_cycler_choice/department/vintage/merc - ) - -/obj/machinery/suit_cycler/vintage/omni - name = "Vintage Master suit cycler" - model_text = "Vintage Master" - limit_departments = list( - /datum/suit_cycler_choice/department/vintage - ) - -/obj/machinery/suit_cycler/attack_ai(mob/user as mob) - return attack_hand(user) - -/obj/machinery/suit_cycler/attackby(obj/item/I as obj, mob/user as mob) - - if(electrified != 0) - if(shock(user, 100)) - return - - //Hacking init. - if(istype(I, /obj/item/device/multitool) || I.is_wirecutter()) - if(panel_open) - attack_hand(user) - return - //Other interface stuff. - if(istype(I, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = I - - if(!(ismob(G.affecting))) - return - - if(locked) - to_chat(user, "The suit cycler is locked.") - return - - if(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.", 3) - - if(do_after(user, 20)) - if(!G || !G.affecting) return - var/mob/M = G.affecting - if(M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - M.loc = src - occupant = M - - add_fingerprint(user) - qdel(G) - - updateUsrDialog() - - return - else if(I.is_screwdriver()) - - panel_open = !panel_open - playsound(src, I.usesound, 50, 1) - to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.") - updateUsrDialog() - return - - else if(istype(I,/obj/item/clothing/head/helmet/space/void) && !istype(I, /obj/item/clothing/head/helmet/space/rig)) - var/obj/item/clothing/head/helmet/space/void/IH = I - - if(locked) - to_chat(user, "The suit cycler is locked.") - return - - if(helmet) - to_chat(user, "The cycler already contains a helmet.") - return - - if(IH.no_cycle) - to_chat(user, "That item is not compatible with the cycler's protocols.") - return - - if(I.icon_override == CUSTOM_ITEM_MOB) - to_chat(user, "You cannot refit a customised voidsuit.") - return - - //VOREStation Edit BEGINS - //Make it so autolok suits can't be refitted in a cycler - if(istype(I,/obj/item/clothing/head/helmet/space/void/autolok)) - to_chat(user, "You cannot refit an autolok helmet. In fact you shouldn't even be able to remove it in the first place. Inform an admin!") - return - - //Ditto the Mk7 - if(istype(I,/obj/item/clothing/head/helmet/space/void/responseteam)) - to_chat(user, "The cycler indicates that the Mark VII Emergency Response Helmet is not compatible with the refitting system. How did you manage to detach it anyway? Inform an admin!") - return - //VOREStation Edit ENDS - - to_chat(user, "You fit \the [I] into the suit cycler.") - user.drop_item() - I.loc = src - helmet = I - - update_icon() - updateUsrDialog() - return - - else if(istype(I,/obj/item/clothing/suit/space/void)) - var/obj/item/clothing/suit/space/void/IS = I - - if(locked) - to_chat(user, "The suit cycler is locked.") - return - - if(suit) - to_chat(user, "The cycler already contains a voidsuit.") - return - - if(IS.no_cycle) - to_chat(user, "That item is not compatible with the cycler's protocols.") - return - - if(I.icon_override == CUSTOM_ITEM_MOB) - to_chat(user, "You cannot refit a customised voidsuit.") - return - - //VOREStation Edit BEGINS - //Make it so autolok suits can't be refitted in a cycler - if(istype(I,/obj/item/clothing/suit/space/void/autolok)) - to_chat(user, "You cannot refit an autolok suit.") - return - - //Ditto the Mk7 - if(istype(I,/obj/item/clothing/suit/space/void/responseteam)) - to_chat(user, "The cycler indicates that the Mark VII Emergency Response Suit is not compatible with the refitting system.") - return - //VOREStation Edit ENDS - - to_chat(user, "You fit \the [I] into the suit cycler.") - user.drop_item() - I.loc = src - suit = I - - update_icon() - updateUsrDialog() - return - - ..() - -/obj/machinery/suit_cycler/emag_act(var/remaining_charges, var/mob/user) - 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.") - - emagged = 1 - safeties = 0 - req_access = list() - updateUsrDialog() - return 1 - -/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(shock(user, 100)) - return - - tgui_interact(user) - -/obj/machinery/suit_cycler/tgui_state(mob/user) - return GLOB.tgui_notcontained_state - -/obj/machinery/suit_cycler/tgui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "SuitCycler", name) - ui.open() - -/obj/machinery/suit_cycler/tgui_data(mob/user) - var/list/data = list() - - data["model_text"] = model_text - data["can_repair"] = can_repair - data["userHasAccess"] = allowed(user) - - data["locked"] = locked - data["active"] = active - data["safeties"] = safeties - data["uv_active"] = (active && irradiating > 0) - data["uv_level"] = radiation_level - data["max_uv_level"] = emagged ? 5 : 3 - if(helmet) - data["helmet"] = helmet.name - else - data["helmet"] = null - if(suit) - data["suit"] = suit.name - if(istype(suit) && can_repair) - data["damage"] = suit.damage - else - data["suit"] = null - data["damage"] = null - if(occupant) - data["occupied"] = TRUE - else - data["occupied"] = FALSE - - return data - -/obj/machinery/suit_cycler/tgui_static_data(mob/user) - var/list/data = list() - - // tgui gets angy if you pass values too - var/list/department_keys = list() - for(var/key in departments) - department_keys += key - - // emagged at the bottom - if(emagged) - for(var/key in emagged_departments) - department_keys += key - - var/list/species_keys = list() - for(var/key in species) - species_keys += key - - data["departments"] = department_keys - data["species"] = species_keys - - return data - -/obj/machinery/suit_cycler/tgui_act(action, params) - if(..()) - return TRUE - - switch(action) - if("dispense") - switch(params["item"]) - if("helmet") - helmet.forceMove(get_turf(src)) - helmet = null - if("suit") - suit.forceMove(get_turf(src)) - suit = null - . = TRUE - - if("department") - var/choice = params["department"] - if(choice in departments) - target_department = departments[choice] - else if(emagged && (choice in emagged_departments)) - target_department = emagged_departments[choice] - . = TRUE - - if("species") - var/choice = params["species"] - if(choice in species) - target_species = species[choice] - . = TRUE - - if("radlevel") - radiation_level = clamp(params["radlevel"], 1, emagged ? 5 : 3) - . = TRUE - - if("repair_suit") - if(!suit || !can_repair) - return - active = 1 - spawn(100) - repair_suit() - finished_job() - . = TRUE - - if("apply_paintjob") - if(!suit && !helmet) - return - active = 1 - spawn(100) - apply_paintjob() - finished_job() - . = TRUE - - if("lock") - if(allowed(usr)) - locked = !locked - to_chat(usr, "You [locked ? "" : "un"]lock \the [src].") - else - to_chat(usr, "Access denied.") - . = TRUE - - if("eject_guy") - eject_occupant(usr) - . = TRUE - - if("uv") - 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 - - sleep(10) - - if(helmet) - if(radiation_level > 2) - helmet.decontaminate() - if(radiation_level > 1) - helmet.clean_blood() - - if(suit) - if(radiation_level > 2) - suit.decontaminate() - if(radiation_level > 1) - suit.clean_blood() - - . = TRUE - -/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("\icon[src][bicon(src)]The [src] beeps several times.") - icon_state = initial(icon_state) - active = 0 - playsound(src, 'sound/machines/boobeebeep.ogg', 50) - 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 - - if(occupant.client) - occupant.client.eye = occupant.client.mob - occupant.client.perspective = MOB_PERSPECTIVE - - occupant.loc = get_turf(occupant) - occupant = null - - add_fingerprint(user) - updateUsrDialog() - update_icon() - - return - -// "Streamlined" before? Ok. -Aro -/obj/machinery/suit_cycler/proc/apply_paintjob() - if(!target_species || !target_department) - return - - // Helmet to new paint - if(target_department.can_refit_helmet(helmet)) - target_department.do_refit_helmet(helmet) - // Suit to new paint - if(target_department.can_refit_suit(suit)) - target_department.do_refit_suit(suit) - // Attached voidsuit helmet to new paint - if(target_department.can_refit_helmet(suit?.helmet)) - target_department.do_refit_helmet(suit.helmet) - - // Species fitting for all 3 potential changes - if(target_species.can_refit_to(helmet, suit, suit?.helmet)) - target_species.do_refit_to(helmet, suit, suit?.helmet) - else - visible_message("\icon[src][bicon(src)]Unable to apply specified cosmetics with specified species. Please try again with a different species or cosmetic option selected.") - return diff --git a/icons/obj/robot_storage.dmi b/icons/obj/robot_storage.dmi index 24e0aa73a37c6ee2bc8337ca91d78cac101f38a7..a515f76d2f14bab1b65cb423bf48e7d46bf24d00 100644 GIT binary patch delta 1427 zcmV;E1#J4fF0%`NiBL{Q4GJ0x0000DNk~Le0001h0001B2m=5B0OF*IdjJ3cV^B;~ zMF0Q*7%4m~OKl%EPB?>$M69-z+~el<_uVBO4HqLVF+5dSW2C6C7#JdVdxTb6avvZm zH9mWTh@dcd$$YfgGCEWi7aSoZE-WxUidQmI7$0m@9sd9#0RBBa;G_xv=2pLmGs|_a zg8%>k0d!JMQvg8b*k%9#0G*K~Gk*YbjE%TBGg33tGfE(w;*!LYR3K9+IX|yBKPOd* zi!&v&s2C_>$iW zU6m2S!N$l=1#7`&G@2%51y?^8a99EWe=%I!ZHcmY000D4NklwkKqAP|OQ z)EsnOP=jfb9&-OzSPd%6vPCY+asHP1{_? zmLBA=MQXmu@~kKdEt4PQ*?OEeD9b`!o}%1MJ23b@z(eQnoC3;1M!73p9gKYM6tMh! zo2v$6I7a}&EnqqKR6w2W9)H1}MY-Gg_>Ki_MY*#=g7fna&I;%bLKWDD`D_KKfJ2}H zd(Q}&ey;BsemETD@H`ce1ulIhe53*o@}(6h)iw6a5!J+3AuoS?6}*^F8hF-mGA_4D zBOF_4I!+tp_RT6cJ4nknM|yX%BFm2JaoXaT<*-0`c3hRSDs9<4f`85q_O~z}7uMjc z!ER4~3f{`uK~io%G&wp*%h^1EVPB!-oXry$>+^TKBQ7dOJi_CX*L7X}(ZLT@k`Rv< zzv1#cE10p;g5^=m&O4zpj>W(SL-$=LtH5FbH~R3Yg(MLD=69 z!!UAopgCJp4Iza0-1qz+J#5%gTf&uqfWIHk=RtA)c@#iHBxuDXYefRM56tmVz^uO? z&L8JN2K#7LK-HEdkXPEMzzhch=9~@9`f--=;SfNu5yTeY=YLuN@b~TtfPez%q-F_v z(XYtVg9ITyt$@?t`vnlh65t*VuxBN%nq~>t0<=9ZUG_Xwfl1J11}os_ud09?8kl5e z1-u;0fpX>@P`CnpOQ$$rX>ISSfR8`03fuzdPRA2~c~0O6L)<06Spg$P0mNA6M5o~+ zBw?-v1pNJAg@59t;|W?>Vxmgi@@3YM5LXGF_V+SDFH0;&NdNSv052B_BK*BfZ~|AC z$H^4naL8nTr#@X=%h=e#45b*b~ z0wc#FfqLA~vz+ce6-|Ic93*(o-_r#2sh=g_CB|x&BY!bM9O7`EJ>~DkP*?(UqtRan zIGkrs`Fq(DoWKjYB+I0KMDE1Q&9- zT&x63c)Wl{TMpwIvsl7;#QOUv9_#O;-w(w4`{?%rvHm{#{ea=$uh)5hf4j}|C(eid z{rdU!^?!Nw`}^DX&(HVG&!0L!+TTaNAK(qdty1q2m_Iav4ia)<9uew{K*%(g3Ayy| z$O_xvr{nSs210jqzu!Rv^9@Hjt{d12?G93L<=-c_OUvIU}%={WK2REED#$Y{H{b*jx}GX55z1bB8T-9a+0{JrOP zsr`L2uKc}oqX7Os8CU+^bB(mWPsWwKb}Jn1buvEsduxtN{Cy%G?eC-C55)TW7rY;s hYp_{?NBjFY{tKB}e1$J$Zma+R002ovPDHLkV1mQmnFas= literal 5948 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 F{s&j~;vWD2 literal 0 HcmV?d00001 diff --git a/icons/obj/suit_storage.dmi b/icons/obj/suit_storage.dmi new file mode 100644 index 0000000000000000000000000000000000000000..5c39c1364e0d3f09133940c6d334ec11bad2966d GIT binary patch literal 4070 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 Zh7k$#?y9N?{>>>>>> fe3a6f2dfd... Merge pull request #14995 from Youtubeboy139/Suit-and-Robotic-Storage #include "code\game\machinery\supply_display.dm" #include "code\game\machinery\supplybeacon.dm" #include "code\game\machinery\syndicatebeacon.dm" @@ -1024,6 +1027,12 @@ #include "code\game\machinery\pipe\pipe_dispenser.dm" #include "code\game\machinery\pipe\pipe_recipes.dm" #include "code\game\machinery\pipe\pipelayer.dm" +#include "code\game\machinery\suit_storage\suit_cycler.dm" +#include "code\game\machinery\suit_storage\suit_cycler_datums.dm" +#include "code\game\machinery\suit_storage\suit_cycler_units.dm" +#include "code\game\machinery\suit_storage\suit_cycler_units_vr.dm" +#include "code\game\machinery\suit_storage\suit_storage.dm" +#include "code\game\machinery\suit_storage\suit_storage_units.dm" #include "code\game\machinery\telecomms\broadcaster.dm" #include "code\game\machinery\telecomms\broadcaster_ch.dm" #include "code\game\machinery\telecomms\logbrowser.dm"