Files
Space-Game/apps/game/src/gameplay/character_creation/mod.rs
francy51 07316dbcd7 feat(gameplay): implement in-system onboarding with docked station view
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>
2026-06-14 15:19:18 -04:00

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);
}
}