3 Commits

29 changed files with 140 additions and 51 deletions

View File

@@ -1,12 +1,6 @@
blank_issues_enabled: false
blank_issues_enabled: true
contact_links:
- name: Help
url: https://github.com/ppy/osu/discussions/categories/q-a
about: osu! not working or performing as you'd expect? Not sure it's a bug? Check the Q&A section!
- name: Suggestions or feature request
url: https://github.com/ppy/osu/discussions/categories/ideas
about: Got something you think should change or be added? Search for or start a new discussion!
- name: osu!stable issues
url: https://github.com/ppy/osu-stable-issues
about: For osu!(stable) - ie. the current "live" game version, check out the dedicated repository. Note that this is for serious bug reports only, not tech support.
url: https://t.me/jvnkosu_chat
about: Your jvnkosu! is not working right? Please contact us using our Telegram chat

View File

@@ -208,9 +208,10 @@ namespace osu.Desktop
[SupportedOSPlatform("windows")]
private static void configureWindows(VelopackApp app)
{
app.OnFirstRun(_ => WindowsAssociationManager.InstallAssociations());
app.OnAfterUpdateFastCallback(_ => WindowsAssociationManager.UpdateAssociations());
app.OnBeforeUninstallFastCallback(_ => WindowsAssociationManager.UninstallAssociations());
// we do not want associations here, as that breaks official lazer's associations
// app.OnFirstRun(_ => WindowsAssociationManager.InstallAssociations());
// app.OnAfterUpdateFastCallback(_ => WindowsAssociationManager.UpdateAssociations());
// app.OnBeforeUninstallFastCallback(_ => WindowsAssociationManager.UninstallAssociations());
}
}
}

View File

@@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Mods
typeof(ManiaModFadeIn)
}).ToArray();
public override bool Ranked => false;
public override bool Ranked => true;
public override bool ValidForFreestyleAsRequiredMod => false;

View File

@@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModHardRock : ModHardRock, IApplicableToHitObject
{
public override double ScoreMultiplier => 1;
public override bool Ranked => false;
public override bool Ranked => true;
public const double HIT_WINDOW_DIFFICULTY_MULTIPLIER = 1.4;

View File

@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModMirror : ModMirror, IApplicableToBeatmap
{
public override LocalisableString Description => "Notes are flipped horizontally.";
public override bool Ranked => UsesDefaultConfiguration;
public override bool Ranked => true;
public void ApplyToBeatmap(IBeatmap beatmap)
{

View File

@@ -0,0 +1,16 @@
// 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.
using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Game.Configuration;
using osu.Game.Overlays.Settings;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Osu.Mods
{
public class OsuModRateAdjustConcrete : ModRateAdjustConcrete
{
}
}

View File

@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public override LocalisableString Description => @"Spinners will be automatically completed.";
public override double ScoreMultiplier => 0.9;
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot), typeof(OsuModTargetPractice) };
public override bool Ranked => UsesDefaultConfiguration;
public override bool Ranked => true;
public void ApplyToDrawableHitObject(DrawableHitObject hitObject)
{

View File

@@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModTouchDevice : ModTouchDevice
{
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot), typeof(OsuModBloom) }).ToArray();
public override bool Ranked => UsesDefaultConfiguration;
public override bool Ranked => true;
}
}

View File

@@ -230,6 +230,12 @@ namespace osu.Game.Rulesets.Osu
new ModScoreV2(),
};
case ModType.Special:
return new Mod[]
{
new OsuModRateAdjustConcrete(),
};
default:
return Array.Empty<Mod>();
}

View File

@@ -183,6 +183,9 @@ namespace osu.Game.Graphics
case ModType.System:
return Yellow;
case ModType.Special:
return Orange2;
default:
throw new ArgumentOutOfRangeException(nameof(modType), modType, "Unknown mod type");
}

View File

@@ -329,6 +329,7 @@ namespace osu.Game.Overlays.Mods
yield return createModColumnContent(ModType.Automation);
yield return createModColumnContent(ModType.Conversion);
yield return createModColumnContent(ModType.Fun);
yield return createModColumnContent(ModType.Special);
}
private ColumnDimContainer createModColumnContent(ModType modType)

View File

@@ -0,0 +1,22 @@
// 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.
namespace osu.Game.Rulesets.Mods
{
/// <summary>
/// Represents a mod which can override a fail and quit the game instead.
/// </summary>
public interface IApplicableFailExit : IApplicableMod
{
/// <summary>
/// Whether we should allow failing at the current point in time.
/// </summary>
/// <returns>Whether the fail should be allowed to proceed. Return false to block.</returns>
bool PerformFail();
/// <summary>
/// Whether we want to exit the game on fail. Only used if <see cref="PerformFail"/> returns true.
/// </summary>
bool ExitOnFail { get; }
}
}

View File

