1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-27 00:23:01 +08:00

Merge pull request #24933 from bdach/scoring-test-mods

Include mod multipliers in scoring test scenes
This commit is contained in:
Dean Herbert 2023-11-28 19:07:14 +09:00 committed by GitHub
commit 644dd68180
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 231 additions and 45 deletions

View File

@ -2,6 +2,8 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -10,7 +12,9 @@ using osu.Game.Rulesets.Catch.Judgements;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Catch.Scoring;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Scoring.Legacy;
using osu.Game.Tests.Visual.Gameplay; using osu.Game.Tests.Visual.Gameplay;
namespace osu.Game.Rulesets.Catch.Tests namespace osu.Game.Rulesets.Catch.Tests
@ -37,11 +41,14 @@ namespace osu.Game.Rulesets.Catch.Tests
return beatmap; return beatmap;
} }
protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1 { ScoreMultiplier = { BindTarget = scoreMultiplier } }; protected override IScoringAlgorithm CreateScoreV1(IReadOnlyList<Mod> selectedMods)
=> new ScoreV1(selectedMods) { ScoreMultiplier = { BindTarget = scoreMultiplier } };
protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); protected override IScoringAlgorithm CreateScoreV2(int maxCombo, IReadOnlyList<Mod> selectedMods)
=> new ScoreV2(maxCombo, selectedMods);
protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode) => new CatchProcessorBasedScoringAlgorithm(beatmap, mode); protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList<Mod> selectedMods)
=> new CatchProcessorBasedScoringAlgorithm(beatmap, mode, selectedMods);
[Test] [Test]
public void TestBasicScenarios() public void TestBasicScenarios()
@ -69,10 +76,21 @@ namespace osu.Game.Rulesets.Catch.Tests
private class ScoreV1 : IScoringAlgorithm private class ScoreV1 : IScoringAlgorithm
{ {
private int currentCombo; private readonly double modMultiplier;
public BindableDouble ScoreMultiplier { get; } = new BindableDouble(); public BindableDouble ScoreMultiplier { get; } = new BindableDouble();
private int currentCombo;
public ScoreV1(IReadOnlyList<Mod> selectedMods)
{
var ruleset = new CatchRuleset();
modMultiplier = ruleset.CreateLegacyScoreSimulator().GetLegacyScoreMultiplier(selectedMods, new LegacyBeatmapConversionDifficultyInfo
{
SourceRuleset = ruleset.RulesetInfo
});
}
public void ApplyHit() => applyHitV1(base_great); public void ApplyHit() => applyHitV1(base_great);
public void ApplyNonPerfect() => throw new NotSupportedException("catch does not have \"non-perfect\" judgements."); public void ApplyNonPerfect() => throw new NotSupportedException("catch does not have \"non-perfect\" judgements.");
@ -91,7 +109,7 @@ namespace osu.Game.Rulesets.Catch.Tests
// combo multiplier // combo multiplier
// ReSharper disable once PossibleLossOfFraction // 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++; currentCombo++;
} }
@ -104,13 +122,23 @@ namespace osu.Game.Rulesets.Catch.Tests
private int currentCombo; private int currentCombo;
private double comboPortion; private double comboPortion;
private readonly double modMultiplier;
private readonly double comboPortionMax; private readonly double comboPortionMax;
private const double combo_base = 4; private const double combo_base = 4;
private const int combo_cap = 200; private const int combo_cap = 200;
public ScoreV2(int maxCombo) public ScoreV2(int maxCombo, IReadOnlyList<Mod> 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++) for (int i = 0; i < maxCombo; i++)
ApplyHit(); ApplyHit();
@ -135,13 +163,13 @@ namespace osu.Game.Rulesets.Catch.Tests
} }
public long TotalScore 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 private class CatchProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm
{ {
public CatchProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode) public CatchProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList<Mod> selectedMods)
: base(beatmap, mode) : base(beatmap, mode, selectedMods)
{ {
} }

View File

