diff --git a/code/modules/keybindings/bindings_robot.dm b/code/modules/keybindings/bindings_robot.dm
index 073f0ccae84..f85264308a0 100644
--- a/code/modules/keybindings/bindings_robot.dm
+++ b/code/modules/keybindings/bindings_robot.dm
@@ -11,10 +11,8 @@
return
if("Q")
if(!(client.prefs.toggles & AZERTY))
- uneq_active()
- return
+ on_drop_hotkey_press() // User is in QWERTY hotkey mode.
if("A")
if(client.prefs.toggles & AZERTY)
- uneq_active()
- return
+ on_drop_hotkey_press()
return ..()
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
index d200bdb075a..7958f983805 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
@@ -30,29 +30,22 @@
/obj/item/circuitboard,
/obj/item/stack/tile/light,
/obj/item/stack/ore/bluespace_crystal
- )
+ )
//Item currently being held.
- var/obj/item/wrapped = null
-
-/obj/item/gripper/paperwork
- name = "paperwork gripper"
- desc = "A simple grasping tool for clerical work."
-
- can_hold = list(
- /obj/item/clipboard,
- /obj/item/paper,
- /obj/item/card/id
- )
+ var/obj/item/gripped_item = null
/obj/item/gripper/medical
name = "medical gripper"
desc = "A grasping tool used to help patients up once surgery is complete."
can_hold = list()
-/obj/item/gripper/medical/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
+/obj/item/gripper/medical/attack_self(mob/user)
+ return
+
+/obj/item/gripper/medical/afterattack(atom/target, mob/living/user, proximity, params)
var/mob/living/carbon/human/H
- if(!wrapped && proximity && target && ishuman(target))
+ if(!gripped_item && proximity && target && ishuman(target))
H = target
if(H.lying)
H.AdjustSleeping(-5)
@@ -71,98 +64,69 @@
..()
can_hold = typecacheof(can_hold)
-/obj/item/gripper/attack_self(mob/user as mob)
- if(wrapped)
- wrapped.attack_self(user)
-
/obj/item/gripper/verb/drop_item()
-
set name = "Drop Gripped Item"
set desc = "Release an item from your magnetic gripper."
set category = "Drone"
- drop_item_p()
+ drop_gripped_item()
-// The "p" stands for proc, since I was having annoying weird stuff happening with this in the verb
-// when trying to have default values for arguments and stuff
-/obj/item/gripper/proc/drop_item_p(var/silent = 0)
+/obj/item/gripper/attack_self(mob/user)
+ if(gripped_item)
+ gripped_item.attack_self(user)
+ else
+ to_chat(user, "[src] is empty.")
- if(!wrapped)
- //There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z
- for(var/obj/item/thing in src.contents)
- thing.forceMove(get_turf(src))
- return
+/obj/item/gripper/proc/drop_gripped_item(silent = FALSE)
+ if(gripped_item)
+ if(!silent)
+ to_chat(loc, "You drop [gripped_item].")
+ gripped_item.forceMove(get_turf(src))
+ gripped_item = null
- if(wrapped.loc != src)
- wrapped = null
- return
-
- if(!silent)
- to_chat(src.loc, "You drop \the [wrapped].")
- wrapped.forceMove(get_turf(src))
- wrapped = null
-
-/obj/item/gripper/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
+/obj/item/gripper/attack(mob/living/carbon/M, mob/living/carbon/user)
return
-/obj/item/gripper/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
+/// Grippers are snowflakey so this is needed to to prevent forceMoving grippers after `if(!user.drop_item())` checks done in certain attackby's.
+/obj/item/gripper/forceMove(atom/destination)
+ return
+
+/obj/item/gripper/afterattack(atom/target, mob/living/user, proximity, params)
if(!target || !proximity) //Target is invalid or we are not adjacent.
- return
+ return FALSE
- //There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z
- if(!wrapped)
- for(var/obj/item/thing in src.contents)
- wrapped = thing
- break
+ if(gripped_item) //Already have an item.
- if(wrapped) //Already have an item.
-
- //Temporary put wrapped into user so target's attackby() checks pass.
- wrapped.forceMove(user)
-
- //Pass the attack on to the target. This might delete/relocate wrapped.
- if(!target.attackby(wrapped, user, params) && target && wrapped)
- // If the attackby didn't resolve or delete the target or wrapped, afterattack
+ //Pass the attack on to the target. This might delete/relocate gripped_item.
+ if(!target.attackby(gripped_item, user, params))
+ // If the attackby didn't resolve or delete the target or gripped_item, afterattack
// (Certain things, such as mountable frames, rely on afterattack)
- wrapped.afterattack(target, user, 1, params)
+ gripped_item?.afterattack(target, user, 1, params)
- //If wrapped did neither get deleted nor put into target, put it back into the gripper.
- if(wrapped && user && (wrapped.loc == user))
- wrapped.forceMove(src)
- else
- wrapped = null
- return
-
- else if(istype(target,/obj/item)) //Check that we're not pocketing a mob.
-
- //...and that the item is not in a container.
- if(!isturf(target.loc))
- return
+ //If gripped_item either didn't get deleted, or it failed to be transfered to its target
+ if(!gripped_item && contents.len)
+ gripped_item = contents[1]
+ return FALSE
+ else if(gripped_item && !contents.len)
+ gripped_item = null
+ else if(istype(target, /obj/item)) //Check that we're not pocketing a mob.
var/obj/item/I = target
-
- //Check if the item is blacklisted.
- var/grab = 0
- if(can_hold.len)
- if(is_type_in_typecache(I, can_hold))
- grab = 1
-
- //We can grab the item, finally.
- if(grab)
- to_chat(user, "You collect \the [I].")
+ if(is_type_in_typecache(I, can_hold)) // Make sure the item is something the gripper can hold
+ to_chat(user, "You collect [I].")
I.forceMove(src)
- wrapped = I
- return
+ gripped_item = I
else
- to_chat(user, "Your gripper cannot hold \the [target].")
+ to_chat(user, "Your gripper cannot hold [target].")
+ return FALSE
else if(istype(target,/obj/machinery/power/apc))
var/obj/machinery/power/apc/A = target
if(A.opened)
if(A.cell)
- wrapped = A.cell
+ gripped_item = A.cell
A.cell.add_fingerprint(user)
A.cell.update_icon()
@@ -173,6 +137,7 @@
A.update_icon()
user.visible_message("[user] removes the power cell from [A]!", "You remove the power cell.")
+ return TRUE
//TODO: Matter decompiler.
/obj/item/matter_decompiler
diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm
index 16d9080ef7e..a68da651ee9 100644
--- a/code/modules/mob/living/silicon/robot/inventory.dm
+++ b/code/modules/mob/living/silicon/robot/inventory.dm
@@ -115,11 +115,11 @@
return 0
/mob/living/silicon/robot/drop_item()
- var/obj/item/I = get_active_hand()
- if(istype(I, /obj/item/gripper))
- var/obj/item/gripper/G = I
- G.drop_item_p(silent = 1)
- return
+ var/obj/item/gripper/G = get_active_hand()
+ if(istype(G))
+ G.drop_gripped_item(silent = TRUE)
+ return TRUE // The gripper is special because it has a normal item inside that we can drop.
+ return FALSE // All robot inventory items have NODROP, so they should return FALSE.
//Helper procs for cyborg modules on the UI.
//These are hackish but they help clean up code elsewhere.
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index a8bad5ebc03..270ee325bf9 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -1472,3 +1472,12 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
+
+/// Used in `robot_bindings.dm` when the user presses "A" if on AZERTY mode, or "Q" on QWERTY mode.
+/mob/living/silicon/robot/proc/on_drop_hotkey_press()
+ var/obj/item/gripper/G = get_active_hand()
+ if(istype(G) && G.gripped_item)
+ G.drop_gripped_item() // if the active module is a gripper, try to drop its held item.
+ else
+ uneq_active() // else unequip the module and put it back into the robot's inventory.
+ return
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 47dcb93cef5..3260775c674 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -230,7 +230,7 @@
/obj/item/robot_module/engineering/handle_death()
var/obj/item/gripper/G = locate(/obj/item/gripper) in modules
if(G)
- G.drop_item()
+ G.drop_gripped_item(silent = TRUE)
/obj/item/robot_module/security
name = "security robot module"
@@ -578,7 +578,7 @@
/obj/item/robot_module/drone/handle_death()
var/obj/item/gripper/G = locate(/obj/item/gripper) in modules
if(G)
- G.drop_item()
+ G.drop_gripped_item(silent = TRUE)
//checks whether this item is a module of the robot it is located in.
/obj/item/proc/is_robot_module()