use super::*;
impl StorySystem {
pub(super) fn start(&mut self, ctx: &mut PipelineContext) {
self.started = true;
self.vars.clear();
self.history.clear();
self.auto = false;
self.skip = false;
self.hold_skip = false;
self.overlay = Overlay::None;
self.exit_choice_ui(ctx);
let screen = self.ids.as_ref().expect("resolved at init").screen;
if self.active_screen != Some(screen) {
ctx.events_mut::<ScreenCommand>()
.send(ScreenCommand::Show(screen));
}
self.enter_node(0, ctx);
}
pub(super) fn continue_story(&mut self, ctx: &mut PipelineContext) {
let save = if self.story.save_key.is_empty() {
None
} else {
self.save_dir
.as_deref()
.and_then(|dir| read_save(&save_file(dir)))
};
match save {
Some(save) => self.resume_from(save, ctx),
None => self.start(ctx),
}
}
pub(super) fn resume_from(&mut self, save: StorySave, ctx: &mut PipelineContext) {
let Some(node) = self.story.nodes.iter().position(|n| n.slug == save.slug) else {
self.start(ctx);
return;
};
if self.story.nodes[node].pages.is_empty() {
self.start(ctx);
return;
}
self.started = true;
self.vars = save.vars.into_iter().collect();
self.history.clear();
self.overlay = Overlay::None;
self.exit_choice_ui(ctx);
let screen = self.ids.as_ref().expect("resolved at init").screen;
if self.active_screen != Some(screen) {
ctx.events_mut::<ScreenCommand>()
.send(ScreenCommand::Show(screen));
}
self.node = node;
self.page = (save.page as usize).min(self.story.nodes[node].pages.len() - 1);
self.apply_page(ctx);
}
pub(super) fn current_save(&self) -> StorySave {
StorySave {
slug: self.story.nodes[self.node].slug.clone(),
page: self.page as u32,
vars: self.vars.iter().map(|(k, v)| (k.clone(), *v)).collect(),
}
}
pub(super) fn persist_position(&mut self, _ctx: &mut PipelineContext) {
if self.story.save_key.is_empty() {
return;
}
let Some(dir) = self.save_dir.as_deref() else {
return;
};
let save = self.current_save();
if let Err(e) = write_save(&save_file(dir), &save) {
tracing::warn!("StorySystem: save failed: {e}");
}
}
pub(super) fn clear_save(&mut self, _ctx: &mut PipelineContext) {
if self.story.save_key.is_empty() {
return;
}
if let Some(dir) = self.save_dir.as_deref() {
let _ = std::fs::remove_file(save_file(dir));
}
}
pub(super) fn any_slot_save(&self) -> bool {
!self.story.save_key.is_empty()
&& self
.save_dir
.as_deref()
.is_some_and(|dir| (0..SLOT_COUNT).any(|i| slot_file(dir, i).exists()))
}
}