mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Clean up, make state handlers options
This commit is contained in:
parent
2f3ccbc5d6
commit
8fe5cec947
@ -5,6 +5,8 @@ use crate::{
|
||||
event::{EventBus, LocalEvent, ServerEvent},
|
||||
state::DeltaTime,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use specs::LazyUpdate;
|
||||
use specs::{Component, Entity, FlaggedStorage, HashMapStorage, NullStorage};
|
||||
use sphynx::Uid;
|
||||
@ -36,20 +38,20 @@ pub struct StateUpdate {
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum MoveState {
|
||||
Stand(StandState),
|
||||
Run(RunState),
|
||||
Sit(SitState),
|
||||
Jump(JumpState),
|
||||
Fall(FallState),
|
||||
Glide(GlideState),
|
||||
Swim(SwimState),
|
||||
Climb(ClimbState),
|
||||
Stand(Option<StandState>),
|
||||
Run(Option<RunState>),
|
||||
Sit(Option<SitState>),
|
||||
Jump(Option<JumpState>),
|
||||
Fall(Option<FallState>),
|
||||
Glide(Option<GlideState>),
|
||||
Swim(Option<SwimState>),
|
||||
Climb(Option<ClimbState>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum ActionState {
|
||||
Idle(IdleState),
|
||||
Wield(WieldState),
|
||||
Idle(Option<IdleState>),
|
||||
Wield(Option<WieldState>),
|
||||
Attack(AttackKind),
|
||||
Block(BlockKind),
|
||||
Dodge(DodgeKind),
|
||||
@ -58,24 +60,24 @@ pub enum ActionState {
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum AttackKind {
|
||||
BasicAttack(BasicAttackState),
|
||||
Charge(ChargeAttackState),
|
||||
BasicAttack(Option<BasicAttackState>),
|
||||
Charge(Option<ChargeAttackState>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum BlockKind {
|
||||
BasicBlock(BasicBlockState),
|
||||
BasicBlock(Option<BasicBlockState>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum DodgeKind {
|
||||
Roll(RollState),
|
||||
Roll(Option<RollState>),
|
||||
}
|
||||
|
||||
impl ActionState {
|
||||
pub fn is_equip_finished(&self) -> bool {
|
||||
match self {
|
||||
Wield(WieldState { equip_delay }) => *equip_delay == Duration::default(),
|
||||
Wield(Some(WieldState { equip_delay })) => *equip_delay == Duration::default(),
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
@ -83,21 +85,21 @@ impl ActionState {
|
||||
/// Returns the current `equip_delay` if in `WieldState`, otherwise `Duration::default()`
|
||||
pub fn get_delay(&self) -> Duration {
|
||||
match self {
|
||||
Wield(WieldState { equip_delay }) => *equip_delay,
|
||||
Wield(Some(WieldState { equip_delay })) => *equip_delay,
|
||||
_ => Duration::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_attacking(&self) -> bool {
|
||||
match self {
|
||||
Block(_) => true,
|
||||
Attack(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_blocking(&self) -> bool {
|
||||
match self {
|
||||
Attack(_) => true,
|
||||
Block(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -126,7 +128,7 @@ impl ActionState {
|
||||
}
|
||||
|
||||
/// __A concurrent state machine that allows for separate `ActionState`s and `MoveState`s.__
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct CharacterState {
|
||||
/// __How the character is currently moving, e.g. Running, Standing, Falling.__
|
||||
///
|
||||
@ -162,8 +164,8 @@ impl CharacterState {
|
||||
impl Default for CharacterState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
move_state: MoveState::Fall(FallState),
|
||||
action_state: ActionState::Idle(IdleState),
|
||||
move_state: MoveState::Fall(Some(FallState)),
|
||||
action_state: ActionState::Idle(Some(IdleState)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::comp::{
|
||||
ActionState::Attack, AttackKind::BasicAttack, EcsStateData, StateHandle, StateUpdate,
|
||||
ActionState::Attack, AttackKind::BasicAttack, EcsStateData, MoveState, StateHandler,
|
||||
StateUpdate, ToolData,
|
||||
};
|
||||
use crate::util::movement_utils::*;
|
||||
use crate::util::state_utils::*;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
@ -10,7 +11,7 @@ pub struct BasicAttackState {
|
||||
pub remaining_duration: Duration,
|
||||
}
|
||||
|
||||
impl StateHandle for BasicAttackState {
|
||||
impl StateHandler for BasicAttackState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
pos: *ecs_data.pos,
|
||||
@ -27,12 +28,12 @@ impl StateHandle for BasicAttackState {
|
||||
}
|
||||
|
||||
// Otherwise, tick down remaining_duration, and keep rolling
|
||||
update.character.action_state = Attack(BasicAttack(BasicAttackState {
|
||||
update.character.action_state = Attack(BasicAttack(Some(BasicAttackState {
|
||||
remaining_duration: self
|
||||
.remaining_duration
|
||||
.checked_sub(Duration::from_secs_f32(ecs_data.dt.0))
|
||||
.unwrap_or_default(),
|
||||
}));
|
||||
})));
|
||||
|
||||
return update;
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
use super::{BLOCK_ACCEL, BLOCK_SPEED};
|
||||
use crate::comp::{EcsStateData, StateHandle, StateUpdate};
|
||||
use crate::util::movement_utils::*;
|
||||
use crate::comp::{EcsStateData, StateHandler, StateUpdate};
|
||||
use crate::util::state_utils::*;
|
||||
use std::time::Duration;
|
||||
use vek::Vec2;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct BasicBlockState {
|
||||
/// How long the blocking state has been active
|
||||
pub active_duration: Duration,
|
||||
}
|
||||
|
||||
impl StateHandle for BasicBlockState {
|
||||
impl StateHandler for BasicBlockState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
pos: *ecs_data.pos,
|
||||
|
@ -1,21 +1,21 @@
|
||||
use crate::comp::{
|
||||
ActionState::Attack, AttackKind::Charge, EcsStateData, HealthChange, HealthSource,
|
||||
MoveState::Run, RunState, StateHandle, StateUpdate,
|
||||
MoveState::Run, RunState, StateHandler, StateUpdate,
|
||||
};
|
||||
use crate::event::ServerEvent;
|
||||
use crate::util::movement_utils::*;
|
||||
use crate::util::state_utils::*;
|
||||
use std::time::Duration;
|
||||
use vek::Vec3;
|
||||
|
||||
use super::CHARGE_SPEED;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct ChargeAttackState {
|
||||
/// How long the state has until exitting
|
||||
pub remaining_duration: Duration,
|
||||
}
|
||||
|
||||
impl StateHandle for ChargeAttackState {
|
||||
impl StateHandler for ChargeAttackState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
pos: *ecs_data.pos,
|
||||
@ -25,7 +25,7 @@ impl StateHandle for ChargeAttackState {
|
||||
};
|
||||
|
||||
// Prevent move state handling, handled here
|
||||
update.character.move_state = Run(RunState);
|
||||
update.character.move_state = Run(Some(RunState));
|
||||
|
||||
// Move player
|
||||
update.vel.0 = Vec3::new(0.0, 0.0, update.vel.0.z)
|
||||
@ -64,12 +64,12 @@ impl StateHandle for ChargeAttackState {
|
||||
}
|
||||
|
||||
// Tick remaining-duration and keep charging
|
||||
update.character.action_state = Attack(Charge(ChargeAttackState {
|
||||
update.character.action_state = Attack(Charge(Some(ChargeAttackState {
|
||||
remaining_duration: self
|
||||
.remaining_duration
|
||||
.checked_sub(Duration::from_secs_f32(ecs_data.dt.0))
|
||||
.unwrap_or_default(),
|
||||
}));
|
||||
})));
|
||||
|
||||
return update;
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
use super::{
|
||||
ActionState::*, EcsStateData, FallState, IdleState, JumpState, MoveState::*, StandState,
|
||||
StateHandle, StateUpdate,
|
||||
StateHandler, StateUpdate,
|
||||
};
|
||||
use super::{CLIMB_SPEED, HUMANOID_CLIMB_ACCEL, HUMANOID_SPEED};
|
||||
use crate::sys::phys::GRAVITY;
|
||||
use vek::vec::{Vec2, Vec3};
|
||||
use vek::Lerp;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct ClimbState;
|
||||
|
||||
impl StateHandle for ClimbState {
|
||||
impl StateHandler for ClimbState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
pos: *ecs_data.pos,
|
||||
@ -19,7 +19,7 @@ impl StateHandle for ClimbState {
|
||||
character: *ecs_data.character,
|
||||
};
|
||||
|
||||
update.character.action_state = Idle(IdleState);
|
||||
update.character.action_state = Idle(Some(IdleState));
|
||||
|
||||
// Move player
|
||||
update.vel.0 += Vec2::broadcast(ecs_data.dt.0)
|
||||
@ -78,12 +78,12 @@ impl StateHandle for ClimbState {
|
||||
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 = Jump(JumpState);
|
||||
update.character.move_state = Jump(Some(JumpState));
|
||||
|
||||
return update;
|
||||
} else {
|
||||
// Just fall off
|
||||
update.character.move_state = Fall(FallState);
|
||||
update.character.move_state = Fall(Some(FallState));
|
||||
|
||||
return update;
|
||||
}
|
||||
@ -91,7 +91,7 @@ impl StateHandle for ClimbState {
|
||||
|
||||
// Remove climb state on ground, otherwise character will get stuck
|
||||
if ecs_data.physics.on_ground {
|
||||
update.character.move_state = Stand(StandState);
|
||||
update.character.move_state = Stand(Some(StandState));
|
||||
return update;
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
use super::{HUMANOID_AIR_ACCEL, HUMANOID_AIR_SPEED};
|
||||
use crate::comp::{ClimbState, EcsStateData, GlideState, MoveState::*, StateHandle, StateUpdate};
|
||||
use crate::comp::{ClimbState, EcsStateData, GlideState, MoveState::*, StateHandler, StateUpdate};
|
||||
|
||||
use crate::util::movement_utils::*;
|
||||
use crate::util::state_utils::*;
|
||||
use vek::{Vec2, Vec3};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct FallState;
|
||||
|
||||
impl StateHandle for FallState {
|
||||
impl StateHandler for FallState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
pos: *ecs_data.pos,
|
||||
@ -44,13 +44,13 @@ impl StateHandle for FallState {
|
||||
|
||||
// Check to start climbing
|
||||
if can_climb(ecs_data.physics, ecs_data.inputs, ecs_data.body) {
|
||||
update.character.move_state = Climb(ClimbState);
|
||||
update.character.move_state = Climb(Some(ClimbState));
|
||||
return update;
|
||||
}
|
||||
|
||||
// Check gliding
|
||||
if ecs_data.inputs.glide.is_pressed() {
|
||||
update.character.move_state = Glide(GlideState);
|
||||
update.character.move_state = Glide(Some(GlideState));
|
||||
return update;
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
use super::{GLIDE_ACCEL, GLIDE_ANTIGRAV, GLIDE_SPEED};
|
||||
use crate::comp::{
|
||||
ActionState::*, ClimbState, EcsStateData, FallState, IdleState, MoveState::*, StandState,
|
||||
StateHandle, StateUpdate,
|
||||
StateHandler, StateUpdate,
|
||||
};
|
||||
use vek::{Vec2, Vec3};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct GlideState;
|
||||
|
||||
impl StateHandle for GlideState {
|
||||
impl StateHandler for GlideState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
pos: *ecs_data.pos,
|
||||
@ -18,8 +18,8 @@ impl StateHandle for GlideState {
|
||||
};
|
||||
|
||||
// Defaults for this state
|
||||
update.character.action_state = Idle(IdleState);
|
||||
update.character.move_state = Glide(GlideState);
|
||||
update.character.action_state = Idle(Some(IdleState));
|
||||
update.character.move_state = Glide(Some(GlideState));
|
||||
|
||||
// Move player according to movement direction vector
|
||||
update.vel.0 += Vec2::broadcast(ecs_data.dt.0)
|
||||
@ -54,19 +54,19 @@ impl StateHandle for GlideState {
|
||||
|
||||
// If glide button isn't held, start falling
|
||||
if !ecs_data.inputs.glide.is_pressed() {
|
||||
update.character.move_state = Fall(FallState);
|
||||
update.character.move_state = Fall(Some(FallState));
|
||||
return update;
|
||||
}
|
||||
|
||||
// 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 = Climb(ClimbState);
|
||||
update.character.move_state = Climb(Some(ClimbState));
|
||||
return update;
|
||||
}
|
||||
|
||||
// If on ground go to stand
|
||||
if ecs_data.physics.on_ground {
|
||||
update.character.move_state = Stand(StandState);
|
||||
update.character.move_state = Stand(Some(StandState));
|
||||
return update;
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
use super::TEMP_EQUIP_DELAY;
|
||||
use crate::comp::{
|
||||
ActionState::Wield, EcsStateData, ItemKind::Tool, StateHandle, StateUpdate, WieldState,
|
||||
ActionState::Wield, EcsStateData, ItemKind::Tool, StateHandler, StateUpdate, WieldState,
|
||||
};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct IdleState;
|
||||
|
||||
impl StateHandle for IdleState {
|
||||
impl StateHandler for IdleState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
character: *ecs_data.character,
|
||||
@ -23,9 +23,9 @@ impl StateHandle for IdleState {
|
||||
&& 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 = Wield(WieldState {
|
||||
update.character.action_state = Wield(Some(WieldState {
|
||||
equip_delay: Duration::from_millis(TEMP_EQUIP_DELAY),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
// else unarmed stuff?
|
||||
|
@ -1,10 +1,10 @@
|
||||
use super::{EcsStateData, FallState, MoveState::*, StateHandle, StateUpdate};
|
||||
use super::{EcsStateData, FallState, MoveState::*, StateHandler, StateUpdate};
|
||||
use crate::event::LocalEvent;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct JumpState;
|
||||
|
||||
impl StateHandle for JumpState {
|
||||
impl StateHandler for JumpState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
character: *ecs_data.character,
|
||||
@ -19,7 +19,7 @@ impl StateHandle for JumpState {
|
||||
.emit(LocalEvent::Jump(*ecs_data.entity));
|
||||
|
||||
// Immediately go to falling state after jump impulse
|
||||
update.character.move_state = Fall(FallState);
|
||||
update.character.move_state = Fall(Some(FallState));
|
||||
return update;
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,8 @@ use super::{
|
||||
ActionState, ActionState::*, AttackKind::*, BlockKind::*, DodgeKind::*, EcsStateData,
|
||||
MoveState, MoveState::*, StateUpdate,
|
||||
};
|
||||
use std::time::Duration;
|
||||
|
||||
/// #### A trait for implementing state `handle()`ing logic.
|
||||
/// _Mimics the typical OOP style state machine pattern where states implement their own behavior,
|
||||
/// exit conditions, and return new states to the state machine upon exit.
|
||||
@ -70,50 +72,49 @@ use super::{
|
||||
/// `CharacterState` update `System` passes `EcsStateData` to `ActionState`/`MoveState` `handle()` which matches the character's
|
||||
/// current state to its `handle()` fn, hiding the implementation details, since the System is only concerned with
|
||||
/// how the update flow occurs and is in charge of updating the ECS components.
|
||||
pub trait StateHandle {
|
||||
pub trait StateHandler: Default {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate;
|
||||
}
|
||||
|
||||
// Public interface that passes EcsStateData to `StateHandle`s `handle()` fn
|
||||
impl StateHandle for ActionState {
|
||||
impl ActionState {
|
||||
/// Passes handle to variant or subvariant handlers
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
pub fn update(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
match self {
|
||||
Attack(kind) => match kind {
|
||||
BasicAttack(state) => state.handle(ecs_data),
|
||||
Charge(state) => state.handle(ecs_data),
|
||||
BasicAttack(Some(state)) => state.handle(&ecs_data),
|
||||
Charge(Some(state)) => state.handle(&ecs_data),
|
||||
},
|
||||
Block(kind) => match kind {
|
||||
BasicBlock(state) => state.handle(ecs_data),
|
||||
BasicBlock(Some(state)) => state.handle(&ecs_data),
|
||||
},
|
||||
Dodge(kind) => match kind {
|
||||
Roll(state) => state.handle(ecs_data),
|
||||
Roll(Some(state)) => state.handle(&ecs_data),
|
||||
},
|
||||
Wield(state) => state.handle(ecs_data),
|
||||
Idle(state) => state.handle(ecs_data),
|
||||
Wield(Some(state)) => state.handle(&ecs_data),
|
||||
Idle(Some(state)) => state.handle(&ecs_data),
|
||||
//
|
||||
// All states should be explicitly handled
|
||||
// Do not use default match: _ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Other fn's that relate to individual `ActionState`s
|
||||
impl ActionState {
|
||||
/// Returns whether a given `ActionState` overrides `MoveState` `handle()`ing
|
||||
pub fn overrides_move_state(&self) -> bool {
|
||||
match self {
|
||||
Attack(kind) => match kind {
|
||||
BasicAttack(state) => false,
|
||||
Charge(state) => true,
|
||||
BasicAttack(_) => false,
|
||||
Charge(_) => true,
|
||||
},
|
||||
Block(kind) => match kind {
|
||||
BasicBlock(state) => true,
|
||||
BasicBlock(_) => true,
|
||||
},
|
||||
Dodge(kind) => match kind {
|
||||
Roll(state) => true,
|
||||
Roll(_) => true,
|
||||
},
|
||||
Wield(state) => false,
|
||||
Idle(state) => false,
|
||||
Wield(_) => false,
|
||||
Idle(_) => false,
|
||||
//
|
||||
// All states should be explicitly handled
|
||||
// Do not use default match: _ => {},
|
||||
}
|
||||
@ -125,33 +126,31 @@ impl MoveState {
|
||||
/// Returns whether a given `ActionState` overrides `MoveState` `handle()`ing
|
||||
pub fn overrides_action_state(&self) -> bool {
|
||||
match self {
|
||||
Stand(state) => false,
|
||||
Run(state) => false,
|
||||
Jump(state) => false,
|
||||
Climb(state) => true,
|
||||
Glide(state) => true,
|
||||
Swim(state) => false,
|
||||
Fall(state) => false,
|
||||
Sit(state) => true,
|
||||
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: _ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Public interface that passes EcsStateData to `StateHandle`s `handle()` fn
|
||||
impl StateHandle for MoveState {
|
||||
/// Passes handle to variant handlers
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
pub fn update(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
match self {
|
||||
Stand(state) => state.handle(&ecs_data),
|
||||
Run(state) => state.handle(&ecs_data),
|
||||
Jump(state) => state.handle(&ecs_data),
|
||||
Climb(state) => state.handle(&ecs_data),
|
||||
Glide(state) => state.handle(&ecs_data),
|
||||
Swim(state) => state.handle(&ecs_data),
|
||||
Fall(state) => state.handle(&ecs_data),
|
||||
Sit(state) => state.handle(&ecs_data),
|
||||
Stand(Some(state)) => state.handle(&ecs_data),
|
||||
Run(Some(state)) => state.handle(&ecs_data),
|
||||
Jump(Some(state)) => state.handle(&ecs_data),
|
||||
Climb(Some(state)) => state.handle(&ecs_data),
|
||||
Glide(Some(state)) => state.handle(&ecs_data),
|
||||
Swim(Some(state)) => state.handle(&ecs_data),
|
||||
Fall(Some(state)) => state.handle(&ecs_data),
|
||||
Sit(Some(state)) => state.handle(&ecs_data),
|
||||
// All states should be explicitly handled
|
||||
// Do not use default match: _ => {},
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::ROLL_SPEED;
|
||||
use crate::comp::{ActionState::*, DodgeKind::*, EcsStateData, StateHandle, StateUpdate};
|
||||
use crate::util::movement_utils::*;
|
||||
use crate::comp::{ActionState::*, DodgeKind::*, EcsStateData, StateHandler, StateUpdate};
|
||||
use crate::util::state_utils::*;
|
||||
use std::time::Duration;
|
||||
use vek::Vec3;
|
||||
|
||||
@ -10,7 +10,7 @@ pub struct RollState {
|
||||
remaining_duration: Duration,
|
||||
}
|
||||
|
||||
impl StateHandle for RollState {
|
||||
impl StateHandler for RollState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
character: *ecs_data.character,
|
||||
@ -40,12 +40,12 @@ impl StateHandle for RollState {
|
||||
}
|
||||
|
||||
// Otherwise, tick down remaining_duration
|
||||
update.character.action_state = Dodge(Roll(RollState {
|
||||
update.character.action_state = Dodge(Roll(Some(RollState {
|
||||
remaining_duration: self
|
||||
.remaining_duration
|
||||
.checked_sub(Duration::from_secs_f32(ecs_data.dt.0))
|
||||
.unwrap_or_default(),
|
||||
}));
|
||||
})));
|
||||
|
||||
// Keep rolling
|
||||
return update;
|
||||
|
@ -1,15 +1,15 @@
|
||||
use super::{HUMANOID_ACCEL, HUMANOID_SPEED};
|
||||
use crate::comp::{
|
||||
ClimbState, EcsStateData, GlideState, JumpState, MoveState::*, SitState, StateHandle,
|
||||
ClimbState, EcsStateData, GlideState, JumpState, MoveState::*, SitState, StateHandler,
|
||||
StateUpdate,
|
||||
};
|
||||
use crate::util::movement_utils::*;
|
||||
use crate::util::state_utils::*;
|
||||
use vek::vec::{Vec2, Vec3};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct RunState;
|
||||
|
||||
impl StateHandle for RunState {
|
||||
impl StateHandler for RunState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
character: *ecs_data.character,
|
||||
@ -46,25 +46,25 @@ impl StateHandle for RunState {
|
||||
|
||||
// Try to sit
|
||||
if can_sit(ecs_data.physics, ecs_data.inputs, ecs_data.body) {
|
||||
update.character.move_state = Sit(SitState);
|
||||
update.character.move_state = Sit(Some(SitState));
|
||||
return update;
|
||||
}
|
||||
|
||||
// Try to climb
|
||||
if can_climb(ecs_data.physics, ecs_data.inputs, ecs_data.body) {
|
||||
update.character.move_state = Climb(ClimbState);
|
||||
update.character.move_state = Climb(Some(ClimbState));
|
||||
return update;
|
||||
}
|
||||
|
||||
// Try to jump
|
||||
if can_jump(ecs_data.physics, ecs_data.inputs) {
|
||||
update.character.move_state = Jump(JumpState);
|
||||
update.character.move_state = Jump(Some(JumpState));
|
||||
return update;
|
||||
}
|
||||
|
||||
// Try to glide
|
||||
if can_glide(ecs_data.physics, ecs_data.inputs, ecs_data.body) {
|
||||
update.character.move_state = Glide(GlideState);
|
||||
update.character.move_state = Glide(Some(GlideState));
|
||||
return update;
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
use crate::comp::{
|
||||
ActionState::*, EcsStateData, IdleState, JumpState, MoveState::*, RunState, StandState,
|
||||
StateHandle, StateUpdate,
|
||||
StateHandler, StateUpdate,
|
||||
};
|
||||
use crate::util::movement_utils::*;
|
||||
use crate::util::state_utils::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct SitState;
|
||||
|
||||
impl StateHandle for SitState {
|
||||
impl StateHandler for SitState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
character: *ecs_data.character,
|
||||
@ -17,8 +17,8 @@ impl StateHandle for SitState {
|
||||
};
|
||||
|
||||
// Prevent action state handling
|
||||
update.character.action_state = Idle(IdleState);
|
||||
update.character.move_state = Sit(SitState);
|
||||
update.character.action_state = Idle(Some(IdleState));
|
||||
update.character.move_state = Sit(Some(SitState));
|
||||
|
||||
// Try to Fall
|
||||
// ... maybe the ground disappears,
|
||||
@ -30,19 +30,19 @@ impl StateHandle for SitState {
|
||||
}
|
||||
// Try to jump
|
||||
if ecs_data.inputs.jump.is_pressed() {
|
||||
update.character.move_state = Jump(JumpState);
|
||||
update.character.move_state = Jump(Some(JumpState));
|
||||
return update;
|
||||
}
|
||||
|
||||
// Try to Run
|
||||
if ecs_data.inputs.move_dir.magnitude_squared() > 0.0 {
|
||||
update.character.move_state = Run(RunState);
|
||||
update.character.move_state = Run(Some(RunState));
|
||||
return update;
|
||||
}
|
||||
|
||||
// Try to Stand
|
||||
if ecs_data.inputs.sit.is_just_pressed() {
|
||||
update.character.move_state = Stand(StandState);
|
||||
update.character.move_state = Stand(Some(StandState));
|
||||
return update;
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
use crate::comp::{
|
||||
ClimbState, EcsStateData, GlideState, JumpState, MoveState::*, SitState, StateHandle,
|
||||
ClimbState, EcsStateData, GlideState, JumpState, MoveState::*, SitState, StateHandler,
|
||||
StateUpdate,
|
||||
};
|
||||
use crate::util::movement_utils::*;
|
||||
use crate::util::state_utils::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct StandState;
|
||||
|
||||
impl StateHandle for StandState {
|
||||
impl StateHandler for StandState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
character: *ecs_data.character,
|
||||
@ -18,25 +18,25 @@ impl StateHandle for StandState {
|
||||
|
||||
// Try to sit
|
||||
if can_sit(ecs_data.physics, ecs_data.inputs, ecs_data.body) {
|
||||
update.character.move_state = Sit(SitState);
|
||||
update.character.move_state = Sit(Some(SitState));
|
||||
return update;
|
||||
}
|
||||
|
||||
// Try to climb
|
||||
if can_climb(ecs_data.physics, ecs_data.inputs, ecs_data.body) {
|
||||
update.character.move_state = Climb(ClimbState);
|
||||
update.character.move_state = Climb(Some(ClimbState));
|
||||
return update;
|
||||
}
|
||||
|
||||
// Try to jump
|
||||
if can_jump(ecs_data.physics, ecs_data.inputs) {
|
||||
update.character.move_state = Jump(JumpState);
|
||||
update.character.move_state = Jump(Some(JumpState));
|
||||
return update;
|
||||
}
|
||||
|
||||
// Check gliding
|
||||
if can_glide(ecs_data.physics, ecs_data.inputs, ecs_data.body) {
|
||||
update.character.move_state = Glide(GlideState);
|
||||
update.character.move_state = Glide(Some(GlideState));
|
||||
return update;
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
use super::{HUMANOID_WATER_ACCEL, HUMANOID_WATER_SPEED};
|
||||
use crate::comp::{EcsStateData, MoveState::*, RunState, StandState, StateHandle, StateUpdate};
|
||||
use crate::comp::{EcsStateData, MoveState::*, RunState, StandState, StateHandler, StateUpdate};
|
||||
use crate::sys::phys::GRAVITY;
|
||||
use vek::{Vec2, Vec3};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct SwimState;
|
||||
|
||||
impl StateHandle for SwimState {
|
||||
impl StateHandler for SwimState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
character: *ecs_data.character,
|
||||
@ -51,16 +51,16 @@ impl StateHandle for SwimState {
|
||||
|
||||
// Not on ground
|
||||
if !ecs_data.physics.on_ground {
|
||||
update.character.move_state = Swim(SwimState);
|
||||
update.character.move_state = Swim(Some(SwimState));
|
||||
return update;
|
||||
}
|
||||
// On ground
|
||||
else {
|
||||
// Return to running or standing based on move inputs
|
||||
update.character.move_state = if ecs_data.inputs.move_dir.magnitude_squared() > 0.0 {
|
||||
Run(RunState)
|
||||
Run(Some(RunState))
|
||||
} else {
|
||||
Stand(StandState)
|
||||
Stand(Some(StandState))
|
||||
};
|
||||
|
||||
return update;
|
||||
|
@ -1,18 +1,18 @@
|
||||
use crate::comp::{
|
||||
AbilityAction, AbilityActionKind::*, ActionState::*, EcsStateData, IdleState, StateHandle,
|
||||
AbilityAction, AbilityActionKind::*, ActionState::*, EcsStateData, IdleState, StateHandler,
|
||||
StateUpdate,
|
||||
};
|
||||
use crate::util::movement_utils::*;
|
||||
use crate::util::state_utils::*;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct WieldState {
|
||||
/// How long before a new action can be performed
|
||||
/// after equipping
|
||||
pub equip_delay: Duration,
|
||||
}
|
||||
|
||||
impl StateHandle for WieldState {
|
||||
impl StateHandler for WieldState {
|
||||
fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate {
|
||||
let mut update = StateUpdate {
|
||||
character: *ecs_data.character,
|
||||
@ -27,29 +27,29 @@ impl StateHandle for WieldState {
|
||||
if ecs_data.inputs.toggle_wield.is_just_pressed()
|
||||
&& ecs_data.character.action_state.is_equip_finished()
|
||||
{
|
||||
update.character.action_state = Idle(IdleState);
|
||||
update.character.action_state = Idle(Some(IdleState));
|
||||
return update;
|
||||
}
|
||||
|
||||
// Try weapon actions
|
||||
if ecs_data.inputs.primary.is_pressed() {
|
||||
ecs_data
|
||||
.updater
|
||||
.insert(*ecs_data.entity, AbilityAction(Primary));
|
||||
// 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));
|
||||
// ecs_data
|
||||
// .updater
|
||||
// .insert(*ecs_data.entity, AbilityAction(Secondary));
|
||||
}
|
||||
} else {
|
||||
// Equip delay hasn't expired yet
|
||||
// Update wield delay
|
||||
update.character.action_state = Wield(WieldState {
|
||||
update.character.action_state = Wield(Some(WieldState {
|
||||
equip_delay: self
|
||||
.equip_delay
|
||||
.checked_sub(Duration::from_secs_f32(ecs_data.dt.0))
|
||||
.unwrap_or_default(),
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
return update;
|
||||
|
@ -1,5 +1,8 @@
|
||||
#![allow(unused_imports)]
|
||||
#![allow(dead_code)]
|
||||
use crate::comp::{
|
||||
AbilityAction, AbilityActionKind, AbilityPool, ActionState::*, AttackKind, CharacterState,
|
||||
StateHandler,
|
||||
};
|
||||
|
||||
use specs::{Entities, Join, LazyUpdate, Read, ReadStorage, System, WriteStorage};
|
||||
@ -37,27 +40,27 @@ impl<'a> System<'a> for Sys {
|
||||
.join()
|
||||
{
|
||||
match ability_action.0 {
|
||||
AbilityActionKind::Primary => {
|
||||
if let Some(attack_kind) = ability_pool.primary {
|
||||
character.action_state = Attack(attack_kind);
|
||||
}
|
||||
}
|
||||
AbilityActionKind::Secondary => {
|
||||
if let Some(attack_kind) = ability_pool.secondary {
|
||||
character.action_state = Attack(attack_kind);
|
||||
}
|
||||
}
|
||||
AbilityActionKind::Block => {
|
||||
if let Some(block_kind) = ability_pool.block {
|
||||
character.action_state = Block(block_kind);
|
||||
}
|
||||
}
|
||||
AbilityActionKind::Dodge => {
|
||||
if let Some(dodge_kind) = ability_pool.dodge {
|
||||
character.action_state = Dodge(dodge_kind);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
// AbilityActionKind::Primary => {
|
||||
// if let Some(AttackKind(Some(attack_kind))) = ability_pool.primary {
|
||||
// character.action_state = Attack(attack_kind::default());
|
||||
// }
|
||||
// }
|
||||
// AbilityActionKind::Secondary => {
|
||||
// if let Some(attack_kind) = ability_pool.secondary {
|
||||
// character.action_state = Attack(attack_kind::default());
|
||||
// }
|
||||
// }
|
||||
// AbilityActionKind::Block => {
|
||||
// if let Some(block_kind) = ability_pool.block {
|
||||
// character.action_state = Block(block_kind::default());
|
||||
// }
|
||||
// }
|
||||
// AbilityActionKind::Dodge => {
|
||||
// if let Some(dodge_kind) = ability_pool.dodge {
|
||||
// character.action_state = Dodge(dodge_kind::default());
|
||||
// }
|
||||
// }
|
||||
// _ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ impl<'a> System<'a> for Sys {
|
||||
inputs.roll.set_state(true);
|
||||
}
|
||||
|
||||
if target_character.move_state == Glide(GlideState)
|
||||
if target_character.move_state == Glide(Some(GlideState))
|
||||
&& target_pos.0.z > pos.0.z + 5.0
|
||||
{
|
||||
inputs.glide.set_state(true);
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
comp::{
|
||||
states::*, Body, CharacterState, Controller, EcsStateData, Mounting, MoveState::*, Ori,
|
||||
OverrideAction, OverrideMove, OverrideState, PhysicsState, Pos, SitState, StateHandle,
|
||||
OverrideAction, OverrideMove, OverrideState, PhysicsState, Pos, SitState, StateHandler,
|
||||
Stats, Vel,
|
||||
},
|
||||
event::{EventBus, LocalEvent, ServerEvent},
|
||||
@ -102,7 +102,7 @@ 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(SitState);
|
||||
character.move_state = Sit(Some(SitState));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ impl<'a> System<'a> for Sys {
|
||||
action_overrides.get(entity),
|
||||
character.action_state.overrides_move_state(),
|
||||
) {
|
||||
let state_update = character.action_state.handle(&EcsStateData {
|
||||
let state_update = character.action_state.update(&EcsStateData {
|
||||
entity: &entity,
|
||||
uid,
|
||||
character,
|
||||
@ -139,7 +139,7 @@ impl<'a> System<'a> for Sys {
|
||||
move_overrides.get(entity),
|
||||
character.move_state.overrides_action_state(),
|
||||
) {
|
||||
let state_update = character.move_state.handle(&EcsStateData {
|
||||
let state_update = character.move_state.update(&EcsStateData {
|
||||
entity: &entity,
|
||||
uid,
|
||||
character,
|
||||
|
@ -7,7 +7,7 @@ lazy_static::lazy_static! {
|
||||
|
||||
use vek::{Mat3, Rgb, Rgba, Vec3};
|
||||
|
||||
pub mod movement_utils;
|
||||
pub mod state_utils;
|
||||
|
||||
/// TODO: Move these to a named utils folder. Are they even being used? I couldnt find references.
|
||||
/// This is a fast approximation of powf. This should only be used when minor accuracy loss is acceptable.
|
||||
|
@ -11,11 +11,11 @@ use std::time::Duration;
|
||||
/// ... or Idle if nothing it possible?_
|
||||
pub fn determine_primary_ability(stats: &Stats) -> ActionState {
|
||||
if let Some(Tool(data)) = stats.equipment.main.as_ref().map(|i| &i.kind) {
|
||||
Attack(BasicAttack(BasicAttackState {
|
||||
Attack(BasicAttack(Some(BasicAttackState {
|
||||
remaining_duration: data.attack_duration(),
|
||||
}))
|
||||
})))
|
||||
} else {
|
||||
Idle(IdleState)
|
||||
Idle(Some(IdleState))
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,11 +24,11 @@ pub fn determine_primary_ability(stats: &Stats) -> ActionState {
|
||||
/// ... or Idle if nothing it possible?_
|
||||
pub fn determine_secondary_ability(stats: &Stats) -> ActionState {
|
||||
if let Some(Tool(data)) = stats.equipment.main.as_ref().map(|i| &i.kind) {
|
||||
Block(BasicBlock(BasicBlockState {
|
||||
Block(BasicBlock(Some(BasicBlockState {
|
||||
active_duration: Duration::default(),
|
||||
}))
|
||||
})))
|
||||
} else {
|
||||
Idle(IdleState)
|
||||
Idle(Some(IdleState))
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,18 +36,18 @@ pub fn determine_secondary_ability(stats: &Stats) -> ActionState {
|
||||
pub fn determine_fall_or_swim(physics: &PhysicsState) -> MoveState {
|
||||
// Check if in fluid to go to swimming or back to falling
|
||||
if physics.in_fluid {
|
||||
Swim(SwimState)
|
||||
Swim(Some(SwimState))
|
||||
} else {
|
||||
Fall(FallState)
|
||||
Fall(Some(FallState))
|
||||
}
|
||||
}
|
||||
/// __Returns a `MoveState` based on `move_dir` magnitude__
|
||||
pub fn determine_stand_or_run(inputs: &ControllerInputs) -> MoveState {
|
||||
// Return to running or standing based on move inputs
|
||||
if inputs.move_dir.magnitude_squared() > 0.0 {
|
||||
Run(RunState)
|
||||
Run(Some(RunState))
|
||||
} else {
|
||||
Stand(StandState)
|
||||
Stand(Some(StandState))
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,11 +72,11 @@ pub fn determine_move_from_grounded_state(
|
||||
/// __Returns an ActionState based on whether character has a weapon equipped.__
|
||||
pub fn attempt_wield(stats: &Stats) -> ActionState {
|
||||
if let Some(Tool { .. }) = stats.equipment.main.as_ref().map(|i| &i.kind) {
|
||||
Wield(WieldState {
|
||||
Wield(Some(WieldState {
|
||||
equip_delay: Duration::from_millis(TEMP_EQUIP_DELAY),
|
||||
})
|
||||
}))
|
||||
} else {
|
||||
Idle(IdleState)
|
||||
Idle(Some(IdleState))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user