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

253 lines
9.3 KiB
Plaintext

/obj/machinery/computer/apc_control
name = "power flow control console"
desc = "Used to remotely control the flow of power to different parts of the station."
icon_screen = "solar"
icon_keyboard = "power_key"
req_access = list(ACCESS_CE)
circuit = /obj/item/circuitboard/computer/apc_control
light_color = LIGHT_COLOR_DIM_YELLOW
///The APC we're remotely connected to right now
var/obj/machinery/power/apc/active_apc
///Whether actions are being logged to the console's logs or not
var/should_log = TRUE
///Whether the console is currently being restored from an emagged state
var/restoring = FALSE
///List of logs containing events like logins/logoffs, APC access and manipulation, checking the APC/logs tabs and restoring logging after an emag
var/list/logs = list()
///Tracks the current logged-in user's ID card's name and assignment
var/auth_id = "\[NULL\]:"
///Whether the computer is on a station-level; set in Initialize() for use in checking APCs
var/is_on_station = TRUE
/obj/machinery/computer/apc_control/Initialize(mapload, obj/item/circuitboard/C)
. = ..()
is_on_station = is_station_level(z)
/obj/machinery/computer/apc_control/on_set_machine_stat(old_value)
. = ..()
if(machine_stat && active_apc)
disconnect_apc()
/obj/machinery/computer/apc_control/attack_ai(mob/user)
if(!isAdminGhostAI(user))
to_chat(user,span_warning("[src] does not support AI control.")) //You already have APC access, cheater!
return
return ..()
/obj/machinery/computer/apc_control/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
return FALSE
obj_flags |= EMAGGED
if (user)
user.log_message("emagged [src].", LOG_ATTACK, color="red")
balloon_alert(user, "access controller shorted")
playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
return TRUE
///Creates a log entry in the console with a timestamp, current login ID data and the text provided in log_text
/obj/machinery/computer/apc_control/proc/log_activity(log_text)
if(!should_log)
return
LAZYADD(logs, "([station_time_timestamp()]): [auth_id] [log_text]")
///Resets the console's emagged state and re-enables logging of activity
/obj/machinery/computer/apc_control/proc/restore_comp(mob/user)
obj_flags &= ~EMAGGED
should_log = TRUE
user.log_message("restored the logs of [src].", LOG_GAME)
log_activity("-=- Logging restored to full functionality at this point -=-")
restoring = FALSE
///Initiates remote access to the APC
/obj/machinery/computer/apc_control/proc/connect_apc(obj/machinery/power/apc/apc, mob/user)
if(isnull(apc))
return
if(apc.remote_control_user)
to_chat(user, span_warning("\The [apc] is being controlled by someone else!"))
return
if(active_apc)
disconnect_apc()
playsound(src, 'sound/machines/terminal/terminal_prompt_confirm.ogg', 50, FALSE)
apc.connect_remote_access(user)
user.log_message("remotely accessed [apc] from [src].", LOG_GAME)
log_activity("[auth_id] remotely accessed APC in [get_area_name(apc.area, TRUE)]")
active_apc = apc
RegisterSignal(active_apc, COMSIG_QDELETING, PROC_REF(on_apc_destroyed))
///Disconnects the computer from the accessed APC upon its destruction
/obj/machinery/computer/apc_control/proc/on_apc_destroyed(datum/source)
SIGNAL_HANDLER
disconnect_apc(TRUE) //to prevent the APC from trying to speak while being qdel'd
/**
* Disconnect from the APC we're currently in remote access with
* arguments:
* mute - whether the APC should announce the disconnection locally, passed into apc's disconnect_remote_access()
*/
/obj/machinery/computer/apc_control/proc/disconnect_apc(mute = FALSE)
UnregisterSignal(active_apc, COMSIG_QDELETING)
if(active_apc.remote_control_user)
active_apc.disconnect_remote_access(mute)
active_apc = null
/**
* Checks for whether the APC provided is eligible for access and being listed in the APC list.
* The APC has to:
* - be on a station z-level if the computer is station-side or be on the same z-level as the computer if otherwise (away subtype, charlie station)
* - be not hacked by a malf AI
* - have AI control enabled
* - be not emagged
* - be working
* - not be an AI monitored area (AI sat areas and AI upload)
*/
/obj/machinery/computer/apc_control/proc/check_apc(obj/machinery/power/apc/checked_apc)
return (is_on_station ? is_station_level(checked_apc.z) : checked_apc.z == z) && !checked_apc.malfhack && !checked_apc.aidisabled && !(checked_apc.obj_flags & EMAGGED) && !checked_apc.machine_stat && !istype(checked_apc.area, /area/station/ai)
/obj/machinery/computer/apc_control/ui_interact(mob/user, datum/tgui/ui)
. = ..()
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ApcControl")
ui.open()
/obj/machinery/computer/apc_control/ui_data(mob/user)
var/list/data = list()
data["auth_id"] = auth_id
data["authenticated"] = authenticated
data["emagged"] = obj_flags & EMAGGED
data["logging"] = should_log
data["restoring"] = restoring
data["logs"] = list()
data["apcs"] = list()
for(var/entry in logs)
data["logs"] += list(list("entry" = entry))
for(var/obj/machinery/power/apc/apc as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/power/apc))
if(check_apc(apc))
var/has_cell = (apc.cell) ? TRUE : FALSE
data["apcs"] += list(list(
"name" = apc.area.name,
"operating" = apc.operating,
"charge" = (has_cell) ? apc.cell.percent() : "NOCELL",
"load" = display_power(apc.lastused_total),
"charging" = apc.charging,
"chargeMode" = apc.chargemode,
"eqp" = apc.equipment,
"lgt" = apc.lighting,
"env" = apc.environ,
"responds" = apc.aidisabled || apc.panel_open,
"ref" = REF(apc)
)
)
return data
/obj/machinery/computer/apc_control/ui_act(action, params, datum/tgui/ui)
. = ..()
if(.)
return
var/mob/living/user = ui.user
switch(action)
if("log-in")
if(obj_flags & EMAGGED)
authenticated = TRUE
auth_id = "Unknown (Unknown):"
log_activity("[auth_id] logged in to the terminal")
return
if(!istype(user))
return
var/obj/item/card/id/user_id_card = user.get_idcard(TRUE)
if(istype(user_id_card))
if(check_access(user_id_card))
authenticated = TRUE
auth_id = "[user_id_card.registered_name] ([user_id_card.assignment]):"
log_activity("[auth_id] logged in to the terminal")
playsound(src, 'sound/machines/terminal/terminal_on.ogg', 50, FALSE)
else
auth_id = "[user_id_card.registered_name] ([user_id_card.assignment]):"
log_activity("[auth_id] attempted to log into the terminal")
playsound(src, 'sound/machines/terminal/terminal_error.ogg', 50, FALSE)
say("ID rejected, access denied!")
return
auth_id = "Unknown (Unknown):"
log_activity("[auth_id] attempted to log into the terminal")
if("log-out")
log_activity("[auth_id] logged out of the terminal")
playsound(src, 'sound/machines/terminal/terminal_off.ogg', 50, FALSE)
authenticated = FALSE
auth_id = "\[NULL\]"
if("toggle-logs")
should_log = !should_log
user.log_message("set the logs of [src] [should_log ? "On" : "Off"].", LOG_GAME)
if("restore-console")
restoring = TRUE
addtimer(CALLBACK(src, PROC_REF(restore_comp), user), rand(3,5) * 9 SECONDS)
if("access-apc")
var/ref = params["ref"]
playsound(src, SFX_TERMINAL_TYPE, 50, FALSE)
var/obj/machinery/power/apc/remote_target = locate(ref) in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/power/apc)
if(!remote_target || !check_apc(remote_target))
return
connect_apc(remote_target, user)
return TRUE
if("check-logs")
log_activity("Checked Logs")
if("check-apcs")
log_activity("Checked APCs")
if("toggle-minor")
var/ref = params["ref"]
var/type = params["type"]
var/value = params["value"]
var/obj/machinery/power/apc/target = locate(ref) in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/power/apc)
if(!target || !check_apc(target))
return
value = target.setsubsystem(text2num(value))
switch(type) // Sanity check
if("equipment")
target.equipment = value
if("lighting")
target.lighting = value
if("environ")
target.environ = value
if(null)
return
else
message_admins("Warning: possible href exploit by [key_name(user)] - attempted to set [html_encode(type)] on [target] to [html_encode(value)]")
user.log_message("possibly trying to href exploit - attempted to set [html_encode(type)] on [target] to [html_encode(value)]", LOG_ADMIN)
return
target.update_appearance()
target.update()
var/setTo = ""
switch(target.vars[type])
if(0)
setTo = "Off"
if(1)
setTo = "Auto Off"
if(2)
setTo = "On"
if(3)
setTo = "Auto On"
log_activity("Set APC [target.area.name] [type] to [setTo]")
user.log_message("set APC [target.area.name] [type] to [setTo]]", LOG_GAME)
if("breaker")
var/ref = params["ref"]
var/obj/machinery/power/apc/breaker_target = locate(ref) in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/power/apc)
if(!breaker_target || !check_apc(breaker_target))
return
breaker_target.toggle_breaker(user)
var/setTo = breaker_target.operating ? "On" : "Off"
log_activity("Turned APC [breaker_target.area.name]'s breaker [setTo]")
return TRUE
/obj/machinery/computer/apc_control/ui_close(mob/user)
. = ..()
if(active_apc)
disconnect_apc()
/obj/machinery/computer/apc_control/away
req_access = list(ACCESS_AWAY_ENGINEERING)