mirror of
https://github.com/ppy/osu.git
synced 2024-11-06 09:07:25 +08:00
Add generator to generate patterns from HitObjects.
This commit is contained in:
parent
7b05930fc2
commit
6ab7a91415
@ -11,11 +11,19 @@ using osu.Game.Rulesets.Objects.Types;
|
|||||||
using osu.Game.Rulesets.Mania.Beatmaps.Patterns;
|
using osu.Game.Rulesets.Mania.Beatmaps.Patterns;
|
||||||
using osu.Game.Rulesets.Mania.MathUtils;
|
using osu.Game.Rulesets.Mania.MathUtils;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Beatmaps.Timing;
|
||||||
|
using osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Beatmaps
|
namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||||
{
|
{
|
||||||
public class ManiaBeatmapConverter : BeatmapConverter<ManiaHitObject>
|
public class ManiaBeatmapConverter : BeatmapConverter<ManiaHitObject>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum number of previous notes to consider for density calculation.
|
||||||
|
/// </summary>
|
||||||
|
private const int max_notes_for_density = 7;
|
||||||
|
|
||||||
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) };
|
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) };
|
||||||
|
|
||||||
private Pattern lastPattern = new Pattern();
|
private Pattern lastPattern = new Pattern();
|
||||||
@ -55,6 +63,26 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
yield return obj;
|
yield return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<double> prevNoteTimes = new List<double>(max_notes_for_density);
|
||||||
|
private double density = int.MaxValue;
|
||||||
|
private void computeDensity(double newNoteTime)
|
||||||
|
{
|
||||||
|
if (prevNoteTimes.Count == max_notes_for_density)
|
||||||
|
prevNoteTimes.RemoveAt(0);
|
||||||
|
prevNoteTimes.Add(newNoteTime);
|
||||||
|
|
||||||
|
density = (prevNoteTimes[prevNoteTimes.Count - 1] - prevNoteTimes[0]) / prevNoteTimes.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double lastTime;
|
||||||
|
private Vector2 lastPosition;
|
||||||
|
private PatternType lastStair;
|
||||||
|
private void recordNote(double time, Vector2 position)
|
||||||
|
{
|
||||||
|
lastTime = time;
|
||||||
|
lastPosition = position;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Method that generates hit objects for osu!mania specific beatmaps.
|
/// Method that generates hit objects for osu!mania specific beatmaps.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -83,7 +111,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
|
|
||||||
// Following lines currently commented out to appease resharper
|
// Following lines currently commented out to appease resharper
|
||||||
|
|
||||||
//Patterns.PatternGenerator conversion = null;
|
Patterns.PatternGenerator conversion = null;
|
||||||
|
|
||||||
if (distanceData != null)
|
if (distanceData != null)
|
||||||
{
|
{
|
||||||
@ -95,16 +123,24 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
}
|
}
|
||||||
else if (positionData != null)
|
else if (positionData != null)
|
||||||
{
|
{
|
||||||
// Circle
|
computeDensity(original.StartTime);
|
||||||
|
|
||||||
|
conversion = new HitObjectPatternGenerator(random, original, beatmap, lastPattern, lastTime, lastPosition, density, lastStair);
|
||||||
|
|
||||||
|
recordNote(original.StartTime, positionData.Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (conversion == null)
|
if (conversion == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
//Pattern newPattern = conversion.Generate();
|
Pattern newPattern = conversion.Generate();
|
||||||
//lastPattern = newPattern;
|
lastPattern = newPattern;
|
||||||
|
|
||||||
//return newPattern.HitObjects;
|
var stairPatternGenerator = conversion as HitObjectPatternGenerator;
|
||||||
|
if (stairPatternGenerator != null)
|
||||||
|
lastStair = stairPatternGenerator.StairType;
|
||||||
|
|
||||||
|
return newPattern.HitObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -0,0 +1,425 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.Timing;
|
||||||
|
using osu.Game.Rulesets.Mania.MathUtils;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||||
|
{
|
||||||
|
internal class HitObjectPatternGenerator : PatternGenerator
|
||||||
|
{
|
||||||
|
public PatternType StairType { get; private set; }
|
||||||
|
|
||||||
|
private readonly PatternType convertType;
|
||||||
|
|
||||||
|
public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair)
|
||||||
|
: base(random, hitObject, beatmap, previousPattern)
|
||||||
|
{
|
||||||
|
StairType = lastStair;
|
||||||
|
|
||||||
|
ControlPoint overridePoint;
|
||||||
|
ControlPoint controlPoint = beatmap.TimingInfo.TimingPointAt(hitObject.StartTime, out overridePoint);
|
||||||
|
|
||||||
|
var positionData = hitObject as IHasPosition;
|
||||||
|
|
||||||
|
float positionSeparation = ((positionData?.Position ?? Vector2.Zero) - previousPosition).Length;
|
||||||
|
double timeSeparation = hitObject.StartTime - previousTime;
|
||||||
|
|
||||||
|
double beatLength = controlPoint.BeatLength;
|
||||||
|
bool kiai = (overridePoint ?? controlPoint).KiaiMode;
|
||||||
|
|
||||||
|
if (timeSeparation <= 125)
|
||||||
|
{
|
||||||
|
// More than 120 BPM
|
||||||
|
convertType |= PatternType.ForceNotStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeSeparation <= 80)
|
||||||
|
{
|
||||||
|
// More than 187 BPM
|
||||||
|
convertType |= PatternType.ForceNotStack | PatternType.KeepSingle;
|
||||||
|
}
|
||||||
|
else if (timeSeparation <= 95)
|
||||||
|
{
|
||||||
|
// More than 157 BPM
|
||||||
|
convertType |= PatternType.ForceNotStack | PatternType.KeepSingle | lastStair;
|
||||||
|
}
|
||||||
|
else if (timeSeparation <= 105)
|
||||||
|
{
|
||||||
|
// More than 140 BPM
|
||||||
|
convertType |= PatternType.ForceNotStack | PatternType.LowProbability;
|
||||||
|
}
|
||||||
|
else if (timeSeparation <= 125)
|
||||||
|
{
|
||||||
|
// More than 120 BPM
|
||||||
|
convertType |= PatternType.ForceNotStack;
|
||||||
|
}
|
||||||
|
else if (timeSeparation <= 135 && positionSeparation < 20)
|
||||||
|
{
|
||||||
|
// More than 111 BPM stream
|
||||||
|
convertType |= PatternType.Cycle | PatternType.KeepSingle;
|
||||||
|
}
|
||||||
|
else if (timeSeparation <= 150 & positionSeparation < 20)
|
||||||
|
{
|
||||||
|
// More than 100 BPM stream
|
||||||
|
convertType |= PatternType.ForceStack | PatternType.LowProbability;
|
||||||
|
}
|
||||||
|
else if (positionSeparation < 20 && density >= beatLength / 2.5)
|
||||||
|
{
|
||||||
|
// Low density stream
|
||||||
|
convertType |= PatternType.Reverse | PatternType.LowProbability;
|
||||||
|
}
|
||||||
|
else if (density < beatLength / 2.5 || kiai)
|
||||||
|
{
|
||||||
|
// High density
|
||||||
|
}
|
||||||
|
else
|
||||||
|
convertType |= PatternType.LowProbability;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Pattern Generate()
|
||||||
|
{
|
||||||
|
int lastColumn = PreviousPattern.HitObjects.First().Column;
|
||||||
|
|
||||||
|
if ((convertType & PatternType.Reverse) > 0 && PreviousPattern.HitObjects.Count() > 0)
|
||||||
|
{
|
||||||
|
// Generate a new pattern by copying the last hit objects in reverse-column order
|
||||||
|
var pattern = new Pattern();
|
||||||
|
|
||||||
|
int siblings = PreviousPattern.HitObjects.Count(h => h.Column >= RandomStart);
|
||||||
|
|
||||||
|
for (int i = RandomStart; i < AvailableColumns; i++)
|
||||||
|
if (PreviousPattern.IsFilled(i))
|
||||||
|
addToPattern(pattern, RandomStart + AvailableColumns - i - 1, siblings);
|
||||||
|
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((convertType & PatternType.Cycle) > 0 && PreviousPattern.HitObjects.Count() == 1
|
||||||
|
// If we convert to 7K + 1, let's not overload the special key
|
||||||
|
&& (AvailableColumns != 8 || lastColumn != 0)
|
||||||
|
// Make sure the last column was not the centre column
|
||||||
|
&& (AvailableColumns % 2 == 0 || lastColumn != AvailableColumns / 2))
|
||||||
|
{
|
||||||
|
// Generate a new pattern by cycling backwards (similar to Reverse but for only one hit object)
|
||||||
|
var pattern = new Pattern();
|
||||||
|
|
||||||
|
int column = RandomStart + AvailableColumns - lastColumn - 1;
|
||||||
|
addToPattern(pattern, column);
|
||||||
|
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((convertType & PatternType.ForceStack) > 0 && PreviousPattern.HitObjects.Count() > 0)
|
||||||
|
{
|
||||||
|
// Generate a new pattern by placing on the already filled columns
|
||||||
|
var pattern = new Pattern();
|
||||||
|
|
||||||
|
int siblings = PreviousPattern.HitObjects.Count(h => h.Column >= RandomStart);
|
||||||
|
|
||||||
|
for (int i = RandomStart; i < AvailableColumns; i++)
|
||||||
|
if (PreviousPattern.IsFilled(i))
|
||||||
|
addToPattern(pattern, i, siblings);
|
||||||
|
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((convertType & PatternType.Stair) > 0 && PreviousPattern.HitObjects.Count() == 1)
|
||||||
|
{
|
||||||
|
// Generate a new pattern by placing on the next column, cycling back to the start if there is no "next"
|
||||||
|
var pattern = new Pattern();
|
||||||
|
|
||||||
|
int targetColumn = lastColumn + 1;
|
||||||
|
if (targetColumn == AvailableColumns)
|
||||||
|
{
|
||||||
|
targetColumn = RandomStart;
|
||||||
|
StairType = PatternType.ReverseStair;
|
||||||
|
}
|
||||||
|
|
||||||
|
addToPattern(pattern, targetColumn, 1);
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((convertType & PatternType.ReverseStair) > 0 && PreviousPattern.HitObjects.Count() == 1)
|
||||||
|
{
|
||||||
|
// Generate a new pattern by placing on the previous column, cycling back to the end if there is no "previous"
|
||||||
|
var pattern = new Pattern();
|
||||||
|
|
||||||
|
int targetColumn = lastColumn - 1;
|
||||||
|
if (targetColumn == RandomStart - 1)
|
||||||
|
{
|
||||||
|
targetColumn = AvailableColumns - 1;
|
||||||
|
StairType = PatternType.Stair;
|
||||||
|
}
|
||||||
|
|
||||||
|
addToPattern(pattern, targetColumn, 1);
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((convertType & PatternType.KeepSingle) > 0)
|
||||||
|
return generateRandomNotes(1);
|
||||||
|
|
||||||
|
if ((convertType & PatternType.Mirror) > 0)
|
||||||
|
{
|
||||||
|
if (ConversionDifficulty > 6.5)
|
||||||
|
return generateRandomPatternWithMirrored(0.12, 0.38, 0.12);
|
||||||
|
if (ConversionDifficulty > 4)
|
||||||
|
return generateRandomPatternWithMirrored(0.12, 0.17, 0);
|
||||||
|
return generateRandomPatternWithMirrored(0.12, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConversionDifficulty > 6.5)
|
||||||
|
{
|
||||||
|
if ((convertType & PatternType.LowProbability) > 0)
|
||||||
|
return generateRandomPattern(0.78, 0.42, 0, 0);
|
||||||
|
return generateRandomPattern(1, 0.62, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConversionDifficulty > 4)
|
||||||
|
{
|
||||||
|
if ((convertType & PatternType.LowProbability) > 0)
|
||||||
|
return generateRandomPattern(0.35, 0.08, 0, 0);
|
||||||
|
return generateRandomPattern(0.52, 0.15, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConversionDifficulty > 2)
|
||||||
|
{
|
||||||
|
if ((convertType & PatternType.LowProbability) > 0)
|
||||||
|
return generateRandomPattern(0.18, 0, 0, 0);
|
||||||
|
return generateRandomPattern(0.45, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return generateRandomPattern(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates random notes.
|
||||||
|
/// <para>
|
||||||
|
/// This will generate as many as it can up to <paramref name="noteCount"/>, accounting for
|
||||||
|
/// any stacks if <see cref="convertType"/> is forcing no stacks.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="noteCount">The amount of notes to generate.</param>
|
||||||
|
/// <param name="siblingsOverride">Custom siblings count if <paramref name="noteCount"/> is not the number of siblings in this pattern.</param>
|
||||||
|
/// <returns>The <see cref="Pattern"/> containing the hit objects.</returns>
|
||||||
|
private Pattern generateRandomNotes(int noteCount, int siblingsOverride = -1)
|
||||||
|
{
|
||||||
|
var pattern = new Pattern();
|
||||||
|
|
||||||
|
bool allowStacking = (convertType & PatternType.ForceNotStack) == 0;
|
||||||
|
|
||||||
|
if (!allowStacking)
|
||||||
|
noteCount = Math.Min(noteCount, AvailableColumns - RandomStart - PreviousPattern.ColumnsFilled);
|
||||||
|
|
||||||
|
int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);
|
||||||
|
for (int i = 0; i < noteCount; i++)
|
||||||
|
{
|
||||||
|
while (pattern.IsFilled(nextColumn) || (PreviousPattern.IsFilled(nextColumn) && !allowStacking))
|
||||||
|
{
|
||||||
|
if ((convertType & PatternType.Gathered) > 0)
|
||||||
|
{
|
||||||
|
nextColumn++;
|
||||||
|
if (nextColumn == AvailableColumns)
|
||||||
|
nextColumn = RandomStart;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
nextColumn = Random.Next(RandomStart, AvailableColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
addToPattern(pattern, nextColumn, siblingsOverride != -1 ? siblingsOverride : noteCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this hit object can generate a note in the special column.
|
||||||
|
/// </summary>
|
||||||
|
private bool hasSpecialColumn() => HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_CLAP) && HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a random pattern.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p2">Probability for 2 notes to be generated.</param>
|
||||||
|
/// <param name="p3">Probability for 3 notes to be generated.</param>
|
||||||
|
/// <param name="p4">Probability for 4 notes to be generated.</param>
|
||||||
|
/// <param name="p5">Probability for 5 notes to be generated.</param>
|
||||||
|
/// <returns>The <see cref="Pattern"/> containing the hit objects.</returns>
|
||||||
|
private Pattern generateRandomPattern(double p2, double p3, double p4, double p5)
|
||||||
|
{
|
||||||
|
var pattern = new Pattern();
|
||||||
|
|
||||||
|
int noteCount = getRandomNoteCount(p2, p3, p4, p5);
|
||||||
|
int siblings = noteCount;
|
||||||
|
|
||||||
|
if (RandomStart > 0 && hasSpecialColumn(HitObject.Samples))
|
||||||
|
{
|
||||||
|
siblings++;
|
||||||
|
addToPattern(pattern, 0, siblings);
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern.Add(generateRandomNotes(noteCount, siblings));
|
||||||
|
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a random pattern which has both normal and mirrored notes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="centreProbability">The probability for a note to be added to the centre column.</param>
|
||||||
|
/// <param name="p2">Probability for 2 notes to be generated.</param>
|
||||||
|
/// <param name="p3">Probability for 3 notes to be generated.</param>
|
||||||
|
/// <returns>The <see cref="Pattern"/> containing the hit objects.</returns>
|
||||||
|
private Pattern generateRandomPatternWithMirrored(double centreProbability, double p2, double p3)
|
||||||
|
{
|
||||||
|
var pattern = new Pattern();
|
||||||
|
|
||||||
|
bool addToCentre = false;
|
||||||
|
int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out addToCentre);
|
||||||
|
int siblings = noteCount;
|
||||||
|
|
||||||
|
if (addToCentre)
|
||||||
|
siblings++;
|
||||||
|
if (RandomStart > 0 && hasSpecialColumn(HitObject.Samples))
|
||||||
|
siblings++;
|
||||||
|
|
||||||
|
int columnLimit = (AvailableColumns % 2 == 0 ? AvailableColumns : AvailableColumns - 1) / 2;
|
||||||
|
int nextColumn = Random.Next(RandomStart, columnLimit);
|
||||||
|
for (int i = 0; i < noteCount; i++)
|
||||||
|
{
|
||||||
|
while (pattern.IsFilled(nextColumn))
|
||||||
|
nextColumn = Random.Next(RandomStart, columnLimit);
|
||||||
|
// Add normal note
|
||||||
|
addToPattern(pattern, nextColumn, siblings);
|
||||||
|
// Add mirrored note
|
||||||
|
addToPattern(pattern, RandomStart + AvailableColumns - nextColumn - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addToCentre)
|
||||||
|
addToPattern(pattern, AvailableColumns / 2, siblings);
|
||||||
|
|
||||||
|
if (RandomStart > 0 && hasSpecialColumn(HitObject.Samples))
|
||||||
|
addToPattern(pattern, 0, siblings);
|
||||||
|
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a count of notes to be generated from a list of probabilities.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p2">Probability for 2 notes to be generated.</param>
|
||||||
|
/// <param name="p3">Probability for 3 notes to be generated.</param>
|
||||||
|
/// <param name="p4">Probability for 4 notes to be generated.</param>
|
||||||
|
/// <param name="p5">Probability for 5 notes to be generated.</param>
|
||||||
|
/// <returns>The amount of notes to be generated.</returns>
|
||||||
|
private int getRandomNoteCount(double p2, double p3, double p4, double p5)
|
||||||
|
{
|
||||||
|
switch (AvailableColumns)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
p2 = 0;
|
||||||
|
p3 = 0;
|
||||||
|
p4 = 0;
|
||||||
|
p5 = 0;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
p2 = Math.Max(p2, 0.1);
|
||||||
|
p3 = 0;
|
||||||
|
p4 = 0;
|
||||||
|
p5 = 0;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
p2 = Math.Max(p2, 0.23);
|
||||||
|
p3 = Math.Max(p3, 0.04);
|
||||||
|
p4 = 0;
|
||||||
|
p5 = 0;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
p3 = Math.Max(p3, 0.15);
|
||||||
|
p4 = Math.Max(p4, 0.03);
|
||||||
|
p5 = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_CLAP))
|
||||||
|
p2 = 1;
|
||||||
|
|
||||||
|
return GetRandomNoteCount(p2, p3, p4, p5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a count of notes to be generated from a list of probabilities.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="centreProbability">The probability for a note to be added to the centre column.</param>
|
||||||
|
/// <param name="p2">Probability for 2 notes to be generated.</param>
|
||||||
|
/// <param name="p3">Probability for 3 notes to be generated.</param>
|
||||||
|
/// <param name="addToCentre">Whether to add a note to the centre column.</param>
|
||||||
|
/// <returns>The amount of notes to be generated. The note to be added to the centre column will NOT be part of this count.</returns>
|
||||||
|
private int getRandomNoteCountMirrored(double centreProbability, double p2, double p3, out bool addToCentre)
|
||||||
|
{
|
||||||
|
addToCentre = false;
|
||||||
|
|
||||||
|
if ((convertType & PatternType.ForceNotStack) > 0)
|
||||||
|
return getRandomNoteCount(p2 / 2, p2, (p2 + p3) / 2, p3);
|
||||||
|
|
||||||
|
switch (AvailableColumns)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
centreProbability = 0;
|
||||||
|
p2 = 0;
|
||||||
|
p3 = 0;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
centreProbability = Math.Max(centreProbability, 0.03);
|
||||||
|
p2 = Math.Max(p2, 0.1);
|
||||||
|
p3 = 0;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
centreProbability = 0;
|
||||||
|
p2 = Math.Max(p2 * 2, 0.2);
|
||||||
|
p3 = 0;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
centreProbability = Math.Max(centreProbability, 0.03);
|
||||||
|
p3 = 0;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
centreProbability = 0;
|
||||||
|
p2 = Math.Max(p2 * 2, 0.5);
|
||||||
|
p3 = Math.Max(p3 * 2, 0.15);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
double centreVal = Random.NextDouble();
|
||||||
|
int noteCount = GetRandomNoteCount(p2, p3);
|
||||||
|
|
||||||
|
addToCentre = AvailableColumns % 2 != 0 && noteCount != 3 && centreVal > 1 - centreProbability;
|
||||||
|
return noteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and adds a note to a pattern.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pattern">The pattern to add to.</param>
|
||||||
|
/// <param name="column">The column to add the note to.</param>
|
||||||
|
/// <param name="siblings">The number of children alongside this note (these will not be generated, but are used for volume calculations).</param>
|
||||||
|
private void addToPattern(Pattern pattern, int column, int siblings = 1)
|
||||||
|
{
|
||||||
|
pattern.Add(new Note
|
||||||
|
{
|
||||||
|
StartTime = HitObject.StartTime,
|
||||||
|
Samples = HitObject.Samples,
|
||||||
|
Column = column,
|
||||||
|
Siblings = siblings
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -49,6 +49,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Beatmaps\Patterns\Legacy\PatternGenerator.cs" />
|
<Compile Include="Beatmaps\Patterns\Legacy\PatternGenerator.cs" />
|
||||||
<Compile Include="Beatmaps\Patterns\PatternGenerator.cs" />
|
<Compile Include="Beatmaps\Patterns\PatternGenerator.cs" />
|
||||||
|
<Compile Include="Beatmaps\Patterns\Legacy\HitObjectPatternGenerator.cs" />
|
||||||
<Compile Include="Beatmaps\Patterns\Legacy\PatternType.cs" />
|
<Compile Include="Beatmaps\Patterns\Legacy\PatternType.cs" />
|
||||||
<Compile Include="Beatmaps\ManiaBeatmapConverter.cs" />
|
<Compile Include="Beatmaps\ManiaBeatmapConverter.cs" />
|
||||||
<Compile Include="Beatmaps\Patterns\Pattern.cs" />
|
<Compile Include="Beatmaps\Patterns\Pattern.cs" />
|
||||||
|
Loading…
Reference in New Issue
Block a user