Files
tontyandGitHub 14d2514aa9 [MDB IGNORE] Refactors away /area/station/ai_monitored and its subtypes (with bonus neat repathing) (#93704)
## About The Pull Request

/area/station/ai_monitored's behaviour was isolated into a component,
`/datum/component/monitored_area`, which itself uses
`/datum/motion_group`s to query cameras. Functionally, it (should) work
identically to the old implementation. I'm sure that behaviour could
have been further cleaned up, camera code is quite dreadful, but it's
better to focus on isolating the behaviour first. Baby steps.

Areas that want to opt into monitoring can set `var/motion_monitored` to
TRUE (this approach was taken to make subtyping easier).

The following non-AI areas were changed:
- /area/station/ai_monitored/security/armory ->
/area/station/security/armory
- /area/station/ai_monitored/command/nuke_storage ->
/area/station/command/vault
- /area/station/ai_monitored/command/storage/eva ->
/area/station/command/eva

All other `/area/station/ai_monitored` subtypes were repathed into
`/area/station/ai` and cleaned up in a way that I thought made logical
sense. It is **much** more readable now. For example:

- /area/station/ai_monitored/turret_protected/aisat ->
/area/station/ai/satellite
- /area/station/ai_monitored/command/storage/satellite ->
/area/station/ai/satellite/maintenance/storage
- /area/station/ai_monitored/turret_protected/ai ->
/area/station/ai/satellite/chamber
2025-11-03 11:27:14 -06:00

98 lines
3.2 KiB
Plaintext

/obj/machinery/camera/process()
// motion camera event loop
if(!isMotion())
return PROCESS_KILL // FIXME: This is never undone if the camera gets upgraded to a motion camera
if(machine_stat & EMPED)
return
if (detectTime > 0)
var/elapsed = world.time - detectTime
if (elapsed > alarm_delay)
triggerAlarm()
else if (detectTime == -1)
for (var/datum/weakref/targetref in getTargetList())
var/mob/target = targetref.resolve()
if(QDELETED(target) || target.stat == DEAD || (!area_motion && !in_range(src, target)))
//If not part of a monitored area and the camera is not in range or the target is dead
lost_target(target)
/obj/machinery/camera/proc/getTargetList()
if(area_motion)
return area_motion.motion_targets
return localMotionTargets
/obj/machinery/camera/proc/new_target(mob/target)
if(isAI(target))
return FALSE
if (detectTime == 0)
detectTime = world.time // start the clock
var/list/targets = getTargetList()
targets |= WEAKREF(target)
return TRUE
/obj/machinery/camera/proc/lost_target(mob/target)
var/list/targets = getTargetList()
targets -= WEAKREF(target)
if (!length(targets))
cancelAlarm()
/obj/machinery/camera/Destroy()
localMotionTargets = null
cancelAlarm()
return ..()
/obj/machinery/camera/proc/cancelAlarm()
if (detectTime == -1 && camera_enabled)
alarm_manager.clear_alarm(ALARM_MOTION)
detectTime = 0
return TRUE
/obj/machinery/camera/proc/triggerAlarm()
if (!detectTime)
return FALSE
if(camera_enabled)
if(alarm_manager.send_alarm(ALARM_MOTION, src, src))
visible_message(span_warning("A red light flashes on [src]!"))
detectTime = -1
return TRUE
/obj/machinery/camera/HasProximity(atom/movable/AM as mob|obj)
// Motion cameras outside of an "ai monitored" area will use this to detect stuff.
if (!area_motion)
if(isliving(AM))
new_target(AM)
/obj/machinery/camera/motion/thunderdome
name = "entertainment camera"
network = list(CAMERANET_NETWORK_THUNDERDOME)
c_tag = "Arena"
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF | FREEZE_PROOF
/obj/machinery/camera/motion/thunderdome/Initialize(mapload)
. = ..()
proximity_monitor.set_range(7)
/obj/machinery/camera/motion/thunderdome/HasProximity(atom/movable/AM as mob|obj)
if (!isliving(AM) || get_area(AM) != get_area(src))
return
localMotionTargets |= WEAKREF(AM)
if (!detectTime)
for(var/obj/machinery/computer/security/telescreen/entertainment/TV as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/computer/security/telescreen/entertainment))
TV.notify(TRUE)
detectTime = world.time + 30 SECONDS
/obj/machinery/camera/motion/thunderdome/process()
if (!detectTime)
return
for (var/datum/weakref/targetref in localMotionTargets)
var/mob/target = targetref.resolve()
if(QDELETED(target) || target.stat == DEAD || get_dist(src, target) > 7 || get_area(src) != get_area(target))
localMotionTargets -= targetref
if (localMotionTargets.len)
detectTime = world.time + 30 SECONDS
else if (world.time > detectTime)
detectTime = 0
for(var/obj/machinery/computer/security/telescreen/entertainment/TV as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/computer/security/telescreen/entertainment))
TV.notify(FALSE)