feat(engine): fire XpAwardedEvent for daily and weekly bonus XP

Daily challenge completions (+100 XP) and weekly goal bonuses (+75 XP)
now fire XpAwardedEvent so the player sees a "+N XP" toast — consistent
with the post-win XP toast already shown by ProgressPlugin.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-04-27 03:23:55 +00:00
parent 91b675f2f1
commit 3eb7901023
2 changed files with 8 additions and 2 deletions
@@ -18,7 +18,7 @@ use chrono::{Local, NaiveDate};
use solitaire_data::{daily_seed_for, save_progress_to};
use solitaire_sync::ChallengeGoal;
use crate::events::{GameWonEvent, NewGameRequestEvent};
use crate::events::{GameWonEvent, NewGameRequestEvent, XpAwardedEvent};
use crate::game_plugin::GameMutation;
use crate::progress_plugin::{ProgressResource, ProgressStoragePath, ProgressUpdate};
use crate::resources::GameStateResource;
@@ -81,6 +81,7 @@ impl Plugin for DailyChallengePlugin {
.add_event::<DailyGoalAnnouncementEvent>()
.add_event::<GameWonEvent>()
.add_event::<NewGameRequestEvent>()
.add_event::<XpAwardedEvent>()
.add_systems(Startup, fetch_server_challenge)
.add_systems(Update, poll_server_challenge)
// record/award after the base ProgressUpdate so we don't fight
@@ -149,6 +150,7 @@ fn handle_daily_completion(
mut progress: ResMut<ProgressResource>,
path: Res<ProgressStoragePath>,
mut completed: EventWriter<DailyChallengeCompletedEvent>,
mut xp_awarded: EventWriter<XpAwardedEvent>,
) {
for ev in wins.read() {
if game.0.seed != daily.seed {
@@ -170,6 +172,7 @@ fn handle_daily_completion(
continue;
}
progress.0.add_xp(DAILY_BONUS_XP);
xp_awarded.send(XpAwardedEvent { amount: DAILY_BONUS_XP });
if let Some(target) = &path.0 {
if let Err(e) = save_progress_to(target, &progress.0) {
warn!("failed to save progress after daily completion: {e}");
+4 -1
View File
@@ -9,7 +9,7 @@ use solitaire_data::{
WEEKLY_GOAL_XP,
};
use crate::events::GameWonEvent;
use crate::events::{GameWonEvent, XpAwardedEvent};
use crate::game_plugin::GameMutation;
use crate::progress_plugin::{LevelUpEvent, ProgressResource, ProgressStoragePath, ProgressUpdate};
use crate::resources::GameStateResource;
@@ -27,6 +27,7 @@ impl Plugin for WeeklyGoalsPlugin {
fn build(&self, app: &mut App) {
app.add_event::<WeeklyGoalCompletedEvent>()
.add_event::<GameWonEvent>()
.add_event::<XpAwardedEvent>()
.add_systems(Startup, roll_weekly_goals_on_startup)
// Run after GameMutation (so GameWonEvent is available) and
// ProgressUpdate (so we don't fight ProgressPlugin's add_xp).
@@ -62,6 +63,7 @@ fn evaluate_weekly_goals(
path: Res<ProgressStoragePath>,
mut completions: EventWriter<WeeklyGoalCompletedEvent>,
mut levelups: EventWriter<LevelUpEvent>,
mut xp_awarded: EventWriter<XpAwardedEvent>,
) {
let mut events: Vec<&GameWonEvent> = wins.read().collect();
if events.is_empty() {
@@ -99,6 +101,7 @@ fn evaluate_weekly_goals(
}
if bonus_xp > 0 {
xp_awarded.send(XpAwardedEvent { amount: bonus_xp });
let prev_level = progress.0.add_xp(bonus_xp);
if progress.0.leveled_up_from(prev_level) {
levelups.send(LevelUpEvent {