Implement the final onboarding step where the player loads into their selected starting system docked at a station. New features: - Create in_system module for system-scale gameplay - Spawn player ship docked at highest-population station - Display station info panel with undock button - Position camera for cinematic docked view with orbit controls Implementation details: - in_system/mod.rs: Plugin setup with DockedState and ActiveSystem resources - in_system/scene.rs: System/POI spawning and player ship docked positioning - in_system/docked.rs: Docked state management and UndockEvent - in_system/ui.rs: Docked UI with station details and undock button - Reuse existing POI spawning patterns from galaxy/contents.rs - Select docking station by highest population (better for new players) Modified files: - Add in_system module exports to gameplay/mod.rs - Register InSystemPlugin in main.rs - Update orbit camera control for InGame state - Re-export GeneratedStation and STARTING_SHIPS for use by in_system The player now completes onboarding by loading into a system view with their ship docked at a station, ready for gameplay. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
87 lines
3.2 KiB
Rust
87 lines
3.2 KiB
Rust
//! Character creation scene.
|
|
//!
|
|
//! Layout / picker UI lives in [`ui`]; presets and the editable draft
|
|
//! resource live in [`params`]. This module wires the Bevy plugin, owns the
|
|
//! spawn / despawn lifecycle, and handles the Escape → Galaxy shortcut.
|
|
//!
|
|
//! Persistence is not yet wired up — on Confirm, the current draft is logged
|
|
//! and the app transitions to [`AppState::StartingBaseSelection`]. The TODO is
|
|
//! to persist it to SpacetimeDB once the Rust SDK is integrated.
|
|
|
|
mod params;
|
|
mod ui;
|
|
|
|
// Public API surface for the (yet-to-be-wired) persistence layer / InGame
|
|
// plugin. Currently unused outside this module — `#[allow]` keeps the names
|
|
// exported so consumers can `use crate::gameplay::character_creation::Origin`
|
|
// without us remembering to re-add the re-export the day they're needed.
|
|
#[allow(unused_imports)]
|
|
pub use params::{CharacterDraft, Origin, StartingShip, STARTING_SHIPS};
|
|
|
|
use bevy::prelude::*;
|
|
|
|
use crate::state::AppState;
|
|
|
|
pub struct CharacterCreationPlugin;
|
|
|
|
impl Plugin for CharacterCreationPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.init_resource::<CharacterDraft>()
|
|
.add_systems(
|
|
OnEnter(AppState::CharacterCreation),
|
|
ui::setup_character_creation_ui,
|
|
)
|
|
.add_systems(
|
|
OnExit(AppState::CharacterCreation),
|
|
despawn_character_creation,
|
|
)
|
|
.add_systems(
|
|
Update,
|
|
(
|
|
escape_to_galaxy,
|
|
ui::scroll_character_creation_form,
|
|
ui::picker_button_handler,
|
|
ui::refresh_picker_values,
|
|
ui::action_button_handler,
|
|
)
|
|
.chain()
|
|
.run_if(in_state(AppState::CharacterCreation)),
|
|
);
|
|
}
|
|
}
|
|
|
|
// ── Markers ─────────────────────────────────────────────────────────────────
|
|
|
|
/// Tag for everything spawned during character creation so it can be cleanly
|
|
/// despawned on state exit.
|
|
#[derive(Component)]
|
|
pub struct CharacterCreationSpawned;
|
|
|
|
#[derive(Component)]
|
|
pub enum CharacterCreationButton {
|
|
/// Finalize the character and begin the game.
|
|
Confirm,
|
|
/// Discard and return to the galaxy selection screen.
|
|
Back,
|
|
}
|
|
|
|
// ── Lifecycle ───────────────────────────────────────────────────────────────
|
|
|
|
fn despawn_character_creation(
|
|
mut commands: Commands,
|
|
query: Query<Entity, With<CharacterCreationSpawned>>,
|
|
) {
|
|
for entity in &query {
|
|
// Bevy 0.16: despawn() is recursive by default.
|
|
commands.entity(entity).despawn();
|
|
}
|
|
}
|
|
|
|
// ── Input ───────────────────────────────────────────────────────────────────
|
|
|
|
fn escape_to_galaxy(keys: Res<ButtonInput<KeyCode>>, mut next_state: ResMut<NextState<AppState>>) {
|
|
if keys.just_pressed(KeyCode::Escape) {
|
|
next_state.set(AppState::Galaxy);
|
|
}
|
|
}
|