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

100 lines
2.7 KiB
Rust

use std::sync::Arc;
use anyhow::Result;
use druid::Data;
use crate::{GameState, Notes};
use crate::notes::{Area, Step};
#[derive(Clone, Data)]
pub struct NotesState {
pub notes: Arc<Notes>,
last_stage: u16,
last_location: u32,
pub step_idx: Option<usize>,
pub area_idx: usize,
current_step: Step,
}
impl NotesState {
pub fn new(notes: 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.stage)
.count();
let (step, step_idx) = if steps == 0 {
// nothing previous
(notes.steps[0].clone(), None)
} else {
// in progress
(notes.steps[steps - 1].clone(), Some(steps - 1))
};
// 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: Arc::new(notes),
last_stage: 0,
last_location: 0,
step_idx,
area_idx,
current_step: step,
})
}
pub fn tick(&mut self, game: &mut GameState) -> Result<bool> {
self.last_stage = game.stage;
self.last_location = game.location;
game.refresh()?;
let stage_changed = self.last_stage != game.stage;
let location_changed = self.last_location != game.location;
let step_advanced = stage_changed && self.change_step(game);
let mut highlight_changed = step_advanced;
let area = match self.next_area() {
Some(area) => area.clone(),
None => return Ok(highlight_changed),
};
if !step_advanced && location_changed && (game.location == area.area || area.area == 0) {
self.area_idx += 1;
highlight_changed = true;
}
Ok(highlight_changed)
}
fn area(&self) -> Option<&Area> {
self.current_step.areas.get(self.area_idx)
}
fn next_area(&self) -> Option<&Area> {
self.current_step.areas.get(self.area_idx + 1)
}
fn change_step(&mut self, game: &mut GameState) -> bool {
let idx = self.step_idx.map(|x| x + 1).unwrap_or(0);
let next = match self.notes.steps.get(idx) {
Some(step) => step,
None => return false,
};
if next.stage == game.stage {
self.current_step = next.clone();
self.step_idx = Some(idx);
self.area_idx = 0;
return true;
}
false
}
}