diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm index d0d280dc194..115576b2833 100644 --- a/code/_onclick/drag_drop.dm +++ b/code/_onclick/drag_drop.dm @@ -10,14 +10,74 @@ return if(SEND_SIGNAL(src, COMSIG_MOUSEDROP_ONTO, over, usr) & COMPONENT_NO_MOUSEDROP) //Whatever is receiving will verify themselves for adjacency. return - if(over == src) - return usr.client.Click(src, src_location, src_control, params) + var/proximity_check = usr.client.check_drag_proximity(src, over, src_location, over_location, src_control, over_control, params) + if(proximity_check) + return proximity_check + if(!Adjacent(usr) || !over.Adjacent(usr)) return // should stop you from dragging through windows over.MouseDrop_T(src,usr, params) return +/// Handles treating drags as clicks if they're within some conditions +/// Does some other stuff adjacent to trying to figure out what the user actually "wanted" to click +/// Returns TRUE if it caused a click, FALSE otherwise +/client/proc/check_drag_proximity(atom/dragging, atom/over, src_location, over_location, src_control, over_control, params) + // We will swap which thing we're trying to check for clickability based off the type + // Assertion is if you drag a turf to anything else, you really just wanted to click the anything else + // And slightly misseed. I'm not interested in making this game pixel percise, so if it fits our other requirements + // Lets just let that through yeah? + var/atom/attempt_click = dragging + var/atom/click_from = over + var/location_to_use = src_location + var/control_to_use = src_control + if(isturf(attempt_click) && !isturf(over)) + // swapppp + attempt_click = over + click_from = dragging + location_to_use = over_location + control_to_use = over_control + + if(is_drag_clickable(attempt_click, click_from, params)) + Click(attempt_click, location_to_use, control_to_use, params) + return TRUE + return FALSE + +/// Distance in pixels that we consider "acceptable" from the initial click to the release +/// Note: this does not account for the position of the object, just where it is on the screen +#define LENIENCY_DISTANCE 16 +/// Accepted time in seconds between the initial click and drag release +/// Go higher then this and we just don't care anymore +#define LENIENCY_TIME (0.1 SECONDS) + +/// Does the logic for checking if a drag counts as a click or not +/// Returns true if it does, false otherwise +/client/proc/is_drag_clickable(atom/dragging, atom/over, params) + if(dragging == over) + return TRUE + if(world.time - drag_start > LENIENCY_TIME) // Time's up bestie + return FALSE + if(!get_turf(dragging)) // If it isn't in the world, drop it. This is for things that can move, and we assume hud elements will not have this problem + return FALSE + // Basically, are you trying to buckle someone down, or drag them onto you? + // If so, we know you must be right about what you want + if(ismovable(over)) + var/atom/movable/over_movable = over + // The buckle bit will cover most mobs, for stupid reasons. still useful here tho + if(over_movable.can_buckle || over_movable == eye) + return FALSE + + var/list/modifiers = params2list(params) + var/list/old_offsets = screen_loc_to_offset(LAZYACCESS(drag_details, SCREEN_LOC), view) + var/list/new_offsets = screen_loc_to_offset(LAZYACCESS(modifiers, SCREEN_LOC), view) + + var/distance = sqrt(((old_offsets[1] - new_offsets[1]) ** 2) + ((old_offsets[2] - new_offsets[2]) ** 2)) + if(distance > LENIENCY_DISTANCE) + return FALSE + + return TRUE + // receive a mousedrop /atom/proc/MouseDrop_T(atom/dropping, mob/user, params) SEND_SIGNAL(src, COMSIG_MOUSEDROPPED_ONTO, dropping, user, params) @@ -96,6 +156,9 @@ else middragtime = 0 middle_drag_atom_ref = null + if(!drag_start) // If we're just starting to drag + drag_start = world.time + drag_details = modifiers.Copy() mouseParams = params mouse_location_ref = WEAKREF(over_location) mouse_object_ref = WEAKREF(over_object) @@ -115,3 +178,5 @@ middragtime = 0 middle_drag_atom_ref = null ..() + drag_start = 0 + drag_details = null diff --git a/code/datums/ai/generic/generic_behaviors.dm b/code/datums/ai/generic/generic_behaviors.dm index cc0d415f3a0..bd454e3c27d 100644 --- a/code/datums/ai/generic/generic_behaviors.dm +++ b/code/datums/ai/generic/generic_behaviors.dm @@ -72,11 +72,11 @@ /datum/ai_behavior/use_in_hand/perform(delta_time, datum/ai_controller/controller) . = ..() var/mob/living/pawn = controller.pawn - var/obj/item/held = pawn.get_item_by_slot(pawn.get_active_hand()) + var/obj/item/held = pawn.get_active_held_item() if(!held) finish_action(controller, FALSE) return - pawn.activate_hand(pawn.get_active_hand()) + pawn.activate_hand() finish_action(controller, TRUE) /// Use the currently held item, or unarmed, on a weakref to an object in the world diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 4468ad719bc..b21a0339110 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1414,8 +1414,8 @@ GLOBAL_LIST_EMPTY(intento_players) return var/input - var/icon_x = text2num(modifiers["icon-x"]) - var/icon_y = text2num(modifiers["icon-y"]) + var/icon_x = text2num(modifiers[ICON_X]) + var/icon_y = text2num(modifiers[ICON_Y]) if(icon_x > ICON_SPLIT && icon_y > ICON_SPLIT) input = DISARM if(icon_x < ICON_SPLIT && icon_y > ICON_SPLIT) diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 10c7125d7fd..c3c6bd24425 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -172,6 +172,10 @@ var/middragtime = 0 //Middle-mouse-button clicked object control for aimbot exploit detection. Weakref var/datum/weakref/middle_drag_atom_ref + //When we started the currently active drag + var/drag_start = 0 + //The params we were passed at the start of the drag, in list form + var/list/drag_details /// Messages currently seen by this client diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 828a4415a9c..86f33016ec2 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -38,6 +38,9 @@ if(!held_index) held_index = (active_hand_index % held_items.len)+1 + if(!isnum(held_index)) + CRASH("You passed [held_index] into swap_hand instead of a number. WTF man") + var/oindex = active_hand_index active_hand_index = held_index if(hud_used)