From 9b759efe41476722679f75efe0437bd709cb40e7 Mon Sep 17 00:00:00 2001 From: jiminycrick Date: Fri, 6 Nov 2020 00:05:29 -0800 Subject: [PATCH] Snow footsteps --- assets/voxygen/audio/sfx.ron | 8 ++ .../audio/sfx/footsteps/snow_step_1.wav | 4 +- .../audio/sfx/footsteps/snow_step_2.wav | 4 +- .../audio/sfx/footsteps/snow_step_3.wav | 4 +- common/src/terrain/block.rs | 1 + voxygen/src/audio/music.rs | 75 +++++++-------- .../src/audio/sfx/event_mapper/block/mod.rs | 91 +++---------------- .../audio/sfx/event_mapper/movement/mod.rs | 60 ++++++++---- voxygen/src/audio/sfx/mod.rs | 1 + world/src/block/mod.rs | 7 +- world/src/sim/mod.rs | 12 ++- 11 files changed, 113 insertions(+), 154 deletions(-) diff --git a/assets/voxygen/audio/sfx.ron b/assets/voxygen/audio/sfx.ron index 5434e7818a..7deae97637 100644 --- a/assets/voxygen/audio/sfx.ron +++ b/assets/voxygen/audio/sfx.ron @@ -75,6 +75,14 @@ ], threshold: 0.25, ), + SnowRun: ( + files: [ + "voxygen.audio.sfx.footsteps.snow_step_1", + "voxygen.audio.sfx.footsteps.snow_step_2", + "voxygen.audio.sfx.footsteps.snow_step_3", + ], + threshold: 0.25, + ), ExperienceGained: ( files: [ // "voxygen.audio.sfx.character.experience_gained_1", diff --git a/assets/voxygen/audio/sfx/footsteps/snow_step_1.wav b/assets/voxygen/audio/sfx/footsteps/snow_step_1.wav index 15f1da1ff9..38fb243d2a 100644 --- a/assets/voxygen/audio/sfx/footsteps/snow_step_1.wav +++ b/assets/voxygen/audio/sfx/footsteps/snow_step_1.wav @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14b5b2d7867a04886b235902e6655c362a6d7e26d9a7f3ab6935433c3c3a3577 -size 174854 +oid sha256:b5df4056f85354b477c81dfde450542c3684eb11ffc850ddebdd730cae5c16db +size 116752 diff --git a/assets/voxygen/audio/sfx/footsteps/snow_step_2.wav b/assets/voxygen/audio/sfx/footsteps/snow_step_2.wav index 1e79239998..28cb9352cc 100644 --- a/assets/voxygen/audio/sfx/footsteps/snow_step_2.wav +++ b/assets/voxygen/audio/sfx/footsteps/snow_step_2.wav @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7009a1825d54f68df2c68e1bd1186793de52574d53817f60550558f8ae27ce55 -size 174854 +oid sha256:2d6ebde0ec293ba854987ac4473b3d0db0f83a9c4edfaf281b69b6fe33f49170 +size 116752 diff --git a/assets/voxygen/audio/sfx/footsteps/snow_step_3.wav b/assets/voxygen/audio/sfx/footsteps/snow_step_3.wav index 1778435063..0e05ef9814 100644 --- a/assets/voxygen/audio/sfx/footsteps/snow_step_3.wav +++ b/assets/voxygen/audio/sfx/footsteps/snow_step_3.wav @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3bf83db6c9d68423ee36f6c3f8e07caf37a40292b05ad730f6e6a964dcea021 -size 131654 +oid sha256:37042b31ca33c07967a8f94dac7cc8f4887e22e812f8baedc774c0adf781049d +size 87952 diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 494ee2c0ad..0cb9752003 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -42,6 +42,7 @@ make_case_elim!( Wood = 0x40, Leaves = 0x41, // 0x42 <= x < 0x50 is reserved for future tree parts + Snow = 0x50, // Covers all other cases (we sometimes have bizarrely coloured misc blocks, and also we // often want to experiment with new kinds of block without allocating them a diff --git a/voxygen/src/audio/music.rs b/voxygen/src/audio/music.rs index 2434904bf3..96b8ecad36 100644 --- a/voxygen/src/audio/music.rs +++ b/voxygen/src/audio/music.rs @@ -45,7 +45,7 @@ use common::{ state::State, terrain::{BiomeKind, SitesKind}, }; -use rand::{prelude::SliceRandom, thread_rng}; +use rand::{prelude::SliceRandom, thread_rng, Rng}; use serde::Deserialize; use std::time::Instant; use tracing::warn; @@ -64,7 +64,7 @@ pub struct SoundtrackItem { title: String, path: String, /// Length of the track in seconds - length: f64, + length: f32, /// Whether this track should play during day or night timing: Option, biomes: Vec<(BiomeKind, u8)>, @@ -93,13 +93,10 @@ enum PlayState { pub struct MusicMgr { soundtrack: SoundtrackCollection, began_playing: Instant, - //began_fading: Instant, - next_track_change: f64, + next_track_change: f32, /// The title of the last track played. Used to prevent a track /// being played twice in a row last_track: String, - /*last_biome: BiomeKind, - *playing: PlayState, */ } impl MusicMgr { @@ -108,61 +105,51 @@ impl MusicMgr { Self { soundtrack: Self::load_soundtrack_items(), began_playing: Instant::now(), - //began_fading: Instant::now(), next_track_change: 0.0, last_track: String::from("None"), - /*last_biome: BiomeKind::Void, - *playing: PlayState::Stopped, */ } } /// Checks whether the previous track has completed. If so, sends a /// request to play the next (random) track pub fn maintain(&mut self, audio: &mut AudioFrontend, state: &State, client: &Client) { - // Gets the current player biome - //let current_biome: BiomeKind = match client.current_chunk() { - // Some(chunk) => chunk.meta().biome(), - // _ => self.last_biome, + if let Some(current_chunk) = client.current_chunk() { + println!("biome: {:?}", current_chunk.meta().biome()); + println!("chaos: {}", current_chunk.meta().chaos()); + println!("alt: {}", current_chunk.meta().alt()); + println!("temp: {}", current_chunk.meta().temp()); + println!("tree_density: {}", current_chunk.meta().tree_density()); + println!("humidity: {}", current_chunk.meta().humidity()); + println!("cave_alt: {}", current_chunk.meta().cave_alt()); + //if let Some(position) = client.current_position() { + // println!("player_pos: {:?}", position); + } + //let player_position = match client.current_position() { + // Some(pos) => pos, + // None => Vec3::default(), //}; - - //if let Some(current_chunk) = client.current_chunk() { - // println!("biome: {:?}", current_chunk.meta().biome()); - // println!("chaos: {}", current_chunk.meta().chaos()); - // println!("alt: {}", current_chunk.meta().alt()); - // println!("temp: {}", current_chunk.meta().temp()); - // println!("tree_density: {}", - // current_chunk.meta().tree_density()); - // println!("humidity: {}", current_chunk.meta().humidity()); - // println!("cave_alt: {}", current_chunk.meta().cave_alt()); - // if let Some(position) = client.current_position() { - // println!("player_alt: {}", position[2]); - // } - //} + //let block_position = Vec3::new( + // player_position[0], + // player_position[1], + // player_position[2] - 1.0, + //) + //.map(|x| x as i32); + //let block_kind = match state.get_block(block_position) { + // Some(block) => block.kind(), + // None => BlockKind::Air, + //}; + //println!("BlockKind: {:?}", block_kind); if audio.music_enabled() && !self.soundtrack.tracks.is_empty() - && self.began_playing.elapsed().as_secs_f64() > self.next_track_change - // || self.playing == PlayState::Stopped) - // && self.playing != PlayState::FadingOut + && self.began_playing.elapsed().as_secs_f32() > self.next_track_change { self.play_random_track(audio, state, client); - // self.playing = PlayState::Playing; - //} else if current_biome != self.last_biome && self.playing == PlayState::Playing { - // audio.fade_out_exploration_music(); - // self.began_fading = Instant::now(); - // self.playing = PlayState::FadingOut; - //} else if self.began_fading.elapsed().as_secs_f64() > 5.0 - // && self.playing == PlayState::FadingOut - //{ - // audio.stop_exploration_music(); - // self.playing = PlayState::Stopped; } - //self.last_biome = current_biome; } fn play_random_track(&mut self, audio: &mut AudioFrontend, state: &State, client: &Client) { - //const SILENCE_BETWEEN_TRACKS_SECONDS: f64 = 45.0; - const SILENCE_BETWEEN_TRACKS_SECONDS: f64 = 5.0; + let silence_between_tracks_seconds: f32 = thread_rng().gen_range(30.0, 60.0); let game_time = (state.get_time_of_day() as u64 % 86400) as u32; let current_period_of_day = Self::get_current_day_period(game_time); @@ -217,7 +204,7 @@ impl MusicMgr { if let Ok(track) = new_maybe_track { self.last_track = String::from(&track.title); self.began_playing = Instant::now(); - self.next_track_change = track.length + SILENCE_BETWEEN_TRACKS_SECONDS; + self.next_track_change = track.length + silence_between_tracks_seconds; audio.play_exploration_music(&track.path); } diff --git a/voxygen/src/audio/sfx/event_mapper/block/mod.rs b/voxygen/src/audio/sfx/event_mapper/block/mod.rs index 8282892a41..991f72987c 100644 --- a/voxygen/src/audio/sfx/event_mapper/block/mod.rs +++ b/voxygen/src/audio/sfx/event_mapper/block/mod.rs @@ -71,6 +71,7 @@ impl EventMapper for BlockEventMapper { // Condition that must be true to play cond: fn(&State) -> bool, } + let sounds: &[BlockSounds] = &[ BlockSounds { blocks: |boi| &boi.leaves, @@ -108,7 +109,6 @@ impl EventMapper for BlockEventMapper { sfx: SfxEvent::Frog, volume: 0.8, cond: |st| st.get_day_period().is_dark(), - //cond: |_| true, }, //BlockSounds { // blocks: |boi| &boi.flowers, @@ -153,86 +153,34 @@ impl EventMapper for BlockEventMapper { // Get the positions of the blocks of type sounds let blocks = (sounds.blocks)(&chunk_data.blocks_of_interest); - //let mut my_blocks = blocks.to_vec(); - //// Reduce the number of bird calls from trees - //if sounds.sfx == SfxEvent::Birdcall { - // my_blocks = my_blocks.choose_multiple(&mut thread_rng(), 6).cloned().collect(); - // //blocks = blocks.to_vec().choose_multiple(&mut thread_rng(), 6).cloned().collect::>>().as_slice(); - //} else if sounds.sfx == SfxEvent::Cricket { - // my_blocks = my_blocks.choose_multiple(&mut thread_rng(), 6).cloned().collect(); - //} - let absolute_pos: Vec3 = Vec3::from(chunk_pos * TerrainChunk::RECT_SIZE.map(|e| e as i32)); // Iterate through each individual block for block in blocks { - - if (sounds.sfx == SfxEvent::Birdcall || sounds.sfx == SfxEvent::Owl) && thread_rng().gen_bool(0.999) { - continue; - } + if (sounds.sfx == SfxEvent::Birdcall || sounds.sfx == SfxEvent::Owl) + && thread_rng().gen_bool(0.999) + { + continue; + } let block_pos: Vec3 = absolute_pos + block; let state = self.history.entry(block_pos).or_default(); - // Convert to f32 for sfx emitter - //let block_pos = Vec3::new( - // block_pos[0] as f32, - // block_pos[1] as f32, - // block_pos[2] as f32, - //); let block_pos = block_pos.map(|x| x as f32); if Self::should_emit(state, triggers.get_key_value(&sounds.sfx)) { // If the camera is within SFX distance if (block_pos.distance_squared(cam_pos)) < SFX_DIST_LIMIT_SQR { - sfx_emitter.emit(SfxEventItem::new(sounds.sfx.clone(), Some(block_pos), Some(sounds.volume))); + sfx_emitter.emit(SfxEventItem::new( + sounds.sfx.clone(), + Some(block_pos), + Some(sounds.volume), + )); state.time = Instant::now(); state.event = sounds.sfx.clone(); } } } - - //// If the timer for this block is over the spacing - //// and the block is in the history - //if self.history.contains_key(&block_pos) { - // if self - // .history - // .get(&block_pos) - // .unwrap() // can't fail as the key is in the hashmap - // .elapsed() - // .as_secs_f32() - // > sounds.spacing - // { - // // Reset timer for this block - // self.history.insert(block_pos, Instant::now()); - - // // Convert to f32 for distance_squared function - // let block_pos = Vec3::new( - // block_pos[0] as f32, - // block_pos[1] as f32, - // block_pos[2] as f32, - // ); - - // // If the camera is within SFX distance - // if (block_pos.distance_squared(cam_pos)) < SFX_DIST_LIMIT_SQR { - // // Emit the sound - // let sfx_trigger_item = triggers.get_trigger(&sounds.sfx); - // if sfx_trigger_item.is_some() { - // ecs.read_resource::>().emit_now( - // SfxEventItem::new( - // sounds.sfx.clone(), - // Some(block_pos), - // Some(sounds.volume), - // ), - // ); - // } - // } - // } - //} else { - // // Start the timer for this block - // self.history.insert(block_pos, Instant::now()); - //} - //} }); } } @@ -260,21 +208,4 @@ impl BlockEventMapper { false } } - //fn map_event(&mut self, blocktype: BlockEmitter) -> Option { - // if self.timer.elapsed().as_secs_f32() > 1.0 { - // self.timer = Instant::now(); - // let sfx_event = match blocktype { - // BlockEmitter::Leaves => Some(SfxEvent::LevelUp), - // BlockEmitter::Grass => Some(SfxEvent::Roll), - // BlockEmitter::Embers => Some(SfxEvent::Roll), - // BlockEmitter::Beehives => Some(SfxEvent::Roll), - // BlockEmitter::Reeds => Some(SfxEvent::Roll), - // BlockEmitter::Flowers => Some(SfxEvent::Roll), - // }; - - // sfx_event - // } else { - // None - // } - //} } diff --git a/voxygen/src/audio/sfx/event_mapper/movement/mod.rs b/voxygen/src/audio/sfx/event_mapper/movement/mod.rs index b421ecbf50..c0bc9c574b 100644 --- a/voxygen/src/audio/sfx/event_mapper/movement/mod.rs +++ b/voxygen/src/audio/sfx/event_mapper/movement/mod.rs @@ -10,7 +10,7 @@ use common::{ comp::{Body, CharacterState, PhysicsState, Pos, Vel}, event::EventBus, state::State, - terrain::TerrainChunk, + terrain::{BlockKind, TerrainChunk}, }; use hashbrown::HashMap; use specs::{Entity as EcsEntity, Join, WorldExt}; @@ -69,38 +69,53 @@ impl EventMapper for MovementEventMapper { .filter(|(_, e_pos, ..)| (e_pos.0.distance_squared(cam_pos)) < SFX_DIST_LIMIT_SQR) { if let Some(character) = character { - let state = self.event_history.entry(entity).or_default(); + let internal_state = self.event_history.entry(entity).or_default(); + + // Get the underfoot block + let block_position = Vec3::new(pos.0.x, pos.0.y, pos.0.z - 1.0).map(|x| x as i32); + let underfoot_block_kind = match state.get_block(block_position) { + Some(block) => block.kind(), + None => BlockKind::Air, + }; let mapped_event = match body { - Body::Humanoid(_) => Self::map_movement_event(character, physics, state, vel.0), + Body::Humanoid(_) => Self::map_movement_event( + character, + physics, + internal_state, + vel.0, + underfoot_block_kind, + ), Body::QuadrupedMedium(_) | Body::QuadrupedSmall(_) | Body::QuadrupedLow(_) | Body::BirdMedium(_) | Body::BirdSmall(_) - | Body::BipedLarge(_) => Self::map_non_humanoid_movement_event(physics, vel.0), + | Body::BipedLarge(_) => { + Self::map_non_humanoid_movement_event(physics, vel.0, underfoot_block_kind) + }, _ => SfxEvent::Idle, // Ignore fish, etc... }; // Check for SFX config entry for this movement - if Self::should_emit(state, triggers.get_key_value(&mapped_event)) { + if Self::should_emit(internal_state, triggers.get_key_value(&mapped_event)) { sfx_emitter.emit(SfxEventItem::new( mapped_event.clone(), Some(pos.0), Some(Self::get_volume_for_body_type(body)), )); - state.time = Instant::now(); + internal_state.time = Instant::now(); } // update state to determine the next event. We only record the time (above) if // it was dispatched - state.event = mapped_event; - state.on_ground = physics.on_ground; + internal_state.event = mapped_event; + internal_state.on_ground = physics.on_ground; if physics.in_fluid.is_some() { - state.in_water = true; + internal_state.in_water = true; } else { - state.in_water = false; + internal_state.in_water = false; } } } @@ -162,11 +177,10 @@ impl MovementEventMapper { physics_state: &PhysicsState, previous_state: &PreviousEntityState, vel: Vec3, + underfoot_block_kind: BlockKind, ) -> SfxEvent { // Match run / roll / swim state - if physics_state.in_fluid.is_some() - //&& physics_state.in_fluid.unwrap() < 2.0 // To control different sound based on depth - && vel.magnitude() > 0.1 + if physics_state.in_fluid.is_some() && vel.magnitude() > 0.1 || !previous_state.in_water && physics_state.in_fluid.is_some() { return SfxEvent::Swim; @@ -178,7 +192,10 @@ impl MovementEventMapper { } else if matches!(character_state, CharacterState::Sneak) { SfxEvent::Sneak } else { - SfxEvent::Run + match underfoot_block_kind { + BlockKind::Snow => SfxEvent::SnowRun, + _ => SfxEvent::Run, + } }; } @@ -198,9 +215,18 @@ impl MovementEventMapper { } /// Maps a limited set of movements for other non-humanoid entities - fn map_non_humanoid_movement_event(physics_state: &PhysicsState, vel: Vec3) -> SfxEvent { - if physics_state.on_ground && vel.magnitude() > 0.1 { - SfxEvent::Run + fn map_non_humanoid_movement_event( + physics_state: &PhysicsState, + vel: Vec3, + underfoot_block_kind: BlockKind, + ) -> SfxEvent { + if physics_state.in_fluid.is_some() && vel.magnitude() > 0.1 { + return SfxEvent::Swim; + } else if physics_state.on_ground && vel.magnitude() > 0.1 { + match underfoot_block_kind { + BlockKind::Snow => SfxEvent::SnowRun, + _ => SfxEvent::Run, + } } else { SfxEvent::Idle } diff --git a/voxygen/src/audio/sfx/mod.rs b/voxygen/src/audio/sfx/mod.rs index d4e56855bc..cb72910152 100644 --- a/voxygen/src/audio/sfx/mod.rs +++ b/voxygen/src/audio/sfx/mod.rs @@ -146,6 +146,7 @@ pub enum SfxEvent { Idle, Swim, Run, + SnowRun, Roll, Sneak, Climb, diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 53ddc1cc73..e543f6e00e 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -1,7 +1,7 @@ use crate::{ column::{ColumnGen, ColumnSample}, util::{RandomField, Sampler, SmallCache}, - IndexRef, + IndexRef, CONFIG, }; use common::terrain::{ structure::{self, StructureBlock}, @@ -67,6 +67,7 @@ impl<'a> BlockGen<'a> { // marble_small, rock, // temp, + temp, // humidity, stone_col, .. @@ -128,7 +129,9 @@ impl<'a> BlockGen<'a> { let col = Lerp::lerp(sub_surface_color, surface_color, grass_factor); // Surface Some(Block::new( - if grass_factor > 0.7 { + if temp < CONFIG.snow_temp + 0.031 { + BlockKind::Snow + } else if grass_factor > 0.7 { BlockKind::Grass } else { BlockKind::Earth diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index 60bf0efe0d..2ec204b473 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -2303,13 +2303,15 @@ impl SimChunk { pub fn get_biome(&self) -> BiomeKind { if self.alt < CONFIG.sea_level { BiomeKind::Ocean - } else if self.alt > 450.0 && self.chaos > 0.4 && self.tree_density < 0.7 { - BiomeKind::Mountain - } else if self.temp > CONFIG.desert_temp && self.humidity < 0.1 { - BiomeKind::Desert + } else if self.humidity == 0.0 { + BiomeKind::Lake } else if self.temp < CONFIG.snow_temp { BiomeKind::Snowland - } else if self.tree_density > 0.65 && self.humidity > 0.9 && self.temp > 0.8 { + } else if self.alt > 450.0 && self.chaos > 0.35 && self.tree_density < 0.7 { + BiomeKind::Mountain + } else if self.temp > CONFIG.desert_temp && self.humidity < 0.6 { + BiomeKind::Desert + } else if self.tree_density > 0.65 && self.humidity > 0.7 && self.temp > 0.8 { BiomeKind::Jungle } else if self.tree_density > 0.65 { BiomeKind::Forest