From a62be4f0b059ac5e98caa3c084b025ee794df1d7 Mon Sep 17 00:00:00 2001 From: AdamWhitehurst Date: Sun, 22 Dec 2019 08:08:48 -0800 Subject: [PATCH] finish movment states handle() fn logic --- .DS_Store | Bin 0 -> 6148 bytes common/src/comp/character_state.rs | 26 +- common/src/comp/mod.rs | 5 +- common/src/sys/agent.rs | 7 +- common/src/sys/character_state.rs | 1043 ++++++++++++++++++------- common/src/sys/movement.rs | 232 +++--- voxygen/src/audio/sfx/event_mapper.rs | 8 +- voxygen/src/scene/figure/mod.rs | 26 +- 8 files changed, 930 insertions(+), 417 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8cda30a1a4792f56e6be97fda60289fc9c97c759 GIT binary patch literal 6148 zcmeHKyH3L}6g`GgN|AsK#*8c=F|&j|gevincaS^ve!>5#;9oUf%wdSE;QLnMD=`ch$97Q?FF%-SOn* zKR52#Vzotsp$-ZJ1%d)!3dr{%ViAlj<_7hrgOxr45G(A~#b{p7ITA!4rLD?%Fe9p2}SAIIew(wp<;uf4hjSXd Self { Self { - movement: MovementState::Jump, + movement: MovementState::Fall(FallData), action: ActionState::Idle, } } diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index a119bf10a6..1f2e894539 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -20,7 +20,10 @@ pub use body::{ biped_large, bird_medium, bird_small, dragon, fish_medium, fish_small, humanoid, object, quadruped_medium, quadruped_small, Body, }; -pub use character_state::{ActionState, CharacterState, MovementState, RunData, StandData}; +pub use character_state::{ + ActionState, CharacterState, ClimbData, FallData, GlideData, JumpData, MovementState, RunData, + SitData, StandData, SwimData, +}; pub use controller::{ ControlEvent, Controller, ControllerInputs, Input, InputState, InventoryManip, MountState, Mounting, diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index c2bcbe1c2a..f0df4a9e0d 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -1,6 +1,6 @@ use crate::comp::{ - Agent, CharacterState, Controller, ControllerInputs, MountState, MovementState::Glide, Pos, - Stats, + Agent, CharacterState, Controller, ControllerInputs, GlideData, MountState, + MovementState::Glide, Pos, Stats, }; use crate::pathfinding::WorldPath; use crate::terrain::TerrainGrid; @@ -163,7 +163,8 @@ impl<'a> System<'a> for Sys { inputs.roll.set_state(true); } - if target_character.movement == Glide && target_pos.0.z > pos.0.z + 5.0 + if target_character.movement == Glide(GlideData) + && target_pos.0.z > pos.0.z + 5.0 { inputs.glide.set_state(true); inputs.jump.set_state(true); diff --git a/common/src/sys/character_state.rs b/common/src/sys/character_state.rs index 8a26c82e5b..716ddacf46 100644 --- a/common/src/sys/character_state.rs +++ b/common/src/sys/character_state.rs @@ -1,12 +1,30 @@ use super::movement::ROLL_DURATION; +use super::phys::GRAVITY; + const HUMANOID_ACCEL: f32 = 50.0; const HUMANOID_SPEED: f32 = 120.0; +const HUMANOID_AIR_ACCEL: f32 = 10.0; +const HUMANOID_AIR_SPEED: f32 = 100.0; +const HUMANOID_WATER_ACCEL: f32 = 70.0; +const HUMANOID_WATER_SPEED: f32 = 120.0; +const HUMANOID_CLIMB_ACCEL: f32 = 5.0; +const ROLL_SPEED: f32 = 17.0; +const CHARGE_SPEED: f32 = 20.0; +const GLIDE_ACCEL: f32 = 15.0; +const GLIDE_SPEED: f32 = 45.0; +const BLOCK_ACCEL: f32 = 30.0; +const BLOCK_SPEED: f32 = 75.0; +// Gravity is 9.81 * 4, so this makes gravity equal to .15 +const GLIDE_ANTIGRAV: f32 = GRAVITY * 0.96; +const CLIMB_SPEED: f32 = 5.0; + +pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0; use crate::{ comp::{ - self, item, projectile, ActionState, ActionState::*, Body, CharacterState, ControlEvent, - Controller, ControllerInputs, HealthChange, HealthSource, ItemKind, Mounting, - MovementState, MovementState::*, Ori, PhysicsState, Pos, Projectile, RunData, StandData, - Stats, Vel, + self, item, projectile, ActionState, ActionState::*, Body, CharacterState, ClimbData, + ControlEvent, Controller, ControllerInputs, FallData, GlideData, HealthChange, + HealthSource, ItemKind, JumpData, Mounting, MovementState, MovementState::*, Ori, + PhysicsState, Pos, Projectile, RunData, SitData, StandData, Stats, SwimData, Vel, }, event::{Emitter, EventBus, LocalEvent, ServerEvent}, state::DeltaTime, @@ -19,6 +37,8 @@ use sphynx::{Uid, UidAllocator}; use std::time::Duration; use vek::*; +struct CharacterStateData(); + /// # Character State System /// #### Updates then detemrines next Character States based on ControllerInputs pub struct Sys; @@ -61,8 +81,6 @@ impl<'a> System<'a> for Sys { mountings, ): Self::SystemData, ) { - let mut server_emitter = server_bus.emitter(); - let mut local_emitter = local_bus.emitter(); for ( entity, uid, @@ -91,7 +109,7 @@ impl<'a> System<'a> for Sys { .join() { let inputs = &controller.inputs; - + // println!("{:?}", character); // Returns a Wield action, or Idle if nothing to wield let try_wield = |stats: &Stats| -> ActionState { // Get weapon to wield @@ -121,14 +139,15 @@ impl<'a> System<'a> for Sys { // prevent instant-respawns (i.e. player was holding attack) // by disallowing while input is held down if inputs.respawn.is_pressed() && !inputs.respawn.is_held_down() { - server_emitter.emit(ServerEvent::Respawn(entity)); + server_bus.emitter().emit(ServerEvent::Respawn(entity)); } // Or do nothing continue; } // If mounted, character state is controlled by mount + // TODO: Make mounting a state if mount.is_some() { - character.movement = Sit; + character.movement = Sit(SitData); continue; } @@ -168,263 +187,153 @@ impl<'a> System<'a> for Sys { Idle => {} } - // Determine new states - match (character.action, character.movement) { - // Jumping, one frame state that calls jump server event - (_, Jump) => { - character.movement = Fall; - local_emitter.emit(LocalEvent::Jump(entity)); - } - // Charging + Any Movement, prioritizes finishing charge - // over movement states - (Charge { time_left }, _) => { - if let Some(uid_b) = physics.touch_entity { - server_emitter.emit(ServerEvent::Damage { - uid: uid_b, - change: HealthChange { - amount: -20, - cause: HealthSource::Attack { by: *uid }, - }, - }); + // Determine new state + *character = match character.movement { + Stand(data) => data.handle( + &entity, + character, + pos, + vel, + ori, + &dt, + inputs, + stats, + body, + physics, + &server_bus, + &local_bus, + ), + Run(data) => data.handle( + &entity, + character, + pos, + vel, + ori, + &dt, + inputs, + stats, + body, + physics, + &server_bus, + &local_bus, + ), + Jump(data) => data.handle( + &entity, + character, + pos, + vel, + ori, + &dt, + inputs, + stats, + body, + physics, + &server_bus, + &local_bus, + ), + Climb(data) => data.handle( + &entity, + character, + pos, + vel, + ori, + &dt, + inputs, + stats, + body, + physics, + &server_bus, + &local_bus, + ), + Glide(data) => data.handle( + &entity, + character, + pos, + vel, + ori, + &dt, + inputs, + stats, + body, + physics, + &server_bus, + &local_bus, + ), + Swim(data) => data.handle( + &entity, + character, + pos, + vel, + ori, + &dt, + inputs, + stats, + body, + physics, + &server_bus, + &local_bus, + ), + Fall(data) => data.handle( + &entity, + character, + pos, + vel, + ori, + &dt, + inputs, + stats, + body, + physics, + &server_bus, + &local_bus, + ), + Sit(data) => data.handle( + &entity, + character, + pos, + vel, + ori, + &dt, + inputs, + stats, + body, + physics, + &server_bus, + &local_bus, + ), // Charging + Any Movement, prioritizes finishing charge + // over movement states + // (Charge { time_left }, _) => { + // if let Some(uid_b) = physics.touch_entity { + // server_emitter.emit(ServerEvent::Damage { + // uid: uid_b, + // change: HealthChange { + // amount: -20, + // cause: HealthSource::Attack { by: *uid }, + // }, + // }); - character.action = try_wield(stats); - } else if time_left == Duration::default() || vel.0.magnitude_squared() < 10.0 { - character.action = try_wield(stats); - } - } - // Rolling + Any Movement, prioritizes finishing charge - // over movement states - ( - Roll { - time_left, - was_wielding, - }, - _, - ) => { - if time_left == Duration::default() { - if was_wielding { - character.action = try_wield(stats); - } else { - character.action = Idle; - } - } - } - // Any Action + Falling - (action_state, Fall) => { - // character.movement = get_state_from_move_dir(&inputs.move_dir); - if inputs.glide.is_pressed() && !inputs.glide.is_held_down() { - character.movement = Glide; - continue; - } - // Reset to Falling while not standing on ground, - // otherwise keep the state given above - if !physics.on_ground { - if physics.in_fluid { - character.movement = Swim; - } else { - character.movement = Fall; - } - } else { - character.movement = Stand(StandData); - continue; - } - - match action_state { - // Unwield if buttons pressed - Wield { .. } | Attack { .. } => { - if inputs.toggle_wield.is_just_pressed() { - character.action = Idle; - } - } - // Try to wield if any of buttons pressed - Idle => { - if inputs.primary.is_pressed() || inputs.secondary.is_pressed() { - character.action = try_wield(stats); - } - } - // Cancel blocks - Block { .. } => { - character.action = try_wield(stats); - } - // Don't change action - Charge { .. } | Roll { .. } => {} - } - } - // Any Action + Swimming - (_, Swim) => { - character.movement = get_state_from_move_dir(&inputs.move_dir); - - if !physics.on_ground && physics.in_fluid { - character.movement = Swim; - } - if inputs.primary.is_pressed() { - // TODO: PrimaryStart - } else if inputs.secondary.is_pressed() { - // TODO: SecondaryStart - } - } - // // Blocking, restricted look_dir compared to other states - // (Block { .. }, Stand) | (Block { .. }, Run) => { - // character.movement = get_state_from_move_dir(&inputs.move_dir); - - // if !inputs.secondary.is_pressed() { - // character.action = try_wield(stats); - // } else { - // // TODO: SecondaryStart - // } - - // if !physics.on_ground && physics.in_fluid { - // character.movement = Swim; - // } - // } - // // Standing and Running states, typical states :shrug: - // (action_state, Run) | (action_state, Stand) => { - // character.movement = get_state_from_move_dir(&inputs.move_dir); - // // Try to sit - // if inputs.sit.is_pressed() && physics.on_ground && body.is_humanoid() { - // character.movement = Sit; - // continue; - // } - - // // Try to climb - // if let (true, Some(_wall_dir)) = ( - // inputs.climb.is_pressed() | inputs.climb_down.is_pressed() - // && body.is_humanoid(), - // physics.on_wall, - // ) { - // character.movement = Climb; - // continue; - // } - - // // Try to swim - // if !physics.on_ground && physics.in_fluid { - // character.movement = Swim; - // continue; - // } - - // // While on ground ... - // if physics.on_ground { - // // Try to jump - // if inputs.jump.is_pressed() && !inputs.jump.is_held_down() { - // character.movement = Jump; - // continue; - // } - - // // Try to charge - // if inputs.charge.is_pressed() && !inputs.charge.is_held_down() { - // character.action = Charge { - // time_left: Duration::from_millis(250), - // }; - // continue; - // } - - // // Try to roll - // if character.movement == Run - // && inputs.roll.is_pressed() - // && body.is_humanoid() - // { - // character.action = Roll { - // time_left: ROLL_DURATION, - // was_wielding: character.action.is_wield(), - // }; - // continue; - // } - // } - // // While not on ground ... - // else { - // // Try to glide - // if physics.on_wall == None - // && inputs.glide.is_pressed() - // && !inputs.glide.is_held_down() - // && body.is_humanoid() - // { - // character.movement = Glide; - // continue; - // } - // character.movement = Fall; - // } - - // // Tool Actions - // if inputs.toggle_wield.is_just_pressed() { - // match action_state { - // Wield { .. } | Attack { .. } => { - // // Prevent instantaneous reequipping by checking - // // for done wielding - // if character.action.is_action_finished() { - // character.action = Idle; - // } - // continue; - // } - // Idle => { - // character.action = try_wield(stats); - // continue; - // } - // Charge { .. } | Roll { .. } | Block { .. } => {} - // } - // } - // if inputs.primary.is_pressed() { - // // TODO: PrimaryStart - // } else if inputs.secondary.is_pressed() { - // // TODO: SecondaryStart - // } - // } - // Sitting - (_, Sit) => { - character.action = Idle; - character.movement = get_state_from_move_dir(&inputs.move_dir); - - // character.movement will be Stand after updating when - // no movement has occurred - if character.movement == Stand(StandData) { - character.movement = Sit; - } - if inputs.jump.is_pressed() && !inputs.jump.is_held_down() { - character.movement = Jump; - continue; - } - if !physics.on_ground { - character.movement = Fall; - } - } - // Any Action + Gliding, shouldnt care about action, - // because should be Idle - (_, Glide) => { - character.action = Idle; - - if !inputs.glide.is_pressed() { - character.movement = Fall; - } else if let Some(_wall_dir) = physics.on_wall { - character.movement = Fall; - } - - if physics.on_ground { - character.movement = Stand(StandData) - } - } - // Any Action + Climbing, shouldnt care about action, - // because should be Idle - (_, Climb) => { - character.action = Idle; - if let None = physics.on_wall { - if inputs.jump.is_pressed() { - character.movement = Jump; - } else { - character.movement = Fall; - } - } - if physics.on_ground { - character.movement = Stand(StandData); - } - } - (_, Stand(data)) => { - let mut new_char = - data.handle(character, pos, vel, ori, &dt, inputs, stats, body, physics); - println!("{:?}", new_char); - character = &mut new_char; - } - (_, _) => { - character.movement = Stand(StandData); - } + // character.action = try_wield(stats); + // } else if time_left == Duration::default() || vel.0.magnitude_squared() < 10.0 { + // character.action = try_wield(stats); + // } + // } + // Rolling + Any Movement, prioritizes finishing charge + // over movement states + // ( + // Roll { + // time_left, + // was_wielding, + // }, + // _, + // ) => { + // if time_left == Duration::default() { + // if was_wielding { + // character.action = try_wield(stats); + // } else { + // character.action = Idle; + // } + // } + // } }; } } @@ -433,6 +342,7 @@ impl<'a> System<'a> for Sys { pub trait State { fn handle( &self, + entity: &Entity, character: &CharacterState, pos: &mut Pos, vel: &mut Vel, @@ -442,14 +352,17 @@ pub trait State { stats: &Stats, body: &Body, physics: &PhysicsState, + server_bus: &EventBus, + local_bus: &EventBus, ) -> CharacterState; } -impl State for StandData { +impl State for RunData { fn handle( &self, + _entity: &Entity, character: &CharacterState, - pos: &mut Pos, + _pos: &mut Pos, vel: &mut Vel, ori: &mut Ori, dt: &DeltaTime, @@ -457,6 +370,8 @@ impl State for StandData { stats: &Stats, body: &Body, physics: &PhysicsState, + _server_bus: &EventBus, + _local_bus: &EventBus, ) -> CharacterState { // Move player according to move_dir vel.0 += Vec2::broadcast(dt.0) @@ -483,7 +398,7 @@ impl State for StandData { // Try to sit if inputs.sit.is_pressed() && physics.on_ground && body.is_humanoid() { return CharacterState { - movement: Sit, + movement: Sit(SitData), action: Idle, }; } @@ -494,7 +409,7 @@ impl State for StandData { physics.on_wall, ) { return CharacterState { - movement: Climb, + movement: Climb(ClimbData), action: Idle, }; } @@ -503,7 +418,7 @@ impl State for StandData { if !physics.on_ground && physics.in_fluid { return CharacterState { action: character.action, - movement: Swim, + movement: Swim(SwimData), }; } @@ -513,7 +428,7 @@ impl State for StandData { if inputs.jump.is_pressed() && !inputs.jump.is_held_down() { return CharacterState { action: character.action, - movement: Jump, + movement: Jump(JumpData), }; } @@ -548,12 +463,12 @@ impl State for StandData { { return CharacterState { action: Idle, - movement: Glide, + movement: Glide(GlideData), }; } return CharacterState { action: character.action, - movement: Fall, + movement: Fall(FallData), }; } @@ -608,3 +523,585 @@ impl State for StandData { } } } + +impl State for StandData { + fn handle( + &self, + _entity: &Entity, + character: &CharacterState, + _pos: &mut Pos, + _vel: &mut Vel, + _ori: &mut Ori, + _dt: &DeltaTime, + inputs: &ControllerInputs, + stats: &Stats, + body: &Body, + physics: &PhysicsState, + _server_bus: &EventBus, + _local_bus: &EventBus, + ) -> CharacterState { + // Try to sit + if inputs.sit.is_pressed() && physics.on_ground && body.is_humanoid() { + return CharacterState { + movement: Sit(SitData), + action: Idle, + }; + } + + // Try to climb + if let (true, Some(_wall_dir)) = ( + inputs.climb.is_pressed() | inputs.climb_down.is_pressed() && body.is_humanoid(), + physics.on_wall, + ) { + return CharacterState { + movement: Climb(ClimbData), + action: Idle, + }; + } + + // Try to swim + if !physics.on_ground && physics.in_fluid { + return CharacterState { + action: character.action, + movement: Swim(SwimData), + }; + } + + // While on ground ... + if physics.on_ground { + // Try to jump + if inputs.jump.is_pressed() { + return CharacterState { + action: character.action, + movement: Jump(JumpData), + }; + } + + // Try to charge + if inputs.charge.is_pressed() && !inputs.charge.is_held_down() { + return CharacterState { + action: Charge { + time_left: Duration::from_millis(250), + }, + movement: Run(RunData), + }; + } + + // Try to roll + if inputs.roll.is_pressed() && body.is_humanoid() { + return CharacterState { + action: Roll { + time_left: Duration::from_millis(600), + was_wielding: character.action.is_wield(), + }, + movement: Run(RunData), + }; + } + } + // While not on ground ... + else { + // Try to glide + if physics.on_wall == None + && inputs.glide.is_pressed() + && !inputs.glide.is_held_down() + && body.is_humanoid() + { + return CharacterState { + action: Idle, + movement: Glide(GlideData), + }; + } + return CharacterState { + action: character.action, + movement: Fall(FallData), + }; + } + + // Tool Actions + if inputs.toggle_wield.is_just_pressed() { + match character.action { + Wield { .. } | Attack { .. } => { + // Prevent instantaneous reequipping by checking + // for done wielding + if character.action.is_action_finished() { + return CharacterState { + action: Idle, + movement: character.movement, + }; + } + } + Idle => { + return CharacterState { + // Try to wield if an item is equipped in main hand + action: if let Some(ItemKind::Tool { kind, .. }) = + stats.equipment.main.as_ref().map(|i| &i.kind) + { + let wield_duration = kind.wield_duration(); + Wield { + time_left: wield_duration, + } + } else { + Idle + }, + movement: character.movement, + }; + } + Charge { .. } | Roll { .. } | Block { .. } => {} + } + } + if inputs.primary.is_pressed() { + // TODO: PrimaryStart + } else if inputs.secondary.is_pressed() { + // TODO: SecondaryStart + } + + if inputs.move_dir.magnitude_squared() > 0.0 { + return CharacterState { + action: character.action, + movement: Run(RunData), + }; + } else { + return CharacterState { + action: character.action, + movement: Stand(StandData), + }; + } + } +} + +impl State for SitData { + fn handle( + &self, + _entity: &Entity, + _character: &CharacterState, + _pos: &mut Pos, + _vel: &mut Vel, + _ori: &mut Ori, + _dt: &DeltaTime, + inputs: &ControllerInputs, + _stats: &Stats, + _body: &Body, + physics: &PhysicsState, + _server_bus: &EventBus, + _local_bus: &EventBus, + ) -> CharacterState { + // Falling + // Idk, maybe the ground disappears, + // suddenly maybe a water spell appears. + // Can't hurt to be safe :shrug: + if !physics.on_ground { + if physics.in_fluid { + return CharacterState { + action: Idle, + movement: Swim(SwimData), + }; + } else { + return CharacterState { + action: Idle, + movement: Fall(FallData), + }; + } + } + // Jumping + if inputs.jump.is_pressed() { + return CharacterState { + action: Idle, + movement: Jump(JumpData), + }; + } + + // Moving + if inputs.move_dir.magnitude_squared() > 0.0 { + return CharacterState { + action: Idle, + movement: Run(RunData), + }; + } + + // Standing back up (unsitting) + if inputs.sit.is_just_pressed() { + return CharacterState { + action: Idle, + movement: Stand(StandData), + }; + } + + // no movement has occurred + return CharacterState { + action: Idle, + movement: Sit(SitData), + }; + } +} + +impl State for JumpData { + fn handle( + &self, + entity: &Entity, + character: &CharacterState, + _pos: &mut Pos, + _vel: &mut Vel, + _ori: &mut Ori, + _dt: &DeltaTime, + _inputs: &ControllerInputs, + _stats: &Stats, + _body: &Body, + _physics: &PhysicsState, + _server_bus: &EventBus, + local_bus: &EventBus, + ) -> CharacterState { + local_bus.emitter().emit(LocalEvent::Jump(*entity)); + + return CharacterState { + action: character.action, + movement: Fall(FallData), + }; + } +} + +impl State for FallData { + fn handle( + &self, + _entity: &Entity, + character: &CharacterState, + _pos: &mut Pos, + vel: &mut Vel, + ori: &mut Ori, + dt: &DeltaTime, + inputs: &ControllerInputs, + stats: &Stats, + _body: &Body, + physics: &PhysicsState, + _server_bus: &EventBus, + _local_bus: &EventBus, + ) -> CharacterState { + // Move player according to move_dir + vel.0 += Vec2::broadcast(dt.0) + * inputs.move_dir + * if vel.0.magnitude_squared() < HUMANOID_AIR_SPEED.powf(2.0) { + HUMANOID_AIR_ACCEL + } else { + 0.0 + }; + + // Set direction based on move direction when on the ground + let ori_dir = if character.action.is_attack() || character.action.is_block() { + Vec2::from(inputs.look_dir).normalized() + } else { + Vec2::from(vel.0) + }; + + if ori_dir.magnitude_squared() > 0.0001 + && (ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared() > 0.001 + { + ori.0 = vek::ops::Slerp::slerp(ori.0, ori_dir.into(), 2.0 * dt.0); + } + + let mut new_action = character.action; + + // Update actions + match character.action { + // Unwield if buttons pressed + Wield { .. } | Attack { .. } => { + if inputs.toggle_wield.is_just_pressed() { + new_action = Idle; + } + } + // Try to wield if any of buttons pressed + Idle => { + if inputs.primary.is_pressed() || inputs.secondary.is_pressed() { + new_action = if let Some(ItemKind::Tool { kind, .. }) = + stats.equipment.main.as_ref().map(|i| &i.kind) + { + let wield_duration = kind.wield_duration(); + Wield { + time_left: wield_duration, + } + } else { + Idle + } + }; + } + // Cancel blocks + Block { .. } => { + new_action = if let Some(ItemKind::Tool { kind, .. }) = + stats.equipment.main.as_ref().map(|i| &i.kind) + { + let wield_duration = kind.wield_duration(); + Wield { + time_left: wield_duration, + } + } else { + Idle + }; + } + // Don't change action + Charge { .. } | Roll { .. } => {} + }; + + // Gliding + if inputs.glide.is_pressed() && !inputs.glide.is_held_down() { + return CharacterState { + action: Idle, + movement: Glide(GlideData), + }; + } + + // Reset to Falling while not standing on ground, + // otherwise keep the state given above + if !physics.on_ground { + if physics.in_fluid { + return CharacterState { + action: new_action, + movement: Swim(SwimData), + }; + } else { + return CharacterState { + action: new_action, + movement: Fall(FallData), + }; + } + } + // On ground + else { + // Return to running or standing based on move inputs + return CharacterState { + action: new_action, + movement: if inputs.move_dir.magnitude_squared() > 0.0 { + Run(RunData) + } else { + Stand(StandData) + }, + }; + } + } +} +impl State for GlideData { + fn handle( + &self, + _entity: &Entity, + _character: &CharacterState, + _pos: &mut Pos, + vel: &mut Vel, + ori: &mut Ori, + dt: &DeltaTime, + inputs: &ControllerInputs, + _stats: &Stats, + _body: &Body, + physics: &PhysicsState, + _server_bus: &EventBus, + _local_bus: &EventBus, + ) -> CharacterState { + // Move player according to move_dir + vel.0 += Vec2::broadcast(dt.0) + * inputs.move_dir + * if vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) { + GLIDE_ACCEL + } else { + 0.0 + }; + + let ori_dir = Vec2::from(vel.0); + + if ori_dir.magnitude_squared() > 0.0001 + && (ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared() > 0.001 + { + ori.0 = vek::ops::Slerp::slerp(ori.0, ori_dir.into(), 2.0 * dt.0); + } + + // Apply Glide lift + if Vec2::::from(vel.0).magnitude_squared() < GLIDE_SPEED.powf(2.0) && vel.0.z < 0.0 { + let lift = GLIDE_ANTIGRAV + vel.0.z.abs().powf(2.0) * 0.15; + vel.0.z += dt.0 + * lift + * (Vec2::::from(vel.0).magnitude() * 0.075) + .min(1.0) + .max(0.2); + } + + if !inputs.glide.is_pressed() { + return CharacterState { + action: Idle, + movement: Fall(FallData), + }; + } else if let Some(_wall_dir) = physics.on_wall { + return CharacterState { + action: Idle, + movement: Climb(ClimbData), + }; + } + + if physics.on_ground { + return CharacterState { + action: Idle, + movement: Stand(StandData), + }; + } + + return CharacterState { + action: Idle, + movement: Glide(GlideData), + }; + } +} +impl State for ClimbData { + fn handle( + &self, + _entity: &Entity, + character: &CharacterState, + _pos: &mut Pos, + vel: &mut Vel, + ori: &mut Ori, + dt: &DeltaTime, + inputs: &ControllerInputs, + _stats: &Stats, + _body: &Body, + physics: &PhysicsState, + _server_bus: &EventBus, + _local_bus: &EventBus, + ) -> CharacterState { + // Move player according to move_dir + vel.0 += Vec2::broadcast(dt.0) + * inputs.move_dir + * if 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) = physics.on_wall { + if Vec2::::from(wall_dir).magnitude_squared() > 0.001 { + Vec2::from(wall_dir).normalized() + } else { + Vec2::from(vel.0) + } + } else { + Vec2::from(vel.0) + }; + + if ori_dir.magnitude_squared() > 0.0001 + && (ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared() > 0.001 + { + ori.0 = vek::ops::Slerp::slerp( + ori.0, + ori_dir.into(), + if physics.on_ground { 9.0 } else { 2.0 } * dt.0, + ); + } + + // Apply Vertical Climbing Movement + if let (true, Some(_wall_dir)) = ( + (inputs.climb.is_pressed() | inputs.climb_down.is_pressed()) && vel.0.z <= CLIMB_SPEED, + physics.on_wall, + ) { + if inputs.climb_down.is_pressed() && !inputs.climb.is_pressed() { + vel.0 -= dt.0 * vel.0.map(|e| e.abs().powf(1.5) * e.signum() * 6.0); + } else if inputs.climb.is_pressed() && !inputs.climb_down.is_pressed() { + vel.0.z = (vel.0.z + dt.0 * GRAVITY * 1.25).min(CLIMB_SPEED); + } else { + vel.0.z = vel.0.z + dt.0 * GRAVITY * 1.5; + vel.0 = Lerp::lerp( + vel.0, + Vec3::zero(), + 30.0 * dt.0 / (1.0 - vel.0.z.min(0.0) * 5.0), + ); + } + } + + if let None = physics.on_wall { + if inputs.jump.is_pressed() { + return CharacterState { + action: Idle, + movement: Jump(JumpData), + }; + } else { + return CharacterState { + action: Idle, + movement: Fall(FallData), + }; + } + } + if physics.on_ground { + return CharacterState { + action: Idle, + movement: Stand(StandData), + }; + } + + return *character; + } +} +impl State for SwimData { + fn handle( + &self, + _entity: &Entity, + character: &CharacterState, + _pos: &mut Pos, + vel: &mut Vel, + ori: &mut Ori, + dt: &DeltaTime, + inputs: &ControllerInputs, + _stats: &Stats, + _body: &Body, + physics: &PhysicsState, + _server_bus: &EventBus, + _local_bus: &EventBus, + ) -> CharacterState { + // Update velocity + vel.0 += Vec2::broadcast(dt.0) + * inputs.move_dir + * if 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 character.action.is_attack() || character.action.is_block() { + Vec2::from(inputs.look_dir).normalized() + } else { + Vec2::from(vel.0) + }; + + if ori_dir.magnitude_squared() > 0.0001 + && (ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared() > 0.001 + { + ori.0 = vek::ops::Slerp::slerp( + ori.0, + ori_dir.into(), + if physics.on_ground { 9.0 } else { 2.0 } * dt.0, + ); + } + + if inputs.jump.is_pressed() { + vel.0.z = (vel.0.z + dt.0 * GRAVITY * 1.25).min(HUMANOID_WATER_SPEED); + } + + if inputs.primary.is_pressed() { + // TODO: PrimaryStart + } else if inputs.secondary.is_pressed() { + // TODO: SecondaryStart + } + + // Not on ground + if !physics.on_ground { + return CharacterState { + action: character.action, + movement: Swim(SwimData), + }; + } + // On ground + else { + // Return to running or standing based on move inputs + return CharacterState { + action: character.action, + movement: if inputs.move_dir.magnitude_squared() > 0.0 { + Run(RunData) + } else { + Stand(StandData) + }, + }; + } + } +} diff --git a/common/src/sys/movement.rs b/common/src/sys/movement.rs index bcbb29436b..c3693dd828 100644 --- a/common/src/sys/movement.rs +++ b/common/src/sys/movement.rs @@ -106,131 +106,131 @@ impl<'a> System<'a> for Sys { ) .join() { - if character.movement == Run(RunData) || character.movement == Stand(StandData) { - continue; - } + // if character.movement == Run(RunData) || character.movement == Stand(StandData) { + // continue; + // } - if stats.is_dead { - continue; - } + // if stats.is_dead { + // continue; + // } - if mount.is_some() { - continue; - } + // if mount.is_some() { + // continue; + // } - let inputs = &controller.inputs; + // let inputs = &controller.inputs; - if character.action.is_roll() { - vel.0 = Vec3::new(0.0, 0.0, vel.0.z) - + (vel.0 * Vec3::new(1.0, 1.0, 0.0) - + 1.5 * inputs.move_dir.try_normalized().unwrap_or_default()) - .try_normalized() - .unwrap_or_default() - * ROLL_SPEED; - } else if character.action.is_charge() { - vel.0 = Vec3::new(0.0, 0.0, vel.0.z) - + (vel.0 * Vec3::new(1.0, 1.0, 0.0) - + 1.5 * inputs.move_dir.try_normalized().unwrap_or_default()) - .try_normalized() - .unwrap_or_default() - * CHARGE_SPEED; - } else if character.action.is_block() { - vel.0 += Vec2::broadcast(dt.0) - * inputs.move_dir - * match physics.on_ground { - true if vel.0.magnitude_squared() < BLOCK_SPEED.powf(2.0) => BLOCK_ACCEL, - _ => 0.0, - } - } else { - // Move player according to move_dir - vel.0 += Vec2::broadcast(dt.0) - * inputs.move_dir - * match (physics.on_ground, &character.movement) { - (true, Run(_)) if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => { - HUMANOID_ACCEL - } - (false, Climb) if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => { - HUMANOID_CLIMB_ACCEL - } - (false, Glide) if vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) => { - GLIDE_ACCEL - } - (false, Fall) | (false, Jump) - if vel.0.magnitude_squared() < HUMANOID_AIR_SPEED.powf(2.0) => - { - HUMANOID_AIR_ACCEL - } - (false, Swim) - if vel.0.magnitude_squared() < HUMANOID_WATER_SPEED.powf(2.0) => - { - HUMANOID_WATER_ACCEL - } - _ => 0.0, - }; - } + // if character.action.is_roll() { + // vel.0 = Vec3::new(0.0, 0.0, vel.0.z) + // + (vel.0 * Vec3::new(1.0, 1.0, 0.0) + // + 1.5 * inputs.move_dir.try_normalized().unwrap_or_default()) + // .try_normalized() + // .unwrap_or_default() + // * ROLL_SPEED; + // } else if character.action.is_charge() { + // vel.0 = Vec3::new(0.0, 0.0, vel.0.z) + // + (vel.0 * Vec3::new(1.0, 1.0, 0.0) + // + 1.5 * inputs.move_dir.try_normalized().unwrap_or_default()) + // .try_normalized() + // .unwrap_or_default() + // * CHARGE_SPEED; + // } else if character.action.is_block() { + // vel.0 += Vec2::broadcast(dt.0) + // * inputs.move_dir + // * match physics.on_ground { + // true if vel.0.magnitude_squared() < BLOCK_SPEED.powf(2.0) => BLOCK_ACCEL, + // _ => 0.0, + // } + // } else { + // // Move player according to move_dir + // vel.0 += Vec2::broadcast(dt.0) + // * inputs.move_dir + // * match (physics.on_ground, &character.movement) { + // (true, Run(_)) if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => { + // HUMANOID_ACCEL + // } + // (false, Climb) if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => { + // HUMANOID_CLIMB_ACCEL + // } + // (false, Glide) if vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) => { + // GLIDE_ACCEL + // } + // (false, Fall) | (false, Jump) + // if vel.0.magnitude_squared() < HUMANOID_AIR_SPEED.powf(2.0) => + // { + // HUMANOID_AIR_ACCEL + // } + // (false, Swim) + // if vel.0.magnitude_squared() < HUMANOID_WATER_SPEED.powf(2.0) => + // { + // HUMANOID_WATER_ACCEL + // } + // _ => 0.0, + // }; + // } - // Set direction based on move direction when on the ground - let ori_dir = if - //character.action.is_wield() || - character.action.is_attack() || character.action.is_block() { - Vec2::from(inputs.look_dir).normalized() - } else if let (Climb, Some(wall_dir)) = (character.movement, physics.on_wall) { - if Vec2::::from(wall_dir).magnitude_squared() > 0.001 { - Vec2::from(wall_dir).normalized() - } else { - Vec2::from(vel.0) - } - } else { - Vec2::from(vel.0) - }; + // // Set direction based on move direction when on the ground + // let ori_dir = if + // //character.action.is_wield() || + // character.action.is_attack() || character.action.is_block() { + // Vec2::from(inputs.look_dir).normalized() + // } else if let (Climb, Some(wall_dir)) = (character.movement, physics.on_wall) { + // if Vec2::::from(wall_dir).magnitude_squared() > 0.001 { + // Vec2::from(wall_dir).normalized() + // } else { + // Vec2::from(vel.0) + // } + // } else { + // Vec2::from(vel.0) + // }; - if ori_dir.magnitude_squared() > 0.0001 - && (ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared() - > 0.001 - { - ori.0 = vek::ops::Slerp::slerp( - ori.0, - ori_dir.into(), - if physics.on_ground { 9.0 } else { 2.0 } * dt.0, - ); - } + // if ori_dir.magnitude_squared() > 0.0001 + // && (ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared() + // > 0.001 + // { + // ori.0 = vek::ops::Slerp::slerp( + // ori.0, + // ori_dir.into(), + // if physics.on_ground { 9.0 } else { 2.0 } * dt.0, + // ); + // } - // Glide - if character.movement == Glide - && Vec2::::from(vel.0).magnitude_squared() < GLIDE_SPEED.powf(2.0) - && vel.0.z < 0.0 - { - let lift = GLIDE_ANTIGRAV + vel.0.z.abs().powf(2.0) * 0.15; - vel.0.z += dt.0 - * lift - * (Vec2::::from(vel.0).magnitude() * 0.075) - .min(1.0) - .max(0.2); - } + // // Glide + // if character.movement == Glide + // && Vec2::::from(vel.0).magnitude_squared() < GLIDE_SPEED.powf(2.0) + // && vel.0.z < 0.0 + // { + // let lift = GLIDE_ANTIGRAV + vel.0.z.abs().powf(2.0) * 0.15; + // vel.0.z += dt.0 + // * lift + // * (Vec2::::from(vel.0).magnitude() * 0.075) + // .min(1.0) + // .max(0.2); + // } - // Climb - if let (true, Some(_wall_dir)) = ( - (inputs.climb.is_pressed() | inputs.climb_down.is_pressed()) - && vel.0.z <= CLIMB_SPEED, - physics.on_wall, - ) { - if inputs.climb_down.is_pressed() && !inputs.climb.is_pressed() { - vel.0 -= dt.0 * vel.0.map(|e| e.abs().powf(1.5) * e.signum() * 6.0); - } else if inputs.climb.is_pressed() && !inputs.climb_down.is_pressed() { - vel.0.z = (vel.0.z + dt.0 * GRAVITY * 1.25).min(CLIMB_SPEED); - } else { - vel.0.z = vel.0.z + dt.0 * GRAVITY * 1.5; - vel.0 = Lerp::lerp( - vel.0, - Vec3::zero(), - 30.0 * dt.0 / (1.0 - vel.0.z.min(0.0) * 5.0), - ); - } - } + // // Climb + // if let (true, Some(_wall_dir)) = ( + // (inputs.climb.is_pressed() | inputs.climb_down.is_pressed()) + // && vel.0.z <= CLIMB_SPEED, + // physics.on_wall, + // ) { + // if inputs.climb_down.is_pressed() && !inputs.climb.is_pressed() { + // vel.0 -= dt.0 * vel.0.map(|e| e.abs().powf(1.5) * e.signum() * 6.0); + // } else if inputs.climb.is_pressed() && !inputs.climb_down.is_pressed() { + // vel.0.z = (vel.0.z + dt.0 * GRAVITY * 1.25).min(CLIMB_SPEED); + // } else { + // vel.0.z = vel.0.z + dt.0 * GRAVITY * 1.5; + // vel.0 = Lerp::lerp( + // vel.0, + // Vec3::zero(), + // 30.0 * dt.0 / (1.0 - vel.0.z.min(0.0) * 5.0), + // ); + // } + // } - if character.movement == Swim && inputs.jump.is_pressed() { - vel.0.z = (vel.0.z + dt.0 * GRAVITY * 1.25).min(HUMANOID_WATER_SPEED); - } + // if character.movement == Swim && inputs.jump.is_pressed() { + // vel.0.z = (vel.0.z + dt.0 * GRAVITY * 1.25).min(HUMANOID_WATER_SPEED); + // } } } } diff --git a/voxygen/src/audio/sfx/event_mapper.rs b/voxygen/src/audio/sfx/event_mapper.rs index 2873f2d590..af68a96313 100644 --- a/voxygen/src/audio/sfx/event_mapper.rs +++ b/voxygen/src/audio/sfx/event_mapper.rs @@ -160,17 +160,17 @@ impl SfxEventMapper { stats, ) { (_, ActionState::Roll { .. }, ..) => SfxEvent::Roll, - (MovementState::Climb, ..) => SfxEvent::Climb, - (MovementState::Swim, ..) => SfxEvent::Swim, + (MovementState::Climb(_), ..) => SfxEvent::Climb, + (MovementState::Swim(_), ..) => SfxEvent::Swim, (MovementState::Run(_), ..) => SfxEvent::Run, - (MovementState::Fall, _, previous_event, _) => { + (MovementState::Fall(_), _, previous_event, _) => { if previous_event != SfxEvent::Glide { SfxEvent::Fall } else { SfxEvent::GliderClose } } - (MovementState::Glide, _, previous_event, ..) => { + (MovementState::Glide(_), _, previous_event, ..) => { if previous_event != SfxEvent::GliderOpen && previous_event != SfxEvent::Glide { SfxEvent::GliderOpen } else { diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 7c7319f74e..80f52b69fc 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -211,35 +211,35 @@ impl FigureMgr { &mut movement_animation_rate, skeleton_attr, ), - Jump | Fall => anim::character::JumpAnimation::update_skeleton( + Jump(_) | Fall(_) => anim::character::JumpAnimation::update_skeleton( &CharacterSkeleton::new(), (active_tool_kind, time), state.movement_time, &mut movement_animation_rate, skeleton_attr, ), - Glide => anim::character::GlidingAnimation::update_skeleton( + 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, skeleton_attr, ), - Swim => anim::character::SwimAnimation::update_skeleton( + 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, skeleton_attr, ), - Climb => anim::character::ClimbAnimation::update_skeleton( + Climb(_) => anim::character::ClimbAnimation::update_skeleton( &CharacterSkeleton::new(), (active_tool_kind, vel.0, ori.0, time), state.movement_time, &mut movement_animation_rate, skeleton_attr, ), - Sit => anim::character::SitAnimation::update_skeleton( + Sit(_) => anim::character::SitAnimation::update_skeleton( &CharacterSkeleton::new(), (active_tool_kind, time), state.movement_time, @@ -349,7 +349,7 @@ impl FigureMgr { &mut movement_animation_rate, skeleton_attr, ), - Jump => anim::quadruped_small::JumpAnimation::update_skeleton( + Jump(_) => anim::quadruped_small::JumpAnimation::update_skeleton( &QuadrupedSmallSkeleton::new(), (vel.0.magnitude(), time), state.movement_time, @@ -406,7 +406,7 @@ impl FigureMgr { &mut movement_animation_rate, skeleton_attr, ), - Jump => anim::quadruped_medium::JumpAnimation::update_skeleton( + Jump(_) => anim::quadruped_medium::JumpAnimation::update_skeleton( &QuadrupedMediumSkeleton::new(), (vel.0.magnitude(), time), state.movement_time, @@ -461,7 +461,7 @@ impl FigureMgr { &mut movement_animation_rate, skeleton_attr, ), - Jump => anim::bird_medium::JumpAnimation::update_skeleton( + Jump(_) => anim::bird_medium::JumpAnimation::update_skeleton( &BirdMediumSkeleton::new(), (vel.0.magnitude(), time), state.movement_time, @@ -516,7 +516,7 @@ impl FigureMgr { &mut movement_animation_rate, skeleton_attr, ), - Jump => anim::fish_medium::JumpAnimation::update_skeleton( + Jump(_) => anim::fish_medium::JumpAnimation::update_skeleton( &FishMediumSkeleton::new(), (vel.0.magnitude(), time), state.movement_time, @@ -571,7 +571,7 @@ impl FigureMgr { &mut movement_animation_rate, skeleton_attr, ), - Jump => anim::dragon::JumpAnimation::update_skeleton( + Jump(_) => anim::dragon::JumpAnimation::update_skeleton( &DragonSkeleton::new(), (vel.0.magnitude(), time), state.movement_time, @@ -626,7 +626,7 @@ impl FigureMgr { &mut movement_animation_rate, skeleton_attr, ), - Jump => anim::bird_small::JumpAnimation::update_skeleton( + Jump(_) => anim::bird_small::JumpAnimation::update_skeleton( &BirdSmallSkeleton::new(), (vel.0.magnitude(), time), state.movement_time, @@ -681,7 +681,7 @@ impl FigureMgr { &mut movement_animation_rate, skeleton_attr, ), - Jump => anim::fish_small::JumpAnimation::update_skeleton( + Jump(_) => anim::fish_small::JumpAnimation::update_skeleton( &FishSmallSkeleton::new(), (vel.0.magnitude(), time), state.movement_time, @@ -736,7 +736,7 @@ impl FigureMgr { &mut movement_animation_rate, skeleton_attr, ), - Jump => anim::biped_large::JumpAnimation::update_skeleton( + Jump(_) => anim::biped_large::JumpAnimation::update_skeleton( &BipedLargeSkeleton::new(), (vel.0.magnitude(), time), state.movement_time,