From 9c9a5d28ffbbec7493f907b20c2de0386164739f Mon Sep 17 00:00:00 2001 From: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Date: Wed, 26 Jun 2024 04:36:59 +0530 Subject: [PATCH] Some alt & ctrl click improvements (#84203) ## About The Pull Request Improved code quality of both so they resemble each other. Some of the new specs are as follows 1. Moved` COMSIG_CLICK_ALT` & `COMSIG_CLICK_ALT_SECONDARY` up i.e. before `can_perform_action()` making them pure hooks not bound by any action checks giving components full control over them 2. Removed range check(`CAN_I_SEE`) & view check(`is_blind()`) out of the base alt click proc. They now only apply to living mobs and don't apply to ghosts(ghosts don't get blind & see everything) & revenants (the range check still applies for revenants though). This was actually a bug because these 2 checks were only meant to see if the loot panel could be opened (as stated in https://github.com/tgstation/tgstation/pull/83736#discussion_r1628097941) but because they are at the top of the proc they also apply to all alt click actions which is not intended. Also, by moving these checks down to mob subtype levels some of the snowflake checks like this https://github.com/tgstation/tgstation/blob/7579e0e1734ee40b33ce1fd3fc5c2dd08fe30404/code/_onclick/click_alt.dm#L23 can be removed. We should not check for subtypes within the parent type proc but instead have subtypes override their parent procs to implement custom behaviour 3. Removed redundant signals like` COMSIG_XENO_SLIME_CLICK_ALT` in favour of just `COMSIG_MOB_ALTCLICKON` 4. While looking for alt click signal overrides I found alt click for style meter was run timing, that's fixed now ## Changelog :cl: fix: alt click runtime no more when using style meter code: improved alt & ctrl click code /:cl: --- .../dcs/signals/signals_xeno_control.dm | 2 - code/__DEFINES/mobs.dm | 4 +- code/_onclick/click.dm | 4 +- code/_onclick/click_alt.dm | 65 +++++++++---------- code/_onclick/click_ctrl.dm | 11 ++-- code/datums/ai/oldhostile/hostile_tameable.dm | 5 +- .../components/pet_commands/obeys_commands.dm | 2 +- code/datums/components/rotation.dm | 1 + code/datums/components/style/style_meter.dm | 4 +- code/datums/components/toggle_suit.dm | 17 ++--- code/datums/storage/storage.dm | 9 +-- code/modules/mob/dead/observer/observer.dm | 10 ++- .../basic/guardian/guardian_types/support.dm | 6 +- .../basic/space_fauna/revenant/_revenant.dm | 4 ++ code/modules/mob/living/living.dm | 2 +- code/modules/mob/mob.dm | 1 + .../research/xenobiology/xenobio_camera.dm | 25 +++---- code/modules/wiremod/shell/controller.dm | 5 +- 18 files changed, 89 insertions(+), 88 deletions(-) diff --git a/code/__DEFINES/dcs/signals/signals_xeno_control.dm b/code/__DEFINES/dcs/signals/signals_xeno_control.dm index c67756a64f3..660dc9ce446 100644 --- a/code/__DEFINES/dcs/signals/signals_xeno_control.dm +++ b/code/__DEFINES/dcs/signals/signals_xeno_control.dm @@ -1,7 +1,5 @@ //Xenobio hotkeys -///from slime AltClickOn(): (/mob) -#define COMSIG_XENO_SLIME_CLICK_ALT "xeno_slime_click_alt" ///from slime ShiftClickOn(): (/mob) #define COMSIG_XENO_SLIME_CLICK_SHIFT "xeno_slime_click_shift" ///from turf ShiftClickOn(): (/mob) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index f1a48df79fa..f22e4d9c723 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -837,8 +837,10 @@ GLOBAL_LIST_INIT(layers_to_offset, list( #define NEED_VENTCRAWL (1<<8) /// Skips adjacency checks #define BYPASS_ADJACENCY (1<<9) +/// Skips reccursive loc checks +#define NOT_INSIDE_TARGET (1<<10) /// Checks for base adjacency, but silences the error -#define SILENT_ADJACENCY (1<<10) +#define SILENT_ADJACENCY (1<<11) /// The default mob sprite size (used for shrinking or enlarging the mob sprite to regular size) #define RESIZE_DEFAULT_SIZE 1 diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 4dde5a7f04a..cd8563d849f 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -93,9 +93,9 @@ return if(LAZYACCESS(modifiers, ALT_CLICK)) // alt and alt-gr (rightalt) if(LAZYACCESS(modifiers, RIGHT_CLICK)) - base_click_alt_secondary(A) + AltClickSecondaryOn(A) else - base_click_alt(A) + AltClickOn(A) return if(LAZYACCESS(modifiers, CTRL_CLICK)) CtrlClickOn(A) diff --git a/code/_onclick/click_alt.dm b/code/_onclick/click_alt.dm index 51c58408e25..28801b9816d 100644 --- a/code/_onclick/click_alt.dm +++ b/code/_onclick/click_alt.dm @@ -1,5 +1,9 @@ +///Main proc for primary alt click +/mob/proc/AltClickOn(atom/target) + base_click_alt(target) + /** - * ### Base proc for alt click interaction left click. + * ### Base proc for alt click interaction left click. Returns if the click was intercepted & handled * * If you wish to add custom `click_alt` behavior for a single type, use that proc. */ @@ -8,43 +12,36 @@ // Check if they've hooked in to prevent src from alt clicking anything if(SEND_SIGNAL(src, COMSIG_MOB_ALTCLICKON, target) & COMSIG_MOB_CANCEL_CLICKON) - return + return TRUE - // Is it visible (and we're not wearing it (our clothes are invisible))? - if(!CAN_I_SEE(target)) - return - - if(is_blind() && !IN_GIVEN_RANGE(src, target, 1)) - return - - var/turf/tile = get_turf(target) - - // Ghosties just see loot - if(isobserver(src) || isrevenant(src)) - client.loot_panel.open(tile) - return + // If it has a signal handler that returns a click action, done. + if(SEND_SIGNAL(target, COMSIG_CLICK_ALT, src) & CLICK_ACTION_ANY) + return TRUE + // If it has a custom click_alt that returns success/block, done. if(can_perform_action(target, (target.interaction_flags_click | SILENT_ADJACENCY))) - // If it has a signal handler that returns a click action, done. - if(SEND_SIGNAL(target, COMSIG_CLICK_ALT, src) & CLICK_ACTION_ANY) - return + return target.click_alt(src) & CLICK_ACTION_ANY - // If it has a custom click_alt that returns success/block, done. - if(target.click_alt(src) & CLICK_ACTION_ANY) - return + return FALSE + +/mob/living/base_click_alt(atom/target) + SHOULD_NOT_OVERRIDE(TRUE) + + . = ..() + if(. || !CAN_I_SEE(target) || (is_blind() && !IN_GIVEN_RANGE(src, target, 1))) + return // No alt clicking to view turf from beneath if(HAS_TRAIT(src, TRAIT_MOVE_VENTCRAWLING)) return /// No loot panel if it's on our person - if(isobj(target) && isliving(src)) - var/mob/living/user = src - if(target in user.get_all_gear()) - to_chat(user, span_warning("You can't search for this item, it's already in your inventory! Take it off first.")) - return + if(isobj(target) && (target in get_all_gear())) + to_chat(src, span_warning("You can't search for this item, it's already in your inventory! Take it off first.")) + return - client.loot_panel.open(tile) + client.loot_panel.open(get_turf(target)) + return TRUE /** * ## Custom alt click interaction @@ -78,6 +75,10 @@ return NONE +///Main proc for secondary alt click +/mob/proc/AltClickSecondaryOn(atom/target) + base_click_alt_secondary(target) + /** * ### Base proc for alt click interaction right click. * @@ -90,17 +91,13 @@ if(SEND_SIGNAL(src, COMSIG_MOB_ALTCLICKON_SECONDARY, target) & COMSIG_MOB_CANCEL_CLICKON) return - if(!can_perform_action(target, target.interaction_flags_click | SILENT_ADJACENCY)) - return - //Hook on the atom to intercept the click if(SEND_SIGNAL(target, COMSIG_CLICK_ALT_SECONDARY, src) & COMPONENT_CANCEL_CLICK_ALT_SECONDARY) return - if(isobserver(src) && client && check_rights_for(client, R_DEBUG)) - client.toggle_tag_datum(src) - return - target.click_alt_secondary(src) + // If it has a custom click_alt_secondary then do that + if(can_perform_action(target, target.interaction_flags_click | SILENT_ADJACENCY)) + target.click_alt_secondary(src) /** * ## Custom alt click secondary interaction diff --git a/code/_onclick/click_ctrl.dm b/code/_onclick/click_ctrl.dm index 2e80f017816..72f67b4271e 100644 --- a/code/_onclick/click_ctrl.dm +++ b/code/_onclick/click_ctrl.dm @@ -20,12 +20,11 @@ if(SEND_SIGNAL(target, COMSIG_CLICK_CTRL, src) & CLICK_ACTION_ANY) return TRUE - // This means the action has been processed even though nothing happened - if(!can_perform_action(target, target.interaction_flags_click | SILENT_ADJACENCY)) - return TRUE - // If it has a custom click_alt that returns success/block, done. - return target.click_ctrl(src) & CLICK_ACTION_ANY + if(can_perform_action(target, target.interaction_flags_click | SILENT_ADJACENCY)) + return target.click_ctrl(src) & CLICK_ACTION_ANY + + return FALSE /** * Ctrl click @@ -35,7 +34,7 @@ SHOULD_NOT_OVERRIDE(TRUE) . = ..() - if(. || world.time < next_move || !CanReach(target)) + if(. || world.time < next_move || !can_perform_action(target, NOT_INSIDE_TARGET | SILENT_ADJACENCY)) return . = TRUE diff --git a/code/datums/ai/oldhostile/hostile_tameable.dm b/code/datums/ai/oldhostile/hostile_tameable.dm index d76ffb8a282..1c30cb95487 100644 --- a/code/datums/ai/oldhostile/hostile_tameable.dm +++ b/code/datums/ai/oldhostile/hostile_tameable.dm @@ -106,10 +106,11 @@ if(!COOLDOWN_FINISHED(src, command_cooldown)) return - if(!istype(clicker) || blackboard[BB_HOSTILE_FRIEND] != clicker) + if(!istype(clicker) || blackboard[BB_HOSTILE_FRIEND] != clicker || !clicker.can_perform_action(source)) return - . = CLICK_ACTION_BLOCKING + INVOKE_ASYNC(src, PROC_REF(command_radial), clicker) + return CLICK_ACTION_BLOCKING /// Show the command radial menu /datum/ai_controller/hostile_friend/proc/command_radial(mob/living/clicker) diff --git a/code/datums/components/pet_commands/obeys_commands.dm b/code/datums/components/pet_commands/obeys_commands.dm index ec3a04c940a..8aaa7e71792 100644 --- a/code/datums/components/pet_commands/obeys_commands.dm +++ b/code/datums/components/pet_commands/obeys_commands.dm @@ -66,7 +66,7 @@ SIGNAL_HANDLER var/mob/living/living_parent = parent - if (IS_DEAD_OR_INCAP(living_parent)) + if (IS_DEAD_OR_INCAP(living_parent) || !clicker.can_perform_action(living_parent)) return if (!(clicker in living_parent.ai_controller?.blackboard[BB_FRIENDS_LIST])) return // Not our friend, can't boss us around diff --git a/code/datums/components/rotation.dm b/code/datums/components/rotation.dm index f872c6bfd69..6ff8197e093 100644 --- a/code/datums/components/rotation.dm +++ b/code/datums/components/rotation.dm @@ -55,6 +55,7 @@ /datum/component/simple_rotation/proc/rotate_right(datum/source, mob/user) SIGNAL_HANDLER rotate(user, ROTATION_CLOCKWISE) + return CLICK_ACTION_SUCCESS /datum/component/simple_rotation/proc/rotate_left(datum/source, mob/user) SIGNAL_HANDLER diff --git a/code/datums/components/style/style_meter.dm b/code/datums/components/style/style_meter.dm index c06fc35aca3..94263700dda 100644 --- a/code/datums/components/style/style_meter.dm +++ b/code/datums/components/style/style_meter.dm @@ -93,10 +93,10 @@ /obj/item/style_meter/proc/on_click_alt(datum/source, mob/user) SIGNAL_HANDLER - if(!istype(loc, /obj/item/clothing/glasses)) + if(!istype(loc, /obj/item/clothing/glasses) || !user.can_perform_action(source)) return CLICK_ACTION_BLOCKING - clean_up() + clean_up(loc) forceMove(get_turf(src)) return CLICK_ACTION_SUCCESS diff --git a/code/datums/components/toggle_suit.dm b/code/datums/components/toggle_suit.dm index aee7522745e..022fc37c07a 100644 --- a/code/datums/components/toggle_suit.dm +++ b/code/datums/components/toggle_suit.dm @@ -36,24 +36,15 @@ * source - the atom being clicked on * user - the mob doing the click */ -/datum/component/toggle_icon/proc/on_click_alt(atom/source, mob/user) +/datum/component/toggle_icon/proc/on_click_alt(atom/source, mob/living/living_user) SIGNAL_HANDLER - if(!isliving(user)) + if(!isliving(living_user) || !living_user.can_perform_action(source)) return - var/mob/living/living_user = user - - if(!living_user.Adjacent(source)) - return - - if(living_user.incapacitated()) - source.balloon_alert(user, "you're incapacitated!") - return CLICK_ACTION_BLOCKING - if(living_user.usable_hands <= 0) - source.balloon_alert(user, "you don't have hands!") - return CLICK_ACTION_BLOCKING + source.balloon_alert(living_user, "you don't have hands!") + return do_icon_toggle(source, living_user) return CLICK_ACTION_SUCCESS diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index 2a5bd2a98fd..38c39300d54 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -954,8 +954,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) if(!click_alt_open) return - return open_storage_on_signal(source, user) - + return open_storage_on_signal(source, user) ? CLICK_ACTION_SUCCESS : NONE /// Opens the storage to the mob, showing them the contents to their UI. /datum/storage/proc/open_storage(mob/to_show) @@ -963,11 +962,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) show_contents(to_show) return FALSE - if(!to_show.CanReach(parent)) - parent.balloon_alert(to_show, "can't reach!") - return FALSE - - if(!isliving(to_show) || to_show.incapacitated()) + if(!isliving(to_show) || !to_show.can_perform_action(parent)) return FALSE if(locked) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 3c02de47073..1a7b362ec2e 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -693,8 +693,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp //this is called when a ghost is drag clicked to something. /mob/dead/observer/mouse_drop_dragged(atom/over, mob/user) if (isobserver(user) && user.client.holder && (isliving(over) || iscameramob(over))) - if (user.client.holder.cmd_ghost_drag(src,over)) - return + user.client.holder.cmd_ghost_drag(src, over) /mob/dead/observer/Topic(href, href_list) ..() @@ -983,6 +982,13 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp game = create_mafia_game() game.ui_interact(usr) +/mob/dead/observer/AltClickOn(atom/target) + client.loot_panel.open(get_turf(target)) + +/mob/dead/observer/AltClickSecondaryOn(atom/target) + if(client && check_rights_for(client, R_DEBUG)) + client.toggle_tag_datum(src) + /mob/dead/observer/CtrlShiftClickOn(atom/target) if(isobserver(target) && check_rights(R_SPAWN)) var/mob/dead/observer/target_ghost = target diff --git a/code/modules/mob/living/basic/guardian/guardian_types/support.dm b/code/modules/mob/living/basic/guardian/guardian_types/support.dm index 3b5574db7f3..8ab24b7e9b7 100644 --- a/code/modules/mob/living/basic/guardian/guardian_types/support.dm +++ b/code/modules/mob/living/basic/guardian/guardian_types/support.dm @@ -103,10 +103,12 @@ /// Try and teleport something to our beacon /datum/action/cooldown/mob_cooldown/guardian_bluespace_beacon/proc/try_teleporting(mob/living/source, atom/target) SIGNAL_HANDLER + if (!can_teleport(source, target)) return + INVOKE_ASYNC(src, PROC_REF(perform_teleport), source, target) - return COMPONENT_CANCEL_ATTACK_CHAIN + return COMSIG_MOB_CANCEL_CLICKON /// Validate whether we can teleport this object /datum/action/cooldown/mob_cooldown/guardian_bluespace_beacon/proc/can_teleport(mob/living/source, atom/movable/target) @@ -118,7 +120,7 @@ if (!guardian_mob.is_deployed()) source.balloon_alert(source, "manifest yourself!") return FALSE - if (!source.Adjacent(target)) + if (!source.can_perform_action(target)) target.balloon_alert(source, "too far!") return FALSE if (target.anchored) diff --git a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm index 4ba903d9928..a154ba9da0c 100644 --- a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm +++ b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm @@ -150,6 +150,10 @@ update_appearance(UPDATE_ICON) update_health_hud() +/mob/living/basic/revenant/AltClickOn(atom/target) + if(CAN_I_SEE(target)) + client.loot_panel.open(get_turf(target)) + /mob/living/basic/revenant/get_status_tab_items() . = ..() . += "Current Essence: [essence >= max_essence ? essence : "[essence] / [max_essence]"] E" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 54fce885a80..a03d00648c6 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1345,7 +1345,7 @@ to_chat(src, span_warning("You don't have the hands for this action!")) return FALSE - if(!(action_bitflags & BYPASS_ADJACENCY) && !recursive_loc_check(src, target) && !CanReach(target)) + if(!(action_bitflags & BYPASS_ADJACENCY) && ((action_bitflags & NOT_INSIDE_TARGET) || !recursive_loc_check(src, target)) && !CanReach(target)) if(HAS_SILICON_ACCESS(src) && !ispAI(src)) if(!(action_bitflags & ALLOW_SILICON_REACH)) // silicons can ignore range checks (except pAIs) if(!(action_bitflags & SILENT_ADJACENCY)) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 7dd1cf0d288..f24f5a58c0d 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1160,6 +1160,7 @@ * * ALLOW_VENTCRAWL - Mobs with ventcrawl traits can alt-click this to vent * * BYPASS_ADJACENCY - The target does not have to be adjacent * * SILENT_ADJACENCY - Adjacency is required but errors are not printed + * * NOT_INSIDE_TARGET - The target maybe adjacent but the mob should not be inside the target * * silence_adjacency: Sometimes we want to use this proc to check interaction without allowing it to throw errors for base case adjacency * Alt click uses this, as otherwise you can detect what is interactable from a distance via the error message diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index 5dbe284026d..68ffe5e9248 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -91,18 +91,20 @@ eyeobj.icon_state = "generic_camera" /obj/machinery/computer/camera_advanced/xenobio/GrantActions(mob/living/user) - ..() + . = ..() RegisterSignal(user, COMSIG_MOB_CTRL_CLICKED, PROC_REF(XenoClickCtrl)) - RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_ALT, PROC_REF(XenoSlimeClickAlt)) + RegisterSignal(user, COMSIG_MOB_ALTCLICKON, PROC_REF(XenoSlimeClickAlt)) RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_SHIFT, PROC_REF(XenoSlimeClickShift)) RegisterSignal(user, COMSIG_XENO_TURF_CLICK_SHIFT, PROC_REF(XenoTurfClickShift)) /obj/machinery/computer/camera_advanced/xenobio/remove_eye_control(mob/living/user) - UnregisterSignal(user, COMSIG_MOB_CTRL_CLICKED) - UnregisterSignal(user, COMSIG_XENO_SLIME_CLICK_ALT) - UnregisterSignal(user, COMSIG_XENO_SLIME_CLICK_SHIFT) - UnregisterSignal(user, COMSIG_XENO_TURF_CLICK_SHIFT) - ..() + UnregisterSignal(user, list( + COMSIG_MOB_CTRL_CLICKED, + COMSIG_MOB_ALTCLICKON, + COMSIG_XENO_SLIME_CLICK_SHIFT, + COMSIG_XENO_TURF_CLICK_SHIFT, + )) + return ..() /obj/machinery/computer/camera_advanced/xenobio/attackby(obj/item/used_item, mob/user, params) if(istype(used_item, /obj/item/food/monkeycube)) @@ -355,11 +357,6 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo // // Alternate clicks for slime, monkey and open turf if using a xenobio console - -/mob/living/basic/slime/click_alt(mob/user) - SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_ALT, src) - return CLICK_ACTION_SUCCESS - /mob/living/basic/slime/ShiftClick(mob/user) SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_SHIFT, src) ..() @@ -372,6 +369,10 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo /obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickAlt(mob/living/user, mob/living/basic/slime/target_slime) SIGNAL_HANDLER + . = COMSIG_MOB_CANCEL_CLICKON + if(!isslime(target_slime)) + return + var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin diff --git a/code/modules/wiremod/shell/controller.dm b/code/modules/wiremod/shell/controller.dm index 9afe0303be8..126cc889436 100644 --- a/code/modules/wiremod/shell/controller.dm +++ b/code/modules/wiremod/shell/controller.dm @@ -81,6 +81,9 @@ */ /obj/item/circuit_component/controller/proc/send_right_signal(atom/source, mob/user) SIGNAL_HANDLER - if(!user.Adjacent(source)) + + if(!user.can_perform_action(source)) return + handle_trigger(source, user, "extra", right) + return CLICK_ACTION_SUCCESS