diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm
index 62b00dab0f..8306b3a87e 100644
--- a/code/game/machinery/computer/atmos_alert.dm
+++ b/code/game/machinery/computer/atmos_alert.dm
@@ -13,6 +13,10 @@ var/global/list/minor_air_alarms = list()
/obj/machinery/computer/atmos_alert/New()
..()
atmosphere_alarm.register(src, /obj/machinery/computer/station_alert/update_icon)
+
+/obj/machinery/computer/atmos_alert/Del()
+ atmosphere_alarm.unregister(src)
+ ..()
/obj/machinery/computer/atmos_alert/attack_hand(mob/user)
ui_interact(user)
diff --git a/code/modules/alarm/alarm_handler.dm b/code/modules/alarm/alarm_handler.dm
index ef9bfa8bd6..73bd2348aa 100644
--- a/code/modules/alarm/alarm_handler.dm
+++ b/code/modules/alarm/alarm_handler.dm
@@ -97,56 +97,3 @@
/datum/alarm_handler/proc/notify_listeners(var/alarm, var/was_raised)
for(var/listener in listeners)
call(listener, listeners[listener])(src, alarm, was_raised)
-
-/********
-* DEBUG *
-********/
-/obj/item/device/alarm_debug
- name = "An alarm debug tool - Self"
- desc = "Alarm Up. Alarm Reset."
- icon = 'icons/obj/radio.dmi'
- icon_state = "beacon"
- item_state = "signaler"
- var/obj/nano_module/alarm_monitor/ai/alarm_monitor
-
-/obj/item/device/alarm_debug/New()
- ..()
- alarm_monitor = new(src)
-
-/obj/item/device/alarm_debug/loc
- name = "An alarm debug tool - Loc"
-
-/obj/item/device/alarm_debug/verb/alarm()
- set name = "Alarm"
- set category = "Debug"
- usr << "Raising alarm"
- fire_alarm.triggerAlarm(src, src)
-
-/obj/item/device/alarm_debug/verb/reset()
- set name = "Reset"
- set category = "Debug"
- usr << "Clearing alarm"
- fire_alarm.clearAlarm(src, src)
-
-/obj/item/device/alarm_debug/loc/alarm()
- set name = "Alarm"
- set category = "Debug"
- usr << "Raising alarm"
- fire_alarm.triggerAlarm(src.loc, src)
-
-/obj/item/device/alarm_debug/loc/reset()
- set name = "Reset"
- set category = "Debug"
- usr << "Clearing alarm"
- fire_alarm.clearAlarm(src.loc, src)
-
-/obj/item/device/alarm_debug/verb/nano()
- set name = "Nano"
- set category = "Debug"
- alarm_monitor.ui_interact(usr)
-
-/obj/item/device/alarm_debug/attack_self(var/mob/user)
- alarm_monitor.ui_interact(user)
-
-#undef ALARM_RAISED
-#undef ALARM_CLEARED
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index a1b9f20605..602e427f95 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -171,6 +171,7 @@
sleep(50)
theAPC = null
+ process_queued_alarms()
regular_hud_updates()
switch(src.sensor_mode)
if (SEC_HUD)
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index 8295687de9..c5d74c54dd 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -18,6 +18,7 @@
use_power()
process_killswitch()
process_locks()
+ process_queued_alarms()
update_canmove()
/mob/living/silicon/robot/proc/clamp_values()
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index a4ee540c2b..fc647dcbeb 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -27,6 +27,9 @@
var/sensor_mode = 0 //Determines the current HUD.
+ var/next_alarm_notice
+ var/list/datum/alarm/queued_alarms = new()
+
#define SEC_HUD 1 //Security HUD mode
#define MED_HUD 2 //Medical HUD mode
@@ -35,6 +38,11 @@
add_language("Galactic Common")
init_subsystems()
+/mob/living/silicon/Del()
+ for(var/datum/alarm_handler/AH in alarm_manager.all_handlers)
+ AH.unregister(src)
+ ..()
+
/mob/living/silicon/proc/SetName(pickedName as text)
real_name = pickedName
name = real_name
@@ -291,3 +299,59 @@
/mob/living/silicon/proc/init_subsystems()
alarm_monitor = new/obj/nano_module/alarm_monitor/borg(src)
+ for(var/datum/alarm_handler/AH in alarm_manager.all_handlers)
+ AH.register(src, /mob/living/silicon/proc/receive_alarm)
+ queued_alarms[AH] = list() // Makes sure alarms remain listed in consistent order
+
+/mob/living/silicon/proc/receive_alarm(var/datum/alarm_handler/alarm_handler, var/datum/alarm/alarm, was_raised)
+ if(!next_alarm_notice)
+ next_alarm_notice = world.time + SecondsToTicks(10)
+
+ var/list/alarms = queued_alarms[alarm_handler]
+ if(was_raised)
+ // Raised alarms are always set
+ alarms[alarm] = 1
+ else
+ // Alarms that were raised but then cleared before the next notice are instead removed
+ if(alarm in alarms)
+ alarms -= alarm
+ // And alarms that have only been cleared thus far are set as such
+ else
+ alarms[alarm] = -1
+
+/mob/living/silicon/proc/process_queued_alarms()
+ if(next_alarm_notice && (world.time > next_alarm_notice))
+ next_alarm_notice = 0
+
+ for(var/datum/alarm_handler/AH in queued_alarms)
+ var/list/alarms = queued_alarms[AH]
+ var/reported = 0
+ for(var/datum/alarm/A in alarms)
+ if(alarms[A] == 1)
+ if(!reported)
+ reported = 1
+ src << "--- [AH.category] Detected ---"
+ raised_alarm(A)
+
+ for(var/datum/alarm_handler/AH in queued_alarms)
+ var/list/alarms = queued_alarms[AH]
+ var/reported = 0
+ for(var/datum/alarm/A in alarms)
+ if(alarms[A] == -1)
+ if(!reported)
+ reported = 1
+ src << "--- [AH.category] Cleared ---"
+ src << "\The [A.alarm_name()]."
+
+ for(var/datum/alarm_handler/AH in queued_alarms)
+ var/list/alarms = queued_alarms[AH]
+ alarms.Cut()
+
+/mob/living/silicon/proc/raised_alarm(var/datum/alarm/A)
+ src << "[A.alarm_name()]!"
+
+/mob/living/silicon/ai/raised_alarm(var/datum/alarm/A)
+ var/cameratext = ""
+ for(var/obj/machinery/camera/C in A.cameras())
+ cameratext += "[(cameratext == "")? "" : "|"][C.c_tag]"
+ src << "[A.alarm_name()]! ([(cameratext)? cameratext : "No Camera"])"