Skip to content

Fix perfect mod not failing with special judgements #26036

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
// 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.Collections.Generic;
using NUnit.Framework;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.Mods;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Replays;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Replays;
using osu.Game.Tests.Visual;

namespace osu.Game.Rulesets.Mania.Tests.Mods
Expand All @@ -24,5 +29,29 @@ public TestSceneManiaModPerfect()
[TestCase(false)]
[TestCase(true)]
public void TestHoldNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new HoldNote { StartTime = 1000, EndTime = 3000 }), shouldMiss);

[Test]
public void TestBreakOnHoldNote() => CreateModTest(new ModTestData
{
Mod = new ManiaModPerfect(),
PassCondition = () => ((PerfectModTestPlayer)Player).CheckFailed(true) && Player.Results.Count == 2,
Autoplay = false,
Beatmap = new Beatmap
{
HitObjects = new List<HitObject>
{
new HoldNote
{
StartTime = 1000,
EndTime = 3000,
},
},
},
ReplayFrames = new List<ReplayFrame>
{
new ManiaReplayFrame(1000, ManiaAction.Key1),
new ManiaReplayFrame(2000)
}
});
}
}
29 changes: 29 additions & 0 deletions osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModPerfect.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
// 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.Collections.Generic;
using NUnit.Framework;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Replays;
using osu.Game.Rulesets.Replays;
using osu.Game.Tests.Visual;
using osuTK;

Expand Down Expand Up @@ -50,5 +54,30 @@ public void TestSpinner(bool shouldMiss)

CreateHitObjectTest(new HitObjectTestData(spinner), shouldMiss);
}

[Test]
public void TestMissSliderTail() => CreateModTest(new ModTestData
{
Mod = new OsuModPerfect(),
PassCondition = () => ((PerfectModTestPlayer)Player).CheckFailed(true),
Autoplay = false,
Beatmap = new Beatmap
{
HitObjects = new List<HitObject>
{
new Slider
{
Position = new Vector2(256, 192),
StartTime = 1000,
Path = new SliderPath(PathType.LINEAR, new[] { Vector2.Zero, new Vector2(100, 0), })
},
},
},
ReplayFrames = new List<ReplayFrame>
{
new OsuReplayFrame(1000, new Vector2(256, 192), OsuAction.LeftButton),
new OsuReplayFrame(1001, new Vector2(256, 192)),
}
});
}
}
4 changes: 3 additions & 1 deletion osu.Game/Rulesets/Mods/ModPerfect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ protected ModPerfect()
}

protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result)
=> result.Type.AffectsAccuracy()
=> (isRelevantResult(result.Judgement.MinResult) || isRelevantResult(result.Judgement.MaxResult) || isRelevantResult(result.Type))
&& result.Type != result.Judgement.MaxResult;

private bool isRelevantResult(HitResult result) => result.AffectsAccuracy() || result.AffectsCombo();
}
}
2 changes: 1 addition & 1 deletion osu.Game/Rulesets/Mods/ModSuddenDeath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public abstract class ModSuddenDeath : ModFailCondition
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModPerfect)).ToArray();

protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result)
=> result.Type.AffectsCombo()
=> (result.Judgement.MinResult.AffectsCombo() || result.Judgement.MaxResult.AffectsCombo() || result.Type.AffectsCombo())
&& !result.IsHit;
}
}
8 changes: 4 additions & 4 deletions osu.Game/Tests/Visual/ModPerfectTestScene.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ protected void CreateHitObjectTest(HitObjectTestData testData, bool shouldMiss)
PassCondition = () => ((PerfectModTestPlayer)Player).CheckFailed(shouldMiss && testData.FailOnMiss)
});

protected override TestPlayer CreateModPlayer(Ruleset ruleset) => new PerfectModTestPlayer();
protected override TestPlayer CreateModPlayer(Ruleset ruleset) => new PerfectModTestPlayer(CurrentTestData, AllowFail);

private partial class PerfectModTestPlayer : TestPlayer
protected partial class PerfectModTestPlayer : ModTestPlayer
{
public PerfectModTestPlayer()
: base(showResults: false)
public PerfectModTestPlayer(ModTestData data, bool allowFail)
: base(data, allowFail)
{
}

Expand Down
18 changes: 9 additions & 9 deletions osu.Game/Tests/Visual/ModTestScene.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,43 @@ public abstract partial class ModTestScene : PlayerTestScene
{
protected sealed override bool HasCustomSteps => true;

private ModTestData currentTestData;
protected ModTestData CurrentTestData { get; private set; }

protected void CreateModTest(ModTestData testData) => CreateTest(() =>
{
AddStep("set test data", () => currentTestData = testData);
AddStep("set test data", () => CurrentTestData = testData);
});

public override void TearDownSteps()
{
AddUntilStep("test passed", () =>
{
if (currentTestData == null)
if (CurrentTestData == null)
return true;

return currentTestData.PassCondition?.Invoke() ?? false;
return CurrentTestData.PassCondition?.Invoke() ?? false;
});

base.TearDownSteps();
}

protected sealed override IBeatmap CreateBeatmap(RulesetInfo ruleset) => currentTestData?.Beatmap ?? base.CreateBeatmap(ruleset);
protected sealed override IBeatmap CreateBeatmap(RulesetInfo ruleset) => CurrentTestData?.Beatmap ?? base.CreateBeatmap(ruleset);

protected sealed override TestPlayer CreatePlayer(Ruleset ruleset)
{
var mods = new List<Mod>(SelectedMods.Value);

if (currentTestData.Mods != null)
mods.AddRange(currentTestData.Mods);
if (currentTestData.Autoplay)
if (CurrentTestData.Mods != null)
mods.AddRange(CurrentTestData.Mods);
if (CurrentTestData.Autoplay)
mods.Add(ruleset.GetAutoplayMod());

SelectedMods.Value = mods;

return CreateModPlayer(ruleset);
}

protected virtual TestPlayer CreateModPlayer(Ruleset ruleset) => new ModTestPlayer(currentTestData, AllowFail);
protected virtual TestPlayer CreateModPlayer(Ruleset ruleset) => new ModTestPlayer(CurrentTestData, AllowFail);

protected partial class ModTestPlayer : TestPlayer
{
Expand Down