From a6f6b8b58287e720d9e4951daf606b918817e028 Mon Sep 17 00:00:00 2001 From: hut Date: Thu, 11 Apr 2024 01:12:07 +0200 Subject: [PATCH] implement bus stops (no riding yet) --- assets/models/orb_busstop.glb | Bin 0 -> 13396 bytes src/chat.rs | 22 +++++++++- src/commands.rs | 18 +++++++- src/defs.txt | 79 ++++++++++++++++++++++++++++++++++ src/effects.rs | 51 +++++++++++++++++++--- src/world.rs | 2 + 6 files changed, 164 insertions(+), 8 deletions(-) create mode 100644 assets/models/orb_busstop.glb diff --git a/assets/models/orb_busstop.glb b/assets/models/orb_busstop.glb new file mode 100644 index 0000000000000000000000000000000000000000..a3dd7537a36f55362af2b1848f8224dd0e826377 GIT binary patch literal 13396 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 Q!$yIQ*t`ceK*p&51G33{KL7v# literal 0 HcmV?d00001 diff --git a/src/chat.rs b/src/chat.rs index 853516c..c02351f 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -1,5 +1,5 @@ use bevy::prelude::*; -use crate::{actor, audio, hud, settings, world}; +use crate::{actor, audio, hud, settings, world, effects}; pub struct ChatPlugin; impl Plugin for ChatPlugin { @@ -301,6 +301,8 @@ pub fn handle_chat_scripts( mut er_chatscript: EventReader, mut q_actor: Query<(&mut actor::Actor, &mut actor::Suit), Without>, mut q_player: Query<(&mut actor::Actor, &mut actor::Suit), With>, + mut ew_sfx: EventWriter, + mut ew_effect: EventWriter, ) { for script in er_chatscript.read() { match script.name.as_str() { @@ -334,7 +336,23 @@ pub fn handle_chat_scripts( } else { error!("Invalid parameter for command `{}`: `{}`", script.name, script.param); } - _ => {} + "cryotrip" => { + ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::WakeUp)); + ew_effect.send(effects::SpawnEffectEvent { + class: effects::Effects::FadeIn(Color::CYAN), + duration: 1.0, + }); + } + "cryofadeout" => { + ew_effect.send(effects::SpawnEffectEvent { + class: effects::Effects::FadeOut(Color::CYAN), + duration: 5.1, + }); + } + _ => { + let script_name = &script.name; + error!("Error, undefined chat script {script_name}"); + } } } } diff --git a/src/commands.rs b/src/commands.rs index 48020e6..f2634a8 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -80,6 +80,7 @@ struct ParserState { script: String, script_parameter: String, script_parameter2: String, + sound: Option, } impl Default for ParserState { fn default() -> Self { @@ -134,6 +135,7 @@ impl Default for ParserState { script: "".to_string(), script_parameter: "".to_string(), script_parameter2: "".to_string(), + sound: Some("chat".to_string()), } } } @@ -146,6 +148,10 @@ impl ParserState { self.level = default.level; self.text = default.text; self.is_choice = default.is_choice; + self.script = default.script; + self.script_parameter = default.script_parameter; + self.script_parameter2 = default.script_parameter2; + self.sound = default.sound; } fn as_chatbranch(&self) -> chat::ChatBranch { return chat::ChatBranch { @@ -153,7 +159,7 @@ impl ParserState { name: self.name.clone().unwrap_or("".to_string()), label: self.label.clone(), delay: self.delay.clone(), - sound: if self.is_choice { "".to_string() } else { "chat".to_string() }, + 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() }, @@ -228,6 +234,8 @@ pub fn load_defs( } } ["relativeto", id] => { + // NOTE: call this command before "id", otherwise actors that + // set their position relative to this actor will get the wrong offset match id2pos.get(&id.to_string()) { Some(pos) => { state.pos += *pos; @@ -542,6 +550,11 @@ pub fn load_defs( 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(); @@ -552,6 +565,9 @@ pub fn load_defs( state.script_parameter = parameter.to_string(); state.script_parameter2 = parameter2.to_string(); } + ["sound", "none"] => { + state.sound = None; + } _ => { error!("No match for [{}]", parts.join(",")); } diff --git a/src/defs.txt b/src/defs.txt index 0d163a1..0bc92cd 100644 --- a/src/defs.txt +++ b/src/defs.txt @@ -361,6 +361,85 @@ actor -300 0 40 suit script refilloxygen 1 drifter msg 0 outcold EXIT "" +actor 100 -18000 2000 "orb_busstop" + relativeto player + id "busstop" + name "StarTrans Bus Station 'River of Time'" + scale 100 + wants maxrotation 0 + wants maxvelocity 0 + actor 120 864 150 clippy + relativeto "busstop" + id "busstopclippy" + name "StarTrans Clippy™" + armodel clippy_ar + angularmomentum 0 0 0 + wants maxrotation 0 + wants maxvelocity 0 + thrust 15 6 3 400 0.5 + rotationy -0.5 + scale 3 + chatid "busstopclippy" + chat "busstopclippy" + name "StarTrans Clippy™" + msg 2 INIT question "You have reached the bus station 'River of Time'" + msg 2 question wait "Ready for a trip? Available stops: Oscillation Station, J-Prime Station" + msg 40 wait answer "" + sound none + choice 2 answer how1 "Bus stop?! How does this work?" + msg 6 how1 how2 "StarTrans Cargo Service is the most convenient way to travel the vast distances of space." + msg 6 how2 how3 "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." + msg 40 how3 answer "Of course we will supply you with free oxygen and ensure your safety." + choice 1 answer stopA1 "Take me to Oscillation Station, please." + msg 5 stopA1 stopA2 "StarTrans wishes you a pleasant journey." + script cryofadeout + msg 0 stopA2 EXIT "" + script cryotrip oscillation + sound none + choice 1 answer stopB1 "Take me to J-Prime Station, please." + msg 5 stopB1 stopB2 "StarTrans wishes you a pleasant journey." + script cryofadeout + msg 0 stopB2 EXIT "" + script cryotrip jprime + choice 1 answer oxy "Can you please fill up my oxygen tank without taking me anywhere?" + msg 2 oxy EXIT "Acceptable." + script refilloxygen 1000 + sound none + choice 2 answer bye "No, thank you." + msg 2 bye EXIT "Feel free to come back any time." + msg 0 answer EXIT "Connection terminated." + actor 40 10 40 "orb_busstop" + name "Light Orb" + relativeto busstopclippy + light "47FF00" 1000000 + actor 30 60 -10 "orb_busstop" + name "Light Orb" + relativeto busstopclippy + light "47FF00" 1000000 + actor -10 -60 20 "orb_busstop" + name "Light Orb" + relativeto busstopclippy + light "47FF00" 1000000 + actor -40 20 30 "orb_busstop" + name "Light Orb" + relativeto busstopclippy + light "47FF00" 1000000 + actor 8 2 0 suit + relativeto "busstopclippy" + name "Mayhem" + wants maxrotation 0.2 + wants maxvelocity 0 + thrust 1.2 1 1 400 1.5 + scale 2 + collider capsule 1 0.5 + chatid "busstop1clippynpc1" + chat "busstop1clippynpc1" + name "Rudy" + msg 3 INIT cryo "Error: No response" + lvl info + msg 0 cryo EXIT "Lifeform in cryostasis detected." + lvl info + chat error name ERROR msg 0 INIT EXIT "Unspecified conversation ID" diff --git a/src/effects.rs b/src/effects.rs index 2586ef8..db9ec8b 100644 --- a/src/effects.rs +++ b/src/effects.rs @@ -8,7 +8,8 @@ impl Plugin for EffectsPlugin { app.add_systems(Startup, setup); app.add_systems(Startup, spawn_effects.after(setup).after(camera::setup_camera)); app.add_systems(Update, spawn_effects); - app.add_systems(Update, update_fadeblack); + app.add_systems(Update, update_fadein); + app.add_systems(Update, update_fadeout); // Blackout disabled for now //app.add_systems(Update, update_blackout); app.add_event::(); @@ -18,12 +19,14 @@ impl Plugin for EffectsPlugin { #[derive(Clone)] pub enum Effects { FadeIn(Color), + FadeOut(Color), } // Blackout disabled for now //#[derive(Component)] pub struct BlackOutOverlay; -#[derive(Component)] pub struct FadeBlack; +#[derive(Component)] pub struct FadeIn; +#[derive(Component)] pub struct FadeOut; #[derive(Component)] pub struct Effect { pub class: Effects, @@ -76,7 +79,7 @@ pub fn spawn_effects( duration: effect.duration, start_time: now, }, - FadeBlack, + FadeIn, NodeBundle { style: Style { width: Val::Vw(100.0), @@ -91,14 +94,36 @@ pub fn spawn_effects( }, )); }, + Effects::FadeOut(color) => { + commands.spawn(( + Effect { + class: effect.class.clone(), + duration: effect.duration, + start_time: now, + }, + FadeOut, + NodeBundle { + style: Style { + width: Val::Vw(100.0), + height: Val::Vh(100.0), + position_type: PositionType::Absolute, + top: Val::Px(0.0), + left: Val::Px(0.0), + ..default() + }, + background_color: color.with_a(0.0).into(), + ..default() + }, + )); + }, //_ => {}, } } } -pub fn update_fadeblack( +pub fn update_fadein( mut commands: Commands, - mut q_effect: Query<(Entity, &Effect, &mut BackgroundColor), With>, + mut q_effect: Query<(Entity, &Effect, &mut BackgroundColor), With>, time: Res