Add state disables, cleanup imports

This commit is contained in:
AdamWhitehurst 2019-12-26 10:01:19 -08:00
parent 8e0317e03d
commit 06053faed0
19 changed files with 341 additions and 334 deletions

View File

@ -10,7 +10,7 @@ use specs::{Component, Entity, FlaggedStorage, HashMapStorage, NullStorage};
use sphynx::Uid;
use std::time::Duration;
pub struct ECSStateData<'a> {
pub struct EcsCharacterState<'a> {
pub entity: &'a Entity,
pub uid: &'a Uid,
pub character: &'a CharacterState,
@ -27,7 +27,7 @@ pub struct ECSStateData<'a> {
pub local_bus: &'a EventBus<LocalEvent>,
}
pub struct ECSStateUpdate {
pub struct EcsStateUpdate {
pub character: CharacterState,
pub pos: Pos,
pub vel: Vel,
@ -127,6 +127,8 @@ impl ActionState {
pub struct CharacterState {
pub move_state: MoveState,
pub action_state: ActionState,
pub action_disabled: bool,
pub move_disabled: bool,
}
impl CharacterState {
@ -134,6 +136,7 @@ impl CharacterState {
// Check if state is the same without looking at the inner data
std::mem::discriminant(&self.move_state) == std::mem::discriminant(&other.move_state)
}
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)
@ -148,6 +151,8 @@ impl Default for CharacterState {
Self {
move_state: MoveState::Fall(FallHandler),
action_state: ActionState::Idle,
action_disabled: false,
move_disabled: false,
}
}
}

View File

@ -22,8 +22,8 @@ pub use body::{
quadruped_medium, quadruped_small, Body,
};
pub use character_state::{
ActionState, AttackKind, BlockKind, CharacterState, DodgeKind, ECSStateData, ECSStateUpdate,
MoveState, OverrideAction, OverrideMove, OverrideState,
ActionState, AttackKind, BlockKind, CharacterState, DodgeKind, EcsCharacterState,
EcsStateUpdate, MoveState, OverrideAction, OverrideMove, OverrideState,
};
pub use controller::{
ControlEvent, Controller, ControllerInputs, Input, InputState, InventoryManip, MountState,

View File

@ -1,4 +1,11 @@
use super::{ECSStateData, ECSStateUpdate, StateHandle};
use super::TEMP_EQUIP_DELAY;
use crate::comp::{
ActionState::{Attack, Idle, Wield},
AttackKind::BasicAttack,
EcsCharacterState, EcsStateUpdate,
ItemKind::Tool,
StateHandle, WieldHandler,
};
use std::time::Duration;
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
@ -8,12 +15,38 @@ pub struct BasicAttackHandler {
}
impl StateHandle for BasicAttackHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
return ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
pos: *ecs_data.pos,
vel: *ecs_data.vel,
ori: *ecs_data.ori,
character: *ecs_data.character,
};
// Check if attack duration has expired
if self.remaining_duration == Duration::default() {
// If so, go back to wielding or idling
update.character.action_state = if let Some(Tool { .. }) =
ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind)
{
Wield(WieldHandler {
equip_delay: Duration::from_millis(TEMP_EQUIP_DELAY),
})
} else {
Idle
};
return update;
}
// Otherwise, tick down remaining_duration, and keep rolling
update.character.action_state = Attack(BasicAttack(BasicAttackHandler {
remaining_duration: self
.remaining_duration
.checked_sub(Duration::from_secs_f32(ecs_data.dt.0))
.unwrap_or_default(),
}));
return update;
}
}

View File

@ -1,5 +1,12 @@
use super::{ECSStateData, ECSStateUpdate, StateHandle};
use super::{BLOCK_ACCEL, BLOCK_SPEED, TEMP_EQUIP_DELAY};
use crate::comp::{
ActionState::{Idle, Wield},
EcsCharacterState, EcsStateUpdate,
ItemKind::Tool,
StateHandle, WieldHandler,
};
use std::time::Duration;
use vek::Vec2;
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub struct BasicBlockHandler {
@ -8,12 +15,39 @@ pub struct BasicBlockHandler {
}
impl StateHandle for BasicBlockHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
return ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
pos: *ecs_data.pos,
vel: *ecs_data.vel,
ori: *ecs_data.ori,
character: *ecs_data.character,
};
// TODO: Apply simple move speed debuff instead
// Update movement
update.vel.0 += Vec2::broadcast(ecs_data.dt.0)
* ecs_data.inputs.move_dir
* match ecs_data.physics.on_ground {
true if update.vel.0.magnitude_squared() < BLOCK_SPEED.powf(2.0) => BLOCK_ACCEL,
_ => 0.0,
};
if !ecs_data.inputs.secondary.is_pressed() {
update.character.action_state = if let Some(Tool { .. }) =
ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind)
{
Wield(WieldHandler {
equip_delay: Duration::from_millis(TEMP_EQUIP_DELAY),
})
} else {
Idle
};
update.character.move_disabled = false;
return update;
}
return update;
}
}

