Dungeon and cave specific music

This commit is contained in:
jiminycrick 2020-11-01 23:19:28 -08:00
parent 0a9f1ee11c
commit c8d79b0b0e
9 changed files with 286 additions and 123 deletions

View File

@ -3,116 +3,130 @@
(
tracks: [
(
title: "A Solemn Quest",
path: "voxygen.audio.soundtrack.a_solemn_quest",
length: 206.0,
timing: Some(Day),
biome: Some(Forest),
artist: "Eden",
),
(
title: "Into The Dark Forest",
path: "voxygen.audio.soundtrack.into_the_dark_forest",
length: 184.0,
timing: Some(Day),
biome: Some(Grassland),
artist: "Aeronic",
),
(
title: "Field Grazing",
path: "voxygen.audio.soundtrack.field_grazing",
length: 154.0,
timing: Some(Day),
biome: Some(Snowlands),
artist: "Aeronic",
),
(
title: "Wandering Voices",
path: "voxygen.audio.soundtrack.wandering_voices",
length: 137.0,
timing: Some(Day),
biome: Some(Desert),
artist: "Aeronic",
),
(
title: "Snowtop Volume", //Snow Region
path: "voxygen.audio.soundtrack.snowtop_volume",
length: 89.0,
timing: Some(Day),
biome: Some(Desert),
artist: "Aeronic",
),
(
title: "Mineral Deposits",
path: "voxygen.audio.soundtrack.mineral_deposits",
length: 148.0,
timing: Some(Day),
biome: Some(Desert),
artist: "Aeronic",
),
(
title: "Moonbeams",
path: "voxygen.audio.soundtrack.moonbeams",
length: 158.0,
timing: Some(Night),
biome: Some(Desert),
artist: "Aeronic",
),
(
title: "Serene Meadows",
path: "voxygen.audio.soundtrack.serene_meadows",
length: 173.0,
timing: Some(Night),
biome: Some(Desert),
artist: "Aeronic",
),
/*(
title: "Rest Assured", // Town/Shop
path: "voxygen.audio.soundtrack.rest_assured",
length: 185.0,
timing: Some(Day),
biome: Some(Desert),
artist: "badbbad",
),*/
(
title: "Just The Beginning",
path: "voxygen.audio.soundtrack.just_the_beginning",
length: 188.0,
timing: Some(Day),
biome: Some(Desert),
artist: "badbbad",
),
(
title: "Campfire Stories",
path: "voxygen.audio.soundtrack.campfire_stories",
length: 100.0,
timing: Some(Night),
biome: Some(Desert),
artist: "badbbad",
),
(
title: "Limits",
path: "voxygen.audio.soundtrack.limits",
length: 203.0,
timing: Some(Night),
biome: Some(Desert),
artist: "badbbad",
),
/*( // Dungeon
//(
// title: "A Solemn Quest",
// path: "voxygen.audio.soundtrack.a_solemn_quest",
// length: 206.0,
// timing: Some(Day),
// biome: Some(Forest),
// site: None,
// artist: "Eden",
//),
//(
// title: "Into The Dark Forest",
// path: "voxygen.audio.soundtrack.into_the_dark_forest",
// length: 184.0,
// timing: Some(Day),
// biome: Some(Grassland),
// site: None,
// artist: "Aeronic",
//),
//(
// title: "Field Grazing",
// path: "voxygen.audio.soundtrack.field_grazing",
// length: 154.0,
// timing: Some(Day),
// biome: Some(Snowland),
// site: None,
// artist: "Aeronic",
//),
//(
// title: "Wandering Voices",
// path: "voxygen.audio.soundtrack.wandering_voices",
// length: 137.0,
// timing: Some(Day),
// biome: Some(Desert),
// site: None,
// artist: "Aeronic",
//),
//(
// title: "Snowtop Volume", //Snow Region
// path: "voxygen.audio.soundtrack.snowtop_volume",
// length: 89.0,
// timing: Some(Day),
// biome: Some(Desert),
// site: None,
// artist: "Aeronic",
//),
//(
// title: "Mineral Deposits",
// path: "voxygen.audio.soundtrack.mineral_deposits",
// length: 148.0,
// timing: Some(Day),
// biome: Some(Desert),
// site: None,
// artist: "Aeronic",
//),
//(
// title: "Moonbeams",
// path: "voxygen.audio.soundtrack.moonbeams",
// length: 158.0,
// timing: Some(Night),
// biome: Some(Desert),
// site: None,
// artist: "Aeronic",
//),
//(
// title: "Serene Meadows",
// path: "voxygen.audio.soundtrack.serene_meadows",
// length: 173.0,
// timing: Some(Night),
// biome: Some(Desert),
// site: None,
// artist: "Aeronic",
//),
///*(
// title: "Rest Assured", // Town/Shop
// path: "voxygen.audio.soundtrack.rest_assured",
// length: 185.0,
// timing: Some(Day),
// biome: Some(Desert),
// site: None,
// artist: "badbbad",
//),*/
//(
// title: "Just The Beginning",
// path: "voxygen.audio.soundtrack.just_the_beginning",
// length: 188.0,
// timing: Some(Day),
// biome: Some(Desert),
// site: None,
// artist: "badbbad",
//),
//(
// title: "Campfire Stories",
// path: "voxygen.audio.soundtrack.campfire_stories",
// length: 100.0,
// timing: Some(Night),
// biome: Some(Desert),
// site: None,
// artist: "badbbad",
//),
//(
// title: "Limits",
// path: "voxygen.audio.soundtrack.limits",
// length: 203.0,
// timing: Some(Night),
// biome: Some(Desert),
// site: None,
// artist: "badbbad",
//),
( // Dungeon
title: "Down The Rabbit Hole",
path: "voxygen.audio.soundtrack.down_the_rabbit_hole",
length: 244.0,
timing: Some(Night),
biome: Some(Desert),
timing: None,
biome: None,
site: Some(Cave),
artist: "badbbad",
),*/
),
(
title: "Between The Fairies",
path: "voxygen.audio.soundtrack.between_the_fairies",
length: 175.0,
timing: Some(Night),
biome: Some(Desert),
timing: None,
biome: None,
site: Some(Dungeon),
artist: "badbbad",
),
]

