1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 15:27:24 +08:00

Add "Whiplash" mod for osu! ruleset

This commit is contained in:
Pants 2024-02-22 18:34:09 -05:00
parent ef413c08f1
commit bd2d6f3c71
2 changed files with 95 additions and 1 deletions

View File

@ -0,0 +1,93 @@
// 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 osu.Framework.Bindables;
using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Mods
{
public class OsuModWhiplash : Mod, IApplicableToHitObject, IApplicableToBeatmapProcessor
{
public override string Name => "Whiplash";
public override string Acronym => "WL";
public override LocalisableString Description => "Am I rushing.. or am I dragging?";
public override ModType Type => ModType.Conversion;
private IBeatmap? currentBeatmap { get; set; }
[SettingSource("Target BPM", "Target BPM to center the changes around.")]
public Bindable<TargetBPMStyle> TargetBPM { get; } = new Bindable<TargetBPMStyle>(TargetBPMStyle.MaxBPM);
public override double ScoreMultiplier => TargetBPM.Value == TargetBPMStyle.MaxBPM ? 1.0 : 0.75;
public void ApplyToHitObject(HitObject hitObject)
{
if (currentBeatmap == null || hitObject is not OsuHitObject hitCircle)
return;
double currentBpm = currentBeatmap.ControlPointInfo.TimingPointAt(hitCircle.StartTime).BPM;
if (currentBpm < 1)
{
updateTimePreempty(hitCircle, hitCircle.StartTime);
return;
}
double scaleBpm = getBaseBPM(currentBeatmap);
double preempt = hitCircle.TimePreempt;
double newTimePreempt = (scaleBpm / Math.Max(currentBpm, 1)) * preempt;
//don't allow AR to go over 11
updateTimePreempty(hitCircle, Math.Max(newTimePreempt, 300));
}
private void updateTimePreempty(OsuHitObject hitCircle, double value)
{
hitCircle.TimePreempt = value;
if (hitCircle is Slider slider)
{
slider.HeadCircle.TimePreempt = value;
}
}
private double getBaseBPM(IBeatmap beatmap)
{
switch (TargetBPM.Value)
{
case TargetBPMStyle.MainBPM:
return beatmap.BeatmapInfo.BPM;
case TargetBPMStyle.MaxBPM:
return beatmap.ControlPointInfo.BPMMaximum;
case TargetBPMStyle.MinBPM:
return beatmap.ControlPointInfo.BPMMinimum;
default:
throw new ArgumentOutOfRangeException(nameof(TargetBPM), TargetBPM, @"Unsupported BPM scale");
}
}
public void ApplyToBeatmapProcessor(IBeatmapProcessor beatmapProcessor)
{
if (currentBeatmap != beatmapProcessor.Beatmap)
{
currentBeatmap = beatmapProcessor.Beatmap;
}
}
public enum TargetBPMStyle
{
MainBPM,
MinBPM,
MaxBPM,
}
}
}

View File

@ -183,7 +183,8 @@ namespace osu.Game.Rulesets.Osu
new OsuModClassic(),
new OsuModRandom(),
new OsuModMirror(),
new MultiMod(new OsuModAlternate(), new OsuModSingleTap())
new MultiMod(new OsuModAlternate(), new OsuModSingleTap()),
new OsuModWhiplash()
};
case ModType.Automation: