[MIRROR] Airlock Construction (#9580)

Co-authored-by: Heroman3003 <31296024+Heroman3003@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2024-12-05 08:04:35 -07:00
committed by GitHub
parent 5f03a3f37f
commit 67fe8c3c8e
23 changed files with 662 additions and 164 deletions

View File

@@ -308,8 +308,11 @@
radio_filter_in = frequency==1439?(RADIO_FROM_AIRALARM):null radio_filter_in = frequency==1439?(RADIO_FROM_AIRALARM):null
radio_filter_out = frequency==1439?(RADIO_TO_AIRALARM):null radio_filter_out = frequency==1439?(RADIO_TO_AIRALARM):null
if(frequency) if(frequency)
radio_connection = register_radio(src, frequency, frequency, radio_filter_in) set_frequency(frequency)
src.broadcast_status()
/obj/machinery/atmospherics/unary/vent_pump/proc/set_frequency(new_frequency)
radio_connection = register_radio(src, frequency, new_frequency, radio_filter_in)
frequency = new_frequency
/obj/machinery/atmospherics/unary/vent_pump/receive_signal(datum/signal/signal) /obj/machinery/atmospherics/unary/vent_pump/receive_signal(datum/signal/signal)
if(stat & (NOPOWER|BROKEN)) if(stat & (NOPOWER|BROKEN))
@@ -407,6 +410,20 @@
else else
to_chat(user, span_warning("You need more welding fuel to complete this task.")) to_chat(user, span_warning("You need more welding fuel to complete this task."))
return 1 return 1
if(W.has_tool_quality(TOOL_MULTITOOL))
var/choice = tgui_alert(user, "[src] has an ID of \"[id_tag]\" and a frequency of [frequency]. What would you like to change?", "[src] ID", list("ID Tag", "Frequency", "Nothing"))
switch(choice)
if("ID Tag")
var/new_id = tgui_input_text(user, "[src] has an ID of \"[id_tag]\". What would you like it to be?", "[src] ID", id_tag, 30, FALSE, TRUE)
if(new_id)
id_tag = new_id
if("Frequency")
var/new_frequency = tgui_input_number(user, "[src] has a frequency of [frequency]. What would you like it to be?", "[src] frequency", frequency, RADIO_HIGH_FREQ, RADIO_LOW_FREQ)
if(new_frequency)
new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ)
set_frequency(new_frequency)
return TRUE
else else
..() ..()

View File

@@ -8,6 +8,7 @@
holder_type = /obj/machinery/door/airlock holder_type = /obj/machinery/door/airlock
wire_count = 12 wire_count = 12
proper_name = "Airlock" proper_name = "Airlock"
tgui_template = "WiresAirlock"
/datum/wires/airlock/interactable(mob/user) /datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder var/obj/machinery/door/airlock/A = holder
@@ -41,6 +42,39 @@
. += "The 'Check Timing Mechanism' light is [(A.normalspeed == 0 && haspower) ? "on" : "off"]." . += "The 'Check Timing Mechanism' light is [(A.normalspeed == 0 && haspower) ? "on" : "off"]."
. += "The IDScan light is [(A.aiDisabledIdScanner == 0 && haspower) ? "on" : "off."]" . += "The IDScan light is [(A.aiDisabledIdScanner == 0 && haspower) ? "on" : "off."]"
/datum/wires/airlock/tgui_data(mob/user)
var/list/data = ..()
var/obj/machinery/door/airlock/A = holder
data["id_tag"] = A.id_tag
data["frequency"] = A.radio_connection ? A.frequency : null
data["min_freq"] = RADIO_LOW_FREQ
data["max_freq"] = RADIO_HIGH_FREQ
return data
/datum/wires/airlock/tgui_act(action, list/params)
. = ..()
if(.)
return
var/obj/machinery/door/airlock/A = holder
switch(action)
if("set_id_tag")
var/new_id = tgui_input_text(usr, "Enter a new ID tag for [A]", "[A] ID Tag", A.id_tag, 30, FALSE, TRUE)
if(new_id)
A.id_tag = new_id
return TRUE
if("set_frequency")
A.set_frequency(sanitize_frequency(text2num(params["freq"]), RADIO_LOW_FREQ, RADIO_HIGH_FREQ))
return TRUE
if("clear_frequency")
A.set_frequency(null)
return TRUE
/datum/wires/airlock/on_cut(wire, mend) /datum/wires/airlock/on_cut(wire, mend)
var/obj/machinery/door/airlock/A = holder var/obj/machinery/door/airlock/A = holder
switch(wire) switch(wire)

View File

@@ -9,6 +9,8 @@
/// The display name for the TGUI window. For example, given the var is "APC"... /// The display name for the TGUI window. For example, given the var is "APC"...
/// When the TGUI window is opened, "wires" will be appended to it's title, and it would become "APC wires". /// When the TGUI window is opened, "wires" will be appended to it's title, and it would become "APC wires".
var/proper_name = "Unknown" var/proper_name = "Unknown"
/// The template to use for TGUI.
var/tgui_template = "Wires"
/// The total number of wires that our holder atom has. /// The total number of wires that our holder atom has.
var/wire_count = NONE var/wire_count = NONE
/// A list of all wires. For a list of valid wires defines that can go here, see `code/__DEFINES/wires.dm` /// A list of all wires. For a list of valid wires defines that can go here, see `code/__DEFINES/wires.dm`
@@ -92,7 +94,7 @@
/datum/wires/tgui_interact(mob/user, datum/tgui/ui = null) /datum/wires/tgui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui) ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, "Wires", "[proper_name] wires") ui = new(user, src, tgui_template, "[proper_name] wires")
ui.open() ui.open()
/datum/wires/tgui_state(mob/user) /datum/wires/tgui_state(mob/user)

