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 = 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::, _>().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::, _>().stop(); wants_to_whip.sound = None; } } } } for entity in entities_to_remove { wants_to_whips.remove(entity); } } }