@@ -1,19 +0,0 @@
// 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.
using osu.Game;
namespace osu.Game.Rulesets.Mods
{
/// <summary>
/// An interface for mods that apply changes to the <see cref="OsuGameBase"/>.
/// This is really stupid and f%%king dangerous, possibly disasterous even.
/// </summary>
public interface IApplicableToOsuGameBase : IApplicableMod
{
/// <summary>
/// Provide a <see cref="OsuGameBase"/>. Called once on initialisation of a play instance.
/// </summary>
void ApplyToOsuGameBase(OsuGameBase game);
}
}

View File

@@ -127,7 +127,9 @@ namespace osu.Game.Rulesets.Mods
/// The settings are returned in ascending key order as per <see cref="SettingsMap"/>.
/// The ordering is intentionally enforced manually, as ordering of <see cref="Dictionary{TKey,TValue}.Values"/> is unspecified.
/// </remarks>
internal IEnumerable<IBindable> SettingsBindables => SettingsMap.OrderBy(pair => pair.Key).Select(pair => pair.Value);
internal IEnumerable<IBindable> SettingsBindables => SettingsMap.OrderBy(pair => pair.Key)
.Select(pair => pair.Value)
.Where(x => !x.GetType().GetCustomAttributes(typeof(JsonIgnoreAttribute)).Any());
/// <summary>
/// Provides mapping of names to <see cref="IBindable"/>s of all settings within this mod.

View File

@@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mods
/// - Hit windows differ (https://github.com/ppy/osu/issues/11311).
/// - Sliders always gives combo for slider end, even on miss (https://github.com/ppy/osu/issues/11769).
/// </summary>
public sealed override bool Ranked => false;
public sealed override bool Ranked => true;
public sealed override bool ValidForFreestyleAsRequiredMod => false;
}

View File

@@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mods
public override IconUsage? Icon => OsuIcon.ModDaycore;
public override ModType Type => ModType.DifficultyReduction;
public override LocalisableString Description => "Whoaaaaa...";
public override bool Ranked => UsesDefaultConfiguration;
public override bool Ranked => true;
[SettingSource("Speed decrease", "The actual decrease to apply", SettingControlType = typeof(MultiplierSettingsSlider))]
public override BindableNumber<double> SpeedChange { get; } = new BindableDouble(0.75)

View File

@@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mods
public override IconUsage? Icon => OsuIcon.ModDoubleTime;
public override ModType Type => ModType.DifficultyIncrease;
public override LocalisableString Description => "Zoooooooooom...";
public override bool Ranked => SpeedChange.IsDefault;
public override bool Ranked => true;
[SettingSource("Speed increase", "The actual increase to apply", SettingControlType = typeof(MultiplierSettingsSlider))]
public override BindableNumber<double> SpeedChange { get; } = new BindableDouble(1.5)

View File

@@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mods
public override ModType Type => ModType.DifficultyReduction;
public override double ScoreMultiplier => 0.5;
public override Type[] IncompatibleMods => new[] { typeof(ModHardRock), typeof(ModDifficultyAdjust) };
public override bool Ranked => UsesDefaultConfiguration;
public override bool Ranked => true;
public override bool ValidForFreestyleAsRequiredMod => true;
protected const float ADJUST_RATIO = 0.5f;

View File

@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using Newtonsoft.Json;
using osu.Framework.Bindables;
using osu.Game.Configuration;
using osu.Game.Rulesets.Judgements;
@@ -9,17 +10,23 @@ using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mods
{
public abstract class ModFailCondition : Mod, IApplicableToHealthProcessor, IApplicableFailOverride
public abstract class ModFailCondition : Mod, IApplicableToHealthProcessor, IApplicableFailOverride, IApplicableFailExit
{
public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModCinema) };
[SettingSource("Restart on fail", "Automatically restarts when failed.")]
public BindableBool Restart { get; } = new BindableBool();
[SettingSource("Exit game on fail", "Automatically exits the game when failed."), JsonIgnore]
public BindableBool Exit { get; } = new BindableBool();
public virtual bool PerformFail() => true;
public virtual bool RestartOnFail => Restart.Value;
[JsonIgnore]
public virtual bool ExitOnFail => Exit.Value;
private Action? triggerFailureDelegate;
public void ApplyToHealthProcessor(HealthProcessor healthProcessor)
@@ -39,7 +46,7 @@ namespace osu.Game.Rulesets.Mods
/// </summary>
/// <param name="healthProcessor">The loaded <see cref="HealthProcessor"/>.</param>
/// <param name="result">The latest <see cref="JudgementResult"/>.</param>
/// <returns>Whether the fail condition has been met.</returns>
/// <returns>Whether the fail condition has been met.</returns>z
/// <remarks>
/// This method should only be used to trigger failures based on <paramref name="result"/>.
/// Using outside values to evaluate failure may introduce event ordering discrepancies, use

View File

@@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Mods
public override IconUsage? Icon => OsuIcon.ModFlashlight;
public override ModType Type => ModType.DifficultyIncrease;
public override LocalisableString Description => "Restricted view area.";
public override bool Ranked => UsesDefaultConfiguration;
public override bool Ranked => true;
[SettingSource("Flashlight size", "Multiplier applied to the default flashlight size.")]
public abstract BindableFloat SizeMultiplier { get; }