View File

@@ -125,10 +125,12 @@
return return
/obj/machinery/door/airlock/proc/set_frequency(new_frequency) /obj/machinery/door/airlock/proc/set_frequency(new_frequency)
radio_connection = null
radio_controller.remove_object(src, frequency) radio_controller.remove_object(src, frequency)
frequency = new_frequency
if(new_frequency) if(new_frequency)
frequency = new_frequency radio_connection = radio_controller.add_object(src, new_frequency, RADIO_AIRLOCK)
radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK)
/obj/machinery/door/airlock/Initialize() /obj/machinery/door/airlock/Initialize()
@@ -152,6 +154,7 @@
anchored = TRUE anchored = TRUE
power_channel = ENVIRON power_channel = ENVIRON
circuit = /obj/item/circuitboard/airlock_cycling
var/id_tag var/id_tag
var/master_tag var/master_tag
@@ -165,6 +168,9 @@
var/previousPressure var/previousPressure
/obj/machinery/airlock_sensor/update_icon() /obj/machinery/airlock_sensor/update_icon()
if(panel_open)
icon_state = "airlock_sensor_open"
return
if(on) if(on)
if(alert) if(alert)
icon_state = "airlock_sensor_alert" icon_state = "airlock_sensor_alert"
@@ -216,6 +222,45 @@
radio_controller.remove_object(src,frequency) radio_controller.remove_object(src,frequency)
return ..() return ..()
/obj/machinery/airlock_sensor/examine(mob/user, infix, suffix)
. = ..()
if(in_range(src, user))
. += "It has a master tag of \"[master_tag]\"."
. += "It has an ID tag of \"[id_tag]\"."
. += "It has a frequency of [frequency]."
. += "It has a command of \"[command]\"."
if(panel_open)
. += "It's panel is open."
/obj/machinery/airlock_sensor/attackby(obj/item/I, mob/user)
if(default_deconstruction_screwdriver(user, I))
return
if(default_deconstruction_crowbar(user, I))
return
if(I.has_tool_quality(TOOL_MULTITOOL))
var/choice = tgui_alert(user, "What would you like to configure?", "[src] Configuration", list("Master Tag", "ID Tag", "Frequency", "Command", "None"))
switch(choice)
if("Master Tag")
var/new_value = tgui_input_text(user, "The current master tag is \"[master_tag]\", what would you like it to be?", "[src] Master Tag", master_tag, 30, encode = TRUE)
if(new_value)
master_tag = new_value
if("ID Tag")
var/new_value = tgui_input_text(user, "The current id tag is \"[id_tag]\", what would you like it to be?", "[src] ID Tag", id_tag, 30, encode = TRUE)
if(new_value)
id_tag = new_value
if("Frequency")
var/new_frequency = tgui_input_number(user, "[src] has a frequency of [frequency]. What would you like it to be?", "[src] frequency", frequency, RADIO_HIGH_FREQ, RADIO_LOW_FREQ)
if(new_frequency)
new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ)
set_frequency(new_frequency)
if("Command")
var/new_value = tgui_input_text(user, "The current command is \"[command]\", what would you like it to be? Valid options include: cycle, cycle_interior, cycle_exterior.", "[src] command", command, encode = TRUE)
if(new_value)
command = new_value
return TRUE
return ..()
/obj/machinery/airlock_sensor/airlock_interior /obj/machinery/airlock_sensor/airlock_interior
command = "cycle_interior" command = "cycle_interior"
@@ -237,6 +282,7 @@
anchored = TRUE anchored = TRUE
power_channel = ENVIRON power_channel = ENVIRON
circuit = /obj/item/circuitboard/airlock_cycling
var/master_tag var/master_tag
var/frequency = 1449 var/frequency = 1449
@@ -246,18 +292,50 @@
var/on = 1 var/on = 1
/obj/machinery/access_button/update_icon() /obj/machinery/access_button/update_icon()
if(on) if(panel_open)
icon_state = "access_button_open"
else if(on)
icon_state = "access_button_standby" icon_state = "access_button_standby"
else else
icon_state = "access_button_off" icon_state = "access_button_off"
/obj/machinery/access_button/examine(mob/user, infix, suffix)
. = ..()
if(in_range(src, user))
. += "It has a master tag of \"[master_tag]\"."
. += "It has a frequency of \"[frequency]\"."
. += "It is sending a command of \"[command]\"."
if(panel_open)
. += "It's panel is open."
/obj/machinery/access_button/attackby(obj/item/I as obj, mob/user as mob) /obj/machinery/access_button/attackby(obj/item/I as obj, mob/user as mob)
//Swiping ID on the access button //Swiping ID on the access button
if (istype(I, /obj/item/card/id) || istype(I, /obj/item/pda)) if (istype(I, /obj/item/card/id) || istype(I, /obj/item/pda))
attack_hand(user) attack_hand(user)
return return
if(default_deconstruction_screwdriver(user, I))
return
if(default_deconstruction_crowbar(user, I))
return
if(I.has_tool_quality(TOOL_MULTITOOL))
var/choice = tgui_alert(user, "What would you like to change?", "[src] Settings", list("Tag", "Frequency", "Command", "None"))
switch(choice)
if("Tag")
var/new_id = tgui_input_text(user, "[src] has an master tag of \"[master_tag]\". What would you like it to be?", "[src] ID", master_tag, 30, FALSE, TRUE)
if(new_id)
master_tag = new_id
if("Frequency")
var/new_frequency = tgui_input_number(user, "[src] has a frequency of [frequency]. What would you like it to be?", "[src] frequency", frequency, RADIO_HIGH_FREQ, RADIO_LOW_FREQ)
if(new_frequency)
new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ)
set_frequency(new_frequency)
if("Command")
var/new_command = tgui_input_text(user, "[src] has a command of \"[command]\". Valid options include: cycle, cycle_interior, cycle_exterior", "[src] command", command, encode = TRUE)
if(new_command)
command = new_command
return TRUE
..() ..()
/obj/machinery/access_button/attack_hand(mob/user) /obj/machinery/access_button/attack_hand(mob/user)

