ffxii-tza-auto-notes/src/notes_state.rs

112 lines
3.1 KiB
Rust

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<Self> {
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
(&notes.steps[0], 0, false)
} else {
// in progress
(&notes.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
}
}