2019-12-26 14:43:59 +00:00
|
|
|
use self::ActionState::*;
|
|
|
|
use super::states::*;
|
|
|
|
use crate::{
|
|
|
|
comp::{Body, ControllerInputs, Ori, PhysicsState, Pos, Stats, Vel},
|
|
|
|
event::{EventBus, LocalEvent, ServerEvent},
|
|
|
|
state::DeltaTime,
|
|
|
|
};
|
|
|
|
use specs::LazyUpdate;
|
|
|
|
use specs::{Component, Entity, FlaggedStorage, HashMapStorage, NullStorage};
|
|
|
|
use sphynx::Uid;
|
2019-08-23 10:11:37 +00:00
|
|
|
use std::time::Duration;
|
2019-12-20 13:30:37 +00:00
|
|
|
|
2019-12-28 16:10:39 +00:00
|
|
|
pub struct EcsStateData<'a> {
|
2019-12-26 14:43:59 +00:00
|
|
|
pub entity: &'a Entity,
|
|
|
|
pub uid: &'a Uid,
|
|
|
|
pub character: &'a CharacterState,
|
|
|
|
pub pos: &'a Pos,
|
|
|
|
pub vel: &'a Vel,
|
|
|
|
pub ori: &'a Ori,
|
|
|
|
pub dt: &'a DeltaTime,
|
|
|
|
pub inputs: &'a ControllerInputs,
|
|
|
|
pub stats: &'a Stats,
|
|
|
|
pub body: &'a Body,
|
|
|
|
pub physics: &'a PhysicsState,
|
|
|
|
pub updater: &'a LazyUpdate,
|
|
|
|
pub server_bus: &'a EventBus<ServerEvent>,
|
|
|
|
pub local_bus: &'a EventBus<LocalEvent>,
|
|
|
|
}
|
|
|
|
|
2019-12-28 16:10:39 +00:00
|
|
|
pub struct StateUpdate {
|
2019-12-26 14:43:59 +00:00
|
|
|
pub character: CharacterState,
|
|
|
|
pub pos: Pos,
|
|
|
|
pub vel: Vel,
|
|
|
|
pub ori: Ori,
|
|
|
|
}
|
|
|
|
|
2019-12-20 13:30:37 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
2019-12-26 14:43:59 +00:00
|
|
|
pub enum MoveState {
|
2019-12-28 16:10:39 +00:00
|
|
|
Stand(StandState),
|
|
|
|
Run(RunState),
|
|
|
|
Sit(SitState),
|
|
|
|
Jump(JumpState),
|
|
|
|
Fall(FallState),
|
|
|
|
Glide(GlideState),
|
|
|
|
Swim(SwimState),
|
|
|
|
Climb(ClimbState),
|
2019-12-26 14:43:59 +00:00
|
|
|
}
|
|
|
|
|
2019-12-22 16:08:48 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
2019-12-26 14:43:59 +00:00
|
|
|
pub enum ActionState {
|
2019-12-28 16:10:39 +00:00
|
|
|
Idle(IdleState),
|
|
|
|
Wield(WieldState),
|
2019-12-26 14:43:59 +00:00
|
|
|
Attack(AttackKind),
|
|
|
|
Block(BlockKind),
|
|
|
|
Dodge(DodgeKind),
|
2019-12-28 16:10:39 +00:00
|
|
|
// Interact?,
|
2019-12-26 14:43:59 +00:00
|
|
|
}
|
|
|
|
|
2019-12-22 16:08:48 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
2019-12-26 14:43:59 +00:00
|
|
|
pub enum AttackKind {
|
2019-12-28 16:10:39 +00:00
|
|
|
BasicAttack(BasicAttackState),
|
|
|
|
Charge(ChargeAttackState),
|
2019-12-26 14:43:59 +00:00
|
|
|
}
|
2019-12-20 13:30:37 +00:00
|
|
|
|
2019-08-18 09:01:57 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
2019-12-26 14:43:59 +00:00
|
|
|
pub enum BlockKind {
|
2019-12-28 16:10:39 +00:00
|
|
|
BasicBlock(BasicBlockState),
|
2019-08-23 10:11:37 +00:00
|
|
|
}
|
|
|
|
|
2019-08-18 09:01:57 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
2019-12-26 14:43:59 +00:00
|
|
|
pub enum DodgeKind {
|
2019-12-28 16:10:39 +00:00
|
|
|
Roll(RollState),
|
2019-08-23 10:11:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ActionState {
|
2019-12-26 14:43:59 +00:00
|
|
|
pub fn is_equip_finished(&self) -> bool {
|
|
|
|
match self {
|
2019-12-28 16:10:39 +00:00
|
|
|
Wield(WieldState { equip_delay }) => *equip_delay == Duration::default(),
|
2019-12-26 14:43:59 +00:00
|
|
|
_ => true,
|
|
|
|
}
|
|
|
|
}
|
2019-12-29 16:36:59 +00:00
|
|
|
|
|
|
|
/// Returns the current `equip_delay` if in `WieldState`, otherwise `Duration::default()`
|
2019-12-26 14:43:59 +00:00
|
|
|
pub fn get_delay(&self) -> Duration {
|
|
|
|
match self {
|
2019-12-28 16:10:39 +00:00
|
|
|
Wield(WieldState { equip_delay }) => *equip_delay,
|
2019-12-26 14:43:59 +00:00
|
|
|
_ => Duration::default(),
|
2019-08-23 10:11:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-26 14:43:59 +00:00
|
|
|
pub fn is_attacking(&self) -> bool {
|
2019-12-03 06:30:08 +00:00
|
|
|
match self {
|
2019-12-26 14:43:59 +00:00
|
|
|
Block(_) => true,
|
|
|
|
_ => false,
|
2019-12-03 06:30:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-26 14:43:59 +00:00
|
|
|
pub fn is_blocking(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
Attack(_) => true,
|
|
|
|
_ => false,
|
2019-08-23 10:11:37 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-24 16:38:59 +00:00
|
|
|
|
2019-12-26 14:43:59 +00:00
|
|
|
pub fn is_dodging(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
Dodge(_) => true,
|
|
|
|
_ => false,
|
2019-08-24 16:38:59 +00:00
|
|
|
}
|
|
|
|
}
|
2019-12-03 06:30:08 +00:00
|
|
|
|
2019-12-26 14:43:59 +00:00
|
|
|
pub fn is_wielding(&self) -> bool {
|
|
|
|
if let Wield(_) = self {
|
2019-12-03 06:30:08 +00:00
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
2019-12-26 14:43:59 +00:00
|
|
|
pub fn is_idling(&self) -> bool {
|
2019-12-28 16:10:39 +00:00
|
|
|
if let Idle(_) = self {
|
2019-12-03 06:30:08 +00:00
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
2019-08-23 10:11:37 +00:00
|
|
|
}
|
|
|
|
|
2019-12-29 16:36:59 +00:00
|
|
|
/// __A concurrent state machine that allows for spearate `ActionState`s and `MoveState`s.__
|
|
|
|
///
|
|
|
|
/// _Each state can optionally override the other through `*_disabled` flag_
|
2019-08-18 09:01:57 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
2019-08-23 10:11:37 +00:00
|
|
|
pub struct CharacterState {
|
2019-12-28 16:10:39 +00:00
|
|
|
/// __How the character is currently moving, e.g. Running, Standing, Falling.__
|
|
|
|
///
|
|
|
|
/// _Primarily `handle()`s updating `Pos`, `Vel`, `Ori`, and lower body animations.
|
|
|
|
/// Can be overidden by `ActionState`s using `move_disabled` flag. Example: `ChargeAttackState`_
|
2019-12-26 14:43:59 +00:00
|
|
|
pub move_state: MoveState,
|
2019-12-28 16:10:39 +00:00
|
|
|
|
|
|
|
/// __How the character is currently acting, e.g. Wielding, Attacking, Dodging.__
|
|
|
|
///
|
|
|
|
/// _Primarily `handle()`s how character interacts with world, and upper body animations.
|
|
|
|
/// Can be overidden by `MoveState`s using `action_disabled` flag. Example: `GlideState`_
|
2019-12-26 14:43:59 +00:00
|
|
|
pub action_state: ActionState,
|
2019-12-28 16:10:39 +00:00
|
|
|
|
|
|
|
/// Used by `move_state` to disable `action_state` `handle()` calls.
|
2019-12-26 18:01:19 +00:00
|
|
|
pub action_disabled: bool,
|
2019-12-28 16:10:39 +00:00
|
|
|
|
|
|
|
/// Used by `action_state` to disable `move_state` `handle()` calls.
|
2019-12-26 18:01:19 +00:00
|
|
|
pub move_disabled: bool,
|
2019-08-23 10:11:37 +00:00
|
|
|
}
|
|
|
|
|
2019-08-30 18:40:22 +00:00
|
|
|
impl CharacterState {
|
2019-12-28 16:10:39 +00:00
|
|
|
/// __Compares `move_state`s for shallow equality (does not check internal struct equality)__
|
2019-12-26 14:43:59 +00:00
|
|
|
pub fn is_same_move_state(&self, other: &Self) -> bool {
|
|
|
|
// Check if state is the same without looking at the inner data
|
|
|
|
std::mem::discriminant(&self.move_state) == std::mem::discriminant(&other.move_state)
|
2019-08-30 18:40:22 +00:00
|
|
|
}
|
2019-12-26 18:01:19 +00:00
|
|
|
|
2019-12-28 16:10:39 +00:00
|
|
|
/// __Compares `action_state`s for shallow equality (does not check internal struct equality)__
|
2019-12-26 14:43:59 +00:00
|
|
|
pub fn is_same_action_state(&self, other: &Self) -> bool {
|
|
|
|
// Check if state is the same without looking at the inner data
|
|
|
|
std::mem::discriminant(&self.action_state) == std::mem::discriminant(&other.action_state)
|
2019-08-30 18:40:22 +00:00
|
|
|
}
|
2019-12-28 16:10:39 +00:00
|
|
|
|
|
|
|
/// __Compares both `move_state`s and `action_state`a for shallow equality
|
|
|
|
/// (does not check internal struct equality)__
|
2019-08-30 18:40:22 +00:00
|
|
|
pub fn is_same_state(&self, other: &Self) -> bool {
|
2019-12-26 14:43:59 +00:00
|
|
|
self.is_same_move_state(other) && self.is_same_action_state(other)
|
2019-08-30 18:40:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-23 10:11:37 +00:00
|
|
|
impl Default for CharacterState {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
2019-12-28 16:10:39 +00:00
|
|
|
move_state: MoveState::Fall(FallState),
|
|
|
|
action_state: ActionState::Idle(IdleState),
|
2019-12-26 18:01:19 +00:00
|
|
|
action_disabled: false,
|
|
|
|
move_disabled: false,
|
2019-08-23 10:11:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Component for CharacterState {
|
|
|
|
type Storage = FlaggedStorage<Self, HashMapStorage<Self>>;
|
|
|
|
}
|
2019-12-26 14:43:59 +00:00
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
|
|
|
pub struct OverrideState;
|
|
|
|
impl Component for OverrideState {
|
|
|
|
type Storage = FlaggedStorage<Self, NullStorage<Self>>;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
|
|
|
pub struct OverrideAction;
|
|
|
|
impl Component for OverrideAction {
|
|
|
|
type Storage = FlaggedStorage<Self, NullStorage<Self>>;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
|
|
|
pub struct OverrideMove;
|
|
|
|
impl Component for OverrideMove {
|
|
|
|
type Storage = FlaggedStorage<Self, NullStorage<Self>>;
|
|
|
|
}
|