[MIRROR] Drastically improved the USB connection for air alarms. Any airlock can now be made into a shell [MDB IGNORE] (#15270)

* Drastically improved the USB connection for air alarms. Any airlock can now be made into a shell (#68632)

The USB connections for air alarms have been improved and now include scrubber control, vent control and the setting of the air alarm mode. Also fixes a bug where the limits were not being properly set.

The scrubber, vent and limit control can be duplicated in the circuit to allow multiple limits/scrubbers/vents to be controlled by one circuit.

Any airlock can be made into a shell during construction by configuring the airlock electronic before insert.

* Drastically improved the USB connection for air alarms. Any airlock can now be made into a shell

Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com>
This commit is contained in:
SkyratBot
2022-07-30 00:41:36 +02:00
committed by GitHub
parent f671c7348a
commit fbce7aa40f
16 changed files with 742 additions and 47 deletions

View File

@@ -14,10 +14,18 @@
#define COMSIG_EXIT_AREA "exit_area"
// Alarm listener datum signals
///Sent when an alarm is fired (alarm, area/source_area)
#define COMSIG_ALARM_TRIGGERED "comsig_alarm_triggered"
///Send when an alarm source is cleared (alarm_type, area/source_area)
#define COMSIG_ALARM_CLEARED "comsig_alarm_clear"
///Sent when an alarm is fired and an alarm listener has tracked onto it (alarm, area/source_area)
#define COMSIG_ALARM_LISTENER_TRIGGERED "alarm_listener_triggered"
///Send when an alarm source is cleared and an alarm listener has tracked onto it (alarm_type, area/source_area)
#define COMSIG_ALARM_LISTENER_CLEARED "alarm_listener_clear"
/// Called when an alarm handler fires an alarm
#define COMSIG_ALARM_TRIGGERED "alarm_triggered"
/// Called when an alarm handler clears an alarm
#define COMSIG_ALARM_CLEARED "alarm_cleared"
/// Called when the air alarm mode is updated
#define COMSIG_AIRALARM_UPDATE_MODE "airalarm_update_mode"
// Area fire signals
/// Sent when an area's fire var changes: (fire_value)

View File

@@ -59,9 +59,9 @@
#define COMSIG_WEATHER_WINDDOWN(event_type) "!weather_winddown [event_type]"
#define COMSIG_WEATHER_END(event_type) "!weather_end [event_type]"
/// An alarm of some form was sent (datum/alarm_handler/source, alarm_type, area/source_area)
#define COMSIG_ALARM_FIRE(alarm_type) "!alarm_fire [alarm_type]"
#define COMSIG_GLOB_ALARM_FIRE(alarm_type) "!alarm_fire [alarm_type]"
/// An alarm of some form was cleared (datum/alarm_handler/source, alarm_type, area/source_area)
#define COMSIG_ALARM_CLEAR(alarm_type) "!alarm_clear [alarm_type]"
#define COMSIG_GLOB_ALARM_CLEAR(alarm_type) "!alarm_clear [alarm_type]"
///global mob logged in signal! (/mob/added_player)
#define COMSIG_GLOB_MOB_LOGGED_IN "!mob_logged_in"

View File

@@ -61,7 +61,8 @@
our_area.active_alarms[alarm_type] += 1
SEND_GLOBAL_SIGNAL(COMSIG_ALARM_FIRE(alarm_type), src, alarm_type, our_area, our_z_level, optional_camera)
SEND_SIGNAL(src, COMSIG_ALARM_TRIGGERED, alarm_type, our_area)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ALARM_FIRE(alarm_type), src, alarm_type, our_area, our_z_level, optional_camera)
return TRUE
@@ -95,7 +96,8 @@
if(!length(our_area.active_alarms))
our_area.active_alarms -= alarm_type
SEND_GLOBAL_SIGNAL(COMSIG_ALARM_CLEAR(alarm_type), src, alarm_type, our_area)
SEND_SIGNAL(src, COMSIG_ALARM_CLEARED, alarm_type, our_area)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ALARM_CLEAR(alarm_type), src, alarm_type, our_area)
return TRUE
/datum/alarm_listener
@@ -114,8 +116,8 @@
src.allowed_z_levels = allowed_z_levels
src.allowed_areas = allowed_areas
for(var/alarm_type in alarms_to_listen_for)
RegisterSignal(SSdcs, COMSIG_ALARM_FIRE(alarm_type), .proc/add_alarm)
RegisterSignal(SSdcs, COMSIG_ALARM_CLEAR(alarm_type), .proc/clear_alarm)
RegisterSignal(SSdcs, COMSIG_GLOB_ALARM_FIRE(alarm_type), .proc/add_alarm)
RegisterSignal(SSdcs, COMSIG_GLOB_ALARM_CLEAR(alarm_type), .proc/clear_alarm)
return ..()
@@ -153,7 +155,7 @@
//This does mean that only the first alarm of that camera type in the area will send a ping, but jesus what else can ya do
alarms_of_our_type[source_area.name] = list(source_area, cameras, list(handler))
SEND_SIGNAL(src, COMSIG_ALARM_TRIGGERED, alarm_type, source_area)
SEND_SIGNAL(src, COMSIG_ALARM_LISTENER_TRIGGERED, alarm_type, source_area)
///Removes an alarm to our alarms list, you probably shouldn't be calling this manually
///It should all be handled by the signal listening we do, unless you want to only remove an alarm to one listener
@@ -183,7 +185,7 @@
if(!length(alarms_of_our_type))
alarms -= alarm_type
SEND_SIGNAL(src, COMSIG_ALARM_CLEARED, alarm_type, source_area)
SEND_SIGNAL(src, COMSIG_ALARM_LISTENER_CLEARED, alarm_type, source_area)
///Does what it says on the tin, exists for signal hooking
/datum/alarm_listener/proc/prevent_alarm_changes()

