2019-05-17 20:47:58 +00:00
|
|
|
use crate::{
|
2019-11-20 18:31:36 +00:00
|
|
|
comp::{ActionState, CharacterState, Energy, EnergySource, HealthSource, Stats},
|
2020-01-11 04:08:33 +00:00
|
|
|
event::{EventBus, ServerEvent},
|
2019-05-17 20:47:58 +00:00
|
|
|
state::DeltaTime,
|
|
|
|
};
|
2019-11-20 18:31:36 +00:00
|
|
|
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
|
|
|
|
2019-11-22 00:53:28 +00:00
|
|
|
const ENERGY_REGEN_ACCEL: f32 = 1.0;
|
2019-05-17 20:47:58 +00:00
|
|
|
|
2019-11-22 00:53:28 +00:00
|
|
|
/// This system kills players, levels them up, and regenerates energy.
|
2019-05-17 20:47:58 +00:00
|
|
|
pub struct Sys;
|
|
|
|
impl<'a> System<'a> for Sys {
|
|
|
|
type SystemData = (
|
|
|
|
Entities<'a>,
|
2019-05-19 20:14:18 +00:00
|
|
|
Read<'a, DeltaTime>,
|
2019-08-25 14:49:54 +00:00
|
|
|
Read<'a, EventBus<ServerEvent>>,
|
2019-11-20 18:31:36 +00:00
|
|
|
ReadStorage<'a, CharacterState>,
|
2019-05-19 20:14:18 +00:00
|
|
|
WriteStorage<'a, Stats>,
|
2019-11-20 18:31:36 +00:00
|
|
|
WriteStorage<'a, Energy>,
|
2019-05-17 20:47:58 +00:00
|
|
|
);
|
|
|
|
|
2019-11-20 18:31:36 +00:00
|
|
|
fn run(
|
|
|
|
&mut self,
|
|
|
|
(entities, dt, server_event_bus, character_states, mut stats,mut energies): Self::SystemData,
|
|
|
|
) {
|
2019-11-23 08:26:39 +00:00
|
|
|
let mut server_event_emitter = server_event_bus.emitter();
|
2019-08-23 10:11:37 +00:00
|
|
|
|
2019-12-01 21:54:21 +00:00
|
|
|
// Increment last change timer
|
|
|
|
stats.set_event_emission(false); // avoid unnecessary syncing
|
|
|
|
for stat in (&mut stats).join() {
|
|
|
|
stat.health.last_change.0 += f64::from(dt.0);
|
|
|
|
}
|
|
|
|
stats.set_event_emission(true);
|
|
|
|
|
2019-11-04 00:57:36 +00:00
|
|
|
// Mutates all stats every tick causing the server to resend this component for every entity every tick
|
2019-11-20 18:31:36 +00:00
|
|
|
for (entity, character_state, mut stats, energy) in (
|
|
|
|
&entities,
|
|
|
|
&character_states,
|
|
|
|
&mut stats.restrict_mut(),
|
|
|
|
&mut energies,
|
|
|
|
)
|
|
|
|
.join()
|
|
|
|
{
|
2019-12-01 21:54:21 +00:00
|
|
|
let (set_dead, level_up) = {
|
|
|
|
let stat = stats.get_unchecked();
|
|
|
|
(
|
|
|
|
stat.should_die() && !stat.is_dead,
|
|
|
|
stat.exp.current() >= stat.exp.maximum(),
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
if set_dead {
|
|
|
|
let stat = stats.get_mut_unchecked();
|
2019-11-23 08:26:39 +00:00
|
|
|
server_event_emitter.emit(ServerEvent::Destroy {
|
2019-05-27 19:41:24 +00:00
|
|
|
entity,
|
2019-10-17 20:59:36 +00:00
|
|
|
cause: stat.health.last_change.1.cause,
|
2019-08-23 10:11:37 +00:00
|
|
|
});
|
|
|
|
|
2019-05-27 17:45:43 +00:00
|
|
|
stat.is_dead = true;
|
2019-05-17 20:47:58 +00:00
|
|
|
}
|
2019-08-23 10:11:37 +00:00
|
|
|
|
2019-12-01 21:54:21 +00:00
|
|
|
if level_up {
|
|
|
|
let stat = stats.get_mut_unchecked();
|
2019-10-05 11:38:33 +00:00
|
|
|
while stat.exp.current() >= stat.exp.maximum() {
|
|
|
|
stat.exp.change_by(-(stat.exp.maximum() as i64));
|
|
|
|
stat.exp.change_maximum_by(25);
|
|
|
|
stat.level.change_by(1);
|
|
|
|
}
|
2019-11-23 08:26:39 +00:00
|
|
|
|
2019-10-08 16:12:08 +00:00
|
|
|
stat.update_max_hp();
|
2019-08-03 19:30:01 +00:00
|
|
|
stat.health
|
|
|
|
.set_to(stat.health.maximum(), HealthSource::LevelUp)
|
|
|
|
}
|
2019-11-20 18:31:36 +00:00
|
|
|
|
2019-11-22 00:53:28 +00:00
|
|
|
// Accelerate recharging energy if not wielding.
|
2019-11-20 18:31:36 +00:00
|
|
|
match character_state.action {
|
|
|
|
ActionState::Idle => {
|
2019-11-22 00:53:28 +00:00
|
|
|
energy.regen_rate += ENERGY_REGEN_ACCEL * dt.0;
|
|
|
|
energy.change_by(energy.regen_rate as i32, EnergySource::Regen);
|
2019-11-20 18:31:36 +00:00
|
|
|
}
|
2019-11-22 00:53:28 +00:00
|
|
|
// All other states do not regen and set the rate back to zero.
|
|
|
|
_ => energy.regen_rate = 0.0,
|
2019-11-20 18:31:36 +00:00
|
|
|
}
|
2019-05-17 20:47:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|