diff --git a/code/__HELPERS/trait_helpers.dm b/code/__HELPERS/trait_helpers.dm
index e72b5df1a5d..b19bf436541 100644
--- a/code/__HELPERS/trait_helpers.dm
+++ b/code/__HELPERS/trait_helpers.dm
@@ -243,6 +243,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_OBSCURED_WIRES "obscured_wires"
/// Forces open doors after a delay specific to the item
#define TRAIT_FORCES_OPEN_DOORS_ITEM "forces_open_doors_item_varient"
+/// Makes the item no longer spit out a visible message when thrown
+#define TRAIT_NO_THROWN_MESSAGE "no_message_when_thrown"
/// A surgical tool; when in hand in help intent (and with a surgery in progress) won't attack the user
#define TRAIT_SURGICAL "surgical_tool"
diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm
index c02b5b6a9ef..159b0cb0baa 100644
--- a/code/_globalvars/traits.dm
+++ b/code/_globalvars/traits.dm
@@ -102,7 +102,8 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_CMAGGED" = TRAIT_CMAGGED,
"TRAIT_FORCES_OPEN_DOORS" = TRAIT_FORCES_OPEN_DOORS_ITEM,
"TRAIT_OBSCURED_WIRES" = TRAIT_OBSCURED_WIRES,
- "TRAIT_XENO_INTERACTABLE" = TRAIT_XENO_INTERACTABLE
+ "TRAIT_XENO_INTERACTABLE" = TRAIT_XENO_INTERACTABLE,
+ "TRAIT_NO_THROWN_MESSAGE" = TRAIT_NO_THROWN_MESSAGE
),
/turf = list(
"bluespace_speed_trait" = TRAIT_BLUESPACE_SPEED
diff --git a/code/datums/components/sticky.dm b/code/datums/components/sticky.dm
index 49f6723ac62..7c36f320795 100644
--- a/code/datums/components/sticky.dm
+++ b/code/datums/components/sticky.dm
@@ -24,9 +24,11 @@
/datum/component/sticky/RegisterWithParent()
RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(stick_to_it))
+ RegisterSignal(parent, COMSIG_MOVABLE_IMPACT, PROC_REF(stick_to_it_throwing))
/datum/component/sticky/UnregisterFromParent()
UnregisterSignal(parent, COMSIG_ITEM_PRE_ATTACK)
+ UnregisterSignal(parent, COMSIG_MOVABLE_IMPACT)
/datum/component/sticky/proc/stick_to_it(obj/item/I, atom/target, mob/user, params)
SIGNAL_HANDLER
@@ -58,8 +60,23 @@
overlay.Shift(EAST, clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2))
overlay.Shift(NORTH, clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2))
+ attach_signals(I)
+ return COMPONENT_CANCEL_ATTACK_CHAIN
+
+/datum/component/sticky/proc/stick_to_it_throwing(obj/item/thrown_item, atom/hit_target, throwingdatum, params)
+ SIGNAL_HANDLER
+ if(hit_target.GetComponent(/datum/component/sticky))
+ return
+
+ attached_to = hit_target
+ move_to_the_thing(parent)
+
+ overlay = icon(thrown_item.icon, thrown_item.icon_state)
+ attach_signals(thrown_item)
+
+/datum/component/sticky/proc/attach_signals(obj/item/attached)
attached_to.add_overlay(overlay, priority = TRUE)
- I.invisibility = INVISIBILITY_ABSTRACT
+ attached.invisibility = INVISIBILITY_ABSTRACT
RegisterSignal(attached_to, COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY, PROC_REF(pick_up))
RegisterSignal(attached_to, COMSIG_PARENT_EXAMINE, PROC_REF(add_sticky_text))
@@ -67,7 +84,6 @@
if(ismovable(attached_to))
RegisterSignal(attached_to, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
START_PROCESSING(SSobj, src)
- return COMPONENT_CANCEL_ATTACK_CHAIN
/datum/component/sticky/proc/pick_up(atom/A, mob/living/carbon/human/user)
SIGNAL_HANDLER
diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm
index 3a2e38d1cdf..d4f2a95c3ef 100644
--- a/code/game/objects/items/devices/camera_bug.dm
+++ b/code/game/objects/items/devices/camera_bug.dm
@@ -62,10 +62,11 @@
. = ..()
link_to_camera(the_bug)
AddComponent(/datum/component/sticky)
+ ADD_TRAIT(src, TRAIT_NO_THROWN_MESSAGE, ROUNDSTART_TRAIT)
/obj/item/wall_bug/Destroy()
QDEL_NULL(camera)
- . = ..()
+ return ..()
/obj/item/wall_bug/examine(mob/user)
. = ..()
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 35b4b979520..11c74b9dcc7 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -697,7 +697,8 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
return
if(thrown_thing)
- visible_message("[src] has thrown [thrown_thing].")
+ if(!HAS_TRAIT(thrown_thing, TRAIT_NO_THROWN_MESSAGE))
+ visible_message("[src] has thrown [thrown_thing].")
newtonian_move(get_dir(target, src))
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src, null, null, null, move_force)