mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
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:
parent
5988237b3d
commit
96bf86dae0
@ -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),
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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(
|
||||||
|
@ -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 {
|
||||||
|
@ -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) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user