1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-26 19:20:47 +08:00

Fix combined slider velocity calculation (#36773)

This changes how the current/previous velocity is being calculated in
Aim. Currently it's being calculated as an addition of 2 velocities
together which isn't really correct, instead here velocity is being
calculated as a (combined distances) / (combined times). On practice
this buffs underweighted slider maps while overweighted ones stay about
the same

https://pp.huismetbenen.nl/rankings/players/use-proper-slider-velocity
This commit is contained in:
StanR
2026-03-03 04:14:31 +05:00
committed by GitHub
Unverified
parent 2d6fa65262
commit f241d9c84e
2 changed files with 6 additions and 10 deletions
@@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
{
private const double wide_angle_multiplier = 1.5;
private const double acute_angle_multiplier = 2.6;
private const double slider_multiplier = 1.5;
private const double slider_multiplier = 2.9;
private const double velocity_change_multiplier = 0.9;
private const double wiggle_multiplier = 1.02; // WARNING: Increasing this multiplier beyond 1.02 reduces difficulty as distance increases. Refer to the desmos link above the wiggle bonus calculation
@@ -46,10 +46,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
// But if the last object is a slider, then we extend the travel velocity through the slider into the current object.
if (osuLastObj.BaseObject is Slider && withSliderTravelDistance)
{
double travelVelocity = osuLastObj.TravelDistance / osuLastObj.TravelTime; // calculate the slider velocity from slider head to slider end.
double movementVelocity = osuCurrObj.MinimumJumpDistance / osuCurrObj.MinimumJumpTime; // calculate the movement velocity from slider end to current object
currVelocity = Math.Max(currVelocity, movementVelocity + travelVelocity); // take the larger total combined velocity.
double sliderDistance = osuLastObj.LazyTravelDistance + osuCurrObj.LazyJumpDistance;
currVelocity = Math.Max(currVelocity, sliderDistance / osuCurrObj.AdjustedDeltaTime);
}
// As above, do the same for the previous hitobject.
@@ -58,10 +56,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
if (osuLastLastObj.BaseObject is Slider && withSliderTravelDistance)
{
double travelVelocity = osuLastLastObj.TravelDistance / osuLastLastObj.TravelTime;
double movementVelocity = osuLastObj.MinimumJumpDistance / osuLastObj.MinimumJumpTime;
prevVelocity = Math.Max(prevVelocity, movementVelocity + travelVelocity);
double sliderDistance = osuLastLastObj.LazyTravelDistance + osuLastObj.LazyJumpDistance;
prevVelocity = Math.Max(prevVelocity, sliderDistance / osuLastObj.AdjustedDeltaTime);
}
double wideAngleBonus = 0;
@@ -199,7 +199,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
if (BaseObject is Slider currentSlider)
{
// Bonus for repeat sliders until a better per nested object strain system can be achieved.
TravelDistance = LazyTravelDistance * Math.Pow(1 + currentSlider.RepeatCount / 2.5, 1.0 / 2.5);
TravelDistance = LazyTravelDistance * Math.Max(1, Math.Pow(currentSlider.RepeatCount, 0.2));
TravelTime = Math.Max(LazyTravelTime / clockRate, MIN_DELTA_TIME);
}