2019-12-26 14:43:59 +00:00
|
|
|
use crate::{
|
2020-02-24 18:17:16 +00:00
|
|
|
comp::{
|
|
|
|
AbilityPool, Body, ControllerInputs, Energy, Ori, PhysicsState, Pos, Stats, ToolData, Vel,
|
|
|
|
},
|
2020-02-03 10:54:50 +00:00
|
|
|
event::{LocalEvent, ServerEvent},
|
2019-12-26 14:43:59 +00:00
|
|
|
state::DeltaTime,
|
2020-02-03 21:02:32 +00:00
|
|
|
states::*,
|
2020-01-16 13:28:45 +00:00
|
|
|
sync::Uid,
|
2019-12-26 14:43:59 +00:00
|
|
|
};
|
2020-02-03 21:02:32 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2020-02-11 15:42:17 +00:00
|
|
|
use specs::{Component, Entity, FlaggedStorage, HashMapStorage, LazyUpdate, VecStorage};
|
2020-02-24 18:17:16 +00:00
|
|
|
use std::collections::VecDeque;
|
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,
|
2020-02-24 18:17:16 +00:00
|
|
|
pub energy: &'a Energy,
|
2019-12-26 14:43:59 +00:00
|
|
|
pub body: &'a Body,
|
|
|
|
pub physics: &'a PhysicsState,
|
2020-02-03 10:54:50 +00:00
|
|
|
pub ability_pool: &'a AbilityPool,
|
2019-12-26 14:43:59 +00:00
|
|
|
pub updater: &'a LazyUpdate,
|
|
|
|
}
|
|
|
|
|
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,
|
2020-02-24 18:17:16 +00:00
|
|
|
pub energy: Energy,
|
2020-02-03 10:54:50 +00:00
|
|
|
pub local_events: VecDeque<LocalEvent>,
|
|
|
|
pub server_events: VecDeque<ServerEvent>,
|
2019-12-26 14:43:59 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
|
|
|
pub enum CharacterState {
|
2020-01-08 16:56:36 +00:00
|
|
|
Idle(Option<idle::State>),
|
2020-01-21 22:54:32 +00:00
|
|
|
Climb(Option<climb::State>),
|
|
|
|
Sit(Option<sit::State>),
|
|
|
|
Wielding(Option<wielding::State>),
|
|
|
|
Wielded(Option<wielded::State>),
|
2020-02-03 10:54:50 +00:00
|
|
|
Glide(Option<glide::State>),
|
|
|
|
BasicAttack(Option<basic_attack::State>),
|
2020-02-24 14:35:07 +00:00
|
|
|
BasicBlock(Option<basic_block::State>),
|
2020-01-21 22:54:32 +00:00
|
|
|
//Charge(Option<charge_attack::State>),
|
2020-01-08 16:56:36 +00:00
|
|
|
Roll(Option<roll::State>),
|
2019-08-23 10:11:37 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
impl CharacterState {
|
2020-02-24 19:57:33 +00:00
|
|
|
pub fn is_wielded(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
CharacterState::Wielded(_) => true,
|
|
|
|
CharacterState::BasicAttack(_) => true,
|
|
|
|
CharacterState::BasicBlock(_) => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
pub fn is_attack(&self) -> bool {
|
2019-12-03 06:30:08 +00:00
|
|
|
match self {
|
2020-02-03 10:54:50 +00:00
|
|
|
CharacterState::BasicAttack(_) => true,
|
2019-12-26 14:43:59 +00:00
|
|
|
_ => false,
|
2019-12-03 06:30:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
pub fn is_block(&self) -> bool {
|
2019-12-26 14:43:59 +00:00
|
|
|
match self {
|
2020-02-24 14:35:07 +00:00
|
|
|
CharacterState::BasicBlock(_) => true,
|
2019-12-26 14:43:59 +00:00
|
|
|
_ => false,
|
2019-08-23 10:11:37 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-24 16:38:59 +00:00
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
pub fn is_dodge(&self) -> bool {
|
2019-12-26 14:43:59 +00:00
|
|
|
match self {
|
2020-01-21 22:54:32 +00:00
|
|
|
CharacterState::Roll(_) => true,
|
2019-12-26 14:43:59 +00:00
|
|
|
_ => false,
|
2019-08-24 16:38:59 +00:00
|
|
|
}
|
|
|
|
}
|
2020-01-08 19:31:42 +00:00
|
|
|
|
2020-01-22 12:48:55 +00:00
|
|
|
/// Compares for shallow equality (does not check internal struct equality)
|
2020-01-08 19:31:42 +00:00
|
|
|
pub fn equals(&self, other: &Self) -> bool {
|
|
|
|
// Check if state is the same without looking at the inner data
|
2020-01-22 12:48:55 +00:00
|
|
|
std::mem::discriminant(self) == std::mem::discriminant(other)
|
2019-12-03 06:30:08 +00:00
|
|
|
}
|
2019-08-23 10:11:37 +00:00
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
/// 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
|
2020-02-03 10:54:50 +00:00
|
|
|
// If data hasn't been initialized, initialize a new one
|
2020-01-21 22:54:32 +00:00
|
|
|
.unwrap_or_else(|| idle::State::new(ecs_data))
|
2020-02-03 10:54:50 +00:00
|
|
|
// Call handler
|
2020-01-21 22:54:32 +00:00
|
|
|
.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),
|
2020-02-03 10:54:50 +00:00
|
|
|
CharacterState::BasicAttack(opt_state) => opt_state
|
2020-01-21 22:54:32 +00:00
|
|
|
.unwrap_or_else(|| basic_attack::State::new(ecs_data))
|
|
|
|
.handle(ecs_data),
|
|
|
|
CharacterState::BasicBlock(opt_state) => opt_state
|
|
|
|
.unwrap_or_else(|| basic_block::State::new(ecs_data))
|
2020-02-24 14:35:07 +00:00
|
|
|
.handle(ecs_data),
|
|
|
|
/*CharacterState::Charge(opt_state) => opt_state
|
|
|
|
.unwrap_or_else(|| charge_attack::State::new(ecs_data))
|
|
|
|
.handle(ecs_data),*/
|
2020-01-21 22:54:32 +00:00
|
|
|
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),
|
2020-02-03 21:02:32 +00:00
|
|
|
/* All states should be explicitly handled
|
|
|
|
* DO NOT use default match: _ => {}, */
|
2020-01-21 22:54:32 +00:00
|
|
|
}
|
2019-08-30 18:40:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-23 10:11:37 +00:00
|
|
|
impl Default for CharacterState {
|
2020-02-03 21:02:32 +00:00
|
|
|
fn default() -> Self { Self::Idle(None) }
|
2019-08-23 10:11:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Component for CharacterState {
|
|
|
|
type Storage = FlaggedStorage<Self, HashMapStorage<Self>>;
|
|
|
|
}
|
2020-02-11 15:42:17 +00:00
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
|
|
|
pub struct Attacking {
|
|
|
|
pub weapon: ToolData,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Component for Attacking {
|
|
|
|
type Storage = VecStorage<Self>;
|
|
|
|
}
|