143 lines
5 KiB
Rust
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()));
|
|
}
|
|
}
|