diff --git a/CHANGELOG.md b/CHANGELOG.md index e3e97a72e4..086b25c678 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed a bug where walk/run sfx played while a character rolled/dodged - Energy regen resets on last ability use instead of on wield - Fixed unable to use ability; Secondary and ability3 (fire rod) will now automatically wield +- Gliding is now a toggle that can be triggered from the ground + ### Removed diff --git a/client/src/lib.rs b/client/src/lib.rs index a718d774d4..a628fd96f7 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -413,6 +413,26 @@ impl Client { } } + pub fn toggle_glide(&mut self) { + let is_gliding = self + .state + .ecs() + .read_storage::() + .get(self.entity) + .map(|cs| { + matches!( + cs, + comp::CharacterState::GlideWield | comp::CharacterState::Glide + ) + }); + + match is_gliding { + Some(true) => self.control_action(ControlAction::Unwield), + Some(false) => self.control_action(ControlAction::GlideWield), + None => warn!("Can't toggle glide, client entity doesn't have a `CharacterState`"), + } + } + fn control_action(&mut self, control_action: ControlAction) { if let Some(controller) = self .state diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 809e928fad..f2cdcbb5b7 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -41,6 +41,7 @@ pub enum CharacterState { Sit, Dance, Glide, + GlideWield, /// A basic blocking state BasicBlock, /// Player is busy equipping or unequipping weapons diff --git a/common/src/comp/controller.rs b/common/src/comp/controller.rs index 2f7664c313..2912fce476 100644 --- a/common/src/comp/controller.rs +++ b/common/src/comp/controller.rs @@ -29,6 +29,7 @@ pub enum ControlEvent { pub enum ControlAction { SwapLoadout, Wield, + GlideWield, Unwield, Sit, Dance, diff --git a/common/src/states/dance.rs b/common/src/states/dance.rs index 67070edf9c..1d1b9c49c1 100644 --- a/common/src/states/dance.rs +++ b/common/src/states/dance.rs @@ -12,6 +12,7 @@ impl CharacterBehavior for Data { let mut update = StateUpdate::from(data); handle_wield(data, &mut update); + handle_jump(&data, &mut update); // Try to Fall/Stand up/Move if !data.physics.on_ground || data.inputs.move_dir.magnitude_squared() > 0.0 { diff --git a/common/src/states/glide.rs b/common/src/states/glide.rs index dc052e48c2..d49619c67f 100644 --- a/common/src/states/glide.rs +++ b/common/src/states/glide.rs @@ -1,3 +1,4 @@ +use super::utils::handle_climb; use crate::{ comp::{CharacterState, StateUpdate}, sys::character_behavior::{CharacterBehavior, JoinData}, @@ -17,17 +18,15 @@ impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData) -> StateUpdate { let mut update = StateUpdate::from(data); - // If glide button isn't held or player is on ground, end glide - if !data.inputs.glide.is_pressed() || data.physics.on_ground { - update.character = CharacterState::Idle; + // If player is on ground, end glide + if data.physics.on_ground { + update.character = CharacterState::GlideWield; return update; } - // If there is a wall in front of character go to climb - if data.physics.on_wall.is_some() { - update.character = CharacterState::Climb; - return update; - } + // If there is a wall in front of character and they are trying to climb go to + // climb + handle_climb(&data, &mut update); // Move player according to movement direction vector update.vel.0 += Vec2::broadcast(data.dt.0) @@ -56,4 +55,10 @@ impl CharacterBehavior for Data { update } + + fn unwield(&self, data: &JoinData) -> StateUpdate { + let mut update = StateUpdate::from(data); + update.character = CharacterState::Idle; + update + } } diff --git a/common/src/states/glide_wield.rs b/common/src/states/glide_wield.rs new file mode 100644 index 0000000000..8efd033c75 --- /dev/null +++ b/common/src/states/glide_wield.rs @@ -0,0 +1,41 @@ +use super::utils::*; +use crate::{ + comp::{CharacterState, StateUpdate}, + sys::character_behavior::{CharacterBehavior, JoinData}, +}; + +pub struct Data; + +impl CharacterBehavior for Data { + fn behavior(&self, data: &JoinData) -> StateUpdate { + let mut update = StateUpdate::from(data); + + handle_move(&data, &mut update, 1.0); + handle_jump(&data, &mut update); + + // If not on the ground while wielding glider enter gliding state + if !data.physics.on_ground && !data.physics.in_fluid { + update.character = CharacterState::Glide; + } + + update + } + + fn sit(&self, data: &JoinData) -> StateUpdate { + let mut update = StateUpdate::from(data); + attempt_sit(data, &mut update); + update + } + + fn dance(&self, data: &JoinData) -> StateUpdate { + let mut update = StateUpdate::from(data); + attempt_dance(data, &mut update); + update + } + + fn unwield(&self, data: &JoinData) -> StateUpdate { + let mut update = StateUpdate::from(data); + update.character = CharacterState::Idle; + update + } +} diff --git a/common/src/states/idle.rs b/common/src/states/idle.rs index 4e7797bb51..e86c1bd77c 100644 --- a/common/src/states/idle.rs +++ b/common/src/states/idle.rs @@ -14,7 +14,6 @@ impl CharacterBehavior for Data { handle_jump(data, &mut update); handle_wield(data, &mut update); handle_climb(data, &mut update); - handle_glide(data, &mut update); handle_dodge_input(data, &mut update); update @@ -38,6 +37,12 @@ impl CharacterBehavior for Data { update } + fn glide_wield(&self, data: &JoinData) -> StateUpdate { + let mut update = StateUpdate::from(data); + attempt_glide_wield(data, &mut update); + update + } + fn swap_loadout(&self, data: &JoinData) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_swap_loadout(data, &mut update); diff --git a/common/src/states/mod.rs b/common/src/states/mod.rs index b59ee755e0..268dc0b875 100644 --- a/common/src/states/mod.rs +++ b/common/src/states/mod.rs @@ -7,6 +7,7 @@ pub mod dance; pub mod dash_melee; pub mod equipping; pub mod glide; +pub mod glide_wield; pub mod idle; pub mod roll; pub mod sit; diff --git a/common/src/states/sit.rs b/common/src/states/sit.rs index 8d372c6ccf..d471e390e2 100644 --- a/common/src/states/sit.rs +++ b/common/src/states/sit.rs @@ -12,6 +12,7 @@ impl CharacterBehavior for Data { let mut update = StateUpdate::from(data); handle_wield(data, &mut update); + handle_jump(&data, &mut update); // Try to Fall/Stand up/Move if !data.physics.on_ground || data.inputs.move_dir.magnitude_squared() > 0.0 { diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 952d648468..539a2e12bd 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -154,16 +154,10 @@ pub fn attempt_swap_loadout(_data: &JoinData, update: &mut StateUpdate) { } } -/// Checks that player can glide and updates `CharacterState` if so -pub fn handle_glide(data: &JoinData, update: &mut StateUpdate) { - if let CharacterState::Idle { .. } | CharacterState::Wielding { .. } = update.character { - if data.inputs.glide.is_pressed() - && !data.physics.on_ground - && !data.physics.in_fluid - && data.body.is_humanoid() - { - update.character = CharacterState::Glide; - } +/// Checks that player can wield the glider and updates `CharacterState` if so +pub fn attempt_glide_wield(data: &JoinData, update: &mut StateUpdate) { + if data.physics.on_ground && !data.physics.in_fluid && data.body.is_humanoid() { + update.character = CharacterState::GlideWield; } } diff --git a/common/src/states/wielding.rs b/common/src/states/wielding.rs index a978896028..c63f0a3d95 100644 --- a/common/src/states/wielding.rs +++ b/common/src/states/wielding.rs @@ -13,7 +13,6 @@ impl CharacterBehavior for Data { handle_move(&data, &mut update, 1.0); handle_jump(&data, &mut update); handle_climb(&data, &mut update); - handle_glide(&data, &mut update); handle_ability1_input(&data, &mut update); handle_ability2_input(&data, &mut update); handle_ability3_input(&data, &mut update); diff --git a/common/src/sys/character_behavior.rs b/common/src/sys/character_behavior.rs index 98fe902c1f..db1aa1cd8a 100644 --- a/common/src/sys/character_behavior.rs +++ b/common/src/sys/character_behavior.rs @@ -18,6 +18,7 @@ pub trait CharacterBehavior { // Impl these to provide behavior for these inputs fn swap_loadout(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } fn wield(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } + fn glide_wield(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } fn unwield(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } fn sit(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } fn dance(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } @@ -26,6 +27,7 @@ pub trait CharacterBehavior { match event { ControlAction::SwapLoadout => self.swap_loadout(data), ControlAction::Wield => self.wield(data), + ControlAction::GlideWield => self.glide_wield(data), ControlAction::Unwield => self.unwield(data), ControlAction::Sit => self.sit(data), ControlAction::Dance => self.dance(data), @@ -197,6 +199,9 @@ impl<'a> System<'a> for Sys { CharacterState::Idle => states::idle::Data.handle_event(&j, action), CharacterState::Climb => states::climb::Data.handle_event(&j, action), CharacterState::Glide => states::glide::Data.handle_event(&j, action), + CharacterState::GlideWield => { + states::glide_wield::Data.handle_event(&j, action) + }, CharacterState::Sit => { states::sit::Data::handle_event(&states::sit::Data, &j, action) }, @@ -226,6 +231,7 @@ impl<'a> System<'a> for Sys { CharacterState::Idle => states::idle::Data.behavior(&j), CharacterState::Climb => states::climb::Data.behavior(&j), CharacterState::Glide => states::glide::Data.behavior(&j), + CharacterState::GlideWield => states::glide_wield::Data.behavior(&j), CharacterState::Sit => states::sit::Data::behavior(&states::sit::Data, &j), CharacterState::Dance => states::dance::Data::behavior(&states::dance::Data, &j), CharacterState::BasicBlock => states::basic_block::Data.behavior(&j), diff --git a/common/src/sys/stats.rs b/common/src/sys/stats.rs index e594ef2667..2879b3f90d 100644 --- a/common/src/sys/stats.rs +++ b/common/src/sys/stats.rs @@ -81,6 +81,7 @@ impl<'a> System<'a> for Sys { | CharacterState::Sit { .. } | CharacterState::Dance { .. } | CharacterState::Glide { .. } + | CharacterState::GlideWield { .. } | CharacterState::Wielding { .. } | CharacterState::Equipping { .. } | CharacterState::Boost { .. } => { diff --git a/voxygen/examples/voxygen - Shortcut.lnk b/voxygen/examples/voxygen - Shortcut.lnk new file mode 100644 index 0000000000..722dd67f2a Binary files /dev/null and b/voxygen/examples/voxygen - Shortcut.lnk differ diff --git a/voxygen/src/anim/character/glidewield.rs b/voxygen/src/anim/character/glidewield.rs new file mode 100644 index 0000000000..c3509d6495 --- /dev/null +++ b/voxygen/src/anim/character/glidewield.rs @@ -0,0 +1,304 @@ +use super::{super::Animation, CharacterSkeleton, SkeletonAttr}; +use common::comp::item::ToolKind; +use std::{f32::consts::PI, ops::Mul}; +use vek::*; + +pub struct GlideWieldAnimation; + +impl Animation for GlideWieldAnimation { + type Dependency = (Option, Vec3, Vec3, Vec3, f64); + type Skeleton = CharacterSkeleton; + + #[allow(clippy::identity_conversion)] // TODO: Pending review in #587 + fn update_skeleton( + skeleton: &Self::Skeleton, + (_active_tool_kind, velocity, orientation, last_ori, global_time): Self::Dependency, + anim_time: f64, + rate: &mut f32, + skeleton_attr: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + let speed = Vec2::::from(velocity).magnitude(); + *rate = 1.0; + let slow = (anim_time as f32 * 1.0).sin(); + let breathe = ((anim_time as f32 * 0.5).sin()).abs(); + let walkintensity = if speed > 5.0 { 1.0 } else { 0.45 }; + let walk = if speed > 5.0 { 1.0 } else { 0.5 }; + let lower = if speed > 5.0 { 0.0 } else { 1.0 }; + let _snapfoot = if speed > 5.0 { 1.1 } else { 2.0 }; + let lab = 1.0; + let foothoril = (anim_time as f32 * 16.0 * walk * lab as f32 + PI * 1.45).sin(); + let foothorir = (anim_time as f32 * 16.0 * walk * lab as f32 + PI * (0.45)).sin(); + + let footvertl = (anim_time as f32 * 16.0 * walk * lab as f32).sin(); + let footvertr = (anim_time as f32 * 16.0 * walk * lab as f32 + PI).sin(); + + let footrotl = (((5.0) + / (2.5 + + (2.5) + * ((anim_time as f32 * 16.0 * walk * lab as f32 + PI * 1.4).sin()) + .powf(2.0 as f32))) + .sqrt()) + * ((anim_time as f32 * 16.0 * walk * lab as f32 + PI * 1.4).sin()); + + let footrotr = (((5.0) + / (1.0 + + (4.0) + * ((anim_time as f32 * 16.0 * walk * lab as f32 + PI * 0.4).sin()) + .powf(2.0 as f32))) + .sqrt()) + * ((anim_time as f32 * 16.0 * walk * lab as f32 + PI * 0.4).sin()); + + let short = (((5.0) + / (1.5 + + 3.5 * ((anim_time as f32 * lab as f32 * 16.0 * walk).sin()).powf(2.0 as f32))) + .sqrt()) + * ((anim_time as f32 * lab as f32 * 16.0 * walk).sin()); + let noisea = (anim_time as f32 * 11.0 + PI / 6.0).sin(); + let noiseb = (anim_time as f32 * 19.0 + PI / 4.0).sin(); + + let shorte = (((5.0) + / (4.0 + + 1.0 * ((anim_time as f32 * lab as f32 * 16.0 * walk).sin()).powf(2.0 as f32))) + .sqrt()) + * ((anim_time as f32 * lab as f32 * 16.0 * walk).sin()); + + let shortalt = (anim_time as f32 * lab as f32 * 16.0 * walk + PI / 2.0).sin(); + let shortalter = (anim_time as f32 * lab as f32 * 16.0 * walk + PI / -2.0).sin(); + + let wave_stop = (anim_time as f32 * 26.0).min(PI / 2.0 / 2.0).sin(); + + let head_look = Vec2::new( + ((global_time + anim_time) as f32 / 18.0) + .floor() + .mul(7331.0) + .sin() + * 0.2, + ((global_time + anim_time) as f32 / 18.0) + .floor() + .mul(1337.0) + .sin() + * 0.1, + ); + + let ori = Vec2::from(orientation); + let last_ori = Vec2::from(last_ori); + let tilt = if Vec2::new(ori, last_ori) + .map(|o| Vec2::::from(o).magnitude_squared()) + .map(|m| m > 0.001 && m.is_finite()) + .reduce_and() + && ori.angle_between(last_ori).is_finite() + { + ori.angle_between(last_ori).min(0.2) + * last_ori.determine_side(Vec2::zero(), ori).signum() + } else { + 0.0 + } * 1.3; + + next.l_hand.offset = Vec3::new( + -2.0 - skeleton_attr.hand.0, + skeleton_attr.hand.1, + skeleton_attr.hand.2 + 15.0, + ); + next.l_hand.ori = Quaternion::rotation_x(3.35); + next.l_hand.scale = Vec3::one(); + + next.r_hand.offset = Vec3::new( + 2.0 + skeleton_attr.hand.0, + skeleton_attr.hand.1, + skeleton_attr.hand.2 + 15.0, + ); + next.r_hand.ori = Quaternion::rotation_x(3.35); + next.r_hand.scale = Vec3::one(); + + if speed > 0.5 { + next.head.offset = Vec3::new( + 0.0, + -3.0 + skeleton_attr.head.0, + skeleton_attr.head.1 + short * 0.1, + ); + next.head.ori = Quaternion::rotation_z(tilt * -2.5 + head_look.x * 0.2 - short * 0.1) + * Quaternion::rotation_x(head_look.y + 0.45 - lower * 0.35); + next.head.scale = Vec3::one() * skeleton_attr.head_scale; + + next.chest.offset = Vec3::new( + 0.0, + skeleton_attr.chest.0, + skeleton_attr.chest.1 + 2.0 + shortalt * -1.5 - lower, + ); + next.chest.ori = Quaternion::rotation_z(short * 0.10 * walkintensity + tilt * -1.0) + * Quaternion::rotation_y(tilt * 2.2) + * Quaternion::rotation_x( + shortalter * 0.035 + wave_stop * speed * -0.1 + (tilt.abs()), + ); + next.chest.scale = Vec3::one(); + + next.belt.offset = Vec3::new(0.0, skeleton_attr.belt.0, skeleton_attr.belt.1); + next.belt.ori = Quaternion::rotation_z(short * 0.1 + tilt * -1.1) + * Quaternion::rotation_y(tilt * 0.5); + next.belt.scale = Vec3::one(); + + next.glider.ori = Quaternion::rotation_x(0.8); + next.glider.offset = Vec3::new(0.0, -10.0, 15.0); + next.glider.scale = Vec3::one() * 1.0; + + next.back.offset = Vec3::new(0.0, skeleton_attr.back.0, skeleton_attr.back.1); + next.back.ori = + Quaternion::rotation_x(-0.25 + short * 0.1 + noisea * 0.1 + noiseb * 0.1); + next.back.scale = Vec3::one() * 1.02; + + next.shorts.offset = Vec3::new(0.0, skeleton_attr.shorts.0, skeleton_attr.shorts.1); + next.shorts.ori = Quaternion::rotation_z(short * 0.25 + tilt * -1.5) + * Quaternion::rotation_y(tilt * 0.7); + next.shorts.scale = Vec3::one(); + + next.l_foot.offset = Vec3::new( + -skeleton_attr.foot.0, + -1.5 + skeleton_attr.foot.1 + foothoril * -8.5 * walkintensity - lower * 1.0, + 2.0 + skeleton_attr.foot.2 + ((footvertl * -2.7).max(-1.0)) * walkintensity, + ); + next.l_foot.ori = Quaternion::rotation_x(-0.2 + footrotl * -1.2 * walkintensity) + * Quaternion::rotation_y(tilt * 1.8); + next.l_foot.scale = Vec3::one(); + + next.r_foot.offset = Vec3::new( + skeleton_attr.foot.0, + -1.5 + skeleton_attr.foot.1 + foothorir * -8.5 * walkintensity - lower * 1.0, + 2.0 + skeleton_attr.foot.2 + ((footvertr * -2.7).max(-1.0)) * walkintensity, + ); + next.r_foot.ori = Quaternion::rotation_x(-0.2 + footrotr * -1.2 * walkintensity) + * Quaternion::rotation_y(tilt * 1.8); + next.r_foot.scale = Vec3::one(); + + next.l_shoulder.offset = Vec3::new( + -skeleton_attr.shoulder.0, + skeleton_attr.shoulder.1, + skeleton_attr.shoulder.2, + ); + next.l_shoulder.ori = Quaternion::rotation_x(short * 0.15 * walkintensity); + next.l_shoulder.scale = Vec3::one() * 1.1; + + next.r_shoulder.offset = Vec3::new( + skeleton_attr.shoulder.0, + skeleton_attr.shoulder.1, + skeleton_attr.shoulder.2, + ); + next.r_shoulder.ori = Quaternion::rotation_x(short * -0.15 * walkintensity); + next.r_shoulder.scale = Vec3::one() * 1.1; + + next.main.offset = Vec3::new(-7.0, -6.5, 15.0); + next.main.ori = + Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57 + short * 0.25); + next.main.scale = Vec3::one(); + + next.second.scale = Vec3::one() * 0.0; + + next.lantern.offset = Vec3::new( + skeleton_attr.lantern.0, + skeleton_attr.lantern.1, + skeleton_attr.lantern.2, + ); + next.lantern.ori = + Quaternion::rotation_x(shorte * 0.7 + 0.4) * Quaternion::rotation_y(shorte * 0.4); + next.lantern.scale = Vec3::one() * 0.65; + + next.torso.offset = Vec3::new(0.0, 0.0, 0.0) * skeleton_attr.scaler; + next.torso.ori = Quaternion::rotation_y(0.0); + next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler; + + next.control.offset = Vec3::new(0.0, 0.0, 0.0); + next.control.ori = Quaternion::rotation_x(0.0); + next.control.scale = Vec3::one(); + + next.l_control.scale = Vec3::one(); + + next.r_control.scale = Vec3::one(); + } else { + next.head.offset = Vec3::new( + 0.0, + -3.0 + skeleton_attr.head.0, + skeleton_attr.head.1 + slow * 0.3 + breathe * -0.05, + ); + next.head.ori = + Quaternion::rotation_z(head_look.x) * Quaternion::rotation_x(head_look.y.abs()); + next.head.scale = Vec3::one() * skeleton_attr.head_scale + breathe * -0.05; + + next.chest.offset = Vec3::new( + 0.0, + skeleton_attr.chest.0, + skeleton_attr.chest.1 + slow * 0.3, + ); + next.chest.ori = Quaternion::rotation_z(head_look.x * 0.6); + next.chest.scale = Vec3::one() * 1.01 + breathe * 0.03; + + next.belt.offset = Vec3::new(0.0, skeleton_attr.belt.0, skeleton_attr.belt.1); + next.belt.ori = Quaternion::rotation_z(head_look.x * -0.1); + next.belt.scale = Vec3::one() + breathe * -0.03; + + next.glider.ori = Quaternion::rotation_x(0.35); + next.glider.offset = Vec3::new(0.0, -9.0, 17.0); + next.glider.scale = Vec3::one() * 1.0; + + next.back.offset = Vec3::new(0.0, skeleton_attr.back.0, skeleton_attr.back.1); + next.back.scale = Vec3::one() * 1.02; + + next.shorts.offset = Vec3::new(0.0, skeleton_attr.shorts.0, skeleton_attr.shorts.1); + next.shorts.ori = Quaternion::rotation_z(head_look.x * -0.2); + next.shorts.scale = Vec3::one() + breathe * -0.03; + + next.l_foot.offset = Vec3::new( + -skeleton_attr.foot.0, + skeleton_attr.foot.1, + skeleton_attr.foot.2, + ); + next.l_foot.scale = Vec3::one(); + + next.r_foot.offset = Vec3::new( + skeleton_attr.foot.0, + skeleton_attr.foot.1, + skeleton_attr.foot.2, + ); + next.r_foot.scale = Vec3::one(); + + next.l_shoulder.offset = Vec3::new( + -skeleton_attr.shoulder.0, + skeleton_attr.shoulder.1, + skeleton_attr.shoulder.2, + ); + next.l_shoulder.scale = (Vec3::one() + breathe * -0.05) * 1.15; + + next.r_shoulder.offset = Vec3::new( + skeleton_attr.shoulder.0, + skeleton_attr.shoulder.1, + skeleton_attr.shoulder.2, + ); + next.r_shoulder.scale = (Vec3::one() + breathe * -0.05) * 1.15; + + next.main.offset = Vec3::new(-7.0, -5.0, 15.0); + next.main.ori = Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57); + next.main.scale = Vec3::one(); + + next.second.offset = Vec3::new(0.0, 0.0, 0.0); + next.second.scale = Vec3::one() * 0.0; + + next.lantern.offset = Vec3::new( + skeleton_attr.lantern.0, + skeleton_attr.lantern.1, + skeleton_attr.lantern.2, + ); + next.lantern.ori = Quaternion::rotation_x(0.1) * Quaternion::rotation_y(0.1); + next.lantern.scale = Vec3::one() * 0.65; + + next.torso.offset = Vec3::new(0.0, 0.0, 0.0) * skeleton_attr.scaler; + next.torso.ori = Quaternion::rotation_x(0.0); + next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler; + + next.control.scale = Vec3::one(); + + next.l_control.scale = Vec3::one(); + + next.r_control.scale = Vec3::one(); + } + next + } +} diff --git a/voxygen/src/anim/character/gliding.rs b/voxygen/src/anim/character/gliding.rs index 9bde7282bc..4f9a89cdb4 100644 --- a/voxygen/src/anim/character/gliding.rs +++ b/voxygen/src/anim/character/gliding.rs @@ -55,43 +55,49 @@ impl Animation for GlidingAnimation { 0.0 }; + let tiltcancel = if anim_time > 1.0 { + 1.0 + } else { + anim_time as f32 + }; + next.head.offset = Vec3::new(0.0, -2.0 + skeleton_attr.head.0, skeleton_attr.head.1); next.head.ori = Quaternion::rotation_x(0.35 - slow * 0.10 + head_look.y) * Quaternion::rotation_z(head_look.x + slowa * 0.15); - next.chest.offset = Vec3::new(0.0, 0.0, -2.0); - next.chest.ori = Quaternion::rotation_z(slowa * 0.2); + next.chest.offset = Vec3::new(0.0, skeleton_attr.chest.0, skeleton_attr.chest.1); + next.chest.ori = Quaternion::rotation_z(slowa * 0.02); next.belt.offset = Vec3::new(0.0, 0.0, -2.0); - next.belt.ori = Quaternion::rotation_z(slowa * 0.25); + next.belt.ori = Quaternion::rotation_z(slowa * 0.1 + tilt * tiltcancel * 12.0); next.shorts.offset = Vec3::new(0.0, skeleton_attr.shorts.0, skeleton_attr.shorts.1); - next.shorts.ori = Quaternion::rotation_z(slowa * 0.35); + next.shorts.ori = Quaternion::rotation_z(slowa * 0.12 + tilt * tiltcancel * 16.0); - next.l_hand.offset = Vec3::new(-9.5 + slowa * -1.5, -3.0 + slowa * 1.5, 10.0); + next.l_hand.offset = Vec3::new(-9.5, -3.0, 10.0); next.l_hand.ori = Quaternion::rotation_x(-2.7 + slowa * -0.1); - next.r_hand.offset = Vec3::new(9.5 + slowa * -1.5, -3.0 + slowa * -1.5, 10.0); + next.r_hand.offset = Vec3::new(9.5, -3.0, 10.0); next.r_hand.ori = Quaternion::rotation_x(-2.7 + slowa * -0.10); next.l_foot.offset = Vec3::new( -skeleton_attr.foot.0, - skeleton_attr.foot.1, - -9.0 + skeleton_attr.foot.2, + skeleton_attr.foot.1 + slowa * -1.0 + tilt * tiltcancel * -35.0, + -1.0 + skeleton_attr.foot.2, ); next.l_foot.ori = Quaternion::rotation_x( (wave_stop * -0.7 - quicka * -0.21 + slow * 0.19) * speed * 0.04, - ); + ) * Quaternion::rotation_z(tilt * tiltcancel * 20.0); next.l_foot.scale = Vec3::one(); next.r_foot.offset = Vec3::new( skeleton_attr.foot.0, - skeleton_attr.foot.1, - -9.0 + skeleton_attr.foot.2, + skeleton_attr.foot.1 + slowa * 1.0 + tilt * tiltcancel * 35.0, + -1.0 + skeleton_attr.foot.2, ); next.r_foot.ori = Quaternion::rotation_x( (wave_stop * -0.8 + quick * -0.25 + slowb * 0.13) * speed * 0.04, - ); + ) * Quaternion::rotation_z(tilt * tiltcancel * 20.0); next.r_foot.scale = Vec3::one(); next.l_shoulder.offset = Vec3::new( @@ -125,9 +131,9 @@ impl Animation for GlidingAnimation { ); next.lantern.scale = Vec3::one() * 0.65; - next.torso.offset = Vec3::new(0.0, 6.0, 15.0) / 11.0 * skeleton_attr.scaler; - next.torso.ori = Quaternion::rotation_x(-0.05 * speed.max(12.0) + slow * 0.06) - * Quaternion::rotation_y(tilt * 32.0); + next.torso.offset = Vec3::new(0.0, -4.0, 0.0) / 11.0 * skeleton_attr.scaler; + next.torso.ori = Quaternion::rotation_x(-0.06 * speed.max(12.0) + slow * 0.04) + * Quaternion::rotation_y(tilt * tiltcancel * 32.0); next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler; next.control.scale = Vec3::one(); diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 23b493b459..bbc0d3bfa3 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -7,6 +7,7 @@ pub mod climb; pub mod dance; pub mod dash; pub mod equip; +pub mod glidewield; pub mod gliding; pub mod idle; pub mod jump; @@ -23,10 +24,11 @@ pub mod wield; pub use self::{ alpha::AlphaAnimation, beta::BetaAnimation, block::BlockAnimation, blockidle::BlockIdleAnimation, charge::ChargeAnimation, climb::ClimbAnimation, - dance::DanceAnimation, dash::DashAnimation, equip::EquipAnimation, gliding::GlidingAnimation, - idle::IdleAnimation, jump::JumpAnimation, roll::RollAnimation, run::RunAnimation, - shoot::ShootAnimation, sit::SitAnimation, spin::SpinAnimation, stand::StandAnimation, - swim::SwimAnimation, wield::WieldAnimation, + dance::DanceAnimation, dash::DashAnimation, equip::EquipAnimation, + glidewield::GlideWieldAnimation, gliding::GlidingAnimation, idle::IdleAnimation, + jump::JumpAnimation, roll::RollAnimation, run::RunAnimation, shoot::ShootAnimation, + sit::SitAnimation, spin::SpinAnimation, stand::StandAnimation, swim::SwimAnimation, + wield::WieldAnimation, }; use super::{Bone, Skeleton}; @@ -100,7 +102,7 @@ impl Skeleton for CharacterSkeleton { FigureBoneData::new(torso_mat * self.r_foot.compute_base_matrix()), FigureBoneData::new(torso_mat * chest_mat * self.l_shoulder.compute_base_matrix()), FigureBoneData::new(torso_mat * chest_mat * self.r_shoulder.compute_base_matrix()), - FigureBoneData::new(torso_mat * self.glider.compute_base_matrix()), + FigureBoneData::new(torso_mat * chest_mat * self.glider.compute_base_matrix()), FigureBoneData::new(torso_mat * chest_mat * control_mat * l_control_mat * main_mat), FigureBoneData::new( torso_mat * chest_mat * control_mat * r_control_mat * second_mat, diff --git a/voxygen/src/anim/character/shoot.rs b/voxygen/src/anim/character/shoot.rs index a8a7ce1956..5dc41d5716 100644 --- a/voxygen/src/anim/character/shoot.rs +++ b/voxygen/src/anim/character/shoot.rs @@ -167,7 +167,7 @@ impl Animation for ShootAnimation { Quaternion::rotation_x(exp * -0.7 + 0.4) * Quaternion::rotation_y(exp * 0.4); next.lantern.scale = Vec3::one() * 0.65; - next.hold.offset = Vec3::new(17.4, -24.8, -10.5); + next.hold.offset = Vec3::new(17.5, -25.0, -10.5); next.hold.ori = Quaternion::rotation_x(-1.6) * Quaternion::rotation_y(-0.1) * Quaternion::rotation_z(0.0); diff --git a/voxygen/src/anim/character/swim.rs b/voxygen/src/anim/character/swim.rs index b65a09fcfe..649efbb9fc 100644 --- a/voxygen/src/anim/character/swim.rs +++ b/voxygen/src/anim/character/swim.rs @@ -151,7 +151,7 @@ impl Animation for SwimAnimation { next.lantern.ori = Quaternion::rotation_x(0.0) * Quaternion::rotation_y(0.0); next.lantern.scale = Vec3::one() * 0.65; - next.torso.offset = Vec3::new(0.0, -0.3 + shortalt * -0.065, 0.4) * skeleton_attr.scaler; + next.torso.offset = Vec3::new(0.0, -1.2 + shortalt * -0.065, 0.4) * skeleton_attr.scaler; next.torso.ori = Quaternion::rotation_x(speed * -0.190 * wave_stop * 1.05) * Quaternion::rotation_z(tilt * 12.0); next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler; diff --git a/voxygen/src/key_state.rs b/voxygen/src/key_state.rs index 1edc204ef1..775168de66 100644 --- a/voxygen/src/key_state.rs +++ b/voxygen/src/key_state.rs @@ -8,6 +8,7 @@ pub struct KeyState { pub climb_up: bool, pub climb_down: bool, pub toggle_wield: bool, + pub toggle_glide: bool, pub toggle_sit: bool, pub toggle_dance: bool, pub auto_walk: bool, @@ -27,6 +28,7 @@ impl KeyState { climb_up: false, climb_down: false, toggle_wield: false, + toggle_glide: false, toggle_sit: false, toggle_dance: false, auto_walk: false, diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 7127edb555..c8f2fd3b27 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -730,6 +730,15 @@ impl FigureMgr { skeleton_attr, ) }, + CharacterState::GlideWield { .. } => { + anim::character::GlideWieldAnimation::update_skeleton( + &CharacterSkeleton::new(), + (active_tool_kind, vel.0, ori, state.last_ori, time), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ) + }, CharacterState::Dance { .. } => { anim::character::DanceAnimation::update_skeleton( &CharacterSkeleton::new(), diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index df3d37252f..fd7729db33 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -354,9 +354,14 @@ impl PlayState for SessionState { } self.key_state.right = state }, - Event::InputUpdate(GameInput::Glide, state) => { - self.inputs.glide.set_state(state); - }, + Event::InputUpdate(GameInput::Glide, state) + if state != self.key_state.toggle_glide => + { + self.key_state.toggle_glide = state; + if state { + self.client.borrow_mut().toggle_glide(); + } + } Event::InputUpdate(GameInput::Climb, state) => { self.key_state.climb_up = state; },