diff --git a/assets/voxygen/audio/sfx.ron b/assets/voxygen/audio/sfx.ron index b8d4f71986..64442b4b7c 100644 --- a/assets/voxygen/audio/sfx.ron +++ b/assets/voxygen/audio/sfx.ron @@ -28,11 +28,24 @@ ], threshold: 14.0, ), - Cricket: ( + //Crickets: -20dB + Cricket1: ( files: [ "voxygen.audio.sfx.ambient.crickets_1", ], - threshold: 1.0, + threshold: 0.0, + ), + Cricket2: ( + files: [ + "voxygen.audio.sfx.ambient.crickets_2", + ], + threshold: 0.0, + ), + Cricket3: ( + files: [ + "voxygen.audio.sfx.ambient.crickets_3", + ], + threshold: 0.0, ), Frog: ( files: [ diff --git a/assets/voxygen/audio/sfx/ambient/crickets_1.wav b/assets/voxygen/audio/sfx/ambient/crickets_1.wav index 0da586731e..5d3863268f 100644 --- a/assets/voxygen/audio/sfx/ambient/crickets_1.wav +++ b/assets/voxygen/audio/sfx/ambient/crickets_1.wav @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b36412b86538f64041720a8a46e25426087713badd577b358d976bc812488cb7 -size 80192 +oid sha256:3331bb02dd24c96f087d9055af834cadce79968ed778f6e6ea1cd6367a2dbd55 +size 40118 diff --git a/assets/voxygen/audio/sfx/ambient/crickets_2.wav b/assets/voxygen/audio/sfx/ambient/crickets_2.wav new file mode 100644 index 0000000000..fb72ef8191 --- /dev/null +++ b/assets/voxygen/audio/sfx/ambient/crickets_2.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:812511e90659174caeb6c790c97376aa31d011eb1dd36b2c40d736662645f5f8 +size 66092 diff --git a/assets/voxygen/audio/sfx/ambient/crickets_3.wav b/assets/voxygen/audio/sfx/ambient/crickets_3.wav new file mode 100644 index 0000000000..68d9afb9a0 --- /dev/null +++ b/assets/voxygen/audio/sfx/ambient/crickets_3.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b02474db3d826785d875be38b79a453274696e86af45a70f957490c5abd58a84 +size 64264 diff --git a/common/src/terrain/mod.rs b/common/src/terrain/mod.rs index a0f6bf7c46..e1a18f2dbc 100644 --- a/common/src/terrain/mod.rs +++ b/common/src/terrain/mod.rs @@ -59,6 +59,7 @@ pub struct TerrainChunkMeta { tree_density: f32, contains_cave: bool, contains_river: bool, + temp: f32, } impl TerrainChunkMeta { @@ -69,6 +70,7 @@ impl TerrainChunkMeta { tree_density: f32, contains_cave: bool, contains_river: bool, + temp: f32, ) -> Self { Self { name, @@ -77,6 +79,7 @@ impl TerrainChunkMeta { tree_density, contains_cave, contains_river, + temp, } } @@ -88,6 +91,7 @@ impl TerrainChunkMeta { tree_density: 0.0, contains_cave: false, contains_river: false, + temp: 0.0, } } @@ -102,6 +106,8 @@ impl TerrainChunkMeta { pub fn contains_cave(&self) -> bool { self.contains_cave } pub fn contains_river(&self) -> bool { self.contains_river } + + pub fn temp(&self) -> f32 { self.temp } } // Terrain type aliases diff --git a/voxygen/src/audio/sfx/event_mapper/block/mod.rs b/voxygen/src/audio/sfx/event_mapper/block/mod.rs index 1c08267f08..5d2afb1789 100644 --- a/voxygen/src/audio/sfx/event_mapper/block/mod.rs +++ b/voxygen/src/audio/sfx/event_mapper/block/mod.rs @@ -17,7 +17,7 @@ use common::{ use common_sys::state::State; use hashbrown::HashMap; use rand::{thread_rng, Rng}; -use std::time::Instant; +use std::time::{Duration, Instant}; use vek::*; #[derive(Clone, PartialEq)] @@ -30,7 +30,9 @@ impl Default for PreviousBlockState { fn default() -> Self { Self { event: SfxEvent::Idle, - time: Instant::now(), + time: Instant::now() + .checked_add(Duration::from_millis(thread_rng().gen_range(0..500))) + .unwrap_or_else(Instant::now), } } } @@ -61,10 +63,10 @@ impl EventMapper for BlockEventMapper { (e.floor() as i32).div_euclid(sz as i32) }); - // For determining if underground - let terrain_alt = match client.current_chunk() { - Some(chunk) => chunk.meta().alt(), - None => 0.0, + // For determining if underground/crickets should chirp + let (terrain_alt, temp) = match client.current_chunk() { + Some(chunk) => (chunk.meta().alt(), chunk.meta().temp()), + None => (0.0, 0.0), }; struct BlockSounds<'a> { @@ -112,7 +114,7 @@ impl EventMapper for BlockEventMapper { // //cond: |st| st.get_day_period().is_dark(), //}, BlockSounds { - blocks: |boi| &boi.reeds, + blocks: |boi| &boi.frogs, range: 1, sfx: SfxEvent::Frog, volume: 0.8, @@ -126,10 +128,24 @@ impl EventMapper for BlockEventMapper { // cond: |st| st.get_day_period().is_dark(), //}, BlockSounds { - blocks: |boi| &boi.grass, + blocks: |boi| &boi.cricket1, range: 1, - sfx: SfxEvent::Cricket, - volume: 0.5, + sfx: SfxEvent::Cricket1, + volume: 0.33, + cond: |st| st.get_day_period().is_dark(), + }, + BlockSounds { + blocks: |boi| &boi.cricket2, + range: 1, + sfx: SfxEvent::Cricket2, + volume: 0.33, + cond: |st| st.get_day_period().is_dark(), + }, + BlockSounds { + blocks: |boi| &boi.cricket3, + range: 1, + sfx: SfxEvent::Cricket3, + volume: 0.33, cond: |st| st.get_day_period().is_dark(), }, BlockSounds { @@ -145,12 +161,12 @@ impl EventMapper for BlockEventMapper { for sounds in sounds.iter() { // If the timing condition is false, continue // or if the player is far enough underground, continue - // TODO Address bird hack properly. See TODO on line 171 + // TODO Address bird hack properly. See TODO on line 190 if !(sounds.cond)(state) || player_pos.0.z < (terrain_alt - 30.0) || (sounds.sfx == SfxEvent::Birdcall && thread_rng().gen_bool(0.995)) || (sounds.sfx == SfxEvent::Owl && thread_rng().gen_bool(0.998)) - || (sounds.sfx == SfxEvent::Cricket && thread_rng().gen_bool(0.99)) + || (sounds.sfx == SfxEvent::Frog && thread_rng().gen_bool(0.9)) { continue; } @@ -172,9 +188,9 @@ impl EventMapper for BlockEventMapper { // TODO Address this hack properly, potentially by making a new // block of interest type which picks fewer leaf blocks // Hack to reduce the number of bird sounds (too many leaf blocks) - if (sounds.sfx == SfxEvent::Birdcall || sounds.sfx == SfxEvent::Owl) - && thread_rng().gen_bool(0.999) - || (sounds.sfx == SfxEvent::Cricket && thread_rng().gen_bool(0.999)) + if ((sounds.sfx == SfxEvent::Birdcall || sounds.sfx == SfxEvent::Owl) + && thread_rng().gen_bool(0.999)) + || (sounds.sfx == SfxEvent::Frog && thread_rng().gen_bool(0.75)) { continue; } @@ -183,7 +199,11 @@ impl EventMapper for BlockEventMapper { let block_pos = block_pos.map(|x| x as f32); - if Self::should_emit(internal_state, triggers.get_key_value(&sounds.sfx)) { + if Self::should_emit( + internal_state, + triggers.get_key_value(&sounds.sfx), + temp, + ) { // If the camera is within SFX distance if (block_pos.distance_squared(cam_pos)) < SFX_DIST_LIMIT_SQR { let underwater = state @@ -228,12 +248,42 @@ impl BlockEventMapper { fn should_emit( previous_state: &PreviousBlockState, sfx_trigger_item: Option<(&SfxEvent, &SfxTriggerItem)>, + temp: f32, ) -> bool { if let Some((event, item)) = sfx_trigger_item { + //The interval between cricket chirps calculated by converting chunk + // temperature to centigrade (we should create a function for this) and applying + // the "cricket formula" to it + let cricket_interval = (25.0 / (3.0 * ((temp * 30.0) + 15.0))).max(0.5); if &previous_state.event == event { //In case certain sounds need modification to their threshold, //use match event - previous_state.time.elapsed().as_secs_f32() >= item.threshold + match event { + //Crickets' threshold is 0.0 by default + SfxEvent::Cricket1 => { + previous_state.time.elapsed().as_secs_f32() + >= cricket_interval + thread_rng().gen_range(-0.1..0.1) + }, + SfxEvent::Cricket2 => { + //the length and manner of this sound is quite different + if cricket_interval < 0.75 { + previous_state.time.elapsed().as_secs_f32() >= 0.75 + } else { + previous_state.time.elapsed().as_secs_f32() + >= cricket_interval + thread_rng().gen_range(-0.1..0.1) + } + }, + SfxEvent::Cricket3 => { + previous_state.time.elapsed().as_secs_f32() + >= cricket_interval + thread_rng().gen_range(-0.1..0.1) + }, + //Adds random factor to frogs + SfxEvent::Frog => { + previous_state.time.elapsed().as_secs_f32() + >= thread_rng().gen_range(-2.0..2.0) + }, + _ => previous_state.time.elapsed().as_secs_f32() >= item.threshold, + } } else { true } diff --git a/voxygen/src/audio/sfx/mod.rs b/voxygen/src/audio/sfx/mod.rs index 2e8e66e75e..76b22b4fe7 100644 --- a/voxygen/src/audio/sfx/mod.rs +++ b/voxygen/src/audio/sfx/mod.rs @@ -141,7 +141,9 @@ pub enum SfxEvent { Embers, Birdcall, Owl, - Cricket, + Cricket1, + Cricket2, + Cricket3, Frog, Bees, RunningWater, diff --git a/voxygen/src/scene/terrain/watcher.rs b/voxygen/src/scene/terrain/watcher.rs index 50f42d1668..257e01c05e 100644 --- a/voxygen/src/scene/terrain/watcher.rs +++ b/voxygen/src/scene/terrain/watcher.rs @@ -18,6 +18,11 @@ pub struct BlocksOfInterest { pub flowers: Vec>, pub fire_bowls: Vec>, pub snow: Vec>, + //This is so crickets stay in place and don't randomly change sounds + pub cricket1: Vec>, + pub cricket2: Vec>, + pub cricket3: Vec>, + pub frogs: Vec>, // Note: these are only needed for chunks within the iteraction range so this is a potential // area for optimization pub interactables: Vec>, @@ -39,6 +44,10 @@ impl BlocksOfInterest { let mut lights = Vec::new(); let mut fire_bowls = Vec::new(); let mut snow = Vec::new(); + let mut cricket1 = Vec::new(); + let mut cricket2 = Vec::new(); + let mut cricket3 = Vec::new(); + let mut frogs = Vec::new(); chunk .vol_iter( @@ -52,7 +61,17 @@ impl BlocksOfInterest { .for_each(|(pos, block)| { match block.kind() { BlockKind::Leaves if thread_rng().gen_range(0..16) == 0 => leaves.push(pos), - BlockKind::Grass if thread_rng().gen_range(0..16) == 0 => grass.push(pos), + BlockKind::Grass => { + if thread_rng().gen_range(0..16) == 0 { + grass.push(pos); + } + match thread_rng().gen_range(0..8192) { + 1 => cricket1.push(pos), + 2 => cricket2.push(pos), + 3 => cricket3.push(pos), + _ => {}, + } + }, BlockKind::Water if chunk.meta().contains_river() && thread_rng().gen_range(0..16) == 0 => { @@ -73,7 +92,12 @@ impl BlocksOfInterest { }, Some(SpriteKind::WallSconce) => fire_bowls.push(pos + Vec3::unit_z()), Some(SpriteKind::Beehive) => beehives.push(pos), - Some(SpriteKind::Reed) => reeds.push(pos), + Some(SpriteKind::Reed) => { + reeds.push(pos); + if thread_rng().gen_range(0..12) == 0 { + frogs.push(pos) + } + }, Some(SpriteKind::PinkFlower) => flowers.push(pos), Some(SpriteKind::PurpleFlower) => flowers.push(pos), Some(SpriteKind::RedFlower) => flowers.push(pos), @@ -104,6 +128,10 @@ impl BlocksOfInterest { lights, fire_bowls, snow, + cricket1, + cricket2, + cricket3, + frogs, } } } diff --git a/world/src/lib.rs b/world/src/lib.rs index b1e1ba9431..859f829d82 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -226,6 +226,7 @@ impl World { sim_chunk.tree_density, sim_chunk.cave.1.alt != 0.0, sim_chunk.river.is_river(), + sim_chunk.temp, ); let mut chunk = TerrainChunk::new(base_z, stone, air, meta);