From dde0756bed9702c95c918af247e9339bc913bb48 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Tue, 24 May 2022 10:23:44 -0400 Subject: [PATCH 01/15] add accuracy challenge mod --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 1 + osu.Game.Rulesets.Mania/ManiaRuleset.cs | 1 + osu.Game.Rulesets.Osu/OsuRuleset.cs | 3 +- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 1 + .../Rulesets/Mods/ModAccuracyChallenge.cs | 59 +++++++++++++++++++ .../Rulesets/Mods/ModEasyWithExtraLives.cs | 3 + osu.Game/Rulesets/Mods/ModPerfect.cs | 2 +- 7 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 80b9436b2c..bcce28adb2 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -109,6 +109,7 @@ namespace osu.Game.Rulesets.Catch new MultiMod(new CatchModDoubleTime(), new CatchModNightcore()), new CatchModHidden(), new CatchModFlashlight(), + //new ModAccuracyChallenge(), }; case ModType.Conversion: diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index bd6a67bf67..8f2d679750 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -222,6 +222,7 @@ namespace osu.Game.Rulesets.Mania new MultiMod(new ManiaModDoubleTime(), new ManiaModNightcore()), new MultiMod(new ManiaModFadeIn(), new ManiaModHidden()), new ManiaModFlashlight(), + //new ModAccuracyChallenge(), }; case ModType.Conversion: diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 207e7a4ab0..15998a48c3 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -159,7 +159,8 @@ namespace osu.Game.Rulesets.Osu new MultiMod(new OsuModDoubleTime(), new OsuModNightcore()), new OsuModHidden(), new MultiMod(new OsuModFlashlight(), new OsuModBlinds()), - new OsuModStrictTracking() + new OsuModStrictTracking(), + new ModAccuracyChallenge(), }; case ModType.Conversion: diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 615fbf093f..655aba88e3 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -128,6 +128,7 @@ namespace osu.Game.Rulesets.Taiko new MultiMod(new TaikoModDoubleTime(), new TaikoModNightcore()), new TaikoModHidden(), new TaikoModFlashlight(), + //new ModAccuracyChallenge(), }; case ModType.Conversion: diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs new file mode 100644 index 0000000000..bb7d3896b2 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -0,0 +1,59 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Settings; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Judgements; + +namespace osu.Game.Rulesets.Mods +{ + public class ModAccuracyChallenge : ModFailCondition + { + public override string Name => "Accuracy Challenge"; + public override string Acronym => "AC"; + public override string Description => "Fail the map if you don't maintain a certain accuracy."; + public override IconUsage? Icon => FontAwesome.Solid.Calculator; + public override ModType Type => ModType.DifficultyIncrease; + public override double ScoreMultiplier => 1.0; + public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModEasyWithExtraLives)).Append(typeof(ModPerfect)).ToArray(); + + [SettingSource("Minimum accuracy", "Trigger a failure if your accuracy goes below this value.", SettingControlType = typeof(SettingsSlider))] + public BindableNumber MinimumAccuracy { get; } = new BindableDouble + { + MinValue = 0, + MaxValue = 1, + Precision = 0.01, + Default = 0.9, + Value = 0.9, + }; + + private double baseScore; + private double maxBaseScore; + private double accuracy => maxBaseScore > 0 ? baseScore / maxBaseScore : 1; + + protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) + { + if (!result.Type.IsScorable() || result.Type.IsBonus()) + return false; + + baseScore += result.Type.IsHit() ? result.Judgement.NumericResultFor(result) : 0; + maxBaseScore += result.Judgement.MaxNumericResult; + + return accuracy < MinimumAccuracy.Value; + } + } + + public class PercentSlider : OsuSliderBar + { + public PercentSlider() + { + DisplayAsPercentage = true; + } + } +} diff --git a/osu.Game/Rulesets/Mods/ModEasyWithExtraLives.cs b/osu.Game/Rulesets/Mods/ModEasyWithExtraLives.cs index 2ac0f59d84..7e6b085f8a 100644 --- a/osu.Game/Rulesets/Mods/ModEasyWithExtraLives.cs +++ b/osu.Game/Rulesets/Mods/ModEasyWithExtraLives.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Linq; using Humanizer; using osu.Framework.Bindables; using osu.Game.Beatmaps; @@ -19,6 +21,7 @@ namespace osu.Game.Rulesets.Mods }; public override string SettingDescription => Retries.IsDefault ? string.Empty : $"{"lives".ToQuantity(Retries.Value)}"; + public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModAccuracyChallenge)).ToArray(); private int retries; diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 9016a24f8d..4c68d0d375 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 1; public override string Description => "SS or quit."; - public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModSuddenDeath)).ToArray(); + public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModSuddenDeath)).Append(typeof(ModAccuracyChallenge)).ToArray(); protected ModPerfect() { From 252bacc8d4aeee7bacf96598b97a28eef7e884c7 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Tue, 24 May 2022 10:56:31 -0400 Subject: [PATCH 02/15] revert more testing leftovers... --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index bcce28adb2..9ddafc9315 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -109,7 +109,7 @@ namespace osu.Game.Rulesets.Catch new MultiMod(new CatchModDoubleTime(), new CatchModNightcore()), new CatchModHidden(), new CatchModFlashlight(), - //new ModAccuracyChallenge(), + new ModAccuracyChallenge(), }; case ModType.Conversion: diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 8f2d679750..659d7f242f 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -222,7 +222,7 @@ namespace osu.Game.Rulesets.Mania new MultiMod(new ManiaModDoubleTime(), new ManiaModNightcore()), new MultiMod(new ManiaModFadeIn(), new ManiaModHidden()), new ManiaModFlashlight(), - //new ModAccuracyChallenge(), + new ModAccuracyChallenge(), }; case ModType.Conversion: diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 655aba88e3..a80c87ecd3 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -128,7 +128,7 @@ namespace osu.Game.Rulesets.Taiko new MultiMod(new TaikoModDoubleTime(), new TaikoModNightcore()), new TaikoModHidden(), new TaikoModFlashlight(), - //new ModAccuracyChallenge(), + new ModAccuracyChallenge(), }; case ModType.Conversion: From 5944a15c30abfa9dfc56b169d68955f68bd0edbb Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Tue, 24 May 2022 20:04:57 -0400 Subject: [PATCH 03/15] review pass eins --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 5 +++-- osu.Game/Rulesets/Mods/ModPerfect.cs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index bb7d3896b2..804ce867af 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -21,12 +21,13 @@ namespace osu.Game.Rulesets.Mods public override IconUsage? Icon => FontAwesome.Solid.Calculator; public override ModType Type => ModType.DifficultyIncrease; public override double ScoreMultiplier => 1.0; - public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModEasyWithExtraLives)).Append(typeof(ModPerfect)).ToArray(); + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(ModEasyWithExtraLives), typeof(ModPerfect) }).ToArray(); + public override bool RequiresConfiguration => false; [SettingSource("Minimum accuracy", "Trigger a failure if your accuracy goes below this value.", SettingControlType = typeof(SettingsSlider))] public BindableNumber MinimumAccuracy { get; } = new BindableDouble { - MinValue = 0, + MinValue = 0.01, MaxValue = 1, Precision = 0.01, Default = 0.9, diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 4c68d0d375..c40c651655 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 1; public override string Description => "SS or quit."; - public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModSuddenDeath)).Append(typeof(ModAccuracyChallenge)).ToArray(); + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(ModSuddenDeath), typeof(ModAccuracyChallenge) }).ToArray(); protected ModPerfect() { From 58d4aeb4fb1b60fe5c5fe7e701fc5db469e1ad8e Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Wed, 25 May 2022 15:11:06 -0400 Subject: [PATCH 04/15] add accuracy calculation comment --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 804ce867af..fe12b72d1e 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -40,6 +40,7 @@ namespace osu.Game.Rulesets.Mods protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) { + // accuracy calculation logic taken from `ScoreProcessor`. should be updated here if the formula ever changes. if (!result.Type.IsScorable() || result.Type.IsBonus()) return false; From 6710df94a79052689d67b79c3ec55dfd81fd7107 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Mon, 6 Jun 2022 12:05:45 -0400 Subject: [PATCH 05/15] change max accuracy to 99% --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index fe12b72d1e..307a9594fe 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Mods public BindableNumber MinimumAccuracy { get; } = new BindableDouble { MinValue = 0.01, - MaxValue = 1, + MaxValue = 0.99, Precision = 0.01, Default = 0.9, Value = 0.9, From fdbec4f8c0c8082445beaef065c7df9aa4a36065 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Wed, 8 Jun 2022 23:44:34 -0400 Subject: [PATCH 06/15] display tooltip accuracy as percentage --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 307a9594fe..2c088e880b 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -23,6 +23,7 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 1.0; public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(ModEasyWithExtraLives), typeof(ModPerfect) }).ToArray(); public override bool RequiresConfiguration => false; + public override string SettingDescription => base.SettingDescription.Replace(MinimumAccuracy.Value.ToString(), MinimumAccuracy.Value.ToString("##%")); [SettingSource("Minimum accuracy", "Trigger a failure if your accuracy goes below this value.", SettingControlType = typeof(SettingsSlider))] public BindableNumber MinimumAccuracy { get; } = new BindableDouble From 99dc2fbc3e51a4d8a81eba6c595eeda7079532a9 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Thu, 9 Jun 2022 00:15:15 -0400 Subject: [PATCH 07/15] specify culture --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 2c088e880b..891832a353 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Globalization; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; @@ -23,7 +24,7 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 1.0; public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(ModEasyWithExtraLives), typeof(ModPerfect) }).ToArray(); public override bool RequiresConfiguration => false; - public override string SettingDescription => base.SettingDescription.Replace(MinimumAccuracy.Value.ToString(), MinimumAccuracy.Value.ToString("##%")); + public override string SettingDescription => base.SettingDescription.Replace(MinimumAccuracy.ToString(), MinimumAccuracy.Value.ToString("##%", NumberFormatInfo.InvariantInfo)); [SettingSource("Minimum accuracy", "Trigger a failure if your accuracy goes below this value.", SettingControlType = typeof(SettingsSlider))] public BindableNumber MinimumAccuracy { get; } = new BindableDouble From 4b73c423bda6c0c8d14b0db3d046c8cd8820fb9f Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Thu, 9 Jun 2022 18:58:22 -0400 Subject: [PATCH 08/15] don't specify icon --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 891832a353..74a9a205a0 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -5,7 +5,6 @@ using System; using System.Globalization; using System.Linq; using osu.Framework.Bindables; -using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; @@ -19,7 +18,6 @@ namespace osu.Game.Rulesets.Mods public override string Name => "Accuracy Challenge"; public override string Acronym => "AC"; public override string Description => "Fail the map if you don't maintain a certain accuracy."; - public override IconUsage? Icon => FontAwesome.Solid.Calculator; public override ModType Type => ModType.DifficultyIncrease; public override double ScoreMultiplier => 1.0; public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(ModEasyWithExtraLives), typeof(ModPerfect) }).ToArray(); From 23ea77cb74034f2e19071a4758329efc8fad4ba0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Jan 2023 17:03:04 +0900 Subject: [PATCH 09/15] Use `ScoreProcessor` to fetch accuracy rather than calculating manually --- .../Rulesets/Mods/ModAccuracyChallenge.cs | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 74a9a205a0..732f54e356 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -5,23 +5,32 @@ using System; using System.Globalization; using System.Linq; using osu.Framework.Bindables; +using osu.Framework.Localisation; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Judgements; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Mods { - public class ModAccuracyChallenge : ModFailCondition + public class ModAccuracyChallenge : ModFailCondition, IApplicableToScoreProcessor { public override string Name => "Accuracy Challenge"; + public override string Acronym => "AC"; - public override string Description => "Fail the map if you don't maintain a certain accuracy."; + + public override LocalisableString Description => "Fail if your accuracy drops too low!"; + public override ModType Type => ModType.DifficultyIncrease; + public override double ScoreMultiplier => 1.0; + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(ModEasyWithExtraLives), typeof(ModPerfect) }).ToArray(); + public override bool RequiresConfiguration => false; + public override string SettingDescription => base.SettingDescription.Replace(MinimumAccuracy.ToString(), MinimumAccuracy.Value.ToString("##%", NumberFormatInfo.InvariantInfo)); [SettingSource("Minimum accuracy", "Trigger a failure if your accuracy goes below this value.", SettingControlType = typeof(SettingsSlider))] @@ -34,9 +43,14 @@ namespace osu.Game.Rulesets.Mods Value = 0.9, }; - private double baseScore; - private double maxBaseScore; - private double accuracy => maxBaseScore > 0 ? baseScore / maxBaseScore : 1; + private ScoreProcessor scoreProcessor = null!; + + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + { + this.scoreProcessor = scoreProcessor; + } + + public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) { @@ -44,14 +58,11 @@ namespace osu.Game.Rulesets.Mods if (!result.Type.IsScorable() || result.Type.IsBonus()) return false; - baseScore += result.Type.IsHit() ? result.Judgement.NumericResultFor(result) : 0; - maxBaseScore += result.Judgement.MaxNumericResult; - - return accuracy < MinimumAccuracy.Value; + return scoreProcessor.Accuracy.Value < MinimumAccuracy.Value; } } - public class PercentSlider : OsuSliderBar + public partial class PercentSlider : OsuSliderBar { public PercentSlider() { From dfbbc4002c0fccf6ecdedea8a609972efa0fdd45 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Tue, 17 Jan 2023 10:22:58 -0500 Subject: [PATCH 10/15] address test failure --- .../Mods/OsuModAccuracyChallenge.cs | 14 ++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModAccuracyChallenge.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAccuracyChallenge.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAccuracyChallenge.cs new file mode 100644 index 0000000000..5b79753632 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAccuracyChallenge.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModAccuracyChallenge : ModAccuracyChallenge + { + public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray(); + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 6417b557f4..48056a49de 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -165,7 +165,7 @@ namespace osu.Game.Rulesets.Osu new OsuModHidden(), new MultiMod(new OsuModFlashlight(), new OsuModBlinds()), new OsuModStrictTracking(), - new ModAccuracyChallenge(), + new OsuModAccuracyChallenge(), }; case ModType.Conversion: From 0b1e5c0f53f4470ab9ead7d1b99c35d5fca2c790 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Tue, 17 Jan 2023 10:23:57 -0500 Subject: [PATCH 11/15] lambdaify function --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 732f54e356..78e6acf23a 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -45,10 +45,7 @@ namespace osu.Game.Rulesets.Mods private ScoreProcessor scoreProcessor = null!; - public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) - { - this.scoreProcessor = scoreProcessor; - } + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) => this.scoreProcessor = scoreProcessor; public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; From 522bb8bccafc93603d068775b6c3a28cd3b58c25 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 18:08:58 +0900 Subject: [PATCH 12/15] Use `ComputeAccuracy` to get imminent accuracy --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 15 +++++++++++++-- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 18 +++++++++++------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 78e6acf23a..02d4fb4d67 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -51,11 +51,22 @@ namespace osu.Game.Rulesets.Mods protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) { - // accuracy calculation logic taken from `ScoreProcessor`. should be updated here if the formula ever changes. if (!result.Type.IsScorable() || result.Type.IsBonus()) return false; - return scoreProcessor.Accuracy.Value < MinimumAccuracy.Value; + return getAccuracyWithImminentResultAdded(result) < MinimumAccuracy.Value; + } + + private double getAccuracyWithImminentResultAdded(JudgementResult result) + { + var score = new ScoreInfo { Ruleset = scoreProcessor.Ruleset.RulesetInfo }; + + // This is super ugly, but if we don't do it this way we will not have the most recent result added to the accuracy value. + // Hopefully we can improve this in the future. + scoreProcessor.PopulateScore(score); + score.Statistics[result.Type]++; + + return scoreProcessor.ComputeAccuracy(score); } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ff0d91c0dd..3ff1b69612 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -97,7 +97,11 @@ namespace osu.Game.Rulesets.Scoring /// protected virtual double ClassicScoreMultiplier => 36; - private readonly Ruleset ruleset; + /// + /// The ruleset this score processor is valid for. + /// + public readonly Ruleset Ruleset; + private readonly double accuracyPortion; private readonly double comboPortion; @@ -145,7 +149,7 @@ namespace osu.Game.Rulesets.Scoring public ScoreProcessor(Ruleset ruleset) { - this.ruleset = ruleset; + this.Ruleset = ruleset; accuracyPortion = DefaultAccuracyPortion; comboPortion = DefaultComboPortion; @@ -291,8 +295,8 @@ namespace osu.Game.Rulesets.Scoring [Pure] public double ComputeAccuracy(ScoreInfo scoreInfo) { - if (!ruleset.RulesetInfo.Equals(scoreInfo.Ruleset)) - throw new ArgumentException($"Unexpected score ruleset. Expected \"{ruleset.RulesetInfo.ShortName}\" but was \"{scoreInfo.Ruleset.ShortName}\"."); + if (!Ruleset.RulesetInfo.Equals(scoreInfo.Ruleset)) + throw new ArgumentException($"Unexpected score ruleset. Expected \"{Ruleset.RulesetInfo.ShortName}\" but was \"{scoreInfo.Ruleset.ShortName}\"."); // We only extract scoring values from the score's statistics. This is because accuracy is always relative to the point of pass or fail rather than relative to the whole beatmap. extractScoringValues(scoreInfo.Statistics, out var current, out var maximum); @@ -312,8 +316,8 @@ namespace osu.Game.Rulesets.Scoring [Pure] public long ComputeScore(ScoringMode mode, ScoreInfo scoreInfo) { - if (!ruleset.RulesetInfo.Equals(scoreInfo.Ruleset)) - throw new ArgumentException($"Unexpected score ruleset. Expected \"{ruleset.RulesetInfo.ShortName}\" but was \"{scoreInfo.Ruleset.ShortName}\"."); + if (!Ruleset.RulesetInfo.Equals(scoreInfo.Ruleset)) + throw new ArgumentException($"Unexpected score ruleset. Expected \"{Ruleset.RulesetInfo.ShortName}\" but was \"{scoreInfo.Ruleset.ShortName}\"."); extractScoringValues(scoreInfo, out var current, out var maximum); @@ -552,7 +556,7 @@ namespace osu.Game.Rulesets.Scoring break; default: - maxResult = maxBasicResult ??= ruleset.GetHitResults().MaxBy(kvp => Judgement.ToNumericResult(kvp.result)).result; + maxResult = maxBasicResult ??= Ruleset.GetHitResults().MaxBy(kvp => Judgement.ToNumericResult(kvp.result)).result; break; } From e0f3fa1af61734545767fac51baa9ff7a1fb1838 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Wed, 18 Jan 2023 12:22:27 -0500 Subject: [PATCH 13/15] remove `this` in ruleset assignment --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 3ff1b69612..b5f42ec2cc 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -149,7 +149,7 @@ namespace osu.Game.Rulesets.Scoring public ScoreProcessor(Ruleset ruleset) { - this.Ruleset = ruleset; + Ruleset = ruleset; accuracyPortion = DefaultAccuracyPortion; comboPortion = DefaultComboPortion; From 150195b8878bd9ca5ed83fe71f92487e92b52403 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Wed, 18 Jan 2023 12:24:41 -0500 Subject: [PATCH 14/15] use extension method to check accuracy impact --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 02d4fb4d67..e18164db89 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Mods protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) { - if (!result.Type.IsScorable() || result.Type.IsBonus()) + if (!result.Type.AffectsAccuracy()) return false; return getAccuracyWithImminentResultAdded(result) < MinimumAccuracy.Value; From b46ef67a14c68a48d210e206db542dc90cff20ee Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Tue, 24 Jan 2023 00:31:46 -0500 Subject: [PATCH 15/15] increase min minimum accuracy to 60% --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index e18164db89..59fbfe49b6 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Mods [SettingSource("Minimum accuracy", "Trigger a failure if your accuracy goes below this value.", SettingControlType = typeof(SettingsSlider))] public BindableNumber MinimumAccuracy { get; } = new BindableDouble { - MinValue = 0.01, + MinValue = 0.60, MaxValue = 0.99, Precision = 0.01, Default = 0.9,