View File

@@ -17,6 +17,8 @@
valid_actions = list("cycle_ext", "cycle_int", "force_ext", "force_int", "abort", "purge", "secure") valid_actions = list("cycle_ext", "cycle_int", "force_ext", "force_int", "abort", "purge", "secure")
layer = ABOVE_WINDOW_LAYER layer = ABOVE_WINDOW_LAYER
var/deconstructable = FALSE
/obj/machinery/embedded_controller/radio/airlock/Destroy() /obj/machinery/embedded_controller/radio/airlock/Destroy()
// TODO - Leshana - Implement dummy terminals // TODO - Leshana - Implement dummy terminals
//for(var/thing in dummy_terminals) //for(var/thing in dummy_terminals)
@@ -30,12 +32,75 @@
if(!allowed(user)) if(!allowed(user))
return min(STATUS_UPDATE, .) return min(STATUS_UPDATE, .)
/obj/machinery/embedded_controller/radio/airlock/attackby(obj/item/I, mob/user)
if(deconstructable)
if(default_deconstruction_screwdriver(user, I))
return
if(default_deconstruction_crowbar(user, I))
return
. = ..()
/obj/machinery/embedded_controller/radio/airlock/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["panel_open"] = panel_open
data["tags"] = null
data["frequency"] = null
data["min_freq"] = null
data["max_freq"] = null
if(panel_open)
var/datum/embedded_program/airlock/airlock_program = program
data["tags"] = airlock_program.get_all_tags()
data["frequency"] = frequency
data["min_freq"] = RADIO_LOW_FREQ
data["max_freq"] = RADIO_HIGH_FREQ
return data
/obj/machinery/embedded_controller/radio/airlock/tgui_act(action, params)
. = ..()
if(.)
return
if(!panel_open)
return
switch(action)
if("edit_tag")
var/datum/embedded_program/airlock/airlock_program = program
var/tag = params["tag"]
var/current = airlock_program.get_tag(tag)
var/new_tag = tgui_input_text(usr, "What would you like to set [tag] to?", "New [tag]?", current, 30, FALSE, TRUE)
if(new_tag)
airlock_program.set_tag(tag, new_tag)
return TRUE
if("set_frequency")
set_frequency(sanitize_frequency(text2num(params["freq"]), RADIO_LOW_FREQ, RADIO_HIGH_FREQ))
return TRUE
/obj/machinery/embedded_controller/radio/airlock/update_icon()
cut_overlays()
if(panel_open)
add_overlay("airlock_control_open")
//Advanced airlock controller for when you want a more versatile airlock controller - useful for turning simple access control rooms into airlocks //Advanced airlock controller for when you want a more versatile airlock controller - useful for turning simple access control rooms into airlocks
/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller /obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller
name = "Advanced Airlock Controller" name = "Advanced Airlock Controller"
deconstructable = TRUE
circuit = /obj/item/circuitboard/airlock_cycling
/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller/tgui_data(mob/user) /obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller/tgui_data(mob/user)
. = list( var/list/data = ..()
// Deliberately not using UNTYPED_LIST_ADD, we want this to be appended
data += list(
"chamber_pressure" = round(program.memory["chamber_sensor_pressure"]), "chamber_pressure" = round(program.memory["chamber_sensor_pressure"]),
"external_pressure" = round(program.memory["external_sensor_pressure"]), "external_pressure" = round(program.memory["external_sensor_pressure"]),
"internal_pressure" = round(program.memory["internal_sensor_pressure"]), "internal_pressure" = round(program.memory["internal_sensor_pressure"]),
@@ -45,15 +110,22 @@
"internalTemplateName" = "AirlockConsoleAdvanced", "internalTemplateName" = "AirlockConsoleAdvanced",
) )
return data
//Airlock controller for airlock control - most airlocks on the station use this //Airlock controller for airlock control - most airlocks on the station use this
/obj/machinery/embedded_controller/radio/airlock/airlock_controller /obj/machinery/embedded_controller/radio/airlock/airlock_controller
name = "Airlock Controller" name = "Airlock Controller"
tag_secure = 1 tag_secure = 1
valid_actions = list("cycle_ext", "cycle_int", "force_ext", "force_int", "abort") valid_actions = list("cycle_ext", "cycle_int", "force_ext", "force_int", "abort")
deconstructable = TRUE
circuit = /obj/item/circuitboard/airlock_cycling
/obj/machinery/embedded_controller/radio/airlock/airlock_controller/tgui_data(mob/user) /obj/machinery/embedded_controller/radio/airlock/airlock_controller/tgui_data(mob/user)
. = list( var/list/data = ..()
// Deliberately not using UNTYPED_LIST_ADD, we want this to be appended
data += list(
"chamber_pressure" = round(program.memory["chamber_sensor_pressure"]), "chamber_pressure" = round(program.memory["chamber_sensor_pressure"]),
"exterior_status" = program.memory["exterior_status"], "exterior_status" = program.memory["exterior_status"],
"interior_status" = program.memory["interior_status"], "interior_status" = program.memory["interior_status"],
@@ -61,6 +133,8 @@
"internalTemplateName" = "AirlockConsoleSimple", "internalTemplateName" = "AirlockConsoleSimple",
) )
return data
//Access controller for door control - used in virology and the like //Access controller for door control - used in virology and the like
/obj/machinery/embedded_controller/radio/airlock/access_controller /obj/machinery/embedded_controller/radio/airlock/access_controller
icon = 'icons/obj/airlock_machines.dmi' icon = 'icons/obj/airlock_machines.dmi'
@@ -69,7 +143,8 @@
name = "Access Controller" name = "Access Controller"
tag_secure = 1 tag_secure = 1
valid_actions = list("cycle_ext_door", "cycle_int_door", "force_ext", "force_int") valid_actions = list("cycle_ext_door", "cycle_int_door", "force_ext", "force_int")
deconstructable = TRUE
circuit = /obj/item/circuitboard/airlock_cycling
/obj/machinery/embedded_controller/radio/airlock/access_controller/update_icon() /obj/machinery/embedded_controller/radio/airlock/access_controller/update_icon()
if(on && program) if(on && program)
@@ -81,9 +156,14 @@
icon_state = "access_control_off" icon_state = "access_control_off"
/obj/machinery/embedded_controller/radio/airlock/access_controller/tgui_data(mob/user) /obj/machinery/embedded_controller/radio/airlock/access_controller/tgui_data(mob/user)
. = list( var/list/data = ..()
// Deliberately not using UNTYPED_LIST_ADD, we want this to be appended
data += list(
"exterior_status" = program.memory["exterior_status"], "exterior_status" = program.memory["exterior_status"],
"interior_status" = program.memory["interior_status"], "interior_status" = program.memory["interior_status"],
"processing" = program.memory["processing"], "processing" = program.memory["processing"],
"internalTemplateName" = "DoorAccessConsole", "internalTemplateName" = "DoorAccessConsole",
) )
return data

