diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm
index fa915e6e58f..bca000eac81 100644
--- a/code/_onclick/hud/action_button.dm
+++ b/code/_onclick/hud/action_button.dm
@@ -1,8 +1,10 @@
/obj/screen/movable/action_button
+ desc = "CTRL-Shift click on this button to bind it to a hotkey."
var/datum/action/linked_action
var/actiontooltipstyle = ""
screen_loc = null
var/ordered = TRUE
+ var/datum/keybinding/mob/trigger_action_button/linked_keybind
/obj/screen/movable/action_button/MouseDrop(over_object)
if(locked && could_be_click_lag()) // in case something bad happend and game realised we dragged our ability instead of pressing it
@@ -32,6 +34,9 @@
/obj/screen/movable/action_button/Click(location,control,params)
var/list/modifiers = params2list(params)
+ if(modifiers["ctrl"] && modifiers["shift"])
+ INVOKE_ASYNC(src, PROC_REF(set_to_keybind), usr)
+ return TRUE
if(usr.next_click > world.time)
return FALSE
usr.changeNext_click(1)
@@ -58,9 +63,32 @@
animate(src, transform = matrix(), time = 0.4 SECONDS, alpha = 255)
return TRUE
+/obj/screen/movable/action_button/proc/set_to_keybind(mob/user)
+ var/keybind_to_set_to = uppertext(input(user, "What keybind do you want to set this action button to?") as text)
+ if(keybind_to_set_to)
+ if(linked_keybind)
+ clean_up_keybinds(user)
+ var/datum/keybinding/mob/trigger_action_button/triggerer = new
+ triggerer.linked_action = linked_action
+ user.client.active_keybindings[keybind_to_set_to] += list(triggerer)
+ linked_keybind = triggerer
+ triggerer.binded_to = keybind_to_set_to
+ to_chat(user, "[src] has been binded to [keybind_to_set_to]!")
+ else if(linked_keybind)
+ clean_up_keybinds(user)
+ to_chat(user, "Your active keybinding on [src] has been cleared.")
+
/obj/screen/movable/action_button/AltClick(mob/user)
return linked_action.AltTrigger()
+/obj/screen/movable/action_button/proc/clean_up_keybinds(mob/owner)
+ if(linked_keybind)
+ owner.client.active_keybindings[linked_keybind.binded_to] -= (linked_keybind)
+ if(!length(owner.client.active_keybindings[linked_keybind.binded_to]))
+ owner.client.active_keybindings[linked_keybind.binded_to] = null
+ owner.client.active_keybindings -= linked_keybind.binded_to
+ QDEL_NULL(linked_keybind)
+
//Hide/Show Action Buttons ... Button
/obj/screen/movable/action_button/hide_toggle
name = "Hide Buttons"
@@ -121,7 +149,14 @@
/obj/screen/movable/action_button/MouseEntered(location, control, params)
. = ..()
if(!QDELETED(src))
- openToolTip(usr, src, params, title = name, content = desc, theme = actiontooltipstyle)
+ if(!linked_keybind)
+ openToolTip(usr, src, params, title = name, content = desc, theme = actiontooltipstyle)
+ else
+ var/list/desc_information = list()
+ desc_information += desc
+ desc_information += "This action is currently bound to the [linked_keybind.binded_to] key."
+ desc_information = desc_information.Join(" ")
+ openToolTip(usr, src, params, title = name, content = desc_information, theme = actiontooltipstyle)
/obj/screen/movable/action_button/MouseExited()
closeToolTip(usr)
diff --git a/code/datums/action.dm b/code/datums/action.dm
index 79173b4c4a8..0bdd5c4a0a3 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -26,8 +26,10 @@
button.linked_action = src
button.name = name
button.actiontooltipstyle = buttontooltipstyle
- if(desc)
- button.desc = desc
+ var/list/our_description = list()
+ our_description += desc
+ our_description += button.desc
+ button.desc = our_description.Join(" ")
/datum/action/Destroy()
if(owner)
@@ -55,6 +57,7 @@
return
if(M.client)
M.client.screen -= button
+ button.clean_up_keybinds(M)
button.moved = FALSE //so the button appears in its normal position when given to another owner.
button.locked = FALSE
M.actions -= src
@@ -110,7 +113,6 @@
else
button.icon = button_icon
button.icon_state = background_icon_state
- button.desc = desc
ApplyIcon(button)
var/obj/effect/proc_holder/spell/S = target
@@ -562,7 +564,10 @@
var/obj/effect/proc_holder/spell/S = target
S.action = src
name = S.name
- desc = S.desc
+ var/list/our_description = list()
+ our_description += S.desc
+ our_description += button.desc
+ button.desc = our_description.Join(" ")
button_icon = S.action_icon
button_icon_state = S.action_icon_state
background_icon_state = S.action_background_icon_state
diff --git a/code/datums/keybindings/mob_keybinds.dm b/code/datums/keybindings/mob_keybinds.dm
index c870739da56..c2f782dd024 100644
--- a/code/datums/keybindings/mob_keybinds.dm
+++ b/code/datums/keybindings/mob_keybinds.dm
@@ -224,3 +224,13 @@
/datum/keybinding/mob/target/l_foot
name = "Target Left Foot"
body_part = BODY_ZONE_PRECISE_L_FOOT
+
+/datum/keybinding/mob/trigger_action_button // Don't add a name to this, shouldn't show up in the prefs menu
+ var/datum/action/linked_action
+ var/binded_to // these are expected to actually get deleted at some point, to prevent hard deletes we need to know where to remove them from the clients list
+
+/datum/keybinding/mob/trigger_action_button/down(client/C)
+ . = ..()
+ if(C.mob.next_click > world.time)
+ return
+ linked_action.Trigger()
diff --git a/code/datums/spell.dm b/code/datums/spell.dm
index 4199efa023e..a40432406b3 100644
--- a/code/datums/spell.dm
+++ b/code/datums/spell.dm
@@ -17,7 +17,6 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
to_chat(user, "[user.ranged_ability.name] has been disabled.")
user.ranged_ability.remove_ranged_ability(user)
return TRUE //TRUE for failed, FALSE for passed.
- user.changeNext_click(CLICK_CD_CLICK_ABILITY)
user.face_atom(A)
return FALSE
@@ -159,6 +158,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
if(!can_cast(user, charge_check, TRUE))
return FALSE
+ user.changeNext_click(CLICK_CD_CLICK_ABILITY)
if(ishuman(user))
var/mob/living/carbon/human/caster = user
if(caster.remoteview_target)
diff --git a/code/game/objects/items/weapons/storage/storage_base.dm b/code/game/objects/items/weapons/storage/storage_base.dm
index 4511e5b807e..c5de6b7bd3a 100644
--- a/code/game/objects/items/weapons/storage/storage_base.dm
+++ b/code/game/objects/items/weapons/storage/storage_base.dm
@@ -546,7 +546,6 @@
handle_item_insertion(I)
-
/obj/item/storage/attack_hand(mob/user)
if(ishuman(user))
var/mob/living/carbon/human/H = user
diff --git a/code/modules/input/keybindings_procs.dm b/code/modules/input/keybindings_procs.dm
index 1d231127996..8ae07693672 100644
--- a/code/modules/input/keybindings_procs.dm
+++ b/code/modules/input/keybindings_procs.dm
@@ -12,5 +12,11 @@
movement_kb_dirs[key] = KBM.move_dir
else
active_keybindings[key] += list(KB)
+ if(!mob) // Clients can join before world/new is setup, so we gotta mob check em
+ return active_keybindings
+ for(var/datum/action/action as anything in mob.actions)
+ if(action.button?.linked_keybind?.binded_to)
+ var/datum/keybinding/mob/trigger_action_button/linked_bind = action.button.linked_keybind
+ active_keybindings[linked_bind.binded_to] += list(linked_bind)
return active_keybindings
diff --git a/code/modules/mob/living/carbon/human/human_inventory.dm b/code/modules/mob/living/carbon/human/human_inventory.dm
index 8e482ef37df..d8bda565092 100644
--- a/code/modules/mob/living/carbon/human/human_inventory.dm
+++ b/code/modules/mob/living/carbon/human/human_inventory.dm
@@ -168,9 +168,6 @@
update_inv_l_hand()
update_action_buttons_icon()
-
-
-
//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
// Initial is used to indicate whether or not this is the initial equipment (job datums etc) or just a player doing it
/mob/living/carbon/human/equip_to_slot(obj/item/I, slot, initial = FALSE)