Compare commits
13 commits
a670778fb0
...
2e57f911ed
Author | SHA1 | Date | |
---|---|---|---|
yuni | 2e57f911ed | ||
yuni | d21f8b4b09 | ||
yuni | 011938cadf | ||
yuni | 00df7bc711 | ||
yuni | d51333274b | ||
yuni | d6901bef00 | ||
yuni | a13264a404 | ||
yuni | b4ff95c3be | ||
yuni | 5df3f66ea6 | ||
yuni | 07be89162c | ||
yuni | 7b6b14a992 | ||
yuni | 600f9d5e3e | ||
yuni | 86cd3b049e |
|
@ -2,7 +2,7 @@ use bevy::prelude::*;
|
||||||
use bevy_xpbd_3d::prelude::*;
|
use bevy_xpbd_3d::prelude::*;
|
||||||
use bevy::scene::SceneInstance;
|
use bevy::scene::SceneInstance;
|
||||||
use bevy::math::DVec3;
|
use bevy::math::DVec3;
|
||||||
use crate::{actor, audio, camera, chat, commands, effects, hud, nature, settings, world};
|
use crate::{actor, audio, camera, chat, commands, effects, hud, nature, var, world};
|
||||||
|
|
||||||
pub const ENGINE_SPEED_FACTOR: f32 = 30.0;
|
pub const ENGINE_SPEED_FACTOR: f32 = 30.0;
|
||||||
const MAX_TRANSMISSION_DISTANCE: f32 = 60.0;
|
const MAX_TRANSMISSION_DISTANCE: f32 = 60.0;
|
||||||
|
@ -234,7 +234,7 @@ pub fn update_physics_lifeforms(
|
||||||
pub fn handle_input(
|
pub fn handle_input(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
mut settings: ResMut<settings::Settings>,
|
mut settings: ResMut<var::Settings>,
|
||||||
q_talker: Query<(&chat::Talker, &Transform), (Without<actor::Player>, Without<Camera>)>,
|
q_talker: Query<(&chat::Talker, &Transform), (Without<actor::Player>, Without<Camera>)>,
|
||||||
player: Query<Entity, With<actor::Player>>,
|
player: Query<Entity, With<actor::Player>>,
|
||||||
q_camera: Query<&Transform, With<Camera>>,
|
q_camera: Query<&Transform, With<Camera>>,
|
||||||
|
@ -424,7 +424,7 @@ fn handle_player_death(
|
||||||
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
||||||
mut ew_effect: EventWriter<effects::SpawnEffectEvent>,
|
mut ew_effect: EventWriter<effects::SpawnEffectEvent>,
|
||||||
mut log: ResMut<hud::Log>,
|
mut log: ResMut<hud::Log>,
|
||||||
mut settings: ResMut<settings::Settings>,
|
mut settings: ResMut<var::Settings>,
|
||||||
) {
|
) {
|
||||||
for death in er_playerdies.read() {
|
for death in er_playerdies.read() {
|
||||||
if settings.god_mode {
|
if settings.god_mode {
|
||||||
|
@ -472,7 +472,7 @@ fn handle_player_death(
|
||||||
fn handle_damage(
|
fn handle_damage(
|
||||||
mut ew_playerdies: EventWriter<PlayerDiesEvent>,
|
mut ew_playerdies: EventWriter<PlayerDiesEvent>,
|
||||||
mut q_hp: Query<(&mut HitPoints, Option<&Player>), Changed<HitPoints>>,
|
mut q_hp: Query<(&mut HitPoints, Option<&Player>), Changed<HitPoints>>,
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
) {
|
) {
|
||||||
for (mut hp, player_maybe) in &mut q_hp {
|
for (mut hp, player_maybe) in &mut q_hp {
|
||||||
if player_maybe.is_some() {
|
if player_maybe.is_some() {
|
||||||
|
|
10
src/audio.rs
10
src/audio.rs
|
@ -1,6 +1,6 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::audio::{PlaybackMode, Volume};
|
use bevy::audio::{PlaybackMode, Volume};
|
||||||
use crate::settings;
|
use crate::var;
|
||||||
|
|
||||||
const ASSET_CLICK: &str = "sounds/click-button-140881-crop.ogg";
|
const ASSET_CLICK: &str = "sounds/click-button-140881-crop.ogg";
|
||||||
const ASSET_SWITCH: &str = "sounds/typosonic-typing-192811-crop.ogg";
|
const ASSET_SWITCH: &str = "sounds/typosonic-typing-192811-crop.ogg";
|
||||||
|
@ -59,7 +59,7 @@ pub enum Sfx {
|
||||||
|
|
||||||
pub fn setup(
|
pub fn setup(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
) {
|
) {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
|
@ -132,7 +132,7 @@ pub fn toggle_bgm(
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
mut evwriter_toggle: EventWriter<ToggleMusicEvent>,
|
mut evwriter_toggle: EventWriter<ToggleMusicEvent>,
|
||||||
mut evwriter_sfx: EventWriter<PlaySfxEvent>,
|
mut evwriter_sfx: EventWriter<PlaySfxEvent>,
|
||||||
mut settings: ResMut<settings::Settings>,
|
mut settings: ResMut<var::Settings>,
|
||||||
) {
|
) {
|
||||||
if keyboard_input.just_pressed(KeyCode::KeyT) {
|
if keyboard_input.just_pressed(KeyCode::KeyT) {
|
||||||
settings.mute_music ^= true;
|
settings.mute_music ^= true;
|
||||||
|
@ -148,7 +148,7 @@ pub fn toggle_bgm(
|
||||||
|
|
||||||
pub fn play_sfx(
|
pub fn play_sfx(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
mut events_sfx: EventReader<PlaySfxEvent>,
|
mut events_sfx: EventReader<PlaySfxEvent>,
|
||||||
sound_click: Res<SoundClick>,
|
sound_click: Res<SoundClick>,
|
||||||
sound_switch: Res<SoundSwitch>,
|
sound_switch: Res<SoundSwitch>,
|
||||||
|
@ -200,7 +200,7 @@ pub fn str2sfx(sfx_label: &str) -> Sfx {
|
||||||
pub fn update_music(
|
pub fn update_music(
|
||||||
mut events: EventReader<ToggleMusicEvent>,
|
mut events: EventReader<ToggleMusicEvent>,
|
||||||
bgm_controller: Query<&AudioSink, With<ComponentBGM>>,
|
bgm_controller: Query<&AudioSink, With<ComponentBGM>>,
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
) {
|
) {
|
||||||
if !events.is_empty() {
|
if !events.is_empty() {
|
||||||
events.clear();
|
events.clear();
|
||||||
|
|
|
@ -8,7 +8,7 @@ use bevy::transform::TransformSystem;
|
||||||
use bevy::math::{DVec3, DQuat};
|
use bevy::math::{DVec3, DQuat};
|
||||||
use bevy_xpbd_3d::prelude::*;
|
use bevy_xpbd_3d::prelude::*;
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use crate::{actor, audio, hud, settings};
|
use crate::{actor, audio, hud, var};
|
||||||
|
|
||||||
pub struct CameraPlugin;
|
pub struct CameraPlugin;
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ pub fn setup_camera(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync_camera_to_player(
|
pub fn sync_camera_to_player(
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
mut q_camera: Query<&mut Transform, (With<Camera>, Without<actor::PlayerCamera>)>,
|
mut q_camera: Query<&mut Transform, (With<Camera>, Without<actor::PlayerCamera>)>,
|
||||||
q_playercam: Query<(&actor::Actor, &Transform), (With<actor::PlayerCamera>, Without<Camera>)>,
|
q_playercam: Query<(&actor::Actor, &Transform), (With<actor::PlayerCamera>, Without<Camera>)>,
|
||||||
) {
|
) {
|
||||||
|
@ -93,7 +93,7 @@ pub fn sync_camera_to_player(
|
||||||
pub fn update_fov(
|
pub fn update_fov(
|
||||||
q_player: Query<&actor::ExperiencesGForce, With<actor::Player>>,
|
q_player: Query<&actor::ExperiencesGForce, With<actor::Player>>,
|
||||||
mouse_input: Res<ButtonInput<MouseButton>>,
|
mouse_input: Res<ButtonInput<MouseButton>>,
|
||||||
mut settings: ResMut<settings::Settings>,
|
mut settings: ResMut<var::Settings>,
|
||||||
mut q_camera: Query<&mut Projection, With<Camera>>,
|
mut q_camera: Query<&mut Projection, With<Camera>>,
|
||||||
) {
|
) {
|
||||||
if let (Ok(gforce), Ok(mut projection)) = (q_player.get_single(), q_camera.get_single_mut())
|
if let (Ok(gforce), Ok(mut projection)) = (q_player.get_single(), q_camera.get_single_mut())
|
||||||
|
@ -116,7 +116,7 @@ pub fn update_fov(
|
||||||
|
|
||||||
pub fn handle_input(
|
pub fn handle_input(
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
mut settings: ResMut<settings::Settings>,
|
mut settings: ResMut<var::Settings>,
|
||||||
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
||||||
) {
|
) {
|
||||||
if keyboard_input.just_pressed(settings.key_camera) {
|
if keyboard_input.just_pressed(settings.key_camera) {
|
||||||
|
@ -129,7 +129,7 @@ pub fn handle_input(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn manage_player_actor(
|
fn manage_player_actor(
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
mut q_playercam: Query<&mut Visibility, With<actor::PlayerCamera>>,
|
mut q_playercam: Query<&mut Visibility, With<actor::PlayerCamera>>,
|
||||||
mut q_hiddenplayer: Query<(&mut Visibility, &mut Position, &mut Rotation, &mut LinearVelocity, &mut AngularVelocity), (With<actor::Player>, Without<actor::PlayerCamera>)>,
|
mut q_hiddenplayer: Query<(&mut Visibility, &mut Position, &mut Rotation, &mut LinearVelocity, &mut AngularVelocity), (With<actor::Player>, Without<actor::PlayerCamera>)>,
|
||||||
q_ride: Query<(&Transform, &Position, &Rotation, &LinearVelocity, &AngularVelocity), (With<actor::PlayerDrivesThis>, Without<actor::Player>)>,
|
q_ride: Query<(&Transform, &Position, &Rotation, &LinearVelocity, &AngularVelocity), (With<actor::PlayerDrivesThis>, Without<actor::Player>)>,
|
||||||
|
@ -161,7 +161,7 @@ fn manage_player_actor(
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn apply_input_to_player(
|
pub fn apply_input_to_player(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
windows: Query<&Window, With<PrimaryWindow>>,
|
windows: Query<&Window, With<PrimaryWindow>>,
|
||||||
mut mouse_events: EventReader<MouseMotion>,
|
mut mouse_events: EventReader<MouseMotion>,
|
||||||
key_input: Res<ButtonInput<KeyCode>>,
|
key_input: Res<ButtonInput<KeyCode>>,
|
||||||
|
|
158
src/chat.rs
158
src/chat.rs
|
@ -1,4 +1,4 @@
|
||||||
use crate::{actor, audio, hud, settings, world, effects};
|
use crate::{actor, audio, effects, hud, var, world};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::math::DVec3;
|
use bevy::math::DVec3;
|
||||||
use bevy_xpbd_3d::prelude::*;
|
use bevy_xpbd_3d::prelude::*;
|
||||||
|
@ -18,6 +18,7 @@ pub const TOKEN_WARN: &str = "warn";
|
||||||
pub const TOKEN_SLEEP: &str = "sleep";
|
pub const TOKEN_SLEEP: &str = "sleep";
|
||||||
pub const TOKEN_SET: &str = "set";
|
pub const TOKEN_SET: &str = "set";
|
||||||
pub const TOKEN_IF: &str = "if";
|
pub const TOKEN_IF: &str = "if";
|
||||||
|
pub const TOKEN_THEN: &str = "then";
|
||||||
pub const TOKEN_GOTO: &str = "goto";
|
pub const TOKEN_GOTO: &str = "goto";
|
||||||
pub const TOKEN_LABEL: &str = "label";
|
pub const TOKEN_LABEL: &str = "label";
|
||||||
pub const TOKEN_SCRIPT: &str = "script";
|
pub const TOKEN_SCRIPT: &str = "script";
|
||||||
|
@ -26,13 +27,14 @@ pub const TOKEN_NOWAIT: &str = "nowait";
|
||||||
|
|
||||||
pub const TOKEN_INCLUDE: &str = "include";
|
pub const TOKEN_INCLUDE: &str = "include";
|
||||||
pub const TOKEN_GOTO_EXIT: &str = "EXIT";
|
pub const TOKEN_GOTO_EXIT: &str = "EXIT";
|
||||||
|
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 CHOICE_TIMER: f64 = 40.0 * settings::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 = settings::DEFAULT_CHAT_SPEED / LETTERS_PER_SECOND;
|
pub const TALKER_SPEED_FACTOR: f32 = var::DEFAULT_CHAT_SPEED / LETTERS_PER_SECOND;
|
||||||
pub const CHAT_SPEED_MIN_LEN: f32 = 40.0;
|
pub const CHAT_SPEED_MIN_LEN: f32 = 40.0;
|
||||||
|
|
||||||
pub const NON_CHOICE_TOKENS: &[&str] = &[
|
pub const NON_CHOICE_TOKENS: &[&str] = &[
|
||||||
|
@ -43,6 +45,7 @@ pub const NON_CHOICE_TOKENS: &[&str] = &[
|
||||||
TOKEN_SLEEP,
|
TOKEN_SLEEP,
|
||||||
TOKEN_SET,
|
TOKEN_SET,
|
||||||
TOKEN_IF,
|
TOKEN_IF,
|
||||||
|
TOKEN_THEN,
|
||||||
TOKEN_GOTO,
|
TOKEN_GOTO,
|
||||||
TOKEN_LABEL,
|
TOKEN_LABEL,
|
||||||
TOKEN_SCRIPT,
|
TOKEN_SCRIPT,
|
||||||
|
@ -78,7 +81,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 +97,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,
|
||||||
|
@ -113,12 +117,29 @@ pub enum ChatEvent {
|
||||||
DespawnAllChoices,
|
DespawnAllChoices,
|
||||||
DespawnAllChats,
|
DespawnAllChats,
|
||||||
SpawnMessage(String, hud::LogLevel, String),
|
SpawnMessage(String, hud::LogLevel, String),
|
||||||
SpawnChoice(String, usize, ChatPos, bool),
|
SpawnChoice(String, usize, ChatPos, bool, Option<String>),
|
||||||
RunScript(String),
|
RunScript(String),
|
||||||
Sleep(f64),
|
SleepSeconds(f64),
|
||||||
//Script(String, String, String),
|
SetVariable(String),
|
||||||
|
GotoIf(String, ChatPos),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Extracted {
|
||||||
|
choice_text: Option<String>,
|
||||||
|
nowait: bool,
|
||||||
|
condition: Option<String>,
|
||||||
|
}
|
||||||
|
impl Default for Extracted {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
choice_text: None,
|
||||||
|
nowait: false,
|
||||||
|
condition: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// This is the only place where any YAML interaction should be happening.
|
// This is the only place where any YAML interaction should be happening.
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
pub struct ChatDB(Vec<Value>);
|
pub struct ChatDB(Vec<Value>);
|
||||||
|
@ -191,7 +212,9 @@ impl ChatDB {
|
||||||
for (index, label) in changes {
|
for (index, label) in changes {
|
||||||
if index < vector.len() {
|
if index < vector.len() {
|
||||||
vector.remove(index);
|
vector.remove(index);
|
||||||
vector.splice(index..index, include_db[&label].iter().cloned());
|
if let Some(chat) = include_db.get(&label) {
|
||||||
|
vector.splice(index..index, chat.iter().cloned());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,25 +245,38 @@ impl ChatDB {
|
||||||
// Not acceptable:
|
// Not acceptable:
|
||||||
// - `"What's up?"`
|
// - `"What's up?"`
|
||||||
// - `{"goto": "foo"}`
|
// - `{"goto": "foo"}`
|
||||||
// Returns (choice text, sub-conversation branch, nowait flag)
|
fn is_choice(&self, yaml: Option<&Value>) -> bool {
|
||||||
fn search_choice(&self, yaml: Option<&Value>) -> Option<(String, Value, bool)> {
|
if let Some(data) = self.extract(yaml) {
|
||||||
|
return data.choice_text.is_some();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract(&self, yaml: Option<&Value>) -> Option<Extracted> {
|
||||||
let non_choice_tokens = NON_CHOICE_TOKENS.to_vec();
|
let non_choice_tokens = NON_CHOICE_TOKENS.to_vec();
|
||||||
let mut result: Option<(String, Value, bool)> = None;
|
|
||||||
let mut nowait = false;
|
|
||||||
if let Some(Value::Mapping(map)) = yaml {
|
if let Some(Value::Mapping(map)) = yaml {
|
||||||
|
let mut result: Extracted = Extracted::default();
|
||||||
for (key, value) in map {
|
for (key, value) in map {
|
||||||
if let Value::String(key) = key {
|
if let Value::String(key) = key {
|
||||||
if key == TOKEN_NOWAIT && value.as_bool() == Some(true) {
|
if key == TOKEN_NOWAIT && value.as_bool() == Some(true) {
|
||||||
nowait = true;
|
result.nowait = true;
|
||||||
}
|
}
|
||||||
if non_choice_tokens.contains(&key.as_str()) {
|
else if key == TOKEN_IF {
|
||||||
continue;
|
if let Some(condition) = value.as_str() {
|
||||||
|
result.condition = Some(condition.to_string());
|
||||||
}
|
}
|
||||||
result = Some((key.into(), map[key].clone(), nowait));
|
}
|
||||||
|
else if non_choice_tokens.contains(&key.as_str()) {
|
||||||
|
// skip over the other non-choice tokens
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.choice_text = Some(key.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return Some(result);
|
||||||
|
}
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_label_recursively(&self, sequence: &Value, label: &String, mut pos: ChatPos) -> Option<ChatPos> {
|
fn search_label_recursively(&self, sequence: &Value, label: &String, mut pos: ChatPos) -> Option<ChatPos> {
|
||||||
|
@ -296,7 +332,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;
|
||||||
|
@ -307,7 +343,7 @@ impl ChatDB {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(Value::Mapping(map)) => {
|
Some(Value::Mapping(map)) => {
|
||||||
if seek_past_dialog_choices && self.search_choice(Some(&Value::Mapping(map))).is_some() {
|
if seek_past_dialog_choices && self.is_choice(Some(&Value::Mapping(map))) {
|
||||||
// we just dropped out of a branch and ended up in a dialog
|
// we just dropped out of a branch and ended up in a dialog
|
||||||
// choice. let's seek past all the choices until we find
|
// choice. let's seek past all the choices until we find
|
||||||
// the next non-dialog-choice item.
|
// the next non-dialog-choice item.
|
||||||
|
@ -348,12 +384,12 @@ impl ChatDB {
|
||||||
result = Some(Value::String(value_string.into()));
|
result = Some(Value::String(value_string.into()));
|
||||||
}
|
}
|
||||||
Some(Value::Mapping(mapping)) => {
|
Some(Value::Mapping(mapping)) => {
|
||||||
if let Some((_choicetext, subconversation, _)) = self.search_choice(value) {
|
|
||||||
result = Some(Value::Mapping(mapping.clone()));
|
result = Some(Value::Mapping(mapping.clone()));
|
||||||
next_pointer = Some(subconversation);
|
for value in mapping.values() {
|
||||||
|
if let Some(list) = value.as_sequence() {
|
||||||
|
next_pointer = Some(Value::Sequence(list.clone()));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
result = Some(Value::Mapping(mapping.clone()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -379,7 +415,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;
|
||||||
}
|
}
|
||||||
|
@ -405,7 +441,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)) => {
|
||||||
|
@ -416,7 +452,7 @@ impl ChatDB {
|
||||||
let mut sound = DEFAULT_SOUND.to_string();
|
let mut sound = DEFAULT_SOUND.to_string();
|
||||||
|
|
||||||
// Is this a dialog choice?
|
// Is this a dialog choice?
|
||||||
if let Some(_) = self.search_choice(Some(&Value::Mapping(map.clone()))) {
|
if self.is_choice(Some(&Value::Mapping(map.clone()))) {
|
||||||
processed_a_choice = true;
|
processed_a_choice = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,12 +463,25 @@ impl ChatDB {
|
||||||
for (key, value) in &map {
|
for (key, value) in &map {
|
||||||
let key = key.as_str();
|
let key = key.as_str();
|
||||||
match (key, value) {
|
match (key, value) {
|
||||||
(Some(TOKEN_IF), _) => {} // TODO
|
(Some(TOKEN_IF), Value::String(condition)) => {
|
||||||
|
let mut pos = chat.position.clone();
|
||||||
|
pos.push(0);
|
||||||
|
event.send(ChatEvent::GotoIf(condition.into(), pos));
|
||||||
|
}
|
||||||
(Some(TOKEN_SOUND), Value::String(sound_name)) => {
|
(Some(TOKEN_SOUND), Value::String(sound_name)) => {
|
||||||
sound = sound_name.clone();
|
sound = sound_name.clone();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(key) = key {
|
||||||
|
if key.starts_with(TOKEN_IF_INLINE) {
|
||||||
|
let condition: &str = &key[TOKEN_IF_INLINE.len()..];
|
||||||
|
let mut pos = chat.position.clone();
|
||||||
|
pos.push(0);
|
||||||
|
event.send(ChatEvent::GotoIf(condition.into(), pos));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second pass
|
// Second pass
|
||||||
|
@ -451,7 +500,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()));
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,11 +513,11 @@ impl ChatDB {
|
||||||
match (key, value) {
|
match (key, value) {
|
||||||
(Some(TOKEN_SLEEP), Value::Number(time)) => {
|
(Some(TOKEN_SLEEP), Value::Number(time)) => {
|
||||||
if let Some(time_f64) = time.as_f64() {
|
if let Some(time_f64) = time.as_f64() {
|
||||||
event.send(ChatEvent::Sleep(time_f64));
|
event.send(ChatEvent::SleepSeconds(time_f64));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(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;
|
||||||
}
|
}
|
||||||
|
@ -517,17 +568,22 @@ impl ChatDB {
|
||||||
// Spawn choices until we reach a non-choice item or the end of the branch
|
// Spawn choices until we reach a non-choice item or the end of the branch
|
||||||
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(data) = self.extract(self.at(chat.internal_id, &chat.position).as_ref()) {
|
||||||
self.search_choice(self.at(chat.id, &chat.position).as_ref()) {
|
if let Some(choice_text) = data.choice_text {
|
||||||
if reached_end_of_branch {
|
if reached_end_of_branch {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let mut goto: Vec<usize> = chat.position.clone();
|
let mut goto: Vec<usize> = chat.position.clone();
|
||||||
goto.push(0);
|
goto.push(0);
|
||||||
event.send(ChatEvent::SpawnChoice(choice, key, goto, nowait));
|
event.send(ChatEvent::SpawnChoice(choice_text,
|
||||||
|
key, goto, data.nowait, data.condition));
|
||||||
key += 1;
|
key += 1;
|
||||||
reached_end_of_branch = self.advance_pointer(chat);
|
reached_end_of_branch = self.advance_pointer(chat);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -555,10 +611,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(),
|
||||||
|
@ -596,10 +652,11 @@ 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>,
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
) {
|
) {
|
||||||
for event in er_chatevent.read() {
|
for event in er_chatevent.read() {
|
||||||
let now = time.elapsed_seconds_f64();
|
let now = time.elapsed_seconds_f64();
|
||||||
|
@ -635,7 +692,14 @@ pub fn handle_chat_events(
|
||||||
let sfx = audio::str2sfx(sound);
|
let sfx = audio::str2sfx(sound);
|
||||||
ew_sfx.send(audio::PlaySfxEvent(sfx));
|
ew_sfx.send(audio::PlaySfxEvent(sfx));
|
||||||
}
|
}
|
||||||
ChatEvent::SpawnChoice(replytext, key, goto, nowait) => {
|
ChatEvent::SpawnChoice(replytext, key, goto, nowait, condition) => {
|
||||||
|
'out: {
|
||||||
|
dbg!(condition);
|
||||||
|
if let Some(condition) = condition {
|
||||||
|
if !vars.evaluate_condition(condition, &chat.talker.actor_id) {
|
||||||
|
break 'out;
|
||||||
|
}
|
||||||
|
}
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
world::DespawnOnPlayerDeath,
|
world::DespawnOnPlayerDeath,
|
||||||
Choice {
|
Choice {
|
||||||
|
@ -648,22 +712,34 @@ pub fn handle_chat_events(
|
||||||
chat.timer = now + CHOICE_TIMER / settings.chat_speed as f64;
|
chat.timer = now + CHOICE_TIMER / settings.chat_speed as f64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ChatEvent::RunScript(script) => {
|
ChatEvent::RunScript(script) => {
|
||||||
ew_chatscript.send(ChatScriptEvent(script.clone()));
|
ew_chatscript.send(ChatScriptEvent(script.clone()));
|
||||||
}
|
}
|
||||||
ChatEvent::Sleep(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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ChatEvent::GotoIf(condition, goto) => {
|
||||||
|
if vars.evaluate_condition(condition, &chat.talker.actor_id) {
|
||||||
|
chat.position = goto.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_reply_keys(
|
fn handle_reply_keys(
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
settings: ResMut<settings::Settings>,
|
settings: ResMut<var::Settings>,
|
||||||
q_choices: Query<&Choice>,
|
q_choices: Query<&Choice>,
|
||||||
mut q_chats: Query<&mut Chat>,
|
mut q_chats: Query<&mut Chat>,
|
||||||
//mut evwriter_sendmsg: EventWriter<SendMessageEvent>,
|
|
||||||
mut evwriter_sfx: EventWriter<audio::PlaySfxEvent>,
|
mut evwriter_sfx: EventWriter<audio::PlaySfxEvent>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -17,7 +17,12 @@
|
||||||
|
|
||||||
|
|
||||||
- chat: Icarus
|
- chat: Icarus
|
||||||
|
- if $met:
|
||||||
|
- Oh hey, you're back!
|
||||||
|
- How are you doing?
|
||||||
|
- goto: howru
|
||||||
- Oh hey, you're awake!
|
- Oh hey, you're awake!
|
||||||
|
- set: $met
|
||||||
- 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!:
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
|
|
||||||
- chat: ClippyTransSerenity
|
- chat: ClippyTransSerenity
|
||||||
- set: busstop serenity
|
- set: $busstop serenity
|
||||||
- Welcome at StarTrans Cargo Services! You have reached Serenity Station.
|
- Welcome at StarTrans Cargo Services! You have reached Serenity Station.
|
||||||
- "Ready for a trip? Available bus stops: Oscillation Station, Metis Prime Station"
|
- "Ready for a trip? Available bus stops: Oscillation Station, Metis Prime Station"
|
||||||
- label: startransbusstop
|
- label: startransbusstop
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
|
|
||||||
- chat: ClippyTransMetis
|
- chat: ClippyTransMetis
|
||||||
- set: busstop metis
|
- set: $busstop metis
|
||||||
- Welcome at StarTrans Cargo Services! You have reached Metis Prime Station.
|
- Welcome at StarTrans Cargo Services! You have reached Metis Prime Station.
|
||||||
- "Ready for a trip? Available bus stops: Oscillation Station, Serenity Station"
|
- "Ready for a trip? Available bus stops: Oscillation Station, Serenity Station"
|
||||||
- label: startransbusstop
|
- label: startransbusstop
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
|
|
||||||
- chat: ClippyTransOscillation
|
- chat: ClippyTransOscillation
|
||||||
- set: busstop oscillation
|
- set: $busstop oscillation
|
||||||
- Welcome at StarTrans Cargo Services! You have reached Oscillation Station.
|
- Welcome at StarTrans Cargo Services! You have reached Oscillation Station.
|
||||||
- "Ready for a trip? Available bus stops: Serenity Station, Metis Prime Station"
|
- "Ready for a trip? Available bus stops: Serenity Station, Metis Prime Station"
|
||||||
- label: startransbusstop
|
- label: startransbusstop
|
||||||
|
@ -57,21 +57,21 @@
|
||||||
- Can I take a spacecraft with me?:
|
- Can I take a spacecraft with me?:
|
||||||
- Absolutely.
|
- Absolutely.
|
||||||
- goto: startransbusstop
|
- goto: startransbusstop
|
||||||
- if: busstop != "oscillation"
|
- if: $busstop != oscillation
|
||||||
Take me to Oscillation Station, please.:
|
Take me to Oscillation Station, please.:
|
||||||
- StarTrans wishes you a pleasant journey.
|
- StarTrans wishes you a pleasant journey.
|
||||||
- script: cryofadeout
|
- script: cryofadeout
|
||||||
- sleep: 5
|
- sleep: 5
|
||||||
- script: cryotrip oscillation
|
- script: cryotrip oscillation
|
||||||
- goto: EXIT
|
- goto: EXIT
|
||||||
- if: busstop != "metis"
|
- if: $busstop != metis
|
||||||
Take me to Metis Prime Station, please.:
|
Take me to Metis Prime Station, please.:
|
||||||
- StarTrans wishes you a pleasant journey.
|
- StarTrans wishes you a pleasant journey.
|
||||||
- script: cryofadeout
|
- script: cryofadeout
|
||||||
- sleep: 5
|
- sleep: 5
|
||||||
- script: cryotrip metisprime
|
- script: cryotrip metisprime
|
||||||
- goto: EXIT
|
- goto: EXIT
|
||||||
- if: busstop != "serenity"
|
- if: $busstop != serenity
|
||||||
Take me to Serenity Station, please.:
|
Take me to Serenity Station, please.:
|
||||||
- StarTrans wishes you a pleasant journey.
|
- StarTrans wishes you a pleasant journey.
|
||||||
- script: cryofadeout
|
- script: cryofadeout
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use crate::{camera, settings};
|
use crate::{camera, var};
|
||||||
|
|
||||||
pub struct EffectsPlugin;
|
pub struct EffectsPlugin;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ pub struct SpawnEffectEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup(
|
pub fn setup(
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
mut ew_effect: EventWriter<SpawnEffectEvent>,
|
mut ew_effect: EventWriter<SpawnEffectEvent>,
|
||||||
) {
|
) {
|
||||||
if !settings.dev_mode {
|
if !settings.dev_mode {
|
||||||
|
|
14
src/hud.rs
14
src/hud.rs
|
@ -1,4 +1,4 @@
|
||||||
use crate::{actor, audio, camera, chat, nature, settings, world};
|
use crate::{actor, audio, camera, chat, nature, var, world};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin};
|
use bevy::diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin};
|
||||||
use bevy::transform::TransformSystem;
|
use bevy::transform::TransformSystem;
|
||||||
|
@ -151,7 +151,7 @@ impl Log {
|
||||||
|
|
||||||
fn setup(
|
fn setup(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut log: ResMut<Log>,
|
mut log: ResMut<Log>,
|
||||||
mut ambient_light: ResMut<AmbientLight>,
|
mut ambient_light: ResMut<AmbientLight>,
|
||||||
|
@ -414,7 +414,7 @@ fn update_hud(
|
||||||
q_choices: Query<&chat::Choice>,
|
q_choices: Query<&chat::Choice>,
|
||||||
mut query_chat: Query<&mut Text, (With<ChatText>, Without<GaugesText>)>,
|
mut query_chat: Query<&mut Text, (With<ChatText>, Without<GaugesText>)>,
|
||||||
query_all_actors: Query<&actor::Actor>,
|
query_all_actors: Query<&actor::Actor>,
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
q_target: Query<(&IsClickable, Option<&Position>, Option<&LinearVelocity>), With<IsTargeted>>,
|
q_target: Query<(&IsClickable, Option<&Position>, Option<&LinearVelocity>), With<IsTargeted>>,
|
||||||
) {
|
) {
|
||||||
// TODO only when hud is actually on
|
// TODO only when hud is actually on
|
||||||
|
@ -563,7 +563,7 @@ fn update_hud(
|
||||||
fn handle_input(
|
fn handle_input(
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
mouse_input: Res<ButtonInput<MouseButton>>,
|
mouse_input: Res<ButtonInput<MouseButton>>,
|
||||||
mut settings: ResMut<settings::Settings>,
|
mut settings: ResMut<var::Settings>,
|
||||||
mut q_hud: Query<(&mut Visibility, Option<&OnlyHideWhenTogglingHud>), With<ToggleableHudElement>>,
|
mut q_hud: Query<(&mut Visibility, Option<&OnlyHideWhenTogglingHud>), With<ToggleableHudElement>>,
|
||||||
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
||||||
mut ew_togglemusic: EventWriter<audio::ToggleMusicEvent>,
|
mut ew_togglemusic: EventWriter<audio::ToggleMusicEvent>,
|
||||||
|
@ -607,7 +607,7 @@ fn handle_input(
|
||||||
|
|
||||||
fn handle_target_event(
|
fn handle_target_event(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
mut er_target: EventReader<TargetEvent>,
|
mut er_target: EventReader<TargetEvent>,
|
||||||
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
||||||
q_target: Query<Entity, With<IsTargeted>>,
|
q_target: Query<Entity, With<IsTargeted>>,
|
||||||
|
@ -631,7 +631,7 @@ fn handle_target_event(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_target_selectagon(
|
fn update_target_selectagon(
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
mut q_selectagon: Query<(&mut Transform, &mut Visibility), (With<Selectagon>, Without<IsTargeted>, Without<Camera>)>,
|
mut q_selectagon: Query<(&mut Transform, &mut Visibility), (With<Selectagon>, Without<IsTargeted>, Without<Camera>)>,
|
||||||
q_target: Query<&Transform, (With<IsTargeted>, Without<Camera>, Without<Selectagon>)>,
|
q_target: Query<&Transform, (With<IsTargeted>, Without<Camera>, Without<Selectagon>)>,
|
||||||
q_camera: Query<&Transform, (With<Camera>, Without<IsTargeted>, Without<Selectagon>)>,
|
q_camera: Query<&Transform, (With<Camera>, Without<IsTargeted>, Without<Selectagon>)>,
|
||||||
|
@ -671,7 +671,7 @@ fn update_target_selectagon(
|
||||||
fn update_ar_overlays (
|
fn update_ar_overlays (
|
||||||
q_owners: Query<(Entity, &Transform, &Visibility), (With<AugmentedRealityOverlayBroadcaster>, Without<AugmentedRealityOverlay>)>,
|
q_owners: Query<(Entity, &Transform, &Visibility), (With<AugmentedRealityOverlayBroadcaster>, Without<AugmentedRealityOverlay>)>,
|
||||||
mut q_overlays: Query<(&mut Transform, &mut Visibility, &mut AugmentedRealityOverlay)>,
|
mut q_overlays: Query<(&mut Transform, &mut Visibility, &mut AugmentedRealityOverlay)>,
|
||||||
settings: ResMut<settings::Settings>,
|
settings: ResMut<var::Settings>,
|
||||||
mut state: ResMut<AugmentedRealityState>,
|
mut state: ResMut<AugmentedRealityState>,
|
||||||
) {
|
) {
|
||||||
let (need_activate, need_clean, need_update);
|
let (need_activate, need_clean, need_update);
|
||||||
|
|
|
@ -5,8 +5,8 @@ mod chat;
|
||||||
mod commands;
|
mod commands;
|
||||||
mod effects;
|
mod effects;
|
||||||
mod hud;
|
mod hud;
|
||||||
mod settings;
|
|
||||||
mod stars;
|
mod stars;
|
||||||
|
mod var;
|
||||||
mod world;
|
mod world;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -47,7 +47,8 @@ impl Plugin for OutFlyPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
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(settings::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,
|
||||||
|
@ -77,7 +78,7 @@ fn setup(
|
||||||
|
|
||||||
fn handle_input(
|
fn handle_input(
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<var::Settings>,
|
||||||
mut app_exit_events: ResMut<Events<bevy::app::AppExit>>,
|
mut app_exit_events: ResMut<Events<bevy::app::AppExit>>,
|
||||||
mut windows: Query<&mut Window, With<PrimaryWindow>>,
|
mut windows: Query<&mut Window, With<PrimaryWindow>>,
|
||||||
) {
|
) {
|
||||||
|
|
190
src/settings.rs
190
src/settings.rs
|
@ -1,190 +0,0 @@
|
||||||
use bevy::prelude::*;
|
|
||||||
use std::env;
|
|
||||||
|
|
||||||
pub const DEFAULT_CHAT_SPEED: f32 = 10.0;
|
|
||||||
|
|
||||||
#[derive(Resource)]
|
|
||||||
pub struct Settings {
|
|
||||||
pub dev_mode: bool,
|
|
||||||
pub god_mode: bool,
|
|
||||||
pub mute_sfx: bool,
|
|
||||||
pub mute_music: bool,
|
|
||||||
pub volume_sfx: u8,
|
|
||||||
pub volume_music: u8,
|
|
||||||
pub mouse_sensitivity: f32,
|
|
||||||
pub fov: f32,
|
|
||||||
pub fov_highspeed: f32,
|
|
||||||
pub zoom_fov: f32,
|
|
||||||
pub zoom_sensitivity_factor: f32,
|
|
||||||
pub font_size_hud: f32,
|
|
||||||
pub font_size_conversations: f32,
|
|
||||||
pub chat_speed: f32,
|
|
||||||
pub hud_active: bool,
|
|
||||||
pub is_zooming: bool,
|
|
||||||
pub third_person: bool,
|
|
||||||
pub rotation_stabilizer_active: bool,
|
|
||||||
pub key_selectobject: MouseButton,
|
|
||||||
pub key_zoom: MouseButton,
|
|
||||||
pub key_togglehud: KeyCode,
|
|
||||||
pub key_exit: KeyCode,
|
|
||||||
pub key_restart: KeyCode,
|
|
||||||
pub key_fullscreen: KeyCode,
|
|
||||||
pub key_forward: KeyCode,
|
|
||||||
pub key_back: KeyCode,
|
|
||||||
pub key_left: KeyCode,
|
|
||||||
pub key_right: KeyCode,
|
|
||||||
pub key_up: KeyCode,
|
|
||||||
pub key_down: KeyCode,
|
|
||||||
pub key_run: KeyCode,
|
|
||||||
pub key_stop: KeyCode,
|
|
||||||
pub key_interact: KeyCode,
|
|
||||||
pub key_vehicle: KeyCode,
|
|
||||||
pub key_camera: KeyCode,
|
|
||||||
pub key_rotate: KeyCode,
|
|
||||||
pub key_rotation_stabilizer: KeyCode,
|
|
||||||
pub key_mouseup: KeyCode,
|
|
||||||
pub key_mousedown: KeyCode,
|
|
||||||
pub key_mouseleft: KeyCode,
|
|
||||||
pub key_mouseright: KeyCode,
|
|
||||||
pub key_rotateleft: KeyCode,
|
|
||||||
pub key_rotateright: KeyCode,
|
|
||||||
pub key_reply1: KeyCode,
|
|
||||||
pub key_reply2: KeyCode,
|
|
||||||
pub key_reply3: KeyCode,
|
|
||||||
pub key_reply4: KeyCode,
|
|
||||||
pub key_reply5: KeyCode,
|
|
||||||
pub key_reply6: KeyCode,
|
|
||||||
pub key_reply7: KeyCode,
|
|
||||||
pub key_reply8: KeyCode,
|
|
||||||
pub key_reply9: KeyCode,
|
|
||||||
pub key_reply10: KeyCode,
|
|
||||||
pub key_cheat_god_mode: KeyCode,
|
|
||||||
pub key_cheat_stop: KeyCode,
|
|
||||||
pub key_cheat_speed: KeyCode,
|
|
||||||
pub key_cheat_speed_backward: KeyCode,
|
|
||||||
pub key_cheat_pizza: KeyCode,
|
|
||||||
pub key_cheat_farview1: KeyCode,
|
|
||||||
pub key_cheat_farview2: KeyCode,
|
|
||||||
pub key_cheat_adrenaline_zero: KeyCode,
|
|
||||||
pub key_cheat_adrenaline_mid: KeyCode,
|
|
||||||
pub key_cheat_adrenaline_max: KeyCode,
|
|
||||||
pub key_cheat_die: KeyCode,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Settings {
|
|
||||||
fn default() -> Self {
|
|
||||||
let dev_mode;
|
|
||||||
|
|
||||||
let default_mute_sfx = false;
|
|
||||||
let default_mute_music;
|
|
||||||
if let Ok(_) = env::var("CARGO") {
|
|
||||||
// Mute audio by default when run through `cargo`
|
|
||||||
default_mute_music = cfg!(debug_assertions);
|
|
||||||
|
|
||||||
// Enable dev mode when running `cargo run` without `--release`
|
|
||||||
dev_mode = cfg!(debug_assertions);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
default_mute_music = false;
|
|
||||||
dev_mode = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Settings {
|
|
||||||
dev_mode,
|
|
||||||
god_mode: false,
|
|
||||||
mute_sfx: default_mute_sfx,
|
|
||||||
mute_music: default_mute_music,
|
|
||||||
volume_sfx: 100,
|
|
||||||
volume_music: 100,
|
|
||||||
mouse_sensitivity: 0.7,
|
|
||||||
fov: 50.0,
|
|
||||||
fov_highspeed: 25.0,
|
|
||||||
zoom_fov: 15.0,
|
|
||||||
zoom_sensitivity_factor: 0.25,
|
|
||||||
font_size_hud: 32.0,
|
|
||||||
font_size_conversations: 32.0,
|
|
||||||
chat_speed: DEFAULT_CHAT_SPEED,
|
|
||||||
hud_active: false,
|
|
||||||
is_zooming: false,
|
|
||||||
third_person: false,
|
|
||||||
rotation_stabilizer_active: true,
|
|
||||||
key_selectobject: MouseButton::Left,
|
|
||||||
key_zoom: MouseButton::Right,
|
|
||||||
key_togglehud: KeyCode::Tab,
|
|
||||||
key_exit: KeyCode::Escape,
|
|
||||||
key_restart: KeyCode::F7,
|
|
||||||
key_fullscreen: KeyCode::F11,
|
|
||||||
key_forward: KeyCode::KeyW,
|
|
||||||
key_back: KeyCode::KeyS,
|
|
||||||
key_left: KeyCode::KeyA,
|
|
||||||
key_right: KeyCode::KeyD,
|
|
||||||
key_up: KeyCode::ShiftLeft,
|
|
||||||
key_down: KeyCode::ControlLeft,
|
|
||||||
key_run: KeyCode::KeyR,
|
|
||||||
key_stop: KeyCode::Space,
|
|
||||||
key_interact: KeyCode::KeyE,
|
|
||||||
key_vehicle: KeyCode::KeyQ,
|
|
||||||
key_camera: KeyCode::KeyF,
|
|
||||||
key_rotate: KeyCode::KeyR,
|
|
||||||
key_rotation_stabilizer: KeyCode::KeyY,
|
|
||||||
key_mouseup: KeyCode::KeyI,
|
|
||||||
key_mousedown: KeyCode::KeyK,
|
|
||||||
key_mouseleft: KeyCode::KeyJ,
|
|
||||||
key_mouseright: KeyCode::KeyL,
|
|
||||||
key_rotateleft: KeyCode::KeyU,
|
|
||||||
key_rotateright: KeyCode::KeyO,
|
|
||||||
key_reply1: KeyCode::Digit1,
|
|
||||||
key_reply2: KeyCode::Digit2,
|
|
||||||
key_reply3: KeyCode::Digit3,
|
|
||||||
key_reply4: KeyCode::Digit4,
|
|
||||||
key_reply5: KeyCode::Digit5,
|
|
||||||
key_reply6: KeyCode::Digit6,
|
|
||||||
key_reply7: KeyCode::Digit7,
|
|
||||||
key_reply8: KeyCode::Digit8,
|
|
||||||
key_reply9: KeyCode::Digit9,
|
|
||||||
key_reply10: KeyCode::Digit0,
|
|
||||||
key_cheat_god_mode: KeyCode::KeyG,
|
|
||||||
key_cheat_stop: KeyCode::KeyC,
|
|
||||||
key_cheat_speed: KeyCode::KeyV,
|
|
||||||
key_cheat_speed_backward: KeyCode::KeyB,
|
|
||||||
key_cheat_pizza: KeyCode::F9,
|
|
||||||
key_cheat_farview1: KeyCode::F10,
|
|
||||||
key_cheat_farview2: KeyCode::F12,
|
|
||||||
key_cheat_adrenaline_zero: KeyCode::F5,
|
|
||||||
key_cheat_adrenaline_mid: KeyCode::F6,
|
|
||||||
key_cheat_adrenaline_max: KeyCode::F8,
|
|
||||||
key_cheat_die: KeyCode::KeyZ,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Settings {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn reset(&mut self) {
|
|
||||||
println!("Resetting settings!");
|
|
||||||
*self = Self::default();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reset_player_settings(&mut self) {
|
|
||||||
println!("Resetting player settings!");
|
|
||||||
let default = Self::default();
|
|
||||||
self.rotation_stabilizer_active = default.rotation_stabilizer_active;
|
|
||||||
self.third_person = default.third_person;
|
|
||||||
self.is_zooming = default.is_zooming;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_reply_keys(&self) -> [KeyCode; 10] {
|
|
||||||
return [
|
|
||||||
self.key_reply1,
|
|
||||||
self.key_reply2,
|
|
||||||
self.key_reply3,
|
|
||||||
self.key_reply4,
|
|
||||||
self.key_reply5,
|
|
||||||
self.key_reply6,
|
|
||||||
self.key_reply7,
|
|
||||||
self.key_reply8,
|
|
||||||
self.key_reply9,
|
|
||||||
self.key_reply10,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
385
src/var.rs
Normal file
385
src/var.rs
Normal file
|
@ -0,0 +1,385 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
pub const SCOPE_SEPARATOR: &str = "$";
|
||||||
|
|
||||||
|
pub const TOKEN_EQUALS: &str = "==";
|
||||||
|
pub const TOKEN_EQUALS_NOT: &str = "!=";
|
||||||
|
pub const TOKEN_GREATER_THAN: &str = ">";
|
||||||
|
pub const TOKEN_LESS_THAN: &str = "<";
|
||||||
|
pub const TOKEN_GREATER_EQUALS: &str = ">=";
|
||||||
|
pub const TOKEN_LESS_EQUALS: &str = "<=";
|
||||||
|
|
||||||
|
pub const DEFAULT_CHAT_SPEED: f32 = 10.0;
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
|
pub struct Settings {
|
||||||
|
pub dev_mode: bool,
|
||||||
|
pub god_mode: bool,
|
||||||
|
pub mute_sfx: bool,
|
||||||
|
pub mute_music: bool,
|
||||||
|
pub volume_sfx: u8,
|
||||||
|
pub volume_music: u8,
|
||||||
|
pub mouse_sensitivity: f32,
|
||||||
|
pub fov: f32,
|
||||||
|
pub fov_highspeed: f32,
|
||||||
|
pub zoom_fov: f32,
|
||||||
|
pub zoom_sensitivity_factor: f32,
|
||||||
|
pub font_size_hud: f32,
|
||||||
|
pub font_size_conversations: f32,
|
||||||
|
pub chat_speed: f32,
|
||||||
|
pub hud_active: bool,
|
||||||
|
pub is_zooming: bool,
|
||||||
|
pub third_person: bool,
|
||||||
|
pub rotation_stabilizer_active: bool,
|
||||||
|
pub key_selectobject: MouseButton,
|
||||||
|
pub key_zoom: MouseButton,
|
||||||
|
pub key_togglehud: KeyCode,
|
||||||
|
pub key_exit: KeyCode,
|
||||||
|
pub key_restart: KeyCode,
|
||||||
|
pub key_fullscreen: KeyCode,
|
||||||
|
pub key_forward: KeyCode,
|
||||||
|
pub key_back: KeyCode,
|
||||||
|
pub key_left: KeyCode,
|
||||||
|
pub key_right: KeyCode,
|
||||||
|
pub key_up: KeyCode,
|
||||||
|
pub key_down: KeyCode,
|
||||||
|
pub key_run: KeyCode,
|
||||||
|
pub key_stop: KeyCode,
|
||||||
|
pub key_interact: KeyCode,
|
||||||
|
pub key_vehicle: KeyCode,
|
||||||
|
pub key_camera: KeyCode,
|
||||||
|
pub key_rotate: KeyCode,
|
||||||
|
pub key_rotation_stabilizer: KeyCode,
|
||||||
|
pub key_mouseup: KeyCode,
|
||||||
|
pub key_mousedown: KeyCode,
|
||||||
|
pub key_mouseleft: KeyCode,
|
||||||
|
pub key_mouseright: KeyCode,
|
||||||
|
pub key_rotateleft: KeyCode,
|
||||||
|
pub key_rotateright: KeyCode,
|
||||||
|
pub key_reply1: KeyCode,
|
||||||
|
pub key_reply2: KeyCode,
|
||||||
|
pub key_reply3: KeyCode,
|
||||||
|
pub key_reply4: KeyCode,
|
||||||
|
pub key_reply5: KeyCode,
|
||||||
|
pub key_reply6: KeyCode,
|
||||||
|
pub key_reply7: KeyCode,
|
||||||
|
pub key_reply8: KeyCode,
|
||||||
|
pub key_reply9: KeyCode,
|
||||||
|
pub key_reply10: KeyCode,
|
||||||
|
pub key_cheat_god_mode: KeyCode,
|
||||||
|
pub key_cheat_stop: KeyCode,
|
||||||
|
pub key_cheat_speed: KeyCode,
|
||||||
|
pub key_cheat_speed_backward: KeyCode,
|
||||||
|
pub key_cheat_pizza: KeyCode,
|
||||||
|
pub key_cheat_farview1: KeyCode,
|
||||||
|
pub key_cheat_farview2: KeyCode,
|
||||||
|
pub key_cheat_adrenaline_zero: KeyCode,
|
||||||
|
pub key_cheat_adrenaline_mid: KeyCode,
|
||||||
|
pub key_cheat_adrenaline_max: KeyCode,
|
||||||
|
pub key_cheat_die: KeyCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Settings {
|
||||||
|
fn default() -> Self {
|
||||||
|
let dev_mode;
|
||||||
|
|
||||||
|
let default_mute_sfx = false;
|
||||||
|
let default_mute_music;
|
||||||
|
if let Ok(_) = env::var("CARGO") {
|
||||||
|
// Mute audio by default when run through `cargo`
|
||||||
|
default_mute_music = cfg!(debug_assertions);
|
||||||
|
|
||||||
|
// Enable dev mode when running `cargo run` without `--release`
|
||||||
|
dev_mode = cfg!(debug_assertions);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
default_mute_music = false;
|
||||||
|
dev_mode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings {
|
||||||
|
dev_mode,
|
||||||
|
god_mode: false,
|
||||||
|
mute_sfx: default_mute_sfx,
|
||||||
|
mute_music: default_mute_music,
|
||||||
|
volume_sfx: 100,
|
||||||
|
volume_music: 100,
|
||||||
|
mouse_sensitivity: 0.7,
|
||||||
|
fov: 50.0,
|
||||||
|
fov_highspeed: 25.0,
|
||||||
|
zoom_fov: 15.0,
|
||||||
|
zoom_sensitivity_factor: 0.25,
|
||||||
|
font_size_hud: 32.0,
|
||||||
|
font_size_conversations: 32.0,
|
||||||
|
chat_speed: DEFAULT_CHAT_SPEED,
|
||||||
|
hud_active: false,
|
||||||
|
is_zooming: false,
|
||||||
|
third_person: false,
|
||||||
|
rotation_stabilizer_active: true,
|
||||||
|
key_selectobject: MouseButton::Left,
|
||||||
|
key_zoom: MouseButton::Right,
|
||||||
|
key_togglehud: KeyCode::Tab,
|
||||||
|
key_exit: KeyCode::Escape,
|
||||||
|
key_restart: KeyCode::F7,
|
||||||
|
key_fullscreen: KeyCode::F11,
|
||||||
|
key_forward: KeyCode::KeyW,
|
||||||
|
key_back: KeyCode::KeyS,
|
||||||
|
key_left: KeyCode::KeyA,
|
||||||
|
key_right: KeyCode::KeyD,
|
||||||
|
key_up: KeyCode::ShiftLeft,
|
||||||
|
key_down: KeyCode::ControlLeft,
|
||||||
|
key_run: KeyCode::KeyR,
|
||||||
|
key_stop: KeyCode::Space,
|
||||||
|
key_interact: KeyCode::KeyE,
|
||||||
|
key_vehicle: KeyCode::KeyQ,
|
||||||
|
key_camera: KeyCode::KeyF,
|
||||||
|
key_rotate: KeyCode::KeyR,
|
||||||
|
key_rotation_stabilizer: KeyCode::KeyY,
|
||||||
|
key_mouseup: KeyCode::KeyI,
|
||||||
|
key_mousedown: KeyCode::KeyK,
|
||||||
|
key_mouseleft: KeyCode::KeyJ,
|
||||||
|
key_mouseright: KeyCode::KeyL,
|
||||||
|
key_rotateleft: KeyCode::KeyU,
|
||||||
|
key_rotateright: KeyCode::KeyO,
|
||||||
|
key_reply1: KeyCode::Digit1,
|
||||||
|
key_reply2: KeyCode::Digit2,
|
||||||
|
key_reply3: KeyCode::Digit3,
|
||||||
|
key_reply4: KeyCode::Digit4,
|
||||||
|
key_reply5: KeyCode::Digit5,
|
||||||
|
key_reply6: KeyCode::Digit6,
|
||||||
|
key_reply7: KeyCode::Digit7,
|
||||||
|
key_reply8: KeyCode::Digit8,
|
||||||
|
key_reply9: KeyCode::Digit9,
|
||||||
|
key_reply10: KeyCode::Digit0,
|
||||||
|
key_cheat_god_mode: KeyCode::KeyG,
|
||||||
|
key_cheat_stop: KeyCode::KeyC,
|
||||||
|
key_cheat_speed: KeyCode::KeyV,
|
||||||
|
key_cheat_speed_backward: KeyCode::KeyB,
|
||||||
|
key_cheat_pizza: KeyCode::F9,
|
||||||
|
key_cheat_farview1: KeyCode::F10,
|
||||||
|
key_cheat_farview2: KeyCode::F12,
|
||||||
|
key_cheat_adrenaline_zero: KeyCode::F5,
|
||||||
|
key_cheat_adrenaline_mid: KeyCode::F6,
|
||||||
|
key_cheat_adrenaline_max: KeyCode::F8,
|
||||||
|
key_cheat_die: KeyCode::KeyZ,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Settings {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
println!("Resetting settings!");
|
||||||
|
*self = Self::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_player_settings(&mut self) {
|
||||||
|
println!("Resetting player settings!");
|
||||||
|
let default = Self::default();
|
||||||
|
self.rotation_stabilizer_active = default.rotation_stabilizer_active;
|
||||||
|
self.third_person = default.third_person;
|
||||||
|
self.is_zooming = default.is_zooming;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_reply_keys(&self) -> [KeyCode; 10] {
|
||||||
|
return [
|
||||||
|
self.key_reply1,
|
||||||
|
self.key_reply2,
|
||||||
|
self.key_reply3,
|
||||||
|
self.key_reply4,
|
||||||
|
self.key_reply5,
|
||||||
|
self.key_reply6,
|
||||||
|
self.key_reply7,
|
||||||
|
self.key_reply8,
|
||||||
|
self.key_reply9,
|
||||||
|
self.key_reply10,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
|
pub struct GameVars {
|
||||||
|
pub db: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for GameVars {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
db: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GameVars {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn get(&self, key: &str) -> Option<String> {
|
||||||
|
if let Some(value) = self.db.get(key) {
|
||||||
|
return Some(value.clone());
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getb(&self, key: &str) -> bool {
|
||||||
|
if let Some(value) = self.db.get(key) {
|
||||||
|
return Self::evaluate_str_as_bool(value);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn evaluate_str_as_bool(string: &str) -> bool {
|
||||||
|
return string != "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method ensures that the variable name contains a scope separator,
|
||||||
|
// and if a scope is missing, it prefixes the fallback scope.
|
||||||
|
// Should NOT be used on non-variable values, like plain strings.
|
||||||
|
//
|
||||||
|
// Some examples, assuming fallback_scope="Clippy", SCOPE_SEPARATOR="$":
|
||||||
|
//
|
||||||
|
// "" -> "clippy$"
|
||||||
|
// "foo" -> "clippy$foo"
|
||||||
|
// "FOO" -> "clippy$foo"
|
||||||
|
// "$foo" -> "clippy$foo"
|
||||||
|
// "$$foo" -> "$$foo"
|
||||||
|
// "PizzaClippy$foo" -> "pizzaclippy$foo" (unchanged)
|
||||||
|
// "$foo$foo$foo$foo" -> "$foo$foo$foo$foo" (unchanged)
|
||||||
|
pub fn normalize_varname(fallback_scope: &str, key: &str) -> String {
|
||||||
|
let parts: Vec<&str> = key.split(SCOPE_SEPARATOR).collect();
|
||||||
|
let key: String = if parts.len() == 1 {
|
||||||
|
// we got a key like "foo", turn it into "<scope>$foo"
|
||||||
|
fallback_scope.to_string() + SCOPE_SEPARATOR + key
|
||||||
|
} else if parts.len() > 1 {
|
||||||
|
// we got a key with at least one "$"
|
||||||
|
// extract anything before the last "$":
|
||||||
|
let scope_part: String = parts[0..parts.len() - 2].join(SCOPE_SEPARATOR);
|
||||||
|
|
||||||
|
if scope_part.is_empty() {
|
||||||
|
// we got a key like "$foo", just prefix the fallback scope
|
||||||
|
fallback_scope.to_string() + key
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// we got a key like "Ke$ha$foo" or "$$foo" (which is the convention for
|
||||||
|
// global variables), leave the scope intact
|
||||||
|
key.to_string()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we got an empty string. this is bad, but handle gracefully
|
||||||
|
fallback_scope.to_string() + SCOPE_SEPARATOR
|
||||||
|
};
|
||||||
|
return key.to_lowercase();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_in_scope(&mut self, fallback_scope: &str, key: &str, value: String) {
|
||||||
|
let key = Self::normalize_varname(fallback_scope, key);
|
||||||
|
self.db.insert(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn evaluate_condition(&self, condition: &str, scope: &str) -> bool {
|
||||||
|
let parts: Vec<&str> = condition.split(" ").collect();
|
||||||
|
if parts.len() == 0 {
|
||||||
|
// Got an empty string, this is always false.
|
||||||
|
return false;
|
||||||
|
} else if parts.len() == 1 {
|
||||||
|
// Got something like "if $somevar:".
|
||||||
|
// Check whether the variable evaluates to true.
|
||||||
|
let part = parts[0];
|
||||||
|
if part.contains(SCOPE_SEPARATOR) {
|
||||||
|
let part = Self::normalize_varname(scope, part);
|
||||||
|
let value_bool = self.getb(part.as_str());
|
||||||
|
return value_bool;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Self::evaluate_str_as_bool(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if parts.len() == 2 {
|
||||||
|
// Got something like "if $something somethingelse"
|
||||||
|
// Check whether the two are identical.
|
||||||
|
let mut left: String = parts[0].to_string();
|
||||||
|
if left.contains(SCOPE_SEPARATOR) {
|
||||||
|
left = self
|
||||||
|
.get(Self::normalize_varname(scope, left.as_str()).as_str())
|
||||||
|
.unwrap_or("".to_string());
|
||||||
|
}
|
||||||
|
let mut right: String = parts[1].to_string();
|
||||||
|
if right.contains(SCOPE_SEPARATOR) {
|
||||||
|
right = self
|
||||||
|
.get(Self::normalize_varname(scope, right.as_str()).as_str())
|
||||||
|
.unwrap_or("".to_string());
|
||||||
|
}
|
||||||
|
return left == right;
|
||||||
|
} else {
|
||||||
|
// Got something like "if $something != somethingelse bla bla"
|
||||||
|
let mut left: String = parts[0].to_string();
|
||||||
|
if left.contains(SCOPE_SEPARATOR) {
|
||||||
|
left = self
|
||||||
|
.get(Self::normalize_varname(scope, left.as_str()).as_str())
|
||||||
|
.unwrap_or("".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut right: String = parts[2..parts.len()].join(" ").to_string();
|
||||||
|
if right.contains(SCOPE_SEPARATOR) {
|
||||||
|
right = self
|
||||||
|
.get(Self::normalize_varname(scope, right.as_str()).as_str())
|
||||||
|
.unwrap_or("".to_string());
|
||||||
|
}
|
||||||
|
let floats = (left.parse::<f64>(), right.parse::<f64>());
|
||||||
|
let operator: &str = parts[1];
|
||||||
|
|
||||||
|
match operator {
|
||||||
|
TOKEN_EQUALS => {
|
||||||
|
if let (Ok(left), Ok(right)) = floats {
|
||||||
|
return left == right;
|
||||||
|
}
|
||||||
|
return left == right;
|
||||||
|
}
|
||||||
|
TOKEN_EQUALS_NOT => {
|
||||||
|
if let (Ok(left), Ok(right)) = floats {
|
||||||
|
return left != right;
|
||||||
|
}
|
||||||
|
return left != right;
|
||||||
|
}
|
||||||
|
TOKEN_GREATER_THAN => {
|
||||||
|
if let (Ok(left), Ok(right)) = floats {
|
||||||
|
return left > right;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TOKEN_GREATER_EQUALS => {
|
||||||
|
if let (Ok(left), Ok(right)) = floats {
|
||||||
|
return left >= right;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TOKEN_LESS_THAN => {
|
||||||
|
if let (Ok(left), Ok(right)) = floats {
|
||||||
|
return left < right;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TOKEN_LESS_EQUALS => {
|
||||||
|
if let (Ok(left), Ok(right)) = floats {
|
||||||
|
return left <= right;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
error!("Unknown operator '{operator}' in if-condition!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{actor, audio, hud, nature, settings, stars};
|
use crate::{actor, audio, hud, nature, stars, var};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::render::render_resource::{AsBindGroup, ShaderRef};
|
use bevy::render::render_resource::{AsBindGroup, ShaderRef};
|
||||||
use bevy::math::{DVec3, I64Vec3};
|
use bevy::math::{DVec3, I64Vec3};
|
||||||
|
@ -385,7 +385,7 @@ fn handle_cheats(
|
||||||
mut q_player: Query<(&Transform, &mut Position, &mut LinearVelocity), With<actor::PlayerCamera>>,
|
mut q_player: Query<(&Transform, &mut Position, &mut LinearVelocity), With<actor::PlayerCamera>>,
|
||||||
mut q_life: Query<(&mut actor::LifeForm, &mut actor::ExperiencesGForce), With<actor::Player>>,
|
mut q_life: Query<(&mut actor::LifeForm, &mut actor::ExperiencesGForce), With<actor::Player>>,
|
||||||
mut ew_playerdies: EventWriter<actor::PlayerDiesEvent>,
|
mut ew_playerdies: EventWriter<actor::PlayerDiesEvent>,
|
||||||
mut settings: ResMut<settings::Settings>,
|
mut settings: ResMut<var::Settings>,
|
||||||
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
||||||
) {
|
) {
|
||||||
if q_player.is_empty() || q_life.is_empty() {
|
if q_player.is_empty() || q_life.is_empty() {
|
||||||
|
|
Loading…
Reference in a new issue