diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 15d095f44af..25df1301eee 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -80,6 +80,8 @@ GLOBAL_PROTECT(admin_verbs_admin)
/client/proc/resetasaycolor,
/client/proc/toggleadminhelpsound,
/client/proc/respawn_character,
+ /datum/admins/proc/toggleaooc, //SKYRAT EDIT ADDITION - ADMIN
+ /datum/admins/proc/togglesooc, //SKYRAT EDIT ADDITION - ADMIN
/datum/admins/proc/open_borgopanel
)
GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/ban_panel, /client/proc/stickybanpanel))
diff --git a/modular_skyrat/modules/admin/code/aooc.dm b/modular_skyrat/modules/admin/code/aooc.dm
new file mode 100644
index 00000000000..d5e3ed7c4a5
--- /dev/null
+++ b/modular_skyrat/modules/admin/code/aooc.dm
@@ -0,0 +1,112 @@
+GLOBAL_VAR_INIT(AOOC_COLOR, "#de3c8c")
+GLOBAL_VAR_INIT(aooc_allowed, TRUE) // used with admin verbs to disable aooc - not a config option
+GLOBAL_LIST_EMPTY(ckey_to_aooc_name)
+
+#define AOOC_LISTEN_PLAYER 1
+#define AOOC_LISTEN_ADMIN 2
+
+/client/verb/aooc(msg as text)
+ set name = "AOOC"
+ set category = "OOC"
+
+ if(GLOB.say_disabled) //This is here to try to identify lag problems
+ to_chat(usr, "Speech is currently admin-disabled.")
+ return
+
+ if(!mob)
+ return
+
+ if(!holder)
+ if(!mob.mind || !length(mob.mind.antag_datums))
+ to_chat(src, "You're not an antagonist!")
+ return
+ if(!GLOB.aooc_allowed)
+ to_chat(src, "AOOC is globally muted.")
+ return
+ if(prefs.muted & MUTE_OOC)
+ to_chat(src, "You cannot use OOC (muted).")
+ return
+ if(is_banned_from(ckey, "OOC"))
+ to_chat(src, "You have been banned from OOC.")
+ return
+ if(QDELETED(src))
+ return
+
+ msg = copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN)
+ var/raw_msg = msg
+
+ if(!msg)
+ return
+
+ msg = emoji_parse(msg)
+
+ if(!(prefs.chat_toggles & CHAT_OOC))
+ to_chat(src, "You have OOC muted.")
+ return
+
+ mob.log_talk(raw_msg, LOG_OOC, tag="AOOC")
+
+ var/keyname = key
+ var/anon = FALSE
+
+ //Anonimity for players and deadminned admins
+ if(!holder || holder.deadmined)
+ if(!GLOB.ckey_to_aooc_name[key])
+ GLOB.ckey_to_aooc_name[key] = "Operator [pick(GLOB.phonetic_alphabet)] [rand(1, 99)]"
+ keyname = GLOB.ckey_to_aooc_name[key]
+ anon = TRUE
+
+ var/list/listeners = list()
+
+ for(var/mind in get_antag_minds(/datum/antagonist))
+ var/datum/mind/M = mind
+ if(!M.current || !M.current.client || isnewplayer(M.current))
+ continue
+ listeners[M.current.client] = AOOC_LISTEN_PLAYER
+
+ for(var/m in GLOB.player_list)
+ var/mob/M = m
+ //Admins with muted OOC do not get to listen to AOOC, but normal players do, as it could be admins talking important stuff to them
+ if(M.client && M.client.holder && !M.client.holder.deadmined && M.client.prefs.chat_toggles & CHAT_OOC)
+ listeners[M.client] = AOOC_LISTEN_ADMIN
+
+ for(var/c in listeners)
+ var/client/C = c
+ var/mode = listeners[c]
+ var/color = (!anon && CONFIG_GET(flag/allow_admin_ooccolor) && C.prefs.ooccolor) ? C.prefs.ooccolor : GLOB.AOOC_COLOR
+ var/name = (mode == AOOC_LISTEN_ADMIN && anon) ? "([key])[keyname]" : keyname
+ to_chat(C, "AOOC: [name]: [msg]")
+
+#undef AOOC_LISTEN_PLAYER
+#undef AOOC_LISTEN_ADMIN
+
+/proc/toggle_aooc(toggle = null)
+ if(toggle != null) //if we're specifically en/disabling aooc
+ if(toggle != GLOB.aooc_allowed)
+ GLOB.aooc_allowed = toggle
+ else
+ return
+ else //otherwise just toggle it
+ GLOB.aooc_allowed = !GLOB.aooc_allowed
+ var/list/listeners = list()
+ for(var/mind in get_antag_minds(/datum/antagonist))
+ var/datum/mind/M = mind
+ if(!M.current || !M.current.client || isnewplayer(M.current))
+ continue
+ listeners[M.current.client] = TRUE
+
+ for(var/m in GLOB.player_list)
+ var/mob/M = m
+ if(M.client && M.client.holder && !M.client.holder.deadmined)
+ listeners[M.client] = TRUE
+ for(var/c in listeners)
+ var/client/C = c
+ to_chat(C, "The AOOC channel has been globally [GLOB.aooc_allowed ? "enabled" : "disabled"].")
+
+/datum/admins/proc/toggleaooc()
+ set category = "Server"
+ set name="Toggle Antag OOC"
+ toggle_aooc()
+ log_admin("[key_name(usr)] toggled Antagonist OOC.")
+ message_admins("[key_name_admin(usr)] toggled Antagonist OOC.")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Antag OOC", "[GLOB.aooc_allowed ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/modular_skyrat/modules/admin/code/sooc.dm b/modular_skyrat/modules/admin/code/sooc.dm
new file mode 100644
index 00000000000..56e642c4fa5
--- /dev/null
+++ b/modular_skyrat/modules/admin/code/sooc.dm
@@ -0,0 +1,118 @@
+GLOBAL_VAR_INIT(SOOC_COLOR, "#ff5454")
+GLOBAL_VAR_INIT(sooc_allowed, TRUE) // used with admin verbs to disable sooc - not a config option
+GLOBAL_LIST_EMPTY(ckey_to_sooc_name)
+
+#define SOOC_LISTEN_PLAYER 1
+#define SOOC_LISTEN_ADMIN 2
+
+/client/verb/sooc(msg as text)
+ set name = "SOOC"
+ set category = "OOC"
+
+ if(GLOB.say_disabled) //This is here to try to identify lag problems
+ to_chat(usr, "Speech is currently admin-disabled.")
+ return
+
+ if(!mob)
+ return
+
+ var/static/list/job_lookup = list("Security Officer"=TRUE, "Warden"=TRUE, "Detective"=TRUE, "Head of Security"=TRUE, "Captain"=TRUE, "Blueshield"=TRUE)
+ if(!holder)
+ if(!mob.mind || !job_lookup[mob.mind.assigned_role])
+ to_chat(src, "You're not a security role!")
+ return
+ if(!GLOB.sooc_allowed)
+ to_chat(src, "SOOC is globally muted.")
+ return
+ if(prefs.muted & MUTE_OOC)
+ to_chat(src, "You cannot use OOC (muted).")
+ return
+ if(is_banned_from(ckey, "OOC"))
+ to_chat(src, "You have been banned from OOC.")
+ return
+ if(QDELETED(src))
+ return
+
+ msg = copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN)
+ var/raw_msg = msg
+
+ if(!msg)
+ return
+
+ msg = emoji_parse(msg)
+
+ if(!(prefs.chat_toggles & CHAT_OOC))
+ to_chat(src, "You have OOC muted.")
+ return
+
+ mob.log_talk(raw_msg, LOG_OOC, tag="SOOC")
+
+ var/keyname = key
+ var/anon = FALSE
+
+ //Anonimity for players and deadminned admins
+ if(!holder || holder.deadmined)
+ if(!GLOB.ckey_to_sooc_name[key])
+ GLOB.ckey_to_sooc_name[key] = "Deputy [pick(GLOB.phonetic_alphabet)] [rand(1, 99)]"
+ keyname = GLOB.ckey_to_sooc_name[key]
+ anon = TRUE
+
+ var/list/listeners = list()
+
+ for(var/mind in get_antag_minds(/datum/antagonist))
+ var/datum/mind/M = mind
+ if(!M.current || !M.current.client || isnewplayer(M.current))
+ continue
+ listeners[M.current.client] = SOOC_LISTEN_PLAYER
+
+ for(var/m in GLOB.player_list)
+ var/mob/M = m
+ //Admins with muted OOC do not get to listen to SOOC, but normal players do, as it could be admins talking important stuff to them
+ if(M.client && M.client.holder && !M.client.holder.deadmined && M.client.prefs.chat_toggles & CHAT_OOC)
+ listeners[M.client] = SOOC_LISTEN_ADMIN
+ else
+ if(M.mind)
+ var/datum/mind/MIND = M.mind
+ if(job_lookup[MIND.assigned_role])
+ listeners[M.client] = SOOC_LISTEN_PLAYER
+
+ for(var/c in listeners)
+ var/client/C = c
+ var/mode = listeners[c]
+ var/color = (!anon && CONFIG_GET(flag/allow_admin_ooccolor) && C.prefs.ooccolor) ? C.prefs.ooccolor : GLOB.SOOC_COLOR
+ var/name = (mode == SOOC_LISTEN_ADMIN && anon) ? "([key])[keyname]" : keyname
+ to_chat(C, "SOOC: [name]: [msg]")
+
+#undef SOOC_LISTEN_PLAYER
+#undef SOOC_LISTEN_ADMIN
+
+/proc/toggle_sooc(toggle = null)
+ if(toggle != null) //if we're specifically en/disabling sooc
+ if(toggle != GLOB.sooc_allowed)
+ GLOB.sooc_allowed = toggle
+ else
+ return
+ else //otherwise just toggle it
+ GLOB.sooc_allowed = !GLOB.sooc_allowed
+ var/list/listeners = list()
+ for(var/mind in get_antag_minds(/datum/antagonist))
+ var/datum/mind/M = mind
+ if(!M.current || !M.current.client || isnewplayer(M.current))
+ continue
+ listeners[M.current.client] = TRUE
+
+ for(var/m in GLOB.player_list)
+ var/mob/M = m
+ if(M.client && M.client.holder && !M.client.holder.deadmined)
+ listeners[M.client] = TRUE
+ for(var/c in listeners)
+ var/client/C = c
+ to_chat(C, "The SOOC channel has been globally [GLOB.sooc_allowed ? "enabled" : "disabled"].")
+
+/datum/admins/proc/togglesooc()
+ set category = "Server"
+ set name="Toggle Security OOC"
+ toggle_sooc()
+ log_admin("[key_name(usr)] toggled Security OOC.")
+ message_admins("[key_name_admin(usr)] toggled Security OOC.")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Antag OOC", "[GLOB.sooc_allowed ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/tgstation.dme b/tgstation.dme
index 06d2d36b61c..6c5db9b50c5 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -3284,7 +3284,9 @@
#include "modular_skyrat\master_files\code\modules\mob\living\carbon\carbon_say.dm"
#include "modular_skyrat\master_files\code\modules\power\lighting.dm"
#include "modular_skyrat\modules\admin\code\admin_help.dm"
+#include "modular_skyrat\modules\admin\code\aooc.dm"
#include "modular_skyrat\modules\admin\code\loud_say.dm"
+#include "modular_skyrat\modules\admin\code\sooc.dm"
#include "modular_skyrat\modules\aesthetics\airalarm\code\airalarm.dm"
#include "modular_skyrat\modules\aesthetics\airlock\code\airlock.dm"
#include "modular_skyrat\modules\aesthetics\apc\code\apc.dm"
@@ -3330,13 +3332,13 @@
#include "modular_skyrat\modules\altborgs\code\modules\mob\living\silicon\robot\robot.dm"
#include "modular_skyrat\modules\altborgs\code\modules\mob\living\silicon\robot\robot_modules.dm"
#include "modular_skyrat\modules\altborgs\code\modules\mob\living\silicon\robot\update_icons.dm"
+#include "modular_skyrat\modules\antagonists\code\gamemodes.dm"
+#include "modular_skyrat\modules\antagonists\code\modules\uplink\uplink_items.dm"
#include "modular_skyrat\modules\biohazard_blob\code\_biohazard_blob_defines.dm"
#include "modular_skyrat\modules\biohazard_blob\code\biohazard_blob_controller.dm"
#include "modular_skyrat\modules\biohazard_blob\code\biohazard_blob_disease.dm"
#include "modular_skyrat\modules\biohazard_blob\code\biohazard_blob_mobs.dm"
#include "modular_skyrat\modules\biohazard_blob\code\biohazard_blob_structures.dm"
-#include "modular_skyrat\modules\antagonists\code\gamemodes.dm"
-#include "modular_skyrat\modules\antagonists\code\modules\uplink\uplink_items.dm"
#include "modular_skyrat\modules\blueshield\code\game\area\Space_Station_13_areas.dm"
#include "modular_skyrat\modules\blueshield\code\game\gamemodes\brother\traitor_bro.dm"
#include "modular_skyrat\modules\blueshield\code\game\gamemodes\changeling\changeling.dm"
@@ -3591,12 +3593,12 @@
#include "modular_skyrat\modules\pixel_shift\code\pixel_shift.dm"
#include "modular_skyrat\modules\QOL\code\_under.dm"
#include "modular_skyrat\modules\radiosound\code\game\objects\items\devices\radio\headset.dm"
+#include "modular_skyrat\modules\roboclothes\code\clothing\robotics_clothing.dm"
+#include "modular_skyrat\modules\roboclothes\code\vending\wardrobes.dm"
#include "modular_skyrat\modules\shapeshifting_module\code\game\objects\items\borg_shapeshifter.dm"
#include "modular_skyrat\modules\shapeshifting_module\code\game\objects\items\robot\robot_upgrades.dm"
#include "modular_skyrat\modules\shapeshifting_module\code\modules\research\designs\mechfabricator_designs.dm"
#include "modular_skyrat\modules\shapeshifting_module\code\modules\research\techweb\all_nodes.dm"
-#include "modular_skyrat\modules\roboclothes\code\clothing\robotics_clothing.dm"
-#include "modular_skyrat\modules\roboclothes\code\vending\wardrobes.dm"
#include "modular_skyrat\modules\SiliconQoL\code\_onclick.dm"
#include "modular_skyrat\modules\ssd_indicator\code\mob.dm"
#include "modular_skyrat\modules\tagline\code\world.dm"