From 87570ed238bb303237d40aa3a51a3af46317e17d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Jul 2023 17:23:31 +0900 Subject: [PATCH] Fix incorrect slider stacking on very old beatmaps Closes https://github.com/ppy/osu/issues/24185 The stable code has had a bug in this logic forever. So we'll need to reimplement the bug. Basically, sliders have to have `UpdateCalculations` run in order to have a correct `Position2` and `EndTime`, but this wasn't being called in the inner loop before use of `EndTime` at https://github.com/peppy/osu-stable-reference/blob/1531237b63392e82c003c712faa028406073aa8f/osu!/GameplayElements/HitObjectManager.cs#L1813. To fix this, we use `StartTime` in the inner loop to reproduce the bug. --- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index f51f04bf87..c081df3ac6 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -214,17 +214,24 @@ namespace osu.Game.Rulesets.Osu.Beatmaps ? currSlider.Position + currSlider.Path.PositionAt(1) : currHitObject.Position; + // Note the use of `StartTime` in the code below doesn't match stable's use of `EndTime`. + // This is because in the stable implementation, `UpdateCalculations` is not called on the inner-loop hitobject (j) + // and therefore it does not have a correct `EndTime`, but instead the default of `EndTime = StartTime`. + // + // Effects of this can be seen on https://osu.ppy.sh/beatmapsets/243#osu/1146 at sliders around 86647 ms, where + // if we use `EndTime` here it would result in unexpected stacking. + if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, currHitObject.Position) < stack_distance) { currHitObject.StackHeight++; - startTime = beatmap.HitObjects[j].GetEndTime(); + startTime = beatmap.HitObjects[j].StartTime; } else if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, position2) < stack_distance) { // Case for sliders - bump notes down and right, rather than up and left. sliderStack++; beatmap.HitObjects[j].StackHeight -= sliderStack; - startTime = beatmap.HitObjects[j].GetEndTime(); + startTime = beatmap.HitObjects[j].StartTime; } } }