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

View File

@ -857,6 +857,10 @@ impl Client {
self.state.terrain().get_key_arc(chunk_pos).cloned() 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 inventories(&self) -> ReadStorage<comp::Inventory> { self.state.read_storage() }
pub fn loadouts(&self) -> ReadStorage<comp::Loadout> { 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> { impl<T> Id<T> {
pub fn id(&self) -> u64 { self.0 } pub fn id(&self) -> u64 { self.0 }
pub fn phantomdata(&self) -> PhantomData<T> { self.1 }
} }
impl<T> Copy for Id<T> {} impl<T> Copy for Id<T> {}

View File

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

View File

@ -2,6 +2,7 @@ pub mod biome;
pub mod block; pub mod block;
pub mod chonk; pub mod chonk;
pub mod map; pub mod map;
pub mod site;
pub mod sprite; pub mod sprite;
pub mod structure; pub mod structure;
@ -10,6 +11,7 @@ pub use self::{
biome::BiomeKind, biome::BiomeKind,
block::{Block, BlockKind}, block::{Block, BlockKind},
map::MapSizeLg, map::MapSizeLg,
site::SitesKind,
sprite::SpriteKind, sprite::SpriteKind,
structure::Structure, structure::Structure,
}; };
@ -50,21 +52,92 @@ impl RectVolSize for TerrainChunkSize {
pub struct TerrainChunkMeta { pub struct TerrainChunkMeta {
name: Option<String>, name: Option<String>,
biome: BiomeKind, 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 { 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 { pub fn void() -> Self {
Self { Self {
name: None, name: None,
biome: BiomeKind::Void, 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 name(&self) -> &str { self.name.as_deref().unwrap_or("Wilderness") }
pub fn biome(&self) -> BiomeKind { self.biome } 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 // 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 //! permits usage of the track for non-commercial use
use crate::audio::AudioFrontend; use crate::audio::AudioFrontend;
use client::Client; 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 rand::{seq::IteratorRandom, thread_rng};
use serde::Deserialize; use serde::Deserialize;
use std::time::Instant; use std::time::Instant;
@ -64,6 +68,7 @@ pub struct SoundtrackItem {
/// Whether this track should play during day or night /// Whether this track should play during day or night
timing: Option<DayPeriod>, timing: Option<DayPeriod>,
biome: Option<BiomeKind>, biome: Option<BiomeKind>,
site: Option<SitesKind>,
} }
/// Allows control over when a track should play based on in-game time of day /// Allows control over when a track should play based on in-game time of day
@ -120,25 +125,38 @@ impl MusicMgr {
_ => self.last_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_alt: {}", position[2]);
}
}
if audio.music_enabled() if audio.music_enabled()
&& !self.soundtrack.tracks.is_empty() && !self.soundtrack.tracks.is_empty()
&& (self.began_playing.elapsed().as_secs_f64() > self.next_track_change && self.began_playing.elapsed().as_secs_f64() > self.next_track_change
|| self.playing == PlayState::Stopped) // || self.playing == PlayState::Stopped)
&& self.playing != PlayState::FadingOut // && self.playing != PlayState::FadingOut
{ {
self.play_random_track(audio, state, client); self.play_random_track(audio, state, client);
self.playing = PlayState::Playing; // self.playing = PlayState::Playing;
} else if current_biome != self.last_biome && self.playing == PlayState::Playing { //} else if current_biome != self.last_biome && self.playing == PlayState::Playing {
audio.fade_out_exploration_music(); // audio.fade_out_exploration_music();
self.began_fading = Instant::now(); // self.began_fading = Instant::now();
self.playing = PlayState::FadingOut; // self.playing = PlayState::FadingOut;
} else if self.began_fading.elapsed().as_secs_f64() > 5.0 //} else if self.began_fading.elapsed().as_secs_f64() > 5.0
&& self.playing == PlayState::FadingOut // && self.playing == PlayState::FadingOut
{ //{
audio.stop_exploration_music(); // audio.stop_exploration_music();
self.playing = PlayState::Stopped; // 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) { 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 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_period_of_day = Self::get_current_day_period(game_time);
let current_biome = Self::get_current_biome(client); let current_biome = Self::get_current_biome(client);
let current_site = Self::get_current_site(client);
let mut rng = thread_rng(); let mut rng = thread_rng();
let maybe_track = self let maybe_track = self
@ -165,6 +184,10 @@ impl MusicMgr {
Some(biome) => biome == &current_biome, Some(biome) => biome == &current_biome,
None => true, None => true,
}) })
.filter(|track| match &track.site {
Some(site) => site == &current_site,
None => true,
})
.choose(&mut rng); .choose(&mut rng);
if let Some(track) = maybe_track { 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 { fn load_soundtrack_items() -> SoundtrackCollection {
match assets::load_file("voxygen.audio.soundtrack", &["ron"]) { match assets::load_file("voxygen.audio.soundtrack", &["ron"]) {
Ok(file) => match ron::de::from_reader(file) { 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); let mut chunk = TerrainChunk::new(base_z, stone, air, meta);

View File

@ -2303,14 +2303,18 @@ impl SimChunk {
pub fn get_biome(&self) -> BiomeKind { pub fn get_biome(&self) -> BiomeKind {
if self.alt < CONFIG.sea_level { if self.alt < CONFIG.sea_level {
BiomeKind::Ocean 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 BiomeKind::Mountain
} else if self.temp > CONFIG.desert_temp { } else if self.temp > CONFIG.desert_temp && self.humidity < 0.1 {
BiomeKind::Desert BiomeKind::Desert
} else if self.temp < CONFIG.snow_temp { } 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 { } else if self.tree_density > 0.65 {
BiomeKind::Forest BiomeKind::Forest
} else if self.humidity > 0.8 {
BiomeKind::Swamp
} else { } else {
BiomeKind::Grassland BiomeKind::Grassland
} }