diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index baf6fe24af..8dc488a620 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -23,10 +23,10 @@ impl Component for AbilityAction { #[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)] pub struct AbilityPool { - pub primary: Option, - pub secondary: Option, - pub block: Option, - pub dodge: Option, + pub primary: Option, + pub secondary: Option, + pub block: Option, + pub dodge: Option, } impl Component for AbilityPool { diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 5fd75a0924..4bd65127a6 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -1,4 +1,3 @@ -use self::ActionState::*; use crate::states::*; use crate::{ comp::{Body, ControllerInputs, Ori, PhysicsState, Pos, Stats, Vel}, @@ -10,7 +9,6 @@ use serde::Deserialize; use serde::Serialize; use specs::LazyUpdate; use specs::{Component, Entity, FlaggedStorage, HashMapStorage}; -use std::time::Duration; pub struct EcsStateData<'a> { pub entity: &'a Entity, @@ -36,123 +34,95 @@ pub struct StateUpdate { pub ori: Ori, } -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] -pub enum MoveState { - Stand(Option), - Run(Option), - Sit(Option), - Jump(Option), - Fall(Option), - Glide(Option), - Swim(Option), - Climb(Option), -} - -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] -pub enum ActionState { +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] +pub enum CharacterState { Idle(Option), - Wield(Option), - Attack(AttackKind), - Block(BlockKind), - Dodge(DodgeKind), - // Interact?, -} - -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] -pub enum AttackKind { - BasicAttack(Option), - Charge(Option), -} - -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] -pub enum BlockKind { - BasicBlock(Option), -} - -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] -pub enum DodgeKind { + Climb(Option), + Sit(Option), + Wielding(Option), + Wielded(Option), + //BasicAttack(Option), + //BasicBlock(Option), + //Charge(Option), Roll(Option), + Glide(Option), } -impl ActionState { - pub fn is_equip_finished(&self) -> bool { +impl CharacterState { + pub fn is_attack(&self) -> bool { match self { - Wield(Some(wield::State { equip_delay })) => *equip_delay == Duration::default(), - _ => true, - } - } - - /// Returns the current `equip_delay` if in `WieldState`, otherwise `Duration::default()` - pub fn get_delay(&self) -> Duration { - match self { - Wield(Some(wield::State { equip_delay })) => *equip_delay, - _ => Duration::default(), - } - } - - pub fn is_attacking(&self) -> bool { - match self { - Attack(_) => true, + //CharacterState::BasicAttack(_) => true, _ => false, } } - pub fn is_blocking(&self) -> bool { + pub fn is_block(&self) -> bool { match self { - Block(_) => true, + //CharacterState::BasicBlock(_) => true, _ => false, } } - pub fn is_dodging(&self) -> bool { + pub fn is_dodge(&self) -> bool { match self { - Dodge(_) => true, + CharacterState::Roll(_) => true, _ => false, } } + /// Compares `action_state`s for shallow equality (does not check internal struct equality) pub fn equals(&self, other: &Self) -> bool { // Check if state is the same without looking at the inner data std::mem::discriminant(&self) == std::mem::discriminant(&other) } -} -impl MoveState { - /// Compares `move_state`s for shallow equality (does not check internal struct equality) - pub fn equals(&self, other: &Self) -> bool { - // Check if state is the same without looking at the inner data - std::mem::discriminant(&self) == std::mem::discriminant(&other) - } -} - -/// __A concurrent state machine that allows for separate `ActionState`s and `MoveState`s.__ -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] -pub struct CharacterState { - /// __How the character is currently moving, e.g. Running, Standing, Falling.__ - /// - /// _Primarily `handle()`s updating `Pos`, `Vel`, `Ori`, and lower body animations. - pub move_state: MoveState, - - /// __How the character is currently acting, e.g. Wielding, Attacking, Dodging.__ - /// - /// _Primarily `handle()`s how character interacts with world, and upper body animations. - pub action_state: ActionState, -} - -impl CharacterState { - /// Compares both `move_state`s and `action_state`a for shallow equality - /// (does not check internal struct equality) - pub fn equals(&self, other: &Self) -> bool { - self.move_state.equals(&other.move_state) && self.action_state.equals(&other.action_state) + /// Passes data to variant or subvariant handlers + /// States contain `Option`s, and will be + /// `None` if state data has not been initialized. So we have to + /// check and intialize new state data if so. + pub fn update(&self, ecs_data: &EcsStateData) -> StateUpdate { + match self { + CharacterState::Idle(opt_state) => opt_state + .unwrap_or_else(|| idle::State::new(ecs_data)) + .handle(ecs_data), + CharacterState::Climb(opt_state) => opt_state + .unwrap_or_else(|| climb::State::new(ecs_data)) + .handle(ecs_data), + CharacterState::Sit(opt_state) => opt_state + .unwrap_or_else(|| sit::State::new(ecs_data)) + .handle(ecs_data), + CharacterState::Wielding(opt_state) => opt_state + .unwrap_or_else(|| wielding::State::new(ecs_data)) + .handle(ecs_data), + CharacterState::Wielded(opt_state) => opt_state + .unwrap_or_else(|| wielded::State::new(ecs_data)) + .handle(ecs_data), + /*CharacterState::BasicAttack(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| basic_attack::State::new(ecs_data)) + // Call handler + .handle(ecs_data), + CharacterState::Charge(opt_state) => opt_state + .unwrap_or_else(|| charge_attack::State::new(ecs_data)) + .handle(ecs_data), + CharacterState::BasicBlock(opt_state) => opt_state + .unwrap_or_else(|| basic_block::State::new(ecs_data)) + .handle(ecs_data),*/ + CharacterState::Roll(opt_state) => opt_state + .unwrap_or_else(|| roll::State::new(ecs_data)) + .handle(ecs_data), + CharacterState::Glide(opt_state) => opt_state + .unwrap_or_else(|| glide::State::new(ecs_data)) + .handle(ecs_data), + // All states should be explicitly handled + // Do not use default match: _ => {}, + } } } impl Default for CharacterState { fn default() -> Self { - Self { - move_state: MoveState::Fall(None), - action_state: ActionState::Idle(None), - } + Self::Idle(None) } } diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 6457cdee37..4b346e6ca6 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -23,10 +23,7 @@ pub use body::{ biped_large, bird_medium, bird_small, dragon, fish_medium, fish_small, humanoid, object, quadruped_medium, quadruped_small, Body, }; -pub use character_state::{ - ActionState, AttackKind, BlockKind, CharacterState, DodgeKind, EcsStateData, MoveState, - StateUpdate, -}; +pub use character_state::{CharacterState, EcsStateData, StateUpdate}; pub use controller::{ ControlEvent, Controller, ControllerInputs, Input, InputState, InventoryManip, MountState, Mounting, diff --git a/common/src/states/climb.rs b/common/src/states/climb.rs index a42175e874..7db0631a6d 100644 --- a/common/src/states/climb.rs +++ b/common/src/states/climb.rs @@ -1,4 +1,5 @@ -use super::{ActionState, EcsStateData, MoveState, StateHandler, StateUpdate}; +use crate::comp::{CharacterState, EcsStateData, StateUpdate}; +use crate::states::StateHandler; use crate::sys::phys::GRAVITY; use vek::vec::{Vec2, Vec3}; use vek::Lerp; @@ -22,27 +23,20 @@ impl StateHandler for State { character: *ecs_data.character, }; - update.character.action_state = ActionState::Idle(None); - // If no wall is in front of character ... if let None = ecs_data.physics.on_wall { if ecs_data.inputs.jump.is_pressed() { // They've climbed atop something, give them a boost - update.character.move_state = MoveState::Jump(None); - - return update; + //TODO: JUMP EVENT } else { // Just fall off - update.character.move_state = MoveState::Fall(None); - - return update; + update.character = CharacterState::Idle(None); } } // Remove climb state on ground, otherwise character will get stuck if ecs_data.physics.on_ground { - update.character.move_state = MoveState::Stand(None); - return update; + update.character = CharacterState::Idle(None); } // Move player @@ -65,6 +59,7 @@ impl StateHandler for State { Vec2::from(update.vel.0) }; + // Smooth orientation if ori_dir.magnitude_squared() > 0.0001 && (update.ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared() > 0.001 diff --git a/common/src/states/glide.rs b/common/src/states/glide.rs index 4fc0b8bb0f..f848cd6ee6 100644 --- a/common/src/states/glide.rs +++ b/common/src/states/glide.rs @@ -1,4 +1,4 @@ -use crate::comp::{ActionState, EcsStateData, MoveState, StateUpdate}; +use crate::comp::{CharacterState, EcsStateData, StateUpdate}; use crate::states::StateHandler; use vek::{Vec2, Vec3}; @@ -16,6 +16,7 @@ impl StateHandler for State { } fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { + dbg!(); let mut update = StateUpdate { pos: *ecs_data.pos, vel: *ecs_data.vel, @@ -23,26 +24,14 @@ impl StateHandler for State { character: *ecs_data.character, }; - // Defaults for this state - update.character.action_state = ActionState::Idle(None); - update.character.move_state = MoveState::Glide(None); - - // If glide button isn't held, start falling - if !ecs_data.inputs.glide.is_pressed() { - update.character.move_state = MoveState::Fall(None); - return update; + // If glide button isn't held or player is on ground, end glide + if !ecs_data.inputs.glide.is_pressed() || ecs_data.physics.on_ground { + update.character = CharacterState::Idle(None); } // If there is a wall in front of character go to climb - if let Some(_wall_dir) = ecs_data.physics.on_wall { - update.character.move_state = MoveState::Climb(None); - return update; - } - - // If on ground go to stand - if ecs_data.physics.on_ground { - update.character.move_state = MoveState::Stand(None); - return update; + if let Some(_) = ecs_data.physics.on_wall { + update.character = CharacterState::Climb(None); } // Move player according to movement direction vector diff --git a/common/src/states/idle.rs b/common/src/states/idle.rs index c9c18aa690..541285dad4 100644 --- a/common/src/states/idle.rs +++ b/common/src/states/idle.rs @@ -1,4 +1,5 @@ -use crate::comp::{ActionState, EcsStateData, ItemKind::Tool, StateUpdate}; +use super::utils::*; +use crate::comp::{EcsStateData, StateUpdate}; use crate::states::StateHandler; #[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] @@ -17,18 +18,13 @@ impl StateHandler for State { ori: *ecs_data.ori, }; - // Try to wield - if ecs_data.inputs.primary.is_pressed() - || ecs_data.inputs.secondary.is_pressed() - || (ecs_data.inputs.toggle_wield.is_just_pressed() - && update.character.action_state.is_equip_finished()) - { - if let Some(Tool(_)) = ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind) { - update.character.action_state = ActionState::Wield(None); - } - - // else unarmed stuff? - } + handle_move_dir(ecs_data, &mut update); + handle_wield(ecs_data, &mut update); + handle_sit(ecs_data, &mut update); + handle_climb(ecs_data, &mut update); + handle_roll(ecs_data, &mut update); + //handle_jump(ecs_data, &mut update); + handle_glide(ecs_data, &mut update); update } diff --git a/common/src/states/mod.rs b/common/src/states/mod.rs index d95186eaf9..a794626c10 100644 --- a/common/src/states/mod.rs +++ b/common/src/states/mod.rs @@ -1,24 +1,14 @@ // Module declarations -pub mod basic_attack; -pub mod basic_block; -pub mod charge_attack; pub mod climb; -pub mod fall; pub mod glide; pub mod idle; -pub mod jump; pub mod roll; -pub mod run; pub mod sit; -pub mod stand; -pub mod swim; pub mod utils; -pub mod wield; +pub mod wielded; +pub mod wielding; -use crate::comp::{ - ActionState, ActionState::*, AttackKind::*, BlockKind::*, DodgeKind::*, EcsStateData, - MoveState, MoveState::*, StateUpdate, -}; +use crate::comp::{EcsStateData, StateUpdate}; /// ## A type for implementing State Handling Behavior. /// @@ -69,123 +59,3 @@ pub trait StateHandler: Default { fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate; fn new(ecs_data: &EcsStateData) -> Self; } - -// fn's relating to individual `ActionState`s -// or passing data from system to handlers -impl ActionState { - /// Passes data to variant or subvariant handlers - /// States contain `Option`s, and will be - /// `None` if state data has not been initialized. So we have to - /// check and intialize new state data if so. - pub fn update(&self, ecs_data: &EcsStateData) -> StateUpdate { - match self { - Attack(kind) => match kind { - BasicAttack(opt_state) => opt_state - // If data hasn't been initialized, initialize a new one - .unwrap_or_else(|| basic_attack::State::new(ecs_data)) - // Call handler - .handle(ecs_data), - Charge(opt_state) => opt_state - .unwrap_or_else(|| charge_attack::State::new(ecs_data)) - .handle(ecs_data), - }, - Block(kind) => match kind { - BasicBlock(opt_state) => opt_state - .unwrap_or_else(|| basic_block::State::new(ecs_data)) - .handle(ecs_data), - }, - Dodge(kind) => match kind { - Roll(opt_state) => opt_state - .unwrap_or_else(|| roll::State::new(ecs_data)) - .handle(ecs_data), - }, - Wield(opt_state) => opt_state - .unwrap_or_else(|| wield::State::new(ecs_data)) - .handle(ecs_data), - Idle(opt_state) => opt_state - .unwrap_or_else(|| idle::State::new(ecs_data)) - .handle(ecs_data), - // All states should be explicitly handled - // Do not use default match: _ => {}, - } - } - - // TODO: remove when we split up character states into SingleAction and MultiAction enum variants - /// Returns whether a given `ActionState` overrides `MoveState` `handle()`ing - pub fn overrides_move_state(&self) -> bool { - match self { - Attack(kind) => match kind { - BasicAttack(_) => false, - Charge(_) => true, - }, - Block(kind) => match kind { - BasicBlock(_) => true, - }, - Dodge(kind) => match kind { - Roll(_) => true, - }, - Wield(_) => false, - Idle(_) => false, - // All states should be explicitly handled - // Do not use default match: _ => {}, - } - } -} - -// fn's that relate to individual `MoveState`s -// or passing data from system to handlers -impl MoveState { - // TODO: remove when we split up character states into SingleAction and MultiAction enum variants - /// Passes data to variant or subvariant handlers - /// States contain `Option`s, and will be - /// `None` if state data has not been initialized. So we have to - /// check and intialize new state data if so. - pub fn overrides_action_state(&self) -> bool { - match self { - Stand(_) => false, - Run(_) => false, - Jump(_) => false, - Climb(_) => true, - Glide(_) => true, - Swim(_) => false, - Fall(_) => false, - Sit(_) => true, - // All states should be explicitly handled - // Do not use default match: _ => {}, - } - } - - /// Passes handle to variant handlers - pub fn update(&self, ecs_data: &EcsStateData) -> StateUpdate { - match self { - Stand(opt_state) => opt_state - // If data hasn't been initialized, initialize a new one - .unwrap_or_else(|| stand::State::new(ecs_data)) - // Call handler - .handle(ecs_data), - Run(opt_state) => opt_state - .unwrap_or_else(|| run::State::new(ecs_data)) - .handle(ecs_data), - Jump(opt_state) => opt_state - .unwrap_or_else(|| jump::State::new(ecs_data)) - .handle(ecs_data), - Climb(opt_state) => opt_state - .unwrap_or_else(|| climb::State::new(ecs_data)) - .handle(ecs_data), - Glide(opt_state) => opt_state - .unwrap_or_else(|| glide::State::new(ecs_data)) - .handle(ecs_data), - Swim(opt_state) => opt_state - .unwrap_or_else(|| swim::State::new(ecs_data)) - .handle(ecs_data), - Fall(opt_state) => opt_state - .unwrap_or_else(|| fall::State::new(ecs_data)) - .handle(ecs_data), - Sit(opt_state) => opt_state - .unwrap_or_else(|| sit::State::new(ecs_data)) - .handle(ecs_data), - // All states should be explicitly handled - // Do not use default match: _ => {}, - } - } -} diff --git a/common/src/states/roll.rs b/common/src/states/roll.rs index 1f3391ae9b..9979d6308d 100644 --- a/common/src/states/roll.rs +++ b/common/src/states/roll.rs @@ -1,7 +1,5 @@ use super::utils::*; -use crate::comp::{ - ActionState::Dodge, DodgeKind::Roll, EcsStateData, ItemKind::Tool, StateUpdate, ToolData, -}; +use crate::comp::{CharacterState, EcsStateData, ItemKind::Tool, StateUpdate, ToolData}; use crate::states::StateHandler; use std::time::Duration; use vek::Vec3; @@ -48,20 +46,13 @@ impl StateHandler for State { .unwrap_or_default() * ROLL_SPEED; - // Check if roll duration has expired - if self.remaining_duration == Duration::default() { - // If so, go back to wielding or idling - update.character.action_state = attempt_wield(ecs_data.stats); - return update; - } - // Otherwise, tick down remaining_duration - update.character.action_state = Dodge(Roll(Some(State { + update.character = CharacterState::Roll(Some(State { remaining_duration: self .remaining_duration .checked_sub(Duration::from_secs_f32(ecs_data.dt.0)) .unwrap_or_default(), - }))); + })); // Keep rolling update diff --git a/common/src/states/run.rs b/common/src/states/run.rs deleted file mode 100644 index 366ae80dab..0000000000 --- a/common/src/states/run.rs +++ /dev/null @@ -1,80 +0,0 @@ -use super::utils::*; -use crate::comp::{ActionState, EcsStateData, MoveState, StateUpdate}; -use crate::states::StateHandler; -use vek::vec::{Vec2, Vec3}; - -const HUMANOID_ACCEL: f32 = 50.0; -const HUMANOID_SPEED: f32 = 120.0; - -#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] -pub struct State; - -impl StateHandler for State { - fn new(_ecs_data: &EcsStateData) -> Self { - Self {} - } - - fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { - let mut update = StateUpdate { - character: *ecs_data.character, - pos: *ecs_data.pos, - vel: *ecs_data.vel, - ori: *ecs_data.ori, - }; - - // Move player according to move_dir - update.vel.0 += Vec2::broadcast(ecs_data.dt.0) - * ecs_data.inputs.move_dir - * if update.vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) { - HUMANOID_ACCEL - } else { - 0.0 - }; - - // Set direction based on move direction when on the ground - let ori_dir = - if let ActionState::Attack(_) | ActionState::Block(_) = update.character.action_state { - Vec2::from(ecs_data.inputs.look_dir).normalized() - } else { - Vec2::from(update.vel.0) - }; - - if ori_dir.magnitude_squared() > 0.0001 - && (update.ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared() - > 0.001 - { - update.ori.0 = - vek::ops::Slerp::slerp(update.ori.0, ori_dir.into(), 9.0 * ecs_data.dt.0); - } - - // Try to sit - if can_sit(ecs_data.physics, ecs_data.inputs, ecs_data.body) { - update.character.move_state = MoveState::Sit(None); - return update; - } - - // Try to climb - if can_climb(ecs_data.physics, ecs_data.inputs, ecs_data.body) { - update.character.move_state = MoveState::Climb(None); - return update; - } - - // Try to jump - if can_jump(ecs_data.physics, ecs_data.inputs) { - update.character.move_state = MoveState::Jump(None); - return update; - } - - // Try to glide - if can_glide(ecs_data.physics, ecs_data.inputs, ecs_data.body) { - update.character.move_state = MoveState::Glide(None); - return update; - } - - // Update based on groundedness - update.character.move_state = - determine_move_from_grounded_state(ecs_data.physics, ecs_data.inputs); - - update - } -} diff --git a/common/src/states/sit.rs b/common/src/states/sit.rs index 47b8fb9aff..f6a392acb8 100644 --- a/common/src/states/sit.rs +++ b/common/src/states/sit.rs @@ -1,5 +1,5 @@ use super::utils::*; -use crate::comp::{ActionState, EcsStateData, MoveState, StateUpdate}; +use crate::comp::{CharacterState, EcsStateData, StateUpdate}; use crate::states::StateHandler; #[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] @@ -18,37 +18,17 @@ impl StateHandler for State { ori: *ecs_data.ori, }; - // Prevent action state handling - update.character.action_state = ActionState::Idle(None); - update.character.move_state = MoveState::Sit(None); + //handle_jump(ecs_data, &mut update); + handle_wield(ecs_data, &mut update); - // Try to Fall - // ... maybe the ground disappears, - // suddenly maybe a water spell appears. - // Can't hurt to be safe :shrug: - if !ecs_data.physics.on_ground { - update.character.move_state = determine_fall_or_swim(ecs_data.physics); - return update; - } - // Try to jump - if ecs_data.inputs.jump.is_pressed() { - update.character.move_state = MoveState::Jump(None); - return update; + // Try to Fall/Stand up/Move + if !ecs_data.physics.on_ground + || ecs_data.inputs.sit.is_just_pressed() + || ecs_data.inputs.move_dir.magnitude_squared() > 0.0 + { + update.character = CharacterState::Idle(None); } - // Try to Run - if ecs_data.inputs.move_dir.magnitude_squared() > 0.0 { - update.character.move_state = MoveState::Run(None); - return update; - } - - // Try to Stand - if ecs_data.inputs.sit.is_just_pressed() { - update.character.move_state = MoveState::Stand(None); - return update; - } - - // No move has occurred, keep sitting update } } diff --git a/common/src/states/stand.rs b/common/src/states/stand.rs index 3068f9e993..37dd3c4bbe 100644 --- a/common/src/states/stand.rs +++ b/common/src/states/stand.rs @@ -36,12 +36,6 @@ impl StateHandler for State { return update; } - // Check gliding - if can_glide(ecs_data.physics, ecs_data.inputs, ecs_data.body) { - update.character.move_state = MoveState::Glide(None); - return update; - } - // Else update based on groundedness update.character.move_state = determine_move_from_grounded_state(ecs_data.physics, ecs_data.inputs); diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index b458596d15..8ae5410587 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -1,8 +1,10 @@ use crate::comp::{ - ActionState, ActionState::*, AttackKind::*, BlockKind::*, Body, ControllerInputs, - ItemKind::Tool, MoveState, MoveState::*, PhysicsState, Stats, + Body, CharacterState, ControllerInputs, EcsStateData, ItemKind::Tool, PhysicsState, + StateUpdate, Stats, }; +use vek::vec::{Vec2, Vec3}; +/* /// _Determines what ability a player has selected for their primary ability, /// and returns the corresponding `ActionState` or Idle if nothing_ pub fn determine_primary_ability(stats: &Stats) -> ActionState { @@ -102,4 +104,91 @@ pub fn can_jump(physics: &PhysicsState, inputs: &ControllerInputs) -> bool { } else { false } +}*/ + +pub fn handle_move_dir(ecs_data: &EcsStateData, update: &mut StateUpdate) { + let (accel, speed): (f32, f32) = if ecs_data.physics.on_ground { + let accel = 50.0; + let speed = 120.0; + (accel, speed) + } else { + let accel = 10.0; + let speed = 100.0; + (accel, speed) + }; + + // Move player according to move_dir + update.vel.0 += Vec2::broadcast(ecs_data.dt.0) + * ecs_data.inputs.move_dir + * if update.vel.0.magnitude_squared() < speed.powf(2.0) { + accel + } else { + 0.0 + }; + + // Set direction based on move direction + let ori_dir = if update.character.is_attack() || update.character.is_block() { + Vec2::from(ecs_data.inputs.look_dir).normalized() + } else { + Vec2::from(update.vel.0) + }; + + // Smooth orientation + if ori_dir.magnitude_squared() > 0.0001 + && (update.ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared() + > 0.001 + { + update.ori.0 = vek::ops::Slerp::slerp(update.ori.0, ori_dir.into(), 9.0 * ecs_data.dt.0); + } +} + +pub fn handle_wield(ecs_data: &EcsStateData, update: &mut StateUpdate) { + if ecs_data.inputs.primary.is_pressed() || ecs_data.inputs.secondary.is_pressed() { + if let Some(Tool(_)) = ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind) { + update.character = CharacterState::Wielding(None); + } + } +} + +pub fn handle_sit(ecs_data: &EcsStateData, update: &mut StateUpdate) { + if ecs_data.inputs.sit.is_pressed() && ecs_data.physics.on_ground && ecs_data.body.is_humanoid() + { + update.character = CharacterState::Sit(None); + } +} + +pub fn handle_climb(ecs_data: &EcsStateData, update: &mut StateUpdate) { + if (ecs_data.inputs.climb.is_pressed() || ecs_data.inputs.climb_down.is_pressed()) + && ecs_data.physics.on_wall.is_some() + && ecs_data.body.is_humanoid() + { + update.character = CharacterState::Climb(None); + } +} + +pub fn handle_roll(ecs_data: &EcsStateData, update: &mut StateUpdate) { + if ecs_data.inputs.roll.is_pressed() + && ecs_data.physics.on_ground + && ecs_data.body.is_humanoid() + { + update.character = CharacterState::Roll(None); + } +} + +pub fn handle_unwield(ecs_data: &EcsStateData, update: &mut StateUpdate) { + if let CharacterState::Wielded(_) = update.character { + if ecs_data.inputs.toggle_wield.is_pressed() { + update.character = CharacterState::Idle(None); + } + } +} + +pub fn handle_glide(ecs_data: &EcsStateData, update: &mut StateUpdate) { + if ecs_data.inputs.glide.is_pressed() + && !ecs_data.physics.on_ground + && ecs_data.body.is_humanoid() + { + dbg!(); + update.character = CharacterState::Glide(None); + } } diff --git a/common/src/states/wielded.rs b/common/src/states/wielded.rs new file mode 100644 index 0000000000..27800331b3 --- /dev/null +++ b/common/src/states/wielded.rs @@ -0,0 +1,43 @@ +use super::utils::*; +use crate::comp::{EcsStateData, ItemKind::Tool, StateUpdate, ToolData}; +use crate::states::StateHandler; +use std::time::Duration; + +#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] +pub struct State { + /// How long before a new action can be performed + /// after equipping + pub equip_delay: Duration, +} + +impl StateHandler for State { + fn new(ecs_data: &EcsStateData) -> Self { + let tool_data = + if let Some(Tool(data)) = ecs_data.stats.equipment.main.as_ref().map(|i| i.kind) { + data + } else { + ToolData::default() + }; + Self { + equip_delay: tool_data.equip_time(), + } + } + + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { + let mut update = StateUpdate { + character: *ecs_data.character, + pos: *ecs_data.pos, + vel: *ecs_data.vel, + ori: *ecs_data.ori, + }; + + handle_move_dir(&ecs_data, &mut update); + handle_sit(&ecs_data, &mut update); + handle_roll(&ecs_data, &mut update); + handle_climb(&ecs_data, &mut update); + handle_glide(&ecs_data, &mut update); + handle_unwield(&ecs_data, &mut update); + + update + } +} diff --git a/common/src/states/wield.rs b/common/src/states/wielding.rs similarity index 55% rename from common/src/states/wield.rs rename to common/src/states/wielding.rs index 508e400113..32e97b8bb4 100644 --- a/common/src/states/wield.rs +++ b/common/src/states/wielding.rs @@ -1,4 +1,5 @@ -use crate::comp::{ActionState, EcsStateData, ItemKind::Tool, StateUpdate, ToolData}; +use super::utils::*; +use crate::comp::{CharacterState, EcsStateData, ItemKind::Tool, StateUpdate, ToolData}; use crate::states::StateHandler; use std::time::Duration; @@ -17,6 +18,7 @@ impl StateHandler for State { } else { ToolData::default() }; + Self { equip_delay: tool_data.equip_time(), } @@ -30,30 +32,15 @@ impl StateHandler for State { ori: *ecs_data.ori, }; - // Only act once equip_delay has expired - if self.equip_delay == Duration::default() { - // Toggle Weapons - if ecs_data.inputs.toggle_wield.is_just_pressed() - && ecs_data.character.action_state.is_equip_finished() - { - update.character.action_state = ActionState::Idle(None); - return update; - } + handle_move_dir(&ecs_data, &mut update); - // Try weapon actions - if ecs_data.inputs.primary.is_pressed() { - // ecs_data - // .updater - // .insert(*ecs_data.entity, AbilityAction(Primary)); - } else if ecs_data.inputs.secondary.is_pressed() { - // ecs_data - // .updater - // .insert(*ecs_data.entity, AbilityAction(Secondary)); - } + if self.equip_delay == Duration::default() { + // Wield delay has expired + update.character = CharacterState::Wielded(None); } else { - // Equip delay hasn't expired yet + // Wield delay hasn't expired yet // Update wield delay - update.character.action_state = ActionState::Wield(Some(State { + update.character = CharacterState::Wielding(Some(State { equip_delay: self .equip_delay .checked_sub(Duration::from_secs_f32(ecs_data.dt.0)) diff --git a/common/src/sys/ability.rs b/common/src/sys/ability.rs index f4569f0b0b..07aaa21bd1 100644 --- a/common/src/sys/ability.rs +++ b/common/src/sys/ability.rs @@ -1,8 +1,6 @@ #![allow(unused_imports)] #![allow(dead_code)] -use crate::comp::{ - AbilityAction, AbilityActionKind, AbilityPool, ActionState::*, AttackKind, CharacterState, -}; +use crate::comp::{AbilityAction, AbilityActionKind, AbilityPool, CharacterState}; use crate::states::StateHandler; use specs::{Entities, Join, LazyUpdate, Read, ReadStorage, System, WriteStorage}; diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index 272462f3f6..649dc86100 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -1,4 +1,4 @@ -use crate::comp::{Agent, CharacterState, Controller, MountState, MoveState::Glide, Pos, Stats}; +use crate::comp::{Agent, CharacterState, Controller, MountState, Pos, Stats}; use crate::hierarchical::ChunkPath; use crate::pathfinding::WorldPath; use crate::terrain::TerrainGrid; @@ -167,11 +167,11 @@ impl<'a> System<'a> for Sys { inputs.roll.set_state(true); } - if target_character.move_state == Glide(None) - && target_pos.0.z > pos.0.z + 5.0 - { - inputs.glide.set_state(true); - inputs.jump.set_state(true); + if let CharacterState::Glide(_) = target_character { + if target_pos.0.z > pos.0.z + 5.0 { + inputs.glide.set_state(true); + inputs.jump.set_state(true); + } } } else { choose_new = true; diff --git a/common/src/sys/character_state.rs b/common/src/sys/character_state.rs index 151b0a3791..c36aae2a1d 100644 --- a/common/src/sys/character_state.rs +++ b/common/src/sys/character_state.rs @@ -1,7 +1,7 @@ use crate::{ comp::{ - Body, CharacterState, Controller, EcsStateData, Mounting, MoveState::*, Ori, PhysicsState, - Pos, Stats, Vel, + Body, CharacterState, Controller, EcsStateData, Mounting, Ori, PhysicsState, Pos, Stats, + Vel, }, event::{EventBus, LocalEvent, ServerEvent}, state::DeltaTime, @@ -87,59 +87,31 @@ impl<'a> System<'a> for Sys { // If mounted, character state is controlled by mount // TODO: Make mounting a state if let Some(Mounting(_)) = mountings.get(entity) { - character.move_state = Sit(None); + *character = CharacterState::Sit(None); return; } - // Determine new action if character can act - if !character.move_state.overrides_action_state() { - let state_update = character.action_state.update(&EcsStateData { - entity: &entity, - uid, - character, - pos, - vel, - ori, - dt: &dt, - inputs, - stats, - body, - physics, - updater: &updater, - server_bus: &server_bus, - local_bus: &local_bus, - }); + let state_update = character.update(&EcsStateData { + entity: &entity, + uid, + character, + pos, + vel, + ori, + dt: &dt, + inputs, + stats, + body, + physics, + updater: &updater, + server_bus: &server_bus, + local_bus: &local_bus, + }); - *character = state_update.character; - *pos = state_update.pos; - *vel = state_update.vel; - *ori = state_update.ori; - } - - // Determine new move state if character can move - if !character.action_state.overrides_move_state() { - let state_update = character.move_state.update(&EcsStateData { - entity: &entity, - uid, - character, - pos, - vel, - ori, - dt: &dt, - inputs, - stats, - body, - physics, - updater: &updater, - server_bus: &server_bus, - local_bus: &local_bus, - }); - - *character = state_update.character; - *pos = state_update.pos; - *vel = state_update.vel; - *ori = state_update.ori; - } + *character = state_update.character; + *pos = state_update.pos; + *vel = state_update.vel; + *ori = state_update.ori; } } } diff --git a/voxygen/src/audio/sfx/event_mapper/movement.rs b/voxygen/src/audio/sfx/event_mapper/movement.rs index eecf6d7752..5026b9c8a6 100644 --- a/voxygen/src/audio/sfx/event_mapper/movement.rs +++ b/voxygen/src/audio/sfx/event_mapper/movement.rs @@ -4,7 +4,7 @@ use crate::audio::sfx::{SfxTriggerItem, SfxTriggers}; use client::Client; use common::{ - comp::{ActionState, Body, CharacterState, MoveState, Pos}, + comp::{Body, CharacterState, Pos}, event::{EventBus, SfxEvent, SfxEventItem}, }; use hashbrown::HashMap; @@ -123,28 +123,21 @@ impl MovementEventMapper { /// as opening or closing the glider. These methods translate those entity states with some additional /// data into more specific `SfxEvent`'s which we attach sounds to fn map_movement_event(current_event: &CharacterState, previous_event: SfxEvent) -> SfxEvent { - match ( - current_event.move_state, - current_event.action_state, - previous_event, - ) { - (_, ActionState::Dodge(_), _) => SfxEvent::Roll, - (MoveState::Climb(_), ..) => SfxEvent::Climb, - (MoveState::Swim(_), ..) => SfxEvent::Swim, - (MoveState::Run(_), ..) => SfxEvent::Run, - (MoveState::Jump(_), ..) => SfxEvent::Jump, - (MoveState::Fall(_), _, SfxEvent::Glide) => SfxEvent::GliderClose, - (MoveState::Stand(_), _, SfxEvent::Fall) => SfxEvent::Run, - (MoveState::Fall(_), _, SfxEvent::Jump) => SfxEvent::Idle, - (MoveState::Fall(_), _, _) => SfxEvent::Fall, - (MoveState::Glide(_), _, previous_event) => { + match (current_event, previous_event) { + (CharacterState::Roll(_), _) => SfxEvent::Roll, + (CharacterState::Climb(_), _) => SfxEvent::Climb, + (CharacterState::Idle(_), _) => SfxEvent::Run, + (CharacterState::Idle(_), SfxEvent::Glide) => SfxEvent::GliderClose, + (CharacterState::Idle(_), SfxEvent::Fall) => SfxEvent::Run, + (CharacterState::Idle(_), SfxEvent::Jump) => SfxEvent::Idle, + (CharacterState::Glide(_), previous_event) => { if previous_event != SfxEvent::GliderOpen && previous_event != SfxEvent::Glide { SfxEvent::GliderOpen } else { SfxEvent::Glide } } - (MoveState::Stand(_), _, SfxEvent::Glide) => SfxEvent::GliderClose, + (CharacterState::Idle(_), SfxEvent::Glide) => SfxEvent::GliderClose, _ => SfxEvent::Idle, } } @@ -153,10 +146,7 @@ impl MovementEventMapper { #[cfg(test)] mod tests { use super::*; - use common::{ - comp::{ActionState, CharacterState, DodgeKind::*, MoveState}, - event::SfxEvent, - }; + use common::{comp::CharacterState, event::SfxEvent}; use std::time::{Duration, Instant}; #[test] @@ -236,118 +226,50 @@ mod tests { #[test] fn maps_idle() { - let result = MovementEventMapper::map_movement_event( - &CharacterState { - move_state: MoveState::Stand(None), - action_state: ActionState::Idle(None), - }, - SfxEvent::Idle, - ); - + let result = + MovementEventMapper::map_movement_event(&CharacterState::Idle(None), SfxEvent::Idle); assert_eq!(result, SfxEvent::Idle); } - #[test] - fn maps_run() { - let result = MovementEventMapper::map_movement_event( - &CharacterState { - move_state: MoveState::Run(None), - action_state: ActionState::Idle(None), - }, - SfxEvent::Idle, - ); - - assert_eq!(result, SfxEvent::Run); - } - #[test] fn maps_roll() { - let result = MovementEventMapper::map_movement_event( - &CharacterState { - action_state: ActionState::Dodge(Roll(None)), - move_state: MoveState::Run(None), - }, - SfxEvent::Run, - ); - + let result = + MovementEventMapper::map_movement_event(&CharacterState::Roll(None), SfxEvent::Run); assert_eq!(result, SfxEvent::Roll); } - #[test] - fn maps_fall() { - let result = MovementEventMapper::map_movement_event( - &CharacterState { - move_state: MoveState::Fall(None), - action_state: ActionState::Idle(None), - }, - SfxEvent::Fall, - ); - - assert_eq!(result, SfxEvent::Fall); - } - #[test] fn maps_land_on_ground_to_run() { - let result = MovementEventMapper::map_movement_event( - &CharacterState { - move_state: MoveState::Stand(None), - action_state: ActionState::Idle(None), - }, - SfxEvent::Fall, - ); - + let result = + MovementEventMapper::map_movement_event(&CharacterState::Idle(None), SfxEvent::Fall); assert_eq!(result, SfxEvent::Run); } #[test] fn maps_glider_open() { - let result = MovementEventMapper::map_movement_event( - &CharacterState { - move_state: MoveState::Glide(None), - action_state: ActionState::Idle(None), - }, - SfxEvent::Jump, - ); - + let result = + MovementEventMapper::map_movement_event(&CharacterState::Glide(None), SfxEvent::Jump); assert_eq!(result, SfxEvent::GliderOpen); } #[test] fn maps_glide() { - let result = MovementEventMapper::map_movement_event( - &CharacterState { - move_state: MoveState::Glide(None), - action_state: ActionState::Idle(None), - }, - SfxEvent::Glide, - ); - + let result = + MovementEventMapper::map_movement_event(&CharacterState::Glide(None), SfxEvent::Glide); assert_eq!(result, SfxEvent::Glide); } #[test] fn maps_glider_close_when_closing_mid_flight() { - let result = MovementEventMapper::map_movement_event( - &CharacterState { - move_state: MoveState::Fall(None), - action_state: ActionState::Idle(None), - }, - SfxEvent::Glide, - ); - + let result = + MovementEventMapper::map_movement_event(&CharacterState::Idle(None), SfxEvent::Glide); assert_eq!(result, SfxEvent::GliderClose); } #[test] fn maps_glider_close_when_landing() { - let result = MovementEventMapper::map_movement_event( - &CharacterState { - move_state: MoveState::Stand(None), - action_state: ActionState::Idle(None), - }, - SfxEvent::Glide, - ); - + let result = + MovementEventMapper::map_movement_event(&CharacterState::Idle(None), SfxEvent::Glide); assert_eq!(result, SfxEvent::GliderClose); } } diff --git a/voxygen/src/menu/char_selection/scene.rs b/voxygen/src/menu/char_selection/scene.rs index e5712f956e..78013154b2 100644 --- a/voxygen/src/menu/char_selection/scene.rs +++ b/voxygen/src/menu/char_selection/scene.rs @@ -168,7 +168,6 @@ impl Scene { Rgba::broadcast(1.0), 1.0 / 60.0, // TODO: Use actual deltatime here? 1.0, - 1.0, 0, true, ); diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index b8dacc5ee1..b681c3df1c 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -6,7 +6,7 @@ use crate::{ }; use common::{ assets::watch::ReloadIndicator, - comp::{ActionState, Body, CharacterState, Equipment, MoveState}, + comp::{Body, CharacterState, Equipment}, }; use hashbrown::HashMap; use std::mem::{discriminant, Discriminant}; @@ -24,15 +24,13 @@ enum FigureKey { #[derive(PartialEq, Eq, Hash, Clone)] struct CharacterStateCacheKey { - move_state: Discriminant, - action: Discriminant, + state: Discriminant, // TODO: Can this be simplified? } impl From<&CharacterState> for CharacterStateCacheKey { fn from(cs: &CharacterState) -> Self { Self { - move_state: discriminant(&cs.move_state), - action: discriminant(&cs.action_state), + state: discriminant(&cs), } } } @@ -132,17 +130,14 @@ impl FigureModelCache { }, if camera_mode == CameraMode::FirstPerson && character_state - .map(|cs| cs.action_state.is_dodging()) + .map(|cs| cs.is_dodge()) .unwrap_or_default() { None } else { Some(humanoid_armor_hand_spec.mesh_left_hand(&body)) }, - if character_state - .map(|cs| cs.action_state.is_dodging()) - .unwrap_or_default() - { + if character_state.map(|cs| cs.is_dodge()).unwrap_or_default() { None } else { Some(humanoid_armor_hand_spec.mesh_right_hand(&body)) @@ -161,10 +156,11 @@ impl FigureModelCache { }, if camera_mode != CameraMode::FirstPerson || character_state - .map(|cs| match cs.action_state { - ActionState::Attack(_) - | ActionState::Block(_) - | ActionState::Wield(_) => true, + .map(|cs| match cs { + //CharacterState::BasicAttack(_) // TODO: enable + //| CharacterState::BasicBlock(_) + CharacterState::Wielding(_) + | CharacterState::Wielded(_) => true, _ => false, }) .unwrap_or_default() diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index bfb89b9b7d..29dd93927a 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -18,8 +18,7 @@ use crate::{ use client::Client; use common::{ comp::{ - ActionState::*, AttackKind::*, Body, CharacterState, ItemKind, Last, MoveState::*, Ori, - Pos, Scale, Stats, ToolData, Vel, + Body, CharacterState, ItemKind, Last, Ori, PhysicsState, Pos, Scale, Stats, ToolData, Vel, }, terrain::TerrainChunk, vol::RectRasterableVol, @@ -80,14 +79,16 @@ impl FigureMgr { .get(client.entity()) .map_or(Vec3::zero(), |pos| pos.0); - for (entity, pos, ori, scale, body, character, last_character, stats) in ( + for (entity, pos, vel, ori, scale, body, character, last_character, physics, stats) in ( &ecs.entities(), &ecs.read_storage::(), + &ecs.read_storage::(), &ecs.read_storage::(), ecs.read_storage::().maybe(), &ecs.read_storage::(), ecs.read_storage::().maybe(), ecs.read_storage::>().maybe(), + &ecs.read_storage::(), ecs.read_storage::().maybe(), ) .join() @@ -328,8 +329,7 @@ impl FigureMgr { ) .1; - let mut move_state_animation_rate = 1.0; - let mut action_animation_rate = 1.0; + let mut state_animation_rate = 1.0; let vel = ecs .read_storage::() @@ -357,121 +357,142 @@ impl FigureMgr { _ => continue, }; - if !character.move_state.equals(&last_character.0.move_state) { - state.move_state_time = 0.0; - } - if !character - .action_state - .equals(&last_character.0.action_state) - { - state.action_time = 0.0; + if !character.equals(&last_character.0) { + state.state_time = 0.0; } - let target_base = match &character.move_state { - Stand(_) => anim::character::StandAnimation::update_skeleton( + let target_base = match ( + physics.on_ground, + vel.0.magnitude_squared() > 0.001, // Moving + physics.in_fluid, // In water + ) { + // Standing + (true, false, false) => anim::character::StandAnimation::update_skeleton( &CharacterSkeleton::new(), (active_tool_kind, time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Run(_) => anim::character::RunAnimation::update_skeleton( + // Running + (true, true, false) => anim::character::RunAnimation::update_skeleton( &CharacterSkeleton::new(), (active_tool_kind, vel.0, ori.0, state.last_ori, time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Jump(_) | Fall(_) => anim::character::JumpAnimation::update_skeleton( + // In air + (false, _, false) => anim::character::JumpAnimation::update_skeleton( &CharacterSkeleton::new(), (active_tool_kind, time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Glide(_) => anim::character::GlidingAnimation::update_skeleton( - &CharacterSkeleton::new(), - (active_tool_kind, vel.0, ori.0, state.last_ori, time), - state.move_state_time, - &mut move_state_animation_rate, - skeleton_attr, - ), - Swim(_) => anim::character::SwimAnimation::update_skeleton( + // Swim + (_, _, true) => anim::character::SwimAnimation::update_skeleton( &CharacterSkeleton::new(), (active_tool_kind, vel.0.magnitude(), ori.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, - skeleton_attr, - ), - Climb(_) => anim::character::ClimbAnimation::update_skeleton( - &CharacterSkeleton::new(), - (active_tool_kind, vel.0, ori.0, time), - state.move_state_time, - &mut move_state_animation_rate, - skeleton_attr, - ), - Sit(_) => anim::character::SitAnimation::update_skeleton( - &CharacterSkeleton::new(), - (active_tool_kind, time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), }; - let target_bones = match (&character.move_state, &character.action_state) { - (Stand(_), Wield { .. }) => { + let target_bones = match &character { + CharacterState::Roll(_) => anim::character::RollAnimation::update_skeleton( + &target_base, + (active_tool_kind, ori.0, state.last_ori, time), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ), + CharacterState::Wielding(_) => { anim::character::CidleAnimation::update_skeleton( &target_base, (active_tool_kind, time), - state.action_time, - &mut action_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ) } - (Stand(_), Block { .. }) => { + CharacterState::Wielded(_) => { + anim::character::CidleAnimation::update_skeleton( + &target_base, + (active_tool_kind, time), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ) + } + /*CharacterState::Block(_) => { anim::character::BlockIdleAnimation::update_skeleton( &target_base, (active_tool_kind, time), - state.action_time, - &mut action_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ) } - (_, Attack(kind)) => match kind { - Charge(_) => anim::character::ChargeAnimation::update_skeleton( + CharacterState::Charge(_) => { + anim::character::ChargeAnimation::update_skeleton( &target_base, (active_tool_kind, time), - state.action_time, - &mut action_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, - ), - BasicAttack(_) => anim::character::AttackAnimation::update_skeleton( + ) + } + CharacterState::BasicAttack(_) => { + anim::character::AttackAnimation::update_skeleton( &target_base, (active_tool_kind, time), - state.action_time, - &mut action_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, - ), - }, - (_, Wield(_)) => anim::character::WieldAnimation::update_skeleton( - &target_base, - (active_tool_kind, vel.0.magnitude(), time), - state.action_time, - &mut action_animation_rate, - skeleton_attr, - ), - (_, Dodge(_)) => anim::character::RollAnimation::update_skeleton( - &target_base, - (active_tool_kind, ori.0, state.last_ori, time), - state.action_time, - &mut action_animation_rate, - skeleton_attr, - ), - (_, Block(_)) => anim::character::BlockAnimation::update_skeleton( - &target_base, + ) + }*/ + CharacterState::Wielding(_) => { + anim::character::WieldAnimation::update_skeleton( + &target_base, + (active_tool_kind, vel.0.magnitude(), time), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ) + } + CharacterState::Wielded(_) => { + anim::character::WieldAnimation::update_skeleton( + &target_base, + (active_tool_kind, vel.0.magnitude(), time), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ) + } + CharacterState::Glide(_) => { + anim::character::GlidingAnimation::update_skeleton( + &target_base, + (active_tool_kind, vel.0, ori.0, state.last_ori, time), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ) + } + CharacterState::Climb(_) => { + anim::character::ClimbAnimation::update_skeleton( + &CharacterSkeleton::new(), + (active_tool_kind, vel.0, ori.0, time), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ) + } + CharacterState::Sit(_) => anim::character::SitAnimation::update_skeleton( + &CharacterSkeleton::new(), (active_tool_kind, time), - state.action_time, - &mut action_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), _ => target_base, @@ -486,8 +507,7 @@ impl FigureMgr { scale, col, dt, - move_state_animation_rate, - action_animation_rate, + state_animation_rate, lpindex, true, ); @@ -505,30 +525,41 @@ impl FigureMgr { _ => continue, }; - if !character.move_state.equals(&last_character.0.move_state) { - state.move_state_time = 0.0; + if !character.equals(&last_character.0) { + state.state_time = 0.0; } - let target_base = match character.move_state { - Stand(_) => anim::quadruped_small::IdleAnimation::update_skeleton( - &QuadrupedSmallSkeleton::new(), - time, - state.move_state_time, - &mut move_state_animation_rate, - skeleton_attr, - ), - Run(_) => anim::quadruped_small::RunAnimation::update_skeleton( + let target_base = match ( + physics.on_ground, + vel.0.magnitude_squared() > 0.001, // Moving + physics.in_fluid, // In water + ) { + // Standing + (true, false, false) => { + anim::quadruped_small::IdleAnimation::update_skeleton( + &QuadrupedSmallSkeleton::new(), + time, + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ) + } + // Running + (true, true, false) => { + anim::quadruped_small::RunAnimation::update_skeleton( + &QuadrupedSmallSkeleton::new(), + (vel.0.magnitude(), time), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ) + } + // In air + (false, _, false) => anim::quadruped_small::JumpAnimation::update_skeleton( &QuadrupedSmallSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, - skeleton_attr, - ), - Jump(_) => anim::quadruped_small::JumpAnimation::update_skeleton( - &QuadrupedSmallSkeleton::new(), - (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), @@ -545,8 +576,7 @@ impl FigureMgr { scale, col, dt, - move_state_animation_rate, - action_animation_rate, + state_animation_rate, lpindex, true, ); @@ -564,32 +594,45 @@ impl FigureMgr { _ => continue, }; - if !character.move_state.equals(&last_character.0.move_state) { - state.move_state_time = 0.0; + if !character.equals(&last_character.0) { + state.state_time = 0.0; } - let target_base = match character.move_state { - Stand(_) => anim::quadruped_medium::IdleAnimation::update_skeleton( - &QuadrupedMediumSkeleton::new(), - time, - state.move_state_time, - &mut move_state_animation_rate, - skeleton_attr, - ), - Run(_) => anim::quadruped_medium::RunAnimation::update_skeleton( - &QuadrupedMediumSkeleton::new(), - (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, - skeleton_attr, - ), - Jump(_) => anim::quadruped_medium::JumpAnimation::update_skeleton( - &QuadrupedMediumSkeleton::new(), - (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, - skeleton_attr, - ), + let target_base = match ( + physics.on_ground, + vel.0.magnitude_squared() > 0.001, // Moving + physics.in_fluid, // In water + ) { + // Standing + (true, false, false) => { + anim::quadruped_medium::IdleAnimation::update_skeleton( + &QuadrupedMediumSkeleton::new(), + time, + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ) + } + // Running + (true, true, false) => { + anim::quadruped_medium::RunAnimation::update_skeleton( + &QuadrupedMediumSkeleton::new(), + (vel.0.magnitude(), time), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ) + } + // In air + (false, _, false) => { + anim::quadruped_medium::JumpAnimation::update_skeleton( + &QuadrupedMediumSkeleton::new(), + (vel.0.magnitude(), time), + state.state_time, + &mut state_animation_rate, + skeleton_attr, + ) + } // TODO! _ => state.skeleton_mut().clone(), @@ -604,8 +647,7 @@ impl FigureMgr { scale, col, dt, - move_state_animation_rate, - action_animation_rate, + state_animation_rate, lpindex, true, ); @@ -621,30 +663,37 @@ impl FigureMgr { _ => continue, }; - if !character.move_state.equals(&last_character.0.move_state) { - state.move_state_time = 0.0; + if !character.equals(&last_character.0) { + state.state_time = 0.0; } - let target_base = match character.move_state { - Stand(_) => anim::bird_medium::IdleAnimation::update_skeleton( + let target_base = match ( + physics.on_ground, + vel.0.magnitude_squared() > 0.001, // Moving + physics.in_fluid, // In water + ) { + // Standing + (true, false, false) => anim::bird_medium::IdleAnimation::update_skeleton( &BirdMediumSkeleton::new(), time, - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Run(_) => anim::bird_medium::RunAnimation::update_skeleton( + // Running + (true, true, false) => anim::bird_medium::RunAnimation::update_skeleton( &BirdMediumSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Jump(_) => anim::bird_medium::JumpAnimation::update_skeleton( + // In air + (false, _, false) => anim::bird_medium::JumpAnimation::update_skeleton( &BirdMediumSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), @@ -661,8 +710,7 @@ impl FigureMgr { scale, col, dt, - move_state_animation_rate, - action_animation_rate, + state_animation_rate, lpindex, true, ); @@ -678,30 +726,37 @@ impl FigureMgr { _ => continue, }; - if !character.move_state.equals(&last_character.0.move_state) { - state.move_state_time = 0.0; + if !character.equals(&last_character.0) { + state.state_time = 0.0; } - let target_base = match character.move_state { - Stand(_) => anim::fish_medium::IdleAnimation::update_skeleton( + let target_base = match ( + physics.on_ground, + vel.0.magnitude_squared() > 0.001, // Moving + physics.in_fluid, // In water + ) { + // Standing + (true, false, false) => anim::fish_medium::IdleAnimation::update_skeleton( &FishMediumSkeleton::new(), time, - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Run(_) => anim::fish_medium::RunAnimation::update_skeleton( + // Running + (true, true, false) => anim::fish_medium::RunAnimation::update_skeleton( &FishMediumSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Jump(_) => anim::fish_medium::JumpAnimation::update_skeleton( + // In air + (false, _, false) => anim::fish_medium::JumpAnimation::update_skeleton( &FishMediumSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), @@ -718,8 +773,7 @@ impl FigureMgr { scale, col, dt, - move_state_animation_rate, - action_animation_rate, + state_animation_rate, lpindex, true, ); @@ -735,30 +789,37 @@ impl FigureMgr { _ => continue, }; - if !character.move_state.equals(&last_character.0.move_state) { - state.move_state_time = 0.0; + if !character.equals(&last_character.0) { + state.state_time = 0.0; } - let target_base = match character.move_state { - Stand(_) => anim::dragon::IdleAnimation::update_skeleton( + let target_base = match ( + physics.on_ground, + vel.0.magnitude_squared() > 0.001, // Moving + physics.in_fluid, // In water + ) { + // Standing + (true, false, false) => anim::dragon::IdleAnimation::update_skeleton( &DragonSkeleton::new(), time, - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Run(_) => anim::dragon::RunAnimation::update_skeleton( + // Running + (true, true, false) => anim::dragon::RunAnimation::update_skeleton( &DragonSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Jump(_) => anim::dragon::JumpAnimation::update_skeleton( + // In air + (false, _, false) => anim::dragon::JumpAnimation::update_skeleton( &DragonSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), @@ -775,8 +836,7 @@ impl FigureMgr { scale, col, dt, - move_state_animation_rate, - action_animation_rate, + state_animation_rate, lpindex, true, ); @@ -792,30 +852,37 @@ impl FigureMgr { _ => continue, }; - if !character.move_state.equals(&last_character.0.move_state) { - state.move_state_time = 0.0; + if !character.equals(&last_character.0) { + state.state_time = 0.0; } - let target_base = match character.move_state { - Stand(_) => anim::bird_small::IdleAnimation::update_skeleton( + let target_base = match ( + physics.on_ground, + vel.0.magnitude_squared() > 0.001, // Moving + physics.in_fluid, // In water + ) { + // Standing + (true, false, false) => anim::bird_small::IdleAnimation::update_skeleton( &BirdSmallSkeleton::new(), time, - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Run(_) => anim::bird_small::RunAnimation::update_skeleton( + // Running + (true, true, false) => anim::bird_small::RunAnimation::update_skeleton( &BirdSmallSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Jump(_) => anim::bird_small::JumpAnimation::update_skeleton( + // In air + (false, _, false) => anim::bird_small::JumpAnimation::update_skeleton( &BirdSmallSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), @@ -832,8 +899,7 @@ impl FigureMgr { scale, col, dt, - move_state_animation_rate, - action_animation_rate, + state_animation_rate, lpindex, true, ); @@ -849,30 +915,37 @@ impl FigureMgr { _ => continue, }; - if !character.move_state.equals(&last_character.0.move_state) { - state.move_state_time = 0.0; + if !character.equals(&last_character.0) { + state.state_time = 0.0; } - let target_base = match character.move_state { - Stand(_) => anim::fish_small::IdleAnimation::update_skeleton( + let target_base = match ( + physics.on_ground, + vel.0.magnitude_squared() > 0.001, // Moving + physics.in_fluid, // In water + ) { + // Standing + (true, false, false) => anim::fish_small::IdleAnimation::update_skeleton( &FishSmallSkeleton::new(), time, - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Run(_) => anim::fish_small::RunAnimation::update_skeleton( + // Running + (true, true, false) => anim::fish_small::RunAnimation::update_skeleton( &FishSmallSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Jump(_) => anim::fish_small::JumpAnimation::update_skeleton( + // In air + (false, _, false) => anim::fish_small::JumpAnimation::update_skeleton( &FishSmallSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), @@ -889,8 +962,7 @@ impl FigureMgr { scale, col, dt, - move_state_animation_rate, - action_animation_rate, + state_animation_rate, lpindex, true, ); @@ -906,30 +978,37 @@ impl FigureMgr { _ => continue, }; - if !character.move_state.equals(&last_character.0.move_state) { - state.move_state_time = 0.0; + if !character.equals(&last_character.0) { + state.state_time = 0.0; } - let target_base = match character.move_state { - Stand(_) => anim::biped_large::IdleAnimation::update_skeleton( + let target_base = match ( + physics.on_ground, + vel.0.magnitude_squared() > 0.001, // Moving + physics.in_fluid, // In water + ) { + // Standing + (true, false, false) => anim::biped_large::IdleAnimation::update_skeleton( &BipedLargeSkeleton::new(), time, - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Run(_) => anim::biped_large::RunAnimation::update_skeleton( + // Running + (true, true, false) => anim::biped_large::RunAnimation::update_skeleton( &BipedLargeSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), - Jump(_) => anim::biped_large::JumpAnimation::update_skeleton( + // In air + (false, _, false) => anim::biped_large::JumpAnimation::update_skeleton( &BipedLargeSkeleton::new(), (vel.0.magnitude(), time), - state.move_state_time, - &mut move_state_animation_rate, + state.state_time, + &mut state_animation_rate, skeleton_attr, ), @@ -946,8 +1025,7 @@ impl FigureMgr { scale, col, dt, - move_state_animation_rate, - action_animation_rate, + state_animation_rate, lpindex, true, ); @@ -967,8 +1045,7 @@ impl FigureMgr { scale, col, dt, - move_state_animation_rate, - action_animation_rate, + state_animation_rate, lpindex, true, ); @@ -1163,8 +1240,7 @@ impl FigureMgr { pub struct FigureState { bone_consts: Consts, locals: Consts, - move_state_time: f64, - action_time: f64, + state_time: f64, skeleton: S, pos: Vec3, ori: Vec3, @@ -1180,8 +1256,7 @@ impl FigureState { .create_consts(&skeleton.compute_matrices()) .unwrap(), locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(), - move_state_time: 0.0, - action_time: 0.0, + state_time: 0.0, skeleton, pos: Vec3::zero(), ori: Vec3::zero(), @@ -1200,8 +1275,7 @@ impl FigureState { scale: f32, col: Rgba, dt: f32, - move_state_rate: f32, - action_rate: f32, + state_animation_rate: f32, lpindex: u8, visible: bool, ) { @@ -1219,8 +1293,7 @@ impl FigureState { self.ori = ori; } - self.move_state_time += (dt * move_state_rate) as f64; - self.action_time += (dt * action_rate) as f64; + self.state_time += (dt * state_animation_rate) as f64; // TODO: what are the interpolated ori values used for if not here??? let mat = Mat4::::identity() diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 5731865710..c4ba62bdd3 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -170,7 +170,7 @@ impl Scene { .ecs() .read_storage::() .get(client.entity()) - .map_or(false, |cs| cs.action_state.is_dodging()); + .map_or(false, |cs| cs.is_dodge()); let player_scale = match client .state() diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index aebc915d6a..514ec17ce0 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -11,7 +11,7 @@ use client::{self, Client, Event::Chat}; use common::{ clock::Clock, comp, - comp::{ActionState, Pos, Vel}, + comp::{Pos, Vel}, msg::ClientState, terrain::{Block, BlockKind}, vol::ReadVol, @@ -212,10 +212,10 @@ impl PlayState for SessionState { .state() .read_storage::() .get(client.entity()) - .map(|cs| match cs.action_state { - ActionState::Attack(_) + .map(|cs| match cs { + /*ActionState::Attack(_) // TODO: uncomment | ActionState::Block(_) - | ActionState::Wield(_) => true, + | ActionState::Wield(_) => true,*/ _ => false, }) .unwrap_or(false)