1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-16 05:32:35 +08:00
Files
osu-lazer/osu.Game/Rulesets/Scoring/DefaultHitWindows.cs
T
Bartłomiej Dach 8b542e5442 Refactor hit windows class structure to reduce rigidity
This change pulls back a significant degree of overspecialisation and
rigidity in the class structure of `HitWindows` to make subsequent
changes to hit windows, whose purpose is to improve replay playback
accuracy, possible to do cleanly.

Notably:

- `HitWindows` is full abstract now. In a few use cases, and as a
  reference for ruleset implementors, `DefaultHitWindows` is provided as
  a separate class instead.

  This fixes the weirdness wherein `HitWindows` always declared 6 fields
  for result types but some of them would never be set to a non-zero
  value or read.

- `HitWindow.GetRanges()` is deleted because it is overspecialised and
  prevents being able to adjust hitwindows by ±0.5ms cleanly which will
  be required later.

  The fallout of this is that the assertion that used `GetRanges()` in
  the `HitWindows` ctor must use something else now, and the closest
  thing to it was `GetAllAvailableWindows()`, which didn't return
  the miss window - so I made it return the miss window and fixed the
  one consumer that didn't want it (bar hit error meter) to skip it.

- Diff also contains some clean-up around `DifficultyRange` to unify
  handling of it.
2025-06-25 08:40:12 +02:00

67 lines
2.5 KiB
C#

// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Game.Beatmaps;
namespace osu.Game.Rulesets.Scoring
{
/// <summary>
/// An example implementation of <see cref="HitWindows"/>.
/// Not meaningfully used, provided mostly as a reference to ruleset implementors.
/// </summary>
public class DefaultHitWindows : HitWindows
{
private static readonly DifficultyRange perfect_window_range = new DifficultyRange(22.4D, 19.4D, 13.9D);
private static readonly DifficultyRange great_window_range = new DifficultyRange(64, 49, 34);
private static readonly DifficultyRange good_window_range = new DifficultyRange(97, 82, 67);
private static readonly DifficultyRange ok_window_range = new DifficultyRange(127, 112, 97);
private static readonly DifficultyRange meh_window_range = new DifficultyRange(151, 136, 121);
private static readonly DifficultyRange miss_window_range = new DifficultyRange(188, 173, 158);
private double perfect;
private double great;
private double good;
private double ok;
private double meh;
private double miss;
public override void SetDifficulty(double difficulty)
{
perfect = IBeatmapDifficultyInfo.DifficultyRange(difficulty, perfect_window_range);
great = IBeatmapDifficultyInfo.DifficultyRange(difficulty, great_window_range);
good = IBeatmapDifficultyInfo.DifficultyRange(difficulty, good_window_range);
ok = IBeatmapDifficultyInfo.DifficultyRange(difficulty, ok_window_range);
meh = IBeatmapDifficultyInfo.DifficultyRange(difficulty, meh_window_range);
miss = IBeatmapDifficultyInfo.DifficultyRange(difficulty, miss_window_range);
}
public override double WindowFor(HitResult result)
{
switch (result)
{
case HitResult.Perfect:
return perfect;
case HitResult.Great:
return great;
case HitResult.Good:
return good;
case HitResult.Ok:
return ok;
case HitResult.Meh:
return meh;
case HitResult.Miss:
return miss;
default:
throw new ArgumentOutOfRangeException(nameof(result), result, null);
}
}
}
}