implement "set" token for chats
This commit is contained in:
parent
07be89162c
commit
5df3f66ea6
32
src/chat.rs
32
src/chat.rs
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
33
src/var.rs
33
src/var.rs
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue