diff --git a/client/src/lib.rs b/client/src/lib.rs index 66fb721872..3328a81ade 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -1252,7 +1252,7 @@ impl Client { .map(|cs| { matches!( cs, - comp::CharacterState::GlideWield | comp::CharacterState::Glide(_) + comp::CharacterState::GlideWield(_) | comp::CharacterState::Glide(_) ) }); diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 86db71191b..b1b24591dd 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -53,7 +53,7 @@ pub enum CharacterState { Talk, Sneak, Glide(glide::Data), - GlideWield, + GlideWield(glide_wield::Data), /// A stunned state Stunned(stunned::Data), /// A basic blocking state @@ -180,7 +180,7 @@ impl CharacterState { | CharacterState::Equipping(_) | CharacterState::Dance | CharacterState::Glide(_) - | CharacterState::GlideWield + | CharacterState::GlideWield(_) | CharacterState::Talk | CharacterState::Roll(_), ) diff --git a/common/src/states/glide.rs b/common/src/states/glide.rs index f176493087..80007b09e1 100644 --- a/common/src/states/glide.rs +++ b/common/src/states/glide.rs @@ -1,4 +1,4 @@ -use super::utils::handle_climb; +use super::{glide_wield, utils::handle_climb}; use crate::{ comp::{inventory::slot::EquipSlot, CharacterState, ControllerInputs, Ori, StateUpdate, Vel}, glider::Glider, @@ -108,7 +108,7 @@ impl CharacterBehavior for Data { if data.physics.on_ground && (data.vel.0 - data.physics.ground_vel).magnitude_squared() < 2_f32.powi(2) { - update.character = CharacterState::GlideWield; + update.character = CharacterState::GlideWield(glide_wield::Data(self.glider)); update.ori = update.ori.to_horizontal(); } else if data.physics.in_liquid().is_some() || data.inventory.equipped(EquipSlot::Glider).is_none() @@ -149,9 +149,6 @@ impl CharacterBehavior for Data { { let glider_up = glider.ori.up(); let d = glider_up.dot(*char_up); - let cap = |max_ang: f32| -> Option { - (d - max_ang.cos()).is_sign_positive().then_some(max_ang) - }; if let Some(roll_input) = self.roll_input(data.inputs) { if (d - max_roll.cos()).is_sign_positive() diff --git a/common/src/states/glide_wield.rs b/common/src/states/glide_wield.rs index 8bf2f65e54..27bbb435cf 100644 --- a/common/src/states/glide_wield.rs +++ b/common/src/states/glide_wield.rs @@ -1,14 +1,26 @@ use super::utils::*; use crate::{ - comp::{slot::EquipSlot, CharacterState, InventoryAction, StateUpdate}, + comp::{slot::EquipSlot, Body, CharacterState, InventoryAction, Ori, StateUpdate}, glider::Glider, states::{ behavior::{CharacterBehavior, JoinData}, glide, }, }; +use serde::{Deserialize, Serialize}; -pub struct Data; +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Data(pub Glider); + +impl Data { + pub fn new(body: &Body, ori: &Ori) -> Self { + Self(Glider::new( + body.dimensions().z * 3.0, + body.dimensions().z / 3.0, + *ori, + )) + } +} impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData) -> StateUpdate { @@ -20,25 +32,26 @@ impl CharacterBehavior for Data { handle_dodge_input(data, &mut update); handle_wield(data, &mut update); + let mut glider = self.0; + glider.ori = glider.ori.slerped_towards( + Ori::from(data.inputs.look_dir).pitched_up(inline_tweak::tweak!(0.35)), + inline_tweak::tweak!(10.0) * data.dt.0, + ); + // If not on the ground while wielding glider enter gliding state - if !data.physics.on_ground { - let glider = Glider::new( - data.body.dimensions().z * 3.0, - data.body.dimensions().z / 3.0, - *data.ori, - ); - update.character = CharacterState::Glide(glide::Data::new(glider, data.ori)); - } - if data + update.character = if !data.physics.on_ground { + CharacterState::Glide(glide::Data::new(glider, data.ori)) + } else if data .physics .in_liquid() .map(|depth| depth > 0.5) .unwrap_or(false) { - update.character = CharacterState::Idle; - } - if data.inventory.equipped(EquipSlot::Glider).is_none() { - update.character = CharacterState::Idle + CharacterState::Idle + } else if data.inventory.equipped(EquipSlot::Glider).is_none() { + CharacterState::Idle + } else { + CharacterState::GlideWield(Self(glider)) }; update diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 2964e148eb..2431d64e1d 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -570,7 +570,7 @@ pub fn attempt_glide_wield(data: &JoinData, update: &mut StateUpdate) { .unwrap_or(false) && data.body.is_humanoid() { - update.character = CharacterState::GlideWield; + update.character = CharacterState::GlideWield(glide_wield::Data::new(data.body, data.ori)); } } diff --git a/common/systems/src/character_behavior.rs b/common/systems/src/character_behavior.rs index 382067f7d7..84f6582d52 100644 --- a/common/systems/src/character_behavior.rs +++ b/common/systems/src/character_behavior.rs @@ -297,8 +297,8 @@ impl<'a> System<'a> for Sys { CharacterState::Talk => states::talk::Data.handle_event(&j, action), CharacterState::Climb(data) => data.handle_event(&j, action), CharacterState::Glide(data) => data.handle_event(&j, action), - CharacterState::GlideWield => { - states::glide_wield::Data.handle_event(&j, action) + CharacterState::GlideWield(data) => { + data.handle_event(&j, action) }, CharacterState::Stunned(data) => data.handle_event(&j, action), CharacterState::Sit => { @@ -360,7 +360,7 @@ impl<'a> System<'a> for Sys { CharacterState::Talk => states::talk::Data.behavior(&j), CharacterState::Climb(data) => data.behavior(&j), CharacterState::Glide(data) => data.behavior(&j), - CharacterState::GlideWield => states::glide_wield::Data.behavior(&j), + CharacterState::GlideWield(data) => data.behavior(&j), CharacterState::Stunned(data) => data.behavior(&j), CharacterState::Sit => states::sit::Data::behavior(&states::sit::Data, &j), CharacterState::Dance => states::dance::Data::behavior(&states::dance::Data, &j), diff --git a/common/systems/src/phys.rs b/common/systems/src/phys.rs index c37abc24a7..afb193f75a 100644 --- a/common/systems/src/phys.rs +++ b/common/systems/src/phys.rs @@ -49,7 +49,8 @@ fn integrate_glider_forces( rel_wind: &Vel, ) -> Option<()> { let glider = match character_state { - CharacterState::Glide(glider) => Some(glider.glider), + CharacterState::Glide(data) => Some(data.glider), + CharacterState::GlideWield(data) => Some(data.0), _ => None, }?; diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 67240676be..31a14f5e46 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -279,7 +279,7 @@ impl<'a> System<'a> for Sys { }); let is_gliding = matches!( read_data.char_states.get(entity), - Some(CharacterState::GlideWield) | Some(CharacterState::Glide(_)) + Some(CharacterState::GlideWield(_)) | Some(CharacterState::Glide(_)) ) && !physics_state.on_ground; if let Some(pid) = agent.position_pid_controller.as_mut() { diff --git a/voxygen/anim/src/character/glidewield.rs b/voxygen/anim/src/character/glidewield.rs index 8118fb117b..e142946b12 100644 --- a/voxygen/anim/src/character/glidewield.rs +++ b/voxygen/anim/src/character/glidewield.rs @@ -5,8 +5,9 @@ use super::{ pub struct GlideWieldAnimation; +type GlideWieldAnimationDependency = (Quaternion, Quaternion); impl Animation for GlideWieldAnimation { - type Dependency<'a> = (); + type Dependency<'a> = GlideWieldAnimationDependency; type Skeleton = CharacterSkeleton; #[cfg(feature = "use-dyn-lib")] @@ -16,21 +17,25 @@ impl Animation for GlideWieldAnimation { fn update_skeleton_inner<'a>( skeleton: &Self::Skeleton, - _: Self::Dependency<'a>, + (orientation, glider_orientation): Self::Dependency<'a>, _anim_time: f32, rate: &mut f32, s_a: &SkeletonAttr, ) -> Self::Skeleton { let mut next = (*skeleton).clone(); + let glider_ori = orientation.inverse() * glider_orientation; + let glider_pos = Vec3::new(0.0, -5.0, 13.0); *rate = 1.0; - next.hand_l.position = Vec3::new(-2.0 - s_a.hand.0, s_a.hand.1, s_a.hand.2 + 15.0); + next.hand_l.position = + glider_pos + glider_ori * Vec3::new(-s_a.hand.0 + -2.0, s_a.hand.1 + 8.0, s_a.hand.2); next.hand_l.orientation = Quaternion::rotation_x(3.35) * Quaternion::rotation_y(0.2); - next.hand_r.position = Vec3::new(2.0 + s_a.hand.0, s_a.hand.1, s_a.hand.2 + 15.0); + next.hand_r.position = + glider_pos + glider_ori * Vec3::new(s_a.hand.0 + 2.0, s_a.hand.1 + 8.0, s_a.hand.2); next.hand_r.orientation = Quaternion::rotation_x(3.35) * Quaternion::rotation_y(-0.2); next.glider.scale = Vec3::one() * 1.0; - next.glider.orientation = Quaternion::rotation_x(0.35); + next.glider.orientation = glider_ori; next.glider.position = Vec3::new(0.0, -5.0, 13.0); diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 1cd7ac6aac..6be21fbf3f 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -1522,10 +1522,10 @@ impl FigureMgr { skeleton_attr, ) }, - CharacterState::GlideWield { .. } => { + CharacterState::GlideWield(data) => { anim::character::GlideWieldAnimation::update_skeleton( &target_base, - (), + (ori, data.0.ori.into()), state.state_time, &mut state_animation_rate, skeleton_attr,