View File

@@ -414,6 +414,55 @@ send an additional command to open the door again.
if(doorCommand) if(doorCommand)
signalDoor(doorTag, doorCommand) signalDoor(doorTag, doorCommand)
/datum/embedded_program/airlock/proc/get_all_tags()
return list(
"id_tag" = id_tag,
"tag_exterior_door" = tag_exterior_door,
"tag_interior_door" = tag_interior_door,
"tag_airpump" = tag_airpump,
"tag_chamber_sensor" = tag_chamber_sensor,
"tag_exterior_sensor" = tag_exterior_sensor,
"tag_interior_sensor" = tag_interior_sensor,
"tag_airlock_mech_sensor" = tag_airlock_mech_sensor,
"tag_shuttle_mech_sensor" = tag_shuttle_mech_sensor
)
/datum/embedded_program/airlock/proc/get_tag(tag_name)
switch(tag_name)
if("id_tag") . = id_tag
if("tag_exterior_door") . = tag_exterior_door
if("tag_interior_door") . = tag_interior_door
if("tag_airpump") . = tag_airpump
if("tag_chamber_sensor") . = tag_chamber_sensor
if("tag_exterior_sensor") . = tag_exterior_sensor
if("tag_interior_sensor") . = tag_interior_sensor
if("tag_airlock_mech_sensor") . = tag_airlock_mech_sensor
if("tag_shuttle_mech_sensor") . = tag_shuttle_mech_sensor
/datum/embedded_program/airlock/proc/set_tag(tag_name, new_tag)
switch(tag_name)
if("id_tag")
id_tag = new_tag
if("tag_exterior_door")
tag_exterior_door = new_tag
signalDoor(tag_exterior_door, "update")
if("tag_interior_door")
tag_interior_door = new_tag
signalDoor(tag_interior_door, "update")
if("tag_airpump")
tag_airpump = new_tag
if("tag_chamber_sensor")
tag_chamber_sensor = new_tag
if("tag_exterior_sensor")
tag_exterior_sensor = new_tag
if("tag_interior_sensor")
tag_interior_sensor = new_tag
if("tag_airlock_mech_sensor")
tag_airlock_mech_sensor = new_tag
if("tag_shuttle_mech_sensor")
tag_shuttle_mech_sensor = new_tag
#undef SKIPCYCLE_MARGIN #undef SKIPCYCLE_MARGIN
#undef MIN_TARGET_PRESSURE #undef MIN_TARGET_PRESSURE
@@ -424,4 +473,4 @@ send an additional command to open the door again.
#undef TARGET_NONE #undef TARGET_NONE
#undef TARGET_INOPEN #undef TARGET_INOPEN
#undef TARGET_OUTOPEN #undef TARGET_OUTOPEN

