diff --git a/assets/models/orb_busstop.glb b/assets/models/orb_busstop.glb new file mode 100644 index 0000000..a3dd753 Binary files /dev/null and b/assets/models/orb_busstop.glb differ 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