@ -2,6 +2,8 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
@ -9,7 +11,9 @@ using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Scoring.Legacy;
using osu.Game.Tests.Visual.Gameplay; using osu.Game.Tests.Visual.Gameplay;
namespace osu.Game.Rulesets.Mania.Tests namespace osu.Game.Rulesets.Mania.Tests
@ -25,9 +29,11 @@ namespace osu.Game.Rulesets.Mania.Tests
return beatmap; return beatmap;
} }
protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1(MaxCombo.Value); protected override IScoringAlgorithm CreateScoreV1(IReadOnlyList<Mod> selectedMods) => new ScoreV1(MaxCombo.Value, selectedMods);
protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); protected override IScoringAlgorithm CreateScoreV2(int maxCombo, IReadOnlyList<Mod> selectedMods) => new ScoreV2(maxCombo, selectedMods);
protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode) => new ManiaProcessorBasedScoringAlgorithm(beatmap, mode);
protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList<Mod> selectedMods)
=> new ManiaProcessorBasedScoringAlgorithm(beatmap, mode, selectedMods);
[Test] [Test]
public void TestBasicScenarios() public void TestBasicScenarios()
@ -59,11 +65,17 @@ namespace osu.Game.Rulesets.Mania.Tests
private int currentCombo; private int currentCombo;
private double comboAddition = 100; private double comboAddition = 100;
private double totalScoreDouble; private double totalScoreDouble;
private readonly double scoreMultiplier; private readonly double scoreMultiplier;
public ScoreV1(int maxCombo) public ScoreV1(int maxCombo, IReadOnlyList<Mod> 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); public void ApplyHit() => applyHitV1(320, add => add + 2, 32);
@ -103,13 +115,22 @@ namespace osu.Game.Rulesets.Mania.Tests
private readonly double comboPortionMax; private readonly double comboPortionMax;
private readonly int maxCombo; private readonly int maxCombo;
private readonly double modMultiplier;
private const double combo_base = 4; private const double combo_base = 4;
public ScoreV2(int maxCombo) public ScoreV2(int maxCombo, IReadOnlyList<Mod> selectedMods)
{ {
this.maxCombo = maxCombo; 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++) for (int i = 0; i < this.maxCombo; i++)
ApplyHit(); ApplyHit();
@ -148,18 +169,18 @@ namespace osu.Game.Rulesets.Mania.Tests
float accuracy = (float)(currentBaseScore / maxBaseScore); float accuracy = (float)(currentBaseScore / maxBaseScore);
return (int)Math.Round return (int)Math.Round
( ((
200000 * comboPortion / comboPortionMax + 200000 * comboPortion / comboPortionMax +
800000 * Math.Pow(accuracy, 2 + 2 * accuracy) * ((double)currentHits / maxCombo) 800000 * Math.Pow(accuracy, 2 + 2 * accuracy) * ((double)currentHits / maxCombo)
); ) * modMultiplier);
} }
} }
} }
private class ManiaProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm private class ManiaProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm
{ {
public ManiaProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode) public ManiaProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList<Mod> selectedMods)
: base(beatmap, mode) : base(beatmap, mode, selectedMods)
{ {
} }

View File

