From 652fc92cd184920f59491dcbec7a1a3650f231f8 Mon Sep 17 00:00:00 2001 From: Y0SH1M4S73R Date: Sat, 23 Dec 2023 13:52:33 -0500 Subject: [PATCH 1/2] Circuit action button refactor (#80379) ## About The Pull Request This PR makes several changes to how circuit action buttons work: - The MOD action and BCI action components have been merged into a single component. - MOD circuit actions can be pinned from the configuration menu. This works the same way as pinning individual modules, and can be done both by the wearer and a suit AI. - Action components have an output pin for the user of the action. This allows MOD module circuits to distinguish between the wearer and an AI. - Creates a supertype for `/datum/action/item_action/mod/pinned_module` named `/datum/action/item_action/mod/pinnable`, which implements common functionality for pinned modules and pinned circuit module actions. ## Why It's Good For The Game The prior functionality of circuit MOD actions was somewhat unintuitive, requiring the user to select an action from a radial menu *after* activating the module, whether from a pinned action or from the module radial. Providing similar pinning functionality to modules themselves makes MOD actions more readily usable. Merging the two different types of circuit components into one was made with the idea that adding new types of shells with equipment actions would inflate the number of subtypes of `/obj/item/circuit_component/equipment_action` without adding much meaningful functionality. ## Changelog :cl: qol: MOD wearers and internal AIs can pin the individual actions in a MOD circuit module in a similar way to how they can pin modules. Circuit module actions can be pinned from the configuration menu of the circuit refactor: The MOD action and BCI action components have been merged into one component - the Equipment Action component. /:cl: --- code/__DEFINES/dcs/signals/signals_circuit.dm | 6 + code/modules/mod/mod_actions.dm | 54 ++++---- code/modules/mod/mod_control.dm | 4 +- code/modules/mod/mod_ui.dm | 2 +- code/modules/mod/modules/_module.dm | 6 +- .../research/designs/wiremod_designs.dm | 18 +-- code/modules/research/techweb/all_nodes.dm | 3 +- .../components/abstract/equpiment_action.dm | 65 --------- .../components/action/equpiment_action.dm | 92 +++++++++++++ .../wiremod/shell/brain_computer_interface.dm | 60 +++------ code/modules/wiremod/shell/module.dm | 123 +++++++++++++----- tgstation.dme | 2 +- tgui/packages/tgui/interfaces/MODsuit.tsx | 17 +++ 13 files changed, 268 insertions(+), 184 deletions(-) delete mode 100644 code/modules/wiremod/components/abstract/equpiment_action.dm create mode 100644 code/modules/wiremod/components/action/equpiment_action.dm diff --git a/code/__DEFINES/dcs/signals/signals_circuit.dm b/code/__DEFINES/dcs/signals/signals_circuit.dm index 1b7b6b53c4f5a8..c0676d768ce1a0 100644 --- a/code/__DEFINES/dcs/signals/signals_circuit.dm +++ b/code/__DEFINES/dcs/signals/signals_circuit.dm @@ -75,3 +75,9 @@ ///Called when an Ntnet sender is sending Ntnet data #define COMSIG_GLOB_CIRCUIT_NTNET_DATA_SENT "!circuit_ntnet_data_sent" + +/// Called when an equipment action component is added to a shell (/obj/item/circuit_component/equipment_action/action_comp) +#define COMSIG_CIRCUIT_ACTION_COMPONENT_REGISTERED "circuit_action_component_registered" + +/// Called when an equipment action component is removed from a shell (/obj/item/circuit_component/equipment_action/action_comp) +#define COMSIG_CIRCUIT_ACTION_COMPONENT_UNREGISTERED "circuit_action_component_unregistered" diff --git a/code/modules/mod/mod_actions.dm b/code/modules/mod/mod_actions.dm index 111ea425b6a6e5..2a2ed02c022091 100644 --- a/code/modules/mod/mod_actions.dm +++ b/code/modules/mod/mod_actions.dm @@ -117,26 +117,43 @@ /datum/action/item_action/mod/panel/ai ai_action = TRUE -/datum/action/item_action/mod/pinned_module +/datum/action/item_action/mod/pinnable + /// A reference to the mob we are pinned to. + var/mob/pinner + +/datum/action/item_action/mod/pinnable/New(Target, mob/user) + . = ..() + var/obj/item/mod/control/mod = Target + if(user == mod.ai_assistant) + ai_action = TRUE + pinner = user + RegisterSignal(user, COMSIG_QDELETING, PROC_REF(pinner_deleted)) + +/datum/action/item_action/mod/pinnable/Grant(mob/user) + if(pinner != user) + return + return ..() + +/// If the guy whose UI we are pinned to got deleted +/datum/action/item_action/mod/pinnable/proc/pinner_deleted() + SIGNAL_HANDLER + pinner = null + qdel(src) + +/datum/action/item_action/mod/pinnable/module desc = "Activate the module." /// Overrides the icon applications. var/override = FALSE /// Module we are linked to. var/obj/item/mod/module/module - /// A reference to the mob we are pinned to. - var/mob/pinner /// Timer until we remove our cooldown overlay var/cooldown_timer -/datum/action/item_action/mod/pinned_module/New(Target, obj/item/mod/module/linked_module, mob/user) - var/obj/item/mod/control/mod = Target - if(user == mod.ai_assistant) - ai_action = TRUE +/datum/action/item_action/mod/pinnable/module/New(Target, mob/user, obj/item/mod/module/linked_module) button_icon = linked_module.icon button_icon_state = linked_module.icon_state . = ..() module = linked_module - pinner = user module.pinned_to[REF(user)] = src if(linked_module.allow_flags & MODULE_ALLOW_INCAPACITATED) // clears check hands and check conscious @@ -149,9 +166,8 @@ COMSIG_MODULE_USED, ), PROC_REF(module_interacted_with)) RegisterSignal(linked_module, COMSIG_MODULE_COOLDOWN_STARTED, PROC_REF(cooldown_started)) - RegisterSignal(user, COMSIG_QDELETING, PROC_REF(pinner_deleted)) -/datum/action/item_action/mod/pinned_module/Destroy() +/datum/action/item_action/mod/pinnable/module/Destroy() deltimer(cooldown_timer) UnregisterSignal(module, list( COMSIG_MODULE_ACTIVATED, @@ -164,23 +180,13 @@ pinner = null return ..() -/datum/action/item_action/mod/pinned_module/Grant(mob/user) - if(pinner != user) - return - return ..() - -/datum/action/item_action/mod/pinned_module/Trigger(trigger_flags) +/datum/action/item_action/mod/pinnable/module/Trigger(trigger_flags) . = ..() if(!.) return module.on_select() -/// If the guy whose UI we are pinned to got deleted -/datum/action/item_action/mod/pinned_module/proc/pinner_deleted() - pinner = null - qdel(src) - -/datum/action/item_action/mod/pinned_module/apply_button_overlay(atom/movable/screen/movable/action_button/current_button, force) +/datum/action/item_action/mod/pinnable/module/apply_button_overlay(atom/movable/screen/movable/action_button/current_button, force) current_button.cut_overlays() if(override) return ..() @@ -194,12 +200,12 @@ current_button.add_overlay(image(icon = 'icons/hud/radial.dmi', icon_state = "module_cooldown")) return ..() -/datum/action/item_action/mod/pinned_module/proc/module_interacted_with(datum/source) +/datum/action/item_action/mod/pinnable/module/proc/module_interacted_with(datum/source) SIGNAL_HANDLER build_all_button_icons(UPDATE_BUTTON_OVERLAY|UPDATE_BUTTON_STATUS) -/datum/action/item_action/mod/pinned_module/proc/cooldown_started(datum/source, cooldown_time) +/datum/action/item_action/mod/pinnable/module/proc/cooldown_started(datum/source, cooldown_time) SIGNAL_HANDLER deltimer(cooldown_timer) diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index a32c8b28b26640..88bb8ac7b6013a 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -271,9 +271,9 @@ // Grant pinned actions to pin owners, gives AI pinned actions to the AI and not the wearer /obj/item/mod/control/grant_action_to_bearer(datum/action/action) - if (!istype(action, /datum/action/item_action/mod/pinned_module)) + if (!istype(action, /datum/action/item_action/mod/pinnable)) return ..() - var/datum/action/item_action/mod/pinned_module/pinned = action + var/datum/action/item_action/mod/pinnable/pinned = action give_item_action(action, pinned.pinner, slot_flags) /obj/item/mod/control/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) diff --git a/code/modules/mod/mod_ui.dm b/code/modules/mod/mod_ui.dm index eaf4b75d7ee700..575518affbb567 100644 --- a/code/modules/mod/mod_ui.dm +++ b/code/modules/mod/mod_ui.dm @@ -53,7 +53,7 @@ "cooldown" = round(COOLDOWN_TIMELEFT(module, cooldown_timer), 1 SECONDS), "id" = module.tgui_id, "ref" = REF(module), - "configuration_data" = module.get_configuration() + "configuration_data" = module.get_configuration(user) )) data["module_custom_status"] = module_custom_status data["module_info"] = module_info diff --git a/code/modules/mod/modules/_module.dm b/code/modules/mod/modules/_module.dm index d3d05d205abe47..874f5f3dbdf88a 100644 --- a/code/modules/mod/modules/_module.dm +++ b/code/modules/mod/modules/_module.dm @@ -250,7 +250,7 @@ return list() /// Creates a list of configuring options for this module -/obj/item/mod/module/proc/get_configuration() +/obj/item/mod/module/proc/get_configuration(mob/user) return list() /// Generates an element of the get_configuration list with a display name, type and value @@ -325,12 +325,12 @@ if(module_type == MODULE_PASSIVE) return - var/datum/action/item_action/mod/pinned_module/existing_action = pinned_to[REF(user)] + var/datum/action/item_action/mod/pinnable/module/existing_action = pinned_to[REF(user)] if(existing_action) mod.remove_item_action(existing_action) return - var/datum/action/item_action/mod/pinned_module/new_action = new(mod, src, user) + var/datum/action/item_action/mod/pinnable/module/new_action = new(mod, user, src) mod.add_item_action(new_action) /// On drop key, concels a device item. diff --git a/code/modules/research/designs/wiremod_designs.dm b/code/modules/research/designs/wiremod_designs.dm index 5783ee360824cf..3606dd67e2e608 100644 --- a/code/modules/research/designs/wiremod_designs.dm +++ b/code/modules/research/designs/wiremod_designs.dm @@ -357,15 +357,10 @@ id = "comp_pinpointer" build_path = /obj/item/circuit_component/pinpointer -/datum/design/component/bci - category = list( - RND_CATEGORY_CIRCUITRY + RND_SUBCATEGORY_CIRCUITRY_BCI_COMPONENTS - ) - -/datum/design/component/bci/bci_action - name = "BCI Action Component" - id = "comp_bci_action" - build_path = /obj/item/circuit_component/equipment_action/bci +/datum/design/component/equipment_action + name = "Equipment Action Component" + id = "comp_equip_action" + build_path = /obj/item/circuit_component/equipment_action /datum/design/component/bci/object_overlay name = "Object Overlay Component" @@ -417,11 +412,6 @@ 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" diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 733cd707578bcb..fcaea7b53c81b7 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -854,7 +854,7 @@ design_ids = list( "assembly_shell", "bot_shell", - "comp_mod_action", + "comp_equip_action", "controller_shell", "dispenser_shell", "door_shell", @@ -876,7 +876,6 @@ "bci_implanter", "bci_shell", "comp_bar_overlay", - "comp_bci_action", "comp_counter_overlay", "comp_install_detector", "comp_object_overlay", diff --git a/code/modules/wiremod/components/abstract/equpiment_action.dm b/code/modules/wiremod/components/abstract/equpiment_action.dm deleted file mode 100644 index 17f931ae5e3085..00000000000000 --- a/code/modules/wiremod/components/abstract/equpiment_action.dm +++ /dev/null @@ -1,65 +0,0 @@ -/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/components/action/equpiment_action.dm b/code/modules/wiremod/components/action/equpiment_action.dm new file mode 100644 index 00000000000000..54150ca44d60b6 --- /dev/null +++ b/code/modules/wiremod/components/action/equpiment_action.dm @@ -0,0 +1,92 @@ +/obj/item/circuit_component/equipment_action + display_name = "Equipment Action" + desc = "Represents an action the user can take when using supported shells." + required_shells = list(/obj/item/organ/internal/cyberimp/bci, /obj/item/mod/module/circuit) + + /// 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 + + /// The mob who activated their granted action + var/datum/port/output/user + + /// Called when the user presses the button + var/datum/port/output/signal + + /// An assoc list of datum REF()s, linked to the actions granted. + var/list/granted_to = list() + +/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) + + user = add_output_port("User", PORT_TYPE_USER) + signal = add_output_port("Signal", PORT_TYPE_SIGNAL) + +/obj/item/circuit_component/equipment_action/Destroy() + QDEL_LIST_ASSOC_VAL(granted_to) + return ..() + +/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/register_shell(atom/movable/shell) + . = ..() + SEND_SIGNAL(shell, COMSIG_CIRCUIT_ACTION_COMPONENT_REGISTERED, src) + +/obj/item/circuit_component/equipment_action/unregister_shell(atom/movable/shell) + . = ..() + SEND_SIGNAL(shell, COMSIG_CIRCUIT_ACTION_COMPONENT_UNREGISTERED, src) + +/obj/item/circuit_component/equipment_action/input_received(datum/port/input/port) + if (length(granted_to)) + update_actions() + +/obj/item/circuit_component/equipment_action/proc/update_actions() + for(var/ref in granted_to) + var/datum/action/granted_action = granted_to[ref] + granted_action.name = button_name.value || "Action" + granted_action.button_icon_state = "bci_[replacetextEx(lowertext(icon_options.value), " ", "_")]" diff --git a/code/modules/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm index c3ac3154d2d132..c30c7e629f2fcf 100644 --- a/code/modules/wiremod/shell/brain_computer_interface.dm +++ b/code/modules/wiremod/shell/brain_computer_interface.dm @@ -10,8 +10,11 @@ /obj/item/organ/internal/cyberimp/bci/Initialize(mapload) . = ..() + RegisterSignal(src, COMSIG_CIRCUIT_ACTION_COMPONENT_REGISTERED, PROC_REF(action_comp_registered)) + RegisterSignal(src, COMSIG_CIRCUIT_ACTION_COMPONENT_UNREGISTERED, PROC_REF(action_comp_unregistered)) + var/obj/item/integrated_circuit/circuit = new(src) - circuit.add_component(new /obj/item/circuit_component/equipment_action/bci(null, "One")) + circuit.add_component(new /obj/item/circuit_component/equipment_action(null, "One")) AddComponent(/datum/component/shell, list( new /obj/item/circuit_component/bci_core, @@ -33,41 +36,17 @@ else return ..() -/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/internal/cyberimp/bci) - - /// A reference to the action button itself - var/datum/action/innate/bci_action/bci_action - -/obj/item/circuit_component/equipment_action/bci/Destroy() - QDEL_NULL(bci_action) - return ..() - -/obj/item/circuit_component/equipment_action/bci/register_shell(atom/movable/shell) - . = ..() - var/obj/item/organ/internal/cyberimp/bci/bci = shell - if(istype(bci)) - bci_action = new(src) - update_action() - - bci.actions += list(bci_action) - -/obj/item/circuit_component/equipment_action/bci/unregister_shell(atom/movable/shell) - var/obj/item/organ/internal/cyberimp/bci/bci = shell - if(istype(bci)) - bci.actions -= bci_action - QDEL_NULL(bci_action) - return ..() - -/obj/item/circuit_component/equipment_action/bci/input_received(datum/port/input/port) - if (!isnull(bci_action)) - update_action() +/obj/item/organ/internal/cyberimp/bci/proc/action_comp_registered(datum/source, obj/item/circuit_component/equipment_action/action_comp) + SIGNAL_HANDLER + LAZYADD(actions, new/datum/action/innate/bci_action(src, action_comp)) -/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), " ", "_")]" +/obj/item/organ/internal/cyberimp/bci/proc/action_comp_unregistered(datum/source, obj/item/circuit_component/equipment_action/action_comp) + SIGNAL_HANDLER + var/datum/action/innate/bci_action/action = action_comp.granted_to[REF(src)] + if(!istype(action)) + return + LAZYREMOVE(actions, action) + QDEL_LIST_ASSOC_VAL(action_comp.granted_to) /datum/action/innate/bci_action name = "Action" @@ -75,20 +54,23 @@ check_flags = AB_CHECK_CONSCIOUS button_icon_state = "bci_power" - var/obj/item/circuit_component/equipment_action/bci/circuit_component + var/obj/item/organ/internal/cyberimp/bci/bci + var/obj/item/circuit_component/equipment_action/circuit_component -/datum/action/innate/bci_action/New(obj/item/circuit_component/equipment_action/bci/circuit_component) +/datum/action/innate/bci_action/New(obj/item/organ/internal/cyberimp/bci/_bci, obj/item/circuit_component/equipment_action/circuit_component) ..() - + bci = _bci + circuit_component.granted_to[REF(_bci)] = src src.circuit_component = circuit_component /datum/action/innate/bci_action/Destroy() - circuit_component.bci_action = null + circuit_component.granted_to -= REF(bci) circuit_component = null return ..() /datum/action/innate/bci_action/Activate() + circuit_component.user.set_output(owner) circuit_component.signal.set_output(COMPONENT_SIGNAL) /obj/item/circuit_component/bci_core diff --git a/code/modules/wiremod/shell/module.dm b/code/modules/wiremod/shell/module.dm index 4201c6afb179a6..6f9a3dda93b7e1 100644 --- a/code/modules/wiremod/shell/module.dm +++ b/code/modules/wiremod/shell/module.dm @@ -10,8 +10,15 @@ /// A reference to the shell component, used to access the shell and its attached circuit var/datum/component/shell/shell + /// List of installed action components + var/list/obj/item/circuit_component/equipment_action/action_comps = list() + /obj/item/mod/module/circuit/Initialize(mapload) . = ..() + + RegisterSignal(src, COMSIG_CIRCUIT_ACTION_COMPONENT_REGISTERED, PROC_REF(action_comp_registered)) + RegisterSignal(src, COMSIG_CIRCUIT_ACTION_COMPONENT_UNREGISTERED, PROC_REF(action_comp_unregistered)) + shell = AddComponent(/datum/component/shell, \ list(new /obj/item/circuit_component/mod_adapter_core()), \ capacity = SHELL_CAPACITY_LARGE, \ @@ -22,6 +29,17 @@ if(drain_power(amount)) . = COMPONENT_OVERRIDE_POWER_USAGE +/obj/item/mod/module/circuit/proc/action_comp_registered(datum/source, obj/item/circuit_component/equipment_action/action_comp) + SIGNAL_HANDLER + action_comps += action_comp + +/obj/item/mod/module/circuit/proc/action_comp_unregistered(datum/source, obj/item/circuit_component/equipment_action/action_comp) + SIGNAL_HANDLER + action_comps -= action_comp + for(var/ref in action_comp.granted_to) + unpin_action(action_comp, locate(ref)) + QDEL_LIST_ASSOC_VAL(action_comp.granted_to) + /obj/item/mod/module/circuit/on_install() if(!shell?.attached_circuit) return @@ -30,6 +48,9 @@ /obj/item/mod/module/circuit/on_uninstall(deleting = FALSE) if(!shell?.attached_circuit) return + for(var/obj/item/circuit_component/equipment_action/action_comp in action_comps) + for(var/ref in action_comp.granted_to) + unpin_action(action_comp, locate(ref)) UnregisterSignal(shell?.attached_circuit, COMSIG_CIRCUIT_PRE_POWER_USAGE) /obj/item/mod/module/circuit/on_use() @@ -38,38 +59,79 @@ 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) + shell.attached_circuit?.interact(mod.wearer) + +/obj/item/mod/module/circuit/get_configuration(mob/user) + . = ..() + var/unnamed_action_index = 1 + for(var/obj/item/circuit_component/equipment_action/action_comp in action_comps) + .[REF(action_comp)] = add_ui_configuration(action_comp.button_name.value || "Unnamed Action [unnamed_action_index++]", "pin", !!action_comp.granted_to[REF(user)]) + +/obj/item/mod/module/circuit/configure_edit(key, value) + . = ..() + var/obj/item/circuit_component/equipment_action/action_comp = locate(key) in action_comps + if(!istype(action_comp)) + return + if(text2num(value)) + pin_action(action_comp, usr) + else + unpin_action(action_comp, usr) + +/obj/item/mod/module/circuit/proc/pin_action(obj/item/circuit_component/equipment_action/action_comp, mob/user) + if(!istype(user)) 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) + if(action_comp.granted_to[REF(user)]) // Sanity check - don't pin an action for a mob that has already pinned it return - if(!mod || !mod.wearer || !mod.active || mod.activating) + mod.add_item_action(new/datum/action/item_action/mod/pinnable/circuit(mod, user, src, action_comp)) + +/obj/item/mod/module/circuit/proc/unpin_action(obj/item/circuit_component/equipment_action/action_comp, mob/user) + var/datum/action/item_action/mod/pinnable/circuit/action = action_comp.granted_to[REF(user)] + if(!istype(action)) 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) + qdel(action) +/datum/action/item_action/mod/pinnable/circuit + button_icon = 'icons/mob/actions/actions_items.dmi' + button_icon_state = "bci_blank" + + /// A reference to the module containing this action's component + var/obj/item/mod/module/circuit/module + + /// A reference to the component this action triggers. + var/obj/item/circuit_component/equipment_action/circuit_component + +/datum/action/item_action/mod/pinnable/circuit/New(Target, mob/user, obj/item/mod/module/circuit/linked_module, obj/item/circuit_component/equipment_action/action_comp) + . = ..() + module = linked_module + action_comp.granted_to[REF(user)] = src + circuit_component = action_comp + name = action_comp.button_name.value + button_icon_state = "bci_[replacetextEx(lowertext(action_comp.icon_options.value), " ", "_")]" + +/datum/action/item_action/mod/pinnable/circuit/Destroy() + circuit_component.granted_to -= REF(pinner) + circuit_component = null + + return ..() + +/datum/action/item_action/mod/pinnable/circuit/Trigger(trigger_flags) + . = ..() + if(!.) + return + var/obj/item/mod/control/mod = module.mod + if(!istype(mod)) + return + if(!mod.active || mod.activating) + if(mod.wearer) + module.balloon_alert(mod.wearer, "not active!") + return + circuit_component.user.set_output(owner) + circuit_component.signal.set_output(COMPONENT_SIGNAL) + +/// If the guy whose UI we are pinned to got deleted +/datum/action/item_action/mod/pinnable/circuit/pinner_deleted() + module?.action_comps[circuit_component] -= REF(pinner) + . = ..() /obj/item/circuit_component/mod_adapter_core display_name = "MOD circuit adapter core" @@ -237,8 +299,3 @@ 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 6826d507e9ddb1..1473e8a321e8ba 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -5966,10 +5966,10 @@ #include "code\modules\visuals\render_steps.dm" #include "code\modules\wiremod\components\abstract\assoc_list_variable.dm" #include "code\modules\wiremod\components\abstract\compare.dm" -#include "code\modules\wiremod\components\abstract\equpiment_action.dm" #include "code\modules\wiremod\components\abstract\list_variable.dm" #include "code\modules\wiremod\components\abstract\module.dm" #include "code\modules\wiremod\components\abstract\variable.dm" +#include "code\modules\wiremod\components\action\equpiment_action.dm" #include "code\modules\wiremod\components\action\laserpointer.dm" #include "code\modules\wiremod\components\action\light.dm" #include "code\modules\wiremod\components\action\mmi.dm" diff --git a/tgui/packages/tgui/interfaces/MODsuit.tsx b/tgui/packages/tgui/interfaces/MODsuit.tsx index f4f9654abc28a5..5a979583e1df96 100644 --- a/tgui/packages/tgui/interfaces/MODsuit.tsx +++ b/tgui/packages/tgui/interfaces/MODsuit.tsx @@ -238,6 +238,22 @@ const ConfigureListEntry = (props) => { ); }; +const ConfigurePinEntry = (props) => { + const { name, value, module_ref } = props; + const { act } = useBackend(); + return ( +