diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 4368757352..644eaf1d65 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -13,6 +13,7 @@ GLOBAL_LIST_EMPTY(player_list) //all mobs **with clients attached**. Excludes GLOBAL_LIST_EMPTY(mob_list) //all mobs, including clientless GLOBAL_LIST_EMPTY(mob_directory) //mob_id -> mob GLOBAL_LIST_EMPTY(living_mob_list) //all alive mobs, including clientless. Excludes /mob/dead/new_player +GLOBAL_LIST_EMPTY(drones_list) GLOBAL_LIST_EMPTY(dead_mob_list) //all dead mobs, including clientless. Excludes /mob/dead/new_player GLOBAL_LIST_EMPTY(joined_player_list) //all clients that have joined the game at round-start or as a latejoin. GLOBAL_LIST_EMPTY(silicon_mobs) //all silicon mobs diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 5defb16551..12173b21b7 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -36,4 +36,5 @@ GLOBAL_LIST_EMPTY(wire_name_directory) GLOBAL_LIST_EMPTY(ai_status_displays) -GLOBAL_LIST_EMPTY(mob_spawners) // All mob_spawn objects \ No newline at end of file +GLOBAL_LIST_EMPTY(mob_spawners) // All mob_spawn objects +GLOBAL_LIST_EMPTY(alert_consoles) // Station alert consoles, /obj/machinery/computer/station_alert \ No newline at end of file diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 75a6581aa9..ff33f8e32a 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -58,6 +58,8 @@ flags_1 = CAN_BE_DIRTY_1 var/list/firedoors + var/list/cameras + var/list/firealarms var/firedoors_last_closed_on = 0 /*Adding a wizard area teleport list because motherfucking lag -- Urist*/ @@ -102,7 +104,7 @@ GLOBAL_LIST_EMPTY(teleportlocs) uid = ++global_uid related = list(src) map_name = name // Save the initial (the name set in the map) name of the area. - + if(requires_power) luminosity = 0 else @@ -154,27 +156,28 @@ GLOBAL_LIST_EMPTY(teleportlocs) if (state != poweralm) poweralm = state if(istype(source)) //Only report power alarms on the z-level where the source is located. - var/list/cameras = list() - for (var/obj/machinery/camera/C in src) - cameras += C - for (var/mob/living/silicon/aiPlayer in GLOB.player_list) + for (var/item in GLOB.silicon_mobs) + var/mob/living/silicon/aiPlayer = item if (state == 1) aiPlayer.cancelAlarm("Power", src, source) else aiPlayer.triggerAlarm("Power", src, cameras, source) - for(var/obj/machinery/computer/station_alert/a in GLOB.machines) + for (var/item in GLOB.alert_consoles) + var/obj/machinery/computer/station_alert/a = item if(state == 1) a.cancelAlarm("Power", src, source) else a.triggerAlarm("Power", src, cameras, source) - for(var/mob/living/simple_animal/drone/D in GLOB.mob_list) + for (var/item in GLOB.drones_list) + var/mob/living/simple_animal/drone/D = item if(state == 1) D.cancelAlarm("Power", src, source) else D.triggerAlarm("Power", src, cameras, source) - for(var/datum/computer_file/program/alarm_monitor/p in GLOB.alarmdisplay) + for(var/item in GLOB.alarmdisplay) + var/datum/computer_file/program/alarm_monitor/p = item if(state == 1) p.cancelAlarm("Power", src, source) else @@ -185,26 +188,35 @@ GLOBAL_LIST_EMPTY(teleportlocs) if (danger_level==2) var/list/cameras = list() for(var/area/RA in related) - for(var/obj/machinery/camera/C in RA) + for (var/item in RA.cameras) + var/obj/machinery/camera/C = item cameras += C - for(var/mob/living/silicon/aiPlayer in GLOB.player_list) + for (var/item in GLOB.silicon_mobs) + var/mob/living/silicon/aiPlayer = item aiPlayer.triggerAlarm("Atmosphere", src, cameras, source) - for(var/obj/machinery/computer/station_alert/a in GLOB.machines) + for (var/item in GLOB.alert_consoles) + var/obj/machinery/computer/station_alert/a = item a.triggerAlarm("Atmosphere", src, cameras, source) - for(var/mob/living/simple_animal/drone/D in GLOB.mob_list) + for (var/item in GLOB.drones_list) + var/mob/living/simple_animal/drone/D = item D.triggerAlarm("Atmosphere", src, cameras, source) - for(var/datum/computer_file/program/alarm_monitor/p in GLOB.alarmdisplay) + for(var/item in GLOB.alarmdisplay) + var/datum/computer_file/program/alarm_monitor/p = item p.triggerAlarm("Atmosphere", src, cameras, source) else if (src.atmosalm == 2) - for(var/mob/living/silicon/aiPlayer in GLOB.player_list) + for (var/item in GLOB.silicon_mobs) + var/mob/living/silicon/aiPlayer = item aiPlayer.cancelAlarm("Atmosphere", src, source) - for(var/obj/machinery/computer/station_alert/a in GLOB.machines) + for (var/item in GLOB.alert_consoles) + var/obj/machinery/computer/station_alert/a = item a.cancelAlarm("Atmosphere", src, source) - for(var/mob/living/simple_animal/drone/D in GLOB.mob_list) + for (var/item in GLOB.drones_list) + var/mob/living/simple_animal/drone/D = item D.cancelAlarm("Atmosphere", src, source) - for(var/datum/computer_file/program/alarm_monitor/p in GLOB.alarmdisplay) + for(var/item in GLOB.alarmdisplay) + var/datum/computer_file/program/alarm_monitor/p = item p.cancelAlarm("Atmosphere", src, source) src.atmosalm = danger_level @@ -239,18 +251,24 @@ GLOBAL_LIST_EMPTY(teleportlocs) if (!( RA.fire )) RA.set_fire_alarm_effect() RA.ModifyFiredoors(FALSE) - for(var/obj/machinery/firealarm/F in RA) + for(var/item in RA.firealarms) + var/obj/machinery/firealarm/F = item F.update_icon() - for (var/obj/machinery/camera/C in RA) + for (var/item in RA.cameras) + var/obj/machinery/camera/C = item cameras += C - for (var/obj/machinery/computer/station_alert/a in GLOB.machines) + for (var/item in GLOB.alert_consoles) + var/obj/machinery/computer/station_alert/a = item a.triggerAlarm("Fire", src, cameras, source) - for (var/mob/living/silicon/aiPlayer in GLOB.player_list) + for (var/item in GLOB.silicon_mobs) + var/mob/living/silicon/aiPlayer = item aiPlayer.triggerAlarm("Fire", src, cameras, source) - for (var/mob/living/simple_animal/drone/D in GLOB.mob_list) + for (var/item in GLOB.drones_list) + var/mob/living/simple_animal/drone/D = item D.triggerAlarm("Fire", src, cameras, source) - for(var/datum/computer_file/program/alarm_monitor/p in GLOB.alarmdisplay) + for(var/item in GLOB.alarmdisplay) + var/datum/computer_file/program/alarm_monitor/p = item p.triggerAlarm("Fire", src, cameras, source) START_PROCESSING(SSobj, src) @@ -262,16 +280,21 @@ GLOBAL_LIST_EMPTY(teleportlocs) RA.mouse_opacity = MOUSE_OPACITY_TRANSPARENT RA.updateicon() RA.ModifyFiredoors(TRUE) - for(var/obj/machinery/firealarm/F in RA) + for(var/item in RA.firealarms) + var/obj/machinery/firealarm/F = item F.update_icon() - for (var/mob/living/silicon/aiPlayer in GLOB.player_list) + for (var/item in GLOB.silicon_mobs) + var/mob/living/silicon/aiPlayer = item aiPlayer.cancelAlarm("Fire", src, source) - for (var/obj/machinery/computer/station_alert/a in GLOB.machines) + for (var/item in GLOB.alert_consoles) + var/obj/machinery/computer/station_alert/a = item a.cancelAlarm("Fire", src, source) - for (var/mob/living/simple_animal/drone/D in GLOB.mob_list) + for (var/item in GLOB.drones_list) + var/mob/living/simple_animal/drone/D = item D.cancelAlarm("Fire", src, source) - for(var/datum/computer_file/program/alarm_monitor/p in GLOB.alarmdisplay) + for(var/item in GLOB.alarmdisplay) + var/datum/computer_file/program/alarm_monitor/p = item p.cancelAlarm("Fire", src, source) STOP_PROCESSING(SSobj, src) @@ -299,7 +322,8 @@ GLOBAL_LIST_EMPTY(teleportlocs) //Lockdown airlocks for(var/obj/machinery/door/DOOR in RA) close_and_lock_door(DOOR) - for (var/obj/machinery/camera/C in RA) + for (var/item in RA.cameras) + var/obj/machinery/camera/C = item cameras += C for (var/mob/living/silicon/SILICON in GLOB.player_list) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 17a65f7033..93b2904606 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -26,6 +26,7 @@ var/invuln = null var/obj/item/device/camera_bug/bug = null var/obj/structure/camera_assembly/assembly = null + var/area/myarea = null //OTHER @@ -47,6 +48,9 @@ assembly.state = 4 GLOB.cameranet.cameras += src GLOB.cameranet.addCamera(src) + if (isturf(loc)) + myarea = get_area(src) + LAZYADD(myarea.cameras, src) proximity_monitor = new(src, 1) if(mapload && (z in GLOB.station_z_levels) && prob(3) && !start_active) @@ -54,6 +58,8 @@ /obj/machinery/camera/Destroy() toggle_cam(null, 0) //kick anyone viewing out + if(isarea(myarea)) + LAZYREMOVE(myarea.cameras, src) if(assembly) qdel(assembly) assembly = null @@ -64,7 +70,6 @@ bug = null GLOB.cameranet.removeCamera(src) //Will handle removal from the camera network and the chunks, so we don't need to worry about that GLOB.cameranet.cameras -= src - GLOB.cameranet.removeCamera(src) return ..() /obj/machinery/camera/emp_act(severity) @@ -119,6 +124,11 @@ return user.electrocute_act(10, src) +/obj/machinery/camera/singularity_pull(S, current_size) + if (status && current_size >= STAGE_FIVE) // If the singulo is strong enough to pull anchored objects and the camera is still active, turn off the camera as it gets ripped off the wall. + toggle_cam(null, 0) + ..() + /obj/machinery/camera/attackby(obj/item/W, mob/living/user, params) var/msg = "You attach [W] into the assembly's inner circuits." var/msg2 = "[src] already has that upgrade!" @@ -268,9 +278,16 @@ status = !status if(can_use()) GLOB.cameranet.addCamera(src) + if (isturf(loc)) + myarea = get_area(src) + LAZYADD(myarea.cameras, src) + else + myarea = null else set_light(0) GLOB.cameranet.removeCamera(src) + if (isarea(myarea)) + LAZYREMOVE(myarea.cameras, src) GLOB.cameranet.updateChunk(x, y, z) var/change_msg = "deactivates" if(status) @@ -298,12 +315,12 @@ /obj/machinery/camera/proc/triggerCameraAlarm() alarm_on = TRUE - for(var/mob/living/silicon/S in GLOB.mob_list) + for(var/mob/living/silicon/S in GLOB.silicon_mobs) S.triggerAlarm("Camera", get_area(src), list(src), src) /obj/machinery/camera/proc/cancelCameraAlarm() alarm_on = FALSE - for(var/mob/living/silicon/S in GLOB.mob_list) + for(var/mob/living/silicon/S in GLOB.silicon_mobs) S.cancelAlarm("Camera", get_area(src), src) /obj/machinery/camera/proc/can_use() diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index 019d52fe86..1d21210116 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD /obj/machinery/computer/station_alert name = "station alert console" desc = "Used to access the station's automated alert system." @@ -83,3 +84,92 @@ active_alarms = TRUE if(active_alarms) add_overlay("alert:2") +======= +/obj/machinery/computer/station_alert + name = "station alert console" + desc = "Used to access the station's automated alert system." + icon_screen = "alert:0" + icon_keyboard = "atmos_key" + circuit = /obj/item/circuitboard/computer/stationalert + var/alarms = list("Fire" = list(), "Atmosphere" = list(), "Power" = list()) + + light_color = LIGHT_COLOR_CYAN + +/obj/machinery/computer/station_alert/Initialize() + . = ..() + GLOB.alert_consoles += src + +/obj/machinery/computer/station_alert/Destroy() + GLOB.alert_consoles -= src + return ..() + +/obj/machinery/computer/station_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ + datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "station_alert", name, 300, 500, master_ui, state) + ui.open() + +/obj/machinery/computer/station_alert/ui_data(mob/user) + . = list() + + .["alarms"] = list() + for(var/class in alarms) + .["alarms"][class] = list() + for(var/area in alarms[class]) + .["alarms"][class] += area + +/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source) + if(source.z != z) + return + if(stat & (BROKEN)) + return + + 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 (!(source in sources)) + sources += source + return 1 + var/obj/machinery/camera/C = null + var/list/CL = null + if(O && islist(O)) + 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(source)) + return 1 + + +/obj/machinery/computer/station_alert/proc/cancelAlarm(class, area/A, obj/origin) + if(stat & (BROKEN)) + return + 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 + return !cleared + +/obj/machinery/computer/station_alert/update_icon() + ..() + if(stat & (NOPOWER|BROKEN)) + return + var/active_alarms = FALSE + for(var/cat in alarms) + var/list/L = alarms[cat] + if(L.len) + active_alarms = TRUE + if(active_alarms) + add_overlay("alert:2") +>>>>>>> 6a32f31... Greatly increases the performance of station-ending plasma fires (#32620) diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 83d51bae0c..39df6f409e 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -1,3 +1,5 @@ +#define FIREALARM_COOLDOWN 67 // Chosen fairly arbitrarily, it is the length of the audio in FireAlarm.ogg. The actual track length is 7 seconds 8ms but but the audio stops at 6s 700ms + /obj/item/electronics/firealarm name = "fire alarm electronics" desc = "A fire alarm circuit. Can handle heat levels up to 40 degrees celsius." @@ -25,7 +27,8 @@ var/detecting = 1 var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone resistance_flags = FIRE_PROOF - + var/last_alarm = 0 + var/area/myarea = null /obj/machinery/firealarm/New(loc, dir, building) ..() @@ -37,6 +40,12 @@ pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 update_icon() + myarea = get_area(src) + LAZYADD(myarea.firealarms, src) + +/obj/machinery/firealarm/Destroy() + LAZYREMOVE(myarea.firealarms, src) + return ..() /obj/machinery/firealarm/power_change() ..() @@ -87,29 +96,24 @@ playsound(src, "sparks", 50, 1) /obj/machinery/firealarm/temperature_expose(datum/gas_mixture/air, temperature, volume) - if(!emagged && detecting && !stat && (temperature > T0C + 200 || temperature < BODYTEMP_COLD_DAMAGE_LIMIT)) + if((temperature > T0C + 200 || temperature < BODYTEMP_COLD_DAMAGE_LIMIT) && (last_alarm+FIREALARM_COOLDOWN < world.time) && !emagged && detecting && !stat) alarm() ..() /obj/machinery/firealarm/proc/alarm() - if(!is_operational()) + if(!is_operational() && (last_alarm+FIREALARM_COOLDOWN < world.time)) return + last_alarm = world.time var/area/A = get_area(src) A.firealert(src) playsound(src.loc, 'goon/sound/machinery/FireAlarm.ogg', 75) -/obj/machinery/firealarm/proc/alarm_in(time) - addtimer(CALLBACK(src, .proc/alarm), time) - /obj/machinery/firealarm/proc/reset() if(!is_operational()) return var/area/A = get_area(src) A.firereset(src) -/obj/machinery/firealarm/proc/reset_in(time) - addtimer(CALLBACK(src, .proc/reset), time) - /obj/machinery/firealarm/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) @@ -248,8 +252,14 @@ if(prob(33)) alarm() +/obj/machinery/firealarm/singularity_pull(S, current_size) + if (current_size >= STAGE_FIVE) // If the singulo is strong enough to pull anchored objects, the fire alarm experiences integrity failure + deconstruct() + ..() + /obj/machinery/firealarm/obj_break(damage_flag) if(!(stat & BROKEN) && !(flags_1 & NODECONSTRUCT_1) && buildstage != 0) //can't break the electronics if there isn't any inside. + LAZYREMOVE(myarea.firealarms, src) stat |= BROKEN update_icon() diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm index a8eb8ad12b..f7ee4ac29a 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm @@ -80,7 +80,7 @@ /mob/living/simple_animal/drone/Initialize() . = ..() - + GLOB.drones_list += src access_card = new /obj/item/card/id(src) var/datum/job/captain/C = new /datum/job/captain access_card.access = C.get_access() @@ -124,6 +124,7 @@ holder.icon_state = "hudstat" /mob/living/simple_animal/drone/Destroy() + GLOB.drones_list -= src qdel(access_card) //Otherwise it ends up on the floor! return ..()