From 75a3717a04bcd82fff5aa2c57f547840d95ce457 Mon Sep 17 00:00:00 2001 From: Timberpoes Date: Thu, 24 Jun 2021 18:30:33 +0100 Subject: [PATCH] Modifies right click logic so that it is not the same priority as modifier keys. (#59656) Strips out the existing right click code - Due to the myriad of ways right clicking has been implemented, dedicated signals and procs for right clicking without modifiers are fundamentally incompatible with our system of primary and secondary attacks. Adds additional signals to attacking code. These signals allow atoms to cancel the attack chain early on secondary attacks, or override the standard procs and not send signals to prevent any undesired behaviour from signal handlers. Items that used RightClick procs have been converted to attack_hand_secondary. The slaughter demon, having its own set of snowflake code as poor OOP principles have been applied in UnarmedAttack() procs with lacking calls to parent procs and arbitrary redefinition of behaviour, checks for a right click in its own UnarmedAttack() and performs a bodyslam off that. Storage components now hijack the secondary attackby stage via signals to handle their opening and closing shortcuts on right click. When you right click a storage component equipped item with an object in your active hand, the object has an opportunity to perform its logic in pre secondary attack code and cancel the attack chain. If it does not cancel the attack chain in pre-attack, then the storage component takes over for attackby and, if possible, opens the relevant inventory and ends the attack chain. The forensic scanner is a proof-of-concept of this working in action. With its scan logic moved from afterattack code to pre attack code for right clicking, right clicking with the scanner will now perform a scan where previously one was impossible. Left clicking still does what it always does - Scans at the very end of the attack chain. The logic still isn't perfect - For example, you still can't attack containers in melee even in combat mode (you'll either open them or put your weapon into them regardless of which option you choose) - But this is a better setup overall which allows for items to at least override this behaviour in pre-attack if needed. --- code/__DEFINES/dcs/signals.dm | 12 +++++-- code/_onclick/click.dm | 27 +--------------- code/_onclick/item_attack.dm | 17 +++++++++- code/_onclick/other_mobs.dm | 4 ++- .../components/storage/concrete/wallet.dm | 6 ++-- code/datums/components/storage/storage.dm | 31 +++++++++++-------- code/game/machinery/iv_drip.dm | 4 +++ code/game/machinery/washing_machine.dm | 4 +++ code/game/objects/items/stacks/stack.dm | 4 +++ code/game/objects/items/stacks/wrap.dm | 2 +- .../structures/crates_lockers/closets.dm | 2 +- .../antagonists/slaughter/slaughter.dm | 26 ++++++++++------ code/modules/clothing/under/_under.dm | 4 +++ code/modules/detectivework/scanner.dm | 7 +++-- .../kitchen_machinery/microwave.dm | 2 +- code/modules/paperwork/carbonpaper.dm | 5 ++- .../plumbing/plumbers/plumbing_buffer.dm | 5 +++ code/modules/wiremod/shell/controller.dm | 4 +-- 18 files changed, 100 insertions(+), 66 deletions(-) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 0d24b9ba172..decea2f50bd 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -87,6 +87,10 @@ #define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE "atom_init_success" ///from base of atom/attackby(): (/obj/item, /mob/living, params) #define COMSIG_PARENT_ATTACKBY "atom_attackby" +/// From base of [atom/proc/attacby_secondary()]: (/obj/item/weapon, /mob/user, params) +#define COMSIG_PARENT_ATTACKBY_SECONDARY "atom_attackby_secondary" +/// From base of [/atom/proc/attack_hand_secondary]: (mob/user, list/modifiers) - Called when the atom receives a secondary unarmed attack. +#define COMSIG_ATOM_ATTACK_HAND_SECONDARY "atom_attack_hand_secondary" ///Return this in response if you don't want afterattack to be called #define COMPONENT_NO_AFTERATTACK (1<<0) ///from base of atom/attack_hulk(): (/mob/living/carbon/human) @@ -340,9 +344,6 @@ #define COMSIG_EXIT_AREA "exit_area" ///from base of atom/Click(): (location, control, params, mob/user) #define COMSIG_CLICK "atom_click" -///from base of atom/RightClick(): (/mob) -#define COMSIG_CLICK_RIGHT "right_click" - #define COMPONENT_CANCEL_CLICK_RIGHT (1<<0) ///from base of atom/ShiftClick(): (/mob) #define COMSIG_CLICK_SHIFT "shift_click" #define COMPONENT_ALLOW_EXAMINATE (1<<0) //Allows the user to examinate regardless of client.eye. @@ -1243,6 +1244,11 @@ #define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" ///from base of obj/item/pre_attack(): (atom/target, mob/user, params) #define COMSIG_ITEM_PRE_ATTACK "item_pre_attack" +/// From base of [/obj/item/proc/pre_attack_secondary()]: (atom/target, mob/user, params) +#define COMSIG_ITEM_PRE_ATTACK_SECONDARY "item_pre_attack_secondary" + #define COMPONENT_SECONDARY_CANCEL_ATTACK_CHAIN (1<<0) + #define COMPONENT_SECONDARY_CONTINUE_ATTACK_CHAIN (1<<1) + #define COMPONENT_SECONDARY_CALL_NORMAL_ATTACK_CHAIN (1<<2) ///from base of obj/item/afterattack(): (atom/target, mob/user, params) #define COMSIG_ITEM_AFTERATTACK "item_afterattack" ///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, params) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 1883d13723a..a6cdaf29153 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -78,9 +78,6 @@ if(SEND_SIGNAL(src, COMSIG_MOB_CLICKON, A, params) & COMSIG_MOB_CANCEL_CLICKON) return var/list/modifiers = params2list(params) - if(LAZYACCESS(modifiers, RIGHT_CLICK)) - if(RightClickOn(A)) - return if(LAZYACCESS(modifiers, SHIFT_CLICK)) if(LAZYACCESS(modifiers, MIDDLE_CLICK)) ShiftMiddleClickOn(A) @@ -144,6 +141,7 @@ else if(ismob(A)) changeNext_move(CLICK_CD_MELEE) + UnarmedAttack(A, FALSE, modifiers) return @@ -307,29 +305,6 @@ */ /mob/proc/ranged_secondary_attack(atom/target, modifiers) -/** - * Right click - * - * Used for right-clicking interactions, in similar fashion of AltClick. - * Returns [atom/proc/RightClick] on the atom being right-clicked, which checks if the click chain doesn't continue. - * Arguments: - * * atom/target - The atom being rightclicked. - */ -/mob/proc/RightClickOn(atom/target) - return target.RightClick(src) - -/** - * Proc used for right-clicking - * - * Used for right-click interactions, called by [mob/proc/RightClickOn]. - * Returns TRUE if the click chain should not continue from a right-click. - * Arguments: - * * mob/user - The mob right-clicking. - */ -/atom/proc/RightClick(mob/user) - if(SEND_SIGNAL(src, COMSIG_CLICK_RIGHT, user) & COMPONENT_CANCEL_CLICK_RIGHT) - return TRUE - /** * Middle click * Mainly used for swapping hands diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index b8da3560dae..20d6e219919 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -8,7 +8,6 @@ * * [/obj/item/proc/afterattack]. The return value does not matter. */ /obj/item/proc/melee_attack_chain(mob/user, atom/target, params) - var/is_right_clicking = LAZYACCESS(params2list(params), RIGHT_CLICK) if(tool_behaviour && (target.tool_act(user, src, tool_behaviour, is_right_clicking) & TOOL_ACT_MELEE_CHAIN_BLOCKING)) @@ -99,6 +98,14 @@ * See: [/obj/item/proc/melee_attack_chain] */ /obj/item/proc/pre_attack_secondary(atom/target, mob/living/user, params) + var/signal_result = SEND_SIGNAL(src, COMSIG_ITEM_PRE_ATTACK_SECONDARY, target, user, params) + + if(signal_result & COMPONENT_SECONDARY_CANCEL_ATTACK_CHAIN) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if(signal_result & COMPONENT_SECONDARY_CONTINUE_ATTACK_CHAIN) + return SECONDARY_ATTACK_CONTINUE_CHAIN + return SECONDARY_ATTACK_CALL_NORMAL /** @@ -127,6 +134,14 @@ * See: [/obj/item/proc/melee_attack_chain] */ /atom/proc/attackby_secondary(obj/item/weapon, mob/user, params) + var/signal_result = SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY_SECONDARY, weapon, user, params) + + if(signal_result & COMPONENT_SECONDARY_CANCEL_ATTACK_CHAIN) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if(signal_result & COMPONENT_SECONDARY_CONTINUE_ATTACK_CHAIN) + return SECONDARY_ATTACK_CONTINUE_CHAIN + return SECONDARY_ATTACK_CALL_NORMAL /obj/attackby(obj/item/I, mob/living/user, params) diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index 3f53c598029..e62f6d2ce8b 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -60,7 +60,9 @@ /// When the user uses their hand on an item while holding right-click /// Returns a SECONDARY_ATTACK_* value. -/atom/proc/attack_hand_secondary(mob/user, modifiers) +/atom/proc/attack_hand_secondary(mob/user, list/modifiers) + if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_HAND_SECONDARY, user, modifiers) & COMPONENT_CANCEL_ATTACK_CHAIN) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN return SECONDARY_ATTACK_CALL_NORMAL //Return a non FALSE value to cancel whatever called this from propagating, if it respects it. diff --git a/code/datums/components/storage/concrete/wallet.dm b/code/datums/components/storage/concrete/wallet.dm index d4ab447ba0f..3da70fb7294 100644 --- a/code/datums/components/storage/concrete/wallet.dm +++ b/code/datums/components/storage/concrete/wallet.dm @@ -1,6 +1,6 @@ -/datum/component/storage/concrete/wallet/on_right_click(datum/source, mob/user) +/datum/component/storage/concrete/wallet/open_storage(mob/user) if(!isliving(user) || !user.CanReach(parent) || user.incapacitated()) - return + return FALSE if(locked) to_chat(user, span_warning("[parent] seems to be locked!")) return @@ -9,5 +9,5 @@ if(istype(A) && A.front_id && !issilicon(user) && !(A.item_flags & IN_STORAGE)) //if it's a wallet in storage seeing the full inventory is more useful var/obj/item/I = A.front_id INVOKE_ASYNC(src, .proc/attempt_put_in_hands, I, user) - return + return TRUE return ..() diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index 0bb5844201b..558574a96af 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -98,8 +98,8 @@ RegisterSignal(parent, COMSIG_MOVABLE_POST_THROW, .proc/close_all) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/on_move) - RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/on_alt_click) - RegisterSignal(parent, COMSIG_CLICK_RIGHT, .proc/on_right_click) + RegisterSignal(parent, list(COMSIG_CLICK_ALT, COMSIG_ATOM_ATTACK_HAND_SECONDARY), .proc/on_open_storage_click) + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY_SECONDARY, .proc/on_open_storage_attackby) RegisterSignal(parent, COMSIG_MOUSEDROP_ONTO, .proc/mousedrop_onto) RegisterSignal(parent, COMSIG_MOUSEDROPPED_ONTO, .proc/mousedrop_receive) @@ -839,22 +839,15 @@ return hide_from(target) -/datum/component/storage/proc/on_alt_click(datum/source, mob/user) - SIGNAL_HANDLER - - if(on_right_click(source, user)) - to_chat(user,span_warning("This action is being moved from alt-click to right-click.")) - -/datum/component/storage/proc/on_right_click(datum/source, mob/user) - SIGNAL_HANDLER +/datum/component/storage/proc/open_storage(mob/user) if(!isliving(user) || !user.CanReach(parent) || user.incapacitated()) - return + return FALSE if(locked) to_chat(user, span_warning("[parent] seems to be locked!")) - return + return FALSE - . = COMPONENT_CANCEL_CLICK_RIGHT + . = TRUE var/atom/A = parent if(!quickdraw) A.add_fingerprint(user) @@ -868,6 +861,18 @@ INVOKE_ASYNC(src, .proc/attempt_put_in_hands, to_remove, user) +/datum/component/storage/proc/on_open_storage_click(datum/source, mob/user, list/modifiers) + SIGNAL_HANDLER + + if(open_storage(user)) + return COMPONENT_CANCEL_ATTACK_CHAIN + +/datum/component/storage/proc/on_open_storage_attackby(datum/source, obj/item/weapon, mob/user, params) + SIGNAL_HANDLER + + if(open_storage(user)) + return COMPONENT_SECONDARY_CANCEL_ATTACK_CHAIN + ///attempt to put an item from contents into the users hands /datum/component/storage/proc/attempt_put_in_hands(obj/item/to_remove, mob/user) var/atom/parent_as_atom = parent diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 2004888fe4c..6b918f7001c 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -179,6 +179,10 @@ toggle_mode() /obj/machinery/iv_drip/attack_hand_secondary(mob/user, modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + if(dripfeed) dripfeed = FALSE to_chat(usr, span_notice("You loosen the valve to speed up the [src].")) diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index 965f21f3b36..5aa0c4f42a9 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -346,6 +346,10 @@ GLOBAL_LIST_INIT(dye_registry, list( update_appearance() /obj/machinery/washing_machine/attack_hand_secondary(mob/user, modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + if(!user.canUseTopic(src, !issilicon(user))) return SECONDARY_ATTACK_CONTINUE_CHAIN if(busy) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index b1c5f47c792..1a7edcd2d59 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -464,6 +464,10 @@ . = ..() /obj/item/stack/attack_hand_secondary(mob/user, modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + if(is_cyborg || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)) || zero_amount()) return SECONDARY_ATTACK_CONTINUE_CHAIN var/max = get_amount() diff --git a/code/game/objects/items/stacks/wrap.dm b/code/game/objects/items/stacks/wrap.dm index 8a3cc375eef..f4d51cf7e61 100644 --- a/code/game/objects/items/stacks/wrap.dm +++ b/code/game/objects/items/stacks/wrap.dm @@ -34,7 +34,7 @@ //Set layers to these colors, base then ribbon set_greyscale(colors = list(generated_base_color, generated_ribbon_color)) -/obj/item/stack/wrapping_paper/RightClick(mob/user, modifiers) +/obj/item/stack/wrapping_paper/attack_hand_secondary(mob/user, modifiers) var/new_base = input(user, "", "Select a base color", color) as color var/new_ribbon = input(user, "", "Select a ribbon color", color) as color if(!user.canUseTopic(src, BE_CLOSE)) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index f427bb76737..2e3c0c99cca 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -466,7 +466,7 @@ broken = TRUE //applies to secure lockers only open() -/obj/structure/closet/RightClick(mob/user, modifiers) +/obj/structure/closet/attack_hand_secondary(mob/user, modifiers) if(!user.canUseTopic(src, BE_CLOSE) || !isturf(loc)) return if(!opened && secure) diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm index 49f786e350a..aed8644a728 100644 --- a/code/modules/antagonists/slaughter/slaughter.dm +++ b/code/modules/antagonists/slaughter/slaughter.dm @@ -95,20 +95,21 @@ if(bloodpool) bloodpool.RegisterSignal(src, list(COMSIG_LIVING_AFTERPHASEIN,COMSIG_PARENT_QDELETING), /obj/effect/dummy/phased_mob/.proc/deleteself) -/mob/living/simple_animal/hostile/imp/slaughter/RightClickOn(atom/A) - if(!isliving(A)) - return ..() +/// Performs the classic slaughter demon bodyslam on the attack_target. Yeets them a screen away. +/mob/living/simple_animal/hostile/imp/slaughter/proc/bodyslam(atom/attack_target) + if(!isliving(attack_target)) + return - if(!Adjacent(A)) - to_chat(src, span_warning("You are too far away to use your slam attack on [A]!")) + if(!Adjacent(attack_target)) + to_chat(src, span_warning("You are too far away to use your slam attack on [attack_target]!")) return if(slam_cooldown + slam_cooldown_time > world.time) to_chat(src, span_warning("Your slam ability is still on cooldown!")) return - face_atom(A) - var/mob/living/victim = A + face_atom(attack_target) + var/mob/living/victim = attack_target victim.take_bodypart_damage(brute=20, wound_bonus=wound_bonus) // don't worry, there's more punishment when they hit something visible_message(span_danger("[src] slams into [victim] with monstrous strength!"), span_danger("You slam into [victim] with monstrous strength!"), ignored_mobs=victim) to_chat(victim, span_userdanger("[src] slams into you with monstrous strength, sending you flying like a ragdoll!")) @@ -117,11 +118,16 @@ slam_cooldown = world.time log_combat(src, victim, "slaughter slammed") -/mob/living/simple_animal/hostile/imp/slaughter/UnarmedAttack(atom/A, proximity_flag, list/modifiers) +/mob/living/simple_animal/hostile/imp/slaughter/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) + if(LAZYACCESS(modifiers, RIGHT_CLICK)) + bodyslam(attack_target) + return + if(HAS_TRAIT(src, TRAIT_HANDS_BLOCKED)) return - if(iscarbon(A)) - var/mob/living/carbon/target = A + + if(iscarbon(attack_target)) + var/mob/living/carbon/target = attack_target if(target.stat != DEAD && target.mind && current_hitstreak < wound_bonus_hitstreak_max) current_hitstreak++ wound_bonus += wound_bonus_per_hit diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index 9c0db2d3ce6..3025e005c01 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -45,6 +45,10 @@ return ..() /obj/item/clothing/under/attack_hand_secondary(mob/user, params) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + toggle() return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm index 0c26985ec83..04d92cfb662 100644 --- a/code/modules/detectivework/scanner.dm +++ b/code/modules/detectivework/scanner.dm @@ -38,9 +38,6 @@ else to_chat(user, span_notice("The scanner has no logs or is in use.")) -/obj/item/detective_scanner/attack(mob/living/M, mob/user) - return - /obj/item/detective_scanner/proc/PrintReport() // Create our paper var/obj/item/paper/P = new(get_turf(src)) @@ -63,6 +60,10 @@ log = list() scanning = FALSE +/obj/item/detective_scanner/pre_attack_secondary(atom/A, mob/user, params) + scan(A, user) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + /obj/item/detective_scanner/afterattack(atom/A, mob/user, params) . = ..() scan(A, user) diff --git a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm index 70bb0107063..1aa75330ec1 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm @@ -198,7 +198,7 @@ ..() -/obj/machinery/microwave/RightClick(mob/user) +/obj/machinery/microwave/attack_hand_secondary(mob/user, list/modifiers) if(user.canUseTopic(src, !issilicon(usr))) cook() diff --git a/code/modules/paperwork/carbonpaper.dm b/code/modules/paperwork/carbonpaper.dm index bff767aa732..2f8662aaeef 100644 --- a/code/modules/paperwork/carbonpaper.dm +++ b/code/modules/paperwork/carbonpaper.dm @@ -45,7 +45,10 @@ user.put_in_hands(Copy) /obj/item/paper/carbon/attack_hand_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + if(loc == user && user.is_holding(src)) removecopy(user) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - return ..() diff --git a/code/modules/plumbing/plumbers/plumbing_buffer.dm b/code/modules/plumbing/plumbers/plumbing_buffer.dm index fe2b7649d81..47494c35dc4 100644 --- a/code/modules/plumbing/plumbers/plumbing_buffer.dm +++ b/code/modules/plumbing/plumbers/plumbing_buffer.dm @@ -71,6 +71,10 @@ /obj/machinery/plumbing/buffer/attack_hand_secondary(mob/user, modifiers) . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + + . = SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN var/new_volume = input(user, "Enter new activation threshold", "Beepityboop", activation_volume) as num|null if(!new_volume) @@ -78,6 +82,7 @@ activation_volume = round(clamp(new_volume, 0, buffer)) to_chat(user, span_notice("New activation threshold is now [activation_volume].")) + return /obj/machinery/plumbing/buffer/attackby(obj/item/item, mob/user, params) if(item.tool_behaviour == TOOL_SCREWDRIVER) diff --git a/code/modules/wiremod/shell/controller.dm b/code/modules/wiremod/shell/controller.dm index 8df6782822b..c70493b7fd2 100644 --- a/code/modules/wiremod/shell/controller.dm +++ b/code/modules/wiremod/shell/controller.dm @@ -45,12 +45,12 @@ /obj/item/circuit_component/controller/register_shell(atom/movable/shell) RegisterSignal(shell, COMSIG_ITEM_ATTACK_SELF, .proc/send_trigger) RegisterSignal(shell, COMSIG_CLICK_ALT, .proc/send_alternate_signal) - RegisterSignal(shell, COMSIG_CLICK_RIGHT, .proc/send_right_signal) + RegisterSignal(shell, COMSIG_ATOM_ATTACK_HAND_SECONDARY, .proc/send_right_signal) /obj/item/circuit_component/controller/unregister_shell(atom/movable/shell) UnregisterSignal(shell, list( COMSIG_ITEM_ATTACK_SELF, - COMSIG_CLICK_RIGHT, + COMSIG_ATOM_ATTACK_HAND_SECONDARY, COMSIG_CLICK_ALT, ))