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)]
pub struct Chat {
pub id: usize,
pub internal_id: usize,
pub position: ChatPos,
pub timer: f64,
pub talker: Talker,
@ -94,7 +94,8 @@ pub struct Choice {
#[derive(Component)]
#[derive(Clone)]
pub struct Talker {
pub conv_id: String,
pub chat_name: String,
pub actor_id: String,
pub name: Option<String>,
pub pronoun: Option<String>,
pub talking_speed: f32,
@ -116,6 +117,7 @@ pub enum ChatEvent {
SpawnChoice(String, usize, ChatPos, bool),
RunScript(String),
SleepSeconds(f64),
SetVariable(String),
}
// This is the only place where any YAML interaction should be happening.
@ -297,7 +299,7 @@ impl ChatDB {
let mut popped = false;
let mut seek_past_dialog_choices = false;
while chat.position.len() > 0 {
match self.at(chat.id, &chat.position) {
match self.at(chat.internal_id, &chat.position) {
None => {
chat.position.pop();
popped = true;
@ -380,7 +382,7 @@ impl ChatDB {
// 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".
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() {
return false;
}
@ -406,7 +408,7 @@ impl ChatDB {
chat: &mut Chat,
event: &mut EventWriter<ChatEvent>,
) -> 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;
match current_item {
Some(Value::String(message)) => {
@ -452,7 +454,9 @@ impl ChatDB {
event.send(ChatEvent::SpawnMessage(
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)) => {
match self.search_label(chat.id, &label) {
match self.search_label(chat.internal_id, &label) {
Some(pos) => {
chat.position = pos;
}
@ -519,7 +523,7 @@ impl ChatDB {
let mut key: usize = 0;
let mut reached_end_of_branch = false;
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 {
break;
}
@ -556,10 +560,10 @@ pub fn handle_new_conversations(
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Ping));
return;
}
match (*chatdb).get_chat_by_id(&event.talker.conv_id) {
match (*chatdb).get_chat_by_id(&event.talker.chat_name) {
Ok(chat_id) => {
let mut chat = Chat {
id: chat_id,
internal_id: chat_id,
position: vec![0],
timer: time.elapsed_seconds_f64(),
talker: event.talker.clone(),
@ -597,6 +601,7 @@ pub fn handle_chat_events(
mut ew_chatscript: EventWriter<ChatScriptEvent>,
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
mut log: ResMut<hud::Log>,
mut vars: ResMut<var::GameVars>,
q_choices: Query<Entity, With<Choice>>,
mut q_chats: Query<(Entity, &mut Chat)>,
time: Res<Time>,
@ -655,6 +660,13 @@ pub fn handle_chat_events(
ChatEvent::SleepSeconds(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
- Oh hey, you're awake!
- set: talked_before
- 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.
- Thank you!:

View file

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

View file

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

View file

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

View file

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