fix(engine): drop duplicate "You Win" toast — WinSummary modal owns the celebration
The post-win UI was firing TWO celebration surfaces on every
GameWonEvent:
- animation_plugin::handle_win_cascade spawned a 4-second toast:
"You Win! Score: {score} Time: {m}:{ss}"
- win_summary_plugin spawned the proper "You Won!" modal with
score breakdown, time bonus, achievements unlocked, XP earned,
and a Play Again button
Both rendered on top of each other — in screenshots the toast
banner was partially clipped behind the modal card, peeking out
on either side. The toast predates the WinSummary modal; the
modal carries strictly more information so the toast is dead
weight.
handle_win_cascade keeps the cards-fly-off animation
(MotionCurve::Expressive cascade with per-card rotation drift) —
that's the visual celebration, distinct from the textual
celebration the modal owns. The system still gates on the same
GameWonEvent message reader; it just doesn't write a toast
afterward. WIN_TOAST_SECS const removed (no remaining callers).
Workspace: 1172 passing tests / 0 failing. cargo clippy
--workspace --all-targets -- -D warnings clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -61,7 +61,6 @@ fn anim_speed_to_secs(speed: &AnimSpeed) -> f32 {
|
|||||||
scaled_duration(MOTION_SLIDE_SECS, *speed)
|
scaled_duration(MOTION_SLIDE_SECS, *speed)
|
||||||
}
|
}
|
||||||
|
|
||||||
const WIN_TOAST_SECS: f32 = 4.0;
|
|
||||||
const ACHIEVEMENT_TOAST_SECS: f32 = 3.0;
|
const ACHIEVEMENT_TOAST_SECS: f32 = 3.0;
|
||||||
const LEVELUP_TOAST_SECS: f32 = 3.0;
|
const LEVELUP_TOAST_SECS: f32 = 3.0;
|
||||||
const DAILY_TOAST_SECS: f32 = 3.0;
|
const DAILY_TOAST_SECS: f32 = 3.0;
|
||||||
@@ -266,9 +265,15 @@ fn handle_win_cascade(
|
|||||||
layout: Option<Res<LayoutResource>>,
|
layout: Option<Res<LayoutResource>>,
|
||||||
settings: Option<Res<SettingsResource>>,
|
settings: Option<Res<SettingsResource>>,
|
||||||
) {
|
) {
|
||||||
let Some(ev) = events.read().next() else {
|
// Drain the event reader; the cascade visual is the only thing
|
||||||
|
// this system contributes — the post-win "You Won!" modal
|
||||||
|
// (`win_summary_plugin`) consumes the same `GameWonEvent` and
|
||||||
|
// carries score / time / achievements / XP itself, so a duplicate
|
||||||
|
// toast saying "You Win! Score X Time Y" rendered behind the modal
|
||||||
|
// in earlier builds. Removed.
|
||||||
|
if events.read().next().is_none() {
|
||||||
return;
|
return;
|
||||||
};
|
}
|
||||||
|
|
||||||
let margin = layout.as_ref().map_or(800.0, |l| l.0.card_size.x * 8.0);
|
let margin = layout.as_ref().map_or(800.0, |l| l.0.card_size.x * 8.0);
|
||||||
|
|
||||||
@@ -284,11 +289,6 @@ fn handle_win_cascade(
|
|||||||
Vec3::new(-margin, 0.0, 300.0),
|
Vec3::new(-margin, 0.0, 300.0),
|
||||||
];
|
];
|
||||||
|
|
||||||
let m = ev.time_seconds / 60;
|
|
||||||
let s = ev.time_seconds % 60;
|
|
||||||
let win_msg = format!("You Win! Score: {} Time: {m}:{s:02}", ev.score);
|
|
||||||
spawn_toast(&mut commands, win_msg, WIN_TOAST_SECS);
|
|
||||||
|
|
||||||
let step = settings
|
let step = settings
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(CASCADE_STAGGER_NORMAL, |s| cascade_step_secs(s.0.animation_speed));
|
.map_or(CASCADE_STAGGER_NORMAL, |s| cascade_step_secs(s.0.animation_speed));
|
||||||
|
|||||||
Reference in New Issue
Block a user