From d4fbd0247b78383b0a2db802f30c8bd23ed87758 Mon Sep 17 00:00:00 2001 From: Daddy32 Date: Tue, 16 Dec 2025 13:25:18 +0100 Subject: [PATCH] Clamp goal milestone announcements --- src/goals.js | 66 +++++++++++++++++++++++++++------------------------- src/main.js | 1 + 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/goals.js b/src/goals.js index 5bae6e4..74d5866 100644 --- a/src/goals.js +++ b/src/goals.js @@ -107,39 +107,41 @@ const maybeAnnounceGoalProgress = (goal) => { if (!goal || !Number.isFinite(goal.progress)) return; const fraction = Math.max(0, Math.min(1, goal.progress / 100)); - for (const threshold of goalMilestoneThresholds) { - if (fraction >= threshold && !announcedGoalMilestones.has(threshold)) { - announcedGoalMilestones.add(threshold); - const text = config.messages?.text || formatGoalMessage(goal); - if (!text) { - logGoalEvent("skip-progress-announcement", { - threshold, - progress: goal.progress, - reason: "missing text", - }); - return; - } - const colors = - (Array.isArray(config.messages?.colors) && - config.messages.colors) || - goal?.colors || - null; - logGoalEvent("announce-progress", { - threshold, - progress: goal.progress, - colors, - text, - }); - ui.showFloatingMessage( - { text, colors }, - { - durationMs: config.messages.durationMs, - position: config.messages.position, - }, - ); - break; - } + const newlyReached = goalMilestoneThresholds.filter( + (threshold) => + fraction >= threshold && !announcedGoalMilestones.has(threshold), + ); + if (newlyReached.length === 0) return; + const threshold = Math.max(...newlyReached); + newlyReached.forEach((t) => announcedGoalMilestones.add(t)); + const text = config.messages?.text || formatGoalMessage(goal); + if (!text) { + logGoalEvent("skip-progress-announcement", { + threshold, + progress: goal.progress, + reason: "missing text", + suppressed: newlyReached.filter((t) => t !== threshold), + }); + return; } + const colors = + (Array.isArray(config.messages?.colors) && config.messages.colors) || + goal?.colors || + null; + logGoalEvent("announce-progress", { + threshold, + progress: goal.progress, + colors, + text, + suppressed: newlyReached.filter((t) => t !== threshold), + }); + ui.showFloatingMessage( + { text, colors }, + { + durationMs: config.messages.durationMs, + position: config.messages.position, + }, + ); }; const showGoalIntro = () => { diff --git a/src/main.js b/src/main.js index 16d17e1..f542a05 100644 --- a/src/main.js +++ b/src/main.js @@ -281,6 +281,7 @@ state.lastTimerDisplay = null; } resetChainVisuals(); + ui.clearMessages(); state.balls.forEach((ball) => { spawnSystem.cleanupBall(ball); World.remove(world, ball);