diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs new file mode 100644 index 0000000000..d0db193738 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs @@ -0,0 +1,68 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Beatmaps; +using osu.Game.Rulesets.Taiko.Mods; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Screens.Play; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + public class TestSceneTaikoSuddenDeath : PlayerTestScene + { + public TestSceneTaikoSuddenDeath() + : base(new TaikoRuleset()) + { + } + + protected override bool AllowFail => true; + + protected override Player CreatePlayer(Ruleset ruleset) + { + Mods.Value = Mods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray(); + return new ScoreAccessiblePlayer(); + } + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => + new TaikoBeatmap + { + HitObjects = + { + new Swell { StartTime = 1500 }, + new Hit { StartTime = 100000 }, + }, + BeatmapInfo = + { + Ruleset = new TaikoRuleset().RulesetInfo + } + }; + + [Test] + public void TestSpinnerDoesNotFail() + { + bool judged = false; + AddStep("Setup judgements", () => + { + judged = false; + ((ScoreAccessiblePlayer)Player).ScoreProcessor.NewJudgement += b => judged = true; + }); + AddUntilStep("swell judged", () => judged); + AddAssert("not failed", () => !Player.HasFailed); + } + + private class ScoreAccessiblePlayer : TestPlayer + { + public ScoreAccessiblePlayer() + : base(false, false) + { + } + + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + } + } +} diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs index f06f72615b..f4e8a68819 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void LoadComplete() { base.LoadComplete(); - ScoreProcessor.FailConditions += _ => true; + ScoreProcessor.FailConditions += (_, __) => true; } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 5a903b9417..80408ab43b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestOsuMods() { var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 0); - AddStep("change ruleset", () => { Ruleset.Value = ruleset; }); + changeRuleset(ruleset); var instance = ruleset.CreateInstance(); @@ -108,7 +108,7 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestManiaMods() { var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 3); - AddStep("change ruleset", () => { Ruleset.Value = ruleset; }); + changeRuleset(ruleset); testRankedText(ruleset.CreateInstance().GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom)); } @@ -119,7 +119,7 @@ namespace osu.Game.Tests.Visual.UserInterface var rulesetOsu = rulesets.AvailableRulesets.First(r => r.ID == 0); var rulesetMania = rulesets.AvailableRulesets.First(r => r.ID == 3); - AddStep("change ruleset to null", () => { Ruleset.Value = null; }); + changeRuleset(null); var instance = rulesetOsu.CreateInstance(); var easierMods = instance.GetModsFor(ModType.DifficultyReduction); @@ -127,15 +127,15 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("set mods externally", () => { modDisplay.Current.Value = new[] { noFailMod }; }); - AddStep("change ruleset to osu", () => { Ruleset.Value = rulesetOsu; }); + changeRuleset(rulesetOsu); AddAssert("ensure mods still selected", () => modDisplay.Current.Value.Single(m => m is OsuModNoFail) != null); - AddStep("change ruleset to mania", () => { Ruleset.Value = rulesetMania; }); + changeRuleset(rulesetMania); AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any(m => m is OsuModNoFail)); - AddStep("change ruleset to osu", () => { Ruleset.Value = rulesetOsu; }); + changeRuleset(rulesetOsu); AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any()); } @@ -216,14 +216,11 @@ namespace osu.Game.Tests.Visual.UserInterface private void testRankedText(Mod mod) { - waitForLoad(); - AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); + AddUntilStep("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); selectNext(mod); - waitForLoad(); - AddAssert("check for unranked", () => modSelect.UnrankedLabel.Alpha != 0); + AddUntilStep("check for unranked", () => modSelect.UnrankedLabel.Alpha != 0); selectPrevious(mod); - waitForLoad(); - AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); + AddUntilStep("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); } private void selectNext(Mod mod) => AddStep($"left click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectNext(1)); @@ -232,7 +229,6 @@ namespace osu.Game.Tests.Visual.UserInterface private void checkSelected(Mod mod) { - waitForLoad(); AddAssert($"check {mod.Name} is selected", () => { var button = modSelect.GetModButton(mod); @@ -240,14 +236,17 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private void waitForLoad() + private void changeRuleset(RulesetInfo ruleset) { - AddUntilStep("wait for icons to load", () => modSelect.AllLoaded); + AddStep($"change ruleset to {ruleset}", () => { Ruleset.Value = ruleset; }); + waitForLoad(); } + private void waitForLoad() => + AddUntilStep("wait for icons to load", () => modSelect.AllLoaded); + private void checkNotSelected(Mod mod) { - waitForLoad(); AddAssert($"check {mod.Name} is not selected", () => { var button = modSelect.GetModButton(mod); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 692e7189a3..35684849a3 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -181,10 +181,10 @@ namespace osu.Game configSkin.ValueChanged += skinId => SkinManager.CurrentSkinInfo.Value = SkinManager.Query(s => s.ID == skinId.NewValue) ?? SkinInfo.Default; configSkin.TriggerChange(); - LocalConfig.BindWith(OsuSetting.VolumeInactive, userInactiveVolume); - IsActive.BindValueChanged(active => updateActiveState(active.NewValue), true); + Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade); + Beatmap.BindValueChanged(beatmapChanged, true); } @@ -707,22 +707,14 @@ namespace osu.Game #region Inactive audio dimming - private readonly BindableDouble userInactiveVolume = new BindableDouble(); - private readonly BindableDouble inactiveVolumeFade = new BindableDouble(); private void updateActiveState(bool isActive) { if (isActive) - { - this.TransformBindableTo(inactiveVolumeFade, 1, 500, Easing.OutQuint) - .Finally(_ => Audio.RemoveAdjustment(AdjustableProperty.Volume, inactiveVolumeFade)); //wait for the transition to finish to remove the inactive audio adjustment - } + this.TransformBindableTo(inactiveVolumeFade, 1, 400, Easing.OutQuint); else - { - Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade); - this.TransformBindableTo(inactiveVolumeFade, userInactiveVolume.Value, 1500, Easing.OutSine); - } + this.TransformBindableTo(inactiveVolumeFade, LocalConfig.Get(OsuSetting.VolumeInactive), 4000, Easing.OutQuint); } #endregion diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index e984fb8574..0994d1f7d3 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mods @@ -14,6 +15,6 @@ namespace osu.Game.Rulesets.Mods public override IconUsage Icon => OsuIcon.ModPerfect; public override string Description => "SS or quit."; - protected override bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Accuracy.Value != 1; + protected override bool FailCondition(ScoreProcessor scoreProcessor, JudgementResult result) => scoreProcessor.Accuracy.Value != 1; } } diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 809661db8e..e332abd914 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; @@ -27,6 +28,6 @@ namespace osu.Game.Rulesets.Mods public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; - protected virtual bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Combo.Value == 0; + protected virtual bool FailCondition(ScoreProcessor scoreProcessor, JudgementResult result) => scoreProcessor.Combo.Value == 0 && result.Judgement.AffectsCombo; } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ce94ca9c7d..47ce28db4c 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Scoring /// /// Additional conditions on top of that cause a failing state. /// - public event Func FailConditions; + public event Func FailConditions; /// /// The current total score. @@ -151,12 +151,12 @@ namespace osu.Game.Rulesets.Scoring /// This can only ever notify subscribers once. /// /// - protected void UpdateFailed() + protected void UpdateFailed(JudgementResult result) { if (HasFailed) return; - if (!DefaultFailCondition && FailConditions?.Invoke(this) != true) + if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true) return; if (Failed?.Invoke() != false) @@ -287,7 +287,7 @@ namespace osu.Game.Rulesets.Scoring ApplyResult(result); updateScore(); - UpdateFailed(); + UpdateFailed(result); NotifyNewJudgement(result); }