@ -2,15 +2,19 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Scoring.Legacy;
using osu.Game.Tests.Visual.Gameplay; using osu.Game.Tests.Visual.Gameplay;
namespace osu.Game.Rulesets.Osu.Tests namespace osu.Game.Rulesets.Osu.Tests
@ -32,9 +36,17 @@ namespace osu.Game.Rulesets.Osu.Tests
return beatmap; return beatmap;
} }
protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1 { ScoreMultiplier = { BindTarget = scoreMultiplier } }; protected override IScoringAlgorithm CreateScoreV1(IReadOnlyList<Mod> selectedMods)
protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); => new ScoreV1(selectedMods)
protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode) => new OsuProcessorBasedScoringAlgorithm(beatmap, mode); {
ScoreMultiplier = { BindTarget = scoreMultiplier }
};
protected override IScoringAlgorithm CreateScoreV2(int maxCombo, IReadOnlyList<Mod> selectedMods)
=> new ScoreV2(maxCombo, selectedMods);
protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList<Mod> mods)
=> new OsuProcessorBasedScoringAlgorithm(beatmap, mode, mods);
[Test] [Test]
public void TestBasicScenarios() public void TestBasicScenarios()
@ -71,9 +83,19 @@ namespace osu.Game.Rulesets.Osu.Tests
private class ScoreV1 : IScoringAlgorithm private class ScoreV1 : IScoringAlgorithm
{ {
private readonly double modMultiplier;
public BindableDouble ScoreMultiplier { get; } = new BindableDouble();
private int currentCombo; private int currentCombo;
public BindableDouble ScoreMultiplier { get; } = new BindableDouble(); public ScoreV1(IReadOnlyList<Mod> selectedMods)
{
var ruleset = new OsuRuleset();
modMultiplier = ruleset.CreateLegacyScoreSimulator().GetLegacyScoreMultiplier(selectedMods, new LegacyBeatmapConversionDifficultyInfo
{
SourceRuleset = ruleset.RulesetInfo
});
}
public void ApplyHit() => applyHitV1(base_great); public void ApplyHit() => applyHitV1(base_great);
public void ApplyNonPerfect() => applyHitV1(base_ok); public void ApplyNonPerfect() => applyHitV1(base_ok);
@ -91,7 +113,7 @@ namespace osu.Game.Rulesets.Osu.Tests
// combo multiplier // combo multiplier
// ReSharper disable once PossibleLossOfFraction // 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++; currentCombo++;
} }
@ -107,13 +129,23 @@ namespace osu.Game.Rulesets.Osu.Tests
private double maxBaseScore; private double maxBaseScore;
private int currentHits; private int currentHits;
private readonly double modMultiplier;
private readonly double comboPortionMax; private readonly double comboPortionMax;
private readonly int maxCombo; private readonly int maxCombo;
public ScoreV2(int maxCombo) public ScoreV2(int maxCombo, IReadOnlyList<Mod> selectedMods)
{ {
this.maxCombo = maxCombo; 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++) for (int i = 0; i < this.maxCombo; i++)
ApplyHit(); ApplyHit();
@ -152,18 +184,18 @@ namespace osu.Game.Rulesets.Osu.Tests
double accuracy = currentBaseScore / maxBaseScore; double accuracy = currentBaseScore / maxBaseScore;
return (int)Math.Round return (int)Math.Round
( ((
700000 * comboPortion / comboPortionMax + 700000 * comboPortion / comboPortionMax +
300000 * Math.Pow(accuracy, 10) * ((double)currentHits / maxCombo) 300000 * Math.Pow(accuracy, 10) * ((double)currentHits / maxCombo)
); ) * modMultiplier);
} }
} }
} }
private class OsuProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm private class OsuProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm
{ {
public OsuProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode) public OsuProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList<Mod> selectedMods)
: base(beatmap, mode) : base(beatmap, mode, selectedMods)
{ {
} }

View File

