Fix non-humanoid pathfinding and movement in water

This commit is contained in:
Joshua Barretto 2023-05-16 20:48:50 +01:00
parent a0ad6fc779
commit cfdf184c4c
4 changed files with 57 additions and 30 deletions

View File

@ -79,6 +79,9 @@ impl Link for Mounting {
// relationship // relationship
if !is_mounts.contains(mount) if !is_mounts.contains(mount)
&& !is_riders.contains(rider) && !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) && !is_volume_rider.contains(rider)
{ {
let _ = is_mounts.insert(mount, this.make_role()); let _ = is_mounts.insert(mount, this.make_role());

View File

@ -143,7 +143,14 @@ impl Route {
// Determine whether we're close enough to the next to to consider it completed // Determine whether we're close enough to the next to to consider it completed
let dist_sqrd = pos.xy().distance_squared(closest_tgt.xy()); let dist_sqrd = pos.xy().distance_squared(closest_tgt.xy());
if dist_sqrd 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 > -0.2 && traversal_cfg.on_ground))
&& (pos.z - closest_tgt.z < 1.2 || (pos.z - closest_tgt.z < 2.9 && vel.z < -0.05)) && (pos.z - closest_tgt.z < 1.2 || (pos.z - closest_tgt.z < 2.9 && vel.z < -0.05))
&& vel.z <= 0.0 && vel.z <= 0.0

View File

@ -230,13 +230,13 @@ impl Body {
match self { match self {
Body::Object(_) => None, Body::Object(_) => None,
Body::ItemDrop(_) => None, Body::ItemDrop(_) => None,
Body::BipedLarge(_) | Body::Golem(_) => Some(200.0 * self.mass().0), Body::BipedLarge(_) | Body::Golem(_) => Some(3000.0 * self.mass().0),
Body::BipedSmall(_) => Some(100.0 * self.mass().0), Body::BipedSmall(_) => Some(1000.0 * self.mass().0),
Body::BirdMedium(_) => Some(50.0 * self.mass().0), Body::BirdMedium(_) => Some(1200.0 * self.mass().0),
Body::BirdLarge(_) => Some(50.0 * self.mass().0), Body::BirdLarge(_) => Some(750.0 * self.mass().0),
Body::FishMedium(_) => Some(50.0 * self.mass().0), Body::FishMedium(_) => Some(50.0 * self.mass().0),
Body::FishSmall(_) => 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::Humanoid(_) => Some(2500.0 * self.mass().0),
Body::Theropod(body) => match body.species { Body::Theropod(body) => match body.species {
theropod::Species::Sandraptor theropod::Species::Sandraptor
@ -244,12 +244,12 @@ impl Body {
| theropod::Species::Sunlizard | theropod::Species::Sunlizard
| theropod::Species::Woodraptor | theropod::Species::Woodraptor
| theropod::Species::Dodarock | 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), _ => Some(100.0 * self.mass().0),
}, },
Body::QuadrupedLow(_) => Some(300.0 * self.mass().0), Body::QuadrupedLow(_) => Some(2500.0 * self.mass().0),
Body::QuadrupedMedium(_) => Some(300.0 * self.mass().0), Body::QuadrupedMedium(_) => Some(3000.0 * self.mass().0),
Body::QuadrupedSmall(_) => Some(300.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(ship) if ship.has_water_thrust() => Some(3500.0 * self.mass().0),
Body::Ship(_) => None, Body::Ship(_) => None,
Body::Arthropod(_) => Some(300.0 * self.mass().0), Body::Arthropod(_) => Some(300.0 * self.mass().0),
@ -275,7 +275,7 @@ impl Body {
match self { match self {
Body::Object(_) | Body::Ship(_) | Body::ItemDrop(_) => None, Body::Object(_) | Body::Ship(_) | Body::ItemDrop(_) => None,
Body::BipedLarge(_) | Body::Dragon(_) | Body::Golem(_) | Body::QuadrupedLow(_) => { 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::QuadrupedMedium(_) => Some(0.4 * self.mass().0),
Body::Theropod(body) => match body.species { Body::Theropod(body) => match body.species {
@ -284,7 +284,7 @@ impl Body {
| theropod::Species::Woodraptor => Some(0.4 * self.mass().0), | theropod::Species::Woodraptor => Some(0.4 * self.mass().0),
_ => None, _ => None,
}, },
Body::Arthropod(_) => Some(2.0 * self.mass().0), Body::Arthropod(_) => Some(1.0 * self.mass().0),
_ => Some(0.4 * self.mass().0), _ => Some(0.4 * self.mass().0),
} }
.map(|f| f * GRAVITY) .map(|f| f * GRAVITY)
@ -593,6 +593,8 @@ pub fn handle_orientation(
* efficiency * efficiency
* if data.physics.on_ground.is_some() { * if data.physics.on_ground.is_some() {
1.0 1.0
} else if data.physics.in_liquid().is_some() {
0.4
} else { } else {
0.2 0.2
} }
@ -1098,9 +1100,22 @@ pub fn handle_jump(
_update: &mut StateUpdate, _update: &mut StateUpdate,
strength: f32, strength: f32,
) -> bool { ) -> bool {
(input_is_pressed(data, InputKind::Jump) && data.physics.on_ground.is_some()) input_is_pressed(data, InputKind::Jump)
.then(|| data.body.jump_impulse()) .then(|| data.body.jump_impulse())
.flatten() .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| { .map(|impulse| {
output_events.emit_local(LocalEvent::Jump( output_events.emit_local(LocalEvent::Jump(
data.entity, data.entity,

View File

@ -152,16 +152,23 @@ impl<'a> AgentData<'a> {
..self.traversal_config ..self.traversal_config
}, },
) { ) {
controller.inputs.move_dir = self.traverse(controller, bearing, speed * speed_multiplier);
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;
true true
} else { } else {
false false
} }
} }
fn traverse(&self, controller: &mut Controller, bearing: Vec3<f32>, 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) { pub fn jump_if(&self, condition: bool, controller: &mut Controller) {
if condition { if condition {
controller.push_basic_input(InputKind::Jump); controller.push_basic_input(InputKind::Jump);
@ -265,12 +272,9 @@ impl<'a> AgentData<'a> {
..self.traversal_config ..self.traversal_config
}, },
) { ) {
controller.inputs.move_dir = self.traverse(controller, bearing, speed.min(speed_factor));
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) self.jump_if(self.traversal_config.can_fly, controller);
* speed.min(speed_factor);
self.jump_if(bearing.z > 1.5 || self.traversal_config.can_fly, controller);
controller.inputs.climb = Some(comp::Climb::Up); controller.inputs.climb = Some(comp::Climb::Up);
//.filter(|_| bearing.z > 0.1 || self.physics_state.in_liquid().is_some());
let height_offset = bearing.z let height_offset = bearing.z
+ if self.traversal_config.can_fly { + 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); let dist_sqrd = self.pos.0.distance_squared(tgt_pos.0);
controller.inputs.move_dir = bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) self.traverse(
* speed.min(0.2 + (dist_sqrd - AVG_FOLLOW_DIST.powi(2)) / 8.0); controller,
self.jump_if(bearing.z > 1.5, controller); bearing,
controller.inputs.move_z = bearing.z; speed.min(0.2 + (dist_sqrd - AVG_FOLLOW_DIST.powi(2)) / 8.0),
);
} }
} }
@ -617,10 +622,7 @@ impl<'a> AgentData<'a> {
..self.traversal_config ..self.traversal_config
}, },
) { ) {
controller.inputs.move_dir = bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) self.traverse(controller, bearing, speed.min(MAX_FLEE_SPEED));
* speed.min(MAX_FLEE_SPEED);
self.jump_if(bearing.z > 1.5, controller);
controller.inputs.move_z = bearing.z;
} }
} }