Retrieve great hit window from the hit object

This commit is contained in:
apollo-dw 2022-09-06 17:10:32 +01:00
parent 604fc0fb97
commit b5779508d0
5 changed files with 29 additions and 18 deletions

View File

@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
/// <summary>
/// Calculates a rhythm multiplier for the difficulty of the tap associated with historic data of the current <see cref="OsuDifficultyHitObject"/>.
/// </summary>
public static double EvaluateDifficultyOf(DifficultyHitObject current, double greatWindow)
public static double EvaluateDifficultyOf(DifficultyHitObject current)
{
if (current.BaseObject is Spinner)
return 0;
@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
double lastDelta = lastObj.StrainTime;
double currRatio = 1.0 + 6.0 * Math.Min(0.5, Math.Pow(Math.Sin(Math.PI / (Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta))), 2)); // fancy function to calculate rhythmbonuses.
double windowPenalty = Math.Min(1, Math.Max(0, Math.Abs(prevDelta - currDelta) - greatWindow * 0.6) / (greatWindow * 0.6));
double windowPenalty = Math.Min(1, Math.Max(0, Math.Abs(prevDelta - currDelta) - currObj.HitWindowGreat * 0.6) / (currObj.HitWindowGreat * 0.6));
windowPenalty = Math.Min(1, windowPenalty);

View File

@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
/// <item><description>and how easily they can be cheesed.</description></item>
/// </list>
/// </summary>
public static double EvaluateDifficultyOf(DifficultyHitObject current, double greatWindow)
public static double EvaluateDifficultyOf(DifficultyHitObject current)
{
if (current.BaseObject is Spinner)
return 0;
@ -35,7 +35,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
var osuNextObj = (OsuDifficultyHitObject)current.Next(0);
double strainTime = osuCurrObj.StrainTime;
double greatWindowFull = greatWindow * 2;
double doubletapness = 1;
// Nerf doubletappable doubles.
@ -45,13 +44,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
double nextDeltaTime = Math.Max(1, osuNextObj.DeltaTime);
double deltaDifference = Math.Abs(nextDeltaTime - currDeltaTime);
double speedRatio = currDeltaTime / Math.Max(currDeltaTime, deltaDifference);
double windowRatio = Math.Pow(Math.Min(1, currDeltaTime / greatWindowFull), 2);
double windowRatio = Math.Pow(Math.Min(1, currDeltaTime / osuCurrObj.HitWindowGreat), 2);
doubletapness = Math.Pow(speedRatio, 1 - windowRatio);
}
// Cap deltatime to the OD 300 hitwindow.
// 0.93 is derived from making sure 260bpm OD8 streams aren't nerfed harshly, whilst 0.92 limits the effect of the cap.
strainTime /= Math.Clamp((strainTime / greatWindowFull) / 0.93, 0.92, 1);
strainTime /= Math.Clamp((strainTime / osuCurrObj.HitWindowGreat) / 0.93, 0.92, 1);
// derive speedBonus for calculation
double speedBonus = 1.0;

View File

@ -23,7 +23,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty
public class OsuDifficultyCalculator : DifficultyCalculator
{
private const double difficulty_multiplier = 0.0675;
private double hitWindowGreat;
public override int Version => 20220902;
@ -76,6 +75,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty
int sliderCount = beatmap.HitObjects.Count(h => h is Slider);
int spinnerCount = beatmap.HitObjects.Count(h => h is Spinner);
HitWindows hitWindows = new OsuHitWindows();
hitWindows.SetDifficulty(beatmap.Difficulty.OverallDifficulty);
double hitWindowGreat = hitWindows.WindowFor(HitResult.Great) / clockRate;
return new OsuDifficultyAttributes
{
StarRating = starRating,
@ -112,16 +116,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
{
HitWindows hitWindows = new OsuHitWindows();
hitWindows.SetDifficulty(beatmap.Difficulty.OverallDifficulty);
hitWindowGreat = hitWindows.WindowFor(HitResult.Great) / clockRate;
return new Skill[]
{
new Aim(mods, true),
new Aim(mods, false),
new Speed(mods, hitWindowGreat),
new Speed(mods),
new Flashlight(mods)
};
}

View File

@ -9,6 +9,7 @@ using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Scoring;
using osuTK;
namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
@ -78,6 +79,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
/// </summary>
public double? Angle { get; private set; }
/// <summary>
/// Retrieves the full hit window for a Great <see cref="HitResult"/>.
/// </summary>
public double HitWindowGreat { get; private set; }
private readonly OsuHitObject lastLastObject;
private readonly OsuHitObject lastObject;
@ -90,6 +96,15 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
// Capped to 25ms to prevent difficulty calculation breaking from simultaneous objects.
StrainTime = Math.Max(DeltaTime, min_delta_time);
if (BaseObject is Slider sliderObject)
{
HitWindowGreat = 2 * sliderObject.HeadCircle.HitWindows.WindowFor(HitResult.Great) / clockRate;
}
else
{
HitWindowGreat = 2 * BaseObject.HitWindows.WindowFor(HitResult.Great) / clockRate;
}
setDistances(clockRate);
}

View File

@ -26,14 +26,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
protected override int ReducedSectionCount => 5;
protected override double DifficultyMultiplier => 1.04;
private readonly double greatWindow;
private readonly List<double> objectStrains = new List<double>();
public Speed(Mod[] mods, double hitWindowGreat)
public Speed(Mod[] mods)
: base(mods)
{
greatWindow = hitWindowGreat;
}
private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000);
@ -43,9 +41,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
protected override double StrainValueAt(DifficultyHitObject current)
{
currentStrain *= strainDecay(((OsuDifficultyHitObject)current).StrainTime);
currentStrain += SpeedEvaluator.EvaluateDifficultyOf(current, greatWindow) * skillMultiplier;
currentStrain += SpeedEvaluator.EvaluateDifficultyOf(current) * skillMultiplier;
currentRhythm = RhythmEvaluator.EvaluateDifficultyOf(current, greatWindow);
currentRhythm = RhythmEvaluator.EvaluateDifficultyOf(current);
double totalStrain = currentStrain * currentRhythm;