1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-28 07:23:14 +08:00

Add mod "Random" for ruleset "osu!"

This commit is contained in:
Pasi4K5 2021-04-25 00:39:36 +02:00
parent a2215d8078
commit 961bd1177c
3 changed files with 125 additions and 0 deletions

View File

@ -0,0 +1,77 @@
// 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.Linq;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.UI;
using osuTK;
namespace osu.Game.Rulesets.Osu.Mods
{
public class OsuModRandom : ModRandomOsu
{
protected override void RandomiseHitObjectPositions(IBeatmap beatmap)
{
var rng = new Random();
foreach (var hitObject in beatmap.HitObjects)
{
if (RandomiseCirclePositions.Value && hitObject is HitCircle circle)
{
circle.Position = new Vector2(
(float)rng.NextDouble() * OsuPlayfield.BASE_SIZE.X,
(float)rng.NextDouble() * OsuPlayfield.BASE_SIZE.Y
);
}
else if (RandomiseSpinnerPositions.Value && hitObject is Spinner spinner)
{
spinner.Position = new Vector2(
(float)rng.NextDouble() * OsuPlayfield.BASE_SIZE.X,
(float)rng.NextDouble() * OsuPlayfield.BASE_SIZE.Y
);
}
else if (RandomiseSliderPositions.Value && hitObject is Slider slider)
{
// Min. distances from the slider's position to the border to prevent the slider from being partially out of the screen
float minLeft = 0, minRight = 0, minTop = 0, minBottom = 0;
var controlPointPositions = (from position
in slider.Path.ControlPoints
select position.Position.Value).ToList();
controlPointPositions.Add(slider.EndPosition);
controlPointPositions.RemoveAt(controlPointPositions.Count - 1);
foreach (var position in controlPointPositions)
{
if (position.X > minRight)
{
minRight = position.X;
}
else if (-position.X > minLeft)
{
minLeft = -position.X;
}
if (position.Y > minBottom)
{
minBottom = position.Y;
}
else if (-position.Y > minTop)
{
minTop = -position.Y;
}
}
slider.Position = new Vector2(
(float)rng.NextDouble() * (OsuPlayfield.BASE_SIZE.X - minLeft - minRight) + minLeft,
(float)rng.NextDouble() * (OsuPlayfield.BASE_SIZE.Y - minTop - minBottom) + minTop
);
}
}
}
}
}

View File

@ -186,6 +186,7 @@ namespace osu.Game.Rulesets.Osu
new MultiMod(new ModWindUp(), new ModWindDown()),
new OsuModTraceable(),
new OsuModBarrelRoll(),
new OsuModRandom(),
};
case ModType.System:

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 osu.Framework.Bindables;
using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Graphics;
namespace osu.Game.Rulesets.Mods
{
public abstract class ModRandomOsu : Mod, IApplicableToBeatmap
{
public override string Name => "Random";
public override string Acronym => "RD";
public override IconUsage? Icon => OsuIcon.Dice;
public override ModType Type => ModType.Fun;
public override string Description => "Hit objects appear at random positions";
public override double ScoreMultiplier => 1;
public override bool Ranked => false;
[SettingSource("Randomise circle positions", "Hit circles appear at random positions")]
public Bindable<bool> RandomiseCirclePositions { get; } = new BindableBool
{
Default = true,
Value = true,
};
[SettingSource("Randomise slider positions", "Sliders appear at random positions")]
public Bindable<bool> RandomiseSliderPositions { get; } = new BindableBool
{
Default = true,
Value = true,
};
[SettingSource("Randomise spinner positions", "Spinners appear at random positions")]
public Bindable<bool> RandomiseSpinnerPositions { get; } = new BindableBool
{
Default = true,
Value = true,
};
public void ApplyToBeatmap(IBeatmap beatmap) => RandomiseHitObjectPositions(beatmap);
protected abstract void RandomiseHitObjectPositions(IBeatmap beatmap);
}
}