add chat definitions in YAML format (integration still needed)

This commit is contained in:
yuni 2024-04-12 20:10:36 +02:00
parent b53545ce2c
commit 5ca31fda65
5 changed files with 428 additions and 180 deletions

View file

@ -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<ButtonInput<KeyCode>>,
mut settings: ResMut<settings::Settings>,
q_talker: Query<(&chat::Talker, &Transform), (Without<actor::Player>, Without<Camera>)>,
q_talker: Query<(&chat2::Talker, &Transform), (Without<actor::Player>, Without<Camera>)>,
player: Query<Entity, With<actor::Player>>,
q_camera: Query<&Transform, With<Camera>>,
q_vehicles: Query<(Entity, &Transform), (With<actor::Vehicle>, Without<actor::Player>, Without<Camera>)>,
mut ew_conv: EventWriter<chat::StartConversationEvent>,
mut ew_conv: EventWriter<chat2::StartConversationEvent>,
mut ew_vehicle: EventWriter<VehicleEnterExitEvent>,
mut ew_playerdies: EventWriter<PlayerDiesEvent>,
q_player_drives: Query<Entity, With<PlayerDrivesThis>>,
@ -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::<chat::Talker>(objects, camtrans) {
if let (Some(talker), dist) = camera::find_closest_target::<chat2::Talker>(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

254
src/chats/serenity.yaml Normal file
View file

@ -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?

View file

@ -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::<f64>() {
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::<f64>() {
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::<f64>() {
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::<f64>() {
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::<f64>() {
// 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::<f64>() {
// 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::<f64>() {
// 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::<f64>() {
// 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()
});

View file

@ -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<actor::PlayerCamera>>,
mut timer: ResMut<FPSUpdateTimer>,
mut query: Query<&mut Text, With<GaugesText>>,
q_choices: Query<&chat::ChoiceAvailable>,
//q_choices: Query<&chat::ChoiceAvailable>,
mut query_chat: Query<&mut Text, (With<ChatText>, Without<GaugesText>)>,
query_all_actors: Query<&actor::Actor>,
settings: Res<settings::Settings>,
@ -514,48 +514,48 @@ fn update_hud(
}
}
if let Ok(mut chat) = query_chat.get_single_mut() {
// Choices
let mut choices: Vec<String> = 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<String> = 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<String> = 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<String> = 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();
}

View file

@ -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,