Added entity event system, fixed fall damage

This commit is contained in:
Joshua Barretto 2019-08-07 10:50:49 +01:00
parent 2fb8306b98
commit 98a913195b
6 changed files with 89 additions and 11 deletions

30
common/src/comp/event.rs Normal file
View File

@ -0,0 +1,30 @@
use specs::Component;
use specs_idvs::IDVStorage;
use std::ops::{Deref, DerefMut};
use vek::*;
#[derive(Clone, Debug, Default)]
pub struct Events(pub Vec<EntityEvent>);
impl Deref for Events {
type Target = Vec<EntityEvent>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Events {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Component for Events {
type Storage = IDVStorage<Self>;
}
#[derive(Clone, Debug)]
pub enum EntityEvent {
HitGround { vel: Vec3<f32> },
}

View File

@ -3,6 +3,7 @@ mod agent;
mod animation;
mod body;
mod controller;
mod event;
mod inputs;
mod inventory;
mod last;
@ -17,6 +18,7 @@ pub use agent::Agent;
pub use animation::{Animation, AnimationInfo};
pub use body::{humanoid, object, quadruped, quadruped_medium, Body};
pub use controller::Controller;
pub use event::{EntityEvent, Events};
pub use inputs::{
Attacking, CanBuild, Gliding, Jumping, MoveDir, OnGround, Respawning, Rolling, Wielding,
};

View File

@ -161,6 +161,7 @@ impl State {
ecs.register::<comp::ForceUpdate>();
ecs.register::<comp::InventoryUpdate>();
ecs.register::<comp::Inventory>();
ecs.register::<comp::Events>();
// Controller effects
ecs.register::<comp::MoveDir>();
ecs.register::<comp::OnGround>();

View File

@ -0,0 +1,33 @@
use crate::{
comp::{EntityEvent, Events, HealthSource, Stats},
state::DeltaTime,
};
use log::warn;
use specs::{Entities, Join, Read, System, WriteStorage};
/// This system kills players
pub struct Sys;
impl<'a> System<'a> for Sys {
type SystemData = (
Entities<'a>,
WriteStorage<'a, Events>,
WriteStorage<'a, Stats>,
);
fn run(&mut self, (entities, mut events, mut stats): Self::SystemData) {
for (entity, mut events) in (&entities, &mut events).join() {
for event in events.drain(..) {
match event {
EntityEvent::HitGround { vel } => {
if let Some(stat) = stats.get_mut(entity) {
let falldmg = (vel.z / 1.5 + 6.0) as i32;
if falldmg < 0 {
stat.health.change_by(falldmg, HealthSource::World);
}
}
}
}
}
}
}
}

View File

@ -3,6 +3,7 @@ pub mod agent;
pub mod animation;
pub mod combat;
pub mod controller;
mod event_handler;
pub mod movement;
pub mod phys;
mod stats;
@ -19,6 +20,7 @@ const MOVEMENT_SYS: &str = "movement_sys";
const COMBAT_SYS: &str = "combat_sys";
const ANIMATION_SYS: &str = "animation_sys";
const STATS_SYS: &str = "stats_sys";
const EVENT_HANDLER_SYS: &str = "event_handler_sys";
pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
dispatch_builder.add(agent::Sys, AGENT_SYS, &[]);
@ -33,4 +35,9 @@ pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
dispatch_builder.add(combat::Sys, COMBAT_SYS, &[ACTION_STATE_SYS]);
dispatch_builder.add(animation::Sys, ANIMATION_SYS, &[ACTION_STATE_SYS]);
dispatch_builder.add(stats::Sys, STATS_SYS, &[COMBAT_SYS]);
dispatch_builder.add(
event_handler::Sys,
EVENT_HANDLER_SYS,
&[AGENT_SYS, PHYS_SYS, ACTION_STATE_SYS, COMBAT_SYS],
);
}

View File

@ -1,8 +1,8 @@
use crate::{
comp::HealthSource,
comp::{
ActionState, Body, Jumping, MoveDir, OnGround, Ori, Pos, Rolling, Scale, Stats, Vel,
Wielding,
ActionState, Body, EntityEvent, Events, Jumping, MoveDir, OnGround, Ori, Pos, Rolling,
Scale, Stats, Vel, Wielding,
},
state::DeltaTime,
terrain::TerrainMap,
@ -42,7 +42,7 @@ impl<'a> System<'a> for Sys {
WriteStorage<'a, Pos>,
WriteStorage<'a, Vel>,
WriteStorage<'a, Ori>,
WriteStorage<'a, Stats>,
WriteStorage<'a, Events>,
);
fn run(
@ -58,11 +58,11 @@ impl<'a> System<'a> for Sys {
mut positions,
mut velocities,
mut orientations,
mut stats,
mut events,
): Self::SystemData,
) {
// Apply movement inputs
for (entity, a, scale, b, mut pos, mut vel, mut ori, mut stat) in (
for (entity, a, scale, b, mut pos, mut vel, mut ori) in (
&entities,
&action_states,
scales.maybe(),
@ -70,7 +70,6 @@ impl<'a> System<'a> for Sys {
&mut positions,
&mut velocities,
&mut orientations,
&mut stats,
)
.join()
{
@ -210,12 +209,18 @@ impl<'a> System<'a> for Sys {
// When the resolution direction is pointing upwards, we must be on the ground
if resolve_dir.z > 0.0 && vel.0.z <= 0.0 {
// Check for fall damage
let falldmg = (vel.0.z / 1.5 + 6.0) as i32;
if falldmg < 0 {
stat.health.change_by(falldmg, HealthSource::World);
}
on_ground = true;
// Hitting the ground
const COLLISION_VEL: f32 = GRAVITY * 0.75; // Falling for 0.75 seconds
if vel.0.z < -COLLISION_VEL {
if events.get(entity).is_none() {
events.insert(entity, Events::default());
}
events
.get_mut(entity) // TODO: Use get_mut_or_default when updating to SPECS 15
.map(|e| e.push(EntityEvent::HitGround { vel: vel.0 }));
}
}
// When the resolution direction is non-vertical, we must be colliding with a wall