diff --git a/aurorastation.dme b/aurorastation.dme
index 18de5e3f31a..ad9d421d282 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -637,6 +637,7 @@
#include "code\game\machinery\status_display.dm"
#include "code\game\machinery\status_display_ai.dm"
#include "code\game\machinery\status_display_snowflakes.dm"
+#include "code\game\machinery\suit_cycler.dm"
#include "code\game\machinery\suit_storage_unit.dm"
#include "code\game\machinery\supplybeacon.dm"
#include "code\game\machinery\syndicatebeacon.dm"
diff --git a/code/game/machinery/suit_cycler.dm b/code/game/machinery/suit_cycler.dm
new file mode 100644
index 00000000000..8bdfc5b67ef
--- /dev/null
+++ b/code/game/machinery/suit_cycler.dm
@@ -0,0 +1,647 @@
+/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 = "base"
+
+ req_access = list(access_captain, access_heads)
+
+ var/active = FALSE // PLEASE HOLD.
+ var/safeties = TRUE // 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 = TRUE // If locked, nothing can be taken from or added to the cycler.
+ var/can_repair // If set, the cycler can repair voidsuits.
+ var/electrified = FALSE
+
+ //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", "Tajara", "Vaurca", "Machine")
+
+ var/target_department
+ var/target_species
+
+ var/mob/living/carbon/human/occupant
+ var/obj/item/clothing/head/helmet/space/helmet
+ var/obj/item/clothing/suit/space/void/suit
+
+ var/datum/wires/suit_storage_unit/wires
+
+/obj/machinery/suit_cycler/Initialize()
+ . = ..()
+
+ wires = new(src)
+ target_department = departments[1]
+ target_species = species[1]
+ update_icon()
+ if(!target_department || !target_species)
+ qdel(src)
+
+/obj/machinery/suit_cycler/Destroy()
+ QDEL_NULL(wires)
+ return ..()
+
+/obj/machinery/suit_cycler/update_icon()
+ cut_overlays()
+
+ if(helmet)
+ //copied straight from the human update_icons thing
+ var/image/helmet_image = helmet.return_own_image()
+ if(helmet_image)
+ add_overlay(helmet_image)
+ if(suit)
+ var/image/suit_image = suit.return_own_image()
+ if(suit_image)
+ add_overlay(suit_image)
+ if(occupant)
+ var/image/occupant_image = image(occupant.icon, occupant.icon_state)
+ occupant_image.overlays = occupant.overlays
+ add_overlay(occupant_image)
+ add_overlay("closed")
+ add_overlay("overbase")
+ if(panel_open)
+ add_overlay("panel")
+
+ if(irradiating)
+ var/image/irradiating_lights = make_screen_overlay(icon, "light_radiation")
+ add_overlay(irradiating_lights)
+ else if(active)
+ var/image/active_lights = make_screen_overlay(icon, "light_active")
+ add_overlay(active_lights)
+
+/obj/machinery/suit_cycler/engineering
+ name = "engineering suit cycler"
+ model_text = "Engineering"
+ req_access = list(access_construction)
+ departments = list("Engineering", "Atmos")
+
+/obj/machinery/suit_cycler/mining
+ name = "mining suit cycler"
+ model_text = "Mining"
+ req_access = list(access_mining)
+ departments = list("Mining")
+
+/obj/machinery/suit_cycler/security
+ name = "security suit cycler"
+ model_text = "Security"
+ req_access = list(access_security)
+ departments = list("Security")
+
+/obj/machinery/suit_cycler/medical
+ name = "medical suit cycler"
+ model_text = "Medical"
+ req_access = list(access_medical)
+ departments = list("Medical")
+
+/obj/machinery/suit_cycler/syndicate
+ name = "non-standard suit cycler"
+ model_text = "Nonstandard"
+ req_access = list(access_syndicate)
+ departments = list("Mercenary")
+ can_repair = TRUE
+
+/obj/machinery/suit_cycler/wizard
+ name = "magic suit cycler"
+ model_text = "Wizardry"
+ req_access = null
+ departments = list("Wizardry")
+ species = list("Human", "Tajara", "Skrell", "Unathi", "Machine")
+ can_repair = TRUE
+
+/obj/machinery/suit_cycler/hos
+ name = "head of security suit cycler"
+ model_text = "head of Security"
+ req_access = list(access_hos)
+ departments = list("Head of Security") // ONE MAN DEPARTMENT HOO HA GIMME CRAYONS - Geeves
+ species = list("Human", "Tajara", "Skrell", "Unathi", "Machine")
+ can_repair = TRUE
+
+/obj/machinery/suit_cycler/captain
+ name = "captain suit cycler"
+ model_text = "Captain"
+ req_access = list(access_captain)
+ departments = list("Captain")
+ species = list("Human", "Tajara", "Skrell", "Unathi", "Machine")
+ can_repair = TRUE
+
+/obj/machinery/suit_cycler/science
+ name = "research suit cycler"
+ model_text = "Research"
+ req_access = list(access_research)
+ departments = list("Research")
+ species = list("Human", "Tajara", "Skrell", "Unathi", "Machine")
+ can_repair = TRUE
+
+/obj/machinery/suit_cycler/freelancer
+ name = "freelancers suit cycler"
+ model_text = "Freelancers"
+ req_access = list(access_distress)
+ departments = list("Freelancers")
+ species = list("Human", "Tajara", "Skrell", "Unathi", "Machine")
+ can_repair = TRUE
+
+/obj/machinery/suit_cycler/MouseDrop_T(mob/living/M, mob/living/user)
+ if(use_check_and_message(user))
+ return
+ if(!istype(M))
+ return
+
+ if(user != M)
+ to_chat(user, SPAN_WARNING("You need a grab to do this!"))
+ return
+
+ if(active || locked)
+ to_chat(user, SPAN_WARNING("\The [src] is locked."))
+ return
+
+ if(occupant)
+ to_chat(user, SPAN_WARNING("\The [src] is already occupied!"))
+ return
+
+ if(length(contents))
+ to_chat(user, SPAN_WARNING("There's no space in \the [src] for you!"))
+ return
+
+ user.visible_message("\The [M] starts climbing into \the [src]...", SPAN_NOTICE("You start climbing into \the [src]..."), range = 3)
+ if(do_after(user, 20, TRUE, src))
+ if(M.client)
+ M.client.perspective = EYE_PERSPECTIVE
+ M.client.eye = src
+ user.visible_message("\The [user] climbs into \the [src].", SPAN_NOTICE("You climb into \the [src]."), range = 3)
+ M.forceMove(src)
+ occupant = M
+
+ add_fingerprint(user)
+ updateUsrDialog()
+ update_icon()
+
+/obj/machinery/suit_cycler/attack_ai(mob/user)
+ return src.attack_hand(user)
+
+/obj/machinery/suit_cycler/attackby(obj/item/I, mob/user)
+ if(electrified != 0)
+ if(src.shock(user, 100))
+ return
+
+ if(istype(I, /obj/item/card/id) || istype(I, /obj/item/device/pda) || istype(I, /obj/item/modular_computer))
+ if(allowed(user))
+ locked = !locked
+ to_chat(user, SPAN_NOTICE("You [locked ? "" : "un"]lock \the [src]."))
+ else
+ to_chat(user, SPAN_WARNING("Access denied."))
+ return
+
+ //Hacking init.
+ if(I.ismultitool() || I.iswirecutter())
+ if(panel_open)
+ wires.Interact(user)
+ return
+
+ //Other interface stuff.
+ if(istype(I, /obj/item/grab))
+ var/obj/item/grab/G = I
+ if(G.state < GRAB_NECK)
+ to_chat(user, SPAN_WARNING("You need a stronger grip to do this!"))
+ return
+
+ if(!ismob(G.affecting))
+ to_chat(user, SPAN_WARNING("\The [G.affecting] doesn't fit into \the [src]!"))
+ return
+
+ if(active || locked)
+ to_chat(user, SPAN_DANGER("The suit cycler is locked."))
+ return
+
+ if(contents.len > 0)
+ to_chat(user, SPAN_WARNING("There is no room inside \the [src] for \the [G.affecting]."))
+ return
+
+ if(occupant)
+ to_chat(user, SPAN_WARNING("\The [src] is already occupied."))
+ return
+
+ user.visible_message("\The [user] starts putting \the [G.affecting] into \the [src]...", SPAN_NOTICE("You start putting \the [G.affecting] into \the [src]..."), range = 3)
+ if(do_after(user, 20, TRUE, src))
+ if(!G || !G.affecting)
+ return
+ var/mob/M = G.affecting
+ if(M.client)
+ M.client.perspective = EYE_PERSPECTIVE
+ M.client.eye = src
+ user.visible_message("\The [user] puts \the [G.affecting] into \the [src].", SPAN_NOTICE("You put \the [G.affecting] into \the [src]."), range = 3)
+ M.forceMove(src)
+ occupant = M
+
+ add_fingerprint(user)
+ qdel(G)
+
+ updateUsrDialog()
+ update_icon()
+ return
+ else if(I.isscrewdriver())
+ panel_open = !panel_open
+ to_chat(user, SPAN_NOTICE("You [panel_open ? "open" : "close"] the maintenance panel."))
+ updateUsrDialog()
+ update_icon()
+ return
+
+ else if(istype(I, /obj/item/clothing/head/helmet/space) && !istype(I, /obj/item/clothing/head/helmet/space/rig))
+ if(active || locked)
+ to_chat(user, SPAN_WARNING("\The [src] is locked."))
+ return
+
+ if(occupant)
+ to_chat(user, SPAN_WARNING("There is no space in \the [src] for \the [I]!"))
+ return
+
+ if(helmet)
+ to_chat(user, SPAN_WARNING("\The [src] already contains a helmet."))
+ return
+
+ if(I.icon_override == CUSTOM_ITEM_MOB)
+ to_chat(user, SPAN_WARNING("You cannot refit a customised voidsuit."))
+ return
+
+ to_chat(user, SPAN_NOTICE("You fit \the [I] into \the [src]."))
+ user.drop_from_inventory(I, src)
+ helmet = I
+ update_icon()
+ updateUsrDialog()
+ return
+
+ else if(istype(I, /obj/item/clothing/suit/space/void))
+ if(active || locked)
+ to_chat(user, SPAN_WARNING("\The [src] is locked."))
+ return
+
+ if(occupant)
+ to_chat(user, SPAN_WARNING("There is no space in \the [src] for \the [I]!"))
+ return
+
+ if(suit)
+ to_chat(user, SPAN_WARNING("\The [src] already contains a voidsuit."))
+ return
+
+ if(I.icon_override == CUSTOM_ITEM_MOB)
+ to_chat(user, SPAN_WARNING("You cannot refit a customised voidsuit."))
+ return
+
+ to_chat(user, SPAN_NOTICE("You fit \the [I] into \the [src]."))
+ user.drop_from_inventory(I, src)
+ suit = I
+
+ update_icon()
+ updateUsrDialog()
+ return
+
+ ..()
+
+/obj/machinery/suit_cycler/emag_act(var/remaining_charges, mob/user)
+ if(emagged)
+ to_chat(user, SPAN_WARNING("The cycler has already been subverted."))
+ return
+
+ //Clear the access reqs, disable the safeties, and open up all paintjobs.
+ to_chat(user, SPAN_WARNING("You run the sequencer across the interface, corrupting the operating protocols."))
+ departments = list("Engineering", "Mining", "Medical", "Security", "Atmos", "^%###^%$")
+ emagged = TRUE
+ safeties = FALSE
+ req_access = list()
+ updateUsrDialog()
+ return 1
+
+/obj/machinery/suit_cycler/attack_hand(mob/user)
+
+ add_fingerprint(user)
+
+ if(..() || stat & (BROKEN|NOPOWER))
+ return
+
+ if(!user.IsAdvancedToolUser())
+ return FALSE
+
+ if(electrified != 0)
+ if(src.shock(user, 100))
+ return
+
+ usr.set_machine(src)
+
+ var/dat = ""
+
+ 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(can_repair && 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)
+ wires.Interact(user)
+
+ send_theme_resources(user)
+ user << browse(enable_ui_theme(user, dat), "window=suit_cycler")
+ onclose(user, "suit_cycler")
+ return
+
+/obj/machinery/suit_cycler/Topic(href, href_list)
+ if(href_list["eject_suit"])
+ if(!suit)
+ return
+ suit.forceMove(get_turf(src))
+ usr.put_in_hands(suit)
+ suit = null
+ update_icon()
+
+ else if(href_list["eject_helmet"])
+ if(!helmet)
+ return
+ helmet.forceMove(get_turf(src))
+ usr.put_in_hands(helmet)
+ helmet = null
+ update_icon()
+
+ 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)
+ var/choice = input("Please select the desired radiation level.", "Suit cycler", null) as null|anything in choices
+ if(choice)
+ radiation_level = choice
+
+ else if(href_list["repair_suit"])
+ if(!suit || !can_repair)
+ return
+ active = TRUE
+ update_icon()
+ spawn(100)
+ repair_suit()
+ finished_job()
+
+ else if(href_list["apply_paintjob"])
+ if(!suit && !helmet)
+ return
+ if(suit && suit.helmet)
+ to_chat(usr, SPAN_WARNING("\The [src] cannot function while a helmet is attached to the suit!"))
+ return
+ var/list/no_refit
+ if(helmet && !helmet.refittable)
+ LAZYADD(no_refit, helmet)
+ if(suit && !suit.refittable)
+ LAZYADD(no_refit, suit)
+ if(LAZYLEN(no_refit))
+ to_chat(usr, SPAN_WARNING("\The [english_list(no_refit)] in [src] [no_refit.len == 1 ? "is" : "are"] not refittable!"))
+ return
+
+ active = TRUE
+ update_icon()
+ 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, SPAN_WARNING("You [locked ? "" : "un"]lock \the [src]."))
+ else
+ to_chat(usr, SPAN_WARNING("Access denied."))
+
+ else if(href_list["begin_decontamination"])
+ if(safeties && occupant)
+ to_chat(usr, SPAN_WARNING("The cycler has detected an occupant. Please remove the occupant before commencing the decontamination cycle."))
+ return
+
+ active = TRUE
+ irradiating = 10
+ update_icon()
+ src.updateUsrDialog()
+
+ 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()
+
+ src.updateUsrDialog()
+ return
+
+/obj/machinery/suit_cycler/machinery_process()
+ if(electrified > 0)
+ electrified = max(electrified - 1, 0)
+
+ if(!active)
+ return
+
+ if(active && stat & (BROKEN|NOPOWER))
+ active = FALSE
+ irradiating = 0
+ electrified = 0
+ update_icon()
+ return
+
+ if(irradiating == 1)
+ finished_job()
+ irradiating = 0
+ update_icon()
+ return
+
+ irradiating = max(irradiating - 1, 0)
+
+ 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()
+ visible_message("\icon[src] \The [src] pings loudly.")
+ playsound(loc, 'sound/machines/ping.ogg', 50, FALSE)
+ active = FALSE
+ update_icon()
+ 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(use_check_and_message(usr))
+ return
+
+ eject_occupant(usr)
+
+/obj/machinery/suit_cycler/proc/eject_occupant(mob/user)
+ if(locked || active)
+ to_chat(user, SPAN_WARNING("\The [src] is locked!"))
+ return
+
+ if(!occupant)
+ return
+
+ if(occupant.client)
+ occupant.client.eye = occupant.client.mob
+ occupant.client.perspective = MOB_PERSPECTIVE
+
+ occupant.forceMove(get_turf(src))
+ occupant = null
+
+ add_fingerprint(usr)
+ updateUsrDialog()
+ update_icon()
+ return
+
+//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 voidsuit helmet"
+ helmet.icon_state = "rig0-engineering"
+ helmet.item_state = "eng_helm"
+ if(suit)
+ suit.name = "engineering voidsuit"
+ suit.icon_state = "rig-engineering"
+ suit.item_state = "eng_voidsuit"
+ if("Mining")
+ if(helmet)
+ helmet.name = "mining voidsuit helmet"
+ helmet.icon_state = "rig0-mining"
+ helmet.item_state = "mining_helm"
+ if(suit)
+ suit.name = "mining voidsuit"
+ suit.icon_state = "rig-mining"
+ suit.item_state = "mining_voidsuit"
+ if("Medical")
+ if(helmet)
+ helmet.name = "medical voidsuit helmet"
+ helmet.icon_state = "rig0-medical"
+ helmet.item_state = "medical_helm"
+ if(suit)
+ suit.name = "medical voidsuit"
+ suit.icon_state = "rig-medical"
+ suit.item_state = "medical_voidsuit"
+ if("Security")
+ if(helmet)
+ helmet.name = "security voidsuit helmet"
+ helmet.icon_state = "rig0-sec"
+ helmet.item_state = "sec_helm"
+ if(suit)
+ suit.name = "security voidsuit"
+ suit.icon_state = "rig-sec"
+ suit.item_state = "sec_voidsuit"
+ if("Atmos")
+ if(helmet)
+ helmet.name = "atmospherics voidsuit helmet"
+ helmet.icon_state = "rig0-atmos"
+ helmet.item_state = "atmos_helm"
+ if(suit)
+ suit.name = "atmospherics voidsuit"
+ suit.icon_state = "rig-atmos"
+ suit.item_state = "atmos_voidsuit"
+ if("Captain")
+ if(helmet)
+ helmet.name = "captain voidsuit helmet"
+ helmet.icon_state = "capspace"
+ helmet.item_state = "capspace"
+ if(suit)
+ suit.name = "captain voidsuit"
+ suit.icon_state = "capspace"
+ suit.item_state = "capspace"
+ if("^%###^%$" || "Mercenary")
+ if(helmet)
+ helmet.name = "blood-red voidsuit helmet"
+ helmet.icon_state = "rig0-syndie"
+ helmet.item_state = "syndie_helm"
+ if(suit)
+ suit.name = "blood-red voidsuit"
+ suit.item_state = "syndie_voidsuit"
+ suit.icon_state = "rig-syndie"
+ if("Research")
+ if(helmet)
+ helmet.name = "research voidsuit helmet"
+ helmet.icon_state = "rig0-sci"
+ helmet.item_state = "research_voidsuit_helmet"
+ if(suit)
+ suit.name = "research voidsuit"
+ suit.item_state = "research_voidsuit"
+ suit.icon_state = "rig-sci"
+
+ if("Freelancers")
+ if(helmet)
+ helmet.name = "freelancer voidsuit helmet"
+ helmet.icon_state = "rig0-freelancer"
+ helmet.item_state = "rig0-freelancer"
+ if(suit)
+ suit.name = "freelancer voidsuit"
+ suit.item_state = "freelancer"
+ suit.icon_state = "freelancer"
+
+ if(helmet)
+ helmet.name = "refitted [helmet.name]"
+ if(suit)
+ suit.name = "refitted [suit.name]"
+ update_icon()
\ No newline at end of file
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index 9f0064f1430..dd2d768db3c 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -542,579 +542,4 @@
/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 painting and refitting voidsuits."
- anchored = TRUE
- density = TRUE
-
- icon = 'icons/obj/suit_storage.dmi'
- icon_state = "base"
-
- req_access = list(access_captain,access_heads)
-
- var/active = FALSE // PLEASE HOLD.
- var/safeties = TRUE // 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 = TRUE // If locked, nothing can be taken from or added to the cycler.
- var/can_repair // If set, the cycler can repair voidsuits.
- var/electrified = FALSE
-
- //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", "Tajara", "Vaurca", "Machine")
-
- var/target_department
- var/target_species
-
- var/mob/living/carbon/human/occupant
- var/obj/item/clothing/suit/space/void/suit
- var/obj/item/clothing/head/helmet/space/helmet
-
- var/datum/wires/suit_storage_unit/wires
-
-/obj/machinery/suit_cycler/Initialize()
- . = ..()
-
- wires = new(src)
- target_department = departments[1]
- target_species = species[1]
- update_icon()
- if(!target_department || !target_species)
- qdel(src)
-
-/obj/machinery/suit_cycler/Destroy()
- QDEL_NULL(wires)
- return ..()
-
-/obj/machinery/suit_cycler/update_icon()
- cut_overlays()
-
- if(panel_open)
- add_overlay("panel")
-
- if(irradiating)
- if(occupant)
- add_overlay("uvhuman")
- else
- add_overlay("uv")
-
-
- if(occupant)
- add_overlay("human")
-
- if(stat & BROKEN)
- add_overlay("broken")
-
- else
- add_overlay("closed")
-
-/obj/machinery/suit_cycler/engineering
- name = "engineering suit cycler"
- model_text = "Engineering"
- req_access = list(access_construction)
- departments = list("Engineering", "Atmos")
-
-/obj/machinery/suit_cycler/mining
- name = "mining suit cycler"
- model_text = "Mining"
- req_access = list(access_mining)
- departments = list("Mining")
-
-/obj/machinery/suit_cycler/security
- name = "security suit cycler"
- model_text = "Security"
- req_access = list(access_security)
- departments = list("Security")
-
-/obj/machinery/suit_cycler/medical
- name = "medical suit cycler"
- model_text = "Medical"
- req_access = list(access_medical)
- departments = list("Medical")
-
-/obj/machinery/suit_cycler/syndicate
- name = "non-standard suit cycler"
- model_text = "Nonstandard"
- req_access = list(access_syndicate)
- departments = list("Mercenary")
- can_repair = TRUE
-
-/obj/machinery/suit_cycler/wizard
- name = "magic suit cycler"
- model_text = "Wizardry"
- req_access = null
- departments = list("Wizardry")
- species = list("Human", "Tajara", "Skrell", "Unathi", "Machine")
- can_repair = TRUE
-
-/obj/machinery/suit_cycler/hos
- name = "head of security suit cycler"
- model_text = "Head of Security"
- req_access = list(access_hos)
- departments = list("Head of Security") // ONE MAN DEPARTMENT HOO HA GIMME CRAYONS - Geeves
- species = list("Human", "Tajara", "Skrell", "Unathi", "Machine")
- can_repair = TRUE
-
-/obj/machinery/suit_cycler/captain
- name = "captain suit cycler"
- model_text = "Captain"
- req_access = list(access_captain)
- departments = list("Captain")
- species = list("Human", "Tajara", "Skrell", "Unathi", "Machine")
- can_repair = TRUE
-
-/obj/machinery/suit_cycler/science
- name = "research suit cycler"
- model_text = "Research"
- req_access = list(access_research)
- departments = list("Research")
- species = list("Human", "Tajara", "Skrell", "Unathi", "Machine")
- can_repair = TRUE
-
-/obj/machinery/suit_cycler/freelancer
- name = "freelancers suit cycler"
- model_text = "Freelancers"
- req_access = list(access_distress)
- departments = list("Freelancers")
- species = list("Human", "Tajara", "Skrell", "Unathi", "Machine")
- can_repair = TRUE
-
-/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)
-
- if(electrified != 0)
- if(src.shock(user, 100))
- return
-
- //Hacking init.
- if(I.ismultitool() || I.iswirecutter())
- 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
-
- user.visible_message("[user] starts putting [G.affecting] into [src].", "You start putting [G.affecting] into [src].", range = 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.forceMove(src)
- src.occupant = M
-
- src.add_fingerprint(user)
- qdel(G)
-
- src.updateUsrDialog()
-
- return
- else if(I.isscrewdriver())
-
- panel_open = !panel_open
- to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.")
- src.updateUsrDialog()
- update_icon()
- return
-
- else if(istype(I,/obj/item/clothing/head/helmet/space) && !istype(I, /obj/item/clothing/head/helmet/space/rig))
-
- if(locked)
- to_chat(user, "The suit cycler is locked.")
- return
-
- if(helmet)
- to_chat(user, "The cycler already contains a helmet.")
- return
-
- if(I.icon_override == CUSTOM_ITEM_MOB)
- to_chat(user, "You cannot refit a customised voidsuit.")
- return
-
- to_chat(user, "You fit \the [I] into the suit cycler.")
- user.drop_from_inventory(I,src)
- helmet = I
-
- src.update_icon()
- src.updateUsrDialog()
- return
-
- else if(istype(I,/obj/item/clothing/suit/space/void))
-
- if(locked)
- to_chat(user, "The suit cycler is locked.")
- return
-
- if(suit)
- to_chat(user, "The cycler already contains a voidsuit.")
- return
-
- if(I.icon_override == CUSTOM_ITEM_MOB)
- to_chat(user, "You cannot refit a customised voidsuit.")
- return
-
- to_chat(user, "You fit \the [I] into the suit cycler.")
- user.drop_from_inventory(I,src)
- suit = I
-
- src.update_icon()
- src.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.")
- departments = list("Engineering","Mining","Medical","Security","Atmos","^%###^%$")
- emagged = 1
- safeties = 0
- req_access = list()
- src.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(src.shock(user, 100))
- return
-
- usr.set_machine(src)
-
- var/dat = ""
-
- 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(can_repair && 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)
- wires.Interact(user)
-
- send_theme_resources(user)
- user << browse(enable_ui_theme(user, dat), "window=suit_cycler")
- onclose(user, "suit_cycler")
- return
-
-/obj/machinery/suit_cycler/Topic(href, href_list)
- if(href_list["eject_suit"])
- if(!suit) return
- suit.forceMove(get_turf(src))
- suit = null
- else if(href_list["eject_helmet"])
- if(!helmet) return
- helmet.forceMove(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 || !can_repair) return
- active = 1
- spawn(100)
- repair_suit()
- finished_job()
-
- else if(href_list["apply_paintjob"])
-
- if(!suit && !helmet) return
- if(suit && suit.helmet)
- to_chat(usr, "\The [src] cannot function while a helmet is attached to the suit!")
- return
- var/list/no_refit
- if (helmet && !helmet.refittable)
- LAZYADD(no_refit, helmet)
- if (suit && !suit.refittable)
- LAZYADD(no_refit, suit)
- if (LAZYLEN(no_refit))
- to_chat(usr, "\The [english_list(no_refit)] in [src] [no_refit.len == 1 ? "is" : "are"] not refittable!")
- 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
- update_icon()
- src.updateUsrDialog()
-
- 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()
-
- src.updateUsrDialog()
- return
-
-/obj/machinery/suit_cycler/machinery_process()
-
- if(electrified > 0)
- electrified--
-
- if(!active)
- return
-
- if(active && stat & (BROKEN|NOPOWER))
- active = 0
- irradiating = 0
- electrified = 0
- update_icon()
- return
-
- if(irradiating == 1)
- finished_job()
- irradiating = 0
- update_icon()
- 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]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
-
- if (occupant.client)
- occupant.client.eye = occupant.client.mob
- occupant.client.perspective = MOB_PERSPECTIVE
-
- occupant.forceMove(get_turf(occupant))
- occupant = null
-
- add_fingerprint(usr)
- src.updateUsrDialog()
- src.update_icon()
-
- return
-
-//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 voidsuit helmet"
- helmet.icon_state = "rig0-engineering"
- helmet.item_state = "eng_helm"
- if(suit)
- suit.name = "engineering voidsuit"
- suit.icon_state = "rig-engineering"
- suit.item_state = "eng_voidsuit"
- if("Mining")
- if(helmet)
- helmet.name = "mining voidsuit helmet"
- helmet.icon_state = "rig0-mining"
- helmet.item_state = "mining_helm"
- if(suit)
- suit.name = "mining voidsuit"
- suit.icon_state = "rig-mining"
- suit.item_state = "mining_voidsuit"
- if("Medical")
- if(helmet)
- helmet.name = "medical voidsuit helmet"
- helmet.icon_state = "rig0-medical"
- helmet.item_state = "medical_helm"
- if(suit)
- suit.name = "medical voidsuit"
- suit.icon_state = "rig-medical"
- suit.item_state = "medical_voidsuit"
- if("Security")
- if(helmet)
- helmet.name = "security voidsuit helmet"
- helmet.icon_state = "rig0-sec"
- helmet.item_state = "sec_helm"
- if(suit)
- suit.name = "security voidsuit"
- suit.icon_state = "rig-sec"
- suit.item_state = "sec_voidsuit"
- if("Atmos")
- if(helmet)
- helmet.name = "atmospherics voidsuit helmet"
- helmet.icon_state = "rig0-atmos"
- helmet.item_state = "atmos_helm"
- if(suit)
- suit.name = "atmospherics voidsuit"
- suit.icon_state = "rig-atmos"
- suit.item_state = "atmos_voidsuit"
- if("Captain")
- if(helmet)
- helmet.name = "captain voidsuit helmet"
- helmet.icon_state = "capspace"
- helmet.item_state = "capspace"
- if(suit)
- suit.name = "captain voidsuit"
- suit.icon_state = "capspace"
- suit.item_state = "capspace"
- if("^%###^%$" || "Mercenary")
- if(helmet)
- helmet.name = "blood-red voidsuit helmet"
- helmet.icon_state = "rig0-syndie"
- helmet.item_state = "syndie_helm"
- if(suit)
- suit.name = "blood-red voidsuit"
- suit.item_state = "syndie_voidsuit"
- suit.icon_state = "rig-syndie"
- if("Research")
- if(helmet)
- helmet.name = "research voidsuit helmet"
- helmet.icon_state = "rig0-sci"
- helmet.item_state = "research_voidsuit_helmet"
- if(suit)
- suit.name = "research voidsuit"
- suit.item_state = "research_voidsuit"
- suit.icon_state = "rig-sci"
-
- if("Freelancers")
- if(helmet)
- helmet.name = "freelancer voidsuit helmet"
- helmet.icon_state = "rig0-freelancer"
- helmet.item_state = "rig0-freelancer"
- if(suit)
- suit.name = "freelancer voidsuit"
- suit.item_state = "freelancer"
- suit.icon_state = "freelancer"
-
- if(helmet) helmet.name = "refitted [helmet.name]"
- if(suit) suit.name = "refitted [suit.name]"
+ return src.attack_hand(user)
\ No newline at end of file
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index b0209b3d146..1703fca3137 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -85,6 +85,15 @@
return 0
return 1
+/obj/item/clothing/proc/return_own_image()
+ var/image/our_image
+ if(icon_override)
+ our_image = image(icon_override, icon_state)
+ else if(item_icons && (slot_head_str in item_icons))
+ our_image = image(item_icons[slot_head_str], icon_state)
+ our_image.color = color
+ return our_image
+
/obj/item/clothing/proc/refit_for_species(var/target_species)
if(!species_restricted)
return //this item doesn't use the species_restricted system
@@ -508,6 +517,21 @@
to_chat(user, "You crawl under \the [src].")
return 1
+/obj/item/clothing/head/return_own_image()
+ var/image/our_image
+ if(contained_sprite)
+ auto_adapt_species(src)
+ var/state = "[icon_species_tag ? "[icon_species_tag]_" : ""][item_state][WORN_HEAD]"
+ our_image = image(icon_override || icon, state)
+ else if(icon_override)
+ our_image = image(icon_override, icon_state)
+ else if(item_icons && (slot_head_str in item_icons))
+ our_image = image(item_icons[slot_head_str], icon_state)
+ else
+ our_image = image(INV_HEAD_DEF_ICON, icon_state)
+ our_image.color = color
+ return our_image
+
/obj/item/clothing/head/update_icon(var/mob/user)
cut_overlays()
@@ -749,6 +773,21 @@
valid_accessory_slots = list("armband","decor", "over")
+/obj/item/clothing/suit/return_own_image()
+ var/image/our_image
+ if(contained_sprite)
+ auto_adapt_species(src)
+ var/state = "[icon_species_tag ? "[icon_species_tag]_" : ""][item_state][WORN_SUIT]"
+ our_image = image(icon_override || icon, state)
+ else if(icon_override)
+ our_image = image(icon_override, icon_state)
+ else if(item_icons && (slot_head_str in item_icons))
+ our_image = image(item_icons[slot_head_str], icon_state)
+ else
+ our_image = image(INV_SUIT_DEF_ICON, icon_state)
+ our_image.color = color
+ return our_image
+
/obj/item/clothing/suit/update_clothing_icon()
if (ismob(src.loc))
var/mob/M = src.loc
@@ -860,6 +899,21 @@
rolled_sleeves = -1
if(H) update_clothing_icon()
+/obj/item/clothing/under/return_own_image()
+ var/image/our_image
+ if(contained_sprite)
+ auto_adapt_species(src)
+ var/state = "[icon_species_tag ? "[icon_species_tag]_" : ""][item_state][WORN_UNDER]"
+ our_image = image(icon_override || icon, state)
+ else if(icon_override)
+ our_image = image(icon_override, icon_state)
+ else if(item_icons && (slot_head_str in item_icons))
+ our_image = image(item_icons[slot_head_str], icon_state)
+ else
+ our_image = image(INV_W_UNIFORM_DEF_ICON, icon_state)
+ our_image.color = color
+ return our_image
+
/obj/item/clothing/under/update_clothing_icon()
if (ismob(src.loc))
var/mob/M = src.loc
diff --git a/html/changelogs/geeves-suit_storage_pretty.yml b/html/changelogs/geeves-suit_storage_pretty.yml
new file mode 100644
index 00000000000..9d86c3fa1c8
--- /dev/null
+++ b/html/changelogs/geeves-suit_storage_pretty.yml
@@ -0,0 +1,12 @@
+author: Geeves
+
+delete-after: True
+
+changes:
+ - imageadd: "Suit Cyclers have received new sprites, and any suits contained within will be on display as part of the sprite."
+ - rscadd: "Using your ID, PDA, or Computer on a suit cycler will now attempt to unlock it."
+ - tweak: "The grab strength needed to put someone into a suit cycler has been increased to a neck grab."
+ - bugfix: "You can no longer put helmets and suits in a suit cycler that's containing someone."
+ - rscadd: "Ejecting a helmet or suit from a suit cycler will now attempt to place it in one of your empty hands."
+ - rscadd: "Added an audible ping to suit cycler action completion."
+ - rscadd: "You can now click drag yourself into a suit cycler to climb into it."
\ No newline at end of file
diff --git a/icons/obj/suit_cycler.dmi b/icons/obj/suit_cycler.dmi
new file mode 100644
index 00000000000..418ce5d1767
Binary files /dev/null and b/icons/obj/suit_cycler.dmi differ