feat(engine): add Modes dropdown with Classic/Daily/Zen/Challenge/Time Attack
Continues the UI-first pass. The five game modes were each behind a keyboard shortcut (N/Z/X/T/C) with no visible UI affordance, three of them additionally gated by an unlock level the player has to discover themselves. Add a "Modes ▾" button to the action bar that toggles a popover panel beneath. Each row dispatches the same code path the keyboard accelerator uses by writing a new `Start*RequestEvent` (or `NewGameRequestEvent` for Classic): - Classic → NewGameRequestEvent::default() - Daily Challenge → StartDailyChallengeRequestEvent - Zen → StartZenRequestEvent - Challenge → StartChallengeRequestEvent - Time Attack → StartTimeAttackRequestEvent The existing keyboard handlers in input_plugin (Z), challenge_plugin (X), time_attack_plugin (T), and daily_challenge_plugin (C) now read either their key or the matching request event, so level gates, TimeAttackResource setup, daily seed lookup, and toast feedback for locked modes all stay in their owning plugins — the popover never duplicates that logic. The popover only lists modes available to the player: Classic always shows, Daily Challenge shows when DailyChallengeResource is loaded, and Zen/Challenge/Time Attack show once the player reaches level 5 (the existing CHALLENGE_UNLOCK_LEVEL). Click handler despawns the popover after dispatch; clicking the Modes button again toggles it shut. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,9 @@ use bevy::prelude::*;
|
||||
use solitaire_core::game_state::GameMode;
|
||||
|
||||
use crate::challenge_plugin::CHALLENGE_UNLOCK_LEVEL;
|
||||
use crate::events::{GameWonEvent, InfoToastEvent, NewGameRequestEvent};
|
||||
use crate::events::{
|
||||
GameWonEvent, InfoToastEvent, NewGameRequestEvent, StartTimeAttackRequestEvent,
|
||||
};
|
||||
use crate::game_plugin::GameMutation;
|
||||
use crate::progress_plugin::ProgressResource;
|
||||
use crate::resources::GameStateResource;
|
||||
@@ -40,6 +42,7 @@ impl Plugin for TimeAttackPlugin {
|
||||
.add_message::<TimeAttackEndedEvent>()
|
||||
.add_message::<GameWonEvent>()
|
||||
.add_message::<NewGameRequestEvent>()
|
||||
.add_message::<StartTimeAttackRequestEvent>()
|
||||
.add_message::<InfoToastEvent>()
|
||||
.add_systems(
|
||||
Update,
|
||||
@@ -52,12 +55,15 @@ impl Plugin for TimeAttackPlugin {
|
||||
|
||||
fn handle_start_time_attack_request(
|
||||
keys: Res<ButtonInput<KeyCode>>,
|
||||
mut requests: MessageReader<StartTimeAttackRequestEvent>,
|
||||
progress: Res<ProgressResource>,
|
||||
mut session: ResMut<TimeAttackResource>,
|
||||
mut new_game: MessageWriter<NewGameRequestEvent>,
|
||||
mut info_toast: MessageWriter<InfoToastEvent>,
|
||||
) {
|
||||
if !keys.just_pressed(KeyCode::KeyT) {
|
||||
// Either T or the HUD Modes-popover "Time Attack" row triggers this.
|
||||
let button_clicked = requests.read().count() > 0;
|
||||
if !keys.just_pressed(KeyCode::KeyT) && !button_clicked {
|
||||
return;
|
||||
}
|
||||
if progress.0.level < CHALLENGE_UNLOCK_LEVEL {
|
||||
|
||||
Reference in New Issue
Block a user