Revamp score processing to once more unify scoring methods

This commit is contained in:
smoogipooo
2017-09-12 21:05:50 +09:00
parent 0b94939474
commit abab2a4878
7 changed files with 61 additions and 300 deletions

View File

@ -15,27 +15,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring
{
internal class TaikoScoreProcessor : ScoreProcessor<TaikoHitObject>
{
/// <summary>
/// The maximum score achievable.
/// Does _not_ include bonus score - for bonus score see <see cref="bonusScore"/>.
/// </summary>
private const int max_score = 1000000;
/// <summary>
/// The amount of the score attributed to combo.
/// </summary>
private const double combo_portion_max = max_score * 0.2;
/// <summary>
/// The amount of the score attributed to accuracy.
/// </summary>
private const double accuracy_portion_max = max_score * 0.8;
/// <summary>
/// The factor used to determine relevance of combos.
/// </summary>
private const double combo_base = 4;
/// <summary>
/// The HP awarded by a <see cref="HitResult.Great"/> hit.
/// </summary>
@ -76,40 +55,16 @@ namespace osu.Game.Rulesets.Taiko.Scoring
/// <summary>
/// Taiko fails at the end of the map if the player has not half-filled their HP bar.
/// </summary>
public override bool HasFailed => totalHits == maxTotalHits && Health.Value <= 0.5;
public override bool HasFailed => Hits == MaxHits && Health.Value <= 0.5;
/// <summary>
/// The cumulative combo portion of the score.
/// </summary>
private double comboScore => combo_portion_max * comboPortion / maxComboPortion;
/// <summary>
/// The cumulative accuracy portion of the score.
/// </summary>
private double accuracyScore => accuracy_portion_max * Math.Pow(Accuracy, 3.6) * totalHits / maxTotalHits;
/// <summary>
/// The cumulative bonus score.
/// This is added on top of <see cref="max_score"/>, thus the total score can exceed <see cref="max_score"/>.
/// </summary>
private double bonusScore;
/// <summary>
/// The multiple of the original score added to the combo portion of the score
/// for correctly hitting a strong hit object with both keys.
/// </summary>
private double strongHitScale;
protected override double ComboPortion => 0.2;
protected override double AccuracyPortion => 0.8;
private double hpIncreaseTick;
private double hpIncreaseGreat;
private double hpIncreaseGood;
private double hpIncreaseMiss;
private double maxComboPortion;
private double comboPortion;
private int maxTotalHits;
private int totalHits;
public TaikoScoreProcessor()
{
}
@ -128,13 +83,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring
hpIncreaseGood = hpMultiplierNormal * hp_hit_good;
hpIncreaseMiss = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, hp_miss_min, hp_miss_mid, hp_miss_max);
var strongHits = beatmap.HitObjects.FindAll(o => o is Hit && o.IsStrong);
// This is a linear function that awards:
// 10 times bonus points for hitting a strong hit object with both keys with 30 strong hit objects in the map
// 3 times bonus points for hitting a strong hit object with both keys with 120 strong hit objects in the map
strongHitScale = -7d / 90d * MathHelper.Clamp(strongHits.Count, 30, 120) + 111d / 9d;
foreach (var obj in beatmap.HitObjects)
{
if (obj is Hit)
@ -163,46 +111,14 @@ namespace osu.Game.Rulesets.Taiko.Scoring
AddJudgement(new TaikoJudgement { Result = HitResult.Great });
}
}
maxTotalHits = totalHits;
maxComboPortion = comboPortion;
}
protected override void OnNewJudgement(Judgement judgement)
{
bool isStrong = judgement is TaikoStrongHitJudgement;
base.OnNewJudgement(judgement);
bool isTick = judgement is TaikoDrumRollTickJudgement;
// Don't consider ticks and strong hits as a type of hit that counts towards map completion
if (!isTick && !isStrong)
totalHits++;
// Apply score changes
if (judgement.IsHit)
{
double baseValue = judgement.NumericResult;
if (isStrong)
{
// Add increased score for the previous judgement by hitting a strong hit object with the second key
var prevJudgement = Judgements[Judgements.Count - 1];
baseValue = prevJudgement.NumericResult * strongHitScale;
}
// Add score to portions
if (judgement is TaikoDrumRollTickJudgement)
bonusScore += baseValue;
else
{
// A relevance factor that needs to be applied to make higher combos more relevant
// Value is capped at 400 combo
double comboRelevance = Math.Min(Math.Log(400, combo_base), Math.Max(0.5, Math.Log(Combo.Value, combo_base)));
comboPortion += baseValue * comboRelevance;
}
}
// Apply HP changes
switch (judgement.Result)
{
@ -221,20 +137,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring
Health.Value += hpIncreaseGreat;
break;
}
int scoreForAccuracy = 0;
int maxScoreForAccuracy = 0;
foreach (var j in Judgements)
{
var taikoJudgement = (TaikoJudgement)j;
scoreForAccuracy += taikoJudgement.ResultNumericForAccuracy;
maxScoreForAccuracy += taikoJudgement.MaxResultValueForAccuracy;
}
Accuracy.Value = (double)scoreForAccuracy / maxScoreForAccuracy;
TotalScore.Value = comboScore + accuracyScore + bonusScore;
}
protected override void Reset()
@ -242,10 +144,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring
base.Reset();
Health.Value = 0;
bonusScore = 0;
comboPortion = 0;
totalHits = 0;
}
}
}