use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DialogueSystem {
pub dialogues: HashMap<String, Dialogue>,
pub current_dialogue: Option<String>,
pub current_node: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Dialogue {
pub id: String,
pub speaker: String,
pub nodes: Vec<DialogueNode>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DialogueNode {
pub text: String,
pub choices: Vec<DialogueChoice>,
pub next_node: Option<usize>,
pub triggers: Vec<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DialogueChoice {
pub text: String,
pub next_node: usize,
pub condition: Option<String>, }
impl DialogueSystem {
pub fn new() -> Self {
Self {
dialogues: HashMap::new(),
current_dialogue: None,
current_node: 0,
}
}
pub fn add_dialogue(&mut self, dialogue: Dialogue) {
self.dialogues.insert(dialogue.id.clone(), dialogue);
}
pub fn start_dialogue(&mut self, dialogue_id: &str) -> bool {
if self.dialogues.contains_key(dialogue_id) {
self.current_dialogue = Some(dialogue_id.to_string());
self.current_node = 0;
true
} else {
false
}
}
pub fn get_current_node(&self) -> Option<&DialogueNode> {
if let Some(dialogue_id) = &self.current_dialogue {
if let Some(dialogue) = self.dialogues.get(dialogue_id) {
return dialogue.nodes.get(self.current_node);
}
}
None
}
pub fn advance(&mut self) -> bool {
if let Some(node) = self.get_current_node() {
if let Some(next) = node.next_node {
self.current_node = next;
return true;
}
}
self.end_dialogue();
false
}
pub fn choose(&mut self, choice_index: usize) -> bool {
if let Some(node) = self.get_current_node() {
if let Some(choice) = node.choices.get(choice_index) {
self.current_node = choice.next_node;
return true;
}
}
false
}
pub fn end_dialogue(&mut self) {
self.current_dialogue = None;
self.current_node = 0;
}
pub fn is_active(&self) -> bool {
self.current_dialogue.is_some()
}
pub fn get_current_speaker(&self) -> Option<String> {
if let Some(dialogue_id) = &self.current_dialogue {
if let Some(dialogue) = self.dialogues.get(dialogue_id) {
return Some(dialogue.speaker.clone());
}
}
None
}
}
impl Default for DialogueSystem {
fn default() -> Self {
Self::new()
}
}
pub struct DialogueBuilder {
dialogue: Dialogue,
}
impl DialogueBuilder {
pub fn new(id: &str, speaker: &str) -> Self {
Self {
dialogue: Dialogue {
id: id.to_string(),
speaker: speaker.to_string(),
nodes: Vec::new(),
},
}
}
pub fn add_node(mut self, text: &str) -> Self {
self.dialogue.nodes.push(DialogueNode {
text: text.to_string(),
choices: Vec::new(),
next_node: None,
triggers: Vec::new(),
});
self
}
pub fn add_node_with_choices(mut self, text: &str, choices: Vec<(&str, usize)>) -> Self {
let choices: Vec<DialogueChoice> = choices
.into_iter()
.map(|(text, next)| DialogueChoice {
text: text.to_string(),
next_node: next,
condition: None,
})
.collect();
self.dialogue.nodes.push(DialogueNode {
text: text.to_string(),
choices,
next_node: None,
triggers: Vec::new(),
});
self
}
pub fn build(self) -> Dialogue {
self.dialogue
}
}