1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-18 05:42:56 +08:00

Remove problematic total deviation scaling, rebalance aim (#31515)

* Remove problematic total deviation scaling, rebalance aim

* Fix tests
This commit is contained in:
James Wilson 2025-01-14 18:27:25 +00:00 committed by GitHub
parent c53188cf45
commit 6cf15e3e5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 11 additions and 60 deletions

View File

@ -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());

View File

@ -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);

View File

@ -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; }

View File

@ -42,7 +42,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty
/// </summary>
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;
}
/// <summary>
/// Using <see cref="calculateDeviation"/> 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.
/// </summary>
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);
}
/// <summary>
/// Estimates player's deviation on speed notes using <see cref="calculateDeviation"/>, assuming worst-case.
/// Treats all speed notes as hit circles.

View File

@ -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<double> sliderStrains = new List<double>();