diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 0e5df329d8..0048566b15 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// /// Taiko fails at the end of the map if the player has not half-filled their HP bar. /// - protected override bool FailCondition => Hits == MaxHits && Health.Value <= 0.5; + protected override bool DefaultFailCondition => Hits == MaxHits && Health.Value <= 0.5; private double hpIncreaseTick; private double hpIncreaseGreat; diff --git a/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs b/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs new file mode 100644 index 0000000000..db9b713c59 --- /dev/null +++ b/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Mods +{ + /// + /// An interface for mods that make general adjustments to score processor. + /// + public interface IApplicableToScoreProcessor + { + void ApplyToScoreProcessor(ScoreProcessor scoreProcessor); + } +} diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 082370ea5d..59539d2b2c 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Rulesets.Scoring; + namespace osu.Game.Rulesets.Mods { public abstract class ModPerfect : ModSuddenDeath @@ -8,5 +10,7 @@ namespace osu.Game.Rulesets.Mods public override string Name => "Perfect"; public override string ShortenedName => "PF"; public override string Description => "SS or quit."; + + protected override bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Accuracy.Value != 1; } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 999cb40f89..bc42c69cbe 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -3,10 +3,11 @@ using System; using osu.Game.Graphics; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModSuddenDeath : Mod + public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor { public override string Name => "Sudden Death"; public override string ShortenedName => "SD"; @@ -16,5 +17,12 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 1; public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; + + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + { + scoreProcessor.FailConditions += FailCondition; + } + + protected virtual bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Combo.Value == 0; } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 4dd88600b2..7b26e50dd8 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -31,6 +31,11 @@ namespace osu.Game.Rulesets.Scoring /// public event Action NewJudgement; + /// + /// Additional conditions on top of that cause a failing state. + /// + public event Func FailConditions; + /// /// The current total score. /// @@ -72,9 +77,9 @@ namespace osu.Game.Rulesets.Scoring public virtual bool HasFailed { get; private set; } /// - /// The conditions for failing. + /// The default conditions for failing. /// - protected virtual bool FailCondition => Health.Value == Health.MinValue; + protected virtual bool DefaultFailCondition => Health.Value == Health.MinValue; protected ScoreProcessor() { @@ -121,7 +126,10 @@ namespace osu.Game.Rulesets.Scoring /// protected void UpdateFailed() { - if (HasFailed || !FailCondition) + if (HasFailed) + return; + + if (!DefaultFailCondition && FailConditions?.Invoke(this) != true) return; if (Failed?.Invoke() != false) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 3e57e18963..cd2818398d 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -227,6 +227,9 @@ namespace osu.Game.Screens.Play // Bind ScoreProcessor to ourselves scoreProcessor.AllJudged += onCompletion; scoreProcessor.Failed += onFail; + + foreach (var mod in Beatmap.Value.Mods.Value.OfType()) + mod.ApplyToScoreProcessor(scoreProcessor); } private void applyRateFromMods() diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3b4434d1f4..c3af014fe1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -298,6 +298,7 @@ +