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:
parent
c53188cf45
commit
6cf15e3e5a
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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>();
|
||||
|
Loading…
Reference in New Issue
Block a user