diff --git a/voxygen/anim/src/character/divemelee.rs b/voxygen/anim/src/character/divemelee.rs new file mode 100644 index 0000000000..080959859c --- /dev/null +++ b/voxygen/anim/src/character/divemelee.rs @@ -0,0 +1,78 @@ +use super::{ + super::{vek::*, Animation}, + CharacterSkeleton, SkeletonAttr, +}; +use common::states::utils::StageSection; +use core::f32::consts::PI; + +pub struct DiveMeleeAnimation; +impl Animation for DiveMeleeAnimation { + type Dependency<'a> = (Option<&'a str>, Option, f32); + type Skeleton = CharacterSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"character_dive_melee\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "character_dive_melee")] + fn update_skeleton_inner<'a>( + skeleton: &Self::Skeleton, + (ability_id, stage_section, ground_dist): Self::Dependency<'a>, + anim_time: f32, + rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + *rate = 1.0; + let mut next = (*skeleton).clone(); + next.main_weapon_trail = true; + next.off_weapon_trail = true; + + next.main.position = Vec3::new(0.0, 0.0, 0.0); + next.main.orientation = Quaternion::rotation_z(0.0); + let ground_dist = ground_dist.clamp(0.0, 0.5) * 2.0; + let ground_dist = if ground_dist.is_nan() { + 0.0 + } else { + ground_dist + }; + + match ability_id { + Some("common.abilities.sword.cleaving_dive") => { + let (move1, move2, move3, move4) = match stage_section { + Some(StageSection::Movement) => (anim_time.min(1.0).powi(2), (1.0 - ground_dist).powi(2), 0.0, 0.0), + Some(StageSection::Action) => (1.0, 1.0, anim_time.powf(0.25), 0.0), + Some(StageSection::Recover) => (1.0, 1.0, 1.0, anim_time.powi(4)), + _ => (0.0, 0.0, 0.0, 0.0), + }; + + next.hand_l.position = Vec3::new(s_a.shl.0, s_a.shl.1, s_a.shl.2); + next.hand_l.orientation = + Quaternion::rotation_x(s_a.shl.3) * Quaternion::rotation_y(s_a.shl.4); + next.hand_r.position = + Vec3::new(-s_a.sc.0 + 6.0 + move1 * -12.0, -4.0 + move1 * 3.0, -2.0); + next.hand_r.orientation = Quaternion::rotation_x(0.9 + move1 * 0.5); + next.control.position = Vec3::new( + s_a.sc.0, + s_a.sc.1, + s_a.sc.2, + ); + next.control.orientation = + Quaternion::rotation_x(s_a.sc.3); + + next.torso.orientation.rotate_x(move1 * -0.8); + next.control.orientation.rotate_x(move1 * 1.5); + next.control.position += Vec3::new(move1 * 7.0, move1.powi(4) * -6.0, move1 * 20.0); + + next.torso.orientation.rotate_x(move2 * 0.8); + next.chest.orientation = Quaternion::rotation_x(move2 * -0.4); + next.control.orientation.rotate_x(move2 * -1.2); + next.control.position += Vec3::new(0.0, move2 * 12.0, move2 * -8.0); + + next.control.orientation.rotate_x(move3 * -1.2); + next.control.position += Vec3::new(0.0, move3 * 4.0, move3 * -8.0); + }, + _ => {}, + } + + next + } +} diff --git a/voxygen/anim/src/character/mod.rs b/voxygen/anim/src/character/mod.rs index c942d2512e..46d2dd5bd1 100644 --- a/voxygen/anim/src/character/mod.rs +++ b/voxygen/anim/src/character/mod.rs @@ -9,6 +9,7 @@ pub mod combomelee; pub mod consume; pub mod dance; pub mod dash; +pub mod divemelee; pub mod equip; pub mod finishermelee; pub mod glidewield; @@ -51,7 +52,7 @@ pub use self::{ sneakequip::SneakEquipAnimation, sneakwield::SneakWieldAnimation, spin::SpinAnimation, spinmelee::SpinMeleeAnimation, staggered::StaggeredAnimation, stand::StandAnimation, stunned::StunnedAnimation, swim::SwimAnimation, swimwield::SwimWieldAnimation, - talk::TalkAnimation, wallrun::WallrunAnimation, wield::WieldAnimation, + talk::TalkAnimation, wallrun::WallrunAnimation, wield::WieldAnimation, divemelee::DiveMeleeAnimation, }; use super::{make_bone, vek::*, FigureBoneData, Offsets, Skeleton, TrailSource}; use common::comp; diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 3bed64d83e..815ea66434 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -40,9 +40,9 @@ use common::{ mounting::Rider, resources::{DeltaTime, Time}, states::{equipping, idle, utils::StageSection, wielding}, - terrain::TerrainChunk, + terrain::{TerrainChunk, TerrainGrid, Block}, uid::UidAllocator, - vol::RectRasterableVol, + vol::{RectRasterableVol, ReadVol}, }; use common_base::span; use common_state::State; @@ -726,6 +726,8 @@ impl FigureMgr { let bodies = ecs.read_storage::(); + let terrain_grid = ecs.read_resource::(); + for ( i, ( @@ -1186,6 +1188,38 @@ impl FigureMgr { skeleton_attr, ) }, + CharacterState::DiveMelee(s) => { + let stage_time = s.timer.as_secs_f32(); + let stage_progress = match s.stage_section { + StageSection::Movement => { + stage_time + }, + StageSection::Action => { + stage_time / s.static_data.swing_duration.as_secs_f32() + }, + StageSection::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f32() + }, + _ => 0.0, + }; + let convert_vec3 = |vec3: anim::vek::Vec3<_>| { + Vec3::new(vec3.x, vec3.y, vec3.z) + }; + let ground_dist = terrain_grid + .ray(convert_vec3(pos.0), convert_vec3(pos.0 + vel.0)) + .until(Block::is_solid) + .cast() + .0 + .powi(2) + / vel.0.magnitude_squared(); + anim::character::DiveMeleeAnimation::update_skeleton( + &target_base, + (ability_id, Some(s.stage_section), ground_dist), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, CharacterState::ChargedRanged(s) => { let stage_time = s.timer.as_secs_f32();