View File

@ -1,17 +1,16 @@
use super::{
CharacterState, ECSStateData, ECSStateUpdate, MoveState::Run, RunHandler, Stand, StandHandler,
StateHandle, WieldHandler,
};
use crate::comp::{
ActionState::{Attack, Idle, Wield},
AttackKind::Charge,
HealthChange, HealthSource,
EcsCharacterState, EcsStateUpdate, HealthChange, HealthSource,
ItemKind::Tool,
MoveState::Run,
RunHandler, StateHandle, WieldHandler,
};
use crate::event::ServerEvent;
use std::time::Duration;
use vek::Vec3;
use super::TEMP_EQUIP_DELAY;
use super::{CHARGE_SPEED, TEMP_EQUIP_DELAY};
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub struct ChargeAttackHandler {
@ -20,15 +19,36 @@ pub struct ChargeAttackHandler {
}
impl StateHandle for ChargeAttackHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
let mut update = ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
pos: *ecs_data.pos,
vel: *ecs_data.vel,
ori: *ecs_data.ori,
character: *ecs_data.character,
};
// Prevent move state handling, handled here
// ecs_data.updater.insert(*ecs_data.entity, OverrideMove);
update.character.action_disabled = true;
update.character.move_state = Run(RunHandler);
// Move player
update.vel.0 = Vec3::new(0.0, 0.0, update.vel.0.z)
+ (update.vel.0 * Vec3::new(1.0, 1.0, 0.0)
+ 1.5
* ecs_data
.inputs
.move_dir
.try_normalized()
.unwrap_or_default())
.try_normalized()
.unwrap_or_default()
* CHARGE_SPEED;
// Check if hitting another entity
if let Some(uid_b) = ecs_data.physics.touch_entity {
// Send Damage event
ecs_data.server_bus.emitter().emit(ServerEvent::Damage {
uid: uid_b,
change: HealthChange {
@ -37,49 +57,45 @@ impl StateHandle for ChargeAttackHandler {
},
});
update.character = CharacterState {
move_state: Stand(StandHandler),
action_state: if let Some(Tool { .. }) =
ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind)
{
Wield(WieldHandler {
equip_delay: Duration::from_millis(TEMP_EQUIP_DELAY),
})
} else {
Idle
},
// Go back to wielding
update.character.action_state = if let Some(Tool { .. }) =
ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind)
{
Wield(WieldHandler {
equip_delay: Duration::from_millis(TEMP_EQUIP_DELAY),
})
} else {
Idle
};
update.character.move_disabled = false;
return update;
}
// Check if charge timed out or can't keep moving forward
if self.remaining_duration == Duration::default() || update.vel.0.magnitude_squared() < 10.0
{
update.character = CharacterState {
move_state: Stand(StandHandler),
action_state: if let Some(Tool { .. }) =
ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind)
{
Wield(WieldHandler {
equip_delay: Duration::from_millis(TEMP_EQUIP_DELAY),
})
} else {
Idle
},
update.character.action_state = if let Some(Tool { .. }) =
ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind)
{
Wield(WieldHandler {
equip_delay: Duration::from_millis(TEMP_EQUIP_DELAY),
})
} else {
Idle
};
update.character.move_disabled = false;
return update;
}
update.character = CharacterState {
move_state: Run(RunHandler),
action_state: Attack(Charge(ChargeAttackHandler {
remaining_duration: self
.remaining_duration
.checked_sub(Duration::from_secs_f32(ecs_data.dt.0))
.unwrap_or_default(),
})),
};
// Tick remaining-duration and keep charging
update.character.action_state = Attack(Charge(ChargeAttackHandler {
remaining_duration: self
.remaining_duration
.checked_sub(Duration::from_secs_f32(ecs_data.dt.0))
.unwrap_or_default(),
}));
return update;
}

View File

