diff --git a/code/game/objects/items/radio/headset.dm b/code/game/objects/items/radio/headset.dm index b00dc776cde4b..0c90aaa70a395 100644 --- a/code/game/objects/items/radio/headset.dm +++ b/code/game/objects/items/radio/headset.dm @@ -1,3 +1,9 @@ +// Defines for TTS modes. +#define HEADSET_TTS_NONE 0 +#define HEADSET_TTS_SL_ONLY 1 +#define HEADSET_TTS_SQUAD 2 +#define HEADSET_TTS_ALL 3 + // Used for translating channels to tokens on examination GLOBAL_LIST_INIT(channel_tokens, list( RADIO_CHANNEL_REQUISITIONS = RADIO_TOKEN_REQUISITIONS, @@ -26,7 +32,8 @@ GLOBAL_LIST_INIT(channel_tokens, list( equip_slot_flags = ITEM_SLOT_EARS var/obj/item/encryptionkey/keyslot2 = null - + /// Current squad TTS mode the headset is switched to; defaults to no radio TTS + var/squad_tts_mode = HEADSET_TTS_SQUAD /obj/item/radio/headset/Initialize(mapload) if(keyslot) @@ -156,6 +163,23 @@ GLOBAL_LIST_INIT(channel_tokens, list( channels[RADIO_CHANNEL_REQUISITIONS] = !channels[RADIO_CHANNEL_REQUISITIONS] balloon_alert(user, "toggles supply comms [channels[RADIO_CHANNEL_REQUISITIONS] ? "on" : "off"].") +//Toggles TTS mode. If TTS is enabled, we will play TTS for any radio messages passed through the headset. +/obj/item/radio/headset/RightClick(mob/user) + . = ..() + switch(squad_tts_mode) + if(HEADSET_TTS_NONE) + user.balloon_alert(user, "You switch the TTS mode to \"SL Only\"") + squad_tts_mode = HEADSET_TTS_SL_ONLY + if(HEADSET_TTS_SL_ONLY) + user.balloon_alert(user, "You switch the TTS mode to \"Squad\"") + squad_tts_mode = HEADSET_TTS_SQUAD + if(HEADSET_TTS_SQUAD) + user.balloon_alert(user, "You switch the TTS mode to \"All\"") + squad_tts_mode = HEADSET_TTS_ALL + if(HEADSET_TTS_ALL) + user.balloon_alert(user, "You switch the TTS mode to \"None\"") + squad_tts_mode = HEADSET_TTS_NONE + /obj/item/radio/headset/vendor_equip(mob/user) ..() return user.equip_to_appropriate_slot(src) diff --git a/code/game/objects/machinery/overwatch.dm b/code/game/objects/machinery/overwatch.dm index 1f10d7e6fd8de..8b2e0c9a527ff 100644 --- a/code/game/objects/machinery/overwatch.dm +++ b/code/game/objects/machinery/overwatch.dm @@ -986,17 +986,17 @@ GLOBAL_LIST_EMPTY(active_cas_targets) switch(command_aura) if("move") var/image/move = image('icons/mob/talk.dmi', src, icon_state = "order_move") - message = pick(";GET MOVING!", ";GO, GO, GO!", ";WE ARE ON THE MOVE!", ";MOVE IT!", ";DOUBLE TIME!", ";ONWARDS!", ";MOVE MOVE MOVE!", ";ON YOUR FEET!", ";GET A MOVE ON!", ";ON THE DOUBLE!", ";ROLL OUT!", ";LET'S GO, LET'S GO!", ";MOVE OUT!", ";LEAD THE WAY!", ";FORWARD!", ";COME ON, MOVE!", ";HURRY, GO!") + message = pick("GET MOVING!", "GO, GO, GO!", "WE ARE ON THE MOVE!", "MOVE IT!", "DOUBLE TIME!", "ONWARDS!", "MOVE MOVE MOVE!", "ON YOUR FEET!", "GET A MOVE ON!", "ON THE DOUBLE!", "ROLL OUT!", "LET'S GO, LET'S GO!", "MOVE OUT!", "LEAD THE WAY!", "FORWARD!", "COME ON, MOVE!", "HURRY, GO!") say(message) add_emote_overlay(move) if("hold") var/image/hold = image('icons/mob/talk.dmi', src, icon_state = "order_hold") - message = pick(";DUCK AND COVER!", ";HOLD THE LINE!", ";HOLD POSITION!", ";STAND YOUR GROUND!", ";STAND AND FIGHT!", ";TAKE COVER!", ";COVER THE AREA!", ";BRACE FOR COVER!", ";BRACE!", ";INCOMING!") + message = pick("DUCK AND COVER!", "HOLD THE LINE!", "HOLD POSITION!", "STAND YOUR GROUND!", "STAND AND FIGHT!", "TAKE COVER!", "COVER THE AREA!", "BRACE FOR COVER!", "BRACE!", "INCOMING!") say(message) add_emote_overlay(hold) if("focus") var/image/focus = image('icons/mob/talk.dmi', src, icon_state = "order_focus") - message = pick(";FOCUS FIRE!", ";PICK YOUR TARGETS!", ";CENTER MASS!", ";CONTROLLED BURSTS!", ";AIM YOUR SHOTS!", ";READY WEAPONS!", ";TAKE AIM!", ";LINE YOUR SIGHTS!", ";LOCK AND LOAD!", ";GET READY TO FIRE!") + message = pick("FOCUS FIRE!", "PICK YOUR TARGETS!", "CENTER MASS!", "CONTROLLED BURSTS!", "AIM YOUR SHOTS!", "READY WEAPONS!", "TAKE AIM!", "LINE YOUR SIGHTS!", "LOCK AND LOAD!", "GET READY TO FIRE!") say(message) add_emote_overlay(focus) diff --git a/code/game/objects/machinery/telecomms/broadcasting.dm b/code/game/objects/machinery/telecomms/broadcasting.dm index e87c0718dc798..63b3c4980020e 100644 --- a/code/game/objects/machinery/telecomms/broadcasting.dm +++ b/code/game/objects/machinery/telecomms/broadcasting.dm @@ -199,6 +199,44 @@ continue hearer.Hear(rendered, virt, language, message, frequency, spans) + + //Check that speaker isn't banned from TTS + var/atom/movable/speaker = virt?.source + var/banned = FALSE + if(ismob(speaker)) + var/mob/potential_user = speaker + if(is_banned_from(potential_user.ckey, "TTS") || potential_user.client?.prefs.muted & MUTE_TTS) + banned = TRUE + + //If they aren't, handle radio TTS + if(speaker && speaker.voice && !banned) + var/is_speaker_squad_lead = FALSE + if(ishuman(speaker)) + var/mob/living/carbon/human/human_speaker = speaker + if(human_speaker.assigned_squad?.squad_leader == speaker) + is_speaker_squad_lead = TRUE + + if(speaker in receive) + receive -= speaker //This list isn't used again, so we can just cut out the original speaker from it so TTS doesn't play twice + + for(var/mob/living/carbon/human/potential_hearer in receive) + if(potential_hearer.stat >= UNCONSCIOUS || potential_hearer.disabilities & DEAF || !(potential_hearer.client?.prefs.sound_tts != TTS_SOUND_OFF)) + continue + + var/obj/item/radio/headset/radio = potential_hearer.wear_ear + switch(radio.squad_tts_mode) + if(HEADSET_TTS_NONE) + continue + if(HEADSET_TTS_SQUAD) + if(potential_hearer.assigned_squad?.radio_freq != frequency) + continue + if(HEADSET_TTS_SL_ONLY) + if(potential_hearer.assigned_squad?.radio_freq != frequency || !is_speaker_squad_lead) + continue + + INVOKE_ASYNC(SStts, TYPE_PROC_REF(/datum/controller/subsystem/tts, queue_tts_message), potential_hearer, html_decode(message), language, speaker.voice, potential_hearer.voice_filter, local = TRUE, pitch = speaker.pitch, special_filters = TTS_FILTER_RADIO) + + var/spans_part = "" if(length(spans)) spans_part = "(spans:"