From 6cf15e3e5a2f5aa0df42886a60367eb2f184fe30 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Tue, 14 Jan 2025 18:27:25 +0000 Subject: [PATCH] Remove problematic total deviation scaling, rebalance aim (#31515) * Remove problematic total deviation scaling, rebalance aim * Fix tests --- .../OsuDifficultyCalculatorTest.cs | 12 ++--- .../Difficulty/Evaluators/AimEvaluator.cs | 2 +- .../Difficulty/OsuPerformanceAttributes.cs | 3 -- .../Difficulty/OsuPerformanceCalculator.cs | 52 ++----------------- .../Difficulty/Skills/Aim.cs | 2 +- 5 files changed, 11 insertions(+), 60 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs index a68d9dad39..7cf5b0529f 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs @@ -15,21 +15,21 @@ namespace osu.Game.Rulesets.Osu.Tests { protected override string ResourceAssembly => "osu.Game.Rulesets.Osu.Tests"; - [TestCase(6.7443067697205539d, 239, "diffcalc-test")] - [TestCase(1.4630292101418947d, 54, "zero-length-sliders")] + [TestCase(6.7331304290522747d, 239, "diffcalc-test")] + [TestCase(1.4602604078137214d, 54, "zero-length-sliders")] [TestCase(0.43052813047866129d, 4, "very-fast-slider")] [TestCase(0.14143808967817237d, 2, "nan-slider")] public void Test(double expectedStarRating, int expectedMaxCombo, string name) => base.Test(expectedStarRating, expectedMaxCombo, name); - [TestCase(9.7058844423552308d, 239, "diffcalc-test")] - [TestCase(1.7724929629205366d, 54, "zero-length-sliders")] + [TestCase(9.6779397290273756d, 239, "diffcalc-test")] + [TestCase(1.7691451263718989d, 54, "zero-length-sliders")] [TestCase(0.55785578988249407d, 4, "very-fast-slider")] public void TestClockRateAdjusted(double expectedStarRating, int expectedMaxCombo, string name) => Test(expectedStarRating, expectedMaxCombo, name, new OsuModDoubleTime()); - [TestCase(6.7443067697205539d, 239, "diffcalc-test")] - [TestCase(1.4630292101418947d, 54, "zero-length-sliders")] + [TestCase(6.7331304290522747d, 239, "diffcalc-test")] + [TestCase(1.4602604078137214d, 54, "zero-length-sliders")] [TestCase(0.43052813047866129d, 4, "very-fast-slider")] public void TestClassicMod(double expectedStarRating, int expectedMaxCombo, string name) => Test(expectedStarRating, expectedMaxCombo, name, new OsuModClassic()); diff --git a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/AimEvaluator.cs b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/AimEvaluator.cs index 858ce673ee..9a5533e536 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/AimEvaluator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/AimEvaluator.cs @@ -84,7 +84,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators // Penalize angle repetition. wideAngleBonus *= 1 - Math.Min(wideAngleBonus, Math.Pow(calcWideAngleBonus(lastAngle), 3)); - acuteAngleBonus *= 0.09 + 0.91 * (1 - Math.Min(acuteAngleBonus, Math.Pow(calcAcuteAngleBonus(lastAngle), 3))); + acuteAngleBonus *= 0.08 + 0.92 * (1 - Math.Min(acuteAngleBonus, Math.Pow(calcAcuteAngleBonus(lastAngle), 3))); // Apply full wide angle bonus for distance more than one diameter wideAngleBonus *= angleBonus * DifficultyCalculationUtils.Smootherstep(osuCurrObj.LazyJumpDistance, 0, diameter); diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs index 9c30c0f7c7..de4491a31b 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs @@ -24,9 +24,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty [JsonProperty("effective_miss_count")] public double EffectiveMissCount { get; set; } - [JsonProperty("total_deviation")] - public double? TotalDeviation { get; set; } - [JsonProperty("speed_deviation")] public double? SpeedDeviation { get; set; } diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index a03e3fd6ef..7013ee55c4 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -42,7 +42,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty /// private double effectiveMissCount; - private double? totalDeviation; private double? speedDeviation; public OsuPerformanceCalculator() @@ -115,7 +114,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty effectiveMissCount = Math.Min(effectiveMissCount + countOk * okMultiplier + countMeh * mehMultiplier, totalHits); } - totalDeviation = calculateTotalDeviation(osuAttributes); speedDeviation = calculateSpeedDeviation(osuAttributes); double aimValue = computeAimValue(score, osuAttributes); @@ -138,7 +136,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty Accuracy = accuracyValue, Flashlight = flashlightValue, EffectiveMissCount = effectiveMissCount, - TotalDeviation = totalDeviation, SpeedDeviation = speedDeviation, Total = totalValue }; @@ -149,9 +146,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (score.Mods.Any(h => h is OsuModAutopilot)) return 0.0; - if (totalDeviation == null) - return 0; - double aimDifficulty = attributes.AimDifficulty; if (attributes.SliderCount > 0 && attributes.AimDifficultSliderCount > 0) @@ -203,7 +197,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty aimValue *= 1.0 + 0.04 * (12.0 - attributes.ApproachRate); } - aimValue *= SpecialFunctions.Erf(25.0 / (Math.Sqrt(2) * totalDeviation.Value)); + aimValue *= accuracy; + // It is important to consider accuracy difficulty when scaling with accuracy. + aimValue *= 0.98 + Math.Pow(Math.Max(0, attributes.OverallDifficulty), 2) / 2500; return aimValue; } @@ -322,48 +318,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty return flashlightValue; } - /// - /// Using estimates player's deviation on accuracy objects. - /// Returns deviation for circles and sliders if score was set with slideracc. - /// Returns the min between deviation of circles and deviation on circles and sliders (assuming slider hits are 50s), if score was set without slideracc. - /// - private double? calculateTotalDeviation(OsuDifficultyAttributes attributes) - { - if (totalSuccessfulHits == 0) - return null; - - int accuracyObjectCount = attributes.HitCircleCount; - - if (!usingClassicSliderAccuracy) - accuracyObjectCount += attributes.SliderCount; - - // Assume worst case: all mistakes was on accuracy objects - int relevantCountMiss = Math.Min(countMiss, accuracyObjectCount); - int relevantCountMeh = Math.Min(countMeh, accuracyObjectCount - relevantCountMiss); - int relevantCountOk = Math.Min(countOk, accuracyObjectCount - relevantCountMiss - relevantCountMeh); - int relevantCountGreat = Math.Max(0, accuracyObjectCount - relevantCountMiss - relevantCountMeh - relevantCountOk); - - // Calculate deviation on accuracy objects - double? deviation = calculateDeviation(attributes, relevantCountGreat, relevantCountOk, relevantCountMeh, relevantCountMiss); - if (deviation == null) - return null; - - if (!usingClassicSliderAccuracy) - return deviation.Value; - - // If score was set without slider accuracy - also compute deviation with sliders - // Assume that all hits was 50s - int totalCountWithSliders = attributes.HitCircleCount + attributes.SliderCount; - int missCountWithSliders = Math.Min(totalCountWithSliders, countMiss); - int hitCountWithSliders = totalCountWithSliders - missCountWithSliders; - - double hitProbabilityWithSliders = hitCountWithSliders / (totalCountWithSliders + 1.0); - double deviationWithSliders = attributes.MehHitWindow / (Math.Sqrt(2) * SpecialFunctions.ErfInv(hitProbabilityWithSliders)); - - // Min is needed for edgecase maps with 1 circle and 999 sliders, as deviation on sliders can be lower in this case - return Math.Min(deviation.Value, deviationWithSliders); - } - /// /// Estimates player's deviation on speed notes using , assuming worst-case. /// Treats all speed notes as hit circles. diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs index 69211b610f..f04b679b73 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private double currentStrain; - private double skillMultiplier => 25.7; + private double skillMultiplier => 25.6; private double strainDecayBase => 0.15; private readonly List sliderStrains = new List();