Initial implemention of the No Release mod

This commit adds a new osu!mania mod No Release that relaxes tail
judgements. The current implementation automatically awards Perfect
(or Meh if the hold note is broken midway) for a hold note tail at
the end of its Perfect window, as long as it is held by then.

Tests are pending for the next commit.
This commit is contained in:
Nathan Du 2024-06-28 19:43:45 +08:00
parent 007bd3973a
commit 960d552dc1
3 changed files with 58 additions and 2 deletions

View File

@ -241,6 +241,7 @@ namespace osu.Game.Rulesets.Mania
new ManiaModEasy(),
new ManiaModNoFail(),
new MultiMod(new ManiaModHalfTime(), new ManiaModDaycore()),
new ManiaModNoRelease(),
};
case ModType.DifficultyIncrease:

View File

@ -0,0 +1,35 @@
// 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 osu.Framework.Localisation;
using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModNoRelease : Mod, IApplicableToDrawableHitObject
{
public override string Name => "No Release";
public override string Acronym => "NR";
public override LocalisableString Description => "No more timing the end of hold notes.";
public override double ScoreMultiplier => 0.9;
public override ModType Type => ModType.DifficultyReduction;
public void ApplyToDrawableHitObject(DrawableHitObject drawable)
{
if (drawable is DrawableHoldNote hold)
{
hold.HitObjectApplied += dho =>
{
((DrawableHoldNote)dho).Tail.LateReleaseResult = HitResult.Perfect;
};
}
}
}
}

View File

@ -3,6 +3,7 @@
#nullable disable
using System.Diagnostics;
using osu.Framework.Graphics;
using osu.Framework.Input.Events;
using osu.Game.Rulesets.Scoring;
@ -18,6 +19,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
protected internal DrawableHoldNote HoldNote => (DrawableHoldNote)ParentHitObject;
/// <summary>
/// The minimum uncapped result for a late release.
/// </summary>
public HitResult LateReleaseResult { get; set; } = HitResult.Miss;
public DrawableHoldNoteTail()
: this(null)
{
@ -32,9 +38,23 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
public void UpdateResult() => base.UpdateResult(true);
protected override void CheckForResult(bool userTriggered, double timeOffset) =>
protected override void CheckForResult(bool userTriggered, double timeOffset)
{
Debug.Assert(HitObject.HitWindows != null);
// Factor in the release lenience
base.CheckForResult(userTriggered, timeOffset / TailNote.RELEASE_WINDOW_LENIENCE);
double scaledTimeOffset = timeOffset / TailNote.RELEASE_WINDOW_LENIENCE;
// Check for late release
if (HoldNote.HoldStartTime != null && scaledTimeOffset > HitObject.HitWindows.WindowFor(LateReleaseResult))
{
ApplyResult(GetCappedResult(LateReleaseResult));
}
else
{
base.CheckForResult(userTriggered, scaledTimeOffset);
}
}
protected override HitResult GetCappedResult(HitResult result)
{