diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs
index dc6d5b28ee..c74d4b84e4 100644
--- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs
+++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs
@@ -17,51 +17,48 @@ namespace osu.Game.Rulesets.Catch.Scoring
private int maximumTinyDroplets;
private int hitTinyDroplets;
+ private int maximumBasicJudgements;
+ private int currentBasicJudgements;
public CatchScoreProcessor()
: base(new CatchRuleset())
{
}
- protected override double ComputeTotalScore()
+ protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion)
{
- double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1;
double fruitHitsRatio = maximumTinyDroplets == 0 ? 0 : (double)hitTinyDroplets / maximumTinyDroplets;
const int tiny_droplets_portion = 400000;
- return (
- ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * comboRatio +
- tiny_droplets_portion * tinyDropletScale * fruitHitsRatio +
- BonusPortion
- ) * ScoreMultiplier;
+ return ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * comboRatio
+ + tiny_droplets_portion * tinyDropletScale * fruitHitsRatio
+ + bonusPortion;
}
- protected override void AddScoreChange(JudgementResult result)
+ protected override double GetComboScoreChange(JudgementResult result)
+ => Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(combo_cap, combo_base));
+
+ protected override void ApplyScoreChange(JudgementResult result)
{
- var change = computeScoreChange(result);
- ComboPortion += change.combo;
- BonusPortion += change.bonus;
- hitTinyDroplets += change.tinyDropletHits;
+ base.ApplyScoreChange(result);
+
+ if (result.HitObject is TinyDroplet)
+ hitTinyDroplets++;
+
+ if (result.Type.IsBasic())
+ currentBasicJudgements++;
}
protected override void RemoveScoreChange(JudgementResult result)
{
- var change = computeScoreChange(result);
- ComboPortion -= change.combo;
- BonusPortion -= change.bonus;
- hitTinyDroplets -= change.tinyDropletHits;
- }
+ base.RemoveScoreChange(result);
- private (double combo, double bonus, int tinyDropletHits) computeScoreChange(JudgementResult result)
- {
if (result.HitObject is TinyDroplet)
- return (0, 0, 1);
+ hitTinyDroplets--;
- if (result.Type.IsBonus())
- return (0, Judgement.ToNumericResult(result.Type), 0);
-
- return (Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(combo_cap, combo_base)), 0, 0);
+ if (result.Type.IsBasic())
+ currentBasicJudgements--;
}
protected override void Reset(bool storeResults)
@@ -71,14 +68,16 @@ namespace osu.Game.Rulesets.Catch.Scoring
if (storeResults)
{
maximumTinyDroplets = hitTinyDroplets;
+ maximumBasicJudgements = currentBasicJudgements;
- if (maximumTinyDroplets + MaxBasicJudgements == 0)
+ if (maximumTinyDroplets + maximumBasicJudgements == 0)
tinyDropletScale = 0;
else
- tinyDropletScale = (double)maximumTinyDroplets / (maximumTinyDroplets + MaxBasicJudgements);
+ tinyDropletScale = (double)maximumTinyDroplets / (maximumTinyDroplets + maximumBasicJudgements);
}
hitTinyDroplets = 0;
+ currentBasicJudgements = 0;
}
}
}
diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs
index 544b9add32..214aded2d7 100644
--- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs
+++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs
@@ -16,38 +16,14 @@ namespace osu.Game.Rulesets.Mania.Scoring
{
}
- protected override double ComputeTotalScore()
+ protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion)
{
- double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1;
- double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1;
-
- return (
- 200000 * comboRatio +
- 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyRatio +
- BonusPortion
- ) * ScoreMultiplier;
+ return 200000 * comboRatio
+ + 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyRatio
+ + bonusPortion;
}
- protected override void AddScoreChange(JudgementResult result)
- {
- var change = computeScoreChange(result);
- ComboPortion += change.combo;
- BonusPortion += change.bonus;
- }
-
- protected override void RemoveScoreChange(JudgementResult result)
- {
- var change = computeScoreChange(result);
- ComboPortion -= change.combo;
- BonusPortion -= change.bonus;
- }
-
- private (double combo, double bonus) computeScoreChange(JudgementResult result)
- {
- if (result.Type.IsBonus())
- return (0, Judgement.ToNumericResult(result.Type));
-
- return (Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base)), 0);
- }
+ protected override double GetComboScoreChange(JudgementResult result)
+ => Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base));
}
}
diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs
index edd0880271..5028d5b8d6 100644
--- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs
+++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs
@@ -13,16 +13,11 @@ namespace osu.Game.Rulesets.Osu.Scoring
{
}
- protected override double ComputeTotalScore()
+ protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion)
{
- double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1;
- double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1;
-
- return (
- 700000 * comboRatio +
- 300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio +
- BonusPortion
- ) * ScoreMultiplier;
+ return 700000 * comboRatio
+ + 300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio
+ + bonusPortion;
}
}
}
diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs
index 32f4421ed2..e0f83505cf 100644
--- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs
+++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs
@@ -17,46 +17,28 @@ namespace osu.Game.Rulesets.Taiko.Scoring
{
}
- protected override double ComputeTotalScore()
+ protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion)
{
- double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1;
- double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1;
-
- return (
- 250000 * comboRatio +
- 750000 * Math.Pow(Accuracy.Value, 3.6) * accuracyRatio +
- BonusPortion
- ) * ScoreMultiplier;
+ return 250000 * comboRatio
+ + 750000 * Math.Pow(Accuracy.Value, 3.6) * accuracyRatio
+ + bonusPortion;
}
- protected override void AddScoreChange(JudgementResult result)
+ protected override double GetBonusScoreChange(JudgementResult result) => base.GetBonusScoreChange(result) * strongScaleValue(result);
+
+ protected override double GetComboScoreChange(JudgementResult result)
{
- var change = computeScoreChange(result);
- ComboPortion += change.combo;
- BonusPortion += change.bonus;
+ return Judgement.ToNumericResult(result.Type)
+ * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base))
+ * strongScaleValue(result);
}
- protected override void RemoveScoreChange(JudgementResult result)
+ private double strongScaleValue(JudgementResult result)
{
- var change = computeScoreChange(result);
- ComboPortion -= change.combo;
- BonusPortion -= change.bonus;
- }
-
- private (double combo, double bonus) computeScoreChange(JudgementResult result)
- {
- double hitValue = Judgement.ToNumericResult(result.Type);
-
if (result.HitObject is StrongNestedHitObject strong)
- {
- double strongBonus = strong.Parent is DrumRollTick ? 3 : 7;
- hitValue *= strongBonus;
- }
+ return strong.Parent is DrumRollTick ? 3 : 7;
- if (result.Type.IsBonus())
- return (0, hitValue);
-
- return (hitValue * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base)), 0);
+ return 1;
}
}
}
diff --git a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs
index 3dd7f934a8..64a04f896f 100644
--- a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs
+++ b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs
@@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Difficulty
ScoreProcessor scoreProcessor = ruleset.CreateScoreProcessor();
scoreProcessor.Mods.Value = perfectPlay.Mods;
scoreProcessor.ApplyBeatmap(playableBeatmap);
- perfectPlay.TotalScore = scoreProcessor.MaxTotalScore;
+ perfectPlay.TotalScore = scoreProcessor.MaximumTotalScore;
// compute rank achieved
// default to SS, then adjust the rank with mods
diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
index 0ec9c884c3..a94ee9c181 100644
--- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
+++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
@@ -90,10 +90,18 @@ namespace osu.Game.Rulesets.Scoring
///
/// The maximum achievable total score.
///
- public long MaxTotalScore { get; private set; }
+ public long MaximumTotalScore { get; private set; }
///
- /// The sum of all accuracy-affecting judgements at the current time.
+ /// The maximum sum of accuracy-affecting judgements at the current point in time.
+ ///
+ ///
+ /// Used to compute accuracy.
+ ///
+ private double currentMaximumBaseScore;
+
+ ///
+ /// The sum of all accuracy-affecting judgements at the current point in time.
///
///
/// Used to compute accuracy.
@@ -101,42 +109,34 @@ namespace osu.Game.Rulesets.Scoring
private double currentBaseScore;
///
- /// The maximum sum of accuracy-affecting judgements at the current time.
+ /// The count of all basic judgements in the beatmap.
///
- ///
- /// Used to compute accuracy.
- ///
- private double currentMaxBaseScore;
+ private int maximumCountBasicJudgements;
///
- /// The total count of basic judgements in the beatmap.
+ /// The count of basic judgements at the current point in time.
///
- protected int MaxBasicJudgements { get; private set; }
+ private int currentCountBasicJudgements;
///
- /// The current count of basic judgements by the player.
+ /// The maximum combo score in the beatmap.
///
- protected int CurrentBasicJudgements { get; private set; }
+ private double maximumComboPortion;
///
- /// The current combo score.
+ /// The combo score at the current point in time.
///
- protected double ComboPortion { get; set; }
+ private double currentComboPortion;
///
- /// The maximum achievable combo score.
+ /// The bonus score at the current point in time.
///
- protected double MaxComboPortion { get; private set; }
-
- ///
- /// The current bonus score.
- ///
- protected double BonusPortion { get; set; }
+ private double currentBonusPortion;
///
/// The total score multiplier.
///
- protected double ScoreMultiplier { get; private set; } = 1;
+ private double scoreMultiplier = 1;
public Dictionary MaximumStatistics
{
@@ -171,10 +171,10 @@ namespace osu.Game.Rulesets.Scoring
Mods.ValueChanged += mods =>
{
- ScoreMultiplier = 1;
+ scoreMultiplier = 1;
foreach (var m in mods.NewValue)
- ScoreMultiplier *= m.ScoreMultiplier;
+ scoreMultiplier *= m.ScoreMultiplier;
updateScore();
};
@@ -207,15 +207,21 @@ namespace osu.Game.Rulesets.Scoring
result.ComboAfterJudgement = Combo.Value;
if (result.Type.IsBasic())
- CurrentBasicJudgements++;
+ currentCountBasicJudgements++;
if (result.Type.AffectsAccuracy())
{
- currentMaxBaseScore += Judgement.ToNumericResult(result.Judgement.MaxResult);
+ currentMaximumBaseScore += Judgement.ToNumericResult(result.Judgement.MaxResult);
currentBaseScore += Judgement.ToNumericResult(result.Type);
}
- AddScoreChange(result);
+ if (result.Type.IsBonus())
+ currentBonusPortion += GetBonusScoreChange(result);
+
+ if (result.Type.AffectsCombo())
+ currentComboPortion += GetComboScoreChange(result);
+
+ ApplyScoreChange(result);
hitEvents.Add(CreateHitEvent(result));
lastHitObject = result.HitObject;
@@ -245,14 +251,20 @@ namespace osu.Game.Rulesets.Scoring
return;
if (result.Type.IsBasic())
- CurrentBasicJudgements--;
+ currentCountBasicJudgements--;
if (result.Type.AffectsAccuracy())
{
- currentMaxBaseScore -= Judgement.ToNumericResult(result.Judgement.MaxResult);
+ currentMaximumBaseScore -= Judgement.ToNumericResult(result.Judgement.MaxResult);
currentBaseScore -= Judgement.ToNumericResult(result.Type);
}
+ if (result.Type.IsBonus())
+ currentBonusPortion -= GetBonusScoreChange(result);
+
+ if (result.Type.AffectsCombo())
+ currentComboPortion -= GetComboScoreChange(result);
+
RemoveScoreChange(result);
Debug.Assert(hitEvents.Count > 0);
@@ -262,42 +274,37 @@ namespace osu.Game.Rulesets.Scoring
updateScore();
}
- protected virtual void AddScoreChange(JudgementResult result)
- {
- if (result.Type.IsBonus())
- BonusPortion += Judgement.ToNumericResult(result.Type);
+ protected virtual double GetBonusScoreChange(JudgementResult result) => Judgement.ToNumericResult(result.Type);
- if (result.Type.AffectsCombo())
- ComboPortion += Judgement.ToNumericResult(result.Type) * (1 + result.ComboAfterJudgement / 10d);
+ protected virtual double GetComboScoreChange(JudgementResult result) => Judgement.ToNumericResult(result.Type) * (1 + result.ComboAfterJudgement / 10d);
+
+ protected virtual void ApplyScoreChange(JudgementResult result)
+ {
}
protected virtual void RemoveScoreChange(JudgementResult result)
{
- if (result.Type.IsBonus())
- BonusPortion -= Judgement.ToNumericResult(result.Type);
-
- if (result.Type.AffectsCombo())
- ComboPortion -= Judgement.ToNumericResult(result.Type) * (1 + result.ComboAfterJudgement / 10d);
}
private void updateScore()
{
- Accuracy.Value = currentMaxBaseScore > 0 ? currentBaseScore / currentMaxBaseScore : 1;
- TotalScore.Value = (long)Math.Round(ComputeTotalScore());
+ Accuracy.Value = currentMaximumBaseScore > 0 ? currentBaseScore / currentMaximumBaseScore : 1;
+
+ double comboRatio = maximumComboPortion > 0 ? currentComboPortion / maximumComboPortion : 1;
+ double accuracyRatio = maximumCountBasicJudgements > 0 ? (double)currentCountBasicJudgements / maximumCountBasicJudgements : 1;
+
+ TotalScore.Value = (long)Math.Round(ComputeTotalScore(comboRatio, accuracyRatio, currentBonusPortion) * scoreMultiplier);
}
- protected virtual double ComputeTotalScore()
+ protected virtual double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion)
{
- double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1;
- double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1;
-
return
(int)Math.Round
((
700000 * comboRatio +
300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio +
- BonusPortion
- ) * ScoreMultiplier);
+ bonusPortion
+ ) * scoreMultiplier);
}
///
@@ -313,22 +320,22 @@ namespace osu.Game.Rulesets.Scoring
if (storeResults)
{
- MaxComboPortion = ComboPortion;
- MaxBasicJudgements = CurrentBasicJudgements;
+ maximumComboPortion = currentComboPortion;
+ maximumCountBasicJudgements = currentCountBasicJudgements;
maximumResultCounts.Clear();
maximumResultCounts.AddRange(scoreResultCounts);
- MaxTotalScore = TotalScore.Value;
+ MaximumTotalScore = TotalScore.Value;
}
scoreResultCounts.Clear();
currentBaseScore = 0;
- currentMaxBaseScore = 0;
- CurrentBasicJudgements = 0;
- ComboPortion = 0;
- BonusPortion = 0;
+ currentMaximumBaseScore = 0;
+ currentCountBasicJudgements = 0;
+ currentComboPortion = 0;
+ currentBonusPortion = 0;
TotalScore.Value = 0;
Accuracy.Value = 1;
@@ -338,7 +345,7 @@ namespace osu.Game.Rulesets.Scoring
HighestCombo.Value = 0;
currentBaseScore = 0;
- currentMaxBaseScore = 0;
+ currentMaximumBaseScore = 0;
}
///