diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm
index 779d239c834..329a90ebd8b 100644
--- a/code/__DEFINES/sound.dm
+++ b/code/__DEFINES/sound.dm
@@ -107,7 +107,7 @@
#define ANNOUNCER_ALIENS "announcer_aliens"
#define ANNOUNCER_ANIMES "announcer_animes"
#define ANNOUNCER_GRANOMALIES "announcer_granomalies"
-#define ANNOUNCER_INTERCEPT "announcer_animes"
+#define ANNOUNCER_INTERCEPT "announcer_intercept"
#define ANNOUNCER_IONSTORM "announcer_ionstorm"
#define ANNOUNCER_METEORS "announcer_meteors"
#define ANNOUNCER_OUTBREAK5 "announcer_outbreak5"
@@ -119,3 +119,67 @@
#define ANNOUNCER_SHUTTLEDOCK "announcer_shuttledock"
#define ANNOUNCER_SHUTTLERECALLED "announcer_shuttlerecalled"
#define ANNOUNCER_SPANOMALIES "announcer_spanomalies"
+
+//SKYRAT EDIT ADDITION BEGIN
+#define ANNOUNCER_SHUTTLELEFT "announcer_shuttleleft"
+#define ANNOUNCER_CARP "announcer_carp"
+#define ANNOUNCER_VORTEXANOMALIES "announcer_vortexanomalies"
+#define ANNOUNCER_CAPTAIN "announcer_captain"
+#define ANNOUNCER_MASSIVEBSPACEANOMALIES "announcer_massivebspaceanomalies"
+#define ANNOUNCER_PYROANOMALIES "announcer_pyroanomalies"
+#define ANNOUNCER_FLUXANOMALIES "announcer_fluxanomalies"
+#define ANNOUNCER_GRAVANOMALIES "announcer_gravanomalies"
+#define ANNOUNCER_GRAVGENON "announcer_gravgenon"
+#define ANNOUNCER_GRAVGENOFF "announcer_gravgenoff"
+#define ANNOUNCER_GREYTIDE "announcer_greytide"
+#define ANNOUNCER_COMMSBLACKOUT "announcer_commsblackout"
+#define ANNOUNCER_ELECTRICALSTORM "announcer_electricalstorm"
+#define ANNOUNCER_BRANDINTELLIGENCE "announcer_brandintelligence"
+#define ANNOUNCER_RADIATIONPASSED "announcer_radiationpasssed"
+#define ANNOUNCER_BLUESPACEARTY "announcer_bluespacearty"
+#define ANNOUNCER_SPOOKY "announcer_spooky"
+#define ANNOUNCER_ERTYES "announcer_ertyes"
+#define ANNOUNCER_MUTANTS "announcer_mutants"
+//SKYRAT EDIT END
+
+
+/// Global list of all of our announcer keys.
+GLOBAL_LIST_INIT(announcer_keys, list(
+ ANNOUNCER_AIMALF,
+ ANNOUNCER_ALIENS,
+ ANNOUNCER_ANIMES,
+ ANNOUNCER_GRANOMALIES,
+ ANNOUNCER_INTERCEPT,
+ ANNOUNCER_IONSTORM,
+ ANNOUNCER_METEORS,
+ ANNOUNCER_OUTBREAK5,
+ ANNOUNCER_OUTBREAK7,
+ ANNOUNCER_POWEROFF,
+ ANNOUNCER_POWERON,
+ ANNOUNCER_RADIATION,
+ ANNOUNCER_SHUTTLECALLED,
+ ANNOUNCER_SHUTTLEDOCK,
+ ANNOUNCER_SHUTTLERECALLED,
+ ANNOUNCER_SPANOMALIES,
+ //SKYRAT EDIT ADDITION BEGIN
+ ANNOUNCER_SHUTTLELEFT,
+ ANNOUNCER_CARP,
+ ANNOUNCER_VORTEXANOMALIES,
+ ANNOUNCER_CAPTAIN,
+ ANNOUNCER_MASSIVEBSPACEANOMALIES,
+ ANNOUNCER_PYROANOMALIES,
+ ANNOUNCER_FLUXANOMALIES,
+ ANNOUNCER_GRAVANOMALIES,
+ ANNOUNCER_GRAVGENON,
+ ANNOUNCER_GRAVGENOFF,
+ ANNOUNCER_GREYTIDE,
+ ANNOUNCER_COMMSBLACKOUT,
+ ANNOUNCER_ELECTRICALSTORM,
+ ANNOUNCER_BRANDINTELLIGENCE,
+ ANNOUNCER_RADIATIONPASSED,
+ ANNOUNCER_BLUESPACEARTY,
+ ANNOUNCER_SPOOKY,
+ ANNOUNCER_ERTYES,
+ ANNOUNCER_MUTANTS
+ //SKYRAT EDIT END
+))
diff --git a/code/__DEFINES/~skyrat_defines/sound.dm b/code/__DEFINES/~skyrat_defines/sound.dm
deleted file mode 100644
index b0ed3ea6347..00000000000
--- a/code/__DEFINES/~skyrat_defines/sound.dm
+++ /dev/null
@@ -1,19 +0,0 @@
-#define ANNOUNCER_SHUTTLELEFT "announcer_shuttleleft"
-#define ANNOUNCER_CARP "announcer_carp"
-#define ANNOUNCER_VORTEXANOMALIES "announcer_vortexanomalies"
-#define ANNOUNCER_CAPTAIN "announcer_captain"
-#define ANNOUNCER_MASSIVEBSPACEANOMALIES "announcer_massivebspaceanomalies"
-#define ANNOUNCER_PYROANOMALIES "announcer_pyroanomalies"
-#define ANNOUNCER_FLUXANOMALIES "announcer_fluxanomalies"
-#define ANNOUNCER_GRAVANOMALIES "announcer_gravanomalies"
-#define ANNOUNCER_GRAVGENON "announcer_gravgenon"
-#define ANNOUNCER_GRAVGENOFF "announcer_gravgenoff"
-#define ANNOUNCER_GREYTIDE "announcer_greytide"
-#define ANNOUNCER_COMMSBLACKOUT "announcer_commsblackout"
-#define ANNOUNCER_ELECTRICALSTORM "announcer_electricalstorm"
-#define ANNOUNCER_BRANDINTELLIGENCE "announcer_brandintelligence"
-#define ANNOUNCER_RADIATIONPASSED "announcer_radiationpasssed"
-#define ANNOUNCER_BLUESPACEARTY "announcer_bluespacearty"
-#define ANNOUNCER_SPOOKY "announcer_spooky"
-#define ANNOUNCER_ERTYES "announcer_ertyes"
-#define ANNOUNCER_MUTANTS "announcer_mutants"
diff --git a/code/modules/admin/verbs/commandreport.dm b/code/modules/admin/verbs/commandreport.dm
new file mode 100644
index 00000000000..3a164f2b75d
--- /dev/null
+++ b/code/modules/admin/verbs/commandreport.dm
@@ -0,0 +1,146 @@
+/// The default command report announcement sound.
+#define DEFAULT_ANNOUNCEMENT_SOUND "default_announcement"
+
+/// Preset central command names to chose from for centcom reports.
+#define CENTCOM_PRESET "Central Command"
+#define SYNDICATE_PRESET "The Syndicate"
+#define WIZARD_PRESET "The Wizard Federation"
+#define CUSTOM_PRESET "Custom Command Name"
+
+/// Verb to change the global command name.
+/client/proc/cmd_change_command_name()
+ set category = "Admin.Events"
+ set name = "Change Command Name"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/input = input(usr, "Please input a new name for Central Command.", "What?", "") as text|null
+ if(!input)
+ return
+ change_command_name(input)
+ message_admins("[key_name_admin(src)] has changed Central Command's name to [input]")
+ log_admin("[key_name(src)] has changed the Central Command name to: [input]")
+
+/// Verb to open the create command report window and send command reports.
+/client/proc/cmd_admin_create_centcom_report()
+ set category = "Admin.Events"
+ set name = "Create Command Report"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Create Command Report") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ var/datum/command_report_menu/tgui = new(usr)
+ tgui.ui_interact(usr)
+
+/// Datum for holding the TGUI window for command reports.
+/datum/command_report_menu
+ /// The mob using the UI.
+ var/mob/ui_user
+ /// The name of central command that will accompany our report
+ var/command_name = CENTCOM_PRESET
+ /// Whether we are using a custom name instead of a preset.
+ var/custom_name
+ /// The actual contents of the report we're going to send.
+ var/command_report_content
+ /// Whether the report's contents are announced.
+ var/announce_contents = TRUE
+ /// The sound that's going to accompany our message.
+ var/played_sound = DEFAULT_ANNOUNCEMENT_SOUND
+ /// A static list of preset names that can be chosen.
+ var/static/list/preset_names = list(CENTCOM_PRESET, SYNDICATE_PRESET, WIZARD_PRESET, CUSTOM_PRESET)
+
+/datum/command_report_menu/New(mob/user)
+ ui_user = user
+
+/datum/command_report_menu/ui_state(mob/user)
+ return GLOB.admin_state
+
+/datum/command_report_menu/ui_close()
+ qdel(src)
+
+/datum/command_report_menu/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "CommandReport")
+ ui.open()
+
+/datum/command_report_menu/ui_data(mob/user)
+ var/list/data = list()
+ data["command_name"] = command_name
+ data["custom_name"] = custom_name
+ data["command_report_content"] = command_report_content
+ data["announce_contents"] = announce_contents
+ data["played_sound"] = played_sound
+
+ return data
+
+/datum/command_report_menu/ui_static_data(mob/user)
+ var/list/data = list()
+ data["command_name_presets"] = preset_names
+ data["announcer_sounds"] = list(DEFAULT_ANNOUNCEMENT_SOUND) + GLOB.announcer_keys
+
+ return data
+
+/datum/command_report_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ if(.)
+ return
+
+ switch(action)
+ if("update_command_name")
+ if(params["updated_name"] == CUSTOM_PRESET)
+ custom_name = TRUE
+ else if (params["updated_name"] in preset_names)
+ custom_name = FALSE
+
+ command_name = params["updated_name"]
+ if("update_report_contents")
+ command_report_content = params["updated_contents"]
+ if("set_report_sound")
+ played_sound = params["picked_sound"]
+ if("toggle_announce")
+ announce_contents = !announce_contents
+ if("submit_report")
+ if(!command_name)
+ to_chat(ui_user, "You can't send a report with no command name.")
+ return
+ if(!command_report_content)
+ to_chat(ui_user, "You can't send a report with no contents.")
+ return
+ send_announcement()
+
+ return TRUE
+
+/*
+ * The actual proc that sends the priority announcement and reports
+ *
+ * Uses the variables set by the user on our datum as the arguments for the report.
+ */
+/datum/command_report_menu/proc/send_announcement()
+ /// Our current command name to swap back to after sending the report.
+ var/original_command_name = command_name()
+ change_command_name(command_name)
+
+ /// The sound we're going to play on report.
+ var/report_sound = played_sound
+ if(played_sound == DEFAULT_ANNOUNCEMENT_SOUND)
+ report_sound = SSstation.announcer.get_rand_report_sound()
+
+ if(announce_contents)
+ priority_announce(command_report_content, null, report_sound, has_important_message = TRUE)
+ print_command_report(command_report_content, "[announce_contents ? "" : "Classified "][command_name] Update", !announce_contents)
+
+ change_command_name(original_command_name)
+
+ log_admin("[key_name(ui_user)] has created a command report: \"[command_report_content]\", sent from \"[command_name]\" with the sound \"[played_sound]\".")
+ message_admins("[key_name_admin(ui_user)] has created a command report, sent from \"[command_name]\" with the sound \"[played_sound]\"")
+
+
+#undef DEFAULT_ANNOUNCEMENT_SOUND
+
+#undef CENTCOM_PRESET
+#undef SYNDICATE_PRESET
+#undef WIZARD_PRESET
+#undef CUSTOM_PRESET
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 5f4008e32cd..149d9be1365 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -546,46 +546,6 @@ Traitors and the like can also be revived with the previous role mostly intact.
admin_ticket_log(M, msg)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Rejuvenate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/client/proc/cmd_admin_create_centcom_report()
- set category = "Admin.Events"
- set name = "Create Command Report"
-
- if(!check_rights(R_ADMIN))
- return
-
- var/input = input(usr, "Enter a Command Report. Ensure it makes sense IC. Command's name is currently set to [command_name()].", "What?", "") as message|null
- if(!input)
- return
-
- var/confirm = alert(src, "Do you want to announce the contents of the report to the crew?", "Announce", "Yes", "No", "Cancel")
- var/announce_command_report = TRUE
- switch(confirm)
- if("Yes")
- priority_announce(input, null, SSstation.announcer.get_rand_report_sound(), has_important_message = TRUE)
- announce_command_report = FALSE
- if("Cancel")
- return
-
- print_command_report(input, "[announce_command_report ? "Classified " : ""][command_name()] Update", announce_command_report)
-
- log_admin("[key_name(src)] has created a command report: [input]")
- message_admins("[key_name_admin(src)] has created a command report")
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Create Command Report") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/proc/cmd_change_command_name()
- set category = "Admin.Events"
- set name = "Change Command Name"
-
- if(!check_rights(R_ADMIN))
- return
-
- var/input = input(usr, "Please input a new name for Central Command.", "What?", "") as text|null
- if(!input)
- return
- change_command_name(input)
- message_admins("[key_name_admin(src)] has changed Central Command's name to [input]")
- log_admin("[key_name(src)] has changed the Central Command name to: [input]")
-
/client/proc/cmd_admin_delete(atom/A as obj|mob|turf in world)
set category = "Debug"
set name = "Delete"
diff --git a/tgstation.dme b/tgstation.dme
index 5715764c7b5..f61b9fc32d2 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -176,7 +176,6 @@
#include "code\__DEFINES\~skyrat_defines\say.dm"
#include "code\__DEFINES\~skyrat_defines\security_alerts.dm"
#include "code\__DEFINES\~skyrat_defines\signals.dm"
-#include "code\__DEFINES\~skyrat_defines\sound.dm"
#include "code\__DEFINES\~skyrat_defines\traits.dm"
#include "code\__HELPERS\_lists.dm"
#include "code\__HELPERS\_logging.dm"
@@ -1576,6 +1575,7 @@
#include "code\modules\admin\verbs\borgpanel.dm"
#include "code\modules\admin\verbs\BrokenInhands.dm"
#include "code\modules\admin\verbs\cinematic.dm"
+#include "code\modules\admin\verbs\commandreport.dm"
#include "code\modules\admin\verbs\deadsay.dm"
#include "code\modules\admin\verbs\debug.dm"
#include "code\modules\admin\verbs\diagnostics.dm"
diff --git a/tgui/packages/tgui/interfaces/CommandReport.js b/tgui/packages/tgui/interfaces/CommandReport.js
new file mode 100644
index 00000000000..f86c808b00d
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/CommandReport.js
@@ -0,0 +1,89 @@
+import { useBackend } from '../backend';
+import { Button, Dropdown, Input, Section, Stack, TextArea } from '../components';
+import { Window } from '../layouts';
+
+export const CommandReport = (props, context) => {
+ const { act, data } = useBackend(context);
+ const {
+ command_name,
+ custom_name,
+ command_name_presets = [],
+ command_report_content,
+ played_sound,
+ announcer_sounds = [],
+ announce_contents,
+ } = data;
+ return (
+
+
+
+
+
+
+
+
+ act('set_report_sound', {
+ picked_sound: value,
+ })} />
+
+
+
+
+
+
+
+
+ );
+};