diff --git a/baystation12.dme b/baystation12.dme
index f09b367b43..43e4f78c28 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -956,6 +956,7 @@
#include "code\modules\mob\living\carbon\monkey\monkey.dm"
#include "code\modules\mob\living\carbon\monkey\powers.dm"
#include "code\modules\mob\living\carbon\monkey\update_icons.dm"
+#include "code\modules\mob\living\silicon\alarm.dm"
#include "code\modules\mob\living\silicon\death.dm"
#include "code\modules\mob\living\silicon\login.dm"
#include "code\modules\mob\living\silicon\say.dm"
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index daea3219d6..5d206b9f94 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -215,7 +215,7 @@
/obj/machinery/camera/proc/cancelCameraAlarm()
alarm_on = 0
for(var/mob/living/silicon/S in mob_list)
- S.cancelAlarm("Camera", get_area(src), list(src), src)
+ S.cancelAlarm("Camera", get_area(src), src)
/obj/machinery/camera/proc/can_use()
if(!status)
diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm
index 588ab5005c..19f2620630 100644
--- a/code/game/machinery/camera/motion.dm
+++ b/code/game/machinery/camera/motion.dm
@@ -42,14 +42,14 @@
/obj/machinery/camera/proc/cancelAlarm()
if (detectTime == -1)
for (var/mob/living/silicon/aiPlayer in player_list)
- if (status) aiPlayer.cancelAlarm("Motion", src.loc.loc)
+ if (status) aiPlayer.cancelAlarm("Motion", get_area(src), src)
detectTime = 0
return 1
/obj/machinery/camera/proc/triggerAlarm()
if (!detectTime) return 0
for (var/mob/living/silicon/aiPlayer in player_list)
- if (status) aiPlayer.triggerAlarm("Motion", src.loc.loc, src)
+ if (status) aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src)
detectTime = -1
return 1
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index dfda7bae5c..77ec775059 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -24,7 +24,6 @@ var/list/ai_list = list()
var/list/connected_robots = list()
var/aiRestorePowerRoutine = 0
//var/list/laws = list()
- var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list())
var/viewalerts = 0
var/lawcheck[1]
var/ioncheck[1]
@@ -237,26 +236,20 @@ var/list/ai_list = list()
dat += "Close
"
for (var/cat in alarms)
dat += text("[]
\n", cat)
- var/list/L = alarms[cat]
- if (L.len)
- for (var/alarm in L)
- var/list/alm = L[alarm]
- var/area/A = alm[1]
- var/C = alm[2]
- var/list/sources = alm[3]
+ var/list/alarmlist = alarms[cat]
+ if (alarmlist.len)
+ for (var/area_name in alarmlist)
+ var/datum/alarm/alarm = alarmlist[area_name]
dat += ""
- if (C && istype(C, /list))
- var/dat2 = ""
- for (var/obj/machinery/camera/I in C)
- dat2 += text("[][]", (dat2=="") ? "" : " | ", src, I, I.c_tag)
- dat += text("-- [] ([])", A.name, (dat2!="") ? dat2 : "No Camera")
- else if (C && istype(C, /obj/machinery/camera))
- var/obj/machinery/camera/Ctmp = C
- dat += text("-- [] ([])", A.name, src, C, Ctmp.c_tag)
- else
- dat += text("-- [] (No Camera)", A.name)
- if (sources.len > 1)
- dat += text("- [] sources", sources.len)
+
+ var/cameratext = ""
+ if (alarm.cameras)
+ for (var/obj/machinery/camera/I in alarm.cameras)
+ cameratext += text("[][]", (cameratext=="") ? "" : " | ", src, I, I.c_tag)
+ dat += text("-- [] ([])", alarm.area.name, (cameratext)? cameratext : "No Camera")
+
+ if (alarm.sources.len > 1)
+ dat += text(" - [] sources", alarm.sources.len)
dat += "
\n"
else
dat += "-- All Systems Nominal
\n"
@@ -534,59 +527,28 @@ var/list/ai_list = list()
return 1
-/mob/living/silicon/ai/triggerAlarm(var/class, area/A, var/O, var/alarmsource)
+/mob/living/silicon/ai/triggerAlarm(var/class, area/A, list/cameralist, var/source)
if (stat == 2)
return 1
- var/list/L = alarms[class]
- for (var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
- var/list/sources = alarm[3]
- if (!(alarmsource in sources))
- sources += alarmsource
- return 1
- var/obj/machinery/camera/C = null
- var/list/CL = null
- if (O && istype(O, /list))
- CL = O
- if (CL.len == 1)
- C = CL[1]
- else if (O && istype(O, /obj/machinery/camera))
- C = O
- L[A.name] = list(A, (C) ? C : O, list(alarmsource))
- if (O)
- if (C && C.can_use())
- queueAlarm("--- [class] alarm detected in [A.name]! ([C.c_tag])", class)
- else if (CL && CL.len)
- var/foo = 0
- var/dat2 = ""
- for (var/obj/machinery/camera/I in CL)
- dat2 += text("[][]", (!foo) ? "" : " | ", src, I, I.c_tag) //I'm not fixing this shit...
- foo = 1
- queueAlarm(text ("--- [] alarm detected in []! ([])", class, A.name, dat2), class)
- else
- queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class)
- else
- queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class)
+
+ ..()
+
+ var/cameratext = ""
+ for (var/obj/machinery/camera/C in cameralist)
+ cameratext += "[(cameratext == "")? "" : "|"][C.c_tag]"
+
+ queueAlarm("--- [class] alarm detected in [A.name]! ([(cameratext)? cameratext : "No Camera"])", class)
+
if (viewalerts) ai_alerts()
- return 1
-/mob/living/silicon/ai/cancelAlarm(var/class, area/A as area, obj/origin)
- var/list/L = alarms[class]
- var/cleared = 0
- for (var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
- var/list/srcs = alarm[3]
- if (origin in srcs)
- srcs -= origin
- if (srcs.len == 0)
- cleared = 1
- L -= I
- if (cleared)
+/mob/living/silicon/ai/cancelAlarm(var/class, area/A as area, var/source)
+ var/has_alarm = ..()
+
+ if (!has_alarm)
queueAlarm(text("--- [] alarm in [] has been cleared.", class, A.name), class, 0)
if (viewalerts) ai_alerts()
- return !cleared
+
+ return has_alarm
/mob/living/silicon/ai/cancel_camera()
set category = "AI Commands"
diff --git a/code/modules/mob/living/silicon/alarm.dm b/code/modules/mob/living/silicon/alarm.dm
new file mode 100644
index 0000000000..ee505fae5c
--- /dev/null
+++ b/code/modules/mob/living/silicon/alarm.dm
@@ -0,0 +1,111 @@
+/datum/alarm
+ var/area/area //the area associated with the alarm. Used to identify the alarm
+ var/list/sources //list of things triggering the alarm. Used to determine when the alarm should be cleared.
+ var/list/cameras //list of cameras that can be switched to, if the player has that capability.
+
+/datum/alarm/New(area/A, list/sourcelist=list(), list/cameralist=list())
+ area = A
+ sources = sourcelist
+ cameras = cameralist
+
+/mob/living/silicon
+ var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list()) //each sublist stores alarms keyed by the area name
+ var/list/alarms_to_show = list()
+ var/list/alarms_to_clear = list()
+ var/list/alarm_types_show = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0)
+ var/list/alarm_types_clear = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0)
+
+/mob/living/silicon/proc/triggerAlarm(var/class, area/A, list/cameralist, var/source)
+ var/list/alarmlist = alarms[class]
+
+ //see if there is already an alarm of this class for this area
+ if (A.name in alarmlist)
+ var/datum/alarm/existing = alarmlist[A.name]
+ existing.sources += source
+ existing.cameras |= cameralist
+ else
+ alarmlist[A.name] = new /datum/alarm(A, list(source), cameralist)
+
+/mob/living/silicon/proc/cancelAlarm(var/class, area/A as area, var/source)
+ var/cleared = 0
+ var/list/alarmlist = alarms[class]
+
+ if (A.name in alarmlist)
+ var/datum/alarm/alarm = alarmlist[A.name]
+ alarm.sources -= source
+
+ if (!(alarm.sources.len))
+ cleared = 1
+ alarmlist -= A.name
+
+ return !cleared
+
+/mob/living/silicon/proc/queueAlarm(var/message, var/type, var/incoming = 1)
+ var/in_cooldown = (alarms_to_show.len > 0 || alarms_to_clear.len > 0)
+ if(incoming)
+ alarms_to_show += message
+ alarm_types_show[type] += 1
+ else
+ alarms_to_clear += message
+ alarm_types_clear[type] += 1
+
+ if(!in_cooldown)
+ spawn(10 * 10) // 10 seconds
+
+ if(alarms_to_show.len < 5)
+ for(var/msg in alarms_to_show)
+ src << msg
+ else if(alarms_to_show.len)
+
+ var/msg = "--- "
+
+ if(alarm_types_show["Motion"])
+ msg += "MOTION: [alarm_types_show["Motion"]] alarms detected. - "
+
+ if(alarm_types_show["Fire"])
+ msg += "FIRE: [alarm_types_show["Fire"]] alarms detected. - "
+
+ if(alarm_types_show["Atmosphere"])
+ msg += "ATMOSPHERE: [alarm_types_show["Atmosphere"]] alarms detected. - "
+
+ if(alarm_types_show["Power"])
+ msg += "POWER: [alarm_types_show["Power"]] alarms detected. - "
+
+ if(alarm_types_show["Camera"])
+ msg += "CAMERA: [alarm_types_show["Power"]] alarms detected. - "
+
+ msg += "\[Show Alerts\]"
+ src << msg
+
+ if(alarms_to_clear.len < 3)
+ for(var/msg in alarms_to_clear)
+ src << msg
+
+ else if(alarms_to_clear.len)
+ var/msg = "--- "
+
+ if(alarm_types_clear["Motion"])
+ msg += "MOTION: [alarm_types_clear["Motion"]] alarms cleared. - "
+
+ if(alarm_types_clear["Fire"])
+ msg += "FIRE: [alarm_types_clear["Fire"]] alarms cleared. - "
+
+ if(alarm_types_clear["Atmosphere"])
+ msg += "ATMOSPHERE: [alarm_types_clear["Atmosphere"]] alarms cleared. - "
+
+ if(alarm_types_clear["Power"])
+ msg += "POWER: [alarm_types_clear["Power"]] alarms cleared. - "
+
+ if(alarm_types_show["Camera"])
+ msg += "CAMERA: [alarm_types_show["Power"]] alarms detected. - "
+
+ msg += "\[Show Alerts\]"
+ src << msg
+
+
+ alarms_to_show = list()
+ alarms_to_clear = list()
+ for(var/i = 1; i < alarm_types_show.len; i++)
+ alarm_types_show[i] = 0
+ for(var/i = 1; i < alarm_types_clear.len; i++)
+ alarm_types_clear[i] = 0
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 6b3bea036b..484fd521c6 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -46,7 +46,6 @@
var/list/req_access = list(access_robotics)
var/ident = 0
//var/list/laws = list()
- var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list())
var/viewalerts = 0
var/modtype = "Default"
var/lower_mod = 0
@@ -328,16 +327,14 @@
dat += "Close
"
for (var/cat in alarms)
dat += text("[cat]
\n")
- var/list/L = alarms[cat]
- if (L.len)
- for (var/alarm in L)
- var/list/alm = L[alarm]
- var/area/A = alm[1]
- var/list/sources = alm[3]
+ var/list/alarmlist = alarms[cat]
+ if (alarmlist.len)
+ for (var/area_name in alarmlist)
+ var/datum/alarm/alarm = alarmlist[area_name]
dat += ""
- dat += text("-- [A.name]")
- if (sources.len > 1)
- dat += text("- [sources.len] sources")
+ dat += text("-- [area_name]")
+ if (alarm.sources.len > 1)
+ dat += text("- [alarm.sources.len] sources")
dat += "
\n"
else
dat += "-- All Systems Nominal
\n"
@@ -529,47 +526,22 @@
return
-/mob/living/silicon/robot/triggerAlarm(var/class, area/A, var/O, var/alarmsource)
+/mob/living/silicon/robot/triggerAlarm(var/class, area/A, list/cameralist, var/source)
if (stat == 2)
return 1
- var/list/L = alarms[class]
- for (var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
- var/list/sources = alarm[3]
- if (!(alarmsource in sources))
- sources += alarmsource
- return 1
- var/obj/machinery/camera/C = null
- var/list/CL = null
- if (O && istype(O, /list))
- CL = O
- if (CL.len == 1)
- C = CL[1]
- else if (O && istype(O, /obj/machinery/camera))
- C = O
- L[A.name] = list(A, (C) ? C : O, list(alarmsource))
+
+ ..()
+
queueAlarm(text("--- [class] alarm detected in [A.name]!"), class)
-// if (viewalerts) robot_alerts()
- return 1
/mob/living/silicon/robot/cancelAlarm(var/class, area/A as area, obj/origin)
- var/list/L = alarms[class]
- var/cleared = 0
- for (var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
- var/list/srcs = alarm[3]
- if (origin in srcs)
- srcs -= origin
- if (srcs.len == 0)
- cleared = 1
- L -= I
- if (cleared)
+ var/has_alarm = ..()
+
+ if (!has_alarm)
queueAlarm(text("--- [class] alarm in [A.name] has been cleared."), class, 0)
// if (viewalerts) robot_alerts()
- return !cleared
+ return has_alarm
/mob/living/silicon/robot/attackby(obj/item/weapon/W as obj, mob/user as mob)
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 944063d9e0..9a1fdd85dd 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -4,92 +4,12 @@
voice_name = "synthesized voice"
var/syndicate = 0
var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS
- var/list/alarms_to_show = list()
- var/list/alarms_to_clear = list()
immune_to_ssd = 1
var/list/hud_list[9]
- var/list/alarm_types_show = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0)
- var/list/alarm_types_clear = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0)
-
-/mob/living/silicon/proc/cancelAlarm()
- return
-
-/mob/living/silicon/proc/triggerAlarm()
- return
/mob/living/silicon/proc/show_laws()
return
-/mob/living/silicon/proc/queueAlarm(var/message, var/type, var/incoming = 1)
- var/in_cooldown = (alarms_to_show.len > 0 || alarms_to_clear.len > 0)
- if(incoming)
- alarms_to_show += message
- alarm_types_show[type] += 1
- else
- alarms_to_clear += message
- alarm_types_clear[type] += 1
-
- if(!in_cooldown)
- spawn(10 * 10) // 10 seconds
-
- if(alarms_to_show.len < 5)
- for(var/msg in alarms_to_show)
- src << msg
- else if(alarms_to_show.len)
-
- var/msg = "--- "
-
- if(alarm_types_show["Motion"])
- msg += "MOTION: [alarm_types_show["Motion"]] alarms detected. - "
-
- if(alarm_types_show["Fire"])
- msg += "FIRE: [alarm_types_show["Fire"]] alarms detected. - "
-
- if(alarm_types_show["Atmosphere"])
- msg += "ATMOSPHERE: [alarm_types_show["Atmosphere"]] alarms detected. - "
-
- if(alarm_types_show["Power"])
- msg += "POWER: [alarm_types_show["Power"]] alarms detected. - "
-
- if(alarm_types_show["Camera"])
- msg += "CAMERA: [alarm_types_show["Power"]] alarms detected. - "
-
- msg += "\[Show Alerts\]"
- src << msg
-
- if(alarms_to_clear.len < 3)
- for(var/msg in alarms_to_clear)
- src << msg
-
- else if(alarms_to_clear.len)
- var/msg = "--- "
-
- if(alarm_types_clear["Motion"])
- msg += "MOTION: [alarm_types_clear["Motion"]] alarms cleared. - "
-
- if(alarm_types_clear["Fire"])
- msg += "FIRE: [alarm_types_clear["Fire"]] alarms cleared. - "
-
- if(alarm_types_clear["Atmosphere"])
- msg += "ATMOSPHERE: [alarm_types_clear["Atmosphere"]] alarms cleared. - "
-
- if(alarm_types_clear["Power"])
- msg += "POWER: [alarm_types_clear["Power"]] alarms cleared. - "
-
- if(alarm_types_show["Camera"])
- msg += "CAMERA: [alarm_types_show["Power"]] alarms detected. - "
-
- msg += "\[Show Alerts\]"
- src << msg
-
-
- alarms_to_show = list()
- alarms_to_clear = list()
- for(var/i = 1; i < alarm_types_show.len; i++)
- alarm_types_show[i] = 0
- for(var/i = 1; i < alarm_types_clear.len; i++)
- alarm_types_clear[i] = 0
-
/mob/living/silicon/drop_item()
return