diff options
| -rw-r--r-- | dungeon/src/entity.rs | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/dungeon/src/entity.rs b/dungeon/src/entity.rs index 3463618..794ef05 100644 --- a/dungeon/src/entity.rs +++ b/dungeon/src/entity.rs @@ -320,15 +320,24 @@ impl Updater<'_> { fn update_enemy_ai(&mut self, entity: &mut Entity, ai: &mut EnemyMoveState) { use EnemyMoveState as State; - // get the position in front - let front_pos = entity.pos.step(entity.dir).unwrap_or(entity.pos); + // get the next position this entity may be moving to. + // + // we want to be able to short circut past pathed movement + // if we generate a new path, without allowing the entity to move + // off grid! thus this is the best position to start the new + // movement from :) + let next_pos = entity + .in_front() + .filter(|pos| self.floor.get(*pos).is_walkable()) + .or(entity.moving_to) + .unwrap_or(entity.pos); // check if player is in range if !matches!(ai, State::Attack { .. }) - && let Some(m_state) = State::attack(front_pos, self.player_pos, self.floor) + && let Some(m_state) = State::attack(next_pos, self.player_pos, self.floor) { *ai = m_state; - entity.moving_to = Some(front_pos); + entity.moving_to = Some(next_pos); return; } @@ -339,8 +348,8 @@ impl Updater<'_> { return; } - *ai = State::roam(entity.pos, self.floor, self.rng); - entity.moving_to = Some(front_pos); + *ai = State::roam(next_pos, self.floor, self.rng); + entity.moving_to = Some(next_pos); } State::Roam(moves) => { if moves.is_empty() { @@ -354,9 +363,9 @@ impl Updater<'_> { } State::Attack(moves, old_player_pos) => { if *old_player_pos != self.player_pos { - *ai = State::attack(front_pos, self.player_pos, self.floor) + *ai = State::attack(next_pos, self.player_pos, self.floor) .unwrap_or_default(); - entity.moving_to = Some(front_pos); + entity.moving_to = Some(next_pos); return; } *old_player_pos = self.player_pos; |