Adds the airlock shell, refactors USB code to be easier to use, implements USB cables for the binary valve and more. (#59728)

Adds the airlock shell. The circuit has full control over the airlock.
Refactors USB code to be easier to use for less experienced coders.
Implements USB cables for the binary valve to be able to open/close the valve.
Adds a private channel for radios that only lets circuits with the same owner's ID to interact with it.
This commit is contained in:
Watermelon914
2021-06-24 14:22:19 -03:00
committed by GitHub
parent 6985c5f663
commit 921416b5d8
16 changed files with 313 additions and 49 deletions
+7 -1
View File
@@ -761,13 +761,19 @@
/// from /obj/machinery/atmospherics/components/unary/cryo_cell/set_on(bool): (on)
#define COMSIG_CRYO_SET_ON "cryo_set_on"
// /obj/machinery/atmospherics/components/binary/valve signals
/// from /obj/machinery/atmospherics/components/binary/valve/toggle(): (on)
#define COMSIG_VALVE_SET_OPEN "valve_toggled"
// /obj/machinery/door/airlock signals
//from /obj/machinery/door/airlock/open(): (forced)
#define COMSIG_AIRLOCK_OPEN "airlock_open"
//from /obj/machinery/door/airlock/close(): (forced)
#define COMSIG_AIRLOCK_CLOSE "airlock_close"
///from /obj/machinery/door/airlock/set_bolt():
#define COMSIG_AIRLOCK_SET_BOLT "airlock_set_bolt"
// /obj/item signals
///from base of obj/item/equipped(): (/mob/equipper, slot)
+7
View File
@@ -84,6 +84,10 @@
// Clock component
#define COMP_CLOCK_DELAY 0.9 SECONDS
// Radio component
#define COMP_RADIO_PUBLIC "public"
#define COMP_RADIO_PRIVATE "private"
// Shells
/// Whether a circuit is stuck on a shell and cannot be removed (by a user)
@@ -95,6 +99,9 @@
/// Whether or not the shell has a USB port.
#define SHELL_FLAG_USB_PORT (1<<2)
/// Whether the shell allows actions to be peformed on a shell if the action fails. This will additionally block the messages from being displayed.
#define SHELL_FLAG_ALLOW_FAILURE_ACTION (1<<3)
// Shell capacities. These can be converted to configs very easily later
#define SHELL_CAPACITY_SMALL 10
#define SHELL_CAPACITY_MEDIUM 25
+4
View File
@@ -133,6 +133,8 @@
return
if(locked)
if(shell_flags & SHELL_FLAG_ALLOW_FAILURE_ACTION)
return
source.balloon_alert(user, "it's locked!")
return COMPONENT_BLOCK_TOOL_ATTACK
@@ -148,6 +150,8 @@
return
if(locked)
if(shell_flags & SHELL_FLAG_ALLOW_FAILURE_ACTION)
return
source.balloon_alert(user, "it's locked!")
return COMPONENT_BLOCK_TOOL_ATTACK
+25 -19
View File
@@ -19,13 +19,20 @@
if (!isatom(parent))
return COMPONENT_INCOMPATIBLE
src.circuit_component_types = circuit_component_types
circuit_components = list()
for(var/circuit_component_type in circuit_component_types)
var/obj/item/circuit_component/circuit_component = new circuit_component_type(null)
circuit_components += circuit_component
/datum/component/usb_port/RegisterWithParent()
RegisterSignal(parent, COMSIG_ATOM_USB_CABLE_TRY_ATTACH, .proc/on_atom_usb_cable_try_attach)
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/on_moved)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
for(var/obj/item/circuit_component/component as anything in circuit_components)
component.register_usb_parent(parent)
/datum/component/usb_port/UnregisterFromParent()
UnregisterSignal(parent, list(
COMSIG_ATOM_USB_CABLE_TRY_ATTACH,
@@ -33,10 +40,14 @@
COMSIG_PARENT_EXAMINE,
))
for(var/obj/item/circuit_component/component as anything in circuit_components)
component.unregister_usb_parent(parent)
unregister_circuit_signals()
attached_circuit = null
/datum/component/usb_port/Destroy()
QDEL_LAZYLIST(circuit_components)
QDEL_LIST(circuit_components)
QDEL_NULL(usb_cable_beam)
attached_circuit = null
@@ -58,16 +69,12 @@
UnregisterSignal(shell, COMSIG_MOVABLE_MOVED)
UnregisterSignal(shell, COMSIG_PARENT_EXAMINE)
/datum/component/usb_port/proc/create_circuit_components(obj/item/integrated_circuit/circuitboard)
var/created_circuit_components = list()
/datum/component/usb_port/proc/attach_circuit_components(obj/item/integrated_circuit/circuitboard)
for(var/obj/item/circuit_component/component as anything in circuit_components)
circuitboard.add_component(component)
RegisterSignal(component, COMSIG_CIRCUIT_COMPONENT_REMOVED, .proc/on_circuit_component_removed)
for(var/circuit_component_type in circuit_component_types)
var/obj/item/circuit_component/circuit_component = new circuit_component_type(parent)
circuitboard.add_component(circuit_component)
created_circuit_components += circuit_component
RegisterSignal(circuit_component, COMSIG_CIRCUIT_COMPONENT_REMOVED, .proc/on_circuit_component_removed)
return created_circuit_components
return
/datum/component/usb_port/proc/on_examine(datum/source, mob/user, list/examine_text)
SIGNAL_HANDLER
@@ -103,7 +110,7 @@
attached_circuit = connecting_cable.attached_circuit
connecting_cable.forceMove(attached_circuit)
circuit_components = create_circuit_components(attached_circuit)
attach_circuit_components(attached_circuit)
attached_circuit.interact(user)
usb_cable_beam = atom_parent.Beam(attached_circuit.shell, "usb_cable_beam", 'icons/obj/wiremod.dmi')
@@ -128,19 +135,15 @@
/datum/component/usb_port/proc/on_circuit_deleting()
SIGNAL_HANDLER
unregister_circuit_signals()
attached_circuit = null
detach()
qdel(usb_cable_ref)
/datum/component/usb_port/proc/on_circuit_component_removed(datum/source)
SIGNAL_HANDLER
qdel(source)
detach()
/datum/component/usb_port/proc/on_circuit_shell_removed()
SIGNAL_HANDLER
detach()
/datum/component/usb_port/proc/detach()
@@ -148,14 +151,17 @@
if (isnull(usb_cable))
return
for(var/obj/item/circuit_component/component as anything in circuit_components)
UnregisterSignal(component, COMSIG_CIRCUIT_COMPONENT_REMOVED)
attached_circuit.remove_component(component)
component.moveToNullspace()
unregister_circuit_signals()
var/atom/atom_parent = parent
usb_cable.forceMove(atom_parent.drop_location())
usb_cable.balloon_alert_to_viewers("snap")
QDEL_LAZYLIST(circuit_components)
attached_circuit = null
usb_cable_ref = null
+16 -16
View File
@@ -117,24 +117,28 @@
var/datum/port/output/travelling_output
/// The tram controls computer (/obj/machinery/computer/tram_controls)
var/datum/weakref/computer
var/obj/machinery/computer/tram_controls/computer
/obj/item/circuit_component/tram_controls/Initialize()
. = ..()
var/obj/machinery/computer/tram_controls/computer_object = get(src, /obj/machinery/computer/tram_controls)
if (computer_object)
computer = WEAKREF(computer_object)
RegisterSignal(computer_object.tram_part, COMSIG_TRAM_SET_TRAVELLING, .proc/on_tram_set_travelling)
RegisterSignal(computer_object.tram_part, COMSIG_TRAM_TRAVEL, .proc/on_tram_travel)
new_destination = add_input_port("Destination", PORT_TYPE_STRING, FALSE)
trigger_move = add_input_port("Send Tram", PORT_TYPE_SIGNAL)
location = add_output_port("Location", PORT_TYPE_STRING)
travelling_output = add_output_port("Travelling", PORT_TYPE_NUMBER)
/obj/item/circuit_component/tram_controls/register_usb_parent(atom/movable/parent)
. = ..()
if (istype(parent, /obj/machinery/computer/tram_controls))
computer = parent
RegisterSignal(computer.tram_part, COMSIG_TRAM_SET_TRAVELLING, .proc/on_tram_set_travelling)
RegisterSignal(computer.tram_part, COMSIG_TRAM_TRAVEL, .proc/on_tram_travel)
/obj/item/circuit_component/tram_controls/unregister_usb_parent(atom/movable/parent)
computer = null
UnregisterSignal(computer.tram_part, list(COMSIG_TRAM_SET_TRAVELLING, COMSIG_TRAM_TRAVEL))
return ..()
/obj/item/circuit_component/tram_controls/Destroy()
new_destination = null
trigger_move = null
@@ -151,12 +155,10 @@
if (!COMPONENT_TRIGGERED_BY(trigger_move, port))
return
var/obj/machinery/computer/tram_controls/tram_controls = computer.resolve()
if (isnull(tram_controls))
if (isnull(computer))
return
if (!tram_controls.powered())
if (!computer.powered())
return
var/destination
@@ -169,14 +171,12 @@
if (!destination)
return
tram_controls.try_send_tram(destination)
computer.try_send_tram(destination)
/obj/item/circuit_component/tram_controls/proc/on_tram_set_travelling(datum/source, travelling)
SIGNAL_HANDLER
travelling_output.set_output(travelling)
/obj/item/circuit_component/tram_controls/proc/on_tram_travel(datum/source, obj/effect/landmark/tram/from_where, obj/effect/landmark/tram/to_where)
SIGNAL_HANDLER
location.set_output(to_where.name)
+9 -2
View File
@@ -298,18 +298,25 @@
/obj/machinery/door/airlock/proc/bolt()
if(locked)
return
locked = TRUE
set_bolt(TRUE)
playsound(src,boltDown,30,FALSE,3)
audible_message(span_hear("You hear a click from the bottom of the door."), null, 1)
update_appearance()
/obj/machinery/door/airlock/proc/set_bolt(should_bolt)
if(locked == should_bolt)
return
SEND_SIGNAL(src, COMSIG_AIRLOCK_SET_BOLT, should_bolt)
. = locked
locked = should_bolt
/obj/machinery/door/airlock/unlock()
unbolt()
/obj/machinery/door/airlock/proc/unbolt()
if(!locked)
return
locked = FALSE
set_bolt(FALSE)
playsound(src,boltUp,30,FALSE,3)
audible_message(span_hear("You hear a click from the bottom of the door."), null, 1)
update_appearance()
@@ -28,20 +28,24 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
/**
* Called by finish_interact(), switch between open and closed, reconcile the air between two pipelines
*/
/obj/machinery/atmospherics/components/binary/valve/proc/toggle()
/obj/machinery/atmospherics/components/binary/valve/proc/set_open(to_open)
if(on == to_open)
return
SEND_SIGNAL(src, COMSIG_VALVE_SET_OPEN, to_open)
. = on
on = to_open
if(on)
on = FALSE
update_icon_nopipes()
investigate_log("was closed by [usr ? key_name(usr) : "a remote signal"]", INVESTIGATE_ATMOS)
vent_movement &= ~VENTCRAWL_ALLOWED
else
on = TRUE
update_icon_nopipes()
update_parents()
var/datum/pipeline/parent1 = parents[1]
parent1.reconcile_air()
investigate_log("was opened by [usr ? key_name(usr) : "a remote signal"]", INVESTIGATE_ATMOS)
vent_movement |= VENTCRAWL_ALLOWED
else
update_icon_nopipes()
investigate_log("was closed by [usr ? key_name(usr) : "a remote signal"]", INVESTIGATE_ATMOS)
vent_movement &= ~VENTCRAWL_ALLOWED
/obj/machinery/atmospherics/components/binary/valve/interact(mob/user)
add_fingerprint(usr)
@@ -55,7 +59,7 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
* Called by iteract() after a 1 second timer, calls toggle(), allows another interaction with the component.
*/
/obj/machinery/atmospherics/components/binary/valve/proc/finish_interact()
toggle()
set_open(!on)
switching = FALSE
/obj/machinery/atmospherics/components/binary/valve/digital // can be controlled by AI
@@ -68,6 +72,68 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_OPEN | INTERACT_MACHINE_OPEN_SILICON
/obj/machinery/atmospherics/components/binary/valve/digital/Initialize()
. = ..()
AddComponent(/datum/component/usb_port, list(/obj/item/circuit_component/digital_valve))
/obj/item/circuit_component/digital_valve
display_name = "Digital Valve"
display_desc = "The interface for communicating with a digital valve."
var/obj/machinery/atmospherics/components/binary/valve/digital/attached_valve
/// Opens the digital valve
var/datum/port/input/open
/// Closes the digital valve
var/datum/port/input/close
/// Whether the valve is currently open
var/datum/port/output/is_open
/// Sent when the valve is opened
var/datum/port/output/opened
/// Sent when the valve is closed
var/datum/port/output/closed
/obj/item/circuit_component/digital_valve/Initialize()
. = ..()
open = add_input_port("Open", PORT_TYPE_SIGNAL)
close = add_input_port("Close", PORT_TYPE_SIGNAL)
is_open = add_output_port("Is Open", PORT_TYPE_NUMBER)
opened = add_output_port("Opened", PORT_TYPE_SIGNAL)
closed = add_output_port("Closed", PORT_TYPE_SIGNAL)
/obj/item/circuit_component/digital_valve/register_usb_parent(atom/movable/shell)
. = ..()
if(istype(shell, /obj/machinery/atmospherics/components/binary/valve/digital))
attached_valve = shell
RegisterSignal(attached_valve, COMSIG_VALVE_SET_OPEN, .proc/handle_valve_toggled)
/obj/item/circuit_component/digital_valve/unregister_usb_parent(atom/movable/shell)
UnregisterSignal(attached_valve, COMSIG_VALVE_SET_OPEN)
attached_valve = null
return ..()
/obj/item/circuit_component/digital_valve/proc/handle_valve_toggled(datum/source, on)
is_open.set_output(on)
if(on)
opened.set_output(COMPONENT_SIGNAL)
else
closed.set_output(COMPONENT_SIGNAL)
/obj/item/circuit_component/digital_valve/input_received(datum/port/input/port)
. = ..()
if(.)
return
if(!attached_valve)
return
if(COMPONENT_TRIGGERED_BY(open, port) && !attached_valve.on)
attached_valve.set_open(TRUE)
if(COMPONENT_TRIGGERED_BY(close, port) && attached_valve.on)
attached_valve.set_open(FALSE)
/obj/machinery/atmospherics/components/binary/valve/digital/update_icon_nopipes(animation)
if(!is_operational)
normalize_cardinal_directions()
@@ -244,3 +244,15 @@
build_path = /obj/item/shell/server
build_type = PROTOLATHE | COMPONENT_PRINTER
category = list("Circuitry", "Shells")
/datum/design/airlock_shell
name = "Airlock Shell"
desc = "A door shell that cannot be moved around when assembled."
id = "door_shell"
materials = list(
/datum/material/glass = 5000,
/datum/material/iron = 15000,
)
build_path = /obj/item/shell/airlock
build_type = PROTOLATHE | COMPONENT_PRINTER
category = list("Circuitry", "Shells")
@@ -644,6 +644,7 @@
prereq_ids = list("basic_circuitry", "engineering")
design_ids = list(
"bot_shell",
"door_shell",
"controller_shell",
"money_bot_shell",
)
+6
View File
@@ -231,3 +231,9 @@
"content" = "Power Usage Per Input: [power_usage_per_input]",
"color" = "orange",
))
/obj/item/circuit_component/proc/register_usb_parent(atom/movable/parent)
return
/obj/item/circuit_component/proc/unregister_usb_parent(atom/movable/parent)
return
@@ -5,7 +5,7 @@
*/
/obj/item/circuit_component/radio
display_name = "Radio"
display_desc = "A component that can listen and send frequencies."
display_desc = "A component that can listen and send frequencies. If set to private, the component will only receive signals from other components attached to circuitboards with the same owner id."
/// Frequency input
var/datum/port/input/freq
@@ -17,10 +17,18 @@
var/datum/radio_frequency/radio_connection
/obj/item/circuit_component/radio/populate_options()
var/static/component_options = list(
COMP_RADIO_PUBLIC,
COMP_RADIO_PRIVATE,
)
options = component_options
/obj/item/circuit_component/radio/Initialize()
. = ..()
freq = add_input_port("Frequency", PORT_TYPE_NUMBER, default = FREQ_SIGNALER)
code = add_input_port("Code", PORT_TYPE_NUMBER, default = DEFAULT_SIGNALER_CODE)
TRIGGER_CIRCUIT_COMPONENT(src, null)
// These are cleaned up on the parent
trigger_input = add_input_port("Send", PORT_TYPE_SIGNAL)
trigger_output = add_output_port("Received", PORT_TYPE_SIGNAL)
@@ -44,7 +52,7 @@
current_freq = frequency
if(COMPONENT_TRIGGERED_BY(trigger_input, port))
var/datum/signal/signal = new(list("code" = round(code.input_value) || 0))
var/datum/signal/signal = new(list("code" = round(code.input_value) || 0, "key" = parent?.owner_id))
radio_connection.post_signal(src, signal)
/obj/item/circuit_component/radio/receive_signal(datum/signal/signal)
@@ -54,4 +62,7 @@
if(signal.data["code"] != round(code.input_value || 0))
return
if(current_option == COMP_RADIO_PRIVATE && parent?.owner_id != signal.data["key"])
return
trigger_output.set_output(COMPONENT_SIGNAL)
+2 -1
View File
@@ -329,7 +329,8 @@
return
component.disconnect()
remove_component(component)
usr.put_in_hands(component)
if(component.loc == src)
usr.put_in_hands(component)
. = TRUE
if("set_component_coordinates")
var/component_id = text2num(params["component_id"])
+128
View File
@@ -0,0 +1,128 @@
/obj/machinery/door/airlock/shell
name = "circuit airlock"
autoclose = FALSE
/obj/machinery/door/airlock/shell/Initialize()
. = ..()
AddComponent( \
/datum/component/shell, \
unremovable_circuit_components = list(new /obj/item/circuit_component/airlock), \
capacity = SHELL_CAPACITY_LARGE, \
shell_flags = SHELL_FLAG_ALLOW_FAILURE_ACTION \
)
/obj/machinery/door/airlock/shell/check_access(obj/item/I)
return FALSE
/obj/item/circuit_component/airlock
display_name = "Airlock"
display_desc = "The general interface with an airlock. Includes general statuses of the airlock"
/// Called when attack_hand is called on the shell.
var/obj/machinery/door/airlock/attached_airlock
/// Bolts the airlock (if possible)
var/datum/port/input/bolt
/// Unbolts the airlock (if possible)
var/datum/port/input/unbolt
/// Opens the airlock (if possible)
var/datum/port/input/open
/// Closes the airlock (if possible)
var/datum/port/input/close
/// Contains whether the airlock is open or not
var/datum/port/output/is_open
/// Contains whether the airlock is bolted or not
var/datum/port/output/is_bolted
/// Called when the airlock is opened.
var/datum/port/output/opened
/// Called when the airlock is closed
var/datum/port/output/closed
/// Called when the airlock is bolted
var/datum/port/output/bolted
/// Called when the airlock is unbolted
var/datum/port/output/unbolted
/obj/item/circuit_component/airlock/Initialize()
. = ..()
// Input Signals
bolt = add_input_port("Bolt", PORT_TYPE_SIGNAL)
unbolt = add_input_port("Unbolt", PORT_TYPE_SIGNAL)
open = add_input_port("Open", PORT_TYPE_SIGNAL)
close = add_input_port("Close", PORT_TYPE_SIGNAL)
// States
is_open = add_output_port("Is Open", PORT_TYPE_NUMBER)
is_bolted = add_output_port("Is Bolted", PORT_TYPE_NUMBER)
// Output Signals
opened = add_output_port("Opened", PORT_TYPE_SIGNAL)
closed = add_output_port("Closed", PORT_TYPE_SIGNAL)
bolted = add_output_port("Bolted", PORT_TYPE_SIGNAL)
unbolted = add_output_port("Unbolted", PORT_TYPE_SIGNAL)
/obj/item/circuit_component/airlock/Destroy()
bolt = null
unbolt = null
open = null
close = null
is_open = null
is_bolted = null
opened = null
closed = null
bolted = null
unbolted = null
attached_airlock = null
return ..()
/obj/item/circuit_component/airlock/register_shell(atom/movable/shell)
. = ..()
if(istype(shell, /obj/machinery/door/airlock))
attached_airlock = shell
RegisterSignal(shell, COMSIG_AIRLOCK_SET_BOLT, .proc/on_airlock_set_bolted)
RegisterSignal(shell, COMSIG_AIRLOCK_OPEN, .proc/on_airlock_open)
RegisterSignal(shell, COMSIG_AIRLOCK_CLOSE, .proc/on_airlock_closed)
/obj/item/circuit_component/airlock/unregister_shell(atom/movable/shell)
attached_airlock = null
UnregisterSignal(shell, list(
COMSIG_AIRLOCK_SET_BOLT,
COMSIG_AIRLOCK_OPEN,
COMSIG_AIRLOCK_CLOSE,
))
return ..()
/obj/item/circuit_component/airlock/proc/on_airlock_set_bolted(datum/source, should_bolt)
SIGNAL_HANDLER
is_bolted.set_output(should_bolt)
if(should_bolt)
bolted.set_output(COMPONENT_SIGNAL)
else
unbolted.set_output(COMPONENT_SIGNAL)
/obj/item/circuit_component/airlock/proc/on_airlock_open(datum/source, force)
SIGNAL_HANDLER
is_open.set_output(TRUE)
opened.set_output(COMPONENT_SIGNAL)
/obj/item/circuit_component/airlock/proc/on_airlock_closed(datum/source, forced)
SIGNAL_HANDLER
is_open.set_output(FALSE)
closed.set_output(COMPONENT_SIGNAL)
/obj/item/circuit_component/airlock/input_received(datum/port/input/port)
. = ..()
if(.)
return
if(!attached_airlock)
return
if(COMPONENT_TRIGGERED_BY(bolt, port))
attached_airlock.bolt()
if(COMPONENT_TRIGGERED_BY(unbolt, port))
attached_airlock.unbolt()
if(COMPONENT_TRIGGERED_BY(open, port) && attached_airlock.density)
INVOKE_ASYNC(attached_airlock, /obj/machinery/door/airlock.proc/open)
if(COMPONENT_TRIGGERED_BY(close, port) && !attached_airlock.density)
INVOKE_ASYNC(attached_airlock, /obj/machinery/door/airlock.proc/close)
+1
View File
@@ -23,6 +23,7 @@
/obj/item/circuit_component/bot
display_name = "Bot"
display_desc = "Triggers when someone interacts with the bot."
/// Called when attack_hand is called on the shell.
var/datum/port/output/signal
@@ -45,3 +45,10 @@
icon_state = "setup_stationary-open"
shell_to_spawn = /obj/structure/server
screw_delay = 10 SECONDS
/obj/item/shell/airlock
name = "circuit airlock assembly"
icon = 'icons/obj/doors/airlocks/station/public.dmi'
icon_state = "construction"
shell_to_spawn = /obj/machinery/door/airlock/shell
screw_delay = 10 SECONDS
+1
View File
@@ -3598,6 +3598,7 @@
#include "code\modules\wiremod\components\utility\typecheck.dm"
#include "code\modules\wiremod\preset\hello_world.dm"
#include "code\modules\wiremod\preset\speech_relay.dm"
#include "code\modules\wiremod\shell\airlock.dm"
#include "code\modules\wiremod\shell\bot.dm"
#include "code\modules\wiremod\shell\compact_remote.dm"
#include "code\modules\wiremod\shell\controller.dm"