Skip to content

Commit

Permalink
Blooper, finally (#106)
Browse files Browse the repository at this point in the history
* blooper begin

* LETS DO THIS

* Defines done

* Its working 👍

* NOW IT'S WORKING

* ...

* I broke everything

* idk

* It's working

* Almost done

* Some changes

* Also some changes

* Some changes

* It's almost end.

* IT'S THE END OF TIMES

* Забыл про 900 коммитов до...

* Some kek moment fix.

* Update global_lists.dm

* Update code/game/atoms_movable.dm

Co-authored-by: Yaroslav Nurkov <[email protected]>

* Update code/__HELPERS/global_lists.dm

Co-authored-by: Yaroslav Nurkov <[email protected]>

* Update code/game/atoms_movable.dm

Co-authored-by: Yaroslav Nurkov <[email protected]>

* VishenkaNeedThis

* SpecialForSomeone

* Little fix

* Separate

* How Veshenka Saying

* Prettier. You know.

* Update tff_modular/modules/blooper/atoms_movable.dm

Co-authored-by: ReezeBL <[email protected]>

* Update tff_modular/modules/blooper/atoms_movable.dm

Co-authored-by: ReezeBL <[email protected]>

* Update code/__DEFINES/~ff_defines/dcs/signals.dm

Co-authored-by: ReezeBL <[email protected]>

* fix sound falloff

* UltraMegaChanges

* Bark->Blooper

* remove unnecessary defines

---------

Co-authored-by: Yaroslav Nurkov <[email protected]>
Co-authored-by: ReezeBL <[email protected]>
Co-authored-by: Iajret <[email protected]>
  • Loading branch information
4 people authored Oct 18, 2023
1 parent 12ea013 commit 2840788
Show file tree
Hide file tree
Showing 91 changed files with 760 additions and 0 deletions.
2 changes: 2 additions & 0 deletions code/__DEFINES/~ff_defines/__HELPERS/global_lists.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GLOBAL_LIST_EMPTY(blooper_list)
GLOBAL_LIST_EMPTY(blooper_random_list)
19 changes: 19 additions & 0 deletions code/__DEFINES/~ff_defines/say.dm
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions code/__HELPERS/global_lists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@
sort_list(GLOB.laugh_types, GLOBAL_PROC_REF(cmp_typepaths_asc))
//SKYRAT EDIT END

//THE FLUFFY FRONTIER 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 FLUFFY FRONTIER EDIT END

/// Inits GLOB.species_list. Not using GLOBAL_LIST_INIT b/c it depends on GLOB.string_lists
/proc/init_species_list()
for(var/species_path in subtypesof(/datum/species))
Expand Down
6 changes: 6 additions & 0 deletions code/game/atoms_movable.dm
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,12 @@
if(NAMEOF(src, glide_size))
set_glide_size(var_value)
. = TRUE
// THE FLUFFY FRONTIER 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 FLUFFY FRONTIER EDIT ADDITION END

if(!isnull(.))
datum_flags |= DF_VAR_EDITED
Expand Down
84 changes: 84 additions & 0 deletions tff_modular/modules/blooper/atoms_movable.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/atom/movable
// Text-to-blooper sounds
// Да. У нас все атом могут иметь звучение для 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 = 70
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

/randomize_human(mob/living/carbon/human/human)
. = ..()
human.set_blooper(pick(GLOB.blooper_random_list))
human.blooper_pitch = BLOOPER_PITCH_RAND(human.gender)
human.blooper_pitch_range = BLOOPER_VARIANCE_RAND

/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 = 55
if(message_mods[WHISPER_MODE])
blooper_volume = 25
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) //На седьмом тайле функция равна нулю, поэтому мы обязаны ставить максимум на 1 тайл дальше.
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
148 changes: 148 additions & 0 deletions tff_modular/modules/blooper/bark.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
GLOBAL_VAR_INIT(blooper_allowed, TRUE) // For administrators

/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 ANNOYING NOIZES"
set name = "Toggle Blooper"
toggle_blooper()
log_admin("[key_name(usr)] toggled Blooper.")
message_admins("[key_name_admin(usr)] toggled Blooper.")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Blooper", "[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>The Blooper has 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, /datum/preference/numeric/blooper_speech_speed)
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


/// Могу ли я использовать свой блупер?
/datum/preference/toggle/send_sound_blooper
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
savefile_key = "send_sound_blooper"
savefile_identifier = PREFERENCE_PLAYER
default_value = FALSE

/// Могу ли я слышать блупки остальных?
/datum/preference/toggle/hear_sound_blooper
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
savefile_key = "hear_sound_blooper"
savefile_identifier = PREFERENCE_PLAYER
default_value = FALSE

/// It's was stoolen from Splurt build >:3
/datum/blooper
var/name = "None"
var/id = "Default"
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
Loading

0 comments on commit 2840788

Please sign in to comment.