diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index fb7c4f05f4..36af9fb980 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -49,9 +49,9 @@ namespace osu.Game.Rulesets.Catch.Difficulty Mods = mods, ApproachRate = preempt > 1200.0 ? -(preempt - 1800.0) / 120.0 : -(preempt - 1200.0) / 150.0 + 5.0, MaxCombo = beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)), - LegacyTotalScore = sv1Processor.TotalScore, + LegacyAccuracyScore = sv1Processor.AccuracyScore, LegacyComboScore = sv1Processor.ComboScore, - LegacyBonusScore = sv1Processor.BonusScore + LegacyBonusScoreRatio = sv1Processor.BonusScoreRatio }; } diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchScoreV1Processor.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchScoreV1Processor.cs index b5c3838fdc..3f0ac7a760 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchScoreV1Processor.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchScoreV1Processor.cs @@ -6,31 +6,34 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Difficulty { internal class CatchScoreV1Processor { - public int TotalScore => BaseScore + ComboScore + BonusScore; + /// + /// The accuracy portion of the legacy (ScoreV1) total score. + /// + public int AccuracyScore { get; private set; } /// - /// Amount of score that is combo-and-difficulty-multiplied, excluding mod multipliers. + /// The combo-multiplied portion of the legacy (ScoreV1) total score. /// public int ComboScore { get; private set; } /// - /// Amount of score that is NOT combo-and-difficulty-multiplied. + /// A ratio of new_bonus_score / old_bonus_score for converting the bonus score of legacy scores to the new scoring. + /// This is made up of all judgements that would be or . /// - public int BaseScore { get; private set; } - - /// - /// Amount of score whose judgements would be treated as "bonus" in ScoreV2. - /// - public int BonusScore { get; private set; } + public double BonusScoreRatio => legacyBonusScore == 0 ? 0 : (double)modernBonusScore / legacyBonusScore; + private int legacyBonusScore; + private int modernBonusScore; private int combo; private readonly double scoreMultiplier; @@ -77,7 +80,9 @@ namespace osu.Game.Rulesets.Catch.Difficulty { bool increaseCombo = true; bool addScoreComboMultiplier = false; + bool isBonus = false; + HitResult bonusResult = HitResult.None; int scoreIncrease = 0; @@ -102,6 +107,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty scoreIncrease = 1100; increaseCombo = false; isBonus = true; + bonusResult = HitResult.LargeBonus; break; case JuiceStream: @@ -122,9 +128,12 @@ namespace osu.Game.Rulesets.Catch.Difficulty } if (isBonus) - BonusScore += scoreIncrease; + { + legacyBonusScore += scoreIncrease; + modernBonusScore += Judgement.ToNumericResult(bonusResult); + } else - BaseScore += scoreIncrease; + AccuracyScore += scoreIncrease; if (increaseCombo) combo++; diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index cb41b93deb..d1058a9f8c 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -33,13 +33,9 @@ namespace osu.Game.Rulesets.Mania.Difficulty public override int Version => 20220902; - private readonly IWorkingBeatmap workingBeatmap; - public ManiaDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap) : base(ruleset, beatmap) { - workingBeatmap = beatmap; - isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.MatchesOnlineID(ruleset); originalOverallDifficulty = beatmap.BeatmapInfo.Difficulty.OverallDifficulty; } @@ -62,7 +58,6 @@ namespace osu.Game.Rulesets.Mania.Difficulty // This is done the way it is to introduce fractional differences in order to match osu-stable for the time being. GreatHitWindow = Math.Ceiling((int)(getHitWindow300(mods) * clockRate) / clockRate), MaxCombo = beatmap.HitObjects.Sum(maxComboForObject), - LegacyTotalScore = sv1Processor.TotalScore, LegacyComboScore = sv1Processor.TotalScore }; } diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 21ee03d1a5..5d6ed4792d 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -109,9 +109,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty HitCircleCount = hitCirclesCount, SliderCount = sliderCount, SpinnerCount = spinnerCount, - LegacyTotalScore = sv1Processor.TotalScore, + LegacyAccuracyScore = sv1Processor.AccuracyScore, LegacyComboScore = sv1Processor.ComboScore, - LegacyBonusScore = sv1Processor.BonusScore + LegacyBonusScoreRatio = sv1Processor.BonusScoreRatio }; } diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuScoreV1Processor.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuScoreV1Processor.cs index c82928b745..28d029b73a 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuScoreV1Processor.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuScoreV1Processor.cs @@ -5,32 +5,35 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Difficulty { internal class OsuScoreV1Processor { - public int TotalScore => BaseScore + ComboScore + BonusScore; + /// + /// The accuracy portion of the legacy (ScoreV1) total score. + /// + public int AccuracyScore { get; private set; } /// - /// Amount of score that is combo-and-difficulty-multiplied, excluding mod multipliers. + /// The combo-multiplied portion of the legacy (ScoreV1) total score. /// public int ComboScore { get; private set; } /// - /// Amount of score that is NOT combo-and-difficulty-multiplied. + /// A ratio of new_bonus_score / old_bonus_score for converting the bonus score of legacy scores to the new scoring. + /// This is made up of all judgements that would be or . /// - public int BaseScore { get; private set; } - - /// - /// Amount of score whose judgements would be treated as "bonus" in ScoreV2. - /// - public int BonusScore { get; private set; } + public double BonusScoreRatio => legacyBonusScore == 0 ? 0 : (double)modernBonusScore / legacyBonusScore; + private int legacyBonusScore; + private int modernBonusScore; private int combo; private readonly double scoreMultiplier; @@ -80,7 +83,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty { bool increaseCombo = true; bool addScoreComboMultiplier = false; + bool isBonus = false; + HitResult bonusResult = HitResult.None; int scoreIncrease = 0; @@ -100,12 +105,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty scoreIncrease = 1100; increaseCombo = false; isBonus = true; + bonusResult = HitResult.LargeBonus; break; case SpinnerTick: scoreIncrease = 100; increaseCombo = false; isBonus = true; + bonusResult = HitResult.SmallBonus; break; case HitCircle: @@ -156,9 +163,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty } if (isBonus) - BonusScore += scoreIncrease; + { + legacyBonusScore += scoreIncrease; + modernBonusScore += Judgement.ToNumericResult(bonusResult); + } else - BaseScore += scoreIncrease; + AccuracyScore += scoreIncrease; if (increaseCombo) combo++; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 28b07c0d59..49222adc89 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -101,9 +101,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty PeakDifficulty = combinedRating, GreatHitWindow = hitWindows.WindowFor(HitResult.Great) / clockRate, MaxCombo = beatmap.HitObjects.Count(h => h is Hit), - LegacyTotalScore = sv1Processor.TotalScore, + LegacyAccuracyScore = sv1Processor.AccuracyScore, LegacyComboScore = sv1Processor.ComboScore, - LegacyBonusScore = sv1Processor.BonusScore + LegacyBonusScoreRatio = sv1Processor.BonusScoreRatio }; } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoScoreV1Processor.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoScoreV1Processor.cs index ee52424b26..23ff9585e8 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoScoreV1Processor.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoScoreV1Processor.cs @@ -5,32 +5,35 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Difficulty { internal class TaikoScoreV1Processor { - public int TotalScore => BaseScore + ComboScore + BonusScore; + /// + /// The accuracy portion of the legacy (ScoreV1) total score. + /// + public int AccuracyScore { get; private set; } /// - /// Amount of score that is combo-and-difficulty-multiplied, excluding mod multipliers. + /// The combo-multiplied portion of the legacy (ScoreV1) total score. /// public int ComboScore { get; private set; } /// - /// Amount of score that is NOT combo-and-difficulty-multiplied. + /// A ratio of new_bonus_score / old_bonus_score for converting the bonus score of legacy scores to the new scoring. + /// This is made up of all judgements that would be or . /// - public int BaseScore { get; private set; } - - /// - /// Amount of score whose judgements would be treated as "bonus" in ScoreV2. - /// - public int BonusScore { get; private set; } + public double BonusScoreRatio => legacyBonusScore == 0 ? 0 : (double)modernBonusScore / legacyBonusScore; + private int legacyBonusScore; + private int modernBonusScore; private int combo; private readonly double modMultiplier; @@ -83,7 +86,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty { bool increaseCombo = true; bool addScoreComboMultiplier = false; + bool isBonus = false; + HitResult bonusResult = HitResult.None; int scoreIncrease = 0; @@ -98,6 +103,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty scoreIncrease = 300; increaseCombo = false; isBonus = true; + bonusResult = HitResult.SmallBonus; break; case Swell swell: @@ -123,6 +129,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty addScoreComboMultiplier = true; increaseCombo = false; isBonus = true; + bonusResult = HitResult.LargeBonus; break; case Hit: @@ -181,9 +188,12 @@ namespace osu.Game.Rulesets.Taiko.Difficulty ComboScore += comboScoreIncrease; if (isBonus) - BonusScore += scoreIncrease; + { + legacyBonusScore += scoreIncrease; + modernBonusScore += Judgement.ToNumericResult(bonusResult); + } else - BaseScore += scoreIncrease; + AccuracyScore += scoreIncrease; if (increaseCombo) combo++; diff --git a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs index 5a51fb24a6..48e67ff425 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs @@ -27,9 +27,9 @@ namespace osu.Game.Rulesets.Difficulty protected const int ATTRIB_ID_FLASHLIGHT = 17; protected const int ATTRIB_ID_SLIDER_FACTOR = 19; protected const int ATTRIB_ID_SPEED_NOTE_COUNT = 21; - protected const int ATTRIB_ID_LEGACY_TOTAL_SCORE = 23; + protected const int ATTRIB_ID_LEGACY_ACCURACY_SCORE = 23; protected const int ATTRIB_ID_LEGACY_COMBO_SCORE = 25; - protected const int ATTRIB_ID_LEGACY_BONUS_SCORE = 27; + protected const int ATTRIB_ID_LEGACY_BONUS_SCORE_RATIO = 27; /// /// The mods which were applied to the beatmap. @@ -49,22 +49,23 @@ namespace osu.Game.Rulesets.Difficulty public int MaxCombo { get; set; } /// - /// The maximum achievable legacy total score. + /// The accuracy portion of the legacy (ScoreV1) total score. /// - [JsonProperty("legacy_total_score", Order = -5)] - public int LegacyTotalScore { get; set; } + [JsonProperty("legacy_accuracy_score", Order = -5)] + public int LegacyAccuracyScore { get; set; } /// - /// The combo-multiplied portion of . + /// The combo-multiplied portion of the legacy (ScoreV1) total score. /// [JsonProperty("legacy_combo_score", Order = -4)] public int LegacyComboScore { get; set; } /// - /// The "bonus" portion of consisting of all judgements that would be or . + /// A ratio of new_bonus_score / old_bonus_score for converting the bonus score of legacy scores to the new scoring. + /// This is made up of all judgements that would be or . /// - [JsonProperty("legacy_bonus_score", Order = -3)] - public int LegacyBonusScore { get; set; } + [JsonProperty("legacy_bonus_score_ratio", Order = -3)] + public double LegacyBonusScoreRatio { get; set; } /// /// Creates new . @@ -93,9 +94,9 @@ namespace osu.Game.Rulesets.Difficulty public virtual IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() { yield return (ATTRIB_ID_MAX_COMBO, MaxCombo); - yield return (ATTRIB_ID_LEGACY_TOTAL_SCORE, LegacyTotalScore); + yield return (ATTRIB_ID_LEGACY_ACCURACY_SCORE, LegacyAccuracyScore); yield return (ATTRIB_ID_LEGACY_COMBO_SCORE, LegacyComboScore); - yield return (ATTRIB_ID_LEGACY_BONUS_SCORE, LegacyBonusScore); + yield return (ATTRIB_ID_LEGACY_BONUS_SCORE_RATIO, LegacyBonusScoreRatio); } /// @@ -106,9 +107,9 @@ namespace osu.Game.Rulesets.Difficulty public virtual void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) { MaxCombo = (int)values[ATTRIB_ID_MAX_COMBO]; - LegacyTotalScore = (int)values[ATTRIB_ID_LEGACY_TOTAL_SCORE]; + LegacyAccuracyScore = (int)values[ATTRIB_ID_LEGACY_ACCURACY_SCORE]; LegacyComboScore = (int)values[ATTRIB_ID_LEGACY_COMBO_SCORE]; - LegacyBonusScore = (int)values[ATTRIB_ID_LEGACY_BONUS_SCORE]; + LegacyBonusScoreRatio = (int)values[ATTRIB_ID_LEGACY_BONUS_SCORE_RATIO]; } } }