veloren/common/src/sys/controller.rs

151 lines
4.7 KiB
Rust
Raw Normal View History

use crate::{
comp::{
ActionState::*, Body, CharacterState, Controller, MovementState::*, PhysicsState, Stats,
Vel,
},
event::{Event, EventBus},
2019-06-09 14:20:20 +00:00
};
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
use std::time::Duration;
2019-06-09 14:20:20 +00:00
2019-06-09 19:33:20 +00:00
/// This system is responsible for validating controller inputs
2019-06-09 14:20:20 +00:00
pub struct Sys;
impl<'a> System<'a> for Sys {
type SystemData = (
Entities<'a>,
Read<'a, EventBus>,
2019-07-21 16:50:13 +00:00
WriteStorage<'a, Controller>,
2019-06-09 14:20:20 +00:00
ReadStorage<'a, Stats>,
2019-08-04 08:21:29 +00:00
ReadStorage<'a, Body>,
2019-06-13 18:09:50 +00:00
ReadStorage<'a, Vel>,
ReadStorage<'a, PhysicsState>,
WriteStorage<'a, CharacterState>,
2019-06-09 14:20:20 +00:00
);
fn run(
&mut self,
(
entities,
event_bus,
2019-07-21 16:50:13 +00:00
mut controllers,
2019-06-09 14:20:20 +00:00
stats,
2019-08-04 08:21:29 +00:00
bodies,
2019-06-13 18:09:50 +00:00
velocities,
physics_states,
mut character_states,
2019-06-09 14:20:20 +00:00
): Self::SystemData,
) {
let mut event_emitter = event_bus.emitter();
for (entity, controller, stats, body, vel, physics, mut character) in (
2019-06-09 14:20:20 +00:00
&entities,
2019-07-21 16:50:13 +00:00
&mut controllers,
2019-06-09 14:20:20 +00:00
&stats,
2019-08-04 08:21:29 +00:00
&bodies,
2019-06-13 18:09:50 +00:00
&velocities,
&physics_states,
&mut character_states,
2019-06-09 14:20:20 +00:00
)
.join()
{
if stats.is_dead {
2019-06-09 19:33:20 +00:00
// Respawn
if controller.respawn {
event_emitter.emit(Event::Respawn(entity));
2019-06-09 19:33:20 +00:00
}
2019-06-09 14:20:20 +00:00
continue;
}
// Move
controller.move_dir = if controller.move_dir.magnitude_squared() > 1.0 {
controller.move_dir.normalized()
} else {
controller.move_dir
};
if character.movement == Stand && controller.move_dir.magnitude_squared() > 0.0 {
character.movement = Run;
} else if character.movement == Run && controller.move_dir.magnitude_squared() == 0.0 {
character.movement = Stand;
2019-06-16 15:40:47 +00:00
}
2019-08-24 19:12:54 +00:00
// Look
if controller
.look_dir
.map(|n| !n.is_normal() || n.abs() < std::f32::EPSILON)
.reduce_or()
{
controller.look_dir = controller.move_dir.into();
}
2019-06-09 19:33:20 +00:00
// Glide
if controller.glide
&& !physics.on_ground
&& (character.action == Idle || character.action.is_wield())
&& character.movement == Jump
// TODO: Ask zesterer if we can remove this
&& body.is_humanoid()
2019-08-04 08:21:29 +00:00
{
character.movement = Glide;
} else if !controller.glide && character.movement == Glide {
character.movement = Jump;
2019-06-09 14:20:20 +00:00
}
// Wield
if controller.attack
&& character.action == Idle
&& (character.movement == Stand || character.movement == Run)
{
character.action = Wield {
time_left: Duration::from_millis(300),
};
}
2019-06-09 14:20:20 +00:00
// Attack
if controller.attack
&& (character.movement == Stand
|| character.movement == Run
|| character.movement == Jump)
{
// TODO: Check if wield ability exists
if let Wield { time_left } = character.action {
if time_left == Duration::default() {
character.action = Attack {
time_left: Duration::from_millis(300),
applied: false,
};
}
}
2019-06-09 14:20:20 +00:00
}
2019-06-11 04:08:55 +00:00
// Block
if controller.block
&& (character.movement == Stand || character.movement == Run)
&& (character.action == Idle || character.action.is_wield())
{
character.action = Block {
time_left: Duration::from_secs(5),
};
} else if !controller.block && character.action.is_block() {
character.action = Idle;
}
2019-06-11 04:08:55 +00:00
// Roll
2019-06-29 20:40:40 +00:00
if controller.roll
&& (character.action == Idle || character.action.is_wield())
&& character.movement == Run
&& physics.on_ground
2019-06-29 20:40:40 +00:00
{
character.movement = Roll {
time_left: Duration::from_millis(600),
};
2019-06-30 17:48:38 +00:00
}
// Jump
if controller.jump && physics.on_ground && vel.0.z <= 0.0 {
event_emitter.emit(Event::Jump(entity));
2019-06-11 04:08:55 +00:00
}
2019-06-09 14:20:20 +00:00
}
}
}