use crate::{ components::{ monster::{self, damage_for_kind, sound_effect_for_kind, ticks_for_kind}, Monster, Player, Position, Renderable, }, resources::{Clock, Map, SoundEffects, SoundOutput, Stats}, tile_data::TileType, }; use bracket_lib::{prelude::*, random::RandomNumberGenerator}; use specs::prelude::*; pub struct MonsterAiSystem {} #[allow(clippy::type_complexity)] impl<'a> System<'a> for MonsterAiSystem { type SystemData = ( Entities<'a>, ReadExpect<'a, Clock>, WriteExpect<'a, Map>, WriteExpect<'a, Stats>, ReadExpect<'a, SoundEffects>, WriteExpect<'a, SoundOutput>, WriteStorage<'a, Monster>, WriteStorage<'a, Position>, WriteStorage<'a, Renderable>, ReadStorage<'a, Player>, ); fn run( &mut self, ( entities, clock, mut map, mut stats, sound_effects, mut sound_output, mut monsters, mut positions, mut renderables, players, ): Self::SystemData, ) { let mut player_position = None; for (_entity, _player, position) in (&entities, &players, &positions).join() { player_position = Some(Point::from(*position)); } if let Some(player_pos) = player_position { let mut data = (&entities, &mut monsters, &mut positions, &mut renderables) .join() .collect::>(); for (entity, monster, position, renderable) in &mut data { if clock.has_ticked { monster.ticks_until_move -= 1; if monster.ticks_until_move <= 0 { // Change glyph let mut rng = RandomNumberGenerator::new(); if let Some(glyph) = rng.random_slice_entry(&monster::glyphs_for_kind(monster.kind)) { renderable.glyph = *glyph; } // Move monster let (mut delta_x, mut delta_y) = (0, 0); if player_pos.x < position.x { delta_x = -1; } if player_pos.x > position.x { delta_x = 1; } if player_pos.y < position.y { delta_y = -1; } if player_pos.y > position.y { delta_y = 1; } let destination = Point { x: position.x + delta_x, y: position.y + delta_y, }; if let Some(e) = map.get_tile_content_at(destination) { if let Some(_player) = players.get(e) { // TODO: Sound map.clear_tile_content_at(Point::from(**position)); stats.take_gems(damage_for_kind(monster.kind)); sound_output.play_sound(sound_effect_for_kind( monster.kind, &sound_effects, )); let _ = entities.delete(*entity); } } else { let tile = map.get_tile_at_mut(destination); match tile { TileType::Wall => {} TileType::Block => { // TODO: Sound *tile = TileType::Floor; let _ = entities.delete(*entity); } _ => { map.clear_tile_content_at(Point::from(**position)); position.x = destination.x; position.y = destination.y; map.set_tile_content_at(destination, *entity); } } } monster.ticks_until_move = ticks_for_kind(monster.kind); } } } } } }