From 8abc39bdd266768a4a2019457bc2a803034b39fb Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Tue, 7 Feb 2023 17:20:58 -0600 Subject: [PATCH] Fixes admin "power failure" secret. (#73277) ## About The Pull Request - Fixes "power failure" secret not working. `GLOB.the_station_areas` is a list of types, not list of areas. This `as anything` was causing runtimes, as it was accessing values on types, and not area instances. Swaps it over to use `GLOB.areas` + location check that the areas are on station Z level. - Fixes "power failure" secret having no announcement if no grid check has occurred `GLOB.power_failure_message_cooldown` starts at 0, so it was always lower than `world.time` if an admin uses it when no grid check has occurred. Delving deeper, these should not have been linked whatsoever. The power failure spam prevention is now tied to the grid check event itself. I also don't believe it to be necessary, as we fixed discounts having infinite stock, but I'll keep it just cause. ## Why It's Good For The Game Secrets work as advertised ## Changelog :cl: Melbert fix: Admins, "All areas unpowered" in the secrets menu will now function again. /:cl: --- code/__HELPERS/game.dm | 6 ---- code/game/gamemodes/events.dm | 58 ++++++++++++++++++++++--------- code/modules/events/grid_check.dm | 11 ++++-- 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index ccca11387dd..51ce05309ca 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -395,12 +395,8 @@ return pick(possible_loc) -///Prevents power_failure message spam if a traitor purchases repeatedly. -GLOBAL_VAR_INIT(power_failure_message_cooldown, 0) - ///Disable power in the station APCs /proc/power_fail(duration_min, duration_max) - var/message_cooldown for(var/obj/machinery/power/apc/current_apc as anything in GLOB.apcs_list) if(!current_apc.cell || !SSmapping.level_trait(current_apc.z, ZTRAIT_STATION)) continue @@ -409,9 +405,7 @@ GLOBAL_VAR_INIT(power_failure_message_cooldown, 0) continue var/duration = rand(duration_min,duration_max) - message_cooldown = max(duration, message_cooldown) current_apc.energy_fail(duration) - GLOB.power_failure_message_cooldown = world.time + message_cooldown /** * Sends a round tip to a target. If selected_tip is null, a random tip will be sent instead (5% chance of it being silly). diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index 2829acccb82..6819805c0c6 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -1,6 +1,13 @@ +/** + * Causes a power failure across the station. + * + * All SMESs and APCs will be fully drained, and all areas will power down. + * + * The drain is permanent (that is, it won't automatically come back after some time like the grid check event), + * but the crew themselves can return power via the engine, solars, or other means of creating power. + */ /proc/power_failure() - if(GLOB.power_failure_message_cooldown > world.time) - priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", ANNOUNCER_POWEROFF) + priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", ANNOUNCER_POWEROFF) for(var/obj/machinery/power/smes/S in GLOB.machines) if(istype(get_area(S), /area/station/ai_monitored/turret_protected) || !is_station_level(S.z)) continue @@ -10,16 +17,18 @@ S.update_appearance() S.power_change() - for(var/area/A as anything in GLOB.the_station_areas) - if(!A.requires_power || A.always_unpowered ) + for(var/area/station_area as anything in GLOB.areas) + if(!station_area.z || !is_station_level(station_area.z)) continue - if(GLOB.typecache_powerfailure_safe_areas[A.type]) + if(!station_area.requires_power || station_area.always_unpowered ) + continue + if(GLOB.typecache_powerfailure_safe_areas[station_area.type]) continue - A.power_light = FALSE - A.power_equip = FALSE - A.power_environ = FALSE - A.power_change() + station_area.power_light = FALSE + station_area.power_equip = FALSE + station_area.power_environ = FALSE + station_area.power_change() for(var/obj/machinery/power/apc/C in GLOB.apcs_list) if(C.cell && is_station_level(C.z)) @@ -29,6 +38,11 @@ C.cell.charge = 0 +/** + * Restores power to all rooms on the station. + * + * Magically fills ALL APCs and SMESs to capacity, and restores power to depowered areas. + */ /proc/power_restore() priority_announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", ANNOUNCER_POWERON) for(var/obj/machinery/power/apc/C in GLOB.apcs_list) @@ -43,17 +57,27 @@ S.output_attempt = TRUE S.update_appearance() S.power_change() - for(var/area/A in GLOB.the_station_areas) - if(!A.requires_power || A.always_unpowered) + for(var/area/station_area as anything in GLOB.areas) + if(!station_area.z || !is_station_level(station_area.z)) continue - if(!istype(A, /area/shuttle)) - A.power_light = TRUE - A.power_equip = TRUE - A.power_environ = TRUE - A.power_change() + if(!station_area.requires_power || station_area.always_unpowered) + continue + if(istype(station_area, /area/shuttle)) + continue + station_area.power_light = TRUE + station_area.power_equip = TRUE + station_area.power_environ = TRUE + station_area.power_change() +/** + * A quicker version of [/proc/power_restore] that only handles recharging SMESs. + * + * This will also repower an entire station - it is not instantaneous like power restore, + * but it is faster performance-wise as it only handles SMES units. + * + * Great as a less magical / more IC way to return power to a sapped station. + */ /proc/power_restore_quick() - priority_announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", ANNOUNCER_POWERON) for(var/obj/machinery/power/smes/S in GLOB.machines) if(!is_station_level(S.z)) diff --git a/code/modules/events/grid_check.dm b/code/modules/events/grid_check.dm index 143d36ed40f..7752ddfab0e 100644 --- a/code/modules/events/grid_check.dm +++ b/code/modules/events/grid_check.dm @@ -5,14 +5,21 @@ max_occurrences = 3 category = EVENT_CATEGORY_ENGINEERING description = "Turns off all APCs for a while, or until they are manually rebooted." + /// Cooldown for the announement associated with this event. + /// Necessary due to the fact that this event is player triggerable. + COOLDOWN_DECLARE(announcement_spam_protection) /datum/round_event/grid_check announce_when = 1 start_when = 1 /datum/round_event/grid_check/announce(fake) - if(fake || (GLOB.power_failure_message_cooldown > world.time)) - priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", ANNOUNCER_POWEROFF) + var/datum/round_event_control/grid_check/controller = control + if(!COOLDOWN_FINISHED(controller, announcement_spam_protection) && !fake) + return + priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", ANNOUNCER_POWEROFF) + if(!fake) // Only start the CD if we're real + COOLDOWN_START(controller, announcement_spam_protection, 30 SECONDS) /datum/round_event/grid_check/start() power_fail(30, 120)