diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm
index 87af417a28c..96c32112f59 100644
--- a/code/datums/components/riding.dm
+++ b/code/datums/components/riding.dm
@@ -223,6 +223,7 @@
RegisterSignal(parent, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee)
/datum/component/riding/human/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE)
+ unequip_buckle_inhands(parent)
var/mob/living/carbon/human/H = parent
H.remove_movespeed_modifier(/datum/movespeed_modifier/human_carry)
. = ..()
@@ -377,3 +378,11 @@
AM.unbuckle_mob(rider)
. = ..()
+/obj/item/riding_offhand/on_thrown(mob/living/carbon/user, atom/target)
+ if(rider == user)
+ return //Piggyback user.
+ user.unbuckle_mob(rider)
+ if(HAS_TRAIT(user, TRAIT_PACIFISM))
+ to_chat(user, "You gently let go of [rider].")
+ return
+ return rider
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 01705a8f89d..932f4d8682f 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -897,3 +897,12 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
if(embedding)
return !isnull(embedding["pain_mult"]) && !isnull(embedding["jostle_pain_mult"]) && embedding["pain_mult"] == 0 && embedding["jostle_pain_mult"] == 0
+///Called by the carbon throw_item() proc. Returns null if the item negates the throw, or a reference to the thing to suffer the throw else.
+/obj/item/proc/on_thrown(mob/living/carbon/user, atom/target)
+ if((item_flags & ABSTRACT) || HAS_TRAIT(src, TRAIT_NODROP))
+ return
+ user.dropItemToGround(src, silent = TRUE)
+ if(throwforce && HAS_TRAIT(user, TRAIT_PACIFISM))
+ to_chat(user, "You set [src] down gently on the ground.")
+ return
+ return src
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index eae6a2c608c..d46caf30fc7 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -175,6 +175,34 @@
return
// If the tray IS empty, continue on (tray will be placed on the table like other items)
+ if(istype(I, /obj/item/riding_offhand))
+ var/obj/item/riding_offhand/riding_item = I
+ var/mob/living/carried_mob = riding_item.rider
+ if(carried_mob == user) //Piggyback user.
+ return
+ switch(user.a_intent)
+ if(INTENT_HARM)
+ user.unbuckle_mob(carried_mob)
+ tableheadsmash(user, carried_mob)
+ if(INTENT_HELP)
+ var/tableplace_delay = 3.5 SECONDS
+ var/skills_space = ""
+ if(HAS_TRAIT(user, TRAIT_QUICKER_CARRY))
+ tableplace_delay = 2 SECONDS
+ skills_space = " expertly"
+ else if(HAS_TRAIT(user, TRAIT_QUICK_CARRY))
+ tableplace_delay = 2.75 SECONDS
+ skills_space = " quickly"
+ carried_mob.visible_message("[user] begins to[skills_space] place [carried_mob] onto [src]...",
+ "[user] begins to[skills_space] place [carried_mob] onto [src]...")
+ if(do_after(user, tableplace_delay, target = carried_mob))
+ user.unbuckle_mob(carried_mob)
+ tableplace(user, carried_mob)
+ else
+ user.unbuckle_mob(carried_mob)
+ tablepush(user, carried_mob)
+ return TRUE
+
if(user.a_intent != INTENT_HARM && !(I.item_flags & ABSTRACT))
if(user.transferItemToLoc(I, drop_location(), silent = FALSE))
var/list/click_params = params2list(params)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 66a70e1d636..3d2f4d4724f 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -131,20 +131,15 @@
if(HAS_TRAIT(src, TRAIT_PACIFISM))
to_chat(src, "You gently let go of [throwable_mob].")
return
- var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
- var/turf/end_T = get_turf(target)
- if(start_T && end_T)
- log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
-
- else if(!(I.item_flags & ABSTRACT) && !HAS_TRAIT(I, TRAIT_NODROP))
- thrown_thing = I
- dropItemToGround(I, silent = TRUE)
-
- if(HAS_TRAIT(src, TRAIT_PACIFISM) && I.throwforce)
- to_chat(src, "You set [I] down gently on the ground.")
- return
+ else
+ thrown_thing = I.on_thrown(src, target)
if(thrown_thing)
+ if(isliving(thrown_thing))
+ var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
+ var/turf/end_T = get_turf(target)
+ if(start_T && end_T)
+ log_combat(src, thrown_thing, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
visible_message("[src] throws [thrown_thing].", \
"You throw [thrown_thing].")
log_message("has thrown [thrown_thing]", LOG_ATTACK)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 49a12ed2e3f..d254cdf87df 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -964,17 +964,19 @@
message_admins(msg)
admin_ticket_log(src, msg)
+
/mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user)
- if(pulling == target && grab_state >= GRAB_AGGRESSIVE && stat == CONSCIOUS)
- //If they dragged themselves and we're currently aggressively grabbing them try to piggyback
- if(user == target && can_piggyback(target))
+ if(pulling != target || grab_state < GRAB_AGGRESSIVE || stat != CONSCIOUS || a_intent != INTENT_GRAB)
+ return ..()
+
+ //If they dragged themselves and we're currently aggressively grabbing them try to piggyback
+ if(user == target)
+ if(can_piggyback(target))
piggyback(target)
- return
- //If you dragged them to you and you're aggressively grabbing try to fireman carry them
- else if(user != target && can_be_firemanned(target))
- fireman_carry(target)
- return
- . = ..()
+ //If you dragged them to you and you're aggressively grabbing try to fireman carry them
+ else if(can_be_firemanned(target))
+ fireman_carry(target)
+
//src is the user that will be carrying, target is the mob to be carried
/mob/living/carbon/human/proc/can_piggyback(mob/living/carbon/target)