Ports Bloopers (Vocal Barks) from FluffySTG (#987)

<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->

## About The Pull Request

Ports this: https://github.com/Fluffy-Frontier/FluffySTG/pull/106
Allows for characters to bloop and bark. You can choose a bark for your
character and adjust its pitch, range, and speed.
You can preview your blooper under Character Preferences.
The preference is toggled off by default in Game Preferences.
Allows for admins to disable global bloopers
Includes Goon assets, which are properly attributed.

## Why It's Good For The Game

This isn't a 100% of what I envisioned my original bounty was supposed
to do ( https://github.com/Bubberstation/Bubberstation/issues/688 ).
Although, I believe the players will enjoy having something like it
while I tune and adjust this in upcoming changes.

This is good for the game because audio cues coming from characters
bring a quality of life on the station. This can bring attention to a
character if they need attention from others. This allows for more
optional customization for a character.

## Proof Of Testing

Tested locally with no errors. This may cause errors on live.


https://github.com/Bubberstation/Bubberstation/assets/96078776/af28a732-276b-4d0b-8be1-f45b710856b1


## Changelog

<!-- If your PR modifies aspects of the game that can be concretely
observed by players or admins you should add a changelog. If your change
does NOT meet this description, remove this section. Be sure to properly
mark your PRs to prevent unnecessary GBP loss. You can read up on GBP
and it's effects on PRs in the tgstation guides for contributors. Please
note that maintainers freely reserve the right to remove and add tags
should they deem it appropriate. You can attempt to finagle the system
all you want, but it's best to shoot for clear communication right off
the bat. -->

🆑 Shayoki
add: Players can now choose a voice for their characters.
sound: Added a lot of 'borrowed' sounds to use as voices.
admin: Admins can globally disable Bloopers
/🆑 

<!-- Both 🆑's are required for the changelog to work! You can put
your name to the right of the first 🆑 if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->

<!-- By opening a pull request. You have read and understood the
repository rules located on the main README.md on this project. -->

---------

Co-authored-by: nevimer <77420409+nevimer@users.noreply.github.com>
Co-authored-by: lessthanthree <83487515+lessthnthree@users.noreply.github.com>
Co-authored-by: Waterpig <49160555+Majkl-J@users.noreply.github.com>
This commit is contained in:
gavla
2024-02-19 14:48:52 -06:00
committed by GitHub
parent 2cda0592df
commit 2bcb423aae
93 changed files with 841 additions and 3 deletions

View File

@@ -0,0 +1,2 @@
GLOBAL_LIST_EMPTY(blooper_list)
GLOBAL_LIST_EMPTY(blooper_random_list)

View File

@@ -0,0 +1,19 @@
//BLOOPER defines
#define BLOOPER_DEFAULT_MINPITCH 0.4
#define BLOOPER_DEFAULT_MAXPITCH 2
#define BLOOPER_DEFAULT_MINVARY 0.1
#define BLOOPER_DEFAULT_MAXVARY 0.8
#define BLOOPER_DEFAULT_MINSPEED 2
#define BLOOPER_DEFAULT_MAXSPEED 16
#define BLOOPER_SPEED_BASELINE 4 //Used to calculate delay between BLOOPERs, any BLOOPER speeds below this feature higher BLOOPER density, any speeds above feature lower BLOOPER density. Keeps BLOOPERing length consistent
#define BLOOPER_MAX_BLOOPERS 24
#define BLOOPER_MAX_TIME (1.5 SECONDS) // More or less the amount of time the above takes to process through with a BLOOPER speed of 2.
#define BLOOPER_PITCH_RAND(gend) ((gend == MALE ? rand(60, 120) : (gend == FEMALE ? rand(80, 140) : rand(60,140))) / 100) //Macro for determining random pitch based off gender
#define BLOOPER_VARIANCE_RAND (rand(BLOOPER_DEFAULT_MINVARY * 100, BLOOPER_DEFAULT_MAXVARY * 100) / 100) //Macro for randomizing BLOOPER variance to reduce the amount of copy-pasta necessary for that
#define BLOOPER_DO_VARY(pitch, variance) (rand(((pitch * 100) - (variance*50)), ((pitch*100) + (variance*50))) / 100)
#define BLOOPER_SOUND_FALLOFF_EXPONENT 0.5 //At lower ranges, we want the exponent to be below 1 so that whispers don't sound too awkward. At higher ranges, we want the exponent fairly high to make yelling less obnoxious

View File

@@ -54,6 +54,13 @@
GLOB.laugh_types[L.name] = spath
sort_list(GLOB.laugh_types, GLOBAL_PROC_REF(cmp_typepaths_asc))
//SKYRAT EDIT END
//THE BUBBER EDIT ADDITION BEGIN - Blooper
for(var/sound_blooper_path in subtypesof(/datum/blooper))
var/datum/blooper/B = new sound_blooper_path()
GLOB.blooper_list[B.id] = sound_blooper_path
if(B.allow_random)
GLOB.blooper_random_list[B.id] = sound_blooper_path
//THE BUBBER EDIT END
/// Inits GLOB.species_list. Not using GLOBAL_LIST_INIT b/c it depends on GLOB.string_lists
/proc/init_species_list()

View File

@@ -479,7 +479,12 @@
if(NAMEOF(src, glide_size))
set_glide_size(var_value)
. = TRUE
// THE BUBBER EDIT ADDITION BEGIN - BLOOPER
if(NAMEOF(src, blooper)) // Sorry, Vishenka.
if(isfile(var_value))
blooper = sound(var_value) //bark() expects vocal_bark to already be a sound datum, for performance reasons. adminbus QoL!
. = TRUE
// THE BUBBER EDIT ADDITION END
if(!isnull(.))
datum_flags |= DF_VAR_EDITED
return

View File

@@ -570,7 +570,12 @@
for(var/datum/quirk/target_quirk in target.quirks)
LAZYADD(new_profile.quirks, new target_quirk.type)
//SKYRAT EDIT END
//THE BUBBER EDIT ADDITION BEGIN - Voice Bark
new_profile.blooper_id = target.blooper_id
new_profile.blooper_pitch = target.blooper_pitch
new_profile.blooper_speed = target.blooper_speed
new_profile.blooper_pitch_range = target.blooper_pitch_range
//THE BUBBER EDIT END
// Grab skillchips they have
new_profile.skillchips = target.clone_skillchip_list(TRUE)
@@ -949,7 +954,13 @@
user.name = user.get_visible_name()
current_profile = chosen_profile
// SKYRAT EDIT END
//THE BUBBER EDIT ADDITION BEGIN - Voice Bark
user.blooper = null
user.blooper_id = chosen_profile.blooper_id
user.blooper_pitch = chosen_profile.blooper_pitch
user.blooper_speed = chosen_profile.blooper_speed
user.blooper_pitch_range = chosen_profile.blooper_pitch_range
//THE BUBBER EDIT END
// Changeling profile themselves. Store a data to store what every DNA instance looked like.
/datum/changeling_profile
/// The name of the profile / the name of whoever this profile source.

1
goon/LICENSE.md Normal file
View File

@@ -0,0 +1 @@
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 United States License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/us/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.

8
goon/README.md Normal file
View File

@@ -0,0 +1,8 @@
# Goon-ported-assets
All files excluding this one you're reading right now have been most likely, taken from [goonstation's 2016 release](https://github.com/goonstation/goonstation-2016), unless stated otherwise.
It is very likely that there are modifications to be compatible or on par with our code, however. These changes are licensed under the same license as the other goon files.
## License
See LICENSE.md

BIN
goon/sounds/blub.ogg Normal file

Binary file not shown.

BIN
goon/sounds/bottalk_1.ogg Normal file

Binary file not shown.

BIN
goon/sounds/bottalk_2.ogg Normal file

Binary file not shown.

BIN
goon/sounds/bottalk_3.ogg Normal file

Binary file not shown.

BIN
goon/sounds/bottalk_4.ogg Normal file

Binary file not shown.

BIN
goon/sounds/buwoo.ogg Normal file

Binary file not shown.

BIN
goon/sounds/cow.ogg Normal file

Binary file not shown.

BIN
goon/sounds/lizard.ogg Normal file

Binary file not shown.

BIN
goon/sounds/pug.ogg Normal file

Binary file not shown.

BIN
goon/sounds/pugg.ogg Normal file

Binary file not shown.

BIN
goon/sounds/radio.ogg Normal file

Binary file not shown.

BIN
goon/sounds/radio2.ogg Normal file

Binary file not shown.

BIN
goon/sounds/radio_ai.ogg Normal file

Binary file not shown.

BIN
goon/sounds/roach.ogg Normal file

Binary file not shown.

BIN
goon/sounds/skelly.ogg Normal file

Binary file not shown.

BIN
goon/sounds/speak_1.ogg Normal file

Binary file not shown.

BIN
goon/sounds/speak_2.ogg Normal file

Binary file not shown.

BIN
goon/sounds/speak_3.ogg Normal file

Binary file not shown.

BIN
goon/sounds/speak_4.ogg Normal file

Binary file not shown.

View File

@@ -0,0 +1,98 @@
/atom/movable
// Text-to-blooper sounds
// yes. all atoms can have a say.
var/sound/blooper
var/blooper_id
var/blooper_pitch = 1
var/blooper_pitch_range = 0.2 //Actual pitch is (pitch - (blooper_pitch_range*0.5)) to (pitch + (blooper_pitch_range*0.5))
var/blooper_volume = 50
var/blooper_speed = 4 //Lower values are faster, higher values are slower
var/blooper_current_blooper //When bloopers are queued, this gets passed to the blooper proc. If blooper_current_blooper doesn't match the args passed to the blooper proc (if passed at all), then the blooper simply doesn't play. Basic curtailing of spam~
/atom/movable/proc/set_blooper(id)
if(!id)
return FALSE
var/datum/blooper/B = GLOB.blooper_list[id]
if(!B)
return FALSE
blooper = sound(initial(B.soundpath))
blooper_id = id
return blooper
/atom/movable/proc/blooper(list/listeners, distance, volume, pitch, queue_time)
if(!GLOB.blooper_allowed)
return
if(queue_time && blooper_current_blooper != queue_time)
return
if(!blooper)
if(!blooper_id || !set_blooper(blooper_id)) //just-in-time blooper generation
return
volume = min(volume, 100)
var/turf/T = get_turf(src)
for(var/mob/M in listeners)
M.playsound_local(T, vol = volume, vary = TRUE, frequency = pitch, max_distance = distance, falloff_distance = 0, falloff_exponent = BLOOPER_SOUND_FALLOFF_EXPONENT, sound_to_use = blooper, distance_multiplier = 1)
/atom/movable/send_speech(message, range = 7, obj/source = src, bubble_type, list/spans, datum/language/message_language, list/message_mods = list(), forced = FALSE, tts_message, list/tts_filter)
. = ..()
var/list/listeners = get_hearers_in_view(range, source)
if(blooper || blooper_id)
for(var/mob/M in listeners)
if(!M.client)
continue
if(!(M.client.prefs?.read_preference(/datum/preference/toggle/hear_sound_blooper)))
listeners -= M
var/bloopers = min(round((LAZYLEN(message) / blooper_speed)) + 1, BLOOPER_MAX_BLOOPERS)
var/total_delay
blooper_current_blooper = world.time //this is juuuuust random enough to reliably be unique every time send_speech() is called, in most scenarios
for(var/i in 1 to bloopers)
if(total_delay > BLOOPER_MAX_TIME)
break
addtimer(CALLBACK(src, PROC_REF(blooper), listeners, range, blooper_volume, BLOOPER_DO_VARY(blooper_pitch, blooper_pitch_range), blooper_current_blooper), total_delay)
total_delay += rand(DS2TICKS(blooper_speed / BLOOPER_SPEED_BASELINE), DS2TICKS(blooper_speed / BLOOPER_SPEED_BASELINE) + DS2TICKS(blooper_speed / BLOOPER_SPEED_BASELINE)) TICKS
/mob/living/carbon/human/Initialize(mapload)
. = ..()
// This gives a random vocal bark to a random created person
if(!client)
set_blooper(pick(GLOB.blooper_list))
blooper_pitch = BLOOPER_PITCH_RAND(gender)
blooper_pitch_range = BLOOPER_VARIANCE_RAND
blooper_speed = rand(BLOOPER_DEFAULT_MINSPEED, BLOOPER_DEFAULT_MAXSPEED)
/randomize_human(mob/living/carbon/human/human, randomize_mutations = FALSE)
. = ..()
human.set_blooper(pick(GLOB.blooper_list))
human.blooper_pitch = BLOOPER_PITCH_RAND(human.gender)
human.blooper_pitch_range = BLOOPER_VARIANCE_RAND
human.blooper_speed = rand(BLOOPER_DEFAULT_MINSPEED, BLOOPER_DEFAULT_MAXSPEED)
/mob/living/send_speech(message_raw, message_range = 6, obj/source = src, bubble_type = bubble_icon, list/spans, datum/language/message_language = null, list/message_mods = list(), forced = null, tts_message, list/tts_filter)
. = ..()
if(client)
if(!(client.prefs.read_preference(/datum/preference/toggle/send_sound_blooper)))
return
blooper_volume = client?.prefs.read_preference(/datum/preference/numeric/sound_blooper_volume) //volume scales with your volume slider in game preferences.
if(HAS_TRAIT(src, TRAIT_SIGN_LANG) && !HAS_TRAIT(src, TRAIT_MUTE)) //if you can speak and you sign, your hands don't make a bark. Unless you are completely mute, you can have some hand bark.
return
if(message_mods[WHISPER_MODE])
blooper_volume = (client?.prefs.read_preference(/datum/preference/numeric/sound_blooper_volume)*0.5) //Whispered barked are half as loud.
message_range++
var/list/listening = get_hearers_in_view(message_range, source)
var/is_yell = (say_test(message_raw) == "2")
//Listening gets trimmed here if a blooper blooper'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(blooper || blooper_id)
for(var/mob/M in listening)
if(!M.client)
continue
if(!(M.client.prefs?.read_preference(/datum/preference/toggle/hear_sound_blooper)))
listening -= M
var/bloopers = min(round((LAZYLEN(message_raw) / blooper_speed)) + 1, BLOOPER_MAX_BLOOPERS)
var/total_delay
blooper_current_blooper = world.time
for(var/i in 1 to bloopers)
if(total_delay > BLOOPER_MAX_TIME)
break
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom/movable, blooper), listening, message_range + 1, (blooper_volume * (is_yell ? 2 : 1)), BLOOPER_DO_VARY(blooper_pitch, blooper_pitch_range), blooper_current_blooper), total_delay) //The function is zero on the seventh tile. This makes it a maximum of 1 more.
total_delay += rand(DS2TICKS(blooper_speed / BLOOPER_SPEED_BASELINE), DS2TICKS(blooper_speed / BLOOPER_SPEED_BASELINE) + DS2TICKS((blooper_speed / BLOOPER_SPEED_BASELINE) * (is_yell ? 0.5 : 1))) TICKS

