Rebalanced masses, dimensions, swim thrusts, and made various improvements to water movement that help with gameplay and pathfinding. Also fixed swimming animations for many creatures.

This commit is contained in:
Joshua Barretto 2023-05-17 14:01:03 +01:00
parent 5988237b3d
commit 96bf86dae0
6 changed files with 161 additions and 137 deletions

View File

@ -261,8 +261,7 @@ impl Body {
Body::BirdMedium(_) => 700.0, Body::BirdMedium(_) => 700.0,
Body::BirdLarge(_) => 2_200.0, Body::BirdLarge(_) => 2_200.0,
// based on its mass divided by the volume of a bird scaled up to the size of the dragon Body::Dragon(_) => 5_000.0,
Body::Dragon(_) => 3_700.0,
Body::Golem(_) => WATER_DENSITY * 2.5, Body::Golem(_) => WATER_DENSITY * 2.5,
Body::Humanoid(_) => HUMAN_DENSITY, Body::Humanoid(_) => HUMAN_DENSITY,
@ -312,7 +311,7 @@ impl Body {
bird_medium::Species::Puffin => 2.0, bird_medium::Species::Puffin => 2.0,
bird_medium::Species::Toucan => 4.5, bird_medium::Species::Toucan => 4.5,
}, },
Body::BirdLarge(_) => 100.0, Body::BirdLarge(_) => 250.0,
Body::Dragon(_) => 20_000.0, Body::Dragon(_) => 20_000.0,
Body::FishMedium(_) => 5.0, Body::FishMedium(_) => 5.0,
Body::FishSmall(_) => 1.0, Body::FishSmall(_) => 1.0,
@ -337,23 +336,23 @@ impl Body {
// alligator or smaller, so whatever // alligator or smaller, so whatever
quadruped_low::Species::Crocodile => 360.0, quadruped_low::Species::Crocodile => 360.0,
quadruped_low::Species::SeaCrocodile => 410.0, quadruped_low::Species::SeaCrocodile => 410.0,
quadruped_low::Species::Deadwood => 150.0, quadruped_low::Species::Deadwood => 200.0,
quadruped_low::Species::Monitor => 200.0, quadruped_low::Species::Monitor => 200.0,
quadruped_low::Species::Pangolin => 300.0, quadruped_low::Species::Pangolin => 300.0,
quadruped_low::Species::Salamander => 350.0, quadruped_low::Species::Salamander => 350.0,
quadruped_low::Species::Elbst => 65.0, quadruped_low::Species::Elbst => 350.0,
quadruped_low::Species::Tortoise => 300.0, quadruped_low::Species::Tortoise => 300.0,
quadruped_low::Species::Lavadrake => 500.0, quadruped_low::Species::Lavadrake => 700.0,
quadruped_low::Species::Icedrake => 500.0, quadruped_low::Species::Icedrake => 700.0,
quadruped_low::Species::Mossdrake => 500.0, quadruped_low::Species::Mossdrake => 700.0,
quadruped_low::Species::Rocksnapper => 450.0, quadruped_low::Species::Rocksnapper => 450.0,
quadruped_low::Species::Rootsnapper => 450.0, quadruped_low::Species::Rootsnapper => 450.0,
quadruped_low::Species::Reefsnapper => 450.0, quadruped_low::Species::Reefsnapper => 450.0,
quadruped_low::Species::Maneater => 350.0, quadruped_low::Species::Maneater => 350.0,
quadruped_low::Species::Sandshark => 450.0, quadruped_low::Species::Sandshark => 450.0,
quadruped_low::Species::Hakulaq => 300.0, quadruped_low::Species::Hakulaq => 400.0,
quadruped_low::Species::Dagon => 400.0, quadruped_low::Species::Dagon => 600.0,
quadruped_low::Species::Basilisk => 500.0, quadruped_low::Species::Basilisk => 800.0,
}, },
Body::QuadrupedMedium(body) => match body.species { Body::QuadrupedMedium(body) => match body.species {
quadruped_medium::Species::Bear => 500.0, // ~✅ (350-700 kg) quadruped_medium::Species::Bear => 500.0, // ~✅ (350-700 kg)
@ -361,12 +360,15 @@ impl Body {
quadruped_medium::Species::Deer => 80.0, quadruped_medium::Species::Deer => 80.0,
quadruped_medium::Species::Donkey => 200.0, quadruped_medium::Species::Donkey => 200.0,
quadruped_medium::Species::Highland => 200.0, quadruped_medium::Species::Highland => 200.0,
quadruped_medium::Species::Horse => 500.0, // ~✅ quadruped_medium::Species::Horse => 300.0, // ~✅
quadruped_medium::Species::Kelpie => 200.0, quadruped_medium::Species::Kelpie => 250.0,
quadruped_medium::Species::Lion => 170.0, // ~✅ (110-225 kg) quadruped_medium::Species::Lion => 170.0, // ~✅ (110-225 kg)
quadruped_medium::Species::Panda => 200.0, quadruped_medium::Species::Panda => 200.0,
quadruped_medium::Species::Saber => 130.0, quadruped_medium::Species::Saber => 130.0,
quadruped_medium::Species::Yak => 200.0, quadruped_medium::Species::Yak => 200.0,
quadruped_medium::Species::Dreadhorn => 500.0,
quadruped_medium::Species::Mammoth => 1500.0,
quadruped_medium::Species::Catoblepas => 300.0,
_ => 200.0, _ => 200.0,
}, },
Body::QuadrupedSmall(body) => match body.species { Body::QuadrupedSmall(body) => match body.species {
@ -401,9 +403,9 @@ impl Body {
Body::Theropod(body) => match body.species { Body::Theropod(body) => match body.species {
// for reference, elephants are in the range of 2.6-6.9 tons // for reference, elephants are in the range of 2.6-6.9 tons
// and Tyrannosaurus rex were ~8.4-14 tons // and Tyrannosaurus rex were ~8.4-14 tons
theropod::Species::Archaeos => 13_000.0, theropod::Species::Archaeos => 8_000.0,
theropod::Species::Ntouka => 13_000.0, theropod::Species::Ntouka => 8_000.0,
theropod::Species::Odonto => 13_000.0, theropod::Species::Odonto => 8_000.0,
theropod::Species::Dodarock => 700.0, theropod::Species::Dodarock => 700.0,
theropod::Species::Sandraptor => 500.0, theropod::Species::Sandraptor => 500.0,
theropod::Species::Snowraptor => 500.0, theropod::Species::Snowraptor => 500.0,
@ -460,7 +462,7 @@ impl Body {
| bird_large::Species::FrostWyvern | bird_large::Species::FrostWyvern
| bird_large::Species::CloudWyvern | bird_large::Species::CloudWyvern
| bird_large::Species::SeaWyvern | bird_large::Species::SeaWyvern
| bird_large::Species::WealdWyvern => Vec3::new(4.0, 9.0, 4.5), | bird_large::Species::WealdWyvern => Vec3::new(2.5, 9.0, 4.5),
_ => Vec3::new(2.0, 6.0, 3.5), _ => Vec3::new(2.0, 6.0, 3.5),
}, },
Body::Dragon(_) => Vec3::new(16.0, 10.0, 16.0), Body::Dragon(_) => Vec3::new(16.0, 10.0, 16.0),
@ -480,14 +482,14 @@ impl Body {
quadruped_medium::Species::Akhlut => Vec3::new(2.5, 7.0, 3.0), quadruped_medium::Species::Akhlut => Vec3::new(2.5, 7.0, 3.0),
quadruped_medium::Species::Barghest => Vec3::new(2.0, 4.4, 2.7), quadruped_medium::Species::Barghest => Vec3::new(2.0, 4.4, 2.7),
quadruped_medium::Species::Bear => Vec3::new(2.0, 3.8, 3.0), quadruped_medium::Species::Bear => Vec3::new(2.0, 3.8, 3.0),
quadruped_medium::Species::Catoblepas => Vec3::new(2.0, 4.0, 2.9), quadruped_medium::Species::Catoblepas => Vec3::new(2.0, 4.0, 2.3),
quadruped_medium::Species::Cattle => Vec3::new(2.0, 3.6, 2.4), quadruped_medium::Species::Cattle => Vec3::new(2.0, 3.6, 2.4),
quadruped_medium::Species::Deer => Vec3::new(2.0, 3.0, 2.2), quadruped_medium::Species::Deer => Vec3::new(2.0, 3.0, 2.2),
quadruped_medium::Species::Dreadhorn => Vec3::new(3.5, 6.0, 4.0), quadruped_medium::Species::Dreadhorn => Vec3::new(3.5, 6.0, 2.6),
quadruped_medium::Species::Frostfang => Vec3::new(1.5, 3.0, 1.5), quadruped_medium::Species::Frostfang => Vec3::new(1.5, 3.0, 1.5),
quadruped_medium::Species::Grolgar => Vec3::new(2.0, 4.0, 2.0), quadruped_medium::Species::Grolgar => Vec3::new(2.0, 4.0, 2.0),
quadruped_medium::Species::Highland => Vec3::new(2.0, 3.6, 2.4), quadruped_medium::Species::Highland => Vec3::new(2.0, 3.6, 2.4),
quadruped_medium::Species::Horse => Vec3::new(2.0, 3.0, 2.4), quadruped_medium::Species::Horse => Vec3::new(1.6, 3.0, 2.4),
quadruped_medium::Species::Lion => Vec3::new(2.0, 3.3, 2.0), quadruped_medium::Species::Lion => Vec3::new(2.0, 3.3, 2.0),
quadruped_medium::Species::Moose => Vec3::new(2.0, 4.0, 2.5), quadruped_medium::Species::Moose => Vec3::new(2.0, 4.0, 2.5),
quadruped_medium::Species::Bristleback => Vec3::new(2.0, 3.0, 2.0), quadruped_medium::Species::Bristleback => Vec3::new(2.0, 3.0, 2.0),
@ -500,7 +502,7 @@ impl Body {
quadruped_medium::Species::Llama => Vec3::new(2.0, 2.5, 2.6), quadruped_medium::Species::Llama => Vec3::new(2.0, 2.5, 2.6),
quadruped_medium::Species::Alpaca => Vec3::new(2.0, 2.0, 2.0), quadruped_medium::Species::Alpaca => Vec3::new(2.0, 2.0, 2.0),
quadruped_medium::Species::Camel => Vec3::new(2.0, 4.0, 3.5), quadruped_medium::Species::Camel => Vec3::new(2.0, 4.0, 3.5),
quadruped_medium::Species::Wolf => Vec3::new(1.7, 3.0, 1.8), quadruped_medium::Species::Wolf => Vec3::new(1.25, 3.0, 1.8),
// FIXME: We really shouldn't be doing wildcards here // FIXME: We really shouldn't be doing wildcards here
_ => Vec3::new(2.0, 3.0, 2.0), _ => Vec3::new(2.0, 3.0, 2.0),
}, },
@ -519,8 +521,9 @@ impl Body {
quadruped_low::Species::Hakulaq => Vec3::new(1.8, 3.0, 2.0), quadruped_low::Species::Hakulaq => Vec3::new(1.8, 3.0, 2.0),
quadruped_low::Species::Dagon => Vec3::new(3.0, 6.0, 2.0), quadruped_low::Species::Dagon => Vec3::new(3.0, 6.0, 2.0),
quadruped_low::Species::Icedrake => Vec3::new(2.0, 5.5, 2.5), quadruped_low::Species::Icedrake => Vec3::new(2.0, 5.5, 2.5),
quadruped_low::Species::Lavadrake => Vec3::new(2.0, 4.7, 2.5), quadruped_low::Species::Lavadrake => Vec3::new(2.0, 5.5, 2.5),
quadruped_low::Species::Maneater => Vec3::new(2.5, 3.7, 4.0), quadruped_low::Species::Mossdrake => Vec3::new(2.0, 5.5, 2.5),
quadruped_low::Species::Maneater => Vec3::new(2.0, 3.7, 4.0),
quadruped_low::Species::Monitor => Vec3::new(1.4, 3.2, 1.3), quadruped_low::Species::Monitor => Vec3::new(1.4, 3.2, 1.3),
quadruped_low::Species::Pangolin => Vec3::new(1.0, 2.6, 1.1), quadruped_low::Species::Pangolin => Vec3::new(1.0, 2.6, 1.1),
quadruped_low::Species::Rocksnapper => Vec3::new(2.5, 3.5, 2.9), quadruped_low::Species::Rocksnapper => Vec3::new(2.5, 3.5, 2.9),
@ -531,14 +534,13 @@ impl Body {
quadruped_low::Species::Salamander => Vec3::new(1.7, 4.0, 1.3), quadruped_low::Species::Salamander => Vec3::new(1.7, 4.0, 1.3),
quadruped_low::Species::Elbst => Vec3::new(1.7, 4.0, 1.3), quadruped_low::Species::Elbst => Vec3::new(1.7, 4.0, 1.3),
quadruped_low::Species::Tortoise => Vec3::new(1.7, 2.7, 1.5), quadruped_low::Species::Tortoise => Vec3::new(1.7, 2.7, 1.5),
quadruped_low::Species::Mossdrake => Vec3::new(2.0, 4.7, 2.5),
_ => Vec3::new(1.0, 1.6, 1.3), _ => Vec3::new(1.0, 1.6, 1.3),
}, },
Body::Ship(ship) => ship.dimensions(), Body::Ship(ship) => ship.dimensions(),
Body::Theropod(body) => match body.species { Body::Theropod(body) => match body.species {
theropod::Species::Archaeos => Vec3::new(4.0, 8.5, 8.0), theropod::Species::Archaeos => Vec3::new(4.5, 8.5, 8.0),
theropod::Species::Ntouka => Vec3::new(4.0, 9.0, 6.6), theropod::Species::Ntouka => Vec3::new(4.5, 9.0, 6.6),
theropod::Species::Odonto => Vec3::new(4.0, 8.0, 6.6), theropod::Species::Odonto => Vec3::new(4.5, 8.0, 6.6),
theropod::Species::Dodarock => Vec3::new(2.0, 3.0, 2.6), theropod::Species::Dodarock => Vec3::new(2.0, 3.0, 2.6),
theropod::Species::Sandraptor => Vec3::new(2.0, 3.0, 2.6), theropod::Species::Sandraptor => Vec3::new(2.0, 3.0, 2.6),
theropod::Species::Snowraptor => Vec3::new(2.0, 3.0, 2.6), theropod::Species::Snowraptor => Vec3::new(2.0, 3.0, 2.6),

View File

@ -66,8 +66,8 @@ impl Body {
match self { match self {
Body::DefaultAirship | Body::Volume => Vec3::new(25.0, 50.0, 40.0), Body::DefaultAirship | Body::Volume => Vec3::new(25.0, 50.0, 40.0),
Body::AirBalloon => Vec3::new(25.0, 50.0, 40.0), Body::AirBalloon => Vec3::new(25.0, 50.0, 40.0),
Body::SailBoat => Vec3::new(13.0, 31.0, 3.0), Body::SailBoat => Vec3::new(6.0, 17.0, 6.0),
Body::Galleon => Vec3::new(13.0, 32.0, 3.0), Body::Galleon => Vec3::new(7.0, 32.0, 10.0),
} }
} }
@ -100,7 +100,7 @@ impl Body {
pub fn density(&self) -> Density { pub fn density(&self) -> Density {
match self { match self {
Body::DefaultAirship | Body::AirBalloon | Body::Volume => Density(AIR_DENSITY), Body::DefaultAirship | Body::AirBalloon | Body::Volume => Density(AIR_DENSITY),
_ => Density(AIR_DENSITY * 0.2 + WATER_DENSITY * 0.8), // Most boats should be buoyant _ => Density(AIR_DENSITY * 0.75 + WATER_DENSITY * 0.25), // Most boats should be buoyant
} }
} }

View File

@ -220,7 +220,7 @@ impl Body {
quadruped_low::Species::Mossdrake => 1.7, quadruped_low::Species::Mossdrake => 1.7,
_ => 2.0, _ => 2.0,
}, },
Body::Ship(ship) if ship.has_water_thrust() => 0.1, Body::Ship(ship) if ship.has_water_thrust() => 0.2,
Body::Ship(_) => 0.12, Body::Ship(_) => 0.12,
Body::Arthropod(_) => 3.5, Body::Arthropod(_) => 3.5,
} }
@ -228,33 +228,46 @@ impl Body {
/// Returns thrust force if the body type can swim, otherwise None /// Returns thrust force if the body type can swim, otherwise None
pub fn swim_thrust(&self) -> Option<f32> { pub fn swim_thrust(&self) -> Option<f32> {
// Swim thrust is proportional to the frontal area of the creature, since we
// assume that strength roughly scales according to square laws. Also,
// it happens to make balancing against drag much simpler.
let front_profile = self.dimensions().x * self.dimensions().z;
Some(
match self { match self {
Body::Object(_) => None, Body::Object(_) => return None,
Body::ItemDrop(_) => None, Body::ItemDrop(_) => return None,
Body::BipedLarge(_) | Body::Golem(_) => Some(3000.0 * self.mass().0), Body::Ship(ship) if ship.has_water_thrust() => 0.1 * self.mass().0,
Body::BipedSmall(_) => Some(1000.0 * self.mass().0), Body::Ship(_) => return None,
Body::BirdMedium(_) => Some(1200.0 * self.mass().0), Body::BipedLarge(_) => 120.0 * self.mass().0,
Body::BirdLarge(_) => Some(750.0 * self.mass().0), Body::Golem(_) => 0.5 * self.mass().0,
Body::FishMedium(_) => Some(50.0 * self.mass().0), Body::BipedSmall(_) => 1000.0 * self.mass().0,
Body::FishSmall(_) => Some(50.0 * self.mass().0), Body::BirdMedium(_) => 1500.0 * self.mass().0,
Body::Dragon(_) => Some(3000.0 * self.mass().0), Body::BirdLarge(_) => 35.0 * self.mass().0,
Body::Humanoid(_) => Some(2500.0 * self.mass().0), Body::FishMedium(_) => 75.0 * self.mass().0,
Body::FishSmall(_) => 120.0 * self.mass().0,
Body::Dragon(_) => 0.5 * self.mass().0,
// Humanoids are a bit different: we try to give them thrusts that result in similar
// speeds for gameplay reasons
Body::Humanoid(_) => 4_000_000.0 / self.mass().0,
Body::Theropod(body) => match body.species { Body::Theropod(body) => match body.species {
theropod::Species::Sandraptor theropod::Species::Sandraptor
| theropod::Species::Snowraptor | theropod::Species::Snowraptor
| theropod::Species::Sunlizard | theropod::Species::Sunlizard
| theropod::Species::Woodraptor | theropod::Species::Woodraptor
| theropod::Species::Dodarock | theropod::Species::Dodarock
| theropod::Species::Yale => Some(2500.0 * self.mass().0), | theropod::Species::Axebeak
_ => Some(100.0 * self.mass().0), | theropod::Species::Yale => 700.0 * self.mass().0,
_ => 3.0 * self.mass().0,
}, },
Body::QuadrupedLow(_) => Some(2500.0 * self.mass().0), Body::QuadrupedLow(_) => 120.0 * self.mass().0,
Body::QuadrupedMedium(_) => Some(3000.0 * self.mass().0), Body::QuadrupedMedium(body) => match body.species {
Body::QuadrupedSmall(_) => Some(3000.0 * self.mass().0), quadruped_medium::Species::Mammoth => 75.0 * self.mass().0,
Body::Ship(ship) if ship.has_water_thrust() => Some(3500.0 * self.mass().0), _ => 500.0 * self.mass().0,
Body::Ship(_) => None, },
Body::Arthropod(_) => Some(300.0 * self.mass().0), Body::QuadrupedSmall(_) => 1500.0 * self.mass().0,
} Body::Arthropod(_) => 300.0 * self.mass().0,
} * front_profile,
)
} }
/// Returns thrust force if the body type can fly, otherwise None /// Returns thrust force if the body type can fly, otherwise None
@ -371,7 +384,7 @@ pub fn handle_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f3
&& data.body.fly_thrust().is_some() && data.body.fly_thrust().is_some()
{ {
fly_move(data, update, efficiency); fly_move(data, update, efficiency);
} else if let Some(submersion) = (data.physics.on_ground.is_none() } else if let Some(submersion) = (data.physics.in_liquid().is_some()
&& data.body.swim_thrust().is_some()) && data.body.swim_thrust().is_some())
.then_some(submersion) .then_some(submersion)
.flatten() .flatten()
@ -645,19 +658,27 @@ fn swim_move(
fw * data.inputs.move_dir.dot(fw).max(0.0) fw * data.inputs.move_dir.dot(fw).max(0.0)
}; };
// Autoswim to stay afloat // Automatically tread water to stay afloat
let move_z = if submersion < 1.0 && data.inputs.move_z.abs() < f32::EPSILON { let move_z = if submersion < 1.0
(submersion - 0.1).max(0.0) && data.inputs.move_z.abs() < f32::EPSILON
&& data.physics.on_ground.is_none()
{
submersion.max(0.0) * 0.1
} else { } else {
data.inputs.move_z data.inputs.move_z
}; };
// Assume that feet/flippers get less efficient as we become less submerged
let move_z = move_z.min((submersion * 1.5 - 0.5).clamp(0.0, 1.0).powi(2));
update.vel.0 += Vec3::broadcast(data.dt.0) update.vel.0 += Vec3::broadcast(data.dt.0)
* Vec3::new(dir.x, dir.y, move_z) * Vec3::new(dir.x, dir.y, move_z)
.try_normalized() // TODO: Should probably be normalised, but creates odd discrepancies when treading water
.unwrap_or_default() // .try_normalized()
// .unwrap_or_default()
* water_accel * water_accel
* (submersion - 0.2).clamp(0.0, 1.0).powi(2); // Gives a good balance between submerged and surface speed
* (submersion * 3.0).clamp(0.0, 1.0);
true true
} else { } else {
@ -822,7 +843,8 @@ pub fn handle_climb(data: &JoinData<'_>, update: &mut StateUpdate) -> bool {
.map(|depth| depth > 1.0) .map(|depth| depth > 1.0)
.unwrap_or(false) .unwrap_or(false)
//&& update.vel.0.z < 0.0 //&& update.vel.0.z < 0.0
&& data.body.can_climb() // *All* entities can climb when in liquids, to let them get out of
&& (data.body.can_climb() || data.physics.in_liquid().is_some())
&& update.energy.current() > 1.0 && update.energy.current() > 1.0
{ {
update.character = CharacterState::Climb(climb::Data::create_adjusted_by_skills(data)); update.character = CharacterState::Climb(climb::Data::create_adjusted_by_skills(data));
@ -1104,17 +1126,19 @@ pub fn handle_jump(
.then(|| data.body.jump_impulse()) .then(|| data.body.jump_impulse())
.flatten() .flatten()
.and_then(|impulse| { .and_then(|impulse| {
if data.physics.on_ground.is_some() { if data.physics.in_liquid().is_some() {
Some(impulse) if data.physics.on_wall.is_some() {
} 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, // Allow entities to make a small jump when at the edge of a body of water,
// allowing them to path out of it // allowing them to path out of it
Some(impulse * 0.75) Some(impulse * 0.75)
} else { } else {
None None
} }
} else if data.physics.on_ground.is_some() {
Some(impulse)
} else {
None
}
}) })
.map(|impulse| { .map(|impulse| {
output_events.emit_local(LocalEvent::Jump( output_events.emit_local(LocalEvent::Jump(

View File

@ -1612,7 +1612,11 @@ fn box_voxel_collision<T: BaseVol<Vox = Block> + ReadVol>(
if on_ground.is_some() { if on_ground.is_some() {
physics_state.on_ground = on_ground; physics_state.on_ground = on_ground;
// If the space below us is free, then "snap" to the ground // If the space below us is free, then "snap" to the ground
} else if vel.0.z <= 0.0 && was_on_ground && block_snap && { } else if vel.0.z <= 0.0
&& was_on_ground
&& block_snap
&& physics_state.in_liquid().is_none()
&& {
//prof_span!("snap check"); //prof_span!("snap check");
collision_with( collision_with(
pos.0 - Vec3::unit_z() * 1.1, pos.0 - Vec3::unit_z() * 1.1,
@ -1622,7 +1626,8 @@ fn box_voxel_collision<T: BaseVol<Vox = Block> + ReadVol>(
z_range.clone(), z_range.clone(),
vel.0, vel.0,
) )
} { }
{
//prof_span!("snap!!"); //prof_span!("snap!!");
let snap_height = terrain let snap_height = terrain
.get(Vec3::new(pos.0.x, pos.0.y, pos.0.z - 0.1).map(|e| e.floor() as i32)) .get(Vec3::new(pos.0.x, pos.0.y, pos.0.z - 0.1).map(|e| e.floor() as i32))
@ -1715,6 +1720,32 @@ fn box_voxel_collision<T: BaseVol<Vox = Block> + ReadVol>(
physics_state.on_wall = on_wall; physics_state.on_wall = on_wall;
let fric_mod = read.stats.get(entity).map_or(1.0, |s| s.friction_modifier); let fric_mod = read.stats.get(entity).map_or(1.0, |s| s.friction_modifier);
physics_state.in_fluid = liquid
.map(|(kind, max_z)| {
// NOTE: assumes min_z == 0.0
let depth = max_z - pos.0.z;
// This is suboptimal because it doesn't check for true depth,
// so it can cause problems for situations like swimming down
// a river and spawning or teleporting in(/to) water
let new_depth = physics_state.in_liquid().map_or(depth, |old_depth| {
(old_depth + old_pos.z - pos.0.z).max(depth)
});
Fluid::Liquid {
kind,
depth: new_depth,
vel: Vel::zero(),
}
})
.or_else(|| match physics_state.in_fluid {
Some(Fluid::Liquid { .. }) | None => Some(Fluid::Air {
elevation: pos.0.z,
vel: Vel::default(),
}),
fluid => fluid,
});
// skating (ski) // skating (ski)
if !vel.0.xy().is_approx_zero() if !vel.0.xy().is_approx_zero()
&& physics_state && physics_state
@ -1778,7 +1809,19 @@ fn box_voxel_collision<T: BaseVol<Vox = Block> + ReadVol>(
physics_state.skating_active = true; physics_state.skating_active = true;
vel.0 = Vec3::new(new_ground_speed.x, new_ground_speed.y, 0.0); vel.0 = Vec3::new(new_ground_speed.x, new_ground_speed.y, 0.0);
} else { } else {
let ground_fric = physics_state let ground_fric = if physics_state.in_liquid().is_some() {
// HACK:
// If we're in a liquid, radically reduce ground friction (i.e: assume that
// contact force is negligible due to buoyancy) Note that this might
// not be realistic for very dense entities (currently no entities in Veloren
// are sufficiently negatively buoyant for this to matter). We
// should really make friction be proportional to net downward force, but
// that means taking into account buoyancy which is a bit difficult to do here
// for now.
0.1
} else {
1.0
} * physics_state
.on_ground .on_ground
.map(|b| b.get_friction()) .map(|b| b.get_friction())
.unwrap_or(0.0); .unwrap_or(0.0);
@ -1794,32 +1837,6 @@ fn box_voxel_collision<T: BaseVol<Vox = Block> + ReadVol>(
} }
physics_state.skating_active = false; physics_state.skating_active = false;
} }
physics_state.in_fluid = liquid
.map(|(kind, max_z)| {
// NOTE: assumes min_z == 0.0
let depth = max_z - pos.0.z;
// This is suboptimal because it doesn't check for true depth,
// so it can cause problems for situations like swimming down
// a river and spawning or teleporting in(/to) water
let new_depth = physics_state.in_liquid().map_or(depth, |old_depth| {
(old_depth + old_pos.z - pos.0.z).max(depth)
});
Fluid::Liquid {
kind,
depth: new_depth,
vel: Vel::zero(),
}
})
.or_else(|| match physics_state.in_fluid {
Some(Fluid::Liquid { .. }) | None => Some(Fluid::Air {
elevation: pos.0.z,
vel: Vel::default(),
}),
fluid => fluid,
});
} }
fn voxel_collider_bounding_sphere( fn voxel_collider_bounding_sphere(

View File

@ -167,6 +167,9 @@ impl<'a> AgentData<'a> {
&& self.physics_state.on_wall.is_some(); && self.physics_state.on_wall.is_some();
self.jump_if(bearing.z > 1.5 || climbing_out_of_water, controller); self.jump_if(bearing.z > 1.5 || climbing_out_of_water, controller);
controller.inputs.move_z = bearing.z; controller.inputs.move_z = bearing.z;
if bearing.z > 0.0 {
controller.inputs.climb = Some(comp::Climb::Up);
}
} }
pub fn jump_if(&self, condition: bool, controller: &mut Controller) { pub fn jump_if(&self, condition: bool, controller: &mut Controller) {
@ -274,7 +277,6 @@ impl<'a> AgentData<'a> {
) { ) {
self.traverse(controller, bearing, speed.min(speed_factor)); self.traverse(controller, bearing, speed.min(speed_factor));
self.jump_if(self.traversal_config.can_fly, controller); self.jump_if(self.traversal_config.can_fly, controller);
controller.inputs.climb = Some(comp::Climb::Up);
let height_offset = bearing.z let height_offset = bearing.z
+ if self.traversal_config.can_fly { + if self.traversal_config.can_fly {

View File

@ -2275,8 +2275,8 @@ impl FigureMgr {
skeleton_attr, skeleton_attr,
) )
}, },
// Running // Swimming
(false, _, true) => anim::quadruped_small::RunAnimation::update_skeleton( (_, _, true) => anim::quadruped_small::RunAnimation::update_skeleton(
&QuadrupedSmallSkeleton::default(), &QuadrupedSmallSkeleton::default(),
( (
rel_vel.magnitude(), rel_vel.magnitude(),
@ -2307,13 +2307,6 @@ impl FigureMgr {
&mut state_animation_rate, &mut state_animation_rate,
skeleton_attr, skeleton_attr,
), ),
_ => anim::quadruped_small::IdleAnimation::update_skeleton(
&QuadrupedSmallSkeleton::default(),
time,
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
}; };
let target_bones = match &character { let target_bones = match &character {
CharacterState::ComboMelee(s) => { CharacterState::ComboMelee(s) => {
@ -2476,7 +2469,7 @@ impl FigureMgr {
) )
}, },
//Swimming //Swimming
(false, _, true) => anim::quadruped_medium::RunAnimation::update_skeleton( (_, _, true) => anim::quadruped_medium::RunAnimation::update_skeleton(
&QuadrupedMediumSkeleton::default(), &QuadrupedMediumSkeleton::default(),
( (
rel_vel.magnitude(), rel_vel.magnitude(),
@ -2501,13 +2494,6 @@ impl FigureMgr {
skeleton_attr, skeleton_attr,
) )
}, },
_ => anim::quadruped_medium::IdleAnimation::update_skeleton(
&QuadrupedMediumSkeleton::default(),
time,
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
}; };
let target_bones = match &character { let target_bones = match &character {
CharacterState::BasicMelee(s) => { CharacterState::BasicMelee(s) => {
@ -2851,7 +2837,7 @@ impl FigureMgr {
skeleton_attr, skeleton_attr,
), ),
// Swimming // Swimming
(false, _, true) => anim::quadruped_low::RunAnimation::update_skeleton( (_, _, true) => anim::quadruped_low::RunAnimation::update_skeleton(
&QuadrupedLowSkeleton::default(), &QuadrupedLowSkeleton::default(),
( (
rel_vel.magnitude(), rel_vel.magnitude(),
@ -2882,13 +2868,6 @@ impl FigureMgr {
&mut state_animation_rate, &mut state_animation_rate,
skeleton_attr, skeleton_attr,
), ),
_ => anim::quadruped_low::IdleAnimation::update_skeleton(
&QuadrupedLowSkeleton::default(),
time,
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
}; };
let target_bones = match &character { let target_bones = match &character {
CharacterState::BasicRanged(s) => { CharacterState::BasicRanged(s) => {