From c4a6875133b91f5b3026e10279f68cd1633f5eb0 Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Wed, 24 Mar 2021 15:42:37 -0400 Subject: [PATCH] Fix airships getting stuck in trees and campfires spawning too close to new-style dungeon stairs. --- CHANGELOG.md | 1 + server/src/rtsim/tick.rs | 17 ++++++++++------- server/src/sys/agent.rs | 35 ++++++++++++++++++++++++----------- world/src/site/dungeon/mod.rs | 2 +- 4 files changed, 36 insertions(+), 19 deletions(-) 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..8f5030ee15 100644 --- a/server/src/rtsim/tick.rs +++ b/server/src/rtsim/tick.rs @@ -102,7 +102,7 @@ impl<'a> System<'a> for Sys { .map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0); let body = entity.get_body(); - let pos = comp::Pos(spawn_pos); + let mut pos = comp::Pos(spawn_pos); let agent = Some(comp::Agent::new( None, matches!(body, comp::Body::Humanoid(_)), @@ -112,12 +112,15 @@ impl<'a> System<'a> for Sys { )); let rtsim_entity = Some(RtSimEntity(id)); let event = match body { - comp::Body::Ship(ship) => ServerEvent::CreateShip { - pos, - ship, - mountable: false, - agent, - rtsim_entity, + comp::Body::Ship(ship) => { + pos.0 += Vec3::unit_z() * body.flying_height(); + ServerEvent::CreateShip { + pos, + ship, + mountable: false, + agent, + rtsim_entity, + } }, _ => ServerEvent::CreateNpc { pos: comp::Pos(spawn_pos), 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(), ); }