@ -1,6 +1,6 @@
use super::{
ActionState::*, CharacterState, ECSStateData, ECSStateUpdate, FallHandler, JumpHandler,
MoveState::*, StandHandler, StateHandle,
ActionState::*, EcsCharacterState, EcsStateUpdate, FallHandler, JumpHandler, MoveState::*,
StandHandler, StateHandle,
};
use super::{CLIMB_SPEED, HUMANOID_CLIMB_ACCEL, HUMANOID_SPEED};
use crate::sys::phys::GRAVITY;
@ -11,15 +11,19 @@ use vek::Lerp;
pub struct ClimbHandler;
impl StateHandle for ClimbHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
let mut update = ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
pos: *ecs_data.pos,
vel: *ecs_data.vel,
ori: *ecs_data.ori,
character: *ecs_data.character,
};
// Move player according to move_dir
// Disable actions in this state
update.character.action_state = Idle;
update.character.action_disabled = true;
// Move player
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) {
@ -28,7 +32,7 @@ impl StateHandle for ClimbHandler {
0.0
};
// Set direction based on move direction when on the ground
// Set orientation direction based on wall direction
let ori_dir = if let Some(wall_dir) = ecs_data.physics.on_wall {
if Vec2::<f32>::from(wall_dir).magnitude_squared() > 0.001 {
Vec2::from(wall_dir).normalized()
@ -72,26 +76,27 @@ impl StateHandle for ClimbHandler {
}
}
// If no wall is infront of character ...
if let None = ecs_data.physics.on_wall {
if ecs_data.inputs.jump.is_pressed() {
update.character = CharacterState {
action_state: Idle,
move_state: Jump(JumpHandler),
};
// They've climbed atop something, give them a boost
update.character.move_state = Jump(JumpHandler);
update.character.action_disabled = false;
return update;
} else {
update.character = CharacterState {
action_state: Idle,
move_state: Fall(FallHandler),
};
// Just fall off
update.character.move_state = Fall(FallHandler);
update.character.action_disabled = false;
return update;
}
}
// Remove climb state on ground, otherwise character will get stuck
if ecs_data.physics.on_ground {
update.character = CharacterState {
action_state: Idle,
move_state: Stand(StandHandler),
};
update.character.move_state = Stand(StandHandler);
update.character.action_disabled = false;
return update;
}

View File

@ -1,6 +1,6 @@
use super::{
ActionState::*, CharacterState, ECSStateData, ECSStateUpdate, GlideHandler, MoveState::*,
RunHandler, StandHandler, StateHandle, SwimHandler,
EcsCharacterState, EcsStateUpdate, GlideHandler, MoveState::*, RunHandler, StandHandler,
StateHandle, SwimHandler,
};
use super::{HUMANOID_AIR_ACCEL, HUMANOID_AIR_SPEED};
use vek::{Vec2, Vec3};
@ -9,8 +9,8 @@ use vek::{Vec2, Vec3};
pub struct FallHandler;
impl StateHandle for FallHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
let mut update = ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
pos: *ecs_data.pos,
vel: *ecs_data.vel,
ori: *ecs_data.ori,
@ -34,6 +34,7 @@ impl StateHandle for FallHandler {
} 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
@ -43,11 +44,8 @@ impl StateHandle for FallHandler {
}
// Check gliding
if ecs_data.inputs.glide.is_pressed() && !ecs_data.inputs.glide.is_held_down() {
update.character = CharacterState {
action_state: Idle,
move_state: Glide(GlideHandler),
};
if ecs_data.inputs.glide.is_pressed() {
update.character.move_state = Glide(GlideHandler);
return update;
}
@ -56,17 +54,11 @@ impl StateHandle for FallHandler {
if !ecs_data.physics.on_ground {
// Check if in fluid to go to swimming or back to falling
if ecs_data.physics.in_fluid {
update.character = CharacterState {
action_state: update.character.action_state,
move_state: Swim(SwimHandler),
};
update.character.move_state = Swim(SwimHandler);
return update;
} else {
update.character = CharacterState {
action_state: update.character.action_state,
move_state: Fall(FallHandler),
};
update.character.move_state = Fall(FallHandler);
return update;
}
@ -74,13 +66,10 @@ impl StateHandle for FallHandler {
// On ground
else {
// Return to running or standing based on move inputs
update.character = CharacterState {
action_state: update.character.action_state,
move_state: if ecs_data.inputs.move_dir.magnitude_squared() > 0.0 {
Run(RunHandler)
} else {
Stand(StandHandler)
},
update.character.move_state = if ecs_data.inputs.move_dir.magnitude_squared() > 0.0 {
Run(RunHandler)
} else {
Stand(StandHandler)
};
return update;

View File

@ -1,6 +1,6 @@
use super::{
ActionState::*, CharacterState, ClimbHandler, ECSStateData, ECSStateUpdate, FallHandler,
MoveState::*, StandHandler, StateHandle,
ActionState::*, ClimbHandler, EcsCharacterState, EcsStateUpdate, FallHandler, MoveState::*,
StandHandler, StateHandle,
};
use super::{GLIDE_ACCEL, GLIDE_ANTIGRAV, GLIDE_SPEED};
use vek::{Vec2, Vec3};
@ -9,14 +9,20 @@ use vek::{Vec2, Vec3};
pub struct GlideHandler;
impl StateHandle for GlideHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
let mut update = ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
pos: *ecs_data.pos,
vel: *ecs_data.vel,
ori: *ecs_data.ori,
character: *ecs_data.character,
};
// Prevent action in this state, set here
update.character.action_disabled = true;
update.character.action_state = Idle;
update.character.move_state = Glide(GlideHandler);
// Move player according to movement direction vector
update.vel.0 += Vec2::broadcast(ecs_data.dt.0)
* ecs_data.inputs.move_dir
@ -36,7 +42,7 @@ impl StateHandle for GlideHandler {
vek::ops::Slerp::slerp(update.ori.0, ori_dir.into(), 2.0 * ecs_data.dt.0);
}
// Apply Glide lift
// Apply Glide antigrav lift
if Vec2::<f32>::from(update.vel.0).magnitude_squared() < GLIDE_SPEED.powf(2.0)
&& update.vel.0.z < 0.0
{
@ -50,38 +56,24 @@ impl StateHandle for GlideHandler {
// If glide button isn't held
if !ecs_data.inputs.glide.is_pressed() {
update.character = CharacterState {
action_state: Idle,
move_state: Fall(FallHandler),
};
update.character.move_state = Fall(FallHandler);
return update;
}
// If there is a wall in front of character go to climb
else if let Some(_wall_dir) = ecs_data.physics.on_wall {
update.character = CharacterState {
action_state: Idle,
move_state: Climb(ClimbHandler),
};
update.character.move_state = Climb(ClimbHandler);
return update;
}
// If on ground go to stand
if ecs_data.physics.on_ground {
update.character = CharacterState {
action_state: Idle,
move_state: Stand(StandHandler),
};
update.character.move_state = Stand(StandHandler);
return update;
}
// Otherwise keep gliding
update.character = CharacterState {
action_state: Idle,
move_state: Glide(GlideHandler),
};
return update;
}
}

View File

@ -1,12 +1,12 @@
use super::{CharacterState, ECSStateData, ECSStateUpdate, FallHandler, MoveState::*, StateHandle};
use super::{EcsCharacterState, EcsStateUpdate, FallHandler, MoveState::*, StateHandle};
use crate::event::LocalEvent;
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub struct JumpHandler;
impl StateHandle for JumpHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
let mut update = ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
character: *ecs_data.character,
pos: *ecs_data.pos,
vel: *ecs_data.vel,
@ -18,10 +18,7 @@ impl StateHandle for JumpHandler {
.emitter()
.emit(LocalEvent::Jump(*ecs_data.entity));
update.character = CharacterState {
action_state: ecs_data.character.action_state,
move_state: Fall(FallHandler),
};
update.character.move_state = Fall(FallHandler);
return update;
}

View File

@ -50,17 +50,17 @@ pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0;
// Public interface, wires character states to their handlers.
use super::{
ActionState, ActionState::*, AttackKind::*, BlockKind::*, CharacterState, DodgeKind::*,
ECSStateData, ECSStateUpdate, MoveState, MoveState::*,
ActionState, ActionState::*, AttackKind::*, BlockKind::*, DodgeKind::*, EcsCharacterState,
EcsStateUpdate, MoveState, MoveState::*,
};
pub trait StateHandle {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate;
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate;
}
impl StateHandle for ActionState {
/// Passes handle to variant or subvariant handlers
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
match self {
Attack(kind) => match kind {
BasicAttack(handler) => handler.handle(ecs_data),
@ -73,7 +73,7 @@ impl StateHandle for ActionState {
Roll(handler) => handler.handle(ecs_data),
},
Wield(handler) => handler.handle(ecs_data),
Idle => ECSStateUpdate {
Idle => EcsStateUpdate {
character: *ecs_data.character,
pos: *ecs_data.pos,
vel: *ecs_data.vel,
@ -87,7 +87,7 @@ impl StateHandle for ActionState {
impl StateHandle for MoveState {
/// Passes handle to variant handlers
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
match self {
Stand(handler) => handler.handle(&ecs_data),
Run(handler) => handler.handle(&ecs_data),

View File

@ -1,6 +1,10 @@
use super::{ECSStateData, ECSStateUpdate, StateHandle};
use super::{ROLL_SPEED, TEMP_EQUIP_DELAY};
use crate::comp::{
ActionState::*, DodgeKind::*, EcsCharacterState, EcsStateUpdate, ItemKind::Tool, OverrideMove,
StateHandle, WieldHandler,
};
use std::time::Duration;
use vek::Vec3;
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub struct RollHandler {
/// How long the state has until exitting
@ -8,12 +12,55 @@ pub struct RollHandler {
}
impl StateHandle for RollHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
character: *ecs_data.character,
pos: *ecs_data.pos,
vel: *ecs_data.vel,
ori: *ecs_data.ori,
};
// Prevent move state handling, handled here
ecs_data.updater.insert(*ecs_data.entity, OverrideMove);
// Update velocity
update.vel.0 = Vec3::new(0.0, 0.0, update.vel.0.z)
+ (update.vel.0 * Vec3::new(1.0, 1.0, 0.0)
+ 1.5
* ecs_data
.inputs
.move_dir
.try_normalized()
.unwrap_or_default())
.try_normalized()
.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 = if let Some(Tool { .. }) =
ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind)
{
Wield(WieldHandler {
equip_delay: Duration::from_millis(TEMP_EQUIP_DELAY),
})
} else {
Idle
};
ecs_data.updater.remove::<OverrideMove>(*ecs_data.entity);
return update;
}
// Otherwise, tick down remaining_duration, and keep rolling
update.character.action_state = Dodge(Roll(RollHandler {
remaining_duration: self
.remaining_duration
.checked_sub(Duration::from_secs_f32(ecs_data.dt.0))
.unwrap_or_default(),
}));
return update;
}
}

View File

@ -1,6 +1,6 @@
use super::{
ActionState::*, CharacterState, ClimbHandler, ECSStateData, ECSStateUpdate, FallHandler,
GlideHandler, JumpHandler, MoveState::*, SitHandler, StandHandler, StateHandle, SwimHandler,
ClimbHandler, EcsCharacterState, EcsStateUpdate, FallHandler, GlideHandler, JumpHandler,
MoveState::*, SitHandler, StandHandler, StateHandle, SwimHandler,
};
use super::{HUMANOID_ACCEL, HUMANOID_SPEED};
use vek::vec::{Vec2, Vec3};
@ -9,8 +9,8 @@ use vek::vec::{Vec2, Vec3};
pub struct RunHandler;
impl StateHandle for RunHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
let mut update = ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
character: *ecs_data.character,
pos: *ecs_data.pos,
vel: *ecs_data.vel,
@ -48,10 +48,7 @@ impl StateHandle for RunHandler {
&& ecs_data.physics.on_ground
&& ecs_data.body.is_humanoid()
{
update.character = CharacterState {
action_state: Idle,
move_state: Sit(SitHandler),
};
update.character.move_state = Sit(SitHandler);
return update;
}
@ -62,20 +59,14 @@ impl StateHandle for RunHandler {
&& ecs_data.body.is_humanoid(),
ecs_data.physics.on_wall,
) {
update.character = CharacterState {
action_state: Idle,
move_state: Climb(ClimbHandler),
};
update.character.move_state = Climb(ClimbHandler);
return update;
}
// Try to swim
if !ecs_data.physics.on_ground && ecs_data.physics.in_fluid {
update.character = CharacterState {
action_state: ecs_data.character.action_state,
move_state: Swim(SwimHandler),
};
update.character.move_state = Swim(SwimHandler);
return update;
}
@ -84,18 +75,10 @@ impl StateHandle for RunHandler {
if ecs_data.physics.on_ground {
// Try to jump
if ecs_data.inputs.jump.is_pressed() && !ecs_data.inputs.jump.is_held_down() {
update.character = CharacterState {
action_state: ecs_data.character.action_state,
move_state: Jump(JumpHandler),
};
update.character.move_state = Jump(JumpHandler);
return update;
}
// Try to dodge
if ecs_data.inputs.roll.is_pressed() && ecs_data.body.is_humanoid() {
// updater.insert(entity, DodgeStart);
}
}
// While not on ground ...
else {
@ -105,33 +88,21 @@ impl StateHandle for RunHandler {
&& !ecs_data.inputs.glide.is_held_down()
&& ecs_data.body.is_humanoid()
{
update.character = CharacterState {
action_state: Idle,
move_state: Glide(GlideHandler),
};
update.character.move_state = Glide(GlideHandler);
return update;
}
update.character = CharacterState {
action_state: ecs_data.character.action_state,
move_state: Fall(FallHandler),
};
update.character.move_state = Fall(FallHandler);
return update;
}
if ecs_data.inputs.move_dir.magnitude_squared() > 0.0 {
update.character = CharacterState {
action_state: ecs_data.character.action_state,
move_state: Run(RunHandler),
};
update.character.move_state = Run(RunHandler);
return update;
} else {
update.character = CharacterState {
action_state: ecs_data.character.action_state,
move_state: Stand(StandHandler),
};
update.character.move_state = Stand(StandHandler);
return update;
}

View File

@ -1,76 +1,66 @@
use super::{
ActionState::*, CharacterState, ECSStateData, ECSStateUpdate, FallHandler, JumpHandler,
MoveState::*, RunHandler, StandHandler, StateHandle, SwimHandler,
use crate::comp::{
ActionState::*, EcsCharacterState, EcsStateUpdate, FallHandler, JumpHandler, MoveState::*,
RunHandler, StandHandler, StateHandle, SwimHandler,
};
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub struct SitHandler;
impl StateHandle for SitHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
let mut update = ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
character: *ecs_data.character,
pos: *ecs_data.pos,
vel: *ecs_data.vel,
ori: *ecs_data.ori,
};
// Prevent action state handling
update.character.action_disabled = true;
update.character.action_state = Idle;
update.character.move_state = Sit(SitHandler);
// Falling
// Idk, maybe the ground disappears,
// suddenly maybe a water spell appears.
// Can't hurt to be safe :shrug:
if !ecs_data.physics.on_ground {
if ecs_data.physics.in_fluid {
update.character = CharacterState {
action_state: Idle,
move_state: Swim(SwimHandler),
};
update.character.move_state = Swim(SwimHandler);
update.character.action_disabled = false;
return update;
} else {
update.character = CharacterState {
action_state: Idle,
move_state: Fall(FallHandler),
};
update.character.move_state = Fall(FallHandler);
update.character.action_disabled = false;
return update;
}
}
// Jumping
if ecs_data.inputs.jump.is_pressed() {
update.character = CharacterState {
action_state: Idle,
move_state: Jump(JumpHandler),
};
update.character.move_state = Jump(JumpHandler);
update.character.action_disabled = false;
return update;
}
// Moving
if ecs_data.inputs.move_dir.magnitude_squared() > 0.0 {
update.character = CharacterState {
action_state: Idle,
move_state: Run(RunHandler),
};
update.character.move_state = Run(RunHandler);
update.character.action_disabled = false;
return update;
}
// Standing back up (unsitting)
if ecs_data.inputs.sit.is_just_pressed() {
update.character = CharacterState {
action_state: Idle,
move_state: Stand(StandHandler),
};
update.character.move_state = Stand(StandHandler);
update.character.action_disabled = false;
return update;
}
// no move_state has occurred
update.character = CharacterState {
action_state: Idle,
move_state: Sit(SitHandler),
};
// No move has occurred, keep sitting
return update;
}
}

View File

@ -1,13 +1,13 @@
use super::{
ActionState::*, CharacterState, ClimbHandler, ECSStateData, ECSStateUpdate, FallHandler,
GlideHandler, JumpHandler, MoveState::*, RunHandler, SitHandler, StateHandle, SwimHandler,
ClimbHandler, EcsCharacterState, EcsStateUpdate, FallHandler, GlideHandler, JumpHandler,
MoveState::*, RunHandler, SitHandler, StateHandle, SwimHandler,
};
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub struct StandHandler;
impl StateHandle for StandHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
let mut update = ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
character: *ecs_data.character,
pos: *ecs_data.pos,
vel: *ecs_data.vel,
@ -19,10 +19,7 @@ impl StateHandle for StandHandler {
&& ecs_data.physics.on_ground
&& ecs_data.body.is_humanoid()
{
update.character = CharacterState {
move_state: Sit(SitHandler),
action_state: update.character.action_state,
};
update.character.move_state = Sit(SitHandler);
return update;
}
@ -33,20 +30,14 @@ impl StateHandle for StandHandler {
&& ecs_data.body.is_humanoid(),
ecs_data.physics.on_wall,
) {
update.character = CharacterState {
action_state: update.character.action_state,
move_state: Climb(ClimbHandler),
};
update.character.move_state = Climb(ClimbHandler);
return update;
}
// Try to swim
if !ecs_data.physics.on_ground && ecs_data.physics.in_fluid {
update.character = CharacterState {
action_state: update.character.action_state,
move_state: Swim(SwimHandler),
};
update.character.move_state = Swim(SwimHandler);
return update;
}
@ -55,64 +46,33 @@ impl StateHandle for StandHandler {
if ecs_data.physics.on_ground {
// Try to jump
if ecs_data.inputs.jump.is_pressed() {
update.character = CharacterState {
action_state: update.character.action_state,
move_state: Jump(JumpHandler),
};
update.character.move_state = Jump(JumpHandler);
return update;
}
// // Try to charge
// if inputs.charge.is_pressed() && !inputs.charge.is_held_down() {
// }
// Try to roll
if ecs_data.inputs.roll.is_pressed() && ecs_data.body.is_humanoid() {
// updater.insert(entity, DodgeStart);
}
}
// While not on ground ...
else {
// Try to glide
if ecs_data.physics.on_wall == None
&& ecs_data.inputs.glide.is_pressed()
&& !ecs_data.inputs.glide.is_held_down()
&& ecs_data.body.is_humanoid()
{
update.character = CharacterState {
action_state: Idle,
move_state: Glide(GlideHandler),
};
update.character.move_state = Glide(GlideHandler);
return update;
}
update.character = CharacterState {
action_state: update.character.action_state,
move_state: Fall(FallHandler),
};
update.character.move_state = Fall(FallHandler);
return update;
}
if ecs_data.inputs.primary.is_pressed() {
// updater.insert(entity, PrimaryStart);
} else if ecs_data.inputs.secondary.is_pressed() {
// updater.insert(entity, SecondaryStart);
}
if ecs_data.inputs.move_dir.magnitude_squared() > 0.0 {
update.character = CharacterState {
action_state: update.character.action_state,
move_state: Run(RunHandler),
};
update.character.move_state = Run(RunHandler);
return update;
} else {
update.character = CharacterState {
action_state: update.character.action_state,
move_state: Stand(StandHandler),
};
update.character.move_state = Stand(StandHandler);
return update;
}

View File

@ -1,6 +1,5 @@
use super::{
CharacterState, ECSStateData, ECSStateUpdate, MoveState::*, RunHandler, StandHandler,
StateHandle,
EcsCharacterState, EcsStateUpdate, MoveState::*, RunHandler, StandHandler, StateHandle,
};
use super::{HUMANOID_WATER_ACCEL, HUMANOID_WATER_SPEED};
use crate::sys::phys::GRAVITY;
@ -10,8 +9,8 @@ use vek::{Vec2, Vec3};
pub struct SwimHandler;
impl StateHandle for SwimHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
let mut update = ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
character: *ecs_data.character,
pos: *ecs_data.pos,
vel: *ecs_data.vel,
@ -52,31 +51,19 @@ impl StateHandle for SwimHandler {
(update.vel.0.z + ecs_data.dt.0 * GRAVITY * 1.25).min(HUMANOID_WATER_SPEED);
}
if ecs_data.inputs.primary.is_pressed() {
// TODO: PrimaryStart
} else if ecs_data.inputs.secondary.is_pressed() {
// TODO: SecondaryStart
}
// Not on ground
if !ecs_data.physics.on_ground {
update.character = CharacterState {
action_state: ecs_data.character.action_state,
move_state: Swim(SwimHandler),
};
update.character.move_state = Swim(SwimHandler);
return update;
}
// On ground
else {
// Return to running or standing based on move inputs
update.character = CharacterState {
action_state: ecs_data.character.action_state,
move_state: if ecs_data.inputs.move_dir.magnitude_squared() > 0.0 {
Run(RunHandler)
} else {
Stand(StandHandler)
},
update.character.move_state = if ecs_data.inputs.move_dir.magnitude_squared() > 0.0 {
Run(RunHandler)
} else {
Stand(StandHandler)
};
return update;

View File

@ -1,4 +1,4 @@
use super::{ActionState::*, CharacterState, ECSStateData, ECSStateUpdate, StateHandle};
use super::{ActionState::*, EcsCharacterState, EcsStateUpdate, StateHandle};
use std::time::Duration;
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
@ -9,42 +9,42 @@ pub struct WieldHandler {
}
impl StateHandle for WieldHandler {
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
let mut update = ECSStateUpdate {
fn handle(&self, ecs_data: &EcsCharacterState) -> EcsStateUpdate {
let mut update = EcsStateUpdate {
character: *ecs_data.character,
pos: *ecs_data.pos,
vel: *ecs_data.vel,
ori: *ecs_data.ori,
};
// Toggling Weapons
if ecs_data.inputs.toggle_wield.is_pressed()
&& ecs_data.character.action_state.is_equip_finished()
{
update.character = CharacterState {
action_state: Idle,
move_state: ecs_data.character.move_state,
};
// Only act once equip_delay has expired
if self.equip_delay == Duration::default() {
// Toggle Weapons
if ecs_data.inputs.toggle_wield.is_pressed()
&& ecs_data.character.action_state.is_equip_finished()
{
update.character.action_state = Idle;
return update;
return update;
}
// Try weapon actions
if ecs_data.inputs.primary.is_pressed() {
// TODO: PrimaryStart
} else if ecs_data.inputs.secondary.is_pressed() {
// TODO: SecondaryStart
}
}
if ecs_data.inputs.primary.is_pressed() {
// TODO: PrimaryStart
} else if ecs_data.inputs.secondary.is_pressed() {
// TODO: SecondaryStart
}
// Update wield delay
update.character = CharacterState {
action_state: Wield(WieldHandler {
// Equip delay hasn't expired yet
else {
// Update wield delay
update.character.action_state = Wield(WieldHandler {
equip_delay: self
.equip_delay
.checked_sub(Duration::from_secs_f32(ecs_data.dt.0))
.unwrap_or_default(),
}),
move_state: ecs_data.character.move_state,
};
});
}
return update;
}

View File

@ -1,6 +1,6 @@
use crate::comp::{
Agent, CharacterState, Controller, ControllerInputs, GlideHandler, MountState,
MoveState::Glide, Pos, SitHandler, Stats,
MoveState::Glide, Pos, Stats,
};
use crate::pathfinding::WorldPath;
use crate::terrain::TerrainGrid;

View File

@ -1,8 +1,8 @@
use crate::{
comp::{
Body, CharacterState, Controller, ControllerInputs, ECSStateData, Mounting, MoveState::*,
Ori, OverrideAction, OverrideMove, OverrideState, PhysicsState, Pos, SitHandler,
StateHandle, Stats, Vel,
Body, CharacterState, Controller, EcsCharacterState, Mounting, MoveState::*, Ori,
OverrideAction, OverrideMove, OverrideState, PhysicsState, Pos, SitHandler, StateHandle,
Stats, Vel,
},
event::{EventBus, LocalEvent, ServerEvent},
state::DeltaTime,
@ -41,7 +41,7 @@ impl<'a> System<'a> for Sys {
&mut self,
(
entities,
uid_allocator,
_uid_allocator,
server_bus,
local_bus,
dt,
@ -65,9 +65,9 @@ impl<'a> System<'a> for Sys {
entity,
uid,
mut character,
mut pos,
mut vel,
mut ori,
pos,
vel,
ori,
controller,
stats,
body,
@ -108,15 +108,15 @@ impl<'a> System<'a> for Sys {
continue;
}
// If mounted, character state is controlled by mount
// TODO: Make mounting a stater
// TODO: Make mounting a state
if maybe_mount.is_some() {
character.move_state = Sit(SitHandler);
continue;
}
// Determine new move state if can move
if !maybe_move_override.is_some() {
let state_update = character.move_state.handle(&ECSStateData {
if !maybe_move_override.is_some() && !character.move_disabled {
let state_update = character.move_state.handle(&EcsCharacterState {
entity: &entity,
uid,
character,
@ -140,8 +140,8 @@ impl<'a> System<'a> for Sys {
}
// Determine new action if can_act
if !maybe_action_override.is_some() {
let state_update = character.action_state.handle(&ECSStateData {
if !maybe_action_override.is_some() && !character.action_disabled {
let state_update = character.action_state.handle(&EcsCharacterState {
entity: &entity,
uid,
character,
@ -163,24 +163,6 @@ impl<'a> System<'a> for Sys {
*vel = state_update.vel;
*ori = state_update.ori;
}
// Rolling + Any Movement, prioritizes finishing charge
// over move_state states
// (
// Roll {
// time_left,
// was_wielding,
// },
// _,
// ) => {
// if time_left == Duration::default() {
// if was_wielding {
// character.action = try_wield(stats);
// } else {
// character.action = Idle;
// }
// }
// }
}
}
}

View File

@ -25,11 +25,10 @@ impl<'a> System<'a> for Sys {
);
fn run(
&mut self,
(entities, uid_allocator, server_bus, local_bus, dt, mut controllers, uids): Self::SystemData,
(entities, uid_allocator, server_bus, _local_bus, _dt, mut controllers, uids): Self::SystemData,
) {
let mut server_emitter = server_bus.emitter();
let mut local_emitter = local_bus.emitter();
for (entity, uid, controller) in (&entities, &uids, &mut controllers).join() {
for (entity, _uid, controller) in (&entities, &uids, &mut controllers).join() {
let inputs = &mut controller.inputs;
// Update `inputs.move_dir`.