From fadb1c3f2c0a2a700a94fbbf02b8e9b23c428d6d Mon Sep 17 00:00:00 2001 From: StanR <8269193+stanriders@users.noreply.github.com> Date: Tue, 17 Mar 2026 02:17:49 +0500 Subject: [PATCH] Calculate clock time when creating difficulty hit objects (#36962) This change removes `clockRate` precalculation from `DifficultyCalculator`. The idea is that clock rate should be calculated in-place (ideally for every object) since we store and access it using DHOs. This also prevents anyone from accidentally passing clock rate to skills Unfortunately osu uses clock rate to calculate OD for the whole map in `CreateDifficultyAttributes` so we can't make it completely DHO-based, but I think one single in-place call to `ModUtils.CalculateRateWithMods` in `CreateDifficultyAttributes` is fine --------- Co-authored-by: James Wilson --- .../EmptyFreeformDifficultyCalculator.cs | 6 ++--- .../PippidonDifficultyCalculator.cs | 6 ++--- .../EmptyScrollingDifficultyCalculator.cs | 6 ++--- .../PippidonDifficultyCalculator.cs | 6 ++--- .../Difficulty/CatchDifficultyCalculator.cs | 9 ++++--- .../Difficulty/ManiaDifficultyCalculator.cs | 9 ++++--- .../Difficulty/OsuDifficultyCalculator.cs | 11 +++++--- .../Difficulty/TaikoDifficultyCalculator.cs | 9 ++++--- ...DifficultyAdjustmentModCombinationsTest.cs | 6 ++--- .../TestSceneTimedDifficultyCalculation.cs | 9 ++++--- .../TestSceneBeatmapAttributeText.cs | 6 ++--- .../Difficulty/DifficultyCalculator.cs | 25 ++++++++----------- 12 files changed, 59 insertions(+), 49 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformDifficultyCalculator.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformDifficultyCalculator.cs index 312d3d5e9a..c7851cc12f 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformDifficultyCalculator.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformDifficultyCalculator.cs @@ -19,13 +19,13 @@ namespace osu.Game.Rulesets.EmptyFreeform { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills) { return new DifficultyAttributes(mods, 0); } - protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty(); + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods) => Enumerable.Empty(); - protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => Array.Empty(); + protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) => Array.Empty(); } } diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs index f6addab279..8525769584 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs @@ -19,13 +19,13 @@ namespace osu.Game.Rulesets.Pippidon { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills) { return new DifficultyAttributes(mods, 0); } - protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty(); + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods) => Enumerable.Empty(); - protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => Array.Empty(); + protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) => Array.Empty(); } } diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingDifficultyCalculator.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingDifficultyCalculator.cs index a4dc1762d5..17139218a5 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingDifficultyCalculator.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingDifficultyCalculator.cs @@ -19,13 +19,13 @@ namespace osu.Game.Rulesets.EmptyScrolling { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills) { return new DifficultyAttributes(mods, 0); } - protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty(); + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods) => Enumerable.Empty(); - protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => Array.Empty(); + protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) => Array.Empty(); } } diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs index f6addab279..8525769584 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs @@ -19,13 +19,13 @@ namespace osu.Game.Rulesets.Pippidon { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills) { return new DifficultyAttributes(mods, 0); } - protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty(); + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods) => Enumerable.Empty(); - protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => Array.Empty(); + protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) => Array.Empty(); } } diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index ea1c31b216..75db566009 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; +using osu.Game.Utils; namespace osu.Game.Rulesets.Catch.Difficulty { @@ -29,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills) { if (beatmap.HitObjects.Count == 0) return new CatchDifficultyAttributes { Mods = mods }; @@ -44,12 +45,14 @@ namespace osu.Game.Rulesets.Catch.Difficulty return attributes; } - protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods) { CatchHitObject? lastObject = null; List objects = new List(); + double clockRate = ModUtils.CalculateRateWithMods(mods); + float halfCatcherWidth = Catcher.CalculateCatchWidth(beatmap.Difficulty) * 0.5f; // For circle sizes above 5.5, reduce the catcher width further to simulate imperfect gameplay. @@ -71,7 +74,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty return objects; } - protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) + protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) { return new Skill[] { diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index bcf16e6808..1bfa3bec6d 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -19,6 +19,7 @@ using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; +using osu.Game.Utils; namespace osu.Game.Rulesets.Mania.Difficulty { @@ -36,7 +37,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.MatchesOnlineID(ruleset); } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills) { if (beatmap.HitObjects.Count == 0) return new ManiaDifficultyAttributes { Mods = mods }; @@ -62,11 +63,13 @@ namespace osu.Game.Rulesets.Mania.Difficulty return 1; } - protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods) { var sortedObjects = beatmap.HitObjects.ToArray(); int totalColumns = ((ManiaBeatmap)beatmap).TotalColumns; + double clockRate = ModUtils.CalculateRateWithMods(mods); + LegacySortHelper.Sort(sortedObjects, Comparer.Create((a, b) => (int)Math.Round(a.StartTime) - (int)Math.Round(b.StartTime))); List objects = new List(); @@ -88,7 +91,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty // Sorting is done in CreateDifficultyHitObjects, since the full list of hitobjects is required. protected override IEnumerable SortObjects(IEnumerable input) => input; - protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[] + protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) => new Skill[] { new Strain(mods, ((ManiaBeatmap)Beatmap).TotalColumns) }; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 2a425712b0..65d708cb30 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -17,6 +17,7 @@ using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; +using osu.Game.Utils; namespace osu.Game.Rulesets.Osu.Difficulty { @@ -45,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty return (79.5 - hitWindowGreat) / 6; } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills) { if (beatmap.HitObjects.Count == 0) return new OsuDifficultyAttributes { Mods = mods }; @@ -77,7 +78,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty double difficultSliders = aim.GetDifficultSliders(); - double overallDifficulty = CalculateRateAdjustedOverallDifficulty(beatmap.Difficulty.OverallDifficulty, clockRate); + double overallDifficulty = CalculateRateAdjustedOverallDifficulty(beatmap.Difficulty.OverallDifficulty, ModUtils.CalculateRateWithMods(mods)); int hitCircleCount = beatmap.HitObjects.Count(h => h is HitCircle); int sliderCount = beatmap.HitObjects.Count(h => h is Slider); @@ -161,10 +162,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty return Math.Cbrt(basePerformance * OsuPerformanceCalculator.PERFORMANCE_BASE_MULTIPLIER); } - protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods) { List objects = new List(); + double clockRate = ModUtils.CalculateRateWithMods(mods); + // The first jump is formed by the first two hitobjects of the map. // If the map has less than two OsuHitObjects, the enumerator will not return anything. for (int i = 1; i < beatmap.HitObjects.Count; i++) @@ -175,7 +178,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty return objects; } - protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) + protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) { var skills = new List { diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 2cb49e8a45..64af2861ec 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing.Colour; using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing.Rhythm; using osu.Game.Rulesets.Taiko.Difficulty.Skills; using osu.Game.Rulesets.Taiko.Mods; +using osu.Game.Utils; namespace osu.Game.Rulesets.Taiko.Difficulty { @@ -39,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty { } - protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) + protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) { isConvert = beatmap.BeatmapInfo.Ruleset.OnlineID == 0; isRelax = mods.Any(h => h is TaikoModRelax); @@ -62,13 +63,15 @@ namespace osu.Game.Rulesets.Taiko.Difficulty new TaikoModHardRock(), }; - protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods) { var difficultyHitObjects = new List(); var centreObjects = new List(); var rimObjects = new List(); var noteObjects = new List(); + double clockRate = ModUtils.CalculateRateWithMods(mods); + // Generate TaikoDifficultyHitObjects from the beatmap's hit objects. for (int i = 2; i < beatmap.HitObjects.Count; i++) { @@ -92,7 +95,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty return difficultyHitObjects; } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills) { if (beatmap.HitObjects.Count == 0) return new TaikoDifficultyAttributes { Mods = mods }; diff --git a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs index 90671093a5..f95e5768b0 100644 --- a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs +++ b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs @@ -223,17 +223,17 @@ namespace osu.Game.Tests.NonVisual protected override Mod[] DifficultyAdjustmentMods { get; } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills) { throw new NotImplementedException(); } - protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods) { throw new NotImplementedException(); } - protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) + protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) { throw new NotImplementedException(); } diff --git a/osu.Game.Tests/NonVisual/TestSceneTimedDifficultyCalculation.cs b/osu.Game.Tests/NonVisual/TestSceneTimedDifficultyCalculation.cs index daf0bec44c..e3c5b92b54 100644 --- a/osu.Game.Tests/NonVisual/TestSceneTimedDifficultyCalculation.cs +++ b/osu.Game.Tests/NonVisual/TestSceneTimedDifficultyCalculation.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; using osu.Game.Tests.Beatmaps; +using osu.Game.Utils; namespace osu.Game.Tests.NonVisual { @@ -172,13 +173,15 @@ namespace osu.Game.Tests.NonVisual { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills) => new TestDifficultyAttributes { Objects = beatmap.HitObjects.ToArray() }; - protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods) { List objects = new List(); + double clockRate = ModUtils.CalculateRateWithMods(mods); + foreach (var obj in beatmap.HitObjects.OfType()) { if (!obj.Skip) @@ -191,7 +194,7 @@ namespace osu.Game.Tests.NonVisual return objects; } - protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[] { new PassThroughSkill(mods) }; + protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) => new Skill[] { new PassThroughSkill(mods) }; private class PassThroughSkill : Skill { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapAttributeText.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapAttributeText.cs index 5acd6cb084..36dbed3742 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapAttributeText.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapAttributeText.cs @@ -208,13 +208,13 @@ namespace osu.Game.Tests.Visual.UserInterface { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills) => new DifficultyAttributes(mods, mods.OfType().SingleOrDefault()?.Difficulty.Value ?? 0); - protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods) => Array.Empty(); - protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) + protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods) => Array.Empty(); } diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 7acfbe651f..ec94bd704b 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -34,7 +34,6 @@ namespace osu.Game.Rulesets.Difficulty protected readonly IWorkingBeatmap WorkingBeatmap; private Mod[] playableMods; - private double clockRate; private readonly IRulesetInfo ruleset; @@ -74,10 +73,10 @@ namespace osu.Game.Rulesets.Difficulty // ReSharper disable once PossiblyMistakenUseOfCancellationToken preProcess(mods, cancellationToken); - var skills = CreateSkills(Beatmap, playableMods, clockRate); + var skills = CreateSkills(Beatmap, playableMods); if (!Beatmap.HitObjects.Any()) - return CreateDifficultyAttributes(Beatmap, playableMods, skills, clockRate); + return CreateDifficultyAttributes(Beatmap, playableMods, skills); foreach (var hitObject in getDifficultyHitObjects()) { @@ -88,7 +87,7 @@ namespace osu.Game.Rulesets.Difficulty } } - return CreateDifficultyAttributes(Beatmap, playableMods, skills, clockRate); + return CreateDifficultyAttributes(Beatmap, playableMods, skills); } /// @@ -121,7 +120,7 @@ namespace osu.Game.Rulesets.Difficulty if (!Beatmap.HitObjects.Any()) return attribs; - var skills = CreateSkills(Beatmap, playableMods, clockRate); + var skills = CreateSkills(Beatmap, playableMods); var progressiveBeatmap = new ProgressiveCalculationBeatmap(Beatmap); var difficultyObjects = getDifficultyHitObjects().ToArray(); @@ -142,7 +141,7 @@ namespace osu.Game.Rulesets.Difficulty currentIndex++; } - attribs.Add(new TimedDifficultyAttributes(obj.GetEndTime(), CreateDifficultyAttributes(progressiveBeatmap, playableMods, skills, clockRate))); + attribs.Add(new TimedDifficultyAttributes(obj.GetEndTime(), CreateDifficultyAttributes(progressiveBeatmap, playableMods, skills))); } return attribs; @@ -174,7 +173,7 @@ namespace osu.Game.Rulesets.Difficulty /// /// Retrieves the s to calculate against. /// - private IEnumerable getDifficultyHitObjects() => SortObjects(CreateDifficultyHitObjects(Beatmap, clockRate)); + private IEnumerable getDifficultyHitObjects() => SortObjects(CreateDifficultyHitObjects(Beatmap, playableMods)); /// /// Performs required tasks before every calculation. @@ -185,8 +184,6 @@ namespace osu.Game.Rulesets.Difficulty { playableMods = mods.Select(m => m.DeepClone()).ToArray(); Beatmap = WorkingBeatmap.GetPlayableBeatmap(ruleset, playableMods, cancellationToken); - - clockRate = ModUtils.CalculateRateWithMods(playableMods); } /// @@ -277,16 +274,15 @@ namespace osu.Game.Rulesets.Difficulty /// This may differ from in the case of timed calculation. /// The s that difficulty was calculated with. /// The skills which processed the beatmap. - /// The rate at which the gameplay clock is run at. - protected abstract DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate); + protected abstract DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills); /// /// Enumerates s to be processed from s in the . /// /// The providing the s to enumerate. - /// The rate at which the gameplay clock is run at. + /// Mods to create difficulty objects with. /// The enumerated s. - protected abstract IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate); + protected abstract IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods); /// /// Creates the s to calculate the difficulty of an . @@ -294,9 +290,8 @@ namespace osu.Game.Rulesets.Difficulty /// The whose difficulty will be calculated. /// This may differ from in the case of timed calculation. /// Mods to calculate difficulty with. - /// Clockrate to calculate difficulty with. /// The s. - protected abstract Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate); + protected abstract Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods); /// /// Used to calculate timed difficulty attributes, where only a subset of hitobjects should be visible at any point in time.