diff --git a/code/modules/surgery/organs/internal/ears/_ears.dm b/code/modules/surgery/organs/internal/ears/_ears.dm
index 8e9c7ae70a7..6bdf093dd47 100644
--- a/code/modules/surgery/organs/internal/ears/_ears.dm
+++ b/code/modules/surgery/organs/internal/ears/_ears.dm
@@ -15,17 +15,16 @@
now_fixed = "Noise slowly begins filling your ears once more."
low_threshold_cleared = "The ringing in your ears has died down."
- // `deaf` measures "ticks" of deafness. While > 0, the person is unable
- // to hear anything.
+ /// `deaf` measures "ticks" of deafness. While > 0, the person is unable to hear anything.
var/deaf = 0
// `damage` in this case measures long term damage to the ears, if too high,
// the person will not have either `deaf` or `ear_damage` decrease
// without external aid (earmuffs, drugs)
- //Resistance against loud noises
+ /// Resistance against loud noises
var/bang_protect = 0
- // Multiplier for both long term and short term ear damage
+ /// Multiplier for both long term and short term ear damage
var/damage_multiplier = 1
/obj/item/organ/internal/ears/on_life(seconds_per_tick, times_fired)
@@ -34,28 +33,98 @@
to_chat(owner, span_warning("The ringing in your ears grows louder, blocking out any external noises for a moment."))
. = ..()
- // if we have non-damage related deafness like mutations, quirks or clothing (earmuffs), don't bother processing here. Ear healing from earmuffs or chems happen elsewhere
+ // if we have non-damage related deafness like mutations, quirks or clothing (earmuffs), don't bother processing here.
+ // Ear healing from earmuffs or chems happen elsewhere
if(HAS_TRAIT_NOT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE))
return
+ // no healing if failing
+ if(organ_flags & ORGAN_FAILING)
+ return
+ adjustEarDamage(0, -0.5 * seconds_per_tick)
+ if((damage > low_threshold) && SPT_PROB(damage / 60, seconds_per_tick))
+ adjustEarDamage(0, 4)
+ SEND_SOUND(owner, sound('sound/weapons/flash_ring.ogg'))
- if((organ_flags & ORGAN_FAILING))
- deaf = max(deaf, 1) // if we're failing we always have at least 1 deaf stack (and thus deafness)
- else // only clear deaf stacks if we're not failing
- deaf = max(deaf - (0.5 * seconds_per_tick), 0)
- if((damage > low_threshold) && SPT_PROB(damage / 60, seconds_per_tick))
- adjustEarDamage(0, 4)
- SEND_SOUND(owner, sound('sound/weapons/flash_ring.ogg'))
+/obj/item/organ/internal/ears/apply_organ_damage(damage_amount, maximum, required_organ_flag)
+ . = ..()
+ update_temp_deafness()
- if(deaf)
- ADD_TRAIT(owner, TRAIT_DEAF, EAR_DAMAGE)
+/obj/item/organ/internal/ears/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
+ . = ..()
+ update_temp_deafness()
+
+/obj/item/organ/internal/ears/on_mob_remove(mob/living/carbon/organ_owner, special)
+ . = ..()
+ UnregisterSignal(organ_owner, COMSIG_MOB_SAY)
+ REMOVE_TRAIT(organ_owner, TRAIT_DEAF, EAR_DAMAGE)
+
+/**
+ * Snowflake proc to handle temporary deafness
+ *
+ * * ddmg: Handles normal organ damage
+ * * ddeaf: Handles temporary deafness, 1 ddeaf = 2 seconds of deafness, by default (with no multiplier)
+ */
+/obj/item/organ/internal/ears/proc/adjustEarDamage(ddmg = 0, ddeaf = 0)
+ if(owner.status_flags & GODMODE)
+ update_temp_deafness()
+ return
+
+ var/mod_damage = ddmg > 0 ? (ddmg * damage_multiplier) : ddmg
+ if(mod_damage)
+ apply_organ_damage(mod_damage)
+ var/mod_deaf = ddeaf > 0 ? (ddeaf * damage_multiplier) : ddeaf
+ if(mod_deaf)
+ deaf = max(deaf + mod_deaf, 0)
+ update_temp_deafness()
+
+/// Updates status of deafness
+/obj/item/organ/internal/ears/proc/update_temp_deafness()
+ // if we're failing we always have at least some deaf stacks (and thus deafness)
+ if(organ_flags & ORGAN_FAILING)
+ deaf = max(deaf, 1 * damage_multiplier)
+
+ if(isnull(owner))
+ return
+
+ if(owner.status_flags & GODMODE)
+ deaf = 0
+
+ if(deaf > 0)
+ if(!HAS_TRAIT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE))
+ RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(adjust_speech))
+ ADD_TRAIT(owner, TRAIT_DEAF, EAR_DAMAGE)
else
REMOVE_TRAIT(owner, TRAIT_DEAF, EAR_DAMAGE)
+ UnregisterSignal(owner, COMSIG_MOB_SAY)
-/obj/item/organ/internal/ears/proc/adjustEarDamage(ddmg, ddeaf)
- if(owner.status_flags & GODMODE)
+/// Being deafened by loud noises makes you shout
+/obj/item/organ/internal/ears/proc/adjust_speech(datum/source, list/speech_args)
+ SIGNAL_HANDLER
+
+ if(HAS_TRAIT_NOT_FROM(source, TRAIT_DEAF, EAR_DAMAGE))
return
- set_organ_damage(clamp(damage + (ddmg * damage_multiplier), 0, maxHealth))
- deaf = max(deaf + (ddeaf * damage_multiplier), 0)
+ if(HAS_TRAIT(source, TRAIT_SIGN_LANG))
+ return
+
+ var/message = speech_args[SPEECH_MESSAGE]
+ // Replace only end-of-sentence punctuation with exclamation marks (hence the empty space)
+ // We don't wanna mess with things like ellipses
+ message = replacetext(message, ". ", "! ")
+ message = replacetext(message, "? ", "?! ")
+ // Special case for the last character
+ switch(copytext_char(message, -1))
+ if(".")
+ if(copytext_char(message, -2) != "..") // Once again ignoring ellipses, let people trail off
+ message = copytext_char(message, 1, -1) + "!"
+ if("?")
+ message = copytext_char(message, 1, -1) + "?!"
+ if("!")
+ pass()
+ else
+ message += "!"
+
+ speech_args[SPEECH_MESSAGE] = message
+ return COMPONENT_UPPERCASE_SPEECH
/obj/item/organ/internal/ears/invincible
damage_multiplier = 0