diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index 5973fb25111..e0cd34d8065 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -123,6 +123,7 @@ #define GENETICS_SPELL "genetics_spell" #define EYES_COVERED "eyes_covered" #define NO_EYES "no_eyes" +#define NO_EARS "no_ears" #define HYPNOCHAIR_TRAIT "hypnochair" #define FLASHLIGHT_EYES "flashlight_eyes" #define IMPURE_OCULINE "impure_oculine" diff --git a/code/__HELPERS/honkerblast.dm b/code/__HELPERS/honkerblast.dm index e76d8178228..c3926d421b0 100644 --- a/code/__HELPERS/honkerblast.dm +++ b/code/__HELPERS/honkerblast.dm @@ -8,7 +8,7 @@ playsound(origin_turf, 'sound/items/airhorn/airhorn.ogg', 100, TRUE) for(var/mob/living/carbon/victim in hearers(max(light_range, medium_range, heavy_range), origin_turf)) - if(!victim.can_hear()) + if(HAS_TRAIT(victim, TRAIT_DEAF)) continue var/distance = get_dist(origin_turf, victim.loc) if(distance <= heavy_range) diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm index bbb0d9db5ba..e1be4c7ad05 100644 --- a/code/__HELPERS/priority_announce.dm +++ b/code/__HELPERS/priority_announce.dm @@ -192,7 +192,7 @@ var/datum/callback/should_play_sound_callback = astype(should_play_sound) for(var/mob/target in players) - if(isnewplayer(target) || !target.can_hear()) + if(isnewplayer(target) || HAS_TRAIT(target, TRAIT_DEAF)) continue to_chat(target, announcement) diff --git a/code/controllers/subsystem/ambience.dm b/code/controllers/subsystem/ambience.dm index f49604b058a..88db3ffcc33 100644 --- a/code/controllers/subsystem/ambience.dm +++ b/code/controllers/subsystem/ambience.dm @@ -27,7 +27,7 @@ SUBSYSTEM_DEF(ambience) client_old_areas -= client_iterator continue - if(!client_mob.can_hear()) //WHAT? I CAN'T HEAR YOU + if(HAS_TRAIT(client_mob, TRAIT_DEAF)) //WHAT? I CAN'T HEAR YOU continue //Check to see if the client-mob is in a valid area @@ -126,7 +126,7 @@ SUBSYSTEM_DEF(ambience) client.current_ambient_sound = null return - if(!can_hear()) // Can the mob hear? + if(HAS_TRAIT(src, TRAIT_DEAF)) // Can the mob hear? SEND_SOUND(src, sound(null, repeat = 0, wait = 0, channel = CHANNEL_BUZZ)) client.current_ambient_sound = null return diff --git a/code/datums/brain_damage/hypnosis.dm b/code/datums/brain_damage/hypnosis.dm index 05c98b0ec30..d789a7d142c 100644 --- a/code/datums/brain_damage/hypnosis.dm +++ b/code/datums/brain_damage/hypnosis.dm @@ -76,6 +76,6 @@ ) /datum/brain_trauma/hypnosis/handle_hearing(datum/source, list/hearing_args) - if(!owner.can_hear() || owner == hearing_args[HEARING_SPEAKER]) + if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == hearing_args[HEARING_SPEAKER]) return hearing_args[HEARING_RAW_MESSAGE] = target_phrase.Replace(hearing_args[HEARING_RAW_MESSAGE], span_hypnophrase("$1")) diff --git a/code/datums/brain_damage/mild.dm b/code/datums/brain_damage/mild.dm index 3db89c03880..993ddea4ebb 100644 --- a/code/datums/brain_damage/mild.dm +++ b/code/datums/brain_damage/mild.dm @@ -256,7 +256,7 @@ var/list/speak_dejavu = list() /datum/brain_trauma/mild/mind_echo/handle_hearing(datum/source, list/hearing_args) - if(!owner.can_hear() || owner == hearing_args[HEARING_SPEAKER]) + if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == hearing_args[HEARING_SPEAKER]) return if(hear_dejavu.len >= 5) diff --git a/code/datums/brain_damage/severe.dm b/code/datums/brain_damage/severe.dm index 522bc2479c6..3e6f0e6691b 100644 --- a/code/datums/brain_damage/severe.dm +++ b/code/datums/brain_damage/severe.dm @@ -294,7 +294,7 @@ owner.remove_status_effect(/datum/status_effect/trance) /datum/brain_trauma/severe/hypnotic_trigger/handle_hearing(datum/source, list/hearing_args) - if(!owner.can_hear() || owner == hearing_args[HEARING_SPEAKER]) + if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == hearing_args[HEARING_SPEAKER]) return var/regex/reg = new("(\\b[REGEX_QUOTE(trigger_phrase)]\\b)","ig") diff --git a/code/datums/brain_damage/split_personality.dm b/code/datums/brain_damage/split_personality.dm index 57c94e60b1d..3cedb77dcdb 100644 --- a/code/datums/brain_damage/split_personality.dm +++ b/code/datums/brain_damage/split_personality.dm @@ -235,7 +235,7 @@ return //no random switching /datum/brain_trauma/severe/split_personality/brainwashing/handle_hearing(datum/source, list/hearing_args) - if(!owner.can_hear() || owner == hearing_args[HEARING_SPEAKER] || !owner.has_language(hearing_args[HEARING_LANGUAGE])) + if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == hearing_args[HEARING_SPEAKER] || !owner.has_language(hearing_args[HEARING_LANGUAGE])) return var/message = hearing_args[HEARING_RAW_MESSAGE] diff --git a/code/datums/components/codeword_hearing.dm b/code/datums/components/codeword_hearing.dm index 0b171d9492e..a8ac051ab1c 100644 --- a/code/datums/components/codeword_hearing.dm +++ b/code/datums/components/codeword_hearing.dm @@ -42,7 +42,7 @@ return // don't skip codewords when owner speaks - if(!owner.can_hear() || !owner.has_language(hearing_args[HEARING_LANGUAGE])) + if(HAS_TRAIT(owner, TRAIT_DEAF) || !owner.has_language(hearing_args[HEARING_LANGUAGE])) return var/message = hearing_args[HEARING_RAW_MESSAGE] diff --git a/code/datums/components/fearful/sources/phobia.dm b/code/datums/components/fearful/sources/phobia.dm index e9303867769..155e949f298 100644 --- a/code/datums/components/fearful/sources/phobia.dm +++ b/code/datums/components/fearful/sources/phobia.dm @@ -101,7 +101,7 @@ return // Words can't trigger you if you can't hear them *taps head* - if(!owner.can_hear() || owner == hearing_args[HEARING_SPEAKER] || !owner.has_language(hearing_args[HEARING_LANGUAGE])) + if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == hearing_args[HEARING_SPEAKER] || !owner.has_language(hearing_args[HEARING_LANGUAGE])) return if(trigger_regex.Find(hearing_args[HEARING_RAW_MESSAGE])) diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index 2d5dbf84ea6..bfda885aba9 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -134,7 +134,7 @@ if(isnull(viewer.client)) continue if(!is_important && viewer != user && (!is_visual || !is_audible)) - if(is_audible && !viewer.can_hear()) + if(is_audible && HAS_TRAIT(viewer, TRAIT_DEAF)) continue if(is_visual && viewer.is_blind()) continue diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index cad5efca459..50a2e229273 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -369,7 +369,7 @@ status_type = STATUS_EFFECT_REFRESH /datum/status_effect/good_music/tick(seconds_between_ticks) - if(owner.can_hear()) + if(!HAS_TRAIT(owner, TRAIT_DEAF)) owner.adjust_dizzy(-4 SECONDS) owner.adjust_jitter(-4 SECONDS) owner.adjust_confusion(-1 SECONDS) diff --git a/code/datums/status_effects/debuffs/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm index 556a8e2e4dc..5d390a8035b 100644 --- a/code/datums/status_effects/debuffs/debuffs.dm +++ b/code/datums/status_effects/debuffs/debuffs.dm @@ -604,7 +604,7 @@ /datum/status_effect/trance/proc/hypnotize(datum/source, list/hearing_args) SIGNAL_HANDLER - if(!owner.can_hear() || owner == hearing_args[HEARING_SPEAKER]) + if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == hearing_args[HEARING_SPEAKER]) return var/mob/hearing_speaker = hearing_args[HEARING_SPEAKER] diff --git a/code/datums/voice_of_god_command.dm b/code/datums/voice_of_god_command.dm index 1b701432076..a49c7cb6c34 100644 --- a/code/datums/voice_of_god_command.dm +++ b/code/datums/voice_of_god_command.dm @@ -44,7 +44,7 @@ GLOBAL_LIST_INIT(voice_of_god_commands, init_voice_of_god_commands()) var/to_remove_string var/list/candidates = get_hearers_in_view(8, user) - (include_speaker ? null : user) for(var/mob/living/candidate in candidates) - if(candidate.stat != DEAD && candidate.can_hear()) + if(candidate.stat != DEAD && !HAS_TRAIT(candidate, TRAIT_DEAF)) if(candidate.can_block_magic(MAGIC_RESISTANCE_HOLY|MAGIC_RESISTANCE_MIND, charge_cost = 0)) to_chat(user, span_userdanger("Something's wrong! [candidate] seems to be resisting your commands.")) continue diff --git a/code/game/machinery/wall_vitals.dm b/code/game/machinery/wall_vitals.dm index c175fc98f48..51790a1e7bc 100644 --- a/code/game/machinery/wall_vitals.dm +++ b/code/game/machinery/wall_vitals.dm @@ -453,7 +453,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/vitals_reader/advanced, 32) /obj/machinery/vitals_reader/proc/beep_message(message) for(var/mob/viewer as anything in viewers(src)) - if(isnull(viewer.client) || !viewer.can_hear()) + if(isnull(viewer.client) || HAS_TRAIT(viewer, TRAIT_DEAF)) continue if(!viewer.runechat_prefs_check(viewer, EMOTE_MESSAGE)) continue diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm index c08b1c3fcd2..9b2537e205b 100644 --- a/code/game/objects/items/clown_items.dm +++ b/code/game/objects/items/clown_items.dm @@ -266,7 +266,7 @@ return var/turf/T = get_turf(src) for(M in ohearers(7, T)) - if(M.can_hear()) + if(!HAS_TRAIT(M, TRAIT_DEAF)) M.emote("flip") COOLDOWN_START(src, golden_horn_cooldown, 1 SECONDS) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index c7c9c94f8e3..9eb377ca8f9 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -369,7 +369,7 @@ if(isliving(talking_movable)) var/mob/living/talking_living = talking_movable var/volume_modifier = (talking_living.client?.prefs.read_preference(/datum/preference/numeric/volume/sound_radio_noise)) - if(radio_noise && talking_living.can_hear() && volume_modifier && signal.frequency != FREQ_COMMON && !LAZYACCESS(message_mods, MODE_SEQUENTIAL) && COOLDOWN_FINISHED(src, audio_cooldown)) + if(radio_noise && !HAS_TRAIT(talking_living, TRAIT_DEAF) && volume_modifier && signal.frequency != FREQ_COMMON && !LAZYACCESS(message_mods, MODE_SEQUENTIAL) && COOLDOWN_FINISHED(src, audio_cooldown)) COOLDOWN_START(src, audio_cooldown, 0.5 SECONDS) var/sound/radio_noise = sound('sound/items/radio/radio_talk.ogg', volume = volume_modifier) radio_noise.frequency = get_rand_frequency_low_range() diff --git a/code/game/sound/sound.dm b/code/game/sound/sound.dm index a3d086eac3a..451ee6d60a4 100644 --- a/code/game/sound/sound.dm +++ b/code/game/sound/sound.dm @@ -98,7 +98,7 @@ * * volume_preference - Optional: Will be checked to modify the volume of the sound. */ /mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff_exponent = SOUND_FALLOFF_EXPONENT, channel = 0, pressure_affected = TRUE, sound/sound_to_use, max_distance, falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, distance_multiplier = 1, use_reverb = TRUE, datum/preference/numeric/volume/volume_preference = null) - if(!client || !can_hear()) + if(!client || HAS_TRAIT(src, TRAIT_DEAF)) return if(!sound_to_use) diff --git a/code/modules/client/preferences/sounds.dm b/code/modules/client/preferences/sounds.dm index 3fa9c16ca34..e6434afdd32 100644 --- a/code/modules/client/preferences/sounds.dm +++ b/code/modules/client/preferences/sounds.dm @@ -20,6 +20,11 @@ savefile_key = "sound_breathing" savefile_identifier = PREFERENCE_PLAYER +/datum/preference/toggle/sound_breathing/apply_to_client_updated(client/client, value) + var/mob/living/carbon/carbon_mob = client.mob + if(istype(carbon_mob) && !value) + carbon_mob.breathing_loop.stop() + /// Controls hearing announcement sounds /datum/preference/toggle/sound_announcements category = PREFERENCE_CATEGORY_GAME_PREFERENCES diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index 49f5a7412b7..7d6df307725 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -270,7 +270,7 @@ switch (body_part) if(BODY_ZONE_CHEST)//Listening to the chest user.visible_message(span_notice("[user] places [src] against [carbon_patient]'s [body_part] and listens attentively."), ignored_mobs = user) - if(!user.can_hear()) + if(HAS_TRAIT(user, TRAIT_DEAF)) to_chat(user, span_notice("You place [src] against [carbon_patient]'s [body_part]. Fat load of good it does you though, since you can't hear.")) return else diff --git a/code/modules/economy/account.dm b/code/modules/economy/account.dm index 797dd9d3856..5c0f8b3fe9d 100644 --- a/code/modules/economy/account.dm +++ b/code/modules/economy/account.dm @@ -244,7 +244,7 @@ if(!card_holder.client || (!(get_chat_toggles(card_holder.client) & CHAT_BANKCARD) && !force)) return - if(card_holder.can_hear()) + if(!HAS_TRAIT(card_holder, TRAIT_DEAF)) card_holder.playsound_local(get_turf(card_holder), 'sound/machines/beep/twobeep_high.ogg', 50, TRUE) to_chat(card_holder, "[icon2html(icon_source, card_holder)] [span_notice("[message]")]") else if(isturf(card.loc)) //If on the ground @@ -252,7 +252,7 @@ for(var/mob/potential_hearer in hearers(1,card_location)) if(!potential_hearer.client || (!(get_chat_toggles(potential_hearer.client) & CHAT_BANKCARD) && !force)) continue - if(potential_hearer.can_hear()) + if(!HAS_TRAIT(potential_hearer, TRAIT_DEAF)) potential_hearer.playsound_local(card_location, 'sound/machines/beep/twobeep_high.ogg', 50, TRUE) to_chat(potential_hearer, "[icon2html(icon_source, potential_hearer)] [span_notice("[message]")]") else @@ -262,7 +262,7 @@ continue if(!sound_atom) sound_atom = card.drop_location() //in case we're inside a bodybag in a crate or something. doing this here to only process it if there's a valid mob who can hear the sound. - if(potential_hearer.can_hear()) + if(!HAS_TRAIT(potential_hearer, TRAIT_DEAF)) potential_hearer.playsound_local(get_turf(sound_atom), 'sound/machines/beep/twobeep_high.ogg', 50, TRUE) to_chat(potential_hearer, "[icon2html(icon_source, potential_hearer)] [span_notice("[message]")]") diff --git a/code/modules/fishing/fish/types/rift.dm b/code/modules/fishing/fish/types/rift.dm index 641336f0dbe..626be1ecde0 100644 --- a/code/modules/fishing/fish/types/rift.dm +++ b/code/modules/fishing/fish/types/rift.dm @@ -636,7 +636,7 @@ to_chat(screeched, span_notice("You resist the psychic wail!")) continue var/power = 1 - if(!screeched.can_hear()) // bit weaker if deaf. but its still psychic + if(HAS_TRAIT(screeched, TRAIT_DEAF)) // bit weaker if deaf. but its still psychic power *= 0.5 var/affect_time = 15 SECONDS * power // it really fucks you up diff --git a/code/modules/hallucination/battle.dm b/code/modules/hallucination/battle.dm index 985709b90d0..60e2555e387 100644 --- a/code/modules/hallucination/battle.dm +++ b/code/modules/hallucination/battle.dm @@ -5,7 +5,7 @@ hallucination_tier = HALLUCINATION_TIER_COMMON /datum/hallucination/battle/start() - if(!hallucinator.can_hear()) + if(HAS_TRAIT(hallucinator, TRAIT_DEAF)) return FALSE // for subtypes diff --git a/code/modules/hallucination/fake_sound.dm b/code/modules/hallucination/fake_sound.dm index 7b2e2ee8825..b7809548630 100644 --- a/code/modules/hallucination/fake_sound.dm +++ b/code/modules/hallucination/fake_sound.dm @@ -11,7 +11,7 @@ var/sound_type /datum/hallucination/fake_sound/start() - if(!hallucinator.can_hear()) + if(HAS_TRAIT(hallucinator, TRAIT_DEAF)) return FALSE var/sound_to_play = islist(sound_type) ? pick(sound_type) : sound_type diff --git a/code/modules/hallucination/station_message.dm b/code/modules/hallucination/station_message.dm index a8bddedcdad..33f20cb1014 100644 --- a/code/modules/hallucination/station_message.dm +++ b/code/modules/hallucination/station_message.dm @@ -8,7 +8,7 @@ var/require_hearing = TRUE /datum/hallucination/station_message/start() - if(require_hearing && !hallucinator.can_hear()) + if(require_hearing && HAS_TRAIT(hallucinator, TRAIT_DEAF)) return FALSE if(do_fake_alert() == CANCEL_FAKE_ALERT) return FALSE diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 5dac58d3123..5dc3cbd7d70 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -30,9 +30,7 @@ /mob/living/carbon/get_ear_protection(ignore_deafness = FALSE) var/obj/item/organ/ears/ears = get_organ_slot(ORGAN_SLOT_EARS) - if(!ears) - return INFINITY - return ..() + ears.bang_protect + return ..() + ears?.bang_protect /mob/living/carbon/is_mouth_covered(check_flags = ALL) if((check_flags & ITEM_SLOT_HEAD) && head && (head.flags_cover & HEADCOVERSMOUTH)) @@ -535,15 +533,6 @@ if(hit_clothes) hit_clothes.take_damage(damage_amount, damage_type, damage_flag, 0) -/mob/living/carbon/can_hear() - . = FALSE - var/obj/item/organ/ears/ears = get_organ_slot(ORGAN_SLOT_EARS) - if(ears && !HAS_TRAIT(src, TRAIT_DEAF)) - . = TRUE - if(health <= hardcrit_threshold && !HAS_TRAIT(src, TRAIT_NOHARDCRIT)) - . = FALSE - - /mob/living/carbon/adjust_oxy_loss(amount, updating_health = TRUE, forced, required_biotype, required_respiration_type) if(!forced && HAS_TRAIT(src, TRAIT_NOBREATH)) amount = min(amount, 0) //Prevents oxy damage but not healing diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index f527b70d6bd..32c7dfd139e 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -55,6 +55,8 @@ /mob/living/carbon/human/proc/setup_organless_effects() // All start without eyes, and get them via set species become_blind(NO_EYES) + // And no ears, and get them via set species + ADD_TRAIT(src, TRAIT_DEAF, NO_EARS) // Mobs cannot taste anything without a tongue; the tongue organ removes this on Insert ADD_TRAIT(src, TRAIT_AGEUSIA, NO_TONGUE_TRAIT) diff --git a/code/modules/mob/living/carbon/init_signals.dm b/code/modules/mob/living/carbon/init_signals.dm index a46acd8c520..da1cf59de61 100644 --- a/code/modules/mob/living/carbon/init_signals.dm +++ b/code/modules/mob/living/carbon/init_signals.dm @@ -141,3 +141,7 @@ SIGNAL_HANDLER cure_trauma_type(/datum/brain_trauma/severe/split_personality, TRAUMA_LIMIT_ABSOLUTE) + +/mob/living/carbon/on_hearing_loss(datum/source) + . = ..() + breathing_loop.stop() diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 4076cf77c86..91ab5cc761d 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -119,19 +119,13 @@ loc_as_obj.handle_internal_lifeform(src,0) if(check_breath(breath) && is_on_internals) - try_breathing_sound(breath) + // successful breath from internals, try to play the breathing sound + if(!HAS_TRAIT(src, TRAIT_DEAF) && client?.prefs?.read_preference(/datum/preference/toggle/sound_breathing)) + breathing_loop.start() if(breath) loc.assume_air(breath) -//Tries to play the carbon a breathing sound when using internals, also invokes check_breath -/mob/living/carbon/proc/try_breathing_sound(breath) - var/should_be_on = canon_client?.prefs?.read_preference(/datum/preference/toggle/sound_breathing) - if(should_be_on && !breathing_loop.timer_id && canon_client?.mob.can_hear()) - breathing_loop.start() - else if((!should_be_on && breathing_loop.timer_id) || !canon_client?.mob.can_hear()) - breathing_loop.stop() - /mob/living/carbon/proc/has_smoke_protection() if(HAS_TRAIT(src, TRAIT_NOBREATH)) return TRUE diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 5f0374d08ea..93fbabee070 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -2418,7 +2418,9 @@ GLOBAL_LIST_EMPTY(fire_appearances) if(HARD_CRIT) if(stat != UNCONSCIOUS) cure_blind(UNCONSCIOUS_TRAIT) + REMOVE_TRAIT(src, TRAIT_DEAF, STAT_TRAIT) if(DEAD) + REMOVE_TRAIT(src, TRAIT_DEAF, STAT_TRAIT) remove_from_dead_mob_list() add_to_alive_mob_list() switch(stat) //Current stat. @@ -2446,17 +2448,14 @@ GLOBAL_LIST_EMPTY(fire_appearances) if(. != UNCONSCIOUS) become_blind(UNCONSCIOUS_TRAIT) ADD_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT) + ADD_TRAIT(src, TRAIT_DEAF, STAT_TRAIT) log_combat(src, src, "entered hard crit") if(DEAD) REMOVE_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT) + ADD_TRAIT(src, TRAIT_DEAF, STAT_TRAIT) remove_from_alive_mob_list() add_to_dead_mob_list() log_combat(src, src, "died") - if(!can_hear()) - stop_sound_channel(CHANNEL_AMBIENCE) - refresh_looping_ambience() - - ///Reports the event of the change in value of the buckled variable. /mob/living/proc/set_buckled(new_buckled) diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index 28db8499a66..3bd7fcc8221 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -306,7 +306,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( // But we can still see them speak if(speaker_is_signing) deaf_message = "[span_name("[speaker]")] [speaker.get_default_say_verb()] something, but the motions are too subtle to make out from afar." - else if(can_hear()) // If we can't hear we want to continue to the default deaf message + else if(!HAS_TRAIT(src, TRAIT_DEAF)) // If we can't hear we want to continue to the default deaf message if(isliving(speaker)) var/mob/living/living_speaker = speaker var/mouth_hidden = living_speaker.is_mouth_covered() || HAS_TRAIT(living_speaker, TRAIT_FACE_COVERED) @@ -360,7 +360,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( deaf_type = MSG_AUDIBLE // Since you should be able to hear yourself without looking // Create map text prior to modifying message for goonchat - if (use_runechat && can_hear()) + if (use_runechat && !HAS_TRAIT(src, TRAIT_DEAF)) if (message_mods[MODE_CUSTOM_SAY_ERASE_INPUT]) create_chat_message(speaker, null, message_mods[MODE_CUSTOM_SAY_EMOTE], spans, EMOTE_MESSAGE) else diff --git a/code/modules/mob/living/silicon/ai/ai_say.dm b/code/modules/mob/living/silicon/ai/ai_say.dm index 26f2cc2f64a..88abc47ab37 100644 --- a/code/modules/mob/living/silicon/ai/ai_say.dm +++ b/code/modules/mob/living/silicon/ai/ai_say.dm @@ -171,7 +171,7 @@ // Play voice for all mobs in the z level for(var/mob/player_mob as anything in GLOB.player_list) var/pref_volume = safe_read_pref(player_mob.client, /datum/preference/numeric/volume/sound_ai_vox) - if(!player_mob.can_hear() || !pref_volume) + if(HAS_TRAIT(player_mob, TRAIT_DEAF) || !pref_volume) continue var/turf/player_turf = get_turf(player_mob) diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index d3217bb736f..691a36a8b65 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -100,7 +100,7 @@ update_mouse_pointer() update_ambience_area(get_area(src)) - if(!can_hear()) + if(HAS_TRAIT(src, TRAIT_DEAF)) stop_sound_channel(CHANNEL_AMBIENCE) if(client) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 3796d8711d1..2b3759948c1 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -243,7 +243,7 @@ type = alt_type . = FALSE - if(type & MSG_AUDIBLE && !can_hear())//Hearing related + if(type & MSG_AUDIBLE && HAS_TRAIT(src, TRAIT_DEAF))//Hearing related if(!alt_msg) return FALSE else @@ -369,7 +369,7 @@ continue if(self_message && hearing_mob == src) continue - if(audible_message_flags & EMOTE_MESSAGE && runechat_prefs_check(hearing_mob, audible_message_flags) && hearing_mob.can_hear()) + if(audible_message_flags & EMOTE_MESSAGE && runechat_prefs_check(hearing_mob, audible_message_flags) && !HAS_TRAIT(hearing_mob, TRAIT_DEAF)) hearing_mob.create_chat_message(src, raw_message = raw_msg, runechat_flags = audible_message_flags) hearing_mob.show_message(message, MSG_AUDIBLE, deaf_message, MSG_VISUAL) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index d48bbd9ac23..02e382c7117 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -403,10 +403,6 @@ var/mob/living/T = pick(nearby_mobs) ClickOn(T) -///Can the mob hear -/mob/proc/can_hear() - return !HAS_TRAIT(src, TRAIT_DEAF) - /** * Get the list of keywords for policy config * diff --git a/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm index 76caad943ff..13f14d3af2c 100644 --- a/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm @@ -767,18 +767,18 @@ Basically, we fill the time between now and 2s from now with hands based off the . = ..() random_span = pick("clown", "small", "big", "hypnophrase", "alien", "cult", "alert", "danger", "emote", "yell", "brass", "sans", "papyrus", "robot", "his_grace", "phobia") RegisterSignal(affected_mob, COMSIG_MOVABLE_HEAR, PROC_REF(owner_hear)) - to_chat(affected_mob, span_warning("Your hearing seems to be a bit off[affected_mob.can_hear() ? "!" : " - wait, that's normal."]")) + to_chat(affected_mob, span_warning("Your hearing seems to be a bit off[!HAS_TRAIT(affected_mob, TRAIT_DEAF) ? "!" : " - wait, that's normal."]")) /datum/reagent/impurity/inacusiate/on_mob_end_metabolize(mob/living/affected_mob) . = ..() UnregisterSignal(affected_mob, COMSIG_MOVABLE_HEAR) - to_chat(affected_mob, span_notice("You start hearing things normally again[affected_mob.can_hear() ? "" : " - no, wait, no you don't"].")) + to_chat(affected_mob, span_notice("You start hearing things normally again[!HAS_TRAIT(affected_mob, TRAIT_DEAF) ? "" : " - no, wait, no you don't"].")) /datum/reagent/impurity/inacusiate/proc/owner_hear(mob/living/owner, list/hearing_args) SIGNAL_HANDLER // don't skip messages that the owner says or can't understand (since they still make sounds) - if(!owner.can_hear()) + if(HAS_TRAIT(owner, TRAIT_DEAF)) return // not technically hearing var/atom/movable/speaker = hearing_args[HEARING_SPEAKER] diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 0c57cf86b0e..57e21242b34 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -929,7 +929,7 @@ . = ..() if(creation_purity >= 1) ADD_TRAIT(affected_mob, TRAIT_GOOD_HEARING, type) - if(affected_mob.can_hear()) + if(!HAS_TRAIT(affected_mob, TRAIT_DEAF)) to_chat(affected_mob, span_nicegreen("You can feel your hearing drastically improve!")) /datum/reagent/medicine/inacusiate/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, metabolization_ratio) @@ -945,7 +945,7 @@ /datum/reagent/medicine/inacusiate/on_mob_delete(mob/living/affected_mob) . = ..() REMOVE_TRAIT(affected_mob, TRAIT_GOOD_HEARING, type) - if(affected_mob.can_hear()) + if(!HAS_TRAIT(affected_mob, TRAIT_DEAF)) to_chat(affected_mob, span_notice("Your hearing returns to its normal acuity.")) /datum/reagent/medicine/atropine diff --git a/code/modules/surgery/organs/internal/ears/_ears.dm b/code/modules/surgery/organs/internal/ears/_ears.dm index fb086e8bd36..e1259f5c82d 100644 --- a/code/modules/surgery/organs/internal/ears/_ears.dm +++ b/code/modules/surgery/organs/internal/ears/_ears.dm @@ -48,11 +48,16 @@ . = ..() if(temporary_deafness) on_deafened() + REMOVE_TRAIT(organ_owner, TRAIT_DEAF, NO_EARS) /obj/item/organ/ears/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() if(temporary_deafness) on_undeafened(organ_owner) + // Do not apply with special flag, even if it would ultimately be redundant by new ears being hot-swapped in. + // This is so we don't trip signal_addtrait when hot-swapping ears, which could cause inappropriate behavior like nuking sound effects. + if(!special) + ADD_TRAIT(organ_owner, TRAIT_DEAF, NO_EARS) /obj/item/organ/ears/get_status_appendix(advanced, add_tooltips) if(owner.stat == DEAD || !HAS_TRAIT(owner, TRAIT_DEAF)) diff --git a/code/modules/unit_tests/spawn_humans.dm b/code/modules/unit_tests/spawn_humans.dm index e90473a7ba0..f89f59a4cbf 100644 --- a/code/modules/unit_tests/spawn_humans.dm +++ b/code/modules/unit_tests/spawn_humans.dm @@ -13,3 +13,4 @@ var/mob/living/carbon/human/consistent/dummy = allocate(/mob/living/carbon/human/consistent) TEST_ASSERT(!HAS_TRAIT_FROM(dummy, TRAIT_AGEUSIA, NO_TONGUE_TRAIT), "Dummy has ageusia on init, when it should've been removed by its default tongue.") TEST_ASSERT(!dummy.is_blind_from(NO_EYES), "Dummy is blind on init, when it should've been removed by its default eyes.") + TEST_ASSERT(!HAS_TRAIT_FROM(dummy, TRAIT_DEAF, NO_EARS), "Dummy is deaf on init, when it should've been removed by its default ears.") diff --git a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm index 7e68aaf91cb..d85189ea8ea 100644 --- a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm +++ b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm @@ -265,7 +265,7 @@ playsound(chassis, 'sound/items/airhorn/airhorn.ogg', 100, TRUE) to_chat(source, "[icon2html(src, source)]HONK") for(var/mob/living/carbon/M in ohearers(6, chassis)) - if(!M.can_hear()) + if(HAS_TRAIT(M, TRAIT_DEAF)) continue var/turf/turf_check = get_turf(M) if(isspaceturf(turf_check) && !turf_check.Adjacent(src)) //in space nobody can hear you honk.