diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs
index c241c4cf41..3550d561c1 100644
--- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs
+++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
+using System.Linq;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Database;
using osu.Game.Rulesets.Objects.Types;
@@ -60,6 +61,11 @@ namespace osu.Game.Rulesets.Mania.Objects
tickSpacing = timingPoint.BeatLength / difficulty.SliderTickRate;
}
+ ///
+ /// Total number of hold note ticks.
+ ///
+ public int TotalTicks => Ticks.Count();
+
///
/// The scoring scoring ticks of the hold note.
///
diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs
index 7a9572a0c7..2f4ce075c3 100644
--- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs
+++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs
@@ -1,8 +1,11 @@
// Copyright (c) 2007-2017 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+using System;
+using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Rulesets.Mania.Objects;
+using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
@@ -10,6 +13,52 @@ namespace osu.Game.Rulesets.Mania.Scoring
{
internal class ManiaScoreProcessor : ScoreProcessor
{
+ ///
+ /// The maximum score achievable.
+ /// Does _not_ include bonus score - for bonus score see .
+ ///
+ private const int max_score = 1000000;
+
+ ///
+ /// The amount of the score attributed to combo.
+ ///
+ private const double combo_portion_max = max_score * 0.2;
+
+ ///
+ /// The amount of the score attributed to accuracy.
+ ///
+ private const double accuracy_portion_max = max_score * 0.8;
+
+ ///
+ /// The cumulative combo portion of the score.
+ ///
+ private double comboScore => combo_portion_max * comboPortion / maxComboPortion;
+
+ ///
+ /// The cumulative accuracy portion of the score.
+ ///
+ private double accuracyScore => accuracy_portion_max * Math.Pow(Accuracy, 4) * totalHits / maxTotalHits;
+
+ ///
+ /// The cumulative bonus score.
+ /// This is added on top of , thus the total score can exceed .
+ ///
+ private double bonusScore;
+
+ private double maxComboPortion;
+ private double comboPortion;
+ private int maxTotalHits;
+ private int totalHits;
+
+ private double hpIncreaseBad;
+ private double hpIncreaseOk;
+ private double hpIncreaseGood;
+ private double hpIncreaseGreat;
+ private double hpIncreasePerfect;
+ private double hpIncreaseTick;
+ private double hpIncreaseTickMiss;
+ private double hpIncreaseMiss;
+
public ManiaScoreProcessor()
{
}
@@ -19,8 +68,107 @@ namespace osu.Game.Rulesets.Mania.Scoring
{
}
+ protected override void ComputeTargets(Beatmap beatmap)
+ {
+ foreach (var obj in beatmap.HitObjects)
+ {
+ if (obj is Note)
+ {
+ AddJudgement(new ManiaJudgement
+ {
+ Result = HitResult.Hit,
+ ManiaResult = ManiaHitResult.Perfect
+ });
+ }
+ else if (obj is HoldNote)
+ {
+ // Head
+ AddJudgement(new ManiaJudgement
+ {
+ Result = HitResult.Hit,
+ ManiaResult = ManiaJudgement.MAX_HIT_RESULT
+ });
+
+ // Ticks
+ for (int i = 0; i < ((HoldNote)obj).TotalTicks; i++)
+ {
+ AddJudgement(new HoldNoteTickJudgement
+ {
+ Result = HitResult.Hit,
+ ManiaResult = ManiaJudgement.MAX_HIT_RESULT,
+ });
+ }
+
+ AddJudgement(new HoldNoteTailJudgement
+ {
+ Result = HitResult.Hit,
+ ManiaResult = ManiaJudgement.MAX_HIT_RESULT
+ });
+ }
+ }
+
+ maxTotalHits = totalHits;
+ maxComboPortion = comboPortion;
+ }
+
protected override void OnNewJudgement(ManiaJudgement judgement)
{
+ bool isTick = judgement is HoldNoteTickJudgement;
+
+ if (!isTick)
+ totalHits++;
+
+ switch (judgement.Result)
+ {
+ case HitResult.Miss:
+ if (isTick)
+ Health.Value += hpIncreaseTickMiss;
+ else
+ Health.Value += hpIncreaseMiss;
+ break;
+ case HitResult.Hit:
+ if (isTick)
+ {
+ Health.Value += hpIncreaseTick;
+ bonusScore += judgement.ResultValueForScore;
+ }
+ else
+ {
+ switch (judgement.ManiaResult)
+ {
+ case ManiaHitResult.Bad:
+ Health.Value += hpIncreaseBad;
+ break;
+ case ManiaHitResult.Ok:
+ Health.Value += hpIncreaseOk;
+ break;
+ case ManiaHitResult.Good:
+ Health.Value += hpIncreaseGood;
+ break;
+ case ManiaHitResult.Great:
+ Health.Value += hpIncreaseGreat;
+ break;
+ case ManiaHitResult.Perfect:
+ Health.Value += hpIncreasePerfect;
+ break;
+ }
+
+ comboPortion += judgement.ResultValueForScore;
+ }
+ break;
+ }
+
+ int scoreForAccuracy = 0;
+ int maxScoreForAccuracy = 0;
+
+ foreach (var j in Judgements)
+ {
+ scoreForAccuracy += j.ResultValueForAccuracy;
+ maxScoreForAccuracy += j.MaxResultValueForAccuracy;
+ }
+
+ Accuracy.Value = (double)scoreForAccuracy / maxScoreForAccuracy;
+ TotalScore.Value = comboScore + accuracyScore + bonusScore;
}
protected override void Reset()