Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit 6292a7c

Browse files
authored
Rewrites speech sounds + preferences (#22622)
* all one commit here we go * rename * Update voice_types.dm * type preference based on species * Update voice_types.dm * Update _species.dm * changes * Update voice_types.dm * Update speech_sounds.dm
1 parent 91a45bf commit 6292a7c

File tree

14 files changed

+263
-44
lines changed

14 files changed

+263
-44
lines changed

code/__DEFINES/say.dm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,6 @@
128128

129129

130130
#define MAX_FLAVOR_LEN 4096 //double the maximum message length.
131+
132+
/// Default volume of speech sound effects (this is actually multiplied by 5 when used)
133+
#define DEFAULT_SPEECH_VOLUME 60

code/__DEFINES/{yogs_defines}/mobs.dm

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,3 @@
1616
#define SPECIES_VOX "vox"
1717

1818
#define BUTT_SPRITE_VOX "vox"
19-
20-
21-
GLOBAL_REAL_VAR(list/voice_type2sound = list(
22-
"1" = list(
23-
"1" = sound('goon/sound/speak_1.ogg'),
24-
"!" = sound('goon/sound/speak_1_exclaim.ogg'),
25-
"?" = sound('goon/sound/speak_1_ask.ogg')
26-
),
27-
"2" = list(
28-
"2" = sound('goon/sound/speak_2.ogg'),
29-
"!" = sound('goon/sound/speak_2_exclaim.ogg'),
30-
"?" = sound('goon/sound/speak_2_ask.ogg')
31-
),
32-
"3" = list(
33-
"3" = sound('goon/sound/speak_3.ogg'),
34-
"!" = sound('goon/sound/speak_3_exclaim.ogg'),
35-
"?" = sound('goon/sound/speak_3_ask.ogg')
36-
),
37-
"4" = list(
38-
"4" = sound('goon/sound/speak_4.ogg'),
39-
"!" = sound('goon/sound/speak_4_exclaim.ogg'),
40-
"?" = sound('goon/sound/speak_4_ask.ogg')
41-
),
42-
))
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// Middleware for voice types
2+
3+
/// Generate list of valid voice_types for the species
4+
/datum/preference_middleware/voice_type/get_ui_data()
5+
. = list()
6+
.["available_voices"] = list()
7+
8+
var/datum/species/species_type = preferences.read_preference(/datum/preference/choiced/species)
9+
var/species_id = initial(species_type.id)
10+
11+
for(var/i in GLOB.voice_types)
12+
var/datum/voice/test = GLOB.voice_types[i]
13+
if(test.can_use(species_id))
14+
.["available_voices"] += test.name
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/datum/preference/toggle/speech_hear
2+
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
3+
savefile_key = "speech_hear"
4+
savefile_identifier = PREFERENCE_PLAYER
5+
6+
/// Controls the volume at which the user hears in-person Speech sounds
7+
/datum/preference/numeric/speech_volume
8+
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
9+
savefile_key = "speech_volume"
10+
savefile_identifier = PREFERENCE_PLAYER
11+
12+
minimum = 0
13+
maximum = 100
14+
15+
/datum/preference/numeric/speech_volume/create_default_value()
16+
return DEFAULT_SPEECH_VOLUME
17+
18+
19+
20+
21+
/datum/preference/choiced/voice_type
22+
category = PREFERENCE_CATEGORY_SECONDARY_FEATURES
23+
savefile_identifier = PREFERENCE_CHARACTER
24+
savefile_key = "voice_type"
25+
26+
/datum/preference/choiced/voice_type/init_possible_values()
27+
return GLOB.voice_types
28+
29+
/datum/preference/choiced/voice_type/compile_constant_data()
30+
var/list/data = ..()
31+
32+
data[CHOICED_PREFERENCE_DISPLAY_NAMES] = GLOB.voice_types
33+
34+
return data
35+
36+
//this doesn't yet prevent people from taking invalid voices, but it'll stop you from having one to start
37+
/datum/preference/choiced/voice_type/create_informed_default_value(datum/preferences/preferences)
38+
var/datum/species/species_type = preferences.read_preference(/datum/preference/choiced/species)
39+
var/species_id = initial(species_type.id)
40+
41+
var/list/valid = list()
42+
for(var/i in GLOB.voice_types)
43+
var/datum/voice/test = GLOB.voice_types[i]
44+
if(test.can_use(species_id))
45+
valid |= i
46+
47+
if(length(valid))
48+
return pick(valid)
49+
return pick(GLOB.voice_types)
50+
51+
/datum/preference/choiced/voice_type/apply_to_human(mob/living/carbon/human/target, value)
52+
target.voice_type = GLOB.voice_types[value]
53+
54+
55+
/datum/preference/choiced/voice_type/deserialize(input, datum/preferences/preferences)
56+
var/datum/species/species_type = preferences.read_preference(/datum/preference/choiced/species)
57+
var/species_id = initial(species_type.id)
58+
59+
var/datum/voice/test = GLOB.voice_types[input]
60+
61+
if (!test || !test.can_use(species_id))
62+
return create_informed_default_value(preferences)
63+
64+
return ..(input, preferences)

code/modules/mob/living/carbon/human/_species.dm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,8 @@ GLOBAL_LIST_EMPTY(features_by_species)
514514
C.regenerate_icons()
515515
SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)
516516

517+
if(!(C.voice_type?.can_use(id)))
518+
C.voice_type = get_random_valid_voice(id)
517519

