diff --git a/assets/common/items/npc_weapons/bow/adlet.ron b/assets/common/items/npc_weapons/bow/adlet.ron new file mode 100644 index 0000000000..3ac5f32607 --- /dev/null +++ b/assets/common/items/npc_weapons/bow/adlet.ron @@ -0,0 +1,15 @@ +ItemDef( + name: "Adlet Bow", + description: "Strips of leather are wrapped around the handle.", + kind: Tool( + ( + kind: Bow, + stats: ( + equip_time_millis: 200, + power: 0.8, + speed: 1.0 + ), + ) + ), + quality: Moderate, +) diff --git a/assets/common/npc_names.ron b/assets/common/npc_names.ron index be28efa0fd..07c265b068 100644 --- a/assets/common/npc_names.ron +++ b/assets/common/npc_names.ron @@ -924,7 +924,7 @@ biped_small: ( body: ( keyword: "biped_small", - names: [ + names_0: [ "Harvey" ] ), diff --git a/assets/voxygen/voxel/biped_small_weapon_manifest.ron b/assets/voxygen/voxel/biped_small_weapon_manifest.ron index 82ad7e89c7..6bc9a6737f 100644 --- a/assets/voxygen/voxel/biped_small_weapon_manifest.ron +++ b/assets/voxygen/voxel/biped_small_weapon_manifest.ron @@ -7,4 +7,8 @@ vox_spec: ("weapon.spear.adlet", (-0.5, -3.0, -5.0)), color: None ), + "common.items.npc_weapons.bow.adlet": ( + vox_spec: ("weapon.bow.adlet", (-0.5, -5.5, -9.5)), + color: None + ), }) diff --git a/assets/voxygen/voxel/weapon/bow/adlet.vox b/assets/voxygen/voxel/weapon/bow/adlet.vox new file mode 100644 index 0000000000..208e52cf49 --- /dev/null +++ b/assets/voxygen/voxel/weapon/bow/adlet.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef2809ad85372e7662cb5bf787d6054e49b6b749eaf5c2157e12a15649dc3242 +size 1344 diff --git a/common/src/comp/inventory/loadout_builder.rs b/common/src/comp/inventory/loadout_builder.rs index 7184d94772..eccb4df106 100644 --- a/common/src/comp/inventory/loadout_builder.rs +++ b/common/src/comp/inventory/loadout_builder.rs @@ -32,6 +32,8 @@ pub struct LoadoutBuilder(Loadout); #[derive(Copy, Clone)] pub enum LoadoutConfig { + AdletArcher, + AdletWarrior, Guard, Villager, Outcast, @@ -249,9 +251,14 @@ impl LoadoutBuilder { "common.items.npc_weapons.spear.wooden_spear", )); }, + (biped_small::Species::Adlet, _) => { + main_tool = Some(Item::new_from_asset_expect( + "common.items.npc_weapons.bow.adlet", + )); + }, _ => { main_tool = Some(Item::new_from_asset_expect( - "common.items.npc_weapons.spear.wooden_spear", + "common.items.npc_weapons.bow.adlet", )); }, }, @@ -270,6 +277,16 @@ impl LoadoutBuilder { let loadout = if let Some(config) = config { use LoadoutConfig::*; match config { + AdletArcher => LoadoutBuilder::new() + .active_item(Some(Item::new_from_asset_expect( + "common.items.npc_weapons.bow.adlet", + ))) + .build(), + AdletWarrior => LoadoutBuilder::new() + .active_item(Some(Item::new_from_asset_expect( + "common.items.npc_weapons.spear.wooden_spear", + ))) + .build(), Guard => LoadoutBuilder::new() .active_item(active_item) .shoulder(Some(Item::new_from_asset_expect( diff --git a/server/src/persistence/json_models.rs b/server/src/persistence/json_models.rs index 99bddbe5ed..a067901148 100644 --- a/server/src/persistence/json_models.rs +++ b/server/src/persistence/json_models.rs @@ -141,6 +141,7 @@ pub fn skill_to_db_string(skill: comp::skills::Skill) -> String { UnlockGroup(SkillGroupKind::Weapon(ToolKind::Sceptre)) => "Unlock Weapon Sceptre", UnlockGroup(SkillGroupKind::Weapon(ToolKind::Dagger)) | UnlockGroup(SkillGroupKind::Weapon(ToolKind::Shield)) + | UnlockGroup(SkillGroupKind::Weapon(ToolKind::Spear)) | UnlockGroup(SkillGroupKind::Weapon(ToolKind::Debug)) | UnlockGroup(SkillGroupKind::Weapon(ToolKind::Farming)) | UnlockGroup(SkillGroupKind::Weapon(ToolKind::Empty)) @@ -276,6 +277,7 @@ pub fn skill_group_to_db_string(skill_group: comp::skills::SkillGroupKind) -> St Weapon(ToolKind::Sceptre) => "Weapon Sceptre", Weapon(ToolKind::Dagger) | Weapon(ToolKind::Shield) + | Weapon(ToolKind::Spear) | Weapon(ToolKind::Debug) | Weapon(ToolKind::Farming) | Weapon(ToolKind::Empty) diff --git a/voxygen/anim/src/biped_small/alpha.rs b/voxygen/anim/src/biped_small/alpha.rs index fe42f0c368..12541dde64 100644 --- a/voxygen/anim/src/biped_small/alpha.rs +++ b/voxygen/anim/src/biped_small/alpha.rs @@ -2,7 +2,7 @@ use super::{ super::{vek::*, Animation}, BipedSmallSkeleton, SkeletonAttr, }; -use common::states::utils::StageSection; +use common::{comp::item::ToolKind, states::utils::StageSection}; use std::f32::consts::PI; pub struct AlphaAnimation; diff --git a/voxygen/anim/src/biped_small/mod.rs b/voxygen/anim/src/biped_small/mod.rs index bc48208357..08e069604c 100644 --- a/voxygen/anim/src/biped_small/mod.rs +++ b/voxygen/anim/src/biped_small/mod.rs @@ -1,11 +1,13 @@ pub mod alpha; pub mod idle; pub mod run; +pub mod shoot; pub mod wield; // Reexports pub use self::{ - alpha::AlphaAnimation, idle::IdleAnimation, run::RunAnimation, wield::WieldAnimation, + alpha::AlphaAnimation, idle::IdleAnimation, run::RunAnimation, shoot::ShootAnimation, + wield::WieldAnimation, }; use super::{make_bone, vek::*, FigureBoneData, Skeleton}; diff --git a/voxygen/anim/src/biped_small/shoot.rs b/voxygen/anim/src/biped_small/shoot.rs new file mode 100644 index 0000000000..974f6d2f14 --- /dev/null +++ b/voxygen/anim/src/biped_small/shoot.rs @@ -0,0 +1,129 @@ +use super::{ + super::{vek::*, Animation}, + BipedSmallSkeleton, SkeletonAttr, +}; +use common::{comp::item::ToolKind, states::utils::StageSection}; +use std::f32::consts::PI; + +pub struct ShootAnimation; + +type ShootAnimationDependency = ( + Option, + Vec3, + Vec3, + Vec3, + f64, + Vec3, + f32, + Option, + f64, +); + +impl Animation for ShootAnimation { + type Dependency = ShootAnimationDependency; + type Skeleton = BipedSmallSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"biped_small_shoot\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "biped_small_shoot")] + + fn update_skeleton_inner( + skeleton: &Self::Skeleton, + ( + active_tool_kind, + 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; + + next.foot_l.scale = Vec3::one() / 13.0; + next.foot_r.scale = Vec3::one() / 13.0; + + 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.07 * speednormcancel); + next.chest.position = Vec3::new( + 0.0, + s_a.chest.0, + s_a.chest.1 + fastalt * 0.4 * speednormcancel + speednormcancel * -0.5, + ) / 13.0; + + next.shorts.position = Vec3::new(0.0, s_a.shorts.0, s_a.shorts.1); + + 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.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); + + match active_tool_kind { + Some(ToolKind::Bow) => { + let (movement1base, movement2base, movement3) = match stage_section { + Some(StageSection::Buildup) => (anim_time as f32, 0.0, 0.0), + Some(StageSection::Swing) => (1.0, (anim_time as f32).powf(0.25), 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.control_l.position = Vec3::new( + 1.0 - s_a.grip.0 * 2.0 + movement2abs * -4.0, + movement2abs * -8.0, + 0.0, + ); + next.control_r.position = Vec3::new(-1.0 + s_a.grip.0 * 2.0, 6.0, -2.0); + + next.control.position = Vec3::new( + -1.0, + 2.0 + movement1abs * 4.0 + s_a.grip.2, + 3.0 + movement1abs * 8.0 - s_a.grip.2 / 2.5 + s_a.grip.0 * -2.0, + ); + + next.control_l.orientation = + Quaternion::rotation_x(PI / 2.0) * Quaternion::rotation_y(-0.3); + next.control_r.orientation = Quaternion::rotation_x(PI / 2.0 + s_a.grip.0 * 0.2) + * Quaternion::rotation_y(0.5 + s_a.grip.0 * 0.2); + + next.control.orientation = Quaternion::rotation_x(-0.3 + movement1abs * 0.7) + * Quaternion::rotation_y(0.5 * speednorm); + }, + _ => {}, + } + + next + } +} diff --git a/voxygen/anim/src/biped_small/wield.rs b/voxygen/anim/src/biped_small/wield.rs index cbb1cc1bdc..0b7affbdeb 100644 --- a/voxygen/anim/src/biped_small/wield.rs +++ b/voxygen/anim/src/biped_small/wield.rs @@ -2,11 +2,20 @@ use super::{ super::{vek::*, Animation}, BipedSmallSkeleton, SkeletonAttr, }; +use common::comp::item::ToolKind; use std::f32::consts::PI; pub struct WieldAnimation; -type WieldAnimationDependency = (Vec3, Vec3, Vec3, f64, Vec3, f32); +type WieldAnimationDependency = ( + Option, + Vec3, + Vec3, + Vec3, + f64, + Vec3, + f32, +); impl Animation for WieldAnimation { type Dependency = WieldAnimationDependency; @@ -19,7 +28,7 @@ impl Animation for WieldAnimation { fn update_skeleton_inner( skeleton: &Self::Skeleton, - (velocity, _orientation, _last_ori, _global_time, _avg_vel, acc_vel): Self::Dependency, + (active_tool_kind, velocity, _orientation, _last_ori, _global_time, _avg_vel, acc_vel): Self::Dependency, anim_time: f64, _rate: &mut f32, s_a: &SkeletonAttr, @@ -49,7 +58,10 @@ impl Animation for WieldAnimation { ) / 13.0; next.shorts.position = Vec3::new(0.0, s_a.shorts.0, s_a.shorts.1); - //next.main.position = Vec3::new(0.0, s_a.hand.2*-1.0, 0.0); + + 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.main.position = Vec3::new(0.0, 0.0, 0.0); next.main.orientation = Quaternion::rotation_x(0.0); @@ -60,30 +72,54 @@ impl Animation for WieldAnimation { 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); + match active_tool_kind { + Some(ToolKind::Spear) => { + 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, - s_a.grip.2, - -s_a.grip.2 / 2.5 - + s_a.grip.0 * -2.0 - + fastacc * 1.5 - + fastalt * 0.5 * speednormcancel - + speednorm * 2.0, - ); + 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 + + speednorm * 2.0, + ); - next.control_l.orientation = - Quaternion::rotation_x(PI / 1.5 + slow * 0.1) * Quaternion::rotation_y(-0.3); - next.control_r.orientation = - Quaternion::rotation_x(PI / 1.5 + slow * 0.1 + s_a.grip.0 * 0.2) - * Quaternion::rotation_y(0.5 + slow * 0.0 + s_a.grip.0 * 0.2); + next.control_l.orientation = + Quaternion::rotation_x(PI / 1.5 + slow * 0.1) * Quaternion::rotation_y(-0.3); + next.control_r.orientation = + Quaternion::rotation_x(PI / 1.5 + slow * 0.1 + s_a.grip.0 * 0.2) + * Quaternion::rotation_y(0.5 + slow * 0.0 + s_a.grip.0 * 0.2); - next.control.orientation = Quaternion::rotation_x(-1.35 + 0.5 * speednorm); + next.control.orientation = Quaternion::rotation_x(-1.35 + 0.5 * speednorm); + }, + Some(ToolKind::Bow) => { + next.control_l.position = Vec3::new(1.0 - s_a.grip.0 * 2.0, 0.0, 0.0); + next.control_r.position = Vec3::new(-1.0 + s_a.grip.0 * 2.0, 6.0, -2.0); - 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.control.position = Vec3::new( + -1.0, + 2.0 + s_a.grip.2, + 3.0 + -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 = + Quaternion::rotation_x(PI / 2.0 + slow * 0.1) * Quaternion::rotation_y(-0.3); + next.control_r.orientation = + Quaternion::rotation_x(PI / 2.0 + slow * 0.1 + s_a.grip.0 * 0.2) + * Quaternion::rotation_y(0.5 + slow * 0.0 + s_a.grip.0 * 0.2); + + next.control.orientation = Quaternion::rotation_x(-0.3 + 0.5 * speednorm) + * Quaternion::rotation_y(0.5 * speednorm); + }, + _ => {}, + } next } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 2d38d801fe..274178fe02 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -2697,6 +2697,7 @@ impl FigureMgr { anim::biped_small::WieldAnimation::update_skeleton( &target_base, ( + active_tool_kind, vel.0, ori, state.last_ori, @@ -2709,6 +2710,96 @@ impl FigureMgr { skeleton_attr, ) }, + CharacterState::BasicRanged(s) => { + let stage_time = s.timer.as_secs_f64(); + + let stage_progress = match s.stage_section { + StageSection::Buildup => { + stage_time / s.static_data.buildup_duration.as_secs_f64() + }, + StageSection::Recover => { + stage_time / s.static_data.recover_duration.as_secs_f64() + }, + + _ => 0.0, + }; + anim::biped_small::ShootAnimation::update_skeleton( + &target_base, + ( + active_tool_kind, + 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, + ) + }, + 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, };