diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 4482da107d1..eee7858096c 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -75,11 +75,11 @@
#define TRANSITIONEDGE 7 //Distance from edge to move to another z-level
+//used by canUseTopic()
#define BE_CLOSE TRUE //in the case of a silicon, to select if they need to be next to the atom
#define NO_DEXTERITY TRUE //if other mobs (monkeys, aliens, etc) can use this // I had to change 20+ files because some non-dnd-playing fuckchumbis can't spell "dexterity"
-#define NO_TK TRUE
-#define FLOOR_OKAY TRUE // if you can use it while resting
-//used by canUseTopic()
+#define NO_TK TRUE // if you can't use it from a distance with telekinesis
+#define FLOOR_OKAY TRUE // if you can use it while resting
//singularity defines
#define STAGE_ONE 1
diff --git a/code/datums/components/rotation.dm b/code/datums/components/rotation.dm
index 958682966da..2756c187f57 100644
--- a/code/datums/components/rotation.dm
+++ b/code/datums/components/rotation.dm
@@ -133,7 +133,7 @@
after_rotation.Invoke(user,rotation_type)
/datum/component/simple_rotation/proc/default_can_user_rotate(mob/living/user, rotation_type)
- if(!istype(user) || !user.canUseTopic(parent, BE_CLOSE, NO_DEXTERITY))
+ if(!istype(user) || !user.canUseTopic(parent, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return FALSE
return TRUE
diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm
index 556847b2477..c1738f69cab 100644
--- a/code/game/machinery/computer/buildandrepair.dm
+++ b/code/game/machinery/computer/buildandrepair.dm
@@ -169,7 +169,7 @@
/obj/structure/frame/computer/AltClick(mob/user)
..()
- if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return
if(anchored)
diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm
index ba1a8ee4555..870d419de2e 100644
--- a/code/game/machinery/launch_pad.dm
+++ b/code/game/machinery/launch_pad.dm
@@ -243,9 +243,7 @@
/obj/machinery/launchpad/briefcase/MouseDrop(over_object, src_location, over_location)
. = ..()
if(over_object == usr)
- if(!briefcase || !usr.can_hold_items())
- return
- if(!usr.canUseTopic(src, BE_CLOSE, ismonkey(usr)))
+ if(!briefcase || !usr.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
return
usr.visible_message("[usr] starts closing [src]...", "You start closing [src]...")
if(do_after(usr, 30, target = usr))
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 987a36abeeb..3c5f54ed365 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -421,7 +421,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
/obj/item/attack_alien(mob/user)
var/mob/living/carbon/alien/A = user
- if(!ISADVANCEDTOOLUSER(A))
+ if(!user.can_hold_items(src))
if(src in A.contents) // To stop Aliens having items stuck in their pockets
A.dropItemToGround(src)
to_chat(user, "Your claws aren't capable of such fine manipulation!")
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index 4c4f0d44b7f..53d8d325c3b 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -159,14 +159,13 @@
ui.open()
/obj/item/toy/crayon/spraycan/AltClick(mob/user)
- if(user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
- if(has_cap)
- is_capped = !is_capped
- to_chat(user, "The cap on [src] is now [is_capped ? "on" : "off"].")
- update_icon()
+ if(has_cap && user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
+ is_capped = !is_capped
+ to_chat(user, "The cap on [src] is now [is_capped ? "on" : "off"].")
+ update_icon()
/obj/item/toy/crayon/CtrlClick(mob/user)
- if(can_change_colour && !isturf(loc) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(can_change_colour && !isturf(loc) && user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
select_colour(user)
else
return ..()
@@ -262,7 +261,7 @@
/obj/item/toy/crayon/proc/select_colour(mob/user)
var/chosen_colour = input(user, "", "Choose Color", paint_color) as color|null
- if (!isnull(chosen_colour) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if (!isnull(chosen_colour) && user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
paint_color = chosen_colour
return TRUE
return FALSE
diff --git a/code/game/objects/items/credit_holochip.dm b/code/game/objects/items/credit_holochip.dm
index 0acb225772b..74f6d4d043d 100644
--- a/code/game/objects/items/credit_holochip.dm
+++ b/code/game/objects/items/credit_holochip.dm
@@ -82,10 +82,10 @@
qdel(H)
/obj/item/holochip/AltClick(mob/user)
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return
var/split_amount = round(input(user,"How many credits do you want to extract from the holochip?") as null|num)
- if(split_amount == null || split_amount <= 0 || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(split_amount == null || split_amount <= 0 || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return
else
var/new_credits = spend(split_amount, TRUE)
diff --git a/code/game/objects/items/devices/desynchronizer.dm b/code/game/objects/items/devices/desynchronizer.dm
index d60ef6adc11..186285ca702 100644
--- a/code/game/objects/items/devices/desynchronizer.dm
+++ b/code/game/objects/items/devices/desynchronizer.dm
@@ -33,7 +33,7 @@
. += "Can be used again to interrupt the effect early. The recharge time is the same as the time spent in desync."
/obj/item/desynchronizer/AltClick(mob/living/user)
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return
var/new_duration = input(user, "Set the duration (5-300):", "Desynchronizer", duration / 10) as null|num
if(new_duration)
diff --git a/code/game/objects/items/devices/quantum_keycard.dm b/code/game/objects/items/devices/quantum_keycard.dm
index 25ea0b69029..0f21d21bf8d 100644
--- a/code/game/objects/items/devices/quantum_keycard.dm
+++ b/code/game/objects/items/devices/quantum_keycard.dm
@@ -18,7 +18,7 @@
. += "Insert [src] into an active quantum pad to link it."
/obj/item/quantum_keycard/AltClick(mob/living/user)
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return
to_chat(user, "You start pressing [src]'s unlink button...")
if(do_after(user, 40, target = src))
diff --git a/code/game/objects/items/devices/swapper.dm b/code/game/objects/items/devices/swapper.dm
index 7fdc96073ab..6cc56578d0d 100644
--- a/code/game/objects/items/devices/swapper.dm
+++ b/code/game/objects/items/devices/swapper.dm
@@ -69,7 +69,7 @@
. += "Not Linked. Use on another quantum spin inverter to establish a quantum link."
/obj/item/swapper/AltClick(mob/living/user)
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return
to_chat(user, "You break the current quantum link.")
if(!QDELETED(linked_swapper))
diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm
index 6d63e1bf73e..dc80825a8a0 100644
--- a/code/game/objects/items/extinguisher.dm
+++ b/code/game/objects/items/extinguisher.dm
@@ -231,7 +231,7 @@
addtimer(CALLBACK(src, /obj/item/extinguisher/proc/move_chair, B, movementdirection, repetition), timer_seconds)
/obj/item/extinguisher/AltClick(mob/user)
- if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
return
if(!user.is_holding(src))
to_chat(user, "You must be holding the [src] in your hands do this!")
diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm
index 94d6ad04b4e..866cbe70db9 100644
--- a/code/game/objects/items/flamethrower.dm
+++ b/code/game/objects/items/flamethrower.dm
@@ -146,7 +146,7 @@
toggle_igniter(user)
/obj/item/flamethrower/AltClick(mob/user)
- if(ptank && isliving(user) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(ptank && isliving(user) && user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
user.put_in_hands(ptank)
ptank = null
to_chat(user, "You remove the plasma tank from [src]!")
diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm
index 75e1f271b6f..347fbb97c5e 100644
--- a/code/game/objects/items/pet_carrier.dm
+++ b/code/game/objects/items/pet_carrier.dm
@@ -155,7 +155,7 @@
/obj/item/pet_carrier/MouseDrop(atom/over_atom)
. = ..()
- if(isopenturf(over_atom) && usr.canUseTopic(src, BE_CLOSE, ismonkey(usr)) && usr.Adjacent(over_atom) && open && occupants.len)
+ if(isopenturf(over_atom) && usr.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(usr)) && usr.Adjacent(over_atom) && open && occupants.len)
usr.visible_message("[usr] unloads [src].", \
"You unload [src] onto [over_atom].")
for(var/V in occupants)
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 2fa7fc761a1..d71930252e8 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -445,23 +445,17 @@
. = ..()
if(isturf(loc)) // to prevent people that are alt clicking a tile to see its content from getting undesidered pop ups
return
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(is_cyborg || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)) || zero_amount())
return
- if(is_cyborg)
+ //get amount from user
+ var/max = get_amount()
+ var/stackmaterial = round(input(user,"How many sheets do you wish to take out of this stack? (Maximum [max])") as null|num)
+ max = get_amount()
+ stackmaterial = min(max, stackmaterial)
+ if(stackmaterial == null || stackmaterial <= 0 || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return
- else
- if(zero_amount())
- return
- //get amount from user
- var/max = get_amount()
- var/stackmaterial = round(input(user,"How many sheets do you wish to take out of this stack? (Maximum [max])") as null|num)
- max = get_amount()
- stackmaterial = min(max, stackmaterial)
- if(stackmaterial == null || stackmaterial <= 0 || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
- return
- else
- split_stack(user, stackmaterial)
- to_chat(user, "You take [stackmaterial] sheets out of the stack.")
+ split_stack(user, stackmaterial)
+ to_chat(user, "You take [stackmaterial] sheets out of the stack.")
/** Splits the stack into two stacks.
*
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index df421e73dcf..57cd1677db6 100644
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -694,7 +694,7 @@
. += "Alt-click it to quickly draw the blade."
/obj/item/storage/belt/sabre/AltClick(mob/user)
- if(!iscarbon(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
return
if(length(contents))
var/obj/item/I = contents[1]
diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm
index a472109b743..29a532b7261 100644
--- a/code/game/objects/items/storage/fancy.dm
+++ b/code/game/objects/items/storage/fancy.dm
@@ -217,8 +217,8 @@
if(spawn_coupon)
. += "There's a coupon on the back of the pack! You can tear it off once it's empty."
-/obj/item/storage/fancy/cigarettes/AltClick(mob/living/carbon/user)
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+/obj/item/storage/fancy/cigarettes/AltClick(mob/user)
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
return
var/obj/item/clothing/mask/cigarette/W = locate(/obj/item/clothing/mask/cigarette) in contents
if(W && contents.len > 0)
diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm
index d2a30e53c07..ec00e8fc6a0 100644
--- a/code/game/objects/structures/beds_chairs/chair.dm
+++ b/code/game/objects/structures/beds_chairs/chair.dm
@@ -37,7 +37,7 @@
var/mob/living/L = user
if(istype(L))
- if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return FALSE
else
return TRUE
@@ -240,9 +240,9 @@
/obj/structure/chair/MouseDrop(over_object, src_location, over_location)
. = ..()
if(over_object == usr && Adjacent(usr))
- if(!item_chair || !usr.can_hold_items() || has_buckled_mobs() || src.flags_1 & NODECONSTRUCT_1)
+ if(!item_chair || has_buckled_mobs() || src.flags_1 & NODECONSTRUCT_1)
return
- if(!usr.canUseTopic(src, BE_CLOSE, ismonkey(usr)))
+ if(!usr.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
return
usr.visible_message("[usr] grabs \the [src.name].", "You grab \the [src.name].")
var/obj/item/C = new item_chair(loc)
@@ -415,9 +415,9 @@
if(has_gravity())
playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE)
-/obj/structure/chair/bronze/AltClick(mob/living/user)
+/obj/structure/chair/bronze/AltClick(mob/user)
turns = 0
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return
if(!(datum_flags & DF_ISPROCESSING))
user.visible_message("[user] spins [src] around, and the last vestiges of Ratvarian technology keeps it spinning FOREVER.", \
diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm
index 05110a4ce68..aeac1b9bc8a 100644
--- a/code/game/objects/structures/extinguisher.dm
+++ b/code/game/objects/structures/extinguisher.dm
@@ -110,7 +110,7 @@
return attack_hand(user)
/obj/structure/extinguisher_cabinet/AltClick(mob/living/user)
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
return
toggle_cabinet(user)
diff --git a/code/game/objects/structures/reflector.dm b/code/game/objects/structures/reflector.dm
index f831afd5d2a..f70c559236e 100644
--- a/code/game/objects/structures/reflector.dm
+++ b/code/game/objects/structures/reflector.dm
@@ -157,14 +157,14 @@
to_chat(user, "The rotation is locked!")
return FALSE
var/new_angle = input(user, "Input a new angle for primary reflection face.", "Reflector Angle", rotation_angle) as null|num
- if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return
if(!isnull(new_angle))
setAngle(SIMPLIFY_DEGREES(new_angle))
return TRUE
/obj/structure/reflector/AltClick(mob/user)
- if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return
else if(finished)
rotate(user)
diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm
index be604fb069f..cbe7e9fdf73 100644
--- a/code/game/objects/structures/statues.dm
+++ b/code/game/objects/structures/statues.dm
@@ -28,7 +28,7 @@
to_chat(user, "It's bolted to the floor, you'll need to unwrench it first.")
/obj/structure/statue/proc/can_user_rotate(mob/user)
- return isliving(user) && user.canUseTopic(src, BE_CLOSE, no_dexterity = ismonkey(user))
+ return !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user))
/obj/structure/statue/attackby(obj/item/W, mob/living/user, params)
add_fingerprint(user)
diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm
index a249452746e..e98ba564648 100644
--- a/code/modules/antagonists/revenant/revenant.dm
+++ b/code/modules/antagonists/revenant/revenant.dm
@@ -83,7 +83,7 @@
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/malfunction(null))
random_revenant_name()
-/mob/living/simple_animal/revenant/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE)
+/mob/living/simple_animal/revenant/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE, no_hands = FALSE, floor_okay=FALSE)
return FALSE
/mob/living/simple_animal/revenant/proc/random_revenant_name()
diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
index 7366c5c1c6e..765a648035d 100644
--- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
+++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
@@ -91,7 +91,7 @@
/obj/machinery/portable_atmospherics/AltClick(mob/living/user)
. = ..()
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, !ismonkey(user)) || !can_interact(user))
+ if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)) || !can_interact(user))
return
if(holding)
to_chat(user, "You remove [holding] from [src].")
diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm
index fcb3a63448f..9a0aec75315 100644
--- a/code/modules/clothing/head/jobs.dm
+++ b/code/modules/clothing/head/jobs.dm
@@ -99,16 +99,16 @@
. += "Alt-click to take a candy corn."
/obj/item/clothing/head/fedora/det_hat/AltClick(mob/user)
- if(user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
- ..()
- if(loc == user)
- if(candy_cooldown < world.time)
- var/obj/item/food/candy_corn/CC = new /obj/item/food/candy_corn(src)
- user.put_in_hands(CC)
- to_chat(user, "You slip a candy corn from your hat.")
- candy_cooldown = world.time+1200
- else
- to_chat(user, "You just took a candy corn! You should wait a couple minutes, lest you burn through your stash.")
+ . = ..()
+ if(loc != user || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
+ return
+ if(candy_cooldown < world.time)
+ var/obj/item/food/candy_corn/CC = new /obj/item/food/candy_corn(src)
+ user.put_in_hands(CC)
+ to_chat(user, "You slip a candy corn from your hat.")
+ candy_cooldown = world.time+1200
+ else
+ to_chat(user, "You just took a candy corn! You should wait a couple minutes, lest you burn through your stash.")
//Mime
diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm
index 80030e26cfa..4c6a6db3f87 100644
--- a/code/modules/clothing/head/soft_caps.dm
+++ b/code/modules/clothing/head/soft_caps.dm
@@ -23,9 +23,7 @@
/obj/item/clothing/head/soft/AltClick(mob/user)
..()
- if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
- return
- else
+ if(user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
flip(user)
diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm
index e6bf7711a43..ad4aeef69c8 100644
--- a/code/modules/clothing/masks/breath.dm
+++ b/code/modules/clothing/masks/breath.dm
@@ -23,9 +23,7 @@
/obj/item/clothing/mask/breath/AltClick(mob/user)
..()
- if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
- return
- else
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
adjustmask(user)
/obj/item/clothing/mask/breath/examine(mob/user)
diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm
index e93837a34a9..3f26570d9c6 100644
--- a/code/modules/clothing/spacesuits/_spacesuits.dm
+++ b/code/modules/clothing/spacesuits/_spacesuits.dm
@@ -165,13 +165,13 @@
/// Open the cell cover when ALT+Click on the suit
/obj/item/clothing/suit/space/AltClick(mob/living/user)
- if(!user || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return ..()
toggle_spacesuit_cell(user)
/// Remove the cell whent he cover is open on CTRL+Click
/obj/item/clothing/suit/space/CtrlClick(mob/living/user)
- if(user?.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
if(cell_cover_open && cell)
remove_cell(user)
return
diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm
index ffd799b3d0a..625d12700d5 100644
--- a/code/modules/clothing/suits/toggles.dm
+++ b/code/modules/clothing/suits/toggles.dm
@@ -110,7 +110,7 @@
/obj/item/clothing/suit/toggle/AltClick(mob/user)
..()
- if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return
else
suit_toggle(user)
diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm
index 9149e1fd396..08168e91ee3 100644
--- a/code/modules/clothing/under/_under.dm
+++ b/code/modules/clothing/under/_under.dm
@@ -239,13 +239,12 @@
if(.)
return
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return
+ if(attached_accessory)
+ remove_accessory(user)
else
- if(attached_accessory)
- remove_accessory(user)
- else
- rolldown()
+ rolldown()
/obj/item/clothing/under/verb/jumpsuit_adjust()
set name = "Adjust Jumpsuit Style"
diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm
index 1b4e1145ad8..8afb0e8e367 100755
--- a/code/modules/clothing/under/accessories.dm
+++ b/code/modules/clothing/under/accessories.dm
@@ -73,7 +73,7 @@
return
/obj/item/clothing/accessory/AltClick(mob/user)
- if(istype(user) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
if(initial(above_suit))
above_suit = !above_suit
to_chat(user, "[src] will be worn [above_suit ? "above" : "below"] your suit.")
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index ca0bf906777..6faab949603 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -802,7 +802,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
update_icon()
-/mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE)
+/mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE, need_hands = FALSE, floor_okay=FALSE)
return isAdminGhostAI(usr)
/mob/dead/observer/is_literate()
diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm
index 4da3627a370..6464feec469 100644
--- a/code/modules/mob/living/carbon/alien/alien.dm
+++ b/code/modules/mob/living/carbon/alien/alien.dm
@@ -130,8 +130,8 @@ Des: Removes all infected images from the alien.
SEND_SIGNAL(new_xeno, COMSIG_NANITE_SYNC, nanites)
qdel(src)
-/mob/living/carbon/alien/can_hold_items()
- return ISADVANCEDTOOLUSER(src) && ..()
+/mob/living/carbon/alien/can_hold_items(obj/item/I)
+ return ((I && istype(I, /obj/item/clothing/mask/facehugger)) || (ISADVANCEDTOOLUSER(src) && ..()))
/mob/living/carbon/alien/on_lying_down(new_lying_angle)
. = ..()
diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm
index 837eea02abe..d4b1d99a9ff 100644
--- a/code/modules/mob/living/carbon/alien/special/facehugger.dm
+++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm
@@ -54,9 +54,6 @@
/obj/item/clothing/mask/facehugger/attackby(obj/item/O, mob/user, params)
return O.attack_obj(src, user)
-/obj/item/clothing/mask/facehugger/attack_alien(mob/user) //can be picked up by aliens
- return attack_hand(user)
-
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/mask/facehugger/attack_hand(mob/user)
if((stat == CONSCIOUS && !sterile) && !isalien(user))
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 240f48aaedc..0909a0923d3 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -807,17 +807,6 @@
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#000000")
cut_overlay(MA)
-/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE, floor_okay=FALSE)
- if(!(mobility_flags & MOBILITY_UI) && !floor_okay)
- to_chat(src, "You can't do that right now!")
- return FALSE
- if(!Adjacent(M) && (M.loc != src))
- if((be_close == FALSE) || (!no_tk && (dna.check_mutation(TK) && tkMaxRangeCheck(src, M))))
- return TRUE
- to_chat(src, "You are too far away!")
- return FALSE
- return TRUE
-
/mob/living/carbon/human/resist_restraints()
if(wear_suit?.breakouttime)
changeNext_move(CLICK_CD_BREAKOUT)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index f38dd68d47b..2c74b514b8c 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1115,14 +1115,25 @@
/mob/living/proc/harvest(mob/living/user) //used for extra objects etc. in butchering
return
-/mob/living/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE)
- if(incapacitated())
+/mob/living/can_hold_items(obj/item/I)
+ return usable_hands && ..()
+
+/mob/living/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE, need_hands = FALSE, floor_okay=FALSE)
+ if(!(mobility_flags & MOBILITY_UI) && !floor_okay)
to_chat(src, "You can't do that right now!")
return FALSE
- if(be_close && !in_range(M, src))
- to_chat(src, "You are too far away!")
+ if(be_close && !Adjacent(M) && (M.loc != src))
+ if(no_tk)
+ to_chat(src, "You are too far away!")
+ return FALSE
+ var/datum/dna/D = has_dna()
+ if(!D || !D.check_mutation(TK) || !tkMaxRangeCheck(src, M))
+ to_chat(src, "You are too far away!")
+ return FALSE
+ if(need_hands && !can_hold_items(isitem(M) ? M : null)) //almost redundant if it weren't for mobs,
+ to_chat(src, "You don't have the physical ability to do this!")
return FALSE
- if(!no_dexterity)
+ if(!no_dexterity && !ISADVANCEDTOOLUSER(src))
to_chat(src, "You don't have the dexterity to do this!")
return FALSE
return TRUE
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 950d3e6ffcb..04368ee333a 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -802,14 +802,11 @@
to_chat(src, "You have been downloaded to a mobile storage device. Remote device connection severed.")
to_chat(user, "Transfer successful: [name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory.")
-/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE)
- if(control_disabled || incapacitated())
+/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE, need_hands = FALSE, floor_okay=FALSE)
+ if(control_disabled)
to_chat(src, "You can't do that right now!")
return FALSE
- if(be_close && !in_range(M, src))
- to_chat(src, "You are too far away!")
- return FALSE
- return can_see(M) //stop AIs from leaving windows open and using then after they lose vision
+ return can_see(M) && ..() //stop AIs from leaving windows open and using then after they lose vision
/mob/living/silicon/ai/proc/can_see(atom/A)
if(isturf(loc)) //AI in core, check if on cameras
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 6107d9913a6..76817c5b177 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -203,11 +203,8 @@
// See software.dm for Topic()
-/mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE)
- if(be_close && !in_range(M, src))
- to_chat(src, "You are too far away!")
- return FALSE
- return TRUE
+/mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE, need_hands = FALSE, floor_okay=FALSE)
+ return ..(M, be_close, no_dexterity, no_tk, need_hands, TRUE) //Resting is just an aesthetic feature for them.
/mob/proc/makePAI(delold)
var/obj/item/paicard/card = new /obj/item/paicard(get_turf(src))
diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm
index 6df46ddbbc0..d70f2b4e2b6 100644
--- a/code/modules/mob/living/silicon/robot/inventory.dm
+++ b/code/modules/mob/living/silicon/robot/inventory.dm
@@ -403,6 +403,6 @@
/mob/living/silicon/robot/swap_hand()
cycle_modules()
-/mob/living/silicon/robot/can_hold_items()
- return FALSE //held_items are used for modules.
+/mob/living/silicon/robot/can_hold_items(obj/item/I)
+ return (I && (I in module.modules)) //Only if it's part of our module.
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index cca84ee416c..2f07c89e894 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -721,14 +721,11 @@
if(DISCONNECT) //Tampering with the wires
to_chat(connected_ai, "
NOTICE - Remote telemetry lost with [name].
")
-/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE)
- if(stat || lockcharge || low_power_mode)
+/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE, need_hands = FALSE, floor_okay=FALSE)
+ if(lockcharge || low_power_mode)
to_chat(src, "You can't do that right now!")
return FALSE
- if(be_close && !in_range(M, src))
- to_chat(src, "You are too far away!")
- return FALSE
- return TRUE
+ return ..()
/mob/living/silicon/robot/updatehealth()
..()
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index e5449575629..6b342f62cbe 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -538,18 +538,6 @@
if(target)
return new childspawn(target)
-/mob/living/simple_animal/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE)
- if(incapacitated())
- to_chat(src, "You can't do that right now!")
- return FALSE
- if(be_close && !in_range(M, src))
- to_chat(src, "You are too far away!")
- return FALSE
- if(!(no_dexterity || dextrous))
- to_chat(src, "You don't have the dexterity to do this!")
- return FALSE
- return TRUE
-
/mob/living/simple_animal/stripPanelUnequip(obj/item/what, mob/who, where)
if(!canUseTopic(who, BE_CLOSE))
return
@@ -610,7 +598,7 @@
/mob/living/simple_animal/get_idcard(hand_first)
return (..() || access_card)
-/mob/living/simple_animal/can_hold_items()
+/mob/living/simple_animal/can_hold_items(obj/item/I)
return dextrous && ..()
/mob/living/simple_animal/activate_hand(selhand)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 901580accfb..8f1cdd6e9a7 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1037,7 +1037,7 @@
return TRUE
///Can the mob use Topic to interact with machines
-/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE)
+/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE, need_hands = FALSE, floor_okay=FALSE)
return
///Can this mob use storage
@@ -1190,10 +1190,6 @@
return
return TRUE
-///Can this mob hold items
-/mob/proc/can_hold_items()
- return length(held_items)
-
/**
* Get the mob VV dropdown extras
*/
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 3c2d5b56a82..bd6a94cdba0 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -546,3 +546,7 @@
///Can the mob see reagents inside of containers?
/mob/proc/can_see_reagents()
return stat == DEAD || has_unlimited_silicon_privilege //Dead guys and silicons can always see reagents
+
+///Can this mob hold items
+/mob/proc/can_hold_items(obj/item/I)
+ return length(held_items)
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index 3ce52a269ab..f9d01f30fc9 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -100,7 +100,7 @@
/obj/structure/filingcabinet/Topic(href, href_list)
- if(!usr.canUseTopic(src, BE_CLOSE, ismonkey(usr)))
+ if(!usr.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(usr)))
return
if(href_list["retrieve"])
usr << browse("", "window=filingcabinet") // Close the menu
diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm
index 397e0963239..d3b54e34da8 100644
--- a/code/modules/paperwork/paperplane.dm
+++ b/code/modules/paperwork/paperplane.dm
@@ -121,8 +121,8 @@
. = ..()
. += "Alt-click [src] to fold it into a paper plane."
-/obj/item/paper/AltClick(mob/living/carbon/user, obj/item/I)
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+/obj/item/paper/AltClick(mob/living/user, obj/item/I)
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
return
if(istype(src, /obj/item/paper/carbon))
var/obj/item/paper/carbon/Carbon = src
diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm
index d151e2eccb0..d8a2cee7fc0 100644
--- a/code/modules/projectiles/guns/ballistic/shotgun.dm
+++ b/code/modules/projectiles/guns/ballistic/shotgun.dm
@@ -105,7 +105,7 @@
to_chat(user, "You switch to tube A.")
/obj/item/gun/ballistic/shotgun/automatic/dual_tube/AltClick(mob/living/user)
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
return
rack()
@@ -266,7 +266,7 @@
hook = new /obj/item/gun/magic/hook/bounty(src)
/obj/item/gun/ballistic/shotgun/doublebarrel/hook/AltClick(mob/user)
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, TRUE))
return
if(toggled)
to_chat(user,"You switch to the shotgun.")
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index d150410b1f2..cfab7fc9bb3 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -127,7 +127,7 @@
update_icon()
/obj/item/reagent_containers/hypospray/medipen/attack_self(mob/user)
- if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK, FLOOR_OKAY))
+ if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK, FALSE, FLOOR_OKAY))
inject(user, user)
/obj/item/reagent_containers/hypospray/medipen/update_icon_state()
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index b7a11ca0055..527d6477991 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -165,8 +165,10 @@
user.forceMove(loc)
update_icon()
-// monkeys and xenos can only pull the flush lever
+// clumsy monkeys and xenos can only pull the flush lever
/obj/machinery/disposal/attack_paw(mob/user)
+ if(ISADVANCEDTOOLUSER(user))
+ return ..()
if(machine_stat & BROKEN)
return
flush = !flush
diff --git a/code/modules/tgui/states.dm b/code/modules/tgui/states.dm
index af5bdefc90b..877611fb323 100644
--- a/code/modules/tgui/states.dm
+++ b/code/modules/tgui/states.dm
@@ -89,22 +89,6 @@
return UI_DISABLED
return ..()
-/**
- * public
- *
- * Check the distance for a living mob.
- * Really only used for checks outside the context of a mob.
- * Otherwise, use shared_living_ui_distance().
- *
- * required src_object The object which owns the UI.
- * required user mob The mob who opened/is using the UI.
- *
- * return UI_state The state of the UI.
- */
-/atom/proc/contents_ui_distance(src_object, mob/living/user)
- // Just call this mob's check.
- return user.shared_living_ui_distance(src_object)
-
/**
* public
*
diff --git a/code/modules/tgui/states/default.dm b/code/modules/tgui/states/default.dm
index 367e57beffa..80ac5791ffd 100644
--- a/code/modules/tgui/states/default.dm
+++ b/code/modules/tgui/states/default.dm
@@ -18,15 +18,10 @@ GLOBAL_DATUM_INIT(default_state, /datum/ui_state/default, new)
/mob/living/default_can_use_topic(src_object)
. = shared_ui_interaction(src_object)
- if(. > UI_CLOSE && loc)
- . = min(., loc.contents_ui_distance(src_object, src)) // Check the distance...
- if(. == UI_INTERACTIVE) // Non-human living mobs can only look, not touch.
- return UI_UPDATE
-
-/mob/living/carbon/human/default_can_use_topic(src_object)
- . = shared_ui_interaction(src_object)
- if(. > UI_CLOSE)
+ if(. > UI_CLOSE && loc) //must not be in nullspace.
. = min(., shared_living_ui_distance(src_object)) // Check the distance...
+ if(. == UI_INTERACTIVE && !ISADVANCEDTOOLUSER(src)) // unhandy living mobs can only look, not touch.
+ return UI_UPDATE
/mob/living/silicon/robot/default_can_use_topic(src_object)
. = shared_ui_interaction(src_object)
@@ -49,14 +44,9 @@ GLOBAL_DATUM_INIT(default_state, /datum/ui_state/default, new)
return UI_INTERACTIVE
return UI_CLOSE
-/mob/living/simple_animal/default_can_use_topic(src_object)
- . = shared_ui_interaction(src_object)
- if(. > UI_CLOSE)
- . = min(., shared_living_ui_distance(src_object)) //simple animals can only use things they're near.
-
/mob/living/silicon/pai/default_can_use_topic(src_object)
// pAIs can only use themselves and the owner's radio.
if((src_object == src || src_object == radio) && !stat)
return UI_INTERACTIVE
else
- return ..()
+ return min(..(), UI_UPDATE)
diff --git a/code/modules/vehicles/ridden.dm b/code/modules/vehicles/ridden.dm
index bd0b4691ed8..c6fbcd8a6ac 100644
--- a/code/modules/vehicles/ridden.dm
+++ b/code/modules/vehicles/ridden.dm
@@ -45,7 +45,7 @@
inserted_key = I
/obj/vehicle/ridden/AltClick(mob/user)
- if(!inserted_key || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!inserted_key || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !issilicon(user)))
return ..()
if(!is_occupant(user))
to_chat(user, "You must be riding the [src] to remove [src]'s key!")
diff --git a/code/modules/vehicles/wheelchair.dm b/code/modules/vehicles/wheelchair.dm
index 7f89c2882bd..e8678cc341f 100644
--- a/code/modules/vehicles/wheelchair.dm
+++ b/code/modules/vehicles/wheelchair.dm
@@ -105,7 +105,7 @@
/obj/vehicle/ridden/wheelchair/proc/can_user_rotate(mob/living/user)
var/mob/living/L = user
if(istype(L))
- if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
return FALSE
if(isobserver(user) && CONFIG_GET(flag/ghost_interaction))
return TRUE