Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Squad radio TTS #15961

Merged
merged 23 commits into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0be9485
Automatic changelog compile [ci skip]
actions-user May 29, 2024
fd489d5
Adds squad TTS
breadhunt May 31, 2024
cc9d58b
Merge branch 'master' into squad_tts
breadhunt Jun 1, 2024
eb2b746
Default mode is SL only
breadhunt Jun 2, 2024
e871b3e
Order barks are now in person instead of on radio
breadhunt Jun 2, 2024
211d26c
Speaker doesn't receive TTS
breadhunt Jun 2, 2024
7a07839
Merge branch 'master' into squad_tts
breadhunt Jun 5, 2024
be93484
Hopefully fixes squad TTS + separates "All"/"Squad" mode
breadhunt Jun 20, 2024
cb78c13
Default TTS mode "SL Only" --> "Squad"
breadhunt Jun 20, 2024
22b4b6f
oops
breadhunt Jun 21, 2024
f30d583
Squad TTS is now instead based on solely whether it's on a squad freq…
breadhunt Jun 21, 2024
4edebaa
All roles can use squad TTS + fixes TTS mute bugs
breadhunt Jun 26, 2024
ae6aaa8
should fix eof linechange?
breadhunt Jun 27, 2024
cbf08e9
Should fix all remaining runtimes
breadhunt Jul 5, 2024
4d113f6
Fixes a ton of bugs, squad TTS now only plays for squad members
breadhunt Jul 19, 2024
fd2840f
Should fix squad TTS not working
breadhunt Aug 1, 2024
d522f53
Converts TTS to a prefs-based system
breadhunt Aug 29, 2024
35c313d
Merge remote-tracking branch 'origin/master' into squad_tts
breadhunt Aug 29, 2024
f2c152c
Review compliance optimisation
breadhunt Sep 5, 2024
3468e08
More consistent prefs settings
breadhunt Sep 6, 2024
f718eaf
Fixes radio TTS prefs not setting correctly
breadhunt Sep 8, 2024
ac689c3
Update broadcasting.dm
TiviPlus Sep 28, 2024
17307f1
Update broadcasting.dm
TiviPlus Sep 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions code/__DEFINES/tts.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
#define TTS_SOUND_BLIPS "Blips Only"
GLOBAL_LIST_INIT(all_tts_options, list(TTS_SOUND_OFF, TTS_SOUND_ENABLED, TTS_SOUND_BLIPS))

#define RADIO_TTS_SL (1<<0)
#define RADIO_TTS_SQUAD (1<<1)
#define RADIO_TTS_COMMAND (1<<2)
#define RADIO_TTS_ALL (1<<3)

GLOBAL_LIST_INIT(all_radio_tts_options, list(RADIO_TTS_SL, RADIO_TTS_SQUAD, RADIO_TTS_COMMAND, RADIO_TTS_ALL))

