diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index 4b9c7d0bb9..95d2a23a88 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -1,5 +1,6 @@ use specs::{Component, FlaggedStorage}; use specs_idvs::IDVStorage; +use std::time::Duration; #[derive(Clone, Debug, Serialize, Deserialize)] pub enum Effect { @@ -13,6 +14,8 @@ pub struct Projectile { pub hit_ground: Vec, pub hit_wall: Vec, pub hit_entity: Vec, + /// Time left until the projectile will despawn + pub time_left: Duration, } impl Component for Projectile { diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index 4300513aa5..be4c2b8b46 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -150,6 +150,7 @@ impl<'a> System<'a> for Sys { projectile::Effect::Damage(10), projectile::Effect::Vanish, ], + time_left: Duration::from_secs(60 * 5), }, }); } diff --git a/common/src/sys/projectile.rs b/common/src/sys/projectile.rs index f2ade8f972..a397284b91 100644 --- a/common/src/sys/projectile.rs +++ b/common/src/sys/projectile.rs @@ -1,14 +1,17 @@ use crate::{ comp::{projectile, HealthSource, Ori, PhysicsState, Projectile, Vel}, event::{EventBus, ServerEvent}, + state::DeltaTime, }; use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; +use std::time::Duration; /// This system is responsible for handling projectile effect triggers pub struct Sys; impl<'a> System<'a> for Sys { type SystemData = ( Entities<'a>, + Read<'a, DeltaTime>, Read<'a, EventBus>, ReadStorage<'a, PhysicsState>, ReadStorage<'a, Vel>, @@ -20,6 +23,7 @@ impl<'a> System<'a> for Sys { &mut self, ( entities, + dt, server_bus, physics_states, velocities, @@ -29,8 +33,6 @@ impl<'a> System<'a> for Sys { ) { let mut server_emitter = server_bus.emitter(); - let mut todo = Vec::new(); - // Attacks for (entity, physics, ori, projectile) in ( &entities, @@ -40,8 +42,24 @@ impl<'a> System<'a> for Sys { ) .join() { + // Hit ground + if physics.on_ground { + for effect in projectile.hit_ground.drain(..) { + match effect { + _ => {} + } + } + } + // Hit wall + else if physics.on_wall.is_some() { + for effect in projectile.hit_wall.drain(..) { + match effect { + _ => {} + } + } + } // Hit entity - if let Some(other) = physics.touch_entity { + else if let Some(other) = physics.touch_entity { for effect in projectile.hit_entity.drain(..) { match effect { projectile::Effect::Damage(power) => { @@ -58,34 +76,22 @@ impl<'a> System<'a> for Sys { _ => {} } } - todo.push(entity); - } - // Hit ground - else if physics.on_ground { - for effect in projectile.hit_ground.drain(..) { - match effect { - _ => {} - } - } - todo.push(entity); - } - // Hit wall - else if physics.on_wall.is_some() { - for effect in projectile.hit_wall.drain(..) { - match effect { - _ => {} - } - } - todo.push(entity); } else { if let Some(vel) = velocities.get(entity) { ori.0 = vel.0.normalized(); } } - } - for entity in todo { - projectiles.remove(entity); + if projectile.time_left == Duration::default() { + server_emitter.emit(ServerEvent::Destroy { + entity, + cause: HealthSource::World, + }); + } + projectile.time_left = projectile + .time_left + .checked_sub(Duration::from_secs_f32(dt.0)) + .unwrap_or_default(); } } }