From 5ca31fda65a2c114b6630309adccc4d7fef63fe9 Mon Sep 17 00:00:00 2001 From: hut Date: Fri, 12 Apr 2024 20:10:36 +0200 Subject: [PATCH] add chat definitions in YAML format (integration still needed) --- src/actor.rs | 12 +- src/chats/serenity.yaml | 254 ++++++++++++++++++++++++++++++++++++++++ src/commands.rs | 250 +++++++++++++++++++-------------------- src/hud.rs | 88 +++++++------- src/main.rs | 4 +- 5 files changed, 428 insertions(+), 180 deletions(-) create mode 100644 src/chats/serenity.yaml diff --git a/src/actor.rs b/src/actor.rs index 8b38d41..35a3b31 100644 --- a/src/actor.rs +++ b/src/actor.rs @@ -2,7 +2,7 @@ use bevy::prelude::*; use bevy_xpbd_3d::prelude::*; use bevy::scene::SceneInstance; use bevy::math::DVec3; -use crate::{actor, audio, camera, chat, commands, effects, hud, nature, settings, world}; +use crate::{actor, audio, camera, chat2, commands, effects, hud, nature, settings, world}; pub const ENGINE_SPEED_FACTOR: f32 = 30.0; const MAX_TRANSMISSION_DISTANCE: f32 = 60.0; @@ -235,11 +235,11 @@ pub fn handle_input( mut commands: Commands, keyboard_input: Res>, mut settings: ResMut, - q_talker: Query<(&chat::Talker, &Transform), (Without, Without)>, + q_talker: Query<(&chat2::Talker, &Transform), (Without, Without)>, player: Query>, q_camera: Query<&Transform, With>, q_vehicles: Query<(Entity, &Transform), (With, Without, Without)>, - mut ew_conv: EventWriter, + mut ew_conv: EventWriter, mut ew_vehicle: EventWriter, mut ew_playerdies: EventWriter, q_player_drives: Query>, @@ -252,14 +252,14 @@ pub fn handle_input( if keyboard_input.just_pressed(settings.key_interact) { // Talking to people - let objects: Vec<(chat::Talker, &Transform)> = q_talker + let objects: Vec<(chat2::Talker, &Transform)> = q_talker .iter() .map(|(talker, transform)| (talker.clone(), transform)) .collect(); // TODO: replace Transform.translation with Position - if let (Some(talker), dist) = camera::find_closest_target::(objects, camtrans) { + if let (Some(talker), dist) = camera::find_closest_target::(objects, camtrans) { if dist <= MAX_TRANSMISSION_DISTANCE { - ew_conv.send(chat::StartConversationEvent{talker: talker.clone()}); + ew_conv.send(chat2::StartConversationEvent{talker: talker.clone()}); } } // Entering Vehicles diff --git a/src/chats/serenity.yaml b/src/chats/serenity.yaml new file mode 100644 index 0000000..fe0e314 --- /dev/null +++ b/src/chats/serenity.yaml @@ -0,0 +1,254 @@ +- chat: Drifter +- system: "Error: No response" +- system: No life signs detected +- Damn, it's gotta be moldy in that suit. How long has it been drifting?: +- Harvest some oxygen: + - script: refilloxygen 1 Drifter + + +--- + + +- chat: ClippyPizza +- At your service! + + +--- + + +- chat: ClippyTransSerenity +- Welcome at StarTrans Cargo Services! You have reached Serenity Station. +- "Ready for a trip? Available bus stops: Oscillation Station, Metis Prime Station" +- set busstop: serenity +- label: startransbusstop +- goto: EXIT +- label: interesting +- Serenity Station is famous for the best pizza across the Jovian Rings. +- Look for the neon sign of the pizzeria nearby. + + +--- + + +- chat: ClippyTransMetis +- Welcome at StarTrans Cargo Services! You have reached Metis Prime Station. +- "Ready for a trip? Available bus stops: Oscillation Station, Serenity Station" +- set busstop: metis +- label: startransbusstop +- goto: EXIT +- label: interesting +- This area is an industrial paradise for asteroid miners. +- Though it has been recently abandoned due to the excessive particle radiation. +- I advise you to minimize the duration of your stay here. + + +--- + + +- chat: ClippyTransOscillation +- Welcome at StarTrans Cargo Services! You have reached Oscillation Station. +- "Ready for a trip? Available bus stops: Serenity Station, Metis Prime Station" +- set busstop: oscillation +- label: startransbusstop +- goto: EXIT +- label: interesting +- The main attraction around here is the gorgeous view onto Jupiter from far up ahead. + + +--- + + +- addon: startransbusstop +- Bus stop?! How does this work?: + - StarTrans Cargo Services is the most convenient way to travel the vast distances of space. + - Just activate your suit's built-in cryostasis. A StarTrans carrier will pick you up and you will wake up at your destination in the blink of an eye. + - Of course we will supply you with free oxygen and ensure your safety. + - goto: startransbusstop +- Can I take a spacecraft with me?: + - Absolutely. + - goto startransbusstop +- if: busstop != oscillation + Take me to Oscillation Station, please.: + - StarTrans wishes you a pleasant journey. + - script: cryofadeout + - sleep: 5 + - script: cryotrip oscillation + - goto: EXIT +- if: busstop != metis + Take me to Metis Prime Station, please.: + - StarTrans wishes you a pleasant journey. + - script: cryofadeout + - sleep: 5 + - script: cryotrip metisprime + - goto: EXIT +- if: busstop != serenity + Take me to Serenity Station, please.: + - StarTrans wishes you a pleasant journey. + - script: cryofadeout + - sleep: 5 + - script: cryotrip serenity + - goto: EXIT +- Can you please fill up my oxygen tank without taking me anywhere?: + - Of course, you can count on StarTrans! + - script: refilloxygen 1000 +- Is there anything interesting to do around here?: + - goto: interesting +- No, thank you.: +- TIMEOUT: +- Feel free to come back any time. +- system: Connection terminated. + +--- +- chat: Icarus +- if talkcount > 0: + - "Oh, hi again! How are you?" + - goto: howru +- Oh hey, you're awake! +- 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!: + - label: thx + - No worries. Folks are stretched thin around this corner, we gotta watch out for each other. + - How talkcount are you feeling? + - goto: howru +- I didn't ask for this.: + - "Sure, 'cause you were unconscious. I just did what felt right. Is there a problem?" + - Nevermind. Thank you.: + - goto: thx + - Leave me alone!: + - goto: END +- Micros? What's that?: + - Micrometeorites. Those tiny 混蛋 that fly right through you, leaving holes in your suit. And your body. + - Ouch! Thank you so much.: + - goto: thx + - Whatever... I didn't ask for this.: + - goto: didntask + - TIMEOUT: + - How are you feeling? +- TIMEOUT: + - How are you feeling? + + +- label: howru +- I feel quite cozy, this space suit feels like a second skin.: + - Hah, it does, doesn't it? + - But take care, your suit seems to be leaking. I'd patch it up if I were you. + - I'm all out of SuitPatch™ SuperGlue™ right now, otherwise i'd share. + - Can I help you with anything else, maybe? + - set: friends +- I got this apocalyptic headache...: + - Heh, probably related to why you were passed out. + - Go easy on yourself, I'm sure things will turn for the better. + - Meanwhile, can I help you with anything? + - set: friends +- I... don't know, I'm pretty disoriented.: + - Oh no. Do you need a lowdown on reality? + - set: friends + + +- label: help +- Where are we?: + - This is space, my friend. + - That massive crescent over there, that's Juptiter. + - We're about 150,000km away from its surface, on the very outside of it's rings. + - This area is called the Thebe gossamer ring. + - The moon Thebe is actually pretty close right now, flinging all those micros at us. + - Micros? What's that?: + - Micrometeorites. Those tiny 混蛋 that fly right through you, leaving holes in your suit. And your body. + - goto: help +- What year is this?: + - Oh, is your Augmented Reality deactivated? + - Push the TAB button, your space suit's AR will show you the date and time. +- Why am I here?: + - That's a very philosophical question. + - I don't know. + - It's probably related to the choices you made in your life so far. +- What should I do?: + - Ah, that's the beauty of life. + - You can just do whatever you want. + - So long as you have the means, and respect people's boundaries. + - I'm here mostly for the view and the peace. + - Just look at Jupiter, it's mesmerizing, isn't it? + - So far away from everything, nobody expects anything from you. + - If you want, you can take my sports racing capsule MeteorAceGT™ for a ride. It's right over there. + - It rides like a punch in the face, don't hurt yourself, ok? + - You're too kind!: + - Ah, don't mention it! + - There's also a half-decent pizza restaurant over there, look for the neon sign. +- Do you have some money for me?: + - Huh? What is money? + - Currency? Flat round things that you can exchange for goods and services?: + - Uhm... are you talking about pizza? + - I don't have any pizza with me right now. + - But there's a pizza place right over there, look for the neon sign. + - goto: help + - Well, anyway, need anything else? +- I just want to be alone right now: + - Oh, sure. Ping me if you need anything. I'll go back to playing my VR game. + - goto: EXIT +- TIMEOUT: + - Well, I hope you're ok. + + +- label: chocolate +- I got some left-over instant hot chocolate, would you like some? +- Oh yes! Please!: + - Here you go, my friend! + - system: Received 1x ChuggaChug™ Instant Hot Chocolate +- TIMEOUT: + - I guess not. Well. I think I'll go back to playing my VR game. Ping me if you need anything. +- Oh and make sure to check out the pizza place! +- Will do, bye!: +- system: Disconnected. + + +--- + + +- chat: SpacePizza +- Welcome to Space Pizza™, best pizza around the rings! +- Great to see a customer, we don't get many lately +- Would you like to order today's special? +- label: offer +- What's the special?: + - Suspicious Spacefunghi + - With free pineapple imitation + - Our pizza smoothies are freshly blended every day + - Wait... pizza smoothie?: + - Huh? Of course, smoothie! How else do you want to get that pizza down your spacesuit feeding tube? + - An emulsion of deliciousness! + - TIMEOUT: + - Deliciousness for your spacesuit feeding tube! + - I think I'll pass...: + - Your loss, mate + - TIMEOUT: + - Hey? Are you still there? +- Wh... what's a pizzeria doing here?: + - Hah, beautiful, right? I carved it out this asteroid myself! + - You know how much work it was to neutralize the rotation of the asteroid, so my valued customers don't bang against the walls while drinking my pizza? + - Now would you like today's special or not? +- My head hurts, my suit leaks, I think I'm dying...: + - Seriously? Let me have a look. Just press the 'Grant Access' button please. + - "[GRANT ACCESS TO SPACESUIT WIFI]": + - label: hack + - warn: MALWARE DETECTED + - warn: BITCOIN MINER DETECTED + - Hey, what are you doing with me?: + - Just checking your systems, hang on tight + - Yeah, suit's fucked, I'd look out for a repair shop + - Anyway, wanna order today's special? + - goto: offer + - "[DENY ACCESS TO SPACESUIT WIFI]": + - Oh come on, do you want my help or not? + - "[GRANT ACCESS TO SPACESUIT WIFI]": + - goto hack + - "[DENY ACCESS TO SPACESUIT WIFI]": + - Fuck off!: + - TIMEOUT: + - goto: noreply + - Great, the first customer in ages, and they're brain damaged... + - goto: EXIT + - TIMEOUT: +- TIMEOUT: +- label: noreply +- Hey, are you still there? Is this a prank? diff --git a/src/commands.rs b/src/commands.rs index b58ada4..097a520 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -3,7 +3,7 @@ extern crate regex; use bevy::prelude::*; use bevy_xpbd_3d::prelude::*; use bevy::math::DVec3; -use crate::{actor, chat, hud, nature, world}; +use crate::{actor, chat2, hud, nature, world}; use regex::Regex; use std::f32::consts::PI; use std::f64::consts::PI as PI64; @@ -153,22 +153,22 @@ impl ParserState { self.script_parameter2 = default.script_parameter2; self.sound = default.sound; } - fn as_chatbranch(&self) -> chat::ChatBranch { - return chat::ChatBranch { - id: self.chat.clone(), - name: self.name.clone().unwrap_or("".to_string()), - label: self.label.clone(), - delay: self.delay.clone(), - sound: if self.is_choice || self.sound.is_none() { "".to_string() } else { "chat".to_string() }, - level: self.level.clone(), - reply: if self.is_choice { "".to_string() } else { self.text.clone() }, - choice: if self.is_choice { self.text.clone() } else { "".to_string() }, - goto: self.goto.clone(), - script: self.script.clone(), - script_parameter: self.script_parameter.clone(), - script_parameter2: self.script_parameter2.clone(), - } - } +// fn as_chatbranch(&self) -> chat::ChatBranch { +// return chat::ChatBranch { +// id: self.chat.clone(), +// name: self.name.clone().unwrap_or("".to_string()), +// label: self.label.clone(), +// delay: self.delay.clone(), +// sound: if self.is_choice || self.sound.is_none() { "".to_string() } else { "chat".to_string() }, +// level: self.level.clone(), +// reply: if self.is_choice { "".to_string() } else { self.text.clone() }, +// choice: if self.is_choice { self.text.clone() } else { "".to_string() }, +// goto: self.goto.clone(), +// script: self.script.clone(), +// script_parameter: self.script_parameter.clone(), +// script_parameter2: self.script_parameter2.clone(), +// } +// } } pub fn load_defs( @@ -468,109 +468,109 @@ pub fn load_defs( } // Parsing chats - ["chat", chat_name] => { - debug!("Registering chat: {}", chat_name); - ew_spawn.send(SpawnEvent(state)); - state = ParserState::default(); - state.class = DefClass::Chat; - state.chat = chat_name.to_string(); - } - ["name", name] => { - debug!("Registering name: {}", name); - state.name = Some(name.to_string()); - } - ["msg", sleep, text] => { - debug!("Registering message (sleep={}): {}", sleep, text); - ew_spawn.send(SpawnEvent(state.clone())); - if let Ok(sleep_float) = sleep.parse::() { - state.delay = sleep_float; - state.text = text.to_string(); - state.stores_item = true; - state.is_choice = false; - } else { - error!("The 'sleep' value for this message is not a float: {}", line); - continue; - } - } - ["msg", sleep, label, goto, text] => { - debug!("Registering message (sleep={}): {}", sleep, text); - ew_spawn.send(SpawnEvent(state.clone())); - state.reset_message(); - if let Ok(sleep_float) = sleep.parse::() { - state.delay = sleep_float; - state.text = text.to_string(); - state.stores_item = true; - state.is_choice = false; - state.goto = goto.to_string(); - state.label = label.to_string(); - } else { - error!("The 'sleep' value for this message is not a float: {}", line); - continue; - } - } - ["choice", sleep, text] => { - debug!("Registering choice (sleep={}): {}", sleep, text); - ew_spawn.send(SpawnEvent(state.clone())); - state.reset_message(); - if let Ok(sleep_float) = sleep.parse::() { - state.delay = sleep_float; - state.text = text.to_string(); - state.stores_item = true; - state.is_choice = true; - } else { - error!("The 'sleep' value for this message is not a float: {}", line); - continue; - } - } - ["choice", sleep, label, goto, text] => { - debug!("Registering choice (sleep={}): {}", sleep, text); - ew_spawn.send(SpawnEvent(state.clone())); - state.reset_message(); - if let Ok(sleep_float) = sleep.parse::() { - state.delay = sleep_float; - state.text = text.to_string(); - state.stores_item = true; - state.is_choice = true; - state.goto = goto.to_string(); - state.label = label.to_string(); - } else { - error!("The 'sleep' value for this message is not a float: {}", line); - continue; - } - } - ["goto", label] => { - debug!("Registering goto: {}", label); - state.goto = label.to_string(); - } - ["label", label] => { - debug!("Registering label: {}", label); - state.label = label.to_string(); - } - ["lvl", level] => { - debug!("Registering level: {}", level); - state.level = level.to_string(); - } - ["script", scriptname] => { - state.script = scriptname.to_string(); - state.script_parameter = "".to_string(); - state.script_parameter2 = "".to_string(); - } - ["script", scriptname, parameter] => { - state.script = scriptname.to_string(); - state.script_parameter = parameter.to_string(); - state.script_parameter2 = "".to_string(); - } - ["script", scriptname, parameter, parameter2] => { - state.script = scriptname.to_string(); - state.script_parameter = parameter.to_string(); - state.script_parameter2 = parameter2.to_string(); - } - ["sound", "none"] => { - state.sound = None; - } - _ => { - error!("No match for [{}]", parts.join(",")); - } +// ["chat", chat_name] => { +// debug!("Registering chat: {}", chat_name); +// ew_spawn.send(SpawnEvent(state)); +// state = ParserState::default(); +// state.class = DefClass::Chat; +// state.chat = chat_name.to_string(); +// } +// ["name", name] => { +// debug!("Registering name: {}", name); +// state.name = Some(name.to_string()); +// } +// ["msg", sleep, text] => { +// debug!("Registering message (sleep={}): {}", sleep, text); +// ew_spawn.send(SpawnEvent(state.clone())); +// if let Ok(sleep_float) = sleep.parse::() { +// state.delay = sleep_float; +// state.text = text.to_string(); +// state.stores_item = true; +// state.is_choice = false; +// } else { +// error!("The 'sleep' value for this message is not a float: {}", line); +// continue; +// } +// } +// ["msg", sleep, label, goto, text] => { +// debug!("Registering message (sleep={}): {}", sleep, text); +// ew_spawn.send(SpawnEvent(state.clone())); +// state.reset_message(); +// if let Ok(sleep_float) = sleep.parse::() { +// state.delay = sleep_float; +// state.text = text.to_string(); +// state.stores_item = true; +// state.is_choice = false; +// state.goto = goto.to_string(); +// state.label = label.to_string(); +// } else { +// error!("The 'sleep' value for this message is not a float: {}", line); +// continue; +// } +// } +// ["choice", sleep, text] => { +// debug!("Registering choice (sleep={}): {}", sleep, text); +// ew_spawn.send(SpawnEvent(state.clone())); +// state.reset_message(); +// if let Ok(sleep_float) = sleep.parse::() { +// state.delay = sleep_float; +// state.text = text.to_string(); +// state.stores_item = true; +// state.is_choice = true; +// } else { +// error!("The 'sleep' value for this message is not a float: {}", line); +// continue; +// } +// } +// ["choice", sleep, label, goto, text] => { +// debug!("Registering choice (sleep={}): {}", sleep, text); +// ew_spawn.send(SpawnEvent(state.clone())); +// state.reset_message(); +// if let Ok(sleep_float) = sleep.parse::() { +// state.delay = sleep_float; +// state.text = text.to_string(); +// state.stores_item = true; +// state.is_choice = true; +// state.goto = goto.to_string(); +// state.label = label.to_string(); +// } else { +// error!("The 'sleep' value for this message is not a float: {}", line); +// continue; +// } +// } +// ["goto", label] => { +// debug!("Registering goto: {}", label); +// state.goto = label.to_string(); +// } +// ["label", label] => { +// debug!("Registering label: {}", label); +// state.label = label.to_string(); +// } +// ["lvl", level] => { +// debug!("Registering level: {}", level); +// state.level = level.to_string(); +// } +// ["script", scriptname] => { +// state.script = scriptname.to_string(); +// state.script_parameter = "".to_string(); +// state.script_parameter2 = "".to_string(); +// } +// ["script", scriptname, parameter] => { +// state.script = scriptname.to_string(); +// state.script_parameter = parameter.to_string(); +// state.script_parameter2 = "".to_string(); +// } +// ["script", scriptname, parameter, parameter2] => { +// state.script = scriptname.to_string(); +// state.script_parameter = parameter.to_string(); +// state.script_parameter2 = parameter2.to_string(); +// } +// ["sound", "none"] => { +// state.sound = None; +// } +// _ => { +// error!("No match for [{}]", parts.join(",")); +// } } } ew_spawn.send(SpawnEvent(state)); @@ -585,13 +585,7 @@ fn spawn_entities( ) { for state_wrapper in er_spawn.read() { let state = &state_wrapper.0; - if state.class == DefClass::Chat { - if state.stores_item { - let mut chat = commands.spawn(state.as_chatbranch()); - chat.insert(world::DespawnOnPlayerDeath); - } - } - else if state.class == DefClass::Actor { + if state.class == DefClass::Actor { let actor_entity; { let mut actor = commands.spawn_empty(); @@ -697,7 +691,7 @@ fn spawn_entities( }); } if !state.chat.is_empty() { - actor.insert(chat::Talker { + actor.insert(chat2::Talker { conv_id: state.chat.clone(), ..default() }); diff --git a/src/hud.rs b/src/hud.rs index 70c2386..7a7e10d 100644 --- a/src/hud.rs +++ b/src/hud.rs @@ -1,4 +1,4 @@ -use crate::{actor, audio, camera, chat, nature, settings, world}; +use crate::{actor, audio, camera, nature, settings, world}; use bevy::prelude::*; use bevy::diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin}; use bevy::transform::TransformSystem; @@ -412,7 +412,7 @@ fn update_hud( q_camera: Query<(&Position, &LinearVelocity), With>, mut timer: ResMut, mut query: Query<&mut Text, With>, - q_choices: Query<&chat::ChoiceAvailable>, + //q_choices: Query<&chat::ChoiceAvailable>, mut query_chat: Query<&mut Text, (With, Without)>, query_all_actors: Query<&actor::Actor>, settings: Res, @@ -514,48 +514,48 @@ fn update_hud( } } - if let Ok(mut chat) = query_chat.get_single_mut() { - // Choices - let mut choices: Vec = Vec::new(); - let mut count = 0; - for choice in &q_choices { - if count > 9 { - break; - } - let press_this = REPLY_NUMBERS[count]; - let reply = &choice.text; - //let recipient = &choice.recipient; - // TODO: indicate recipients if there's more than one - choices.push(format!("{press_this} {reply}")); - count += 1; - } - if count < 4 { - for _padding in 0..(4-count) { - choices.push(" ".to_string()); - } - } - chat.sections[2].value = choices.join("\n"); - - // Chat Log and System Log - let logfilter = if settings.hud_active { - |_msg: &&Message| { true } - } else { - |msg: &&Message| { match msg.level { - LogLevel::Chat => true, - LogLevel::Warning => true, - LogLevel::Info => true, - _ => false - }} - }; - let logs_vec: Vec = log.logs.iter() - .filter(logfilter) - .map(|s| if s.sender.is_empty() { - format!("{}", s.text) - } else { - format!("{}: {}", s.sender, s.text) - }).collect(); - chat.sections[0].value = logs_vec.join("\n"); - } +// if let Ok(mut chat) = query_chat.get_single_mut() { +// // Choices +// let mut choices: Vec = Vec::new(); +// let mut count = 0; +// for choice in &q_choices { +// if count > 9 { +// break; +// } +// let press_this = REPLY_NUMBERS[count]; +// let reply = &choice.text; +// //let recipient = &choice.recipient; +// // TODO: indicate recipients if there's more than one +// choices.push(format!("{press_this} {reply}")); +// count += 1; +// } +// if count < 4 { +// for _padding in 0..(4-count) { +// choices.push(" ".to_string()); +// } +// } +// chat.sections[2].value = choices.join("\n"); +// +// // Chat Log and System Log +// let logfilter = if settings.hud_active { +// |_msg: &&Message| { true } +// } else { +// |msg: &&Message| { match msg.level { +// LogLevel::Chat => true, +// LogLevel::Warning => true, +// LogLevel::Info => true, +// _ => false +// }} +// }; +// let logs_vec: Vec = log.logs.iter() +// .filter(logfilter) +// .map(|s| if s.sender.is_empty() { +// format!("{}", s.text) +// } else { +// format!("{}: {}", s.sender, s.text) +// }).collect(); +// chat.sections[0].value = logs_vec.join("\n"); +// } log.needs_rerendering = false; log.remove_old(); } diff --git a/src/main.rs b/src/main.rs index c497348..4f9b83a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ mod actor; mod audio; mod camera; -mod chat; +mod chat2; mod commands; mod effects; mod hud; @@ -55,7 +55,7 @@ impl Plugin for OutFlyPlugin { actor::ActorPlugin, audio::AudioPlugin, camera::CameraPlugin, - chat::ChatPlugin, + chat2::ChatPlugin, commands::CommandsPlugin, effects::EffectsPlugin, hud::HudPlugin,