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

100 lines
2.7 KiB
Rust
Raw Normal View History

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