From cfdf184c4c6647f1b4e2bcca588ad80bc14560a0 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 16 May 2023 20:48:50 +0100 Subject: [PATCH] Fix non-humanoid pathfinding and movement in water --- common/src/mounting.rs | 3 +++ common/src/path.rs | 9 +++++++- common/src/states/utils.rs | 39 ++++++++++++++++++++++---------- server/agent/src/action_nodes.rs | 36 +++++++++++++++-------------- 4 files changed, 57 insertions(+), 30 deletions(-) diff --git a/common/src/mounting.rs b/common/src/mounting.rs index 2230b41059..5e32a78a2e 100644 --- a/common/src/mounting.rs +++ b/common/src/mounting.rs @@ -79,6 +79,9 @@ impl Link for Mounting { // relationship if !is_mounts.contains(mount) && !is_riders.contains(rider) + && !is_riders.contains(rider) + // TODO: Does this definitely prevent mount cycles? + && (!is_mounts.contains(rider) || !is_riders.contains(mount)) && !is_volume_rider.contains(rider) { let _ = is_mounts.insert(mount, this.make_role()); diff --git a/common/src/path.rs b/common/src/path.rs index 861de991ac..1e967f123e 100644 --- a/common/src/path.rs +++ b/common/src/path.rs @@ -143,7 +143,14 @@ impl Route { // Determine whether we're close enough to the next to to consider it completed let dist_sqrd = pos.xy().distance_squared(closest_tgt.xy()); if dist_sqrd - < traversal_cfg.node_tolerance.powi(2) * if be_precise { 0.25 } else { 1.0 } + < traversal_cfg.node_tolerance.powi(2) + * if be_precise { + 0.25 + } else if traversal_cfg.in_liquid { + 2.5 + } else { + 1.0 + } && (((pos.z - closest_tgt.z > 1.2 || (pos.z - closest_tgt.z > -0.2 && traversal_cfg.on_ground)) && (pos.z - closest_tgt.z < 1.2 || (pos.z - closest_tgt.z < 2.9 && vel.z < -0.05)) && vel.z <= 0.0 diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 64114694a5..b9583a9519 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -230,13 +230,13 @@ impl Body { match self { Body::Object(_) => None, Body::ItemDrop(_) => None, - Body::BipedLarge(_) | Body::Golem(_) => Some(200.0 * self.mass().0), - Body::BipedSmall(_) => Some(100.0 * self.mass().0), - Body::BirdMedium(_) => Some(50.0 * self.mass().0), - Body::BirdLarge(_) => Some(50.0 * self.mass().0), + Body::BipedLarge(_) | Body::Golem(_) => Some(3000.0 * self.mass().0), + Body::BipedSmall(_) => Some(1000.0 * self.mass().0), + Body::BirdMedium(_) => Some(1200.0 * self.mass().0), + Body::BirdLarge(_) => Some(750.0 * self.mass().0), Body::FishMedium(_) => Some(50.0 * self.mass().0), Body::FishSmall(_) => Some(50.0 * self.mass().0), - Body::Dragon(_) => Some(200.0 * self.mass().0), + Body::Dragon(_) => Some(3000.0 * self.mass().0), Body::Humanoid(_) => Some(2500.0 * self.mass().0), Body::Theropod(body) => match body.species { theropod::Species::Sandraptor @@ -244,12 +244,12 @@ impl Body { | theropod::Species::Sunlizard | theropod::Species::Woodraptor | theropod::Species::Dodarock - | theropod::Species::Yale => Some(200.0 * self.mass().0), + | theropod::Species::Yale => Some(2500.0 * self.mass().0), _ => Some(100.0 * self.mass().0), }, - Body::QuadrupedLow(_) => Some(300.0 * self.mass().0), - Body::QuadrupedMedium(_) => Some(300.0 * self.mass().0), - Body::QuadrupedSmall(_) => Some(300.0 * self.mass().0), + Body::QuadrupedLow(_) => Some(2500.0 * self.mass().0), + Body::QuadrupedMedium(_) => Some(3000.0 * self.mass().0), + Body::QuadrupedSmall(_) => Some(3000.0 * self.mass().0), Body::Ship(ship) if ship.has_water_thrust() => Some(3500.0 * self.mass().0), Body::Ship(_) => None, Body::Arthropod(_) => Some(300.0 * self.mass().0), @@ -275,7 +275,7 @@ impl Body { match self { Body::Object(_) | Body::Ship(_) | Body::ItemDrop(_) => None, Body::BipedLarge(_) | Body::Dragon(_) | Body::Golem(_) | Body::QuadrupedLow(_) => { - Some(0.1 * self.mass().0) + Some(0.4 * self.mass().0) }, Body::QuadrupedMedium(_) => Some(0.4 * self.mass().0), Body::Theropod(body) => match body.species { @@ -284,7 +284,7 @@ impl Body { | theropod::Species::Woodraptor => Some(0.4 * self.mass().0), _ => None, }, - Body::Arthropod(_) => Some(2.0 * self.mass().0), + Body::Arthropod(_) => Some(1.0 * self.mass().0), _ => Some(0.4 * self.mass().0), } .map(|f| f * GRAVITY) @@ -593,6 +593,8 @@ pub fn handle_orientation( * efficiency * if data.physics.on_ground.is_some() { 1.0 + } else if data.physics.in_liquid().is_some() { + 0.4 } else { 0.2 } @@ -1098,9 +1100,22 @@ pub fn handle_jump( _update: &mut StateUpdate, strength: f32, ) -> bool { - (input_is_pressed(data, InputKind::Jump) && data.physics.on_ground.is_some()) + input_is_pressed(data, InputKind::Jump) .then(|| data.body.jump_impulse()) .flatten() + .and_then(|impulse| { + if data.physics.on_ground.is_some() { + Some(impulse) + } else if data.physics.in_liquid().map_or(false, |h| h < 1.0) + && data.physics.on_wall.is_some() + { + // Allow entities to make a small jump when at the edge of a body of water, + // allowing them to path out of it + Some(impulse * 0.75) + } else { + None + } + }) .map(|impulse| { output_events.emit_local(LocalEvent::Jump( data.entity, diff --git a/server/agent/src/action_nodes.rs b/server/agent/src/action_nodes.rs index 16eaeac655..a3f0a393c6 100644 --- a/server/agent/src/action_nodes.rs +++ b/server/agent/src/action_nodes.rs @@ -152,16 +152,23 @@ impl<'a> AgentData<'a> { ..self.traversal_config }, ) { - controller.inputs.move_dir = - bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed * speed_multiplier; - self.jump_if(bearing.z > 1.5, controller); - controller.inputs.move_z = bearing.z; + self.traverse(controller, bearing, speed * speed_multiplier); true } else { false } } + fn traverse(&self, controller: &mut Controller, bearing: Vec3, speed: f32) { + controller.inputs.move_dir = + bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed; + let climbing_out_of_water = self.physics_state.in_liquid().map_or(false, |h| h < 1.0) + && bearing.z > 0.0 + && self.physics_state.on_wall.is_some(); + self.jump_if(bearing.z > 1.5 || climbing_out_of_water, controller); + controller.inputs.move_z = bearing.z; + } + pub fn jump_if(&self, condition: bool, controller: &mut Controller) { if condition { controller.push_basic_input(InputKind::Jump); @@ -265,12 +272,9 @@ impl<'a> AgentData<'a> { ..self.traversal_config }, ) { - controller.inputs.move_dir = - bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) - * speed.min(speed_factor); - self.jump_if(bearing.z > 1.5 || self.traversal_config.can_fly, controller); + self.traverse(controller, bearing, speed.min(speed_factor)); + self.jump_if(self.traversal_config.can_fly, controller); controller.inputs.climb = Some(comp::Climb::Up); - //.filter(|_| bearing.z > 0.1 || self.physics_state.in_liquid().is_some()); let height_offset = bearing.z + if self.traversal_config.can_fly { @@ -552,10 +556,11 @@ impl<'a> AgentData<'a> { }, ) { let dist_sqrd = self.pos.0.distance_squared(tgt_pos.0); - controller.inputs.move_dir = bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) - * speed.min(0.2 + (dist_sqrd - AVG_FOLLOW_DIST.powi(2)) / 8.0); - self.jump_if(bearing.z > 1.5, controller); - controller.inputs.move_z = bearing.z; + self.traverse( + controller, + bearing, + speed.min(0.2 + (dist_sqrd - AVG_FOLLOW_DIST.powi(2)) / 8.0), + ); } } @@ -617,10 +622,7 @@ impl<'a> AgentData<'a> { ..self.traversal_config }, ) { - controller.inputs.move_dir = bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) - * speed.min(MAX_FLEE_SPEED); - self.jump_if(bearing.z > 1.5, controller); - controller.inputs.move_z = bearing.z; + self.traverse(controller, bearing, speed.min(MAX_FLEE_SPEED)); } }