1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-08 06:36:05 +08:00

Fix stack leniency not applying immediately after change

This commit is contained in:
Bartłomiej Dach 2024-06-10 14:34:04 +02:00
parent a8a2e543d5
commit 25b2dfa601
No known key found for this signature in database
3 changed files with 31 additions and 29 deletions

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -41,22 +42,22 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
{ {
base.PostProcess(); base.PostProcess();
var osuBeatmap = (Beatmap<OsuHitObject>)Beatmap; var hitObjects = Beatmap.HitObjects as List<OsuHitObject> ?? Beatmap.HitObjects.OfType<OsuHitObject>().ToList();
if (osuBeatmap.HitObjects.Count > 0) if (hitObjects.Count > 0)
{ {
// Reset stacking // Reset stacking
foreach (var h in osuBeatmap.HitObjects) foreach (var h in hitObjects)
h.StackHeight = 0; h.StackHeight = 0;
if (Beatmap.BeatmapInfo.BeatmapVersion >= 6) if (Beatmap.BeatmapInfo.BeatmapVersion >= 6)
applyStacking(osuBeatmap, 0, osuBeatmap.HitObjects.Count - 1); applyStacking(Beatmap.BeatmapInfo, hitObjects, 0, hitObjects.Count - 1);
else else
applyStackingOld(osuBeatmap); applyStackingOld(Beatmap.BeatmapInfo, hitObjects);
} }
} }
private void applyStacking(Beatmap<OsuHitObject> beatmap, int startIndex, int endIndex) private void applyStacking(BeatmapInfo beatmapInfo, List<OsuHitObject> hitObjects, int startIndex, int endIndex)
{ {
ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex, endIndex); ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex, endIndex);
ArgumentOutOfRangeException.ThrowIfNegative(startIndex); ArgumentOutOfRangeException.ThrowIfNegative(startIndex);
@ -64,24 +65,24 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
int extendedEndIndex = endIndex; int extendedEndIndex = endIndex;
if (endIndex < beatmap.HitObjects.Count - 1) if (endIndex < hitObjects.Count - 1)
{ {
// Extend the end index to include objects they are stacked on // Extend the end index to include objects they are stacked on
for (int i = endIndex; i >= startIndex; i--) for (int i = endIndex; i >= startIndex; i--)
{ {
int stackBaseIndex = i; int stackBaseIndex = i;
for (int n = stackBaseIndex + 1; n < beatmap.HitObjects.Count; n++) for (int n = stackBaseIndex + 1; n < hitObjects.Count; n++)
{ {
OsuHitObject stackBaseObject = beatmap.HitObjects[stackBaseIndex]; OsuHitObject stackBaseObject = hitObjects[stackBaseIndex];
if (stackBaseObject is Spinner) break; if (stackBaseObject is Spinner) break;
OsuHitObject objectN = beatmap.HitObjects[n]; OsuHitObject objectN = hitObjects[n];
if (objectN is Spinner) if (objectN is Spinner)
continue; continue;
double endTime = stackBaseObject.GetEndTime(); double endTime = stackBaseObject.GetEndTime();
double stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo.StackLeniency; double stackThreshold = objectN.TimePreempt * beatmapInfo.StackLeniency;
if (objectN.StartTime - endTime > stackThreshold) if (objectN.StartTime - endTime > stackThreshold)
// We are no longer within stacking range of the next object. // We are no longer within stacking range of the next object.
@ -100,7 +101,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
if (stackBaseIndex > extendedEndIndex) if (stackBaseIndex > extendedEndIndex)
{ {
extendedEndIndex = stackBaseIndex; extendedEndIndex = stackBaseIndex;
if (extendedEndIndex == beatmap.HitObjects.Count - 1) if (extendedEndIndex == hitObjects.Count - 1)
break; break;
} }
} }
@ -123,10 +124,10 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
* 2 and 1 will be ignored in the i loop because they already have a stack value. * 2 and 1 will be ignored in the i loop because they already have a stack value.
*/ */
OsuHitObject objectI = beatmap.HitObjects[i]; OsuHitObject objectI = hitObjects[i];
if (objectI.StackHeight != 0 || objectI is Spinner) continue; if (objectI.StackHeight != 0 || objectI is Spinner) continue;
double stackThreshold = objectI.TimePreempt * beatmap.BeatmapInfo.StackLeniency; double stackThreshold = objectI.TimePreempt * beatmapInfo.StackLeniency;
/* If this object is a hitcircle, then we enter this "special" case. /* If this object is a hitcircle, then we enter this "special" case.
* It either ends with a stack of hitcircles only, or a stack of hitcircles that are underneath a slider. * It either ends with a stack of hitcircles only, or a stack of hitcircles that are underneath a slider.
@ -136,7 +137,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
{ {
while (--n >= 0) while (--n >= 0)
{ {
OsuHitObject objectN = beatmap.HitObjects[n]; OsuHitObject objectN = hitObjects[n];
if (objectN is Spinner) continue; if (objectN is Spinner) continue;
double endTime = objectN.GetEndTime(); double endTime = objectN.GetEndTime();
@ -164,7 +165,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
for (int j = n + 1; j <= i; j++) for (int j = n + 1; j <= i; j++)
{ {
// For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above). // For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above).
OsuHitObject objectJ = beatmap.HitObjects[j]; OsuHitObject objectJ = hitObjects[j];
if (Vector2Extensions.Distance(objectN.EndPosition, objectJ.Position) < stack_distance) if (Vector2Extensions.Distance(objectN.EndPosition, objectJ.Position) < stack_distance)
objectJ.StackHeight -= offset; objectJ.StackHeight -= offset;
} }
@ -191,7 +192,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
*/ */
while (--n >= startIndex) while (--n >= startIndex)
{ {
OsuHitObject objectN = beatmap.HitObjects[n]; OsuHitObject objectN = hitObjects[n];
if (objectN is Spinner) continue; if (objectN is Spinner) continue;
if (objectI.StartTime - objectN.StartTime > stackThreshold) if (objectI.StartTime - objectN.StartTime > stackThreshold)
@ -208,11 +209,11 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
} }
} }
private void applyStackingOld(Beatmap<OsuHitObject> beatmap) private void applyStackingOld(BeatmapInfo beatmapInfo, List<OsuHitObject> hitObjects)
{ {
for (int i = 0; i < beatmap.HitObjects.Count; i++) for (int i = 0; i < hitObjects.Count; i++)
{ {
OsuHitObject currHitObject = beatmap.HitObjects[i]; OsuHitObject currHitObject = hitObjects[i];
if (currHitObject.StackHeight != 0 && !(currHitObject is Slider)) if (currHitObject.StackHeight != 0 && !(currHitObject is Slider))
continue; continue;
@ -220,11 +221,11 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
double startTime = currHitObject.GetEndTime(); double startTime = currHitObject.GetEndTime();
int sliderStack = 0; int sliderStack = 0;
for (int j = i + 1; j < beatmap.HitObjects.Count; j++) for (int j = i + 1; j < hitObjects.Count; j++)
{ {
double stackThreshold = beatmap.HitObjects[i].TimePreempt * beatmap.BeatmapInfo.StackLeniency; double stackThreshold = hitObjects[i].TimePreempt * beatmapInfo.StackLeniency;
if (beatmap.HitObjects[j].StartTime - stackThreshold > startTime) if (hitObjects[j].StartTime - stackThreshold > startTime)
break; break;
// The start position of the hitobject, or the position at the end of the path if the hitobject is a slider // The start position of the hitobject, or the position at the end of the path if the hitobject is a slider
@ -239,17 +240,17 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
// Effects of this can be seen on https://osu.ppy.sh/beatmapsets/243#osu/1146 at sliders around 86647 ms, where // 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 we use `EndTime` here it would result in unexpected stacking.
if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, currHitObject.Position) < stack_distance) if (Vector2Extensions.Distance(hitObjects[j].Position, currHitObject.Position) < stack_distance)
{ {
currHitObject.StackHeight++; currHitObject.StackHeight++;
startTime = beatmap.HitObjects[j].StartTime; startTime = hitObjects[j].StartTime;
} }
else if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, position2) < stack_distance) else if (Vector2Extensions.Distance(hitObjects[j].Position, position2) < stack_distance)
{ {
// Case for sliders - bump notes down and right, rather than up and left. // Case for sliders - bump notes down and right, rather than up and left.
sliderStack++; sliderStack++;
beatmap.HitObjects[j].StackHeight -= sliderStack; hitObjects[j].StackHeight -= sliderStack;
startTime = beatmap.HitObjects[j].StartTime; startTime = hitObjects[j].StartTime;
} }
} }
} }

View File

@ -49,6 +49,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Setup
private void updateBeatmap() private void updateBeatmap()
{ {
Beatmap.BeatmapInfo.StackLeniency = stackLeniency.Current.Value; Beatmap.BeatmapInfo.StackLeniency = stackLeniency.Current.Value;
Beatmap.UpdateAllHitObjects();
Beatmap.SaveState(); Beatmap.SaveState();
} }
} }

View File

@ -105,7 +105,7 @@ namespace osu.Game.Screens.Edit
BeatmapSkin.BeatmapSkinChanged += SaveState; BeatmapSkin.BeatmapSkinChanged += SaveState;
} }
beatmapProcessor = playableBeatmap.BeatmapInfo.Ruleset.CreateInstance().CreateBeatmapProcessor(PlayableBeatmap); beatmapProcessor = playableBeatmap.BeatmapInfo.Ruleset.CreateInstance().CreateBeatmapProcessor(this);
foreach (var obj in HitObjects) foreach (var obj in HitObjects)
trackStartTime(obj); trackStartTime(obj);