mirror of
https://github.com/ppy/osu.git
synced 2026-05-16 14:23:22 +08:00
Merge pull request #34432 from bdach/unified-beatmap-attribute-display
Unify display logic of beatmap difficulty attributes across usages
This commit is contained in:
@@ -22,8 +22,9 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
var ruleset = new CatchRuleset();
|
||||
var difficulty = new BeatmapDifficulty { ApproachRate = originalApproachRate };
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, []);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, []);
|
||||
|
||||
Assert.That(adjustedDifficulty.ApproachRate, Is.EqualTo(originalApproachRate));
|
||||
}
|
||||
@@ -33,8 +34,9 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
var ruleset = new CatchRuleset();
|
||||
var difficulty = new BeatmapDifficulty();
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, [new CatchModHalfTime()]);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, [new CatchModHalfTime()]);
|
||||
|
||||
Assert.That(adjustedDifficulty.ApproachRate, Is.EqualTo(1.67).Within(0.01));
|
||||
}
|
||||
@@ -44,8 +46,9 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
var ruleset = new CatchRuleset();
|
||||
var difficulty = new BeatmapDifficulty();
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, [new CatchModDoubleTime()]);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, [new CatchModDoubleTime()]);
|
||||
|
||||
Assert.That(adjustedDifficulty.ApproachRate, Is.EqualTo(7.67).Within(0.01));
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Rulesets.Catch.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Difficulty;
|
||||
using osu.Game.Rulesets.Catch.Edit;
|
||||
@@ -267,9 +268,9 @@ namespace osu.Game.Rulesets.Catch
|
||||
}
|
||||
|
||||
/// <seealso cref="CatchHitObject.ApplyDefaultsToSelf"/>
|
||||
public override BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapDifficultyInfo difficulty, IReadOnlyCollection<Mod> mods)
|
||||
public override BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
BeatmapDifficulty adjustedDifficulty = new BeatmapDifficulty(difficulty);
|
||||
BeatmapDifficulty adjustedDifficulty = base.GetAdjustedDisplayDifficulty(beatmapInfo, mods);
|
||||
double rate = ModUtils.CalculateRateWithMods(mods);
|
||||
|
||||
double preempt = IBeatmapDifficultyInfo.DifficultyRange(adjustedDifficulty.ApproachRate, CatchHitObject.PREEMPT_MAX, CatchHitObject.PREEMPT_MID, CatchHitObject.PREEMPT_MIN);
|
||||
@@ -279,6 +280,16 @@ namespace osu.Game.Rulesets.Catch
|
||||
return adjustedDifficulty;
|
||||
}
|
||||
|
||||
public override IEnumerable<RulesetBeatmapAttribute> GetBeatmapAttributesForDisplay(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
var originalDifficulty = beatmapInfo.Difficulty;
|
||||
var adjustedDifficulty = GetAdjustedDisplayDifficulty(beatmapInfo, mods);
|
||||
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.CircleSize, @"CS", originalDifficulty.CircleSize, adjustedDifficulty.CircleSize, 10);
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.ApproachRate, @"AR", originalDifficulty.ApproachRate, adjustedDifficulty.ApproachRate, 10);
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.HPDrain, @"HP", originalDifficulty.DrainRate, adjustedDifficulty.DrainRate, 10);
|
||||
}
|
||||
|
||||
public override bool EditorShowScrollSpeed => false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetColumnCount(LegacyBeatmapConversionDifficultyInfo difficulty, IReadOnlyList<Mod>? mods = null)
|
||||
public static int GetColumnCount(LegacyBeatmapConversionDifficultyInfo difficulty, IReadOnlyCollection<Mod>? mods = null)
|
||||
{
|
||||
var converter = new ManiaBeatmapConverter(null, difficulty, new ManiaRuleset());
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Configuration;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
@@ -415,9 +416,9 @@ namespace osu.Game.Rulesets.Mania
|
||||
};
|
||||
|
||||
/// <seealso cref="ManiaHitWindows"/>
|
||||
public override BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapDifficultyInfo difficulty, IReadOnlyCollection<Mod> mods)
|
||||
public override BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
BeatmapDifficulty adjustedDifficulty = new BeatmapDifficulty(difficulty);
|
||||
BeatmapDifficulty adjustedDifficulty = base.GetAdjustedDisplayDifficulty(beatmapInfo, mods);
|
||||
|
||||
// notably, in mania, hit windows are designed to be independent of track playback rate (see `ManiaHitWindows.SpeedMultiplier`).
|
||||
// *however*, to not make matters *too* simple, mania Hard Rock and Easy differ from all other rulesets
|
||||
@@ -436,10 +437,25 @@ namespace osu.Game.Rulesets.Mania
|
||||
perfectHitWindow /= ManiaModEasy.HIT_WINDOW_DIFFICULTY_MULTIPLIER;
|
||||
|
||||
adjustedDifficulty.OverallDifficulty = (float)IBeatmapDifficultyInfo.InverseDifficultyRange(perfectHitWindow, ManiaHitWindows.PERFECT_WINDOW_RANGE);
|
||||
adjustedDifficulty.CircleSize = ManiaBeatmapConverter.GetColumnCount(LegacyBeatmapConversionDifficultyInfo.FromBeatmapInfo(beatmapInfo), mods);
|
||||
|
||||
return adjustedDifficulty;
|
||||
}
|
||||
|
||||
public override IEnumerable<RulesetBeatmapAttribute> GetBeatmapAttributesForDisplay(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
// a special touch-up of key count is required to the original difficulty, since key conversion mods are not `IApplicableToDifficulty`
|
||||
var originalDifficulty = new BeatmapDifficulty(beatmapInfo.Difficulty)
|
||||
{
|
||||
CircleSize = ManiaBeatmapConverter.GetColumnCount(LegacyBeatmapConversionDifficultyInfo.FromBeatmapInfo(beatmapInfo), [])
|
||||
};
|
||||
var adjustedDifficulty = GetAdjustedDisplayDifficulty(beatmapInfo, mods);
|
||||
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.KeyCount, @"KC", originalDifficulty.CircleSize, adjustedDifficulty.CircleSize, 18);
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.Accuracy, @"OD", originalDifficulty.OverallDifficulty, adjustedDifficulty.OverallDifficulty, 10);
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.HPDrain, @"HP", originalDifficulty.DrainRate, adjustedDifficulty.DrainRate, 10);
|
||||
}
|
||||
|
||||
public override IRulesetFilterCriteria CreateRulesetFilterCriteria()
|
||||
{
|
||||
return new ManiaFilterCriteria();
|
||||
|
||||
@@ -22,8 +22,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
var ruleset = new OsuRuleset();
|
||||
var difficulty = new BeatmapDifficulty { ApproachRate = originalApproachRate };
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, []);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, []);
|
||||
|
||||
Assert.That(adjustedDifficulty.ApproachRate, Is.EqualTo(originalApproachRate));
|
||||
}
|
||||
@@ -33,8 +34,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
var ruleset = new OsuRuleset();
|
||||
var difficulty = new BeatmapDifficulty { OverallDifficulty = originalOverallDifficulty };
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, []);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, []);
|
||||
|
||||
Assert.That(adjustedDifficulty.OverallDifficulty, Is.EqualTo(originalOverallDifficulty));
|
||||
}
|
||||
@@ -44,8 +46,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
var ruleset = new OsuRuleset();
|
||||
var difficulty = new BeatmapDifficulty();
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, [new OsuModHalfTime()]);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, [new OsuModHalfTime()]);
|
||||
|
||||
Assert.That(adjustedDifficulty.ApproachRate, Is.EqualTo(1.67).Within(0.01));
|
||||
Assert.That(adjustedDifficulty.OverallDifficulty, Is.EqualTo(2.22).Within(0.01));
|
||||
@@ -56,8 +59,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
var ruleset = new OsuRuleset();
|
||||
var difficulty = new BeatmapDifficulty();
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, [new OsuModDoubleTime()]);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, [new OsuModDoubleTime()]);
|
||||
|
||||
Assert.That(adjustedDifficulty.ApproachRate, Is.EqualTo(7.67).Within(0.01));
|
||||
Assert.That(adjustedDifficulty.OverallDifficulty, Is.EqualTo(7.77).Within(0.01));
|
||||
|
||||
@@ -366,9 +366,9 @@ namespace osu.Game.Rulesets.Osu
|
||||
|
||||
/// <seealso cref="OsuHitObject.ApplyDefaultsToSelf"/>
|
||||
/// <seealso cref="OsuHitWindows"/>
|
||||
public override BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapDifficultyInfo difficulty, IReadOnlyCollection<Mod> mods)
|
||||
public override BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapInfo difficulty, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
BeatmapDifficulty adjustedDifficulty = new BeatmapDifficulty(difficulty);
|
||||
BeatmapDifficulty adjustedDifficulty = base.GetAdjustedDisplayDifficulty(difficulty, mods);
|
||||
double rate = ModUtils.CalculateRateWithMods(mods);
|
||||
|
||||
double preempt = IBeatmapDifficultyInfo.DifficultyRange(adjustedDifficulty.ApproachRate, OsuHitObject.PREEMPT_MAX, OsuHitObject.PREEMPT_MID, OsuHitObject.PREEMPT_MIN);
|
||||
|
||||
@@ -22,8 +22,9 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
var ruleset = new TaikoRuleset();
|
||||
var difficulty = new BeatmapDifficulty { OverallDifficulty = originalOverallDifficulty };
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, []);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, []);
|
||||
|
||||
Assert.That(adjustedDifficulty.OverallDifficulty, Is.EqualTo(originalOverallDifficulty));
|
||||
}
|
||||
@@ -33,8 +34,9 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
var ruleset = new TaikoRuleset();
|
||||
var difficulty = new BeatmapDifficulty();
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, [new TaikoModHalfTime()]);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, [new TaikoModHalfTime()]);
|
||||
|
||||
Assert.That(adjustedDifficulty.OverallDifficulty, Is.EqualTo(1.11).Within(0.01));
|
||||
}
|
||||
@@ -44,8 +46,9 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
var ruleset = new TaikoRuleset();
|
||||
var difficulty = new BeatmapDifficulty();
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, [new TaikoModDoubleTime()]);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, [new TaikoModDoubleTime()]);
|
||||
|
||||
Assert.That(adjustedDifficulty.OverallDifficulty, Is.EqualTo(8.89).Within(0.01));
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ using osu.Game.Screens.Ranking.Statistics;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Rulesets.Configuration;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Rulesets.Scoring.Legacy;
|
||||
using osu.Game.Rulesets.Taiko.Configuration;
|
||||
using osu.Game.Rulesets.Taiko.Edit.Setup;
|
||||
@@ -271,9 +272,9 @@ namespace osu.Game.Rulesets.Taiko
|
||||
}
|
||||
|
||||
/// <seealso cref="TaikoHitWindows"/>
|
||||
public override BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapDifficultyInfo difficulty, IReadOnlyCollection<Mod> mods)
|
||||
public override BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
BeatmapDifficulty adjustedDifficulty = new BeatmapDifficulty(difficulty);
|
||||
BeatmapDifficulty adjustedDifficulty = base.GetAdjustedDisplayDifficulty(beatmapInfo, mods);
|
||||
double rate = ModUtils.CalculateRateWithMods(mods);
|
||||
|
||||
double greatHitWindow = IBeatmapDifficultyInfo.DifficultyRange(adjustedDifficulty.OverallDifficulty, TaikoHitWindows.GREAT_WINDOW_RANGE);
|
||||
@@ -282,5 +283,15 @@ namespace osu.Game.Rulesets.Taiko
|
||||
|
||||
return adjustedDifficulty;
|
||||
}
|
||||
|
||||
public override IEnumerable<RulesetBeatmapAttribute> GetBeatmapAttributesForDisplay(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
var originalDifficulty = beatmapInfo.Difficulty;
|
||||
var adjustedDifficulty = GetAdjustedDisplayDifficulty(beatmapInfo, mods);
|
||||
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.Accuracy, @"OD", originalDifficulty.OverallDifficulty, adjustedDifficulty.OverallDifficulty, 10);
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.HPDrain, @"HP", originalDifficulty.DrainRate, adjustedDifficulty.DrainRate, 10);
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.ScrollSpeed, @"SS", 1f, (float)(adjustedDifficulty.SliderMultiplier / originalDifficulty.SliderMultiplier), 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,11 @@ using Newtonsoft.Json.Linq;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays.BeatmapSet.Scores;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.Select.Details;
|
||||
@@ -274,7 +274,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
public void TestSelectedModsDontAffectStatistics()
|
||||
{
|
||||
AddStep("show map", () => overlay.ShowBeatmapSet(getBeatmapSet()));
|
||||
AddAssert("AR displayed as 0", () => overlay.ChildrenOfType<AdvancedStats.StatisticRow>().Single(s => s.Title == BeatmapsetsStrings.ShowStatsAr).Value, () => Is.EqualTo((0, 0)));
|
||||
AddAssert("AR displayed as 0", () => overlay.ChildrenOfType<AdvancedStats.StatisticRow>().Single(s => s.Title == SongSelectStrings.ApproachRate).Value, () => Is.EqualTo((0, 0)));
|
||||
AddStep("set AR10 diff adjust", () => SelectedMods.Value = new[]
|
||||
{
|
||||
new OsuModDifficultyAdjust
|
||||
@@ -282,7 +282,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
ApproachRate = { Value = 10 }
|
||||
}
|
||||
});
|
||||
AddAssert("AR still displayed as 0", () => overlay.ChildrenOfType<AdvancedStats.StatisticRow>().Single(s => s.Title == BeatmapsetsStrings.ShowStatsAr).Value, () => Is.EqualTo((0, 0)));
|
||||
AddAssert("AR still displayed as 0", () => overlay.ChildrenOfType<AdvancedStats.StatisticRow>().Single(s => s.Title == SongSelectStrings.ApproachRate).Value, () => Is.EqualTo((0, 0)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -8,11 +8,10 @@ using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@@ -42,7 +41,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
|
||||
private BeatmapInfo exampleBeatmapInfo => new BeatmapInfo
|
||||
{
|
||||
Ruleset = rulesets.AvailableRulesets.First(),
|
||||
Ruleset = rulesets.GetRuleset(0)!,
|
||||
Difficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 7.2f,
|
||||
@@ -56,30 +55,39 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
[Test]
|
||||
public void TestNoMod()
|
||||
{
|
||||
AddStep("set beatmap", () => advancedStats.BeatmapInfo = exampleBeatmapInfo);
|
||||
AddStep("set beatmap and ruleset", () =>
|
||||
{
|
||||
advancedStats.BeatmapInfo = exampleBeatmapInfo;
|
||||
advancedStats.Ruleset.Value = exampleBeatmapInfo.Ruleset;
|
||||
});
|
||||
|
||||
AddStep("no mods selected", () => SelectedMods.Value = Array.Empty<Mod>());
|
||||
|
||||
AddAssert("first bar text is correct", () => advancedStats.ChildrenOfType<SpriteText>().First().Text == BeatmapsetsStrings.ShowStatsCs);
|
||||
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue));
|
||||
AddAssert("HP drain bar is white", () => barIsWhite(advancedStats.HpDrain));
|
||||
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy));
|
||||
AddAssert("approach rate bar is white", () => barIsWhite(advancedStats.ApproachRate));
|
||||
AddAssert("first bar text is correct", () => advancedStats.GetStatistic(SongSelectStrings.CircleSize), () => Is.Not.Null);
|
||||
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.GetStatistic(SongSelectStrings.CircleSize)));
|
||||
AddAssert("HP drain bar is white", () => barIsWhite(advancedStats.GetStatistic(SongSelectStrings.HPDrain)));
|
||||
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.GetStatistic(SongSelectStrings.Accuracy)));
|
||||
AddAssert("approach rate bar is white", () => barIsWhite(advancedStats.GetStatistic(SongSelectStrings.ApproachRate)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFirstBarText()
|
||||
{
|
||||
AddStep("set beatmap", () => advancedStats.BeatmapInfo = exampleBeatmapInfo);
|
||||
AddStep("set ruleset to mania", () => advancedStats.Ruleset.Value = new ManiaRuleset().RulesetInfo);
|
||||
AddAssert("first bar text is correct", () => advancedStats.ChildrenOfType<SpriteText>().First().Text == BeatmapsetsStrings.ShowStatsCsMania);
|
||||
AddAssert("first bar text is correct", () => advancedStats.GetStatistic(SongSelectStrings.KeyCount), () => Is.Not.Null);
|
||||
AddStep("set ruleset to osu", () => advancedStats.Ruleset.Value = new OsuRuleset().RulesetInfo);
|
||||
AddAssert("first bar text is correct", () => advancedStats.ChildrenOfType<SpriteText>().First().Text == BeatmapsetsStrings.ShowStatsCs);
|
||||
AddAssert("first bar text is correct", () => advancedStats.GetStatistic(SongSelectStrings.CircleSize), () => Is.Not.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEasyMod()
|
||||
{
|
||||
AddStep("set beatmap", () => advancedStats.BeatmapInfo = exampleBeatmapInfo);
|
||||
AddStep("set beatmap and ruleset", () =>
|
||||
{
|
||||
advancedStats.BeatmapInfo = exampleBeatmapInfo;
|
||||
advancedStats.Ruleset.Value = exampleBeatmapInfo.Ruleset;
|
||||
});
|
||||
|
||||
AddStep("select EZ mod", () =>
|
||||
{
|
||||
@@ -87,16 +95,20 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
advancedStats.Mods.Value = new[] { ruleset.CreateMod<ModEasy>() };
|
||||
});
|
||||
|
||||
AddAssert("circle size bar is blue", () => barIsBlue(advancedStats.FirstValue));
|
||||
AddAssert("HP drain bar is blue", () => barIsBlue(advancedStats.HpDrain));
|
||||
AddAssert("accuracy bar is blue", () => barIsBlue(advancedStats.Accuracy));
|
||||
AddAssert("approach rate bar is blue", () => barIsBlue(advancedStats.ApproachRate));
|
||||
AddAssert("circle size bar is blue", () => barIsBlue(advancedStats.GetStatistic(SongSelectStrings.CircleSize)));
|
||||
AddAssert("HP drain bar is blue", () => barIsBlue(advancedStats.GetStatistic(SongSelectStrings.HPDrain)));
|
||||
AddAssert("accuracy bar is blue", () => barIsBlue(advancedStats.GetStatistic(SongSelectStrings.Accuracy)));
|
||||
AddAssert("approach rate bar is blue", () => barIsBlue(advancedStats.GetStatistic(SongSelectStrings.ApproachRate)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHardRockMod()
|
||||
{
|
||||
AddStep("set beatmap", () => advancedStats.BeatmapInfo = exampleBeatmapInfo);
|
||||
AddStep("set beatmap and ruleset", () =>
|
||||
{
|
||||
advancedStats.BeatmapInfo = exampleBeatmapInfo;
|
||||
advancedStats.Ruleset.Value = exampleBeatmapInfo.Ruleset;
|
||||
});
|
||||
|
||||
AddStep("select HR mod", () =>
|
||||
{
|
||||
@@ -104,16 +116,20 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
advancedStats.Mods.Value = new[] { ruleset.CreateMod<ModHardRock>() };
|
||||
});
|
||||
|
||||
AddAssert("circle size bar is red", () => barIsRed(advancedStats.FirstValue));
|
||||
AddAssert("HP drain bar is red", () => barIsRed(advancedStats.HpDrain));
|
||||
AddAssert("accuracy bar is red", () => barIsRed(advancedStats.Accuracy));
|
||||
AddAssert("approach rate bar is red", () => barIsRed(advancedStats.ApproachRate));
|
||||
AddAssert("circle size bar is red", () => barIsRed(advancedStats.GetStatistic(SongSelectStrings.CircleSize)));
|
||||
AddAssert("HP drain bar is red", () => barIsRed(advancedStats.GetStatistic(SongSelectStrings.HPDrain)));
|
||||
AddAssert("accuracy bar is red", () => barIsRed(advancedStats.GetStatistic(SongSelectStrings.Accuracy)));
|
||||
AddAssert("approach rate bar is red", () => barIsRed(advancedStats.GetStatistic(SongSelectStrings.ApproachRate)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUnchangedDifficultyAdjustMod()
|
||||
{
|
||||
AddStep("set beatmap", () => advancedStats.BeatmapInfo = exampleBeatmapInfo);
|
||||
AddStep("set beatmap and ruleset", () =>
|
||||
{
|
||||
advancedStats.BeatmapInfo = exampleBeatmapInfo;
|
||||
advancedStats.Ruleset.Value = exampleBeatmapInfo.Ruleset;
|
||||
});
|
||||
|
||||
AddStep("select unchanged Difficulty Adjust mod", () =>
|
||||
{
|
||||
@@ -122,16 +138,20 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
advancedStats.Mods.Value = new[] { difficultyAdjustMod };
|
||||
});
|
||||
|
||||
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue));
|
||||
AddAssert("HP drain bar is white", () => barIsWhite(advancedStats.HpDrain));
|
||||
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy));
|
||||
AddAssert("approach rate bar is white", () => barIsWhite(advancedStats.ApproachRate));
|
||||
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.GetStatistic(SongSelectStrings.CircleSize)));
|
||||
AddAssert("HP drain bar is white", () => barIsWhite(advancedStats.GetStatistic(SongSelectStrings.HPDrain)));
|
||||
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.GetStatistic(SongSelectStrings.Accuracy)));
|
||||
AddAssert("approach rate bar is white", () => barIsWhite(advancedStats.GetStatistic(SongSelectStrings.ApproachRate)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestChangedDifficultyAdjustMod()
|
||||
{
|
||||
AddStep("set beatmap", () => advancedStats.BeatmapInfo = exampleBeatmapInfo);
|
||||
AddStep("set beatmap and ruleset", () =>
|
||||
{
|
||||
advancedStats.BeatmapInfo = exampleBeatmapInfo;
|
||||
advancedStats.Ruleset.Value = exampleBeatmapInfo.Ruleset;
|
||||
});
|
||||
|
||||
AddStep("select changed Difficulty Adjust mod", () =>
|
||||
{
|
||||
@@ -144,10 +164,10 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
advancedStats.Mods.Value = new[] { difficultyAdjustMod };
|
||||
});
|
||||
|
||||
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue));
|
||||
AddAssert("drain rate bar is blue", () => barIsBlue(advancedStats.HpDrain));
|
||||
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy));
|
||||
AddAssert("approach rate bar is red", () => barIsRed(advancedStats.ApproachRate));
|
||||
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.GetStatistic(SongSelectStrings.CircleSize)));
|
||||
AddAssert("drain rate bar is blue", () => barIsBlue(advancedStats.GetStatistic(SongSelectStrings.HPDrain)));
|
||||
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.GetStatistic(SongSelectStrings.Accuracy)));
|
||||
AddAssert("approach rate bar is red", () => barIsRed(advancedStats.GetStatistic(SongSelectStrings.ApproachRate)));
|
||||
}
|
||||
|
||||
private bool barIsWhite(AdvancedStats.StatisticRow row) => row.ModBar.AccentColour == Color4.White;
|
||||
@@ -156,10 +176,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
|
||||
private partial class TestAdvancedStats : AdvancedStats
|
||||
{
|
||||
public new StatisticRow FirstValue => base.FirstValue;
|
||||
public new StatisticRow HpDrain => base.HpDrain;
|
||||
public new StatisticRow Accuracy => base.Accuracy;
|
||||
public new StatisticRow ApproachRate => base.ApproachRate;
|
||||
public StatisticRow GetStatistic(LocalisableString title) => Flow.OfType<StatisticRow>().SingleOrDefault(row => row.Title == title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,9 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
selectBeatmap(null);
|
||||
AddAssert("check default title", () => titleWedge.DisplayedTitle == Beatmap.Default.BeatmapInfo.Metadata.Title);
|
||||
AddAssert("check default artist", () => titleWedge.DisplayedArtist == Beatmap.Default.BeatmapInfo.Metadata.Artist);
|
||||
AddAssert("check no statistics", () => difficultyDisplay.ChildrenOfType<BeatmapTitleWedge.DifficultyStatisticsDisplay>().All(d => !d.Statistics.Any()));
|
||||
AddAssert("statistics not visible",
|
||||
() => difficultyDisplay.ChildrenOfType<BeatmapTitleWedge.DifficultyStatisticsDisplay>()
|
||||
.All(d => d.Alpha == 0 || d.ChildrenOfType<BeatmapTitleWedge.StatisticDifficulty>().All(s => s.Alpha == 0)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -23,10 +23,6 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
private OsuSpriteText difficultyName = null!;
|
||||
private StarRatingDisplay starRating = null!;
|
||||
private OsuSpriteText overallDifficulty = null!;
|
||||
private OsuSpriteText drainRate = null!;
|
||||
private OsuSpriteText circleSize = null!;
|
||||
private OsuSpriteText approachRate = null!;
|
||||
private OsuSpriteText bpm = null!;
|
||||
private OsuSpriteText length = null!;
|
||||
|
||||
@@ -76,13 +72,6 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
circleSize = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) },
|
||||
drainRate = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) },
|
||||
overallDifficulty = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) },
|
||||
approachRate = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) },
|
||||
}
|
||||
},
|
||||
miscFillFlowContainer = new FillFlowContainer
|
||||
{
|
||||
@@ -131,21 +120,16 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
|
||||
double bpmAdjusted = displayedContent.BeatmapInfo.BPM * rate;
|
||||
|
||||
BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(displayedContent.BeatmapInfo.Difficulty);
|
||||
|
||||
if (displayedContent.Mods != null)
|
||||
{
|
||||
foreach (var mod in displayedContent.Mods.OfType<IApplicableToDifficulty>())
|
||||
mod.ApplyToDifficulty(originalDifficulty);
|
||||
}
|
||||
|
||||
Ruleset ruleset = displayedContent.Ruleset.CreateInstance();
|
||||
BeatmapDifficulty adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(originalDifficulty, displayedContent.Mods ?? []);
|
||||
var beatmapAttributes = ruleset.GetBeatmapAttributesForDisplay(displayedContent.BeatmapInfo, displayedContent.Mods ?? [])
|
||||
.Select(attr => new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.Style.Caption1,
|
||||
Text = $@"{attr.Acronym}: {attr.AdjustedValue:0.##}"
|
||||
});
|
||||
|
||||
circleSize.Text = @"CS: " + adjustedDifficulty.CircleSize.ToString(@"0.##");
|
||||
drainRate.Text = @" HP: " + adjustedDifficulty.DrainRate.ToString(@"0.##");
|
||||
approachRate.Text = @" AR: " + adjustedDifficulty.ApproachRate.ToString(@"0.##");
|
||||
overallDifficulty.Text = @" OD: " + adjustedDifficulty.OverallDifficulty.ToString(@"0.##");
|
||||
difficultyFillFlowContainer.Clear();
|
||||
difficultyFillFlowContainer.AddRange(beatmapAttributes);
|
||||
|
||||
TimeSpan lengthTimeSpan = TimeSpan.FromMilliseconds(displayedContent.BeatmapInfo.Length / rate);
|
||||
length.Text = "Length: " + lengthTimeSpan.ToFormattedDuration();
|
||||
|
||||
@@ -79,6 +79,11 @@ namespace osu.Game.Localisation
|
||||
/// </summary>
|
||||
public static LocalisableString HPDrain => new TranslatableString(getKey(@"hp_drain"), @"HP Drain");
|
||||
|
||||
/// <summary>
|
||||
/// "Scroll Speed"
|
||||
/// </summary>
|
||||
public static LocalisableString ScrollSpeed => new TranslatableString(getKey(@"scroll_speed"), @"Scroll Speed");
|
||||
|
||||
/// <summary>
|
||||
/// "Submitted"
|
||||
/// </summary>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -9,9 +9,9 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Overlays.Mods
|
||||
@@ -84,25 +84,17 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
attemptAdd("CS", bd => bd.CircleSize);
|
||||
attemptAdd("AR", bd => bd.ApproachRate);
|
||||
attemptAdd("OD", bd => bd.OverallDifficulty);
|
||||
attemptAdd("HP", bd => bd.DrainRate);
|
||||
foreach (var attribute in data.Attributes)
|
||||
{
|
||||
if (!Precision.AlmostEquals(attribute.OriginalValue, attribute.AdjustedValue))
|
||||
attributesFillFlow.Add(new AttributeDisplay(attribute.Acronym, attribute.OriginalValue, attribute.AdjustedValue));
|
||||
}
|
||||
}
|
||||
|
||||
if (attributesFillFlow.Any())
|
||||
content.Show();
|
||||
else
|
||||
content.Hide();
|
||||
|
||||
void attemptAdd(string name, Func<BeatmapDifficulty, double> lookup)
|
||||
{
|
||||
double originalValue = lookup(data.OriginalDifficulty);
|
||||
double adjustedValue = lookup(data.AdjustedDifficulty);
|
||||
|
||||
if (!Precision.AlmostEquals(originalValue, adjustedValue))
|
||||
attributesFillFlow.Add(new AttributeDisplay(name, originalValue, adjustedValue));
|
||||
}
|
||||
}
|
||||
|
||||
public void SetContent(Data? data)
|
||||
@@ -121,13 +113,11 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
public class Data
|
||||
{
|
||||
public BeatmapDifficulty OriginalDifficulty { get; }
|
||||
public BeatmapDifficulty AdjustedDifficulty { get; }
|
||||
public IReadOnlyCollection<RulesetBeatmapAttribute> Attributes { get; }
|
||||
|
||||
public Data(BeatmapDifficulty originalDifficulty, BeatmapDifficulty adjustedDifficulty)
|
||||
public Data(IReadOnlyCollection<RulesetBeatmapAttribute> attributes)
|
||||
{
|
||||
OriginalDifficulty = originalDifficulty;
|
||||
AdjustedDifficulty = adjustedDifficulty;
|
||||
Attributes = attributes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,11 +32,6 @@ namespace osu.Game.Overlays.Mods
|
||||
private StarRatingDisplay starRatingDisplay = null!;
|
||||
private BPMDisplay bpmDisplay = null!;
|
||||
|
||||
private VerticalAttributeDisplay circleSizeDisplay = null!;
|
||||
private VerticalAttributeDisplay drainRateDisplay = null!;
|
||||
private VerticalAttributeDisplay approachRateDisplay = null!;
|
||||
private VerticalAttributeDisplay overallDifficultyDisplay = null!;
|
||||
|
||||
public Bindable<IBeatmapInfo?> BeatmapInfo { get; } = new Bindable<IBeatmapInfo?>();
|
||||
|
||||
public Bindable<IReadOnlyList<Mod>> Mods { get; } = new Bindable<IReadOnlyList<Mod>>();
|
||||
@@ -84,13 +79,6 @@ namespace osu.Game.Overlays.Mods
|
||||
});
|
||||
|
||||
RightContent.Alpha = 0;
|
||||
RightContent.AddRange(new Drawable[]
|
||||
{
|
||||
circleSizeDisplay = new VerticalAttributeDisplay("CS") { Shear = -OsuGame.SHEAR, },
|
||||
approachRateDisplay = new VerticalAttributeDisplay("AR") { Shear = -OsuGame.SHEAR, },
|
||||
overallDifficultyDisplay = new VerticalAttributeDisplay("OD") { Shear = -OsuGame.SHEAR, },
|
||||
drainRateDisplay = new VerticalAttributeDisplay("HP") { Shear = -OsuGame.SHEAR, },
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -173,26 +161,30 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
bpmDisplay.Current.Value = FormatUtils.RoundBPM(BeatmapInfo.Value.BPM, rate);
|
||||
|
||||
BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(BeatmapInfo.Value.Difficulty);
|
||||
BeatmapDifficulty adjustedDifficulty = new BeatmapDifficulty(originalDifficulty);
|
||||
|
||||
foreach (var mod in Mods.Value.OfType<IApplicableToDifficulty>())
|
||||
mod.ApplyToDifficulty(adjustedDifficulty);
|
||||
|
||||
Ruleset ruleset = GameRuleset.Value.CreateInstance();
|
||||
adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(adjustedDifficulty, Mods.Value);
|
||||
var displayAttributes = ruleset.GetBeatmapAttributesForDisplay(BeatmapInfo.Value, Mods.Value).ToList();
|
||||
|
||||
TooltipContent = new AdjustedAttributesTooltip.Data(originalDifficulty, adjustedDifficulty);
|
||||
TooltipContent = new AdjustedAttributesTooltip.Data(displayAttributes);
|
||||
|
||||
circleSizeDisplay.AdjustType.Value = VerticalAttributeDisplay.CalculateEffect(originalDifficulty.CircleSize, adjustedDifficulty.CircleSize);
|
||||
drainRateDisplay.AdjustType.Value = VerticalAttributeDisplay.CalculateEffect(originalDifficulty.DrainRate, adjustedDifficulty.DrainRate);
|
||||
approachRateDisplay.AdjustType.Value = VerticalAttributeDisplay.CalculateEffect(originalDifficulty.ApproachRate, adjustedDifficulty.ApproachRate);
|
||||
overallDifficultyDisplay.AdjustType.Value = VerticalAttributeDisplay.CalculateEffect(originalDifficulty.OverallDifficulty, adjustedDifficulty.OverallDifficulty);
|
||||
// if there are not enough attribute displays, make more
|
||||
for (int i = RightContent.Count; i < displayAttributes.Count; i++)
|
||||
RightContent.Add(new VerticalAttributeDisplay { Shear = -OsuGame.SHEAR });
|
||||
|
||||
circleSizeDisplay.Current.Value = adjustedDifficulty.CircleSize;
|
||||
drainRateDisplay.Current.Value = adjustedDifficulty.DrainRate;
|
||||
approachRateDisplay.Current.Value = adjustedDifficulty.ApproachRate;
|
||||
overallDifficultyDisplay.Current.Value = adjustedDifficulty.OverallDifficulty;
|
||||
// populate all attribute displays that need to be visible...
|
||||
for (int i = 0; i < displayAttributes.Count; i++)
|
||||
{
|
||||
var attribute = displayAttributes[i];
|
||||
var display = (VerticalAttributeDisplay)RightContent[i];
|
||||
|
||||
display.Label = attribute.Acronym;
|
||||
display.Current.Value = attribute.AdjustedValue;
|
||||
display.AdjustType.Value = VerticalAttributeDisplay.CalculateEffect(attribute.OriginalValue, attribute.AdjustedValue);
|
||||
display.Alpha = 1;
|
||||
}
|
||||
|
||||
// and hide any extra ones
|
||||
for (int i = displayAttributes.Count; i < RightContent.Count; i++)
|
||||
RightContent[i].Alpha = 0;
|
||||
});
|
||||
|
||||
private void updateCollapsedState()
|
||||
|
||||
@@ -33,7 +33,11 @@ namespace osu.Game.Overlays.Mods
|
||||
/// <summary>
|
||||
/// Text to display in the top area of the display.
|
||||
/// </summary>
|
||||
public LocalisableString Label { get; protected set; }
|
||||
public LocalisableString Label
|
||||
{
|
||||
get => text.Text;
|
||||
set => text.Text = value;
|
||||
}
|
||||
|
||||
private readonly EffectCounter counter;
|
||||
private readonly OsuSpriteText text;
|
||||
@@ -67,10 +71,8 @@ namespace osu.Game.Overlays.Mods
|
||||
counter.Colour = newColor;
|
||||
}
|
||||
|
||||
public VerticalAttributeDisplay(LocalisableString label)
|
||||
public VerticalAttributeDisplay()
|
||||
{
|
||||
Label = label;
|
||||
|
||||
AutoSizeAxes = Axes.X;
|
||||
|
||||
Origin = Anchor.CentreLeft;
|
||||
@@ -91,7 +93,6 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Text = Label,
|
||||
Margin = new MarginPadding { Horizontal = 15 }, // to reserve space for 0.XX value
|
||||
Font = OsuFont.Default.With(size: 20, weight: FontWeight.Bold)
|
||||
},
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Difficulty
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="RulesetBeatmapAttribute"/> is like a single property from <see cref="BeatmapDifficulty"/>,
|
||||
/// but adjusted for display in the context of a specific ruleset.
|
||||
/// The reason why this record exists is that rulesets use <see cref="BeatmapDifficulty"/> in different ways.
|
||||
/// Some rulesets completely ignore some fields from <see cref="BeatmapDifficulty"/>,
|
||||
/// some reuse fields in weird ways (like mania reusing <see cref="BeatmapDifficulty.CircleSize"/> to mean key count),
|
||||
/// some want to provide specific extended information for a <see cref="BeatmapDifficulty"/> field
|
||||
/// or adjust the "effective display" in different ways.
|
||||
/// </summary>
|
||||
/// <param name="Label">The long label for this beatmap attribute.</param>
|
||||
/// <param name="Acronym">A two-letter acronym for this beatmap attribute.</param>
|
||||
/// <param name="OriginalValue">The value of this attribute before application of mods.</param>
|
||||
/// <param name="AdjustedValue">The "effective" value of this attribute after application of mods.</param>
|
||||
/// <param name="MaxValue">The highest allowable value of this attribute.</param>
|
||||
public record RulesetBeatmapAttribute(
|
||||
LocalisableString Label,
|
||||
string Acronym,
|
||||
float OriginalValue,
|
||||
float AdjustedValue,
|
||||
float MaxValue);
|
||||
}
|
||||
@@ -17,6 +17,7 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Configuration;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
@@ -385,10 +386,34 @@ namespace osu.Game.Rulesets
|
||||
///
|
||||
/// It is also not always correct, and arguably is never correct depending on your frame of mind.
|
||||
/// </summary>
|
||||
/// <param name="difficulty">>The <see cref="IBeatmapDifficultyInfo"/> that will be adjusted.</param>
|
||||
/// <param name="beatmapInfo">The <see cref="IBeatmapInfo"/> for which to display the adjusted difficulty.</param>
|
||||
/// <param name="mods">The active mods.</param>
|
||||
/// <returns>The adjusted difficulty attributes.</returns>
|
||||
public virtual BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapDifficultyInfo difficulty, IReadOnlyCollection<Mod> mods) => new BeatmapDifficulty(difficulty);
|
||||
public virtual BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
BeatmapDifficulty adjustedDifficulty = new BeatmapDifficulty(beatmapInfo.Difficulty);
|
||||
|
||||
foreach (var mod in mods.OfType<IApplicableToDifficulty>())
|
||||
mod.ApplyToDifficulty(adjustedDifficulty);
|
||||
|
||||
return adjustedDifficulty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of <see cref="RulesetBeatmapAttribute"/>s to be displayed wherever it is wanted to display a given beatmap's difficulty information.
|
||||
/// The returned data includes both material changes to difficulty from <see cref="IApplicableToDifficulty"/> mods,
|
||||
/// as well as "effective" adjustments coming from <see cref="GetAdjustedDisplayDifficulty"/>.
|
||||
/// </summary>
|
||||
public virtual IEnumerable<RulesetBeatmapAttribute> GetBeatmapAttributesForDisplay(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
var originalDifficulty = beatmapInfo.Difficulty;
|
||||
var adjustedDifficulty = GetAdjustedDisplayDifficulty(beatmapInfo, mods);
|
||||
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.CircleSize, @"CS", originalDifficulty.CircleSize, adjustedDifficulty.CircleSize, 10);
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.ApproachRate, @"AR", originalDifficulty.ApproachRate, adjustedDifficulty.ApproachRate, 10);
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.Accuracy, @"OD", originalDifficulty.OverallDifficulty, adjustedDifficulty.OverallDifficulty, 10);
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.HPDrain, @"HP", originalDifficulty.DrainRate, adjustedDifficulty.DrainRate, 10);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates ruleset-specific beatmap filter criteria to be used on the song select screen.
|
||||
|
||||
@@ -16,8 +16,9 @@ using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Framework.Bindables;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Extensions;
|
||||
@@ -34,10 +35,12 @@ namespace osu.Game.Screens.Select.Details
|
||||
{
|
||||
public partial class AdvancedStats : Container, IHasCustomTooltip<AdjustedAttributesTooltip.Data>
|
||||
{
|
||||
private readonly int columns;
|
||||
|
||||
[Resolved]
|
||||
private BeatmapDifficultyCache difficultyCache { get; set; }
|
||||
|
||||
protected readonly StatisticRow FirstValue, HpDrain, Accuracy, ApproachRate;
|
||||
protected FillFlowContainer Flow { get; private set; }
|
||||
private readonly StatisticRow starDifficulty;
|
||||
|
||||
public ITooltip<AdjustedAttributesTooltip.Data> GetCustomTooltip() => new AdjustedAttributesTooltip();
|
||||
@@ -77,65 +80,48 @@ namespace osu.Game.Screens.Select.Details
|
||||
|
||||
public AdvancedStats(int columns = 1)
|
||||
{
|
||||
this.columns = columns;
|
||||
|
||||
switch (columns)
|
||||
{
|
||||
case 1:
|
||||
Child = new FillFlowContainer
|
||||
Child = Flow = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new[]
|
||||
{
|
||||
FirstValue = new StatisticRow(), // circle size/key amount
|
||||
HpDrain = new StatisticRow { Title = BeatmapsetsStrings.ShowStatsDrain },
|
||||
Accuracy = new StatisticRow { Title = BeatmapsetsStrings.ShowStatsAccuracy },
|
||||
ApproachRate = new StatisticRow { Title = BeatmapsetsStrings.ShowStatsAr },
|
||||
starDifficulty = new StatisticRow(10, true) { Title = BeatmapsetsStrings.ShowStatsStars },
|
||||
starDifficulty = new StatisticRow(forceDecimalPlaces: true)
|
||||
{
|
||||
Title = BeatmapsetsStrings.ShowStatsStars,
|
||||
MaxValue = 10,
|
||||
},
|
||||
},
|
||||
};
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Child = new FillFlowContainer
|
||||
Child = Flow = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Full,
|
||||
Children = new[]
|
||||
{
|
||||
FirstValue = new StatisticRow
|
||||
{
|
||||
Width = 0.5f,
|
||||
Padding = new MarginPadding { Right = 5, Vertical = 2.5f },
|
||||
}, // circle size/key amount
|
||||
HpDrain = new StatisticRow
|
||||
{
|
||||
Title = BeatmapsetsStrings.ShowStatsDrain,
|
||||
Width = 0.5f,
|
||||
Padding = new MarginPadding { Left = 5, Vertical = 2.5f },
|
||||
},
|
||||
Accuracy = new StatisticRow
|
||||
{
|
||||
Title = BeatmapsetsStrings.ShowStatsAccuracy,
|
||||
Width = 0.5f,
|
||||
Padding = new MarginPadding { Right = 5, Vertical = 2.5f },
|
||||
},
|
||||
ApproachRate = new StatisticRow
|
||||
{
|
||||
Title = BeatmapsetsStrings.ShowStatsAr,
|
||||
Width = 0.5f,
|
||||
Padding = new MarginPadding { Left = 5, Vertical = 2.5f },
|
||||
},
|
||||
starDifficulty = new StatisticRow(10, true)
|
||||
starDifficulty = new StatisticRow(forceDecimalPlaces: true)
|
||||
{
|
||||
MaxValue = 10,
|
||||
Title = BeatmapsetsStrings.ShowStatsStars,
|
||||
Width = 0.5f,
|
||||
Padding = new MarginPadding { Right = 5, Vertical = 2.5f },
|
||||
Padding = new MarginPadding { Horizontal = 5, Vertical = 2.5f },
|
||||
},
|
||||
},
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
Debug.Assert(Flow != null);
|
||||
Flow.SetLayoutPosition(starDifficulty, float.MaxValue);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@@ -171,52 +157,39 @@ namespace osu.Game.Screens.Select.Details
|
||||
|
||||
private void updateStatistics()
|
||||
{
|
||||
IBeatmapDifficultyInfo baseDifficulty = BeatmapInfo?.Difficulty;
|
||||
BeatmapDifficulty adjustedDifficulty = null;
|
||||
|
||||
if (baseDifficulty != null)
|
||||
if (BeatmapInfo != null && Ruleset.Value != null)
|
||||
{
|
||||
BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(baseDifficulty);
|
||||
var displayAttributes = Ruleset.Value.CreateInstance().GetBeatmapAttributesForDisplay(BeatmapInfo, Mods.Value).ToList();
|
||||
TooltipContent = new AdjustedAttributesTooltip.Data(displayAttributes);
|
||||
|
||||
foreach (var mod in Mods.Value.OfType<IApplicableToDifficulty>())
|
||||
mod.ApplyToDifficulty(originalDifficulty);
|
||||
|
||||
adjustedDifficulty = originalDifficulty;
|
||||
|
||||
if (Ruleset.Value != null)
|
||||
// if there are not enough attribute displays, make more
|
||||
// the subtraction of 1 is to exclude the star rating row which is always present (and always last)
|
||||
for (int i = Flow.Count - 1; i < displayAttributes.Count; i++)
|
||||
{
|
||||
adjustedDifficulty = Ruleset.Value.CreateInstance().GetAdjustedDisplayDifficulty(originalDifficulty, Mods.Value);
|
||||
|
||||
TooltipContent = new AdjustedAttributesTooltip.Data(originalDifficulty, adjustedDifficulty);
|
||||
Flow.Add(new StatisticRow
|
||||
{
|
||||
Width = columns == 1 ? 1 : 0.5f,
|
||||
Padding = columns == 1 ? new MarginPadding() : new MarginPadding { Horizontal = 5, Vertical = 2.5f },
|
||||
});
|
||||
}
|
||||
|
||||
// populate all attribute displays that need to be visible...
|
||||
for (int i = 0; i < displayAttributes.Count; i++)
|
||||
{
|
||||
var attribute = displayAttributes[i];
|
||||
var display = (StatisticRow)Flow.Where(r => r != starDifficulty).ElementAt(i);
|
||||
|
||||
display.Title = attribute.Label;
|
||||
display.MaxValue = attribute.MaxValue;
|
||||
display.Value = (attribute.OriginalValue, attribute.AdjustedValue);
|
||||
display.Alpha = 1;
|
||||
}
|
||||
|
||||
// and hide any extra ones
|
||||
foreach (var row in Flow.Where(r => r != starDifficulty).Skip(displayAttributes.Count))
|
||||
row.Alpha = 0;
|
||||
}
|
||||
|
||||
switch (Ruleset.Value?.OnlineID)
|
||||
{
|
||||
case 3:
|
||||
// Account for mania differences locally for now.
|
||||
// Eventually this should be handled in a more modular way, allowing rulesets to return arbitrary difficulty attributes.
|
||||
ILegacyRuleset legacyRuleset = (ILegacyRuleset)Ruleset.Value.CreateInstance();
|
||||
|
||||
// For the time being, the key count is static no matter what, because:
|
||||
// a) The method doesn't have knowledge of the active keymods. Doing so may require considerations for filtering.
|
||||
// b) Using the difficulty adjustment mod to adjust OD doesn't have an effect on conversion.
|
||||
int keyCount = baseDifficulty == null ? 0 : legacyRuleset.GetKeyCount(BeatmapInfo, Mods.Value);
|
||||
|
||||
FirstValue.Title = BeatmapsetsStrings.ShowStatsCsMania;
|
||||
FirstValue.Value = (keyCount, keyCount);
|
||||
break;
|
||||
|
||||
default:
|
||||
FirstValue.Title = BeatmapsetsStrings.ShowStatsCs;
|
||||
FirstValue.Value = (baseDifficulty?.CircleSize ?? 0, adjustedDifficulty?.CircleSize);
|
||||
break;
|
||||
}
|
||||
|
||||
HpDrain.Value = (baseDifficulty?.DrainRate ?? 0, adjustedDifficulty?.DrainRate);
|
||||
Accuracy.Value = (baseDifficulty?.OverallDifficulty ?? 0, adjustedDifficulty?.OverallDifficulty);
|
||||
ApproachRate.Value = (baseDifficulty?.ApproachRate ?? 0, adjustedDifficulty?.ApproachRate);
|
||||
|
||||
updateStarDifficulty();
|
||||
}
|
||||
|
||||
@@ -265,7 +238,6 @@ namespace osu.Game.Screens.Select.Details
|
||||
private const float value_width = 25;
|
||||
private const float name_width = 70;
|
||||
|
||||
private readonly float maxValue;
|
||||
private readonly bool forceDecimalPlaces;
|
||||
private readonly OsuSpriteText name, valueText;
|
||||
private readonly Bar bar;
|
||||
@@ -280,6 +252,8 @@ namespace osu.Game.Screens.Select.Details
|
||||
set => name.Text = value;
|
||||
}
|
||||
|
||||
public float MaxValue { get; set; }
|
||||
|
||||
private (float baseValue, float? adjustedValue)? value;
|
||||
|
||||
public (float baseValue, float? adjustedValue) Value
|
||||
@@ -292,10 +266,10 @@ namespace osu.Game.Screens.Select.Details
|
||||
|
||||
this.value = value;
|
||||
|
||||
bar.Length = value.baseValue / maxValue;
|
||||
bar.Length = value.baseValue / MaxValue;
|
||||
|
||||
valueText.Text = (value.adjustedValue ?? value.baseValue).ToString(forceDecimalPlaces ? "0.00" : "0.##");
|
||||
ModBar.Length = (value.adjustedValue ?? 0) / maxValue;
|
||||
ModBar.Length = (value.adjustedValue ?? 0) / MaxValue;
|
||||
|
||||
if (Precision.AlmostEquals(value.baseValue, value.adjustedValue ?? value.baseValue, 0.05f))
|
||||
ModBar.AccentColour = valueText.Colour = Color4.White;
|
||||
@@ -312,9 +286,8 @@ namespace osu.Game.Screens.Select.Details
|
||||
set => bar.AccentColour = value;
|
||||
}
|
||||
|
||||
public StatisticRow(float maxValue = 10, bool forceDecimalPlaces = false)
|
||||
public StatisticRow(bool forceDecimalPlaces = false)
|
||||
{
|
||||
this.maxValue = maxValue;
|
||||
this.forceDecimalPlaces = forceDecimalPlaces;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
@@ -241,7 +241,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
if (beatmap.IsDefault)
|
||||
{
|
||||
ratingAndNameContainer.FadeOut(300, Easing.OutQuint);
|
||||
countStatisticsDisplay.Statistics = Array.Empty<StatisticDifficulty.Data>();
|
||||
countStatisticsDisplay.FadeOut(300, Easing.OutQuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -261,7 +261,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
if (beatmap.IsDefault)
|
||||
{
|
||||
countStatisticsDisplay.Statistics = Array.Empty<StatisticDifficulty.Data>();
|
||||
countStatisticsDisplay.FadeOut(300, Easing.OutQuint);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -279,6 +279,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
countStatisticsDisplay.FadeIn(200, Easing.OutQuint);
|
||||
countStatisticsDisplay.Statistics = statistics;
|
||||
});
|
||||
}, cancellationToken);
|
||||
@@ -293,46 +294,11 @@ namespace osu.Game.Screens.SelectV2
|
||||
return;
|
||||
}
|
||||
|
||||
BeatmapDifficulty originalDifficulty = beatmap.Value.BeatmapInfo.Difficulty;
|
||||
BeatmapDifficulty adjustedDifficulty = new BeatmapDifficulty(originalDifficulty);
|
||||
|
||||
foreach (var mod in mods.Value.OfType<IApplicableToDifficulty>())
|
||||
mod.ApplyToDifficulty(adjustedDifficulty);
|
||||
|
||||
Ruleset rulesetInstance = ruleset.Value.CreateInstance();
|
||||
|
||||
adjustedDifficulty = rulesetInstance.GetAdjustedDisplayDifficulty(adjustedDifficulty, mods.Value);
|
||||
difficultyStatisticsDisplay.TooltipContent = new AdjustedAttributesTooltip.Data(originalDifficulty, adjustedDifficulty);
|
||||
|
||||
StatisticDifficulty.Data firstStatistic;
|
||||
|
||||
switch (ruleset.Value.OnlineID)
|
||||
{
|
||||
case 3:
|
||||
// Account for mania differences locally for now.
|
||||
// Eventually this should be handled in a more modular way, allowing rulesets to return arbitrary difficulty attributes.
|
||||
ILegacyRuleset legacyRuleset = (ILegacyRuleset)rulesetInstance;
|
||||
|
||||
// For the time being, the key count is static no matter what, because:
|
||||
// - The method doesn't have knowledge of the active keymods. Doing so may require considerations for filtering.
|
||||
// - Using the difficulty adjustment mod to adjust OD doesn't have an effect on conversion.
|
||||
int keyCount = legacyRuleset.GetKeyCount(beatmap.Value.BeatmapInfo, mods.Value);
|
||||
|
||||
firstStatistic = new StatisticDifficulty.Data(SongSelectStrings.KeyCount, keyCount, keyCount, 10);
|
||||
break;
|
||||
|
||||
default:
|
||||
firstStatistic = new StatisticDifficulty.Data(SongSelectStrings.CircleSize, originalDifficulty.CircleSize, adjustedDifficulty.CircleSize, 10);
|
||||
break;
|
||||
}
|
||||
|
||||
difficultyStatisticsDisplay.Statistics = new[]
|
||||
{
|
||||
firstStatistic,
|
||||
new StatisticDifficulty.Data(SongSelectStrings.ApproachRate, originalDifficulty.ApproachRate, adjustedDifficulty.ApproachRate, 10),
|
||||
new StatisticDifficulty.Data(SongSelectStrings.Accuracy, originalDifficulty.OverallDifficulty, adjustedDifficulty.OverallDifficulty, 10),
|
||||
new StatisticDifficulty.Data(SongSelectStrings.HPDrain, originalDifficulty.DrainRate, adjustedDifficulty.DrainRate, 10),
|
||||
};
|
||||
var displayAttributes = rulesetInstance.GetBeatmapAttributesForDisplay(beatmap.Value.BeatmapInfo, mods.Value).ToList();
|
||||
difficultyStatisticsDisplay.TooltipContent = new AdjustedAttributesTooltip.Data(displayAttributes);
|
||||
difficultyStatisticsDisplay.Statistics = displayAttributes.Select(a => new StatisticDifficulty.Data(a)).ToList();
|
||||
});
|
||||
|
||||
protected override void Update()
|
||||
|
||||
@@ -144,11 +144,13 @@ namespace osu.Game.Screens.SelectV2
|
||||
if (tiny)
|
||||
{
|
||||
statisticsFlow.Hide();
|
||||
// Slow fade hides fill flow layout weirdness.
|
||||
tinyStatisticsGrid.FadeIn(200, Easing.InQuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
tinyStatisticsGrid.Hide();
|
||||
// Slow fade hides fill flow layout weirdness.
|
||||
statisticsFlow.FadeIn(200, Easing.InQuint);
|
||||
}
|
||||
|
||||
@@ -164,12 +166,16 @@ namespace osu.Game.Screens.SelectV2
|
||||
float statisticWidth = Math.Max(65, statisticsFlow.Max(s => s.LabelWidth));
|
||||
|
||||
foreach (var statistic in statisticsFlow)
|
||||
{
|
||||
statistic.Width = statisticWidth;
|
||||
// Slow fade hides fill flow layout weirdness.
|
||||
statistic.FadeIn(200, Easing.InQuint);
|
||||
}
|
||||
|
||||
drawSizeLayout.Invalidate();
|
||||
});
|
||||
|
||||
private void updateStatistics()
|
||||
private void updateStatistics() => Scheduler.AddOnce(() =>
|
||||
{
|
||||
if (statisticsFlow.Select(s => s.Value.Label)
|
||||
.SequenceEqual(statistics.Select(s => s.Label)))
|
||||
@@ -181,12 +187,13 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
statisticsFlow.ChildrenEnumerable = statistics.Select(d => new StatisticDifficulty
|
||||
{
|
||||
Alpha = 0,
|
||||
AccentColour = accentColour,
|
||||
Value = d
|
||||
});
|
||||
updateStatisticsSizing();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
private void updateTinyStatistics()
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@@ -191,7 +192,13 @@ namespace osu.Game.Screens.SelectV2
|
||||
}
|
||||
}
|
||||
|
||||
public record Data(LocalisableString Label, float Value, float AdjustedValue, float Maximum, string? Content = null);
|
||||
public record Data(LocalisableString Label, float Value, float AdjustedValue, float Maximum, string? Content = null)
|
||||
{
|
||||
public Data(RulesetBeatmapAttribute attribute)
|
||||
: this(attribute.Label, attribute.OriginalValue, attribute.AdjustedValue, attribute.MaxValue)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
@@ -237,15 +236,9 @@ namespace osu.Game.Skinning.Components
|
||||
|
||||
BeatmapDifficulty computeDifficulty()
|
||||
{
|
||||
BeatmapDifficulty difficulty = new BeatmapDifficulty(beatmap.Value.BeatmapInfo.Difficulty);
|
||||
|
||||
foreach (var mod in mods.Value.OfType<IApplicableToDifficulty>())
|
||||
mod.ApplyToDifficulty(difficulty);
|
||||
|
||||
if (ruleset.Value is RulesetInfo rulesetInfo)
|
||||
difficulty = rulesetInfo.CreateInstance().GetAdjustedDisplayDifficulty(difficulty, mods.Value);
|
||||
|
||||
return difficulty;
|
||||
return ruleset.Value is RulesetInfo rulesetInfo
|
||||
? rulesetInfo.CreateInstance().GetAdjustedDisplayDifficulty(beatmap.Value.BeatmapInfo, mods.Value)
|
||||
: new BeatmapDifficulty(beatmap.Value.BeatmapInfo.Difficulty);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user