View File

@@ -0,0 +1,44 @@
/obj/item/circuitboard/airlock_cycling
name = T_BOARD("cycling airlock button")
build_path = /obj/machinery/access_button
board_type = new /datum/frame/frame_types/button
matter = list(MAT_STEEL = 50, MAT_GLASS = 50)
/datum/design/circuit/airlock_cycling
name = "Machine Design (Cycling Airlock Board)"
desc = "The circuit board for cycling airlock parts."
id = "airlock_cycling"
build_path = /obj/item/circuitboard/airlock_cycling
req_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2)
sort_string = "MAAAD"
/obj/item/circuitboard/airlock_cycling/attackby(obj/item/I as obj, mob/user as mob)
if(I.has_tool_quality(TOOL_MULTITOOL))
var/result = tgui_input_list(
user,
"What do you want to reconfigure the board to?",
"Multitool-Circuitboard interface",
list(
"Button",
"Sensor",
"Controller - Standard",
"Controller - Advanced",
"Controller - Access",
))
switch(result)
if("Button")
name = T_BOARD("cycling airlock button")
build_path = /obj/machinery/access_button
if("Sensor")
name = T_BOARD("cycling airlock sensor")
build_path = /obj/machinery/airlock_sensor
if("Controller - Standard")
name = T_BOARD("cycling airlock controller (simple)")
build_path = /obj/machinery/embedded_controller/radio/airlock/airlock_controller
if("Controller - Advanced")
name = T_BOARD("cycling airlock controller (advanced)")
build_path = /obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller
if("Controller - Access")
name = T_BOARD("cycling airlock controller (access)")
build_path = /obj/machinery/embedded_controller/radio/airlock/access_controller
return

View File

@@ -17,6 +17,11 @@
qdel(program) // the program will clear the ref in its Destroy qdel(program) // the program will clear the ref in its Destroy
return ..() return ..()
/obj/machinery/embedded_controller/examine(mob/user, infix, suffix)
. = ..()
if(in_range(src, user))
. += "It has an ID tag of \"[program?.id_tag]\""
/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line) /obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line)
return 0 return 0
@@ -36,6 +41,7 @@
if(LAZYLEN(valid_actions)) if(LAZYLEN(valid_actions))
if(action in valid_actions) if(action in valid_actions)
program.receive_user_command(action) program.receive_user_command(action)
return TRUE
if(ui.user) if(ui.user)
add_fingerprint(ui.user) add_fingerprint(ui.user)

View File

@@ -31,6 +31,14 @@
type = replacetext(type, " ", "_") type = replacetext(type, " ", "_")
return "[type]_[state]" return "[type]_[state]"
/datum/frame/frame_types/button
name = "Button"
frame_class = FRAME_CLASS_ALARM
frame_size = 1
frame_style = FRAME_STYLE_WALL
x_offset = 24
y_offset = 24
/datum/frame/frame_types/computer /datum/frame/frame_types/computer
name = "Computer" name = "Computer"
icon_override = 'icons/obj/stock_parts_vr.dmi' //VOREStation Edit icon_override = 'icons/obj/stock_parts_vr.dmi' //VOREStation Edit
@@ -208,14 +216,6 @@
circuit = /obj/machinery/atmospheric_field_generator circuit = /obj/machinery/atmospheric_field_generator
frame_size = 3 frame_size = 3
/datum/frame/frame_types/electrochromic_button
name = "Electrochromic Window Button"
frame_class = FRAME_CLASS_ALARM
frame_size = 1
frame_style = FRAME_STYLE_WALL
x_offset = 24
y_offset = 24
////////////////////////////// //////////////////////////////
// Frame Object (Structure) // Frame Object (Structure)
////////////////////////////// //////////////////////////////

View File

@@ -84,7 +84,7 @@
/obj/item/circuitboard/electrochromic /obj/item/circuitboard/electrochromic
name = T_BOARD("electrochromic button") name = T_BOARD("electrochromic button")
build_path = /obj/machinery/button/windowtint build_path = /obj/machinery/button/windowtint
board_type = new /datum/frame/frame_types/electrochromic_button board_type = new /datum/frame/frame_types/button
matter = list(MAT_STEEL = 50, "glass" = 50) matter = list(MAT_STEEL = 50, "glass" = 50)
//Computer //Computer

View File

@@ -692,6 +692,7 @@
/obj/item/multitool = 4, /obj/item/multitool = 4,
/obj/item/cell/high = 10, /obj/item/cell/high = 10,
/obj/item/airlock_electronics = 10, /obj/item/airlock_electronics = 10,
/obj/item/circuitboard/airlock_cycling = 20,
/obj/item/module/power_control = 10, /obj/item/module/power_control = 10,
/obj/item/circuitboard/airalarm = 10, /obj/item/circuitboard/airalarm = 10,
/obj/item/circuitboard/firealarm = 10, /obj/item/circuitboard/firealarm = 10,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

