diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 36b6d647b7d..8467c6dcb75 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -60,7 +60,7 @@ * item/afterattack(atom,user,adjacent,params) - used both ranged and adjacent * mob/RangedAttack(atom,params) - 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(client.click_intercept) client.click_intercept.InterceptClickOn(src, params, A) return @@ -242,19 +242,13 @@ return // See click_override.dm -/mob/living/MiddleClickOn(var/atom/A) - if(src.middleClickOverride) - middleClickOverride.onClick(A, src) - else - ..() - -/mob/living/carbon/MiddleClickOn(var/atom/A) - if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src)) - changeNext_click(5) - mind.changeling.chosen_sting.try_to_sting(src, A) +/mob/living/MiddleClickOn(atom/A) + if(middleClickOverride) + middleClickOverride.onClick(A, src) else ..() + /* Middle shift-click Makes the mob face the direction of the clicked thing @@ -331,16 +325,9 @@ return // See click_override.dm -/mob/living/AltClickOn(var/atom/A) - if(src.middleClickOverride) - middleClickOverride.onClick(A, src) - else - ..() - -/mob/living/carbon/AltClickOn(var/atom/A) - if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src)) - changeNext_click(5) - mind.changeling.chosen_sting.try_to_sting(src, A) +/mob/living/AltClickOn(atom/A) + if(middleClickOverride) + middleClickOverride.onClick(A, src) else ..() diff --git a/code/_onclick/click_override.dm b/code/_onclick/click_override.dm index 481d30da4b6..fc1d09628e8 100644 --- a/code/_onclick/click_override.dm +++ b/code/_onclick/click_override.dm @@ -90,3 +90,19 @@ next_shocked.Cut() P.last_shocked = world.time + +/** + * # Callback invoker middle click override datum + * + * Middle click override which accepts a callback as an arugment in the `New()` proc. + * When the living mob that has this datum middle-clicks or alt-clicks on something, the callback will be invoked. + */ +/datum/middleClickOverride/callback_invoker + var/datum/callback/callback + +/datum/middleClickOverride/callback_invoker/New(datum/callback/_callback) + . = ..() + callback = _callback + +/datum/middleClickOverride/callback_invoker/onClick(atom/A, mob/living/user) + callback.Invoke(user, A) diff --git a/code/datums/click_intercept.dm b/code/datums/click_intercept.dm index 7eed1bb479b..163938d2f7f 100644 --- a/code/datums/click_intercept.dm +++ b/code/datums/click_intercept.dm @@ -1,10 +1,22 @@ +/** + * # Click intercept datum + * + * Datum which is intended to be stored by a client's `click_intercept` variable. + * Used to override normal clicking behavior when clicking on an object. + * While active, a mob's `ClickOn` proc will redirect to the `InterceptClickOn()` proc instead. + */ /datum/click_intercept + /// A reference to the client which is assigned this click intercept datum. var/client/holder = null + /// Any `obj/screen/buttons` the client is meant to receive when assigned this click intercept datum. var/list/obj/screen/buttons = list() /datum/click_intercept/New(client/C) create_buttons() - enter(C) + holder = C + holder.click_intercept = src + holder.show_popup_menus = FALSE + holder.screen += buttons return ..() /datum/click_intercept/Destroy() @@ -15,17 +27,27 @@ QDEL_LIST(buttons) return ..() -/datum/click_intercept/proc/enter(client/C) - holder = C - holder.click_intercept = src - holder.show_popup_menus = FALSE - holder.screen += buttons - +/** + * Called when you want to cancel a client's click intercept and return to normal clicking. + */ /datum/click_intercept/proc/quit() qdel(src) +/** + * Base proc, intended to be overriden. Code that adds datum specific buttons to the list of `buttons`, should go here. + */ /datum/click_intercept/proc/create_buttons() return -/datum/click_intercept/proc/InterceptClickOn(user,params,atom/object) +/** + * Called in various mob's `ClickOn` procs, which happens when they click on an object in the world. + * + * If the mob's `client.click_intercept` variable is set to something other than null, calls the `InterceptClickOn` proc for that click intercept datum. Aka, this proc. + * + * Arguments: + * * user - the mob which just clicked on something. + * * params - the `params` arguemnt passed from the `ClickOn` proc. + * * object - the atom that was just clicked. + */ +/datum/click_intercept/proc/InterceptClickOn(mob/user, params, atom/object) return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index cc8b2dd5e97..43c82e681c7 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -939,6 +939,8 @@ special_role = null if(changeling) current.remove_changeling_powers() + qdel(current.middleClickOverride) // In case the old changeling has a targeted sting prepared (`datum/middleClickOverride`), delete it. + current.middleClickOverride = null qdel(changeling) changeling = null SSticker.mode.update_change_icons_removed(src) diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm index 69142049280..ae3345248bb 100644 --- a/code/game/gamemodes/changeling/changeling_power.dm +++ b/code/game/gamemodes/changeling/changeling_power.dm @@ -35,7 +35,8 @@ the same goes for Remove(). if you override Remove(), call parent or else your p return try_to_sting(user) -/datum/action/changeling/proc/try_to_sting(var/mob/user, var/mob/target) +/datum/action/changeling/proc/try_to_sting(mob/user, mob/target) + user.changeNext_click(5) if(!user.mind || !user.mind.changeling) return if(!can_sting(user, target)) diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm index 9bc9fc7b511..19a3050ab01 100644 --- a/code/game/gamemodes/changeling/powers/tiny_prick.dm +++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm @@ -2,6 +2,12 @@ name = "Tiny Prick" desc = "Stabby stabby" var/sting_icon = null + /// A middle click override used to intercept changeling stings performed on a target. + var/datum/middleClickOverride/callback_invoker/click_override + +/datum/action/changeling/sting/New(Target) + . = ..() + click_override = new /datum/middleClickOverride/callback_invoker(CALLBACK(src, .proc/try_to_sting)) /datum/action/changeling/sting/Trigger() var/mob/user = owner @@ -13,14 +19,16 @@ unset_sting(user) return -/datum/action/changeling/sting/proc/set_sting(var/mob/user) +/datum/action/changeling/sting/proc/set_sting(mob/living/user) to_chat(user, "We prepare our sting, use alt+click or middle mouse button on target to sting them.") + user.middleClickOverride = click_override user.mind.changeling.chosen_sting = src user.hud_used.lingstingdisplay.icon_state = sting_icon user.hud_used.lingstingdisplay.invisibility = 0 -/datum/action/changeling/sting/proc/unset_sting(var/mob/user) +/datum/action/changeling/sting/proc/unset_sting(mob/living/user) to_chat(user, "We retract our sting, we can't sting anyone for now.") + user.middleClickOverride = null user.mind.changeling.chosen_sting = null user.hud_used.lingstingdisplay.icon_state = null user.hud_used.lingstingdisplay.invisibility = 101