implement bus stops (no riding yet)

This commit is contained in:
yuni 2024-04-11 01:12:07 +02:00
parent db3545e9a3
commit a6f6b8b582
6 changed files with 164 additions and 8 deletions

Binary file not shown.

View file

@ -1,5 +1,5 @@
use bevy::prelude::*; use bevy::prelude::*;
use crate::{actor, audio, hud, settings, world}; use crate::{actor, audio, hud, settings, world, effects};
pub struct ChatPlugin; pub struct ChatPlugin;
impl Plugin for ChatPlugin { impl Plugin for ChatPlugin {
@ -301,6 +301,8 @@ pub fn handle_chat_scripts(
mut er_chatscript: EventReader<ChatScriptEvent>, mut er_chatscript: EventReader<ChatScriptEvent>,
mut q_actor: Query<(&mut actor::Actor, &mut actor::Suit), Without<actor::Player>>, mut q_actor: Query<(&mut actor::Actor, &mut actor::Suit), Without<actor::Player>>,
mut q_player: Query<(&mut actor::Actor, &mut actor::Suit), With<actor::Player>>, mut q_player: Query<(&mut actor::Actor, &mut actor::Suit), With<actor::Player>>,
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
mut ew_effect: EventWriter<effects::SpawnEffectEvent>,
) { ) {
for script in er_chatscript.read() { for script in er_chatscript.read() {
match script.name.as_str() { match script.name.as_str() {
@ -334,7 +336,23 @@ pub fn handle_chat_scripts(
} else { } else {
error!("Invalid parameter for command `{}`: `{}`", script.name, script.param); 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}");
}
} }
} }
} }

View file

