diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index d2b538f5777..c8c69fbce0f 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -364,6 +364,16 @@
#define HEARING_DAMAGE_LIMIT 100
#define HEARING_DAMAGE_SLOW_HEAL 25
+// Used by hearing sensitivity
+#define HEARING_NORMAL 0
+#define HEARING_SENSITIVE 1
+#define HEARING_VERY_SENSITIVE 2
+
+#define MACHINE_SOUND "You hear the sound of machinery"
+#define BUTTON_FLICK "You hear a click"
+#define THUNK_SOUND "You hear a THUNK"
+#define PING_SOUND "You hear a ping"
+
//Used by emotes
#define VISIBLE_MESSAGE 1
#define AUDIBLE_MESSAGE 2
diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm
index 3443d36125e..24481d294a9 100644
--- a/code/_helpers/global_lists.dm
+++ b/code/_helpers/global_lists.dm
@@ -87,6 +87,9 @@ var/global/list/syndicate_access = list(access_maint_tunnels, access_syndicate,
//Cloaking devices
var/global/list/cloaking_devices = list()
+//Hearing sensitive listening in closely
+var/global/list/intent_listener = list()
+
//////////////////////////
/////Initial Building/////
//////////////////////////
diff --git a/code/_helpers/turfs.dm b/code/_helpers/turfs.dm
index d13bb2e6004..29d790b0fda 100644
--- a/code/_helpers/turfs.dm
+++ b/code/_helpers/turfs.dm
@@ -174,3 +174,11 @@
M.forceMove(new_turf)
return new_turf
+
+/proc/air_sound(atom/source, var/required_pressure = SOUND_MINIMUM_PRESSURE)
+ var/turf/T = get_turf(source)
+ var/datum/gas_mixture/environment = T.return_air()
+ var/pressure = (environment)? environment.return_pressure() : 0
+ if(pressure < required_pressure)
+ return FALSE
+ return TRUE
\ No newline at end of file
diff --git a/code/controllers/subsystems/explosives.dm b/code/controllers/subsystems/explosives.dm
index ebbad2cb581..f407721b63b 100644
--- a/code/controllers/subsystems/explosives.dm
+++ b/code/controllers/subsystems/explosives.dm
@@ -150,16 +150,37 @@ var/datum/controller/subsystem/explosives/SSexplosives
continue
var/dist = get_dist(M_turf, epicenter)
- var/explosion_dir = get_dir(M_turf, epicenter)
- if (reception == 2 && (M.ear_deaf <= 0 || !M.ear_deaf))//Dont play sounds to deaf people
+ var/explosion_dir = angle2text(Get_Angle(M_turf, epicenter))
+ if (reception == 2 && (M.ear_deaf <= 0 || !M.ear_deaf)) //Dont play sounds to deaf people
+
+ // Anyone with sensitive hearing gets a bonus to hearing explosions
+ var/extendeddist = closedist
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ var/hearing_sensitivity = H.get_hearing_sensitivity()
+ if (hearing_sensitivity)
+ if(H.is_listening())
+ if (hearing_sensitivity == HEARING_VERY_SENSITIVE)
+ extendeddist *= 2
+ else
+ extendeddist = round(closedist *= 1.5, 1)
+ else
+ if (hearing_sensitivity == HEARING_VERY_SENSITIVE)
+ extendeddist *= 1.5
+ else
+ extendeddist = round(closedist *= 1.2, 1)
+
// If inside the blast radius + world.view - 2
- if(dist <= closedist)
- to_chat(M, FONT_LARGE(SPAN_WARNING("You hear the sound of a nearby explosion coming from \the [dir2text(explosion_dir)].")))
+ if (dist <= closedist)
+ to_chat(M, FONT_LARGE(SPAN_WARNING("You hear the sound of a nearby explosion coming from \the [explosion_dir].")))
+ M.playsound_simple(epicenter, get_sfx(/decl/sound_category/explosion_sound), min(100, volume), use_random_freq = TRUE, falloff = 5)
+ else if (dist > closedist && dist <= extendeddist) // People with sensitive hearing get a better idea of how far it is
+ to_chat(M, FONT_LARGE(SPAN_WARNING("You hear the sound of a semi-close explosion coming from \the [explosion_dir].")))
M.playsound_simple(epicenter, get_sfx(/decl/sound_category/explosion_sound), min(100, volume), use_random_freq = TRUE, falloff = 5)
else //You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
volume = M.playsound_simple(epicenter, 'sound/effects/explosionfar.ogg', volume, use_random_freq = TRUE, falloff = 1000, use_pressure = TRUE)
if(volume)
- to_chat(M, FONT_LARGE(SPAN_NOTICE("You hear the sound of a distant explosion coming from \the [dir2text(explosion_dir)].")))
+ to_chat(M, FONT_LARGE(SPAN_NOTICE("You hear the sound of a distant explosion coming from \the [explosion_dir].")))
//Deaf people will feel vibrations though
if (volume > 0)//Only shake camera if someone was close enough to hear it
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index b1d2126fd3a..4c0c1addeaf 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -543,7 +543,7 @@
// Use for objects performing visible actions
// message is output to anyone who can see, e.g. "The [src] does something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
-/atom/proc/visible_message(var/message, var/blind_message, var/range = world.view)
+/atom/proc/visible_message(var/message, var/blind_message, var/range = world.view, var/intent_message = null, var/intent_range = 7)
var/turf/T = get_turf(src)
var/list/mobs = list()
var/list/objs = list()
@@ -560,12 +560,15 @@
else if(blind_message)
M.show_message(blind_message, 2)
+ if(intent_message)
+ intent_message(intent_message, intent_range)
+
// Show a message to all mobs and objects in earshot of this atom
// Use for objects performing audible actions
// message is the message output to anyone who can hear.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
-/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance)
+/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance, var/intent_message = null, var/intent_range = 7)
var/range = world.view
if(hearing_distance)
@@ -582,6 +585,17 @@
var/obj/O = o
O.show_message(message,2,deaf_message,1)
+ if(intent_message)
+ intent_message(intent_message, intent_range)
+
+/atom/proc/intent_message(var/message, var/range = 7)
+ if(air_sound(src))
+ var/list/mobs = get_mobs_or_objects_in_view(range, src, include_objects = FALSE)
+ for(var/mob/living/carbon/human/H as anything in intent_listener)
+ if(!(H in mobs))
+ if(src.z == H.z && get_dist(src, H) <= range)
+ H.intent_listen(src, message)
+
/atom/proc/change_area(var/area/oldarea, var/area/newarea)
change_area_name(oldarea.name, newarea.name)
diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm
index 0eb80c3bde8..4c428d7e67a 100644
--- a/code/game/gamemodes/vampire/vampire_powers.dm
+++ b/code/game/gamemodes/vampire/vampire_powers.dm
@@ -346,13 +346,22 @@
continue
if(!vampire_can_affect_target(T, 0))
continue
-
to_chat(T, SPAN_DANGER("You hear an ear piercing shriek and feel your senses go dull!"))
- T.Weaken(5)
- T.ear_deaf = 20
+ if (T.get_hearing_sensitivity())
+ if (T.is_listening())
+ T.Weaken(10)
+ T.Stun(10)
+ T.earpain(4)
+ else
+ T.Weaken(7)
+ T.Stun(7)
+ T.earpain(3)
+ else
+ T.Weaken(5)
+ T.Stun(5)
T.stuttering = 20
- T.Stun(5)
-
+ T.adjustEarDamage(10, 20, TRUE)
+
victims += T
for(var/obj/structure/window/W in view(7))
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index 4ae49c3a626..905275703d2 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -65,7 +65,7 @@
to_chat(user, SPAN_WARNING("There is nobody on \the [src]. It would be pointless to turn the suppressor on."))
suppressing = !suppressing
- user.visible_message(SPAN_NOTICE("\The [user] switches [suppressing ? "on" : "off"] \the [src]'s neural suppressor."))
+ user.visible_message(SPAN_NOTICE("\The [user] switches [suppressing ? "on" : "off"] \the [src]'s neural suppressor."), intent_message = BUTTON_FLICK)
playsound(loc, /decl/sound_category/switch_sound, 50, 1)
/obj/machinery/optable/CanPass(atom/movable/mover, turf/target, height = 0, air_group = 0)
diff --git a/code/game/machinery/autolathe/autolathe.dm b/code/game/machinery/autolathe/autolathe.dm
index 2f6550d4b9a..b19ee182093 100644
--- a/code/game/machinery/autolathe/autolathe.dm
+++ b/code/game/machinery/autolathe/autolathe.dm
@@ -268,6 +268,8 @@
busy = TRUE
update_use_power(2)
+ intent_message(MACHINE_SOUND)
+
//Check if we still have the materials.
for(var/material in build_item.resources)
if(!isnull(stored_material[material]))
diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm
index b51e0ed9829..feb38371d7d 100644
--- a/code/game/machinery/biogenerator.dm
+++ b/code/game/machinery/biogenerator.dm
@@ -434,6 +434,7 @@
update_icon()
updateUsrDialog()
playsound(src.loc, 'sound/machines/juicer.ogg', 50, 1)
+ intent_message(MACHINE_SOUND)
use_power(S * 30)
sleep((S + 1.5 SECONDS) / eat_eff)
processing = 0
@@ -479,6 +480,7 @@
points -= totake
use_power(totake * 0.25)
playsound(src.loc, /decl/sound_category/switch_sound, 50, 1)
+ intent_message(PING_SOUND)
if(ispath(recipe.object, /obj/item/reagent_containers/pill))
if(!made_container)
made_container = new /obj/item/storage/pill_bottle(loc)
diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index fac84c244e0..302e309badf 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -36,6 +36,7 @@
if(..()) return 1
user.visible_message("[user] hits \the [src] button.")
activate(user)
+ intent_message(BUTTON_FLICK, 5)
/obj/machinery/button/proc/activate(mob/living/user)
if(operating || !istype(wifi_sender))
@@ -67,6 +68,7 @@
/obj/machinery/button/switch/attack_hand()
playsound(src, /decl/sound_category/switch_sound, 30)
+ intent_message(BUTTON_FLICK, 5)
//alternate button with the same functionality, except has a door control sprite instead
/obj/machinery/button/alternate
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 6c7a56a01fa..652e77f7233 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -505,6 +505,8 @@
return
operating = TRUE
+ intent_message(MACHINE_SOUND)
+
do_animate("opening")
icon_state = "door_open"
set_opacity(0)
@@ -541,6 +543,8 @@
break
operating = TRUE
+ intent_message(MACHINE_SOUND)
+
do_animate("closing")
sleep(3)
src.density = 1
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index 96f50b3e377..8573de23796 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -44,6 +44,7 @@
playsound(src, /decl/sound_category/switch_sound, 30)
on = !on
sync_lights()
+ intent_message(BUTTON_FLICK, 5)
/obj/machinery/light_switch/proc/sync_lights()
var/area/A = get_area(src)
diff --git a/code/game/machinery/mecha_fabricator.dm b/code/game/machinery/mecha_fabricator.dm
index d14379002a8..2201dfaf13a 100644
--- a/code/game/machinery/mecha_fabricator.dm
+++ b/code/game/machinery/mecha_fabricator.dm
@@ -289,10 +289,13 @@
return
for(var/M in D.materials)
materials[M] = max(0, materials[M] - D.materials[M] * mat_efficiency)
+
+ intent_message(MACHINE_SOUND)
+
if(D.build_path)
var/loc_offset = get_step(src, dir)
var/obj/new_item = D.Fabricate(loc_offset, src)
- visible_message("\The [src] pings, indicating that \the [new_item] is complete.", "You hear a ping.")
+ visible_message("\The [src] pings, indicating that \the [new_item] is complete.", "You hear a ping.", intent_message = PING_SOUND)
if(mat_efficiency != 1)
if(new_item.matter && new_item.matter.len > 0)
for(var/i in new_item.matter)
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index b24a4702b40..2b33878f280 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -715,6 +715,7 @@
if (src.icon_vend) //Show the vending animation if needed
flick(src.icon_vend,src)
playsound(src.loc, vending_sound, 100, 1)
+ intent_message(MACHINE_SOUND)
addtimer(CALLBACK(src, .proc/vend_product, R, user), vend_delay)
/obj/machinery/vending/proc/vend_product(var/datum/data/vending_product/R, mob/user)
@@ -831,6 +832,7 @@
break
if(!throw_item)
return FALSE
+ intent_message(MACHINE_SOUND)
throw_item.vendor_action(src)
INVOKE_ASYNC(throw_item, /atom/movable.proc/throw_at, target, rand(3, 10), rand(1, 3), src)
src.visible_message("[src] launches [throw_item.name] at [target.name]!")
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index 2ff11b6394e..0ac56c30459 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -41,14 +41,19 @@
return
if(emagged)
if(insults)
- user.visible_message("[user] broadcasts, \"[pick(insultmsg)]\"")
+ user.audible_message("[user] broadcasts, \"[pick(insultmsg)]\"", "[user] speaks into \the [src].", 7)
insults--
else
to_chat(user, SPAN_WARNING("*BZZZZzzzzzt*"))
else
- user.visible_message("[user] broadcasts, \"[message]\"")
+ user.audible_message("[user] broadcasts, \"[message]\"", "[user] speaks into \the [src].", 7)
if(activation_sound)
playsound(loc, activation_sound, 100, 0, 1)
+ for (var/mob/living/carbon/human/C in range(user, 2) - user)
+ if (C in range(user, 1))
+ C.earpain(3, TRUE, 2)
+ else
+ C.earpain(2, TRUE, 2)
spamcheck = world.time + 50
return
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index 34adbfbfa3c..123cc569776 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -65,20 +65,28 @@
if((get_dist(M, T) <= 2 || src.loc == M.loc || src.loc == M))
if(!(ear_safety > 0))
if ((prob(14) || (M == src.loc && prob(70))))
- M.ear_damage += rand(1, 10)
+ M.adjustEarDamage(rand(1, 10), 0, TRUE)
else
- M.ear_damage += rand(0, 5)
- M.ear_deaf = max(M.ear_deaf,15)
+ M.adjustEarDamage(rand(0, 5), 15, TRUE)
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ if (H.is_listening())
+ if (H.get_hearing_sensitivity() == HEARING_VERY_SENSITIVE)
+ H.Weaken(5)
+ else
+ H.Weaken(2)
else if(get_dist(M, T) <= 5)
if(!ear_safety)
sound_to(M, sound('sound/weapons/flash_ring.ogg',0,1,0,100))
- M.ear_damage += rand(0, 3)
- M.ear_deaf = max(M.ear_deaf,10)
+ M.adjustEarDamage(rand(0, 3), 10, TRUE)
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ if (H.get_hearing_sensitivity() == HEARING_VERY_SENSITIVE)
+ H.Weaken(2)
else if(!ear_safety)
- M.ear_damage += rand(0, 1)
- M.ear_deaf = max(M.ear_deaf,5)
+ M.adjustEarDamage(rand(0, 1), 5, TRUE)
//This really should be in mob not every check
if(ishuman(M))
@@ -89,15 +97,6 @@
if(!banglet && !(istype(src , /obj/item/grenade/flashbang/clusterbang)))
if (E.damage >= E.min_broken_damage)
to_chat(M, "You can't see anything!")
- if (M.ear_damage >= 15)
- to_chat(M, "Your ears start to ring badly!")
- if(!banglet && !(istype(src , /obj/item/grenade/flashbang/clusterbang)))
- if (prob(M.ear_damage - 10 + 5))
- to_chat(M, "You can't hear anything!")
- M.sdisabilities |= DEAF
- else
- if (M.ear_damage >= 5)
- to_chat(M, "Your ears start to ring!")
M.update_icon()
/obj/item/grenade/flashbang/clusterbang//Created by Polymorph, fixed by Sieve
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index bda8a86b4c7..941fd863d36 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -459,7 +459,7 @@
escapee.next_move = world.time + 100
escapee.last_special = world.time + 100
to_chat(escapee, "You lean on the back of \the [src] and start pushing the door open. (this will take about [breakout_time] minutes)")
- visible_message("\The [src] begins to shake violently!")
+ visible_message(SPAN_DANGER("\The [src] begins to shake violently!"), SPAN_DANGER("You hear the sound of metal trashing around nearby."), intent_message = THUNK_SOUND)
var/time = 6 * breakout_time * 2
@@ -471,6 +471,7 @@
for(var/i in 1 to time) //minutes * 6 * 5seconds * 2
playsound(loc, 'sound/effects/grillehit.ogg', 100, 1)
shake_animation()
+ intent_message(THUNK_SOUND)
if (bar)
bar.update(i)
diff --git a/code/modules/cooking/machinery/cooking_machines/_appliance.dm b/code/modules/cooking/machinery/cooking_machines/_appliance.dm
index b50640222e6..29bb442f4ed 100644
--- a/code/modules/cooking/machinery/cooking_machines/_appliance.dm
+++ b/code/modules/cooking/machinery/cooking_machines/_appliance.dm
@@ -324,7 +324,7 @@
/obj/machinery/appliance/proc/finish_cooking(var/datum/cooking_item/CI)
- audible_message("[src] [finish_verb]")
+ audible_message("[src] [finish_verb]", intent_message = PING_SOUND)
if(cooked_sound)
playsound(get_turf(src), cooked_sound, 50, 1)
//Check recipes first, a valid recipe overrides other options
diff --git a/code/modules/cooking/machinery/cooking_machines/oven.dm b/code/modules/cooking/machinery/cooking_machines/oven.dm
index ec6ac017b96..2523a09d8c6 100644
--- a/code/modules/cooking/machinery/cooking_machines/oven.dm
+++ b/code/modules/cooking/machinery/cooking_machines/oven.dm
@@ -95,7 +95,7 @@
//If a combine target is set the oven will do it instead of checking recipes
/obj/machinery/appliance/cooker/oven/finish_cooking(var/datum/cooking_item/CI)
if(CI.combine_target)
- visible_message("[src] pings!")
+ visible_message("[src] pings!", intent_message = PING_SOUND)
combination_cook(CI)
return
..()
diff --git a/code/modules/economy/ATM.dm b/code/modules/economy/ATM.dm
index 66be73f0633..3734b48d2f2 100644
--- a/code/modules/economy/ATM.dm
+++ b/code/modules/economy/ATM.dm
@@ -101,6 +101,7 @@ log transactions
//display a message to the user
var/response = pick("Initiating withdraw. Have a nice day!", "CRITICAL ERROR: Activating cash chamber panic siphon.","PIN Code accepted! Emptying account balance.", "Jackpot!")
to_chat(user, "[icon2html(src, user)] The [src] beeps: \"[response]\"")
+ intent_message(MACHINE_SOUND)
return 1
/obj/machinery/atm/attackby(obj/item/I as obj, mob/user as mob)
@@ -139,7 +140,7 @@ log transactions
T.time = worldtime2text()
SSeconomy.add_transaction_log(authenticated_account,T)
-
+ intent_message(MACHINE_SOUND)
to_chat(user, "You insert [I] into [src].")
src.attack_hand(user)
qdel(I)
@@ -336,6 +337,7 @@ log transactions
// spawn_money(amount,src.loc)
spawn_ewallet(amount,src.loc,usr)
+ intent_message(MACHINE_SOUND)
//create an entry in the account transaction log
var/datum/transaction/T = new()
@@ -361,6 +363,7 @@ log transactions
authenticated_account.money -= amount
spawn_money(amount,src.loc,usr)
+ intent_message(MACHINE_SOUND)
//create an entry in the account transaction log
var/datum/transaction/T = new()
diff --git a/code/modules/heavy_vehicle/equipment/utility.dm b/code/modules/heavy_vehicle/equipment/utility.dm
index c3aae9f5a1f..35f2717824e 100644
--- a/code/modules/heavy_vehicle/equipment/utility.dm
+++ b/code/modules/heavy_vehicle/equipment/utility.dm
@@ -100,7 +100,7 @@
return
- owner.visible_message(SPAN_NOTICE("\The [owner] begins loading \the [O]."))
+ owner.visible_message(SPAN_NOTICE("\The [owner] begins loading \the [O]."), intent_message = MACHINE_SOUND)
if(do_after(user, 2 SECONDS, act_target = owner, extra_checks = CALLBACK(GLOBAL_PROC, .proc/atom_maintain_position, O, O.loc)))
O.forceMove(src)
carrying += O
diff --git a/code/modules/mining/machine_stacking.dm b/code/modules/mining/machine_stacking.dm
index 54768785a7a..8d07975e0a0 100644
--- a/code/modules/mining/machine_stacking.dm
+++ b/code/modules/mining/machine_stacking.dm
@@ -195,4 +195,5 @@
for(var/sheet in stack_storage)
if(stack_storage[sheet] >= stack_amt)
new sheet(output, stack_amt)
- stack_storage[sheet] -= stack_amt
\ No newline at end of file
+ stack_storage[sheet] -= stack_amt
+ intent_message(MACHINE_SOUND)
\ No newline at end of file
diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm
index 6a1aaaa72f7..a1948705cb0 100644
--- a/code/modules/mining/machine_vending.dm
+++ b/code/modules/mining/machine_vending.dm
@@ -215,6 +215,7 @@ var/global/list/minevendor_list = list( //keep in order of price
if(prize.amount != -1)
prize.amount--
new prize.equipment_path(get_turf(src))
+ intent_message(MACHINE_SOUND)
updateUsrDialog()
return
diff --git a/code/modules/mob/living/carbon/alien/alien_damage.dm b/code/modules/mob/living/carbon/alien/alien_damage.dm
index 99c5e52f75d..2eb274c75da 100644
--- a/code/modules/mob/living/carbon/alien/alien_damage.dm
+++ b/code/modules/mob/living/carbon/alien/alien_damage.dm
@@ -17,8 +17,7 @@
f_loss += 60
- ear_damage += 30
- ear_deaf += 120
+ adjustEarDamage(30, 120, 0)
if(3.0)
b_loss += 30
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 82a59ea182a..77d9a2ada57 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -375,6 +375,9 @@
msg += "*---------*"
+ if(src in intent_listener)
+ msg += SPAN_NOTICE("\n[get_pronoun("He")] looks like [get_pronoun("he")] [get_pronoun("is")] listening intently to [get_pronoun("his")] surroundings.")
+
var/datum/vampire/V = get_antag_datum(MODE_VAMPIRE)
if(V && (V.status & VAMP_DRAINING))
var/obj/item/grab/G = get_active_hand()
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 4229446f993..d262943ea7d 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -30,6 +30,8 @@
name = real_name
if(mind)
mind.name = real_name
+ if(get_hearing_sensitivity())
+ verbs += /mob/living/carbon/human/proc/listening_close
// Randomize nutrition and hydration. Defines are in __defines/mobs.dm
if(max_nutrition > 0)
@@ -96,6 +98,7 @@
/mob/living/carbon/human/Destroy()
human_mob_list -= src
+ intent_listener -= src
for(var/organ in organs)
qdel(organ)
organs = null
@@ -247,16 +250,15 @@
f_loss = 60
if (!istype(l_ear, /obj/item/clothing/ears/earmuffs) && !istype(r_ear, /obj/item/clothing/ears/earmuffs))
- ear_damage += 30
- ear_deaf += 120
+ adjustEarDamage(30, 120)
+
if (prob(70))
Paralyse(10)
if(3.0)
b_loss = 30
if (!istype(l_ear, /obj/item/clothing/ears/earmuffs) && !istype(r_ear, /obj/item/clothing/ears/earmuffs))
- ear_damage += 15
- ear_deaf += 60
+ adjustEarDamage(15, 60)
if (prob(50))
Paralyse(10)
@@ -2077,3 +2079,50 @@
var/obj/item/organ/internal/eyes/night/N = E
if(N.night_vision )
N.disable_night_vision()
+
+/mob/living/carbon/human/adjustEarDamage(var/damage, var/deaf, var/ringing = FALSE)
+ if (damage > 0)
+ var/hearing_sensitivity = get_hearing_sensitivity()
+ if (hearing_sensitivity)
+ if (is_listening()) // if the person is listening in, the effect is way worse
+ if (hearing_sensitivity == HEARING_VERY_SENSITIVE)
+ damage *= 2
+ else
+ damage = round(damage *= 1.5, 1)
+ stop_listening()
+ else
+ if (hearing_sensitivity == HEARING_VERY_SENSITIVE)
+ damage = round(damage *= 1.4, 1)
+ else
+ damage = round(damage *= 1.2, 1)
+ return ..()
+
+// Intensity 1: mild, 2: hurts, 3: very painful, 4: extremely painful, 5: that's going to leave some damage
+// Sensitive_only: If yes, only those with sensitive hearing are affected
+// Listening_pain: Increases the intensity by the listed amount if the person is listening in
+/mob/living/carbon/human/proc/earpain(var/intensity, var/sensitive_only = FALSE, var/listening_pain = 0)
+ if (ear_deaf)
+ return
+ if (sensitive_only && !get_hearing_sensitivity())
+ return
+ if (listening_pain && is_listening())
+ intensity += listening_pain
+ else if (sensitive_only)
+ return
+
+ var/obj/item/organ/external/E = organs_by_name[BP_HEAD]
+ switch (intensity)
+ if (1)
+ custom_pain("Your ears hurt a little.", 5, FALSE, E, 0)
+ if (2)
+ custom_pain("Your ears hurt!", 10, TRUE, E, 0)
+ if (3)
+ custom_pain("Your ears hurt badly!", 40, TRUE, E, 0)
+ if (4)
+ custom_pain("Your ears begin to ring faintly from the pain!", 70, TRUE, E, 0)
+ adjustEarDamage(5, 0, FALSE)
+ stop_listening()
+ if (5)
+ custom_pain("YOUR EARS ARE DEAFENED BY THE PAIN!", 110, TRUE, E, 1)
+ adjustEarDamage(5, 5, FALSE)
+ stop_listening()
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index f9b9841e964..7c012da5051 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -309,6 +309,14 @@
return TRUE
return FALSE
+/mob/living/carbon/human/proc/get_hearing_sensitivity()
+ return species.hearing_sensitivity
+
+/mob/living/carbon/human/proc/is_listening()
+ if(src in intent_listener)
+ return TRUE
+ return FALSE
+
/mob/living/carbon/human/get_organ_name_from_zone(var/def_zone)
var/obj/item/organ/external/E = organs_by_name[parse_zone(def_zone)]
if(E)
diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm
index 1faa06ed38b..81282e596ff 100644
--- a/code/modules/mob/living/carbon/human/human_powers.dm
+++ b/code/modules/mob/living/carbon/human/human_powers.dm
@@ -606,6 +606,13 @@ mob/living/carbon/human/proc/change_monitor()
visible_message("\The [src] shrieks!")
playsound(src.loc, 'sound/species/revenant/grue_screech.ogg', 100, 1)
+ for (var/mob/living/carbon/human/T in hearers(4, src) - src)
+ if(T.protected_from_sound())
+ continue
+ if (T.get_hearing_sensitivity() == HEARING_VERY_SENSITIVE)
+ earpain(2, TRUE, 1)
+ else if (T in range(src, 2))
+ earpain(1, TRUE, 1)
for(var/obj/machinery/light/L in range(7))
L.broken()
@@ -779,30 +786,38 @@ mob/living/carbon/human/proc/change_monitor()
set desc = "Emit a powerful screech which stuns hearers in a two-tile radius."
if(last_special > world.time)
- to_chat(src, "You are too tired to screech!")
+ to_chat(src, SPAN_DANGER("You are too tired to screech!"))
return
if(stat || paralysis || stunned || weakened)
- to_chat(src, "You cannot screech in your current state!")
+ to_chat(src, SPAN_DANGER("You cannot screech in your current state!"))
return
last_special = world.time + 100
- visible_message("[src.name] lets out an ear piercing shriek!",
- "You let out an ear-shattering shriek!",
- "You hear a painfully loud shriek!")
+ visible_message(SPAN_DANGER("[src.name] lets out an ear piercing shriek!"),
+ SPAN_DANGER("You let out an ear-shattering shriek!"),
+ SPAN_DANGER("You hear a painfully loud shriek!"))
playsound(loc, 'sound/voice/shriek1.ogg', 100, 1)
var/list/victims = list()
+ for (var/mob/living/carbon/human/T in hearers(4, src) - src)
+ if(T.protected_from_sound())
+ continue
+ if (T.get_hearing_sensitivity() == HEARING_VERY_SENSITIVE)
+ earpain(3, TRUE, 1)
+ else if (T in range(src, 2))
+ earpain(2, TRUE, 2)
+
for (var/mob/living/carbon/human/T in hearers(2, src) - src)
if(T.protected_from_sound())
continue
- to_chat(T, "You hear an ear piercing shriek and feel your senses go dull!")
+ to_chat(T, SPAN_DANGER("You hear an ear piercing shriek and feel your senses go dull!"))
T.Weaken(5)
- T.ear_deaf = 20
+ T.adjustEarDamage(10, 20)
T.stuttering = 20
T.Stun(5)
@@ -1239,4 +1254,37 @@ mob/living/carbon/human/proc/change_monitor()
if(stat == DEAD)
to_chat(M, SPAN_WARNING("You can't name a corpse."))
return FALSE
- return TRUE
\ No newline at end of file
+ return TRUE
+
+/mob/living/carbon/human/proc/intent_listen(var/source,var/message)
+ if(air_sound(src))
+ if (is_listening() && (ear_deaf <= 0 || !ear_deaf))
+ var/sound_dir = angle2text(Get_Angle(get_turf(src), get_turf(source)))
+ to_chat(src, SPAN_WARNING(message + " from \the [sound_dir]."))
+
+/mob/living/carbon/human/proc/listening_close()
+ set category = "Abilities"
+ set name = "Listen closely"
+
+ if (last_special > world.time)
+ return
+
+ if (stat || paralysis || stunned || weakened)
+ return
+
+ if (!is_listening())
+ start_listening()
+ else
+ stop_listening()
+
+ last_special = world.time + 20
+
+/mob/living/carbon/human/proc/start_listening()
+ if (!is_listening())
+ visible_message("[src] begins to listen intently.")
+ intent_listener |= src
+
+/mob/living/carbon/human/proc/stop_listening()
+ if (is_listening())
+ visible_message("[src] stops listening intently.")
+ intent_listener -= src
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index 1835261d3b3..9c4593a04fe 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -94,6 +94,7 @@
var/break_cuffs = FALSE //used in resist.dm to check if they can break hand/leg cuffs
var/natural_climbing = FALSE //If true, the species always succeeds at climbing.
var/climb_coeff = 1.25 //The coefficient to the climbing speed of the individual = 60 SECONDS * climb_coeff
+
// Death vars.
var/respawn_type = CREW
var/meat_type = /obj/item/reagent_containers/food/snacks/meat/human
@@ -208,6 +209,10 @@
var/bp_base_systolic = 120
var/bp_base_disatolic = 80
+ // Hearing sensitivity
+ var/hearing_sensitivity = HEARING_NORMAL
+
+ // Eating & nutrition related stuff
var/gluttonous = 0 // Can eat some mobs. Values can be GLUT_TINY, GLUT_SMALLER, GLUT_ANYTHING, GLUT_ITEM_TINY, GLUT_ITEM_NORMAL, GLUT_ITEM_ANYTHING, GLUT_PROJECTILE_VOMIT
var/stomach_capacity = 5 // How much stuff they can stick in their stomach
var/allowed_eat_types = TYPE_ORGANIC
diff --git a/code/modules/mob/living/carbon/human/species/station/tajara/tajara.dm b/code/modules/mob/living/carbon/human/species/station/tajara/tajara.dm
index 1ad310ad1b4..d37e793cb41 100644
--- a/code/modules/mob/living/carbon/human/species/station/tajara/tajara.dm
+++ b/code/modules/mob/living/carbon/human/species/station/tajara/tajara.dm
@@ -48,8 +48,10 @@
low_pulse = 50 // Default 40
norm_pulse = 70 // Default 60
fast_pulse = 100 // Default 90
- v_fast_pulse = 130// Default 120
- max_pulse = 170// Default 160
+ v_fast_pulse = 130 // Default 120
+ max_pulse = 170 // Default 160
+
+ hearing_sensitivity = HEARING_SENSITIVE // Default HEARING_NORMAL
blurb = "The Tajaran race is a species of feline-like bipeds hailing from the planet of Adhomai in the S'rendarr \
system. They have been brought up into the space age by the Humans and Skrell, who alledgedly influenced their \
diff --git a/code/modules/mob/living/carbon/human/species/station/tajara/tajaran_subspecies.dm b/code/modules/mob/living/carbon/human/species/station/tajara/tajaran_subspecies.dm
index a609f31fd01..96b5415f281 100644
--- a/code/modules/mob/living/carbon/human/species/station/tajara/tajaran_subspecies.dm
+++ b/code/modules/mob/living/carbon/human/species/station/tajara/tajaran_subspecies.dm
@@ -61,6 +61,7 @@
heat_level_2 = 390 //RaceDefault 380 Default 400
heat_level_3 = 900 //RaceDefault 800 Default 1000
+ hearing_sensitivity = HEARING_VERY_SENSITIVE // Species default 1
default_h_style = "M'sai Ears"
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index d1b120840e4..27ecece7d59 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -846,11 +846,24 @@ default behaviour is:
..()
//damage/heal the mob ears and adjust the deaf amount
-/mob/living/adjustEarDamage(var/damage, var/deaf)
+/mob/living/adjustEarDamage(var/damage, var/deaf, var/ringing = FALSE)
+ var/alreadydeaf = FALSE
+ if (ear_deaf)
+ alreadydeaf = TRUE
+
ear_damage = max(0, ear_damage + damage)
ear_deaf = max(0, ear_deaf + deaf)
+ if (ringing && !alreadydeaf)
+ if (ear_damage >= 5)
+ if (ear_damage >= 15)
+ to_chat(src, SPAN_DANGER("Your ears start to ring badly!"))
+ else
+ to_chat(src, SPAN_DANGER("Your ears start to ring!"))
+
+
//pass a negative argument to skip one of the variable
+
/mob/living/setEarDamage(var/damage, var/deaf)
if(damage >= 0)
ear_damage = damage
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
index ca54ddecf4c..c1bdac03ab6 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
@@ -90,6 +90,7 @@
announce_ghost_joinleave(player, 0, "They have taken control over a maintenance drone.")
visible_message(SPAN_NOTICE("\The [src] churns and grinds as it lurches into motion, disgorging a shiny new drone after a few moments."))
flick("h_lathe_leave", src)
+ intent_message(MACHINE_SOUND)
time_last_drone = world.time
if(player.mob?.mind)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 657a14b4ad7..3a94ce9d4b6 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -110,7 +110,7 @@
// self_message (optional) is what the src mob sees e.g. "You do something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
-/mob/visible_message(var/message, var/self_message, var/blind_message, var/range = world.view, var/show_observers = TRUE)
+/mob/visible_message(var/message, var/self_message, var/blind_message, var/range = world.view, var/show_observers = TRUE, var/intent_message = null, var/intent_range = 7)
var/list/messageturfs = list() //List of turfs we broadcast to.
var/list/messagemobs = list() //List of living mobs nearby who can hear it, and distant ghosts who've chosen to hear it
var/list/messageobjs = list() //list of objs nearby who can see it
@@ -151,6 +151,9 @@
var/obj/O = o
O.see_emote(src, message)
+ if(intent_message)
+ intent_message(intent_message, intent_range)
+
// Designed for mobs contained inside things, where a normal visible message wont actually be visible
// Useful for visible actions by pAIs, and held mobs
// Broadcaster is the place the action will be seen/heard from, mobs in sight of THAT will see the message. This is generally the object or mob that src is contained in
diff --git a/code/modules/modular_computers/laptop_vendor.dm b/code/modules/modular_computers/laptop_vendor.dm
index 3e37394ae42..89aa7c739a5 100644
--- a/code/modules/modular_computers/laptop_vendor.dm
+++ b/code/modules/modular_computers/laptop_vendor.dm
@@ -305,6 +305,7 @@
fabricated_tablet.forceMove(src.loc)
fabricated_tablet = null
ping(message)
+ intent_message(MACHINE_SOUND)
state = 3
// Simplified payment processing, returns 1 on success.
diff --git a/code/modules/paperwork/papershredder.dm b/code/modules/paperwork/papershredder.dm
index cabb32b3982..a7033255a23 100644
--- a/code/modules/paperwork/papershredder.dm
+++ b/code/modules/paperwork/papershredder.dm
@@ -56,6 +56,7 @@
qdel(W)
playsound(src.loc, 'sound/bureaucracy/papershred.ogg', 75, 1)
to_chat(user, SPAN_NOTICE("You shred the paper."))
+ intent_message(MACHINE_SOUND)
if(paperamount > max_paper)
to_chat(user, SPAN_DANGER("\The [src] was too full, and shredded paper goes everywhere!"))
for(var/i=(paperamount-max_paper);i>0;i--)
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 74245922dc2..41d0f8a8051 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -1037,6 +1037,7 @@
if (href_list["emergency_lights"])
emergency_lights = !emergency_lights
+ intent_message(BUTTON_FLICK, 5)
for (var/obj/machinery/light/L in area)
if (!initial(L.no_emergency))
L.no_emergency = emergency_lights //If there was an override set on creation, keep that override
@@ -1046,17 +1047,20 @@
if (href_list["lock"])
coverlocked = !coverlocked
+ intent_message(BUTTON_FLICK, 5)
else if (href_list["breaker"])
toggle_breaker()
else if( href_list["reboot"] )
failure_timer = 0
+ intent_message(BUTTON_FLICK, 5)
update_icon()
update()
else if (href_list["cmode"])
chargemode = !chargemode
+ intent_message(BUTTON_FLICK, 5)
if(!chargemode)
charging = CHARGING_OFF
update_icon()
@@ -1071,6 +1075,7 @@
lighting = setsubsystem(val)
if("Environment")
environ = setsubsystem(val)
+ intent_message(BUTTON_FLICK, 5)
update_icon()
update()
@@ -1094,6 +1099,7 @@
operating = !operating
update()
update_icon()
+ intent_message(BUTTON_FLICK)
/obj/machinery/power/apc/proc/ion_act()
if(prob(3))
@@ -1387,6 +1393,7 @@
night_mode = 0
else
night_mode = !night_mode
+ intent_message(BUTTON_FLICK, 5)
/obj/machinery/power/apc/proc/setsubsystem(val)
if(cell && cell.charge > 0)
diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm
index f7b94e6e81b..092ae5d82dc 100644
--- a/code/modules/reagents/Chemistry-Machinery.dm
+++ b/code/modules/reagents/Chemistry-Machinery.dm
@@ -510,6 +510,7 @@
do_hair_pull(user)
playsound(get_turf(src), 'sound/machines/blender.ogg', 50, 1)
+ intent_message(MACHINE_SOUND)
inuse = TRUE
// Reset the machine.
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
index 5ed71735c66..25634affefa 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
@@ -877,6 +877,23 @@
if(prob(2))
to_chat(M, SPAN_WARNING("You feel very cold..."))
+/decl/reagent/inacusiate
+ name = "Inacusiate"
+ description = ""
+ reagent_state = LIQUID
+ color = "#D2B48C"
+ overdose = 10
+ scannable = TRUE
+ metabolism = REM * 1
+ taste_description = "a roll of gauze"
+
+/decl/reagent/inacusiate/affect_blood(var/mob/living/carbon/M, var/alien, var/removed, var/datum/reagents/holder)
+ M.adjustEarDamage(-0.6, -0.6, FALSE)
+
+/decl/reagent/inacusiate/overdose(var/mob/living/carbon/M, var/alien, var/removed, var/datum/reagents/holder)
+ var/obj/item/organ/external/E = M.organs_by_name[BP_HEAD]
+ M.custom_pain("Your head hurts a ton!", 70, FALSE, E, 1)
+
/* mental */
#define MEDICATION_MESSAGE_DELAY 10 MINUTES
diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm
index 08bdf4a9f3d..d94c1bdab78 100644
--- a/code/modules/reagents/Chemistry-Recipes.dm
+++ b/code/modules/reagents/Chemistry-Recipes.dm
@@ -665,6 +665,13 @@
required_reagents = list(/decl/reagent/carbon = 1, /decl/reagent/tungsten = 1, /decl/reagent/water = 1)
result_amount = 3
+/datum/chemical_reaction/inacusiate
+ name = "Inacusiate"
+ id = "inacusiate"
+ result = /decl/reagent/inacusiate
+ required_reagents = list(/decl/reagent/dylovene = 1, /decl/reagent/carbon = 1, /decl/reagent/sulfur = 1)
+ result_amount = 2
+
//Mental Medication
/datum/chemical_reaction/corophenidate
diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm
index 66b6078de61..b78e83e39d8 100644
--- a/code/modules/recycling/disposal.dm
+++ b/code/modules/recycling/disposal.dm
@@ -522,6 +522,8 @@
flush = FALSE
return
+ intent_message(MACHINE_SOUND)
+
flushing = 1
flick("[icon_state]-flush", src)
@@ -1542,6 +1544,7 @@
playsound(src, 'sound/machines/warning-buzzer.ogg', 50, 0, 0)
sleep(20) //wait until correct animation frame
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
+ intent_message(THUNK_SOUND)
if(H)
for(var/atom/movable/AM in H)
diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm
index b1ff3976b33..b4106dc767c 100644
--- a/code/modules/research/protolathe.dm
+++ b/code/modules/research/protolathe.dm
@@ -200,6 +200,8 @@
for(var/C in D.chemicals)
reagents.remove_reagent(C, D.chemicals[C] * mat_efficiency)
+ intent_message(MACHINE_SOUND)
+
if(D.build_path)
var/obj/new_item = D.Fabricate(src, src)
new_item.forceMove(loc)
diff --git a/code/modules/tables/flipping.dm b/code/modules/tables/flipping.dm
index fcdab37c95e..725d399dc88 100644
--- a/code/modules/tables/flipping.dm
+++ b/code/modules/tables/flipping.dm
@@ -25,7 +25,7 @@
to_chat(usr, "It won't budge.")
return
- usr.visible_message("[usr] flips \the [src]!")
+ usr.visible_message(SPAN_WARNING("[usr] flips \the [src]!"), intent_message = THUNK_SOUND)
if(climbable)
structure_shaken()
diff --git a/code/modules/tables/interactions.dm b/code/modules/tables/interactions.dm
index 21ba97aff98..af8f8158ac4 100644
--- a/code/modules/tables/interactions.dm
+++ b/code/modules/tables/interactions.dm
@@ -44,7 +44,7 @@
visible_message("[P] hits \the [src]!")
return 0
else
- visible_message("[src] breaks down!")
+ visible_message(SPAN_WARNING("[src] breaks down!"))
break_to_parts()
return 1
return 1
diff --git a/code/modules/tables/tables.dm b/code/modules/tables/tables.dm
index 574090ace9f..ee0096168df 100644
--- a/code/modules/tables/tables.dm
+++ b/code/modules/tables/tables.dm
@@ -47,7 +47,7 @@
amount *= TABLE_BRITTLE_MATERIAL_MULTIPLIER
health -= amount
if(health <= 0)
- visible_message("\The [src] breaks down!")
+ visible_message(SPAN_WARNING("\The [src] breaks down!"), intent_message = THUNK_SOUND)
return break_to_parts() // if we break and form shards, return them to the caller to do !FUN! things with
diff --git a/html/changelogs/HearingTime.yml b/html/changelogs/HearingTime.yml
new file mode 100644
index 00000000000..38b587f1e6c
--- /dev/null
+++ b/html/changelogs/HearingTime.yml
@@ -0,0 +1,9 @@
+author: TheGreyWolf
+
+delete-after: True
+
+changes:
+ - rscadd: "Added hearing sensitivity. Species with hearing sensitivity (atm only tajara) will risk taking more hearing based damage from various sources including flashbangs. They also get a special ability to listen in which lets them hear various machinery being activated around them even if they can't see it, and to get an extra range at which explosions can be heard to help determine the distance to them."
+ - rscadd: "Medical can now create inacusiate by mixing dylovene, carbon and sulfur. This medicine will help heal any hearing based damage when injected, but is very painful if overdosing by 10u or more."
+ - bugfix: "Explosions now more accurately tells the direction in chat."
+ - bugfix: "Megaphones now properly do audible messages rather than vision based ones."