feat(data,engine): persistent Settings + SFX volume hotkeys
- solitaire_data::Settings { sfx_volume, first_run_complete } with
atomic JSON persistence and clamping sanitizer.
- SettingsPlugin (engine): [ / ] adjust SFX volume by 0.1, clamped;
persists on change; emits SettingsChangedEvent. No-op at rails.
- AudioPlugin applies sfx_volume to kira's main track at startup
and on every change so live tweaks take effect without restart.
- Brief "SFX: N%" toast on each change. Help cheat sheet updated.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ use crate::events::{AchievementUnlockedEvent, GameWonEvent};
|
||||
use crate::game_plugin::GameMutation;
|
||||
use crate::layout::LayoutResource;
|
||||
use crate::progress_plugin::LevelUpEvent;
|
||||
use crate::settings_plugin::SettingsChangedEvent;
|
||||
use crate::time_attack_plugin::TimeAttackEndedEvent;
|
||||
use crate::weekly_goals_plugin::WeeklyGoalCompletedEvent;
|
||||
|
||||
@@ -26,6 +27,7 @@ const DAILY_TOAST_SECS: f32 = 3.0;
|
||||
const WEEKLY_TOAST_SECS: f32 = 3.0;
|
||||
const TIME_ATTACK_TOAST_SECS: f32 = 5.0;
|
||||
const CHALLENGE_TOAST_SECS: f32 = 3.0;
|
||||
const VOLUME_TOAST_SECS: f32 = 1.4;
|
||||
const CASCADE_STAGGER: f32 = 0.05;
|
||||
const CASCADE_DURATION: f32 = 0.5;
|
||||
|
||||
@@ -65,6 +67,7 @@ impl Plugin for AnimationPlugin {
|
||||
.add_event::<WeeklyGoalCompletedEvent>()
|
||||
.add_event::<TimeAttackEndedEvent>()
|
||||
.add_event::<ChallengeAdvancedEvent>()
|
||||
.add_event::<SettingsChangedEvent>()
|
||||
.add_systems(
|
||||
Update,
|
||||
(
|
||||
@@ -76,6 +79,7 @@ impl Plugin for AnimationPlugin {
|
||||
handle_weekly_toast,
|
||||
handle_time_attack_toast,
|
||||
handle_challenge_toast,
|
||||
handle_settings_toast,
|
||||
tick_toasts,
|
||||
)
|
||||
.after(GameMutation),
|
||||
@@ -215,6 +219,20 @@ fn handle_challenge_toast(
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_settings_toast(
|
||||
mut commands: Commands,
|
||||
mut events: EventReader<SettingsChangedEvent>,
|
||||
) {
|
||||
for ev in events.read() {
|
||||
let pct = (ev.0.sfx_volume * 100.0).round() as i32;
|
||||
spawn_toast(
|
||||
&mut commands,
|
||||
format!("SFX: {pct}%"),
|
||||
VOLUME_TOAST_SECS,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn tick_toasts(
|
||||
mut commands: Commands,
|
||||
time: Res<Time>,
|
||||
|
||||
Reference in New Issue
Block a user