Skip to content

Commit

Permalink
Air alarms display location/trigger information (tgstation#81436)
Browse files Browse the repository at this point in the history
## About The Pull Request

Adds additional information to triggered fire alarms, viewable on the
air alarm. Displays the method of alarm trigger and the source of the
alarm.


![image](https://github.com/tgstation/tgstation/assets/83487515/2b8bb334-e641-451b-9d6d-97e650e74032)

## Why It's Good For The Game

Useful for engineers to track down the source of why the fire
alarm/firedoors are triggering. Fire alarms that are manually triggered
will never reset without intervention, so this also identifies these
cases instead of chasing down an issue that may not exist.

## Changelog

:cl: LT3
qol: Air alarms now display the source of triggered fire
alarms/firedoors
/:cl:
  • Loading branch information
lessthnthree authored Feb 19, 2024
1 parent 7ec81f5 commit 68f7e03
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 7 deletions.
7 changes: 7 additions & 0 deletions code/__DEFINES/atmospherics/atmos_machinery.dm
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@
/// Fire alarm has all components but isn't completed
#define FIRE_ALARM_BUILD_SECURED 2

// Fault levels for air alarm display
/// Area faults clear
#define AREA_FAULT_NONE 0
/// Fault triggered by manual intervention (ie: fire alarm pull)
#define AREA_FAULT_MANUAL 1
/// Fault triggered automatically (ie: firedoor detection)
#define AREA_FAULT_AUTOMATIC 2

// threshold_type values for [/datum/tlv/proc/set_value] and [/datum/tlv/proc/reset_value]
/// [/datum/tlv/var/warning_min]
Expand Down
11 changes: 10 additions & 1 deletion code/game/area/areas.dm
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
var/list/firealarms = list()
///Alarm type to count of sources. Not usable for ^ because we handle fires differently
var/list/active_alarms = list()
/// The current alarm fault status
var/fault_status = AREA_FAULT_NONE
/// The source machinery for the area's fault status
var/fault_location
///List of all lights in our area
var/list/lights = list()
///We use this just for fire alarms, because they're area based right now so one alarm going poof shouldn't prevent you from clearing your alarms listing. Fire alarms and fire locks will set and clear alarms.
Expand Down Expand Up @@ -394,10 +398,15 @@ GLOBAL_LIST_EMPTY(teleportlocs)
*
* Allows interested parties (lights and fire alarms) to react
*/
/area/proc/set_fire_effect(new_fire)
/area/proc/set_fire_effect(new_fire, fault_type, fault_source)
if(new_fire == fire)
return
fire = new_fire
fault_status = fault_type
if(fire)
fault_location = fault_source
else
fault_location = null
SEND_SIGNAL(src, COMSIG_AREA_FIRE_CHANGED, fire)

/**
Expand Down
15 changes: 13 additions & 2 deletions code/game/machinery/doors/firedoor.dm
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,12 @@

/obj/machinery/door/firedoor/Initialize(mapload)
. = ..()
id_tag = assign_random_name()
soundloop = new(src, FALSE)
CalculateAffectingAreas()
my_area = get_area(src)
if(name == initial(name))
update_name()
if(!merger_typecache)
merger_typecache = typecacheof(/obj/machinery/door/firedoor)

Expand Down Expand Up @@ -180,6 +183,10 @@

return .

/obj/machinery/door/firedoor/update_name(updates)
. = ..()
name = "[get_area_name(my_area)] [initial(name)] [id_tag]"

/**
* Calculates what areas we should worry about.
*
Expand Down Expand Up @@ -323,6 +330,8 @@
return //We're already active
soundloop.start()
is_playing_alarm = TRUE
my_area.fault_status = AREA_FAULT_AUTOMATIC
my_area.fault_location = name
var/datum/merger/merge_group = GetMergeGroup(merger_id, merger_typecache)
for(var/obj/machinery/door/firedoor/buddylock as anything in merge_group.members)
buddylock.activate(code)
Expand All @@ -335,6 +344,8 @@
/obj/machinery/door/firedoor/proc/start_deactivation_process()
soundloop.stop()
is_playing_alarm = FALSE
my_area.fault_status = AREA_FAULT_NONE
my_area.fault_location = null
var/datum/merger/merge_group = GetMergeGroup(merger_id, merger_typecache)
for(var/obj/machinery/door/firedoor/buddylock as anything in merge_group.members)
buddylock.reset()
Expand Down Expand Up @@ -371,7 +382,7 @@
if(LAZYLEN(place.active_firelocks) != 1)
continue
//if we're the first to activate in this particular area
place.set_fire_effect(TRUE) //bathe in red
place.set_fire_effect(TRUE, AREA_FAULT_AUTOMATIC, name) //bathe in red
if(place == my_area)
// We'll limit our reporting to just the area we're on. If the issue affects bordering areas, they can report it themselves
place.alarm_manager.send_alarm(ALARM_FIRE, place)
Expand Down Expand Up @@ -431,7 +442,7 @@
LAZYREMOVE(place.active_firelocks, src)
if(LAZYLEN(place.active_firelocks)) // If we were the last firelock still active, clear the area effects
continue
place.set_fire_effect(FALSE)
place.set_fire_effect(FALSE, AREA_FAULT_NONE, name)
if(place == my_area)
place.alarm_manager.clear_alarm(ALARM_FIRE, place)

Expand Down
8 changes: 6 additions & 2 deletions code/game/machinery/firealarm.dm
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@

/obj/machinery/firealarm/Initialize(mapload, dir, building)
. = ..()
id_tag = assign_random_name()
if(building)
buildstage = FIRE_ALARM_BUILD_NO_CIRCUIT
set_panel_open(TRUE)
if(name == initial(name))
name = "[get_area_name(src)] [initial(name)]"
update_name()
my_area = get_area(src)
LAZYADD(my_area.firealarms, src)

Expand Down Expand Up @@ -114,7 +115,7 @@

/obj/machinery/firealarm/update_name(updates)
. = ..()
name = "[get_area_name(my_area)] [initial(name)]"
name = "[get_area_name(my_area)] [initial(name)] [id_tag]"

/obj/machinery/firealarm/on_exit_area(datum/source, area/area_to_unregister)
//we cannot unregister from an area we never registered to in the first place
Expand Down Expand Up @@ -259,6 +260,8 @@
if(user)
balloon_alert(user, "triggered alarm!")
user.log_message("triggered a fire alarm.", LOG_GAME)
my_area.fault_status = AREA_FAULT_MANUAL
my_area.fault_location = name
soundloop.start() //Manually pulled fire alarms will make the sound, rather than the doors.
SEND_SIGNAL(src, COMSIG_FIREALARM_ON_TRIGGER)
update_use_power(ACTIVE_POWER_USE)
Expand Down Expand Up @@ -454,6 +457,7 @@
. = ..()
if((my_area?.fire || LAZYLEN(my_area?.active_firelocks)))
. += "The local area hazard light is flashing."
. += "The fault location display is [my_area.fault_location] ([my_area.fault_status == AREA_FAULT_AUTOMATIC ? "Automatic Detection" : "Manual Trigger"])."
if(is_station_level(z))
. += "The station security alert level is [SSsecurity_level.get_current_level_as_text()]."
. += "<b>Left-Click</b> to activate all firelocks in this area."
Expand Down
2 changes: 2 additions & 0 deletions code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm)
data["dangerLevel"] = danger_level
data["atmosAlarm"] = !!my_area.active_alarms[ALARM_ATMOS]
data["fireAlarm"] = my_area.fire
data["faultStatus"] = my_area.fault_status
data["faultLocation"] = my_area.fault_location
data["sensor"] = !!connected_sensor
data["allowLinkChange"] = allow_link_change

Expand Down
30 changes: 28 additions & 2 deletions tgui/packages/tgui/interfaces/AirAlarm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ type AirAlarmData = {
dangerLevel: 0 | 1 | 2;
atmosAlarm: BooleanLike; // fix this
fireAlarm: BooleanLike;
faultStatus: 0 | 1 | 2;
faultLocation: string;
sensor: BooleanLike;
allowLinkChange: BooleanLike;
envData: {
Expand Down Expand Up @@ -89,7 +91,22 @@ const AirAlarmStatus = (props) => {
localStatusText: 'Danger (Internals Required)',
},
};
const faultMap = {
0: {
color: 'green',
areaFaultText: 'None',
},
1: {
color: 'purple',
areaFaultText: 'Manual Trigger',
},
2: {
color: 'average',
areaFaultText: 'Automatic Detection',
},
};
const localStatus = dangerMap[data.dangerLevel] || dangerMap[0];
const areaFault = faultMap[data.faultStatus] || faultMap[0];
return (
<Section title="Air Status">
<LabeledList>
Expand All @@ -107,17 +124,26 @@ const AirAlarmStatus = (props) => {
</LabeledList.Item>
);
})}
<LabeledList.Item label="Local status" color={localStatus.color}>
<LabeledList.Item label="Local Status" color={localStatus.color}>
{localStatus.localStatusText}
</LabeledList.Item>
<LabeledList.Item
label="Area status"
label="Area Status"
color={data.atmosAlarm || data.fireAlarm ? 'bad' : 'good'}
>
{(data.atmosAlarm && 'Atmosphere Alarm') ||
(data.fireAlarm && 'Fire Alarm') ||
'Nominal'}
</LabeledList.Item>
<LabeledList.Item label="Fault Status" color={areaFault.color}>
{areaFault.areaFaultText}
</LabeledList.Item>
<LabeledList.Item
label="Fault Location"
color={data.faultLocation ? 'blue' : 'green'}
>
{data.faultLocation || 'None'}
</LabeledList.Item>
</>
)) || (
<LabeledList.Item label="Warning" color="bad">
Expand Down

0 comments on commit 68f7e03

Please sign in to comment.