@@ -1,6 +1,7 @@
import { useBackend } from '../../backend'; import { useBackend } from '../../backend';
import { Box, Button, Section } from '../../components'; import { Box, Button, Section } from '../../components';
import { StandardControls, StatusDisplay } from './EmbeddedControllerHelpers'; import { StandardControls, StatusDisplay } from './EmbeddedControllerHelpers';
import { PanelOpen } from './PanelOpen';
import { AirlockConsoleAdvancedData } from './types'; import { AirlockConsoleAdvancedData } from './types';
/** /**
@@ -12,8 +13,13 @@ import { AirlockConsoleAdvancedData } from './types';
export const AirlockConsoleAdvanced = (props) => { export const AirlockConsoleAdvanced = (props) => {
const { act, data } = useBackend<AirlockConsoleAdvancedData>(); const { act, data } = useBackend<AirlockConsoleAdvancedData>();
const { external_pressure, chamber_pressure, internal_pressure, processing } = const {
data; external_pressure,
chamber_pressure,
internal_pressure,
processing,
panel_open,
} = data;
const pressure_range = { const pressure_range = {
external_pressure, external_pressure,
@@ -59,27 +65,31 @@ export const AirlockConsoleAdvanced = (props) => {
return ( return (
<> <>
<StatusDisplay bars={bars} /> <StatusDisplay bars={bars} />
<Section title="Controls"> {panel_open ? (
<StandardControls pressure_range={pressure_range} /> <PanelOpen />
<Box> ) : (
<Button icon="sync" onClick={() => act('purge')}> <Section title="Controls">
Purge <StandardControls pressure_range={pressure_range} />
</Button> <Box>
<Button icon="lock-open" onClick={() => act('secure')}> <Button icon="sync" onClick={() => act('purge')}>
Secure Purge
</Button> </Button>
</Box> <Button icon="lock-open" onClick={() => act('secure')}>
<Box> Secure
<Button </Button>
disabled={!processing} </Box>
icon="ban" <Box>
color="bad" <Button
onClick={() => act('abort')} disabled={!processing}
> icon="ban"
Abort color="bad"
</Button> onClick={() => act('abort')}
</Box> >
</Section> Abort
</Button>
</Box>
</Section>
)}
</> </>
); );
}; };

View File

@@ -1,6 +1,7 @@
import { useBackend } from '../../backend'; import { useBackend } from '../../backend';
import { Box, Button, Section } from '../../components'; import { Box, Button, Section } from '../../components';
import { StandardControls, StatusDisplay } from './EmbeddedControllerHelpers'; import { StandardControls, StatusDisplay } from './EmbeddedControllerHelpers';
import { PanelOpen } from './PanelOpen';
import { AirlockConsoleSimpleData } from './types'; import { AirlockConsoleSimpleData } from './types';
/** /**
@@ -12,8 +13,13 @@ import { AirlockConsoleSimpleData } from './types';
export const AirlockConsoleSimple = (props) => { export const AirlockConsoleSimple = (props) => {
const { act, data } = useBackend<AirlockConsoleSimpleData>(); const { act, data } = useBackend<AirlockConsoleSimpleData>();
const { exterior_status, chamber_pressure, processing, interior_status } = const {
data; exterior_status,
chamber_pressure,
processing,
interior_status,
panel_open,
} = data;
const status_range = { interior_status, exterior_status }; const status_range = { interior_status, exterior_status };
@@ -37,19 +43,23 @@ export const AirlockConsoleSimple = (props) => {
return ( return (
<> <>
<StatusDisplay bars={bars} /> <StatusDisplay bars={bars} />
<Section title="Controls"> {panel_open ? (
<StandardControls status_range={status_range} /> <PanelOpen />
<Box> ) : (
<Button <Section title="Controls">
disabled={!processing} <StandardControls status_range={status_range} />
icon="ban" <Box>
color="bad" <Button
onClick={() => act('abort')} disabled={!processing}
> icon="ban"
Abort color="bad"
</Button> onClick={() => act('abort')}
</Box> >
</Section> Abort
</Button>
</Box>
</Section>
)}
</> </>
); );
}; };

View File

@@ -1,5 +1,6 @@
import { useBackend } from '../../backend'; import { useBackend } from '../../backend';
import { Button, LabeledList, Section } from '../../components'; import { Button, LabeledList, Section } from '../../components';
import { PanelOpen } from './PanelOpen';
import { DoorAccessConsoleData } from './types'; import { DoorAccessConsoleData } from './types';
/** /**
@@ -9,7 +10,7 @@ import { DoorAccessConsoleData } from './types';
export const DoorAccessConsole = (props) => { export const DoorAccessConsole = (props) => {
const { act, data } = useBackend<DoorAccessConsoleData>(); const { act, data } = useBackend<DoorAccessConsoleData>();
const { interior_status, exterior_status } = data; const { interior_status, exterior_status, panel_open } = data;
const interiorOpen = const interiorOpen =
interior_status.state === 'open' || exterior_status.state === 'closed'; interior_status.state === 'open' || exterior_status.state === 'closed';
@@ -17,39 +18,42 @@ export const DoorAccessConsole = (props) => {
exterior_status.state === 'open' || interior_status.state === 'closed'; exterior_status.state === 'open' || interior_status.state === 'closed';
return ( return (
<Section <>
title="Status" <Section
buttons={ title="Status"
<> buttons={
{/* Interior Button */} <>
<Button {/* Interior Button */}
icon={interiorOpen ? 'arrow-left' : 'exclamation-triangle'} <Button
onClick={() => { icon={interiorOpen ? 'arrow-left' : 'exclamation-triangle'}
act(interiorOpen ? 'cycle_ext_door' : 'force_ext'); onClick={() => {
}} act(interiorOpen ? 'cycle_ext_door' : 'force_ext');
> }}
{interiorOpen ? 'Cycle To Exterior' : 'Lock Exterior Door'} >
</Button> {interiorOpen ? 'Cycle To Exterior' : 'Lock Exterior Door'}
{/* Exterior Button */} </Button>
<Button {/* Exterior Button */}
icon={exteriorOpen ? 'arrow-right' : 'exclamation-triangle'} <Button
onClick={() => { icon={exteriorOpen ? 'arrow-right' : 'exclamation-triangle'}
act(exteriorOpen ? 'cycle_int_door' : 'force_int'); onClick={() => {
}} act(exteriorOpen ? 'cycle_int_door' : 'force_int');
> }}
{exteriorOpen ? 'Cycle To Interior' : 'Lock Interior Door'} >
</Button> {exteriorOpen ? 'Cycle To Interior' : 'Lock Interior Door'}
</> </Button>
} </>
> }
<LabeledList> >
<LabeledList.Item label="Exterior Door Status"> <LabeledList>
{exterior_status.state === 'closed' ? 'Locked' : 'Open'} <LabeledList.Item label="Exterior Door Status">
</LabeledList.Item> {exterior_status.state === 'closed' ? 'Locked' : 'Open'}
<LabeledList.Item label="Interior Door Status"> </LabeledList.Item>
{interior_status.state === 'closed' ? 'Locked' : 'Open'} <LabeledList.Item label="Interior Door Status">
</LabeledList.Item> {interior_status.state === 'closed' ? 'Locked' : 'Open'}
</LabeledList> </LabeledList.Item>
</Section> </LabeledList>
</Section>
{!!panel_open && <PanelOpen />}
</>
); );
}; };