518520
/datum/species/proc/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load)
519521
if(C.dna.species.exotic_bloodtype)

code/modules/mob/living/living.dm

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
GLOB.mob_living_list += src
1212
if(startDead)
1313
death(FALSE)
14-
if(!voice_type)
15-
voice_type = pick(voice_type2sound) //yogs edit (stolen from monke)
1614

1715
/mob/living/prepare_huds()
1816
..()

code/modules/mob/living/say.dm

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -233,22 +233,6 @@ GLOBAL_LIST_INIT(special_radio_keys, list(
233233
spans |= SPAN_ITALICS
234234

235235
send_speech(message, message_range, src, bubble_type, spans, language, message_mods)
236-
237-
//yogs edit (stolen from monkestation)
238-
///Play a sound to indicate we just spoke
239-
if(client && !HAS_TRAIT(src, TRAIT_SIGN_LANG))
240-
var/ending = copytext_char(message, -1)
241-
var/sound/speak_sound
242-
if(SPAN_HELIUM in spans)
243-
speak_sound = sound('sound/effects/mousesqueek.ogg')
244-
else if(ending == "?")
245-
speak_sound = voice_type2sound[voice_type]["?"]
246-
else if(ending == "!")
247-
speak_sound = voice_type2sound[voice_type]["!"]
248-
else
249-
speak_sound = voice_type2sound[voice_type][voice_type]
250-
playsound(src, speak_sound, 300, 1, SHORT_RANGE_SOUND_EXTRARANGE-2, falloff_exponent = 1, pressure_affected = FALSE, ignore_walls = FALSE, use_reverb = FALSE)
251-
//yogs change end
252236

253237
return on_say_success(message,message_range,succumbed, spans, language, message_mods)//Yogs
254238

@@ -318,13 +302,28 @@ GLOBAL_LIST_INIT(special_radio_keys, list(
318302
eavesdropping = stars(message)
319303
eavesrendered = compose_message(src, message_language, eavesdropping, , spans, message_mods)
320304

305+
306+
307+
//yogs edit (stolen from monkestation and moved)
308+
///Play a sound to indicate we just spoke
309+
var/sound/speak_sound
310+
if(client && voice_type && istype(voice_type))
311+
speak_sound = voice_type.get_sound(src, message, spans)
312+
//yogs change end
313+
321314
var/rendered = compose_message(src, message_language, message, , spans, message_mods)
322315
for(var/_AM in listening)
323316
var/atom/movable/AM = _AM
324317
if(eavesdrop_range && get_dist(source, AM) > message_range && !(the_dead[AM]))
325318
AM.Hear(eavesrendered, src, message_language, eavesdropping, , spans, message_mods)
326319
else
327320
AM.Hear(rendered, src, message_language, message, , spans, message_mods)
321+
if(speak_sound && ismob(AM))
322+
var/mob/hearing_mob = AM
323+
if(hearing_mob.client?.prefs?.read_preference(/datum/preference/toggle/speech_hear) && hearing_mob.has_language(message_language))
324+
var/volume = hearing_mob.client?.prefs?.read_preference(/datum/preference/numeric/speech_volume) || DEFAULT_SPEECH_VOLUME
325+
volume *= 6 //the sounds are actually really quiet, we just reduced the numbers shown in preferences to not confuse players
326+
hearing_mob.playsound_local(src, speak_sound, volume, TRUE, pressure_affected = FALSE, use_reverb = FALSE) //virtualspeaker handles radio stuff
328327
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIVING_SAY_SPECIAL, src, message)
329328

330329
//speech bubble

tgui/packages/tgui/interfaces/PreferencesMenu/data.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ export type PreferencesMenuData = {
175175

176176
earned_skillcapes: string[];
177177

178+
available_voices: string[];
179+
178180
window: Window;
179181
};
180182

tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ export type FeatureChoicedServerData = {
147147

148148
export type FeatureChoiced = Feature<string, string, FeatureChoicedServerData>;
149149

150-
const capitalizeFirstLetter = (text: string) => (
150+
export const capitalizeFirstLetter = (text: string) => (
151151
text.toString().charAt(0).toUpperCase() + text.toString().slice(1)
152152
);
153153

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { useBackend } from "../../../../../backend";
2+
import { PreferencesMenuData } from "../../../data";
3+
import { sortStrings } from "common/collections";
4+
import { StandardizedDropdown, capitalizeFirstLetter, FeatureChoiced, FeatureChoicedServerData, FeatureValueProps } from "../base";
5+
6+
const VoiceDropdownInput = (
7+
props: FeatureValueProps<string, string, FeatureChoicedServerData> & {
8+
disabled?: boolean,
9+
}, context) => {
10+
const serverData = props.serverData;
11+
if (!serverData) {
12+
return null;
13+
}
14+
15+
const { data } = useBackend<PreferencesMenuData>(context);
16+
17+
const displayNames = serverData.display_names || Object.fromEntries(serverData.choices.map(choice => [choice, capitalizeFirstLetter(choice)]));
18+
19+
let choices = sortStrings(data.available_voices);
20+
21+
return (<StandardizedDropdown
22+
choices={choices}
23+
disabled={props.disabled}
24+
displayNames={displayNames}
25+
onSetValue={props.handleSetValue}
26+
value={props.value}
27+
/>);
28+
};
29+
30+
export const voice_type: FeatureChoiced = {
31+
name: "Voice",
32+
component: VoiceDropdownInput,
33+
};

0 commit comments

Comments
 (0)