1
0
mirror of https://github.com/ppy/osu.git synced 2026-06-05 17:54:14 +08:00

Buff precision difficulty rating in osu! (#28877)

* Buff precision difficulty rating in osu!

* Fix position repetition calculation

* Fix aim evaluator crashing, move small circle bonus calculation, adjust the curve slightly

* Refactor

* Fix code quality

* Semicolon

* Apply small circle bonus to speed too

* Fix formatting

---------

Co-authored-by: James Wilson <tsunyoku@gmail.com>
This commit is contained in:
StanR
2025-05-22 13:11:51 +05:00
committed by GitHub
Unverified
parent 4a343ceaf1
commit 60eaf088df
3 changed files with 29 additions and 6 deletions
@@ -34,6 +34,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
var osuCurrObj = (OsuDifficultyHitObject)current;
var osuLastObj = (OsuDifficultyHitObject)current.Previous(0);
var osuLastLastObj = (OsuDifficultyHitObject)current.Previous(1);
var osuLast2Obj = (OsuDifficultyHitObject)current.Previous(2);
const int radius = OsuDifficultyHitObject.NORMALISED_RADIUS;
const int diameter = OsuDifficultyHitObject.NORMALISED_DIAMETER;
@@ -103,6 +104,21 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
* DifficultyCalculationUtils.Smootherstep(osuLastObj.LazyJumpDistance, radius, diameter)
* Math.Pow(DifficultyCalculationUtils.ReverseLerp(osuLastObj.LazyJumpDistance, diameter * 3, diameter), 1.8)
* DifficultyCalculationUtils.Smootherstep(lastAngle, double.DegreesToRadians(110), double.DegreesToRadians(60));
if (osuLast2Obj != null)
{
// If objects just go back and forth through a middle point - don't give as much wide bonus
// Use Previous(2) and Previous(0) because angles calculation is done prevprev-prev-curr, so any object's angle's center point is always the previous object
var lastBaseObject = (OsuHitObject)osuLastObj.BaseObject;
var last2BaseObject = (OsuHitObject)osuLast2Obj.BaseObject;
float distance = (last2BaseObject.StackedPosition - lastBaseObject.StackedPosition).Length;
if (distance < 1)
{
wideAngleBonus *= 1 - 0.35 * (1 - distance);
}
}
}
}
@@ -139,6 +155,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
if (withSliderTravelDistance)
aimStrain += sliderBonus * slider_multiplier;
// Apply high circle size bonus
aimStrain *= osuCurrObj.SmallCircleBonus;
return aimStrain;
}
@@ -60,6 +60,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
// Max distance bonus is 1 * `distance_multiplier` at single_spacing_threshold
double distanceBonus = Math.Pow(distance / single_spacing_threshold, 3.95) * distance_multiplier;
// Apply reduced small circle bonus because flow aim difficulty on small circles doesn't scale as hard as jumps
distanceBonus *= Math.Sqrt(osuCurrObj.SmallCircleBonus);
if (mods.OfType<OsuModAutopilot>().Any())
distanceBonus = 0;
@@ -105,6 +105,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
/// </summary>
public double HitWindowGreat { get; private set; }
/// <summary>
/// Selective bonus for maps with higher circle size.
/// </summary>
public double SmallCircleBonus { get; private set; }
private readonly OsuDifficultyHitObject? lastLastDifficultyObject;
private readonly OsuDifficultyHitObject? lastDifficultyObject;
@@ -117,6 +122,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
// Capped to 25ms to prevent difficulty calculation breaking from simultaneous objects.
StrainTime = Math.Max(DeltaTime, MIN_DELTA_TIME);
SmallCircleBonus = Math.Max(1.0, 1.0 + (30 - BaseObject.Radius) / 40);
if (BaseObject is Slider sliderObject)
{
HitWindowGreat = 2 * sliderObject.HeadCircle.HitWindows.WindowFor(HitResult.Great) / clockRate;
@@ -193,12 +200,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
// We will scale distances by this factor, so we can assume a uniform CircleSize among beatmaps.
float scalingFactor = NORMALISED_RADIUS / (float)BaseObject.Radius;
if (BaseObject.Radius < 30)
{
float smallCircleBonus = Math.Min(30 - (float)BaseObject.Radius, 5) / 50;
scalingFactor *= 1 + smallCircleBonus;
}
Vector2 lastCursorPosition = lastDifficultyObject != null ? getEndCursorPosition(lastDifficultyObject) : LastObject.StackedPosition;
LazyJumpDistance = (BaseObject.StackedPosition * scalingFactor - lastCursorPosition * scalingFactor).Length;