[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_out = frequency==1439?(RADIO_TO_AIRALARM):null
if(frequency)
radio_connection = register_radio(src, frequency, frequency, radio_filter_in)
src.broadcast_status()
set_frequency(frequency)
/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)
if(stat & (NOPOWER|BROKEN))
@@ -407,6 +410,20 @@
else
to_chat(user, span_warning("You need more welding fuel to complete this task."))
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
..()

View File

@@ -8,6 +8,7 @@
holder_type = /obj/machinery/door/airlock
wire_count = 12
proper_name = "Airlock"
tgui_template = "WiresAirlock"
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
@@ -41,6 +42,39 @@
. += "The 'Check Timing Mechanism' light is [(A.normalspeed == 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)
var/obj/machinery/door/airlock/A = holder
switch(wire)

View File

@@ -9,6 +9,8 @@
/// 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".
var/proper_name = "Unknown"
/// The template to use for TGUI.
var/tgui_template = "Wires"
/// The total number of wires that our holder atom has.
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`
@@ -92,7 +94,7 @@
/datum/wires/tgui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Wires", "[proper_name] wires")
ui = new(user, src, tgui_template, "[proper_name] wires")
ui.open()
/datum/wires/tgui_state(mob/user)

View File

@@ -125,10 +125,12 @@
return
/obj/machinery/door/airlock/proc/set_frequency(new_frequency)
radio_connection = null
radio_controller.remove_object(src, frequency)
frequency = new_frequency
if(new_frequency)
frequency = new_frequency
radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK)
radio_connection = radio_controller.add_object(src, new_frequency, RADIO_AIRLOCK)
/obj/machinery/door/airlock/Initialize()
@@ -152,6 +154,7 @@
anchored = TRUE
power_channel = ENVIRON
circuit = /obj/item/circuitboard/airlock_cycling
var/id_tag
var/master_tag
@@ -165,6 +168,9 @@
var/previousPressure
/obj/machinery/airlock_sensor/update_icon()
if(panel_open)
icon_state = "airlock_sensor_open"
return
if(on)
if(alert)
icon_state = "airlock_sensor_alert"
@@ -216,6 +222,45 @@
radio_controller.remove_object(src,frequency)
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
command = "cycle_interior"
@@ -237,6 +282,7 @@
anchored = TRUE
power_channel = ENVIRON
circuit = /obj/item/circuitboard/airlock_cycling
var/master_tag
var/frequency = 1449
@@ -246,18 +292,50 @@
var/on = 1
/obj/machinery/access_button/update_icon()
if(on)
if(panel_open)
icon_state = "access_button_open"
else if(on)
icon_state = "access_button_standby"
else
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)
//Swiping ID on the access button
if (istype(I, /obj/item/card/id) || istype(I, /obj/item/pda))
attack_hand(user)
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)

View File

@@ -17,6 +17,8 @@
valid_actions = list("cycle_ext", "cycle_int", "force_ext", "force_int", "abort", "purge", "secure")
layer = ABOVE_WINDOW_LAYER
var/deconstructable = FALSE
/obj/machinery/embedded_controller/radio/airlock/Destroy()
// TODO - Leshana - Implement dummy terminals
//for(var/thing in dummy_terminals)
@@ -30,12 +32,75 @@
if(!allowed(user))
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
/obj/machinery/embedded_controller/radio/airlock/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)
. = 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"]),
"external_pressure" = round(program.memory["external_sensor_pressure"]),
"internal_pressure" = round(program.memory["internal_sensor_pressure"]),
@@ -45,15 +110,22 @@
"internalTemplateName" = "AirlockConsoleAdvanced",
)
return data
//Airlock controller for airlock control - most airlocks on the station use this
/obj/machinery/embedded_controller/radio/airlock/airlock_controller
name = "Airlock Controller"
tag_secure = 1
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)
. = 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"]),
"exterior_status" = program.memory["exterior_status"],
"interior_status" = program.memory["interior_status"],
@@ -61,6 +133,8 @@
"internalTemplateName" = "AirlockConsoleSimple",
)
return data
//Access controller for door control - used in virology and the like
/obj/machinery/embedded_controller/radio/airlock/access_controller
icon = 'icons/obj/airlock_machines.dmi'
@@ -69,7 +143,8 @@
name = "Access Controller"
tag_secure = 1
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()
if(on && program)
@@ -81,9 +156,14 @@
icon_state = "access_control_off"
/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"],
"interior_status" = program.memory["interior_status"],
"processing" = program.memory["processing"],
"internalTemplateName" = "DoorAccessConsole",
)
return data

View File

@@ -414,6 +414,55 @@ send an additional command to open the door again.
if(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 MIN_TARGET_PRESSURE

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
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)
return 0
@@ -36,6 +41,7 @@
if(LAZYLEN(valid_actions))
if(action in valid_actions)
program.receive_user_command(action)
return TRUE
if(ui.user)
add_fingerprint(ui.user)

View File

@@ -31,6 +31,14 @@
type = replacetext(type, " ", "_")
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
name = "Computer"
icon_override = 'icons/obj/stock_parts_vr.dmi' //VOREStation Edit
@@ -208,14 +216,6 @@
circuit = /obj/machinery/atmospheric_field_generator
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)
//////////////////////////////

View File

@@ -84,7 +84,7 @@
/obj/item/circuitboard/electrochromic
name = T_BOARD("electrochromic button")
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)
//Computer

View File

@@ -692,6 +692,7 @@
/obj/item/multitool = 4,
/obj/item/cell/high = 10,
/obj/item/airlock_electronics = 10,
/obj/item/circuitboard/airlock_cycling = 20,
/obj/item/module/power_control = 10,
/obj/item/circuitboard/airalarm = 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 { Box, Button, Section } from '../../components';
import { StandardControls, StatusDisplay } from './EmbeddedControllerHelpers';
import { PanelOpen } from './PanelOpen';
import { AirlockConsoleAdvancedData } from './types';
/**
@@ -12,8 +13,13 @@ import { AirlockConsoleAdvancedData } from './types';
export const AirlockConsoleAdvanced = (props) => {
const { act, data } = useBackend<AirlockConsoleAdvancedData>();
const { external_pressure, chamber_pressure, internal_pressure, processing } =
data;
const {
external_pressure,
chamber_pressure,
internal_pressure,
processing,
panel_open,
} = data;
const pressure_range = {
external_pressure,
@@ -59,27 +65,31 @@ export const AirlockConsoleAdvanced = (props) => {
return (
<>
<StatusDisplay bars={bars} />
<Section title="Controls">
<StandardControls pressure_range={pressure_range} />
<Box>
<Button icon="sync" onClick={() => act('purge')}>
Purge
</Button>
<Button icon="lock-open" onClick={() => act('secure')}>
Secure
</Button>
</Box>
<Box>
<Button
disabled={!processing}
icon="ban"
color="bad"
onClick={() => act('abort')}
>
Abort
</Button>
</Box>
</Section>
{panel_open ? (
<PanelOpen />
) : (
<Section title="Controls">
<StandardControls pressure_range={pressure_range} />
<Box>
<Button icon="sync" onClick={() => act('purge')}>
Purge
</Button>
<Button icon="lock-open" onClick={() => act('secure')}>
Secure
</Button>
</Box>
<Box>
<Button
disabled={!processing}
icon="ban"
color="bad"
onClick={() => act('abort')}
>
Abort
</Button>
</Box>
</Section>
)}
</>
);
};

View File

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

View File

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

View File

@@ -44,7 +44,7 @@ export type AirlockConsoleAdvancedData = {
purge: BooleanLike;
secure: BooleanLike;
internalTemplateName: string;
};
} & PanelOpenData;
export type AirlockConsoleSimpleData = {
chamber_pressure: number;
@@ -52,7 +52,7 @@ export type AirlockConsoleSimpleData = {
interior_status: status;
processing: BooleanLike;
internalTemplateName: string;
};
} & PanelOpenData;
export type AirlockConsolePhoronData = {
chamber_pressure: number;
@@ -68,7 +68,7 @@ export type DoorAccessConsoleData = {
interior_status: status;
processing: BooleanLike;
internalTemplateName: string;
};
} & PanelOpenData;
export type EscapePodConsoleData = {
docking_status: string;
@@ -80,3 +80,11 @@ export type EscapePodConsoleData = {
};
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 { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Box, Button, LabeledList, Section } from 'tgui-core/components';
import { useBackend } from '../backend';
import { Box, Button, LabeledList, Section } from '../components';
import { Window } from '../layouts';
type Data = {
export type WireData = {
wires: {
seen_color: string;
color_name: string;
@@ -17,71 +16,88 @@ type Data = {
};
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 statuses = data.status || [];
return (
<Window width={350} height={150 + wires.length * 30}>
<Window.Content>
<Section>
<LabeledList>
{wires.map((wire) => (
<LabeledList.Item
key={wire.seen_color}
className="candystripe"
label={wire.color_name}
labelColor={wire.seen_color}
color={wire.seen_color}
buttons={
<>
<Button
onClick={() =>
act('cut', {
wire: wire.color,
})
}
>
{wire.cut ? 'Mend' : 'Cut'}
</Button>
<Button
onClick={() =>
act('pulse', {
wire: wire.color,
})
}
>
Pulse
</Button>
<Button
onClick={() =>
act('attach', {
wire: wire.color,
})
}
>
{wire.attached ? 'Detach' : 'Attach'}
</Button>
</>
}
>
{!!wire.wire && <i>({wire.wire})</i>}
</LabeledList.Item>
))}
</LabeledList>
</Section>
{!!statuses.length && (
<Section>
{statuses.map((status) => (
<Box key={status} color="lightgray" mt={0.1}>
{status}
</Box>
))}
</Section>
)}
</Window.Content>
</Window>
<Section>
<LabeledList>
{wires.map((wire) => (
<LabeledList.Item
key={wire.seen_color}
className="candystripe"
label={wire.color_name}
labelColor={wire.seen_color}
color={wire.seen_color}
buttons={
<>
<Button
onClick={() =>
act('cut', {
wire: wire.color,
})
}
>
{wire.cut ? 'Mend' : 'Cut'}
</Button>
<Button
onClick={() =>
act('pulse', {
wire: wire.color,
})
}
>
Pulse
</Button>
<Button
onClick={() =>
act('attach', {
wire: wire.color,
})
}
>
{wire.attached ? 'Detach' : 'Attach'}
</Button>
</>
}
>
{!!wire.wire && <i>({wire.wire})</i>}
</LabeledList.Item>
))}
</LabeledList>
</Section>
);
};
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_multi.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_multi.dm"
#include "code\game\machinery\embedded_controller\embedded_controller_base.dm"