Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify osu! high-bpm acute angle jumps bonus #30902

Merged
merged 15 commits into from
Dec 20, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Simplify osu! high-bpm acute angle jumps bonus
  • Loading branch information
stanriders committed Nov 27, 2024
commit bb21dd0a72d153ee611f6c566bc1f4e1296e418c
22 changes: 8 additions & 14 deletions osu.Game.Rulesets.Osu/Difficulty/Evaluators/AimEvaluator.cs
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
public static class AimEvaluator
{
private const double wide_angle_multiplier = 1.5;
private const double acute_angle_multiplier = 1.95;
private const double acute_angle_multiplier = 2.5;
private const double slider_multiplier = 1.35;
private const double velocity_change_multiplier = 0.75;

@@ -34,7 +34,6 @@ public static double EvaluateDifficultyOf(DifficultyHitObject current, bool with
var osuLastObj = (OsuDifficultyHitObject)current.Previous(0);
var osuLastLastObj = (OsuDifficultyHitObject)current.Previous(1);

const int radius = OsuDifficultyHitObject.NORMALISED_RADIUS;
const int diameter = OsuDifficultyHitObject.NORMALISED_DIAMETER;

// Calculate the velocity to the current hitobject, which starts with a base distance / time assuming the last object is a hitcircle.
@@ -79,22 +78,17 @@ public static double EvaluateDifficultyOf(DifficultyHitObject current, bool with
double angleBonus = Math.Min(currVelocity, prevVelocity);

wideAngleBonus = calcWideAngleBonus(currAngle);
acuteAngleBonus = calcAcuteAngleBonus(currAngle);

if (DifficultyCalculationUtils.MillisecondsToBPM(osuCurrObj.StrainTime, 2) < 300) // Only buff deltaTime exceeding 300 bpm 1/2.
acuteAngleBonus = 0;
else
{
acuteAngleBonus *= calcAcuteAngleBonus(lastAngle) // Multiply by previous angle, we don't want to buff unless this is a wiggle type pattern.
* Math.Min(angleBonus, diameter * 1.25 / osuCurrObj.StrainTime) // The maximum velocity we buff is equal to 125 / strainTime
* Math.Pow(Math.Sin(Math.PI / 2 * Math.Min(1, (100 - osuCurrObj.StrainTime) / 25)), 2) // scale buff from 150 bpm 1/4 to 200 bpm 1/4
* Math.Pow(Math.Sin(Math.PI / 2 * (Math.Clamp(osuCurrObj.LazyJumpDistance, radius, diameter) - radius) / radius), 2); // Buff distance exceeding radius up to diameter.
}

// Apply acute angle bonus for BPM above 300 1/2 and distance more than one diameter
acuteAngleBonus = calcAcuteAngleBonus(currAngle) *
angleBonus *
DifficultyCalculationUtils.Smootherstep(DifficultyCalculationUtils.MillisecondsToBPM(osuCurrObj.StrainTime, 2), 300, 400) *
DifficultyCalculationUtils.Smootherstep(osuCurrObj.LazyJumpDistance, diameter, diameter * 2);

// Penalize wide angles if they're repeated, reducing the penalty as the lastAngle gets more acute.
wideAngleBonus *= angleBonus * (1 - Math.Min(wideAngleBonus, Math.Pow(calcWideAngleBonus(lastAngle), 3)));
// Penalize acute angles if they're repeated, reducing the penalty as the lastLastAngle gets more obtuse.
acuteAngleBonus *= 0.5 + 0.5 * (1 - Math.Min(acuteAngleBonus, Math.Pow(calcAcuteAngleBonus(lastLastAngle), 3)));
acuteAngleBonus *= 1 - Math.Min(acuteAngleBonus, Math.Pow(calcAcuteAngleBonus(lastLastAngle), 3));
}
}

13 changes: 13 additions & 0 deletions osu.Game/Rulesets/Difficulty/Utils/DifficultyCalculationUtils.cs
Original file line number Diff line number Diff line change
@@ -46,5 +46,18 @@ public static double MillisecondsToBPM(double ms, int delimiter = 4)
/// <param name="exponent">Exponent</param>
/// <returns>The output of logistic function</returns>
public static double Logistic(double exponent, double maxValue = 1) => maxValue / (1 + Math.Exp(exponent));

/// <summary>
/// Smootherstep function (https://en.wikipedia.org/wiki/Smoothstep#Variations)
/// </summary>
/// <param name="x">Value to calculate the function for</param>
/// <param name="start">Value at which function returns 0</param>
/// <param name="end">Value at which function returns 1</param>
public static double Smootherstep(double x, double start, double end)
{
x = Math.Clamp((x - start) / (end - start), 0.0, 1.0);

return x * x * x * (x * (6.0 * x - 15.0) + 10.0);
}
}
}