// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using System; using System.Collections.Generic; using osu.Game.Configuration; using System.Linq; namespace osu.Game.Rulesets.Mods { public abstract class ModDifficultyAdjust : Mod, IApplicableToDifficulty { public override string Name => @"Difficulty Adjust"; public override string Description => @"Override a beatmap's difficulty settings."; public override string Acronym => "DA"; public override ModType Type => ModType.Conversion; public override IconUsage? Icon => FontAwesome.Solid.Hammer; public override double ScoreMultiplier => 1.0; public override bool RequiresConfiguration => true; public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModHardRock) }; protected const int FIRST_SETTING_ORDER = 1; protected const int LAST_SETTING_ORDER = 2; [SettingSource("HP Drain", "Override a beatmap's set HP.", FIRST_SETTING_ORDER)] public BindableNumber DrainRate { get; } = new BindableFloat { Precision = 0.1f, MinValue = 1, MaxValue = 10, Default = 5, Value = 5, }; [SettingSource("Accuracy", "Override a beatmap's set OD.", LAST_SETTING_ORDER)] public BindableNumber OverallDifficulty { get; } = new BindableFloat { Precision = 0.1f, MinValue = 1, MaxValue = 10, Default = 5, Value = 5, }; public override string SettingDescription { get { string drainRate = DrainRate.IsDefault ? string.Empty : $"HP {DrainRate.Value:0.#}"; string overallDifficulty = OverallDifficulty.IsDefault ? string.Empty : $"OD {OverallDifficulty.Value:0.#}"; return string.Join(", ", new[] { drainRate, overallDifficulty }.Where(s => !string.IsNullOrEmpty(s))); } } private BeatmapDifficulty difficulty; public void ReadFromDifficulty(BeatmapDifficulty difficulty) { if (this.difficulty == null || this.difficulty.ID != difficulty.ID) { TransferSettings(difficulty); this.difficulty = difficulty; } } public void ApplyToDifficulty(BeatmapDifficulty difficulty) => ApplySettings(difficulty); /// /// Transfer initial settings from the beatmap to settings. /// /// The beatmap's initial values. protected virtual void TransferSettings(BeatmapDifficulty difficulty) { TransferSetting(DrainRate, difficulty.DrainRate); TransferSetting(OverallDifficulty, difficulty.OverallDifficulty); } private readonly Dictionary userChangedSettings = new Dictionary(); /// /// Transfer a setting from to a configuration bindable. /// Only performs the transfer if the user is not currently overriding. /// protected void TransferSetting(BindableNumber bindable, T beatmapDefault) where T : struct, IComparable, IConvertible, IEquatable { bindable.UnbindEvents(); userChangedSettings.TryAdd(bindable, false); bindable.Default = beatmapDefault; // users generally choose a difficulty setting and want it to stick across multiple beatmap changes. // we only want to value transfer if the user hasn't changed the value previously. if (!userChangedSettings[bindable]) bindable.Value = beatmapDefault; bindable.ValueChanged += _ => userChangedSettings[bindable] = !bindable.IsDefault; } /// /// Apply all custom settings to the provided beatmap. /// /// The beatmap to have settings applied. protected virtual void ApplySettings(BeatmapDifficulty difficulty) { difficulty.DrainRate = DrainRate.Value; difficulty.OverallDifficulty = OverallDifficulty.Value; } } }