From 2a2caeba3275a30c1a78ae46675da4d4cf8f61a1 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 16 Mar 2017 13:39:57 +0900 Subject: [PATCH 1/3] Add better failing support to ScoreProcessor. --- osu.Game/Modes/ScoreProcessor.cs | 85 +++++++++++++++++++++++--------- osu.Game/Screens/Play/Player.cs | 13 ++++- 2 files changed, 73 insertions(+), 25 deletions(-) diff --git a/osu.Game/Modes/ScoreProcessor.cs b/osu.Game/Modes/ScoreProcessor.cs index 35e19626b2..d042864f7d 100644 --- a/osu.Game/Modes/ScoreProcessor.cs +++ b/osu.Game/Modes/ScoreProcessor.cs @@ -12,6 +12,36 @@ namespace osu.Game.Modes { public abstract class ScoreProcessor { + /// + /// Invoked when the score is in a failing state. + /// + public event Action Failed; + + /// + /// The current total score. + /// + public readonly BindableDouble TotalScore = new BindableDouble { MinValue = 0 }; + + /// + /// The current accuracy. + /// + public readonly BindableDouble Accuracy = new BindableDouble { MinValue = 0, MaxValue = 1 }; + + /// + /// The current health. + /// + public readonly BindableDouble Health = new BindableDouble { MinValue = 0, MaxValue = 1 }; + + /// + /// The current combo. + /// + public readonly BindableInt Combo = new BindableInt(); + + /// + /// THe highest combo achieved by this score. + /// + 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(); - /// - /// 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. /// - public readonly BindableInt HighestCombo = new BindableInt(); - - /// - /// Called when we reach a failing health of zero. - /// - public event Action Failed; + /// Whether the score is in a failing state. + public abstract bool CheckFailed(); /// /// Notifies subscribers that the score is in a failed state. @@ -59,14 +76,14 @@ namespace osu.Game.Modes protected List Judgements; /// - /// Are we allowed to fail? + /// Whether the score is in a failable state. /// - protected bool CanFail => true; + protected virtual bool IsFailable => Health.Value == Health.MinValue; /// - /// Whether this ScoreProcessor has already triggered the failed event. + /// Whether this ScoreProcessor has already failed. /// - protected bool HasFailed { get; private set; } + private bool hasFailed; protected ScoreProcessor() { @@ -82,6 +99,10 @@ namespace osu.Game.Modes hitRenderer.OnJudgement += addJudgement; } + /// + /// Adds a judgement to this ScoreProcessor. + /// + /// The judgement to add. 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; } /// /// Resets this ScoreProcessor to a stale state. /// - 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; + } /// /// Update any values that potentially need post-processing on a judgement change. diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a4c7e84ce7..261d279600 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -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 { From 7764474cfeaa7fda32dbd8d1bb1a6f92ebe28463 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 16 Mar 2017 13:49:16 +0900 Subject: [PATCH 2/3] Fix possible nullref. --- osu.Game/Modes/ScoreProcessor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Modes/ScoreProcessor.cs b/osu.Game/Modes/ScoreProcessor.cs index d042864f7d..3900a79485 100644 --- a/osu.Game/Modes/ScoreProcessor.cs +++ b/osu.Game/Modes/ScoreProcessor.cs @@ -73,7 +73,7 @@ namespace osu.Game.Modes /// /// All judgements held by this ScoreProcessor. /// - protected List Judgements; + protected readonly List Judgements = new List(); /// /// Whether the score is in a failable state. @@ -95,7 +95,7 @@ namespace osu.Game.Modes protected ScoreProcessor(HitRenderer hitRenderer) : this() { - Judgements = new List(hitRenderer.Beatmap.HitObjects.Count); + Judgements.Capacity = hitRenderer.Beatmap.HitObjects.Count; hitRenderer.OnJudgement += addJudgement; } From b13340c3c8e93b5ce3707e8f7341bb5bf348c9f8 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 00:30:23 +0900 Subject: [PATCH 3/3] Move CheckFailed outside of Schedule(). --- osu.Game/Screens/Play/Player.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 261d279600..ec8cbb1438 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -239,18 +239,18 @@ namespace osu.Game.Screens.Play 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); 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 {