From db94f7851182c5eb0b14bfbb9608a83417feb766 Mon Sep 17 00:00:00 2001 From: Y0SH1M4S73R Date: Tue, 25 Jan 2022 17:54:08 -0500 Subject: [PATCH] MODsuit Action Circuit Component (+ MODsuit circuit module fixes) (#63755) This makes several small changes to the MODsuit circuit module: Adds the MODsuit Action component. When selected, the circuit module opens a radial menu with which to select an action component to trigger. Due to its similarity to the BCI Action component, both it and the BCI Action component have been made subtypes of an abstract equipment_action component that implements their shared functionality. Renames the MOD component to the MOD circuit adapter core component. Changes the "selected module" port on the MOD circuit adapter core to a string port, for consistency with the corresponding input port. The circuit in the circuit module can be removed. Consequentually, the circuit module no longer comes with a pre-installed circuit. The "Toggle Suit" signal port on the MOD circuit adapter core can now activate the modsuit. Makes the circuit module printable in the component printer, for consistency. Moves the circuit module's code to modules/wiremod, for consistency. BCI action component properly typechecks the shell it's inserted in. Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com> --- code/__DEFINES/dcs/signals/signals_mod.dm | 2 +- code/modules/mod/modules/modules_science.dm | 105 ------------ .../designs/mechfabricator_designs.dm | 7 - .../research/designs/wiremod_designs.dm | 16 +- code/modules/research/techweb/all_nodes.dm | 3 +- .../components/abstract/equpiment_action.dm | 65 ++++++++ .../wiremod/shell/brain_computer_interface.dm | 93 ++--------- code/modules/wiremod/shell/module.dm | 156 ++++++++++++++++++ tgstation.dme | 2 + 9 files changed, 259 insertions(+), 190 deletions(-) create mode 100644 code/modules/wiremod/components/abstract/equpiment_action.dm create mode 100644 code/modules/wiremod/shell/module.dm diff --git a/code/__DEFINES/dcs/signals/signals_mod.dm b/code/__DEFINES/dcs/signals/signals_mod.dm index 26a8f2b80c0..4050481fb99 100644 --- a/code/__DEFINES/dcs/signals/signals_mod.dm +++ b/code/__DEFINES/dcs/signals/signals_mod.dm @@ -1,5 +1,5 @@ //MODsuit signals -/// Called when a module is selected to be the active one from on_select() +/// Called when a module is selected to be the active one from on_select(obj/item/mod/module/module) #define COMSIG_MOD_MODULE_SELECTED "mod_module_selected" /// Called when a MOD activation is called from toggle_activate(mob/user) #define COMSIG_MOD_ACTIVATE "mod_activate" diff --git a/code/modules/mod/modules/modules_science.dm b/code/modules/mod/modules/modules_science.dm index c472a0cd37d..5ef7ac34857 100644 --- a/code/modules/mod/modules/modules_science.dm +++ b/code/modules/mod/modules/modules_science.dm @@ -55,111 +55,6 @@ return to_chat(mod.wearer, span_notice("Explosion detected! Epicenter: [devastation_range], Outer: [heavy_impact_range], Shock: [light_impact_range]")) -//Circuit Adapter - -/obj/item/mod/module/circuit - name = "MOD circuit adapter module" - desc = "A popular aftermarket module, seen in wide varieties with wide applications by those across the galaxy. \ - This is able to fit any sort of integrated circuit, hooking it into controls in the suit and displaying information \ - to the HUD. Useful for universal translation, or perhaps as a calculator." - module_type = MODULE_USABLE - complexity = 3 - idle_power_cost = DEFAULT_CHARGE_DRAIN * 0.5 - incompatible_modules = list(/obj/item/mod/module/circuit) - cooldown_time = 0.5 SECONDS - var/obj/item/integrated_circuit/circuit - -/obj/item/mod/module/circuit/Initialize(mapload) - . = ..() - circuit = new() - AddComponent(/datum/component/shell, \ - list(new /obj/item/circuit_component/mod()), \ - capacity = SHELL_CAPACITY_LARGE, \ - shell_flags = SHELL_FLAG_CIRCUIT_UNREMOVABLE, \ - starting_circuit = circuit, \ - ) - -/obj/item/mod/module/circuit/on_install() - circuit.set_cell(mod.get_cell()) - -/obj/item/mod/module/circuit/on_uninstall() - circuit.set_cell(mod.get_cell()) - -/obj/item/mod/module/circuit/on_suit_activation() - circuit.set_on(TRUE) - -/obj/item/mod/module/circuit/on_suit_deactivation() - circuit.set_on(FALSE) - -/obj/item/mod/module/circuit/on_use() - . = ..() - if(!.) - return - circuit.interact(mod.wearer) - -/obj/item/circuit_component/mod - display_name = "MOD" - desc = "Used to send and receive signals from a MODsuit." - - var/obj/item/mod/module/attached_module - - var/datum/port/input/module_to_select - var/datum/port/input/toggle_suit - var/datum/port/input/select_module - - var/datum/port/output/wearer - var/datum/port/output/selected_module - -/obj/item/circuit_component/mod/populate_ports() - // Input Signals - module_to_select = add_input_port("Module to Select", PORT_TYPE_STRING) - toggle_suit = add_input_port("Toggle Suit", PORT_TYPE_SIGNAL) - select_module = add_input_port("Select Module", PORT_TYPE_SIGNAL) - // States - wearer = add_output_port("Wearer", PORT_TYPE_ATOM) - selected_module = add_output_port("Selected Module", PORT_TYPE_ATOM) - -/obj/item/circuit_component/mod/register_shell(atom/movable/shell) - if(istype(shell, /obj/item/mod/module)) - attached_module = shell - RegisterSignal(attached_module, COMSIG_MOVABLE_MOVED, .proc/on_move) - -/obj/item/circuit_component/mod/unregister_shell(atom/movable/shell) - UnregisterSignal(attached_module, COMSIG_MOVABLE_MOVED) - attached_module = null - -/obj/item/circuit_component/mod/input_received(datum/port/input/port) - var/obj/item/mod/module/module - for(var/obj/item/mod/module/potential_module as anything in attached_module.mod.modules) - if(potential_module.name == module_to_select.value) - module = potential_module - if(COMPONENT_TRIGGERED_BY(toggle_suit, port)) - INVOKE_ASYNC(attached_module.mod, /obj/item/mod/control.proc/toggle_activate, attached_module.mod.wearer) - if(module && COMPONENT_TRIGGERED_BY(select_module, port)) - INVOKE_ASYNC(module, /obj/item/mod/module.proc/on_select) - -/obj/item/circuit_component/mod/proc/on_move(atom/movable/source, atom/old_loc, dir, forced) - SIGNAL_HANDLER - if(istype(source.loc, /obj/item/mod/control)) - RegisterSignal(source.loc, COMSIG_MOD_MODULE_SELECTED, .proc/on_module_select) - RegisterSignal(source.loc, COMSIG_ITEM_EQUIPPED, .proc/equip_check) - equip_check() - else if(istype(old_loc, /obj/item/mod/control)) - UnregisterSignal(old_loc, list(COMSIG_MOD_MODULE_SELECTED, COMSIG_ITEM_EQUIPPED)) - selected_module.set_output(null) - wearer.set_output(null) - -/obj/item/circuit_component/mod/proc/on_module_select() - SIGNAL_HANDLER - selected_module.set_output(attached_module.mod.selected_module) - -/obj/item/circuit_component/mod/proc/equip_check() - SIGNAL_HANDLER - - if(!attached_module.mod?.wearer) - return - wearer.set_output(attached_module.mod.wearer) - ///Anti-Gravity - Makes the user weightless. /obj/item/mod/module/anomaly_locked/antigrav name = "MOD anti-gravity module" diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 67cb72007c2..7988d2ce5b5 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -1328,13 +1328,6 @@ materials = list(/datum/material/diamond = 500, /datum/material/glass = 1000) build_path = /obj/item/mod/module/dna_lock -/datum/design/module/mod_circuit - name = "MOD Module: Circuit Adapter" - id = "mod_circuit" - materials = list(/datum/material/glass = 2000) - build_path = /obj/item/mod/module/circuit - department_type = MODULE_SCIENCE - /datum/design/module/mod_plasma_stabilizer name = "MOD Module: Plasma Stabilizer" id = "mod_plasma" diff --git a/code/modules/research/designs/wiremod_designs.dm b/code/modules/research/designs/wiremod_designs.dm index 673767bef72..4dc93953e8a 100644 --- a/code/modules/research/designs/wiremod_designs.dm +++ b/code/modules/research/designs/wiremod_designs.dm @@ -309,7 +309,7 @@ /datum/design/component/bci/bci_action name = "BCI Action Component" id = "comp_bci_action" - build_path = /obj/item/circuit_component/bci_action + build_path = /obj/item/circuit_component/equipment_action/bci /datum/design/component/bci/object_overlay name = "Object Overlay Component" @@ -341,6 +341,11 @@ id = "comp_filter_list" build_path = /obj/item/circuit_component/filter_list +/datum/design/component/mod_action + name = "MOD Action Component" + id = "comp_mod_action" + build_path = /obj/item/circuit_component/equipment_action/mod + /datum/design/component/id_getter name = "ID Getter Component" id = "comp_id_getter" @@ -505,3 +510,12 @@ build_path = /obj/item/assembly/wiremod build_type = PROTOLATHE | COMPONENT_PRINTER category = list("Circuitry", "Shells") + +/datum/design/mod_module_shell + name = "MOD Module Shell" + desc = "A module shell that allows a circuit to be inserted into, and interface with, a MODsuit." + id = "module_shell" + materials = list(/datum/material/glass = 2000) + build_path = /obj/item/mod/module/circuit + build_type = MECHFAB | COMPONENT_PRINTER + category = list("MOD Modules", "Shells") diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 82359fafee6..463bf1d122e 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -715,11 +715,12 @@ design_ids = list( "assembly_shell", "bot_shell", + "comp_mod_action", "controller_shell", "dispenser_shell", "door_shell", "gun_shell", - "mod_circuit", + "module_shell", "money_bot_shell", "scanner_gate_shell", "scanner_shell", diff --git a/code/modules/wiremod/components/abstract/equpiment_action.dm b/code/modules/wiremod/components/abstract/equpiment_action.dm new file mode 100644 index 00000000000..17f931ae5e3 --- /dev/null +++ b/code/modules/wiremod/components/abstract/equpiment_action.dm @@ -0,0 +1,65 @@ +/obj/item/circuit_component/equipment_action + display_name = "Abstract Equipment Action" + desc = "You shouldn't be seeing this." + + /// The icon of the button + var/datum/port/input/option/icon_options + + /// 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 + +/obj/item/circuit_component/equipment_action/Initialize(mapload, default_icon) + . = ..() + + if (!isnull(default_icon)) + icon_options.set_input(default_icon) + + button_name = add_input_port("Name", PORT_TYPE_STRING) + + signal = add_output_port("Signal", PORT_TYPE_SIGNAL) + +/obj/item/circuit_component/equipment_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", + ) + + icon_options = add_option_port("Icon", action_options) + +/obj/item/circuit_component/equipment_action/proc/update_action() + return diff --git a/code/modules/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm index 91c745db74f..e0244f5b017 100644 --- a/code/modules/wiremod/shell/brain_computer_interface.dm +++ b/code/modules/wiremod/shell/brain_computer_interface.dm @@ -11,7 +11,7 @@ . = ..() var/obj/item/integrated_circuit/circuit = new(src) - circuit.add_component(new /obj/item/circuit_component/bci_action(null, "One")) + circuit.add_component(new /obj/item/circuit_component/equipment_action/bci(null, "One")) AddComponent(/datum/component/shell, list( new /obj/item/circuit_component/bci_core, @@ -34,96 +34,39 @@ else return ..() -/obj/item/circuit_component/bci_action +/obj/item/circuit_component/equipment_action/bci display_name = "BCI Action" desc = "Represents an action the user can take when implanted with the brain-computer interface." required_shells = list(/obj/item/organ/cyberimp/bci) - /// The icon of the button - var/datum/port/input/option/icon_options - - /// 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)) - icon_options.set_input(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() +/obj/item/circuit_component/equipment_action/bci/Destroy() 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", - ) - - icon_options = add_option_port("Icon", action_options) - -/obj/item/circuit_component/bci_action/register_shell(atom/movable/shell) +/obj/item/circuit_component/equipment_action/bci/register_shell(atom/movable/shell) + . = ..() var/obj/item/organ/cyberimp/bci/bci = shell + if(istype(bci)) + bci_action = new(src) + update_action() - bci_action = new(src) - update_action() + bci.actions += list(bci_action) - bci.actions += list(bci_action) - -/obj/item/circuit_component/bci_action/unregister_shell(atom/movable/shell) +/obj/item/circuit_component/equipment_action/bci/unregister_shell(atom/movable/shell) var/obj/item/organ/cyberimp/bci/bci = shell + if(istype(bci)) + bci.actions -= bci_action + QDEL_NULL(bci_action) + return ..() - bci.actions -= bci_action - QDEL_NULL(bci_action) - -/obj/item/circuit_component/bci_action/input_received(datum/port/input/port) +/obj/item/circuit_component/equipment_action/bci/input_received(datum/port/input/port) if (!isnull(bci_action)) update_action() -/obj/item/circuit_component/bci_action/proc/update_action() +/obj/item/circuit_component/equipment_action/bci/update_action() bci_action.name = button_name.value bci_action.button_icon_state = "bci_[replacetextEx(lowertext(icon_options.value), " ", "_")]" @@ -133,9 +76,9 @@ check_flags = AB_CHECK_CONSCIOUS button_icon_state = "bci_power" - var/obj/item/circuit_component/bci_action/circuit_component + var/obj/item/circuit_component/equipment_action/bci/circuit_component -/datum/action/innate/bci_action/New(obj/item/circuit_component/bci_action/circuit_component) +/datum/action/innate/bci_action/New(obj/item/circuit_component/equipment_action/bci/circuit_component) ..() src.circuit_component = circuit_component diff --git a/code/modules/wiremod/shell/module.dm b/code/modules/wiremod/shell/module.dm new file mode 100644 index 00000000000..b3a8275d607 --- /dev/null +++ b/code/modules/wiremod/shell/module.dm @@ -0,0 +1,156 @@ +/obj/item/mod/module/circuit + name = "MOD circuit adapter module" + desc = "A module shell that allows a circuit to be inserted into, and interface with, a MODsuit." + module_type = MODULE_USABLE + complexity = 3 + idle_power_cost = DEFAULT_CHARGE_DRAIN * 0.5 + incompatible_modules = list(/obj/item/mod/module/circuit) + cooldown_time = 0.5 SECONDS + + /// A reference to the shell component, used to access the shell and its attached circuit + var/datum/component/shell/shell + +/obj/item/mod/module/circuit/Initialize(mapload) + . = ..() + shell = AddComponent(/datum/component/shell, \ + list(new /obj/item/circuit_component/mod_adapter_core()), \ + capacity = SHELL_CAPACITY_LARGE, \ + ) + +/obj/item/mod/module/circuit/proc/override_power_usage(datum/source, amount) + SIGNAL_HANDLER + if(drain_power(amount)) + . = COMPONENT_OVERRIDE_POWER_USAGE + +/obj/item/mod/module/circuit/on_install() + RegisterSignal(shell?.attached_circuit, COMSIG_CIRCUIT_PRE_POWER_USAGE, .proc/override_power_usage) + +/obj/item/mod/module/circuit/on_uninstall() + UnregisterSignal(shell?.attached_circuit, COMSIG_CIRCUIT_PRE_POWER_USAGE) + +/obj/item/mod/module/circuit/on_use() + . = ..() + if(!.) + return + if(!shell.attached_circuit) + return + var/list/action_components = shell.attached_circuit.get_all_contents_type(/obj/item/circuit_component/equipment_action/mod) + if(!action_components.len) + shell.attached_circuit.interact(mod.wearer) + return + var/list/repeat_name_counts = list("Access Circuit" = 1) + var/list/display_names = list() + var/list/radial_options = list() + for(var/obj/item/circuit_component/equipment_action/mod/action_component in action_components) + var/action_name = action_component.button_name.value + if(!repeat_name_counts[action_name]) + repeat_name_counts[action_name] = 0 + repeat_name_counts[action_name]++ + if(repeat_name_counts[action_name] > 1) + action_name += " ([repeat_name_counts[action_name]])" + display_names[action_name] = REF(action_component) + var/option_icon_state = "bci_[replacetextEx(lowertext(action_component.icon_options.value), " ", "_")]" + radial_options += list("[action_name]" = image('icons/mob/actions/actions_items.dmi', option_icon_state)) + radial_options += list("Access Circuit" = image(shell.attached_circuit)) + var/selected_option = show_radial_menu(mod.wearer, src, radial_options, custom_check = FALSE, require_near = TRUE) + if(!selected_option) + return + if(!mod || !mod.wearer || !mod.active || mod.activating) + return + if(selected_option == "Access Circuit") + shell.attached_circuit?.interact(mod.wearer) + else + var/component_reference = display_names[selected_option] + var/obj/item/circuit_component/equipment_action/mod/selected_component = locate(component_reference) in shell.attached_circuit.contents + if(!istype(selected_component)) + return + selected_component.signal.set_output(COMPONENT_SIGNAL) + + +/obj/item/circuit_component/mod_adapter_core + display_name = "MOD circuit adapter core" + desc = "Provides a reference to the MODsuit's occupant and allows the circuit to toggle the MODsuit." + + /// The MODsuit module this circuit is associated with + var/obj/item/mod/module/attached_module + + /// The name of the module to select + var/datum/port/input/module_to_select + + /// The signal to toggle the suit + var/datum/port/input/toggle_suit + + /// The signal to select a module + var/datum/port/input/select_module + + /// A reference to the wearer of the MODsuit + var/datum/port/output/wearer + + /// The name of the last selected module + var/datum/port/output/selected_module + + /// The signal that is triggered when a module is selected + var/datum/port/output/on_module_selected + +/obj/item/circuit_component/mod_adapter_core/populate_ports() + // Input Signals + module_to_select = add_input_port("Module to Select", PORT_TYPE_STRING) + toggle_suit = add_input_port("Toggle Suit", PORT_TYPE_SIGNAL) + select_module = add_input_port("Select Module", PORT_TYPE_SIGNAL) + // States + wearer = add_output_port("Wearer", PORT_TYPE_ATOM) + selected_module = add_output_port("Selected Module", PORT_TYPE_STRING) + // Output Signals + on_module_selected = add_output_port("On Module Selected", PORT_TYPE_SIGNAL) + +/obj/item/circuit_component/mod_adapter_core/register_shell(atom/movable/shell) + . = ..() + if(istype(shell, /obj/item/mod/module)) + attached_module = shell + RegisterSignal(attached_module, COMSIG_MOVABLE_MOVED, .proc/on_move) + +/obj/item/circuit_component/mod_adapter_core/unregister_shell(atom/movable/shell) + UnregisterSignal(attached_module, COMSIG_MOVABLE_MOVED) + attached_module = null + return ..() + +/obj/item/circuit_component/mod_adapter_core/input_received(datum/port/input/port) + if(!attached_module?.mod) + return + var/obj/item/mod/module/module + for(var/obj/item/mod/module/potential_module as anything in attached_module.mod.modules) + if(potential_module.name == module_to_select.value) + module = potential_module + if(COMPONENT_TRIGGERED_BY(toggle_suit, port)) + INVOKE_ASYNC(attached_module.mod, /obj/item/mod/control.proc/toggle_activate, attached_module.mod.wearer) + if(attached_module.mod.active && module && COMPONENT_TRIGGERED_BY(select_module, port)) + INVOKE_ASYNC(module, /obj/item/mod/module.proc/on_select) + +/obj/item/circuit_component/mod_adapter_core/proc/on_move(atom/movable/source, atom/old_loc, dir, forced) + SIGNAL_HANDLER + if(istype(source.loc, /obj/item/mod/control)) + RegisterSignal(source.loc, COMSIG_MOD_MODULE_SELECTED, .proc/on_module_select) + RegisterSignal(source.loc, COMSIG_ITEM_EQUIPPED, .proc/equip_check) + equip_check() + else if(istype(old_loc, /obj/item/mod/control)) + UnregisterSignal(old_loc, list(COMSIG_MOD_MODULE_SELECTED, COMSIG_ITEM_EQUIPPED)) + selected_module.set_output(null) + wearer.set_output(null) + +/obj/item/circuit_component/mod_adapter_core/proc/on_module_select(datum/source, obj/item/mod/module/module) + SIGNAL_HANDLER + selected_module.set_output(module.name) + on_module_selected.set_output(COMPONENT_SIGNAL) + + +/obj/item/circuit_component/mod_adapter_core/proc/equip_check() + SIGNAL_HANDLER + + if(!attached_module.mod?.wearer) + return + wearer.set_output(attached_module.mod.wearer) + +/obj/item/circuit_component/equipment_action/mod + display_name = "MOD action" + desc = "Represents an action the user can take when wearing the MODsuit." + required_shells = list(/obj/item/mod/module/circuit) diff --git a/tgstation.dme b/tgstation.dme index de3ec01751d..290929ec2ec 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4081,6 +4081,7 @@ #include "code\modules\vending\youtool.dm" #include "code\modules\wiremod\components\abstract\binary_decimal.dm" #include "code\modules\wiremod\components\abstract\compare.dm" +#include "code\modules\wiremod\components\abstract\equpiment_action.dm" #include "code\modules\wiremod\components\abstract\module.dm" #include "code\modules\wiremod\components\abstract\variable.dm" #include "code\modules\wiremod\components\action\light.dm" @@ -4189,6 +4190,7 @@ #include "code\modules\wiremod\shell\dispenser.dm" #include "code\modules\wiremod\shell\drone.dm" #include "code\modules\wiremod\shell\gun.dm" +#include "code\modules\wiremod\shell\module.dm" #include "code\modules\wiremod\shell\moneybot.dm" #include "code\modules\wiremod\shell\scanner.dm" #include "code\modules\wiremod\shell\scanner_gate.dm"