mirror of
https://github.com/ppy/osu.git
synced 2025-02-12 05:03:20 +08:00
implemented Strict Tracking pp
This commit is contained in:
parent
5d48b9c6af
commit
2ad4ee2e07
@ -88,11 +88,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
|||||||
private readonly OsuHitObject? lastLastObject;
|
private readonly OsuHitObject? lastLastObject;
|
||||||
private readonly OsuHitObject lastObject;
|
private readonly OsuHitObject lastObject;
|
||||||
|
|
||||||
|
private readonly Mod[] mods;
|
||||||
|
|
||||||
public OsuDifficultyHitObject(HitObject hitObject, HitObject lastObject, HitObject? lastLastObject, double clockRate, List<DifficultyHitObject> objects, int index, Mod[] mods)
|
public OsuDifficultyHitObject(HitObject hitObject, HitObject lastObject, HitObject? lastLastObject, double clockRate, List<DifficultyHitObject> objects, int index, Mod[] mods)
|
||||||
: base(hitObject, lastObject, clockRate, objects, index)
|
: base(hitObject, lastObject, clockRate, objects, index)
|
||||||
{
|
{
|
||||||
this.lastLastObject = lastLastObject as OsuHitObject;
|
this.lastLastObject = lastLastObject as OsuHitObject;
|
||||||
this.lastObject = (OsuHitObject)lastObject;
|
this.lastObject = (OsuHitObject)lastObject;
|
||||||
|
this.mods = mods;
|
||||||
|
|
||||||
// Capped to 25ms to prevent difficulty calculation breaking from simultaneous objects.
|
// Capped to 25ms to prevent difficulty calculation breaking from simultaneous objects.
|
||||||
StrainTime = Math.Max(DeltaTime, MIN_DELTA_TIME);
|
StrainTime = Math.Max(DeltaTime, MIN_DELTA_TIME);
|
||||||
@ -333,6 +336,15 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
|||||||
if (i == nestedObjects.Count - 1)
|
if (i == nestedObjects.Count - 1)
|
||||||
slider.LazyEndPosition = currCursorPosition;
|
slider.LazyEndPosition = currCursorPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mods.OfType<OsuModStrictTracking>().Any())
|
||||||
|
{
|
||||||
|
double strictVelocity = calculateStrictSliderVelocity(slider);
|
||||||
|
double strictDistance = strictVelocity * slider.LazyTravelTime;
|
||||||
|
|
||||||
|
Console.WriteLine($"Normal = {slider.LazyTravelDistance:0.00}, Strict = {strictDistance:0.00}");
|
||||||
|
slider.LazyTravelDistance = Math.Max(slider.LazyTravelDistance, (float)strictDistance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Vector2 positionWithRepeats(double relativeTime, Slider slider)
|
private static Vector2 positionWithRepeats(double relativeTime, Slider slider)
|
||||||
@ -343,10 +355,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
|||||||
return slider.Position + slider.Path.PositionAt(progress);
|
return slider.Position + slider.Path.PositionAt(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculateStrictSliderPath(Slider slider)
|
private double calculateStrictSliderVelocity(Slider slider)
|
||||||
{
|
{
|
||||||
|
//Console.WriteLine($"Calculating strict path for {slider.StartTime}");
|
||||||
|
|
||||||
|
float scalingFactor = (float)(NORMALISED_RADIUS / slider.Radius);
|
||||||
|
|
||||||
double updateDistance = slider.Radius;
|
double updateDistance = slider.Radius;
|
||||||
float followCircleRadius = (float)(slider.Radius * 2.4);
|
float followCircleRadius = assumed_slider_radius / scalingFactor;
|
||||||
|
|
||||||
// WARNING, this is lazer-correct implementation because stable doesn't have Strict Tracking mod
|
// WARNING, this is lazer-correct implementation because stable doesn't have Strict Tracking mod
|
||||||
// This means that path of this function can be lower than normal path
|
// This means that path of this function can be lower than normal path
|
||||||
@ -355,6 +371,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
|||||||
slider.NestedHitObjects.LastOrDefault(n => n is not SliderTailCircle)?.StartTime ?? double.MinValue
|
slider.NestedHitObjects.LastOrDefault(n => n is not SliderTailCircle)?.StartTime ?? double.MinValue
|
||||||
);
|
);
|
||||||
|
|
||||||
|
trackingEndTime = Math.Max(trackingEndTime, slider.StartTime + slider.Duration / 2);
|
||||||
|
|
||||||
OsuHitObject head;
|
OsuHitObject head;
|
||||||
if (slider.RepeatCount == 0)
|
if (slider.RepeatCount == 0)
|
||||||
head = (OsuHitObject)slider.NestedHitObjects[0];
|
head = (OsuHitObject)slider.NestedHitObjects[0];
|
||||||
@ -364,12 +382,17 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
|||||||
var tail = (OsuHitObject)slider.NestedHitObjects[^1];
|
var tail = (OsuHitObject)slider.NestedHitObjects[^1];
|
||||||
|
|
||||||
double totalTrackingTime = trackingEndTime - head.StartTime;
|
double totalTrackingTime = trackingEndTime - head.StartTime;
|
||||||
|
if (totalTrackingTime == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
double numberOfUpdates = Math.Ceiling(slider.Path.Distance / updateDistance);
|
double numberOfUpdates = Math.Ceiling(slider.Path.Distance / updateDistance);
|
||||||
|
|
||||||
double deltaT = totalTrackingTime / numberOfUpdates;
|
double deltaT = totalTrackingTime / numberOfUpdates;
|
||||||
|
|
||||||
double totalPath = 0;
|
double totalPath = 0;
|
||||||
Vector2 currentCursorPosition = head.StackedPosition;
|
Vector2 currentCursorPosition = head.StackedPosition;
|
||||||
|
|
||||||
|
double peakVelocity = 0;
|
||||||
double lastTimeWithMovement = 0;
|
double lastTimeWithMovement = 0;
|
||||||
|
|
||||||
for (double relativeTime = 0; relativeTime <= totalTrackingTime; relativeTime += deltaT)
|
for (double relativeTime = 0; relativeTime <= totalTrackingTime; relativeTime += deltaT)
|
||||||
@ -382,14 +405,17 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
|||||||
if (distanceToCursor <= followCircleRadius)
|
if (distanceToCursor <= followCircleRadius)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
lastTimeWithMovement = relativeTime;
|
|
||||||
float neededMovement = distanceToCursor - followCircleRadius;
|
float neededMovement = distanceToCursor - followCircleRadius;
|
||||||
|
double currentVelocity = neededMovement / (relativeTime - lastTimeWithMovement);
|
||||||
|
peakVelocity = Math.Max(peakVelocity, currentVelocity);
|
||||||
|
|
||||||
|
lastTimeWithMovement = relativeTime;
|
||||||
|
|
||||||
totalPath += neededMovement;
|
totalPath += neededMovement;
|
||||||
currentCursorPosition = Vector2.Lerp(currentCursorPosition, ballPosition, neededMovement / distanceToCursor);
|
currentCursorPosition = Vector2.Lerp(currentCursorPosition, ballPosition, neededMovement / distanceToCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return peakVelocity * scalingFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector2 getEndCursorPosition(OsuHitObject hitObject)
|
private Vector2 getEndCursorPosition(OsuHitObject hitObject)
|
||||||
|
Loading…
Reference in New Issue
Block a user