osu/osu.Game/Rulesets/Objects/HitWindows.cs

213 lines
7.1 KiB
C#
Raw Normal View History

2018-01-05 11:21:19 +00:00
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
2017-05-03 03:53:45 +00:00
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
2017-07-26 04:22:46 +00:00
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Scoring;
2017-05-03 03:53:45 +00:00
2018-02-02 08:52:55 +00:00
namespace osu.Game.Rulesets.Objects
2017-05-03 03:53:45 +00:00
{
public class HitWindows
{
#region Constants
/// <summary>
/// PERFECT hit window at OD = 10.
/// </summary>
private const double perfect_min = 27.8;
/// <summary>
/// PERFECT hit window at OD = 5.
/// </summary>
private const double perfect_mid = 38.8;
/// <summary>
/// PERFECT hit window at OD = 0.
/// </summary>
private const double perfect_max = 44.8;
/// <summary>
/// GREAT hit window at OD = 10.
/// </summary>
private const double great_min = 68;
/// <summary>
/// GREAT hit window at OD = 5.
/// </summary>
private const double great_mid = 98;
/// <summary>
/// GREAT hit window at OD = 0.
/// </summary>
private const double great_max = 128;
/// <summary>
/// GOOD hit window at OD = 10.
/// </summary>
private const double good_min = 134;
/// <summary>
/// GOOD hit window at OD = 5.
/// </summary>
private const double good_mid = 164;
/// <summary>
/// GOOD hit window at OD = 0.
/// </summary>
private const double good_max = 194;
/// <summary>
/// OK hit window at OD = 10.
/// </summary>
private const double ok_min = 194;
/// <summary>
/// OK hit window at OD = 5.
/// </summary>
private const double ok_mid = 224;
/// <summary>
/// OK hit window at OD = 0.
/// </summary>
private const double ok_max = 254;
/// <summary>
2018-02-02 09:56:44 +00:00
/// MEH hit window at OD = 10.
2017-05-03 03:53:45 +00:00
/// </summary>
2018-02-02 09:56:44 +00:00
private const double meh_min = 242;
2017-05-03 03:53:45 +00:00
/// <summary>
2018-02-02 09:56:44 +00:00
/// MEH hit window at OD = 5.
2017-05-03 03:53:45 +00:00
/// </summary>
2018-02-02 09:56:44 +00:00
private const double meh_mid = 272;
2017-05-03 03:53:45 +00:00
/// <summary>
2018-02-02 09:56:44 +00:00
/// MEH hit window at OD = 0.
2017-05-03 03:53:45 +00:00
/// </summary>
2018-02-02 09:56:44 +00:00
private const double meh_max = 302;
2017-05-03 03:53:45 +00:00
/// <summary>
/// MISS hit window at OD = 10.
/// </summary>
private const double miss_min = 316;
/// <summary>
/// MISS hit window at OD = 5.
/// </summary>
private const double miss_mid = 346;
/// <summary>
/// MISS hit window at OD = 0.
/// </summary>
private const double miss_max = 376;
#endregion
/// <summary>
/// Hit window for a PERFECT hit.
/// </summary>
public double Perfect = perfect_mid;
2017-05-09 11:55:20 +00:00
2017-05-03 03:53:45 +00:00
/// <summary>
/// Hit window for a GREAT hit.
/// </summary>
public double Great = great_mid;
/// <summary>
/// Hit window for a GOOD hit.
/// </summary>
public double Good = good_mid;
/// <summary>
/// Hit window for an OK hit.
/// </summary>
public double Ok = ok_mid;
/// <summary>
2018-02-02 09:56:44 +00:00
/// Hit window for a MEH hit.
2017-05-03 03:53:45 +00:00
/// </summary>
2018-02-02 09:56:44 +00:00
public double Meh = meh_mid;
2017-05-03 03:53:45 +00:00
/// <summary>
/// Hit window for a MISS hit.
/// </summary>
public double Miss = miss_mid;
2017-05-10 08:29:54 +00:00
/// <summary>
/// Constructs default hit windows.
/// </summary>
2017-05-03 03:53:45 +00:00
public HitWindows()
{
}
2017-05-10 08:29:54 +00:00
/// <summary>
/// Constructs hit windows by fitting a parameter to a 2-part piecewise linear function for each hit window.
/// </summary>
/// <param name="difficulty">The parameter.</param>
2017-05-03 03:53:45 +00:00
public HitWindows(double difficulty)
{
Perfect = BeatmapDifficulty.DifficultyRange(difficulty, perfect_max, perfect_mid, perfect_min);
Great = BeatmapDifficulty.DifficultyRange(difficulty, great_max, great_mid, great_min);
Good = BeatmapDifficulty.DifficultyRange(difficulty, good_max, good_mid, good_min);
Ok = BeatmapDifficulty.DifficultyRange(difficulty, ok_max, ok_mid, ok_min);
2018-02-02 09:56:44 +00:00
Meh = BeatmapDifficulty.DifficultyRange(difficulty, meh_max, meh_mid, meh_min);
2017-05-03 03:53:45 +00:00
Miss = BeatmapDifficulty.DifficultyRange(difficulty, miss_max, miss_mid, miss_min);
}
/// <summary>
/// Retrieves the hit result for a time offset.
/// </summary>
/// <param name="timeOffset">The time offset. This should always be a positive value indicating the absolute time offset.</param>
/// <returns>The hit result, or null if <paramref name="timeOffset"/> doesn't result in a judgement.</returns>
public HitResult? ResultFor(double timeOffset)
{
timeOffset = Math.Abs(timeOffset);
if (timeOffset <= Perfect / 2)
2017-09-05 10:44:59 +00:00
return HitResult.Perfect;
if (timeOffset <= Great / 2)
2017-09-05 10:44:59 +00:00
return HitResult.Great;
if (timeOffset <= Good / 2)
2017-09-05 10:44:59 +00:00
return HitResult.Good;
if (timeOffset <= Ok / 2)
2017-09-05 10:44:59 +00:00
return HitResult.Ok;
2018-02-02 09:56:44 +00:00
if (timeOffset <= Meh / 2)
2017-09-05 10:44:59 +00:00
return HitResult.Meh;
if (timeOffset <= Miss / 2)
return HitResult.Miss;
return null;
}
2017-05-10 08:29:54 +00:00
/// <summary>
/// Given a time offset, whether the <see cref="HitObject"/> can ever be hit in the future.
2018-02-02 09:56:44 +00:00
/// This happens if <paramref name="timeOffset"/> > <see cref="Meh"/>.
/// </summary>
/// <param name="timeOffset">The time offset.</param>
/// <returns>Whether the <see cref="HitObject"/> can be hit at any point in the future from this time offset.</returns>
2018-02-02 09:56:44 +00:00
public bool CanBeHit(double timeOffset) => timeOffset <= Meh / 2;
/// <summary>
/// Multiplies all hit windows by a value.
2017-05-10 08:29:54 +00:00
/// </summary>
/// <param name="windows">The hit windows to multiply.</param>
2017-05-10 08:29:54 +00:00
/// <param name="value">The value to multiply each hit window by.</param>
2017-05-03 03:53:45 +00:00
public static HitWindows operator *(HitWindows windows, double value)
{
windows.Perfect *= value;
windows.Great *= value;
windows.Good *= value;
windows.Ok *= value;
2018-02-02 09:56:44 +00:00
windows.Meh *= value;
windows.Miss *= value;
return windows;
2017-05-03 03:53:45 +00:00
}
2017-05-10 08:29:54 +00:00
/// <summary>
/// Divides all hit windows by a value.
2017-05-10 08:29:54 +00:00
/// </summary>
/// <param name="windows">The hit windows to divide.</param>
2017-05-10 08:29:54 +00:00
/// <param name="value">The value to divide each hit window by.</param>
2017-05-03 03:53:45 +00:00
public static HitWindows operator /(HitWindows windows, double value)
{
windows.Perfect /= value;
windows.Great /= value;
windows.Good /= value;
windows.Ok /= value;
2018-02-02 09:56:44 +00:00
windows.Meh /= value;
windows.Miss /= value;
return windows;
2017-05-03 03:53:45 +00:00
}
}
}