View File

@ -857,6 +857,10 @@ impl Client {
self.state.terrain().get_key_arc(chunk_pos).cloned()
}
pub fn current_position(&self) -> Option<Vec3<f32>> {
Some(self.state.read_storage::<comp::Pos>().get(self.entity).cloned()?.0)
}
pub fn inventories(&self) -> ReadStorage<comp::Inventory> { self.state.read_storage() }
pub fn loadouts(&self) -> ReadStorage<comp::Loadout> { self.state.read_storage() }

View File

@ -11,6 +11,8 @@ pub struct Id<T>(u64, PhantomData<T>);
impl<T> Id<T> {
pub fn id(&self) -> u64 { self.0 }
pub fn phantomdata(&self) -> PhantomData<T> { self.1 }
}
impl<T> Copy for Id<T> {}

View File

@ -3,11 +3,13 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq)]
pub enum BiomeKind {
Void,
Lake,
Grassland,
Ocean,
Mountain,
Snowlands,
Snowland,
Desert,
Swamp,
Jungle,
Forest,
}

View File

@ -2,6 +2,7 @@ pub mod biome;
pub mod block;
pub mod chonk;
pub mod map;
pub mod site;
pub mod sprite;
pub mod structure;
@ -10,6 +11,7 @@ pub use self::{
biome::BiomeKind,
block::{Block, BlockKind},
map::MapSizeLg,
site::SitesKind,
sprite::SpriteKind,
structure::Structure,
};
@ -50,21 +52,92 @@ impl RectVolSize for TerrainChunkSize {
pub struct TerrainChunkMeta {
name: Option<String>,
biome: BiomeKind,
chaos: f32,
alt: f32,
//basement: f32,
//water_alt: f32,
//downhill: Option<Vec2<i32>>,
//flux: f32,
temp: f32,
humidity: f32,
rockiness: f32,
//is_cliffs: bool,
//near_cliffs: bool,
tree_density: f32,
//forest_kind: ForestKind,
//spawn_rate: f32,
//river: RiverData,
//warp_factor: f32,
surface_veg: f32,
cave_alt: f32,
/*place: Option<Id<Place>>, */
/*path: (Way, Path),*/
/* contains_waypoint: bool, */
}
impl TerrainChunkMeta {
pub fn new(name: Option<String>, biome: BiomeKind) -> Self { Self { name, biome } }
pub fn new(
name: Option<String>,
biome: BiomeKind,
chaos: f32,
alt: f32,
temp: f32,
humidity: f32,
rockiness: f32,
tree_density: f32,
surface_veg: f32,
cave_alt: f32,
) -> Self {
Self {
name,
biome,
chaos,
alt,
temp,
humidity,
rockiness,
tree_density,
surface_veg,
cave_alt,
}
}
pub fn void() -> Self {
Self {
name: None,
biome: BiomeKind::Void,
chaos: 0.0,
alt: 0.0,
temp: 0.0,
humidity: 0.0,
rockiness: 0.0,
tree_density: 0.0,
surface_veg: 0.0,
cave_alt: 0.0,
}
}
pub fn name(&self) -> &str { self.name.as_deref().unwrap_or("Wilderness") }
pub fn biome(&self) -> BiomeKind { self.biome }
pub fn chaos(&self) -> f32 { self.chaos }
pub fn alt(&self) -> f32 { self.alt }
pub fn temp(&self) -> f32 { self.temp }
pub fn humidity(&self) -> f32 { self.humidity }
pub fn rockiness(&self) -> f32 { self.rockiness }
pub fn tree_density(&self) -> f32 { self.tree_density }
pub fn surface_veg(&self) -> f32 { self.surface_veg }
pub fn cave_alt(&self) -> f32 { self.cave_alt }
}
// Terrain type aliases

View File

@ -0,0 +1,10 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq)]
pub enum SitesKind {
Dungeon,
Cave,
Settlement,
Castle,
None,
}

