feat(engine): add daily challenge, level-up toast, and daily_devotee achievement

Phase 6 part 2 (partial):
- daily_seed_for(date) and PlayerProgress::record_daily_completion in
  solitaire_data, with streak logic that increments on consecutive days,
  resets on a skipped day, and is idempotent on same-day re-completions.
- DailyChallengePlugin tracks today's seed, awards +100 XP and updates
  the streak when the player wins a game whose seed matches. Pressing C
  starts a new game with the daily seed.
- LevelUpEvent toast in AnimationPlugin announces level changes.
- AchievementContext gains daily_challenge_streak; daily_devotee
  achievement unlocks at streak >= 7. AchievementPlugin reads
  ProgressResource and runs after ProgressUpdate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-04-24 19:17:59 -07:00
parent 0cb8b32ec4
commit 622b35a3bf
8 changed files with 376 additions and 9 deletions
+14
View File
@@ -10,12 +10,14 @@ use crate::card_plugin::CardEntity;
use crate::events::{AchievementUnlockedEvent, GameWonEvent};
use crate::game_plugin::GameMutation;
use crate::layout::LayoutResource;
use crate::progress_plugin::LevelUpEvent;
/// Duration of a card slide (move) animation in seconds.
pub const SLIDE_SECS: f32 = 0.15;
const WIN_TOAST_SECS: f32 = 4.0;
const ACHIEVEMENT_TOAST_SECS: f32 = 3.0;
const LEVELUP_TOAST_SECS: f32 = 3.0;
const CASCADE_STAGGER: f32 = 0.05;
const CASCADE_DURATION: f32 = 0.5;
@@ -50,12 +52,14 @@ impl Plugin for AnimationPlugin {
// is idempotent in Bevy.
app.add_event::<GameWonEvent>()
.add_event::<AchievementUnlockedEvent>()
.add_event::<LevelUpEvent>()
.add_systems(
Update,
(
advance_card_anims,
handle_win_cascade,
handle_achievement_toast,
handle_levelup_toast,
tick_toasts,
)
.after(GameMutation),
@@ -133,6 +137,16 @@ fn handle_achievement_toast(
}
}
fn handle_levelup_toast(mut commands: Commands, mut events: EventReader<LevelUpEvent>) {
for ev in events.read() {
spawn_toast(
&mut commands,
format!("Level Up! → {}", ev.new_level),
LEVELUP_TOAST_SECS,
);
}
}
fn tick_toasts(
mut commands: Commands,
time: Res<Time>,