diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index 8722b85839..fd14f664d8 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -93,37 +93,60 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing int repeatCount = 0; + Vector2 currSliderPosition = ((OsuHitObject)lastSlider.NestedHitObjects[0]).StackedPosition; + for (int i = 1; i < lastSlider.NestedHitObjects.Count; i++) { - Vector2 currSlider = Vector2.Subtract(((OsuHitObject)lastSlider.NestedHitObjects[i]).StackedPosition, ((OsuHitObject)lastSlider.NestedHitObjects[i - 1]).StackedPosition); + Vector2 currSlider = Vector2.Subtract(((OsuHitObject)lastSlider.NestedHitObjects[i]).StackedPosition, currSliderPosition); + double currSliderLength = currSlider.Length * scalingFactor; - if ((OsuHitObject)lastSlider.NestedHitObjects[i] is SliderRepeat && (OsuHitObject)lastSlider.NestedHitObjects[i - 1] is SliderRepeat) + if ((OsuHitObject)lastSlider.NestedHitObjects[i] is SliderEndCircle && !((OsuHitObject)lastSlider.NestedHitObjects[i] is SliderRepeat)) { - repeatCount++; - TravelDistance += Math.Max(0, currSlider.Length * scalingFactor - 240); // remove 240 distance to avoid buffing overlapping followcircles. + Vector2 possSlider = Vector2.Subtract((Vector2)lastSlider.LazyEndPosition, currSliderPosition); + if (possSlider.Length < currSlider.Length) + currSlider = possSlider; // Take the least distance from slider end vs lazy end. + + currSliderLength = currSlider.Length * scalingFactor; + } + + if ((OsuHitObject)lastSlider.NestedHitObjects[i] is SliderTick) + { + if (currSliderLength > 120) + { + currSliderPosition = Vector2.Add(currSliderPosition, Vector2.Multiply(currSlider, (float)((currSliderLength - 120) / currSliderLength))); + currSliderLength *= (currSliderLength - 120) / currSliderLength; + } + else + currSliderLength = 0; } else if ((OsuHitObject)lastSlider.NestedHitObjects[i] is SliderRepeat) { - repeatCount++; - TravelDistance += Math.Max(0, currSlider.Length * scalingFactor - 120); // remove 120 distance to avoid buffing overlapping followcircles. - } - else if ((OsuHitObject)lastSlider.NestedHitObjects[i] is SliderEndCircle) - { - Vector2 possSlider = Vector2.Subtract((Vector2)lastSlider.LazyEndPosition, ((OsuHitObject)lastSlider.NestedHitObjects[i - 1]).StackedPosition); - TravelDistance += Math.Min(possSlider.Length, currSlider.Length) * scalingFactor; // Take the least distance from slider end vs lazy end. + if (currSliderLength > 50) + { + currSliderPosition = Vector2.Add(currSliderPosition, Vector2.Multiply(currSlider, (float)((currSliderLength - 50) / currSliderLength))); + currSliderLength *= (currSliderLength - 50) / currSliderLength; + } + else + currSliderLength = 0; } else - TravelDistance += Math.Max(0, currSlider.Length * scalingFactor - 100); // remove 100 distance to avoid buffing overlapping ticks, mostly needed to prevent buffing slow sliders with high tick rate. + { + if (currSliderLength > 0) + { + currSliderPosition = Vector2.Add(currSliderPosition, Vector2.Multiply(currSlider, (float)((currSliderLength - 0) / currSliderLength))); + currSliderLength *= (currSliderLength - 0) / currSliderLength; + } + else + currSliderLength = 0; + } + + if ((OsuHitObject)lastSlider.NestedHitObjects[i] is SliderRepeat) + repeatCount++; + + TravelDistance += currSliderLength; } - if (repeatCount == 0) - { - TravelDistance = Math.Max(TravelDistance, scalingFactor * // idea here is to prevent ticks from dropping difficulty of slider by removing distance in calculation. - Math.Min(Vector2.Subtract(((OsuHitObject)lastSlider.NestedHitObjects[lastSlider.NestedHitObjects.Count - 1]).StackedPosition, ((OsuHitObject)lastSlider.NestedHitObjects[0]).StackedPosition).Length, - Vector2.Subtract((Vector2)lastSlider.LazyEndPosition, ((OsuHitObject)lastSlider.NestedHitObjects[0]).StackedPosition).Length)); - } - else - TravelDistance *= Math.Pow(1 + repeatCount / 2.0, 1.0 / 2.0); // Bonus for repeat sliders until a better per nested object strain system can be achieved. + TravelDistance *= Math.Pow(1 + repeatCount / 2.5, 1.0 / 2.5); // Bonus for repeat sliders until a better per nested object strain system can be achieved. } Vector2 lastCursorPosition = getEndCursorPosition(lastObject);