use instant::Instant; use std::time::Duration; use bracket_lib::prelude::*; use hecs::{Entity, World}; use crate::{ components::{monster::damage_for_kind, Monster, Position, WantsToWhip}, resources::Resources, tile_data::TileType, }; pub fn run(world: &mut World, resources: &mut Resources) { let mut to_kill: Vec = Vec::new(); let mut to_remove: Vec = Vec::new(); for (entity, (position, mut wants_to_whip)) in &mut world.query::<(&Position, &mut WantsToWhip)>() { resources.stop_clock = 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 resources.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) = resources.map.get_tile_content_at(dest) { if let Ok(monster) = world.get::<&Monster>(e) { resources.stats.add_score(damage_for_kind(monster.kind)); to_kill.push(e); resources.map.clear_tile_content_at(dest); if let (Some(sound_effects), Some(sound_output)) = (&mut resources.sound_effects, &mut resources.sound_output) { sound_output.play_sound(sound_effects.whipping_hit_enemy.clone()); } switch_to_hit_sound(resources, wants_to_whip); } } else { hit_tile(resources, wants_to_whip, dest); } } if wants_to_whip.frame < 7 { wants_to_whip.frame += 1; wants_to_whip.last_frame = now; } else { to_remove.push(entity); resources.stop_clock = false; if let Some(sound) = &mut wants_to_whip.sound { sound.control::, _>().stop(); wants_to_whip.sound = None; } } } } for e in to_kill { let _ = world.despawn(e); } for e in to_remove { let _ = world.remove_one::(e); } } fn hit_tile(resources: &mut Resources, wants_to_whip: &mut WantsToWhip, location: Point) { let tile = resources.map.get_tile_at(location); match tile { TileType::Block | TileType::Tree => { let mut rng = RandomNumberGenerator::new(); if (rng.range(0, 7) as u32) < resources.stats.whip_power { resources.map.set_tile_at(location, TileType::Floor); if let (Some(sound_effects), Some(sound_output)) = (&mut resources.sound_effects, &mut resources.sound_output) { sound_output.play_sound(sound_effects.whipping_hit_block.clone()); } switch_to_hit_sound(resources, wants_to_whip); } } TileType::Forest => todo!(), _ => (), } } fn switch_to_hit_sound(resources: &mut Resources, wants_to_whip: &mut WantsToWhip) { if let Some(sound) = &mut wants_to_whip.sound { sound.control::, _>().stop(); } if let (Some(sound_effects), Some(sound_output)) = (&mut resources.sound_effects, &mut resources.sound_output) { wants_to_whip.sound = Some(sound_output.play_sound(sound_effects.whipping_hit.clone())); } }