Merge pull request #15677 from deathride58/vocalbark

Vocal barks - Fully customizable noises for talking!
This commit is contained in:
silicons
2022-06-10 22:10:44 -07:00
committed by GitHub
24 changed files with 416 additions and 16 deletions
+4
View File
@@ -50,6 +50,10 @@
H.dna.features["flavor_text"] = "" //Oh no.
H.dna.features["body_model"] = H.gender
H.set_bark(pick(GLOB.bark_random_list))
H.vocal_pitch = BARK_PITCH_RAND(H.gender)
H.vocal_pitch_range = BARK_VARIANCE_RAND
SEND_SIGNAL(H, COMSIG_HUMAN_ON_RANDOMIZE)
H.update_body(TRUE)
+79 -3
View File
@@ -140,6 +140,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/modified_limbs = list() //prosthetic/amputated limbs
var/chosen_limb_id //body sprite selected to load for the users limbs, null means default, is sanitized when loaded
// Vocal bark prefs
var/bark_id = "mutedc3"
var/bark_speed = 4
var/bark_pitch = 1
var/bark_variance = 0.2
COOLDOWN_DECLARE(bark_previewing)
/// Security record note section
var/security_records
/// Medical record note section
@@ -795,11 +802,21 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>Speech preferences</h2>"
dat += "<b>Custom Speech Verb:</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=speech_verb;task=input'>[custom_speech_verb]</a><BR>"
dat += "<a style='display:block;width:100px' href='?_src_=prefs;preference=speech_verb;task=input'>[custom_speech_verb]</a><BR>"
dat += "<b>Custom Tongue:</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=tongue;task=input'>[custom_tongue]</a><BR>"
dat += "<a style='display:block;width:100px' href='?_src_=prefs;preference=tongue;task=input'>[custom_tongue]</a><BR>"
dat += "<b>Additional Language</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=language;task=input'>[additional_language]</a><BR>"
dat += "<a style='display:block;width:100px' href='?_src_=prefs;preference=language;task=input'>[additional_language]</a><BR>"
dat += "</td>"
dat += "<td width='340px' height='300px' valign='top'>"
dat += "<h2>Vocal Bark preferences</h2>"
var/datum/bark/B = GLOB.bark_list[bark_id]
dat += "<b>Vocal Bark Sound:</b><BR>"
dat += "<a style='display:block;width:200px' href='?_src_=prefs;preference=barksound;task=input'>[B ? initial(B.name) : "INVALID"]</a><BR>"
dat += "<b>Vocal Bark Speed:</b> <a href='?_src_=prefs;preference=barkspeed;task=input'>[bark_speed]</a><BR>"
dat += "<b>Vocal Bark Pitch:</b> <a href='?_src_=prefs;preference=barkpitch;task=input'>[bark_pitch]</a><BR>"
dat += "<b>Vocal Bark Variance:</b> <a href='?_src_=prefs;preference=barkvary;task=input'>[bark_variance]</a><BR>"
dat += "<BR><a href='?_src_=prefs;preference=barkpreview'>Preview Bark</a><BR>"
dat += "</td>"
dat += "</tr></table>"
@@ -2555,6 +2572,43 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(selected_language)
additional_language = selected_language
if("barksound")
var/list/woof_woof = list()
for(var/path in GLOB.bark_list)
var/datum/bark/B = GLOB.bark_list[path]
if(initial(B.ignore))
continue
if(initial(B.ckeys_allowed))
var/list/allowed = initial(B.ckeys_allowed)
if(!allowed.Find(user.client.ckey))
continue
woof_woof[initial(B.name)] = initial(B.id)
var/new_bork = input(user, "Choose your desired vocal bark", "Character Preference") as null|anything in woof_woof
if(new_bork)
bark_id = woof_woof[new_bork]
var/datum/bark/B = GLOB.bark_list[bark_id] //Now we need sanitization to take into account bark-specific min/max values
bark_speed = round(clamp(bark_speed, initial(B.minspeed), initial(B.maxspeed)), 1)
bark_pitch = clamp(bark_pitch, initial(B.minpitch), initial(B.maxpitch))
bark_variance = clamp(bark_variance, initial(B.minvariance), initial(B.maxvariance))
if("barkspeed")
var/datum/bark/B = GLOB.bark_list[bark_id]
var/borkset = input(user, "Choose your desired bark speed (Higher is slower, lower is faster). Min: [initial(B.minspeed)]. Max: [initial(B.maxspeed)]", "Character Preference") as null|num
if(borkset)
bark_speed = round(clamp(borkset, initial(B.minspeed), initial(B.maxspeed)), 1)
if("barkpitch")
var/datum/bark/B = GLOB.bark_list[bark_id]
var/borkset = input(user, "Choose your desired baseline bark pitch. Min: [initial(B.minpitch)]. Max: [initial(B.maxpitch)]", "Character Preference") as null|num
if(borkset)
bark_pitch = clamp(borkset, initial(B.minpitch), initial(B.maxpitch))
if("barkvary")
var/datum/bark/B = GLOB.bark_list[bark_id]
var/borkset = input(user, "Choose your desired baseline bark pitch. Min: [initial(B.minvariance)]. Max: [initial(B.maxvariance)]", "Character Preference") as null|num
if(borkset)
bark_variance = clamp(borkset, initial(B.minvariance), initial(B.maxvariance))
if("bodysprite")
var/selected_body_sprite = input(user, "Choose your desired body sprite", "Character Preference") as null|anything in pref_species.allowed_limb_ids
if(selected_body_sprite)
@@ -3015,6 +3069,23 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("hud_toggle_flash")
hud_toggle_flash = !hud_toggle_flash
if("barkpreview")
if(SSticker.current_state == GAME_STATE_STARTUP) //Timers don't tick at all during game startup, so let's just give an error message
to_chat(user, "<span class='warning'>Bark previews can't play during initialization!</span>")
return
if(!COOLDOWN_FINISHED(src, bark_previewing))
return
if(!parent || !parent.mob)
return
COOLDOWN_START(src, bark_previewing, (5 SECONDS))
var/atom/movable/barkbox = new(get_turf(parent.mob))
barkbox.set_bark(bark_id)
var/total_delay
for(var/i in 1 to (round((32 / bark_speed)) + 1))
addtimer(CALLBACK(barkbox, /atom/movable/proc/bark, list(parent.mob), 7, 70, BARK_DO_VARY(bark_pitch, bark_variance)), total_delay)
total_delay += rand(DS2TICKS(bark_speed/4), DS2TICKS(bark_speed/4) + DS2TICKS(bark_speed/4)) TICKS
QDEL_IN(barkbox, total_delay)
if("save")
save_preferences()
save_character()
@@ -3236,6 +3307,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.additional_language = language_entry
character.grant_language(language_entry, TRUE, TRUE)
character.set_bark(bark_id)
character.vocal_speed = bark_speed
character.vocal_pitch = bark_pitch
character.vocal_pitch_range = bark_variance
//limb stuff, only done when initially spawning in
if(initial_spawn)
//delete any existing prosthetic limbs to make sure no remnant prosthetics are left over - But DO NOT delete those that are species-related
+19 -1
View File
@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults.
// Only raise this value when changing the meaning/format/name/layout of an existing value
// where you would want the updater procs below to run
#define SAVEFILE_VERSION_MAX 54
#define SAVEFILE_VERSION_MAX 55
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -42,6 +42,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
//if your savefile is 3 months out of date, then 'tough shit'.
/datum/preferences/proc/update_preferences(current_version, savefile/S)
if(current_version < 55) //Bitflag toggles don't set their defaults when they're added, always defaulting to off instead.
toggles |= SOUND_BARK
if(current_version < 46) //If you remove this, remove force_reset_keybindings() too.
force_reset_keybindings_direct(TRUE)
addtimer(CALLBACK(src, .proc/force_reset_keybindings), 30) //No mob available when this is run, timer allows user choice.
@@ -845,6 +847,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_silicon_flavor_text"] >> features["silicon_flavor_text"]
S["feature_ooc_notes"] >> features["ooc_notes"]
// Barks
S["bark_id"] >> bark_id
S["bark_speed"] >> bark_speed
S["bark_pitch"] >> bark_pitch
S["bark_variance"] >> bark_variance
S["vore_flags"] >> vore_flags
S["vore_taste"] >> vore_taste
S["vore_smell"] >> vore_smell
@@ -1022,6 +1030,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
scars_list["4"] = sanitize_text(scars_list["4"])
scars_list["5"] = sanitize_text(scars_list["5"])
bark_id = sanitize_inlist(bark_id, GLOB.bark_list, pick(GLOB.bark_random_list))
var/datum/bark/bark_path = GLOB.bark_list[bark_id]
bark_speed = sanitize_num_clamp(bark_speed, initial(bark_path.minspeed), initial(bark_path.maxspeed), initial(bark_speed))
bark_pitch = sanitize_num_clamp(bark_pitch, initial(bark_path.minpitch), initial(bark_path.maxpitch), BARK_PITCH_RAND(gender))
bark_variance = sanitize_num_clamp(bark_variance, initial(bark_path.minvariance), initial(bark_path.maxvariance), BARK_VARIANCE_RAND)
joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole))
//Validate job prefs
for(var/j in job_preferences)
@@ -1089,6 +1103,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["custom_speech_verb"] , custom_speech_verb)
WRITE_FILE(S["custom_tongue"] , custom_tongue)
WRITE_FILE(S["additional_language"] , additional_language)
WRITE_FILE(S["bark_id"] , bark_id)
WRITE_FILE(S["bark_speed"] , bark_speed)
WRITE_FILE(S["bark_pitch"] , bark_pitch)
WRITE_FILE(S["bark_variance"] , bark_variance)
// records
WRITE_FILE(S["security_records"] , security_records)
@@ -227,6 +227,17 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggleprayersounds)()
return C.prefs.toggles & SOUND_PRAYERS
TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggle_bark)()
set name = "Hear/Silence Vocal Barks"
set category = "Preferences"
set desc = "Hear Vocal Barks"
usr.client.prefs.toggles ^= SOUND_BARK
usr.client.prefs.save_preferences()
to_chat(usr, "You will now [(usr.client.prefs.toggles & SOUND_BARK) ? "hear" : "no longer hear"] vocal barks when other people talk.")
SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Vocal Barks", "[usr.client.prefs.toggles & SOUND_BARK ? "Enabled" : "Disabled"]"))
/datum/verbs/menu/Settings/Sound/toggle_bark/Get_checked(client/C)
return C.prefs.toggles & SOUND_BARK
/datum/verbs/menu/Settings/Sound/verb/stop_client_sounds()
set name = "Stop Sounds"
set category = "Preferences"
@@ -24,6 +24,9 @@
var/rando_race = pick(GLOB.roundstart_races)
pref_species = new rando_race()
features = random_features(pref_species?.id, gender)
bark_id = pick(GLOB.bark_random_list)
bark_pitch = BARK_PITCH_RAND(gender)
bark_variance = BARK_VARIANCE_RAND
age = rand(AGE_MIN,AGE_MAX)
/datum/preferences/proc/update_preview_icon(current_tab)
+21 -2
View File
@@ -297,8 +297,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
AM.Hear(rendered, src, message_language, message, null, spans, message_mode, source)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIVING_SAY_SPECIAL, src, message)
if(client && !eavesdrop_range && say_test(message) == "2") // Yell hook
process_yelling(listening, rendered, src, message_language, message, spans, message_mode, source)
var/is_yell = (say_test(message) == "2")
if(client && !eavesdrop_range && is_yell) // Yell hook
listening |= process_yelling(listening, rendered, src, message_language, message, spans, message_mode, source)
//speech bubble
var/list/speech_bubble_recipients = list()
@@ -309,6 +310,22 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_recipients, 30)
//Listening gets trimmed here if a vocal bark's present. If anyone ever makes this proc return listening, make sure to instead initialize a copy of listening in here to avoid wonkiness
if(vocal_bark || vocal_bark_id)
for(var/mob/M in listening)
if(!M.client)
continue
if(!(M.client.prefs.toggles & SOUND_BARK))
listening -= M
var/barks = min(round((LAZYLEN(message) / vocal_speed)) + 1, BARK_MAX_BARKS)
var/total_delay
for(var/i in 1 to barks)
if(total_delay > BARK_MAX_TIME)
break
addtimer(CALLBACK(src, /atom/movable/proc/bark, listening, (message_range * (is_yell ? 4 : 1)), (vocal_volume * (is_yell ? 1.5 : 1)), BARK_DO_VARY(vocal_pitch, vocal_pitch_range)), total_delay)
total_delay += rand(DS2TICKS((vocal_speed / BARK_SPEED_BASELINE) * (is_yell ? 0.5 : 1)), DS2TICKS(vocal_speed / BARK_SPEED_BASELINE) + DS2TICKS((vocal_speed / BARK_SPEED_BASELINE) * (is_yell ? 0.5 : 1))) TICKS
/atom/movable/proc/process_yelling(list/already_heard, rendered, atom/movable/speaker, datum/language/message_language, message, list/spans, message_mode, obj/source)
if(last_yell > (world.time - 10))
to_chat(src, "<span class='warning'>Your voice doesn't project as far as you try to yell in such quick succession.") // yeah no, no spamming an expensive floodfill.
@@ -333,6 +350,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/atom/movable/AM = _AM
AM.Hear(rendered, speaker, message_language, message, null, spans, message_mode, source)
return overhearing
/mob/proc/binarycheck()
return FALSE
@@ -50,6 +50,9 @@
typing_indicator_state = /obj/effect/overlay/typing_indicator/machine
vocal_bark_id = "synth"
vocal_pitch_range = 0.1
/mob/living/silicon/Initialize(mapload)
. = ..()
GLOB.silicon_mobs += src
@@ -35,6 +35,9 @@
collar_type = "cat"
var/held_icon = "cat2"
footstep_type = FOOTSTEP_MOB_CLAW
vocal_bark_id = "mutedc4"
vocal_pitch = 1.4
vocal_pitch_range = 0.4
/mob/living/simple_animal/pet/cat/Initialize(mapload)
. = ..()
@@ -20,6 +20,9 @@
footstep_type = FOOTSTEP_MOB_CLAW
vocal_bark_id = "bullet"
vocal_speed = 6
/mob/living/simple_animal/pet/dog/ComponentInitialize()
. = ..()
AddElement(/datum/element/wuv, "yaps happily!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "growls!", EMOTE_AUDIBLE)
@@ -639,6 +642,8 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
mob_size = MOB_SIZE_SMALL
collar_type = "puppy"
vocal_pitch = 1.6
//puppies cannot wear anything.
/mob/living/simple_animal/pet/dog/corgi/puppy/Topic(href, href_list)
if(href_list["remove_inv"] || href_list["add_inv"])
@@ -660,6 +665,8 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
maxbodytemp = T0C + 40
held_icon = "void_puppy"
vocal_pitch = 0.6
/mob/living/simple_animal/pet/dog/corgi/puppy/void/Process_Spacemove(movement_dir = 0)
return 1 //Void puppies can navigate space.
@@ -36,6 +36,7 @@
var/datum/reagent/milk_reagent = /datum/reagent/consumable/milk
footstep_type = FOOTSTEP_MOB_SHOE
vocal_bark_id = "banjoc3"
/mob/living/simple_animal/hostile/retaliate/goat/Initialize(mapload, /datum/reagent/milk_reagent)
udder = new (null, milk_reagent)
@@ -143,6 +144,8 @@
blood_volume = BLOOD_VOLUME_NORMAL
footstep_type = FOOTSTEP_MOB_SHOE
vocal_bark_id = "mutedc2"
vocal_pitch = 1.2
/mob/living/simple_animal/cow/Initialize(mapload)
udder = new(null, milk_reagent)
@@ -247,6 +250,8 @@
gold_core_spawnable = FRIENDLY_SPAWN
footstep_type = FOOTSTEP_MOB_CLAW
vocal_bark_id = "squeak"
vocal_pitch = 1.4
/mob/living/simple_animal/chick/Initialize(mapload)
. = ..()
@@ -309,6 +314,9 @@
var/static/chicken_count = 0
footstep_type = FOOTSTEP_MOB_CLAW
vocal_bark_id = "synthgrunt"
vocal_pitch = 1.4
vocal_pitch_range = 0.4
/mob/living/simple_animal/chicken/Initialize(mapload)
. = ..()
@@ -403,6 +411,8 @@
var/static/kiwi_count = 0
footstep_type = FOOTSTEP_MOB_CLAW
vocal_bark_id = "squeak"
vocal_pitch = 1.4
/mob/living/simple_animal/kiwi/Destroy()
--kiwi_count
@@ -481,6 +491,8 @@
gold_core_spawnable = FRIENDLY_SPAWN
footstep_type = FOOTSTEP_MOB_CLAW
vocal_bark_id = "squeak"
vocal_pitch = 1.4
/mob/living/simple_animal/babyKiwi/Initialize(mapload)
. = ..()
@@ -557,3 +569,4 @@
maxHealth = 75
blood_volume = BLOOD_VOLUME_NORMAL
footstep_type = FOOTSTEP_MOB_SHOE
vocal_bark_id = "mutedc4"
@@ -23,6 +23,11 @@
gold_core_spawnable = FRIENDLY_SPAWN
footstep_type = FOOTSTEP_MOB_CLAW
vocal_bark_id = "bullet"
vocal_speed = 2
vocal_pitch = 1.6
vocal_pitch_range = 0.4
/mob/living/simple_animal/pet/fox/ComponentInitialize()
. = ..()
AddElement(/datum/element/mob_holder, "fox")
@@ -29,6 +29,8 @@
gold_core_spawnable = FRIENDLY_SPAWN
var/chew_probability = 1
faction = list("rat")
vocal_bark_id = "squeak"
vocal_pitch = 1.4
/mob/living/simple_animal/mouse/Initialize(mapload)
. = ..()
@@ -29,6 +29,8 @@
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
pressure_resistance = 200
vocal_bark_id = "squeak"
vocal_pitch_range = 0.4
/mob/living/simple_animal/pet/plushie/ComponentInitialize()
. = ..()