mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Particles for lifesteal beam. Changed how frontend recognized beams.
This commit is contained in:
parent
18edc1092b
commit
c6a222340e
@ -8,4 +8,5 @@ HealingBeam(
|
|||||||
max_angle: 1.0,
|
max_angle: 1.0,
|
||||||
lifesteal_eff: 0.0,
|
lifesteal_eff: 0.0,
|
||||||
energy_cost: 50,
|
energy_cost: 50,
|
||||||
|
specifier: HealingBeam,
|
||||||
)
|
)
|
@ -10,4 +10,5 @@ BasicBeam(
|
|||||||
energy_regen: 25,
|
energy_regen: 25,
|
||||||
energy_drain: 0,
|
energy_drain: 0,
|
||||||
orientation_behavior: Normal,
|
orientation_behavior: Normal,
|
||||||
|
specifier: LifestealBeam
|
||||||
)
|
)
|
@ -10,4 +10,5 @@ BasicBeam(
|
|||||||
energy_regen: 0,
|
energy_regen: 0,
|
||||||
energy_drain: 350,
|
energy_drain: 350,
|
||||||
orientation_behavior: Normal,
|
orientation_behavior: Normal,
|
||||||
|
specifier: Flamethrower,
|
||||||
)
|
)
|
@ -10,4 +10,5 @@ BasicBeam(
|
|||||||
energy_regen: 0,
|
energy_regen: 0,
|
||||||
energy_drain: 350,
|
energy_drain: 350,
|
||||||
orientation_behavior: Normal,
|
orientation_behavior: Normal,
|
||||||
|
specifier: Flamethrower,
|
||||||
)
|
)
|
||||||
|
@ -12,4 +12,5 @@ BasicBeam(
|
|||||||
//energy_cost: 50,
|
//energy_cost: 50,
|
||||||
energy_drain: 0,
|
energy_drain: 0,
|
||||||
orientation_behavior: Normal,
|
orientation_behavior: Normal,
|
||||||
|
specifier: HealingBeam,
|
||||||
)
|
)
|
@ -10,4 +10,5 @@ BasicBeam(
|
|||||||
energy_regen: 0,
|
energy_regen: 0,
|
||||||
energy_drain: 0,
|
energy_drain: 0,
|
||||||
orientation_behavior: Normal,
|
orientation_behavior: Normal,
|
||||||
|
specifier: Flamethrower,
|
||||||
)
|
)
|
@ -10,4 +10,5 @@ BasicBeam(
|
|||||||
energy_regen: 0,
|
energy_regen: 0,
|
||||||
energy_drain: 0,
|
energy_drain: 0,
|
||||||
orientation_behavior: Turret,
|
orientation_behavior: Turret,
|
||||||
|
specifier: Flamethrower,
|
||||||
)
|
)
|
@ -60,6 +60,7 @@ const int FIRE_BOWL = 18;
|
|||||||
const int SNOW = 19;
|
const int SNOW = 19;
|
||||||
const int EXPLOSION = 20;
|
const int EXPLOSION = 20;
|
||||||
const int ICE = 21;
|
const int ICE = 21;
|
||||||
|
const int LIFESTEAL_BEAM = 22;
|
||||||
|
|
||||||
// meters per second squared (acceleration)
|
// meters per second squared (acceleration)
|
||||||
const float earth_gravity = 9.807;
|
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*/),
|
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)
|
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) {
|
} else if (inst_mode == ENERGY_NATURE) {
|
||||||
f_reflect = 0.0;
|
f_reflect = 0.0;
|
||||||
attr = Attr(
|
attr = Attr(
|
||||||
|
@ -2,8 +2,8 @@ use crate::{
|
|||||||
assets::{self, Asset},
|
assets::{self, Asset},
|
||||||
combat,
|
combat,
|
||||||
comp::{
|
comp::{
|
||||||
aura, inventory::item::tool::ToolKind, projectile::ProjectileConstructor, skills, Body,
|
aura, beam, inventory::item::tool::ToolKind, projectile::ProjectileConstructor, skills,
|
||||||
CharacterState, EnergySource, Gravity, LightEmitter, StateUpdate,
|
Body, CharacterState, EnergySource, Gravity, LightEmitter, StateUpdate,
|
||||||
},
|
},
|
||||||
states::{
|
states::{
|
||||||
behavior::JoinData,
|
behavior::JoinData,
|
||||||
@ -224,6 +224,7 @@ pub enum CharacterAbility {
|
|||||||
energy_regen: f32,
|
energy_regen: f32,
|
||||||
energy_drain: f32,
|
energy_drain: f32,
|
||||||
orientation_behavior: basic_beam::MovementBehavior,
|
orientation_behavior: basic_beam::MovementBehavior,
|
||||||
|
specifier: beam::FrontendSpecifier,
|
||||||
},
|
},
|
||||||
CastAura {
|
CastAura {
|
||||||
buildup_duration: f32,
|
buildup_duration: f32,
|
||||||
@ -243,6 +244,7 @@ pub enum CharacterAbility {
|
|||||||
range: f32,
|
range: f32,
|
||||||
max_angle: f32,
|
max_angle: f32,
|
||||||
energy_cost: f32,
|
energy_cost: f32,
|
||||||
|
specifier: beam::FrontendSpecifier,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1472,6 +1474,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
energy_regen,
|
energy_regen,
|
||||||
energy_drain,
|
energy_drain,
|
||||||
orientation_behavior,
|
orientation_behavior,
|
||||||
|
specifier,
|
||||||
} => CharacterState::BasicBeam(basic_beam::Data {
|
} => CharacterState::BasicBeam(basic_beam::Data {
|
||||||
static_data: basic_beam::StaticData {
|
static_data: basic_beam::StaticData {
|
||||||
buildup_duration: Duration::from_secs_f32(*buildup_duration),
|
buildup_duration: Duration::from_secs_f32(*buildup_duration),
|
||||||
@ -1486,6 +1489,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
energy_drain: *energy_drain,
|
energy_drain: *energy_drain,
|
||||||
ability_info,
|
ability_info,
|
||||||
orientation_behavior: *orientation_behavior,
|
orientation_behavior: *orientation_behavior,
|
||||||
|
specifier: *specifier,
|
||||||
},
|
},
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
stage_section: StageSection::Buildup,
|
stage_section: StageSection::Buildup,
|
||||||
@ -1520,6 +1524,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
range,
|
range,
|
||||||
max_angle,
|
max_angle,
|
||||||
energy_cost,
|
energy_cost,
|
||||||
|
specifier,
|
||||||
} => CharacterState::HealingBeam(healing_beam::Data {
|
} => CharacterState::HealingBeam(healing_beam::Data {
|
||||||
static_data: healing_beam::StaticData {
|
static_data: healing_beam::StaticData {
|
||||||
buildup_duration: Duration::from_secs_f32(*buildup_duration),
|
buildup_duration: Duration::from_secs_f32(*buildup_duration),
|
||||||
@ -1531,6 +1536,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
max_angle: *max_angle,
|
max_angle: *max_angle,
|
||||||
energy_cost: *energy_cost,
|
energy_cost: *energy_cost,
|
||||||
ability_info,
|
ability_info,
|
||||||
|
specifier: *specifier,
|
||||||
},
|
},
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
stage_section: StageSection::Buildup,
|
stage_section: StageSection::Buildup,
|
||||||
|
@ -11,6 +11,7 @@ pub struct Properties {
|
|||||||
pub speed: f32,
|
pub speed: f32,
|
||||||
pub duration: Duration,
|
pub duration: Duration,
|
||||||
pub owner: Option<Uid>,
|
pub owner: Option<Uid>,
|
||||||
|
pub specifier: FrontendSpecifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Separate components out for cheaper network syncing
|
// TODO: Separate components out for cheaper network syncing
|
||||||
@ -44,3 +45,10 @@ pub struct Beam {
|
|||||||
impl Component for Beam {
|
impl Component for Beam {
|
||||||
type Storage = IdvStorage<Self>;
|
type Storage = IdvStorage<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
pub enum FrontendSpecifier {
|
||||||
|
Flamethrower,
|
||||||
|
LifestealBeam,
|
||||||
|
HealingBeam,
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{comp, uid::Uid};
|
use crate::{comp, uid::Uid};
|
||||||
use comp::item::Reagent;
|
use comp::{beam, item::Reagent};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ pub enum Outcome {
|
|||||||
},
|
},
|
||||||
Beam {
|
Beam {
|
||||||
pos: Vec3<f32>,
|
pos: Vec3<f32>,
|
||||||
heal: bool,
|
specifier: beam::FrontendSpecifier,
|
||||||
},
|
},
|
||||||
ExpChange {
|
ExpChange {
|
||||||
uid: Uid,
|
uid: Uid,
|
||||||
|
@ -43,6 +43,8 @@ pub struct StaticData {
|
|||||||
pub orientation_behavior: MovementBehavior,
|
pub orientation_behavior: MovementBehavior,
|
||||||
/// What key is used to press ability
|
/// What key is used to press ability
|
||||||
pub ability_info: AbilityInfo,
|
pub ability_info: AbilityInfo,
|
||||||
|
/// Used to specify the beam to the frontend
|
||||||
|
pub specifier: beam::FrontendSpecifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -141,6 +143,7 @@ impl CharacterBehavior for Data {
|
|||||||
speed,
|
speed,
|
||||||
duration: self.static_data.beam_duration,
|
duration: self.static_data.beam_duration,
|
||||||
owner: Some(*data.uid),
|
owner: Some(*data.uid),
|
||||||
|
specifier: self.static_data.specifier,
|
||||||
};
|
};
|
||||||
// Gets offsets
|
// Gets offsets
|
||||||
let body_offsets = match data.body {
|
let body_offsets = match data.body {
|
||||||
|
@ -33,6 +33,8 @@ pub struct StaticData {
|
|||||||
pub energy_cost: f32,
|
pub energy_cost: f32,
|
||||||
/// What key is used to press ability
|
/// What key is used to press ability
|
||||||
pub ability_info: AbilityInfo,
|
pub ability_info: AbilityInfo,
|
||||||
|
/// Used to specify the beam to the frontend
|
||||||
|
pub specifier: beam::FrontendSpecifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -106,6 +108,7 @@ impl CharacterBehavior for Data {
|
|||||||
speed,
|
speed,
|
||||||
duration: self.static_data.beam_duration,
|
duration: self.static_data.beam_duration,
|
||||||
owner: Some(*data.uid),
|
owner: Some(*data.uid),
|
||||||
|
specifier: self.static_data.specifier,
|
||||||
};
|
};
|
||||||
// Gets offsets
|
// Gets offsets
|
||||||
let body_offsets = match data.body {
|
let body_offsets = match data.body {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use crate::{sys, Server, StateExt};
|
use crate::{sys, Server, StateExt};
|
||||||
use common::{
|
use common::{
|
||||||
character::CharacterId,
|
character::CharacterId,
|
||||||
combat,
|
|
||||||
comp::{
|
comp::{
|
||||||
self,
|
self,
|
||||||
aura::{Aura, AuraKind, AuraTarget},
|
aura::{Aura, AuraKind, AuraTarget},
|
||||||
@ -175,10 +174,7 @@ pub fn handle_beam(server: &mut Server, properties: beam::Properties, pos: Pos,
|
|||||||
let ecs = state.ecs();
|
let ecs = state.ecs();
|
||||||
ecs.write_resource::<Vec<Outcome>>().push(Outcome::Beam {
|
ecs.write_resource::<Vec<Outcome>>().push(Outcome::Beam {
|
||||||
pos: pos.0,
|
pos: pos.0,
|
||||||
heal: properties
|
specifier: properties.specifier,
|
||||||
.attack
|
|
||||||
.effects()
|
|
||||||
.any(|e| matches!(e.effect(), combat::CombatEffect::Heal(h) if *h > 0.0)),
|
|
||||||
});
|
});
|
||||||
state.create_beam(properties, pos, ori).build();
|
state.create_beam(properties, pos, ori).build();
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,7 @@ use client::Client;
|
|||||||
use common::{
|
use common::{
|
||||||
assets::{self, AssetExt, AssetHandle},
|
assets::{self, AssetExt, AssetHandle},
|
||||||
comp::{
|
comp::{
|
||||||
|
beam,
|
||||||
item::{ItemKind, Reagent, ToolKind},
|
item::{ItemKind, Reagent, ToolKind},
|
||||||
object, Body, CharacterAbilityType, InventoryUpdateEvent,
|
object, Body, CharacterAbilityType, InventoryUpdateEvent,
|
||||||
},
|
},
|
||||||
@ -353,14 +354,15 @@ impl SfxMgr {
|
|||||||
let file_ref = "voxygen.audio.sfx.character.level_up_sound_-_shorter_wind_up";
|
let file_ref = "voxygen.audio.sfx.character.level_up_sound_-_shorter_wind_up";
|
||||||
audio.play_sfx(file_ref, *pos, None);
|
audio.play_sfx(file_ref, *pos, None);
|
||||||
},
|
},
|
||||||
Outcome::Beam { pos, heal } => {
|
Outcome::Beam { pos, specifier } => match specifier {
|
||||||
if *heal {
|
beam::FrontendSpecifier::LifestealBeam | beam::FrontendSpecifier::HealingBeam => {
|
||||||
let file_ref = "voxygen.audio.sfx.abilities.staff_channeling";
|
let file_ref = "voxygen.audio.sfx.abilities.staff_channeling";
|
||||||
audio.play_sfx(file_ref, *pos, None);
|
audio.play_sfx(file_ref, *pos, None);
|
||||||
} else {
|
},
|
||||||
|
beam::FrontendSpecifier::Flamethrower => {
|
||||||
let file_ref = "voxygen.audio.sfx.abilities.flame_thrower";
|
let file_ref = "voxygen.audio.sfx.abilities.flame_thrower";
|
||||||
audio.play_sfx(file_ref, *pos, None);
|
audio.play_sfx(file_ref, *pos, None);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
Outcome::ExpChange { .. } => {},
|
Outcome::ExpChange { .. } => {},
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,7 @@ pub enum ParticleMode {
|
|||||||
Snow = 19,
|
Snow = 19,
|
||||||
Explosion = 20,
|
Explosion = 20,
|
||||||
Ice = 21,
|
Ice = 21,
|
||||||
|
LifestealBeam = 22,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParticleMode {
|
impl ParticleMode {
|
||||||
|
@ -8,8 +8,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
assets::{AssetExt, DotVoxAsset},
|
assets::{AssetExt, DotVoxAsset},
|
||||||
combat::CombatEffect,
|
comp::{beam, item::Reagent, object, BeamSegment, Body, CharacterState, Ori, Pos, Shockwave},
|
||||||
comp::{item::Reagent, object, BeamSegment, Body, CharacterState, Ori, Pos, Shockwave},
|
|
||||||
figure::Segment,
|
figure::Segment,
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
resources::DeltaTime,
|
resources::DeltaTime,
|
||||||
@ -401,77 +400,14 @@ impl ParticleMgr {
|
|||||||
.join()
|
.join()
|
||||||
.filter(|(_, _, b)| b.creation.map_or(true, |c| (c + dt as f64) >= time))
|
.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();
|
let range = beam.properties.speed * beam.properties.duration.as_secs_f32();
|
||||||
if beam
|
match beam.properties.specifier {
|
||||||
.properties
|
beam::FrontendSpecifier::Flamethrower => {
|
||||||
.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,
|
|
||||||
pos.0,
|
|
||||||
pos.0 + *ori.look_dir() * range,
|
|
||||||
));
|
|
||||||
/*
|
|
||||||
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 mut rng = thread_rng();
|
||||||
let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
|
let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
|
||||||
let m = Mat3::<f32>::rotation_from_to_3d(from, to);
|
let m = Mat3::<f32>::rotation_from_to_3d(from, to);
|
||||||
@ -482,23 +418,52 @@ impl ParticleMgr {
|
|||||||
2.0,
|
2.0,
|
||||||
));
|
));
|
||||||
self.particles.resize_with(
|
self.particles.resize_with(
|
||||||
self.particles.len()
|
self.particles.len() + 2 * usize::from(beam_tick_count),
|
||||||
+ 2 * usize::from(self.scheduler.heartbeats(Duration::from_millis(1))),
|
|
||||||
|| {
|
|| {
|
||||||
let phi: f32 = rng.gen_range(0.0..beam.properties.angle);
|
let phi: f32 = rng.gen_range(0.0..beam.properties.angle);
|
||||||
let theta: f32 = rng.gen_range(0.0..2.0 * PI);
|
let theta: f32 = rng.gen_range(0.0..2.0 * PI);
|
||||||
let offset_z =
|
let offset_z = Vec3::new(
|
||||||
Vec3::new(phi.sin() * theta.cos(), phi.sin() * theta.sin(), phi.cos());
|
phi.sin() * theta.cos(),
|
||||||
|
phi.sin() * theta.sin(),
|
||||||
|
phi.cos(),
|
||||||
|
);
|
||||||
let random_ori = offset_z * m * Vec3::new(-1.0, -1.0, 1.0);
|
let random_ori = offset_z * m * Vec3::new(-1.0, -1.0, 1.0);
|
||||||
Particle::new_directed(
|
Particle::new_directed(
|
||||||
beam.properties.duration,
|
beam.properties.duration,
|
||||||
time,
|
time,
|
||||||
ParticleMode::FlameThrower,
|
ParticleMode::FlameThrower,
|
||||||
pos.0, /* + random_ori */
|
pos.0,
|
||||||
pos.0 + random_ori * range,
|
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 + 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,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user