kroz-rs/src/systems/whip.rs
2022-11-23 23:57:14 -05:00

143 lines
5 KiB
Rust

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<Entity> = Vec::new();
let mut to_remove: Vec<Entity> = 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::<oddio::Stop<_>, _>().stop();
wants_to_whip.sound = None;
}
}
}
}
for e in to_kill {
let _ = world.despawn(e);
}
for e in to_remove {
let _ = world.remove_one::<WantsToWhip>(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::<oddio::Stop<_>, _>().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()));
}
}