diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f77b5fe83..621684c177 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added command shortcuts for each of the above chat modes (`/g`, `/f`, `/r`, `/s`, and `/w`, respectively and `/t` for `/tell`) - Ability to wield 2 × 1h weapons and shields (Note: 1h weapons & shields are not currently avaliable, see [!1095](https://gitlab.com/veloren/veloren/-/merge_requests/1095) for more info) - Zoomable Map +- M2 attack for hammer ### Changed diff --git a/assets/voxygen/element/icons/skill_hammerleap.png b/assets/voxygen/element/icons/skill_hammerleap.png new file mode 100644 index 0000000000..1fbf26e82f --- /dev/null +++ b/assets/voxygen/element/icons/skill_hammerleap.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aefd100b0aa77988566812bae909e0659244ac86c0ee9838ea37d19810817018 +size 1015 diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index eaa2b7ae6b..b1068ed928 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -18,6 +18,7 @@ pub enum CharacterAbilityType { DashMelee, BasicBlock, TripleStrike(Stage), + LeapMelee, } impl From<&CharacterState> for CharacterAbilityType { @@ -28,6 +29,7 @@ impl From<&CharacterState> for CharacterAbilityType { CharacterState::Boost(_) => Self::Boost, CharacterState::DashMelee(_) => Self::DashMelee, CharacterState::BasicBlock => Self::BasicBlock, + CharacterState::LeapMelee(_) => Self::LeapMelee, CharacterState::TripleStrike(data) => Self::TripleStrike(data.stage), _ => Self::BasicMelee, } @@ -59,6 +61,7 @@ pub enum CharacterAbility { only_up: bool, }, DashMelee { + energy_cost: u32, buildup_duration: Duration, recover_duration: Duration, base_damage: u32, @@ -69,6 +72,13 @@ pub enum CharacterAbility { base_damage: u32, needs_timing: bool, }, + LeapMelee { + energy_cost: u32, + movement_duration: Duration, + buildup_duration: Duration, + recover_duration: Duration, + base_damage: u32, + }, } impl CharacterAbility { @@ -90,9 +100,9 @@ impl CharacterAbility { .try_change_by(-220, EnergySource::Ability) .is_ok() }, - CharacterAbility::DashMelee { .. } => update + CharacterAbility::DashMelee { energy_cost, .. } => update .energy - .try_change_by(-700, EnergySource::Ability) + .try_change_by(-(*energy_cost as i32), EnergySource::Ability) .is_ok(), CharacterAbility::BasicMelee { energy_cost, .. } => update .energy @@ -102,6 +112,10 @@ impl CharacterAbility { .energy .try_change_by(-(*energy_cost as i32), EnergySource::Ability) .is_ok(), + CharacterAbility::LeapMelee { energy_cost, .. } => update + .energy + .try_change_by(-(*energy_cost as i32), EnergySource::Ability) + .is_ok(), _ => true, } } @@ -179,6 +193,7 @@ impl From<&CharacterAbility> for CharacterState { only_up: *only_up, }), CharacterAbility::DashMelee { + energy_cost: _, buildup_duration, recover_duration, base_damage, @@ -209,6 +224,20 @@ impl From<&CharacterAbility> for CharacterState { TransitionStyle::Hold(HoldingState::Holding) }, }), + CharacterAbility::LeapMelee { + energy_cost: _, + movement_duration, + buildup_duration, + recover_duration, + base_damage, + } => CharacterState::LeapMelee(leap_melee::Data { + initialize: true, + exhausted: false, + movement_duration: *movement_duration, + buildup_duration: *buildup_duration, + recover_duration: *recover_duration, + base_damage: *base_damage, + }), } } } diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 5af32477d9..5cde7824ca 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -61,6 +61,8 @@ pub enum CharacterState { /// A three-stage attack where each attack pushes player forward /// and successive attacks increase in damage, while player holds button. TripleStrike(triple_strike::Data), + /// A leap followed by a small aoe ground attack + LeapMelee(leap_melee::Data), } impl CharacterState { @@ -71,7 +73,8 @@ impl CharacterState { | CharacterState::BasicRanged(_) | CharacterState::DashMelee(_) | CharacterState::TripleStrike(_) - | CharacterState::BasicBlock => true, + | CharacterState::BasicBlock + | CharacterState::LeapMelee(_) => true, _ => false, } } @@ -81,7 +84,8 @@ impl CharacterState { CharacterState::BasicMelee(_) | CharacterState::BasicRanged(_) | CharacterState::DashMelee(_) - | CharacterState::TripleStrike(_) => true, + | CharacterState::TripleStrike(_) + | CharacterState::LeapMelee(_) => true, _ => false, } } @@ -92,7 +96,8 @@ impl CharacterState { | CharacterState::BasicRanged(_) | CharacterState::DashMelee(_) | CharacterState::TripleStrike(_) - | CharacterState::BasicBlock => true, + | CharacterState::BasicBlock + | CharacterState::LeapMelee(_) => true, _ => false, } } diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 1f95413004..5746370145 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -197,6 +197,7 @@ impl Tool { needs_timing: false, }, DashMelee { + energy_cost: 700, buildup_duration: Duration::from_millis(500), recover_duration: Duration::from_millis(500), base_damage: 20, @@ -208,6 +209,7 @@ impl Tool { needs_timing: false, }, DashMelee { + energy_cost: 700, buildup_duration: Duration::from_millis(500), recover_duration: Duration::from_millis(500), base_damage: 10, @@ -227,14 +229,23 @@ impl Tool { max_angle: 30.0, }, ], - Hammer(_) => vec![BasicMelee { - energy_cost: 0, - buildup_duration: Duration::from_millis(700), - recover_duration: Duration::from_millis(300), - base_healthchange: -10, - range: 3.5, - max_angle: 60.0, - }], + Hammer(_) => vec![ + BasicMelee { + energy_cost: 0, + buildup_duration: Duration::from_millis(700), + recover_duration: Duration::from_millis(300), + base_healthchange: -10, + range: 3.5, + max_angle: 60.0, + }, + LeapMelee { + energy_cost: 800, + movement_duration: Duration::from_millis(500), + buildup_duration: Duration::from_millis(1000), + recover_duration: Duration::from_millis(100), + base_damage: 20, + }, + ], Farming(_) => vec![BasicMelee { energy_cost: 1, buildup_duration: Duration::from_millis(700), @@ -303,6 +314,7 @@ impl Tool { max_angle: 60.0, }, DashMelee { + energy_cost: 700, buildup_duration: Duration::from_millis(500), recover_duration: Duration::from_millis(500), base_damage: 20, diff --git a/common/src/states/dash_melee.rs b/common/src/states/dash_melee.rs index 580eef21b5..8964b35638 100644 --- a/common/src/states/dash_melee.rs +++ b/common/src/states/dash_melee.rs @@ -27,7 +27,7 @@ impl CharacterBehavior for Data { if self.initialize { update.vel.0 = *data.inputs.look_dir * 20.0; - if let Some(dir) = Vec3::from(data.vel.0.xy()).try_normalized() { + if let Some(dir) = Vec3::from(data.inputs.look_dir.xy()).try_normalized() { update.ori.0 = dir.into(); } } diff --git a/common/src/states/leap_melee.rs b/common/src/states/leap_melee.rs new file mode 100644 index 0000000000..8906c94f46 --- /dev/null +++ b/common/src/states/leap_melee.rs @@ -0,0 +1,121 @@ +use crate::{ + comp::{Attacking, CharacterState, EnergySource, StateUpdate}, + states::utils::*, + sys::character_behavior::*, +}; +use std::time::Duration; +use vek::Vec3; + +const LEAP_SPEED: f32 = 16.0; + +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] +pub struct Data { + /// How long the state is moving + pub movement_duration: Duration, + /// How long until state should deal damage + pub buildup_duration: Duration, + /// How long the state has until exiting + pub recover_duration: Duration, + /// Base damage + pub base_damage: u32, + /// Whether the attack can deal more damage + pub exhausted: bool, + pub initialize: bool, +} + +impl CharacterBehavior for Data { + fn behavior(&self, data: &JoinData) -> StateUpdate { + let mut update = StateUpdate::from(data); + + if self.initialize { + update.vel.0 = *data.inputs.look_dir * 20.0; + if let Some(dir) = Vec3::from(data.inputs.look_dir.xy()).try_normalized() { + update.ori.0 = dir.into(); + } + } + + if self.movement_duration != Duration::default() { + // Jumping + update.vel.0 = Vec3::new(data.inputs.look_dir.x, data.inputs.look_dir.y, 8.0) + * ((self.movement_duration.as_millis() as f32) / 250.0) + + (update.vel.0 * Vec3::new(2.0, 2.0, 0.0) + + 0.25 * data.inputs.move_dir.try_normalized().unwrap_or_default()) + .try_normalized() + .unwrap_or_default() + * LEAP_SPEED; + + update.character = CharacterState::LeapMelee(Data { + movement_duration: self + .movement_duration + .checked_sub(Duration::from_secs_f32(data.dt.0)) + .unwrap_or_default(), + buildup_duration: self.buildup_duration, + recover_duration: self.recover_duration, + base_damage: self.base_damage, + exhausted: false, + initialize: false, + }); + } else if self.buildup_duration != Duration::default() && !data.physics.on_ground { + // Falling + update.character = CharacterState::LeapMelee(Data { + movement_duration: Duration::default(), + buildup_duration: self + .buildup_duration + .checked_sub(Duration::from_secs_f32(data.dt.0)) + .unwrap_or_default(), + recover_duration: self.recover_duration, + base_damage: self.base_damage, + exhausted: false, + initialize: false, + }); + } else if !self.exhausted { + // Hit attempt + data.updater.insert(data.entity, Attacking { + base_healthchange: -(self.base_damage as i32), + range: 4.5, + max_angle: 360_f32.to_radians(), + applied: false, + hit_count: 0, + knockback: 25.0, + }); + + update.character = CharacterState::LeapMelee(Data { + movement_duration: self.movement_duration, + buildup_duration: Duration::default(), + recover_duration: self.recover_duration, + base_damage: self.base_damage, + exhausted: true, + initialize: false, + }); + } else if self.recover_duration != Duration::default() { + // Recovery + handle_move(data, &mut update, 0.7); + update.character = CharacterState::LeapMelee(Data { + movement_duration: self.movement_duration, + buildup_duration: self.buildup_duration, + recover_duration: self + .recover_duration + .checked_sub(Duration::from_secs_f32(data.dt.0)) + .unwrap_or_default(), + base_damage: self.base_damage, + exhausted: true, + initialize: false, + }); + } else { + // Done + update.character = CharacterState::Wielding; + // Make sure attack component is removed + data.updater.remove::(data.entity); + } + + // Grant energy on successful hit + if let Some(attack) = data.attacking { + if attack.applied && attack.hit_count > 0 { + data.updater.remove::(data.entity); + update.energy.change_by(100, EnergySource::HitEnemy); + } + } + + update + } +} diff --git a/common/src/states/mod.rs b/common/src/states/mod.rs index 268dc0b875..aaf7f0bdc1 100644 --- a/common/src/states/mod.rs +++ b/common/src/states/mod.rs @@ -9,6 +9,7 @@ pub mod equipping; pub mod glide; pub mod glide_wield; pub mod idle; +pub mod leap_melee; pub mod roll; pub mod sit; pub mod triple_strike; diff --git a/common/src/sys/character_behavior.rs b/common/src/sys/character_behavior.rs index db1aa1cd8a..fb6e71884e 100644 --- a/common/src/sys/character_behavior.rs +++ b/common/src/sys/character_behavior.rs @@ -219,6 +219,7 @@ impl<'a> System<'a> for Sys { CharacterState::BasicRanged(data) => data.handle_event(&j, action), CharacterState::Boost(data) => data.handle_event(&j, action), CharacterState::DashMelee(data) => data.handle_event(&j, action), + CharacterState::LeapMelee(data) => data.handle_event(&j, action), }; local_emitter.append(&mut state_update.local_events); server_emitter.append(&mut state_update.server_events); @@ -243,6 +244,7 @@ impl<'a> System<'a> for Sys { CharacterState::BasicRanged(data) => data.behavior(&j), CharacterState::Boost(data) => data.behavior(&j), CharacterState::DashMelee(data) => data.behavior(&j), + CharacterState::LeapMelee(data) => data.behavior(&j), }; local_emitter.append(&mut state_update.local_events); diff --git a/common/src/sys/stats.rs b/common/src/sys/stats.rs index 3fb7384fe0..af95d1cc98 100644 --- a/common/src/sys/stats.rs +++ b/common/src/sys/stats.rs @@ -105,6 +105,7 @@ impl<'a> System<'a> for Sys { // Ability use does not regen and sets the rate back to zero. CharacterState::BasicMelee { .. } | CharacterState::DashMelee { .. } + | CharacterState::LeapMelee { .. } | CharacterState::TripleStrike { .. } | CharacterState::BasicRanged { .. } => { if energy.get_unchecked().regen_rate != 0.0 { diff --git a/voxygen/src/anim/src/character/alpha.rs b/voxygen/src/anim/src/character/alpha.rs index 1445463f42..ecaca5f4c9 100644 --- a/voxygen/src/anim/src/character/alpha.rs +++ b/voxygen/src/anim/src/character/alpha.rs @@ -26,13 +26,13 @@ impl Animation for AlphaAnimation { let lab = 1.0; - let foot = (((5.0) + let foot = (((1.0) / (0.2 - + 4.8 - * ((anim_time as f32 * lab as f32 * 1.3 * velocity).sin()).powf(2.0 as f32))) + + 0.8 + * ((anim_time as f32 * lab as f32 * 2.0 * velocity).sin()).powf(2.0 as f32))) .sqrt()) - * ((anim_time as f32 * lab as f32 * 1.3 * velocity).sin()); - + * ((anim_time as f32 * lab as f32 * 2.0 * velocity).sin()); + let slowersmooth = (anim_time as f32 * lab as f32 * 4.0).sin(); let accel_med = 1.0 - (anim_time as f32 * 16.0 * lab as f32).cos(); let accel_slow = 1.0 - (anim_time as f32 * 12.0 * lab as f32).cos(); let accel_fast = 1.0 - (anim_time as f32 * 24.0 * lab as f32).cos(); @@ -46,8 +46,8 @@ impl Animation for AlphaAnimation { / (0.4 + 4.6 * ((anim_time as f32 * lab as f32 * 18.0).sin()).powf(2.0 as f32))) .sqrt()) * ((anim_time as f32 * lab as f32 * 18.0).sin()); - let slower = (((5.0) - / (0.1 + 4.9 * ((anim_time as f32 * lab as f32 * 4.0).sin()).powf(2.0 as f32))) + let slower = (((1.0) + / (0.0001 + 0.999 * ((anim_time as f32 * lab as f32 * 4.0).sin()).powf(2.0 as f32))) .sqrt()) * ((anim_time as f32 * lab as f32 * 4.0).sin()); let slowax = (((5.0) @@ -262,33 +262,39 @@ impl Animation for AlphaAnimation { next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler; }, Some(ToolKind::Hammer(_)) => { - next.l_hand.offset = Vec3::new(-7.0, 5.5, 3.5); - next.l_hand.ori = Quaternion::rotation_x(0.3) * Quaternion::rotation_y(0.32); - next.l_hand.scale = Vec3::one() * 1.05; - next.r_hand.offset = Vec3::new(8.0, 7.75, 0.0); - next.r_hand.ori = Quaternion::rotation_x(0.3) * Quaternion::rotation_y(0.22); - next.r_hand.scale = Vec3::one() * 1.05; - next.main.offset = Vec3::new(6.0, 7.0, 0.0); - next.main.ori = Quaternion::rotation_x(0.3) - * Quaternion::rotation_y(-1.35) + next.l_hand.offset = Vec3::new(-12.0, 0.0, 0.0); + next.l_hand.ori = Quaternion::rotation_x(-0.0) * Quaternion::rotation_y(0.0); + next.l_hand.scale = Vec3::one() * 1.08; + next.r_hand.offset = Vec3::new(3.0, 0.0, 0.0); + next.r_hand.ori = Quaternion::rotation_x(0.0) * Quaternion::rotation_y(0.0); + next.r_hand.scale = Vec3::one() * 1.06; + next.main.offset = Vec3::new(0.0, 0.0, 0.0); + next.main.ori = Quaternion::rotation_x(0.0) + * Quaternion::rotation_y(-1.57) * Quaternion::rotation_z(1.57); + next.head.offset = Vec3::new(0.0, -2.0 + skeleton_attr.head.0, skeleton_attr.head.1); - next.head.ori = Quaternion::rotation_z(slower * 0.05) - * Quaternion::rotation_x(0.0 + slower * 0.05) - * Quaternion::rotation_y(slower * 0.05); + next.head.ori = Quaternion::rotation_z(slower * 0.03) + * Quaternion::rotation_x(slowersmooth * 0.1) + * Quaternion::rotation_y(slower * 0.05 + slowersmooth * 0.06) + * Quaternion::rotation_z((slowersmooth * -0.4).max(0.0)); next.head.scale = Vec3::one() * skeleton_attr.head_scale; next.chest.offset = Vec3::new(0.0, 0.0, 7.0); - next.chest.ori = Quaternion::rotation_z(slower * 0.2) - * Quaternion::rotation_x(0.0 + slower * 0.2) - * Quaternion::rotation_y(slower * 0.2); + next.chest.ori = Quaternion::rotation_z(slower * 0.18 + slowersmooth * 0.15) + * Quaternion::rotation_x(0.0 + slower * 0.18 + slowersmooth * 0.15) + * Quaternion::rotation_y(slower * 0.18 + slowersmooth * 0.15); next.belt.offset = Vec3::new(0.0, 0.0, -2.0); - next.belt.ori = next.chest.ori * -0.2; + next.belt.ori = Quaternion::rotation_z(slower * -0.1 + slowersmooth * -0.075) + * Quaternion::rotation_x(0.0 + slower * -0.1) + * Quaternion::rotation_y(slower * -0.1); next.shorts.offset = Vec3::new(0.0, 0.0, -5.0); - next.shorts.ori = next.chest.ori * -0.15; + next.shorts.ori = Quaternion::rotation_z(slower * -0.1 + slowersmooth * -0.075) + * Quaternion::rotation_x(0.0 + slower * -0.1) + * Quaternion::rotation_y(slower * -0.1); next.lantern.ori = Quaternion::rotation_x(slower * -0.7 + 0.4) * Quaternion::rotation_y(slower * 0.4); @@ -299,15 +305,15 @@ impl Animation for AlphaAnimation { if velocity > 0.5 { next.l_foot.offset = - Vec3::new(-skeleton_attr.foot.0, foot * -2.0, skeleton_attr.foot.2); + Vec3::new(-skeleton_attr.foot.0, foot * -6.0, skeleton_attr.foot.2); next.l_foot.ori = Quaternion::rotation_x(foot * -0.4) - * Quaternion::rotation_z((slower * 0.6).max(0.0)); + * Quaternion::rotation_z((slower * 0.3).max(0.0)); next.l_foot.scale = Vec3::one(); next.r_foot.offset = - Vec3::new(skeleton_attr.foot.0, foot * 2.0, skeleton_attr.foot.2); + Vec3::new(skeleton_attr.foot.0, foot * 6.0, skeleton_attr.foot.2); next.r_foot.ori = Quaternion::rotation_x(foot * 0.4) - * Quaternion::rotation_z((slower * 0.6).max(0.0)); + * Quaternion::rotation_z((slower * 0.3).max(0.0)); next.r_foot.scale = Vec3::one(); next.torso.offset = Vec3::new(0.0, 0.0, 0.1) * skeleton_attr.scaler; next.torso.ori = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(-0.15); @@ -335,10 +341,15 @@ impl Animation for AlphaAnimation { next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler; } - next.control.offset = Vec3::new(-4.0, 3.0 + slower * 2.0, 5.0 + slower * 5.0); - next.control.ori = Quaternion::rotation_x(-0.7 + slower * 1.8) - * Quaternion::rotation_y(0.0) - * Quaternion::rotation_z(1.4); + //next.control.offset = Vec3::new(-4.0, 3.0 + slower * 2.0, 5.0 + slower * + // 5.0); next.control.ori = Quaternion::rotation_x() + // * Quaternion::rotation_y(0.0) + // * Quaternion::rotation_z(1.4); + next.control.scale = Vec3::one(); + next.control.offset = Vec3::new(-8.0, 7.0, 1.0); + next.control.ori = Quaternion::rotation_x(-1.5 + slower * 1.5) + * Quaternion::rotation_y(slowersmooth * 0.35 - 0.3) + * Quaternion::rotation_z(1.4 + slowersmooth * 0.2); next.control.scale = Vec3::one(); next.torso.offset = Vec3::new(0.0, 0.0, 0.1) * skeleton_attr.scaler; diff --git a/voxygen/src/anim/src/character/leapmelee.rs b/voxygen/src/anim/src/character/leapmelee.rs new file mode 100644 index 0000000000..7a1a218401 --- /dev/null +++ b/voxygen/src/anim/src/character/leapmelee.rs @@ -0,0 +1,118 @@ +use super::{super::Animation, CharacterSkeleton, SkeletonAttr}; +use common::comp::item::{Hands, ToolKind}; +/* use std::f32::consts::PI; */ +use vek::*; + +pub struct LeapAnimation; + +impl Animation for LeapAnimation { + type Dependency = (Option, Option, Vec3, f64); + type Skeleton = CharacterSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"character_leapmelee\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "character_leapmelee")] + #[allow(clippy::approx_constant)] // TODO: Pending review in #587 + fn update_skeleton_inner( + skeleton: &Self::Skeleton, + (active_tool_kind, second_tool_kind, _velocity, _global_time): Self::Dependency, + anim_time: f64, + rate: &mut f32, + skeleton_attr: &SkeletonAttr, + ) -> Self::Skeleton { + *rate = 1.0; + let mut next = (*skeleton).clone(); + + let lab = 1.0; + let slowersmooth = (anim_time as f32 * lab as f32 * 4.0).sin(); + let slower = (((1.0) + / (0.0001 + 0.999 * ((anim_time as f32 * lab as f32 * 4.0).sin()).powf(2.0 as f32))) + .sqrt()) + * ((anim_time as f32 * lab as f32 * 4.0).sin()); + + if let Some(ToolKind::Hammer(_)) = active_tool_kind { + next.l_hand.offset = Vec3::new(-12.0, 0.0, 0.0); + next.l_hand.ori = Quaternion::rotation_x(-0.0) * Quaternion::rotation_y(0.0); + next.l_hand.scale = Vec3::one() * 1.08; + next.r_hand.offset = Vec3::new(3.0, 0.0, 0.0); + next.r_hand.ori = Quaternion::rotation_x(0.0) * Quaternion::rotation_y(0.0); + next.r_hand.scale = Vec3::one() * 1.06; + next.main.offset = Vec3::new(0.0, 0.0, 0.0); + next.main.ori = Quaternion::rotation_x(0.0) + * Quaternion::rotation_y(-1.57) + * Quaternion::rotation_z(1.57); + + next.head.offset = Vec3::new( + 0.0, + -2.0 + skeleton_attr.head.0 + slower * -1.0, + skeleton_attr.head.1, + ); + next.head.ori = Quaternion::rotation_z(slower * 0.05) + * Quaternion::rotation_x((slowersmooth * -0.25 + slower * 0.55).max(-0.2)) + * Quaternion::rotation_y(slower * 0.05); + next.head.scale = Vec3::one() * skeleton_attr.head_scale; + + next.chest.offset = Vec3::new(0.0, 0.0, 7.0); + next.chest.ori = Quaternion::rotation_z(slower * 0.08 + slowersmooth * 0.15) + * Quaternion::rotation_x(-0.3 + slower * 0.45 + slowersmooth * 0.26) + * Quaternion::rotation_y(slower * 0.18 + slowersmooth * 0.15); + + next.belt.offset = Vec3::new(0.0, 0.0, -2.0 + slower * -0.7); + next.belt.ori = Quaternion::rotation_z(slower * -0.16 + slowersmooth * -0.12) + * Quaternion::rotation_x(0.0 + slower * -0.06) + * Quaternion::rotation_y(slower * -0.05); + + next.shorts.offset = Vec3::new(0.0, 0.0, -5.0 + slower * -0.7); + next.shorts.ori = Quaternion::rotation_z(slower * -0.08 + slowersmooth * -0.08) + * Quaternion::rotation_x(0.0 + slower * -0.08 + slowersmooth * -0.08) + * Quaternion::rotation_y(slower * -0.07); + + next.lantern.ori = + Quaternion::rotation_x(slower * -0.7 + 0.4) * Quaternion::rotation_y(slower * 0.4); + + next.l_foot.offset = Vec3::new( + -skeleton_attr.foot.0, + slower * 3.0 + slowersmooth * -6.0 - 2.0, + skeleton_attr.foot.2, + ); + next.l_foot.ori = Quaternion::rotation_x(slower * -0.2 + slowersmooth * -0.3 - 0.2); + + next.r_foot.offset = Vec3::new( + skeleton_attr.foot.0, + slower * 2.0 + slowersmooth * -4.0 - 1.0, + -2.0 + skeleton_attr.foot.2, + ); + next.r_foot.ori = Quaternion::rotation_x(slower * -0.4 + slowersmooth * -0.6 - 1.0); + + next.control.scale = Vec3::one(); + next.control.offset = Vec3::new(-7.0, 7.0, 1.0); + next.control.ori = Quaternion::rotation_x(-0.7 + slower * 1.5) + * Quaternion::rotation_y(0.0) + * Quaternion::rotation_z(1.4 + slowersmooth * -0.4 + slower * 0.2); + next.control.scale = Vec3::one(); + } + next.lantern.offset = Vec3::new( + skeleton_attr.lantern.0, + skeleton_attr.lantern.1, + skeleton_attr.lantern.2, + ); + next.glider.offset = Vec3::new(0.0, 0.0, 10.0); + next.glider.scale = Vec3::one() * 0.0; + next.l_control.scale = Vec3::one(); + next.r_control.scale = Vec3::one(); + + next.second.scale = match ( + active_tool_kind.map(|tk| tk.into_hands()), + second_tool_kind.map(|tk| tk.into_hands()), + ) { + (Some(Hands::OneHand), Some(Hands::OneHand)) => Vec3::one(), + (_, _) => Vec3::zero(), + }; + + next.torso.offset = Vec3::new(0.0, 0.0, 0.0) * skeleton_attr.scaler; + next.torso.ori = Quaternion::rotation_z(0.0); + next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler; + next + } +} diff --git a/voxygen/src/anim/src/character/mod.rs b/voxygen/src/anim/src/character/mod.rs index 78237a3a02..6416638929 100644 --- a/voxygen/src/anim/src/character/mod.rs +++ b/voxygen/src/anim/src/character/mod.rs @@ -11,6 +11,7 @@ pub mod glidewield; pub mod gliding; pub mod idle; pub mod jump; +pub mod leapmelee; pub mod roll; pub mod run; pub mod shoot; @@ -26,9 +27,9 @@ pub use self::{ blockidle::BlockIdleAnimation, charge::ChargeAnimation, climb::ClimbAnimation, 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, + jump::JumpAnimation, leapmelee::LeapAnimation, roll::RollAnimation, run::RunAnimation, + shoot::ShootAnimation, sit::SitAnimation, spin::SpinAnimation, stand::StandAnimation, + swim::SwimAnimation, wield::WieldAnimation, }; use super::{Bone, FigureBoneData, Skeleton}; diff --git a/voxygen/src/anim/src/character/wield.rs b/voxygen/src/anim/src/character/wield.rs index a4d2e54c5c..eb11f819aa 100644 --- a/voxygen/src/anim/src/character/wield.rs +++ b/voxygen/src/anim/src/character/wield.rs @@ -194,19 +194,19 @@ impl Animation for WieldAnimation { next.control.scale = Vec3::one(); }, Some(ToolKind::Hammer(_)) => { - next.l_hand.offset = Vec3::new(-7.0, 5.5, 3.5); - next.l_hand.ori = Quaternion::rotation_x(0.3) * Quaternion::rotation_y(0.32); + next.l_hand.offset = Vec3::new(-12.0, 0.0, 0.0); + next.l_hand.ori = Quaternion::rotation_x(-0.0) * Quaternion::rotation_y(0.0); next.l_hand.scale = Vec3::one() * 1.08; - next.r_hand.offset = Vec3::new(8.0, 7.75, 0.0); - next.r_hand.ori = Quaternion::rotation_x(0.3) * Quaternion::rotation_y(0.22); + next.r_hand.offset = Vec3::new(2.0, 0.0, 0.0); + next.r_hand.ori = Quaternion::rotation_x(0.0) * Quaternion::rotation_y(0.0); next.r_hand.scale = Vec3::one() * 1.06; - next.main.offset = Vec3::new(6.0, 7.0, 0.0); - next.main.ori = Quaternion::rotation_x(0.3) - * Quaternion::rotation_y(-1.35) + next.main.offset = Vec3::new(0.0, 0.0, 0.0); + next.main.ori = Quaternion::rotation_x(0.0) + * Quaternion::rotation_y(-1.57) * Quaternion::rotation_z(1.57); - next.control.offset = Vec3::new(0.0, 0.0, 0.0); - next.control.ori = Quaternion::rotation_x(u_slow * 0.15) + next.control.offset = Vec3::new(6.0, 7.0, 1.0); + next.control.ori = Quaternion::rotation_x(0.3 + u_slow * 0.15) * Quaternion::rotation_y(0.0) * Quaternion::rotation_z(u_slowalt * 0.08); next.control.scale = Vec3::one(); diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index 4421fb5cf1..9357985bb7 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -116,6 +116,7 @@ image_ids! { flyingrod_m1: "voxygen.element.icons.debug_wand_m1", flyingrod_m2: "voxygen.element.icons.debug_wand_m2", charge: "voxygen.element.icons.skill_charge_3", + hammerleap: "voxygen.element.icons.skill_hammerleap", // Skillbar level_up: "voxygen.element.misc_bg.level_up", @@ -136,7 +137,6 @@ image_ids! { skillbar_slot_l_act: "voxygen.element.skillbar.skillbar_slot_l_active", skillbar_slot_r_act: "voxygen.element.skillbar.skillbar_slot_r_active", - // Other Icons/Art skull: "voxygen.element.icons.skull", skull_2: "voxygen.element.icons.skull_2", diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index c2aa0af80e..b8d21f71d8 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -707,7 +707,7 @@ impl<'a> Widget for Skillbar<'a> { Some(ToolKind::Sword(_)) => self.imgs.charge, Some(ToolKind::Dagger(_)) => self.imgs.onehdagger_m2, Some(ToolKind::Shield(_)) => self.imgs.onehshield_m2, - Some(ToolKind::Hammer(_)) => self.imgs.nothing, + Some(ToolKind::Hammer(_)) => self.imgs.hammerleap, Some(ToolKind::Axe(_)) => self.imgs.nothing, Some(ToolKind::Bow(_)) => self.imgs.bow_m2, Some(ToolKind::Staff(StaffKind::Sceptre)) => self.imgs.heal_0, diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 4567125201..cde859f370 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -674,6 +674,15 @@ impl FigureMgr { skeleton_attr, ) }, + CharacterState::LeapMelee(_) => { + anim::character::LeapAnimation::update_skeleton( + &target_base, + (active_tool_kind, second_tool_kind, vel.0, time), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ) + }, CharacterState::TripleStrike(s) => match s.stage { triple_strike::Stage::First => { anim::character::AlphaAnimation::update_skeleton(