diff --git a/assets/voxygen/audio/sfx.ron b/assets/voxygen/audio/sfx.ron index 85ff1b92af..e81459a2df 100644 --- a/assets/voxygen/audio/sfx.ron +++ b/assets/voxygen/audio/sfx.ron @@ -109,9 +109,9 @@ ), Explosion: ( files: [ - "voxygen.audio.sfx.glider_open", + "voxygen.audio.sfx.explosion", ], - threshold: 0.5, + threshold: 0.2, ), ProjectileShot: ( files: [ diff --git a/assets/voxygen/audio/sfx/explosion.wav b/assets/voxygen/audio/sfx/explosion.wav new file mode 100644 index 0000000000..f7269ac71c --- /dev/null +++ b/assets/voxygen/audio/sfx/explosion.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d7f0bb0a0865d45e98d107c1d24a448aaeeced9c37db9f9e472ab3e1bd2eb03 +size 604946 diff --git a/assets/voxygen/shaders/particle-vert.glsl b/assets/voxygen/shaders/particle-vert.glsl index 70580be584..49d2fd86ab 100644 --- a/assets/voxygen/shaders/particle-vert.glsl +++ b/assets/voxygen/shaders/particle-vert.glsl @@ -31,6 +31,7 @@ float gold_noise(in vec2 xy, in float seed){ const int SMOKE = 0; const int FIRE = 1; const int GUN_POWDER_SPARK = 2; +const int SHRAPNEL = 3; // meters per second const float earth_gravity = 9.807; @@ -105,6 +106,15 @@ void main() { 1.0, vec3(3.5, 3 + rand7, 0) ); + } else if (inst_mode == SHRAPNEL) { + attr = Attr( + linear_motion( + vec3(0), + vec3(rand4, rand5, rand6) * 40.0 + grav_vel(earth_gravity) + ), + 3.0 + rand0, + vec3(0.6 + rand7 * 0.4) + ); } else { attr = Attr( linear_motion( diff --git a/voxygen/src/audio/sfx/mod.rs b/voxygen/src/audio/sfx/mod.rs index d2bb328494..6a4e0f8855 100644 --- a/voxygen/src/audio/sfx/mod.rs +++ b/voxygen/src/audio/sfx/mod.rs @@ -199,7 +199,7 @@ impl<'a> TryFrom<&'a Outcome> for SfxEventItem { Outcome::Explosion { pos, power } => Ok(Self::new( SfxEvent::Explosion, Some(*pos), - Some((*power / 10.0).min(1.0)), + Some((*power / 2.5).min(1.5)), )), Outcome::ProjectileShot { pos, .. } => { Ok(Self::new(SfxEvent::ProjectileShot, Some(*pos), None)) diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index f97890626d..442b31be32 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -117,6 +117,11 @@ impl Light { } pub fn get_pos(&self) -> Vec3 { Vec3::new(self.pos[0], self.pos[1], self.pos[2]) } + + pub fn with_strength(mut self, strength: f32) -> Self { + self.col = (Vec4::::from(self.col) * strength).into_array(); + self + } } impl Default for Light { diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 1f467c638e..e8e222e224 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -83,9 +83,10 @@ impl Vertex { } pub enum ParticleMode { - CampfireSmoke, - CampfireFire, - GunPowderSpark, + CampfireSmoke = 0, + CampfireFire = 1, + GunPowderSpark = 2, + Shrapnel = 3, } impl ParticleMode { diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 83b827799e..5ee7f0257b 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -21,9 +21,10 @@ use crate::{ use anim::character::SkeletonAttr; use common::{ comp, - state::State, + state::{State, DeltaTime}, terrain::{BlockKind, TerrainChunk}, vol::ReadVol, + outcome::Outcome, }; use specs::{Entity as EcsEntity, Join, WorldExt}; use vek::*; @@ -41,6 +42,12 @@ const SHADOW_MAX_DIST: f32 = 96.0; // The distance beyond which shadows may not /// Used for first person camera effects const RUNNING_THRESHOLD: f32 = 0.7; +struct EventLight { + light: Light, + timeout: f32, + fadeout: fn(f32) -> f32, +} + struct Skybox { model: Model, locals: Consts, @@ -57,6 +64,7 @@ pub struct Scene { shadows: Consts, camera: Camera, camera_input_state: Vec2, + event_lights: Vec, skybox: Skybox, postprocess: PostProcess, @@ -101,6 +109,7 @@ impl Scene { .unwrap(), camera: Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson), camera_input_state: Vec2::zero(), + event_lights: Vec::new(), skybox: Skybox { model: renderer.create_model(&create_skybox_mesh()).unwrap(), @@ -135,9 +144,6 @@ impl Scene { /// Get a reference to the scene's particle manager. pub fn particle_mgr(&self) -> &ParticleMgr { &self.particle_mgr } - /// Get a mutable reference to the scene's particle manager. - pub fn particle_mgr_mut(&mut self) -> &mut ParticleMgr { &mut self.particle_mgr } - /// Get a reference to the scene's figure manager. pub fn figure_mgr(&self) -> &FigureMgr { &self.figure_mgr } @@ -187,6 +193,23 @@ impl Scene { } } + pub fn handle_outcome(&mut self, outcome: &Outcome, scene_data: &SceneData) { + match outcome { + Outcome::Explosion { pos, power, .. } => self.event_lights.push(EventLight { + light: Light::new( + *pos, + Rgb::new(1.0, 0.5, 0.0), + *power * 2.5, + ), + timeout: 0.5, + fadeout: |timeout| timeout * 2.0, + }), + _ => {}, + } + + self.particle_mgr.handle_outcome(&outcome, &scene_data); + } + /// Maintain data such as GPU constant buffers, models, etc. To be called /// once per tick. pub fn maintain( @@ -319,6 +342,9 @@ impl Scene { light_anim.strength, ) }) + .chain(self.event_lights + .iter() + .map(|el| el.light.with_strength((el.fadeout)(el.timeout)))) .collect::>(); lights.sort_by_key(|light| light.get_pos().distance_squared(player_pos) as i32); lights.truncate(MAX_LIGHT_COUNT); @@ -326,6 +352,13 @@ impl Scene { .update_consts(&mut self.lights, &lights) .expect("Failed to update light constants"); + // Update event lights + let dt = ecs.fetch::().0; + self.event_lights.drain_filter(|el| { + el.timeout -= dt; + el.timeout <= 0.0 + }); + // Update shadow constants let mut shadows = ( &scene_data.state.ecs().read_storage::(), diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 68aed3c937..ddc9595ff1 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -53,7 +53,13 @@ impl ParticleMgr { match outcome { Outcome::Explosion { pos, power } => { - for _ in 0..64 { + for _ in 0..150 { + self.particles.push(Particles { + alive_until: now + Duration::from_millis(250), + instance: ParticleInstance::new(time, rng.gen(), ParticleMode::Shrapnel, *pos), + }); + } + for _ in 0..200 { self.particles.push(Particles { alive_until: now + Duration::from_secs(4), instance: ParticleInstance::new(time, rng.gen(), ParticleMode::CampfireSmoke, *pos + Vec2::::zero().map(|_| rng.gen_range(-1.0, 1.0) * power)), diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index a6a417c9f3..15570db133 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -1033,7 +1033,7 @@ impl PlayState for SessionState { .read_resource::>() .emit_now(sfx_event_item); } - self.scene.particle_mgr_mut().handle_outcome(&outcome, &scene_data); + self.scene.handle_outcome(&outcome, &scene_data); } } }