mirror of
https://github.com/ppy/osu.git
synced 2026-05-24 02:09:54 +08:00
Disallow adjusting scroll speed during gameplay
Matches stable. Addresses https://github.com/ppy/osu/discussions/32670.
This commit is contained in:
@@ -60,8 +60,9 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
private readonly BindableDouble configScrollSpeed = new BindableDouble();
|
||||
private readonly Bindable<ManiaMobileLayout> mobileLayout = new Bindable<ManiaMobileLayout>();
|
||||
|
||||
public double TargetTimeRange { get; protected set; }
|
||||
|
||||
private double currentTimeRange;
|
||||
protected double TargetTimeRange;
|
||||
|
||||
// Stores the current speed adjustment active in gameplay.
|
||||
private readonly Track speedAdjustmentTrack = new TrackVirtual(0);
|
||||
@@ -109,7 +110,13 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
configDirection.BindValueChanged(direction => Direction.Value = (ScrollingDirection)direction.NewValue, true);
|
||||
|
||||
Config.BindWith(ManiaRulesetSetting.ScrollSpeed, configScrollSpeed);
|
||||
configScrollSpeed.BindValueChanged(speed => TargetTimeRange = ComputeScrollTime(speed.NewValue));
|
||||
configScrollSpeed.BindValueChanged(speed =>
|
||||
{
|
||||
if (!AllowScrollSpeedAdjustment)
|
||||
return;
|
||||
|
||||
TargetTimeRange = ComputeScrollTime(speed.NewValue);
|
||||
});
|
||||
|
||||
TimeRange.Value = TargetTimeRange = currentTimeRange = ComputeScrollTime(configScrollSpeed.Value);
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ using osu.Game.Overlays.BeatmapListing;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Overlays.Toolbar;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Mania.Configuration;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Scoring;
|
||||
@@ -394,6 +398,60 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestScrollSpeedAdjustDuringGameplay()
|
||||
{
|
||||
Player player = null;
|
||||
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadOszIntoOsu(Game).WaitSafely());
|
||||
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
AddStep("switch to mania ruleset", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.LControl);
|
||||
InputManager.Key(Key.Number4);
|
||||
InputManager.ReleaseKey(Key.LControl);
|
||||
});
|
||||
|
||||
AddStep("set mods", () => Game.SelectedMods.Value = new Mod[] { new OsuModNoFail() });
|
||||
AddStep("press enter", () => InputManager.Key(Key.Enter));
|
||||
|
||||
AddUntilStep("wait for player", () =>
|
||||
{
|
||||
DismissAnyNotifications();
|
||||
player = Game.ScreenStack.CurrentScreen as Player;
|
||||
return player?.IsLoaded == true;
|
||||
});
|
||||
|
||||
AddUntilStep("wait for track playing", () => Game.Beatmap.Value.Track.IsRunning);
|
||||
checkScrollSpeed(8, 8);
|
||||
|
||||
AddStep("adjust scroll speed via keyboard", () => InputManager.Key(Key.F4));
|
||||
checkScrollSpeed(9, 9);
|
||||
|
||||
AddStep("seek beyond 10 seconds", () => player.ChildrenOfType<GameplayClockContainer>().First().Seek(10500));
|
||||
AddUntilStep("wait for seek", () => player.ChildrenOfType<GameplayClockContainer>().First().CurrentTime, () => Is.GreaterThan(10600));
|
||||
AddStep("attempt adjust offset via keyboard", () => InputManager.Key(Key.F4));
|
||||
checkScrollSpeed(9, 9);
|
||||
|
||||
AddStep("attempt adjust offset via config change", () => getConfigManager().SetValue(ManiaRulesetSetting.ScrollSpeed, 10.0));
|
||||
checkScrollSpeed(10, 9);
|
||||
|
||||
void checkScrollSpeed(double configValue, double gameplayValue)
|
||||
{
|
||||
AddUntilStep($"config value is {configValue}", () => getConfigManager().Get<double>(ManiaRulesetSetting.ScrollSpeed), () => Is.EqualTo(configValue));
|
||||
AddUntilStep($"gameplay value is {gameplayValue}", () => this.ChildrenOfType<DrawableManiaRuleset>().Single().TargetTimeRange,
|
||||
() => Is.EqualTo(DrawableManiaRuleset.ComputeScrollTime(gameplayValue)));
|
||||
}
|
||||
|
||||
ManiaRulesetConfigManager getConfigManager() => ((ManiaRulesetConfigManager)Game.Dependencies.Get<IRulesetConfigCache>().GetConfigFor(new ManiaRuleset())!);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOffsetAdjustDuringGameplay()
|
||||
{
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -21,6 +19,7 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Timing;
|
||||
using osu.Game.Rulesets.UI.Scrolling.Algorithms;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Rulesets.UI.Scrolling
|
||||
{
|
||||
@@ -69,6 +68,12 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
/// </summary>
|
||||
protected virtual bool UserScrollSpeedAdjustment => true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether at the current point in time, whether scroll speed adjustments should be applied to gameplay.
|
||||
/// This can potentially become false at some point during gameplay for game balance reasons.
|
||||
/// </summary>
|
||||
protected bool AllowScrollSpeedAdjustment => UserScrollSpeedAdjustment && player?.AllowCriticalSettingsAdjustment != false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether <see cref="TimingControlPoint"/> beat lengths should scale relative to the most common beat length in the <see cref="Beatmap"/>.
|
||||
/// </summary>
|
||||
@@ -84,7 +89,10 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
[Cached(Type = typeof(IScrollingInfo))]
|
||||
private readonly LocalScrollingInfo scrollingInfo;
|
||||
|
||||
protected DrawableScrollingRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
||||
[Resolved]
|
||||
private Player? player { get; set; }
|
||||
|
||||
protected DrawableScrollingRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod>? mods = null)
|
||||
: base(ruleset, beatmap, mods)
|
||||
{
|
||||
scrollingInfo = new LocalScrollingInfo();
|
||||
@@ -195,28 +203,30 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
/// Adjusts the scroll speed of <see cref="HitObject"/>s.
|
||||
/// </summary>
|
||||
/// <param name="amount">The amount to adjust by. Greater than 0 if the scroll speed should be increased, less than 0 if it should be decreased.</param>
|
||||
protected virtual void AdjustScrollSpeed(int amount) => this.TransformBindableTo(TimeRange, TimeRange.Value - amount * time_span_step, 200, Easing.OutQuint);
|
||||
protected virtual void AdjustScrollSpeed(int amount)
|
||||
{
|
||||
this.TransformBindableTo(TimeRange, TimeRange.Value - amount * time_span_step, 200, Easing.OutQuint);
|
||||
}
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||
{
|
||||
if (!UserScrollSpeedAdjustment)
|
||||
return false;
|
||||
|
||||
switch (e.Action)
|
||||
{
|
||||
case GlobalAction.IncreaseScrollSpeed:
|
||||
AdjustScrollSpeed(1);
|
||||
if (AllowScrollSpeedAdjustment)
|
||||
AdjustScrollSpeed(1);
|
||||
return true;
|
||||
|
||||
case GlobalAction.DecreaseScrollSpeed:
|
||||
AdjustScrollSpeed(-1);
|
||||
if (AllowScrollSpeedAdjustment)
|
||||
AdjustScrollSpeed(-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private ScheduledDelegate scheduledScrollSpeedAdjustment;
|
||||
private ScheduledDelegate? scheduledScrollSpeedAdjustment;
|
||||
|
||||
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
||||
{
|
||||
|
||||
@@ -112,6 +112,12 @@ namespace osu.Game.Screens.Play
|
||||
/// </summary>
|
||||
public IBindable<bool> ShowingOverlayComponents = new Bindable<bool>();
|
||||
|
||||
/// <summary>
|
||||
/// A flag which can be checked to decide whether we are in a state where settings that affect
|
||||
/// game balance should be allowed to be applied at the current point in time.
|
||||
/// </summary>
|
||||
public virtual bool AllowCriticalSettingsAdjustment { get; } = true;
|
||||
|
||||
// Should match PlayerLoader for consistency. Cached here for the rare case we push a Player
|
||||
// without the loading screen (one such usage is the skin editor's scene library).
|
||||
[Cached]
|
||||
|
||||
@@ -60,9 +60,6 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
||||
[Resolved]
|
||||
private Player? player { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IGameplayClock? gameplayClock { get; set; }
|
||||
|
||||
private double lastPlayMedian;
|
||||
private double lastPlayBeatmapOffset;
|
||||
private HitEventTimingDistributionGraph? lastPlayGraph;
|
||||
@@ -287,27 +284,7 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
||||
Current.Disabled = !allow;
|
||||
}
|
||||
|
||||
private bool allowOffsetAdjust
|
||||
{
|
||||
get
|
||||
{
|
||||
// General limitations to ensure players don't do anything too weird.
|
||||
// These match stable for now.
|
||||
if (player is SubmittingPlayer)
|
||||
{
|
||||
Debug.Assert(gameplayClock != null);
|
||||
|
||||
// TODO: the blocking conditions should probably display a message.
|
||||
if (!player.IsBreakTime.Value && gameplayClock.CurrentTime - gameplayClock.GameplayStartTime > 10000)
|
||||
return false;
|
||||
|
||||
if (gameplayClock.IsPaused.Value)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
private bool allowOffsetAdjust => player?.AllowCriticalSettingsAdjustment != false;
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||
{
|
||||
|
||||
@@ -186,6 +186,24 @@ namespace osu.Game.Screens.Play
|
||||
/// <returns>Whether gameplay should be immediately exited as a result. Returning false allows the gameplay session to continue. Defaults to true.</returns>
|
||||
protected virtual bool ShouldExitOnTokenRetrievalFailure(Exception exception) => true;
|
||||
|
||||
public override bool AllowCriticalSettingsAdjustment
|
||||
{
|
||||
get
|
||||
{
|
||||
// General limitations to ensure players don't do anything too weird.
|
||||
// These match stable for now.
|
||||
|
||||
// TODO: the blocking conditions should probably display a message.
|
||||
if (!IsBreakTime.Value && GameplayClockContainer.CurrentTime - GameplayClockContainer.GameplayStartTime > 10000)
|
||||
return false;
|
||||
|
||||
if (GameplayClockContainer.IsPaused.Value)
|
||||
return false;
|
||||
|
||||
return base.AllowCriticalSettingsAdjustment;
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task PrepareScoreForResultsAsync(Score score)
|
||||
{
|
||||
await base.PrepareScoreForResultsAsync(score).ConfigureAwait(false);
|
||||
|
||||
Reference in New Issue
Block a user