From 7a23314e3b2251452a7a93b144c6c5a63c97e01e Mon Sep 17 00:00:00 2001 From: James Melkonian Date: Tue, 5 Mar 2024 23:26:44 -0800 Subject: [PATCH] bowser spin animation --- .cargo/config | 2 +- .../common/abilities/ability_set_manifest.ron | 7 + .../abilities/custom/rocksnapper/dash.ron | 28 +++ .../custom/rocksnapper/singlestrike.ron | 25 +++ .../custom/rocksnapper/triplestrike.ron | 65 ++++++ .../items/npc_weapons/unique/rocksnapper.ron | 20 ++ common/src/comp/inventory/loadout_builder.rs | 3 + voxygen/anim/src/quadruped_low/dash.rs | 199 +++++++++++++----- voxygen/src/scene/figure/mod.rs | 1 + 9 files changed, 301 insertions(+), 49 deletions(-) create mode 100644 assets/common/abilities/custom/rocksnapper/dash.ron create mode 100644 assets/common/abilities/custom/rocksnapper/singlestrike.ron create mode 100644 assets/common/abilities/custom/rocksnapper/triplestrike.ron create mode 100644 assets/common/items/npc_weapons/unique/rocksnapper.ron diff --git a/.cargo/config b/.cargo/config index e78c87c91f..89c3d55c3a 100644 --- a/.cargo/config +++ b/.cargo/config @@ -1,6 +1,6 @@ [target.x86_64-unknown-linux-gnu] rustflags = [ - "-C", "link-arg=-fuse-ld=gold", + "-C", "link-arg=-fuse-ld=mold", ] [target.x86_64-pc-windows-gnu] diff --git a/assets/common/abilities/ability_set_manifest.ron b/assets/common/abilities/ability_set_manifest.ron index f6c8edf177..3ada6d0154 100644 --- a/assets/common/abilities/ability_set_manifest.ron +++ b/assets/common/abilities/ability_set_manifest.ron @@ -535,6 +535,13 @@ secondary: Simple(None, "common.abilities.custom.quadlowbasic.singlestrike"), abilities: [], ), + Custom("Rocksnapper"): ( + primary: Simple(None, "common.abilities.custom.rocksnapper.triplestrike"), + secondary: Simple(None, "common.abilities.custom.rocksnapper.singlestrike"), + abilities: [ + Simple(None, "common.abilities.custom.rocksnapper.dash"), + ], + ), Custom("Quad Low Beam"): ( primary: Simple(None, "common.abilities.custom.quadlowbeam.lifestealbeam"), secondary: Simple(None, "common.abilities.custom.quadlowbreathe.triplestrike"), diff --git a/assets/common/abilities/custom/rocksnapper/dash.ron b/assets/common/abilities/custom/rocksnapper/dash.ron new file mode 100644 index 0000000000..eea0872892 --- /dev/null +++ b/assets/common/abilities/custom/rocksnapper/dash.ron @@ -0,0 +1,28 @@ +DashMelee( + energy_cost: 0, + melee_constructor: ( + kind: Bash( + damage: 16.0, + poise: 0.0, + knockback: 4.0, + energy_regen: 0.0, + ), + scaled: Some(( + kind: Bash( + damage: 36.0, + poise: 8.0, + knockback: 23.0, + energy_regen: 0.0, + ))), + range: 2.5, + angle: 360.0, + ), + energy_drain: 0, + forward_speed: 5.0, + buildup_duration: 1.0, + charge_duration: 2.0, + swing_duration: 2.0, + recover_duration: 0.5, + ori_modifier: 0.3, + charge_through: true, +) diff --git a/assets/common/abilities/custom/rocksnapper/singlestrike.ron b/assets/common/abilities/custom/rocksnapper/singlestrike.ron new file mode 100644 index 0000000000..fd8b7ae6f6 --- /dev/null +++ b/assets/common/abilities/custom/rocksnapper/singlestrike.ron @@ -0,0 +1,25 @@ +ComboMelee2( + strikes: [ + ( + melee_constructor: ( + kind: Bash( + damage: 36, + poise: 28, + knockback: 3, + energy_regen: 0, + ), + range: 3.0, + angle: 90.0, + ), + buildup_duration: 0.5, + swing_duration: 0.2, + hit_timing: 0.5, + recover_duration: 0.5, + movement: ( + swing: Some(Forward(0.1)), + ), + ori_modifier: 0.6, + ), + ], + energy_cost_per_strike: 0, +) diff --git a/assets/common/abilities/custom/rocksnapper/triplestrike.ron b/assets/common/abilities/custom/rocksnapper/triplestrike.ron new file mode 100644 index 0000000000..5743aeed47 --- /dev/null +++ b/assets/common/abilities/custom/rocksnapper/triplestrike.ron @@ -0,0 +1,65 @@ +ComboMelee2( + strikes: [ + ( + melee_constructor: ( + kind: Slash( + damage: 36, + poise: 24, + knockback: 3, + energy_regen: 0, + ), + range: 4.0, + angle: 30.0, + ), + buildup_duration: 0.75, + swing_duration: 0.45, + hit_timing: 0.5, + recover_duration: 0.4, + movement: ( + swing: Some(Forward(0.4)), + ), + ori_modifier: 0.65, + ), + ( + melee_constructor: ( + kind: Stab( + damage: 18, + poise: 18, + knockback: 15, + energy_regen: 0, + ), + range: 3.5, + angle: 75.0, + ), + buildup_duration: 0.35, + swing_duration: 0.35, + hit_timing: 0.5, + recover_duration: 0.3, + movement: ( + swing: Some(Forward(0.2)), + ), + ori_modifier: 0.65, + ), + ( + melee_constructor: ( + kind: Bash( + damage: 28, + poise: 36, + knockback: 3, + energy_regen: 0, + ), + range: 3.0, + angle: 55.0, + ), + buildup_duration: 0.55, + swing_duration: 0.25, + hit_timing: 0.5, + recover_duration: 0.6, + movement: ( + swing: Some(Forward(0.3)), + ), + ori_modifier: 0.65, + ), + ], + energy_cost_per_strike: 0, +) diff --git a/assets/common/items/npc_weapons/unique/rocksnapper.ron b/assets/common/items/npc_weapons/unique/rocksnapper.ron new file mode 100644 index 0000000000..fc2d2e3153 --- /dev/null +++ b/assets/common/items/npc_weapons/unique/rocksnapper.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Rocksnapper", + legacy_description: "Rocksnapper's totally awesome legacy description", + kind: Tool(( + kind: Natural, + hands: Two, + stats: ( + equip_time_secs: 0.01, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("Rocksnapper")), +) diff --git a/common/src/comp/inventory/loadout_builder.rs b/common/src/comp/inventory/loadout_builder.rs index 6cfdee57a7..6f0f480c18 100644 --- a/common/src/comp/inventory/loadout_builder.rs +++ b/common/src/comp/inventory/loadout_builder.rs @@ -686,6 +686,9 @@ fn default_main_tool(body: &Body) -> Item { quadruped_low::Species::Driggle => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.driggle", )), + quadruped_low::Species::Rocksnapper => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.rocksnapper", + )), _ => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.quadlowbasic", )), diff --git a/voxygen/anim/src/quadruped_low/dash.rs b/voxygen/anim/src/quadruped_low/dash.rs index 5f0e4b1432..5b54d8321f 100644 --- a/voxygen/anim/src/quadruped_low/dash.rs +++ b/voxygen/anim/src/quadruped_low/dash.rs @@ -9,7 +9,7 @@ use std::f32::consts::PI; pub struct DashAnimation; impl Animation for DashAnimation { - type Dependency<'a> = (f32, f32, Option, f32); + type Dependency<'a> = (Option<&'a str>, f32, f32, Option, f32); type Skeleton = QuadrupedLowSkeleton; #[cfg(feature = "use-dyn-lib")] @@ -18,64 +18,167 @@ impl Animation for DashAnimation { #[cfg_attr(feature = "be-dyn-lib", export_name = "quadruped_low_dash")] fn update_skeleton_inner( skeleton: &Self::Skeleton, - (_velocity, global_time, stage_section, timer): Self::Dependency<'_>, + (ability_id, _velocity, global_time, stage_section, timer): Self::Dependency<'_>, anim_time: f32, _rate: &mut f32, - _s_a: &SkeletonAttr, + s_a: &SkeletonAttr, ) -> Self::Skeleton { let mut next = (*skeleton).clone(); - let (movement1base, chargemovementbase, movement2base, movement3) = match stage_section { - Some(StageSection::Buildup) => (anim_time.sqrt(), 0.0, 0.0, 0.0), - Some(StageSection::Charge) => (1.0, 1.0, 0.0, 0.0), - Some(StageSection::Action) => (1.0, 1.0, anim_time.powi(4), 0.0), - Some(StageSection::Recover) => (1.0, 1.0, 1.0, anim_time), - _ => (0.0, 0.0, 0.0, 0.0), - }; - let pullback = 1.0 - movement3; - let subtract = global_time - timer; - let check = subtract - subtract.trunc(); - let mirror = (check - 0.5).signum(); - let twitch1 = (mirror * movement1base * 9.5).sin(); - let twitch1fast = (mirror * movement1base * 25.0).sin(); - //let twitch3 = (mirror * movement3 * 4.0).sin(); - //let movement1 = mirror * movement1base * pullback; - //let movement2 = mirror * movement2base * pullback; - let movement1abs = movement1base * pullback; - let movement2abs = movement2base * pullback; - let short = ((1.0 / (0.72 + 0.28 * ((anim_time * 16.0_f32 + PI * 0.25).sin()).powi(2))) - .sqrt()) - * ((anim_time * 16.0_f32 + PI * 0.25).sin()) - * chargemovementbase - * pullback; - let shortalt = (anim_time * 16.0_f32 + PI * 0.25).sin() * chargemovementbase * pullback; + match ability_id { + Some("common.abilities.custom.rocksnapper.dash") => { + let (movement1, charge, movement2, movement3) = match stage_section { + Some(StageSection::Buildup) => (anim_time, 0.0, 0.0, 0.0), + Some(StageSection::Charge) => (1.0, anim_time, 0.0, 0.0), + Some(StageSection::Action) => (1.0, 1.0, anim_time, 0.0), + Some(StageSection::Recover) => (1.0, 1.0, 1.0, anim_time), + _ => (0.0, 0.0, 0.0, 0.0), + }; + let subtract = global_time - timer; + let check = subtract - subtract.trunc(); + let mirror = (check - 0.5).signum(); + let twitch1 = (mirror * movement1.sqrt() * 9.5).sin(); + fn quintic(x: f32) -> f32 { x.powf(0.2) } + let quick_movement1 = movement1.powf(0.2); + //let quick_movement3 = movement3.powf(0.2); + let quick_movement3 = elastic(movement3); + next.head_upper.position = Vec3::new( + 0.0, + s_a.head_upper.0 + (-1.0 * quick_movement1 + quick_movement3) * 10.0, + s_a.head_upper.1, + ); + next.head_upper.scale = Vec3::one() * (1.0 - movement1 + quick_movement3); + next.head_lower.position = Vec3::new( + 0.0, + s_a.head_lower.0 + (-1.0 * quick_movement1 + quick_movement3) * 10.0, + s_a.head_lower.1, + ); + next.head_lower.scale = Vec3::one() * (1.0 - movement1 + quick_movement3); + next.foot_fl.position = Vec3::new( + -s_a.feet_f.0 + (quick_movement1 - quick_movement3) * 8.0, + s_a.feet_f.1 + (-1.0 * quick_movement1 + quick_movement3) * 8.0, + s_a.feet_f.2 + (quick_movement1 - quick_movement3) * 8.0, + ); + next.foot_fl.scale = Vec3::one() * (1.0 - movement1 + quick_movement3); + next.foot_fr.position = Vec3::new( + s_a.feet_f.0 - (quick_movement1 - quick_movement3) * 8.0, + s_a.feet_f.1 + (-1.0 * quick_movement1 + quick_movement3) * 8.0, + s_a.feet_f.2 + (quick_movement1 - quick_movement3) * 8.0, + ); + next.foot_fr.scale = Vec3::one() * (1.0 - movement1 + quick_movement3); + next.foot_bl.position = Vec3::new( + -s_a.feet_b.0 + (quick_movement1 - quick_movement3) * 8.0, + s_a.feet_b.1 + (quick_movement1 - quick_movement3) * 8.0, + s_a.feet_b.2 + (quick_movement1 - quick_movement3) * 8.0, + ); + next.foot_bl.scale = Vec3::one() * (1.0 - movement1 + quick_movement3); + next.foot_br.position = Vec3::new( + s_a.feet_b.0 - (quick_movement1 - quick_movement3) * 8.0, + s_a.feet_b.1 + (quick_movement1 - quick_movement3) * 8.0, + s_a.feet_b.2 + (quick_movement1 - quick_movement3) * 8.0, + ); + next.foot_br.scale = Vec3::one() * (1.0 - movement1 + quick_movement3); + next.tail_front.position = Vec3::new( + 0.0, + s_a.tail_front.0 + (quick_movement1 - quick_movement3) * 20.0, + s_a.tail_front.1, + ); + next.tail_front.scale = Vec3::one() * (1.0 - movement1 + quick_movement3); + next.tail_rear.position = Vec3::new( + 0.0, + s_a.tail_rear.0 + (quick_movement1 - quick_movement3) * 20.0, + s_a.tail_rear.1, + ); + next.tail_rear.scale = Vec3::one() * (1.0 - movement1 + movement3); - next.head_upper.orientation = - Quaternion::rotation_x(movement1abs * 0.4 + movement2abs * 0.3) - * Quaternion::rotation_z(short * -0.06 + twitch1 * -0.3); + fn bounce(x: f32) -> f32 { + if x < (1.0 / 2.75) { + 7.5625 * x.powi(2) + } else if x < (2.0 / 2.75) { + 7.5625 * (x - (1.5 / 2.75)).powi(2) + 0.75 + } else if x < (2.5 / 2.75) { + 7.5625 * (x - (2.25 / 2.75)).powi(2) + 0.9375 + } else { + 7.5625 * (x - (2.625 / 2.75)).powi(2) + 0.984375 + } + } - next.head_lower.orientation = - Quaternion::rotation_x(movement1abs * -0.4 + movement2abs * -0.5) - * Quaternion::rotation_z(short * 0.15 + twitch1 * 0.3); + fn elastic(x: f32) -> f32 { + fn f(x: f32, a: f32, b: f32) -> f32 { + let p = 0.8; + b + a * 2.0_f32.powf(a * 10.0 * x) * ((4.0 * PI * x) / p).cos() + } + f(x, -1.0, 1.0) / f(1.0, -1.0, 1.0) + } - next.jaw.orientation = Quaternion::rotation_x( - twitch1fast * 0.2 - + movement1abs * -0.3 - + movement2abs * 1.2 - + chargemovementbase * -0.5, - ); - next.chest.orientation = - Quaternion::rotation_z(twitch1 * 0.06) * Quaternion::rotation_y(short * 0.06); + next.chest.position = Vec3::new( + 0.0, + 0.0, + s_a.chest.1 - bounce(movement1) * 5.0 + elastic(movement3) * 5.0, + ); + let smooth_end_charge = if charge < 0.5 { + charge + } else { + 3.0 * charge.powi(2) - 2.0 * charge.powi(3) + }; + next.chest.orientation = + Quaternion::rotation_z(2.0 * PI * movement1 + 4.0 * PI * charge); + }, + _ => { + let (movement1, chargemovementbase, movement2, movement3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.sqrt(), 0.0, 0.0, 0.0), + Some(StageSection::Charge) => (1.0, 1.0, 0.0, 0.0), + Some(StageSection::Action) => (1.0, 1.0, anim_time.powi(4), 0.0), + Some(StageSection::Recover) => (1.0, 1.0, 1.0, anim_time), + _ => (0.0, 0.0, 0.0, 0.0), + }; + let pullback = 1.0 - movement3; + let subtract = global_time - timer; + let check = subtract - subtract.trunc(); + let mirror = (check - 0.5).signum(); + let twitch1 = (mirror * movement1 * 9.5).sin(); + let twitch1fast = (mirror * movement1 * 25.0).sin(); + //let twitch3 = (mirror * movement3 * 4.0).sin(); + //let movement1 = mirror * movement1 * pullback; + //let movement2 = mirror * movement2 * pullback; + let movement1abs = movement1 * pullback; + let movement2abs = movement2 * pullback; + let short = ((1.0 + / (0.72 + 0.28 * ((anim_time * 16.0_f32 + PI * 0.25).sin()).powi(2))) + .sqrt()) + * ((anim_time * 16.0_f32 + PI * 0.25).sin()) + * chargemovementbase + * pullback; + let shortalt = + (anim_time * 16.0_f32 + PI * 0.25).sin() * chargemovementbase * pullback; - next.tail_front.orientation = Quaternion::rotation_x( - 0.15 + movement1abs * -0.4 + movement2abs * 0.2 + chargemovementbase * 0.2, - ) * Quaternion::rotation_z(shortalt * 0.15); + next.head_upper.orientation = + Quaternion::rotation_x(movement1abs * 0.4 + movement2abs * 0.3) + * Quaternion::rotation_z(short * -0.06 + twitch1 * -0.3); - next.tail_rear.orientation = - Quaternion::rotation_x( - -0.12 + movement1abs * -0.4 + movement2abs * 0.2 + chargemovementbase * 0.2, - ) * Quaternion::rotation_z(shortalt * 0.15 + twitch1fast * 0.3); + next.head_lower.orientation = + Quaternion::rotation_x(movement1abs * -0.4 + movement2abs * -0.5) + * Quaternion::rotation_z(short * 0.15 + twitch1 * 0.3); + next.jaw.orientation = Quaternion::rotation_x( + twitch1fast * 0.2 + + movement1abs * -0.3 + + movement2abs * 1.2 + + chargemovementbase * -0.5, + ); + next.chest.orientation = + Quaternion::rotation_z(twitch1 * 0.06) * Quaternion::rotation_y(short * 0.06); + + next.tail_front.orientation = Quaternion::rotation_x( + 0.15 + movement1abs * -0.4 + movement2abs * 0.2 + chargemovementbase * 0.2, + ) * Quaternion::rotation_z(shortalt * 0.15); + + next.tail_rear.orientation = + Quaternion::rotation_x( + -0.12 + movement1abs * -0.4 + movement2abs * 0.2 + chargemovementbase * 0.2, + ) * Quaternion::rotation_z(shortalt * 0.15 + twitch1fast * 0.3); + }, + } next } } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index dbda2c46bb..ad0c6c145f 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -3098,6 +3098,7 @@ impl FigureMgr { anim::quadruped_low::DashAnimation::update_skeleton( &target_base, ( + ability_id, rel_vel.magnitude(), time, Some(s.stage_section),