diff --git a/code/modules/research/designs/wiremod_designs.dm b/code/modules/research/designs/wiremod_designs.dm index 3606dd67e2e..204ecaa289b 100644 --- a/code/modules/research/designs/wiremod_designs.dm +++ b/code/modules/research/designs/wiremod_designs.dm @@ -81,6 +81,11 @@ id = "comp_logic" build_path = /obj/item/circuit_component/compare/logic +/datum/design/component/toggle + name = "Toggle Component" + id = "comp_toggle" + build_path = /obj/item/circuit_component/compare/toggle + /datum/design/component/delay name = "Delay Component" id = "comp_delay" @@ -221,6 +226,11 @@ id = "comp_health" build_path = /obj/item/circuit_component/health +/datum/design/component/compare/health_state + name = "Compare Health State Component" + id = "comp_health_state" + build_path = /obj/item/circuit_component/compare/health_state + /datum/design/component/matscanner name = "Material Scanner" id = "comp_matscanner" @@ -337,6 +347,11 @@ id = "comp_ntnet_send" build_path = /obj/item/circuit_component/ntnet_send +/datum/design/component/list_literal/ntnet_send + name = "NTNet Transmitter List Literal" + id = "comp_ntnet_send_list_literal" + build_path = /obj/item/circuit_component/list_literal/ntnet_send + /datum/design/component/list_literal name = "List Literal Component" id = "comp_list_literal" diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 37245958aa3..69552a4923c 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -344,6 +344,7 @@ "comp_get_column", "comp_gps", "comp_health", + "comp_health_state", "comp_hear", "comp_id_access_reader", "comp_id_getter", @@ -368,6 +369,7 @@ "comp_not", "comp_ntnet_receive", "comp_ntnet_send", + "comp_ntnet_send_list_literal", "comp_pinpointer", "comp_pressuresensor", "comp_radio", @@ -386,6 +388,7 @@ "comp_tempsensor", "comp_textcase", "comp_timepiece", + "comp_toggle", "comp_tonumber", "comp_tostring", "comp_trigonometry", diff --git a/code/modules/wiremod/components/action/speech.dm b/code/modules/wiremod/components/action/speech.dm index 0e2936bcfbf..f149cba9122 100644 --- a/code/modules/wiremod/components/action/speech.dm +++ b/code/modules/wiremod/components/action/speech.dm @@ -11,6 +11,8 @@ /// The message to send var/datum/port/input/message + /// The quiet mode flag + var/datum/port/input/quietmode /// The cooldown for this component of how often it can send speech messages. var/speech_cooldown = 1 SECONDS @@ -21,6 +23,7 @@ /obj/item/circuit_component/speech/populate_ports() message = add_input_port("Message", PORT_TYPE_STRING, trigger = null) + quietmode = add_input_port("Quiet Mode", PORT_TYPE_NUMBER, default = 0) /obj/item/circuit_component/speech/input_received(datum/port/input/port) if(!parent.shell) @@ -31,5 +34,5 @@ if(message.value) var/atom/movable/shell = parent.shell - shell.say(message.value, forced = "circuit speech | [parent.get_creator()]") + shell.say(message.value, forced = "circuit speech | [parent.get_creator()]", message_range = quietmode.value > 0 ? WHISPER_RANGE : MESSAGE_RANGE) TIMER_COOLDOWN_START(shell, COOLDOWN_CIRCUIT_SPEECH, speech_cooldown) diff --git a/code/modules/wiremod/components/atom/health_state.dm b/code/modules/wiremod/components/atom/health_state.dm new file mode 100644 index 00000000000..dc83a41fdfd --- /dev/null +++ b/code/modules/wiremod/components/atom/health_state.dm @@ -0,0 +1,56 @@ +/** + * # Compare Health State Component + * + * Returns true when state matches entity. + */ + +/obj/item/circuit_component/compare/health_state + display_name = "Compare Health State" + desc = "A component that compares the health state of an organism, and returns true or false." + category = "Entity" + + /// The input port + var/datum/port/input/input_port + + /// Compare state option + var/datum/port/input/option/state_option + + var/max_range = 5 + +/obj/item/circuit_component/compare/health_state/get_ui_notices() + . = ..() + . += create_ui_notice("Maximum Range: [max_range] tiles", "orange", "info") + +/obj/item/circuit_component/compare/health_state/populate_options() + input_port = add_input_port("Organism", PORT_TYPE_ATOM) + + var/static/component_options = list( + "Alive", + "Asleep", + "Critical", + "Unconscious", + "Deceased", + ) + state_option = add_option_port("Comparison Option", component_options) + +/obj/item/circuit_component/compare/health_state/do_comparisons() + var/mob/living/organism = input_port.value + var/turf/current_turf = get_location() + if(!istype(organism) || current_turf.z != organism.z || get_dist(current_turf, organism) > max_range) + return FALSE + + var/current_option = state_option.value + var/state = organism.stat + switch(current_option) + if("Alive") + return state != DEAD + if("Asleep") + return !!organism.IsSleeping() && !organism.IsUnconscious() + if("Critical") + return state == SOFT_CRIT || state == HARD_CRIT + if("Unconscious") + return state == UNCONSCIOUS || state == HARD_CRIT || !!organism.IsUnconscious() + if("Deceased") + return state == DEAD + //Unknown state, something fucked up really bad - just return false + return FALSE diff --git a/code/modules/wiremod/components/atom/hear.dm b/code/modules/wiremod/components/atom/hear.dm index 3c3f05691b2..98c45a77f6f 100644 --- a/code/modules/wiremod/components/atom/hear.dm +++ b/code/modules/wiremod/components/atom/hear.dm @@ -8,6 +8,9 @@ desc = "A component that listens for messages. Requires a shell." category = "Entity" + /// The on/off port + var/datum/port/input/on + /// The message heard var/datum/port/output/message_port /// The language heard @@ -20,6 +23,7 @@ var/datum/port/output/trigger_port /obj/item/circuit_component/hear/populate_ports() + on = add_input_port("On", PORT_TYPE_NUMBER, default = 1) message_port = add_output_port("Message", PORT_TYPE_STRING) language_port = add_output_port("Language", PORT_TYPE_STRING) speaker_port = add_output_port("Speaker", PORT_TYPE_ATOM) @@ -40,6 +44,8 @@ return Hear(arglist(arguments)) /obj/item/circuit_component/hear/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods, message_range) + if(!on.value) + return FALSE if(speaker == parent?.shell) return FALSE diff --git a/code/modules/wiremod/components/math/toggle.dm b/code/modules/wiremod/components/math/toggle.dm new file mode 100644 index 00000000000..9f51c974cb3 --- /dev/null +++ b/code/modules/wiremod/components/math/toggle.dm @@ -0,0 +1,36 @@ +/** + * # Toggle Component + * + * Does a toggle between true and false on trigger + */ +/obj/item/circuit_component/compare/toggle + display_name = "Toggle" + desc = "A component that toggles between on and off when triggered. All input ports (except for set toggle) will trigger the component." + category = "Math" + + /// A signal to reset the toggle back to 0 + var/datum/port/input/toggle_set + /// A signal to toggle and return the current state + var/datum/port/input/toggle_and_compare + + var/toggle_state = FALSE + +/obj/item/circuit_component/compare/toggle/populate_custom_ports() + toggle_set = add_input_port("Set Toggle State", PORT_TYPE_NUMBER) + toggle_and_compare = add_input_port("Toggle And Compare", PORT_TYPE_SIGNAL) + toggle_state = FALSE + +/obj/item/circuit_component/compare/toggle/input_received(datum/port/input/port) + if(port == toggle_set) + toggle_state = !!port.value + return + if(COMPONENT_TRIGGERED_BY(toggle_and_compare, port)) + toggle_state = !toggle_state + if(toggle_state) + true.set_output(COMPONENT_SIGNAL) + else + false.set_output(COMPONENT_SIGNAL) + return ..() + +/obj/item/circuit_component/compare/toggle/do_comparisons() + return toggle_state diff --git a/code/modules/wiremod/components/ntnet/ntnet_send.dm b/code/modules/wiremod/components/ntnet/ntnet_send.dm index 105af11760b..7ff4372927f 100644 --- a/code/modules/wiremod/components/ntnet/ntnet_send.dm +++ b/code/modules/wiremod/components/ntnet/ntnet_send.dm @@ -27,12 +27,17 @@ data_package = add_input_port("Data Package", PORT_TYPE_LIST(PORT_TYPE_ANY)) enc_key = add_input_port("Encryption Key", PORT_TYPE_STRING) +/obj/item/circuit_component/ntnet_send/should_receive_input(datum/port/input/port) + . = ..() + if(!.) + return FALSE + /// If the server is down, don't use power or attempt to send data + return find_functional_ntnet_relay() + /obj/item/circuit_component/ntnet_send/pre_input_received(datum/port/input/port) if(port == list_options) var/new_datatype = list_options.value data_package.set_datatype(PORT_TYPE_LIST(new_datatype)) /obj/item/circuit_component/ntnet_send/input_received(datum/port/input/port) - if(!find_functional_ntnet_relay()) - return - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CIRCUIT_NTNET_DATA_SENT, list("data" = data_package.value, "enc_key" = enc_key.value, "port" = WEAKREF(data_package))) + send_ntnet_data(data_package, enc_key.value) diff --git a/code/modules/wiremod/components/ntnet/ntnet_send_literal.dm b/code/modules/wiremod/components/ntnet/ntnet_send_literal.dm new file mode 100644 index 00000000000..49e1c2b00ab --- /dev/null +++ b/code/modules/wiremod/components/ntnet/ntnet_send_literal.dm @@ -0,0 +1,30 @@ +/** + * # NTNet Transmitter List Literal Component + * + * Create a list literal and send a data package through NTNet + * + * This file is based off of ntnet_send.dm + * Any changes made to those files should be copied over with discretion + */ +/obj/item/circuit_component/list_literal/ntnet_send + display_name = "NTNet Transmitter List Literal" + desc = "Creates a list literal data package and sends it through NTNet. If Encryption Key is set then transmitted data will be only picked up by receivers with the same Encryption Key." + category = "NTNet" + + /// Encryption key + var/datum/port/input/enc_key + +/obj/item/circuit_component/list_literal/ntnet_send/populate_ports() + . = ..() + enc_key = add_input_port("Encryption Key", PORT_TYPE_STRING) + +/obj/item/circuit_component/list_literal/ntnet_send/should_receive_input(datum/port/input/port) + . = ..() + if(!.) + return FALSE + /// If the server is down, don't use power or attempt to send data + return find_functional_ntnet_relay() + +/obj/item/circuit_component/list_literal/ntnet_send/input_received(datum/port/input/port) + . = ..() + send_ntnet_data(list_output, enc_key.value) diff --git a/code/modules/wiremod/core/component.dm b/code/modules/wiremod/core/component.dm index 4d8344e1e6a..cf142d1e365 100644 --- a/code/modules/wiremod/core/component.dm +++ b/code/modules/wiremod/core/component.dm @@ -405,3 +405,14 @@ */ /obj/item/circuit_component/proc/unregister_usb_parent(atom/movable/shell) return + +/** + * Called when a circuit component requests to send Ntnet data signal. + * + * Arguments: + * * port - The required list port needed by the Ntnet recieve + * * key - The encryption key + * * signal_type - The signal type used for sending this global signal (optional, default is COMSIG_GLOB_CIRCUIT_NTNET_DATA_SENT) + */ +/obj/item/circuit_component/proc/send_ntnet_data(datum/port/input/port, key, signal_type = COMSIG_GLOB_CIRCUIT_NTNET_DATA_SENT) + SEND_GLOBAL_SIGNAL(signal_type, list("data" = port.value, "enc_key" = key, "port" = WEAKREF(port))) diff --git a/code/modules/wiremod/core/integrated_circuit.dm b/code/modules/wiremod/core/integrated_circuit.dm index 7dde89e5116..5a825b81482 100644 --- a/code/modules/wiremod/core/integrated_circuit.dm +++ b/code/modules/wiremod/core/integrated_circuit.dm @@ -80,6 +80,9 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) /// The Y position of the screen. Used for adding components. var/screen_y = 0 + /// The grid mode state for the circuit. + var/grid_mode = TRUE + /// The current size of the circuit. var/current_size = 0 @@ -400,6 +403,7 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) .["examined_notices"] = examined?.get_ui_notices() .["examined_rel_x"] = examined_rel_x .["examined_rel_y"] = examined_rel_y + .["grid_mode"] = grid_mode .["is_admin"] = (admin_only || isAdminGhostAI(user)) && check_rights_for(user.client, R_VAREDIT) @@ -577,6 +581,9 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) else set_display_name("") . = TRUE + if("toggle_grid_mode") + toggle_grid_mode() + . = TRUE if("set_examined_component") var/component_id = text2num(params["component_id"]) if(!WITHIN_RANGE(component_id, attached_components)) @@ -709,6 +716,10 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) else shell.name = initial(shell.name) +/// Toggles the grid mode property for this circuit. +/obj/item/integrated_circuit/proc/toggle_grid_mode() + grid_mode = !grid_mode + /** * Returns the creator of the integrated circuit. Used in admin messages and other related things. */ diff --git a/tgstation.dme b/tgstation.dme index 3dfe9614fc2..839c7b6628a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -6087,6 +6087,7 @@ #include "code\modules\wiremod\components\atom\direction.dm" #include "code\modules\wiremod\components\atom\gps.dm" #include "code\modules\wiremod\components\atom\health.dm" +#include "code\modules\wiremod\components\atom\health_state.dm" #include "code\modules\wiremod\components\atom\hear.dm" #include "code\modules\wiremod\components\atom\matscanner.dm" #include "code\modules\wiremod\components\atom\pinpointer.dm" @@ -6130,9 +6131,11 @@ #include "code\modules\wiremod\components\math\logic.dm" #include "code\modules\wiremod\components\math\not.dm" #include "code\modules\wiremod\components\math\random.dm" +#include "code\modules\wiremod\components\math\toggle.dm" #include "code\modules\wiremod\components\math\trigonometry.dm" #include "code\modules\wiremod\components\ntnet\ntnet_receive.dm" #include "code\modules\wiremod\components\ntnet\ntnet_send.dm" +#include "code\modules\wiremod\components\ntnet\ntnet_send_literal.dm" #include "code\modules\wiremod\components\sensors\pressuresensor.dm" #include "code\modules\wiremod\components\sensors\tempsensor.dm" #include "code\modules\wiremod\components\sensors\view_sensor.dm" diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/ObjectComponent.jsx b/tgui/packages/tgui/interfaces/IntegratedCircuit/ObjectComponent.jsx index d51c39714ef..22f7c6ce1a8 100644 --- a/tgui/packages/tgui/interfaces/IntegratedCircuit/ObjectComponent.jsx +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/ObjectComponent.jsx @@ -39,8 +39,8 @@ export class ObjectComponent extends Component { if (dragPos) { act('set_component_coordinates', { component_id: index, - rel_x: dragPos.x, - rel_y: dragPos.y, + rel_x: this.roundToGrid(dragPos.x), + rel_y: this.roundToGrid(dragPos.y), }); } @@ -81,6 +81,12 @@ export class ObjectComponent extends Component { ); } + // Round the units to the grid (bypass if grid mode is off) + roundToGrid(input_value) { + if (!this.props.gridMode) return input_value; + return Math.round(input_value / 10) * 10; + } + render() { const { input_ports, @@ -99,14 +105,15 @@ export class ObjectComponent extends Component { onPortRightClick = noop, onPortMouseUp = noop, act = noop, + gridMode = true, ...rest } = this.props; const { startPos, dragPos } = this.state; let [x_pos, y_pos] = [x, y]; if (dragPos && startPos && startPos.x === x_pos && startPos.y === y_pos) { - x_pos = dragPos.x; - y_pos = dragPos.y; + x_pos = this.roundToGrid(dragPos.x); + y_pos = this.roundToGrid(dragPos.y); } // Assigned onto the ports diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/index.jsx b/tgui/packages/tgui/interfaces/IntegratedCircuit/index.jsx index 79e4df4109f..316a1754b45 100644 --- a/tgui/packages/tgui/interfaces/IntegratedCircuit/index.jsx +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/index.jsx @@ -401,6 +401,7 @@ export class IntegratedCircuit extends Component { examined_rel_y, screen_x, screen_y, + grid_mode, is_admin, variables, global_basic_types, @@ -473,6 +474,7 @@ export class IntegratedCircuit extends Component { position="absolute" top={0} color="transparent" + tooltip="Show Variables Menu" icon="cog" selected={variableMenuOpen} onClick={() => @@ -487,6 +489,7 @@ export class IntegratedCircuit extends Component { position="absolute" top={0} color="transparent" + tooltip="Show Components Menu" icon="plus" selected={componentMenuOpen} onClick={() => @@ -496,6 +499,17 @@ export class IntegratedCircuit extends Component { } /> + +