From 29732bb763f8fdf88e72a0d8d1bf7f876677e5d4 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Fri, 18 Dec 2020 21:05:39 -0500 Subject: [PATCH] starting stun anim stagger anim, mirroring, bettern walk anim wielding with stuns/stagger Knockback fix Added Poise documentation/comments --- 4 | 286 ----------------------- common/src/comp/beam.rs | 6 +- common/src/comp/character_state.rs | 2 + common/src/comp/poise.rs | 67 ++++-- common/src/states/staggered.rs | 2 +- common/src/states/stunned.rs | 6 +- common/sys/src/melee.rs | 13 +- common/sys/src/stats.rs | 10 +- server/src/events/entity_manipulation.rs | 38 +-- voxygen/anim/src/character/mod.rs | 6 +- voxygen/anim/src/character/run.rs | 44 ++-- voxygen/anim/src/character/staggered.rs | 213 +++++++++++++++++ voxygen/anim/src/character/stunned.rs | 177 ++++++++++++++ voxygen/anim/src/dyn_lib.rs | 3 +- voxygen/src/scene/figure/mod.rs | 56 +++++ 15 files changed, 560 insertions(+), 369 deletions(-) delete mode 100644 4 create mode 100644 voxygen/anim/src/character/staggered.rs create mode 100644 voxygen/anim/src/character/stunned.rs diff --git a/4 b/4 deleted file mode 100644 index 628b6390ea..0000000000 --- a/4 +++ /dev/null @@ -1,286 +0,0 @@ -use crate::{ - comp::{Attacking, CharacterState, EnergyChange, EnergySource, StateUpdate}, - states::{ - behavior::{CharacterBehavior, JoinData}, - utils::*, - }, - Damage, DamageSource, GroupTarget, Knockback, -}; -use serde::{Deserialize, Serialize}; -use std::time::Duration; - -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] -pub struct Stage { - /// Specifies which stage the combo attack is in - pub stage: u32, - /// Initial damage of stage - pub base_damage: u32, - /// Max damage of stage - pub max_damage: u32, - /// Damage scaling per combo - pub damage_increase: u32, - /// Initial poise damage of stage - pub base_poise_damage: u32, - /// Knockback of stage - pub knockback: f32, - /// Range of attack - pub range: f32, - /// Angle of attack - pub angle: f32, - /// Initial buildup duration of stage (how long until state can deal damage) - pub base_buildup_duration: T, - /// Duration of stage spent in swing (controls animation stuff, and can also - /// be used to handle movement separately to buildup) - pub base_swing_duration: T, - /// Initial recover duration of stage (how long until character exits state) - pub base_recover_duration: T, - /// How much forward movement there is in the swing portion of the stage - pub forward_movement: f32, -} - -impl Stage { - pub fn to_duration(self) -> Stage { - Stage:: { - stage: self.stage, - base_damage: self.base_damage, - max_damage: self.max_damage, - damage_increase: self.damage_increase, - base_poise_damage: self.base_poise_damage, - knockback: self.knockback, - range: self.range, - angle: self.angle, - base_buildup_duration: Duration::from_millis(self.base_buildup_duration), - base_swing_duration: Duration::from_millis(self.base_swing_duration), - base_recover_duration: Duration::from_millis(self.base_recover_duration), - forward_movement: self.forward_movement, - } - } - - pub fn adjusted_by_stats(mut self, power: f32, speed: f32) -> Self { - self.base_damage = (self.base_damage as f32 * power) as u32; - self.max_damage = (self.max_damage as f32 * power) as u32; - self.damage_increase = (self.damage_increase as f32 * power) as u32; - self.base_buildup_duration = (self.base_buildup_duration as f32 / speed) as u64; - self.base_swing_duration = (self.base_swing_duration as f32 / speed) as u64; - self.base_recover_duration = (self.base_recover_duration as f32 / speed) as u64; - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -/// Separated out to condense update portions of character state -pub struct StaticData { - /// Indicates number of stages in combo - pub num_stages: u32, - /// Data for each stage - pub stage_data: Vec>, - /// Initial energy gain per strike - pub initial_energy_gain: u32, - /// Max energy gain per strike - pub max_energy_gain: u32, - /// Energy gain increase per combo - pub energy_increase: u32, - /// (100% - speed_increase) is percentage speed increases from current to - /// max when combo increases - pub speed_increase: f32, - /// (100% + max_speed_increase) is the max attack speed - pub max_speed_increase: f32, - /// Whether the state can be interrupted by other abilities - pub is_interruptible: bool, - /// What key is used to press ability - pub ability_key: AbilityKey, -} -/// A sequence of attacks that can incrementally become faster and more -/// damaging. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Data { - /// Struct containing data that does not change over the course of the - /// character state - pub static_data: StaticData, - /// Indicates what stage the combo is in - pub stage: u32, - /// Number of consecutive strikes - pub combo: u32, - /// Timer for each stage - pub timer: Duration, - /// Checks what section a stage is in - pub stage_section: StageSection, - /// Whether the state should go onto the next stage - pub next_stage: bool, -} - -impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { - let mut update = StateUpdate::from(data); - - handle_orientation(data, &mut update, 1.0); - handle_move(data, &mut update, 0.3); - if !ability_key_is_pressed(data, self.static_data.ability_key) { - handle_interrupt(data, &mut update, self.static_data.is_interruptible); - if let CharacterState::Roll(roll) = &mut update.character { - roll.was_combo = Some((self.stage, self.combo)); - } - match update.character { - CharacterState::ComboMelee(_) => {}, - _ => { - return update; - }, - } - } - - let stage_index = (self.stage - 1) as usize; - - let speed_modifer = 1.0 - + self.static_data.max_speed_increase - * (1.0 - self.static_data.speed_increase.powi(self.combo as i32)); - - match self.stage_section { - StageSection::Buildup => { - if self.timer < self.static_data.stage_data[stage_index].base_buildup_duration { - // Build up - update.character = CharacterState::ComboMelee(Data { - static_data: self.static_data.clone(), - timer: self - .timer - .checked_add(Duration::from_secs_f32(data.dt.0 * speed_modifer)) - .unwrap_or_default(), - ..*self - }); - } else { - // Transitions to swing section of stage - update.character = CharacterState::ComboMelee(Data { - static_data: self.static_data.clone(), - timer: Duration::default(), - stage_section: StageSection::Swing, - ..*self - }); - - // Hit attempt - let damage = self.static_data.stage_data[stage_index].max_damage.min( - self.static_data.stage_data[stage_index].base_damage - + self.combo / self.static_data.num_stages - * self.static_data.stage_data[stage_index].damage_increase, - ); - let poise_damage = self.static_data.stage_data[stage_index].base_poise_damage; - data.updater.insert(data.entity, Attacking { - damages: vec![(Some(GroupTarget::OutOfGroup), Damage { - source: DamageSource::Melee, - value: damage as f32, - poise_damage: poise_damage as f32, - })], - range: self.static_data.stage_data[stage_index].range, - max_angle: self.static_data.stage_data[stage_index].angle.to_radians(), - applied: false, - hit_count: 0, - knockback: Knockback::Away( - self.static_data.stage_data[stage_index].knockback, - ), - }); - } - }, - StageSection::Swing => { - if self.timer < self.static_data.stage_data[stage_index].base_swing_duration { - // Forward movement - handle_forced_movement( - data, - &mut update, - ForcedMovement::Forward { - strength: self.static_data.stage_data[stage_index].forward_movement, - }, - 0.3, - ); - - // Swings - update.character = CharacterState::ComboMelee(Data { - static_data: self.static_data.clone(), - timer: self - .timer - .checked_add(Duration::from_secs_f32(data.dt.0 * speed_modifer)) - .unwrap_or_default(), - ..*self - }); - } else { - // Transitions to recover section of stage - update.character = CharacterState::ComboMelee(Data { - static_data: self.static_data.clone(), - timer: Duration::default(), - stage_section: StageSection::Recover, - ..*self - }); - } - }, - StageSection::Recover => { - if self.timer < self.static_data.stage_data[stage_index].base_recover_duration { - // Recovers - if ability_key_is_pressed(data, self.static_data.ability_key) { - // Checks if state will transition to next stage after recover - update.character = CharacterState::ComboMelee(Data { - static_data: self.static_data.clone(), - timer: self - .timer - .checked_add(Duration::from_secs_f32(data.dt.0 * speed_modifer)) - .unwrap_or_default(), - next_stage: true, - ..*self - }); - } else { - update.character = CharacterState::ComboMelee(Data { - static_data: self.static_data.clone(), - timer: self - .timer - .checked_add(Duration::from_secs_f32(data.dt.0 * speed_modifer)) - .unwrap_or_default(), - ..*self - }); - } - } else if self.next_stage { - // Transitions to buildup section of next stage - update.character = CharacterState::ComboMelee(Data { - static_data: self.static_data.clone(), - stage: (self.stage % self.static_data.num_stages) + 1, - timer: Duration::default(), - stage_section: StageSection::Buildup, - next_stage: false, - ..*self - }); - } else { - // Done - update.character = CharacterState::Wielding; - // Make sure attack component is removed - data.updater.remove::(data.entity); - } - }, - _ => { - // If it somehow ends up in an incorrect stage section - update.character = CharacterState::Wielding; - // Make sure attack component is removed - data.updater.remove::(data.entity); - }, - } - - // Grant energy on successful hit - if let Some(attack) = data.attacking { - if attack.applied && attack.hit_count > 0 { - let energy = self.static_data.max_energy_gain.min( - self.static_data.initial_energy_gain - + self.combo * self.static_data.energy_increase, - ) as i32; - update.character = CharacterState::ComboMelee(Data { - static_data: self.static_data.clone(), - stage: self.stage, - combo: self.combo + 1, - timer: self.timer, - stage_section: self.stage_section, - next_stage: self.next_stage, - }); - data.updater.remove::(data.entity); - update.energy.change_by(EnergyChange { - amount: energy, - source: EnergySource::HitEnemy, - }); - } - } - - update - } -} diff --git a/common/src/comp/beam.rs b/common/src/comp/beam.rs index 9527c17302..a9cce8b74d 100644 --- a/common/src/comp/beam.rs +++ b/common/src/comp/beam.rs @@ -1,8 +1,4 @@ -use crate::{ - comp::{PoiseChange, PoiseSource}, - uid::Uid, - Damage, GroupTarget, -}; +use crate::{comp::PoiseChange, uid::Uid, Damage, GroupTarget}; use serde::{Deserialize, Serialize}; use specs::{Component, DerefFlaggedStorage}; use specs_idvs::IdvStorage; diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 125ca1e4e0..f8cd0fd244 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -139,6 +139,8 @@ impl CharacterState { | CharacterState::RepeaterRanged(_) | CharacterState::Shockwave(_) | CharacterState::BasicBeam(_) + | CharacterState::Stunned(_) + | CharacterState::Staggered(_) | CharacterState::Wielding ) } diff --git a/common/src/comp/poise.rs b/common/src/comp/poise.rs index 8e5e05c8a5..e7ffb62096 100644 --- a/common/src/comp/poise.rs +++ b/common/src/comp/poise.rs @@ -4,20 +4,19 @@ use specs::{Component, FlaggedStorage}; use specs_idvs::IdvStorage; use vek::*; +/// A change in the poise component. Stores the amount as a signed +/// integer to allow for added or removed poise. Also has a field to +/// label where the poise change came from. #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] pub struct PoiseChange { + /// Value of the change in poise pub amount: i32, + /// Source of change in poise pub source: PoiseSource, } impl PoiseChange { - pub fn set_zero(self) -> Self { - Self { - amount: 0, - source: self.source, - } - } - + /// Alters poise damage as a result of armor poise damage reduction pub fn modify_poise_damage(self, loadout: Option<&Loadout>) -> PoiseChange { let mut poise_damage = self.amount as f32; match self.source { @@ -77,6 +76,7 @@ impl PoiseChange { } } +/// Sources of poise change #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] pub enum PoiseSource { LevelUp, @@ -91,17 +91,20 @@ pub enum PoiseSource { Other, } +/// Poise component #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub struct Poise { + /// Base poise amount for this entity base_max: u32, + /// Poise of entity at any given moment current: u32, + /// Maximum poise of entity at a given time maximum: u32, + /// Knockback direction of last change, for use as an effect in sys/stats.rs knockback: Vec3, + /// Last poise change, storing time since last change pub last_change: (f64, PoiseChange), - pub is_interrupted: bool, - pub is_stunned: bool, - pub is_dazed: bool, - pub is_knockeddown: bool, + /// Rate of poise regeneration per tick. Starts at zero and accelerates. pub regen_rate: f32, } @@ -116,35 +119,41 @@ impl Default for Poise { amount: 0, source: PoiseSource::Revive, }), - is_interrupted: false, - is_stunned: false, - is_dazed: false, - is_knockeddown: false, regen_rate: 0.0, } } } +/// States to define effects of a poise change #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub enum PoiseState { + /// No effect applied Normal, + /// Poise reset, and target briefly stunned Interrupted, + /// Poise reset, target stunned and knocked back horizontally Stunned, + /// Poise reset, target staggered Dazed, + /// Poise reset, target staggered and knocked back further KnockedDown, } impl Poise { + /// Creates a new poise struct based on the body it is being assigned to pub fn new(body: Body) -> Self { let mut poise = Poise::default(); - poise.update_max_poise(Some(body)); - poise.set_to(poise.maximum(), PoiseSource::Revive); + poise.update_base_max(Some(body)); + poise.set_maximum(poise.base_max); + poise.set_to(poise.maximum, PoiseSource::Revive); poise } + /// Returns knockback as a Vec3 pub fn knockback(&self) -> Vec3 { self.knockback } + /// Defines the poise states based on fraction of maximum poise pub fn poise_state(&self) -> PoiseState { if self.current >= 8 * self.maximum / 10 { PoiseState::Normal @@ -159,10 +168,17 @@ impl Poise { } } + /// Gets the current poise value pub fn current(&self) -> u32 { self.current } + /// Gets the maximum poise value pub fn maximum(&self) -> u32 { self.maximum } + /// Gets the base_max value + pub fn base_max(&self) -> u32 { self.base_max } + + /// Sets the poise value to a provided value. First cuts off the value + /// at the maximum. In most cases change_by() should be used. pub fn set_to(&mut self, amount: u32, cause: PoiseSource) { let amount = amount.min(self.maximum); self.last_change = (0.0, PoiseChange { @@ -172,6 +188,7 @@ impl Poise { self.current = amount; } + /// Changes the current poise due to an in-game effect. pub fn change_by(&mut self, change: PoiseChange, impulse: Vec3) { self.current = ((self.current as i32 + change.amount).max(0) as u32).min(self.maximum); self.knockback = impulse; @@ -181,32 +198,32 @@ impl Poise { }); } + /// Resets current value to maximum pub fn reset(&mut self) { self.current = self.maximum; } + /// Sets the maximum and updates the current value to max out at the new + /// maximum pub fn set_maximum(&mut self, amount: u32) { self.maximum = amount; self.current = self.current.min(self.maximum); } + /// Sets the `Poise` base_max fn set_base_max(&mut self, amount: u32) { self.base_max = amount; self.current = self.current.min(self.maximum); } + /// Resets the maximum to the base_max. Example use would be a potion + /// wearing off pub fn reset_max(&mut self) { self.maximum = self.base_max; } - pub fn update_max_poise(&mut self, body: Option) { + /// Sets the base_max based on the entity `Body` + pub fn update_base_max(&mut self, body: Option) { if let Some(body) = body { self.set_base_max(body.base_poise()); - self.set_maximum(body.base_poise()); } } - - pub fn with_max_poise(mut self, amount: u32) -> Self { - self.maximum = amount; - self.current = amount; - self - } } impl Component for Poise { diff --git a/common/src/states/staggered.rs b/common/src/states/staggered.rs index af6049f85d..34dec76b76 100644 --- a/common/src/states/staggered.rs +++ b/common/src/states/staggered.rs @@ -30,7 +30,7 @@ pub struct Data { impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData) -> StateUpdate { - println!("staggered"); + //println!("staggered"); let mut update = StateUpdate::from(data); match self.stage_section { StageSection::Buildup => { diff --git a/common/src/states/stunned.rs b/common/src/states/stunned.rs index 337249ba1b..2e07dcd8f4 100644 --- a/common/src/states/stunned.rs +++ b/common/src/states/stunned.rs @@ -13,6 +13,8 @@ pub struct StaticData { pub buildup_duration: Duration, /// How long the state has until exiting pub recover_duration: Duration, + /// Fraction of normal movement speed allowed during the state + pub movement_speed: f32, } #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -30,8 +32,10 @@ pub struct Data { impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData) -> StateUpdate { - println!("stunned"); let mut update = StateUpdate::from(data); + + handle_move(data, &mut update, self.static_data.movement_speed); + match self.stage_section { StageSection::Buildup => { if self.timer < self.static_data.buildup_duration { diff --git a/common/sys/src/melee.rs b/common/sys/src/melee.rs index 8dd8d4a62c..fd9a31a63c 100644 --- a/common/sys/src/melee.rs +++ b/common/sys/src/melee.rs @@ -101,9 +101,6 @@ impl<'a> System<'a> for Sys { // Check if entity is dodging let is_dodge = char_state_b_maybe.map_or(false, |c_s| c_s.is_melee_dodge()); - // Check if entity is stunned - let is_stunned = char_state_b_maybe.map_or(false, |c_s| c_s.is_stunned()); - // Check if it is a hit if entity != b && !health_b.is_dead @@ -132,12 +129,8 @@ impl<'a> System<'a> for Sys { } } - let change = damage.modify_damage(inventories.get(b), Some(*uid)); - let poise_change = if is_stunned { - poise_change.set_zero() - } else { - poise_change.modify_poise_damage(inventories.get(b)) - }; + let change = damage.modify_damage(loadouts.get(b), Some(*uid)); + let poise_change = poise_change.modify_poise_damage(inventories.get(b)); server_emitter.emit(ServerEvent::Damage { entity: b, change }); // Apply bleeding buff on melee hits with 10% chance @@ -166,7 +159,7 @@ impl<'a> System<'a> for Sys { server_emitter.emit(ServerEvent::PoiseChange { entity: b, change: poise_change, - kb_dir: *Dir::slerp(kb_dir, Dir::new(Vec3::unit_z()), 0.5), + kb_dir: *kb_dir, }); attack.hit_count += 1; diff --git a/common/sys/src/stats.rs b/common/sys/src/stats.rs index 68ede0ae91..1e6aeaaa1e 100644 --- a/common/sys/src/stats.rs +++ b/common/sys/src/stats.rs @@ -167,8 +167,9 @@ impl<'a> System<'a> for Sys { poise.reset(); *character_state = CharacterState::Stunned(common::states::stunned::Data { static_data: common::states::stunned::StaticData { - buildup_duration: Duration::from_millis(100), - recover_duration: Duration::from_millis(100), + buildup_duration: Duration::from_millis(150), + recover_duration: Duration::from_millis(150), + movement_speed: 0.3, }, timer: Duration::default(), stage_section: common::states::utils::StageSection::Buildup, @@ -181,6 +182,7 @@ impl<'a> System<'a> for Sys { static_data: common::states::stunned::StaticData { buildup_duration: Duration::from_millis(500), recover_duration: Duration::from_millis(500), + movement_speed: 0.1, }, timer: Duration::default(), stage_section: common::states::utils::StageSection::Buildup, @@ -211,8 +213,8 @@ impl<'a> System<'a> for Sys { poise.reset(); *character_state = CharacterState::Staggered(common::states::staggered::Data { static_data: common::states::staggered::StaticData { - buildup_duration: Duration::from_millis(5000), - recover_duration: Duration::from_millis(250), + buildup_duration: Duration::from_millis(3000), + recover_duration: Duration::from_millis(500), }, timer: Duration::default(), stage_section: common::states::utils::StageSection::Buildup, diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index a3be99aaf4..151548b7fd 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -12,9 +12,9 @@ use common::{ combat, comp::{ self, aura, buff, - chat::{KillSource, KillType}, CharacterState, - object, Alignment, Body, Energy, EnergyChange, Group, Health, HealthChange, HealthSource, - Inventory, Item, Player, Poise, PoiseChange, PoiseSource, Pos, Stats, + chat::{KillSource, KillType}, + object, Alignment, Body, CharacterState, Energy, EnergyChange, Group, Health, HealthChange, + HealthSource, Inventory, Item, Player, Poise, PoiseChange, PoiseSource, Pos, Stats, }, effect::Effect, lottery::Lottery, @@ -42,6 +42,7 @@ pub fn handle_poise( ) { let ecs = &server.state.ecs(); if let Some(character_state) = ecs.read_storage::().get(entity) { + // Entity is invincible to poise change during stunned/staggered character state if !character_state.is_stunned() { if let Some(poise) = ecs.write_storage::().get_mut(entity) { poise.change_by(change, knockback_dir); @@ -74,7 +75,7 @@ pub fn handle_knockback(server: &Server, entity: EcsEntity, impulse: Vec3) } let mut velocities = ecs.write_storage::(); if let Some(vel) = velocities.get_mut(entity) { - vel.0 = impulse; + vel.0 += impulse; } if let Some(client) = clients.get(entity) { client.send_fallible(ServerGeneral::Knockback(impulse)); @@ -435,17 +436,26 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc }; let pos = state.ecs().read_storage::().get(entity).cloned(); + let vel = state.ecs().read_storage::().get(entity).cloned(); if let Some(pos) = pos { - let _ = state - .create_object(comp::Pos(pos.0 + Vec3::unit_z() * 0.25), match old_body { - Some(common::comp::Body::Humanoid(_)) => object::Body::Pouch, - Some(common::comp::Body::Golem(_)) => object::Body::Chest, - Some(common::comp::Body::BipedLarge(_)) - | Some(common::comp::Body::QuadrupedLow(_)) => object::Body::MeatDrop, - _ => object::Body::Steak, - }) - .with(item) - .build(); + if let Some(vel) = vel { + let _ = state + .create_object(comp::Pos(pos.0 + Vec3::unit_z() * 0.25), match old_body { + Some(common::comp::Body::Humanoid(_)) => object::Body::Pouch, + Some(common::comp::Body::Golem(_)) => object::Body::Chest, + Some(common::comp::Body::BipedLarge(_)) + | Some(common::comp::Body::QuadrupedLow(_)) => object::Body::MeatDrop, + _ => object::Body::Steak, + }) + .with(vel) + .with(item) + .build(); + } else { + error!( + ?entity, + "Entity doesn't have a velocity, no bag is being dropped" + ) + } } else { error!( ?entity, diff --git a/voxygen/anim/src/character/mod.rs b/voxygen/anim/src/character/mod.rs index 437a65b489..8999c390bd 100644 --- a/voxygen/anim/src/character/mod.rs +++ b/voxygen/anim/src/character/mod.rs @@ -22,7 +22,9 @@ pub mod sit; pub mod sneak; pub mod spin; pub mod spinmelee; +pub mod staggered; pub mod stand; +pub mod stunned; pub mod swim; pub mod swimwield; pub mod wield; @@ -36,8 +38,8 @@ pub use self::{ jump::JumpAnimation, leapmelee::LeapAnimation, repeater::RepeaterAnimation, roll::RollAnimation, run::RunAnimation, shockwave::ShockwaveAnimation, shoot::ShootAnimation, sit::SitAnimation, sneak::SneakAnimation, spin::SpinAnimation, spinmelee::SpinMeleeAnimation, - stand::StandAnimation, swim::SwimAnimation, swimwield::SwimWieldAnimation, - wield::WieldAnimation, + staggered::StaggeredAnimation, stand::StandAnimation, stunned::StunnedAnimation, + swim::SwimAnimation, swimwield::SwimWieldAnimation, wield::WieldAnimation, }; use super::{make_bone, vek::*, FigureBoneData, Skeleton}; use common::comp; diff --git a/voxygen/anim/src/character/run.rs b/voxygen/anim/src/character/run.rs index 7920070ff3..8b96ea838f 100644 --- a/voxygen/anim/src/character/run.rs +++ b/voxygen/anim/src/character/run.rs @@ -123,15 +123,19 @@ impl Animation for RunAnimation { * Quaternion::rotation_x(head_look.y + 0.45 * speednorm); next.head.scale = Vec3::one() * s_a.head_scale; - next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1 + 1.0 + shortalt * -0.8); + next.chest.position = Vec3::new( + 0.0, + s_a.chest.0, + s_a.chest.1 + 1.0 * speednorm + shortalt * -0.8, + ); next.chest.orientation = Quaternion::rotation_z(short * 0.06 + tilt * -0.6) * Quaternion::rotation_y(tilt * 1.6) * Quaternion::rotation_x( - impact * 0.06 + shortalter * 0.035 + speed * -0.07 + (tilt.abs()), + impact * 0.06 + shortalter * 0.035 + speednorm * -0.5 + (tilt.abs()), ); next.belt.position = Vec3::new(0.0, 0.25 + s_a.belt.0, 0.25 + s_a.belt.1); - next.belt.orientation = Quaternion::rotation_x(0.1) + next.belt.orientation = Quaternion::rotation_x(0.1 * speednorm) * Quaternion::rotation_z(short * 0.1 + tilt * -1.1) * Quaternion::rotation_y(tilt * 0.5); @@ -140,34 +144,36 @@ impl Animation for RunAnimation { Quaternion::rotation_x(-0.05 + short * 0.02 + noisea * 0.02 + noiseb * 0.02); next.shorts.position = Vec3::new(0.0, 0.65 + s_a.shorts.0, 0.65 + s_a.shorts.1); - next.shorts.orientation = Quaternion::rotation_x(0.2) + next.shorts.orientation = Quaternion::rotation_x(0.2 * speednorm) * Quaternion::rotation_z(short * 0.25 + tilt * -1.5) * Quaternion::rotation_y(tilt * 0.7); next.hand_l.position = Vec3::new( - -s_a.hand.0 + foothorir * -1.3, - 3.0 + s_a.hand.1 + foothorir * -7.0 * speednorm, - 1.5 + s_a.hand.2 - foothorir * 5.5 * speednorm, + -s_a.hand.0 + foothorir * -1.3 * speednorm, + 3.0 * speednorm + s_a.hand.1 + foothorir * -7.0 * speednorm, + 1.5 * speednorm + s_a.hand.2 - foothorir * 5.5 * speednorm, ); - next.hand_l.orientation = Quaternion::rotation_x(0.6 + (footrotr * -1.2) * speednorm) - * Quaternion::rotation_y(footrotr * 0.4); + next.hand_l.orientation = + Quaternion::rotation_x(0.6 * speednorm + (footrotr * -1.2) * speednorm) + * Quaternion::rotation_y(footrotr * 0.4 * speednorm); next.hand_r.position = Vec3::new( - s_a.hand.0 + foothoril * 1.3, - 3.0 + s_a.hand.1 + foothoril * -7.0 * speednorm, - 1.5 + s_a.hand.2 - foothoril * 5.5 * speednorm, + s_a.hand.0 + foothoril * 1.3 * speednorm, + 3.0 * speednorm + s_a.hand.1 + foothoril * -7.0 * speednorm, + 1.5 * speednorm + s_a.hand.2 - foothoril * 5.5 * speednorm, ); - next.hand_r.orientation = Quaternion::rotation_x(0.6 + (footrotl * -1.2) * speednorm) - * Quaternion::rotation_y(footrotl * -0.4); + next.hand_r.orientation = + Quaternion::rotation_x(0.6 * speednorm + (footrotl * -1.2) * speednorm) + * Quaternion::rotation_y(footrotl * -0.4 * speednorm); // next.foot_l.position = Vec3::new( -s_a.foot.0 + footstrafel * sideabs * 3.0 + tilt * -2.0, s_a.foot.1 - + (1.0 - sideabs) * (-1.5 + foothoril * -10.5 * speednorm) + + (1.0 - sideabs) * (-1.5 * speednorm + foothoril * -10.5 * speednorm) + (direction * 5.0).max(0.0), s_a.foot.2 - + (1.0 - sideabs) * (2.0 + ((footvertl * -2.1 * speednorm).max(-1.0))) + + (1.0 - sideabs) * (2.0 * speednorm + ((footvertl * -2.1 * speednorm).max(-1.0))) + side * ((footvertsl * 1.5).max(-1.0)), ); next.foot_l.orientation = Quaternion::rotation_x( @@ -179,10 +185,10 @@ impl Animation for RunAnimation { next.foot_r.position = Vec3::new( s_a.foot.0 + footstrafer * sideabs * 3.0 + tilt * -2.0, s_a.foot.1 - + (1.0 - sideabs) * (-1.5 + foothorir * -10.5 * speednorm) + + (1.0 - sideabs) * (-1.5 * speednorm + foothorir * -10.5 * speednorm) + (direction * 5.0).max(0.0), s_a.foot.2 - + (1.0 - sideabs) * (2.0 + ((footvertr * -2.1 * speednorm).max(-1.0))) + + (1.0 - sideabs) * (2.0 * speednorm + ((footvertr * -2.1 * speednorm).max(-1.0))) + side * ((footvertsr * -1.5).max(-1.0)), ); next.foot_r.orientation = Quaternion::rotation_x( @@ -253,7 +259,7 @@ impl Animation for RunAnimation { next.lantern.scale = Vec3::one() * 0.65; next.hold.scale = Vec3::one() * 0.0; - next.torso.position = Vec3::new(0.0, -0.3, 0.0) * s_a.scaler; + next.torso.position = Vec3::new(0.0, 0.0, 0.0) * s_a.scaler; next.torso.scale = Vec3::one() / 11.0 * s_a.scaler; next.second.scale = match ( diff --git a/voxygen/anim/src/character/staggered.rs b/voxygen/anim/src/character/staggered.rs new file mode 100644 index 0000000000..b054abf480 --- /dev/null +++ b/voxygen/anim/src/character/staggered.rs @@ -0,0 +1,213 @@ +use super::{ + super::{vek::*, Animation}, + CharacterSkeleton, SkeletonAttr, +}; +use common::{comp::item::ToolKind, states::utils::StageSection}; + +pub struct StaggeredAnimation; + +impl Animation for StaggeredAnimation { + type Dependency = ( + Option, + Option, + f32, + f64, + Option, + f64, + bool, + ); + type Skeleton = CharacterSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"character_staggered\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "character_staggered")] + #[allow(clippy::approx_constant)] // TODO: Pending review in #587 + fn update_skeleton_inner( + skeleton: &Self::Skeleton, + ( + active_tool_kind, + _second_tool_kind, + _velocity, + global_time, + stage_section, + timer, + wield_status, + ): Self::Dependency, + anim_time: f64, + rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + *rate = 1.0; + let mut next = (*skeleton).clone(); + + let (movement1base, movement2) = match stage_section { + Some(StageSection::Buildup) => ((anim_time as f32).powf(0.25), 0.0), + Some(StageSection::Recover) => (1.0, (anim_time as f32).powf(4.0)), + _ => (0.0, 0.0), + }; + let pullback = 1.0 - movement2; + let subtract = global_time - timer; + let check = subtract - subtract.trunc(); + let mirror = (check - 0.5).signum() as f32; + let movement1 = movement1base * pullback * mirror; + let movement1abs = movement1base * pullback; + + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); + next.head.orientation = + Quaternion::rotation_x(movement1abs * -0.2) * Quaternion::rotation_z(movement1 * 0.3); + next.shorts.orientation = + Quaternion::rotation_x(movement1abs * 0.2) * Quaternion::rotation_z(movement1 * -0.3); + next.belt.orientation = + Quaternion::rotation_x(movement1abs * 0.1) * Quaternion::rotation_z(movement1 * -0.2); + next.shorts.position = Vec3::new(0.0, s_a.shorts.0 + movement1abs * 1.0, s_a.shorts.1); + next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1 + movement1abs * -4.0); + next.chest.orientation = + Quaternion::rotation_x(movement1abs * -0.1) * Quaternion::rotation_z(movement1 * 1.0); + if wield_status { + next.main.position = Vec3::new(0.0, 0.0, 0.0); + next.main.orientation = Quaternion::rotation_x(0.0); + match active_tool_kind { + Some(ToolKind::Sword) => { + 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.shr.0, s_a.shr.1, s_a.shr.2); + next.hand_r.orientation = + Quaternion::rotation_x(s_a.shr.3) * Quaternion::rotation_y(s_a.shr.4); + + 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); + }, + Some(ToolKind::Axe) => { + next.hand_l.position = Vec3::new(s_a.ahl.0, s_a.ahl.1, s_a.ahl.2); + next.hand_l.orientation = + Quaternion::rotation_x(s_a.ahl.3) * Quaternion::rotation_y(s_a.ahl.4); + next.hand_r.position = Vec3::new(s_a.ahr.0, s_a.ahr.1, s_a.ahr.2); + next.hand_r.orientation = + Quaternion::rotation_x(s_a.ahr.3) * Quaternion::rotation_z(s_a.ahr.5); + + next.control.position = Vec3::new(s_a.ac.0, s_a.ac.1, s_a.ac.2); + next.control.orientation = Quaternion::rotation_x(s_a.ac.3) + * Quaternion::rotation_y(s_a.ac.4) + * Quaternion::rotation_z(s_a.ac.5); + }, + Some(ToolKind::Hammer) => { + next.hand_l.position = Vec3::new(s_a.hhl.0, s_a.hhl.1, s_a.hhl.2); + next.hand_l.orientation = + Quaternion::rotation_x(s_a.hhl.3) * Quaternion::rotation_y(s_a.hhl.4); + next.hand_r.position = Vec3::new(s_a.hhr.0, s_a.hhr.1, s_a.hhr.2); + next.hand_r.orientation = + Quaternion::rotation_x(s_a.hhr.3) * Quaternion::rotation_y(s_a.hhr.4); + + next.control.position = Vec3::new(s_a.hc.0, s_a.hc.1, s_a.hc.2); + next.control.orientation = Quaternion::rotation_x(s_a.hc.3) + * Quaternion::rotation_y(s_a.hc.4) + * Quaternion::rotation_z(s_a.hc.5); + }, + Some(ToolKind::Staff) | Some(ToolKind::Sceptre) => { + next.hand_r.position = Vec3::new(s_a.sthr.0, s_a.sthr.1, s_a.sthr.2); + next.hand_r.orientation = + Quaternion::rotation_x(s_a.sthr.3) * Quaternion::rotation_y(s_a.sthr.4); + + next.control.position = Vec3::new(s_a.stc.0, s_a.stc.1, s_a.stc.2); + + next.hand_l.position = Vec3::new(s_a.sthl.0, s_a.sthl.1, s_a.sthl.2); + next.hand_l.orientation = Quaternion::rotation_x(s_a.sthl.3); + + next.control.orientation = Quaternion::rotation_x(s_a.stc.3) + * Quaternion::rotation_y(s_a.stc.4) + * Quaternion::rotation_z(s_a.stc.5); + }, + Some(ToolKind::Bow) => { + next.hand_l.position = Vec3::new(s_a.bhl.0, s_a.bhl.1, s_a.bhl.2); + next.hand_l.orientation = Quaternion::rotation_x(s_a.bhl.3); + next.hand_r.position = Vec3::new(s_a.bhr.0, s_a.bhr.1, s_a.bhr.2); + next.hand_r.orientation = Quaternion::rotation_x(s_a.bhr.3); + + next.hold.position = Vec3::new(0.0, -1.0, -5.2); + next.hold.orientation = Quaternion::rotation_x(-1.57); + next.hold.scale = Vec3::one() * 1.0; + + next.control.position = Vec3::new(s_a.bc.0, s_a.bc.1, s_a.bc.2); + next.control.orientation = + Quaternion::rotation_y(s_a.bc.4) * Quaternion::rotation_z(s_a.bc.5); + }, + Some(ToolKind::Debug) => { + next.hand_l.position = Vec3::new(-7.0, 4.0, 3.0); + next.hand_l.orientation = Quaternion::rotation_x(1.27); + next.main.position = Vec3::new(-5.0, 5.0, 23.0); + next.main.orientation = Quaternion::rotation_x(3.14); + }, + Some(ToolKind::Farming) => { + next.hand_l.position = Vec3::new(9.0, 1.0, 1.0); + next.hand_l.orientation = Quaternion::rotation_x(1.57); + next.hand_r.position = Vec3::new(9.0, 1.0, 11.0); + next.hand_r.orientation = Quaternion::rotation_x(1.57); + next.main.position = Vec3::new(7.5, 7.5, 13.2); + next.main.orientation = Quaternion::rotation_y(3.14); + + next.control.position = Vec3::new(-11.0, 1.8, 4.0); + }, + _ => {}, + } + } else { + if mirror > 0.0 { + next.hand_r.position = Vec3::new( + s_a.hand.0 + movement1abs * -9.0, + s_a.hand.1 + movement1 * 9.0, + s_a.hand.2 + movement1 * 5.0, + ); + next.hand_r.orientation = Quaternion::rotation_x(movement1 * 1.2) + * Quaternion::rotation_y(movement1 * 1.5); + next.hand_l.position = Vec3::new( + -s_a.hand.0, + s_a.hand.1 + movement1abs * 3.0, + s_a.hand.2 + movement1abs * -1.0, + ); + next.hand_l.orientation = Quaternion::rotation_x(movement1abs * 0.5) + * Quaternion::rotation_y(movement1 * 0.3); + next.foot_l.position = + Vec3::new(-s_a.foot.0, s_a.foot.1 + movement1abs * -7.0, s_a.foot.2); + next.foot_l.orientation = Quaternion::rotation_x(movement1abs * -1.2) + * Quaternion::rotation_z(movement1 * 0.8); + + next.foot_r.position = Vec3::new( + s_a.foot.0 + movement1 * -5.0, + s_a.foot.1 + movement1abs * 3.0, + s_a.foot.2, + ); + next.foot_r.orientation = Quaternion::rotation_z(movement1 * 0.6); + } else { + next.hand_l.position = Vec3::new( + -s_a.hand.0 + movement1abs * 9.0, + s_a.hand.1 + movement1abs * 9.0, + s_a.hand.2 + movement1abs * 5.0, + ); + next.hand_l.orientation = Quaternion::rotation_x(movement1abs * 1.2) + * Quaternion::rotation_y(movement1 * 1.5); + next.hand_r.position = Vec3::new( + s_a.hand.0, + s_a.hand.1 + movement1abs * 3.0, + s_a.hand.2 + movement1abs * -1.0, + ); + next.hand_r.orientation = Quaternion::rotation_x(movement1abs * 0.5) + * Quaternion::rotation_y(movement1 * 0.3); + next.foot_r.position = + Vec3::new(s_a.foot.0, s_a.foot.1 + movement1abs * -7.0, s_a.foot.2); + next.foot_r.orientation = Quaternion::rotation_x(movement1abs * -1.2) + * Quaternion::rotation_z(movement1 * 0.8); + next.foot_l.position = Vec3::new( + -s_a.foot.0 + movement1 * -5.0, + s_a.foot.1 + movement1abs * 3.0, + s_a.foot.2, + ); + next.foot_l.orientation = Quaternion::rotation_z(movement1 * 0.6); + }; + }; + next.torso.position = Vec3::new(0.0, 0.0, 0.0) * s_a.scaler; + next.torso.orientation = Quaternion::rotation_z(0.0); + + next + } +} diff --git a/voxygen/anim/src/character/stunned.rs b/voxygen/anim/src/character/stunned.rs new file mode 100644 index 0000000000..c214a605de --- /dev/null +++ b/voxygen/anim/src/character/stunned.rs @@ -0,0 +1,177 @@ +use super::{ + super::{vek::*, Animation}, + CharacterSkeleton, SkeletonAttr, +}; +use common::{comp::item::ToolKind, states::utils::StageSection}; + +pub struct StunnedAnimation; + +impl Animation for StunnedAnimation { + type Dependency = ( + Option, + Option, + f32, + f64, + Option, + f64, + bool, + ); + type Skeleton = CharacterSkeleton; + + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"character_stunned\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "character_stunned")] + #[allow(clippy::approx_constant)] // TODO: Pending review in #587 + fn update_skeleton_inner( + skeleton: &Self::Skeleton, + ( + active_tool_kind, + _second_tool_kind, + _velocity, + global_time, + stage_section, + timer, + wield_status, + ): Self::Dependency, + anim_time: f64, + rate: &mut f32, + s_a: &SkeletonAttr, + ) -> Self::Skeleton { + *rate = 1.0; + let mut next = (*skeleton).clone(); + + let (movement1base, movement2) = match stage_section { + Some(StageSection::Buildup) => ((anim_time as f32).powf(0.25), 0.0), + Some(StageSection::Recover) => (1.0, (anim_time as f32).powf(4.0)), + _ => (0.0, 0.0), + }; + let pullback = 1.0 - movement2; + let subtract = global_time - timer; + let check = subtract - subtract.trunc(); + let mirror = (check - 0.5).signum() as f32; + let movement1 = movement1base * pullback * mirror; + let movement1abs = movement1base * pullback; + println!("wield {}", wield_status); + + next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1); + next.head.orientation = Quaternion::rotation_z(movement1 * 0.3); + next.shorts.orientation = + Quaternion::rotation_x(movement1abs * -0.2) * Quaternion::rotation_z(movement1 * -0.3); + next.belt.orientation = + Quaternion::rotation_x(movement1abs * -0.1) * Quaternion::rotation_z(movement1 * -0.2); + + next.chest.orientation = + Quaternion::rotation_x(movement1abs * 0.3) * Quaternion::rotation_z(movement1 * 0.5); + if wield_status { + next.main.position = Vec3::new(0.0, 0.0, 0.0); + next.main.orientation = Quaternion::rotation_x(0.0); + match active_tool_kind { + Some(ToolKind::Sword) => { + 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.shr.0, s_a.shr.1, s_a.shr.2); + next.hand_r.orientation = + Quaternion::rotation_x(s_a.shr.3) * Quaternion::rotation_y(s_a.shr.4); + + 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); + }, + Some(ToolKind::Axe) => { + next.hand_l.position = Vec3::new(s_a.ahl.0, s_a.ahl.1, s_a.ahl.2); + next.hand_l.orientation = + Quaternion::rotation_x(s_a.ahl.3) * Quaternion::rotation_y(s_a.ahl.4); + next.hand_r.position = Vec3::new(s_a.ahr.0, s_a.ahr.1, s_a.ahr.2); + next.hand_r.orientation = + Quaternion::rotation_x(s_a.ahr.3) * Quaternion::rotation_z(s_a.ahr.5); + + next.control.position = Vec3::new(s_a.ac.0, s_a.ac.1, s_a.ac.2); + next.control.orientation = Quaternion::rotation_x(s_a.ac.3) + * Quaternion::rotation_y(s_a.ac.4) + * Quaternion::rotation_z(s_a.ac.5); + }, + Some(ToolKind::Hammer) => { + next.hand_l.position = Vec3::new(s_a.hhl.0, s_a.hhl.1, s_a.hhl.2); + next.hand_l.orientation = + Quaternion::rotation_x(s_a.hhl.3) * Quaternion::rotation_y(s_a.hhl.4); + next.hand_r.position = Vec3::new(s_a.hhr.0, s_a.hhr.1, s_a.hhr.2); + next.hand_r.orientation = + Quaternion::rotation_x(s_a.hhr.3) * Quaternion::rotation_y(s_a.hhr.4); + + next.control.position = Vec3::new(s_a.hc.0, s_a.hc.1, s_a.hc.2); + next.control.orientation = Quaternion::rotation_x(s_a.hc.3) + * Quaternion::rotation_y(s_a.hc.4) + * Quaternion::rotation_z(s_a.hc.5); + }, + Some(ToolKind::Staff) | Some(ToolKind::Sceptre) => { + next.hand_r.position = Vec3::new(s_a.sthr.0, s_a.sthr.1, s_a.sthr.2); + next.hand_r.orientation = + Quaternion::rotation_x(s_a.sthr.3) * Quaternion::rotation_y(s_a.sthr.4); + + next.control.position = Vec3::new(s_a.stc.0, s_a.stc.1, s_a.stc.2); + + next.hand_l.position = Vec3::new(s_a.sthl.0, s_a.sthl.1, s_a.sthl.2); + next.hand_l.orientation = Quaternion::rotation_x(s_a.sthl.3); + + next.control.orientation = Quaternion::rotation_x(s_a.stc.3) + * Quaternion::rotation_y(s_a.stc.4) + * Quaternion::rotation_z(s_a.stc.5); + }, + Some(ToolKind::Bow) => { + next.hand_l.position = Vec3::new(s_a.bhl.0, s_a.bhl.1, s_a.bhl.2); + next.hand_l.orientation = Quaternion::rotation_x(s_a.bhl.3); + next.hand_r.position = Vec3::new(s_a.bhr.0, s_a.bhr.1, s_a.bhr.2); + next.hand_r.orientation = Quaternion::rotation_x(s_a.bhr.3); + + next.hold.position = Vec3::new(0.0, -1.0, -5.2); + next.hold.orientation = Quaternion::rotation_x(-1.57); + next.hold.scale = Vec3::one() * 1.0; + + next.control.position = Vec3::new(s_a.bc.0, s_a.bc.1, s_a.bc.2); + next.control.orientation = + Quaternion::rotation_y(s_a.bc.4) * Quaternion::rotation_z(s_a.bc.5); + }, + Some(ToolKind::Debug) => { + next.hand_l.position = Vec3::new(-7.0, 4.0, 3.0); + next.hand_l.orientation = Quaternion::rotation_x(1.27); + next.main.position = Vec3::new(-5.0, 5.0, 23.0); + next.main.orientation = Quaternion::rotation_x(3.14); + }, + Some(ToolKind::Farming) => { + next.hand_l.position = Vec3::new(9.0, 1.0, 1.0); + next.hand_l.orientation = Quaternion::rotation_x(1.57); + next.hand_r.position = Vec3::new(9.0, 1.0, 11.0); + next.hand_r.orientation = Quaternion::rotation_x(1.57); + next.main.position = Vec3::new(7.5, 7.5, 13.2); + next.main.orientation = Quaternion::rotation_y(3.14); + + next.control.position = Vec3::new(-11.0, 1.8, 4.0); + }, + _ => {}, + } + } else { + if mirror > 0.0 { + next.hand_r.position = Vec3::new( + s_a.hand.0 + movement1abs * -4.0, + s_a.hand.1 + movement1 * 7.0, + s_a.hand.2 + movement1 * 6.0, + ); + next.hand_r.orientation = Quaternion::rotation_x(movement1 * 1.2) + * Quaternion::rotation_y(movement1 * 1.2); + } else { + next.hand_l.position = Vec3::new( + -s_a.hand.0 + movement1abs * 4.0, + s_a.hand.1 + movement1abs * 7.0, + s_a.hand.2 + movement1abs * 6.0, + ); + next.hand_l.orientation = Quaternion::rotation_x(movement1abs * 1.2) + * Quaternion::rotation_y(movement1 * 1.2); + }; + }; + next.torso.position = Vec3::new(0.0, 0.0, 0.0) * s_a.scaler; + next.torso.orientation = Quaternion::rotation_z(0.0); + + next + } +} diff --git a/voxygen/anim/src/dyn_lib.rs b/voxygen/anim/src/dyn_lib.rs index 798df8bfbc..372053fa27 100644 --- a/voxygen/anim/src/dyn_lib.rs +++ b/voxygen/anim/src/dyn_lib.rs @@ -148,8 +148,7 @@ pub fn init() { // "Debounces" events since I can't find the option to do this in the latest // `notify` thread::spawn(move || { - let mut modified_paths = HashSet::new(); - + let mut modified_paths = std::collections::HashSet::new(); while let Ok(path) = reload_recv.recv() { modified_paths.insert(path); // Wait for any additional modify events before reloading diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 792f28d2e2..d6aecc486e 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -1122,6 +1122,62 @@ impl FigureMgr { skeleton_attr, ) }, + CharacterState::Stunned(s) => { + let stage_time = s.timer.as_secs_f64(); + let wield_status = s.was_wielded; + 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::character::StunnedAnimation::update_skeleton( + &target_base, + ( + active_tool_kind, + second_tool_kind, + vel.0.magnitude(), + time, + Some(s.stage_section), + state.state_time, + wield_status, + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, + CharacterState::Staggered(s) => { + let stage_time = s.timer.as_secs_f64(); + let wield_status = s.was_wielded; + 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::character::StaggeredAnimation::update_skeleton( + &target_base, + ( + active_tool_kind, + second_tool_kind, + vel.0.magnitude(), + time, + Some(s.stage_section), + state.state_time, + wield_status, + ), + stage_progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, CharacterState::BasicBeam(s) => { let stage_time = s.timer.as_secs_f64(); let stage_progress = match s.stage_section {