From fc711a828e18d43a83229263fa251edb34635dbf Mon Sep 17 00:00:00 2001 From: Mothblocks <35135081+Mothblocks@users.noreply.github.com> Date: Mon, 26 Jul 2021 04:10:16 -0700 Subject: [PATCH] Brain-computer interfaces, circuits in your brain (#60338) BCIs are a new shell that can be implanted in your brain through surgery or through a BCI Manipulation Chamber, which provide the ability to easily implant and remove BCIs. They are the same size as compact remotes and generally share the same limitations. Also adds CIRCUIT_FLAG_HIDDEN, to hide components from the UI. I didn't end up needing this, but Watermelon said he had ideas for it, so eh. Why It's Good For The Game BCIs provide an interesting, stealthy input method for circuits. They are seen as a healthier alternative to nanites, and improve on them in several ways: Circuits have limited manipulation of the world, and intentionally do not perform the ability to provide passive healing, revives, etc. Circuits have a significantly better UI and UX than nanites. Circuits regularly get content expansions, which means that as a side-effect, there'll often be new things to play with for BCIs. Other point to make: BCI implanters have no cloud, and instead require the BCI to be put inside the machine. This means it requires the attention of the scientist (or even just a box with them inside). With Adds the ability to save/load circuits for admins. Adds the ability to duplicate modules in a round. #60222, which lets you reprint a circuit you made that round, this means you can print out lots of BCIs, rather than going through the tedium of constantly remaking it. BCI implanters are not roundstart, but rather in the advanced shells node. This is essentially the same as nanites, except for the difference of nanites starting with all the machinery, but none of the powers. Changelog cl add: Added brain-computer interface circuit shells. /cl --- code/__DEFINES/dcs/signals.dm | 8 + code/__DEFINES/wiremod.dm | 2 + .../research/designs/wiremod_designs.dm | 20 + code/modules/research/techweb/all_nodes.dm | 2 + code/modules/surgery/organs/organ_internal.dm | 2 + code/modules/wiremod/integrated_circuit.dm | 4 + .../wiremod/shell/brain_computer_interface.dm | 545 ++++++++++++++++++ code/modules/wiremod/shell/shell_items.dm | 5 + icons/obj/wiremod.dmi | Bin 20697 -> 21129 bytes tgstation.dme | 1 + .../interfaces/IntegratedCircuit/index.js | 6 +- 11 files changed, 594 insertions(+), 1 deletion(-) create mode 100644 code/modules/wiremod/shell/brain_computer_interface.dm diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index cb2ff740a55..136f42a77eb 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -1393,3 +1393,11 @@ #define COMSIG_VACUUM_BAG_ATTACH "comsig_vacuum_bag_attach" /// Called on a bag being detached from a vacuum parent #define COMSIG_VACUUM_BAG_DETACH "comsig_vacuum_bag_detach" + +// Organ signals +/// Called on the organ when it is implanted into someone (mob/living/carbon/receiver) +#define COMSIG_ORGAN_IMPLANTED "comsig_organ_implanted" + +/// Called on the organ when it is removed from someone (mob/living/carbon/old_owner) +#define COMSIG_ORGAN_REMOVED "comsig_organ_removed" + diff --git a/code/__DEFINES/wiremod.dm b/code/__DEFINES/wiremod.dm index 807270544cc..07278ad0f7d 100644 --- a/code/__DEFINES/wiremod.dm +++ b/code/__DEFINES/wiremod.dm @@ -138,3 +138,5 @@ #define CIRCUIT_FLAG_INPUT_SIGNAL (1<<0) /// Creates an output trigger that sends a pulse whenever the component is successfully triggered #define CIRCUIT_FLAG_OUTPUT_SIGNAL (1<<1) +/// This circuit component does not show in the menu. +#define CIRCUIT_FLAG_HIDDEN (1<<2) diff --git a/code/modules/research/designs/wiremod_designs.dm b/code/modules/research/designs/wiremod_designs.dm index b7734cfd4c5..a8200913a3d 100644 --- a/code/modules/research/designs/wiremod_designs.dm +++ b/code/modules/research/designs/wiremod_designs.dm @@ -321,3 +321,23 @@ build_path = /obj/item/shell/airlock build_type = PROTOLATHE | COMPONENT_PRINTER category = list("Circuitry", "Shells") + +/datum/design/bci_shell + name = "Brain-Computer Interface Shell" + desc = "An implant that can be placed in a user's head to control circuits using their brain." + id = "bci_shell" + materials = list( + /datum/material/glass = 2000, + /datum/material/iron = 8000, + ) + build_path = /obj/item/shell/bci + build_type = PROTOLATHE | COMPONENT_PRINTER + category = list("Circuitry", "Shells") + +/datum/design/board/bci_implanter + name = "Brain-Computer Interface Manipulation Chamber" + desc = "A machine that, when given a brain-computer interface, will implant it into an occupant. Otherwise, will remove any brain-computer interfaces they already have." + id = "bci_implanter" + build_path = /obj/item/circuitboard/machine/bci_implanter + build_type = IMPRINTER | COMPONENT_PRINTER + category = list("Circuitry", "Core") diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 6905d92ebe7..da16d8e1d80 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -656,6 +656,8 @@ description = "Grants access to more complicated shell designs." prereq_ids = list("basic_circuitry", "engineering") design_ids = list( + "bci_implanter", + "bci_shell", "bot_shell", "door_shell", "controller_shell", diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 0441a7ba465..cf251c74d67 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -61,6 +61,7 @@ else qdel(replaced) + SEND_SIGNAL(src, COMSIG_ORGAN_IMPLANTED, reciever) SEND_SIGNAL(reciever, COMSIG_CARBON_GAIN_ORGAN, src, special) owner = reciever @@ -92,6 +93,7 @@ for(var/datum/action/action as anything in actions) action.Remove(organ_owner) + SEND_SIGNAL(src, COMSIG_ORGAN_REMOVED, organ_owner) SEND_SIGNAL(organ_owner, COMSIG_CARBON_LOSE_ORGAN, src, special) START_PROCESSING(SSobj, src) diff --git a/code/modules/wiremod/integrated_circuit.dm b/code/modules/wiremod/integrated_circuit.dm index b1415f682b7..b203be6411e 100644 --- a/code/modules/wiremod/integrated_circuit.dm +++ b/code/modules/wiremod/integrated_circuit.dm @@ -224,6 +224,10 @@ . = list() .["components"] = list() for(var/obj/item/circuit_component/component as anything in attached_components) + if (component.circuit_flags & CIRCUIT_FLAG_HIDDEN) + .["components"] += null + continue + var/list/component_data = list() component_data["input_ports"] = list() for(var/datum/port/input/port as anything in component.input_ports) diff --git a/code/modules/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm new file mode 100644 index 00000000000..a97b6dad692 --- /dev/null +++ b/code/modules/wiremod/shell/brain_computer_interface.dm @@ -0,0 +1,545 @@ +/obj/item/organ/cyberimp/bci + name = "brain-computer interface" + desc = "An implant that can be placed in a user's head to control circuits using their brain." + icon = 'icons/obj/wiremod.dmi' + icon_state = "bci" + zone = BODY_ZONE_HEAD + w_class = WEIGHT_CLASS_TINY + +/obj/item/organ/cyberimp/bci/Initialize() + . = ..() + + AddComponent(/datum/component/shell, list( + new /obj/item/circuit_component/bci_core, + new /obj/item/circuit_component/bci_action("One"), + new /obj/item/circuit_component/bci_action("Two"), + new /obj/item/circuit_component/bci_action("Three"), + ), SHELL_CAPACITY_SMALL) + +/obj/item/organ/cyberimp/bci/Insert(mob/living/carbon/reciever, special, drop_if_replaced) + . = ..() + + // Organs are put in nullspace, but this breaks circuit interactions + forceMove(reciever) + +/obj/item/organ/cyberimp/bci/say(message, bubble_type, list/spans, sanitize, datum/language/language, ignore_spam, forced) + if (owner) + // Otherwise say_dead will be called. + // It's intentional that a circuit for a dead person does not speak from the shell. + if (owner.stat == DEAD) + return + + owner.say(message, forced = "circuit speech") + else + return ..() + +/obj/item/circuit_component/bci + display_name = "Brain-Computer Interface" + display_desc = "Used to receive inputs for the brain-computer interface. User is presented with three buttons." + +/obj/item/circuit_component/bci_action + display_name = "BCI Action" + display_desc = "Represents an action the user can take when implanted with the brain-computer interface." + + /// The name to use for the button + var/datum/port/input/button_name + + /// Called when the user presses the button + var/datum/port/output/signal + + /// A reference to the action button itself + var/datum/action/innate/bci_action/bci_action + +/obj/item/circuit_component/bci_action/Initialize(mapload, default_icon) + . = ..() + + if (!isnull(default_icon)) + set_option(default_icon) + + button_name = add_input_port("Name", PORT_TYPE_STRING) + + signal = add_output_port("Signal", PORT_TYPE_SIGNAL) + +/obj/item/circuit_component/bci_action/Destroy() + button_name = null + signal = null + + QDEL_NULL(bci_action) + + return ..() + +/obj/item/circuit_component/bci_action/populate_options() + var/static/action_options = list( + "Blank", + + "One", + "Two", + "Three", + "Four", + "Five", + + "Blood", + "Bomb", + "Brain", + "Brain Damage", + "Cross", + "Electricity", + "Exclamation", + "Heart", + "Id", + "Info", + "Injection", + "Magnetism", + "Minus", + "Network", + "Plus", + "Power", + "Question", + "Radioactive", + "Reaction", + "Repair", + "Say", + "Scan", + "Shield", + "Skull", + "Sleep", + "Wireless", + ) + + options = action_options + +/obj/item/circuit_component/bci_action/register_shell(atom/movable/shell) + var/obj/item/organ/cyberimp/bci/bci = shell + + bci_action = new(src) + update_action() + + bci.actions += list(bci_action) + +/obj/item/circuit_component/bci_action/unregister_shell(atom/movable/shell) + var/obj/item/organ/cyberimp/bci/bci = shell + + bci.actions -= bci_action + QDEL_NULL(bci_action) + +/obj/item/circuit_component/bci_action/input_received(datum/port/input/port) + . = ..() + + if (.) + return + + if (!isnull(bci_action)) + update_action() + +/obj/item/circuit_component/bci_action/proc/update_action() + bci_action.name = button_name.input_value + bci_action.button_icon_state = "nanite_[replacetextEx(lowertext(current_option), " ", "_")]" + +/datum/action/innate/bci_action + name = "Action" + icon_icon = 'icons/mob/actions/actions_items.dmi' + check_flags = AB_CHECK_CONSCIOUS + button_icon_state = "nanite_power" + + var/obj/item/circuit_component/bci_action/circuit_component + +/datum/action/innate/bci_action/New(obj/item/circuit_component/bci_action/circuit_component) + ..() + + src.circuit_component = circuit_component + +/datum/action/innate/bci_action/Destroy() + circuit_component.bci_action = null + circuit_component = null + + return ..() + +/datum/action/innate/bci_action/Activate() + circuit_component.signal.set_output(COMPONENT_SIGNAL) + +/obj/item/circuit_component/bci_core + display_name = "BCI Core" + display_desc = "Controls the core operations of the BCI." + + /// A reference to the action button to look at charge/get info + var/datum/action/innate/bci_charge_action/charge_action + + var/datum/port/input/message + var/datum/port/input/send_message_signal + + var/datum/port/output/user_port + + var/datum/weakref/user + +/obj/item/circuit_component/bci_core/Initialize() + . = ..() + + message = add_input_port("Message", PORT_TYPE_STRING) + send_message_signal = add_input_port("Send Message", PORT_TYPE_SIGNAL) + + user_port = add_output_port("User", PORT_TYPE_ATOM) + +/obj/item/circuit_component/bci_core/Destroy() + QDEL_NULL(charge_action) + + message = null + send_message_signal = null + + user_port = null + + user = null + + return ..() + +/obj/item/circuit_component/bci_core/register_shell(atom/movable/shell) + var/obj/item/organ/cyberimp/bci/bci = shell + + charge_action = new(src) + bci.actions += list(charge_action) + + RegisterSignal(shell, COMSIG_ORGAN_IMPLANTED, .proc/on_organ_implanted) + RegisterSignal(shell, COMSIG_ORGAN_REMOVED, .proc/on_organ_removed) + +/obj/item/circuit_component/bci_core/unregister_shell(atom/movable/shell) + var/obj/item/organ/cyberimp/bci/bci = shell + + bci.actions -= charge_action + QDEL_NULL(charge_action) + + UnregisterSignal(shell, list( + COMSIG_ORGAN_IMPLANTED, + COMSIG_ORGAN_REMOVED, + )) + +/obj/item/circuit_component/bci_core/input_received(datum/port/input/port) + . = ..() + if (.) + return . + + if (COMPONENT_TRIGGERED_BY(send_message_signal, port)) + var/sent_message = trim(message.input_value) + if (!sent_message) + return + + var/mob/living/carbon/resolved_owner = user?.resolve() + if (isnull(resolved_owner)) + return + + if (resolved_owner.stat == DEAD) + return + + to_chat(resolved_owner, "You hear a strange, robotic voice in your head... \"[span_robot("[html_encode(sent_message)]")]\"") + +/obj/item/circuit_component/bci_core/proc/on_organ_implanted(datum/source, mob/living/carbon/owner) + SIGNAL_HANDLER + + user_port.set_output(owner) + user = WEAKREF(owner) + + RegisterSignal(owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, .proc/on_borg_charge) + RegisterSignal(owner, COMSIG_LIVING_ELECTROCUTE_ACT, .proc/on_electrocute) + +/obj/item/circuit_component/bci_core/proc/on_organ_removed(datum/source, mob/living/carbon/owner) + SIGNAL_HANDLER + + user_port.set_output(null) + user = null + + UnregisterSignal(owner, list( + COMSIG_PROCESS_BORGCHARGER_OCCUPANT, + COMSIG_LIVING_ELECTROCUTE_ACT, + )) + +/obj/item/circuit_component/bci_core/proc/on_borg_charge(datum/source, amount) + SIGNAL_HANDLER + + if (isnull(parent.cell)) + return + + parent.cell.give(amount) + +/obj/item/circuit_component/bci_core/proc/on_electrocute(datum/source, shock_damage, siemens_coefficient, flags) + SIGNAL_HANDLER + + if (isnull(parent.cell)) + return + + if (flags & SHOCK_ILLUSION) + return + + parent.cell.give(shock_damage * 2) + to_chat(source, span_notice("You absorb some of the shock into your [parent.name]!")) + +/datum/action/innate/bci_charge_action + name = "Check BCI Charge" + check_flags = NONE + icon_icon = 'icons/obj/power.dmi' + button_icon_state = "cell" + + var/obj/item/circuit_component/bci_core/circuit_component + +/datum/action/innate/bci_charge_action/New(obj/item/circuit_component/bci_core/circuit_component) + ..() + + src.circuit_component = circuit_component + + button.maptext_x = 2 + button.maptext_y = 0 + update_maptext() + + START_PROCESSING(SSobj, src) + +/datum/action/innate/bci_charge_action/Destroy() + circuit_component.charge_action = null + circuit_component = null + + STOP_PROCESSING(SSobj, src) + + return ..() + +/datum/action/innate/bci_charge_action/Trigger() + var/obj/item/stock_parts/cell/cell = circuit_component.parent.cell + + if (isnull(cell)) + to_chat(owner, span_boldwarning("[circuit_component.parent] has no power cell.")) + else + to_chat(owner, span_info("[circuit_component.parent]'s [cell.name] has [cell.percent()]% charge left.")) + to_chat(owner, span_info("You can recharge it by using a cyborg recharging station.")) + +/datum/action/innate/bci_charge_action/process(delta_time) + update_maptext() + +/datum/action/innate/bci_charge_action/proc/update_maptext() + var/obj/item/stock_parts/cell/cell = circuit_component.parent.cell + button.maptext = cell ? MAPTEXT("[cell.percent()]%") : "" + +/obj/machinery/bci_implanter + name = "brain-computer interface manipulation chamber" + desc = "A machine that, when given a brain-computer interface, will implant it into an occupant. Otherwise, will remove any brain-computer interfaces they already have." + circuit = /obj/item/circuitboard/machine/bci_implanter + icon = 'icons/obj/machines/nanite_chamber.dmi' + icon_state = "nanite_chamber" + base_icon_state = "nanite_chamber" + layer = ABOVE_WINDOW_LAYER + use_power = IDLE_POWER_USE + anchored = TRUE + density = TRUE + obj_flags = NO_BUILD // Becomes undense when the door is open + idle_power_usage = 50 + active_power_usage = 300 + + var/busy = FALSE + var/busy_icon_state + var/locked = FALSE + + var/datum/weakref/bci_to_implant + + COOLDOWN_DECLARE(message_cooldown) + +/obj/machinery/bci_implanter/Initialize() + . = ..() + occupant_typecache = typecacheof(/mob/living/carbon) + +/obj/machinery/bci_implanter/Destroy() + QDEL_NULL(bci_to_implant) + return ..() + +/obj/machinery/bci_implanter/examine(mob/user) + . = ..() + + if (isnull(bci_to_implant?.resolve())) + . += span_notice("There is no BCI inserted.") + else + . += span_notice("Right-click to remove current BCI.") + +/obj/machinery/bci_implanter/proc/set_busy(status, working_icon) + busy = status + busy_icon_state = working_icon + update_appearance() + +/obj/machinery/bci_implanter/update_icon_state() + if (occupant) + icon_state = busy ? busy_icon_state : "[base_icon_state]_occupied" + return ..() + icon_state = "[base_icon_state][state_open ? "_open" : null]" + return ..() + +/obj/machinery/bci_implanter/update_overlays() + var/list/overlays = ..() + + if ((machine_stat & MAINT) || panel_open) + overlays += "maint" + return overlays + + if (machine_stat & (NOPOWER|BROKEN)) + return overlays + + if (busy || locked) + overlays += "red" + if (locked) + overlays += "bolted" + return overlays + + overlays += "green" + + return overlays + +/obj/machinery/bci_implanter/attack_hand_secondary(mob/user, list/modifiers) + . = ..() + if (. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return . + + if (locked) + balloon_alert(user, "it's locked!") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + var/obj/item/organ/cyberimp/bci/bci_to_implant_resolved = bci_to_implant?.resolve() + if (isnull(bci_to_implant_resolved) && user.Adjacent(src)) + balloon_alert(user, "no bci inserted!") + else + user.put_in_hands(bci_to_implant_resolved) + balloon_alert(user, "ejected bci") + + bci_to_implant = null + + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/machinery/bci_implanter/attackby(obj/item/weapon, mob/user, params) + var/obj/item/organ/cyberimp/bci/new_bci = weapon + if (istype(new_bci)) + if (!(locate(/obj/item/integrated_circuit) in new_bci)) + balloon_alert(user, "bci has no circuit!") + return + + var/obj/item/organ/cyberimp/bci/previous_bci_to_implant = bci_to_implant?.resolve() + + bci_to_implant = WEAKREF(weapon) + weapon.forceMove(src) + + if (isnull(previous_bci_to_implant)) + balloon_alert(user, "inserted bci") + else + balloon_alert(user, "swapped bci") + user.put_in_hands(previous_bci_to_implant) + + return + + return ..() + +/obj/machinery/bci_implanter/attackby_secondary(obj/item/weapon, mob/user, params) + if (!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, weapon)) + update_appearance() + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if (default_pry_open(weapon)) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if (default_deconstruction_crowbar(weapon)) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/machinery/bci_implanter/proc/start_process() + if (machine_stat & (NOPOWER|BROKEN)) + return + if ((machine_stat & MAINT) || panel_open) + return + if (!occupant || busy) + return + + var/locked_state = locked + locked = TRUE + + set_busy(TRUE, "[initial(icon_state)]_raising") + addtimer(CALLBACK(src, .proc/set_busy, TRUE, "[initial(icon_state)]_active"), 1 SECONDS) + addtimer(CALLBACK(src, .proc/set_busy, TRUE, "[initial(icon_state)]_falling"), 2 SECONDS) + addtimer(CALLBACK(src, .proc/complete_process, locked_state), 3 SECONDS) + +/obj/machinery/bci_implanter/proc/complete_process(locked_state) + locked = locked_state + set_busy(FALSE) + + var/mob/living/carbon/carbon_occupant = occupant + if (!istype(carbon_occupant)) + return + + playsound(loc, 'sound/machines/ping.ogg', 30, FALSE) + + var/obj/item/organ/cyberimp/bci/bci_organ = carbon_occupant.getorgan(/obj/item/organ/cyberimp/bci) + var/obj/item/organ/cyberimp/bci/bci_to_implant_resolved = bci_to_implant?.resolve() + + if (bci_organ) + bci_organ.Remove(carbon_occupant) + + if (isnull(bci_to_implant_resolved)) + say("Occupant's previous brain-computer interface has been transferred to internal storage unit.") + bci_organ.forceMove(src) + bci_to_implant = WEAKREF(bci_organ) + else + say("Occupant's previous brain-computer interface has been ejected.") + bci_organ.forceMove(drop_location()) + else if (!isnull(bci_to_implant_resolved)) + say("Occupant has been injected with [bci_to_implant_resolved].") + bci_to_implant_resolved.Insert(carbon_occupant) + bci_to_implant = null + +/obj/machinery/bci_implanter/open_machine() + if(state_open) + return FALSE + + ..() + + return TRUE + +/obj/machinery/bci_implanter/close_machine(mob/living/carbon/user) + if(!state_open) + return FALSE + + ..() + + var/mob/living/carbon/carbon_occupant = occupant + if (istype(occupant)) + var/obj/item/organ/cyberimp/bci/existing_bci_organ = carbon_occupant.getorgan(/obj/item/organ/cyberimp/bci) + if (isnull(existing_bci_organ) && isnull(bci_to_implant?.resolve())) + say("No brain-computer interface inserted, and occupant does not have one. Insert a BCI to implant one.") + playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE) + return FALSE + + addtimer(CALLBACK(src, .proc/start_process), 1 SECONDS) + return TRUE + +/obj/machinery/bci_implanter/relaymove(mob/living/user, direction) + var/message + + if (locked) + message = "it won't budge!" + else if (user.stat != CONSCIOUS) + message = "you don't have the energy!" + + if (!isnull(message)) + if (COOLDOWN_FINISHED(src, message_cooldown)) + COOLDOWN_START(src, message_cooldown, 5 SECONDS) + balloon_alert(user, "it won't budge!") + + return + + open_machine() + +/obj/machinery/bci_implanter/interact(mob/user) + if (state_open) + close_machine(null, user) + return + else if (locked) + balloon_alert(user, "it's locked!") + return + + open_machine() + +/obj/item/circuitboard/machine/bci_implanter + name = "Brain-Computer Interface Manipulation Chamber (Machine Board)" + greyscale_colors = CIRCUIT_COLOR_SCIENCE + build_path = /obj/machinery/bci_implanter + req_components = list( + /obj/item/stock_parts/micro_laser = 2, + /obj/item/stock_parts/manipulator = 1, + ) diff --git a/code/modules/wiremod/shell/shell_items.dm b/code/modules/wiremod/shell/shell_items.dm index 6f2abdfd12b..95e70d28ea0 100644 --- a/code/modules/wiremod/shell/shell_items.dm +++ b/code/modules/wiremod/shell/shell_items.dm @@ -52,3 +52,8 @@ icon_state = "construction" shell_to_spawn = /obj/machinery/door/airlock/shell screw_delay = 10 SECONDS + +/obj/item/shell/bci + name = "brain-computer interface assembly" + icon_state = "bci-open" + shell_to_spawn = /obj/item/organ/cyberimp/bci diff --git a/icons/obj/wiremod.dmi b/icons/obj/wiremod.dmi index e4f9afc8681b54ae92b55e260b246dd2a57e8725..6e6fec0e55e5c35c5f816335cef9984791346ccc 100644 GIT binary patch literal 21129 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 literal 20697 zcmafbby!qy*X|I~AfS@cNJzKR4I(KZ-QA4{3^TMyOLv2GcY_EBNK2PeLrDxZFmN`% z_dVbF-gB;V&L57~9@u+7v7U9`Ypr_`p{}Zck3)e20)g<~D9XMAflwrYf3#Q_z&8Vy zWyipUy|0$8r>vESg}a@rr=5#42;`HQmDC&4M@uLs=?MY=(}Ph#&LSC zlZz>8kcOT*BJP#S8{S9q*>-Ygk4E%<62CHLNk1aRSDv61pM|E<*5$4WooGJ}eH3~^ z0s9a!Qrp3rQepY%4?A;Oc!KxKG@L_{yhDWSqhJ}*sQMr=$6zU(j@LoWi^H``o78># zg*1NQRVQEVVtMy|zJUZRDgS)+Cw8pEs>i4CFxvCvBY$@e5OHqQp63zwYEuEL%wmX`I0Y2 zpbk2TWIw)_e~W*agjHeY=@L5nUQunh_9bQMEA53mm9#Ea1uH-6XTt);%pw!Z*vy(C z2}&B?ecFOS_3!ma`YPU}DznJBgI?kky|98lWwos55DSZ*`DrL*>TfEF6)$;%lNwHUIApaS z0wdonnLC)9)4U+VLXT5q)JhTX)1;Ubs>@D80@K^1prFvA*@Jm5*8UDR-$(O5QKFA0 z%#wH~tBG~+%j68h_5+FG&s*qnhfQEBnm6n4*)(nv2)fk#IKR&Q)BTb9P4~~Asz3M7 z`*zM)ITMtMK*#YVi|*FWN(>11uPaZjRq~6AF-octNbDFfd`S+}1{vAVaS4BsODA=18PKf(tsn*6$FeVV3NRG~$|pvzf#FQd&wqNG z!ilXZfL3on0}7L-BM9iOypdrT!=9MzUj6*C9O1N-a0LrhS{C=oP`gxtLbNKle7(N7 zM(0!yqEk{($acShzsPzFijYMOl%)MD!S*;gDBCrl$MaU!11OxbySfT>t^- zsQW%ZQzP}+;Y2(kX&FvlR~I$N<+Jztx$i~}+~Nqt{qn3^qB%;_r_4A;iz zPEy)1Uy&Pdq{07)L%*Z9|Eu!JkNi9+ypm$um=&Ur z+!RG2uP8#-Op_Us5YOMS=03ZfcKYceZqdp|F(4PIN8RINK5s<8INROjLgStJI(R?v z|=D)c^WKGYe|_QI!m}lJ@$ZkRa}sG&D5;|Cu-t~vF)eG0RkNP-NfrjIl9o7 zce&TM{mpJ`<0!=U=Xj_E?jms`)R6)EA)C3Iulz15j*+#4)S8B>`me1*q<2M3uupNI z_d55#^Ck#)&X9PJcqKDDvEv&BjTB`HzFta@y~o-m8rfWT8L@LSWg%364DV$CO^kf) zLXa8dq}mm7-ftTZWIFR#Ax=MRJCxLz5GP8)Z5vOTH~veaEPdb_L?l8D2_aB`a)q^+ zxLwFXzuijb(Zw(ZJ|W6A)WBlB8?vrXZmI-EU?p)ukKMiQJ1mOSbs2poO#QpCxa897 z$HIc%!Zl!-!<}y$Ebn>~N&`;WWLuzasXeq-}+EBW82l zKik=G zlwn4Hag*$>*$;zTFLOX$eOAt%FZQ&{3tw7+wb9_${{CsJbn8aZ_+YY*>uZ1Ucn^sa z()62LMNQ3wyse@|5cfMXW0TKSSjV+2f{?+q(Ku@G7}kUrMjnGOLyr$}4&v0=vR-ci zOP%6y0$&RT*6s?#5U+6;Elnm7&E%76hudvZ`{U!|f32<_JUFP}&Pq$0JcsfZKE)Oa3|4(cL>+A}sWY>?MK- z`Ju#)Qj12Sx_7NClgy24vX|0tas37NQl0?5F>Tx*BOt*_k5b6_+xh++3TWekoAY;m z-nqnC+Bhvy#Cp5}HBS-M8`+SxjmxNgwmdde|JR?#dWmB|A2OwO-M~cat82{hi?gVb zU3hV+PsCm%alx0!l~hPU>x%5(#ID%3fPs?Rp|i}Um|OpA;cWVcEP18Tv3dm0G+vUv zK!9?7sluL2!5YjLxITW0D_uM{(_WL<8{D;a0>j*W;m`1oms>rO7aLkvoXs$2>^%}2 z_CdE-gA#(wUD%4_MJoRcOLS8i{j1Je71qT5`ETi;x1cR1N%)wKkr78~q<#iRI;ji~ zsq`s=UmqbEfX@x;zbTLd$llFD?(qut!?rO+fN)O`X;U9l#Qihv>9-rY@=@+!YLLF= z<;)HI#onAdI5UX58uHlnF!n+)=G|we-M_u2gp(UAw;6}Apz}QkIVj}z8~LiI)&s&v z2Fxm!qhXwO>rYcM#7F3XQA-~+IY4X`7i@3xxB&qEiZ{XekGb@eG-@KynN479&%knM z&nYNg>c8%rn26g~Wcl{YgJv@>5_nU6ef>PLbVV|lFQP;t$G_x!Ocpx8slZ!6gM}t1$-FAA9}RN}`?7}@*s$?=fS}DdYQRuIn$B5yLwd+yZlmh= zVU>}A6QUdifpAj_PK;i)Crv?FT)34hHB8(^yS9Q>bSrwaD7l$>ZoIj>%Du~@u72$h zG;s8#YaS7mbo4bbH7(5z-a%>r;du9sh?b5-WT@Fxi1+6q6SC7VHE*8ueeF59=s?W3 z$ja_tEN{>(xs{0QwxX8r9rS=ZzUY|-<*`g`uyY6Z>iQ)%prD?LE&k{ojqNohE84`5 z>ow)h{4F!Eih>c`%R({=BFB?o=)(iPPUNT{#|t(iE{LAC(@jX4f@%kGlQGd+kWd~5 zhQJpvxu38<(nTLKB@4k@vcqT$93u}6CpX15f8kK{-9GBoXm+IZ^KuOahCf_n+3$z+TUTQg0KQBotW7fcC#ml|kdVHrG(YzxX_gZ7~vy^D?NWTQs-<&ULdCzN8$ zTe;(S>W@U|YiFN&#s5Jf9p1EHpj2V@d7hz20Qa{{)J?sGuSQ@`x>Pz*c3xFl@{QT1 zOaCoT&!F|(sm83#HfaFXj))2Za6M8y46mF7_emiuC_v6e`NCZM|4=?^pTx~mBkuXJ z3x|2OaSP?)6P~>lJlhU;=%MkTa&N~7q>i{oxiuC2qo!&)#|mb$#o*hrvd)(;z(Qkt zgGsH^CyBYmcq*`T_7=c?8JXY-R?gPs`UQ4?p7B=?yH5!@KD=$S&_Wd*6(v*j;}^CN zY?5~nYwP0Ol^{}7_du*cU;LH;vU#7N`(ZI$N9uE#be^14AF?WDYLbBF2E!V!?p;Ug z^1#|sWJ16oUYsm(3a1e&Xi`!|KQ2#n*4eRsA;7dKOs@(nw6OAhPT*Ft%RDIJdV;d{ zixI08k~znp*r3^Y0PV4;sn1G=kjw8MNo=pY_7Yj0+Hr@Iemon-=b%vg_~h7>Duj;3 zC>Zp`@9b9+MYiT-F7+9j`-mv+C{+!Z^psokZVsSi0B#LTE>##07KZ7yshqk_`=+K8 z0O$8d5@fOjX%1kL7ZC03htGJp1MG2PfMP*3?N1>T-Ko5%HfmvG3o3e zd3(Gh0FS?xmJ&t3ED3{5nP{CAxwWtK`Skb}2uoaL^u~CUM4)X!EZ4n+a@lUwY;Ir{ z*?`qJ2TaA6Wrs_*!YF^BmPc1EPE4#{^{@|2+#7V$+`mryCgkVNr+7WTV zy1Iq}ilJExTh;yh17mf!w>^*WvNpB$4yP!u*UmZA%Iu8xZ$g!TKY>En+7|0^13Fs+8+AeUK0B~eU14Z zbAsQA3P=%k?SOpK#`q5#`rSS=w7Z{n0@wdZ2j3l)`v@FWGPWiQ_^K;{`Zf#Y2_v># z)JPP0{K5N|NmGsD;Ox&obaXT6g8)DO z`gG16f57#K$zpzWh$cd5&_UZ|7L=5o50EOa>K8nMSOBlGd7SBGY3VC~++1bU_k-3- ztsi{lLntjNGZOpbn-bg?nt17fxYHkDyiX6D=}eY&V9OcE5b0T4Jv6&RrPF)l-n(qS zQvv{W?zCUx%ZS9$4>tUtFZ;|6Iw%MHF2ia)-ah?ng#QPbr6CG8CbJQD!?+138uy>g ztxuO90cFvrE#r1Wo&wRrfRNc{@*Aehe9U07^BZlpt)Sjq?qlI-_;(#X)S^Fg2?Z~O z9$0m2258+yRs!0pv9(oU32A^M3j#(p1d_aWNASxkzjCqKyqj+3Rd1f#A6O1dO8v46 zKp}vOEi1F!n6Yr6MnDHz-rysWm5DUd|}()j^iym_NGhJ z+JSIt;Clx^kC}~_o>KfK_-@V_BE786@(q$gM;(icRy~au5Xgl?=BMA$@m^N8pd_ke z87_byCrit?m?5&RAR~jex4+LLBEqI@V{Lt!T#qJU)9Mk9Fv z>wGQ&lo#OF^)*Ts76k|XMnt)Cg^!TmJ~hzy?EVCXO~RT)fTozhMtuB0MUQWI%8ttl z*SL(C(w5mo(IZY+(@eR^zExf%VSTc^AC6vq*}4(>nI_u8=cskZ(05e{ShWkz8g#bF z^p!Yk3FB(gG-V8cDxCNjUb>VIpek*bv!OPiOg*d!xb1h9=hI~cu4$pEbV3on^)``ZvjDWS9<95#)5IF%AOCxI_v z(<2K-T%?bNVQ*9F3-nZJ2?@0sC!%|21NQAa%jIjwNTDyz>KSky!>{Ad@+^Jcp$3A2 zTCo&iD23=*+wRqwu#a@Pz)~_u7VQPNdnA-VZ%*57CW8kwPaStWKi9^unWsWYtnV7%sjuYW%|#Nod0v}maH)4-)ue7K2we!B zW&IMAX@%AENGTCA`-c2l!pvB42?7l{#8+e1aRH&ug5$55#0D4sG6&0#uSe5!s1WZP zMl^D?gA!>6_9Wu?!@SMgt$)2OdPkO%+QV74)_anpW;$nMaD04)&Us+p`|S!{-+N&R zE!vTbYqN9BL2`?W4F!|~xe^4emyo^;{Y%Pq!$A(JIVBK{U}|iO<*gH)Chez}lpi+# zkh1H&I~AQV{9)>Np{y#iYjtRa^U!_T1_K}vmMl+yLz9Zx-SKzH%h8e_Stp8xF^n0a zziLwo6ES5u%QOEA3f53ojQ%_KgTsw4Bl!iic6)Xr^b15vLq*g6AOfL zcPhexeAXN4-5phBqYQmFg?SZOU0ON}7gttOGibv~6QAY^>3WtR5bT-rxu}{9Wol(K z)y&#j-tyH$u8Es$#z}hMmksxiN99a@u&EdQD{~U(Gn&tN^33-}C}=-QOgUD!r76qv zbMx@jI|{OONR-YF>hPQc6zpT14b=0)x_n+cT8i|jV!6YG^zL63rn5U8nQ`b()joKd zct5!;hT?|^=dkqj^p09aMYsSTU%~6|@^tWF=&WyZYfTLlfa~cSOD|8};&FK8UOE0Z zsU$*$5Qj&%Mk}JKEuIJl->q2$+-v zaz=dgXAhYwdwY9+{5a~w@ZE%3vR%6^^%vrot>biU&*fU^qkKfG%3O{+HtEDj;cjTR zp+4t(+Gf`r22Hw2{1uS#Zy_}u%>%1$yzpHKWta&|&|N~}U8#WY?K`+JM4!pFfjH3G z+WPx3VtRV|MIILoN`OejMZFnFT|k2Na;?4x@RA=lVGIH^VhqvoSn9&t?4Z?K_vzqf z7mHmR37Ho!i8{d&utFW}98>rk#fuDaU=#`W4h{}hbM>E%!NO^rPo*FQeZHYnDaOSP zhgWYvJz}^m7#DKQQT?xkHE z-_96cC%v*8-#_h!;S2HeW68^V0JboYRdD_+K4#`caC(>a_iPN>XwcXDot>S~zwXa? zRQF>Ss%(|-edEvP5GPLz)zA#lU6Ii~0ajK;MTdJF?x((;wvLY9hSK=vyIpd)a|n!w zI#m^{Er+JwO^x&Q_=v`=4JO!1JpHvy^t!CPoQIDuL1%StVgjlLK}=t5aY0Jk#L1r- z&tiEj-+3NIG}{r9otN*SL6ZUB&ZWph<#Qu56Wzg6ju5|BctQZb7#9>2#9?|00QZS+($T&-Y(xPX ze){1Z1?&xEnng~+x9sdpb%IjtYsGWo0O}4frA$&1Ss8i_>_VwYH@xdv!w)FPhCxyc zp(-!w3(tyz&Y#%CEoY35piUQmB|+J%MAu+D{X+5qUxMV>=N}-qW9gj>I69va!ouQo zfWRBJ;}r(52Df`xewW@}u456tt4Ak;SODAdNb?cpe2xWbfOxBuc_PjpuYJeNF(Qvk z=X~NxOf2|z1gf9&?B2w{fX#pRI&{jVNPJ*oO%eP#ulrYQ&blu}2a!1Q-TlSkQeSws zOEE_3^1g+|?=}90Yf#4|VLgvQDbGcNuI5p57UClY86JjPIoPV-64Tds=Se3(?G)NH zl|(O>J*sGK*D)U;OzTOII2Neo@6Ihe_nl95f#C$_3^Cd|gXAe|*d5t9@Zq(miHB?q zxFtK-sJ>iQsKSf$w~b1rd0kvv;&IvB=K>-N(0k4@*^3*|v+Kx0HP14MIQa3A+E4!u z7(<;Eba;)K$ocU|vfmILM`R5u)%PP6CZ4@Zw3NV3MROmj#`Tf`4O1W)z3EQ;6+@ro zz$pl1oAQu|)|f`?JS07wDaq)1DswL#f38-!@kfp6vhOd=vmb3RB)zZFTuwYz&AFcV z6oWj&Wrn3x(K))il`A7LUphXMwL)FzyR-VYCQVePH7kZ>Z^QT8t23Q#qD*}ia__2@XrT2nm=A|X%x-~()vr<0q=^r`jt;>=(785z)AF7W zetFpc-8L~6HGU>#BoTJz+aj>2o(gQG=9JY=N_@~4?q7j{Srb`&6I7gWb4Npo*=k%P@U$+yFTK*MCYiR$d%4im`oR~=m|gpzfV6@{Km*hh_-CQ`W11yl%a<4|F{xqr8{ zTzWsa#)Gz^T$PG=VFs-wm07NSwY59WvKjIP^*2y9Fk9;a0|B3uaMt(70mo>dqWDg0 zZg{S>=hXe^W&jRV=y3GBE*|m=w6`fb6D$<>ch={yKXfwS=b0^N10O#c6ncx>j7XNTML@J;I9mmC|L=E|iAuzRfKA zH9$g9#t#a)|FzdIAH8iIY(%$3MnhwRpuobgZNwX8nc}TC-!~Z8z1yFyE-&Y6mH`20 z4LrS1qLkCo$Y3K5oreyIiZF1Oio>FU;f&Ir@*ZbEvFlxF;&C!j&t=XK~V&kRiJj$o0vBM85*1c>%|m(`mb>YZK|UyMA~Ch?V< z$4KX|nJCz73uJ-AFf@OX<$r2abV*9RJ7;tmW5QEQQO3ImtrX|y=gKC`?6{fz2iyUm zdvh;--)>XyslUJ}_$YG)+X4zuEuOG1RoUQ9dvfFQf)=S1G+B~hH2B5BY`r>^G+}&au)@p^`2nk;xKr3kQOo7AFFR& zFYY8+$QLOs8TNtpJJ;cEbA5e+fvzs$-JklspZQ*A30Ae;qMR;<;5K#|| z$J@dlE9BAU%zCsq9i&a;P!LNxO%1O-33=6o>X~McU^nSYHjM~6#so|vyj9)`u9Qbf ze7Vx{rr(xl@@050fNB(v=qW`3zbQs)|DiW-e6oE>`P_T@%5av11d7$4EE2Y7eASz= zrhobSxfIU6D>wf5yn%uwLw80SN~7uhOC!hMM!GyEwSw@Rv+@*?H1{r1%kd7CmdR{j zRpz1RX8i^o?&5u72>zGV>^^X?{I!8!q!W8?zE7ZU?#kJy9_jS2?Y=_-RH+#SbpHZ- z=rBFM3xD1zAOu(~P!H}`Eu){G#Er1&oG=w%3PC&T_JzpqtqDXRAE>8ag?SaUoJHdR^8Pq98aiZ??cz4R<_QqPsmrK@Jw<(%#ZDkTRRu*gE z#K!(7a?fA8qsJ?LOYF+Lwk0p2B1+}QRqe*v@kFzcKOw@4<3yV_SemCM=vS$9v9i1} z-_HmXln?+jUrJ%Ok5EONv}SKZ+S_O?L++2mC2|W2&>&a+G@#V#>n3}CYkF=wl1yg@ zd3yDd2J!*sY6;28#qYmtbOIg&^an`;u&nRZQ}GLwl$2g8SF#XCWl@M@1vf%ofcTv1 zzq9}ln=WywMX8`9Fqxn5z5gahg5N8`umX*(P?dGxpjZSJ{8A_Q9(sNKv4i3ka}X$} z)Rn#$aeBy}E+XP%lj&^g_2}|#wws0HD<4tc2F-u^o}DZt57RW}K;;c`<$HU9GX6Qm zL-wA6-ysnDap%tH$rD8j)B8di4@{^=^cHeG5)*I{Cj6#6?Hs#1VfxF@HwA_+7xla9 zOwT^tf&!w)x-XW>xI$xQ3ejSKNC#jk7Bjyo>3rvk7!*1+^0gHSa~tud=hU)MfFd%y zBb%>xZVQr-A-T95BrEAj{`{j#^qm^6dCNEW?pi+9gf-Y)urOK2={4w67meH%U2Rtb zUR;36_|R+6)rAv4GNheKj1TNdbsWJIQ)Vb24Hce^_phQPkD8O_en+u)3#EPQ)g1*Q zpl6$67opXTgY(^Ag)oe-KJ!J#&6NS@NgQkk_I^Q}c*lhATr@_tNl)v3w%-Ypo7}EH z?T$cMs&r{!#diwONBCX_elI0G(1`>#K%1oJ@+nZ>4*A>jnFj+EW$7hXiw?#K6T$Z3 z;~t@(*r8#sfQ(UARzb}BU0~^f=K%wc1;YrM`SfebS z?=w=f;X*v7BIiKPnK(k$ST59X>ycQj>UxF>&*Z)f$fbsIJhS&4d;{eptU_rO(m(iCs*3SL z&qNRxuTp=0*#*X?<~`G=bPhwh>YGqlDK@iaF*{AY`>Jm`#RGy7<^m{Jtvrg8$3RC= zNLnERI?_u+YxrO{bWM#*i$$;I_GNQ&bc8yQ98a&Qd2keF~s z0jw>?vKJdDEw%Z|pg=vMFES?dXG!rU?8(VG#X)8t>)6v2Qqm@$8qoCoQ0a=e@7mXj zGzK@bOeLQDAC{O>UzHP*h!Wscb1pC^1RU)jjc(X3MJs9IjV%c9T8F`U-EQi_l^>bA9FeAey@0X4q2UmR(GD01a$d*ScQ1+zoirE)JEfRL~lLl-n$oq zHxo6CeA+#c#>p$eHexC}pQynuYJRS0V8p!EH&GySX965ygzVhUKS(UoPD)z72~vC3 z{riHoSm2@WjTvoAx{|CMZSd4bF{?5y} z-DGY`JpriZ10(%GVx+fzbmXi_aJyGty?Bbw(j*Sl^)hVbp(`sZ%T-40%1-|OaLxx| zlWB#~Y1=m&Zn7x%KyupPTKV}ptG7~1Q&o>VlTZYOgfbSduC7{2&y`djepiJb|9E>W z<7$8_z|8&+K;ZZrjagv;>urq83!8ALm5~LqXI;C3lIG(2S;W~6%P~NHNkLe4rd@>@ zPLB6|v0okiYl*@yu@uffh6Q|7zi-FO?n|%MN=PKOJ~0K?>MJrOEaFxY7d{i#sW$d1 ze7#gw{-`S;HQkwb+=83TA-G(px@~uSYKmAv+cuQH?%dstEpN&Vi=O*_8n4rkWNT2Ji6sI>Cii~}SYu#%T!VC-y zyL)?e6_DKtI@Lv-!h(WekM@;Mvh-#9zM|A)U|lZ^MOXaO>HYBQzXL;{@Vgfw0dNl_ z5-GAPjJK|4c@H zj-!`s?}=m}5DDf>6Dj!kLiO6(+IT3SlB+WkKrSpS1W`j?YwGBfT%q7B9XL2UtDgTs zZzxq&R;JAu(-&OSeui?lmcms)Q%(C^JThyNWfk|V-(0>RHjhSaz0;L!a@S(M3;Ag9 zg6`K-k9f*}r6#8qmpgI)np+ga%}uLr_t`?PD3WU}{IO|H05A##nv`^LWDV=gNeZ9R z_jfuv;fjnwfq^Kp^hChCUgt}Qin7bmOnCvjPky9ID4|*2*>2)v;($U;>kE_SOX?@vKhc zyQhqGg$&9sG>aJ|3lLN16%#8fW2NUQp&a zba&^lX_4!;?xXcweG56xA~TbUrxbHZ==*>MKRM) zx9M+CP;Pnoh=7E|IJr|;9ppY>=GU(_Uq8Rr&!2H*_NPWZczLx3oMo)J!dZOW8Ga8> z&dzS_9UgA&{^3yqP8JNS8X&|w<2gD;-__A|4=x=dE4hlgyVtZwi)n!3q(Fl?b@x6O zG}|2O$@AxUS%S1}M5hd~qNv?#v6j3M&1(S${IQbvq!F^OBptu{=B6+&fgX6SKXTt> z@b*^J-ob%KLgF!~?}M*WwZjY)8x0MObE;;EU0POm>H{qJeW;)uE=Frd2YV_Zk|}uYZ+LYtGp{J{S{LxXL0|Y?Y=wb_hS^Za?p9^T znAESL*g?E0FJ||xZY9lDuSC-oGoJTU%&M8LRO0@r1<}=UW2T?PL9{ye+%qEIgo5*; z#+C711v3V=M*LsjAkO#Yh)j9YWN}zEN-&2liMcxAUv`Ba_I1JWJ*Dskkyo2v9 zO&!D!=AOmlY<7Ete1#Ym*4+26ypxAy%@Hx@B2U;mfqRY;S&>!jtzhpTphYV%Ka8+W

vyD@KQ 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 diff --git a/tgstation.dme b/tgstation.dme index e8a1f8bf1fd..50b0b51f978 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3693,6 +3693,7 @@ #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\brain_computer_interface.dm" #include "code\modules\wiremod\shell\compact_remote.dm" #include "code\modules\wiremod\shell\controller.dm" #include "code\modules\wiremod\shell\drone.dm" diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/index.js b/tgui/packages/tgui/interfaces/IntegratedCircuit/index.js index a28f880d39c..3667c66f9fd 100644 --- a/tgui/packages/tgui/interfaces/IntegratedCircuit/index.js +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/index.js @@ -232,7 +232,7 @@ export class IntegratedCircuit extends Component { backgroundImage={resolveAsset('grid_background.png')} imageWidth={900} > - {components.map((comp, index) => ( + {components.map((comp, index) => comp && ( { const connections = []; for (const comp of components) { + if (comp === null) { + continue; + } + for (const port of comp.input_ports) { if (port.connected_to === NULL_REF) continue; const output_port = locations[port.connected_to];