diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
index afeef9341a..96cf4bcc24 100644
--- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
+++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
@@ -11,6 +11,7 @@ using osu.Framework.Bindables;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Extensions;
+using osu.Game.Online.Spectator;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
@@ -89,13 +90,16 @@ namespace osu.Game.Rulesets.Scoring
private readonly double comboPortion;
///
- /// Maximum achievable scoring values.
+ /// Scoring values for a perfect play.
///
private ScoringValues maximumScoringValues;
///
/// Maximum achievable scoring values up to the current point in time.
///
+ ///
+ /// This is only used to determine the accuracy with respect to the current point in time for an ongoing play session.
+ ///
private ScoringValues rollingMaximumScoringValues;
///
@@ -284,7 +288,7 @@ namespace osu.Game.Rulesets.Scoring
if (!ruleset.RulesetInfo.Equals(scoreInfo.Ruleset))
throw new ArgumentException($"Unexpected score ruleset. Expected \"{ruleset.RulesetInfo.ShortName}\" but was \"{scoreInfo.Ruleset.ShortName}\".");
- extractFromStatistics(scoreInfo.Statistics, out var current, out var maximum);
+ extractScoringValues(scoreInfo.Statistics, out var current, out var maximum);
current.MaxCombo = scoreInfo.MaxCombo;
return ComputeScore(mode, current, maximum);
@@ -307,7 +311,7 @@ namespace osu.Game.Rulesets.Scoring
if (!beatmapApplied)
throw new InvalidOperationException($"Cannot compute partial score without calling {nameof(ApplyBeatmap)}.");
- extractFromStatistics(scoreInfo.Statistics, out var current, out _);
+ extractScoringValues(scoreInfo.Statistics, out var current, out _);
current.MaxCombo = scoreInfo.MaxCombo;
return ComputeScore(mode, current, maximumScoringValues);
@@ -332,7 +336,7 @@ namespace osu.Game.Rulesets.Scoring
double accuracyRatio = scoreInfo.Accuracy;
double comboRatio = maxAchievableCombo > 0 ? (double)scoreInfo.MaxCombo / maxAchievableCombo : 1;
- extractFromStatistics(scoreInfo.Statistics, out var current, out var maximum);
+ extractScoringValues(scoreInfo.Statistics, out var current, out var maximum);
// For legacy osu!mania scores, a full-GREAT score has 100% accuracy. If combined with a full-combo, the score becomes indistinguishable from a full-PERFECT score.
// To get around this, the accuracy ratio is always recalculated based on the hit statistics rather than trusting the score.
@@ -452,7 +456,7 @@ namespace osu.Game.Rulesets.Scoring
if (frame.Header == null)
return;
- extractFromStatistics(frame.Header.Statistics, out var current, out var maximum);
+ extractScoringValues(frame.Header.Statistics, out var current, out var maximum);
currentScoringValues.BaseScore = current.BaseScore;
currentScoringValues.MaxCombo = frame.Header.MaxCombo;
rollingMaximumScoringValues.BaseScore = maximum.BaseScore;
@@ -468,7 +472,72 @@ namespace osu.Game.Rulesets.Scoring
OnResetFromReplayFrame?.Invoke();
}
- private void extractFromStatistics(IReadOnlyDictionary statistics, out ScoringValues current, out ScoringValues maximum)
+ #region ScoringValue extraction
+
+ ///
+ /// Applies a best-effort extraction of hit statistics into .
+ ///
+ ///
+ /// This method is useful in a variety of situations, with a few drawbacks that need to be considered:
+ ///
+ /// - The maximum will always be 0.
+ /// - The current and maximum will always be the same value.
+ ///
+ /// Consumers are expected to more accurately fill in the above values through external means.
+ ///
+ /// Ensure to fill in the maximum for use in
+ /// .
+ ///
+ ///
+ /// The score to extract scoring values from.
+ /// The "current" scoring values, representing the hit statistics as they appear.
+ /// The "maximum" scoring values, representing the hit statistics as if the maximum hit result was attained each time.
+ public void ExtractScoringValues(ScoreInfo scoreInfo, out ScoringValues current, out ScoringValues maximum)
+ {
+ extractScoringValues(scoreInfo.Statistics, out current, out maximum);
+ current.MaxCombo = scoreInfo.MaxCombo;
+ }
+
+ ///
+ /// Applies a best-effort extraction of hit statistics into .
+ ///
+ ///
+ /// This method is useful in a variety of situations, with a few drawbacks that need to be considered:
+ ///
+ /// - The maximum will always be 0.
+ /// - The current and maximum will always be the same value.
+ ///
+ /// Consumers are expected to more accurately fill in the above values through external means.
+ ///
+ /// Ensure to fill in the maximum for use in
+ /// .
+ ///
+ ///
+ /// The replay frame header to extract scoring values from.
+ /// The "current" scoring values, representing the hit statistics as they appear.
+ /// The "maximum" scoring values, representing the hit statistics as if the maximum hit result was attained each time.
+ public void ExtractScoringValues(FrameHeader header, out ScoringValues current, out ScoringValues maximum)
+ {
+ extractScoringValues(header.Statistics, out current, out maximum);
+ current.MaxCombo = header.MaxCombo;
+ }
+
+ ///
+ /// Applies a best-effort extraction of hit statistics into .
+ ///
+ ///
+ /// This method is useful in a variety of situations, with a few drawbacks that need to be considered:
+ ///
+ /// - The current will always be 0.
+ /// - The maximum will always be 0.
+ /// - The current and maximum will always be the same value.
+ ///
+ /// Consumers are expected to more accurately fill in the above values (especially the current ) via external means (e.g. ).
+ ///
+ /// The hit statistics to extract scoring values from.
+ /// The "current" scoring values, representing the hit statistics as they appear.
+ /// The "maximum" scoring values, representing the hit statistics as if the maximum hit result was attained each time.
+ private void extractScoringValues(IReadOnlyDictionary statistics, out ScoringValues current, out ScoringValues maximum)
{
current = default;
maximum = default;
@@ -479,10 +548,7 @@ namespace osu.Game.Rulesets.Scoring
continue;
if (result.IsBonus())
- {
current.BonusScore += count * Judgement.ToNumericResult(result);
- maximum.BonusScore += count * Judgement.ToNumericResult(result);
- }
else
{
// The maximum result of this judgement if it wasn't a miss.
@@ -511,10 +577,7 @@ namespace osu.Game.Rulesets.Scoring
}
if (result.AffectsCombo())
- {
- current.MaxCombo += count;
maximum.MaxCombo += count;
- }
if (result.IsBasic())
{
@@ -524,6 +587,8 @@ namespace osu.Game.Rulesets.Scoring
}
}
+ #endregion
+
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);