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:
@@ -18,7 +18,7 @@ use chrono::{Local, NaiveDate};
|
|||||||
use solitaire_data::{daily_seed_for, save_progress_to};
|
use solitaire_data::{daily_seed_for, save_progress_to};
|
||||||
use solitaire_sync::ChallengeGoal;
|
use solitaire_sync::ChallengeGoal;
|
||||||
|
|
||||||
use crate::events::{GameWonEvent, NewGameRequestEvent};
|
use crate::events::{GameWonEvent, NewGameRequestEvent, XpAwardedEvent};
|
||||||
use crate::game_plugin::GameMutation;
|
use crate::game_plugin::GameMutation;
|
||||||
use crate::progress_plugin::{ProgressResource, ProgressStoragePath, ProgressUpdate};
|
use crate::progress_plugin::{ProgressResource, ProgressStoragePath, ProgressUpdate};
|
||||||
use crate::resources::GameStateResource;
|
use crate::resources::GameStateResource;
|
||||||
@@ -81,6 +81,7 @@ impl Plugin for DailyChallengePlugin {
|
|||||||
.add_event::<DailyGoalAnnouncementEvent>()
|
.add_event::<DailyGoalAnnouncementEvent>()
|
||||||
.add_event::<GameWonEvent>()
|
.add_event::<GameWonEvent>()
|
||||||
.add_event::<NewGameRequestEvent>()
|
.add_event::<NewGameRequestEvent>()
|
||||||
|
.add_event::<XpAwardedEvent>()
|
||||||
.add_systems(Startup, fetch_server_challenge)
|
.add_systems(Startup, fetch_server_challenge)
|
||||||
.add_systems(Update, poll_server_challenge)
|
.add_systems(Update, poll_server_challenge)
|
||||||
// record/award after the base ProgressUpdate so we don't fight
|
// record/award after the base ProgressUpdate so we don't fight
|
||||||
@@ -149,6 +150,7 @@ fn handle_daily_completion(
|
|||||||
mut progress: ResMut<ProgressResource>,
|
mut progress: ResMut<ProgressResource>,
|
||||||
path: Res<ProgressStoragePath>,
|
path: Res<ProgressStoragePath>,
|
||||||
mut completed: EventWriter<DailyChallengeCompletedEvent>,
|
mut completed: EventWriter<DailyChallengeCompletedEvent>,
|
||||||
|
mut xp_awarded: EventWriter<XpAwardedEvent>,
|
||||||
) {
|
) {
|
||||||
for ev in wins.read() {
|
for ev in wins.read() {
|
||||||
if game.0.seed != daily.seed {
|
if game.0.seed != daily.seed {
|
||||||
@@ -170,6 +172,7 @@ fn handle_daily_completion(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
progress.0.add_xp(DAILY_BONUS_XP);
|
progress.0.add_xp(DAILY_BONUS_XP);
|
||||||
|
xp_awarded.send(XpAwardedEvent { amount: DAILY_BONUS_XP });
|
||||||
if let Some(target) = &path.0 {
|
if let Some(target) = &path.0 {
|
||||||
if let Err(e) = save_progress_to(target, &progress.0) {
|
if let Err(e) = save_progress_to(target, &progress.0) {
|
||||||
warn!("failed to save progress after daily completion: {e}");
|
warn!("failed to save progress after daily completion: {e}");
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use solitaire_data::{
|
|||||||
WEEKLY_GOAL_XP,
|
WEEKLY_GOAL_XP,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::events::GameWonEvent;
|
use crate::events::{GameWonEvent, XpAwardedEvent};
|
||||||
use crate::game_plugin::GameMutation;
|
use crate::game_plugin::GameMutation;
|
||||||
use crate::progress_plugin::{LevelUpEvent, ProgressResource, ProgressStoragePath, ProgressUpdate};
|
use crate::progress_plugin::{LevelUpEvent, ProgressResource, ProgressStoragePath, ProgressUpdate};
|
||||||
use crate::resources::GameStateResource;
|
use crate::resources::GameStateResource;
|
||||||
@@ -27,6 +27,7 @@ impl Plugin for WeeklyGoalsPlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_event::<WeeklyGoalCompletedEvent>()
|
app.add_event::<WeeklyGoalCompletedEvent>()
|
||||||
.add_event::<GameWonEvent>()
|
.add_event::<GameWonEvent>()
|
||||||
|
.add_event::<XpAwardedEvent>()
|
||||||
.add_systems(Startup, roll_weekly_goals_on_startup)
|
.add_systems(Startup, roll_weekly_goals_on_startup)
|
||||||
// Run after GameMutation (so GameWonEvent is available) and
|
// Run after GameMutation (so GameWonEvent is available) and
|
||||||
// ProgressUpdate (so we don't fight ProgressPlugin's add_xp).
|
// ProgressUpdate (so we don't fight ProgressPlugin's add_xp).
|
||||||
@@ -62,6 +63,7 @@ fn evaluate_weekly_goals(
|
|||||||
path: Res<ProgressStoragePath>,
|
path: Res<ProgressStoragePath>,
|
||||||
mut completions: EventWriter<WeeklyGoalCompletedEvent>,
|
mut completions: EventWriter<WeeklyGoalCompletedEvent>,
|
||||||
mut levelups: EventWriter<LevelUpEvent>,
|
mut levelups: EventWriter<LevelUpEvent>,
|
||||||
|
mut xp_awarded: EventWriter<XpAwardedEvent>,
|
||||||
) {
|
) {
|
||||||
let mut events: Vec<&GameWonEvent> = wins.read().collect();
|
let mut events: Vec<&GameWonEvent> = wins.read().collect();
|
||||||
if events.is_empty() {
|
if events.is_empty() {
|
||||||
@@ -99,6 +101,7 @@ fn evaluate_weekly_goals(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if bonus_xp > 0 {
|
if bonus_xp > 0 {
|
||||||
|
xp_awarded.send(XpAwardedEvent { amount: bonus_xp });
|
||||||
let prev_level = progress.0.add_xp(bonus_xp);
|
let prev_level = progress.0.add_xp(bonus_xp);
|
||||||
if progress.0.leveled_up_from(prev_level) {
|
if progress.0.leveled_up_from(prev_level) {
|
||||||
levelups.send(LevelUpEvent {
|
levelups.send(LevelUpEvent {
|
||||||
|
|||||||
Reference in New Issue
Block a user