@ -2,11 +2,15 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Scoring.Legacy;
using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Beatmaps;
using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Judgements;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
@ -32,10 +36,17 @@ namespace osu.Game.Rulesets.Taiko.Tests
return beatmap; return beatmap;
} }
protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1 { ScoreMultiplier = { BindTarget = scoreMultiplier } }; protected override IScoringAlgorithm CreateScoreV1(IReadOnlyList<Mod> selectedMods)
protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); => new ScoreV1(selectedMods)
{
ScoreMultiplier = { BindTarget = scoreMultiplier }
};
protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode) => new TaikoProcessorBasedScoringAlgorithm(beatmap, mode); protected override IScoringAlgorithm CreateScoreV2(int maxCombo, IReadOnlyList<Mod> selectedMods)
=> new ScoreV2(maxCombo, selectedMods);
protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList<Mod> selectedMods)
=> new TaikoProcessorBasedScoringAlgorithm(beatmap, mode, selectedMods);
[Test] [Test]
public void TestBasicScenarios() public void TestBasicScenarios()
@ -72,8 +83,19 @@ namespace osu.Game.Rulesets.Taiko.Tests
private class ScoreV1 : IScoringAlgorithm private class ScoreV1 : IScoringAlgorithm
{ {
private readonly double modMultiplier;
private int currentCombo; private int currentCombo;
public ScoreV1(IReadOnlyList<Mod> selectedMods)
{
var ruleset = new TaikoRuleset();
modMultiplier = ruleset.CreateLegacyScoreSimulator().GetLegacyScoreMultiplier(selectedMods, new LegacyBeatmapConversionDifficultyInfo
{
SourceRuleset = ruleset.RulesetInfo
});
}
public BindableDouble ScoreMultiplier { get; } = new BindableDouble(); public BindableDouble ScoreMultiplier { get; } = new BindableDouble();
public void ApplyHit() => applyHitV1(base_great); public void ApplyHit() => applyHitV1(base_great);
@ -94,7 +116,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
// combo multiplier // combo multiplier
// ReSharper disable once PossibleLossOfFraction // 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++; currentCombo++;
} }
@ -110,15 +132,24 @@ namespace osu.Game.Rulesets.Taiko.Tests
private double maxBaseScore; private double maxBaseScore;
private int currentHits; private int currentHits;
private readonly double modMultiplier;
private readonly double comboPortionMax; private readonly double comboPortionMax;
private readonly int maxCombo; private readonly int maxCombo;
private const double combo_base = 4; private const double combo_base = 4;
public ScoreV2(int maxCombo) public ScoreV2(int maxCombo, IReadOnlyList<Mod> selectedMods)
{ {
this.maxCombo = maxCombo; 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++) for (int i = 0; i < this.maxCombo; i++)
ApplyHit(); ApplyHit();
@ -161,18 +192,18 @@ namespace osu.Game.Rulesets.Taiko.Tests
double accuracy = currentBaseScore / maxBaseScore; double accuracy = currentBaseScore / maxBaseScore;
return (int)Math.Round return (int)Math.Round
( ((
250000 * comboPortion / comboPortionMax + 250000 * comboPortion / comboPortionMax +
750000 * Math.Pow(accuracy, 3.6) * ((double)currentHits / maxCombo) 750000 * Math.Pow(accuracy, 3.6) * ((double)currentHits / maxCombo)
); ) * modMultiplier);
} }
} }
} }
private class TaikoProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm private class TaikoProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm
{ {
public TaikoProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode) public TaikoProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList<Mod> selectedMods)
: base(beatmap, mode) : base(beatmap, mode, selectedMods)
{ {
} }

View File

