Skip to content

Commit

Permalink
Merge pull request ppy#26036 from smoogipoo/fix-perfect-mod-special-j…
Browse files Browse the repository at this point in the history
…udgements

Fix perfect mod not failing with special judgements
  • Loading branch information
peppy authored Dec 22, 2023
2 parents a7326e3 + 5703546 commit 7e09164
Show file tree
Hide file tree
Showing 10 changed files with 269 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace osu.Game.Rulesets.Catch.Tests.Mods
{
public partial class TestSceneCatchModPerfect : ModPerfectTestScene
public partial class TestSceneCatchModPerfect : ModFailConditionTestScene
{
protected override Ruleset CreatePlayerRuleset() => new CatchRuleset();

Expand Down
54 changes: 53 additions & 1 deletion osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
// 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
{
public partial class TestSceneManiaModPerfect : ModPerfectTestScene
public partial class TestSceneManiaModPerfect : ModFailConditionTestScene
{
protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset();

Expand All @@ -24,5 +29,52 @@ public TestSceneManiaModPerfect()
[TestCase(false)]
[TestCase(true)]
public void TestHoldNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new HoldNote { StartTime = 1000, EndTime = 3000 }), shouldMiss);

[Test]
public void TestGreatHit() => CreateModTest(new ModTestData
{
Mod = new ManiaModPerfect(),
PassCondition = () => ((ModFailConditionTestPlayer)Player).CheckFailed(false),
Autoplay = false,
Beatmap = new Beatmap
{
HitObjects = new List<HitObject>
{
new Note
{
StartTime = 1000,
}
},
},
ReplayFrames = new List<ReplayFrame>
{
new ManiaReplayFrame(1020, ManiaAction.Key1),
new ManiaReplayFrame(2000)
}
});

[Test]
public void TestBreakOnHoldNote() => CreateModTest(new ModTestData
{
Mod = new ManiaModPerfect(),
PassCondition = () => ((ModFailConditionTestPlayer)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)
}
});
}
}
72 changes: 72 additions & 0 deletions osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModSuddenDeath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// 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
{
public partial class TestSceneManiaModSuddenDeath : ModFailConditionTestScene
{
protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset();

public TestSceneManiaModSuddenDeath()
: base(new ManiaModSuddenDeath())
{
}

[Test]
public void TestGreatHit() => CreateModTest(new ModTestData
{
Mod = new ManiaModSuddenDeath(),
PassCondition = () => ((ModFailConditionTestPlayer)Player).CheckFailed(false),
Autoplay = false,
Beatmap = new Beatmap
{
HitObjects = new List<HitObject>
{
new Note
{
StartTime = 1000,
}
},
},
ReplayFrames = new List<ReplayFrame>
{
new ManiaReplayFrame(1020, ManiaAction.Key1),
new ManiaReplayFrame(2000)
}
});

[Test]
public void TestBreakOnHoldNote() => CreateModTest(new ModTestData
{
Mod = new ManiaModSuddenDeath(),
PassCondition = () => ((ModFailConditionTestPlayer)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)
}
});
}
}
15 changes: 15 additions & 0 deletions osu.Game.Rulesets.Mania/Mods/ManiaModPerfect.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
// 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.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;

namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModPerfect : ModPerfect
{
protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result)
{
if (!isRelevantResult(result.Judgement.MinResult) && !isRelevantResult(result.Judgement.MaxResult) && !isRelevantResult(result.Type))
return false;

// Mania allows imperfect "Great" hits without failing.
if (result.Judgement.MaxResult == HitResult.Perfect)
return result.Type < HitResult.Great;

return result.Type != result.Judgement.MaxResult;
}

private bool isRelevantResult(HitResult result) => result.AffectsAccuracy() || result.AffectsCombo();
}
}
31 changes: 30 additions & 1 deletion osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModPerfect.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
// 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;

namespace osu.Game.Rulesets.Osu.Tests.Mods
{
public partial class TestSceneOsuModPerfect : ModPerfectTestScene
public partial class TestSceneOsuModPerfect : ModFailConditionTestScene
{
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();

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 = () => ((ModFailConditionTestPlayer)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)),
}
});
}
}
77 changes: 77 additions & 0 deletions osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSuddenDeath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// 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;

namespace osu.Game.Rulesets.Osu.Tests.Mods
{
public partial class TestSceneOsuModSuddenDeath : ModFailConditionTestScene
{
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();

public TestSceneOsuModSuddenDeath()
: base(new OsuModSuddenDeath())
{
}

[Test]
public void TestMissTail() => CreateModTest(new ModTestData
{
Mod = new OsuModSuddenDeath(),
PassCondition = () => ((ModFailConditionTestPlayer)Player).CheckFailed(false),
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)),
}
});

[Test]
public void TestMissTick() => CreateModTest(new ModTestData
{
Mod = new OsuModSuddenDeath(),
PassCondition = () => ((ModFailConditionTestPlayer)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(200, 0), })
},
},
},
ReplayFrames = new List<ReplayFrame>
{
new OsuReplayFrame(1000, new Vector2(256, 192), OsuAction.LeftButton),
new OsuReplayFrame(1001, new Vector2(256, 192)),
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace osu.Game.Rulesets.Taiko.Tests.Mods
{
public partial class TestSceneTaikoModPerfect : ModPerfectTestScene
public partial class TestSceneTaikoModPerfect : ModFailConditionTestScene
{
protected override Ruleset CreatePlayerRuleset() => new TestTaikoRuleset();

Expand Down
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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

namespace osu.Game.Tests.Visual
{
public abstract partial class ModPerfectTestScene : ModTestScene
public abstract partial class ModFailConditionTestScene : ModTestScene
{
private readonly ModPerfect mod;
private readonly ModFailCondition mod;

protected ModPerfectTestScene(ModPerfect mod)
protected ModFailConditionTestScene(ModFailCondition mod)
{
this.mod = mod;
}
Expand All @@ -26,15 +26,15 @@ protected void CreateHitObjectTest(HitObjectTestData testData, bool shouldMiss)
HitObjects = { testData.HitObject }
},
Autoplay = !shouldMiss,
PassCondition = () => ((PerfectModTestPlayer)Player).CheckFailed(shouldMiss && testData.FailOnMiss)
PassCondition = () => ((ModFailConditionTestPlayer)Player).CheckFailed(shouldMiss && testData.FailOnMiss)
});

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

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

Expand Down
Loading

0 comments on commit 7e09164

Please sign in to comment.