Optimizes grid check event a bit (+minor fixes) (#96075)

This commit is contained in:
MrMelbert
2026-05-27 20:43:58 -04:00
committed by GitHub
parent b8de8c78f2
commit 49d502ac9b
15 changed files with 139 additions and 41 deletions
+3
View File
@@ -1657,6 +1657,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// Makes the owner desensetized to death, but happy whenever someone gets blown to pieces (as a sacrifice to the necropolis) unless its another worshipper
#define TRAIT_NECROPOLIS_WORSHIP "necropolis_worship"
/// Applied to an area, stops random power failures from affecting it
#define TRAIT_AREA_BLOCK_POWER_FAIL "area_block_power_fail"
/// Sunlight on this turf is blocked and thus you can't get solar power or whatever
#define TRAIT_TURF_SUN_BLOCKED "turf_sun_blocked"
-9
View File
@@ -2,15 +2,6 @@
#define EXTRA_ROOM_CHECK_SKIP 1
#define EXTRA_ROOM_CHECK_FAIL 2
GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(list(
/area/station/engineering/main,
/area/station/engineering/supermatter,
/area/station/engineering/atmospherics_engine,
/area/station/ai/satellite/chamber,
/area/ruin/comms_agent //fixes icemoon comms station being affected
)))
// Gets an atmos isolated contained space
// Returns an associative list of turf|dirs pairs
// The dirs are connected turfs in the same space
+9 -6
View File
@@ -307,17 +307,20 @@
return FALSE
///Disable power in the station APCs
/**
* Disables power in most station APCs temporarily
*
* * duration_min - the minimum duration of the power failure in seconds (not deciseconds)
* * duration_max - the maximum duration of the power failure in seconds (not deciseconds)
*/
/proc/power_fail(duration_min, duration_max)
for(var/obj/machinery/power/apc/current_apc as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/power/apc))
if(!current_apc.cell || !SSmapping.level_trait(current_apc.z, ZTRAIT_STATION))
continue
var/area/apc_area = current_apc.area
if(is_type_in_typecache(apc_area, GLOB.typecache_powerfailure_safe_areas))
if(!current_apc.cell || !SSmapping.level_trait(current_apc.z, ZTRAIT_STATION) || HAS_TRAIT(current_apc.area, TRAIT_AREA_BLOCK_POWER_FAIL))
continue
var/duration = rand(duration_min,duration_max)
var/duration = rand(duration_min, duration_max)
current_apc.energy_fail(duration)
CHECK_TICK
/**
* 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).
+1
View File
@@ -99,6 +99,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_STRONGPULL" = TRAIT_STRONGPULL,
),
/area = list(
"TRAIT_AREA_BLOCK_POWER_FAIL" = TRAIT_AREA_BLOCK_POWER_FAIL,
"TRAIT_HAS_SHUTTLE_CONSTRUCTION_TURF" = TRAIT_HAS_SHUTTLE_CONSTRUCTION_TURF,
),
/datum/controller/global_vars = list(
@@ -0,0 +1,67 @@
// Used to differentiate what is protecting an area
#define AREA_TRAIT_SOURCE(the_source) "[type]_[the_source.type]"
#define MOVABLE_TRAIT_SOURCE(the_source) "[type]_[REF(the_source)]"
#define TURF_TRAIT_SOURCE(the_source) "[type]_[the_source.x]-[the_source.y]-[the_source.z]"
/**
* ## block_area_power_fail
*
* Element that interacts with the grid check event (and similar effects) to protect certain rooms
*
* * Attach to an area to prevent arbitrary power outages from affecting it
* * Attach to a movable to prevent arbitrary power outages from affecting the area it's in
* * Attach to a turf to prevent arbitrary power outages from affecting its area
*/
/datum/element/block_area_power_fail
element_flags = ELEMENT_DETACH_ON_HOST_DESTROY
/datum/element/block_area_power_fail/Attach(datum/target)
. = ..()
if(isarea(target)) // practically just a complicated way to do add trait
ADD_TRAIT(target, TRAIT_AREA_BLOCK_POWER_FAIL, AREA_TRAIT_SOURCE(target))
else if(ismovable(target)) // manages adding and removing the trait as the movable moves
var/atom/movable/movable_target = target
movable_target.become_area_sensitive(type)
RegisterSignal(target, COMSIG_ENTER_AREA, PROC_REF(on_movable_entered_area))
RegisterSignal(target, COMSIG_EXIT_AREA, PROC_REF(on_movable_exited_area))
on_movable_entered_area(target, get_area(movable_target))
else if(isturf(target)) // turfs don't move so it just adds the trait to the turf's area
var/turf/turf_target = target
ADD_TRAIT(turf_target.loc, TRAIT_AREA_BLOCK_POWER_FAIL, TURF_TRAIT_SOURCE(turf_target))
else
return ELEMENT_INCOMPATIBLE
/datum/element/block_area_power_fail/Detach(datum/source)
. = ..()
if(isarea(source))
REMOVE_TRAIT(source, TRAIT_AREA_BLOCK_POWER_FAIL, AREA_TRAIT_SOURCE(source))
else if(ismovable(source))
var/atom/movable/movable_source = source
movable_source.lose_area_sensitivity(type)
UnregisterSignal(source, COMSIG_ENTER_AREA)
UnregisterSignal(source, COMSIG_EXIT_AREA)
on_movable_exited_area(source, get_area(movable_source))
else if(isturf(source))
var/turf/turf_source = source
REMOVE_TRAIT(turf_source.loc, TRAIT_AREA_BLOCK_POWER_FAIL, TURF_TRAIT_SOURCE(turf_source))
/datum/element/block_area_power_fail/proc/on_movable_entered_area(atom/movable/source, area/new_area)
SIGNAL_HANDLER
if(new_area)
ADD_TRAIT(new_area, TRAIT_AREA_BLOCK_POWER_FAIL, MOVABLE_TRAIT_SOURCE(source))
/datum/element/block_area_power_fail/proc/on_movable_exited_area(atom/movable/source, area/old_area)
SIGNAL_HANDLER
if(old_area)
REMOVE_TRAIT(old_area, TRAIT_AREA_BLOCK_POWER_FAIL, MOVABLE_TRAIT_SOURCE(source))
#undef AREA_TRAIT_SOURCE
#undef MOVABLE_TRAIT_SOURCE
#undef TURF_TRAIT_SOURCE
+4
View File
@@ -27,6 +27,10 @@
name = "\improper Listening Post"
sound_environment = SOUND_ENVIRONMENT_CITY
/area/ruin/comms_agent/Initialize(mapload)
. = ..()
AddElement(/datum/element/block_area_power_fail)
/area/ruin/comms_agent/maint
name = "\improper Listening Post Maintenance"
sound_environment = SOUND_AREA_TUNNEL_ENCLOSED
+4
View File
@@ -45,6 +45,10 @@
icon_state = "ai_chamber"
annoying_ambience = null
/area/station/ai/satellite/chamber/Initialize(mapload)
. = ..()
AddElement(/datum/element/block_area_power_fail)
/area/station/ai/satellite/exterior
name = "\improper AI Satellite Exterior"
secure = FALSE
@@ -16,6 +16,10 @@
name = "Engineering"
icon_state = "engine"
/area/station/engineering/main/Initialize(mapload)
. = ..()
AddElement(/datum/element/block_area_power_fail)
/area/station/engineering/hallway
name = "Engineering Hallway"
icon_state = "engine_hallway"
@@ -69,6 +73,10 @@
icon_state = "atmos_engine"
area_flags = BLOBS_ALLOWED | CULT_PERMITTED
/area/station/engineering/atmospherics_engine/Initialize(mapload)
. = ..()
AddElement(/datum/element/block_area_power_fail)
/area/station/engineering/lobby
name = "\improper Engineering Lobby"
icon_state = "engi_lobby"
@@ -79,6 +87,10 @@
area_flags = BLOBS_ALLOWED | CULT_PERMITTED
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/station/engineering/supermatter/Initialize(mapload)
. = ..()
AddElement(/datum/element/block_area_power_fail)
/area/station/engineering/supermatter/waste
name = "\improper Supermatter Waste Chamber"
icon_state = "engine_sm_waste"
+2 -2
View File
@@ -23,7 +23,7 @@
continue
if(!station_area.requires_power || station_area.always_unpowered )
continue
if(GLOB.typecache_powerfailure_safe_areas[station_area.type])
if(HAS_TRAIT(station_area, TRAIT_AREA_BLOCK_POWER_FAIL))
continue
station_area.power_light = FALSE
@@ -34,7 +34,7 @@
for(var/obj/machinery/power/apc/C as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/power/apc))
if(C.cell && is_station_level(C.z))
var/area/A = C.area
if(GLOB.typecache_powerfailure_safe_areas[A.type])
if(HAS_TRAIT(A, TRAIT_AREA_BLOCK_POWER_FAIL))
continue
C.cell.charge = 0
+16 -3
View File
@@ -185,12 +185,15 @@
if(occupant_typecache)
occupant_typecache = typecacheof(occupant_typecache)
if((resistance_flags & INDESTRUCTIBLE) && component_parts){ // This is needed to prevent indestructible machinery still blowing up. If an explosion occurs on the same tile as the indestructible machinery without the PREVENT_CONTENTS_EXPLOSION_1 flag, /datum/controller/subsystem/explosions/proc/propagate_blastwave will call ex_act on all movable atoms inside the machine, including the circuit board and component parts. However, if those parts get deleted, the entire machine gets deleted, allowing for INDESTRUCTIBLE machines to be destroyed. (See #62164 for more info)
if((resistance_flags & INDESTRUCTIBLE) && component_parts) // This is needed to prevent indestructible machinery still blowing up. If an explosion occurs on the same tile as the indestructible machinery without the PREVENT_CONTENTS_EXPLOSION_1 flag, /datum/controller/subsystem/explosions/proc/propagate_blastwave will call ex_act on all movable atoms inside the machine, including the circuit board and component parts. However, if those parts get deleted, the entire machine gets deleted, allowing for INDESTRUCTIBLE machines to be destroyed. (See #62164 for more info)
flags_1 |= PREVENT_CONTENTS_EXPLOSION_1
}
if(critical_machine)
AddElement(/datum/element/block_area_power_fail)
if(HAS_TRAIT(SSstation, STATION_TRAIT_MACHINES_GLITCHED) && mapload)
randomize_language_if_on_station()
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_MACHINE, src)
return INITIALIZE_HINT_LATELOAD
@@ -1289,8 +1292,18 @@
set_machine_stat(vval)
datum_flags |= DF_VAR_EDITED
return TRUE
if(vname == NAMEOF(src, critical_machine))
if(critical_machine == !!vval) // boolean cast in case a badmin tries to set it to 2 for some reason
return FALSE
critical_machine = !!vval
if(critical_machine)
AddElement(/datum/element/block_area_power_fail)
else
RemoveElement(/datum/element/block_area_power_fail)
datum_flags |= DF_VAR_EDITED
return TRUE
return ..()
. = ..()
/**
* Alerts the AI that a hack is in progress.
+1 -1
View File
@@ -27,4 +27,4 @@
COOLDOWN_START(controller, announcement_spam_protection, 30 SECONDS)
/datum/round_event/grid_check/start()
power_fail(30, 120)
power_fail(60, 240) // 1 to 4 minutes
+1
View File
@@ -97,6 +97,7 @@
RegisterSignal(ai_tracking_tool, COMSIG_TRACKABLE_GLIDE_CHANGED, PROC_REF(tracked_glidesize_changed))
add_traits(list(TRAIT_PULL_BLOCKED, TRAIT_AI_ACCESS, TRAIT_HANDS_BLOCKED, TRAIT_CAN_GET_AI_TRACKING_MESSAGE, TRAIT_LOUD_BINARY), INNATE_TRAIT)
AddElement(/datum/element/block_area_power_fail)
//Heads up to other binary chat listeners that a new AI is online and listening to Binary.
if(announce_init_to_others && !is_centcom_level(z)) //Skip new syndicate AIs and also new AIs on centcom Z
+4 -4
View File
@@ -100,7 +100,7 @@
var/long_term_power = 10
///Automatically name the APC after the area is in
var/auto_name = FALSE
///Time to allow the APC to regain some power and to turn the channels back online
///Time to allow the APC to regain some power and to turn the channels back online in seconds
var/failure_timer = 0
///Forces an update on the power use to ensure that the apc has enough power
var/force_update = FALSE
@@ -282,8 +282,8 @@
/obj/machinery/power/apc/on_saboteur(datum/source, disrupt_duration)
. = ..()
disrupt_duration *= 0.1 // so, turns out, failure timer is in seconds, not deciseconds; without this, disruptions last 10 times as long as they probably should
energy_fail(disrupt_duration)
// failure timer is in seconds, not deciseconds, so we need to convert
energy_fail(disrupt_duration * 0.1)
return TRUE
/obj/machinery/power/apc/on_set_is_operational(old_value)
@@ -589,7 +589,7 @@
if(!area?.requires_power)
return
if(failure_timer)
failure_timer--
failure_timer = max(0, failure_timer - seconds_per_tick)
force_update = TRUE
return
+14 -16
View File
@@ -127,16 +127,15 @@
terminal.master = null
terminal = null
/**
* Temporarily disables all power to the room for a set duration
*
* Some rooms are immune to this effect due to having important machines
*
* * duration - the duration of the power failure in seconds (not deciseconds)
*/
/obj/machinery/power/apc/proc/energy_fail(duration)
for(var/obj/machinery/failing_machine in area.contents)
if(failing_machine.critical_machine)
return
for(var/mob/living/silicon/ai as anything in GLOB.ai_list)
if(get_area(ai) == area)
return
failure_timer = max(failure_timer, round(duration))
failure_timer = max(failure_timer, round(duration, SSMACHINES_DT))
update()
queue_icon_update()
@@ -147,10 +146,9 @@
if(nightshift_lights == on)
return //no change
nightshift_lights = on
for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists())
for(var/turf/area_turf as anything in zlevel_turfs)
for(var/obj/machinery/light/night_light in area_turf)
if(night_light.nightshift_allowed)
night_light.nightshift_enabled = nightshift_lights
night_light.update(FALSE)
CHECK_TICK
for(var/turf/area_turf as anything in area.get_turfs_from_all_zlevels())
for(var/obj/machinery/light/night_light in area_turf)
if(night_light.nightshift_allowed)
night_light.nightshift_enabled = nightshift_lights
night_light.update(FALSE)
CHECK_TICK
+1
View File
@@ -1550,6 +1550,7 @@
#include "code\datums\elements\beauty.dm"
#include "code\datums\elements\bed_tucking.dm"
#include "code\datums\elements\befriend_petting.dm"
#include "code\datums\elements\block_area_power_fail.dm"
#include "code\datums\elements\block_turf_fingerprints.dm"
#include "code\datums\elements\blocks_explosives.dm"
#include "code\datums\elements\blood_limb_overlay.dm"