Fixed shockwaves hitting entities multiple times. Explosions can now regen energy. Staff M1 now has particles instead of using bomb particles.

This commit is contained in:
Sam 2020-10-07 19:32:30 -05:00
parent 7ef73f5981
commit 1c21362bc3
14 changed files with 92 additions and 22 deletions

View File

@ -393,6 +393,7 @@ impl Tool {
max_heal: (140.0 * self.base_power()) as u32,
min_heal: (50.0 * self.base_power()) as u32,
terrain_destruction_power: 0.0,
energy_regen: 0,
}),
projectile::Effect::Vanish,
],
@ -404,6 +405,7 @@ impl Tool {
max_heal: (140.0 * self.base_power()) as u32,
min_heal: (50.0 * self.base_power()) as u32,
terrain_destruction_power: 0.0,
energy_regen: 0,
}),
projectile::Effect::Vanish,
],
@ -431,10 +433,11 @@ impl Tool {
projectile::Effect::Explode(Explosion {
radius: 4.0,
max_damage: (100.0 * self.base_power()) as u32,
min_damage: (40.0 * self.base_power()) as u32,
min_damage: (10.0 * self.base_power()) as u32,
max_heal: 0,
min_heal: 0,
terrain_destruction_power: 0.0,
energy_regen: 50,
}),
projectile::Effect::Vanish,
],
@ -442,10 +445,11 @@ impl Tool {
projectile::Effect::Explode(Explosion {
radius: 4.0,
max_damage: (100.0 * self.base_power()) as u32,
min_damage: (40.0 * self.base_power()) as u32,
min_damage: (10.0 * self.base_power()) as u32,
max_heal: 0,
min_heal: 0,
terrain_destruction_power: 0.0,
energy_regen: 50,
}),
projectile::Effect::Vanish,
],
@ -466,7 +470,7 @@ impl Tool {
recover_duration: Duration::from_millis(250),
beam_duration: Duration::from_millis(500),
base_hps: 0,
base_dps: (100.0 * self.base_power()) as u32,
base_dps: (200.0 * self.base_power()) as u32,
tick_rate: 2.0,
range: 15.0,
max_angle: 22.5,
@ -480,8 +484,8 @@ impl Tool {
energy_cost: 0,
buildup_duration: Duration::from_millis(500),
recover_duration: Duration::from_millis(300),
damage: 200,
knockback: 12.0,
damage: (200.0 * self.base_power()) as u32,
knockback: 20.0,
shockwave_angle: 360.0,
shockwave_speed: 20.0,
shockwave_duration: Duration::from_millis(500),

View File

@ -54,7 +54,7 @@ pub use misc::Object;
pub use phys::{Collider, ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel};
pub use player::{Player, MAX_MOUNT_RANGE_SQR};
pub use projectile::{Explosion, Projectile};
pub use shockwave::Shockwave;
pub use shockwave::{Shockwave, ShockwaveHitEntities};
pub use skills::{Skill, SkillGroup, SkillGroupType, SkillSet};
pub use stats::{Exp, HealthChange, HealthSource, Level, Stats};
pub use visual::{LightAnimation, LightEmitter};

View File

@ -23,6 +23,7 @@ pub struct Explosion {
pub max_heal: u32,
pub min_heal: u32,
pub terrain_destruction_power: f32,
pub energy_regen: u32,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]

View File

@ -34,3 +34,12 @@ impl std::ops::Deref for Shockwave {
fn deref(&self) -> &Properties { &self.properties }
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ShockwaveHitEntities {
pub hit_entities: Vec<Uid>,
}
impl Component for ShockwaveHitEntities {
type Storage = IdvStorage<Self>;
}

View File

@ -14,6 +14,7 @@ pub enum Outcome {
pos: Vec3<f32>,
power: f32,
radius: f32,
is_attack: bool,
reagent: Option<Reagent>, // How can we better define this?
},
ProjectileShot {

View File

@ -127,6 +127,7 @@ impl State {
ecs.register::<comp::Object>();
ecs.register::<comp::Group>();
ecs.register::<comp::Shockwave>();
ecs.register::<comp::ShockwaveHitEntities>();
ecs.register::<comp::BeamSegment>();
// Register components send from clients -> server

View File

@ -1,7 +1,7 @@
use crate::{
comp::{
BeamSegment, Collider, Gravity, Mass, Mounting, Ori, PhysicsState, Pos, Projectile, Scale,
Sticky, Vel,
Shockwave, Sticky, Vel,
},
event::{EventBus, ServerEvent},
metrics::SysMetrics,
@ -66,6 +66,7 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, Mounting>,
ReadStorage<'a, Projectile>,
ReadStorage<'a, BeamSegment>,
ReadStorage<'a, Shockwave>,
);
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
@ -91,6 +92,7 @@ impl<'a> System<'a> for Sys {
mountings,
projectiles,
beams,
shockwaves,
): Self::SystemData,
) {
let start_time = std::time::Instant::now();
@ -168,6 +170,7 @@ impl<'a> System<'a> for Sys {
_,
_,
_,
_,
) in (
&entities,
&uids,
@ -178,6 +181,7 @@ impl<'a> System<'a> for Sys {
!&projectiles,
!&mountings,
!&beams,
!&shockwaves,
)
.join()
{

View File

@ -1,7 +1,7 @@
use crate::{
comp::{
group, Body, CharacterState, Damage, DamageSource, HealthChange, HealthSource, Last,
Loadout, Ori, PhysicsState, Pos, Scale, Shockwave, Stats,
Loadout, Ori, PhysicsState, Pos, Scale, Shockwave, ShockwaveHitEntities, Stats,
},
event::{EventBus, LocalEvent, ServerEvent},
state::{DeltaTime, Time},
@ -37,6 +37,7 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, CharacterState>,
ReadStorage<'a, PhysicsState>,
WriteStorage<'a, Shockwave>,
WriteStorage<'a, ShockwaveHitEntities>,
);
fn run(
@ -60,6 +61,7 @@ impl<'a> System<'a> for Sys {
character_states,
physics_states,
mut shockwaves,
mut shockwave_hit_lists,
): Self::SystemData,
) {
let mut server_emitter = server_bus.emitter();
@ -69,8 +71,15 @@ impl<'a> System<'a> for Sys {
let dt = dt.0;
// Shockwaves
for (entity, uid, pos, ori, shockwave) in
(&entities, &uids, &positions, &orientations, &shockwaves).join()
for (entity, uid, pos, ori, shockwave, shockwave_hit_list) in (
&entities,
&uids,
&positions,
&orientations,
&shockwaves,
&mut shockwave_hit_lists,
)
.join()
{
let creation_time = match shockwave.creation {
Some(time) => time,
@ -142,6 +151,15 @@ impl<'a> System<'a> for Sys {
)
.join()
{
// Check to see if entity has already been hit
if shockwave_hit_list
.hit_entities
.iter()
.any(|&uid| uid == *uid_b)
{
continue;
}
// 2D versions
let pos_b2 = pos_b.0.xy();
let last_pos_b2_maybe = last_pos_b_maybe.map(|p| (p.0).0.xy());
@ -204,6 +222,7 @@ impl<'a> System<'a> for Sys {
cause,
},
});
shockwave_hit_list.hit_entities.push(*uid_b);
}
if shockwave.knockback != 0.0 && damage.healthchange != 0.0 {
let impulse = if shockwave.knockback < 0.0 {

View File

@ -1136,6 +1136,7 @@ fn handle_explosion(
max_heal: 0,
min_heal: 0,
terrain_destruction_power: power,
energy_regen: 0,
},
owner: ecs.read_storage::<Uid>().get(target).copied(),
friendly_damage: true,

View File

@ -510,6 +510,7 @@ pub fn handle_explosion(
pos,
power: outcome_power,
radius: explosion.radius,
is_attack: explosion.max_heal > 0 || explosion.max_damage > 0,
reagent,
});
let owner_entity = owner.and_then(|uid| {
@ -588,6 +589,12 @@ pub fn handle_explosion(
amount: damage.healthchange as i32,
cause,
});
if let Some(owner) = owner_entity {
if let Some(energy) = ecs.write_storage::<comp::Energy>().get_mut(owner) {
energy
.change_by(explosion.energy_regen as i32, comp::EnergySource::HitEnemy);
}
}
}
}
}

View File

@ -162,6 +162,9 @@ impl StateExt for State {
properties,
creation: None,
})
.with(comp::ShockwaveHitEntities {
hit_entities: Vec::<Uid>::new(),
})
}
fn create_beam(

View File

@ -53,6 +53,7 @@ impl<'a> System<'a> for Sys {
max_heal: 0,
min_heal: 0,
terrain_destruction_power: 4.0,
energy_regen: 0,
},
owner: *owner,
friendly_damage: true,
@ -75,6 +76,7 @@ impl<'a> System<'a> for Sys {
max_heal: 0,
min_heal: 0,
terrain_destruction_power: 4.0,
energy_regen: 0,
},
owner: *owner,
friendly_damage: true,

View File

@ -390,6 +390,7 @@ impl Scene {
pos,
power,
radius: _,
is_attack: _,
reagent,
} => self.event_lights.push(EventLight {
light: Light::new(

View File

@ -59,20 +59,37 @@ impl ParticleMgr {
pos,
power,
radius,
is_attack,
reagent,
} => {
if *power < 0.0 {
self.particles.resize_with(
self.particles.len() + (200.0 * power.abs()) as usize,
|| {
Particle::new(
Duration::from_secs(1),
time,
ParticleMode::EnergyNature,
*pos + Vec3::<f32>::zero().map(|_| rng.gen_range(-radius, radius)),
)
},
);
if *is_attack {
if *power < 0.0 {
self.particles.resize_with(
self.particles.len() + (200.0 * power.abs()) as usize,
|| {
Particle::new(
Duration::from_secs(1),
time,
ParticleMode::EnergyNature,
*pos + Vec3::<f32>::zero()
.map(|_| rng.gen_range(-radius, radius)),
)
},
);
} else {
self.particles.resize_with(
self.particles.len() + (50.0 * power.abs()) as usize,
|| {
Particle::new(
Duration::from_secs(1),
time,
ParticleMode::CampfireFire,
*pos + Vec3::<f32>::zero()
.map(|_| rng.gen_range(-radius, radius)),
)
},
);
}
} else {
self.particles.resize_with(
self.particles.len() + if reagent.is_some() { 300 } else { 150 },