View File

@@ -0,0 +1,57 @@
import { round, toFixed } from 'common/math';
import { useBackend } from 'tgui/backend';
import {
Box,
Button,
LabeledList,
NumberInput,
Section,
} from 'tgui-core/components';
import { PanelOpenData } from './types';
export const PanelOpen = (props) => {
const { act, data } = useBackend<PanelOpenData>();
const { panel_open, tags, frequency, min_freq, max_freq } = data;
if (!panel_open || !tags) {
return null;
}
return (
<Section title="Airlock Configuration">
<LabeledList>
<LabeledList.Item label="Frequency">
<NumberInput
animated
fluid
unit="kHz"
step={0.2}
stepPixelSize={10}
value={frequency / 10}
minValue={min_freq / 10}
maxValue={max_freq / 10}
format={(val) => toFixed(val, 1)}
onDrag={(freq) =>
act('set_frequency', { freq: round(freq * 10, 0) })
}
/>
</LabeledList.Item>
{Object.entries(tags).map(([tag, value]) => (
<LabeledList.Item
label={tag}
key={tag}
buttons={
<Button icon="pencil" onClick={() => act('edit_tag', { tag })}>
Edit
</Button>
}
>
{value || <Box color="bad">Unset</Box>}
</LabeledList.Item>
))}
</LabeledList>
</Section>
);
};

View File

@@ -98,7 +98,7 @@ export const EmbeddedController = (props) => {
} }
return ( return (
<Window width={450} height={340}> <Window width={500} height={400}>
<Window.Content>{Component}</Window.Content> <Window.Content>{Component}</Window.Content>
</Window> </Window>
); );

View File

