diff --git a/assets/common/abilities/custom/claygolem/laser.ron b/assets/common/abilities/custom/claygolem/laser.ron index 7c4574d9c6..8e029678d4 100644 --- a/assets/common/abilities/custom/claygolem/laser.ron +++ b/assets/common/abilities/custom/claygolem/laser.ron @@ -1,6 +1,6 @@ BasicBeam( - buildup_duration: 0.20, - recover_duration: 0.20, + buildup_duration: 0.5, + recover_duration: 0.4, beam_duration: 0.25, damage: 100, tick_rate: 2.0, diff --git a/assets/voxygen/voxel/golem_central_manifest.ron b/assets/voxygen/voxel/golem_central_manifest.ron index 10ab717d32..97e5b4c84f 100644 --- a/assets/voxygen/voxel/golem_central_manifest.ron +++ b/assets/voxygen/voxel/golem_central_manifest.ron @@ -73,7 +73,7 @@ ), (ClayGolem, Male): ( head: ( - offset: (-10.5, -6.0, -5.0), + offset: (-10.5, -3.0, -3.0), central: ("npc.claygolem.male.head"), ), jaw: ( @@ -91,7 +91,7 @@ ), (ClayGolem, Female): ( head: ( - offset: (-10.5, -6.0, -5.0), + offset: (-10.5, -3.0, -3.0), central: ("npc.claygolem.male.head"), ), jaw: ( diff --git a/voxygen/anim/src/golem/beam.rs b/voxygen/anim/src/golem/beam.rs new file mode 100644 index 0000000000..f9d8132f9b --- /dev/null +++ b/voxygen/anim/src/golem/beam.rs @@ -0,0 +1,74 @@ +use super::{ + super::{vek::*, Animation}, + GolemSkeleton, SkeletonAttr, +}; +use common::{states::utils::StageSection, util::Dir}; +pub struct BeamAnimation; + +impl Animation for BeamAnimation { + type Dependency<'a> = (Option, f32, f32, Dir); + type Skeleton = GolemSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"golem_beam\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "golem_beam")] + + fn update_skeleton_inner<'a>( + skeleton: &Self::Skeleton, + (stage_section, _global_time, _timer, look_dir): Self::Dependency<'a>, + anim_time: f32, + _rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let (move1base, move1iso, move2base, move3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powf(0.25), anim_time.powf(0.25), 0.0, 0.0), + Some(StageSection::Cast) => (1.0, 0.0, 1.0, 0.0), + Some(StageSection::Recover) => (1.0, 0.0, 1.0, anim_time.powf(4.0)), + _ => (0.0, 0.0, 0.0, 0.0), + }; + + let pullback = 1.0 - move3; + let move1 = move1base * pullback; + let move2 = move2base * pullback; + + next.head.orientation = Quaternion::rotation_x(move1iso * 0.5 + move2 * (look_dir.z * 1.0)); + next.head.position = Vec3::new( + 0.0, + s_a.head.0, + s_a.head.1 - move2 * 5.0 * (look_dir.z * 1.0).min(0.0), + ); + + next.upper_torso.orientation = + Quaternion::rotation_x(move1iso * 0.3) * Quaternion::rotation_z(0.0); + + next.lower_torso.orientation = + Quaternion::rotation_z(0.0) * Quaternion::rotation_x(move1iso * -0.3); + + next.shoulder_l.orientation = + Quaternion::rotation_x(move1 * 0.8) * Quaternion::rotation_y(move1 * -0.5); + + next.shoulder_r.orientation = + Quaternion::rotation_x(move1 * 0.8) * Quaternion::rotation_y(move1 * 0.5); + next.shoulder_l.position = Vec3::new( + -s_a.shoulder.0, + s_a.shoulder.1 + move1 * 2.0, + s_a.shoulder.2 + move1 * -2.0, + ); + next.shoulder_r.position = Vec3::new( + s_a.shoulder.0, + s_a.shoulder.1 + move1 * 2.0, + s_a.shoulder.2 + move1 * -2.0, + ); + + next.hand_l.orientation = + Quaternion::rotation_z(0.0) * Quaternion::rotation_y(move1 * -1.1); + + next.hand_r.orientation = Quaternion::rotation_y(0.0) * Quaternion::rotation_y(move1 * 1.1); + + next.torso.position = Vec3::new(0.0, 0.0, 0.0); + next + } +} diff --git a/voxygen/anim/src/golem/mod.rs b/voxygen/anim/src/golem/mod.rs index 2e03caadc2..ef5acd9057 100644 --- a/voxygen/anim/src/golem/mod.rs +++ b/voxygen/anim/src/golem/mod.rs @@ -1,13 +1,15 @@ pub mod alpha; +pub mod beam; pub mod idle; pub mod run; pub mod shockwave; +pub mod shoot; pub mod spinmelee; // Reexports pub use self::{ - alpha::AlphaAnimation, idle::IdleAnimation, run::RunAnimation, shockwave::ShockwaveAnimation, - spinmelee::SpinMeleeAnimation, + alpha::AlphaAnimation, beam::BeamAnimation, idle::IdleAnimation, run::RunAnimation, + shockwave::ShockwaveAnimation, shoot::ShootAnimation, spinmelee::SpinMeleeAnimation, }; use super::{make_bone, vek::*, FigureBoneData, Skeleton}; @@ -120,7 +122,7 @@ impl<'a> From<&'a Body> for SkeletonAttr { head: match (body.species, body.body_type) { (StoneGolem, _) => (0.0, 2.0), (Treant, _) => (18.0, -8.0), - (ClayGolem, _) => (2.0, 9.0), + (ClayGolem, _) => (-2.0, 7.0), }, jaw: match (body.species, body.body_type) { (StoneGolem, _) => (0.0, 0.0), diff --git a/voxygen/anim/src/golem/shoot.rs b/voxygen/anim/src/golem/shoot.rs new file mode 100644 index 0000000000..e4d8b3ae1d --- /dev/null +++ b/voxygen/anim/src/golem/shoot.rs @@ -0,0 +1,61 @@ +use super::{ + super::{vek::*, Animation}, + GolemSkeleton, SkeletonAttr, +}; +use common::{states::utils::StageSection, util::Dir}; +pub struct ShootAnimation; + +impl Animation for ShootAnimation { + type Dependency<'a> = (Option, f32, f32, Dir); + type Skeleton = GolemSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"golem_shoot\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "golem_shoot")] + + fn update_skeleton_inner<'a>( + skeleton: &Self::Skeleton, + (stage_section, _global_time, _timer, look_dir): Self::Dependency<'a>, + anim_time: f32, + _rate: &mut f32, + _s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let (move1base, move2base, move3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powf(0.4), 0.0, 0.0), + Some(StageSection::Shoot) => (1.0, anim_time, 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time.powf(4.0)), + _ => (0.0, 0.0, 0.0), + }; + + let pullback = 1.0 - move3; + + let move1 = move1base * pullback; + let move2 = move2base * pullback; + + next.head.orientation = Quaternion::rotation_x(-0.2) * Quaternion::rotation_z(move1 * -0.5); + + next.upper_torso.orientation = + Quaternion::rotation_x(0.0) * Quaternion::rotation_z(move1 * 0.5); + + next.lower_torso.orientation = + Quaternion::rotation_z(move1 * -0.5) * Quaternion::rotation_x(0.0); + + next.shoulder_l.orientation = + Quaternion::rotation_y(0.0) * Quaternion::rotation_z(move1 * 0.7); + + next.shoulder_r.orientation = Quaternion::rotation_x(move1 * (look_dir.z * 1.2 + 1.57)) + * Quaternion::rotation_y(move1 * 0.0); + + next.hand_l.orientation = + Quaternion::rotation_z(move1 * -0.3) * Quaternion::rotation_x(move1 * 1.3); + + next.hand_r.orientation = Quaternion::rotation_y(move1 * -0.3) + * Quaternion::rotation_z(move1 * -0.9 + move2 * -1.6); + + next.torso.position = Vec3::new(0.0, 0.0, 0.0); + next + } +} diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index df94a7fe52..be968bb815 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -4327,6 +4327,51 @@ impl FigureMgr { skeleton_attr, ) }, + CharacterState::BasicRanged(s) => { + let stage_time = s.timer.as_secs_f32(); + + let stage_progress = match s.stage_section { + StageSection::Buildup => { + stage_time / s.static_data.buildup_duration.as_secs_f32() + }, + StageSection::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f32() + }, + + _ => 0.0, + }; + + anim::golem::ShootAnimation::update_skeleton( + &target_base, + (Some(s.stage_section), time, state.state_time, look_dir), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, + CharacterState::BasicBeam(s) => { + let stage_time = s.timer.as_secs_f32(); + + let stage_progress = match s.stage_section { + StageSection::Buildup => { + stage_time / s.static_data.buildup_duration.as_secs_f32() + }, + StageSection::Cast => s.timer.as_secs_f32(), + StageSection::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f32() + }, + + _ => 0.0, + }; + + anim::golem::BeamAnimation::update_skeleton( + &target_base, + (Some(s.stage_section), time, state.state_time, look_dir), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, CharacterState::BasicMelee(s) => { let stage_time = s.timer.as_secs_f32(); let stage_progress = match s.stage_section {