kroz-rs/src/systems/whip_system.rs

135 lines
4.8 KiB
Rust

use std::time::{Duration, Instant};
use bracket_lib::prelude::*;
use specs::prelude::*;
use crate::{
components::{monster::damage_for_kind, Monster, Position, WantsToWhip},
resources::{Map, SoundEffects, SoundOutput, Stats, StopClock},
};
pub struct WhipSystem {}
#[allow(clippy::type_complexity)]
impl<'a> System<'a> for WhipSystem {
type SystemData = (
WriteExpect<'a, Map>,
WriteExpect<'a, StopClock>,
WriteExpect<'a, SoundOutput>,
ReadExpect<'a, SoundEffects>,
WriteExpect<'a, Stats>,
ReadStorage<'a, Position>,
WriteStorage<'a, WantsToWhip>,
WriteStorage<'a, Monster>,
Entities<'a>,
);
fn run(&mut self, data: Self::SystemData) {
let (
mut map,
mut stop_clock,
mut sound_output,
sound_effects,
mut stats,
positions,
mut wants_to_whips,
monsters,
entities,
) = data;
let mut entities_to_remove: Vec<Entity> = vec![];
for (entity, position, mut wants_to_whip) in
(&entities, &positions, &mut wants_to_whips).join()
{
stop_clock.0 = true;
let now = Instant::now();
if now - wants_to_whip.last_frame > Duration::from_secs_f32(0.1) {
let destination = loop {
let destination = match wants_to_whip.frame {
0 => Some(Point {
x: position.x - 1,
y: position.y - 1,
}),
1 => Some(Point {
x: position.x - 1,
y: position.y,
}),
2 => Some(Point {
x: position.x - 1,
y: position.y + 1,
}),
3 => Some(Point {
x: position.x,
y: position.y + 1,
}),
4 => Some(Point {
x: position.x + 1,
y: position.y + 1,
}),
5 => Some(Point {
x: position.x + 1,
y: position.y,
}),
6 => Some(Point {
x: position.x + 1,
y: position.y - 1,
}),
7 => Some(Point {
x: position.x,
y: position.y - 1,
}),
_ => None,
};
if let Some(dest) = destination {
if map.in_bounds(dest) {
break destination;
}
wants_to_whip.frame += 1;
if wants_to_whip.frame > 7 {
break None;
}
}
};
if let Some(dest) = destination {
if let Some(e) = map.get_tile_content_at(dest) {
if let Some(monster) = monsters.get(e) {
stats.add_score(damage_for_kind(monster.kind));
let _ = entities.delete(e);
map.clear_tile_content_at(dest);
if let Some(sound) = &mut wants_to_whip.sound {
sound.control::<oddio::Stop<_>, _>().stop();
}
if wants_to_whip.frame == 7 {
wants_to_whip.sound = None;
sound_output.play_sound(sound_effects.whipping_hit_end.clone());
} else {
wants_to_whip.sound = Some(
sound_output.play_sound(sound_effects.whipping_hit.clone()),
);
}
}
}
}
if wants_to_whip.frame < 7 {
wants_to_whip.frame += 1;
wants_to_whip.last_frame = now;
} else {
entities_to_remove.push(entity);
stop_clock.0 = false;
if let Some(sound) = &mut wants_to_whip.sound {
sound.control::<oddio::Stop<_>, _>().stop();
wants_to_whip.sound = None;
}
}
}
}
for entity in entities_to_remove {
wants_to_whips.remove(entity);
}
}
}