implement "set" token for chats

This commit is contained in:
yuni 2024-04-14 16:20:51 +02:00
parent 07be89162c
commit 5df3f66ea6
6 changed files with 54 additions and 17 deletions

View file

@ -78,7 +78,7 @@ type ChatPos = Vec<usize>;
#[derive(Component)] #[derive(Component)]
pub struct Chat { pub struct Chat {
pub id: usize, pub internal_id: usize,
pub position: ChatPos, pub position: ChatPos,
pub timer: f64, pub timer: f64,
pub talker: Talker, pub talker: Talker,
@ -94,7 +94,8 @@ pub struct Choice {
#[derive(Component)] #[derive(Component)]
#[derive(Clone)] #[derive(Clone)]
pub struct Talker { pub struct Talker {
pub conv_id: String, pub chat_name: String,
pub actor_id: String,
pub name: Option<String>, pub name: Option<String>,
pub pronoun: Option<String>, pub pronoun: Option<String>,
pub talking_speed: f32, pub talking_speed: f32,
@ -116,6 +117,7 @@ pub enum ChatEvent {
SpawnChoice(String, usize, ChatPos, bool), SpawnChoice(String, usize, ChatPos, bool),
RunScript(String), RunScript(String),
SleepSeconds(f64), SleepSeconds(f64),
SetVariable(String),
} }
// This is the only place where any YAML interaction should be happening. // This is the only place where any YAML interaction should be happening.
@ -297,7 +299,7 @@ impl ChatDB {
let mut popped = false; let mut popped = false;
let mut seek_past_dialog_choices = false; let mut seek_past_dialog_choices = false;
while chat.position.len() > 0 { while chat.position.len() > 0 {
match self.at(chat.id, &chat.position) { match self.at(chat.internal_id, &chat.position) {
None => { None => {
chat.position.pop(); chat.position.pop();
popped = true; popped = true;
@ -380,7 +382,7 @@ impl ChatDB {
// This includes flow control tokens like "goto", no-op tokens like "label", // This includes flow control tokens like "goto", no-op tokens like "label",
// but not something with a side effect like "script", and especially not "if". // but not something with a side effect like "script", and especially not "if".
fn is_skippable(&self, chat: &mut Chat) -> bool { fn is_skippable(&self, chat: &mut Chat) -> bool {
let current_item = self.at(chat.id, &chat.position); let current_item = self.at(chat.internal_id, &chat.position);
if current_item.is_none() { if current_item.is_none() {
return false; return false;
} }
@ -406,7 +408,7 @@ impl ChatDB {
chat: &mut Chat, chat: &mut Chat,
event: &mut EventWriter<ChatEvent>, event: &mut EventWriter<ChatEvent>,
) -> bool { ) -> bool {
let current_item = self.at(chat.id, &chat.position); let current_item = self.at(chat.internal_id, &chat.position);
let mut processed_a_choice = false; let mut processed_a_choice = false;
match current_item { match current_item {
Some(Value::String(message)) => { Some(Value::String(message)) => {
@ -452,7 +454,9 @@ impl ChatDB {
event.send(ChatEvent::SpawnMessage( event.send(ChatEvent::SpawnMessage(
message.to_string(), hud::LogLevel::Warning, sound.clone())); message.to_string(), hud::LogLevel::Warning, sound.clone()));
} }
(Some(TOKEN_SET), _) => {} // TODO (Some(TOKEN_SET), Value::String(instructions)) => {
event.send(ChatEvent::SetVariable(instructions.to_string()));
}
_ => {} _ => {}
} }
} }
@ -467,7 +471,7 @@ impl ChatDB {
} }
} }
(Some(TOKEN_GOTO), Value::String(label)) => { (Some(TOKEN_GOTO), Value::String(label)) => {
match self.search_label(chat.id, &label) { match self.search_label(chat.internal_id, &label) {
Some(pos) => { Some(pos) => {
chat.position = pos; chat.position = pos;
} }
@ -519,7 +523,7 @@ impl ChatDB {
let mut key: usize = 0; let mut key: usize = 0;
let mut reached_end_of_branch = false; let mut reached_end_of_branch = false;
while let Some((choice, _, nowait)) = while let Some((choice, _, nowait)) =
self.search_choice(self.at(chat.id, &chat.position).as_ref()) { self.search_choice(self.at(chat.internal_id, &chat.position).as_ref()) {
if reached_end_of_branch { if reached_end_of_branch {
break; break;
} }
@ -556,10 +560,10 @@ pub fn handle_new_conversations(
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Ping)); ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Ping));
return; return;
} }
match (*chatdb).get_chat_by_id(&event.talker.conv_id) { match (*chatdb).get_chat_by_id(&event.talker.chat_name) {
Ok(chat_id) => { Ok(chat_id) => {
let mut chat = Chat { let mut chat = Chat {
id: chat_id, internal_id: chat_id,
position: vec![0], position: vec![0],
timer: time.elapsed_seconds_f64(), timer: time.elapsed_seconds_f64(),
talker: event.talker.clone(), talker: event.talker.clone(),
@ -597,6 +601,7 @@ pub fn handle_chat_events(
mut ew_chatscript: EventWriter<ChatScriptEvent>, mut ew_chatscript: EventWriter<ChatScriptEvent>,
mut ew_sfx: EventWriter<audio::PlaySfxEvent>, mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
mut log: ResMut<hud::Log>, mut log: ResMut<hud::Log>,
mut vars: ResMut<var::GameVars>,
q_choices: Query<Entity, With<Choice>>, q_choices: Query<Entity, With<Choice>>,
mut q_chats: Query<(Entity, &mut Chat)>, mut q_chats: Query<(Entity, &mut Chat)>,
time: Res<Time>, time: Res<Time>,
@ -655,6 +660,13 @@ pub fn handle_chat_events(
ChatEvent::SleepSeconds(sleep_duration) => { ChatEvent::SleepSeconds(sleep_duration) => {
chat.timer = now + sleep_duration; chat.timer = now + sleep_duration;
} }
ChatEvent::SetVariable(string) => {
if let Some((key, value)) = string.split_once(" ") {
vars.set_in_scope(&chat.talker.actor_id, key, value.into());
} else {
vars.set_in_scope(&chat.talker.actor_id, string, "".into());
}
}
} }
} }
} }

View file

@ -18,6 +18,7 @@
- chat: Icarus - chat: Icarus
- Oh hey, you're awake! - Oh hey, you're awake!
- set: talked_before
- I found you drifting out cold, and thought, I better watch over you. - I found you drifting out cold, and thought, I better watch over you.
- Took us here behind that moonlet, to shield you from the micros. - Took us here behind that moonlet, to shield you from the micros.
- Thank you!: - Thank you!:

View file

@ -692,7 +692,8 @@ fn spawn_entities(
} }
if !state.chat.is_empty() { if !state.chat.is_empty() {
actor.insert(chat::Talker { actor.insert(chat::Talker {
conv_id: state.chat.clone(), actor_id: state.id.clone(),
chat_name: state.chat.clone(),
name: state.name.clone(), name: state.name.clone(),
pronoun: Some(state.pronoun.clone()), pronoun: Some(state.pronoun.clone()),
talking_speed: 1.0, talking_speed: 1.0,

View file

@ -199,6 +199,7 @@ actor -3300 10 0 pizzeria
actor 60 -15 -40 suit actor 60 -15 -40 suit
relativeto player relativeto player
name Icarus name Icarus
id Icarus
chatid Icarus chatid Icarus
alive yes alive yes
scale 2 scale 2

View file

@ -48,6 +48,7 @@ impl Plugin for OutFlyPlugin {
app.add_systems(Startup, setup); app.add_systems(Startup, setup);
app.add_systems(Update, handle_input); app.add_systems(Update, handle_input);
app.insert_resource(var::Settings::default()); app.insert_resource(var::Settings::default());
app.insert_resource(var::GameVars::default());
app.add_plugins(( app.add_plugins((
DefaultPlugins,//.set(ImagePlugin::default_nearest()), DefaultPlugins,//.set(ImagePlugin::default_nearest()),
FrameTimeDiagnosticsPlugin, FrameTimeDiagnosticsPlugin,

View file

@ -2,6 +2,8 @@ use bevy::prelude::*;
use std::collections::HashMap; use std::collections::HashMap;
use std::env; use std::env;
pub const SCOPE_SEPARATOR: &str = "$";
pub const DEFAULT_CHAT_SPEED: f32 = 10.0; pub const DEFAULT_CHAT_SPEED: f32 = 10.0;
#[derive(Resource)] #[derive(Resource)]
@ -191,13 +193,21 @@ impl Settings {
} }
#[derive(Resource)] #[derive(Resource)]
struct GameVars { pub struct GameVars {
pub db: HashMap<String, String>, pub db: HashMap<String, String>,
} }
impl Default for GameVars {
fn default() -> Self {
Self {
db: HashMap::new(),
}
}
}
impl GameVars { impl GameVars {
#[allow(dead_code)] #[allow(dead_code)]
fn get(&self, key: &str) -> Option<String> { pub fn get(&self, key: &str) -> Option<String> {
if let Some(value) = self.db.get(key) { if let Some(value) = self.db.get(key) {
return Some(value.clone()); return Some(value.clone());
} }
@ -205,7 +215,7 @@ impl GameVars {
} }
#[allow(dead_code)] #[allow(dead_code)]
fn getf(&self, key: &str) -> Option<f64> { pub fn getf(&self, key: &str) -> Option<f64> {
if let Some(value) = self.db.get(key) { if let Some(value) = self.db.get(key) {
if let Ok(float) = value.parse::<f64>() { if let Ok(float) = value.parse::<f64>() {
return Some(float); return Some(float);
@ -215,7 +225,7 @@ impl GameVars {
} }
#[allow(dead_code)] #[allow(dead_code)]
fn getb(&self, key: &str) -> bool { pub fn getb(&self, key: &str) -> bool {
if let Some(value) = self.db.get(key) { if let Some(value) = self.db.get(key) {
return value != "0"; return value != "0";
} }
@ -223,7 +233,18 @@ impl GameVars {
} }
#[allow(dead_code)] #[allow(dead_code)]
fn set(&mut self, key: &str, value: String) { pub fn set(&mut self, key: &str, value: String) {
self.db.insert(key.to_string(), value); self.db.insert(key.to_lowercase(), value);
}
#[allow(dead_code)]
pub fn set_in_scope(&mut self, scope: &str, key: &str, value: String) {
let key: String = if key.contains(SCOPE_SEPARATOR) {
key.to_string()
} else {
scope.to_string() + SCOPE_SEPARATOR + key
};
let key = key.to_lowercase();
self.db.insert(key, value);
} }
} }