From d09ee618345dfcc5dc8c0d4b7d10527b8727bf98 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 22 Mar 2021 12:32:27 +0000 Subject: [PATCH 1/2] Added raycast check to beams --- CHANGELOG.md | 1 + common/sys/src/beam.rs | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 418e9aea3b..2df9c850c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Server kicks old client when a user is trying to log in again (often the case when a user's original connection gets dropped) +- Added a raycast check to beams to prevent their effect applying through walls ## [0.9.0] - 2021-03-20 diff --git a/common/sys/src/beam.rs b/common/sys/src/beam.rs index 65c86c8c45..3f40960a9f 100644 --- a/common/sys/src/beam.rs +++ b/common/sys/src/beam.rs @@ -6,14 +6,16 @@ use common::{ }, event::{EventBus, ServerEvent}, resources::{DeltaTime, Time}, + terrain::TerrainGrid, uid::{Uid, UidAllocator}, + vol::ReadVol, GroupTarget, }; use common_ecs::{Job, Origin, ParMode, Phase, System}; use rayon::iter::ParallelIterator; use specs::{ - saveload::MarkerAllocator, shred::ResourceId, Entities, Join, ParJoin, Read, ReadStorage, - SystemData, World, WriteStorage, + saveload::MarkerAllocator, shred::ResourceId, Entities, Join, ParJoin, Read, ReadExpect, + ReadStorage, SystemData, World, WriteStorage, }; use std::time::Duration; use vek::*; @@ -24,6 +26,7 @@ pub struct ReadData<'a> { server_bus: Read<'a, EventBus>, time: Read<'a, Time>, dt: Read<'a, DeltaTime>, + terrain: ReadExpect<'a, TerrainGrid>, uid_allocator: Read<'a, UidAllocator>, uids: ReadStorage<'a, Uid>, positions: ReadStorage<'a, Pos>, @@ -65,10 +68,11 @@ impl<'a> System<'a> for Sys { &read_data.entities, &read_data.positions, &read_data.orientations, + read_data.bodies.maybe(), &beam_segments, ) .par_join() - .fold(|| (Vec::new(), Vec::new()), |(mut server_events, mut add_hit_entities), (entity, pos, ori, beam_segment)| + .fold(|| (Vec::new(), Vec::new()), |(mut server_events, mut add_hit_entities), (entity, pos, ori, body, beam_segment)| { let creation_time = match beam_segment.creation { Some(time) => time, @@ -112,6 +116,8 @@ impl<'a> System<'a> for Sys { return (server_events, add_hit_entities); }; + let eye_pos = pos.0 + Vec3::unit_z() * body.map_or(0.0, |b| b.eye_height()); + // Go through all other effectable entities for (target, uid_b, pos_b, health_b, body_b) in ( &read_data.entities, @@ -136,7 +142,15 @@ impl<'a> System<'a> for Sys { let hit = entity != target && !health_b.is_dead // Collision shapes - && sphere_wedge_cylinder_collision(pos.0, frame_start_dist, frame_end_dist, *ori.look_dir(), beam_segment.angle, pos_b.0, rad_b, height_b); + && sphere_wedge_cylinder_collision(eye_pos, frame_start_dist, frame_end_dist, *ori.look_dir(), beam_segment.angle, pos_b.0, rad_b, height_b); + + // Finally, ensure that a hit has actually occurred by performing a raycast. We do this last because + // it's likely to be the most expensive operation. + let tgt_dist = eye_pos.distance(pos_b.0); + let hit = hit && read_data.terrain + .ray(eye_pos, eye_pos + *ori.look_dir() * (tgt_dist + 1.0)) + .until(|b| b.is_filled()) + .cast().0 >= tgt_dist; if hit { // See if entities are in the same group From 4401230d4b3ee886f143ddf0d0b3b6348bf7341d Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 22 Mar 2021 14:55:24 +0000 Subject: [PATCH 2/2] Remove eye height check for beam --- common/sys/src/beam.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/common/sys/src/beam.rs b/common/sys/src/beam.rs index 3f40960a9f..b1bdc0d504 100644 --- a/common/sys/src/beam.rs +++ b/common/sys/src/beam.rs @@ -68,11 +68,10 @@ impl<'a> System<'a> for Sys { &read_data.entities, &read_data.positions, &read_data.orientations, - read_data.bodies.maybe(), &beam_segments, ) .par_join() - .fold(|| (Vec::new(), Vec::new()), |(mut server_events, mut add_hit_entities), (entity, pos, ori, body, beam_segment)| + .fold(|| (Vec::new(), Vec::new()), |(mut server_events, mut add_hit_entities), (entity, pos, ori, beam_segment)| { let creation_time = match beam_segment.creation { Some(time) => time, @@ -116,8 +115,6 @@ impl<'a> System<'a> for Sys { return (server_events, add_hit_entities); }; - let eye_pos = pos.0 + Vec3::unit_z() * body.map_or(0.0, |b| b.eye_height()); - // Go through all other effectable entities for (target, uid_b, pos_b, health_b, body_b) in ( &read_data.entities, @@ -142,13 +139,13 @@ impl<'a> System<'a> for Sys { let hit = entity != target && !health_b.is_dead // Collision shapes - && sphere_wedge_cylinder_collision(eye_pos, frame_start_dist, frame_end_dist, *ori.look_dir(), beam_segment.angle, pos_b.0, rad_b, height_b); + && sphere_wedge_cylinder_collision(pos.0, frame_start_dist, frame_end_dist, *ori.look_dir(), beam_segment.angle, pos_b.0, rad_b, height_b); // Finally, ensure that a hit has actually occurred by performing a raycast. We do this last because // it's likely to be the most expensive operation. - let tgt_dist = eye_pos.distance(pos_b.0); + let tgt_dist = pos.0.distance(pos_b.0); let hit = hit && read_data.terrain - .ray(eye_pos, eye_pos + *ori.look_dir() * (tgt_dist + 1.0)) + .ray(pos.0, pos.0 + *ori.look_dir() * (tgt_dist + 1.0)) .until(|b| b.is_filled()) .cast().0 >= tgt_dist;