mirror of
https://github.com/ppy/osu.git
synced 2024-12-13 08:32:57 +08:00
Merge pull request #24779 from smoogipoo/split-legacy-scoring-attribs
Split legacy scoring attribs into its own table
This commit is contained in:
commit
9d8c3f0f5c
@ -25,6 +25,7 @@ using osu.Game.Rulesets.Edit;
|
|||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Replays.Types;
|
using osu.Game.Rulesets.Replays.Types;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.Scoring.Legacy;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens.Ranking.Statistics;
|
using osu.Game.Screens.Ranking.Statistics;
|
||||||
|
@ -25,12 +25,9 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
|
|
||||||
public override int Version => 20220701;
|
public override int Version => 20220701;
|
||||||
|
|
||||||
private readonly IWorkingBeatmap workingBeatmap;
|
|
||||||
|
|
||||||
public CatchDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
public CatchDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
{
|
{
|
||||||
workingBeatmap = beatmap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
|
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
|
||||||
@ -49,15 +46,6 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
MaxCombo = beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType<JuiceStream>().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)),
|
MaxCombo = beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType<JuiceStream>().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ComputeLegacyScoringValues)
|
|
||||||
{
|
|
||||||
CatchLegacyScoreSimulator sv1Simulator = new CatchLegacyScoreSimulator();
|
|
||||||
sv1Simulator.Simulate(workingBeatmap, beatmap, mods);
|
|
||||||
attributes.LegacyAccuracyScore = sv1Simulator.AccuracyScore;
|
|
||||||
attributes.LegacyComboScore = sv1Simulator.ComboScore;
|
|
||||||
attributes.LegacyBonusScoreRatio = sv1Simulator.BonusScoreRatio;
|
|
||||||
}
|
|
||||||
|
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,33 +2,26 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Mods;
|
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.Scoring.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Difficulty
|
namespace osu.Game.Rulesets.Catch.Difficulty
|
||||||
{
|
{
|
||||||
internal class CatchLegacyScoreSimulator : ILegacyScoreSimulator
|
internal class CatchLegacyScoreSimulator : ILegacyScoreSimulator
|
||||||
{
|
{
|
||||||
public int AccuracyScore { get; private set; }
|
|
||||||
|
|
||||||
public int ComboScore { get; private set; }
|
|
||||||
|
|
||||||
public double BonusScoreRatio => legacyBonusScore == 0 ? 0 : (double)modernBonusScore / legacyBonusScore;
|
|
||||||
|
|
||||||
private int legacyBonusScore;
|
private int legacyBonusScore;
|
||||||
private int modernBonusScore;
|
private int standardisedBonusScore;
|
||||||
private int combo;
|
private int combo;
|
||||||
|
|
||||||
private double scoreMultiplier;
|
private double scoreMultiplier;
|
||||||
|
|
||||||
public void Simulate(IWorkingBeatmap workingBeatmap, IBeatmap playableBeatmap, IReadOnlyList<Mod> mods)
|
public LegacyScoreAttributes Simulate(IWorkingBeatmap workingBeatmap, IBeatmap playableBeatmap)
|
||||||
{
|
{
|
||||||
IBeatmap baseBeatmap = workingBeatmap.Beatmap;
|
IBeatmap baseBeatmap = workingBeatmap.Beatmap;
|
||||||
|
|
||||||
@ -70,13 +63,19 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
+ baseBeatmap.Difficulty.CircleSize
|
+ baseBeatmap.Difficulty.CircleSize
|
||||||
+ Math.Clamp((float)objectCount / drainLength * 8, 0, 16)) / 38 * 5);
|
+ Math.Clamp((float)objectCount / drainLength * 8, 0, 16)) / 38 * 5);
|
||||||
|
|
||||||
scoreMultiplier = difficultyPeppyStars * mods.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier);
|
scoreMultiplier = difficultyPeppyStars;
|
||||||
|
|
||||||
|
LegacyScoreAttributes attributes = new LegacyScoreAttributes();
|
||||||
|
|
||||||
foreach (var obj in playableBeatmap.HitObjects)
|
foreach (var obj in playableBeatmap.HitObjects)
|
||||||
simulateHit(obj);
|
simulateHit(obj, ref attributes);
|
||||||
|
|
||||||
|
attributes.BonusScoreRatio = legacyBonusScore == 0 ? 0 : (double)standardisedBonusScore / legacyBonusScore;
|
||||||
|
|
||||||
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void simulateHit(HitObject hitObject)
|
private void simulateHit(HitObject hitObject, ref LegacyScoreAttributes attributes)
|
||||||
{
|
{
|
||||||
bool increaseCombo = true;
|
bool increaseCombo = true;
|
||||||
bool addScoreComboMultiplier = false;
|
bool addScoreComboMultiplier = false;
|
||||||
@ -112,28 +111,28 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
|
|
||||||
case JuiceStream:
|
case JuiceStream:
|
||||||
foreach (var nested in hitObject.NestedHitObjects)
|
foreach (var nested in hitObject.NestedHitObjects)
|
||||||
simulateHit(nested);
|
simulateHit(nested, ref attributes);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case BananaShower:
|
case BananaShower:
|
||||||
foreach (var nested in hitObject.NestedHitObjects)
|
foreach (var nested in hitObject.NestedHitObjects)
|
||||||
simulateHit(nested);
|
simulateHit(nested, ref attributes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addScoreComboMultiplier)
|
if (addScoreComboMultiplier)
|
||||||
{
|
{
|
||||||
// ReSharper disable once PossibleLossOfFraction (intentional to match osu-stable...)
|
// ReSharper disable once PossibleLossOfFraction (intentional to match osu-stable...)
|
||||||
ComboScore += (int)(Math.Max(0, combo - 1) * (scoreIncrease / 25 * scoreMultiplier));
|
attributes.ComboScore += (int)(Math.Max(0, combo - 1) * (scoreIncrease / 25 * scoreMultiplier));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBonus)
|
if (isBonus)
|
||||||
{
|
{
|
||||||
legacyBonusScore += scoreIncrease;
|
legacyBonusScore += scoreIncrease;
|
||||||
modernBonusScore += Judgement.ToNumericResult(bonusResult);
|
standardisedBonusScore += Judgement.ToNumericResult(bonusResult);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
AccuracyScore += scoreIncrease;
|
attributes.AccuracyScore += scoreIncrease;
|
||||||
|
|
||||||
if (increaseCombo)
|
if (increaseCombo)
|
||||||
combo++;
|
combo++;
|
||||||
|
@ -31,13 +31,9 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
|
|
||||||
public override int Version => 20220902;
|
public override int Version => 20220902;
|
||||||
|
|
||||||
private readonly IWorkingBeatmap workingBeatmap;
|
|
||||||
|
|
||||||
public ManiaDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
public ManiaDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
{
|
{
|
||||||
workingBeatmap = beatmap;
|
|
||||||
|
|
||||||
isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.MatchesOnlineID(ruleset);
|
isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.MatchesOnlineID(ruleset);
|
||||||
originalOverallDifficulty = beatmap.BeatmapInfo.Difficulty.OverallDifficulty;
|
originalOverallDifficulty = beatmap.BeatmapInfo.Difficulty.OverallDifficulty;
|
||||||
}
|
}
|
||||||
@ -60,15 +56,6 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
MaxCombo = beatmap.HitObjects.Sum(maxComboForObject),
|
MaxCombo = beatmap.HitObjects.Sum(maxComboForObject),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ComputeLegacyScoringValues)
|
|
||||||
{
|
|
||||||
ManiaLegacyScoreSimulator sv1Simulator = new ManiaLegacyScoreSimulator();
|
|
||||||
sv1Simulator.Simulate(workingBeatmap, beatmap, mods);
|
|
||||||
attributes.LegacyAccuracyScore = sv1Simulator.AccuracyScore;
|
|
||||||
attributes.LegacyComboScore = sv1Simulator.ComboScore;
|
|
||||||
attributes.LegacyBonusScoreRatio = sv1Simulator.BonusScoreRatio;
|
|
||||||
}
|
|
||||||
|
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,28 +1,16 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mania.Mods;
|
using osu.Game.Rulesets.Scoring.Legacy;
|
||||||
using osu.Game.Rulesets.Mods;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Difficulty
|
namespace osu.Game.Rulesets.Mania.Difficulty
|
||||||
{
|
{
|
||||||
internal class ManiaLegacyScoreSimulator : ILegacyScoreSimulator
|
internal class ManiaLegacyScoreSimulator : ILegacyScoreSimulator
|
||||||
{
|
{
|
||||||
public int AccuracyScore => 0;
|
public LegacyScoreAttributes Simulate(IWorkingBeatmap workingBeatmap, IBeatmap playableBeatmap)
|
||||||
public int ComboScore { get; private set; }
|
|
||||||
public double BonusScoreRatio => 0;
|
|
||||||
|
|
||||||
public void Simulate(IWorkingBeatmap workingBeatmap, IBeatmap playableBeatmap, IReadOnlyList<Mod> mods)
|
|
||||||
{
|
{
|
||||||
double multiplier = mods.Where(m => m is not (ModHidden or ModHardRock or ModDoubleTime or ModFlashlight or ManiaModFadeIn))
|
return new LegacyScoreAttributes { ComboScore = 1000000 };
|
||||||
.Select(m => m.ScoreMultiplier)
|
|
||||||
.Aggregate(1.0, (c, n) => c * n);
|
|
||||||
|
|
||||||
ComboScore = (int)(1000000 * multiplier);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ using osu.Game.Rulesets.Mania.UI;
|
|||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Replays.Types;
|
using osu.Game.Rulesets.Replays.Types;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.Scoring.Legacy;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens.Edit.Setup;
|
using osu.Game.Screens.Edit.Setup;
|
||||||
|
@ -26,12 +26,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
|
|
||||||
public override int Version => 20220902;
|
public override int Version => 20220902;
|
||||||
|
|
||||||
private readonly IWorkingBeatmap workingBeatmap;
|
|
||||||
|
|
||||||
public OsuDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
public OsuDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
{
|
{
|
||||||
workingBeatmap = beatmap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
|
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
|
||||||
@ -109,15 +106,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
SpinnerCount = spinnerCount,
|
SpinnerCount = spinnerCount,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ComputeLegacyScoringValues)
|
|
||||||
{
|
|
||||||
OsuLegacyScoreSimulator sv1Simulator = new OsuLegacyScoreSimulator();
|
|
||||||
sv1Simulator.Simulate(workingBeatmap, beatmap, mods);
|
|
||||||
attributes.LegacyAccuracyScore = sv1Simulator.AccuracyScore;
|
|
||||||
attributes.LegacyComboScore = sv1Simulator.ComboScore;
|
|
||||||
attributes.LegacyBonusScoreRatio = sv1Simulator.BonusScoreRatio;
|
|
||||||
}
|
|
||||||
|
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,37 +2,27 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Mods;
|
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.Scoring.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Difficulty
|
namespace osu.Game.Rulesets.Osu.Difficulty
|
||||||
{
|
{
|
||||||
internal class OsuLegacyScoreSimulator : ILegacyScoreSimulator
|
internal class OsuLegacyScoreSimulator : ILegacyScoreSimulator
|
||||||
{
|
{
|
||||||
public int AccuracyScore { get; private set; }
|
|
||||||
|
|
||||||
public int ComboScore { get; private set; }
|
|
||||||
|
|
||||||
public double BonusScoreRatio => legacyBonusScore == 0 ? 0 : (double)modernBonusScore / legacyBonusScore;
|
|
||||||
|
|
||||||
private int legacyBonusScore;
|
private int legacyBonusScore;
|
||||||
private int modernBonusScore;
|
private int standardisedBonusScore;
|
||||||
private int combo;
|
private int combo;
|
||||||
|
|
||||||
private double scoreMultiplier;
|
private double scoreMultiplier;
|
||||||
private IBeatmap playableBeatmap = null!;
|
|
||||||
|
|
||||||
public void Simulate(IWorkingBeatmap workingBeatmap, IBeatmap playableBeatmap, IReadOnlyList<Mod> mods)
|
public LegacyScoreAttributes Simulate(IWorkingBeatmap workingBeatmap, IBeatmap playableBeatmap)
|
||||||
{
|
{
|
||||||
this.playableBeatmap = playableBeatmap;
|
|
||||||
|
|
||||||
IBeatmap baseBeatmap = workingBeatmap.Beatmap;
|
IBeatmap baseBeatmap = workingBeatmap.Beatmap;
|
||||||
|
|
||||||
int countNormal = 0;
|
int countNormal = 0;
|
||||||
@ -73,13 +63,19 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
+ baseBeatmap.Difficulty.CircleSize
|
+ baseBeatmap.Difficulty.CircleSize
|
||||||
+ Math.Clamp((float)objectCount / drainLength * 8, 0, 16)) / 38 * 5);
|
+ Math.Clamp((float)objectCount / drainLength * 8, 0, 16)) / 38 * 5);
|
||||||
|
|
||||||
scoreMultiplier = difficultyPeppyStars * mods.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier);
|
scoreMultiplier = difficultyPeppyStars;
|
||||||
|
|
||||||
|
LegacyScoreAttributes attributes = new LegacyScoreAttributes();
|
||||||
|
|
||||||
foreach (var obj in playableBeatmap.HitObjects)
|
foreach (var obj in playableBeatmap.HitObjects)
|
||||||
simulateHit(obj);
|
simulateHit(obj, ref attributes);
|
||||||
|
|
||||||
|
attributes.BonusScoreRatio = legacyBonusScore == 0 ? 0 : (double)standardisedBonusScore / legacyBonusScore;
|
||||||
|
|
||||||
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void simulateHit(HitObject hitObject)
|
private void simulateHit(HitObject hitObject, ref LegacyScoreAttributes attributes)
|
||||||
{
|
{
|
||||||
bool increaseCombo = true;
|
bool increaseCombo = true;
|
||||||
bool addScoreComboMultiplier = false;
|
bool addScoreComboMultiplier = false;
|
||||||
@ -122,7 +118,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
|
|
||||||
case Slider:
|
case Slider:
|
||||||
foreach (var nested in hitObject.NestedHitObjects)
|
foreach (var nested in hitObject.NestedHitObjects)
|
||||||
simulateHit(nested);
|
simulateHit(nested, ref attributes);
|
||||||
|
|
||||||
scoreIncrease = 300;
|
scoreIncrease = 300;
|
||||||
increaseCombo = false;
|
increaseCombo = false;
|
||||||
@ -133,22 +129,27 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
// The spinner object applies a lenience because gameplay mechanics differ from osu-stable.
|
// The spinner object applies a lenience because gameplay mechanics differ from osu-stable.
|
||||||
// We'll redo the calculations to match osu-stable here...
|
// We'll redo the calculations to match osu-stable here...
|
||||||
const double maximum_rotations_per_second = 477.0 / 60;
|
const double maximum_rotations_per_second = 477.0 / 60;
|
||||||
double minimumRotationsPerSecond = IBeatmapDifficultyInfo.DifficultyRange(playableBeatmap.Difficulty.OverallDifficulty, 3, 5, 7.5);
|
|
||||||
|
// Normally, this value depends on the final overall difficulty. For simplicity, we'll only consider the worst case that maximises bonus score.
|
||||||
|
// As we're primarily concerned with computing the maximum theoretical final score,
|
||||||
|
// this will have the final effect of slightly underestimating bonus score achieved on stable when converting from score V1.
|
||||||
|
const double minimum_rotations_per_second = 3;
|
||||||
|
|
||||||
double secondsDuration = spinner.Duration / 1000;
|
double secondsDuration = spinner.Duration / 1000;
|
||||||
|
|
||||||
// The total amount of half spins possible for the entire spinner.
|
// The total amount of half spins possible for the entire spinner.
|
||||||
int totalHalfSpinsPossible = (int)(secondsDuration * maximum_rotations_per_second * 2);
|
int totalHalfSpinsPossible = (int)(secondsDuration * maximum_rotations_per_second * 2);
|
||||||
// The amount of half spins that are required to successfully complete the spinner (i.e. get a 300).
|
// The amount of half spins that are required to successfully complete the spinner (i.e. get a 300).
|
||||||
int halfSpinsRequiredForCompletion = (int)(secondsDuration * minimumRotationsPerSecond);
|
int halfSpinsRequiredForCompletion = (int)(secondsDuration * minimum_rotations_per_second);
|
||||||
// To be able to receive bonus points, the spinner must be rotated another 1.5 times.
|
// To be able to receive bonus points, the spinner must be rotated another 1.5 times.
|
||||||
int halfSpinsRequiredBeforeBonus = halfSpinsRequiredForCompletion + 3;
|
int halfSpinsRequiredBeforeBonus = halfSpinsRequiredForCompletion + 3;
|
||||||
|
|
||||||
for (int i = 0; i <= totalHalfSpinsPossible; i++)
|
for (int i = 0; i <= totalHalfSpinsPossible; i++)
|
||||||
{
|
{
|
||||||
if (i > halfSpinsRequiredBeforeBonus && (i - halfSpinsRequiredBeforeBonus) % 2 == 0)
|
if (i > halfSpinsRequiredBeforeBonus && (i - halfSpinsRequiredBeforeBonus) % 2 == 0)
|
||||||
simulateHit(new SpinnerBonusTick());
|
simulateHit(new SpinnerBonusTick(), ref attributes);
|
||||||
else if (i > 1 && i % 2 == 0)
|
else if (i > 1 && i % 2 == 0)
|
||||||
simulateHit(new SpinnerTick());
|
simulateHit(new SpinnerTick(), ref attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
scoreIncrease = 300;
|
scoreIncrease = 300;
|
||||||
@ -159,16 +160,16 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
if (addScoreComboMultiplier)
|
if (addScoreComboMultiplier)
|
||||||
{
|
{
|
||||||
// ReSharper disable once PossibleLossOfFraction (intentional to match osu-stable...)
|
// ReSharper disable once PossibleLossOfFraction (intentional to match osu-stable...)
|
||||||
ComboScore += (int)(Math.Max(0, combo - 1) * (scoreIncrease / 25 * scoreMultiplier));
|
attributes.ComboScore += (int)(Math.Max(0, combo - 1) * (scoreIncrease / 25 * scoreMultiplier));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBonus)
|
if (isBonus)
|
||||||
{
|
{
|
||||||
legacyBonusScore += scoreIncrease;
|
legacyBonusScore += scoreIncrease;
|
||||||
modernBonusScore += Judgement.ToNumericResult(bonusResult);
|
standardisedBonusScore += Judgement.ToNumericResult(bonusResult);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
AccuracyScore += scoreIncrease;
|
attributes.AccuracyScore += scoreIncrease;
|
||||||
|
|
||||||
if (increaseCombo)
|
if (increaseCombo)
|
||||||
combo++;
|
combo++;
|
||||||
|
@ -33,6 +33,7 @@ using osu.Game.Rulesets.Osu.Statistics;
|
|||||||
using osu.Game.Rulesets.Osu.UI;
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
using osu.Game.Rulesets.Replays.Types;
|
using osu.Game.Rulesets.Replays.Types;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.Scoring.Legacy;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens.Edit.Setup;
|
using osu.Game.Screens.Edit.Setup;
|
||||||
|
@ -25,12 +25,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
|
|
||||||
public override int Version => 20220902;
|
public override int Version => 20220902;
|
||||||
|
|
||||||
private readonly IWorkingBeatmap workingBeatmap;
|
|
||||||
|
|
||||||
public TaikoDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
public TaikoDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
{
|
{
|
||||||
workingBeatmap = beatmap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
|
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
|
||||||
@ -99,15 +96,6 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
MaxCombo = beatmap.HitObjects.Count(h => h is Hit),
|
MaxCombo = beatmap.HitObjects.Count(h => h is Hit),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ComputeLegacyScoringValues)
|
|
||||||
{
|
|
||||||
TaikoLegacyScoreSimulator sv1Simulator = new TaikoLegacyScoreSimulator();
|
|
||||||
sv1Simulator.Simulate(workingBeatmap, beatmap, mods);
|
|
||||||
attributes.LegacyAccuracyScore = sv1Simulator.AccuracyScore;
|
|
||||||
attributes.LegacyComboScore = sv1Simulator.ComboScore;
|
|
||||||
attributes.LegacyBonusScoreRatio = sv1Simulator.BonusScoreRatio;
|
|
||||||
}
|
|
||||||
|
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,39 +2,29 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Mods;
|
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.Scoring.Legacy;
|
||||||
using osu.Game.Rulesets.Taiko.Objects;
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Difficulty
|
namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||||
{
|
{
|
||||||
internal class TaikoLegacyScoreSimulator : ILegacyScoreSimulator
|
internal class TaikoLegacyScoreSimulator : ILegacyScoreSimulator
|
||||||
{
|
{
|
||||||
public int AccuracyScore { get; private set; }
|
|
||||||
|
|
||||||
public int ComboScore { get; private set; }
|
|
||||||
|
|
||||||
public double BonusScoreRatio => legacyBonusScore == 0 ? 0 : (double)modernBonusScore / legacyBonusScore;
|
|
||||||
|
|
||||||
private int legacyBonusScore;
|
private int legacyBonusScore;
|
||||||
private int modernBonusScore;
|
private int standardisedBonusScore;
|
||||||
private int combo;
|
private int combo;
|
||||||
|
|
||||||
private double modMultiplier;
|
|
||||||
private int difficultyPeppyStars;
|
private int difficultyPeppyStars;
|
||||||
private IBeatmap playableBeatmap = null!;
|
private IBeatmap playableBeatmap = null!;
|
||||||
private IReadOnlyList<Mod> mods = null!;
|
|
||||||
|
|
||||||
public void Simulate(IWorkingBeatmap workingBeatmap, IBeatmap playableBeatmap, IReadOnlyList<Mod> mods)
|
public LegacyScoreAttributes Simulate(IWorkingBeatmap workingBeatmap, IBeatmap playableBeatmap)
|
||||||
{
|
{
|
||||||
this.playableBeatmap = playableBeatmap;
|
this.playableBeatmap = playableBeatmap;
|
||||||
this.mods = mods;
|
|
||||||
|
|
||||||
IBeatmap baseBeatmap = workingBeatmap.Beatmap;
|
IBeatmap baseBeatmap = workingBeatmap.Beatmap;
|
||||||
|
|
||||||
@ -76,13 +66,17 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
+ baseBeatmap.Difficulty.CircleSize
|
+ baseBeatmap.Difficulty.CircleSize
|
||||||
+ Math.Clamp((float)objectCount / drainLength * 8, 0, 16)) / 38 * 5);
|
+ Math.Clamp((float)objectCount / drainLength * 8, 0, 16)) / 38 * 5);
|
||||||
|
|
||||||
modMultiplier = mods.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier);
|
LegacyScoreAttributes attributes = new LegacyScoreAttributes();
|
||||||
|
|
||||||
foreach (var obj in playableBeatmap.HitObjects)
|
foreach (var obj in playableBeatmap.HitObjects)
|
||||||
simulateHit(obj);
|
simulateHit(obj, ref attributes);
|
||||||
|
|
||||||
|
attributes.BonusScoreRatio = legacyBonusScore == 0 ? 0 : (double)standardisedBonusScore / legacyBonusScore;
|
||||||
|
|
||||||
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void simulateHit(HitObject hitObject)
|
private void simulateHit(HitObject hitObject, ref LegacyScoreAttributes attributes)
|
||||||
{
|
{
|
||||||
bool increaseCombo = true;
|
bool increaseCombo = true;
|
||||||
bool addScoreComboMultiplier = false;
|
bool addScoreComboMultiplier = false;
|
||||||
@ -109,21 +103,24 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
case Swell swell:
|
case Swell swell:
|
||||||
// The taiko swell generally does not match the osu-stable implementation in any way.
|
// The taiko swell generally does not match the osu-stable implementation in any way.
|
||||||
// We'll redo the calculations to match osu-stable here...
|
// We'll redo the calculations to match osu-stable here...
|
||||||
double minimumRotationsPerSecond = IBeatmapDifficultyInfo.DifficultyRange(playableBeatmap.Difficulty.OverallDifficulty, 3, 5, 7.5);
|
|
||||||
double secondsDuration = swell.Duration / 1000;
|
// Normally, this value depends on the final overall difficulty. For simplicity, we'll only consider the worst case that maximises rotations.
|
||||||
|
const double minimum_rotations_per_second = 7.5;
|
||||||
|
|
||||||
// The amount of half spins that are required to successfully complete the spinner (i.e. get a 300).
|
// The amount of half spins that are required to successfully complete the spinner (i.e. get a 300).
|
||||||
int halfSpinsRequiredForCompletion = (int)(secondsDuration * minimumRotationsPerSecond);
|
int halfSpinsRequiredForCompletion = (int)(swell.Duration / 1000 * minimum_rotations_per_second);
|
||||||
|
|
||||||
halfSpinsRequiredForCompletion = (int)Math.Max(1, halfSpinsRequiredForCompletion * 1.65f);
|
halfSpinsRequiredForCompletion = (int)Math.Max(1, halfSpinsRequiredForCompletion * 1.65f);
|
||||||
|
|
||||||
if (mods.Any(m => m is ModDoubleTime))
|
//
|
||||||
halfSpinsRequiredForCompletion = Math.Max(1, (int)(halfSpinsRequiredForCompletion * 0.75f));
|
// Normally, this multiplier depends on the active mods (DT = 0.75, HT = 1.5). For simplicity, we'll only consider the worst case that maximises rotations.
|
||||||
if (mods.Any(m => m is ModHalfTime))
|
// This way, scores remain beatable at the cost of the conversion being slightly inaccurate.
|
||||||
halfSpinsRequiredForCompletion = Math.Max(1, (int)(halfSpinsRequiredForCompletion * 1.5f));
|
// - A perfect DT/NM score will have less than 1M total score (excluding bonus).
|
||||||
|
// - A perfect HT score will have 1M total score (excluding bonus).
|
||||||
|
//
|
||||||
|
halfSpinsRequiredForCompletion = Math.Max(1, (int)(halfSpinsRequiredForCompletion * 1.5f));
|
||||||
|
|
||||||
for (int i = 0; i <= halfSpinsRequiredForCompletion; i++)
|
for (int i = 0; i <= halfSpinsRequiredForCompletion; i++)
|
||||||
simulateHit(new SwellTick());
|
simulateHit(new SwellTick(), ref attributes);
|
||||||
|
|
||||||
scoreIncrease = 300;
|
scoreIncrease = 300;
|
||||||
addScoreComboMultiplier = true;
|
addScoreComboMultiplier = true;
|
||||||
@ -139,7 +136,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
|
|
||||||
case DrumRoll:
|
case DrumRoll:
|
||||||
foreach (var nested in hitObject.NestedHitObjects)
|
foreach (var nested in hitObject.NestedHitObjects)
|
||||||
simulateHit(nested);
|
simulateHit(nested, ref attributes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,8 +156,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
{
|
{
|
||||||
int oldScoreIncrease = scoreIncrease;
|
int oldScoreIncrease = scoreIncrease;
|
||||||
|
|
||||||
// ReSharper disable once PossibleLossOfFraction (intentional to match osu-stable...)
|
scoreIncrease += scoreIncrease / 35 * 2 * (difficultyPeppyStars + 1) * (Math.Min(100, combo) / 10);
|
||||||
scoreIncrease += (int)(scoreIncrease / 35 * 2 * (difficultyPeppyStars + 1) * modMultiplier) * (Math.Min(100, combo) / 10);
|
|
||||||
|
|
||||||
if (hitObject is Swell)
|
if (hitObject is Swell)
|
||||||
{
|
{
|
||||||
@ -185,15 +181,15 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
scoreIncrease -= comboScoreIncrease;
|
scoreIncrease -= comboScoreIncrease;
|
||||||
|
|
||||||
if (addScoreComboMultiplier)
|
if (addScoreComboMultiplier)
|
||||||
ComboScore += comboScoreIncrease;
|
attributes.ComboScore += comboScoreIncrease;
|
||||||
|
|
||||||
if (isBonus)
|
if (isBonus)
|
||||||
{
|
{
|
||||||
legacyBonusScore += scoreIncrease;
|
legacyBonusScore += scoreIncrease;
|
||||||
modernBonusScore += Judgement.ToNumericResult(bonusResult);
|
standardisedBonusScore += Judgement.ToNumericResult(bonusResult);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
AccuracyScore += scoreIncrease;
|
attributes.AccuracyScore += scoreIncrease;
|
||||||
|
|
||||||
if (increaseCombo)
|
if (increaseCombo)
|
||||||
combo++;
|
combo++;
|
||||||
|
@ -34,6 +34,7 @@ using osu.Game.Screens.Ranking.Statistics;
|
|||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Rulesets.Configuration;
|
using osu.Game.Rulesets.Configuration;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Rulesets.Scoring.Legacy;
|
||||||
using osu.Game.Rulesets.Taiko.Configuration;
|
using osu.Game.Rulesets.Taiko.Configuration;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko
|
namespace osu.Game.Rulesets.Taiko
|
||||||
|
@ -15,6 +15,7 @@ using osu.Game.Rulesets.Judgements;
|
|||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.Scoring.Legacy;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Database
|
namespace osu.Game.Database
|
||||||
@ -222,15 +223,9 @@ namespace osu.Game.Database
|
|||||||
throw new InvalidOperationException("Beatmap contains no hit objects!");
|
throw new InvalidOperationException("Beatmap contains no hit objects!");
|
||||||
|
|
||||||
ILegacyScoreSimulator sv1Simulator = legacyRuleset.CreateLegacyScoreSimulator();
|
ILegacyScoreSimulator sv1Simulator = legacyRuleset.CreateLegacyScoreSimulator();
|
||||||
|
LegacyScoreAttributes attributes = sv1Simulator.Simulate(beatmap, playableBeatmap);
|
||||||
|
|
||||||
sv1Simulator.Simulate(beatmap, playableBeatmap, mods);
|
return ConvertFromLegacyTotalScore(score, attributes);
|
||||||
|
|
||||||
return ConvertFromLegacyTotalScore(score, new DifficultyAttributes
|
|
||||||
{
|
|
||||||
LegacyAccuracyScore = sv1Simulator.AccuracyScore,
|
|
||||||
LegacyComboScore = sv1Simulator.ComboScore,
|
|
||||||
LegacyBonusScoreRatio = sv1Simulator.BonusScoreRatio
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -241,20 +236,21 @@ namespace osu.Game.Database
|
|||||||
/// (<see cref="DifficultyAttributes.LegacyAccuracyScore"/>, <see cref="DifficultyAttributes.LegacyComboScore"/>, and <see cref="DifficultyAttributes.LegacyBonusScoreRatio"/>)
|
/// (<see cref="DifficultyAttributes.LegacyAccuracyScore"/>, <see cref="DifficultyAttributes.LegacyComboScore"/>, and <see cref="DifficultyAttributes.LegacyBonusScoreRatio"/>)
|
||||||
/// for the beatmap which the score was set on.</param>
|
/// for the beatmap which the score was set on.</param>
|
||||||
/// <returns>The standardised total score.</returns>
|
/// <returns>The standardised total score.</returns>
|
||||||
public static long ConvertFromLegacyTotalScore(ScoreInfo score, DifficultyAttributes attributes)
|
public static long ConvertFromLegacyTotalScore(ScoreInfo score, LegacyScoreAttributes attributes)
|
||||||
{
|
{
|
||||||
if (!score.IsLegacyScore)
|
if (!score.IsLegacyScore)
|
||||||
return score.TotalScore;
|
return score.TotalScore;
|
||||||
|
|
||||||
Debug.Assert(score.LegacyTotalScore != null);
|
Debug.Assert(score.LegacyTotalScore != null);
|
||||||
|
|
||||||
int maximumLegacyAccuracyScore = attributes.LegacyAccuracyScore;
|
|
||||||
int maximumLegacyComboScore = attributes.LegacyComboScore;
|
|
||||||
double maximumLegacyBonusRatio = attributes.LegacyBonusScoreRatio;
|
|
||||||
double modMultiplier = score.Mods.Select(m => m.ScoreMultiplier).Aggregate(1.0, (c, n) => c * n);
|
double modMultiplier = score.Mods.Select(m => m.ScoreMultiplier).Aggregate(1.0, (c, n) => c * n);
|
||||||
|
|
||||||
|
int maximumLegacyAccuracyScore = attributes.AccuracyScore;
|
||||||
|
long maximumLegacyComboScore = (long)Math.Round(attributes.ComboScore * modMultiplier);
|
||||||
|
double maximumLegacyBonusRatio = attributes.BonusScoreRatio;
|
||||||
|
|
||||||
// The part of total score that doesn't include bonus.
|
// The part of total score that doesn't include bonus.
|
||||||
int maximumLegacyBaseScore = maximumLegacyAccuracyScore + maximumLegacyComboScore;
|
long maximumLegacyBaseScore = maximumLegacyAccuracyScore + maximumLegacyComboScore;
|
||||||
|
|
||||||
// The combo proportion is calculated as a proportion of maximumLegacyBaseScore.
|
// The combo proportion is calculated as a proportion of maximumLegacyBaseScore.
|
||||||
double comboProportion = Math.Min(1, (double)score.LegacyTotalScore / maximumLegacyBaseScore);
|
double comboProportion = Math.Min(1, (double)score.LegacyTotalScore / maximumLegacyBaseScore);
|
||||||
|
@ -27,9 +27,6 @@ namespace osu.Game.Rulesets.Difficulty
|
|||||||
protected const int ATTRIB_ID_FLASHLIGHT = 17;
|
protected const int ATTRIB_ID_FLASHLIGHT = 17;
|
||||||
protected const int ATTRIB_ID_SLIDER_FACTOR = 19;
|
protected const int ATTRIB_ID_SLIDER_FACTOR = 19;
|
||||||
protected const int ATTRIB_ID_SPEED_NOTE_COUNT = 21;
|
protected const int ATTRIB_ID_SPEED_NOTE_COUNT = 21;
|
||||||
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_RATIO = 27;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The mods which were applied to the beatmap.
|
/// The mods which were applied to the beatmap.
|
||||||
@ -91,9 +88,6 @@ namespace osu.Game.Rulesets.Difficulty
|
|||||||
public virtual IEnumerable<(int attributeId, object value)> ToDatabaseAttributes()
|
public virtual IEnumerable<(int attributeId, object value)> ToDatabaseAttributes()
|
||||||
{
|
{
|
||||||
yield return (ATTRIB_ID_MAX_COMBO, MaxCombo);
|
yield return (ATTRIB_ID_MAX_COMBO, MaxCombo);
|
||||||
yield return (ATTRIB_ID_LEGACY_ACCURACY_SCORE, LegacyAccuracyScore);
|
|
||||||
yield return (ATTRIB_ID_LEGACY_COMBO_SCORE, LegacyComboScore);
|
|
||||||
yield return (ATTRIB_ID_LEGACY_BONUS_SCORE_RATIO, LegacyBonusScoreRatio);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -104,11 +98,6 @@ namespace osu.Game.Rulesets.Difficulty
|
|||||||
public virtual void FromDatabaseAttributes(IReadOnlyDictionary<int, double> values, IBeatmapOnlineInfo onlineInfo)
|
public virtual void FromDatabaseAttributes(IReadOnlyDictionary<int, double> values, IBeatmapOnlineInfo onlineInfo)
|
||||||
{
|
{
|
||||||
MaxCombo = (int)values[ATTRIB_ID_MAX_COMBO];
|
MaxCombo = (int)values[ATTRIB_ID_MAX_COMBO];
|
||||||
|
|
||||||
// Temporarily allow these attributes to not exist so as to not block releases of server-side components while these attributes aren't populated/used yet.
|
|
||||||
LegacyAccuracyScore = (int)values.GetValueOrDefault(ATTRIB_ID_LEGACY_ACCURACY_SCORE);
|
|
||||||
LegacyComboScore = (int)values.GetValueOrDefault(ATTRIB_ID_LEGACY_COMBO_SCORE);
|
|
||||||
LegacyBonusScoreRatio = values.GetValueOrDefault(ATTRIB_ID_LEGACY_BONUS_SCORE_RATIO);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,13 +23,6 @@ namespace osu.Game.Rulesets.Difficulty
|
|||||||
{
|
{
|
||||||
public abstract class DifficultyCalculator
|
public abstract class DifficultyCalculator
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Whether legacy scoring values (ScoreV1) should be computed to populate the difficulty attributes
|
|
||||||
/// <see cref="DifficultyAttributes.LegacyAccuracyScore"/>, <see cref="DifficultyAttributes.LegacyComboScore"/>,
|
|
||||||
/// and <see cref="DifficultyAttributes.LegacyBonusScoreRatio"/>.
|
|
||||||
/// </summary>
|
|
||||||
public bool ComputeLegacyScoringValues;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The beatmap for which difficulty will be calculated.
|
/// The beatmap for which difficulty will be calculated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets
|
namespace osu.Game.Rulesets
|
||||||
{
|
{
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
// 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.Collections.Generic;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Rulesets.Mods;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Scoring
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Generates attributes which are required to calculate old-style Score V1 scores.
|
|
||||||
/// </summary>
|
|
||||||
public interface ILegacyScoreSimulator
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The accuracy portion of the legacy (ScoreV1) total score.
|
|
||||||
/// </summary>
|
|
||||||
int AccuracyScore { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The combo-multiplied portion of the legacy (ScoreV1) total score.
|
|
||||||
/// </summary>
|
|
||||||
int ComboScore { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A ratio of <c>new_bonus_score / old_bonus_score</c> for converting the bonus score of legacy scores to the new scoring.
|
|
||||||
/// This is made up of all judgements that would be <see cref="HitResult.SmallBonus"/> or <see cref="HitResult.LargeBonus"/>.
|
|
||||||
/// </summary>
|
|
||||||
double BonusScoreRatio { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Performs the simulation, computing the maximum <see cref="AccuracyScore"/>, <see cref="ComboScore"/>,
|
|
||||||
/// and <see cref="BonusScoreRatio"/> achievable for the given beatmap.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="workingBeatmap">The working beatmap.</param>
|
|
||||||
/// <param name="playableBeatmap">A playable version of the beatmap for the ruleset.</param>
|
|
||||||
/// <param name="mods">The applied mods.</param>
|
|
||||||
void Simulate(IWorkingBeatmap workingBeatmap, IBeatmap playableBeatmap, IReadOnlyList<Mod> mods);
|
|
||||||
}
|
|
||||||
}
|
|
20
osu.Game/Rulesets/Scoring/Legacy/ILegacyScoreSimulator.cs
Normal file
20
osu.Game/Rulesets/Scoring/Legacy/ILegacyScoreSimulator.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// 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.Game.Beatmaps;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Scoring.Legacy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Generates attributes which are required to calculate old-style Score V1 scores.
|
||||||
|
/// </summary>
|
||||||
|
public interface ILegacyScoreSimulator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Performs the simulation, computing the maximum scoring values achievable for the given beatmap.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="workingBeatmap">The working beatmap.</param>
|
||||||
|
/// <param name="playableBeatmap">A playable version of the beatmap for the ruleset.</param>
|
||||||
|
LegacyScoreAttributes Simulate(IWorkingBeatmap workingBeatmap, IBeatmap playableBeatmap);
|
||||||
|
}
|
||||||
|
}
|
23
osu.Game/Rulesets/Scoring/Legacy/LegacyScoreAttributes.cs
Normal file
23
osu.Game/Rulesets/Scoring/Legacy/LegacyScoreAttributes.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Scoring.Legacy
|
||||||
|
{
|
||||||
|
public struct LegacyScoreAttributes
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The accuracy portion of the legacy (ScoreV1) total score.
|
||||||
|
/// </summary>
|
||||||
|
public int AccuracyScore;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The combo-multiplied portion of the legacy (ScoreV1) total score.
|
||||||
|
/// </summary>
|
||||||
|
public long ComboScore;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A ratio of standardised score to legacy score for the bonus part of total score.
|
||||||
|
/// </summary>
|
||||||
|
public double BonusScoreRatio;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user