1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-22 17:27:39 +08:00

Add better failing support to ScoreProcessor.

This commit is contained in:
smoogipooo 2017-03-16 13:39:57 +09:00
parent 5cafec3b6a
commit 2a2caeba32
2 changed files with 73 additions and 25 deletions

View File

@ -12,6 +12,36 @@ namespace osu.Game.Modes
{
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
{
TotalScore = TotalScore,
@ -21,24 +51,11 @@ namespace osu.Game.Modes
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>
/// Keeps track of the highest combo ever achieved in this play.
/// This is handled automatically by ScoreProcessor.
/// Checks if the score is in a failing state.
/// </summary>
public readonly BindableInt HighestCombo = new BindableInt();
/// <summary>
/// Called when we reach a failing health of zero.
/// </summary>
public event Action Failed;
/// <returns>Whether the score is in a failing state.</returns>
public abstract bool CheckFailed();
/// <summary>
/// Notifies subscribers that the score is in a failed state.
@ -59,14 +76,14 @@ namespace osu.Game.Modes
protected List<TJudgement> Judgements;
/// <summary>
/// Are we allowed to fail?
/// Whether the score is in a failable state.
/// </summary>
protected bool CanFail => true;
protected virtual bool IsFailable => Health.Value == Health.MinValue;
/// <summary>
/// Whether this ScoreProcessor has already triggered the failed event.
/// Whether this ScoreProcessor has already failed.
/// </summary>
protected bool HasFailed { get; private set; }
private bool hasFailed;
protected ScoreProcessor()
{
@ -82,6 +99,10 @@ namespace osu.Game.Modes
hitRenderer.OnJudgement += addJudgement;
}
/// <summary>
/// Adds a judgement to this ScoreProcessor.
/// </summary>
/// <param name="judgement">The judgement to add.</param>
private void addJudgement(TJudgement judgement)
{
Judgements.Add(judgement);
@ -89,17 +110,35 @@ namespace osu.Game.Modes
UpdateCalculations(judgement);
judgement.ComboAtHit = (ulong)Combo.Value;
if (Health.Value == Health.MinValue && !HasFailed)
CheckFailed();
}
public override bool CheckFailed()
{
if (!hasFailed && IsFailable)
{
HasFailed = true;
hasFailed = true;
TriggerFailed();
}
return hasFailed;
}
/// <summary>
/// Resets this ScoreProcessor to a stale state.
/// </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>
/// 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);
//bind HitRenderer to ScoreProcessor and ourselves (for a pass situation)
hitRenderer.OnAllJudged += onPass;
hitRenderer.OnAllJudged += onCompletion;
//bind ScoreProcessor to ourselves (for a fail situation)
scoreProcessor.Failed += onFail;
@ -237,11 +237,20 @@ namespace osu.Game.Screens.Play
});
}
private void onPass()
private void onCompletion()
{
Delay(1000);
Schedule(delegate
{
// 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 called which will push a new screen.
// Let's not push the completion screen in this case
return;
}
ValidForResume = false;
Push(new Results
{