From fa1fea02dcce596043b704e048c0ab575bc16873 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Thu, 7 Aug 2025 19:13:00 +0100 Subject: [PATCH] Fix edge case that estimates sliderbreaks in impossible scenarios (#34544) * Test theory crafting * Place in more appropriate place * fix a bit better * Move things around * Reduce diff --------- Co-authored-by: StanR --- .../Difficulty/OsuLegacyScoreMissCalculator.cs | 13 +++++++++++++ .../Difficulty/OsuPerformanceCalculator.cs | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuLegacyScoreMissCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuLegacyScoreMissCalculator.cs index 207ecde81a..0d406ea72a 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuLegacyScoreMissCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuLegacyScoreMissCalculator.cs @@ -125,6 +125,19 @@ namespace osu.Game.Rulesets.Osu.Difficulty // In classic scores there can't be more misses than a sum of all non-perfect judgements missCount = Math.Min(missCount, totalImperfectHits); + // Every slider has *at least* 2 combo attributed in classic mechanics. + // If they broke on a slider with a tick, then this still works since they would have lost at least 2 combo (the tick and the end) + // Using this as a max means a score that loses 1 combo on a map can't possibly have been a slider break. + // It must have been a slider end. + int maxPossibleSliderBreaks = Math.Min(attributes.SliderCount, (attributes.MaxCombo - score.MaxCombo) / 2); + + int scoreMissCount = score.Statistics.GetValueOrDefault(HitResult.Miss); + + double sliderBreaks = missCount - scoreMissCount; + + if (sliderBreaks > maxPossibleSliderBreaks) + missCount = scoreMissCount + maxPossibleSliderBreaks; + return missCount; } diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 11e9714ed8..7230c52f9c 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -343,6 +343,17 @@ namespace osu.Game.Rulesets.Osu.Difficulty // In classic scores there can't be more misses than a sum of all non-perfect judgements missCount = Math.Min(missCount, totalImperfectHits); + + // Every slider has *at least* 2 combo attributed in classic mechanics. + // If they broke on a slider with a tick, then this still works since they would have lost at least 2 combo (the tick and the end) + // Using this as a max means a score that loses 1 combo on a map can't possibly have been a slider break. + // It must have been a slider end. + int maxPossibleSliderBreaks = Math.Min(attributes.SliderCount, (attributes.MaxCombo - scoreMaxCombo) / 2); + + double sliderBreaks = missCount - countMiss; + + if (sliderBreaks > maxPossibleSliderBreaks) + missCount = countMiss + maxPossibleSliderBreaks; } else {