@ -80,6 +80,7 @@ struct ParserState {
script: String, script: String,
script_parameter: String, script_parameter: String,
script_parameter2: String, script_parameter2: String,
sound: Option<String>,
} }
impl Default for ParserState { impl Default for ParserState {
fn default() -> Self { fn default() -> Self {
@ -134,6 +135,7 @@ impl Default for ParserState {
script: "".to_string(), script: "".to_string(),
script_parameter: "".to_string(), script_parameter: "".to_string(),
script_parameter2: "".to_string(), script_parameter2: "".to_string(),
sound: Some("chat".to_string()),
} }
} }
} }
@ -146,6 +148,10 @@ impl ParserState {
self.level = default.level; self.level = default.level;
self.text = default.text; self.text = default.text;
self.is_choice = default.is_choice; 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 { fn as_chatbranch(&self) -> chat::ChatBranch {
return chat::ChatBranch { return chat::ChatBranch {
@ -153,7 +159,7 @@ impl ParserState {
name: self.name.clone().unwrap_or("".to_string()), name: self.name.clone().unwrap_or("".to_string()),
label: self.label.clone(), label: self.label.clone(),
delay: self.delay.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(), level: self.level.clone(),
reply: if self.is_choice { "".to_string() } else { self.text.clone() }, reply: if self.is_choice { "".to_string() } else { self.text.clone() },
choice: if self.is_choice { self.text.clone() } else { "".to_string() }, choice: if self.is_choice { self.text.clone() } else { "".to_string() },
@ -228,6 +234,8 @@ pub fn load_defs(
} }
} }
["relativeto", id] => { ["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()) { match id2pos.get(&id.to_string()) {
Some(pos) => { Some(pos) => {
state.pos += *pos; state.pos += *pos;
@ -542,6 +550,11 @@ pub fn load_defs(
debug!("Registering level: {}", level); debug!("Registering level: {}", level);
state.level = level.to_string(); 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] => { ["script", scriptname, parameter] => {
state.script = scriptname.to_string(); state.script = scriptname.to_string();
state.script_parameter = parameter.to_string(); state.script_parameter = parameter.to_string();
@ -552,6 +565,9 @@ pub fn load_defs(
state.script_parameter = parameter.to_string(); state.script_parameter = parameter.to_string();
state.script_parameter2 = parameter2.to_string(); state.script_parameter2 = parameter2.to_string();
} }
["sound", "none"] => {
state.sound = None;
}
_ => { _ => {
error!("No match for [{}]", parts.join(",")); error!("No match for [{}]", parts.join(","));
} }

View file

@ -361,6 +361,85 @@ actor -300 0 40 suit
script refilloxygen 1 drifter script refilloxygen 1 drifter
msg 0 outcold EXIT "" 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 chat error
name ERROR name ERROR
msg 0 INIT EXIT "Unspecified conversation ID" msg 0 INIT EXIT "Unspecified conversation ID"

View file

@ -8,7 +8,8 @@ impl Plugin for EffectsPlugin {
app.add_systems(Startup, setup); app.add_systems(Startup, setup);
app.add_systems(Startup, spawn_effects.after(setup).after(camera::setup_camera)); app.add_systems(Startup, spawn_effects.after(setup).after(camera::setup_camera));
app.add_systems(Update, spawn_effects); 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 // Blackout disabled for now
//app.add_systems(Update, update_blackout); //app.add_systems(Update, update_blackout);
app.add_event::<SpawnEffectEvent>(); app.add_event::<SpawnEffectEvent>();
@ -18,12 +19,14 @@ impl Plugin for EffectsPlugin {
#[derive(Clone)] #[derive(Clone)]
pub enum Effects { pub enum Effects {
FadeIn(Color), FadeIn(Color),
FadeOut(Color),
} }
// Blackout disabled for now // Blackout disabled for now
//#[derive(Component)] pub struct BlackOutOverlay; //#[derive(Component)] pub struct BlackOutOverlay;
#[derive(Component)] pub struct FadeBlack; #[derive(Component)] pub struct FadeIn;
#[derive(Component)] pub struct FadeOut;
#[derive(Component)] #[derive(Component)]
pub struct Effect { pub struct Effect {
pub class: Effects, pub class: Effects,
@ -76,7 +79,7 @@ pub fn spawn_effects(
duration: effect.duration, duration: effect.duration,
start_time: now, start_time: now,
}, },
FadeBlack, FadeIn,
NodeBundle { NodeBundle {
style: Style { style: Style {
width: Val::Vw(100.0), 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 commands: Commands,
mut q_effect: Query<(Entity, &Effect, &mut BackgroundColor), With<FadeBlack>>, mut q_effect: Query<(Entity, &Effect, &mut BackgroundColor), With<FadeIn>>,
time: Res<Time>, time: Res<Time>,
) { ) {
for (entity, effect, mut bgcolor) in &mut q_effect { for (entity, effect, mut bgcolor) in &mut q_effect {
@ -112,6 +137,22 @@ pub fn update_fadeblack(
} }
} }
pub fn update_fadeout(
mut commands: Commands,
mut q_effect: Query<(Entity, &Effect, &mut BackgroundColor), With<FadeOut>>,
time: Res<Time>,
) {
for (entity, effect, mut bgcolor) in &mut q_effect {
let now = time.elapsed_seconds_f64();
if effect.start_time + effect.duration < now {
commands.entity(entity).despawn();
continue;
}
let alpha = ((now - effect.start_time) / effect.duration).clamp(0.0, 1.0);
bgcolor.0.set_a(alpha as f32);
}
}
// Blackout disabled for now // Blackout disabled for now
//pub fn update_blackout( //pub fn update_blackout(
// mut q_effect: Query<&mut BackgroundColor, With<BlackOutOverlay>>, // mut q_effect: Query<&mut BackgroundColor, With<BlackOutOverlay>>,

View file

@ -30,6 +30,8 @@ pub fn asset_name_to_path(name: &str) -> &'static str {
"moonlet" => "models/moonlet.glb#Scene0", "moonlet" => "models/moonlet.glb#Scene0",
"monolith" => "models/monolith_neon.glb#Scene0", "monolith" => "models/monolith_neon.glb#Scene0",
"lightorb" => "models/lightorb.glb#Scene0", "lightorb" => "models/lightorb.glb#Scene0",
"orb_busstop" => "models/orb_busstop.glb#Scene0",
"orb_busstop_dim" => "models/orb_busstop_dim.glb#Scene0",
"MeteorAceGT" => "models/MeteorAceGT.glb#Scene0", "MeteorAceGT" => "models/MeteorAceGT.glb#Scene0",
"satellite" => "models/satellite.glb#Scene0", "satellite" => "models/satellite.glb#Scene0",
"pizzeria" => "models/pizzeria2.glb#Scene0", "pizzeria" => "models/pizzeria2.glb#Scene0",