From f7c53dec8ea1bd985202f8363ab1a515b6f9466a Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 3 Oct 2024 19:50:07 -0500 Subject: [PATCH] Fix air alarms to work correctly while connected to a gas sensor (#86958) ## About The Pull Request This fixes a bug that was hard to troubleshoot. While I was testing my other PR, I noticed that I was getting inconsistent atmos readouts while using a gas sensor hooked to an air alarm. Sometimes I would get the readout from the tile of the air alarm, and other times it would give me the readout of the gas sensor... I tracked it down and the root cause was the `COMSIG_TURF_EXPOSE` signal not being properly reassigned when a gas sensor was connected. My fix is to transfer the signal from the air alarm to the air sensor and vice versa when they are connected/disconnected. I also added some redundancies in place to limit air sensors to be only connected to one air alarm at a time. I threw in a mapping check to make sure one air alarm isn't linked to multiple sensors to catch some accidents. Another small fix is that air alarms now can be relinked to other air sensors if the sensor is reset. This was a problem for round-start linked air alarms that were paired with sensors since you could turn off or break a sensor and then the air alarm would have it's link severed without being able to link to any new sensors. ## Why It's Good For The Game Air alarms are becoming more robust! ## Changelog :cl: fix: Fix air alarms to work correctly while connected to a gas sensor fix: Fix paired air alarms and sensors to be able to relink to other devices if turned off, reset, or destroyed. /:cl: --- .../computer/atmos_computers/_air_sensor.dm | 9 +++- .../machinery/air_alarm/_air_alarm.dm | 42 +++++++++++++++---- code/modules/mapping/mapping_helpers.dm | 8 ++-- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/code/game/machinery/computer/atmos_computers/_air_sensor.dm b/code/game/machinery/computer/atmos_computers/_air_sensor.dm index 91a616cc5f6..1f4a8bf8340 100644 --- a/code/game/machinery/computer/atmos_computers/_air_sensor.dm +++ b/code/game/machinery/computer/atmos_computers/_air_sensor.dm @@ -15,6 +15,8 @@ var/inlet_id /// The outlet[vent pump] controlled by this sensor var/outlet_id + /// The air alarm connected to this sensor + var/obj/machinery/airalarm/connected_airalarm /obj/machinery/air_sensor/Initialize(mapload) id_tag = assign_random_name() @@ -57,7 +59,7 @@ /obj/machinery/air_sensor/examine(mob/user) . = ..() - . += span_notice("Use multitool to link it to an injector/vent or reset its ports") + . += span_notice("Use a multitool to link it to an injector, vent, or air alarm, or reset its ports.") . += span_notice("Click with hand to turn it off.") /obj/machinery/air_sensor/attack_hand(mob/living/user, list/modifiers) @@ -78,6 +80,11 @@ /obj/machinery/air_sensor/proc/reset() inlet_id = null outlet_id = null + if(connected_airalarm) + connected_airalarm.disconnect_sensor() + // if air alarm and sensor were linked at roundstart we allow them to link to new devices + connected_airalarm.allow_link_change = TRUE + connected_airalarm = null ///right click with multi tool to disconnect everything /obj/machinery/air_sensor/multitool_act_secondary(mob/living/user, obj/item/tool) diff --git a/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm b/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm index 1b4ea7a6f48..1e9045d8227 100644 --- a/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm +++ b/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm @@ -99,13 +99,14 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) tlv_collection = list() tlv_collection["pressure"] = new /datum/tlv/pressure tlv_collection["temperature"] = new /datum/tlv/temperature - var/list/meta_info = GLOB.meta_gas_info // shorthand - for(var/gas_path in meta_info) + + var/list/cached_gas_info = GLOB.meta_gas_info + for(var/datum/gas/gas_path as anything in cached_gas_info) if(ispath(gas_path, /datum/gas/oxygen)) tlv_collection[gas_path] = new /datum/tlv/oxygen else if(ispath(gas_path, /datum/gas/carbon_dioxide)) tlv_collection[gas_path] = new /datum/tlv/carbon_dioxide - else if(meta_info[gas_path][META_GAS_DANGER]) + else if(cached_gas_info[gas_path][META_GAS_DANGER]) tlv_collection[gas_path] = new /datum/tlv/dangerous else tlv_collection[gas_path] = new /datum/tlv/no_checks @@ -137,6 +138,12 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) /obj/machinery/airalarm/Destroy() if(my_area) my_area = null + if(connected_sensor) + UnregisterSignal(connected_sensor, COMSIG_QDELETING) + UnregisterSignal(connected_sensor.loc, COMSIG_TURF_EXPOSE) + connected_sensor.connected_airalarm = null + connected_sensor = null + QDEL_NULL(alarm_manager) GLOB.air_alarms -= src return ..() @@ -201,10 +208,16 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) return . if(istype(multi_tool.buffer, /obj/machinery/air_sensor)) + var/obj/machinery/air_sensor/sensor = multi_tool.buffer + if(!allow_link_change) balloon_alert(user, "linking disabled") return ITEM_INTERACT_BLOCKING - connect_sensor(multi_tool.buffer) + if(connected_sensor || sensor.connected_airalarm) + balloon_alert(user, "sensor already connected!") + return ITEM_INTERACT_BLOCKING + + connect_sensor(sensor) balloon_alert(user, "connected sensor") return ITEM_INTERACT_SUCCESS @@ -568,7 +581,8 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) danger_level = max(danger_level, tlv_collection["pressure"].check_value(pressure)) danger_level = max(danger_level, tlv_collection["temperature"].check_value(temp)) if(total_moles) - for(var/gas_path in GLOB.meta_gas_info) + var/list/cached_gas_info = GLOB.meta_gas_info + for(var/datum/gas/gas_path as anything in cached_gas_info) var/moles = environment.gases[gas_path] ? environment.gases[gas_path][MOLES] : 0 danger_level = max(danger_level, tlv_collection[gas_path].check_value(pressure * moles / total_moles)) @@ -691,14 +705,22 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 27) if(isnull(sensor)) log_mapping("[src] at [AREACOORD(src)] tried to connect to a sensor, but no sensor with chamber_id:[air_sensor_chamber_id] found!") return + if(connected_sensor) + log_mapping("[src] at [AREACOORD(src)] tried to connect to more than one sensor!") + return connect_sensor(sensor) ///Used to connect air alarm with a sensor /obj/machinery/airalarm/proc/connect_sensor(obj/machinery/air_sensor/sensor) - if(!isnull(connected_sensor)) - UnregisterSignal(connected_sensor, COMSIG_QDELETING) + sensor.connected_airalarm = src connected_sensor = sensor + RegisterSignal(connected_sensor, COMSIG_QDELETING, PROC_REF(disconnect_sensor)) + + // Transfer signal from air alarm to sensor + UnregisterSignal(loc, COMSIG_TURF_EXPOSE) + RegisterSignal(connected_sensor.loc, COMSIG_TURF_EXPOSE, PROC_REF(check_danger), override=TRUE) + my_area = get_area(connected_sensor) check_enviroment() @@ -709,6 +731,12 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 27) ///Used to reset the air alarm to default configuration after disconnecting from air sensor /obj/machinery/airalarm/proc/disconnect_sensor() UnregisterSignal(connected_sensor, COMSIG_QDELETING) + + // Transfer signal from sensor to air alarm + UnregisterSignal(connected_sensor.loc, COMSIG_TURF_EXPOSE) + RegisterSignal(loc, COMSIG_TURF_EXPOSE, PROC_REF(check_danger), override=TRUE) + + connected_sensor.connected_airalarm = null connected_sensor = null my_area = get_area(src) diff --git a/code/modules/mapping/mapping_helpers.dm b/code/modules/mapping/mapping_helpers.dm index 587a62ec0e1..55b802cc26c 100644 --- a/code/modules/mapping/mapping_helpers.dm +++ b/code/modules/mapping/mapping_helpers.dm @@ -326,9 +326,6 @@ if(target.syndicate_access + target.away_general_access + target.engine_access + target.mixingchamber_access + target.all_access > 1) CRASH("Tried to combine incompatible air alarm access helpers!") - if(target.air_sensor_chamber_id) - target.setup_chamber_link() - target.update_appearance() qdel(src) @@ -418,6 +415,7 @@ /obj/effect/mapping_helpers/airalarm/link name = "airalarm link helper" icon_state = "airalarm_link_helper" + late = TRUE var/chamber_id = "" var/allow_link_change = FALSE @@ -427,13 +425,15 @@ log_mapping("[src] spawned outside of mapload!") return INITIALIZE_HINT_QDEL +/obj/effect/mapping_helpers/airalarm/link/LateInitialize(mapload) var/obj/machinery/airalarm/alarm = locate(/obj/machinery/airalarm) in loc if(!isnull(alarm)) alarm.air_sensor_chamber_id = chamber_id alarm.allow_link_change = allow_link_change + alarm.setup_chamber_link() else log_mapping("[src] failed to find air alarm at [AREACOORD(src)].") - return INITIALIZE_HINT_QDEL + qdel(src) //apc helpers /obj/effect/mapping_helpers/apc