implement conditions on choices
This commit is contained in:
parent
d21f8b4b09
commit
2e57f911ed
103
src/chat.rs
103
src/chat.rs
|
@ -117,13 +117,29 @@ pub enum ChatEvent {
|
|||
DespawnAllChoices,
|
||||
DespawnAllChats,
|
||||
SpawnMessage(String, hud::LogLevel, String),
|
||||
SpawnChoice(String, usize, ChatPos, bool),
|
||||
SpawnChoice(String, usize, ChatPos, bool, Option<String>),
|
||||
RunScript(String),
|
||||
SleepSeconds(f64),
|
||||
SetVariable(String),
|
||||
GotoIf(String, ChatPos),
|
||||
}
|
||||
|
||||
pub struct Extracted {
|
||||
choice_text: Option<String>,
|
||||
nowait: bool,
|
||||
condition: Option<String>,
|
||||
}
|
||||
impl Default for Extracted {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
choice_text: None,
|
||||
nowait: false,
|
||||
condition: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This is the only place where any YAML interaction should be happening.
|
||||
#[derive(Resource)]
|
||||
pub struct ChatDB(Vec<Value>);
|
||||
|
@ -229,28 +245,38 @@ impl ChatDB {
|
|||
// Not acceptable:
|
||||
// - `"What's up?"`
|
||||
// - `{"goto": "foo"}`
|
||||
// Returns (choice text, sub-conversation branch, nowait flag)
|
||||
fn search_choice(&self, yaml: Option<&Value>) -> Option<(String, Value, bool)> {
|
||||
fn is_choice(&self, yaml: Option<&Value>) -> bool {
|
||||
if let Some(data) = self.extract(yaml) {
|
||||
return data.choice_text.is_some();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn extract(&self, yaml: Option<&Value>) -> Option<Extracted> {
|
||||
let non_choice_tokens = NON_CHOICE_TOKENS.to_vec();
|
||||
let mut result: Option<(String, Value, bool)> = None;
|
||||
let mut nowait = false;
|
||||
if let Some(Value::Mapping(map)) = yaml {
|
||||
let mut result: Extracted = Extracted::default();
|
||||
for (key, value) in map {
|
||||
if let Value::String(key) = key {
|
||||
if key == TOKEN_NOWAIT && value.as_bool() == Some(true) {
|
||||
nowait = true;
|
||||
result.nowait = true;
|
||||
}
|
||||
if non_choice_tokens.contains(&key.as_str()) {
|
||||
continue;
|
||||
else if key == TOKEN_IF {
|
||||
if let Some(condition) = value.as_str() {
|
||||
result.condition = Some(condition.to_string());
|
||||
}
|
||||
}
|
||||
if key.as_str().starts_with(TOKEN_IF_INLINE) {
|
||||
continue;
|
||||
else if non_choice_tokens.contains(&key.as_str()) {
|
||||
// skip over the other non-choice tokens
|
||||
}
|
||||
else {
|
||||
result.choice_text = Some(key.to_string());
|
||||
}
|
||||
result = Some((key.into(), map[key].clone(), nowait));
|
||||
}
|
||||
}
|
||||
return Some(result);
|
||||
}
|
||||
return result;
|
||||
return None;
|
||||
}
|
||||
|
||||
fn search_label_recursively(&self, sequence: &Value, label: &String, mut pos: ChatPos) -> Option<ChatPos> {
|
||||
|
@ -317,7 +343,7 @@ impl ChatDB {
|
|||
}
|
||||
},
|
||||
Some(Value::Mapping(map)) => {
|
||||
if seek_past_dialog_choices && self.search_choice(Some(&Value::Mapping(map))).is_some() {
|
||||
if seek_past_dialog_choices && self.is_choice(Some(&Value::Mapping(map))) {
|
||||
// we just dropped out of a branch and ended up in a dialog
|
||||
// choice. let's seek past all the choices until we find
|
||||
// the next non-dialog-choice item.
|
||||
|
@ -426,7 +452,7 @@ impl ChatDB {
|
|||
let mut sound = DEFAULT_SOUND.to_string();
|
||||
|
||||
// Is this a dialog choice?
|
||||
if let Some(_) = self.search_choice(Some(&Value::Mapping(map.clone()))) {
|
||||
if self.is_choice(Some(&Value::Mapping(map.clone()))) {
|
||||
processed_a_choice = true;
|
||||
}
|
||||
|
||||
|
@ -542,16 +568,21 @@ impl ChatDB {
|
|||
// Spawn choices until we reach a non-choice item or the end of the branch
|
||||
let mut key: usize = 0;
|
||||
let mut reached_end_of_branch = false;
|
||||
while let Some((choice, _, nowait)) =
|
||||
self.search_choice(self.at(chat.internal_id, &chat.position).as_ref()) {
|
||||
if reached_end_of_branch {
|
||||
while let Some(data) = self.extract(self.at(chat.internal_id, &chat.position).as_ref()) {
|
||||
if let Some(choice_text) = data.choice_text {
|
||||
if reached_end_of_branch {
|
||||
break;
|
||||
}
|
||||
let mut goto: Vec<usize> = chat.position.clone();
|
||||
goto.push(0);
|
||||
event.send(ChatEvent::SpawnChoice(choice_text,
|
||||
key, goto, data.nowait, data.condition));
|
||||
key += 1;
|
||||
reached_end_of_branch = self.advance_pointer(chat);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
let mut goto: Vec<usize> = chat.position.clone();
|
||||
goto.push(0);
|
||||
event.send(ChatEvent::SpawnChoice(choice, key, goto, nowait));
|
||||
key += 1;
|
||||
reached_end_of_branch = self.advance_pointer(chat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -661,17 +692,25 @@ pub fn handle_chat_events(
|
|||
let sfx = audio::str2sfx(sound);
|
||||
ew_sfx.send(audio::PlaySfxEvent(sfx));
|
||||
}
|
||||
ChatEvent::SpawnChoice(replytext, key, goto, nowait) => {
|
||||
commands.spawn((
|
||||
world::DespawnOnPlayerDeath,
|
||||
Choice {
|
||||
text: replytext.into(),
|
||||
key: *key,
|
||||
goto: goto.clone(),
|
||||
ChatEvent::SpawnChoice(replytext, key, goto, nowait, condition) => {
|
||||
'out: {
|
||||
dbg!(condition);
|
||||
if let Some(condition) = condition {
|
||||
if !vars.evaluate_condition(condition, &chat.talker.actor_id) {
|
||||
break 'out;
|
||||
}
|
||||
}
|
||||
commands.spawn((
|
||||
world::DespawnOnPlayerDeath,
|
||||
Choice {
|
||||
text: replytext.into(),
|
||||
key: *key,
|
||||
goto: goto.clone(),
|
||||
}
|
||||
));
|
||||
if !nowait {
|
||||
chat.timer = now + CHOICE_TIMER / settings.chat_speed as f64;
|
||||
}
|
||||
));
|
||||
if !nowait {
|
||||
chat.timer = now + CHOICE_TIMER / settings.chat_speed as f64;
|
||||
}
|
||||
}
|
||||
ChatEvent::RunScript(script) => {
|
||||
|
|
Loading…
Reference in a new issue