//! Starting base selection scene. //! //! After character creation, the player chooses a starting base from generated //! outer-galaxy systems. The choice is kept in a resource until persistence is //! wired into the game client. mod scene; mod ui; use bevy::prelude::*; use crate::gameplay::galaxy::{StartingBaseCandidate, orbits}; use crate::state::AppState; // Public exports for POI spawning pub use scene::{SpawnedPoiSystem, StartingBasePoi}; pub struct StartingBasePlugin; impl Plugin for StartingBasePlugin { fn build(&self, app: &mut App) { app.init_resource::() .init_resource::() .add_systems( OnEnter(AppState::StartingBaseSelection), (scene::setup_starting_base_scene, ui::setup_starting_base_ui).chain(), ) .add_systems( OnExit(AppState::StartingBaseSelection), (despawn_starting_base_ui, scene::despawn_pois_on_exit).chain(), ) .add_systems( Update, ( escape_to_character_creation, ui::candidate_button_handler, scene::focus_starting_base_camera, scene::animate_starting_base_selection, ui::scroll_starting_base_panels, ui::refresh_starting_base_ui, ui::action_button_handler, scene::spawn_selected_pois, orbits::advance_orbital_paths, ) .chain() .run_if(in_state(AppState::StartingBaseSelection)), ); } } #[derive(Resource, Default)] pub struct StartingBaseDraft { pub candidates: Vec, pub selected_index: Option, } #[derive(Resource, Debug, Clone)] pub struct StartingBaseSelection { pub system_id: String, pub system_name: String, pub faction: &'static str, pub security: f32, } #[derive(Resource, Debug, Clone, Copy)] pub struct StartingBaseFocusRequest { pub candidate_index: usize, } #[derive(Component)] pub struct StartingBaseSpawned; #[derive(Component)] pub struct StartingBaseInputBlocker; #[derive(Component, Clone, Copy)] pub enum StartingBaseButton { Candidate(usize), Confirm, Back, } fn despawn_starting_base_ui( mut commands: Commands, query: Query>, ) { for entity in &query { commands.entity(entity).despawn(); } } fn escape_to_character_creation( keys: Res>, mut next_state: ResMut>, ) { if keys.just_pressed(KeyCode::Escape) { next_state.set(AppState::CharacterCreation); } }