monster_ai_system.rs 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. extern crate specs;
  2. use specs::prelude::*;
  3. use super::{Viewshed, Monster, Map, Position, WantsToMelee, RunState,
  4. Confusion, particle_system::ParticleBuilder, EntityMoved};
  5. extern crate rltk;
  6. use rltk::{Point};
  7. pub struct MonsterAI {}
  8. impl<'a> System<'a> for MonsterAI {
  9. #[allow(clippy::type_complexity)]
  10. type SystemData = ( WriteExpect<'a, Map>,
  11. ReadExpect<'a, Point>,
  12. ReadExpect<'a, Entity>,
  13. ReadExpect<'a, RunState>,
  14. Entities<'a>,
  15. WriteStorage<'a, Viewshed>,
  16. ReadStorage<'a, Monster>,
  17. WriteStorage<'a, Position>,
  18. WriteStorage<'a, WantsToMelee>,
  19. WriteStorage<'a, Confusion>,
  20. WriteExpect<'a, ParticleBuilder>,
  21. WriteStorage<'a, EntityMoved>);
  22. fn run(&mut self, data : Self::SystemData) {
  23. let (mut map, player_pos, player_entity, runstate, entities, mut viewshed,
  24. monster, mut position, mut wants_to_melee, mut confused, mut particle_builder,
  25. mut entity_moved) = data;
  26. if *runstate != RunState::MonsterTurn { return; }
  27. for (entity, mut viewshed,_monster,mut pos) in (&entities, &mut viewshed, &monster, &mut position).join() {
  28. let mut can_act = true;
  29. let is_confused = confused.get_mut(entity);
  30. if let Some(i_am_confused) = is_confused {
  31. i_am_confused.turns -= 1;
  32. if i_am_confused.turns < 1 {
  33. confused.remove(entity);
  34. }
  35. can_act = false;
  36. particle_builder.request(pos.x, pos.y, rltk::RGB::named(rltk::MAGENTA),
  37. rltk::RGB::named(rltk::BLACK), rltk::to_cp437('?'), 200.0);
  38. }
  39. if can_act {
  40. let distance = rltk::DistanceAlg::Pythagoras.distance2d(Point::new(pos.x, pos.y), *player_pos);
  41. if distance < 1.5 {
  42. wants_to_melee.insert(entity, WantsToMelee{ target: *player_entity }).expect("Unable to insert attack");
  43. }
  44. else if viewshed.visible_tiles.contains(&*player_pos) {
  45. // Path to the player
  46. let path = rltk::a_star_search(
  47. map.xy_idx(pos.x, pos.y) as i32,
  48. map.xy_idx(player_pos.x, player_pos.y) as i32,
  49. &mut *map
  50. );
  51. if path.success && path.steps.len()>1 {
  52. let mut idx = map.xy_idx(pos.x, pos.y);
  53. map.blocked[idx] = false;
  54. pos.x = path.steps[1] % map.width;
  55. pos.y = path.steps[1] / map.width;
  56. entity_moved.insert(entity, EntityMoved{}).expect("Unable to insert marker");
  57. idx = map.xy_idx(pos.x, pos.y);
  58. map.blocked[idx] = true;
  59. viewshed.dirty = true;
  60. }
  61. }
  62. }
  63. }
  64. }
  65. }