Clicks refactor (#20321)

Added various events to the dcs system in regards to click handling.
Refactored various mouse related procs.
Fixed MUI mask.
Fixed AI jump on double click.
Fixed some runtimes with the click handler system.
Updated the click handler system.
Fixed fireman carry.
This commit is contained in:
Fluffy
2025-01-09 23:04:48 +00:00
committed by GitHub
parent db6d55b759
commit 457a091d9a
31 changed files with 661 additions and 310 deletions
+23 -13
View File
@@ -9,8 +9,9 @@
Note that AI have no need for the adjacency proc, and so this proc is a lot cleaner.
*/
/mob/living/silicon/ai/DblClickOn(var/atom/A, params)
if(control_disabled || stat) return
/mob/living/silicon/ai/DblClickOn(atom/A, params)
if(control_disabled || stat)
return
if(ismob(A))
ai_actual_track(A)
@@ -18,7 +19,7 @@
A.move_camera_by_click()
/mob/living/silicon/ai/ClickOn(var/atom/A, params)
/mob/living/silicon/ai/ClickOn(atom/A, params)
if(world.time <= next_click)
return
next_click = world.time + 1
@@ -27,19 +28,28 @@
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["middle"])
MiddleClickOn(A)
return
if(modifiers["shift"])
if(LAZYACCESS(modifiers, SHIFT_CLICK))
if(LAZYACCESS(modifiers, MIDDLE_CLICK))
ShiftMiddleClickOn(A)
return
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlShiftClickOn(A)
return
ShiftClickOn(A)
return
if(modifiers["alt"]) // alt and alt-gr (rightalt)
AltClickOn(A)
if(LAZYACCESS(modifiers, MIDDLE_CLICK))
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlMiddleClickOn(A)
else
MiddleClickOn(A, params)
return
if(modifiers["ctrl"])
if(LAZYACCESS(modifiers, ALT_CLICK)) // alt and alt-gr (rightalt)
if(LAZYACCESS(modifiers, RIGHT_CLICK))
AltClickSecondaryOn(A)
else
AltClickOn(A)
return
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlClickOn(A)
return
+184 -226
View File
@@ -6,49 +6,38 @@
// 1 decisecond click delay (above and beyond mob/next_move)
/mob/var/next_click = 0
/*
Before anything else, defer these calls to a per-mobtype handler. This allows us to
remove istype() spaghetti code, but requires the addition of other handler procs to simplify it.
Alternately, you could hardcode every mob's variation in a flat ClickOn() proc; however,
that's a lot of code duplication and is hard to maintain.
/**
* Before anything else, defer these calls to a per-mobtype handler. This allows us to
* remove istype() spaghetti code, but requires the addition of other handler procs to simplify it.
*
* Alternately, you could hardcode every mob's variation in a flat [/mob/proc/ClickOn] proc; however,
* that's a lot of code duplication and is hard to maintain.
*
* Note that this proc can be overridden, and is in the case of screen objects.
*/
/atom/Click(location, control, params)
if(flags_1 & INITIALIZED_1)
SEND_SIGNAL(src, COMSIG_CLICK, location, control, params, usr)
Note that this proc can be overridden, and is in the case of screen objects.
*/
//Aurora snowflake click handler system
var/datum/click_handler/click_handler = usr.GetClickHandler()
click_handler.OnClick(src, params)
/atom/Click(location,control,params)
var/datum/click_handler/click_handler = usr.GetClickHandler()
click_handler.OnClick(src, params)
/atom/DblClick(location,control,params)
if(flags_1 & INITIALIZED_1)
//Aurora snowflake click handler system
var/datum/click_handler/click_handler = usr.GetClickHandler()
click_handler.OnDblClick(src, params)
/atom/DblClick(var/location, var/control, var/params)
var/datum/click_handler/click_handler = usr.GetClickHandler()
click_handler.OnDblClick(src, params)
//Why god why
if(istype(usr.machine, /obj/machinery/computer/security))
var/obj/machinery/computer/security/console = usr.machine
console.jump_on_click(usr,src)
if(istype(usr.machine,/obj/machinery/computer/security))
var/obj/machinery/computer/security/console = usr.machine
console.jump_on_click(usr,src)
/atom/proc/allow_click_through(var/atom/A, var/params, var/mob/user)
return FALSE
/turf/allow_click_through(var/atom/A, var/params, var/mob/user)
return TRUE
/atom/proc/RelayMouseDrag(src_object, over_object, src_location, over_location, src_control, over_control, params, var/mob/user)
return FALSE
/mob/proc/OnMouseDrag(src_object, over_object, src_location, over_location, src_control, over_control, params)
if(istype(loc, /atom))
var/atom/A = loc
if(A.RelayMouseDrag(src_object, over_object, src_location, over_location, src_control, over_control, params, src))
return
if(over_object)
if(!incapacitated())
var/obj/item/gun/gun = get_active_hand()
if(istype(gun))
set_dir(get_dir(src, over_object))
gun.Fire(get_turf(over_object), src, params, (get_dist(over_object, src) <= 1), FALSE)
/atom/MouseWheel(delta_x,delta_y,location,control,params)
if(flags_1 & INITIALIZED_1)
usr.MouseWheelOn(src, delta_x, delta_y, params)
/**
* Standard mob ClickOn()
@@ -63,13 +52,18 @@
* * [obj/item/proc/afterattack] (atom,user,adjacent,params) - used both ranged and adjacent
* * [mob/proc/RangedAttack] (atom,modifiers) - used only ranged, only used for tk and laser eyes but could be changed
*/
/mob/proc/ClickOn(var/atom/A, var/params)
/mob/proc/ClickOn(atom/A, params)
if(world.time <= next_click) // Hard check, before anything else, to avoid crashing
return
next_click = world.time + 1
var/list/modifiers = params2list(params)
if(SEND_SIGNAL(src, COMSIG_MOB_CLICKON, A, modifiers) & COMSIG_MOB_CANCEL_CLICKON)
return
/* START Aurora snowflake */
if(istype(loc, /mob/living/heavy_vehicle) && !(A in src.contents))
var/mob/living/heavy_vehicle/M = loc
return M.ClickOn(A, params, src)
@@ -82,34 +76,44 @@
return
return B.ClickOn(A, params)
var/list/modifiers = params2list(params)
if(modifiers["right"])
RightClickOn(A)
return TRUE
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return TRUE
if(modifiers["ctrl"] && modifiers["middle"])
pointed(A)
return TRUE
if(modifiers["middle"])
MiddleClickOn(A)
return TRUE
if(modifiers["shift"])
ShiftClickOn(A)
return FALSE
if(modifiers["alt"]) // alt and alt-gr (rightalt)
AltClickOn(A)
return
if(modifiers["ctrl"])
CtrlClickOn(A)
return TRUE
/* END Aurora snowflake */
if(stat || paralysis || stunned || weakened)
if(LAZYACCESS(modifiers, SHIFT_CLICK))
if(LAZYACCESS(modifiers, MIDDLE_CLICK))
ShiftMiddleClickOn(A)
return
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlShiftClickOn(A)
return
ShiftClickOn(A)
return
if(LAZYACCESS(modifiers, MIDDLE_CLICK))
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlMiddleClickOn(A)
else
MiddleClickOn(A, params)
return
if(LAZYACCESS(modifiers, ALT_CLICK)) // alt and alt-gr (rightalt)
if(LAZYACCESS(modifiers, RIGHT_CLICK))
AltClickSecondaryOn(A)
else
AltClickOn(A)
return
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlClickOn(A)
return
if(stat || paralysis || stunned || weakened) // In TG it's if(INCAPACITATED_IGNORING(src, INCAPABLE_RESTRAINTS|INCAPABLE_STASIS))
return
face_atom(A) // change direction to face what you clicked on
/* START Aurora snowflake */
if(LAZYACCESS(modifiers, RIGHT_CLICK))
RightClickOn(A)
return TRUE
/* END Aurora snowflake */
if(!canClick()) // in the year 2000...
return
@@ -125,14 +129,30 @@
var/obj/item/W = get_active_hand()
if(W == A) // Handle attack_self
W.attack_self(src)
trigger_aiming(TARGET_CAN_CLICK)
if(hand)
update_inv_l_hand(0)
if(W == A)
if(LAZYACCESS(modifiers, RIGHT_CLICK))
W.attack_self_secondary(src, modifiers)
/* START Aurora snowflake */
trigger_aiming(TARGET_CAN_CLICK)
if(hand)
update_inv_l_hand(FALSE)
else
update_inv_r_hand(FALSE)
/* END Aurora snowflake */
return
else
update_inv_r_hand(0)
return 1
W.attack_self(src, modifiers)
/* START Aurora snowflake */
trigger_aiming(TARGET_CAN_CLICK)
if(hand)
update_inv_l_hand(FALSE)
else
update_inv_r_hand(FALSE)
/* END Aurora snowflake */
return
/* START AURORA SNOWFLAKE CODE */
//Atoms on your person
// A is your location but is not a turf; or is on you (backpack); or is on something on you (box in backpack); sdepth is needed here because contents depth does not equate inventory storage depth.
@@ -149,7 +169,7 @@
else
if(ismob(A)) // No instant mob attacking
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
UnarmedAttack(A, 1)
UnarmedAttack(A, TRUE, modifiers)
trigger_aiming(TARGET_CAN_CLICK)
return 1
@@ -170,7 +190,7 @@
else
if(ismob(A)) // No instant mob attacking
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
UnarmedAttack(A, 1)
UnarmedAttack(A, TRUE, modifiers)
trigger_aiming(TARGET_CAN_CLICK)
return
@@ -183,6 +203,8 @@
trigger_aiming(TARGET_CAN_CLICK)
return 1
/* END AURORA SNOWFLAKE CODE */
/mob/proc/setClickCooldown(var/timeout)
next_move = max(world.time + timeout, next_move)
@@ -191,21 +213,28 @@
return 1
return 0
// Default behavior: ignore double clicks, the second click that makes the doubleclick call already calls for a normal click
/mob/proc/DblClickOn(var/atom/A, var/params)
/// Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click)
/mob/proc/DblClickOn(atom/A, params)
return
/*
Translates into attack_hand, etc.
/**
* UnarmedAttack: The higest level of mob click chain discounting click itself.
*
* This handles, just "clicking on something" without an item. It translates
* into [atom/proc/attack_hand], [atom/proc/attack_animal] etc.
*
* Note: proximity_flag here is used to distinguish between normal usage (flag=1),
* and usage when clicking on things telekinetically (flag=0). This proc will
* not be called at ranged except with telekinesis.
*
* proximity_flag is not currently passed to attack_hand, and is instead used
* in human click code to allow glove touches only at melee range.
*
* modifiers is a lazy list of click modifiers this attack had,
* used for figuring out different properties of the click, mostly right vs left and such.
*/
Note: proximity_flag here is used to distinguish between normal usage (flag=1),
and usage when clicking on things telekinetically (flag=0). This proc will
not be called at ranged except with telekinesis.
proximity_flag is not currently passed to attack_hand, and is instead used
in human click code to allow glove touches only at melee range.
*/
/mob/proc/UnarmedAttack(var/atom/A, var/proximity_flag)
/mob/proc/UnarmedAttack(atom/A, proximity_flag, list/modifiers)
return
/mob/living/UnarmedAttack(var/atom/A, var/proximity_flag)
@@ -229,13 +258,14 @@
* for things like ranged glove touches, spitting alien acid/neurotoxin,
* animals lunging, etc.
*/
/mob/proc/RangedAttack(atom/A, params)
SHOULD_NOT_SLEEP(TRUE)
/mob/proc/RangedAttack(atom/A, modifiers)
if(SEND_SIGNAL(src, COMSIG_MOB_ATTACK_RANGED, A, modifiers) & COMPONENT_CANCEL_ATTACK_CHAIN)
return TRUE
if((mutations & LASER_EYES) && a_intent == I_HURT)
LaserEyes(A, params) // moved into a proc below
LaserEyes(A, modifiers) // moved into a proc below
return
A.attack_ranged(src, params)
A.attack_ranged(src, modifiers)
/*
Restrained ClickOn
@@ -246,53 +276,44 @@
/mob/proc/RestrainedClickOn(var/atom/A)
return
/*
Middle click
*/
/mob/proc/MiddleClickOn(var/atom/A)
/**
* Middle click
* Mainly used for swapping hands
*/
/mob/proc/MiddleClickOn(atom/A, params)
. = SEND_SIGNAL(src, COMSIG_MOB_MIDDLECLICKON, A, params)
if(. & COMSIG_MOB_CANCEL_CLICKON)
return
if(A.handle_middle_mouse_click(src))
return
swap_hand()
/mob/living/carbon/human/MiddleClickOn(var/atom/A)
/mob/living/carbon/human/MiddleClickOn(atom/A, params)
if(species.handle_middle_mouse_click(src, A))
return
return ..()
// In case of use break glass
/*
/atom/proc/MiddleClick(var/mob/M as mob)
return
*/
/*
Shift click
For most mobs, examine.
This is overridden in ai.dm
*/
/mob/proc/ShiftClickOn(var/atom/A)
/**
* Shift click
* For most mobs, examine.
* This is overridden in ai.dm
*/
/mob/proc/ShiftClickOn(atom/A)
A.ShiftClick(src)
return
/atom/proc/ShiftClick(var/mob/user)
if(user.can_examine())
/atom/proc/ShiftClick(mob/user)
SEND_SIGNAL(src, COMSIG_SHIFT_CLICKED_ON, user)
var/flags = SEND_SIGNAL(user, COMSIG_CLICK_SHIFT, src)
if(flags & COMSIG_MOB_CANCEL_CLICKON)
return
if(user.can_examine() || flags & COMPONENT_ALLOW_EXAMINATE)
examinate(user, src)
/*
Ctrl click
For most objects, pull
*/
/mob/proc/CtrlClickOn(var/atom/A)
A.CtrlClick(src)
/mob/proc/ShiftMiddleClickOn(atom/A)
src.pointed(A)
return
/atom/proc/CtrlClick(var/mob/user)
return
/atom/movable/CtrlClick(var/mob/user)
if(Adjacent(user))
user.start_pulling(src)
/*
Alt click
Unused except for AI
@@ -317,16 +338,40 @@
/atom/proc/RightClick(mob/user)
return
/*
Control+Shift click
Unused except for AI
*/
/mob/proc/CtrlShiftClickOn(var/atom/A)
A.CtrlShiftClick(src)
return
///Main proc for secondary alt click
/mob/proc/AltClickSecondaryOn(atom/target)
base_click_alt_secondary(target)
/atom/proc/CtrlShiftClick(var/mob/user)
return
/**
* ### Base proc for alt click interaction right click.
*
* If you wish to add custom `click_alt_secondary` behavior for a single type, use that proc.
*/
/mob/proc/base_click_alt_secondary(atom/target)
SHOULD_NOT_OVERRIDE(TRUE)
//Hook on the mob to intercept the click
if(SEND_SIGNAL(src, COMSIG_MOB_ALTCLICKON_SECONDARY, target) & COMSIG_MOB_CANCEL_CLICKON)
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 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
* Override this to change default alt right click behavior.
*
* ### Guard clauses
* Consider adding `interaction_flags_click` before adding unique guard clauses.
**/
/atom/proc/click_alt_secondary(mob/user)
SHOULD_CALL_PARENT(FALSE)
return NONE
/*
Misc helpers
@@ -399,15 +444,20 @@ var/global/list/click_catchers
/atom/movable/screen/click_catcher/Click(location, control, params)
var/list/modifiers = params2list(params)
if(modifiers["middle"] && istype(usr, /mob/living/carbon))
if(LAZYACCESS(modifiers, MIDDLE_CLICK) && iscarbon(usr))
var/mob/living/carbon/C = usr
C.swap_hand()
else
var/turf/T = screen_loc2turf(screen_loc, get_turf(usr))
if(T)
T.Click(location, control, params)
var/turf/click_turf = parse_caught_click_modifiers(modifiers, get_turf(usr.client ? usr.client.eye : usr), usr.client)
if (click_turf)
modifiers["catcher"] = TRUE
click_turf.Click(click_turf, control, list2params(modifiers))
. = 1
/// MouseWheelOn
/mob/proc/MouseWheelOn(atom/A, delta_x, delta_y, params)
SEND_SIGNAL(src, COMSIG_MOUSE_SCROLL_ON, A, delta_x, delta_y, params)
// Suppress the mouse macros
/client/var/has_mouse_macro_warning
/mob/proc/LogMouseMacro(verbused, params)
@@ -427,95 +477,3 @@ var/global/list/click_catchers
set hidden = 1
set name = ".mouse"
LogMouseMacro(".mouse", params)
/*
Custom Click Handlinig
*/
/mob
var/datum/stack/click_handlers
var/const/CLICK_HANDLER_NONE = 0
var/const/CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT = 1
var/const/CLICK_HANDLER_ALL = (~0)
/datum/click_handler
var/mob/user
var/handler_flags = CLICK_HANDLER_NONE
/datum/click_handler/New(mob/user)
..()
src.user = user
if(handler_flags & CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT)
RegisterSignal(user, COMSIG_MOB_LOGOUT, /datum/click_handler/proc/OnMobLogout, TRUE)
/datum/click_handler/Destroy()
if(handler_flags & CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT)
UnregisterSignal(user, COMSIG_MOB_LOGOUT)
user = null
. = ..()
/datum/click_handler/proc/Enter()
return
/datum/click_handler/proc/Exit()
return
/datum/click_handler/proc/OnMobLogout()
user.RemoveClickHandler(src)
/datum/click_handler/proc/OnClick(var/atom/A, var/params)
return
/datum/click_handler/proc/OnDblClick(var/atom/A, var/params)
return
/datum/click_handler/default/OnClick(var/atom/A, var/params)
user.ClickOn(A, params)
/datum/click_handler/default/OnDblClick(var/atom/A, var/params)
user.DblClickOn(A, params)
/mob/proc/GetClickHandler(var/datum/click_handler/popped_handler)
if(!click_handlers)
click_handlers = new()
if(click_handlers.is_empty())
PushClickHandler(/datum/click_handler/default)
return click_handlers.Top()
/mob/proc/RemoveClickHandler(var/datum/click_handler/click_handler)
if(!click_handlers)
return
var/was_top = click_handlers.Top() == click_handler
if(was_top)
click_handler.Exit()
click_handlers.Remove(click_handler)
qdel(click_handler)
if(!was_top)
return
click_handler = click_handlers.Top()
if(click_handler)
click_handler.Enter()
/mob/proc/PopClickHandler()
if(!click_handlers)
return
RemoveClickHandler(click_handlers.Top())
/mob/proc/PushClickHandler(var/datum/click_handler/new_click_handler_type)
if((initial(new_click_handler_type.handler_flags) & CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT) && !client)
return FALSE
if(!click_handlers)
click_handlers = new()
var/datum/click_handler/click_handler = click_handlers.Top()
if(click_handler)
click_handler.Exit()
click_handler = new new_click_handler_type(src)
click_handler.Enter()
click_handlers.Push(click_handler)
+29
View File
@@ -0,0 +1,29 @@
/**
* Ctrl click
*/
/mob/proc/CtrlClickOn(atom/A)
A.CtrlClick(src)
/mob/proc/CtrlShiftClickOn(var/atom/A)
A.CtrlShiftClick(src)
return
/atom/proc/CtrlShiftClick(var/mob/user)
return
/atom/proc/CtrlClick(var/mob/user)
return
/atom/movable/CtrlClick(var/mob/user)
if(Adjacent(user))
user.start_pulling(src)
/**
* Ctrl mouse wheel click
* Except for tagging datumns same as control click (<-- not implemented in Aurora yet)
*/
/mob/proc/CtrlMiddleClickOn(atom/A)
// if(check_rights_for(client, R_ADMIN))
// client.toggle_tag_datum(A)
// return
CtrlClickOn(A)
+226
View File
@@ -0,0 +1,226 @@
/*
Custom click handling
All of this shit should be made redundant by signals and burned to the ground at some point, in the meantime I have updated it
*/
/// Populates `click_handlers` with the default handler if not already defined.
#define SETUP_CLICK_HANDLERS \
if(!click_handlers) { \
click_handlers = new(); \
click_handlers += new/datum/click_handler/default(src) \
}
/**
* LAZYLIST (Instances of `/datum/click_handler`). Click handlers for this mob that should intercept and handle click
* calls.
*
* The 'topmost'/'active' click handler for the mob is the handler currently at index `1`. By default, this will be
* `/datum/click_handler/default`.
*/
/mob/var/list/click_handlers
// In the mob code, because otherwise it's a redefinition
// /mob/Destroy()
// QDEL_LIST(click_handlers)
// return ..()
/// Removes this click handler on `/mob/Logout()`.
var/global/const/CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT = FLAG(0)
/// Removes and prevents creation of the click handler if it is not the active handler for the mob.
var/global/const/CLICK_HANDLER_REMOVE_IF_NOT_TOP = FLAG(1)
/datum/click_handler
/// The mob this click handler is attached to.
var/mob/user
/**
* Bitfield (Any of `CLICK_HANDLER_*`). Relevant flags to control the logic flow of this click handler.
*
* See `code\_onclick\click_handling.dm` for valid options.
*/
var/flags = EMPTY_BITFIELD
/datum/click_handler/New(mob/user)
..()
src.user = user
if (flags & CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT)
RegisterSignal(user, COMSIG_MOB_LOGOUT, PROC_REF(OnMobLogout))
/datum/click_handler/Destroy()
if (flags & CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT)
UnregisterSignal(user, COMSIG_MOB_LOGOUT)
user = null
. = ..()
/**
* Called when the click handler becomes the active entry in the mob's click handlers list. Called by
* `PushClickHandler()` and `RemoveClickHandler()`.
*
* Has no return value.
*/
/datum/click_handler/proc/Enter()
return
/**
* Called when the click handler was active in the mob's click handler list and has been replaced by another handler or
* otherwise removed. Called by `PushClickHandler()` and `RemoveClickHandler()`.
*
* Has no return value.
*/
/datum/click_handler/proc/Exit()
return
/**
* Event proc for `logged_out_event`. Called when the mob logs out and this click handler has the
* `CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT` flag set.
*
* By default, this removes the click handler from the assigned mob.
*
* Has no return value.
*/
/datum/click_handler/proc/OnMobLogout()
user.RemoveClickHandler(src)
/**
* Called on click by `/atom/Click()` when this is the mob's currently active click handler.
*
* **Parameters**:
* - `A` - The atom clicked on.
* - `params` (list of strings) - List of click parameters. See BYOND's `CLick()` documentation.
*
* Has no return value.
*/
/datum/click_handler/proc/OnClick(atom/A, params)
return
/**
* Called on doubleclick by `/atom/DblClick()` when this is the mob's currently active click handler.
*
* **Parameters**:
* - `A` - The atom double clicked on.
* - `params` (list of strings) - List of click parameters. See BYOND's `CLick()` documentation.
*
* Has no return value.
*/
/datum/click_handler/proc/OnDblClick(atom/A, params)
return
/**
* Called on MouseDown by `/client/MouseDown()` when this is the mob's currently active click handler.
*
* **Parameters**:
* - `object` - The atom mouse is underneath.
* - `location` - the turf, stat panel, grid cell, etc. containing the object where it was clicked
* - `params` (list of strings) - List of click parameters. See BYOND's `CLick()` documentation.
*
* Has no return value.
*/
// /datum/click_handler/proc/OnMouseDown(object, location, params) //NOT IMPLEMENTED
// return
/**
* Called on MouseUp by `/client/MouseUp()` when this is the mob's currently active click handler.
*
* **Parameters**:
* - `object` - The atom underneath mouse.
* - `location` - the turf, stat panel, grid cell, etc. containing the object where it was clicked
* - `params` (list of strings) - List of click parameters. See BYOND's `CLick()` documentation.
*
* Has no return value.
*/
// /datum/click_handler/proc/OnMouseUp(object, location, params) //NOT IMPLEMENTED
// return
/datum/click_handler/default/OnClick(atom/A, params)
user.ClickOn(A, params)
/datum/click_handler/default/OnDblClick(atom/A, params)
user.DblClickOn(A, params)
/**
* Returns the mob's currently active click handler.
*
* **Parameters**:
* - `popped_handler`. Not used, should probably be removed?
*/
/mob/proc/GetClickHandler(datum/click_handler/popped_handler)
SETUP_CLICK_HANDLERS
return click_handlers[1]
/**
* Removes the given click handler from `click_handlers`.
*
* This will not remove the protected default handler.
*
* **Parameters**:
* - `click_handler` (Path or instance of `/datum/click_handler`) - The handler to remove. If a path, finds the first
* matching instance of that type.
*
* Returns boolean. Whether or not the click handler was found and removed.
*/
/mob/proc/RemoveClickHandler(datum/click_handler/click_handler)
if(!click_handlers)
return FALSE
if(ispath(click_handler)) // If we were given a path instead of an instance, find the first matching instance by type
// No removing of the default click handler
if(click_handler == /datum/click_handler/default)
return FALSE
click_handler = get_instance_of_strict_type(click_handlers, click_handler)
if(!click_handler)
return FALSE
. = (click_handler in click_handlers)
if(!.)
return
var/was_top = click_handlers[1] == click_handler
if(was_top)
click_handler.Exit()
click_handlers.Remove(click_handler)
qdel(click_handler)
if(!was_top)
return
click_handler = click_handlers[1]
if(click_handler)
click_handler.Enter()
/**
* Pushes the given click handler to the top of the `click_handlers` list, making it the active handler.
*
* **Parameters**:
* - `new_click_handler_type` (Type path - Type of `/datum/click_handler`). The click handler to make active.
*
* Returns boolean. If `TRUE`, the click handler was successfully pushed to the top. Returns `FALSE` if the handler was
* already active.
*/
/mob/proc/PushClickHandler(datum/click_handler/new_click_handler_type)
// No manipulation of the default click handler
if(new_click_handler_type == /datum/click_handler/default)
return FALSE
if ((initial(new_click_handler_type.flags) & CLICK_HANDLER_REMOVE_ON_MOB_LOGOUT) && !client)
return FALSE
SETUP_CLICK_HANDLERS
var/datum/click_handler/click_handler = click_handlers[1]
if(click_handler.type == new_click_handler_type)
return FALSE // If the top click handler is already the same as the desired one, bow out
click_handler.Exit()
if (click_handler.flags & CLICK_HANDLER_REMOVE_IF_NOT_TOP)
click_handlers.Remove(click_handler)
qdel(click_handler)
click_handler = get_instance_of_strict_type(click_handlers, click_handler)
if(click_handler)
click_handlers.Remove(click_handler)
else
click_handler = new new_click_handler_type(src)
click_handlers.Insert(1, click_handler) // Insert new handlers first
click_handler.Enter()
return TRUE
#undef SETUP_CLICK_HANDLERS
+2 -2
View File
@@ -6,7 +6,7 @@
adjacency code.
*/
/mob/living/silicon/robot/ClickOn(var/atom/A, var/params)
/mob/living/silicon/robot/ClickOn(atom/A, params)
if(world.time <= next_click)
return
next_click = world.time + 1
@@ -16,7 +16,7 @@
CtrlShiftClickOn(A)
return
if(modifiers["middle"])
MiddleClickOn(A)
MiddleClickOn(A, params)
return
if(modifiers["shift"])
ShiftClickOn(A)
+8 -1
View File
@@ -14,9 +14,16 @@ avoid code duplication. This includes items that may sometimes act as a standard
*/
// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
/obj/item/proc/attack_self(mob/user)
/obj/item/proc/attack_self(mob/user, modifiers)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF, user) & COMPONENT_CANCEL_ATTACK_CHAIN)
return TRUE
return
/// Called when the item is in the active hand, and right-clicked. Intended for alternate or opposite functions, such as lowering reagent transfer amount. At the moment, there is no verb or hotkey.
/obj/item/proc/attack_self_secondary(mob/user, modifiers)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF_SECONDARY, user) & COMPONENT_CANCEL_ATTACK_CHAIN)
return TRUE
// Called at the start of resolve_attackby(), before the actual attack.
/obj/item/proc/pre_attack(atom/a, mob/user)
return