///TTS filter to activate start/stop radio clicks on speech.
#define TTS_FILTER_RADIO "radio"
///TTS filter to activate a silicon effect on speech.
Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/items/radio/headset.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Defines for TTS modes.
// Used for translating channels to tokens on examination
GLOBAL_LIST_INIT(channel_tokens, list(
RADIO_CHANNEL_REQUISITIONS = RADIO_TOKEN_REQUISITIONS,
Expand Down Expand Up @@ -27,7 +28,6 @@ GLOBAL_LIST_INIT(channel_tokens, list(
equip_slot_flags = ITEM_SLOT_EARS
var/obj/item/encryptionkey/keyslot2 = null


/obj/item/radio/headset/Initialize(mapload)
if(keyslot)
keyslot = new keyslot(src)
Expand Down
6 changes: 3 additions & 3 deletions code/game/objects/machinery/overwatch.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
42 changes: 42 additions & 0 deletions code/game/objects/machinery/telecomms/broadcasting.dm
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,48 @@
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

var/is_speaker_command_freq = FALSE
if(frequency == FREQ_COMMAND || frequency == FREQ_COMMAND_SOM)
is_speaker_command_freq = 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/radio_flags = potential_hearer.client.prefs.radio_tts_flags
TiviPlus marked this conversation as resolved.
Show resolved Hide resolved
var/should_play_tts = FALSE
if(CHECK_BITFIELD(radio_flags, RADIO_TTS_ALL))
should_play_tts = TRUE
else if(potential_hearer.assigned_squad?.radio_freq == frequency && (CHECK_BITFIELD(radio_flags, RADIO_TTS_SQUAD) || (CHECK_BITFIELD(radio_flags, RADIO_TTS_SL) && is_speaker_squad_lead)))
should_play_tts = TRUE
else if(CHECK_BITFIELD(radio_flags, RADIO_TTS_COMMAND) && is_speaker_command_freq)
should_play_tts = TRUE

if(!should_play_tts)
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)
Copy link
Member

@Watermelon914 Watermelon914 Sep 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll instead want to modify the backend so that you can pass in an option to disable directionality for a specific request. This is generally a lot more inefficient than just passing in a list of potential hearers as you're making a lot of HTTP requests when you only really need to make 1. Also, it'll fall into the same problems of the same person speaking where they're able to speak over themselves, which can kinda hurt the illusion of TTS.

Best thing to do is to just add another option to queue_tts_message that lets you set some directional var to FALSE. Pass that into the TTS request, then in the subsystem before play_tts, pass that in and disable directionality/range checks if it is set to FALSE.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, you could just add them all up into a list and send it to TTS subsystem in one go.
Add a variable for directionality
If it's set, ignore turf source and play at source.


var/spans_part = ""
if(length(spans))
spans_part = "(spans:"
Expand Down
2 changes: 2 additions & 0 deletions code/modules/client/preferences.dm
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/tts_pitch = 0
///Volume to use for tts
var/volume_tts = 100
///Which types of comms the user wants to hear TTS from
var/radio_tts_flags = RADIO_TTS_SL | RADIO_TTS_SQUAD

/// Preference for letting people make TGUI windows use more accessible (basically, default) themes, where needed/possible.
/// Example application: health analyzers using this to choose between default themes or the NtOS themes.
Expand Down
3 changes: 3 additions & 0 deletions code/modules/client/preferences_savefile.dm
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@
tooltips = sanitize_integer(tooltips, FALSE, TRUE, initial(tooltips))
sound_tts = sanitize_inlist(sound_tts, GLOB.all_tts_options, initial(sound_tts))
volume_tts = sanitize_integer(volume_tts, 1, 100, initial(volume_tts))
radio_tts_flags = sanitize_inlist(radio_tts_flags, GLOB.all_radio_tts_options, (RADIO_TTS_SL | RADIO_TTS_SQUAD | RADIO_TTS_COMMAND))

key_bindings = sanitize_islist(key_bindings, list())
if (!length(key_bindings))
Expand Down Expand Up @@ -304,6 +305,7 @@
tooltips = sanitize_integer(tooltips, FALSE, TRUE, initial(tooltips))
sound_tts = sanitize_inlist(sound_tts, GLOB.all_tts_options, initial(sound_tts))
volume_tts = sanitize_integer(volume_tts, 1, 100, initial(volume_tts))
//radio_tts_flags = sanitize

mute_self_combat_messages = sanitize_integer(mute_self_combat_messages, FALSE, TRUE, initial(mute_self_combat_messages))
mute_others_combat_messages = sanitize_integer(mute_others_combat_messages, FALSE, TRUE, initial(mute_others_combat_messages))
Expand Down Expand Up @@ -462,6 +464,7 @@

READ_FILE(S["tts_voice"], tts_voice)
READ_FILE(S["tts_pitch"], tts_pitch)
READ_FILE(S["radio_tts_flags"], radio_tts_flags)

READ_FILE(S["med_record"], med_record)
READ_FILE(S["sec_record"], sec_record)
Expand Down
21 changes: 21 additions & 0 deletions code/modules/client/preferences_ui.dm
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
data["mute_xeno_health_alert_messages"] = mute_xeno_health_alert_messages
data["sound_tts"] = sound_tts
data["volume_tts"] = volume_tts
data["radio_tts_flags"] = radio_tts_flags
data["accessible_tgui_themes"] = accessible_tgui_themes
data["tgui_fancy"] = tgui_fancy
data["tgui_lock"] = tgui_lock
Expand Down Expand Up @@ -637,6 +638,26 @@
new_vol = round(new_vol)
volume_tts = clamp(new_vol, 0, 100)

if("toggle_radio_tts_setting")
var/flag_to_change
switch(params["newsetting"])
if("sl")
flag_to_change = RADIO_TTS_SL
if("squad")
ENABLE_BITFIELD(radio_tts_flags, RADIO_TTS_SL) //Enable SL TTS if not already enabled
flag_to_change = RADIO_TTS_SQUAD
if("command")
flag_to_change = RADIO_TTS_COMMAND
if("all")
flag_to_change = RADIO_TTS_ALL
else
return

if(CHECK_BITFIELD(radio_tts_flags, flag_to_change))
DISABLE_BITFIELD(radio_tts_flags, flag_to_change)
else
ENABLE_BITFIELD(radio_tts_flags, flag_to_change)

if("accessible_tgui_themes")
accessible_tgui_themes = !accessible_tgui_themes

Expand Down
34 changes: 34 additions & 0 deletions tgui/packages/tgui/interfaces/PlayerPreferences/GameSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ export const GameSettings = (props) => {
const { act, data } = useBackend<GameSettingData>();
const { ui_style_color, scaling_method, pixel_size, parallax, is_admin } =
data;

// Remember to update this alongside defines
const TTSRadioSetting = ['sl', 'squad', 'command', 'all'];
const TTSRadioSettingToBitfield = {
sl: 1 << 0,
squad: 1 << 1,
command: 1 << 2,
all: 1 << 3,
};
const TTSRadioSettingToName = {
sl: 'Squad Leader',
squad: 'Squad',
command: 'Command',
all: 'All (except Squad/Command)',
};

return (
<Section title="Game Settings">
<Stack fill>
Expand Down Expand Up @@ -78,6 +94,24 @@ export const GameSettings = (props) => {
label="Text to speech volume"
value="volume_tts"
/>
<LabeledList.Item label={'Text to Speech radio configuration'}>
{TTSRadioSetting.map((setting) => (
<Button.Checkbox
inline
key={setting}
content={TTSRadioSettingToName[setting]}
checked={
TTSRadioSettingToBitfield[setting] &
data['radio_tts_flags']
}
onClick={() =>
act('toggle_radio_tts_setting', {
newsetting: setting,
})
}
/>
))}
</LabeledList.Item>
<Tooltip content="Use more accessible TGUI themes/layouts wherever possible.">
<ToggleFieldPreference
label="Accessible TGUI themes"
Expand Down
Loading