From 714aa3b150bedf268111347437f8043c93a064bb Mon Sep 17 00:00:00 2001 From: distributivgesetz Date: Thu, 1 Sep 2022 23:45:45 +0200 Subject: [PATCH] [MDB IGNORE] APC controller and Power Monitor/AmpCheck fixes, aka How do I write PR titles (#69146) About The Pull Request bgug fix stuff APC controller UI has its elements section'ed off. The backend has been redone to make the behaviour of the APC controller a bit less janky. The console should be more stable, and all the soul has been removed from the code and the UI. before this PR stales out from nobody wanting to review my pr, I should probably outline what exactly changed: APC controller consoles have had their APC code almost entirely reworked. They no longer have to hold a reference to the person using the controller currently, and APCs themselves no longer hold a reference to the controller, instead to the person directly. A lot of code was moved to APC themselves to make it a lot more stable. APC controller used to call toggle_breaker without passing args, causing a runtime. Fixed in Fixes the power flow control console not actually being able to toggle breakers #69343 APC controller UI has had the Window.Content tags moved up to the top component, and a lot has been sectioned off to make the UI more sane. AmpCheck used to look for a wire on it's turf, or as a fallback look for the Area APC. A check to see if the APC has a terminal did so on a weakref, causing a runtime and preventing the program from ever finding a valid APC in it's area, making it show nothing. This has been fixed. On the other hand, the power monitor console did not store the ground wire or APC terminal as a weakref, this has been updated. As a fallback, if there are still no APCs in the powernet, the UI will show a dimmer popup. There was a "secret" power monitor variation in code so PDAs could not access monitors in hidden places. With the removal of PDAs, this control console is useless. Why It's Good For The Game Tiny bit of (much needed) polish on some useful tools in the engineering department. Changelog cl fix: Fixed runtime when using AmpCheck without connecting the console with a wire. fix: Fixed a few runtimes that could occur when using APC controller consoles. qol: Sucked soul out of APC controller code and UI. del: Removed "secret" power monitor console. /cl --- .../lavaland_surface_biodome_winter.dmm | 2 +- .../lavaland_surface_syndicate_base1.dmm | 2 +- _maps/RandomRuins/SpaceRuins/TheDerelict.dmm | 2 +- _maps/RandomZLevels/moonoutpost19.dmm | 4 +- _maps/RandomZLevels/snowdin.dmm | 12 +- _maps/RandomZLevels/undergroundoutpost45.dmm | 4 +- _maps/map_files/generic/CentCom.dmm | 2 +- _maps/shuttles/emergency_cere.dmm | 2 +- _maps/shuttles/infiltrator_advanced.dmm | 2 +- _maps/shuttles/pirate_default.dmm | 2 +- _maps/shuttles/pirate_dutchman.dmm | 2 +- _maps/shuttles/pirate_silverscale.dmm | 2 +- code/game/machinery/computer/apc_control.dm | 124 +++++----- .../circuitboards/computer_circuitboards.dm | 5 - .../file_system/programs/powermonitor.dm | 2 +- code/modules/power/apc/apc_attack.dm | 5 - code/modules/power/apc/apc_main.dm | 40 +++- code/modules/power/apc/apc_tool_act.dm | 2 +- code/modules/power/monitor.dm | 28 +-- tgui/packages/tgui/interfaces/Apc.js | 5 +- tgui/packages/tgui/interfaces/ApcControl.js | 216 ++++++++++-------- tgui/packages/tgui/interfaces/PowerMonitor.js | 14 +- .../common/InterfaceLockNoticeBox.js | 2 + .../69146_remove_outdated_terminals.txt | 1 + 24 files changed, 260 insertions(+), 222 deletions(-) create mode 100644 tools/UpdatePaths/Scripts/69146_remove_outdated_terminals.txt diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_biodome_winter.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_biodome_winter.dmm index 39c8ec119b3..f83887d9b42 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_biodome_winter.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_biodome_winter.dmm @@ -449,7 +449,7 @@ /turf/open/floor/pod/dark, /area/ruin/powered/snow_biodome) "UM" = ( -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ dir = 1 }, /turf/open/floor/pod/dark, diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm index 0022970008e..4575acc7690 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm @@ -3239,7 +3239,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/structure/cable, -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ dir = 4 }, /turf/open/floor/plating, diff --git a/_maps/RandomRuins/SpaceRuins/TheDerelict.dmm b/_maps/RandomRuins/SpaceRuins/TheDerelict.dmm index fd392713dce..a527e92db32 100644 --- a/_maps/RandomRuins/SpaceRuins/TheDerelict.dmm +++ b/_maps/RandomRuins/SpaceRuins/TheDerelict.dmm @@ -432,7 +432,7 @@ /turf/open/floor/plating/airless, /area/ruin/space/ks13/ai/vault) "gx" = ( -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ dir = 4 }, /obj/structure/cable, diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm index b36a35d7225..42230fbd2b9 100644 --- a/_maps/RandomZLevels/moonoutpost19.dmm +++ b/_maps/RandomZLevels/moonoutpost19.dmm @@ -493,7 +493,7 @@ }, /area/awaymission/moonoutpost19/syndicate) "bS" = ( -/obj/machinery/computer/monitor/secret, +/obj/machinery/computer/monitor, /obj/effect/turf_decal/stripes/line{ dir = 5 }, @@ -2432,7 +2432,7 @@ }, /area/awaymission/moonoutpost19/research) "gA" = ( -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ dir = 1 }, /obj/structure/cable, diff --git a/_maps/RandomZLevels/snowdin.dmm b/_maps/RandomZLevels/snowdin.dmm index 8022b7c88ec..a7312884ada 100644 --- a/_maps/RandomZLevels/snowdin.dmm +++ b/_maps/RandomZLevels/snowdin.dmm @@ -4960,7 +4960,7 @@ /turf/open/misc/asteroid/snow, /area/awaymission/snowdin/cave) "ns" = ( -/obj/machinery/computer/monitor/secret, +/obj/machinery/computer/monitor, /obj/structure/cable, /turf/open/floor/iron, /area/awaymission/snowdin/post/engineering) @@ -6569,7 +6569,7 @@ /turf/open/floor/plating, /area/awaymission/snowdin/post/cavern2) "sv" = ( -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ dir = 8 }, /obj/structure/cable, @@ -6839,7 +6839,7 @@ /turf/open/misc/asteroid/snow/ice, /area/awaymission/snowdin/cave/cavern) "uj" = ( -/obj/machinery/computer/monitor/secret, +/obj/machinery/computer/monitor, /obj/structure/cable, /turf/open/floor/plating, /area/awaymission/snowdin/post/cavern1) @@ -7257,7 +7257,7 @@ /turf/open/floor/plating, /area/awaymission/snowdin/post/mining_dock) "wJ" = ( -/obj/machinery/computer/monitor/secret, +/obj/machinery/computer/monitor, /obj/structure/cable, /turf/open/floor/plating, /area/awaymission/snowdin/post/mining_dock) @@ -8563,7 +8563,7 @@ }, /area/awaymission/snowdin/cave) "Br" = ( -/obj/machinery/computer/monitor/secret, +/obj/machinery/computer/monitor, /turf/open/floor/plating, /area/awaymission/snowdin/post/minipost) "Bs" = ( @@ -10916,7 +10916,7 @@ /turf/open/floor/plating, /area/awaymission/snowdin/post/mining_dock) "KH" = ( -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ dir = 1 }, /obj/structure/cable, diff --git a/_maps/RandomZLevels/undergroundoutpost45.dmm b/_maps/RandomZLevels/undergroundoutpost45.dmm index dddf221ee6e..7ccd1a1abdb 100644 --- a/_maps/RandomZLevels/undergroundoutpost45.dmm +++ b/_maps/RandomZLevels/undergroundoutpost45.dmm @@ -11265,7 +11265,7 @@ }, /area/awaymission/undergroundoutpost45/caves) "BN" = ( -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ dir = 1; name = "primary power monitoring console" }, @@ -11354,7 +11354,7 @@ }, /area/awaymission/undergroundoutpost45/engineering) "De" = ( -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ name = "primary power monitoring console" }, /obj/structure/sign/warning/no_smoking/directional/west, diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index 6c0fd5c50f4..83336663224 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -8930,7 +8930,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 }, -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ dir = 1 }, /obj/structure/cable, diff --git a/_maps/shuttles/emergency_cere.dmm b/_maps/shuttles/emergency_cere.dmm index 3c07a3ce01c..a26125ce258 100644 --- a/_maps/shuttles/emergency_cere.dmm +++ b/_maps/shuttles/emergency_cere.dmm @@ -886,7 +886,7 @@ /area/shuttle/escape) "cV" = ( /obj/machinery/light/directional/north, -/obj/machinery/computer/monitor/secret, +/obj/machinery/computer/monitor, /obj/effect/turf_decal/tile/yellow{ dir = 1 }, diff --git a/_maps/shuttles/infiltrator_advanced.dmm b/_maps/shuttles/infiltrator_advanced.dmm index d628e665074..75c171015d2 100644 --- a/_maps/shuttles/infiltrator_advanced.dmm +++ b/_maps/shuttles/infiltrator_advanced.dmm @@ -245,7 +245,7 @@ /area/shuttle/syndicate/bridge) "az" = ( /obj/effect/turf_decal/bot, -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ dir = 8 }, /obj/structure/cable, diff --git a/_maps/shuttles/pirate_default.dmm b/_maps/shuttles/pirate_default.dmm index 5a1abdae1fa..adafca9b9ee 100644 --- a/_maps/shuttles/pirate_default.dmm +++ b/_maps/shuttles/pirate_default.dmm @@ -294,7 +294,7 @@ /area/shuttle/pirate) "aB" = ( /obj/machinery/light/small/directional/east, -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ dir = 8 }, /obj/effect/decal/cleanable/dirt, diff --git a/_maps/shuttles/pirate_dutchman.dmm b/_maps/shuttles/pirate_dutchman.dmm index 686d6c90e22..58146e30a59 100644 --- a/_maps/shuttles/pirate_dutchman.dmm +++ b/_maps/shuttles/pirate_dutchman.dmm @@ -109,7 +109,7 @@ /turf/open/floor/wood/airless, /area/shuttle/pirate/flying_dutchman) "aw" = ( -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ dir = 8 }, /turf/open/floor/carpet/royalblack/airless, diff --git a/_maps/shuttles/pirate_silverscale.dmm b/_maps/shuttles/pirate_silverscale.dmm index b9a8c5d0843..b2cf5c59be8 100644 --- a/_maps/shuttles/pirate_silverscale.dmm +++ b/_maps/shuttles/pirate_silverscale.dmm @@ -293,7 +293,7 @@ /turf/open/floor/carpet/royalblack, /area/shuttle/pirate) "nh" = ( -/obj/machinery/computer/monitor/secret{ +/obj/machinery/computer/monitor{ dir = 8 }, /turf/open/floor/iron/dark/side{ diff --git a/code/game/machinery/computer/apc_control.dm b/code/game/machinery/computer/apc_control.dm index 9fc5b487b12..8d546b45430 100644 --- a/code/game/machinery/computer/apc_control.dm +++ b/code/game/machinery/computer/apc_control.dm @@ -6,7 +6,6 @@ req_access = list(ACCESS_CE) circuit = /obj/item/circuitboard/computer/apc_control light_color = LIGHT_COLOR_YELLOW - var/mob/living/operator //Who's operating the computer right now var/obj/machinery/power/apc/active_apc //The APC we're using right now var/should_log = TRUE var/restoring = FALSE @@ -17,18 +16,10 @@ . = ..() logs = list() -/obj/machinery/computer/apc_control/process() - if(operator && (!operator.Adjacent(src) || machine_stat)) - operator = null - if(active_apc) - if(!active_apc.locked) - active_apc.say("Remote access canceled. Interface locked.") - playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, FALSE) - playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, FALSE) - active_apc.locked = TRUE - active_apc.update_appearance() - active_apc.remote_control = null - active_apc = null +/obj/machinery/computer/apc_control/on_set_machine_stat(old_value) + . = ..() + if(machine_stat) + disconnect_apc() /obj/machinery/computer/apc_control/attack_ai(mob/user) if(!isAdminGhostAI(user)) @@ -36,12 +27,52 @@ return ..() +/obj/machinery/computer/apc_control/emag_act(mob/user) + if(obj_flags & EMAGGED) + return + obj_flags |= EMAGGED + usr.log_message("emagged [src].", LOG_ATTACK, color="red") + playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + +/obj/machinery/computer/apc_control/proc/log_activity(log_text) + if(!should_log) + return + LAZYADD(logs, "([station_time_timestamp()]): [auth_id] [log_text]") + +/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 + +/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_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 + +/obj/machinery/computer/apc_control/proc/disconnect_apc() + // check if apc exists and is not controlled by anyone + if(QDELETED(active_apc)) + return + if(active_apc.remote_control_user) + active_apc.disconnect_remote_access() + active_apc = null + /obj/machinery/computer/apc_control/proc/check_apc(obj/machinery/power/apc/APC) return APC.z == z && !APC.malfhack && !APC.aidisabled && !(APC.obj_flags & EMAGGED) && !APC.machine_stat && !istype(APC.area, /area/station/ai_monitored) && !(APC.area.area_flags & NO_ALERTS) /obj/machinery/computer/apc_control/ui_interact(mob/user, datum/tgui/ui) . = ..() - operator = user ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "ApcControl") @@ -80,7 +111,7 @@ ) return data -/obj/machinery/computer/apc_control/ui_act(action, params) +/obj/machinery/computer/apc_control/ui_act(action, params, datum/tgui/ui) . = ..() if(.) return @@ -92,6 +123,9 @@ auth_id = "Unknown (Unknown):" log_activity("[auth_id] logged in to the terminal") return + var/mob/living/operator = usr + if(!istype(operator)) + return var/obj/item/card/id/ID = operator.get_idcard(TRUE) if(ID && istype(ID)) if(check_access(ID)) @@ -103,7 +137,7 @@ auth_id = "[ID.registered_name] ([ID.assignment]):" log_activity("[auth_id] attempted to log into the terminal") playsound(src, 'sound/machines/terminal_error.ogg', 50, FALSE) - to_chat(usr, span_warning("ID REJECTED - Access Denied.")) + say("ID rejected, access denied!") return auth_id = "Unknown (Unknown):" log_activity("[auth_id] attempted to log into the terminal") @@ -114,37 +148,15 @@ auth_id = "\[NULL\]" if("toggle-logs") should_log = !should_log - operator.log_message("set the logs of [src] [should_log ? "On" : "Off"].", LOG_GAME) + usr.log_message("set the logs of [src] [should_log ? "On" : "Off"].", LOG_GAME) if("restore-console") restoring = TRUE - addtimer(CALLBACK(src, .proc/restore_comp), rand(3,5) * 9) + addtimer(CALLBACK(src, .proc/restore_comp), rand(3,5) * 9 SECONDS) if("access-apc") var/ref = params["ref"] playsound(src, SFX_TERMINAL_TYPE, 50, FALSE) var/obj/machinery/power/apc/APC = locate(ref) in GLOB.apcs_list - if(!APC) - return - if(active_apc) - to_chat(operator, "[icon2html(src, auth_id)] Disconnected from [active_apc].") - active_apc.say("Remote access canceled. Interface locked.") - playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, FALSE) - playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, FALSE) - active_apc.locked = TRUE - active_apc.update_appearance() - active_apc.remote_control = null - active_apc = null - APC.remote_control = src - APC.ui_interact(operator) - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) - operator.log_message("remotely accessed [APC] from [src].", LOG_GAME) - log_activity("[auth_id] remotely accessed APC in [get_area_name(APC.area, TRUE)]") - if(APC.locked) - APC.say("Remote access detected. Interface unlocked.") - playsound(APC, 'sound/machines/boltsup.ogg', 25, FALSE) - playsound(APC, 'sound/machines/terminal_alert.ogg', 50, FALSE) - APC.locked = FALSE - APC.update_appearance() - active_apc = APC + connect_apc(APC, usr) if("check-logs") log_activity("Checked Logs") if("check-apcs") @@ -179,7 +191,7 @@ if(3) setTo = "Auto On" log_activity("Set APC [target.area.name] [type] to [setTo]") - operator.log_message("set APC [target.area.name] [type] to [setTo]]", LOG_GAME) + usr.log_message("set APC [target.area.name] [type] to [setTo]]", LOG_GAME) if("breaker") var/ref = params["ref"] var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list @@ -187,27 +199,7 @@ var/setTo = target.operating ? "On" : "Off" log_activity("Turned APC [target.area.name]'s breaker [setTo]") -/obj/machinery/computer/apc_control/emag_act(mob/user) - if(obj_flags & EMAGGED) - return - obj_flags |= EMAGGED - usr.log_message("emagged [src].", LOG_ATTACK, color="red") - playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - -/obj/machinery/computer/apc_control/proc/log_activity(log_text) - if(!should_log) - return - LAZYADD(logs, "([station_time_timestamp()]): [auth_id] [log_text]") - -/obj/machinery/computer/apc_control/proc/restore_comp() - obj_flags &= ~EMAGGED - should_log = TRUE - operator.log_message("restored the logs of [src].", LOG_GAME) - log_activity("-=- Logging restored to full functionality at this point -=-") - restoring = FALSE - -/mob/proc/using_power_flow_console() - for(var/obj/machinery/computer/apc_control/A in range(1, src)) - if(A.operator && A.operator == src && !A.machine_stat) - return TRUE - return +/obj/machinery/computer/apc_control/ui_close(mob/user) + . = ..() + if(active_apc) + disconnect_apc() diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index 5d0e364d400..011fd851545 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -203,11 +203,6 @@ greyscale_colors = CIRCUIT_COLOR_ENGINEERING build_path = /obj/machinery/computer/monitor -/obj/item/circuitboard/computer/powermonitor/secret - name = "Outdated Power Monitor" //Variant used on ruins to prevent them from showing up on PDA's. - greyscale_colors = CIRCUIT_COLOR_ENGINEERING - build_path = /obj/machinery/computer/monitor/secret - /obj/item/circuitboard/computer/sat_control name = "Satellite Network Control" greyscale_colors = CIRCUIT_COLOR_ENGINEERING diff --git a/code/modules/modular_computers/file_system/programs/powermonitor.dm b/code/modules/modular_computers/file_system/programs/powermonitor.dm index 92969d3355f..c2a47f47a00 100644 --- a/code/modules/modular_computers/file_system/programs/powermonitor.dm +++ b/code/modules/modular_computers/file_system/programs/powermonitor.dm @@ -45,7 +45,7 @@ var/area/A = get_area(computer) //if the computer isn't directly connected to a wire, attempt to find the APC powering it to pull it's powernet instead if(!A) return - var/obj/machinery/power/apc/local_apc = WEAKREF(A.apc) + var/obj/machinery/power/apc/local_apc = A.apc if(!local_apc) return if(!local_apc.terminal) //this really shouldn't happen without badminnery. diff --git a/code/modules/power/apc/apc_attack.dm b/code/modules/power/apc/apc_attack.dm index 36605c3f8b1..2890bd1501a 100644 --- a/code/modules/power/apc/apc_attack.dm +++ b/code/modules/power/apc/apc_attack.dm @@ -289,11 +289,6 @@ return FALSE return TRUE -/obj/machinery/power/apc/can_interact(mob/user) - . = ..() - if(!. && !QDELETED(remote_control)) - . = remote_control.can_interact(user) - /obj/machinery/power/apc/proc/set_broken() if(malfai && operating) malfai.malf_picker.processing_time = clamp(malfai.malf_picker.processing_time - 10,0,1000) diff --git a/code/modules/power/apc/apc_main.dm b/code/modules/power/apc/apc_main.dm index 0570ec737fd..59cc47b3e30 100644 --- a/code/modules/power/apc/apc_main.dm +++ b/code/modules/power/apc/apc_main.dm @@ -104,7 +104,7 @@ ///Used to stop process from updating the icons too much var/icon_update_needed = FALSE ///Reference to our remote control - var/obj/machinery/computer/apc_control/remote_control = null + var/mob/remote_control_user = null ///Represents a signel source of power alarms for this apc var/datum/alarm_handler/alarm_manager /// Offsets the object by APC_PIXEL_OFFSET (defined in apc_defines.dm) pixels in the direction we want it placed in. This allows the APC to be embedded in a wall, yet still inside an area (like mapping). @@ -268,7 +268,8 @@ "chargingStatus" = charging, "totalLoad" = display_power(lastused_total), "coverLocked" = coverlocked, - "siliconUser" = user.has_unlimited_silicon_privilege || user.using_power_flow_console(), + "remoteAccess" = (user == remote_control_user), + "siliconUser" = user.has_unlimited_silicon_privilege, "malfStatus" = get_malf_status(user), "emergencyLights" = !emergency_lights, "nightshiftLights" = nightshift_lights, @@ -309,9 +310,35 @@ ) return data +/obj/machinery/power/apc/proc/connect_remote_access(mob/remote_user) + if(opened) + return + remote_control_user = remote_user + ui_interact(remote_user) + remote_user.log_message("remotely accessed [src].", LOG_GAME) + say("Remote access detected.[locked ? " Interface unlocked." : ""]") + to_chat(remote_control_user, span_danger("[icon2html(src, remote_control_user)] Connected to [src].")) + if(locked) + playsound(src, 'sound/machines/terminal_on.ogg', 25, FALSE) + locked = FALSE + playsound(src, 'sound/machines/terminal_alert.ogg', 50, FALSE) + update_appearance() + +/obj/machinery/power/apc/proc/disconnect_remote_access() + // nothing to disconnect from + if(isnull(remote_control_user)) + return + locked = TRUE + say("Remote access canceled. Interface locked.") + to_chat(remote_control_user, span_danger("[icon2html(src, remote_control_user)] Disconnected from [src].")) + playsound(src, 'sound/machines/terminal_off.ogg', 25, FALSE) + playsound(src, 'sound/machines/terminal_alert.ogg', 50, FALSE) + update_appearance() + remote_control_user = null + /obj/machinery/power/apc/ui_status(mob/user) . = ..() - if(!QDELETED(remote_control) && user == remote_control.operator) + if(!QDELETED(remote_control_user) && user == remote_control_user) . = UI_INTERACTIVE /obj/machinery/power/apc/ui_act(action, params) @@ -322,7 +349,7 @@ switch(action) if("lock") if(usr.has_unlimited_silicon_privilege) - if((obj_flags & EMAGGED) || (machine_stat & (BROKEN|MAINT))) + if((obj_flags & EMAGGED) || (machine_stat & (BROKEN|MAINT)) || remote_control_user) to_chat(usr, span_warning("The APC does not respond to the command!")) else locked = !locked @@ -384,6 +411,11 @@ CHECK_TICK return TRUE +/obj/machinery/power/apc/ui_close(mob/user) + . = ..() + if(user == remote_control_user) + disconnect_remote_access() + /obj/machinery/power/apc/process() if(icon_update_needed) update_appearance() diff --git a/code/modules/power/apc/apc_tool_act.dm b/code/modules/power/apc/apc_tool_act.dm index ba72b822d80..7bf7e74dc0e 100644 --- a/code/modules/power/apc/apc_tool_act.dm +++ b/code/modules/power/apc/apc_tool_act.dm @@ -215,7 +215,7 @@ else if(machine_stat & (BROKEN|MAINT)) balloon_alert(user, "nothing happens!") else - if(allowed(usr) && !wires.is_cut(WIRE_IDSCAN) && !malfhack) + if(allowed(usr) && !wires.is_cut(WIRE_IDSCAN) && !malfhack && !remote_control_user) locked = !locked balloon_alert(user, "APC [ locked ? "locked" : "unlocked"]") update_appearance() diff --git a/code/modules/power/monitor.dm b/code/modules/power/monitor.dm index 091151fe479..856193d3cda 100644 --- a/code/modules/power/monitor.dm +++ b/code/modules/power/monitor.dm @@ -10,24 +10,13 @@ circuit = /obj/item/circuitboard/computer/powermonitor tgui_id = "PowerMonitor" - var/obj/structure/cable/attached_wire - var/obj/machinery/power/apc/local_apc + var/datum/weakref/attached_wire_ref + var/datum/weakref/local_apc_ref var/list/history = list() var/record_size = 60 var/record_interval = 50 var/next_record = 0 - var/is_secret_monitor = FALSE - -/obj/machinery/computer/monitor/secret //Hides the power monitor (such as ones on ruins & CentCom) from PDA's to prevent metagaming. - name = "outdated power monitoring console" - desc = "It monitors power levels across the local powernet." - circuit = /obj/item/circuitboard/computer/powermonitor/secret - is_secret_monitor = TRUE - -/obj/machinery/computer/monitor/secret/examine(mob/user) - . = ..() - . += span_notice("It's operating system seems quite outdated... It doesn't seem like it'd be compatible with the latest remote NTOS monitoring systems.") /obj/machinery/computer/monitor/Initialize(mapload) . = ..() @@ -43,21 +32,24 @@ update_use_power(ACTIVE_POWER_USE) record() -/obj/machinery/computer/monitor/proc/search() //keep in sync with /datum/computer_file/program/power_monitor's version +/obj/machinery/computer/monitor/proc/search() //keep in sync with /obj/machinery/computer/monitor's version var/turf/T = get_turf(src) - attached_wire = locate(/obj/structure/cable) in T - if(attached_wire) + attached_wire_ref = WEAKREF(locate(/obj/structure/cable) in T) + if(attached_wire_ref) return var/area/A = get_area(src) //if the computer isn't directly connected to a wire, attempt to find the APC powering it to pull it's powernet instead if(!A) return - local_apc = A.apc + var/obj/machinery/power/apc/local_apc = A.apc if(!local_apc) return if(!local_apc.terminal) //this really shouldn't happen without badminnery. local_apc = null + local_apc_ref = WEAKREF(local_apc) -/obj/machinery/computer/monitor/proc/get_powernet() //keep in sync with /datum/computer_file/program/power_monitor's version +/obj/machinery/computer/monitor/proc/get_powernet() //keep in sync with /datum/computer_file/program/power_monitor's version //np + var/obj/structure/cable/attached_wire = attached_wire_ref?.resolve() + var/obj/machinery/power/apc/local_apc = local_apc_ref?.resolve() if(attached_wire || (local_apc?.terminal)) return attached_wire ? attached_wire.powernet : local_apc.terminal.powernet return FALSE diff --git a/tgui/packages/tgui/interfaces/Apc.js b/tgui/packages/tgui/interfaces/Apc.js index baf818edcbc..4802d1966f9 100644 --- a/tgui/packages/tgui/interfaces/Apc.js +++ b/tgui/packages/tgui/interfaces/Apc.js @@ -83,7 +83,10 @@ const ApcContent = (props, context) => { } return ( <> - +
{ const { data } = useBackend(context); return ( - {data.authenticated === 1 && } - {data.authenticated === 0 && } + + {data.authenticated === 1 && } + {data.authenticated === 0 && } + ); }; @@ -21,14 +23,15 @@ const ApcLoggedOut = (props, context) => { const { emagged } = data; const text = emagged === 1 ? 'Open' : 'Log In'; return ( - +
); }; @@ -37,7 +40,7 @@ const ApcLoggedIn = (props, context) => { const { restoring } = data; const [tabIndex, setTabIndex] = useLocalState(context, 'tab-index', 1); return ( - <> + { )} {tabIndex === 1 && ( - <> - - - + + +
+ +
+
+ +
- - - +
+
+
)} {tabIndex === 2 && ( - - +
+ - - + +
)} - +
); }; @@ -89,11 +96,11 @@ const ControlPanel = (props, context) => { const [sortByField, setSortByField] = useLocalState( context, 'sortByField', - null + 'name' ); return ( - - + + Sort by: @@ -112,9 +119,9 @@ const ControlPanel = (props, context) => { content="Draw" onClick={() => setSortByField(sortByField !== 'draw' && 'draw')} /> - - - + + + {emagged === 1 && ( <>