diff --git a/assets/common/abilities/spear/doublestrike.ron b/assets/common/abilities/spear/doublestrike.ron new file mode 100644 index 0000000000..ce79b87260 --- /dev/null +++ b/assets/common/abilities/spear/doublestrike.ron @@ -0,0 +1,35 @@ +ComboMelee( + stage_data: [ + ( + stage: 1, + base_damage: 90, + damage_increase: 10, + knockback: 8.0, + range: 3.5, + angle: 50.0, + base_buildup_duration: 350, + base_swing_duration: 75, + base_recover_duration: 400, + forward_movement: 2.5, + ), + ( + stage: 2, + base_damage: 130, + damage_increase: 15, + knockback: 12.0, + range: 3.5, + angle: 30.0, + base_buildup_duration: 500, + base_swing_duration: 100, + base_recover_duration: 500, + forward_movement: 2.0, + ), + ], + initial_energy_gain: 25, + max_energy_gain: 175, + energy_increase: 30, + speed_increase: 0.075, + max_speed_increase: 1.6, + scales_from_combo: 2, + is_interruptible: false, +) \ No newline at end of file diff --git a/assets/common/abilities/weapon_ability_manifest.ron b/assets/common/abilities/weapon_ability_manifest.ron index bf5bb437ac..5f415d04e1 100644 --- a/assets/common/abilities/weapon_ability_manifest.ron +++ b/assets/common/abilities/weapon_ability_manifest.ron @@ -29,6 +29,12 @@ (Some(Bow(UnlockRepeater)), "common.abilities.bow.repeater"), ], ), + Spear: ( + primary: "common.abilities.spear.doublestrike", + secondary: "common.abilities.spear.doublestrike", + skills: [], + + ), Staff: ( primary: "common.abilities.staff.firebomb", secondary: "common.abilities.staff.flamethrower", diff --git a/assets/common/items/npc_weapons/spear/wooden_spear.ron b/assets/common/items/npc_weapons/spear/wooden_spear.ron new file mode 100644 index 0000000000..e24f70e1c7 --- /dev/null +++ b/assets/common/items/npc_weapons/spear/wooden_spear.ron @@ -0,0 +1,15 @@ +ItemDef( + name: "Wooden Spear", + description: "Testing", + kind: Tool( + ( + kind: Spear, + stats: ( + equip_time_millis: 250, + power: 1.0, + speed: 1.0 + ), + ) + ), + quality: Low, +) diff --git a/assets/voxygen/voxel/biped_small_weapon_manifest.ron b/assets/voxygen/voxel/biped_small_weapon_manifest.ron index 06850173f8..82ad7e89c7 100644 --- a/assets/voxygen/voxel/biped_small_weapon_manifest.ron +++ b/assets/voxygen/voxel/biped_small_weapon_manifest.ron @@ -1,74 +1,10 @@ ({ - (Gnome, Male): ( - main: ( - offset: (-1.5, -3.0, -5.0), - weapon: ("weapon.spear.sahagin"), - ), + "common.items.npc_weapons.spear.wooden_spear": ( + vox_spec: ("weapon.spear.sahagin", (-1.5, -3.0, -5.0)), + color: None ), - (Gnome, Female): ( - main: ( - offset: (-1.5, -3.0, -5.0), - weapon: ("weapon.spear.sahagin"), - ), - ), - (Sahagin, Male): ( - main: ( - offset: (-1.5, -3.0, -5.0), - weapon: ("weapon.spear.sahagin"), - ), - ), - (Sahagin, Female): ( - main: ( - offset: (-1.5, -3.0, -5.0), - weapon: ("weapon.spear.sahagin"), - ), - ), - (Adlet, Male): ( - main: ( - offset: (-0.5, -3.0, -5.0), - weapon: ("weapon.spear.adlet"), - ), - ), - (Adlet, Female): ( - main: ( - offset: (-0.5, -3.0, -5.0), - weapon: ("weapon.spear.adlet"), - ), - ), - (Gnarling, Male): ( - main: ( - offset: (-0.5, -3.0, -5.0), - weapon: ("weapon.spear.adlet"), - ), - ), - (Gnarling, Female): ( - main: ( - offset: (-0.5, -3.0, -5.0), - weapon: ("weapon.spear.adlet"), - ), - ), - (Mandragora, Male): ( - main: ( - offset: (-0.5, -3.0, -5.0), - weapon: ("weapon.spear.adlet"), - ), - ), - (Mandragora, Female): ( - main: ( - offset: (-0.5, -3.0, -5.0), - weapon: ("weapon.spear.adlet"), - ), - ), - (Kappa, Male): ( - main: ( - offset: (-0.5, -3.0, -5.0), - weapon: ("weapon.spear.adlet"), - ), - ), - (Kappa, Female): ( - main: ( - offset: (-0.5, -3.0, -5.0), - weapon: ("weapon.spear.adlet"), - ), + "common.items.weapon.spear.adlet": ( + vox_spec: ("weapon.spear.adlet", (-0.5, -3.0, -5.0)), + color: None ), }) diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 11dad4f3a9..4dce7a4a0e 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -23,6 +23,7 @@ pub enum ToolKind { Staff, Sceptre, Shield, + Spear, Unique(UniqueKind), Debug, Farming, @@ -383,4 +384,5 @@ pub enum UniqueKind { TheropodBasic, TheropodBird, ObjectTurret, + WoodenSpear, } diff --git a/common/src/comp/inventory/loadout_builder.rs b/common/src/comp/inventory/loadout_builder.rs index 5f1620709c..7184d94772 100644 --- a/common/src/comp/inventory/loadout_builder.rs +++ b/common/src/comp/inventory/loadout_builder.rs @@ -1,5 +1,5 @@ use crate::comp::{ - biped_large, golem, + biped_large, biped_small, golem, inventory::{ loadout::Loadout, slot::{ArmorSlot, EquipSlot}, @@ -242,6 +242,19 @@ impl LoadoutBuilder { "common.items.npc_weapons.unique.turret", )); }, + Body::BipedSmall(biped_small) => match (biped_small.species, biped_small.body_type) + { + (biped_small::Species::Gnome, _) => { + main_tool = Some(Item::new_from_asset_expect( + "common.items.npc_weapons.spear.wooden_spear", + )); + }, + _ => { + main_tool = Some(Item::new_from_asset_expect( + "common.items.npc_weapons.spear.wooden_spear", + )); + }, + }, _ => {}, }; } diff --git a/voxygen/anim/src/biped_small/alpha.rs b/voxygen/anim/src/biped_small/alpha.rs new file mode 100644 index 0000000000..fe42f0c368 --- /dev/null +++ b/voxygen/anim/src/biped_small/alpha.rs @@ -0,0 +1,109 @@ +use super::{ + super::{vek::*, Animation}, + BipedSmallSkeleton, SkeletonAttr, +}; +use common::states::utils::StageSection; +use std::f32::consts::PI; + +pub struct AlphaAnimation; + +type AlphaAnimationDependency = ( + Vec3, + Vec3, + Vec3, + f64, + Vec3, + f32, + Option, + f64, +); + +impl Animation for AlphaAnimation { + type Dependency = AlphaAnimationDependency; + type Skeleton = BipedSmallSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"biped_small_alpha\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "biped_small_alpha")] + + fn update_skeleton_inner( + skeleton: &Self::Skeleton, + (velocity, _orientation, _last_ori, global_time, _avg_vel, acc_vel, stage_section, timer): Self::Dependency, + anim_time: f64, + _rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + let speed = Vec2::::from(velocity).magnitude(); + + let fastacc = (acc_vel * 2.0).sin(); + let fast = (anim_time as f32 * 10.0).sin(); + let fastalt = (anim_time as f32 * 10.0 + PI / 2.0).sin(); + let slow = (anim_time as f32 * 2.0).sin(); + + let speednorm = speed / 9.4; + let speednormcancel = 1.0 - speednorm; + + let (movement1base, movement2base, movement3) = match stage_section { + Some(StageSection::Buildup) => ((anim_time as f32).sqrt(), 0.0, 0.0), + Some(StageSection::Swing) => (1.0, (anim_time as f32).powi(4), 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time as f32), + _ => (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() as f32; + let movement1 = mirror * movement1base * pullback; + let movement2 = mirror * movement2base * pullback; + let movement1abs = movement1base * pullback; + let movement2abs = movement2base * pullback; + + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); + next.head.orientation = Quaternion::rotation_x(movement1abs * -0.1 + movement2abs * 0.5) + * Quaternion::rotation_z(movement1abs * -0.2 + movement2abs * 0.6) + * Quaternion::rotation_y(movement1abs * 0.3 + movement2abs * -0.5); + next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1) / 13.0; + next.chest.orientation = Quaternion::rotation_z(movement1abs * 0.5 + movement2abs * -0.6); + + next.shorts.position = Vec3::new(0.0, s_a.shorts.0, s_a.shorts.1); + next.shorts.orientation = Quaternion::rotation_z(movement1abs * -0.2 + movement2abs * 0.2); + + next.main.position = Vec3::new(0.0, 0.0, 0.0); + next.main.orientation = Quaternion::rotation_x(0.0); + + next.hand_l.position = Vec3::new(s_a.grip.0 * 4.0, 0.0, s_a.grip.2); + next.hand_r.position = Vec3::new(-s_a.grip.0 * 4.0, 0.0, s_a.grip.2); + + next.hand_l.orientation = Quaternion::rotation_x(0.0); + next.hand_r.orientation = Quaternion::rotation_x(0.0); + + next.control_l.position = Vec3::new(1.0 - s_a.grip.0 * 2.0, 2.0, -2.0); + next.control_r.position = Vec3::new(-1.0 + s_a.grip.0 * 2.0, 2.0, 2.0); + + next.control.position = Vec3::new( + -3.0 + movement1abs * -3.0 + movement2abs * 5.0, + s_a.grip.2 + movement1abs * -12.0 + movement2abs * 17.0, + -s_a.grip.2 / 2.5 + s_a.grip.0 * -2.0 + movement2abs * 10.0, + ); + + next.control_l.orientation = + Quaternion::rotation_x(PI / 1.5 + movement1abs * -1.0 + movement2abs * 3.0) + * Quaternion::rotation_y(-0.3); + next.control_r.orientation = Quaternion::rotation_x( + PI / 1.5 + s_a.grip.0 * 0.2 + movement1abs * -1.0 + movement2abs * 3.0, + ) * Quaternion::rotation_y(0.5 + s_a.grip.0 * 0.2); + + next.control.orientation = + Quaternion::rotation_x(-1.35 + movement1abs * -0.3 + movement2abs * 1.0) + * Quaternion::rotation_z(movement1abs * 1.0 + movement2abs * -1.8) + * Quaternion::rotation_y(movement2abs * 0.5); + + next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1); + next.tail.orientation = Quaternion::rotation_x(0.05 * fastalt * speednormcancel) + * Quaternion::rotation_z(fast * 0.15 * speednormcancel); + + next + } +} diff --git a/voxygen/anim/src/biped_small/idle.rs b/voxygen/anim/src/biped_small/idle.rs index 72348a531b..840fc1214b 100644 --- a/voxygen/anim/src/biped_small/idle.rs +++ b/voxygen/anim/src/biped_small/idle.rs @@ -34,7 +34,8 @@ impl Animation for IdleAnimation { next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1 + slow * 0.3) / 13.0; next.shorts.position = Vec3::new(0.0, s_a.shorts.0, s_a.shorts.1); - next.main.position = Vec3::new(0.0, 0.0, 0.0); + next.main.position = Vec3::new(2.0, -3.0, -3.0); + next.main.orientation = Quaternion::rotation_y(-0.5) * Quaternion::rotation_z(1.57); next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1); next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2 + slow * -0.1); diff --git a/voxygen/anim/src/biped_small/mod.rs b/voxygen/anim/src/biped_small/mod.rs index c8bf4bdd1a..bc48208357 100644 --- a/voxygen/anim/src/biped_small/mod.rs +++ b/voxygen/anim/src/biped_small/mod.rs @@ -1,9 +1,12 @@ +pub mod alpha; pub mod idle; pub mod run; pub mod wield; // Reexports -pub use self::{idle::IdleAnimation, run::RunAnimation, wield::WieldAnimation}; +pub use self::{ + alpha::AlphaAnimation, idle::IdleAnimation, run::RunAnimation, wield::WieldAnimation, +}; use super::{make_bone, vek::*, FigureBoneData, Skeleton}; use common::comp::{self}; diff --git a/voxygen/anim/src/biped_small/run.rs b/voxygen/anim/src/biped_small/run.rs index bf35df919e..70330eb8b1 100644 --- a/voxygen/anim/src/biped_small/run.rs +++ b/voxygen/anim/src/biped_small/run.rs @@ -105,6 +105,8 @@ impl Animation for RunAnimation { next.chest.orientation = Quaternion::rotation_z(short * 0.06 + tilt * -0.6) * Quaternion::rotation_y(tilt * 1.6) * Quaternion::rotation_x(shortalter * 0.035 + speednorm * -0.4 + (tilt.abs())); + next.main.position = Vec3::new(2.0, -3.0, -3.0); + next.main.orientation = Quaternion::rotation_y(-0.5) * Quaternion::rotation_z(1.57); next.shorts.position = Vec3::new(0.0, s_a.shorts.0, s_a.shorts.1); next.shorts.orientation = Quaternion::rotation_x(0.1 * speednorm) diff --git a/voxygen/anim/src/biped_small/wield.rs b/voxygen/anim/src/biped_small/wield.rs index eaeed43738..cbb1cc1bdc 100644 --- a/voxygen/anim/src/biped_small/wield.rs +++ b/voxygen/anim/src/biped_small/wield.rs @@ -41,7 +41,7 @@ impl Animation for WieldAnimation { next.chest.scale = Vec3::one() / 13.0; next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1 + fast * -0.1 * speednormcancel); next.head.orientation = Quaternion::rotation_x(0.45 * speednorm) - * Quaternion::rotation_y(fast * 0.15 * speednormcancel); + * Quaternion::rotation_y(fast * 0.07 * speednormcancel); next.chest.position = Vec3::new( 0.0, s_a.chest.0, @@ -52,6 +52,7 @@ impl Animation for WieldAnimation { //next.main.position = Vec3::new(0.0, s_a.hand.2*-1.0, 0.0); next.main.position = Vec3::new(0.0, 0.0, 0.0); + next.main.orientation = Quaternion::rotation_x(0.0); next.hand_l.position = Vec3::new(s_a.grip.0 * 4.0, 0.0, s_a.grip.2); next.hand_r.position = Vec3::new(-s_a.grip.0 * 4.0, 0.0, s_a.grip.2); @@ -65,7 +66,11 @@ impl Animation for WieldAnimation { next.control.position = Vec3::new( -3.0, s_a.grip.2, - -s_a.grip.2 / 2.5 + s_a.grip.0 * -2.0 + fastacc * 1.5 + fastalt * 0.5 * speednormcancel, + -s_a.grip.2 / 2.5 + + s_a.grip.0 * -2.0 + + fastacc * 1.5 + + fastalt * 0.5 * speednormcancel + + speednorm * 2.0, ); next.control_l.orientation = diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index cde747dfe4..4295469fd2 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -153,6 +153,7 @@ fn tool_desc(tool: &Tool, components: &[Item], msm: &MaterialStatManifest, desc: ToolKind::Staff => "Staff", ToolKind::Sceptre => "Sceptre", ToolKind::Shield => "Shield", + ToolKind::Spear => "Spear", ToolKind::Unique(_) => "Unique", ToolKind::Debug => "Debug", ToolKind::Farming => "Farming Tool", diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index 8483653367..34eb78c9c4 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -2500,16 +2500,7 @@ struct BipedSmallLateralSubSpec { } #[derive(Deserialize)] -struct BipedSmallWeaponSpec(HashMap<(BSSpecies, BSBodyType), SidedBSWeaponVoxSpec>); -#[derive(Deserialize)] -struct SidedBSWeaponVoxSpec { - main: BipedSmallWeaponSubSpec, -} -#[derive(Deserialize)] -struct BipedSmallWeaponSubSpec { - offset: [f32; 3], // Should be relative to initial origin - weapon: VoxSimple, -} +struct BipedSmallWeaponSpec(HashMap); make_vox_spec!( biped_small::Body, @@ -2518,8 +2509,20 @@ make_vox_spec!( lateral: BipedSmallLateralSpec = "voxygen.voxel.biped_small_lateral_manifest", weapon: BipedSmallWeaponSpec = "voxygen.voxel.biped_small_weapon_manifest", }, - |FigureKey { body, .. }, spec| { - [ + |FigureKey { body, extra }, spec| { + const DEFAULT_LOADOUT: super::cache::CharacterCacheKey = super::cache::CharacterCacheKey { + third_person: None, + tool: None, + lantern: None, + glider: None, + hand: None, + foot: None, + }; + + // TODO: This is bad code, maybe this method should return Option<_> + let loadout = extra.as_deref().unwrap_or(&DEFAULT_LOADOUT); + let tool = loadout.tool.as_ref(); +[ Some(spec.central.read().0.mesh_head( body.species, body.body_type, @@ -2536,10 +2539,12 @@ make_vox_spec!( body.species, body.body_type, )), - Some(spec.weapon.read().0.mesh_main( - body.species, - body.body_type, - )), + tool.and_then(|tool| tool.active.as_ref()).map(|tool| { + spec.weapon.read().0.mesh_main( + tool, + false, + ) + }), Some(spec.lateral.read().0.mesh_hand_l( body.species, body.body_type, @@ -2698,7 +2703,7 @@ impl BipedSmallLateralSpec { (lateral, Vec3::from(spec.foot_r.offset)) } } -impl BipedSmallWeaponSpec { +/*impl BipedSmallWeaponSpec { fn mesh_main(&self, species: BSSpecies, body_type: BSBodyType) -> BoneMeshes { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, @@ -2714,8 +2719,38 @@ impl BipedSmallWeaponSpec { (weapon, Vec3::from(spec.main.offset)) } -} +*///} +impl BipedSmallWeaponSpec { + fn mesh_main(&self, item_definition_id: &str, flipped: bool) -> BoneMeshes { + let spec = match self.0.get(item_definition_id) { + Some(spec) => spec, + None => { + error!(?item_definition_id, "No tool/weapon specification exists"); + return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0)); + }, + }; + let tool_kind_segment = if flipped { + graceful_load_segment_flipped(&spec.vox_spec.0) + } else { + graceful_load_segment(&spec.vox_spec.0) + }; + + let offset = Vec3::new( + if flipped { + //log::warn!("tool kind segment {:?}", ); + //tool_kind_segment.; + 0.0 - spec.vox_spec.1[0] - (tool_kind_segment.sz.x as f32) + } else { + spec.vox_spec.1[0] + }, + spec.vox_spec.1[1], + spec.vox_spec.1[2], + ); + + (tool_kind_segment, offset) + } +} //// #[derive(Deserialize)] diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 8669f3b3ac..2d38d801fe 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -2430,6 +2430,65 @@ impl FigureMgr { skeleton_attr, ) }, + CharacterState::ComboMelee(s) => { + let stage_index = (s.stage - 1) as usize; + let stage_time = s.timer.as_secs_f64(); + let stage_progress = match s.stage_section { + StageSection::Buildup => { + stage_time + / s.static_data.stage_data[stage_index] + .base_buildup_duration + .as_secs_f64() + }, + StageSection::Swing => { + stage_time + / s.static_data.stage_data[stage_index] + .base_swing_duration + .as_secs_f64() + }, + StageSection::Recover => { + stage_time + / s.static_data.stage_data[stage_index] + .base_recover_duration + .as_secs_f64() + }, + _ => 0.0, + }; + match s.stage { + 1 => anim::biped_small::AlphaAnimation::update_skeleton( + &target_base, + ( + vel.0, + ori, + state.last_ori, + time, + state.avg_vel, + state.acc_vel, + Some(s.stage_section), + state.state_time, + ), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ), + _ => anim::biped_small::AlphaAnimation::update_skeleton( + &target_base, + ( + vel.0, + ori, + state.last_ori, + time, + state.avg_vel, + state.acc_vel, + Some(s.stage_section), + state.state_time, + ), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ), + } + }, // TODO! _ => target_base, };