From 55064c387d4558e342e0287368bfb26178167062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 26 Sep 2023 08:11:53 +0200 Subject: [PATCH 1/3] Add mod controls to scoring test scene --- .../Tests/Visual/Gameplay/ScoringTestScene.cs | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs b/osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs index de4688a6fe..879a5e8a2b 100644 --- a/osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs +++ b/osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs @@ -18,6 +18,9 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Overlays; +using osu.Game.Overlays.Mods; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -53,6 +56,10 @@ namespace osu.Game.Tests.Visual.Gameplay private readonly BindableBool scoreV1Visible = new BindableBool(true); private readonly BindableBool scoreV2Visible = new BindableBool(true); + private RoundedButton changeModsButton = null!; + private OsuSpriteText modsText = null!; + private TestModSelectOverlay modSelect = null!; + [Resolved] private OsuColour colours { get; set; } = null!; @@ -83,6 +90,7 @@ namespace osu.Game.Tests.Visual.Gameplay new Dimension(), new Dimension(GridSizeMode.AutoSize), new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), }, Content = new[] { @@ -104,6 +112,47 @@ namespace osu.Game.Tests.Visual.Gameplay }, }, new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = 20 }, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = "Selected mods", + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10), + Children = new Drawable[] + { + changeModsButton = new RoundedButton + { + Text = "Change", + Width = 100, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + }, + modsText = new OsuSpriteText + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + }, + } + } + } + } + }, + new Drawable[] { new FillFlowContainer { @@ -139,6 +188,11 @@ namespace osu.Game.Tests.Visual.Gameplay }, }, } + }, + modSelect = new TestModSelectOverlay + { + RelativeSizeAxes = Axes.Both, + SelectedMods = { BindTarget = SelectedMods } } }; @@ -159,6 +213,9 @@ namespace osu.Game.Tests.Visual.Gameplay graphs.MaxCombo.BindTo(sliderMaxCombo.Current); + changeModsButton.Action = () => modSelect.Show(); + SelectedMods.BindValueChanged(mods => Rerun()); + Rerun(); }); } @@ -168,6 +225,10 @@ namespace osu.Game.Tests.Visual.Gameplay graphs.Clear(); legend.Clear(); + modsText.Text = SelectedMods.Value.Any() + ? string.Join(", ", SelectedMods.Value.Select(mod => mod.Acronym)) + : "(none)"; + runForProcessor("lazer-standardised", colours.Green1, ScoringMode.Standardised, standardisedVisible); runForProcessor("lazer-classic", colours.Blue1, ScoringMode.Classic, classicVisible); @@ -592,5 +653,16 @@ namespace osu.Game.Tests.Visual.Gameplay lineGraph.Alpha = Visible.Value ? 1 : 0; } } + + private partial class TestModSelectOverlay : UserModSelectOverlay + { + protected override bool ShowModEffects => true; + protected override bool ShowPresets => false; + + public TestModSelectOverlay() + : base(OverlayColourScheme.Aquamarine) + { + } + } } } From 419cc8784a5f3cc10849a5c202250529933693ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 26 Sep 2023 08:20:09 +0200 Subject: [PATCH 2/3] Apply mods to processor-based score algorithms --- osu.Game.Rulesets.Catch.Tests/TestSceneScoring.cs | 9 ++++++--- osu.Game.Rulesets.Mania.Tests/TestSceneScoring.cs | 10 +++++++--- osu.Game.Rulesets.Osu.Tests/TestSceneScoring.cs | 10 +++++++--- osu.Game.Rulesets.Taiko.Tests/TestSceneScoring.cs | 9 ++++++--- osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs | 8 +++++--- 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneScoring.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneScoring.cs index dfdde0a325..886fbe7222 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneScoring.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneScoring.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Bindables; using osu.Game.Beatmaps; @@ -10,6 +11,7 @@ using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Tests.Visual.Gameplay; @@ -41,7 +43,8 @@ namespace osu.Game.Rulesets.Catch.Tests protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); - protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode) => new CatchProcessorBasedScoringAlgorithm(beatmap, mode); + protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList selectedMods) + => new CatchProcessorBasedScoringAlgorithm(beatmap, mode, selectedMods); [Test] public void TestBasicScenarios() @@ -140,8 +143,8 @@ namespace osu.Game.Rulesets.Catch.Tests private class CatchProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm { - public CatchProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode) - : base(beatmap, mode) + public CatchProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList selectedMods) + : base(beatmap, mode, selectedMods) { } diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneScoring.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneScoring.cs index ae3ea861ea..f37d130b87 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneScoring.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneScoring.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; @@ -9,6 +10,7 @@ using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Scoring; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Tests.Visual.Gameplay; @@ -27,7 +29,9 @@ namespace osu.Game.Rulesets.Mania.Tests protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1(MaxCombo.Value); protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); - protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode) => new ManiaProcessorBasedScoringAlgorithm(beatmap, mode); + + protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList selectedMods) + => new ManiaProcessorBasedScoringAlgorithm(beatmap, mode, selectedMods); [Test] public void TestBasicScenarios() @@ -158,8 +162,8 @@ namespace osu.Game.Rulesets.Mania.Tests private class ManiaProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm { - public ManiaProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode) - : base(beatmap, mode) + public ManiaProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList selectedMods) + : base(beatmap, mode, selectedMods) { } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneScoring.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneScoring.cs index bb09328ab7..671817d30f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneScoring.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneScoring.cs @@ -2,10 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Objects; @@ -34,7 +36,9 @@ namespace osu.Game.Rulesets.Osu.Tests protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1 { ScoreMultiplier = { BindTarget = scoreMultiplier } }; protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); - protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode) => new OsuProcessorBasedScoringAlgorithm(beatmap, mode); + + protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList mods) + => new OsuProcessorBasedScoringAlgorithm(beatmap, mode, mods); [Test] public void TestBasicScenarios() @@ -162,8 +166,8 @@ namespace osu.Game.Rulesets.Osu.Tests private class OsuProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm { - public OsuProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode) - : base(beatmap, mode) + public OsuProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList selectedMods) + : base(beatmap, mode, selectedMods) { } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneScoring.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneScoring.cs index e065070822..90c866acdb 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneScoring.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneScoring.cs @@ -2,10 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Judgements; @@ -35,7 +37,8 @@ namespace osu.Game.Rulesets.Taiko.Tests protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1 { ScoreMultiplier = { BindTarget = scoreMultiplier } }; protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); - protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode) => new TaikoProcessorBasedScoringAlgorithm(beatmap, mode); + protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList selectedMods) + => new TaikoProcessorBasedScoringAlgorithm(beatmap, mode, selectedMods); [Test] public void TestBasicScenarios() @@ -171,8 +174,8 @@ namespace osu.Game.Rulesets.Taiko.Tests private class TaikoProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm { - public TaikoProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode) - : base(beatmap, mode) + public TaikoProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList selectedMods) + : base(beatmap, mode, selectedMods) { } diff --git a/osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs b/osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs index 879a5e8a2b..8a2a81ce96 100644 --- a/osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs +++ b/osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs @@ -23,6 +23,7 @@ using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring.Legacy; using osuTK; @@ -37,7 +38,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected abstract IScoringAlgorithm CreateScoreV1(); protected abstract IScoringAlgorithm CreateScoreV2(int maxCombo); - protected abstract ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode); + protected abstract ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList mods); protected Bindable MaxCombo => sliderMaxCombo.Current; protected BindableList NonPerfectLocations => graphs.NonPerfectLocations; @@ -270,7 +271,7 @@ namespace osu.Game.Tests.Visual.Gameplay { int maxCombo = sliderMaxCombo.Current.Value; var beatmap = CreateBeatmap(maxCombo); - var algorithm = CreateScoreAlgorithm(beatmap, scoringMode); + var algorithm = CreateScoreAlgorithm(beatmap, scoringMode, SelectedMods.Value); runForAlgorithm(new ScoringAlgorithmInfo { @@ -343,11 +344,12 @@ namespace osu.Game.Tests.Visual.Gameplay private readonly ScoreProcessor scoreProcessor; private readonly ScoringMode mode; - protected ProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode) + protected ProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList selectedMods) { this.mode = mode; scoreProcessor = CreateScoreProcessor(); scoreProcessor.ApplyBeatmap(beatmap); + scoreProcessor.Mods.Value = selectedMods; } public void ApplyHit() => scoreProcessor.ApplyResult(CreatePerfectJudgementResult()); From d7e891140de52b8c8c0eb623040fd60df729cf17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 26 Sep 2023 08:44:32 +0200 Subject: [PATCH 3/3] Apply mod multipliers to local score V1/V2 reimplementations --- .../TestSceneScoring.cs | 37 +++++++++++++--- .../TestSceneScoring.cs | 31 ++++++++++---- .../TestSceneScoring.cs | 42 +++++++++++++++---- .../TestSceneScoring.cs | 40 +++++++++++++++--- .../Tests/Visual/Gameplay/ScoringTestScene.cs | 8 ++-- 5 files changed, 128 insertions(+), 30 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneScoring.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneScoring.cs index 886fbe7222..9f667358db 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneScoring.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneScoring.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Bindables; using osu.Game.Beatmaps; @@ -13,6 +14,7 @@ using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Scoring.Legacy; using osu.Game.Tests.Visual.Gameplay; namespace osu.Game.Rulesets.Catch.Tests @@ -39,9 +41,11 @@ namespace osu.Game.Rulesets.Catch.Tests return beatmap; } - protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1 { ScoreMultiplier = { BindTarget = scoreMultiplier } }; + protected override IScoringAlgorithm CreateScoreV1(IReadOnlyList selectedMods) + => new ScoreV1(selectedMods) { ScoreMultiplier = { BindTarget = scoreMultiplier } }; - protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); + protected override IScoringAlgorithm CreateScoreV2(int maxCombo, IReadOnlyList selectedMods) + => new ScoreV2(maxCombo, selectedMods); protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList selectedMods) => new CatchProcessorBasedScoringAlgorithm(beatmap, mode, selectedMods); @@ -72,10 +76,21 @@ namespace osu.Game.Rulesets.Catch.Tests private class ScoreV1 : IScoringAlgorithm { - private int currentCombo; + private readonly double modMultiplier; public BindableDouble ScoreMultiplier { get; } = new BindableDouble(); + private int currentCombo; + + public ScoreV1(IReadOnlyList selectedMods) + { + var ruleset = new CatchRuleset(); + modMultiplier = ruleset.CreateLegacyScoreSimulator().GetLegacyScoreMultiplier(selectedMods, new LegacyBeatmapConversionDifficultyInfo + { + SourceRuleset = ruleset.RulesetInfo + }); + } + public void ApplyHit() => applyHitV1(base_great); public void ApplyNonPerfect() => throw new NotSupportedException("catch does not have \"non-perfect\" judgements."); @@ -94,7 +109,7 @@ namespace osu.Game.Rulesets.Catch.Tests // combo multiplier // ReSharper disable once PossibleLossOfFraction - TotalScore += (int)(Math.Max(0, currentCombo - 1) * (baseScore / 25 * ScoreMultiplier.Value)); + TotalScore += (int)(Math.Max(0, currentCombo - 1) * (baseScore / 25 * (ScoreMultiplier.Value * modMultiplier))); currentCombo++; } @@ -107,13 +122,23 @@ namespace osu.Game.Rulesets.Catch.Tests private int currentCombo; private double comboPortion; + private readonly double modMultiplier; + private readonly double comboPortionMax; private const double combo_base = 4; private const int combo_cap = 200; - public ScoreV2(int maxCombo) + public ScoreV2(int maxCombo, IReadOnlyList selectedMods) { + var ruleset = new CatchRuleset(); + modMultiplier = ruleset.CreateLegacyScoreSimulator().GetLegacyScoreMultiplier( + selectedMods.Append(new ModScoreV2()).ToList(), + new LegacyBeatmapConversionDifficultyInfo + { + SourceRuleset = ruleset.RulesetInfo + }); + for (int i = 0; i < maxCombo; i++) ApplyHit(); @@ -138,7 +163,7 @@ namespace osu.Game.Rulesets.Catch.Tests } public long TotalScore - => (int)Math.Round(1000000 * comboPortion / comboPortionMax); // vast simplification, as we're not doing ticks here. + => (int)Math.Round((1000000 * comboPortion / comboPortionMax) * modMultiplier); // vast simplification, as we're not doing ticks here. } private class CatchProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneScoring.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneScoring.cs index f37d130b87..19d90e0551 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneScoring.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneScoring.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; @@ -12,6 +13,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Scoring.Legacy; using osu.Game.Tests.Visual.Gameplay; namespace osu.Game.Rulesets.Mania.Tests @@ -27,8 +29,8 @@ namespace osu.Game.Rulesets.Mania.Tests return beatmap; } - protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1(MaxCombo.Value); - protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); + protected override IScoringAlgorithm CreateScoreV1(IReadOnlyList selectedMods) => new ScoreV1(MaxCombo.Value, selectedMods); + protected override IScoringAlgorithm CreateScoreV2(int maxCombo, IReadOnlyList selectedMods) => new ScoreV2(maxCombo, selectedMods); protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList selectedMods) => new ManiaProcessorBasedScoringAlgorithm(beatmap, mode, selectedMods); @@ -63,11 +65,17 @@ namespace osu.Game.Rulesets.Mania.Tests private int currentCombo; private double comboAddition = 100; private double totalScoreDouble; + private readonly double scoreMultiplier; - public ScoreV1(int maxCombo) + public ScoreV1(int maxCombo, IReadOnlyList selectedMods) { - scoreMultiplier = 500000d / maxCombo; + var ruleset = new ManiaRuleset(); + + scoreMultiplier = 500000d / maxCombo * ruleset.CreateLegacyScoreSimulator().GetLegacyScoreMultiplier(selectedMods, new LegacyBeatmapConversionDifficultyInfo + { + SourceRuleset = ruleset.RulesetInfo + }); } public void ApplyHit() => applyHitV1(320, add => add + 2, 32); @@ -107,13 +115,22 @@ namespace osu.Game.Rulesets.Mania.Tests private readonly double comboPortionMax; private readonly int maxCombo; + private readonly double modMultiplier; private const double combo_base = 4; - public ScoreV2(int maxCombo) + public ScoreV2(int maxCombo, IReadOnlyList selectedMods) { this.maxCombo = maxCombo; + var ruleset = new ManiaRuleset(); + modMultiplier = new ManiaRuleset().CreateLegacyScoreSimulator().GetLegacyScoreMultiplier( + selectedMods.Append(new ModScoreV2()).ToArray(), + new LegacyBeatmapConversionDifficultyInfo + { + SourceRuleset = ruleset.RulesetInfo + }); + for (int i = 0; i < this.maxCombo; i++) ApplyHit(); @@ -152,10 +169,10 @@ namespace osu.Game.Rulesets.Mania.Tests float accuracy = (float)(currentBaseScore / maxBaseScore); return (int)Math.Round - ( + (( 200000 * comboPortion / comboPortionMax + 800000 * Math.Pow(accuracy, 2 + 2 * accuracy) * ((double)currentHits / maxCombo) - ); + ) * modMultiplier); } } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneScoring.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneScoring.cs index 671817d30f..627c8f416e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneScoring.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneScoring.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Bindables; using osu.Game.Beatmaps; @@ -13,6 +14,7 @@ using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Scoring.Legacy; using osu.Game.Tests.Visual.Gameplay; namespace osu.Game.Rulesets.Osu.Tests @@ -34,8 +36,14 @@ namespace osu.Game.Rulesets.Osu.Tests return beatmap; } - protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1 { ScoreMultiplier = { BindTarget = scoreMultiplier } }; - protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); + protected override IScoringAlgorithm CreateScoreV1(IReadOnlyList selectedMods) + => new ScoreV1(selectedMods) + { + ScoreMultiplier = { BindTarget = scoreMultiplier } + }; + + protected override IScoringAlgorithm CreateScoreV2(int maxCombo, IReadOnlyList selectedMods) + => new ScoreV2(maxCombo, selectedMods); protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList mods) => new OsuProcessorBasedScoringAlgorithm(beatmap, mode, mods); @@ -75,9 +83,19 @@ namespace osu.Game.Rulesets.Osu.Tests private class ScoreV1 : IScoringAlgorithm { + private readonly double modMultiplier; + public BindableDouble ScoreMultiplier { get; } = new BindableDouble(); + private int currentCombo; - public BindableDouble ScoreMultiplier { get; } = new BindableDouble(); + public ScoreV1(IReadOnlyList selectedMods) + { + var ruleset = new OsuRuleset(); + modMultiplier = ruleset.CreateLegacyScoreSimulator().GetLegacyScoreMultiplier(selectedMods, new LegacyBeatmapConversionDifficultyInfo + { + SourceRuleset = ruleset.RulesetInfo + }); + } public void ApplyHit() => applyHitV1(base_great); public void ApplyNonPerfect() => applyHitV1(base_ok); @@ -95,7 +113,7 @@ namespace osu.Game.Rulesets.Osu.Tests // combo multiplier // ReSharper disable once PossibleLossOfFraction - TotalScore += (int)(Math.Max(0, currentCombo - 1) * (baseScore / 25 * ScoreMultiplier.Value)); + TotalScore += (int)(Math.Max(0, currentCombo - 1) * (baseScore / 25 * (ScoreMultiplier.Value * modMultiplier))); currentCombo++; } @@ -111,13 +129,23 @@ namespace osu.Game.Rulesets.Osu.Tests private double maxBaseScore; private int currentHits; + private readonly double modMultiplier; + private readonly double comboPortionMax; private readonly int maxCombo; - public ScoreV2(int maxCombo) + public ScoreV2(int maxCombo, IReadOnlyList selectedMods) { this.maxCombo = maxCombo; + var ruleset = new OsuRuleset(); + modMultiplier = ruleset.CreateLegacyScoreSimulator().GetLegacyScoreMultiplier( + selectedMods.Append(new ModScoreV2()).ToList(), + new LegacyBeatmapConversionDifficultyInfo + { + SourceRuleset = ruleset.RulesetInfo + }); + for (int i = 0; i < this.maxCombo; i++) ApplyHit(); @@ -156,10 +184,10 @@ namespace osu.Game.Rulesets.Osu.Tests double accuracy = currentBaseScore / maxBaseScore; return (int)Math.Round - ( + (( 700000 * comboPortion / comboPortionMax + 300000 * Math.Pow(accuracy, 10) * ((double)currentHits / maxCombo) - ); + ) * modMultiplier); } } } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneScoring.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneScoring.cs index 90c866acdb..cf8e3767da 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneScoring.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneScoring.cs @@ -3,12 +3,14 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Scoring.Legacy; using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects; @@ -34,8 +36,14 @@ namespace osu.Game.Rulesets.Taiko.Tests return beatmap; } - protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1 { ScoreMultiplier = { BindTarget = scoreMultiplier } }; - protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); + protected override IScoringAlgorithm CreateScoreV1(IReadOnlyList selectedMods) + => new ScoreV1(selectedMods) + { + ScoreMultiplier = { BindTarget = scoreMultiplier } + }; + + protected override IScoringAlgorithm CreateScoreV2(int maxCombo, IReadOnlyList selectedMods) + => new ScoreV2(maxCombo, selectedMods); protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList selectedMods) => new TaikoProcessorBasedScoringAlgorithm(beatmap, mode, selectedMods); @@ -75,8 +83,19 @@ namespace osu.Game.Rulesets.Taiko.Tests private class ScoreV1 : IScoringAlgorithm { + private readonly double modMultiplier; + private int currentCombo; + public ScoreV1(IReadOnlyList selectedMods) + { + var ruleset = new TaikoRuleset(); + modMultiplier = ruleset.CreateLegacyScoreSimulator().GetLegacyScoreMultiplier(selectedMods, new LegacyBeatmapConversionDifficultyInfo + { + SourceRuleset = ruleset.RulesetInfo + }); + } + public BindableDouble ScoreMultiplier { get; } = new BindableDouble(); public void ApplyHit() => applyHitV1(base_great); @@ -97,7 +116,7 @@ namespace osu.Game.Rulesets.Taiko.Tests // combo multiplier // ReSharper disable once PossibleLossOfFraction - TotalScore += (int)((baseScore / 35) * 2 * (ScoreMultiplier.Value + 1)) * (Math.Min(100, currentCombo) / 10); + TotalScore += (int)((baseScore / 35) * 2 * (ScoreMultiplier.Value + 1) * modMultiplier) * (Math.Min(100, currentCombo) / 10); currentCombo++; } @@ -113,15 +132,24 @@ namespace osu.Game.Rulesets.Taiko.Tests private double maxBaseScore; private int currentHits; + private readonly double modMultiplier; private readonly double comboPortionMax; private readonly int maxCombo; private const double combo_base = 4; - public ScoreV2(int maxCombo) + public ScoreV2(int maxCombo, IReadOnlyList selectedMods) { this.maxCombo = maxCombo; + var ruleset = new TaikoRuleset(); + modMultiplier = ruleset.CreateLegacyScoreSimulator().GetLegacyScoreMultiplier( + selectedMods.Append(new ModScoreV2()).ToArray(), + new LegacyBeatmapConversionDifficultyInfo + { + SourceRuleset = ruleset.RulesetInfo + }); + for (int i = 0; i < this.maxCombo; i++) ApplyHit(); @@ -164,10 +192,10 @@ namespace osu.Game.Rulesets.Taiko.Tests double accuracy = currentBaseScore / maxBaseScore; return (int)Math.Round - ( + (( 250000 * comboPortion / comboPortionMax + 750000 * Math.Pow(accuracy, 3.6) * ((double)currentHits / maxCombo) - ); + ) * modMultiplier); } } } diff --git a/osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs b/osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs index 8a2a81ce96..e7053e4202 100644 --- a/osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs +++ b/osu.Game/Tests/Visual/Gameplay/ScoringTestScene.cs @@ -36,8 +36,8 @@ namespace osu.Game.Tests.Visual.Gameplay { protected abstract IBeatmap CreateBeatmap(int maxCombo); - protected abstract IScoringAlgorithm CreateScoreV1(); - protected abstract IScoringAlgorithm CreateScoreV2(int maxCombo); + protected abstract IScoringAlgorithm CreateScoreV1(IReadOnlyList selectedMods); + protected abstract IScoringAlgorithm CreateScoreV2(int maxCombo, IReadOnlyList selectedMods); protected abstract ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList mods); protected Bindable MaxCombo => sliderMaxCombo.Current; @@ -237,14 +237,14 @@ namespace osu.Game.Tests.Visual.Gameplay { Name = "ScoreV1 (classic)", Colour = colours.Purple1, - Algorithm = CreateScoreV1(), + Algorithm = CreateScoreV1(SelectedMods.Value), Visible = scoreV1Visible }); runForAlgorithm(new ScoringAlgorithmInfo { Name = "ScoreV2", Colour = colours.Red1, - Algorithm = CreateScoreV2(sliderMaxCombo.Current.Value), + Algorithm = CreateScoreV2(sliderMaxCombo.Current.Value, SelectedMods.Value), Visible = scoreV2Visible });