// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. #nullable disable 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.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing; using osu.Game.Rulesets.Taiko.Difficulty.Skills; using osu.Game.Rulesets.Taiko.Mods; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Scoring; namespace osu.Game.Rulesets.Taiko.Difficulty { public class TaikoDifficultyCalculator : DifficultyCalculator { private const double difficulty_multiplier = 1.35; public TaikoDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap) : base(ruleset, beatmap) { } protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) { return new Skill[] { new Peaks(mods) }; } protected override Mod[] DifficultyAdjustmentMods => new Mod[] { new TaikoModDoubleTime(), new TaikoModHalfTime(), new TaikoModEasy(), new TaikoModHardRock(), }; protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) { return TaikoDifficultyPreprocessor.CreateDifficultyHitObjects(beatmap, clockRate); } protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) return new TaikoDifficultyAttributes { Mods = mods }; var combined = (Peaks)skills[0]; double colourRating = combined.ColourDifficultyValue * difficulty_multiplier; double rhythmRating = combined.RhythmDifficultyValue * difficulty_multiplier; double staminaRating = combined.StaminaDifficultyValue * difficulty_multiplier; double combinedRating = combined.DifficultyValue() * difficulty_multiplier; double starRating = rescale(combinedRating * 1.4); // TODO: This is temporary measure as we don't detect abuse-type playstyles of converts within the current system. if (beatmap.BeatmapInfo.Ruleset.OnlineID == 0) { starRating *= 0.80; } HitWindows hitWindows = new TaikoHitWindows(); hitWindows.SetDifficulty(beatmap.Difficulty.OverallDifficulty); return new TaikoDifficultyAttributes { StarRating = starRating, Mods = mods, StaminaDifficulty = staminaRating, RhythmDifficulty = rhythmRating, ColourDifficulty = colourRating, PeakDifficulty = combinedRating, GreatHitWindow = hitWindows.WindowFor(HitResult.Great) / clockRate, MaxCombo = beatmap.HitObjects.Count(h => h is Hit), }; } /// /// Applies a final re-scaling of the star rating. /// /// The raw star rating value before re-scaling. private double rescale(double sr) { if (sr < 0) return sr; return 10.43 * Math.Log(sr / 8 + 1); } } }