mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Lifesteal now works. Added particles to healing beam.
This commit is contained in:
parent
f20134d7ea
commit
921d224ef6
@ -48,6 +48,7 @@ const int LEAF = 9;
|
||||
const int FIREFLY = 10;
|
||||
const int BEE = 11;
|
||||
const int GROUND_SHOCKWAVE = 12;
|
||||
const int HEALING_BEAM = 13;
|
||||
|
||||
// meters per second squared (acceleration)
|
||||
const float earth_gravity = 9.807;
|
||||
@ -248,6 +249,13 @@ void main() {
|
||||
vec4(vec3(0.32 + (rand0 * 0.04), 0.22 + (rand1 * 0.03), 0.05 + (rand2 * 0.01)), 1),
|
||||
spin_in_axis(vec3(1,0,0),0)
|
||||
);
|
||||
} else if (inst_mode == HEALING_BEAM) {
|
||||
attr = Attr(
|
||||
vec3(rand0 * 0.2, rand1 * 0.2, rand2 * 0.2 + 1),
|
||||
1,
|
||||
vec4(vec3(0, 1, 0), 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5)
|
||||
);
|
||||
} else {
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
|
@ -11,6 +11,7 @@ use serde::{Deserialize, Serialize};
|
||||
use specs::{Component, FlaggedStorage};
|
||||
use specs_idvs::IdvStorage;
|
||||
use std::time::Duration;
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub enum CharacterAbilityType {
|
||||
@ -526,6 +527,7 @@ impl From<&CharacterAbility> for CharacterState {
|
||||
energy_regen,
|
||||
} => CharacterState::BasicBeam(basic_beam::Data {
|
||||
exhausted: false,
|
||||
particle_ori: None::<Vec3<f32>>,
|
||||
buildup_duration: *buildup_duration,
|
||||
cooldown_duration: Duration::from_millis(250),
|
||||
cooldown_duration_default: Duration::from_millis(250),
|
||||
|
@ -310,8 +310,8 @@ impl Tool {
|
||||
base_dps: (80.0 * self.base_power()) as u32,
|
||||
range: 25.0,
|
||||
max_angle: 1.0,
|
||||
lifesteal_eff: 0.2,
|
||||
energy_regen: 50,
|
||||
lifesteal_eff: 0.25,
|
||||
energy_regen: 120,
|
||||
},
|
||||
BasicMelee {
|
||||
energy_cost: 350,
|
||||
|
@ -5,11 +5,14 @@ use crate::{
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
/// Whether the attack can currently deal damage
|
||||
pub exhausted: bool,
|
||||
/// Used for particle stuffs
|
||||
pub particle_ori: Option<Vec3<f32>>,
|
||||
/// How long until state should deal damage or heal
|
||||
pub buildup_duration: Duration,
|
||||
/// How long until weapon can deal another tick of damage
|
||||
@ -46,6 +49,7 @@ impl CharacterBehavior for Data {
|
||||
// Build up
|
||||
update.character = CharacterState::BasicBeam(Data {
|
||||
exhausted: self.exhausted,
|
||||
particle_ori: Some(*data.inputs.look_dir),
|
||||
buildup_duration: self
|
||||
.buildup_duration
|
||||
.checked_sub(Duration::from_secs_f32(data.dt.0))
|
||||
@ -73,11 +77,12 @@ impl CharacterBehavior for Data {
|
||||
hit_count: 0,
|
||||
knockback: 0.0,
|
||||
is_melee: false,
|
||||
lifesteal_eff: 0.0,
|
||||
lifesteal_eff: self.lifesteal_eff,
|
||||
});
|
||||
|
||||
update.character = CharacterState::BasicBeam(Data {
|
||||
exhausted: true,
|
||||
particle_ori: Some(*data.inputs.look_dir),
|
||||
buildup_duration: self.buildup_duration,
|
||||
recover_duration: self.recover_duration,
|
||||
cooldown_duration: self.cooldown_duration_default,
|
||||
@ -89,18 +94,11 @@ impl CharacterBehavior for Data {
|
||||
lifesteal_eff: self.lifesteal_eff,
|
||||
energy_regen: self.energy_regen,
|
||||
});
|
||||
|
||||
// Grant energy and lifesteal on successful hit
|
||||
if let Some(attack) = data.attacking {
|
||||
if attack.applied && attack.hit_count > 0 {
|
||||
let energy = (self.energy_regen as f32 / ticks_per_sec) as i32;
|
||||
update.energy.change_by(energy, EnergySource::HitEnemy);
|
||||
}
|
||||
}
|
||||
} else if data.inputs.primary.is_pressed() && self.cooldown_duration != Duration::default() {
|
||||
// Cooldown until next tick of damage
|
||||
update.character = CharacterState::BasicBeam(Data {
|
||||
exhausted: self.exhausted,
|
||||
particle_ori: Some(*data.inputs.look_dir),
|
||||
buildup_duration: self.buildup_duration,
|
||||
cooldown_duration: self
|
||||
.cooldown_duration
|
||||
@ -118,6 +116,7 @@ impl CharacterBehavior for Data {
|
||||
} else if data.inputs.primary.is_pressed() {
|
||||
update.character = CharacterState::BasicBeam(Data {
|
||||
exhausted: false,
|
||||
particle_ori: Some(*data.inputs.look_dir),
|
||||
buildup_duration: self.buildup_duration,
|
||||
recover_duration: self.recover_duration,
|
||||
cooldown_duration: self.cooldown_duration_default,
|
||||
@ -129,10 +128,15 @@ impl CharacterBehavior for Data {
|
||||
lifesteal_eff: self.lifesteal_eff,
|
||||
energy_regen: self.energy_regen,
|
||||
});
|
||||
|
||||
// Grant energy on successful hit
|
||||
let energy = (self.energy_regen as f32 / ticks_per_sec) as i32;
|
||||
update.energy.change_by(energy, EnergySource::HitEnemy);
|
||||
} else if self.recover_duration != Duration::default() {
|
||||
// Recovery
|
||||
update.character = CharacterState::BasicBeam(Data {
|
||||
exhausted: self.exhausted,
|
||||
particle_ori: Some(*data.inputs.look_dir),
|
||||
buildup_duration: self.buildup_duration,
|
||||
cooldown_duration: self.cooldown_duration,
|
||||
cooldown_duration_default: self.cooldown_duration_default,
|
||||
|
@ -120,6 +120,9 @@ impl<'a> System<'a> for Sys {
|
||||
if same_group && (attack.base_heal > 0) {
|
||||
is_heal = true;
|
||||
}
|
||||
if !is_heal && !is_damage {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Weapon gives base damage
|
||||
let source = if is_heal {
|
||||
@ -129,8 +132,13 @@ impl<'a> System<'a> for Sys {
|
||||
} else {
|
||||
DamageSource::Energy
|
||||
};
|
||||
let healthchange = if is_heal {
|
||||
attack.base_heal as f32
|
||||
} else {
|
||||
-(attack.base_damage as f32)
|
||||
};
|
||||
let mut damage = Damage {
|
||||
healthchange: -(attack.base_damage as f32),
|
||||
healthchange,
|
||||
source,
|
||||
};
|
||||
|
||||
@ -150,7 +158,7 @@ impl<'a> System<'a> for Sys {
|
||||
cause,
|
||||
},
|
||||
});
|
||||
if attack.lifesteal_eff != 0.0 && is_damage {
|
||||
if attack.lifesteal_eff > 0.0 && is_damage {
|
||||
server_emitter.emit(ServerEvent::Damage {
|
||||
uid: *uid,
|
||||
change: HealthChange {
|
||||
|
@ -106,6 +106,7 @@ pub enum ParticleMode {
|
||||
Firefly = 10,
|
||||
Bee = 11,
|
||||
GroundShockwave = 12,
|
||||
HealingBeam = 13,
|
||||
}
|
||||
|
||||
impl ParticleMode {
|
||||
|
@ -112,6 +112,7 @@ impl ParticleMgr {
|
||||
// add new Particle
|
||||
self.maintain_body_particles(scene_data);
|
||||
self.maintain_boost_particles(scene_data);
|
||||
self.maintain_beam_particles(scene_data);
|
||||
self.maintain_block_particles(scene_data, terrain);
|
||||
self.maintain_shockwave_particles(scene_data);
|
||||
} else {
|
||||
@ -300,6 +301,39 @@ impl ParticleMgr {
|
||||
}
|
||||
}
|
||||
|
||||
fn maintain_beam_particles(&mut self, scene_data: &SceneData) {
|
||||
let state = scene_data.state;
|
||||
let ecs = state.ecs();
|
||||
let time = state.get_time();
|
||||
|
||||
for (pos, ori, character_state) in (
|
||||
&ecs.read_storage::<Pos>(),
|
||||
&ecs.read_storage::<Ori>(),
|
||||
&ecs.read_storage::<CharacterState>(),
|
||||
)
|
||||
.join()
|
||||
{
|
||||
if let CharacterState::BasicBeam(b) = character_state {
|
||||
if b.buildup_duration == Duration::default() {
|
||||
let scale = 5.0;
|
||||
let particle_ori = b.particle_ori.unwrap_or(*ori.vec());
|
||||
for _ in 0..self.scheduler.heartbeats(Duration::from_millis(10)) {
|
||||
for d in 0..((b.range * scale) as i32) {
|
||||
self.particles.push(
|
||||
Particle::new(
|
||||
Duration::from_millis(10),
|
||||
time,
|
||||
ParticleMode::HealingBeam,
|
||||
pos.0 + particle_ori * (d as f32) / scale,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::same_item_push)] // TODO: Pending review in #587
|
||||
fn maintain_block_particles(
|
||||
&mut self,
|
||||
|
Loading…
Reference in New Issue
Block a user