View File

@@ -10,7 +10,7 @@
/obj/machinery/computer/station_alert/Initialize(mapload)
alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER), list(z), title = name)
RegisterSignal(alert_control.listener, list(COMSIG_ALARM_TRIGGERED, COMSIG_ALARM_CLEARED), .proc/update_alarm_display)
RegisterSignal(alert_control.listener, list(COMSIG_ALARM_LISTENER_TRIGGERED, COMSIG_ALARM_LISTENER_CLEARED), .proc/update_alarm_display)
return ..()
/obj/machinery/computer/station_alert/Destroy()

View File

@@ -15,6 +15,8 @@
var/passed_cycle_id
/// A holder of the electronics, in case of them working as an integrated part
var/holder
/// Whether this airlock can have an integrated circuit inside of it or not
var/shell = FALSE
/obj/item/electronics/airlock/examine(mob/user)
. = ..()
@@ -47,6 +49,7 @@
data["unres_direction"] = unres_sides
data["passedName"] = passed_name
data["passedCycleId"] = passed_cycle_id
data["shell"] = shell
return data
/obj/item/electronics/airlock/ui_act(action, params)
@@ -72,6 +75,9 @@
else
accesses -= access
. = TRUE
if("set_shell")
shell = !!params["on"]
. = TRUE
if("direc_set")
var/unres_direction = text2num(params["unres_direction"])
unres_sides ^= unres_direction //XOR, toggles only the bit that was clicked

View File

@@ -109,7 +109,6 @@
to_chat(user, span_notice("You add [I] to the turret."))
build_step = PTURRET_GUN_EQUIPPED
return
else if(I.tool_behaviour == TOOL_WRENCH)
I.play_tool_sound(src, 100)
to_chat(user, span_notice("You remove the turret's metal armor bolts."))

View File

@@ -268,6 +268,13 @@
door.electronics = electronics
door.heat_proof = heat_proof_finished
door.security_level = 0
if(electronics.shell)
door.AddComponent( \
/datum/component/shell, \
unremovable_circuit_components = list(new /obj/item/circuit_component/airlock, new /obj/item/circuit_component/airlock_access_event), \
capacity = SHELL_CAPACITY_LARGE, \
shell_flags = SHELL_FLAG_ALLOW_FAILURE_ACTION|SHELL_FLAG_REQUIRE_ANCHOR \
)
if(electronics.one_access)
door.req_one_access = electronics.accesses
else

View File

