mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
refactor: combine actionstate and movestate
This commit is contained in:
parent
7353ab3432
commit
7b558b4542
@ -23,10 +23,10 @@ impl Component for AbilityAction {
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||
pub struct AbilityPool {
|
||||
pub primary: Option<comp::AttackKind>,
|
||||
pub secondary: Option<comp::AttackKind>,
|
||||
pub block: Option<comp::BlockKind>,
|
||||
pub dodge: Option<comp::DodgeKind>,
|
||||
pub primary: Option<comp::CharacterState>,
|
||||
pub secondary: Option<comp::CharacterState>,
|
||||
pub block: Option<comp::CharacterState>,
|
||||
pub dodge: Option<comp::CharacterState>,
|
||||
}
|
||||
|
||||
impl Component for AbilityPool {
|
||||
|
@ -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<stand::State>),
|
||||
Run(Option<run::State>),
|
||||
Sit(Option<sit::State>),
|
||||
Jump(Option<jump::State>),
|
||||
Fall(Option<fall::State>),
|
||||
Glide(Option<glide::State>),
|
||||
Swim(Option<swim::State>),
|
||||
Climb(Option<climb::State>),
|
||||
}
|
||||
|
||||
#[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<idle::State>),
|
||||
Wield(Option<wield::State>),
|
||||
Attack(AttackKind),
|
||||
Block(BlockKind),
|
||||
Dodge(DodgeKind),
|
||||
// Interact?,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum AttackKind {
|
||||
BasicAttack(Option<basic_attack::State>),
|
||||
Charge(Option<charge_attack::State>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum BlockKind {
|
||||
BasicBlock(Option<basic_block::State>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum DodgeKind {
|
||||
Climb(Option<climb::State>),
|
||||
Sit(Option<sit::State>),
|
||||
Wielding(Option<wielding::State>),
|
||||
Wielded(Option<wielded::State>),
|
||||
//BasicAttack(Option<basic_attack::State>),
|
||||
//BasicBlock(Option<basic_block::State>),
|
||||
//Charge(Option<charge_attack::State>),
|
||||
Roll(Option<roll::State>),
|
||||
Glide(Option<glide::State>),
|
||||
}
|
||||
|
||||
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<StateHandler Implementor>`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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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<StateHandler Implementor>`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<StateHandler Implementor>`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: _ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
43
common/src/states/wielded.rs
Normal file
43
common/src/states/wielded.rs
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -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))
|
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
);
|
||||
|
@ -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<MoveState>,
|
||||
action: Discriminant<ActionState>,
|
||||
state: Discriminant<CharacterState>, // 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()
|
||||
|
@ -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::<Pos>(),
|
||||
&ecs.read_storage::<Vel>(),
|
||||
&ecs.read_storage::<Ori>(),
|
||||
ecs.read_storage::<Scale>().maybe(),
|
||||
&ecs.read_storage::<Body>(),
|
||||
ecs.read_storage::<CharacterState>().maybe(),
|
||||
ecs.read_storage::<Last<CharacterState>>().maybe(),
|
||||
&ecs.read_storage::<PhysicsState>(),
|
||||
ecs.read_storage::<Stats>().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::<Vel>()
|
||||
@ -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<S: Skeleton> {
|
||||
bone_consts: Consts<FigureBoneData>,
|
||||
locals: Consts<FigureLocals>,
|
||||
move_state_time: f64,
|
||||
action_time: f64,
|
||||
state_time: f64,
|
||||
skeleton: S,
|
||||
pos: Vec3<f32>,
|
||||
ori: Vec3<f32>,
|
||||
@ -1180,8 +1256,7 @@ impl<S: Skeleton> FigureState<S> {
|
||||
.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<S: Skeleton> FigureState<S> {
|
||||
scale: f32,
|
||||
col: Rgba<f32>,
|
||||
dt: f32,
|
||||
move_state_rate: f32,
|
||||
action_rate: f32,
|
||||
state_animation_rate: f32,
|
||||
lpindex: u8,
|
||||
visible: bool,
|
||||
) {
|
||||
@ -1219,8 +1293,7 @@ impl<S: Skeleton> FigureState<S> {
|
||||
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::<f32>::identity()
|
||||
|
@ -170,7 +170,7 @@ impl Scene {
|
||||
.ecs()
|
||||
.read_storage::<comp::CharacterState>()
|
||||
.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()
|
||||
|
@ -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::<comp::CharacterState>()
|
||||
.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)
|
||||
|
Loading…
Reference in New Issue
Block a user