// ▄████████▄ + ███ + ▄█████████ ███ + // ███▀ ▀███ + + ███ ███▀ + ███ + + // ███ + ███ ███ ███ █████████ ███ ███ ███ ███ // ███ +███ ███ ███ ███ ███▐██████ ███ ███ ███ // ███ + ███ ███+ ███ +███ ███ + ███ ███ + ███ // ███▄ ▄███ ███▄ ███ ███ + ███ + ███ ███▄ ███ // ▀████████▀ + ▀███████ ███▄ ███▄ ▀████ ▀███████ // + + + ███ // + ▀████████████████████████████████████████████████████▀ // // This plugin manages game menus and the player death screen use crate::prelude::*; use bevy::prelude::*; use fastrand; pub const POEMS: &str = &include_str!("data/deathpoems.in"); pub struct MenuPlugin; impl Plugin for MenuPlugin { fn build(&self, app: &mut App) { app.add_systems(Startup, setup.after(hud::setup)); app.add_systems(PreUpdate, show_deathscreen.run_if(on_event::())); app.add_systems(Update, handle_deathscreen_input); app.add_event::(); } } #[derive(Component)] pub struct DeathScreenElement; #[derive(Component)] pub struct BlackScreen; #[derive(Component)] pub struct DeathText; #[derive(Event, PartialEq)] pub enum DeathScreenEvent { Show, Hide } pub fn setup( mut commands: Commands, asset_server: Res, settings: Res, ) { commands.spawn(( BlackScreen, DeathScreenElement, NodeBundle { style: style_fullscreen(), background_color: Color::BLACK.into(), visibility: Visibility::Hidden, ..default() }, )); let font_handle = asset_server.load(FONT); let style_death = TextStyle { font: font_handle.clone(), font_size: settings.font_size_deathtext, color: settings.hud_color_subtitles, ..default() }; let style_death_poem = TextStyle { font: font_handle.clone(), font_size: settings.font_size_deathpoem, color: settings.hud_color_deathpoem, ..default() }; let style_death_subtext = TextStyle { font: font_handle.clone(), font_size: settings.font_size_deathsubtext, color: settings.hud_color_subtitles, ..default() }; let style_death_subsubtext = TextStyle { font: font_handle.clone(), font_size: settings.font_size_deathsubtext * 0.8, color: settings.hud_color_subtitles, ..default() }; commands.spawn(( DeathScreenElement, NodeBundle { style: style_centered(), visibility: Visibility::Hidden, ..default() }, )).with_children(|builder| { builder.spawn(( DeathText, TextBundle { text: Text { sections: vec![ TextSection::new("", style_death_poem), TextSection::new("You are dead.\n", style_death), TextSection::new("Cause: ", style_death_subtext.clone()), TextSection::new("Unknown", style_death_subtext), TextSection::new("\n\n\n\nPress E to begin anew.", style_death_subsubtext), ], justify: JustifyText::Center, ..default() }, ..default() }, )); }); } pub fn show_deathscreen( mut er_deathscreen: EventReader, mut q_vis: Query<&mut Visibility, With>, mut q_text: Query<&mut Text, With>, mut ew_pausesfx: EventWriter, mut ew_sfx: EventWriter, mut ew_effect: EventWriter, mut ew_respawn: EventWriter, mut ew_respawnaudiosinks: EventWriter, mut settings: ResMut, ) { for event in er_deathscreen.read() { let show = *event == DeathScreenEvent::Show; for mut vis in &mut q_vis { *vis = bool2vis(show); } settings.deathscreen_active = show; settings.alive = !show; if show { ew_pausesfx.send(audio::PauseAllSfxEvent); if let Ok(mut text) = q_text.get_single_mut() { let poems: Vec<&str> = POEMS.split("\n\n").collect(); if poems.len() > 0 { let poem_index = fastrand::usize(..poems.len()); let poem = poems[poem_index].to_string(); text.sections[0].value = poem + "\n\n\n\n"; } text.sections[3].value = settings.death_cause.clone(); } } else { ew_respawnaudiosinks.send(audio::RespawnSinksEvent); ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::WakeUp)); ew_effect.send(visual::SpawnEffectEvent { class: visual::Effects::FadeIn(Color::BLACK), duration: 0.3 }); ew_respawn.send(world::RespawnEvent); } } } pub fn handle_deathscreen_input( keyboard_input: Res>, mut ew_deathscreen: EventWriter, settings: Res, ) { if !settings.deathscreen_active { return; } if keyboard_input.pressed(settings.key_interact) { ew_deathscreen.send(DeathScreenEvent::Hide); } }