View File

@@ -0,0 +1,171 @@
GLOBAL_VAR_INIT(blooper_allowed, TRUE) // For administrators
// we let borgs have some bark too
/mob/living/silicon/Login()
// This is the only found function that updates the client for borgs.
set_blooper(client.prefs.read_preference(/datum/preference/choiced/blooper))
blooper_pitch = client.prefs.read_preference(/datum/preference/numeric/blooper_speech_pitch)
blooper_speed = client.prefs.read_preference(/datum/preference/numeric/blooper_speech_speed)
blooper_pitch_range = client.prefs.read_preference(/datum/preference/numeric/blooper_pitch_range)
. = ..()
// Mechanics for Changelings
/datum/changeling_profile
var/blooper_id
var/blooper_pitch
var/blooper_pitch_range
var/blooper_speed
/datum/smite/normalblooper
name = "Normal blooper"
/datum/smite/normalblooper/effect(client/user, mob/living/carbon/human/target)
. = ..()
target.blooper = null
target.blooper_id = pick(GLOB.blooper_random_list)
target.blooper_speed = round((BLOOPER_DEFAULT_MINSPEED + BLOOPER_DEFAULT_MAXSPEED) / 2)
target.blooper_pitch = round((BLOOPER_DEFAULT_MINPITCH + BLOOPER_DEFAULT_MAXPITCH) / 2)
target.blooper_pitch_range = 0.2
/datum/admins/proc/toggleblooper()
set category = "Server"
set desc = "Toggle the annoying voices."
set name = "Toggle Vocal Barks"
toggle_blooper()
log_admin("[key_name(usr)] toggled Voice Barks.")
message_admins("[key_name_admin(usr)] toggled Voice Barks.")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Voice Bark", "[GLOB.blooper_allowed ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
/world/AVerbsAdmin()
. = ..()
return . + /datum/admins/proc/toggleblooper
/proc/toggle_blooper(toggle = null)
if(toggle != null)
if(toggle != GLOB.blooper_allowed)
GLOB.blooper_allowed = toggle
else
return
else
GLOB.blooper_allowed = !GLOB.blooper_allowed
to_chat(world, "<span class='oocplain'><B>Vocal barks have been globally [GLOB.blooper_allowed ? "enabled" : "disabled"].</B></span>")
/datum/preference/choiced/blooper
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
savefile_identifier = PREFERENCE_CHARACTER
savefile_key = "blooper_speech"
/datum/preference/choiced/blooper/init_possible_values()
return assoc_to_keys(GLOB.blooper_list)
/datum/preference/choiced/blooper/apply_to_human(mob/living/carbon/human/target, value)
target.set_blooper(value)
/datum/preference_middleware/blooper
/// Cooldown on requesting a Blooper preview.
COOLDOWN_DECLARE(blooper_cooldown)
action_delegations = list(
"play_blooper" = PROC_REF(play_blooper),
)
/datum/preference_middleware/blooper/proc/play_blooper(list/params, mob/user)
if(!COOLDOWN_FINISHED(src, blooper_cooldown))
return TRUE
var/atom/movable/blooperbox = new(get_turf(user))
blooperbox.set_blooper(preferences.read_preference(/datum/preference/choiced/blooper))
blooperbox.blooper_pitch = preferences.read_preference(/datum/preference/numeric/blooper_speech_pitch)
blooperbox.blooper_speed = preferences.read_preference(/datum/preference/numeric/blooper_speech_speed)
blooperbox.blooper_pitch_range = preferences.read_preference(/datum/preference/numeric/blooper_pitch_range)
var/total_delay
for(var/i in 1 to (round((32 / blooperbox.blooper_speed)) + 1))
addtimer(CALLBACK(blooperbox, TYPE_PROC_REF(/atom/movable, blooper), list(user), 7, 70, BLOOPER_DO_VARY(blooperbox.blooper_pitch, blooperbox.blooper_pitch_range)), total_delay)
total_delay += rand(DS2TICKS(blooperbox.blooper_speed/4), DS2TICKS(blooperbox.blooper_speed/4) + DS2TICKS(blooperbox.blooper_speed/4)) TICKS
QDEL_IN(blooperbox, total_delay)
COOLDOWN_START(src, blooper_cooldown, 2 SECONDS)
return TRUE
/datum/preference/numeric/blooper_speech_speed
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
savefile_identifier = PREFERENCE_CHARACTER
savefile_key = "blooper_speech_speed"
minimum = BLOOPER_DEFAULT_MINSPEED
maximum = BLOOPER_DEFAULT_MAXSPEED
step = 0.01
/datum/preference/numeric/blooper_speech_speed/apply_to_human(mob/living/carbon/human/target, value)
target.blooper_speed = value
/datum/preference/numeric/blooper_speech_speed/create_default_value()
return round((BLOOPER_DEFAULT_MINSPEED + BLOOPER_DEFAULT_MAXSPEED) / 2)
/datum/preference/numeric/blooper_speech_pitch
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
savefile_identifier = PREFERENCE_CHARACTER
savefile_key = "blooper_speech_pitch"
minimum = BLOOPER_DEFAULT_MINPITCH
maximum = BLOOPER_DEFAULT_MAXPITCH
step = 0.01
/datum/preference/numeric/blooper_speech_pitch/apply_to_human(mob/living/carbon/human/target, value)
target.blooper_pitch = value
/datum/preference/numeric/blooper_speech_pitch/create_default_value()
return round((BLOOPER_DEFAULT_MINPITCH + BLOOPER_DEFAULT_MAXPITCH) / 2)
/datum/preference/numeric/blooper_pitch_range
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
savefile_identifier = PREFERENCE_CHARACTER
savefile_key = "blooper_pitch_range"
minimum = BLOOPER_DEFAULT_MINVARY
maximum = BLOOPER_DEFAULT_MAXVARY
step = 0.01
/datum/preference/numeric/blooper_pitch_range/apply_to_human(mob/living/carbon/human/target, value)
target.blooper_pitch_range = value
/datum/preference/numeric/blooper_pitch_range/create_default_value()
return 0.2
/// Can I use the blooper?
/datum/preference/toggle/send_sound_blooper
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
savefile_key = "send_sound_blooper"
savefile_identifier = PREFERENCE_PLAYER
default_value = TRUE
/// Can I hear everyone else's bloops?
/datum/preference/toggle/hear_sound_blooper
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
savefile_key = "hear_sound_blooper"
savefile_identifier = PREFERENCE_PLAYER
default_value = TRUE
/// Can I have a slider to adjust the volume of the barks?
/datum/preference/numeric/sound_blooper_volume
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
savefile_key = "sound_blooper_volume"
savefile_identifier = PREFERENCE_PLAYER
minimum = 0
maximum = 60
step = 5
/// It's was stoolen from Splurt build >:3 and from fluffySTG!! nyeehehehheee!~
/datum/blooper
var/name = "None"
var/id = "No Voice"
var/soundpath
var/minpitch = BLOOPER_DEFAULT_MINPITCH
var/maxpitch = BLOOPER_DEFAULT_MAXPITCH
var/minvariance = BLOOPER_DEFAULT_MINVARY
var/maxvariance = BLOOPER_DEFAULT_MAXVARY
// Speed vars. Speed determines the number of characters required for each blooper, with lower speeds being faster with higher blooper density
var/minspeed = BLOOPER_DEFAULT_MINSPEED
var/maxspeed = BLOOPER_DEFAULT_MAXSPEED
// Visibility vars. Regardless of what's set below, these can still be obtained via adminbus and genetics. Rule of fun.
var/list/ckeys_allowed
var/ignore = FALSE // If TRUE - only for admins
var/allow_random = FALSE

View File

@@ -0,0 +1,431 @@
/datum/blooper/mutedc2
name = "Muted String (Low)"
id = "mutedc2"
soundpath = 'sound/runtime/instruments/synthesis_samples/guitar/crisis_muted/C2.ogg'
allow_random = TRUE
/datum/blooper/mutedc3
name = "Muted String (Medium)"
id = "mutedc3"
soundpath = 'sound/runtime/instruments/synthesis_samples/guitar/crisis_muted/C3.ogg'
allow_random = TRUE
/datum/blooper/mutedc4
name = "Muted String (High)"
id = "mutedc4"
soundpath = 'sound/runtime/instruments/synthesis_samples/guitar/crisis_muted/C4.ogg'
allow_random = TRUE
/datum/blooper/banjoc3
name = "Banjo (Medium)"
id = "banjoc3"
soundpath = 'sound/runtime/instruments/banjo/Cn3.ogg'
allow_random = TRUE
/datum/blooper/banjoc4
name = "Banjo (High)"
id = "banjoc4"
soundpath = 'sound/runtime/instruments/banjo/Cn4.ogg'
allow_random = TRUE
/datum/blooper/squeaky
name = "Squeaky"
id = "squeak"
soundpath = 'sound/items/toysqueak1.ogg'
maxspeed = 4
/datum/blooper/beep
name = "Beepy"
id = "beep"
soundpath = 'sound/machines/terminal_select.ogg'
maxpitch = 1 //Bringing the pitch higher just hurts your ears :<
maxspeed = 4 //This soundbyte's too short for larger speeds to not sound awkward
/datum/blooper/chitter
name = "Chittery"
id = "chitter"
minspeed = 4 //Even with the sound being replaced with a unique, shorter sound, this is still a little too long for higher speeds
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/chitter.ogg'
/datum/blooper/synthetic_grunt
name = "Synthetic (Grunt)"
id = "synthgrunt"
soundpath = 'sound/misc/bloop.ogg'
/datum/blooper/synthetic
name = "Synthetic (Normal)"
id = "synth"
soundpath = 'sound/machines/uplinkerror.ogg'
/datum/blooper/bullet
name = "Windy"
id = "bullet"
maxpitch = 1.6
soundpath = 'sound/weapons/bulletflyby.ogg'
/datum/blooper/coggers
name = "Brassy"
id = "coggers"
soundpath = 'sound/machines/clockcult/integration_cog_install.ogg'
/datum/blooper/moff/short
name = "Moff squeak"
id = "moffsqueak"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/mothsqueak.ogg'
allow_random = TRUE
ignore = FALSE
/datum/blooper/meow //Meow blooper?
name = "Meow"
id = "meow"
allow_random = TRUE
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/meow1.ogg'
minspeed = 5
maxspeed = 11
/datum/blooper/chirp
name = "Chirp"
id = "chirp"
allow_random = TRUE
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/chirp.ogg'
/datum/blooper/caw
name = "Caw"
id = "caw"
allow_random = TRUE
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/caw.ogg'
//Undertale
/datum/blooper/alphys
name = "Alphys"
id = "alphys"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_alphys.ogg'
minvariance = 0
/datum/blooper/asgore
name = "Asgore"
id = "asgore"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_asgore.ogg'
minvariance = 0
/datum/blooper/flowey
name = "Flowey (normal)"
id = "flowey1"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_flowey_1.ogg'
minvariance = 0
/datum/blooper/flowey/evil
name = "Flowey (evil)"
id = "flowey2"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_flowey_2.ogg'
minvariance = 0
/datum/blooper/papyrus
name = "Papyrus"
id = "papyrus"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_papyrus.ogg'
minvariance = 0
/datum/blooper/ralsei
name = "Ralsei"
id = "ralsei"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_ralsei.ogg'
minvariance = 0
/datum/blooper/sans //real
name = "Sans"
id = "sans"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_sans.ogg'
minvariance = 0
/datum/blooper/toriel
name = "Toriel"
id = "toriel"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_toriel.ogg'
minvariance = 0
maxpitch = BLOOPER_DEFAULT_MAXPITCH*2
/datum/blooper/undyne
name = "Undyne"
id = "undyne"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_undyne.ogg'
minvariance = 0
/datum/blooper/temmie
name = "Temmie"
id = "temmie"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_temmie.ogg'
minvariance = 0
/datum/blooper/susie
name = "Susie"
id = "susie"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_susie.ogg'
minvariance = 0
/datum/blooper/gaster
name = "Gaster"
id = "gaster"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_gaster_1.ogg'
minvariance = 0
/datum/blooper/mettaton
name = "Mettaton"
id = "mettaton"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_metta_1.ogg'
minvariance = 0
/datum/blooper/gen_monster
name = "Generic Monster 1"
id = "gen_monster_1"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_monster1.ogg'
minvariance = 0
/datum/blooper/gen_monster/alt
name = "Generic Monster 2"
id = "gen_monster_2"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/undertale/voice_monster2.ogg'
minvariance = 0
/datum/blooper/wilson
name = "Wilson"
id = "wilson"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/dont_starve/wilson_blooper.ogg'
/datum/blooper/wolfgang
name = "Wolfgang"
id = "wolfgang"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/dont_starve/wolfgang_blooper.ogg'
minspeed = 4
maxspeed = 10
/datum/blooper/woodie
name = "Woodie"
id = "woodie"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/dont_starve/woodie_blooper.ogg'
minspeed = 4
maxspeed = 10
/datum/blooper/wurt
name = "Wurt"
id = "wurt"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/dont_starve/wurt_blooper.ogg'
/datum/blooper/wx78
name = "wx78"
id = "wx78"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/dont_starve/wx78_blooper.ogg'
minspeed = 3
maxspeed = 9
/datum/blooper/blub
name = "Blub"
id = "blub"
soundpath = 'goon/sounds/blub.ogg'
/datum/blooper/bottalk
name = "Bottalk 1"
id = "bottalk1"
soundpath = 'goon/sounds/bottalk_1.ogg'
minspeed = 3
maxspeed = 9
/datum/blooper/bottalk/alt1
name = "Bottalk 2"
id = "bottalk2"
soundpath = 'goon/sounds/bottalk_2.ogg'
/datum/blooper/bottalk/alt2
name = "Bottalk 3"
id = "bottalk3"
soundpath = 'goon/sounds/bottalk_3.ogg'
/datum/blooper/bottalk/alt3
name = "Bottalk 4"
id = "bottalk4"
soundpath = 'goon/sounds/bottalk_4.ogg'
/datum/blooper/buwoo
name = "Buwoo"
id = "buwoo"
soundpath = 'goon/sounds/buwoo.ogg'
/datum/blooper/cow
name = "Cow"
id = "cow"
soundpath = 'goon/sounds/cow.ogg'
/datum/blooper/lizard
name = "Lizard"
id = "lizard"
soundpath = 'goon/sounds/lizard.ogg'
/datum/blooper/pug
name = "Pug"
id = "pug"
soundpath = 'goon/sounds/pug.ogg'
/datum/blooper/pugg
name = "Pugg"
id = "pugg"
soundpath = 'goon/sounds/pugg.ogg'
/datum/blooper/radio
name = "Radio 1"
id = "radio1"
soundpath = 'goon/sounds/radio.ogg'
/datum/blooper/radio/short
name = "Radio 2"
id = "radio2"
soundpath = 'goon/sounds/radio2.ogg'
/datum/blooper/radio/ai
name = "Radio (AI)"
id = "radio_ai"
soundpath = 'goon/sounds/radio_ai.ogg'
/datum/blooper/roach //Turkish characters be like
name = "Roach"
id = "roach"
soundpath = 'goon/sounds/roach.ogg'
/datum/blooper/skelly
name = "Skelly"
id = "skelly"
soundpath = 'goon/sounds/skelly.ogg'
/datum/blooper/speak
name = "Speak 1"
id = "speak1"
soundpath = 'goon/sounds/speak_1.ogg'
/datum/blooper/speak/alt1
name = "Speak 2"
id = "speak2"
soundpath = 'goon/sounds/speak_2.ogg'
/datum/blooper/speak/alt2
name = "Speak 3"
id = "speak3"
soundpath = 'goon/sounds/speak_3.ogg'
/datum/blooper/speak/alt3
name = "Speak 4"
id = "speak4"
soundpath = 'goon/sounds/speak_4.ogg'
/datum/blooper/chitter/alt
name = "Chittery Alt"
id = "chitter2"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/moth/mothchitter2.ogg'
// The Mayhem Special
/datum/blooper/whistle
name = "Whistle 1"
id = "whistle1"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/birdwhistle.ogg'
/datum/blooper/whistle/alt1
name = "Whistle 2"
id = "whistle2"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/birdwhistle2.ogg'
/datum/blooper/caw/alt1
name = "Caw 2"
id = "caw2"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/caw.ogg'
minspeed = 4
maxspeed = 9
/datum/blooper/caw/alt2
name = "Caw 3"
id = "caw3"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/caw2.ogg'
minspeed = 3
maxspeed = 9
/datum/blooper/caw/alt3
name = "Caw 4"
id = "caw4"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/caw3.ogg'
minspeed = 3
maxspeed = 9
/datum/blooper/ehh
name = "Ehh 1"
id = "ehh1"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/ehh.ogg'
minspeed = 3
maxspeed = 9
/datum/blooper/ehh/alt1
name = "Ehh 2"
id = "ehh2"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/ehh2.ogg'
/datum/blooper/ehh/alt2
name = "Ehh 3"
id = "ehh3"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/ehh3.ogg'
/datum/blooper/ehh/alt3
name = "Ehh 4"
id = "ehh4"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/ehh4.ogg'
minspeed = 3
maxspeed = 9
/datum/blooper/ehh/alt5
name = "Ehh 5"
id = "ehh5"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/ehh5.ogg'
/datum/blooper/faucet
name = "Faucet 1"
id = "faucet1"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/faucet.ogg'
/datum/blooper/faucet/alt1
name = "Faucet 2"
id = "faucet2"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/faucet2.ogg'
/datum/blooper/ribbit
name = "Ribbit"
id = "ribbit"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/ribbit.ogg'
/datum/blooper/hoot
name = "Hoot"
id = "hoot"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/hoot.ogg'
minspeed = 4
maxspeed = 9
/datum/blooper/tweet
name = "Tweet"
id = "tweet"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/tweet.ogg'
/datum/blooper/dwoop
name = "Dwoop"
id = "dwoop"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/dwoop.ogg'
minspeed = 3
maxspeed = 9
/datum/blooper/uhm
name = "Uhm"
id = "uhm"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/uhm.ogg'
/datum/blooper/wurtesh
name = "Wurtesh"
id = "wurtesh"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/wurble1.ogg'
/datum/blooper/chitter2
name = "Chitter2"
id = "chitter2"
soundpath = 'modular_zubbers/modules/blooper/voice/bloopers/kazooie/chitter1.ogg'

Binary file not shown.

View File

@@ -479,10 +479,12 @@
#include "code\__DEFINES\~~bubber_defines\misc.dm"
#include "code\__DEFINES\~~bubber_defines\quirk_whitelist.dm"
#include "code\__DEFINES\~~bubber_defines\robot_defines.dm"
#include "code\__DEFINES\~~bubber_defines\say.dm"
#include "code\__DEFINES\~~bubber_defines\signals.dm"
#include "code\__DEFINES\~~bubber_defines\species.dm"
#include "code\__DEFINES\~~bubber_defines\status_indicator_defines.dm"
#include "code\__DEFINES\~~bubber_defines\traits.dm"
#include "code\__DEFINES\~~bubber_defines\___HELPERS\global_lists.dm"
#include "code\__HELPERS\_auxtools_api.dm"
#include "code\__HELPERS\_lists.dm"
#include "code\__HELPERS\_planes.dm"
@@ -8524,6 +8526,9 @@
#include "modular_zubbers\modules\ashwalkers\code\effects\ash_rituals.dm"
#include "modular_zubbers\modules\automapper\code\area_spawn_entries.dm"
#include "modular_zubbers\modules\automapper\code\overrides\area_spawn_subsystem.dm"
#include "modular_zubbers\modules\blooper\atoms_movable.dm"
#include "modular_zubbers\modules\blooper\bark.dm"
#include "modular_zubbers\modules\blooper\bark_list.dm"
#include "modular_zubbers\modules\borgs\code\robot_defines.dm"
#include "modular_zubbers\modules\borgs\code\robot_items.dm"
#include "modular_zubbers\modules\borgs\code\robot_model.dm"

View File

@@ -0,0 +1,80 @@
import { Button, Stack } from '../../../../../../components';
import {
CheckboxInput,
Feature,
FeatureChoiced,
FeatureChoicedServerData,
FeatureDropdownInput,
FeatureNumberInput,
FeatureNumeric,
FeatureSliderInput,
FeatureToggle,
FeatureValueProps,
} from '../../base';
const FeatureBlooperDropdownInput = (
props: FeatureValueProps<string, string, FeatureChoicedServerData>,
) => {
return (
<Stack>
<Stack.Item grow>
<FeatureDropdownInput {...props} />
</Stack.Item>
<Stack.Item>
<Button
onClick={() => {
props.act('play_blooper');
}}
icon="play"
width="100%"
height="100%"
/>
</Stack.Item>
</Stack>
);
};
export const blooper_pitch_range: FeatureNumeric = {
name: 'Character Voice Range',
description:
'[0.1 - 0.8] Lower number, less range. Higher number, more range.',
component: FeatureNumberInput,
};
export const blooper_speech: FeatureChoiced = {
name: 'Character Voice',
component: FeatureBlooperDropdownInput,
};
export const blooper_speech_speed: FeatureNumeric = {
name: 'Character Voice Speed',
description:
'[2 - 16] Lower number, faster speed. Higher number, slower voice.',
component: FeatureNumberInput,
};
export const blooper_speech_pitch: FeatureNumeric = {
name: 'Character Voice Pitch',
description:
'[0.4 - 2] Lower number, deeper pitch. Higher number, higher pitch.',
component: FeatureNumberInput,
};
export const hear_sound_blooper: FeatureToggle = {
name: 'Enable Vocal Bark hearing',
category: 'SOUND',
component: CheckboxInput,
};
export const sound_blooper_volume: Feature<number> = {
name: 'Vocal Bark Volume',
category: 'SOUND',
description: 'The volume that the Vocal Barks sounds will play at.',
component: FeatureSliderInput,
};
export const send_sound_blooper: FeatureToggle = {
name: 'Enable Vocal Bark sending',
category: 'SOUND',
component: CheckboxInput,
};