From 5ab9aba9d4119f01a28745dbf3435e5cdf853bb3 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Wed, 23 Jun 2021 23:50:59 +0200 Subject: [PATCH] [MIRROR] Added circuit component UI details, added multiplexer and allowed inserting components directly into shells. (#6479) * Added circuit component UI details, added multiplexer and allowed inserting components directly into shells. (#59635) Adds the multiplexer circuit component - en.wikipedia.org/wiki/Multiplexer Circuit components can now be directly inserted into shells rather than having to take the integrated circuit out. Special information can be accessed from components now through the "Info" button besides the eject button on a component. * Added circuit component UI details, added multiplexer and allowed inserting components directly into shells. Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com> --- code/__DEFINES/wiremod.dm | 6 +- code/datums/components/shell.dm | 13 +++- .../research/designs/wiremod_designs.dm | 37 +++------- code/modules/research/techweb/all_nodes.dm | 1 + code/modules/wiremod/component.dm | 36 ++++++++++ .../wiremod/components/action/light.dm | 9 +++ .../modules/wiremod/components/action/pull.dm | 1 + .../wiremod/components/action/radio.dm | 1 + .../wiremod/components/action/speech.dm | 9 +++ .../wiremod/components/atom/direction.dm | 9 +++ code/modules/wiremod/components/atom/gps.dm | 1 + .../modules/wiremod/components/atom/health.dm | 9 +++ code/modules/wiremod/components/atom/hear.dm | 1 + code/modules/wiremod/components/atom/self.dm | 1 + .../wiremod/components/atom/species.dm | 1 + .../wiremod/components/math/arithmetic.dm | 20 +++--- .../wiremod/components/math/comparison.dm | 23 +++---- code/modules/wiremod/components/math/index.dm | 1 + .../modules/wiremod/components/math/length.dm | 1 + code/modules/wiremod/components/math/logic.dm | 18 +++-- code/modules/wiremod/components/math/not.dm | 1 + .../modules/wiremod/components/math/random.dm | 1 + .../wiremod/components/string/concat.dm | 1 + .../wiremod/components/string/contains.dm | 1 + .../wiremod/components/string/textcase.dm | 12 ++-- .../wiremod/components/string/tostring.dm | 1 + .../wiremod/components/utility/clock.dm | 9 +++ .../wiremod/components/utility/combiner.dm | 37 +++++----- .../wiremod/components/utility/delay.dm | 1 + .../wiremod/components/utility/multiplexer.dm | 66 ++++++++++++++++++ .../modules/wiremod/components/utility/ram.dm | 1 + .../wiremod/components/utility/typecheck.dm | 14 +++- code/modules/wiremod/integrated_circuit.dm | 33 +++++++++ code/modules/wiremod/shell/compact_remote.dm | 1 + code/modules/wiremod/shell/controller.dm | 1 + code/modules/wiremod/shell/drone.dm | 3 +- code/modules/wiremod/shell/moneybot.dm | 2 + tgstation.dme | 1 + .../IntegratedCircuit/CircuitInfo.js | 33 +++++++++ .../index.js} | 67 ++++++++++++++++--- .../styles/interfaces/IntegratedCircuit.scss | 9 +++ 41 files changed, 398 insertions(+), 95 deletions(-) create mode 100644 code/modules/wiremod/components/utility/multiplexer.dm create mode 100644 tgui/packages/tgui/interfaces/IntegratedCircuit/CircuitInfo.js rename tgui/packages/tgui/interfaces/{IntegratedCircuit.js => IntegratedCircuit/index.js} (90%) diff --git a/code/__DEFINES/wiremod.dm b/code/__DEFINES/wiremod.dm index 752d915fc93..f1f29bf6e89 100644 --- a/code/__DEFINES/wiremod.dm +++ b/code/__DEFINES/wiremod.dm @@ -25,6 +25,9 @@ // Other datatypes /// Atom datatype #define PORT_TYPE_ATOM "entity" +/// Any datatype (USED ONLY FOR DISPLAY, DO NOT USE) +#define COMP_TYPE_ANY "any" + /// The maximum range between a port and an atom #define PORT_ATOM_MAX_RANGE 7 @@ -81,9 +84,6 @@ // Clock component #define COMP_CLOCK_DELAY 0.9 SECONDS -// Combiner component -#define COMP_COMBINER_ANY "any" - // Shells /// Whether a circuit is stuck on a shell and cannot be removed (by a user) diff --git a/code/datums/components/shell.dm b/code/datums/components/shell.dm index 8d6abd53500..d0e546ae382 100644 --- a/code/datums/components/shell.dm +++ b/code/datums/components/shell.dm @@ -105,6 +105,10 @@ source.balloon_alert(attacker, "[locked? "locked" : "unlocked"] [source]") return COMPONENT_NO_AFTERATTACK + if(attached_circuit && istype(item, /obj/item/circuit_component)) + attached_circuit.add_component(item, attacker) + return + if(!istype(item, /obj/item/integrated_circuit)) return var/obj/item/integrated_circuit/logic_board = item @@ -167,10 +171,15 @@ SIGNAL_HANDLER remove_circuit() -/datum/component/shell/proc/on_circuit_add_component_manually(datum/source, obj/item/circuit_component/added_comp) +/datum/component/shell/proc/on_circuit_add_component_manually(atom/source, obj/item/circuit_component/added_comp, mob/living/user) SIGNAL_HANDLER + if(locked) + source.balloon_alert(user, "it's locked!") + return COMPONENT_CANCEL_ADD_COMPONENT - return COMPONENT_CANCEL_ADD_COMPONENT + if(length(attached_circuit.attached_components) - length(unremovable_circuit_components) >= capacity) + source.balloon_alert(user, "it's at maximum capacity!") + return COMPONENT_CANCEL_ADD_COMPONENT /** * Attaches a circuit to the parent. Doesn't do any checks to see for any existing circuits so that should be done beforehand. diff --git a/code/modules/research/designs/wiremod_designs.dm b/code/modules/research/designs/wiremod_designs.dm index 55e46c3afb3..9c13ffee8a7 100644 --- a/code/modules/research/designs/wiremod_designs.dm +++ b/code/modules/research/designs/wiremod_designs.dm @@ -37,162 +37,147 @@ departmental_flags = DEPARTMENTAL_FLAG_SCIENCE category = list("Circuitry", "Components") +/datum/design/component/New() + . = ..() + if(build_path) + var/obj/item/circuit_component/component_path = build_path + desc = initial(component_path.display_desc) + /datum/design/component/arithmetic name = "Arithmetic Component" - desc = "General arithmetic component with add/subtract/multiplication/division capabilities." id = "comp_arithmetic" build_path = /obj/item/circuit_component/arithmetic /datum/design/component/clock name = "Clock Component" - desc = "A component that repeatedly fires." id = "comp_clock" build_path = /obj/item/circuit_component/clock /datum/design/component/comparison name = "Comparison Component" - desc = "A component that compares two objects." id = "comp_comparison" build_path = /obj/item/circuit_component/compare/comparison /datum/design/component/logic name = "Logic Component" - desc = "A component with 'and' and 'or' capabilities." id = "comp_logic" build_path = /obj/item/circuit_component/compare/logic /datum/design/component/delay name = "Delay Component" - desc = "A component that delays a signal by a specified duration." id = "comp_delay" build_path = /obj/item/circuit_component/delay /datum/design/component/index name = "Index Component" - desc = "A component that returns the value of a list at a given index." id = "comp_index" build_path = /obj/item/circuit_component/index /datum/design/component/length name = "Length Component" - desc = "A component that returns the length of its input." id = "comp_length" build_path = /obj/item/circuit_component/length /datum/design/component/light name = "Light Component" - desc = "A component that emits a light of a specific brightness and colour. Requires a shell." id = "comp_light" build_path = /obj/item/circuit_component/light /datum/design/component/not name = "Not Component" - desc = "A component that inverts its input." id = "comp_not" build_path = /obj/item/circuit_component/not /datum/design/component/ram name = "RAM Component" - desc = "A component that retains a variable." id = "comp_ram" build_path = /obj/item/circuit_component/ram /datum/design/component/random name = "Random Component" - desc = "A component that returns random values." id = "comp_random" build_path = /obj/item/circuit_component/random /datum/design/component/species name = "Get Species Component" - desc = "A component that returns the species of its input." id = "comp_species" build_path = /obj/item/circuit_component/species /datum/design/component/speech name = "Speech Component" - desc = "A component that sends a message. Requires a shell." id = "comp_speech" build_path = /obj/item/circuit_component/speech /datum/design/component/tostring name = "To String Component" - desc = "A component that converts its input to text." id = "comp_tostring" build_path = /obj/item/circuit_component/tostring /datum/design/component/typecheck name = "Typecheck Component" - desc = "A component that checks the type of its input." id = "comp_typecheck" build_path = /obj/item/circuit_component/compare/typecheck /datum/design/component/concat name = "Concatenation Component" - desc = "A component that combines strings." id = "comp_concat" build_path = /obj/item/circuit_component/concat /datum/design/component/textcase name = "Textcase Component" - desc = "A component that makes its input uppercase or lowercase." id = "comp_textcase" build_path = /obj/item/circuit_component/textcase /datum/design/component/hear name = "Voice Activator Component" - desc = "A component that listens for messages. Requires a shell." id = "comp_hear" build_path = /obj/item/circuit_component/hear /datum/design/component/contains name = "String Contains Component" - desc = "Checks if a string contains a word/letter" id = "comp_string_contains" build_path = /obj/item/circuit_component/compare/contains /datum/design/component/self name = "Self Component" - desc = "A component that returns the current shell." id = "comp_self" build_path = /obj/item/circuit_component/self /datum/design/component/radio name = "Radio Component" - desc = "A component that can listen and send frequencies." id = "comp_radio" build_path = /obj/item/circuit_component/radio /datum/design/component/gps name = "GPS Component" - desc = "A component that returns the xyz co-ordinates of itself." id = "comp_gps" build_path = /obj/item/circuit_component/gps /datum/design/component/direction name = "Direction Component" - desc = "A component that returns the direction of itself and an entity." id = "comp_direction" build_path = /obj/item/circuit_component/direction /datum/design/component/health name = "Health Component" - desc = "A component that returns the health of an organism." id = "comp_health" build_path = /obj/item/circuit_component/health /datum/design/component/combiner name = "Combiner Component" - desc = "A component that combines multiple inputs to provide 1 output." id = "comp_combiner" build_path = /obj/item/circuit_component/combiner /datum/design/component/pull name = "Pull Component" - desc = "A component that can force the shell to pull entities. Only works for drone shells." id = "comp_pull" build_path = /obj/item/circuit_component/pull +/datum/design/component/multiplexer + name = "Multiplexer Component" + id = "comp_multiplexer" + build_path = /obj/item/circuit_component/multiplexer + /datum/design/compact_remote_shell name = "Compact Remote Shell" desc = "A handheld shell with one big button." diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 8a15c5430c5..06677146d9b 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -223,6 +223,7 @@ "comp_length", "comp_light", "comp_logic", + "comp_multiplexer", "comp_not", "comp_radio", "comp_ram", diff --git a/code/modules/wiremod/component.dm b/code/modules/wiremod/component.dm index 3a12593c1bb..5e743169729 100644 --- a/code/modules/wiremod/component.dm +++ b/code/modules/wiremod/component.dm @@ -16,6 +16,9 @@ /// The name of the component shown on the UI var/display_name = "Generic" + /// The description of the component shown on the UI + var/display_desc = "A generic component" + /// The integrated_circuit that this component is attached to. var/obj/item/integrated_circuit/parent @@ -54,11 +57,16 @@ . = ..() if(name == COMPONENT_DEFAULT_NAME) name = "[lowertext(display_name)] [COMPONENT_DEFAULT_NAME]" + populate_options() if(length(options)) current_option = options[1] return INITIALIZE_HINT_LATELOAD +/// Called when the options variable should be set. +/obj/item/circuit_component/proc/populate_options() + return + /obj/item/circuit_component/LateInitialize() . = ..() if(circuit_flags & CIRCUIT_FLAG_INPUT_SIGNAL) @@ -187,3 +195,31 @@ if((circuit_flags & CIRCUIT_FLAG_INPUT_SIGNAL) && !COMPONENT_TRIGGERED_BY(trigger_input, port)) return TRUE + +/** + * Gets the UI notices to be displayed on the CircuitInfo panel. + * + * Returns a list of buttons in the following format + * list( + * "icon" = ICON(string) + * "content" = CONTENT(string) + * "color" = COLOR(string, not a hex) + * ) + */ +/obj/item/circuit_component/proc/get_ui_notices() + . = list() + + if(!removable) + . += list(list( + "icon" = "lock", + "content" = "Unremovable", + "color" = "red" + )) + + + if(length(input_ports)) + . += list(list( + "icon" = "bolt", + "content" = "Power Usage Per Input: [power_usage_per_input]", + "color" = "orange", + )) diff --git a/code/modules/wiremod/components/action/light.dm b/code/modules/wiremod/components/action/light.dm index d4137a4173f..f398ac9dafd 100644 --- a/code/modules/wiremod/components/action/light.dm +++ b/code/modules/wiremod/components/action/light.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/light display_name = "Light" + display_desc = "A component that emits a light of a specific brightness and colour. Requires a shell." /// The colours of the light var/datum/port/input/red @@ -21,6 +22,14 @@ var/min_lightness = 0.4 var/shell_light_color +/obj/item/circuit_component/light/get_ui_notices() + . = ..() + . += list(list( + "icon" = "lightbulb", + "content" = "Maximum Brightness: [max_power]", + "color" = "orange" + )) + /obj/item/circuit_component/light/Initialize() . = ..() red = add_input_port("Red", PORT_TYPE_NUMBER) diff --git a/code/modules/wiremod/components/action/pull.dm b/code/modules/wiremod/components/action/pull.dm index e1a0b9d34b3..e10c71dc57e 100644 --- a/code/modules/wiremod/components/action/pull.dm +++ b/code/modules/wiremod/components/action/pull.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/pull display_name = "Start Pulling" + display_desc = "A component that can force the shell to pull entities. Only works for drone shells." /// Frequency input var/datum/port/input/target diff --git a/code/modules/wiremod/components/action/radio.dm b/code/modules/wiremod/components/action/radio.dm index ab8b0c9f782..b0b5fa58fa9 100644 --- a/code/modules/wiremod/components/action/radio.dm +++ b/code/modules/wiremod/components/action/radio.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/radio display_name = "Radio" + display_desc = "A component that can listen and send frequencies." /// Frequency input var/datum/port/input/freq diff --git a/code/modules/wiremod/components/action/speech.dm b/code/modules/wiremod/components/action/speech.dm index aafbbfdd1e0..8b0084fa522 100644 --- a/code/modules/wiremod/components/action/speech.dm +++ b/code/modules/wiremod/components/action/speech.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/speech display_name = "Speech" + display_desc = "A component that sends a message. Requires a shell." /// The message to send var/datum/port/input/message @@ -16,6 +17,14 @@ COOLDOWN_DECLARE(next_speech) +/obj/item/circuit_component/speech/get_ui_notices() + . = ..() + . += list(list( + "icon" = "stopwatch", + "content" = "Speech Cooldown: [DisplayTimeText(speech_cooldown)]", + "color" = "orange", + )) + /obj/item/circuit_component/speech/Initialize() . = ..() message = add_input_port("Message", PORT_TYPE_STRING, FALSE) diff --git a/code/modules/wiremod/components/atom/direction.dm b/code/modules/wiremod/components/atom/direction.dm index 62a6806d0b7..872076af7f2 100644 --- a/code/modules/wiremod/components/atom/direction.dm +++ b/code/modules/wiremod/components/atom/direction.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/direction display_name = "Get Direction" + display_desc = "A component that returns the direction of itself and an entity." /// The input port var/datum/port/input/input_port @@ -23,6 +24,14 @@ /// Maximum range for a valid direction to be returned var/max_range = 7 +/obj/item/circuit_component/direction/get_ui_notices() + . = ..() + . += list(list( + "icon" = "info", + "content" = "Maximum Range: [max_range] tiles", + "color" = "orange", + )) + /obj/item/circuit_component/direction/Initialize() . = ..() input_port = add_input_port("Organism", PORT_TYPE_ATOM) diff --git a/code/modules/wiremod/components/atom/gps.dm b/code/modules/wiremod/components/atom/gps.dm index 9dc4ba72755..3c0b70b4188 100644 --- a/code/modules/wiremod/components/atom/gps.dm +++ b/code/modules/wiremod/components/atom/gps.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/gps display_name = "Internal GPS" + display_desc = "A component that returns the xyz co-ordinates of itself." /// The result from the output var/datum/port/output/x_pos diff --git a/code/modules/wiremod/components/atom/health.dm b/code/modules/wiremod/components/atom/health.dm index 7a9dcaba61b..af8afcb3167 100644 --- a/code/modules/wiremod/components/atom/health.dm +++ b/code/modules/wiremod/components/atom/health.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/health display_name = "Get Health" + display_desc = "A component that returns the health of an organism." /// The input port var/datum/port/input/input_port @@ -24,6 +25,14 @@ var/max_range = 5 +/obj/item/circuit_component/health/get_ui_notices() + . = ..() + . += list(list( + "icon" = "info", + "content" = "Maximum Range: [max_range] tiles", + "color" = "orange", + )) + /obj/item/circuit_component/health/Initialize() . = ..() input_port = add_input_port("Organism", PORT_TYPE_ATOM) diff --git a/code/modules/wiremod/components/atom/hear.dm b/code/modules/wiremod/components/atom/hear.dm index 92dad54c4ce..322253001e3 100644 --- a/code/modules/wiremod/components/atom/hear.dm +++ b/code/modules/wiremod/components/atom/hear.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/hear display_name = "Voice Activator" + display_desc = "A component that listens for messages. Requires a shell." flags_1 = HEAR_1 diff --git a/code/modules/wiremod/components/atom/self.dm b/code/modules/wiremod/components/atom/self.dm index fdd69567da7..364d51cd6d6 100644 --- a/code/modules/wiremod/components/atom/self.dm +++ b/code/modules/wiremod/components/atom/self.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/self display_name = "Self" + display_desc = "A component that returns the current shell." /// The shell this component is attached to. var/datum/port/output/output diff --git a/code/modules/wiremod/components/atom/species.dm b/code/modules/wiremod/components/atom/species.dm index cf774ae3640..7c3735f852c 100644 --- a/code/modules/wiremod/components/atom/species.dm +++ b/code/modules/wiremod/components/atom/species.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/species display_name = "Get Species" + display_desc = "A component that returns the species of its input." /// The input port var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/math/arithmetic.dm b/code/modules/wiremod/components/math/arithmetic.dm index 2b6db052fc6..6b010b08e0e 100644 --- a/code/modules/wiremod/components/math/arithmetic.dm +++ b/code/modules/wiremod/components/math/arithmetic.dm @@ -6,6 +6,7 @@ */ /obj/item/circuit_component/arithmetic display_name = "Arithmetic" + display_desc = "General arithmetic component with arithmetic capabilities." /// The amount of input ports to have var/input_port_amount = 4 @@ -15,17 +16,18 @@ circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL -GLOBAL_LIST_INIT(comp_arithmetic_options, list( - COMP_ARITHMETIC_ADD, - COMP_ARITHMETIC_SUBTRACT, - COMP_ARITHMETIC_MULTIPLY, - COMP_ARITHMETIC_DIVIDE, - COMP_ARITHMETIC_MIN, - COMP_ARITHMETIC_MAX, -)) +/obj/item/circuit_component/arithmetic/populate_options() + var/static/component_options = list( + COMP_ARITHMETIC_ADD, + COMP_ARITHMETIC_SUBTRACT, + COMP_ARITHMETIC_MULTIPLY, + COMP_ARITHMETIC_DIVIDE, + COMP_ARITHMETIC_MIN, + COMP_ARITHMETIC_MAX, + ) + options = component_options /obj/item/circuit_component/arithmetic/Initialize() - options = GLOB.comp_arithmetic_options . = ..() for(var/port_id in 1 to input_port_amount) var/letter = ascii2text(text2ascii("A") + (port_id-1)) diff --git a/code/modules/wiremod/components/math/comparison.dm b/code/modules/wiremod/components/math/comparison.dm index 46e7910ab2c..af90d612179 100644 --- a/code/modules/wiremod/components/math/comparison.dm +++ b/code/modules/wiremod/components/math/comparison.dm @@ -5,22 +5,21 @@ */ /obj/item/circuit_component/compare/comparison display_name = "Comparison" + display_desc = "A component that compares two objects." input_port_amount = 2 var/current_type = PORT_TYPE_ANY -GLOBAL_LIST_INIT(comp_comparison_options, list( - COMP_COMPARISON_EQUAL, - COMP_COMPARISON_NOT_EQUAL, - COMP_COMPARISON_GREATER_THAN, - COMP_COMPARISON_LESS_THAN, - COMP_COMPARISON_GREATER_THAN_OR_EQUAL, - COMP_COMPARISON_LESS_THAN_OR_EQUAL -)) - -/obj/item/circuit_component/compare/comparison/Initialize() - options = GLOB.comp_comparison_options - return ..() +/obj/item/circuit_component/compare/comparison/populate_options() + var/static/component_options = list( + COMP_COMPARISON_EQUAL, + COMP_COMPARISON_NOT_EQUAL, + COMP_COMPARISON_GREATER_THAN, + COMP_COMPARISON_LESS_THAN, + COMP_COMPARISON_GREATER_THAN_OR_EQUAL, + COMP_COMPARISON_LESS_THAN_OR_EQUAL, + ) + options = component_options /obj/item/circuit_component/compare/comparison/input_received(datum/port/input/port) switch(current_option) diff --git a/code/modules/wiremod/components/math/index.dm b/code/modules/wiremod/components/math/index.dm index 9c3f34c28c3..b327f814b8f 100644 --- a/code/modules/wiremod/components/math/index.dm +++ b/code/modules/wiremod/components/math/index.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/index display_name = "Index List" + display_desc = "A component that returns the value of a list at a given index." /// The input port var/datum/port/input/list_port diff --git a/code/modules/wiremod/components/math/length.dm b/code/modules/wiremod/components/math/length.dm index 4382d17873c..4ebe782a4b7 100644 --- a/code/modules/wiremod/components/math/length.dm +++ b/code/modules/wiremod/components/math/length.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/length display_name = "Length" + display_desc = "A component that returns the length of its input." /// The input port var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/math/logic.dm b/code/modules/wiremod/components/math/logic.dm index acedb79613c..efb6b410b0e 100644 --- a/code/modules/wiremod/components/math/logic.dm +++ b/code/modules/wiremod/components/math/logic.dm @@ -5,17 +5,15 @@ */ /obj/item/circuit_component/compare/logic display_name = "Logic" + display_desc = "A component with 'and' and 'or' capabilities." - -GLOBAL_LIST_INIT(comp_logic_options, list( - COMP_LOGIC_AND, - COMP_LOGIC_OR, - COMP_LOGIC_XOR -)) - -/obj/item/circuit_component/compare/logic/Initialize() - options = GLOB.comp_logic_options - return ..() +/obj/item/circuit_component/compare/logic/populate_options() + var/static/component_options = list( + COMP_LOGIC_AND, + COMP_LOGIC_OR, + COMP_LOGIC_XOR, + ) + options = component_options /obj/item/circuit_component/compare/logic/do_comparisons(list/ports) . = FALSE diff --git a/code/modules/wiremod/components/math/not.dm b/code/modules/wiremod/components/math/not.dm index a147224d6dc..dd60c593ecb 100644 --- a/code/modules/wiremod/components/math/not.dm +++ b/code/modules/wiremod/components/math/not.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/not display_name = "Not" + display_desc = "A component that inverts its input." /// The input port var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/math/random.dm b/code/modules/wiremod/components/math/random.dm index 47b2e765d17..dce8296efac 100644 --- a/code/modules/wiremod/components/math/random.dm +++ b/code/modules/wiremod/components/math/random.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/random display_name = "Random" + display_desc = "A component that returns random values." /// The minimum value that the random number can be var/datum/port/input/minimum diff --git a/code/modules/wiremod/components/string/concat.dm b/code/modules/wiremod/components/string/concat.dm index 16691f88920..ac4ba9d0665 100644 --- a/code/modules/wiremod/components/string/concat.dm +++ b/code/modules/wiremod/components/string/concat.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/concat display_name = "Concatenate" + display_desc = "A component that combines strings." /// The amount of input ports to have var/input_port_amount = 4 diff --git a/code/modules/wiremod/components/string/contains.dm b/code/modules/wiremod/components/string/contains.dm index 3f5c34e595a..61c48a476b2 100644 --- a/code/modules/wiremod/components/string/contains.dm +++ b/code/modules/wiremod/components/string/contains.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/compare/contains display_name = "String Contains" + display_desc = "Checks if a string contains a word/letter" input_port_amount = 0 diff --git a/code/modules/wiremod/components/string/textcase.dm b/code/modules/wiremod/components/string/textcase.dm index b2d6c926356..809f36bb0ab 100644 --- a/code/modules/wiremod/components/string/textcase.dm +++ b/code/modules/wiremod/components/string/textcase.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/textcase display_name = "Text Case" + display_desc = "A component that makes its input uppercase or lowercase." /// The input port var/datum/port/input/input_port @@ -14,13 +15,14 @@ circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL -GLOBAL_LIST_INIT(comp_text_operations, list( - COMP_TEXT_LOWER, - COMP_TEXT_UPPER -)) +/obj/item/circuit_component/textcase/populate_options() + var/static/component_options = list( + COMP_TEXT_LOWER, + COMP_TEXT_UPPER, + ) + options = component_options /obj/item/circuit_component/textcase/Initialize() - options = GLOB.comp_text_operations . = ..() input_port = add_input_port("Input", PORT_TYPE_STRING) output = add_output_port("Output", PORT_TYPE_STRING) diff --git a/code/modules/wiremod/components/string/tostring.dm b/code/modules/wiremod/components/string/tostring.dm index e447501e418..642594bb08c 100644 --- a/code/modules/wiremod/components/string/tostring.dm +++ b/code/modules/wiremod/components/string/tostring.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/tostring display_name = "To String" + display_desc = "A component that converts its input to text." /// The input port var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/utility/clock.dm b/code/modules/wiremod/components/utility/clock.dm index 9fe6c5699e7..91b3a0db4b3 100644 --- a/code/modules/wiremod/components/utility/clock.dm +++ b/code/modules/wiremod/components/utility/clock.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/clock display_name = "Clock" + display_desc = "A component that repeatedly fires." /// Whether the clock is on or not var/datum/port/input/on @@ -12,6 +13,14 @@ /// The signal from this clock component var/datum/port/output/signal +/obj/item/circuit_component/clock/get_ui_notices() + . = ..() + . += list(list( + "icon" = "clock", + "content" = "Clock Interval: [DisplayTimeText(COMP_CLOCK_DELAY)]", + "color" = "orange", + )) + /obj/item/circuit_component/clock/Initialize() . = ..() on = add_input_port("On", PORT_TYPE_NUMBER) diff --git a/code/modules/wiremod/components/utility/combiner.dm b/code/modules/wiremod/components/utility/combiner.dm index 56bd664367d..7857f0f260a 100644 --- a/code/modules/wiremod/components/utility/combiner.dm +++ b/code/modules/wiremod/components/utility/combiner.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/combiner display_name = "Combiner" + display_desc = "A component that combines multiple inputs to provide 1 output." /// The amount of input ports to have var/input_port_amount = 4 @@ -13,34 +14,40 @@ var/current_type -GLOBAL_LIST_INIT(comp_combiner_options, list( - COMP_COMBINER_ANY, - PORT_TYPE_STRING, - PORT_TYPE_NUMBER, - PORT_TYPE_LIST, - PORT_TYPE_ATOM, - PORT_TYPE_SIGNAL, -)) +/obj/item/circuit_component/combiner/populate_options() + var/static/component_options = list( + COMP_TYPE_ANY, + PORT_TYPE_STRING, + PORT_TYPE_NUMBER, + PORT_TYPE_LIST, + PORT_TYPE_ATOM, + PORT_TYPE_SIGNAL, + ) + options = component_options /obj/item/circuit_component/combiner/Initialize() - options = GLOB.comp_combiner_options . = ..() - current_type = current_option + current_option = COMP_TYPE_ANY + current_type = COMP_TYPE_ANY for(var/port_id in 1 to input_port_amount) var/letter = ascii2text(text2ascii("A") + (port_id-1)) - add_input_port(letter, current_type) - output_port = add_output_port("Output", current_type) + add_input_port(letter, PORT_TYPE_ANY) + output_port = add_output_port("Output", PORT_TYPE_ANY) + +/obj/item/circuit_component/combiner/Destroy() + output_port = null + return ..() /obj/item/circuit_component/combiner/input_received(datum/port/input/port) . = ..() - if(current_type != current_option && (current_option != COMP_COMBINER_ANY || current_type != PORT_TYPE_ANY)) + if(current_type != current_option && (current_option != COMP_TYPE_ANY || current_type != PORT_TYPE_ANY)) current_type = current_option - if(current_type == COMP_COMBINER_ANY) + if(current_type == COMP_TYPE_ANY) current_type = PORT_TYPE_ANY for(var/datum/port/input/input_port as anything in input_ports) input_port.set_datatype(current_type) output_port.set_datatype(current_type) - output_port.set_output(port?.input_value) if(. || !port) return TRUE + output_port.set_output(port.input_value) diff --git a/code/modules/wiremod/components/utility/delay.dm b/code/modules/wiremod/components/utility/delay.dm index ff659162d2a..7403bb41321 100644 --- a/code/modules/wiremod/components/utility/delay.dm +++ b/code/modules/wiremod/components/utility/delay.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/delay display_name = "Delay" + display_desc = "A component that delays a signal by a specified duration." /// Amount to delay by var/datum/port/input/delay_amount diff --git a/code/modules/wiremod/components/utility/multiplexer.dm b/code/modules/wiremod/components/utility/multiplexer.dm new file mode 100644 index 00000000000..9ea48e70a0d --- /dev/null +++ b/code/modules/wiremod/components/utility/multiplexer.dm @@ -0,0 +1,66 @@ +/** + * # Combiner Component + * + * Combines multiple inputs into 1 output port. + */ +/obj/item/circuit_component/multiplexer + display_name = "Multiplexer" + display_desc = "A component that allows you to selectively choose which input port provides an output. The first port is the selector and takes a number between 1 and the maximum port amount." + circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL + + /// The port to select from, goes from 1 to input_port_amount + var/datum/port/input/input_port + + /// The amount of input ports to have + var/input_port_amount = 4 + + var/datum/port/output/output_port + + /// Current type of the ports + var/current_type + + /// The multiplexer inputs. These are what get selected for the output by the input_port. + var/list/datum/port/input/multiplexer_inputs + +/obj/item/circuit_component/multiplexer/populate_options() + var/static/component_options = list( + COMP_TYPE_ANY, + PORT_TYPE_STRING, + PORT_TYPE_NUMBER, + PORT_TYPE_LIST, + PORT_TYPE_ATOM, + ) + options = component_options + +/obj/item/circuit_component/multiplexer/Initialize() + . = ..() + current_option = COMP_TYPE_ANY + current_type = COMP_TYPE_ANY + input_port = add_input_port("Selector", PORT_TYPE_NUMBER, default = 1) + multiplexer_inputs = list() + for(var/port_id in 1 to input_port_amount) + multiplexer_inputs += add_input_port("Port [port_id]", PORT_TYPE_ANY) + output_port = add_output_port("Output", PORT_TYPE_ANY) + +/obj/item/circuit_component/multiplexer/Destroy() + output_port = null + multiplexer_inputs.Cut() + multiplexer_inputs = null + return ..() + + +/obj/item/circuit_component/multiplexer/input_received(datum/port/input/port) + . = ..() + if(current_type != current_option && (current_option != COMP_TYPE_ANY || current_type != PORT_TYPE_ANY)) + current_type = current_option + if(current_type == COMP_TYPE_ANY) + current_type = PORT_TYPE_ANY + for(var/datum/port/input/input_port as anything in multiplexer_inputs) + input_port.set_datatype(current_type) + output_port.set_datatype(current_type) + + input_port.set_input(clamp(input_port.input_value || 1, 1, input_port_amount), FALSE) + if(.) + return TRUE + output_port.set_output(multiplexer_inputs[input_port.input_value].input_value) + diff --git a/code/modules/wiremod/components/utility/ram.dm b/code/modules/wiremod/components/utility/ram.dm index 194f4474e54..9c8e120cd81 100644 --- a/code/modules/wiremod/components/utility/ram.dm +++ b/code/modules/wiremod/components/utility/ram.dm @@ -7,6 +7,7 @@ */ /obj/item/circuit_component/ram display_name = "RAM" + display_desc = "A component that retains a variable." /// The input to store var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/utility/typecheck.dm b/code/modules/wiremod/components/utility/typecheck.dm index f939f116836..faef753aca5 100644 --- a/code/modules/wiremod/components/utility/typecheck.dm +++ b/code/modules/wiremod/components/utility/typecheck.dm @@ -5,6 +5,7 @@ */ /obj/item/circuit_component/compare/typecheck display_name = "Typecheck" + display_desc = "A component that checks the type of its input." input_port_amount = 1 @@ -17,9 +18,16 @@ GLOBAL_LIST_INIT(comp_typecheck_options, list( COMP_TYPECHECK_HUMAN, )) -/obj/item/circuit_component/compare/typecheck/Initialize() - options = GLOB.comp_typecheck_options - return ..() +/obj/item/circuit_component/compare/typecheck/populate_options() + var/static/component_options = list( + PORT_TYPE_STRING, + PORT_TYPE_NUMBER, + PORT_TYPE_LIST, + PORT_TYPE_ATOM, + COMP_TYPECHECK_MOB, + COMP_TYPECHECK_HUMAN, + ) + options = component_options /obj/item/circuit_component/compare/typecheck/do_comparisons(list/ports) if(!length(ports)) diff --git a/code/modules/wiremod/integrated_circuit.dm b/code/modules/wiremod/integrated_circuit.dm index 35e486adbaf..b04c85acafe 100644 --- a/code/modules/wiremod/integrated_circuit.dm +++ b/code/modules/wiremod/integrated_circuit.dm @@ -32,6 +32,15 @@ /// The ID that is authorized to unlock/lock the shell so that the circuit can/cannot be removed. var/datum/weakref/owner_id + /// The current examined component. Used in IntegratedCircuit UI + var/datum/weakref/examined_component + + /// X position of the examined_component + var/examined_rel_x = 0 + + /// Y position of the examined component + var/examined_rel_y = 0 + /obj/item/integrated_circuit/Initialize() . = ..() RegisterSignal(src, COMSIG_ATOM_USB_CABLE_TRY_ATTACH, .proc/on_atom_usb_cable_try_attach) @@ -44,7 +53,10 @@ for(var/obj/item/circuit_component/to_delete in attached_components) remove_component(to_delete) qdel(to_delete) + attached_components.Cut() shell = null + examined_component = null + owner_id = null QDEL_NULL(cell) return ..() @@ -228,6 +240,16 @@ .["display_name"] = display_name + var/obj/item/circuit_component/examined + if(examined_component) + examined = examined_component.resolve() + + .["examined_name"] = examined?.display_name + .["examined_desc"] = examined?.display_desc + .["examined_notices"] = examined?.get_ui_notices() + .["examined_rel_x"] = examined_rel_x + .["examined_rel_y"] = examined_rel_y + /obj/item/integrated_circuit/ui_host(mob/user) if(shell) return shell @@ -396,6 +418,17 @@ shell.name = initial(shell.name) . = TRUE + if("set_examined_component") + var/component_id = text2num(params["component_id"]) + if(!WITHIN_RANGE(component_id, attached_components)) + return + examined_component = WEAKREF(attached_components[component_id]) + examined_rel_x = text2num(params["x"]) + examined_rel_y = text2num(params["y"]) + . = TRUE + if("remove_examined_component") + examined_component = null + . = TRUE /obj/item/integrated_circuit/proc/on_atom_usb_cable_try_attach(datum/source, obj/item/usb_cable/usb_cable, mob/user) usb_cable.balloon_alert(user, "circuit needs to be in a compatible shell") diff --git a/code/modules/wiremod/shell/compact_remote.dm b/code/modules/wiremod/shell/compact_remote.dm index cc3b5327243..d1877771e40 100644 --- a/code/modules/wiremod/shell/compact_remote.dm +++ b/code/modules/wiremod/shell/compact_remote.dm @@ -22,6 +22,7 @@ /obj/item/circuit_component/compact_remote display_name = "Compact Remote" + display_desc = "Used to receive inputs from the compact remote shell. Use the shell in hand to trigger the output signal." /// Called when attack_self is called on the shell. var/datum/port/output/signal diff --git a/code/modules/wiremod/shell/controller.dm b/code/modules/wiremod/shell/controller.dm index 84564986579..8df6782822b 100644 --- a/code/modules/wiremod/shell/controller.dm +++ b/code/modules/wiremod/shell/controller.dm @@ -23,6 +23,7 @@ /obj/item/circuit_component/controller display_name = "Controller" + display_desc = "Used to receive inputs from the controller shell. Use the shell in hand to trigger the output signal. Alt-click for the alternate signal. Right click for the extra signal." /// The three separate buttons that are called in attack_hand on the shell. var/datum/port/output/signal diff --git a/code/modules/wiremod/shell/drone.dm b/code/modules/wiremod/shell/drone.dm index c523c19d018..5944b662302 100644 --- a/code/modules/wiremod/shell/drone.dm +++ b/code/modules/wiremod/shell/drone.dm @@ -27,6 +27,7 @@ /obj/item/circuit_component/bot_circuit display_name = "Drone" + display_desc = "Used to send movement output signals to the drone shell." /// The inputs to allow for the drone to move var/datum/port/input/north @@ -41,7 +42,7 @@ COOLDOWN_DECLARE(west_delay) /// Delay between each movement - var/move_delay = COMP_CLOCK_DELAY + var/move_delay = PORT_INPUT_RECEIVE_DELAY /obj/item/circuit_component/bot_circuit/Initialize() . = ..() diff --git a/code/modules/wiremod/shell/moneybot.dm b/code/modules/wiremod/shell/moneybot.dm index 06af6971898..cceef55b0bc 100644 --- a/code/modules/wiremod/shell/moneybot.dm +++ b/code/modules/wiremod/shell/moneybot.dm @@ -38,6 +38,7 @@ /obj/item/circuit_component/money_dispenser display_name = "Money Dispenser" + display_desc = "Used to dispense money from the money bot. Money is taken from the internal storage of money." circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL /// The amount of money to dispense @@ -86,6 +87,7 @@ /obj/item/circuit_component/money_bot display_name = "Money Bot" var/obj/structure/money_bot/attached_bot + display_desc = "Used to receive input signals when money is inserted into the money bot shell and also keep track of the total money in the shell." /// Total money in the shell var/datum/port/output/total_money diff --git a/tgstation.dme b/tgstation.dme index a5de9f732ee..396512a40d2 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3631,6 +3631,7 @@ #include "code\modules\wiremod\components\utility\clock.dm" #include "code\modules\wiremod\components\utility\combiner.dm" #include "code\modules\wiremod\components\utility\delay.dm" +#include "code\modules\wiremod\components\utility\multiplexer.dm" #include "code\modules\wiremod\components\utility\ram.dm" #include "code\modules\wiremod\components\utility\typecheck.dm" #include "code\modules\wiremod\preset\hello_world.dm" diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/CircuitInfo.js b/tgui/packages/tgui/interfaces/IntegratedCircuit/CircuitInfo.js new file mode 100644 index 00000000000..8fd1263b7aa --- /dev/null +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/CircuitInfo.js @@ -0,0 +1,33 @@ +import { Button, Section, Stack, Box } from '../../components'; + +export const CircuitInfo = (props, context) => { + const { + name, + desc, + notices, + ...rest + } = props; + return ( + + + + {desc} + + + + {notices.map((val, index) => ( + +