View File

@@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mods
public override IconUsage? Icon => OsuIcon.ModHalfTime;
public override ModType Type => ModType.DifficultyReduction;
public override LocalisableString Description => "Less zoom...";
public override bool Ranked => SpeedChange.IsDefault;
public override bool Ranked => true;
[SettingSource("Speed decrease", "The actual decrease to apply", SettingControlType = typeof(MultiplierSettingsSlider))]
public override BindableNumber<double> SpeedChange { get; } = new BindableDouble(0.75)

View File

@@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mods
public override ModType Type => ModType.DifficultyIncrease;
public override LocalisableString Description => "Everything just got a bit harder...";
public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModDifficultyAdjust) };
public override bool Ranked => UsesDefaultConfiguration;
public override bool Ranked => true;
public override bool ValidForFreestyleAsRequiredMod => true;
protected const float ADJUST_RATIO = 1.4f;

View File

@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mods
public override string Acronym => "HD";
public override IconUsage? Icon => OsuIcon.ModHidden;
public override ModType Type => ModType.DifficultyIncrease;
public override bool Ranked => UsesDefaultConfiguration;
public override bool Ranked => true;
public virtual void ApplyToScoreProcessor(ScoreProcessor scoreProcessor)
{

View File

@@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Mods
public override IconUsage? Icon => OsuIcon.ModNightcore;
public override ModType Type => ModType.DifficultyIncrease;
public override LocalisableString Description => "Uguuuuuuuu...";
public override bool Ranked => UsesDefaultConfiguration;
public override bool Ranked => true;
[SettingSource("Speed increase", "The actual increase to apply", SettingControlType = typeof(MultiplierSettingsSlider))]
public override BindableNumber<double> SpeedChange { get; } = new BindableDouble(1.5)

View File

@@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mods
public override LocalisableString Description => "You can't fail, no matter what.";
public override double ScoreMultiplier => 0.5;
public override Type[] IncompatibleMods => new[] { typeof(ModFailCondition), typeof(ModCinema) };
public override bool Ranked => UsesDefaultConfiguration;
public override bool Ranked => true;
public override bool ValidForFreestyleAsRequiredMod => true;
private readonly Bindable<bool> showHealthBar = new Bindable<bool>();

View File

@@ -0,0 +1,47 @@
// 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.
using System;
using System.Collections.Generic;
using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.Localisation;
using osu.Game.Configuration;
using osu.Game.Overlays.Settings;
namespace osu.Game.Rulesets.Mods
{
public abstract class ModRateAdjustConcrete : ModRateAdjust
{
public override string Name => "Rate Adjust";
public override LocalisableString Description => "[DEBUG BUILDS ONLY] Set any speed";
public override string Acronym => "_R";
private readonly RateAdjustModHelper rateAdjustHelper;
[SettingSource("Speed decrease", "The actual decrease to apply", SettingControlType = typeof(MultiplierSettingsSlider))]
public override BindableNumber<double> SpeedChange { get; } = new BindableDouble(0.75)
{
MinValue = 0.1, // BASS breaks at lower rates
MaxValue = 10,
Precision = 0.01
};
[SettingSource("Adjust pitch", "Should pitch be adjusted with speed")]
public virtual BindableBool AdjustPitch { get; } = new BindableBool();
protected ModRateAdjustConcrete()
{
rateAdjustHelper = new RateAdjustModHelper(SpeedChange);
rateAdjustHelper.HandleAudioAdjustments(AdjustPitch);
}
public override double ScoreMultiplier => 1.0;
public override void ApplyToTrack(IAdjustableAudioComponent track)
{
rateAdjustHelper.ApplyToTrack(track);
}
public override bool Ranked => false;
public override ModType Type => ModType.Special;
}
}

View File

@@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Mods
Conversion,
Automation,
Fun,
System
System,
Special
}
}

View File

@@ -411,7 +411,7 @@ namespace osu.Game.Screens.Menu
// if the dialog has already displayed and been accepted by the user, we are good.
&& !exitConfirmedViaDialog
// Only require confirmation if there is either an ongoing operation or the user exited via a non-hold escape press.
&& (notifications.HasOngoingOperations || !exitConfirmedViaHoldOrClick);
&& (notifications.HasOngoingOperations /* || !exitConfirmedViaHoldOrClick */);
if (requiresConfirmation)
{

View File

@@ -983,6 +983,14 @@ namespace osu.Game.Screens.Play
if (PauseOverlay.State.Value == Visibility.Visible)
PauseOverlay.Hide();
bool exitOnFail = GameplayState.Mods.OfType<IApplicableFailExit>().Any(m => m.ExitOnFail);
if (exitOnFail)
{
// game.AttemptExit();
game.Exit();
}
bool restartOnFail = GameplayState.Mods.OfType<IApplicableFailOverride>().Any(m => m.RestartOnFail);
if (!restartOnFail)
failAnimationContainer.Start();