Files
Bubberstation/code/modules/wiremod/component.dm
SkyratBot 1b122706a3 [MIRROR] USB Cables -- Connect circuits to computers/machines (#6327)
* USB Cables -- Connect circuits to computers/machines (#59345)

* Initial commit

* Sprites, finishing work

* More ways to detach from circuitboards

* Clear TODOs, give bots a button

* Fix qdel loop

* Designs

* It's the bots that have them

* Grammar fix

* Feedback for connecting to circuit directly

* Add USB cable design to basic circuitry

* Better naming

* Feedback

* Fix for new code

* COMSIG_CIRCUIT_ADD_COMPONENT_MANUALLY

* span procs

* USB Cables -- Connect circuits to computers/machines

Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
2021-06-16 00:37:07 +01:00

190 lines
5.7 KiB
Plaintext

/**
* # Integrated Circuit Component
*
* A component that performs a function when given an input
*
* Can be attached to an integrated circuitboard, where it can then
* be connected between other components to provide an output or to receive
* an input. This is the base type of all components
*/
/obj/item/circuit_component
name = COMPONENT_DEFAULT_NAME
icon = 'icons/obj/module.dmi'
icon_state = "component"
inhand_icon_state = "electronic"
/// The name of the component shown on the UI
var/display_name = "Generic"
/// The integrated_circuit that this component is attached to.
var/obj/item/integrated_circuit/parent
/// A list that contains the outpurt ports on this component
/// Used to connect between the ports
var/list/datum/port/output/output_ports = list()
/// A list that contains the components the input ports on this component
/// Used to connect between the ports
var/list/datum/port/input/input_ports = list()
/// Generic trigger input for triggering this component
var/datum/port/input/trigger_input
var/datum/port/output/trigger_output
/// The flags of the circuit to control basic generalised behaviour.
var/circuit_flags = NONE
/// Used to determine the x position of the component within the UI
var/rel_x = 0
/// Used to determine the y position of the component within the UI
var/rel_y = 0
/// The power usage whenever this component receives an input
var/power_usage_per_input = 1
/// The current selected option
var/current_option
/// The options that this component can take on. Limited to strings
var/list/options
// Whether the component is removable or not. Only affects user UI
var/removable = TRUE
/obj/item/circuit_component/Initialize()
. = ..()
if(name == COMPONENT_DEFAULT_NAME)
name = "[lowertext(display_name)] [COMPONENT_DEFAULT_NAME]"
if(length(options))
current_option = options[1]
return INITIALIZE_HINT_LATELOAD
/obj/item/circuit_component/LateInitialize()
. = ..()
if(circuit_flags & CIRCUIT_FLAG_INPUT_SIGNAL)
trigger_input = add_input_port("Trigger", PORT_TYPE_SIGNAL)
if(circuit_flags & CIRCUIT_FLAG_OUTPUT_SIGNAL)
trigger_output = add_output_port("Triggered", PORT_TYPE_SIGNAL)
/obj/item/circuit_component/Destroy()
if(parent)
// Prevents a Destroy() recursion
var/obj/item/integrated_circuit/old_parent = parent
parent = null
old_parent.remove_component(src)
trigger_input = null
trigger_output = null
QDEL_LIST(output_ports)
QDEL_LIST(input_ports)
return ..()
/**
* Called when a shell is registered from the component/the component is added to a circuit.
*
* Register all signals here on the shell.
* Arguments:
* * shell - Shell being registered
*/
/obj/item/circuit_component/proc/register_shell(atom/movable/shell)
return
/**
* Called when a shell is unregistered from the component/the component is removed from a circuit.
*
* Unregister all signals here on the shell.
* Arguments:
* * shell - Shell being unregistered
*/
/obj/item/circuit_component/proc/unregister_shell(atom/movable/shell)
return
/**
* Disconnects a component from other components
*
* Disconnects both the input and output ports of the component
*/
/obj/item/circuit_component/proc/disconnect()
for(var/datum/port/output/port_to_disconnect as anything in output_ports)
port_to_disconnect.disconnect()
for(var/datum/port/input/port_to_disconnect as anything in input_ports)
port_to_disconnect.disconnect()
/**
* Sets the option on this component
*
* Can only be a value from the options variable
* Arguments:
* * option - The option that has been switched to.
*/
/obj/item/circuit_component/proc/set_option(option)
current_option = option
TRIGGER_CIRCUIT_COMPONENT(src, null)
/**
* Matches the output port's datatype with the input port's current connected port.
*
* Returns true if datatype was changed, otherwise returns false.
* Arguments:
* * input_port - The input port to check the connected port from.
* * output_port - The output port to convert. Warning, this does change the output port.
*/
/obj/item/circuit_component/proc/match_port_datatype(datum/port/input/input_port, datum/port/output/output_port)
if(input_port.connected_port)
var/datum/port/connected_port = input_port.connected_port
if(connected_port.datatype != output_port.datatype)
output_port.set_datatype(connected_port.datatype)
return TRUE
else
output_port.set_datatype(output_port.default_datatype)
return TRUE
return FALSE
/**
* Adds an input port and returns it
*
* Arguments:
* * name - The name of the input port
* * type - The datatype it handles
* * trigger - Whether this input port triggers an update on the component when updated.
*/
/obj/item/circuit_component/proc/add_input_port(name, type, trigger = TRUE, default = null)
var/datum/port/input/input_port = new(src, name, type, trigger, default)
input_ports += input_port
return input_port
/**
* Adds an output port and returns it
*
* Arguments:
* * name - The name of the output port
* * type - The datatype it handles.
*/
/obj/item/circuit_component/proc/add_output_port(name, type)
var/datum/port/output/output_port = new(src, name, type)
output_ports += output_port
return output_port
/**
* Called whenever an input is received from one of the ports.
*
* Return value indicates that the circuit should not do anything. Also prevents an output signal.
* Arguments:
* * port - Can be null. The port that sent the input
*/
/obj/item/circuit_component/proc/input_received(datum/port/input/port)
SHOULD_CALL_PARENT(TRUE)
if(!parent?.on)
return TRUE
var/obj/item/stock_parts/cell/cell = parent.get_cell()
if(!cell?.use(power_usage_per_input))
return TRUE
if((circuit_flags & CIRCUIT_FLAG_INPUT_SIGNAL) && !COMPONENT_TRIGGERED_BY(trigger_input, port))
return TRUE