diff --git a/code/datums/looping_sounds/_looping_sound.dm b/code/datums/looping_sounds/_looping_sound.dm index c1bb487425..228bef6778 100644 --- a/code/datums/looping_sounds/_looping_sound.dm +++ b/code/datums/looping_sounds/_looping_sound.dm @@ -16,6 +16,7 @@ direct (bool) If true plays directly to provided atoms instead of from them opacity_check (bool) If true, things behind walls/opaque things won't hear the sounds. pref_check (type) If set to a /datum/client_preference type, will check if the hearer has that preference active before playing it to them. + volume_chan (type) If set to a specific volume channel via the incoming argument, we tell the playsound proc to modulate volume based on that channel exclusive (bool) If true, only one of this sound is allowed to play. Relies on if started is true or not. If true, it will not start another loop until it is false. */ /datum/looping_sound @@ -34,6 +35,7 @@ var/opacity_check var/pref_check var/exclusive + var/falloff var/volume_chan var/timerid @@ -57,6 +59,8 @@ return ..() /datum/looping_sound/proc/start(atom/add_thing, skip_start_sound = FALSE) + if(QDELETED(src)) + return if(add_thing) output_atoms |= add_thing if(timerid) @@ -82,7 +86,7 @@ started = FALSE /datum/looping_sound/proc/sound_loop(starttime) - if(max_loops && world.time >= starttime + mid_length * max_loops) + if(QDELETED(src) || (max_loops && world.time >= starttime + mid_length * max_loops)) stop() return if(!chance || prob(chance)) @@ -98,7 +102,7 @@ if(direct) S.channel = SSsounds.random_available_channel() S.volume = volume - for(var/i in 1 to atoms_cache.len) + for(var/i in 1 to atoms_cache?.len) var/atom/thing = atoms_cache[i] if(direct) if(ismob(thing)) @@ -107,7 +111,7 @@ continue SEND_SOUND(thing, S) else - playsound(thing, S, volume, vary, extra_range, ignore_walls = !opacity_check, preference = pref_check) + playsound(thing, S, volume, vary, extra_range, falloff = falloff, ignore_walls = !opacity_check, preference = pref_check, volume_channel = volume_chan) /datum/looping_sound/proc/get_sound(starttime, _mid_sounds) if(!_mid_sounds) diff --git a/code/datums/looping_sounds/machinery_sounds.dm b/code/datums/looping_sounds/machinery_sounds.dm index b9be54d701..1ce534a681 100644 --- a/code/datums/looping_sounds/machinery_sounds.dm +++ b/code/datums/looping_sounds/machinery_sounds.dm @@ -118,6 +118,40 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/datum/looping_sound/fridge + mid_sounds = list('sound/machines/kitchen/fridge/fridge_loop.ogg' = 1) + mid_length = 60 + volume = 10 + extra_range = -1 // Short-range + pref_check = /datum/preference/toggle/fridge_hum + volume_chan = VOLUME_CHANNEL_MACHINERY_IDLE + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/datum/looping_sound/tcomms + start_sound = 'sound/machines/tcomms/tcomms_pulse.ogg' + mid_sounds = list('sound/machines/tcomms/tcomms_01.ogg' = 1) + mid_length = 20 + end_sound = 'sound/machines/tcomms/tcomms_pulse.ogg' + volume = 40 + extra_range = -5 // Short-range + falloff = 0.1 // Harsh + volume_chan = VOLUME_CHANNEL_MACHINERY_IDLE + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/datum/looping_sound/shield_generator + start_sound = 'sound/machines/shield_hum/shield_generator_whir.ogg' + mid_sounds = list('sound/machines/shield_hum/shield_generator_hum2.ogg', 'sound/machines/shield_hum/shield_generator_hum3.ogg') + mid_length = 60 + end_sound = 'sound/machines/shield_hum/shield_generator_whir.ogg' + volume = 40 + volume_chan = VOLUME_CHANNEL_MACHINERY + exclusive = TRUE + extra_range = 10 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /datum/looping_sound/lathe_print mid_sounds = list('sound/machines/lathe/lathe_print.ogg') mid_length = 2 SECONDS diff --git a/code/game/machinery/exonet_node.dm b/code/game/machinery/exonet_node.dm index 6d3c74bcbd..b422b1a206 100644 --- a/code/game/machinery/exonet_node.dm +++ b/code/game/machinery/exonet_node.dm @@ -17,16 +17,36 @@ var/list/logs = list() // Gets written to by exonet's send_message() function. circuit = /obj/item/circuitboard/telecomms/exonet_node + + var/datum/looping_sound/tcomms/soundloop + var/noisy = TRUE + // Proc: New() // Parameters: None // Description: Adds components to the machine for deconstruction. /obj/machinery/exonet_node/Initialize(mapload) + soundloop = new(list(src), FALSE) + if(prob(60)) // 60% chance to change the midloop + if(prob(40)) + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_02.ogg' = 1) + soundloop.mid_length = 40 + else if(prob(20)) + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_03.ogg' = 1) + soundloop.mid_length = 10 + else + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_04.ogg' = 1) + soundloop.mid_length = 30 + soundloop.start() . = ..() default_apply_parts() if(mapload) desc = "This machine is one of many, many nodes inside [using_map.starsys_name]'s section of the Exonet, connecting the [using_map.station_short] to the rest of the system, at least \ electronically." +/obj/machinery/exonet_node/Destroy() + QDEL_NULL(soundloop) + return ..() + // Proc: update_icon() // Parameters: None // Description: Self explanatory. @@ -49,12 +69,19 @@ if(stat & (BROKEN|NOPOWER|EMPED)) on = 0 update_idle_power_usage(0) + soundloop.stop() + noisy = FALSE else on = 1 update_idle_power_usage(2500) else on = 0 update_idle_power_usage(0) + soundloop.stop() + noisy = FALSE + if(!noisy && on) + soundloop.start() + noisy = TRUE update_icon() // Proc: emp_act(severity, recursive) diff --git a/code/game/machinery/pda_multicaster.dm b/code/game/machinery/pda_multicaster.dm index 07f1889ee1..a84def7f3a 100644 --- a/code/game/machinery/pda_multicaster.dm +++ b/code/game/machinery/pda_multicaster.dm @@ -12,6 +12,9 @@ var/toggle = 1 // If we /should/ be active or not, var/list/internal_PDAs = list() // Assoc list of PDAs inside of this, with the department name being the index, + var/datum/looping_sound/tcomms/soundloop + var/noisy = TRUE + /obj/machinery/pda_multicaster/Initialize(mapload) . = ..() internal_PDAs = list("command" = new /obj/item/pda/multicaster/command(src), @@ -19,10 +22,23 @@ "engineering" = new /obj/item/pda/multicaster/engineering(src), "medical" = new /obj/item/pda/multicaster/medical(src), "research" = new /obj/item/pda/multicaster/research(src), - "exploration" = new /obj/item/pda/multicaster/exploration(src), //VOREStation Add, + "exploration" = new /obj/item/pda/multicaster/exploration(src), "cargo" = new /obj/item/pda/multicaster/cargo(src), "civilian" = new /obj/item/pda/multicaster/civilian(src)) + soundloop = new(list(src), FALSE) + if(prob(60)) // 60% chance to change the midloop + if(prob(40)) + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_02.ogg' = 1) + soundloop.mid_length = 40 + else if(prob(20)) + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_03.ogg' = 1) + soundloop.mid_length = 10 + else + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_04.ogg' = 1) + soundloop.mid_length = 30 + soundloop.start() // Have to do this here bc it starts on + /obj/machinery/pda_multicaster/prebuilt/Initialize(mapload) . = ..() default_apply_parts() @@ -30,6 +46,7 @@ /obj/machinery/pda_multicaster/Destroy() for(var/atom/movable/AM in contents) qdel(AM) + QDEL_NULL(soundloop) . = ..() /obj/machinery/pda_multicaster/update_icon() @@ -73,14 +90,20 @@ on = 0 update_PDAs(1) // 1 being to turn off. update_idle_power_usage(0) + soundloop.stop() + noisy = FALSE else on = 1 update_PDAs(0) update_idle_power_usage(750) + soundloop.start() + noisy = TRUE else on = 0 update_PDAs(1) update_idle_power_usage(0) + soundloop.stop() + noisy = FALSE update_icon() /obj/machinery/pda_multicaster/process() diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 43716fb5fb..1f74802811 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -36,6 +36,8 @@ var/hide = 0 // Is it a hidden machine? var/listening_level = 0 // 0 = auto set in New() - this is the z level that the machine is listening to. + var/datum/looping_sound/tcomms/soundloop + var/noisy = TRUE /obj/machinery/telecomms/proc/relay_information(datum/signal/signal, filter, copysig, amount = 20) // relay signal to all linked machinery that are of type [filter]. If signal has been sent [amount] times, stop sending @@ -139,12 +141,25 @@ else for(var/obj/machinery/telecomms/T in GLOB.telecomms_list) add_link(T) + soundloop = new(list(src), FALSE) + if(prob(60)) // 60% chance to change the midloop + if(prob(40)) + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_02.ogg' = 1) + soundloop.mid_length = 40 + else if(prob(20)) + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_03.ogg' = 1) + soundloop.mid_length = 10 + else + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_04.ogg' = 1) + soundloop.mid_length = 30 + soundloop.start() /obj/machinery/telecomms/Destroy() GLOB.telecomms_list -= src for(var/obj/machinery/telecomms/comm in GLOB.telecomms_list) comm.links -= src links = list() + QDEL_NULL(soundloop) . = ..() // Used in auto linking @@ -167,11 +182,18 @@ if(toggled) if(stat & (BROKEN|NOPOWER|EMPED) || integrity <= 0) // if powered, on. if not powered, off. if too damaged, off - on = 0 + on = FALSE + soundloop.stop() + noisy = FALSE else - on = 1 + on = TRUE else - on = 0 + on = FALSE + soundloop.stop() + noisy = FALSE + if(!noisy) + soundloop.start() + noisy = TRUE /obj/machinery/telecomms/process() update_power() @@ -192,6 +214,7 @@ if(prob(100/severity)) if(!(stat & EMPED)) stat |= EMPED + playsound(src, 'sound/machines/tcomms/tcomms_pulse.ogg', 70, 1, 30) var/duration = (300 * 10)/severity spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot. stat &= ~EMPED diff --git a/code/modules/client/preferences/types/game/sound.dm b/code/modules/client/preferences/types/game/sound.dm index a93b1c33e1..8c4189145e 100644 --- a/code/modules/client/preferences/types/game/sound.dm +++ b/code/modules/client/preferences/types/game/sound.dm @@ -269,3 +269,8 @@ category = PREFERENCE_CATEGORY_GAME_PREFERENCES savefile_key = "sound_instruments" savefile_identifier = PREFERENCE_PLAYER + +/datum/preference/toggle/fridge_hum + category = PREFERENCE_CATEGORY_GAME_PREFERENCES + savefile_key = "SOUND_FRIDGEHUM" + savefile_identifier = PREFERENCE_PLAYER diff --git a/code/modules/food/kitchen/smartfridge/smartfridge.dm b/code/modules/food/kitchen/smartfridge/smartfridge.dm index a32244ca10..cdc6677540 100644 --- a/code/modules/food/kitchen/smartfridge/smartfridge.dm +++ b/code/modules/food/kitchen/smartfridge/smartfridge.dm @@ -24,6 +24,9 @@ var/persistent = null // Path of persistence datum used to track contents circuit = /obj/item/circuitboard/smartfridge //This one is meant to be uncraftable, however. + var/datum/looping_sound/fridge/soundloop + var/playing_sound = FALSE + /obj/machinery/smartfridge/secure is_secure = 1 @@ -35,6 +38,8 @@ set_wires(new /datum/wires/smartfridge/secure(src)) else set_wires(new /datum/wires/smartfridge(src)) + + soundloop = new(list(src), FALSE) update_icon() default_apply_parts() @@ -45,6 +50,7 @@ wires = null if(persistent) SSpersistence.forget_value(src, persistent) + QDEL_NULL(soundloop) return ..() /obj/machinery/smartfridge/proc/accept_check(obj/item/O) @@ -52,7 +58,12 @@ /obj/machinery/smartfridge/process() if(stat & (BROKEN|NOPOWER)) + soundloop.stop() + playing_sound = FALSE return + if(!playing_sound && !stat) + soundloop.start() + playing_sound = TRUE if(src.seconds_electrified > 0) src.seconds_electrified-- if(src.shoot_inventory && prob(2)) @@ -63,6 +74,12 @@ ..() if(old_stat != stat) update_icon() + if(stat & (NOPOWER | BROKEN)) + soundloop.stop() + playing_sound = FALSE + else + soundloop.start() + playing_sound = TRUE /obj/machinery/smartfridge/update_icon() cut_overlays() diff --git a/code/modules/integrated_electronics/core/tools.dm b/code/modules/integrated_electronics/core/tools.dm index a46e0dafce..7eea79716c 100644 --- a/code/modules/integrated_electronics/core/tools.dm +++ b/code/modules/integrated_electronics/core/tools.dm @@ -262,9 +262,18 @@ /obj/item/integrated_electronics, /obj/item/tool/crowbar, /obj/item/tool/screwdriver, - /obj/item/multitool + /obj/item/multitool, + /obj/item/integrated_electronics/wirer, + /obj/item/integrated_electronics/debugger, + /obj/item/integrated_electronics/detailer, ) +//Emp'ing this one bag causes a recursion loop of over 700 emp_act's, +//Which is enough to trigger byond's recursion level protection +/obj/item/storage/bag/circuits/basic/Initialize(mapload) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF) + . = ..() + /obj/item/storage/bag/circuits/basic/Initialize(mapload) new /obj/item/storage/bag/circuits/mini/arithmetic(src) new /obj/item/storage/bag/circuits/mini/trig(src) @@ -283,6 +292,9 @@ new /obj/item/multitool(src) new /obj/item/tool/screwdriver(src) new /obj/item/tool/crowbar(src) + new /obj/item/integrated_electronics/wirer(src) + new /obj/item/integrated_electronics/debugger(src) + new /obj/item/integrated_electronics/detailer(src) make_exact_fit() . = ..() @@ -307,6 +319,7 @@ new /obj/item/electronic_assembly/drone(src) new /obj/item/integrated_electronics/wirer(src) new /obj/item/integrated_electronics/debugger(src) + new /obj/item/integrated_electronics/detailer(src) new /obj/item/tool/crowbar(src) make_exact_fit() . = ..() diff --git a/code/modules/modular_computers/NTNet/NTNet_relay.dm b/code/modules/modular_computers/NTNet/NTNet_relay.dm index a4cf97404a..4371fdbc6d 100644 --- a/code/modules/modular_computers/NTNet/NTNet_relay.dm +++ b/code/modules/modular_computers/NTNet/NTNet_relay.dm @@ -19,6 +19,9 @@ var/dos_capacity = 500 // Amount of DoS "packets" in buffer required to crash the relay var/dos_dissipate = 1 // Amount of DoS "packets" dissipated over time. + var/datum/looping_sound/tcomms/soundloop + var/noisy = TRUE + // TODO: Implement more logic here. For now it's only a placeholder. /obj/machinery/ntnet_relay/operable() @@ -33,8 +36,13 @@ /obj/machinery/ntnet_relay/update_icon() if(operable()) icon_state = initial(icon_state) + if(!noisy) + soundloop.start() + noisy = TRUE else icon_state = "[initial(icon_state)]_off" + soundloop.stop() + noisy = FALSE /obj/machinery/ntnet_relay/process() if(operable()) @@ -106,6 +114,18 @@ GLOB.ntnet_global.relays.Add(src) NTNet = GLOB.ntnet_global GLOB.ntnet_global.add_log("New quantum relay activated. Current amount of linked relays: [NTNet.relays.len]") + soundloop = new(list(src), FALSE) + if(prob(60)) // 60% chance to change the midloop + if(prob(40)) + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_02.ogg' = 1) + soundloop.mid_length = 40 + else if(prob(20)) + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_03.ogg' = 1) + soundloop.mid_length = 10 + else + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_04.ogg' = 1) + soundloop.mid_length = 30 + soundloop.start() // Have to do this here bc it starts on /obj/machinery/ntnet_relay/Destroy() if(GLOB.ntnet_global) @@ -115,6 +135,7 @@ for(var/datum/computer_file/program/ntnet_dos/D in dos_sources) D.target = null D.error = "Connection to quantum relay severed" + QDEL_NULL(soundloop) . = ..() /obj/machinery/ntnet_relay/attackby(var/obj/item/W as obj, var/mob/user as mob) diff --git a/code/modules/research/message_server.dm b/code/modules/research/message_server.dm index e969bbd9f7..e32e6c237c 100644 --- a/code/modules/research/message_server.dm +++ b/code/modules/research/message_server.dm @@ -69,7 +69,21 @@ //Messages having theese tokens will be rejected by server. Case sensitive var/spamfilter_limit = MESSAGE_SERVER_DEFAULT_SPAM_LIMIT //Maximal amount of tokens + var/datum/looping_sound/tcomms/soundloop + var/noisy = FALSE + /obj/machinery/message_server/Initialize(mapload) + soundloop = new(list(src), FALSE) + if(prob(60)) // 60% chance to change the midloop + if(prob(40)) + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_02.ogg' = 1) + soundloop.mid_length = 40 + else if(prob(20)) + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_03.ogg' = 1) + soundloop.mid_length = 10 + else + soundloop.mid_sounds = list('sound/machines/tcomms/tcomms_04.ogg' = 1) + soundloop.mid_length = 30 . = ..() GLOB.message_servers += src decryptkey = GenerateKey() @@ -77,6 +91,7 @@ /obj/machinery/message_server/Destroy() GLOB.message_servers -= src + QDEL_NULL(soundloop) return ..() /obj/machinery/message_server/examine(mob/user, distance, infix, suffix) @@ -96,7 +111,12 @@ // decryptkey = generateKey() if(active && (stat & (BROKEN|NOPOWER))) active = 0 + soundloop.stop() + noisy = FALSE return + if(!noisy && active) + soundloop.start() + noisy = TRUE update_icon() return @@ -366,7 +386,7 @@ GLOBAL_DATUM(blackbox, /obj/machinery/blackbox_recorder) query_insert.Execute() qdel(query_insert) -// Sanitize inputs to avoid SQL injection attacks +// Sanitize inputs to avoid SQL injection attacks. This is not secure. Basic filters like this are pretty easy to bypass. Use the format for arguments used in the above. /proc/sql_sanitize_text(var/text) text = replacetext(text, "'", "''") text = replacetext(text, ";", "") diff --git a/code/modules/shieldgen/shield_gen.dm b/code/modules/shieldgen/shield_gen.dm index 61a657ab23..861416875a 100644 --- a/code/modules/shieldgen/shield_gen.dm +++ b/code/modules/shieldgen/shield_gen.dm @@ -25,6 +25,7 @@ use_power = USE_POWER_OFF //doesn't use APC power interact_offline = TRUE // don't check stat & NOPOWER|BROKEN for our UI. We check BROKEN ourselves. var/id //for button usage + var/datum/looping_sound/shield_generator/shield_hum /obj/machinery/shield_gen/advanced name = "advanced bubble shield generator" @@ -41,11 +42,13 @@ if(get_dir(cap, src) == cap.dir) capacitors |= cap cap.owned_gen = src + shield_hum = new(list(src), FALSE) . = ..() AddElement(/datum/element/climbable) /obj/machinery/shield_gen/Destroy() QDEL_LIST_NULL(field) + QDEL_NULL(shield_hum) return ..() /obj/machinery/shield_gen/emag_act(var/remaining_charges, var/mob/user) @@ -243,6 +246,7 @@ to_chat(M, "[icon2html(src, M.client)] You hear heavy droning start up.") for(var/obj/effect/energy_field/E in field) // Update the icons here to ensure all the shields have been made already. E.update_icon() + shield_hum.start() else for(var/obj/effect/energy_field/D in field) field.Remove(D) @@ -251,11 +255,25 @@ for(var/mob/M in view(5,src)) to_chat(M, "[icon2html(src, M.client)] You hear heavy droning fade out.") + shield_hum.stop() + +/obj/machinery/shield_gen/proc/fill_diffused() + if(active) + var/list/covered_turfs = get_shielded_turfs() + var/turf/T = get_turf(src) + var/obj/effect/energy_field/E + if(T in covered_turfs) + covered_turfs.Remove(T) + for(var/turf/O in covered_turfs) + if(locate(/obj/effect/energy_field, O) || locate(/obj/machinery/pointdefense, orange(2, O))) + continue + E = new(O, src) /obj/machinery/shield_gen/update_icon() if(stat & BROKEN) icon_state = "broke" set_light(0) + shield_hum.stop() else if (src.active) icon_state = "generator1" diff --git a/sound/machines/kitchen/fridge/close_fridge.ogg b/sound/machines/kitchen/fridge/close_fridge.ogg new file mode 100644 index 0000000000..f8ee3ab8aa Binary files /dev/null and b/sound/machines/kitchen/fridge/close_fridge.ogg differ diff --git a/sound/machines/kitchen/fridge/fridge_loop.ogg b/sound/machines/kitchen/fridge/fridge_loop.ogg new file mode 100644 index 0000000000..dcd112f8ee Binary files /dev/null and b/sound/machines/kitchen/fridge/fridge_loop.ogg differ diff --git a/sound/machines/kitchen/fridge/open_fridge.ogg b/sound/machines/kitchen/fridge/open_fridge.ogg new file mode 100644 index 0000000000..0ac523eefe Binary files /dev/null and b/sound/machines/kitchen/fridge/open_fridge.ogg differ diff --git a/sound/machines/tcomms/tcomms_01.ogg b/sound/machines/tcomms/tcomms_01.ogg new file mode 100644 index 0000000000..3e877371b6 Binary files /dev/null and b/sound/machines/tcomms/tcomms_01.ogg differ diff --git a/sound/machines/tcomms/tcomms_02.ogg b/sound/machines/tcomms/tcomms_02.ogg new file mode 100644 index 0000000000..fc8a6a5191 Binary files /dev/null and b/sound/machines/tcomms/tcomms_02.ogg differ diff --git a/sound/machines/tcomms/tcomms_03.ogg b/sound/machines/tcomms/tcomms_03.ogg new file mode 100644 index 0000000000..a22a3575f0 Binary files /dev/null and b/sound/machines/tcomms/tcomms_03.ogg differ diff --git a/sound/machines/tcomms/tcomms_04.ogg b/sound/machines/tcomms/tcomms_04.ogg new file mode 100644 index 0000000000..15ec8a342e Binary files /dev/null and b/sound/machines/tcomms/tcomms_04.ogg differ diff --git a/sound/machines/tcomms/tcomms_pulse.ogg b/sound/machines/tcomms/tcomms_pulse.ogg new file mode 100644 index 0000000000..bdc44e991a Binary files /dev/null and b/sound/machines/tcomms/tcomms_pulse.ogg differ