Particles for lifesteal beam. Changed how frontend recognized beams.

This commit is contained in:
Sam 2021-03-02 23:56:09 -05:00
parent 18edc1092b
commit c6a222340e
17 changed files with 109 additions and 109 deletions

View File

@ -8,4 +8,5 @@ HealingBeam(
max_angle: 1.0,
lifesteal_eff: 0.0,
energy_cost: 50,
specifier: HealingBeam,
)

View File

@ -10,4 +10,5 @@ BasicBeam(
energy_regen: 25,
energy_drain: 0,
orientation_behavior: Normal,
specifier: LifestealBeam
)

View File

@ -10,4 +10,5 @@ BasicBeam(
energy_regen: 0,
energy_drain: 350,
orientation_behavior: Normal,
specifier: Flamethrower,
)

View File

@ -10,4 +10,5 @@ BasicBeam(
energy_regen: 0,
energy_drain: 350,
orientation_behavior: Normal,
specifier: Flamethrower,
)

View File

@ -12,4 +12,5 @@ BasicBeam(
//energy_cost: 50,
energy_drain: 0,
orientation_behavior: Normal,
specifier: HealingBeam,
)

View File

@ -10,4 +10,5 @@ BasicBeam(
energy_regen: 0,
energy_drain: 0,
orientation_behavior: Normal,
specifier: Flamethrower,
)

View File

@ -10,4 +10,5 @@ BasicBeam(
energy_regen: 0,
energy_drain: 0,
orientation_behavior: Turret,
specifier: Flamethrower,
)

View File

