2019-08-26 18:05:30 +00:00
|
|
|
use super::{
|
|
|
|
combat::{ATTACK_DURATION, WIELD_DURATION},
|
|
|
|
movement::ROLL_DURATION,
|
|
|
|
};
|
2019-08-23 10:11:37 +00:00
|
|
|
use crate::{
|
|
|
|
comp::{
|
2019-08-28 20:47:52 +00:00
|
|
|
item, ActionState::*, Body, CharacterState, Controller, Item, MovementState::*,
|
|
|
|
PhysicsState, Stats, Vel,
|
2019-08-23 10:11:37 +00:00
|
|
|
},
|
2019-08-25 16:48:12 +00:00
|
|
|
event::{EventBus, LocalEvent, ServerEvent},
|
2019-06-09 14:20:20 +00:00
|
|
|
};
|
2019-08-23 10:11:37 +00:00
|
|
|
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
|
|
|
use std::time::Duration;
|
2019-08-29 17:39:34 +00:00
|
|
|
use vek::*;
|
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>,
|
2019-08-25 14:49:54 +00:00
|
|
|
Read<'a, EventBus<ServerEvent>>,
|
|
|
|
Read<'a, EventBus<LocalEvent>>,
|
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>,
|
2019-08-23 10:11:37 +00:00
|
|
|
ReadStorage<'a, PhysicsState>,
|
|
|
|
WriteStorage<'a, CharacterState>,
|
2019-06-09 14:20:20 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
fn run(
|
|
|
|
&mut self,
|
|
|
|
(
|
|
|
|
entities,
|
2019-08-25 14:49:54 +00:00
|
|
|
server_bus,
|
|
|
|
local_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,
|
2019-08-23 10:11:37 +00:00
|
|
|
physics_states,
|
|
|
|
mut character_states,
|
2019-06-09 14:20:20 +00:00
|
|
|
): Self::SystemData,
|
|
|
|
) {
|
2019-08-25 14:49:54 +00:00
|
|
|
let mut server_emitter = server_bus.emitter();
|
|
|
|
let mut local_emitter = local_bus.emitter();
|
2019-08-23 10:11:37 +00:00
|
|
|
|
|
|
|
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,
|
2019-08-23 10:11:37 +00:00
|
|
|
&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 {
|
2019-08-25 14:49:54 +00:00
|
|
|
server_emitter.emit(ServerEvent::Respawn(entity));
|
2019-06-09 19:33:20 +00:00
|
|
|
}
|
2019-06-09 14:20:20 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-08-23 10:11:37 +00:00
|
|
|
// 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
|
2019-08-25 16:08:00 +00:00
|
|
|
controller.look_dir = controller
|
2019-08-24 19:12:54 +00:00
|
|
|
.look_dir
|
2019-08-25 16:08:00 +00:00
|
|
|
.try_normalized()
|
|
|
|
.unwrap_or(controller.move_dir.into());
|
2019-08-24 19:12:54 +00:00
|
|
|
|
2019-06-09 19:33:20 +00:00
|
|
|
// Glide
|
2019-08-25 19:14:10 +00:00
|
|
|
// TODO: Check for glide ability/item
|
2019-08-23 10:11:37 +00:00
|
|
|
if controller.glide
|
|
|
|
&& !physics.on_ground
|
|
|
|
&& (character.action == Idle || character.action.is_wield())
|
|
|
|
&& character.movement == Jump
|
|
|
|
&& body.is_humanoid()
|
2019-08-04 08:21:29 +00:00
|
|
|
{
|
2019-08-23 10:11:37 +00:00
|
|
|
character.movement = Glide;
|
|
|
|
} else if !controller.glide && character.movement == Glide {
|
|
|
|
character.movement = Jump;
|
2019-06-09 14:20:20 +00:00
|
|
|
}
|
|
|
|
|
2019-07-06 19:00:05 +00:00
|
|
|
// Wield
|
2019-08-30 22:13:45 +00:00
|
|
|
if controller.primary
|
2019-08-23 10:11:37 +00:00
|
|
|
&& character.action == Idle
|
|
|
|
&& (character.movement == Stand || character.movement == Run)
|
|
|
|
{
|
|
|
|
character.action = Wield {
|
2019-08-26 18:05:30 +00:00
|
|
|
time_left: WIELD_DURATION,
|
2019-08-23 10:11:37 +00:00
|
|
|
};
|
2019-07-06 19:00:05 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 20:47:52 +00:00
|
|
|
match stats.equipment.main {
|
|
|
|
Some(Item::Tool { .. }) => {
|
|
|
|
// Attack
|
2019-08-30 22:13:45 +00:00
|
|
|
if controller.primary
|
2019-08-28 20:47:52 +00:00
|
|
|
&& (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: ATTACK_DURATION,
|
|
|
|
applied: false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Block
|
2019-08-30 22:13:45 +00:00
|
|
|
if controller.secondary
|
2019-08-28 20:47:52 +00:00
|
|
|
&& (character.movement == Stand || character.movement == Run)
|
|
|
|
&& (character.action == Idle || character.action.is_wield())
|
|
|
|
{
|
|
|
|
character.action = Block {
|
|
|
|
time_left: Duration::from_secs(5),
|
2019-08-23 10:11:37 +00:00
|
|
|
};
|
2019-08-30 22:13:45 +00:00
|
|
|
} else if !controller.secondary && character.action.is_block() {
|
2019-08-28 20:47:52 +00:00
|
|
|
character.action = Idle;
|
2019-08-23 10:11:37 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-29 17:42:25 +00:00
|
|
|
Some(Item::Debug(item::Debug::Boost)) => {
|
2019-08-30 22:13:45 +00:00
|
|
|
if controller.primary {
|
2019-08-28 20:47:52 +00:00
|
|
|
local_emitter.emit(LocalEvent::Boost {
|
|
|
|
entity,
|
2019-08-29 17:39:34 +00:00
|
|
|
vel: controller.look_dir * 7.0,
|
|
|
|
});
|
|
|
|
}
|
2019-08-30 22:13:45 +00:00
|
|
|
if controller.secondary {
|
2019-08-29 17:39:34 +00:00
|
|
|
// Go upward
|
|
|
|
local_emitter.emit(LocalEvent::Boost {
|
|
|
|
entity,
|
2019-08-30 22:08:44 +00:00
|
|
|
vel: Vec3::new(0.0, 0.0, 7.0),
|
2019-08-28 20:47:52 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
2019-08-24 16:38:59 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 04:08:55 +00:00
|
|
|
// Roll
|
2019-06-29 20:40:40 +00:00
|
|
|
if controller.roll
|
2019-08-23 10:11:37 +00:00
|
|
|
&& (character.action == Idle || character.action.is_wield())
|
|
|
|
&& character.movement == Run
|
|
|
|
&& physics.on_ground
|
2019-06-29 20:40:40 +00:00
|
|
|
{
|
2019-08-23 10:11:37 +00:00
|
|
|
character.movement = Roll {
|
2019-08-26 18:05:30 +00:00
|
|
|
time_left: ROLL_DURATION,
|
2019-08-23 10:11:37 +00:00
|
|
|
};
|
2019-06-30 17:48:38 +00:00
|
|
|
}
|
2019-08-25 16:48:12 +00:00
|
|
|
|
2019-06-30 17:48:38 +00:00
|
|
|
// Jump
|
2019-08-23 10:11:37 +00:00
|
|
|
if controller.jump && physics.on_ground && vel.0.z <= 0.0 {
|
2019-08-25 14:49:54 +00:00
|
|
|
local_emitter.emit(LocalEvent::Jump(entity));
|
2019-06-11 04:08:55 +00:00
|
|
|
}
|
2019-06-09 14:20:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|