@ -18,8 +18,12 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; 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.Overlays.Settings;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring.Legacy; using osu.Game.Scoring.Legacy;
using osuTK; using osuTK;
@ -32,9 +36,9 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
protected abstract IBeatmap CreateBeatmap(int maxCombo); protected abstract IBeatmap CreateBeatmap(int maxCombo);
protected abstract IScoringAlgorithm CreateScoreV1(); protected abstract IScoringAlgorithm CreateScoreV1(IReadOnlyList<Mod> selectedMods);
protected abstract IScoringAlgorithm CreateScoreV2(int maxCombo); protected abstract IScoringAlgorithm CreateScoreV2(int maxCombo, IReadOnlyList<Mod> selectedMods);
protected abstract ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode); protected abstract ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList<Mod> mods);
protected Bindable<int> MaxCombo => sliderMaxCombo.Current; protected Bindable<int> MaxCombo => sliderMaxCombo.Current;
protected BindableList<double> NonPerfectLocations => graphs.NonPerfectLocations; protected BindableList<double> NonPerfectLocations => graphs.NonPerfectLocations;
@ -53,6 +57,10 @@ namespace osu.Game.Tests.Visual.Gameplay
private readonly BindableBool scoreV1Visible = new BindableBool(true); private readonly BindableBool scoreV1Visible = new BindableBool(true);
private readonly BindableBool scoreV2Visible = new BindableBool(true); private readonly BindableBool scoreV2Visible = new BindableBool(true);
private RoundedButton changeModsButton = null!;
private OsuSpriteText modsText = null!;
private TestModSelectOverlay modSelect = null!;
[Resolved] [Resolved]
private OsuColour colours { get; set; } = null!; private OsuColour colours { get; set; } = null!;
@ -83,6 +91,7 @@ namespace osu.Game.Tests.Visual.Gameplay
new Dimension(), new Dimension(),
new Dimension(GridSizeMode.AutoSize), new Dimension(GridSizeMode.AutoSize),
new Dimension(GridSizeMode.AutoSize), new Dimension(GridSizeMode.AutoSize),
new Dimension(GridSizeMode.AutoSize),
}, },
Content = new[] Content = new[]
{ {
@ -104,6 +113,47 @@ namespace osu.Game.Tests.Visual.Gameplay
}, },
}, },
new Drawable[] 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 new FillFlowContainer
{ {
@ -139,6 +189,11 @@ namespace osu.Game.Tests.Visual.Gameplay
}, },
}, },
} }
},
modSelect = new TestModSelectOverlay
{
RelativeSizeAxes = Axes.Both,
SelectedMods = { BindTarget = SelectedMods }
} }
}; };
@ -159,6 +214,9 @@ namespace osu.Game.Tests.Visual.Gameplay
graphs.MaxCombo.BindTo(sliderMaxCombo.Current); graphs.MaxCombo.BindTo(sliderMaxCombo.Current);
changeModsButton.Action = () => modSelect.Show();
SelectedMods.BindValueChanged(mods => Rerun());
Rerun(); Rerun();
}); });
} }
@ -168,6 +226,10 @@ namespace osu.Game.Tests.Visual.Gameplay
graphs.Clear(); graphs.Clear();
legend.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-standardised", colours.Green1, ScoringMode.Standardised, standardisedVisible);
runForProcessor("lazer-classic", colours.Blue1, ScoringMode.Classic, classicVisible); runForProcessor("lazer-classic", colours.Blue1, ScoringMode.Classic, classicVisible);
@ -175,14 +237,14 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
Name = "ScoreV1 (classic)", Name = "ScoreV1 (classic)",
Colour = colours.Purple1, Colour = colours.Purple1,
Algorithm = CreateScoreV1(), Algorithm = CreateScoreV1(SelectedMods.Value),
Visible = scoreV1Visible Visible = scoreV1Visible
}); });
runForAlgorithm(new ScoringAlgorithmInfo runForAlgorithm(new ScoringAlgorithmInfo
{ {
Name = "ScoreV2", Name = "ScoreV2",
Colour = colours.Red1, Colour = colours.Red1,
Algorithm = CreateScoreV2(sliderMaxCombo.Current.Value), Algorithm = CreateScoreV2(sliderMaxCombo.Current.Value, SelectedMods.Value),
Visible = scoreV2Visible Visible = scoreV2Visible
}); });
@ -209,7 +271,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
int maxCombo = sliderMaxCombo.Current.Value; int maxCombo = sliderMaxCombo.Current.Value;
var beatmap = CreateBeatmap(maxCombo); var beatmap = CreateBeatmap(maxCombo);
var algorithm = CreateScoreAlgorithm(beatmap, scoringMode); var algorithm = CreateScoreAlgorithm(beatmap, scoringMode, SelectedMods.Value);
runForAlgorithm(new ScoringAlgorithmInfo runForAlgorithm(new ScoringAlgorithmInfo
{ {
@ -282,11 +344,12 @@ namespace osu.Game.Tests.Visual.Gameplay
private readonly ScoreProcessor scoreProcessor; private readonly ScoreProcessor scoreProcessor;
private readonly ScoringMode mode; private readonly ScoringMode mode;
protected ProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode) protected ProcessorBasedScoringAlgorithm(IBeatmap beatmap, ScoringMode mode, IReadOnlyList<Mod> selectedMods)
{ {
this.mode = mode; this.mode = mode;
scoreProcessor = CreateScoreProcessor(); scoreProcessor = CreateScoreProcessor();
scoreProcessor.ApplyBeatmap(beatmap); scoreProcessor.ApplyBeatmap(beatmap);
scoreProcessor.Mods.Value = selectedMods;
} }
public void ApplyHit() => scoreProcessor.ApplyResult(CreatePerfectJudgementResult()); public void ApplyHit() => scoreProcessor.ApplyResult(CreatePerfectJudgementResult());
@ -592,5 +655,16 @@ namespace osu.Game.Tests.Visual.Gameplay
lineGraph.Alpha = Visible.Value ? 1 : 0; 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)
{
}
}
} }
} }