diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ad473f0b6..a10ea27e91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 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 +- Flying agents raycast more angles to check for obstacles. ## [0.9.0] - 2021-03-20 diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs index 238e921566..c68d7a99b3 100644 --- a/server/src/rtsim/tick.rs +++ b/server/src/rtsim/tick.rs @@ -97,11 +97,11 @@ impl<'a> System<'a> for Sys { for id in to_reify { rtsim.reify_entity(id); let entity = &rtsim.entities[id]; + let body = entity.get_body(); let spawn_pos = terrain .find_space(entity.pos.map(|e| e.floor() as i32)) .map(|e| e as f32) - + Vec3::new(0.5, 0.5, 0.0); - let body = entity.get_body(); + + Vec3::new(0.5, 0.5, body.flying_height()); let pos = comp::Pos(spawn_pos); let agent = Some(comp::Agent::new( None, diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index d80439aa8b..5608cc3477 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -680,7 +680,7 @@ impl<'a> AgentData<'a> { .cast() .1 .map_or(true, |b| b.is_some()); - let ground_too_close = self + let mut ground_too_close = self .body .map(|body| { let height_approx = self.pos.0.y @@ -691,19 +691,32 @@ impl<'a> AgentData<'a> { .unwrap_or(0.0); height_approx < body.flying_height() - || read_data - .terrain - .ray( - self.pos.0, - self.pos.0 - body.flying_height() * Vec3::unit_z(), - ) - .until(|b: &Block| b.is_solid() || b.is_liquid()) - .cast() - .1 - .map_or(false, |b| b.is_some()) }) .unwrap_or(false); + const NUM_RAYS: usize = 5; + for i in 0..=NUM_RAYS { + let magnitude = self.body.map_or(20.0, |b| b.flying_height()); + // Lerp between a line straight ahead and straight down to detect a + // wedge of obstacles we might fly into (inclusive so that both vectors + // are sampled) + if let Some(dir) = Lerp::lerp( + -Vec3::unit_z(), + Vec3::new(bearing.x, bearing.y, 0.0), + i as f32 / NUM_RAYS as f32, + ) + .try_normalized() + { + ground_too_close |= read_data + .terrain + .ray(self.pos.0, self.pos.0 + magnitude * dir) + .until(|b: &Block| b.is_solid() || b.is_liquid()) + .cast() + .1 + .map_or(false, |b| b.is_some()) + } + } + if obstacle_ahead || ground_too_close { 1.0 //fly up when approaching obstacles } else { diff --git a/world/src/site/dungeon/mod.rs b/world/src/site/dungeon/mod.rs index 934cc358b1..7af91c00d0 100644 --- a/world/src/site/dungeon/mod.rs +++ b/world/src/site/dungeon/mod.rs @@ -201,7 +201,7 @@ impl Dungeon { let pos = self.origin.map2(FLOOR_SIZE, |e, sz| e + sz as i32 / 2); if area.contains_point(pos - self.origin) { supplement.add_entity( - EntityInfo::at(Vec3::new(pos.x as f32, pos.y as f32, self.alt as f32) + 2.5) + EntityInfo::at(Vec3::new(pos.x as f32, pos.y as f32, self.alt as f32) + 5.0) .into_waypoint(), ); }