@@ -140,7 +140,10 @@
set_frequency(frequency)
AddElement(/datum/element/connect_loc, atmos_connections)
AddComponent(/datum/component/usb_port, list(
/obj/item/circuit_component/air_alarm_general,
/obj/item/circuit_component/air_alarm,
/obj/item/circuit_component/air_alarm_scrubbers,
/obj/item/circuit_component/air_alarm_vents
))
@@ -550,6 +553,7 @@
"checks" = 2,
"set_internal_pressure" = 0
), signal_source)
SEND_SIGNAL(src, COMSIG_AIRALARM_UPDATE_MODE, signal_source)
/obj/machinery/airalarm/update_appearance(updates)
. = ..()
@@ -914,8 +918,114 @@
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 24)
/obj/item/circuit_component/air_alarm
/obj/item/circuit_component/air_alarm_general
display_name = "Air Alarm"
desc = "Outputs basic information that the air alarm has recorded"
var/obj/machinery/airalarm/connected_alarm
/// Enables the fire alarm
var/datum/port/input/enable_fire_alarm
/// Disables the fire alarm
var/datum/port/input/disable_fire_alarm
/// The mode to set the air alarm to
var/datum/port/input/option/mode
/// The trigger to set the mode
var/datum/port/input/set_mode
/// Whether the fire alarm is enabled or not
var/datum/port/output/fire_alarm_enabled
/// The current set mode
var/datum/port/output/current_mode
var/static/list/options_map
/obj/item/circuit_component/air_alarm_general/populate_options()
if(!options_map)
options_map = list(
"Filtering" = AALARM_MODE_SCRUBBING,
"Contaminated" = AALARM_MODE_CONTAMINATED,
"Draught" = AALARM_MODE_VENTING,
"Refill" = AALARM_MODE_REFILL,
"Cycle" = AALARM_MODE_REPLACEMENT,
"Siphon" = AALARM_MODE_SIPHON,
"Panic Siphon" = AALARM_MODE_PANIC,
"Off" = AALARM_MODE_OFF,
)
/obj/item/circuit_component/air_alarm_general/populate_ports()
mode = add_option_port("Mode", options_map, order = 1)
set_mode = add_input_port("Set Mode", PORT_TYPE_SIGNAL, trigger = .proc/set_mode)
enable_fire_alarm = add_input_port("Enable Alarm", PORT_TYPE_SIGNAL, trigger = .proc/trigger_alarm)
disable_fire_alarm = add_input_port("Disable Alarm", PORT_TYPE_SIGNAL, trigger = .proc/trigger_alarm)
fire_alarm_enabled = add_output_port("Alarm Enabled", PORT_TYPE_NUMBER)
current_mode = add_output_port("Current Mode", PORT_TYPE_STRING)
/obj/item/circuit_component/air_alarm_general/register_usb_parent(atom/movable/shell)
. = ..()
if(istype(shell, /obj/machinery/airalarm))
connected_alarm = shell
RegisterSignal(connected_alarm.alarm_manager, COMSIG_ALARM_TRIGGERED, .proc/on_alarm_triggered)
RegisterSignal(connected_alarm.alarm_manager, COMSIG_ALARM_CLEARED, .proc/on_alarm_cleared)
RegisterSignal(shell, COMSIG_AIRALARM_UPDATE_MODE, .proc/on_mode_updated)
current_mode.set_value(connected_alarm.get_mode_name(connected_alarm.mode))
/obj/item/circuit_component/air_alarm_general/unregister_usb_parent(atom/movable/shell)
if(connected_alarm)
UnregisterSignal(connected_alarm.alarm_manager, list(
COMSIG_ALARM_TRIGGERED,
COMSIG_ALARM_CLEARED,
))
connected_alarm = null
UnregisterSignal(shell, list(
COMSIG_AIRALARM_UPDATE_MODE,
))
return ..()
/obj/item/circuit_component/air_alarm_general/proc/on_mode_updated(obj/machinery/airalarm/alarm, datum/signal_source)
SIGNAL_HANDLER
current_mode.set_value(alarm.get_mode_name(alarm.mode))
/obj/item/circuit_component/air_alarm_general/proc/on_alarm_triggered(datum/source, alarm_type, area/location)
SIGNAL_HANDLER
if(alarm_type == ALARM_ATMOS)
fire_alarm_enabled.set_output(TRUE)
/obj/item/circuit_component/air_alarm_general/proc/on_alarm_cleared(datum/source, alarm_type, area/location)
SIGNAL_HANDLER
if(alarm_type == ALARM_ATMOS)
fire_alarm_enabled.set_output(FALSE)
/obj/item/circuit_component/air_alarm_general/proc/trigger_alarm(datum/port/input/port)
CIRCUIT_TRIGGER
if(!connected_alarm || connected_alarm.locked)
return
if(port == enable_fire_alarm)
if(connected_alarm.alarm_manager.send_alarm(ALARM_ATMOS))
INVOKE_ASYNC(connected_alarm, /obj/machinery/airalarm.proc/post_alert, 2)
else
if(connected_alarm.alarm_manager.clear_alarm(ALARM_ATMOS))
INVOKE_ASYNC(connected_alarm, /obj/machinery/airalarm.proc/post_alert, 0)
/obj/item/circuit_component/air_alarm_general/proc/set_mode(datum/port/input/port)
CIRCUIT_TRIGGER
if(!connected_alarm || connected_alarm.locked)
return
if(!mode.value)
return
connected_alarm.mode = options_map[mode.value]
connected_alarm.investigate_log("was turned to [connected_alarm.get_mode_name(connected_alarm.mode)] by [parent.get_creator()]")
INVOKE_ASYNC(connected_alarm, /obj/machinery/airalarm.proc/apply_mode, src)
/obj/item/circuit_component/air_alarm
display_name = "Air Alarm Core Control"
desc = "Controls levels of gases and their temperature as well as all vents and scrubbers in the room."
var/datum/port/input/option/air_alarm_options
@@ -925,25 +1035,51 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 24)
var/datum/port/input/max_1
var/datum/port/input/max_2
var/datum/port/input/set_data
var/datum/port/input/request_data
var/datum/port/output/pressure
var/datum/port/output/temperature
var/datum/port/output/gas_amount
var/datum/port/output/update_received
var/obj/machinery/airalarm/connected_alarm
var/list/options_map
ui_buttons = list(
"plus" = "add_new_component"
)
var/list/alarm_duplicates = list()
var/max_alarm_duplicates = 20
/obj/item/circuit_component/air_alarm/ui_perform_action(mob/user, action)
if(length(alarm_duplicates) >= max_alarm_duplicates)
return
if(action == "add_new_component")
var/obj/item/circuit_component/air_alarm/component = new /obj/item/circuit_component/air_alarm/duplicate(parent)
parent.add_component(component)
RegisterSignal(component, COMSIG_PARENT_QDELETING, .proc/on_duplicate_removed)
component.connected_alarm = connected_alarm
alarm_duplicates += component
/obj/item/circuit_component/air_alarm/proc/on_duplicate_removed(datum/source)
SIGNAL_HANDLER
alarm_duplicates -= source
/obj/item/circuit_component/air_alarm/populate_ports()
min_2 = add_input_port("Min 2", PORT_TYPE_NUMBER)
min_1 = add_input_port("Min 1", PORT_TYPE_NUMBER)
max_1 = add_input_port("Max 1", PORT_TYPE_NUMBER)
max_2 = add_input_port("Max 2", PORT_TYPE_NUMBER)
request_data = add_input_port("Request Atmosphere Data", PORT_TYPE_SIGNAL)
min_2 = add_input_port("Hazard Minimum", PORT_TYPE_NUMBER, trigger = null)
min_1 = add_input_port("Warning Minimum", PORT_TYPE_NUMBER, trigger = null)
max_1 = add_input_port("Warning Maximum", PORT_TYPE_NUMBER, trigger = null)
max_2 = add_input_port("Hazard Maximum", PORT_TYPE_NUMBER, trigger = null)
set_data = add_input_port("Set Limits", PORT_TYPE_SIGNAL, trigger = .proc/set_limits)
request_data = add_input_port("Request Data", PORT_TYPE_SIGNAL)
pressure = add_output_port("Pressure", PORT_TYPE_NUMBER)
temperature = add_output_port("Temperature", PORT_TYPE_NUMBER)
gas_amount = add_output_port("Chosen Gas Amount", PORT_TYPE_NUMBER)
update_received = add_output_port("Update Received", PORT_TYPE_SIGNAL)
/obj/item/circuit_component/air_alarm/populate_options()
var/static/list/component_options
@@ -960,6 +1096,25 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 24)
air_alarm_options = add_option_port("Air Alarm Options", component_options)
options_map = component_options
/obj/item/circuit_component/air_alarm/duplicate
display_name = "Air Alarm Control"
circuit_size = 0
ui_buttons = list()
/obj/item/circuit_component/air_alarm/duplicate/removed_from(obj/item/integrated_circuit/removed_from)
if(!QDELING(src))
qdel(src)
return ..()
/obj/item/circuit_component/air_alarm/duplicate/Destroy()
connected_alarm = null
return ..()
/obj/item/circuit_component/air_alarm/removed_from(obj/item/integrated_circuit/removed_from)
QDEL_LIST(alarm_duplicates)
return ..()
/obj/item/circuit_component/air_alarm/register_usb_parent(atom/movable/shell)
. = ..()
if(istype(shell, /obj/machinery/airalarm))
@@ -967,28 +1122,534 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 24)
/obj/item/circuit_component/air_alarm/unregister_usb_parent(atom/movable/shell)
connected_alarm = null
for(var/obj/item/circuit_component/air_alarm/alarm as anything in alarm_duplicates)
alarm.connected_alarm = null
return ..()
/obj/item/circuit_component/air_alarm/proc/set_limits()
CIRCUIT_TRIGGER
if(!connected_alarm || connected_alarm.locked)
return
var/current_option = air_alarm_options.value
if(!current_option)
return
var/datum/tlv/settings = connected_alarm.TLV[options_map[current_option]]
if(min_2.value != null)
settings.hazard_min = min_2.value
if(min_1.value != null)
settings.warning_min = min_1.value
if(max_1.value != null)
settings.warning_max = max_1.value
if(max_2.value != null)
settings.hazard_max = max_2.value
/obj/item/circuit_component/air_alarm/input_received(datum/port/input/port)
if(!connected_alarm || connected_alarm.locked)
return
var/current_option = air_alarm_options.value
if(COMPONENT_TRIGGERED_BY(request_data, port))
var/turf/alarm_turf = get_turf(connected_alarm)
var/datum/gas_mixture/environment = alarm_turf.return_air()
pressure.set_output(round(environment.return_pressure()))
temperature.set_output(round(environment.temperature))
if(ispath(options_map[current_option]))
gas_amount.set_output(round(environment.gases[options_map[current_option]][MOLES]))
var/turf/alarm_turf = get_turf(connected_alarm)
var/datum/gas_mixture/environment = alarm_turf.return_air()
pressure.set_output(round(environment.return_pressure()))
temperature.set_output(round(environment.temperature))
if(ispath(options_map[current_option]))
gas_amount.set_output(round(environment.gases[options_map[current_option]][MOLES]))
update_received.set_output(COMPONENT_SIGNAL)
/obj/item/circuit_component/air_alarm_scrubbers
display_name = "Air Alarm Scrubber Core Control"
desc = "Controls the scrubbers in the room."
var/datum/port/input/option/scrubbers
/// Enables the scrubber
var/datum/port/input/enable
/// Disables the scrubber
var/datum/port/input/disable
/// Enables siphoning
var/datum/port/input/enable_siphon
/// Disables siphoning
var/datum/port/input/disable_siphon
/// Enables extended range
var/datum/port/input/enable_extended_range
/// Disables extended range
var/datum/port/input/disable_extended_range
/// Gas to filter using the scrubber
var/datum/port/input/gas_filter
/// Sets the filter
var/datum/port/input/set_gas_filter
/// Requests an update of the data
var/datum/port/input/request_update
/// Whether the scrubber is enabled or not
var/datum/port/output/enabled
/// Whether the scrubber is siphoning or not
var/datum/port/output/is_siphoning
/// Information based on what the scrubber is filtering. Outputs null if the scrubber is siphoning
var/datum/port/output/filtering
/// Sent when an update is received
var/datum/port/output/update_received
var/obj/machinery/airalarm/connected_alarm
ui_buttons = list(
"plus" = "add_new_component"
)
var/static/list/filtering_map = list()
var/max_scrubber_duplicates = 20
var/list/scrubber_duplicates = list()
/obj/item/circuit_component/air_alarm_scrubbers/ui_perform_action(mob/user, action)
if(length(scrubber_duplicates) >= max_scrubber_duplicates)
return
var/datum/tlv/settings = connected_alarm.TLV[options_map[current_option]]
settings.hazard_min = min_2
settings.warning_min = min_1
settings.warning_max = max_1
settings.hazard_max = max_2
if(action == "add_new_component")
var/obj/item/circuit_component/air_alarm_scrubbers/component = new /obj/item/circuit_component/air_alarm_scrubbers/duplicate(parent)
parent.add_component(component)
RegisterSignal(component, COMSIG_PARENT_QDELETING, .proc/on_duplicate_removed)
component.connected_alarm = connected_alarm
component.scrubbers.possible_options = connected_alarm.my_area.air_scrub_info
scrubber_duplicates += component
/obj/item/circuit_component/air_alarm_scrubbers/proc/on_duplicate_removed(datum/source)
SIGNAL_HANDLER
scrubber_duplicates -= source
/obj/item/circuit_component/air_alarm_scrubbers/populate_options()
scrubbers = add_option_port("Scrubber", null)
/obj/item/circuit_component/air_alarm_scrubbers/populate_ports()
gas_filter = add_input_port("Gas To Filter", PORT_TYPE_LIST(PORT_TYPE_STRING), trigger = null)
set_gas_filter = add_input_port("Set Filter", PORT_TYPE_SIGNAL, trigger = .proc/set_gas_to_filter)
enable_extended_range = add_input_port("Enable Extra Range", PORT_TYPE_SIGNAL, trigger = .proc/toggle_range)
disable_extended_range = add_input_port("Disable Extra Range", PORT_TYPE_SIGNAL, trigger = .proc/toggle_range)
enable_siphon = add_input_port("Enable Siphon", PORT_TYPE_SIGNAL, trigger = .proc/toggle_siphon)
disable_siphon = add_input_port("Disable Siphon", PORT_TYPE_SIGNAL, trigger = .proc/toggle_siphon)
enable = add_input_port("Enable", PORT_TYPE_SIGNAL, trigger = .proc/toggle_scrubber)
disable = add_input_port("Disable", PORT_TYPE_SIGNAL, trigger = .proc/toggle_scrubber)
request_update = add_input_port("Request Data", PORT_TYPE_SIGNAL, trigger = .proc/update_data)
enabled = add_output_port("Enabled", PORT_TYPE_NUMBER)
is_siphoning = add_output_port("Siphoning", PORT_TYPE_NUMBER)
filtering = add_output_port("Filtered Gases", PORT_TYPE_LIST(PORT_TYPE_STRING))
update_received = add_output_port("Update Received", PORT_TYPE_SIGNAL)
/obj/item/circuit_component/air_alarm_scrubbers/duplicate
display_name = "Air Alarm Scrubber Control"
circuit_size = 0
ui_buttons = list()
/obj/item/circuit_component/air_alarm_scrubbers/duplicate/Destroy()
connected_alarm = null
return ..()
/obj/item/circuit_component/air_alarm_scrubbers/duplicate/removed_from(obj/item/integrated_circuit/removed_from)
if(!QDELING(src))
qdel(src)
return ..()
/obj/item/circuit_component/air_alarm_scrubbers/removed_from(obj/item/integrated_circuit/removed_from)
QDEL_LIST(scrubber_duplicates)
return ..()
/obj/item/circuit_component/air_alarm_scrubbers/register_usb_parent(atom/movable/shell)
. = ..()
if(istype(shell, /obj/machinery/airalarm))
connected_alarm = shell
scrubbers.possible_options = connected_alarm.my_area.air_scrub_info
/obj/item/circuit_component/air_alarm_scrubbers/unregister_usb_parent(atom/movable/shell)
connected_alarm = null
scrubbers.possible_options = null
for(var/obj/item/circuit_component/air_alarm_scrubbers/scrubber as anything in scrubber_duplicates)
scrubber.connected_alarm = null
return ..()
/obj/item/circuit_component/air_alarm_scrubbers/get_ui_notices()
. = ..()
var/static/list/meta_data = list()
if(length(meta_data) == 0)
for(var/typepath as anything in GLOB.meta_gas_info)
meta_data += GLOB.meta_gas_info[typepath][META_GAS_ID]
. += create_table_notices(meta_data, column_name = "Gas", column_name_plural = "Gases")
/obj/item/circuit_component/air_alarm_scrubbers/proc/set_gas_to_filter(datum/port/input/port)
CIRCUIT_TRIGGER
INVOKE_ASYNC(src, .proc/set_gas_filter_async, port)
/obj/item/circuit_component/air_alarm_scrubbers/proc/set_gas_filter_async(datum/port/input/port)
if(!connected_alarm || connected_alarm.locked)
return
var/scrubber_id = scrubbers.value
var/list/valid_filters = list()
for(var/info in gas_filter.value)
if(gas_id2path(info) == "")
continue
valid_filters += info
connected_alarm.send_signal(scrubber_id, list(
"set_filters" = valid_filters,
))
/obj/item/circuit_component/air_alarm_scrubbers/proc/toggle_scrubber(datum/port/input/port)
CIRCUIT_TRIGGER
INVOKE_ASYNC(src, .proc/toggle_scrubber_async, port)
/obj/item/circuit_component/air_alarm_scrubbers/proc/toggle_scrubber_async(datum/port/input/port)
if(!connected_alarm || connected_alarm.locked)
return
var/scrubber_id = scrubbers.value
if(port == enable)
connected_alarm.send_signal(scrubber_id, list(
"power" = TRUE,
))
else
connected_alarm.send_signal(scrubber_id, list(
"power" = FALSE,
))
/obj/item/circuit_component/air_alarm_scrubbers/proc/toggle_range(datum/port/input/port)
CIRCUIT_TRIGGER
INVOKE_ASYNC(src, .proc/toggle_range_async, port)
/obj/item/circuit_component/air_alarm_scrubbers/proc/toggle_range_async(datum/port/input/port)
if(!connected_alarm || connected_alarm.locked)
return
var/scrubber_id = scrubbers.value
if(port == enable_extended_range)
connected_alarm.send_signal(scrubber_id, list(
"widenet" = TRUE,
))
else
connected_alarm.send_signal(scrubber_id, list(
"widenet" = FALSE,
))
/obj/item/circuit_component/air_alarm_scrubbers/proc/toggle_siphon(datum/port/input/port)
CIRCUIT_TRIGGER
INVOKE_ASYNC(src, .proc/toggle_siphon_async, port)
/obj/item/circuit_component/air_alarm_scrubbers/proc/toggle_siphon_async(datum/port/input/port)
if(!connected_alarm || connected_alarm.locked)
return
var/scrubber_id = scrubbers.value
if(port == enable_siphon)
connected_alarm.send_signal(scrubber_id, list(
"scrubbing" = FALSE,
))
else
connected_alarm.send_signal(scrubber_id, list(
"scrubbing" = TRUE,
))
/obj/item/circuit_component/air_alarm_scrubbers/proc/update_data()
CIRCUIT_TRIGGER
if(!connected_alarm || connected_alarm.locked)
return
var/scrubber_id = scrubbers.value
var/list/info = connected_alarm.my_area.air_scrub_info[scrubber_id]
if(!info || info["frequency"] != connected_alarm.frequency)
return
enabled.set_value(info["power"])
is_siphoning.set_value(!info["scrubbing"])
var/list/filtered = list()
for(var/list/data as anything in info["filter_types"])
if(data["enabled"])
filtered += data["gas_id"]
filtering.set_value(filtered)
update_received.set_value(COMPONENT_SIGNAL)
/obj/item/circuit_component/air_alarm_vents
display_name = "Air Alarm Vent Core Control"
desc = "Controls the vents in the room."
var/datum/port/input/option/vents
/// Enables the vent
var/datum/port/input/enable
/// Disables the vent
var/datum/port/input/disable
/// Enables siphoning
var/datum/port/input/enable_siphon
/// Disables siphoning
var/datum/port/input/disable_siphon
/// Enables external
var/datum/port/input/enable_external
/// Disables external
var/datum/port/input/disable_external
/// External target pressure
var/datum/port/input/external_pressure
/// Enables internal
var/datum/port/input/enable_internal
/// Disables internal
var/datum/port/input/disable_internal
/// Internal target pressure
var/datum/port/input/internal_pressure
/// Requests an update of the data
var/datum/port/input/request_update
/// Whether the scrubber is enabled or not
var/datum/port/output/enabled
/// Whether the scrubber is siphoning or not
var/datum/port/output/is_siphoning
/// Whether internal pressure is on or not
var/datum/port/output/internal_on
/// Whether external pressure is on or not
var/datum/port/output/external_on
/// Reported external pressure
var/datum/port/output/current_external_pressure
/// Reported internal pressure
var/datum/port/output/current_internal_pressure
/// Sent when an update is received
var/datum/port/output/update_received
var/obj/machinery/airalarm/connected_alarm
ui_buttons = list(
"plus" = "add_new_component"
)
var/static/list/filtering_map = list()
var/max_vent_duplicates = 20
var/list/vent_duplicates = list()
/obj/item/circuit_component/air_alarm_vents/ui_perform_action(mob/user, action)
if(length(vent_duplicates) >= max_vent_duplicates)
return
if(action == "add_new_component")
var/obj/item/circuit_component/air_alarm_vents/component = new /obj/item/circuit_component/air_alarm_vents/duplicate(parent)
parent.add_component(component)
RegisterSignal(component, COMSIG_PARENT_QDELETING, .proc/on_duplicate_removed)
vent_duplicates += component
component.connected_alarm = connected_alarm
component.vents.possible_options = connected_alarm.my_area.air_vent_info
/obj/item/circuit_component/air_alarm_vents/proc/on_duplicate_removed(datum/source)
SIGNAL_HANDLER
vent_duplicates -= source
/obj/item/circuit_component/air_alarm_vents/populate_options()
vents = add_option_port("Vent", null)
/obj/item/circuit_component/air_alarm_vents/populate_ports()
external_pressure = add_input_port("External Pressure", PORT_TYPE_NUMBER, trigger = .proc/set_external_pressure)
internal_pressure = add_input_port("Internal Pressure", PORT_TYPE_NUMBER, trigger = .proc/set_internal_pressure)
enable_external = add_input_port("Enable External", PORT_TYPE_SIGNAL, trigger = .proc/toggle_external)
disable_external = add_input_port("Disable External", PORT_TYPE_SIGNAL, trigger = .proc/toggle_external)
enable_internal = add_input_port("Enable Internal", PORT_TYPE_SIGNAL, trigger = .proc/toggle_internal)
disable_internal = add_input_port("Disable Internal", PORT_TYPE_SIGNAL, trigger = .proc/toggle_internal)
enable_siphon = add_input_port("Enable Siphon", PORT_TYPE_SIGNAL, trigger = .proc/toggle_siphon)
disable_siphon = add_input_port("Disable Siphon", PORT_TYPE_SIGNAL, trigger = .proc/toggle_siphon)
enable = add_input_port("Enable", PORT_TYPE_SIGNAL, trigger = .proc/toggle_vent)
disable = add_input_port("Disable", PORT_TYPE_SIGNAL, trigger = .proc/toggle_vent)
request_update = add_input_port("Request Data", PORT_TYPE_SIGNAL, trigger = .proc/update_data)
enabled = add_output_port("Enabled", PORT_TYPE_NUMBER)
is_siphoning = add_output_port("Siphoning", PORT_TYPE_NUMBER)
external_on = add_output_port("External On", PORT_TYPE_NUMBER)
internal_on = add_output_port("Internal On", PORT_TYPE_NUMBER)
current_external_pressure = add_output_port("External Pressure", PORT_TYPE_NUMBER)
current_internal_pressure = add_output_port("Internal Pressure", PORT_TYPE_NUMBER)
update_received = add_output_port("Update Received", PORT_TYPE_SIGNAL)
/obj/item/circuit_component/air_alarm_vents/duplicate
display_name = "Air Alarm Vent Control"
circuit_size = 0
ui_buttons = list()
/obj/item/circuit_component/air_alarm_vents/duplicate/removed_from(obj/item/integrated_circuit/removed_from)
if(!QDELING(src))
qdel(src)
return ..()
/obj/item/circuit_component/air_alarm_vents/duplicate/Destroy()
connected_alarm = null
return ..()
/obj/item/circuit_component/air_alarm_vents/removed_from(obj/item/integrated_circuit/removed_from)
QDEL_LIST(vent_duplicates)
return ..()
/obj/item/circuit_component/air_alarm_vents/register_usb_parent(atom/movable/shell)
. = ..()
if(istype(shell, /obj/machinery/airalarm))
connected_alarm = shell
vents.possible_options = connected_alarm.my_area.air_vent_info
/obj/item/circuit_component/air_alarm_vents/unregister_usb_parent(atom/movable/shell)
connected_alarm = null
vents.possible_options = null
for(var/obj/item/circuit_component/air_alarm_vents/vent as anything in vent_duplicates)
vent.connected_alarm = null
return ..()
/obj/item/circuit_component/air_alarm_vents/proc/toggle_vent(datum/port/input/port)
CIRCUIT_TRIGGER
INVOKE_ASYNC(src, .proc/toggle_vent_async, port)
/obj/item/circuit_component/air_alarm_vents/proc/toggle_vent_async(datum/port/input/port)
if(!connected_alarm || connected_alarm.locked)
return
var/vent_id = vents.value
if(port == enable)
connected_alarm.send_signal(vent_id, list(
"power" = TRUE,
))
else
connected_alarm.send_signal(vent_id, list(
"power" = FALSE,
))
#define EXT_BOUND 1
#define INT_BOUND 2
#define NO_BOUND 3
/obj/item/circuit_component/air_alarm_vents/proc/toggle_external(datum/port/input/port)
CIRCUIT_TRIGGER
INVOKE_ASYNC(src, .proc/toggle_external_async, port)
/obj/item/circuit_component/air_alarm_vents/proc/toggle_external_async(datum/port/input/port)
if(!connected_alarm || connected_alarm.locked)
return
var/vent_id = vents.value
var/list/info = connected_alarm.my_area.air_vent_info[vent_id]
if(!info || info["frequency"] != connected_alarm.frequency)
return
if(port == enable_external)
connected_alarm.send_signal(vent_id, list(
"checks" = (info["checks"] | EXT_BOUND),
))
else
connected_alarm.send_signal(vent_id, list(
"checks" = (info["checks"] & ~EXT_BOUND),
))
/obj/item/circuit_component/air_alarm_vents/proc/toggle_internal(datum/port/input/port)
CIRCUIT_TRIGGER
INVOKE_ASYNC(src, .proc/toggle_internal_async, port)
/obj/item/circuit_component/air_alarm_vents/proc/toggle_internal_async(datum/port/input/port)
if(!connected_alarm || connected_alarm.locked)
return
var/vent_id = vents.value
var/list/info = connected_alarm.my_area.air_vent_info[vent_id]
if(!info || info["frequency"] != connected_alarm.frequency)
return
if(port == enable_internal)
connected_alarm.send_signal(vent_id, list(
"checks" = (info["checks"] | INT_BOUND),
))
else
connected_alarm.send_signal(vent_id, list(
"checks" = (info["checks"] & ~INT_BOUND),
))
/obj/item/circuit_component/air_alarm_vents/proc/set_internal_pressure(datum/port/input/port)
CIRCUIT_TRIGGER
INVOKE_ASYNC(src, .proc/set_internal_pressure_async, port)
/obj/item/circuit_component/air_alarm_vents/proc/set_internal_pressure_async(datum/port/input/port)
if(!connected_alarm || connected_alarm.locked)
return
var/vent_id = vents.value
connected_alarm.send_signal(vent_id, list(
"set_internal_pressure" = internal_pressure.value || 0,
))
/obj/item/circuit_component/air_alarm_vents/proc/set_external_pressure(datum/port/input/port)
CIRCUIT_TRIGGER
INVOKE_ASYNC(src, .proc/set_external_pressure_async, port)
/obj/item/circuit_component/air_alarm_vents/proc/set_external_pressure_async(datum/port/input/port)
if(!connected_alarm || connected_alarm.locked)
return
var/vent_id = vents.value
connected_alarm.send_signal(vent_id, list(
"set_external_pressure" = external_pressure.value || 0,
))
/obj/item/circuit_component/air_alarm_vents/proc/toggle_siphon(datum/port/input/port)
CIRCUIT_TRIGGER
INVOKE_ASYNC(src, .proc/toggle_siphon_async, port)
/obj/item/circuit_component/air_alarm_vents/proc/toggle_siphon_async(datum/port/input/port)
if(!connected_alarm || connected_alarm.locked)
return
var/scrubber_id = vents.value
if(port == enable_siphon)
connected_alarm.send_signal(scrubber_id, list(
"direction" = FALSE,
))
else
connected_alarm.send_signal(scrubber_id, list(
"direction" = TRUE,
))
/obj/item/circuit_component/air_alarm_vents/proc/update_data()
CIRCUIT_TRIGGER
if(!connected_alarm || connected_alarm.locked)
return
var/vent_id = vents.value
var/list/info = connected_alarm.my_area.air_vent_info[vent_id]
if(!info || info["frequency"] != connected_alarm.frequency)
return
enabled.set_value(info["power"])
is_siphoning.set_value(!info["direction"])
internal_on.set_value(!!(info["checks"] & INT_BOUND))
current_internal_pressure.set_value(info["internal"])
external_on.set_value(!!(info["checks"] & EXT_BOUND))
current_external_pressure.set_value(info["external"])
update_received.set_value(COMPONENT_SIGNAL)
#undef EXT_BOUND
#undef INT_BOUND
#undef NO_BOUND
#undef AALARM_MODE_SCRUBBING
#undef AALARM_MODE_VENTING

