mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
refactor states to handle update logic
This commit is contained in:
parent
c2ceabea0e
commit
8e0317e03d
@ -1,109 +1,121 @@
|
||||
use crate::comp::{Body, Controller, ControllerInputs, ItemKind, PhysicsState, Stats};
|
||||
use specs::{Component, FlaggedStorage, HashMapStorage};
|
||||
use specs::{Entities, Join, LazyUpdate, Read, ReadStorage, System};
|
||||
use sphynx::{Uid, UidAllocator};
|
||||
//use specs_idvs::IDVStorage;
|
||||
use self::{ActionState::*, MovementState::*};
|
||||
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;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct RunData;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct StandData;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct SitData;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct JumpData;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct FallData;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct GlideData;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct SwimData;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct ClimbData;
|
||||
pub struct ECSStateData<'a> {
|
||||
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>,
|
||||
}
|
||||
|
||||
pub struct ECSStateUpdate {
|
||||
pub character: CharacterState,
|
||||
pub pos: Pos,
|
||||
pub vel: Vel,
|
||||
pub ori: Ori,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum MovementState {
|
||||
Stand(StandData),
|
||||
Run(RunData),
|
||||
Sit(SitData),
|
||||
Jump(JumpData),
|
||||
Fall(FallData),
|
||||
Glide(GlideData),
|
||||
Swim(SwimData),
|
||||
Climb(ClimbData),
|
||||
pub enum MoveState {
|
||||
Stand(StandHandler),
|
||||
Run(RunHandler),
|
||||
Sit(SitHandler),
|
||||
Jump(JumpHandler),
|
||||
Fall(FallHandler),
|
||||
Glide(GlideHandler),
|
||||
Swim(SwimHandler),
|
||||
Climb(ClimbHandler),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum ActionState {
|
||||
Idle,
|
||||
Wield {
|
||||
time_left: Duration,
|
||||
},
|
||||
Attack {
|
||||
time_left: Duration,
|
||||
applied: bool,
|
||||
},
|
||||
Block {
|
||||
time_active: Duration,
|
||||
},
|
||||
Roll {
|
||||
time_left: Duration,
|
||||
// Whether character was wielding before they started roll
|
||||
was_wielding: bool,
|
||||
},
|
||||
Charge {
|
||||
time_left: Duration,
|
||||
},
|
||||
// Handle(CharacterAction),
|
||||
Wield(WieldHandler),
|
||||
Attack(AttackKind),
|
||||
Block(BlockKind),
|
||||
Dodge(DodgeKind),
|
||||
// Interact,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum AttackKind {
|
||||
BasicAttack(BasicAttackHandler),
|
||||
Charge(ChargeAttackHandler),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum BlockKind {
|
||||
BasicBlock(BasicBlockHandler),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum DodgeKind {
|
||||
Roll(RollHandler),
|
||||
}
|
||||
|
||||
impl ActionState {
|
||||
pub fn is_wield(&self) -> bool {
|
||||
if let Self::Wield { .. } = self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_action_finished(&self) -> bool {
|
||||
pub fn is_equip_finished(&self) -> bool {
|
||||
match self {
|
||||
Self::Wield { time_left }
|
||||
| Self::Attack { time_left, .. }
|
||||
| Self::Roll { time_left, .. }
|
||||
| Self::Charge { time_left } => *time_left == Duration::default(),
|
||||
Self::Idle | Self::Block { .. } => false,
|
||||
Wield(WieldHandler { equip_delay }) => *equip_delay == Duration::default(),
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
pub fn get_delay(&self) -> Duration {
|
||||
match self {
|
||||
Wield(WieldHandler { equip_delay }) => *equip_delay,
|
||||
_ => Duration::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_attack(&self) -> bool {
|
||||
if let Self::Attack { .. } = self {
|
||||
pub fn is_attacking(&self) -> bool {
|
||||
match self {
|
||||
Block(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_blocking(&self) -> bool {
|
||||
match self {
|
||||
Attack(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_dodging(&self) -> bool {
|
||||
match self {
|
||||
Dodge(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_wielding(&self) -> bool {
|
||||
if let Wield(_) = self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_block(&self) -> bool {
|
||||
if let Self::Block { .. } = self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_roll(&self) -> bool {
|
||||
if let Self::Roll { .. } = self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_charge(&self) -> bool {
|
||||
if let Self::Charge { .. } = self {
|
||||
pub fn is_idling(&self) -> bool {
|
||||
if let Idle = self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@ -113,29 +125,29 @@ impl ActionState {
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct CharacterState {
|
||||
pub movement: MovementState,
|
||||
pub action: ActionState,
|
||||
pub move_state: MoveState,
|
||||
pub action_state: ActionState,
|
||||
}
|
||||
|
||||
impl CharacterState {
|
||||
pub fn is_same_movement(&self, other: &Self) -> bool {
|
||||
// Check if enum item is the same without looking at the inner data
|
||||
std::mem::discriminant(&self.movement) == std::mem::discriminant(&other.movement)
|
||||
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)
|
||||
}
|
||||
pub fn is_same_action(&self, other: &Self) -> bool {
|
||||
// Check if enum item is the same without looking at the inner data
|
||||
std::mem::discriminant(&self.action) == std::mem::discriminant(&other.action)
|
||||
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)
|
||||
}
|
||||
pub fn is_same_state(&self, other: &Self) -> bool {
|
||||
self.is_same_movement(other) && self.is_same_action(other)
|
||||
self.is_same_move_state(other) && self.is_same_action_state(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CharacterState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
movement: MovementState::Fall(FallData),
|
||||
action: ActionState::Idle,
|
||||
move_state: MoveState::Fall(FallHandler),
|
||||
action_state: ActionState::Idle,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -143,3 +155,21 @@ impl Default for CharacterState {
|
||||
impl Component for CharacterState {
|
||||
type Storage = FlaggedStorage<Self, HashMapStorage<Self>>;
|
||||
}
|
||||
|
||||
#[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>>;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ mod location;
|
||||
mod phys;
|
||||
mod player;
|
||||
pub mod projectile;
|
||||
mod states;
|
||||
mod stats;
|
||||
mod visual;
|
||||
|
||||
@ -21,8 +22,8 @@ pub use body::{
|
||||
quadruped_medium, quadruped_small, Body,
|
||||
};
|
||||
pub use character_state::{
|
||||
ActionState, CharacterState, ClimbData, FallData, GlideData, JumpData, MovementState, RunData,
|
||||
SitData, StandData, SwimData,
|
||||
ActionState, AttackKind, BlockKind, CharacterState, DodgeKind, ECSStateData, ECSStateUpdate,
|
||||
MoveState, OverrideAction, OverrideMove, OverrideState,
|
||||
};
|
||||
pub use controller::{
|
||||
ControlEvent, Controller, ControllerInputs, Input, InputState, InventoryManip, MountState,
|
||||
@ -35,5 +36,6 @@ pub use location::Waypoint;
|
||||
pub use phys::{ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel};
|
||||
pub use player::Player;
|
||||
pub use projectile::Projectile;
|
||||
pub use states::*;
|
||||
pub use stats::{Equipment, Exp, HealthChange, HealthSource, Level, Stats};
|
||||
pub use visual::LightEmitter;
|
||||
|
19
common/src/comp/states/basic_attack.rs
Normal file
19
common/src/comp/states/basic_attack.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use super::{ECSStateData, ECSStateUpdate, StateHandle};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct BasicAttackHandler {
|
||||
/// How long the state has until exitting
|
||||
remaining_duration: Duration,
|
||||
}
|
||||
|
||||
impl StateHandle for BasicAttackHandler {
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
|
||||
return ECSStateUpdate {
|
||||
pos: *ecs_data.pos,
|
||||
vel: *ecs_data.vel,
|
||||
ori: *ecs_data.ori,
|
||||
character: *ecs_data.character,
|
||||
};
|
||||
}
|
||||
}
|
19
common/src/comp/states/basic_block.rs
Normal file
19
common/src/comp/states/basic_block.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use super::{ECSStateData, ECSStateUpdate, StateHandle};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct BasicBlockHandler {
|
||||
/// How long the blocking state has been active
|
||||
active_duration: Duration,
|
||||
}
|
||||
|
||||
impl StateHandle for BasicBlockHandler {
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
|
||||
return ECSStateUpdate {
|
||||
pos: *ecs_data.pos,
|
||||
vel: *ecs_data.vel,
|
||||
ori: *ecs_data.ori,
|
||||
character: *ecs_data.character,
|
||||
};
|
||||
}
|
||||
}
|
86
common/src/comp/states/charge_attack.rs
Normal file
86
common/src/comp/states/charge_attack.rs
Normal file
@ -0,0 +1,86 @@
|
||||
use super::{
|
||||
CharacterState, ECSStateData, ECSStateUpdate, MoveState::Run, RunHandler, Stand, StandHandler,
|
||||
StateHandle, WieldHandler,
|
||||
};
|
||||
use crate::comp::{
|
||||
ActionState::{Attack, Idle, Wield},
|
||||
AttackKind::Charge,
|
||||
HealthChange, HealthSource,
|
||||
ItemKind::Tool,
|
||||
};
|
||||
use crate::event::ServerEvent;
|
||||
use std::time::Duration;
|
||||
|
||||
use super::TEMP_EQUIP_DELAY;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct ChargeAttackHandler {
|
||||
/// How long the state has until exitting
|
||||
pub remaining_duration: Duration,
|
||||
}
|
||||
|
||||
impl StateHandle for ChargeAttackHandler {
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
|
||||
let mut update = ECSStateUpdate {
|
||||
pos: *ecs_data.pos,
|
||||
vel: *ecs_data.vel,
|
||||
ori: *ecs_data.ori,
|
||||
character: *ecs_data.character,
|
||||
};
|
||||
|
||||
if let Some(uid_b) = ecs_data.physics.touch_entity {
|
||||
ecs_data.server_bus.emitter().emit(ServerEvent::Damage {
|
||||
uid: uid_b,
|
||||
change: HealthChange {
|
||||
amount: -20,
|
||||
cause: HealthSource::Attack { by: *ecs_data.uid },
|
||||
},
|
||||
});
|
||||
|
||||
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
|
||||
},
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
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
|
||||
},
|
||||
};
|
||||
|
||||
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(),
|
||||
})),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
}
|
100
common/src/comp/states/climb.rs
Normal file
100
common/src/comp/states/climb.rs
Normal file
@ -0,0 +1,100 @@
|
||||
use super::{
|
||||
ActionState::*, CharacterState, ECSStateData, ECSStateUpdate, FallHandler, JumpHandler,
|
||||
MoveState::*, StandHandler, StateHandle,
|
||||
};
|
||||
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)]
|
||||
pub struct ClimbHandler;
|
||||
|
||||
impl StateHandle for ClimbHandler {
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> 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
|
||||
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_CLIMB_ACCEL
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
// Set direction based on move direction when on the ground
|
||||
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()
|
||||
} else {
|
||||
Vec2::from(update.vel.0)
|
||||
}
|
||||
} 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(),
|
||||
if ecs_data.physics.on_ground { 9.0 } else { 2.0 } * ecs_data.dt.0,
|
||||
);
|
||||
}
|
||||
|
||||
// Apply Vertical Climbing Movement
|
||||
if let (true, Some(_wall_dir)) = (
|
||||
(ecs_data.inputs.climb.is_pressed() | ecs_data.inputs.climb_down.is_pressed())
|
||||
&& update.vel.0.z <= CLIMB_SPEED,
|
||||
ecs_data.physics.on_wall,
|
||||
) {
|
||||
if ecs_data.inputs.climb_down.is_pressed() && !ecs_data.inputs.climb.is_pressed() {
|
||||
update.vel.0 -=
|
||||
ecs_data.dt.0 * update.vel.0.map(|e| e.abs().powf(1.5) * e.signum() * 6.0);
|
||||
} else if ecs_data.inputs.climb.is_pressed() && !ecs_data.inputs.climb_down.is_pressed()
|
||||
{
|
||||
update.vel.0.z = (update.vel.0.z + ecs_data.dt.0 * GRAVITY * 1.25).min(CLIMB_SPEED);
|
||||
} else {
|
||||
update.vel.0.z = update.vel.0.z + ecs_data.dt.0 * GRAVITY * 1.5;
|
||||
update.vel.0 = Lerp::lerp(
|
||||
update.vel.0,
|
||||
Vec3::zero(),
|
||||
30.0 * ecs_data.dt.0 / (1.0 - update.vel.0.z.min(0.0) * 5.0),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
};
|
||||
return update;
|
||||
} else {
|
||||
update.character = CharacterState {
|
||||
action_state: Idle,
|
||||
move_state: Fall(FallHandler),
|
||||
};
|
||||
return update;
|
||||
}
|
||||
}
|
||||
if ecs_data.physics.on_ground {
|
||||
update.character = CharacterState {
|
||||
action_state: Idle,
|
||||
move_state: Stand(StandHandler),
|
||||
};
|
||||
return update;
|
||||
}
|
||||
|
||||
return update;
|
||||
}
|
||||
}
|
89
common/src/comp/states/fall.rs
Normal file
89
common/src/comp/states/fall.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use super::{
|
||||
ActionState::*, CharacterState, ECSStateData, ECSStateUpdate, GlideHandler, MoveState::*,
|
||||
RunHandler, StandHandler, StateHandle, SwimHandler,
|
||||
};
|
||||
use super::{HUMANOID_AIR_ACCEL, HUMANOID_AIR_SPEED};
|
||||
use vek::{Vec2, Vec3};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct FallHandler;
|
||||
|
||||
impl StateHandle for FallHandler {
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> 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 movement direction vector
|
||||
update.vel.0 += Vec2::broadcast(ecs_data.dt.0)
|
||||
* ecs_data.inputs.move_dir
|
||||
* if update.vel.0.magnitude_squared() < HUMANOID_AIR_SPEED.powf(2.0) {
|
||||
HUMANOID_AIR_ACCEL
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
// Set orientation vector based on direction of movement when on the ground
|
||||
let ori_dir = if update.character.action_state.is_attacking()
|
||||
|| update.character.action_state.is_blocking()
|
||||
{
|
||||
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(), 2.0 * ecs_data.dt.0);
|
||||
}
|
||||
|
||||
// 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),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
// Not on ground, go to swim or fall
|
||||
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),
|
||||
};
|
||||
|
||||
return update;
|
||||
} else {
|
||||
update.character = CharacterState {
|
||||
action_state: update.character.action_state,
|
||||
move_state: Fall(FallHandler),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
}
|
||||
// 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)
|
||||
},
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
}
|
||||
}
|
87
common/src/comp/states/glide.rs
Normal file
87
common/src/comp/states/glide.rs
Normal file
@ -0,0 +1,87 @@
|
||||
use super::{
|
||||
ActionState::*, CharacterState, ClimbHandler, ECSStateData, ECSStateUpdate, FallHandler,
|
||||
MoveState::*, StandHandler, StateHandle,
|
||||
};
|
||||
use super::{GLIDE_ACCEL, GLIDE_ANTIGRAV, GLIDE_SPEED};
|
||||
use vek::{Vec2, Vec3};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct GlideHandler;
|
||||
|
||||
impl StateHandle for GlideHandler {
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> 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 movement direction vector
|
||||
update.vel.0 += Vec2::broadcast(ecs_data.dt.0)
|
||||
* ecs_data.inputs.move_dir
|
||||
* if ecs_data.vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) {
|
||||
GLIDE_ACCEL
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
// Determine orientation vector from movement direction vector
|
||||
let ori_dir = 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(), 2.0 * ecs_data.dt.0);
|
||||
}
|
||||
|
||||
// Apply Glide lift
|
||||
if Vec2::<f32>::from(update.vel.0).magnitude_squared() < GLIDE_SPEED.powf(2.0)
|
||||
&& update.vel.0.z < 0.0
|
||||
{
|
||||
let lift = GLIDE_ANTIGRAV + update.vel.0.z.abs().powf(2.0) * 0.15;
|
||||
update.vel.0.z += ecs_data.dt.0
|
||||
* lift
|
||||
* (Vec2::<f32>::from(update.vel.0).magnitude() * 0.075)
|
||||
.min(1.0)
|
||||
.max(0.2);
|
||||
}
|
||||
|
||||
// If glide button isn't held
|
||||
if !ecs_data.inputs.glide.is_pressed() {
|
||||
update.character = CharacterState {
|
||||
action_state: Idle,
|
||||
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),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
// If on ground go to stand
|
||||
if ecs_data.physics.on_ground {
|
||||
update.character = CharacterState {
|
||||
action_state: Idle,
|
||||
move_state: Stand(StandHandler),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
// Otherwise keep gliding
|
||||
update.character = CharacterState {
|
||||
action_state: Idle,
|
||||
move_state: Glide(GlideHandler),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
}
|
28
common/src/comp/states/jump.rs
Normal file
28
common/src/comp/states/jump.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use super::{CharacterState, ECSStateData, 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 {
|
||||
character: *ecs_data.character,
|
||||
pos: *ecs_data.pos,
|
||||
vel: *ecs_data.vel,
|
||||
ori: *ecs_data.ori,
|
||||
};
|
||||
|
||||
ecs_data
|
||||
.local_bus
|
||||
.emitter()
|
||||
.emit(LocalEvent::Jump(*ecs_data.entity));
|
||||
|
||||
update.character = CharacterState {
|
||||
action_state: ecs_data.character.action_state,
|
||||
move_state: Fall(FallHandler),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
}
|
104
common/src/comp/states/mod.rs
Normal file
104
common/src/comp/states/mod.rs
Normal file
@ -0,0 +1,104 @@
|
||||
// Module declarations
|
||||
mod basic_attack;
|
||||
mod basic_block;
|
||||
mod charge_attack;
|
||||
mod climb;
|
||||
mod fall;
|
||||
mod glide;
|
||||
mod jump;
|
||||
mod roll;
|
||||
mod run;
|
||||
mod sit;
|
||||
mod stand;
|
||||
mod swim;
|
||||
mod wield;
|
||||
|
||||
// Reexports
|
||||
pub use basic_attack::*;
|
||||
pub use basic_block::*;
|
||||
pub use charge_attack::*;
|
||||
pub use climb::*;
|
||||
pub use fall::*;
|
||||
pub use glide::*;
|
||||
pub use jump::*;
|
||||
pub use roll::*;
|
||||
pub use run::*;
|
||||
pub use sit::*;
|
||||
pub use stand::*;
|
||||
pub use swim::*;
|
||||
pub use wield::*;
|
||||
|
||||
// TODO: Attach these to racial components and/or ecs resources
|
||||
pub const HUMANOID_ACCEL: f32 = 50.0;
|
||||
pub const HUMANOID_SPEED: f32 = 120.0;
|
||||
pub const HUMANOID_AIR_ACCEL: f32 = 10.0;
|
||||
pub const HUMANOID_AIR_SPEED: f32 = 100.0;
|
||||
pub const HUMANOID_WATER_ACCEL: f32 = 70.0;
|
||||
pub const HUMANOID_WATER_SPEED: f32 = 120.0;
|
||||
pub const HUMANOID_CLIMB_ACCEL: f32 = 5.0;
|
||||
pub const ROLL_SPEED: f32 = 17.0;
|
||||
pub const CHARGE_SPEED: f32 = 20.0;
|
||||
pub const GLIDE_ACCEL: f32 = 15.0;
|
||||
pub const GLIDE_SPEED: f32 = 45.0;
|
||||
pub const BLOCK_ACCEL: f32 = 30.0;
|
||||
pub const BLOCK_SPEED: f32 = 75.0;
|
||||
pub const TEMP_EQUIP_DELAY: u64 = 100;
|
||||
// Gravity is 9.81 * 4, so this makes gravity equal to .15
|
||||
pub const GLIDE_ANTIGRAV: f32 = crate::sys::phys::GRAVITY * 0.96;
|
||||
pub const CLIMB_SPEED: f32 = 5.0;
|
||||
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::*,
|
||||
};
|
||||
|
||||
pub trait StateHandle {
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate;
|
||||
}
|
||||
|
||||
impl StateHandle for ActionState {
|
||||
/// Passes handle to variant or subvariant handlers
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
|
||||
match self {
|
||||
Attack(kind) => match kind {
|
||||
BasicAttack(handler) => handler.handle(ecs_data),
|
||||
Charge(handler) => handler.handle(ecs_data),
|
||||
},
|
||||
Block(kind) => match kind {
|
||||
BasicBlock(handler) => handler.handle(ecs_data),
|
||||
},
|
||||
Dodge(kind) => match kind {
|
||||
Roll(handler) => handler.handle(ecs_data),
|
||||
},
|
||||
Wield(handler) => handler.handle(ecs_data),
|
||||
Idle => ECSStateUpdate {
|
||||
character: *ecs_data.character,
|
||||
pos: *ecs_data.pos,
|
||||
vel: *ecs_data.vel,
|
||||
ori: *ecs_data.ori,
|
||||
},
|
||||
// All states should be explicitly handled
|
||||
// Do not use default match: _ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StateHandle for MoveState {
|
||||
/// Passes handle to variant handlers
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
|
||||
match self {
|
||||
Stand(handler) => handler.handle(&ecs_data),
|
||||
Run(handler) => handler.handle(&ecs_data),
|
||||
Jump(handler) => handler.handle(&ecs_data),
|
||||
Climb(handler) => handler.handle(&ecs_data),
|
||||
Glide(handler) => handler.handle(&ecs_data),
|
||||
Swim(handler) => handler.handle(&ecs_data),
|
||||
Fall(handler) => handler.handle(&ecs_data),
|
||||
Sit(handler) => handler.handle(&ecs_data),
|
||||
// All states should be explicitly handled
|
||||
// Do not use default match: _ => {},
|
||||
}
|
||||
}
|
||||
}
|
19
common/src/comp/states/roll.rs
Normal file
19
common/src/comp/states/roll.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use super::{ECSStateData, ECSStateUpdate, StateHandle};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct RollHandler {
|
||||
/// How long the state has until exitting
|
||||
remaining_duration: Duration,
|
||||
}
|
||||
|
||||
impl StateHandle for RollHandler {
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
|
||||
ECSStateUpdate {
|
||||
character: *ecs_data.character,
|
||||
pos: *ecs_data.pos,
|
||||
vel: *ecs_data.vel,
|
||||
ori: *ecs_data.ori,
|
||||
}
|
||||
}
|
||||
}
|
139
common/src/comp/states/run.rs
Normal file
139
common/src/comp/states/run.rs
Normal file
@ -0,0 +1,139 @@
|
||||
use super::{
|
||||
ActionState::*, CharacterState, ClimbHandler, ECSStateData, ECSStateUpdate, FallHandler,
|
||||
GlideHandler, JumpHandler, MoveState::*, SitHandler, StandHandler, StateHandle, SwimHandler,
|
||||
};
|
||||
use super::{HUMANOID_ACCEL, HUMANOID_SPEED};
|
||||
use vek::vec::{Vec2, Vec3};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct RunHandler;
|
||||
|
||||
impl StateHandle for RunHandler {
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
|
||||
let mut update = ECSStateUpdate {
|
||||
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 update.character.action_state.is_attacking()
|
||||
|| update.character.action_state.is_blocking()
|
||||
{
|
||||
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 ecs_data.inputs.sit.is_pressed()
|
||||
&& ecs_data.physics.on_ground
|
||||
&& ecs_data.body.is_humanoid()
|
||||
{
|
||||
update.character = CharacterState {
|
||||
action_state: Idle,
|
||||
move_state: Sit(SitHandler),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
// Try to climb
|
||||
if let (true, Some(_wall_dir)) = (
|
||||
ecs_data.inputs.climb.is_pressed() | ecs_data.inputs.climb_down.is_pressed()
|
||||
&& ecs_data.body.is_humanoid(),
|
||||
ecs_data.physics.on_wall,
|
||||
) {
|
||||
update.character = CharacterState {
|
||||
action_state: Idle,
|
||||
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),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
// While on ground ...
|
||||
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),
|
||||
};
|
||||
|
||||
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 {
|
||||
// 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),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
update.character = CharacterState {
|
||||
action_state: ecs_data.character.action_state,
|
||||
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),
|
||||
};
|
||||
|
||||
return update;
|
||||
} else {
|
||||
update.character = CharacterState {
|
||||
action_state: ecs_data.character.action_state,
|
||||
move_state: Stand(StandHandler),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
}
|
||||
}
|
76
common/src/comp/states/sit.rs
Normal file
76
common/src/comp/states/sit.rs
Normal file
@ -0,0 +1,76 @@
|
||||
use super::{
|
||||
ActionState::*, CharacterState, ECSStateData, 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 {
|
||||
character: *ecs_data.character,
|
||||
pos: *ecs_data.pos,
|
||||
vel: *ecs_data.vel,
|
||||
ori: *ecs_data.ori,
|
||||
};
|
||||
|
||||
// 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),
|
||||
};
|
||||
|
||||
return update;
|
||||
} else {
|
||||
update.character = CharacterState {
|
||||
action_state: Idle,
|
||||
move_state: Fall(FallHandler),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
}
|
||||
// Jumping
|
||||
if ecs_data.inputs.jump.is_pressed() {
|
||||
update.character = CharacterState {
|
||||
action_state: Idle,
|
||||
move_state: Jump(JumpHandler),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
// Moving
|
||||
if ecs_data.inputs.move_dir.magnitude_squared() > 0.0 {
|
||||
update.character = CharacterState {
|
||||
action_state: Idle,
|
||||
move_state: Run(RunHandler),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
// Standing back up (unsitting)
|
||||
if ecs_data.inputs.sit.is_just_pressed() {
|
||||
update.character = CharacterState {
|
||||
action_state: Idle,
|
||||
move_state: Stand(StandHandler),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
// no move_state has occurred
|
||||
update.character = CharacterState {
|
||||
action_state: Idle,
|
||||
move_state: Sit(SitHandler),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
}
|
120
common/src/comp/states/stand.rs
Normal file
120
common/src/comp/states/stand.rs
Normal file
@ -0,0 +1,120 @@
|
||||
use super::{
|
||||
ActionState::*, CharacterState, ClimbHandler, ECSStateData, 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 {
|
||||
character: *ecs_data.character,
|
||||
pos: *ecs_data.pos,
|
||||
vel: *ecs_data.vel,
|
||||
ori: *ecs_data.ori,
|
||||
};
|
||||
|
||||
// Try to sit
|
||||
if ecs_data.inputs.sit.is_pressed()
|
||||
&& ecs_data.physics.on_ground
|
||||
&& ecs_data.body.is_humanoid()
|
||||
{
|
||||
update.character = CharacterState {
|
||||
move_state: Sit(SitHandler),
|
||||
action_state: update.character.action_state,
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
// Try to climb
|
||||
if let (true, Some(_wall_dir)) = (
|
||||
ecs_data.inputs.climb.is_pressed() | ecs_data.inputs.climb_down.is_pressed()
|
||||
&& ecs_data.body.is_humanoid(),
|
||||
ecs_data.physics.on_wall,
|
||||
) {
|
||||
update.character = CharacterState {
|
||||
action_state: update.character.action_state,
|
||||
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),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
// While on ground ...
|
||||
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),
|
||||
};
|
||||
|
||||
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),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
update.character = CharacterState {
|
||||
action_state: update.character.action_state,
|
||||
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),
|
||||
};
|
||||
|
||||
return update;
|
||||
} else {
|
||||
update.character = CharacterState {
|
||||
action_state: update.character.action_state,
|
||||
move_state: Stand(StandHandler),
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
}
|
||||
}
|
85
common/src/comp/states/swim.rs
Normal file
85
common/src/comp/states/swim.rs
Normal file
@ -0,0 +1,85 @@
|
||||
use super::{
|
||||
CharacterState, ECSStateData, ECSStateUpdate, MoveState::*, RunHandler, StandHandler,
|
||||
StateHandle,
|
||||
};
|
||||
use super::{HUMANOID_WATER_ACCEL, HUMANOID_WATER_SPEED};
|
||||
use crate::sys::phys::GRAVITY;
|
||||
use vek::{Vec2, Vec3};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct SwimHandler;
|
||||
|
||||
impl StateHandle for SwimHandler {
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> ECSStateUpdate {
|
||||
let mut update = ECSStateUpdate {
|
||||
character: *ecs_data.character,
|
||||
pos: *ecs_data.pos,
|
||||
vel: *ecs_data.vel,
|
||||
ori: *ecs_data.ori,
|
||||
};
|
||||
|
||||
// Update velocity
|
||||
update.vel.0 += Vec2::broadcast(ecs_data.dt.0)
|
||||
* ecs_data.inputs.move_dir
|
||||
* if update.vel.0.magnitude_squared() < HUMANOID_WATER_SPEED.powf(2.0) {
|
||||
HUMANOID_WATER_ACCEL
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
// Set direction based on move direction when on the ground
|
||||
let ori_dir = if update.character.action_state.is_attacking()
|
||||
|| update.character.action_state.is_blocking()
|
||||
{
|
||||
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(),
|
||||
if ecs_data.physics.on_ground { 9.0 } else { 2.0 } * ecs_data.dt.0,
|
||||
);
|
||||
}
|
||||
|
||||
if ecs_data.inputs.jump.is_pressed() {
|
||||
update.vel.0.z =
|
||||
(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),
|
||||
};
|
||||
|
||||
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)
|
||||
},
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
}
|
||||
}
|
51
common/src/comp/states/wield.rs
Normal file
51
common/src/comp/states/wield.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use super::{ActionState::*, CharacterState, ECSStateData, ECSStateUpdate, StateHandle};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub struct WieldHandler {
|
||||
/// How long before a new action can be performed
|
||||
/// after equipping
|
||||
pub equip_delay: Duration,
|
||||
}
|
||||
|
||||
impl StateHandle for WieldHandler {
|
||||
fn handle(&self, ecs_data: &ECSStateData) -> 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,
|
||||
};
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
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: 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;
|
||||
}
|
||||
}
|
@ -33,6 +33,9 @@ sphynx::sum_type! {
|
||||
Projectile(comp::Projectile),
|
||||
Gravity(comp::Gravity),
|
||||
Sticky(comp::Sticky),
|
||||
OverrideAction(comp::OverrideAction),
|
||||
OverrideMove(comp::OverrideMove),
|
||||
OverrideState(comp::OverrideState),
|
||||
}
|
||||
}
|
||||
// Automatically derive From<T> for EcsCompPhantom
|
||||
@ -56,6 +59,9 @@ sphynx::sum_type! {
|
||||
Projectile(PhantomData<comp::Projectile>),
|
||||
Gravity(PhantomData<comp::Gravity>),
|
||||
Sticky(PhantomData<comp::Sticky>),
|
||||
OverrideAction(PhantomData<comp::OverrideAction>),
|
||||
OverrideMove(PhantomData<comp::OverrideMove>),
|
||||
OverrideState(PhantomData<comp::OverrideState>),
|
||||
}
|
||||
}
|
||||
impl sphynx::CompPacket for EcsCompPacket {
|
||||
|
@ -136,6 +136,9 @@ impl State {
|
||||
ecs.register_synced::<comp::Sticky>();
|
||||
ecs.register_synced::<comp::Gravity>();
|
||||
ecs.register_synced::<comp::Projectile>();
|
||||
ecs.register_synced::<comp::OverrideAction>();
|
||||
ecs.register_synced::<comp::OverrideMove>();
|
||||
ecs.register_synced::<comp::OverrideState>();
|
||||
|
||||
// Register components send from clients -> server
|
||||
ecs.register::<comp::Controller>();
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::comp::{
|
||||
Agent, CharacterState, Controller, ControllerInputs, GlideData, MountState,
|
||||
MovementState::Glide, Pos, Stats,
|
||||
Agent, CharacterState, Controller, ControllerInputs, GlideHandler, MountState,
|
||||
MoveState::Glide, Pos, SitHandler, Stats,
|
||||
};
|
||||
use crate::pathfinding::WorldPath;
|
||||
use crate::terrain::TerrainGrid;
|
||||
@ -163,7 +163,7 @@ impl<'a> System<'a> for Sys {
|
||||
inputs.roll.set_state(true);
|
||||
}
|
||||
|
||||
if target_character.movement == Glide(GlideData)
|
||||
if target_character.move_state == Glide(GlideHandler)
|
||||
&& target_pos.0.z > pos.0.z + 5.0
|
||||
{
|
||||
inputs.glide.set_state(true);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -46,119 +46,119 @@ impl<'a> System<'a> for Sys {
|
||||
stats,
|
||||
): Self::SystemData,
|
||||
) {
|
||||
let mut server_emitter = server_bus.emitter();
|
||||
let mut _local_emitter = local_bus.emitter();
|
||||
// let mut server_emitter = server_bus.emitter();
|
||||
// let mut _local_emitter = local_bus.emitter();
|
||||
|
||||
// Attacks
|
||||
for (entity, uid, pos, ori, _, stat) in (
|
||||
&entities,
|
||||
&uids,
|
||||
&positions,
|
||||
&orientations,
|
||||
&controllers,
|
||||
&stats,
|
||||
)
|
||||
.join()
|
||||
{
|
||||
let recover_duration = if let Some(Item {
|
||||
kind: ItemKind::Tool { kind, .. },
|
||||
..
|
||||
}) = stat.equipment.main
|
||||
{
|
||||
kind.attack_recover_duration()
|
||||
} else {
|
||||
Duration::from_secs(1)
|
||||
};
|
||||
// // Attacks
|
||||
// for (entity, uid, pos, ori, _, stat) in (
|
||||
// &entities,
|
||||
// &uids,
|
||||
// &positions,
|
||||
// &orientations,
|
||||
// &controllers,
|
||||
// &stats,
|
||||
// )
|
||||
// .join()
|
||||
// {
|
||||
// let recover_duration = if let Some(Item {
|
||||
// kind: ItemKind::Tool { kind, .. },
|
||||
// ..
|
||||
// }) = stat.equipment.main
|
||||
// {
|
||||
// kind.attack_recover_duration()
|
||||
// } else {
|
||||
// Duration::from_secs(1)
|
||||
// };
|
||||
|
||||
let (deal_damage, should_end) = if let Some(Attack { time_left, applied }) =
|
||||
&mut character_states.get_mut(entity).map(|c| &mut c.action)
|
||||
{
|
||||
*time_left = time_left
|
||||
.checked_sub(Duration::from_secs_f32(dt.0))
|
||||
.unwrap_or_default();
|
||||
if !*applied && recover_duration > *time_left {
|
||||
*applied = true;
|
||||
(true, false)
|
||||
} else if *time_left == Duration::default() {
|
||||
(false, true)
|
||||
} else {
|
||||
(false, false)
|
||||
}
|
||||
} else {
|
||||
(false, false)
|
||||
};
|
||||
// let (deal_damage, should_end) = if let Some(Attack { time_left, applied }) =
|
||||
// &mut character_states.get_mut(entity).map(|c| &mut c.action)
|
||||
// {
|
||||
// *time_left = time_left
|
||||
// .checked_sub(Duration::from_secs_f32(dt.0))
|
||||
// .unwrap_or_default();
|
||||
// if !*applied && recover_duration > *time_left {
|
||||
// *applied = true;
|
||||
// (true, false)
|
||||
// } else if *time_left == Duration::default() {
|
||||
// (false, true)
|
||||
// } else {
|
||||
// (false, false)
|
||||
// }
|
||||
// } else {
|
||||
// (false, false)
|
||||
// };
|
||||
|
||||
if deal_damage {
|
||||
if let Some(Attack { .. }) = &character_states.get(entity).map(|c| c.action) {
|
||||
// Go through all other entities
|
||||
for (b, uid_b, pos_b, ori_b, character_b, stat_b) in (
|
||||
&entities,
|
||||
&uids,
|
||||
&positions,
|
||||
&orientations,
|
||||
&character_states,
|
||||
&stats,
|
||||
)
|
||||
.join()
|
||||
{
|
||||
// 2D versions
|
||||
let pos2 = Vec2::from(pos.0);
|
||||
let pos_b2: Vec2<f32> = Vec2::from(pos_b.0);
|
||||
let ori2 = Vec2::from(ori.0);
|
||||
// if deal_damage {
|
||||
// if let Some(Attack { .. }) = &character_states.get(entity).map(|c| c.action) {
|
||||
// // Go through all other entities
|
||||
// for (b, uid_b, pos_b, ori_b, character_b, stat_b) in (
|
||||
// &entities,
|
||||
// &uids,
|
||||
// &positions,
|
||||
// &orientations,
|
||||
// &character_states,
|
||||
// &stats,
|
||||
// )
|
||||
// .join()
|
||||
// {
|
||||
// // 2D versions
|
||||
// let pos2 = Vec2::from(pos.0);
|
||||
// let pos_b2: Vec2<f32> = Vec2::from(pos_b.0);
|
||||
// let ori2 = Vec2::from(ori.0);
|
||||
|
||||
// Check if it is a hit
|
||||
if entity != b
|
||||
&& !stat_b.is_dead
|
||||
&& pos.0.distance_squared(pos_b.0) < ATTACK_RANGE.powi(2)
|
||||
// TODO: Use size instead of 1.0
|
||||
&& ori2.angle_between(pos_b2 - pos2) < (2.0 / pos2.distance(pos_b2)).atan()
|
||||
{
|
||||
// Weapon gives base damage
|
||||
let mut dmg = if let Some(ItemKind::Tool { power, .. }) =
|
||||
stat.equipment.main.as_ref().map(|i| &i.kind)
|
||||
{
|
||||
*power as i32
|
||||
} else {
|
||||
1
|
||||
};
|
||||
// // Check if it is a hit
|
||||
// if entity != b
|
||||
// && !stat_b.is_dead
|
||||
// && pos.0.distance_squared(pos_b.0) < ATTACK_RANGE.powi(2)
|
||||
// // TODO: Use size instead of 1.0
|
||||
// && ori2.angle_between(pos_b2 - pos2) < (2.0 / pos2.distance(pos_b2)).atan()
|
||||
// {
|
||||
// // Weapon gives base damage
|
||||
// let mut dmg = if let Some(ItemKind::Tool { power, .. }) =
|
||||
// stat.equipment.main.as_ref().map(|i| &i.kind)
|
||||
// {
|
||||
// *power as i32
|
||||
// } else {
|
||||
// 1
|
||||
// };
|
||||
|
||||
// Block
|
||||
if character_b.action.is_block()
|
||||
&& ori_b.0.angle_between(pos.0 - pos_b.0).to_degrees()
|
||||
< BLOCK_ANGLE / 2.0
|
||||
{
|
||||
dmg = (dmg as f32 * (1.0 - BLOCK_EFFICIENCY)) as i32
|
||||
}
|
||||
// // Block
|
||||
// if character_b.action.is_block()
|
||||
// && ori_b.0.angle_between(pos.0 - pos_b.0).to_degrees()
|
||||
// < BLOCK_ANGLE / 2.0
|
||||
// {
|
||||
// dmg = (dmg as f32 * (1.0 - BLOCK_EFFICIENCY)) as i32
|
||||
// }
|
||||
|
||||
server_emitter.emit(ServerEvent::Damage {
|
||||
uid: *uid_b,
|
||||
change: HealthChange {
|
||||
amount: -dmg,
|
||||
cause: HealthSource::Attack { by: *uid },
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// server_emitter.emit(ServerEvent::Damage {
|
||||
// uid: *uid_b,
|
||||
// change: HealthChange {
|
||||
// amount: -dmg,
|
||||
// cause: HealthSource::Attack { by: *uid },
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if should_end {
|
||||
if let Some(character) = &mut character_states.get_mut(entity) {
|
||||
character.action = Wield {
|
||||
time_left: Duration::default(),
|
||||
};
|
||||
}
|
||||
}
|
||||
// if should_end {
|
||||
// if let Some(character) = &mut character_states.get_mut(entity) {
|
||||
// character.action = Wield {
|
||||
// time_left: Duration::default(),
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
if let Some(Wield { time_left }) =
|
||||
&mut character_states.get_mut(entity).map(|c| &mut c.action)
|
||||
{
|
||||
if *time_left != Duration::default() {
|
||||
*time_left = time_left
|
||||
.checked_sub(Duration::from_secs_f32(dt.0))
|
||||
.unwrap_or_default();
|
||||
}
|
||||
}
|
||||
}
|
||||
// if let Some(Wield { time_left }) =
|
||||
// &mut character_states.get_mut(entity).map(|c| &mut c.action)
|
||||
// {
|
||||
// if *time_left != Duration::default() {
|
||||
// *time_left = time_left
|
||||
// .checked_sub(Duration::from_secs_f32(dt.0))
|
||||
// .unwrap_or_default();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,13 @@
|
||||
use super::movement::ROLL_DURATION;
|
||||
use crate::{
|
||||
comp::{
|
||||
self, item, projectile, ActionState, ActionState::*, Body, CharacterState, ControlEvent,
|
||||
Controller, ControllerInputs, HealthChange, HealthSource, ItemKind, Mounting,
|
||||
MovementState, MovementState::*, PhysicsState, Projectile, Stats, Vel,
|
||||
},
|
||||
event::{Emitter, EventBus, LocalEvent, ServerEvent},
|
||||
comp::{ControlEvent, Controller},
|
||||
event::{EventBus, LocalEvent, ServerEvent},
|
||||
state::DeltaTime,
|
||||
};
|
||||
use specs::{
|
||||
saveload::{Marker, MarkerAllocator},
|
||||
Entities, Entity, Join, Read, ReadStorage, System, WriteStorage,
|
||||
Entities, Join, Read, ReadStorage, System, WriteStorage,
|
||||
};
|
||||
use sphynx::{Uid, UidAllocator};
|
||||
use std::time::Duration;
|
||||
use vek::*;
|
||||
|
||||
/// # Controller System
|
||||
/// #### Responsible for validating and updating controller inputs
|
||||
|
@ -3,7 +3,6 @@ pub mod character_state;
|
||||
mod cleanup;
|
||||
pub mod combat;
|
||||
pub mod controller;
|
||||
pub mod movement;
|
||||
pub mod phys;
|
||||
mod projectile;
|
||||
mod stats;
|
||||
@ -16,7 +15,6 @@ const AGENT_SYS: &str = "agent_sys";
|
||||
const CHARACTER_STATE_SYS: &str = "character_state_sys";
|
||||
const CONTROLLER_SYS: &str = "controller_sys";
|
||||
const PHYS_SYS: &str = "phys_sys";
|
||||
const MOVEMENT_SYS: &str = "movement_sys";
|
||||
const PROJECTILE_SYS: &str = "projectile_sys";
|
||||
const COMBAT_SYS: &str = "combat_sys";
|
||||
const STATS_SYS: &str = "stats_sys";
|
||||
@ -26,13 +24,12 @@ pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
|
||||
dispatch_builder.add(agent::Sys, AGENT_SYS, &[]);
|
||||
dispatch_builder.add(controller::Sys, CONTROLLER_SYS, &[AGENT_SYS]);
|
||||
dispatch_builder.add(character_state::Sys, CHARACTER_STATE_SYS, &[CONTROLLER_SYS]);
|
||||
dispatch_builder.add(movement::Sys, MOVEMENT_SYS, &[CHARACTER_STATE_SYS]);
|
||||
dispatch_builder.add(combat::Sys, COMBAT_SYS, &[CONTROLLER_SYS]);
|
||||
dispatch_builder.add(stats::Sys, STATS_SYS, &[COMBAT_SYS]);
|
||||
dispatch_builder.add(
|
||||
phys::Sys,
|
||||
PHYS_SYS,
|
||||
&[CONTROLLER_SYS, MOVEMENT_SYS, COMBAT_SYS, STATS_SYS],
|
||||
&[CONTROLLER_SYS, COMBAT_SYS, STATS_SYS],
|
||||
);
|
||||
dispatch_builder.add(projectile::Sys, PROJECTILE_SYS, &[PHYS_SYS]);
|
||||
dispatch_builder.add(cleanup::Sys, CLEANUP_SYS, &[PHYS_SYS]);
|
||||
|
@ -1,8 +1,8 @@
|
||||
use super::phys::GRAVITY;
|
||||
use crate::{
|
||||
comp::{
|
||||
CharacterState, Controller, Mounting, MovementState::*, Ori, PhysicsState, Pos, RunData,
|
||||
StandData, Stats, Vel,
|
||||
CharacterState, Controller, Mounting, MoveState::*, Ori, PhysicsState, Pos, RunHandler,
|
||||
StandHandler, Stats, Vel,
|
||||
},
|
||||
event::{EventBus, ServerEvent},
|
||||
state::DeltaTime,
|
||||
@ -106,7 +106,7 @@ impl<'a> System<'a> for Sys {
|
||||
)
|
||||
.join()
|
||||
{
|
||||
// if character.movement == Run(RunData) || character.movement == Stand(StandData) {
|
||||
// if character.movement == Run(RunHandler) || character.movement == Stand(StandHandler) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
|
@ -4,7 +4,11 @@ use crate::audio::sfx::{SfxTriggerItem, SfxTriggers};
|
||||
|
||||
use client::Client;
|
||||
use common::{
|
||||
comp::{ActionState, Body, CharacterState, ItemKind, MovementState, Pos, Stats},
|
||||
comp::{
|
||||
ActionState, AttackKind::*, BasicAttackHandler, Body, CharacterState, DodgeKind::*,
|
||||
FallHandler, GlideHandler, ItemKind, MoveState, Pos, RollHandler, RunHandler, StandHandler,
|
||||
Stats,
|
||||
},
|
||||
event::{EventBus, SfxEvent, SfxEventItem},
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
@ -125,7 +129,7 @@ impl SfxEventMapper {
|
||||
}
|
||||
}
|
||||
|
||||
/// Voxygen has an existing list of character states via `MovementState::*` and `ActionState::*`
|
||||
/// Voxygen has an existing list of character states via `MoveState::*` and `ActionState::*`
|
||||
/// however that list does not provide enough resolution to target specific entity events, such
|
||||
/// 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
|
||||
@ -135,8 +139,8 @@ impl SfxEventMapper {
|
||||
stats: &Stats,
|
||||
) -> SfxEvent {
|
||||
match (
|
||||
current_event.movement,
|
||||
current_event.action,
|
||||
current_event.move_state,
|
||||
current_event.action_state,
|
||||
previous_event,
|
||||
stats,
|
||||
) {
|
||||
@ -154,23 +158,23 @@ impl SfxEventMapper {
|
||||
stats: &Stats,
|
||||
) -> SfxEvent {
|
||||
match (
|
||||
current_event.movement,
|
||||
current_event.action,
|
||||
current_event.move_state,
|
||||
current_event.action_state,
|
||||
previous_event,
|
||||
stats,
|
||||
) {
|
||||
(_, ActionState::Roll { .. }, ..) => SfxEvent::Roll,
|
||||
(MovementState::Climb(_), ..) => SfxEvent::Climb,
|
||||
(MovementState::Swim(_), ..) => SfxEvent::Swim,
|
||||
(MovementState::Run(_), ..) => SfxEvent::Run,
|
||||
(MovementState::Fall(_), _, previous_event, _) => {
|
||||
(_, ActionState::Dodge(_), ..) => SfxEvent::Roll,
|
||||
(MoveState::Climb(_), ..) => SfxEvent::Climb,
|
||||
(MoveState::Swim(_), ..) => SfxEvent::Swim,
|
||||
(MoveState::Run(_), ..) => SfxEvent::Run,
|
||||
(MoveState::Fall(_), _, previous_event, _) => {
|
||||
if previous_event != SfxEvent::Glide {
|
||||
SfxEvent::Fall
|
||||
} else {
|
||||
SfxEvent::GliderClose
|
||||
}
|
||||
}
|
||||
(MovementState::Glide(_), _, previous_event, ..) => {
|
||||
(MoveState::Glide(_), _, previous_event, ..) => {
|
||||
if previous_event != SfxEvent::GliderOpen && previous_event != SfxEvent::Glide {
|
||||
SfxEvent::GliderOpen
|
||||
} else {
|
||||
@ -193,7 +197,7 @@ mod tests {
|
||||
use super::*;
|
||||
use common::{
|
||||
assets,
|
||||
comp::{item::Tool, ActionState, MovementState, Stats},
|
||||
comp::{item::Tool, ActionState, MoveState, Stats},
|
||||
event::SfxEvent,
|
||||
};
|
||||
use std::time::{Duration, Instant};
|
||||
@ -273,8 +277,8 @@ mod tests {
|
||||
|
||||
let result = SfxEventMapper::map_character_event(
|
||||
&CharacterState {
|
||||
movement: MovementState::Stand,
|
||||
action: ActionState::Idle,
|
||||
move_state: MoveState::Stand(StandHandler),
|
||||
action_state: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Idle,
|
||||
&stats,
|
||||
@ -289,8 +293,8 @@ mod tests {
|
||||
|
||||
let result = SfxEventMapper::map_character_event(
|
||||
&CharacterState {
|
||||
movement: MovementState::Run,
|
||||
action: ActionState::Idle,
|
||||
move_state: MoveState::Run(RunHandler),
|
||||
action_state: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Idle,
|
||||
&stats,
|
||||
@ -305,11 +309,8 @@ mod tests {
|
||||
|
||||
let result = SfxEventMapper::map_character_event(
|
||||
&CharacterState {
|
||||
action: ActionState::Roll {
|
||||
time_left: Duration::new(1, 0),
|
||||
was_wielding: false,
|
||||
},
|
||||
movement: MovementState::Run,
|
||||
action_state: ActionState::Dodge(Roll(RollHandler::default())),
|
||||
move_state: MoveState::Run(RunHandler),
|
||||
},
|
||||
SfxEvent::Run,
|
||||
&stats,
|
||||
@ -324,8 +325,8 @@ mod tests {
|
||||
|
||||
let result = SfxEventMapper::map_character_event(
|
||||
&CharacterState {
|
||||
movement: MovementState::Fall,
|
||||
action: ActionState::Idle,
|
||||
move_state: MoveState::Fall(FallHandler),
|
||||
action_state: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Idle,
|
||||
&stats,
|
||||
@ -340,8 +341,8 @@ mod tests {
|
||||
|
||||
let result = SfxEventMapper::map_character_event(
|
||||
&CharacterState {
|
||||
movement: MovementState::Glide,
|
||||
action: ActionState::Idle,
|
||||
move_state: MoveState::Glide(GlideHandler),
|
||||
action_state: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Jump,
|
||||
&stats,
|
||||
@ -356,8 +357,8 @@ mod tests {
|
||||
|
||||
let result = SfxEventMapper::map_character_event(
|
||||
&CharacterState {
|
||||
movement: MovementState::Glide,
|
||||
action: ActionState::Idle,
|
||||
move_state: MoveState::Glide(GlideHandler),
|
||||
action_state: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Glide,
|
||||
&stats,
|
||||
@ -372,8 +373,8 @@ mod tests {
|
||||
|
||||
let result = SfxEventMapper::map_character_event(
|
||||
&CharacterState {
|
||||
movement: MovementState::Fall,
|
||||
action: ActionState::Idle,
|
||||
move_state: MoveState::Fall(FallHandler),
|
||||
action_state: ActionState::Idle,
|
||||
},
|
||||
SfxEvent::Glide,
|
||||
&stats,
|
||||
@ -393,11 +394,8 @@ mod tests {
|
||||
|
||||
let result = SfxEventMapper::map_character_event(
|
||||
&CharacterState {
|
||||
movement: MovementState::Stand,
|
||||
action: ActionState::Attack {
|
||||
time_left: Duration::new(1, 0),
|
||||
applied: true,
|
||||
},
|
||||
move_state: MoveState::Stand(StandHandler),
|
||||
action_state: ActionState::Attack(BasicAttack(BasicAttackHandler::default())),
|
||||
},
|
||||
SfxEvent::Idle,
|
||||
&stats,
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
};
|
||||
use common::{
|
||||
assets::watch::ReloadIndicator,
|
||||
comp::{ActionState, Body, CharacterState, Equipment, MovementState},
|
||||
comp::{ActionState, Body, CharacterState, Equipment, MoveState},
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use std::mem::{discriminant, Discriminant};
|
||||
@ -24,15 +24,15 @@ enum FigureKey {
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
struct CharacterStateCacheKey {
|
||||
movement: Discriminant<MovementState>,
|
||||
move_state: Discriminant<MoveState>,
|
||||
action: Discriminant<ActionState>,
|
||||
}
|
||||
|
||||
impl From<&CharacterState> for CharacterStateCacheKey {
|
||||
fn from(cs: &CharacterState) -> Self {
|
||||
Self {
|
||||
movement: discriminant(&cs.movement),
|
||||
action: discriminant(&cs.action),
|
||||
move_state: discriminant(&cs.move_state),
|
||||
action: discriminant(&cs.action_state),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,7 +132,7 @@ impl FigureModelCache {
|
||||
},
|
||||
if camera_mode == CameraMode::FirstPerson
|
||||
&& character_state
|
||||
.map(|cs| cs.action.is_roll())
|
||||
.map(|cs| cs.action_state.is_dodging())
|
||||
.unwrap_or_default()
|
||||
{
|
||||
None
|
||||
@ -140,7 +140,7 @@ impl FigureModelCache {
|
||||
Some(humanoid_armor_hand_spec.mesh_left_hand(&body))
|
||||
},
|
||||
if character_state
|
||||
.map(|cs| cs.action.is_roll())
|
||||
.map(|cs| cs.action_state.is_dodging())
|
||||
.unwrap_or_default()
|
||||
{
|
||||
None
|
||||
@ -162,9 +162,9 @@ impl FigureModelCache {
|
||||
if camera_mode != CameraMode::FirstPerson
|
||||
|| character_state
|
||||
.map(|cs| {
|
||||
cs.action.is_attack()
|
||||
|| cs.action.is_block()
|
||||
|| cs.action.is_wield()
|
||||
cs.action_state.is_attacking()
|
||||
|| cs.action_state.is_blocking()
|
||||
|| cs.action_state.is_wielding()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
{
|
||||
|
@ -18,8 +18,8 @@ use crate::{
|
||||
use client::Client;
|
||||
use common::{
|
||||
comp::{
|
||||
ActionState::*, Body, CharacterState, ItemKind, Last, MovementState::*, Ori, Pos, Scale,
|
||||
Stats, Vel,
|
||||
ActionState::*, AttackKind::*, Body, CharacterState, ItemKind, Last, MoveState::*, Ori,
|
||||
Pos, Scale, Stats, Vel,
|
||||
},
|
||||
terrain::TerrainChunk,
|
||||
vol::RectRasterableVol,
|
||||
@ -160,7 +160,7 @@ impl FigureMgr {
|
||||
)
|
||||
.1;
|
||||
|
||||
let mut movement_animation_rate = 1.0;
|
||||
let mut move_state_animation_rate = 1.0;
|
||||
let mut action_animation_rate = 1.0;
|
||||
|
||||
let vel = ecs
|
||||
@ -189,65 +189,65 @@ impl FigureMgr {
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if !character.is_same_movement(&last_character.0) {
|
||||
state.movement_time = 0.0;
|
||||
if !character.is_same_move_state(&last_character.0) {
|
||||
state.move_state_time = 0.0;
|
||||
}
|
||||
if !character.is_same_action(&last_character.0) {
|
||||
if !character.is_same_action_state(&last_character.0) {
|
||||
state.action_time = 0.0;
|
||||
}
|
||||
|
||||
let target_base = match &character.movement {
|
||||
let target_base = match &character.move_state {
|
||||
Stand(_) => anim::character::StandAnimation::update_skeleton(
|
||||
&CharacterSkeleton::new(),
|
||||
(active_tool_kind, time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Run(_) => anim::character::RunAnimation::update_skeleton(
|
||||
&CharacterSkeleton::new(),
|
||||
(active_tool_kind, vel.0, ori.0, state.last_ori, time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Jump(_) | Fall(_) => anim::character::JumpAnimation::update_skeleton(
|
||||
&CharacterSkeleton::new(),
|
||||
(active_tool_kind, time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_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.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Swim(_) => anim::character::SwimAnimation::update_skeleton(
|
||||
&CharacterSkeleton::new(),
|
||||
(active_tool_kind, vel.0.magnitude(), ori.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
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.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Sit(_) => anim::character::SitAnimation::update_skeleton(
|
||||
&CharacterSkeleton::new(),
|
||||
(active_tool_kind, time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
};
|
||||
let target_bones = match (&character.movement, &character.action) {
|
||||
let target_bones = match (&character.move_state, &character.action_state) {
|
||||
(Stand(_), Wield { .. }) => {
|
||||
anim::character::CidleAnimation::update_skeleton(
|
||||
&target_base,
|
||||
@ -266,35 +266,37 @@ impl FigureMgr {
|
||||
skeleton_attr,
|
||||
)
|
||||
}
|
||||
(_, Attack { .. }) => anim::character::AttackAnimation::update_skeleton(
|
||||
&target_base,
|
||||
(active_tool_kind, time),
|
||||
state.action_time,
|
||||
&mut action_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
(_, Wield { .. }) => anim::character::WieldAnimation::update_skeleton(
|
||||
(_, Attack(kind)) => match kind {
|
||||
Charge(_) => anim::character::ChargeAnimation::update_skeleton(
|
||||
&target_base,
|
||||
(active_tool_kind, time),
|
||||
state.action_time,
|
||||
&mut action_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
BasicAttack(_) => anim::character::AttackAnimation::update_skeleton(
|
||||
&target_base,
|
||||
(active_tool_kind, time),
|
||||
state.action_time,
|
||||
&mut action_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,
|
||||
),
|
||||
(_, Roll { .. }) => anim::character::RollAnimation::update_skeleton(
|
||||
(_, Dodge(_)) => anim::character::RollAnimation::update_skeleton(
|
||||
&target_base,
|
||||
(active_tool_kind, time),
|
||||
state.action_time,
|
||||
&mut action_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
(_, Block { .. }) => anim::character::BlockAnimation::update_skeleton(
|
||||
&target_base,
|
||||
(active_tool_kind, time),
|
||||
state.action_time,
|
||||
&mut action_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
(_, Charge { .. }) => anim::character::ChargeAnimation::update_skeleton(
|
||||
(_, Block(_)) => anim::character::BlockAnimation::update_skeleton(
|
||||
&target_base,
|
||||
(active_tool_kind, time),
|
||||
state.action_time,
|
||||
@ -313,7 +315,7 @@ impl FigureMgr {
|
||||
scale,
|
||||
col,
|
||||
dt,
|
||||
movement_animation_rate,
|
||||
move_state_animation_rate,
|
||||
action_animation_rate,
|
||||
);
|
||||
}
|
||||
@ -330,30 +332,30 @@ impl FigureMgr {
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if !character.is_same_movement(&last_character.0) {
|
||||
state.movement_time = 0.0;
|
||||
if !character.is_same_move_state(&last_character.0) {
|
||||
state.move_state_time = 0.0;
|
||||
}
|
||||
|
||||
let target_base = match character.movement {
|
||||
let target_base = match character.move_state {
|
||||
Stand(_) => anim::quadruped_small::IdleAnimation::update_skeleton(
|
||||
&QuadrupedSmallSkeleton::new(),
|
||||
time,
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Run(_) => anim::quadruped_small::RunAnimation::update_skeleton(
|
||||
&QuadrupedSmallSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
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.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
|
||||
@ -370,7 +372,7 @@ impl FigureMgr {
|
||||
scale,
|
||||
col,
|
||||
dt,
|
||||
movement_animation_rate,
|
||||
move_state_animation_rate,
|
||||
action_animation_rate,
|
||||
);
|
||||
}
|
||||
@ -387,30 +389,30 @@ impl FigureMgr {
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if !character.is_same_movement(&last_character.0) {
|
||||
state.movement_time = 0.0;
|
||||
if !character.is_same_move_state(&last_character.0) {
|
||||
state.move_state_time = 0.0;
|
||||
}
|
||||
|
||||
let target_base = match character.movement {
|
||||
let target_base = match character.move_state {
|
||||
Stand(_) => anim::quadruped_medium::IdleAnimation::update_skeleton(
|
||||
&QuadrupedMediumSkeleton::new(),
|
||||
time,
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
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.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
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.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
|
||||
@ -427,7 +429,7 @@ impl FigureMgr {
|
||||
scale,
|
||||
col,
|
||||
dt,
|
||||
movement_animation_rate,
|
||||
move_state_animation_rate,
|
||||
action_animation_rate,
|
||||
);
|
||||
}
|
||||
@ -442,30 +444,30 @@ impl FigureMgr {
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if !character.is_same_movement(&last_character.0) {
|
||||
state.movement_time = 0.0;
|
||||
if !character.is_same_move_state(&last_character.0) {
|
||||
state.move_state_time = 0.0;
|
||||
}
|
||||
|
||||
let target_base = match character.movement {
|
||||
let target_base = match character.move_state {
|
||||
Stand(_) => anim::bird_medium::IdleAnimation::update_skeleton(
|
||||
&BirdMediumSkeleton::new(),
|
||||
time,
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Run(_) => anim::bird_medium::RunAnimation::update_skeleton(
|
||||
&BirdMediumSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Jump(_) => anim::bird_medium::JumpAnimation::update_skeleton(
|
||||
&BirdMediumSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
|
||||
@ -482,7 +484,7 @@ impl FigureMgr {
|
||||
scale,
|
||||
col,
|
||||
dt,
|
||||
movement_animation_rate,
|
||||
move_state_animation_rate,
|
||||
action_animation_rate,
|
||||
);
|
||||
}
|
||||
@ -497,30 +499,30 @@ impl FigureMgr {
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if !character.is_same_movement(&last_character.0) {
|
||||
state.movement_time = 0.0;
|
||||
if !character.is_same_move_state(&last_character.0) {
|
||||
state.move_state_time = 0.0;
|
||||
}
|
||||
|
||||
let target_base = match character.movement {
|
||||
let target_base = match character.move_state {
|
||||
Stand(_) => anim::fish_medium::IdleAnimation::update_skeleton(
|
||||
&FishMediumSkeleton::new(),
|
||||
time,
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Run(_) => anim::fish_medium::RunAnimation::update_skeleton(
|
||||
&FishMediumSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Jump(_) => anim::fish_medium::JumpAnimation::update_skeleton(
|
||||
&FishMediumSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
|
||||
@ -537,7 +539,7 @@ impl FigureMgr {
|
||||
scale,
|
||||
col,
|
||||
dt,
|
||||
movement_animation_rate,
|
||||
move_state_animation_rate,
|
||||
action_animation_rate,
|
||||
);
|
||||
}
|
||||
@ -552,30 +554,30 @@ impl FigureMgr {
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if !character.is_same_movement(&last_character.0) {
|
||||
state.movement_time = 0.0;
|
||||
if !character.is_same_move_state(&last_character.0) {
|
||||
state.move_state_time = 0.0;
|
||||
}
|
||||
|
||||
let target_base = match character.movement {
|
||||
let target_base = match character.move_state {
|
||||
Stand(_) => anim::dragon::IdleAnimation::update_skeleton(
|
||||
&DragonSkeleton::new(),
|
||||
time,
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Run(_) => anim::dragon::RunAnimation::update_skeleton(
|
||||
&DragonSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Jump(_) => anim::dragon::JumpAnimation::update_skeleton(
|
||||
&DragonSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
|
||||
@ -592,7 +594,7 @@ impl FigureMgr {
|
||||
scale,
|
||||
col,
|
||||
dt,
|
||||
movement_animation_rate,
|
||||
move_state_animation_rate,
|
||||
action_animation_rate,
|
||||
);
|
||||
}
|
||||
@ -607,30 +609,30 @@ impl FigureMgr {
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if !character.is_same_movement(&last_character.0) {
|
||||
state.movement_time = 0.0;
|
||||
if !character.is_same_move_state(&last_character.0) {
|
||||
state.move_state_time = 0.0;
|
||||
}
|
||||
|
||||
let target_base = match character.movement {
|
||||
let target_base = match character.move_state {
|
||||
Stand(_) => anim::bird_small::IdleAnimation::update_skeleton(
|
||||
&BirdSmallSkeleton::new(),
|
||||
time,
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Run(_) => anim::bird_small::RunAnimation::update_skeleton(
|
||||
&BirdSmallSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Jump(_) => anim::bird_small::JumpAnimation::update_skeleton(
|
||||
&BirdSmallSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
|
||||
@ -647,7 +649,7 @@ impl FigureMgr {
|
||||
scale,
|
||||
col,
|
||||
dt,
|
||||
movement_animation_rate,
|
||||
move_state_animation_rate,
|
||||
action_animation_rate,
|
||||
);
|
||||
}
|
||||
@ -662,30 +664,30 @@ impl FigureMgr {
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if !character.is_same_movement(&last_character.0) {
|
||||
state.movement_time = 0.0;
|
||||
if !character.is_same_move_state(&last_character.0) {
|
||||
state.move_state_time = 0.0;
|
||||
}
|
||||
|
||||
let target_base = match character.movement {
|
||||
let target_base = match character.move_state {
|
||||
Stand(_) => anim::fish_small::IdleAnimation::update_skeleton(
|
||||
&FishSmallSkeleton::new(),
|
||||
time,
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Run(_) => anim::fish_small::RunAnimation::update_skeleton(
|
||||
&FishSmallSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Jump(_) => anim::fish_small::JumpAnimation::update_skeleton(
|
||||
&FishSmallSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
|
||||
@ -702,7 +704,7 @@ impl FigureMgr {
|
||||
scale,
|
||||
col,
|
||||
dt,
|
||||
movement_animation_rate,
|
||||
move_state_animation_rate,
|
||||
action_animation_rate,
|
||||
);
|
||||
}
|
||||
@ -717,30 +719,30 @@ impl FigureMgr {
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if !character.is_same_movement(&last_character.0) {
|
||||
state.movement_time = 0.0;
|
||||
if !character.is_same_move_state(&last_character.0) {
|
||||
state.move_state_time = 0.0;
|
||||
}
|
||||
|
||||
let target_base = match character.movement {
|
||||
let target_base = match character.move_state {
|
||||
Stand(_) => anim::biped_large::IdleAnimation::update_skeleton(
|
||||
&BipedLargeSkeleton::new(),
|
||||
time,
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Run(_) => anim::biped_large::RunAnimation::update_skeleton(
|
||||
&BipedLargeSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
Jump(_) => anim::biped_large::JumpAnimation::update_skeleton(
|
||||
&BipedLargeSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.movement_time,
|
||||
&mut movement_animation_rate,
|
||||
state.move_state_time,
|
||||
&mut move_state_animation_rate,
|
||||
skeleton_attr,
|
||||
),
|
||||
|
||||
@ -757,7 +759,7 @@ impl FigureMgr {
|
||||
scale,
|
||||
col,
|
||||
dt,
|
||||
movement_animation_rate,
|
||||
move_state_animation_rate,
|
||||
action_animation_rate,
|
||||
);
|
||||
}
|
||||
@ -776,7 +778,7 @@ impl FigureMgr {
|
||||
scale,
|
||||
col,
|
||||
dt,
|
||||
movement_animation_rate,
|
||||
move_state_animation_rate,
|
||||
action_animation_rate,
|
||||
);
|
||||
}
|
||||
@ -919,7 +921,7 @@ impl FigureMgr {
|
||||
pub struct FigureState<S: Skeleton> {
|
||||
bone_consts: Consts<FigureBoneData>,
|
||||
locals: Consts<FigureLocals>,
|
||||
movement_time: f64,
|
||||
move_state_time: f64,
|
||||
action_time: f64,
|
||||
skeleton: S,
|
||||
pos: Vec3<f32>,
|
||||
@ -934,7 +936,7 @@ impl<S: Skeleton> FigureState<S> {
|
||||
.create_consts(&skeleton.compute_matrices())
|
||||
.unwrap(),
|
||||
locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(),
|
||||
movement_time: 0.0,
|
||||
move_state_time: 0.0,
|
||||
action_time: 0.0,
|
||||
skeleton,
|
||||
pos: Vec3::zero(),
|
||||
@ -952,7 +954,7 @@ impl<S: Skeleton> FigureState<S> {
|
||||
scale: f32,
|
||||
col: Rgba<f32>,
|
||||
dt: f32,
|
||||
movement_rate: f32,
|
||||
move_state_rate: f32,
|
||||
action_rate: f32,
|
||||
) {
|
||||
self.last_ori = Lerp::lerp(self.last_ori, ori, 15.0 * dt);
|
||||
@ -966,7 +968,7 @@ impl<S: Skeleton> FigureState<S> {
|
||||
self.ori = ori;
|
||||
}
|
||||
|
||||
self.movement_time += (dt * movement_rate) as f64;
|
||||
self.move_state_time += (dt * move_state_rate) as f64;
|
||||
self.action_time += (dt * action_rate) as f64;
|
||||
|
||||
let mat = Mat4::<f32>::identity()
|
||||
|
@ -160,7 +160,7 @@ impl Scene {
|
||||
.ecs()
|
||||
.read_storage::<comp::CharacterState>()
|
||||
.get(client.entity())
|
||||
.map_or(false, |cs| cs.action.is_roll());
|
||||
.map_or(false, |cs| cs.action_state.is_dodging());
|
||||
|
||||
let player_scale = match client
|
||||
.state()
|
||||
|
@ -202,9 +202,9 @@ impl PlayState for SessionState {
|
||||
.read_storage::<comp::CharacterState>()
|
||||
.get(client.entity())
|
||||
.map(|cs| {
|
||||
cs.action.is_wield()
|
||||
|| cs.action.is_block()
|
||||
|| cs.action.is_attack()
|
||||
cs.action_state.is_wielding()
|
||||
|| cs.action_state.is_blocking()
|
||||
|| cs.action_state.is_attacking()
|
||||
})
|
||||
.unwrap_or(false)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user