diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModNoRelease.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModNoRelease.cs
index 82534ee019..f6e79114de 100644
--- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModNoRelease.cs
+++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModNoRelease.cs
@@ -273,10 +273,10 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods
///
/// -----[ ]--------------
- /// xo
+ /// xo
///
[Test]
- public void TestPressAndReleaseJustAfterTailWithCloseByHead()
+ public void TestPressAndReleaseAfterTailWithCloseByHead()
{
const int duration = 30;
@@ -301,11 +301,11 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods
performTest(new List
{
- new ManiaReplayFrame(time_head + duration + 20, ManiaAction.Key1),
- new ManiaReplayFrame(time_head + duration + 30),
+ new ManiaReplayFrame(time_head + duration + 60, ManiaAction.Key1),
+ new ManiaReplayFrame(time_head + duration + 70),
}, beatmap);
- assertHeadJudgement(HitResult.Good);
+ assertHeadJudgement(HitResult.Ok);
assertTailJudgement(HitResult.Perfect);
}
diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModNoRelease.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModNoRelease.cs
index f370ef15bd..8cb2e821e6 100644
--- a/osu.Game.Rulesets.Mania/Mods/ManiaModNoRelease.cs
+++ b/osu.Game.Rulesets.Mania/Mods/ManiaModNoRelease.cs
@@ -1,15 +1,21 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System.Linq;
+using System.Threading;
using osu.Framework.Localisation;
+using osu.Game.Beatmaps;
+using osu.Game.Rulesets.Mania.Beatmaps;
+using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables;
+using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Mods;
-using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
+using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Mania.Mods
{
- public class ManiaModNoRelease : Mod, IApplicableToDrawableHitObject
+ public partial class ManiaModNoRelease : Mod, IApplicableAfterBeatmapConversion, IApplicableToDrawableRuleset
{
public override string Name => "No Release";
@@ -21,14 +27,80 @@ namespace osu.Game.Rulesets.Mania.Mods
public override ModType Type => ModType.DifficultyReduction;
- public void ApplyToDrawableHitObject(DrawableHitObject drawable)
+ public void ApplyToBeatmap(IBeatmap beatmap)
{
- if (drawable is DrawableHoldNote hold)
+ var maniaBeatmap = (ManiaBeatmap)beatmap;
+ var hitObjects = maniaBeatmap.HitObjects.Select(obj =>
{
- hold.HitObjectApplied += dho =>
+ if (obj is HoldNote hold)
+ return new NoReleaseHoldNote(hold);
+
+ return obj;
+ }).ToList();
+
+ maniaBeatmap.HitObjects = hitObjects;
+ }
+
+ public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset)
+ {
+ var maniaRuleset = (DrawableManiaRuleset)drawableRuleset;
+
+ foreach (var stage in maniaRuleset.Playfield.Stages)
+ {
+ foreach (var column in stage.Columns)
{
- ((DrawableHoldNote)dho).Tail.LateReleaseResult = HitResult.Perfect;
- };
+ column.RegisterPool(10, 50);
+ }
+ }
+ }
+
+ private partial class NoReleaseDrawableHoldNoteTail : DrawableHoldNoteTail
+ {
+ protected override void CheckForResult(bool userTriggered, double timeOffset)
+ {
+ // apply perfect once the tail is reached
+ if (HoldNote.HoldStartTime != null && timeOffset >= 0)
+ ApplyResult(GetCappedResult(HitResult.Perfect));
+ else
+ base.CheckForResult(userTriggered, timeOffset);
+ }
+ }
+
+ private class NoReleaseTailNote : TailNote
+ {
+ }
+
+ private class NoReleaseHoldNote : HoldNote
+ {
+ public NoReleaseHoldNote(HoldNote hold)
+ {
+ StartTime = hold.StartTime;
+ Duration = hold.Duration;
+ Column = hold.Column;
+ NodeSamples = hold.NodeSamples;
+ }
+
+ protected override void CreateNestedHitObjects(CancellationToken cancellationToken)
+ {
+ AddNested(Head = new HeadNote
+ {
+ StartTime = StartTime,
+ Column = Column,
+ Samples = GetNodeSamples(0),
+ });
+
+ AddNested(Tail = new NoReleaseTailNote
+ {
+ StartTime = EndTime,
+ Column = Column,
+ Samples = GetNodeSamples((NodeSamples?.Count - 1) ?? 1),
+ });
+
+ AddNested(Body = new HoldNoteBody
+ {
+ StartTime = StartTime,
+ Column = Column
+ });
}
}
}
diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs
index eb1637b0ea..79002b3819 100644
--- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs
+++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs
@@ -3,7 +3,6 @@
#nullable disable
-using System.Diagnostics;
using osu.Framework.Graphics;
using osu.Framework.Input.Events;
using osu.Game.Rulesets.Scoring;
@@ -19,11 +18,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
protected internal DrawableHoldNote HoldNote => (DrawableHoldNote)ParentHitObject;
- ///
- /// The minimum uncapped result for a late release.
- ///
- public HitResult LateReleaseResult { get; set; } = HitResult.Miss;
-
public DrawableHoldNoteTail()
: this(null)
{
@@ -38,23 +32,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
public void UpdateResult() => base.UpdateResult(true);
- protected override void CheckForResult(bool userTriggered, double timeOffset)
- {
- Debug.Assert(HitObject.HitWindows != null);
-
+ protected override void CheckForResult(bool userTriggered, double timeOffset) =>
// Factor in the release 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);
- }
- }
+ base.CheckForResult(userTriggered, timeOffset / TailNote.RELEASE_WINDOW_LENIENCE);
protected override HitResult GetCappedResult(HitResult result)
{
diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs
index 3f930a310b..6be0ee2d6b 100644
--- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs
+++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs
@@ -72,18 +72,18 @@ namespace osu.Game.Rulesets.Mania.Objects
///
/// The head note of the hold.
///
- public HeadNote Head { get; private set; }
+ public HeadNote Head { get; protected set; }
///
/// The tail note of the hold.
///
- public TailNote Tail { get; private set; }
+ public TailNote Tail { get; protected set; }
///
/// The body of the hold.
/// This is an invisible and silent object that tracks the holding state of the .
///
- public HoldNoteBody Body { get; private set; }
+ public HoldNoteBody Body { get; protected set; }
public override double MaximumJudgementOffset => Tail.MaximumJudgementOffset;