mirror of
https://github.com/ppy/osu.git
synced 2024-12-13 08:32:57 +08:00
Update classic scoring algorithm to closer match stable score V1
This commit is contained in:
parent
81130eacd1
commit
57c00e728b
@ -27,44 +27,37 @@ namespace osu.Game.Scoring.Legacy
|
||||
.DefaultIfEmpty(0)
|
||||
.Sum();
|
||||
|
||||
// This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring.
|
||||
// The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes.
|
||||
double scaledRawScore = score / ScoreProcessor.MAX_SCORE;
|
||||
|
||||
return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, maxBasicJudgements), 2) * getStandardisedToClassicMultiplier(rulesetId));
|
||||
return convertStandardisedToClassic(rulesetId, score, maxBasicJudgements);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a ballpark multiplier which gives a similar "feel" for how large scores should get when displayed in "classic" mode.
|
||||
/// Returns a ballpark "classic" score which gives a similar "feel" to stable.
|
||||
/// This is different per ruleset to match the different algorithms used in the scoring implementation.
|
||||
/// </summary>
|
||||
private static double getStandardisedToClassicMultiplier(int rulesetId)
|
||||
/// <remarks>
|
||||
/// The coefficients chosen here were determined by a least-squares fit performed over all beatmaps
|
||||
/// with the goal of minimising the relative error of maximum possible base score (without bonus).
|
||||
/// The constant coefficients (100000, 1 / 10d) - while being detrimental to the least-squares fit - are forced,
|
||||
/// so that every 10 points in standardised mode converts to at least 1 point in classic mode.
|
||||
/// This is done to account for bonus judgements in a way that does not reorder scores.
|
||||
/// </remarks>
|
||||
private static long convertStandardisedToClassic(int rulesetId, long standardisedTotalScore, int objectCount)
|
||||
{
|
||||
double multiplier;
|
||||
|
||||
switch (rulesetId)
|
||||
{
|
||||
// For non-legacy rulesets, just go with the same as the osu! ruleset.
|
||||
// This is arbitrary, but at least allows the setting to do something to the score.
|
||||
default:
|
||||
case 0:
|
||||
multiplier = 36;
|
||||
break;
|
||||
return (long)Math.Round((objectCount * objectCount * 32.57 + 100000) * standardisedTotalScore / ScoreProcessor.MAX_SCORE);
|
||||
|
||||
case 1:
|
||||
multiplier = 22;
|
||||
break;
|
||||
return (long)Math.Round((objectCount * 1109 + 100000) * standardisedTotalScore / ScoreProcessor.MAX_SCORE);
|
||||
|
||||
case 2:
|
||||
multiplier = 28;
|
||||
break;
|
||||
return (long)Math.Round(Math.Pow(standardisedTotalScore / ScoreProcessor.MAX_SCORE * objectCount, 2) * 21.62 + standardisedTotalScore / 10d);
|
||||
|
||||
case 3:
|
||||
multiplier = 16;
|
||||
break;
|
||||
default:
|
||||
return standardisedTotalScore;
|
||||
}
|
||||
|
||||
return multiplier;
|
||||
}
|
||||
|
||||
public static int? GetCountGeki(this ScoreInfo scoreInfo)
|
||||
|
Loading…
Reference in New Issue
Block a user