View File

@ -40,7 +40,11 @@
//! permits usage of the track for non-commercial use
use crate::audio::AudioFrontend;
use client::Client;
use common::{assets, state::State, terrain::BiomeKind};
use common::{
assets,
state::State,
terrain::{BiomeKind, SitesKind},
};
use rand::{seq::IteratorRandom, thread_rng};
use serde::Deserialize;
use std::time::Instant;
@ -64,6 +68,7 @@ pub struct SoundtrackItem {
/// Whether this track should play during day or night
timing: Option<DayPeriod>,
biome: Option<BiomeKind>,
site: Option<SitesKind>,
}
/// Allows control over when a track should play based on in-game time of day
@ -120,25 +125,38 @@ impl MusicMgr {
_ => 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_alt: {}", position[2]);
}
}
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_f64() > self.next_track_change
// || self.playing == PlayState::Stopped)
// && self.playing != PlayState::FadingOut
{
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.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;
//self.last_biome = current_biome;
}
fn play_random_track(&mut self, audio: &mut AudioFrontend, state: &State, client: &Client) {
@ -148,6 +166,7 @@ impl MusicMgr {
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);
let current_biome = Self::get_current_biome(client);
let current_site = Self::get_current_site(client);
let mut rng = thread_rng();
let maybe_track = self
@ -165,6 +184,10 @@ impl MusicMgr {
Some(biome) => biome == &current_biome,
None => true,
})
.filter(|track| match &track.site {
Some(site) => site == &current_site,
None => true,
})
.choose(&mut rng);
if let Some(track) = maybe_track {
@ -191,6 +214,26 @@ impl MusicMgr {
}
}
fn get_current_site(client: &Client) -> SitesKind {
let mut player_alt = 0.0;
if let Some(position) = client.current_position() {
player_alt = position[2];
}
let mut cave_alt = 0.0;
let mut alt = 0.0;
if let Some(chunk) = client.current_chunk() {
alt = chunk.meta().alt();
cave_alt = chunk.meta().cave_alt();
}
if player_alt < cave_alt && cave_alt != 0.0 {
SitesKind::Cave
} else if player_alt < (alt - 30.0) {
SitesKind::Dungeon
} else {
SitesKind::None
}
}
fn load_soundtrack_items() -> SoundtrackCollection {
match assets::load_file("voxygen.audio.soundtrack", &["ron"]) {
Ok(file) => match ron::de::from_reader(file) {

View File

@ -155,7 +155,18 @@ impl World {
},
};
let meta = TerrainChunkMeta::new(sim_chunk.get_name(&self.sim), sim_chunk.get_biome());
let meta = TerrainChunkMeta::new(
sim_chunk.get_name(&self.sim),
sim_chunk.get_biome(),
sim_chunk.chaos,
sim_chunk.alt,
sim_chunk.temp,
sim_chunk.humidity,
sim_chunk.rockiness,
sim_chunk.tree_density,
sim_chunk.surface_veg,
sim_chunk.cave.1.alt,
);
let mut chunk = TerrainChunk::new(base_z, stone, air, meta);

View File

@ -2303,14 +2303,18 @@ impl SimChunk {
pub fn get_biome(&self) -> BiomeKind {
if self.alt < CONFIG.sea_level {
BiomeKind::Ocean
} else if self.chaos > 0.6 {
} else if self.alt > 450.0 && self.chaos > 0.4 && self.tree_density < 0.7 {
BiomeKind::Mountain
} else if self.temp > CONFIG.desert_temp {
} else if self.temp > CONFIG.desert_temp && self.humidity < 0.1 {
BiomeKind::Desert
} else if self.temp < CONFIG.snow_temp {
BiomeKind::Snowlands
BiomeKind::Snowland
} else if self.tree_density > 0.65 && self.humidity > 0.9 && self.temp > 0.8 {
BiomeKind::Jungle
} else if self.tree_density > 0.65 {
BiomeKind::Forest
} else if self.humidity > 0.8 {
BiomeKind::Swamp
} else {
BiomeKind::Grassland
}