View File

@@ -196,8 +196,8 @@
ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, ROUNDSTART_TRAIT)
alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER, ALARM_CAMERA, ALARM_BURGLAR, ALARM_MOTION), list(z), camera_view = TRUE)
RegisterSignal(alert_control.listener, COMSIG_ALARM_TRIGGERED, .proc/alarm_triggered)
RegisterSignal(alert_control.listener, COMSIG_ALARM_CLEARED, .proc/alarm_cleared)
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_TRIGGERED, .proc/alarm_triggered)
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_CLEARED, .proc/alarm_cleared)
/mob/living/silicon/ai/key_down(_key, client/user)
if(findtext(_key, "numpad")) //if it's a numpad number, we can convert it to just the number

View File

@@ -80,8 +80,8 @@
diag_hud_set_borgcell()
logevent("System brought online.")
alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER, ALARM_CAMERA, ALARM_BURGLAR, ALARM_MOTION), list(z))
RegisterSignal(alert_control.listener, COMSIG_ALARM_TRIGGERED, .proc/alarm_triggered)
RegisterSignal(alert_control.listener, COMSIG_ALARM_CLEARED, .proc/alarm_cleared)
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_TRIGGERED, .proc/alarm_triggered)
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_CLEARED, .proc/alarm_cleared)
alert_control.listener.RegisterSignal(src, COMSIG_LIVING_DEATH, /datum/alarm_listener/proc/prevent_alarm_changes)
alert_control.listener.RegisterSignal(src, COMSIG_LIVING_REVIVE, /datum/alarm_listener/proc/allow_alarm_changes)

