Make fade timings configurable, and stop combat music on death.

This commit is contained in:
Avi Weinstock 2021-04-08 17:42:39 -04:00
parent f1b022cdee
commit 7c34a96934
4 changed files with 39 additions and 13 deletions

View File

@ -3,4 +3,12 @@
combat_health_factor: 1000,
combat_nearby_high_thresh: 4,
combat_nearby_low_thresh: 1,
fade_timings: {
(TitleMusic, Explore): (2.0, 12.0),
(TitleMusic, Combat): (2.0, 3.0),
(Explore, TitleMusic): (2.0, 12.0),
(Explore, Combat): (5.0, 3.0),
(Combat, Explore): (5.0, 3.0),
(Combat, TitleMusic): (2.0, 12.0),
},
)

View File

@ -37,7 +37,7 @@ enum ChannelState {
/// transition between `TitleMusic` and `Exploration` when a player enters the
/// world by crossfading over a slow duration. In the future, transitions in the
/// world such as `Exploration` -> `BossBattle` would transition more rapidly.
#[derive(PartialEq, Clone, Copy)]
#[derive(PartialEq, Clone, Copy, Hash, Eq, Deserialize)]
pub enum MusicChannelTag {
TitleMusic,
Exploration,

View File

@ -9,6 +9,7 @@ pub mod soundcache;
use channel::{AmbientChannel, AmbientChannelTag, MusicChannel, MusicChannelTag, SfxChannel};
use fader::Fader;
use music::MUSIC_TRANSITION_MANIFEST;
use sfx::{SfxEvent, SfxTriggerItem};
use soundcache::{OggSound, WavSound};
use std::time::Duration;
@ -152,14 +153,19 @@ impl AudioFrontend {
let existing_channel = self.music_channels.last_mut()?;
if existing_channel.get_tag() != next_channel_tag {
let mtm = MUSIC_TRANSITION_MANIFEST.read();
let (fade_out, fade_in) = mtm
.fade_timings
.get(&(existing_channel.get_tag(), next_channel_tag))
.unwrap_or(&(1.0, 1.0));
let fade_out = Duration::from_millis((1000.0 * fade_out) as _);
let fade_in = Duration::from_millis((1000.0 * fade_in) as _);
// Fade the existing channel out. It will be removed when the fade completes.
existing_channel
.set_fader(Fader::fade_out(Duration::from_secs(2), self.music_volume));
existing_channel.set_fader(Fader::fade_out(fade_out, self.music_volume));
let mut next_music_channel = MusicChannel::new(&audio_stream);
next_music_channel
.set_fader(Fader::fade_in(Duration::from_secs(12), self.music_volume));
next_music_channel.set_fader(Fader::fade_in(fade_in, self.music_volume));
self.music_channels.push(next_music_channel);
}

View File

@ -50,6 +50,7 @@ use common::{
terrain::{BiomeKind, SitesKind},
};
use common_sys::state::State;
use hashbrown::HashMap;
use lazy_static::lazy_static;
use rand::{prelude::SliceRandom, thread_rng, Rng};
use serde::Deserialize;
@ -156,7 +157,7 @@ pub struct MusicMgr {
}
#[derive(Deserialize)]
struct MusicTransitionManifest {
pub struct MusicTransitionManifest {
/// Within what radius do enemies count towards combat music?
combat_nearby_radius: f32,
/// Each multiple of this factor that an enemy has health counts as an extra
@ -166,6 +167,8 @@ struct MusicTransitionManifest {
combat_nearby_high_thresh: u32,
/// How many nearby enemies trigger Low combat music
combat_nearby_low_thresh: u32,
/// Fade in and fade out timings for transitions between channels
pub fade_timings: HashMap<(MusicChannelTag, MusicChannelTag), (f32, f32)>,
}
impl Default for MusicTransitionManifest {
@ -175,6 +178,7 @@ impl Default for MusicTransitionManifest {
combat_health_factor: 1000,
combat_nearby_high_thresh: 3,
combat_nearby_low_thresh: 1,
fade_timings: HashMap::new(),
}
}
}
@ -191,7 +195,7 @@ impl assets::Asset for MusicTransitionManifest {
}
lazy_static! {
static ref MUSIC_TRANSITION_MANIFEST: AssetHandle<MusicTransitionManifest> =
pub static ref MUSIC_TRANSITION_MANIFEST: AssetHandle<MusicTransitionManifest> =
AssetExt::load_expect("voxygen.audio.music_transition_manifest");
}
@ -260,6 +264,13 @@ impl MusicMgr {
);
}
// Override combat music with explore music if the player is dead
if let Some(health) = healths.get(player) {
if health.is_dead {
activity_state = Explore;
}
}
let activity = match self.last_activity {
MusicActivity::State(prev) if prev != activity_state => {
MusicActivity::Transition(prev, activity_state)
@ -311,7 +322,6 @@ impl MusicMgr {
// too many constraints. Returning Err(()) signals that we couldn't find
// an appropriate track for the current state, and hence the state
// machine for the activity shouldn't be updated.
let mut res = Ok(*activity);
let soundtrack = self.soundtrack.read();
// First, filter out tracks not matching the timing, site, and biome
let mut maybe_tracks = soundtrack
@ -354,7 +364,7 @@ impl MusicMgr {
if !filtered_tracks.is_empty() {
maybe_tracks = filtered_tracks;
} else {
res = Err(());
return Err(());
}
// Third, prevent playing the last track if possible (though don't return Err
// here, since the combat music is intended to loop)
@ -396,9 +406,6 @@ impl MusicMgr {
);
if let Ok(track) = new_maybe_track {
if let Some(state) = track.activity_override {
res = Ok(MusicActivity::State(state));
}
//println!("Now playing {:?}", track.title);
self.last_track = String::from(&track.title);
self.began_playing = Instant::now();
@ -410,7 +417,12 @@ impl MusicMgr {
MusicChannelTag::Combat
};
audio.play_music(&track.path, tag);
res
if let Some(state) = track.activity_override {
Ok(MusicActivity::State(state))
} else {
Ok(*activity)
}
} else {
Err(())
}