Compare commits
5 commits
8199ed790c
...
b2f28c36f1
Author | SHA1 | Date | |
---|---|---|---|
yuni | b2f28c36f1 | ||
yuni | 092feccc84 | ||
yuni | b01d53833b | ||
yuni | 3234b1f4bb | ||
yuni | 5723fd909b |
|
@ -54,7 +54,6 @@ Press **ESC** to view these any time from the in-game menu.
|
||||||
- **T**: Cruise control
|
- **T**: Cruise control
|
||||||
- **R**: Rotate (hold + move mouse)
|
- **R**: Rotate (hold + move mouse)
|
||||||
- **Y**: Rotation stabilizer
|
- **Y**: Rotation stabilizer
|
||||||
- **`**: Fast forward conversation
|
|
||||||
- **AWSD/Shift/Ctrl**: Move
|
- **AWSD/Shift/Ctrl**: Move
|
||||||
- **J/K/U/L/I/O**: Rotate
|
- **J/K/U/L/I/O**: Rotate
|
||||||
- **F11**: Fullscreen
|
- **F11**: Fullscreen
|
||||||
|
|
83
src/chat.rs
83
src/chat.rs
|
@ -25,6 +25,8 @@ pub const CHATS: &[&str] = &[
|
||||||
include_str!("chats/thebe.yaml"),
|
include_str!("chats/thebe.yaml"),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
pub const TEXT_CONTINUE: &str = "Continue...";
|
||||||
|
|
||||||
pub const TOKEN_CHAT: &str = "chat";
|
pub const TOKEN_CHAT: &str = "chat";
|
||||||
pub const TOKEN_MSG: &str = "msg";
|
pub const TOKEN_MSG: &str = "msg";
|
||||||
pub const TOKEN_SYSTEM: &str = "system";
|
pub const TOKEN_SYSTEM: &str = "system";
|
||||||
|
@ -46,6 +48,7 @@ pub const TOKEN_IF_INLINE: &str = "if "; // for lines like `- if foo:`
|
||||||
pub const DEFAULT_SOUND: &str = "chat";
|
pub const DEFAULT_SOUND: &str = "chat";
|
||||||
pub const MAX_BRANCH_DEPTH: usize = 64;
|
pub const MAX_BRANCH_DEPTH: usize = 64;
|
||||||
|
|
||||||
|
pub const ENABLE_CHOICE_TIMER: bool = false;
|
||||||
pub const CHOICE_TIMER: f64 = 40.0 * var::DEFAULT_CHAT_SPEED as f64;
|
pub const CHOICE_TIMER: f64 = 40.0 * var::DEFAULT_CHAT_SPEED as f64;
|
||||||
pub const LETTERS_PER_SECOND: f32 = 17.0;
|
pub const LETTERS_PER_SECOND: f32 = 17.0;
|
||||||
pub const TALKER_SPEED_FACTOR: f32 = var::DEFAULT_CHAT_SPEED / LETTERS_PER_SECOND;
|
pub const TALKER_SPEED_FACTOR: f32 = var::DEFAULT_CHAT_SPEED / LETTERS_PER_SECOND;
|
||||||
|
@ -105,6 +108,7 @@ pub struct Chat {
|
||||||
pub internal_id: usize,
|
pub internal_id: usize,
|
||||||
pub position: ChatPos,
|
pub position: ChatPos,
|
||||||
pub timer: f64,
|
pub timer: f64,
|
||||||
|
pub message_open: bool,
|
||||||
pub talker: Talker,
|
pub talker: Talker,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,6 +477,7 @@ impl ChatDB {
|
||||||
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)) => {
|
||||||
|
chat.message_open = true;
|
||||||
event.send(ChatEvent::SpawnMessage(
|
event.send(ChatEvent::SpawnMessage(
|
||||||
message.to_string(),
|
message.to_string(),
|
||||||
hud::LogLevel::Chat,
|
hud::LogLevel::Chat,
|
||||||
|
@ -520,23 +525,35 @@ impl ChatDB {
|
||||||
let key = key.as_str();
|
let key = key.as_str();
|
||||||
match (key, value) {
|
match (key, value) {
|
||||||
(Some(TOKEN_MSG), Value::String(message)) => {
|
(Some(TOKEN_MSG), Value::String(message)) => {
|
||||||
|
let loglevel = hud::LogLevel::Chat;
|
||||||
|
if loglevel.is_subtitle() {
|
||||||
|
chat.message_open = true;
|
||||||
|
}
|
||||||
event.send(ChatEvent::SpawnMessage(
|
event.send(ChatEvent::SpawnMessage(
|
||||||
message.to_string(),
|
message.to_string(),
|
||||||
hud::LogLevel::Chat,
|
loglevel,
|
||||||
sound.clone(),
|
sound.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
(Some(TOKEN_SYSTEM), Value::String(message)) => {
|
(Some(TOKEN_SYSTEM), Value::String(message)) => {
|
||||||
|
let loglevel = hud::LogLevel::Info;
|
||||||
|
if loglevel.is_subtitle() {
|
||||||
|
chat.message_open = true;
|
||||||
|
}
|
||||||
event.send(ChatEvent::SpawnMessage(
|
event.send(ChatEvent::SpawnMessage(
|
||||||
message.to_string(),
|
message.to_string(),
|
||||||
hud::LogLevel::Info,
|
loglevel,
|
||||||
sound.clone(),
|
sound.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
(Some(TOKEN_WARN), Value::String(message)) => {
|
(Some(TOKEN_WARN), Value::String(message)) => {
|
||||||
|
let loglevel = hud::LogLevel::Warning;
|
||||||
|
if loglevel.is_subtitle() {
|
||||||
|
chat.message_open = true;
|
||||||
|
}
|
||||||
event.send(ChatEvent::SpawnMessage(
|
event.send(ChatEvent::SpawnMessage(
|
||||||
message.to_string(),
|
message.to_string(),
|
||||||
hud::LogLevel::Warning,
|
loglevel,
|
||||||
sound.clone(),
|
sound.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -575,11 +592,7 @@ impl ChatDB {
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if chat.position.len() == 0 {
|
if chat.position.len() == 0 {
|
||||||
event.send(ChatEvent::SpawnMessage(
|
// Here it used to spawn the "Disconnected" message.
|
||||||
"Disconnected.".to_string(),
|
|
||||||
hud::LogLevel::Info,
|
|
||||||
DEFAULT_SOUND.to_string(),
|
|
||||||
));
|
|
||||||
event.send(ChatEvent::DespawnAllChats);
|
event.send(ChatEvent::DespawnAllChats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -633,6 +646,19 @@ impl ChatDB {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a "Continue" choice to any conversation line that doesn't define any choices
|
||||||
|
let choices_available = key > 0;
|
||||||
|
if chat.message_open && !choices_available {
|
||||||
|
let goto: Vec<usize> = chat.position.clone();
|
||||||
|
event.send(ChatEvent::SpawnChoice(
|
||||||
|
String::from(TEXT_CONTINUE),
|
||||||
|
0,
|
||||||
|
goto,
|
||||||
|
true,
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -671,6 +697,7 @@ pub fn handle_new_conversations(
|
||||||
let mut chat = Chat {
|
let mut chat = Chat {
|
||||||
internal_id: chat_id,
|
internal_id: chat_id,
|
||||||
position: vec![0],
|
position: vec![0],
|
||||||
|
message_open: false,
|
||||||
timer: time.elapsed_seconds_f64(),
|
timer: time.elapsed_seconds_f64(),
|
||||||
talker: event.talker.clone(),
|
talker: event.talker.clone(),
|
||||||
};
|
};
|
||||||
|
@ -728,6 +755,12 @@ pub fn handle_chat_events(
|
||||||
}
|
}
|
||||||
ChatEvent::DespawnAllChats => {
|
ChatEvent::DespawnAllChats => {
|
||||||
commands.entity(chat_entity).despawn();
|
commands.entity(chat_entity).despawn();
|
||||||
|
|
||||||
|
// also despawn all choices (keep in sync with DespawnAllChoices handler)
|
||||||
|
for entity in &q_choices {
|
||||||
|
commands.entity(entity).despawn();
|
||||||
|
}
|
||||||
|
choice_key = 0;
|
||||||
}
|
}
|
||||||
ChatEvent::SpawnMessage(message, level, sound) => {
|
ChatEvent::SpawnMessage(message, level, sound) => {
|
||||||
match level {
|
match level {
|
||||||
|
@ -754,11 +787,15 @@ pub fn handle_chat_events(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ENABLE_CHOICE_TIMER {
|
||||||
chat.timer = now
|
chat.timer = now
|
||||||
+ ((message.len() as f32).max(CHAT_SPEED_MIN_LEN)
|
+ ((message.len() as f32).max(CHAT_SPEED_MIN_LEN)
|
||||||
* TALKER_SPEED_FACTOR
|
* TALKER_SPEED_FACTOR
|
||||||
* chat.talker.talking_speed
|
* chat.talker.talking_speed
|
||||||
/ settings.chat_speed) as f64;
|
/ settings.chat_speed) as f64;
|
||||||
|
} else {
|
||||||
|
chat.timer = f64::INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
let sfx = audio::str2sfx(sound);
|
let sfx = audio::str2sfx(sound);
|
||||||
ew_sfx.send(audio::PlaySfxEvent(sfx));
|
ew_sfx.send(audio::PlaySfxEvent(sfx));
|
||||||
|
@ -778,8 +815,10 @@ pub fn handle_chat_events(
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
choice_key += 1;
|
choice_key += 1;
|
||||||
if !nowait {
|
if ENABLE_CHOICE_TIMER && !nowait {
|
||||||
chat.timer = now + CHOICE_TIMER / settings.chat_speed as f64;
|
chat.timer = now + CHOICE_TIMER / settings.chat_speed as f64;
|
||||||
|
} else {
|
||||||
|
chat.timer = f64::INFINITY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ChatEvent::RunScript(script) => {
|
ChatEvent::RunScript(script) => {
|
||||||
|
@ -809,7 +848,8 @@ fn handle_reply_keys(
|
||||||
settings: Res<var::Settings>,
|
settings: Res<var::Settings>,
|
||||||
q_choices: Query<&Choice>,
|
q_choices: Query<&Choice>,
|
||||||
mut q_chats: Query<&mut Chat>,
|
mut q_chats: Query<&mut Chat>,
|
||||||
mut evwriter_sfx: EventWriter<audio::PlaySfxEvent>,
|
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
||||||
|
mut ew_chat: EventWriter<ChatEvent>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
) {
|
) {
|
||||||
let mut selected_choice: usize = 0;
|
let mut selected_choice: usize = 0;
|
||||||
|
@ -817,10 +857,18 @@ fn handle_reply_keys(
|
||||||
if keyboard_input.just_pressed(key) {
|
if keyboard_input.just_pressed(key) {
|
||||||
for choice in &q_choices {
|
for choice in &q_choices {
|
||||||
if choice.key == selected_choice {
|
if choice.key == selected_choice {
|
||||||
|
if choice.goto.is_empty() {
|
||||||
|
// Conversation ended. No need to advance the chat.
|
||||||
|
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Click));
|
||||||
|
ew_chat.send(ChatEvent::DespawnAllChats);
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
if let Ok(mut chat) = q_chats.get_single_mut() {
|
if let Ok(mut chat) = q_chats.get_single_mut() {
|
||||||
evwriter_sfx.send(audio::PlaySfxEvent(audio::Sfx::Click));
|
// Advance the chat.
|
||||||
|
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Click));
|
||||||
chat.timer = time.elapsed_seconds_f64();
|
chat.timer = time.elapsed_seconds_f64();
|
||||||
chat.position = choice.goto.clone();
|
chat.position = choice.goto.clone();
|
||||||
|
chat.message_open = false;
|
||||||
}
|
}
|
||||||
break 'outer;
|
break 'outer;
|
||||||
}
|
}
|
||||||
|
@ -828,13 +876,6 @@ fn handle_reply_keys(
|
||||||
}
|
}
|
||||||
selected_choice += 1;
|
selected_choice += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if keyboard_input.just_pressed(settings.key_next_chat_line) {
|
|
||||||
if let Ok(mut chat) = q_chats.get_single_mut() {
|
|
||||||
evwriter_sfx.send(audio::PlaySfxEvent(audio::Sfx::Click));
|
|
||||||
chat.timer = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_chat_scripts(
|
pub fn handle_chat_scripts(
|
||||||
|
@ -987,7 +1028,11 @@ pub fn update_chat_variables(
|
||||||
vars.set_in_scope(
|
vars.set_in_scope(
|
||||||
"$",
|
"$",
|
||||||
"ar",
|
"ar",
|
||||||
if settings.hud_active { String::from("1") } else { String::from("0") }
|
if settings.hud_active {
|
||||||
|
String::from("1")
|
||||||
|
} else {
|
||||||
|
String::from("0")
|
||||||
|
},
|
||||||
);
|
);
|
||||||
let wears_chefhat = if let Some(ava) = hud::PLAYER_AR_AVATARS.get(settings.ar_avatar) {
|
let wears_chefhat = if let Some(ava) = hud::PLAYER_AR_AVATARS.get(settings.ar_avatar) {
|
||||||
match ava.0 {
|
match ava.0 {
|
||||||
|
|
|
@ -470,8 +470,8 @@
|
||||||
- You age slower, can fly further, time dilation from special relativity.
|
- You age slower, can fly further, time dilation from special relativity.
|
||||||
- label: skiprelativityintro
|
- label: skiprelativityintro
|
||||||
- Given the right speed, you age so slowly that you can literally go anywhere you want.
|
- Given the right speed, you age so slowly that you can literally go anywhere you want.
|
||||||
- Any *time* you want.
|
|
||||||
- set: timetravel
|
- set: timetravel
|
||||||
|
- Any *time* you want.
|
||||||
- Time travel! Only into the future though, of course.:
|
- Time travel! Only into the future though, of course.:
|
||||||
- Exactly.
|
- Exactly.
|
||||||
- goto: continuemonologue
|
- goto: continuemonologue
|
||||||
|
|
|
@ -7,7 +7,6 @@ C: Camera
|
||||||
T: Cruise control
|
T: Cruise control
|
||||||
R: Rotate (hold + move mouse)
|
R: Rotate (hold + move mouse)
|
||||||
Y: Rotation stabilizer
|
Y: Rotation stabilizer
|
||||||
`: Fast forward conversation
|
|
||||||
AWSD/Shift/Ctrl: Move
|
AWSD/Shift/Ctrl: Move
|
||||||
J/K/U/L/I/O: Rotate
|
J/K/U/L/I/O: Rotate
|
||||||
F11: Fullscreen
|
F11: Fullscreen
|
||||||
|
|
43
src/hud.rs
43
src/hud.rs
|
@ -213,6 +213,7 @@ pub enum Avatar {
|
||||||
Armor,
|
Armor,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum LogLevel {
|
pub enum LogLevel {
|
||||||
Achievement,
|
Achievement,
|
||||||
Always,
|
Always,
|
||||||
|
@ -224,7 +225,18 @@ pub enum LogLevel {
|
||||||
//Ping,
|
//Ping,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Message {
|
impl LogLevel {
|
||||||
|
pub fn is_subtitle(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
LogLevel::Chat => true,
|
||||||
|
LogLevel::Info => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Message {
|
||||||
text: String,
|
text: String,
|
||||||
sender: String,
|
sender: String,
|
||||||
level: LogLevel,
|
level: LogLevel,
|
||||||
|
@ -310,6 +322,20 @@ impl Log {
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.logs.clear();
|
self.logs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_subtitle_line(&self) -> Option<Message> {
|
||||||
|
let messages: Vec<&Message> = self
|
||||||
|
.logs
|
||||||
|
.iter()
|
||||||
|
.filter(|msg: &&Message| msg.level.is_subtitle())
|
||||||
|
.rev()
|
||||||
|
.take(1)
|
||||||
|
.collect();
|
||||||
|
if messages.len() > 0 {
|
||||||
|
return Some(messages[0].clone());
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup(
|
pub fn setup(
|
||||||
|
@ -1016,19 +1042,8 @@ fn update_hud(
|
||||||
|
|
||||||
// Display the last chat line as "subtitles"
|
// Display the last chat line as "subtitles"
|
||||||
if !q_chat.is_empty() {
|
if !q_chat.is_empty() {
|
||||||
let messages: Vec<&Message> = log
|
if let Some(message) = log.get_subtitle_line() {
|
||||||
.logs
|
node_currentline.sections[0].value = message.format();
|
||||||
.iter()
|
|
||||||
.filter(|msg: &&Message| match msg.level {
|
|
||||||
LogLevel::Chat => true,
|
|
||||||
LogLevel::Info => true,
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
.rev()
|
|
||||||
.take(1)
|
|
||||||
.collect();
|
|
||||||
if messages.len() > 0 {
|
|
||||||
node_currentline.sections[0].value = messages[0].format();
|
|
||||||
} else {
|
} else {
|
||||||
node_currentline.sections[0].value = "".to_string();
|
node_currentline.sections[0].value = "".to_string();
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,6 @@ pub struct Settings {
|
||||||
pub key_reply8: KeyCode,
|
pub key_reply8: KeyCode,
|
||||||
pub key_reply9: KeyCode,
|
pub key_reply9: KeyCode,
|
||||||
pub key_reply10: KeyCode,
|
pub key_reply10: KeyCode,
|
||||||
pub key_next_chat_line: KeyCode,
|
|
||||||
pub key_cheat_god_mode: KeyCode,
|
pub key_cheat_god_mode: KeyCode,
|
||||||
pub key_cheat_stop: KeyCode,
|
pub key_cheat_stop: KeyCode,
|
||||||
pub key_cheat_speed: KeyCode,
|
pub key_cheat_speed: KeyCode,
|
||||||
|
@ -286,7 +285,6 @@ impl Default for Settings {
|
||||||
key_reply8: KeyCode::Digit8,
|
key_reply8: KeyCode::Digit8,
|
||||||
key_reply9: KeyCode::Digit9,
|
key_reply9: KeyCode::Digit9,
|
||||||
key_reply10: KeyCode::Digit0,
|
key_reply10: KeyCode::Digit0,
|
||||||
key_next_chat_line: KeyCode::Backquote,
|
|
||||||
key_cheat_god_mode: KeyCode::KeyG,
|
key_cheat_god_mode: KeyCode::KeyG,
|
||||||
key_cheat_stop: KeyCode::KeyZ,
|
key_cheat_stop: KeyCode::KeyZ,
|
||||||
key_cheat_speed: KeyCode::KeyV,
|
key_cheat_speed: KeyCode::KeyV,
|
||||||
|
|
Loading…
Reference in a new issue