View File

@@ -189,8 +189,8 @@
ADD_TRAIT(src, TRAIT_LITERATE, INNATE_TRAIT)
listener = new(list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER), list(z))
RegisterSignal(listener, COMSIG_ALARM_TRIGGERED, .proc/alarm_triggered)
RegisterSignal(listener, COMSIG_ALARM_CLEARED, .proc/alarm_cleared)
RegisterSignal(listener, COMSIG_ALARM_LISTENER_TRIGGERED, .proc/alarm_triggered)
RegisterSignal(listener, COMSIG_ALARM_LISTENER_CLEARED, .proc/alarm_cleared)
listener.RegisterSignal(src, COMSIG_LIVING_DEATH, /datum/alarm_listener/proc/prevent_alarm_changes)
listener.RegisterSignal(src, COMSIG_LIVING_REVIVE, /datum/alarm_listener/proc/allow_alarm_changes)

View File

@@ -19,7 +19,7 @@
//Or if we're on station. Otherwise, die.
var/list/allowed_areas = GLOB.the_station_areas + typesof(/area/mine)
alert_control = new(computer, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER), listener_areas = allowed_areas)
RegisterSignal(alert_control.listener, list(COMSIG_ALARM_TRIGGERED, COMSIG_ALARM_CLEARED), .proc/update_alarm_display)
RegisterSignal(alert_control.listener, list(COMSIG_ALARM_LISTENER_TRIGGERED, COMSIG_ALARM_LISTENER_CLEARED), .proc/update_alarm_display)
return ..()
/datum/computer_file/program/alarm_monitor/Destroy()

