diff --git a/assets/common/abilities/staff/flamethrower.ron b/assets/common/abilities/staff/flamethrower.ron index 4d886dbff5..f451b9347e 100644 --- a/assets/common/abilities/staff/flamethrower.ron +++ b/assets/common/abilities/staff/flamethrower.ron @@ -1,15 +1,15 @@ BasicBeam( buildup_duration: 0.25, recover_duration: 0.25, - beam_duration: 0.5, + beam_duration: 1.5, base_hps: 0, base_dps: 150, tick_rate: 3.0, range: 15.0, - max_angle: 22.5, + max_angle: 10.0, lifesteal_eff: 0.0, energy_regen: 0, energy_cost: 1, energy_drain: 350, orientation_behavior: Normal, -) \ No newline at end of file +) diff --git a/assets/voxygen/shaders/particle-vert.glsl b/assets/voxygen/shaders/particle-vert.glsl index e7a9b75237..70389f8599 100644 --- a/assets/voxygen/shaders/particle-vert.glsl +++ b/assets/voxygen/shaders/particle-vert.glsl @@ -86,6 +86,18 @@ float linear_scale(float factor) { return lifetime * factor; } +float percent() { + return lifetime / inst_lifespan; +} + +float slow_end(float factor) { + return (1 + factor) * percent() / (percent() + factor); +} + +float slow_start(float factor) { + return 1-(1 + factor) * (1-percent()) / ((1-percent()) + factor); +} + float start_end(float from, float to) { return mix(from, to, lifetime / inst_lifespan); } @@ -124,10 +136,10 @@ vec3 spiral_motion(vec3 line, float radius, float time_function) { vec3 axis2 = perp_axis1(line); vec3 axis3 = perp_axis2(line, axis2); - return line * time_function + vec3( - radius * cos(10 * time_function - inst_time) * axis2.x + radius * sin(10 * time_function - inst_time) * axis3.x, - radius * cos(10 * time_function - inst_time) * axis2.y + radius * sin(10 * time_function - inst_time) * axis3.y, - radius * cos(10 * time_function - inst_time) * axis2.z + radius * sin(10 * time_function - inst_time) * axis3.z); + return vec3( + radius * cos(time_function) * axis2.x + radius * sin(time_function) * axis3.x, + radius * cos(time_function) * axis2.y + radius * sin(time_function) * axis3.y, + radius * cos(time_function) * axis2.z + radius * sin(time_function) * axis3.z); } void main() { @@ -161,7 +173,7 @@ void main() { f_reflect = 0.0; // Fire doesn't reflect light, it emits it attr = Attr( linear_motion( - vec3(normalize(vec2(rand0, rand1)) * 0.25, 0.3), + vec3(0.0), vec3(rand2 * 0.1, rand3 * 0.1, 2.0 + rand4 * 1.0) ), vec3(1.0), @@ -317,26 +329,25 @@ void main() { } else if (inst_mode == ENERGY_NATURE) { f_reflect = 0.0; attr = Attr( - linear_motion( - vec3(rand0 * 1, rand1 * 1, rand2 * 1), - vec3(rand3 * 2, rand4 * 2, rand5 * 2) - ), - vec3(0.8), + inst_dir * slow_end(0.03) + spiral_motion(vec3(rand1, rand2, rand3), + 0.2 * (rand4 + 1.3) * slow_end(0.02), percent() * 3 * (rand4 + 4.0) + rand0), + vec3(1.0), vec4(vec3(0, 2.5, 1.5 + rand7 * 0.7), start_end(1.0, 0.0)), spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3) ); } else if (inst_mode == FLAMETHROWER) { f_reflect = 0.0; // Fire doesn't reflect light, it emits it attr = Attr( - (inst_dir * lifetime / inst_lifespan) + vec3(rand0, rand1, rand2) * (lifetime * 5 + 0.25), - vec3(0.6 + rand3 * 0.5 + lifetime / inst_lifespan * 5), - vec4(3, 1.6 + rand5 * 0.3 - 0.4 * lifetime / inst_lifespan, 0.2, start_end(1.0, 0.0) /*0.8 - 0.6 * lifetime / inst_lifespan*/), - spin_in_axis(vec3(rand6, rand7, rand8), lifetime / inst_lifespan * 10 + 3 * rand9) + inst_dir * ((rand0+1.0)/2 + 0.5) * slow_end(0.2) + /*0.4 * vec3(rand0, + rand1, rand2) * slow_end(0.1)*/ + 0.1 * grav_vel(earth_gravity), + vec3((3 * (1 - slow_start(0.1)))), + vec4(3, 1.6 + rand5 * 0.3 - 0.4 * percent(), 0.2, start_end(1.0, 0.0)), + spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9) ); } else if (inst_mode == FIRE_SHOCKWAVE) { f_reflect = 0.0; // Fire doesn't reflect light, it emits it attr = Attr( - vec3(rand0, rand1, lifetime * 10 + rand2), + vec3(rand0, rand1, lifetime * 1 + rand2), vec3(1.6 + rand3 * 1.5 + 10 * (lifetime + inst_lifespan)), vec4(3, 1.6 + rand7 * 0.3 - 5 * inst_lifespan + 2 * lifetime, 0.2, start_end(1.0, 0.0) /*0.8 - 3.5 * inst_lifespan*/), spin_in_axis(vec3(rand3, rand4, rand5), rand6) diff --git a/voxygen/src/render/pipelines/particle.rs b/voxygen/src/render/pipelines/particle.rs index 224587f429..09e1218db1 100644 --- a/voxygen/src/render/pipelines/particle.rs +++ b/voxygen/src/render/pipelines/particle.rs @@ -139,7 +139,7 @@ impl Instance { } } - pub fn new_beam( + pub fn new_directed( inst_time: f64, lifespan: f32, inst_mode: ParticleMode, diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 83d8ceb793..3498b4c1a9 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -66,14 +66,15 @@ impl ParticleMgr { self.particles.resize_with( self.particles.len() + (200.0 * power.abs()) as usize, || { - Particle::new( - Duration::from_secs(1), + Particle::new_directed( + Duration::from_secs_f32(rng.gen_range(1.0, 8.0)), time, ParticleMode::EnergyNature, + *pos, *pos + Vec3::::zero() .map(|_| rng.gen_range(-1.0..1.0)) .normalized() - * *radius, + * rng.gen_range(1.0, radius) ) }, ); @@ -81,10 +82,11 @@ impl ParticleMgr { self.particles.resize_with( self.particles.len() + (200.0 * power.abs()) as usize, || { - Particle::new( - Duration::from_secs(1), + Particle::new_directed( + Duration::from_secs(2), time, - ParticleMode::CampfireFire, + ParticleMode::FlameThrower, + *pos, *pos + Vec3::::zero() .map(|_| rng.gen_range(-1.0..1.0)) .normalized() @@ -295,7 +297,7 @@ impl ParticleMgr { Particle::new( Duration::from_millis(250), time, - ParticleMode::EnergyNature, + ParticleMode::CampfireSmoke, pos.0, ) }, @@ -376,6 +378,7 @@ impl ParticleMgr { .join() .filter(|(_, _, b)| b.creation.map_or(true, |c| (c + dt as f64) >= time)) { +// let range = beam.properties.speed * beam.properties.duration.as_secs_f32(); if beam .properties @@ -393,6 +396,58 @@ impl ParticleMgr { pos.0, pos.0 + *ori.look_dir() * range, )); +// + if let CharacterState::BasicBeam(b) = character_state { + let particle_ori = b.particle_ori.unwrap_or_else(|| ori.look_vec()); + if b.stage_section == StageSection::Cast { + if b.static_data.base_hps > 0.0 { + // Emit a light when using healing + lights.push(Light::new(pos.0 + b.offset, Rgb::new(0.1, 1.0, 0.15), 1.0)); + for i in 0..self.scheduler.heartbeats(Duration::from_millis(1)) { + self.particles.push(Particle::new_directed( + b.static_data.beam_duration, + time + i as f64 / 1000.0, + ParticleMode::HealingBeam, + pos.0 + particle_ori * 0.5 + b.offset, + pos.0 + particle_ori * b.static_data.range + b.offset, + )); + } + } else { + let mut rng = thread_rng(); + let (from, to) = (Vec3::::unit_z(), particle_ori); + let m = Mat3::::rotation_from_to_3d(from, to); + // Emit a light when using flames + lights.push(Light::new( + pos.0 + b.offset, + Rgb::new(1.0, 0.25, 0.05).map(|e| e * rng.gen_range(0.8..1.2)), + 2.0, + )); + self.particles.resize_with( + self.particles.len() + + 2 * usize::from( + self.scheduler.heartbeats(Duration::from_millis(1)), + ), + || { + let phi: f32 = + rng.gen_range(0.0..b.static_data.max_angle.to_radians()); + let theta: f32 = rng.gen_range(0.0..2.0 * PI); + let offset_z = Vec3::new( + phi.sin() * theta.cos(), + phi.sin() * theta.sin(), + phi.cos(), + ); + let random_ori = offset_z * m * Vec3::new(-1.0, -1.0, 1.0); + Particle::new_directed( + b.static_data.beam_duration, + time, + ParticleMode::FlameThrower, + pos.0 + random_ori * 0.5 + b.offset, + pos.0 + random_ori * b.static_data.range + b.offset, + ) + }, + ); + } +// } } else { let mut rng = thread_rng(); @@ -612,25 +667,27 @@ impl ParticleMgr { let position_snapped = ((position / scale).floor() + 0.5) * scale; - self.particles.push(Particle::new( - Duration::from_millis(250), + self.particles.push(Particle::new_directed( + Duration::from_secs(2), time, - ParticleMode::GroundShockwave, + ParticleMode::FlameThrower, position_snapped, + Vec3::new(0.0, 0.0, 10.0) + position_snapped, )); } } else { - for d in 0..3 * distance as i32 { + for d in 0..8 * distance as i32 { let arc_position = theta - radians / 2.0 + dtheta * d as f32 / 3.0; - let position = pos.0 - + distance * Vec3::new(arc_position.cos(), arc_position.sin(), 0.0); + let diff = distance * Vec3::new(arc_position.cos(), arc_position.sin(), 0.0); + let position = pos.0 + diff; - self.particles.push(Particle::new( - Duration::from_secs_f32(distance / 50.0), + self.particles.push(Particle::new_directed( + Duration::from_millis(500), time, - ParticleMode::FireShockwave, - position, + ParticleMode::FlameThrower, + pos.0 + diff * 0.9, + Vec3::new(0.0, 0.0, 2.0) + position, )); } } @@ -805,7 +862,7 @@ impl Particle { } } - fn new_beam( + fn new_directed( lifespan: Duration, time: f64, mode: ParticleMode, @@ -814,7 +871,13 @@ impl Particle { ) -> Self { Particle { alive_until: time + lifespan.as_secs_f64(), - instance: ParticleInstance::new_beam(time, lifespan.as_secs_f32(), mode, pos1, pos2), + instance: ParticleInstance::new_directed( + time, + lifespan.as_secs_f32(), + mode, + pos1, + pos2, + ), } } }