diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index 189f792ceb1..e4a02c3ac0d 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -35,6 +35,9 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define INITIALIZED (1<<9)
/// Atom is admin spawned
#define ADMIN_SPAWNED (1<<10)
+/// get_hearers_in_view() returns us, meaning we intercept usually for-players messages. Mobs, mechas, etc should all have this!
+#define HEAR (1<<11)
+
//Flags for items (equipment) - Used in /obj/item/var/item_flags
#define THICKMATERIAL (1<<0) // Prevents syringes, parapens and hyposprays if equipped to slot_suit or slot_head.
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index b502e1c6634..ea734f1c089 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -67,6 +67,31 @@
return heard
+/proc/get_hearers_in_view(R, atom/source)
+ var/turf/T = get_turf(source)
+ . = list()
+ if(!T)
+ return
+ var/list/processing = list()
+ if(R == 0)
+ processing += T.contents
+ else
+ var/lum = T.luminosity
+ T.luminosity = 6
+ var/list/cached_view = view(R, T)
+ for(var/mob/M in cached_view)
+ processing += M
+ for(var/obj/O in cached_view)
+ processing += O
+ T.luminosity = lum
+ var/i = 0
+ while(i < length(processing))
+ var/atom/A = processing[++i]
+ if(A.flags & HEAR)
+ . += A
+ SEND_SIGNAL(A, COMSIG_ATOM_HEARER_IN_VIEW, processing, .)
+ processing += A.contents
+
/proc/isStationLevel(var/level)
return level in GLOB.using_map.station_levels
diff --git a/code/datums/looping_sounds/_looping_sound.dm b/code/datums/looping_sounds/_looping_sound.dm
index 95007a17dd3..64ed16006dc 100644
--- a/code/datums/looping_sounds/_looping_sound.dm
+++ b/code/datums/looping_sounds/_looping_sound.dm
@@ -78,7 +78,7 @@
var/list/atoms_cache = output_atoms
var/sound/S = sound(soundfile)
if(direct)
- S.channel = open_sound_channel()
+ S.channel = SSsounds.random_available_channel()
S.volume = volume
for(var/i in 1 to atoms_cache.len)
var/atom/thing = atoms_cache[i]
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index aaca6a7c8a7..ec5dda9ffd4 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -16,6 +16,7 @@
name = "Mecha"
desc = "Exosuit"
icon = 'icons/mecha/mecha.dmi'
+ flags = HEAR
density = 1 //Dense. To raise the heat.
opacity = 1 ///opaque. Menacing.
anchored = 1 //no pulling around.
diff --git a/code/modules/instruments/instruments/item.dm b/code/modules/instruments/instruments/item.dm
index 2af35a93ca3..d17afad58ff 100644
--- a/code/modules/instruments/instruments/item.dm
+++ b/code/modules/instruments/instruments/item.dm
@@ -5,8 +5,10 @@
// max_integrity = 100
// resistance_flags = FLAMMABLE
icon = 'icons/obj/musician.dmi'
- lefthand_file = 'icons/mob/inhands/equipment/instruments_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/instruments_righthand.dmi'
+ item_icons = list(
+ slot_l_hand_str = 'icons/mob/inhands/equipment/instruments_lefthand.dmi',
+ slot_r_hand_str = 'icons/mob/inhands/equipment/instruments_righthand.dmi'
+ )
var/datum/song/handheld/song
var/list/allowed_instrument_ids
// var/tune_time_left = 0
@@ -229,7 +231,7 @@
icon_state = "harmonica"
item_state = "harmonica"
allowed_instrument_ids = "harmonica"
- slot_flags = ITEM_SLOT_MASK
+// slot_flags = ITEM_SLOT_MASK
force = 5
w_class = WEIGHT_CLASS_SMALL
// actions_types = list(/datum/action/item_action/instrument)
diff --git a/code/modules/instruments/instruments/stationary.dm b/code/modules/instruments/instruments/stationary.dm
index 8575604d0e1..af7e78cd111 100644
--- a/code/modules/instruments/instruments/stationary.dm
+++ b/code/modules/instruments/instruments/stationary.dm
@@ -35,11 +35,21 @@
. = ..()
song.ui_interact(user)
+/obj/structure/musician/attackby(obj/item/I, mob/living/user)
+ if(I.is_wrench())
+ playsound(src, O.usesound, 50, 1)
+ to_chat(user, "You begin to [anchored? "loosen" : "tighten"] [src]'s casters...")
+ if(do_after(user, 40 * O.toolspeed))
+ user.visible_message("[user] [anchored? "loosens" : "tightens"] [src]'s casters.")
+ anchored = !anchored
+ else
+ return ..()
+
+/*
/obj/structure/musician/wrench_act(mob/living/user, obj/item/I)
- anchored = !anchored
- user.visible_message("[user] [anchored? "anchors" : "unanchors"] [src].")
- //default_unfasten_wrench(user, I, 40)
+ default_unfasten_wrench(user, I, 40)
return TRUE
+*/
/obj/structure/musician/piano
name = "space minimoog"
diff --git a/code/modules/instruments/songs/play_synthesized.dm b/code/modules/instruments/songs/play_synthesized.dm
index 4d19ae4b395..375e2c91daf 100644
--- a/code/modules/instruments/songs/play_synthesized.dm
+++ b/code/modules/instruments/songs/play_synthesized.dm
@@ -80,7 +80,7 @@
last_channel_played = channel_text
for(var/i in hearing_mobs)
var/mob/M = i
- M.playsound_local(get_turf(parent), null, volume, FALSE, K.frequency, INSTRUMENT_DISTANCE_NO_FALLOFF, FALSE, channel, null, copy, /datum/client_preference/intrument_toggle, distance_multiplier = INSTRUMENT_DISTANCE_FALLOFF_BUFF)
+ M.playsound_local(get_turf(parent), null, volume, FALSE, K.frequency, INSTRUMENT_DISTANCE_NO_FALLOFF, FALSE, channel, null, copy, /datum/client_preference/instrument_toggle, distance_multiplier = INSTRUMENT_DISTANCE_FALLOFF_BUFF)
// Could do environment and echo later but not for now
/datum/song/proc/terminate_all_sounds(clear_channels = TRUE)
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 6fab1270840..be0202fe339 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -3,7 +3,7 @@
layer = MOB_LAYER
plane = MOB_PLANE
animate_movement = 2
- flags = PROXMOVE
+ flags = PROXMOVE | HEAR
var/datum/mind/mind
var/stat = 0 //Whether a mob is alive or dead. TODO: Move this to living - Nodrak
diff --git a/sound/weapons/banjoslap.ogg b/sound/weapons/banjoslap.ogg
new file mode 100644
index 00000000000..06a86a535dd
Binary files /dev/null and b/sound/weapons/banjoslap.ogg differ
diff --git a/sound/weapons/stringsmash.ogg b/sound/weapons/stringsmash.ogg
new file mode 100644
index 00000000000..ea96bc0b50b
Binary files /dev/null and b/sound/weapons/stringsmash.ogg differ