mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Improve Projectile/Entity Hit Detection
This commit is contained in:
parent
696b575611
commit
ef5737360b
@ -5,7 +5,7 @@ use crate::{
|
||||
terrain::Block,
|
||||
uid::Uid,
|
||||
};
|
||||
use hashbrown::HashSet;
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specs::{Component, DerefFlaggedStorage, NullStorage, VecStorage};
|
||||
use std::sync::Arc;
|
||||
@ -176,7 +176,7 @@ pub struct PhysicsState {
|
||||
pub on_ground: Option<Block>,
|
||||
pub on_ceiling: bool,
|
||||
pub on_wall: Option<Vec3<f32>>,
|
||||
pub touch_entities: HashSet<Uid>,
|
||||
pub touch_entities: HashMap<Uid, Vec3<f32>>,
|
||||
pub in_fluid: Option<Fluid>,
|
||||
pub ground_vel: Vec3<f32>,
|
||||
pub footwear: Friction,
|
||||
|
@ -1917,7 +1917,7 @@ fn resolve_e2e_collision(
|
||||
// is either in mid air or is not sticky, then mark them as colliding with
|
||||
// the other entity.
|
||||
if !*collision_registered && (is_mid_air || !is_sticky) {
|
||||
physics.touch_entities.insert(other);
|
||||
physics.touch_entities.insert(other, pos);
|
||||
*entity_entity_collisions += 1;
|
||||
}
|
||||
|
||||
|
@ -12,15 +12,19 @@ use common::{
|
||||
util::Dir,
|
||||
GroupTarget,
|
||||
};
|
||||
|
||||
use common::vol::ReadVol;
|
||||
use common_ecs::{Job, Origin, Phase, System};
|
||||
use rand::{thread_rng, Rng};
|
||||
use specs::{
|
||||
saveload::MarkerAllocator, shred::ResourceId, Entities, Entity as EcsEntity, Join, Read,
|
||||
ReadStorage, SystemData, World, WriteStorage,
|
||||
ReadExpect, ReadStorage, SystemData, World, WriteStorage,
|
||||
};
|
||||
use std::time::Duration;
|
||||
use vek::*;
|
||||
|
||||
use common::terrain::TerrainGrid;
|
||||
|
||||
#[derive(SystemData)]
|
||||
pub struct ReadData<'a> {
|
||||
time: Read<'a, Time>,
|
||||
@ -42,6 +46,7 @@ pub struct ReadData<'a> {
|
||||
healths: ReadStorage<'a, Health>,
|
||||
bodies: ReadStorage<'a, Body>,
|
||||
character_states: ReadStorage<'a, CharacterState>,
|
||||
terrain: ReadExpect<'a, TerrainGrid>,
|
||||
}
|
||||
|
||||
/// This system is responsible for handling projectile effect triggers
|
||||
@ -90,7 +95,7 @@ impl<'a> System<'a> for Sys {
|
||||
let mut projectile_vanished: bool = false;
|
||||
|
||||
// Hit entity
|
||||
for other in physics.touch_entities.iter().copied() {
|
||||
for (&other, &pos_other) in physics.touch_entities.iter() {
|
||||
let same_group = projectile_owner
|
||||
// Note: somewhat inefficient since we do the lookup for every touching
|
||||
// entity, but if we pull this out of the loop we would want to do it only
|
||||
@ -121,6 +126,28 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
let entity_of =
|
||||
|uid: Uid| read_data.uid_allocator.retrieve_entity_internal(uid.into());
|
||||
|
||||
// Don't hit if there is a surface in the entity's way in the direction the
|
||||
// projectile is going
|
||||
|
||||
if physics.on_surface().is_some() {
|
||||
let projectile_direction = orientations
|
||||
.get(entity)
|
||||
.map_or_else(Vec3::zero, |ori| ori.look_vec());
|
||||
let pos_wall = pos.0 - 0.2 * projectile_direction;
|
||||
if !matches!(
|
||||
read_data
|
||||
.terrain
|
||||
.ray(pos_wall, pos_other)
|
||||
.until(|b| b.is_filled())
|
||||
.cast()
|
||||
.1,
|
||||
Ok(None)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for effect in projectile.hit_entity.drain(..) {
|
||||
let owner = projectile.owner.and_then(entity_of);
|
||||
let projectile_info = ProjectileInfo {
|
||||
|
Loading…
Reference in New Issue
Block a user