From 9127d6cbf2454f493fae619827fac1e2289b563b Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 25 May 2023 01:21:44 +0100 Subject: [PATCH] Account for surface normal when calculating collision damage --- common/src/event.rs | 1 + common/systems/src/phys.rs | 30 +++++++++++++++++------- server/src/events/entity_manipulation.rs | 21 +++++++++++------ server/src/events/mod.rs | 8 ++++--- 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/common/src/event.rs b/common/src/event.rs index ed44b7b31f..46186047d6 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -188,6 +188,7 @@ pub enum ServerEvent { LandOnGround { entity: EcsEntity, vel: Vec3, + surface_normal: Vec3, }, EnableLantern(EcsEntity), DisableLantern(EcsEntity), diff --git a/common/systems/src/phys.rs b/common/systems/src/phys.rs index 00ad521ea6..4d73748e27 100644 --- a/common/systems/src/phys.rs +++ b/common/systems/src/phys.rs @@ -889,7 +889,9 @@ impl<'a> PhysicsData<'a> { was_on_ground, block_snap, climbing, - |entity, vel| land_on_ground = Some((entity, vel)), + |entity, vel, surface_normal| { + land_on_ground = Some((entity, vel, surface_normal)) + }, read, &ori, ); @@ -921,7 +923,9 @@ impl<'a> PhysicsData<'a> { was_on_ground, block_snap, climbing, - |entity, vel| land_on_ground = Some((entity, vel)), + |entity, vel, surface_normal| { + land_on_ground = Some((entity, vel, surface_normal)) + }, read, &ori, ); @@ -1200,10 +1204,12 @@ impl<'a> PhysicsData<'a> { was_on_ground, block_snap, climbing, - |entity, vel| { + |entity, vel, surface_normal| { land_on_ground = Some(( entity, - Vel(ori_other.to_quat() * vel.0), + Vel(previous_cache_other.ori * vel.0 + + vel_other), + surface_normal, )); }, read, @@ -1337,9 +1343,15 @@ impl<'a> PhysicsData<'a> { drop(guard); let mut event_emitter = read.event_bus.emitter(); - land_on_grounds.into_iter().for_each(|(entity, vel)| { - event_emitter.emit(ServerEvent::LandOnGround { entity, vel: vel.0 }); - }); + land_on_grounds + .into_iter() + .for_each(|(entity, vel, surface_normal)| { + event_emitter.emit(ServerEvent::LandOnGround { + entity, + vel: vel.0, + surface_normal, + }); + }); } fn update_cached_spatial_grid(&mut self) { @@ -1418,7 +1430,7 @@ fn box_voxel_collision + ReadVol>( was_on_ground: bool, block_snap: bool, climbing: bool, - mut land_on_ground: impl FnMut(Entity, Vel), + mut land_on_ground: impl FnMut(Entity, Vel, Vec3), read: &PhysicsRead, ori: &Ori, ) { @@ -1594,7 +1606,7 @@ fn box_voxel_collision + ReadVol>( } if resolve_dir.magnitude_squared() > 0.0 { - land_on_ground(entity, *vel); + land_on_ground(entity, *vel, resolve_dir.normalized()); } // When the resolution direction is non-vertical, we must be colliding diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index d4f9f6894b..6117d2aa6c 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -595,14 +595,21 @@ pub fn handle_delete(server: &mut Server, entity: EcsEntity) { .map_err(|e| error!(?e, ?entity, "Failed to delete destroyed entity")); } -pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3) { +pub fn handle_land_on_ground( + server: &Server, + entity: EcsEntity, + vel: Vec3, + surface_normal: Vec3, +) { let ecs = server.state.ecs(); + let relative_vel = vel.dot(-surface_normal); + // The second part of this if statement disables all fall damage when in the // water. This was added as a *temporary* fix a bug that causes you to take // fall damage while swimming downwards. FIXME: Fix the actual bug and // remove the following relevant part of the if statement. - if vel.magnitude() >= 30.0 + if relative_vel >= 30.0 && ecs .read_storage::() .get(entity) @@ -610,10 +617,10 @@ pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3) { let char_states = ecs.read_storage::(); - let reduced_vel_z = if let Some(CharacterState::DiveMelee(c)) = char_states.get(entity) { - (vel.magnitude() + c.static_data.vertical_speed).min(0.0) + let reduced_vel = if let Some(CharacterState::DiveMelee(c)) = char_states.get(entity) { + (relative_vel + c.static_data.vertical_speed).min(0.0) } else { - vel.magnitude() + relative_vel }; let mass = ecs @@ -621,7 +628,7 @@ pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3) .get(entity) .copied() .unwrap_or_default(); - let impact_energy = mass.0 * reduced_vel_z.powi(2) / 2.0; + let impact_energy = mass.0 * reduced_vel.powi(2) / 2.0; let falldmg = impact_energy / 1000.0; let inventories = ecs.read_storage::(); @@ -655,7 +662,7 @@ pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3) server_eventbus.emit_now(ServerEvent::HealthChange { entity, change }); // Emit poise change - let poise_damage = -(mass.0 * reduced_vel_z.powi(2) / 1500.0); + let poise_damage = -(mass.0 * reduced_vel.powi(2) / 1500.0); let poise_change = Poise::apply_poise_reduction( poise_damage, inventories.get(entity), diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs index b8cbec958e..37669c5581 100644 --- a/server/src/events/mod.rs +++ b/server/src/events/mod.rs @@ -120,9 +120,11 @@ impl Server { ServerEvent::InventoryManip(entity, manip) => handle_inventory(self, entity, manip), ServerEvent::GroupManip(entity, manip) => handle_group(self, entity, manip), ServerEvent::Respawn(entity) => handle_respawn(self, entity), - ServerEvent::LandOnGround { entity, vel } => { - handle_land_on_ground(self, entity, vel) - }, + ServerEvent::LandOnGround { + entity, + vel, + surface_normal, + } => handle_land_on_ground(self, entity, vel, surface_normal), ServerEvent::EnableLantern(entity) => handle_lantern(self, entity, true), ServerEvent::DisableLantern(entity) => handle_lantern(self, entity, false), ServerEvent::NpcInteract(interactor, target, subject) => {