// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Difficulty.Preprocessing; using osu.Game.Rulesets.Mania.Difficulty.Skills; using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Difficulty { public class ManiaDifficultyCalculator : DifficultyCalculator { private const double star_scaling_factor = 0.018; private readonly bool isForCurrentRuleset; public ManiaDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo); } protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) return new ManiaDifficultyAttributes { Mods = mods, Skills = skills }; HitWindows hitWindows = new ManiaHitWindows(); hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); return new ManiaDifficultyAttributes { StarRating = skills[0].DifficultyValue() * star_scaling_factor, Mods = mods, // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future GreatHitWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate, MaxCombo = beatmap.HitObjects.Sum(h => h is HoldNote ? 2 : 1), Skills = skills }; } protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) { var sortedObjects = beatmap.HitObjects.ToArray(); LegacySortHelper.Sort(sortedObjects, Comparer.Create((a, b) => (int)Math.Round(a.StartTime) - (int)Math.Round(b.StartTime))); for (int i = 1; i < sortedObjects.Length; i++) yield return new ManiaDifficultyHitObject(sortedObjects[i], sortedObjects[i - 1], clockRate); } // 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) => new Skill[] { new Strain(((ManiaBeatmap)beatmap).TotalColumns) }; protected override Mod[] DifficultyAdjustmentMods { get { var mods = new Mod[] { new ManiaModDoubleTime(), new ManiaModHalfTime(), new ManiaModEasy(), new ManiaModHardRock(), }; if (isForCurrentRuleset) return mods; // if we are a convert, we can be played in any key mod. return mods.Concat(new Mod[] { new ManiaModKey1(), new ManiaModKey2(), new ManiaModKey3(), new ManiaModKey4(), new ManiaModKey5(), new ManiaModKey6(), new ManiaModKey7(), new ManiaModKey8(), new ManiaModKey9(), }).ToArray(); } } } }