mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
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
This commit is contained in:
@@ -128,3 +128,6 @@
|
||||
|
||||
|
||||
#define MAX_FLAVOR_LEN 4096 //double the maximum message length.
|
||||
|
||||
/// Default volume of speech sound effects (this is actually multiplied by 5 when used)
|
||||
#define DEFAULT_SPEECH_VOLUME 60
|
||||
|
||||
@@ -16,27 +16,3 @@
|
||||
#define SPECIES_VOX "vox"
|
||||
|
||||
#define BUTT_SPRITE_VOX "vox"
|
||||
|
||||
|
||||
GLOBAL_REAL_VAR(list/voice_type2sound = list(
|
||||
"1" = list(
|
||||
"1" = sound('goon/sound/speak_1.ogg'),
|
||||
"!" = sound('goon/sound/speak_1_exclaim.ogg'),
|
||||
"?" = sound('goon/sound/speak_1_ask.ogg')
|
||||
),
|
||||
"2" = list(
|
||||
"2" = sound('goon/sound/speak_2.ogg'),
|
||||
"!" = sound('goon/sound/speak_2_exclaim.ogg'),
|
||||
"?" = sound('goon/sound/speak_2_ask.ogg')
|
||||
),
|
||||
"3" = list(
|
||||
"3" = sound('goon/sound/speak_3.ogg'),
|
||||
"!" = sound('goon/sound/speak_3_exclaim.ogg'),
|
||||
"?" = sound('goon/sound/speak_3_ask.ogg')
|
||||
),
|
||||
"4" = list(
|
||||
"4" = sound('goon/sound/speak_4.ogg'),
|
||||
"!" = sound('goon/sound/speak_4_exclaim.ogg'),
|
||||
"?" = sound('goon/sound/speak_4_ask.ogg')
|
||||
),
|
||||
))
|
||||
|
||||
14
code/modules/client/preferences/middleware/voice_type.dm
Normal file
14
code/modules/client/preferences/middleware/voice_type.dm
Normal file
@@ -0,0 +1,14 @@
|
||||
/// Middleware for voice types
|
||||
|
||||
/// Generate list of valid voice_types for the species
|
||||
/datum/preference_middleware/voice_type/get_ui_data()
|
||||
. = list()
|
||||
.["available_voices"] = list()
|
||||
|
||||
var/datum/species/species_type = preferences.read_preference(/datum/preference/choiced/species)
|
||||
var/species_id = initial(species_type.id)
|
||||
|
||||
for(var/i in GLOB.voice_types)
|
||||
var/datum/voice/test = GLOB.voice_types[i]
|
||||
if(test.can_use(species_id))
|
||||
.["available_voices"] += test.name
|
||||
64
code/modules/client/preferences/speech_sounds.dm
Normal file
64
code/modules/client/preferences/speech_sounds.dm
Normal file
@@ -0,0 +1,64 @@
|
||||
/datum/preference/toggle/speech_hear
|
||||
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
|
||||
savefile_key = "speech_hear"
|
||||
savefile_identifier = PREFERENCE_PLAYER
|
||||
|
||||
/// Controls the volume at which the user hears in-person Speech sounds
|
||||
/datum/preference/numeric/speech_volume
|
||||
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
|
||||
savefile_key = "speech_volume"
|
||||
savefile_identifier = PREFERENCE_PLAYER
|
||||
|
||||
minimum = 0
|
||||
maximum = 100
|
||||
|
||||
/datum/preference/numeric/speech_volume/create_default_value()
|
||||
return DEFAULT_SPEECH_VOLUME
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/preference/choiced/voice_type
|
||||
category = PREFERENCE_CATEGORY_SECONDARY_FEATURES
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "voice_type"
|
||||
|
||||
/datum/preference/choiced/voice_type/init_possible_values()
|
||||
return GLOB.voice_types
|
||||
|
||||
/datum/preference/choiced/voice_type/compile_constant_data()
|
||||
var/list/data = ..()
|
||||
|
||||
data[CHOICED_PREFERENCE_DISPLAY_NAMES] = GLOB.voice_types
|
||||
|
||||
return data
|
||||
|
||||
//this doesn't yet prevent people from taking invalid voices, but it'll stop you from having one to start
|
||||
/datum/preference/choiced/voice_type/create_informed_default_value(datum/preferences/preferences)
|
||||
var/datum/species/species_type = preferences.read_preference(/datum/preference/choiced/species)
|
||||
var/species_id = initial(species_type.id)
|
||||
|
||||
var/list/valid = list()
|
||||
for(var/i in GLOB.voice_types)
|
||||
var/datum/voice/test = GLOB.voice_types[i]
|
||||
if(test.can_use(species_id))
|
||||
valid |= i
|
||||
|
||||
if(length(valid))
|
||||
return pick(valid)
|
||||
return pick(GLOB.voice_types)
|
||||
|
||||
/datum/preference/choiced/voice_type/apply_to_human(mob/living/carbon/human/target, value)
|
||||
target.voice_type = GLOB.voice_types[value]
|
||||
|
||||
|
||||
/datum/preference/choiced/voice_type/deserialize(input, datum/preferences/preferences)
|
||||
var/datum/species/species_type = preferences.read_preference(/datum/preference/choiced/species)
|
||||
var/species_id = initial(species_type.id)
|
||||
|
||||
var/datum/voice/test = GLOB.voice_types[input]
|
||||
|
||||
if (!test || !test.can_use(species_id))
|
||||
return create_informed_default_value(preferences)
|
||||
|
||||
return ..(input, preferences)
|
||||
@@ -514,6 +514,8 @@ GLOBAL_LIST_EMPTY(features_by_species)
|
||||
C.regenerate_icons()
|
||||
SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)
|
||||
|
||||
if(!(C.voice_type?.can_use(id)))
|
||||
C.voice_type = get_random_valid_voice(id)
|
||||
|
||||
/datum/species/proc/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load)
|
||||
if(C.dna.species.exotic_bloodtype)
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
GLOB.mob_living_list += src
|
||||
if(startDead)
|
||||
death(FALSE)
|
||||
if(!voice_type)
|
||||
voice_type = pick(voice_type2sound) //yogs edit (stolen from monke)
|
||||
|
||||
/mob/living/prepare_huds()
|
||||
..()
|
||||
|
||||
@@ -233,22 +233,6 @@ GLOBAL_LIST_INIT(special_radio_keys, list(
|
||||
spans |= SPAN_ITALICS
|
||||
|
||||
send_speech(message, message_range, src, bubble_type, spans, language, message_mods)
|
||||
|
||||
//yogs edit (stolen from monkestation)
|
||||
///Play a sound to indicate we just spoke
|
||||
if(client && !HAS_TRAIT(src, TRAIT_SIGN_LANG))
|
||||
var/ending = copytext_char(message, -1)
|
||||
var/sound/speak_sound
|
||||
if(SPAN_HELIUM in spans)
|
||||
speak_sound = sound('sound/effects/mousesqueek.ogg')
|
||||
else if(ending == "?")
|
||||
speak_sound = voice_type2sound[voice_type]["?"]
|
||||
else if(ending == "!")
|
||||
speak_sound = voice_type2sound[voice_type]["!"]
|
||||
else
|
||||
speak_sound = voice_type2sound[voice_type][voice_type]
|
||||
playsound(src, speak_sound, 300, 1, SHORT_RANGE_SOUND_EXTRARANGE-2, falloff_exponent = 1, pressure_affected = FALSE, ignore_walls = FALSE, use_reverb = FALSE)
|
||||
//yogs change end
|
||||
|
||||
return on_say_success(message,message_range,succumbed, spans, language, message_mods)//Yogs
|
||||
|
||||
@@ -318,6 +302,15 @@ GLOBAL_LIST_INIT(special_radio_keys, list(
|
||||
eavesdropping = stars(message)
|
||||
eavesrendered = compose_message(src, message_language, eavesdropping, , spans, message_mods)
|
||||
|
||||
|
||||
|
||||
//yogs edit (stolen from monkestation and moved)
|
||||
///Play a sound to indicate we just spoke
|
||||
var/sound/speak_sound
|
||||
if(client && voice_type && istype(voice_type))
|
||||
speak_sound = voice_type.get_sound(src, message, spans)
|
||||
//yogs change end
|
||||
|
||||
var/rendered = compose_message(src, message_language, message, , spans, message_mods)
|
||||
for(var/_AM in listening)
|
||||
var/atom/movable/AM = _AM
|
||||
@@ -325,6 +318,12 @@ GLOBAL_LIST_INIT(special_radio_keys, list(
|
||||
AM.Hear(eavesrendered, src, message_language, eavesdropping, , spans, message_mods)
|
||||
else
|
||||
AM.Hear(rendered, src, message_language, message, , spans, message_mods)
|
||||
if(speak_sound && ismob(AM))
|
||||
var/mob/hearing_mob = AM
|
||||
if(hearing_mob.client?.prefs?.read_preference(/datum/preference/toggle/speech_hear) && hearing_mob.has_language(message_language))
|
||||
var/volume = hearing_mob.client?.prefs?.read_preference(/datum/preference/numeric/speech_volume) || DEFAULT_SPEECH_VOLUME
|
||||
volume *= 6 //the sounds are actually really quiet, we just reduced the numbers shown in preferences to not confuse players
|
||||
hearing_mob.playsound_local(src, speak_sound, volume, TRUE, pressure_affected = FALSE, use_reverb = FALSE) //virtualspeaker handles radio stuff
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIVING_SAY_SPECIAL, src, message)
|
||||
|
||||
//speech bubble
|
||||
|
||||
@@ -175,6 +175,8 @@ export type PreferencesMenuData = {
|
||||
|
||||
earned_skillcapes: string[];
|
||||
|
||||
available_voices: string[];
|
||||
|
||||
window: Window;
|
||||
};
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ export type FeatureChoicedServerData = {
|
||||
|
||||
export type FeatureChoiced = Feature<string, string, FeatureChoicedServerData>;
|
||||
|
||||
const capitalizeFirstLetter = (text: string) => (
|
||||
export const capitalizeFirstLetter = (text: string) => (
|
||||
text.toString().charAt(0).toUpperCase() + text.toString().slice(1)
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { useBackend } from "../../../../../backend";
|
||||
import { PreferencesMenuData } from "../../../data";
|
||||
import { sortStrings } from "common/collections";
|
||||
import { StandardizedDropdown, capitalizeFirstLetter, FeatureChoiced, FeatureChoicedServerData, FeatureValueProps } from "../base";
|
||||
|
||||
const VoiceDropdownInput = (
|
||||
props: FeatureValueProps<string, string, FeatureChoicedServerData> & {
|
||||
disabled?: boolean,
|
||||
}, context) => {
|
||||
const serverData = props.serverData;
|
||||
if (!serverData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { data } = useBackend<PreferencesMenuData>(context);
|
||||
|
||||
const displayNames = serverData.display_names || Object.fromEntries(serverData.choices.map(choice => [choice, capitalizeFirstLetter(choice)]));
|
||||
|
||||
let choices = sortStrings(data.available_voices);
|
||||
|
||||
return (<StandardizedDropdown
|
||||
choices={choices}
|
||||
disabled={props.disabled}
|
||||
displayNames={displayNames}
|
||||
onSetValue={props.handleSetValue}
|
||||
value={props.value}
|
||||
/>);
|
||||
};
|
||||
|
||||
export const voice_type: FeatureChoiced = {
|
||||
name: "Voice",
|
||||
component: VoiceDropdownInput,
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Feature, FeatureNumberInput, CheckboxInput, FeatureToggle } from "../base";
|
||||
|
||||
export const speech_hear: FeatureToggle = {
|
||||
name: "Hear speech sounds",
|
||||
category: "SOUND",
|
||||
description: "If turned off, speech sounds will be muted for you.",
|
||||
component: CheckboxInput,
|
||||
};
|
||||
|
||||
export const speech_volume: Feature<number> = {
|
||||
name: "Speech volume",
|
||||
category: "SOUND",
|
||||
description: "Controls the volume at which you hear in-person speech sounds.",
|
||||
component: FeatureNumberInput,
|
||||
};
|
||||
|
||||
// export const speech_hear_radio: FeatureToggle = {
|
||||
// name: "Hear radio speech",
|
||||
// category: "SOUND",
|
||||
// description: "If turned off, speech sounds over radio channels will be muted for you.",
|
||||
// component: CheckboxInput,
|
||||
// };
|
||||
|
||||
// export const speech_volume_radio: Feature<number> = {
|
||||
// name: "Speech radio volume",
|
||||
// category: "SOUND",
|
||||
// description: "Controls the volume at which you hear speech sounds over radio channels.",
|
||||
// component: FeatureNumberInput,
|
||||
// };
|
||||
@@ -2319,6 +2319,7 @@
|
||||
#include "code\modules\client\preferences\skin_tone.dm"
|
||||
#include "code\modules\client\preferences\sounds.dm"
|
||||
#include "code\modules\client\preferences\species.dm"
|
||||
#include "code\modules\client\preferences\speech_sounds.dm"
|
||||
#include "code\modules\client\preferences\tgui.dm"
|
||||
#include "code\modules\client\preferences\tooltips.dm"
|
||||
#include "code\modules\client\preferences\ui_style.dm"
|
||||
@@ -2335,6 +2336,7 @@
|
||||
#include "code\modules\client\preferences\middleware\random.dm"
|
||||
#include "code\modules\client\preferences\middleware\skillcapes.dm"
|
||||
#include "code\modules\client\preferences\middleware\species.dm"
|
||||
#include "code\modules\client\preferences\middleware\voice_type.dm"
|
||||
#include "code\modules\client\preferences\migrations\legacy_mood_migration.dm"
|
||||
#include "code\modules\client\preferences\migrations\tgui_prefs_migration.dm"
|
||||
#include "code\modules\client\preferences\species_features\basic.dm"
|
||||
@@ -4478,6 +4480,7 @@
|
||||
#include "yogstation\code\modules\mob\living\life.dm"
|
||||
#include "yogstation\code\modules\mob\living\living.dm"
|
||||
#include "yogstation\code\modules\mob\living\living_defines.dm"
|
||||
#include "yogstation\code\modules\mob\living\voice_types.dm"
|
||||
#include "yogstation\code\modules\mob\living\brain\brain_item.dm"
|
||||
#include "yogstation\code\modules\mob\living\brain\MMI.dm"
|
||||
#include "yogstation\code\modules\mob\living\carbon\carbon.dm"
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
var/ignores_capitalism = FALSE // Decides whether vending machines will just always give them shit for free or not
|
||||
|
||||
///The talk chime set to use when speaking.
|
||||
var/voice_type
|
||||
var/datum/voice/voice_type
|
||||
|
||||
96
yogstation/code/modules/mob/living/voice_types.dm
Normal file
96
yogstation/code/modules/mob/living/voice_types.dm
Normal file
@@ -0,0 +1,96 @@
|
||||
GLOBAL_LIST_INIT(voice_types, generate_voice_types()) //we have a list of all voice types that players reference to, rather than creating a new one for each character
|
||||
|
||||
/proc/generate_voice_types()
|
||||
. = list()
|
||||
for(var/path in subtypesof(/datum/voice))
|
||||
var/datum/voice/new_type = new path()
|
||||
.[new_type.name] = new_type
|
||||
|
||||
/// Returns a voice datum that is valid for the input species
|
||||
/proc/get_random_valid_voice(species)
|
||||
var/list/valid = list()
|
||||
for(var/i in GLOB.voice_types)
|
||||
var/datum/voice/test = GLOB.voice_types[i]
|
||||
if(test.can_use(species))
|
||||
valid |= i
|
||||
|
||||
var/voice = GLOB.voice_types[pick(GLOB.voice_types)]
|
||||
if(length(valid))
|
||||
voice = GLOB.voice_types[pick(valid)]
|
||||
return voice
|
||||
|
||||
/datum/voice
|
||||
var/name = "debug"
|
||||
|
||||
/// list of sounds used any time it isn't a question or exclamation
|
||||
var/list/normal
|
||||
/// list of sounds used for when adding ! at the end
|
||||
var/list/exclamation
|
||||
/// list of sounds used for when adding ? at the end
|
||||
var/list/question
|
||||
|
||||
/// set this to false if you don't want people to be able to select it
|
||||
var/selectable = TRUE
|
||||
|
||||
///if this is initialized, a species needs to be on this list to pick it (unused)
|
||||
var/list/species_whitelist
|
||||
///needs to not be on this list to pick it (unused)
|
||||
var/list/species_blacklist
|
||||
|
||||
/datum/voice/proc/get_sound(mob/living/speaker, message, list/spans)
|
||||
if(HAS_TRAIT(speaker, TRAIT_SIGN_LANG))
|
||||
return
|
||||
|
||||
if(SPAN_HELIUM in spans) //lol, squeeky
|
||||
return 'sound/effects/mousesqueek.ogg'
|
||||
|
||||
var/ending = copytext_char(message, -1)
|
||||
|
||||
if(ending == "?" && length(question))
|
||||
return pick(question)
|
||||
|
||||
if(ending == "!" && length(exclamation))
|
||||
return pick(exclamation)
|
||||
|
||||
if(!length(normal))
|
||||
return
|
||||
|
||||
//otherwise, just pick one of the regular ones
|
||||
return pick(normal)
|
||||
|
||||
/datum/voice/proc/can_use(species)
|
||||
if(!selectable)
|
||||
return FALSE
|
||||
if(species_blacklist && (species in species_blacklist))
|
||||
return FALSE
|
||||
if(species_whitelist && !(species in species_whitelist))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/voice/high
|
||||
name = "High pitched"
|
||||
|
||||
normal = list('goon/sound/speak_2.ogg')
|
||||
exclamation = list('goon/sound/speak_2_exclaim.ogg')
|
||||
question = list('goon/sound/speak_2_ask.ogg')
|
||||
|
||||
/datum/voice/middle
|
||||
name = "Medium pitched"
|
||||
|
||||
normal = list('goon/sound/speak_1.ogg')
|
||||
exclamation = list('goon/sound/speak_1_exclaim.ogg')
|
||||
question = list('goon/sound/speak_1_ask.ogg')
|
||||
|
||||
/datum/voice/low
|
||||
name = "Low pitched"
|
||||
|
||||
normal = list('goon/sound/speak_4.ogg')
|
||||
exclamation = list('goon/sound/speak_4_exclaim.ogg')
|
||||
question = list('goon/sound/speak_4_ask.ogg')
|
||||
|
||||
/datum/voice/wonky
|
||||
name = "Wonky"
|
||||
|
||||
normal = list('goon/sound/speak_3.ogg')
|
||||
exclamation = list('goon/sound/speak_3_exclaim.ogg')
|
||||
question = list('goon/sound/speak_3_ask.ogg')
|
||||
Reference in New Issue
Block a user