diff --git a/assets/common/manifests/ship_manifest.ron b/assets/common/manifests/ship_manifest.ron index 98d8a1ca48..344306f506 100644 --- a/assets/common/manifests/ship_manifest.ron +++ b/assets/common/manifests/ship_manifest.ron @@ -199,16 +199,16 @@ ), Carriage: ( bone0: ( - offset: (-4.5, -6.5, -0.5), + offset: (-4.5, -7.0, -0.5), central: ("carriage.structure"), ), bone1: ( - offset: (0.0, 0.0, 0.0), - central: ("empty"), + offset: (-2.0, -5.0, -2.0), + central: ("carriage.axle"), ), bone2: ( - offset: (0.0, 0.0, 0.0), - central: ("empty"), + offset: (-2.0, -5.0, -2.0), + central: ("carriage.axle"), ), bone3: ( offset: (0.0, 0.0, 0.0), diff --git a/assets/common/voxel/carriage/axle.vox b/assets/common/voxel/carriage/axle.vox new file mode 100644 index 0000000000..e8fc9cf8f7 --- /dev/null +++ b/assets/common/voxel/carriage/axle.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:214fff18f7ab927215d002b122303874697c1290d9d4626a46d2f0c0f81d4172 +size 1192 diff --git a/assets/common/voxel/carriage/prop.vox b/assets/common/voxel/carriage/prop.vox deleted file mode 100644 index e3747c02c9..0000000000 --- a/assets/common/voxel/carriage/prop.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bd4854e224023f76d93bc5f595bcf81940061b797f8d5ef6e9bd2af687a7899d -size 1200 diff --git a/assets/common/voxel/carriage/rudder.vox b/assets/common/voxel/carriage/rudder.vox deleted file mode 100644 index bf59b76a74..0000000000 --- a/assets/common/voxel/carriage/rudder.vox +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6019cd971b4cd79445f23be0e53b2d5d71b1993cd5fcb7b16fc09fa520167de8 -size 1240 diff --git a/assets/common/voxel/carriage/structure.vox b/assets/common/voxel/carriage/structure.vox index 2ab2284187..3ecbf70875 100644 --- a/assets/common/voxel/carriage/structure.vox +++ b/assets/common/voxel/carriage/structure.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5094f74957ae008cbbfe98c945c7b0bf3e65745ec51b2dd5401803990e466cd -size 2448 +oid sha256:f22fb1ea1c6cd2cb3a59a21c5b267635f08dfcca9f342b5f575a43e27a4fda98 +size 2256 diff --git a/common/src/comp/body/ship.rs b/common/src/comp/body/ship.rs index a75d672e8e..f0ba0470d3 100644 --- a/common/src/comp/body/ship.rs +++ b/common/src/comp/body/ship.rs @@ -19,7 +19,13 @@ pub const ALL_BODIES: [Body; 6] = [ ]; pub const ALL_AIRSHIPS: [Body; 2] = [Body::DefaultAirship, Body::AirBalloon]; -pub const ALL_SHIPS: [Body; 5] = [Body::SailBoat, Body::Galleon, Body::Skiff, Body::Submarine, Body::Carriage]; +pub const ALL_SHIPS: [Body; 5] = [ + Body::SailBoat, + Body::Galleon, + Body::Skiff, + Body::Submarine, + Body::Carriage, +]; make_case_elim!( body, @@ -114,7 +120,7 @@ impl Body { Body::Submarine => Density(WATER_DENSITY), // Neutrally buoyant Body::Carriage => Density(WATER_DENSITY * 0.5), _ => Density(AIR_DENSITY * 0.95 + WATER_DENSITY * 0.05), /* Most boats should be very - * buoyant */ + * buoyant */ } } @@ -130,6 +136,8 @@ impl Body { !self.can_fly() && !matches!(self, Body::Carriage) // TODO: Differentiate this more carefully } + pub fn has_wheels(&self) -> bool { matches!(self, Body::Carriage) } + pub fn make_collider(&self) -> Collider { match self.manifest_entry() { Some(manifest_entry) => Collider::Voxel { diff --git a/common/src/comp/phys.rs b/common/src/comp/phys.rs index 4257d04301..31282be1f9 100644 --- a/common/src/comp/phys.rs +++ b/common/src/comp/phys.rs @@ -63,7 +63,6 @@ pub struct PreviousPhysCache { pub origins: Option<(Vec2, Vec2)>, pub pos: Option, pub ori: Quaternion, - pub pos_interp: Option, } impl Component for PreviousPhysCache { diff --git a/common/src/states/behavior.rs b/common/src/states/behavior.rs index a309be7607..e2225dbb45 100644 --- a/common/src/states/behavior.rs +++ b/common/src/states/behavior.rs @@ -5,8 +5,8 @@ use crate::{ item::{tool::AbilityMap, MaterialStatManifest}, ActiveAbilities, Beam, Body, CharacterActivity, CharacterState, Combo, ControlAction, Controller, ControllerInputs, Density, Energy, Health, InputAttr, InputKind, Inventory, - InventoryAction, Mass, Melee, Ori, PhysicsState, Pos, Scale, SkillSet, Stance, StateUpdate, - Stats, Vel, PreviousPhysCache, + InventoryAction, Mass, Melee, Ori, PhysicsState, Pos, PreviousPhysCache, Scale, SkillSet, + Stance, StateUpdate, Stats, Vel, }, link::Is, mounting::{Rider, VolumeRider}, diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 86befb7ba9..a482f16a06 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -21,7 +21,7 @@ use crate::{ event::{LocalEvent, ServerEvent}, outcome::Outcome, states::{behavior::JoinData, utils::CharacterState::Idle, *}, - terrain::{TerrainGrid, UnlockKind}, + terrain::{Block, TerrainGrid, UnlockKind}, util::Dir, vol::ReadVol, }; @@ -146,7 +146,7 @@ impl Body { quadruped_low::Species::Deadwood => 140.0, quadruped_low::Species::Mossdrake => 100.0, }, - Body::Ship(ship::Body::Carriage) => 350.0, + Body::Ship(ship::Body::Carriage) => 200.0, Body::Ship(_) => 0.0, Body::Arthropod(arthropod) => match arthropod.species { arthropod::Species::Tarantula => 135.0, @@ -221,7 +221,7 @@ impl Body { quadruped_low::Species::Mossdrake => 1.7, _ => 2.0, }, - Body::Ship(ship::Body::Carriage) => 0.6, + Body::Ship(ship::Body::Carriage) => 0.04, Body::Ship(ship) if ship.has_water_thrust() => 5.0 / self.dimensions().y, Body::Ship(_) => 6.0 / self.dimensions().y, Body::Arthropod(_) => 3.5, @@ -589,11 +589,26 @@ pub fn handle_orientation( (a.to_quat().into_vec4() - b.to_quat().into_vec4()).reduce(|a, b| a.abs() + b.abs()) } - let pitch = if matches!(data.body, Body::Ship(ship::Body::Carriage)) { - let change = (data.pos.0 - data.previous_physics.and_then(|p| p.pos_interp).unwrap_or(*data.pos).0) / data.dt.0; - change.z / change.xy().magnitude().max(1.0) + let (tilt_ori, efficiency) = if let Body::Ship(ship) = data.body && ship.has_wheels() && data.physics.on_ground.is_some() { + let height_at = |rpos| data + .terrain + .ray( + data.pos.0 + rpos + Vec3::unit_z() * 4.0, + data.pos.0 + rpos - Vec3::unit_z() * 4.0, + ) + .until(Block::is_solid) + .cast() + .0; + + let x_diff = (height_at(data.ori.to_horizontal().right().to_vec() * 3.0) - height_at(data.ori.to_horizontal().right().to_vec() * -3.0)) / 10.0; + let y_diff = (height_at(data.ori.to_horizontal().look_dir().to_vec() * -4.5) - height_at(data.ori.to_horizontal().look_dir().to_vec() * 4.5)) / 10.0; + + ( + Quaternion::rotation_y(x_diff.atan()) * Quaternion::rotation_x(y_diff.atan()), + (data.vel.0 - data.physics.ground_vel).dot(data.ori.to_horizontal().look_dir().to_vec()).max(3.0) * efficiency, + ) } else { - 0.0 + (Quaternion::identity(), efficiency) }; // Direction is set to the override if one is provided, else if entity is @@ -611,7 +626,7 @@ pub fn handle_orientation( Dir::from_unnormalized(data.inputs.move_dir.into()) .map_or_else(|| to_horizontal_fast(data.ori), |dir| dir.into()) } - .pitched_up(pitch); + .rotated(tilt_ori); // unit is multiples of 180° let half_turns_per_tick = data.body.base_ori_rate() / data.scale.map_or(1.0, |s| s.0.sqrt()) * efficiency diff --git a/common/systems/src/character_behavior.rs b/common/systems/src/character_behavior.rs index 8e0b2ea878..b6d8c1a392 100644 --- a/common/systems/src/character_behavior.rs +++ b/common/systems/src/character_behavior.rs @@ -10,7 +10,7 @@ use common::{ inventory::item::{tool::AbilityMap, MaterialStatManifest}, ActiveAbilities, Beam, Body, CharacterActivity, CharacterState, Combo, Controller, Density, Energy, Health, Inventory, InventoryManip, Mass, Melee, Ori, PhysicsState, Poise, Pos, - Scale, SkillSet, Stance, StateUpdate, Stats, Vel, PreviousPhysCache, + PreviousPhysCache, Scale, SkillSet, Stance, StateUpdate, Stats, Vel, }, event::{EventBus, LocalEvent, ServerEvent}, link::Is, diff --git a/common/systems/src/phys.rs b/common/systems/src/phys.rs index 0b07405591..00ad521ea6 100644 --- a/common/systems/src/phys.rs +++ b/common/systems/src/phys.rs @@ -218,7 +218,6 @@ impl<'a> PhysicsData<'a> { origins: None, pos: None, ori: Quaternion::identity(), - pos_interp: None, }); } @@ -745,9 +744,6 @@ impl<'a> PhysicsData<'a> { // it did not work (investigate root cause?) previous_phys_cache.pos = Some(*pos); previous_phys_cache.ori = ori.to_quat(); - previous_phys_cache.pos_interp = Some(Pos( - previous_phys_cache.pos_interp.unwrap_or(*pos).0 * 0.85 + pos.0 * 0.15, - )); } drop(guard); } diff --git a/voxygen/anim/src/ship/idle.rs b/voxygen/anim/src/ship/idle.rs index 501cf1d224..2fc787c12b 100644 --- a/voxygen/anim/src/ship/idle.rs +++ b/voxygen/anim/src/ship/idle.rs @@ -45,10 +45,12 @@ impl Animation for IdleAnimation { next.bone0.position = Vec3::new(s_a.bone0.0, s_a.bone0.1, s_a.bone0.2); next.bone1.position = Vec3::new(s_a.bone1.0, s_a.bone1.1, s_a.bone1.2); - next.bone1.orientation = Quaternion::rotation_y(acc_vel * 0.8); + next.bone1.orientation = Quaternion::rotation_z(s_a.bone1_ori) + * Quaternion::rotation_y(acc_vel * s_a.bone_rotation_rate); next.bone2.position = Vec3::new(s_a.bone2.0, s_a.bone2.1, s_a.bone2.2); - next.bone2.orientation = Quaternion::rotation_y(-acc_vel * 0.8); + next.bone2.orientation = Quaternion::rotation_z(s_a.bone2_ori) + * Quaternion::rotation_y(-acc_vel * s_a.bone_rotation_rate); next.bone3.position = Vec3::new(s_a.bone3.0, s_a.bone3.1, s_a.bone3.2); next.bone3.orientation = Quaternion::rotation_z(tilt * 25.0); diff --git a/voxygen/anim/src/ship/mod.rs b/voxygen/anim/src/ship/mod.rs index 70bcbe2d2d..6d12dbee83 100644 --- a/voxygen/anim/src/ship/mod.rs +++ b/voxygen/anim/src/ship/mod.rs @@ -70,6 +70,9 @@ pub struct SkeletonAttr { bone1: (f32, f32, f32), bone2: (f32, f32, f32), bone3: (f32, f32, f32), + bone1_ori: f32, + bone2_ori: f32, + bone_rotation_rate: f32, bone1_prop_trail_offset: Option, bone2_prop_trail_offset: Option, } @@ -92,6 +95,9 @@ impl Default for SkeletonAttr { bone1: (0.0, 0.0, 0.0), bone2: (0.0, 0.0, 0.0), bone3: (0.0, 0.0, 0.0), + bone1_ori: 0.0, + bone2_ori: 0.0, + bone_rotation_rate: 0.0, bone1_prop_trail_offset: None, bone2_prop_trail_offset: None, } @@ -119,7 +125,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { Galleon => (0.0, 0.0, 0.0), Skiff => (0.0, 0.0, 0.0), Submarine => (0.0, -15.0, 3.5), - Carriage => (0.0, 0.0, 0.0), + Carriage => (0.0, 3.0, 2.0), Volume => (0.0, 0.0, 0.0), }, bone2: match body { @@ -129,7 +135,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { Galleon => (0.0, 0.0, 0.0), Skiff => (0.0, 0.0, 0.0), Submarine => (0.0, 0.0, 0.0), - Carriage => (0.0, 0.0, 0.0), + Carriage => (0.0, -3.0, 2.0), Volume => (0.0, 0.0, 0.0), }, bone3: match body { @@ -142,6 +148,18 @@ impl<'a> From<&'a Body> for SkeletonAttr { Carriage => (0.0, 0.0, 0.0), Volume => (0.0, 0.0, 0.0), }, + bone1_ori: match body { + Carriage => std::f32::consts::PI * 0.5, + _ => 0.0, + }, + bone2_ori: match body { + Carriage => std::f32::consts::PI * -0.5, + _ => 0.0, + }, + bone_rotation_rate: match body { + Carriage => 0.25, + _ => 0.8, + }, bone1_prop_trail_offset: match body { DefaultAirship => Some(8.5), Submarine => Some(3.5),