@@ -44,7 +44,7 @@ export type AirlockConsoleAdvancedData = {
purge: BooleanLike; purge: BooleanLike;
secure: BooleanLike; secure: BooleanLike;
internalTemplateName: string; internalTemplateName: string;
}; } & PanelOpenData;
export type AirlockConsoleSimpleData = { export type AirlockConsoleSimpleData = {
chamber_pressure: number; chamber_pressure: number;
@@ -52,7 +52,7 @@ export type AirlockConsoleSimpleData = {
interior_status: status; interior_status: status;
processing: BooleanLike; processing: BooleanLike;
internalTemplateName: string; internalTemplateName: string;
}; } & PanelOpenData;
export type AirlockConsolePhoronData = { export type AirlockConsolePhoronData = {
chamber_pressure: number; chamber_pressure: number;
@@ -68,7 +68,7 @@ export type DoorAccessConsoleData = {
interior_status: status; interior_status: status;
processing: BooleanLike; processing: BooleanLike;
internalTemplateName: string; internalTemplateName: string;
}; } & PanelOpenData;
export type EscapePodConsoleData = { export type EscapePodConsoleData = {
docking_status: string; docking_status: string;
@@ -80,3 +80,11 @@ export type EscapePodConsoleData = {
}; };
export type status = { state: string; lock: string }; export type status = { state: string; lock: string };
export type PanelOpenData = {
panel_open: BooleanLike;
tags: Record<string, string> | null;
frequency: number;
min_freq: number;
max_freq: number;
};

View File

@@ -1,10 +1,9 @@
import { BooleanLike } from 'common/react'; import { BooleanLike } from 'common/react';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Box, Button, LabeledList, Section } from 'tgui-core/components';
import { useBackend } from '../backend'; export type WireData = {
import { Box, Button, LabeledList, Section } from '../components';
import { Window } from '../layouts';
type Data = {
wires: { wires: {
seen_color: string; seen_color: string;
color_name: string; color_name: string;
@@ -17,71 +16,88 @@ type Data = {
}; };
export const Wires = (props) => { export const Wires = (props) => {
const { act, data } = useBackend<Data>(); const { data } = useBackend<WireData>();
const { wires = [] } = data;
return (
<Window width={350} height={150 + wires.length * 30}>
<Window.Content>
<WiresWires />
<WiresStatus />
</Window.Content>
</Window>
);
};
export const WiresWires = (props) => {
const { act, data } = useBackend<WireData>();
const { wires = [] } = data; const { wires = [] } = data;
const statuses = data.status || []; const statuses = data.status || [];
return ( return (
<Window width={350} height={150 + wires.length * 30}> <Section>
<Window.Content> <LabeledList>
<Section> {wires.map((wire) => (
<LabeledList> <LabeledList.Item
{wires.map((wire) => ( key={wire.seen_color}
<LabeledList.Item className="candystripe"
key={wire.seen_color} label={wire.color_name}
className="candystripe" labelColor={wire.seen_color}
label={wire.color_name} color={wire.seen_color}
labelColor={wire.seen_color} buttons={
color={wire.seen_color} <>
buttons={ <Button
<> onClick={() =>
<Button act('cut', {
onClick={() => wire: wire.color,
act('cut', { })
wire: wire.color, }
}) >
} {wire.cut ? 'Mend' : 'Cut'}
> </Button>
{wire.cut ? 'Mend' : 'Cut'} <Button
</Button> onClick={() =>
<Button act('pulse', {
onClick={() => wire: wire.color,
act('pulse', { })
wire: wire.color, }
}) >
} Pulse
> </Button>
Pulse <Button
</Button> onClick={() =>
<Button act('attach', {
onClick={() => wire: wire.color,
act('attach', { })
wire: wire.color, }
}) >
} {wire.attached ? 'Detach' : 'Attach'}
> </Button>
{wire.attached ? 'Detach' : 'Attach'} </>
</Button> }
</> >
} {!!wire.wire && <i>({wire.wire})</i>}
> </LabeledList.Item>
{!!wire.wire && <i>({wire.wire})</i>} ))}
</LabeledList.Item> </LabeledList>
))} </Section>
</LabeledList>
</Section>
{!!statuses.length && (
<Section>
{statuses.map((status) => (
<Box key={status} color="lightgray" mt={0.1}>
{status}
</Box>
))}
</Section>
)}
</Window.Content>
</Window>
); );
}; };
export const WiresStatus = (props) => {
const { act, data } = useBackend<WireData>();
const { wires = [] } = data;
const statuses = data.status || [];
return statuses.length ? (
<Section>
{statuses.map((status) => (
<Box key={status} color="lightgray" mt={0.1}>
{status}
</Box>
))}
</Section>
) : null;
};

View File

@@ -0,0 +1,81 @@
import { round } from 'common/math';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import {
Box,
Button,
LabeledList,
NumberInput,
Section,
} from 'tgui-core/components';
import { WireData, WiresStatus, WiresWires } from './Wires';
type WiresAirlockData = WireData & {
id_tag: string;
frequency: number | null;
min_freq: number;
max_freq: number;
};
export const WiresAirlock = (props) => {
const { act, data } = useBackend<WiresAirlockData>();
const { wires = [], id_tag, frequency, min_freq, max_freq } = data;
return (
<Window width={350} height={180 + wires.length * 30}>
<Window.Content>
<Section>
<LabeledList>
<LabeledList.Item
label="Airlock ID Tag"
buttons={
<Button icon="pencil" onClick={() => act('set_id_tag')}>
Edit
</Button>
}
>
{id_tag || <Box color="bad">None Set</Box>}
</LabeledList.Item>
<LabeledList.Item
label="Frequency"
buttons={
frequency ? (
<Button icon="times" onClick={() => act('clear_frequency')}>
Clear
</Button>
) : null
}
>
{frequency ? (
<NumberInput
animated
fluid
unit="kHz"
step={0.2}
stepPixelSize={10}
value={frequency / 10}
minValue={min_freq / 10}
maxValue={max_freq / 10}
format={(val) => val.toFixed(1)}
onChange={(freq) =>
act('set_frequency', { freq: round(freq * 10, 0) })
}
/>
) : (
<Button
color="bad"
onClick={() => act('set_frequency', { freq: 1379 })}
>
No Frequency, set?
</Button>
)}
</LabeledList.Item>
</LabeledList>
</Section>
<WiresWires />
<WiresStatus />
</Window.Content>
</Window>
);
};

View File

@@ -1146,6 +1146,7 @@
#include "code\game\machinery\embedded_controller\airlock_docking_controller.dm" #include "code\game\machinery\embedded_controller\airlock_docking_controller.dm"
#include "code\game\machinery\embedded_controller\airlock_docking_controller_multi.dm" #include "code\game\machinery\embedded_controller\airlock_docking_controller_multi.dm"
#include "code\game\machinery\embedded_controller\airlock_program.dm" #include "code\game\machinery\embedded_controller\airlock_program.dm"
#include "code\game\machinery\embedded_controller\construction.dm"
#include "code\game\machinery\embedded_controller\docking_program.dm" #include "code\game\machinery\embedded_controller\docking_program.dm"
#include "code\game\machinery\embedded_controller\docking_program_multi.dm" #include "code\game\machinery\embedded_controller\docking_program_multi.dm"
#include "code\game\machinery\embedded_controller\embedded_controller_base.dm" #include "code\game\machinery\embedded_controller\embedded_controller_base.dm"