diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 8462041a373a..2f5d10f94dfb 100755
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -57,6 +57,12 @@
return TRUE
return ACCESS_CAPTAIN in authorize_access
+/// Are we NOT a silicon, AND we're logged in as a head
+/obj/machinery/computer/communications/proc/authenticated_as_non_silicon_head(mob/user)
+ if(issilicon(user))
+ return FALSE
+ return ACCESS_HEADS in authorize_access
+
/// Are we a silicon, OR logged in?
/obj/machinery/computer/communications/proc/authenticated(mob/user)
if (issilicon(user))
@@ -330,6 +336,11 @@
log_game("[key_name(usr)] enabled emergency maintenance access.")
message_admins("[ADMIN_LOOKUPFLW(usr)] enabled emergency maintenance access.")
deadchat_broadcast(" enabled emergency maintenance access at [get_area_name(usr, TRUE)].", "[usr.real_name]", usr)
+ if ("printSpare")
+ if (authenticated_as_non_silicon_head(usr))
+ playsound(loc, 'sound/items/poster_being_created.ogg', 100, 1)
+ new /obj/item/card/id/captains_spare/temporary(loc)
+ priority_announce("The emergency spare ID has been printed by [authorize_name].", "Emergency Spare ID Warning System", SSstation.announcer.get_rand_report_sound())
/obj/machinery/computer/communications/ui_data(mob/user)
var/list/data = list(
@@ -361,6 +372,7 @@
data["importantActionReady"] = COOLDOWN_FINISHED(src, important_action_cooldown)
data["shuttleCalled"] = FALSE
data["shuttleLastCalled"] = FALSE
+ data["canPrintId"] = FALSE
data["alertLevel"] = get_security_level()
data["authorizeName"] = authorize_name
@@ -371,6 +383,9 @@
data["canMessageAssociates"] = TRUE
data["canRequestNuke"] = TRUE
+ if (!issilicon(user))
+ data["canPrintId"] = TRUE
+
if (can_send_messages_to_other_sectors(user))
data["canSendToSectors"] = TRUE
diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm
index cbf239e9e3bf..204741af900a 100644
--- a/code/game/objects/items/cards_ids.dm
+++ b/code/game/objects/items/cards_ids.dm
@@ -443,6 +443,28 @@ update_label("John Doe", "Clowny")
access = J.get_access()
. = ..()
+/obj/item/card/id/captains_spare/temporary
+ name = "emergency id card"
+ desc = "A temporary ID for access to secure areas in the event of an emergency"
+ resistance_flags = FLAMMABLE
+
+/obj/item/card/id/captains_spare/temporary/Initialize()
+ . = ..()
+ access -= ACCESS_CHANGE_IDS
+ access -= ACCESS_HEADS
+ addtimer(CALLBACK(src, .proc/wipe_id), 50 SECONDS)
+
+/obj/item/card/id/captains_spare/temporary/proc/wipe_id()
+ visible_message("The temporary spare begins to smolder", "The temporary spare begins to smolder", "The temporary spare begins to smolder")
+ sleep(10 SECONDS)
+ if(isliving(loc))
+ var/mob/living/M = loc
+ M.adjust_fire_stacks(1)
+ M.IgniteMob()
+ fire_act()
+ sleep(2 SECONDS)
+ burn()
+
/obj/item/card/id/centcom
name = "\improper CentCom ID"
desc = "An ID straight from Central Command."
diff --git a/tgui/packages/tgui/interfaces/CommunicationsConsole.js b/tgui/packages/tgui/interfaces/CommunicationsConsole.js
index fea57f37dcbd..df5df9c2272b 100644
--- a/tgui/packages/tgui/interfaces/CommunicationsConsole.js
+++ b/tgui/packages/tgui/interfaces/CommunicationsConsole.js
@@ -283,6 +283,7 @@ const PageMain = (props, context) => {
shuttleCalledPreviously,
shuttleCanEvacOrFailReason,
shuttleLastCalled,
+ canPrintId,
shuttleRecallable,
} = data;
@@ -387,6 +388,12 @@ const PageMain = (props, context) => {
onClick={() => act("makeVoiceAnnouncement")}
/>}
+ {!!canPrintId &&