mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-20 11:40:07 +01:00
## About The Pull Request Deletes `can_hear`, replaces it with trait-checking deafness. The only two non-trait sources of deafness (hardcrit and lacking ears) were refactored into using the trait. ## Why It's Good For The Game Many places inconsistently check for the deaf trait rather than use can_hear which meant behavior was not consistent. Some code would treat "do we lack ears?" as being deaf, some would not. This unifies all the behavior so being deaf means you're deaf everywhere. It also means we can now easily react to gaining and losing deafness via signal, where before we could not react to it without hooking the trait, organ remove, AND stat change. Which no one did, of course, because who would ever think to do that? ## Changelog 🆑 Melbert refactor: Refactored how deafness is tracked. Please report any weird interactions with sounds, like messages or sfx being missing. fix: Lacking ears and being in hard crit now consistently treats you as "being deaf". This affects a few minor interactions like empath, the jukebox, and sleeping. /🆑
145 lines
5.7 KiB
Plaintext
145 lines
5.7 KiB
Plaintext
/// The subsystem used to play ambience to users every now and then, makes them real excited.
|
|
SUBSYSTEM_DEF(ambience)
|
|
name = "Ambience"
|
|
flags = SS_BACKGROUND|SS_NO_INIT
|
|
priority = FIRE_PRIORITY_AMBIENCE
|
|
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
|
wait = 1 SECONDS
|
|
///Assoc list of listening client - next ambience time
|
|
var/list/ambience_listening_clients = list()
|
|
var/list/client_old_areas = list()
|
|
///Cache for sanic speed :D
|
|
var/list/currentrun = list()
|
|
|
|
/datum/controller/subsystem/ambience/fire(resumed)
|
|
if(!resumed)
|
|
currentrun = ambience_listening_clients.Copy()
|
|
var/list/cached_clients = currentrun
|
|
|
|
while(cached_clients.len)
|
|
var/client/client_iterator = cached_clients[cached_clients.len]
|
|
cached_clients.len--
|
|
|
|
//Check to see if the client exists and isn't held by a new player
|
|
var/mob/client_mob = client_iterator?.mob
|
|
if(isnull(client_iterator) || !client_mob || isnewplayer(client_mob))
|
|
ambience_listening_clients -= client_iterator
|
|
client_old_areas -= client_iterator
|
|
continue
|
|
|
|
if(HAS_TRAIT(client_mob, TRAIT_DEAF)) //WHAT? I CAN'T HEAR YOU
|
|
continue
|
|
|
|
//Check to see if the client-mob is in a valid area
|
|
var/area/current_area = get_area(client_mob)
|
|
if(!current_area) //Something's gone horribly wrong
|
|
stack_trace("[key_name(client_mob)] has somehow ended up in nullspace. WTF did you do")
|
|
remove_ambience_client(client_iterator)
|
|
continue
|
|
|
|
if(ambience_listening_clients[client_iterator] > world.time)
|
|
if(!(current_area.forced_ambience && (client_old_areas?[client_iterator] != current_area) && prob(5)))
|
|
continue
|
|
|
|
//Run play_ambience() on the client-mob and set a cooldown
|
|
ambience_listening_clients[client_iterator] = world.time + current_area.play_ambience(client_mob)
|
|
|
|
//We REALLY don't want runtimes in SSambience
|
|
if(client_iterator)
|
|
client_old_areas[client_iterator] = current_area
|
|
|
|
if(MC_TICK_CHECK)
|
|
return
|
|
|
|
///Attempts to play an ambient sound to a mob, returning the cooldown in deciseconds
|
|
/area/proc/play_ambience(mob/M, sound/override_sound, volume = 27)
|
|
var/sound/new_sound = override_sound || pick(ambientsounds)
|
|
if(!new_sound) // Dont try to play a sound if we dont have any.
|
|
return 1 MINUTES
|
|
/// volume modifier for ambience as set by the player in preferences.
|
|
var/volume_modifier = (M.client?.prefs.read_preference(/datum/preference/numeric/volume/sound_ambience_volume))/100
|
|
new_sound = sound(new_sound, repeat = 0, wait = 0, volume = volume*volume_modifier, channel = CHANNEL_AMBIENCE)
|
|
SEND_SOUND(M, new_sound)
|
|
|
|
var/sound_length = SSsounds.get_sound_length(new_sound.file)
|
|
if(!sound_length)
|
|
// This will cause sounds to cut into eachother if the sound is longer then the min_ambience_cooldown
|
|
stack_trace("play_ambience failed to get soundlength from [new_sound] with a file of [new_sound.file].")
|
|
return sound_length + rand(min_ambience_cooldown, max_ambience_cooldown)
|
|
|
|
/datum/controller/subsystem/ambience/proc/remove_ambience_client(client/to_remove)
|
|
ambience_listening_clients -= to_remove
|
|
client_old_areas -= to_remove
|
|
currentrun -= to_remove
|
|
|
|
/area/station/maintenance
|
|
|
|
///A list of rare sound effects to fuck with players. No, it does not contain actual minecraft sounds anymore.
|
|
var/static/list/minecraft_cave_noises = list(
|
|
'sound/machines/airlock/airlock.ogg',
|
|
'sound/effects/snap.ogg',
|
|
'sound/effects/footstep/clownstep1.ogg',
|
|
'sound/effects/footstep/clownstep2.ogg',
|
|
'sound/items/tools/welder.ogg',
|
|
'sound/items/tools/welder2.ogg',
|
|
'sound/items/tools/crowbar.ogg',
|
|
'sound/items/deconstruct.ogg',
|
|
'sound/ambience/misc/source_holehit3.ogg',
|
|
'sound/ambience/misc/cavesound3.ogg',
|
|
)
|
|
|
|
/area/station/maintenance/play_ambience(mob/M, sound/override_sound, volume)
|
|
if(!M.has_light_nearby() && prob(0.5))
|
|
return ..(M, pick(minecraft_cave_noises))
|
|
return ..()
|
|
|
|
/**
|
|
* Ambience buzz handling called by either area/Enter() or refresh_looping_ambience()
|
|
*/
|
|
|
|
/mob/proc/update_ambience_area(area/new_area)
|
|
|
|
var/old_tracked_area = ambience_tracked_area
|
|
if(old_tracked_area)
|
|
UnregisterSignal(old_tracked_area, COMSIG_AREA_POWER_CHANGE)
|
|
ambience_tracked_area = null
|
|
if(!client)
|
|
return
|
|
if(new_area)
|
|
ambience_tracked_area = new_area
|
|
RegisterSignal(ambience_tracked_area, COMSIG_AREA_POWER_CHANGE, PROC_REF(refresh_looping_ambience), TRUE)
|
|
|
|
refresh_looping_ambience()
|
|
|
|
/mob/proc/refresh_looping_ambience()
|
|
SIGNAL_HANDLER
|
|
|
|
if(!client || isobserver(client.mob)) // If a tree falls in the woods. sadboysuss: Don't refresh for ghosts, it sounds bad
|
|
return
|
|
|
|
var/area/my_area = get_area(src)
|
|
var/sound_to_use = my_area.ambient_buzz
|
|
var/volume_modifier = client.prefs.read_preference(/datum/preference/numeric/volume/sound_ship_ambience_volume)
|
|
|
|
if(!sound_to_use || !(client.prefs.read_preference(/datum/preference/numeric/volume/sound_ship_ambience_volume)))
|
|
SEND_SOUND(src, sound(null, repeat = 0, wait = 0, channel = CHANNEL_BUZZ))
|
|
client.current_ambient_sound = null
|
|
return
|
|
|
|
if(HAS_TRAIT(src, TRAIT_DEAF)) // Can the mob hear?
|
|
SEND_SOUND(src, sound(null, repeat = 0, wait = 0, channel = CHANNEL_BUZZ))
|
|
client.current_ambient_sound = null
|
|
return
|
|
|
|
//Station ambience is dependent on a functioning and charged APC with environment power enabled.
|
|
if(!is_mining_level(my_area.z) && ((!my_area.apc || !my_area.apc.operating || !my_area.apc.cell?.charge && my_area.requires_power || !my_area.power_environ)))
|
|
SEND_SOUND(src, sound(null, repeat = 0, wait = 0, channel = CHANNEL_BUZZ))
|
|
client.current_ambient_sound = null
|
|
return
|
|
else
|
|
if(sound_to_use == client.current_ambient_sound) // Don't reset current loops
|
|
return
|
|
|
|
client.current_ambient_sound = sound_to_use
|
|
SEND_SOUND(src, sound(my_area.ambient_buzz, repeat = 1, wait = 0, volume = my_area.ambient_buzz_vol * (volume_modifier / 100), channel = CHANNEL_BUZZ))
|