View File

@@ -373,15 +373,15 @@
* Returns a list that can then be added to the return list in get_ui_notices()
* Used by components to list their available columns. Recommended to use at the end of get_ui_notices()
*/
/obj/item/circuit_component/proc/create_table_notices(list/entries)
/obj/item/circuit_component/proc/create_table_notices(list/entries, column_name = "Column", column_name_plural = "Columns")
SHOULD_BE_PURE(TRUE)
SHOULD_NOT_OVERRIDE(TRUE)
. = list()
. += create_ui_notice("Available Columns:", "grey", "question-circle")
. += create_ui_notice("Available [column_name_plural]:", "grey", "question-circle")
for(var/entry in entries)
. += create_ui_notice("Column Name: '[entry]'", "grey", "columns")
. += create_ui_notice("[column_name] Name: '[entry]'", "grey", "columns")
/**
* Called when a circuit component is added to an object with a USB port.

View File

@@ -221,13 +221,13 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
*/
/obj/item/integrated_circuit/proc/add_component(obj/item/circuit_component/to_add, mob/living/user)
if(to_add.parent)
return
return FALSE
if(SEND_SIGNAL(src, COMSIG_CIRCUIT_ADD_COMPONENT, to_add, user) & COMPONENT_CANCEL_ADD_COMPONENT)
return
return FALSE
if(!to_add.add_to(src))
return
return FALSE
var/success = FALSE
if(user)
@@ -236,7 +236,7 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
success = to_add.forceMove(src)
if(!success)
return
return FALSE
to_add.rel_x = rand(COMPONENT_MIN_RANDOM_POS, COMPONENT_MAX_RANDOM_POS) - screen_x
to_add.rel_y = rand(COMPONENT_MIN_RANDOM_POS, COMPONENT_MAX_RANDOM_POS) - screen_y

View File

@@ -193,4 +193,4 @@
return
if(result["should_open"])
return COMPONENT_AIRLOCK_SHELL_ALLOW
return COMPONENT_AIRLOCK_SHELL_ALLOW

View File

@@ -11,6 +11,7 @@ type Data = {
passedCycleId: number;
regions: string[];
accesses: string[];
shell: BooleanLike;
};
export const AirlockElectronics = (props, context) => {
@@ -22,6 +23,7 @@ export const AirlockElectronics = (props, context) => {
passedCycleId,
regions = [],
unres_direction,
shell,
} = data;
return (
@@ -29,6 +31,16 @@ export const AirlockElectronics = (props, context) => {
<Window.Content>
<Section title="Main">
<LabeledList>
<LabeledList.Item label="Integrated Circuit Shell">
<Button.Checkbox
content="Shell"
checked={shell}
onClick={() => {
act('set_shell', { on: !shell });
}}
tooltip="Whether this airlock can have an integrated circuit placed inside of it or not."
/>
</LabeledList.Item>
<LabeledList.Item label="Access Required">
<Button
icon={oneAccess ? 'unlock' : 'lock'}