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, last_stage: u16, last_location: u32, pub step_idx: Option, pub area_idx: usize, current_step: Step, } impl NotesState { pub fn new(notes: 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.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 { 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 } }