@ -60,6 +60,7 @@ const int FIRE_BOWL = 18;
const int SNOW = 19;
const int EXPLOSION = 20;
const int ICE = 21;
const int LIFESTEAL_BEAM = 22;
// meters per second squared (acceleration)
const float earth_gravity = 9.807;
@ -340,6 +341,14 @@ void main() {
vec4(vec3(0.4, 1.6 + 0.3 * sin(tick.x * 10 - lifetime * 3 + 4), 1.0 + 0.15 * sin(tick.x * 5 - lifetime * 5)), 1 /*0.3*/),
spin_in_axis(inst_dir, tick.z)
);
} else if (inst_mode == LIFESTEAL_BEAM) {
f_reflect = 0.01;
attr = Attr(
spiral_motion(inst_dir, 0.3 * (floor(2 * rand0 + 0.5) - 0.5) * min(linear_scale(10), 1), lifetime / inst_lifespan, 10.0, inst_time),
vec3((1.7 - 0.7 * abs(floor(2 * rand0 - 0.5) + 0.5)) * (1.5 + 0.5 * sin(tick.x * 10 - lifetime * 4))),
vec4(vec3(1.0 + 0.3 * sin(tick.x + lifetime * 5), 1.25 + 0.2 * sin(tick.x * 10 - lifetime * 3 + 4), 0.7), 1 /*0.3*/),
spin_in_axis(inst_dir, tick.z)
);
} else if (inst_mode == ENERGY_NATURE) {
f_reflect = 0.0;
attr = Attr(

View File

@ -2,8 +2,8 @@ use crate::{
assets::{self, Asset},
combat,
comp::{
aura, inventory::item::tool::ToolKind, projectile::ProjectileConstructor, skills, Body,
CharacterState, EnergySource, Gravity, LightEmitter, StateUpdate,
aura, beam, inventory::item::tool::ToolKind, projectile::ProjectileConstructor, skills,
Body, CharacterState, EnergySource, Gravity, LightEmitter, StateUpdate,
},
states::{
behavior::JoinData,
@ -224,6 +224,7 @@ pub enum CharacterAbility {
energy_regen: f32,
energy_drain: f32,
orientation_behavior: basic_beam::MovementBehavior,
specifier: beam::FrontendSpecifier,
},
CastAura {
buildup_duration: f32,
@ -243,6 +244,7 @@ pub enum CharacterAbility {
range: f32,
max_angle: f32,
energy_cost: f32,
specifier: beam::FrontendSpecifier,
},
}
@ -1472,6 +1474,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
energy_regen,
energy_drain,
orientation_behavior,
specifier,
} => CharacterState::BasicBeam(basic_beam::Data {
static_data: basic_beam::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -1486,6 +1489,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
energy_drain: *energy_drain,
ability_info,
orientation_behavior: *orientation_behavior,
specifier: *specifier,
},
timer: Duration::default(),
stage_section: StageSection::Buildup,
@ -1520,6 +1524,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
range,
max_angle,
energy_cost,
specifier,
} => CharacterState::HealingBeam(healing_beam::Data {
static_data: healing_beam::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -1531,6 +1536,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
max_angle: *max_angle,
energy_cost: *energy_cost,
ability_info,
specifier: *specifier,
},
timer: Duration::default(),
stage_section: StageSection::Buildup,

View File

@ -11,6 +11,7 @@ pub struct Properties {
pub speed: f32,
pub duration: Duration,
pub owner: Option<Uid>,
pub specifier: FrontendSpecifier,
}
// TODO: Separate components out for cheaper network syncing
@ -44,3 +45,10 @@ pub struct Beam {
impl Component for Beam {
type Storage = IdvStorage<Self>;
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum FrontendSpecifier {
Flamethrower,
LifestealBeam,
HealingBeam,
}

View File

@ -1,5 +1,5 @@
use crate::{comp, uid::Uid};
use comp::item::Reagent;
use comp::{beam, item::Reagent};
use serde::{Deserialize, Serialize};
use vek::*;
@ -24,7 +24,7 @@ pub enum Outcome {
},
Beam {
pos: Vec3<f32>,
heal: bool,
specifier: beam::FrontendSpecifier,
},
ExpChange {
uid: Uid,

View File

@ -43,6 +43,8 @@ pub struct StaticData {
pub orientation_behavior: MovementBehavior,
/// What key is used to press ability
pub ability_info: AbilityInfo,
/// Used to specify the beam to the frontend
pub specifier: beam::FrontendSpecifier,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -141,6 +143,7 @@ impl CharacterBehavior for Data {
speed,
duration: self.static_data.beam_duration,
owner: Some(*data.uid),
specifier: self.static_data.specifier,
};
// Gets offsets
let body_offsets = match data.body {

View File

@ -33,6 +33,8 @@ pub struct StaticData {
pub energy_cost: f32,
/// What key is used to press ability
pub ability_info: AbilityInfo,
/// Used to specify the beam to the frontend
pub specifier: beam::FrontendSpecifier,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -106,6 +108,7 @@ impl CharacterBehavior for Data {
speed,
duration: self.static_data.beam_duration,
owner: Some(*data.uid),
specifier: self.static_data.specifier,
};
// Gets offsets
let body_offsets = match data.body {

View File

@ -1,7 +1,6 @@
use crate::{sys, Server, StateExt};
use common::{
character::CharacterId,
combat,
comp::{
self,
aura::{Aura, AuraKind, AuraTarget},
@ -175,10 +174,7 @@ pub fn handle_beam(server: &mut Server, properties: beam::Properties, pos: Pos,
let ecs = state.ecs();
ecs.write_resource::<Vec<Outcome>>().push(Outcome::Beam {
pos: pos.0,
heal: properties
.attack
.effects()
.any(|e| matches!(e.effect(), combat::CombatEffect::Heal(h) if *h > 0.0)),
specifier: properties.specifier,
});
state.create_beam(properties, pos, ori).build();
}

View File

@ -91,6 +91,7 @@ use client::Client;
use common::{
assets::{self, AssetExt, AssetHandle},
comp::{
beam,
item::{ItemKind, Reagent, ToolKind},
object, Body, CharacterAbilityType, InventoryUpdateEvent,
},
@ -353,14 +354,15 @@ impl SfxMgr {
let file_ref = "voxygen.audio.sfx.character.level_up_sound_-_shorter_wind_up";
audio.play_sfx(file_ref, *pos, None);
},
Outcome::Beam { pos, heal } => {
if *heal {
Outcome::Beam { pos, specifier } => match specifier {
beam::FrontendSpecifier::LifestealBeam | beam::FrontendSpecifier::HealingBeam => {
let file_ref = "voxygen.audio.sfx.abilities.staff_channeling";
audio.play_sfx(file_ref, *pos, None);
} else {
},
beam::FrontendSpecifier::Flamethrower => {
let file_ref = "voxygen.audio.sfx.abilities.flame_thrower";
audio.play_sfx(file_ref, *pos, None);
}
},
},
Outcome::ExpChange { .. } => {},
}

View File

@ -118,6 +118,7 @@ pub enum ParticleMode {
Snow = 19,
Explosion = 20,
Ice = 21,
LifestealBeam = 22,
}
impl ParticleMode {

View File

@ -8,8 +8,7 @@ use crate::{
};
use common::{
assets::{AssetExt, DotVoxAsset},
combat::CombatEffect,
comp::{item::Reagent, object, BeamSegment, Body, CharacterState, Ori, Pos, Shockwave},
comp::{beam, item::Reagent, object, BeamSegment, Body, CharacterState, Ori, Pos, Shockwave},
figure::Segment,
outcome::Outcome,
resources::DeltaTime,
@ -401,104 +400,70 @@ impl ParticleMgr {
.join()
.filter(|(_, _, b)| b.creation.map_or(true, |c| (c + dt as f64) >= time))
{
//
// TODO: Handle this less hackily. Done this way as beam segments are created
// every server tick, which is approximately 33 ms. Heartbeat scheduler used to
// account for clients with less than 30 fps because they start the creation
// time when the segments are received and could receive 2 at once
let beam_tick_count = 33.max(self.scheduler.heartbeats(Duration::from_millis(1)));
let range = beam.properties.speed * beam.properties.duration.as_secs_f32();
if beam
.properties
.attack
.effects()
.any(|e| matches!(e.effect(), CombatEffect::Heal(h) if *h > 0.0))
{
// Emit a light when using healing
lights.push(Light::new(pos.0, 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(
beam.properties.duration,
time + i as f64 / 1000.0,
ParticleMode::HealingBeam,
match beam.properties.specifier {
beam::FrontendSpecifier::Flamethrower => {
let mut rng = thread_rng();
let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
let m = Mat3::<f32>::rotation_from_to_3d(from, to);
// Emit a light when using flames
lights.push(Light::new(
pos.0,
pos.0 + *ori.look_dir() * range,
Rgb::new(1.0, 0.25, 0.05).map(|e| e * rng.gen_range(0.8..1.2)),
2.0,
));
/*
if let CharacterState::BasicBeam(b) = character_state {
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::<f32>::unit_z(), particle_ori);
let m = Mat3::<f32>::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();
let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
let m = Mat3::<f32>::rotation_from_to_3d(from, to);
// Emit a light when using flames
lights.push(Light::new(
pos.0,
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..beam.properties.angle);
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(
self.particles.resize_with(
self.particles.len() + 2 * usize::from(beam_tick_count),
|| {
let phi: f32 = rng.gen_range(0.0..beam.properties.angle);
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(
beam.properties.duration,
time,
ParticleMode::FlameThrower,
pos.0,
pos.0 + random_ori * range,
)
},
);
},
beam::FrontendSpecifier::HealingBeam => {
// Emit a light when using healing
lights.push(Light::new(pos.0, Rgb::new(0.1, 1.0, 0.15), 1.0));
for i in 0..beam_tick_count {
self.particles.push(Particle::new_directed(
beam.properties.duration,
time,
ParticleMode::FlameThrower,
pos.0, /* + random_ori */
pos.0 + random_ori * range,
)
},
);
time + i as f64 / 1000.0,
ParticleMode::HealingBeam,
pos.0,
pos.0 + *ori.look_dir() * range,
));
}
},
beam::FrontendSpecifier::LifestealBeam => {
// Emit a light when using lifesteal beam
lights.push(Light::new(pos.0, Rgb::new(0.8, 1.0, 0.5), 1.0));
for i in 0..beam_tick_count {
self.particles.push(Particle::new_directed(
beam.properties.duration,
time + i as f64 / 1000.0,
ParticleMode::LifestealBeam,
pos.0,
pos.0 + *ori.look_dir() * range,
));
}
},
}
}
}