use anyhow::Result; use crate::{GameState, Notes}; use crate::notes::{Area, Step}; pub struct NotesState<'a> { notes: &'a Notes, last_printed_location: u16, last_stage: u16, last_location: u16, step_idx: usize, area_idx: usize, current_step: &'a Step, first_step: bool, force_print: bool, } impl<'a> NotesState<'a> { pub fn new(notes: &'a Notes, game: &mut GameState) -> Result { game.refresh()?; // find first step with a matching story stage let steps = notes.steps .iter() .take_while(|step| step.stage <= game.story) .count(); let (step, step_idx, force) = if steps <= 1 { // nothing previous OR first step (¬es.steps[0], 0, false) } else { // in progress (¬es.steps[steps - 1], steps - 1, true) }; // find first area that matches let area_idx = step.areas .iter() .position(|area| area.area == 0 || area.area == game.location) .unwrap_or(0); Ok(Self { notes, last_printed_location: 0, last_stage: 0, last_location: 0, step_idx, area_idx, current_step: step, first_step: true, force_print: force, }) } pub fn tick(&mut self, game: &mut GameState) -> Result<()> { self.last_stage = game.story; self.last_location = game.location; game.refresh()?; let stage_changed = self.last_stage != game.story; let location_changed = self.last_location != game.location; let step_advanced = stage_changed && self.change_step(game); let area = match self.area() { Some(area) => area.clone(), None => return Ok(()), }; if self.force_print || ((step_advanced || location_changed) && (game.location == area.area || area.area == 0)) { if self.last_printed_location != game.location { self.last_printed_location = game.location; println!("{}", game.location_name().unwrap_or("Unknown Location")) } println!("{}", area.steps); self.area_idx += 1; if self.first_step { self.first_step = false; self.step_idx += 1; if !self.force_print { self.area_idx = 0; } } if self.force_print { self.force_print = false; } } Ok(()) } fn area(&self) -> Option<&Area> { self.current_step.areas.get(self.area_idx) } fn change_step(&mut self, game: &mut GameState) -> bool { let next = match self.notes.steps.get(self.step_idx) { Some(step) => step, None => return false, }; if next.stage == game.story { self.current_step = next; self.step_idx += 1; self.area_idx = 0; return true; } false } }