Merge pull request #491 from smoogipooo/scoreprocessor_failing_improvements

Scoreprocessor failing improvements
This commit is contained in:
Dean Herbert 2017-03-17 01:03:35 +09:00 committed by GitHub
commit 847f96de94
2 changed files with 75 additions and 27 deletions

View File

@ -12,6 +12,36 @@ namespace osu.Game.Modes
{ {
public abstract class ScoreProcessor public abstract class ScoreProcessor
{ {
/// <summary>
/// Invoked when the score is in a failing state.
/// </summary>
public event Action Failed;
/// <summary>
/// The current total score.
/// </summary>
public readonly BindableDouble TotalScore = new BindableDouble { MinValue = 0 };
/// <summary>
/// The current accuracy.
/// </summary>
public readonly BindableDouble Accuracy = new BindableDouble { MinValue = 0, MaxValue = 1 };
/// <summary>
/// The current health.
/// </summary>
public readonly BindableDouble Health = new BindableDouble { MinValue = 0, MaxValue = 1 };
/// <summary>
/// The current combo.
/// </summary>
public readonly BindableInt Combo = new BindableInt();
/// <summary>
/// THe highest combo achieved by this score.
/// </summary>
public readonly BindableInt HighestCombo = new BindableInt();
public virtual Score GetScore() => new Score public virtual Score GetScore() => new Score
{ {
TotalScore = TotalScore, TotalScore = TotalScore,
@ -21,24 +51,11 @@ namespace osu.Game.Modes
Health = Health, Health = Health,
}; };
public readonly BindableDouble TotalScore = new BindableDouble { MinValue = 0 };
public readonly BindableDouble Accuracy = new BindableDouble { MinValue = 0, MaxValue = 1 };
public readonly BindableDouble Health = new BindableDouble { MinValue = 0, MaxValue = 1 };
public readonly BindableInt Combo = new BindableInt();
/// <summary> /// <summary>
/// Keeps track of the highest combo ever achieved in this play. /// Checks if the score is in a failing state.
/// This is handled automatically by ScoreProcessor.
/// </summary> /// </summary>
public readonly BindableInt HighestCombo = new BindableInt(); /// <returns>Whether the score is in a failing state.</returns>
public abstract bool CheckFailed();
/// <summary>
/// Called when we reach a failing health of zero.
/// </summary>
public event Action Failed;
/// <summary> /// <summary>
/// Notifies subscribers that the score is in a failed state. /// Notifies subscribers that the score is in a failed state.
@ -56,17 +73,17 @@ namespace osu.Game.Modes
/// <summary> /// <summary>
/// All judgements held by this ScoreProcessor. /// All judgements held by this ScoreProcessor.
/// </summary> /// </summary>
protected List<TJudgement> Judgements; protected readonly List<TJudgement> Judgements = new List<TJudgement>();
/// <summary> /// <summary>
/// Are we allowed to fail? /// Whether the score is in a failable state.
/// </summary> /// </summary>
protected bool CanFail => true; protected virtual bool IsFailable => Health.Value == Health.MinValue;
/// <summary> /// <summary>
/// Whether this ScoreProcessor has already triggered the failed event. /// Whether this ScoreProcessor has already failed.
/// </summary> /// </summary>
protected bool HasFailed { get; private set; } private bool hasFailed;
protected ScoreProcessor() protected ScoreProcessor()
{ {
@ -78,10 +95,14 @@ namespace osu.Game.Modes
protected ScoreProcessor(HitRenderer<TObject, TJudgement> hitRenderer) protected ScoreProcessor(HitRenderer<TObject, TJudgement> hitRenderer)
: this() : this()
{ {
Judgements = new List<TJudgement>(hitRenderer.Beatmap.HitObjects.Count); Judgements.Capacity = hitRenderer.Beatmap.HitObjects.Count;
hitRenderer.OnJudgement += addJudgement; hitRenderer.OnJudgement += addJudgement;
} }
/// <summary>
/// Adds a judgement to this ScoreProcessor.
/// </summary>
/// <param name="judgement">The judgement to add.</param>
private void addJudgement(TJudgement judgement) private void addJudgement(TJudgement judgement)
{ {
Judgements.Add(judgement); Judgements.Add(judgement);
@ -89,17 +110,35 @@ namespace osu.Game.Modes
UpdateCalculations(judgement); UpdateCalculations(judgement);
judgement.ComboAtHit = (ulong)Combo.Value; judgement.ComboAtHit = (ulong)Combo.Value;
if (Health.Value == Health.MinValue && !HasFailed)
CheckFailed();
}
public override bool CheckFailed()
{ {
HasFailed = true; if (!hasFailed && IsFailable)
{
hasFailed = true;
TriggerFailed(); TriggerFailed();
} }
return hasFailed;
} }
/// <summary> /// <summary>
/// Resets this ScoreProcessor to a stale state. /// Resets this ScoreProcessor to a stale state.
/// </summary> /// </summary>
protected virtual void Reset() { } protected virtual void Reset()
{
Judgements.Clear();
hasFailed = false;
TotalScore.Value = 0;
Accuracy.Value = 0;
Health.Value = 0;
Combo.Value = 0;
HighestCombo.Value = 0;
}
/// <summary> /// <summary>
/// Update any values that potentially need post-processing on a judgement change. /// Update any values that potentially need post-processing on a judgement change.

View File

@ -135,7 +135,7 @@ namespace osu.Game.Screens.Play
hudOverlay.BindHitRenderer(hitRenderer); hudOverlay.BindHitRenderer(hitRenderer);
//bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation)
hitRenderer.OnAllJudged += onPass; hitRenderer.OnAllJudged += onCompletion;
//bind ScoreProcessor to ourselves (for a fail situation) //bind ScoreProcessor to ourselves (for a fail situation)
scoreProcessor.Failed += onFail; scoreProcessor.Failed += onFail;
@ -237,8 +237,17 @@ namespace osu.Game.Screens.Play
}); });
} }
private void onPass() private void onCompletion()
{ {
// Force a final check to see if the player has failed
// Some game modes (e.g. taiko) fail at the end of the map
if (scoreProcessor.CheckFailed())
{
// If failed, onFail will be invoked which will push a new screen.
// Let's not push the completion screen in this case
return;
}
Delay(1000); Delay(1000);
Schedule(delegate Schedule(delegate
{ {