1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 18:07:23 +08:00

Add reordering support to match existing diffcalc 100%

This commit is contained in:
Dean Herbert 2023-10-13 14:25:38 +09:00
parent 5ffc25c8e8
commit a3b21281e6
No known key found for this signature in database

View File

@ -215,7 +215,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
if (slider.LazyEndPosition != null)
return;
// This commented version is actually correct by the new lazer implementation, but intentionally held back from
// TODO: This commented version is actually correct by the new lazer implementation, but intentionally held back from
// difficulty calculator to preserve known behaviour.
// double trackingEndTime = Math.Max(
// // SliderTailCircle always occurs at the final end time of the slider, but the player only needs to hold until within a lenience before it.
@ -225,10 +225,33 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
// slider.NestedHitObjects.LastOrDefault(n => n is not SliderTailCircle)?.StartTime ?? double.MinValue
// );
double trackingEndTime = Math.Max(Math.Max(
double trackingEndTime = Math.Max(
slider.StartTime + slider.Duration + SliderEventGenerator.TAIL_LENIENCY,
slider.StartTime + slider.Duration / 2
), slider.NestedHitObjects.OfType<SliderTick>().LastOrDefault()?.StartTime ?? double.MinValue);
);
IList<HitObject> nestedObjects = slider.NestedHitObjects;
SliderTick? lastRealTick = slider.NestedHitObjects.OfType<SliderTick>().LastOrDefault();
if (lastRealTick?.StartTime > trackingEndTime)
{
trackingEndTime = lastRealTick.StartTime;
// When the last tick falls after the tracking end time, we need to re-sort the nested objects
// based on time. This creates a somewhat weird ordering which is counter to how a user would
// understand the slider, but allows a zero-diff with known diffcalc output.
//
// To reiterate, this is definitely not correct from a difficulty calculation perspective
// and should be revisited at a later date (likely by replacing this whole code with the commented
// version above).
List<HitObject> reordered = nestedObjects.ToList();
reordered.Remove(lastRealTick);
reordered.Add(lastRealTick);
nestedObjects = reordered;
}
slider.LazyTravelTime = trackingEndTime - slider.StartTime;
@ -239,12 +262,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
endTimeMin %= 1;
slider.LazyEndPosition = slider.StackedPosition + slider.Path.PositionAt(endTimeMin); // temporary lazy end position until a real result can be derived.
var currCursorPosition = slider.StackedPosition;
Vector2 currCursorPosition = slider.StackedPosition;
double scalingFactor = NORMALISED_RADIUS / slider.Radius; // lazySliderDistance is coded to be sensitive to scaling, this makes the maths easier with the thresholds being used.
for (int i = 1; i < slider.NestedHitObjects.Count; i++)
for (int i = 1; i < nestedObjects.Count; i++)
{
var currMovementObj = (OsuHitObject)slider.NestedHitObjects[i];
var currMovementObj = (OsuHitObject)nestedObjects[i];
Vector2 currMovement = Vector2.Subtract(currMovementObj.StackedPosition, currCursorPosition);
double currMovementLength = scalingFactor * currMovement.Length;
@ -252,7 +277,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
// Amount of movement required so that the cursor position needs to be updated.
double requiredMovement = assumed_slider_radius;
if (i == slider.NestedHitObjects.Count - 1)
if (i == nestedObjects.Count - 1)
{
// The end of a slider has special aim rules due to the relaxed time constraint on position.
// There is both a lazy end position as well as the actual end slider position. We assume the player takes the simpler movement.
@ -279,7 +304,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
slider.LazyTravelDistance += (float)currMovementLength;
}
if (i == slider.NestedHitObjects.Count - 1)
if (i == nestedObjects.Count - 1)
slider.LazyEndPosition = currCursorPosition;
}
}