1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 16:07:24 +08:00

Change catch scoring to match score V2

This commit is contained in:
Bartłomiej Dach 2024-01-02 21:58:44 +01:00
parent 16c7c14602
commit 8295ad1feb
No known key found for this signature in database
2 changed files with 69 additions and 15 deletions

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
@ -20,20 +21,73 @@ namespace osu.Game.Rulesets.Catch.Scoring
private const int combo_cap = 200;
private const double combo_base = 4;
private double fruitTinyScale;
public CatchScoreProcessor()
: base(new CatchRuleset())
{
}
protected override void Reset(bool storeResults)
{
base.Reset(storeResults);
// large ticks are *purposefully* not counted to match stable
int fruitTinyScaleDivisor = MaximumResultCounts.GetValueOrDefault(HitResult.SmallTickHit) + MaximumResultCounts.GetValueOrDefault(HitResult.Great);
fruitTinyScale = fruitTinyScaleDivisor == 0
? 0
: (double)MaximumResultCounts.GetValueOrDefault(HitResult.SmallTickHit) / fruitTinyScaleDivisor;
}
protected override double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion)
{
return 600000 * comboProgress
+ 400000 * Accuracy.Value * accuracyProgress
const int max_tiny_droplets_portion = 400000;
double comboPortion = 1000000 - max_tiny_droplets_portion + max_tiny_droplets_portion * (1 - fruitTinyScale);
double dropletsPortion = max_tiny_droplets_portion * fruitTinyScale;
double dropletsHit = MaximumResultCounts.GetValueOrDefault(HitResult.SmallTickHit) == 0
? 0
: (double)ScoreResultCounts.GetValueOrDefault(HitResult.SmallTickHit) / MaximumResultCounts.GetValueOrDefault(HitResult.SmallTickHit);
return comboPortion * comboProgress
+ dropletsPortion * dropletsHit
+ bonusPortion;
}
public override int GetBaseScoreForResult(HitResult result)
{
switch (result)
{
// dirty hack to emulate accuracy on stable weighting every object equally in accuracy portion
case HitResult.Great:
case HitResult.LargeTickHit:
case HitResult.SmallTickHit:
return 300;
case HitResult.LargeBonus:
return 200;
}
return base.GetBaseScoreForResult(result);
}
protected override double GetComboScoreChange(JudgementResult result)
=> GetBaseScoreForResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(combo_cap, combo_base));
{
double baseIncrease = 0;
switch (result.Type)
{
case HitResult.Great:
baseIncrease = 300;
break;
case HitResult.LargeTickHit:
baseIncrease = 100;
break;
}
return baseIncrease * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(combo_cap, combo_base));
}
public override ScoreRank RankFromAccuracy(double accuracy)
{

View File

@ -167,14 +167,14 @@ namespace osu.Game.Rulesets.Scoring
if (!beatmapApplied)
throw new InvalidOperationException($"Cannot access maximum statistics before calling {nameof(ApplyBeatmap)}.");
return new Dictionary<HitResult, int>(maximumResultCounts);
return new Dictionary<HitResult, int>(MaximumResultCounts);
}
}
private bool beatmapApplied;
private readonly Dictionary<HitResult, int> scoreResultCounts = new Dictionary<HitResult, int>();
private readonly Dictionary<HitResult, int> maximumResultCounts = new Dictionary<HitResult, int>();
protected readonly Dictionary<HitResult, int> ScoreResultCounts = new Dictionary<HitResult, int>();
protected readonly Dictionary<HitResult, int> MaximumResultCounts = new Dictionary<HitResult, int>();
private readonly List<HitEvent> hitEvents = new List<HitEvent>();
private HitObject? lastHitObject;
@ -216,7 +216,7 @@ namespace osu.Game.Rulesets.Scoring
if (result.FailedAtJudgement)
return;
scoreResultCounts[result.Type] = scoreResultCounts.GetValueOrDefault(result.Type) + 1;
ScoreResultCounts[result.Type] = ScoreResultCounts.GetValueOrDefault(result.Type) + 1;
if (result.Type.IncreasesCombo())
Combo.Value++;
@ -272,7 +272,7 @@ namespace osu.Game.Rulesets.Scoring
if (result.FailedAtJudgement)
return;
scoreResultCounts[result.Type] = scoreResultCounts.GetValueOrDefault(result.Type) - 1;
ScoreResultCounts[result.Type] = ScoreResultCounts.GetValueOrDefault(result.Type) - 1;
if (result.Judgement.MaxResult.AffectsAccuracy())
{
@ -394,13 +394,13 @@ namespace osu.Game.Rulesets.Scoring
maximumComboPortion = currentComboPortion;
maximumAccuracyJudgementCount = currentAccuracyJudgementCount;
maximumResultCounts.Clear();
maximumResultCounts.AddRange(scoreResultCounts);
MaximumResultCounts.Clear();
MaximumResultCounts.AddRange(ScoreResultCounts);
MaximumTotalScore = TotalScore.Value;
}
scoreResultCounts.Clear();
ScoreResultCounts.Clear();
currentBaseScore = 0;
currentMaximumBaseScore = 0;
@ -430,10 +430,10 @@ namespace osu.Game.Rulesets.Scoring
score.MaximumStatistics.Clear();
foreach (var result in HitResultExtensions.ALL_TYPES)
score.Statistics[result] = scoreResultCounts.GetValueOrDefault(result);
score.Statistics[result] = ScoreResultCounts.GetValueOrDefault(result);
foreach (var result in HitResultExtensions.ALL_TYPES)
score.MaximumStatistics[result] = maximumResultCounts.GetValueOrDefault(result);
score.MaximumStatistics[result] = MaximumResultCounts.GetValueOrDefault(result);
// Populate total score after everything else.
score.TotalScore = TotalScore.Value;
@ -464,8 +464,8 @@ namespace osu.Game.Rulesets.Scoring
HighestCombo.Value = frame.Header.MaxCombo;
TotalScore.Value = frame.Header.TotalScore;
scoreResultCounts.Clear();
scoreResultCounts.AddRange(frame.Header.Statistics);
ScoreResultCounts.Clear();
ScoreResultCounts.AddRange(frame.Header.Statistics);
SetScoreProcessorStatistics(frame.Header.ScoreProcessorStatistics);